summaryrefslogtreecommitdiff
path: root/net/switchdev
diff options
context:
space:
mode:
Diffstat (limited to 'net/switchdev')
0 files changed, 0 insertions, 0 deletions
r> -rw-r--r--.gitignore1
-rw-r--r--.mailmap4
-rw-r--r--Documentation/ABI/testing/debugfs-dell-wmi-ddv21
-rw-r--r--Documentation/ABI/testing/debugfs-pktcdvd18
-rw-r--r--Documentation/ABI/testing/sysfs-bus-nvdimm14
-rw-r--r--Documentation/ABI/testing/sysfs-bus-pci10
-rw-r--r--Documentation/ABI/testing/sysfs-bus-spi-devices-spi-nor6
-rw-r--r--Documentation/ABI/testing/sysfs-class-pktcdvd97
-rw-r--r--Documentation/ABI/testing/sysfs-devices-mapping30
-rw-r--r--Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon75
-rw-r--r--Documentation/ABI/testing/sysfs-driver-intel_sdsi47
-rw-r--r--Documentation/ABI/testing/sysfs-platform-dell-wmi-ddv7
-rw-r--r--Documentation/ABI/testing/sysfs-platform-intel-ifs30
-rw-r--r--Documentation/Makefile11
-rw-r--r--Documentation/PCI/msi-howto.rst10
-rw-r--r--Documentation/PCI/pci-error-recovery.rst7
-rw-r--r--Documentation/RCU/Design/Requirements/Requirements.rst2
-rw-r--r--Documentation/RCU/arrayRCU.rst165
-rw-r--r--Documentation/RCU/checklist.rst244
-rw-r--r--Documentation/RCU/index.rst1
-rw-r--r--Documentation/RCU/listRCU.rst174
-rw-r--r--Documentation/RCU/lockdep.rst4
-rw-r--r--Documentation/accel/index.rst17
-rw-r--r--Documentation/accel/introduction.rst110
-rw-r--r--Documentation/admin-guide/bootconfig.rst2
-rw-r--r--Documentation/admin-guide/device-mapper/dm-init.rst8
-rw-r--r--Documentation/admin-guide/devices.txt5
-rw-r--r--Documentation/admin-guide/hw_random.rst6
-rw-r--r--Documentation/admin-guide/kernel-parameters.txt59
-rw-r--r--Documentation/admin-guide/media/cec-drivers.rst10
-rw-r--r--Documentation/admin-guide/media/cec.rst369
-rw-r--r--Documentation/admin-guide/media/index.rst3
-rw-r--r--Documentation/admin-guide/media/pulse8-cec.rst13
-rw-r--r--Documentation/admin-guide/media/v4l-drivers.rst1
-rw-r--r--Documentation/admin-guide/media/vimc.rst8
-rw-r--r--Documentation/admin-guide/media/visl.rst175
-rw-r--r--Documentation/admin-guide/media/vivid.rst2
-rw-r--r--Documentation/admin-guide/mm/zswap.rst8
-rw-r--r--Documentation/admin-guide/perf/hisi-pcie-pmu.rst112
-rw-r--r--Documentation/admin-guide/perf/index.rst2
-rw-r--r--Documentation/admin-guide/perf/meson-ddr-pmu.rst70
-rw-r--r--Documentation/admin-guide/perf/nvidia-pmu.rst299
-rw-r--r--Documentation/admin-guide/pm/amd-pstate.rst194
-rw-r--r--Documentation/admin-guide/sysctl/fs.rst240
-rw-r--r--Documentation/admin-guide/sysctl/kernel.rst26
-rw-r--r--Documentation/arm/marvell.rst12
-rw-r--r--Documentation/arm64/acpi_object_usage.rst2
-rw-r--r--Documentation/arm64/booting.rst7
-rw-r--r--Documentation/arm64/elf_hwcaps.rst9
-rw-r--r--Documentation/arm64/silicon-errata.rst2
-rw-r--r--Documentation/arm64/sve.rst1
-rw-r--r--Documentation/block/inline-encryption.rst12
-rw-r--r--Documentation/conf.py211
-rw-r--r--Documentation/core-api/kernel-api.rst3
-rw-r--r--Documentation/core-api/local_ops.rst2
-rw-r--r--Documentation/cpu-freq/index.rst9
-rw-r--r--Documentation/dev-tools/ktap.rst4
-rw-r--r--Documentation/dev-tools/kunit/architecture.rst115
-rw-r--r--Documentation/dev-tools/kunit/index.rst20
-rw-r--r--Documentation/dev-tools/kunit/start.rst18
-rw-r--r--Documentation/dev-tools/kunit/tips.rst190
-rw-r--r--Documentation/dev-tools/kunit/usage.rst92
-rw-r--r--Documentation/devicetree/bindings/arm/amlogic.yaml1
-rw-r--r--Documentation/devicetree/bindings/arm/apple.yaml14
-rw-r--r--Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml3
-rw-r--r--Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.yaml2
-rw-r--r--Documentation/devicetree/bindings/arm/cpus.yaml2
-rw-r--r--Documentation/devicetree/bindings/arm/fsl.yaml15
-rw-r--r--Documentation/devicetree/bindings/arm/mediatek.yaml2
-rw-r--r--Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml14
-rw-r--r--Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml1
-rw-r--r--Documentation/devicetree/bindings/arm/qcom-soc.yaml66
-rw-r--r--Documentation/devicetree/bindings/arm/qcom.yaml232
-rw-r--r--Documentation/devicetree/bindings/arm/rockchip.yaml42
-rw-r--r--Documentation/devicetree/bindings/arm/socionext/uniphier.yaml6
-rw-r--r--Documentation/devicetree/bindings/arm/stm32/stm32.yaml6
-rw-r--r--Documentation/devicetree/bindings/arm/swir.txt12
-rw-r--r--Documentation/devicetree/bindings/arm/tegra/nvidia,tegra-ccplex-cluster.yaml1
-rw-r--r--Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml54
-rw-r--r--Documentation/devicetree/bindings/arm/ti/k3.yaml1
-rw-r--r--Documentation/devicetree/bindings/ata/ata-generic.yaml58
-rw-r--r--Documentation/devicetree/bindings/chrome/google,cros-ec-typec.yaml1
-rw-r--r--Documentation/devicetree/bindings/chrome/google,cros-kbd-led-backlight.yaml1
-rw-r--r--Documentation/devicetree/bindings/clock/fsl,imx8m-anatop.yaml51
-rw-r--r--Documentation/devicetree/bindings/clock/ingenic,cgu.yaml2
-rw-r--r--Documentation/devicetree/bindings/clock/mediatek,mt8186-fhctl.yaml53
-rw-r--r--Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt2
-rw-r--r--Documentation/devicetree/bindings/clock/pwm-clock.txt26
-rw-r--r--Documentation/devicetree/bindings/clock/pwm-clock.yaml45
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,a53pll.yaml2
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,a7pll.yaml2
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,aoncc-sm8250.yaml11
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,audiocc-sm8250.yaml7
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,camcc-sm8250.yaml6
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,dispcc-sc8280xp.yaml97
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,dispcc-sm6125.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,dispcc-sm6350.yaml8
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,dispcc-sm8x50.yaml14
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-apq8064.yaml18
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-apq8084.yaml10
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-ipq8064.yaml27
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-ipq8074.yaml40
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-msm8660.yaml12
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-msm8909.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-msm8916.yaml16
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-msm8974.yaml61
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-msm8976.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-msm8994.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-msm8996.yaml7
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-msm8998.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-other.yaml38
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-qcm2290.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-qcs404.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-sc7180.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-sc7280.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-sc8180x.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-sc8280xp.yaml7
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-sdm660.yaml61
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-sdm845.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-sdx55.yaml7
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-sdx65.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-sm6115.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-sm6125.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-sm6350.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-sm8150.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-sm8250.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-sm8350.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc-sm8450.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gcc.yaml6
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gpucc-sdm660.yaml4
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gpucc-sm8350.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,gpucc.yaml22
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,lcc.txt22
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,lcc.yaml86
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,lpasscc.txt26
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,mmcc.yaml42
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,msm8998-gpucc.yaml8
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,q6sstopcc.yaml2
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml8
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml1
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sc7180-camcc.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sc7180-dispcc.yaml8
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sc7180-lpasscorecc.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sc7180-mss.yaml7
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sc7280-camcc.yaml6
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sc7280-dispcc.yaml8
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sc7280-lpasscc.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sc7280-lpasscorecc.yaml12
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sdm845-camcc.yaml8
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sdm845-dispcc.yaml8
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sdm845-lpasscc.yaml47
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm6115-dispcc.yaml7
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm6375-dispcc.yaml54
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm6375-gcc.yaml9
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml8
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm8450-dispcc.yaml7
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,sm8550-gcc.yaml62
-rw-r--r--Documentation/devicetree/bindings/clock/qcom,videocc.yaml20
-rw-r--r--Documentation/devicetree/bindings/clock/rockchip,rk3588-cru.yaml71
-rw-r--r--Documentation/devicetree/bindings/clock/ti,cdce925.txt53
-rw-r--r--Documentation/devicetree/bindings/clock/ti,cdce925.yaml103
-rw-r--r--Documentation/devicetree/bindings/cpufreq/apple,cluster-cpufreq.yaml117
-rw-r--r--Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml31
-rw-r--r--Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml30
-rw-r--r--Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/bridge/renesas,dsi.yaml182
-rw-r--r--Documentation/devicetree/bindings/display/fsl,lcdif.yaml29
-rw-r--r--Documentation/devicetree/bindings/display/imx/fsl,imx-fb.txt57
-rw-r--r--Documentation/devicetree/bindings/display/imx/fsl,imx-lcdc.yaml102
-rw-r--r--Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml1
-rw-r--r--Documentation/devicetree/bindings/display/msm/dpu-common.yaml52
-rw-r--r--Documentation/devicetree/bindings/display/msm/dpu-msm8998.yaml223
-rw-r--r--Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml222
-rw-r--r--Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml235
-rw-r--r--Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml239
-rw-r--r--Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml217
-rw-r--r--Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml5
-rw-r--r--Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml1
-rw-r--r--Documentation/devicetree/bindings/display/msm/mdp5.txt30
-rw-r--r--Documentation/devicetree/bindings/display/msm/mdss-common.yaml83
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,mdss.yaml196
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,msm8998-dpu.yaml95
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,msm8998-mdss.yaml268
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml84
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml198
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sc7180-dpu.yaml95
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sc7180-mdss.yaml304
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml98
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sc7280-mdss.yaml422
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sdm845-dpu.yaml90
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sdm845-mdss.yaml270
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sm6115-dpu.yaml94
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sm6115-mdss.yaml182
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sm8250-dpu.yaml92
-rw-r--r--Documentation/devicetree/bindings/display/msm/qcom,sm8250-mdss.yaml330
-rw-r--r--Documentation/devicetree/bindings/display/panel/ilitek,ili9163.yaml3
-rw-r--r--Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml1
-rw-r--r--Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml70
-rw-r--r--Documentation/devicetree/bindings/display/panel/nec,nl8048hl11.yaml3
-rw-r--r--Documentation/devicetree/bindings/display/panel/newvision,nv3051d.yaml63
-rw-r--r--Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml5
-rw-r--r--Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml3
-rw-r--r--Documentation/devicetree/bindings/display/panel/samsung,s6d27a1.yaml4
-rw-r--r--Documentation/devicetree/bindings/display/panel/tpo,tpg110.yaml1
-rw-r--r--Documentation/devicetree/bindings/display/tegra/nvidia,tegra124-dpaux.yaml1
-rw-r--r--Documentation/devicetree/bindings/display/tegra/nvidia,tegra186-display.yaml2
-rw-r--r--Documentation/devicetree/bindings/display/xlnx/xlnx,zynqmp-dpsub.yaml67
-rw-r--r--Documentation/devicetree/bindings/dma/apple,admac.yaml3
-rw-r--r--Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml1
-rw-r--r--Documentation/devicetree/bindings/extcon/extcon-usbc-cros-ec.yaml1
-rw-r--r--Documentation/devicetree/bindings/firmware/qcom,scm.yaml3
-rw-r--r--Documentation/devicetree/bindings/gpu/host1x/nvidia,tegra234-nvdec.yaml156
-rw-r--r--Documentation/devicetree/bindings/hwinfo/loongson,ls2k-chipid.yaml38
-rw-r--r--Documentation/devicetree/bindings/hwmon/adt7475.yaml4
-rw-r--r--Documentation/devicetree/bindings/i2c/google,cros-ec-i2c-tunnel.yaml1
-rw-r--r--Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml94
-rw-r--r--Documentation/devicetree/bindings/iio/addac/adi,ad74413r.yaml1
-rw-r--r--Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml4
-rw-r--r--Documentation/devicetree/bindings/input/azoteq,iqs7222.yaml25
-rw-r--r--Documentation/devicetree/bindings/input/gpio-beeper.txt13
-rw-r--r--Documentation/devicetree/bindings/input/gpio-beeper.yaml33
-rw-r--r--Documentation/devicetree/bindings/input/qcom,pm8921-pwrkey.yaml75
-rw-r--r--Documentation/devicetree/bindings/input/qcom,pm8xxx-pwrkey.txt46
-rw-r--r--Documentation/devicetree/bindings/input/ti,drv260x.txt50
-rw-r--r--Documentation/devicetree/bindings/input/ti,drv260x.yaml109
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/cypress,tt21000.yaml106
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt4
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/himax,hx83112b.yaml63
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/hynitron,cstxxx.yaml65
-rw-r--r--Documentation/devicetree/bindings/input/touchscreen/mstar,msg2638.yaml8
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml1
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/apple,aic2.yaml29
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.txt26
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.yaml60
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-lapic.yaml71
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/loongarch,cpu-interrupt-controller.yaml34
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/mediatek,cirq.txt33
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/mediatek,mtk-cirq.yaml68
-rw-r--r--Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml4
-rw-r--r--Documentation/devicetree/bindings/iommu/apple,dart.yaml4
-rw-r--r--Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml6
-rw-r--r--Documentation/devicetree/bindings/ipmi/ssif-bmc.yaml38
-rw-r--r--Documentation/devicetree/bindings/leds/irled/gpio-ir-tx.txt14
-rw-r--r--Documentation/devicetree/bindings/leds/irled/gpio-ir-tx.yaml36
-rw-r--r--Documentation/devicetree/bindings/leds/irled/ir-spi-led.yaml61
-rw-r--r--Documentation/devicetree/bindings/leds/irled/pwm-ir-tx.txt13
-rw-r--r--Documentation/devicetree/bindings/leds/irled/pwm-ir-tx.yaml34
-rw-r--r--Documentation/devicetree/bindings/leds/irled/spi-ir-led.txt29
-rw-r--r--Documentation/devicetree/bindings/leds/issi,is31fl319x.yaml1
-rw-r--r--Documentation/devicetree/bindings/leds/leds-aw2013.yaml1
-rw-r--r--Documentation/devicetree/bindings/leds/leds-gpio.yaml2
-rw-r--r--Documentation/devicetree/bindings/leds/leds-lgm.yaml10
-rw-r--r--Documentation/devicetree/bindings/leds/leds-lp50xx.yaml8
-rw-r--r--Documentation/devicetree/bindings/leds/leds-lp55xx.yaml47
-rw-r--r--Documentation/devicetree/bindings/leds/leds-max77650.yaml9
-rw-r--r--Documentation/devicetree/bindings/leds/leds-mt6360.yaml43
-rw-r--r--Documentation/devicetree/bindings/leds/leds-pwm.yaml2
-rw-r--r--Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml12
-rw-r--r--Documentation/devicetree/bindings/leds/leds-rt4505.yaml1
-rw-r--r--Documentation/devicetree/bindings/leds/leds-sgm3140.yaml5
-rw-r--r--Documentation/devicetree/bindings/leds/rohm,bd71828-leds.yaml16
-rw-r--r--Documentation/devicetree/bindings/leds/ti,tca6507.yaml2
-rw-r--r--Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml1
-rw-r--r--Documentation/devicetree/bindings/media/allwinner,sun6i-a31-csi.yaml4
-rw-r--r--Documentation/devicetree/bindings/media/allwinner,sun6i-a31-isp.yaml101
-rw-r--r--Documentation/devicetree/bindings/media/atmel,isc.yaml4
-rw-r--r--Documentation/devicetree/bindings/media/i2c/imx290.txt57
-rw-r--r--Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml3
-rw-r--r--Documentation/devicetree/bindings/media/i2c/ov5645.txt54
-rw-r--r--Documentation/devicetree/bindings/media/i2c/ovti,ov4689.yaml134
-rw-r--r--Documentation/devicetree/bindings/media/i2c/ovti,ov5645.yaml104
-rw-r--r--Documentation/devicetree/bindings/media/i2c/ovti,ov772x.yaml3
-rw-r--r--Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml14
-rw-r--r--Documentation/devicetree/bindings/media/i2c/sony,imx290.yaml129
-rw-r--r--Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml4
-rw-r--r--Documentation/devicetree/bindings/media/i2c/st,st-mipid02.txt82
-rw-r--r--Documentation/devicetree/bindings/media/i2c/st,st-mipid02.yaml176
-rw-r--r--Documentation/devicetree/bindings/media/i2c/st,st-vgxy61.yaml113
-rw-r--r--Documentation/devicetree/bindings/media/i2c/toshiba,tc358746.yaml178
-rw-r--r--Documentation/devicetree/bindings/media/marvell,mmp2-ccic.yaml3
-rw-r--r--Documentation/devicetree/bindings/media/mediatek,mt8195-jpegdec.yaml168
-rw-r--r--Documentation/devicetree/bindings/media/mediatek,mt8195-jpegenc.yaml147
-rw-r--r--Documentation/devicetree/bindings/media/mediatek,vcodec-encoder.yaml12
-rw-r--r--Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.yaml1
-rw-r--r--Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.yaml1
-rw-r--r--Documentation/devicetree/bindings/media/microchip,xisc.yaml3
-rw-r--r--Documentation/devicetree/bindings/media/renesas,rzg2l-cru.yaml157
-rw-r--r--Documentation/devicetree/bindings/media/renesas,rzg2l-csi2.yaml149
-rw-r--r--Documentation/devicetree/bindings/media/s5p-mfc.txt10
-rw-r--r--Documentation/devicetree/bindings/media/samsung-s5c73m3.txt2
-rw-r--r--Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml4
-rw-r--r--Documentation/devicetree/bindings/media/video-interfaces.yaml5
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/arm,pl35x-smc.yaml (renamed from Documentation/devicetree/bindings/memory-controllers/arm,pl353-smc.yaml)80
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr-channel.yaml146
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr-props.yaml74
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml48
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr3.yaml44
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr4.yaml35
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr5.yaml46
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/mc-peripheral-props.yaml38
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml5
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/st,stm32-fmc2-ebi-props.yaml144
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/st,stm32-fmc2-ebi.yaml138
-rw-r--r--Documentation/devicetree/bindings/memory-controllers/ti,gpmc-child.yaml7
-rw-r--r--Documentation/devicetree/bindings/mfd/google,cros-ec.yaml103
-rw-r--r--Documentation/devicetree/bindings/mfd/max77650.yaml2
-rw-r--r--Documentation/devicetree/bindings/mfd/mediatek,mt6360.yaml9
-rw-r--r--Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml1
-rw-r--r--Documentation/devicetree/bindings/mips/brcm/brcm,bmips.txt8
-rw-r--r--Documentation/devicetree/bindings/mips/brcm/soc.yaml96
-rw-r--r--Documentation/devicetree/bindings/mips/cpus.yaml115
-rw-r--r--Documentation/devicetree/bindings/mips/ingenic/ingenic,cpu.yaml69
-rw-r--r--Documentation/devicetree/bindings/misc/idt,89hpesx.yaml72
-rw-r--r--Documentation/devicetree/bindings/misc/idt_89hpesx.txt44
-rw-r--r--Documentation/devicetree/bindings/mmc/arm,pl18x.yaml4
-rw-r--r--Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml7
-rw-r--r--Documentation/devicetree/bindings/mmc/fujitsu,sdhci-fujitsu.yaml57
-rw-r--r--Documentation/devicetree/bindings/mmc/mmc-controller.yaml1
-rw-r--r--Documentation/devicetree/bindings/mmc/mtk-sd.yaml171
-rw-r--r--Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml1
-rw-r--r--Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml3
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-am654.yaml69
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-common.yaml32
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-fujitsu.txt32
-rw-r--r--Documentation/devicetree/bindings/mmc/sdhci-msm.yaml23
-rw-r--r--Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml11
-rw-r--r--Documentation/devicetree/bindings/mmc/sunplus,mmc.yaml61
-rw-r--r--Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.yaml32
-rw-r--r--Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml34
-rw-r--r--Documentation/devicetree/bindings/mtd/arasan,nand-controller.yaml5
-rw-r--r--Documentation/devicetree/bindings/mtd/arm,pl353-nand-r2p1.yaml32
-rw-r--r--Documentation/devicetree/bindings/mtd/atmel-nand.txt6
-rw-r--r--Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml96
-rw-r--r--Documentation/devicetree/bindings/mtd/denali,nand.yaml2
-rw-r--r--Documentation/devicetree/bindings/mtd/ingenic,nand.yaml146
-rw-r--r--Documentation/devicetree/bindings/mtd/intel,lgm-ebunand.yaml50
-rw-r--r--Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml20
-rw-r--r--Documentation/devicetree/bindings/mtd/lpc32xx-mlc.txt2
-rw-r--r--Documentation/devicetree/bindings/mtd/lpc32xx-slc.txt2
-rw-r--r--Documentation/devicetree/bindings/mtd/microchip,mchp48l640.yaml16
-rw-r--r--Documentation/devicetree/bindings/mtd/mtd-physmap.yaml7
-rw-r--r--Documentation/devicetree/bindings/mtd/mtd.yaml24
-rw-r--r--Documentation/devicetree/bindings/mtd/mtk-nand.txt2
-rw-r--r--Documentation/devicetree/bindings/mtd/nand-chip.yaml4
-rw-r--r--Documentation/devicetree/bindings/mtd/nand-controller.yaml2
-rw-r--r--Documentation/devicetree/bindings/mtd/partition.txt33
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/arm,arm-firmware-suite.yaml2
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/brcm,bcm4908-partitions.yaml2
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/brcm,bcm947xx-cfe-partitions.yaml2
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml30
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/linksys,ns-partitions.yaml2
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/nvmem-cells.yaml4
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/partition.yaml5
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/partitions.yaml41
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/qcom,smem-part.yaml38
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/redboot-fis.yaml6
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/tplink,safeloader-partitions.yaml57
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/u-boot.yaml7
-rw-r--r--Documentation/devicetree/bindings/mtd/qcom,nandc.yaml131
-rw-r--r--Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml4
-rw-r--r--Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml47
-rw-r--r--Documentation/devicetree/bindings/mtd/ti,am654-hbmc.yaml36
-rw-r--r--Documentation/devicetree/bindings/mtd/ti,gpmc-onenand.yaml3
-rw-r--r--Documentation/devicetree/bindings/net/cdns,macb.yaml1
-rw-r--r--Documentation/devicetree/bindings/net/micrel,ks8851.yaml1
-rw-r--r--Documentation/devicetree/bindings/net/nxp,dwmac-imx.yaml1
-rw-r--r--Documentation/devicetree/bindings/nvmem/snvs-lpgpr.yaml20
-rw-r--r--Documentation/devicetree/bindings/nvmem/u-boot,env.yaml21
-rw-r--r--Documentation/devicetree/bindings/opp/allwinner,sun50i-h6-operating-points.yaml4
-rw-r--r--Documentation/devicetree/bindings/opp/opp-v2-base.yaml6
-rw-r--r--Documentation/devicetree/bindings/opp/opp-v2.yaml2
-rw-r--r--Documentation/devicetree/bindings/pci/mediatek,mt7621-pcie.yaml2
-rw-r--r--Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.yaml34
-rw-r--r--Documentation/devicetree/bindings/pci/renesas,pci-rcar-gen2.yaml2
-rw-r--r--Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml2
-rw-r--r--Documentation/devicetree/bindings/pci/xilinx-nwl-pcie.txt73
-rw-r--r--Documentation/devicetree/bindings/pci/xilinx-pcie.txt88
-rw-r--r--Documentation/devicetree/bindings/pci/xlnx,axi-pcie-host.yaml88
-rw-r--r--Documentation/devicetree/bindings/pci/xlnx,nwl-pcie.yaml149
-rw-r--r--Documentation/devicetree/bindings/perf/amlogic,g12-ddr-pmu.yaml54
-rw-r--r--Documentation/devicetree/bindings/perf/arm,dsu-pmu.yaml3
-rw-r--r--Documentation/devicetree/bindings/phy/intel,phy-thunderbay-emmc.yaml15
-rw-r--r--Documentation/devicetree/bindings/pinctrl/fsl,imxrt1050.yaml2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/loongson,ls2k-pinctrl.yaml123
-rw-r--r--Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml5
-rw-r--r--Documentation/devicetree/bindings/pinctrl/mediatek,mt6779-pinctrl.yaml95
-rw-r--r--Documentation/devicetree/bindings/pinctrl/mediatek,mt6797-pinctrl.yaml176
-rw-r--r--Documentation/devicetree/bindings/pinctrl/mediatek,mt7986-pinctrl.yaml108
-rw-r--r--Documentation/devicetree/bindings/pinctrl/mediatek,pinctrl-mt6795.yaml7
-rw-r--r--Documentation/devicetree/bindings/pinctrl/nvidia,tegra-pinmux-common.yaml178
-rw-r--r--Documentation/devicetree/bindings/pinctrl/nvidia,tegra114-pinmux.txt131
-rw-r--r--Documentation/devicetree/bindings/pinctrl/nvidia,tegra114-pinmux.yaml155
-rw-r--r--Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-pinmux.txt153
-rw-r--r--Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-pinmux.yaml176
-rw-r--r--Documentation/devicetree/bindings/pinctrl/nvidia,tegra194-pinmux.txt107
-rw-r--r--Documentation/devicetree/bindings/pinctrl/nvidia,tegra194-pinmux.yaml284
-rw-r--r--Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt143
-rw-r--r--Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.yaml112
-rw-r--r--Documentation/devicetree/bindings/pinctrl/nvidia,tegra210-pinmux.txt166
-rw-r--r--Documentation/devicetree/bindings/pinctrl/nvidia,tegra210-pinmux.yaml142
-rw-r--r--Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt144
-rw-r--r--Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.yaml176
-rw-r--r--Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt72
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,ipq6018-pinctrl.yaml113
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,ipq8074-pinctrl.txt181
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,ipq8074-pinctrl.yaml135
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-tlmm.yaml (renamed from Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-pinctrl.yaml)41
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,mdm9615-pinctrl.txt161
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,mdm9615-pinctrl.yaml119
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8226-pinctrl.yaml103
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8660-pinctrl.txt96
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8660-pinctrl.yaml125
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8909-tlmm.yaml75
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8916-pinctrl.txt195
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8916-pinctrl.yaml166
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8953-pinctrl.yaml97
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.txt190
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.yaml164
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.txt121
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.yaml179
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8976-pinctrl.txt183
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8976-pinctrl.yaml136
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt186
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.yaml162
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8996-pinctrl.txt208
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8996-pinctrl.yaml182
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8998-pinctrl.txt202
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,msm8998-pinctrl.yaml171
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,pmic-mpp.yaml45
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,qcm2290-tlmm.yaml (renamed from Documentation/devicetree/bindings/pinctrl/qcom,qcm2290-pinctrl.yaml)64
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,qcs404-pinctrl.txt199
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,qcs404-pinctrl.yaml176
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sc7180-pinctrl.txt187
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sc7180-pinctrl.yaml158
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml48
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sc7280-pinctrl.yaml47
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sc8180x-tlmm.yaml (renamed from Documentation/devicetree/bindings/pinctrl/qcom,sc8180x-pinctrl.yaml)29
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sc8280xp-lpass-lpi-pinctrl.yaml44
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sc8280xp-tlmm.yaml (renamed from Documentation/devicetree/bindings/pinctrl/qcom,sc8280xp-pinctrl.yaml)28
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sdm630-pinctrl.yaml188
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sdm660-pinctrl.txt191
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sdm670-tlmm.yaml127
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sdm845-pinctrl.txt176
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sdm845-pinctrl.yaml158
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sdx55-pinctrl.yaml95
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sdx65-tlmm.yaml (renamed from Documentation/devicetree/bindings/pinctrl/qcom,sdx65-pinctrl.yaml)62
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sm6115-tlmm.yaml (renamed from Documentation/devicetree/bindings/pinctrl/qcom,sm6115-pinctrl.yaml)67
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sm6125-tlmm.yaml (renamed from Documentation/devicetree/bindings/pinctrl/qcom,sm6125-pinctrl.yaml)32
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sm6350-tlmm.yaml (renamed from Documentation/devicetree/bindings/pinctrl/qcom,sm6350-pinctrl.yaml)25
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sm6375-tlmm.yaml23
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sm8150-pinctrl.txt190
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sm8150-pinctrl.yaml173
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sm8250-lpass-lpi-pinctrl.yaml58
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sm8250-pinctrl.yaml206
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sm8350-tlmm.yaml (renamed from Documentation/devicetree/bindings/pinctrl/qcom,sm8350-pinctrl.yaml)25
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sm8450-lpass-lpi-pinctrl.yaml51
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,sm8450-tlmm.yaml (renamed from Documentation/devicetree/bindings/pinctrl/qcom,sm8450-pinctrl.yaml)24
-rw-r--r--Documentation/devicetree/bindings/pinctrl/qcom,tlmm-common.yaml20
-rw-r--r--Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml2
-rw-r--r--Documentation/devicetree/bindings/pinctrl/semtech,sx1501q.yaml208
-rw-r--r--Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml7
-rw-r--r--Documentation/devicetree/bindings/power/qcom,rpmpd.yaml4
-rw-r--r--Documentation/devicetree/bindings/power/renesas,apmu.yaml6
-rw-r--r--Documentation/devicetree/bindings/power/supply/mt6360_charger.yaml2
-rw-r--r--Documentation/devicetree/bindings/power/wakeup-source.txt13
-rw-r--r--Documentation/devicetree/bindings/pwm/allwinner,sun4i-a10-pwm.yaml4
-rw-r--r--Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.yaml1
-rw-r--r--Documentation/devicetree/bindings/pwm/microchip,corepwm.yaml4
-rw-r--r--Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt77
-rw-r--r--Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.yaml96
-rw-r--r--Documentation/devicetree/bindings/regulator/google,cros-ec-regulator.yaml1
-rw-r--r--Documentation/devicetree/bindings/regulator/max77650-regulator.yaml1
-rw-r--r--Documentation/devicetree/bindings/regulator/max8660.yaml8
-rw-r--r--Documentation/devicetree/bindings/regulator/maxim,max77802.yaml2
-rw-r--r--Documentation/devicetree/bindings/regulator/mediatek,mt6357-regulator.yaml294
-rw-r--r--Documentation/devicetree/bindings/regulator/mt6360-regulator.yaml12
-rw-r--r--Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml36
-rw-r--r--Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.yaml3
-rw-r--r--Documentation/devicetree/bindings/regulator/regulator-output.yaml39
-rw-r--r--Documentation/devicetree/bindings/regulator/regulator.yaml2
-rw-r--r--Documentation/devicetree/bindings/regulator/richtek,rt6190.yaml79
-rw-r--r--Documentation/devicetree/bindings/regulator/rohm,bd9576-regulator.yaml2
-rw-r--r--Documentation/devicetree/bindings/regulator/ti,tps65219.yaml14
-rw-r--r--Documentation/devicetree/bindings/riscv/cpus.yaml13
-rw-r--r--Documentation/devicetree/bindings/riscv/starfive.yaml4
-rw-r--r--Documentation/devicetree/bindings/serial/fsl-lpuart.yaml3
-rw-r--r--Documentation/devicetree/bindings/soc/mediatek/pwrap.txt3
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml2
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,apr-services.yaml54
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml171
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,rpmh-rsc.yaml5
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml28
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.yaml2
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qcom,spm.yaml3
-rw-r--r--Documentation/devicetree/bindings/soc/renesas/renesas,r9a09g011-sys.yaml43
-rw-r--r--Documentation/devicetree/bindings/soc/renesas/renesas.yaml (renamed from Documentation/devicetree/bindings/arm/renesas.yaml)5
-rw-r--r--Documentation/devicetree/bindings/sound/adi,adau1372.yaml7
-rw-r--r--Documentation/devicetree/bindings/sound/adi,adau1977.yaml1
-rw-r--r--Documentation/devicetree/bindings/sound/adi,adau7118.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/ak4375.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/ak4613.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/ak4642.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml3
-rw-r--r--Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml3
-rw-r--r--Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml3
-rw-r--r--Documentation/devicetree/bindings/sound/allwinner,sun50i-h6-dmic.yaml12
-rw-r--r--Documentation/devicetree/bindings/sound/allwinner,sun8i-a33-codec.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/amlogic,aiu.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/amlogic,g12a-toacodec.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/amlogic,t9015.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/apple,mca.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/awinic,aw8738.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/cirrus,cs35l41.yaml3
-rw-r--r--Documentation/devicetree/bindings/sound/cirrus,cs35l45.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/cirrus,lochnagar.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/cirrus,madera.yaml3
-rw-r--r--Documentation/devicetree/bindings/sound/dai-common.yaml (renamed from Documentation/devicetree/bindings/sound/name-prefix.yaml)6
-rw-r--r--Documentation/devicetree/bindings/sound/davinci-mcasp-audio.yaml3
-rw-r--r--Documentation/devicetree/bindings/sound/dmic-codec.yaml55
-rw-r--r--Documentation/devicetree/bindings/sound/dmic.txt22
-rw-r--r--Documentation/devicetree/bindings/sound/everest,es8316.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,micfil.yaml1
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml36
-rw-r--r--Documentation/devicetree/bindings/sound/fsl,sai.yaml100
-rw-r--r--Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml6
-rw-r--r--Documentation/devicetree/bindings/sound/ingenic,aic.yaml15
-rw-r--r--Documentation/devicetree/bindings/sound/ingenic,codec.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml8
-rw-r--r--Documentation/devicetree/bindings/sound/linux,bt-sco.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/linux,spdif-dit.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/marvell,mmp-sspa.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/max98357a.txt28
-rw-r--r--Documentation/devicetree/bindings/sound/max98504.txt44
-rw-r--r--Documentation/devicetree/bindings/sound/maxim,max98357a.yaml52
-rw-r--r--Documentation/devicetree/bindings/sound/maxim,max98504.yaml86
-rw-r--r--Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml18
-rw-r--r--Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/microchip,pdmc.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml14
-rw-r--r--Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml3
-rw-r--r--Documentation/devicetree/bindings/sound/mvebu-audio.txt14
-rw-r--r--Documentation/devicetree/bindings/sound/nau8315.txt6
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra186-asrc.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra20-spdif.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra210-adx.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra210-amx.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra210-mixer.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra210-mvc.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra210-ope.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/nvidia,tegra210-sfc.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml3
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml8
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml8
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml8
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml8
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,q6adm-routing.yaml27
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,q6adm.yaml51
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,q6afe.yaml68
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml19
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml35
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,q6apm.yaml68
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,q6asm-dais.yaml48
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,q6asm.yaml68
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,q6core.yaml39
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-clocks.yaml40
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-ports.yaml57
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,q6prm.yaml50
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,wcd9335.txt2
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,wcd938x.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/qcom,wsa883x.yaml15
-rw-r--r--Documentation/devicetree/bindings/sound/realtek,rt5682s.yaml31
-rw-r--r--Documentation/devicetree/bindings/sound/renesas,fsi.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/renesas,rsnd.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/richtek,rt9120.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.yaml7
-rw-r--r--Documentation/devicetree/bindings/sound/rockchip,pdm.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/rockchip-i2s.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/rockchip-spdif.yaml23
-rw-r--r--Documentation/devicetree/bindings/sound/rohm,bd28623.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/rt5659.txt2
-rw-r--r--Documentation/devicetree/bindings/sound/rt5682.txt22
-rw-r--r--Documentation/devicetree/bindings/sound/samsung-i2s.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/sgtl5000.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/simple-audio-amplifier.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/simple-audio-mux.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/snps,designware-i2s.yaml30
-rw-r--r--Documentation/devicetree/bindings/sound/socionext,uniphier-aio.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/socionext,uniphier-evea.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/tas2562.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/tas2770.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/tas27xx.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/ti,src4xxx.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/ti,tlv320adc3xxx.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/tlv320adcx140.yaml64
-rw-r--r--Documentation/devicetree/bindings/sound/wlf,arizona.yaml3
-rw-r--r--Documentation/devicetree/bindings/sound/wlf,wm8731.yaml1
-rw-r--r--Documentation/devicetree/bindings/sound/wlf,wm8940.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/wlf,wm8961.yaml43
-rw-r--r--Documentation/devicetree/bindings/sound/wlf,wm8962.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/wlf,wm8978.yaml5
-rw-r--r--Documentation/devicetree/bindings/sound/zl38060.yaml5
-rw-r--r--Documentation/devicetree/bindings/spi/amlogic,meson-gx-spicc.yaml75
-rw-r--r--Documentation/devicetree/bindings/spi/fsl-imx-cspi.yaml4
-rw-r--r--Documentation/devicetree/bindings/spi/nuvoton,npcm-fiu.txt2
-rw-r--r--Documentation/devicetree/bindings/spi/nuvoton,wpcm450-fiu.yaml66
-rw-r--r--Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml2
-rw-r--r--Documentation/devicetree/bindings/spi/socionext,f-ospi.yaml57
-rw-r--r--Documentation/devicetree/bindings/spi/socionext,synquacer-spi.yaml73
-rw-r--r--Documentation/devicetree/bindings/spi/spi-fsl-lpspi.yaml8
-rw-r--r--Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml5
-rw-r--r--Documentation/devicetree/bindings/spi/spi-synquacer.txt27
-rw-r--r--Documentation/devicetree/bindings/spi/spi-zynqmp-qspi.yaml4
-rw-r--r--Documentation/devicetree/bindings/sram/qcom,imem.yaml1
-rw-r--r--Documentation/devicetree/bindings/thermal/qcom-lmh.yaml2
-rw-r--r--Documentation/devicetree/bindings/thermal/qcom-spmi-adc-tm5.yaml6
-rw-r--r--Documentation/devicetree/bindings/thermal/qcom-tsens.yaml1
-rw-r--r--Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml4
-rw-r--r--Documentation/devicetree/bindings/thermal/thermal-idle.yaml154
-rw-r--r--Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml2
-rw-r--r--Documentation/devicetree/bindings/timer/nuvoton,npcm7xx-timer.yaml8
-rw-r--r--Documentation/devicetree/bindings/timer/renesas,cmt.yaml2
-rw-r--r--Documentation/devicetree/bindings/timer/renesas,tmu.yaml1
-rw-r--r--Documentation/devicetree/bindings/timer/rockchip,rk-timer.yaml1
-rw-r--r--Documentation/devicetree/bindings/ufs/cdns,ufshc.yaml2
-rw-r--r--Documentation/devicetree/bindings/usb/generic-ehci.yaml1
-rw-r--r--Documentation/devicetree/bindings/usb/generic-ohci.yaml1
-rw-r--r--Documentation/devicetree/bindings/usb/nvidia,tegra124-xusb.txt132
-rw-r--r--Documentation/devicetree/bindings/usb/nvidia,tegra124-xusb.yaml202
-rw-r--r--Documentation/devicetree/bindings/usb/nvidia,tegra186-xusb.yaml173
-rw-r--r--Documentation/devicetree/bindings/usb/nvidia,tegra194-xusb.yaml179
-rw-r--r--Documentation/devicetree/bindings/usb/nvidia,tegra210-xusb.yaml199
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.yaml14
-rw-r--r--Documentation/doc-guide/sphinx.rst16
-rw-r--r--Documentation/driver-api/dma-buf.rst6
-rw-r--r--Documentation/driver-api/driver-model/devres.rst9
-rw-r--r--Documentation/driver-api/eisa.rst2
-rw-r--r--Documentation/driver-api/pin-control.rst10
-rw-r--r--Documentation/driver-api/spi.rst4
-rw-r--r--Documentation/fault-injection/fault-injection.rst10
-rw-r--r--Documentation/fb/modedb.rst5
-rw-r--r--Documentation/features/core/cBPF-JIT/arch-support.txt2
-rw-r--r--Documentation/features/core/eBPF-JIT/arch-support.txt2
-rw-r--r--Documentation/features/core/generic-idle-thread/arch-support.txt2
-rw-r--r--Documentation/features/core/jump-labels/arch-support.txt4
-rw-r--r--Documentation/features/core/thread-info-in-task/arch-support.txt2
-rw-r--r--Documentation/features/core/tracehook/arch-support.txt2
-rw-r--r--Documentation/features/debug/KASAN/arch-support.txt4
-rw-r--r--Documentation/features/debug/debug-vm-pgtable/arch-support.txt2
-rw-r--r--Documentation/features/debug/gcov-profile-all/arch-support.txt2
-rw-r--r--Documentation/features/debug/kcov/arch-support.txt2
-rw-r--r--Documentation/features/debug/kgdb/arch-support.txt2
-rw-r--r--Documentation/features/debug/kmemleak/arch-support.txt2
-rw-r--r--Documentation/features/debug/kprobes-on-ftrace/arch-support.txt2
-rw-r--r--Documentation/features/debug/kprobes/arch-support.txt2
-rw-r--r--Documentation/features/debug/kretprobes/arch-support.txt2
-rw-r--r--Documentation/features/debug/optprobes/arch-support.txt2
-rw-r--r--Documentation/features/debug/stackprotector/arch-support.txt2
-rw-r--r--Documentation/features/debug/uprobes/arch-support.txt2
-rw-r--r--Documentation/features/debug/user-ret-profiler/arch-support.txt2
-rw-r--r--Documentation/features/io/dma-contiguous/arch-support.txt2
-rw-r--r--Documentation/features/locking/cmpxchg-local/arch-support.txt2
-rw-r--r--Documentation/features/locking/lockdep/arch-support.txt2
-rw-r--r--Documentation/features/locking/queued-rwlocks/arch-support.txt2
-rw-r--r--Documentation/features/locking/queued-spinlocks/arch-support.txt4
-rw-r--r--Documentation/features/perf/kprobes-event/arch-support.txt2
-rw-r--r--Documentation/features/perf/perf-regs/arch-support.txt2
-rw-r--r--Documentation/features/perf/perf-stackdump/arch-support.txt2
-rw-r--r--Documentation/features/sched/membarrier-sync-core/arch-support.txt2
-rw-r--r--Documentation/features/sched/numa-balancing/arch-support.txt2
-rwxr-xr-xDocumentation/features/scripts/features-refresh.sh2
-rw-r--r--Documentation/features/seccomp/seccomp-filter/arch-support.txt2
-rw-r--r--Documentation/features/time/arch-tick-broadcast/arch-support.txt2
-rw-r--r--Documentation/features/time/clockevents/arch-support.txt2
-rw-r--r--Documentation/features/time/context-tracking/arch-support.txt2
-rw-r--r--Documentation/features/time/irq-time-acct/arch-support.txt2
-rw-r--r--Documentation/features/time/virt-cpuacct/arch-support.txt2
-rw-r--r--Documentation/features/vm/ELF-ASLR/arch-support.txt2
-rw-r--r--Documentation/features/vm/PG_uncached/arch-support.txt2
-rw-r--r--Documentation/features/vm/THP/arch-support.txt2
-rw-r--r--Documentation/features/vm/TLB/arch-support.txt2
-rw-r--r--Documentation/features/vm/huge-vmap/arch-support.txt2
-rw-r--r--Documentation/features/vm/ioremap_prot/arch-support.txt2
-rw-r--r--Documentation/features/vm/pte_special/arch-support.txt2
-rw-r--r--Documentation/filesystems/configfs.rst48
-rw-r--r--Documentation/filesystems/debugfs.rst8
-rw-r--r--Documentation/filesystems/erofs.rst38
-rw-r--r--Documentation/filesystems/fscrypt.rst7
-rw-r--r--Documentation/filesystems/locking.rst10
-rw-r--r--Documentation/filesystems/mount_api.rst12
-rw-r--r--Documentation/filesystems/porting.rst4
-rw-r--r--Documentation/filesystems/proc.rst20
-rw-r--r--Documentation/filesystems/sysfs.rst41
-rw-r--r--Documentation/filesystems/vfs.rst5
-rw-r--r--Documentation/gpu/amdgpu/amdgpu-glossary.rst23
-rw-r--r--Documentation/gpu/amdgpu/driver-core.rst4
-rw-r--r--Documentation/gpu/amdgpu/index.rst2
-rw-r--r--Documentation/gpu/drm-kms-helpers.rst3
-rw-r--r--Documentation/gpu/drm-usage-stats.rst1
-rw-r--r--Documentation/gpu/i915.rst2
-rw-r--r--Documentation/gpu/todo.rst11
-rw-r--r--Documentation/hwmon/aquacomputer_d5next.rst4
-rw-r--r--Documentation/hwmon/index.rst2
-rw-r--r--Documentation/hwmon/oxp-sensors.rst44
-rw-r--r--Documentation/hwmon/smpro-hwmon.rst102
-rw-r--r--Documentation/ia64/aliasing.rst2
-rw-r--r--Documentation/kernel-hacking/locking.rst17
-rw-r--r--Documentation/loongarch/introduction.rst8
-rw-r--r--Documentation/memory-barriers.txt2
-rw-r--r--Documentation/mm/slub.rst2
-rw-r--r--Documentation/process/kernel-docs.rst477
-rw-r--r--Documentation/riscv/vm-layout.rst36
-rw-r--r--Documentation/security/keys/trusted-encrypted.rst3
-rw-r--r--Documentation/sphinx-static/custom.css29
-rw-r--r--Documentation/sphinx/requirements.txt1
-rw-r--r--Documentation/subsystem-apis.rst1
-rw-r--r--Documentation/timers/hrtimers.rst2
-rw-r--r--Documentation/tools/index.rst1
-rw-r--r--Documentation/tools/rv/Makefile52
-rw-r--r--Documentation/tools/rv/common_appendix.rst16
-rw-r--r--Documentation/tools/rv/common_ikm.rst21
-rw-r--r--Documentation/tools/rv/index.rst24
-rw-r--r--Documentation/tools/rv/rv-list.rst43
-rw-r--r--Documentation/tools/rv/rv-mon-wip.rst44
-rw-r--r--Documentation/tools/rv/rv-mon-wwnr.rst43
-rw-r--r--Documentation/tools/rv/rv-mon.rst55
-rw-r--r--Documentation/tools/rv/rv.rst63
-rw-r--r--Documentation/trace/ftrace.rst2
-rw-r--r--Documentation/translations/index.rst1
-rw-r--r--Documentation/translations/it_IT/kernel-hacking/locking.rst14
-rw-r--r--Documentation/translations/ja_JP/howto.rst66
-rw-r--r--Documentation/translations/ko_KR/memory-barriers.txt149
-rw-r--r--Documentation/translations/sp_SP/disclaimer-sp.rst6
-rw-r--r--Documentation/translations/sp_SP/howto.rst617
-rw-r--r--Documentation/translations/sp_SP/index.rst81
-rw-r--r--Documentation/translations/sp_SP/memory-barriers.txt3134
-rw-r--r--Documentation/translations/sp_SP/process/coding-style.rst1315
-rw-r--r--Documentation/translations/sp_SP/process/index.rst15
-rw-r--r--Documentation/translations/sp_SP/process/kernel-docs.rst187
-rw-r--r--Documentation/translations/sp_SP/process/submitting-patches.rst894
-rw-r--r--Documentation/translations/sp_SP/wrappers/memory-barriers.rst19
-rw-r--r--Documentation/translations/zh_CN/core-api/errseq.rst145
-rw-r--r--Documentation/translations/zh_CN/core-api/index.rst6
-rw-r--r--Documentation/translations/zh_CN/core-api/local_ops.rst2
-rw-r--r--Documentation/translations/zh_CN/core-api/this_cpu_ops.rst285
-rw-r--r--Documentation/translations/zh_CN/doc-guide/index.rst2
-rw-r--r--Documentation/translations/zh_CN/index.rst11
-rw-r--r--Documentation/translations/zh_CN/loongarch/introduction.rst8
-rw-r--r--Documentation/translations/zh_CN/rust/arch-support.rst23
-rw-r--r--Documentation/translations/zh_CN/rust/coding-guidelines.rst192
-rw-r--r--Documentation/translations/zh_CN/rust/general-information.rst75
-rw-r--r--Documentation/translations/zh_CN/rust/index.rst28
-rw-r--r--Documentation/translations/zh_CN/rust/quick-start.rst211
-rw-r--r--Documentation/translations/zh_CN/staging/index.rst26
-rw-r--r--Documentation/translations/zh_CN/staging/xz.rst100
-rw-r--r--Documentation/translations/zh_CN/userspace-api/accelerators/ocxl.rst168
-rw-r--r--Documentation/translations/zh_CN/userspace-api/ebpf/index.rst22
-rw-r--r--Documentation/translations/zh_CN/userspace-api/ebpf/syscall.rst29
-rw-r--r--Documentation/translations/zh_CN/userspace-api/futex2.rst80
-rw-r--r--Documentation/translations/zh_CN/userspace-api/index.rst50
-rw-r--r--Documentation/translations/zh_CN/userspace-api/no_new_privs.rst57
-rw-r--r--Documentation/translations/zh_CN/userspace-api/seccomp_filter.rst293
-rw-r--r--Documentation/translations/zh_CN/userspace-api/sysfs-platform_profile.rst40
-rw-r--r--Documentation/usb/CREDITS6
-rw-r--r--Documentation/usb/functionfs.rst2
-rw-r--r--Documentation/usb/gadget_multi.rst2
-rw-r--r--Documentation/userspace-api/landlock.rst67
-rw-r--r--Documentation/userspace-api/media/Makefile3
-rw-r--r--Documentation/userspace-api/media/cec/cec-pin-error-inj.rst2
-rw-r--r--Documentation/userspace-api/media/drivers/aspeed-video.rst65
-rw-r--r--Documentation/userspace-api/media/drivers/index.rst2
-rw-r--r--Documentation/userspace-api/media/drivers/st-vgxy61.rst25
-rw-r--r--Documentation/userspace-api/media/dvb/fe_property_parameters.rst25
-rw-r--r--Documentation/userspace-api/media/frontend.h.rst.exceptions28
-rw-r--r--Documentation/userspace-api/media/v4l/buffer.rst11
-rw-r--r--Documentation/userspace-api/media/v4l/ext-ctrls-camera.rst8
-rw-r--r--Documentation/userspace-api/media/v4l/pixfmt-reserved.rst17
-rw-r--r--Documentation/userspace-api/media/v4l/pixfmt-yuv-planar.rst8
-rw-r--r--Documentation/userspace-api/media/v4l/subdev-formats.rst37
-rw-r--r--Documentation/virt/coco/tdx-guest.rst52
-rw-r--r--Documentation/virt/index.rst1
-rw-r--r--Documentation/x86/boot.rst1
-rw-r--r--Documentation/x86/tdx.rst43
-rw-r--r--MAINTAINERS252
-rw-r--r--Makefile12
-rw-r--r--arch/Kconfig10
-rw-r--r--arch/alpha/include/asm/elf.h6
-rw-r--r--arch/alpha/include/asm/ptrace.h1
-rw-r--r--arch/alpha/include/asm/thread_info.h6
-rw-r--r--arch/alpha/kernel/entry.S14
-rw-r--r--arch/alpha/kernel/process.c8
-rw-r--r--arch/arc/kernel/ptrace.c2
-rw-r--r--arch/arm/Kconfig3
-rw-r--r--arch/arm/Makefile81
-rw-r--r--arch/arm/boot/compressed/Makefile2
-rw-r--r--arch/arm/boot/dts/Makefile13
-rw-r--r--arch/arm/boot/dts/am335x-baltos-leds.dtsi6
-rw-r--r--arch/arm/boot/dts/am335x-boneblack-hdmi.dtsi7
-rw-r--r--arch/arm/boot/dts/am335x-evm.dts4
-rw-r--r--arch/arm/boot/dts/am335x-evmsk.dts2
-rw-r--r--arch/arm/boot/dts/am335x-guardian.dts3
-rw-r--r--arch/arm/boot/dts/am335x-igep0033.dtsi4
-rw-r--r--arch/arm/boot/dts/am335x-moxa-uc-2100-common.dtsi10
-rw-r--r--arch/arm/boot/dts/am335x-moxa-uc-8100-common.dtsi10
-rw-r--r--arch/arm/boot/dts/am335x-myirtech-myd.dts7
-rw-r--r--arch/arm/boot/dts/am335x-pepper.dts4
-rw-r--r--arch/arm/boot/dts/am335x-pocketbeagle.dts8
-rw-r--r--arch/arm/boot/dts/am3517-evm.dts18
-rw-r--r--arch/arm/boot/dts/am3517.dtsi38
-rw-r--r--arch/arm/boot/dts/am437x-idk-evm.dts2
-rw-r--r--arch/arm/boot/dts/am437x-sk-evm.dts2
-rw-r--r--arch/arm/boot/dts/am43x-epos-evm.dts2
-rw-r--r--arch/arm/boot/dts/am57xx-idk-common.dtsi2
-rw-r--r--arch/arm/boot/dts/armada-370-dlink-dns327l.dts6
-rw-r--r--arch/arm/boot/dts/armada-370-netgear-rn102.dts10
-rw-r--r--arch/arm/boot/dts/armada-370-netgear-rn104.dts10
-rw-r--r--arch/arm/boot/dts/armada-370-rd.dts16
-rw-r--r--arch/arm/boot/dts/armada-370-seagate-nas-4bay.dts4
-rw-r--r--arch/arm/boot/dts/armada-370-seagate-nas-xbay.dtsi8
-rw-r--r--arch/arm/boot/dts/armada-370-seagate-personal-cloud.dtsi2
-rw-r--r--arch/arm/boot/dts/armada-370-synology-ds213j.dts6
-rw-r--r--arch/arm/boot/dts/armada-370.dtsi2
-rw-r--r--arch/arm/boot/dts/armada-375.dtsi2
-rw-r--r--arch/arm/boot/dts/armada-380.dtsi4
-rw-r--r--arch/arm/boot/dts/armada-385-linksys-caiman.dts4
-rw-r--r--arch/arm/boot/dts/armada-385-linksys-cobra.dts4
-rw-r--r--arch/arm/boot/dts/armada-385-linksys-rango.dts8
-rw-r--r--arch/arm/boot/dts/armada-385-linksys-shelby.dts4
-rw-r--r--arch/arm/boot/dts/armada-385-linksys.dtsi4
-rw-r--r--arch/arm/boot/dts/armada-385-synology-ds116.dts2
-rw-r--r--arch/arm/boot/dts/armada-385-turris-omnia.dts18
-rw-r--r--arch/arm/boot/dts/armada-385.dtsi6
-rw-r--r--arch/arm/boot/dts/armada-38x.dtsi4
-rw-r--r--arch/arm/boot/dts/armada-39x.dtsi10
-rw-r--r--arch/arm/boot/dts/armada-xp-98dx3236.dtsi1
-rw-r--r--arch/arm/boot/dts/armada-xp-linksys-mamba.dts2
-rw-r--r--arch/arm/boot/dts/armada-xp-mv78230.dtsi8
-rw-r--r--arch/arm/boot/dts/armada-xp-mv78260.dtsi16
-rw-r--r--arch/arm/boot/dts/armada-xp-netgear-rn2120.dts10
-rw-r--r--arch/arm/boot/dts/armada-xp.dtsi1
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-ampere-mtjade.dts12
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-ampere-mtmitchell.dts4
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-delta-ahe50dc.dts418
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-facebook-bletchley.dts213
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-facebook-cloudripper.dts2
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-facebook-elbert.dts2
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-facebook-fuji.dts2
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-facebook-wedge400.dts2
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-ibm-bonnell.dts921
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts57
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts244
-rw-r--r--arch/arm/boot/dts/aspeed-bmc-opp-mihawk.dts1381
-rw-r--r--arch/arm/boot/dts/aspeed-g6.dtsi4
-rw-r--r--arch/arm/boot/dts/ast2600-facebook-netbmc-common.dtsi2
-rw-r--r--arch/arm/boot/dts/at91-sam9x60ek.dts4
-rw-r--r--arch/arm/boot/dts/at91-sama7g5ek.dts5
-rw-r--r--arch/arm/boot/dts/axp22x.dtsi6
-rw-r--r--arch/arm/boot/dts/axp809.dtsi7
-rw-r--r--arch/arm/boot/dts/axp81x.dtsi14
-rw-r--r--arch/arm/boot/dts/bcm2711-rpi-4-b.dts31
-rw-r--r--arch/arm/boot/dts/bcm2711-rpi-400.dts16
-rw-r--r--arch/arm/boot/dts/bcm2711-rpi-cm4-io.dts27
-rw-r--r--arch/arm/boot/dts/bcm2711-rpi-cm4.dtsi4
-rw-r--r--arch/arm/boot/dts/bcm2711.dtsi95
-rw-r--r--arch/arm/boot/dts/bcm2835-common.dtsi18
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-a-plus.dts28
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-a.dts12
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-b-plus.dts28
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts12
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-b.dts12
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi6
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-common.dtsi17
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-zero-w.dts12
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi-zero.dts12
-rw-r--r--arch/arm/boot/dts/bcm2835-rpi.dtsi10
-rw-r--r--arch/arm/boot/dts/bcm2835.dtsi1
-rw-r--r--arch/arm/boot/dts/bcm2836-rpi-2-b.dts27
-rw-r--r--arch/arm/boot/dts/bcm2836-rpi.dtsi1
-rw-r--r--arch/arm/boot/dts/bcm2836.dtsi4
-rw-r--r--arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts27
-rw-r--r--arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts27
-rw-r--r--arch/arm/boot/dts/bcm2837-rpi-3-b.dts11
-rw-r--r--arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi8
-rw-r--r--arch/arm/boot/dts/bcm2837-rpi-zero-2-w.dts11
-rw-r--r--arch/arm/boot/dts/bcm2837.dtsi2
-rw-r--r--arch/arm/boot/dts/bcm283x-rpi-led-deprecated.dtsi18
-rw-r--r--arch/arm/boot/dts/bcm283x.dtsi70
-rw-r--r--arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts15
-rw-r--r--arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts8
-rw-r--r--arch/arm/boot/dts/bcm4708-buffalo-wzr-1166dhp-common.dtsi16
-rw-r--r--arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts16
-rw-r--r--arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts6
-rw-r--r--arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts2
-rw-r--r--arch/arm/boot/dts/bcm4708-netgear-r6250.dts10
-rw-r--r--arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts10
-rw-r--r--arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts22
-rw-r--r--arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts10
-rw-r--r--arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts14
-rw-r--r--arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts16
-rw-r--r--arch/arm/boot/dts/bcm47081-luxul-xap-1410.dts6
-rw-r--r--arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts20
-rw-r--r--arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts43
-rw-r--r--arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts6
-rw-r--r--arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts18
-rw-r--r--arch/arm/boot/dts/bcm4709-netgear-r7000.dts16
-rw-r--r--arch/arm/boot/dts/bcm4709-netgear-r8000.dts22
-rw-r--r--arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts43
-rw-r--r--arch/arm/boot/dts/bcm47094-asus-rt-ac88u.dts12
-rw-r--r--arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts14
-rw-r--r--arch/arm/boot/dts/bcm47094-dlink-dir-890l.dts211
-rw-r--r--arch/arm/boot/dts/bcm47094-linksys-panamera.dts28
-rw-r--r--arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts4
-rw-r--r--arch/arm/boot/dts/bcm47094-luxul-xap-1610.dts6
-rw-r--r--arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts4
-rw-r--r--arch/arm/boot/dts/bcm47094-luxul-xwc-2000.dts2
-rw-r--r--arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts20
-rw-r--r--arch/arm/boot/dts/bcm47094-luxul-xwr-3150-v1.dts10
-rw-r--r--arch/arm/boot/dts/bcm47094-netgear-r8500.dts14
-rw-r--r--arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts4
-rw-r--r--arch/arm/boot/dts/bcm47189-luxul-xap-810.dts10
-rw-r--r--arch/arm/boot/dts/bcm47189-tenda-ac9.dts14
-rw-r--r--arch/arm/boot/dts/bcm47622.dtsi1
-rw-r--r--arch/arm/boot/dts/bcm53016-dlink-dwl-8610ap.dts131
-rw-r--r--arch/arm/boot/dts/bcm53016-meraki-mr32.dts6
-rw-r--r--arch/arm/boot/dts/bcm63148.dtsi1
-rw-r--r--arch/arm/boot/dts/bcm63178.dtsi1
-rw-r--r--arch/arm/boot/dts/bcm6756.dtsi1
-rw-r--r--arch/arm/boot/dts/bcm6846.dtsi1
-rw-r--r--arch/arm/boot/dts/bcm6855.dtsi1
-rw-r--r--arch/arm/boot/dts/bcm6878.dtsi1
-rw-r--r--arch/arm/boot/dts/bcm947189acdbmr.dts6
-rw-r--r--arch/arm/boot/dts/dove.dtsi2
-rw-r--r--arch/arm/boot/dts/dra7-evm-common.dtsi2
-rw-r--r--arch/arm/boot/dts/dra7-evm.dts2
-rw-r--r--arch/arm/boot/dts/dra72-evm-common.dtsi4
-rw-r--r--arch/arm/boot/dts/e60k02.dtsi11
-rw-r--r--arch/arm/boot/dts/exynos3250.dtsi2
-rw-r--r--arch/arm/boot/dts/imx6dl-colibri-aster.dts1
-rw-r--r--arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts1
-rw-r--r--arch/arm/boot/dts/imx6dl-colibri-iris.dts1
-rw-r--r--arch/arm/boot/dts/imx6qdl-colibri.dtsi22
-rw-r--r--arch/arm/boot/dts/imx6qdl-pico.dtsi1
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabreauto.dtsi4
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabrelite.dtsi5
-rw-r--r--arch/arm/boot/dts/imx6qdl-sabresd.dtsi8
-rw-r--r--arch/arm/boot/dts/imx6qdl-wandboard.dtsi1
-rw-r--r--arch/arm/boot/dts/imx6sl-kobo-aura2.dts555
-rw-r--r--arch/arm/boot/dts/imx6sl-tolino-shine2hd.dts30
-rw-r--r--arch/arm/boot/dts/imx6sl-tolino-shine3.dts7
-rw-r--r--arch/arm/boot/dts/imx6sll-kobo-clarahd.dts7
-rw-r--r--arch/arm/boot/dts/imx6sx.dtsi2
-rw-r--r--arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi4
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-aster.dts40
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-eval-v3.dts24
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-iris-v2.dts48
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-iris.dts22
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-iris.dtsi4
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-wifi-aster.dts40
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-wifi-eval-v3.dts24
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-wifi-iris-v2.dts32
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri-wifi-iris.dts20
-rw-r--r--arch/arm/boot/dts/imx6ull-colibri.dtsi37
-rw-r--r--arch/arm/boot/dts/imx7-colibri.dtsi5
-rw-r--r--arch/arm/boot/dts/imx7d-remarkable2.dts62
-rw-r--r--arch/arm/boot/dts/imx7s.dtsi4
-rw-r--r--arch/arm/boot/dts/kirkwood-b3.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-db-88f6281.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-db-88f6282.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-dir665.dts14
-rw-r--r--arch/arm/boot/dts/kirkwood-ds112.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-ds411.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-iconnect.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-km_common.dtsi2
-rw-r--r--arch/arm/boot/dts/kirkwood-l-50.dts24
-rw-r--r--arch/arm/boot/dts/kirkwood-laplug.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-linkstation.dtsi2
-rw-r--r--arch/arm/boot/dts/kirkwood-mplcec4.dts16
-rw-r--r--arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-nas2big.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-net2big.dts10
-rw-r--r--arch/arm/boot/dts/kirkwood-net5big.dts10
-rw-r--r--arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts12
-rw-r--r--arch/arm/boot/dts/kirkwood-nsa310.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-nsa310s.dts259
-rw-r--r--arch/arm/boot/dts/kirkwood-nsa320.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-nsa325.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi2
-rw-r--r--arch/arm/boot/dts/kirkwood-rd88f6192.dts60
-rw-r--r--arch/arm/boot/dts/kirkwood-rd88f6281-z0.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-rd88f6281.dtsi4
-rw-r--r--arch/arm/boot/dts/kirkwood-rs212.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-synology.dtsi2
-rw-r--r--arch/arm/boot/dts/kirkwood-t5325.dts2
-rw-r--r--arch/arm/boot/dts/kirkwood-ts219.dtsi4
-rw-r--r--arch/arm/boot/dts/kirkwood.dtsi34
-rw-r--r--arch/arm/boot/dts/lan966x-pcb8290.dts16
-rw-r--r--arch/arm/boot/dts/lan966x.dtsi5
-rw-r--r--arch/arm/boot/dts/logicpd-torpedo-baseboard.dtsi2
-rw-r--r--arch/arm/boot/dts/logicpd-torpedo-som.dtsi2
-rw-r--r--arch/arm/boot/dts/lpc32xx.dtsi2
-rw-r--r--arch/arm/boot/dts/ls1021a-moxa-uc-8410a.dts10
-rw-r--r--arch/arm/boot/dts/motorola-mapphone-common.dtsi4
-rw-r--r--arch/arm/boot/dts/nuvoton-npcm730-gbs.dts2
-rw-r--r--arch/arm/boot/dts/nuvoton-npcm730-gsj.dts2
-rw-r--r--arch/arm/boot/dts/nuvoton-npcm730-kudo.dts6
-rw-r--r--arch/arm/boot/dts/nuvoton-npcm750-evb.dts4
-rw-r--r--arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts6
-rw-r--r--arch/arm/boot/dts/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts36
-rw-r--r--arch/arm/boot/dts/nuvoton-wpcm450.dtsi34
-rw-r--r--arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi6
-rw-r--r--arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi6
-rw-r--r--arch/arm/boot/dts/omap3-beagle.dts6
-rw-r--r--arch/arm/boot/dts/omap3-cm-t3517.dts12
-rw-r--r--arch/arm/boot/dts/omap3-devkit8000-common.dtsi8
-rw-r--r--arch/arm/boot/dts/omap3-echo.dts2
-rw-r--r--arch/arm/boot/dts/omap3-gta04.dtsi8
-rw-r--r--arch/arm/boot/dts/omap3-ldp.dts2
-rw-r--r--arch/arm/boot/dts/omap3-n900.dts42
-rw-r--r--arch/arm/boot/dts/omap3-overo-alto35-common.dtsi8
-rw-r--r--arch/arm/boot/dts/omap3-overo-chestnut43-common.dtsi4
-rw-r--r--arch/arm/boot/dts/omap3-overo-gallop43-common.dtsi4
-rw-r--r--arch/arm/boot/dts/omap3-overo-palo35-common.dtsi4
-rw-r--r--arch/arm/boot/dts/omap3-overo-palo43-common.dtsi4
-rw-r--r--arch/arm/boot/dts/omap3-overo-summit-common.dtsi2
-rw-r--r--arch/arm/boot/dts/omap3-overo-tobi-common.dtsi2
-rw-r--r--arch/arm/boot/dts/omap3-zoom3.dts44
-rw-r--r--arch/arm/boot/dts/omap3.dtsi40
-rw-r--r--arch/arm/boot/dts/omap34xx.dtsi4
-rw-r--r--arch/arm/boot/dts/omap36xx.dtsi4
-rw-r--r--arch/arm/boot/dts/omap4-cpu-thermal.dtsi24
-rw-r--r--arch/arm/boot/dts/omap4-panda-common.dtsi4
-rw-r--r--arch/arm/boot/dts/omap4-panda-es.dts4
-rw-r--r--arch/arm/boot/dts/omap5-cm-t54.dts64
-rw-r--r--arch/arm/boot/dts/pxa168.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom-apq8026-asus-sparrow.dts2
-rw-r--r--arch/arm/boot/dts/qcom-apq8026-huawei-sturgeon.dts376
-rw-r--r--arch/arm/boot/dts/qcom-apq8026-lg-lenok.dts9
-rw-r--r--arch/arm/boot/dts/qcom-apq8026-samsung-matisse-wifi.dts453
-rw-r--r--arch/arm/boot/dts/qcom-apq8060-dragonboard.dts1754
-rw-r--r--arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts524
-rw-r--r--arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts390
-rw-r--r--arch/arm/boot/dts/qcom-apq8064-ifc6410.dts561
-rw-r--r--arch/arm/boot/dts/qcom-apq8064-sony-xperia-lagan-yuga.dts650
-rw-r--r--arch/arm/boot/dts/qcom-apq8064.dtsi149
-rw-r--r--arch/arm/boot/dts/qcom-apq8074-dragonboard.dts60
-rw-r--r--arch/arm/boot/dts/qcom-apq8084.dtsi10
-rw-r--r--arch/arm/boot/dts/qcom-ipq4018-ap120c-ac-bit.dts6
-rw-r--r--arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts6
-rw-r--r--arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom-ipq4018-jalapeno.dts2
-rw-r--r--arch/arm/boot/dts/qcom-ipq4019.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom-ipq8064-rb3011.dts5
-rw-r--r--arch/arm/boot/dts/qcom-ipq8064.dtsi7
-rw-r--r--arch/arm/boot/dts/qcom-mdm9615-wp8548-mangoh-green.dts59
-rw-r--r--arch/arm/boot/dts/qcom-mdm9615-wp8548.dtsi61
-rw-r--r--arch/arm/boot/dts/qcom-mdm9615.dtsi123
-rw-r--r--arch/arm/boot/dts/qcom-msm8226-samsung-s3ve3g.dts1
-rw-r--r--arch/arm/boot/dts/qcom-msm8226.dtsi78
-rw-r--r--arch/arm/boot/dts/qcom-msm8660.dtsi42
-rw-r--r--arch/arm/boot/dts/qcom-msm8960-cdp.dts23
-rw-r--r--arch/arm/boot/dts/qcom-msm8960.dtsi92
-rw-r--r--arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts83
-rw-r--r--arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine-amami.dts1
-rw-r--r--arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine-honami.dts1
-rw-r--r--arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine.dtsi70
-rw-r--r--arch/arm/boot/dts/qcom-msm8974.dtsi174
-rw-r--r--arch/arm/boot/dts/qcom-msm8974pro-fairphone-fp2.dts75
-rw-r--r--arch/arm/boot/dts/qcom-msm8974pro-oneplus-bacon.dts417
-rw-r--r--arch/arm/boot/dts/qcom-msm8974pro-samsung-klte.dts83
-rw-r--r--arch/arm/boot/dts/qcom-msm8974pro-sony-xperia-shinano-castor.dts86
-rw-r--r--arch/arm/boot/dts/qcom-pm8226.dtsi12
-rw-r--r--arch/arm/boot/dts/qcom-pm8941.dtsi33
-rw-r--r--arch/arm/boot/dts/qcom-pma8084.dtsi19
-rw-r--r--arch/arm/boot/dts/qcom-pmx65.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom-sdx55-telit-fn980-tlb.dts45
-rw-r--r--arch/arm/boot/dts/qcom-sdx55.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom-sdx65.dtsi4
-rw-r--r--arch/arm/boot/dts/r8a7742.dtsi2
-rw-r--r--arch/arm/boot/dts/r8a7790.dtsi2
-rw-r--r--arch/arm/boot/dts/r8a7791.dtsi2
-rw-r--r--arch/arm/boot/dts/r8a7793.dtsi2
-rw-r--r--arch/arm/boot/dts/r9a06g032.dtsi10
-rw-r--r--arch/arm/boot/dts/sama7g5-pinfunc.h2
-rw-r--r--arch/arm/boot/dts/sama7g5.dtsi67
-rw-r--r--arch/arm/boot/dts/socfpga.dtsi4
-rw-r--r--arch/arm/boot/dts/socfpga_arria10.dtsi4
-rw-r--r--arch/arm/boot/dts/socfpga_arria10_mercury_aa1.dtsi1
-rw-r--r--arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts4
-rw-r--r--arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts1
-rw-r--r--arch/arm/boot/dts/socfpga_arria5.dtsi3
-rw-r--r--arch/arm/boot/dts/socfpga_arria5_socdk.dts8
-rw-r--r--arch/arm/boot/dts/socfpga_cyclone5.dtsi3
-rw-r--r--arch/arm/boot/dts/socfpga_cyclone5_de0_nano_soc.dts2
-rw-r--r--arch/arm/boot/dts/socfpga_cyclone5_mcv.dtsi1
-rw-r--r--arch/arm/boot/dts/socfpga_cyclone5_socdk.dts8
-rw-r--r--arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts2
-rw-r--r--arch/arm/boot/dts/socfpga_vt.dts2
-rw-r--r--arch/arm/boot/dts/spear600.dtsi32
-rw-r--r--arch/arm/boot/dts/ste-dbx5x0.dtsi6
-rw-r--r--arch/arm/boot/dts/ste-ux500-samsung-codina-tmo.dts2
-rw-r--r--arch/arm/boot/dts/ste-ux500-samsung-codina.dts2
-rw-r--r--arch/arm/boot/dts/ste-ux500-samsung-gavini.dts2
-rw-r--r--arch/arm/boot/dts/ste-ux500-samsung-janice.dts16
-rw-r--r--arch/arm/boot/dts/ste-ux500-samsung-kyle.dts29
-rw-r--r--arch/arm/boot/dts/stih410-b2260.dts8
-rw-r--r--arch/arm/boot/dts/stih418-b2199.dts4
-rw-r--r--arch/arm/boot/dts/stih418-b2264.dts2
-rw-r--r--arch/arm/boot/dts/stihxxx-b2120.dtsi4
-rw-r--r--arch/arm/boot/dts/stm32h743.dtsi2
-rw-r--r--arch/arm/boot/dts/stm32mp13-pinctrl.dtsi21
-rw-r--r--arch/arm/boot/dts/stm32mp131.dtsi126
-rw-r--r--arch/arm/boot/dts/stm32mp133.dtsi31
-rw-r--r--arch/arm/boot/dts/stm32mp135f-dk.dts144
-rw-r--r--arch/arm/boot/dts/stm32mp151.dtsi3
-rw-r--r--arch/arm/boot/dts/stm32mp151a-dhcor-testbench.dts17
-rw-r--r--arch/arm/boot/dts/stm32mp157a-dhcor-avenger96.dts1
-rw-r--r--arch/arm/boot/dts/stm32mp157c-emstamp-argon.dtsi2
-rw-r--r--arch/arm/boot/dts/stm32mp157c-ev1.dts15
-rw-r--r--arch/arm/boot/dts/stm32mp157c-lxa-mc1.dts2
-rw-r--r--arch/arm/boot/dts/stm32mp157c-odyssey.dts2
-rw-r--r--arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi4
-rw-r--r--arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi2
-rw-r--r--arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi7
-rw-r--r--arch/arm/boot/dts/stm32mp15xx-dhcor-drc-compact.dtsi2
-rw-r--r--arch/arm/boot/dts/stm32mp15xx-dhcor-testbench.dtsi171
-rw-r--r--arch/arm/boot/dts/stm32mp15xx-dkx.dtsi6
-rw-r--r--arch/arm/boot/dts/suniv-f1c100s.dtsi70
-rw-r--r--arch/arm/boot/dts/sunplus-sp7021.dtsi3
-rw-r--r--arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi14
-rw-r--r--arch/arm/boot/dts/sunxi-h3-h5.dtsi4
-rw-r--r--arch/arm/boot/dts/tegra114-asus-tf701t.dts24
-rw-r--r--arch/arm/boot/dts/tegra124-nyan-big.dts3
-rw-r--r--arch/arm/boot/dts/tegra124-nyan-blaze.dts3
-rw-r--r--arch/arm/boot/dts/tegra124-venice2.dts3
-rw-r--r--arch/arm/boot/dts/tegra20-acer-a500-picasso.dts6
-rw-r--r--arch/arm/boot/dts/tegra20-asus-tf101.dts8
-rw-r--r--arch/arm/boot/dts/tegra20-seaboard.dts6
-rw-r--r--arch/arm/boot/dts/tegra20-tamonten.dtsi6
-rw-r--r--arch/arm/boot/dts/tegra20-ventana.dts6
-rw-r--r--arch/arm/boot/dts/tegra30-asus-transformer-common.dtsi10
-rw-r--r--arch/arm/boot/dts/tegra30-pegatron-chagall.dts11
-rw-r--r--arch/arm/boot/dts/uniphier-pro5-epcore.dts76
-rw-r--r--arch/arm/boot/dts/uniphier-pro5-proex.dts59
-rw-r--r--arch/arm/boot/dts/vexpress-v2m.dtsi16
-rw-r--r--arch/arm/boot/dts/vf610-zii-dev-rev-c.dts2
-rw-r--r--arch/arm/common/Makefile2
-rw-r--r--arch/arm/common/mcpm_head.S2
-rw-r--r--arch/arm/common/vlock.S2
-rw-r--r--arch/arm/configs/clps711x_defconfig3
-rw-r--r--arch/arm/configs/collie_defconfig3
-rw-r--r--arch/arm/configs/imx_v6_v7_defconfig5
-rw-r--r--arch/arm/configs/multi_v4t_defconfig3
-rw-r--r--arch/arm/configs/multi_v7_defconfig8
-rw-r--r--arch/arm/configs/omap1_defconfig3
-rw-r--r--arch/arm/configs/pxa_defconfig3
-rw-r--r--arch/arm/configs/qcom_defconfig5
-rw-r--r--arch/arm/configs/sama5_defconfig2
-rw-r--r--arch/arm/configs/sama7_defconfig11
-rw-r--r--arch/arm/configs/spear6xx_defconfig7
-rw-r--r--arch/arm/configs/tct_hammer_defconfig3
-rw-r--r--arch/arm/configs/xcep_defconfig3
-rw-r--r--arch/arm/include/asm/assembler.h6
-rw-r--r--arch/arm/include/asm/cputype.h4
-rw-r--r--arch/arm/include/asm/efi.h3
-rw-r--r--arch/arm/include/asm/module.h5
-rw-r--r--arch/arm/include/asm/ptdump.h1
-rw-r--r--arch/arm/include/asm/ptrace.h4
-rw-r--r--arch/arm/include/asm/stackprotector.h9
-rw-r--r--arch/arm/include/asm/stacktrace.h2
-rw-r--r--arch/arm/include/asm/vfp.h6
-rw-r--r--arch/arm/include/asm/xor.h4
-rw-r--r--arch/arm/include/uapi/asm/hwcap.h8
-rw-r--r--arch/arm/kernel/Makefile2
-rw-r--r--arch/arm/kernel/efi.c31
-rw-r--r--arch/arm/kernel/hyp-stub.S2
-rw-r--r--arch/arm/kernel/machine_kexec.c4
-rw-r--r--arch/arm/kernel/module-plts.c14
-rw-r--r--arch/arm/kernel/perf_callchain.c9
-rw-r--r--arch/arm/kernel/process.c2
-rw-r--r--arch/arm/kernel/ptrace.c8
-rw-r--r--arch/arm/kernel/return_address.c8
-rw-r--r--arch/arm/kernel/setup.c22
-rw-r--r--arch/arm/kernel/smp.c5
-rw-r--r--arch/arm/kernel/stacktrace.c119
-rw-r--r--arch/arm/kernel/swp_emulate.c1
-rw-r--r--arch/arm/kernel/traps.c25
-rw-r--r--arch/arm/kernel/unwind.c13
-rw-r--r--arch/arm/lib/Makefile6
-rw-r--r--arch/arm/lib/delay-loop.S4
-rw-r--r--arch/arm/lib/error-inject.c10
-rw-r--r--arch/arm/lib/findbit.S230
-rw-r--r--arch/arm/mach-at91/Makefile3
-rw-r--r--arch/arm/mach-at91/pm_suspend.S4
-rw-r--r--arch/arm/mach-imx/Makefile3
-rw-r--r--arch/arm/mach-imx/headsmp.S2
-rw-r--r--arch/arm/mach-imx/mm-imx3.c1
-rw-r--r--arch/arm/mach-imx/resume-imx6.S2
-rw-r--r--arch/arm/mach-imx/suspend-imx6.S2
-rw-r--r--arch/arm/mach-ixp4xx/ixp4xx-of.c42
-rw-r--r--arch/arm/mach-keystone/Makefile4
-rw-r--r--arch/arm/mach-keystone/keystone.c2
-rw-r--r--arch/arm/mach-keystone/keystone.h5
-rw-r--r--arch/arm/mach-keystone/platsmp.c41
-rw-r--r--arch/arm/mach-keystone/smc.S26
-rw-r--r--arch/arm/mach-mmp/time.c11
-rw-r--r--arch/arm/mach-mvebu/Makefile3
-rw-r--r--arch/arm/mach-mvebu/coherency_ll.S1
-rw-r--r--arch/arm/mach-mvebu/pm-board.c28
-rw-r--r--arch/arm/mach-mvebu/pmsu.c1
-rw-r--r--arch/arm/mach-mxs/mach-mxs.c1
-rw-r--r--arch/arm/mach-npcm/Makefile2
-rw-r--r--arch/arm/mach-npcm/headsmp.S2
-rw-r--r--arch/arm/mach-omap2/board-n8x0.c5
-rw-r--r--arch/arm/mach-omap2/common-board-devices.h2
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_3xxx_data.c99
-rw-r--r--arch/arm/mach-omap2/pdata-quirks.c1
-rw-r--r--arch/arm/mach-s3c/mach-crag6410.c1
-rw-r--r--arch/arm/mach-shmobile/Kconfig2
-rw-r--r--arch/arm/mach-spear/time.c8
-rw-r--r--arch/arm/mach-tegra/Makefile2
-rw-r--r--arch/arm/mach-tegra/reset-handler.S2
-rw-r--r--arch/arm/mach-tegra/sleep-tegra20.S2
-rw-r--r--arch/arm/mach-tegra/sleep-tegra30.S2
-rw-r--r--arch/arm/mach-tegra/sleep.S2
-rw-r--r--arch/arm/mach-ux500/cpu-db8500.c1
-rw-r--r--arch/arm/mach-ux500/db8500-regs.h195
-rw-r--r--arch/arm/mach-ux500/platsmp.c2
-rw-r--r--arch/arm/mach-ux500/pm.c4
-rw-r--r--arch/arm/mm/Makefile15
-rw-r--r--arch/arm/mm/abort-ev6.S1
-rw-r--r--arch/arm/mm/abort-ev7.S1
-rw-r--r--arch/arm/mm/cache-v6.S2
-rw-r--r--arch/arm/mm/cache-v7.S2
-rw-r--r--arch/arm/mm/cache-v7m.S2
-rw-r--r--arch/arm/mm/copypage-feroceon.c1
-rw-r--r--arch/arm/mm/dma-mapping.c17
-rw-r--r--arch/arm/mm/fault.c23
-rw-r--r--arch/arm/mm/fault.h9
-rw-r--r--arch/arm/mm/proc-v6.S2
-rw-r--r--arch/arm/mm/proc-v7-2level.S2
-rw-r--r--arch/arm/mm/proc-v7.S2
-rw-r--r--arch/arm/mm/tlb-v6.S2
-rw-r--r--arch/arm/mm/tlb-v7.S2
-rw-r--r--arch/arm/nwfpe/Makefile6
-rw-r--r--arch/arm/vdso/Makefile1
-rw-r--r--arch/arm/vfp/vfpmodule.c32
-rw-r--r--arch/arm/xen/enlighten.c2
-rw-r--r--arch/arm64/Kconfig50
-rw-r--r--arch/arm64/Kconfig.platforms2
-rw-r--r--arch/arm64/Makefile17
-rw-r--r--arch/arm64/boot/dts/allwinner/axp803.dtsi10
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts14
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts41
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts25
-rw-r--r--arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi160
-rw-r--r--arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi1
-rw-r--r--arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts7
-rw-r--r--arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_nand.dts6
-rw-r--r--arch/arm64/boot/dts/amlogic/Makefile1
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-a1.dtsi1
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-axg.dtsi1
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi6
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12a.dtsi5
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12b-odroid-go-ultra.dts722
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi42
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-g12b.dtsi5
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gx.dtsi1
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi14
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts1
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxl.dtsi14
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts1
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-gxm-minix-neo-u9h.dts1
-rw-r--r--arch/arm64/boot/dts/amlogic/meson-sm1.dtsi5
-rw-r--r--arch/arm64/boot/dts/apple/Makefile6
-rw-r--r--arch/arm64/boot/dts/apple/multi-die-cpp.h22
-rw-r--r--arch/arm64/boot/dts/apple/t6000-j314s.dts18
-rw-r--r--arch/arm64/boot/dts/apple/t6000-j316s.dts18
-rw-r--r--arch/arm64/boot/dts/apple/t6000.dtsi18
-rw-r--r--arch/arm64/boot/dts/apple/t6001-j314c.dts18
-rw-r--r--arch/arm64/boot/dts/apple/t6001-j316c.dts18
-rw-r--r--arch/arm64/boot/dts/apple/t6001-j375c.dts18
-rw-r--r--arch/arm64/boot/dts/apple/t6001.dtsi63
-rw-r--r--arch/arm64/boot/dts/apple/t6002-j375d.dts50
-rw-r--r--arch/arm64/boot/dts/apple/t6002.dtsi301
-rw-r--r--arch/arm64/boot/dts/apple/t600x-common.dtsi374
-rw-r--r--arch/arm64/boot/dts/apple/t600x-die0.dtsi361
-rw-r--r--arch/arm64/boot/dts/apple/t600x-dieX.dtsi121
-rw-r--r--arch/arm64/boot/dts/apple/t600x-gpio-pins.dtsi45
-rw-r--r--arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi114
-rw-r--r--arch/arm64/boot/dts/apple/t600x-j375.dtsi117
-rw-r--r--arch/arm64/boot/dts/apple/t600x-nvme.dtsi42
-rw-r--r--arch/arm64/boot/dts/apple/t600x-pmgr.dtsi2012
-rw-r--r--arch/arm64/boot/dts/apple/t8103-j456.dts2
-rw-r--r--arch/arm64/boot/dts/apple/t8103-j457.dts2
-rw-r--r--arch/arm64/boot/dts/apple/t8103-jxxx.dtsi4
-rw-r--r--arch/arm64/boot/dts/apple/t8103-pmgr.dtsi2
-rw-r--r--arch/arm64/boot/dts/apple/t8103.dtsi322
-rw-r--r--arch/arm64/boot/dts/arm/corstone1000.dtsi1
-rw-r--r--arch/arm64/boot/dts/arm/foundation-v8.dtsi6
-rw-r--r--arch/arm64/boot/dts/arm/fvp-base-revc.dts73
-rw-r--r--arch/arm64/boot/dts/arm/juno-r1.dts2
-rw-r--r--arch/arm64/boot/dts/arm/juno-r2.dts2
-rw-r--r--arch/arm64/boot/dts/arm/juno.dts2
-rw-r--r--arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts1
-rw-r--r--arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts1
-rw-r--r--arch/arm64/boot/dts/broadcom/bcmbca/bcm4908.dtsi6
-rw-r--r--arch/arm64/boot/dts/broadcom/bcmbca/bcm4912.dtsi1
-rw-r--r--arch/arm64/boot/dts/broadcom/bcmbca/bcm63146.dtsi1
-rw-r--r--arch/arm64/boot/dts/broadcom/bcmbca/bcm63158.dtsi1
-rw-r--r--arch/arm64/boot/dts/broadcom/bcmbca/bcm6813.dtsi1
-rw-r--r--arch/arm64/boot/dts/broadcom/bcmbca/bcm6856.dtsi1
-rw-r--r--arch/arm64/boot/dts/broadcom/bcmbca/bcm6858.dtsi20
-rw-r--r--arch/arm64/boot/dts/broadcom/northstar2/ns2-svk.dts2
-rw-r--r--arch/arm64/boot/dts/broadcom/northstar2/ns2-xmc.dts2
-rw-r--r--arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi1
-rw-r--r--arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi4
-rw-r--r--arch/arm64/boot/dts/freescale/Makefile2
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dtso (renamed from arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dts)0
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-65bb.dtso (renamed from arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-65bb.dts)0
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-7777.dtso (renamed from arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-7777.dts)0
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-85bb.dtso (renamed from arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-85bb.dts)0
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-899b.dtso (renamed from arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-899b.dts)0
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-9999.dtso (renamed from arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-9999.dts)0
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi1
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi1
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi1
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi4
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi4
-rw-r--r--arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi8
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi39
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi164
-rw-r--r--arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi17
-rw-r--r--arch/arm64/boot/dts/freescale/imx8dxl-evk.dts107
-rw-r--r--arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi20
-rw-r--r--arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi10
-rw-r--r--arch/arm64/boot/dts/freescale/imx8dxl-ss-lsio.dtsi46
-rw-r--r--arch/arm64/boot/dts/freescale/imx8dxl.dtsi7
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-beacon-som.dtsi6
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc.dts24
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-evk.dts6
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi6
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-innocomm-wb15-evk.dts146
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-innocomm-wb15.dtsi480
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-kontron-osm-s.dtsi4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-kontron-sl.dtsi4
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-phg.dts266
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-phycore-som.dtsi6
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-var-som.dtsi6
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi30
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-imx219.dtso (renamed from arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-imx219.dts)0
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs232-rts.dtso (renamed from arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs232-rts.dts)0
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs422.dtso (renamed from arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs422.dts)0
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs485.dtso (renamed from arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs485.dts)0
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-imx219.dtso (renamed from arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-imx219.dts)0
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dtso (renamed from arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dts)0
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dtso (renamed from arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dts)0
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dtso (renamed from arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dts)0
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts54
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts66
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts42
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts54
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi16
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mm.dtsi6
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn-beacon-som.dtsi6
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts6
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn-evk.dts3
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi47
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts62
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mn.dtsi7
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi31
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-evk.dts111
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts159
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts48
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi1
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi49
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mp.dtsi34
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-evk.dts9
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts22
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi6
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq-tqma8mq.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8mq.dtsi16
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm-ss-lsio.dtsi38
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qm.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-colibri-eval-v3.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp-ss-lsio.dtsi25
-rw-r--r--arch/arm64/boot/dts/freescale/imx8qxp.dtsi1
-rw-r--r--arch/arm64/boot/dts/freescale/imx8ulp.dtsi1
-rw-r--r--arch/arm64/boot/dts/freescale/imx93.dtsi111
-rw-r--r--arch/arm64/boot/dts/freescale/mba8mx.dtsi1
-rw-r--r--arch/arm64/boot/dts/freescale/s32g2.dtsi2
-rw-r--r--arch/arm64/boot/dts/freescale/s32v234.dtsi2
-rw-r--r--arch/arm64/boot/dts/hisilicon/hi3660.dtsi2
-rw-r--r--arch/arm64/boot/dts/hisilicon/hi6220.dtsi2
-rw-r--r--arch/arm64/boot/dts/hisilicon/hip05.dtsi4
-rw-r--r--arch/arm64/boot/dts/hisilicon/hip06.dtsi4
-rw-r--r--arch/arm64/boot/dts/hisilicon/hip07.dtsi16
-rw-r--r--arch/arm64/boot/dts/intel/socfpga_agilex.dtsi1
-rw-r--r--arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts1
-rw-r--r--arch/arm64/boot/dts/intel/socfpga_n5x_socdk.dts1
-rw-r--r--arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi1
-rw-r--r--arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts4
-rw-r--r--arch/arm64/boot/dts/marvell/armada-37xx.dtsi5
-rw-r--r--arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi1
-rw-r--r--arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi2
-rw-r--r--arch/arm64/boot/dts/marvell/armada-ap807-quad.dtsi2
-rw-r--r--arch/arm64/boot/dts/marvell/armada-ap80x.dtsi5
-rw-r--r--arch/arm64/boot/dts/mediatek/Makefile1
-rw-r--r--arch/arm64/boot/dts/mediatek/mt2712-evb.dts12
-rw-r--r--arch/arm64/boot/dts/mediatek/mt2712e.dtsi28
-rw-r--r--arch/arm64/boot/dts/mediatek/mt6779.dtsi10
-rw-r--r--arch/arm64/boot/dts/mediatek/mt6795-sony-xperia-m5.dts88
-rw-r--r--arch/arm64/boot/dts/mediatek/mt6795.dtsi109
-rw-r--r--arch/arm64/boot/dts/mediatek/mt6797.dtsi2
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts1
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts1
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts135
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7986a.dtsi74
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts57
-rw-r--r--arch/arm64/boot/dts/mediatek/mt7986b.dtsi3
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi6
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8186.dtsi3
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8192.dtsi3
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi86
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8195.dtsi233
-rw-r--r--arch/arm64/boot/dts/mediatek/pumpkin-common.dtsi6
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra132-norrin.dts2
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra132.dtsi1
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra186.dtsi12
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi2
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra194-p3509-0000.dtsi4
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra194-p3668.dtsi2
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra194.dtsi70
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi5
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts4
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra210.dtsi61
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra234-p3701-0000.dtsi8
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0000.dts21
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra234-p3737-0000.dtsi14
-rw-r--r--arch/arm64/boot/dts/nvidia/tegra234.dtsi666
-rw-r--r--arch/arm64/boot/dts/qcom/Makefile27
-rw-r--r--arch/arm64/boot/dts/qcom/apq8016-sbc.dts16
-rw-r--r--arch/arm64/boot/dts/qcom/apq8096-db820c.dts114
-rw-r--r--arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts70
-rw-r--r--arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts11
-rw-r--r--arch/arm64/boot/dts/qcom/ipq6018.dtsi25
-rw-r--r--arch/arm64/boot/dts/qcom/ipq8074-hk01.dts10
-rw-r--r--arch/arm64/boot/dts/qcom/ipq8074-hk10-c1.dts3
-rw-r--r--arch/arm64/boot/dts/qcom/ipq8074-hk10-c2.dts3
-rw-r--r--arch/arm64/boot/dts/qcom/ipq8074-hk10.dtsi21
-rw-r--r--arch/arm64/boot/dts/qcom/ipq8074.dtsi134
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts80
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-asus-z00l.dts24
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-huawei-g7.dts24
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts22
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-longcheer-l8910.dts8
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-pins.dtsi276
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-pm8916.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi112
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts14
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts10
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-e2015-common.dtsi28
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-grandmax.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-j5.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-samsung-serranove.dts45
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dts47
-rw-r--r--arch/arm64/boot/dts/qcom/msm8916.dtsi17
-rw-r--r--arch/arm64/boot/dts/qcom/msm8953.dtsi314
-rw-r--r--arch/arm64/boot/dts/qcom/msm8956-sony-xperia-loire-kugo.dts35
-rw-r--r--arch/arm64/boot/dts/qcom/msm8956-sony-xperia-loire-suzu.dts17
-rw-r--r--arch/arm64/boot/dts/qcom/msm8956-sony-xperia-loire.dtsi282
-rw-r--r--arch/arm64/boot/dts/qcom/msm8956.dtsi18
-rw-r--r--arch/arm64/boot/dts/qcom/msm8976.dtsi1198
-rw-r--r--arch/arm64/boot/dts/qcom/msm8992-lg-bullhead-rev-10.dts3
-rw-r--r--arch/arm64/boot/dts/qcom/msm8992-lg-bullhead-rev-101.dts3
-rw-r--r--arch/arm64/boot/dts/qcom/msm8992-lg-bullhead.dtsi45
-rw-r--r--arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts4
-rw-r--r--arch/arm64/boot/dts/qcom/msm8992.dtsi3
-rw-r--r--arch/arm64/boot/dts/qcom/msm8994-huawei-angler-rev-101.dts3
-rw-r--r--arch/arm64/boot/dts/qcom/msm8994-msft-lumia-octagon.dtsi12
-rw-r--r--arch/arm64/boot/dts/qcom/msm8994-sony-xperia-kitakami.dtsi10
-rw-r--r--arch/arm64/boot/dts/qcom/msm8994.dtsi135
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996-oneplus-common.dtsi787
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996-oneplus3.dts44
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996-oneplus3t.dts45
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone.dtsi29
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996-xiaomi-common.dtsi17
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996-xiaomi-gemini.dts11
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996.dtsi389
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996pro-xiaomi-natrium.dts (renamed from arch/arm64/boot/dts/qcom/msm8996-xiaomi-natrium.dts)9
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996pro-xiaomi-scorpio.dts (renamed from arch/arm64/boot/dts/qcom/msm8996-xiaomi-scorpio.dts)13
-rw-r--r--arch/arm64/boot/dts/qcom/msm8996pro.dtsi291
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi9
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998-fxtec-pro1.dts28
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998-lenovo-miix-630.dts4
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998-mtp.dts16
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998-oneplus-cheeseburger.dts12
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998-oneplus-common.dtsi22
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998-sony-xperia-yoshino.dtsi67
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998-xiaomi-sagit.dts711
-rw-r--r--arch/arm64/boot/dts/qcom/msm8998.dtsi95
-rw-r--r--arch/arm64/boot/dts/qcom/pm6125.dtsi154
-rw-r--r--arch/arm64/boot/dts/qcom/pm6150.dtsi6
-rw-r--r--arch/arm64/boot/dts/qcom/pm6150l.dtsi44
-rw-r--r--arch/arm64/boot/dts/qcom/pm6350.dtsi41
-rw-r--r--arch/arm64/boot/dts/qcom/pm660.dtsi4
-rw-r--r--arch/arm64/boot/dts/qcom/pm660l.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/pm7325.dtsi6
-rw-r--r--arch/arm64/boot/dts/qcom/pm8005.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/pm8150b.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/pm8450a.dtsi77
-rw-r--r--arch/arm64/boot/dts/qcom/pm8916.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/pm8950.dtsi165
-rw-r--r--arch/arm64/boot/dts/qcom/pm8994.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/pm8998.dtsi12
-rw-r--r--arch/arm64/boot/dts/qcom/pmi8950.dtsi97
-rw-r--r--arch/arm64/boot/dts/qcom/pmi8994.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/pmi8998.dtsi10
-rw-r--r--arch/arm64/boot/dts/qcom/pmk8350.dtsi22
-rw-r--r--arch/arm64/boot/dts/qcom/pmp8074.dtsi125
-rw-r--r--arch/arm64/boot/dts/qcom/pms405.dtsi4
-rw-r--r--arch/arm64/boot/dts/qcom/qcs404-evb-1000.dts4
-rw-r--r--arch/arm64/boot/dts/qcom/qcs404-evb-4000.dts24
-rw-r--r--arch/arm64/boot/dts/qcom/qcs404-evb.dtsi58
-rw-r--r--arch/arm64/boot/dts/qcom/qcs404.dtsi70
-rw-r--r--arch/arm64/boot/dts/qcom/qrb5165-rb5-vision-mezzanine.dts62
-rw-r--r--arch/arm64/boot/dts/qcom/qrb5165-rb5.dts22
-rw-r--r--arch/arm64/boot/dts/qcom/sa8155p-adp.dts82
-rw-r--r--arch/arm64/boot/dts/qcom/sa8295p-adp.dts199
-rw-r--r--arch/arm64/boot/dts/qcom/sa8540p-ride.dts270
-rw-r--r--arch/arm64/boot/dts/qcom/sa8540p.dtsi98
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-idp.dts236
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi36
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi51
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown-r0.dts16
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown.dtsi9
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi16
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-mrbland-rev0.dtsi25
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-mrbland.dtsi78
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-parade-ps8640.dtsi34
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel.dtsi8
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel360-lte.dts22
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel360-wifi.dts17
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel360.dtsi50
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi14
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick.dtsi60
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-r1.dts8
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-ti-sn65dsi86.dtsi16
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev0.dtsi25
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-boe-rt5682s.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-inx-rt5682s.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi78
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi668
-rw-r--r--arch/arm64/boot/dts/qcom/sc7180.dtsi606
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-chrome-common.dtsi15
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-crd-r3.dts8
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-herobrine-audio-rt5682-3mic.dtsi187
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-herobrine-audio-rt5682.dtsi122
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-herobrine-audio-wcd9385.dtsi20
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-herobrine-crd.dts1
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-herobrine-evoker-lte.dts16
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-herobrine-evoker.dts16
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-herobrine-evoker.dtsi (renamed from arch/arm64/boot/dts/qcom/sc7280-herobrine-evoker-r0.dts)24
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-herobrine-herobrine-r1.dts6
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi19
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-herobrine-villager-r1-lte.dts4
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-herobrine-villager-r1.dts31
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-herobrine-villager-r1.dtsi37
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-herobrine-villager.dtsi11
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi11
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-herobrine-zombie-lte.dts16
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-herobrine-zombie.dts16
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-herobrine-zombie.dtsi312
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-herobrine.dtsi73
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-idp-ec-h1.dtsi10
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-idp.dts6
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-idp.dtsi55
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi22
-rw-r--r--arch/arm64/boot/dts/qcom/sc7280.dtsi432
-rw-r--r--arch/arm64/boot/dts/qcom/sc8280xp-crd.dts219
-rw-r--r--arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts439
-rw-r--r--arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi84
-rw-r--r--arch/arm64/boot/dts/qcom/sc8280xp.dtsi786
-rw-r--r--arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts14
-rw-r--r--arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile.dtsi24
-rw-r--r--arch/arm64/boot/dts/qcom/sdm630.dtsi140
-rw-r--r--arch/arm64/boot/dts/qcom/sdm632-fairphone-fp3.dts16
-rw-r--r--arch/arm64/boot/dts/qcom/sdm636-sony-xperia-ganges-mermaid.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sdm660-xiaomi-lavender.dts10
-rw-r--r--arch/arm64/boot/dts/qcom/sdm660.dtsi3
-rw-r--r--arch/arm64/boot/dts/qcom/sdm670-google-sargo.dts531
-rw-r--r--arch/arm64/boot/dts/qcom/sdm670.dtsi1160
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi49
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dts104
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-db845c.dts169
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-lg-common.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi39
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts460
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts9
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi2
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi (renamed from arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium.dts)46
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-ebbg.dts15
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-tianma.dts15
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts36
-rw-r--r--arch/arm64/boot/dts/qcom/sdm845.dtsi177
-rw-r--r--arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts10
-rw-r--r--arch/arm64/boot/dts/qcom/sdm850-samsung-w737.dts24
-rw-r--r--arch/arm64/boot/dts/qcom/sm4250-oneplus-billie2.dts241
-rw-r--r--arch/arm64/boot/dts/qcom/sm4250.dtsi38
-rw-r--r--arch/arm64/boot/dts/qcom/sm6115.dtsi1425
-rw-r--r--arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts164
-rw-r--r--arch/arm64/boot/dts/qcom/sm6125.dtsi8
-rw-r--r--arch/arm64/boot/dts/qcom/sm6350-sony-xperia-lena-pdx213.dts335
-rw-r--r--arch/arm64/boot/dts/qcom/sm6350.dtsi56
-rw-r--r--arch/arm64/boot/dts/qcom/sm6375-sony-xperia-murray-pdx225.dts406
-rw-r--r--arch/arm64/boot/dts/qcom/sm6375.dtsi1396
-rw-r--r--arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts37
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150-microsoft-surface-duo.dts2
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150-sony-xperia-kumano.dtsi10
-rw-r--r--arch/arm64/boot/dts/qcom/sm8150.dtsi407
-rw-r--r--arch/arm64/boot/dts/qcom/sm8250-mtp.dts40
-rw-r--r--arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi41
-rw-r--r--arch/arm64/boot/dts/qcom/sm8250.dtsi1205
-rw-r--r--arch/arm64/boot/dts/qcom/sm8350-hdk.dts20
-rw-r--r--arch/arm64/boot/dts/qcom/sm8350-sony-xperia-sagami-pdx215.dts206
-rw-r--r--arch/arm64/boot/dts/qcom/sm8350-sony-xperia-sagami.dtsi604
-rw-r--r--arch/arm64/boot/dts/qcom/sm8350.dtsi98
-rw-r--r--arch/arm64/boot/dts/qcom/sm8450-hdk.dts205
-rw-r--r--arch/arm64/boot/dts/qcom/sm8450-qrd.dts19
-rw-r--r--arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara-pdx223.dts831
-rw-r--r--arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara-pdx224.dts234
-rw-r--r--arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara.dtsi631
-rw-r--r--arch/arm64/boot/dts/qcom/sm8450.dtsi600
-rw-r--r--arch/arm64/boot/dts/renesas/aistarvision-mipi-adapter-2.1.dtsi1
-rw-r--r--arch/arm64/boot/dts/renesas/condor-common.dtsi1
-rw-r--r--arch/arm64/boot/dts/renesas/draak-ebisu-panel-aa104xd12.dtso (renamed from arch/arm64/boot/dts/renesas/draak-ebisu-panel-aa104xd12.dts)0
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779a0.dtsi24
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi30
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779f0-spider-ethernet.dtsi90
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779f0.dtsi126
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779g0-white-hawk-cpu.dtsi89
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779g0.dtsi735
-rw-r--r--arch/arm64/boot/dts/renesas/r9a07g043.dtsi362
-rw-r--r--arch/arm64/boot/dts/renesas/r9a07g043u.dtsi73
-rw-r--r--arch/arm64/boot/dts/renesas/r9a07g043u11-smarc.dts2
-rw-r--r--arch/arm64/boot/dts/renesas/r9a07g044.dtsi17
-rw-r--r--arch/arm64/boot/dts/renesas/r9a07g044c2-smarc.dts30
-rw-r--r--arch/arm64/boot/dts/renesas/r9a07g054.dtsi17
-rw-r--r--arch/arm64/boot/dts/renesas/r9a09g011-v2mevk2.dts4
-rw-r--r--arch/arm64/boot/dts/renesas/r9a09g011.dtsi31
-rw-r--r--arch/arm64/boot/dts/renesas/rzg2l-smarc-som.dtsi5
-rw-r--r--arch/arm64/boot/dts/renesas/rzg2lc-smarc-som.dtsi5
-rw-r--r--arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi28
-rw-r--r--arch/arm64/boot/dts/renesas/rzg2ul-smarc-pinfunction.dtsi7
-rw-r--r--arch/arm64/boot/dts/renesas/rzg2ul-smarc-som.dtsi7
-rw-r--r--arch/arm64/boot/dts/renesas/salvator-panel-aa104xd12.dtso (renamed from arch/arm64/boot/dts/renesas/salvator-panel-aa104xd12.dts)0
-rw-r--r--arch/arm64/boot/dts/rockchip/Makefile10
-rw-r--r--arch/arm64/boot/dts/rockchip/px30-ringneck-haikou.dts232
-rw-r--r--arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi382
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3308.dtsi1
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3326-anbernic-rg351m.dts33
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3326-odroid-go.dtsi600
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3326-odroid-go2-v11.dts156
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts620
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3326-odroid-go3.dts185
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3328.dtsi12
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts76
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-rock-4c-plus.dts6
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi2
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3399.dtsi20
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353p.dts109
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353v.dts114
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353vs.dts87
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353x.dtsi60
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg503.dts79
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-anbernic-rgxx3.dtsi47
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-box-demo.dts503
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-roc-pc.dts34
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-soquartz-blade.dts194
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts11
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-soquartz-model-a.dts232
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi75
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts744
-rw-r--r--arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts146
-rw-r--r--arch/arm64/boot/dts/rockchip/rk356x.dtsi50
-rw-r--r--arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi34
-rw-r--r--arch/arm64/boot/dts/tesla/fsd-pinctrl.h6
-rw-r--r--arch/arm64/boot/dts/ti/Makefile1
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-main.dtsi122
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi49
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi4
-rw-r--r--arch/arm64/boot/dts/ti/k3-am625-sk.dts90
-rw-r--r--arch/arm64/boot/dts/ti/k3-am625.dtsi51
-rw-r--r--arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi2
-rw-r--r--arch/arm64/boot/dts/ti/k3-am64-main.dtsi44
-rw-r--r--arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi6
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-evm.dts119
-rw-r--r--arch/arm64/boot/dts/ti/k3-am642-sk.dts142
-rw-r--r--arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi101
-rw-r--r--arch/arm64/boot/dts/ti/k3-am65-main.dtsi207
-rw-r--r--arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi85
-rw-r--r--arch/arm64/boot/dts/ti/k3-am65-wakeup.dtsi2
-rw-r--r--arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic-common.dtsi1
-rw-r--r--arch/arm64/boot/dts/ti/k3-am654-base-board.dts113
-rw-r--r--arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-common.dtsi4
-rw-r--r--arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts48
-rw-r--r--arch/arm64/boot/dts/ti/k3-j7200-main.dtsi29
-rw-r--r--arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi8
-rw-r--r--arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi42
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts1055
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts143
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721e-main.dtsi125
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi11
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721e-sk.dts205
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi33
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts132
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi79
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi9
-rw-r--r--arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi98
-rw-r--r--arch/arm64/boot/dts/xilinx/zynqmp-zcu106-revA.dts20
-rw-r--r--arch/arm64/boot/dts/xilinx/zynqmp.dtsi24
-rw-r--r--arch/arm64/configs/defconfig43
-rw-r--r--arch/arm64/include/asm/alternative-macros.h4
-rw-r--r--arch/arm64/include/asm/archrandom.h48
-rw-r--r--arch/arm64/include/asm/assembler.h33
-rw-r--r--arch/arm64/include/asm/cpufeature.h3
-rw-r--r--arch/arm64/include/asm/cputype.h2
-rw-r--r--arch/arm64/include/asm/efi.h27
-rw-r--r--arch/arm64/include/asm/exception.h7
-rw-r--r--arch/arm64/include/asm/fpsimd.h17
-rw-r--r--arch/arm64/include/asm/ftrace.h72
-rw-r--r--arch/arm64/include/asm/hugetlb.h9
-rw-r--r--arch/arm64/include/asm/hwcap.h3
-rw-r--r--arch/arm64/include/asm/insn.h156
-rw-r--r--arch/arm64/include/asm/jump_label.h8
-rw-r--r--arch/arm64/include/asm/kernel-pgtable.h11
-rw-r--r--arch/arm64/include/asm/kvm_host.h12
-rw-r--r--arch/arm64/include/asm/lse.h1
-rw-r--r--arch/arm64/include/asm/mmu_context.h10
-rw-r--r--arch/arm64/include/asm/module.lds.h8
-rw-r--r--arch/arm64/include/asm/pgtable-hwdef.h1
-rw-r--r--arch/arm64/include/asm/pgtable.h14
-rw-r--r--arch/arm64/include/asm/processor.h24
-rw-r--r--arch/arm64/include/asm/ptdump.h1
-rw-r--r--arch/arm64/include/asm/scs.h49
-rw-r--r--arch/arm64/include/asm/spectre.h2
-rw-r--r--arch/arm64/include/asm/stackprotector.h9
-rw-r--r--arch/arm64/include/asm/stacktrace.h2
-rw-r--r--arch/arm64/include/asm/sysreg.h150
-rw-r--r--arch/arm64/include/asm/traps.h19
-rw-r--r--arch/arm64/include/asm/uprobes.h2
-rw-r--r--arch/arm64/include/uapi/asm/hwcap.h3
-rw-r--r--arch/arm64/include/uapi/asm/sigcontext.h4
-rw-r--r--arch/arm64/kernel/Makefile11
-rw-r--r--arch/arm64/kernel/acpi.c106
-rw-r--r--arch/arm64/kernel/alternative.c6
-rw-r--r--arch/arm64/kernel/armv8_deprecated.c567
-rw-r--r--arch/arm64/kernel/asm-offsets.c13
-rw-r--r--arch/arm64/kernel/cpu_errata.c7
-rw-r--r--arch/arm64/kernel/cpufeature.c253
-rw-r--r--arch/arm64/kernel/cpuinfo.c3
-rw-r--r--arch/arm64/kernel/efi-entry.S69
-rw-r--r--arch/arm64/kernel/efi-rt-wrapper.S39
-rw-r--r--arch/arm64/kernel/efi.c49
-rw-r--r--arch/arm64/kernel/entry-common.c24
-rw-r--r--arch/arm64/kernel/entry-ftrace.S156
-rw-r--r--arch/arm64/kernel/entry.S3
-rw-r--r--arch/arm64/kernel/fpsimd.c169
-rw-r--r--arch/arm64/kernel/ftrace.c87
-rw-r--r--arch/arm64/kernel/head.S3
-rw-r--r--arch/arm64/kernel/image-vars.h8
-rw-r--r--arch/arm64/kernel/irq.c11
-rw-r--r--arch/arm64/kernel/module.c11
-rw-r--r--arch/arm64/kernel/paravirt.c4
-rw-r--r--arch/arm64/kernel/patch-scs.c257
-rw-r--r--arch/arm64/kernel/perf_event.c21
-rw-r--r--arch/arm64/kernel/pi/Makefile1
-rw-r--r--arch/arm64/kernel/probes/decode-insn.c2
-rw-r--r--arch/arm64/kernel/probes/kprobes.c86
-rw-r--r--arch/arm64/kernel/process.c4
-rw-r--r--arch/arm64/kernel/proton-pack.c26
-rw-r--r--arch/arm64/kernel/ptrace.c21
-rw-r--r--arch/arm64/kernel/sdei.c2
-rw-r--r--arch/arm64/kernel/setup.c4
-rw-r--r--arch/arm64/kernel/signal.c7
-rw-r--r--arch/arm64/kernel/stacktrace.c10
-rw-r--r--arch/arm64/kernel/suspend.c2
-rw-r--r--arch/arm64/kernel/syscall.c19
-rw-r--r--arch/arm64/kernel/traps.c93
-rw-r--r--arch/arm64/kernel/vdso.c22
-rw-r--r--arch/arm64/kernel/vmlinux.lds.S13
-rw-r--r--arch/arm64/kvm/fpsimd.c26
-rw-r--r--arch/arm64/kvm/hyp/nvhe/Makefile1
-rw-r--r--arch/arm64/kvm/sys_regs.c4
-rw-r--r--arch/arm64/lib/insn.c165
-rw-r--r--arch/arm64/lib/mte.S2
-rw-r--r--arch/arm64/mm/fault.c12
-rw-r--r--arch/arm64/mm/hugetlbpage.c21
-rw-r--r--arch/arm64/mm/init.c25
-rw-r--r--arch/arm64/mm/mmu.c23
-rw-r--r--arch/arm64/mm/proc.S4
-rw-r--r--arch/arm64/tools/cpucaps2
-rwxr-xr-xarch/arm64/tools/gen-sysreg.awk2
-rw-r--r--arch/arm64/tools/sysreg766
-rw-r--r--arch/csky/include/asm/stackprotector.h10
-rw-r--r--arch/csky/kernel/process.c4
-rw-r--r--arch/hexagon/kernel/ptrace.c7
-rw-r--r--arch/ia64/hp/common/aml_nfw.c4
-rw-r--r--arch/ia64/include/asm/io.h4
-rw-r--r--arch/ia64/include/asm/kprobes.h2
-rw-r--r--arch/ia64/kernel/ptrace.c20
-rw-r--r--arch/ia64/kernel/sys_ia64.c6
-rw-r--r--arch/loongarch/Kconfig1
-rw-r--r--arch/loongarch/include/asm/acpi.h142
-rw-r--r--arch/loongarch/include/asm/efi.h14
-rw-r--r--arch/loongarch/include/asm/irq.h2
-rw-r--r--arch/loongarch/kernel/efi.c24
-rw-r--r--arch/loongarch/kernel/head.S3
-rw-r--r--arch/loongarch/kernel/image-vars.h8
-rw-r--r--arch/loongarch/kernel/process.c2
-rw-r--r--arch/loongarch/kernel/vdso.c2
-rw-r--r--arch/m68k/configs/amiga_defconfig42
-rw-r--r--arch/m68k/configs/apollo_defconfig42
-rw-r--r--arch/m68k/configs/atari_defconfig42
-rw-r--r--arch/m68k/configs/bvme6000_defconfig42
-rw-r--r--arch/m68k/configs/hp300_defconfig42
-rw-r--r--arch/m68k/configs/mac_defconfig42
-rw-r--r--arch/m68k/configs/multi_defconfig42
-rw-r--r--arch/m68k/configs/mvme147_defconfig42
-rw-r--r--arch/m68k/configs/mvme16x_defconfig42
-rw-r--r--arch/m68k/configs/q40_defconfig42
-rw-r--r--arch/m68k/configs/sun3_defconfig42
-rw-r--r--arch/m68k/configs/sun3x_defconfig42
-rw-r--r--arch/m68k/emu/nfcon.c9
-rw-r--r--arch/m68k/include/asm/mac_via.h8
-rw-r--r--arch/m68k/kernel/process.c4
-rw-r--r--arch/m68k/mac/misc.c2
-rw-r--r--arch/microblaze/Kconfig8
-rw-r--r--arch/microblaze/configs/mmu_defconfig1
-rw-r--r--arch/microblaze/include/asm/pci-bridge.h92
-rw-r--r--arch/microblaze/include/asm/pci.h29
-rw-r--r--arch/microblaze/kernel/process.c2
-rw-r--r--arch/microblaze/pci/Makefile3
-rw-r--r--arch/microblaze/pci/indirect_pci.c158
-rw-r--r--arch/microblaze/pci/iomap.c36
-rw-r--r--arch/microblaze/pci/pci-common.c1067
-rw-r--r--arch/microblaze/pci/xilinx_pci.c170
-rw-r--r--arch/mips/Makefile2
-rw-r--r--arch/mips/bcm63xx/clk.c2
-rw-r--r--arch/mips/boot/dts/brcm/bcm63268.dtsi5
-rw-r--r--arch/mips/boot/dts/brcm/bcm7435.dtsi1
-rw-r--r--arch/mips/boot/dts/ingenic/ci20.dts2
-rw-r--r--arch/mips/boot/dts/mscc/jaguar2_pcb110.dts4
-rw-r--r--arch/mips/boot/dts/qca/ar9331.dtsi1
-rw-r--r--arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts2
-rw-r--r--arch/mips/boot/dts/ralink/mt7621.dtsi11
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-bootmem.c3
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-helper-board.c2
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-helper.c2
-rw-r--r--arch/mips/include/asm/asm-prototypes.h3
-rw-r--r--arch/mips/include/asm/mach-ralink/mt7621.h4
-rw-r--r--arch/mips/include/asm/stackprotector.h9
-rw-r--r--arch/mips/kernel/process.c2
-rw-r--r--arch/mips/kernel/ptrace.c9
-rw-r--r--arch/mips/kernel/vdso.c2
-rw-r--r--arch/mips/kernel/vpe-cmp.c4
-rw-r--r--arch/mips/kernel/vpe-mt.c4
-rw-r--r--arch/mips/pci/pci-rt3883.c4
-rw-r--r--arch/mips/ralink/mt7621.c97
-rw-r--r--arch/mips/vdso/Makefile2
-rw-r--r--arch/nios2/kernel/ptrace.c6
-rw-r--r--arch/openrisc/configs/or1ksim_defconfig3
-rw-r--r--arch/openrisc/configs/simple_smp_defconfig3
-rw-r--r--arch/openrisc/kernel/ptrace.c8
-rw-r--r--arch/parisc/kernel/ptrace.c15
-rw-r--r--arch/parisc/kernel/vdso.c2
-rw-r--r--arch/powerpc/configs/microwatt_defconfig1
-rw-r--r--arch/powerpc/crypto/crc-vpmsum_test.c4
-rw-r--r--arch/powerpc/include/asm/ftrace.h24
-rw-r--r--arch/powerpc/include/asm/stackprotector.h10
-rw-r--r--arch/powerpc/kernel/process.c2
-rw-r--r--arch/powerpc/kernel/ptrace/ptrace-tm.c10
-rw-r--r--arch/powerpc/kernel/ptrace/ptrace-view.c15
-rw-r--r--arch/powerpc/kernel/vdso.c22
-rw-r--r--arch/powerpc/kexec/file_load_64.c2
-rw-r--r--arch/powerpc/kexec/ranges.c8
-rw-r--r--arch/powerpc/perf/core-book3s.c8
-rw-r--r--arch/powerpc/platforms/pseries/msi.c7
-rw-r--r--arch/riscv/Kconfig.socs5
-rw-r--r--arch/riscv/boot/dts/Makefile1
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs-icicle-kit-fabric.dtsi33
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts36
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs-m100pfs-fabric.dtsi4
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs-polarberry-fabric.dtsi4
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs-sev-kit-fabric.dtsi29
-rw-r--r--arch/riscv/boot/dts/microchip/mpfs.dtsi32
-rw-r--r--arch/riscv/boot/dts/renesas/Makefile2
-rw-r--r--arch/riscv/boot/dts/renesas/r9a07g043f.dtsi59
-rw-r--r--arch/riscv/boot/dts/renesas/r9a07g043f01-smarc.dts27
-rw-r--r--arch/riscv/boot/dts/renesas/rzfive-smarc-som.dtsi47
-rw-r--r--arch/riscv/boot/dts/renesas/rzfive-smarc.dtsi64
-rw-r--r--arch/riscv/boot/dts/starfive/Makefile2
-rw-r--r--arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts153
-rw-r--r--arch/riscv/boot/dts/starfive/jh7100-common.dtsi161
-rw-r--r--arch/riscv/boot/dts/starfive/jh7100-starfive-visionfive-v1.dts20
-rw-r--r--arch/riscv/configs/defconfig3
-rw-r--r--arch/riscv/configs/nommu_k210_defconfig3
-rw-r--r--arch/riscv/configs/nommu_k210_sdcard_defconfig3
-rw-r--r--arch/riscv/configs/nommu_virt_defconfig3
-rw-r--r--arch/riscv/include/asm/efi.h13
-rw-r--r--arch/riscv/include/asm/stackprotector.h10
-rw-r--r--arch/riscv/kernel/image-vars.h6
-rw-r--r--arch/riscv/kernel/vdso.c22
-rw-r--r--arch/s390/Kconfig8
-rw-r--r--arch/s390/appldata/appldata_base.c113
-rw-r--r--arch/s390/boot/ipl_parm.c9
-rw-r--r--arch/s390/configs/debug_defconfig2
-rw-r--r--arch/s390/configs/defconfig2
-rw-r--r--arch/s390/configs/zfcpdump_defconfig1
-rw-r--r--arch/s390/hypfs/hypfs_diag.c8
-rw-r--r--arch/s390/include/asm/bugs.h21
-rw-r--r--arch/s390/include/asm/checksum.h7
-rw-r--r--arch/s390/include/asm/ftrace.h29
-rw-r--r--arch/s390/include/asm/ipl.h11
-rw-r--r--arch/s390/include/asm/pai.h6
-rw-r--r--arch/s390/include/asm/sclp.h2
-rw-r--r--arch/s390/include/asm/serial.h7
-rw-r--r--arch/s390/include/asm/shmparam.h12
-rw-r--r--arch/s390/include/asm/vga.h7
-rw-r--r--arch/s390/include/asm/vx-insn-asm.h681
-rw-r--r--arch/s390/include/asm/vx-insn.h671
-rw-r--r--arch/s390/include/uapi/asm/ipl.h29
-rw-r--r--arch/s390/kernel/crash_dump.c2
-rw-r--r--arch/s390/kernel/debug.c7
-rw-r--r--arch/s390/kernel/entry.S34
-rw-r--r--arch/s390/kernel/fpu.c3
-rw-r--r--arch/s390/kernel/ipl.c403
-rw-r--r--arch/s390/kernel/kprobes.c3
-rw-r--r--arch/s390/kernel/kprobes.h9
-rw-r--r--arch/s390/kernel/nmi.c181
-rw-r--r--arch/s390/kernel/perf_pai_crypto.c50
-rw-r--r--arch/s390/kernel/perf_pai_ext.c14
-rw-r--r--arch/s390/kernel/process.c2
-rw-r--r--arch/s390/kernel/setup.c3
-rw-r--r--arch/s390/kernel/vdso.c22
-rw-r--r--arch/s390/mm/init.c39
-rw-r--r--arch/s390/mm/maccess.c2
-rw-r--r--arch/s390/mm/page-states.c11
-rw-r--r--arch/s390/pci/pci_irq.c2
-rw-r--r--arch/sh/configs/rsk7201_defconfig3
-rw-r--r--arch/sh/configs/rsk7203_defconfig3
-rw-r--r--arch/sh/configs/se7206_defconfig3
-rw-r--r--arch/sh/configs/shmin_defconfig3
-rw-r--r--arch/sh/configs/shx3_defconfig3
-rw-r--r--arch/sh/include/asm/stackprotector.h10
-rw-r--r--arch/sh/kernel/ptrace_32.c8
-rw-r--r--arch/sparc/kernel/ptrace_32.c9
-rw-r--r--arch/sparc/kernel/ptrace_64.c23
-rw-r--r--arch/sparc/vdso/vma.c2
-rw-r--r--arch/um/drivers/Kconfig1
-rw-r--r--arch/um/include/asm/pci.h2
-rw-r--r--arch/um/kernel/kmsg_dump.c24
-rw-r--r--arch/um/kernel/process.c5
-rw-r--r--arch/x86/Kconfig55
-rw-r--r--arch/x86/boot/compressed/Makefile8
-rw-r--r--arch/x86/boot/compressed/efi_mixed.S345
-rw-r--r--arch/x86/boot/compressed/efi_thunk_64.S195
-rw-r--r--arch/x86/boot/compressed/head_32.S4
-rw-r--r--arch/x86/boot/compressed/head_64.S303
-rw-r--r--arch/x86/boot/compressed/kaslr.c2
-rw-r--r--arch/x86/boot/compressed/mem_encrypt.S152
-rw-r--r--arch/x86/boot/cpuflags.c15
-rw-r--r--arch/x86/boot/header.S5
-rw-r--r--arch/x86/boot/string.c2
-rw-r--r--arch/x86/boot/tools/build.c2
-rw-r--r--arch/x86/coco/tdx/tdx.c40
-rw-r--r--arch/x86/entry/entry_64_compat.S4
-rw-r--r--arch/x86/entry/vdso/vdso.lds.S2
-rw-r--r--arch/x86/entry/vdso/vma.c32
-rw-r--r--arch/x86/events/amd/brs.c2
-rw-r--r--arch/x86/events/amd/ibs.c4
-rw-r--r--arch/x86/events/amd/lbr.c6
-rw-r--r--arch/x86/events/core.c48
-rw-r--r--arch/x86/events/intel/core.c23
-rw-r--r--arch/x86/events/intel/ds.c4
-rw-r--r--arch/x86/events/intel/lbr.c30
-rw-r--r--arch/x86/events/intel/p4.c2
-rw-r--r--arch/x86/events/intel/uncore.h24
-rw-r--r--arch/x86/events/intel/uncore_snb.c3
-rw-r--r--arch/x86/events/intel/uncore_snbep.c495
-rw-r--r--arch/x86/events/perf_event.h31
-rw-r--r--arch/x86/hyperv/hv_init.c4
-rw-r--r--arch/x86/ia32/Makefile2
-rw-r--r--arch/x86/include/asm/apic.h3
-rw-r--r--arch/x86/include/asm/cacheinfo.h13
-rw-r--r--arch/x86/include/asm/cpu.h2
-rw-r--r--arch/x86/include/asm/cpufeatures.h1
-rw-r--r--arch/x86/include/asm/cpuid.h141
-rw-r--r--arch/x86/include/asm/disabled-features.h8
-rw-r--r--arch/x86/include/asm/efi.h109
-rw-r--r--arch/x86/include/asm/elf.h5
-rw-r--r--arch/x86/include/asm/entry-common.h4
-rw-r--r--arch/x86/include/asm/fpu/signal.h7
-rw-r--r--arch/x86/include/asm/ftrace.h49
-rw-r--r--arch/x86/include/asm/hyperv-tlfs.h11
-rw-r--r--arch/x86/include/asm/hyperv_timer.h9
-rw-r--r--arch/x86/include/asm/irq_remapping.h4
-rw-r--r--arch/x86/include/asm/irqdomain.h4
-rw-r--r--arch/x86/include/asm/memtype.h5
-rw-r--r--arch/x86/include/asm/microcode.h4
-rw-r--r--arch/x86/include/asm/microcode_intel.h5
-rw-r--r--arch/x86/include/asm/mshyperv.h2
-rw-r--r--arch/x86/include/asm/msi.h6
-rw-r--r--arch/x86/include/asm/msr-index.h22
-rw-r--r--arch/x86/include/asm/mtrr.h16
-rw-r--r--arch/x86/include/asm/paravirt_types.h61
-rw-r--r--arch/x86/include/asm/pci.h5
-rw-r--r--arch/x86/include/asm/processor.h133
-rw-r--r--arch/x86/include/asm/realmode.h1
-rw-r--r--arch/x86/include/asm/resctrl.h8
-rw-r--r--arch/x86/include/asm/segment.h2
-rw-r--r--arch/x86/include/asm/sgx.h33
-rw-r--r--arch/x86/include/asm/sighandling.h9
-rw-r--r--arch/x86/include/asm/signal.h5
-rw-r--r--arch/x86/include/asm/stackprotector.h14
-rw-r--r--arch/x86/include/asm/switch_to.h7
-rw-r--r--arch/x86/include/asm/tdx.h2
-rw-r--r--arch/x86/include/asm/x86_init.h4
-rw-r--r--arch/x86/kernel/Makefile4
-rw-r--r--arch/x86/kernel/acpi/cstate.c24
-rw-r--r--arch/x86/kernel/alternative.c4
-rw-r--r--arch/x86/kernel/apic/apic.c13
-rw-r--r--arch/x86/kernel/apic/msi.c211
-rw-r--r--arch/x86/kernel/apic/vector.c4
-rw-r--r--arch/x86/kernel/cpu/amd.c2
-rw-r--r--arch/x86/kernel/cpu/bugs.c105
-rw-r--r--arch/x86/kernel/cpu/cacheinfo.c179
-rw-r--r--arch/x86/kernel/cpu/common.c4
-rw-r--r--arch/x86/kernel/cpu/cpuid-deps.c1
-rw-r--r--arch/x86/kernel/cpu/hygon.c2
-rw-r--r--arch/x86/kernel/cpu/intel.c207
-rw-r--r--arch/x86/kernel/cpu/intel_epb.c7
-rw-r--r--arch/x86/kernel/cpu/mce/amd.c33
-rw-r--r--arch/x86/kernel/cpu/mce/severity.c8
-rw-r--r--arch/x86/kernel/cpu/microcode/amd.c5
-rw-r--r--arch/x86/kernel/cpu/microcode/core.c205
-rw-r--r--arch/x86/kernel/cpu/microcode/intel.c167
-rw-r--r--arch/x86/kernel/cpu/mshyperv.c6
-rw-r--r--arch/x86/kernel/cpu/mtrr/amd.c8
-rw-r--r--arch/x86/kernel/cpu/mtrr/centaur.c8
-rw-r--r--arch/x86/kernel/cpu/mtrr/cyrix.c42
-rw-r--r--arch/x86/kernel/cpu/mtrr/generic.c107
-rw-r--r--arch/x86/kernel/cpu/mtrr/mtrr.c173
-rw-r--r--arch/x86/kernel/cpu/mtrr/mtrr.h15
-rw-r--r--arch/x86/kernel/cpu/resctrl/core.c4
-rw-r--r--arch/x86/kernel/cpu/resctrl/ctrlmondata.c3
-rw-r--r--arch/x86/kernel/cpu/resctrl/internal.h10
-rw-r--r--arch/x86/kernel/cpu/resctrl/pseudo_lock.c4
-rw-r--r--arch/x86/kernel/cpu/scattered.c1
-rw-r--r--arch/x86/kernel/cpu/sgx/encl.c35
-rw-r--r--arch/x86/kernel/cpu/sgx/ioctl.c6
-rw-r--r--arch/x86/kernel/cpu/sgx/main.c8
-rw-r--r--arch/x86/kernel/crash_dump_64.c2
-rw-r--r--arch/x86/kernel/devicetree.c18
-rw-r--r--arch/x86/kernel/espfix_64.c12
-rw-r--r--arch/x86/kernel/fpu/core.c19
-rw-r--r--arch/x86/kernel/fpu/init.c7
-rw-r--r--arch/x86/kernel/fpu/regset.c2
-rw-r--r--arch/x86/kernel/fpu/signal.c2
-rw-r--r--arch/x86/kernel/fpu/xstate.c64
-rw-r--r--arch/x86/kernel/fpu/xstate.h4
-rw-r--r--arch/x86/kernel/head_32.S22
-rw-r--r--arch/x86/kernel/i8259.c2
-rw-r--r--arch/x86/kernel/module.c13
-rw-r--r--arch/x86/kernel/process.c2
-rw-r--r--arch/x86/kernel/process_64.c4
-rw-r--r--arch/x86/kernel/ptrace.c174
-rw-r--r--arch/x86/kernel/setup.c17
-rw-r--r--arch/x86/kernel/setup_percpu.c2
-rw-r--r--arch/x86/kernel/signal.c654
-rw-r--r--arch/x86/kernel/signal_32.c (renamed from arch/x86/ia32/ia32_signal.c)117
-rw-r--r--arch/x86/kernel/signal_64.c383
-rw-r--r--arch/x86/kernel/smpboot.c10
-rw-r--r--arch/x86/kernel/topology.c2
-rw-r--r--arch/x86/kernel/traps.c4
-rw-r--r--arch/x86/kernel/tsc.c2
-rw-r--r--arch/x86/kernel/uprobes.c4
-rw-r--r--arch/x86/kernel/x86_init.c3
-rw-r--r--arch/x86/kvm/cpuid.c6
-rw-r--r--arch/x86/kvm/reverse_cpuid.h3
-rw-r--r--arch/x86/lib/Makefile1
-rw-r--r--arch/x86/lib/memcpy_32.c187
-rw-r--r--arch/x86/lib/memmove_32.S200
-rw-r--r--arch/x86/mm/cpu_entry_area.c8
-rw-r--r--arch/x86/mm/pat/cpa-test.c4
-rw-r--r--arch/x86/mm/pat/memtype.c157
-rw-r--r--arch/x86/mm/pat/set_memory.c18
-rw-r--r--arch/x86/platform/efi/Makefile5
-rw-r--r--arch/x86/platform/efi/efi.c8
-rw-r--r--arch/x86/platform/efi/fake_mem.c (renamed from drivers/firmware/efi/fake_mem.c)79
-rw-r--r--arch/x86/platform/efi/memmap.c239
-rw-r--r--arch/x86/platform/efi/runtime-map.c (renamed from drivers/firmware/efi/runtime-map.c)7
-rw-r--r--arch/x86/platform/olpc/olpc-xo15-sci.c3
-rw-r--r--arch/x86/power/cpu.c3
-rw-r--r--arch/x86/realmode/init.c8
-rw-r--r--arch/x86/um/asm/elf.h4
-rw-r--r--arch/x86/xen/enlighten_pv.c4
-rw-r--r--arch/x86/xen/smp.c24
-rw-r--r--arch/x86/xen/smp_pv.c12
-rw-r--r--arch/x86/xen/spinlock.c6
-rw-r--r--arch/x86/xen/xen-asm.S8
-rw-r--r--arch/xtensa/configs/audio_kc705_defconfig1
-rw-r--r--arch/xtensa/configs/cadence_csp_defconfig4
-rw-r--r--arch/xtensa/configs/generic_kc705_defconfig1
-rw-r--r--arch/xtensa/configs/nommu_kc705_defconfig1
-rw-r--r--arch/xtensa/configs/smp_lx200_defconfig1
-rw-r--r--arch/xtensa/configs/xip_kc705_defconfig1
-rw-r--r--arch/xtensa/include/asm/stackprotector.h9
-rw-r--r--arch/xtensa/kernel/xtensa_ksyms.c2
-rw-r--r--arch/xtensa/lib/Makefile2
-rw-r--r--arch/xtensa/lib/umulsidi3.S230
-rw-r--r--block/bdev.c4
-rw-r--r--block/bfq-cgroup.c12
-rw-r--r--block/bfq-iosched.c102
-rw-r--r--block/bfq-iosched.h32
-rw-r--r--block/bfq-wf2q.c157
-rw-r--r--block/bio.c146
-rw-r--r--block/blk-cgroup.c94
-rw-r--r--block/blk-cgroup.h10
-rw-r--r--block/blk-core.c83
-rw-r--r--block/blk-crypto-internal.h22
-rw-r--r--block/blk-crypto-profile.c1
-rw-r--r--block/blk-crypto-sysfs.c11
-rw-r--r--block/blk-crypto.c43
-rw-r--r--block/blk-ia-ranges.c3
-rw-r--r--block/blk-iocost.c57
-rw-r--r--block/blk-iolatency.c37
-rw-r--r--block/blk-map.c14
-rw-r--r--block/blk-merge.c44
-rw-r--r--block/blk-mq-sched.c8
-rw-r--r--block/blk-mq-sysfs.c11
-rw-r--r--block/blk-mq.c229
-rw-r--r--block/blk-mq.h14
-rw-r--r--block/blk-settings.c6
-rw-r--r--block/blk-sysfs.c137
-rw-r--r--block/blk-throttle.c102
-rw-r--r--block/blk-wbt.c26
-rw-r--r--block/blk-wbt.h17
-rw-r--r--block/blk.h27
-rw-r--r--block/bsg-lib.c2
-rw-r--r--block/bsg.c11
-rw-r--r--block/elevator.c254
-rw-r--r--block/elevator.h20
-rw-r--r--block/fops.c7
-rw-r--r--block/genhd.c35
-rw-r--r--block/holder.c103
-rw-r--r--block/ioctl.c12
-rw-r--r--block/mq-deadline.c83
-rw-r--r--block/sed-opal.c39
-rw-r--r--crypto/rsa-pkcs1pad.c2
-rw-r--r--crypto/testmgr.c90
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/accel/Kconfig24
-rw-r--r--drivers/accel/drm_accel.c323
-rw-r--r--drivers/acpi/Kconfig12
-rw-r--r--drivers/acpi/Makefile1
-rw-r--r--drivers/acpi/ac.c8
-rw-r--r--drivers/acpi/acpi_ffh.c55
-rw-r--r--drivers/acpi/acpi_pad.c7
-rw-r--r--drivers/acpi/acpi_pcc.c47
-rw-r--r--drivers/acpi/acpi_video.c8
-rw-r--r--drivers/acpi/acpica/Makefile1
-rw-r--r--drivers/acpi/acpica/acglobal.h1
-rw-r--r--drivers/acpi/acpica/actables.h5
-rw-r--r--drivers/acpi/acpica/acutils.h13
-rw-r--r--drivers/acpi/acpica/dsmethod.c10
-rw-r--r--drivers/acpi/acpica/evevent.c11
-rw-r--r--drivers/acpi/acpica/evregion.c9
-rw-r--r--drivers/acpi/acpica/exconfig.c4
-rw-r--r--drivers/acpi/acpica/exfield.c8
-rw-r--r--drivers/acpi/acpica/exserial.c6
-rw-r--r--drivers/acpi/acpica/hwsleep.c14
-rw-r--r--drivers/acpi/acpica/tbdata.c2
-rw-r--r--drivers/acpi/acpica/tbfadt.c2
-rw-r--r--drivers/acpi/acpica/tbprint.c77
-rw-r--r--drivers/acpi/acpica/tbutils.c2
-rw-r--r--drivers/acpi/acpica/tbxfroot.c32
-rw-r--r--drivers/acpi/acpica/utcksum.c170
-rw-r--r--drivers/acpi/acpica/utcopy.c7
-rw-r--r--drivers/acpi/acpica/utglobal.c4
-rw-r--r--drivers/acpi/acpica/utstring.c10
-rw-r--r--drivers/acpi/apei/apei-base.c2
-rw-r--r--drivers/acpi/apei/einj.c56
-rw-r--r--drivers/acpi/apei/ghes.c128
-rw-r--r--drivers/acpi/arm64/Kconfig3
-rw-r--r--drivers/acpi/arm64/Makefile1
-rw-r--r--drivers/acpi/arm64/apmt.c178
-rw-r--r--drivers/acpi/arm64/iort.c16
-rw-r--r--drivers/acpi/battery.c16
-rw-r--r--drivers/acpi/bus.c5
-rw-r--r--drivers/acpi/button.c5
-rw-r--r--drivers/acpi/cppc_acpi.c4
-rw-r--r--drivers/acpi/ec.c15
-rw-r--r--drivers/acpi/fan_attr.c16
-rw-r--r--drivers/acpi/fan_core.c1
-rw-r--r--drivers/acpi/hed.c3
-rw-r--r--drivers/acpi/irq.c5
-rw-r--r--drivers/acpi/nfit/core.c3
-rw-r--r--drivers/acpi/nfit/intel.c30
-rw-r--r--drivers/acpi/pci_irq.c6
-rw-r--r--drivers/acpi/pci_root.c1
-rw-r--r--drivers/acpi/pfr_telemetry.c6
-rw-r--r--drivers/acpi/pfr_update.c8
-rw-r--r--drivers/acpi/power.c2
-rw-r--r--drivers/acpi/processor_idle.c9
-rw-r--r--drivers/acpi/processor_perflib.c100
-rw-r--r--drivers/acpi/processor_throttling.c4
-rw-r--r--drivers/acpi/sbs.c9
-rw-r--r--drivers/acpi/sbshc.c7
-rw-r--r--drivers/acpi/scan.c2
-rw-r--r--drivers/acpi/sysfs.c5
-rw-r--r--drivers/acpi/tables.c17
-rw-r--r--drivers/acpi/thermal.c9
-rw-r--r--drivers/acpi/tiny-power-button.c10
-rw-r--r--drivers/acpi/video_detect.c110
-rw-r--r--drivers/acpi/x86/utils.c24
-rw-r--r--drivers/amba/bus.c6
-rw-r--r--drivers/ata/Kconfig13
-rw-r--r--drivers/ata/Makefile1
-rw-r--r--drivers/ata/ahci.c1
-rw-r--r--drivers/ata/ahci.h245
-rw-r--r--drivers/ata/libahci.c20
-rw-r--r--drivers/ata/libata-acpi.c4
-rw-r--r--drivers/ata/libata-core.c7
-rw-r--r--drivers/ata/libata-eh.c40
-rw-r--r--drivers/ata/libata-sata.c50
-rw-r--r--drivers/ata/libata-scsi.c18
-rw-r--r--drivers/ata/libata-sff.c56
-rw-r--r--drivers/ata/libata.h1
-rw-r--r--drivers/ata/pata_bk3710.c380
-rw-r--r--drivers/ata/pata_ep93xx.c3
-rw-r--r--drivers/ata/pata_ftide010.c2
-rw-r--r--drivers/ata/pata_mpc52xx.c2
-rw-r--r--drivers/ata/sata_dwc_460ex.c12
-rw-r--r--drivers/ata/sata_gemini.c2
-rw-r--r--drivers/ata/sata_nv.c2
-rw-r--r--drivers/ata/sata_promise.c2
-rw-r--r--drivers/ata/sata_sx4.c2
-rw-r--r--drivers/base/Makefile2
-rw-r--r--drivers/base/platform-msi.c6
-rw-r--r--drivers/base/power/domain.c176
-rw-r--r--drivers/base/power/domain_governor.c3
-rw-r--r--drivers/base/power/runtime.c145
-rw-r--r--drivers/base/regmap/Kconfig6
-rw-r--r--drivers/base/regmap/Makefile1
-rw-r--r--drivers/base/regmap/regmap-fsi.c231
-rw-r--r--drivers/base/regmap/regmap-irq.c59
-rw-r--r--drivers/base/regmap/regmap.c13
-rw-r--r--drivers/block/Kconfig43
-rw-r--r--drivers/block/Makefile1
-rw-r--r--drivers/block/drbd/Kconfig2
-rw-r--r--drivers/block/drbd/Makefile2
-rw-r--r--drivers/block/drbd/drbd_actlog.c8
-rw-r--r--drivers/block/drbd/drbd_bitmap.c62
-rw-r--r--drivers/block/drbd/drbd_debugfs.c2
-rw-r--r--drivers/block/drbd/drbd_debugfs.h2
-rw-r--r--drivers/block/drbd/drbd_int.h78
-rw-r--r--drivers/block/drbd/drbd_interval.c2
-rw-r--r--drivers/block/drbd/drbd_interval.h2
-rw-r--r--drivers/block/drbd/drbd_main.c23
-rw-r--r--drivers/block/drbd/drbd_nl.c27
-rw-r--r--drivers/block/drbd/drbd_nla.c2
-rw-r--r--drivers/block/drbd/drbd_nla.h2
-rw-r--r--drivers/block/drbd/drbd_polymorph_printk.h141
-rw-r--r--drivers/block/drbd/drbd_proc.c2
-rw-r--r--drivers/block/drbd/drbd_protocol.h2
-rw-r--r--drivers/block/drbd/drbd_receiver.c105
-rw-r--r--drivers/block/drbd/drbd_req.c8
-rw-r--r--drivers/block/drbd/drbd_req.h2
-rw-r--r--drivers/block/drbd/drbd_state.c2
-rw-r--r--drivers/block/drbd/drbd_state.h2
-rw-r--r--drivers/block/drbd/drbd_state_change.h2
-rw-r--r--drivers/block/drbd/drbd_strings.c2
-rw-r--r--drivers/block/drbd/drbd_strings.h2
-rw-r--r--drivers/block/drbd/drbd_vli.h2
-rw-r--r--drivers/block/drbd/drbd_worker.c18
-rw-r--r--drivers/block/floppy.c4
-rw-r--r--drivers/block/loop.c12
-rw-r--r--drivers/block/nbd.c10
-rw-r--r--drivers/block/null_blk/main.c22
-rw-r--r--drivers/block/null_blk/null_blk.h8
-rw-r--r--drivers/block/null_blk/zoned.c95
-rw-r--r--drivers/block/pktcdvd.c2944
-rw-r--r--drivers/block/virtio_blk.c8
-rw-r--r--drivers/block/xen-blkfront.c1
-rw-r--r--drivers/bluetooth/hci_qca.c10
-rw-r--r--drivers/bus/fsl-mc/Kconfig2
-rw-r--r--drivers/bus/fsl-mc/dprc-driver.c1
-rw-r--r--drivers/bus/fsl-mc/fsl-mc-bus.c1
-rw-r--r--drivers/bus/fsl-mc/fsl-mc-msi.c25
-rw-r--r--drivers/bus/mhi/host/internal.h2
-rw-r--r--drivers/bus/ti-sysc.c6
-rw-r--r--drivers/char/Kconfig36
-rw-r--r--drivers/char/hw_random/core.c8
-rw-r--r--drivers/char/ipmi/Kconfig10
-rw-r--r--drivers/char/ipmi/Makefile1
-rw-r--r--drivers/char/ipmi/ipmi_kcs_sm.c16
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c14
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c27
-rw-r--r--drivers/char/ipmi/ipmi_ssif.c2
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c4
-rw-r--r--drivers/char/ipmi/kcs_bmc_aspeed.c24
-rw-r--r--drivers/char/ipmi/ssif_bmc.c873
-rw-r--r--drivers/char/random.c265
-rw-r--r--drivers/char/sonypi.c3
-rw-r--r--drivers/char/tpm/eventlog/acpi.c12
-rw-r--r--drivers/char/tpm/st33zp24/i2c.c142
-rw-r--r--drivers/char/tpm/st33zp24/spi.c145
-rw-r--r--drivers/char/tpm/st33zp24/st33zp24.c39
-rw-r--r--drivers/char/tpm/st33zp24/st33zp24.h7
-rw-r--r--drivers/char/tpm/tpm-chip.c7
-rw-r--r--drivers/char/tpm/tpm-dev-common.c4
-rw-r--r--drivers/char/tpm/tpm_crb.c35
-rw-r--r--drivers/char/tpm/tpm_ftpm_tee.c8
-rw-r--r--drivers/char/tpm/tpm_tis.c9
-rw-r--r--drivers/char/tpm/tpm_tis_core.c20
-rw-r--r--drivers/char/tpm/tpm_tis_core.h1
-rw-r--r--drivers/char/tpm/tpm_tis_i2c.c3
-rw-r--r--drivers/clk/bcm/clk-raspberrypi.c19
-rw-r--r--drivers/clk/clk-bulk.c6
-rw-r--r--drivers/clk/clk-cdce925.c21
-rw-r--r--drivers/clk/clk-fractional-divider.c65
-rw-r--r--drivers/clk/clk-lmk04832.c41
-rw-r--r--drivers/clk/clk-nomadik.c2
-rw-r--r--drivers/clk/clk-stm32mp1.c2
-rw-r--r--drivers/clk/clk-versaclock5.c1
-rw-r--r--drivers/clk/clk.c32
-rw-r--r--drivers/clk/imx/clk-imx6sll.c8
-rw-r--r--drivers/clk/imx/clk-imx6sx.c12
-rw-r--r--drivers/clk/imx/clk-imx6ul.c8
-rw-r--r--drivers/clk/imx/clk-imx7d.c4
-rw-r--r--drivers/clk/imx/clk-imx7ulp.c10
-rw-r--r--drivers/clk/imx/clk-imx8mm.c12
-rw-r--r--drivers/clk/imx/clk-imx8mn.c128
-rw-r--r--drivers/clk/imx/clk-imx8mp.c28
-rw-r--r--drivers/clk/imx/clk-imx8mq.c14
-rw-r--r--drivers/clk/imx/clk-imx93.c46
-rw-r--r--drivers/clk/imx/clk-imxrt1050.c5
-rw-r--r--drivers/clk/imx/clk-pll14xx.c2
-rw-r--r--drivers/clk/imx/clk.c5
-rw-r--r--drivers/clk/imx/clk.h3
-rw-r--r--drivers/clk/ingenic/Kconfig10
-rw-r--r--drivers/clk/ingenic/Makefile1
-rw-r--r--drivers/clk/ingenic/cgu.c42
-rw-r--r--drivers/clk/ingenic/cgu.h17
-rw-r--r--drivers/clk/ingenic/jz4755-cgu.c346
-rw-r--r--drivers/clk/ingenic/x1000-cgu.c119
-rw-r--r--drivers/clk/keystone/syscon-clk.c9
-rw-r--r--drivers/clk/mediatek/Kconfig8
-rw-r--r--drivers/clk/mediatek/Makefile1
-rw-r--r--drivers/clk/mediatek/clk-fhctl.c244
-rw-r--r--drivers/clk/mediatek/clk-fhctl.h26
-rw-r--r--drivers/clk/mediatek/clk-mt6795-topckgen.c76
-rw-r--r--drivers/clk/mediatek/clk-mt7986-infracfg.c2
-rw-r--r--drivers/clk/mediatek/clk-mt8173.c76
-rw-r--r--drivers/clk/mediatek/clk-mt8183.c216
-rw-r--r--drivers/clk/mediatek/clk-mt8186-apmixedsys.c66
-rw-r--r--drivers/clk/mediatek/clk-mt8186-mfg.c5
-rw-r--r--drivers/clk/mediatek/clk-mt8186-topckgen.c89
-rw-r--r--drivers/clk/mediatek/clk-mt8192.c76
-rw-r--r--drivers/clk/mediatek/clk-mt8195-topckgen.c78
-rw-r--r--drivers/clk/mediatek/clk-mtk.c2
-rw-r--r--drivers/clk/mediatek/clk-mtk.h7
-rw-r--r--drivers/clk/mediatek/clk-pll.c84
-rw-r--r--drivers/clk/mediatek/clk-pll.h55
-rw-r--r--drivers/clk/mediatek/clk-pllfh.c275
-rw-r--r--drivers/clk/mediatek/clk-pllfh.h82
-rw-r--r--drivers/clk/meson/clk-pll.c21
-rw-r--r--drivers/clk/microchip/Kconfig3
-rw-r--r--drivers/clk/microchip/clk-mpfs-ccc.c6
-rw-r--r--drivers/clk/mstar/Kconfig7
-rw-r--r--drivers/clk/mstar/Makefile1
-rw-r--r--drivers/clk/mstar/clk-msc313-cpupll.c220
-rw-r--r--drivers/clk/qcom/Kconfig26
-rw-r--r--drivers/clk/qcom/Makefile3
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.c16
-rw-r--r--drivers/clk/qcom/clk-alpha-pll.h5
-rw-r--r--drivers/clk/qcom/clk-krait.c2
-rw-r--r--drivers/clk/qcom/clk-rpm.c204
-rw-r--r--drivers/clk/qcom/clk-rpmh.c427
-rw-r--r--drivers/clk/qcom/dispcc-sc8280xp.c3218
-rw-r--r--drivers/clk/qcom/dispcc-sm6350.c4
-rw-r--r--drivers/clk/qcom/dispcc-sm6375.c610
-rw-r--r--drivers/clk/qcom/dispcc-sm8250.c38
-rw-r--r--drivers/clk/qcom/gcc-ipq4019.c11
-rw-r--r--drivers/clk/qcom/gcc-ipq806x.c4
-rw-r--r--drivers/clk/qcom/gcc-ipq8074.c1795
-rw-r--r--drivers/clk/qcom/gcc-msm8939.c35
-rw-r--r--drivers/clk/qcom/gcc-msm8974.c682
-rw-r--r--drivers/clk/qcom/gcc-sm6125.c1
-rw-r--r--drivers/clk/qcom/gcc-sm8250.c4
-rw-r--r--drivers/clk/qcom/gcc-sm8550.c3387
-rw-r--r--drivers/clk/qcom/gdsc.c3
-rw-r--r--drivers/clk/qcom/hfpll.c4
-rw-r--r--drivers/clk/qcom/kpss-xcc.c13
-rw-r--r--drivers/clk/qcom/krait-cc.c236
-rw-r--r--drivers/clk/qcom/lpassaudiocc-sc7280.c55
-rw-r--r--drivers/clk/qcom/lpasscorecc-sc7180.c34
-rw-r--r--drivers/clk/qcom/mmcc-msm8974.c736
-rw-r--r--drivers/clk/qcom/reset.c4
-rw-r--r--drivers/clk/qcom/reset.h1
-rw-r--r--drivers/clk/renesas/r8a779a0-cpg-mssr.c2
-rw-r--r--drivers/clk/renesas/r8a779f0-cpg-mssr.c28
-rw-r--r--drivers/clk/renesas/r8a779g0-cpg-mssr.c33
-rw-r--r--drivers/clk/renesas/r9a06g032-clocks.c3
-rw-r--r--drivers/clk/renesas/r9a07g043-cpg.c5
-rw-r--r--drivers/clk/renesas/r9a07g044-cpg.c10
-rw-r--r--drivers/clk/renesas/rzg2l-cpg.c49
-rw-r--r--drivers/clk/renesas/rzg2l-cpg.h4
-rw-r--r--drivers/clk/rockchip/Kconfig8
-rw-r--r--drivers/clk/rockchip/Makefile1
-rw-r--r--drivers/clk/rockchip/clk-cpu.c69
-rw-r--r--drivers/clk/rockchip/clk-pll.c219
-rw-r--r--drivers/clk/rockchip/clk-rk3588.c2533
-rw-r--r--drivers/clk/rockchip/clk.c15
-rw-r--r--drivers/clk/rockchip/clk.h95
-rw-r--r--drivers/clk/rockchip/rst-rk3588.c857
-rw-r--r--drivers/clk/rockchip/softrst.c34
-rw-r--r--drivers/clk/samsung/clk-exynos5-subcmu.c4
-rw-r--r--drivers/clk/samsung/clk-pll.c1
-rw-r--r--drivers/clk/socfpga/clk-gate-a10.c68
-rw-r--r--drivers/clk/socfpga/clk-gate.c66
-rw-r--r--drivers/clk/socfpga/clk.h1
-rw-r--r--drivers/clk/spear/spear6xx_clock.c8
-rw-r--r--drivers/clk/st/clkgen-fsyn.c5
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-v3s.h6
-rw-r--r--drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c11
-rw-r--r--drivers/clk/sunxi-ng/ccu-suniv-f1c100s.h2
-rw-r--r--drivers/clk/tegra/clk-bpmp.c37
-rw-r--r--drivers/clk/ti/apll.c4
-rw-r--r--drivers/clk/ti/clk-dra7-atl.c16
-rw-r--r--drivers/clk/ti/clk.c36
-rw-r--r--drivers/clk/ti/clkctrl.c4
-rw-r--r--drivers/clk/ti/clock.h10
-rw-r--r--drivers/clk/ti/composite.c2
-rw-r--r--drivers/clk/ti/divider.c2
-rw-r--r--drivers/clk/ti/dpll.c4
-rw-r--r--drivers/clk/ti/fixed-factor.c2
-rw-r--r--drivers/clk/ti/gate.c6
-rw-r--r--drivers/clk/ti/interface.c7
-rw-r--r--drivers/clk/ti/mux.c6
-rw-r--r--drivers/clk/visconti/pll.c1
-rw-r--r--drivers/clk/x86/Kconfig5
-rw-r--r--drivers/clk/x86/clk-cgu-pll.c23
-rw-r--r--drivers/clk/x86/clk-cgu.c106
-rw-r--r--drivers/clk/x86/clk-cgu.h46
-rw-r--r--drivers/clk/x86/clk-lgm.c18
-rw-r--r--drivers/clk/xilinx/Kconfig4
-rw-r--r--drivers/clocksource/arm_arch_timer.c15
-rw-r--r--drivers/clocksource/hyperv_timer.c61
-rw-r--r--drivers/clocksource/ingenic-ost.c10
-rw-r--r--drivers/clocksource/sh_cmt.c88
-rw-r--r--drivers/clocksource/timer-npcm7xx.c10
-rw-r--r--drivers/clocksource/timer-sp804.c6
-rw-r--r--drivers/clocksource/timer-ti-dm-systimer.c4
-rw-r--r--drivers/clocksource/timer-ti-dm.c21
-rw-r--r--drivers/cpufreq/Kconfig.arm13
-rw-r--r--drivers/cpufreq/Makefile1
-rw-r--r--drivers/cpufreq/acpi-cpufreq.c43
-rw-r--r--drivers/cpufreq/amd-pstate-ut.c2
-rw-r--r--drivers/cpufreq/amd_freq_sensitivity.c2
-rw-r--r--drivers/cpufreq/apple-soc-cpufreq.c352
-rw-r--r--drivers/cpufreq/cpufreq-dt-platdev.c3
-rw-r--r--drivers/cpufreq/cpufreq.c2
-rw-r--r--drivers/cpufreq/cpufreq_stats.c16
-rw-r--r--drivers/cpufreq/intel_pstate.c10
-rw-r--r--drivers/cpufreq/longhaul.c4
-rw-r--r--drivers/cpufreq/mediatek-cpufreq-hw.c14
-rw-r--r--drivers/cpufreq/qcom-cpufreq-hw.c206
-rw-r--r--drivers/cpufreq/spear-cpufreq.c2
-rw-r--r--drivers/cpufreq/tegra186-cpufreq.c11
-rw-r--r--drivers/cpufreq/ti-cpufreq.c36
-rw-r--r--drivers/cpuidle/cpuidle-psci-domain.c3
-rw-r--r--drivers/cpuidle/dt_idle_states.c11
-rw-r--r--drivers/cxl/Kconfig18
-rw-r--r--drivers/cxl/Makefile2
-rw-r--r--drivers/cxl/acpi.c275
-rw-r--r--drivers/cxl/core/core.h8
-rw-r--r--drivers/cxl/core/hdm.c45
-rw-r--r--drivers/cxl/core/mbox.c102
-rw-r--r--drivers/cxl/core/memdev.c1
-rw-r--r--drivers/cxl/core/pci.c5
-rw-r--r--drivers/cxl/core/pmem.c109
-rw-r--r--drivers/cxl/core/port.c216
-rw-r--r--drivers/cxl/core/region.c112
-rw-r--r--drivers/cxl/core/regs.c242
-rw-r--r--drivers/cxl/cxl.h140
-rw-r--r--drivers/cxl/cxlmem.h64
-rw-r--r--drivers/cxl/cxlpci.h9
-rw-r--r--drivers/cxl/mem.c74
-rw-r--r--drivers/cxl/pci.c228
-rw-r--r--drivers/cxl/pmem.c407
-rw-r--r--drivers/cxl/security.c202
-rw-r--r--drivers/devfreq/devfreq-event.c2
-rw-r--r--drivers/devfreq/devfreq.c8
-rw-r--r--drivers/devfreq/event/exynos-nocp.c3
-rw-r--r--drivers/devfreq/governor_userspace.c12
-rw-r--r--drivers/dma-buf/dma-buf.c225
-rw-r--r--drivers/dma-buf/heaps/cma_heap.c3
-rw-r--r--drivers/dma-buf/heaps/system_heap.c3
-rw-r--r--drivers/dma-buf/st-dma-fence-chain.c6
-rw-r--r--drivers/dma-buf/udmabuf.c3
-rw-r--r--drivers/dma/Kconfig2
-rw-r--r--drivers/dma/qcom/hidma.c8
-rw-r--r--drivers/edac/Kconfig5
-rw-r--r--drivers/edac/amd64_edac.c3
-rw-r--r--drivers/edac/armada_xp_edac.c3
-rw-r--r--drivers/edac/edac_mc_sysfs.c24
-rw-r--r--drivers/edac/edac_module.h1
-rw-r--r--drivers/edac/ghes_edac.c90
-rw-r--r--drivers/edac/i10nm_base.c6
-rw-r--r--drivers/edac/i5400_edac.c3
-rw-r--r--drivers/edac/igen6_edac.c5
-rw-r--r--drivers/edac/layerscape_edac.c3
-rw-r--r--drivers/edac/pnd2_edac.c3
-rw-r--r--drivers/edac/sb_edac.c3
-rw-r--r--drivers/edac/skx_base.c3
-rw-r--r--drivers/edac/thunderx_edac.c3
-rw-r--r--drivers/edac/xgene_edac.c3
-rw-r--r--drivers/firmware/arm_ffa/driver.c101
-rw-r--r--drivers/firmware/broadcom/bcm47xx_nvram.c18
-rw-r--r--drivers/firmware/cirrus/Kconfig2
-rw-r--r--drivers/firmware/cirrus/Makefile2
-rw-r--r--drivers/firmware/cirrus/cs_dsp.c79
-rw-r--r--drivers/firmware/efi/Kconfig45
-rw-r--r--drivers/firmware/efi/Makefile7
-rw-r--r--drivers/firmware/efi/arm-runtime.c4
-rw-r--r--drivers/firmware/efi/cper.c12
-rw-r--r--drivers/firmware/efi/cper_cxl.c179
-rw-r--r--drivers/firmware/efi/cper_cxl.h66
-rw-r--r--drivers/firmware/efi/earlycon.c8
-rw-r--r--drivers/firmware/efi/efi-init.c21
-rw-r--r--drivers/firmware/efi/efi-pstore.c25
-rw-r--r--drivers/firmware/efi/efi.c33
-rw-r--r--drivers/firmware/efi/fake_mem.h10
-rw-r--r--drivers/firmware/efi/fdtparams.c4
-rw-r--r--drivers/firmware/efi/libstub/Makefile35
-rw-r--r--drivers/firmware/efi/libstub/Makefile.zboot22
-rw-r--r--drivers/firmware/efi/libstub/alignedmem.c7
-rw-r--r--drivers/firmware/efi/libstub/arm32-stub.c37
-rw-r--r--drivers/firmware/efi/libstub/arm64-entry.S67
-rw-r--r--drivers/firmware/efi/libstub/arm64-stub.c75
-rw-r--r--drivers/firmware/efi/libstub/arm64.c76
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-entry.c65
-rw-r--r--drivers/firmware/efi/libstub/efi-stub-helper.c150
-rw-r--r--drivers/firmware/efi/libstub/efi-stub.c140
-rw-r--r--drivers/firmware/efi/libstub/efistub.h143
-rw-r--r--drivers/firmware/efi/libstub/file.c122
-rw-r--r--drivers/firmware/efi/libstub/intrinsics.c18
-rw-r--r--drivers/firmware/efi/libstub/loongarch-stub.c89
-rw-r--r--drivers/firmware/efi/libstub/loongarch.c80
-rw-r--r--drivers/firmware/efi/libstub/mem.c5
-rw-r--r--drivers/firmware/efi/libstub/printk.c154
-rw-r--r--drivers/firmware/efi/libstub/random.c96
-rw-r--r--drivers/firmware/efi/libstub/randomalloc.c7
-rw-r--r--drivers/firmware/efi/libstub/riscv-stub.c96
-rw-r--r--drivers/firmware/efi/libstub/riscv.c98
-rw-r--r--drivers/firmware/efi/libstub/screen_info.c56
-rw-r--r--drivers/firmware/efi/libstub/string.c95
-rw-r--r--drivers/firmware/efi/libstub/x86-stub.c2
-rw-r--r--drivers/firmware/efi/libstub/zboot-header.S5
-rw-r--r--drivers/firmware/efi/libstub/zboot.c307
-rw-r--r--drivers/firmware/efi/memmap.c243
-rw-r--r--drivers/firmware/efi/runtime-wrappers.c1
-rw-r--r--drivers/firmware/efi/x86_fake_mem.c75
-rw-r--r--drivers/firmware/imx/scu-pd.c1
-rw-r--r--drivers/firmware/raspberrypi.c47
-rw-r--r--drivers/firmware/tegra/Kconfig1
-rw-r--r--drivers/firmware/tegra/bpmp-debugfs.c62
-rw-r--r--drivers/firmware/tegra/bpmp-tegra186.c36
-rw-r--r--drivers/firmware/tegra/bpmp-tegra210.c15
-rw-r--r--drivers/firmware/tegra/bpmp.c33
-rw-r--r--drivers/firmware/tegra/ivc.c150
-rw-r--r--drivers/firmware/ti_sci.c24
-rw-r--r--drivers/firmware/xilinx/zynqmp.c7
-rw-r--r--drivers/fsi/fsi-sbefifo.c6
-rw-r--r--drivers/gpio/gpio-arizona.c5
-rw-r--r--drivers/gpio/gpio-aspeed.c5
-rw-r--r--drivers/gpio/gpio-da9052.c9
-rw-r--r--drivers/gpio/gpio-mockup.c1
-rw-r--r--drivers/gpio/gpio-mxc.c92
-rw-r--r--drivers/gpio/gpio-pca953x.c3
-rw-r--r--drivers/gpio/gpio-pl061.c15
-rw-r--r--drivers/gpio/gpio-tegra186.c3
-rw-r--r--drivers/gpio/gpio-wm8350.c7
-rw-r--r--drivers/gpio/gpiolib-acpi.h12
-rw-r--r--drivers/gpio/gpiolib-cdev.c4
-rw-r--r--drivers/gpio/gpiolib-of.h11
-rw-r--r--drivers/gpio/gpiolib-sysfs.h2
-rw-r--r--drivers/gpu/drm/Kconfig63
-rw-r--r--drivers/gpu/drm/Makefile113
-rw-r--r--drivers/gpu/drm/amd/amdgpu/Kconfig29
-rw-r--r--drivers/gpu/drm/amd/amdgpu/Makefile5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c78
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c110
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c43
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c197
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c39
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_display.c42
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_display.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c21
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c54
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c215
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c21
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c (renamed from drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c)101
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.h (renamed from drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h)15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c56
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c58
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_job.c80
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_job.h17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c24
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_object.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c120
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c217
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.h5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c43
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c72
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c514
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.h103
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_securedisplay.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c56
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c149
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c87
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c39
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c58
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c43
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c71
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/atombios_encoders.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v10_0.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v11_0.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v6_0.c16
-rw-r--r--drivers/gpu/drm/amd/amdgpu/dce_v8_0.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c66
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c330
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c15
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c19
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c79
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c81
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.h7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mes_v10_1.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mes_v11_0.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nv.c28
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v10_0.c27
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v11_0.c27
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v11_0_8.c27
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v12_0.c31
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v13_0.c30
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c27
-rw-r--r--drivers/gpu/drm/amd/amdgpu/psp_v3_1.c27
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c24
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/si_dma.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc15.c24
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc15d.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/soc21.c57
-rw-r--r--drivers/gpu/drm/amd/amdgpu/umc_v6_7.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/umc_v6_7.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/umc_v8_10.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/umc_v8_10.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c42
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c94
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0.h6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vega20_ih.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vi.c6
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_crat.c377
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_crat.h36
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device.c23
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_iommu.c29
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_migrate.c26
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_pm4_headers_diq.h291
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_priv.h4
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process.c12
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_svm.c27
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_topology.c371
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_topology.h6
-rw-r--r--drivers/gpu/drm/amd/display/Kconfig3
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c382
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h24
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.c157
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crc.h12
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c3
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c80
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c2
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c53
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h2
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c11
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c4
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h64
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/bios_parser.c50
-rw-r--r--drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_smu11_driver_if.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_smu.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn314/dcn314_smu.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn315/dcn315_clk_mgr.c71
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn316/dcn316_clk_mgr.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_clk_mgr.c39
-rw-r--r--drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_smu13_driver_if.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c688
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link.c12
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c233
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_link_dpia.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_resource.c256
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_stream.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h106
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c185
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_link.h37
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_stream.h36
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_trace.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_types.h7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c11
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c81
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c46
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c44
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb.h363
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c127
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mmhubbub.h7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c27
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.h15
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mmhubbub.h7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c21
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c21
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c20
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c9
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c46
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.c29
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.h5
-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.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c10
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c19
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c14
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c22
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c61
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c8
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c112
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h17
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource_helpers.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/dm_helpers.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/Makefile20
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dc_features.h7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c36
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn20/dcn20_fpu.c22
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn30/dcn30_fpu.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c26
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn31/display_mode_vba_31.c59
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c16
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn314/display_mode_vba_314.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.c157
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/dcn32_fpu.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_32.c40
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.c69
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h18
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/display_mode_enums.h25
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h13
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml/dsc/qp_tables.h36
-rw-r--r--drivers/gpu/drm/amd/display/dc/gpio/dcn32/hw_factory_dcn32.c4
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/core_types.h66
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h16
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h16
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h9
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h7
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/link_hwss.h5
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn201/irq_service_dcn201.c17
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/dcn201/irq_service_dcn201.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/irq/irq_service.c17
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_dp_dpia_bw.c28
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_dp_dpia_bw.h69
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c52
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h4
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c25
-rw-r--r--drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h55
-rw-r--r--drivers/gpu/drm/amd/display/modules/color/color_gamma.c2
-rw-r--r--drivers/gpu/drm/amd/display/modules/freesync/freesync.c8
-rw-r--r--drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h3
-rw-r--r--drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c6
-rw-r--r--drivers/gpu/drm/amd/display/modules/power/power_helpers.c9
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_offset.h1
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h1
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_2_5_offset.h3
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_2_5_sh_mask.h27
-rw-r--r--drivers/gpu/drm/amd/include/atombios.h34
-rw-r--r--drivers/gpu/drm/amd/include/atomfirmware.h63
-rw-r--r--drivers/gpu/drm/amd/include/ivsrcid/vcn/irqsrcs_vcn_4_0.h3
-rw-r--r--drivers/gpu/drm/amd/include/kgd_pp_interface.h3
-rw-r--r--drivers/gpu/drm/amd/include/mes_v11_api_def.h6
-rw-r--r--drivers/gpu/drm/amd/include/yellow_carp_offset.h1
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c5
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c2
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c3
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c6
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h5
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_0_ppsmc.h8
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h4
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/smu_v11_0.c28
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c34
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c92
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c17
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c1
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c18
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h3
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_drv.c2
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_kms.c2
-rw-r--r--drivers/gpu/drm/arm/hdlcd_crtc.c25
-rw-r--r--drivers/gpu/drm/arm/hdlcd_drv.c43
-rw-r--r--drivers/gpu/drm/arm/hdlcd_drv.h2
-rw-r--r--drivers/gpu/drm/arm/malidp_crtc.c7
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.c71
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.h2
-rw-r--r--drivers/gpu/drm/arm/malidp_hw.c10
-rw-r--r--drivers/gpu/drm/arm/malidp_mw.c6
-rw-r--r--drivers/gpu/drm/arm/malidp_planes.c32
-rw-r--r--drivers/gpu/drm/armada/armada_fbdev.c6
-rw-r--r--drivers/gpu/drm/armada/armada_gem.c8
-rw-r--r--drivers/gpu/drm/aspeed/aspeed_gfx_drv.c2
-rw-r--r--drivers/gpu/drm/ast/Kconfig4
-rw-r--r--drivers/gpu/drm/ast/ast_drv.c5
-rw-r--r--drivers/gpu/drm/ast/ast_drv.h35
-rw-r--r--drivers/gpu/drm/ast/ast_main.c5
-rw-r--r--drivers/gpu/drm/ast/ast_mm.c14
-rw-r--r--drivers/gpu/drm/ast/ast_mode.c499
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c2
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511.h3
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511_drv.c24
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7533.c45
-rw-r--r--drivers/gpu/drm/bridge/ite-it6505.c164
-rw-r--r--drivers/gpu/drm/bridge/parade-ps8640.c9
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi.c6
-rw-r--r--drivers/gpu/drm/bridge/tc358762.c2
-rw-r--r--drivers/gpu/drm/bridge/tc358775.c2
-rw-r--r--drivers/gpu/drm/bridge/ti-sn65dsi86.c4
-rw-r--r--drivers/gpu/drm/display/Makefile14
-rw-r--r--drivers/gpu/drm/drm_atomic_helper.c94
-rw-r--r--drivers/gpu/drm/drm_atomic_state_helper.c6
-rw-r--r--drivers/gpu/drm/drm_atomic_uapi.c4
-rw-r--r--drivers/gpu/drm/drm_client.c10
-rw-r--r--drivers/gpu/drm/drm_client_modeset.c4
-rw-r--r--drivers/gpu/drm/drm_connector.c4
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c27
-rw-r--r--drivers/gpu/drm/drm_crtc_internal.h15
-rw-r--r--drivers/gpu/drm/drm_debugfs.c8
-rw-r--r--drivers/gpu/drm/drm_drv.c101
-rw-r--r--drivers/gpu/drm/drm_edid.c704
-rw-r--r--drivers/gpu/drm/drm_edid_load.c112
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c1014
-rw-r--r--drivers/gpu/drm/drm_fbdev_generic.c494
-rw-r--r--drivers/gpu/drm/drm_file.c2
-rw-r--r--drivers/gpu/drm/drm_format_helper.c10
-rw-r--r--drivers/gpu/drm/drm_fourcc.c8
-rw-r--r--drivers/gpu/drm/drm_gem.c24
-rw-r--r--drivers/gpu/drm/drm_gem_atomic_helper.c66
-rw-r--r--drivers/gpu/drm/drm_gem_dma_helper.c6
-rw-r--r--drivers/gpu/drm/drm_gem_framebuffer_helper.c7
-rw-r--r--drivers/gpu/drm/drm_gem_shmem_helper.c18
-rw-r--r--drivers/gpu/drm/drm_gem_ttm_helper.c9
-rw-r--r--drivers/gpu/drm/drm_gem_vram_helper.c18
-rw-r--r--drivers/gpu/drm/drm_mipi_dsi.c2
-rw-r--r--drivers/gpu/drm/drm_modes.c116
-rw-r--r--drivers/gpu/drm/drm_plane_helper.c4
-rw-r--r--drivers/gpu/drm/drm_prime.c8
-rw-r--r--drivers/gpu/drm/drm_probe_helper.c3
-rw-r--r--drivers/gpu/drm/drm_rect.c2
-rw-r--r--drivers/gpu/drm/drm_simple_kms_helper.c32
-rw-r--r--drivers/gpu/drm/drm_sysfs.c24
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_drv.h3
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_dump.c7
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gem.c19
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gem.h1
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c2
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c6
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.c58
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.h23
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_hwdb.c31
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_mmu.c27
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_mmu.h1
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_sched.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fbdev.c6
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c2
-rw-r--r--drivers/gpu/drm/gma500/framebuffer.c12
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.h1
-rw-r--r--drivers/gpu/drm/gud/gud_connector.c2
-rw-r--r--drivers/gpu/drm/gud/gud_drv.c2
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c17
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h4
-rw-r--r--drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c2
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c2
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c2
-rw-r--r--drivers/gpu/drm/hyperv/hyperv_drm_drv.c2
-rw-r--r--drivers/gpu/drm/hyperv/hyperv_drm_modeset.c1
-rw-r--r--drivers/gpu/drm/i2c/tda998x_drv.c2
-rw-r--r--drivers/gpu/drm/i915/Kconfig.profile26
-rw-r--r--drivers/gpu/drm/i915/Makefile20
-rw-r--r--drivers/gpu/drm/i915/display/g4x_dp.c1
-rw-r--r--drivers/gpu/drm/i915/display/g4x_dp.h2
-rw-r--r--drivers/gpu/drm/i915/display/g4x_hdmi.c19
-rw-r--r--drivers/gpu/drm/i915/display/hsw_ips.c8
-rw-r--r--drivers/gpu/drm/i915/display/i9xx_plane.c4
-rw-r--r--drivers/gpu/drm/i915/display/icl_dsi.c22
-rw-r--r--drivers/gpu/drm/i915/display/icl_dsi_regs.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_atomic.c8
-rw-r--r--drivers/gpu/drm/i915/display/intel_atomic_plane.c64
-rw-r--r--drivers/gpu/drm/i915/display/intel_audio.c682
-rw-r--r--drivers/gpu/drm/i915/display/intel_audio_regs.h89
-rw-r--r--drivers/gpu/drm/i915/display/intel_backlight.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_backlight_regs.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_bios.c12
-rw-r--r--drivers/gpu/drm/i915/display/intel_bw.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_cdclk.c92
-rw-r--r--drivers/gpu/drm/i915/display/intel_color.c946
-rw-r--r--drivers/gpu/drm/i915/display/intel_color.h6
-rw-r--r--drivers/gpu/drm/i915/display/intel_combo_phy.c19
-rw-r--r--drivers/gpu/drm/i915/display/intel_connector.c18
-rw-r--r--drivers/gpu/drm/i915/display/intel_connector.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_crt.c11
-rw-r--r--drivers/gpu/drm/i915/display/intel_crtc.c8
-rw-r--r--drivers/gpu/drm/i915/display/intel_crtc_state_dump.c12
-rw-r--r--drivers/gpu/drm/i915/display/intel_cursor.c9
-rw-r--r--drivers/gpu/drm/i915/display/intel_ddi.c137
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.c187
-rw-r--r--drivers/gpu/drm/i915/display/intel_display.h46
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_core.h26
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_debugfs.c311
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power.c37
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power.h15
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power_map.c69
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power_well.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_power_well.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_reg_defs.h53
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_trace.h206
-rw-r--r--drivers/gpu/drm/i915/display/intel_display_types.h82
-rw-r--r--drivers/gpu/drm/i915/display/intel_dkl_phy.c33
-rw-r--r--drivers/gpu/drm/i915/display/intel_dkl_phy.h10
-rw-r--r--drivers/gpu/drm/i915/display/intel_dkl_phy_regs.h204
-rw-r--r--drivers/gpu/drm/i915/display/intel_dmc.c26
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp.c111
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_aux.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_hdcp.c21
-rw-r--r--drivers/gpu/drm/i915/display/intel_dp_mst.c47
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpio_phy.c43
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpio_phy.h19
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll_mgr.c126
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpll_mgr.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_dpt.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_drrs.c113
-rw-r--r--drivers/gpu/drm/i915/display/intel_drrs.h4
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsb.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsi_vbt.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_dvo.c7
-rw-r--r--drivers/gpu/drm/i915/display/intel_dvo_dev.h8
-rw-r--r--drivers/gpu/drm/i915/display/intel_fb.c13
-rw-r--r--drivers/gpu/drm/i915/display/intel_fb.h1
-rw-r--r--drivers/gpu/drm/i915/display/intel_fb_pin.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_fbc.c35
-rw-r--r--drivers/gpu/drm/i915/display/intel_fbdev.c14
-rw-r--r--drivers/gpu/drm/i915/display/intel_fdi.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_fifo_underrun.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_frontbuffer.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_global_state.c4
-rw-r--r--drivers/gpu/drm/i915/display/intel_global_state.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_gmbus.c22
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp_regs.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdmi.c58
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdmi.h8
-rw-r--r--drivers/gpu/drm/i915/display/intel_hotplug.c216
-rw-r--r--drivers/gpu/drm/i915/display/intel_hotplug.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_hti.c38
-rw-r--r--drivers/gpu/drm/i915/display/intel_hti.h18
-rw-r--r--drivers/gpu/drm/i915/display/intel_hti_regs.h16
-rw-r--r--drivers/gpu/drm/i915/display/intel_lpe_audio.c11
-rw-r--r--drivers/gpu/drm/i915/display/intel_lspcon.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_lvds.c48
-rw-r--r--drivers/gpu/drm/i915/display/intel_mg_phy_regs.h (renamed from drivers/gpu/drm/i915/display/intel_tc_phy_regs.h)8
-rw-r--r--drivers/gpu/drm/i915/display/intel_modeset_setup.c23
-rw-r--r--drivers/gpu/drm/i915/display/intel_modeset_verify.c3
-rw-r--r--drivers/gpu/drm/i915/display/intel_opregion.c7
-rw-r--r--drivers/gpu/drm/i915/display/intel_panel.c31
-rw-r--r--drivers/gpu/drm/i915/display/intel_pch_display.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_pch_refclk.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_pipe_crc.c12
-rw-r--r--drivers/gpu/drm/i915/display/intel_pps.c10
-rw-r--r--drivers/gpu/drm/i915/display/intel_psr.c52
-rw-r--r--drivers/gpu/drm/i915/display/intel_sdvo.c173
-rw-r--r--drivers/gpu/drm/i915/display/intel_snps_phy.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_snps_phy_regs.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_sprite.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_sprite.h9
-rw-r--r--drivers/gpu/drm/i915/display/intel_tc.c78
-rw-r--r--drivers/gpu/drm/i915/display/intel_tc.h3
-rw-r--r--drivers/gpu/drm/i915/display/intel_tv.c89
-rw-r--r--drivers/gpu/drm/i915/display/intel_vdsc.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_vga.c1
-rw-r--r--drivers/gpu/drm/i915/display/intel_vrr.c1
-rw-r--r--drivers/gpu/drm/i915/display/skl_scaler.c2
-rw-r--r--drivers/gpu/drm/i915/display/skl_universal_plane.c7
-rw-r--r--drivers/gpu/drm/i915/display/skl_universal_plane.h1
-rw-r--r--drivers/gpu/drm/i915/display/skl_watermark.c26
-rw-r--r--drivers/gpu/drm/i915/display/vlv_dsi.c23
-rw-r--r--drivers/gpu/drm/i915/display/vlv_dsi_regs.h2
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_clflush.c2
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_context.c5
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c55
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c51
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_internal.c5
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_mman.c23
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_object.c26
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_object.h7
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_pages.c19
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_phys.c9
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_pm.c35
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_shmem.c2
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_stolen.c263
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_ttm.c121
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_ttm.h18
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c2
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_userptr.c7
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c2
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/huge_pages.c167
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c22
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c4
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c134
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c95
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c12
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/igt_gem_utils.c8
-rw-r--r--drivers/gpu/drm/i915/gem/selftests/igt_gem_utils.h14
-rw-r--r--drivers/gpu/drm/i915/gt/gen8_engine_cs.c55
-rw-r--r--drivers/gpu/drm/i915/gt/gen8_engine_cs.h12
-rw-r--r--drivers/gpu/drm/i915/gt/gen8_ppgtt.c92
-rw-r--r--drivers/gpu/drm/i915/gt/intel_context.h8
-rw-r--r--drivers/gpu/drm/i915/gt/intel_context_types.h9
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine.h6
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_cs.c124
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c39
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_regs.h1
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_types.h1
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_user.c28
-rw-r--r--drivers/gpu/drm/i915/gt/intel_execlists_submission.c20
-rw-r--r--drivers/gpu/drm/i915/gt/intel_ggtt.c20
-rw-r--r--drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c4
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gpu_commands.h4
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gsc.c23
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt.c159
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt.h1
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c38
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_irq.c104
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_mcr.c307
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_mcr.h24
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_pm.c28
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c284
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_regs.h210
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_sysfs.c15
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_sysfs.h7
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c477
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gt_types.h25
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gtt.c44
-rw-r--r--drivers/gpu/drm/i915/gt/intel_gtt.h3
-rw-r--r--drivers/gpu/drm/i915/gt/intel_lrc.c143
-rw-r--r--drivers/gpu/drm/i915/gt/intel_lrc.h2
-rw-r--r--drivers/gpu/drm/i915/gt/intel_migrate.c1
-rw-r--r--drivers/gpu/drm/i915/gt/intel_mocs.c12
-rw-r--r--drivers/gpu/drm/i915/gt/intel_rc6.c64
-rw-r--r--drivers/gpu/drm/i915/gt/intel_rc6.h11
-rw-r--r--drivers/gpu/drm/i915/gt/intel_rc6_types.h15
-rw-r--r--drivers/gpu/drm/i915/gt/intel_renderstate.c4
-rw-r--r--drivers/gpu/drm/i915/gt/intel_reset.c20
-rw-r--r--drivers/gpu/drm/i915/gt/intel_reset.h1
-rw-r--r--drivers/gpu/drm/i915/gt/intel_ring_submission.c2
-rw-r--r--drivers/gpu/drm/i915/gt/intel_rps.c318
-rw-r--r--drivers/gpu/drm/i915/gt/intel_rps.h5
-rw-r--r--drivers/gpu/drm/i915/gt/intel_sseu.c4
-rw-r--r--drivers/gpu/drm/i915/gt/intel_wopcm.c (renamed from drivers/gpu/drm/i915/intel_wopcm.c)43
-rw-r--r--drivers/gpu/drm/i915/gt/intel_wopcm.h (renamed from drivers/gpu/drm/i915/intel_wopcm.h)0
-rw-r--r--drivers/gpu/drm/i915/gt/intel_workarounds.c713
-rw-r--r--drivers/gpu/drm/i915/gt/intel_workarounds_types.h12
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_engine_cs.c22
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_engine_pm.c2
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_execlists.c64
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_gt_pm.c36
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_hangcheck.c86
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_lrc.c33
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_migrate.c1
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_mocs.c5
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_rc6.c6
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_rps.c20
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_slpc.c260
-rw-r--r--drivers/gpu/drm/i915/gt/selftest_workarounds.c28
-rw-r--r--drivers/gpu/drm/i915/gt/sysfs_engines.c25
-rw-r--r--drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h1
-rw-r--r--drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h9
-rw-r--r--drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h9
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc.c48
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc.h21
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c82
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c132
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c61
-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.h50
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_log.c6
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c13
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h2
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c103
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h4
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_slpc_types.h3
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c348
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_huc.c316
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_huc.h31
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c34
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_huc_fw.h1
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_uc.c13
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c70
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h14
-rw-r--r--drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c8
-rw-r--r--drivers/gpu/drm/i915/gvt/cfg_space.c6
-rw-r--r--drivers/gpu/drm/i915/gvt/cmd_parser.c1
-rw-r--r--drivers/gpu/drm/i915/gvt/display.c2
-rw-r--r--drivers/gpu/drm/i915/gvt/dmabuf.c2
-rw-r--r--drivers/gpu/drm/i915/gvt/dmabuf.h2
-rw-r--r--drivers/gpu/drm/i915/gvt/firmware.c2
-rw-r--r--drivers/gpu/drm/i915/gvt/gtt.c7
-rw-r--r--drivers/gpu/drm/i915/gvt/gvt.h2
-rw-r--r--drivers/gpu/drm/i915/gvt/handlers.c5
-rw-r--r--drivers/gpu/drm/i915/gvt/kvmgt.c4
-rw-r--r--drivers/gpu/drm/i915/gvt/mmio.c1
-rw-r--r--drivers/gpu/drm/i915/gvt/mmio_context.c15
-rw-r--r--drivers/gpu/drm/i915/gvt/page_track.c2
-rw-r--r--drivers/gpu/drm/i915/gvt/scheduler.c5
-rw-r--r--drivers/gpu/drm/i915/gvt/vgpu.c6
-rw-r--r--drivers/gpu/drm/i915/i915_debugfs.c4
-rw-r--r--drivers/gpu/drm/i915/i915_driver.c34
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h67
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c57
-rw-r--r--drivers/gpu/drm/i915/i915_getparam.c5
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c13
-rw-r--r--drivers/gpu/drm/i915/i915_hwmon.c732
-rw-r--r--drivers/gpu/drm/i915/i915_hwmon.h20
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c293
-rw-r--r--drivers/gpu/drm/i915/i915_irq.h9
-rw-r--r--drivers/gpu/drm/i915/i915_pci.c13
-rw-r--r--drivers/gpu/drm/i915/i915_perf.c601
-rw-r--r--drivers/gpu/drm/i915/i915_perf.h2
-rw-r--r--drivers/gpu/drm/i915/i915_perf_oa_regs.h6
-rw-r--r--drivers/gpu/drm/i915/i915_perf_types.h47
-rw-r--r--drivers/gpu/drm/i915/i915_pmu.c9
-rw-r--r--drivers/gpu/drm/i915/i915_query.c12
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h354
-rw-r--r--drivers/gpu/drm/i915/i915_reg_defs.h57
-rw-r--r--drivers/gpu/drm/i915/i915_request.c24
-rw-r--r--drivers/gpu/drm/i915/i915_request.h5
-rw-r--r--drivers/gpu/drm/i915/i915_scatterlist.c4
-rw-r--r--drivers/gpu/drm/i915/i915_selftest.h2
-rw-r--r--drivers/gpu/drm/i915/i915_sw_fence.c1
-rw-r--r--drivers/gpu/drm/i915/i915_sw_fence.h1
-rw-r--r--drivers/gpu/drm/i915/i915_sysfs.c3
-rw-r--r--drivers/gpu/drm/i915/i915_trace.h16
-rw-r--r--drivers/gpu/drm/i915/i915_ttm_buddy_manager.c12
-rw-r--r--drivers/gpu/drm/i915/i915_vma.c30
-rw-r--r--drivers/gpu/drm/i915/i915_vma.h1
-rw-r--r--drivers/gpu/drm/i915/intel_device_info.c85
-rw-r--r--drivers/gpu/drm/i915/intel_device_info.h20
-rw-r--r--drivers/gpu/drm/i915/intel_gvt_mmio_table.c3
-rw-r--r--drivers/gpu/drm/i915/intel_mchbar_regs.h21
-rw-r--r--drivers/gpu/drm/i915/intel_memory_region.c4
-rw-r--r--drivers/gpu/drm/i915/intel_pci_config.h28
-rw-r--r--drivers/gpu/drm/i915/intel_pm.c472
-rw-r--r--drivers/gpu/drm/i915/intel_region_ttm.c2
-rw-r--r--drivers/gpu/drm/i915/intel_runtime_pm.c5
-rw-r--r--drivers/gpu/drm/i915/intel_runtime_pm.h22
-rw-r--r--drivers/gpu/drm/i915/intel_step.c32
-rw-r--r--drivers/gpu/drm/i915/intel_step.h28
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.c302
-rw-r--r--drivers/gpu/drm/i915/intel_uncore.h54
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp.c32
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp.h32
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_42.h28
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_43.h26
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_cmn.h35
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_huc.c70
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_huc.h13
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_irq.h8
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_session.c9
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_session.h11
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_tee.c154
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_tee.h5
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_tee_interface.h36
-rw-r--r--drivers/gpu/drm/i915/pxp/intel_pxp_types.h6
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_gem_gtt.c15
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_perf.c16
-rw-r--r--drivers/gpu/drm/i915/selftests/i915_request.c266
-rw-r--r--drivers/gpu/drm/i915/selftests/igt_spinner.c20
-rw-r--r--drivers/gpu/drm/i915/selftests/intel_uncore.c4
-rw-r--r--drivers/gpu/drm/i915/selftests/mock_gem_device.c1
-rw-r--r--drivers/gpu/drm/i915/selftests/mock_region.c2
-rw-r--r--drivers/gpu/drm/i915/vlv_sideband.c2
-rw-r--r--drivers/gpu/drm/i915/vlv_suspend.c28
-rw-r--r--drivers/gpu/drm/imx/dcss/dcss-kms.c3
-rw-r--r--drivers/gpu/drm/imx/imx-drm-core.c2
-rw-r--r--drivers/gpu/drm/imx/imx-ldb.c2
-rw-r--r--drivers/gpu/drm/imx/imx-tve.c1
-rw-r--r--drivers/gpu/drm/imx/parallel-display.c2
-rw-r--r--drivers/gpu/drm/ingenic/ingenic-drm-drv.c9
-rw-r--r--drivers/gpu/drm/kmb/kmb_drv.c2
-rw-r--r--drivers/gpu/drm/kmb/kmb_plane.c1
-rw-r--r--drivers/gpu/drm/lima/lima_sched.c4
-rw-r--r--drivers/gpu/drm/logicvc/logicvc_drm.c2
-rw-r--r--drivers/gpu/drm/logicvc/logicvc_mode.c2
-rw-r--r--drivers/gpu/drm/mcde/mcde_drv.c3
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_ovl.c57
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dpi.c29
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.c10
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_plane.c74
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_plane.h8
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi.c9
-rw-r--r--drivers/gpu/drm/meson/meson_drv.c2
-rw-r--r--drivers/gpu/drm/meson/meson_encoder_cvbs.c7
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.c1
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.h1
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_g200se.c3
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c11
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx_gpu.c2
-rw-r--r--drivers/gpu/drm/msm/adreno/a4xx_gpu.c5
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_gpu.c29
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_preempt.c4
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gmu.c12
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu.c117
-rw-r--r--drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c3
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c29
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h9
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c7
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c24
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c104
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h1
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c11
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c19
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c2
-rw-r--r--drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c19
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c27
-rw-r--r--drivers/gpu/drm/msm/dp/dp_display.c14
-rw-r--r--drivers/gpu/drm/msm/dp/dp_link.c21
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.c7
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c121
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.c2
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy.h1
-rw-r--r--drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c17
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.c352
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.h3
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c29
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h8
-rw-r--r--drivers/gpu/drm/msm/msm_fbdev.c6
-rw-r--r--drivers/gpu/drm/msm/msm_gem_shrinker.c2
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c3
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c31
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h22
-rw-r--r--drivers/gpu/drm/msm/msm_iommu.c20
-rw-r--r--drivers/gpu/drm/msm/msm_mdss.c85
-rw-r--r--drivers/gpu/drm/msm/msm_mmu.h3
-rw-r--r--drivers/gpu/drm/msm/msm_ringbuffer.h28
-rw-r--r--drivers/gpu/drm/mxsfb/lcdif_drv.c2
-rw-r--r--drivers/gpu/drm/mxsfb/lcdif_kms.c269
-rw-r--r--drivers/gpu/drm/mxsfb/lcdif_regs.h42
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_drv.c2
-rw-r--r--drivers/gpu/drm/nouveau/Kbuild4
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/crtc.c43
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/disp.c15
-rw-r--r--drivers/gpu/drm/nouveau/dispnv04/disp.h7
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/crc.c2
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/disp.c406
-rw-r--r--drivers/gpu/drm/nouveau/dispnv50/head.c25
-rw-r--r--drivers/gpu/drm/nouveau/include/nvfw/acr.h85
-rw-r--r--drivers/gpu/drm/nouveau/include/nvfw/hs.h28
-rw-r--r--drivers/gpu/drm/nouveau/include/nvfw/ls.h51
-rw-r--r--drivers/gpu/drm/nouveau/include/nvfw/sec2.h45
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl0046.h23
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl006b.h12
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl0080.h4
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl506e.h13
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl506f.h14
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl5070.h92
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl826e.h15
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl826f.h16
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cl906f.h16
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/cla06f.h18
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/class.h45
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/clb069.h5
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/clc36f.h19
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/conn.h10
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/disp.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/event.h91
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/head.h23
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if0004.h5
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if000e.h26
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if0010.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if0011.h11
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if0012.h98
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if0013.h35
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if0020.h45
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/if0021.h16
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/ioctl.h51
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/notify.h35
-rw-r--r--drivers/gpu/drm/nouveau/include/nvif/outp.h19
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/client.h15
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/device.h12
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/engine.h8
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/event.h64
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h167
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h25
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/intr.h73
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/layout.h5
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/memory.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/notify.h39
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/object.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/os.h20
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h42
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h9
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h66
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h86
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h5
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h29
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h7
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h7
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/gpio.h6
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h3
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h19
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h16
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h6
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h2
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h1
-rw-r--r--drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h23
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_abi16.c27
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_backlight.c6
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo.c7
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo0039.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo5039.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo74c1.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo85b5.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo9039.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bo90b5.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_boa0b5.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_chan.c306
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_chan.h14
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c81
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.h9
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_crtc.h7
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c86
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dma.c8
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dmem.c1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_dp.c40
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c57
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h18
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_encoder.h5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.c27
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fbcon.h82
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.c53
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_fence.h4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_mem.c4
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_nvif.c17
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_svm.c50
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_ttm.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_usif.c6
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_vga.c1
-rw-r--r--drivers/gpu/drm/nouveau/nv04_fbcon.c257
-rw-r--r--drivers/gpu/drm/nouveau/nv50_fbcon.c299
-rw-r--r--drivers/gpu/drm/nouveau/nv84_fence.c24
-rw-r--r--drivers/gpu/drm/nouveau/nvc0_fbcon.c297
-rw-r--r--drivers/gpu/drm/nouveau/nvif/Kbuild3
-rw-r--r--drivers/gpu/drm/nouveau/nvif/conn.c19
-rw-r--r--drivers/gpu/drm/nouveau/nvif/disp.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvif/event.c81
-rw-r--r--drivers/gpu/drm/nouveau/nvif/head.c58
-rw-r--r--drivers/gpu/drm/nouveau/nvif/notify.c210
-rw-r--r--drivers/gpu/drm/nouveau/nvif/outp.c178
-rw-r--r--drivers/gpu/drm/nouveau/nvif/user.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/Kbuild3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/client.c130
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/engine.c85
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/event.c158
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/firmware.c127
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/intr.c442
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/ioctl.c115
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/notify.c163
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/oproxy.c20
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/subdev.c117
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/core/uevent.c157
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/ga100.c82
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/ga102.c (renamed from drivers/gpu/drm/nouveau/nvkm/engine/fifo/usergv100.c)35
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c11
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/base.c104
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c40
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/user.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c93
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c39
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c283
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c91
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c93
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c85
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c13
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c89
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c95
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c38
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h23
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c12
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h16
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c250
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c75
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c25
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/uhead.c127
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c250
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/falcon.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild30
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c448
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c252
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h76
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c633
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h99
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c263
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h29
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h52
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h29
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c276
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h53
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.c111
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.h25
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c226
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c97
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c98
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c254
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c253
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c70
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c550
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c292
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c942
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h38
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c1506
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h168
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c105
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c59
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c33
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c109
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c49
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c45
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c99
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c46
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c95
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c308
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c361
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c241
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c93
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c81
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c252
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c344
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h23
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c94
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c103
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c198
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c381
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h20
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h223
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c430
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h125
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.c45
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h31
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c471
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/ucgrp.c125
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c409
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/fifo/user.h8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c12
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxga102.c77
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c224
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h77
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf104.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c21
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf110.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c24
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf119.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c40
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c12
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c71
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm200.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c12
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c80
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c60
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp104.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp107.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c62
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c35
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/ga102.c347
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c488
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h80
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c119
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c203
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c47
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvdec/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvdec/ga102.c61
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c19
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c11
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c98
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec2/ga102.c197
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c116
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c26
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c24
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c20
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c24
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c35
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/base.c245
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/fw.c354
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/ga100.c62
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/ga102.c148
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c345
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/gp102.c82
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/priv.h8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/falcon/v1.c210
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/nvfw/acr.c41
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/nvfw/hs.c39
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/nvfw/ls.c72
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c152
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga100.c49
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga102.c326
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c199
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c44
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c31
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c55
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/gv100.c67
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c177
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c145
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h104
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c38
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c21
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c41
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c120
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.c30
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c61
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c35
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c25
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c18
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c66
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c49
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c8
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c27
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga102.c59
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c31
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c27
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c12
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c27
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/ga102.c57
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm200.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp100.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp102.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp10b.c3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h3
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c130
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c35
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c35
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c50
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c82
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c38
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c9
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c126
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp10b.c11
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c63
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c93
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c21
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c23
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c7
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c29
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h50
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mc/tu102.c136
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c44
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c50
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c1
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c40
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c56
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c32
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c15
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c33
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h5
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/top/base.c13
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/top/ga100.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/top/gk104.c4
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/top/priv.h2
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/vfn/Kbuild6
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c (renamed from drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c)58
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c47
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/vfn/gv100.c (renamed from drivers/gpu/drm/nouveau/nvkm/engine/fifo/usertu102.c)27
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h25
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c108
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/vfn/uvfn.c67
-rw-r--r--drivers/gpu/drm/omapdrm/omap_fbdev.c8
-rw-r--r--drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c6
-rw-r--r--drivers/gpu/drm/panel/Kconfig19
-rw-r--r--drivers/gpu/drm/panel/Makefile2
-rw-r--r--drivers/gpu/drm/panel/panel-edp.c2
-rw-r--r--drivers/gpu/drm/panel/panel-ilitek-ili9341.c3
-rw-r--r--drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c473
-rw-r--r--drivers/gpu/drm/panel/panel-newvision-nv3051d.c504
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-db7430.c7
-rw-r--r--drivers/gpu/drm/panel/panel-sitronix-st7701.c70
-rw-r--r--drivers/gpu/drm/panel/panel-tpo-tpg110.c7
-rw-r--r--drivers/gpu/drm/panel/panel-widechips-ws2401.c7
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_dump.c4
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_perfcnt.c6
-rw-r--r--drivers/gpu/drm/pl111/pl111_drv.c2
-rw-r--r--drivers/gpu/drm/qxl/qxl_display.c2
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.c1
-rw-r--r--drivers/gpu/drm/qxl/qxl_drv.h1
-rw-r--r--drivers/gpu/drm/qxl/qxl_object.c17
-rw-r--r--drivers/gpu/drm/qxl/qxl_prime.c4
-rw-r--r--drivers/gpu/drm/radeon/Kconfig30
-rw-r--r--drivers/gpu/drm/radeon/atombios.h2
-rw-r--r--drivers/gpu/drm/radeon/radeon.h8
-rw-r--r--drivers/gpu/drm/radeon/radeon_atombios.c7
-rw-r--r--drivers/gpu/drm/radeon/radeon_audio.c117
-rw-r--r--drivers/gpu/drm/radeon/radeon_bios.c19
-rw-r--r--drivers/gpu/drm/radeon/radeon_cs.c7
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c6
-rw-r--r--drivers/gpu/drm/radeon/radeon_display.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c8
-rw-r--r--drivers/gpu/drm/radeon/radeon_object.c4
-rw-r--r--drivers/gpu/drm/radeon/radeon_trace.h2
-rw-r--r--drivers/gpu/drm/radeon/radeon_ttm.c8
-rw-r--r--drivers/gpu/drm/rcar-du/Kconfig10
-rw-r--r--drivers/gpu/drm/rcar-du/Makefile2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.c2
-rw-r--r--drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c816
-rw-r--r--drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi_regs.h151
-rw-r--r--drivers/gpu/drm/rockchip/cdn-dp-core.c2
-rw-r--r--drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c8
-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_drv.h2
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_fb.c45
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_fb.h6
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_gem.c1
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c4
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop2.c2
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_lvds.c10
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_vop2_reg.c2
-rw-r--r--drivers/gpu/drm/scheduler/sched_entity.c216
-rw-r--r--drivers/gpu/drm/scheduler/sched_main.c229
-rw-r--r--drivers/gpu/drm/solomon/ssd130x.c37
-rw-r--r--drivers/gpu/drm/sti/sti_drv.c2
-rw-r--r--drivers/gpu/drm/sti/sti_dvo.c2
-rw-r--r--drivers/gpu/drm/sti/sti_hda.c2
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi.c2
-rw-r--r--drivers/gpu/drm/stm/drv.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_drv.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c61
-rw-r--r--drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h7
-rw-r--r--drivers/gpu/drm/tegra/Makefile3
-rw-r--r--drivers/gpu/drm/tegra/dc.c4
-rw-r--r--drivers/gpu/drm/tegra/drm.c1
-rw-r--r--drivers/gpu/drm/tegra/fb.c9
-rw-r--r--drivers/gpu/drm/tegra/gem.c19
-rw-r--r--drivers/gpu/drm/tegra/hdmi.c9
-rw-r--r--drivers/gpu/drm/tegra/nvdec.c171
-rw-r--r--drivers/gpu/drm/tegra/output.c10
-rw-r--r--drivers/gpu/drm/tegra/riscv.c106
-rw-r--r--drivers/gpu/drm/tegra/riscv.h30
-rw-r--r--drivers/gpu/drm/tegra/submit.c13
-rw-r--r--drivers/gpu/drm/tegra/uapi.c2
-rw-r--r--drivers/gpu/drm/tests/Makefile15
-rw-r--r--drivers/gpu/drm/tests/drm_buddy_test.c6
-rw-r--r--drivers/gpu/drm/tests/drm_client_modeset_test.c98
-rw-r--r--drivers/gpu/drm/tests/drm_dp_mst_helper_test.c445
-rw-r--r--drivers/gpu/drm/tests/drm_format_helper_test.c12
-rw-r--r--drivers/gpu/drm/tests/drm_kunit_helpers.c71
-rw-r--r--drivers/gpu/drm/tests/drm_kunit_helpers.h11
-rw-r--r--drivers/gpu/drm/tests/drm_mm_test.c8
-rw-r--r--drivers/gpu/drm/tests/drm_plane_helper_test.c467
-rw-r--r--drivers/gpu/drm/tidss/tidss_drv.c2
-rw-r--r--drivers/gpu/drm/tidss/tidss_kms.c1
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.c2
-rw-r--r--drivers/gpu/drm/tiny/Kconfig13
-rw-r--r--drivers/gpu/drm/tiny/Makefile1
-rw-r--r--drivers/gpu/drm/tiny/arcpgu.c2
-rw-r--r--drivers/gpu/drm/tiny/bochs.c3
-rw-r--r--drivers/gpu/drm/tiny/cirrus.c2
-rw-r--r--drivers/gpu/drm/tiny/gm12u320.c2
-rw-r--r--drivers/gpu/drm/tiny/hx8357d.c2
-rw-r--r--drivers/gpu/drm/tiny/ili9163.c2
-rw-r--r--drivers/gpu/drm/tiny/ili9225.c2
-rw-r--r--drivers/gpu/drm/tiny/ili9341.c2
-rw-r--r--drivers/gpu/drm/tiny/ili9486.c2
-rw-r--r--drivers/gpu/drm/tiny/mi0283qt.c2
-rw-r--r--drivers/gpu/drm/tiny/ofdrm.c1429
-rw-r--r--drivers/gpu/drm/tiny/panel-mipi-dbi.c2
-rw-r--r--drivers/gpu/drm/tiny/repaper.c2
-rw-r--r--drivers/gpu/drm/tiny/simpledrm.c18
-rw-r--r--drivers/gpu/drm/tiny/st7586.c2
-rw-r--r--drivers/gpu/drm/tiny/st7735r.c2
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo.c3
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_util.c6
-rw-r--r--drivers/gpu/drm/ttm/ttm_bo_vm.c4
-rw-r--r--drivers/gpu/drm/ttm/ttm_pool.c82
-rw-r--r--drivers/gpu/drm/ttm/ttm_range_manager.c3
-rw-r--r--drivers/gpu/drm/ttm/ttm_resource.c14
-rw-r--r--drivers/gpu/drm/tve200/tve200_drv.c3
-rw-r--r--drivers/gpu/drm/udl/Makefile2
-rw-r--r--drivers/gpu/drm/udl/udl_connector.c139
-rw-r--r--drivers/gpu/drm/udl/udl_connector.h15
-rw-r--r--drivers/gpu/drm/udl/udl_drv.c2
-rw-r--r--drivers/gpu/drm/udl/udl_drv.h42
-rw-r--r--drivers/gpu/drm/udl/udl_modeset.c566
-rw-r--r--drivers/gpu/drm/udl/udl_proto.h68
-rw-r--r--drivers/gpu/drm/udl/udl_transfer.c7
-rw-r--r--drivers/gpu/drm/v3d/v3d_drv.c1
-rw-r--r--drivers/gpu/drm/v3d/v3d_gem.c17
-rw-r--r--drivers/gpu/drm/v3d/v3d_perfmon.c6
-rw-r--r--drivers/gpu/drm/vboxvideo/vbox_drv.c4
-rw-r--r--drivers/gpu/drm/vboxvideo/vbox_main.c1
-rw-r--r--drivers/gpu/drm/vc4/vc4_bo.c4
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.h16
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c41
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.h8
-rw-r--r--drivers/gpu/drm/vc4/vc4_hvs.c26
-rw-r--r--drivers/gpu/drm/vc4/vc4_kms.c13
-rw-r--r--drivers/gpu/drm/vc4/vc4_vec.c8
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.c1
-rw-r--r--drivers/gpu/drm/virtio/virtgpu_drv.h1
-rw-r--r--drivers/gpu/drm/vkms/vkms_drv.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/Kconfig7
-rw-r--r--drivers/gpu/drm/vmwgfx/Makefile4
-rw-r--r--drivers/gpu/drm/vmwgfx/ttm_object.c123
-rw-r--r--drivers/gpu/drm/vmwgfx/ttm_object.h20
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_blit.c4
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_bo.c22
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c62
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c31
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c129
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.h53
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c17
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_fb.c831
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c6
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.c199
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.h83
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.c669
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_kms.h31
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c8
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_mksstat.h2
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_msg.c65
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c6
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c35
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c26
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_surface.c14
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_validation.c55
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_validation.h26
-rw-r--r--drivers/gpu/drm/xen/xen_drm_front_gem.c1
-rw-r--r--drivers/gpu/drm/xlnx/Makefile2
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_disp.c646
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_disp.h48
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_dp.c477
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_dp.h4
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_dpsub.c300
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_dpsub.h46
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_kms.c534
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_kms.h46
-rw-r--r--drivers/gpu/host1x/context.c4
-rw-r--r--drivers/gpu/host1x/debug.c28
-rw-r--r--drivers/gpu/host1x/dev.c12
-rw-r--r--drivers/gpu/host1x/fence.c2
-rw-r--r--drivers/hid/Kconfig3
-rw-r--r--drivers/hid/hid-alps.c6
-rw-r--r--drivers/hid/hid-apple.c141
-rw-r--r--drivers/hid/hid-debug.c3
-rw-r--r--drivers/hid/hid-elan.c6
-rw-r--r--drivers/hid/hid-ft260.c325
-rw-r--r--drivers/hid/hid-hyperv.c31
-rw-r--r--drivers/hid/hid-input.c9
-rw-r--r--drivers/hid/hid-logitech-hidpp.c2
-rw-r--r--drivers/hid/hid-mcp2221.c313
-rw-r--r--drivers/hid/hid-playstation.c1136
-rw-r--r--drivers/hid/hid-rmi.c2
-rw-r--r--drivers/hid/hid-sensor-custom.c4
-rw-r--r--drivers/hid/hid-uclogic-params-test.c4
-rw-r--r--drivers/hid/hid-uclogic-params.c73
-rw-r--r--drivers/hid/hid-uclogic-rdesc-test.c4
-rw-r--r--drivers/hid/hid-uclogic-rdesc.c34
-rw-r--r--drivers/hid/hid-uclogic-rdesc.h7
-rw-r--r--drivers/hid/hid-wiimote-core.c7
-rw-r--r--drivers/hid/hid-wiimote-modules.c225
-rw-r--r--drivers/hid/hid-wiimote.h1
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-acpi.c5
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-core.c27
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-of-elan.c5
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-of-goodix.c5
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-of.c5
-rw-r--r--drivers/hid/intel-ish-hid/ishtp/client.c3
-rw-r--r--drivers/hv/hv_balloon.c94
-rw-r--r--drivers/hv/ring_buffer.c13
-rw-r--r--drivers/hv/vmbus_drv.c110
-rw-r--r--drivers/hwmon/Kconfig20
-rw-r--r--drivers/hwmon/Makefile2
-rw-r--r--drivers/hwmon/acpi_power_meter.c5
-rw-r--r--drivers/hwmon/adm1177.c27
-rw-r--r--drivers/hwmon/aht10.c5
-rw-r--r--drivers/hwmon/aquacomputer_d5next.c233
-rw-r--r--drivers/hwmon/asus_atk0110.c6
-rw-r--r--drivers/hwmon/atxp1.c1
-rw-r--r--drivers/hwmon/coretemp.c242
-rw-r--r--drivers/hwmon/dell-smm-hwmon.c3
-rw-r--r--drivers/hwmon/ds1621.c2
-rw-r--r--drivers/hwmon/emc2305.c48
-rw-r--r--drivers/hwmon/fschmd.c4
-rw-r--r--drivers/hwmon/gpio-fan.c1
-rw-r--r--drivers/hwmon/gsc-hwmon.c6
-rw-r--r--drivers/hwmon/hwmon.c1
-rw-r--r--drivers/hwmon/it87.c90
-rw-r--r--drivers/hwmon/jc42.c273
-rw-r--r--drivers/hwmon/lm73.c6
-rw-r--r--drivers/hwmon/lm90.c21
-rw-r--r--drivers/hwmon/ltc2992.c4
-rw-r--r--drivers/hwmon/max127.c5
-rw-r--r--drivers/hwmon/mr75203.c1
-rw-r--r--drivers/hwmon/nct6775-platform.c7
-rw-r--r--drivers/hwmon/occ/Kconfig2
-rw-r--r--drivers/hwmon/oxp-sensors.c284
-rw-r--r--drivers/hwmon/pcf8591.c1
-rw-r--r--drivers/hwmon/pmbus/ltc2978.c17
-rw-r--r--drivers/hwmon/pmbus/pmbus_core.c52
-rw-r--r--drivers/hwmon/pmbus/q54sj108a2.c1
-rw-r--r--drivers/hwmon/sbrmi.c5
-rw-r--r--drivers/hwmon/sbtsi_temp.c5
-rw-r--r--drivers/hwmon/sht3x.c12
-rw-r--r--drivers/hwmon/sht4x.c5
-rw-r--r--drivers/hwmon/smpro-hwmon.c466
-rw-r--r--drivers/hwmon/vt8231.c1
-rw-r--r--drivers/hwmon/w83l786ng.c1
-rw-r--r--drivers/iio/adc/twl4030-madc.c1
-rw-r--r--drivers/infiniband/core/cm_trace.h2
-rw-r--r--drivers/infiniband/core/cma.c2
-rw-r--r--drivers/infiniband/core/cma_trace.h2
-rw-r--r--drivers/infiniband/core/umem_dmabuf.c7
-rw-r--r--drivers/infiniband/hw/cxgb4/id_table.c4
-rw-r--r--drivers/infiniband/hw/hfi1/init.c21
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_ah.c5
-rw-r--r--drivers/infiniband/hw/qib/qib_iba6120.c2
-rw-r--r--drivers/infiniband/hw/qib/qib_init.c21
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-clt.c4
-rw-r--r--drivers/input/input.c3
-rw-r--r--drivers/input/joystick/Kconfig1
-rw-r--r--drivers/input/joystick/as5011.c5
-rw-r--r--drivers/input/joystick/psxpad-spi.c9
-rw-r--r--drivers/input/keyboard/Kconfig10
-rw-r--r--drivers/input/keyboard/adp5588-keys.c5
-rw-r--r--drivers/input/keyboard/adp5589-keys.c14
-rw-r--r--drivers/input/keyboard/cap11xx.c6
-rw-r--r--drivers/input/keyboard/cros_ec_keyb.c6
-rw-r--r--drivers/input/keyboard/cypress-sf.c10
-rw-r--r--drivers/input/keyboard/dlink-dir685-touchkeys.c9
-rw-r--r--drivers/input/keyboard/ep93xx_keypad.c10
-rw-r--r--drivers/input/keyboard/gpio_keys.c8
-rw-r--r--drivers/input/keyboard/ipaq-micro-keys.c10
-rw-r--r--drivers/input/keyboard/lm8323.c11
-rw-r--r--drivers/input/keyboard/lm8333.c5
-rw-r--r--drivers/input/keyboard/lpc32xx-keys.c8
-rw-r--r--drivers/input/keyboard/matrix_keypad.c11
-rw-r--r--drivers/input/keyboard/max7359_keypad.c11
-rw-r--r--drivers/input/keyboard/mcs_touchkey.c14
-rw-r--r--drivers/input/keyboard/mpr121_touchkey.c13
-rw-r--r--drivers/input/keyboard/mtk-pmic-keys.c10
-rw-r--r--drivers/input/keyboard/nomadik-ske-keypad.c8
-rw-r--r--drivers/input/keyboard/pmic8xxx-keypad.c8
-rw-r--r--drivers/input/keyboard/pxa27x_keypad.c8
-rw-r--r--drivers/input/keyboard/qt1050.c8
-rw-r--r--drivers/input/keyboard/qt1070.c11
-rw-r--r--drivers/input/keyboard/qt2160.c5
-rw-r--r--drivers/input/keyboard/sh_keysc.c8
-rw-r--r--drivers/input/keyboard/spear-keyboard.c9
-rw-r--r--drivers/input/keyboard/st-keyscan.c7
-rw-r--r--drivers/input/keyboard/stmpe-keypad.c1
-rw-r--r--drivers/input/keyboard/tc3589x-keypad.c8
-rw-r--r--drivers/input/keyboard/tca6416-keypad.c14
-rw-r--r--drivers/input/keyboard/tca8418_keypad.c5
-rw-r--r--drivers/input/keyboard/tegra-kbc.c7
-rw-r--r--drivers/input/keyboard/tm2-touchkey.c15
-rw-r--r--drivers/input/misc/Kconfig4
-rw-r--r--drivers/input/misc/ad714x-i2c.c5
-rw-r--r--drivers/input/misc/adxl34x-i2c.c5
-rw-r--r--drivers/input/misc/apanel.c5
-rw-r--r--drivers/input/misc/atlas_btns.c4
-rw-r--r--drivers/input/misc/atmel_captouch.c9
-rw-r--r--drivers/input/misc/bma150.c5
-rw-r--r--drivers/input/misc/cma3000_d0x_i2c.c5
-rw-r--r--drivers/input/misc/da7280.c5
-rw-r--r--drivers/input/misc/drv260x.c5
-rw-r--r--drivers/input/misc/drv2665.c5
-rw-r--r--drivers/input/misc/drv2667.c5
-rw-r--r--drivers/input/misc/ibm-panel.c5
-rw-r--r--drivers/input/misc/iqs7222.c504
-rw-r--r--drivers/input/misc/kxtj9.c5
-rw-r--r--drivers/input/misc/max8997_haptic.c7
-rw-r--r--drivers/input/misc/mma8450.c5
-rw-r--r--drivers/input/misc/pcf8574_keypad.c4
-rw-r--r--drivers/input/mouse/cyapa.c5
-rw-r--r--drivers/input/mouse/elan_i2c_core.c20
-rw-r--r--drivers/input/mouse/synaptics_i2c.c5
-rw-r--r--drivers/input/rmi4/rmi_i2c.c5
-rw-r--r--drivers/input/rmi4/rmi_smbus.c5
-rw-r--r--drivers/input/touchscreen/Kconfig42
-rw-r--r--drivers/input/touchscreen/Makefile3
-rw-r--r--drivers/input/touchscreen/ad7879-i2c.c5
-rw-r--r--drivers/input/touchscreen/ar1021_i2c.c5
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c4
-rw-r--r--drivers/input/touchscreen/auo-pixcir-ts.c5
-rw-r--r--drivers/input/touchscreen/bu21013_ts.c5
-rw-r--r--drivers/input/touchscreen/bu21029_ts.c5
-rw-r--r--drivers/input/touchscreen/chipone_icn8318.c5
-rw-r--r--drivers/input/touchscreen/cy8ctma140.c5
-rw-r--r--drivers/input/touchscreen/cy8ctmg110_ts.c5
-rw-r--r--drivers/input/touchscreen/cyttsp4_i2c.c5
-rw-r--r--drivers/input/touchscreen/cyttsp5.c900
-rw-r--r--drivers/input/touchscreen/cyttsp_i2c.c5
-rw-r--r--drivers/input/touchscreen/edt-ft5x06.c6
-rw-r--r--drivers/input/touchscreen/eeti_ts.c5
-rw-r--r--drivers/input/touchscreen/egalax_ts.c54
-rw-r--r--drivers/input/touchscreen/ektf2127.c5
-rw-r--r--drivers/input/touchscreen/elants_i2c.c28
-rw-r--r--drivers/input/touchscreen/goodix.c5
-rw-r--r--drivers/input/touchscreen/hideep.c5
-rw-r--r--drivers/input/touchscreen/himax_hx83112b.c364
-rw-r--r--drivers/input/touchscreen/hycon-hy46xx.c5
-rw-r--r--drivers/input/touchscreen/hynitron_cstxxx.c498
-rw-r--r--drivers/input/touchscreen/ili210x.c6
-rw-r--r--drivers/input/touchscreen/ilitek_ts_i2c.c5
-rw-r--r--drivers/input/touchscreen/iqs5xx.c5
-rw-r--r--drivers/input/touchscreen/max11801_ts.c5
-rw-r--r--drivers/input/touchscreen/mcs5000_ts.c5
-rw-r--r--drivers/input/touchscreen/melfas_mip4.c4
-rw-r--r--drivers/input/touchscreen/migor_ts.c5
-rw-r--r--drivers/input/touchscreen/mms114.c5
-rw-r--r--drivers/input/touchscreen/msg2638.c197
-rw-r--r--drivers/input/touchscreen/pixcir_i2c_ts.c6
-rw-r--r--drivers/input/touchscreen/raydium_i2c_ts.c12
-rw-r--r--drivers/input/touchscreen/rohm_bu21023.c5
-rw-r--r--drivers/input/touchscreen/s6sy761.c5
-rw-r--r--drivers/input/touchscreen/silead.c6
-rw-r--r--drivers/input/touchscreen/sis_i2c.c5
-rw-r--r--drivers/input/touchscreen/st1232.c6
-rw-r--r--drivers/input/touchscreen/stmfts.c5
-rw-r--r--drivers/input/touchscreen/sx8654.c6
-rw-r--r--drivers/input/touchscreen/tps6507x-ts.c2
-rw-r--r--drivers/input/touchscreen/tsc2004.c5
-rw-r--r--drivers/input/touchscreen/tsc2007_core.c6
-rw-r--r--drivers/input/touchscreen/wacom_i2c.c5
-rw-r--r--drivers/input/touchscreen/wdt87xx_i2c.c5
-rw-r--r--drivers/input/touchscreen/zet6223.c5
-rw-r--r--drivers/input/touchscreen/zforce_ts.c5
-rw-r--r--drivers/iommu/Kconfig8
-rw-r--r--drivers/iommu/amd/amd_iommu_types.h1
-rw-r--r--drivers/iommu/amd/iommu.c44
-rw-r--r--drivers/iommu/dma-iommu.c3
-rw-r--r--drivers/iommu/hyperv-iommu.c11
-rw-r--r--drivers/iommu/intel/iommu.c2
-rw-r--r--drivers/iommu/intel/iommu.h1
-rw-r--r--drivers/iommu/intel/irq_remapping.c52
-rw-r--r--drivers/iommu/of_iommu.c1
-rw-r--r--drivers/irqchip/Kconfig9
-rw-r--r--drivers/irqchip/irq-apple-aic.c6
-rw-r--r--drivers/irqchip/irq-gic-pm.c2
-rw-r--r--drivers/irqchip/irq-gic-v2m.c11
-rw-r--r--drivers/irqchip/irq-gic-v3.c3
-rw-r--r--drivers/irqchip/irq-gic.c7
-rw-r--r--drivers/irqchip/irq-loongarch-cpu.c48
-rw-r--r--drivers/irqchip/irq-loongson-eiointc.c63
-rw-r--r--drivers/irqchip/irq-loongson-htvec.c176
-rw-r--r--drivers/irqchip/irq-loongson-liointc.c37
-rw-r--r--drivers/irqchip/irq-loongson-pch-lpc.c25
-rw-r--r--drivers/irqchip/irq-loongson-pch-pic.c76
-rw-r--r--drivers/irqchip/irq-ls-extirq.c2
-rw-r--r--drivers/irqchip/irq-mips-gic.c2
-rw-r--r--drivers/irqchip/irq-mtk-cirq.c95
-rw-r--r--drivers/irqchip/irq-mvebu-icu.c4
-rw-r--r--drivers/irqchip/irq-sifive-plic.c6
-rw-r--r--drivers/irqchip/irq-sl28cpld.c3
-rw-r--r--drivers/irqchip/irq-st.c7
-rw-r--r--drivers/irqchip/irq-ti-sci-inta.c2
-rw-r--r--drivers/irqchip/irq-wpcm450-aic.c1
-rw-r--r--drivers/isdn/mISDN/l1oip_core.c2
-rw-r--r--drivers/mailbox/Kconfig2
-rw-r--r--drivers/mailbox/pcc.c1
-rw-r--r--drivers/md/bcache/movinggc.c2
-rw-r--r--drivers/md/bcache/request.c4
-rw-r--r--drivers/md/bcache/writeback.c4
-rw-r--r--drivers/md/dm-cache-metadata.c54
-rw-r--r--drivers/md/dm-cache-target.c11
-rw-r--r--drivers/md/dm-clone-target.c1
-rw-r--r--drivers/md/dm-init.c22
-rw-r--r--drivers/md/dm-integrity.c2
-rw-r--r--drivers/md/dm-ioctl.c6
-rw-r--r--drivers/md/dm-table.c2
-rw-r--r--drivers/md/dm-thin-metadata.c60
-rw-r--r--drivers/md/dm-thin.c20
-rw-r--r--drivers/md/dm.c138
-rw-r--r--drivers/md/md-bitmap.c47
-rw-r--r--drivers/md/md.c323
-rw-r--r--drivers/md/md.h1
-rw-r--r--drivers/md/raid0.c1
-rw-r--r--drivers/md/raid1.c13
-rw-r--r--drivers/md/raid10.c20
-rw-r--r--drivers/md/raid5-cache.c10
-rw-r--r--drivers/md/raid5-ppl.c5
-rw-r--r--drivers/media/Kconfig2
-rw-r--r--drivers/media/cec/platform/stm32/stm32-cec.c9
-rw-r--r--drivers/media/common/v4l2-tpg/v4l2-tpg-core.c8
-rw-r--r--drivers/media/common/videobuf2/frame_vector.c10
-rw-r--r--drivers/media/common/videobuf2/videobuf2-core.c26
-rw-r--r--drivers/media/common/videobuf2/videobuf2-dma-contig.c28
-rw-r--r--drivers/media/common/videobuf2/videobuf2-dma-sg.c26
-rw-r--r--drivers/media/common/videobuf2/videobuf2-memops.c6
-rw-r--r--drivers/media/common/videobuf2/videobuf2-vmalloc.c24
-rw-r--r--drivers/media/dvb-core/dmxdev.c8
-rw-r--r--drivers/media/dvb-core/dvb_ca_en50221.c2
-rw-r--r--drivers/media/dvb-core/dvb_demux.c4
-rw-r--r--drivers/media/dvb-core/dvb_frontend.c33
-rw-r--r--drivers/media/dvb-core/dvb_ringbuffer.c4
-rw-r--r--drivers/media/dvb-core/dvbdev.c36
-rw-r--r--drivers/media/dvb-frontends/a8293.c160
-rw-r--r--drivers/media/dvb-frontends/a8293.h3
-rw-r--r--drivers/media/dvb-frontends/af9013.c5
-rw-r--r--drivers/media/dvb-frontends/af9033.c5
-rw-r--r--drivers/media/dvb-frontends/au8522_decoder.c5
-rw-r--r--drivers/media/dvb-frontends/bcm3510.c1
-rw-r--r--drivers/media/dvb-frontends/cxd2099.c5
-rw-r--r--drivers/media/dvb-frontends/cxd2820r_core.c7
-rw-r--r--drivers/media/dvb-frontends/cxd2820r_priv.h2
-rw-r--r--drivers/media/dvb-frontends/drx39xyj/drx_dap_fasi.h2
-rw-r--r--drivers/media/dvb-frontends/drx39xyj/drxj.c1
-rw-r--r--drivers/media/dvb-frontends/helene.c5
-rw-r--r--drivers/media/dvb-frontends/lgdt3306a.c5
-rw-r--r--drivers/media/dvb-frontends/lgdt330x.c5
-rw-r--r--drivers/media/dvb-frontends/mn88472.c5
-rw-r--r--drivers/media/dvb-frontends/mn88473.c5
-rw-r--r--drivers/media/dvb-frontends/mxl5xx.c2
-rw-r--r--drivers/media/dvb-frontends/mxl692.c5
-rw-r--r--drivers/media/dvb-frontends/rtl2830.c5
-rw-r--r--drivers/media/dvb-frontends/rtl2832.c5
-rw-r--r--drivers/media/dvb-frontends/si2165.c5
-rw-r--r--drivers/media/dvb-frontends/si2168.c5
-rw-r--r--drivers/media/dvb-frontends/sp2.c5
-rw-r--r--drivers/media/dvb-frontends/stv0288.c5
-rw-r--r--drivers/media/dvb-frontends/stv090x.c5
-rw-r--r--drivers/media/dvb-frontends/stv6110x.c5
-rw-r--r--drivers/media/dvb-frontends/tda10071.c5
-rw-r--r--drivers/media/dvb-frontends/ts2020.c5
-rw-r--r--drivers/media/i2c/Kconfig62
-rw-r--r--drivers/media/i2c/Makefile5
-rw-r--r--drivers/media/i2c/ad5820.c33
-rw-r--r--drivers/media/i2c/ad9389b.c4
-rw-r--r--drivers/media/i2c/adp1653.c5
-rw-r--r--drivers/media/i2c/adv7170.c5
-rw-r--r--drivers/media/i2c/adv7175.c5
-rw-r--r--drivers/media/i2c/adv7183.c5
-rw-r--r--drivers/media/i2c/adv7393.c5
-rw-r--r--drivers/media/i2c/adv748x/adv748x-afe.c4
-rw-r--r--drivers/media/i2c/adv748x/adv748x.h3
-rw-r--r--drivers/media/i2c/adv7511-v4l2.c4
-rw-r--r--drivers/media/i2c/adv7842.c5
-rw-r--r--drivers/media/i2c/ak881x.c5
-rw-r--r--drivers/media/i2c/aptina-pll.c1
-rw-r--r--drivers/media/i2c/ar0521.c352
-rw-r--r--drivers/media/i2c/bt819.c5
-rw-r--r--drivers/media/i2c/bt856.c5
-rw-r--r--drivers/media/i2c/bt866.c5
-rw-r--r--drivers/media/i2c/cs3308.c5
-rw-r--r--drivers/media/i2c/cs5345.c5
-rw-r--r--drivers/media/i2c/cx25840/cx25840-core.c5
-rw-r--r--drivers/media/i2c/dw9768.c33
-rw-r--r--drivers/media/i2c/hi846.c14
-rw-r--r--drivers/media/i2c/imx208.c4
-rw-r--r--drivers/media/i2c/imx274.c5
-rw-r--r--drivers/media/i2c/imx290.c786
-rw-r--r--drivers/media/i2c/imx319.c4
-rw-r--r--drivers/media/i2c/imx355.c4
-rw-r--r--drivers/media/i2c/imx412.c9
-rw-r--r--drivers/media/i2c/isl7998x.c2
-rw-r--r--drivers/media/i2c/ks0127.c4
-rw-r--r--drivers/media/i2c/lm3560.c5
-rw-r--r--drivers/media/i2c/lm3646.c5
-rw-r--r--drivers/media/i2c/m52790.c5
-rw-r--r--drivers/media/i2c/m5mols/m5mols_core.c5
-rw-r--r--drivers/media/i2c/ml86v7667.c5
-rw-r--r--drivers/media/i2c/mt9m032.c5
-rw-r--r--drivers/media/i2c/mt9p031.c9
-rw-r--r--drivers/media/i2c/mt9t001.c5
-rw-r--r--drivers/media/i2c/mt9t112.c5
-rw-r--r--drivers/media/i2c/mt9v011.c5
-rw-r--r--drivers/media/i2c/noon010pc30.c5
-rw-r--r--drivers/media/i2c/ov08d10.c5
-rw-r--r--drivers/media/i2c/ov08x40.c3325
-rw-r--r--drivers/media/i2c/ov13858.c5
-rw-r--r--drivers/media/i2c/ov2640.c2
-rw-r--r--drivers/media/i2c/ov2680.c2
-rw-r--r--drivers/media/i2c/ov2740.c134
-rw-r--r--drivers/media/i2c/ov4689.c1018
-rw-r--r--drivers/media/i2c/ov5640.c25
-rw-r--r--drivers/media/i2c/ov5645.c148
-rw-r--r--drivers/media/i2c/ov5648.c1
-rw-r--r--drivers/media/i2c/ov5693.c10
-rw-r--r--drivers/media/i2c/ov6650.c5
-rw-r--r--drivers/media/i2c/ov7640.c5
-rw-r--r--drivers/media/i2c/ov7670.c1
-rw-r--r--drivers/media/i2c/ov8856.c33
-rw-r--r--drivers/media/i2c/ov9282.c611
-rw-r--r--drivers/media/i2c/ov9640.c5
-rw-r--r--drivers/media/i2c/ov9650.c49
-rw-r--r--drivers/media/i2c/rj54n1cb0c.c5
-rw-r--r--drivers/media/i2c/s5c73m3/s5c73m3-core.c107
-rw-r--r--drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c1
-rw-r--r--drivers/media/i2c/s5c73m3/s5c73m3.h10
-rw-r--r--drivers/media/i2c/s5k4ecgx.c1032
-rw-r--r--drivers/media/i2c/s5k5baf.c64
-rw-r--r--drivers/media/i2c/s5k6a3.c30
-rw-r--r--drivers/media/i2c/s5k6aa.c5
-rw-r--r--drivers/media/i2c/saa6588.c5
-rw-r--r--drivers/media/i2c/saa6752hs.c5
-rw-r--r--drivers/media/i2c/saa7110.c5
-rw-r--r--drivers/media/i2c/saa717x.c5
-rw-r--r--drivers/media/i2c/saa7185.c5
-rw-r--r--drivers/media/i2c/sony-btf-mpx.c5
-rw-r--r--drivers/media/i2c/sr030pc30.c5
-rw-r--r--drivers/media/i2c/st-vgxy61.c1963
-rw-r--r--drivers/media/i2c/tc358743.c9
-rw-r--r--drivers/media/i2c/tc358746.c1694
-rw-r--r--drivers/media/i2c/tda7432.c5
-rw-r--r--drivers/media/i2c/tda9840.c5
-rw-r--r--drivers/media/i2c/tea6415c.c5
-rw-r--r--drivers/media/i2c/tea6420.c5
-rw-r--r--drivers/media/i2c/ths7303.c5
-rw-r--r--drivers/media/i2c/tlv320aic23b.c5
-rw-r--r--drivers/media/i2c/tw2804.c5
-rw-r--r--drivers/media/i2c/tw9903.c5
-rw-r--r--drivers/media/i2c/tw9906.c5
-rw-r--r--drivers/media/i2c/tw9910.c5
-rw-r--r--drivers/media/i2c/uda1342.c5
-rw-r--r--drivers/media/i2c/upd64031a.c5
-rw-r--r--drivers/media/i2c/upd64083.c5
-rw-r--r--drivers/media/i2c/vp27smpx.c5
-rw-r--r--drivers/media/i2c/vpx3220.c5
-rw-r--r--drivers/media/i2c/vs6624.c5
-rw-r--r--drivers/media/i2c/wm8739.c5
-rw-r--r--drivers/media/i2c/wm8775.c5
-rw-r--r--drivers/media/pci/bt8xx/bttv.h1
-rw-r--r--drivers/media/pci/cx25821/cx25821-video.h3
-rw-r--r--drivers/media/pci/intel/ipu3/Kconfig1
-rw-r--r--drivers/media/pci/mantis/Kconfig2
-rw-r--r--drivers/media/pci/pt3/pt3.c16
-rw-r--r--drivers/media/pci/saa7134/saa7134.h4
-rw-r--r--drivers/media/pci/saa7164/saa7164-core.c10
-rw-r--r--drivers/media/pci/saa7164/saa7164.h2
-rw-r--r--drivers/media/pci/solo6x10/solo6x10-core.c1
-rw-r--r--drivers/media/pci/zoran/zoran_device.h2
-rw-r--r--drivers/media/platform/Kconfig1
-rw-r--r--drivers/media/platform/Makefile1
-rw-r--r--drivers/media/platform/amphion/vdec.c218
-rw-r--r--drivers/media/platform/amphion/venc.c41
-rw-r--r--drivers/media/platform/amphion/vpu.h5
-rw-r--r--drivers/media/platform/amphion/vpu_cmds.c39
-rw-r--r--drivers/media/platform/amphion/vpu_dbg.c8
-rw-r--r--drivers/media/platform/amphion/vpu_drv.c6
-rw-r--r--drivers/media/platform/amphion/vpu_helpers.c45
-rw-r--r--drivers/media/platform/amphion/vpu_helpers.h2
-rw-r--r--drivers/media/platform/amphion/vpu_malone.c4
-rw-r--r--drivers/media/platform/amphion/vpu_msgs.c2
-rw-r--r--drivers/media/platform/amphion/vpu_v4l2.c199
-rw-r--r--drivers/media/platform/amphion/vpu_v4l2.h3
-rw-r--r--drivers/media/platform/amphion/vpu_windsor.c9
-rw-r--r--drivers/media/platform/aspeed/Kconfig1
-rw-r--r--drivers/media/platform/aspeed/aspeed-video.c346
-rw-r--r--drivers/media/platform/atmel/Kconfig51
-rw-r--r--drivers/media/platform/atmel/Makefile7
-rw-r--r--drivers/media/platform/chips-media/coda-bit.c14
-rw-r--r--drivers/media/platform/chips-media/coda-jpeg.c10
-rw-r--r--drivers/media/platform/mediatek/jpeg/Makefile14
-rw-r--r--drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c490
-rw-r--r--drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.h169
-rw-r--r--drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c325
-rw-r--r--drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.h6
-rw-r--r--drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_reg.h1
-rw-r--r--drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c255
-rw-r--r--drivers/media/platform/mediatek/mdp/mtk_mdp_comp.c5
-rw-r--r--drivers/media/platform/mediatek/mdp3/Kconfig1
-rw-r--r--drivers/media/platform/mediatek/mdp3/mtk-img-ipi.h76
-rw-r--r--drivers/media/platform/mediatek/mdp3/mtk-mdp3-cmdq.c51
-rw-r--r--drivers/media/platform/mediatek/mdp3/mtk-mdp3-comp.c24
-rw-r--r--drivers/media/platform/mediatek/mdp3/mtk-mdp3-core.c15
-rw-r--r--drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateless.c13
-rw-r--r--drivers/media/platform/mediatek/vcodec/mtk_vcodec_enc.c5
-rw-r--r--drivers/media/platform/mediatek/vcodec/vdec/vdec_h264_req_multi_if.c60
-rw-r--r--drivers/media/platform/mediatek/vcodec/vdec/vdec_vp9_req_lat_if.c15
-rw-r--r--drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c2
-rw-r--r--drivers/media/platform/microchip/Kconfig61
-rw-r--r--drivers/media/platform/microchip/Makefile9
-rw-r--r--drivers/media/platform/microchip/microchip-csi2dc.c (renamed from drivers/media/platform/atmel/microchip-csi2dc.c)0
-rw-r--r--drivers/media/platform/microchip/microchip-isc-base.c2040
-rw-r--r--drivers/media/platform/microchip/microchip-isc-clk.c311
-rw-r--r--drivers/media/platform/microchip/microchip-isc-regs.h413
-rw-r--r--drivers/media/platform/microchip/microchip-isc-scaler.c267
-rw-r--r--drivers/media/platform/microchip/microchip-isc.h400
-rw-r--r--drivers/media/platform/microchip/microchip-sama5d2-isc.c683
-rw-r--r--drivers/media/platform/microchip/microchip-sama7g5-isc.c646
-rw-r--r--drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c6
-rw-r--r--drivers/media/platform/nxp/Kconfig13
-rw-r--r--drivers/media/platform/nxp/Makefile1
-rw-r--r--drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.c4
-rw-r--r--drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c612
-rw-r--r--drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h10
-rw-r--r--drivers/media/platform/nxp/imx7-media-csi.c (renamed from drivers/staging/media/imx/imx7-media-csi.c)138
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe-170.c20
-rw-r--r--drivers/media/platform/qcom/camss/camss-vfe-480.c20
-rw-r--r--drivers/media/platform/qcom/camss/camss-video.c3
-rw-r--r--drivers/media/platform/qcom/camss/camss.c61
-rw-r--r--drivers/media/platform/qcom/camss/camss.h1
-rw-r--r--drivers/media/platform/qcom/venus/firmware.c20
-rw-r--r--drivers/media/platform/qcom/venus/pm_helpers.c4
-rw-r--r--drivers/media/platform/renesas/Kconfig1
-rw-r--r--drivers/media/platform/renesas/Makefile1
-rw-r--r--drivers/media/platform/renesas/rcar-vin/rcar-core.c22
-rw-r--r--drivers/media/platform/renesas/rcar-vin/rcar-dma.c104
-rw-r--r--drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c93
-rw-r--r--drivers/media/platform/renesas/rcar-vin/rcar-vin.h9
-rw-r--r--drivers/media/platform/renesas/rzg2l-cru/Kconfig33
-rw-r--r--drivers/media/platform/renesas/rzg2l-cru/Makefile6
-rw-r--r--drivers/media/platform/renesas/rzg2l-cru/rzg2l-core.c338
-rw-r--r--drivers/media/platform/renesas/rzg2l-cru/rzg2l-cru.h154
-rw-r--r--drivers/media/platform/renesas/rzg2l-cru/rzg2l-csi2.c875
-rw-r--r--drivers/media/platform/renesas/rzg2l-cru/rzg2l-ip.c255
-rw-r--r--drivers/media/platform/renesas/rzg2l-cru/rzg2l-video.c1058
-rw-r--r--drivers/media/platform/rockchip/rkisp1/rkisp1-params.c4
-rw-r--r--drivers/media/platform/samsung/exynos4-is/fimc-core.c2
-rw-r--r--drivers/media/platform/samsung/exynos4-is/media-dev.c14
-rw-r--r--drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c73
-rw-r--r--drivers/media/platform/samsung/s5p-mfc/s5p_mfc_ctrl.c4
-rw-r--r--drivers/media/platform/samsung/s5p-mfc/s5p_mfc_enc.c12
-rw-r--r--drivers/media/platform/samsung/s5p-mfc/s5p_mfc_opr_v6.c14
-rw-r--r--drivers/media/platform/st/sti/c8sectpfe/c8sectpfe-core.c9
-rw-r--r--drivers/media/platform/st/stm32/stm32-dcmi.c31
-rw-r--r--drivers/media/platform/sunxi/sun6i-csi/Makefile2
-rw-r--r--drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.c779
-rw-r--r--drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h145
-rw-r--r--drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c868
-rw-r--r--drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h69
-rw-r--r--drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.c1102
-rw-r--r--drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_capture.h89
-rw-r--r--drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_reg.h362
-rw-r--r--drivers/media/platform/sunxi/sun6i-csi/sun6i_video.c733
-rw-r--r--drivers/media/platform/sunxi/sun6i-csi/sun6i_video.h35
-rw-r--r--drivers/media/platform/sunxi/sun6i-mipi-csi2/sun6i_mipi_csi2.c23
-rw-r--r--drivers/media/platform/sunxi/sun8i-a83t-mipi-csi2/sun8i_a83t_mipi_csi2.c23
-rw-r--r--drivers/media/platform/ti/omap3isp/isp.c3
-rw-r--r--drivers/media/platform/xilinx/xilinx-csi2rxss.c8
-rw-r--r--drivers/media/radio/radio-tea5764.c5
-rw-r--r--drivers/media/radio/radio-terratec.c3
-rw-r--r--drivers/media/radio/saa7706h.c5
-rw-r--r--drivers/media/radio/si470x/radio-si470x-usb.c4
-rw-r--r--drivers/media/radio/tef6862.c5
-rw-r--r--drivers/media/rc/gpio-ir-recv.c10
-rw-r--r--drivers/media/rc/gpio-ir-tx.c9
-rw-r--r--drivers/media/rc/imon.c6
-rw-r--r--drivers/media/rc/ir-rx51.c9
-rw-r--r--drivers/media/rc/ir-spi.c7
-rw-r--r--drivers/media/test-drivers/Kconfig1
-rw-r--r--drivers/media/test-drivers/Makefile1
-rw-r--r--drivers/media/test-drivers/vidtv/vidtv_bridge.c22
-rw-r--r--drivers/media/test-drivers/vidtv/vidtv_demod.c13
-rw-r--r--drivers/media/test-drivers/vidtv/vidtv_tuner.c5
-rw-r--r--drivers/media/test-drivers/vimc/vimc-core.c2
-rw-r--r--drivers/media/test-drivers/visl/Kconfig29
-rw-r--r--drivers/media/test-drivers/visl/Makefile8
-rw-r--r--drivers/media/test-drivers/visl/visl-core.c541
-rw-r--r--drivers/media/test-drivers/visl/visl-debugfs.c112
-rw-r--r--drivers/media/test-drivers/visl/visl-debugfs.h40
-rw-r--r--drivers/media/test-drivers/visl/visl-dec.c499
-rw-r--r--drivers/media/test-drivers/visl/visl-dec.h67
-rw-r--r--drivers/media/test-drivers/visl/visl-trace-fwht.h66
-rw-r--r--drivers/media/test-drivers/visl/visl-trace-h264.h349
-rw-r--r--drivers/media/test-drivers/visl/visl-trace-hevc.h405
-rw-r--r--drivers/media/test-drivers/visl/visl-trace-mpeg2.h99
-rw-r--r--drivers/media/test-drivers/visl/visl-trace-points.c10
-rw-r--r--drivers/media/test-drivers/visl/visl-trace-vp8.h156
-rw-r--r--drivers/media/test-drivers/visl/visl-trace-vp9.h292
-rw-r--r--drivers/media/test-drivers/visl/visl-video.c767
-rw-r--r--drivers/media/test-drivers/visl/visl-video.h27
-rw-r--r--drivers/media/test-drivers/visl/visl.h176
-rw-r--r--drivers/media/test-drivers/vivid/vivid-ctrls.c28
-rw-r--r--drivers/media/test-drivers/vivid/vivid-kthread-cap.c2
-rw-r--r--drivers/media/test-drivers/vivid/vivid-kthread-out.c2
-rw-r--r--drivers/media/test-drivers/vivid/vivid-radio-rx.c4
-rw-r--r--drivers/media/test-drivers/vivid/vivid-sdr-cap.c2
-rw-r--r--drivers/media/test-drivers/vivid/vivid-touch-cap.c2
-rw-r--r--drivers/media/test-drivers/vivid/vivid-vbi-gen.c1
-rw-r--r--drivers/media/test-drivers/vivid/vivid-vid-cap.c1
-rw-r--r--drivers/media/tuners/e4000.c5
-rw-r--r--drivers/media/tuners/fc2580.c5
-rw-r--r--drivers/media/tuners/m88rs6000t.c5
-rw-r--r--drivers/media/tuners/mt2060.c5
-rw-r--r--drivers/media/tuners/mxl301rf.c5
-rw-r--r--drivers/media/tuners/mxl5005s.c2
-rw-r--r--drivers/media/tuners/qm1d1b0004.c4
-rw-r--r--drivers/media/tuners/qm1d1c0042.c5
-rw-r--r--drivers/media/tuners/tda18212.c5
-rw-r--r--drivers/media/tuners/tda18250.c5
-rw-r--r--drivers/media/tuners/tua9001.c5
-rw-r--r--drivers/media/usb/au0828/au0828-vbi.c2
-rw-r--r--drivers/media/usb/au0828/au0828-video.c1
-rw-r--r--drivers/media/usb/dvb-usb/az6027.c4
-rw-r--r--drivers/media/usb/dvb-usb/dib0700.h1
-rw-r--r--drivers/media/usb/dvb-usb/dib0700_devices.c7
-rw-r--r--drivers/media/usb/dvb-usb/dvb-usb-init.c6
-rw-r--r--drivers/media/usb/dvb-usb/m920x.c16
-rw-r--r--drivers/media/usb/em28xx/em28xx-dvb.c6
-rw-r--r--drivers/media/usb/go7007/s2250-board.c5
-rw-r--r--drivers/media/usb/pwc/pwc-uncompress.c2
-rw-r--r--drivers/media/usb/uvc/uvc_driver.c9
-rw-r--r--drivers/media/v4l2-core/tuner-core.c6
-rw-r--r--drivers/media/v4l2-core/v4l2-ctrls-core.c2
-rw-r--r--drivers/media/v4l2-core/v4l2-ctrls-defs.c2
-rw-r--r--drivers/media/v4l2-core/v4l2-dv-timings.c20
-rw-r--r--drivers/media/v4l2-core/v4l2-fwnode.c23
-rw-r--r--drivers/media/v4l2-core/v4l2-ioctl.c121
-rw-r--r--drivers/media/v4l2-core/v4l2-subdev.c17
-rw-r--r--drivers/media/v4l2-core/videobuf-dma-contig.c22
-rw-r--r--drivers/memory/Makefile2
-rw-r--r--drivers/memory/omap-gpmc.c122
-rw-r--r--drivers/memory/renesas-rpc-if.c22
-rw-r--r--drivers/memory/tegra/mc.c25
-rw-r--r--drivers/memory/tegra/tegra186-emc.c15
-rw-r--r--drivers/memory/tegra/tegra20-emc.c15
-rw-r--r--drivers/memory/tegra/tegra210-emc-core.c15
-rw-r--r--drivers/memory/tegra/tegra234.c165
-rw-r--r--drivers/memory/tegra/tegra30-emc.c15
-rw-r--r--drivers/memory/ti-emif-sram-pm.S1
-rw-r--r--drivers/memstick/core/ms_block.c9
-rw-r--r--drivers/memstick/core/mspro_block.c177
-rw-r--r--drivers/misc/fastrpc.c9
-rw-r--r--drivers/misc/mei/bus.c146
-rw-r--r--drivers/misc/mei/client.c55
-rw-r--r--drivers/misc/mei/hbm.c13
-rw-r--r--drivers/misc/mei/hw-me.c7
-rw-r--r--drivers/misc/mei/hw.h89
-rw-r--r--drivers/misc/mei/interrupt.c47
-rw-r--r--drivers/misc/mei/mei_dev.h8
-rw-r--r--drivers/misc/mei/pxp/mei_pxp.c38
-rw-r--r--drivers/misc/vmw_vmci/vmci_queue_pair.c6
-rw-r--r--drivers/mmc/core/block.c13
-rw-r--r--drivers/mmc/core/bus.c4
-rw-r--r--drivers/mmc/core/core.c11
-rw-r--r--drivers/mmc/core/core.h15
-rw-r--r--drivers/mmc/core/host.c6
-rw-r--r--drivers/mmc/core/mmc_test.c5
-rw-r--r--drivers/mmc/core/pwrseq.c2
-rw-r--r--drivers/mmc/core/sd.c11
-rw-r--r--drivers/mmc/host/Kconfig13
-rw-r--r--drivers/mmc/host/Makefile1
-rw-r--r--drivers/mmc/host/alcor.c5
-rw-r--r--drivers/mmc/host/atmel-mci.c9
-rw-r--r--drivers/mmc/host/au1xmmc.c8
-rw-r--r--drivers/mmc/host/bcm2835.c12
-rw-r--r--drivers/mmc/host/dw_mmc-pltfm.c41
-rw-r--r--drivers/mmc/host/dw_mmc.c7
-rw-r--r--drivers/mmc/host/litex_mmc.c1
-rw-r--r--drivers/mmc/host/meson-gx-mmc.c4
-rw-r--r--drivers/mmc/host/mmc_hsq.c40
-rw-r--r--drivers/mmc/host/mmc_hsq.h5
-rw-r--r--drivers/mmc/host/mmci.c4
-rw-r--r--drivers/mmc/host/moxart-mmc.c4
-rw-r--r--drivers/mmc/host/mtk-sd.c38
-rw-r--r--drivers/mmc/host/mxcmmc.c4
-rw-r--r--drivers/mmc/host/omap_hsmmc.c4
-rw-r--r--drivers/mmc/host/pxamci.c7
-rw-r--r--drivers/mmc/host/renesas_sdhi.h16
-rw-r--r--drivers/mmc/host/renesas_sdhi_core.c32
-rw-r--r--drivers/mmc/host/renesas_sdhi_internal_dmac.c86
-rw-r--r--drivers/mmc/host/renesas_sdhi_sys_dmac.c11
-rw-r--r--drivers/mmc/host/rtsx_pci_sdmmc.c9
-rw-r--r--drivers/mmc/host/rtsx_usb_sdmmc.c11
-rw-r--r--drivers/mmc/host/sdhci-acpi.c4
-rw-r--r--drivers/mmc/host/sdhci-bcm-kona.c2
-rw-r--r--drivers/mmc/host/sdhci-brcmstb.c2
-rw-r--r--drivers/mmc/host/sdhci-esdhc-imx.c87
-rw-r--r--drivers/mmc/host/sdhci-msm.c13
-rw-r--r--drivers/mmc/host/sdhci-of-arasan.c69
-rw-r--r--drivers/mmc/host/sdhci-of-esdhc.c11
-rw-r--r--drivers/mmc/host/sdhci-omap.c2
-rw-r--r--drivers/mmc/host/sdhci-pci-core.c14
-rw-r--r--drivers/mmc/host/sdhci-pci-gli.c11
-rw-r--r--drivers/mmc/host/sdhci-pci-o2micro.c3
-rw-r--r--drivers/mmc/host/sdhci-sprd.c16
-rw-r--r--drivers/mmc/host/sdhci-tegra.c77
-rw-r--r--drivers/mmc/host/sdhci.c85
-rw-r--r--drivers/mmc/host/sdhci.h4
-rw-r--r--drivers/mmc/host/sdhci_am654.c2
-rw-r--r--drivers/mmc/host/sdhci_f_sdh30.c31
-rw-r--r--drivers/mmc/host/sdhci_f_sdh30.h3
-rw-r--r--drivers/mmc/host/sunplus-mmc.c1000
-rw-r--r--drivers/mmc/host/tifm_sd.c28
-rw-r--r--drivers/mmc/host/tmio_mmc.h15
-rw-r--r--drivers/mmc/host/tmio_mmc_core.c18
-rw-r--r--drivers/mmc/host/toshsd.c6
-rw-r--r--drivers/mmc/host/via-sdmmc.c4
-rw-r--r--drivers/mmc/host/vub300.c13
-rw-r--r--drivers/mmc/host/wbsd.c22
-rw-r--r--drivers/mmc/host/wmt-sdmmc.c6
-rw-r--r--drivers/mtd/devices/Kconfig8
-rw-r--r--drivers/mtd/devices/Makefile1
-rw-r--r--drivers/mtd/devices/lart.c682
-rw-r--r--drivers/mtd/inftlcore.c2
-rw-r--r--drivers/mtd/lpddr/lpddr2_nvm.c2
-rw-r--r--drivers/mtd/maps/pxa2xx-flash.c2
-rw-r--r--drivers/mtd/mtdcore.c55
-rw-r--r--drivers/mtd/mtdoops.c109
-rw-r--r--drivers/mtd/nand/core.c3
-rw-r--r--drivers/mtd/nand/raw/Kconfig6
-rw-r--r--drivers/mtd/nand/raw/cadence-nand-controller.c70
-rw-r--r--drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c12
-rw-r--r--drivers/mtd/nand/raw/lpc32xx_mlc.c46
-rw-r--r--drivers/mtd/nand/raw/lpc32xx_slc.c43
-rw-r--r--drivers/mtd/nand/raw/marvell_nand.c4
-rw-r--r--drivers/mtd/nand/raw/mpc5121_nfc.c2
-rw-r--r--drivers/mtd/nand/raw/nandsim.c4
-rw-r--r--drivers/mtd/nand/spi/winbond.c79
-rw-r--r--drivers/mtd/parsers/Kconfig19
-rw-r--r--drivers/mtd/parsers/Makefile1
-rw-r--r--drivers/mtd/parsers/tplink_safeloader.c150
-rw-r--r--drivers/mtd/spi-nor/core.c85
-rw-r--r--drivers/mtd/spi-nor/core.h5
-rw-r--r--drivers/mtd/spi-nor/debugfs.c2
-rw-r--r--drivers/mtd/spi-nor/gigadevice.c24
-rw-r--r--drivers/mtd/spi-nor/issi.c5
-rw-r--r--drivers/mtd/spi-nor/micron-st.c12
-rw-r--r--drivers/mtd/spi-nor/sfdp.c37
-rw-r--r--drivers/mtd/spi-nor/sfdp.h2
-rw-r--r--drivers/mtd/spi-nor/spansion.c61
-rw-r--r--drivers/mtd/spi-nor/sysfs.c20
-rw-r--r--drivers/mtd/spi-nor/winbond.c3
-rw-r--r--drivers/mtd/tests/mtd_nandecctest.c10
-rw-r--r--drivers/mtd/tests/stresstest.c8
-rw-r--r--drivers/mtd/ubi/debug.c2
-rw-r--r--drivers/mtd/ubi/debug.h6
-rw-r--r--drivers/net/ethernet/broadcom/cnic.c8
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c4
-rw-r--r--drivers/net/fjes/fjes_main.c4
-rw-r--r--drivers/net/netconsole.c21
-rw-r--r--drivers/net/phy/at803x.c2
-rw-r--r--drivers/net/ppp/ppp_generic.c2
-rw-r--r--drivers/net/team/team_mode_random.c2
-rw-r--r--drivers/net/wireguard/selftest/allowedips.c20
-rw-r--r--drivers/net/wireguard/timers.c4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c2
-rw-r--r--drivers/nvdimm/Kconfig12
-rw-r--r--drivers/nvdimm/dimm_devs.c9
-rw-r--r--drivers/nvdimm/region.c11
-rw-r--r--drivers/nvdimm/region_devs.c50
-rw-r--r--drivers/nvdimm/security.c43
-rw-r--r--drivers/nvme/host/apple.c30
-rw-r--r--drivers/nvme/host/auth.c258
-rw-r--r--drivers/nvme/host/core.c327
-rw-r--r--drivers/nvme/host/fc.c59
-rw-r--r--drivers/nvme/host/ioctl.c118
-rw-r--r--drivers/nvme/host/multipath.c26
-rw-r--r--drivers/nvme/host/nvme.h69
-rw-r--r--drivers/nvme/host/pci.c606
-rw-r--r--drivers/nvme/host/rdma.c42
-rw-r--r--drivers/nvme/host/tcp.c49
-rw-r--r--drivers/nvme/target/admin-cmd.c11
-rw-r--r--drivers/nvme/target/configfs.c138
-rw-r--r--drivers/nvme/target/core.c44
-rw-r--r--drivers/nvme/target/io-cmd-file.c20
-rw-r--r--drivers/nvme/target/loop.c16
-rw-r--r--drivers/nvme/target/nvmet.h6
-rw-r--r--drivers/nvme/target/tcp.c2
-rw-r--r--drivers/nvmem/brcm_nvram.c3
-rw-r--r--drivers/of/kexec.c10
-rw-r--r--drivers/of/overlay.c4
-rw-r--r--drivers/of/platform.c5
-rw-r--r--drivers/of/unittest-data/Makefile66
-rw-r--r--drivers/of/unittest-data/overlay.dtso (renamed from drivers/of/unittest-data/overlay.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_0.dtso (renamed from drivers/of/unittest-data/overlay_0.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_1.dtso (renamed from drivers/of/unittest-data/overlay_1.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_10.dtso (renamed from drivers/of/unittest-data/overlay_10.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_11.dtso (renamed from drivers/of/unittest-data/overlay_11.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_12.dtso (renamed from drivers/of/unittest-data/overlay_12.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_13.dtso (renamed from drivers/of/unittest-data/overlay_13.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_15.dtso (renamed from drivers/of/unittest-data/overlay_15.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_16.dtso (renamed from drivers/of/unittest-data/overlay_16.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_17.dtso (renamed from drivers/of/unittest-data/overlay_17.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_18.dtso (renamed from drivers/of/unittest-data/overlay_18.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_19.dtso (renamed from drivers/of/unittest-data/overlay_19.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_2.dtso (renamed from drivers/of/unittest-data/overlay_2.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_20.dtso (renamed from drivers/of/unittest-data/overlay_20.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_3.dtso (renamed from drivers/of/unittest-data/overlay_3.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_4.dtso (renamed from drivers/of/unittest-data/overlay_4.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_5.dtso (renamed from drivers/of/unittest-data/overlay_5.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_6.dtso (renamed from drivers/of/unittest-data/overlay_6.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_7.dtso (renamed from drivers/of/unittest-data/overlay_7.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_8.dtso (renamed from drivers/of/unittest-data/overlay_8.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_9.dtso (renamed from drivers/of/unittest-data/overlay_9.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_bad_add_dup_node.dtso (renamed from drivers/of/unittest-data/overlay_bad_add_dup_node.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_bad_add_dup_prop.dtso (renamed from drivers/of/unittest-data/overlay_bad_add_dup_prop.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_bad_phandle.dtso (renamed from drivers/of/unittest-data/overlay_bad_phandle.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_bad_symbol.dtso (renamed from drivers/of/unittest-data/overlay_bad_symbol.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_base.dtso (renamed from drivers/of/unittest-data/overlay_base.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_gpio_01.dtso (renamed from drivers/of/unittest-data/overlay_gpio_01.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_gpio_02a.dtso (renamed from drivers/of/unittest-data/overlay_gpio_02a.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_gpio_02b.dtso (renamed from drivers/of/unittest-data/overlay_gpio_02b.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_gpio_03.dtso (renamed from drivers/of/unittest-data/overlay_gpio_03.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_gpio_04a.dtso (renamed from drivers/of/unittest-data/overlay_gpio_04a.dts)0
-rw-r--r--drivers/of/unittest-data/overlay_gpio_04b.dtso (renamed from drivers/of/unittest-data/overlay_gpio_04b.dts)0
-rw-r--r--drivers/of/unittest-data/testcases.dtso (renamed from drivers/of/unittest-data/testcases.dts)0
-rw-r--r--drivers/of/unittest.c58
-rw-r--r--drivers/opp/of.c228
-rw-r--r--drivers/pci/Kconfig7
-rw-r--r--drivers/pci/controller/Kconfig30
-rw-r--r--drivers/pci/controller/dwc/Kconfig48
-rw-r--r--drivers/pci/controller/mobiveil/Kconfig6
-rw-r--r--drivers/pci/controller/pci-hyperv.c21
-rw-r--r--drivers/pci/msi/Makefile3
-rw-r--r--drivers/pci/msi/api.c458
-rw-r--r--drivers/pci/msi/irqdomain.c369
-rw-r--r--drivers/pci/msi/msi.c1078
-rw-r--r--drivers/pci/msi/msi.h114
-rw-r--r--drivers/pci/p2pdma.c126
-rw-r--r--drivers/pci/pci-sysfs.c7
-rw-r--r--drivers/pci/pcie/aer.c8
-rw-r--r--drivers/pci/probe.c8
-rw-r--r--drivers/perf/Kconfig6
-rw-r--r--drivers/perf/Makefile2
-rw-r--r--drivers/perf/amlogic/Kconfig10
-rw-r--r--drivers/perf/amlogic/Makefile5
-rw-r--r--drivers/perf/amlogic/meson_ddr_pmu_core.c561
-rw-r--r--drivers/perf/amlogic/meson_g12_ddr_pmu.c394
-rw-r--r--drivers/perf/arm_cspmu/Kconfig13
-rw-r--r--drivers/perf/arm_cspmu/Makefile6
-rw-r--r--drivers/perf/arm_cspmu/arm_cspmu.c1303
-rw-r--r--drivers/perf/arm_cspmu/arm_cspmu.h151
-rw-r--r--drivers/perf/arm_cspmu/nvidia_cspmu.c400
-rw-r--r--drivers/perf/arm_cspmu/nvidia_cspmu.h17
-rw-r--r--drivers/perf/arm_dmc620_pmu.c8
-rw-r--r--drivers/perf/arm_dsu_pmu.c6
-rw-r--r--drivers/perf/arm_pmu.c36
-rw-r--r--drivers/perf/arm_pmu_acpi.c114
-rw-r--r--drivers/perf/arm_smmuv3_pmu.c8
-rw-r--r--drivers/perf/hisilicon/hisi_pcie_pmu.c22
-rw-r--r--drivers/perf/marvell_cn10k_tad_pmu.c6
-rw-r--r--drivers/phy/phy-core-mipi-dphy.c31
-rw-r--r--drivers/pinctrl/Kconfig11
-rw-r--r--drivers/pinctrl/Makefile1
-rw-r--r--drivers/pinctrl/actions/pinctrl-owl.c49
-rw-r--r--drivers/pinctrl/aspeed/pinctrl-aspeed.c1
-rw-r--r--drivers/pinctrl/bcm/pinctrl-bcm281xx.c13
-rw-r--r--drivers/pinctrl/bcm/pinctrl-cygnus-mux.c9
-rw-r--r--drivers/pinctrl/bcm/pinctrl-iproc-gpio.c12
-rw-r--r--drivers/pinctrl/bcm/pinctrl-ns2-mux.c8
-rw-r--r--drivers/pinctrl/bcm/pinctrl-nsp-mux.c8
-rw-r--r--drivers/pinctrl/cirrus/pinctrl-lochnagar.c6
-rw-r--r--drivers/pinctrl/cirrus/pinctrl-madera-core.c5
-rw-r--r--drivers/pinctrl/core.c25
-rw-r--r--drivers/pinctrl/core.h22
-rw-r--r--drivers/pinctrl/devicetree.h6
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx.c8
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imx1-core.c4
-rw-r--r--drivers/pinctrl/freescale/pinctrl-imxrt1050.c546
-rw-r--r--drivers/pinctrl/freescale/pinctrl-mxs.c7
-rw-r--r--drivers/pinctrl/freescale/pinctrl-scu.c30
-rw-r--r--drivers/pinctrl/intel/Kconfig11
-rw-r--r--drivers/pinctrl/intel/Makefile1
-rw-r--r--drivers/pinctrl/intel/pinctrl-alderlake.c40
-rw-r--r--drivers/pinctrl/intel/pinctrl-cannonlake.c8
-rw-r--r--drivers/pinctrl/intel/pinctrl-cherryview.c6
-rw-r--r--drivers/pinctrl/intel/pinctrl-icelake.c8
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.c61
-rw-r--r--drivers/pinctrl/intel/pinctrl-lynxpoint.c6
-rw-r--r--drivers/pinctrl/intel/pinctrl-merrifield.c19
-rw-r--r--drivers/pinctrl/intel/pinctrl-moorefield.c916
-rw-r--r--drivers/pinctrl/intel/pinctrl-sunrisepoint.c32
-rw-r--r--drivers/pinctrl/intel/pinctrl-tigerlake.c28
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-moore.c52
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mt7986.c112
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mt8365.c18
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mtk-common.c21
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-mtk-common.h8
-rw-r--r--drivers/pinctrl/mediatek/pinctrl-paris.c5
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-mvebu.c14
-rw-r--r--drivers/pinctrl/nuvoton/pinctrl-npcm7xx.c11
-rw-r--r--drivers/pinctrl/nuvoton/pinctrl-wpcm450.c48
-rw-r--r--drivers/pinctrl/pinconf-generic.c4
-rw-r--r--drivers/pinctrl/pinconf.h10
-rw-r--r--drivers/pinctrl/pinctrl-amd.c10
-rw-r--r--drivers/pinctrl/pinctrl-apple-gpio.c7
-rw-r--r--drivers/pinctrl/pinctrl-at91-pio4.c36
-rw-r--r--drivers/pinctrl/pinctrl-at91.c16
-rw-r--r--drivers/pinctrl/pinctrl-axp209.c8
-rw-r--r--drivers/pinctrl/pinctrl-bm1880.c6
-rw-r--r--drivers/pinctrl/pinctrl-cy8c95x0.c134
-rw-r--r--drivers/pinctrl/pinctrl-falcon.c9
-rw-r--r--drivers/pinctrl/pinctrl-gemini.c12
-rw-r--r--drivers/pinctrl/pinctrl-ingenic.c10
-rw-r--r--drivers/pinctrl/pinctrl-k210.c16
-rw-r--r--drivers/pinctrl/pinctrl-lantiq.c5
-rw-r--r--drivers/pinctrl/pinctrl-lantiq.h7
-rw-r--r--drivers/pinctrl/pinctrl-loongson2.c311
-rw-r--r--drivers/pinctrl/pinctrl-lpc18xx.c6
-rw-r--r--drivers/pinctrl/pinctrl-microchip-sgpio.c4
-rw-r--r--drivers/pinctrl/pinctrl-ocelot.c30
-rw-r--r--drivers/pinctrl/pinctrl-single.c6
-rw-r--r--drivers/pinctrl/pinctrl-st.c25
-rw-r--r--drivers/pinctrl/pinctrl-stmfx.c2
-rw-r--r--drivers/pinctrl/pinctrl-thunderbay.c8
-rw-r--r--drivers/pinctrl/pinctrl-utils.h5
-rw-r--r--drivers/pinctrl/pinctrl-zynqmp.c5
-rw-r--r--drivers/pinctrl/pinmux.c17
-rw-r--r--drivers/pinctrl/pinmux.h11
-rw-r--r--drivers/pinctrl/qcom/Kconfig10
-rw-r--r--drivers/pinctrl/qcom/Makefile1
-rw-r--r--drivers/pinctrl/qcom/pinctrl-lpass-lpi.c5
-rw-r--r--drivers/pinctrl/qcom/pinctrl-lpass-lpi.h9
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm.c29
-rw-r--r--drivers/pinctrl/qcom/pinctrl-msm.h5
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdm670.c1345
-rw-r--r--drivers/pinctrl/qcom/pinctrl-spmi-gpio.c8
-rw-r--r--drivers/pinctrl/qcom/pinctrl-spmi-mpp.c8
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c19
-rw-r--r--drivers/pinctrl/qcom/pinctrl-ssbi-mpp.c19
-rw-r--r--drivers/pinctrl/renesas/gpio.c10
-rw-r--r--drivers/pinctrl/renesas/pinctrl-rzg2l.c10
-rw-r--r--drivers/pinctrl/renesas/pinctrl-rzn1.c8
-rw-r--r--drivers/pinctrl/renesas/pinctrl-rzv2m.c7
-rw-r--r--drivers/pinctrl/renesas/pinctrl.c8
-rw-r--r--drivers/pinctrl/samsung/pinctrl-samsung.c11
-rw-r--r--drivers/pinctrl/spear/pinctrl-spear.c6
-rw-r--r--drivers/pinctrl/sprd/pinctrl-sprd.c7
-rw-r--r--drivers/pinctrl/starfive/pinctrl-starfive-jh7100.c7
-rw-r--r--drivers/pinctrl/stm32/pinctrl-stm32.c21
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c4
-rw-r--r--drivers/pinctrl/sunxi/pinctrl-sunxi.c18
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra-xusb.c7
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra.c39
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra.h2
-rw-r--r--drivers/pinctrl/tegra/pinctrl-tegra194.c286
-rw-r--r--drivers/pinctrl/ti/pinctrl-ti-iodelay.c8
-rw-r--r--drivers/pinctrl/uniphier/pinctrl-uniphier-core.c8
-rw-r--r--drivers/platform/Kconfig2
-rw-r--r--drivers/platform/chrome/Kconfig10
-rw-r--r--drivers/platform/chrome/Makefile1
-rw-r--r--drivers/platform/chrome/chromeos_privacy_screen.c3
-rw-r--r--drivers/platform/chrome/cros_ec_debugfs.c1
-rw-r--r--drivers/platform/chrome/cros_ec_i2c.c5
-rw-r--r--drivers/platform/chrome/cros_ec_lightbar.c4
-rw-r--r--drivers/platform/chrome/cros_ec_lpc.c15
-rw-r--r--drivers/platform/chrome/cros_ec_lpc_mec.c6
-rw-r--r--drivers/platform/chrome/cros_ec_lpc_mec.h7
-rw-r--r--drivers/platform/chrome/cros_ec_spi.c1
-rw-r--r--drivers/platform/chrome/cros_ec_typec.c3
-rw-r--r--drivers/platform/chrome/cros_hps_i2c.c160
-rw-r--r--drivers/platform/chrome/cros_usbpd_notify.c6
-rw-r--r--drivers/platform/chrome/wilco_ec/core.c5
-rw-r--r--drivers/platform/chrome/wilco_ec/event.c4
-rw-r--r--drivers/platform/mellanox/mlxbf-pmc.c2
-rw-r--r--drivers/platform/mellanox/mlxbf-tmfifo-regs.h10
-rw-r--r--drivers/platform/mellanox/mlxbf-tmfifo.c86
-rw-r--r--drivers/platform/mips/Kconfig1
-rw-r--r--drivers/platform/surface/surfacepro3_button.c3
-rw-r--r--drivers/platform/x86/Kconfig43
-rw-r--r--drivers/platform/x86/Makefile4
-rw-r--r--drivers/platform/x86/amd/pmf/cnqf.c92
-rw-r--r--drivers/platform/x86/asus-laptop.c3
-rw-r--r--drivers/platform/x86/asus-wireless.c3
-rw-r--r--drivers/platform/x86/asus-wmi.c4
-rw-r--r--drivers/platform/x86/classmate-laptop.c20
-rw-r--r--drivers/platform/x86/dell/Kconfig13
-rw-r--r--drivers/platform/x86/dell/Makefile1
-rw-r--r--drivers/platform/x86/dell/alienware-wmi.c41
-rw-r--r--drivers/platform/x86/dell/dell-rbtn.c6
-rw-r--r--drivers/platform/x86/dell/dell-wmi-ddv.c375
-rw-r--r--drivers/platform/x86/eeepc-laptop.c3
-rw-r--r--drivers/platform/x86/fujitsu-laptop.c4
-rw-r--r--drivers/platform/x86/fujitsu-tablet.c3
-rw-r--r--drivers/platform/x86/hp/Kconfig63
-rw-r--r--drivers/platform/x86/hp/Makefile10
-rw-r--r--drivers/platform/x86/hp/hp-wmi.c (renamed from drivers/platform/x86/hp-wmi.c)0
-rw-r--r--drivers/platform/x86/hp/hp_accel.c (renamed from drivers/platform/x86/hp_accel.c)2
-rw-r--r--drivers/platform/x86/hp/tc1100-wmi.c (renamed from drivers/platform/x86/tc1100-wmi.c)0
-rw-r--r--drivers/platform/x86/huawei-wmi.c51
-rw-r--r--drivers/platform/x86/ideapad-laptop.c388
-rw-r--r--drivers/platform/x86/intel/Kconfig8
-rw-r--r--drivers/platform/x86/intel/hid.c36
-rw-r--r--drivers/platform/x86/intel/ifs/Kconfig4
-rw-r--r--drivers/platform/x86/intel/ifs/core.c23
-rw-r--r--drivers/platform/x86/intel/ifs/ifs.h30
-rw-r--r--drivers/platform/x86/intel/ifs/load.c218
-rw-r--r--drivers/platform/x86/intel/ifs/runtest.c10
-rw-r--r--drivers/platform/x86/intel/ifs/sysfs.c41
-rw-r--r--drivers/platform/x86/intel/int3472/clk_and_regulator.c3
-rw-r--r--drivers/platform/x86/intel/pmc/Makefile3
-rw-r--r--drivers/platform/x86/intel/pmc/adl.c325
-rw-r--r--drivers/platform/x86/intel/pmc/cnp.c210
-rw-r--r--drivers/platform/x86/intel/pmc/core.c994
-rw-r--r--drivers/platform/x86/intel/pmc/core.h91
-rw-r--r--drivers/platform/x86/intel/pmc/icl.c56
-rw-r--r--drivers/platform/x86/intel/pmc/mtl.c52
-rw-r--r--drivers/platform/x86/intel/pmc/spt.c140
-rw-r--r--drivers/platform/x86/intel/pmc/tgl.c269
-rw-r--r--drivers/platform/x86/intel/rst.c4
-rw-r--r--drivers/platform/x86/intel/sdsi.c136
-rw-r--r--drivers/platform/x86/intel/speed_select_if/isst_if_common.c2
-rw-r--r--drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c1
-rw-r--r--drivers/platform/x86/intel_scu_ipc.c2
-rw-r--r--drivers/platform/x86/lg-laptop.c8
-rw-r--r--drivers/platform/x86/mxm-wmi.c8
-rw-r--r--drivers/platform/x86/panasonic-laptop.c8
-rw-r--r--drivers/platform/x86/sony-laptop.c19
-rw-r--r--drivers/platform/x86/system76_acpi.c8
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c63
-rw-r--r--drivers/platform/x86/topstar-laptop.c3
-rw-r--r--drivers/platform/x86/toshiba_acpi.c8
-rw-r--r--drivers/platform/x86/toshiba_bluetooth.c6
-rw-r--r--drivers/platform/x86/toshiba_haps.c4
-rw-r--r--drivers/platform/x86/uv_sysfs.c16
-rw-r--r--drivers/platform/x86/wireless-hotkey.c63
-rw-r--r--drivers/platform/x86/wmi.c1
-rw-r--r--drivers/platform/x86/x86-android-tablets.c285
-rw-r--r--drivers/platform/x86/xo15-ebook.c3
-rw-r--r--drivers/pnp/core.c4
-rw-r--r--drivers/pnp/driver.c3
-rw-r--r--drivers/powercap/Kconfig13
-rw-r--r--drivers/powercap/Makefile1
-rw-r--r--drivers/powercap/arm_scmi_powercap.c509
-rw-r--r--drivers/powercap/idle_inject.c3
-rw-r--r--drivers/powercap/powercap_sys.c3
-rw-r--r--drivers/ptp/ptp_vmw.c3
-rw-r--r--drivers/pwm/pwm-lpss-pci.c2
-rw-r--r--drivers/pwm/pwm-lpss-platform.c2
-rw-r--r--drivers/pwm/pwm-lpss.c8
-rw-r--r--drivers/pwm/pwm-lpss.h26
-rw-r--r--drivers/rapidio/devices/rio_mport_cdev.c15
-rw-r--r--drivers/rapidio/devices/tsi721.c3
-rw-r--r--drivers/rapidio/rio-scan.c8
-rw-r--r--drivers/rapidio/rio.c9
-rw-r--r--drivers/ras/debugfs.c2
-rw-r--r--drivers/regulator/Kconfig30
-rw-r--r--drivers/regulator/Makefile2
-rw-r--r--drivers/regulator/act8865-regulator.c6
-rw-r--r--drivers/regulator/ad5398.c6
-rw-r--r--drivers/regulator/arizona-micsupp.c20
-rw-r--r--drivers/regulator/bd71815-regulator.c10
-rw-r--r--drivers/regulator/bd71828-regulator.c21
-rw-r--r--drivers/regulator/bd718x7-regulator.c53
-rw-r--r--drivers/regulator/bd9576-regulator.c54
-rw-r--r--drivers/regulator/core.c63
-rw-r--r--drivers/regulator/da9121-regulator.c5
-rw-r--r--drivers/regulator/devres.c68
-rw-r--r--drivers/regulator/fan53555.c6
-rw-r--r--drivers/regulator/fan53880.c16
-rw-r--r--drivers/regulator/internal.h2
-rw-r--r--drivers/regulator/isl6271a-regulator.c6
-rw-r--r--drivers/regulator/lp3972.c5
-rw-r--r--drivers/regulator/lp872x.c5
-rw-r--r--drivers/regulator/lp8755.c5
-rw-r--r--drivers/regulator/ltc3589.c6
-rw-r--r--drivers/regulator/max1586.c5
-rw-r--r--drivers/regulator/max8649.c5
-rw-r--r--drivers/regulator/max8660.c6
-rw-r--r--drivers/regulator/max8952.c5
-rw-r--r--drivers/regulator/max8973-regulator.c6
-rw-r--r--drivers/regulator/mp886x.c2
-rw-r--r--drivers/regulator/mt6357-regulator.c453
-rw-r--r--drivers/regulator/of_regulator.c94
-rw-r--r--drivers/regulator/pca9450-regulator.c5
-rw-r--r--drivers/regulator/pfuze100-regulator.c6
-rw-r--r--drivers/regulator/pv88080-regulator.c6
-rw-r--r--drivers/regulator/qcom-labibb-regulator.c1
-rw-r--r--drivers/regulator/qcom-rpmh-regulator.c83
-rw-r--r--drivers/regulator/qcom_smd-regulator.c33
-rw-r--r--drivers/regulator/rk808-regulator.c26
-rw-r--r--drivers/regulator/rpi-panel-attiny-regulator.c5
-rw-r--r--drivers/regulator/rt6190-regulator.c495
-rw-r--r--drivers/regulator/stm32-vrefbuf.c2
-rw-r--r--drivers/regulator/sy8106a-regulator.c4
-rw-r--r--drivers/regulator/sy8824x.c2
-rw-r--r--drivers/regulator/sy8827n.c4
-rw-r--r--drivers/regulator/tps51632-regulator.c5
-rw-r--r--drivers/regulator/tps62360-regulator.c6
-rw-r--r--drivers/regulator/tps6286x-regulator.c5
-rw-r--r--drivers/regulator/tps65023-regulator.c6
-rw-r--r--drivers/regulator/userspace-consumer.c60
-rw-r--r--drivers/s390/char/con3215.c275
-rw-r--r--drivers/s390/char/raw3270.c12
-rw-r--r--drivers/s390/char/sclp.c25
-rw-r--r--drivers/s390/char/sclp.h2
-rw-r--r--drivers/s390/char/sclp_early.c4
-rw-r--r--drivers/s390/char/sclp_early_core.c26
-rw-r--r--drivers/s390/char/zcore.c6
-rw-r--r--drivers/s390/cio/chsc_sch.c3
-rw-r--r--drivers/s390/cio/cio.c14
-rw-r--r--drivers/s390/cio/device.c2
-rw-r--r--drivers/s390/cio/device_fsm.c13
-rw-r--r--drivers/s390/cio/device_id.c2
-rw-r--r--drivers/s390/cio/device_pgid.c11
-rw-r--r--drivers/s390/cio/device_status.c3
-rw-r--r--drivers/s390/cio/eadm_sch.c9
-rw-r--r--drivers/s390/cio/fcx.c23
-rw-r--r--drivers/s390/cio/itcw.c3
-rw-r--r--drivers/s390/cio/vfio_ccw_cp.c4
-rw-r--r--drivers/s390/cio/vfio_ccw_fsm.c2
-rw-r--r--drivers/s390/net/ism_drv.c3
-rw-r--r--drivers/s390/scsi/zfcp_fc.c2
-rw-r--r--drivers/sbus/char/envctrl.c4
-rw-r--r--drivers/scsi/fcoe/fcoe_ctlr.c4
-rw-r--r--drivers/scsi/libsas/sas_ata.c2
-rw-r--r--drivers/scsi/qedi/qedi_main.c2
-rw-r--r--drivers/scsi/scsi_debug.c6
-rw-r--r--drivers/scsi/scsi_error.c2
-rw-r--r--drivers/scsi/scsi_lib.c2
-rw-r--r--drivers/scsi/scsi_scan.c1
-rw-r--r--drivers/scsi/sg.c2
-rw-r--r--drivers/soc/Kconfig1
-rw-r--r--drivers/soc/Makefile1
-rw-r--r--drivers/soc/apple/rtkit.c7
-rw-r--r--drivers/soc/apple/sart.c7
-rw-r--r--drivers/soc/bcm/brcmstb/pm/Makefile1
-rw-r--r--drivers/soc/bcm/brcmstb/pm/s2-arm.S1
-rw-r--r--drivers/soc/fsl/dpio/dpio-driver.c1
-rw-r--r--drivers/soc/fsl/qe/gpio.c81
-rw-r--r--drivers/soc/imx/gpcv2.c3
-rw-r--r--drivers/soc/imx/imx8m-blk-ctrl.c11
-rw-r--r--drivers/soc/loongson/Kconfig18
-rw-r--r--drivers/soc/loongson/Makefile6
-rw-r--r--drivers/soc/loongson/loongson2_guts.c192
-rw-r--r--drivers/soc/mediatek/mt8186-mmsys.h8
-rw-r--r--drivers/soc/mediatek/mtk-mmsys.c176
-rw-r--r--drivers/soc/mediatek/mtk-mmsys.h6
-rw-r--r--drivers/soc/mediatek/mtk-pmic-wrap.c114
-rw-r--r--drivers/soc/pxa/ssp.c4
-rw-r--r--drivers/soc/qcom/Kconfig2
-rw-r--r--drivers/soc/qcom/apr.c15
-rw-r--r--drivers/soc/qcom/cmd-db.c2
-rw-r--r--drivers/soc/qcom/llcc-qcom.c168
-rw-r--r--drivers/soc/qcom/pdr_internal.h20
-rw-r--r--drivers/soc/qcom/qcom_stats.c2
-rw-r--r--drivers/soc/qcom/rpmh-internal.h20
-rw-r--r--drivers/soc/qcom/rpmh-rsc.c321
-rw-r--r--drivers/soc/qcom/rpmh.c14
-rw-r--r--drivers/soc/qcom/rpmhpd.c95
-rw-r--r--drivers/soc/qcom/rpmpd.c18
-rw-r--r--drivers/soc/qcom/smd-rpm.c3
-rw-r--r--drivers/soc/qcom/smp2p.c2
-rw-r--r--drivers/soc/qcom/socinfo.c280
-rw-r--r--drivers/soc/qcom/spm.c46
-rw-r--r--drivers/soc/qcom/trace-rpmh.h11
-rw-r--r--drivers/soc/renesas/Kconfig2
-rw-r--r--drivers/soc/renesas/renesas-soc.c22
-rw-r--r--drivers/soc/sifive/sifive_ccache.c33
-rw-r--r--drivers/soc/tegra/Kconfig1
-rw-r--r--drivers/soc/tegra/cbb/tegra-cbb.c13
-rw-r--r--drivers/soc/tegra/cbb/tegra194-cbb.c18
-rw-r--r--drivers/soc/tegra/cbb/tegra234-cbb.c170
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra.c134
-rw-r--r--drivers/soc/tegra/fuse/fuse-tegra30.c278
-rw-r--r--drivers/soc/tegra/fuse/fuse.h4
-rw-r--r--drivers/soc/tegra/fuse/tegra-apbmisc.c1
-rw-r--r--drivers/soc/tegra/pmc.c878
-rw-r--r--drivers/soc/ti/Kconfig4
-rw-r--r--drivers/soc/ti/k3-ringacc.c28
-rw-r--r--drivers/soc/ti/k3-socinfo.c1
-rw-r--r--drivers/soc/ti/knav_qmss_queue.c3
-rw-r--r--drivers/soc/ti/smartreflex.c1
-rw-r--r--drivers/soc/ti/ti_sci_inta_msi.c12
-rw-r--r--drivers/soc/ux500/ux500-soc-id.c10
-rw-r--r--drivers/soundwire/intel_init.c37
-rw-r--r--drivers/spi/Kconfig31
-rw-r--r--drivers/spi/Makefile3
-rw-r--r--drivers/spi/atmel-quadspi.c34
-rw-r--r--drivers/spi/spi-aspeed-smc.c6
-rw-r--r--drivers/spi/spi-bcm-qspi.c5
-rw-r--r--drivers/spi/spi-bcm-qspi.h2
-rw-r--r--drivers/spi/spi-bcm63xx.c3
-rw-r--r--drivers/spi/spi-brcmstb-qspi.c4
-rw-r--r--drivers/spi/spi-cadence-quadspi.c15
-rw-r--r--drivers/spi/spi-cadence-xspi.c4
-rw-r--r--drivers/spi/spi-fsl-cpm.c2
-rw-r--r--drivers/spi/spi-fsl-dspi.c36
-rw-r--r--drivers/spi/spi-fsl-lpspi.c5
-rw-r--r--drivers/spi/spi-gpio.c16
-rw-r--r--drivers/spi/spi-hisi-sfc-v3xx.c2
-rw-r--r--drivers/spi/spi-img-spfi.c3
-rw-r--r--drivers/spi/spi-imx.c8
-rw-r--r--drivers/spi/spi-intel.c78
-rw-r--r--drivers/spi/spi-iproc-qspi.c4
-rw-r--r--drivers/spi/spi-meson-spicc.c39
-rw-r--r--drivers/spi/spi-microchip-core.c9
-rw-r--r--drivers/spi/spi-mt65xx.c12
-rw-r--r--drivers/spi/spi-mtk-nor.c69
-rw-r--r--drivers/spi/spi-mtk-snfi.c29
-rw-r--r--drivers/spi/spi-mxic.c3
-rw-r--r--drivers/spi/spi-npcm-fiu.c4
-rw-r--r--drivers/spi/spi-nxp-fspi.c2
-rw-r--r--drivers/spi/spi-pci1xxxx.c475
-rw-r--r--drivers/spi/spi-pxa2xx.c195
-rw-r--r--drivers/spi/spi-sc18is602.c6
-rw-r--r--drivers/spi/spi-sn-f-ospi.c703
-rw-r--r--drivers/spi/spi-wpcm-fiu.c508
-rw-r--r--drivers/spi/spi-xcomm.c5
-rw-r--r--drivers/spi/spi-zynqmp-gqspi.c191
-rw-r--r--drivers/spi/spi.c70
-rw-r--r--drivers/spi/spidev.c21
-rw-r--r--drivers/staging/media/Kconfig1
-rw-r--r--drivers/staging/media/Makefile1
-rw-r--r--drivers/staging/media/atomisp/i2c/atomisp-gc0310.c14
-rw-r--r--drivers/staging/media/atomisp/i2c/gc0310.h1
-rw-r--r--drivers/staging/media/atomisp/i2c/ov2680.h46
-rw-r--r--drivers/staging/media/atomisp/include/hmm/hmm.h3
-rw-r--r--drivers/staging/media/atomisp/include/hmm/hmm_bo.h4
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_cmd.c442
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_cmd.h17
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_common.h6
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_compat.h14
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_compat_css20.c96
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_fops.c535
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_fops.h13
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_internal.h1
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_ioctl.c615
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_ioctl.h10
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_subdev.c2
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_subdev.h22
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_v4l2.c104
-rw-r--r--drivers/staging/media/atomisp/pci/camera/pipe/interface/ia_css_pipe_binarydesc.h13
-rw-r--r--drivers/staging/media/atomisp/pci/camera/pipe/interface/ia_css_pipe_stagedesc.h5
-rw-r--r--drivers/staging/media/atomisp/pci/camera/pipe/src/pipe_binarydesc.c55
-rw-r--r--drivers/staging/media/atomisp/pci/camera/pipe/src/pipe_stagedesc.c21
-rw-r--r--drivers/staging/media/atomisp/pci/css_2401_system/host/pixelgen_private.h2
-rw-r--r--drivers/staging/media/atomisp/pci/hive_types.h2
-rw-r--r--drivers/staging/media/atomisp/pci/hmm/hmm.c20
-rw-r--r--drivers/staging/media/atomisp/pci/hmm/hmm_bo.c64
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_frame_public.h108
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_pipe.h3
-rw-r--r--drivers/staging/media/atomisp/pci/ia_css_pipe_public.h69
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/bayer_io_ls/ia_css_bayer_io.host.c10
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ipu2_io_ls/yuv444_io_ls/ia_css_yuv444_io.host.c10
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/ref/ref_1.0/ia_css_ref.host.c2
-rw-r--r--drivers/staging/media/atomisp/pci/isp/kernels/tnr/tnr_1.0/ia_css_tnr.host.c4
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/binary/src/binary.c42
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/debug/src/ia_css_debug.c33
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/frame/src/frame.c203
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/pipeline/interface/ia_css_pipeline.h2
-rw-r--r--drivers/staging/media/atomisp/pci/runtime/pipeline/src/pipeline.c8
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css.c646
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_internal.h13
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_legacy.h1
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_param_shading.c19
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_params.c17
-rw-r--r--drivers/staging/media/atomisp/pci/sh_css_sp.c54
-rw-r--r--drivers/staging/media/deprecated/atmel/Kconfig47
-rw-r--r--drivers/staging/media/deprecated/atmel/Makefile8
-rw-r--r--drivers/staging/media/deprecated/atmel/TODO34
-rw-r--r--drivers/staging/media/deprecated/atmel/atmel-isc-base.c (renamed from drivers/media/platform/atmel/atmel-isc-base.c)20
-rw-r--r--drivers/staging/media/deprecated/atmel/atmel-isc-clk.c (renamed from drivers/media/platform/atmel/atmel-isc-clk.c)8
-rw-r--r--drivers/staging/media/deprecated/atmel/atmel-isc-regs.h (renamed from drivers/media/platform/atmel/atmel-isc-regs.h)0
-rw-r--r--drivers/staging/media/deprecated/atmel/atmel-isc.h (renamed from drivers/media/platform/atmel/atmel-isc.h)16
-rw-r--r--drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c (renamed from drivers/media/platform/atmel/atmel-sama5d2-isc.c)18
-rw-r--r--drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c (renamed from drivers/media/platform/atmel/atmel-sama7g5-isc.c)18
-rw-r--r--drivers/staging/media/deprecated/stkwebcam/Kconfig2
-rw-r--r--drivers/staging/media/imx/Kconfig17
-rw-r--r--drivers/staging/media/imx/Makefile3
-rw-r--r--drivers/staging/media/imx/TODO41
-rw-r--r--drivers/staging/media/imx/imx-media-csi.c135
-rw-r--r--drivers/staging/media/imx/imx-media-fim.c57
-rw-r--r--drivers/staging/media/imx/imx-media-utils.c33
-rw-r--r--drivers/staging/media/imx/imx-media.h1
-rw-r--r--drivers/staging/media/ipu3/ipu3-v4l2.c57
-rw-r--r--drivers/staging/media/meson/vdec/codec_vp9.c10
-rw-r--r--drivers/staging/media/omap4iss/iss_video.c2
-rw-r--r--drivers/staging/media/omap4iss/iss_video.h18
-rw-r--r--drivers/staging/media/rkvdec/rkvdec-vp9.c3
-rw-r--r--drivers/staging/media/sunxi/Kconfig1
-rw-r--r--drivers/staging/media/sunxi/Makefile1
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus.c112
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus.h38
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_dec.c4
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_h264.c120
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_h265.c125
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_hw.c18
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_hw.h2
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_mpeg2.c2
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_regs.h18
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_video.c184
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_video.h2
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus_vp8.c2
-rw-r--r--drivers/staging/media/sunxi/sun6i-isp/Kconfig15
-rw-r--r--drivers/staging/media/sunxi/sun6i-isp/Makefile4
-rw-r--r--drivers/staging/media/sunxi/sun6i-isp/TODO.txt6
-rw-r--r--drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c555
-rw-r--r--drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.h90
-rw-r--r--drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.c742
-rw-r--r--drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_capture.h78
-rw-r--r--drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.c566
-rw-r--r--drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_params.h52
-rw-r--r--drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.c577
-rw-r--r--drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_proc.h66
-rw-r--r--drivers/staging/media/sunxi/sun6i-isp/sun6i_isp_reg.h275
-rw-r--r--drivers/staging/media/sunxi/sun6i-isp/uapi/sun6i-isp-config.h43
-rw-r--r--drivers/staging/media/tegra-video/csi.c4
-rw-r--r--drivers/staging/media/tegra-video/csi.h2
-rw-r--r--drivers/staging/media/tegra-video/vi.c2
-rw-r--r--drivers/staging/pi433/Documentation/devicetree/pi433-overlay.dtso (renamed from drivers/staging/pi433/Documentation/devicetree/pi433-overlay.dts)0
-rw-r--r--drivers/staging/pi433/Documentation/devicetree/pi433.txt6
-rw-r--r--drivers/staging/sm750fb/Kconfig1
-rw-r--r--drivers/staging/sm750fb/sm750.c3
-rw-r--r--drivers/staging/wlan-ng/hfa384x_usb.c4
-rw-r--r--drivers/staging/wlan-ng/prism2usb.c6
-rw-r--r--drivers/target/iscsi/iscsi_target_util.c4
-rw-r--r--drivers/target/target_core_file.c4
-rw-r--r--drivers/tee/optee/core.c4
-rw-r--r--drivers/thermal/gov_fair_share.c6
-rw-r--r--drivers/thermal/intel/intel_hfi.c34
-rw-r--r--drivers/thermal/intel/intel_menlow.c8
-rw-r--r--drivers/thermal/intel/intel_tcc_cooling.c11
-rw-r--r--drivers/thermal/intel/therm_throt.c25
-rw-r--r--drivers/thermal/intel/thermal_interrupt.h6
-rw-r--r--drivers/thermal/intel/x86_pkg_temp_thermal.c9
-rw-r--r--drivers/thermal/tegra/tegra-bpmp-thermal.c15
-rw-r--r--drivers/thermal/thermal_core.c110
-rw-r--r--drivers/thermal/thermal_core.h3
-rw-r--r--drivers/thermal/thermal_helpers.c67
-rw-r--r--drivers/thermal/thermal_hwmon.c10
-rw-r--r--drivers/thermal/thermal_sysfs.c116
-rw-r--r--drivers/tty/hvc/hvc_console.c4
-rw-r--r--drivers/tty/serial/8250/8250_core.c2
-rw-r--r--drivers/tty/serial/earlycon.c4
-rw-r--r--drivers/tty/serial/kgdboc.c46
-rw-r--r--drivers/tty/serial/pic32_uart.c4
-rw-r--r--drivers/tty/serial/samsung_tty.c2
-rw-r--r--drivers/tty/serial/serial_core.c14
-rw-r--r--drivers/tty/serial/sh-sci.c20
-rw-r--r--drivers/tty/serial/xilinx_uartps.c2
-rw-r--r--drivers/tty/tty_io.c18
-rw-r--r--drivers/ufs/core/ufshcd.c2
-rw-r--r--drivers/usb/early/xhci-dbc.c2
-rw-r--r--drivers/usb/host/fhci-hcd.c2
-rw-r--r--drivers/usb/usbip/usbip_common.c2
-rw-r--r--drivers/vfio/fsl-mc/vfio_fsl_mc_intr.c1
-rw-r--r--drivers/vhost/net.c6
-rw-r--r--drivers/vhost/scsi.c10
-rw-r--r--drivers/vhost/vhost.c6
-rw-r--r--drivers/vhost/vringh.c4
-rw-r--r--drivers/vhost/vsock.c4
-rw-r--r--drivers/video/Kconfig4
-rw-r--r--drivers/video/Makefile1
-rw-r--r--drivers/video/backlight/apple_bl.c3
-rw-r--r--drivers/video/fbdev/Kconfig38
-rw-r--r--drivers/video/fbdev/arkfb.c5
-rw-r--r--drivers/video/fbdev/asiliantfb.c3
-rw-r--r--drivers/video/fbdev/aty/aty128fb.c5
-rw-r--r--drivers/video/fbdev/aty/atyfb_base.c5
-rw-r--r--drivers/video/fbdev/aty/radeon_base.c5
-rw-r--r--drivers/video/fbdev/carminefb.c3
-rw-r--r--drivers/video/fbdev/chipsfb.c3
-rw-r--r--drivers/video/fbdev/cirrusfb.c5
-rw-r--r--drivers/video/fbdev/core/fbmem.c15
-rw-r--r--drivers/video/fbdev/cyber2000fb.c6
-rw-r--r--drivers/video/fbdev/geode/Kconfig3
-rw-r--r--drivers/video/fbdev/geode/gx1fb_core.c5
-rw-r--r--drivers/video/fbdev/geode/gxfb_core.c5
-rw-r--r--drivers/video/fbdev/geode/lxfb_core.c5
-rw-r--r--drivers/video/fbdev/gxt4500.c3
-rw-r--r--drivers/video/fbdev/hyperv_fb.c20
-rw-r--r--drivers/video/fbdev/i740fb.c5
-rw-r--r--drivers/video/fbdev/i810/i810_main.c6
-rw-r--r--drivers/video/fbdev/imsttfb.c5
-rw-r--r--drivers/video/fbdev/intelfb/intelfbdrv.c3
-rw-r--r--drivers/video/fbdev/kyro/fbdev.c5
-rw-r--r--drivers/video/fbdev/matrox/matroxfb_base.c3
-rw-r--r--drivers/video/fbdev/mb862xx/mb862xxfbdrv.c3
-rw-r--r--drivers/video/fbdev/neofb.c5
-rw-r--r--drivers/video/fbdev/nvidia/nvidia.c5
-rw-r--r--drivers/video/fbdev/pm2fb.c5
-rw-r--r--drivers/video/fbdev/pm3fb.c5
-rw-r--r--drivers/video/fbdev/pvr2fb.c5
-rw-r--r--drivers/video/fbdev/riva/fbdev.c5
-rw-r--r--drivers/video/fbdev/s3fb.c5
-rw-r--r--drivers/video/fbdev/savage/savagefb_driver.c3
-rw-r--r--drivers/video/fbdev/sis/sis_main.c5
-rw-r--r--drivers/video/fbdev/skeletonfb.c5
-rw-r--r--drivers/video/fbdev/sm712fb.c3
-rw-r--r--drivers/video/fbdev/sstfb.c3
-rw-r--r--drivers/video/fbdev/sunxvr2500.c3
-rw-r--r--drivers/video/fbdev/sunxvr500.c3
-rw-r--r--drivers/video/fbdev/tdfxfb.c5
-rw-r--r--drivers/video/fbdev/tgafb.c5
-rw-r--r--drivers/video/fbdev/tridentfb.c5
-rw-r--r--drivers/video/fbdev/vermilion/vermilion.c5
-rw-r--r--drivers/video/fbdev/via/via-core.c3
-rw-r--r--drivers/video/fbdev/vt8623fb.c5
-rw-r--r--drivers/video/fbdev/xen-fbfront.c12
-rw-r--r--drivers/video/nomodeset.c (renamed from drivers/gpu/drm/drm_nomodeset.c)12
-rw-r--r--drivers/virt/Kconfig2
-rw-r--r--drivers/virt/Makefile1
-rw-r--r--drivers/virt/coco/sev-guest/sev-guest.c5
-rw-r--r--drivers/virt/coco/tdx-guest/Kconfig10
-rw-r--r--drivers/virt/coco/tdx-guest/Makefile2
-rw-r--r--drivers/virt/coco/tdx-guest/tdx-guest.c102
-rw-r--r--drivers/watchdog/ni903x_wdt.c4
-rw-r--r--drivers/xen/gntdev-dmabuf.c8
-rw-r--r--drivers/xen/grant-dma-ops.c105
-rw-r--r--drivers/xen/privcmd.c2
-rw-r--r--drivers/xen/pvcalls-back.c8
-rw-r--r--drivers/xen/xen-acpi-pad.c3
-rw-r--r--fs/9p/acl.c295
-rw-r--r--fs/9p/acl.h8
-rw-r--r--fs/9p/vfs_addr.c4
-rw-r--r--fs/9p/vfs_dir.c2
-rw-r--r--fs/9p/vfs_inode_dotl.c4
-rw-r--r--fs/9p/xattr.c11
-rw-r--r--fs/9p/xattr.h2
-rw-r--r--fs/afs/cmservice.c2
-rw-r--r--fs/afs/dir.c2
-rw-r--r--fs/afs/file.c4
-rw-r--r--fs/afs/internal.h4
-rw-r--r--fs/afs/rxrpc.c10
-rw-r--r--fs/afs/write.c4
-rw-r--r--fs/aio.c4
-rw-r--r--fs/attr.c74
-rw-r--r--fs/bad_inode.c4
-rw-r--r--fs/binfmt_elf.c299
-rw-r--r--fs/binfmt_elf_fdpic.c7
-rw-r--r--fs/binfmt_misc.c8
-rw-r--r--fs/btrfs/Makefile6
-rw-r--r--fs/btrfs/accessors.c (renamed from fs/btrfs/struct-funcs.c)12
-rw-r--r--fs/btrfs/accessors.h1073
-rw-r--r--fs/btrfs/acl.c5
-rw-r--r--fs/btrfs/acl.h27
-rw-r--r--fs/btrfs/backref.c1001
-rw-r--r--fs/btrfs/backref.h195
-rw-r--r--fs/btrfs/bio.c381
-rw-r--r--fs/btrfs/bio.h127
-rw-r--r--fs/btrfs/block-group.c152
-rw-r--r--fs/btrfs/block-group.h30
-rw-r--r--fs/btrfs/block-rsv.c43
-rw-r--r--fs/btrfs/block-rsv.h6
-rw-r--r--fs/btrfs/btrfs_inode.h161
-rw-r--r--fs/btrfs/check-integrity.c4
-rw-r--r--fs/btrfs/compression.c18
-rw-r--r--fs/btrfs/compression.h11
-rw-r--r--fs/btrfs/ctree.c311
-rw-r--r--fs/btrfs/ctree.h3465
-rw-r--r--fs/btrfs/defrag.c1376
-rw-r--r--fs/btrfs/defrag.h22
-rw-r--r--fs/btrfs/delalloc-space.c61
-rw-r--r--fs/btrfs/delalloc-space.h3
-rw-r--r--fs/btrfs/delayed-inode.c17
-rw-r--r--fs/btrfs/delayed-inode.h2
-rw-r--r--fs/btrfs/delayed-ref.c21
-rw-r--r--fs/btrfs/dev-replace.c28
-rw-r--r--fs/btrfs/dev-replace.h8
-rw-r--r--fs/btrfs/dir-item.c60
-rw-r--r--fs/btrfs/dir-item.h42
-rw-r--r--fs/btrfs/discard.c112
-rw-r--r--fs/btrfs/disk-io.c247
-rw-r--r--fs/btrfs/disk-io.h35
-rw-r--r--fs/btrfs/export.c25
-rw-r--r--fs/btrfs/export.h3
-rw-r--r--fs/btrfs/extent-io-tree.c192
-rw-r--r--fs/btrfs/extent-io-tree.h100
-rw-r--r--fs/btrfs/extent-tree.c55
-rw-r--r--fs/btrfs/extent-tree.h78
-rw-r--r--fs/btrfs/extent_io.c482
-rw-r--r--fs/btrfs/extent_io.h67
-rw-r--r--fs/btrfs/extent_map.c75
-rw-r--r--fs/btrfs/file-item.c258
-rw-r--r--fs/btrfs/file-item.h69
-rw-r--r--fs/btrfs/file.c621
-rw-r--r--fs/btrfs/file.h33
-rw-r--r--fs/btrfs/free-space-cache.c52
-rw-r--r--fs/btrfs/free-space-cache.h13
-rw-r--r--fs/btrfs/free-space-tree.c15
-rw-r--r--fs/btrfs/fs.c94
-rw-r--r--fs/btrfs/fs.h976
-rw-r--r--fs/btrfs/inode-item.c79
-rw-r--r--fs/btrfs/inode-item.h20
-rw-r--r--fs/btrfs/inode.c912
-rw-r--r--fs/btrfs/ioctl.c949
-rw-r--r--fs/btrfs/ioctl.h17
-rw-r--r--fs/btrfs/locking.c1
-rw-r--r--fs/btrfs/locking.h76
-rw-r--r--fs/btrfs/lzo.c4
-rw-r--r--fs/btrfs/messages.c353
-rw-r--r--fs/btrfs/messages.h245
-rw-r--r--fs/btrfs/misc.h24
-rw-r--r--fs/btrfs/ordered-data.c31
-rw-r--r--fs/btrfs/ordered-data.h3
-rw-r--r--fs/btrfs/orphan.c1
-rw-r--r--fs/btrfs/orphan.h11
-rw-r--r--fs/btrfs/print-tree.c21
-rw-r--r--fs/btrfs/props.c8
-rw-r--r--fs/btrfs/props.h2
-rw-r--r--fs/btrfs/qgroup.c78
-rw-r--r--fs/btrfs/qgroup.h11
-rw-r--r--fs/btrfs/raid56.c2052
-rw-r--r--fs/btrfs/raid56.h33
-rw-r--r--fs/btrfs/rcu-string.h6
-rw-r--r--fs/btrfs/ref-verify.c3
-rw-r--r--fs/btrfs/reflink.c30
-rw-r--r--fs/btrfs/relocation.c94
-rw-r--r--fs/btrfs/relocation.h23
-rw-r--r--fs/btrfs/root-tree.c24
-rw-r--r--fs/btrfs/root-tree.h34
-rw-r--r--fs/btrfs/scrub.c75
-rw-r--r--fs/btrfs/scrub.h16
-rw-r--r--fs/btrfs/send.c488
-rw-r--r--fs/btrfs/send.h6
-rw-r--r--fs/btrfs/space-info.c86
-rw-r--r--fs/btrfs/space-info.h78
-rw-r--r--fs/btrfs/subpage.c1
-rw-r--r--fs/btrfs/super.c554
-rw-r--r--fs/btrfs/super.h29
-rw-r--r--fs/btrfs/sysfs.c16
-rw-r--r--fs/btrfs/tests/btrfs-tests.c3
-rw-r--r--fs/btrfs/tests/extent-buffer-tests.c1
-rw-r--r--fs/btrfs/tests/extent-io-tests.c4
-rw-r--r--fs/btrfs/tests/free-space-tree-tests.c3
-rw-r--r--fs/btrfs/tests/inode-tests.c58
-rw-r--r--fs/btrfs/tests/qgroup-tests.c52
-rw-r--r--fs/btrfs/transaction.c92
-rw-r--r--fs/btrfs/transaction.h22
-rw-r--r--fs/btrfs/tree-checker.c10
-rw-r--r--fs/btrfs/tree-checker.h35
-rw-r--r--fs/btrfs/tree-defrag.c132
-rw-r--r--fs/btrfs/tree-log.c452
-rw-r--r--fs/btrfs/tree-log.h5
-rw-r--r--fs/btrfs/tree-mod-log.c36
-rw-r--r--fs/btrfs/tree-mod-log.h4
-rw-r--r--fs/btrfs/ulist.c38
-rw-r--r--fs/btrfs/ulist.h2
-rw-r--r--fs/btrfs/uuid-tree.c5
-rw-r--r--fs/btrfs/uuid-tree.h12
-rw-r--r--fs/btrfs/verity.c6
-rw-r--r--fs/btrfs/verity.h28
-rw-r--r--fs/btrfs/volumes.c454
-rw-r--r--fs/btrfs/volumes.h116
-rw-r--r--fs/btrfs/xattr.c4
-rw-r--r--fs/btrfs/zlib.c6
-rw-r--r--fs/btrfs/zoned.c18
-rw-r--r--fs/btrfs/zoned.h1
-rw-r--r--fs/btrfs/zstd.c4
-rw-r--r--fs/cachefiles/io.c77
-rw-r--r--fs/ceph/acl.c3
-rw-r--r--fs/ceph/addr.c4
-rw-r--r--fs/ceph/dir.c2
-rw-r--r--fs/ceph/file.c4
-rw-r--r--fs/ceph/inode.c6
-rw-r--r--fs/ceph/locks.c4
-rw-r--r--fs/ceph/mdsmap.c2
-rw-r--r--fs/ceph/super.h2
-rw-r--r--fs/cifs/cifsacl.c139
-rw-r--r--fs/cifs/cifsfs.c4
-rw-r--r--fs/cifs/cifsproto.h20
-rw-r--r--fs/cifs/cifssmb.c206
-rw-r--r--fs/cifs/connect.c6
-rw-r--r--fs/cifs/file.c6
-rw-r--r--fs/cifs/fscache.c4
-rw-r--r--fs/cifs/smb2ops.c4
-rw-r--r--fs/cifs/transport.c6
-rw-r--r--fs/cifs/xattr.c68
-rw-r--r--fs/configfs/dir.c2
-rw-r--r--fs/coredump.c12
-rw-r--r--fs/crypto/fscrypt_private.h13
-rw-r--r--fs/crypto/inline_crypt.c14
-rw-r--r--fs/crypto/keyring.c14
-rw-r--r--fs/crypto/keysetup.c17
-rw-r--r--fs/crypto/policy.c12
-rw-r--r--fs/debugfs/file.c28
-rw-r--r--fs/dlm/ast.c322
-rw-r--r--fs/dlm/ast.h17
-rw-r--r--fs/dlm/config.c4
-rw-r--r--fs/dlm/debug_fs.c2
-rw-r--r--fs/dlm/dlm_internal.h25
-rw-r--r--fs/dlm/lock.c190
-rw-r--r--fs/dlm/lockspace.c14
-rw-r--r--fs/dlm/lowcomms.c1538
-rw-r--r--fs/dlm/lowcomms.h6
-rw-r--r--fs/dlm/main.c7
-rw-r--r--fs/dlm/member.c5
-rw-r--r--fs/dlm/memory.c30
-rw-r--r--fs/dlm/memory.h4
-rw-r--r--fs/dlm/midcomms.c141
-rw-r--r--fs/dlm/midcomms.h7
-rw-r--r--fs/dlm/rcom.c4
-rw-r--r--fs/dlm/requestqueue.c3
-rw-r--r--fs/dlm/user.c74
-rw-r--r--fs/dlm/user.h2
-rw-r--r--fs/ecryptfs/inode.c32
-rw-r--r--fs/efivarfs/inode.c4
-rw-r--r--fs/efivarfs/super.c3
-rw-r--r--fs/erofs/data.c10
-rw-r--r--fs/erofs/fscache.c412
-rw-r--r--fs/erofs/inode.c8
-rw-r--r--fs/erofs/internal.h13
-rw-r--r--fs/erofs/namei.c2
-rw-r--r--fs/erofs/super.c2
-rw-r--r--fs/erofs/xattr.c8
-rw-r--r--fs/erofs/zdata.c80
-rw-r--r--fs/erofs/zmap.c15
-rw-r--r--fs/eventfd.c37
-rw-r--r--fs/eventpoll.c18
-rw-r--r--fs/exec.c50
-rw-r--r--fs/exportfs/expfs.c8
-rw-r--r--fs/ext2/acl.c3
-rw-r--r--fs/ext2/acl.h2
-rw-r--r--fs/ext2/balloc.c12
-rw-r--r--fs/ext2/dir.c41
-rw-r--r--fs/ext2/file.c2
-rw-r--r--fs/ext2/ialloc.c2
-rw-r--r--fs/ext2/inode.c8
-rw-r--r--fs/ext2/namei.c4
-rw-r--r--fs/ext2/super.c2
-rw-r--r--fs/ext4/acl.c3
-rw-r--r--fs/ext4/acl.h2
-rw-r--r--fs/ext4/ext4.h13
-rw-r--r--fs/ext4/ext4_jbd2.c14
-rw-r--r--fs/ext4/ext4_jbd2.h10
-rw-r--r--fs/ext4/extents.c16
-rw-r--r--fs/ext4/extents_status.c11
-rw-r--r--fs/ext4/fast_commit.c205
-rw-r--r--fs/ext4/fast_commit.h3
-rw-r--r--fs/ext4/file.c2
-rw-r--r--fs/ext4/ialloc.c8
-rw-r--r--fs/ext4/indirect.c9
-rw-r--r--fs/ext4/inline.c3
-rw-r--r--fs/ext4/inode.c254
-rw-r--r--fs/ext4/ioctl.c24
-rw-r--r--fs/ext4/mballoc.c10
-rw-r--r--fs/ext4/mmp.c8
-rw-r--r--fs/ext4/namei.c51
-rw-r--r--fs/ext4/orphan.c2
-rw-r--r--fs/ext4/page-io.c44
-rw-r--r--fs/ext4/readpage.c13
-rw-r--r--fs/ext4/resize.c36
-rw-r--r--fs/ext4/super.c65
-rw-r--r--fs/ext4/verity.c2
-rw-r--r--fs/ext4/xattr.c22
-rw-r--r--fs/f2fs/acl.c4
-rw-r--r--fs/f2fs/acl.h2
-rw-r--r--fs/f2fs/compress.c64
-rw-r--r--fs/f2fs/data.c53
-rw-r--r--fs/f2fs/file.c4
-rw-r--r--fs/f2fs/gc.c2
-rw-r--r--fs/f2fs/namei.c4
-rw-r--r--fs/f2fs/segment.c8
-rw-r--r--fs/fat/nfs.c4
-rw-r--r--fs/fs_parser.c3
-rw-r--r--fs/fscache/io.c2
-rw-r--r--fs/fuse/acl.c5
-rw-r--r--fs/fuse/cuse.c5
-rw-r--r--fs/fuse/dev.c7
-rw-r--r--fs/fuse/dir.c47
-rw-r--r--fs/fuse/file.c45
-rw-r--r--fs/fuse/fuse_i.h6
-rw-r--r--fs/fuse/ioctl.c4
-rw-r--r--fs/fuse/readdir.c4
-rw-r--r--fs/gfs2/acl.c3
-rw-r--r--fs/gfs2/acl.h2
-rw-r--r--fs/gfs2/inode.c6
-rw-r--r--fs/hfs/inode.c2
-rw-r--r--fs/hfs/trans.c2
-rw-r--r--fs/hfsplus/hfsplus_fs.h2
-rw-r--r--fs/hfsplus/inode.c4
-rw-r--r--fs/hfsplus/options.c4
-rw-r--r--fs/inode.c75
-rw-r--r--fs/internal.h35
-rw-r--r--fs/iomap/direct-io.c3
-rw-r--r--fs/jbd2/commit.c5
-rw-r--r--fs/jffs2/acl.c3
-rw-r--r--fs/jffs2/acl.h2
-rw-r--r--fs/jffs2/dir.c2
-rw-r--r--fs/jffs2/file.c2
-rw-r--r--fs/jffs2/fs.c2
-rw-r--r--fs/jfs/acl.c3
-rw-r--r--fs/jfs/file.c4
-rw-r--r--fs/jfs/jfs_acl.h2
-rw-r--r--fs/jfs/jfs_dmap.c27
-rw-r--r--fs/jfs/jfs_extent.h2
-rw-r--r--fs/jfs/jfs_imap.c2
-rw-r--r--fs/jfs/jfs_mount.c4
-rw-r--r--fs/jfs/jfs_umount.c4
-rw-r--r--fs/jfs/jfs_xattr.h2
-rw-r--r--fs/jfs/jfs_xtree.h4
-rw-r--r--fs/jfs/namei.c4
-rw-r--r--fs/jfs/super.c6
-rw-r--r--fs/ksmbd/smb2pdu.c8
-rw-r--r--fs/ksmbd/smbacl.c6
-rw-r--r--fs/ksmbd/vfs.c23
-rw-r--r--fs/ksmbd/vfs.h4
-rw-r--r--fs/libfs.c22
-rw-r--r--fs/lockd/svc4proc.c1
-rw-r--r--fs/lockd/svclock.c17
-rw-r--r--fs/lockd/svcproc.c1
-rw-r--r--fs/lockd/svcsubs.c21
-rw-r--r--fs/locks.c50
-rw-r--r--fs/mbcache.c14
-rw-r--r--fs/namei.c46
-rw-r--r--fs/namespace.c179
-rw-r--r--fs/netfs/io.c6
-rw-r--r--fs/nfs/Kconfig8
-rw-r--r--fs/nfs/delegation.c2
-rw-r--r--fs/nfs/dir.c32
-rw-r--r--fs/nfs/fs_context.c6
-rw-r--r--fs/nfs/fscache.c4
-rw-r--r--fs/nfs/inode.c3
-rw-r--r--fs/nfs/internal.h6
-rw-r--r--fs/nfs/namespace.c4
-rw-r--r--fs/nfs/nfs3_fs.h2
-rw-r--r--fs/nfs/nfs3acl.c9
-rw-r--r--fs/nfs/nfs3proc.c4
-rw-r--r--fs/nfs/nfs42xdr.c9
-rw-r--r--fs/nfs/nfs4_fs.h1
-rw-r--r--fs/nfs/nfs4file.c12
-rw-r--r--fs/nfs/nfs4proc.c57
-rw-r--r--fs/nfs/nfs4state.c7
-rw-r--r--fs/nfs/nfs4trace.h10
-rw-r--r--fs/nfs/nfs4xdr.c22
-rw-r--r--fs/nfs/nfstrace.h6
-rw-r--r--fs/nfs/pagelist.c2
-rw-r--r--fs/nfs/sysfs.c2
-rw-r--r--fs/nfs/unlink.c1
-rw-r--r--fs/nfs/write.c4
-rw-r--r--fs/nfsd/Kconfig19
-rw-r--r--fs/nfsd/Makefile5
-rw-r--r--fs/nfsd/blocklayout.c1
-rw-r--r--fs/nfsd/blocklayoutxdr.c1
-rw-r--r--fs/nfsd/export.h1
-rw-r--r--fs/nfsd/filecache.c241
-rw-r--r--fs/nfsd/filecache.h4
-rw-r--r--fs/nfsd/flexfilelayout.c1
-rw-r--r--fs/nfsd/nfs2acl.c18
-rw-r--r--fs/nfsd/nfs3acl.c38
-rw-r--r--fs/nfsd/nfs3proc.c10
-rw-r--r--fs/nfsd/nfs4acl.c4
-rw-r--r--fs/nfsd/nfs4callback.c72
-rw-r--r--fs/nfsd/nfs4idmap.c1
-rw-r--r--fs/nfsd/nfs4proc.c49
-rw-r--r--fs/nfsd/nfs4state.c347
-rw-r--r--fs/nfsd/nfs4xdr.c771
-rw-r--r--fs/nfsd/nfsctl.c6
-rw-r--r--fs/nfsd/nfsd.h3
-rw-r--r--fs/nfsd/nfsfh.h10
-rw-r--r--fs/nfsd/nfsproc.c66
-rw-r--r--fs/nfsd/nfssvc.c8
-rw-r--r--fs/nfsd/state.h11
-rw-r--r--fs/nfsd/trace.h144
-rw-r--r--fs/nfsd/vfs.c91
-rw-r--r--fs/nfsd/vfs.h4
-rw-r--r--fs/nfsd/xdr4.h5
-rw-r--r--fs/nfsd/xdr4cb.h6
-rw-r--r--fs/nilfs2/the_nilfs.c73
-rw-r--r--fs/ntfs3/file.c4
-rw-r--r--fs/ntfs3/namei.c4
-rw-r--r--fs/ntfs3/ntfs_fs.h4
-rw-r--r--fs/ntfs3/xattr.c9
-rw-r--r--fs/ocfs2/acl.c3
-rw-r--r--fs/ocfs2/acl.h2
-rw-r--r--fs/ocfs2/cluster/heartbeat.c38
-rw-r--r--fs/ocfs2/cluster/heartbeat.h2
-rw-r--r--fs/ocfs2/cluster/netdebug.c2
-rw-r--r--fs/ocfs2/cluster/nodemanager.c2
-rw-r--r--fs/ocfs2/cluster/tcp.c8
-rw-r--r--fs/ocfs2/dlm/dlmcommon.h2
-rw-r--r--fs/ocfs2/dlm/dlmdomain.c19
-rw-r--r--fs/ocfs2/dlm/dlmmaster.c30
-rw-r--r--fs/ocfs2/dlm/dlmrecovery.c2
-rw-r--r--fs/ocfs2/file.c8
-rw-r--r--fs/ocfs2/journal.c2
-rw-r--r--fs/ocfs2/journal.h1
-rw-r--r--fs/ocfs2/namei.c2
-rw-r--r--fs/ocfs2/ocfs2.h3
-rw-r--r--fs/ocfs2/stack_o2cb.c6
-rw-r--r--fs/ocfs2/stackglue.c8
-rw-r--r--fs/ocfs2/super.c5
-rw-r--r--fs/open.c10
-rw-r--r--fs/orangefs/acl.c47
-rw-r--r--fs/orangefs/inode.c62
-rw-r--r--fs/orangefs/namei.c2
-rw-r--r--fs/orangefs/orangefs-kernel.h7
-rw-r--r--fs/overlayfs/Kconfig2
-rw-r--r--fs/overlayfs/copy_up.c38
-rw-r--r--fs/overlayfs/dir.c68
-rw-r--r--fs/overlayfs/export.c8
-rw-r--r--fs/overlayfs/file.c31
-rw-r--r--fs/overlayfs/inode.c187
-rw-r--r--fs/overlayfs/namei.c12
-rw-r--r--fs/overlayfs/overlayfs.h53
-rw-r--r--fs/overlayfs/readdir.c58
-rw-r--r--fs/overlayfs/super.c114
-rw-r--r--fs/overlayfs/util.c15
-rw-r--r--fs/posix_acl.c727
-rw-r--r--fs/proc/cmdline.c6
-rw-r--r--fs/proc/consoles.c21
-rw-r--r--fs/proc/fd.c45
-rw-r--r--fs/proc/vmcore.c7
-rw-r--r--fs/pstore/platform.c25
-rw-r--r--fs/pstore/ram.c44
-rw-r--r--fs/pstore/ram_core.c20
-rw-r--r--fs/pstore/ram_internal.h98
-rw-r--r--fs/pstore/zone.c2
-rw-r--r--fs/quota/dquot.c2
-rw-r--r--fs/read_write.c12
-rw-r--r--fs/reiserfs/acl.h6
-rw-r--r--fs/reiserfs/file.c2
-rw-r--r--fs/reiserfs/inode.c2
-rw-r--r--fs/reiserfs/namei.c8
-rw-r--r--fs/reiserfs/xattr_acl.c11
-rw-r--r--fs/reiserfs/xattr_security.c2
-rw-r--r--fs/remap_range.c9
-rw-r--r--fs/seq_file.c2
-rw-r--r--fs/splice.c10
-rw-r--r--fs/squashfs/Kconfig51
-rw-r--r--fs/squashfs/block.c2
-rw-r--r--fs/squashfs/decompressor.c2
-rw-r--r--fs/squashfs/decompressor_multi.c20
-rw-r--r--fs/squashfs/decompressor_multi_percpu.c23
-rw-r--r--fs/squashfs/decompressor_single.c15
-rw-r--r--fs/squashfs/squashfs.h23
-rw-r--r--fs/squashfs/squashfs_fs_sb.h4
-rw-r--r--fs/squashfs/super.c102
-rw-r--r--fs/stat.c7
-rw-r--r--fs/super.c60
-rw-r--r--fs/sysv/itree.c2
-rw-r--r--fs/ubifs/debug.c8
-rw-r--r--fs/ubifs/lpt_commit.c14
-rw-r--r--fs/ubifs/tnc_commit.c2
-rw-r--r--fs/udf/inode.c83
-rw-r--r--fs/udf/namei.c8
-rw-r--r--fs/udf/super.c4
-rw-r--r--fs/udf/truncate.c48
-rw-r--r--fs/udf/udf_sb.h6
-rw-r--r--fs/verity/fsverity_private.h5
-rw-r--r--fs/verity/hash_algs.c6
-rw-r--r--fs/verity/measure.c19
-rw-r--r--fs/verity/verify.c12
-rw-r--r--fs/xattr.c440
-rw-r--r--fs/xfs/libxfs/xfs_alloc.c2
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c2
-rw-r--r--fs/xfs/xfs_acl.c3
-rw-r--r--fs/xfs/xfs_acl.h2
-rw-r--r--fs/xfs/xfs_error.c2
-rw-r--r--fs/xfs/xfs_iops.c16
-rw-r--r--include/acpi/acconfig.h2
-rw-r--r--include/acpi/acpi_bus.h2
-rw-r--r--include/acpi/acpixf.h2
-rw-r--r--include/acpi/actbl1.h151
-rw-r--r--include/acpi/actbl2.h162
-rw-r--r--include/acpi/actypes.h10
-rw-r--r--include/acpi/acuuid.h3
-rw-r--r--include/acpi/battery.h4
-rw-r--r--include/acpi/ghes.h34
-rw-r--r--include/acpi/processor.h10
-rw-r--r--include/asm-generic/msi.h4
-rw-r--r--include/asm-generic/vmlinux.lds.h9
-rw-r--r--include/clocksource/hyperv_timer.h11
-rw-r--r--include/clocksource/timer-ti-dm.h2
-rw-r--r--include/drm/drm_accel.h97
-rw-r--r--include/drm/drm_atomic_helper.h3
-rw-r--r--include/drm/drm_atomic_state_helper.h2
-rw-r--r--include/drm/drm_connector.h33
-rw-r--r--include/drm/drm_crtc_helper.h2
-rw-r--r--include/drm/drm_device.h3
-rw-r--r--include/drm/drm_drv.h16
-rw-r--r--include/drm/drm_edid.h24
-rw-r--r--include/drm/drm_fb_helper.h68
-rw-r--r--include/drm/drm_fbdev_generic.h15
-rw-r--r--include/drm/drm_file.h21
-rw-r--r--include/drm/drm_gem.h3
-rw-r--r--include/drm/drm_gem_atomic_helper.h20
-rw-r--r--include/drm/drm_mode_config.h2
-rw-r--r--include/drm/drm_modeset_helper_vtables.h41
-rw-r--r--include/drm/drm_simple_kms_helper.h20
-rw-r--r--include/drm/gpu_scheduler.h51
-rw-r--r--include/drm/i915_pxp_tee_interface.h5
-rw-r--r--include/drm/ttm/ttm_resource.h4
-rw-r--r--include/drm/ttm/ttm_tt.h2
-rw-r--r--include/dt-bindings/arm/qcom,ids.h170
-rw-r--r--include/dt-bindings/clock/imx8mn-clock.h24
-rw-r--r--include/dt-bindings/clock/imx8mp-clock.h12
-rw-r--r--include/dt-bindings/clock/imx93-clock.h4
-rw-r--r--include/dt-bindings/clock/ingenic,jz4755-cgu.h49
-rw-r--r--include/dt-bindings/clock/ingenic,x1000-cgu.h4
-rw-r--r--include/dt-bindings/clock/qcom,dispcc-sc8280xp.h100
-rw-r--r--include/dt-bindings/clock/qcom,dispcc-sm8250.h1
-rw-r--r--include/dt-bindings/clock/qcom,gcc-ipq8074.h14
-rw-r--r--include/dt-bindings/clock/qcom,sm6375-dispcc.h42
-rw-r--r--include/dt-bindings/clock/qcom,sm8550-gcc.h231
-rw-r--r--include/dt-bindings/clock/rk3399-cru.h6
-rw-r--r--include/dt-bindings/clock/rockchip,rk3588-cru.h766
-rw-r--r--include/dt-bindings/clock/suniv-ccu-f1c100s.h2
-rw-r--r--include/dt-bindings/clock/tegra234-clock.h639
-rw-r--r--include/dt-bindings/firmware/imx/rsrc.h302
-rw-r--r--include/dt-bindings/iio/qcom,spmi-adc7-pm8350.h90
-rw-r--r--include/dt-bindings/media/video-interfaces.h16
-rw-r--r--include/dt-bindings/memory/tegra234-mc.h440
-rw-r--r--include/dt-bindings/pinctrl/mt6795-pinfunc.h4
-rw-r--r--include/dt-bindings/power/qcom-rpmpd.h42
-rw-r--r--include/dt-bindings/power/tegra234-powergate.h15
-rw-r--r--include/dt-bindings/reset/rockchip,rk3588-cru.h754
-rw-r--r--include/dt-bindings/reset/tegra234-reset.h111
-rw-r--r--include/kunit/assert.h74
-rw-r--r--include/kunit/test-bug.h53
-rw-r--r--include/kunit/test.h118
-rw-r--r--include/kunit/visibility.h33
-rw-r--r--include/linux/acpi.h13
-rw-r--r--include/linux/acpi_apmt.h19
-rw-r--r--include/linux/arm_ffa.h85
-rw-r--r--include/linux/ata.h31
-rw-r--r--include/linux/bcm47xx_nvram.h6
-rw-r--r--include/linux/bio.h2
-rw-r--r--include/linux/blk-crypto-profile.h12
-rw-r--r--include/linux/blk-crypto.h14
-rw-r--r--include/linux/blk-mq.h9
-rw-r--r--include/linux/blk_types.h7
-rw-r--r--include/linux/blkdev.h32
-rw-r--r--include/linux/cgroup.h98
-rw-r--r--include/linux/cgroup_refcnt.h96
-rw-r--r--include/linux/clk-provider.h2
-rw-r--r--include/linux/compat.h2
-rw-r--r--include/linux/configfs.h3
-rw-r--r--include/linux/console.h129
-rw-r--r--include/linux/coredump.h2
-rw-r--r--include/linux/cpufreq.h28
-rw-r--r--include/linux/cpuhotplug.h1
-rw-r--r--include/linux/cxl_err.h22
-rw-r--r--include/linux/damon.h2
-rw-r--r--include/linux/debugfs.h19
-rw-r--r--include/linux/devfreq.h7
-rw-r--r--include/linux/device.h8
-rw-r--r--include/linux/dma-buf.h17
-rw-r--r--include/linux/efi.h55
-rw-r--r--include/linux/elfcore.h13
-rw-r--r--include/linux/eventfd.h9
-rw-r--r--include/linux/evm.h49
-rw-r--r--include/linux/fb.h9
-rw-r--r--include/linux/firmware/xlnx-zynqmp.h19
-rw-r--r--include/linux/fixp-arith.h1
-rw-r--r--include/linux/fs.h95
-rw-r--r--include/linux/fs_context.h16
-rw-r--r--include/linux/fs_parser.h1
-rw-r--r--include/linux/ftrace.h47
-rw-r--r--include/linux/gpio.h2
-rw-r--r--include/linux/gpio/aspeed.h4
-rw-r--r--include/linux/gpio/driver.h4
-rw-r--r--include/linux/gpio/gpio-reg.h4
-rw-r--r--include/linux/gpio/machine.h1
-rw-r--r--include/linux/host1x.h2
-rw-r--r--include/linux/hwmon-sysfs.h1
-rw-r--r--include/linux/hyperv.h4
-rw-r--r--include/linux/ima.h24
-rw-r--r--include/linux/init.h3
-rw-r--r--include/linux/io-mapping.h4
-rw-r--r--include/linux/io_uring.h13
-rw-r--r--include/linux/io_uring_types.h5
-rw-r--r--include/linux/iommu.h25
-rw-r--r--include/linux/ioport.h2
-rw-r--r--include/linux/irqdomain.h143
-rw-r--r--include/linux/irqdomain_defs.h31
-rw-r--r--include/linux/irqreturn.h8
-rw-r--r--include/linux/jbd2.h2
-rw-r--r--include/linux/kallsyms.h9
-rw-r--r--include/linux/kasan.h5
-rw-r--r--include/linux/kcov.h2
-rw-r--r--include/linux/kexec.h7
-rw-r--r--include/linux/kvm_host.h2
-rw-r--r--include/linux/libata.h7
-rw-r--r--include/linux/libnvdimm.h7
-rw-r--r--include/linux/lru_cache.h3
-rw-r--r--include/linux/lsm_hook_defs.h9
-rw-r--r--include/linux/lsm_hooks.h263
-rw-r--r--include/linux/math64.h26
-rw-r--r--include/linux/mbcache.h9
-rw-r--r--include/linux/mei_cl_bus.h6
-rw-r--r--include/linux/mempool.h5
-rw-r--r--include/linux/memregion.h38
-rw-r--r--include/linux/mfd/max8997.h3
-rw-r--r--include/linux/mfd/tmio.h1
-rw-r--r--include/linux/minmax.h26
-rw-r--r--include/linux/mm.h3
-rw-r--r--include/linux/mmzone.h24
-rw-r--r--include/linux/mnt_idmapping.h108
-rw-r--r--include/linux/module.h1
-rw-r--r--include/linux/mount.h9
-rw-r--r--include/linux/msi.h357
-rw-r--r--include/linux/msi_api.h73
-rw-r--r--include/linux/mtd/nand.h1
-rw-r--r--include/linux/mtd/spi-nor.h3
-rw-r--r--include/linux/netfs.h8
-rw-r--r--include/linux/nfs4.h13
-rw-r--r--include/linux/nfs_fs.h1
-rw-r--r--include/linux/nodemask.h2
-rw-r--r--include/linux/nsproxy.h1
-rw-r--r--include/linux/nvme.h2
-rw-r--r--include/linux/of.h4
-rw-r--r--include/linux/of_address.h11
-rw-r--r--include/linux/pci.h49
-rw-r--r--include/linux/pe.h9
-rw-r--r--include/linux/percpu.h9
-rw-r--r--include/linux/perf/arm_pmu.h3
-rw-r--r--include/linux/perf_event.h125
-rw-r--r--include/linux/phy/phy-mipi-dphy.h3
-rw-r--r--include/linux/pinctrl/consumer.h31
-rw-r--r--include/linux/pinctrl/devinfo.h6
-rw-r--r--include/linux/pinctrl/machine.h8
-rw-r--r--include/linux/pinctrl/pinconf-generic.h29
-rw-r--r--include/linux/pinctrl/pinctrl.h20
-rw-r--r--include/linux/pinctrl/pinmux.h5
-rw-r--r--include/linux/pktcdvd.h197
-rw-r--r--include/linux/platform_data/gpmc-omap.h8
-rw-r--r--include/linux/platform_data/gsc_hwmon.h5
-rw-r--r--include/linux/platform_data/st33zp24.h16
-rw-r--r--include/linux/platform_data/x86/pwm-lpss.h33
-rw-r--r--include/linux/pm_domain.h7
-rw-r--r--include/linux/posix_acl.h41
-rw-r--r--include/linux/posix_acl_xattr.h47
-rw-r--r--include/linux/prandom.h19
-rw-r--r--include/linux/property.h10
-rw-r--r--include/linux/psi_types.h4
-rw-r--r--include/linux/pstore_ram.h99
-rw-r--r--include/linux/ptrace.h9
-rw-r--r--include/linux/pwm.h5
-rw-r--r--include/linux/pxa2xx_ssp.h1
-rw-r--r--include/linux/raid/pq.h8
-rw-r--r--include/linux/random.h102
-rw-r--r--include/linux/rcupdate.h14
-rw-r--r--include/linux/rcutiny.h8
-rw-r--r--include/linux/rcutree.h4
-rw-r--r--include/linux/regmap.h49
-rw-r--r--include/linux/regset.h15
-rw-r--r--include/linux/regulator/consumer.h10
-rw-r--r--include/linux/regulator/driver.h3
-rw-r--r--include/linux/regulator/mt6357-regulator.h51
-rw-r--r--include/linux/regulator/userspace-consumer.h1
-rw-r--r--include/linux/resctrl.h6
-rw-r--r--include/linux/sbitmap.h16
-rw-r--r--include/linux/sched.h5
-rw-r--r--include/linux/sched/sysctl.h6
-rw-r--r--include/linux/scs.h18
-rw-r--r--include/linux/seccomp.h1
-rw-r--r--include/linux/security.h46
-rw-r--r--include/linux/sed-opal.h3
-rw-r--r--include/linux/serial_core.h10
-rw-r--r--include/linux/slab.h75
-rw-r--r--include/linux/slab_def.h2
-rw-r--r--include/linux/slub_def.h8
-rw-r--r--include/linux/soc/mediatek/mtk-mmsys.h7
-rw-r--r--include/linux/soc/qcom/llcc-qcom.h12
-rw-r--r--include/linux/soc/qcom/smd-rpm.h2
-rw-r--r--include/linux/soundwire/sdw_intel.h2
-rw-r--r--include/linux/spi/spi.h54
-rw-r--r--include/linux/srcu.h72
-rw-r--r--include/linux/srcutree.h5
-rw-r--r--include/linux/stackprotector.h19
-rw-r--r--include/linux/sunrpc/svc.h8
-rw-r--r--include/linux/swapops.h8
-rw-r--r--include/linux/syscalls.h2
-rw-r--r--include/linux/thermal.h1
-rw-r--r--include/linux/time_namespace.h6
-rw-r--r--include/linux/timer.h35
-rw-r--r--include/linux/timerqueue.h2
-rw-r--r--include/linux/uio.h9
-rw-r--r--include/linux/wait.h2
-rw-r--r--include/linux/xattr.h50
-rw-r--r--include/media/davinci/vpbe.h2
-rw-r--r--include/media/dvb_ringbuffer.h2
-rw-r--r--include/media/dvbdev.h38
-rw-r--r--include/media/frame_vector.h2
-rw-r--r--include/media/i2c/ov9650.h24
-rw-r--r--include/media/i2c/s5c73m3.h15
-rw-r--r--include/media/i2c/s5k4ecgx.h33
-rw-r--r--include/media/i2c/ths7303.h4
-rw-r--r--include/media/media-entity.h4
-rw-r--r--include/media/v4l2-mediabus.h17
-rw-r--r--include/media/v4l2-subdev.h11
-rw-r--r--include/media/videobuf2-core.h14
-rw-r--r--include/media/videobuf2-memops.h3
-rw-r--r--include/memory/renesas-rpc-if.h1
-rw-r--r--include/scsi/scsi_proto.h4
-rw-r--r--include/soc/amlogic/meson_ddr_pmu.h66
-rw-r--r--include/soc/bcm2835/raspberrypi-firmware.h52
-rw-r--r--include/soc/fsl/qe/qe.h5
-rw-r--r--include/soc/qcom/qcom-spmi-pmic.h17
-rw-r--r--include/soc/tegra/bpmp-abi.h1796
-rw-r--r--include/soc/tegra/bpmp.h17
-rw-r--r--include/soc/tegra/fuse.h15
-rw-r--r--include/soc/tegra/ivc.h12
-rw-r--r--include/soc/tegra/mc.h11
-rw-r--r--include/soc/tegra/pmc.h6
-rw-r--r--include/sound/acp63_chip_offset_byte.h (renamed from include/sound/acp62_chip_offset_byte.h)216
-rw-r--r--include/sound/hdaudio.h27
-rw-r--r--include/sound/hdaudio_ext.h69
-rw-r--r--include/sound/hdmi-codec.h4
-rw-r--r--include/sound/pcm.h36
-rw-r--r--include/sound/sdw.h49
-rw-r--r--include/sound/simple_card_utils.h2
-rw-r--r--include/sound/soc-dapm.h188
-rw-r--r--include/sound/soc-dpcm.h2
-rw-r--r--include/sound/sof.h10
-rw-r--r--include/sound/sof/dai-amd.h1
-rw-r--r--include/sound/sof/dai.h2
-rw-r--r--include/sound/sof/ipc4/header.h4
-rw-r--r--include/sound/tlv320aic3x.h65
-rw-r--r--include/trace/events/btrfs.h27
-rw-r--r--include/trace/events/cachefiles.h27
-rw-r--r--include/trace/events/clk.h43
-rw-r--r--include/trace/events/cxl.h112
-rw-r--r--include/trace/events/dlm.h303
-rw-r--r--include/trace/events/ext4.h64
-rw-r--r--include/trace/events/iocost.h4
-rw-r--r--include/trace/events/jbd2.h44
-rw-r--r--include/trace/events/rpcgss.h2
-rw-r--r--include/trace/events/rpcrdma.h4
-rw-r--r--include/trace/events/sunrpc.h6
-rw-r--r--include/trace/misc/fs.h (renamed from include/trace/events/fs.h)0
-rw-r--r--include/trace/misc/nfs.h (renamed from include/trace/events/nfs.h)12
-rw-r--r--include/trace/misc/rdma.h (renamed from include/trace/events/rdma.h)0
-rw-r--r--include/trace/misc/sunrpc.h (renamed from include/trace/events/sunrpc_base.h)0
-rw-r--r--include/uapi/drm/amdgpu_drm.h14
-rw-r--r--include/uapi/drm/drm_fourcc.h29
-rw-r--r--include/uapi/drm/drm_mode.h63
-rw-r--r--include/uapi/drm/i915_drm.h62
-rw-r--r--include/uapi/drm/msm_drm.h1
-rw-r--r--include/uapi/linux/aspeed-video.h14
-rw-r--r--include/uapi/linux/btrfs.h36
-rw-r--r--include/uapi/linux/btrfs_tree.h235
-rw-r--r--include/uapi/linux/dvb/audio.h15
-rw-r--r--include/uapi/linux/dvb/ca.h15
-rw-r--r--include/uapi/linux/dvb/dmx.h15
-rw-r--r--include/uapi/linux/dvb/frontend.h77
-rw-r--r--include/uapi/linux/dvb/net.h15
-rw-r--r--include/uapi/linux/dvb/osd.h15
-rw-r--r--include/uapi/linux/dvb/version.h15
-rw-r--r--include/uapi/linux/dvb/video.h15
-rw-r--r--include/uapi/linux/elf.h14
-rw-r--r--include/uapi/linux/eventpoll.h6
-rw-r--r--include/uapi/linux/fscrypt.h4
-rw-r--r--include/uapi/linux/fuse.h16
-rw-r--r--include/uapi/linux/input-event-codes.h3
-rw-r--r--include/uapi/linux/io_uring.h18
-rw-r--r--include/uapi/linux/ipmi_ssif_bmc.h18
-rw-r--r--include/uapi/linux/landlock.h21
-rw-r--r--include/uapi/linux/media-bus-format.h3
-rw-r--r--include/uapi/linux/pci_regs.h1
-rw-r--r--include/uapi/linux/pktcdvd.h112
-rw-r--r--include/uapi/linux/sed-opal.h8
-rw-r--r--include/uapi/linux/tdx-guest.h42
-rw-r--r--include/uapi/linux/v4l2-common.h39
-rw-r--r--include/uapi/linux/v4l2-controls.h46
-rw-r--r--include/uapi/linux/v4l2-dv-timings.h9
-rw-r--r--include/uapi/linux/v4l2-mediabus.h4
-rw-r--r--include/uapi/linux/v4l2-subdev.h13
-rw-r--r--include/uapi/linux/videodev2.h5
-rw-r--r--include/uapi/sound/asequencer.h8
-rw-r--r--include/uapi/sound/snd_ar_tokens.h27
-rw-r--r--include/uapi/sound/sof/tokens.h14
-rw-r--r--include/video/nomodeset.h8
-rw-r--r--include/xen/arm/xen-ops.h4
-rw-r--r--include/xen/xen-ops.h16
-rw-r--r--include/xen/xen.h4
-rw-r--r--init/Kconfig13
-rw-r--r--init/initramfs.c2
-rw-r--r--init/main.c7
-rw-r--r--io_uring/io_uring.c358
-rw-r--r--io_uring/io_uring.h58
-rw-r--r--io_uring/kbuf.c14
-rw-r--r--io_uring/msg_ring.c168
-rw-r--r--io_uring/msg_ring.h1
-rw-r--r--io_uring/net.c91
-rw-r--r--io_uring/notif.c57
-rw-r--r--io_uring/notif.h15
-rw-r--r--io_uring/opdef.c8
-rw-r--r--io_uring/opdef.h2
-rw-r--r--io_uring/poll.c123
-rw-r--r--io_uring/rsrc.c71
-rw-r--r--io_uring/rsrc.h1
-rw-r--r--io_uring/rw.c19
-rw-r--r--io_uring/timeout.c10
-rw-r--r--io_uring/uring_cmd.c2
-rw-r--r--io_uring/xattr.c8
-rw-r--r--ipc/mqueue.c6
-rw-r--r--kernel/Makefile1
-rw-r--r--kernel/acct.c6
-rw-r--r--kernel/auditsc.c75
-rw-r--r--kernel/bpf/core.c4
-rw-r--r--kernel/capability.c4
-rw-r--r--kernel/cgroup/cgroup.c8
-rw-r--r--kernel/cgroup/cpuset.c48
-rw-r--r--kernel/configs/tiny.config5
-rw-r--r--kernel/cpu.c61
-rw-r--r--kernel/crash_core.c3
-rw-r--r--kernel/debug/kdb/kdb_io.c18
-rw-r--r--kernel/dma/mapping.c8
-rw-r--r--kernel/dma/swiotlb.c63
-rw-r--r--kernel/events/core.c2100
-rw-r--r--kernel/fork.c28
-rw-r--r--kernel/futex/core.c26
-rw-r--r--kernel/irq/Kconfig7
-rw-r--r--kernel/irq/chip.c8
-rw-r--r--kernel/irq/internals.h2
-rw-r--r--kernel/irq/irqdesc.c15
-rw-r--r--kernel/irq/manage.c4
-rw-r--r--kernel/irq/msi.c914
-rw-r--r--kernel/kallsyms.c116
-rw-r--r--kernel/kallsyms_internal.h1
-rw-r--r--kernel/kallsyms_selftest.c485
-rw-r--r--kernel/kallsyms_selftest.h13
-rw-r--r--kernel/kcsan/Makefile1
-rw-r--r--kernel/kcsan/core.c50
-rw-r--r--kernel/kcsan/selftest.c12
-rw-r--r--kernel/kexec_core.c10
-rw-r--r--kernel/kexec_file.c2
-rw-r--r--kernel/livepatch/core.c31
-rw-r--r--kernel/livepatch/patch.c2
-rw-r--r--kernel/livepatch/transition.c54
-rw-r--r--kernel/locking/test-ww_mutex.c4
-rw-r--r--kernel/module/Kconfig3
-rw-r--r--kernel/module/decompress.c100
-rw-r--r--kernel/module/main.c3
-rw-r--r--kernel/module/sysfs.c2
-rw-r--r--kernel/notifier.c6
-rw-r--r--kernel/nsproxy.c23
-rw-r--r--kernel/panic.c5
-rw-r--r--kernel/params.c23
-rw-r--r--kernel/power/process.c25
-rw-r--r--kernel/power/snapshot.c12
-rw-r--r--kernel/printk/printk.c498
-rw-r--r--kernel/printk/printk_ringbuffer.c2
-rw-r--r--kernel/rcu/Kconfig22
-rw-r--r--kernel/rcu/Kconfig.debug3
-rw-r--r--kernel/rcu/rcu.h16
-rw-r--r--kernel/rcu/rcuscale.c69
-rw-r--r--kernel/rcu/rcutorture.c72
-rw-r--r--kernel/rcu/srcutiny.c10
-rw-r--r--kernel/rcu/srcutree.c100
-rw-r--r--kernel/rcu/sync.c2
-rw-r--r--kernel/rcu/tasks.h2
-rw-r--r--kernel/rcu/tiny.c2
-rw-r--r--kernel/rcu/tree.c152
-rw-r--r--kernel/rcu/tree.h12
-rw-r--r--kernel/rcu/tree_exp.h2
-rw-r--r--kernel/rcu/tree_nocb.h259
-rw-r--r--kernel/rcu/tree_plugin.h5
-rw-r--r--kernel/rcu/update.c18
-rw-r--r--kernel/relay.c8
-rw-r--r--kernel/resource.c13
-rw-r--r--kernel/sched/core.c272
-rw-r--r--kernel/sched/deadline.c7
-rw-r--r--kernel/sched/fair.c323
-rw-r--r--kernel/sched/psi.c100
-rw-r--r--kernel/sched/sched.h92
-rw-r--r--kernel/sched/stats.h22
-rw-r--r--kernel/sched/wait.c18
-rw-r--r--kernel/scs.c14
-rw-r--r--kernel/signal.c2
-rw-r--r--kernel/sysctl.c19
-rw-r--r--kernel/time/clockevents.c2
-rw-r--r--kernel/time/clocksource.c2
-rw-r--r--kernel/time/namespace.c18
-rw-r--r--kernel/time/timer.c427
-rw-r--r--kernel/trace/Kconfig6
-rw-r--r--kernel/trace/blktrace.c7
-rw-r--r--kernel/trace/ftrace.c3
-rw-r--r--kernel/trace/trace_events_user.c2
-rw-r--r--kernel/workqueue.c2
-rw-r--r--lib/Kconfig7
-rw-r--r--lib/Kconfig.debug26
-rw-r--r--lib/Kconfig.kasan2
-rw-r--r--lib/Kconfig.kcsan6
-rw-r--r--lib/debugobjects.c14
-rw-r--r--lib/fault-inject.c2
-rw-r--r--lib/find_bit_benchmark.c4
-rw-r--r--lib/fonts/fonts.c4
-rw-r--r--lib/iov_iter.c82
-rw-r--r--lib/is_signed_type_kunit.c4
-rw-r--r--lib/kobject.c2
-rw-r--r--lib/kunit/assert.c62
-rw-r--r--lib/kunit/debugfs.c2
-rw-r--r--lib/kunit/executor.c6
-rw-r--r--lib/kunit/kunit-example-test.c7
-rw-r--r--lib/kunit/string-stream.c5
-rw-r--r--lib/kunit/test.c15
-rw-r--r--lib/llist.c4
-rw-r--r--lib/lru_cache.c59
-rw-r--r--lib/math/div64.c15
-rw-r--r--lib/memcpy_kunit.c22
-rw-r--r--lib/notifier-error-inject.c2
-rw-r--r--lib/oid_registry.c1
-rw-r--r--lib/percpu-refcount.c3
-rw-r--r--lib/radix-tree.c2
-rw-r--r--lib/raid6/algos.c2
-rw-r--r--lib/raid6/s390vx.uc3
-rw-r--r--lib/reed_solomon/test_rslib.c6
-rw-r--r--lib/sbitmap.c148
-rw-r--r--lib/scatterlist.c25
-rw-r--r--lib/slub_kunit.c58
-rw-r--r--lib/test-string_helpers.c2
-rw-r--r--lib/test_fprobe.c5
-rw-r--r--lib/test_hexdump.c10
-rw-r--r--lib/test_kprobes.c5
-rw-r--r--lib/test_linear_ranges.c13
-rw-r--r--lib/test_list_sort.c2
-rw-r--r--lib/test_printf.c40
-rw-r--r--lib/test_rhashtable.c6
-rw-r--r--lib/test_vmalloc.c8
-rw-r--r--lib/vsprintf.c16
-rw-r--r--mm/Kconfig38
-rw-r--r--mm/Kconfig.debug2
-rw-r--r--mm/gup.c47
-rw-r--r--mm/huge_memory.c19
-rw-r--r--mm/hugetlb.c23
-rw-r--r--mm/kasan/generic.c19
-rw-r--r--mm/kasan/kasan_test.c6
-rw-r--r--mm/kfence/core.c4
-rw-r--r--mm/kfence/kfence_test.c4
-rw-r--r--mm/madvise.c2
-rw-r--r--mm/migrate.c16
-rw-r--r--mm/mmap.c14
-rw-r--r--mm/page_io.c4
-rw-r--r--mm/page_reporting.c50
-rw-r--r--mm/percpu.c44
-rw-r--r--mm/process_vm_access.c2
-rw-r--r--mm/shmem.c15
-rw-r--r--mm/slab.c113
-rw-r--r--mm/slab.h86
-rw-r--r--mm/slab_common.c27
-rw-r--r--mm/slub.c558
-rw-r--r--mm/swapfile.c5
-rw-r--r--net/802/garp.c2
-rw-r--r--net/802/mrp.c2
-rw-r--r--net/9p/client.c2
-rw-r--r--net/batman-adv/bat_iv_ogm.c4
-rw-r--r--net/batman-adv/bat_v_elp.c2
-rw-r--r--net/batman-adv/bat_v_ogm.c4
-rw-r--r--net/batman-adv/network-coding.c2
-rw-r--r--net/bluetooth/6lowpan.c2
-rw-r--r--net/bluetooth/a2mp.c2
-rw-r--r--net/bluetooth/mgmt.c5
-rw-r--r--net/bluetooth/smp.c2
-rw-r--r--net/can/j1939/socket.c2
-rw-r--r--net/can/j1939/transport.c2
-rw-r--r--net/ceph/messenger_v1.c4
-rw-r--r--net/ceph/messenger_v2.c14
-rw-r--r--net/ceph/mon_client.c2
-rw-r--r--net/ceph/osd_client.c2
-rw-r--r--net/compat.c3
-rw-r--r--net/core/dev_addr_lists_test.c4
-rw-r--r--net/core/dst.c2
-rw-r--r--net/core/neighbour.c4
-rw-r--r--net/core/pktgen.c37
-rw-r--r--net/core/sock.c3
-rw-r--r--net/core/stream.c2
-rw-r--r--net/ipv4/devinet.c19
-rw-r--r--net/ipv4/icmp.c2
-rw-r--r--net/ipv4/igmp.c6
-rw-r--r--net/ipv4/inet_connection_sock.c2
-rw-r--r--net/ipv4/inet_hashtables.c2
-rw-r--r--net/ipv4/route.c4
-rw-r--r--net/ipv4/tcp.c4
-rw-r--r--net/ipv4/tcp_bbr.c2
-rw-r--r--net/ipv4/tcp_input.c3
-rw-r--r--net/ipv6/addrconf.c8
-rw-r--r--net/ipv6/mcast.c10
-rw-r--r--net/ipv6/output_core.c8
-rw-r--r--net/ipv6/route.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_sync.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_twos.c4
-rw-r--r--net/netfilter/nf_conntrack_core.c4
-rw-r--r--net/netfilter/nf_nat_helper.c2
-rw-r--r--net/netlink/af_netlink.c2
-rw-r--r--net/packet/af_packet.c4
-rw-r--r--net/sched/act_gact.c2
-rw-r--r--net/sched/act_sample.c2
-rw-r--r--net/sched/sch_choke.c2
-rw-r--r--net/sched/sch_netem.c4
-rw-r--r--net/sctp/socket.c2
-rw-r--r--net/sctp/transport.c2
-rw-r--r--net/smc/smc_clc.c6
-rw-r--r--net/smc/smc_tx.c2
-rw-r--r--net/socket.c12
-rw-r--r--net/sunrpc/auth_gss/svcauth_gss.c64
-rw-r--r--net/sunrpc/cache.c2
-rw-r--r--net/sunrpc/clnt.c2
-rw-r--r--net/sunrpc/socklib.c6
-rw-r--r--net/sunrpc/svc.c4
-rw-r--r--net/sunrpc/svcsock.c4
-rw-r--r--net/sunrpc/xdr.c22
-rw-r--r--net/sunrpc/xprt.c2
-rw-r--r--net/sunrpc/xprtrdma/verbs.c2
-rw-r--r--net/sunrpc/xprtsock.c8
-rw-r--r--net/tipc/socket.c2
-rw-r--r--net/tipc/topsrv.c2
-rw-r--r--net/tls/tls_device.c4
-rw-r--r--net/vmw_vsock/af_vsock.c3
-rw-r--r--net/xfrm/espintcp.c2
-rw-r--r--net/xfrm/xfrm_state.c2
-rw-r--r--rust/Makefile22
-rw-r--r--rust/alloc/raw_vec.rs33
-rw-r--r--rust/alloc/vec/mod.rs89
-rw-r--r--rust/build_error.rs31
-rw-r--r--rust/exports.c5
-rw-r--r--rust/kernel/build_assert.rs82
-rw-r--r--rust/kernel/error.rs90
-rw-r--r--rust/kernel/lib.rs9
-rw-r--r--rust/kernel/prelude.rs20
-rw-r--r--rust/kernel/print.rs214
-rw-r--r--rust/kernel/static_assert.rs34
-rw-r--r--rust/kernel/std_vendor.rs163
-rw-r--r--rust/kernel/str.rs523
-rw-r--r--rust/kernel/types.rs37
-rw-r--r--rust/macros/concat_idents.rs23
-rw-r--r--rust/macros/helpers.rs24
-rw-r--r--rust/macros/lib.rs108
-rw-r--r--rust/macros/module.rs10
-rw-r--r--rust/macros/vtable.rs95
-rw-r--r--samples/landlock/sandboxer.c29
-rw-r--r--samples/rust/Kconfig10
-rw-r--r--samples/rust/Makefile1
-rw-r--r--samples/rust/rust_minimal.rs8
-rw-r--r--samples/rust/rust_print.rs54
-rw-r--r--scripts/Makefile.build2
-rw-r--r--scripts/Makefile.lib35
-rwxr-xr-xscripts/checkpatch.pl20
-rw-r--r--scripts/dtc/checks.c15
-rw-r--r--scripts/dtc/dtc-lexer.l2
-rw-r--r--scripts/dtc/dtc-parser.y13
-rw-r--r--scripts/dtc/libfdt/fdt.c20
-rw-r--r--scripts/dtc/libfdt/fdt.h4
-rw-r--r--scripts/dtc/libfdt/fdt_addresses.c2
-rw-r--r--scripts/dtc/libfdt/fdt_overlay.c29
-rw-r--r--scripts/dtc/libfdt/fdt_ro.c2
-rw-r--r--scripts/dtc/libfdt/libfdt.h25
-rw-r--r--scripts/dtc/livetree.c39
-rw-r--r--scripts/dtc/util.c15
-rw-r--r--scripts/dtc/util.h4
-rw-r--r--scripts/dtc/version_gen.h2
-rwxr-xr-xscripts/generate_rust_analyzer.py8
-rw-r--r--scripts/head-object-list.txt1
-rw-r--r--scripts/kallsyms.c78
-rwxr-xr-xscripts/kernel-doc54
-rwxr-xr-xscripts/link-vmlinux.sh4
-rw-r--r--scripts/module.lds.S6
-rw-r--r--scripts/spelling.txt33
-rwxr-xr-xscripts/sphinx-pre-install8
-rw-r--r--security/apparmor/Kconfig4
-rw-r--r--security/apparmor/Makefile3
-rw-r--r--security/apparmor/domain.c11
-rw-r--r--security/apparmor/file.c4
-rw-r--r--security/apparmor/include/policy_unpack.h50
-rw-r--r--security/apparmor/lsm.c60
-rw-r--r--security/apparmor/policy_unpack.c238
-rw-r--r--security/apparmor/policy_unpack_test.c69
-rw-r--r--security/commoncap.c73
-rw-r--r--security/device_cgroup.c33
-rw-r--r--security/integrity/digsig.c6
-rw-r--r--security/integrity/evm/evm_crypto.c5
-rw-r--r--security/integrity/evm/evm_main.c153
-rw-r--r--security/integrity/ima/Kconfig2
-rw-r--r--security/integrity/ima/ima.h5
-rw-r--r--security/integrity/ima/ima_appraise.c15
-rw-r--r--security/integrity/ima/ima_main.c13
-rw-r--r--security/integrity/ima/ima_policy.c85
-rw-r--r--security/integrity/ima/ima_template.c9
-rw-r--r--security/integrity/ima/ima_template_lib.c11
-rw-r--r--security/integrity/platform_certs/load_uefi.c1
-rw-r--r--security/keys/encrypted-keys/encrypted.c6
-rw-r--r--security/keys/keyctl.c4
-rw-r--r--security/keys/trusted-keys/trusted_tee.c3
-rw-r--r--security/landlock/fs.c206
-rw-r--r--security/landlock/fs.h24
-rw-r--r--security/landlock/limits.h2
-rw-r--r--security/landlock/setup.c1
-rw-r--r--security/landlock/syscalls.c2
-rw-r--r--security/lsm_audit.c1
-rw-r--r--security/security.c109
-rw-r--r--security/selinux/hooks.c35
-rw-r--r--security/selinux/selinuxfs.c4
-rw-r--r--security/selinux/ss/services.c54
-rw-r--r--security/selinux/ss/services.h15
-rw-r--r--security/selinux/ss/sidtab.c23
-rw-r--r--security/selinux/ss/sidtab.h3
-rw-r--r--security/smack/smack_lsm.c90
-rw-r--r--security/tomoyo/tomoyo.c13
-rw-r--r--sound/aoa/codecs/onyx.c5
-rw-r--r--sound/aoa/codecs/tas.c5
-rw-r--r--sound/core/memalloc.c49
-rw-r--r--sound/core/pcm_native.c24
-rw-r--r--sound/core/pcm_trace.h6
-rw-r--r--sound/core/rawmidi.c2
-rw-r--r--sound/drivers/mts64.c3
-rw-r--r--sound/firewire/dice/Makefile2
-rw-r--r--sound/firewire/dice/dice-focusrite.c23
-rw-r--r--sound/firewire/dice/dice.c10
-rw-r--r--sound/firewire/dice/dice.h1
-rw-r--r--sound/hda/ext/hdac_ext_controller.c116
-rw-r--r--sound/hda/ext/hdac_ext_stream.c203
-rw-r--r--sound/hda/hdac_stream.c158
-rw-r--r--sound/pci/asihpi/asihpi.c2
-rw-r--r--sound/pci/asihpi/hpioctl.c2
-rw-r--r--sound/pci/cs5535audio/cs5535audio_pcm.c4
-rw-r--r--sound/pci/hda/Kconfig2
-rw-r--r--sound/pci/hda/cs35l41_hda.c1
-rw-r--r--sound/pci/hda/cs35l41_hda_i2c.c4
-rw-r--r--sound/pci/hda/hda_cs_dsp_ctl.c1
-rw-r--r--sound/pci/hda/patch_cs8409.c2
-rw-r--r--sound/pci/hda/patch_realtek.c39
-rw-r--r--sound/ppc/keywest.c5
-rw-r--r--sound/soc/amd/Kconfig4
-rw-r--r--sound/soc/amd/acp-da7219-max98357a.c3
-rw-r--r--sound/soc/amd/acp/acp-i2s.c16
-rw-r--r--sound/soc/amd/acp/acp-mach-common.c62
-rw-r--r--sound/soc/amd/acp/acp-platform.c8
-rw-r--r--sound/soc/amd/ps/acp63.h (renamed from sound/soc/amd/ps/acp62.h)25
-rw-r--r--sound/soc/amd/ps/pci-ps.c141
-rw-r--r--sound/soc/amd/ps/ps-mach.c30
-rw-r--r--sound/soc/amd/ps/ps-pdm-dma.c188
-rw-r--r--sound/soc/amd/yc/acp6x-mach.c7
-rw-r--r--sound/soc/atmel/mchp-spdiftx.c165
-rw-r--r--sound/soc/codecs/Kconfig10
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/adau1372.c32
-rw-r--r--sound/soc/codecs/adau1373.c1
-rw-r--r--sound/soc/codecs/adau17x1.c1
-rw-r--r--sound/soc/codecs/ak4458.c13
-rw-r--r--sound/soc/codecs/cs35l36.c4
-rw-r--r--sound/soc/codecs/cs42l83-i2c.c2
-rw-r--r--sound/soc/codecs/cs42xx8-i2c.c28
-rw-r--r--sound/soc/codecs/cs42xx8.c22
-rw-r--r--sound/soc/codecs/cs42xx8.h3
-rw-r--r--sound/soc/codecs/da7219-aad.c46
-rw-r--r--sound/soc/codecs/da7219-aad.h1
-rw-r--r--sound/soc/codecs/da7219.c9
-rwxr-xr-xsound/soc/codecs/es8326.c5
-rw-r--r--sound/soc/codecs/hda.c12
-rw-r--r--sound/soc/codecs/hdac_hda.c6
-rw-r--r--sound/soc/codecs/hdac_hdmi.c8
-rw-r--r--sound/soc/codecs/hdmi-codec.c30
-rw-r--r--sound/soc/codecs/jz4725b.c81
-rw-r--r--sound/soc/codecs/lpass-tx-macro.c149
-rw-r--r--sound/soc/codecs/lpass-wsa-macro.c6
-rw-r--r--sound/soc/codecs/max98373-sdw.c31
-rw-r--r--sound/soc/codecs/max98396.c6
-rw-r--r--sound/soc/codecs/max9867.c33
-rw-r--r--sound/soc/codecs/nau8315.c2
-rw-r--r--sound/soc/codecs/nau8825.c135
-rw-r--r--sound/soc/codecs/nau8825.h23
-rw-r--r--sound/soc/codecs/pcm512x.c8
-rw-r--r--sound/soc/codecs/rt1308-sdw.c72
-rw-r--r--sound/soc/codecs/rt1308-sdw.h2
-rw-r--r--sound/soc/codecs/rt1316-sdw.c71
-rw-r--r--sound/soc/codecs/rt1316-sdw.h2
-rw-r--r--sound/soc/codecs/rt1318-sdw.c884
-rw-r--r--sound/soc/codecs/rt1318-sdw.h101
-rw-r--r--sound/soc/codecs/rt298.c7
-rw-r--r--sound/soc/codecs/rt5640.c8
-rw-r--r--sound/soc/codecs/rt5682-sdw.c28
-rw-r--r--sound/soc/codecs/rt5682.c2
-rw-r--r--sound/soc/codecs/rt5682.h2
-rw-r--r--sound/soc/codecs/rt5682s.c22
-rw-r--r--sound/soc/codecs/rt5682s.h2
-rw-r--r--sound/soc/codecs/rt700.c32
-rw-r--r--sound/soc/codecs/rt711-sdca.c27
-rw-r--r--sound/soc/codecs/rt711.c27
-rw-r--r--sound/soc/codecs/rt715-sdca.c25
-rw-r--r--sound/soc/codecs/rt715.c73
-rw-r--r--sound/soc/codecs/sdw-mockup.c28
-rw-r--r--sound/soc/codecs/simple-mux.c9
-rw-r--r--sound/soc/codecs/src4xxx-i2c.c5
-rw-r--r--sound/soc/codecs/tas2780.c5
-rw-r--r--sound/soc/codecs/tlv320aic3x.c120
-rw-r--r--sound/soc/codecs/tlv320aic3x.h43
-rw-r--r--sound/soc/codecs/twl4030.c6
-rw-r--r--sound/soc/codecs/wcd938x.c4
-rw-r--r--sound/soc/codecs/wm8961.c7
-rw-r--r--sound/soc/codecs/wm8978.c2
-rw-r--r--sound/soc/codecs/wm_adsp.c39
-rw-r--r--sound/soc/codecs/wm_adsp.h1
-rw-r--r--sound/soc/codecs/wsa883x.c28
-rw-r--r--sound/soc/fsl/fsl_micfil.c447
-rw-r--r--sound/soc/fsl/fsl_micfil.h6
-rw-r--r--sound/soc/fsl/fsl_rpmsg.c6
-rw-r--r--sound/soc/fsl/fsl_sai.c23
-rw-r--r--sound/soc/fsl/fsl_sai.h1
-rw-r--r--sound/soc/fsl/fsl_xcvr.c40
-rw-r--r--sound/soc/fsl/fsl_xcvr.h21
-rw-r--r--sound/soc/fsl/imx-audio-rpmsg.c3
-rw-r--r--sound/soc/fsl/imx-pcm-rpmsg.c10
-rw-r--r--sound/soc/fsl/imx-rpmsg.c6
-rw-r--r--sound/soc/generic/audio-graph-card2-custom-sample.dtsi10
-rw-r--r--sound/soc/generic/audio-graph-card2.c6
-rw-r--r--sound/soc/generic/simple-card-utils.c35
-rw-r--r--sound/soc/intel/Kconfig2
-rw-r--r--sound/soc/intel/avs/apl.c6
-rw-r--r--sound/soc/intel/avs/avs.h12
-rw-r--r--sound/soc/intel/avs/board_selection.c22
-rw-r--r--sound/soc/intel/avs/boards/Kconfig10
-rw-r--r--sound/soc/intel/avs/boards/Makefile2
-rw-r--r--sound/soc/intel/avs/boards/da7219.c41
-rw-r--r--sound/soc/intel/avs/boards/hdaudio.c1
-rw-r--r--sound/soc/intel/avs/boards/max98373.c2
-rw-r--r--sound/soc/intel/avs/boards/max98927.c236
-rw-r--r--sound/soc/intel/avs/boards/nau8825.c35
-rw-r--r--sound/soc/intel/avs/boards/rt274.c30
-rw-r--r--sound/soc/intel/avs/boards/rt286.c37
-rw-r--r--sound/soc/intel/avs/boards/rt298.c61
-rw-r--r--sound/soc/intel/avs/boards/rt5682.c31
-rw-r--r--sound/soc/intel/avs/boards/ssm4567.c2
-rw-r--r--sound/soc/intel/avs/core.c116
-rw-r--r--sound/soc/intel/avs/ipc.c8
-rw-r--r--sound/soc/intel/avs/loader.c28
-rw-r--r--sound/soc/intel/avs/messages.c19
-rw-r--r--sound/soc/intel/avs/messages.h2
-rw-r--r--sound/soc/intel/avs/pcm.c416
-rw-r--r--sound/soc/intel/avs/skl.c4
-rw-r--r--sound/soc/intel/avs/topology.c10
-rw-r--r--sound/soc/intel/boards/Kconfig1
-rw-r--r--sound/soc/intel/boards/Makefile4
-rw-r--r--sound/soc/intel/boards/bdw-rt5650.c2
-rw-r--r--sound/soc/intel/boards/bdw-rt5677.c2
-rw-r--r--sound/soc/intel/boards/bdw_rt286.c55
-rw-r--r--sound/soc/intel/boards/bxt_da7219_max98357a.c3
-rw-r--r--sound/soc/intel/boards/bxt_rt298.c2
-rw-r--r--sound/soc/intel/boards/bytcht_cx2072x.c2
-rw-r--r--sound/soc/intel/boards/bytcht_es8316.c2
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c2
-rw-r--r--sound/soc/intel/boards/bytcr_rt5651.c2
-rw-r--r--sound/soc/intel/boards/bytcr_wm5102.c2
-rw-r--r--sound/soc/intel/boards/cht_bsw_max98090_ti.c2
-rw-r--r--sound/soc/intel/boards/cht_bsw_nau8824.c2
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5645.c2
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5672.c2
-rw-r--r--sound/soc/intel/boards/kbl_da7219_max98357a.c3
-rw-r--r--sound/soc/intel/boards/kbl_da7219_max98927.c3
-rw-r--r--sound/soc/intel/boards/skl_nau88l25_max98357a.c2
-rw-r--r--sound/soc/intel/boards/skl_nau88l25_ssm4567.c2
-rw-r--r--sound/soc/intel/boards/sof_cirrus_common.c2
-rw-r--r--sound/soc/intel/boards/sof_da7219_max98373.c4
-rw-r--r--sound/soc/intel/boards/sof_nau8825.c16
-rw-r--r--sound/soc/intel/boards/sof_rt5682.c7
-rw-r--r--sound/soc/intel/boards/sof_sdw.c50
-rw-r--r--sound/soc/intel/boards/sof_sdw_amp_coeff_tables.h300
-rw-r--r--sound/soc/intel/boards/sof_sdw_common.h10
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt1308.c120
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt1316.c119
-rw-r--r--sound/soc/intel/boards/sof_sdw_rt1318.c120
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-adl-match.c16
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-mtl-match.c59
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-rpl-match.c157
-rw-r--r--sound/soc/intel/skylake/skl-messages.c6
-rw-r--r--sound/soc/intel/skylake/skl-pcm.c35
-rw-r--r--sound/soc/intel/skylake/skl.c11
-rw-r--r--sound/soc/jz4740/Kconfig1
-rw-r--r--sound/soc/jz4740/jz4740-i2s.c485
-rw-r--r--sound/soc/jz4740/jz4740-i2s.h10
-rw-r--r--sound/soc/kirkwood/kirkwood-i2s.c135
-rw-r--r--sound/soc/kirkwood/kirkwood.h2
-rw-r--r--sound/soc/mediatek/common/mtk-btcvsd.c6
-rw-r--r--sound/soc/mediatek/mt2701/mt2701-cs42448.c1
-rw-r--r--sound/soc/mediatek/mt2701/mt2701-wm8960.c1
-rw-r--r--sound/soc/mediatek/mt6797/mt6797-mt6351.c1
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-afe-pcm.c20
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-da7219-max98357.c4
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c1
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c7
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c105
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c1
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-mt6359.c1
-rw-r--r--sound/soc/meson/axg-pdm.c2
-rw-r--r--sound/soc/pxa/mmp-pcm.c2
-rw-r--r--sound/soc/qcom/Kconfig16
-rw-r--r--sound/soc/qcom/common.c2
-rw-r--r--sound/soc/qcom/common.h23
-rw-r--r--sound/soc/qcom/lpass-sc7180.c23
-rw-r--r--sound/soc/qcom/lpass-sc7280.c19
-rw-r--r--sound/soc/qcom/qdsp6/audioreach.c310
-rw-r--r--sound/soc/qcom/qdsp6/audioreach.h47
-rw-r--r--sound/soc/qcom/qdsp6/q6apm.c84
-rw-r--r--sound/soc/qcom/qdsp6/q6apm.h6
-rw-r--r--sound/soc/qcom/qdsp6/q6prm.c2
-rw-r--r--sound/soc/qcom/qdsp6/topology.c243
-rw-r--r--sound/soc/rockchip/rk3399_gru_sound.c3
-rw-r--r--sound/soc/rockchip/rockchip_i2s_tdm.c19
-rw-r--r--sound/soc/sh/Kconfig2
-rw-r--r--sound/soc/sh/rcar/adg.c4
-rw-r--r--sound/soc/sh/rcar/core.c7
-rw-r--r--sound/soc/soc-core.c8
-rw-r--r--sound/soc/soc-dai.c11
-rw-r--r--sound/soc/soc-dapm.c189
-rw-r--r--sound/soc/soc-pcm.c12
-rw-r--r--sound/soc/sof/Kconfig20
-rw-r--r--sound/soc/sof/Makefile6
-rw-r--r--sound/soc/sof/amd/Kconfig1
-rw-r--r--sound/soc/sof/amd/acp-common.c109
-rw-r--r--sound/soc/sof/amd/acp-ipc.c43
-rw-r--r--sound/soc/sof/amd/acp-loader.c6
-rw-r--r--sound/soc/sof/amd/acp.c12
-rw-r--r--sound/soc/sof/amd/acp.h18
-rw-r--r--sound/soc/sof/amd/rembrandt.c16
-rw-r--r--sound/soc/sof/amd/renoir.c16
-rw-r--r--sound/soc/sof/intel/Kconfig2
-rw-r--r--sound/soc/sof/intel/Makefile2
-rw-r--r--sound/soc/sof/intel/apl.c4
-rw-r--r--sound/soc/sof/intel/bdw.c6
-rw-r--r--sound/soc/sof/intel/byt.c12
-rw-r--r--sound/soc/sof/intel/cnl.c35
-rw-r--r--sound/soc/sof/intel/hda-bus.c23
-rw-r--r--sound/soc/sof/intel/hda-codec.c252
-rw-r--r--sound/soc/sof/intel/hda-common-ops.c6
-rw-r--r--sound/soc/sof/intel/hda-ctrl.c102
-rw-r--r--sound/soc/sof/intel/hda-dai.c95
-rw-r--r--sound/soc/sof/intel/hda-dsp.c83
-rw-r--r--sound/soc/sof/intel/hda-ipc.c27
-rw-r--r--sound/soc/sof/intel/hda-loader-skl.c37
-rw-r--r--sound/soc/sof/intel/hda-loader.c98
-rw-r--r--sound/soc/sof/intel/hda-mlink.c89
-rw-r--r--sound/soc/sof/intel/hda-pcm.c3
-rw-r--r--sound/soc/sof/intel/hda-stream.c93
-rw-r--r--sound/soc/sof/intel/hda.c139
-rw-r--r--sound/soc/sof/intel/hda.h113
-rw-r--r--sound/soc/sof/intel/icl.c6
-rw-r--r--sound/soc/sof/intel/mtl.c161
-rw-r--r--sound/soc/sof/intel/mtl.h2
-rw-r--r--sound/soc/sof/intel/pci-apl.c6
-rw-r--r--sound/soc/sof/intel/pci-cnl.c9
-rw-r--r--sound/soc/sof/intel/pci-icl.c6
-rw-r--r--sound/soc/sof/intel/pci-mtl.c3
-rw-r--r--sound/soc/sof/intel/pci-tgl.c24
-rw-r--r--sound/soc/sof/intel/pci-tng.c6
-rw-r--r--sound/soc/sof/intel/shim.h3
-rw-r--r--sound/soc/sof/intel/tgl.c15
-rw-r--r--sound/soc/sof/ipc.c14
-rw-r--r--sound/soc/sof/ipc3-loader.c26
-rw-r--r--sound/soc/sof/ipc3-pcm.c2
-rw-r--r--sound/soc/sof/ipc3-topology.c36
-rw-r--r--sound/soc/sof/ipc3.c4
-rw-r--r--sound/soc/sof/ipc4-loader.c244
-rw-r--r--sound/soc/sof/ipc4-pcm.c4
-rw-r--r--sound/soc/sof/ipc4-priv.h67
-rw-r--r--sound/soc/sof/ipc4-topology.c214
-rw-r--r--sound/soc/sof/ipc4.c45
-rw-r--r--sound/soc/sof/loader.c25
-rw-r--r--sound/soc/sof/mediatek/mt8186/mt8186.c7
-rw-r--r--sound/soc/sof/ops.h51
-rw-r--r--sound/soc/sof/sof-audio.c5
-rw-r--r--sound/soc/sof/sof-audio.h43
-rw-r--r--sound/soc/sof/sof-client-probes-ipc3.c236
-rw-r--r--sound/soc/sof/sof-client-probes-ipc4.c281
-rw-r--r--sound/soc/sof/sof-client-probes.c278
-rw-r--r--sound/soc/sof/sof-client-probes.h34
-rw-r--r--sound/soc/sof/sof-client.c34
-rw-r--r--sound/soc/sof/sof-client.h6
-rw-r--r--sound/soc/sof/sof-pci-dev.c26
-rw-r--r--sound/soc/sof/sof-priv.h36
-rw-r--r--sound/soc/sof/topology.c187
-rw-r--r--sound/soc/sunxi/sun50i-dmic.c5
-rw-r--r--sound/soc/tegra/tegra210_mbdrc.c4
-rw-r--r--sound/soc/tegra/tegra210_mbdrc.h2
-rw-r--r--sound/soc/ti/davinci-mcasp.c7
-rw-r--r--sound/soc/uniphier/aio-core.c11
-rw-r--r--sound/usb/endpoint.c7
-rw-r--r--sound/usb/pcm.c13
-rw-r--r--sound/usb/quirks.c2
-rw-r--r--sound/usb/usbaudio.h4
-rw-r--r--tools/accounting/procacct.c7
-rw-r--r--tools/arch/x86/intel_sdsi/intel_sdsi.c464
-rw-r--r--tools/memory-model/Documentation/explanation.txt7
-rw-r--r--tools/objtool/check.c10
-rw-r--r--tools/power/acpi/tools/acpidump/Makefile1
-rw-r--r--tools/power/acpi/tools/acpidump/apdump.c4
-rw-r--r--tools/power/cpupower/Makefile15
-rw-r--r--tools/power/cpupower/lib/powercap.c290
-rw-r--r--tools/power/cpupower/lib/powercap.h54
-rw-r--r--tools/power/cpupower/man/cpupower-powercap-info.125
-rw-r--r--tools/power/cpupower/po/ka.po983
-rw-r--r--tools/power/cpupower/utils/builtin.h2
-rw-r--r--tools/power/cpupower/utils/cpufreq-info.c4
-rw-r--r--tools/power/cpupower/utils/cpuidle-info.c4
-rw-r--r--tools/power/cpupower/utils/cpupower-info.c4
-rw-r--r--tools/power/cpupower/utils/cpupower.c1
-rw-r--r--tools/power/cpupower/utils/idle_monitor/cpupower-monitor.c7
-rw-r--r--tools/power/cpupower/utils/idle_monitor/idle_monitors.def1
-rw-r--r--tools/power/cpupower/utils/idle_monitor/rapl_monitor.c148
-rw-r--r--tools/power/cpupower/utils/powercap-info.c117
-rwxr-xr-xtools/power/pm-graph/sleepgraph.py2
-rw-r--r--tools/testing/cxl/Kbuild2
-rw-r--r--tools/testing/cxl/config_check.c2
-rw-r--r--tools/testing/cxl/test/cxl.c303
-rw-r--r--tools/testing/cxl/test/mem.c453
-rw-r--r--tools/testing/cxl/test/mock.c19
-rw-r--r--tools/testing/cxl/test/mock.h3
-rwxr-xr-xtools/testing/ktest/ktest.pl32
-rw-r--r--tools/testing/ktest/sample.conf8
-rwxr-xr-xtools/testing/kunit/kunit.py36
-rw-r--r--tools/testing/kunit/kunit_parser.py188
-rwxr-xr-xtools/testing/kunit/kunit_tool_test.py164
-rw-r--r--tools/testing/kunit/test_data/test_parse_ktap_output.log8
-rw-r--r--tools/testing/kunit/test_data/test_parse_subtest_header.log7
-rw-r--r--tools/testing/nvdimm/Kbuild1
-rw-r--r--tools/testing/nvdimm/dimm_devs.c30
-rw-r--r--tools/testing/selftests/Makefile1
-rw-r--r--tools/testing/selftests/alsa/.gitignore1
-rw-r--r--tools/testing/selftests/alsa/Makefile15
-rw-r--r--tools/testing/selftests/alsa/alsa-local.h24
-rw-r--r--tools/testing/selftests/alsa/conf.c448
-rw-r--r--tools/testing/selftests/alsa/conf.d/Lenovo_ThinkPad_P1_Gen2.conf79
-rw-r--r--tools/testing/selftests/alsa/mixer-test.c53
-rw-r--r--tools/testing/selftests/alsa/pcm-test.c489
-rw-r--r--tools/testing/selftests/amd-pstate/Makefile11
-rwxr-xr-xtools/testing/selftests/amd-pstate/amd-pstate-ut.sh56
-rwxr-xr-xtools/testing/selftests/amd-pstate/basic.sh38
-rwxr-xr-xtools/testing/selftests/amd-pstate/gitsource.sh354
-rwxr-xr-xtools/testing/selftests/amd-pstate/run.sh387
-rwxr-xr-xtools/testing/selftests/amd-pstate/tbench.sh339
-rw-r--r--tools/testing/selftests/arm64/abi/hwcap.c32
-rw-r--r--tools/testing/selftests/arm64/abi/syscall-abi-asm.S4
-rw-r--r--tools/testing/selftests/arm64/fp/fp-stress.c120
-rw-r--r--tools/testing/selftests/arm64/mte/check_buffer_fill.c12
-rw-r--r--tools/testing/selftests/arm64/mte/check_mmap_options.c9
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/TODO1
-rw-r--r--tools/testing/selftests/arm64/signal/testcases/testcases.c21
-rw-r--r--tools/testing/selftests/cgroup/cgroup_util.c5
-rwxr-xr-xtools/testing/selftests/cgroup/test_cpuset_prs.sh19
-rw-r--r--tools/testing/selftests/cgroup/test_kmem.c6
-rwxr-xr-xtools/testing/selftests/efivarfs/efivarfs.sh5
-rw-r--r--tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc15
-rw-r--r--tools/testing/selftests/ftrace/test.d/functions8
-rw-r--r--tools/testing/selftests/ftrace/test.d/preemptirq/irqsoff_tracer.tc8
-rw-r--r--tools/testing/selftests/ftrace/test.d/tracer/wakeup.tc7
-rw-r--r--tools/testing/selftests/ftrace/test.d/tracer/wakeup_rt.tc7
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-field-variable-support.tc2
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-inter-event-combined-hist.tc2
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onchange-action-hist.tc2
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-action-hist.tc2
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmatch-onmax-action-hist.tc2
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onmax-action-hist.tc2
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-snapshot-action-hist.tc2
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-eprobe.tc2
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-synthetic-event-dynstring.tc2
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-trace-action-hist.tc2
-rwxr-xr-xtools/testing/selftests/gpio/gpio-sim.sh2
-rwxr-xr-xtools/testing/selftests/kselftest_deps.sh2
-rw-r--r--tools/testing/selftests/landlock/base_test.c38
-rw-r--r--tools/testing/selftests/landlock/common.h85
-rw-r--r--tools/testing/selftests/landlock/fs_test.c468
-rw-r--r--tools/testing/selftests/lib.mk5
-rw-r--r--tools/testing/selftests/nolibc/Makefile3
-rw-r--r--tools/testing/selftests/nolibc/nolibc-test.c7
-rw-r--r--tools/testing/selftests/proc/proc-uptime-002.c3
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/config2csv.sh3
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/config_override.sh3
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/configcheck.sh3
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/configinit.sh3
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-again.sh49
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-assign-cpus.sh3
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-build.sh3
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-end-run-stats.sh3
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-recheck.sh2
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-remote.sh13
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-test-1-run-batch.sh3
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-test-1-run-qemu.sh5
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh3
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-transform.sh68
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm.sh3
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/parse-build.sh3
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/torture.sh145
-rw-r--r--tools/testing/selftests/rtc/rtctest.c33
-rw-r--r--tools/testing/selftests/seccomp/seccomp_bpf.c6
-rwxr-xr-xtools/testing/selftests/splice/short_splice_read.sh4
-rw-r--r--tools/testing/selftests/tdx/Makefile7
-rw-r--r--tools/testing/selftests/tdx/config1
-rw-r--r--tools/testing/selftests/tdx/tdx_guest_test.c163
-rw-r--r--tools/testing/selftests/timens/.gitignore1
-rw-r--r--tools/testing/selftests/timens/Makefile2
-rw-r--r--tools/testing/selftests/timens/vfork_exec.c139
-rw-r--r--tools/testing/selftests/tpm2/Makefile2
-rwxr-xr-xtools/testing/selftests/tpm2/test_async.sh10
-rwxr-xr-xtools/testing/selftests/tpm2/test_smoke.sh1
-rw-r--r--tools/testing/selftests/vDSO/vdso_test_getcpu.c4
-rw-r--r--tools/testing/selftests/vDSO/vdso_test_gettimeofday.c3
-rw-r--r--tools/testing/selftests/vm/.gitignore2
-rw-r--r--tools/testing/selftests/vm/pkey-x86.h12
-rw-r--r--tools/testing/selftests/vm/protection_keys.c131
-rw-r--r--tools/testing/selftests/watchdog/watchdog-test.c106
-rw-r--r--tools/testing/selftests/wireguard/qemu/kernel.config2
-rw-r--r--tools/tracing/rtla/src/osnoise.c9
-rw-r--r--tools/tracing/rtla/src/rtla.c12
-rw-r--r--tools/tracing/rtla/src/timerlat.c9
-rw-r--r--tools/verification/rv/Makefile141
-rw-r--r--tools/verification/rv/README.txt38
-rw-r--r--tools/verification/rv/include/in_kernel.h3
-rw-r--r--tools/verification/rv/include/rv.h12
-rw-r--r--tools/verification/rv/include/trace.h16
-rw-r--r--tools/verification/rv/include/utils.h8
-rw-r--r--tools/verification/rv/src/in_kernel.c698
-rw-r--r--tools/verification/rv/src/rv.c188
-rw-r--r--tools/verification/rv/src/trace.c133
-rw-r--r--tools/verification/rv/src/utils.c47
-rw-r--r--tools/vm/slabinfo.c6
6795 files changed, 272860 insertions, 116134 deletions
diff --git a/.clang-format b/.clang-format
index 8d01225bfcb7..bcf60344f9f5 100644
--- a/.clang-format
+++ b/.clang-format
@@ -222,6 +222,7 @@ ForEachMacros:
- 'for_each_component_dais'
- 'for_each_component_dais_safe'
- 'for_each_console'
+ - 'for_each_console_srcu'
- 'for_each_cpu'
- 'for_each_cpu_and'
- 'for_each_cpu_not'
diff --git a/.gitignore b/.gitignore
index 5da004814678..3ec73ead6757 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,7 @@
*.dtb
*.dtbo
*.dtb.S
+*.dtbo.S
*.dwo
*.elf
*.gcno
diff --git a/.mailmap b/.mailmap
index bbb6a077d227..ccba4cf0d893 100644
--- a/.mailmap
+++ b/.mailmap
@@ -228,6 +228,7 @@ Juha Yrjola <at solidboot.com>
Juha Yrjola <juha.yrjola@nokia.com>
Juha Yrjola <juha.yrjola@solidboot.com>
Julien Thierry <julien.thierry.kdev@gmail.com> <julien.thierry@arm.com>
+Iskren Chernev <me@iskren.info> <iskren.chernev@gmail.com>
Kalle Valo <kvalo@kernel.org> <kvalo@codeaurora.org>
Kalyan Thota <quic_kalyant@quicinc.com> <kalyan_t@codeaurora.org>
Kay Sievers <kay.sievers@vrfy.org>
@@ -287,6 +288,7 @@ Matthew Wilcox <willy@infradead.org> <willy@linux.intel.com>
Matthew Wilcox <willy@infradead.org> <willy@parisc-linux.org>
Matthias Fuchs <socketcan@esd.eu> <matthias.fuchs@esd.eu>
Matthieu CASTET <castet.matthieu@free.fr>
+Matti Vaittinen <mazziesaccount@gmail.com> <matti.vaittinen@fi.rohmeurope.com>
Matt Ranostay <matt.ranostay@konsulko.com> <matt@ranostay.consulting>
Matt Ranostay <mranostay@gmail.com> Matthew Ranostay <mranostay@embeddedalley.com>
Matt Ranostay <mranostay@gmail.com> <matt.ranostay@intel.com>
@@ -372,6 +374,8 @@ Ricardo Ribalda <ribalda@kernel.org> <ricardo.ribalda@gmail.com>
Roman Gushchin <roman.gushchin@linux.dev> <guro@fb.com>
Roman Gushchin <roman.gushchin@linux.dev> <guroan@gmail.com>
Roman Gushchin <roman.gushchin@linux.dev> <klamm@yandex-team.ru>
+Muchun Song <muchun.song@linux.dev> <songmuchun@bytedance.com>
+Muchun Song <muchun.song@linux.dev> <smuchun@gmail.com>
Ross Zwisler <zwisler@kernel.org> <ross.zwisler@linux.intel.com>
Rudolf Marek <R.Marek@sh.cvut.cz>
Rui Saraiva <rmps@joel.ist.utl.pt>
diff --git a/Documentation/ABI/testing/debugfs-dell-wmi-ddv b/Documentation/ABI/testing/debugfs-dell-wmi-ddv
new file mode 100644
index 000000000000..fbcc5d6f7388
--- /dev/null
+++ b/Documentation/ABI/testing/debugfs-dell-wmi-ddv
@@ -0,0 +1,21 @@
+What: /sys/kernel/debug/dell-wmi-ddv-<wmi_device_name>/fan_sensor_information
+Date: September 2022
+KernelVersion: 6.1
+Contact: Armin Wolf <W_Armin@gmx.de>
+Description:
+ This file contains the contents of the fan sensor information buffer,
+ which contains fan sensor entries and a terminating character (0xFF).
+
+ Each fan sensor entry consists of three bytes with an unknown meaning,
+ interested people may use this file for reverse-engineering.
+
+What: /sys/kernel/debug/dell-wmi-ddv-<wmi_device_name>/thermal_sensor_information
+Date: September 2022
+KernelVersion: 6.1
+Contact: Armin Wolf <W_Armin@gmx.de>
+Description:
+ This file contains the contents of the thermal sensor information buffer,
+ which contains thermal sensor entries and a terminating character (0xFF).
+
+ Each thermal sensor entry consists of five bytes with an unknown meaning,
+ interested people may use this file for reverse-engineering.
diff --git a/Documentation/ABI/testing/debugfs-pktcdvd b/Documentation/ABI/testing/debugfs-pktcdvd
deleted file mode 100644
index f6f65a4faea0..000000000000
--- a/Documentation/ABI/testing/debugfs-pktcdvd
+++ /dev/null
@@ -1,18 +0,0 @@
-What: /sys/kernel/debug/pktcdvd/pktcdvd[0-7]
-Date: Oct. 2006
-KernelVersion: 2.6.20
-Contact: Thomas Maier <balagi@justmail.de>
-Description:
-
-The pktcdvd module (packet writing driver) creates
-these files in debugfs:
-
-/sys/kernel/debug/pktcdvd/pktcdvd[0-7]/
-
- ==== ====== ====================================
- info 0444 Lots of driver statistics and infos.
- ==== ====== ====================================
-
-Example::
-
- cat /sys/kernel/debug/pktcdvd/pktcdvd0/info
diff --git a/Documentation/ABI/testing/sysfs-bus-nvdimm b/Documentation/ABI/testing/sysfs-bus-nvdimm
index 1c1f5acbf53d..de8c5a59c77f 100644
--- a/Documentation/ABI/testing/sysfs-bus-nvdimm
+++ b/Documentation/ABI/testing/sysfs-bus-nvdimm
@@ -41,3 +41,17 @@ KernelVersion: 5.18
Contact: Kajol Jain <kjain@linux.ibm.com>
Description: (RO) This sysfs file exposes the cpumask which is designated to
to retrieve nvdimm pmu event counter data.
+
+What: /sys/bus/nd/devices/nmemX/cxl/id
+Date: November 2022
+KernelVersion: 6.2
+Contact: Dave Jiang <dave.jiang@intel.com>
+Description: (RO) Show the id (serial) of the device. This is CXL specific.
+
+What: /sys/bus/nd/devices/nmemX/cxl/provider
+Date: November 2022
+KernelVersion: 6.2
+Contact: Dave Jiang <dave.jiang@intel.com>
+Description: (RO) Shows the CXL bridge device that ties to a CXL memory device
+ to this NVDIMM device. I.e. the parent of the device returned is
+ a /sys/bus/cxl/devices/memX instance.
diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci
index 840727fc75dc..ecf47559f495 100644
--- a/Documentation/ABI/testing/sysfs-bus-pci
+++ b/Documentation/ABI/testing/sysfs-bus-pci
@@ -407,6 +407,16 @@ Description:
file contains a '1' if the memory has been published for
use outside the driver that owns the device.
+What: /sys/bus/pci/devices/.../p2pmem/allocate
+Date: August 2022
+Contact: Logan Gunthorpe <logang@deltatee.com>
+Description:
+ This file allows mapping p2pmem into userspace. For each
+ mmap() call on this file, the kernel will allocate a chunk
+ of Peer-to-Peer memory for use in Peer-to-Peer transactions.
+ This memory can be used in O_DIRECT calls to NVMe backed
+ files for Peer-to-Peer copies.
+
What: /sys/bus/pci/devices/.../link/clkpm
/sys/bus/pci/devices/.../link/l0s_aspm
/sys/bus/pci/devices/.../link/l1_aspm
diff --git a/Documentation/ABI/testing/sysfs-bus-spi-devices-spi-nor b/Documentation/ABI/testing/sysfs-bus-spi-devices-spi-nor
index d76cd3946434..c800621eff95 100644
--- a/Documentation/ABI/testing/sysfs-bus-spi-devices-spi-nor
+++ b/Documentation/ABI/testing/sysfs-bus-spi-devices-spi-nor
@@ -5,6 +5,9 @@ Contact: linux-mtd@lists.infradead.org
Description: (RO) The JEDEC ID of the SPI NOR flash as reported by the
flash device.
+ The attribute is not present if the flash doesn't support
+ the "Read JEDEC ID" command (9Fh). This is the case for
+ non-JEDEC compliant flashes.
What: /sys/bus/spi/devices/.../spi-nor/manufacturer
Date: April 2021
@@ -12,6 +15,9 @@ KernelVersion: 5.14
Contact: linux-mtd@lists.infradead.org
Description: (RO) Manufacturer of the SPI NOR flash.
+ The attribute is not present if the flash device isn't
+ known to the kernel and is only probed by its SFDP
+ tables.
What: /sys/bus/spi/devices/.../spi-nor/partname
Date: April 2021
diff --git a/Documentation/ABI/testing/sysfs-class-pktcdvd b/Documentation/ABI/testing/sysfs-class-pktcdvd
deleted file mode 100644
index ba1ce626591d..000000000000
--- a/Documentation/ABI/testing/sysfs-class-pktcdvd
+++ /dev/null
@@ -1,97 +0,0 @@
-sysfs interface
----------------
-The pktcdvd module (packet writing driver) creates the following files in the
-sysfs: (<devid> is in the format major:minor)
-
-What: /sys/class/pktcdvd/add
-What: /sys/class/pktcdvd/remove
-What: /sys/class/pktcdvd/device_map
-Date: Oct. 2006
-KernelVersion: 2.6.20
-Contact: Thomas Maier <balagi@justmail.de>
-Description:
-
- ========== ==============================================
- add (WO) Write a block device id (major:minor) to
- create a new pktcdvd device and map it to the
- block device.
-
- remove (WO) Write the pktcdvd device id (major:minor)
- to remove the pktcdvd device.
-
- device_map (RO) Shows the device mapping in format:
- pktcdvd[0-7] <pktdevid> <blkdevid>
- ========== ==============================================
-
-
-What: /sys/class/pktcdvd/pktcdvd[0-7]/dev
-What: /sys/class/pktcdvd/pktcdvd[0-7]/uevent
-Date: Oct. 2006
-KernelVersion: 2.6.20
-Contact: Thomas Maier <balagi@justmail.de>
-Description:
- dev: (RO) Device id
-
- uevent: (WO) To send a uevent
-
-
-What: /sys/class/pktcdvd/pktcdvd[0-7]/stat/packets_started
-What: /sys/class/pktcdvd/pktcdvd[0-7]/stat/packets_finished
-What: /sys/class/pktcdvd/pktcdvd[0-7]/stat/kb_written
-What: /sys/class/pktcdvd/pktcdvd[0-7]/stat/kb_read
-What: /sys/class/pktcdvd/pktcdvd[0-7]/stat/kb_read_gather
-What: /sys/class/pktcdvd/pktcdvd[0-7]/stat/reset
-Date: Oct. 2006
-KernelVersion: 2.6.20
-Contact: Thomas Maier <balagi@justmail.de>
-Description:
- packets_started: (RO) Number of started packets.
-
- packets_finished: (RO) Number of finished packets.
-
- kb_written: (RO) kBytes written.
-
- kb_read: (RO) kBytes read.
-
- kb_read_gather: (RO) kBytes read to fill write packets.
-
- reset: (WO) Write any value to it to reset
- pktcdvd device statistic values, like
- bytes read/written.
-
-
-What: /sys/class/pktcdvd/pktcdvd[0-7]/write_queue/size
-What: /sys/class/pktcdvd/pktcdvd[0-7]/write_queue/congestion_off
-What: /sys/class/pktcdvd/pktcdvd[0-7]/write_queue/congestion_on
-Date: Oct. 2006
-KernelVersion: 2.6.20
-Contact: Thomas Maier <balagi@justmail.de>
-Description:
- ============== ================================================
- size (RO) Contains the size of the bio write queue.
-
- congestion_off (RW) If bio write queue size is below this mark,
- accept new bio requests from the block layer.
-
- congestion_on (RW) If bio write queue size is higher as this
- mark, do no longer accept bio write requests
- from the block layer and wait till the pktcdvd
- device has processed enough bio's so that bio
- write queue size is below congestion off mark.
- A value of <= 0 disables congestion control.
- ============== ================================================
-
-
-Example:
---------
-To use the pktcdvd sysfs interface directly, you can do::
-
- # create a new pktcdvd device mapped to /dev/hdc
- echo "22:0" >/sys/class/pktcdvd/add
- cat /sys/class/pktcdvd/device_map
- # assuming device pktcdvd0 was created, look at stat's
- cat /sys/class/pktcdvd/pktcdvd0/stat/kb_written
- # print the device id of the mapped block device
- fgrep pktcdvd0 /sys/class/pktcdvd/device_map
- # remove device, using pktcdvd0 device id 253:0
- echo "253:0" >/sys/class/pktcdvd/remove
diff --git a/Documentation/ABI/testing/sysfs-devices-mapping b/Documentation/ABI/testing/sysfs-devices-mapping
index 8d202bac9394..2eee1446ad4c 100644
--- a/Documentation/ABI/testing/sysfs-devices-mapping
+++ b/Documentation/ABI/testing/sysfs-devices-mapping
@@ -1,6 +1,6 @@
What: /sys/devices/uncore_iio_x/dieX
Date: February 2020
-Contact: Roman Sudarikov <roman.sudarikov@linux.intel.com>
+Contact: Alexander Antonov <alexander.antonov@linux.intel.com>
Description:
Each IIO stack (PCIe root port) has its own IIO PMON block, so
each dieX file (where X is die number) holds "Segment:Root Bus"
@@ -32,3 +32,31 @@ Description:
IIO PMU 0 on die 1 belongs to PCI RP on bus 0x40, domain 0x0000
IIO PMU 0 on die 2 belongs to PCI RP on bus 0x80, domain 0x0000
IIO PMU 0 on die 3 belongs to PCI RP on bus 0xc0, domain 0x0000
+
+What: /sys/devices/uncore_upi_x/dieX
+Date: March 2022
+Contact: Alexander Antonov <alexander.antonov@linux.intel.com>
+Description:
+ Each /sys/devices/uncore_upi_X/dieY file holds "upi_Z,die_W"
+ value that means UPI link number X on die Y is connected to UPI
+ link Z on die W and this link between sockets can be monitored
+ by UPI PMON block.
+ For example, 4-die Sapphire Rapids platform has the following
+ UPI 0 topology::
+
+ # tail /sys/devices/uncore_upi_0/die*
+ ==> /sys/devices/uncore_upi_0/die0 <==
+ upi_1,die_1
+ ==> /sys/devices/uncore_upi_0/die1 <==
+ upi_0,die_3
+ ==> /sys/devices/uncore_upi_0/die2 <==
+ upi_1,die_3
+ ==> /sys/devices/uncore_upi_0/die3 <==
+ upi_0,die_1
+
+ Which means::
+
+ UPI link 0 on die 0 is connected to UPI link 1 on die 1
+ UPI link 0 on die 1 is connected to UPI link 0 on die 3
+ UPI link 0 on die 2 is connected to UPI link 1 on die 3
+ UPI link 0 on die 3 is connected to UPI link 0 on die 1 \ No newline at end of file
diff --git a/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
new file mode 100644
index 000000000000..2d6a472eef88
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
@@ -0,0 +1,75 @@
+What: /sys/devices/.../hwmon/hwmon<i>/in0_input
+Date: February 2023
+KernelVersion: 6.2
+Contact: intel-gfx@lists.freedesktop.org
+Description: RO. Current Voltage in millivolt.
+
+ Only supported for particular Intel i915 graphics platforms.
+
+What: /sys/devices/.../hwmon/hwmon<i>/power1_max
+Date: February 2023
+KernelVersion: 6.2
+Contact: intel-gfx@lists.freedesktop.org
+Description: RW. Card reactive sustained (PL1/Tau) power limit in microwatts.
+
+ The power controller will throttle the operating frequency
+ if the power averaged over a window (typically seconds)
+ exceeds this limit.
+
+ Only supported for particular Intel i915 graphics platforms.
+
+What: /sys/devices/.../hwmon/hwmon<i>/power1_rated_max
+Date: February 2023
+KernelVersion: 6.2
+Contact: intel-gfx@lists.freedesktop.org
+Description: RO. Card default power limit (default TDP setting).
+
+ Only supported for particular Intel i915 graphics platforms.
+
+What: /sys/devices/.../hwmon/hwmon<i>/power1_max_interval
+Date: February 2023
+KernelVersion: 6.2
+Contact: intel-gfx@lists.freedesktop.org
+Description: RW. Sustained power limit interval (Tau in PL1/Tau) in
+ milliseconds over which sustained power is averaged.
+
+ Only supported for particular Intel i915 graphics platforms.
+
+What: /sys/devices/.../hwmon/hwmon<i>/power1_crit
+Date: February 2023
+KernelVersion: 6.2
+Contact: intel-gfx@lists.freedesktop.org
+Description: RW. Card reactive critical (I1) power limit in microwatts.
+
+ Card reactive critical (I1) power limit in microwatts is exposed
+ for client products. The power controller will throttle the
+ operating frequency if the power averaged over a window exceeds
+ this limit.
+
+ Only supported for particular Intel i915 graphics platforms.
+
+What: /sys/devices/.../hwmon/hwmon<i>/curr1_crit
+Date: February 2023
+KernelVersion: 6.2
+Contact: intel-gfx@lists.freedesktop.org
+Description: RW. Card reactive critical (I1) power limit in milliamperes.
+
+ Card reactive critical (I1) power limit in milliamperes is
+ exposed for server products. The power controller will throttle
+ the operating frequency if the power averaged over a window
+ exceeds this limit.
+
+ Only supported for particular Intel i915 graphics platforms.
+
+What: /sys/devices/.../hwmon/hwmon<i>/energy1_input
+Date: February 2023
+KernelVersion: 6.2
+Contact: intel-gfx@lists.freedesktop.org
+Description: RO. Energy input of device or gt in microjoules.
+
+ For i915 device level hwmon devices (name "i915") this
+ reflects energy input for the entire device. For gt level
+ hwmon devices (name "i915_gtN") this reflects energy input
+ for the gt.
+
+ Only supported for particular Intel i915 graphics platforms.
diff --git a/Documentation/ABI/testing/sysfs-driver-intel_sdsi b/Documentation/ABI/testing/sysfs-driver-intel_sdsi
index 96b92c105ec4..f8afed127107 100644
--- a/Documentation/ABI/testing/sysfs-driver-intel_sdsi
+++ b/Documentation/ABI/testing/sysfs-driver-intel_sdsi
@@ -4,21 +4,21 @@ KernelVersion: 5.18
Contact: "David E. Box" <david.e.box@linux.intel.com>
Description:
This directory contains interface files for accessing Intel
- Software Defined Silicon (SDSi) features on a CPU. X
- represents the socket instance (though not the socket ID).
- The socket ID is determined by reading the registers file
- and decoding it per the specification.
+ On Demand (formerly Software Defined Silicon or SDSi) features
+ on a CPU. X represents the socket instance (though not the
+ socket ID). The socket ID is determined by reading the
+ registers file and decoding it per the specification.
- Some files communicate with SDSi hardware through a mailbox.
- Should the operation fail, one of the following error codes
- may be returned:
+ Some files communicate with On Demand hardware through a
+ mailbox. Should the operation fail, one of the following error
+ codes may be returned:
========== =====
Error Code Cause
========== =====
EIO General mailbox failure. Log may indicate cause.
EBUSY Mailbox is owned by another agent.
- EPERM SDSI capability is not enabled in hardware.
+ EPERM On Demand capability is not enabled in hardware.
EPROTO Failure in mailbox protocol detected by driver.
See log for details.
EOVERFLOW For provision commands, the size of the data
@@ -54,8 +54,8 @@ KernelVersion: 5.18
Contact: "David E. Box" <david.e.box@linux.intel.com>
Description:
(WO) Used to write an Authentication Key Certificate (AKC) to
- the SDSi NVRAM for the CPU. The AKC is used to authenticate a
- Capability Activation Payload. Mailbox command.
+ the On Demand NVRAM for the CPU. The AKC is used to authenticate
+ a Capability Activation Payload. Mailbox command.
What: /sys/bus/auxiliary/devices/intel_vsec.sdsi.X/provision_cap
Date: Feb 2022
@@ -63,17 +63,28 @@ KernelVersion: 5.18
Contact: "David E. Box" <david.e.box@linux.intel.com>
Description:
(WO) Used to write a Capability Activation Payload (CAP) to the
- SDSi NVRAM for the CPU. CAPs are used to activate a given CPU
- feature. A CAP is validated by SDSi hardware using a previously
- provisioned AKC file. Upon successful authentication, the CPU
- configuration is updated. A cold reboot is required to fully
- activate the feature. Mailbox command.
+ On Demand NVRAM for the CPU. CAPs are used to activate a given
+ CPU feature. A CAP is validated by On Demand hardware using a
+ previously provisioned AKC file. Upon successful authentication,
+ the CPU configuration is updated. A cold reboot is required to
+ fully activate the feature. Mailbox command.
+
+What: /sys/bus/auxiliary/devices/intel_vsec.sdsi.X/meter_certificate
+Date: Nov 2022
+KernelVersion: 6.2
+Contact: "David E. Box" <david.e.box@linux.intel.com>
+Description:
+ (RO) Used to read back the current meter certificate for the CPU
+ from Intel On Demand hardware. The meter certificate contains
+ utilization metrics of On Demand enabled features. Mailbox
+ command.
What: /sys/bus/auxiliary/devices/intel_vsec.sdsi.X/state_certificate
Date: Feb 2022
KernelVersion: 5.18
Contact: "David E. Box" <david.e.box@linux.intel.com>
Description:
- (RO) Used to read back the current State Certificate for the CPU
- from SDSi hardware. The State Certificate contains information
- about the current licenses on the CPU. Mailbox command.
+ (RO) Used to read back the current state certificate for the CPU
+ from On Demand hardware. The state certificate contains
+ information about the current licenses on the CPU. Mailbox
+ command.
diff --git a/Documentation/ABI/testing/sysfs-platform-dell-wmi-ddv b/Documentation/ABI/testing/sysfs-platform-dell-wmi-ddv
new file mode 100644
index 000000000000..1d97ad615c66
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-dell-wmi-ddv
@@ -0,0 +1,7 @@
+What: /sys/class/power_supply/<battery_name>/eppid
+Date: September 2022
+KernelVersion: 6.1
+Contact: Armin Wolf <W_Armin@gmx.de>
+Description:
+ Reports the Dell ePPID (electronic Dell Piece Part Identification)
+ of the ACPI battery.
diff --git a/Documentation/ABI/testing/sysfs-platform-intel-ifs b/Documentation/ABI/testing/sysfs-platform-intel-ifs
index 486d6d2ff8a0..55991983d0d0 100644
--- a/Documentation/ABI/testing/sysfs-platform-intel-ifs
+++ b/Documentation/ABI/testing/sysfs-platform-intel-ifs
@@ -1,39 +1,41 @@
What: /sys/devices/virtual/misc/intel_ifs_<N>/run_test
-Date: April 21 2022
-KernelVersion: 5.19
+Date: Nov 16 2022
+KernelVersion: 6.2
Contact: "Jithu Joseph" <jithu.joseph@intel.com>
Description: Write <cpu#> to trigger IFS test for one online core.
Note that the test is per core. The cpu# can be
for any thread on the core. Running on one thread
completes the test for the core containing that thread.
Example: to test the core containing cpu5: echo 5 >
- /sys/devices/platform/intel_ifs.<N>/run_test
+ /sys/devices/virtual/misc/intel_ifs_<N>/run_test
What: /sys/devices/virtual/misc/intel_ifs_<N>/status
-Date: April 21 2022
-KernelVersion: 5.19
+Date: Nov 16 2022
+KernelVersion: 6.2
Contact: "Jithu Joseph" <jithu.joseph@intel.com>
Description: The status of the last test. It can be one of "pass", "fail"
or "untested".
What: /sys/devices/virtual/misc/intel_ifs_<N>/details
-Date: April 21 2022
-KernelVersion: 5.19
+Date: Nov 16 2022
+KernelVersion: 6.2
Contact: "Jithu Joseph" <jithu.joseph@intel.com>
Description: Additional information regarding the last test. The details file reports
the hex value of the SCAN_STATUS MSR. Note that the error_code field
may contain driver defined software code not defined in the Intel SDM.
What: /sys/devices/virtual/misc/intel_ifs_<N>/image_version
-Date: April 21 2022
-KernelVersion: 5.19
+Date: Nov 16 2022
+KernelVersion: 6.2
Contact: "Jithu Joseph" <jithu.joseph@intel.com>
Description: Version (hexadecimal) of loaded IFS binary image. If no scan image
is loaded reports "none".
-What: /sys/devices/virtual/misc/intel_ifs_<N>/reload
-Date: April 21 2022
-KernelVersion: 5.19
+What: /sys/devices/virtual/misc/intel_ifs_<N>/current_batch
+Date: Nov 16 2022
+KernelVersion: 6.2
Contact: "Jithu Joseph" <jithu.joseph@intel.com>
-Description: Write "1" (or "y" or "Y") to reload the IFS image from
- /lib/firmware/intel/ifs/ff-mm-ss.scan.
+Description: Write a number less than or equal to 0xff to load an IFS test image.
+ The number written treated as the 2 digit suffix in the following file name:
+ /lib/firmware/intel/ifs_<N>/ff-mm-ss-02x.scan
+ Reading the file will provide the suffix of the currently loaded IFS test image.
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 64d44c1ecad3..bb73dcb5ed05 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -95,6 +95,15 @@ htmldocs:
@$(srctree)/scripts/sphinx-pre-install --version-check
@+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,html,$(var),,$(var)))
+texinfodocs:
+ @$(srctree)/scripts/sphinx-pre-install --version-check
+ @+$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,texinfo,$(var),texinfo,$(var)))
+
+# Note: the 'info' Make target is generated by sphinx itself when
+# running the texinfodocs target define above.
+infodocs: texinfodocs
+ $(MAKE) -C $(BUILDDIR)/texinfo info
+
linkcheckdocs:
@$(foreach var,$(SPHINXDIRS),$(call loop_cmd,sphinx,linkcheck,$(var),,$(var)))
@@ -143,6 +152,8 @@ cleandocs:
dochelp:
@echo ' Linux kernel internal documentation in different formats from ReST:'
@echo ' htmldocs - HTML'
+ @echo ' texinfodocs - Texinfo'
+ @echo ' infodocs - Info'
@echo ' latexdocs - LaTeX'
@echo ' pdfdocs - PDF'
@echo ' epubdocs - EPUB'
diff --git a/Documentation/PCI/msi-howto.rst b/Documentation/PCI/msi-howto.rst
index aa2046af69f7..8ae461e97c54 100644
--- a/Documentation/PCI/msi-howto.rst
+++ b/Documentation/PCI/msi-howto.rst
@@ -285,3 +285,13 @@ to bridges between the PCI root and the device, MSIs are disabled.
It is also worth checking the device driver to see whether it supports MSIs.
For example, it may contain calls to pci_alloc_irq_vectors() with the
PCI_IRQ_MSI or PCI_IRQ_MSIX flags.
+
+
+List of device drivers MSI(-X) APIs
+===================================
+
+The PCI/MSI subystem has a dedicated C file for its exported device driver
+APIs — `drivers/pci/msi/api.c`. The following functions are exported:
+
+.. kernel-doc:: drivers/pci/msi/api.c
+ :export:
diff --git a/Documentation/PCI/pci-error-recovery.rst b/Documentation/PCI/pci-error-recovery.rst
index 187f43a03200..bdafeb4b66dc 100644
--- a/Documentation/PCI/pci-error-recovery.rst
+++ b/Documentation/PCI/pci-error-recovery.rst
@@ -83,6 +83,7 @@ This structure has the form::
int (*mmio_enabled)(struct pci_dev *dev);
int (*slot_reset)(struct pci_dev *dev);
void (*resume)(struct pci_dev *dev);
+ void (*cor_error_detected)(struct pci_dev *dev);
};
The possible channel states are::
@@ -422,5 +423,11 @@ That is, the recovery API only requires that:
- drivers/net/cxgb3
- drivers/net/s2io.c
+ The cor_error_detected() callback is invoked in handle_error_source() when
+ the error severity is "correctable". The callback is optional and allows
+ additional logging to be done if desired. See example:
+
+ - drivers/cxl/pci.c
+
The End
-------
diff --git a/Documentation/RCU/Design/Requirements/Requirements.rst b/Documentation/RCU/Design/Requirements/Requirements.rst
index a0f8164c8513..49387d823619 100644
--- a/Documentation/RCU/Design/Requirements/Requirements.rst
+++ b/Documentation/RCU/Design/Requirements/Requirements.rst
@@ -1858,7 +1858,7 @@ unloaded. After a given module has been unloaded, any attempt to call
one of its functions results in a segmentation fault. The module-unload
functions must therefore cancel any delayed calls to loadable-module
functions, for example, any outstanding mod_timer() must be dealt
-with via del_timer_sync() or similar.
+with via timer_shutdown_sync() or similar.
Unfortunately, there is no way to cancel an RCU callback; once you
invoke call_rcu(), the callback function is eventually going to be
diff --git a/Documentation/RCU/arrayRCU.rst b/Documentation/RCU/arrayRCU.rst
deleted file mode 100644
index a5f2ff8fc54c..000000000000
--- a/Documentation/RCU/arrayRCU.rst
+++ /dev/null
@@ -1,165 +0,0 @@
-.. _array_rcu_doc:
-
-Using RCU to Protect Read-Mostly Arrays
-=======================================
-
-Although RCU is more commonly used to protect linked lists, it can
-also be used to protect arrays. Three situations are as follows:
-
-1. :ref:`Hash Tables <hash_tables>`
-
-2. :ref:`Static Arrays <static_arrays>`
-
-3. :ref:`Resizable Arrays <resizable_arrays>`
-
-Each of these three situations involves an RCU-protected pointer to an
-array that is separately indexed. It might be tempting to consider use
-of RCU to instead protect the index into an array, however, this use
-case is **not** supported. The problem with RCU-protected indexes into
-arrays is that compilers can play way too many optimization games with
-integers, which means that the rules governing handling of these indexes
-are far more trouble than they are worth. If RCU-protected indexes into
-arrays prove to be particularly valuable (which they have not thus far),
-explicit cooperation from the compiler will be required to permit them
-to be safely used.
-
-That aside, each of the three RCU-protected pointer situations are
-described in the following sections.
-
-.. _hash_tables:
-
-Situation 1: Hash Tables
-------------------------
-
-Hash tables are often implemented as an array, where each array entry
-has a linked-list hash chain. Each hash chain can be protected by RCU
-as described in listRCU.rst. This approach also applies to other
-array-of-list situations, such as radix trees.
-
-.. _static_arrays:
-
-Situation 2: Static Arrays
---------------------------
-
-Static arrays, where the data (rather than a pointer to the data) is
-located in each array element, and where the array is never resized,
-have not been used with RCU. Rik van Riel recommends using seqlock in
-this situation, which would also have minimal read-side overhead as long
-as updates are rare.
-
-Quick Quiz:
- Why is it so important that updates be rare when using seqlock?
-
-:ref:`Answer to Quick Quiz <answer_quick_quiz_seqlock>`
-
-.. _resizable_arrays:
-
-Situation 3: Resizable Arrays
-------------------------------
-
-Use of RCU for resizable arrays is demonstrated by the grow_ary()
-function formerly used by the System V IPC code. The array is used
-to map from semaphore, message-queue, and shared-memory IDs to the data
-structure that represents the corresponding IPC construct. The grow_ary()
-function does not acquire any locks; instead its caller must hold the
-ids->sem semaphore.
-
-The grow_ary() function, shown below, does some limit checks, allocates a
-new ipc_id_ary, copies the old to the new portion of the new, initializes
-the remainder of the new, updates the ids->entries pointer to point to
-the new array, and invokes ipc_rcu_putref() to free up the old array.
-Note that rcu_assign_pointer() is used to update the ids->entries pointer,
-which includes any memory barriers required on whatever architecture
-you are running on::
-
- static int grow_ary(struct ipc_ids* ids, int newsize)
- {
- struct ipc_id_ary* new;
- struct ipc_id_ary* old;
- int i;
- int size = ids->entries->size;
-
- if(newsize > IPCMNI)
- newsize = IPCMNI;
- if(newsize <= size)
- return newsize;
-
- new = ipc_rcu_alloc(sizeof(struct kern_ipc_perm *)*newsize +
- sizeof(struct ipc_id_ary));
- if(new == NULL)
- return size;
- new->size = newsize;
- memcpy(new->p, ids->entries->p,
- sizeof(struct kern_ipc_perm *)*size +
- sizeof(struct ipc_id_ary));
- for(i=size;i<newsize;i++) {
- new->p[i] = NULL;
- }
- old = ids->entries;
-
- /*
- * Use rcu_assign_pointer() to make sure the memcpyed
- * contents of the new array are visible before the new
- * array becomes visible.
- */
- rcu_assign_pointer(ids->entries, new);
-
- ipc_rcu_putref(old);
- return newsize;
- }
-
-The ipc_rcu_putref() function decrements the array's reference count
-and then, if the reference count has dropped to zero, uses call_rcu()
-to free the array after a grace period has elapsed.
-
-The array is traversed by the ipc_lock() function. This function
-indexes into the array under the protection of rcu_read_lock(),
-using rcu_dereference() to pick up the pointer to the array so
-that it may later safely be dereferenced -- memory barriers are
-required on the Alpha CPU. Since the size of the array is stored
-with the array itself, there can be no array-size mismatches, so
-a simple check suffices. The pointer to the structure corresponding
-to the desired IPC object is placed in "out", with NULL indicating
-a non-existent entry. After acquiring "out->lock", the "out->deleted"
-flag indicates whether the IPC object is in the process of being
-deleted, and, if not, the pointer is returned::
-
- struct kern_ipc_perm* ipc_lock(struct ipc_ids* ids, int id)
- {
- struct kern_ipc_perm* out;
- int lid = id % SEQ_MULTIPLIER;
- struct ipc_id_ary* entries;
-
- rcu_read_lock();
- entries = rcu_dereference(ids->entries);
- if(lid >= entries->size) {
- rcu_read_unlock();
- return NULL;
- }
- out = entries->p[lid];
- if(out == NULL) {
- rcu_read_unlock();
- return NULL;
- }
- spin_lock(&out->lock);
-
- /* ipc_rmid() may have already freed the ID while ipc_lock
- * was spinning: here verify that the structure is still valid
- */
- if (out->deleted) {
- spin_unlock(&out->lock);
- rcu_read_unlock();
- return NULL;
- }
- return out;
- }
-
-.. _answer_quick_quiz_seqlock:
-
-Answer to Quick Quiz:
- Why is it so important that updates be rare when using seqlock?
-
- The reason that it is important that updates be rare when
- using seqlock is that frequent updates can livelock readers.
- One way to avoid this problem is to assign a seqlock for
- each array entry rather than to the entire array.
diff --git a/Documentation/RCU/checklist.rst b/Documentation/RCU/checklist.rst
index 048c5bc1f813..cc361fb01ed4 100644
--- a/Documentation/RCU/checklist.rst
+++ b/Documentation/RCU/checklist.rst
@@ -32,8 +32,8 @@ over a rather long period of time, but improvements are always welcome!
for lockless updates. This does result in the mildly
counter-intuitive situation where rcu_read_lock() and
rcu_read_unlock() are used to protect updates, however, this
- approach provides the same potential simplifications that garbage
- collectors do.
+ approach can provide the same simplifications to certain types
+ of lockless algorithms that garbage collectors do.
1. Does the update code have proper mutual exclusion?
@@ -49,12 +49,12 @@ over a rather long period of time, but improvements are always welcome!
them -- even x86 allows later loads to be reordered to precede
earlier stores), and be prepared to explain why this added
complexity is worthwhile. If you choose #c, be prepared to
- explain how this single task does not become a major bottleneck on
- big multiprocessor machines (for example, if the task is updating
- information relating to itself that other tasks can read, there
- by definition can be no bottleneck). Note that the definition
- of "large" has changed significantly: Eight CPUs was "large"
- in the year 2000, but a hundred CPUs was unremarkable in 2017.
+ explain how this single task does not become a major bottleneck
+ on large systems (for example, if the task is updating information
+ relating to itself that other tasks can read, there by definition
+ can be no bottleneck). Note that the definition of "large" has
+ changed significantly: Eight CPUs was "large" in the year 2000,
+ but a hundred CPUs was unremarkable in 2017.
2. Do the RCU read-side critical sections make proper use of
rcu_read_lock() and friends? These primitives are needed
@@ -97,33 +97,38 @@ over a rather long period of time, but improvements are always welcome!
b. Proceed as in (a) above, but also maintain per-element
locks (that are acquired by both readers and writers)
- that guard per-element state. Of course, fields that
- the readers refrain from accessing can be guarded by
- some other lock acquired only by updaters, if desired.
+ that guard per-element state. Fields that the readers
+ refrain from accessing can be guarded by some other lock
+ acquired only by updaters, if desired.
- This works quite well, also.
+ This also works quite well.
c. Make updates appear atomic to readers. For example,
pointer updates to properly aligned fields will
appear atomic, as will individual atomic primitives.
Sequences of operations performed under a lock will *not*
appear to be atomic to RCU readers, nor will sequences
- of multiple atomic primitives.
+ of multiple atomic primitives. One alternative is to
+ move multiple individual fields to a separate structure,
+ thus solving the multiple-field problem by imposing an
+ additional level of indirection.
This can work, but is starting to get a bit tricky.
- d. Carefully order the updates and the reads so that
- readers see valid data at all phases of the update.
- This is often more difficult than it sounds, especially
- given modern CPUs' tendency to reorder memory references.
- One must usually liberally sprinkle memory barriers
- (smp_wmb(), smp_rmb(), smp_mb()) through the code,
- making it difficult to understand and to test.
-
- It is usually better to group the changing data into
- a separate structure, so that the change may be made
- to appear atomic by updating a pointer to reference
- a new structure containing updated values.
+ d. Carefully order the updates and the reads so that readers
+ see valid data at all phases of the update. This is often
+ more difficult than it sounds, especially given modern
+ CPUs' tendency to reorder memory references. One must
+ usually liberally sprinkle memory-ordering operations
+ through the code, making it difficult to understand and
+ to test. Where it works, it is better to use things
+ like smp_store_release() and smp_load_acquire(), but in
+ some cases the smp_mb() full memory barrier is required.
+
+ As noted earlier, it is usually better to group the
+ changing data into a separate structure, so that the
+ change may be made to appear atomic by updating a pointer
+ to reference a new structure containing updated values.
4. Weakly ordered CPUs pose special challenges. Almost all CPUs
are weakly ordered -- even x86 CPUs allow later loads to be
@@ -188,26 +193,29 @@ over a rather long period of time, but improvements are always welcome!
when publicizing a pointer to a structure that can
be traversed by an RCU read-side critical section.
-5. If call_rcu() or call_srcu() is used, the callback function will
- be called from softirq context. In particular, it cannot block.
- If you need the callback to block, run that code in a workqueue
- handler scheduled from the callback. The queue_rcu_work()
- function does this for you in the case of call_rcu().
+5. If any of call_rcu(), call_srcu(), call_rcu_tasks(),
+ call_rcu_tasks_rude(), or call_rcu_tasks_trace() is used,
+ the callback function may be invoked from softirq context,
+ and in any case with bottom halves disabled. In particular,
+ this callback function cannot block. If you need the callback
+ to block, run that code in a workqueue handler scheduled from
+ the callback. The queue_rcu_work() function does this for you
+ in the case of call_rcu().
6. Since synchronize_rcu() can block, it cannot be called
from any sort of irq context. The same rule applies
- for synchronize_srcu(), synchronize_rcu_expedited(), and
- synchronize_srcu_expedited().
+ for synchronize_srcu(), synchronize_rcu_expedited(),
+ synchronize_srcu_expedited(), synchronize_rcu_tasks(),
+ synchronize_rcu_tasks_rude(), and synchronize_rcu_tasks_trace().
The expedited forms of these primitives have the same semantics
- as the non-expedited forms, but expediting is both expensive and
- (with the exception of synchronize_srcu_expedited()) unfriendly
- to real-time workloads. Use of the expedited primitives should
- be restricted to rare configuration-change operations that would
- not normally be undertaken while a real-time workload is running.
- However, real-time workloads can use rcupdate.rcu_normal kernel
- boot parameter to completely disable expedited grace periods,
- though this might have performance implications.
+ as the non-expedited forms, but expediting is more CPU intensive.
+ Use of the expedited primitives should be restricted to rare
+ configuration-change operations that would not normally be
+ undertaken while a real-time workload is running. Note that
+ IPI-sensitive real-time workloads can use the rcupdate.rcu_normal
+ kernel boot parameter to completely disable expedited grace
+ periods, though this might have performance implications.
In particular, if you find yourself invoking one of the expedited
primitives repeatedly in a loop, please do everyone a favor:
@@ -215,8 +223,9 @@ over a rather long period of time, but improvements are always welcome!
a single non-expedited primitive to cover the entire batch.
This will very likely be faster than the loop containing the
expedited primitive, and will be much much easier on the rest
- of the system, especially to real-time workloads running on
- the rest of the system.
+ of the system, especially to real-time workloads running on the
+ rest of the system. Alternatively, instead use asynchronous
+ primitives such as call_rcu().
7. As of v4.20, a given kernel implements only one RCU flavor, which
is RCU-sched for PREEMPTION=n and RCU-preempt for PREEMPTION=y.
@@ -239,7 +248,8 @@ over a rather long period of time, but improvements are always welcome!
the corresponding readers must use rcu_read_lock_trace() and
rcu_read_unlock_trace(). If an updater uses call_rcu_tasks_rude()
or synchronize_rcu_tasks_rude(), then the corresponding readers
- must use anything that disables interrupts.
+ must use anything that disables preemption, for example,
+ preempt_disable() and preempt_enable().
Mixing things up will result in confusion and broken kernels, and
has even resulted in an exploitable security issue. Therefore,
@@ -253,15 +263,16 @@ over a rather long period of time, but improvements are always welcome!
that this usage is safe is that readers can use anything that
disables BH when updaters use call_rcu() or synchronize_rcu().
-8. Although synchronize_rcu() is slower than is call_rcu(), it
- usually results in simpler code. So, unless update performance is
- critically important, the updaters cannot block, or the latency of
- synchronize_rcu() is visible from userspace, synchronize_rcu()
- should be used in preference to call_rcu(). Furthermore,
- kfree_rcu() usually results in even simpler code than does
- synchronize_rcu() without synchronize_rcu()'s multi-millisecond
- latency. So please take advantage of kfree_rcu()'s "fire and
- forget" memory-freeing capabilities where it applies.
+8. Although synchronize_rcu() is slower than is call_rcu(),
+ it usually results in simpler code. So, unless update
+ performance is critically important, the updaters cannot block,
+ or the latency of synchronize_rcu() is visible from userspace,
+ synchronize_rcu() should be used in preference to call_rcu().
+ Furthermore, kfree_rcu() and kvfree_rcu() usually result
+ in even simpler code than does synchronize_rcu() without
+ synchronize_rcu()'s multi-millisecond latency. So please take
+ advantage of kfree_rcu()'s and kvfree_rcu()'s "fire and forget"
+ memory-freeing capabilities where it applies.
An especially important property of the synchronize_rcu()
primitive is that it automatically self-limits: if grace periods
@@ -271,8 +282,8 @@ over a rather long period of time, but improvements are always welcome!
cases where grace periods are delayed, as failing to do so can
result in excessive realtime latencies or even OOM conditions.
- Ways of gaining this self-limiting property when using call_rcu()
- include:
+ Ways of gaining this self-limiting property when using call_rcu(),
+ kfree_rcu(), or kvfree_rcu() include:
a. Keeping a count of the number of data-structure elements
used by the RCU-protected data structure, including
@@ -304,18 +315,21 @@ over a rather long period of time, but improvements are always welcome!
here is that superuser already has lots of ways to crash
the machine.
- d. Periodically invoke synchronize_rcu(), permitting a limited
- number of updates per grace period. Better yet, periodically
- invoke rcu_barrier() to wait for all outstanding callbacks.
+ d. Periodically invoke rcu_barrier(), permitting a limited
+ number of updates per grace period.
- The same cautions apply to call_srcu() and kfree_rcu().
+ The same cautions apply to call_srcu(), call_rcu_tasks(),
+ call_rcu_tasks_rude(), and call_rcu_tasks_trace(). This is
+ why there is an srcu_barrier(), rcu_barrier_tasks(),
+ rcu_barrier_tasks_rude(), and rcu_barrier_tasks_rude(),
+ respectively.
- Note that although these primitives do take action to avoid memory
- exhaustion when any given CPU has too many callbacks, a determined
- user could still exhaust memory. This is especially the case
- if a system with a large number of CPUs has been configured to
- offload all of its RCU callbacks onto a single CPU, or if the
- system has relatively little free memory.
+ Note that although these primitives do take action to avoid
+ memory exhaustion when any given CPU has too many callbacks,
+ a determined user or administrator can still exhaust memory.
+ This is especially the case if a system with a large number of
+ CPUs has been configured to offload all of its RCU callbacks onto
+ a single CPU, or if the system has relatively little free memory.
9. All RCU list-traversal primitives, which include
rcu_dereference(), list_for_each_entry_rcu(), and
@@ -344,14 +358,14 @@ over a rather long period of time, but improvements are always welcome!
and you don't hold the appropriate update-side lock, you *must*
use the "_rcu()" variants of the list macros. Failing to do so
will break Alpha, cause aggressive compilers to generate bad code,
- and confuse people trying to read your code.
+ and confuse people trying to understand your code.
11. Any lock acquired by an RCU callback must be acquired elsewhere
- with softirq disabled, e.g., via spin_lock_irqsave(),
- spin_lock_bh(), etc. Failing to disable softirq on a given
- acquisition of that lock will result in deadlock as soon as
- the RCU softirq handler happens to run your RCU callback while
- interrupting that acquisition's critical section.
+ with softirq disabled, e.g., via spin_lock_bh(). Failing to
+ disable softirq on a given acquisition of that lock will result
+ in deadlock as soon as the RCU softirq handler happens to run
+ your RCU callback while interrupting that acquisition's critical
+ section.
12. RCU callbacks can be and are executed in parallel. In many cases,
the callback code simply wrappers around kfree(), so that this
@@ -372,7 +386,17 @@ over a rather long period of time, but improvements are always welcome!
for some real-time workloads, this is the whole point of using
the rcu_nocbs= kernel boot parameter.
-13. Unlike other forms of RCU, it *is* permissible to block in an
+ In addition, do not assume that callbacks queued in a given order
+ will be invoked in that order, even if they all are queued on the
+ same CPU. Furthermore, do not assume that same-CPU callbacks will
+ be invoked serially. For example, in recent kernels, CPUs can be
+ switched between offloaded and de-offloaded callback invocation,
+ and while a given CPU is undergoing such a switch, its callbacks
+ might be concurrently invoked by that CPU's softirq handler and
+ that CPU's rcuo kthread. At such times, that CPU's callbacks
+ might be executed both concurrently and out of order.
+
+13. Unlike most flavors of RCU, it *is* permissible to block in an
SRCU read-side critical section (demarked by srcu_read_lock()
and srcu_read_unlock()), hence the "SRCU": "sleepable RCU".
Please note that if you don't need to sleep in read-side critical
@@ -412,6 +436,12 @@ over a rather long period of time, but improvements are always welcome!
never sends IPIs to other CPUs, so it is easier on
real-time workloads than is synchronize_rcu_expedited().
+ It is also permissible to sleep in RCU Tasks Trace read-side
+ critical, which are delimited by rcu_read_lock_trace() and
+ rcu_read_unlock_trace(). However, this is a specialized flavor
+ of RCU, and you should not use it without first checking with
+ its current users. In most cases, you should instead use SRCU.
+
Note that rcu_assign_pointer() relates to SRCU just as it does to
other forms of RCU, but instead of rcu_dereference() you should
use srcu_dereference() in order to avoid lockdep splats.
@@ -442,50 +472,62 @@ over a rather long period of time, but improvements are always welcome!
find problems as follows:
CONFIG_PROVE_LOCKING:
- check that accesses to RCU-protected data
- structures are carried out under the proper RCU
- read-side critical section, while holding the right
- combination of locks, or whatever other conditions
- are appropriate.
+ check that accesses to RCU-protected data structures
+ are carried out under the proper RCU read-side critical
+ section, while holding the right combination of locks,
+ or whatever other conditions are appropriate.
CONFIG_DEBUG_OBJECTS_RCU_HEAD:
- check that you don't pass the
- same object to call_rcu() (or friends) before an RCU
- grace period has elapsed since the last time that you
- passed that same object to call_rcu() (or friends).
+ check that you don't pass the same object to call_rcu()
+ (or friends) before an RCU grace period has elapsed
+ since the last time that you passed that same object to
+ call_rcu() (or friends).
__rcu sparse checks:
- tag the pointer to the RCU-protected data
- structure with __rcu, and sparse will warn you if you
- access that pointer without the services of one of the
- variants of rcu_dereference().
+ tag the pointer to the RCU-protected data structure
+ with __rcu, and sparse will warn you if you access that
+ pointer without the services of one of the variants
+ of rcu_dereference().
These debugging aids can help you find problems that are
otherwise extremely difficult to spot.
-17. If you register a callback using call_rcu() or call_srcu(), and
- pass in a function defined within a loadable module, then it in
- necessary to wait for all pending callbacks to be invoked after
- the last invocation and before unloading that module. Note that
- it is absolutely *not* sufficient to wait for a grace period!
- The current (say) synchronize_rcu() implementation is *not*
- guaranteed to wait for callbacks registered on other CPUs.
- Or even on the current CPU if that CPU recently went offline
- and came back online.
+17. If you pass a callback function defined within a module to one of
+ call_rcu(), call_srcu(), call_rcu_tasks(), call_rcu_tasks_rude(),
+ or call_rcu_tasks_trace(), then it is necessary to wait for all
+ pending callbacks to be invoked before unloading that module.
+ Note that it is absolutely *not* sufficient to wait for a grace
+ period! For example, synchronize_rcu() implementation is *not*
+ guaranteed to wait for callbacks registered on other CPUs via
+ call_rcu(). Or even on the current CPU if that CPU recently
+ went offline and came back online.
You instead need to use one of the barrier functions:
- call_rcu() -> rcu_barrier()
- call_srcu() -> srcu_barrier()
+ - call_rcu_tasks() -> rcu_barrier_tasks()
+ - call_rcu_tasks_rude() -> rcu_barrier_tasks_rude()
+ - call_rcu_tasks_trace() -> rcu_barrier_tasks_trace()
However, these barrier functions are absolutely *not* guaranteed
- to wait for a grace period. In fact, if there are no call_rcu()
- callbacks waiting anywhere in the system, rcu_barrier() is within
- its rights to return immediately.
-
- So if you need to wait for both an RCU grace period and for
- all pre-existing call_rcu() callbacks, you will need to execute
- both rcu_barrier() and synchronize_rcu(), if necessary, using
- something like workqueues to execute them concurrently.
+ to wait for a grace period. For example, if there are no
+ call_rcu() callbacks queued anywhere in the system, rcu_barrier()
+ can and will return immediately.
+
+ So if you need to wait for both a grace period and for all
+ pre-existing callbacks, you will need to invoke both functions,
+ with the pair depending on the flavor of RCU:
+
+ - Either synchronize_rcu() or synchronize_rcu_expedited(),
+ together with rcu_barrier()
+ - Either synchronize_srcu() or synchronize_srcu_expedited(),
+ together with and srcu_barrier()
+ - synchronize_rcu_tasks() and rcu_barrier_tasks()
+ - synchronize_tasks_rude() and rcu_barrier_tasks_rude()
+ - synchronize_tasks_trace() and rcu_barrier_tasks_trace()
+
+ If necessary, you can use something like workqueues to execute
+ the requisite pair of functions concurrently.
See rcubarrier.rst for more information.
diff --git a/Documentation/RCU/index.rst b/Documentation/RCU/index.rst
index e703d3dbe60c..84a79903f6a8 100644
--- a/Documentation/RCU/index.rst
+++ b/Documentation/RCU/index.rst
@@ -9,7 +9,6 @@ RCU concepts
.. toctree::
:maxdepth: 3
- arrayRCU
checklist
lockdep
lockdep-splat
diff --git a/Documentation/RCU/listRCU.rst b/Documentation/RCU/listRCU.rst
index 2a643e293fb4..bdc4bcc5289f 100644
--- a/Documentation/RCU/listRCU.rst
+++ b/Documentation/RCU/listRCU.rst
@@ -3,11 +3,10 @@
Using RCU to Protect Read-Mostly Linked Lists
=============================================
-One of the best applications of RCU is to protect read-mostly linked lists
-(``struct list_head`` in list.h). One big advantage of this approach
-is that all of the required memory barriers are included for you in
-the list macros. This document describes several applications of RCU,
-with the best fits first.
+One of the most common uses of RCU is protecting read-mostly linked lists
+(``struct list_head`` in list.h). One big advantage of this approach is
+that all of the required memory ordering is provided by the list macros.
+This document describes several list-based RCU use cases.
Example 1: Read-mostly list: Deferred Destruction
@@ -35,7 +34,8 @@ The code traversing the list of all processes typically looks like::
}
rcu_read_unlock();
-The simplified code for removing a process from a task list is::
+The simplified and heavily inlined code for removing a process from a
+task list is::
void release_task(struct task_struct *p)
{
@@ -45,39 +45,48 @@ The simplified code for removing a process from a task list is::
call_rcu(&p->rcu, delayed_put_task_struct);
}
-When a process exits, ``release_task()`` calls ``list_del_rcu(&p->tasks)`` under
-``tasklist_lock`` writer lock protection, to remove the task from the list of
-all tasks. The ``tasklist_lock`` prevents concurrent list additions/removals
-from corrupting the list. Readers using ``for_each_process()`` are not protected
-with the ``tasklist_lock``. To prevent readers from noticing changes in the list
-pointers, the ``task_struct`` object is freed only after one or more grace
-periods elapse (with the help of call_rcu()). This deferring of destruction
-ensures that any readers traversing the list will see valid ``p->tasks.next``
-pointers and deletion/freeing can happen in parallel with traversal of the list.
-This pattern is also called an **existence lock**, since RCU pins the object in
-memory until all existing readers finish.
+When a process exits, ``release_task()`` calls ``list_del_rcu(&p->tasks)``
+via __exit_signal() and __unhash_process() under ``tasklist_lock``
+writer lock protection. The list_del_rcu() invocation removes
+the task from the list of all tasks. The ``tasklist_lock``
+prevents concurrent list additions/removals from corrupting the
+list. Readers using ``for_each_process()`` are not protected with the
+``tasklist_lock``. To prevent readers from noticing changes in the list
+pointers, the ``task_struct`` object is freed only after one or more
+grace periods elapse, with the help of call_rcu(), which is invoked via
+put_task_struct_rcu_user(). This deferring of destruction ensures that
+any readers traversing the list will see valid ``p->tasks.next`` pointers
+and deletion/freeing can happen in parallel with traversal of the list.
+This pattern is also called an **existence lock**, since RCU refrains
+from invoking the delayed_put_task_struct() callback function until
+all existing readers finish, which guarantees that the ``task_struct``
+object in question will remain in existence until after the completion
+of all RCU readers that might possibly have a reference to that object.
Example 2: Read-Side Action Taken Outside of Lock: No In-Place Updates
----------------------------------------------------------------------
-The best applications are cases where, if reader-writer locking were
-used, the read-side lock would be dropped before taking any action
-based on the results of the search. The most celebrated example is
-the routing table. Because the routing table is tracking the state of
-equipment outside of the computer, it will at times contain stale data.
-Therefore, once the route has been computed, there is no need to hold
-the routing table static during transmission of the packet. After all,
-you can hold the routing table static all you want, but that won't keep
-the external Internet from changing, and it is the state of the external
-Internet that really matters. In addition, routing entries are typically
-added or deleted, rather than being modified in place.
-
-A straightforward example of this use of RCU may be found in the
-system-call auditing support. For example, a reader-writer locked
+Some reader-writer locking use cases compute a value while holding
+the read-side lock, but continue to use that value after that lock is
+released. These use cases are often good candidates for conversion
+to RCU. One prominent example involves network packet routing.
+Because the packet-routing data tracks the state of equipment outside
+of the computer, it will at times contain stale data. Therefore, once
+the route has been computed, there is no need to hold the routing table
+static during transmission of the packet. After all, you can hold the
+routing table static all you want, but that won't keep the external
+Internet from changing, and it is the state of the external Internet
+that really matters. In addition, routing entries are typically added
+or deleted, rather than being modified in place. This is a rare example
+of the finite speed of light and the non-zero size of atoms actually
+helping make synchronization be lighter weight.
+
+A straightforward example of this type of RCU use case may be found in
+the system-call auditing support. For example, a reader-writer locked
implementation of ``audit_filter_task()`` might be as follows::
- static enum audit_state audit_filter_task(struct task_struct *tsk)
+ static enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
{
struct audit_entry *e;
enum audit_state state;
@@ -86,6 +95,8 @@ implementation of ``audit_filter_task()`` might be as follows::
/* Note: audit_filter_mutex held by caller. */
list_for_each_entry(e, &audit_tsklist, list) {
if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
+ if (state == AUDIT_STATE_RECORD)
+ *key = kstrdup(e->rule.filterkey, GFP_ATOMIC);
read_unlock(&auditsc_lock);
return state;
}
@@ -101,7 +112,7 @@ you are turning auditing off, it is OK to audit a few extra system calls.
This means that RCU can be easily applied to the read side, as follows::
- static enum audit_state audit_filter_task(struct task_struct *tsk)
+ static enum audit_state audit_filter_task(struct task_struct *tsk, char **key)
{
struct audit_entry *e;
enum audit_state state;
@@ -110,6 +121,8 @@ This means that RCU can be easily applied to the read side, as follows::
/* Note: audit_filter_mutex held by caller. */
list_for_each_entry_rcu(e, &audit_tsklist, list) {
if (audit_filter_rules(tsk, &e->rule, NULL, &state)) {
+ if (state == AUDIT_STATE_RECORD)
+ *key = kstrdup(e->rule.filterkey, GFP_ATOMIC);
rcu_read_unlock();
return state;
}
@@ -118,13 +131,15 @@ This means that RCU can be easily applied to the read side, as follows::
return AUDIT_BUILD_CONTEXT;
}
-The ``read_lock()`` and ``read_unlock()`` calls have become rcu_read_lock()
-and rcu_read_unlock(), respectively, and the list_for_each_entry() has
-become list_for_each_entry_rcu(). The **_rcu()** list-traversal primitives
-insert the read-side memory barriers that are required on DEC Alpha CPUs.
+The read_lock() and read_unlock() calls have become rcu_read_lock()
+and rcu_read_unlock(), respectively, and the list_for_each_entry()
+has become list_for_each_entry_rcu(). The **_rcu()** list-traversal
+primitives add READ_ONCE() and diagnostic checks for incorrect use
+outside of an RCU read-side critical section.
The changes to the update side are also straightforward. A reader-writer lock
-might be used as follows for deletion and insertion::
+might be used as follows for deletion and insertion in these simplified
+versions of audit_del_rule() and audit_add_rule()::
static inline int audit_del_rule(struct audit_rule *rule,
struct list_head *list)
@@ -188,16 +203,16 @@ Following are the RCU equivalents for these two functions::
return 0;
}
-Normally, the ``write_lock()`` and ``write_unlock()`` would be replaced by a
+Normally, the write_lock() and write_unlock() would be replaced by a
spin_lock() and a spin_unlock(). But in this case, all callers hold
``audit_filter_mutex``, so no additional locking is required. The
-``auditsc_lock`` can therefore be eliminated, since use of RCU eliminates the
+auditsc_lock can therefore be eliminated, since use of RCU eliminates the
need for writers to exclude readers.
The list_del(), list_add(), and list_add_tail() primitives have been
replaced by list_del_rcu(), list_add_rcu(), and list_add_tail_rcu().
-The **_rcu()** list-manipulation primitives add memory barriers that are needed on
-weakly ordered CPUs (most of them!). The list_del_rcu() primitive omits the
+The **_rcu()** list-manipulation primitives add memory barriers that are
+needed on weakly ordered CPUs. The list_del_rcu() primitive omits the
pointer poisoning debug-assist code that would otherwise cause concurrent
readers to fail spectacularly.
@@ -238,7 +253,9 @@ need to be filled in)::
The RCU version creates a copy, updates the copy, then replaces the old
entry with the newly updated entry. This sequence of actions, allowing
concurrent reads while making a copy to perform an update, is what gives
-RCU (*read-copy update*) its name. The RCU code is as follows::
+RCU (*read-copy update*) its name.
+
+The RCU version of audit_upd_rule() is as follows::
static inline int audit_upd_rule(struct audit_rule *rule,
struct list_head *list,
@@ -267,6 +284,9 @@ RCU (*read-copy update*) its name. The RCU code is as follows::
Again, this assumes that the caller holds ``audit_filter_mutex``. Normally, the
writer lock would become a spinlock in this sort of code.
+The update_lsm_rule() does something very similar, for those who would
+prefer to look at real Linux-kernel code.
+
Another use of this pattern can be found in the openswitch driver's *connection
tracking table* code in ``ct_limit_set()``. The table holds connection tracking
entries and has a limit on the maximum entries. There is one such table
@@ -281,9 +301,10 @@ Example 4: Eliminating Stale Data
---------------------------------
The auditing example above tolerates stale data, as do most algorithms
-that are tracking external state. Because there is a delay from the
-time the external state changes before Linux becomes aware of the change,
-additional RCU-induced staleness is generally not a problem.
+that are tracking external state. After all, given there is a delay
+from the time the external state changes before Linux becomes aware
+of the change, and so as noted earlier, a small quantity of additional
+RCU-induced staleness is generally not a problem.
However, there are many examples where stale data cannot be tolerated.
One example in the Linux kernel is the System V IPC (see the shm_lock()
@@ -302,7 +323,7 @@ Quick Quiz:
If the system-call audit module were to ever need to reject stale data, one way
to accomplish this would be to add a ``deleted`` flag and a ``lock`` spinlock to the
-audit_entry structure, and modify ``audit_filter_task()`` as follows::
+``audit_entry`` structure, and modify audit_filter_task() as follows::
static enum audit_state audit_filter_task(struct task_struct *tsk)
{
@@ -319,6 +340,8 @@ audit_entry structure, and modify ``audit_filter_task()`` as follows::
return AUDIT_BUILD_CONTEXT;
}
rcu_read_unlock();
+ if (state == AUDIT_STATE_RECORD)
+ *key = kstrdup(e->rule.filterkey, GFP_ATOMIC);
return state;
}
}
@@ -326,12 +349,6 @@ audit_entry structure, and modify ``audit_filter_task()`` as follows::
return AUDIT_BUILD_CONTEXT;
}
-Note that this example assumes that entries are only added and deleted.
-Additional mechanism is required to deal correctly with the update-in-place
-performed by ``audit_upd_rule()``. For one thing, ``audit_upd_rule()`` would
-need additional memory barriers to ensure that the list_add_rcu() was really
-executed before the list_del_rcu().
-
The ``audit_del_rule()`` function would need to set the ``deleted`` flag under the
spinlock as follows::
@@ -357,24 +374,32 @@ spinlock as follows::
This too assumes that the caller holds ``audit_filter_mutex``.
+Note that this example assumes that entries are only added and deleted.
+Additional mechanism is required to deal correctly with the update-in-place
+performed by audit_upd_rule(). For one thing, audit_upd_rule() would
+need to hold the locks of both the old ``audit_entry`` and its replacement
+while executing the list_replace_rcu().
+
Example 5: Skipping Stale Objects
---------------------------------
-For some usecases, reader performance can be improved by skipping stale objects
-during read-side list traversal if the object in concern is pending destruction
-after one or more grace periods. One such example can be found in the timerfd
-subsystem. When a ``CLOCK_REALTIME`` clock is reprogrammed - for example due to
-setting of the system time, then all programmed timerfds that depend on this
-clock get triggered and processes waiting on them to expire are woken up in
-advance of their scheduled expiry. To facilitate this, all such timers are added
-to an RCU-managed ``cancel_list`` when they are setup in
+For some use cases, reader performance can be improved by skipping
+stale objects during read-side list traversal, where stale objects
+are those that will be removed and destroyed after one or more grace
+periods. One such example can be found in the timerfd subsystem. When a
+``CLOCK_REALTIME`` clock is reprogrammed (for example due to setting
+of the system time) then all programmed ``timerfds`` that depend on
+this clock get triggered and processes waiting on them are awakened in
+advance of their scheduled expiry. To facilitate this, all such timers
+are added to an RCU-managed ``cancel_list`` when they are setup in
``timerfd_setup_cancel()``::
static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)
{
spin_lock(&ctx->cancel_lock);
- if ((ctx->clockid == CLOCK_REALTIME &&
+ if ((ctx->clockid == CLOCK_REALTIME ||
+ ctx->clockid == CLOCK_REALTIME_ALARM) &&
(flags & TFD_TIMER_ABSTIME) && (flags & TFD_TIMER_CANCEL_ON_SET)) {
if (!ctx->might_cancel) {
ctx->might_cancel = true;
@@ -382,13 +407,16 @@ to an RCU-managed ``cancel_list`` when they are setup in
list_add_rcu(&ctx->clist, &cancel_list);
spin_unlock(&cancel_lock);
}
+ } else {
+ __timerfd_remove_cancel(ctx);
}
spin_unlock(&ctx->cancel_lock);
}
-When a timerfd is freed (fd is closed), then the ``might_cancel`` flag of the
-timerfd object is cleared, the object removed from the ``cancel_list`` and
-destroyed::
+When a timerfd is freed (fd is closed), then the ``might_cancel``
+flag of the timerfd object is cleared, the object removed from the
+``cancel_list`` and destroyed, as shown in this simplified and inlined
+version of timerfd_release()::
int timerfd_release(struct inode *inode, struct file *file)
{
@@ -403,7 +431,10 @@ destroyed::
}
spin_unlock(&ctx->cancel_lock);
- hrtimer_cancel(&ctx->t.tmr);
+ if (isalarm(ctx))
+ alarm_cancel(&ctx->t.alarm);
+ else
+ hrtimer_cancel(&ctx->t.tmr);
kfree_rcu(ctx, rcu);
return 0;
}
@@ -416,6 +447,7 @@ objects::
void timerfd_clock_was_set(void)
{
+ ktime_t moffs = ktime_mono_to_real(0);
struct timerfd_ctx *ctx;
unsigned long flags;
@@ -424,7 +456,7 @@ objects::
if (!ctx->might_cancel)
continue;
spin_lock_irqsave(&ctx->wqh.lock, flags);
- if (ctx->moffs != ktime_mono_to_real(0)) {
+ if (ctx->moffs != moffs) {
ctx->moffs = KTIME_MAX;
ctx->ticks++;
wake_up_locked_poll(&ctx->wqh, EPOLLIN);
@@ -434,10 +466,10 @@ objects::
rcu_read_unlock();
}
-The key point here is, because RCU-traversal of the ``cancel_list`` happens
-while objects are being added and removed to the list, sometimes the traversal
-can step on an object that has been removed from the list. In this example, it
-is seen that it is better to skip such objects using a flag.
+The key point is that because RCU-protected traversal of the
+``cancel_list`` happens concurrently with object addition and removal,
+sometimes the traversal can access an object that has been removed from
+the list. In this example, a flag is used to skip such objects.
Summary
diff --git a/Documentation/RCU/lockdep.rst b/Documentation/RCU/lockdep.rst
index a94f55991a71..9308f1bdba05 100644
--- a/Documentation/RCU/lockdep.rst
+++ b/Documentation/RCU/lockdep.rst
@@ -17,7 +17,9 @@ state::
rcu_read_lock_held() for normal RCU.
rcu_read_lock_bh_held() for RCU-bh.
rcu_read_lock_sched_held() for RCU-sched.
+ rcu_read_lock_any_held() for any of normal RCU, RCU-bh, and RCU-sched.
srcu_read_lock_held() for SRCU.
+ rcu_read_lock_trace_held() for RCU Tasks Trace.
These functions are conservative, and will therefore return 1 if they
aren't certain (for example, if CONFIG_DEBUG_LOCK_ALLOC is not set).
@@ -53,6 +55,8 @@ checking of rcu_dereference() primitives:
is invoked by both SRCU readers and updaters.
rcu_dereference_raw(p):
Don't check. (Use sparingly, if at all.)
+ rcu_dereference_raw_check(p):
+ Don't do lockdep at all. (Use sparingly, if at all.)
rcu_dereference_protected(p, c):
Use explicit check expression "c", and omit all barriers
and compiler constraints. This is useful when the data
diff --git a/Documentation/accel/index.rst b/Documentation/accel/index.rst
new file mode 100644
index 000000000000..2b43c9a7f67b
--- /dev/null
+++ b/Documentation/accel/index.rst
@@ -0,0 +1,17 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+====================
+Compute Accelerators
+====================
+
+.. toctree::
+ :maxdepth: 1
+
+ introduction
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
diff --git a/Documentation/accel/introduction.rst b/Documentation/accel/introduction.rst
new file mode 100644
index 000000000000..6f31af14b1fc
--- /dev/null
+++ b/Documentation/accel/introduction.rst
@@ -0,0 +1,110 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+============
+Introduction
+============
+
+The Linux compute accelerators subsystem is designed to expose compute
+accelerators in a common way to user-space and provide a common set of
+functionality.
+
+These devices can be either stand-alone ASICs or IP blocks inside an SoC/GPU.
+Although these devices are typically designed to accelerate
+Machine-Learning (ML) and/or Deep-Learning (DL) computations, the accel layer
+is not limited to handling these types of accelerators.
+
+Typically, a compute accelerator will belong to one of the following
+categories:
+
+- Edge AI - doing inference at an edge device. It can be an embedded ASIC/FPGA,
+ or an IP inside a SoC (e.g. laptop web camera). These devices
+ are typically configured using registers and can work with or without DMA.
+
+- Inference data-center - single/multi user devices in a large server. This
+ type of device can be stand-alone or an IP inside a SoC or a GPU. It will
+ have on-board DRAM (to hold the DL topology), DMA engines and
+ command submission queues (either kernel or user-space queues).
+ It might also have an MMU to manage multiple users and might also enable
+ virtualization (SR-IOV) to support multiple VMs on the same device. In
+ addition, these devices will usually have some tools, such as profiler and
+ debugger.
+
+- Training data-center - Similar to Inference data-center cards, but typically
+ have more computational power and memory b/w (e.g. HBM) and will likely have
+ a method of scaling-up/out, i.e. connecting to other training cards inside
+ the server or in other servers, respectively.
+
+All these devices typically have different runtime user-space software stacks,
+that are tailored-made to their h/w. In addition, they will also probably
+include a compiler to generate programs to their custom-made computational
+engines. Typically, the common layer in user-space will be the DL frameworks,
+such as PyTorch and TensorFlow.
+
+Sharing code with DRM
+=====================
+
+Because this type of devices can be an IP inside GPUs or have similar
+characteristics as those of GPUs, the accel subsystem will use the
+DRM subsystem's code and functionality. i.e. the accel core code will
+be part of the DRM subsystem and an accel device will be a new type of DRM
+device.
+
+This will allow us to leverage the extensive DRM code-base and
+collaborate with DRM developers that have experience with this type of
+devices. In addition, new features that will be added for the accelerator
+drivers can be of use to GPU drivers as well.
+
+Differentiation from GPUs
+=========================
+
+Because we want to prevent the extensive user-space graphic software stack
+from trying to use an accelerator as a GPU, the compute accelerators will be
+differentiated from GPUs by using a new major number and new device char files.
+
+Furthermore, the drivers will be located in a separate place in the kernel
+tree - drivers/accel/.
+
+The accelerator devices will be exposed to the user space with the dedicated
+261 major number and will have the following convention:
+
+- device char files - /dev/accel/accel*
+- sysfs - /sys/class/accel/accel*/
+- debugfs - /sys/kernel/debug/accel/accel*/
+
+Getting Started
+===============
+
+First, read the DRM documentation at Documentation/gpu/index.rst.
+Not only it will explain how to write a new DRM driver but it will also
+contain all the information on how to contribute, the Code Of Conduct and
+what is the coding style/documentation. All of that is the same for the
+accel subsystem.
+
+Second, make sure the kernel is configured with CONFIG_DRM_ACCEL.
+
+To expose your device as an accelerator, two changes are needed to
+be done in your driver (as opposed to a standard DRM driver):
+
+- Add the DRIVER_COMPUTE_ACCEL feature flag in your drm_driver's
+ driver_features field. It is important to note that this driver feature is
+ mutually exclusive with DRIVER_RENDER and DRIVER_MODESET. Devices that want
+ to expose both graphics and compute device char files should be handled by
+ two drivers that are connected using the auxiliary bus framework.
+
+- Change the open callback in your driver fops structure to accel_open().
+ Alternatively, your driver can use DEFINE_DRM_ACCEL_FOPS macro to easily
+ set the correct function operations pointers structure.
+
+External References
+===================
+
+email threads
+-------------
+
+* `Initial discussion on the New subsystem for acceleration devices <https://lkml.org/lkml/2022/7/31/83>`_ - Oded Gabbay (2022)
+* `patch-set to add the new subsystem <https://lkml.org/lkml/2022/10/22/544>`_ - Oded Gabbay (2022)
+
+Conference talks
+----------------
+
+* `LPC 2022 Accelerators BOF outcomes summary <https://airlied.blogspot.com/2022/09/accelerators-bof-outcomes-summary.html>`_ - Dave Airlie (2022)
diff --git a/Documentation/admin-guide/bootconfig.rst b/Documentation/admin-guide/bootconfig.rst
index d99994345d41..9355c525fbe0 100644
--- a/Documentation/admin-guide/bootconfig.rst
+++ b/Documentation/admin-guide/bootconfig.rst
@@ -229,7 +229,7 @@ In addition to the kernel command line, the boot config can be used for
passing the kernel parameters. All the key-value pairs under ``kernel``
key will be passed to kernel cmdline directly. Moreover, the key-value
pairs under ``init`` will be passed to init process via the cmdline.
-The parameters are concatinated with user-given kernel cmdline string
+The parameters are concatenated with user-given kernel cmdline string
as the following order, so that the command line parameter can override
bootconfig parameters (this depends on how the subsystem handles parameters
but in general, earlier parameter will be overwritten by later one.)::
diff --git a/Documentation/admin-guide/device-mapper/dm-init.rst b/Documentation/admin-guide/device-mapper/dm-init.rst
index e5242ff17e9b..981d6a907699 100644
--- a/Documentation/admin-guide/device-mapper/dm-init.rst
+++ b/Documentation/admin-guide/device-mapper/dm-init.rst
@@ -123,3 +123,11 @@ Other examples (per target):
0 1638400 verity 1 8:1 8:2 4096 4096 204800 1 sha256
fb1a5a0f00deb908d8b53cb270858975e76cf64105d412ce764225d53b8f3cfd
51934789604d1b92399c52e7cb149d1b3a1b74bbbcb103b2a0aaacbed5c08584
+
+For setups using device-mapper on top of asynchronously probed block
+devices (MMC, USB, ..), it may be necessary to tell dm-init to
+explicitly wait for them to become available before setting up the
+device-mapper tables. This can be done with the "dm-mod.waitfor="
+module parameter, which takes a list of devices to wait for::
+
+ dm-mod.waitfor=<device1>[,..,<deviceN>]
diff --git a/Documentation/admin-guide/devices.txt b/Documentation/admin-guide/devices.txt
index 9764d6edb189..06c525e01ea5 100644
--- a/Documentation/admin-guide/devices.txt
+++ b/Documentation/admin-guide/devices.txt
@@ -3080,6 +3080,11 @@
...
255 = /dev/osd255 256th OSD Device
+ 261 char Compute Acceleration Devices
+ 0 = /dev/accel/accel0 First acceleration device
+ 1 = /dev/accel/accel1 Second acceleration device
+ ...
+
384-511 char RESERVED FOR DYNAMIC ASSIGNMENT
Character devices that request a dynamic allocation of major
number will take numbers starting from 511 and downward,
diff --git a/Documentation/admin-guide/hw_random.rst b/Documentation/admin-guide/hw_random.rst
index 121de96e395e..d494601717f1 100644
--- a/Documentation/admin-guide/hw_random.rst
+++ b/Documentation/admin-guide/hw_random.rst
@@ -1,6 +1,6 @@
-==========================================================
-Linux support for random number generator in i8xx chipsets
-==========================================================
+=================================
+Hardware random number generators
+=================================
Introduction
============
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 42af9ca0127e..fb388c6c8c60 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -703,6 +703,17 @@
condev= [HW,S390] console device
conmode=
+ con3215_drop= [S390] 3215 console drop mode.
+ Format: y|n|Y|N|1|0
+ When set to true, drop data on the 3215 console when
+ the console buffer is full. In this case the
+ operator using a 3270 terminal emulator (for example
+ x3270) does not have to enter the clear key for the
+ console output to advance and the kernel to continue.
+ This leads to a much faster boot time when a 3270
+ terminal emulator is active. If no 3270 terminal
+ emulator is used, this parameter has no effect.
+
console= [KNL] Output console device and options.
tty<n> Use the virtual console device <n>.
@@ -831,7 +842,7 @@
memory region [offset, offset + size] for that kernel
image. If '@offset' is omitted, then a suitable offset
is selected automatically.
- [KNL, X86-64] Select a region under 4G first, and
+ [KNL, X86-64, ARM64] Select a region under 4G first, and
fall back to reserve region above 4G when '@offset'
hasn't been specified.
See Documentation/admin-guide/kdump/kdump.rst for further details.
@@ -851,26 +862,23 @@
available.
It will be ignored if crashkernel=X is specified.
crashkernel=size[KMG],low
- [KNL, X86-64] range under 4G. When crashkernel=X,high
+ [KNL, X86-64, ARM64] range under 4G. When crashkernel=X,high
is passed, kernel could allocate physical memory region
above 4G, that cause second kernel crash on system
that require some amount of low memory, e.g. swiotlb
requires at least 64M+32K low memory, also enough extra
low memory is needed to make sure DMA buffers for 32-bit
devices won't run out. Kernel would try to allocate
- at least 256M below 4G automatically.
+ default size of memory below 4G automatically. The default
+ size is platform dependent.
+ --> x86: max(swiotlb_size_or_default() + 8MiB, 256MiB)
+ --> arm64: 128MiB
This one lets the user specify own low range under 4G
for second kernel instead.
0: to disable low allocation.
It will be ignored when crashkernel=X,high is not used
or memory reserved is below 4G.
- [KNL, ARM64] range in low memory.
- This one lets the user specify a low range in the
- DMA zone for the crash dump kernel.
- It will be ignored when crashkernel=X,high is not used
- or memory reserved is located in the DMA zones.
-
cryptomgr.notests
[KNL] Disable crypto self-tests
@@ -3777,12 +3785,15 @@
shutdown the other cpus. Instead use the REBOOT_VECTOR
irq.
- nomodeset Disable kernel modesetting. DRM drivers will not perform
- display-mode changes or accelerated rendering. Only the
- system framebuffer will be available for use if this was
- set-up by the firmware or boot loader.
+ nomodeset Disable kernel modesetting. Most systems' firmware
+ sets up a display mode and provides framebuffer memory
+ for output. With nomodeset, DRM and fbdev drivers will
+ not load if they could possibly displace the pre-
+ initialized output. Only the system framebuffer will
+ be available for use. The respective drivers will not
+ perform display-mode changes or accelerated rendering.
- Useful as fallback, or for testing and debugging.
+ Useful as error fallback, or for testing and debugging.
nomodule Disable module load
@@ -4566,17 +4577,15 @@
ramdisk_start= [RAM] RAM disk image start address
- random.trust_cpu={on,off}
- [KNL] Enable or disable trusting the use of the
- CPU's random number generator (if available) to
- fully seed the kernel's CRNG. Default is controlled
- by CONFIG_RANDOM_TRUST_CPU.
-
- random.trust_bootloader={on,off}
- [KNL] Enable or disable trusting the use of a
- seed passed by the bootloader (if available) to
- fully seed the kernel's CRNG. Default is controlled
- by CONFIG_RANDOM_TRUST_BOOTLOADER.
+ random.trust_cpu=off
+ [KNL] Disable trusting the use of the CPU's
+ random number generator (if available) to
+ initialize the kernel's RNG.
+
+ random.trust_bootloader=off
+ [KNL] Disable trusting the use of the a seed
+ passed by the bootloader (if available) to
+ initialize the kernel's RNG.
randomize_kstack_offset=
[KNL] Enable or disable kernel stack offset
diff --git a/Documentation/admin-guide/media/cec-drivers.rst b/Documentation/admin-guide/media/cec-drivers.rst
deleted file mode 100644
index 8d9686c08df9..000000000000
--- a/Documentation/admin-guide/media/cec-drivers.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-=================================
-CEC driver-specific documentation
-=================================
-
-.. toctree::
- :maxdepth: 2
-
- pulse8-cec
diff --git a/Documentation/admin-guide/media/cec.rst b/Documentation/admin-guide/media/cec.rst
new file mode 100644
index 000000000000..5c7259371494
--- /dev/null
+++ b/Documentation/admin-guide/media/cec.rst
@@ -0,0 +1,369 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+========
+HDMI CEC
+========
+
+Supported hardware in mainline
+==============================
+
+HDMI Transmitters:
+
+- Exynos4
+- Exynos5
+- STIH4xx HDMI CEC
+- V4L2 adv7511 (same HW, but a different driver from the drm adv7511)
+- stm32
+- Allwinner A10 (sun4i)
+- Raspberry Pi
+- dw-hdmi (Synopsis IP)
+- amlogic (meson ao-cec and ao-cec-g12a)
+- drm adv7511/adv7533
+- omap4
+- tegra
+- rk3288, rk3399
+- tda998x
+- DisplayPort CEC-Tunneling-over-AUX on i915, nouveau and amdgpu
+- ChromeOS EC CEC
+- CEC for SECO boards (UDOO x86).
+- Chrontel CH7322
+
+
+HDMI Receivers:
+
+- adv7604/11/12
+- adv7842
+- tc358743
+
+USB Dongles (see below for additional information on how to use these
+dongles):
+
+- Pulse-Eight: the pulse8-cec driver implements the following module option:
+ ``persistent_config``: by default this is off, but when set to 1 the driver
+ will store the current settings to the device's internal eeprom and restore
+ it the next time the device is connected to the USB port.
+- RainShadow Tech. Note: this driver does not support the persistent_config
+ module option of the Pulse-Eight driver. The hardware supports it, but I
+ have no plans to add this feature. But I accept patches :-)
+
+Miscellaneous:
+
+- vivid: emulates a CEC receiver and CEC transmitter.
+ Can be used to test CEC applications without actual CEC hardware.
+
+- cec-gpio. If the CEC pin is hooked up to a GPIO pin then
+ you can control the CEC line through this driver. This supports error
+ injection as well.
+
+
+Utilities
+=========
+
+Utilities are available here: https://git.linuxtv.org/v4l-utils.git
+
+``utils/cec-ctl``: control a CEC device
+
+``utils/cec-compliance``: test compliance of a remote CEC device
+
+``utils/cec-follower``: emulate a CEC follower device
+
+Note that ``cec-ctl`` has support for the CEC Hospitality Profile as is
+used in some hotel displays. See http://www.htng.org.
+
+Note that the libcec library (https://github.com/Pulse-Eight/libcec) supports
+the linux CEC framework.
+
+If you want to get the CEC specification, then look at the References of
+the HDMI wikipedia page: https://en.wikipedia.org/wiki/HDMI. CEC is part
+of the HDMI specification. HDMI 1.3 is freely available (very similar to
+HDMI 1.4 w.r.t. CEC) and should be good enough for most things.
+
+
+DisplayPort to HDMI Adapters with working CEC
+=============================================
+
+Background: most adapters do not support the CEC Tunneling feature,
+and of those that do many did not actually connect the CEC pin.
+Unfortunately, this means that while a CEC device is created, it
+is actually all alone in the world and will never be able to see other
+CEC devices.
+
+This is a list of known working adapters that have CEC Tunneling AND
+that properly connected the CEC pin. If you find adapters that work
+but are not in this list, then drop me a note.
+
+To test: hook up your DP-to-HDMI adapter to a CEC capable device
+(typically a TV), then run::
+
+ cec-ctl --playback # Configure the PC as a CEC Playback device
+ cec-ctl -S # Show the CEC topology
+
+The ``cec-ctl -S`` command should show at least two CEC devices,
+ourselves and the CEC device you are connected to (i.e. typically the TV).
+
+General note: I have only seen this work with the Parade PS175, PS176 and
+PS186 chipsets and the MegaChips 2900. While MegaChips 28x0 claims CEC support,
+I have never seen it work.
+
+USB-C to HDMI
+-------------
+
+Samsung Multiport Adapter EE-PW700: https://www.samsung.com/ie/support/model/EE-PW700BBEGWW/
+
+Kramer ADC-U31C/HF: https://www.kramerav.com/product/ADC-U31C/HF
+
+Club3D CAC-2504: https://www.club-3d.com/en/detail/2449/usb_3.1_type_c_to_hdmi_2.0_uhd_4k_60hz_active_adapter/
+
+DisplayPort to HDMI
+-------------------
+
+Club3D CAC-1080: https://www.club-3d.com/en/detail/2442/displayport_1.4_to_hdmi_2.0b_hdr/
+
+CableCreation (SKU: CD0712): https://www.cablecreation.com/products/active-displayport-to-hdmi-adapter-4k-hdr
+
+HP DisplayPort to HDMI True 4k Adapter (P/N 2JA63AA): https://www.hp.com/us-en/shop/pdp/hp-displayport-to-hdmi-true-4k-adapter
+
+Mini-DisplayPort to HDMI
+------------------------
+
+Club3D CAC-1180: https://www.club-3d.com/en/detail/2443/mini_displayport_1.4_to_hdmi_2.0b_hdr/
+
+Note that passive adapters will never work, you need an active adapter.
+
+The Club3D adapters in this list are all MegaChips 2900 based. Other Club3D adapters
+are PS176 based and do NOT have the CEC pin hooked up, so only the three Club3D
+adapters above are known to work.
+
+I suspect that MegaChips 2900 based designs in general are likely to work
+whereas with the PS176 it is more hit-and-miss (mostly miss). The PS186 is
+likely to have the CEC pin hooked up, it looks like they changed the reference
+design for that chipset.
+
+
+USB CEC Dongles
+===============
+
+These dongles appear as ``/dev/ttyACMX`` devices and need the ``inputattach``
+utility to create the ``/dev/cecX`` devices. Support for the Pulse-Eight
+has been added to ``inputattach`` 1.6.0. Support for the Rainshadow Tech has
+been added to ``inputattach`` 1.6.1.
+
+You also need udev rules to automatically start systemd services::
+
+ SUBSYSTEM=="tty", KERNEL=="ttyACM[0-9]*", ATTRS{idVendor}=="2548", ATTRS{idProduct}=="1002", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}+="pulse8-cec-inputattach@%k.service"
+ SUBSYSTEM=="tty", KERNEL=="ttyACM[0-9]*", ATTRS{idVendor}=="2548", ATTRS{idProduct}=="1001", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}+="pulse8-cec-inputattach@%k.service"
+ SUBSYSTEM=="tty", KERNEL=="ttyACM[0-9]*", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="ff59", ACTION=="add", TAG+="systemd", ENV{SYSTEMD_WANTS}+="rainshadow-cec-inputattach@%k.service"
+
+and these systemd services:
+
+For Pulse-Eight make /lib/systemd/system/pulse8-cec-inputattach@.service::
+
+ [Unit]
+ Description=inputattach for pulse8-cec device on %I
+
+ [Service]
+ Type=simple
+ ExecStart=/usr/bin/inputattach --pulse8-cec /dev/%I
+
+For the RainShadow Tech make /lib/systemd/system/rainshadow-cec-inputattach@.service::
+
+ [Unit]
+ Description=inputattach for rainshadow-cec device on %I
+
+ [Service]
+ Type=simple
+ ExecStart=/usr/bin/inputattach --rainshadow-cec /dev/%I
+
+
+For proper suspend/resume support create: /lib/systemd/system/restart-cec-inputattach.service::
+
+ [Unit]
+ Description=restart inputattach for cec devices
+ After=suspend.target
+
+ [Service]
+ Type=forking
+ ExecStart=/bin/bash -c 'for d in /dev/serial/by-id/usb-Pulse-Eight*; do /usr/bin/inputattach --daemon --pulse8-cec $d; done; for d in /dev/serial/by-id/usb-RainShadow_Tech*; do /usr/bin/inputattach --daemon --rainshadow-cec $d; done'
+
+ [Install]
+ WantedBy=suspend.target
+
+And run ``systemctl enable restart-cec-inputattach``.
+
+To automatically set the physical address of the CEC device whenever the
+EDID changes, you can use ``cec-ctl`` with the ``-E`` option::
+
+ cec-ctl -E /sys/class/drm/card0-DP-1/edid
+
+This assumes the dongle is connected to the card0-DP-1 output (``xrandr`` will tell
+you which output is used) and it will poll for changes to the EDID and update
+the Physical Address whenever they occur.
+
+To automatically run this command you can use cron. Edit crontab with
+``crontab -e`` and add this line::
+
+ @reboot /usr/local/bin/cec-ctl -E /sys/class/drm/card0-DP-1/edid
+
+This only works for display drivers that expose the EDID in ``/sys/class/drm``,
+such as the i915 driver.
+
+
+CEC Without HPD
+===============
+
+Some displays when in standby mode have no HDMI Hotplug Detect signal, but
+CEC is still enabled so connected devices can send an <Image View On> CEC
+message in order to wake up such displays. Unfortunately, not all CEC
+adapters can support this. An example is the Odroid-U3 SBC that has a
+level-shifter that is powered off when the HPD signal is low, thus
+blocking the CEC pin. Even though the SoC can use CEC without a HPD,
+the level-shifter will prevent this from functioning.
+
+There is a CEC capability flag to signal this: ``CEC_CAP_NEEDS_HPD``.
+If set, then the hardware cannot wake up displays with this behavior.
+
+Note for CEC application implementers: the <Image View On> message must
+be the first message you send, don't send any other messages before.
+Certain very bad but unfortunately not uncommon CEC implementations
+get very confused if they receive anything else but this message and
+they won't wake up.
+
+When writing a driver it can be tricky to test this. There are two
+ways to do this:
+
+1) Get a Pulse-Eight USB CEC dongle, connect an HDMI cable from your
+ device to the Pulse-Eight, but do not connect the Pulse-Eight to
+ the display.
+
+ Now configure the Pulse-Eight dongle::
+
+ cec-ctl -p0.0.0.0 --tv
+
+ and start monitoring::
+
+ sudo cec-ctl -M
+
+ On the device you are testing run::
+
+ cec-ctl --playback
+
+ It should report a physical address of f.f.f.f. Now run this
+ command::
+
+ cec-ctl -t0 --image-view-on
+
+ The Pulse-Eight should see the <Image View On> message. If not,
+ then something (hardware and/or software) is preventing the CEC
+ message from going out.
+
+ To make sure you have the wiring correct just connect the
+ Pulse-Eight to a CEC-enabled display and run the same command
+ on your device: now there is a HPD, so you should see the command
+ arriving at the Pulse-Eight.
+
+2) If you have another linux device supporting CEC without HPD, then
+ you can just connect your device to that device. Yes, you can connect
+ two HDMI outputs together. You won't have a HPD (which is what we
+ want for this test), but the second device can monitor the CEC pin.
+
+ Otherwise use the same commands as in 1.
+
+If CEC messages do not come through when there is no HPD, then you
+need to figure out why. Typically it is either a hardware restriction
+or the software powers off the CEC core when the HPD goes low. The
+first cannot be corrected of course, the second will likely required
+driver changes.
+
+
+Microcontrollers & CEC
+======================
+
+We have seen some CEC implementations in displays that use a microcontroller
+to sample the bus. This does not have to be a problem, but some implementations
+have timing issues. This is hard to discover unless you can hook up a low-level
+CEC debugger (see the next section).
+
+You will see cases where the CEC transmitter holds the CEC line high or low for
+a longer time than is allowed. For directed messages this is not a problem since
+if that happens the message will not be Acked and it will be retransmitted.
+For broadcast messages no such mechanism exists.
+
+It's not clear what to do about this. It is probably wise to transmit some
+broadcast messages twice to reduce the chance of them being lost. Specifically
+<Standby> and <Active Source> are candidates for that.
+
+
+Making a CEC debugger
+=====================
+
+By using a Raspberry Pi 2B/3/4 and some cheap components you can make
+your own low-level CEC debugger.
+
+Here is a picture of my setup:
+
+https://hverkuil.home.xs4all.nl/rpi3-cec.jpg
+
+It's a Raspberry Pi 3 together with a breadboard and some breadboard wires:
+
+http://www.dx.com/p/diy-40p-male-to-female-male-to-male-female-to-female-dupont-line-wire-3pcs-356089#.WYLOOXWGN7I
+
+Finally on of these HDMI female-female passthrough connectors (full soldering type 1):
+
+https://elabbay.myshopify.com/collections/camera/products/hdmi-af-af-v1a-hdmi-type-a-female-to-hdmi-type-a-female-pass-through-adapter-breakout-board?variant=45533926147
+
+We've tested this and it works up to 4kp30 (297 MHz). The quality is not high
+enough to pass-through 4kp60 (594 MHz).
+
+I also added an RTC and a breakout shield:
+
+https://www.amazon.com/Makerfire%C2%AE-Raspberry-Module-DS1307-Battery/dp/B00ZOXWHK4
+
+https://www.dx.com/p/raspberry-pi-gpio-expansion-board-breadboard-easy-multiplexing-board-one-to-three-with-screw-for-raspberry-pi-2-3-b-b-2729992.html#.YGRCG0MzZ7I
+
+These two are not needed but they make life a bit easier.
+
+If you want to monitor the HPD line as well, then you need one of these
+level shifters:
+
+https://www.adafruit.com/product/757
+
+(This is just where I got these components, there are many other places you
+can get similar things).
+
+The CEC pin of the HDMI connector needs to be connected to these pins:
+CE0/IO8 and CE1/IO7 (pull-up GPIOs). The (optional) HPD pin of the HDMI
+connector should be connected (via a level shifter to convert the 5V
+to 3.3V) to these pins: IO17 and IO27. The (optional) 5V pin of the HDMI
+connector should be connected (via a level shifter) to these pins: IO22
+and IO24. Monitoring the HPD an 5V lines is not necessary, but it is helpful.
+
+This kernel patch will hook up the cec-gpio driver correctly to
+e.g. ``arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts``::
+
+ cec-gpio@7 {
+ compatible = "cec-gpio";
+ cec-gpios = <&gpio 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ hpd-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
+ v5-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
+ };
+
+ cec-gpio@8 {
+ compatible = "cec-gpio";
+ cec-gpios = <&gpio 8 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
+ hpd-gpios = <&gpio 27 GPIO_ACTIVE_HIGH>;
+ v5-gpios = <&gpio 24 GPIO_ACTIVE_HIGH>;
+ };
+
+This dts change will enable two cec GPIO devices: I typically use one to
+send/receive CEC commands and the other to monitor. If you monitor using
+an unconfigured CEC adapter then it will use GPIO interrupts which makes
+monitoring very accurate.
+
+The documentation on how to use the error injection is here: :ref:`cec_pin_error_inj`.
+
+``cec-ctl --monitor-pin`` will do low-level CEC bus sniffing and analysis.
+You can also store the CEC traffic to file using ``--store-pin`` and analyze
+it later using ``--analyze-pin``.
+
+You can also use this as a full-fledged CEC device by configuring it
+using ``cec-ctl --tv -p0.0.0.0`` or ``cec-ctl --playback -p1.0.0.0``.
diff --git a/Documentation/admin-guide/media/index.rst b/Documentation/admin-guide/media/index.rst
index c676af665111..43f4a292b245 100644
--- a/Documentation/admin-guide/media/index.rst
+++ b/Documentation/admin-guide/media/index.rst
@@ -38,13 +38,14 @@ The media subsystem
remote-controller
+ cec
+
dvb
cardlist
v4l-drivers
dvb-drivers
- cec-drivers
**Copyright** |copy| 1999-2020 : LinuxTV Developers
diff --git a/Documentation/admin-guide/media/pulse8-cec.rst b/Documentation/admin-guide/media/pulse8-cec.rst
deleted file mode 100644
index 356d08b519f3..000000000000
--- a/Documentation/admin-guide/media/pulse8-cec.rst
+++ /dev/null
@@ -1,13 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-Pulse-Eight CEC Adapter driver
-==============================
-
-The pulse8-cec driver implements the following module option:
-
-``persistent_config``
----------------------
-
-By default this is off, but when set to 1 the driver will store the current
-settings to the device's internal eeprom and restore it the next time the
-device is connected to the USB port.
diff --git a/Documentation/admin-guide/media/v4l-drivers.rst b/Documentation/admin-guide/media/v4l-drivers.rst
index 9c7ebe2ca3bd..90a026ee05c6 100644
--- a/Documentation/admin-guide/media/v4l-drivers.rst
+++ b/Documentation/admin-guide/media/v4l-drivers.rst
@@ -31,4 +31,5 @@ Video4Linux (V4L) driver-specific documentation
si4713
si476x
vimc
+ visl
vivid
diff --git a/Documentation/admin-guide/media/vimc.rst b/Documentation/admin-guide/media/vimc.rst
index 3b4d2b36b4f3..29d843a8ddb1 100644
--- a/Documentation/admin-guide/media/vimc.rst
+++ b/Documentation/admin-guide/media/vimc.rst
@@ -35,11 +35,11 @@ of commands fits for the default topology:
media-ctl -d platform:vimc -V '"Sensor A":0[fmt:SBGGR8_1X8/640x480]'
media-ctl -d platform:vimc -V '"Debayer A":0[fmt:SBGGR8_1X8/640x480]'
- media-ctl -d platform:vimc -V '"Sensor B":0[fmt:SBGGR8_1X8/640x480]'
- media-ctl -d platform:vimc -V '"Debayer B":0[fmt:SBGGR8_1X8/640x480]'
- v4l2-ctl -z platform:vimc -d "RGB/YUV Capture" -v width=1920,height=1440
+ media-ctl -d platform:vimc -V '"Scaler":0[fmt:RGB888_1X24/640x480]'
+ media-ctl -d platform:vimc -V '"Scaler":0[crop:(100,50)/400x150]'
+ media-ctl -d platform:vimc -V '"Scaler":1[fmt:RGB888_1X24/300x700]'
+ v4l2-ctl -z platform:vimc -d "RGB/YUV Capture" -v width=300,height=700
v4l2-ctl -z platform:vimc -d "Raw Capture 0" -v pixelformat=BA81
- v4l2-ctl -z platform:vimc -d "Raw Capture 1" -v pixelformat=BA81
Subdevices
----------
diff --git a/Documentation/admin-guide/media/visl.rst b/Documentation/admin-guide/media/visl.rst
new file mode 100644
index 000000000000..7d2dc78341c9
--- /dev/null
+++ b/Documentation/admin-guide/media/visl.rst
@@ -0,0 +1,175 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+The Virtual Stateless Decoder Driver (visl)
+===========================================
+
+A virtual stateless decoder device for stateless uAPI development
+purposes.
+
+This tool's objective is to help the development and testing of
+userspace applications that use the V4L2 stateless API to decode media.
+
+A userspace implementation can use visl to run a decoding loop even when
+no hardware is available or when the kernel uAPI for the codec has not
+been upstreamed yet. This can reveal bugs at an early stage.
+
+This driver can also trace the contents of the V4L2 controls submitted
+to it. It can also dump the contents of the vb2 buffers through a
+debugfs interface. This is in many ways similar to the tracing
+infrastructure available for other popular encode/decode APIs out there
+and can help develop a userspace application by using another (working)
+one as a reference.
+
+.. note::
+
+ No actual decoding of video frames is performed by visl. The
+ V4L2 test pattern generator is used to write various debug information
+ to the capture buffers instead.
+
+Module parameters
+-----------------
+
+- visl_debug: Activates debug info, printing various debug messages through
+ dprintk. Also controls whether per-frame debug info is shown. Defaults to off.
+ Note that enabling this feature can result in slow performance through serial.
+
+- visl_transtime_ms: Simulated process time in milliseconds. Slowing down the
+ decoding speed can be useful for debugging.
+
+- visl_dprintk_frame_start, visl_dprintk_frame_nframes: Dictates a range of
+ frames where dprintk is activated. This only controls the dprintk tracing on a
+ per-frame basis. Note that printing a lot of data can be slow through serial.
+
+- keep_bitstream_buffers: Controls whether bitstream (i.e. OUTPUT) buffers are
+ kept after a decoding session. Defaults to false so as to reduce the amount of
+ clutter. keep_bitstream_buffers == false works well when live debugging the
+ client program with GDB.
+
+- bitstream_trace_frame_start, bitstream_trace_nframes: Similar to
+ visl_dprintk_frame_start, visl_dprintk_nframes, but controls the dumping of
+ buffer data through debugfs instead.
+
+What is the default use case for this driver?
+---------------------------------------------
+
+This driver can be used as a way to compare different userspace implementations.
+This assumes that a working client is run against visl and that the ftrace and
+OUTPUT buffer data is subsequently used to debug a work-in-progress
+implementation.
+
+Information on reference frames, their timestamps, the status of the OUTPUT and
+CAPTURE queues and more can be read directly from the CAPTURE buffers.
+
+Supported codecs
+----------------
+
+The following codecs are supported:
+
+- FWHT
+- MPEG2
+- VP8
+- VP9
+- H.264
+- HEVC
+
+visl trace events
+-----------------
+The trace events are defined on a per-codec basis, e.g.:
+
+.. code-block:: bash
+
+ $ ls /sys/kernel/debug/tracing/events/ | grep visl
+ visl_fwht_controls
+ visl_h264_controls
+ visl_hevc_controls
+ visl_mpeg2_controls
+ visl_vp8_controls
+ visl_vp9_controls
+
+For example, in order to dump HEVC SPS data:
+
+.. code-block:: bash
+
+ $ echo 1 > /sys/kernel/debug/tracing/events/visl_hevc_controls/v4l2_ctrl_hevc_sps/enable
+
+The SPS data will be dumped to the trace buffer, i.e.:
+
+.. code-block:: bash
+
+ $ cat /sys/kernel/debug/tracing/trace
+ video_parameter_set_id 0
+ seq_parameter_set_id 0
+ pic_width_in_luma_samples 1920
+ pic_height_in_luma_samples 1080
+ bit_depth_luma_minus8 0
+ bit_depth_chroma_minus8 0
+ log2_max_pic_order_cnt_lsb_minus4 4
+ sps_max_dec_pic_buffering_minus1 6
+ sps_max_num_reorder_pics 2
+ sps_max_latency_increase_plus1 0
+ log2_min_luma_coding_block_size_minus3 0
+ log2_diff_max_min_luma_coding_block_size 3
+ log2_min_luma_transform_block_size_minus2 0
+ log2_diff_max_min_luma_transform_block_size 3
+ max_transform_hierarchy_depth_inter 2
+ max_transform_hierarchy_depth_intra 2
+ pcm_sample_bit_depth_luma_minus1 0
+ pcm_sample_bit_depth_chroma_minus1 0
+ log2_min_pcm_luma_coding_block_size_minus3 0
+ log2_diff_max_min_pcm_luma_coding_block_size 0
+ num_short_term_ref_pic_sets 0
+ num_long_term_ref_pics_sps 0
+ chroma_format_idc 1
+ sps_max_sub_layers_minus1 0
+ flags AMP_ENABLED|SAMPLE_ADAPTIVE_OFFSET|TEMPORAL_MVP_ENABLED|STRONG_INTRA_SMOOTHING_ENABLED
+
+
+Dumping OUTPUT buffer data through debugfs
+------------------------------------------
+
+If the **VISL_DEBUGFS** Kconfig is enabled, visl will populate
+**/sys/kernel/debug/visl/bitstream** with OUTPUT buffer data according to the
+values of bitstream_trace_frame_start and bitstream_trace_nframes. This can
+highlight errors as broken clients may fail to fill the buffers properly.
+
+A single file is created for each processed OUTPUT buffer. Its name contains an
+integer that denotes the buffer sequence, i.e.:
+
+.. code-block:: c
+
+ snprintf(name, 32, "bitstream%d", run->src->sequence);
+
+Dumping the values is simply a matter of reading from the file, i.e.:
+
+For the buffer with sequence == 0:
+
+.. code-block:: bash
+
+ $ xxd /sys/kernel/debug/visl/bitstream/bitstream0
+ 00000000: 2601 af04 d088 bc25 a173 0e41 a4f2 3274 &......%.s.A..2t
+ 00000010: c668 cb28 e775 b4ac f53a ba60 f8fd 3aa1 .h.(.u...:.`..:.
+ 00000020: 46b4 bcfc 506c e227 2372 e5f5 d7ea 579f F...Pl.'#r....W.
+ 00000030: 6371 5eb5 0eb8 23b5 ca6a 5de5 983a 19e4 cq^...#..j]..:..
+ 00000040: e8c3 4320 b4ba a226 cbc1 4138 3a12 32d6 ..C ...&..A8:.2.
+ 00000050: fef3 247b 3523 4e90 9682 ac8e eb0c a389 ..${5#N.........
+ 00000060: ddd0 6cfc 0187 0e20 7aae b15b 1812 3d33 ..l.... z..[..=3
+ 00000070: e1c5 f425 a83a 00b7 4f18 8127 3c4c aefb ...%.:..O..'<L..
+
+For the buffer with sequence == 1:
+
+.. code-block:: bash
+
+ $ xxd /sys/kernel/debug/visl/bitstream/bitstream1
+ 00000000: 0201 d021 49e1 0c40 aa11 1449 14a6 01dc ...!I..@...I....
+ 00000010: 7023 889a c8cd 2cd0 13b4 dab0 e8ca 21fe p#....,.......!.
+ 00000020: c4c8 ab4c 486e 4e2f b0df 96cc c74e 8dde ...LHnN/.....N..
+ 00000030: 8ce7 ee36 d880 4095 4d64 30a0 ff4f 0c5e ...6..@.Md0..O.^
+ 00000040: f16b a6a1 d806 ca2a 0ece a673 7bea 1f37 .k.....*...s{..7
+ 00000050: 370f 5bb9 1dc4 ba21 6434 bc53 0173 cba0 7.[....!d4.S.s..
+ 00000060: dfe6 bc99 01ea b6e0 346b 92b5 c8de 9f5d ........4k.....]
+ 00000070: e7cc 3484 1769 fef2 a693 a945 2c8b 31da ..4..i.....E,.1.
+
+And so on.
+
+By default, the files are removed during STREAMOFF. This is to reduce the amount
+of clutter.
diff --git a/Documentation/admin-guide/media/vivid.rst b/Documentation/admin-guide/media/vivid.rst
index abd90ed31090..672a8371f6ad 100644
--- a/Documentation/admin-guide/media/vivid.rst
+++ b/Documentation/admin-guide/media/vivid.rst
@@ -392,7 +392,7 @@ Which one is returned depends on the chosen channel, each next valid channel
will cycle through the possible audio subchannel combinations. This allows
you to test the various combinations by just switching channels..
-Finally, for these inputs the v4l2_timecode struct is filled in in the
+Finally, for these inputs the v4l2_timecode struct is filled in the
dequeued v4l2_buffer struct.
diff --git a/Documentation/admin-guide/mm/zswap.rst b/Documentation/admin-guide/mm/zswap.rst
index 6e6f7b0d6562..f67de481c7f6 100644
--- a/Documentation/admin-guide/mm/zswap.rst
+++ b/Documentation/admin-guide/mm/zswap.rst
@@ -14,13 +14,7 @@ for potentially reduced swap I/O. This trade-off can also result in a
significant performance improvement if reads from the compressed cache are
faster than reads from a swap device.
-.. note::
- Zswap is a new feature as of v3.11 and interacts heavily with memory
- reclaim. This interaction has not been fully explored on the large set of
- potential configurations and workloads that exist. For this reason, zswap
- is a work in progress and should be considered experimental.
-
- Some potential benefits:
+Some potential benefits:
* Desktop/laptop users with limited RAM capacities can mitigate the
performance impact of swapping.
diff --git a/Documentation/admin-guide/perf/hisi-pcie-pmu.rst b/Documentation/admin-guide/perf/hisi-pcie-pmu.rst
index 294ebbdb22af..7e863662e2d4 100644
--- a/Documentation/admin-guide/perf/hisi-pcie-pmu.rst
+++ b/Documentation/admin-guide/perf/hisi-pcie-pmu.rst
@@ -15,10 +15,10 @@ HiSilicon PCIe PMU driver
The PCIe PMU driver registers a perf PMU with the name of its sicl-id and PCIe
Core id.::
- /sys/bus/event_source/hisi_pcie<sicl>_<core>
+ /sys/bus/event_source/hisi_pcie<sicl>_core<core>
PMU driver provides description of available events and filter options in sysfs,
-see /sys/bus/event_source/devices/hisi_pcie<sicl>_<core>.
+see /sys/bus/event_source/devices/hisi_pcie<sicl>_core<core>.
The "format" directory describes all formats of the config (events) and config1
(filter options) fields of the perf_event_attr structure. The "events" directory
@@ -33,13 +33,13 @@ monitored by PMU.
Example usage of perf::
$# perf list
- hisi_pcie0_0/rx_mwr_latency/ [kernel PMU event]
- hisi_pcie0_0/rx_mwr_cnt/ [kernel PMU event]
+ hisi_pcie0_core0/rx_mwr_latency/ [kernel PMU event]
+ hisi_pcie0_core0/rx_mwr_cnt/ [kernel PMU event]
------------------------------------------
- $# perf stat -e hisi_pcie0_0/rx_mwr_latency/
- $# perf stat -e hisi_pcie0_0/rx_mwr_cnt/
- $# perf stat -g -e hisi_pcie0_0/rx_mwr_latency/ -e hisi_pcie0_0/rx_mwr_cnt/
+ $# perf stat -e hisi_pcie0_core0/rx_mwr_latency/
+ $# perf stat -e hisi_pcie0_core0/rx_mwr_cnt/
+ $# perf stat -g -e hisi_pcie0_core0/rx_mwr_latency/ -e hisi_pcie0_core0/rx_mwr_cnt/
The current driver does not support sampling. So "perf record" is unsupported.
Also attach to a task is unsupported for PCIe PMU.
@@ -48,59 +48,83 @@ Filter options
--------------
1. Target filter
-PMU could only monitor the performance of traffic downstream target Root Ports
-or downstream target Endpoint. PCIe PMU driver support "port" and "bdf"
-interfaces for users, and these two interfaces aren't supported at the same
-time.
--port
-"port" filter can be used in all PCIe PMU events, target Root Port can be
-selected by configuring the 16-bits-bitmap "port". Multi ports can be selected
-for AP-layer-events, and only one port can be selected for TL/DL-layer-events.
+ PMU could only monitor the performance of traffic downstream target Root
+ Ports or downstream target Endpoint. PCIe PMU driver support "port" and
+ "bdf" interfaces for users, and these two interfaces aren't supported at the
+ same time.
-For example, if target Root Port is 0000:00:00.0 (x8 lanes), bit0 of bitmap
-should be set, port=0x1; if target Root Port is 0000:00:04.0 (x4 lanes),
-bit8 is set, port=0x100; if these two Root Ports are both monitored, port=0x101.
+ - port
-Example usage of perf::
+ "port" filter can be used in all PCIe PMU events, target Root Port can be
+ selected by configuring the 16-bits-bitmap "port". Multi ports can be
+ selected for AP-layer-events, and only one port can be selected for
+ TL/DL-layer-events.
- $# perf stat -e hisi_pcie0_0/rx_mwr_latency,port=0x1/ sleep 5
+ For example, if target Root Port is 0000:00:00.0 (x8 lanes), bit0 of
+ bitmap should be set, port=0x1; if target Root Port is 0000:00:04.0 (x4
+ lanes), bit8 is set, port=0x100; if these two Root Ports are both
+ monitored, port=0x101.
--bdf
+ Example usage of perf::
-"bdf" filter can only be used in bandwidth events, target Endpoint is selected
-by configuring BDF to "bdf". Counter only counts the bandwidth of message
-requested by target Endpoint.
+ $# perf stat -e hisi_pcie0_core0/rx_mwr_latency,port=0x1/ sleep 5
-For example, "bdf=0x3900" means BDF of target Endpoint is 0000:39:00.0.
+ - bdf
-Example usage of perf::
+ "bdf" filter can only be used in bandwidth events, target Endpoint is
+ selected by configuring BDF to "bdf". Counter only counts the bandwidth of
+ message requested by target Endpoint.
+
+ For example, "bdf=0x3900" means BDF of target Endpoint is 0000:39:00.0.
+
+ Example usage of perf::
- $# perf stat -e hisi_pcie0_0/rx_mrd_flux,bdf=0x3900/ sleep 5
+ $# perf stat -e hisi_pcie0_core0/rx_mrd_flux,bdf=0x3900/ sleep 5
2. Trigger filter
-Event statistics start when the first time TLP length is greater/smaller
-than trigger condition. You can set the trigger condition by writing "trig_len",
-and set the trigger mode by writing "trig_mode". This filter can only be used
-in bandwidth events.
-For example, "trig_len=4" means trigger condition is 2^4 DW, "trig_mode=0"
-means statistics start when TLP length > trigger condition, "trig_mode=1"
-means start when TLP length < condition.
+ Event statistics start when the first time TLP length is greater/smaller
+ than trigger condition. You can set the trigger condition by writing
+ "trig_len", and set the trigger mode by writing "trig_mode". This filter can
+ only be used in bandwidth events.
-Example usage of perf::
+ For example, "trig_len=4" means trigger condition is 2^4 DW, "trig_mode=0"
+ means statistics start when TLP length > trigger condition, "trig_mode=1"
+ means start when TLP length < condition.
+
+ Example usage of perf::
- $# perf stat -e hisi_pcie0_0/rx_mrd_flux,trig_len=0x4,trig_mode=1/ sleep 5
+ $# perf stat -e hisi_pcie0_core0/rx_mrd_flux,trig_len=0x4,trig_mode=1/ sleep 5
3. Threshold filter
-Counter counts when TLP length within the specified range. You can set the
-threshold by writing "thr_len", and set the threshold mode by writing
-"thr_mode". This filter can only be used in bandwidth events.
-For example, "thr_len=4" means threshold is 2^4 DW, "thr_mode=0" means
-counter counts when TLP length >= threshold, and "thr_mode=1" means counts
-when TLP length < threshold.
+ Counter counts when TLP length within the specified range. You can set the
+ threshold by writing "thr_len", and set the threshold mode by writing
+ "thr_mode". This filter can only be used in bandwidth events.
-Example usage of perf::
+ For example, "thr_len=4" means threshold is 2^4 DW, "thr_mode=0" means
+ counter counts when TLP length >= threshold, and "thr_mode=1" means counts
+ when TLP length < threshold.
+
+ Example usage of perf::
+
+ $# perf stat -e hisi_pcie0_core0/rx_mrd_flux,thr_len=0x4,thr_mode=1/ sleep 5
+
+4. TLP Length filter
+
+ When counting bandwidth, the data can be composed of certain parts of TLP
+ packets. You can specify it through "len_mode":
+
+ - 2'b00: Reserved (Do not use this since the behaviour is undefined)
+ - 2'b01: Bandwidth of TLP payloads
+ - 2'b10: Bandwidth of TLP headers
+ - 2'b11: Bandwidth of both TLP payloads and headers
+
+ For example, "len_mode=2" means only counting the bandwidth of TLP headers
+ and "len_mode=3" means the final bandwidth data is composed of both TLP
+ headers and payloads. Default value if not specified is 2'b11.
+
+ Example usage of perf::
- $# perf stat -e hisi_pcie0_0/rx_mrd_flux,thr_len=0x4,thr_mode=1/ sleep 5
+ $# perf stat -e hisi_pcie0_core0/rx_mrd_flux,len_mode=0x1/ sleep 5
diff --git a/Documentation/admin-guide/perf/index.rst b/Documentation/admin-guide/perf/index.rst
index 793e1970bc05..9de64a40adab 100644
--- a/Documentation/admin-guide/perf/index.rst
+++ b/Documentation/admin-guide/perf/index.rst
@@ -19,3 +19,5 @@ Performance monitor support
arm_dsu_pmu
thunderx2-pmu
alibaba_pmu
+ nvidia-pmu
+ meson-ddr-pmu
diff --git a/Documentation/admin-guide/perf/meson-ddr-pmu.rst b/Documentation/admin-guide/perf/meson-ddr-pmu.rst
new file mode 100644
index 000000000000..8e71be1d6346
--- /dev/null
+++ b/Documentation/admin-guide/perf/meson-ddr-pmu.rst
@@ -0,0 +1,70 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===========================================================
+Amlogic SoC DDR Bandwidth Performance Monitoring Unit (PMU)
+===========================================================
+
+The Amlogic Meson G12 SoC contains a bandwidth monitor inside DRAM controller.
+The monitor includes 4 channels. Each channel can count the request accessing
+DRAM. The channel can count up to 3 AXI port simultaneously. It can be helpful
+to show if the performance bottleneck is on DDR bandwidth.
+
+Currently, this driver supports the following 5 perf events:
+
++ meson_ddr_bw/total_rw_bytes/
++ meson_ddr_bw/chan_1_rw_bytes/
++ meson_ddr_bw/chan_2_rw_bytes/
++ meson_ddr_bw/chan_3_rw_bytes/
++ meson_ddr_bw/chan_4_rw_bytes/
+
+meson_ddr_bw/chan_{1,2,3,4}_rw_bytes/ events are channel-specific events.
+Each channel support filtering, which can let the channel to monitor
+individual IP module in SoC.
+
+Below are DDR access request event filter keywords:
+
++ arm - from CPU
++ vpu_read1 - from OSD + VPP read
++ gpu - from 3D GPU
++ pcie - from PCIe controller
++ hdcp - from HDCP controller
++ hevc_front - from HEVC codec front end
++ usb3_0 - from USB3.0 controller
++ hevc_back - from HEVC codec back end
++ h265enc - from HEVC encoder
++ vpu_read2 - from DI read
++ vpu_write1 - from VDIN write
++ vpu_write2 - from di write
++ vdec - from legacy codec video decoder
++ hcodec - from H264 encoder
++ ge2d - from ge2d
++ spicc1 - from SPI controller 1
++ usb0 - from USB2.0 controller 0
++ dma - from system DMA controller 1
++ arb0 - from arb0
++ sd_emmc_b - from SD eMMC b controller
++ usb1 - from USB2.0 controller 1
++ audio - from Audio module
++ sd_emmc_c - from SD eMMC c controller
++ spicc2 - from SPI controller 2
++ ethernet - from Ethernet controller
+
+
+Examples:
+
+ + Show the total DDR bandwidth per seconds:
+
+ .. code-block:: bash
+
+ perf stat -a -e meson_ddr_bw/total_rw_bytes/ -I 1000 sleep 10
+
+
+ + Show individual DDR bandwidth from CPU and GPU respectively, as well as
+ sum of them:
+
+ .. code-block:: bash
+
+ perf stat -a -e meson_ddr_bw/chan_1_rw_bytes,arm=1/ -I 1000 sleep 10
+ perf stat -a -e meson_ddr_bw/chan_2_rw_bytes,gpu=1/ -I 1000 sleep 10
+ perf stat -a -e meson_ddr_bw/chan_3_rw_bytes,arm=1,gpu=1/ -I 1000 sleep 10
+
diff --git a/Documentation/admin-guide/perf/nvidia-pmu.rst b/Documentation/admin-guide/perf/nvidia-pmu.rst
new file mode 100644
index 000000000000..2e0d47cfe7ea
--- /dev/null
+++ b/Documentation/admin-guide/perf/nvidia-pmu.rst
@@ -0,0 +1,299 @@
+=========================================================
+NVIDIA Tegra SoC Uncore Performance Monitoring Unit (PMU)
+=========================================================
+
+The NVIDIA Tegra SoC includes various system PMUs to measure key performance
+metrics like memory bandwidth, latency, and utilization:
+
+* Scalable Coherency Fabric (SCF)
+* NVLink-C2C0
+* NVLink-C2C1
+* CNVLink
+* PCIE
+
+PMU Driver
+----------
+
+The PMUs in this document are based on ARM CoreSight PMU Architecture as
+described in document: ARM IHI 0091. Since this is a standard architecture, the
+PMUs are managed by a common driver "arm-cs-arch-pmu". This driver describes
+the available events and configuration of each PMU in sysfs. Please see the
+sections below to get the sysfs path of each PMU. Like other uncore PMU drivers,
+the driver provides "cpumask" sysfs attribute to show the CPU id used to handle
+the PMU event. There is also "associated_cpus" sysfs attribute, which contains a
+list of CPUs associated with the PMU instance.
+
+.. _SCF_PMU_Section:
+
+SCF PMU
+-------
+
+The SCF PMU monitors system level cache events, CPU traffic, and
+strongly-ordered (SO) PCIE write traffic to local/remote memory. Please see
+:ref:`NVIDIA_Uncore_PMU_Traffic_Coverage_Section` for more info about the PMU
+traffic coverage.
+
+The events and configuration options of this PMU device are described in sysfs,
+see /sys/bus/event_sources/devices/nvidia_scf_pmu_<socket-id>.
+
+Example usage:
+
+* Count event id 0x0 in socket 0::
+
+ perf stat -a -e nvidia_scf_pmu_0/event=0x0/
+
+* Count event id 0x0 in socket 1::
+
+ perf stat -a -e nvidia_scf_pmu_1/event=0x0/
+
+NVLink-C2C0 PMU
+--------------------
+
+The NVLink-C2C0 PMU monitors incoming traffic from a GPU/CPU connected with
+NVLink-C2C (Chip-2-Chip) interconnect. The type of traffic captured by this PMU
+varies dependent on the chip configuration:
+
+* NVIDIA Grace Hopper Superchip: Hopper GPU is connected with Grace SoC.
+
+ In this config, the PMU captures GPU ATS translated or EGM traffic from the GPU.
+
+* NVIDIA Grace CPU Superchip: two Grace CPU SoCs are connected.
+
+ In this config, the PMU captures read and relaxed ordered (RO) writes from
+ PCIE device of the remote SoC.
+
+Please see :ref:`NVIDIA_Uncore_PMU_Traffic_Coverage_Section` for more info about
+the PMU traffic coverage.
+
+The events and configuration options of this PMU device are described in sysfs,
+see /sys/bus/event_sources/devices/nvidia_nvlink_c2c0_pmu_<socket-id>.
+
+Example usage:
+
+* Count event id 0x0 from the GPU/CPU connected with socket 0::
+
+ perf stat -a -e nvidia_nvlink_c2c0_pmu_0/event=0x0/
+
+* Count event id 0x0 from the GPU/CPU connected with socket 1::
+
+ perf stat -a -e nvidia_nvlink_c2c0_pmu_1/event=0x0/
+
+* Count event id 0x0 from the GPU/CPU connected with socket 2::
+
+ perf stat -a -e nvidia_nvlink_c2c0_pmu_2/event=0x0/
+
+* Count event id 0x0 from the GPU/CPU connected with socket 3::
+
+ perf stat -a -e nvidia_nvlink_c2c0_pmu_3/event=0x0/
+
+NVLink-C2C1 PMU
+-------------------
+
+The NVLink-C2C1 PMU monitors incoming traffic from a GPU connected with
+NVLink-C2C (Chip-2-Chip) interconnect. This PMU captures untranslated GPU
+traffic, in contrast with NvLink-C2C0 PMU that captures ATS translated traffic.
+Please see :ref:`NVIDIA_Uncore_PMU_Traffic_Coverage_Section` for more info about
+the PMU traffic coverage.
+
+The events and configuration options of this PMU device are described in sysfs,
+see /sys/bus/event_sources/devices/nvidia_nvlink_c2c1_pmu_<socket-id>.
+
+Example usage:
+
+* Count event id 0x0 from the GPU connected with socket 0::
+
+ perf stat -a -e nvidia_nvlink_c2c1_pmu_0/event=0x0/
+
+* Count event id 0x0 from the GPU connected with socket 1::
+
+ perf stat -a -e nvidia_nvlink_c2c1_pmu_1/event=0x0/
+
+* Count event id 0x0 from the GPU connected with socket 2::
+
+ perf stat -a -e nvidia_nvlink_c2c1_pmu_2/event=0x0/
+
+* Count event id 0x0 from the GPU connected with socket 3::
+
+ perf stat -a -e nvidia_nvlink_c2c1_pmu_3/event=0x0/
+
+CNVLink PMU
+---------------
+
+The CNVLink PMU monitors traffic from GPU and PCIE device on remote sockets
+to local memory. For PCIE traffic, this PMU captures read and relaxed ordered
+(RO) write traffic. Please see :ref:`NVIDIA_Uncore_PMU_Traffic_Coverage_Section`
+for more info about the PMU traffic coverage.
+
+The events and configuration options of this PMU device are described in sysfs,
+see /sys/bus/event_sources/devices/nvidia_cnvlink_pmu_<socket-id>.
+
+Each SoC socket can be connected to one or more sockets via CNVLink. The user can
+use "rem_socket" bitmap parameter to select the remote socket(s) to monitor.
+Each bit represents the socket number, e.g. "rem_socket=0xE" corresponds to
+socket 1 to 3.
+/sys/bus/event_sources/devices/nvidia_cnvlink_pmu_<socket-id>/format/rem_socket
+shows the valid bits that can be set in the "rem_socket" parameter.
+
+The PMU can not distinguish the remote traffic initiator, therefore it does not
+provide filter to select the traffic source to monitor. It reports combined
+traffic from remote GPU and PCIE devices.
+
+Example usage:
+
+* Count event id 0x0 for the traffic from remote socket 1, 2, and 3 to socket 0::
+
+ perf stat -a -e nvidia_cnvlink_pmu_0/event=0x0,rem_socket=0xE/
+
+* Count event id 0x0 for the traffic from remote socket 0, 2, and 3 to socket 1::
+
+ perf stat -a -e nvidia_cnvlink_pmu_1/event=0x0,rem_socket=0xD/
+
+* Count event id 0x0 for the traffic from remote socket 0, 1, and 3 to socket 2::
+
+ perf stat -a -e nvidia_cnvlink_pmu_2/event=0x0,rem_socket=0xB/
+
+* Count event id 0x0 for the traffic from remote socket 0, 1, and 2 to socket 3::
+
+ perf stat -a -e nvidia_cnvlink_pmu_3/event=0x0,rem_socket=0x7/
+
+
+PCIE PMU
+------------
+
+The PCIE PMU monitors all read/write traffic from PCIE root ports to
+local/remote memory. Please see :ref:`NVIDIA_Uncore_PMU_Traffic_Coverage_Section`
+for more info about the PMU traffic coverage.
+
+The events and configuration options of this PMU device are described in sysfs,
+see /sys/bus/event_sources/devices/nvidia_pcie_pmu_<socket-id>.
+
+Each SoC socket can support multiple root ports. The user can use
+"root_port" bitmap parameter to select the port(s) to monitor, i.e.
+"root_port=0xF" corresponds to root port 0 to 3.
+/sys/bus/event_sources/devices/nvidia_pcie_pmu_<socket-id>/format/root_port
+shows the valid bits that can be set in the "root_port" parameter.
+
+Example usage:
+
+* Count event id 0x0 from root port 0 and 1 of socket 0::
+
+ perf stat -a -e nvidia_pcie_pmu_0/event=0x0,root_port=0x3/
+
+* Count event id 0x0 from root port 0 and 1 of socket 1::
+
+ perf stat -a -e nvidia_pcie_pmu_1/event=0x0,root_port=0x3/
+
+.. _NVIDIA_Uncore_PMU_Traffic_Coverage_Section:
+
+Traffic Coverage
+----------------
+
+The PMU traffic coverage may vary dependent on the chip configuration:
+
+* **NVIDIA Grace Hopper Superchip**: Hopper GPU is connected with Grace SoC.
+
+ Example configuration with two Grace SoCs::
+
+ ********************************* *********************************
+ * SOCKET-A * * SOCKET-B *
+ * * * *
+ * :::::::: * * :::::::: *
+ * : PCIE : * * : PCIE : *
+ * :::::::: * * :::::::: *
+ * | * * | *
+ * | * * | *
+ * ::::::: ::::::::: * * ::::::::: ::::::: *
+ * : : : : * * : : : : *
+ * : GPU :<--NVLink-->: Grace :<---CNVLink--->: Grace :<--NVLink-->: GPU : *
+ * : : C2C : SoC : * * : SoC : C2C : : *
+ * ::::::: ::::::::: * * ::::::::: ::::::: *
+ * | | * * | | *
+ * | | * * | | *
+ * &&&&&&&& &&&&&&&& * * &&&&&&&& &&&&&&&& *
+ * & GMEM & & CMEM & * * & CMEM & & GMEM & *
+ * &&&&&&&& &&&&&&&& * * &&&&&&&& &&&&&&&& *
+ * * * *
+ ********************************* *********************************
+
+ GMEM = GPU Memory (e.g. HBM)
+ CMEM = CPU Memory (e.g. LPDDR5X)
+
+ |
+ | Following table contains traffic coverage of Grace SoC PMU in socket-A:
+
+ ::
+
+ +--------------+-------+-----------+-----------+-----+----------+----------+
+ | | Source |
+ + +-------+-----------+-----------+-----+----------+----------+
+ | Destination | |GPU ATS |GPU Not-ATS| | Socket-B | Socket-B |
+ | |PCI R/W|Translated,|Translated | CPU | CPU/PCIE1| GPU/PCIE2|
+ | | |EGM | | | | |
+ +==============+=======+===========+===========+=====+==========+==========+
+ | Local | PCIE |NVLink-C2C0|NVLink-C2C1| SCF | SCF PMU | CNVLink |
+ | SYSRAM/CMEM | PMU |PMU |PMU | PMU | | PMU |
+ +--------------+-------+-----------+-----------+-----+----------+----------+
+ | Local GMEM | PCIE | N/A |NVLink-C2C1| SCF | SCF PMU | CNVLink |
+ | | PMU | |PMU | PMU | | PMU |
+ +--------------+-------+-----------+-----------+-----+----------+----------+
+ | Remote | PCIE |NVLink-C2C0|NVLink-C2C1| SCF | | |
+ | SYSRAM/CMEM | PMU |PMU |PMU | PMU | N/A | N/A |
+ | over CNVLink | | | | | | |
+ +--------------+-------+-----------+-----------+-----+----------+----------+
+ | Remote GMEM | PCIE |NVLink-C2C0|NVLink-C2C1| SCF | | |
+ | over CNVLink | PMU |PMU |PMU | PMU | N/A | N/A |
+ +--------------+-------+-----------+-----------+-----+----------+----------+
+
+ PCIE1 traffic represents strongly ordered (SO) writes.
+ PCIE2 traffic represents reads and relaxed ordered (RO) writes.
+
+* **NVIDIA Grace CPU Superchip**: two Grace CPU SoCs are connected.
+
+ Example configuration with two Grace SoCs::
+
+ ******************* *******************
+ * SOCKET-A * * SOCKET-B *
+ * * * *
+ * :::::::: * * :::::::: *
+ * : PCIE : * * : PCIE : *
+ * :::::::: * * :::::::: *
+ * | * * | *
+ * | * * | *
+ * ::::::::: * * ::::::::: *
+ * : : * * : : *
+ * : Grace :<--------NVLink------->: Grace : *
+ * : SoC : * C2C * : SoC : *
+ * ::::::::: * * ::::::::: *
+ * | * * | *
+ * | * * | *
+ * &&&&&&&& * * &&&&&&&& *
+ * & CMEM & * * & CMEM & *
+ * &&&&&&&& * * &&&&&&&& *
+ * * * *
+ ******************* *******************
+
+ GMEM = GPU Memory (e.g. HBM)
+ CMEM = CPU Memory (e.g. LPDDR5X)
+
+ |
+ | Following table contains traffic coverage of Grace SoC PMU in socket-A:
+
+ ::
+
+ +-----------------+-----------+---------+----------+-------------+
+ | | Source |
+ + +-----------+---------+----------+-------------+
+ | Destination | | | Socket-B | Socket-B |
+ | | PCI R/W | CPU | CPU/PCIE1| PCIE2 |
+ | | | | | |
+ +=================+===========+=========+==========+=============+
+ | Local | PCIE PMU | SCF PMU | SCF PMU | NVLink-C2C0 |
+ | SYSRAM/CMEM | | | | PMU |
+ +-----------------+-----------+---------+----------+-------------+
+ | Remote | | | | |
+ | SYSRAM/CMEM | PCIE PMU | SCF PMU | N/A | N/A |
+ | over NVLink-C2C | | | | |
+ +-----------------+-----------+---------+----------+-------------+
+
+ PCIE1 traffic represents strongly ordered (SO) writes.
+ PCIE2 traffic represents reads and relaxed ordered (RO) writes.
diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst
index 06e23538f79c..5376d53faaa8 100644
--- a/Documentation/admin-guide/pm/amd-pstate.rst
+++ b/Documentation/admin-guide/pm/amd-pstate.rst
@@ -405,37 +405,55 @@ Unit Tests for amd-pstate
1. Test case decriptions
+ 1). Basic tests
+
+ Test prerequisite and basic functions for the ``amd-pstate`` driver.
+
+---------+--------------------------------+------------------------------------------------------------------------------------+
| Index | Functions | Description |
+=========+================================+====================================================================================+
- | 0 | amd_pstate_ut_acpi_cpc_valid || Check whether the _CPC object is present in SBIOS. |
+ | 1 | amd_pstate_ut_acpi_cpc_valid || Check whether the _CPC object is present in SBIOS. |
| | || |
| | || The detail refer to `Processor Support <processor_support_>`_. |
+---------+--------------------------------+------------------------------------------------------------------------------------+
- | 1 | amd_pstate_ut_check_enabled || Check whether AMD P-State is enabled. |
+ | 2 | amd_pstate_ut_check_enabled || Check whether AMD P-State is enabled. |
| | || |
| | || AMD P-States and ACPI hardware P-States always can be supported in one processor. |
| | | But AMD P-States has the higher priority and if it is enabled with |
| | | :c:macro:`MSR_AMD_CPPC_ENABLE` or ``cppc_set_enable``, it will respond to the |
| | | request from AMD P-States. |
+---------+--------------------------------+------------------------------------------------------------------------------------+
- | 2 | amd_pstate_ut_check_perf || Check if the each performance values are reasonable. |
+ | 3 | amd_pstate_ut_check_perf || Check if the each performance values are reasonable. |
| | || highest_perf >= nominal_perf > lowest_nonlinear_perf > lowest_perf > 0. |
+---------+--------------------------------+------------------------------------------------------------------------------------+
- | 3 | amd_pstate_ut_check_freq || Check if the each frequency values and max freq when set support boost mode |
+ | 4 | amd_pstate_ut_check_freq || Check if the each frequency values and max freq when set support boost mode |
| | | are reasonable. |
| | || max_freq >= nominal_freq > lowest_nonlinear_freq > min_freq > 0 |
| | || If boost is not active but supported, this maximum frequency will be larger than |
| | | the one in ``cpuinfo``. |
+---------+--------------------------------+------------------------------------------------------------------------------------+
+ 2). Tbench test
+
+ Test and monitor the cpu changes when running tbench benchmark under the specified governor.
+ These changes include desire performance, frequency, load, performance, energy etc.
+ The specified governor is ondemand or schedutil.
+ Tbench can also be tested on the ``acpi-cpufreq`` kernel driver for comparison.
+
+ 3). Gitsource test
+
+ Test and monitor the cpu changes when running gitsource benchmark under the specified governor.
+ These changes include desire performance, frequency, load, time, energy etc.
+ The specified governor is ondemand or schedutil.
+ Gitsource can also be tested on the ``acpi-cpufreq`` kernel driver for comparison.
+
#. How to execute the tests
We use test module in the kselftest frameworks to implement it.
- We create amd-pstate-ut module and tie it into kselftest.(for
+ We create ``amd-pstate-ut`` module and tie it into kselftest.(for
details refer to Linux Kernel Selftests [4]_).
- 1. Build
+ 1). Build
+ open the :c:macro:`CONFIG_X86_AMD_PSTATE` configuration option.
+ set the :c:macro:`CONFIG_X86_AMD_PSTATE_UT` configuration option to M.
@@ -445,23 +463,159 @@ Unit Tests for amd-pstate
$ cd linux
$ make -C tools/testing/selftests
- #. Installation & Steps ::
+ + make perf ::
+
+ $ cd tools/perf/
+ $ make
+
+
+ 2). Installation & Steps ::
$ make -C tools/testing/selftests install INSTALL_PATH=~/kselftest
+ $ cp tools/perf/perf /usr/bin/perf
$ sudo ./kselftest/run_kselftest.sh -c amd-pstate
- TAP version 13
- 1..1
- # selftests: amd-pstate: amd-pstate-ut.sh
- # amd-pstate-ut: ok
- ok 1 selftests: amd-pstate: amd-pstate-ut.sh
-
- #. Results ::
-
- $ dmesg | grep "amd_pstate_ut" | tee log.txt
- [12977.570663] amd_pstate_ut: 1 amd_pstate_ut_acpi_cpc_valid success!
- [12977.570673] amd_pstate_ut: 2 amd_pstate_ut_check_enabled success!
- [12977.571207] amd_pstate_ut: 3 amd_pstate_ut_check_perf success!
- [12977.571212] amd_pstate_ut: 4 amd_pstate_ut_check_freq success!
+
+ 3). Specified test case ::
+
+ $ cd ~/kselftest/amd-pstate
+ $ sudo ./run.sh -t basic
+ $ sudo ./run.sh -t tbench
+ $ sudo ./run.sh -t tbench -m acpi-cpufreq
+ $ sudo ./run.sh -t gitsource
+ $ sudo ./run.sh -t gitsource -m acpi-cpufreq
+ $ ./run.sh --help
+ ./run.sh: illegal option -- -
+ Usage: ./run.sh [OPTION...]
+ [-h <help>]
+ [-o <output-file-for-dump>]
+ [-c <all: All testing,
+ basic: Basic testing,
+ tbench: Tbench testing,
+ gitsource: Gitsource testing.>]
+ [-t <tbench time limit>]
+ [-p <tbench process number>]
+ [-l <loop times for tbench>]
+ [-i <amd tracer interval>]
+ [-m <comparative test: acpi-cpufreq>]
+
+
+ 4). Results
+
+ + basic
+
+ When you finish test, you will get the following log info ::
+
+ $ dmesg | grep "amd_pstate_ut" | tee log.txt
+ [12977.570663] amd_pstate_ut: 1 amd_pstate_ut_acpi_cpc_valid success!
+ [12977.570673] amd_pstate_ut: 2 amd_pstate_ut_check_enabled success!
+ [12977.571207] amd_pstate_ut: 3 amd_pstate_ut_check_perf success!
+ [12977.571212] amd_pstate_ut: 4 amd_pstate_ut_check_freq success!
+
+ + tbench
+
+ When you finish test, you will get selftest.tbench.csv and png images.
+ The selftest.tbench.csv file contains the raw data and the drop of the comparative test.
+ The png images shows the performance, energy and performan per watt of each test.
+ Open selftest.tbench.csv :
+
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + Governor | Round | Des-perf | Freq | Load | Performance | Energy | Performance Per Watt |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + Unit | | | GHz | | MB/s | J | MB/J |
+ +=================================================+==============+==========+=========+==========+=============+=========+======================+
+ + amd-pstate-ondemand | 1 | | | | 2504.05 | 1563.67 | 158.5378 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + amd-pstate-ondemand | 2 | | | | 2243.64 | 1430.32 | 155.2941 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + amd-pstate-ondemand | 3 | | | | 2183.88 | 1401.32 | 154.2860 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + amd-pstate-ondemand | Average | | | | 2310.52 | 1465.1 | 156.1268 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + amd-pstate-schedutil | 1 | 165.329 | 1.62257 | 99.798 | 2136.54 | 1395.26 | 151.5971 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + amd-pstate-schedutil | 2 | 166 | 1.49761 | 99.9993 | 2100.56 | 1380.5 | 150.6377 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + amd-pstate-schedutil | 3 | 166 | 1.47806 | 99.9993 | 2084.12 | 1375.76 | 149.9737 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + amd-pstate-schedutil | Average | 165.776 | 1.53275 | 99.9322 | 2107.07 | 1383.84 | 150.7399 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-ondemand | 1 | | | | 2529.9 | 1564.4 | 160.0997 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-ondemand | 2 | | | | 2249.76 | 1432.97 | 155.4297 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-ondemand | 3 | | | | 2181.46 | 1406.88 | 153.5060 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-ondemand | Average | | | | 2320.37 | 1468.08 | 156.4741 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-schedutil | 1 | | | | 2137.64 | 1385.24 | 152.7723 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-schedutil | 2 | | | | 2107.05 | 1372.23 | 152.0138 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-schedutil | 3 | | | | 2085.86 | 1365.35 | 151.2433 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-schedutil | Average | | | | 2110.18 | 1374.27 | 152.0136 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-ondemand VS acpi-cpufreq-schedutil | Comprison(%) | | | | -9.0584 | -6.3899 | -2.8506 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + amd-pstate-ondemand VS amd-pstate-schedutil | Comprison(%) | | | | 8.8053 | -5.5463 | -3.4503 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-ondemand VS amd-pstate-ondemand | Comprison(%) | | | | -0.4245 | -0.2029 | -0.2219 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-schedutil VS amd-pstate-schedutil | Comprison(%) | | | | -0.1473 | 0.6963 | -0.8378 |
+ +-------------------------------------------------+--------------+----------+---------+----------+-------------+---------+----------------------+
+
+ + gitsource
+
+ When you finish test, you will get selftest.gitsource.csv and png images.
+ The selftest.gitsource.csv file contains the raw data and the drop of the comparative test.
+ The png images shows the performance, energy and performan per watt of each test.
+ Open selftest.gitsource.csv :
+
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + Governor | Round | Des-perf | Freq | Load | Time | Energy | Performance Per Watt |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + Unit | | | GHz | | s | J | 1/J |
+ +=================================================+==============+==========+==========+==========+=============+=========+======================+
+ + amd-pstate-ondemand | 1 | 50.119 | 2.10509 | 23.3076 | 475.69 | 865.78 | 0.001155027 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + amd-pstate-ondemand | 2 | 94.8006 | 1.98771 | 56.6533 | 467.1 | 839.67 | 0.001190944 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + amd-pstate-ondemand | 3 | 76.6091 | 2.53251 | 43.7791 | 467.69 | 855.85 | 0.001168429 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + amd-pstate-ondemand | Average | 73.8429 | 2.20844 | 41.2467 | 470.16 | 853.767 | 0.001171279 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + amd-pstate-schedutil | 1 | 165.919 | 1.62319 | 98.3868 | 464.17 | 866.8 | 0.001153668 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + amd-pstate-schedutil | 2 | 165.97 | 1.31309 | 99.5712 | 480.15 | 880.4 | 0.001135847 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + amd-pstate-schedutil | 3 | 165.973 | 1.28448 | 99.9252 | 481.79 | 867.02 | 0.001153375 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + amd-pstate-schedutil | Average | 165.954 | 1.40692 | 99.2944 | 475.37 | 871.407 | 0.001147569 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-ondemand | 1 | | | | 2379.62 | 742.96 | 0.001345967 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-ondemand | 2 | | | | 441.74 | 817.49 | 0.001223256 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-ondemand | 3 | | | | 455.48 | 820.01 | 0.001219497 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-ondemand | Average | | | | 425.613 | 793.487 | 0.001260260 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-schedutil | 1 | | | | 459.69 | 838.54 | 0.001192548 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-schedutil | 2 | | | | 466.55 | 830.89 | 0.001203528 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-schedutil | 3 | | | | 470.38 | 837.32 | 0.001194286 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-schedutil | Average | | | | 465.54 | 835.583 | 0.001196769 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-ondemand VS acpi-cpufreq-schedutil | Comprison(%) | | | | 9.3810 | 5.3051 | -5.0379 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + amd-pstate-ondemand VS amd-pstate-schedutil | Comprison(%) | 124.7392 | -36.2934 | 140.7329 | 1.1081 | 2.0661 | -2.0242 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-ondemand VS amd-pstate-ondemand | Comprison(%) | | | | 10.4665 | 7.5968 | -7.0605 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
+ + acpi-cpufreq-schedutil VS amd-pstate-schedutil | Comprison(%) | | | | 2.1115 | 4.2873 | -4.1110 |
+ +-------------------------------------------------+--------------+----------+----------+----------+-------------+---------+----------------------+
Reference
===========
diff --git a/Documentation/admin-guide/sysctl/fs.rst b/Documentation/admin-guide/sysctl/fs.rst
index 2a501c9ddc55..a321b84eccaa 100644
--- a/Documentation/admin-guide/sysctl/fs.rst
+++ b/Documentation/admin-guide/sysctl/fs.rst
@@ -2,8 +2,6 @@
Documentation for /proc/sys/fs/
===============================
-kernel version 2.2.10
-
Copyright (c) 1998, 1999, Rik van Riel <riel@nl.linux.org>
Copyright (c) 2009, Shen Feng<shen@cn.fujitsu.com>
@@ -12,58 +10,40 @@ For general info and legal blurb, please look in intro.rst.
------------------------------------------------------------------------------
-This file contains documentation for the sysctl files in
-/proc/sys/fs/ and is valid for Linux kernel version 2.2.
+This file contains documentation for the sysctl files and directories
+in ``/proc/sys/fs/``.
The files in this directory can be used to tune and monitor
miscellaneous and general things in the operation of the Linux
-kernel. Since some of the files _can_ be used to screw up your
+kernel. Since some of the files *can* be used to screw up your
system, it is advisable to read both documentation and source
before actually making adjustments.
1. /proc/sys/fs
===============
-Currently, these files are in /proc/sys/fs:
-
-- aio-max-nr
-- aio-nr
-- dentry-state
-- dquot-max
-- dquot-nr
-- file-max
-- file-nr
-- inode-max
-- inode-nr
-- inode-state
-- nr_open
-- overflowuid
-- overflowgid
-- pipe-user-pages-hard
-- pipe-user-pages-soft
-- protected_fifos
-- protected_hardlinks
-- protected_regular
-- protected_symlinks
-- suid_dumpable
-- super-max
-- super-nr
+Currently, these files might (depending on your configuration)
+show up in ``/proc/sys/fs``:
+
+.. contents:: :local:
aio-nr & aio-max-nr
-------------------
-aio-nr is the running total of the number of events specified on the
-io_setup system call for all currently active aio contexts. If aio-nr
-reaches aio-max-nr then io_setup will fail with EAGAIN. Note that
-raising aio-max-nr does not result in the pre-allocation or re-sizing
-of any kernel data structures.
+``aio-nr`` shows the current system-wide number of asynchronous io
+requests. ``aio-max-nr`` allows you to change the maximum value
+``aio-nr`` can grow to. If ``aio-nr`` reaches ``aio-nr-max`` then
+``io_setup`` will fail with ``EAGAIN``. Note that raising
+``aio-max-nr`` does not result in the
+pre-allocation or re-sizing of any kernel data structures.
dentry-state
------------
-From linux/include/linux/dcache.h::
+This file shows the values in ``struct dentry_stat``, as defined in
+``linux/include/linux/dcache.h``::
struct dentry_stat_t dentry_stat {
int nr_dentry;
@@ -76,95 +56,84 @@ From linux/include/linux/dcache.h::
Dentries are dynamically allocated and deallocated.
-nr_dentry shows the total number of dentries allocated (active
-+ unused). nr_unused shows the number of dentries that are not
+``nr_dentry`` shows the total number of dentries allocated (active
++ unused). ``nr_unused shows`` the number of dentries that are not
actively used, but are saved in the LRU list for future reuse.
-Age_limit is the age in seconds after which dcache entries
-can be reclaimed when memory is short and want_pages is
-nonzero when shrink_dcache_pages() has been called and the
+``age_limit`` is the age in seconds after which dcache entries
+can be reclaimed when memory is short and ``want_pages`` is
+nonzero when ``shrink_dcache_pages()`` has been called and the
dcache isn't pruned yet.
-nr_negative shows the number of unused dentries that are also
+``nr_negative`` shows the number of unused dentries that are also
negative dentries which do not map to any files. Instead,
they help speeding up rejection of non-existing files provided
by the users.
-dquot-max & dquot-nr
---------------------
-
-The file dquot-max shows the maximum number of cached disk
-quota entries.
-
-The file dquot-nr shows the number of allocated disk quota
-entries and the number of free disk quota entries.
-
-If the number of free cached disk quotas is very low and
-you have some awesome number of simultaneous system users,
-you might want to raise the limit.
-
-
file-max & file-nr
------------------
-The value in file-max denotes the maximum number of file-
+The value in ``file-max`` denotes the maximum number of file-
handles that the Linux kernel will allocate. When you get lots
of error messages about running out of file handles, you might
want to increase this limit.
Historically,the kernel was able to allocate file handles
dynamically, but not to free them again. The three values in
-file-nr denote the number of allocated file handles, the number
+``file-nr`` denote the number of allocated file handles, the number
of allocated but unused file handles, and the maximum number of
-file handles. Linux 2.6 always reports 0 as the number of free
+file handles. Linux 2.6 and later always reports 0 as the number of free
file handles -- this is not an error, it just means that the
number of allocated file handles exactly matches the number of
used file handles.
-Attempts to allocate more file descriptors than file-max are
-reported with printk, look for "VFS: file-max limit <number>
-reached".
+Attempts to allocate more file descriptors than ``file-max`` are
+reported with ``printk``, look for::
+ VFS: file-max limit <number> reached
-nr_open
--------
-
-This denotes the maximum number of file-handles a process can
-allocate. Default value is 1024*1024 (1048576) which should be
-enough for most machines. Actual limit depends on RLIMIT_NOFILE
-resource limit.
+in the kernel logs.
-inode-max, inode-nr & inode-state
----------------------------------
+inode-nr & inode-state
+----------------------
As with file handles, the kernel allocates the inode structures
dynamically, but can't free them yet.
-The value in inode-max denotes the maximum number of inode
-handlers. This value should be 3-4 times larger than the value
-in file-max, since stdin, stdout and network sockets also
-need an inode struct to handle them. When you regularly run
-out of inodes, you need to increase this value.
-
-The file inode-nr contains the first two items from
-inode-state, so we'll skip to that file...
+The file ``inode-nr`` contains the first two items from
+``inode-state``, so we'll skip to that file...
-Inode-state contains three actual numbers and four dummies.
-The actual numbers are, in order of appearance, nr_inodes,
-nr_free_inodes and preshrink.
+``inode-state`` contains three actual numbers and four dummies.
+The actual numbers are, in order of appearance, ``nr_inodes``,
+``nr_free_inodes`` and ``preshrink``.
-Nr_inodes stands for the number of inodes the system has
-allocated, this can be slightly more than inode-max because
-Linux allocates them one pageful at a time.
+``nr_inodes`` stands for the number of inodes the system has
+allocated.
-Nr_free_inodes represents the number of free inodes (?) and
-preshrink is nonzero when the nr_inodes > inode-max and the
+``nr_free_inodes`` represents the number of free inodes (?) and
+preshrink is nonzero when the
system needs to prune the inode list instead of allocating
more.
+mount-max
+---------
+
+This denotes the maximum number of mounts that may exist
+in a mount namespace.
+
+
+nr_open
+-------
+
+This denotes the maximum number of file-handles a process can
+allocate. Default value is 1024*1024 (1048576) which should be
+enough for most machines. Actual limit depends on ``RLIMIT_NOFILE``
+resource limit.
+
+
overflowgid & overflowuid
-------------------------
@@ -192,7 +161,7 @@ pipe-user-pages-soft
Maximum total number of pages a non-privileged user may allocate for pipes
before the pipe size gets limited to a single page. Once this limit is reached,
new pipes will be limited to a single page in size for this user in order to
-limit total memory usage, and trying to increase them using fcntl() will be
+limit total memory usage, and trying to increase them using ``fcntl()`` will be
denied until usage goes below the limit again. The default value allows to
allocate up to 1024 pipes at their default size. When set to 0, no limit is
applied.
@@ -207,7 +176,7 @@ file.
When set to "0", writing to FIFOs is unrestricted.
-When set to "1" don't allow O_CREAT open on FIFOs that we don't own
+When set to "1" don't allow ``O_CREAT`` open on FIFOs that we don't own
in world writable sticky directories, unless they are owned by the
owner of the directory.
@@ -221,7 +190,7 @@ protected_hardlinks
A long-standing class of security issues is the hardlink-based
time-of-check-time-of-use race, most commonly seen in world-writable
-directories like /tmp. The common method of exploitation of this flaw
+directories like ``/tmp``. The common method of exploitation of this flaw
is to cross privilege boundaries when following a given hardlink (i.e. a
root process follows a hardlink created by another user). Additionally,
on systems without separated partitions, this stops unauthorized users
@@ -239,13 +208,13 @@ This protection is based on the restrictions in Openwall and grsecurity.
protected_regular
-----------------
-This protection is similar to protected_fifos, but it
+This protection is similar to `protected_fifos`_, but it
avoids writes to an attacker-controlled regular file, where a program
expected to create one.
When set to "0", writing to regular files is unrestricted.
-When set to "1" don't allow O_CREAT open on regular files that we
+When set to "1" don't allow ``O_CREAT`` open on regular files that we
don't own in world writable sticky directories, unless they are
owned by the owner of the directory.
@@ -257,7 +226,7 @@ protected_symlinks
A long-standing class of security issues is the symlink-based
time-of-check-time-of-use race, most commonly seen in world-writable
-directories like /tmp. The common method of exploitation of this flaw
+directories like ``/tmp``. The common method of exploitation of this flaw
is to cross privilege boundaries when following a given symlink (i.e. a
root process follows a symlink belonging to another user). For a likely
incomplete list of hundreds of examples across the years, please see:
@@ -272,23 +241,25 @@ follower match, or when the directory owner matches the symlink's owner.
This protection is based on the restrictions in Openwall and grsecurity.
-suid_dumpable:
---------------
+suid_dumpable
+-------------
This value can be used to query and set the core dump mode for setuid
or otherwise protected/tainted binaries. The modes are
= ========== ===============================================================
-0 (default) traditional behaviour. Any process which has changed
+0 (default) Traditional behaviour. Any process which has changed
privilege levels or is execute only will not be dumped.
-1 (debug) all processes dump core when possible. The core dump is
+1 (debug) All processes dump core when possible. The core dump is
owned by the current user and no security is applied. This is
intended for system debugging situations only.
Ptrace is unchecked.
This is insecure as it allows regular users to examine the
memory contents of privileged processes.
-2 (suidsafe) any binary which normally would not be dumped is dumped
- anyway, but only if the "core_pattern" kernel sysctl is set to
+2 (suidsafe) Any binary which normally would not be dumped is dumped
+ anyway, but only if the ``core_pattern`` kernel sysctl (see
+ :ref:`Documentation/admin-guide/sysctl/kernel.rst <core_pattern>`)
+ is set to
either a pipe handler or a fully qualified path. (For more
details on this limitation, see CVE-2006-2451.) This mode is
appropriate when administrators are attempting to debug
@@ -301,36 +272,11 @@ or otherwise protected/tainted binaries. The modes are
= ========== ===============================================================
-super-max & super-nr
---------------------
-
-These numbers control the maximum number of superblocks, and
-thus the maximum number of mounted filesystems the kernel
-can have. You only need to increase super-max if you need to
-mount more filesystems than the current value in super-max
-allows you to.
-
-
-aio-nr & aio-max-nr
--------------------
-
-aio-nr shows the current system-wide number of asynchronous io
-requests. aio-max-nr allows you to change the maximum value
-aio-nr can grow to.
-
-
-mount-max
----------
-
-This denotes the maximum number of mounts that may exist
-in a mount namespace.
-
-
2. /proc/sys/fs/binfmt_misc
===========================
-Documentation for the files in /proc/sys/fs/binfmt_misc is
+Documentation for the files in ``/proc/sys/fs/binfmt_misc`` is
in Documentation/admin-guide/binfmt-misc.rst.
@@ -343,28 +289,32 @@ creation of a user space library that implements the POSIX message queues
API (as noted by the MSG tag in the POSIX 1003.1-2001 version of the System
Interfaces specification.)
-The "mqueue" filesystem contains values for determining/setting the amount of
-resources used by the file system.
+The "mqueue" filesystem contains values for determining/setting the
+amount of resources used by the file system.
-/proc/sys/fs/mqueue/queues_max is a read/write file for setting/getting the
-maximum number of message queues allowed on the system.
+``/proc/sys/fs/mqueue/queues_max`` is a read/write file for
+setting/getting the maximum number of message queues allowed on the
+system.
-/proc/sys/fs/mqueue/msg_max is a read/write file for setting/getting the
-maximum number of messages in a queue value. In fact it is the limiting value
-for another (user) limit which is set in mq_open invocation. This attribute of
-a queue must be less or equal then msg_max.
+``/proc/sys/fs/mqueue/msg_max`` is a read/write file for
+setting/getting the maximum number of messages in a queue value. In
+fact it is the limiting value for another (user) limit which is set in
+``mq_open`` invocation. This attribute of a queue must be less than
+or equal to ``msg_max``.
-/proc/sys/fs/mqueue/msgsize_max is a read/write file for setting/getting the
-maximum message size value (it is every message queue's attribute set during
-its creation).
+``/proc/sys/fs/mqueue/msgsize_max`` is a read/write file for
+setting/getting the maximum message size value (it is an attribute of
+every message queue, set during its creation).
-/proc/sys/fs/mqueue/msg_default is a read/write file for setting/getting the
-default number of messages in a queue value if attr parameter of mq_open(2) is
-NULL. If it exceed msg_max, the default value is initialized msg_max.
+``/proc/sys/fs/mqueue/msg_default`` is a read/write file for
+setting/getting the default number of messages in a queue value if the
+``attr`` parameter of ``mq_open(2)`` is ``NULL``. If it exceeds
+``msg_max``, the default value is initialized to ``msg_max``.
-/proc/sys/fs/mqueue/msgsize_default is a read/write file for setting/getting
-the default message size value if attr parameter of mq_open(2) is NULL. If it
-exceed msgsize_max, the default value is initialized msgsize_max.
+``/proc/sys/fs/mqueue/msgsize_default`` is a read/write file for
+setting/getting the default message size value if the ``attr``
+parameter of ``mq_open(2)`` is ``NULL``. If it exceeds
+``msgsize_max``, the default value is initialized to ``msgsize_max``.
4. /proc/sys/fs/epoll - Configuration options for the epoll interface
=====================================================================
@@ -378,7 +328,7 @@ Every epoll file descriptor can store a number of files to be monitored
for event readiness. Each one of these monitored files constitutes a "watch".
This configuration option sets the maximum number of "watches" that are
allowed for each user.
-Each "watch" costs roughly 90 bytes on a 32bit kernel, and roughly 160 bytes
-on a 64bit one.
-The current default value for max_user_watches is the 1/25 (4%) of the
-available low memory, divided for the "watch" cost in bytes.
+Each "watch" costs roughly 90 bytes on a 32-bit kernel, and roughly 160 bytes
+on a 64-bit one.
+The current default value for ``max_user_watches`` is 4% of the
+available low memory, divided by the "watch" cost in bytes.
diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst
index 98d1b198b2b4..39e7a2d46e1e 100644
--- a/Documentation/admin-guide/sysctl/kernel.rst
+++ b/Documentation/admin-guide/sysctl/kernel.rst
@@ -139,6 +139,8 @@ Highest valid capability of the running kernel. Exports
``CAP_LAST_CAP`` from the kernel.
+.. _core_pattern:
+
core_pattern
============
@@ -174,6 +176,7 @@ core_pattern
%f executable filename
%E executable path
%c maximum size of core file by resource limit RLIMIT_CORE
+ %C CPU the task ran on
%<OTHER> both are dropped
======== ==========================================
@@ -1314,6 +1317,29 @@ watchdog work to be queued by the watchdog timer function, otherwise the NMI
watchdog — if enabled — can detect a hard lockup condition.
+split_lock_mitigate (x86 only)
+==============================
+
+On x86, each "split lock" imposes a system-wide performance penalty. On larger
+systems, large numbers of split locks from unprivileged users can result in
+denials of service to well-behaved and potentially more important users.
+
+The kernel mitigates these bad users by detecting split locks and imposing
+penalties: forcing them to wait and only allowing one core to execute split
+locks at a time.
+
+These mitigations can make those bad applications unbearably slow. Setting
+split_lock_mitigate=0 may restore some application performance, but will also
+increase system exposure to denial of service attacks from split lock users.
+
+= ===================================================================
+0 Disable the mitigation mode - just warns the split lock on kernel log
+ and exposes the system to denials of service from the split lockers.
+1 Enable the mitigation mode (this is the default) - penalizes the split
+ lockers with intentional performance degradation.
+= ===================================================================
+
+
stack_erasing
=============
diff --git a/Documentation/arm/marvell.rst b/Documentation/arm/marvell.rst
index 370721518987..3d369a566038 100644
--- a/Documentation/arm/marvell.rst
+++ b/Documentation/arm/marvell.rst
@@ -14,18 +14,20 @@ Orion family
Flavors:
- 88F5082
- - 88F5181
- - 88F5181L
- - 88F5182
+ - 88F5181 a.k.a Orion-1
+ - 88F5181L a.k.a Orion-VoIP
+ - 88F5182 a.k.a Orion-NAS
- Datasheet: https://web.archive.org/web/20210124231420/http://csclub.uwaterloo.ca/~board/ts7800/MV88F5182-datasheet.pdf
- Programmer's User Guide: https://web.archive.org/web/20210124231536/http://csclub.uwaterloo.ca/~board/ts7800/MV88F5182-opensource-manual.pdf
- User Manual: https://web.archive.org/web/20210124231631/http://csclub.uwaterloo.ca/~board/ts7800/MV88F5182-usermanual.pdf
- Functional Errata: https://web.archive.org/web/20210704165540/https://www.digriz.org.uk/ts78xx/88F5182_Functional_Errata.pdf
- - 88F5281
+ - 88F5281 a.k.a Orion-2
- Datasheet: https://web.archive.org/web/20131028144728/http://www.ocmodshop.com/images/reviews/networking/qnap_ts409u/marvel_88f5281_data_sheet.pdf
- - 88F6183
+ - 88F6183 a.k.a Orion-1-90
+ Homepage:
+ https://web.archive.org/web/20080607215437/http://www.marvell.com/products/media/index.jsp
Core:
Feroceon 88fr331 (88f51xx) or 88fr531-vd (88f52xx) ARMv5 compatible
Linux kernel mach directory:
diff --git a/Documentation/arm64/acpi_object_usage.rst b/Documentation/arm64/acpi_object_usage.rst
index 0609da73970b..484ef9676653 100644
--- a/Documentation/arm64/acpi_object_usage.rst
+++ b/Documentation/arm64/acpi_object_usage.rst
@@ -163,7 +163,7 @@ FPDT Section 5.2.23 (signature == "FPDT")
**Firmware Performance Data Table**
- Optional, not currently supported.
+ Optional, useful for boot performance profiling.
GTDT Section 5.2.24 (signature == "GTDT")
diff --git a/Documentation/arm64/booting.rst b/Documentation/arm64/booting.rst
index 8c324ad638de..96fe10ec6c24 100644
--- a/Documentation/arm64/booting.rst
+++ b/Documentation/arm64/booting.rst
@@ -121,8 +121,9 @@ Header notes:
to the base of DRAM, since memory below it is not
accessible via the linear mapping
1
- 2MB aligned base may be anywhere in physical
- memory
+ 2MB aligned base such that all image_size bytes
+ counted from the start of the image are within
+ the 48-bit addressable range of physical memory
Bits 4-63 Reserved.
============= ===============================================================
@@ -348,7 +349,7 @@ Before jumping into the kernel, the following conditions must be met:
- HWFGWTR_EL2.nSMPRI_EL1 (bit 54) must be initialised to 0b01.
- For CPUs with the Scalable Matrix Extension FA64 feature (FEAT_SME_FA64)
+ For CPUs with the Scalable Matrix Extension FA64 feature (FEAT_SME_FA64):
- If EL3 is present:
diff --git a/Documentation/arm64/elf_hwcaps.rst b/Documentation/arm64/elf_hwcaps.rst
index bb34287c8e01..6fed84f935df 100644
--- a/Documentation/arm64/elf_hwcaps.rst
+++ b/Documentation/arm64/elf_hwcaps.rst
@@ -275,6 +275,15 @@ HWCAP2_EBF16
HWCAP2_SVE_EBF16
Functionality implied by ID_AA64ZFR0_EL1.BF16 == 0b0010.
+HWCAP2_CSSC
+ Functionality implied by ID_AA64ISAR2_EL1.CSSC == 0b0001.
+
+HWCAP2_RPRFM
+ Functionality implied by ID_AA64ISAR2_EL1.RPRFM == 0b0001.
+
+HWCAP2_SVE2P1
+ Functionality implied by ID_AA64ZFR0_EL1.SVEver == 0b0010.
+
4. Unused AT_HWCAP bits
-----------------------
diff --git a/Documentation/arm64/silicon-errata.rst b/Documentation/arm64/silicon-errata.rst
index 808ade4cc008..ec5f889d7681 100644
--- a/Documentation/arm64/silicon-errata.rst
+++ b/Documentation/arm64/silicon-errata.rst
@@ -120,6 +120,8 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-A710 | #2224489 | ARM64_ERRATUM_2224489 |
+----------------+-----------------+-----------------+-----------------------------+
+| ARM | Cortex-A715 | #2645198 | ARM64_ERRATUM_2645198 |
++----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X2 | #2119858 | ARM64_ERRATUM_2119858 |
+----------------+-----------------+-----------------+-----------------------------+
| ARM | Cortex-X2 | #2224489 | ARM64_ERRATUM_2224489 |
diff --git a/Documentation/arm64/sve.rst b/Documentation/arm64/sve.rst
index f338ee2df46d..c7a356bf4e8f 100644
--- a/Documentation/arm64/sve.rst
+++ b/Documentation/arm64/sve.rst
@@ -52,6 +52,7 @@ model features for SVE is included in Appendix A.
HWCAP2_SVEBITPERM
HWCAP2_SVESHA3
HWCAP2_SVESM4
+ HWCAP2_SVE2P1
This list may be extended over time as the SVE architecture evolves.
diff --git a/Documentation/block/inline-encryption.rst b/Documentation/block/inline-encryption.rst
index 4d151fbe2058..f9bf18ea6509 100644
--- a/Documentation/block/inline-encryption.rst
+++ b/Documentation/block/inline-encryption.rst
@@ -142,7 +142,7 @@ Therefore, we also introduce *blk-crypto-fallback*, which is an implementation
of inline encryption using the kernel crypto API. blk-crypto-fallback is built
into the block layer, so it works on any block device without any special setup.
Essentially, when a bio with an encryption context is submitted to a
-request_queue that doesn't support that encryption context, the block layer will
+block_device that doesn't support that encryption context, the block layer will
handle en/decryption of the bio using blk-crypto-fallback.
For encryption, the data cannot be encrypted in-place, as callers usually rely
@@ -187,7 +187,7 @@ API presented to users of the block layer
``blk_crypto_config_supported()`` allows users to check ahead of time whether
inline encryption with particular crypto settings will work on a particular
-request_queue -- either via hardware or via blk-crypto-fallback. This function
+block_device -- either via hardware or via blk-crypto-fallback. This function
takes in a ``struct blk_crypto_config`` which is like blk_crypto_key, but omits
the actual bytes of the key and instead just contains the algorithm, data unit
size, etc. This function can be useful if blk-crypto-fallback is disabled.
@@ -195,7 +195,7 @@ size, etc. This function can be useful if blk-crypto-fallback is disabled.
``blk_crypto_init_key()`` allows users to initialize a blk_crypto_key.
Users must call ``blk_crypto_start_using_key()`` before actually starting to use
-a blk_crypto_key on a request_queue (even if ``blk_crypto_config_supported()``
+a blk_crypto_key on a block_device (even if ``blk_crypto_config_supported()``
was called earlier). This is needed to initialize blk-crypto-fallback if it
will be needed. This must not be called from the data path, as this may have to
allocate resources, which may deadlock in that case.
@@ -207,7 +207,7 @@ for en/decryption. Users don't need to worry about freeing the bio_crypt_ctx
later, as that happens automatically when the bio is freed or reset.
Finally, when done using inline encryption with a blk_crypto_key on a
-request_queue, users must call ``blk_crypto_evict_key()``. This ensures that
+block_device, users must call ``blk_crypto_evict_key()``. This ensures that
the key is evicted from all keyslots it may be programmed into and unlinked from
any kernel data structures it may be linked into.
@@ -221,9 +221,9 @@ as follows:
5. ``blk_crypto_evict_key()`` (after all I/O has completed)
6. Zeroize the blk_crypto_key (this has no dedicated function)
-If a blk_crypto_key is being used on multiple request_queues, then
+If a blk_crypto_key is being used on multiple block_devices, then
``blk_crypto_config_supported()`` (if used), ``blk_crypto_start_using_key()``,
-and ``blk_crypto_evict_key()`` must be called on each request_queue.
+and ``blk_crypto_evict_key()`` must be called on each block_device.
API presented to device drivers
===============================
diff --git a/Documentation/conf.py b/Documentation/conf.py
index b50c85083149..a5c45df0bd83 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -194,6 +194,24 @@ finally:
else:
version = release = "unknown version"
+#
+# HACK: there seems to be no easy way for us to get at the version and
+# release information passed in from the makefile...so go pawing through the
+# command-line options and find it for ourselves.
+#
+def get_cline_version():
+ c_version = c_release = ''
+ for arg in sys.argv:
+ if arg.startswith('version='):
+ c_version = arg[8:]
+ elif arg.startswith('release='):
+ c_release = arg[8:]
+ if c_version:
+ if c_release:
+ return c_version + '-' + c_release
+ return c_version
+ return version # Whatever we came up with before
+
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
@@ -247,7 +265,7 @@ highlight_language = 'none'
# a list of builtin themes.
# Default theme
-html_theme = 'sphinx_rtd_theme'
+html_theme = 'alabaster'
html_css_files = []
if "DOCS_THEME" in os.environ:
@@ -278,8 +296,12 @@ if html_theme == 'sphinx_rtd_theme' or html_theme == 'sphinx_rtd_dark_mode':
# Add color-specific RTD normal mode
html_css_files.append('theme_rtd_colors.css')
+ html_theme_options = {
+ 'navigation_depth': -1,
+ }
+
except ImportError:
- html_theme = 'classic'
+ html_theme = 'alabaster'
if "DOCS_CSS" in os.environ:
css = os.environ["DOCS_CSS"].split(" ")
@@ -295,127 +317,29 @@ if major <= 1 and minor < 8:
for l in html_css_files:
html_context['css_files'].append('_static/' + l)
-if html_theme == 'classic':
+if html_theme == 'alabaster':
html_theme_options = {
- 'rightsidebar': False,
- 'stickysidebar': True,
- 'collapsiblesidebar': True,
- 'externalrefs': False,
-
- 'footerbgcolor': "white",
- 'footertextcolor': "white",
- 'sidebarbgcolor': "white",
- 'sidebarbtncolor': "black",
- 'sidebartextcolor': "black",
- 'sidebarlinkcolor': "#686bff",
- 'relbarbgcolor': "#133f52",
- 'relbartextcolor': "white",
- 'relbarlinkcolor': "white",
- 'bgcolor': "white",
- 'textcolor': "black",
- 'headbgcolor': "#f2f2f2",
- 'headtextcolor': "#20435c",
- 'headlinkcolor': "#c60f0f",
- 'linkcolor': "#355f7c",
- 'visitedlinkcolor': "#355f7c",
- 'codebgcolor': "#3f3f3f",
- 'codetextcolor': "white",
-
- 'bodyfont': "serif",
- 'headfont': "sans-serif",
+ 'description': get_cline_version(),
+ 'page_width': '65em',
+ 'sidebar_width': '15em',
+ 'font_size': 'inherit',
+ 'font_family': 'serif',
}
sys.stderr.write("Using %s theme\n" % html_theme)
-# Theme options are theme-specific and customize the look and feel of a theme
-# further. For a list of options available for each theme, see the
-# documentation.
-#html_theme_options = {}
-
-# Add any paths that contain custom themes here, relative to this directory.
-#html_theme_path = []
-
-# The name for this set of Sphinx documents. If None, it defaults to
-# "<project> v<release> documentation".
-#html_title = None
-
-# A shorter title for the navigation bar. Default is the same as html_title.
-#html_short_title = None
-
-# The name of an image file (relative to this directory) to place at the top
-# of the sidebar.
-#html_logo = None
-
-# The name of an image file (within the static path) to use as favicon of the
-# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
-# pixels large.
-#html_favicon = None
-
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['sphinx-static']
-# Add any extra paths that contain custom files (such as robots.txt or
-# .htaccess) here, relative to this directory. These files are copied
-# directly to the root of the documentation.
-#html_extra_path = []
-
-# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-# using the given strftime format.
-#html_last_updated_fmt = '%b %d, %Y'
-
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
html_use_smartypants = False
# Custom sidebar templates, maps document names to template names.
-# Note that the RTD theme ignores this.
-html_sidebars = { '**': ['searchbox.html', 'localtoc.html', 'sourcelink.html']}
-
-# Additional templates that should be rendered to pages, maps page names to
-# template names.
-#html_additional_pages = {}
-
-# If false, no module index is generated.
-#html_domain_indices = True
-
-# If false, no index is generated.
-#html_use_index = True
-
-# If true, the index is split into individual pages for each letter.
-#html_split_index = False
-
-# If true, links to the reST sources are added to the pages.
-#html_show_sourcelink = True
-
-# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
-
-# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
-
-# If true, an OpenSearch description file will be output, and all pages will
-# contain a <link> tag referring to it. The value of this option must be the
-# base URL from which the finished HTML is served.
-#html_use_opensearch = ''
-
-# This is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = None
-
-# Language to be used for generating the HTML full-text search index.
-# Sphinx supports the following languages:
-# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja'
-# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr'
-#html_search_language = 'en'
-
-# A dictionary with options for the search language support, empty by default.
-# Now only 'ja' uses this config value
-#html_search_options = {'type': 'default'}
-
-# The name of a javascript file (relative to the configuration directory) that
-# implements a search results scorer. If empty, the default will be used.
-#html_search_scorer = 'scorer.js'
+# Note that the RTD theme ignores this
+html_sidebars = { '**': ["about.html", 'searchbox.html', 'localtoc.html', 'sourcelink.html']}
# Output file base name for HTML help builder.
htmlhelp_basename = 'TheLinuxKerneldoc'
@@ -558,19 +482,6 @@ texinfo_documents = [
'Miscellaneous'),
]
-# Documents to append as an appendix to all manuals.
-#texinfo_appendices = []
-
-# If false, no module index is generated.
-#texinfo_domain_indices = True
-
-# How to display URL addresses: 'footnote', 'no', or 'inline'.
-#texinfo_show_urls = 'footnote'
-
-# If true, do not generate a @detailmenu in the "Top" node's menu.
-#texinfo_no_detailmenu = False
-
-
# -- Options for Epub output ----------------------------------------------
# Bibliographic Dublin Core info.
@@ -579,67 +490,9 @@ epub_author = author
epub_publisher = author
epub_copyright = copyright
-# The basename for the epub file. It defaults to the project name.
-#epub_basename = project
-
-# The HTML theme for the epub output. Since the default themes are not
-# optimized for small screen space, using the same theme for HTML and epub
-# output is usually not wise. This defaults to 'epub', a theme designed to save
-# visual space.
-#epub_theme = 'epub'
-
-# The language of the text. It defaults to the language option
-# or 'en' if the language is not set.
-#epub_language = ''
-
-# The scheme of the identifier. Typical schemes are ISBN or URL.
-#epub_scheme = ''
-
-# The unique identifier of the text. This can be a ISBN number
-# or the project homepage.
-#epub_identifier = ''
-
-# A unique identification for the text.
-#epub_uid = ''
-
-# A tuple containing the cover image and cover page html template filenames.
-#epub_cover = ()
-
-# A sequence of (type, uri, title) tuples for the guide element of content.opf.
-#epub_guide = ()
-
-# HTML files that should be inserted before the pages created by sphinx.
-# The format is a list of tuples containing the path and title.
-#epub_pre_files = []
-
-# HTML files that should be inserted after the pages created by sphinx.
-# The format is a list of tuples containing the path and title.
-#epub_post_files = []
-
# A list of files that should not be packed into the epub file.
epub_exclude_files = ['search.html']
-# The depth of the table of contents in toc.ncx.
-#epub_tocdepth = 3
-
-# Allow duplicate toc entries.
-#epub_tocdup = True
-
-# Choose between 'default' and 'includehidden'.
-#epub_tocscope = 'default'
-
-# Fix unsupported image types using the Pillow.
-#epub_fix_images = False
-
-# Scale large images.
-#epub_max_image_width = 0
-
-# How to display URL addresses: 'footnote', 'no', or 'inline'.
-#epub_show_urls = 'inline'
-
-# If false, no index is generated.
-#epub_use_index = True
-
#=======
# rst2pdf
#
diff --git a/Documentation/core-api/kernel-api.rst b/Documentation/core-api/kernel-api.rst
index 06f4ab122697..c9412eb85552 100644
--- a/Documentation/core-api/kernel-api.rst
+++ b/Documentation/core-api/kernel-api.rst
@@ -171,9 +171,6 @@ Division Functions
.. kernel-doc:: include/linux/math64.h
:internal:
-.. kernel-doc:: lib/math/div64.c
- :functions: div_s64_rem div64_u64_rem div64_u64 div64_s64
-
.. kernel-doc:: lib/math/gcd.c
:export:
diff --git a/Documentation/core-api/local_ops.rst b/Documentation/core-api/local_ops.rst
index 2ac3f9f29845..0b42ceaaf3c4 100644
--- a/Documentation/core-api/local_ops.rst
+++ b/Documentation/core-api/local_ops.rst
@@ -191,7 +191,7 @@ Here is a sample module which implements a basic per cpu counter using
static void __exit test_exit(void)
{
- del_timer_sync(&test_timer);
+ timer_shutdown_sync(&test_timer);
}
module_init(test_init);
diff --git a/Documentation/cpu-freq/index.rst b/Documentation/cpu-freq/index.rst
index aba7831ab1cb..2fe32dad562a 100644
--- a/Documentation/cpu-freq/index.rst
+++ b/Documentation/cpu-freq/index.rst
@@ -20,18 +20,15 @@ Author: Dominik Brodowski <linux@brodo.de>
Mailing List
------------
-There is a CPU frequency changing CVS commit and general list where
-you can report bugs, problems or submit patches. To post a message,
-send an email to linux-pm@vger.kernel.org.
+There is a CPU frequency general list where you can report bugs,
+problems or submit patches. To post a message, send an email to
+linux-pm@vger.kernel.org.
Links
-----
the FTP archives:
* ftp://ftp.linux.org.uk/pub/linux/cpufreq/
-how to access the CVS repository:
-* http://cvs.arm.linux.org.uk/
-
the CPUFreq Mailing list:
* http://vger.kernel.org/vger-lists.html#linux-pm
diff --git a/Documentation/dev-tools/ktap.rst b/Documentation/dev-tools/ktap.rst
index d0a9565b0f44..414c105b10a9 100644
--- a/Documentation/dev-tools/ktap.rst
+++ b/Documentation/dev-tools/ktap.rst
@@ -80,8 +80,8 @@ have the number 1 and the number then must increase by 1 for each additional
subtest within the same test at the same nesting level.
The description is a description of the test, generally the name of
-the test, and can be any string of words (can't include #). The
-description is optional, but recommended.
+the test, and can be any string of characters other than # or a
+newline. The description is optional, but recommended.
The directive and any diagnostic data is optional. If either are present, they
must follow a hash sign, "#".
diff --git a/Documentation/dev-tools/kunit/architecture.rst b/Documentation/dev-tools/kunit/architecture.rst
index 8efe792bdcb9..e95ab05342bb 100644
--- a/Documentation/dev-tools/kunit/architecture.rst
+++ b/Documentation/dev-tools/kunit/architecture.rst
@@ -4,16 +4,17 @@
KUnit Architecture
==================
-The KUnit architecture can be divided into two parts:
+The KUnit architecture is divided into two parts:
- `In-Kernel Testing Framework`_
-- `kunit_tool (Command Line Test Harness)`_
+- `kunit_tool (Command-line Test Harness)`_
In-Kernel Testing Framework
===========================
The kernel testing library supports KUnit tests written in C using
-KUnit. KUnit tests are kernel code. KUnit does several things:
+KUnit. These KUnit tests are kernel code. KUnit performs the following
+tasks:
- Organizes tests
- Reports test results
@@ -22,19 +23,17 @@ KUnit. KUnit tests are kernel code. KUnit does several things:
Test Cases
----------
-The fundamental unit in KUnit is the test case. The KUnit test cases are
-grouped into KUnit suites. A KUnit test case is a function with type
-signature ``void (*)(struct kunit *test)``.
-These test case functions are wrapped in a struct called
-struct kunit_case.
+The test case is the fundamental unit in KUnit. KUnit test cases are organised
+into suites. A KUnit test case is a function with type signature
+``void (*)(struct kunit *test)``. These test case functions are wrapped in a
+struct called struct kunit_case.
.. note:
``generate_params`` is optional for non-parameterized tests.
-Each KUnit test case gets a ``struct kunit`` context
-object passed to it that tracks a running test. The KUnit assertion
-macros and other KUnit utilities use the ``struct kunit`` context
-object. As an exception, there are two fields:
+Each KUnit test case receives a ``struct kunit`` context object that tracks a
+running test. The KUnit assertion macros and other KUnit utilities use the
+``struct kunit`` context object. As an exception, there are two fields:
- ``->priv``: The setup functions can use it to store arbitrary test
user data.
@@ -77,12 +76,13 @@ Executor
The KUnit executor can list and run built-in KUnit tests on boot.
The Test suites are stored in a linker section
-called ``.kunit_test_suites``. For code, see:
-https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/asm-generic/vmlinux.lds.h?h=v5.15#n945.
+called ``.kunit_test_suites``. For the code, see ``KUNIT_TABLE()`` macro
+definition in
+`include/asm-generic/vmlinux.lds.h <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/asm-generic/vmlinux.lds.h?h=v6.0#n950>`_.
The linker section consists of an array of pointers to
``struct kunit_suite``, and is populated by the ``kunit_test_suites()``
-macro. To run all tests compiled into the kernel, the KUnit executor
-iterates over the linker section array.
+macro. The KUnit executor iterates over the linker section array in order to
+run all the tests that are compiled into the kernel.
.. kernel-figure:: kunit_suitememorydiagram.svg
:alt: KUnit Suite Memory
@@ -90,17 +90,17 @@ iterates over the linker section array.
KUnit Suite Memory Diagram
On the kernel boot, the KUnit executor uses the start and end addresses
-of this section to iterate over and run all tests. For code, see:
-https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/kunit/executor.c
-
+of this section to iterate over and run all tests. For the implementation of the
+executor, see
+`lib/kunit/executor.c <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/kunit/executor.c>`_.
When built as a module, the ``kunit_test_suites()`` macro defines a
``module_init()`` function, which runs all the tests in the compilation
unit instead of utilizing the executor.
In KUnit tests, some error classes do not affect other tests
or parts of the kernel, each KUnit case executes in a separate thread
-context. For code, see:
-https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/kunit/try-catch.c?h=v5.15#n58
+context. See the ``kunit_try_catch_run()`` function in
+`lib/kunit/try-catch.c <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/kunit/try-catch.c?h=v5.15#n58>`_.
Assertion Macros
----------------
@@ -111,37 +111,36 @@ All expectations/assertions are formatted as:
- ``{EXPECT|ASSERT}`` determines whether the check is an assertion or an
expectation.
+ In the event of a failure, the testing flow differs as follows:
- - For an expectation, if the check fails, marks the test as failed
- and logs the failure.
+ - For expectations, the test is marked as failed and the failure is logged.
- - An assertion, on failure, causes the test case to terminate
- immediately.
+ - Failing assertions, on the other hand, result in the test case being
+ terminated immediately.
- - Assertions call function:
+ - Assertions call the function:
``void __noreturn kunit_abort(struct kunit *)``.
- - ``kunit_abort`` calls function:
+ - ``kunit_abort`` calls the function:
``void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch)``.
- - ``kunit_try_catch_throw`` calls function:
+ - ``kunit_try_catch_throw`` calls the function:
``void kthread_complete_and_exit(struct completion *, long) __noreturn;``
and terminates the special thread context.
- ``<op>`` denotes a check with options: ``TRUE`` (supplied property
- has the boolean value “trueâ€), ``EQ`` (two supplied properties are
+ has the boolean value "true"), ``EQ`` (two supplied properties are
equal), ``NOT_ERR_OR_NULL`` (supplied pointer is not null and does not
- contain an “err†value).
+ contain an "err" value).
- ``[_MSG]`` prints a custom message on failure.
Test Result Reporting
---------------------
-KUnit prints test results in KTAP format. KTAP is based on TAP14, see:
-https://github.com/isaacs/testanything.github.io/blob/tap14/tap-version-14-specification.md.
-KTAP (yet to be standardized format) works with KUnit and Kselftest.
-The KUnit executor prints KTAP results to dmesg, and debugfs
-(if configured).
+KUnit prints the test results in KTAP format. KTAP is based on TAP14, see
+Documentation/dev-tools/ktap.rst.
+KTAP works with KUnit and Kselftest. The KUnit executor prints KTAP results to
+dmesg, and debugfs (if configured).
Parameterized Tests
-------------------
@@ -150,33 +149,35 @@ Each KUnit parameterized test is associated with a collection of
parameters. The test is invoked multiple times, once for each parameter
value and the parameter is stored in the ``param_value`` field.
The test case includes a KUNIT_CASE_PARAM() macro that accepts a
-generator function.
-The generator function is passed the previous parameter and returns the next
-parameter. It also provides a macro to generate common-case generators based on
-arrays.
+generator function. The generator function is passed the previous parameter
+and returns the next parameter. It also includes a macro for generating
+array-based common-case generators.
-kunit_tool (Command Line Test Harness)
+kunit_tool (Command-line Test Harness)
======================================
-kunit_tool is a Python script ``(tools/testing/kunit/kunit.py)``
-that can be used to configure, build, exec, parse and run (runs other
-commands in order) test results. You can either run KUnit tests using
-kunit_tool or can include KUnit in kernel and parse manually.
+``kunit_tool`` is a Python script, found in ``tools/testing/kunit/kunit.py``. It
+is used to configure, build, execute, parse test results and run all of the
+previous commands in correct order (i.e., configure, build, execute and parse).
+You have two options for running KUnit tests: either build the kernel with KUnit
+enabled and manually parse the results (see
+Documentation/dev-tools/kunit/run_manual.rst) or use ``kunit_tool``
+(see Documentation/dev-tools/kunit/run_wrapper.rst).
- ``configure`` command generates the kernel ``.config`` from a
``.kunitconfig`` file (and any architecture-specific options).
- For some architectures, additional config options are specified in the
- ``qemu_config`` Python script
- (For example: ``tools/testing/kunit/qemu_configs/powerpc.py``).
+ The Python scripts available in ``qemu_configs`` folder
+ (for example, ``tools/testing/kunit/qemu configs/powerpc.py``) contains
+ additional configuration options for specific architectures.
It parses both the existing ``.config`` and the ``.kunitconfig`` files
- and ensures that ``.config`` is a superset of ``.kunitconfig``.
- If this is not the case, it will combine the two and run
- ``make olddefconfig`` to regenerate the ``.config`` file. It then
- verifies that ``.config`` is now a superset. This checks if all
- Kconfig dependencies are correctly specified in ``.kunitconfig``.
- ``kunit_config.py`` includes the parsing Kconfigs code. The code which
- runs ``make olddefconfig`` is a part of ``kunit_kernel.py``. You can
- invoke this command via: ``./tools/testing/kunit/kunit.py config`` and
+ to ensure that ``.config`` is a superset of ``.kunitconfig``.
+ If not, it will combine the two and run ``make olddefconfig`` to regenerate
+ the ``.config`` file. It then checks to see if ``.config`` has become a superset.
+ This verifies that all the Kconfig dependencies are correctly specified in the
+ file ``.kunitconfig``. The ``kunit_config.py`` script contains the code for parsing
+ Kconfigs. The code which runs ``make olddefconfig`` is part of the
+ ``kunit_kernel.py`` script. You can invoke this command through:
+ ``./tools/testing/kunit/kunit.py config`` and
generate a ``.config`` file.
- ``build`` runs ``make`` on the kernel tree with required options
(depends on the architecture and some options, for example: build_dir)
@@ -184,8 +185,8 @@ kunit_tool or can include KUnit in kernel and parse manually.
To build a KUnit kernel from the current ``.config``, you can use the
``build`` argument: ``./tools/testing/kunit/kunit.py build``.
- ``exec`` command executes kernel results either directly (using
- User-mode Linux configuration), or via an emulator such
- as QEMU. It reads results from the log via standard
+ User-mode Linux configuration), or through an emulator such
+ as QEMU. It reads results from the log using standard
output (stdout), and passes them to ``parse`` to be parsed.
If you already have built a kernel with built-in KUnit tests,
you can run the kernel and display the test results with the ``exec``
diff --git a/Documentation/dev-tools/kunit/index.rst b/Documentation/dev-tools/kunit/index.rst
index f5d13f1d37be..b3593ae29ace 100644
--- a/Documentation/dev-tools/kunit/index.rst
+++ b/Documentation/dev-tools/kunit/index.rst
@@ -16,7 +16,6 @@ KUnit - Linux Kernel Unit Testing
api/index
style
faq
- tips
running_tips
This section details the kernel unit testing framework.
@@ -100,14 +99,11 @@ Read also :ref:`kinds-of-tests`.
How do I use it?
================
-* Documentation/dev-tools/kunit/start.rst - for KUnit new users.
-* Documentation/dev-tools/kunit/architecture.rst - KUnit architecture.
-* Documentation/dev-tools/kunit/run_wrapper.rst - run kunit_tool.
-* Documentation/dev-tools/kunit/run_manual.rst - run tests without kunit_tool.
-* Documentation/dev-tools/kunit/usage.rst - write tests.
-* Documentation/dev-tools/kunit/tips.rst - best practices with
- examples.
-* Documentation/dev-tools/kunit/api/index.rst - KUnit APIs
- used for testing.
-* Documentation/dev-tools/kunit/faq.rst - KUnit common questions and
- answers.
+You can find a step-by-step guide to writing and running KUnit tests in
+Documentation/dev-tools/kunit/start.rst
+
+Alternatively, feel free to look through the rest of the KUnit documentation,
+or to experiment with tools/testing/kunit/kunit.py and the example test under
+lib/kunit/kunit-example-test.c
+
+Happy testing!
diff --git a/Documentation/dev-tools/kunit/start.rst b/Documentation/dev-tools/kunit/start.rst
index f4f504f1fb15..c736613c9b19 100644
--- a/Documentation/dev-tools/kunit/start.rst
+++ b/Documentation/dev-tools/kunit/start.rst
@@ -294,13 +294,11 @@ Congrats! You just wrote your first KUnit test.
Next Steps
==========
-* Documentation/dev-tools/kunit/architecture.rst - KUnit architecture.
-* Documentation/dev-tools/kunit/run_wrapper.rst - run kunit_tool.
-* Documentation/dev-tools/kunit/run_manual.rst - run tests without kunit_tool.
-* Documentation/dev-tools/kunit/usage.rst - write tests.
-* Documentation/dev-tools/kunit/tips.rst - best practices with
- examples.
-* Documentation/dev-tools/kunit/api/index.rst - KUnit APIs
- used for testing.
-* Documentation/dev-tools/kunit/faq.rst - KUnit common questions and
- answers.
+If you're interested in using some of the more advanced features of kunit.py,
+take a look at Documentation/dev-tools/kunit/run_wrapper.rst
+
+If you'd like to run tests without using kunit.py, check out
+Documentation/dev-tools/kunit/run_manual.rst
+
+For more information on writing KUnit tests (including some common techniques
+for testing different things), see Documentation/dev-tools/kunit/usage.rst
diff --git a/Documentation/dev-tools/kunit/tips.rst b/Documentation/dev-tools/kunit/tips.rst
deleted file mode 100644
index 492d2ded2f5a..000000000000
--- a/Documentation/dev-tools/kunit/tips.rst
+++ /dev/null
@@ -1,190 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-============================
-Tips For Writing KUnit Tests
-============================
-
-Exiting early on failed expectations
-------------------------------------
-
-``KUNIT_EXPECT_EQ`` and friends will mark the test as failed and continue
-execution. In some cases, it's unsafe to continue and you can use the
-``KUNIT_ASSERT`` variant to exit on failure.
-
-.. code-block:: c
-
- void example_test_user_alloc_function(struct kunit *test)
- {
- void *object = alloc_some_object_for_me();
-
- /* Make sure we got a valid pointer back. */
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, object);
- do_something_with_object(object);
- }
-
-Allocating memory
------------------
-
-Where you would use ``kzalloc``, you should prefer ``kunit_kzalloc`` instead.
-KUnit will ensure the memory is freed once the test completes.
-
-This is particularly useful since it lets you use the ``KUNIT_ASSERT_EQ``
-macros to exit early from a test without having to worry about remembering to
-call ``kfree``.
-
-Example:
-
-.. code-block:: c
-
- void example_test_allocation(struct kunit *test)
- {
- char *buffer = kunit_kzalloc(test, 16, GFP_KERNEL);
- /* Ensure allocation succeeded. */
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buffer);
-
- KUNIT_ASSERT_STREQ(test, buffer, "");
- }
-
-
-Testing static functions
-------------------------
-
-If you don't want to expose functions or variables just for testing, one option
-is to conditionally ``#include`` the test file at the end of your .c file, e.g.
-
-.. code-block:: c
-
- /* In my_file.c */
-
- static int do_interesting_thing();
-
- #ifdef CONFIG_MY_KUNIT_TEST
- #include "my_kunit_test.c"
- #endif
-
-Injecting test-only code
-------------------------
-
-Similarly to the above, it can be useful to add test-specific logic.
-
-.. code-block:: c
-
- /* In my_file.h */
-
- #ifdef CONFIG_MY_KUNIT_TEST
- /* Defined in my_kunit_test.c */
- void test_only_hook(void);
- #else
- void test_only_hook(void) { }
- #endif
-
-This test-only code can be made more useful by accessing the current kunit
-test, see below.
-
-Accessing the current test
---------------------------
-
-In some cases, you need to call test-only code from outside the test file, e.g.
-like in the example above or if you're providing a fake implementation of an
-ops struct.
-There is a ``kunit_test`` field in ``task_struct``, so you can access it via
-``current->kunit_test``.
-
-Here's a slightly in-depth example of how one could implement "mocking":
-
-.. code-block:: c
-
- #include <linux/sched.h> /* for current */
-
- struct test_data {
- int foo_result;
- int want_foo_called_with;
- };
-
- static int fake_foo(int arg)
- {
- struct kunit *test = current->kunit_test;
- struct test_data *test_data = test->priv;
-
- KUNIT_EXPECT_EQ(test, test_data->want_foo_called_with, arg);
- return test_data->foo_result;
- }
-
- static void example_simple_test(struct kunit *test)
- {
- /* Assume priv is allocated in the suite's .init */
- struct test_data *test_data = test->priv;
-
- test_data->foo_result = 42;
- test_data->want_foo_called_with = 1;
-
- /* In a real test, we'd probably pass a pointer to fake_foo somewhere
- * like an ops struct, etc. instead of calling it directly. */
- KUNIT_EXPECT_EQ(test, fake_foo(1), 42);
- }
-
-
-Note: here we're able to get away with using ``test->priv``, but if you wanted
-something more flexible you could use a named ``kunit_resource``, see
-Documentation/dev-tools/kunit/api/test.rst.
-
-Failing the current test
-------------------------
-
-But sometimes, you might just want to fail the current test. In that case, we
-have ``kunit_fail_current_test(fmt, args...)`` which is defined in ``<kunit/test-bug.h>`` and
-doesn't require pulling in ``<kunit/test.h>``.
-
-E.g. say we had an option to enable some extra debug checks on some data structure:
-
-.. code-block:: c
-
- #include <kunit/test-bug.h>
-
- #ifdef CONFIG_EXTRA_DEBUG_CHECKS
- static void validate_my_data(struct data *data)
- {
- if (is_valid(data))
- return;
-
- kunit_fail_current_test("data %p is invalid", data);
-
- /* Normal, non-KUnit, error reporting code here. */
- }
- #else
- static void my_debug_function(void) { }
- #endif
-
-
-Customizing error messages
---------------------------
-
-Each of the ``KUNIT_EXPECT`` and ``KUNIT_ASSERT`` macros have a ``_MSG`` variant.
-These take a format string and arguments to provide additional context to the automatically generated error messages.
-
-.. code-block:: c
-
- char some_str[41];
- generate_sha1_hex_string(some_str);
-
- /* Before. Not easy to tell why the test failed. */
- KUNIT_EXPECT_EQ(test, strlen(some_str), 40);
-
- /* After. Now we see the offending string. */
- KUNIT_EXPECT_EQ_MSG(test, strlen(some_str), 40, "some_str='%s'", some_str);
-
-Alternatively, one can take full control over the error message by using ``KUNIT_FAIL()``, e.g.
-
-.. code-block:: c
-
- /* Before */
- KUNIT_EXPECT_EQ(test, some_setup_function(), 0);
-
- /* After: full control over the failure message. */
- if (some_setup_function())
- KUNIT_FAIL(test, "Failed to setup thing for testing");
-
-Next Steps
-==========
-* Optional: see the Documentation/dev-tools/kunit/usage.rst page for a more
- in-depth explanation of KUnit.
diff --git a/Documentation/dev-tools/kunit/usage.rst b/Documentation/dev-tools/kunit/usage.rst
index 2737863ef365..48f8196d5aad 100644
--- a/Documentation/dev-tools/kunit/usage.rst
+++ b/Documentation/dev-tools/kunit/usage.rst
@@ -112,11 +112,45 @@ terminates the test case if the condition is not satisfied. For example:
KUNIT_EXPECT_LE(test, a[i], a[i + 1]);
}
-In this example, the method under test should return pointer to a value. If the
-pointer returns null or an errno, we want to stop the test since the following
-expectation could crash the test case. `ASSERT_NOT_ERR_OR_NULL(...)` allows us
-to bail out of the test case if the appropriate conditions are not satisfied to
-complete the test.
+In this example, we need to be able to allocate an array to test the ``sort()``
+function. So we use ``KUNIT_ASSERT_NOT_ERR_OR_NULL()`` to abort the test if
+there's an allocation error.
+
+.. note::
+ In other test frameworks, ``ASSERT`` macros are often implemented by calling
+ ``return`` so they only work from the test function. In KUnit, we stop the
+ current kthread on failure, so you can call them from anywhere.
+
+Customizing error messages
+--------------------------
+
+Each of the ``KUNIT_EXPECT`` and ``KUNIT_ASSERT`` macros have a ``_MSG``
+variant. These take a format string and arguments to provide additional
+context to the automatically generated error messages.
+
+.. code-block:: c
+
+ char some_str[41];
+ generate_sha1_hex_string(some_str);
+
+ /* Before. Not easy to tell why the test failed. */
+ KUNIT_EXPECT_EQ(test, strlen(some_str), 40);
+
+ /* After. Now we see the offending string. */
+ KUNIT_EXPECT_EQ_MSG(test, strlen(some_str), 40, "some_str='%s'", some_str);
+
+Alternatively, one can take full control over the error message by using
+``KUNIT_FAIL()``, e.g.
+
+.. code-block:: c
+
+ /* Before */
+ KUNIT_EXPECT_EQ(test, some_setup_function(), 0);
+
+ /* After: full control over the failure message. */
+ if (some_setup_function())
+ KUNIT_FAIL(test, "Failed to setup thing for testing");
+
Test Suites
~~~~~~~~~~~
@@ -546,24 +580,6 @@ By reusing the same ``cases`` array from above, we can write the test as a
{}
};
-Exiting Early on Failed Expectations
-------------------------------------
-
-We can use ``KUNIT_EXPECT_EQ`` to mark the test as failed and continue
-execution. In some cases, it is unsafe to continue. We can use the
-``KUNIT_ASSERT`` variant to exit on failure.
-
-.. code-block:: c
-
- void example_test_user_alloc_function(struct kunit *test)
- {
- void *object = alloc_some_object_for_me();
-
- /* Make sure we got a valid pointer back. */
- KUNIT_ASSERT_NOT_ERR_OR_NULL(test, object);
- do_something_with_object(object);
- }
-
Allocating Memory
-----------------
@@ -625,17 +641,23 @@ as shown in next section: *Accessing The Current Test*.
Accessing The Current Test
--------------------------
-In some cases, we need to call test-only code from outside the test file.
-For example, see example in section *Injecting Test-Only Code* or if
-we are providing a fake implementation of an ops struct. Using
-``kunit_test`` field in ``task_struct``, we can access it via
-``current->kunit_test``.
+In some cases, we need to call test-only code from outside the test file. This
+is helpful, for example, when providing a fake implementation of a function, or
+to fail any current test from within an error handler.
+We can do this via the ``kunit_test`` field in ``task_struct``, which we can
+access using the ``kunit_get_current_test()`` function in ``kunit/test-bug.h``.
+
+``kunit_get_current_test()`` is safe to call even if KUnit is not enabled. If
+KUnit is not enabled, was built as a module (``CONFIG_KUNIT=m``), or no test is
+running in the current task, it will return ``NULL``. This compiles down to
+either a no-op or a static key check, so will have a negligible performance
+impact when no test is running.
-The example below includes how to implement "mocking":
+The example below uses this to implement a "mock" implementation of a function, ``foo``:
.. code-block:: c
- #include <linux/sched.h> /* for current */
+ #include <kunit/test-bug.h> /* for kunit_get_current_test */
struct test_data {
int foo_result;
@@ -644,7 +666,7 @@ The example below includes how to implement "mocking":
static int fake_foo(int arg)
{
- struct kunit *test = current->kunit_test;
+ struct kunit *test = kunit_get_current_test();
struct test_data *test_data = test->priv;
KUNIT_EXPECT_EQ(test, test_data->want_foo_called_with, arg);
@@ -675,7 +697,7 @@ Each test can have multiple resources which have string names providing the same
flexibility as a ``priv`` member, but also, for example, allowing helper
functions to create resources without conflicting with each other. It is also
possible to define a clean up function for each resource, making it easy to
-avoid resource leaks. For more information, see Documentation/dev-tools/kunit/api/test.rst.
+avoid resource leaks. For more information, see Documentation/dev-tools/kunit/api/resource.rst.
Failing The Current Test
------------------------
@@ -703,3 +725,9 @@ structures as shown below:
static void my_debug_function(void) { }
#endif
+``kunit_fail_current_test()`` is safe to call even if KUnit is not enabled. If
+KUnit is not enabled, was built as a module (``CONFIG_KUNIT=m``), or no test is
+running in the current task, it will do nothing. This compiles down to either a
+no-op or a static key check, so will have a negligible performance impact when
+no test is running.
+
diff --git a/Documentation/devicetree/bindings/arm/amlogic.yaml b/Documentation/devicetree/bindings/arm/amlogic.yaml
index 9fda2436c618..e16b5fa55847 100644
--- a/Documentation/devicetree/bindings/arm/amlogic.yaml
+++ b/Documentation/devicetree/bindings/arm/amlogic.yaml
@@ -163,6 +163,7 @@ properties:
- azw,gsking-x
- azw,gtking
- azw,gtking-pro
+ - hardkernel,odroid-go-ultra
- hardkernel,odroid-n2
- hardkernel,odroid-n2-plus
- khadas,vim3
diff --git a/Documentation/devicetree/bindings/arm/apple.yaml b/Documentation/devicetree/bindings/arm/apple.yaml
index 7262f3c09867..da78c69774f2 100644
--- a/Documentation/devicetree/bindings/arm/apple.yaml
+++ b/Documentation/devicetree/bindings/arm/apple.yaml
@@ -19,12 +19,14 @@ description: |
- MacBook Air (M1, 2020)
- iMac (24-inch, M1, 2021)
- And devices based on the "M1 Pro" and "M1 Max" SoCs:
+ And devices based on the "M1 Pro", "M1 Max" and "M1 Ultra" SoCs:
- MacBook Pro (14-inch, M1 Pro, 2021)
- MacBook Pro (14-inch, M1 Max, 2021)
- MacBook Pro (16-inch, M1 Pro, 2021)
- MacBook Pro (16-inch, M1 Max, 2021)
+ - Mac Studio (M1 Max, 2022)
+ - Mac Studio (M1 Ultra, 2022)
The compatible property should follow this format:
@@ -67,6 +69,7 @@ properties:
- apple,j457 # iMac (24-inch, 2x USB-C, M1, 2021)
- const: apple,t8103
- const: apple,arm-platform
+
- description: Apple M1 Pro SoC based platforms
items:
- enum:
@@ -74,14 +77,23 @@ properties:
- apple,j316s # MacBook Pro (16-inch, M1 Pro, 2021)
- const: apple,t6000
- const: apple,arm-platform
+
- description: Apple M1 Max SoC based platforms
items:
- enum:
- apple,j314c # MacBook Pro (14-inch, M1 Max, 2021)
- apple,j316c # MacBook Pro (16-inch, M1 Max, 2021)
+ - apple,j375c # Mac Studio (M1 Max, 2022)
- const: apple,t6001
- const: apple,arm-platform
+ - description: Apple M1 Ultra SoC based platforms
+ items:
+ - enum:
+ - apple,j375d # Mac Studio (M1 Ultra, 2022)
+ - const: apple,t6002
+ - const: apple,arm-platform
+
additionalProperties: true
...
diff --git a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
index 217a1d674863..73f272664e83 100644
--- a/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
+++ b/Documentation/devicetree/bindings/arm/aspeed/aspeed.yaml
@@ -17,6 +17,7 @@ properties:
- description: AST2400 based boards
items:
- enum:
+ - delta,ahe50dc-bmc
- facebook,galaxy100-bmc
- facebook,wedge100-bmc
- facebook,wedge40-bmc
@@ -82,7 +83,7 @@ properties:
- ibm,tacoma-bmc
- inventec,transformer-bmc
- jabil,rbp-bmc
- - nuvia,dc-scm-bmc
+ - qcom,dc-scm-v1-bmc
- quanta,s6q-bmc
- const: aspeed,ast2600
diff --git a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.yaml b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.yaml
index 958df32b4899..52b575c40599 100644
--- a/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.yaml
+++ b/Documentation/devicetree/bindings/arm/bcm/brcm,bcm4708.yaml
@@ -66,6 +66,7 @@ properties:
- enum:
- asus,rt-ac88u
- dlink,dir-885l
+ - dlink,dir-890l
- linksys,panamera
- luxul,abr-4500-v1
- luxul,xap-1610-v1
@@ -97,6 +98,7 @@ properties:
- description: BCM53016 based boards
items:
- enum:
+ - dlink,dwl-8610ap
- meraki,mr32
- const: brcm,bcm53016
- const: brcm,bcm4708
diff --git a/Documentation/devicetree/bindings/arm/cpus.yaml b/Documentation/devicetree/bindings/arm/cpus.yaml
index 5c13b73e4d57..7dd84f8f8e4f 100644
--- a/Documentation/devicetree/bindings/arm/cpus.yaml
+++ b/Documentation/devicetree/bindings/arm/cpus.yaml
@@ -178,11 +178,13 @@ properties:
- qcom,kryo250
- qcom,kryo260
- qcom,kryo280
+ - qcom,kryo360
- qcom,kryo385
- qcom,kryo468
- qcom,kryo485
- qcom,kryo560
- qcom,kryo570
+ - qcom,kryo660
- qcom,kryo685
- qcom,kryo780
- qcom,scorpion
diff --git a/Documentation/devicetree/bindings/arm/fsl.yaml b/Documentation/devicetree/bindings/arm/fsl.yaml
index fbfc4f99c01e..05b5276a0e14 100644
--- a/Documentation/devicetree/bindings/arm/fsl.yaml
+++ b/Documentation/devicetree/bindings/arm/fsl.yaml
@@ -520,6 +520,7 @@ properties:
items:
- enum:
- fsl,imx6sl-evk # i.MX6 SoloLite EVK Board
+ - kobo,aura2
- kobo,tolino-shine2hd
- kobo,tolino-shine3
- kobo,tolino-vision5
@@ -814,6 +815,7 @@ properties:
- enum:
- beacon,imx8mm-beacon-kit # i.MX8MM Beacon Development Kit
- boundary,imx8mm-nitrogen8mm # i.MX8MM Nitrogen Board
+ - cloos,imx8mm-phg # i.MX8MM Cloos PHG Board
- dmo,imx8mm-data-modul-edm-sbc # i.MX8MM eDM SBC
- emtrion,emcon-mx8mm-avari # emCON-MX8MM SoM on Avari Base
- fsl,imx8mm-ddr4-evk # i.MX8MM DDR4 EVK Board
@@ -825,6 +827,7 @@ properties:
- gw,imx8mm-gw7901 # i.MX8MM Gateworks Board
- gw,imx8mm-gw7902 # i.MX8MM Gateworks Board
- gw,imx8mm-gw7903 # i.MX8MM Gateworks Board
+ - innocomm,wb15-evk # i.MX8MM Innocomm EVK board with WB15 SoM
- kontron,imx8mm-sl # i.MX8MM Kontron SL (N801X) SOM
- kontron,imx8mm-osm-s # i.MX8MM Kontron OSM-S (N802X) SOM
- menlo,mx8menlo # i.MX8MM Menlo board with Verdin SoM
@@ -1067,6 +1070,18 @@ properties:
- fsl,imx93-11x11-evk # i.MX93 11x11 EVK Board
- const: fsl,imx93
+ - description: i.MXRT1050 based Boards
+ items:
+ - enum:
+ - fsl,imxrt1050-evk # i.MXRT1050 EVK Board
+ - const: fsl,imxrt1050
+
+ - description: i.MXRT1170 based Boards
+ items:
+ - enum:
+ - fsl,imxrt1170-evk # i.MXRT1170 EVK Board
+ - const: fsl,imxrt1170
+
- description:
Freescale Vybrid Platform Device Tree Bindings
diff --git a/Documentation/devicetree/bindings/arm/mediatek.yaml b/Documentation/devicetree/bindings/arm/mediatek.yaml
index d76ce4c3819d..2275e5d93721 100644
--- a/Documentation/devicetree/bindings/arm/mediatek.yaml
+++ b/Documentation/devicetree/bindings/arm/mediatek.yaml
@@ -58,6 +58,7 @@ properties:
- items:
- enum:
- mediatek,mt6795-evb
+ - sony,xperia-m5
- const: mediatek,mt6795
- items:
- enum:
@@ -83,6 +84,7 @@ properties:
- const: mediatek,mt7629
- items:
- enum:
+ - bananapi,bpi-r3
- mediatek,mt7986a-rfb
- const: mediatek,mt7986a
- items:
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml
index eb451bec23d3..0711f1834fbd 100644
--- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml
+++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.yaml
@@ -32,14 +32,26 @@ properties:
- mediatek,mt8183-mmsys
- mediatek,mt8186-mmsys
- mediatek,mt8192-mmsys
- - mediatek,mt8195-mmsys
- mediatek,mt8365-mmsys
- const: syscon
+
+ - description: vdosys0 and vdosys1 are 2 display HW pipelines,
+ so mt8195 binding should be deprecated.
+ deprecated: true
+ items:
+ - const: mediatek,mt8195-mmsys
+ - const: syscon
+
- items:
- const: mediatek,mt7623-mmsys
- const: mediatek,mt2701-mmsys
- const: syscon
+ - items:
+ - const: mediatek,mt8195-vdosys0
+ - const: mediatek,mt8195-mmsys
+ - const: syscon
+
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml
index 5ea506412b4e..38efcad56dbd 100644
--- a/Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml
+++ b/Documentation/devicetree/bindings/arm/msm/qcom,llcc.yaml
@@ -31,6 +31,7 @@ properties:
- qcom,sm8250-llcc
- qcom,sm8350-llcc
- qcom,sm8450-llcc
+ - qcom,sm8550-llcc
reg:
items:
diff --git a/Documentation/devicetree/bindings/arm/qcom-soc.yaml b/Documentation/devicetree/bindings/arm/qcom-soc.yaml
new file mode 100644
index 000000000000..e333ec4a9c5f
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/qcom-soc.yaml
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/arm/qcom-soc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SoC compatibles naming convention
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+
+description: |
+ Guidelines for new compatibles for SoC blocks/components.
+ When adding new compatibles in new bindings, use the format::
+ qcom,SoC-IP
+
+ For example::
+ qcom,sdm845-llcc-bwmon
+
+ When adding new compatibles to existing bindings, use the format in the
+ existing binding, even if it contradicts the above.
+
+select:
+ properties:
+ compatible:
+ pattern: "^qcom,.*(apq|ipq|mdm|msm|qcm|qcs|sa|sc|sdm|sdx|sm)[0-9]+.*$"
+ required:
+ - compatible
+
+properties:
+ compatible:
+ oneOf:
+ # Preferred naming style for compatibles of SoC components:
+ - pattern: "^qcom,(apq|ipq|mdm|msm|qcm|qcs|sa|sc|sdm|sdx|sm)[0-9]+-.*$"
+ - pattern: "^qcom,(sa|sc)8[0-9]+[a-z][a-z]?-.*$"
+
+ # Legacy namings - variations of existing patterns/compatibles are OK,
+ # but do not add completely new entries to these:
+ - pattern: "^qcom,[ak]pss-wdt-(apq|ipq|mdm|msm|qcm|qcs|sa|sc|sdm|sdx|sm)[0-9]+.*$"
+ - pattern: "^qcom,gcc-(apq|ipq|mdm|msm|qcm|qcs|sa|sc|sdm|sdx|sm)[0-9]+.*$"
+ - pattern: "^qcom,mmcc-(apq|ipq|mdm|msm|qcm|qcs|sa|sc|sdm|sdx|sm)[0-9]+.*$"
+ - pattern: "^qcom,pcie-(apq|ipq|mdm|msm|qcm|qcs|sa|sc|sdm|sdx|sm)[0-9]+.*$"
+ - pattern: "^qcom,rpm-(apq|ipq|mdm|msm|qcm|qcs|sa|sc|sdm|sdx|sm)[0-9]+.*$"
+ - pattern: "^qcom,scm-(apq|ipq|mdm|msm|qcm|qcs|sa|sc|sdm|sdx|sm)[0-9]+.*$"
+ - enum:
+ - qcom,dsi-ctrl-6g-qcm2290
+ - qcom,gpucc-sdm630
+ - qcom,gpucc-sdm660
+ - qcom,lcc-apq8064
+ - qcom,lcc-ipq8064
+ - qcom,lcc-mdm9615
+ - qcom,lcc-msm8960
+ - qcom,lpass-cpu-apq8016
+ - qcom,usb-ss-ipq4019-phy
+ - qcom,usb-hs-ipq4019-phy
+ - qcom,vqmmc-ipq4019-regulator
+
+ # Legacy compatibles with wild-cards - list cannot grow with new bindings:
+ - enum:
+ - qcom,ipq806x-gmac
+ - qcom,ipq806x-nand
+ - qcom,ipq806x-sata-phy
+ - qcom,ipq806x-usb-phy-ss
+ - qcom,ipq806x-usb-phy-hs
+
+additionalProperties: true
diff --git a/Documentation/devicetree/bindings/arm/qcom.yaml b/Documentation/devicetree/bindings/arm/qcom.yaml
index 1b5ac6b02bc5..27063a045bd0 100644
--- a/Documentation/devicetree/bindings/arm/qcom.yaml
+++ b/Documentation/devicetree/bindings/arm/qcom.yaml
@@ -29,17 +29,22 @@ description: |
apq8074
apq8084
apq8096
+ ipq4018
ipq6018
ipq8074
mdm9615
msm8226
msm8916
+ msm8956
msm8974
+ msm8976
msm8992
msm8994
msm8996
msm8998
qcs404
+ qdu1000
+ qru1000
sa8155p
sa8540p
sc7180
@@ -51,11 +56,15 @@ description: |
sdm632
sdm636
sdm660
+ sdm670
sdm845
sdx55
sdx65
+ sm4250
+ sm6115
sm6125
sm6350
+ sm6375
sm7225
sm8150
sm8250
@@ -76,6 +85,7 @@ description: |
mtp
qrd
sbc
+ x100
The 'soc_version' and 'board_version' elements take the form of v<Major>.<Minor>
where the minor number may be omitted when it's zero, i.e. v1.0 is the same
@@ -114,7 +124,9 @@ properties:
- items:
- enum:
- asus,sparrow
+ - huawei,sturgeon
- lg,lenok
+ - samsung,matisse-wifi
- const: qcom,apq8026
- items:
@@ -150,20 +162,32 @@ properties:
- items:
- enum:
+ - sony,kugo-row
+ - sony,suzu-row
+ - const: qcom,msm8956
+
+ - items:
+ - enum:
- qcom,msm8960-cdp
- const: qcom,msm8960
- items:
- enum:
- - fairphone,fp2
- lge,hammerhead
- - samsung,klte
- sony,xperia-amami
- - sony,xperia-castor
- sony,xperia-honami
- const: qcom,msm8974
- items:
+ - enum:
+ - fairphone,fp2
+ - oneplus,bacon
+ - samsung,klte
+ - sony,xperia-castor
+ - const: qcom,msm8974pro
+ - const: qcom,msm8974
+
+ - items:
- const: qcom,msm8916-mtp
- const: qcom,msm8916-mtp/1
- const: qcom,msm8916
@@ -221,13 +245,20 @@ properties:
- items:
- enum:
+ - oneplus,oneplus3
+ - oneplus,oneplus3t
- qcom,msm8996-mtp
- sony,dora-row
- sony,kagura-row
- sony,keyaki-row
- xiaomi,gemini
+ - const: qcom,msm8996
+
+ - items:
+ - enum:
- xiaomi,natrium
- xiaomi,scorpio
+ - const: qcom,msm8996pro
- const: qcom,msm8996
- items:
@@ -242,10 +273,17 @@ properties:
- sony,xperia-lilac
- sony,xperia-maple
- sony,xperia-poplar
+ - xiaomi,sagit
- const: qcom,msm8998
- items:
- enum:
+ - 8dev,jalapeno
+ - alfa-network,ap120c-ac
+ - const: qcom,ipq4018
+
+ - items:
+ - enum:
- qcom,ipq4019-ap-dk01.1-c1
- qcom,ipq4019-ap-dk04.1-c3
- qcom,ipq4019-ap-dk07.1-c1
@@ -255,6 +293,7 @@ properties:
- items:
- enum:
+ - mikrotik,rb3011
- qcom,ipq8064-ap148
- const: qcom,ipq8064
@@ -265,6 +304,25 @@ properties:
- qcom,ipq8074-hk10-c2
- const: qcom,ipq8074
+ - description: Sierra Wireless MangOH Green with WP8548 Module
+ items:
+ - const: swir,mangoh-green-wp8548
+ - const: swir,wp8548
+ - const: qcom,mdm9615
+
+ - description: Qualcomm Technologies, Inc. Distributed Unit 1000 platform
+ items:
+ - enum:
+ - qcom,qdu1000-idp
+ - qcom,qdu1000-x100
+ - const: qcom,qdu1000
+
+ - description: Qualcomm Technologies, Inc. Radio Unit 1000 platform
+ items:
+ - enum:
+ - qcom,qru1000-idp
+ - const: qcom,qru1000
+
- description: Qualcomm Technologies, Inc. SC7180 IDP
items:
- enum:
@@ -463,6 +521,17 @@ properties:
- const: google,pazquel-sku2
- const: qcom,sc7180
+ - description: Google Pazquel360 with LTE (newest rev)
+ items:
+ - const: google,pazquel-sku22
+ - const: google,pazquel-sku20
+ - const: qcom,sc7180
+
+ - description: Google Pazquel360 with WiFi (newest rev)
+ items:
+ - const: google,pazquel-sku21
+ - const: qcom,sc7180
+
- description: Sharp Dynabook Chromebook C1 (rev1)
items:
- const: google,pompom-rev1
@@ -575,6 +644,11 @@ properties:
- const: google,evoker
- const: qcom,sc7280
+ - description: Google Evoker with LTE (newest rev)
+ items:
+ - const: google,evoker-sku512
+ - const: qcom,sc7280
+
- description: Google Herobrine (newest rev)
items:
- const: google,herobrine
@@ -595,6 +669,16 @@ properties:
- const: google,villager-sku512
- const: qcom,sc7280
+ - description: Google Zombie (newest rev)
+ items:
+ - const: google,zombie
+ - const: qcom,sc7280
+
+ - description: Google Zombie with LTE (newest rev)
+ items:
+ - const: google,zombie-sku512
+ - const: qcom,sc7280
+
- items:
- enum:
- lenovo,flex-5g
@@ -639,6 +723,11 @@ properties:
- items:
- enum:
+ - google,sargo
+ - const: qcom,sdm670
+
+ - items:
+ - enum:
- qcom,sdx55-mtp
- qcom,sdx55-telit-fn980-tlb
- qcom,sdx55-t55
@@ -670,10 +759,14 @@ properties:
- items:
- enum:
- qcom,sa8295p-adp
+ - qcom,sa8540p-ride
- const: qcom,sa8540p
- items:
- enum:
+ - google,cheza
+ - google,cheza-rev1
+ - google,cheza-rev2
- lenovo,yoga-c630
- lg,judyln
- lg,judyp
@@ -681,17 +774,24 @@ properties:
- oneplus,fajita
- qcom,sdm845-mtp
- shift,axolotl
+ - samsung,starqltechn
- samsung,w737
- sony,akari-row
- sony,akatsuki-row
- sony,apollo-row
- thundercomm,db845c
- xiaomi,beryllium
+ - xiaomi,beryllium-ebbg
- xiaomi,polaris
- const: qcom,sdm845
- items:
- enum:
+ - oneplus,billie2
+ - const: qcom,sm4250
+
+ - items:
+ - enum:
- sony,pdx201
- const: qcom,sm6125
@@ -702,6 +802,11 @@ properties:
- items:
- enum:
+ - sony,pdx225
+ - const: qcom,sm6375
+
+ - items:
+ - enum:
- fairphone,fp4
- const: qcom,sm7225
@@ -737,8 +842,129 @@ properties:
- qcom,sm8450-hdk
- qcom,sm8450-qrd
- sony,pdx223
+ - sony,pdx224
- const: qcom,sm8450
+ # Board compatibles go above
+
+ qcom,msm-id:
+ $ref: /schemas/types.yaml#/definitions/uint32-matrix
+ minItems: 1
+ maxItems: 8
+ items:
+ items:
+ - description: |
+ MSM chipset ID - an exact match value consisting of two bitfields::
+ - bits 0-15 - The unique MSM chipset ID
+ - bits 16-31 - Reserved; should be 0
+ - description: |
+ Hardware revision ID - a chipset specific 32-bit ID representing
+ the version of the chipset. It is best a match value - the
+ bootloader will look for the closest possible match.
+ deprecated: true
+ description:
+ The MSM chipset and hardware revision used Qualcomm bootloaders. It
+ can optionally be an array of these to indicate multiple hardware that
+ use the same device tree. It is expected that the bootloader will use
+ this information at boot-up to decide which device tree to use when given
+ multiple device trees, some of which may not be compatible with the
+ actual hardware. It is the bootloader's responsibility to pass the
+ correct device tree to the kernel.
+ The property is deprecated.
+
+ qcom,board-id:
+ $ref: /schemas/types.yaml#/definitions/uint32-matrix
+ minItems: 1
+ maxItems: 8
+ oneOf:
+ - items:
+ - items:
+ - description: |
+ Board ID consisting of three bitfields::
+ - bits 31-24 - Unused
+ - bits 23-16 - Platform Version Major
+ - bits 15-8 - Platform Version Minor
+ - bits 7-0 - Platform Type
+ Platform Type field is an exact match value. The
+ Platform Major/Minor field is a best match. The bootloader will
+ look for the closest possible match.
+ - description: |
+ Subtype ID unique to a Platform Type/Chipset ID. For a given
+ Platform Type, there will typically only be a single board and the
+ subtype_id will be 0. However in some cases board variants may
+ need to be distinguished by different subtype_id values.
+ - items:
+ # OnePlus uses a variant of board-id with four elements:
+ - items:
+ - const: 8
+ - const: 0
+ - description: OnePlus board ID
+ - description: OnePlus subtype ID
+ deprecated: true
+ description:
+ The board type and revision information. It can optionally be an array
+ of these to indicate multiple boards that use the same device tree. It
+ is expected that the bootloader will use this information at boot-up to
+ decide which device tree to use when given multiple device trees, some of
+ which may not be compatible with the actual hardware. It is the
+ bootloader's responsibility to pass the correct device tree to the
+ kernel
+ The property is deprecated.
+
+allOf:
+ # Explicit allow-list for older SoCs. The legacy properties are not allowed
+ # on newer SoCs.
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,apq8026
+ - qcom,apq8094
+ - qcom,apq8096
+ - qcom,msm8992
+ - qcom,msm8994
+ - qcom,msm8996
+ - qcom,msm8998
+ - qcom,sdm630
+ - qcom,sdm632
+ - qcom,sdm845
+ - qcom,sdx55
+ - qcom,sdx65
+ - qcom,sm6125
+ - qcom,sm6350
+ - qcom,sm7225
+ - qcom,sm8150
+ - qcom,sm8250
+ then:
+ properties:
+ qcom,board-id: true
+ qcom,msm-id: true
+ else:
+ properties:
+ qcom,board-id: false
+ qcom,msm-id: false
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - oneplus,cheeseburger
+ - oneplus,dumpling
+ - oneplus,enchilada
+ - oneplus,fajita
+ then:
+ properties:
+ qcom,board-id:
+ items:
+ minItems: 4
+ else:
+ properties:
+ qcom,board-id:
+ items:
+ maxItems: 2
+
additionalProperties: true
...
diff --git a/Documentation/devicetree/bindings/arm/rockchip.yaml b/Documentation/devicetree/bindings/arm/rockchip.yaml
index c6c69a4e3777..88ff4422a8c1 100644
--- a/Documentation/devicetree/bindings/arm/rockchip.yaml
+++ b/Documentation/devicetree/bindings/arm/rockchip.yaml
@@ -30,11 +30,26 @@ properties:
- const: amarula,vyasa-rk3288
- const: rockchip,rk3288
+ - description: Anbernic RG351M
+ items:
+ - const: anbernic,rg351m
+ - const: rockchip,rk3326
+
- description: Anbernic RG353P
items:
- const: anbernic,rg353p
- const: rockchip,rk3566
+ - description: Anbernic RG353V
+ items:
+ - const: anbernic,rg353v
+ - const: rockchip,rk3566
+
+ - description: Anbernic RG353VS
+ items:
+ - const: anbernic,rg353vs
+ - const: rockchip,rk3566
+
- description: Anbernic RG503
items:
- const: anbernic,rg503
@@ -468,6 +483,21 @@ properties:
- const: hardkernel,rk3326-odroid-go2
- const: rockchip,rk3326
+ - description: Hardkernel Odroid Go Advance Black Edition
+ items:
+ - const: hardkernel,rk3326-odroid-go2-v11
+ - const: rockchip,rk3326
+
+ - description: Hardkernel Odroid Go Super
+ items:
+ - const: hardkernel,rk3326-odroid-go3
+ - const: rockchip,rk3326
+
+ - description: Hardkernel Odroid M1
+ items:
+ - const: rockchip,rk3568-odroid-m1
+ - const: rockchip,rk3568
+
- description: Hugsun X99 TV Box
items:
- const: hugsun,x99
@@ -563,7 +593,9 @@ properties:
- description: Pine64 SoQuartz SoM
items:
- enum:
+ - pine64,soquartz-blade
- pine64,soquartz-cm4io
+ - pine64,soquartz-model-a
- const: pine64,soquartz
- const: rockchip,rk3566
@@ -709,6 +741,11 @@ properties:
- const: rockchip,rv1108-evb
- const: rockchip,rv1108
+ - description: Theobroma Systems PX30-uQ7 with Haikou baseboard
+ items:
+ - const: tsd,px30-ringneck-haikou
+ - const: rockchip,px30
+
- description: Theobroma Systems RK3368-uQ7 with Haikou baseboard
items:
- const: tsd,rk3368-lion-haikou
@@ -729,6 +766,11 @@ properties:
- const: zkmagic,a95x-z2
- const: rockchip,rk3318
+ - description: Rockchip RK3566 BOX Evaluation Demo board
+ items:
+ - const: rockchip,rk3566-box-demo
+ - const: rockchip,rk3566
+
- description: Rockchip RK3568 Evaluation board
items:
- const: rockchip,rk3568-evb1-v10
diff --git a/Documentation/devicetree/bindings/arm/socionext/uniphier.yaml b/Documentation/devicetree/bindings/arm/socionext/uniphier.yaml
index 8c0e91658474..c2cea1c90f3c 100644
--- a/Documentation/devicetree/bindings/arm/socionext/uniphier.yaml
+++ b/Documentation/devicetree/bindings/arm/socionext/uniphier.yaml
@@ -26,6 +26,12 @@ properties:
- socionext,uniphier-pro4-ref
- socionext,uniphier-pro4-sanji
- const: socionext,uniphier-pro4
+ - description: Pro5 SoC boards
+ items:
+ - enum:
+ - socionext,uniphier-pro5-epcore
+ - socionext,uniphier-pro5-proex
+ - const: socionext,uniphier-pro5
- description: sLD8 SoC boards
items:
- enum:
diff --git a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
index 4c605bccc474..44f5c5855af8 100644
--- a/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
+++ b/Documentation/devicetree/bindings/arm/stm32/stm32.yaml
@@ -59,6 +59,12 @@ properties:
- prt,prtt1s # Protonic PRTT1S
- const: st,stm32mp151
+ - description: DH STM32MP151 DHCOR SoM based Boards
+ items:
+ - const: dh,stm32mp151a-dhcor-testbench
+ - const: dh,stm32mp151a-dhcor-som
+ - const: st,stm32mp151
+
- description: DH STM32MP153 DHCOM SoM based Boards
items:
- const: dh,stm32mp153c-dhcom-drc02
diff --git a/Documentation/devicetree/bindings/arm/swir.txt b/Documentation/devicetree/bindings/arm/swir.txt
deleted file mode 100644
index 042be73a95d3..000000000000
--- a/Documentation/devicetree/bindings/arm/swir.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-Sierra Wireless Modules device tree bindings
---------------------------------------------
-
-Supported Modules :
- - WP8548 : Includes MDM9615 and PM8018 in a module
-
-Sierra Wireless modules shall have the following properties :
- Required root node property
- - compatible: "swir,wp8548" for the WP8548 CF3 Module
-
-Board compatible values:
- - "swir,mangoh-green-wp8548" for the mangOH green board with the WP8548 module
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra-ccplex-cluster.yaml b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra-ccplex-cluster.yaml
index 711bb4d08c60..869c266e7ebc 100644
--- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra-ccplex-cluster.yaml
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra-ccplex-cluster.yaml
@@ -47,5 +47,4 @@ examples:
compatible = "nvidia,tegra234-ccplex-cluster";
reg = <0x0e000000 0x5ffff>;
nvidia,bpmp = <&bpmp>;
- status = "okay";
};
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml
index 7fd8d47b1be4..4a00593b9f7f 100644
--- a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml
+++ b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.yaml
@@ -123,6 +123,33 @@ properties:
some PLLs, clocks and then brings up CPU0 for resuming the
system.
+ core-supply:
+ description:
+ Phandle to voltage regulator connected to the SoC Core power rail.
+
+ core-domain:
+ type: object
+ description: |
+ The vast majority of hardware blocks of Tegra SoC belong to a
+ Core power domain, which has a dedicated voltage rail that powers
+ the blocks.
+
+ properties:
+ operating-points-v2:
+ description:
+ Should contain level, voltages and opp-supported-hw property.
+ The supported-hw is a bitfield indicating SoC speedo or process
+ ID mask.
+
+ "#power-domain-cells":
+ const: 0
+
+ required:
+ - operating-points-v2
+ - "#power-domain-cells"
+
+ additionalProperties: false
+
i2c-thermtrip:
type: object
description:
@@ -300,33 +327,6 @@ patternProperties:
additionalProperties: false
- core-domain:
- type: object
- description: |
- The vast majority of hardware blocks of Tegra SoC belong to a
- Core power domain, which has a dedicated voltage rail that powers
- the blocks.
-
- properties:
- operating-points-v2:
- description:
- Should contain level, voltages and opp-supported-hw property.
- The supported-hw is a bitfield indicating SoC speedo or process
- ID mask.
-
- "#power-domain-cells":
- const: 0
-
- required:
- - operating-points-v2
- - "#power-domain-cells"
-
- additionalProperties: false
-
- core-supply:
- description:
- Phandle to voltage regulator connected to the SoC Core power rail.
-
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/arm/ti/k3.yaml b/Documentation/devicetree/bindings/arm/ti/k3.yaml
index 28b8232e1c5b..09e6845ff243 100644
--- a/Documentation/devicetree/bindings/arm/ti/k3.yaml
+++ b/Documentation/devicetree/bindings/arm/ti/k3.yaml
@@ -61,6 +61,7 @@ properties:
- const: ti,j721e
- items:
- enum:
+ - beagle,j721e-beagleboneai64
- ti,j721e-evm
- ti,j721e-sk
- const: ti,j721e
diff --git a/Documentation/devicetree/bindings/ata/ata-generic.yaml b/Documentation/devicetree/bindings/ata/ata-generic.yaml
new file mode 100644
index 000000000000..0697927f3d7e
--- /dev/null
+++ b/Documentation/devicetree/bindings/ata/ata-generic.yaml
@@ -0,0 +1,58 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/ata/ata-generic.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Generic Parallel ATA Controller
+
+maintainers:
+ - Linus Walleij <linus.walleij@linaro.org>
+
+description:
+ Generic Parallel ATA controllers supporting PIO modes only.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - arm,vexpress-cf
+ - fsl,mpc8349emitx-pata
+ - const: ata-generic
+
+ reg:
+ items:
+ - description: Command interface registers
+ - description: Control interface registers
+
+ reg-shift:
+ enum: [ 1, 2 ]
+
+ interrupts:
+ maxItems: 1
+
+ ata-generic,use16bit:
+ type: boolean
+ description: Use 16-bit accesses instead of 32-bit for data transfers
+
+ pio-mode:
+ description: Maximum ATA PIO transfer mode
+ $ref: /schemas/types.yaml#/definitions/uint32
+ maximum: 6
+ default: 0
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ compact-flash@1a000 {
+ compatible = "arm,vexpress-cf", "ata-generic";
+ reg = <0x1a000 0x100>,
+ <0x1a100 0xf00>;
+ reg-shift = <2>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/chrome/google,cros-ec-typec.yaml b/Documentation/devicetree/bindings/chrome/google,cros-ec-typec.yaml
index 50ebd8c57795..defcf1e12aa1 100644
--- a/Documentation/devicetree/bindings/chrome/google,cros-ec-typec.yaml
+++ b/Documentation/devicetree/bindings/chrome/google,cros-ec-typec.yaml
@@ -48,6 +48,7 @@ examples:
cros_ec: ec@0 {
compatible = "google,cros-ec-spi";
reg = <0>;
+ interrupts = <35 0>;
typec {
compatible = "google,cros-ec-typec";
diff --git a/Documentation/devicetree/bindings/chrome/google,cros-kbd-led-backlight.yaml b/Documentation/devicetree/bindings/chrome/google,cros-kbd-led-backlight.yaml
index 5b875af6a95a..40244d003c32 100644
--- a/Documentation/devicetree/bindings/chrome/google,cros-kbd-led-backlight.yaml
+++ b/Documentation/devicetree/bindings/chrome/google,cros-kbd-led-backlight.yaml
@@ -27,6 +27,7 @@ examples:
cros_ec: ec@0 {
compatible = "google,cros-ec-spi";
reg = <0>;
+ interrupts = <15 0>;
kbd-led-backlight {
compatible = "google,cros-kbd-led-backlight";
diff --git a/Documentation/devicetree/bindings/clock/fsl,imx8m-anatop.yaml b/Documentation/devicetree/bindings/clock/fsl,imx8m-anatop.yaml
new file mode 100644
index 000000000000..bbd22e95b319
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/fsl,imx8m-anatop.yaml
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/fsl,imx8m-anatop.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP i.MX8M Family Anatop Module
+
+maintainers:
+ - Peng Fan <peng.fan@nxp.com>
+
+description: |
+ NXP i.MX8M Family anatop PLL module which generates PLL to CCM root.
+
+properties:
+ compatible:
+ oneOf:
+ - enum:
+ - fsl,imx8mm-anatop
+ - fsl,imx8mq-anatop
+ - items:
+ - enum:
+ - fsl,imx8mn-anatop
+ - fsl,imx8mp-anatop
+ - const: fsl,imx8mm-anatop
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ '#clock-cells':
+ const: 1
+
+required:
+ - compatible
+ - reg
+ - '#clock-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ anatop: clock-controller@30360000 {
+ compatible = "fsl,imx8mn-anatop", "fsl,imx8mm-anatop";
+ reg = <0x30360000 0x10000>;
+ #clock-cells = <1>;
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/clock/ingenic,cgu.yaml b/Documentation/devicetree/bindings/clock/ingenic,cgu.yaml
index aa1df03ef4a6..df256ebcd366 100644
--- a/Documentation/devicetree/bindings/clock/ingenic,cgu.yaml
+++ b/Documentation/devicetree/bindings/clock/ingenic,cgu.yaml
@@ -22,6 +22,7 @@ select:
enum:
- ingenic,jz4740-cgu
- ingenic,jz4725b-cgu
+ - ingenic,jz4755-cgu
- ingenic,jz4760-cgu
- ingenic,jz4760b-cgu
- ingenic,jz4770-cgu
@@ -51,6 +52,7 @@ properties:
- enum:
- ingenic,jz4740-cgu
- ingenic,jz4725b-cgu
+ - ingenic,jz4755-cgu
- ingenic,jz4760-cgu
- ingenic,jz4760b-cgu
- ingenic,jz4770-cgu
diff --git a/Documentation/devicetree/bindings/clock/mediatek,mt8186-fhctl.yaml b/Documentation/devicetree/bindings/clock/mediatek,mt8186-fhctl.yaml
new file mode 100644
index 000000000000..cfd042ac1e14
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/mediatek,mt8186-fhctl.yaml
@@ -0,0 +1,53 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/mediatek,mt8186-fhctl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek frequency hopping and spread spectrum clocking control
+
+maintainers:
+ - Edward-JW Yang <edward-jw.yang@mediatek.com>
+
+description: |
+ Frequency hopping control (FHCTL) is a piece of hardware that control
+ some PLLs to adopt "hopping" mechanism to adjust their frequency.
+ Spread spectrum clocking (SSC) is another function provided by this hardware.
+
+properties:
+ compatible:
+ const: mediatek,mt8186-fhctl
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ description: Phandles of the PLL with FHCTL hardware capability.
+ minItems: 1
+ maxItems: 30
+
+ mediatek,hopping-ssc-percent:
+ description: The percentage of spread spectrum clocking for one PLL.
+ minItems: 1
+ maxItems: 30
+ items:
+ default: 0
+ minimum: 0
+ maximum: 8
+
+required:
+ - compatible
+ - reg
+ - clocks
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/mt8186-clk.h>
+ fhctl: fhctl@1000ce00 {
+ compatible = "mediatek,mt8186-fhctl";
+ reg = <0x1000ce00 0x200>;
+ clocks = <&apmixedsys CLK_APMIXED_MSDCPLL>;
+ mediatek,hopping-ssc-percent = <3>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt
index 958e0ad78c52..f7d347385b57 100644
--- a/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt
+++ b/Documentation/devicetree/bindings/clock/nvidia,tegra124-dfll.txt
@@ -136,7 +136,7 @@ clock@70110000 {
};
/* pinmux nodes added for completeness. Binding doc can be found in:
- * Documentation/devicetree/bindings/pinctrl/nvidia,tegra210-pinmux.txt
+ * Documentation/devicetree/bindings/pinctrl/nvidia,tegra210-pinmux.yaml
*/
pinmux: pinmux@700008d4 {
diff --git a/Documentation/devicetree/bindings/clock/pwm-clock.txt b/Documentation/devicetree/bindings/clock/pwm-clock.txt
deleted file mode 100644
index 83db876b3b90..000000000000
--- a/Documentation/devicetree/bindings/clock/pwm-clock.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-Binding for an external clock signal driven by a PWM pin.
-
-This binding uses the common clock binding[1] and the common PWM binding[2].
-
-[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
-[2] Documentation/devicetree/bindings/pwm/pwm.txt
-
-Required properties:
-- compatible : shall be "pwm-clock".
-- #clock-cells : from common clock binding; shall be set to 0.
-- pwms : from common PWM binding; this determines the clock frequency
- via the period given in the PWM specifier.
-
-Optional properties:
-- clock-output-names : From common clock binding.
-- clock-frequency : Exact output frequency, in case the PWM period
- is not exact but was rounded to nanoseconds.
-
-Example:
- clock {
- compatible = "pwm-clock";
- #clock-cells = <0>;
- clock-frequency = <25000000>;
- clock-output-names = "mipi_mclk";
- pwms = <&pwm2 0 40>; /* 1 / 40 ns = 25 MHz */
- };
diff --git a/Documentation/devicetree/bindings/clock/pwm-clock.yaml b/Documentation/devicetree/bindings/clock/pwm-clock.yaml
new file mode 100644
index 000000000000..f88ecb2995e0
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/pwm-clock.yaml
@@ -0,0 +1,45 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/pwm-clock.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: An external clock signal driven by a PWM pin.
+
+maintainers:
+ - Philipp Zabel <p.zabel@pengutronix.de>
+
+properties:
+ compatible:
+ const: pwm-clock
+
+ '#clock-cells':
+ const: 0
+
+ clock-frequency:
+ description: Exact output frequency, in case the PWM period is not exact
+ but was rounded to nanoseconds.
+
+ clock-output-names:
+ maxItems: 1
+
+ pwms:
+ maxItems: 1
+
+required:
+ - compatible
+ - '#clock-cells'
+ - pwms
+
+additionalProperties: false
+
+examples:
+ - |
+ clock {
+ compatible = "pwm-clock";
+ #clock-cells = <0>;
+ clock-frequency = <25000000>;
+ clock-output-names = "mipi_mclk";
+ pwms = <&pwm2 0 40>; /* 1 / 40 ns = 25 MHz */
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml b/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml
index fe6ca4f68bbe..525ebaa93c85 100644
--- a/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,a53pll.yaml
@@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/clock/qcom,a53pll.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm A53 PLL Binding
+title: Qualcomm A53 PLL clock
maintainers:
- Bjorn Andersson <andersson@kernel.org>
diff --git a/Documentation/devicetree/bindings/clock/qcom,a7pll.yaml b/Documentation/devicetree/bindings/clock/qcom,a7pll.yaml
index 0e96f693b050..809c34eb7d5a 100644
--- a/Documentation/devicetree/bindings/clock/qcom,a7pll.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,a7pll.yaml
@@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/clock/qcom,a7pll.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm A7 PLL Binding
+title: Qualcomm A7 PLL clock
maintainers:
- Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
diff --git a/Documentation/devicetree/bindings/clock/qcom,aoncc-sm8250.yaml b/Documentation/devicetree/bindings/clock/qcom,aoncc-sm8250.yaml
index c40a74b5d672..8b8932bd5a92 100644
--- a/Documentation/devicetree/bindings/clock/qcom,aoncc-sm8250.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,aoncc-sm8250.yaml
@@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/clock/qcom,aoncc-sm8250.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Clock bindings for LPASS Always ON Clock Controller on SM8250 SoCs
+title: LPASS Always ON Clock Controller on SM8250 SoCs
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
@@ -17,7 +17,7 @@ description: |
properties:
compatible:
- const: qcom,sm8250-lpass-aon
+ const: qcom,sm8250-lpass-aoncc
reg:
maxItems: 1
@@ -28,11 +28,13 @@ properties:
clocks:
items:
- description: LPASS Core voting clock
+ - description: LPASS Audio codec voting clock
- description: Glitch Free Mux register clock
clock-names:
items:
- const: core
+ - const: audio
- const: bus
required:
@@ -50,9 +52,10 @@ examples:
#include <dt-bindings/sound/qcom,q6afe.h>
clock-controller@3800000 {
#clock-cells = <1>;
- compatible = "qcom,sm8250-lpass-aon";
+ compatible = "qcom,sm8250-lpass-aoncc";
reg = <0x03380000 0x40000>;
clocks = <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
<&q6afecc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
- clock-names = "core", "bus";
+ clock-names = "core", "audio", "bus";
};
diff --git a/Documentation/devicetree/bindings/clock/qcom,audiocc-sm8250.yaml b/Documentation/devicetree/bindings/clock/qcom,audiocc-sm8250.yaml
index 915d76206ad0..cfca888f6014 100644
--- a/Documentation/devicetree/bindings/clock/qcom,audiocc-sm8250.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,audiocc-sm8250.yaml
@@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/clock/qcom,audiocc-sm8250.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Clock bindings for LPASS Audio Clock Controller on SM8250 SoCs
+title: LPASS Audio Clock Controller on SM8250 SoCs
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
@@ -28,11 +28,13 @@ properties:
clocks:
items:
- description: LPASS Core voting clock
+ - description: LPASS Audio codec voting clock
- description: Glitch Free Mux register clock
clock-names:
items:
- const: core
+ - const: audio
- const: bus
required:
@@ -53,6 +55,7 @@ examples:
compatible = "qcom,sm8250-lpass-audiocc";
reg = <0x03300000 0x30000>;
clocks = <&q6afecc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
<&q6afecc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
- clock-names = "core", "bus";
+ clock-names = "core", "audio", "bus";
};
diff --git a/Documentation/devicetree/bindings/clock/qcom,camcc-sm8250.yaml b/Documentation/devicetree/bindings/clock/qcom,camcc-sm8250.yaml
index 9f239c3960d1..93ec1f598e6e 100644
--- a/Documentation/devicetree/bindings/clock/qcom,camcc-sm8250.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,camcc-sm8250.yaml
@@ -4,16 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,camcc-sm8250.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Camera Clock & Reset Controller Binding for SM8250
+title: Qualcomm Camera Clock & Reset Controller on SM8250
maintainers:
- Jonathan Marek <jonathan@marek.ca>
description: |
- Qualcomm camera clock control module which supports the clocks, resets and
+ Qualcomm camera clock control module provides the clocks, resets and
power domains on SM8250.
- See also dt-bindings/clock/qcom,camcc-sm8250.h
+ See also:: include/dt-bindings/clock/qcom,camcc-sm8250.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,dispcc-sc8280xp.yaml b/Documentation/devicetree/bindings/clock/qcom,dispcc-sc8280xp.yaml
new file mode 100644
index 000000000000..28c13237059f
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,dispcc-sc8280xp.yaml
@@ -0,0 +1,97 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,dispcc-sc8280xp.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Display Clock & Reset Controller Binding for SC8280XP
+
+maintainers:
+ - Bjorn Andersson <bjorn.andersson@linaro.org>
+
+description: |
+ Qualcomm display clock control module which supports the clocks, resets and
+ power domains for the two MDSS instances on SC8280XP.
+
+ See also:
+ include/dt-bindings/clock/qcom,dispcc-sc8280xp.h
+
+properties:
+ compatible:
+ enum:
+ - qcom,sc8280xp-dispcc0
+ - qcom,sc8280xp-dispcc1
+
+ clocks:
+ items:
+ - description: AHB interface clock,
+ - description: SoC CXO clock
+ - description: SoC sleep clock
+ - description: DisplayPort 0 link clock
+ - description: DisplayPort 0 VCO div clock
+ - description: DisplayPort 1 link clock
+ - description: DisplayPort 1 VCO div clock
+ - description: DisplayPort 2 link clock
+ - description: DisplayPort 2 VCO div clock
+ - description: DisplayPort 3 link clock
+ - description: DisplayPort 3 VCO div clock
+ - description: DSI 0 PLL byte clock
+ - description: DSI 0 PLL DSI clock
+ - description: DSI 1 PLL byte clock
+ - description: DSI 1 PLL DSI clock
+
+ '#clock-cells':
+ const: 1
+
+ '#reset-cells':
+ const: 1
+
+ '#power-domain-cells':
+ const: 1
+
+ reg:
+ maxItems: 1
+
+ power-domains:
+ items:
+ - description: MMCX power domain
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - '#clock-cells'
+ - '#reset-cells'
+ - '#power-domain-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,gcc-sc8280xp.h>
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+ clock-controller@af00000 {
+ compatible = "qcom,sc8280xp-dispcc0";
+ reg = <0x0af00000 0x20000>;
+ clocks = <&gcc GCC_DISP_AHB_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>,
+ <&sleep_clk>,
+ <&mdss0_dp_phy0 0>,
+ <&mdss0_dp_phy0 1>,
+ <&mdss0_dp_phy1 0>,
+ <&mdss0_dp_phy1 1>,
+ <&mdss0_dp_phy2 0>,
+ <&mdss0_dp_phy2 1>,
+ <&mdss0_dp_phy3 0>,
+ <&mdss0_dp_phy3 1>,
+ <&mdss0_dsi0_phy 0>,
+ <&mdss0_dsi0_phy 1>,
+ <&mdss0_dsi1_phy 0>,
+ <&mdss0_dsi1_phy 1>;
+ power-domains = <&rpmhpd SC8280XP_MMCX>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6125.yaml b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6125.yaml
index 7a03ef19c947..8a210c4c5f82 100644
--- a/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6125.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6125.yaml
@@ -4,17 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,dispcc-sm6125.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Display Clock Controller Binding for SM6125
+title: Qualcomm Display Clock Controller on SM6125
maintainers:
- Martin Botka <martin.botka@somainline.org>
description: |
- Qualcomm display clock control module which supports the clocks and
- power domains on SM6125.
+ Qualcomm display clock control module provides the clocks and power domains
+ on SM6125.
- See also:
- dt-bindings/clock/qcom,dispcc-sm6125.h
+ See also:: include/dt-bindings/clock/qcom,dispcc-sm6125.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6350.yaml b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6350.yaml
index e706678b353a..8efac3fb159f 100644
--- a/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6350.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm6350.yaml
@@ -4,16 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,dispcc-sm6350.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Display Clock & Reset Controller Binding for SM6350
+title: Qualcomm Display Clock & Reset Controller on SM6350
maintainers:
- Konrad Dybcio <konrad.dybcio@somainline.org>
description: |
- Qualcomm display clock control module which supports the clocks, resets and
- power domains on SM6350.
+ Qualcomm display clock control module provides the clocks, resets and power
+ domains on SM6350.
- See also dt-bindings/clock/qcom,dispcc-sm6350.h.
+ See also:: include/dt-bindings/clock/qcom,dispcc-sm6350.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,dispcc-sm8x50.yaml b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm8x50.yaml
index 7a8d375e055e..d6774db257f0 100644
--- a/Documentation/devicetree/bindings/clock/qcom,dispcc-sm8x50.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm8x50.yaml
@@ -4,19 +4,19 @@
$id: http://devicetree.org/schemas/clock/qcom,dispcc-sm8x50.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Display Clock & Reset Controller Binding for SM8150/SM8250/SM8350
+title: Qualcomm Display Clock & Reset Controller on SM8150/SM8250/SM8350
maintainers:
- Jonathan Marek <jonathan@marek.ca>
description: |
- Qualcomm display clock control module which supports the clocks, resets and
- power domains on SM8150/SM8250/SM8350.
+ Qualcomm display clock control module provides the clocks, resets and power
+ domains on SM8150/SM8250/SM8350.
- See also:
- dt-bindings/clock/qcom,dispcc-sm8150.h
- dt-bindings/clock/qcom,dispcc-sm8250.h
- dt-bindings/clock/qcom,dispcc-sm8350.h
+ See also::
+ include/dt-bindings/clock/qcom,dispcc-sm8150.h
+ include/dt-bindings/clock/qcom,dispcc-sm8250.h
+ include/dt-bindings/clock/qcom,dispcc-sm8350.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-apq8064.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-apq8064.yaml
index 6b4efd64c154..09cd7a786871 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-apq8064.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-apq8064.yaml
@@ -4,22 +4,22 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-apq8064.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for APQ8064/MSM8960
-
-allOf:
- - $ref: qcom,gcc.yaml#
+title: Qualcomm Global Clock & Reset Controller on APQ8064/MSM8960
maintainers:
- Stephen Boyd <sboyd@kernel.org>
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on APQ8064.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on APQ8064.
- See also:
- - dt-bindings/clock/qcom,gcc-msm8960.h
- - dt-bindings/reset/qcom,gcc-msm8960.h
+ See also::
+ include/dt-bindings/clock/qcom,gcc-msm8960.h
+ include/dt-bindings/reset/qcom,gcc-msm8960.h
+
+allOf:
+ - $ref: qcom,gcc.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-apq8084.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-apq8084.yaml
index 397fb918e032..8ade176c24f4 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-apq8084.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-apq8084.yaml
@@ -4,19 +4,19 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-apq8084.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for APQ8084
+title: Qualcomm Global Clock & Reset Controller on APQ8084
maintainers:
- Stephen Boyd <sboyd@kernel.org>
- Taniya Das <quic_tdas@quicinc.com>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on APQ8084.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on APQ8084.
See also::
- - dt-bindings/clock/qcom,gcc-apq8084.h
- - dt-bindings/reset/qcom,gcc-apq8084.h
+ include/dt-bindings/clock/qcom,gcc-apq8084.h
+ include/dt-bindings/reset/qcom,gcc-apq8084.h
allOf:
- $ref: qcom,gcc.yaml#
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-ipq8064.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-ipq8064.yaml
index 9eb91dd22557..93f3084b97c1 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-ipq8064.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-ipq8064.yaml
@@ -4,21 +4,21 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-ipq8064.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for IPQ8064
-
-allOf:
- - $ref: qcom,gcc.yaml#
+title: Qualcomm Global Clock & Reset Controller on IPQ8064
maintainers:
- Ansuel Smith <ansuelsmth@gmail.com>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on IPQ8064.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on IPQ8064.
- See also:
- - dt-bindings/clock/qcom,gcc-ipq806x.h (qcom,gcc-ipq8064)
- - dt-bindings/reset/qcom,gcc-ipq806x.h (qcom,gcc-ipq8064)
+ See also::
+ include/dt-bindings/clock/qcom,gcc-ipq806x.h (qcom,gcc-ipq8064)
+ include/dt-bindings/reset/qcom,gcc-ipq806x.h (qcom,gcc-ipq8064)
+
+allOf:
+ - $ref: qcom,gcc.yaml#
properties:
compatible:
@@ -27,14 +27,18 @@ properties:
- const: syscon
clocks:
+ minItems: 2
items:
- description: PXO source
- description: CXO source
+ - description: PLL4 from LCC
clock-names:
+ minItems: 2
items:
- const: pxo
- const: cxo
+ - const: pll4
thermal-sensor:
type: object
@@ -51,13 +55,14 @@ unevaluatedProperties: false
examples:
- |
+ #include <dt-bindings/clock/qcom,lcc-ipq806x.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
gcc: clock-controller@900000 {
compatible = "qcom,gcc-ipq8064", "syscon";
reg = <0x00900000 0x4000>;
- clocks = <&pxo_board>, <&cxo_board>;
- clock-names = "pxo", "cxo";
+ clocks = <&pxo_board>, <&cxo_board>, <&lcc PLL4>;
+ clock-names = "pxo", "cxo", "pll4";
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-ipq8074.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-ipq8074.yaml
index 21470f52ce36..deef398a9872 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-ipq8074.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-ipq8074.yaml
@@ -4,47 +4,39 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-ipq8074.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Bindingfor IPQ8074
+title: Qualcomm Global Clock & Reset Controller on IPQ8074
maintainers:
- Stephen Boyd <sboyd@kernel.org>
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on IPQ8074.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on IPQ8074.
- See also:
- - dt-bindings/clock/qcom,gcc-ipq8074.h
+ See also:: include/dt-bindings/clock/qcom,gcc-ipq8074.h
+
+allOf:
+ - $ref: qcom,gcc.yaml#
properties:
compatible:
const: qcom,gcc-ipq8074
- '#clock-cells':
- const: 1
-
- '#power-domain-cells':
- const: 1
-
- '#reset-cells':
- const: 1
-
- reg:
- maxItems: 1
+ clocks:
+ items:
+ - description: board XO clock
+ - description: sleep clock
- protected-clocks:
- description:
- Protected clock specifier list as per common clock binding.
+ clock-names:
+ items:
+ - const: xo
+ - const: sleep_clk
required:
- compatible
- - reg
- - '#clock-cells'
- - '#power-domain-cells'
- - '#reset-cells'
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8660.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8660.yaml
index 09b2ea60d356..c9e985548621 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8660.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8660.yaml
@@ -4,22 +4,22 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-msm8660.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for MSM8660
+title: Qualcomm Global Clock & Reset Controller on MSM8660
maintainers:
- Stephen Boyd <sboyd@kernel.org>
- Taniya Das <quic_tdas@quicinc.com>
description: |
- Qualcomm global clock control module which supports the clocks and resets on
+ Qualcomm global clock control module provides the clocks and resets on
MSM8660
- See also:
- - dt-bindings/clock/qcom,gcc-msm8660.h
- - dt-bindings/reset/qcom,gcc-msm8660.h
+ See also::
+ include/dt-bindings/clock/qcom,gcc-msm8660.h
+ include/dt-bindings/reset/qcom,gcc-msm8660.h
allOf:
- - $ref: "qcom,gcc.yaml#"
+ - $ref: qcom,gcc.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8909.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8909.yaml
index 2272ea5f78d0..6279a59c2e20 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8909.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8909.yaml
@@ -4,17 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-msm8909.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for MSM8909
+title: Qualcomm Global Clock & Reset Controller on MSM8909
maintainers:
- Stephan Gerhold <stephan@gerhold.net>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on MSM8909.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on MSM8909.
- See also:
- - dt-bindings/clock/qcom,gcc-msm8909.h
+ See also:: include/dt-bindings/clock/qcom,gcc-msm8909.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8916.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8916.yaml
index 2ceb1e501ef9..ad84c0f7680b 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8916.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8916.yaml
@@ -4,21 +4,21 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-msm8916.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for MSM8916 and MSM8939
+title: Qualcomm Global Clock & Reset Controller on MSM8916 and MSM8939
maintainers:
- Stephen Boyd <sboyd@kernel.org>
- Taniya Das <quic_tdas@quicinc.com>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on MSM8916 or MSM8939.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on MSM8916 or MSM8939.
- See also:
- - dt-bindings/clock/qcom,gcc-msm8916.h
- - dt-bindings/clock/qcom,gcc-msm8939.h
- - dt-bindings/reset/qcom,gcc-msm8916.h
- - dt-bindings/reset/qcom,gcc-msm8939.h
+ See also::
+ include/dt-bindings/clock/qcom,gcc-msm8916.h
+ include/dt-bindings/clock/qcom,gcc-msm8939.h
+ include/dt-bindings/reset/qcom,gcc-msm8916.h
+ include/dt-bindings/reset/qcom,gcc-msm8939.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8974.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8974.yaml
new file mode 100644
index 000000000000..1927aecc86bc
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8974.yaml
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,gcc-msm8974.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Global Clock & Reset Controller on MSM8974 (including Pro) and MSM8226
+ Controller
+
+maintainers:
+ - Stephen Boyd <sboyd@kernel.org>
+ - Taniya Das <quic_tdas@quicinc.com>
+
+description: |
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on MSM8974 (all variants) and MSM8226.
+
+ See also::
+ include/dt-bindings/clock/qcom,gcc-msm8974.h (qcom,gcc-msm8226 and qcom,gcc-msm8974)
+ include/dt-bindings/reset/qcom,gcc-msm8974.h (qcom,gcc-msm8226 and qcom,gcc-msm8974)
+
+$ref: qcom,gcc.yaml#
+
+properties:
+ compatible:
+ enum:
+ - qcom,gcc-msm8226
+ - qcom,gcc-msm8974
+ - qcom,gcc-msm8974pro
+ - qcom,gcc-msm8974pro-ac
+
+ clocks:
+ items:
+ - description: XO source
+ - description: Sleep clock source
+
+ clock-names:
+ items:
+ - const: xo
+ - const: sleep_clk
+
+required:
+ - compatible
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ clock-controller@fc400000 {
+ compatible = "qcom,gcc-msm8974";
+ reg = <0x00100000 0x94000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+
+ clock-names = "xo", "sleep_clk";
+ clocks = <&xo_board>,
+ <&sleep_clk>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8976.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8976.yaml
index 4b7d69518371..d2186e25f55f 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8976.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8976.yaml
@@ -4,18 +4,17 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-msm8976.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for MSM8976
+title: Qualcomm Global Clock & Reset Controller on MSM8976
maintainers:
- Stephen Boyd <sboyd@kernel.org>
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on MSM8976.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on MSM8976.
- See also:
- - dt-bindings/clock/qcom,gcc-msm8976.h
+ See also:: include/dt-bindings/clock/qcom,gcc-msm8976.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8994.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8994.yaml
index 7b9fef6d9b23..8f0f20c1442a 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8994.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8994.yaml
@@ -4,17 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-msm8994.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for MSM8994
+title: Qualcomm Global Clock & Reset Controller on MSM8994
maintainers:
- Konrad Dybcio <konrad.dybcio@somainline.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on MSM8994 and MSM8992.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on MSM8994 and MSM8992.
- See also:
- - dt-bindings/clock/qcom,gcc-msm8994.h
+ See also:: include/dt-bindings/clock/qcom,gcc-msm8994.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8996.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8996.yaml
index dfc5165db9f1..f77036ace31b 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8996.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8996.yaml
@@ -4,18 +4,17 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-msm8996.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for MSM8996
+title: Qualcomm Global Clock & Reset Controller on MSM8996
maintainers:
- Stephen Boyd <sboyd@kernel.org>
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
+ Qualcomm global clock control module which provides the clocks, resets and
power domains on MSM8996.
- See also:
- - dt-bindings/clock/qcom,gcc-msm8996.h
+ See also:: include/dt-bindings/clock/qcom,gcc-msm8996.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8998.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8998.yaml
index 544a2335cf05..2d5355cf9def 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-msm8998.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-msm8998.yaml
@@ -4,18 +4,17 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-msm8998.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for MSM8998
+title: Qualcomm Global Clock & Reset Controller on MSM8998
maintainers:
- Stephen Boyd <sboyd@kernel.org>
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on MSM8998.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on MSM8998.
- See also:
- - dt-bindings/clock/qcom,gcc-msm8998.h
+ See also:: include/dt-bindings/clock/qcom,gcc-msm8998.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-other.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-other.yaml
index 76988e04c7db..2e8acca64af1 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-other.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-other.yaml
@@ -4,30 +4,27 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-other.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding
+title: Qualcomm Global Clock & Reset Controller
maintainers:
- Stephen Boyd <sboyd@kernel.org>
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains.
-
- See also:
- - dt-bindings/clock/qcom,gcc-ipq4019.h
- - dt-bindings/clock/qcom,gcc-ipq6018.h
- - dt-bindings/reset/qcom,gcc-ipq6018.h
- - dt-bindings/clock/qcom,gcc-msm8953.h
- - dt-bindings/clock/qcom,gcc-msm8974.h (qcom,gcc-msm8226 and qcom,gcc-msm8974)
- - dt-bindings/reset/qcom,gcc-msm8974.h (qcom,gcc-msm8226 and qcom,gcc-msm8974)
- - dt-bindings/clock/qcom,gcc-mdm9607.h
- - dt-bindings/clock/qcom,gcc-mdm9615.h
- - dt-bindings/reset/qcom,gcc-mdm9615.h
- - dt-bindings/clock/qcom,gcc-sdm660.h (qcom,gcc-sdm630 and qcom,gcc-sdm660)
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains.
+
+ See also::
+ include/dt-bindings/clock/qcom,gcc-ipq4019.h
+ include/dt-bindings/clock/qcom,gcc-ipq6018.h
+ include/dt-bindings/reset/qcom,gcc-ipq6018.h
+ include/dt-bindings/clock/qcom,gcc-msm8953.h
+ include/dt-bindings/clock/qcom,gcc-mdm9607.h
+ include/dt-bindings/clock/qcom,gcc-mdm9615.h
+ include/dt-bindings/reset/qcom,gcc-mdm9615.h
allOf:
- - $ref: "qcom,gcc.yaml#"
+ - $ref: qcom,gcc.yaml#
properties:
compatible:
@@ -35,14 +32,8 @@ properties:
- qcom,gcc-ipq4019
- qcom,gcc-ipq6018
- qcom,gcc-mdm9607
- - qcom,gcc-msm8226
- qcom,gcc-msm8953
- - qcom,gcc-msm8974
- - qcom,gcc-msm8974pro
- - qcom,gcc-msm8974pro-ac
- qcom,gcc-mdm9615
- - qcom,gcc-sdm630
- - qcom,gcc-sdm660
required:
- compatible
@@ -50,10 +41,9 @@ required:
unevaluatedProperties: false
examples:
- # Example for GCC for MSM8974:
- |
clock-controller@900000 {
- compatible = "qcom,gcc-msm8974";
+ compatible = "qcom,gcc-mdm9607";
reg = <0x900000 0x4000>;
#clock-cells = <1>;
#reset-cells = <1>;
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-qcm2290.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-qcm2290.yaml
index aec37e3f5e30..c9bec4656f6e 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-qcm2290.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-qcm2290.yaml
@@ -4,17 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-qcm2290.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for QCM2290
+title: Qualcomm Global Clock & Reset Controller on QCM2290
maintainers:
- Shawn Guo <shawn.guo@linaro.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets
- and power domains on QCM2290.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on QCM2290.
- See also:
- - dt-bindings/clock/qcom,gcc-qcm2290.h
+ See also:: include/dt-bindings/clock/qcom,gcc-qcm2290.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-qcs404.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-qcs404.yaml
index ce06f3f8c3e3..dca5775f79a4 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-qcs404.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-qcs404.yaml
@@ -4,18 +4,17 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-qcs404.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Bindingfor QCS404
+title: Qualcomm Global Clock & Reset Controller on QCS404
maintainers:
- Stephen Boyd <sboyd@kernel.org>
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on QCS404.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on QCS404.
- See also:
- - dt-bindings/clock/qcom,gcc-qcs404.h
+ See also:: include/dt-bindings/clock/qcom,gcc-qcs404.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sc7180.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sc7180.yaml
index e4d490e65d14..06dce0c6b7d0 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-sc7180.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sc7180.yaml
@@ -4,18 +4,17 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-sc7180.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for SC7180
+title: Qualcomm Global Clock & Reset Controller on SC7180
maintainers:
- Stephen Boyd <sboyd@kernel.org>
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on SC7180.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on SC7180.
- See also:
- - dt-bindings/clock/qcom,gcc-sc7180.h
+ See also:: include/dt-bindings/clock/qcom,gcc-sc7180.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sc7280.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sc7280.yaml
index ea61367e5abc..947b47168cec 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-sc7280.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sc7280.yaml
@@ -4,17 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-sc7280.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for SC7280
+title: Qualcomm Global Clock & Reset Controller on SC7280
maintainers:
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on SC7280.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on SC7280.
- See also:
- - dt-bindings/clock/qcom,gcc-sc7280.h
+ See also:: include/dt-bindings/clock/qcom,gcc-sc7280.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sc8180x.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sc8180x.yaml
index 30b5d1215fa8..6c4846b34e4b 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-sc8180x.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sc8180x.yaml
@@ -4,17 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-sc8180x.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for SC8180x
+title: Qualcomm Global Clock & Reset Controller on SC8180x
maintainers:
- Bjorn Andersson <bjorn.andersson@linaro.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on SC8180x.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on SC8180x.
- See also:
- - dt-bindings/clock/qcom,gcc-sc8180x.h
+ See also:: include/dt-bindings/clock/qcom,gcc-sc8180x.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sc8280xp.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sc8280xp.yaml
index b1bf768530a3..c9d8e436d73a 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-sc8280xp.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sc8280xp.yaml
@@ -4,17 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-sc8280xp.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for SC8280xp
+title: Qualcomm Global Clock & Reset Controller on SC8280xp
maintainers:
- Bjorn Andersson <bjorn.andersson@linaro.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
+ Qualcomm global clock control module provides the clocks, resets and
power domains on SC8280xp.
- See also:
- - include/dt-bindings/clock/qcom,gcc-sc8280xp.h
+ See also:: include/dt-bindings/clock/qcom,gcc-sc8280xp.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sdm660.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sdm660.yaml
new file mode 100644
index 000000000000..52e7412aace5
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sdm660.yaml
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,gcc-sdm660.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SDM660/SDM630/SDM636 Global Clock & Reset Controller
+
+maintainers:
+ - Stephen Boyd <sboyd@kernel.org>
+ - Taniya Das <quic_tdas@quicinc.com>
+
+description: |
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on SDM630, SDM636 and SDM660
+
+ See also::
+ include/dt-bindings/clock/qcom,gcc-sdm660.h (qcom,gcc-sdm630 and qcom,gcc-sdm660)
+
+$ref: qcom,gcc.yaml#
+
+properties:
+ compatible:
+ enum:
+ - qcom,gcc-sdm630
+ - qcom,gcc-sdm660
+
+ clocks:
+ items:
+ - description: XO source
+ - description: Sleep clock source
+
+ clock-names:
+ items:
+ - const: xo
+ - const: sleep_clk
+
+ power-domains:
+ maxItems: 1
+
+required:
+ - compatible
+
+unevaluatedProperties: false
+
+examples:
+ # Example for GCC for SDM660:
+ - |
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ clock-controller@100000 {
+ compatible = "qcom,gcc-sdm660";
+ reg = <0x00100000 0x94000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+
+ clock-names = "xo", "sleep_clk";
+ clocks = <&xo_board>,
+ <&sleep_clk>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sdm845.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sdm845.yaml
index e169d46c78f8..68e1b7822fe0 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-sdm845.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sdm845.yaml
@@ -4,18 +4,17 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-sdm845.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding
+title: Qualcomm Global Clock & Reset Controller on SDM670 and SDM845
maintainers:
- Stephen Boyd <sboyd@kernel.org>
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on SDM845
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on SDM670 and SDM845
- See also:
- - dt-bindings/clock/qcom,gcc-sdm845.h
+ See also:: include/dt-bindings/clock/qcom,gcc-sdm845.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sdx55.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sdx55.yaml
index 13ffa16e0833..68d3099c96ae 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-sdx55.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sdx55.yaml
@@ -4,18 +4,17 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-sdx55.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for SDX55
+title: Qualcomm Global Clock & Reset Controller on SDX55
maintainers:
- Vinod Koul <vkoul@kernel.org>
- Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
+ Qualcomm global clock control module provides the clocks, resets and
power domains on SDX55
- See also:
- - dt-bindings/clock/qcom,gcc-sdx55.h
+ See also:: include/dt-bindings/clock/qcom,gcc-sdx55.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sdx65.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sdx65.yaml
index 8a1419c4d465..ba62baab916c 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-sdx65.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sdx65.yaml
@@ -4,17 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-sdx65.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for SDX65
+title: Qualcomm Global Clock & Reset Controller on SDX65
maintainers:
- Vamsi krishna Lanka <quic_vamslank@quicinc.com>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on SDX65
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on SDX65
- See also:
- - dt-bindings/clock/qcom,gcc-sdx65.h
+ See also:: include/dt-bindings/clock/qcom,gcc-sdx65.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm6115.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6115.yaml
index bb81a27a1b16..a5ad0a3da397 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-sm6115.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6115.yaml
@@ -4,17 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-sm6115.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for SM6115 and SM4250
+title: Qualcomm Global Clock & Reset Controller on SM6115 and SM4250
maintainers:
- Iskren Chernev <iskren.chernev@gmail.com>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on SM4250/6115.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on SM4250/6115.
- See also:
- - dt-bindings/clock/qcom,gcc-sm6115.h
+ See also:: include/dt-bindings/clock/qcom,gcc-sm6115.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm6125.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6125.yaml
index 03e84e15815c..8e37623788bd 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-sm6125.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6125.yaml
@@ -4,17 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-sm6125.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for SM6125
+title: Qualcomm Global Clock & Reset Controller on SM6125
maintainers:
- Konrad Dybcio <konrad.dybcio@somainline.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on SM6125.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on SM6125.
- See also:
- - dt-bindings/clock/qcom,gcc-sm6125.h
+ See also:: include/dt-bindings/clock/qcom,gcc-sm6125.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm6350.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6350.yaml
index cbe98c01c085..d1b26ab48eaf 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-sm6350.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm6350.yaml
@@ -4,17 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-sm6350.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for SM6350
+title: Qualcomm Global Clock & Reset Controller on SM6350
maintainers:
- Konrad Dybcio <konrad.dybcio@somainline.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on SM6350.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on SM6350.
- See also:
- - dt-bindings/clock/qcom,gcc-sm6350.h
+ See also:: include/dt-bindings/clock/qcom,gcc-sm6350.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8150.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8150.yaml
index 0333ccb07d8d..3ea0ff37a4cb 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8150.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8150.yaml
@@ -4,18 +4,17 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-sm8150.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for SM8150
+title: Qualcomm Global Clock & Reset Controller on SM8150
maintainers:
- Stephen Boyd <sboyd@kernel.org>
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on SM8150.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on SM8150.
- See also:
- - dt-bindings/clock/qcom,gcc-sm8150.h
+ See also:: include/dt-bindings/clock/qcom,gcc-sm8150.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8250.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8250.yaml
index 4e2a9cac0a91..b752542ee20c 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8250.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8250.yaml
@@ -4,18 +4,17 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-sm8250.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for SM8250
+title: Qualcomm Global Clock & Reset Controller on SM8250
maintainers:
- Stephen Boyd <sboyd@kernel.org>
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on SM8250.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on SM8250.
- See also:
- - dt-bindings/clock/qcom,gcc-sm8250.h
+ See also:: include/dt-bindings/clock/qcom,gcc-sm8250.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8350.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8350.yaml
index 3edbeca70a9c..703d9e075247 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8350.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8350.yaml
@@ -4,17 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-sm8350.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for SM8350
+title: Qualcomm Global Clock & Reset Controller on SM8350
maintainers:
- Vinod Koul <vkoul@kernel.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on SM8350.
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on SM8350.
- See also:
- - dt-bindings/clock/qcom,gcc-sm8350.h
+ See also:: include/dt-bindings/clock/qcom,gcc-sm8350.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8450.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8450.yaml
index 102ce6862e24..9a31981fbeb2 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc-sm8450.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc-sm8450.yaml
@@ -4,17 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc-sm8450.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for SM8450
+title: Qualcomm Global Clock & Reset Controller on SM8450
maintainers:
- Vinod Koul <vkoul@kernel.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on SM8450
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on SM8450
- See also:
- - dt-bindings/clock/qcom,gcc-sm8450.h
+ See also:: include/dt-bindings/clock/qcom,gcc-sm8450.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,gcc.yaml
index 2ed27a2ef445..1ab416c83c8d 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc.yaml
@@ -4,15 +4,15 @@
$id: http://devicetree.org/schemas/clock/qcom,gcc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding Common Bindings
+title: Qualcomm Global Clock & Reset Controller Common Bindings
maintainers:
- Stephen Boyd <sboyd@kernel.org>
- Taniya Das <tdas@codeaurora.org>
description: |
- Common bindings for Qualcomm global clock control module which supports
- the clocks, resets and power domains.
+ Common bindings for Qualcomm global clock control module providing the
+ clocks, resets and power domains.
properties:
'#clock-cells':
diff --git a/Documentation/devicetree/bindings/clock/qcom,gpucc-sdm660.yaml b/Documentation/devicetree/bindings/clock/qcom,gpucc-sdm660.yaml
index 3f70eb59aae3..0518ea963cdd 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gpucc-sdm660.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gpucc-sdm660.yaml
@@ -4,13 +4,13 @@
$id: http://devicetree.org/schemas/clock/qcom,gpucc-sdm660.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Graphics Clock & Reset Controller Binding for SDM630 and SDM660
+title: Qualcomm Graphics Clock & Reset Controller on SDM630 and SDM660
maintainers:
- AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
description: |
- Qualcomm graphics clock control module which supports the clocks, resets and
+ Qualcomm graphics clock control module provides the clocks, resets and
power domains on SDM630 and SDM660.
See also dt-bindings/clock/qcom,gpucc-sdm660.h.
diff --git a/Documentation/devicetree/bindings/clock/qcom,gpucc-sm8350.yaml b/Documentation/devicetree/bindings/clock/qcom,gpucc-sm8350.yaml
index 0a0546c079a9..fb7ae3d18503 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gpucc-sm8350.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gpucc-sm8350.yaml
@@ -4,17 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,gpucc-sm8350.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Graphics Clock & Reset Controller Binding
+title: Qualcomm Graphics Clock & Reset Controller on SM8350
maintainers:
- Robert Foss <robert.foss@linaro.org>
description: |
- Qualcomm graphics clock control module which supports the clocks, resets and
- power domains on Qualcomm SoCs.
+ Qualcomm graphics clock control module provides the clocks, resets and power
+ domains on Qualcomm SoCs.
- See also:
- dt-bindings/clock/qcom,gpucc-sm8350.h
+ See also:: include/dt-bindings/clock/qcom,gpucc-sm8350.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml
index a7d0af1bd9e0..7256c438a4cf 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,gpucc.yaml
@@ -4,23 +4,23 @@
$id: http://devicetree.org/schemas/clock/qcom,gpucc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Graphics Clock & Reset Controller Binding
+title: Qualcomm Graphics Clock & Reset Controller
maintainers:
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm graphics clock control module which supports the clocks, resets and
- power domains on Qualcomm SoCs.
+ Qualcomm graphics clock control module provides the clocks, resets and power
+ domains on Qualcomm SoCs.
- See also:
- dt-bindings/clock/qcom,gpucc-sdm845.h
- dt-bindings/clock/qcom,gpucc-sc7180.h
- dt-bindings/clock/qcom,gpucc-sc7280.h
- dt-bindings/clock/qcom,gpucc-sc8280xp.h
- dt-bindings/clock/qcom,gpucc-sm6350.h
- dt-bindings/clock/qcom,gpucc-sm8150.h
- dt-bindings/clock/qcom,gpucc-sm8250.h
+ See also::
+ include/dt-bindings/clock/qcom,gpucc-sdm845.h
+ include/dt-bindings/clock/qcom,gpucc-sc7180.h
+ include/dt-bindings/clock/qcom,gpucc-sc7280.h
+ include/dt-bindings/clock/qcom,gpucc-sc8280xp.h
+ include/dt-bindings/clock/qcom,gpucc-sm6350.h
+ include/dt-bindings/clock/qcom,gpucc-sm8150.h
+ include/dt-bindings/clock/qcom,gpucc-sm8250.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,lcc.txt b/Documentation/devicetree/bindings/clock/qcom,lcc.txt
deleted file mode 100644
index a3c78aa88038..000000000000
--- a/Documentation/devicetree/bindings/clock/qcom,lcc.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-Qualcomm LPASS Clock & Reset Controller Binding
-------------------------------------------------
-
-Required properties :
-- compatible : shall contain only one of the following:
-
- "qcom,lcc-msm8960"
- "qcom,lcc-apq8064"
- "qcom,lcc-ipq8064"
- "qcom,lcc-mdm9615"
-
-- reg : shall contain base register location and length
-- #clock-cells : shall contain 1
-- #reset-cells : shall contain 1
-
-Example:
- clock-controller@28000000 {
- compatible = "qcom,lcc-ipq8064";
- reg = <0x28000000 0x1000>;
- #clock-cells = <1>;
- #reset-cells = <1>;
- };
diff --git a/Documentation/devicetree/bindings/clock/qcom,lcc.yaml b/Documentation/devicetree/bindings/clock/qcom,lcc.yaml
new file mode 100644
index 000000000000..8c783823e93c
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,lcc.yaml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: GPL-2.0-only
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,lcc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm LPASS Clock & Reset Controller
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+
+properties:
+ compatible:
+ enum:
+ - qcom,lcc-apq8064
+ - qcom,lcc-ipq8064
+ - qcom,lcc-mdm9615
+ - qcom,lcc-msm8960
+
+ clocks:
+ maxItems: 8
+
+ clock-names:
+ maxItems: 8
+
+ '#clock-cells':
+ const: 1
+
+ '#reset-cells':
+ const: 1
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - '#clock-cells'
+ - '#reset-cells'
+
+additionalProperties: false
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,lcc-apq8064
+ - qcom,lcc-msm8960
+ then:
+ properties:
+ clocks:
+ items:
+ - description: Board PXO source
+ - description: PLL 4 Vote clock
+ - description: MI2S codec clock
+ - description: Mic I2S codec clock
+ - description: Mic I2S spare clock
+ - description: Speaker I2S codec clock
+ - description: Speaker I2S spare clock
+ - description: PCM codec clock
+
+ clock-names:
+ items:
+ - const: pxo
+ - const: pll4_vote
+ - const: mi2s_codec_clk
+ - const: codec_i2s_mic_codec_clk
+ - const: spare_i2s_mic_codec_clk
+ - const: codec_i2s_spkr_codec_clk
+ - const: spare_i2s_spkr_codec_clk
+ - const: pcm_codec_clk
+
+ required:
+ - clocks
+ - clock-names
+
+examples:
+ - |
+ clock-controller@28000000 {
+ compatible = "qcom,lcc-ipq8064";
+ reg = <0x28000000 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/qcom,lpasscc.txt b/Documentation/devicetree/bindings/clock/qcom,lpasscc.txt
deleted file mode 100644
index b9e9787045b9..000000000000
--- a/Documentation/devicetree/bindings/clock/qcom,lpasscc.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-Qualcomm LPASS Clock Controller Binding
------------------------------------------------
-
-Required properties :
-- compatible : shall contain "qcom,sdm845-lpasscc"
-- #clock-cells : from common clock binding, shall contain 1.
-- reg : shall contain base register address and size,
- in the order
- Index-0 maps to LPASS_CC register region
- Index-1 maps to LPASS_QDSP6SS register region
-
-Optional properties :
-- reg-names : register names of LPASS domain
- "cc", "qdsp6ss".
-
-Example:
-
-The below node has to be defined in the cases where the LPASS peripheral loader
-would bring the subsystem out of reset.
-
- lpasscc: clock-controller@17014000 {
- compatible = "qcom,sdm845-lpasscc";
- reg = <0x17014000 0x1f004>, <0x17300000 0x200>;
- reg-names = "cc", "qdsp6ss";
- #clock-cells = <1>;
- };
diff --git a/Documentation/devicetree/bindings/clock/qcom,mmcc.yaml b/Documentation/devicetree/bindings/clock/qcom,mmcc.yaml
index 03faab5b6a41..e6d17426e903 100644
--- a/Documentation/devicetree/bindings/clock/qcom,mmcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,mmcc.yaml
@@ -4,14 +4,14 @@
$id: http://devicetree.org/schemas/clock/qcom,mmcc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Multimedia Clock & Reset Controller Binding
+title: Qualcomm Multimedia Clock & Reset Controller
maintainers:
- Jeffrey Hugo <quic_jhugo@quicinc.com>
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm multimedia clock control module which supports the clocks, resets and
+ Qualcomm multimedia clock control module provides the clocks, resets and
power domains.
properties:
@@ -104,6 +104,44 @@ allOf:
compatible:
contains:
enum:
+ - qcom,mmcc-msm8974
+ then:
+ properties:
+ clocks:
+ items:
+ - description: Board XO source
+ - description: MMSS GPLL0 voted clock
+ - description: GPLL0 voted clock
+ - description: GPLL1 voted clock
+ - description: GFX3D clock source
+ - description: DSI phy instance 0 dsi clock
+ - description: DSI phy instance 0 byte clock
+ - description: DSI phy instance 1 dsi clock
+ - description: DSI phy instance 1 byte clock
+ - description: HDMI phy PLL clock
+ - description: eDP phy PLL link clock
+ - description: eDP phy PLL vco clock
+
+ clock-names:
+ items:
+ - const: xo
+ - const: mmss_gpll0_vote
+ - const: gpll0_vote
+ - const: gpll1_vote
+ - const: gfx3d_clk_src
+ - const: dsi0pll
+ - const: dsi0pllbyte
+ - const: dsi1pll
+ - const: dsi1pllbyte
+ - const: hdmipll
+ - const: edp_link_clk
+ - const: edp_vco_div
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
- qcom,mmcc-msm8994
- qcom,mmcc-msm8998
- qcom,mmcc-sdm630
diff --git a/Documentation/devicetree/bindings/clock/qcom,msm8998-gpucc.yaml b/Documentation/devicetree/bindings/clock/qcom,msm8998-gpucc.yaml
index d747bb58f0a7..2d8897991663 100644
--- a/Documentation/devicetree/bindings/clock/qcom,msm8998-gpucc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,msm8998-gpucc.yaml
@@ -4,16 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,msm8998-gpucc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Graphics Clock & Reset Controller Binding for MSM8998
+title: Qualcomm Graphics Clock & Reset Controller on MSM8998
maintainers:
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm graphics clock control module which supports the clocks, resets and
- power domains on MSM8998.
+ Qualcomm graphics clock control module provides the clocks, resets and power
+ domains on MSM8998.
- See also dt-bindings/clock/qcom,gpucc-msm8998.h.
+ See also:: include/dt-bindings/clock/qcom,gpucc-msm8998.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,q6sstopcc.yaml b/Documentation/devicetree/bindings/clock/qcom,q6sstopcc.yaml
index bbaaf1e2a203..03fa30fe9253 100644
--- a/Documentation/devicetree/bindings/clock/qcom,q6sstopcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,q6sstopcc.yaml
@@ -11,7 +11,7 @@ maintainers:
properties:
compatible:
- const: "qcom,qcs404-q6sstopcc"
+ const: qcom,qcs404-q6sstopcc
reg:
items:
diff --git a/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml
index 973e408c6268..4a00f2d41684 100644
--- a/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,qcm2290-dispcc.yaml
@@ -4,16 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,qcm2290-dispcc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Display Clock & Reset Controller Binding for qcm2290
+title: Qualcomm Display Clock & Reset Controller on QCM2290
maintainers:
- Loic Poulain <loic.poulain@linaro.org>
description: |
- Qualcomm display clock control module which supports the clocks, resets and
- power domains on qcm2290.
+ Qualcomm display clock control module provides the clocks, resets and power
+ domains on qcm2290.
- See also dt-bindings/clock/qcom,dispcc-qcm2290.h.
+ See also:: include/dt-bindings/clock/qcom,dispcc-qcm2290.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml
index 437a34b930e3..fccb91e78e49 100644
--- a/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,rpmhcc.yaml
@@ -17,6 +17,7 @@ description: |
properties:
compatible:
enum:
+ - qcom,qdu1000-rpmh-clk
- qcom,sc7180-rpmh-clk
- qcom,sc7280-rpmh-clk
- qcom,sc8180x-rpmh-clk
diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7180-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7180-camcc.yaml
index f49027edfc44..098c8acf4bad 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sc7180-camcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sc7180-camcc.yaml
@@ -4,17 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,sc7180-camcc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Camera Clock & Reset Controller Binding for SC7180
+title: Qualcomm Camera Clock & Reset Controller on SC7180
maintainers:
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm camera clock control module which supports the clocks, resets and
- power domains on SC7180.
+ Qualcomm camera clock control module provides the clocks, resets and power
+ domains on SC7180.
- See also:
- - dt-bindings/clock/qcom,camcc-sc7180.h
+ See also:: include/dt-bindings/clock/qcom,camcc-sc7180.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7180-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7180-dispcc.yaml
index e94847f92770..95ad16d0abc3 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sc7180-dispcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sc7180-dispcc.yaml
@@ -4,16 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,sc7180-dispcc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Display Clock & Reset Controller Binding for SC7180
+title: Qualcomm Display Clock & Reset Controller on SC7180
maintainers:
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm display clock control module which supports the clocks, resets and
- power domains on SC7180.
+ Qualcomm display clock control module provides the clocks, resets and power
+ domains on SC7180.
- See also dt-bindings/clock/qcom,dispcc-sc7180.h.
+ See also:: include/dt-bindings/clock/qcom,dispcc-sc7180.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7180-lpasscorecc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7180-lpasscorecc.yaml
index c54172fbf29f..f297694ef8b8 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sc7180-lpasscorecc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sc7180-lpasscorecc.yaml
@@ -4,17 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,sc7180-lpasscorecc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm LPASS Core Clock Controller Binding for SC7180
+title: Qualcomm LPASS Core Clock Controller on SC7180
maintainers:
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm LPASS core clock control module which supports the clocks and
- power domains on SC7180.
+ Qualcomm LPASS core clock control module provides the clocks and power
+ domains on SC7180.
- See also:
- - dt-bindings/clock/qcom,lpasscorecc-sc7180.h
+ See also:: include/dt-bindings/clock/qcom,lpasscorecc-sc7180.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7180-mss.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7180-mss.yaml
index 970030986a86..1e856a8a996e 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sc7180-mss.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sc7180-mss.yaml
@@ -4,16 +4,15 @@
$id: http://devicetree.org/schemas/clock/qcom,sc7180-mss.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Modem Clock Controller Binding for SC7180
+title: Qualcomm Modem Clock Controller on SC7180
maintainers:
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm modem clock control module which supports the clocks on SC7180.
+ Qualcomm modem clock control module provides the clocks on SC7180.
- See also:
- - dt-bindings/clock/qcom,mss-sc7180.h
+ See also:: include/dt-bindings/clock/qcom,mss-sc7180.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7280-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7280-camcc.yaml
index f27ca6f03ffa..b60adbad4590 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sc7280-camcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sc7280-camcc.yaml
@@ -4,16 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,sc7280-camcc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Camera Clock & Reset Controller Binding for SC7280
+title: Qualcomm Camera Clock & Reset Controller on SC7280
maintainers:
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm camera clock control module which supports the clocks, resets and
+ Qualcomm camera clock control module provides the clocks, resets and
power domains on SC7280.
- See also dt-bindings/clock/qcom,camcc-sc7280.h
+ See also:: include/dt-bindings/clock/qcom,camcc-sc7280.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7280-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7280-dispcc.yaml
index 2178666fb697..cfe6594a0a6b 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sc7280-dispcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sc7280-dispcc.yaml
@@ -4,16 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,sc7280-dispcc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Display Clock & Reset Controller Binding for SC7280
+title: Qualcomm Display Clock & Reset Controller on SC7280
maintainers:
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm display clock control module which supports the clocks, resets and
- power domains on SC7280.
+ Qualcomm display clock control module provides the clocks, resets and power
+ domains on SC7280.
- See also dt-bindings/clock/qcom,dispcc-sc7280.h.
+ See also:: include/dt-bindings/clock/qcom,dispcc-sc7280.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7280-lpasscc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7280-lpasscc.yaml
index 633887dc2f8a..6151fdebbff8 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sc7280-lpasscc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sc7280-lpasscc.yaml
@@ -4,17 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,sc7280-lpasscc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm LPASS Core Clock Controller Binding for SC7280
+title: Qualcomm LPASS Core Clock Controller on SC7280
maintainers:
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm LPASS core clock control module which supports the clocks and
- power domains on SC7280.
+ Qualcomm LPASS core clock control module provides the clocks and power
+ domains on SC7280.
- See also:
- - dt-bindings/clock/qcom,lpass-sc7280.h
+ See also:: include/dt-bindings/clock/qcom,lpass-sc7280.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7280-lpasscorecc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7280-lpasscorecc.yaml
index f50e284e5f46..447cdc447a0c 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sc7280-lpasscorecc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sc7280-lpasscorecc.yaml
@@ -4,18 +4,18 @@
$id: http://devicetree.org/schemas/clock/qcom,sc7280-lpasscorecc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm LPASS Core & Audio Clock Controller Binding for SC7280
+title: Qualcomm LPASS Core & Audio Clock Controller on SC7280
maintainers:
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm LPASS core and audio clock control module which supports the
- clocks and power domains on SC7280.
+ Qualcomm LPASS core and audio clock control module provides the clocks and
+ power domains on SC7280.
- See also:
- - dt-bindings/clock/qcom,lpasscorecc-sc7280.h
- - dt-bindings/clock/qcom,lpassaudiocc-sc7280.h
+ See also::
+ include/dt-bindings/clock/qcom,lpasscorecc-sc7280.h
+ include/dt-bindings/clock/qcom,lpassaudiocc-sc7280.h
properties:
clocks: true
diff --git a/Documentation/devicetree/bindings/clock/qcom,sdm845-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sdm845-camcc.yaml
index d4239ccae917..91d1f7918037 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sdm845-camcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sdm845-camcc.yaml
@@ -4,16 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,sdm845-camcc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Camera Clock & Reset Controller Binding for SDM845
+title: Qualcomm Camera Clock & Reset Controller on SDM845
maintainers:
- Bjorn Andersson <bjorn.andersson@linaro.org>
description: |
- Qualcomm camera clock control module which supports the clocks, resets and
- power domains on SDM845.
+ Qualcomm camera clock control module provides the clocks, resets and power
+ domains on SDM845.
- See also dt-bindings/clock/qcom,camcc-sm845.h
+ See also:: include/dt-bindings/clock/qcom,camcc-sm845.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,sdm845-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sdm845-dispcc.yaml
index 4a3be733d042..76b53ce64e40 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sdm845-dispcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sdm845-dispcc.yaml
@@ -4,16 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,sdm845-dispcc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Display Clock & Reset Controller Binding for SDM845
+title: Qualcomm Display Clock & Reset Controller on SDM845
maintainers:
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm display clock control module which supports the clocks, resets and
- power domains on SDM845.
+ Qualcomm display clock control module provides the clocks, resets and power
+ domains on SDM845.
- See also dt-bindings/clock/qcom,dispcc-sdm845.h.
+ See also:: include/dt-bindings/clock/qcom,dispcc-sdm845.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,sdm845-lpasscc.yaml b/Documentation/devicetree/bindings/clock/qcom,sdm845-lpasscc.yaml
new file mode 100644
index 000000000000..a96fd837c70a
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,sdm845-lpasscc.yaml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,sdm845-lpasscc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SDM845 LPASS Clock Controller
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+
+description: |
+ Qualcomm SDM845 LPASS (Low Power Audio SubSystem) Clock Controller.
+
+ See also:: include/dt-bindings/clock/qcom,lpass-sdm845.h
+
+properties:
+ compatible:
+ const: qcom,sdm845-lpasscc
+
+ '#clock-cells':
+ const: 1
+
+ reg:
+ maxItems: 2
+
+ reg-names:
+ items:
+ - const: cc
+ - const: qdsp6ss
+
+required:
+ - compatible
+ - '#clock-cells'
+ - reg
+ - reg-names
+
+additionalProperties: false
+
+examples:
+ - |
+ clock-controller@17014000 {
+ compatible = "qcom,sdm845-lpasscc";
+ reg = <0x17014000 0x1f004>, <0x17300000 0x200>;
+ reg-names = "cc", "qdsp6ss";
+ #clock-cells = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6115-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6115-dispcc.yaml
index 6660ff16ad1b..f802a2e7f818 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sm6115-dispcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sm6115-dispcc.yaml
@@ -10,11 +10,10 @@ maintainers:
- Bjorn Andersson <andersson@kernel.org>
description: |
- Qualcomm display clock control module which supports the clocks and
- power domains on SM6115.
+ Qualcomm display clock control module provides the clocks and power domains
+ on SM6115.
- See also:
- include/dt-bindings/clock/qcom,sm6115-dispcc.h
+ See also:: include/dt-bindings/clock/qcom,sm6115-dispcc.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6375-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6375-dispcc.yaml
new file mode 100644
index 000000000000..183b1c75dbdf
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,sm6375-dispcc.yaml
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,sm6375-dispcc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Display Clock & Reset Controller on SM6375
+
+maintainers:
+ - Konrad Dybcio <konrad.dybcio@linaro.org>
+
+description: |
+ Qualcomm display clock control module provides the clocks, resets and power
+ domains on SM6375.
+
+ See also:: include/dt-bindings/clock/qcom,dispcc-sm6375.h
+
+allOf:
+ - $ref: qcom,gcc.yaml#
+
+properties:
+ compatible:
+ const: qcom,sm6375-dispcc
+
+ clocks:
+ items:
+ - description: Board XO source
+ - description: GPLL0 source from GCC
+ - description: Byte clock from DSI PHY
+ - description: Pixel clock from DSI PHY
+
+required:
+ - compatible
+ - clocks
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,sm6375-gcc.h>
+ #include <dt-bindings/clock/qcom,rpmh.h>
+
+ clock-controller@5f00000 {
+ compatible = "qcom,sm6375-dispcc";
+ reg = <0x05f00000 0x20000>;
+ clocks = <&rpmhcc RPMH_CXO_CLK>,
+ <&gcc GCC_DISP_GPLL0_CLK_SRC>,
+ <&dsi_phy 0>,
+ <&dsi_phy 1>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm6375-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm6375-gcc.yaml
index 3c573e1a1257..295d4bb1a966 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sm6375-gcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sm6375-gcc.yaml
@@ -4,17 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,sm6375-gcc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Global Clock & Reset Controller Binding for SM6375
+title: Qualcomm Global Clock & Reset Controller on SM6375
maintainers:
- Konrad Dybcio <konrad.dybcio@somainline.org>
description: |
- Qualcomm global clock control module which supports the clocks, resets and
- power domains on SM6375
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on SM6375
- See also:
- - dt-bindings/clock/qcom,sm6375-gcc.h
+ See also:: include/dt-bindings/clock/qcom,sm6375-gcc.h
allOf:
- $ref: qcom,gcc.yaml#
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml
index 268f4c6ae0ee..a52a83fe2831 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sm8450-camcc.yaml
@@ -4,16 +4,16 @@
$id: http://devicetree.org/schemas/clock/qcom,sm8450-camcc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Camera Clock & Reset Controller Binding for SM8450
+title: Qualcomm Camera Clock & Reset Controller on SM8450
maintainers:
- Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
description: |
- Qualcomm camera clock control module which supports the clocks, resets and
- power domains on SM8450.
+ Qualcomm camera clock control module provides the clocks, resets and power
+ domains on SM8450.
- See also include/dt-bindings/clock/qcom,sm8450-camcc.h
+ See also:: include/dt-bindings/clock/qcom,sm8450-camcc.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8450-dispcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8450-dispcc.yaml
index 1cc2457f8208..1dd1f696dcd3 100644
--- a/Documentation/devicetree/bindings/clock/qcom,sm8450-dispcc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,sm8450-dispcc.yaml
@@ -10,11 +10,10 @@ maintainers:
- Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
description: |
- Qualcomm display clock control module which supports the clocks, resets and
- power domains on SM8450.
+ Qualcomm display clock control module provides the clocks, resets and power
+ domains on SM8450.
- See also:
- include/dt-bindings/clock/qcom,sm8450-dispcc.h
+ See also:: include/dt-bindings/clock/qcom,sm8450-dispcc.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/qcom,sm8550-gcc.yaml b/Documentation/devicetree/bindings/clock/qcom,sm8550-gcc.yaml
new file mode 100644
index 000000000000..0c706de31cf1
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,sm8550-gcc.yaml
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,sm8550-gcc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Global Clock & Reset Controller on SM8550
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+
+description: |
+ Qualcomm global clock control module provides the clocks, resets and power
+ domains on SM8550
+
+ See also:: include/dt-bindings/clock/qcom,sm8550-gcc.h
+
+properties:
+ compatible:
+ const: qcom,sm8550-gcc
+
+ clocks:
+ items:
+ - description: Board XO source
+ - description: Sleep clock source
+ - description: PCIE 0 Pipe clock source
+ - description: PCIE 1 Pipe clock source
+ - description: PCIE 1 Phy Auxiliary clock source
+ - description: UFS Phy Rx symbol 0 clock source
+ - description: UFS Phy Rx symbol 1 clock source
+ - description: UFS Phy Tx symbol 0 clock source
+ - description: USB3 Phy wrapper pipe clock source
+
+required:
+ - compatible
+ - clocks
+
+allOf:
+ - $ref: qcom,gcc.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ clock-controller@100000 {
+ compatible = "qcom,sm8550-gcc";
+ reg = <0x00100000 0x001f4200>;
+ clocks = <&rpmhcc RPMH_CXO_CLK>, <&sleep_clk>,
+ <&pcie0_phy>,
+ <&pcie1_phy>,
+ <&pcie_1_phy_aux_clk>,
+ <&ufs_mem_phy 0>,
+ <&ufs_mem_phy 1>,
+ <&ufs_mem_phy 2>,
+ <&usb_1_qmpphy>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/clock/qcom,videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,videocc.yaml
index 3cdbcebdc1a1..e221985e743f 100644
--- a/Documentation/devicetree/bindings/clock/qcom,videocc.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,videocc.yaml
@@ -4,21 +4,21 @@
$id: http://devicetree.org/schemas/clock/qcom,videocc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Video Clock & Reset Controller Binding
+title: Qualcomm Video Clock & Reset Controller
maintainers:
- Taniya Das <tdas@codeaurora.org>
description: |
- Qualcomm video clock control module which supports the clocks, resets and
- power domains on Qualcomm SoCs.
-
- See also:
- dt-bindings/clock/qcom,videocc-sc7180.h
- dt-bindings/clock/qcom,videocc-sc7280.h
- dt-bindings/clock/qcom,videocc-sdm845.h
- dt-bindings/clock/qcom,videocc-sm8150.h
- dt-bindings/clock/qcom,videocc-sm8250.h
+ Qualcomm video clock control module provides the clocks, resets and power
+ domains on Qualcomm SoCs.
+
+ See also::
+ include/dt-bindings/clock/qcom,videocc-sc7180.h
+ include/dt-bindings/clock/qcom,videocc-sc7280.h
+ include/dt-bindings/clock/qcom,videocc-sdm845.h
+ include/dt-bindings/clock/qcom,videocc-sm8150.h
+ include/dt-bindings/clock/qcom,videocc-sm8250.h
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/clock/rockchip,rk3588-cru.yaml b/Documentation/devicetree/bindings/clock/rockchip,rk3588-cru.yaml
new file mode 100644
index 000000000000..74cd3f3f229a
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/rockchip,rk3588-cru.yaml
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/rockchip,rk3588-cru.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Rockchip rk3588 Family Clock and Reset Control Module
+
+maintainers:
+ - Elaine Zhang <zhangqing@rock-chips.com>
+ - Heiko Stuebner <heiko@sntech.de>
+
+description: |
+ The RK3588 clock controller generates the clock and also implements a reset
+ controller for SoC peripherals. For example it provides SCLK_UART2 and
+ PCLK_UART2, as well as SRST_P_UART2 and SRST_S_UART2 for the second UART
+ module.
+ Each clock is assigned an identifier and client nodes can use this identifier
+ to specify the clock which they consume. All available clock and reset IDs
+ are defined as preprocessor macros in dt-binding headers.
+
+properties:
+ compatible:
+ enum:
+ - rockchip,rk3588-cru
+
+ reg:
+ maxItems: 1
+
+ "#clock-cells":
+ const: 1
+
+ "#reset-cells":
+ const: 1
+
+ clocks:
+ minItems: 2
+ maxItems: 2
+
+ clock-names:
+ items:
+ - const: xin24m
+ - const: xin32k
+
+ assigned-clocks: true
+
+ assigned-clock-rates: true
+
+ rockchip,grf:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: >
+ phandle to the syscon managing the "general register files". It is used
+ for GRF muxes, if missing any muxes present in the GRF will not be
+ available.
+
+required:
+ - compatible
+ - reg
+ - "#clock-cells"
+ - "#reset-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ cru: clock-controller@fd7c0000 {
+ compatible = "rockchip,rk3588-cru";
+ reg = <0xfd7c0000 0x5c000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/clock/ti,cdce925.txt b/Documentation/devicetree/bindings/clock/ti,cdce925.txt
deleted file mode 100644
index df42ab72718f..000000000000
--- a/Documentation/devicetree/bindings/clock/ti,cdce925.txt
+++ /dev/null
@@ -1,53 +0,0 @@
-Binding for TI CDCE913/925/937/949 programmable I2C clock synthesizers.
-
-Reference
-This binding uses the common clock binding[1].
-
-[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
-[2] https://www.ti.com/product/cdce913
-[3] https://www.ti.com/product/cdce925
-[4] https://www.ti.com/product/cdce937
-[5] https://www.ti.com/product/cdce949
-
-The driver provides clock sources for each output Y1 through Y5.
-
-Required properties:
- - compatible: Shall be one of the following:
- - "ti,cdce913": 1-PLL, 3 Outputs
- - "ti,cdce925": 2-PLL, 5 Outputs
- - "ti,cdce937": 3-PLL, 7 Outputs
- - "ti,cdce949": 4-PLL, 9 Outputs
- - reg: I2C device address.
- - clocks: Points to a fixed parent clock that provides the input frequency.
- - #clock-cells: From common clock bindings: Shall be 1.
-
-Optional properties:
- - xtal-load-pf: Crystal load-capacitor value to fine-tune performance on a
- board, or to compensate for external influences.
-- vdd-supply: A regulator node for Vdd
-- vddout-supply: A regulator node for Vddout
-
-For all PLL1, PLL2, ... an optional child node can be used to specify spread
-spectrum clocking parameters for a board.
- - spread-spectrum: SSC mode as defined in the data sheet.
- - spread-spectrum-center: Use "centered" mode instead of "max" mode. When
- present, the clock runs at the requested frequency on average. Otherwise
- the requested frequency is the maximum value of the SCC range.
-
-
-Example:
-
- clockgen: cdce925pw@64 {
- compatible = "cdce925";
- reg = <0x64>;
- clocks = <&xtal_27Mhz>;
- #clock-cells = <1>;
- xtal-load-pf = <5>;
- vdd-supply = <&1v8-reg>;
- vddout-supply = <&3v3-reg>;
- /* PLL options to get SSC 1% centered */
- PLL2 {
- spread-spectrum = <4>;
- spread-spectrum-center;
- };
- };
diff --git a/Documentation/devicetree/bindings/clock/ti,cdce925.yaml b/Documentation/devicetree/bindings/clock/ti,cdce925.yaml
new file mode 100644
index 000000000000..a4ec8dd5ddf1
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/ti,cdce925.yaml
@@ -0,0 +1,103 @@
+# SPDX-License-Identifier: (GPL-2.0-only or BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/ti,cdce925.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TI CDCE913/925/937/949 programmable I2C clock synthesizers
+
+maintainers:
+ - Alexander Stein <alexander.stein@ew.tq-group.com>
+
+description: |
+ Flexible Low Power LVCMOS Clock Generator with SSC Support for EMI Reduction
+
+ - CDCE(L)913: 1-PLL, 3 Outputs https://www.ti.com/product/cdce913
+ - CDCE(L)925: 2-PLL, 5 Outputs https://www.ti.com/product/cdce925
+ - CDCE(L)937: 3-PLL, 7 Outputs https://www.ti.com/product/cdce937
+ - CDCE(L)949: 4-PLL, 9 Outputs https://www.ti.com/product/cdce949
+
+properties:
+ compatible:
+ enum:
+ - ti,cdce913
+ - ti,cdce925
+ - ti,cdce937
+ - ti,cdce949
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: fixed parent clock
+
+ "#clock-cells":
+ const: 1
+
+ vdd-supply:
+ description: Regulator that provides 1.8V Vdd power supply
+
+ vddout-supply:
+ description: |
+ Regulator that provides Vddout power supply.
+ non-L variant: 2.5V or 3.3V for
+ L variant: 1.8V for
+
+ xtal-load-pf:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ Crystal load-capacitor value to fine-tune performance on a
+ board, or to compensate for external influences.
+
+patternProperties:
+ "^PLL[1-4]$":
+ type: object
+ description: |
+ optional child node can be used to specify spread
+ spectrum clocking parameters for a board
+
+ additionalProperties: false
+
+ properties:
+ spread-spectrum:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: SSC mode as defined in the data sheet
+
+ spread-spectrum-center:
+ type: boolean
+ description: |
+ Use "centered" mode instead of "max" mode. When
+ present, the clock runs at the requested frequency on average.
+ Otherwise the requested frequency is the maximum value of the
+ SCC range.
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - "#clock-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cdce925: clock-controller@64 {
+ compatible = "ti,cdce925";
+ reg = <0x64>;
+ clocks = <&xtal_27Mhz>;
+ #clock-cells = <1>;
+ xtal-load-pf = <5>;
+ vdd-supply = <&reg_1v8>;
+ vddout-supply = <&reg_3v3>;
+ /* PLL options to get SSC 1% centered */
+ PLL2 {
+ spread-spectrum = <4>;
+ spread-spectrum-center;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/cpufreq/apple,cluster-cpufreq.yaml b/Documentation/devicetree/bindings/cpufreq/apple,cluster-cpufreq.yaml
new file mode 100644
index 000000000000..76cb9726660e
--- /dev/null
+++ b/Documentation/devicetree/bindings/cpufreq/apple,cluster-cpufreq.yaml
@@ -0,0 +1,117 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/cpufreq/apple,cluster-cpufreq.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Apple SoC cluster cpufreq device
+
+maintainers:
+ - Hector Martin <marcan@marcan.st>
+
+description: |
+ Apple SoCs (e.g. M1) have a per-cpu-cluster DVFS controller that is part of
+ the cluster management register block. This binding uses the standard
+ operating-points-v2 table to define the CPU performance states, with the
+ opp-level property specifying the hardware p-state index for that level.
+
+properties:
+ compatible:
+ oneOf:
+ - items:
+ - enum:
+ - apple,t8103-cluster-cpufreq
+ - apple,t8112-cluster-cpufreq
+ - const: apple,cluster-cpufreq
+ - items:
+ - const: apple,t6000-cluster-cpufreq
+ - const: apple,t8103-cluster-cpufreq
+ - const: apple,cluster-cpufreq
+
+ reg:
+ maxItems: 1
+
+ '#performance-domain-cells':
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - '#performance-domain-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ // This example shows a single CPU per domain and 2 domains,
+ // with two p-states per domain.
+ // Shipping hardware has 2-4 CPUs per domain and 2-6 domains.
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ compatible = "apple,icestorm";
+ device_type = "cpu";
+ reg = <0x0 0x0>;
+ operating-points-v2 = <&ecluster_opp>;
+ performance-domains = <&cpufreq_e>;
+ };
+
+ cpu@10100 {
+ compatible = "apple,firestorm";
+ device_type = "cpu";
+ reg = <0x0 0x10100>;
+ operating-points-v2 = <&pcluster_opp>;
+ performance-domains = <&cpufreq_p>;
+ };
+ };
+
+ ecluster_opp: opp-table-0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp01 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-level = <1>;
+ clock-latency-ns = <7500>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <972000000>;
+ opp-level = <2>;
+ clock-latency-ns = <22000>;
+ };
+ };
+
+ pcluster_opp: opp-table-1 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp01 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-level = <1>;
+ clock-latency-ns = <8000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <828000000>;
+ opp-level = <2>;
+ clock-latency-ns = <19000>;
+ };
+ };
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpufreq_e: performance-controller@210e20000 {
+ compatible = "apple,t8103-cluster-cpufreq", "apple,cluster-cpufreq";
+ reg = <0x2 0x10e20000 0 0x1000>;
+ #performance-domain-cells = <0>;
+ };
+
+ cpufreq_p: performance-controller@211e20000 {
+ compatible = "apple,t8103-cluster-cpufreq", "apple,cluster-cpufreq";
+ reg = <0x2 0x11e20000 0 0x1000>;
+ #performance-domain-cells = <0>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml b/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml
index 24fa3d87a40b..903b31129f01 100644
--- a/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml
+++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml
@@ -25,6 +25,7 @@ properties:
- description: v2 of CPUFREQ HW (EPSS)
items:
- enum:
+ - qcom,qdu1000-cpufreq-epss
- qcom,sm6375-cpufreq-epss
- qcom,sm8250-cpufreq-epss
- const: qcom,cpufreq-epss
@@ -56,6 +57,9 @@ properties:
'#freq-domain-cells':
const: 1
+ '#clock-cells':
+ const: 1
+
required:
- compatible
- reg
@@ -83,11 +87,16 @@ examples:
enable-method = "psci";
next-level-cache = <&L2_0>;
qcom,freq-domain = <&cpufreq_hw 0>;
+ clocks = <&cpufreq_hw 0>;
L2_0: l2-cache {
compatible = "cache";
+ cache-unified;
+ cache-level = <2>;
next-level-cache = <&L3_0>;
L3_0: l3-cache {
compatible = "cache";
+ cache-unified;
+ cache-level = <3>;
};
};
};
@@ -99,8 +108,11 @@ examples:
enable-method = "psci";
next-level-cache = <&L2_100>;
qcom,freq-domain = <&cpufreq_hw 0>;
+ clocks = <&cpufreq_hw 0>;
L2_100: l2-cache {
compatible = "cache";
+ cache-unified;
+ cache-level = <2>;
next-level-cache = <&L3_0>;
};
};
@@ -112,8 +124,11 @@ examples:
enable-method = "psci";
next-level-cache = <&L2_200>;
qcom,freq-domain = <&cpufreq_hw 0>;
+ clocks = <&cpufreq_hw 0>;
L2_200: l2-cache {
compatible = "cache";
+ cache-unified;
+ cache-level = <2>;
next-level-cache = <&L3_0>;
};
};
@@ -125,8 +140,11 @@ examples:
enable-method = "psci";
next-level-cache = <&L2_300>;
qcom,freq-domain = <&cpufreq_hw 0>;
+ clocks = <&cpufreq_hw 0>;
L2_300: l2-cache {
compatible = "cache";
+ cache-unified;
+ cache-level = <2>;
next-level-cache = <&L3_0>;
};
};
@@ -138,8 +156,11 @@ examples:
enable-method = "psci";
next-level-cache = <&L2_400>;
qcom,freq-domain = <&cpufreq_hw 1>;
+ clocks = <&cpufreq_hw 1>;
L2_400: l2-cache {
compatible = "cache";
+ cache-unified;
+ cache-level = <2>;
next-level-cache = <&L3_0>;
};
};
@@ -151,8 +172,11 @@ examples:
enable-method = "psci";
next-level-cache = <&L2_500>;
qcom,freq-domain = <&cpufreq_hw 1>;
+ clocks = <&cpufreq_hw 1>;
L2_500: l2-cache {
compatible = "cache";
+ cache-unified;
+ cache-level = <2>;
next-level-cache = <&L3_0>;
};
};
@@ -164,8 +188,11 @@ examples:
enable-method = "psci";
next-level-cache = <&L2_600>;
qcom,freq-domain = <&cpufreq_hw 1>;
+ clocks = <&cpufreq_hw 1>;
L2_600: l2-cache {
compatible = "cache";
+ cache-unified;
+ cache-level = <2>;
next-level-cache = <&L3_0>;
};
};
@@ -177,8 +204,11 @@ examples:
enable-method = "psci";
next-level-cache = <&L2_700>;
qcom,freq-domain = <&cpufreq_hw 1>;
+ clocks = <&cpufreq_hw 1>;
L2_700: l2-cache {
compatible = "cache";
+ cache-unified;
+ cache-level = <2>;
next-level-cache = <&L3_0>;
};
};
@@ -197,6 +227,7 @@ examples:
clock-names = "xo", "alternate";
#freq-domain-cells = <1>;
+ #clock-cells = <1>;
};
};
...
diff --git a/Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml b/Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml
index a11e1b867379..3c00ad09eeaa 100644
--- a/Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml
+++ b/Documentation/devicetree/bindings/cpufreq/qcom-cpufreq-nvmem.yaml
@@ -38,7 +38,7 @@ properties:
type: object
patternProperties:
- 'cpu@[0-9a-f]+':
+ '^cpu@[0-9a-f]+$':
type: object
properties:
diff --git a/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml b/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
index 7910831fa4b8..c731fbdc2fe0 100644
--- a/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
+++ b/Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
@@ -12,9 +12,14 @@ maintainers:
properties:
compatible:
- enum:
- - allwinner,sun6i-a31-mipi-dsi
- - allwinner,sun50i-a64-mipi-dsi
+ oneOf:
+ - enum:
+ - allwinner,sun6i-a31-mipi-dsi
+ - allwinner,sun50i-a64-mipi-dsi
+ - allwinner,sun50i-a100-mipi-dsi
+ - items:
+ - const: allwinner,sun20i-d1-mipi-dsi
+ - const: allwinner,sun50i-a100-mipi-dsi
reg:
maxItems: 1
@@ -59,7 +64,6 @@ required:
- phys
- phy-names
- resets
- - vcc-dsi-supply
- port
allOf:
@@ -68,7 +72,9 @@ allOf:
properties:
compatible:
contains:
- const: allwinner,sun6i-a31-mipi-dsi
+ enum:
+ - allwinner,sun6i-a31-mipi-dsi
+ - allwinner,sun50i-a100-mipi-dsi
then:
properties:
@@ -78,16 +84,22 @@ allOf:
required:
- clock-names
+ else:
+ properties:
+ clocks:
+ maxItems: 1
+
- if:
properties:
compatible:
contains:
- const: allwinner,sun50i-a64-mipi-dsi
+ enum:
+ - allwinner,sun6i-a31-mipi-dsi
+ - allwinner,sun50i-a64-mipi-dsi
then:
- properties:
- clocks:
- minItems: 1
+ required:
+ - vcc-dsi-supply
unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml b/Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml
index 7cdffdb131ac..74cefdf1b843 100644
--- a/Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml
+++ b/Documentation/devicetree/bindings/display/amlogic,meson-dw-hdmi.yaml
@@ -11,7 +11,7 @@ maintainers:
- Neil Armstrong <neil.armstrong@linaro.org>
allOf:
- - $ref: /schemas/sound/name-prefix.yaml#
+ - $ref: /schemas/sound/dai-common.yaml#
description: |
The Amlogic Meson Synopsys Designware Integration is composed of
diff --git a/Documentation/devicetree/bindings/display/bridge/renesas,dsi.yaml b/Documentation/devicetree/bindings/display/bridge/renesas,dsi.yaml
new file mode 100644
index 000000000000..131d5b63ec4f
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/renesas,dsi.yaml
@@ -0,0 +1,182 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/bridge/renesas,dsi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RZ/G2L MIPI DSI Encoder
+
+maintainers:
+ - Biju Das <biju.das.jz@bp.renesas.com>
+
+description: |
+ This binding describes the MIPI DSI encoder embedded in the Renesas
+ RZ/G2L alike family of SoC's. The encoder can operate in DSI mode, with
+ up to four data lanes.
+
+allOf:
+ - $ref: /schemas/display/dsi-controller.yaml#
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - renesas,r9a07g044-mipi-dsi # RZ/G2{L,LC}
+ - const: renesas,rzg2l-mipi-dsi
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ items:
+ - description: Sequence operation channel 0 interrupt
+ - description: Sequence operation channel 1 interrupt
+ - description: Video-Input operation channel 1 interrupt
+ - description: DSI Packet Receive interrupt
+ - description: DSI Fatal Error interrupt
+ - description: DSI D-PHY PPI interrupt
+ - description: Debug interrupt
+
+ interrupt-names:
+ items:
+ - const: seq0
+ - const: seq1
+ - const: vin1
+ - const: rcv
+ - const: ferr
+ - const: ppi
+ - const: debug
+
+ clocks:
+ items:
+ - description: DSI D-PHY PLL multiplied clock
+ - description: DSI D-PHY system clock
+ - description: DSI AXI bus clock
+ - description: DSI Register access clock
+ - description: DSI Video clock
+ - description: DSI D-PHY Escape mode transmit clock
+
+ clock-names:
+ items:
+ - const: pllclk
+ - const: sysclk
+ - const: aclk
+ - const: pclk
+ - const: vclk
+ - const: lpclk
+
+ resets:
+ items:
+ - description: MIPI_DSI_CMN_RSTB
+ - description: MIPI_DSI_ARESET_N
+ - description: MIPI_DSI_PRESET_N
+
+ reset-names:
+ items:
+ - const: rst
+ - const: arst
+ - const: prst
+
+ power-domains:
+ maxItems: 1
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: Parallel input port
+
+ port@1:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description: DSI output port
+
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ description: array of physical DSI data lane indexes.
+ minItems: 1
+ items:
+ - const: 1
+ - const: 2
+ - const: 3
+ - const: 4
+
+ required:
+ - data-lanes
+
+ required:
+ - port@0
+ - port@1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - interrupt-names
+ - clocks
+ - clock-names
+ - resets
+ - reset-names
+ - power-domains
+ - ports
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/r9a07g044-cpg.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ dsi0: dsi@10850000 {
+ compatible = "renesas,r9a07g044-mipi-dsi", "renesas,rzg2l-mipi-dsi";
+ reg = <0x10850000 0x20000>;
+ interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "seq0", "seq1", "vin1", "rcv",
+ "ferr", "ppi", "debug";
+ clocks = <&cpg CPG_MOD R9A07G044_MIPI_DSI_PLLCLK>,
+ <&cpg CPG_MOD R9A07G044_MIPI_DSI_SYSCLK>,
+ <&cpg CPG_MOD R9A07G044_MIPI_DSI_ACLK>,
+ <&cpg CPG_MOD R9A07G044_MIPI_DSI_PCLK>,
+ <&cpg CPG_MOD R9A07G044_MIPI_DSI_VCLK>,
+ <&cpg CPG_MOD R9A07G044_MIPI_DSI_LPCLK>;
+ clock-names = "pllclk", "sysclk", "aclk", "pclk", "vclk", "lpclk";
+ resets = <&cpg R9A07G044_MIPI_DSI_CMN_RSTB>,
+ <&cpg R9A07G044_MIPI_DSI_ARESET_N>,
+ <&cpg R9A07G044_MIPI_DSI_PRESET_N>;
+ reset-names = "rst", "arst", "prst";
+ power-domains = <&cpg>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dsi0_in: endpoint {
+ remote-endpoint = <&du_out_dsi0>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dsi0_out: endpoint {
+ data-lanes = <1 2 3 4>;
+ remote-endpoint = <&adv7535_in>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/fsl,lcdif.yaml b/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
index 876015a44a1e..f449cfc76789 100644
--- a/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
+++ b/Documentation/devicetree/bindings/display/fsl,lcdif.yaml
@@ -52,6 +52,9 @@ properties:
interrupts:
maxItems: 1
+ power-domains:
+ maxItems: 1
+
port:
$ref: /schemas/graph.yaml#/properties/port
description: The LCDIF output port
@@ -81,7 +84,31 @@ allOf:
maxItems: 3
required:
- clock-names
- else:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: fsl,imx8mp-lcdif
+ then:
+ properties:
+ clocks:
+ minItems: 3
+ maxItems: 3
+ clock-names:
+ minItems: 3
+ maxItems: 3
+ required:
+ - clock-names
+ - power-domains
+ - if:
+ not:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx6sx-lcdif
+ - fsl,imx8mp-lcdif
+ then:
properties:
clocks:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx-fb.txt b/Documentation/devicetree/bindings/display/imx/fsl,imx-fb.txt
deleted file mode 100644
index f4df9e83bcd2..000000000000
--- a/Documentation/devicetree/bindings/display/imx/fsl,imx-fb.txt
+++ /dev/null
@@ -1,57 +0,0 @@
-Freescale imx21 Framebuffer
-
-This framebuffer driver supports devices imx1, imx21, imx25, and imx27.
-
-Required properties:
-- compatible : "fsl,<chip>-fb", chip should be imx1 or imx21
-- reg : Should contain 1 register ranges(address and length)
-- interrupts : One interrupt of the fb dev
-
-Required nodes:
-- display: Phandle to a display node as described in
- Documentation/devicetree/bindings/display/panel/display-timing.txt
- Additional, the display node has to define properties:
- - bits-per-pixel: Bits per pixel
- - fsl,pcr: LCDC PCR value
- A display node may optionally define
- - fsl,aus-mode: boolean to enable AUS mode (only for imx21)
-
-Optional properties:
-- lcd-supply: Regulator for LCD supply voltage.
-- fsl,dmacr: DMA Control Register value. This is optional. By default, the
- register is not modified as recommended by the datasheet.
-- fsl,lpccr: Contrast Control Register value. This property provides the
- default value for the contrast control register.
- If that property is omitted, the register is zeroed.
-- fsl,lscr1: LCDC Sharp Configuration Register value.
-
-Example:
-
- imxfb: fb@10021000 {
- compatible = "fsl,imx21-fb";
- interrupts = <61>;
- reg = <0x10021000 0x1000>;
- display = <&display0>;
- };
-
- ...
-
- display0: display0 {
- model = "Primeview-PD050VL1";
- bits-per-pixel = <16>;
- fsl,pcr = <0xf0c88080>; /* non-standard but required */
- display-timings {
- native-mode = <&timing_disp0>;
- timing_disp0: 640x480 {
- hactive = <640>;
- vactive = <480>;
- hback-porch = <112>;
- hfront-porch = <36>;
- hsync-len = <32>;
- vback-porch = <33>;
- vfront-porch = <33>;
- vsync-len = <2>;
- clock-frequency = <25000000>;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/display/imx/fsl,imx-lcdc.yaml b/Documentation/devicetree/bindings/display/imx/fsl,imx-lcdc.yaml
new file mode 100644
index 000000000000..35a8fff036ca
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/imx/fsl,imx-lcdc.yaml
@@ -0,0 +1,102 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/imx/fsl,imx-lcdc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Freescale i.MX LCD Controller, found on i.MX1, i.MX21, i.MX25 and i.MX27
+
+maintainers:
+ - Sascha Hauer <s.hauer@pengutronix.de>
+ - Pengutronix Kernel Team <kernel@pengutronix.de>
+
+properties:
+ compatible:
+ oneOf:
+ - enum:
+ - fsl,imx1-fb
+ - fsl,imx21-fb
+ - items:
+ - enum:
+ - fsl,imx25-fb
+ - fsl,imx27-fb
+ - const: fsl,imx21-fb
+
+ clocks:
+ maxItems: 3
+
+ clock-names:
+ items:
+ - const: ipg
+ - const: ahb
+ - const: per
+
+ display:
+ $ref: /schemas/types.yaml#/definitions/phandle
+
+ interrupts:
+ maxItems: 1
+
+ reg:
+ maxItems: 1
+
+ lcd-supply:
+ description:
+ Regulator for LCD supply voltage.
+
+ fsl,dmacr:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Override value for DMA Control Register
+
+ fsl,lpccr:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Contrast Control Register value.
+
+ fsl,lscr1:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ LCDC Sharp Configuration Register value.
+
+required:
+ - compatible
+ - clocks
+ - clock-names
+ - display
+ - interrupts
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ imxfb: fb@10021000 {
+ compatible = "fsl,imx21-fb";
+ interrupts = <61>;
+ reg = <0x10021000 0x1000>;
+ display = <&display0>;
+ clocks = <&clks 103>, <&clks 49>, <&clks 66>;
+ clock-names = "ipg", "ahb", "per";
+ };
+
+ display0: display0 {
+ model = "Primeview-PD050VL1";
+ bits-per-pixel = <16>;
+ fsl,pcr = <0xf0c88080>; /* non-standard but required */
+
+ display-timings {
+ native-mode = <&timing_disp0>;
+ timing_disp0: timing0 {
+ hactive = <640>;
+ vactive = <480>;
+ hback-porch = <112>;
+ hfront-porch = <36>;
+ hsync-len = <32>;
+ vback-porch = <33>;
+ vfront-porch = <33>;
+ vsync-len = <2>;
+ clock-frequency = <25000000>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
index 5bb23e97cf33..d976380801e3 100644
--- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
+++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
@@ -23,6 +23,7 @@ properties:
- mediatek,mt8173-dpi
- mediatek,mt8183-dpi
- mediatek,mt8186-dpi
+ - mediatek,mt8188-dp-intf
- mediatek,mt8192-dpi
- mediatek,mt8195-dp-intf
diff --git a/Documentation/devicetree/bindings/display/msm/dpu-common.yaml b/Documentation/devicetree/bindings/display/msm/dpu-common.yaml
new file mode 100644
index 000000000000..8ffbc30c6b7f
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/dpu-common.yaml
@@ -0,0 +1,52 @@
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/dpu-common.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Display DPU common properties
+
+maintainers:
+ - Krishna Manikandan <quic_mkrishn@quicinc.com>
+ - Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+ - Rob Clark <robdclark@gmail.com>
+
+description: |
+ Common properties for QCom DPU display controller.
+
+properties:
+ interrupts:
+ maxItems: 1
+
+ power-domains:
+ maxItems: 1
+
+ operating-points-v2: true
+ opp-table:
+ type: object
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description: |
+ Contains the list of output ports from DPU device. These ports
+ connect to interfaces that are external to the DPU hardware,
+ such as DSI, DP etc.
+
+ patternProperties:
+ "^port@[0-9a-f]+$":
+ $ref: /schemas/graph.yaml#/properties/port
+
+ # at least one port is required
+ required:
+ - port@0
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - clocks
+ - interrupts
+ - power-domains
+ - operating-points-v2
+ - ports
+
+additionalProperties: true
diff --git a/Documentation/devicetree/bindings/display/msm/dpu-msm8998.yaml b/Documentation/devicetree/bindings/display/msm/dpu-msm8998.yaml
deleted file mode 100644
index 253665c693e6..000000000000
--- a/Documentation/devicetree/bindings/display/msm/dpu-msm8998.yaml
+++ /dev/null
@@ -1,223 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/display/msm/dpu-msm8998.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Qualcomm Display DPU dt properties for MSM8998 target
-
-maintainers:
- - AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
-
-description: |
- Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates
- sub-blocks like DPU display controller, DSI and DP interfaces etc. Device tree
- bindings of MDSS and DPU are mentioned for MSM8998 target.
-
-properties:
- compatible:
- items:
- - const: qcom,msm8998-mdss
-
- reg:
- maxItems: 1
-
- reg-names:
- const: mdss
-
- power-domains:
- maxItems: 1
-
- clocks:
- items:
- - description: Display AHB clock
- - description: Display AXI clock
- - description: Display core clock
-
- clock-names:
- items:
- - const: iface
- - const: bus
- - const: core
-
- interrupts:
- maxItems: 1
-
- interrupt-controller: true
-
- "#address-cells": true
-
- "#size-cells": true
-
- "#interrupt-cells":
- const: 1
-
- iommus:
- items:
- - description: Phandle to apps_smmu node with SID mask for Hard-Fail port0
-
- ranges: true
-
-patternProperties:
- "^display-controller@[0-9a-f]+$":
- type: object
- description: Node containing the properties of DPU.
- additionalProperties: false
-
- properties:
- compatible:
- items:
- - const: qcom,msm8998-dpu
-
- reg:
- items:
- - description: Address offset and size for mdp register set
- - description: Address offset and size for regdma register set
- - description: Address offset and size for vbif register set
- - description: Address offset and size for non-realtime vbif register set
-
- reg-names:
- items:
- - const: mdp
- - const: regdma
- - const: vbif
- - const: vbif_nrt
-
- clocks:
- items:
- - description: Display ahb clock
- - description: Display axi clock
- - description: Display mem-noc clock
- - description: Display core clock
- - description: Display vsync clock
-
- clock-names:
- items:
- - const: iface
- - const: bus
- - const: mnoc
- - const: core
- - const: vsync
-
- interrupts:
- maxItems: 1
-
- power-domains:
- maxItems: 1
-
- operating-points-v2: true
- opp-table:
- type: object
-
- ports:
- $ref: /schemas/graph.yaml#/properties/ports
- description: |
- Contains the list of output ports from DPU device. These ports
- connect to interfaces that are external to the DPU hardware,
- such as DSI, DP etc. Each output port contains an endpoint that
- describes how it is connected to an external interface.
-
- properties:
- port@0:
- $ref: /schemas/graph.yaml#/properties/port
- description: DPU_INTF1 (DSI1)
-
- port@1:
- $ref: /schemas/graph.yaml#/properties/port
- description: DPU_INTF2 (DSI2)
-
- required:
- - port@0
- - port@1
-
- required:
- - compatible
- - reg
- - reg-names
- - clocks
- - interrupts
- - power-domains
- - operating-points-v2
- - ports
-
-required:
- - compatible
- - reg
- - reg-names
- - power-domains
- - clocks
- - interrupts
- - interrupt-controller
- - iommus
- - ranges
-
-additionalProperties: false
-
-examples:
- - |
- #include <dt-bindings/clock/qcom,mmcc-msm8998.h>
- #include <dt-bindings/interrupt-controller/arm-gic.h>
- #include <dt-bindings/power/qcom-rpmpd.h>
-
- mdss: display-subsystem@c900000 {
- compatible = "qcom,msm8998-mdss";
- reg = <0x0c900000 0x1000>;
- reg-names = "mdss";
-
- clocks = <&mmcc MDSS_AHB_CLK>,
- <&mmcc MDSS_AXI_CLK>,
- <&mmcc MDSS_MDP_CLK>;
- clock-names = "iface", "bus", "core";
-
- #address-cells = <1>;
- #interrupt-cells = <1>;
- #size-cells = <1>;
-
- interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-controller;
- iommus = <&mmss_smmu 0>;
-
- power-domains = <&mmcc MDSS_GDSC>;
- ranges;
-
- display-controller@c901000 {
- compatible = "qcom,msm8998-dpu";
- reg = <0x0c901000 0x8f000>,
- <0x0c9a8e00 0xf0>,
- <0x0c9b0000 0x2008>,
- <0x0c9b8000 0x1040>;
- reg-names = "mdp", "regdma", "vbif", "vbif_nrt";
-
- clocks = <&mmcc MDSS_AHB_CLK>,
- <&mmcc MDSS_AXI_CLK>,
- <&mmcc MNOC_AHB_CLK>,
- <&mmcc MDSS_MDP_CLK>,
- <&mmcc MDSS_VSYNC_CLK>;
- clock-names = "iface", "bus", "mnoc", "core", "vsync";
-
- interrupt-parent = <&mdss>;
- interrupts = <0>;
- operating-points-v2 = <&mdp_opp_table>;
- power-domains = <&rpmpd MSM8998_VDDMX>;
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
- dpu_intf1_out: endpoint {
- remote-endpoint = <&dsi0_in>;
- };
- };
-
- port@1 {
- reg = <1>;
- dpu_intf2_out: endpoint {
- remote-endpoint = <&dsi1_in>;
- };
- };
- };
- };
- };
-...
diff --git a/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml b/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml
deleted file mode 100644
index c5824e1d2382..000000000000
--- a/Documentation/devicetree/bindings/display/msm/dpu-qcm2290.yaml
+++ /dev/null
@@ -1,222 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/display/msm/dpu-qcm2290.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Qualcomm Display DPU dt properties for QCM2290 target
-
-maintainers:
- - Loic Poulain <loic.poulain@linaro.org>
-
-description: |
- Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates
- sub-blocks like DPU display controller and DSI. Device tree bindings of MDSS
- and DPU are mentioned for QCM2290 target.
-
-properties:
- compatible:
- items:
- - const: qcom,qcm2290-mdss
-
- reg:
- maxItems: 1
-
- reg-names:
- const: mdss
-
- power-domains:
- maxItems: 1
-
- clocks:
- items:
- - description: Display AHB clock from gcc
- - description: Display AXI clock
- - description: Display core clock
-
- clock-names:
- items:
- - const: iface
- - const: bus
- - const: core
-
- interrupts:
- maxItems: 1
-
- interrupt-controller: true
-
- "#address-cells": true
-
- "#size-cells": true
-
- "#interrupt-cells":
- const: 1
-
- iommus:
- items:
- - description: Phandle to apps_smmu node with SID mask for Hard-Fail port0
- - description: Phandle to apps_smmu node with SID mask for Hard-Fail port1
-
- ranges: true
-
- interconnects:
- items:
- - description: Interconnect path specifying the port ids for data bus
-
- interconnect-names:
- const: mdp0-mem
-
- resets:
- items:
- - description: MDSS_CORE reset
-
-patternProperties:
- "^display-controller@[0-9a-f]+$":
- type: object
- description: Node containing the properties of DPU.
- additionalProperties: false
-
- properties:
- compatible:
- items:
- - const: qcom,qcm2290-dpu
-
- reg:
- items:
- - description: Address offset and size for mdp register set
- - description: Address offset and size for vbif register set
-
- reg-names:
- items:
- - const: mdp
- - const: vbif
-
- clocks:
- items:
- - description: Display AXI clock from gcc
- - description: Display AHB clock from dispcc
- - description: Display core clock from dispcc
- - description: Display lut clock from dispcc
- - description: Display vsync clock from dispcc
-
- clock-names:
- items:
- - const: bus
- - const: iface
- - const: core
- - const: lut
- - const: vsync
-
- interrupts:
- maxItems: 1
-
- power-domains:
- maxItems: 1
-
- operating-points-v2: true
- opp-table:
- type: object
-
- ports:
- $ref: /schemas/graph.yaml#/properties/ports
- description: |
- Contains the list of output ports from DPU device. These ports
- connect to interfaces that are external to the DPU hardware,
- such as DSI. Each output port contains an endpoint that
- describes how it is connected to an external interface.
-
- properties:
- port@0:
- $ref: /schemas/graph.yaml#/properties/port
- description: DPU_INTF1 (DSI1)
-
- required:
- - port@0
-
- required:
- - compatible
- - reg
- - reg-names
- - clocks
- - interrupts
- - power-domains
- - operating-points-v2
- - ports
-
-required:
- - compatible
- - reg
- - reg-names
- - power-domains
- - clocks
- - interrupts
- - interrupt-controller
- - iommus
- - ranges
-
-additionalProperties: false
-
-examples:
- - |
- #include <dt-bindings/clock/qcom,dispcc-qcm2290.h>
- #include <dt-bindings/clock/qcom,gcc-qcm2290.h>
- #include <dt-bindings/interrupt-controller/arm-gic.h>
- #include <dt-bindings/interconnect/qcom,qcm2290.h>
- #include <dt-bindings/power/qcom-rpmpd.h>
-
- mdss: mdss@5e00000 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "qcom,qcm2290-mdss";
- reg = <0x05e00000 0x1000>;
- reg-names = "mdss";
- power-domains = <&dispcc MDSS_GDSC>;
- clocks = <&gcc GCC_DISP_AHB_CLK>,
- <&gcc GCC_DISP_HF_AXI_CLK>,
- <&dispcc DISP_CC_MDSS_MDP_CLK>;
- clock-names = "iface", "bus", "core";
-
- interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-controller;
- #interrupt-cells = <1>;
-
- interconnects = <&mmrt_virt MASTER_MDP0 &bimc SLAVE_EBI1>;
- interconnect-names = "mdp0-mem";
-
- iommus = <&apps_smmu 0x420 0x2>,
- <&apps_smmu 0x421 0x0>;
- ranges;
-
- mdss_mdp: display-controller@5e01000 {
- compatible = "qcom,qcm2290-dpu";
- reg = <0x05e01000 0x8f000>,
- <0x05eb0000 0x2008>;
- reg-names = "mdp", "vbif";
-
- clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
- <&dispcc DISP_CC_MDSS_AHB_CLK>,
- <&dispcc DISP_CC_MDSS_MDP_CLK>,
- <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
- <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
- clock-names = "bus", "iface", "core", "lut", "vsync";
-
- operating-points-v2 = <&mdp_opp_table>;
- power-domains = <&rpmpd QCM2290_VDDCX>;
-
- interrupt-parent = <&mdss>;
- interrupts = <0>;
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
- dpu_intf1_out: endpoint {
- remote-endpoint = <&dsi0_in>;
- };
- };
- };
- };
- };
-...
diff --git a/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml b/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml
deleted file mode 100644
index 4890bc25f3fd..000000000000
--- a/Documentation/devicetree/bindings/display/msm/dpu-sc7180.yaml
+++ /dev/null
@@ -1,235 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/display/msm/dpu-sc7180.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Qualcomm Display DPU dt properties for SC7180 target
-
-maintainers:
- - Krishna Manikandan <quic_mkrishn@quicinc.com>
-
-description: |
- Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates
- sub-blocks like DPU display controller, DSI and DP interfaces etc. Device tree
- bindings of MDSS and DPU are mentioned for SC7180 target.
-
-properties:
- compatible:
- items:
- - const: qcom,sc7180-mdss
-
- reg:
- maxItems: 1
-
- reg-names:
- const: mdss
-
- power-domains:
- maxItems: 1
-
- clocks:
- items:
- - description: Display AHB clock from gcc
- - description: Display AHB clock from dispcc
- - description: Display core clock
-
- clock-names:
- items:
- - const: iface
- - const: ahb
- - const: core
-
- interrupts:
- maxItems: 1
-
- interrupt-controller: true
-
- "#address-cells": true
-
- "#size-cells": true
-
- "#interrupt-cells":
- const: 1
-
- iommus:
- items:
- - description: Phandle to apps_smmu node with SID mask for Hard-Fail port0
-
- ranges: true
-
- interconnects:
- items:
- - description: Interconnect path specifying the port ids for data bus
-
- interconnect-names:
- const: mdp0-mem
-
- resets:
- items:
- - description: MDSS_CORE reset
-
-patternProperties:
- "^display-controller@[0-9a-f]+$":
- type: object
- description: Node containing the properties of DPU.
- additionalProperties: false
-
- properties:
- compatible:
- items:
- - const: qcom,sc7180-dpu
-
- reg:
- items:
- - description: Address offset and size for mdp register set
- - description: Address offset and size for vbif register set
-
- reg-names:
- items:
- - const: mdp
- - const: vbif
-
- clocks:
- items:
- - description: Display hf axi clock
- - description: Display ahb clock
- - description: Display rotator clock
- - description: Display lut clock
- - description: Display core clock
- - description: Display vsync clock
-
- clock-names:
- items:
- - const: bus
- - const: iface
- - const: rot
- - const: lut
- - const: core
- - const: vsync
-
- interrupts:
- maxItems: 1
-
- power-domains:
- maxItems: 1
-
- operating-points-v2: true
- opp-table:
- type: object
-
- ports:
- $ref: /schemas/graph.yaml#/properties/ports
- description: |
- Contains the list of output ports from DPU device. These ports
- connect to interfaces that are external to the DPU hardware,
- such as DSI, DP etc. Each output port contains an endpoint that
- describes how it is connected to an external interface.
-
- properties:
- port@0:
- $ref: /schemas/graph.yaml#/properties/port
- description: DPU_INTF1 (DSI1)
-
- port@2:
- $ref: /schemas/graph.yaml#/properties/port
- description: DPU_INTF0 (DP)
-
- required:
- - port@0
-
- required:
- - compatible
- - reg
- - reg-names
- - clocks
- - interrupts
- - power-domains
- - operating-points-v2
- - ports
-
-required:
- - compatible
- - reg
- - reg-names
- - power-domains
- - clocks
- - interrupts
- - interrupt-controller
- - iommus
- - ranges
-
-additionalProperties: false
-
-examples:
- - |
- #include <dt-bindings/clock/qcom,dispcc-sc7180.h>
- #include <dt-bindings/clock/qcom,gcc-sc7180.h>
- #include <dt-bindings/interrupt-controller/arm-gic.h>
- #include <dt-bindings/interconnect/qcom,sdm845.h>
- #include <dt-bindings/power/qcom-rpmpd.h>
-
- display-subsystem@ae00000 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "qcom,sc7180-mdss";
- reg = <0xae00000 0x1000>;
- reg-names = "mdss";
- power-domains = <&dispcc MDSS_GDSC>;
- clocks = <&gcc GCC_DISP_AHB_CLK>,
- <&dispcc DISP_CC_MDSS_AHB_CLK>,
- <&dispcc DISP_CC_MDSS_MDP_CLK>;
- clock-names = "iface", "ahb", "core";
-
- interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-controller;
- #interrupt-cells = <1>;
-
- interconnects = <&mmss_noc MASTER_MDP0 &mc_virt SLAVE_EBI1>;
- interconnect-names = "mdp0-mem";
-
- iommus = <&apps_smmu 0x800 0x2>;
- ranges;
-
- display-controller@ae01000 {
- compatible = "qcom,sc7180-dpu";
- reg = <0x0ae01000 0x8f000>,
- <0x0aeb0000 0x2008>;
-
- reg-names = "mdp", "vbif";
-
- clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
- <&dispcc DISP_CC_MDSS_AHB_CLK>,
- <&dispcc DISP_CC_MDSS_ROT_CLK>,
- <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
- <&dispcc DISP_CC_MDSS_MDP_CLK>,
- <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
- clock-names = "bus", "iface", "rot", "lut", "core",
- "vsync";
-
- interrupt-parent = <&mdss>;
- interrupts = <0>;
- power-domains = <&rpmhpd SC7180_CX>;
- operating-points-v2 = <&mdp_opp_table>;
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
- dpu_intf1_out: endpoint {
- remote-endpoint = <&dsi0_in>;
- };
- };
-
- port@2 {
- reg = <2>;
- dpu_intf0_out: endpoint {
- remote-endpoint = <&dp_in>;
- };
- };
- };
- };
- };
-...
diff --git a/Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml b/Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml
deleted file mode 100644
index 584d646021d5..000000000000
--- a/Documentation/devicetree/bindings/display/msm/dpu-sc7280.yaml
+++ /dev/null
@@ -1,239 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/display/msm/dpu-sc7280.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Qualcomm Display DPU dt properties for SC7280
-
-maintainers:
- - Krishna Manikandan <quic_mkrishn@quicinc.com>
-
-description: |
- Device tree bindings for MSM Mobile Display Subsystem (MDSS) that encapsulates
- sub-blocks like DPU display controller, DSI and DP interfaces etc. Device tree
- bindings of MDSS and DPU are mentioned for SC7280.
-
-properties:
- compatible:
- const: qcom,sc7280-mdss
-
- reg:
- maxItems: 1
-
- reg-names:
- const: mdss
-
- power-domains:
- maxItems: 1
-
- clocks:
- items:
- - description: Display AHB clock from gcc
- - description: Display AHB clock from dispcc
- - description: Display core clock
-
- clock-names:
- items:
- - const: iface
- - const: ahb
- - const: core
-
- interrupts:
- maxItems: 1
-
- interrupt-controller: true
-
- "#address-cells": true
-
- "#size-cells": true
-
- "#interrupt-cells":
- const: 1
-
- iommus:
- items:
- - description: Phandle to apps_smmu node with SID mask for Hard-Fail port0
-
- ranges: true
-
- interconnects:
- items:
- - description: Interconnect path specifying the port ids for data bus
-
- interconnect-names:
- const: mdp0-mem
-
- resets:
- items:
- - description: MDSS_CORE reset
-
-patternProperties:
- "^display-controller@[0-9a-f]+$":
- type: object
- description: Node containing the properties of DPU.
- additionalProperties: false
-
- properties:
- compatible:
- const: qcom,sc7280-dpu
-
- reg:
- items:
- - description: Address offset and size for mdp register set
- - description: Address offset and size for vbif register set
-
- reg-names:
- items:
- - const: mdp
- - const: vbif
-
- clocks:
- items:
- - description: Display hf axi clock
- - description: Display sf axi clock
- - description: Display ahb clock
- - description: Display lut clock
- - description: Display core clock
- - description: Display vsync clock
-
- clock-names:
- items:
- - const: bus
- - const: nrt_bus
- - const: iface
- - const: lut
- - const: core
- - const: vsync
-
- interrupts:
- maxItems: 1
-
- power-domains:
- maxItems: 1
-
- operating-points-v2: true
- opp-table:
- type: object
-
- ports:
- $ref: /schemas/graph.yaml#/properties/ports
- description: |
- Contains the list of output ports from DPU device. These ports
- connect to interfaces that are external to the DPU hardware,
- such as DSI, DP etc. Each output port contains an endpoint that
- describes how it is connected to an external interface.
-
- properties:
- port@0:
- $ref: /schemas/graph.yaml#/properties/port
- description: DPU_INTF1 (DSI)
-
- port@1:
- $ref: /schemas/graph.yaml#/properties/port
- description: DPU_INTF5 (EDP)
-
- required:
- - port@0
-
- required:
- - compatible
- - reg
- - reg-names
- - clocks
- - interrupts
- - power-domains
- - operating-points-v2
- - ports
-
-required:
- - compatible
- - reg
- - reg-names
- - power-domains
- - clocks
- - interrupts
- - interrupt-controller
- - iommus
- - ranges
-
-additionalProperties: false
-
-examples:
- - |
- #include <dt-bindings/clock/qcom,dispcc-sc7280.h>
- #include <dt-bindings/clock/qcom,gcc-sc7280.h>
- #include <dt-bindings/interrupt-controller/arm-gic.h>
- #include <dt-bindings/interconnect/qcom,sc7280.h>
- #include <dt-bindings/power/qcom-rpmpd.h>
-
- display-subsystem@ae00000 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "qcom,sc7280-mdss";
- reg = <0xae00000 0x1000>;
- reg-names = "mdss";
- power-domains = <&dispcc DISP_CC_MDSS_CORE_GDSC>;
- clocks = <&gcc GCC_DISP_AHB_CLK>,
- <&dispcc DISP_CC_MDSS_AHB_CLK>,
- <&dispcc DISP_CC_MDSS_MDP_CLK>;
- clock-names = "iface",
- "ahb",
- "core";
-
- interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-controller;
- #interrupt-cells = <1>;
-
- interconnects = <&mmss_noc MASTER_MDP0 &mc_virt SLAVE_EBI1>;
- interconnect-names = "mdp0-mem";
-
- iommus = <&apps_smmu 0x900 0x402>;
- ranges;
-
- display-controller@ae01000 {
- compatible = "qcom,sc7280-dpu";
- reg = <0x0ae01000 0x8f000>,
- <0x0aeb0000 0x2008>;
-
- reg-names = "mdp", "vbif";
-
- clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
- <&gcc GCC_DISP_SF_AXI_CLK>,
- <&dispcc DISP_CC_MDSS_AHB_CLK>,
- <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
- <&dispcc DISP_CC_MDSS_MDP_CLK>,
- <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
- clock-names = "bus",
- "nrt_bus",
- "iface",
- "lut",
- "core",
- "vsync";
-
- interrupt-parent = <&mdss>;
- interrupts = <0>;
- power-domains = <&rpmhpd SC7280_CX>;
- operating-points-v2 = <&mdp_opp_table>;
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
- dpu_intf1_out: endpoint {
- remote-endpoint = <&dsi0_in>;
- };
- };
-
- port@1 {
- reg = <1>;
- dpu_intf5_out: endpoint {
- remote-endpoint = <&edp_in>;
- };
- };
- };
- };
- };
-...
diff --git a/Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml b/Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml
deleted file mode 100644
index 7d1037373175..000000000000
--- a/Documentation/devicetree/bindings/display/msm/dpu-sdm845.yaml
+++ /dev/null
@@ -1,217 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/display/msm/dpu-sdm845.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Qualcomm Display DPU dt properties for SDM845 target
-
-maintainers:
- - Krishna Manikandan <quic_mkrishn@quicinc.com>
-
-description: |
- Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates
- sub-blocks like DPU display controller, DSI and DP interfaces etc. Device tree
- bindings of MDSS and DPU are mentioned for SDM845 target.
-
-properties:
- compatible:
- items:
- - const: qcom,sdm845-mdss
-
- reg:
- maxItems: 1
-
- reg-names:
- const: mdss
-
- power-domains:
- maxItems: 1
-
- clocks:
- items:
- - description: Display AHB clock from gcc
- - description: Display core clock
-
- clock-names:
- items:
- - const: iface
- - const: core
-
- interrupts:
- maxItems: 1
-
- interrupt-controller: true
-
- "#address-cells": true
-
- "#size-cells": true
-
- "#interrupt-cells":
- const: 1
-
- iommus:
- items:
- - description: Phandle to apps_smmu node with SID mask for Hard-Fail port0
- - description: Phandle to apps_smmu node with SID mask for Hard-Fail port1
-
- ranges: true
-
- resets:
- items:
- - description: MDSS_CORE reset
-
-patternProperties:
- "^display-controller@[0-9a-f]+$":
- type: object
- description: Node containing the properties of DPU.
- additionalProperties: false
-
- properties:
- compatible:
- items:
- - const: qcom,sdm845-dpu
-
- reg:
- items:
- - description: Address offset and size for mdp register set
- - description: Address offset and size for vbif register set
-
- reg-names:
- items:
- - const: mdp
- - const: vbif
-
- clocks:
- items:
- - description: Display ahb clock
- - description: Display axi clock
- - description: Display core clock
- - description: Display vsync clock
-
- clock-names:
- items:
- - const: iface
- - const: bus
- - const: core
- - const: vsync
-
- interrupts:
- maxItems: 1
-
- power-domains:
- maxItems: 1
-
- operating-points-v2: true
- opp-table:
- type: object
-
- ports:
- $ref: /schemas/graph.yaml#/properties/ports
- description: |
- Contains the list of output ports from DPU device. These ports
- connect to interfaces that are external to the DPU hardware,
- such as DSI, DP etc. Each output port contains an endpoint that
- describes how it is connected to an external interface.
-
- properties:
- port@0:
- $ref: /schemas/graph.yaml#/properties/port
- description: DPU_INTF1 (DSI1)
-
- port@1:
- $ref: /schemas/graph.yaml#/properties/port
- description: DPU_INTF2 (DSI2)
-
- required:
- - port@0
- - port@1
-
- required:
- - compatible
- - reg
- - reg-names
- - clocks
- - interrupts
- - power-domains
- - operating-points-v2
- - ports
-
-required:
- - compatible
- - reg
- - reg-names
- - power-domains
- - clocks
- - interrupts
- - interrupt-controller
- - iommus
- - ranges
-
-additionalProperties: false
-
-examples:
- - |
- #include <dt-bindings/clock/qcom,dispcc-sdm845.h>
- #include <dt-bindings/clock/qcom,gcc-sdm845.h>
- #include <dt-bindings/interrupt-controller/arm-gic.h>
- #include <dt-bindings/power/qcom-rpmpd.h>
-
- display-subsystem@ae00000 {
- #address-cells = <1>;
- #size-cells = <1>;
- compatible = "qcom,sdm845-mdss";
- reg = <0x0ae00000 0x1000>;
- reg-names = "mdss";
- power-domains = <&dispcc MDSS_GDSC>;
-
- clocks = <&gcc GCC_DISP_AHB_CLK>,
- <&dispcc DISP_CC_MDSS_MDP_CLK>;
- clock-names = "iface", "core";
-
- interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-controller;
- #interrupt-cells = <1>;
-
- iommus = <&apps_smmu 0x880 0x8>,
- <&apps_smmu 0xc80 0x8>;
- ranges;
-
- display-controller@ae01000 {
- compatible = "qcom,sdm845-dpu";
- reg = <0x0ae01000 0x8f000>,
- <0x0aeb0000 0x2008>;
- reg-names = "mdp", "vbif";
-
- clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
- <&dispcc DISP_CC_MDSS_AXI_CLK>,
- <&dispcc DISP_CC_MDSS_MDP_CLK>,
- <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
- clock-names = "iface", "bus", "core", "vsync";
-
- interrupt-parent = <&mdss>;
- interrupts = <0>;
- power-domains = <&rpmhpd SDM845_CX>;
- operating-points-v2 = <&mdp_opp_table>;
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
-
- port@0 {
- reg = <0>;
- dpu_intf1_out: endpoint {
- remote-endpoint = <&dsi0_in>;
- };
- };
-
- port@1 {
- reg = <1>;
- dpu_intf2_out: endpoint {
- remote-endpoint = <&dsi1_in>;
- };
- };
- };
- };
- };
-...
diff --git a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
index 3b609c19e0bc..f2c143730a55 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
@@ -49,6 +49,7 @@ properties:
maxItems: 1
phy-names:
+ deprecated: true
const: dsi
"#address-cells": true
@@ -80,6 +81,9 @@ properties:
operating-points-v2: true
+ opp-table:
+ type: object
+
ports:
$ref: "/schemas/graph.yaml#/properties/ports"
description: |
@@ -131,7 +135,6 @@ required:
- clocks
- clock-names
- phys
- - phy-names
- assigned-clocks
- assigned-clock-parents
- power-domains
diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml
index 1342d74ecfe0..819de5ce0bc9 100644
--- a/Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml
@@ -16,6 +16,7 @@ properties:
compatible:
enum:
- qcom,dsi-phy-14nm
+ - qcom,dsi-phy-14nm-2290
- qcom,dsi-phy-14nm-660
- qcom,dsi-phy-14nm-8953
diff --git a/Documentation/devicetree/bindings/display/msm/mdp5.txt b/Documentation/devicetree/bindings/display/msm/mdp5.txt
index 43d11279c925..65d03c58dee6 100644
--- a/Documentation/devicetree/bindings/display/msm/mdp5.txt
+++ b/Documentation/devicetree/bindings/display/msm/mdp5.txt
@@ -2,37 +2,9 @@ Qualcomm adreno/snapdragon MDP5 display controller
Description:
-This is the bindings documentation for the Mobile Display Subsytem(MDSS) that
-encapsulates sub-blocks like MDP5, DSI, HDMI, eDP etc, and the MDP5 display
+This is the bindings documentation for the MDP5 display
controller found in SoCs like MSM8974, APQ8084, MSM8916, MSM8994 and MSM8996.
-MDSS:
-Required properties:
-- compatible:
- * "qcom,mdss" - MDSS
-- reg: Physical base address and length of the controller's registers.
-- reg-names: The names of register regions. The following regions are required:
- * "mdss_phys"
- * "vbif_phys"
-- interrupts: The interrupt signal from MDSS.
-- interrupt-controller: identifies the node as an interrupt controller.
-- #interrupt-cells: specifies the number of cells needed to encode an interrupt
- source, should be 1.
-- power-domains: a power domain consumer specifier according to
- Documentation/devicetree/bindings/power/power_domain.txt
-- clocks: device clocks. See ../clocks/clock-bindings.txt for details.
-- clock-names: the following clocks are required.
- * "iface"
- * "bus"
- * "vsync"
-- #address-cells: number of address cells for the MDSS children. Should be 1.
-- #size-cells: Should be 1.
-- ranges: parent bus address space is the same as the child bus address space.
-
-Optional properties:
-- clock-names: the following clocks are optional:
- * "lut"
-
MDP5:
Required properties:
- compatible:
diff --git a/Documentation/devicetree/bindings/display/msm/mdss-common.yaml b/Documentation/devicetree/bindings/display/msm/mdss-common.yaml
new file mode 100644
index 000000000000..27d7242657b2
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/mdss-common.yaml
@@ -0,0 +1,83 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/mdss-common.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Display MDSS common properties
+
+maintainers:
+ - Krishna Manikandan <quic_mkrishn@quicinc.com>
+ - Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+ - Rob Clark <robdclark@gmail.com>
+
+description:
+ Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates
+ sub-blocks like DPU display controller, DSI and DP interfaces etc.
+
+properties:
+ reg:
+ maxItems: 1
+
+ reg-names:
+ const: mdss
+
+ power-domains:
+ maxItems: 1
+
+ clocks:
+ minItems: 2
+ maxItems: 4
+
+ clock-names:
+ minItems: 2
+ maxItems: 4
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ "#address-cells": true
+
+ "#size-cells": true
+
+ "#interrupt-cells":
+ const: 1
+
+ iommus:
+ minItems: 1
+ items:
+ - description: Phandle to apps_smmu node with SID mask for Hard-Fail port0
+ - description: Phandle to apps_smmu node with SID mask for Hard-Fail port1
+
+ ranges: true
+
+ interconnects:
+ minItems: 1
+ items:
+ - description: Interconnect path from mdp0 (or a single mdp) port to the data bus
+ - description: Interconnect path from mdp1 port to the data bus
+
+ interconnect-names:
+ minItems: 1
+ items:
+ - const: mdp0-mem
+ - const: mdp1-mem
+
+ resets:
+ items:
+ - description: MDSS_CORE reset
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - power-domains
+ - clocks
+ - interrupts
+ - interrupt-controller
+ - iommus
+ - ranges
+
+additionalProperties: true
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,mdss.yaml
new file mode 100644
index 000000000000..ba0460268731
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,mdss.yaml
@@ -0,0 +1,196 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,mdss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Mobile Display SubSystem (MDSS)
+
+maintainers:
+ - Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+ - Rob Clark <robdclark@gmail.com>
+
+description:
+ This is the bindings documentation for the Mobile Display Subsytem(MDSS) that
+ encapsulates sub-blocks like MDP5, DSI, HDMI, eDP, etc.
+
+properties:
+ compatible:
+ enum:
+ - qcom,mdss
+
+ reg:
+ minItems: 2
+ maxItems: 3
+
+ reg-names:
+ minItems: 2
+ items:
+ - const: mdss_phys
+ - const: vbif_phys
+ - const: vbif_nrt_phys
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ "#interrupt-cells":
+ const: 1
+
+ power-domains:
+ maxItems: 1
+ description: |
+ The MDSS power domain provided by GCC
+
+ clocks:
+ minItems: 1
+ items:
+ - description: Display abh clock
+ - description: Display axi clock
+ - description: Display vsync clock
+
+ clock-names:
+ minItems: 1
+ items:
+ - const: iface
+ - const: bus
+ - const: vsync
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 1
+
+ ranges: true
+
+ resets:
+ items:
+ - description: MDSS_CORE reset
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - interrupts
+ - interrupt-controller
+ - "#interrupt-cells"
+ - power-domains
+ - clocks
+ - clock-names
+ - "#address-cells"
+ - "#size-cells"
+ - ranges
+
+patternProperties:
+ "^mdp@[1-9a-f][0-9a-f]*$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,mdp5
+
+ "^dsi@[1-9a-f][0-9a-f]*$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,mdss-dsi-ctrl
+
+ "^phy@[1-9a-f][0-9a-f]*$":
+ type: object
+ properties:
+ compatible:
+ enum:
+ - qcom,dsi-phy-14nm
+ - qcom,dsi-phy-14nm-660
+ - qcom,dsi-phy-14nm-8953
+ - qcom,dsi-phy-20nm
+ - qcom,dsi-phy-28nm-hpm
+ - qcom,dsi-phy-28nm-lp
+
+ "^hdmi-phy@[1-9a-f][0-9a-f]*$":
+ type: object
+ properties:
+ compatible:
+ enum:
+ - qcom,hdmi-phy-8084
+ - qcom,hdmi-phy-8660
+ - qcom,hdmi-phy-8960
+ - qcom,hdmi-phy-8974
+ - qcom,hdmi-phy-8996
+
+ "^hdmi-tx@[1-9a-f][0-9a-f]*$":
+ type: object
+ properties:
+ compatible:
+ enum:
+ - qcom,hdmi-tx-8084
+ - qcom,hdmi-tx-8660
+ - qcom,hdmi-tx-8960
+ - qcom,hdmi-tx-8974
+ - qcom,hdmi-tx-8994
+ - qcom,hdmi-tx-8996
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,gcc-msm8916.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ mdss@1a00000 {
+ compatible = "qcom,mdss";
+ reg = <0x1a00000 0x1000>,
+ <0x1ac8000 0x3000>;
+ reg-names = "mdss_phys", "vbif_phys";
+
+ power-domains = <&gcc MDSS_GDSC>;
+
+ clocks = <&gcc GCC_MDSS_AHB_CLK>,
+ <&gcc GCC_MDSS_AXI_CLK>,
+ <&gcc GCC_MDSS_VSYNC_CLK>;
+ clock-names = "iface",
+ "bus",
+ "vsync";
+
+ interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ mdp@1a01000 {
+ compatible = "qcom,mdp5";
+ reg = <0x01a01000 0x89000>;
+ reg-names = "mdp_phys";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+
+ clocks = <&gcc GCC_MDSS_AHB_CLK>,
+ <&gcc GCC_MDSS_AXI_CLK>,
+ <&gcc GCC_MDSS_MDP_CLK>,
+ <&gcc GCC_MDSS_VSYNC_CLK>;
+ clock-names = "iface",
+ "bus",
+ "core",
+ "vsync";
+
+ iommus = <&apps_iommu 4>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ mdp5_intf1_out: endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,msm8998-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,msm8998-dpu.yaml
new file mode 100644
index 000000000000..b02adba36e9e
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,msm8998-dpu.yaml
@@ -0,0 +1,95 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,msm8998-dpu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Display DPU dt properties for MSM8998 target
+
+maintainers:
+ - AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
+
+$ref: /schemas/display/msm/dpu-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - const: qcom,msm8998-dpu
+
+ reg:
+ items:
+ - description: Address offset and size for mdp register set
+ - description: Address offset and size for regdma register set
+ - description: Address offset and size for vbif register set
+ - description: Address offset and size for non-realtime vbif register set
+
+ reg-names:
+ items:
+ - const: mdp
+ - const: regdma
+ - const: vbif
+ - const: vbif_nrt
+
+ clocks:
+ items:
+ - description: Display ahb clock
+ - description: Display axi clock
+ - description: Display mem-noc clock
+ - description: Display core clock
+ - description: Display vsync clock
+
+ clock-names:
+ items:
+ - const: iface
+ - const: bus
+ - const: mnoc
+ - const: core
+ - const: vsync
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,mmcc-msm8998.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ display-controller@c901000 {
+ compatible = "qcom,msm8998-dpu";
+ reg = <0x0c901000 0x8f000>,
+ <0x0c9a8e00 0xf0>,
+ <0x0c9b0000 0x2008>,
+ <0x0c9b8000 0x1040>;
+ reg-names = "mdp", "regdma", "vbif", "vbif_nrt";
+
+ clocks = <&mmcc MDSS_AHB_CLK>,
+ <&mmcc MDSS_AXI_CLK>,
+ <&mmcc MNOC_AHB_CLK>,
+ <&mmcc MDSS_MDP_CLK>,
+ <&mmcc MDSS_VSYNC_CLK>;
+ clock-names = "iface", "bus", "mnoc", "core", "vsync";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+ operating-points-v2 = <&mdp_opp_table>;
+ power-domains = <&rpmpd MSM8998_VDDMX>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ endpoint {
+ remote-endpoint = <&dsi1_in>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,msm8998-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,msm8998-mdss.yaml
new file mode 100644
index 000000000000..cf52ff77a41a
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,msm8998-mdss.yaml
@@ -0,0 +1,268 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,msm8998-mdss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm MSM8998 Display MDSS
+
+maintainers:
+ - AngeloGioacchino Del Regno <angelogioacchino.delregno@somainline.org>
+
+description:
+ Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates
+ sub-blocks like DPU display controller, DSI and DP interfaces etc. Device tree
+ bindings of MDSS are mentioned for MSM8998 target.
+
+$ref: /schemas/display/msm/mdss-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - const: qcom,msm8998-mdss
+
+ clocks:
+ items:
+ - description: Display AHB clock
+ - description: Display AXI clock
+ - description: Display core clock
+
+ clock-names:
+ items:
+ - const: iface
+ - const: bus
+ - const: core
+
+ iommus:
+ maxItems: 1
+
+patternProperties:
+ "^display-controller@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,msm8998-dpu
+
+ "^dsi@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,mdss-dsi-ctrl
+
+ "^phy@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,dsi-phy-10nm-8998
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,mmcc-msm8998.h>
+ #include <dt-bindings/clock/qcom,rpmcc.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ display-subsystem@c900000 {
+ compatible = "qcom,msm8998-mdss";
+ reg = <0x0c900000 0x1000>;
+ reg-names = "mdss";
+
+ clocks = <&mmcc MDSS_AHB_CLK>,
+ <&mmcc MDSS_AXI_CLK>,
+ <&mmcc MDSS_MDP_CLK>;
+ clock-names = "iface", "bus", "core";
+
+ #address-cells = <1>;
+ #interrupt-cells = <1>;
+ #size-cells = <1>;
+
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ iommus = <&mmss_smmu 0>;
+
+ power-domains = <&mmcc MDSS_GDSC>;
+ ranges;
+
+ display-controller@c901000 {
+ compatible = "qcom,msm8998-dpu";
+ reg = <0x0c901000 0x8f000>,
+ <0x0c9a8e00 0xf0>,
+ <0x0c9b0000 0x2008>,
+ <0x0c9b8000 0x1040>;
+ reg-names = "mdp", "regdma", "vbif", "vbif_nrt";
+
+ clocks = <&mmcc MDSS_AHB_CLK>,
+ <&mmcc MDSS_AXI_CLK>,
+ <&mmcc MNOC_AHB_CLK>,
+ <&mmcc MDSS_MDP_CLK>,
+ <&mmcc MDSS_VSYNC_CLK>;
+ clock-names = "iface", "bus", "mnoc", "core", "vsync";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+ operating-points-v2 = <&mdp_opp_table>;
+ power-domains = <&rpmpd MSM8998_VDDMX>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dpu_intf1_out: endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dpu_intf2_out: endpoint {
+ remote-endpoint = <&dsi1_in>;
+ };
+ };
+ };
+ };
+
+ dsi@c994000 {
+ compatible = "qcom,mdss-dsi-ctrl";
+ reg = <0x0c994000 0x400>;
+ reg-names = "dsi_ctrl";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <4>;
+
+ clocks = <&mmcc MDSS_BYTE0_CLK>,
+ <&mmcc MDSS_BYTE0_INTF_CLK>,
+ <&mmcc MDSS_PCLK0_CLK>,
+ <&mmcc MDSS_ESC0_CLK>,
+ <&mmcc MDSS_AHB_CLK>,
+ <&mmcc MDSS_AXI_CLK>;
+ clock-names = "byte",
+ "byte_intf",
+ "pixel",
+ "core",
+ "iface",
+ "bus";
+ assigned-clocks = <&mmcc BYTE0_CLK_SRC>, <&mmcc PCLK0_CLK_SRC>;
+ assigned-clock-parents = <&dsi0_phy 0>, <&dsi0_phy 1>;
+
+ operating-points-v2 = <&dsi_opp_table>;
+ power-domains = <&rpmpd MSM8998_VDDCX>;
+
+ phys = <&dsi0_phy>;
+ phy-names = "dsi";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dsi0_in: endpoint {
+ remote-endpoint = <&dpu_intf1_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dsi0_out: endpoint {
+ };
+ };
+ };
+ };
+
+ dsi0_phy: phy@c994400 {
+ compatible = "qcom,dsi-phy-10nm-8998";
+ reg = <0x0c994400 0x200>,
+ <0x0c994600 0x280>,
+ <0x0c994a00 0x1e0>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ clocks = <&mmcc MDSS_AHB_CLK>,
+ <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "iface", "ref";
+
+ vdds-supply = <&pm8998_l1>;
+ };
+
+ dsi@c996000 {
+ compatible = "qcom,mdss-dsi-ctrl";
+ reg = <0x0c996000 0x400>;
+ reg-names = "dsi_ctrl";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <5>;
+
+ clocks = <&mmcc MDSS_BYTE1_CLK>,
+ <&mmcc MDSS_BYTE1_INTF_CLK>,
+ <&mmcc MDSS_PCLK1_CLK>,
+ <&mmcc MDSS_ESC1_CLK>,
+ <&mmcc MDSS_AHB_CLK>,
+ <&mmcc MDSS_AXI_CLK>;
+ clock-names = "byte",
+ "byte_intf",
+ "pixel",
+ "core",
+ "iface",
+ "bus";
+ assigned-clocks = <&mmcc BYTE1_CLK_SRC>, <&mmcc PCLK1_CLK_SRC>;
+ assigned-clock-parents = <&dsi1_phy 0>, <&dsi1_phy 1>;
+
+ operating-points-v2 = <&dsi_opp_table>;
+ power-domains = <&rpmpd MSM8998_VDDCX>;
+
+ phys = <&dsi1_phy>;
+ phy-names = "dsi";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dsi1_in: endpoint {
+ remote-endpoint = <&dpu_intf2_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dsi1_out: endpoint {
+ };
+ };
+ };
+ };
+
+ dsi1_phy: phy@c996400 {
+ compatible = "qcom,dsi-phy-10nm-8998";
+ reg = <0x0c996400 0x200>,
+ <0x0c996600 0x280>,
+ <0x0c996a00 0x10e>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ clocks = <&mmcc MDSS_AHB_CLK>,
+ <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "iface", "ref";
+
+ vdds-supply = <&pm8998_l1>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml
new file mode 100644
index 000000000000..a7b382f01b56
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-dpu.yaml
@@ -0,0 +1,84 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,qcm2290-dpu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Display DPU dt properties for QCM2290 target
+
+maintainers:
+ - Loic Poulain <loic.poulain@linaro.org>
+
+$ref: /schemas/display/msm/dpu-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - const: qcom,qcm2290-dpu
+
+ reg:
+ items:
+ - description: Address offset and size for mdp register set
+ - description: Address offset and size for vbif register set
+
+ reg-names:
+ items:
+ - const: mdp
+ - const: vbif
+
+ clocks:
+ items:
+ - description: Display AXI clock from gcc
+ - description: Display AHB clock from dispcc
+ - description: Display core clock from dispcc
+ - description: Display lut clock from dispcc
+ - description: Display vsync clock from dispcc
+
+ clock-names:
+ items:
+ - const: bus
+ - const: iface
+ - const: core
+ - const: lut
+ - const: vsync
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,dispcc-qcm2290.h>
+ #include <dt-bindings/clock/qcom,gcc-qcm2290.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ display-controller@5e01000 {
+ compatible = "qcom,qcm2290-dpu";
+ reg = <0x05e01000 0x8f000>,
+ <0x05eb0000 0x2008>;
+ reg-names = "mdp", "vbif";
+
+ clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
+ <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ clock-names = "bus", "iface", "core", "lut", "vsync";
+
+ operating-points-v2 = <&mdp_opp_table>;
+ power-domains = <&rpmpd QCM2290_VDDCX>;
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml
new file mode 100644
index 000000000000..d6f043a4b08d
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,qcm2290-mdss.yaml
@@ -0,0 +1,198 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,qcm2290-mdss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm QCM220 Display MDSS
+
+maintainers:
+ - Loic Poulain <loic.poulain@linaro.org>
+
+description:
+ Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates
+ sub-blocks like DPU display controller and DSI. Device tree bindings of MDSS
+ are mentioned for QCM2290 target.
+
+$ref: /schemas/display/msm/mdss-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - const: qcom,qcm2290-mdss
+
+ clocks:
+ items:
+ - description: Display AHB clock from gcc
+ - description: Display AXI clock
+ - description: Display core clock
+
+ clock-names:
+ items:
+ - const: iface
+ - const: bus
+ - const: core
+
+ iommus:
+ maxItems: 2
+
+ interconnects:
+ maxItems: 1
+
+ interconnect-names:
+ maxItems: 1
+
+patternProperties:
+ "^display-controller@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,qcm2290-dpu
+
+ "^dsi@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,dsi-ctrl-6g-qcm2290
+
+ "^phy@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,dsi-phy-14nm-2290
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,dispcc-qcm2290.h>
+ #include <dt-bindings/clock/qcom,gcc-qcm2290.h>
+ #include <dt-bindings/clock/qcom,rpmcc.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interconnect/qcom,qcm2290.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ mdss@5e00000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,qcm2290-mdss";
+ reg = <0x05e00000 0x1000>;
+ reg-names = "mdss";
+ power-domains = <&dispcc MDSS_GDSC>;
+ clocks = <&gcc GCC_DISP_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>;
+ clock-names = "iface", "bus", "core";
+
+ interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interconnects = <&mmrt_virt MASTER_MDP0 &bimc SLAVE_EBI1>;
+ interconnect-names = "mdp0-mem";
+
+ iommus = <&apps_smmu 0x420 0x2>,
+ <&apps_smmu 0x421 0x0>;
+ ranges;
+
+ display-controller@5e01000 {
+ compatible = "qcom,qcm2290-dpu";
+ reg = <0x05e01000 0x8f000>,
+ <0x05eb0000 0x2008>;
+ reg-names = "mdp", "vbif";
+
+ clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
+ <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ clock-names = "bus", "iface", "core", "lut", "vsync";
+
+ operating-points-v2 = <&mdp_opp_table>;
+ power-domains = <&rpmpd QCM2290_VDDCX>;
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dpu_intf1_out: endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+ };
+ };
+
+ dsi@5e94000 {
+ compatible = "qcom,dsi-ctrl-6g-qcm2290";
+ reg = <0x05e94000 0x400>;
+ reg-names = "dsi_ctrl";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <4>;
+
+ clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
+ <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_PCLK0_CLK>,
+ <&dispcc DISP_CC_MDSS_ESC0_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>;
+ clock-names = "byte",
+ "byte_intf",
+ "pixel",
+ "core",
+ "iface",
+ "bus";
+ assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>, <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+ assigned-clock-parents = <&dsi0_phy 0>, <&dsi0_phy 1>;
+
+ operating-points-v2 = <&dsi_opp_table>;
+ power-domains = <&rpmpd QCM2290_VDDCX>;
+
+ phys = <&dsi0_phy>;
+ phy-names = "dsi";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dsi0_in: endpoint {
+ remote-endpoint = <&dpu_intf1_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dsi0_out: endpoint {
+ };
+ };
+ };
+ };
+
+ dsi0_phy: phy@5e94400 {
+ compatible = "qcom,dsi-phy-14nm-2290";
+ reg = <0x05e94400 0x100>,
+ <0x05e94500 0x300>,
+ <0x05e94800 0x188>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "iface", "ref";
+ vcca-supply = <&vreg_dsi_phy>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sc7180-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sc7180-dpu.yaml
new file mode 100644
index 000000000000..bd590a6b5b96
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sc7180-dpu.yaml
@@ -0,0 +1,95 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,sc7180-dpu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Display DPU dt properties for SC7180 target
+
+maintainers:
+ - Krishna Manikandan <quic_mkrishn@quicinc.com>
+
+$ref: /schemas/display/msm/dpu-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - const: qcom,sc7180-dpu
+
+ reg:
+ items:
+ - description: Address offset and size for mdp register set
+ - description: Address offset and size for vbif register set
+
+ reg-names:
+ items:
+ - const: mdp
+ - const: vbif
+
+ clocks:
+ items:
+ - description: Display hf axi clock
+ - description: Display ahb clock
+ - description: Display rotator clock
+ - description: Display lut clock
+ - description: Display core clock
+ - description: Display vsync clock
+
+ clock-names:
+ items:
+ - const: bus
+ - const: iface
+ - const: rot
+ - const: lut
+ - const: core
+ - const: vsync
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,dispcc-sc7180.h>
+ #include <dt-bindings/clock/qcom,gcc-sc7180.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ display-controller@ae01000 {
+ compatible = "qcom,sc7180-dpu";
+ reg = <0x0ae01000 0x8f000>,
+ <0x0aeb0000 0x2008>;
+
+ reg-names = "mdp", "vbif";
+
+ clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_ROT_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>,
+ <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ clock-names = "bus", "iface", "rot", "lut", "core",
+ "vsync";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+ power-domains = <&rpmhpd SC7180_CX>;
+ operating-points-v2 = <&mdp_opp_table>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ endpoint {
+ remote-endpoint = <&dp_in>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sc7180-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sc7180-mdss.yaml
new file mode 100644
index 000000000000..13e396d61a51
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sc7180-mdss.yaml
@@ -0,0 +1,304 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,sc7180-mdss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SC7180 Display MDSS
+
+maintainers:
+ - Krishna Manikandan <quic_mkrishn@quicinc.com>
+
+description:
+ Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates
+ sub-blocks like DPU display controller, DSI and DP interfaces etc. Device tree
+ bindings of MDSS are mentioned for SC7180 target.
+
+$ref: /schemas/display/msm/mdss-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - const: qcom,sc7180-mdss
+
+ clocks:
+ items:
+ - description: Display AHB clock from gcc
+ - description: Display AHB clock from dispcc
+ - description: Display core clock
+
+ clock-names:
+ items:
+ - const: iface
+ - const: ahb
+ - const: core
+
+ iommus:
+ maxItems: 1
+
+ interconnects:
+ maxItems: 1
+
+ interconnect-names:
+ maxItems: 1
+
+patternProperties:
+ "^display-controller@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,sc7180-dpu
+
+ "^displayport-controller@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,sc7180-dp
+
+ "^dsi@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,mdss-dsi-ctrl
+
+ "^phy@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,dsi-phy-10nm
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,dispcc-sc7180.h>
+ #include <dt-bindings/clock/qcom,gcc-sc7180.h>
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interconnect/qcom,sdm845.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ display-subsystem@ae00000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,sc7180-mdss";
+ reg = <0xae00000 0x1000>;
+ reg-names = "mdss";
+ power-domains = <&dispcc MDSS_GDSC>;
+ clocks = <&gcc GCC_DISP_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>;
+ clock-names = "iface", "ahb", "core";
+
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interconnects = <&mmss_noc MASTER_MDP0 &mc_virt SLAVE_EBI1>;
+ interconnect-names = "mdp0-mem";
+
+ iommus = <&apps_smmu 0x800 0x2>;
+ ranges;
+
+ display-controller@ae01000 {
+ compatible = "qcom,sc7180-dpu";
+ reg = <0x0ae01000 0x8f000>,
+ <0x0aeb0000 0x2008>;
+
+ reg-names = "mdp", "vbif";
+
+ clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_ROT_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>,
+ <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ clock-names = "bus", "iface", "rot", "lut", "core",
+ "vsync";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+ power-domains = <&rpmhpd SC7180_CX>;
+ operating-points-v2 = <&mdp_opp_table>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dpu_intf1_out: endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ dpu_intf0_out: endpoint {
+ remote-endpoint = <&dp_in>;
+ };
+ };
+ };
+ };
+
+ dsi@ae94000 {
+ compatible = "qcom,mdss-dsi-ctrl";
+ reg = <0x0ae94000 0x400>;
+ reg-names = "dsi_ctrl";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <4>;
+
+ clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
+ <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_PCLK0_CLK>,
+ <&dispcc DISP_CC_MDSS_ESC0_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>;
+ clock-names = "byte",
+ "byte_intf",
+ "pixel",
+ "core",
+ "iface",
+ "bus";
+
+ assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>, <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+ assigned-clock-parents = <&dsi_phy 0>, <&dsi_phy 1>;
+
+ operating-points-v2 = <&dsi_opp_table>;
+ power-domains = <&rpmhpd SC7180_CX>;
+
+ phys = <&dsi_phy>;
+ phy-names = "dsi";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dsi0_in: endpoint {
+ remote-endpoint = <&dpu_intf1_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dsi0_out: endpoint {
+ };
+ };
+ };
+
+ dsi_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-187500000 {
+ opp-hz = /bits/ 64 <187500000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ };
+
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ required-opps = <&rpmhpd_opp_svs>;
+ };
+
+ opp-358000000 {
+ opp-hz = /bits/ 64 <358000000>;
+ required-opps = <&rpmhpd_opp_svs_l1>;
+ };
+ };
+ };
+
+ dsi_phy: phy@ae94400 {
+ compatible = "qcom,dsi-phy-10nm";
+ reg = <0x0ae94400 0x200>,
+ <0x0ae94600 0x280>,
+ <0x0ae94a00 0x1e0>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "iface", "ref";
+ vdds-supply = <&vreg_dsi_phy>;
+ };
+
+ displayport-controller@ae90000 {
+ compatible = "qcom,sc7180-dp";
+
+ reg = <0xae90000 0x200>,
+ <0xae90200 0x200>,
+ <0xae90400 0xc00>,
+ <0xae91000 0x400>,
+ <0xae91400 0x400>;
+
+ interrupt-parent = <&mdss>;
+ interrupts = <12>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_AUX_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_LINK_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_LINK_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK>;
+ clock-names = "core_iface", "core_aux", "ctrl_link",
+ "ctrl_link_iface", "stream_pixel";
+ assigned-clocks = <&dispcc DISP_CC_MDSS_DP_LINK_CLK_SRC>,
+ <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>;
+ assigned-clock-parents = <&dp_phy 0>, <&dp_phy 1>;
+ phys = <&dp_phy>;
+ phy-names = "dp";
+
+ operating-points-v2 = <&dp_opp_table>;
+ power-domains = <&rpmhpd SC7180_CX>;
+
+ #sound-dai-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ dp_in: endpoint {
+ remote-endpoint = <&dpu_intf0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dp_out: endpoint { };
+ };
+ };
+
+ dp_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-160000000 {
+ opp-hz = /bits/ 64 <160000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ };
+
+ opp-270000000 {
+ opp-hz = /bits/ 64 <270000000>;
+ required-opps = <&rpmhpd_opp_svs>;
+ };
+
+ opp-540000000 {
+ opp-hz = /bits/ 64 <540000000>;
+ required-opps = <&rpmhpd_opp_svs_l1>;
+ };
+
+ opp-810000000 {
+ opp-hz = /bits/ 64 <810000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml
new file mode 100644
index 000000000000..924059b387b6
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sc7280-dpu.yaml
@@ -0,0 +1,98 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,sc7280-dpu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Display DPU dt properties for SC7280
+
+maintainers:
+ - Krishna Manikandan <quic_mkrishn@quicinc.com>
+
+$ref: /schemas/display/msm/dpu-common.yaml#
+
+properties:
+ compatible:
+ const: qcom,sc7280-dpu
+
+ reg:
+ items:
+ - description: Address offset and size for mdp register set
+ - description: Address offset and size for vbif register set
+
+ reg-names:
+ items:
+ - const: mdp
+ - const: vbif
+
+ clocks:
+ items:
+ - description: Display hf axi clock
+ - description: Display sf axi clock
+ - description: Display ahb clock
+ - description: Display lut clock
+ - description: Display core clock
+ - description: Display vsync clock
+
+ clock-names:
+ items:
+ - const: bus
+ - const: nrt_bus
+ - const: iface
+ - const: lut
+ - const: core
+ - const: vsync
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,dispcc-sc7280.h>
+ #include <dt-bindings/clock/qcom,gcc-sc7280.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ display-controller@ae01000 {
+ compatible = "qcom,sc7280-dpu";
+ reg = <0x0ae01000 0x8f000>,
+ <0x0aeb0000 0x2008>;
+
+ reg-names = "mdp", "vbif";
+
+ clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&gcc GCC_DISP_SF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>,
+ <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ clock-names = "bus",
+ "nrt_bus",
+ "iface",
+ "lut",
+ "core",
+ "vsync";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+ power-domains = <&rpmhpd SC7280_CX>;
+ operating-points-v2 = <&mdp_opp_table>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ endpoint {
+ remote-endpoint = <&edp_in>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sc7280-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sc7280-mdss.yaml
new file mode 100644
index 000000000000..a3de1744ba11
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sc7280-mdss.yaml
@@ -0,0 +1,422 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,sc7280-mdss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SC7280 Display MDSS
+
+maintainers:
+ - Krishna Manikandan <quic_mkrishn@quicinc.com>
+
+description:
+ Device tree bindings for MSM Mobile Display Subsystem (MDSS) that encapsulates
+ sub-blocks like DPU display controller, DSI and DP interfaces etc. Device tree
+ bindings of MDSS are mentioned for SC7280.
+
+$ref: /schemas/display/msm/mdss-common.yaml#
+
+properties:
+ compatible:
+ const: qcom,sc7280-mdss
+
+ clocks:
+ items:
+ - description: Display AHB clock from gcc
+ - description: Display AHB clock from dispcc
+ - description: Display core clock
+
+ clock-names:
+ items:
+ - const: iface
+ - const: ahb
+ - const: core
+
+ iommus:
+ maxItems: 1
+
+ interconnects:
+ maxItems: 1
+
+ interconnect-names:
+ maxItems: 1
+
+patternProperties:
+ "^display-controller@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,sc7280-dpu
+
+ "^displayport-controller@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,sc7280-dp
+
+ "^dsi@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,mdss-dsi-ctrl
+
+ "^edp@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,sc7280-edp
+
+ "^phy@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ enum:
+ - qcom,sc7280-dsi-phy-7nm
+ - qcom,sc7280-edp-phy
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,dispcc-sc7280.h>
+ #include <dt-bindings/clock/qcom,gcc-sc7280.h>
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interconnect/qcom,sc7280.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ display-subsystem@ae00000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,sc7280-mdss";
+ reg = <0xae00000 0x1000>;
+ reg-names = "mdss";
+ power-domains = <&dispcc DISP_CC_MDSS_CORE_GDSC>;
+ clocks = <&gcc GCC_DISP_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>;
+ clock-names = "iface",
+ "ahb",
+ "core";
+
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interconnects = <&mmss_noc MASTER_MDP0 &mc_virt SLAVE_EBI1>;
+ interconnect-names = "mdp0-mem";
+
+ iommus = <&apps_smmu 0x900 0x402>;
+ ranges;
+
+ display-controller@ae01000 {
+ compatible = "qcom,sc7280-dpu";
+ reg = <0x0ae01000 0x8f000>,
+ <0x0aeb0000 0x2008>;
+
+ reg-names = "mdp", "vbif";
+
+ clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&gcc GCC_DISP_SF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>,
+ <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ clock-names = "bus",
+ "nrt_bus",
+ "iface",
+ "lut",
+ "core",
+ "vsync";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+ power-domains = <&rpmhpd SC7280_CX>;
+ operating-points-v2 = <&mdp_opp_table>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dpu_intf1_out: endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dpu_intf5_out: endpoint {
+ remote-endpoint = <&edp_in>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ dpu_intf0_out: endpoint {
+ remote-endpoint = <&dp_in>;
+ };
+ };
+ };
+ };
+
+ dsi@ae94000 {
+ compatible = "qcom,mdss-dsi-ctrl";
+ reg = <0x0ae94000 0x400>;
+ reg-names = "dsi_ctrl";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <4>;
+
+ clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
+ <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_PCLK0_CLK>,
+ <&dispcc DISP_CC_MDSS_ESC0_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>;
+ clock-names = "byte",
+ "byte_intf",
+ "pixel",
+ "core",
+ "iface",
+ "bus";
+
+ assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>,
+ <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+ assigned-clock-parents = <&mdss_dsi_phy 0>, <&mdss_dsi_phy 1>;
+
+ operating-points-v2 = <&dsi_opp_table>;
+ power-domains = <&rpmhpd SC7280_CX>;
+
+ phys = <&mdss_dsi_phy>;
+ phy-names = "dsi";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dsi0_in: endpoint {
+ remote-endpoint = <&dpu_intf1_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dsi0_out: endpoint {
+ };
+ };
+ };
+
+ dsi_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-187500000 {
+ opp-hz = /bits/ 64 <187500000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ };
+
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ required-opps = <&rpmhpd_opp_svs>;
+ };
+
+ opp-358000000 {
+ opp-hz = /bits/ 64 <358000000>;
+ required-opps = <&rpmhpd_opp_svs_l1>;
+ };
+ };
+ };
+
+ mdss_dsi_phy: phy@ae94400 {
+ compatible = "qcom,sc7280-dsi-phy-7nm";
+ reg = <0x0ae94400 0x200>,
+ <0x0ae94600 0x280>,
+ <0x0ae94900 0x280>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "iface", "ref";
+
+ vdds-supply = <&vreg_dsi_supply>;
+ };
+
+ edp@aea0000 {
+ compatible = "qcom,sc7280-edp";
+ pinctrl-names = "default";
+ pinctrl-0 = <&edp_hot_plug_det>;
+
+ reg = <0xaea0000 0x200>,
+ <0xaea0200 0x200>,
+ <0xaea0400 0xc00>,
+ <0xaea1000 0x400>;
+
+ interrupt-parent = <&mdss>;
+ interrupts = <14>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_EDP_AUX_CLK>,
+ <&dispcc DISP_CC_MDSS_EDP_LINK_CLK>,
+ <&dispcc DISP_CC_MDSS_EDP_LINK_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_EDP_PIXEL_CLK>;
+ clock-names = "core_iface",
+ "core_aux",
+ "ctrl_link",
+ "ctrl_link_iface",
+ "stream_pixel";
+ assigned-clocks = <&dispcc DISP_CC_MDSS_EDP_LINK_CLK_SRC>,
+ <&dispcc DISP_CC_MDSS_EDP_PIXEL_CLK_SRC>;
+ assigned-clock-parents = <&mdss_edp_phy 0>, <&mdss_edp_phy 1>;
+
+ phys = <&mdss_edp_phy>;
+ phy-names = "dp";
+
+ operating-points-v2 = <&edp_opp_table>;
+ power-domains = <&rpmhpd SC7280_CX>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ edp_in: endpoint {
+ remote-endpoint = <&dpu_intf5_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ mdss_edp_out: endpoint { };
+ };
+ };
+
+ edp_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-160000000 {
+ opp-hz = /bits/ 64 <160000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ };
+
+ opp-270000000 {
+ opp-hz = /bits/ 64 <270000000>;
+ required-opps = <&rpmhpd_opp_svs>;
+ };
+
+ opp-540000000 {
+ opp-hz = /bits/ 64 <540000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ };
+
+ opp-810000000 {
+ opp-hz = /bits/ 64 <810000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ };
+ };
+ };
+
+ mdss_edp_phy: phy@aec2a00 {
+ compatible = "qcom,sc7280-edp-phy";
+
+ reg = <0xaec2a00 0x19c>,
+ <0xaec2200 0xa0>,
+ <0xaec2600 0xa0>,
+ <0xaec2000 0x1c0>;
+
+ clocks = <&rpmhcc RPMH_CXO_CLK>,
+ <&gcc GCC_EDP_CLKREF_EN>;
+ clock-names = "aux",
+ "cfg_ahb";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+ };
+
+ displayport-controller@ae90000 {
+ compatible = "qcom,sc7280-dp";
+
+ reg = <0xae90000 0x200>,
+ <0xae90200 0x200>,
+ <0xae90400 0xc00>,
+ <0xae91000 0x400>,
+ <0xae91400 0x400>;
+
+ interrupt-parent = <&mdss>;
+ interrupts = <12>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_AUX_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_LINK_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_LINK_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK>;
+ clock-names = "core_iface",
+ "core_aux",
+ "ctrl_link",
+ "ctrl_link_iface",
+ "stream_pixel";
+ assigned-clocks = <&dispcc DISP_CC_MDSS_DP_LINK_CLK_SRC>,
+ <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>;
+ assigned-clock-parents = <&dp_phy 0>, <&dp_phy 1>;
+ phys = <&dp_phy>;
+ phy-names = "dp";
+
+ operating-points-v2 = <&dp_opp_table>;
+ power-domains = <&rpmhpd SC7280_CX>;
+
+ #sound-dai-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dp_in: endpoint {
+ remote-endpoint = <&dpu_intf0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dp_out: endpoint { };
+ };
+ };
+
+ dp_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-160000000 {
+ opp-hz = /bits/ 64 <160000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ };
+
+ opp-270000000 {
+ opp-hz = /bits/ 64 <270000000>;
+ required-opps = <&rpmhpd_opp_svs>;
+ };
+
+ opp-540000000 {
+ opp-hz = /bits/ 64 <540000000>;
+ required-opps = <&rpmhpd_opp_svs_l1>;
+ };
+
+ opp-810000000 {
+ opp-hz = /bits/ 64 <810000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sdm845-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sdm845-dpu.yaml
new file mode 100644
index 000000000000..5719b45f2860
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sdm845-dpu.yaml
@@ -0,0 +1,90 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,sdm845-dpu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Display DPU dt properties for SDM845 target
+
+maintainers:
+ - Krishna Manikandan <quic_mkrishn@quicinc.com>
+
+$ref: /schemas/display/msm/dpu-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - const: qcom,sdm845-dpu
+
+ reg:
+ items:
+ - description: Address offset and size for mdp register set
+ - description: Address offset and size for vbif register set
+
+ reg-names:
+ items:
+ - const: mdp
+ - const: vbif
+
+ clocks:
+ items:
+ - description: Display GCC bus clock
+ - description: Display ahb clock
+ - description: Display axi clock
+ - description: Display core clock
+ - description: Display vsync clock
+
+ clock-names:
+ items:
+ - const: gcc-bus
+ - const: iface
+ - const: bus
+ - const: core
+ - const: vsync
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+ #include <dt-bindings/clock/qcom,gcc-sdm845.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ display-controller@ae01000 {
+ compatible = "qcom,sdm845-dpu";
+ reg = <0x0ae01000 0x8f000>,
+ <0x0aeb0000 0x2008>;
+ reg-names = "mdp", "vbif";
+
+ clocks = <&gcc GCC_DISP_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>,
+ <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ clock-names = "gcc-bus", "iface", "bus", "core", "vsync";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+ power-domains = <&rpmhpd SDM845_CX>;
+ operating-points-v2 = <&mdp_opp_table>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ endpoint {
+ remote-endpoint = <&dsi1_in>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sdm845-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sdm845-mdss.yaml
new file mode 100644
index 000000000000..31ca6f99fc22
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sdm845-mdss.yaml
@@ -0,0 +1,270 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,sdm845-mdss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SDM845 Display MDSS
+
+maintainers:
+ - Krishna Manikandan <quic_mkrishn@quicinc.com>
+
+description:
+ Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates
+ sub-blocks like DPU display controller, DSI and DP interfaces etc. Device tree
+ bindings of MDSS are mentioned for SDM845 target.
+
+$ref: /schemas/display/msm/mdss-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - const: qcom,sdm845-mdss
+
+ clocks:
+ items:
+ - description: Display AHB clock from gcc
+ - description: Display core clock
+
+ clock-names:
+ items:
+ - const: iface
+ - const: core
+
+ iommus:
+ maxItems: 2
+
+ interconnects:
+ maxItems: 2
+
+ interconnect-names:
+ maxItems: 2
+
+patternProperties:
+ "^display-controller@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,sdm845-dpu
+
+ "^dsi@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,mdss-dsi-ctrl
+
+ "^phy@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,dsi-phy-10nm
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+ #include <dt-bindings/clock/qcom,gcc-sdm845.h>
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ display-subsystem@ae00000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,sdm845-mdss";
+ reg = <0x0ae00000 0x1000>;
+ reg-names = "mdss";
+ power-domains = <&dispcc MDSS_GDSC>;
+
+ clocks = <&gcc GCC_DISP_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>;
+ clock-names = "iface", "core";
+
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ iommus = <&apps_smmu 0x880 0x8>,
+ <&apps_smmu 0xc80 0x8>;
+ ranges;
+
+ display-controller@ae01000 {
+ compatible = "qcom,sdm845-dpu";
+ reg = <0x0ae01000 0x8f000>,
+ <0x0aeb0000 0x2008>;
+ reg-names = "mdp", "vbif";
+
+ clocks = <&gcc GCC_DISP_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>,
+ <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ clock-names = "gcc-bus", "iface", "bus", "core", "vsync";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+ power-domains = <&rpmhpd SDM845_CX>;
+ operating-points-v2 = <&mdp_opp_table>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dpu_intf1_out: endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dpu_intf2_out: endpoint {
+ remote-endpoint = <&dsi1_in>;
+ };
+ };
+ };
+ };
+
+ dsi@ae94000 {
+ compatible = "qcom,mdss-dsi-ctrl";
+ reg = <0x0ae94000 0x400>;
+ reg-names = "dsi_ctrl";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <4>;
+
+ clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
+ <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_PCLK0_CLK>,
+ <&dispcc DISP_CC_MDSS_ESC0_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_AXI_CLK>;
+ clock-names = "byte",
+ "byte_intf",
+ "pixel",
+ "core",
+ "iface",
+ "bus";
+ assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>,
+ <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+ assigned-clock-parents = <&dsi0_phy 0>, <&dsi0_phy 1>;
+
+ operating-points-v2 = <&dsi_opp_table>;
+ power-domains = <&rpmhpd SDM845_CX>;
+
+ phys = <&dsi0_phy>;
+ phy-names = "dsi";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dsi0_in: endpoint {
+ remote-endpoint = <&dpu_intf1_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dsi0_out: endpoint {
+ };
+ };
+ };
+ };
+
+ dsi0_phy: phy@ae94400 {
+ compatible = "qcom,dsi-phy-10nm";
+ reg = <0x0ae94400 0x200>,
+ <0x0ae94600 0x280>,
+ <0x0ae94a00 0x1e0>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "iface", "ref";
+ vdds-supply = <&vreg_dsi_phy>;
+ };
+
+ dsi@ae96000 {
+ compatible = "qcom,mdss-dsi-ctrl";
+ reg = <0x0ae96000 0x400>;
+ reg-names = "dsi_ctrl";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <5>;
+
+ clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK>,
+ <&dispcc DISP_CC_MDSS_BYTE1_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_PCLK1_CLK>,
+ <&dispcc DISP_CC_MDSS_ESC1_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_AXI_CLK>;
+ clock-names = "byte",
+ "byte_intf",
+ "pixel",
+ "core",
+ "iface",
+ "bus";
+ assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK_SRC>,
+ <&dispcc DISP_CC_MDSS_PCLK1_CLK_SRC>;
+ assigned-clock-parents = <&dsi1_phy 0>, <&dsi1_phy 1>;
+
+ operating-points-v2 = <&dsi_opp_table>;
+ power-domains = <&rpmhpd SDM845_CX>;
+
+ phys = <&dsi1_phy>;
+ phy-names = "dsi";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dsi1_in: endpoint {
+ remote-endpoint = <&dpu_intf2_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dsi1_out: endpoint {
+ };
+ };
+ };
+ };
+
+ dsi1_phy: phy@ae96400 {
+ compatible = "qcom,dsi-phy-10nm";
+ reg = <0x0ae96400 0x200>,
+ <0x0ae96600 0x280>,
+ <0x0ae96a00 0x10e>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "iface", "ref";
+ vdds-supply = <&vreg_dsi_phy>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm6115-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm6115-dpu.yaml
new file mode 100644
index 000000000000..4a39a3031409
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sm6115-dpu.yaml
@@ -0,0 +1,94 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,sm6115-dpu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Display DPU dt properties for SM6115 target
+
+maintainers:
+ - Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+$ref: /schemas/display/msm/dpu-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - const: qcom,sm6115-dpu
+
+ reg:
+ items:
+ - description: MDP register set
+ - description: VBIF register set
+
+ reg-names:
+ items:
+ - const: mdp
+ - const: vbif
+
+ clocks:
+ items:
+ - description: Display AXI
+ - description: Display AHB
+ - description: Display core
+ - description: Display lut
+ - description: Display rotator
+ - description: Display vsync
+
+ clock-names:
+ items:
+ - const: bus
+ - const: iface
+ - const: core
+ - const: lut
+ - const: rot
+ - const: vsync
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - clocks
+ - clock-names
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,sm6115-dispcc.h>
+ #include <dt-bindings/clock/qcom,gcc-sm6115.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ display-controller@5e01000 {
+ compatible = "qcom,sm6115-dpu";
+ reg = <0x05e01000 0x8f000>,
+ <0x05eb0000 0x2008>;
+ reg-names = "mdp", "vbif";
+
+ clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
+ <&dispcc DISP_CC_MDSS_ROT_CLK>,
+ <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ clock-names = "bus", "iface", "core", "lut", "rot", "vsync";
+
+ operating-points-v2 = <&mdp_opp_table>;
+ power-domains = <&rpmpd SM6115_VDDCX>;
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm6115-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm6115-mdss.yaml
new file mode 100644
index 000000000000..a86d7f53fa84
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sm6115-mdss.yaml
@@ -0,0 +1,182 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,sm6115-mdss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SM6115 Display MDSS
+
+maintainers:
+ - Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+description:
+ Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates
+ sub-blocks like DPU display controller and DSI. Device tree bindings of MDSS
+ are mentioned for SM6115 target.
+
+$ref: /schemas/display/msm/mdss-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - const: qcom,sm6115-mdss
+
+ clocks:
+ items:
+ - description: Display AHB clock from gcc
+ - description: Display AXI clock
+ - description: Display core clock
+
+ iommus:
+ maxItems: 2
+
+patternProperties:
+ "^display-controller@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,sm6115-dpu
+
+ "^dsi@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,dsi-ctrl-6g-qcm2290
+
+ "^phy@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,dsi-phy-14nm-2290
+
+required:
+ - compatible
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,sm6115-dispcc.h>
+ #include <dt-bindings/clock/qcom,gcc-sm6115.h>
+ #include <dt-bindings/clock/qcom,rpmcc.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ mdss@5e00000 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "qcom,sm6115-mdss";
+ reg = <0x05e00000 0x1000>;
+ reg-names = "mdss";
+ power-domains = <&dispcc MDSS_GDSC>;
+ clocks = <&gcc GCC_DISP_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>;
+
+ interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ iommus = <&apps_smmu 0x420 0x2>,
+ <&apps_smmu 0x421 0x0>;
+ ranges;
+
+ display-controller@5e01000 {
+ compatible = "qcom,sm6115-dpu";
+ reg = <0x05e01000 0x8f000>,
+ <0x05eb0000 0x2008>;
+ reg-names = "mdp", "vbif";
+
+ clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
+ <&dispcc DISP_CC_MDSS_ROT_CLK>,
+ <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ clock-names = "bus", "iface", "core", "lut", "rot", "vsync";
+
+ operating-points-v2 = <&mdp_opp_table>;
+ power-domains = <&rpmpd SM6115_VDDCX>;
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dpu_intf1_out: endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+ };
+ };
+
+ dsi@5e94000 {
+ compatible = "qcom,dsi-ctrl-6g-qcm2290";
+ reg = <0x05e94000 0x400>;
+ reg-names = "dsi_ctrl";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <4>;
+
+ clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
+ <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_PCLK0_CLK>,
+ <&dispcc DISP_CC_MDSS_ESC0_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>;
+ clock-names = "byte",
+ "byte_intf",
+ "pixel",
+ "core",
+ "iface",
+ "bus";
+ assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>, <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+ assigned-clock-parents = <&dsi0_phy 0>, <&dsi0_phy 1>;
+
+ operating-points-v2 = <&dsi_opp_table>;
+ power-domains = <&rpmpd SM6115_VDDCX>;
+ phys = <&dsi0_phy>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dsi0_in: endpoint {
+ remote-endpoint = <&dpu_intf1_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dsi0_out: endpoint {
+ };
+ };
+ };
+ };
+
+ dsi0_phy: phy@5e94400 {
+ compatible = "qcom,dsi-phy-14nm-2290";
+ reg = <0x05e94400 0x100>,
+ <0x05e94500 0x300>,
+ <0x05e94800 0x188>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>, <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "iface", "ref";
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8250-dpu.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8250-dpu.yaml
new file mode 100644
index 000000000000..9ff8a265c85f
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8250-dpu.yaml
@@ -0,0 +1,92 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,sm8250-dpu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SM8250 Display DPU
+
+maintainers:
+ - Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+$ref: /schemas/display/msm/dpu-common.yaml#
+
+properties:
+ compatible:
+ const: qcom,sm8250-dpu
+
+ reg:
+ items:
+ - description: Address offset and size for mdp register set
+ - description: Address offset and size for vbif register set
+
+ reg-names:
+ items:
+ - const: mdp
+ - const: vbif
+
+ clocks:
+ items:
+ - description: Display ahb clock
+ - description: Display hf axi clock
+ - description: Display core clock
+ - description: Display vsync clock
+
+ clock-names:
+ items:
+ - const: iface
+ - const: bus
+ - const: core
+ - const: vsync
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,dispcc-sm8250.h>
+ #include <dt-bindings/clock/qcom,gcc-sm8250.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interconnect/qcom,sm8250.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ display-controller@ae01000 {
+ compatible = "qcom,sm8250-dpu";
+ reg = <0x0ae01000 0x8f000>,
+ <0x0aeb0000 0x2008>;
+ reg-names = "mdp", "vbif";
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>,
+ <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ clock-names = "iface", "bus", "core", "vsync";
+
+ assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ assigned-clock-rates = <19200000>;
+
+ operating-points-v2 = <&mdp_opp_table>;
+ power-domains = <&rpmhpd SM8250_MMCX>;
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ endpoint {
+ remote-endpoint = <&dsi1_in>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/msm/qcom,sm8250-mdss.yaml b/Documentation/devicetree/bindings/display/msm/qcom,sm8250-mdss.yaml
new file mode 100644
index 000000000000..0d3be5386b3f
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/msm/qcom,sm8250-mdss.yaml
@@ -0,0 +1,330 @@
+# SPDX-License-Identifier: GPL-2.0-only or BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/msm/qcom,sm8250-mdss.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SM8250 Display MDSS
+
+maintainers:
+ - Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+description:
+ Device tree bindings for MSM Mobile Display Subsystem(MDSS) that encapsulates
+ sub-blocks like DPU display controller, DSI and DP interfaces etc. Device tree
+ bindings of MDSS are mentioned for SM8250 target.
+
+$ref: /schemas/display/msm/mdss-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - const: qcom,sm8250-mdss
+
+ clocks:
+ items:
+ - description: Display AHB clock from gcc
+ - description: Display hf axi clock
+ - description: Display sf axi clock
+ - description: Display core clock
+
+ clock-names:
+ items:
+ - const: iface
+ - const: bus
+ - const: nrt_bus
+ - const: core
+
+ iommus:
+ maxItems: 1
+
+ interconnects:
+ maxItems: 2
+
+ interconnect-names:
+ maxItems: 2
+
+patternProperties:
+ "^display-controller@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,sm8250-dpu
+
+ "^dsi@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,mdss-dsi-ctrl
+
+ "^phy@[0-9a-f]+$":
+ type: object
+ properties:
+ compatible:
+ const: qcom,dsi-phy-7nm
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,dispcc-sm8250.h>
+ #include <dt-bindings/clock/qcom,gcc-sm8250.h>
+ #include <dt-bindings/clock/qcom,rpmh.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interconnect/qcom,sm8250.h>
+ #include <dt-bindings/power/qcom-rpmpd.h>
+
+ display-subsystem@ae00000 {
+ compatible = "qcom,sm8250-mdss";
+ reg = <0x0ae00000 0x1000>;
+ reg-names = "mdss";
+
+ interconnects = <&mmss_noc MASTER_MDP_PORT0 &mc_virt SLAVE_EBI_CH0>,
+ <&mmss_noc MASTER_MDP_PORT1 &mc_virt SLAVE_EBI_CH0>;
+ interconnect-names = "mdp0-mem", "mdp1-mem";
+
+ power-domains = <&dispcc MDSS_GDSC>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&gcc GCC_DISP_SF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>;
+ clock-names = "iface", "bus", "nrt_bus", "core";
+
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ iommus = <&apps_smmu 0x820 0x402>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ display-controller@ae01000 {
+ compatible = "qcom,sm8250-dpu";
+ reg = <0x0ae01000 0x8f000>,
+ <0x0aeb0000 0x2008>;
+ reg-names = "mdp", "vbif";
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>,
+ <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ clock-names = "iface", "bus", "core", "vsync";
+
+ assigned-clocks = <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ assigned-clock-rates = <19200000>;
+
+ operating-points-v2 = <&mdp_opp_table>;
+ power-domains = <&rpmhpd SM8250_MMCX>;
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dpu_intf1_out: endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dpu_intf2_out: endpoint {
+ remote-endpoint = <&dsi1_in>;
+ };
+ };
+ };
+
+ mdp_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-200000000 {
+ opp-hz = /bits/ 64 <200000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ };
+
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ required-opps = <&rpmhpd_opp_svs>;
+ };
+
+ opp-345000000 {
+ opp-hz = /bits/ 64 <345000000>;
+ required-opps = <&rpmhpd_opp_svs_l1>;
+ };
+
+ opp-460000000 {
+ opp-hz = /bits/ 64 <460000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ };
+ };
+ };
+
+ dsi@ae94000 {
+ compatible = "qcom,mdss-dsi-ctrl";
+ reg = <0x0ae94000 0x400>;
+ reg-names = "dsi_ctrl";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <4>;
+
+ clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
+ <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_PCLK0_CLK>,
+ <&dispcc DISP_CC_MDSS_ESC0_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>;
+ clock-names = "byte",
+ "byte_intf",
+ "pixel",
+ "core",
+ "iface",
+ "bus";
+
+ assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>,
+ <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+ assigned-clock-parents = <&dsi0_phy 0>, <&dsi0_phy 1>;
+
+ operating-points-v2 = <&dsi_opp_table>;
+ power-domains = <&rpmhpd SM8250_MMCX>;
+
+ phys = <&dsi0_phy>;
+ phy-names = "dsi";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dsi0_in: endpoint {
+ remote-endpoint = <&dpu_intf1_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dsi0_out: endpoint {
+ };
+ };
+ };
+
+ dsi_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-187500000 {
+ opp-hz = /bits/ 64 <187500000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ };
+
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ required-opps = <&rpmhpd_opp_svs>;
+ };
+
+ opp-358000000 {
+ opp-hz = /bits/ 64 <358000000>;
+ required-opps = <&rpmhpd_opp_svs_l1>;
+ };
+ };
+ };
+
+ dsi0_phy: phy@ae94400 {
+ compatible = "qcom,dsi-phy-7nm";
+ reg = <0x0ae94400 0x200>,
+ <0x0ae94600 0x280>,
+ <0x0ae94900 0x260>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "iface", "ref";
+ vdds-supply = <&vreg_dsi_phy>;
+ };
+
+ dsi@ae96000 {
+ compatible = "qcom,mdss-dsi-ctrl";
+ reg = <0x0ae96000 0x400>;
+ reg-names = "dsi_ctrl";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <5>;
+
+ clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK>,
+ <&dispcc DISP_CC_MDSS_BYTE1_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_PCLK1_CLK>,
+ <&dispcc DISP_CC_MDSS_ESC1_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>;
+ clock-names = "byte",
+ "byte_intf",
+ "pixel",
+ "core",
+ "iface",
+ "bus";
+
+ assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE1_CLK_SRC>,
+ <&dispcc DISP_CC_MDSS_PCLK1_CLK_SRC>;
+ assigned-clock-parents = <&dsi1_phy 0>, <&dsi1_phy 1>;
+
+ operating-points-v2 = <&dsi_opp_table>;
+ power-domains = <&rpmhpd SM8250_MMCX>;
+
+ phys = <&dsi1_phy>;
+ phy-names = "dsi";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dsi1_in: endpoint {
+ remote-endpoint = <&dpu_intf2_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dsi1_out: endpoint {
+ };
+ };
+ };
+ };
+
+ dsi1_phy: phy@ae96400 {
+ compatible = "qcom,dsi-phy-7nm";
+ reg = <0x0ae96400 0x200>,
+ <0x0ae96600 0x280>,
+ <0x0ae96900 0x260>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "iface", "ref";
+ vdds-supply = <&vreg_dsi_phy>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/display/panel/ilitek,ili9163.yaml b/Documentation/devicetree/bindings/display/panel/ilitek,ili9163.yaml
index 7e7a8362b951..a4154b51043e 100644
--- a/Documentation/devicetree/bindings/display/panel/ilitek,ili9163.yaml
+++ b/Documentation/devicetree/bindings/display/panel/ilitek,ili9163.yaml
@@ -15,6 +15,7 @@ description:
allOf:
- $ref: panel-common.yaml#
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
properties:
compatible:
@@ -41,7 +42,7 @@ required:
- dc-gpios
- reset-gpios
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml b/Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml
index 99e0cb9440cf..94f169ea065a 100644
--- a/Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml
+++ b/Documentation/devicetree/bindings/display/panel/ilitek,ili9341.yaml
@@ -16,6 +16,7 @@ description: |
allOf:
- $ref: panel-common.yaml#
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml b/Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml
new file mode 100644
index 000000000000..c06902e4fe70
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml
@@ -0,0 +1,70 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/jadard,jd9365da-h3.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Jadard JD9365DA-HE WXGA DSI panel
+
+maintainers:
+ - Jagan Teki <jagan@edgeble.ai>
+
+allOf:
+ - $ref: panel-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - chongzhou,cz101b4001
+ - const: jadard,jd9365da-h3
+
+ reg: true
+
+ vdd-supply:
+ description: supply regulator for VDD, usually 3.3V
+
+ vccio-supply:
+ description: supply regulator for VCCIO, usually 1.8V
+
+ reset-gpios: true
+
+ backlight: true
+
+ port: true
+
+required:
+ - compatible
+ - reg
+ - vdd-supply
+ - vccio-supply
+ - reset-gpios
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/pinctrl/rockchip.h>
+
+ dsi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ panel@0 {
+ compatible = "chongzhou,cz101b4001", "jadard,jd9365da-h3";
+ reg = <0>;
+ vdd-supply = <&lcd_3v3>;
+ vccio-supply = <&vcca_1v8>;
+ reset-gpios = <&gpio1 RK_PC2 GPIO_ACTIVE_HIGH>;
+ backlight = <&backlight>;
+
+ port {
+ mipi_in_panel: endpoint {
+ remote-endpoint = <&mipi_out_panel>;
+ };
+ };
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/display/panel/nec,nl8048hl11.yaml b/Documentation/devicetree/bindings/display/panel/nec,nl8048hl11.yaml
index aa788eaa2f71..3b09b359023e 100644
--- a/Documentation/devicetree/bindings/display/panel/nec,nl8048hl11.yaml
+++ b/Documentation/devicetree/bindings/display/panel/nec,nl8048hl11.yaml
@@ -15,6 +15,7 @@ maintainers:
allOf:
- $ref: panel-common.yaml#
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
properties:
compatible:
@@ -34,7 +35,7 @@ required:
- reset-gpios
- port
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/display/panel/newvision,nv3051d.yaml b/Documentation/devicetree/bindings/display/panel/newvision,nv3051d.yaml
new file mode 100644
index 000000000000..116c1b6030a2
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/panel/newvision,nv3051d.yaml
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/panel/newvision,nv3051d.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NewVision NV3051D based LCD panel
+
+description: |
+ The NewVision NV3051D is a driver chip used to drive DSI panels. For now,
+ this driver only supports the 640x480 panels found in the Anbernic RG353
+ based devices.
+
+maintainers:
+ - Chris Morgan <macromorgan@hotmail.com>
+
+allOf:
+ - $ref: panel-common.yaml#
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - anbernic,rg353p-panel
+ - anbernic,rg353v-panel
+ - const: newvision,nv3051d
+
+ reg: true
+ backlight: true
+ port: true
+ reset-gpios:
+ description: Active low reset GPIO
+ vdd-supply: true
+
+required:
+ - compatible
+ - reg
+ - backlight
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ dsi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ panel@0 {
+ compatible = "anbernic,rg353p-panel", "newvision,nv3051d";
+ reg = <0>;
+ backlight = <&backlight>;
+ reset-gpios = <&gpio4 0 GPIO_ACTIVE_LOW>;
+ vdd-supply = <&vcc3v3_lcd>;
+
+ port {
+ mipi_in_panel: endpoint {
+ remote-endpoint = <&mipi_out_panel>;
+ };
+ };
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml b/Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml
index 251f0c7115aa..70ffc88d2a08 100644
--- a/Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml
+++ b/Documentation/devicetree/bindings/display/panel/samsung,lms380kf01.yaml
@@ -9,14 +9,13 @@ title: Samsung LMS380KF01 display panel
description: The LMS380KF01 is a 480x800 DPI display panel from Samsung Mobile
Displays (SMD) utilizing the WideChips WS2401 display controller. It can be
used with internal or external backlight control.
- The panel must obey the rules for a SPI slave device as specified in
- spi/spi-controller.yaml
maintainers:
- Linus Walleij <linus.walleij@linaro.org>
allOf:
- $ref: panel-common.yaml#
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
properties:
compatible:
@@ -59,7 +58,7 @@ required:
- spi-cpol
- port
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml b/Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
index cd62968426fb..5e77cee93f83 100644
--- a/Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
+++ b/Documentation/devicetree/bindings/display/panel/samsung,lms397kf04.yaml
@@ -14,6 +14,7 @@ maintainers:
allOf:
- $ref: panel-common.yaml#
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
properties:
compatible:
@@ -51,7 +52,7 @@ required:
- spi-cpol
- port
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/display/panel/samsung,s6d27a1.yaml b/Documentation/devicetree/bindings/display/panel/samsung,s6d27a1.yaml
index 26e3c820a2f7..d273faf4442a 100644
--- a/Documentation/devicetree/bindings/display/panel/samsung,s6d27a1.yaml
+++ b/Documentation/devicetree/bindings/display/panel/samsung,s6d27a1.yaml
@@ -7,14 +7,14 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Samsung S6D27A1 display panel
description: The S6D27A1 is a 480x800 DPI display panel from Samsung Mobile
- Displays (SMD). The panel must obey the rules for a SPI slave device
- as specified in spi/spi-controller.yaml
+ Displays (SMD).
maintainers:
- Markuss Broks <markuss.broks@gmail.com>
allOf:
- $ref: panel-common.yaml#
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/display/panel/tpo,tpg110.yaml b/Documentation/devicetree/bindings/display/panel/tpo,tpg110.yaml
index 6f1f02044b4b..f0243d196191 100644
--- a/Documentation/devicetree/bindings/display/panel/tpo,tpg110.yaml
+++ b/Documentation/devicetree/bindings/display/panel/tpo,tpg110.yaml
@@ -41,6 +41,7 @@ description: |+
allOf:
- $ref: panel-common.yaml#
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra124-dpaux.yaml b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra124-dpaux.yaml
index 9ab123cd2325..5cdbc527a560 100644
--- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra124-dpaux.yaml
+++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra124-dpaux.yaml
@@ -128,7 +128,6 @@ examples:
resets = <&tegra_car 181>;
reset-names = "dpaux";
power-domains = <&pd_sor>;
- status = "disabled";
state_dpaux_aux: pinmux-aux {
groups = "dpaux-io";
diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra186-display.yaml b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra186-display.yaml
index 8c0231345529..ce5c673f940c 100644
--- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra186-display.yaml
+++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra186-display.yaml
@@ -138,7 +138,6 @@ examples:
<&bpmp TEGRA186_CLK_NVDISPLAY_DSC>,
<&bpmp TEGRA186_CLK_NVDISPLAYHUB>;
clock-names = "disp", "dsc", "hub";
- status = "disabled";
power-domains = <&bpmp TEGRA186_POWER_DOMAIN_DISP>;
@@ -227,7 +226,6 @@ examples:
clocks = <&bpmp TEGRA194_CLK_NVDISPLAY_DISP>,
<&bpmp TEGRA194_CLK_NVDISPLAYHUB>;
clock-names = "disp", "hub";
- status = "disabled";
power-domains = <&bpmp TEGRA194_POWER_DOMAIN_DISP>;
diff --git a/Documentation/devicetree/bindings/display/xlnx/xlnx,zynqmp-dpsub.yaml b/Documentation/devicetree/bindings/display/xlnx/xlnx,zynqmp-dpsub.yaml
index 10ec78ca1c65..554f9d5809d4 100644
--- a/Documentation/devicetree/bindings/display/xlnx/xlnx,zynqmp-dpsub.yaml
+++ b/Documentation/devicetree/bindings/display/xlnx/xlnx,zynqmp-dpsub.yaml
@@ -117,6 +117,45 @@ properties:
- const: dp-phy0
- const: dp-phy1
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ description: |
+ Connections to the programmable logic and the DisplayPort PHYs. Each port
+ shall have a single endpoint.
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: The live video input from the programmable logic
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: The live graphics input from the programmable logic
+
+ port@2:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: The live audio input from the programmable logic
+
+ port@3:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: The blended video output to the programmable logic
+
+ port@4:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: The mixed audio output to the programmable logic
+
+ port@5:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: The DisplayPort output
+
+ required:
+ - port@0
+ - port@1
+ - port@2
+ - port@3
+ - port@4
+ - port@5
+
required:
- compatible
- reg
@@ -130,6 +169,7 @@ required:
- dma-names
- phys
- phy-names
+ - ports
additionalProperties: false
@@ -164,6 +204,33 @@ examples:
<&psgtr 0 PHY_TYPE_DP 1 3>;
phy-names = "dp-phy0", "dp-phy1";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ };
+ port@1 {
+ reg = <1>;
+ };
+ port@2 {
+ reg = <2>;
+ };
+ port@3 {
+ reg = <3>;
+ };
+ port@4 {
+ reg = <4>;
+ };
+ port@5 {
+ reg = <5>;
+ dpsub_dp_out: endpoint {
+ remote-endpoint = <&dp_connector>;
+ };
+ };
+ };
};
...
diff --git a/Documentation/devicetree/bindings/dma/apple,admac.yaml b/Documentation/devicetree/bindings/dma/apple,admac.yaml
index 3b1e667f7ea0..97282469e4af 100644
--- a/Documentation/devicetree/bindings/dma/apple,admac.yaml
+++ b/Documentation/devicetree/bindings/dma/apple,admac.yaml
@@ -56,6 +56,9 @@ properties:
power-domains:
maxItems: 1
+ resets:
+ maxItems: 1
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml b/Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml
index 67aa7bb6d36a..ad107a4d3b33 100644
--- a/Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml
+++ b/Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml
@@ -8,7 +8,6 @@ title: Synopsys DesignWare AXI DMA Controller
maintainers:
- Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
- - Jee Heng Sia <jee.heng.sia@intel.com>
description:
Synopsys DesignWare AXI DMA Controller DT Binding
diff --git a/Documentation/devicetree/bindings/extcon/extcon-usbc-cros-ec.yaml b/Documentation/devicetree/bindings/extcon/extcon-usbc-cros-ec.yaml
index 2d82b44268db..2e5b39881449 100644
--- a/Documentation/devicetree/bindings/extcon/extcon-usbc-cros-ec.yaml
+++ b/Documentation/devicetree/bindings/extcon/extcon-usbc-cros-ec.yaml
@@ -40,6 +40,7 @@ examples:
cros-ec@0 {
compatible = "google,cros-ec-spi";
reg = <0>;
+ interrupts = <44 0>;
usbc_extcon0: extcon0 {
compatible = "google,extcon-usbc-cros-ec";
diff --git a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
index c5b76c9f7ad0..25688571ee7c 100644
--- a/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
+++ b/Documentation/devicetree/bindings/firmware/qcom,scm.yaml
@@ -41,12 +41,14 @@ properties:
- qcom,scm-sc7180
- qcom,scm-sc7280
- qcom,scm-sc8280xp
+ - qcom,scm-sdm670
- qcom,scm-sdm845
- qcom,scm-sdx55
- qcom,scm-sdx65
- qcom,scm-sm6115
- qcom,scm-sm6125
- qcom,scm-sm6350
+ - qcom,scm-sm6375
- qcom,scm-sm8150
- qcom,scm-sm8250
- qcom,scm-sm8350
@@ -88,6 +90,7 @@ allOf:
- qcom,scm-apq8064
- qcom,scm-msm8660
- qcom,scm-msm8960
+ - qcom,scm-sm6375
then:
properties:
clock-names:
diff --git a/Documentation/devicetree/bindings/gpu/host1x/nvidia,tegra234-nvdec.yaml b/Documentation/devicetree/bindings/gpu/host1x/nvidia,tegra234-nvdec.yaml
new file mode 100644
index 000000000000..7cc2dd525a96
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpu/host1x/nvidia,tegra234-nvdec.yaml
@@ -0,0 +1,156 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/gpu/host1x/nvidia,tegra234-nvdec.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Device tree binding for NVIDIA Tegra234 NVDEC
+
+description: |
+ NVDEC is the hardware video decoder present on NVIDIA Tegra210
+ and newer chips. It is located on the Host1x bus and typically
+ programmed through Host1x channels.
+
+maintainers:
+ - Thierry Reding <treding@gmail.com>
+ - Mikko Perttunen <mperttunen@nvidia.com>
+
+properties:
+ $nodename:
+ pattern: "^nvdec@[0-9a-f]*$"
+
+ compatible:
+ enum:
+ - nvidia,tegra234-nvdec
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 3
+
+ clock-names:
+ items:
+ - const: nvdec
+ - const: fuse
+ - const: tsec_pka
+
+ resets:
+ maxItems: 1
+
+ reset-names:
+ items:
+ - const: nvdec
+
+ power-domains:
+ maxItems: 1
+
+ iommus:
+ maxItems: 1
+
+ dma-coherent: true
+
+ interconnects:
+ items:
+ - description: DMA read memory client
+ - description: DMA write memory client
+
+ interconnect-names:
+ items:
+ - const: dma-mem
+ - const: write
+
+ nvidia,memory-controller:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ phandle to the memory controller for determining information for the NVDEC
+ firmware secure carveout. This carveout is configured by the bootloader and
+ not accessible to CPU.
+
+ nvidia,bl-manifest-offset:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Offset to bootloader manifest from beginning of firmware that was configured by
+ the bootloader.
+
+ nvidia,bl-code-offset:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Offset to bootloader code section from beginning of firmware that was configured by
+ the bootloader.
+
+ nvidia,bl-data-offset:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Offset to bootloader data section from beginning of firmware that was configured by
+ the bootloader.
+
+ nvidia,os-manifest-offset:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Offset to operating system manifest from beginning of firmware that was configured by
+ the bootloader.
+
+ nvidia,os-code-offset:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Offset to operating system code section from beginning of firmware that was configured by
+ the bootloader.
+
+ nvidia,os-data-offset:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Offset to operating system data section from beginning of firmware that was configured
+ by the bootloader.
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - resets
+ - reset-names
+ - power-domains
+ - nvidia,memory-controller
+ - nvidia,bl-manifest-offset
+ - nvidia,bl-code-offset
+ - nvidia,bl-data-offset
+ - nvidia,os-manifest-offset
+ - nvidia,os-code-offset
+ - nvidia,os-data-offset
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/tegra234-clock.h>
+ #include <dt-bindings/memory/tegra234-mc.h>
+ #include <dt-bindings/power/tegra234-powergate.h>
+ #include <dt-bindings/reset/tegra234-reset.h>
+
+ nvdec@15480000 {
+ compatible = "nvidia,tegra234-nvdec";
+ reg = <0x15480000 0x00040000>;
+ clocks = <&bpmp TEGRA234_CLK_NVDEC>,
+ <&bpmp TEGRA234_CLK_FUSE>,
+ <&bpmp TEGRA234_CLK_TSEC_PKA>;
+ clock-names = "nvdec", "fuse", "tsec_pka";
+ resets = <&bpmp TEGRA234_RESET_NVDEC>;
+ reset-names = "nvdec";
+ power-domains = <&bpmp TEGRA234_POWER_DOMAIN_NVDEC>;
+ interconnects = <&mc TEGRA234_MEMORY_CLIENT_NVDECSRD &emc>,
+ <&mc TEGRA234_MEMORY_CLIENT_NVDECSWR &emc>;
+ interconnect-names = "dma-mem", "write";
+ iommus = <&smmu_niso1 TEGRA234_SID_NVDEC>;
+ dma-coherent;
+
+ nvidia,memory-controller = <&mc>;
+
+ /* Placeholder values, to be replaced with values from overlay */
+ nvidia,bl-manifest-offset = <0>;
+ nvidia,bl-data-offset = <0>;
+ nvidia,bl-code-offset = <0>;
+ nvidia,os-manifest-offset = <0>;
+ nvidia,os-data-offset = <0>;
+ nvidia,os-code-offset = <0>;
+ };
diff --git a/Documentation/devicetree/bindings/hwinfo/loongson,ls2k-chipid.yaml b/Documentation/devicetree/bindings/hwinfo/loongson,ls2k-chipid.yaml
new file mode 100644
index 000000000000..9d0c36ec1982
--- /dev/null
+++ b/Documentation/devicetree/bindings/hwinfo/loongson,ls2k-chipid.yaml
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/hwinfo/loongson,ls2k-chipid.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Loongson-2 SoC ChipID
+
+maintainers:
+ - Yinbo Zhu <zhuyinbo@loongson.cn>
+
+description: |
+ Loongson-2 SoC contains many groups of global utilities register
+ blocks, of which the ChipID group registers record SoC version,
+ feature, vendor and id information.
+
+properties:
+ compatible:
+ const: loongson,ls2k-chipid
+
+ reg:
+ maxItems: 1
+
+ little-endian: true
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ chipid: chipid@1fe00000 {
+ compatible = "loongson,ls2k-chipid";
+ reg = <0x1fe00000 0x3ffc>;
+ little-endian;
+ };
diff --git a/Documentation/devicetree/bindings/hwmon/adt7475.yaml b/Documentation/devicetree/bindings/hwmon/adt7475.yaml
index ea595102a86e..051c976ab711 100644
--- a/Documentation/devicetree/bindings/hwmon/adt7475.yaml
+++ b/Documentation/devicetree/bindings/hwmon/adt7475.yaml
@@ -61,7 +61,7 @@ patternProperties:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1]
- "adi,pin(5|10)-function":
+ "^adi,pin(5|10)-function$":
description: |
Configures the function for pin 5 on the adi,adt7473 and adi,adt7475. Or
pin 10 on the adi,adt7476 and adi,adt7490.
@@ -70,7 +70,7 @@ patternProperties:
- pwm2
- smbalert#
- "adi,pin(9|14)-function":
+ "^adi,pin(9|14)-function$":
description: |
Configures the function for pin 9 on the adi,adt7473 and adi,adt7475. Or
pin 14 on the adi,adt7476 and adi,adt7490
diff --git a/Documentation/devicetree/bindings/i2c/google,cros-ec-i2c-tunnel.yaml b/Documentation/devicetree/bindings/i2c/google,cros-ec-i2c-tunnel.yaml
index 6e1c70e9275e..cf523615f5e3 100644
--- a/Documentation/devicetree/bindings/i2c/google,cros-ec-i2c-tunnel.yaml
+++ b/Documentation/devicetree/bindings/i2c/google,cros-ec-i2c-tunnel.yaml
@@ -47,6 +47,7 @@ examples:
compatible = "google,cros-ec-spi";
reg = <0>;
spi-max-frequency = <5000000>;
+ interrupts = <99 0>;
i2c-tunnel {
compatible = "google,cros-ec-i2c-tunnel";
diff --git a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml
index 8bac0c4120dd..e94beb2255ba 100644
--- a/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/qcom,spmi-vadc.yaml
@@ -238,42 +238,72 @@ additionalProperties: false
examples:
- |
- spmi_bus {
- #address-cells = <1>;
- #size-cells = <0>;
- /* VADC node */
- pmic_vadc: adc@3100 {
- compatible = "qcom,spmi-vadc";
- reg = <0x3100>;
- interrupts = <0x0 0x31 0x0 0x1>;
+ spmi {
#address-cells = <1>;
#size-cells = <0>;
- #io-channel-cells = <1>;
-
- /* Channel node */
- adc-chan@39 {
- reg = <0x39>;
- qcom,decimation = <512>;
- qcom,ratiometric;
- qcom,hw-settle-time = <200>;
- qcom,avg-samples = <1>;
- qcom,pre-scaling = <1 3>;
- };
-
- adc-chan@9 {
- reg = <0x9>;
- };
-
- adc-chan@a {
- reg = <0xa>;
+ /* VADC node */
+ pmic_vadc: adc@3100 {
+ compatible = "qcom,spmi-vadc";
+ reg = <0x3100>;
+ interrupts = <0x0 0x31 0x0 0x1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+
+ /* Channel node */
+ adc-chan@39 {
+ reg = <0x39>;
+ qcom,decimation = <512>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,avg-samples = <1>;
+ qcom,pre-scaling = <1 3>;
+ };
+
+ adc-chan@9 {
+ reg = <0x9>;
+ };
+
+ adc-chan@a {
+ reg = <0xa>;
+ };
+
+ adc-chan@e {
+ reg = <0xe>;
+ };
+
+ adc-chan@f {
+ reg = <0xf>;
+ };
};
+ };
- adc-chan@e {
- reg = <0xe>;
- };
+ - |
+ #include <dt-bindings/iio/qcom,spmi-adc7-pmk8350.h>
+ #include <dt-bindings/iio/qcom,spmi-adc7-pm8350.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
- adc-chan@f {
- reg = <0xf>;
+ spmi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ adc@3100 {
+ reg = <0x3100>;
+ compatible = "qcom,spmi-adc7";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+
+ /* Other properties are omitted */
+ xo-therm@44 {
+ reg = <PMK8350_ADC7_AMUX_THM1_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+
+ conn-therm@47 {
+ reg = <PM8350_ADC7_AMUX_THM4_100K_PU(1)>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
};
- };
};
diff --git a/Documentation/devicetree/bindings/iio/addac/adi,ad74413r.yaml b/Documentation/devicetree/bindings/iio/addac/adi,ad74413r.yaml
index 03bb90a7f4f8..d2a9f92c0a6d 100644
--- a/Documentation/devicetree/bindings/iio/addac/adi,ad74413r.yaml
+++ b/Documentation/devicetree/bindings/iio/addac/adi,ad74413r.yaml
@@ -114,7 +114,6 @@ examples:
#size-cells = <0>;
cs-gpios = <&gpio 17 GPIO_ACTIVE_LOW>;
- status = "okay";
ad74413r@0 {
compatible = "adi,ad74413r";
diff --git a/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml b/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml
index 5d631f7137e7..5efceb313879 100644
--- a/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml
+++ b/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml
@@ -16,7 +16,9 @@ properties:
- const: allwinner,sun4i-a10-lradc-keys
- const: allwinner,sun8i-a83t-r-lradc
- items:
- - const: allwinner,sun50i-a64-lradc
+ - enum:
+ - allwinner,suniv-f1c100s-lradc
+ - allwinner,sun50i-a64-lradc
- const: allwinner,sun8i-a83t-r-lradc
- const: allwinner,sun50i-r329-lradc
- items:
diff --git a/Documentation/devicetree/bindings/input/azoteq,iqs7222.yaml b/Documentation/devicetree/bindings/input/azoteq,iqs7222.yaml
index 02e605fac408..9ddba7f2e7aa 100644
--- a/Documentation/devicetree/bindings/input/azoteq,iqs7222.yaml
+++ b/Documentation/devicetree/bindings/input/azoteq,iqs7222.yaml
@@ -473,9 +473,6 @@ patternProperties:
Specifies whether the event is to be interpreted as a key (1)
or a switch (5).
- required:
- - linux,code
-
additionalProperties: false
dependencies:
@@ -501,7 +498,7 @@ patternProperties:
azoteq,slider-size:
$ref: /schemas/types.yaml#/definitions/uint32
- minimum: 0
+ minimum: 1
maximum: 65535
description:
Specifies the slider's one-dimensional resolution, equal to the
@@ -575,9 +572,9 @@ patternProperties:
linux,code: true
azoteq,gesture-max-ms:
- multipleOf: 4
+ multipleOf: 16
minimum: 0
- maximum: 1020
+ maximum: 4080
description:
Specifies the length of time (in ms) within which a tap, swipe
or flick gesture must be completed in order to be acknowledged
@@ -585,9 +582,9 @@ patternProperties:
gesture applies to all remaining swipe or flick gestures.
azoteq,gesture-min-ms:
- multipleOf: 4
+ multipleOf: 16
minimum: 0
- maximum: 124
+ maximum: 496
description:
Specifies the length of time (in ms) for which a tap gesture must
be held in order to be acknowledged by the device.
@@ -620,9 +617,6 @@ patternProperties:
GPIO, they must all be of the same type (proximity, touch or
slider gesture).
- required:
- - linux,code
-
additionalProperties: false
required:
@@ -693,6 +687,7 @@ allOf:
properties:
azoteq,slider-size:
multipleOf: 16
+ minimum: 16
maximum: 4080
azoteq,top-speed:
@@ -935,14 +930,14 @@ examples:
event-tap {
linux,code = <KEY_PLAYPAUSE>;
- azoteq,gesture-max-ms = <600>;
- azoteq,gesture-min-ms = <24>;
+ azoteq,gesture-max-ms = <400>;
+ azoteq,gesture-min-ms = <32>;
};
event-flick-pos {
linux,code = <KEY_NEXTSONG>;
- azoteq,gesture-max-ms = <600>;
- azoteq,gesture-dist = <816>;
+ azoteq,gesture-max-ms = <800>;
+ azoteq,gesture-dist = <800>;
};
event-flick-neg {
diff --git a/Documentation/devicetree/bindings/input/gpio-beeper.txt b/Documentation/devicetree/bindings/input/gpio-beeper.txt
deleted file mode 100644
index a5086e37fce6..000000000000
--- a/Documentation/devicetree/bindings/input/gpio-beeper.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-* GPIO beeper device tree bindings
-
-Register a beeper connected to GPIO pin.
-
-Required properties:
-- compatible: Should be "gpio-beeper".
-- gpios: From common gpio binding; gpio connection to beeper enable pin.
-
-Example:
- beeper: beeper {
- compatible = "gpio-beeper";
- gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
- };
diff --git a/Documentation/devicetree/bindings/input/gpio-beeper.yaml b/Documentation/devicetree/bindings/input/gpio-beeper.yaml
new file mode 100644
index 000000000000..290372add3d5
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/gpio-beeper.yaml
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/gpio-beeper.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: GPIO controlled beeper
+
+maintainers:
+ - Fabio Estevam <festevam@denx.de>
+
+properties:
+ compatible:
+ const: gpio-beeper
+
+ gpios:
+ maxItems: 1
+ description:
+ GPIO that drives the beeper.
+
+required:
+ - compatible
+ - gpios
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ beeper {
+ compatible = "gpio-beeper";
+ gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
+ };
diff --git a/Documentation/devicetree/bindings/input/qcom,pm8921-pwrkey.yaml b/Documentation/devicetree/bindings/input/qcom,pm8921-pwrkey.yaml
new file mode 100644
index 000000000000..12c74c083258
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/qcom,pm8921-pwrkey.yaml
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/qcom,pm8921-pwrkey.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm PM8921 PMIC Power Key
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+
+allOf:
+ - $ref: input.yaml#
+
+properties:
+ compatible:
+ oneOf:
+ - enum:
+ - qcom,pm8921-pwrkey
+ - qcom,pm8058-pwrkey
+ - items:
+ - enum:
+ - qcom,pm8018-pwrkey
+ - const: qcom,pm8921-pwrkey
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ items:
+ - description: key release
+ - description: key press
+
+ debounce:
+ description:
+ Time in microseconds that key must be pressed or
+ released for state change interrupt to trigger.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ pull-up:
+ description:
+ Presence of this property indicates that the KPDPWR_N
+ pin should be configured for pull up.
+ $ref: /schemas/types.yaml#/definitions/flag
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ ssbi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmic@0 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pwrkey@1c {
+ compatible = "qcom,pm8921-pwrkey";
+ reg = <0x1c>;
+ interrupt-parent = <&pmicint>;
+ interrupts = <50 IRQ_TYPE_EDGE_RISING>, <51 IRQ_TYPE_EDGE_RISING>;
+ debounce = <15625>;
+ pull-up;
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/input/qcom,pm8xxx-pwrkey.txt b/Documentation/devicetree/bindings/input/qcom,pm8xxx-pwrkey.txt
deleted file mode 100644
index 588536cc96ed..000000000000
--- a/Documentation/devicetree/bindings/input/qcom,pm8xxx-pwrkey.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-Qualcomm PM8xxx PMIC Power Key
-
-PROPERTIES
-
-- compatible:
- Usage: required
- Value type: <string>
- Definition: must be one of:
- "qcom,pm8058-pwrkey"
- "qcom,pm8921-pwrkey"
-
-- reg:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: address of power key control register
-
-- interrupts:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: the first interrupt specifies the key release interrupt
- and the second interrupt specifies the key press interrupt.
- The format of the specifier is defined by the binding
- document describing the node's interrupt parent.
-
-- debounce:
- Usage: optional
- Value type: <u32>
- Definition: time in microseconds that key must be pressed or release
- for state change interrupt to trigger.
-
-- pull-up:
- Usage: optional
- Value type: <empty>
- Definition: presence of this property indicates that the KPDPWR_N pin
- should be configured for pull up.
-
-EXAMPLE
-
- pwrkey@1c {
- compatible = "qcom,pm8921-pwrkey";
- reg = <0x1c>;
- interrupt-parent = <&pmicintc>;
- interrupts = <50 1>, <51 1>;
- debounce = <15625>;
- pull-up;
- };
diff --git a/Documentation/devicetree/bindings/input/ti,drv260x.txt b/Documentation/devicetree/bindings/input/ti,drv260x.txt
deleted file mode 100644
index 4c5312eaaa85..000000000000
--- a/Documentation/devicetree/bindings/input/ti,drv260x.txt
+++ /dev/null
@@ -1,50 +0,0 @@
-* Texas Instruments - drv260x Haptics driver family
-
-Required properties:
- - compatible - One of:
- "ti,drv2604" - DRV2604
- "ti,drv2605" - DRV2605
- "ti,drv2605l" - DRV2605L
- - reg - I2C slave address
- - vbat-supply - Required supply regulator
- - mode - Power up mode of the chip (defined in include/dt-bindings/input/ti-drv260x.h)
- DRV260X_LRA_MODE - Linear Resonance Actuator mode (Piezoelectric)
- DRV260X_LRA_NO_CAL_MODE - This is a LRA Mode but there is no calibration
- sequence during init. And the device is configured for real
- time playback mode (RTP mode).
- DRV260X_ERM_MODE - Eccentric Rotating Mass mode (Rotary vibrator)
- - library-sel - These are ROM based waveforms pre-programmed into the IC.
- This should be set to set the library to use at power up.
- (defined in include/dt-bindings/input/ti-drv260x.h)
- DRV260X_LIB_EMPTY - Do not use a pre-programmed library
- DRV260X_ERM_LIB_A - Pre-programmed Library
- DRV260X_ERM_LIB_B - Pre-programmed Library
- DRV260X_ERM_LIB_C - Pre-programmed Library
- DRV260X_ERM_LIB_D - Pre-programmed Library
- DRV260X_ERM_LIB_E - Pre-programmed Library
- DRV260X_ERM_LIB_F - Pre-programmed Library
- DRV260X_LIB_LRA - Pre-programmed LRA Library
-
-Optional properties:
- - enable-gpio - gpio pin to enable/disable the device.
- - vib-rated-mv - The rated voltage of the actuator in millivolts.
- If this is not set then the value will be defaulted to
- 3.2 v.
- - vib-overdrive-mv - The overdrive voltage of the actuator in millivolts.
- If this is not set then the value will be defaulted to
- 3.2 v.
-Example:
-
-haptics: haptics@5a {
- compatible = "ti,drv2605l";
- reg = <0x5a>;
- vbat-supply = <&vbat>;
- enable-gpio = <&gpio1 28 GPIO_ACTIVE_HIGH>;
- mode = <DRV260X_LRA_MODE>;
- library-sel = <DRV260X_LIB_LRA>;
- vib-rated-mv = <3200>;
- vib-overdrive-mv = <3200>;
-}
-
-For more product information please see the link below:
-http://www.ti.com/product/drv2605
diff --git a/Documentation/devicetree/bindings/input/ti,drv260x.yaml b/Documentation/devicetree/bindings/input/ti,drv260x.yaml
new file mode 100644
index 000000000000..c6245c5b9e2e
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/ti,drv260x.yaml
@@ -0,0 +1,109 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/ti,drv260x.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments - drv260x Haptics driver family
+
+maintainers:
+ - Andrew Davis <afd@ti.com>
+
+properties:
+ compatible:
+ enum:
+ - ti,drv2604
+ - ti,drv2605
+ - ti,drv2605l
+
+ reg:
+ maxItems: 1
+
+ vbat-supply:
+ description: Power supply to the haptic motor
+
+ # TODO: Deprecate 'mode' in favor of differently named property
+ mode:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ Power up mode of the chip
+ (defined in include/dt-bindings/input/ti-drv260x.h)
+
+ DRV260X_LRA_MODE
+ Linear Resonance Actuator mode (Piezoelectric)
+
+ DRV260X_LRA_NO_CAL_MODE
+ This is a LRA Mode but there is no calibration sequence during init.
+ And the device is configured for real time playback mode (RTP mode).
+
+ DRV260X_ERM_MODE
+ Eccentric Rotating Mass mode (Rotary vibrator)
+ enum: [ 0, 1, 2 ]
+
+ library-sel:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ These are ROM based waveforms pre-programmed into the IC.
+ This should be set to set the library to use at power up.
+ (defined in include/dt-bindings/input/ti-drv260x.h)
+
+ DRV260X_LIB_EMPTY - Do not use a pre-programmed library
+ DRV260X_ERM_LIB_A - Pre-programmed Library
+ DRV260X_ERM_LIB_B - Pre-programmed Library
+ DRV260X_ERM_LIB_C - Pre-programmed Library
+ DRV260X_ERM_LIB_D - Pre-programmed Library
+ DRV260X_ERM_LIB_E - Pre-programmed Library
+ DRV260X_ERM_LIB_F - Pre-programmed Library
+ DRV260X_LIB_LRA - Pre-programmed LRA Library
+ enum: [ 0, 1, 2, 3, 4, 5, 6, 7 ]
+
+ enable-gpio:
+ maxItems: 1
+ deprecated: true
+
+ enable-gpios:
+ maxItems: 1
+
+ vib-rated-mv:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ The rated voltage of the actuator in millivolts.
+ If this is not set then the value will be defaulted to 3200 mV.
+ default: 3200
+
+ vib-overdrive-mv:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: |
+ The overdrive voltage of the actuator in millivolts.
+ If this is not set then the value will be defaulted to 3200 mV.
+ default: 3200
+
+required:
+ - compatible
+ - reg
+ - enable-gpios
+ - mode
+ - library-sel
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/input/ti-drv260x.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ haptics@5a {
+ compatible = "ti,drv2605l";
+ reg = <0x5a>;
+ vbat-supply = <&vbat>;
+ enable-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+ mode = <DRV260X_LRA_MODE>;
+ library-sel = <DRV260X_LIB_LRA>;
+ vib-rated-mv = <3200>;
+ vib-overdrive-mv = <3200>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/input/touchscreen/cypress,tt21000.yaml b/Documentation/devicetree/bindings/input/touchscreen/cypress,tt21000.yaml
new file mode 100644
index 000000000000..1959ec394768
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/cypress,tt21000.yaml
@@ -0,0 +1,106 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/touchscreen/cypress,tt21000.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Cypress TT21000 touchscreen controller
+
+description: The Cypress TT21000 series (also known as "CYTTSP5" after
+ the marketing name Cypress TrueTouch Standard Product series 5).
+
+maintainers:
+ - Alistair Francis <alistair@alistair23.me>
+
+allOf:
+ - $ref: touchscreen.yaml#
+
+properties:
+ compatible:
+ const: cypress,tt21000
+
+ reg:
+ maxItems: 1
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+ interrupts:
+ maxItems: 1
+
+ vdd-supply:
+ description: Regulator for voltage.
+
+ reset-gpios:
+ maxItems: 1
+
+ linux,keycodes:
+ description: EV_ABS specific event code generated by the axis.
+
+patternProperties:
+ "^button@[0-9]+$":
+ type: object
+ $ref: ../input.yaml#
+ properties:
+ reg:
+ maxItems: 1
+ linux,keycodes:
+ description: Keycode to emit
+
+ required:
+ - reg
+ - linux,keycodes
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - vdd-supply
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/input/linux-event-codes.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ touchscreen@24 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compatible = "cypress,tt21000";
+ reg = <0x24>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&tp_reset_ds203>;
+ interrupt-parent = <&pio>;
+ interrupts = <1 5 IRQ_TYPE_LEVEL_LOW>;
+ reset-gpios = <&pio 7 1 GPIO_ACTIVE_LOW>;
+ vdd-supply = <&reg_touch>;
+
+ button@0 {
+ reg = <0>;
+ linux,keycodes = <KEY_HOMEPAGE>;
+ };
+
+ button@1 {
+ reg = <1>;
+ linux,keycodes = <KEY_MENU>;
+ };
+
+ button@2 {
+ reg = <2>;
+ linux,keycodes = <KEY_BACK>;
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt
index 92fb2620f5e2..ebbe93810574 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt
+++ b/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt
@@ -13,6 +13,6 @@ Example:
compatible = "eeti,egalax_ts";
reg = <0x04>;
interrupt-parent = <&gpio1>;
- interrupts = <9 2>;
- wakeup-gpios = <&gpio1 9 0>;
+ interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
+ wakeup-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
};
diff --git a/Documentation/devicetree/bindings/input/touchscreen/himax,hx83112b.yaml b/Documentation/devicetree/bindings/input/touchscreen/himax,hx83112b.yaml
new file mode 100644
index 000000000000..be2ba185c086
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/himax,hx83112b.yaml
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/touchscreen/himax,hx83112b.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Himax hx83112b touchscreen controller bindings
+
+maintainers:
+ - Job Noorman <job@noorman.info>
+
+allOf:
+ - $ref: touchscreen.yaml#
+
+properties:
+ compatible:
+ enum:
+ - himax,hx83112b
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ reset-gpios:
+ maxItems: 1
+
+ touchscreen-inverted-x: true
+ touchscreen-inverted-y: true
+ touchscreen-size-x: true
+ touchscreen-size-y: true
+ touchscreen-swapped-x-y: true
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - reset-gpios
+ - touchscreen-size-x
+ - touchscreen-size-y
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/gpio/gpio.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ touchscreen@48 {
+ compatible = "himax,hx83112b";
+ reg = <0x48>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <65 IRQ_TYPE_LEVEL_LOW>;
+ touchscreen-size-x = <1080>;
+ touchscreen-size-y = <2160>;
+ reset-gpios = <&tlmm 64 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/input/touchscreen/hynitron,cstxxx.yaml b/Documentation/devicetree/bindings/input/touchscreen/hynitron,cstxxx.yaml
new file mode 100644
index 000000000000..9cb5d4af00f7
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/touchscreen/hynitron,cstxxx.yaml
@@ -0,0 +1,65 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/input/touchscreen/hynitron,cstxxx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Hynitron cstxxx series touchscreen controller
+
+description: |
+ Bindings for Hynitron cstxxx series multi-touch touchscreen
+ controllers.
+
+maintainers:
+ - Chris Morgan <macromorgan@hotmail.com>
+
+allOf:
+ - $ref: touchscreen.yaml#
+
+properties:
+ compatible:
+ enum:
+ - hynitron,cst340
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ reset-gpios:
+ maxItems: 1
+
+ touchscreen-size-x: true
+ touchscreen-size-y: true
+ touchscreen-inverted-x: true
+ touchscreen-inverted-y: true
+ touchscreen-swapped-x-y: true
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - reset-gpios
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ touchscreen@1a {
+ compatible = "hynitron,cst340";
+ reg = <0x1a>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <9 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&gpio4 6 GPIO_ACTIVE_LOW>;
+ touchscreen-size-x = <640>;
+ touchscreen-size-y = <480>;
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/input/touchscreen/mstar,msg2638.yaml b/Documentation/devicetree/bindings/input/touchscreen/mstar,msg2638.yaml
index 3a42c23faf6f..af4f954de958 100644
--- a/Documentation/devicetree/bindings/input/touchscreen/mstar,msg2638.yaml
+++ b/Documentation/devicetree/bindings/input/touchscreen/mstar,msg2638.yaml
@@ -14,7 +14,9 @@ allOf:
properties:
compatible:
- const: mstar,msg2638
+ enum:
+ - mstar,msg2138
+ - mstar,msg2638
reg:
const: 0x26
@@ -34,6 +36,10 @@ properties:
touchscreen-size-x: true
touchscreen-size-y: true
+ linux,keycodes:
+ minItems: 1
+ maxItems: 4
+
additionalProperties: false
required:
diff --git a/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml b/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
index e18107eafe7c..698588e9aa86 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/apple,aic.yaml
@@ -90,7 +90,6 @@ properties:
maximum: 5
cpus:
- $ref: /schemas/types.yaml#/definitions/phandle-array
description:
Should be a list of phandles to CPU nodes (as described in
Documentation/devicetree/bindings/arm/cpus.yaml).
diff --git a/Documentation/devicetree/bindings/interrupt-controller/apple,aic2.yaml b/Documentation/devicetree/bindings/interrupt-controller/apple,aic2.yaml
index 47a78a167aba..06948c0e36a5 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/apple,aic2.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/apple,aic2.yaml
@@ -69,6 +69,35 @@ properties:
power-domains:
maxItems: 1
+ affinities:
+ type: object
+ additionalProperties: false
+ description:
+ FIQ affinity can be expressed as a single "affinities" node,
+ containing a set of sub-nodes, one per FIQ with a non-default
+ affinity.
+ patternProperties:
+ "^.+-affinity$":
+ type: object
+ additionalProperties: false
+ properties:
+ apple,fiq-index:
+ description:
+ The interrupt number specified as a FIQ, and for which
+ the affinity is not the default.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ maximum: 5
+
+ cpus:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ description:
+ Should be a list of phandles to CPU nodes (as described in
+ Documentation/devicetree/bindings/arm/cpus.yaml).
+
+ required:
+ - apple,fiq-index
+ - cpus
+
required:
- compatible
- '#interrupt-cells'
diff --git a/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.txt b/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.txt
deleted file mode 100644
index 7d19f494f19a..000000000000
--- a/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-Interrupt chips
----------------
-
-* Intel I/O Advanced Programmable Interrupt Controller (IO APIC)
-
- Required properties:
- --------------------
- compatible = "intel,ce4100-ioapic";
- #interrupt-cells = <2>;
-
- Device's interrupt property:
-
- interrupts = <P S>;
-
- The first number (P) represents the interrupt pin which is wired to the
- IO APIC. The second number (S) represents the sense of interrupt which
- should be configured and can be one of:
- 0 - Edge Rising
- 1 - Level Low
- 2 - Level High
- 3 - Edge Falling
-
-* Local APIC
- Required property:
-
- compatible = "intel,ce4100-lapic";
diff --git a/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.yaml b/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.yaml
new file mode 100644
index 000000000000..39ab8cdd19b4
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-ioapic.yaml
@@ -0,0 +1,60 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/interrupt-controller/intel,ce4100-ioapic.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Intel I/O Advanced Programmable Interrupt Controller (IO APIC)
+
+maintainers:
+ - Rahul Tanwar <rtanwar@maxlinear.com>
+
+description: |
+ Intel's Advanced Programmable Interrupt Controller (APIC) is a
+ family of interrupt controllers. The APIC is a split
+ architecture design, with a local component (LAPIC) integrated
+ into the processor itself and an external I/O APIC. Local APIC
+ (lapic) receives interrupts from the processor's interrupt pins,
+ from internal sources and from an external I/O APIC (ioapic).
+ And it sends these to the processor core for handling.
+ See [1] Chapter 8 for more details.
+
+ Many of the Intel's generic devices like hpet, ioapic, lapic have
+ the ce4100 name in their compatible property names because they
+ first appeared in CE4100 SoC.
+
+ This schema defines bindings for I/O APIC interrupt controller.
+
+ [1] https://pdos.csail.mit.edu/6.828/2008/readings/ia32/IA32-3A.pdf
+
+properties:
+ compatible:
+ const: intel,ce4100-ioapic
+
+ reg:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ '#interrupt-cells':
+ const: 2
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupt-controller
+ - '#interrupt-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ ioapic1: interrupt-controller@fec00000 {
+ compatible = "intel,ce4100-ioapic";
+ reg = <0xfec00000 0x1000>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-lapic.yaml b/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-lapic.yaml
new file mode 100644
index 000000000000..d2d0145cb889
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/intel,ce4100-lapic.yaml
@@ -0,0 +1,71 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: "http://devicetree.org/schemas/interrupt-controller/intel,ce4100-lapic.yaml#"
+$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+
+title: Intel Local Advanced Programmable Interrupt Controller (LAPIC)
+
+maintainers:
+ - Rahul Tanwar <rtanwar@maxlinear.com>
+
+description: |
+ Intel's Advanced Programmable Interrupt Controller (APIC) is a
+ family of interrupt controllers. The APIC is a split
+ architecture design, with a local component (LAPIC) integrated
+ into the processor itself and an external I/O APIC. Local APIC
+ (lapic) receives interrupts from the processor's interrupt pins,
+ from internal sources and from an external I/O APIC (ioapic).
+ And it sends these to the processor core for handling.
+ See [1] Chapter 8 for more details.
+
+ Many of the Intel's generic devices like hpet, ioapic, lapic have
+ the ce4100 name in their compatible property names because they
+ first appeared in CE4100 SoC.
+
+ This schema defines bindings for local APIC interrupt controller.
+
+ [1] https://pdos.csail.mit.edu/6.828/2008/readings/ia32/IA32-3A.pdf
+
+properties:
+ compatible:
+ const: intel,ce4100-lapic
+
+ reg:
+ maxItems: 1
+
+ interrupt-controller: true
+
+ '#interrupt-cells':
+ const: 2
+
+ intel,virtual-wire-mode:
+ description: Intel defines a few possible interrupt delivery
+ modes. With respect to boot/init time, mainly two interrupt
+ delivery modes are possible.
+ PIC Mode - Legacy external 8259 compliant PIC interrupt controller.
+ Virtual Wire Mode - use lapic as virtual wire interrupt delivery mode.
+ For ACPI or MPS spec compliant systems, it is figured out by some read
+ only bit field/s available in their respective defined data structures.
+ For OF based systems, it is by default set to PIC mode.
+ But if this optional boolean property is set, then the interrupt delivery
+ mode is configured to virtual wire compatibility mode.
+ type: boolean
+
+required:
+ - compatible
+ - reg
+ - interrupt-controller
+ - '#interrupt-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ lapic0: interrupt-controller@fee00000 {
+ compatible = "intel,ce4100-lapic";
+ reg = <0xfee00000 0x1000>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ intel,virtual-wire-mode;
+ };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/loongarch,cpu-interrupt-controller.yaml b/Documentation/devicetree/bindings/interrupt-controller/loongarch,cpu-interrupt-controller.yaml
new file mode 100644
index 000000000000..2a1cf885c99d
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/loongarch,cpu-interrupt-controller.yaml
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interrupt-controller/loongarch,cpu-interrupt-controller.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: LoongArch CPU Interrupt Controller
+
+maintainers:
+ - Liu Peibao <liupeibao@loongson.cn>
+
+properties:
+ compatible:
+ const: loongarch,cpu-interrupt-controller
+
+ '#interrupt-cells':
+ const: 1
+
+ interrupt-controller: true
+
+additionalProperties: false
+
+required:
+ - compatible
+ - '#interrupt-cells'
+ - interrupt-controller
+
+examples:
+ - |
+ interrupt-controller {
+ compatible = "loongarch,cpu-interrupt-controller";
+ #interrupt-cells = <1>;
+ interrupt-controller;
+ };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/mediatek,cirq.txt b/Documentation/devicetree/bindings/interrupt-controller/mediatek,cirq.txt
deleted file mode 100644
index 5865f4f2c69d..000000000000
--- a/Documentation/devicetree/bindings/interrupt-controller/mediatek,cirq.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-* Mediatek 27xx cirq
-
-In Mediatek SOCs, the CIRQ is a low power interrupt controller designed to
-work outside MCUSYS which comprises with Cortex-Ax cores,CCI and GIC.
-The external interrupts (outside MCUSYS) will feed through CIRQ and connect
-to GIC in MCUSYS. When CIRQ is enabled, it will record the edge-sensitive
-interrupts and generate a pulse signal to parent interrupt controller when
-flush command is executed. With CIRQ, MCUSYS can be completely turned off
-to improve the system power consumption without losing interrupts.
-
-Required properties:
-- compatible: should be one of
- - "mediatek,mt2701-cirq" for mt2701 CIRQ
- - "mediatek,mt8135-cirq" for mt8135 CIRQ
- - "mediatek,mt8173-cirq" for mt8173 CIRQ
- and "mediatek,cirq" as a fallback.
-- interrupt-controller : Identifies the node as an interrupt controller.
-- #interrupt-cells : Use the same format as specified by GIC in arm,gic.txt.
-- reg: Physical base address of the cirq registers and length of memory
- mapped region.
-- mediatek,ext-irq-range: Identifies external irq number range in different
- SOCs.
-
-Example:
- cirq: interrupt-controller@10204000 {
- compatible = "mediatek,mt2701-cirq",
- "mediatek,mtk-cirq";
- interrupt-controller;
- #interrupt-cells = <3>;
- interrupt-parent = <&sysirq>;
- reg = <0 0x10204000 0 0x400>;
- mediatek,ext-irq-start = <32 200>;
- };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/mediatek,mtk-cirq.yaml b/Documentation/devicetree/bindings/interrupt-controller/mediatek,mtk-cirq.yaml
new file mode 100644
index 000000000000..fdcb4d8db818
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/mediatek,mtk-cirq.yaml
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interrupt-controller/mediatek,mtk-cirq.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek System Interrupt Controller
+
+maintainers:
+ - Youlin Pei <youlin.pei@mediatek.com>
+
+description:
+ In MediaTek SoCs, the CIRQ is a low power interrupt controller designed to
+ work outside of MCUSYS which comprises with Cortex-Ax cores, CCI and GIC.
+ The external interrupts (outside MCUSYS) will feed through CIRQ and connect
+ to GIC in MCUSYS. When CIRQ is enabled, it will record the edge-sensitive
+ interrupts and generate a pulse signal to parent interrupt controller when
+ flush command is executed. With CIRQ, MCUSYS can be completely turned off
+ to improve the system power consumption without losing interrupts.
+
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - mediatek,mt2701-cirq
+ - mediatek,mt8135-cirq
+ - mediatek,mt8173-cirq
+ - mediatek,mt8192-cirq
+ - const: mediatek,mtk-cirq
+
+ reg:
+ maxItems: 1
+
+ '#interrupt-cells':
+ const: 3
+
+ interrupt-controller: true
+
+ mediatek,ext-irq-range:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ items:
+ - description: First CIRQ interrupt
+ - description: Last CIRQ interrupt
+ description:
+ Identifies the range of external interrupts in different SoCs
+
+required:
+ - compatible
+ - reg
+ - '#interrupt-cells'
+ - interrupt-controller
+ - mediatek,ext-irq-range
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ cirq: interrupt-controller@10204000 {
+ compatible = "mediatek,mt2701-cirq", "mediatek,mtk-cirq";
+ reg = <0x10204000 0x400>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ interrupt-parent = <&sysirq>;
+ mediatek,ext-irq-range = <32 200>;
+ };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml b/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml
index b6f56cf5fbe3..94791e261c42 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml
+++ b/Documentation/devicetree/bindings/interrupt-controller/qcom,pdc.yaml
@@ -28,11 +28,15 @@ properties:
- enum:
- qcom,sc7180-pdc
- qcom,sc7280-pdc
+ - qcom,sc8280xp-pdc
- qcom,sdm845-pdc
+ - qcom,sdx55-pdc
+ - qcom,sdx65-pdc
- qcom,sm6350-pdc
- qcom,sm8150-pdc
- qcom,sm8250-pdc
- qcom,sm8350-pdc
+ - qcom,sm8450-pdc
- const: qcom,pdc
reg:
diff --git a/Documentation/devicetree/bindings/iommu/apple,dart.yaml b/Documentation/devicetree/bindings/iommu/apple,dart.yaml
index 82ad669feef7..06af2bacbe97 100644
--- a/Documentation/devicetree/bindings/iommu/apple,dart.yaml
+++ b/Documentation/devicetree/bindings/iommu/apple,dart.yaml
@@ -22,7 +22,9 @@ description: |+
properties:
compatible:
- const: apple,t8103-dart
+ enum:
+ - apple,t8103-dart
+ - apple,t6000-dart
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml b/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml
index 8854569ca3a6..26d0a5121f02 100644
--- a/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml
+++ b/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.yaml
@@ -29,6 +29,7 @@ properties:
- renesas,ipmmu-r8a7793 # R-Car M2-N
- renesas,ipmmu-r8a7794 # R-Car E2
- const: renesas,ipmmu-vmsa # R-Mobile APE6 or R-Car Gen2 or RZ/G1
+
- items:
- enum:
- renesas,ipmmu-r8a774a1 # RZ/G2M
@@ -43,10 +44,11 @@ properties:
- renesas,ipmmu-r8a77980 # R-Car V3H
- renesas,ipmmu-r8a77990 # R-Car E3
- renesas,ipmmu-r8a77995 # R-Car D3
- - renesas,ipmmu-r8a779a0 # R-Car V3U
+
- items:
- enum:
- - renesas,ipmmu-r8a779f0 # R-Car S4-8
+ - renesas,ipmmu-r8a779a0 # R-Car V3U
+ - renesas,ipmmu-r8a779f0 # R-Car S4-8
- const: renesas,rcar-gen4-ipmmu-vmsa # R-Car Gen4
reg:
diff --git a/Documentation/devicetree/bindings/ipmi/ssif-bmc.yaml b/Documentation/devicetree/bindings/ipmi/ssif-bmc.yaml
new file mode 100644
index 000000000000..02b662d780bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/ipmi/ssif-bmc.yaml
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/ipmi/ssif-bmc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: SSIF IPMI BMC interface
+
+description: SSIF IPMI BMC device bindings
+
+maintainers:
+ - Quan Nguyen <quan@os.amperecomputing.com>
+
+properties:
+ compatible:
+ enum:
+ - ssif-bmc
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ssif-bmc@10 {
+ compatible = "ssif-bmc";
+ reg = <0x10>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/leds/irled/gpio-ir-tx.txt b/Documentation/devicetree/bindings/leds/irled/gpio-ir-tx.txt
deleted file mode 100644
index cbe8dfd29715..000000000000
--- a/Documentation/devicetree/bindings/leds/irled/gpio-ir-tx.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-Device tree bindings for IR LED connected through gpio pin which is used as
-remote controller transmitter.
-
-Required properties:
- - compatible: should be "gpio-ir-tx".
- - gpios : Should specify the IR LED GPIO, see "gpios property" in
- Documentation/devicetree/bindings/gpio/gpio.txt. Active low LEDs
- should be indicated using flags in the GPIO specifier.
-
-Example:
- irled@0 {
- compatible = "gpio-ir-tx";
- gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
- };
diff --git a/Documentation/devicetree/bindings/leds/irled/gpio-ir-tx.yaml b/Documentation/devicetree/bindings/leds/irled/gpio-ir-tx.yaml
new file mode 100644
index 000000000000..5839d00c7089
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/irled/gpio-ir-tx.yaml
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/irled/gpio-ir-tx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: IR LED connected through GPIO pin
+
+maintainers:
+ - Sean Young <sean@mess.org>
+
+description:
+ IR LED connected through GPIO pin which is used as remote controller
+ transmitter.
+
+properties:
+ compatible:
+ const: gpio-ir-tx
+
+ gpios:
+ maxItems: 1
+
+required:
+ - compatible
+ - gpios
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ irled {
+ compatible = "gpio-ir-tx";
+ gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+ };
diff --git a/Documentation/devicetree/bindings/leds/irled/ir-spi-led.yaml b/Documentation/devicetree/bindings/leds/irled/ir-spi-led.yaml
new file mode 100644
index 000000000000..72cadebf6e3e
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/irled/ir-spi-led.yaml
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/irled/ir-spi-led.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: IR LED connected through SPI bus
+
+maintainers:
+ - Sean Young <sean@mess.org>
+
+description:
+ IR LED switch is connected to the MOSI line of the SPI device and the data
+ is delivered through that.
+
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+properties:
+ compatible:
+ const: ir-spi-led
+
+ reg:
+ maxItems: 1
+
+ duty-cycle:
+ $ref: /schemas/types.yaml#/definitions/uint8
+ enum: [50, 60, 70, 75, 80, 90]
+ description:
+ Percentage of one period in which the signal is active.
+
+ led-active-low:
+ type: boolean
+ description:
+ Output is negated with a NOT gate.
+
+ power-supply: true
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ irled@0 {
+ compatible = "ir-spi-led";
+ reg = <0x0>;
+
+ duty-cycle = /bits/ 8 <60>;
+ led-active-low;
+ power-supply = <&irda_regulator>;
+ spi-max-frequency = <5000000>;
+ };
+ };
+
diff --git a/Documentation/devicetree/bindings/leds/irled/pwm-ir-tx.txt b/Documentation/devicetree/bindings/leds/irled/pwm-ir-tx.txt
deleted file mode 100644
index 66e5672c2e3d..000000000000
--- a/Documentation/devicetree/bindings/leds/irled/pwm-ir-tx.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-Device tree bindings for IR LED connected through pwm pin which is used as
-remote controller transmitter.
-
-Required properties:
- - compatible: should be "pwm-ir-tx".
- - pwms : PWM property to point to the PWM device (phandle)/port (id)
- and to specify the period time to be used: <&phandle id period_ns>;
-
-Example:
- irled {
- compatible = "pwm-ir-tx";
- pwms = <&pwm0 0 10000000>;
- };
diff --git a/Documentation/devicetree/bindings/leds/irled/pwm-ir-tx.yaml b/Documentation/devicetree/bindings/leds/irled/pwm-ir-tx.yaml
new file mode 100644
index 000000000000..f2a6fa140f38
--- /dev/null
+++ b/Documentation/devicetree/bindings/leds/irled/pwm-ir-tx.yaml
@@ -0,0 +1,34 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/leds/irled/pwm-ir-tx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: IR LED connected through PWM pin
+
+maintainers:
+ - Sean Young <sean@mess.org>
+
+description:
+ IR LED connected through PWM pin which is used as remote controller
+ transmitter.
+
+properties:
+ compatible:
+ const: pwm-ir-tx
+
+ pwms:
+ maxItems: 1
+
+required:
+ - compatible
+ - pwms
+
+additionalProperties: false
+
+examples:
+ - |
+ irled {
+ compatible = "pwm-ir-tx";
+ pwms = <&pwm0 0 10000000>;
+ };
diff --git a/Documentation/devicetree/bindings/leds/irled/spi-ir-led.txt b/Documentation/devicetree/bindings/leds/irled/spi-ir-led.txt
deleted file mode 100644
index 83ff1b4d70a6..000000000000
--- a/Documentation/devicetree/bindings/leds/irled/spi-ir-led.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-Device tree bindings for IR LED connected through SPI bus which is used as
-remote controller.
-
-The IR LED switch is connected to the MOSI line of the SPI device and the data
-are delivered thourgh that.
-
-Required properties:
- - compatible: should be "ir-spi-led".
-
-Optional properties:
- - duty-cycle: 8 bit value that represents the percentage of one period
- in which the signal is active. It can be 50, 60, 70, 75, 80 or 90.
- - led-active-low: boolean value that specifies whether the output is
- negated with a NOT gate.
- - power-supply: specifies the power source. It can either be a regulator
- or a gpio which enables a regulator, i.e. a regulator-fixed as
- described in
- Documentation/devicetree/bindings/regulator/fixed-regulator.yaml
-
-Example:
-
- irled@0 {
- compatible = "ir-spi-led";
- reg = <0x0>;
- spi-max-frequency = <5000000>;
- power-supply = <&vdd_led>;
- led-active-low;
- duty-cycle = /bits/ 8 <60>;
- };
diff --git a/Documentation/devicetree/bindings/leds/issi,is31fl319x.yaml b/Documentation/devicetree/bindings/leds/issi,is31fl319x.yaml
index 940333f2d69c..2929382625b6 100644
--- a/Documentation/devicetree/bindings/leds/issi,is31fl319x.yaml
+++ b/Documentation/devicetree/bindings/leds/issi,is31fl319x.yaml
@@ -57,6 +57,7 @@ patternProperties:
"^led@[1-9]$":
type: object
$ref: common.yaml#
+ unevaluatedProperties: false
properties:
reg:
diff --git a/Documentation/devicetree/bindings/leds/leds-aw2013.yaml b/Documentation/devicetree/bindings/leds/leds-aw2013.yaml
index e24b0d15ef01..6c3ea0f06cef 100644
--- a/Documentation/devicetree/bindings/leds/leds-aw2013.yaml
+++ b/Documentation/devicetree/bindings/leds/leds-aw2013.yaml
@@ -33,6 +33,7 @@ patternProperties:
"^led@[0-2]$":
type: object
$ref: common.yaml#
+ unevaluatedProperties: false
properties:
reg:
diff --git a/Documentation/devicetree/bindings/leds/leds-gpio.yaml b/Documentation/devicetree/bindings/leds/leds-gpio.yaml
index 7ad2baeda0b0..7e11703acbd6 100644
--- a/Documentation/devicetree/bindings/leds/leds-gpio.yaml
+++ b/Documentation/devicetree/bindings/leds/leds-gpio.yaml
@@ -23,8 +23,8 @@ patternProperties:
# node name to at least catch some child nodes.
"(^led-[0-9a-f]$|led)":
type: object
-
$ref: common.yaml#
+ unevaluatedProperties: false
properties:
gpios:
diff --git a/Documentation/devicetree/bindings/leds/leds-lgm.yaml b/Documentation/devicetree/bindings/leds/leds-lgm.yaml
index f8d7963c3a13..8b3b3bf1eaf2 100644
--- a/Documentation/devicetree/bindings/leds/leds-lgm.yaml
+++ b/Documentation/devicetree/bindings/leds/leds-lgm.yaml
@@ -56,7 +56,8 @@ properties:
patternProperties:
"^led@[0-2]$":
- type: object
+ $ref: common.yaml#
+ unevaluatedProperties: false
properties:
reg:
@@ -64,6 +65,9 @@ properties:
minimum: 0
maximum: 2
+ led-gpios:
+ maxItems: 1
+
intel,sso-hw-trigger:
type: boolean
description: This property indicates Hardware driven/control LED.
@@ -118,14 +122,14 @@ examples:
reg = <0>;
function = "gphy";
color = <LED_COLOR_ID_GREEN>;
- led-gpio = <&ssogpio 0 0>;
+ led-gpios = <&ssogpio 0 0>;
};
led@2 {
reg = <2>;
function = LED_FUNCTION_POWER;
color = <LED_COLOR_ID_GREEN>;
- led-gpio = <&ssogpio 23 0>;
+ led-gpios = <&ssogpio 23 0>;
};
};
};
diff --git a/Documentation/devicetree/bindings/leds/leds-lp50xx.yaml b/Documentation/devicetree/bindings/leds/leds-lp50xx.yaml
index 63da380748bf..402c25424525 100644
--- a/Documentation/devicetree/bindings/leds/leds-lp50xx.yaml
+++ b/Documentation/devicetree/bindings/leds/leds-lp50xx.yaml
@@ -77,6 +77,14 @@ patternProperties:
"^led@[0-9a-f]+$":
type: object
$ref: common.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ reg:
+ maxItems: 1
+
+ required:
+ - reg
required:
- compatible
diff --git a/Documentation/devicetree/bindings/leds/leds-lp55xx.yaml b/Documentation/devicetree/bindings/leds/leds-lp55xx.yaml
index 7ec676e53851..ae607911f1db 100644
--- a/Documentation/devicetree/bindings/leds/leds-lp55xx.yaml
+++ b/Documentation/devicetree/bindings/leds/leds-lp55xx.yaml
@@ -43,11 +43,13 @@ properties:
- 1 # internal
- 2 # external
- enable-gpio:
+ enable-gpios:
maxItems: 1
description: |
GPIO attached to the chip's enable pin
+ label: true
+
pwr-sel:
$ref: /schemas/types.yaml#/definitions/uint8
description: |
@@ -65,9 +67,50 @@ properties:
const: 0
patternProperties:
- "(^led@[0-9a-f]$|led)":
+ '^multi-led@[0-8]$':
+ type: object
+ $ref: leds-class-multicolor.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ reg:
+ maximum: 8
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+ patternProperties:
+ "^led@[0-8]$":
+ type: object
+ $ref: common.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ led-cur:
+ $ref: /schemas/types.yaml#/definitions/uint8
+ description: |
+ Current setting at each LED channel (mA x10, 0 if LED is not connected)
+ minimum: 0
+ maximum: 255
+
+ max-cur:
+ $ref: /schemas/types.yaml#/definitions/uint8
+ description: Maximun current at each LED channel.
+
+ reg:
+ maximum: 8
+
+ required:
+ - reg
+
+ "^led@[0-8]$":
type: object
$ref: common.yaml#
+ unevaluatedProperties: false
+
properties:
led-cur:
$ref: /schemas/types.yaml#/definitions/uint8
diff --git a/Documentation/devicetree/bindings/leds/leds-max77650.yaml b/Documentation/devicetree/bindings/leds/leds-max77650.yaml
index c6f96cabd4d1..fdb08f44a45d 100644
--- a/Documentation/devicetree/bindings/leds/leds-max77650.yaml
+++ b/Documentation/devicetree/bindings/leds/leds-max77650.yaml
@@ -30,9 +30,8 @@ properties:
patternProperties:
"^led@[0-2]$":
- type: object
- description: |
- Properties for a single LED.
+ $ref: common.yaml#
+ unevaluatedProperties: false
properties:
reg:
@@ -41,10 +40,6 @@ patternProperties:
minimum: 0
maximum: 2
- label: true
-
- linux,default-trigger: true
-
required:
- compatible
- "#address-cells"
diff --git a/Documentation/devicetree/bindings/leds/leds-mt6360.yaml b/Documentation/devicetree/bindings/leds/leds-mt6360.yaml
index 69e579226d9b..d84e28e616d7 100644
--- a/Documentation/devicetree/bindings/leds/leds-mt6360.yaml
+++ b/Documentation/devicetree/bindings/leds/leds-mt6360.yaml
@@ -26,11 +26,10 @@ properties:
const: 0
patternProperties:
- "^(multi-)?led@[0-5]$":
+ "^multi-led@[0-5]$":
type: object
- $ref: common.yaml#
- description:
- Properties for a single LED.
+ $ref: leds-class-multicolor.yaml#
+ unevaluatedProperties: false
properties:
reg:
@@ -43,6 +42,42 @@ patternProperties:
- 4 # LED output FLASH1
- 5 # LED output FLASH2
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+ patternProperties:
+ "^led@[0-2]$":
+ type: object
+ $ref: common.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ reg:
+ enum: [0, 1, 2]
+
+ required:
+ - reg
+ - color
+
+ required:
+ - reg
+ - "#address-cells"
+ - "#size-cells"
+
+ "^led@[0-5]$":
+ type: object
+ $ref: common.yaml#
+ unevaluatedProperties: false
+ description:
+ Properties for a single LED.
+
+ properties:
+ reg:
+ enum: [0, 1, 2, 3, 4, 5]
+
required:
- compatible
- "#address-cells"
diff --git a/Documentation/devicetree/bindings/leds/leds-pwm.yaml b/Documentation/devicetree/bindings/leds/leds-pwm.yaml
index fe4d5fd25913..7de6da58be3c 100644
--- a/Documentation/devicetree/bindings/leds/leds-pwm.yaml
+++ b/Documentation/devicetree/bindings/leds/leds-pwm.yaml
@@ -20,8 +20,8 @@ properties:
patternProperties:
"^led(-[0-9a-f]+)?$":
type: object
-
$ref: common.yaml#
+ unevaluatedProperties: false
properties:
pwms:
diff --git a/Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml b/Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml
index 497db289169d..1df837798249 100644
--- a/Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml
+++ b/Documentation/devicetree/bindings/leds/leds-qcom-lpg.yaml
@@ -72,14 +72,24 @@ properties:
"^led@[0-9a-f]$":
type: object
$ref: common.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ reg:
+ maxItems: 1
+
+ required:
+ - reg
patternProperties:
"^led@[0-9a-f]$":
type: object
$ref: common.yaml#
+ unevaluatedProperties: false
properties:
- reg: true
+ reg:
+ maxItems: 1
required:
- reg
diff --git a/Documentation/devicetree/bindings/leds/leds-rt4505.yaml b/Documentation/devicetree/bindings/leds/leds-rt4505.yaml
index 5b0c74aa6723..cb71fec173c1 100644
--- a/Documentation/devicetree/bindings/leds/leds-rt4505.yaml
+++ b/Documentation/devicetree/bindings/leds/leds-rt4505.yaml
@@ -27,6 +27,7 @@ properties:
led:
type: object
$ref: common.yaml#
+ unevaluatedProperties: false
required:
- compatible
diff --git a/Documentation/devicetree/bindings/leds/leds-sgm3140.yaml b/Documentation/devicetree/bindings/leds/leds-sgm3140.yaml
index f68259619488..4d2ffe5fcfc7 100644
--- a/Documentation/devicetree/bindings/leds/leds-sgm3140.yaml
+++ b/Documentation/devicetree/bindings/leds/leds-sgm3140.yaml
@@ -18,7 +18,9 @@ description: |
properties:
compatible:
- const: sgmicro,sgm3140
+ enum:
+ - ocs,ocp8110
+ - sgmicro,sgm3140
enable-gpios:
maxItems: 1
@@ -34,6 +36,7 @@ properties:
led:
type: object
$ref: common.yaml#
+ unevaluatedProperties: false
required:
- compatible
diff --git a/Documentation/devicetree/bindings/leds/rohm,bd71828-leds.yaml b/Documentation/devicetree/bindings/leds/rohm,bd71828-leds.yaml
index 86a37c92b834..ca92cea56a6f 100644
--- a/Documentation/devicetree/bindings/leds/rohm,bd71828-leds.yaml
+++ b/Documentation/devicetree/bindings/leds/rohm,bd71828-leds.yaml
@@ -26,26 +26,16 @@ properties:
patternProperties:
"^led-[1-2]$":
- type: object
- description:
- Properties for a single LED.
+ $ref: common.yaml#
+ unevaluatedProperties: false
+
properties:
- #allOf:
- #- $ref: "common.yaml#"
rohm,led-compatible:
description: LED identification string
$ref: "/schemas/types.yaml#/definitions/string"
enum:
- bd71828-ambled
- bd71828-grnled
- function:
- description:
- Purpose of LED as defined in dt-bindings/leds/common.h
- $ref: "/schemas/types.yaml#/definitions/string"
- color:
- description:
- LED colour as defined in dt-bindings/leds/common.h
- $ref: "/schemas/types.yaml#/definitions/uint32"
required:
- compatible
diff --git a/Documentation/devicetree/bindings/leds/ti,tca6507.yaml b/Documentation/devicetree/bindings/leds/ti,tca6507.yaml
index 32c600387895..9ce5c0f16e17 100644
--- a/Documentation/devicetree/bindings/leds/ti,tca6507.yaml
+++ b/Documentation/devicetree/bindings/leds/ti,tca6507.yaml
@@ -38,8 +38,8 @@ properties:
patternProperties:
"^led@[0-6]$":
type: object
-
$ref: common.yaml#
+ unevaluatedProperties: false
properties:
reg:
diff --git a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml
index 704033e21ee8..53945c61325c 100644
--- a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml
+++ b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml
@@ -21,6 +21,7 @@ properties:
- const: allwinner,sun6i-a31-ir
- items:
- enum:
+ - allwinner,suniv-f1c100s-ir
- allwinner,sun8i-a83t-ir
- allwinner,sun8i-r40-ir
- allwinner,sun50i-a64-ir
diff --git a/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-csi.yaml b/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-csi.yaml
index f1ccca35a790..b3d6db922693 100644
--- a/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-csi.yaml
+++ b/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-csi.yaml
@@ -73,6 +73,10 @@ properties:
$ref: /schemas/graph.yaml#/properties/port
description: MIPI CSI-2 bridge input port
+ port@2:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: Internal output port to the ISP
+
anyOf:
- required:
- port@0
diff --git a/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-isp.yaml b/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-isp.yaml
new file mode 100644
index 000000000000..6bda4f2b94c2
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/allwinner,sun6i-a31-isp.yaml
@@ -0,0 +1,101 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/allwinner,sun6i-a31-isp.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allwinner A31 Image Signal Processor Driver (ISP) Device Tree Bindings
+
+maintainers:
+ - Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+
+properties:
+ compatible:
+ enum:
+ - allwinner,sun6i-a31-isp
+ - allwinner,sun8i-v3s-isp
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: Bus Clock
+ - description: Module Clock
+ - description: DRAM Clock
+
+ clock-names:
+ items:
+ - const: bus
+ - const: mod
+ - const: ram
+
+ resets:
+ maxItems: 1
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: CSI0 input port
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: CSI1 input port
+
+ if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - allwinner,sun8i-v3s-isp
+ then:
+ required:
+ - port@0
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+ - resets
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/sun8i-v3s-ccu.h>
+ #include <dt-bindings/reset/sun8i-v3s-ccu.h>
+
+ isp: isp@1cb8000 {
+ compatible = "allwinner,sun8i-v3s-isp";
+ reg = <0x01cb8000 0x1000>;
+ interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_CSI>,
+ <&ccu CLK_CSI1_SCLK>,
+ <&ccu CLK_DRAM_CSI>;
+ clock-names = "bus", "mod", "ram";
+ resets = <&ccu RST_BUS_CSI>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ isp_in_csi0: endpoint {
+ remote-endpoint = <&csi0_out_isp>;
+ };
+ };
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/media/atmel,isc.yaml b/Documentation/devicetree/bindings/media/atmel,isc.yaml
index cd6d7af0c768..dc8aba698d78 100644
--- a/Documentation/devicetree/bindings/media/atmel,isc.yaml
+++ b/Documentation/devicetree/bindings/media/atmel,isc.yaml
@@ -45,7 +45,7 @@ properties:
port:
$ref: /schemas/graph.yaml#/$defs/port-base
- unevaluatedProperties: false
+ additionalProperties: false
description:
Input port node, single endpoint describing the input pad.
@@ -77,8 +77,6 @@ properties:
additionalProperties: false
- additionalProperties: false
-
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/media/i2c/imx290.txt b/Documentation/devicetree/bindings/media/i2c/imx290.txt
deleted file mode 100644
index a3cc21410f7c..000000000000
--- a/Documentation/devicetree/bindings/media/i2c/imx290.txt
+++ /dev/null
@@ -1,57 +0,0 @@
-* Sony IMX290 1/2.8-Inch CMOS Image Sensor
-
-The Sony IMX290 is a 1/2.8-Inch CMOS Solid-state image sensor with
-Square Pixel for Color Cameras. It is programmable through I2C and 4-wire
-interfaces. The sensor output is available via CMOS logic parallel SDR output,
-Low voltage LVDS DDR output and CSI-2 serial data output. The CSI-2 bus is the
-default. No bindings have been defined for the other busses.
-
-Required Properties:
-- compatible: Should be "sony,imx290"
-- reg: I2C bus address of the device
-- clocks: Reference to the xclk clock.
-- clock-names: Should be "xclk".
-- clock-frequency: Frequency of the xclk clock in Hz.
-- vdddo-supply: Sensor digital IO regulator.
-- vdda-supply: Sensor analog regulator.
-- vddd-supply: Sensor digital core regulator.
-
-Optional Properties:
-- reset-gpios: Sensor reset GPIO
-
-The imx290 device node should contain one 'port' child node with
-an 'endpoint' subnode. For further reading on port node refer to
-Documentation/devicetree/bindings/media/video-interfaces.txt.
-
-Required Properties on endpoint:
-- data-lanes: check ../video-interfaces.txt
-- link-frequencies: check ../video-interfaces.txt
-- remote-endpoint: check ../video-interfaces.txt
-
-Example:
- &i2c1 {
- ...
- imx290: camera-sensor@1a {
- compatible = "sony,imx290";
- reg = <0x1a>;
-
- reset-gpios = <&msmgpio 35 GPIO_ACTIVE_LOW>;
- pinctrl-names = "default";
- pinctrl-0 = <&camera_rear_default>;
-
- clocks = <&gcc GCC_CAMSS_MCLK0_CLK>;
- clock-names = "xclk";
- clock-frequency = <37125000>;
-
- vdddo-supply = <&camera_vdddo_1v8>;
- vdda-supply = <&camera_vdda_2v8>;
- vddd-supply = <&camera_vddd_1v5>;
-
- port {
- imx290_ep: endpoint {
- data-lanes = <1 2 3 4>;
- link-frequencies = /bits/ 64 <445500000>;
- remote-endpoint = <&csiphy0_ep>;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml b/Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml
index 39395ea8c318..edde4201116f 100644
--- a/Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml
@@ -104,6 +104,7 @@ additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/media/video-interfaces.h>
i2c2 {
#address-cells = <1>;
@@ -124,7 +125,7 @@ examples:
remote-endpoint = <&csi2a_ep>;
link-frequencies = /bits/ 64 <199200000 210000000
499200000>;
- bus-type = <4>;
+ bus-type = <MEDIA_BUS_TYPE_CSI2_DPHY>;
};
};
};
diff --git a/Documentation/devicetree/bindings/media/i2c/ov5645.txt b/Documentation/devicetree/bindings/media/i2c/ov5645.txt
deleted file mode 100644
index 72ad992f77be..000000000000
--- a/Documentation/devicetree/bindings/media/i2c/ov5645.txt
+++ /dev/null
@@ -1,54 +0,0 @@
-* Omnivision 1/4-Inch 5Mp CMOS Digital Image Sensor
-
-The Omnivision OV5645 is a 1/4-Inch CMOS active pixel digital image sensor with
-an active array size of 2592H x 1944V. It is programmable through a serial I2C
-interface.
-
-Required Properties:
-- compatible: Value should be "ovti,ov5645".
-- clocks: Reference to the xclk clock.
-- clock-names: Should be "xclk".
-- clock-frequency: Frequency of the xclk clock.
-- enable-gpios: Chip enable GPIO. Polarity is GPIO_ACTIVE_HIGH. This corresponds
- to the hardware pin PWDNB which is physically active low.
-- reset-gpios: Chip reset GPIO. Polarity is GPIO_ACTIVE_LOW. This corresponds to
- the hardware pin RESETB.
-- vdddo-supply: Chip digital IO regulator.
-- vdda-supply: Chip analog regulator.
-- vddd-supply: Chip digital core regulator.
-
-The device node must contain one 'port' child node for its digital output
-video port, in accordance with the video interface bindings defined in
-Documentation/devicetree/bindings/media/video-interfaces.txt.
-
-Example:
-
- &i2c1 {
- ...
-
- ov5645: ov5645@3c {
- compatible = "ovti,ov5645";
- reg = <0x3c>;
-
- enable-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
- reset-gpios = <&gpio5 20 GPIO_ACTIVE_LOW>;
- pinctrl-names = "default";
- pinctrl-0 = <&camera_rear_default>;
-
- clocks = <&clks 200>;
- clock-names = "xclk";
- clock-frequency = <24000000>;
-
- vdddo-supply = <&camera_dovdd_1v8>;
- vdda-supply = <&camera_avdd_2v8>;
- vddd-supply = <&camera_dvdd_1v2>;
-
- port {
- ov5645_ep: endpoint {
- clock-lanes = <1>;
- data-lanes = <0 2>;
- remote-endpoint = <&csi0_ep>;
- };
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov4689.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov4689.yaml
new file mode 100644
index 000000000000..50579c947f3c
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov4689.yaml
@@ -0,0 +1,134 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/ovti,ov4689.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Omnivision OV4689 CMOS
+
+maintainers:
+ - Mikhail Rudenko <mike.rudenko@gmail.com>
+
+description: |
+ The Omnivision OV4689 is a high performance, 1/3-inch, 4 megapixel
+ image sensor. Ihis chip supports high frame rate speeds up to 90 fps
+ at 2688x1520 resolution. It is programmable through an I2C
+ interface, and sensor output is sent via 1/2/4 lane MIPI CSI-2
+ connection.
+
+allOf:
+ - $ref: /schemas/media/video-interface-devices.yaml#
+
+properties:
+ compatible:
+ const: ovti,ov4689
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ description:
+ External clock (XVCLK) for the sensor, 6-64 MHz
+ maxItems: 1
+
+ dovdd-supply:
+ description:
+ Digital I/O voltage supply, 1.7-3.0 V
+
+ avdd-supply:
+ description:
+ Analog voltage supply, 2.6-3.0 V
+
+ dvdd-supply:
+ description:
+ Digital core voltage supply, 1.1-1.3 V
+
+ powerdown-gpios:
+ description:
+ GPIO connected to the powerdown pin (active low)
+
+ reset-gpios:
+ maxItems: 1
+ description:
+ GPIO connected to the reset pin (active low)
+
+ orientation: true
+
+ rotation: true
+
+ port:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ additionalProperties: false
+ description:
+ Output port node, single endpoint describing the CSI-2 transmitter
+
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ oneOf:
+ - items:
+ - const: 1
+ - const: 2
+ - const: 3
+ - const: 4
+ - items:
+ - const: 1
+ - const: 2
+ - items:
+ - const: 1
+ link-frequencies: true
+
+ required:
+ - data-lanes
+ - link-frequencies
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - dovdd-supply
+ - avdd-supply
+ - dvdd-supply
+ - port
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ov4689: camera@36 {
+ compatible = "ovti,ov4689";
+ reg = <0x36>;
+
+ clocks = <&ov4689_clk>;
+
+ avdd-supply = <&ov4689_avdd>;
+ dovdd-supply = <&ov4689_dovdd>;
+ dvdd-supply = <&ov4689_dvdd>;
+
+ powerdown-gpios = <&pio 107 GPIO_ACTIVE_LOW>;
+ reset-gpios = <&pio 109 GPIO_ACTIVE_LOW>;
+
+ orientation = <2>;
+ rotation = <0>;
+
+ port {
+ wcam_out: endpoint {
+ remote-endpoint = <&mipi_in_wcam>;
+ data-lanes = <1 2 3 4>;
+ link-frequencies = /bits/ 64 <504000000>;
+ };
+ };
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov5645.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov5645.yaml
new file mode 100644
index 000000000000..52c6281a6684
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov5645.yaml
@@ -0,0 +1,104 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/ovti,ov5645.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: OmniVision OV5645 Image Sensor Device Tree Bindings
+
+maintainers:
+ - Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+
+properties:
+ compatible:
+ const: ovti,ov5645
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ description: XCLK Input Clock
+
+ clock-frequency:
+ description: Frequency of the xclk clock in Hz.
+
+ vdda-supply:
+ description: Analog voltage supply, 2.8 volts
+
+ vddd-supply:
+ description: Digital core voltage supply, 1.5 volts
+
+ vdddo-supply:
+ description: Digital I/O voltage supply, 1.8 volts
+
+ enable-gpios:
+ maxItems: 1
+ description:
+ Reference to the GPIO connected to the PWDNB pin, if any.
+
+ reset-gpios:
+ maxItems: 1
+ description:
+ Reference to the GPIO connected to the RESETB pin, if any.
+
+ port:
+ description: Digital Output Port
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ additionalProperties: false
+
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ minItems: 1
+ maxItems: 2
+ items:
+ enum: [1, 2]
+
+ required:
+ - data-lanes
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - vdddo-supply
+ - vdda-supply
+ - vddd-supply
+ - port
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ camera@3c {
+ compatible = "ovti,ov5645";
+ reg = <0x3c>;
+ clocks = <&clks 1>;
+ clock-frequency = <24000000>;
+ vdddo-supply = <&ov5645_vdddo_1v8>;
+ vdda-supply = <&ov5645_vdda_2v8>;
+ vddd-supply = <&ov5645_vddd_1v5>;
+ enable-gpios = <&gpio1 19 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio1 20 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ov5645>;
+
+ port {
+ ov5645_ep: endpoint {
+ remote-endpoint = <&csi0_ep>;
+ data-lanes = <1 2>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov772x.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov772x.yaml
index 44529425ce3a..161e6d598e1c 100644
--- a/Documentation/devicetree/bindings/media/i2c/ovti,ov772x.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov772x.yaml
@@ -105,6 +105,7 @@ additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/media/video-interfaces.h>
i2c0 {
#address-cells = <1>;
@@ -118,7 +119,7 @@ examples:
port {
ov772x_0: endpoint {
- bus-type = <5>;
+ bus-type = <MEDIA_BUS_TYPE_PARALLEL>;
vsync-active = <0>;
hsync-active = <0>;
pclk-sample = <0>;
diff --git a/Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml b/Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml
index bf115ab9d926..0c4654e70d46 100644
--- a/Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/ovti,ov9282.yaml
@@ -16,10 +16,13 @@ description:
sensor with an active array size of 1296H x 816V. It is programmable through
I2C interface. The I2C client address is fixed to 0x60/0x70 as per sensor data
sheet. Image data is sent through MIPI CSI-2.
+ OV9281 has a different lens chief ray angle.
properties:
compatible:
- const: ovti,ov9282
+ enum:
+ - ovti,ov9281
+ - ovti,ov9282
reg:
description: I2C address
maxItems: 1
@@ -36,6 +39,15 @@ properties:
description: Reference to the GPIO connected to the XCLR pin, if any.
maxItems: 1
+ avdd-supply:
+ description: Analog voltage supply, 2.8 volts
+
+ dvdd-supply:
+ description: Digital core voltage supply, 1.2 volts
+
+ dovdd-supply:
+ description: Digital I/O voltage supply, 1.8 volts
+
port:
additionalProperties: false
$ref: /schemas/graph.yaml#/$defs/port-base
diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx290.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx290.yaml
new file mode 100644
index 000000000000..21377daae026
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/sony,imx290.yaml
@@ -0,0 +1,129 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/sony,imx290.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Sony IMX290 1/2.8-Inch CMOS Image Sensor
+
+maintainers:
+ - Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+ - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+
+description: |-
+ The Sony IMX290 is a 1/2.8-Inch CMOS Solid-state image sensor with Square
+ Pixel for Color Cameras. It is programmable through I2C and 4-wire
+ interfaces. The sensor output is available via CMOS logic parallel SDR
+ output, Low voltage LVDS DDR output and CSI-2 serial data output. The CSI-2
+ bus is the default. No bindings have been defined for the other busses.
+
+properties:
+ compatible:
+ enum:
+ - sony,imx290
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ description: Input clock (37.125 MHz or 74.25 MHz)
+ items:
+ - const: xclk
+
+ clock-frequency:
+ description: Frequency of the xclk clock in Hz
+
+ vdda-supply:
+ description: Analog power supply (2.9V)
+
+ vddd-supply:
+ description: Digital core power supply (1.2V)
+
+ vdddo-supply:
+ description: Digital I/O power supply (1.8V)
+
+ reset-gpios:
+ description: Sensor reset (XCLR) GPIO
+ maxItems: 1
+
+ port:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ description: |
+ Video output port
+
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ anyOf:
+ - items:
+ - const: 1
+ - const: 2
+ - items:
+ - const: 1
+ - const: 2
+ - const: 3
+ - const: 4
+
+ link-frequencies: true
+
+ required:
+ - data-lanes
+ - link-frequencies
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - clock-frequency
+ - vdda-supply
+ - vddd-supply
+ - vdddo-supply
+ - port
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ imx290: camera-sensor@1a {
+ compatible = "sony,imx290";
+ reg = <0x1a>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&camera_rear_default>;
+
+ clocks = <&gcc 90>;
+ clock-names = "xclk";
+ clock-frequency = <37125000>;
+
+ vdddo-supply = <&camera_vdddo_1v8>;
+ vdda-supply = <&camera_vdda_2v8>;
+ vddd-supply = <&camera_vddd_1v5>;
+
+ reset-gpios = <&msmgpio 35 GPIO_ACTIVE_LOW>;
+
+ port {
+ imx290_ep: endpoint {
+ data-lanes = <1 2 3 4>;
+ link-frequencies = /bits/ 64 <445500000>;
+ remote-endpoint = <&csiphy0_ep>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml b/Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
index 26d1807d0bb6..60dc25ff2b9e 100644
--- a/Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
+++ b/Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
@@ -19,7 +19,9 @@ description:
properties:
compatible:
- const: sony,imx412
+ enum:
+ - sony,imx412
+ - sony,imx577
reg:
description: I2C address
maxItems: 1
diff --git a/Documentation/devicetree/bindings/media/i2c/st,st-mipid02.txt b/Documentation/devicetree/bindings/media/i2c/st,st-mipid02.txt
deleted file mode 100644
index 7976e6c40a80..000000000000
--- a/Documentation/devicetree/bindings/media/i2c/st,st-mipid02.txt
+++ /dev/null
@@ -1,82 +0,0 @@
-STMicroelectronics MIPID02 CSI-2 to PARALLEL bridge
-
-MIPID02 has two CSI-2 input ports, only one of those ports can be active at a
-time. Active port input stream will be de-serialized and its content outputted
-through PARALLEL output port.
-CSI-2 first input port is a dual lane 800Mbps per lane whereas CSI-2 second
-input port is a single lane 800Mbps. Both ports support clock and data lane
-polarity swap. First port also supports data lane swap.
-PARALLEL output port has a maximum width of 12 bits.
-Supported formats are RAW6, RAW7, RAW8, RAW10, RAW12, RGB565, RGB888, RGB444,
-YUV420 8-bit, YUV422 8-bit and YUV420 10-bit.
-
-Required Properties:
-- compatible: shall be "st,st-mipid02"
-- clocks: reference to the xclk input clock.
-- clock-names: shall be "xclk".
-- VDDE-supply: sensor digital IO supply. Must be 1.8 volts.
-- VDDIN-supply: sensor internal regulator supply. Must be 1.8 volts.
-
-Optional Properties:
-- reset-gpios: reference to the GPIO connected to the xsdn pin, if any.
- This is an active low signal to the mipid02.
-
-Required subnodes:
- - ports: A ports node with one port child node per device input and output
- port, in accordance with the video interface bindings defined in
- Documentation/devicetree/bindings/media/video-interfaces.txt. The
- port nodes are numbered as follows:
-
- Port Description
- -----------------------------
- 0 CSI-2 first input port
- 1 CSI-2 second input port
- 2 PARALLEL output
-
-Endpoint node required property for CSI-2 connection is:
-- data-lanes: shall be <1> for Port 1. for Port 0 dual-lane operation shall be
-<1 2> or <2 1>. For Port 0 single-lane operation shall be <1> or <2>.
-Endpoint node optional property for CSI-2 connection is:
-- lane-polarities: any lane can be inverted or not.
-
-Endpoint node required property for PARALLEL connection is:
-- bus-width: shall be set to <6>, <7>, <8>, <10> or <12>.
-Endpoint node optional properties for PARALLEL connection are:
-- hsync-active: active state of the HSYNC signal, 0/1 for LOW/HIGH respectively.
-LOW being the default.
-- vsync-active: active state of the VSYNC signal, 0/1 for LOW/HIGH respectively.
-LOW being the default.
-
-Example:
-
-mipid02: csi2rx@14 {
- compatible = "st,st-mipid02";
- reg = <0x14>;
- status = "okay";
- clocks = <&clk_ext_camera_12>;
- clock-names = "xclk";
- VDDE-supply = <&vdd>;
- VDDIN-supply = <&vdd>;
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
-
- ep0: endpoint {
- data-lanes = <1 2>;
- remote-endpoint = <&mipi_csi2_in>;
- };
- };
- port@2 {
- reg = <2>;
-
- ep2: endpoint {
- bus-width = <8>;
- hsync-active = <0>;
- vsync-active = <0>;
- remote-endpoint = <&parallel_out>;
- };
- };
- };
-};
diff --git a/Documentation/devicetree/bindings/media/i2c/st,st-mipid02.yaml b/Documentation/devicetree/bindings/media/i2c/st,st-mipid02.yaml
new file mode 100644
index 000000000000..19a39d753aad
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/st,st-mipid02.yaml
@@ -0,0 +1,176 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/st,st-mipid02.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: STMicroelectronics MIPID02 CSI-2 to PARALLEL bridge
+
+maintainers:
+ - Benjamin Mugnier <benjamin.mugnier@foss.st.com>
+ - Sylvain Petinot <sylvain.petinot@foss.st.com>
+
+description:
+ MIPID02 has two CSI-2 input ports, only one of those ports can be
+ active at a time. Active port input stream will be de-serialized
+ and its content outputted through PARALLEL output port.
+ CSI-2 first input port is a dual lane 800Mbps per lane whereas CSI-2
+ second input port is a single lane 800Mbps. Both ports support clock
+ and data lane polarity swap. First port also supports data lane swap.
+ PARALLEL output port has a maximum width of 12 bits.
+ Supported formats are RAW6, RAW7, RAW8, RAW10, RAW12, RGB565, RGB888,
+ RGB444, YUV420 8-bit, YUV422 8-bit and YUV420 10-bit.
+
+properties:
+ compatible:
+ const: st,st-mipid02
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ const: xclk
+
+ VDDE-supply:
+ description:
+ Sensor digital IO supply. Must be 1.8 volts.
+
+ VDDIN-supply:
+ description:
+ Sensor internal regulator supply. Must be 1.8 volts.
+
+ reset-gpios:
+ description:
+ Reference to the GPIO connected to the xsdn pin, if any.
+ This is an active low signal to the mipid02.
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description: CSI-2 first input port
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ description:
+ Single-lane operation shall be <1> or <2> .
+ Dual-lane operation shall be <1 2> or <2 1> .
+ minItems: 1
+ maxItems: 2
+
+ lane-polarities:
+ description:
+ Any lane can be inverted or not.
+ minItems: 1
+ maxItems: 2
+
+ required:
+ - data-lanes
+
+ port@1:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description: CSI-2 second input port
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ description:
+ Single-lane operation shall be <1> or <2> .
+ maxItems: 1
+
+ lane-polarities:
+ description:
+ Any lane can be inverted or not.
+ maxItems: 1
+
+ required:
+ - data-lanes
+
+ port@2:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description: Output port
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ bus-width:
+ enum: [6, 7, 8, 10, 12]
+
+ required:
+ - bus-width
+
+ anyOf:
+ - required:
+ - port@0
+ - required:
+ - port@1
+
+ required:
+ - port@2
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - VDDE-supply
+ - VDDIN-supply
+ - ports
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ mipid02: csi2rx@14 {
+ compatible = "st,st-mipid02";
+ reg = <0x14>;
+ status = "okay";
+ clocks = <&clk_ext_camera_12>;
+ clock-names = "xclk";
+ VDDE-supply = <&vdd>;
+ VDDIN-supply = <&vdd>;
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+
+ ep0: endpoint {
+ data-lanes = <1 2>;
+ remote-endpoint = <&mipi_csi2_in>;
+ };
+ };
+ port@2 {
+ reg = <2>;
+
+ ep2: endpoint {
+ bus-width = <8>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ remote-endpoint = <&parallel_out>;
+ };
+ };
+ };
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/media/i2c/st,st-vgxy61.yaml b/Documentation/devicetree/bindings/media/i2c/st,st-vgxy61.yaml
new file mode 100644
index 000000000000..6597e1d0e65f
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/st,st-vgxy61.yaml
@@ -0,0 +1,113 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright (c) 2022 STMicroelectronics SA.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/st,st-vgxy61.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: STMicroelectronics VGxy61 HDR Global Shutter Sensor Family Device Tree Bindings
+
+maintainers:
+ - Benjamin Mugnier <benjamin.mugnier@foss.st.com>
+ - Sylvain Petinot <sylvain.petinot@foss.st.com>
+
+description: |-
+ STMicroelectronics VGxy61 family has a CSI-2 output port. CSI-2 output is a
+ quad lanes 800Mbps per lane.
+ Supported formats are RAW8, RAW10, RAW12, RAW14 and RAW16.
+ Following part number are supported
+ - VG5661 and VG6661 are 1.6 Mpx (1464 x 1104) monochrome and color sensors.
+ Maximum frame rate is 75 fps.
+ - VG5761 and VG6761 are 2.3 Mpx (1944 x 1204) monochrome and color sensors.
+ Maximum frame rate is 60 fps.
+
+properties:
+ compatible:
+ const: st,st-vgxy61
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ VCORE-supply:
+ description:
+ Sensor digital core supply. Must be 1.2 volts.
+
+ VDDIO-supply:
+ description:
+ Sensor digital IO supply. Must be 1.8 volts.
+
+ VANA-supply:
+ description:
+ Sensor analog supply. Must be 2.8 volts.
+
+ reset-gpios:
+ description:
+ Reference to the GPIO connected to the reset pin, if any.
+ This is an active low signal to the vgxy61.
+
+ st,strobe-gpios-polarity:
+ description:
+ Invert polarity of illuminator's lights strobe GPIOs.
+ These GPIOs directly drive the illuminator LEDs.
+ type: boolean
+
+ port:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ additionalProperties: false
+
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ description:
+ CSI lanes to use
+ items:
+ - const: 1
+ - const: 2
+ - const: 3
+ - const: 4
+
+ remote-endpoint: true
+
+ required:
+ - data-lanes
+
+required:
+ - compatible
+ - clocks
+ - VCORE-supply
+ - VDDIO-supply
+ - VANA-supply
+ - port
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ vgxy61: csi2tx@10 {
+ compatible = "st,st-vgxy61";
+ reg = <0x10>;
+ clocks = <&clk_ext_camera>;
+ VCORE-supply = <&v1v2>;
+ VDDIO-supply = <&v1v8>;
+ VANA-supply = <&v2v8>;
+ reset-gpios = <&mfxgpio 18 GPIO_ACTIVE_LOW>;
+ port {
+ ep0: endpoint {
+ data-lanes = <1 2 3 4>;
+ remote-endpoint = <&mipi_csi2_out>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/media/i2c/toshiba,tc358746.yaml b/Documentation/devicetree/bindings/media/i2c/toshiba,tc358746.yaml
new file mode 100644
index 000000000000..b8ba85a2416c
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/i2c/toshiba,tc358746.yaml
@@ -0,0 +1,178 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/i2c/toshiba,tc358746.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Toshiba TC358746 Parallel to MIPI CSI2 Bridge
+
+maintainers:
+ - Marco Felsch <kernel@pengutronix.de>
+
+description: |-
+ The Toshiba TC358746 converts a parallel video stream into a MIPI CSI-2
+ stream. The direction can be either parallel-in -> csi-out or csi-in ->
+ parallel-out The chip is programmable trough I2C and SPI but the SPI
+ interface is only supported in parallel-in -> csi-out mode.
+
+ Note that the current device tree bindings only support the
+ parallel-in -> csi-out path.
+
+properties:
+ compatible:
+ const: toshiba,tc358746
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ description:
+ The phandle to the reference clock source. This corresponds to the
+ hardware pin REFCLK.
+ maxItems: 1
+
+ clock-names:
+ const: refclk
+
+ "#clock-cells":
+ description: |
+ The bridge can act as clock provider for the sensor. To enable this
+ support #clock-cells must be specified. Attention if this feature is used
+ then the mclk rate must be at least: (2 * link-frequency) / 8
+ `------------------´ ^
+ internal PLL rate smallest possible
+ mclk-div
+ const: 0
+
+ clock-output-names:
+ description:
+ The clock name of the MCLK output, the default name is tc358746-mclk.
+ maxItems: 1
+
+ vddc-supply:
+ description: Digital core voltage supply, 1.2 volts
+
+ vddio-supply:
+ description: Digital I/O voltage supply, 1.8 volts
+
+ vddmipi-supply:
+ description: MIPI CSI phy voltage supply, 1.2 volts
+
+ reset-gpios:
+ description:
+ The phandle and specifier for the GPIO that controls the chip reset.
+ This corresponds to the hardware pin RESX which is physically active low.
+ maxItems: 1
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ description: Input port
+
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ hsync-active: true
+ vsync-active: true
+ bus-type:
+ enum: [ 5, 6 ]
+
+ required:
+ - hsync-active
+ - vsync-active
+ - bus-type
+
+ port@1:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ description: Output port
+
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ minItems: 1
+ maxItems: 4
+
+ clock-noncontinuous: true
+ link-frequencies: true
+
+ required:
+ - data-lanes
+ - link-frequencies
+
+ required:
+ - port@0
+ - port@1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - vddc-supply
+ - vddio-supply
+ - vddmipi-supply
+ - ports
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ csi-bridge@e {
+ compatible = "toshiba,tc358746";
+ reg = <0xe>;
+
+ clocks = <&refclk>;
+ clock-names = "refclk";
+
+ reset-gpios = <&gpio 2 GPIO_ACTIVE_LOW>;
+
+ vddc-supply = <&v1_2d>;
+ vddio-supply = <&v1_8d>;
+ vddmipi-supply = <&v1_2d>;
+
+ /* sensor mclk provider */
+ #clock-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* Input */
+ port@0 {
+ reg = <0>;
+ tc358746_in: endpoint {
+ remote-endpoint = <&sensor_out>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ bus-type = <5>;
+ };
+ };
+
+ /* Output */
+ port@1 {
+ reg = <1>;
+ tc358746_out: endpoint {
+ remote-endpoint = <&mipi_csi2_in>;
+ data-lanes = <1 2>;
+ clock-noncontinuous;
+ link-frequencies = /bits/ 64 <216000000>;
+ };
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/media/marvell,mmp2-ccic.yaml b/Documentation/devicetree/bindings/media/marvell,mmp2-ccic.yaml
index b39b84c5f012..0e3478551e13 100644
--- a/Documentation/devicetree/bindings/media/marvell,mmp2-ccic.yaml
+++ b/Documentation/devicetree/bindings/media/marvell,mmp2-ccic.yaml
@@ -68,6 +68,7 @@ additionalProperties: false
examples:
- |
#include <dt-bindings/clock/marvell,mmp2.h>
+ #include <dt-bindings/media/video-interfaces.h>
#include <dt-bindings/power/marvell,mmp2.h>
camera@d420a000 {
@@ -83,7 +84,7 @@ examples:
port {
camera0_0: endpoint {
remote-endpoint = <&ov7670_0>;
- bus-type = <5>; /* Parallel */
+ bus-type = <MEDIA_BUS_TYPE_PARALLEL>;
hsync-active = <1>; /* Active high */
vsync-active = <1>; /* Active high */
pclk-sample = <0>; /* Falling */
diff --git a/Documentation/devicetree/bindings/media/mediatek,mt8195-jpegdec.yaml b/Documentation/devicetree/bindings/media/mediatek,mt8195-jpegdec.yaml
new file mode 100644
index 000000000000..71595c013dbb
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/mediatek,mt8195-jpegdec.yaml
@@ -0,0 +1,168 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/mediatek,mt8195-jpegdec.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek JPEG Decoder
+
+maintainers:
+ - kyrie wu <kyrie.wu@mediatek.corp-partner.google.com>
+
+description:
+ MediaTek JPEG Decoder is the JPEG decode hardware present in MediaTek SoCs
+
+properties:
+ compatible:
+ const: mediatek,mt8195-jpgdec
+
+ power-domains:
+ maxItems: 1
+
+ iommus:
+ maxItems: 6
+ description:
+ Points to the respective IOMMU block with master port as argument, see
+ Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml for details.
+ Ports are according to the HW.
+
+ dma-ranges:
+ maxItems: 1
+ description: |
+ Describes the physical address space of IOMMU maps to memory.
+
+ "#address-cells":
+ const: 2
+
+ "#size-cells":
+ const: 2
+
+ ranges: true
+
+# Required child node:
+patternProperties:
+ "^jpgdec@[0-9a-f]+$":
+ type: object
+ description:
+ The jpeg decoder hardware device node which should be added as subnodes to
+ the main jpeg node.
+
+ properties:
+ compatible:
+ const: mediatek,mt8195-jpgdec-hw
+
+ reg:
+ maxItems: 1
+
+ iommus:
+ minItems: 1
+ maxItems: 32
+ description:
+ List of the hardware port in respective IOMMU block for current Socs.
+ Refer to bindings/iommu/mediatek,iommu.yaml.
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ items:
+ - const: jpgdec
+
+ power-domains:
+ maxItems: 1
+
+ required:
+ - compatible
+ - reg
+ - iommus
+ - interrupts
+ - clocks
+ - clock-names
+ - power-domains
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - power-domains
+ - iommus
+ - dma-ranges
+ - ranges
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/memory/mt8195-memory-port.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/clock/mt8195-clk.h>
+ #include <dt-bindings/power/mt8195-power.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ jpgdec-master {
+ compatible = "mediatek,mt8195-jpgdec";
+ power-domains = <&spm MT8195_POWER_DOMAIN_VDEC1>;
+ iommus = <&iommu_vpp M4U_PORT_L19_JPGDEC_WDMA0>,
+ <&iommu_vpp M4U_PORT_L19_JPGDEC_BSDMA0>,
+ <&iommu_vpp M4U_PORT_L19_JPGDEC_WDMA1>,
+ <&iommu_vpp M4U_PORT_L19_JPGDEC_BSDMA1>,
+ <&iommu_vpp M4U_PORT_L19_JPGDEC_BUFF_OFFSET1>,
+ <&iommu_vpp M4U_PORT_L19_JPGDEC_BUFF_OFFSET0>;
+ dma-ranges = <0x1 0x0 0x0 0x40000000 0x0 0xfff00000>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ jpgdec@1a040000 {
+ compatible = "mediatek,mt8195-jpgdec-hw";
+ reg = <0 0x1a040000 0 0x10000>;/* JPGDEC_C0 */
+ iommus = <&iommu_vdo M4U_PORT_L19_JPGDEC_WDMA0>,
+ <&iommu_vdo M4U_PORT_L19_JPGDEC_BSDMA0>,
+ <&iommu_vdo M4U_PORT_L19_JPGDEC_WDMA1>,
+ <&iommu_vdo M4U_PORT_L19_JPGDEC_BSDMA1>,
+ <&iommu_vdo M4U_PORT_L19_JPGDEC_BUFF_OFFSET1>,
+ <&iommu_vdo M4U_PORT_L19_JPGDEC_BUFF_OFFSET0>;
+ interrupts = <GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&vencsys CLK_VENC_JPGDEC>;
+ clock-names = "jpgdec";
+ power-domains = <&spm MT8195_POWER_DOMAIN_VDEC0>;
+ };
+
+ jpgdec@1a050000 {
+ compatible = "mediatek,mt8195-jpgdec-hw";
+ reg = <0 0x1a050000 0 0x10000>;/* JPGDEC_C1 */
+ iommus = <&iommu_vdo M4U_PORT_L19_JPGDEC_WDMA0>,
+ <&iommu_vdo M4U_PORT_L19_JPGDEC_BSDMA0>,
+ <&iommu_vdo M4U_PORT_L19_JPGDEC_WDMA1>,
+ <&iommu_vdo M4U_PORT_L19_JPGDEC_BSDMA1>,
+ <&iommu_vdo M4U_PORT_L19_JPGDEC_BUFF_OFFSET1>,
+ <&iommu_vdo M4U_PORT_L19_JPGDEC_BUFF_OFFSET0>;
+ interrupts = <GIC_SPI 344 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&vencsys CLK_VENC_JPGDEC_C1>;
+ clock-names = "jpgdec";
+ power-domains = <&spm MT8195_POWER_DOMAIN_VDEC1>;
+ };
+
+ jpgdec@1b040000 {
+ compatible = "mediatek,mt8195-jpgdec-hw";
+ reg = <0 0x1b040000 0 0x10000>;/* JPGDEC_C2 */
+ iommus = <&iommu_vpp M4U_PORT_L20_JPGDEC_WDMA0>,
+ <&iommu_vpp M4U_PORT_L20_JPGDEC_BSDMA0>,
+ <&iommu_vpp M4U_PORT_L20_JPGDEC_WDMA1>,
+ <&iommu_vpp M4U_PORT_L20_JPGDEC_BSDMA1>,
+ <&iommu_vpp M4U_PORT_L20_JPGDEC_BUFF_OFFSET1>,
+ <&iommu_vpp M4U_PORT_L20_JPGDEC_BUFF_OFFSET0>;
+ interrupts = <GIC_SPI 348 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&vencsys_core1 CLK_VENC_CORE1_JPGDEC>;
+ clock-names = "jpgdec";
+ power-domains = <&spm MT8195_POWER_DOMAIN_VDEC2>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/media/mediatek,mt8195-jpegenc.yaml b/Documentation/devicetree/bindings/media/mediatek,mt8195-jpegenc.yaml
new file mode 100644
index 000000000000..95990539f7c0
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/mediatek,mt8195-jpegenc.yaml
@@ -0,0 +1,147 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/mediatek,mt8195-jpegenc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek JPEG Encoder
+
+maintainers:
+ - kyrie wu <kyrie.wu@mediatek.corp-partner.google.com>
+
+description:
+ MediaTek JPEG Encoder is the JPEG encode hardware present in MediaTek SoCs
+
+properties:
+ compatible:
+ const: mediatek,mt8195-jpgenc
+
+ power-domains:
+ maxItems: 1
+
+ iommus:
+ maxItems: 4
+ description:
+ Points to the respective IOMMU block with master port as argument, see
+ Documentation/devicetree/bindings/iommu/mediatek,iommu.yaml for details.
+ Ports are according to the HW.
+
+ dma-ranges:
+ maxItems: 1
+ description: |
+ Describes the physical address space of IOMMU maps to memory.
+
+ "#address-cells":
+ const: 2
+
+ "#size-cells":
+ const: 2
+
+ ranges: true
+
+# Required child node:
+patternProperties:
+ "^jpgenc@[0-9a-f]+$":
+ type: object
+ description:
+ The jpeg encoder hardware device node which should be added as subnodes to
+ the main jpeg node.
+
+ properties:
+ compatible:
+ const: mediatek,mt8195-jpgenc-hw
+
+ reg:
+ maxItems: 1
+
+ iommus:
+ minItems: 1
+ maxItems: 32
+ description:
+ List of the hardware port in respective IOMMU block for current Socs.
+ Refer to bindings/iommu/mediatek,iommu.yaml.
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ items:
+ - const: jpgenc
+
+ power-domains:
+ maxItems: 1
+
+ required:
+ - compatible
+ - reg
+ - iommus
+ - interrupts
+ - clocks
+ - clock-names
+ - power-domains
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - power-domains
+ - iommus
+ - dma-ranges
+ - ranges
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/memory/mt8195-memory-port.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/clock/mt8195-clk.h>
+ #include <dt-bindings/power/mt8195-power.h>
+
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ jpgenc-master {
+ compatible = "mediatek,mt8195-jpgenc";
+ power-domains = <&spm MT8195_POWER_DOMAIN_VENC_CORE1>;
+ iommus = <&iommu_vpp M4U_PORT_L20_JPGENC_Y_RDMA>,
+ <&iommu_vpp M4U_PORT_L20_JPGENC_C_RDMA>,
+ <&iommu_vpp M4U_PORT_L20_JPGENC_Q_TABLE>,
+ <&iommu_vpp M4U_PORT_L20_JPGENC_BSDMA>;
+ dma-ranges = <0x1 0x0 0x0 0x40000000 0x0 0xfff00000>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ jpgenc@1a030000 {
+ compatible = "mediatek,mt8195-jpgenc-hw";
+ reg = <0 0x1a030000 0 0x10000>;
+ iommus = <&iommu_vdo M4U_PORT_L19_JPGENC_Y_RDMA>,
+ <&iommu_vdo M4U_PORT_L19_JPGENC_C_RDMA>,
+ <&iommu_vdo M4U_PORT_L19_JPGENC_Q_TABLE>,
+ <&iommu_vdo M4U_PORT_L19_JPGENC_BSDMA>;
+ interrupts = <GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&vencsys CLK_VENC_JPGENC>;
+ clock-names = "jpgenc";
+ power-domains = <&spm MT8195_POWER_DOMAIN_VENC>;
+ };
+
+ jpgenc@1b030000 {
+ compatible = "mediatek,mt8195-jpgenc-hw";
+ reg = <0 0x1b030000 0 0x10000>;
+ iommus = <&iommu_vpp M4U_PORT_L20_JPGENC_Y_RDMA>,
+ <&iommu_vpp M4U_PORT_L20_JPGENC_C_RDMA>,
+ <&iommu_vpp M4U_PORT_L20_JPGENC_Q_TABLE>,
+ <&iommu_vpp M4U_PORT_L20_JPGENC_BSDMA>;
+ interrupts = <GIC_SPI 347 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&vencsys_core1 CLK_VENC_CORE1_JPGENC>;
+ clock-names = "jpgenc";
+ power-domains = <&spm MT8195_POWER_DOMAIN_VENC_CORE1>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder.yaml b/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder.yaml
index 32aee09aea33..0f2ea8d9a10c 100644
--- a/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder.yaml
+++ b/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder.yaml
@@ -67,6 +67,12 @@ properties:
power-domains:
maxItems: 1
+ "#address-cells":
+ const: 2
+
+ "#size-cells":
+ const: 2
+
required:
- compatible
- reg
@@ -84,7 +90,9 @@ allOf:
contains:
enum:
- mediatek,mt8183-vcodec-enc
+ - mediatek,mt8188-vcodec-enc
- mediatek,mt8192-vcodec-enc
+ - mediatek,mt8195-vcodec-enc
then:
required:
@@ -107,7 +115,9 @@ allOf:
compatible:
enum:
- mediatek,mt8173-vcodec-enc
+ - mediatek,mt8188-vcodec-enc
- mediatek,mt8192-vcodec-enc
+ - mediatek,mt8195-vcodec-enc
then:
properties:
@@ -118,7 +128,7 @@ allOf:
clock-names:
items:
- const: venc_sel
- else: # for vp8 hw decoder
+ else: # for vp8 hw encoder
properties:
clock:
items:
diff --git a/Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.yaml b/Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.yaml
index 5e8d001492cc..cfabf360f278 100644
--- a/Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.yaml
+++ b/Documentation/devicetree/bindings/media/mediatek-jpeg-decoder.yaml
@@ -22,6 +22,7 @@ properties:
- items:
- enum:
- mediatek,mt7623-jpgdec
+ - mediatek,mt8188-jpgdec
- const: mediatek,mt2701-jpgdec
reg:
diff --git a/Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.yaml b/Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.yaml
index fc727300b493..c8412e8ab353 100644
--- a/Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.yaml
+++ b/Documentation/devicetree/bindings/media/mediatek-jpeg-encoder.yaml
@@ -19,6 +19,7 @@ properties:
- mediatek,mt2701-jpgenc
- mediatek,mt8183-jpgenc
- mediatek,mt8186-jpgenc
+ - mediatek,mt8188-jpgenc
- const: mediatek,mtk-jpgenc
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/media/microchip,xisc.yaml b/Documentation/devicetree/bindings/media/microchip,xisc.yaml
index 8b37fccab5e2..25f5f79d40ce 100644
--- a/Documentation/devicetree/bindings/media/microchip,xisc.yaml
+++ b/Documentation/devicetree/bindings/media/microchip,xisc.yaml
@@ -106,6 +106,7 @@ examples:
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/at91.h>
#include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/media/video-interfaces.h>
xisc: xisc@e1408000 {
compatible = "microchip,sama7g5-isc";
@@ -118,7 +119,7 @@ examples:
port {
xisc_in: endpoint {
- bus-type = <5>; /* Parallel */
+ bus-type = <MEDIA_BUS_TYPE_PARALLEL>;
remote-endpoint = <&csi2dc_out>;
hsync-active = <1>;
vsync-active = <1>;
diff --git a/Documentation/devicetree/bindings/media/renesas,rzg2l-cru.yaml b/Documentation/devicetree/bindings/media/renesas,rzg2l-cru.yaml
new file mode 100644
index 000000000000..7dde7967c886
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/renesas,rzg2l-cru.yaml
@@ -0,0 +1,157 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright (C) 2022 Renesas Electronics Corp.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/renesas,rzg2l-cru.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RZ/G2L (and alike SoC's) Camera Data Receiving Unit (CRU) Image processing
+
+maintainers:
+ - Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+
+description:
+ The CRU image processing module is a data conversion module equipped with pixel
+ color space conversion, LUT, pixel format conversion, etc. An MIPI CSI-2 input and
+ parallel (including ITU-R BT.656) input are provided as the image sensor interface.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - renesas,r9a07g044-cru # RZ/G2{L,LC}
+ - renesas,r9a07g054-cru # RZ/V2L
+ - const: renesas,rzg2l-cru
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 3
+
+ interrupt-names:
+ items:
+ - const: image_conv
+ - const: image_conv_err
+ - const: axi_mst_err
+
+ clocks:
+ items:
+ - description: CRU Main clock
+ - description: CRU Register access clock
+ - description: CRU image transfer clock
+
+ clock-names:
+ items:
+ - const: video
+ - const: apb
+ - const: axi
+
+ power-domains:
+ maxItems: 1
+
+ resets:
+ items:
+ - description: CRU_PRESETN reset terminal
+ - description: CRU_ARESETN reset terminal
+
+ reset-names:
+ items:
+ - const: presetn
+ - const: aresetn
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description:
+ Input port node, single endpoint describing a parallel input source.
+
+ properties:
+ endpoint:
+ $ref: video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ hsync-active: true
+ vsync-active: true
+ bus-width: true
+ data-shift: true
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ Input port node, describing the Image Processing module connected to the
+ CSI-2 receiver.
+
+ required:
+ - port@0
+ - port@1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - interrupt-names
+ - clocks
+ - clock-names
+ - resets
+ - reset-names
+ - power-domains
+
+additionalProperties: false
+
+examples:
+ # Device node example with CSI-2
+ - |
+ #include <dt-bindings/clock/r9a07g044-cpg.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ cru: video@10830000 {
+ compatible = "renesas,r9a07g044-cru", "renesas,rzg2l-cru";
+ reg = <0x10830000 0x400>;
+ interrupts = <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "image_conv", "image_conv_err", "axi_mst_err";
+ clocks = <&cpg CPG_MOD R9A07G044_CRU_VCLK>,
+ <&cpg CPG_MOD R9A07G044_CRU_PCLK>,
+ <&cpg CPG_MOD R9A07G044_CRU_ACLK>;
+ clock-names = "video", "apb", "axi";
+ power-domains = <&cpg>;
+ resets = <&cpg R9A07G044_CRU_PRESETN>,
+ <&cpg R9A07G044_CRU_ARESETN>;
+ reset-names = "presetn", "aresetn";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+
+ cru_parallel_in: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&ov5642>;
+ hsync-active = <1>;
+ vsync-active = <1>;
+ };
+ };
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+
+ cru_csi_in: endpoint@0 {
+ reg = <0>;
+ remote-endpoint= <&csi_cru_in>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/media/renesas,rzg2l-csi2.yaml b/Documentation/devicetree/bindings/media/renesas,rzg2l-csi2.yaml
new file mode 100644
index 000000000000..67eea2ac1d22
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/renesas,rzg2l-csi2.yaml
@@ -0,0 +1,149 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright (C) 2022 Renesas Electronics Corp.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/media/renesas,rzg2l-csi2.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RZ/G2L (and alike SoC's) MIPI CSI-2 receiver
+
+maintainers:
+ - Lad Prabhakar <prabhakar.mahadev-lad.rj@bp.renesas.com>
+
+description:
+ The CSI-2 receiver device provides MIPI CSI-2 capabilities for the Renesas RZ/G2L
+ (and alike SoCs). MIPI CSI-2 is part of the CRU block which is used in conjunction
+ with the Image Processing module, which provides the video capture capabilities.
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - renesas,r9a07g044-csi2 # RZ/G2{L,LC}
+ - renesas,r9a07g054-csi2 # RZ/V2L
+ - const: renesas,rzg2l-csi2
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: Internal clock for connecting CRU and MIPI
+ - description: CRU Main clock
+ - description: CRU Register access clock
+
+ clock-names:
+ items:
+ - const: system
+ - const: video
+ - const: apb
+
+ power-domains:
+ maxItems: 1
+
+ resets:
+ items:
+ - description: CRU_PRESETN reset terminal
+ - description: CRU_CMN_RSTB reset terminal
+
+ reset-names:
+ items:
+ - const: presetn
+ - const: cmn-rstb
+
+ ports:
+ $ref: /schemas/graph.yaml#/properties/ports
+
+ properties:
+ port@0:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description:
+ Input port node, single endpoint describing the CSI-2 transmitter.
+
+ properties:
+ endpoint:
+ $ref: video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ data-lanes:
+ minItems: 1
+ maxItems: 4
+ items:
+ maximum: 4
+
+ required:
+ - clock-lanes
+ - data-lanes
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description:
+ Output port node, Image Processing block connected to the CSI-2 receiver.
+
+ required:
+ - port@0
+ - port@1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+ - power-domains
+ - resets
+ - reset-names
+ - ports
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/r9a07g044-cpg.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ csi: csi@10830400 {
+ compatible = "renesas,r9a07g044-csi2", "renesas,rzg2l-csi2";
+ reg = <0x10830400 0xfc00>;
+ interrupts = <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD R9A07G044_CRU_SYSCLK>,
+ <&cpg CPG_MOD R9A07G044_CRU_VCLK>,
+ <&cpg CPG_MOD R9A07G044_CRU_PCLK>;
+ clock-names = "system", "video", "apb";
+ power-domains = <&cpg>;
+ resets = <&cpg R9A07G044_CRU_PRESETN>,
+ <&cpg R9A07G044_CRU_CMN_RSTB>;
+ reset-names = "presetn", "cmn-rstb";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+
+ csi2_in: endpoint {
+ clock-lanes = <0>;
+ data-lanes = <1 2>;
+ remote-endpoint = <&ov5645_ep>;
+ };
+ };
+
+ port@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg = <1>;
+
+ csi2cru: endpoint@0 {
+ reg = <0>;
+ remote-endpoint = <&crucsi2>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/media/s5p-mfc.txt b/Documentation/devicetree/bindings/media/s5p-mfc.txt
index aa54c8159d9f..8eb90c043d5d 100644
--- a/Documentation/devicetree/bindings/media/s5p-mfc.txt
+++ b/Documentation/devicetree/bindings/media/s5p-mfc.txt
@@ -10,10 +10,12 @@ Required properties:
- compatible : value should be either one among the following
(a) "samsung,mfc-v5" for MFC v5 present in Exynos4 SoCs
(b) "samsung,mfc-v6" for MFC v6 present in Exynos5 SoCs
- (c) "samsung,mfc-v7" for MFC v7 present in Exynos5420 SoC
- (d) "samsung,mfc-v8" for MFC v8 present in Exynos5800 SoC
- (e) "samsung,exynos5433-mfc" for MFC v8 present in Exynos5433 SoC
- (f) "samsung,mfc-v10" for MFC v10 present in Exynos7880 SoC
+ (c) "samsung,exynos3250-mfc", "samsung,mfc-v7" for MFC v7
+ present in Exynos3250 SoC
+ (d) "samsung,mfc-v7" for MFC v7 present in Exynos5420 SoC
+ (e) "samsung,mfc-v8" for MFC v8 present in Exynos5800 SoC
+ (f) "samsung,exynos5433-mfc" for MFC v8 present in Exynos5433 SoC
+ (g) "samsung,mfc-v10" for MFC v10 present in Exynos7880 SoC
- reg : Physical base address of the IP registers and length of memory
mapped region.
diff --git a/Documentation/devicetree/bindings/media/samsung-s5c73m3.txt b/Documentation/devicetree/bindings/media/samsung-s5c73m3.txt
index 21f31fdf5543..f0ea9adad442 100644
--- a/Documentation/devicetree/bindings/media/samsung-s5c73m3.txt
+++ b/Documentation/devicetree/bindings/media/samsung-s5c73m3.txt
@@ -76,7 +76,7 @@ i2c@138a000000 {
clock-frequency = <24000000>;
clocks = <&clk 0>;
clock-names = "cis_extclk";
- reset-gpios = <&gpf1 3 1>;
+ xshutdown-gpios = <&gpf1 3 1>;
standby-gpios = <&gpm0 1 1>;
port {
s5c73m3_ep: endpoint {
diff --git a/Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml b/Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml
index 9c1262a276b5..e80fcdf280f0 100644
--- a/Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml
+++ b/Documentation/devicetree/bindings/media/st,stm32-dcmi.yaml
@@ -90,7 +90,9 @@ examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
+ #include <dt-bindings/media/video-interfaces.h>
#include <dt-bindings/reset/stm32mp1-resets.h>
+
dcmi: dcmi@4c006000 {
compatible = "st,stm32-dcmi";
reg = <0x4c006000 0x400>;
@@ -104,7 +106,7 @@ examples:
port {
dcmi_0: endpoint {
remote-endpoint = <&ov5640_0>;
- bus-type = <5>;
+ bus-type = <MEDIA_BUS_TYPE_PARALLEL>;
bus-width = <8>;
hsync-active = <0>;
vsync-active = <0>;
diff --git a/Documentation/devicetree/bindings/media/video-interfaces.yaml b/Documentation/devicetree/bindings/media/video-interfaces.yaml
index 68c3b9871cf3..34bdad028180 100644
--- a/Documentation/devicetree/bindings/media/video-interfaces.yaml
+++ b/Documentation/devicetree/bindings/media/video-interfaces.yaml
@@ -145,9 +145,10 @@ properties:
pclk-sample:
$ref: /schemas/types.yaml#/definitions/uint32
- enum: [ 0, 1 ]
+ enum: [ 0, 1, 2 ]
description:
- Sample data on rising (1) or falling (0) edge of the pixel clock signal.
+ Sample data on falling (0), rising (1) or both (2) edges of the pixel
+ clock signal.
sync-on-green-active:
$ref: /schemas/types.yaml#/definitions/uint32
diff --git a/Documentation/devicetree/bindings/memory-controllers/arm,pl353-smc.yaml b/Documentation/devicetree/bindings/memory-controllers/arm,pl35x-smc.yaml
index 01c9acf9275d..bd23257fe021 100644
--- a/Documentation/devicetree/bindings/memory-controllers/arm,pl353-smc.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/arm,pl35x-smc.yaml
@@ -1,26 +1,31 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/memory-controllers/arm,pl353-smc.yaml#
+$id: http://devicetree.org/schemas/memory-controllers/arm,pl35x-smc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: ARM PL353 Static Memory Controller (SMC) device-tree bindings
+title: Arm PL35x Series Static Memory Controller (SMC)
maintainers:
- Miquel Raynal <miquel.raynal@bootlin.com>
- Naga Sureshkumar Relli <naga.sureshkumar.relli@xilinx.com>
-description:
- The PL353 Static Memory Controller is a bus where you can connect two kinds
+description: |
+ The PL35x Static Memory Controller is a bus where you can connect two kinds
of memory interfaces, which are NAND and memory mapped interfaces (such as
- SRAM or NOR).
+ SRAM or NOR) depending on the specific configuration.
+
+ The TRM is available here:
+ https://documentation-service.arm.com/static/5e8e2524fd977155116a58aa
# We need a select here so we don't match all nodes with 'arm,primecell'
select:
properties:
compatible:
contains:
- const: arm,pl353-smc-r2p1
+ enum:
+ - arm,pl353-smc-r2p1
+ - arm,pl354
required:
- compatible
@@ -30,7 +35,9 @@ properties:
compatible:
items:
- - const: arm,pl353-smc-r2p1
+ - enum:
+ - arm,pl353-smc-r2p1
+ - arm,pl354
- const: arm,primecell
"#address-cells":
@@ -46,30 +53,25 @@ properties:
The three chip select regions are defined in 'ranges'.
clocks:
- items:
- - description: clock for the memory device bus
- - description: main clock of the SMC
+ minItems: 1
+ maxItems: 2
clock-names:
- items:
- - const: memclk
- - const: apb_pclk
+ minItems: 1
+ maxItems: 2
ranges:
minItems: 1
- description: |
- Memory bus areas for interacting with the devices. Reflects
- the memory layout with four integer values following:
- <cs-number> 0 <offset> <size>
- items:
- - description: NAND bank 0
- - description: NOR/SRAM bank 0
- - description: NOR/SRAM bank 1
+ maxItems: 8
- interrupts: true
+ interrupts:
+ minItems: 1
+ items:
+ - description: Combined or Memory interface 0 IRQ
+ - description: Memory interface 1 IRQ
patternProperties:
- "@[0-3],[a-f0-9]+$":
+ "@[0-7],[a-f0-9]+$":
type: object
description: |
The child device node represents the controller connected to the SMC
@@ -87,7 +89,7 @@ patternProperties:
- description: |
Chip-select ID, as in the parent range property.
minimum: 0
- maximum: 2
+ maximum: 7
- description: |
Offset of the memory region requested by the device.
- description: |
@@ -102,12 +104,36 @@ required:
- reg
- clock-names
- clocks
- - "#address-cells"
- - "#size-cells"
- - ranges
additionalProperties: false
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: arm,pl354
+ then:
+ properties:
+ clocks:
+ # According to TRM, really should be 3 clocks
+ maxItems: 1
+
+ clock-names:
+ const: apb_pclk
+
+ else:
+ properties:
+ clocks:
+ items:
+ - description: clock for the memory device bus
+ - description: main clock of the SMC
+
+ clock-names:
+ items:
+ - const: memclk
+ - const: apb_pclk
+
examples:
- |
smcc: memory-controller@e000e000 {
diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr-channel.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr-channel.yaml
new file mode 100644
index 000000000000..34b5bd153f63
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr-channel.yaml
@@ -0,0 +1,146 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/ddr/jedec,lpddr-channel.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: LPDDR channel with chip/rank topology description
+
+description:
+ An LPDDR channel is a completely independent set of LPDDR pins (DQ, CA, CS,
+ CK, etc.) that connect one or more LPDDR chips to a host system. The main
+ purpose of this node is to overall LPDDR topology of the system, including the
+ amount of individual LPDDR chips and the ranks per chip.
+
+maintainers:
+ - Julius Werner <jwerner@chromium.org>
+
+properties:
+ compatible:
+ enum:
+ - jedec,lpddr2-channel
+ - jedec,lpddr3-channel
+ - jedec,lpddr4-channel
+ - jedec,lpddr5-channel
+
+ io-width:
+ description:
+ The number of DQ pins in the channel. If this number is different
+ from (a multiple of) the io-width of the LPDDR chip, that means that
+ multiple instances of that type of chip are wired in parallel on this
+ channel (with the channel's DQ pins split up between the different
+ chips, and the CA, CS, etc. pins of the different chips all shorted
+ together). This means that the total physical memory controlled by a
+ channel is equal to the sum of the densities of each rank on the
+ connected LPDDR chip, times the io-width of the channel divided by
+ the io-width of the LPDDR chip.
+ enum:
+ - 8
+ - 16
+ - 32
+ - 64
+ - 128
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+patternProperties:
+ "^rank@[0-9]+$":
+ type: object
+ description:
+ Each physical LPDDR chip may have one or more ranks. Ranks are
+ internal but fully independent sub-units of the chip. Each LPDDR bus
+ transaction on the channel targets exactly one rank, based on the
+ state of the CS pins. Different ranks may have different densities and
+ timing requirements.
+ required:
+ - reg
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: jedec,lpddr2-channel
+ then:
+ patternProperties:
+ "^rank@[0-9]+$":
+ $ref: /schemas/memory-controllers/ddr/jedec,lpddr2.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: jedec,lpddr3-channel
+ then:
+ patternProperties:
+ "^rank@[0-9]+$":
+ $ref: /schemas/memory-controllers/ddr/jedec,lpddr3.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: jedec,lpddr4-channel
+ then:
+ patternProperties:
+ "^rank@[0-9]+$":
+ $ref: /schemas/memory-controllers/ddr/jedec,lpddr4.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: jedec,lpddr5-channel
+ then:
+ patternProperties:
+ "^rank@[0-9]+$":
+ $ref: /schemas/memory-controllers/ddr/jedec,lpddr5.yaml#
+
+required:
+ - compatible
+ - io-width
+ - "#address-cells"
+ - "#size-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ lpddr-channel0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "jedec,lpddr3-channel";
+ io-width = <32>;
+
+ rank@0 {
+ compatible = "lpddr3-ff,0100", "jedec,lpddr3";
+ reg = <0>;
+ density = <8192>;
+ io-width = <16>;
+ revision-id = <1 0>;
+ };
+ };
+
+ lpddr-channel1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "jedec,lpddr4-channel";
+ io-width = <32>;
+
+ rank@0 {
+ compatible = "lpddr4-05,0301", "jedec,lpddr4";
+ reg = <0>;
+ density = <4096>;
+ io-width = <32>;
+ revision-id = <3 1>;
+ };
+
+ rank@1 {
+ compatible = "lpddr4-05,0301", "jedec,lpddr4";
+ reg = <1>;
+ density = <2048>;
+ io-width = <32>;
+ revision-id = <3 1>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr-props.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr-props.yaml
new file mode 100644
index 000000000000..30267ce70124
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr-props.yaml
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/ddr/jedec,lpddr-props.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Common properties for LPDDR types
+
+description:
+ Different LPDDR types generally use the same properties and only differ in the
+ range of legal values for each. This file defines the common parts that can be
+ reused for each type. Nodes using this schema should generally be nested under
+ an LPDDR channel node.
+
+maintainers:
+ - Krzysztof Kozlowski <krzk@kernel.org>
+
+properties:
+ compatible:
+ description:
+ Compatible strings can be either explicit vendor names and part numbers
+ (e.g. elpida,ECB240ABACN), or generated strings of the form
+ lpddrX-YY,ZZZZ where X is the LPDDR version, YY is the manufacturer ID
+ (from MR5) and ZZZZ is the revision ID (from MR6 and MR7). Both IDs are
+ formatted in lower case hexadecimal representation with leading zeroes.
+ The latter form can be useful when LPDDR nodes are created at runtime by
+ boot firmware that doesn't have access to static part number information.
+
+ reg:
+ description:
+ The rank number of this LPDDR rank when used as a subnode to an LPDDR
+ channel.
+ minimum: 0
+ maximum: 3
+
+ revision-id:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description:
+ Revision IDs read from Mode Register 6 and 7. One byte per uint32 cell (i.e. <MR6 MR7>).
+ maxItems: 2
+ items:
+ minimum: 0
+ maximum: 255
+
+ density:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Density in megabits of SDRAM chip. Decoded from Mode Register 8.
+ enum:
+ - 64
+ - 128
+ - 256
+ - 512
+ - 1024
+ - 2048
+ - 3072
+ - 4096
+ - 6144
+ - 8192
+ - 12288
+ - 16384
+ - 24576
+ - 32768
+
+ io-width:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ IO bus width in bits of SDRAM chip. Decoded from Mode Register 8.
+ enum:
+ - 8
+ - 16
+ - 32
+
+additionalProperties: true
diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
index 9d78f140609b..a237bc259273 100644
--- a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr2.yaml
@@ -9,6 +9,9 @@ title: LPDDR2 SDRAM compliant to JEDEC JESD209-2
maintainers:
- Krzysztof Kozlowski <krzk@kernel.org>
+allOf:
+ - $ref: jedec,lpddr-props.yaml#
+
properties:
compatible:
oneOf:
@@ -17,13 +20,15 @@ properties:
- elpida,ECB240ABACN
- elpida,B8132B2PB-6D-F
- enum:
- - jedec,lpddr2-s4
- - items:
- - enum:
+ - jedec,lpddr2-nvm
- jedec,lpddr2-s2
+ - jedec,lpddr2-s4
- items:
+ - pattern: "^lpddr2-[0-9a-f]{2},[0-9a-f]{4}$"
- enum:
- jedec,lpddr2-nvm
+ - jedec,lpddr2-s2
+ - jedec,lpddr2-s4
revision-id1:
$ref: /schemas/types.yaml#/definitions/uint32
@@ -41,41 +46,6 @@ properties:
Property is deprecated, use revision-id instead.
deprecated: true
- revision-id:
- $ref: /schemas/types.yaml#/definitions/uint32-array
- description: |
- Revision IDs read from Mode Register 6 and 7. One byte per uint32 cell (i.e. <MR6 MR7>).
- minItems: 2
- maxItems: 2
- items:
- minimum: 0
- maximum: 255
-
- density:
- $ref: /schemas/types.yaml#/definitions/uint32
- description: |
- Density in megabits of SDRAM chip. Obtained from device datasheet.
- enum:
- - 64
- - 128
- - 256
- - 512
- - 1024
- - 2048
- - 4096
- - 8192
- - 16384
- - 32768
-
- io-width:
- $ref: /schemas/types.yaml#/definitions/uint32
- description: |
- IO bus width in bits of SDRAM chip. Obtained from device datasheet.
- enum:
- - 32
- - 16
- - 8
-
tRRD-min-tck:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 16
@@ -168,7 +138,7 @@ required:
- density
- io-width
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr3.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr3.yaml
index 48908a19473c..e328a1195ba6 100644
--- a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr3.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr3.yaml
@@ -9,35 +9,24 @@ title: LPDDR3 SDRAM compliant to JEDEC JESD209-3
maintainers:
- Krzysztof Kozlowski <krzk@kernel.org>
+allOf:
+ - $ref: jedec,lpddr-props.yaml#
+
properties:
compatible:
- items:
- - enum:
- - samsung,K3QF2F20DB
- - const: jedec,lpddr3
+ oneOf:
+ - items:
+ - enum:
+ - samsung,K3QF2F20DB
+ - const: jedec,lpddr3
+ - items:
+ - pattern: "^lpddr3-[0-9a-f]{2},[0-9a-f]{4}$"
+ - const: jedec,lpddr3
'#address-cells':
const: 1
deprecated: true
- density:
- $ref: /schemas/types.yaml#/definitions/uint32
- description: |
- Density in megabits of SDRAM chip.
- enum:
- - 4096
- - 8192
- - 16384
- - 32768
-
- io-width:
- $ref: /schemas/types.yaml#/definitions/uint32
- description: |
- IO bus width in bits of SDRAM chip.
- enum:
- - 32
- - 16
-
manufacturer-id:
$ref: /schemas/types.yaml#/definitions/uint32
description: |
@@ -45,15 +34,6 @@ properties:
deprecated, manufacturer should be derived from the compatible.
deprecated: true
- revision-id:
- $ref: /schemas/types.yaml#/definitions/uint32-array
- minItems: 2
- maxItems: 2
- items:
- maximum: 255
- description: |
- Revision value of SDRAM chip read from Mode Registers 6 and 7.
-
'#size-cells':
const: 0
deprecated: true
@@ -206,7 +186,7 @@ required:
- density
- io-width
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr4.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr4.yaml
new file mode 100644
index 000000000000..a078892fecee
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr4.yaml
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/ddr/jedec,lpddr4.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: LPDDR4 SDRAM compliant to JEDEC JESD209-4
+
+maintainers:
+ - Krzysztof Kozlowski <krzk@kernel.org>
+
+allOf:
+ - $ref: jedec,lpddr-props.yaml#
+
+properties:
+ compatible:
+ items:
+ - pattern: "^lpddr4-[0-9a-f]{2},[0-9a-f]{4}$"
+ - const: jedec,lpddr4
+
+required:
+ - compatible
+ - density
+ - io-width
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ lpddr {
+ compatible = "lpddr4-ff,0100", "jedec,lpddr4";
+ density = <8192>;
+ io-width = <16>;
+ revision-id = <1 0>;
+ };
diff --git a/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr5.yaml b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr5.yaml
new file mode 100644
index 000000000000..e441dac5f154
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/ddr/jedec,lpddr5.yaml
@@ -0,0 +1,46 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/ddr/jedec,lpddr5.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: LPDDR5 SDRAM compliant to JEDEC JESD209-5
+
+maintainers:
+ - Krzysztof Kozlowski <krzk@kernel.org>
+
+allOf:
+ - $ref: jedec,lpddr-props.yaml#
+
+properties:
+ compatible:
+ items:
+ - pattern: "^lpddr5-[0-9a-f]{2},[0-9a-f]{4}$"
+ - const: jedec,lpddr5
+
+ serial-id:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description:
+ Serial IDs read from Mode Registers 47 through 54. One byte per uint32
+ cell (i.e. <MR47 MR48 MR49 MR50 MR51 MR52 MR53 MR54>).
+ maxItems: 8
+ items:
+ minimum: 0
+ maximum: 255
+
+required:
+ - compatible
+ - density
+ - io-width
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ lpddr {
+ compatible = "lpddr5-01,0200", "jedec,lpddr5";
+ density = <8192>;
+ io-width = <8>;
+ revision-id = <2 0>;
+ serial-id = <3 1 0 0 0 0 0 0>;
+ };
diff --git a/Documentation/devicetree/bindings/memory-controllers/mc-peripheral-props.yaml b/Documentation/devicetree/bindings/memory-controllers/mc-peripheral-props.yaml
new file mode 100644
index 000000000000..53ae995462db
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/mc-peripheral-props.yaml
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/mc-peripheral-props.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Peripheral-specific properties for a Memory Controller bus.
+
+description:
+ Many Memory Controllers need to add properties to peripheral devices.
+ They could be common properties like reg or they could be controller
+ specific like delay in clock or data lines, etc. These properties need
+ to be defined in the peripheral node because they are per-peripheral
+ and there can be multiple peripherals attached to a controller. All
+ those properties are listed here. The controller specific properties
+ should go in their own separate schema that should be referenced
+ from here.
+
+maintainers:
+ - Marek Vasut <marex@denx.de>
+
+properties:
+ reg:
+ description: Bank number, base address and size of the device.
+
+ bank-width:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description: Bank width of the device, in bytes.
+ enum: [1, 2, 4]
+
+required:
+ - reg
+
+# The controller specific properties go here.
+allOf:
+ - $ref: st,stm32-fmc2-ebi-props.yaml#
+
+additionalProperties: true
diff --git a/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml b/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml
index 645249ea21d1..30a403b1b79a 100644
--- a/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/renesas,rpc-if.yaml
@@ -44,6 +44,11 @@ properties:
- items:
- enum:
+ - renesas,r8a779g0-rpc-if # R-Car V4H
+ - const: renesas,rcar-gen4-rpc-if # a generic R-Car gen4 device
+
+ - items:
+ - enum:
- renesas,r9a07g043-rpc-if # RZ/G2UL
- renesas,r9a07g044-rpc-if # RZ/G2{L,LC}
- renesas,r9a07g054-rpc-if # RZ/V2L
diff --git a/Documentation/devicetree/bindings/memory-controllers/st,stm32-fmc2-ebi-props.yaml b/Documentation/devicetree/bindings/memory-controllers/st,stm32-fmc2-ebi-props.yaml
new file mode 100644
index 000000000000..475e4095068c
--- /dev/null
+++ b/Documentation/devicetree/bindings/memory-controllers/st,stm32-fmc2-ebi-props.yaml
@@ -0,0 +1,144 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/memory-controllers/st,stm32-fmc2-ebi-props.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Peripheral properties for ST FMC2 Controller
+
+maintainers:
+ - Christophe Kerello <christophe.kerello@foss.st.com>
+ - Marek Vasut <marex@denx.de>
+
+properties:
+ st,fmc2-ebi-cs-transaction-type:
+ description: |
+ Select one of the transactions type supported
+ 0: Asynchronous mode 1 SRAM/FRAM.
+ 1: Asynchronous mode 1 PSRAM.
+ 2: Asynchronous mode A SRAM/FRAM.
+ 3: Asynchronous mode A PSRAM.
+ 4: Asynchronous mode 2 NOR.
+ 5: Asynchronous mode B NOR.
+ 6: Asynchronous mode C NOR.
+ 7: Asynchronous mode D NOR.
+ 8: Synchronous read synchronous write PSRAM.
+ 9: Synchronous read asynchronous write PSRAM.
+ 10: Synchronous read synchronous write NOR.
+ 11: Synchronous read asynchronous write NOR.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 11
+
+ st,fmc2-ebi-cs-cclk-enable:
+ description: Continuous clock enable (first bank must be configured
+ in synchronous mode). The FMC_CLK is generated continuously
+ during asynchronous and synchronous access. By default, the
+ FMC_CLK is only generated during synchronous access.
+ $ref: /schemas/types.yaml#/definitions/flag
+
+ st,fmc2-ebi-cs-mux-enable:
+ description: Address/Data multiplexed on databus (valid only with
+ NOR and PSRAM transactions type). By default, Address/Data
+ are not multiplexed.
+ $ref: /schemas/types.yaml#/definitions/flag
+
+ st,fmc2-ebi-cs-buswidth:
+ description: Data bus width
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [ 8, 16 ]
+ default: 16
+
+ st,fmc2-ebi-cs-waitpol-high:
+ description: Wait signal polarity (NWAIT signal active high).
+ By default, NWAIT is active low.
+ $ref: /schemas/types.yaml#/definitions/flag
+
+ st,fmc2-ebi-cs-waitcfg-enable:
+ description: The NWAIT signal indicates wheither the data from the
+ device are valid or if a wait state must be inserted when accessing
+ the device in synchronous mode. By default, the NWAIT signal is
+ active one data cycle before wait state.
+ $ref: /schemas/types.yaml#/definitions/flag
+
+ st,fmc2-ebi-cs-wait-enable:
+ description: The NWAIT signal is enabled (its level is taken into
+ account after the programmed latency period to insert wait states
+ if asserted). By default, the NWAIT signal is disabled.
+ $ref: /schemas/types.yaml#/definitions/flag
+
+ st,fmc2-ebi-cs-asyncwait-enable:
+ description: The NWAIT signal is taken into account during asynchronous
+ transactions. By default, the NWAIT signal is not taken into account
+ during asynchronous transactions.
+ $ref: /schemas/types.yaml#/definitions/flag
+
+ st,fmc2-ebi-cs-cpsize:
+ description: CRAM page size. The controller splits the burst access
+ when the memory page is reached. By default, no burst split when
+ crossing page boundary.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [ 0, 128, 256, 512, 1024 ]
+ default: 0
+
+ st,fmc2-ebi-cs-byte-lane-setup-ns:
+ description: This property configures the byte lane setup timing
+ defined in nanoseconds from NBLx low to Chip Select NEx low.
+
+ st,fmc2-ebi-cs-address-setup-ns:
+ description: This property defines the duration of the address setup
+ phase in nanoseconds used for asynchronous read/write transactions.
+
+ st,fmc2-ebi-cs-address-hold-ns:
+ description: This property defines the duration of the address hold
+ phase in nanoseconds used for asynchronous multiplexed read/write
+ transactions.
+
+ st,fmc2-ebi-cs-data-setup-ns:
+ description: This property defines the duration of the data setup phase
+ in nanoseconds used for asynchronous read/write transactions.
+
+ st,fmc2-ebi-cs-bus-turnaround-ns:
+ description: This property defines the delay in nanoseconds between the
+ end of current read/write transaction and the next transaction.
+
+ st,fmc2-ebi-cs-data-hold-ns:
+ description: This property defines the duration of the data hold phase
+ in nanoseconds used for asynchronous read/write transactions.
+
+ st,fmc2-ebi-cs-clk-period-ns:
+ description: This property defines the FMC_CLK output signal period in
+ nanoseconds.
+
+ st,fmc2-ebi-cs-data-latency-ns:
+ description: This property defines the data latency before reading or
+ writing the first data in nanoseconds.
+
+ st,fmc2-ebi-cs-write-address-setup-ns:
+ description: This property defines the duration of the address setup
+ phase in nanoseconds used for asynchronous write transactions.
+
+ st,fmc2-ebi-cs-write-address-hold-ns:
+ description: This property defines the duration of the address hold
+ phase in nanoseconds used for asynchronous multiplexed write
+ transactions.
+
+ st,fmc2-ebi-cs-write-data-setup-ns:
+ description: This property defines the duration of the data setup
+ phase in nanoseconds used for asynchronous write transactions.
+
+ st,fmc2-ebi-cs-write-bus-turnaround-ns:
+ description: This property defines the delay between the end of current
+ write transaction and the next transaction in nanoseconds.
+
+ st,fmc2-ebi-cs-write-data-hold-ns:
+ description: This property defines the duration of the data hold phase
+ in nanoseconds used for asynchronous write transactions.
+
+ st,fmc2-ebi-cs-max-low-pulse-ns:
+ description: This property defines the maximum chip select low pulse
+ duration in nanoseconds for synchronous transactions. When this timing
+ reaches 0, the controller splits the current access, toggles NE to
+ allow device refresh and restarts a new access.
+
+additionalProperties: true
diff --git a/Documentation/devicetree/bindings/memory-controllers/st,stm32-fmc2-ebi.yaml b/Documentation/devicetree/bindings/memory-controllers/st,stm32-fmc2-ebi.yaml
index 6b516d3895af..d71af02b7f16 100644
--- a/Documentation/devicetree/bindings/memory-controllers/st,stm32-fmc2-ebi.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/st,stm32-fmc2-ebi.yaml
@@ -48,143 +48,7 @@ properties:
patternProperties:
"^.*@[0-4],[a-f0-9]+$":
type: object
-
- properties:
- reg:
- description: Bank number, base address and size of the device.
-
- st,fmc2-ebi-cs-transaction-type:
- description: |
- Select one of the transactions type supported
- 0: Asynchronous mode 1 SRAM/FRAM.
- 1: Asynchronous mode 1 PSRAM.
- 2: Asynchronous mode A SRAM/FRAM.
- 3: Asynchronous mode A PSRAM.
- 4: Asynchronous mode 2 NOR.
- 5: Asynchronous mode B NOR.
- 6: Asynchronous mode C NOR.
- 7: Asynchronous mode D NOR.
- 8: Synchronous read synchronous write PSRAM.
- 9: Synchronous read asynchronous write PSRAM.
- 10: Synchronous read synchronous write NOR.
- 11: Synchronous read asynchronous write NOR.
- $ref: /schemas/types.yaml#/definitions/uint32
- minimum: 0
- maximum: 11
-
- st,fmc2-ebi-cs-cclk-enable:
- description: Continuous clock enable (first bank must be configured
- in synchronous mode). The FMC_CLK is generated continuously
- during asynchronous and synchronous access. By default, the
- FMC_CLK is only generated during synchronous access.
- $ref: /schemas/types.yaml#/definitions/flag
-
- st,fmc2-ebi-cs-mux-enable:
- description: Address/Data multiplexed on databus (valid only with
- NOR and PSRAM transactions type). By default, Address/Data
- are not multiplexed.
- $ref: /schemas/types.yaml#/definitions/flag
-
- st,fmc2-ebi-cs-buswidth:
- description: Data bus width
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [ 8, 16 ]
- default: 16
-
- st,fmc2-ebi-cs-waitpol-high:
- description: Wait signal polarity (NWAIT signal active high).
- By default, NWAIT is active low.
- $ref: /schemas/types.yaml#/definitions/flag
-
- st,fmc2-ebi-cs-waitcfg-enable:
- description: The NWAIT signal indicates wheither the data from the
- device are valid or if a wait state must be inserted when accessing
- the device in synchronous mode. By default, the NWAIT signal is
- active one data cycle before wait state.
- $ref: /schemas/types.yaml#/definitions/flag
-
- st,fmc2-ebi-cs-wait-enable:
- description: The NWAIT signal is enabled (its level is taken into
- account after the programmed latency period to insert wait states
- if asserted). By default, the NWAIT signal is disabled.
- $ref: /schemas/types.yaml#/definitions/flag
-
- st,fmc2-ebi-cs-asyncwait-enable:
- description: The NWAIT signal is taken into account during asynchronous
- transactions. By default, the NWAIT signal is not taken into account
- during asynchronous transactions.
- $ref: /schemas/types.yaml#/definitions/flag
-
- st,fmc2-ebi-cs-cpsize:
- description: CRAM page size. The controller splits the burst access
- when the memory page is reached. By default, no burst split when
- crossing page boundary.
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [ 0, 128, 256, 512, 1024 ]
- default: 0
-
- st,fmc2-ebi-cs-byte-lane-setup-ns:
- description: This property configures the byte lane setup timing
- defined in nanoseconds from NBLx low to Chip Select NEx low.
-
- st,fmc2-ebi-cs-address-setup-ns:
- description: This property defines the duration of the address setup
- phase in nanoseconds used for asynchronous read/write transactions.
-
- st,fmc2-ebi-cs-address-hold-ns:
- description: This property defines the duration of the address hold
- phase in nanoseconds used for asynchronous multiplexed read/write
- transactions.
-
- st,fmc2-ebi-cs-data-setup-ns:
- description: This property defines the duration of the data setup phase
- in nanoseconds used for asynchronous read/write transactions.
-
- st,fmc2-ebi-cs-bus-turnaround-ns:
- description: This property defines the delay in nanoseconds between the
- end of current read/write transaction and the next transaction.
-
- st,fmc2-ebi-cs-data-hold-ns:
- description: This property defines the duration of the data hold phase
- in nanoseconds used for asynchronous read/write transactions.
-
- st,fmc2-ebi-cs-clk-period-ns:
- description: This property defines the FMC_CLK output signal period in
- nanoseconds.
-
- st,fmc2-ebi-cs-data-latency-ns:
- description: This property defines the data latency before reading or
- writing the first data in nanoseconds.
-
- st,fmc2_ebi-cs-write-address-setup-ns:
- description: This property defines the duration of the address setup
- phase in nanoseconds used for asynchronous write transactions.
-
- st,fmc2-ebi-cs-write-address-hold-ns:
- description: This property defines the duration of the address hold
- phase in nanoseconds used for asynchronous multiplexed write
- transactions.
-
- st,fmc2-ebi-cs-write-data-setup-ns:
- description: This property defines the duration of the data setup
- phase in nanoseconds used for asynchronous write transactions.
-
- st,fmc2-ebi-cs-write-bus-turnaround-ns:
- description: This property defines the delay between the end of current
- write transaction and the next transaction in nanoseconds.
-
- st,fmc2-ebi-cs-write-data-hold-ns:
- description: This property defines the duration of the data hold phase
- in nanoseconds used for asynchronous write transactions.
-
- st,fmc2-ebi-cs-max-low-pulse-ns:
- description: This property defines the maximum chip select low pulse
- duration in nanoseconds for synchronous transactions. When this timing
- reaches 0, the controller splits the current access, toggles NE to
- allow device refresh and restarts a new access.
-
- required:
- - reg
+ $ref: mc-peripheral-props.yaml#
required:
- "#address-cells"
diff --git a/Documentation/devicetree/bindings/memory-controllers/ti,gpmc-child.yaml b/Documentation/devicetree/bindings/memory-controllers/ti,gpmc-child.yaml
index 6e3995bb1630..4a257fac577e 100644
--- a/Documentation/devicetree/bindings/memory-controllers/ti,gpmc-child.yaml
+++ b/Documentation/devicetree/bindings/memory-controllers/ti,gpmc-child.yaml
@@ -230,6 +230,13 @@ properties:
Wait-pin used by client. Must be less than "gpmc,num-waitpins".
$ref: /schemas/types.yaml#/definitions/uint32
+ ti,wait-pin-polarity:
+ description: |
+ Set the desired polarity for the selected wait pin.
+ 0 for active low, 1 for active high.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [0, 1]
+
gpmc,wait-on-read:
description: Enables wait monitoring on reads.
type: boolean
diff --git a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
index 04962bb29576..3d5efa5578d1 100644
--- a/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
+++ b/Documentation/devicetree/bindings/mfd/google,cros-ec.yaml
@@ -20,19 +20,21 @@ properties:
compatible:
oneOf:
- description:
- For implementations of the EC is connected through I2C.
+ For implementations of the EC connected through I2C.
const: google,cros-ec-i2c
- description:
- For implementations of the EC is connected through SPI.
+ For implementations of the EC connected through SPI.
const: google,cros-ec-spi
- description:
- For implementations of the EC is connected through RPMSG.
+ For implementations of the FPMCU connected through SPI.
+ items:
+ - const: google,cros-ec-fp
+ - const: google,cros-ec-spi
+ - description:
+ For implementations of the EC connected through RPMSG.
const: google,cros-ec-rpmsg
- controller-data:
- description:
- SPI controller data, see bindings/spi/samsung,spi-peripheral-props.yaml
- type: object
+ controller-data: true
google,cros-ec-spi-pre-delay:
description:
@@ -62,8 +64,7 @@ properties:
the SCP.
$ref: "/schemas/types.yaml#/definitions/string"
- spi-max-frequency:
- description: Maximum SPI frequency of the device in Hz.
+ spi-max-frequency: true
reg:
maxItems: 1
@@ -71,6 +72,15 @@ properties:
interrupts:
maxItems: 1
+ reset-gpios:
+ maxItems: 1
+
+ boot0-gpios:
+ maxItems: 1
+ description: Assert for bootloader mode.
+
+ vdd-supply: true
+
wakeup-source:
description: Button can wake-up the system.
@@ -155,18 +165,67 @@ allOf:
- if:
properties:
compatible:
- contains:
- enum:
- - google,cros-ec-i2c
- - google,cros-ec-rpmsg
+ not:
+ contains:
+ const: google,cros-ec-spi
then:
properties:
+ controller-data: false
google,cros-ec-spi-pre-delay: false
google,cros-ec-spi-msg-delay: false
spi-max-frequency: false
else:
$ref: /schemas/spi/spi-peripheral-props.yaml
+ - if:
+ properties:
+ compatible:
+ not:
+ contains:
+ const: google,cros-ec-rpmsg
+ then:
+ properties:
+ mediatek,rpmsg-name: false
+
+ required:
+ - reg
+ - interrupts
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: google,cros-ec-fp
+ then:
+ properties:
+ '#address-cells': false
+ '#size-cells': false
+ typec: false
+ ec-pwm: false
+ kbd-led-backlight: false
+ keyboard-controller: false
+ proximity: false
+ codecs: false
+ cbas: false
+
+ patternProperties:
+ "^i2c-tunnel[0-9]*$": false
+ "^regulator@[0-9]+$": false
+ "^extcon[0-9]*$": false
+
+ # Using additionalProperties: false here and
+ # listing true properties doesn't work
+
+ required:
+ - reset-gpios
+ - boot0-gpios
+ - vdd-supply
+ else:
+ properties:
+ reset-gpios: false
+ boot0-gpios: false
+ vdd-supply: false
+
additionalProperties: false
examples:
@@ -222,4 +281,22 @@ examples:
compatible = "google,cros-ec-rpmsg";
};
};
+
+ # Example for FPMCU
+ - |
+ spi0 {
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+
+ ec@0 {
+ compatible = "google,cros-ec-fp", "google,cros-ec-spi";
+ reg = <0x0>;
+ interrupt-parent = <&gpio_controller>;
+ interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+ spi-max-frequency = <3000000>;
+ reset-gpios = <&gpio_controller 5 GPIO_ACTIVE_LOW>;
+ boot0-gpios = <&gpio_controller 10 GPIO_ACTIVE_HIGH>;
+ vdd-supply = <&pp3300_fp_mcu>;
+ };
+ };
...
diff --git a/Documentation/devicetree/bindings/mfd/max77650.yaml b/Documentation/devicetree/bindings/mfd/max77650.yaml
index b0a0f0d3d9d4..4181174fcf58 100644
--- a/Documentation/devicetree/bindings/mfd/max77650.yaml
+++ b/Documentation/devicetree/bindings/mfd/max77650.yaml
@@ -100,14 +100,12 @@ examples:
compatible = "maxim,max77650-regulator";
max77650_ldo: regulator-ldo {
- regulator-compatible = "ldo";
regulator-name = "max77650-ldo";
regulator-min-microvolt = <1350000>;
regulator-max-microvolt = <2937500>;
};
max77650_sbb0: regulator-sbb0 {
- regulator-compatible = "sbb0";
regulator-name = "max77650-sbb0";
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <1587500>;
diff --git a/Documentation/devicetree/bindings/mfd/mediatek,mt6360.yaml b/Documentation/devicetree/bindings/mfd/mediatek,mt6360.yaml
index 28eee02441ee..fb65abf30d57 100644
--- a/Documentation/devicetree/bindings/mfd/mediatek,mt6360.yaml
+++ b/Documentation/devicetree/bindings/mfd/mediatek,mt6360.yaml
@@ -83,7 +83,6 @@ examples:
richtek,vinovp-microvolt = <14500000>;
otg_vbus_regulator: usb-otg-vbus-regulator {
- regulator-compatible = "usb-otg-vbus";
regulator-name = "usb-otg-vbus";
regulator-min-microvolt = <4425000>;
regulator-max-microvolt = <5825000>;
@@ -145,7 +144,6 @@ examples:
compatible = "mediatek,mt6360-regulator";
LDO_VIN3-supply = <&BUCK2>;
buck1 {
- regulator-compatible = "BUCK1";
regulator-name = "mt6360,buck1";
regulator-min-microvolt = <300000>;
regulator-max-microvolt = <1300000>;
@@ -154,7 +152,6 @@ examples:
MT6360_OPMODE_ULP>;
};
BUCK2: buck2 {
- regulator-compatible = "BUCK2";
regulator-name = "mt6360,buck2";
regulator-min-microvolt = <300000>;
regulator-max-microvolt = <1300000>;
@@ -163,7 +160,6 @@ examples:
MT6360_OPMODE_ULP>;
};
ldo6 {
- regulator-compatible = "LDO6";
regulator-name = "mt6360,ldo6";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <2100000>;
@@ -171,7 +167,6 @@ examples:
MT6360_OPMODE_LP>;
};
ldo7 {
- regulator-compatible = "LDO7";
regulator-name = "mt6360,ldo7";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <2100000>;
@@ -179,7 +174,6 @@ examples:
MT6360_OPMODE_LP>;
};
ldo1 {
- regulator-compatible = "LDO1";
regulator-name = "mt6360,ldo1";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3600000>;
@@ -187,7 +181,6 @@ examples:
MT6360_OPMODE_LP>;
};
ldo2 {
- regulator-compatible = "LDO2";
regulator-name = "mt6360,ldo2";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3600000>;
@@ -195,7 +188,6 @@ examples:
MT6360_OPMODE_LP>;
};
ldo3 {
- regulator-compatible = "LDO3";
regulator-name = "mt6360,ldo3";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3600000>;
@@ -203,7 +195,6 @@ examples:
MT6360_OPMODE_LP>;
};
ldo5 {
- regulator-compatible = "LDO5";
regulator-name = "mt6360,ldo5";
regulator-min-microvolt = <2700000>;
regulator-max-microvolt = <3600000>;
diff --git a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
index 6a3e3ede1ede..a5edab6f2e40 100644
--- a/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
+++ b/Documentation/devicetree/bindings/mfd/qcom,spmi-pmic.yaml
@@ -33,6 +33,7 @@ properties:
compatible:
items:
- enum:
+ - qcom,pm6125
- qcom,pm6150
- qcom,pm6150l
- qcom,pm6350
diff --git a/Documentation/devicetree/bindings/mips/brcm/brcm,bmips.txt b/Documentation/devicetree/bindings/mips/brcm/brcm,bmips.txt
deleted file mode 100644
index 8ef71b4085ca..000000000000
--- a/Documentation/devicetree/bindings/mips/brcm/brcm,bmips.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-* Broadcom MIPS (BMIPS) CPUs
-
-Required properties:
-- compatible: "brcm,bmips3300", "brcm,bmips4350", "brcm,bmips4380",
- "brcm,bmips5000"
-
-- mips-hpt-frequency: This is common to all CPUs in the system so it lives
- under the "cpus" node.
diff --git a/Documentation/devicetree/bindings/mips/brcm/soc.yaml b/Documentation/devicetree/bindings/mips/brcm/soc.yaml
new file mode 100644
index 000000000000..975945ca2888
--- /dev/null
+++ b/Documentation/devicetree/bindings/mips/brcm/soc.yaml
@@ -0,0 +1,96 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mips/brcm/soc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Broadcom cable/DSL/settop platforms
+
+maintainers:
+ - Florian Fainelli <f.fainelli@gmail.com>
+
+description: |
+ Boards Broadcom cable/DSL/settop SoC shall have the following properties.
+ The experimental -viper variants are for running Linux on the 3384's
+ BMIPS4355 cable modem CPU instead of the BMIPS5000 application processor.
+
+properties:
+ $nodename:
+ const: '/'
+
+ compatible:
+ enum:
+ - brcm,bcm3368
+ - brcm,bcm3384
+ - brcm,bcm33843
+ - brcm,bcm3384-viper
+ - brcm,bcm33843-viper
+ - brcm,bcm6328
+ - brcm,bcm6358
+ - brcm,bcm6362
+ - brcm,bcm6368
+ - brcm,bcm63168
+ - brcm,bcm63268
+ - brcm,bcm7125
+ - brcm,bcm7346
+ - brcm,bcm7358
+ - brcm,bcm7360
+ - brcm,bcm7362
+ - brcm,bcm7420
+ - brcm,bcm7425
+
+ cpus:
+ type: object
+ additionalProperties: false
+ properties:
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+ mips-hpt-frequency:
+ description: MIPS counter high precision timer frequency.
+ This is common to all CPUs in the system so it lives
+ under the "cpus" node.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ patternProperties:
+ "^cpu@[0-9]$":
+ type: object
+ $ref: /schemas/mips/cpus.yaml#
+ unevaluatedProperties: false
+
+ required:
+ - mips-hpt-frequency
+
+additionalProperties: true
+
+examples:
+ - |
+ / {
+ compatible = "brcm,bcm3368";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ model = "Broadcom 3368";
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ mips-hpt-frequency = <150000000>;
+
+ cpu@0 {
+ compatible = "brcm,bmips4350";
+ device_type = "cpu";
+ reg = <0>;
+ };
+
+ cpu@1 {
+ compatible = "brcm,bmips4350";
+ device_type = "cpu";
+ reg = <1>;
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/mips/cpus.yaml b/Documentation/devicetree/bindings/mips/cpus.yaml
new file mode 100644
index 000000000000..e991f4c6668d
--- /dev/null
+++ b/Documentation/devicetree/bindings/mips/cpus.yaml
@@ -0,0 +1,115 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mips/cpus.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MIPS CPUs bindings
+
+maintainers:
+ - Thomas Bogendoerfer <tsbogend@alpha.franken.de>
+ - å‘¨ç°æ° (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
+
+description: |
+ The device tree allows to describe the layout of CPUs in a system through
+ the "cpus" node, which in turn contains a number of subnodes (ie "cpu")
+ defining properties for every CPU.
+
+properties:
+ compatible:
+ enum:
+ - brcm,bmips3300
+ - brcm,bmips4350
+ - brcm,bmips4380
+ - brcm,bmips5000
+ - brcm,bmips5200
+ - ingenic,xburst-mxu1.0
+ - ingenic,xburst-fpu1.0-mxu1.1
+ - ingenic,xburst-fpu2.0-mxu2.0
+ - ingenic,xburst2-fpu2.1-mxu2.1-smt
+ - loongson,gs264
+ - mips,m14Kc
+ - mips,mips4Kc
+ - mips,mips4KEc
+ - mips,mips24Kc
+ - mips,mips24KEc
+ - mips,mips74Kc
+ - mips,mips1004Kc
+ - mti,interaptiv
+ - mti,mips24KEc
+ - mti,mips14KEc
+ - mti,mips14Kc
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ device_type: true
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - ingenic,xburst-mxu1.0
+ - ingenic,xburst-fpu1.0-mxu1.1
+ - ingenic,xburst-fpu2.0-mxu2.0
+ - ingenic,xburst2-fpu2.1-mxu2.1-smt
+ then:
+ required:
+ - device_type
+ - clocks
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ cpus {
+ #size-cells = <0>;
+ #address-cells = <1>;
+
+ cpu@0 {
+ compatible = "mips,mips1004Kc";
+ device_type = "cpu";
+ reg = <0>;
+ };
+
+ cpu@1 {
+ compatible = "mips,mips1004Kc";
+ device_type = "cpu";
+ reg = <1>;
+ };
+ };
+
+ - |
+ // Example 2 (Ingenic CPU)
+ #include <dt-bindings/clock/ingenic,jz4780-cgu.h>
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ compatible = "ingenic,xburst-fpu1.0-mxu1.1";
+ device_type = "cpu";
+ reg = <0>;
+
+ clocks = <&cgu JZ4780_CLK_CPU>;
+ };
+
+ cpu@1 {
+ compatible = "ingenic,xburst-fpu1.0-mxu1.1";
+ device_type = "cpu";
+ reg = <1>;
+
+ clocks = <&cgu JZ4780_CLK_CORE1>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/mips/ingenic/ingenic,cpu.yaml b/Documentation/devicetree/bindings/mips/ingenic/ingenic,cpu.yaml
deleted file mode 100644
index b7e7fa715437..000000000000
--- a/Documentation/devicetree/bindings/mips/ingenic/ingenic,cpu.yaml
+++ /dev/null
@@ -1,69 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/mips/ingenic/ingenic,cpu.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Bindings for Ingenic XBurst family CPUs
-
-maintainers:
- - å‘¨ç°æ° (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
-
-description:
- Ingenic XBurst family CPUs shall have the following properties.
-
-properties:
- compatible:
- oneOf:
-
- - description: Ingenic XBurst®1 CPU Cores
- enum:
- - ingenic,xburst-mxu1.0
- - ingenic,xburst-fpu1.0-mxu1.1
- - ingenic,xburst-fpu2.0-mxu2.0
-
- - description: Ingenic XBurst®2 CPU Cores
- enum:
- - ingenic,xburst2-fpu2.1-mxu2.1-smt
-
- reg:
- maxItems: 1
-
- clocks:
- maxItems: 1
-
- device_type: true
-
-required:
- - device_type
- - compatible
- - reg
- - clocks
-
-additionalProperties: false
-
-examples:
- - |
- #include <dt-bindings/clock/ingenic,jz4780-cgu.h>
-
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
-
- cpu0: cpu@0 {
- device_type = "cpu";
- compatible = "ingenic,xburst-fpu1.0-mxu1.1";
- reg = <0>;
-
- clocks = <&cgu JZ4780_CLK_CPU>;
- };
-
- cpu1: cpu@1 {
- device_type = "cpu";
- compatible = "ingenic,xburst-fpu1.0-mxu1.1";
- reg = <1>;
-
- clocks = <&cgu JZ4780_CLK_CORE1>;
- };
- };
-...
diff --git a/Documentation/devicetree/bindings/misc/idt,89hpesx.yaml b/Documentation/devicetree/bindings/misc/idt,89hpesx.yaml
new file mode 100644
index 000000000000..452236e79354
--- /dev/null
+++ b/Documentation/devicetree/bindings/misc/idt,89hpesx.yaml
@@ -0,0 +1,72 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/misc/idt,89hpesx.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: EEPROM / CSR SMBus-slave interface of IDT 89HPESx devices
+
+maintainers:
+ - Serge Semin <fancer.lancer@gmail.com>
+
+select:
+ properties:
+ compatible:
+ contains:
+ pattern: '^idt,89hpes'
+ required:
+ - compatible
+
+properties:
+ compatible:
+ oneOf:
+ - pattern: '^idt,89hpes(8nt2|12nt3|12n3a?|24n3a?|(12|24)t3g2|4t4g2|10t4g2|[56]t5|8t5a?)$'
+ - pattern: '^idt,89hpes(6t6g2|16t7|(24t6|32t8|48t12|16t4a?)(g2)?)$'
+ - pattern: '^idt,89hpes(24nt6a|32nt8[ab]|12nt12|16nt16|24nt24|32nt24[ab])g2$'
+ - pattern: '^idt,89hpes((32h8|48h12a?|22h16|34h16|64h16a?)(g2)?|16h16)$'
+
+ reg:
+ maxItems: 1
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+patternProperties:
+ '^eeprom@':
+ $ref: /schemas/eeprom/at24.yaml#
+ unevaluatedProperties: false
+
+ properties:
+ compatible:
+ description: Only a subset of devices are supported
+ pattern: ',24c(32|64|128|256|512)$'
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ idt@74 {
+ compatible = "idt,89hpes32nt8ag2";
+ reg = <0x74>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ eeprom@50 {
+ compatible = "atmel,24c64";
+ reg = <0x50>;
+ read-only;
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/misc/idt_89hpesx.txt b/Documentation/devicetree/bindings/misc/idt_89hpesx.txt
deleted file mode 100644
index b9093b79ab7d..000000000000
--- a/Documentation/devicetree/bindings/misc/idt_89hpesx.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-EEPROM / CSR SMBus-slave interface of IDT 89HPESx devices
-
-Required properties:
- - compatible : should be "<manufacturer>,<type>"
- Basically there is only one manufacturer: idt, but some
- compatible devices may be produced in future. Following devices
- are supported: 89hpes8nt2, 89hpes12nt3, 89hpes24nt6ag2,
- 89hpes32nt8ag2, 89hpes32nt8bg2, 89hpes12nt12g2, 89hpes16nt16g2,
- 89hpes24nt24g2, 89hpes32nt24ag2, 89hpes32nt24bg2;
- 89hpes12n3, 89hpes12n3a, 89hpes24n3, 89hpes24n3a;
- 89hpes32h8, 89hpes32h8g2, 89hpes48h12, 89hpes48h12g2,
- 89hpes48h12ag2, 89hpes16h16, 89hpes22h16, 89hpes22h16g2,
- 89hpes34h16, 89hpes34h16g2, 89hpes64h16, 89hpes64h16g2,
- 89hpes64h16ag2;
- 89hpes12t3g2, 89hpes24t3g2, 89hpes16t4, 89hpes4t4g2,
- 89hpes10t4g2, 89hpes16t4g2, 89hpes16t4ag2, 89hpes5t5,
- 89hpes6t5, 89hpes8t5, 89hpes8t5a, 89hpes24t6, 89hpes6t6g2,
- 89hpes24t6g2, 89hpes16t7, 89hpes32t8, 89hpes32t8g2,
- 89hpes48t12, 89hpes48t12g2.
- - reg : I2C address of the IDT 89HPESx device.
-
-Optionally there can be EEPROM-compatible subnode:
- - compatible: There are five EEPROM devices supported: 24c32, 24c64, 24c128,
- 24c256 and 24c512 differed by size.
- - reg: Custom address of EEPROM device (If not specified IDT 89HPESx
- (optional) device will try to communicate with EEPROM sited by default
- address - 0x50)
- - read-only : Parameterless property disables writes to the EEPROM
- (optional)
-
-Example:
- idt@60 {
- compatible = "idt,89hpes32nt8ag2";
- reg = <0x74>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- eeprom@50 {
- compatible = "onsemi,24c64";
- reg = <0x50>;
- read-only;
- };
- };
-
diff --git a/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml b/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml
index 1e69a5a42439..1c96da04f0e5 100644
--- a/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml
+++ b/Documentation/devicetree/bindings/mmc/arm,pl18x.yaml
@@ -95,7 +95,9 @@ properties:
PIO (polled I/O) interrupt and occurs when the FIFO needs to be
emptied as part of a bulk read from the card. Some variants have these
two interrupts wired into the same line (logic OR) and in that case
- only one interrupt may be provided.
+ only one interrupt may be provided. The interrupt-names property is
+ not used due to inconsistency of existing DTs regarding its content.
+ deprecated: false
minItems: 1
maxItems: 2
diff --git a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml
index 29339d0196ec..dc6256f04b42 100644
--- a/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml
+++ b/Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.yaml
@@ -50,11 +50,11 @@ properties:
- const: fsl,imx8mm-usdhc
- items:
- enum:
+ - fsl,imx8dxl-usdhc
- fsl,imx8qm-usdhc
- const: fsl,imx8qxp-usdhc
- items:
- enum:
- - fsl,imx8dxl-usdhc
- fsl,imx8mm-usdhc
- fsl,imx8mn-usdhc
- fsl,imx8mp-usdhc
@@ -71,10 +71,15 @@ properties:
deprecated: true
- items:
- enum:
+ - fsl,imx8dxl-usdhc
- fsl,imx8qm-usdhc
- const: fsl,imx8qxp-usdhc
- const: fsl,imx7d-usdhc
deprecated: true
+ - items:
+ - enum:
+ - fsl,imxrt1170-usdhc
+ - const: fsl,imxrt1050-usdhc
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/mmc/fujitsu,sdhci-fujitsu.yaml b/Documentation/devicetree/bindings/mmc/fujitsu,sdhci-fujitsu.yaml
new file mode 100644
index 000000000000..73d747e917f3
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/fujitsu,sdhci-fujitsu.yaml
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mmc/fujitsu,sdhci-fujitsu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Fujitsu/Socionext SDHCI controller (F_SDH30)
+
+maintainers:
+ - Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
+
+allOf:
+ - $ref: mmc-controller.yaml#
+
+properties:
+ compatible:
+ enum:
+ - fujitsu,mb86s70-sdhci-3.0
+ - socionext,f-sdh30-e51-mmc
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 2
+
+ clock-names:
+ items:
+ - const: iface
+ - const: core
+
+ resets:
+ maxItems: 1
+
+ fujitsu,cmd-dat-delay-select:
+ type: boolean
+ description: |
+ Indicating that this host requires the CMD_DAT_DELAY control to be enabled
+
+unevaluatedProperties: false
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+
+examples:
+ - |
+ sdhci1: mmc@36600000 {
+ compatible = "fujitsu,mb86s70-sdhci-3.0";
+ reg = <0x36600000 0x1000>;
+ bus-width = <4>;
+ vqmmc-supply = <&vccq_sdhci1>;
+ clocks = <&clock 2 2 0>, <&clock 2 3 0>;
+ clock-names = "iface", "core";
+ };
diff --git a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml
index 802e3ca8be4d..e82c00368088 100644
--- a/Documentation/devicetree/bindings/mmc/mmc-controller.yaml
+++ b/Documentation/devicetree/bindings/mmc/mmc-controller.yaml
@@ -293,7 +293,6 @@ properties:
description:
SDIO only. Preserves card power during a suspend/resume cycle.
- # Deprecated: enable-sdio-wakeup
wakeup-source:
$ref: /schemas/types.yaml#/definitions/flag
description:
diff --git a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
index d8e1e2e9adf2..8ed94a12a03b 100644
--- a/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
+++ b/Documentation/devicetree/bindings/mmc/mtk-sd.yaml
@@ -10,9 +10,6 @@ maintainers:
- Chaotian Jing <chaotian.jing@mediatek.com>
- Wenbin Mei <wenbin.mei@mediatek.com>
-allOf:
- - $ref: mmc-controller.yaml#
-
properties:
compatible:
oneOf:
@@ -23,6 +20,7 @@ properties:
- mediatek,mt6795-mmc
- mediatek,mt7620-mmc
- mediatek,mt7622-mmc
+ - mediatek,mt7986-mmc
- mediatek,mt8135-mmc
- mediatek,mt8173-mmc
- mediatek,mt8183-mmc
@@ -48,27 +46,11 @@ properties:
description:
Should contain phandle for the clock feeding the MMC controller.
minItems: 2
- items:
- - description: source clock (required).
- - description: HCLK which used for host (required).
- - description: independent source clock gate (required for MT2712).
- - description: bus clock used for internal register access (required for MT2712 MSDC0/3).
- - description: msdc subsys clock gate (required for MT8192).
- - description: peripheral bus clock gate (required for MT8192).
- - description: AXI bus clock gate (required for MT8192).
- - description: AHB bus clock gate (required for MT8192).
+ maxItems: 7
clock-names:
minItems: 2
- items:
- - const: source
- - const: hclk
- - const: source_cg
- - const: bus_clk
- - const: sys_cg
- - const: pclk_cg
- - const: axi_cg
- - const: ahb_cg
+ maxItems: 7
interrupts:
description:
@@ -190,15 +172,144 @@ required:
- vmmc-supply
- vqmmc-supply
-if:
- properties:
- compatible:
- contains:
- const: mediatek,mt8183-mmc
-then:
- properties:
- reg:
- minItems: 2
+allOf:
+ - $ref: mmc-controller.yaml#
+ - if:
+ properties:
+ compatible:
+ enum:
+ - mediatek,mt2701-mmc
+ - mediatek,mt6779-mmc
+ - mediatek,mt6795-mmc
+ - mediatek,mt7620-mmc
+ - mediatek,mt7622-mmc
+ - mediatek,mt7623-mmc
+ - mediatek,mt8135-mmc
+ - mediatek,mt8173-mmc
+ - mediatek,mt8183-mmc
+ - mediatek,mt8186-mmc
+ - mediatek,mt8188-mmc
+ - mediatek,mt8195-mmc
+ - mediatek,mt8516-mmc
+ then:
+ properties:
+ clocks:
+ minItems: 2
+ items:
+ - description: source clock
+ - description: HCLK which used for host
+ - description: independent source clock gate
+ clock-names:
+ minItems: 2
+ items:
+ - const: source
+ - const: hclk
+ - const: source_cg
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: mediatek,mt2712-mmc
+ then:
+ properties:
+ clocks:
+ minItems: 3
+ items:
+ - description: source clock
+ - description: HCLK which used for host
+ - description: independent source clock gate
+ - description: bus clock used for internal register access (required for MSDC0/3).
+ clock-names:
+ minItems: 3
+ items:
+ - const: source
+ - const: hclk
+ - const: source_cg
+ - const: bus_clk
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: mediatek,mt8183-mmc
+ then:
+ properties:
+ reg:
+ minItems: 2
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - mediatek,mt7986-mmc
+ then:
+ properties:
+ clocks:
+ minItems: 3
+ items:
+ - description: source clock
+ - description: HCLK which used for host
+ - description: independent source clock gate
+ - description: bus clock used for internal register access (required for MSDC0/3).
+ - description: msdc subsys clock gate
+ clock-names:
+ minItems: 3
+ items:
+ - const: source
+ - const: hclk
+ - const: source_cg
+ - const: bus_clk
+ - const: sys_cg
+
+ - if:
+ properties:
+ compatible:
+ enum:
+ - mediatek,mt8186-mmc
+ - mediatek,mt8188-mmc
+ - mediatek,mt8195-mmc
+ then:
+ properties:
+ clocks:
+ items:
+ - description: source clock
+ - description: HCLK which used for host
+ - description: independent source clock gate
+ - description: crypto clock used for data encrypt/decrypt (optional)
+ clock-names:
+ items:
+ - const: source
+ - const: hclk
+ - const: source_cg
+ - const: crypto
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: mediatek,mt8192-mmc
+ then:
+ properties:
+ clocks:
+ items:
+ - description: source clock
+ - description: HCLK which used for host
+ - description: independent source clock gate
+ - description: msdc subsys clock gate
+ - description: peripheral bus clock gate
+ - description: AXI bus clock gate
+ - description: AHB bus clock gate
+ clock-names:
+ items:
+ - const: source
+ - const: hclk
+ - const: source_cg
+ - const: sys_cg
+ - const: pclk_cg
+ - const: axi_cg
+ - const: ahb_cg
unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml
index 0424b06cb655..7bfb10c62566 100644
--- a/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml
+++ b/Documentation/devicetree/bindings/mmc/renesas,sdhi.yaml
@@ -64,6 +64,7 @@ properties:
- enum:
- renesas,sdhi-r8a779a0 # R-Car V3U
- renesas,sdhi-r8a779f0 # R-Car S4-8
+ - renesas,sdhi-r8a779g0 # R-Car V4H
- const: renesas,rcar-gen4-sdhi # R-Car Gen4
reg:
diff --git a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
index 95f59a5e3576..c7e14b7dba9e 100644
--- a/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
+++ b/Documentation/devicetree/bindings/mmc/rockchip-dw-mshc.yaml
@@ -71,6 +71,9 @@ properties:
to control the clock phases, "ciu-sample" is required for tuning
high speed modes.
+ power-domains:
+ maxItems: 1
+
rockchip,default-sample-phase:
$ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml b/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml
index ea9121fb188d..676a74695389 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml
+++ b/Documentation/devicetree/bindings/mmc/sdhci-am654.yaml
@@ -2,8 +2,8 @@
# Copyright (C) 2020 Texas Instruments Incorporated - http://www.ti.com/
%YAML 1.2
---
-$id: "http://devicetree.org/schemas/mmc/sdhci-am654.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/mmc/sdhci-am654.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
title: TI AM654 MMC Controller
@@ -11,17 +11,18 @@ maintainers:
- Ulf Hansson <ulf.hansson@linaro.org>
allOf:
- - $ref: mmc-controller.yaml#
+ - $ref: sdhci-common.yaml#
properties:
compatible:
oneOf:
- - const: ti,am654-sdhci-5.1
- - const: ti,j721e-sdhci-8bit
- - const: ti,j721e-sdhci-4bit
- - const: ti,am64-sdhci-8bit
- - const: ti,am64-sdhci-4bit
- - const: ti,am62-sdhci
+ - enum:
+ - ti,am62-sdhci
+ - ti,am64-sdhci-4bit
+ - ti,am64-sdhci-8bit
+ - ti,am654-sdhci-5.1
+ - ti,j721e-sdhci-4bit
+ - ti,j721e-sdhci-8bit
- items:
- const: ti,j7200-sdhci-8bit
- const: ti,j721e-sdhci-8bit
@@ -49,8 +50,6 @@ properties:
- const: clk_ahb
- const: clk_xin
- sdhci-caps-mask: true
-
dma-coherent:
type: boolean
@@ -61,67 +60,67 @@ properties:
ti,otap-del-sel-legacy:
description: Output tap delay for SD/MMC legacy timing
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0xf
ti,otap-del-sel-mmc-hs:
description: Output tap delay for MMC high speed timing
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0xf
ti,otap-del-sel-sd-hs:
description: Output tap delay for SD high speed timing
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0xf
ti,otap-del-sel-sdr12:
description: Output tap delay for SD UHS SDR12 timing
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0xf
ti,otap-del-sel-sdr25:
description: Output tap delay for SD UHS SDR25 timing
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0xf
ti,otap-del-sel-sdr50:
description: Output tap delay for SD UHS SDR50 timing
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0xf
ti,otap-del-sel-sdr104:
description: Output tap delay for SD UHS SDR104 timing
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0xf
ti,otap-del-sel-ddr50:
description: Output tap delay for SD UHS DDR50 timing
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0xf
ti,otap-del-sel-ddr52:
description: Output tap delay for eMMC DDR52 timing
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0xf
ti,otap-del-sel-hs200:
description: Output tap delay for eMMC HS200 timing
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0xf
ti,otap-del-sel-hs400:
description: Output tap delay for eMMC HS400 timing
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0xf
@@ -131,49 +130,55 @@ properties:
ti,itap-del-sel-legacy:
description: Input tap delay for SD/MMC legacy timing
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0x1f
ti,itap-del-sel-mmc-hs:
description: Input tap delay for MMC high speed timing
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0x1f
ti,itap-del-sel-sd-hs:
description: Input tap delay for SD high speed timing
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0x1f
ti,itap-del-sel-sdr12:
description: Input tap delay for SD UHS SDR12 timing
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0x1f
ti,itap-del-sel-sdr25:
description: Input tap delay for SD UHS SDR25 timing
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 0
+ maximum: 0x1f
+
+ ti,itap-del-sel-ddr50:
+ description: Input tap delay for MMC DDR50 timing
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0x1f
ti,itap-del-sel-ddr52:
description: Input tap delay for MMC DDR52 timing
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0x1f
ti,trm-icp:
description: DLL trim select
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
minimum: 0
maximum: 0xf
ti,driver-strength-ohm:
description: DLL drive strength in ohms
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
enum:
- 33
- 40
@@ -183,11 +188,11 @@ properties:
ti,strobe-sel:
description: strobe select delay for HS400 speed mode.
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
ti,clkbuf-sel:
description: Clock Delay Buffer Select
- $ref: "/schemas/types.yaml#/definitions/uint32"
+ $ref: /schemas/types.yaml#/definitions/uint32
ti,fails-without-test-cd:
$ref: /schemas/types.yaml#/definitions/flag
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-common.yaml b/Documentation/devicetree/bindings/mmc/sdhci-common.yaml
new file mode 100644
index 000000000000..1664615187c8
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/sdhci-common.yaml
@@ -0,0 +1,32 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mmc/sdhci-common.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: SDHCI Controller Common Properties
+
+maintainers:
+ - Adrian Hunter <adrian.hunter@intel.com>
+
+description:
+ Common properties present on Secure Digital Host Controller Interface (SDHCI)
+ devices.
+
+properties:
+ sdhci-caps:
+ $ref: /schemas/types.yaml#/definitions/uint64
+ description:
+ Additionally present SDHCI capabilities - values for SDHCI_CAPABILITIES
+ and SDHCI_CAPABILITIES_1 registers.
+
+ sdhci-caps-mask:
+ $ref: /schemas/types.yaml#/definitions/uint64
+ description:
+ Masked SDHCI capabilities to remove from SDHCI_CAPABILITIES and
+ SDHCI_CAPABILITIES_1 registers.
+
+allOf:
+ - $ref: mmc-controller.yaml#
+
+additionalProperties: true
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-fujitsu.txt b/Documentation/devicetree/bindings/mmc/sdhci-fujitsu.txt
deleted file mode 100644
index 3ee9263adf73..000000000000
--- a/Documentation/devicetree/bindings/mmc/sdhci-fujitsu.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-* Fujitsu SDHCI controller
-
-This file documents differences between the core properties in mmc.txt
-and the properties used by the sdhci_f_sdh30 driver.
-
-Required properties:
-- compatible: "fujitsu,mb86s70-sdhci-3.0"
-- clocks: Must contain an entry for each entry in clock-names. It is a
- list of phandles and clock-specifier pairs.
- See ../clocks/clock-bindings.txt for details.
-- clock-names: Should contain the following two entries:
- "iface" - clock used for sdhci interface
- "core" - core clock for sdhci controller
-
-Optional properties:
-- vqmmc-supply: phandle to the regulator device tree node, mentioned
- as the VCCQ/VDD_IO supply in the eMMC/SD specs.
-- fujitsu,cmd-dat-delay-select: boolean property indicating that this host
- requires the CMD_DAT_DELAY control to be enabled.
-
-Example:
-
- sdhci1: mmc@36600000 {
- compatible = "fujitsu,mb86s70-sdhci-3.0";
- reg = <0 0x36600000 0x1000>;
- interrupts = <0 172 0x4>,
- <0 173 0x4>;
- bus-width = <4>;
- vqmmc-supply = <&vccq_sdhci1>;
- clocks = <&clock 2 2 0>, <&clock 2 3 0>;
- clock-names = "iface", "core";
- };
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml
index a96f143479c7..6b89238f0565 100644
--- a/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml
+++ b/Documentation/devicetree/bindings/mmc/sdhci-msm.yaml
@@ -1,9 +1,8 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
-
%YAML 1.2
---
-$id: "http://devicetree.org/schemas/mmc/sdhci-msm.yaml#"
-$schema: "http://devicetree.org/meta-schemas/core.yaml#"
+$id: http://devicetree.org/schemas/mmc/sdhci-msm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm SDHCI controller (sdhci-msm)
@@ -26,6 +25,7 @@ properties:
- qcom,msm8226-sdhci
- qcom,msm8953-sdhci
- qcom,msm8974-sdhci
+ - qcom,msm8976-sdhci
- qcom,msm8916-sdhci
- qcom,msm8992-sdhci
- qcom,msm8994-sdhci
@@ -45,9 +45,12 @@ properties:
- qcom,sm6115-sdhci
- qcom,sm6125-sdhci
- qcom,sm6350-sdhci
+ - qcom,sm6375-sdhci
- qcom,sm8150-sdhci
- qcom,sm8250-sdhci
+ - qcom,sm8350-sdhci
- qcom,sm8450-sdhci
+ - qcom,sm8550-sdhci
- const: qcom,sdhci-msm-v5 # for sdcc version 5.0
reg:
@@ -80,6 +83,8 @@ properties:
- const: cal
- const: sleep
+ dma-coherent: true
+
interrupts:
maxItems: 2
@@ -133,16 +138,6 @@ properties:
description: A phandle to sdhci power domain node
maxItems: 1
- mmc-ddr-1_8v: true
-
- mmc-hs200-1_8v: true
-
- mmc-hs400-1_8v: true
-
- bus-width: true
-
- max-frequency: true
-
operating-points-v2: true
patternProperties:
@@ -165,7 +160,7 @@ required:
- interrupts
allOf:
- - $ref: mmc-controller.yaml#
+ - $ref: sdhci-common.yaml#
- if:
properties:
diff --git a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
index 71f8e726d641..51ba44cad842 100644
--- a/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
+++ b/Documentation/devicetree/bindings/mmc/snps,dwcmshc-sdhci.yaml
@@ -45,6 +45,17 @@ properties:
- const: block
- const: timer
+ resets:
+ maxItems: 5
+
+ reset-names:
+ items:
+ - const: core
+ - const: bus
+ - const: axi
+ - const: block
+ - const: timer
+
rockchip,txclk-tapnum:
description: Specify the number of delay for tx sampling.
$ref: /schemas/types.yaml#/definitions/uint8
diff --git a/Documentation/devicetree/bindings/mmc/sunplus,mmc.yaml b/Documentation/devicetree/bindings/mmc/sunplus,mmc.yaml
new file mode 100644
index 000000000000..23aa8e6b2d70
--- /dev/null
+++ b/Documentation/devicetree/bindings/mmc/sunplus,mmc.yaml
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) Sunplus Ltd. Co. 2021
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mmc/sunplus,mmc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Sunplus MMC Controller
+
+maintainers:
+ - Tony Huang <tonyhuang.sunplus@gmail.com>
+ - Li-hao Kuo <lhjeff911@gmail.com>
+
+allOf:
+ - $ref: "mmc-controller.yaml"
+
+properties:
+ compatible:
+ enum:
+ - sunplus,sp7021-mmc
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ resets:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - resets
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ mmc0: mmc@9c003b00 {
+ compatible = "sunplus,sp7021-mmc";
+ reg = <0x9c003b00 0x180>;
+ interrupts = <20 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clkc 0x4e>;
+ resets = <&rstc 0x3e>;
+ bus-width = <8>;
+ max-frequency = <52000000>;
+ non-removable;
+ disable-wp;
+ cap-mmc-highspeed;
+ mmc-ddr-3_3v;
+ no-sdio;
+ no-sd;
+ };
diff --git a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.yaml b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.yaml
index ae6d6fca79e2..e1f5f26f3f1c 100644
--- a/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.yaml
+++ b/Documentation/devicetree/bindings/mmc/synopsys-dw-mshc.yaml
@@ -6,9 +6,6 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Synopsys Designware Mobile Storage Host Controller Binding
-allOf:
- - $ref: "synopsys-dw-mshc-common.yaml#"
-
maintainers:
- Ulf Hansson <ulf.hansson@linaro.org>
@@ -38,6 +35,35 @@ properties:
- const: biu
- const: ciu
+ altr,sysmgr-syscon:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ items:
+ - items:
+ - description: phandle to the sysmgr node
+ - description: register offset that controls the SDMMC clock phase
+ - description: register shift for the smplsel(drive in) setting
+ description:
+ This property is optional. Contains the phandle to System Manager block
+ that contains the SDMMC clock-phase control register. The first value is
+ the pointer to the sysmgr, the 2nd value is the register offset for the
+ SDMMC clock phase register, and the 3rd value is the bit shift for the
+ smplsel(drive in) setting.
+
+allOf:
+ - $ref: synopsys-dw-mshc-common.yaml#
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: altr,socfpga-dw-mshc
+ then:
+ properties:
+ altr,sysmgr-syscon: true
+ else:
+ properties:
+ altr,sysmgr-syscon: false
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml b/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml
index 4741864da48e..e7ec0c59bca6 100644
--- a/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml
+++ b/Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml
@@ -14,9 +14,6 @@ maintainers:
- Maxime Ripard <mripard@kernel.org>
properties:
- "#address-cells": true
- "#size-cells": true
-
compatible:
enum:
- allwinner,sun4i-a10-nand
@@ -49,12 +46,8 @@ properties:
dma-names:
const: rxtx
- pinctrl-names: true
-
patternProperties:
- "^pinctrl-[0-9]+$": true
-
- "^nand@[a-f0-9]+$":
+ "^nand@[a-f0-9]$":
type: object
properties:
reg:
@@ -91,6 +84,29 @@ required:
- clocks
- clock-names
-additionalProperties: false
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/sun6i-rtc.h>
+ #include <dt-bindings/clock/sun8i-a23-a33-ccu.h>
+ #include <dt-bindings/reset/sun8i-a23-a33-ccu.h>
+
+ nand-controller@1c03000 {
+ compatible = "allwinner,sun8i-a23-nand-controller";
+ reg = <0x01c03000 0x1000>;
+ interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_NAND>, <&ccu CLK_NAND>;
+ clock-names = "ahb", "mod";
+ resets = <&ccu RST_BUS_NAND>;
+ reset-names = "ahb";
+ dmas = <&dma 5>;
+ dma-names = "rxtx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&nand_pins &nand_cs0_pin &nand_rb0_pin>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
...
diff --git a/Documentation/devicetree/bindings/mtd/arasan,nand-controller.yaml b/Documentation/devicetree/bindings/mtd/arasan,nand-controller.yaml
index f013fb976d95..d028269cdbaa 100644
--- a/Documentation/devicetree/bindings/mtd/arasan,nand-controller.yaml
+++ b/Documentation/devicetree/bindings/mtd/arasan,nand-controller.yaml
@@ -35,9 +35,6 @@ properties:
interrupts:
maxItems: 1
- "#address-cells": true
- "#size-cells": true
-
required:
- compatible
- reg
@@ -45,7 +42,7 @@ required:
- clock-names
- interrupts
-additionalProperties: true
+unevaluatedProperties: true
examples:
- |
diff --git a/Documentation/devicetree/bindings/mtd/arm,pl353-nand-r2p1.yaml b/Documentation/devicetree/bindings/mtd/arm,pl353-nand-r2p1.yaml
index 023f3ef0fa13..e552875040e2 100644
--- a/Documentation/devicetree/bindings/mtd/arm,pl353-nand-r2p1.yaml
+++ b/Documentation/devicetree/bindings/mtd/arm,pl353-nand-r2p1.yaml
@@ -34,20 +34,20 @@ unevaluatedProperties: false
examples:
- |
smcc: memory-controller@e000e000 {
- compatible = "arm,pl353-smc-r2p1", "arm,primecell";
- reg = <0xe000e000 0x0001000>;
- clock-names = "memclk", "apb_pclk";
- clocks = <&clkc 11>, <&clkc 44>;
- ranges = <0x0 0x0 0xe1000000 0x1000000 /* Nand CS region */
- 0x1 0x0 0xe2000000 0x2000000 /* SRAM/NOR CS0 region */
- 0x2 0x0 0xe4000000 0x2000000>; /* SRAM/NOR CS1 region */
- #address-cells = <2>;
- #size-cells = <1>;
-
- nfc0: nand-controller@0,0 {
- compatible = "arm,pl353-nand-r2p1";
- reg = <0 0 0x1000000>;
- #address-cells = <1>;
- #size-cells = <0>;
- };
+ compatible = "arm,pl353-smc-r2p1", "arm,primecell";
+ reg = <0xe000e000 0x0001000>;
+ clock-names = "memclk", "apb_pclk";
+ clocks = <&clkc 11>, <&clkc 44>;
+ ranges = <0x0 0x0 0xe1000000 0x1000000 /* Nand CS region */
+ 0x1 0x0 0xe2000000 0x2000000 /* SRAM/NOR CS0 region */
+ 0x2 0x0 0xe4000000 0x2000000>; /* SRAM/NOR CS1 region */
+ #address-cells = <2>;
+ #size-cells = <1>;
+
+ nfc0: nand-controller@0,0 {
+ compatible = "arm,pl353-nand-r2p1";
+ reg = <0 0 0x1000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
};
diff --git a/Documentation/devicetree/bindings/mtd/atmel-nand.txt b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
index 3aa297c97ab6..50645828ac20 100644
--- a/Documentation/devicetree/bindings/mtd/atmel-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/atmel-nand.txt
@@ -45,10 +45,8 @@ Optional properties:
- atmel,rb: an integer identifying the native Ready/Busy pin. Only meaningful
on sama5 SoCs.
-All generic properties described in
-Documentation/devicetree/bindings/mtd/{common,nand}.txt also apply to the NAND
-device node, and NAND partitions should be defined under the NAND node as
-described in Documentation/devicetree/bindings/mtd/partition.txt.
+All generic properties are described in the generic yaml files under
+Documentation/devicetree/bindings/mtd/.
* ECC engine (PMECC) bindings:
diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml
index dd5a64969e37..1571024aa119 100644
--- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml
+++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.yaml
@@ -86,15 +86,15 @@ properties:
minItems: 1
items:
- description: NAND CTLRDY interrupt
- - description: FLASH_DMA_DONE if flash DMA is available
- - description: FLASH_EDU_DONE if EDU is available
+ - description: FLASH_DMA_DONE (if flash DMA is available) or FLASH_EDU_DONE (if EDU is available)
interrupt-names:
minItems: 1
items:
- const: nand_ctlrdy
- - const: flash_dma_done
- - const: flash_edu_done
+ - enum:
+ - flash_dma_done
+ - flash_edu_done
clocks:
maxItems: 1
@@ -173,6 +173,13 @@ allOf:
- const: nand
- const: iproc-idm
- const: iproc-ext
+ - if:
+ properties:
+ interrupts:
+ minItems: 2
+ then:
+ required:
+ - interrupt-names
unevaluatedProperties: false
@@ -184,51 +191,52 @@ required:
examples:
- |
nand-controller@f0442800 {
- compatible = "brcm,brcmnand-v7.0", "brcm,brcmnand";
- reg = <0xf0442800 0x600>,
- <0xf0443000 0x100>;
- reg-names = "nand", "flash-dma";
- interrupt-parent = <&hif_intr2_intc>;
- interrupts = <24>, <4>;
+ compatible = "brcm,brcmnand-v7.0", "brcm,brcmnand";
+ reg = <0xf0442800 0x600>,
+ <0xf0443000 0x100>;
+ reg-names = "nand", "flash-dma";
+ interrupt-parent = <&hif_intr2_intc>;
+ interrupts = <24>, <4>;
+ interrupt-names = "nand_ctlrdy", "flash_dma_done";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ nand@1 {
+ compatible = "brcm,nandcs";
+ reg = <1>; // Chip select 1
+ nand-on-flash-bbt;
+ nand-ecc-strength = <12>;
+ nand-ecc-step-size = <512>;
#address-cells = <1>;
- #size-cells = <0>;
-
- nand@1 {
- compatible = "brcm,nandcs";
- reg = <1>; // Chip select 1
- nand-on-flash-bbt;
- nand-ecc-strength = <12>;
- nand-ecc-step-size = <512>;
-
- #address-cells = <1>;
- #size-cells = <1>;
- };
+ #size-cells = <1>;
+ };
};
- |
nand-controller@10000200 {
- compatible = "brcm,nand-bcm63168", "brcm,nand-bcm6368",
- "brcm,brcmnand-v4.0", "brcm,brcmnand";
- reg = <0x10000200 0x180>,
- <0x100000b0 0x10>,
- <0x10000600 0x200>;
- reg-names = "nand", "nand-int-base", "nand-cache";
- interrupt-parent = <&periph_intc>;
- interrupts = <50>;
- clocks = <&periph_clk 20>;
- clock-names = "nand";
+ compatible = "brcm,nand-bcm63168", "brcm,nand-bcm6368",
+ "brcm,brcmnand-v4.0", "brcm,brcmnand";
+ reg = <0x10000200 0x180>,
+ <0x100000b0 0x10>,
+ <0x10000600 0x200>;
+ reg-names = "nand", "nand-int-base", "nand-cache";
+ interrupt-parent = <&periph_intc>;
+ interrupts = <50>;
+ clocks = <&periph_clk 20>;
+ clock-names = "nand";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ nand@0 {
+ compatible = "brcm,nandcs";
+ reg = <0>;
+ nand-on-flash-bbt;
+ nand-ecc-strength = <1>;
+ nand-ecc-step-size = <512>;
#address-cells = <1>;
- #size-cells = <0>;
-
- nand@0 {
- compatible = "brcm,nandcs";
- reg = <0>;
- nand-on-flash-bbt;
- nand-ecc-strength = <1>;
- nand-ecc-step-size = <512>;
-
- #address-cells = <1>;
- #size-cells = <1>;
- };
+ #size-cells = <1>;
+ };
};
diff --git a/Documentation/devicetree/bindings/mtd/denali,nand.yaml b/Documentation/devicetree/bindings/mtd/denali,nand.yaml
index 1307ed7e7fc6..0be83ad42970 100644
--- a/Documentation/devicetree/bindings/mtd/denali,nand.yaml
+++ b/Documentation/devicetree/bindings/mtd/denali,nand.yaml
@@ -145,6 +145,6 @@ examples:
#size-cells = <0>;
nand@0 {
- reg = <0>;
+ reg = <0>;
};
};
diff --git a/Documentation/devicetree/bindings/mtd/ingenic,nand.yaml b/Documentation/devicetree/bindings/mtd/ingenic,nand.yaml
index 8c272c842bfd..a811a512ecc5 100644
--- a/Documentation/devicetree/bindings/mtd/ingenic,nand.yaml
+++ b/Documentation/devicetree/bindings/mtd/ingenic,nand.yaml
@@ -32,9 +32,9 @@ properties:
partitions:
type: object
+ deprecated: true
description:
Node containing description of fixed partitions.
- See Documentation/devicetree/bindings/mtd/partition.txt
patternProperties:
"^nand@[a-f0-9]$":
@@ -58,78 +58,78 @@ examples:
- |
#include <dt-bindings/clock/ingenic,jz4780-cgu.h>
memory-controller@13410000 {
- compatible = "ingenic,jz4780-nemc";
- reg = <0x13410000 0x10000>;
- #address-cells = <2>;
- #size-cells = <1>;
- ranges = <1 0 0x1b000000 0x1000000>,
- <2 0 0x1a000000 0x1000000>,
- <3 0 0x19000000 0x1000000>,
- <4 0 0x18000000 0x1000000>,
- <5 0 0x17000000 0x1000000>,
- <6 0 0x16000000 0x1000000>;
-
- clocks = <&cgu JZ4780_CLK_NEMC>;
-
- nand-controller@1 {
- compatible = "ingenic,jz4780-nand";
- reg = <1 0 0x1000000>;
-
- #address-cells = <1>;
- #size-cells = <0>;
-
- ecc-engine = <&bch>;
-
- ingenic,nemc-tAS = <10>;
- ingenic,nemc-tAH = <5>;
- ingenic,nemc-tBP = <10>;
- ingenic,nemc-tAW = <15>;
- ingenic,nemc-tSTRV = <100>;
-
- pinctrl-names = "default";
- pinctrl-0 = <&pins_nemc>;
-
- nand@1 {
- reg = <1>;
-
- nand-ecc-step-size = <1024>;
- nand-ecc-strength = <24>;
- nand-ecc-mode = "hw";
- nand-on-flash-bbt;
-
- pinctrl-names = "default";
- pinctrl-0 = <&pins_nemc_cs1>;
-
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <2>;
- #size-cells = <2>;
-
- partition@0 {
- label = "u-boot-spl";
- reg = <0x0 0x0 0x0 0x800000>;
+ compatible = "ingenic,jz4780-nemc";
+ reg = <0x13410000 0x10000>;
+ #address-cells = <2>;
+ #size-cells = <1>;
+ ranges = <1 0 0x1b000000 0x1000000>,
+ <2 0 0x1a000000 0x1000000>,
+ <3 0 0x19000000 0x1000000>,
+ <4 0 0x18000000 0x1000000>,
+ <5 0 0x17000000 0x1000000>,
+ <6 0 0x16000000 0x1000000>;
+
+ clocks = <&cgu JZ4780_CLK_NEMC>;
+
+ nand-controller@1 {
+ compatible = "ingenic,jz4780-nand";
+ reg = <1 0 0x1000000>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ecc-engine = <&bch>;
+
+ ingenic,nemc-tAS = <10>;
+ ingenic,nemc-tAH = <5>;
+ ingenic,nemc-tBP = <10>;
+ ingenic,nemc-tAW = <15>;
+ ingenic,nemc-tSTRV = <100>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_nemc>;
+
+ nand@1 {
+ reg = <1>;
+
+ nand-ecc-step-size = <1024>;
+ nand-ecc-strength = <24>;
+ nand-ecc-mode = "hw";
+ nand-on-flash-bbt;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pins_nemc_cs1>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ partition@0 {
+ label = "u-boot-spl";
+ reg = <0x0 0x0 0x0 0x800000>;
+ };
+
+ partition@800000 {
+ label = "u-boot";
+ reg = <0x0 0x800000 0x0 0x200000>;
+ };
+
+ partition@a00000 {
+ label = "u-boot-env";
+ reg = <0x0 0xa00000 0x0 0x200000>;
+ };
+
+ partition@c00000 {
+ label = "boot";
+ reg = <0x0 0xc00000 0x0 0x4000000>;
+ };
+
+ partition@4c00000 {
+ label = "system";
+ reg = <0x0 0x4c00000 0x1 0xfb400000>;
+ };
+ };
};
-
- partition@800000 {
- label = "u-boot";
- reg = <0x0 0x800000 0x0 0x200000>;
- };
-
- partition@a00000 {
- label = "u-boot-env";
- reg = <0x0 0xa00000 0x0 0x200000>;
- };
-
- partition@c00000 {
- label = "boot";
- reg = <0x0 0xc00000 0x0 0x4000000>;
- };
-
- partition@4c00000 {
- label = "system";
- reg = <0x0 0x4c00000 0x1 0xfb400000>;
- };
- };
};
- };
};
diff --git a/Documentation/devicetree/bindings/mtd/intel,lgm-ebunand.yaml b/Documentation/devicetree/bindings/mtd/intel,lgm-ebunand.yaml
index 741c66ee06c3..8c62c7d3d0cd 100644
--- a/Documentation/devicetree/bindings/mtd/intel,lgm-ebunand.yaml
+++ b/Documentation/devicetree/bindings/mtd/intel,lgm-ebunand.yaml
@@ -39,14 +39,8 @@ properties:
- const: tx
- const: rx
- "#address-cells":
- const: 1
-
- "#size-cells":
- const: 0
-
patternProperties:
- "^nand@[a-f0-9]+$":
+ "^nand@[a-f0-9]$":
type: object
properties:
reg:
@@ -67,33 +61,31 @@ required:
- clocks
- dmas
- dma-names
- - "#address-cells"
- - "#size-cells"
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
nand-controller@e0f00000 {
- compatible = "intel,lgm-ebunand";
- reg = <0xe0f00000 0x100>,
- <0xe1000000 0x300>,
- <0xe1400000 0x8000>,
- <0xe1c00000 0x1000>,
- <0x17400000 0x4>,
- <0x17c00000 0x4>;
- reg-names = "ebunand", "hsnand", "nand_cs0", "nand_cs1",
- "addr_sel0", "addr_sel1";
- clocks = <&cgu0 125>;
- dmas = <&dma0 8>, <&dma0 9>;
- dma-names = "tx", "rx";
- #address-cells = <1>;
- #size-cells = <0>;
-
- nand@0 {
- reg = <0>;
- nand-ecc-mode = "hw";
- };
+ compatible = "intel,lgm-ebunand";
+ reg = <0xe0f00000 0x100>,
+ <0xe1000000 0x300>,
+ <0xe1400000 0x8000>,
+ <0xe1c00000 0x1000>,
+ <0x17400000 0x4>,
+ <0x17c00000 0x4>;
+ reg-names = "ebunand", "hsnand", "nand_cs0", "nand_cs1",
+ "addr_sel0", "addr_sel1";
+ clocks = <&cgu0 125>;
+ dmas = <&dma0 8>, <&dma0 9>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ nand@0 {
+ reg = <0>;
+ nand-ecc-mode = "hw";
+ };
};
...
diff --git a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
index 7149784a36ac..3fe981b14e2c 100644
--- a/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
+++ b/Documentation/devicetree/bindings/mtd/jedec,spi-nor.yaml
@@ -70,24 +70,17 @@ properties:
be used on such systems, to denote the absence of a reliable reset
mechanism.
- partitions:
- type: object
-
- '#address-cells': true
- '#size-cells': true
-
-patternProperties:
- # Note: use 'partitions' node for new users
- '^partition@':
- type: object
-
- "^otp(-[0-9]+)?$":
- type: object
+ reset-gpios:
+ description:
+ A GPIO line connected to the RESET (active low) signal of the device.
+ If "broken-flash-reset" is present then having this property does not
+ make any difference.
unevaluatedProperties: false
examples:
- |
+ #include <dt-bindings/gpio/gpio.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
@@ -97,6 +90,7 @@ examples:
reg = <0>;
spi-max-frequency = <40000000>;
m25p,fast-read;
+ reset-gpios = <&gpio 12 GPIO_ACTIVE_LOW>;
};
};
...
diff --git a/Documentation/devicetree/bindings/mtd/lpc32xx-mlc.txt b/Documentation/devicetree/bindings/mtd/lpc32xx-mlc.txt
index 6d60bc3063f5..64c06aa05ac7 100644
--- a/Documentation/devicetree/bindings/mtd/lpc32xx-mlc.txt
+++ b/Documentation/devicetree/bindings/mtd/lpc32xx-mlc.txt
@@ -19,7 +19,7 @@ accuracy:)
- nxp,wr_low: WR_LOW
Optional subnodes:
-- Partitions, see Documentation/devicetree/bindings/mtd/partition.txt
+- Partitions, see Documentation/devicetree/bindings/mtd/mtd.yaml
Example:
diff --git a/Documentation/devicetree/bindings/mtd/lpc32xx-slc.txt b/Documentation/devicetree/bindings/mtd/lpc32xx-slc.txt
index d94edc0fc554..39f17630a301 100644
--- a/Documentation/devicetree/bindings/mtd/lpc32xx-slc.txt
+++ b/Documentation/devicetree/bindings/mtd/lpc32xx-slc.txt
@@ -20,7 +20,7 @@ clock speed:)
- nxp,rsetup: Read setup time (R_SETUP)
Optional subnodes:
-- Partitions, see Documentation/devicetree/bindings/mtd/partition.txt
+- Partitions, see Documentation/devicetree/bindings/mtd/mtd.yaml
Example:
diff --git a/Documentation/devicetree/bindings/mtd/microchip,mchp48l640.yaml b/Documentation/devicetree/bindings/mtd/microchip,mchp48l640.yaml
index 8cc2a7ceb5fb..ea9450fe7c9f 100644
--- a/Documentation/devicetree/bindings/mtd/microchip,mchp48l640.yaml
+++ b/Documentation/devicetree/bindings/mtd/microchip,mchp48l640.yaml
@@ -34,13 +34,13 @@ unevaluatedProperties: false
examples:
- |
spi {
- #address-cells = <1>;
- #size-cells = <0>;
-
- eeram@0 {
- compatible = "microchip,48l640";
- reg = <0>;
- spi-max-frequency = <20000000>;
- };
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ eeram@0 {
+ compatible = "microchip,48l640";
+ reg = <0>;
+ spi-max-frequency = <20000000>;
+ };
};
...
diff --git a/Documentation/devicetree/bindings/mtd/mtd-physmap.yaml b/Documentation/devicetree/bindings/mtd/mtd-physmap.yaml
index 82eb4e0f453b..5df94953c34e 100644
--- a/Documentation/devicetree/bindings/mtd/mtd-physmap.yaml
+++ b/Documentation/devicetree/bindings/mtd/mtd-physmap.yaml
@@ -13,6 +13,9 @@ description: |
Flash chips (Memory Technology Devices) are often used for solid state
file systems on embedded devices.
+allOf:
+ - $ref: "mtd.yaml#"
+
properties:
compatible:
oneOf:
@@ -121,10 +124,6 @@ properties:
big-endian: true
little-endian: true
-patternProperties:
- '@[0-9a-f]+$':
- $ref: partitions/partition.yaml
-
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/mtd/mtd.yaml b/Documentation/devicetree/bindings/mtd/mtd.yaml
index 3498e485679b..78da129e9985 100644
--- a/Documentation/devicetree/bindings/mtd/mtd.yaml
+++ b/Documentation/devicetree/bindings/mtd/mtd.yaml
@@ -12,7 +12,7 @@ maintainers:
properties:
$nodename:
- pattern: "^flash(@.*)?$"
+ pattern: "^(flash|.*sram)(@.*)?$"
label:
description:
@@ -21,9 +21,28 @@ properties:
based name) in order to ease flash device identification and/or
describe what they are used for.
+ '#address-cells':
+ deprecated: true
+
+ '#size-cells':
+ deprecated: true
+
+ partitions:
+ $ref: /schemas/mtd/partitions/partitions.yaml
+
+ required:
+ - compatible
+
patternProperties:
+ "@[0-9a-f]+$":
+ $ref: partitions/partition.yaml
+ deprecated: true
+
+ "^partition@[0-9a-f]+":
+ $ref: partitions/partition.yaml
+ deprecated: true
+
"^otp(-[0-9]+)?$":
- type: object
$ref: ../nvmem/nvmem.yaml#
description: |
@@ -40,6 +59,7 @@ patternProperties:
required:
- compatible
+# This is a generic file other binding inherit from
additionalProperties: true
examples:
diff --git a/Documentation/devicetree/bindings/mtd/mtk-nand.txt b/Documentation/devicetree/bindings/mtd/mtk-nand.txt
index 4d3ec5e4ff8a..839ea2f93d04 100644
--- a/Documentation/devicetree/bindings/mtd/mtk-nand.txt
+++ b/Documentation/devicetree/bindings/mtd/mtk-nand.txt
@@ -131,7 +131,7 @@ Example:
};
NAND chip optional subnodes:
-- Partitions, see Documentation/devicetree/bindings/mtd/partition.txt
+- Partitions, see Documentation/devicetree/bindings/mtd/mtd.yaml
Example:
nand@0 {
diff --git a/Documentation/devicetree/bindings/mtd/nand-chip.yaml b/Documentation/devicetree/bindings/mtd/nand-chip.yaml
index 97ac3a3fbb52..6e2dc025d694 100644
--- a/Documentation/devicetree/bindings/mtd/nand-chip.yaml
+++ b/Documentation/devicetree/bindings/mtd/nand-chip.yaml
@@ -9,6 +9,9 @@ title: NAND Chip and NAND Controller Generic Binding
maintainers:
- Miquel Raynal <miquel.raynal@bootlin.com>
+allOf:
+ - $ref: "mtd.yaml#"
+
description: |
This file covers the generic description of a NAND chip. It implies that the
bus interface should not be taken into account: both raw NAND devices and
@@ -67,4 +70,5 @@ properties:
required:
- reg
+# This file can be referenced by more specific devices (like spi-nands)
additionalProperties: true
diff --git a/Documentation/devicetree/bindings/mtd/nand-controller.yaml b/Documentation/devicetree/bindings/mtd/nand-controller.yaml
index 359a015d4e5a..220aa2c8c0b5 100644
--- a/Documentation/devicetree/bindings/mtd/nand-controller.yaml
+++ b/Documentation/devicetree/bindings/mtd/nand-controller.yaml
@@ -51,7 +51,6 @@ properties:
patternProperties:
"^nand@[a-f0-9]$":
- type: object
$ref: "nand-chip.yaml#"
properties:
@@ -130,6 +129,7 @@ required:
- "#address-cells"
- "#size-cells"
+# This is a generic file other binding inherit from and extend
additionalProperties: true
examples:
diff --git a/Documentation/devicetree/bindings/mtd/partition.txt b/Documentation/devicetree/bindings/mtd/partition.txt
deleted file mode 100644
index ead90e8274d6..000000000000
--- a/Documentation/devicetree/bindings/mtd/partition.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-Flash partitions in device tree
-===============================
-
-Flash devices can be partitioned into one or more functional ranges (e.g. "boot
-code", "nvram", "kernel").
-
-Different devices may be partitioned in a different ways. Some may use a fixed
-flash layout set at production time. Some may use on-flash table that describes
-the geometry and naming/purpose of each functional region. It is also possible
-to see these methods mixed.
-
-To assist system software in locating partitions, we allow describing which
-method is used for a given flash device. To describe the method there should be
-a subnode of the flash device that is named 'partitions'. It must have a
-'compatible' property, which is used to identify the method to use.
-
-When a single partition is represented with a DT node (it depends on a used
-format) it may also be described using above rules ('compatible' and optionally
-some extra properties / subnodes). It allows describing more complex,
-hierarchical (multi-level) layouts and should be used if there is some
-significant relation between partitions or some partition internally uses
-another partitioning method.
-
-Available bindings are listed in the "partitions" subdirectory.
-
-
-Deprecated: partitions defined in flash node
-============================================
-
-For backwards compatibility partitions as direct subnodes of the flash device are
-supported. This use is discouraged.
-NOTE: also for backwards compatibility, direct subnodes that have a compatible
-string are not considered partitions, as they may be used for other bindings.
diff --git a/Documentation/devicetree/bindings/mtd/partitions/arm,arm-firmware-suite.yaml b/Documentation/devicetree/bindings/mtd/partitions/arm,arm-firmware-suite.yaml
index 76c88027b6d2..97618847ee35 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/arm,arm-firmware-suite.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/arm,arm-firmware-suite.yaml
@@ -9,6 +9,8 @@ title: ARM Firmware Suite (AFS) Partitions
maintainers:
- Linus Walleij <linus.walleij@linaro.org>
+select: false
+
description: |
The ARM Firmware Suite is a flash partitioning system found on the
ARM reference designs: Integrator AP, Integrator CP, Versatile AB,
diff --git a/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm4908-partitions.yaml b/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm4908-partitions.yaml
index 7b113e5e3421..5bbb1c01ddee 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm4908-partitions.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm4908-partitions.yaml
@@ -17,6 +17,8 @@ description: |
maintainers:
- Rafał Miłecki <rafal@milecki.pl>
+select: false
+
properties:
compatible:
const: brcm,bcm4908-partitions
diff --git a/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm947xx-cfe-partitions.yaml b/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm947xx-cfe-partitions.yaml
index 3484e06d6bcb..939e7b50db22 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm947xx-cfe-partitions.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/brcm,bcm947xx-cfe-partitions.yaml
@@ -35,6 +35,8 @@ description: |
maintainers:
- Rafał Miłecki <rafal@milecki.pl>
+select: false
+
properties:
compatible:
const: brcm,bcm947xx-cfe-partitions
diff --git a/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml b/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml
index ad3ccd250802..331e564f29dc 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml
@@ -31,24 +31,17 @@ properties:
patternProperties:
"@[0-9a-f]+$":
- allOf:
- - $ref: "partition.yaml#"
- - if:
- properties:
- compatible:
- contains:
- const: sercomm,sc-partitions
- then:
- properties:
- sercomm,scpart-id:
- description: Partition id in Sercomm partition map. Mtd
- parser uses this id to find a record in the partition map
- containing offset and size of the current partition. The
- values from partition map overrides partition offset and
- size defined in reg property of the dts. Frequently these
- values are the same, but may differ if device has bad
- eraseblocks on a flash.
- $ref: /schemas/types.yaml#/definitions/uint32
+ $ref: partition.yaml#
+
+ properties:
+ sercomm,scpart-id:
+ description: Partition id in Sercomm partition map. Mtd parser
+ uses this id to find a record in the partition map containing
+ offset and size of the current partition. The values from
+ partition map overrides partition offset and size defined in
+ reg property of the dts. Frequently these values are the same,
+ but may differ if device has bad eraseblocks on a flash.
+ $ref: /schemas/types.yaml#/definitions/uint32
required:
- "#address-cells"
@@ -84,6 +77,7 @@ examples:
partition@0 {
label = "filesystem";
reg = <0x00000000 0x1 0x00000000>;
+ linux,rootfs;
};
};
diff --git a/Documentation/devicetree/bindings/mtd/partitions/linksys,ns-partitions.yaml b/Documentation/devicetree/bindings/mtd/partitions/linksys,ns-partitions.yaml
index 99249cdfbfb3..213858f60375 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/linksys,ns-partitions.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/linksys,ns-partitions.yaml
@@ -18,6 +18,8 @@ description: |
maintainers:
- Rafał Miłecki <rafal@milecki.pl>
+select: false
+
properties:
compatible:
const: linksys,ns-partitions
diff --git a/Documentation/devicetree/bindings/mtd/partitions/nvmem-cells.yaml b/Documentation/devicetree/bindings/mtd/partitions/nvmem-cells.yaml
index 5cdd2efa9132..5474d63268dc 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/nvmem-cells.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/nvmem-cells.yaml
@@ -17,6 +17,7 @@ maintainers:
- Ansuel Smith <ansuelsmth@gmail.com>
allOf:
+ - $ref: /schemas/mtd/partitions/partition.yaml#
- $ref: /schemas/nvmem/nvmem.yaml#
properties:
@@ -26,7 +27,7 @@ properties:
required:
- compatible
-additionalProperties: true
+unevaluatedProperties: false
examples:
- |
@@ -84,7 +85,6 @@ examples:
compatible = "nvmem-cells";
label = "calibration";
reg = <0xf00000 0x100000>;
- ranges = <0 0xf00000 0x100000>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/Documentation/devicetree/bindings/mtd/partitions/partition.yaml b/Documentation/devicetree/bindings/mtd/partitions/partition.yaml
index f1a02d840b12..cdffbb9cedc2 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/partition.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/partition.yaml
@@ -52,6 +52,10 @@ properties:
immune to paired-pages corruptions
type: boolean
+ linux,rootfs:
+ description: Marks partition that contains root filesystem to mount and boot
+ user space from
+
if:
not:
required: [ reg ]
@@ -60,4 +64,5 @@ then:
$nodename:
pattern: '^partition-.*$'
+# This is a generic file other binding inherit from and extend
additionalProperties: true
diff --git a/Documentation/devicetree/bindings/mtd/partitions/partitions.yaml b/Documentation/devicetree/bindings/mtd/partitions/partitions.yaml
new file mode 100644
index 000000000000..9aca4e6c6047
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/partitions/partitions.yaml
@@ -0,0 +1,41 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mtd/partitions/partitions.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Partitions
+
+description: |
+ This binding is generic and describes the content of the partitions container
+ node. All partition parsers must be referenced here.
+
+maintainers:
+ - Miquel Raynal <miquel.raynal@bootlin.com>
+
+oneOf:
+ - $ref: arm,arm-firmware-suite.yaml
+ - $ref: brcm,bcm4908-partitions.yaml
+ - $ref: brcm,bcm947xx-cfe-partitions.yaml
+ - $ref: fixed-partitions.yaml
+ - $ref: linksys,ns-partitions.yaml
+ - $ref: qcom,smem-part.yaml
+ - $ref: redboot-fis.yaml
+
+properties:
+ compatible: true
+
+ '#address-cells':
+ enum: [1, 2]
+
+ '#size-cells':
+ enum: [1, 2]
+
+patternProperties:
+ "partition(-.+|@[0-9a-f]+)":
+ $ref: partition.yaml
+
+required:
+ - compatible
+
+unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/mtd/partitions/qcom,smem-part.yaml b/Documentation/devicetree/bindings/mtd/partitions/qcom,smem-part.yaml
index dc07909af023..61d12bda356e 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/qcom,smem-part.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/qcom,smem-part.yaml
@@ -15,13 +15,15 @@ description: |
varies between partition table revisions. V3 supports maximum 16 partitions
and V4 supports 48 partitions.
+select: false
+
properties:
compatible:
const: qcom,smem-part
patternProperties:
"^partition-[0-9a-z]+$":
- $ref: partition.yaml#
+ $ref: nvmem-cells.yaml
required:
- compatible
@@ -39,22 +41,22 @@ examples:
- |
/* Example declaring dynamic partition */
flash {
- partitions {
- compatible = "qcom,smem-part";
-
- partition-art {
- compatible = "nvmem-cells";
- #address-cells = <1>;
- #size-cells = <1>;
- label = "0:art";
-
- macaddr_art_0: macaddr@0 {
- reg = <0x0 0x6>;
- };
-
- macaddr_art_6: macaddr@6 {
- reg = <0x6 0x6>;
- };
+ partitions {
+ compatible = "qcom,smem-part";
+
+ partition-art {
+ compatible = "nvmem-cells";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ label = "0:art";
+
+ macaddr_art_0: macaddr@0 {
+ reg = <0x0 0x6>;
+ };
+
+ macaddr_art_6: macaddr@6 {
+ reg = <0x6 0x6>;
+ };
+ };
};
- };
};
diff --git a/Documentation/devicetree/bindings/mtd/partitions/redboot-fis.yaml b/Documentation/devicetree/bindings/mtd/partitions/redboot-fis.yaml
index fee8d81b5276..ba7445cd69e8 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/redboot-fis.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/redboot-fis.yaml
@@ -16,6 +16,8 @@ description: The FLASH Image System (FIS) directory is a flash description
maintainers:
- Linus Walleij <linus.walleij@linaro.org>
+select: false
+
properties:
compatible:
const: redboot-fis
@@ -26,6 +28,10 @@ properties:
device. On a flash memory with 32KB eraseblocks, 0 means the first
eraseblock at 0x00000000, 1 means the second eraseblock at 0x00008000 and so on.
+ '#address-cells': false
+
+ '#size-cells': false
+
required:
- compatible
- fis-index-block
diff --git a/Documentation/devicetree/bindings/mtd/partitions/tplink,safeloader-partitions.yaml b/Documentation/devicetree/bindings/mtd/partitions/tplink,safeloader-partitions.yaml
new file mode 100644
index 000000000000..a24bbaac3a90
--- /dev/null
+++ b/Documentation/devicetree/bindings/mtd/partitions/tplink,safeloader-partitions.yaml
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mtd/partitions/tplink,safeloader-partitions.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TP-Link SafeLoader partitions
+
+description: |
+ TP-Link home routers store various data on flash (e.g. bootloader,
+ flash layout, firmware, product info, configuration, calibration
+ data). That requires flash partitioning.
+
+ Flash space layout of TP-Link devices is stored on flash itself using
+ a custom ASCII-based format. That format was first found in TP-Link
+ devices with a custom SafeLoader bootloader. Later it was adapted to
+ CFE and U-Boot bootloaders.
+
+ Partitions specified in partitions table cover whole flash space. Some
+ contain static data that shouldn't get modified (device's MAC or WiFi
+ calibration data). Others are semi-static (like kernel). Finally some
+ partitions contain fully changeable content (like rootfs).
+
+ This binding describes partitioning method and defines offset of ASCII
+ based partitions table. That offset is picked at manufacturing process
+ and doesn't change.
+
+maintainers:
+ - Rafał Miłecki <rafal@milecki.pl>
+
+properties:
+ compatible:
+ const: tplink,safeloader-partitions
+
+ partitions-table-offset:
+ description: Flash offset of partitions table
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+patternProperties:
+ "^partition-.*$":
+ $ref: partition.yaml#
+
+required:
+ - partitions-table-offset
+
+additionalProperties: false
+
+examples:
+ - |
+ partitions {
+ compatible = "tplink,safeloader-partitions";
+ partitions-table-offset = <0x100000>;
+
+ partition-file-system {
+ linux,rootfs;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/mtd/partitions/u-boot.yaml b/Documentation/devicetree/bindings/mtd/partitions/u-boot.yaml
index 8a88e7d16524..3c56efe48efd 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/u-boot.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/u-boot.yaml
@@ -27,6 +27,10 @@ properties:
Broadcom stores environment variables inside a U-Boot partition. They
can be identified by a custom header with magic value.
+patternProperties:
+ "^partition-.*$":
+ $ref: partition.yaml#
+
unevaluatedProperties: false
examples:
@@ -40,6 +44,9 @@ examples:
compatible = "brcm,u-boot";
reg = <0x0 0x100000>;
label = "u-boot";
+
+ partition-u-boot-env {
+ };
};
partition@100000 {
diff --git a/Documentation/devicetree/bindings/mtd/qcom,nandc.yaml b/Documentation/devicetree/bindings/mtd/qcom,nandc.yaml
index 482a2c068740..07024ee45951 100644
--- a/Documentation/devicetree/bindings/mtd/qcom,nandc.yaml
+++ b/Documentation/devicetree/bindings/mtd/qcom,nandc.yaml
@@ -31,9 +31,6 @@ properties:
- const: core
- const: aon
- "#address-cells": true
- "#size-cells": true
-
patternProperties:
"^nand@[a-f0-9]$":
type: object
@@ -139,85 +136,85 @@ examples:
- |
#include <dt-bindings/clock/qcom,gcc-ipq806x.h>
nand-controller@1ac00000 {
- compatible = "qcom,ipq806x-nand";
- reg = <0x1ac00000 0x800>;
+ compatible = "qcom,ipq806x-nand";
+ reg = <0x1ac00000 0x800>;
- clocks = <&gcc EBI2_CLK>,
- <&gcc EBI2_AON_CLK>;
- clock-names = "core", "aon";
+ clocks = <&gcc EBI2_CLK>,
+ <&gcc EBI2_AON_CLK>;
+ clock-names = "core", "aon";
- dmas = <&adm_dma 3>;
- dma-names = "rxtx";
- qcom,cmd-crci = <15>;
- qcom,data-crci = <3>;
+ dmas = <&adm_dma 3>;
+ dma-names = "rxtx";
+ qcom,cmd-crci = <15>;
+ qcom,data-crci = <3>;
- #address-cells = <1>;
- #size-cells = <0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
- nand@0 {
- reg = <0>;
+ nand@0 {
+ reg = <0>;
- nand-ecc-strength = <4>;
- nand-bus-width = <8>;
+ nand-ecc-strength = <4>;
+ nand-bus-width = <8>;
- qcom,boot-partitions = <0x0 0x58a0000>;
+ qcom,boot-partitions = <0x0 0x58a0000>;
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
- partition@0 {
- label = "boot-nand";
- reg = <0 0x58a0000>;
- };
+ partition@0 {
+ label = "boot-nand";
+ reg = <0 0x58a0000>;
+ };
- partition@58a0000 {
- label = "fs-nand";
- reg = <0x58a0000 0x4000000>;
- };
+ partition@58a0000 {
+ label = "fs-nand";
+ reg = <0x58a0000 0x4000000>;
+ };
+ };
};
- };
};
#include <dt-bindings/clock/qcom,gcc-ipq4019.h>
nand-controller@79b0000 {
- compatible = "qcom,ipq4019-nand";
- reg = <0x79b0000 0x1000>;
-
- clocks = <&gcc GCC_QPIC_CLK>,
- <&gcc GCC_QPIC_AHB_CLK>;
- clock-names = "core", "aon";
-
- dmas = <&qpicbam 0>,
- <&qpicbam 1>,
- <&qpicbam 2>;
- dma-names = "tx", "rx", "cmd";
-
- #address-cells = <1>;
- #size-cells = <0>;
-
- nand@0 {
- reg = <0>;
- nand-ecc-strength = <4>;
- nand-bus-width = <8>;
-
- partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- partition@0 {
- label = "boot-nand";
- reg = <0 0x58a0000>;
- };
-
- partition@58a0000 {
- label = "fs-nand";
- reg = <0x58a0000 0x4000000>;
- };
+ compatible = "qcom,ipq4019-nand";
+ reg = <0x79b0000 0x1000>;
+
+ clocks = <&gcc GCC_QPIC_CLK>,
+ <&gcc GCC_QPIC_AHB_CLK>;
+ clock-names = "core", "aon";
+
+ dmas = <&qpicbam 0>,
+ <&qpicbam 1>,
+ <&qpicbam 2>;
+ dma-names = "tx", "rx", "cmd";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ nand@0 {
+ reg = <0>;
+ nand-ecc-strength = <4>;
+ nand-bus-width = <8>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "boot-nand";
+ reg = <0 0x58a0000>;
+ };
+
+ partition@58a0000 {
+ label = "fs-nand";
+ reg = <0x58a0000 0x4000000>;
+ };
+ };
};
- };
};
...
diff --git a/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml b/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml
index d681a4676f06..566f330851f7 100644
--- a/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml
+++ b/Documentation/devicetree/bindings/mtd/rockchip,nand-controller.yaml
@@ -19,7 +19,9 @@ properties:
- const: rockchip,rk2928-nfc
- const: rockchip,rv1108-nfc
- items:
- - const: rockchip,rk3036-nfc
+ - enum:
+ - rockchip,rk3036-nfc
+ - rockchip,rk3128-nfc
- const: rockchip,rk2928-nfc
- items:
- const: rockchip,rk3308-nfc
diff --git a/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml b/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml
index eab8ea3da1fa..8cbfa1504a0f 100644
--- a/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml
+++ b/Documentation/devicetree/bindings/mtd/st,stm32-fmc2-nand.yaml
@@ -101,31 +101,32 @@ examples:
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
#include <dt-bindings/reset/stm32mp1-resets.h>
+
nand-controller@58002000 {
- compatible = "st,stm32mp15-fmc2";
- reg = <0x58002000 0x1000>,
- <0x80000000 0x1000>,
- <0x88010000 0x1000>,
- <0x88020000 0x1000>,
- <0x81000000 0x1000>,
- <0x89010000 0x1000>,
- <0x89020000 0x1000>;
- interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>,
- <&mdma1 20 0x2 0x12000a08 0x0 0x0>,
- <&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
- dma-names = "tx", "rx", "ecc";
- clocks = <&rcc FMC_K>;
- resets = <&rcc FMC_R>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- nand@0 {
- reg = <0>;
- nand-on-flash-bbt;
+ compatible = "st,stm32mp15-fmc2";
+ reg = <0x58002000 0x1000>,
+ <0x80000000 0x1000>,
+ <0x88010000 0x1000>,
+ <0x88020000 0x1000>,
+ <0x81000000 0x1000>,
+ <0x89010000 0x1000>,
+ <0x89020000 0x1000>;
+ interrupts = <GIC_SPI 48 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&mdma1 20 0x2 0x12000a02 0x0 0x0>,
+ <&mdma1 20 0x2 0x12000a08 0x0 0x0>,
+ <&mdma1 21 0x2 0x12000a0a 0x0 0x0>;
+ dma-names = "tx", "rx", "ecc";
+ clocks = <&rcc FMC_K>;
+ resets = <&rcc FMC_R>;
#address-cells = <1>;
- #size-cells = <1>;
- };
+ #size-cells = <0>;
+
+ nand@0 {
+ reg = <0>;
+ nand-on-flash-bbt;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
};
...
diff --git a/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.yaml b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.yaml
index 30b458c41cac..4774c92e7fc4 100644
--- a/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.yaml
+++ b/Documentation/devicetree/bindings/mtd/ti,am654-hbmc.yaml
@@ -44,26 +44,26 @@ additionalProperties: false
examples:
- |
bus {
- #address-cells = <2>;
- #size-cells = <2>;
-
- hbmc: memory-controller@47034000 {
- compatible = "ti,am654-hbmc";
- reg = <0x0 0x47034000 0x0 0x100>,
- <0x5 0x00000000 0x1 0x0000000>;
- ranges = <0x0 0x0 0x5 0x00000000 0x4000000>, /* CS0 - 64MB */
- <0x1 0x0 0x5 0x04000000 0x4000000>; /* CS1 - 64MB */
- clocks = <&k3_clks 102 0>;
#address-cells = <2>;
- #size-cells = <1>;
- power-domains = <&k3_pds 55>;
- mux-controls = <&hbmc_mux 0>;
+ #size-cells = <2>;
- flash@0,0 {
- compatible = "cypress,hyperflash", "cfi-flash";
- reg = <0x0 0x0 0x4000000>;
- #address-cells = <1>;
+ hbmc: memory-controller@47034000 {
+ compatible = "ti,am654-hbmc";
+ reg = <0x0 0x47034000 0x0 0x100>,
+ <0x5 0x00000000 0x1 0x0000000>;
+ ranges = <0x0 0x0 0x5 0x00000000 0x4000000>, /* CS0 - 64MB */
+ <0x1 0x0 0x5 0x04000000 0x4000000>; /* CS1 - 64MB */
+ clocks = <&k3_clks 102 0>;
+ #address-cells = <2>;
#size-cells = <1>;
+ power-domains = <&k3_pds 55>;
+ mux-controls = <&hbmc_mux 0>;
+
+ flash@0,0 {
+ compatible = "cypress,hyperflash", "cfi-flash";
+ reg = <0x0 0x0 0x4000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
};
- };
};
diff --git a/Documentation/devicetree/bindings/mtd/ti,gpmc-onenand.yaml b/Documentation/devicetree/bindings/mtd/ti,gpmc-onenand.yaml
index a953f7397c40..8a79ad300216 100644
--- a/Documentation/devicetree/bindings/mtd/ti,gpmc-onenand.yaml
+++ b/Documentation/devicetree/bindings/mtd/ti,gpmc-onenand.yaml
@@ -15,6 +15,9 @@ description:
as child nodes of the GPMC controller.
properties:
+ $nodename:
+ pattern: "^onenand@[0-9],[0,9]$"
+
compatible:
const: ti,omap2-onenand
diff --git a/Documentation/devicetree/bindings/net/cdns,macb.yaml b/Documentation/devicetree/bindings/net/cdns,macb.yaml
index 318f4efe7f6f..bef5e0f895be 100644
--- a/Documentation/devicetree/bindings/net/cdns,macb.yaml
+++ b/Documentation/devicetree/bindings/net/cdns,macb.yaml
@@ -203,7 +203,6 @@ examples:
power-domains = <&zynqmp_firmware PD_ETH_1>;
resets = <&zynqmp_reset ZYNQMP_RESET_GEM1>;
reset-names = "gem1_rst";
- status = "okay";
phy-mode = "sgmii";
phys = <&psgtr 1 PHY_TYPE_SGMII 1 1>;
fixed-link {
diff --git a/Documentation/devicetree/bindings/net/micrel,ks8851.yaml b/Documentation/devicetree/bindings/net/micrel,ks8851.yaml
index 5aa7cf2eacb1..b44d83554ef5 100644
--- a/Documentation/devicetree/bindings/net/micrel,ks8851.yaml
+++ b/Documentation/devicetree/bindings/net/micrel,ks8851.yaml
@@ -44,6 +44,7 @@ required:
allOf:
- $ref: ethernet-controller.yaml#
+ - $ref: /schemas/memory-controllers/mc-peripheral-props.yaml#
- if:
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/net/nxp,dwmac-imx.yaml b/Documentation/devicetree/bindings/net/nxp,dwmac-imx.yaml
index 1857cb4b7139..04df496af7e6 100644
--- a/Documentation/devicetree/bindings/net/nxp,dwmac-imx.yaml
+++ b/Documentation/devicetree/bindings/net/nxp,dwmac-imx.yaml
@@ -94,5 +94,4 @@ examples:
<&clk IMX8MP_CLK_ENET_QOS>;
clock-names = "stmmaceth", "pclk", "ptp_ref", "tx";
phy-mode = "rgmii";
- status = "disabled";
};
diff --git a/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.yaml b/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.yaml
index e374aa7891ae..ec20e33d9b8f 100644
--- a/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.yaml
+++ b/Documentation/devicetree/bindings/nvmem/snvs-lpgpr.yaml
@@ -11,14 +11,18 @@ maintainers:
properties:
compatible:
- enum:
- - fsl,imx6q-snvs-lpgpr
- - fsl,imx6ul-snvs-lpgpr
- - fsl,imx7d-snvs-lpgpr
- - fsl,imx8mm-snvs-lpgpr
- - fsl,imx8mn-snvs-lpgpr
- - fsl,imx8mp-snvs-lpgpr
- - fsl,imx8mq-snvs-lpgpr
+ oneOf:
+ - items:
+ - enum:
+ - fsl,imx8mm-snvs-lpgpr
+ - fsl,imx8mn-snvs-lpgpr
+ - fsl,imx8mp-snvs-lpgpr
+ - fsl,imx8mq-snvs-lpgpr
+ - const: fsl,imx7d-snvs-lpgpr
+ - enum:
+ - fsl,imx6q-snvs-lpgpr
+ - fsl,imx6ul-snvs-lpgpr
+ - fsl,imx7d-snvs-lpgpr
required:
- compatible
diff --git a/Documentation/devicetree/bindings/nvmem/u-boot,env.yaml b/Documentation/devicetree/bindings/nvmem/u-boot,env.yaml
index e96bca99f2d9..cbc5c69fd405 100644
--- a/Documentation/devicetree/bindings/nvmem/u-boot,env.yaml
+++ b/Documentation/devicetree/bindings/nvmem/u-boot,env.yaml
@@ -38,6 +38,8 @@ properties:
const: u-boot,env-redundant-bool
- description: Two redundant blocks with active having higher counter
const: u-boot,env-redundant-count
+ - description: Broadcom's variant with custom header
+ const: brcm,env
reg:
maxItems: 1
@@ -73,3 +75,22 @@ examples:
};
};
};
+ - |
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ reg = <0x0 0x100000>;
+ compatible = "brcm,u-boot";
+ label = "u-boot";
+
+ partition-u-boot-env {
+ compatible = "brcm,env";
+
+ ethaddr {
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/opp/allwinner,sun50i-h6-operating-points.yaml b/Documentation/devicetree/bindings/opp/allwinner,sun50i-h6-operating-points.yaml
index 385b0692261c..51f62c3ae194 100644
--- a/Documentation/devicetree/bindings/opp/allwinner,sun50i-h6-operating-points.yaml
+++ b/Documentation/devicetree/bindings/opp/allwinner,sun50i-h6-operating-points.yaml
@@ -41,7 +41,7 @@ required:
- nvmem-cells
patternProperties:
- "opp-[0-9]+":
+ "^opp-[0-9]+$":
type: object
properties:
@@ -49,7 +49,7 @@ patternProperties:
clock-latency-ns: true
patternProperties:
- "opp-microvolt-.*": true
+ "^opp-microvolt-speed[0-9]$": true
required:
- opp-hz
diff --git a/Documentation/devicetree/bindings/opp/opp-v2-base.yaml b/Documentation/devicetree/bindings/opp/opp-v2-base.yaml
index 66d0ec763f0b..cf9c2f7bddc2 100644
--- a/Documentation/devicetree/bindings/opp/opp-v2-base.yaml
+++ b/Documentation/devicetree/bindings/opp/opp-v2-base.yaml
@@ -108,7 +108,7 @@ patternProperties:
The power for the OPP in micro-Watts.
Entries for multiple regulators shall be provided in the same field
- separated by angular brackets <>. If current values aren't required
+ separated by angular brackets <>. If power values aren't required
for a regulator, then it shall be filled with 0. If power values
aren't required for any of the regulators, then this field is not
required. The OPP binding doesn't provide any provisions to relate the
@@ -230,9 +230,9 @@ patternProperties:
minItems: 1
maxItems: 8 # Should be enough regulators
- '^opp-microwatt':
+ '^opp-microwatt-':
description:
- Named opp-microwatt property. Similar to opp-microamp property,
+ Named opp-microwatt property. Similar to opp-microamp-<name> property,
but for microwatt instead.
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
diff --git a/Documentation/devicetree/bindings/opp/opp-v2.yaml b/Documentation/devicetree/bindings/opp/opp-v2.yaml
index eaf8fba2c691..2f05920fce79 100644
--- a/Documentation/devicetree/bindings/opp/opp-v2.yaml
+++ b/Documentation/devicetree/bindings/opp/opp-v2.yaml
@@ -155,7 +155,7 @@ examples:
opp-hz = /bits/ 64 <1200000000>;
opp-microvolt = <1025000>;
opp-microamp = <90000>;
- lock-latency-ns = <290000>;
+ clock-latency-ns = <290000>;
turbo-mode;
};
};
diff --git a/Documentation/devicetree/bindings/pci/mediatek,mt7621-pcie.yaml b/Documentation/devicetree/bindings/pci/mediatek,mt7621-pcie.yaml
index d60f43fd9c5a..e63e6458cea8 100644
--- a/Documentation/devicetree/bindings/pci/mediatek,mt7621-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/mediatek,mt7621-pcie.yaml
@@ -31,7 +31,7 @@ properties:
maxItems: 2
patternProperties:
- 'pcie@[0-2],0':
+ '^pcie@[0-2],0$':
type: object
$ref: /schemas/pci/pci-bus.yaml#
diff --git a/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.yaml b/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.yaml
index 75da3e8eecb9..fe81d52c7277 100644
--- a/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/nvidia,tegra194-pcie.yaml
@@ -27,6 +27,7 @@ properties:
- nvidia,tegra234-pcie
reg:
+ minItems: 4
items:
- description: controller's application logic registers
- description: configuration registers
@@ -35,13 +36,16 @@ properties:
available for software access.
- description: aperture where the Root Port's own configuration
registers are available.
+ - description: aperture to access the configuration space through ECAM.
reg-names:
+ minItems: 4
items:
- const: appl
- const: config
- const: atu_dma
- const: dbi
+ - const: ecam
interrupts:
items:
@@ -202,6 +206,31 @@ properties:
allOf:
- $ref: /schemas/pci/snps,dw-pcie.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - nvidia,tegra194-pcie
+ then:
+ properties:
+ reg:
+ maxItems: 4
+ reg-names:
+ maxItems: 4
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - nvidia,tegra234-pcie
+ then:
+ properties:
+ reg:
+ minItems: 5
+ reg-names:
+ minItems: 5
unevaluatedProperties: false
@@ -305,8 +334,9 @@ examples:
reg = <0x00 0x14160000 0x0 0x00020000>, /* appl registers (128K) */
<0x00 0x36000000 0x0 0x00040000>, /* configuration space (256K) */
<0x00 0x36040000 0x0 0x00040000>, /* iATU_DMA reg space (256K) */
- <0x00 0x36080000 0x0 0x00040000>; /* DBI reg space (256K) */
- reg-names = "appl", "config", "atu_dma", "dbi";
+ <0x00 0x36080000 0x0 0x00040000>, /* DBI reg space (256K) */
+ <0x24 0x30000000 0x0 0x10000000>; /* ECAM (256MB) */
+ reg-names = "appl", "config", "atu_dma", "dbi", "ecam";
#address-cells = <3>;
#size-cells = <2>;
diff --git a/Documentation/devicetree/bindings/pci/renesas,pci-rcar-gen2.yaml b/Documentation/devicetree/bindings/pci/renesas,pci-rcar-gen2.yaml
index 0f18cceba3d5..5a0d64d3ae6b 100644
--- a/Documentation/devicetree/bindings/pci/renesas,pci-rcar-gen2.yaml
+++ b/Documentation/devicetree/bindings/pci/renesas,pci-rcar-gen2.yaml
@@ -65,7 +65,7 @@ properties:
maxItems: 1
patternProperties:
- 'usb@[0-1],0':
+ '^usb@[0-1],0$':
type: object
description:
diff --git a/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml b/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
index 7287d395e1b6..7e0b015f1414 100644
--- a/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/snps,dw-pcie.yaml
@@ -35,7 +35,7 @@ properties:
maxItems: 5
items:
enum: [ dbi, dbi2, config, atu, atu_dma, app, appl, elbi, mgmt, ctrl,
- parf, cfg, link, ulreg, smu, mpu, apb, phy ]
+ parf, cfg, link, ulreg, smu, mpu, apb, phy, ecam ]
num-lanes:
description: |
diff --git a/Documentation/devicetree/bindings/pci/xilinx-nwl-pcie.txt b/Documentation/devicetree/bindings/pci/xilinx-nwl-pcie.txt
deleted file mode 100644
index f56f8c58c5d9..000000000000
--- a/Documentation/devicetree/bindings/pci/xilinx-nwl-pcie.txt
+++ /dev/null
@@ -1,73 +0,0 @@
-* Xilinx NWL PCIe Root Port Bridge DT description
-
-Required properties:
-- compatible: Should contain "xlnx,nwl-pcie-2.11"
-- #address-cells: Address representation for root ports, set to <3>
-- #size-cells: Size representation for root ports, set to <2>
-- #interrupt-cells: specifies the number of cells needed to encode an
- interrupt source. The value must be 1.
-- reg: Should contain Bridge, PCIe Controller registers location,
- configuration space, and length
-- reg-names: Must include the following entries:
- "breg": bridge registers
- "pcireg": PCIe controller registers
- "cfg": configuration space region
-- device_type: must be "pci"
-- interrupts: Should contain NWL PCIe interrupt
-- interrupt-names: Must include the following entries:
- "msi1, msi0": interrupt asserted when an MSI is received
- "intx": interrupt asserted when a legacy interrupt is received
- "misc": interrupt asserted when miscellaneous interrupt is received
-- interrupt-map-mask and interrupt-map: standard PCI properties to define the
- mapping of the PCI interface to interrupt numbers.
-- ranges: ranges for the PCI memory regions (I/O space region is not
- supported by hardware)
- Please refer to the standard PCI bus binding document for a more
- detailed explanation
-- msi-controller: indicates that this is MSI controller node
-- msi-parent: MSI parent of the root complex itself
-- legacy-interrupt-controller: Interrupt controller device node for Legacy
- interrupts
- - interrupt-controller: identifies the node as an interrupt controller
- - #interrupt-cells: should be set to 1
- - #address-cells: specifies the number of cells needed to encode an
- address. The value must be 0.
-
-Optional properties:
-- dma-coherent: present if DMA operations are coherent
-- clocks: Input clock specifier. Refer to common clock bindings
-
-Example:
-++++++++
-
-nwl_pcie: pcie@fd0e0000 {
- #address-cells = <3>;
- #size-cells = <2>;
- compatible = "xlnx,nwl-pcie-2.11";
- #interrupt-cells = <1>;
- msi-controller;
- device_type = "pci";
- interrupt-parent = <&gic>;
- interrupts = <0 114 4>, <0 115 4>, <0 116 4>, <0 117 4>, <0 118 4>;
- interrupt-names = "msi0", "msi1", "intx", "dummy", "misc";
- interrupt-map-mask = <0x0 0x0 0x0 0x7>;
- interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc 0x1>,
- <0x0 0x0 0x0 0x2 &pcie_intc 0x2>,
- <0x0 0x0 0x0 0x3 &pcie_intc 0x3>,
- <0x0 0x0 0x0 0x4 &pcie_intc 0x4>;
-
- msi-parent = <&nwl_pcie>;
- reg = <0x0 0xfd0e0000 0x0 0x1000>,
- <0x0 0xfd480000 0x0 0x1000>,
- <0x80 0x00000000 0x0 0x1000000>;
- reg-names = "breg", "pcireg", "cfg";
- ranges = <0x02000000 0x00000000 0xe0000000 0x00000000 0xe0000000 0x00000000 0x10000000 /* non-prefetchable memory */
- 0x43000000 0x00000006 0x00000000 0x00000006 0x00000000 0x00000002 0x00000000>;/* prefetchable memory */
-
- pcie_intc: legacy-interrupt-controller {
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <1>;
- };
-
-};
diff --git a/Documentation/devicetree/bindings/pci/xilinx-pcie.txt b/Documentation/devicetree/bindings/pci/xilinx-pcie.txt
deleted file mode 100644
index fd57a81180a4..000000000000
--- a/Documentation/devicetree/bindings/pci/xilinx-pcie.txt
+++ /dev/null
@@ -1,88 +0,0 @@
-* Xilinx AXI PCIe Root Port Bridge DT description
-
-Required properties:
-- #address-cells: Address representation for root ports, set to <3>
-- #size-cells: Size representation for root ports, set to <2>
-- #interrupt-cells: specifies the number of cells needed to encode an
- interrupt source. The value must be 1.
-- compatible: Should contain "xlnx,axi-pcie-host-1.00.a"
-- reg: Should contain AXI PCIe registers location and length
-- device_type: must be "pci"
-- interrupts: Should contain AXI PCIe interrupt
-- interrupt-map-mask,
- interrupt-map: standard PCI properties to define the mapping of the
- PCI interface to interrupt numbers.
-- ranges: ranges for the PCI memory regions (I/O space region is not
- supported by hardware)
- Please refer to the standard PCI bus binding document for a more
- detailed explanation
-
-Optional properties for Zynq/Microblaze:
-- bus-range: PCI bus numbers covered
-
-Interrupt controller child node
-+++++++++++++++++++++++++++++++
-Required properties:
-- interrupt-controller: identifies the node as an interrupt controller
-- #address-cells: specifies the number of cells needed to encode an
- address. The value must be 0.
-- #interrupt-cells: specifies the number of cells needed to encode an
- interrupt source. The value must be 1.
-
-NOTE:
-The core provides a single interrupt for both INTx/MSI messages. So,
-created a interrupt controller node to support 'interrupt-map' DT
-functionality. The driver will create an IRQ domain for this map, decode
-the four INTx interrupts in ISR and route them to this domain.
-
-
-Example:
-++++++++
-Zynq:
- pci_express: axi-pcie@50000000 {
- #address-cells = <3>;
- #size-cells = <2>;
- #interrupt-cells = <1>;
- compatible = "xlnx,axi-pcie-host-1.00.a";
- reg = < 0x50000000 0x1000000 >;
- device_type = "pci";
- interrupts = < 0 52 4 >;
- interrupt-map-mask = <0 0 0 7>;
- interrupt-map = <0 0 0 1 &pcie_intc 1>,
- <0 0 0 2 &pcie_intc 2>,
- <0 0 0 3 &pcie_intc 3>,
- <0 0 0 4 &pcie_intc 4>;
- ranges = < 0x02000000 0 0x60000000 0x60000000 0 0x10000000 >;
-
- pcie_intc: interrupt-controller {
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <1>;
- };
- };
-
-
-Microblaze:
- pci_express: axi-pcie@10000000 {
- #address-cells = <3>;
- #size-cells = <2>;
- #interrupt-cells = <1>;
- compatible = "xlnx,axi-pcie-host-1.00.a";
- reg = <0x10000000 0x4000000>;
- device_type = "pci";
- interrupt-parent = <&microblaze_0_intc>;
- interrupts = <1 2>;
- interrupt-map-mask = <0 0 0 7>;
- interrupt-map = <0 0 0 1 &pcie_intc 1>,
- <0 0 0 2 &pcie_intc 2>,
- <0 0 0 3 &pcie_intc 3>,
- <0 0 0 4 &pcie_intc 4>;
- ranges = <0x02000000 0x00000000 0x80000000 0x80000000 0x00000000 0x10000000>;
-
- pcie_intc: interrupt-controller {
- interrupt-controller;
- #address-cells = <0>;
- #interrupt-cells = <1>;
- };
-
- };
diff --git a/Documentation/devicetree/bindings/pci/xlnx,axi-pcie-host.yaml b/Documentation/devicetree/bindings/pci/xlnx,axi-pcie-host.yaml
new file mode 100644
index 000000000000..69b7decabd45
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/xlnx,axi-pcie-host.yaml
@@ -0,0 +1,88 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/xlnx,axi-pcie-host.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx AXI PCIe Root Port Bridge
+
+maintainers:
+ - Thippeswamy Havalige <thippeswamy.havalige@amd.com>
+
+allOf:
+ - $ref: /schemas/pci/pci-bus.yaml#
+
+properties:
+ compatible:
+ const: xlnx,axi-pcie-host-1.00.a
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ ranges:
+ items:
+ - description: |
+ ranges for the PCI memory regions (I/O space region is not
+ supported by hardware)
+
+ "#interrupt-cells":
+ const: 1
+
+ interrupt-controller:
+ description: identifies the node as an interrupt controller
+ type: object
+ properties:
+ interrupt-controller: true
+
+ "#address-cells":
+ const: 0
+
+ "#interrupt-cells":
+ const: 1
+
+ required:
+ - interrupt-controller
+ - "#address-cells"
+ - "#interrupt-cells"
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - ranges
+ - interrupts
+ - interrupt-map
+ - "#interrupt-cells"
+ - interrupt-controller
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ pcie@50000000 {
+ compatible = "xlnx,axi-pcie-host-1.00.a";
+ reg = <0x50000000 0x1000000>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ device_type = "pci";
+ interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie_intc 1>,
+ <0 0 0 2 &pcie_intc 2>,
+ <0 0 0 3 &pcie_intc 3>,
+ <0 0 0 4 &pcie_intc 4>;
+ ranges = <0x02000000 0 0x60000000 0x60000000 0 0x10000000>;
+ pcie_intc: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pci/xlnx,nwl-pcie.yaml b/Documentation/devicetree/bindings/pci/xlnx,nwl-pcie.yaml
new file mode 100644
index 000000000000..897602559b37
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/xlnx,nwl-pcie.yaml
@@ -0,0 +1,149 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pci/xlnx,nwl-pcie.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Xilinx NWL PCIe Root Port Bridge
+
+maintainers:
+ - Thippeswamy Havalige <thippeswamy.havalige@amd.com>
+
+allOf:
+ - $ref: /schemas/pci/pci-bus.yaml#
+ - $ref: /schemas/interrupt-controller/msi-controller.yaml#
+
+properties:
+ compatible:
+ const: xlnx,nwl-pcie-2.11
+
+ reg:
+ items:
+ - description: PCIe bridge registers location.
+ - description: PCIe Controller registers location.
+ - description: PCIe Configuration space region.
+
+ reg-names:
+ items:
+ - const: breg
+ - const: pcireg
+ - const: cfg
+
+ interrupts:
+ items:
+ - description: interrupt asserted when miscellaneous interrupt is received
+ - description: unused interrupt(dummy)
+ - description: interrupt asserted when a legacy interrupt is received
+ - description: msi1 interrupt asserted when an MSI is received
+ - description: msi0 interrupt asserted when an MSI is received
+
+ interrupt-names:
+ items:
+ - const: misc
+ - const: dummy
+ - const: intx
+ - const: msi1
+ - const: msi0
+
+ interrupt-map-mask:
+ items:
+ - const: 0
+ - const: 0
+ - const: 0
+ - const: 7
+
+ "#interrupt-cells":
+ const: 1
+
+ msi-parent:
+ description: MSI controller the device is capable of using.
+
+ interrupt-map:
+ maxItems: 4
+
+ power-domains:
+ maxItems: 1
+
+ iommus:
+ maxItems: 1
+
+ dma-coherent:
+ description: optional, only needed if DMA operations are coherent.
+
+ clocks:
+ maxItems: 1
+ description: optional, input clock specifier.
+
+ legacy-interrupt-controller:
+ description: Interrupt controller node for handling legacy PCI interrupts.
+ type: object
+ properties:
+ "#address-cells":
+ const: 0
+
+ "#interrupt-cells":
+ const: 1
+
+ "interrupt-controller": true
+
+ required:
+ - "#address-cells"
+ - "#interrupt-cells"
+ - interrupt-controller
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - interrupts
+ - "#interrupt-cells"
+ - interrupt-map
+ - interrupt-map-mask
+ - msi-controller
+ - power-domains
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/power/xlnx-zynqmp-power.h>
+ soc {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ nwl_pcie: pcie@fd0e0000 {
+ compatible = "xlnx,nwl-pcie-2.11";
+ reg = <0x0 0xfd0e0000 0x0 0x1000>,
+ <0x0 0xfd480000 0x0 0x1000>,
+ <0x80 0x00000000 0x0 0x1000000>;
+ reg-names = "breg", "pcireg", "cfg";
+ ranges = <0x02000000 0x0 0xe0000000 0x0 0xe0000000 0x0 0x10000000>,
+ <0x43000000 0x00000006 0x0 0x00000006 0x0 0x00000002 0x0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ #interrupt-cells = <1>;
+ msi-controller;
+ device_type = "pci";
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 116 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 115 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "misc", "dummy", "intx", "msi1", "msi0";
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <0x0 0x0 0x0 0x1 &pcie_intc 0x1>,
+ <0x0 0x0 0x0 0x2 &pcie_intc 0x2>,
+ <0x0 0x0 0x0 0x3 &pcie_intc 0x3>,
+ <0x0 0x0 0x0 0x4 &pcie_intc 0x4>;
+ msi-parent = <&nwl_pcie>;
+ power-domains = <&zynqmp_firmware PD_PCIE>;
+ iommus = <&smmu 0x4d0>;
+ pcie_intc: legacy-interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/perf/amlogic,g12-ddr-pmu.yaml b/Documentation/devicetree/bindings/perf/amlogic,g12-ddr-pmu.yaml
new file mode 100644
index 000000000000..50f46a6898b1
--- /dev/null
+++ b/Documentation/devicetree/bindings/perf/amlogic,g12-ddr-pmu.yaml
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/perf/amlogic,g12-ddr-pmu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic G12 DDR performance monitor
+
+maintainers:
+ - Jiucheng Xu <jiucheng.xu@amlogic.com>
+
+description: |
+ Amlogic G12 series SoC integrate DDR bandwidth monitor.
+ A timer is inside and can generate interrupt when timeout.
+ The bandwidth is counted in the timer ISR. Different platform
+ has different subset of event format attribute.
+
+properties:
+ compatible:
+ enum:
+ - amlogic,g12a-ddr-pmu
+ - amlogic,g12b-ddr-pmu
+ - amlogic,sm1-ddr-pmu
+
+ reg:
+ items:
+ - description: DMC bandwidth register space.
+ - description: DMC PLL register space.
+
+ interrupts:
+ items:
+ - description: The IRQ of the inside timer timeout.
+
+required:
+ - compatible
+ - reg
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ pmu {
+ #address-cells=<2>;
+ #size-cells=<2>;
+
+ pmu@ff638000 {
+ compatible = "amlogic,g12a-ddr-pmu";
+ reg = <0x0 0xff638000 0x0 0x100>,
+ <0x0 0xff638c00 0x0 0x100>;
+ interrupts = <GIC_SPI 52 IRQ_TYPE_EDGE_RISING>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/perf/arm,dsu-pmu.yaml b/Documentation/devicetree/bindings/perf/arm,dsu-pmu.yaml
index c87821be158b..a740378ed592 100644
--- a/Documentation/devicetree/bindings/perf/arm,dsu-pmu.yaml
+++ b/Documentation/devicetree/bindings/perf/arm,dsu-pmu.yaml
@@ -32,11 +32,8 @@ properties:
- description: nCLUSTERPMUIRQ interrupt
cpus:
- $ref: /schemas/types.yaml#/definitions/phandle-array
minItems: 1
maxItems: 12
- items:
- maxItems: 1
description: List of phandles for the CPUs connected to this DSU instance.
required:
diff --git a/Documentation/devicetree/bindings/phy/intel,phy-thunderbay-emmc.yaml b/Documentation/devicetree/bindings/phy/intel,phy-thunderbay-emmc.yaml
index 34bdb5c4cae8..b09e5ba5e127 100644
--- a/Documentation/devicetree/bindings/phy/intel,phy-thunderbay-emmc.yaml
+++ b/Documentation/devicetree/bindings/phy/intel,phy-thunderbay-emmc.yaml
@@ -36,11 +36,10 @@ additionalProperties: false
examples:
- |
- mmc_phy@80440800 {
- #phy-cells = <0x0>;
- compatible = "intel,thunderbay-emmc-phy";
- status = "okay";
- reg = <0x80440800 0x100>;
- clocks = <&emmc>;
- clock-names = "emmcclk";
- };
+ mmc_phy@80440800 {
+ #phy-cells = <0x0>;
+ compatible = "intel,thunderbay-emmc-phy";
+ reg = <0x80440800 0x100>;
+ clocks = <&emmc>;
+ clock-names = "emmcclk";
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/fsl,imxrt1050.yaml b/Documentation/devicetree/bindings/pinctrl/fsl,imxrt1050.yaml
index 1278f7293560..db5fe66ad873 100644
--- a/Documentation/devicetree/bindings/pinctrl/fsl,imxrt1050.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/fsl,imxrt1050.yaml
@@ -35,7 +35,7 @@ patternProperties:
each entry consists of 6 integers and represents the mux and config
setting for one pin. The first 5 integers <mux_reg conf_reg input_reg
mux_val input_val> are specified using a PIN_FUNC_ID macro, which can
- be found in <include/dt-bindings/pinctrl/pins-imxrt1050.h>. The last
+ be found in <arch/arm/boot/dts/imxrt1050-pinfunc.h>. The last
integer CONFIG is the pad setting value like pull-up on this pin. Please
refer to i.MXRT1050 Reference Manual for detailed CONFIG settings.
$ref: /schemas/types.yaml#/definitions/uint32-matrix
diff --git a/Documentation/devicetree/bindings/pinctrl/loongson,ls2k-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/loongson,ls2k-pinctrl.yaml
new file mode 100644
index 000000000000..bd8a45843566
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/loongson,ls2k-pinctrl.yaml
@@ -0,0 +1,123 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/loongson,ls2k-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Loongson-2 SoC Pinctrl Controller
+
+maintainers:
+ - zhanghongchen <zhanghongchen@loongson.cn>
+ - Yinbo Zhu <zhuyinbo@loongson.cn>
+
+allOf:
+ - $ref: pinctrl.yaml#
+
+properties:
+ compatible:
+ const: loongson,ls2k-pinctrl
+
+ reg:
+ maxItems: 1
+
+patternProperties:
+ '-pins$':
+ type: object
+
+ additionalProperties: false
+
+ patternProperties:
+ 'pinmux$':
+ type: object
+ description: node for pinctrl.
+ $ref: pinmux-node.yaml#
+
+ unevaluatedProperties: false
+
+ properties:
+ groups:
+ description:
+ One or more groups of pins to mux to a certain function
+ items:
+ enum: [gpio, sdio, can1, can0, pwm3, pwm2, pwm1, pwm0, i2c1, i2c0,
+ nand, sata_led, i2s, hda]
+ function:
+ description:
+ The function that a group of pins is muxed to
+ enum: [gpio, sdio, can1, can0, pwm3, pwm2, pwm1, pwm0, i2c1, i2c0,
+ nand, sata_led, i2s, hda]
+
+ required:
+ - groups
+ - function
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ pctrl: pinctrl@1fe00420 {
+ compatible = "loongson,ls2k-pinctrl";
+ reg = <0x1fe00420 0x18>;
+ sdio_pins_default: sdio-pins {
+ sdio-pinmux {
+ groups = "sdio";
+ function = "sdio";
+ };
+
+ sdio-det-pinmux {
+ groups = "pwm2";
+ function = "gpio";
+ };
+ };
+
+ pwm1_pins_default: pwm1-pins {
+ pinmux {
+ groups = "pwm1";
+ function = "pwm1";
+ };
+ };
+
+ pwm0_pins_default: pwm0-pins {
+ pinmux {
+ groups = "pwm0";
+ function = "pwm0";
+ };
+ };
+
+ i2c1_pins_default: i2c1-pins {
+ pinmux {
+ groups = "i2c1";
+ function = "i2c1";
+ };
+ };
+
+ i2c0_pins_default: i2c0-pins {
+ pinmux {
+ groups = "i2c0";
+ function = "i2c0";
+ };
+ };
+
+ nand_pins_default: nand-pins {
+ pinmux {
+ groups = "nand";
+ function = "nand";
+ };
+ };
+
+ hda_pins_default: hda-pins {
+ grp0-pinmux {
+ groups = "hda";
+ function = "hda";
+ };
+
+ grp1-pinmux {
+ groups = "i2s";
+ function = "gpio";
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
index 33b5f79e741a..1b44335b1e94 100644
--- a/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
@@ -31,7 +31,8 @@ properties:
pins-are-numbered:
$ref: /schemas/types.yaml#/definitions/flag
description: |
- Specify the subnodes are using numbered pinmux to specify pins.
+ Specify the subnodes are using numbered pinmux to specify pins. (UNUSED)
+ deprecated: true
gpio-controller: true
@@ -62,7 +63,6 @@ properties:
required:
- compatible
- - pins-are-numbered
- gpio-controller
- "#gpio-cells"
@@ -150,7 +150,6 @@ examples:
compatible = "mediatek,mt8135-pinctrl";
reg = <0 0x1000B000 0 0x1000>;
mediatek,pctl-regmap = <&syscfg_pctl_a>, <&syscfg_pctl_b>;
- pins-are-numbered;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt6779-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt6779-pinctrl.yaml
index 8c79fcef7c52..a2141eb0854e 100644
--- a/Documentation/devicetree/bindings/pinctrl/mediatek,mt6779-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt6779-pinctrl.yaml
@@ -8,31 +8,22 @@ title: Mediatek MT6779 Pin Controller
maintainers:
- Andy Teng <andy.teng@mediatek.com>
+ - Sean Wang <sean.wang@kernel.org>
-description: |+
- The pin controller node should be the child of a syscon node with the
- required property:
- - compatible: "syscon"
+description:
+ The MediaTek pin controller on MT6779 is used to control pin
+ functions, pull up/down resistance and drive strength options.
properties:
compatible:
- const: mediatek,mt6779-pinctrl
+ enum:
+ - mediatek,mt6779-pinctrl
+ - mediatek,mt6797-pinctrl
reg:
- minItems: 9
- maxItems: 9
-
- reg-names:
- items:
- - const: "gpio"
- - const: "iocfg_rm"
- - const: "iocfg_br"
- - const: "iocfg_lm"
- - const: "iocfg_lb"
- - const: "iocfg_rt"
- - const: "iocfg_lt"
- - const: "iocfg_tl"
- - const: "eint"
+ description: Physical addresses for GPIO base(s) and EINT registers.
+
+ reg-names: true
gpio-controller: true
@@ -59,19 +50,65 @@ properties:
"#interrupt-cells":
const: 2
-allOf:
- - $ref: "pinctrl.yaml#"
-
required:
- compatible
- reg
- reg-names
- gpio-controller
- "#gpio-cells"
- - gpio-ranges
- - interrupt-controller
- - interrupts
- - "#interrupt-cells"
+
+allOf:
+ - $ref: "pinctrl.yaml#"
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: mediatek,mt6779-pinctrl
+ then:
+ properties:
+ reg:
+ minItems: 9
+ maxItems: 9
+
+ reg-names:
+ items:
+ - const: gpio
+ - const: iocfg_rm
+ - const: iocfg_br
+ - const: iocfg_lm
+ - const: iocfg_lb
+ - const: iocfg_rt
+ - const: iocfg_lt
+ - const: iocfg_tl
+ - const: eint
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: mediatek,mt6797-pinctrl
+ then:
+ properties:
+ reg:
+ minItems: 5
+ maxItems: 5
+
+ reg-names:
+ items:
+ - const: gpio
+ - const: iocfgl
+ - const: iocfgb
+ - const: iocfgr
+ - const: iocfgt
+ - if:
+ properties:
+ reg-names:
+ contains:
+ const: eint
+ then:
+ required:
+ - interrupts
+ - interrupt-controller
+ - "#interrupt-cells"
patternProperties:
'-[0-9]*$':
@@ -113,6 +150,12 @@ patternProperties:
input-schmitt-disable: true
+ drive-strength:
+ enum: [2, 4, 8, 12, 16]
+
+ slew-rate:
+ enum: [0, 1]
+
mediatek,pull-up-adv:
description: |
Pull up setings for 2 pull resistors, R0 and R1. User can
diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt6797-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt6797-pinctrl.yaml
deleted file mode 100644
index 637a8386e23e..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/mediatek,mt6797-pinctrl.yaml
+++ /dev/null
@@ -1,176 +0,0 @@
-# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/pinctrl/mediatek,mt6797-pinctrl.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: Mediatek MT6797 Pin Controller
-
-maintainers:
- - Sean Wang <sean.wang@kernel.org>
-
-description: |+
- The MediaTek's MT6797 Pin controller is used to control SoC pins.
-
-properties:
- compatible:
- const: mediatek,mt6797-pinctrl
-
- reg:
- minItems: 5
- maxItems: 5
-
- reg-names:
- items:
- - const: gpio
- - const: iocfgl
- - const: iocfgb
- - const: iocfgr
- - const: iocfgt
-
- gpio-controller: true
-
- "#gpio-cells":
- const: 2
- description: |
- Number of cells in GPIO specifier. Since the generic GPIO
- binding is used, the amount of cells must be specified as 2. See the below
- mentioned gpio binding representation for description of particular cells.
-
- interrupt-controller: true
-
- interrupts:
- maxItems: 1
-
- "#interrupt-cells":
- const: 2
-
-allOf:
- - $ref: "pinctrl.yaml#"
-
-required:
- - compatible
- - reg
- - reg-names
- - gpio-controller
- - "#gpio-cells"
-
-patternProperties:
- '-[0-9]+$':
- type: object
- additionalProperties: false
- patternProperties:
- 'pins':
- type: object
- additionalProperties: false
- description: |
- A pinctrl node should contain at least one subnodes representing the
- pinctrl groups available on the machine. Each subnode will list the
- pins it needs, and how they should be configured, with regard to muxer
- configuration, pullups, drive strength, input enable/disable and input
- schmitt.
- $ref: "/schemas/pinctrl/pincfg-node.yaml"
-
- properties:
- pinmux:
- description:
- integer array, represents gpio pin number and mux setting.
- Supported pin number and mux varies for different SoCs, and are
- defined as macros in <soc>-pinfunc.h directly.
-
- bias-disable: true
-
- bias-pull-up: true
-
- bias-pull-down: true
-
- input-enable: true
-
- input-disable: true
-
- output-enable: true
-
- output-low: true
-
- output-high: true
-
- input-schmitt-enable: true
-
- input-schmitt-disable: true
-
- drive-strength:
- enum: [2, 4, 8, 12, 16]
-
- slew-rate:
- enum: [0, 1]
-
- mediatek,pull-up-adv:
- description: |
- Pull up setings for 2 pull resistors, R0 and R1. User can
- configure those special pins. Valid arguments are described as below:
- 0: (R1, R0) = (0, 0) which means R1 disabled and R0 disabled.
- 1: (R1, R0) = (0, 1) which means R1 disabled and R0 enabled.
- 2: (R1, R0) = (1, 0) which means R1 enabled and R0 disabled.
- 3: (R1, R0) = (1, 1) which means R1 enabled and R0 enabled.
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [0, 1, 2, 3]
-
- mediatek,pull-down-adv:
- description: |
- Pull down settings for 2 pull resistors, R0 and R1. User can
- configure those special pins. Valid arguments are described as below:
- 0: (R1, R0) = (0, 0) which means R1 disabled and R0 disabled.
- 1: (R1, R0) = (0, 1) which means R1 disabled and R0 enabled.
- 2: (R1, R0) = (1, 0) which means R1 enabled and R0 disabled.
- 3: (R1, R0) = (1, 1) which means R1 enabled and R0 enabled.
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [0, 1, 2, 3]
-
- mediatek,tdsel:
- description: |
- An integer describing the steps for output level shifter duty
- cycle when asserted (high pulse width adjustment). Valid arguments
- are from 0 to 15.
- $ref: /schemas/types.yaml#/definitions/uint32
-
- mediatek,rdsel:
- description: |
- An integer describing the steps for input level shifter duty cycle
- when asserted (high pulse width adjustment). Valid arguments are
- from 0 to 63.
- $ref: /schemas/types.yaml#/definitions/uint32
-
- required:
- - pinmux
-
-additionalProperties: false
-
-examples:
- - |
- #include <dt-bindings/interrupt-controller/irq.h>
- #include <dt-bindings/interrupt-controller/arm-gic.h>
- #include <dt-bindings/pinctrl/mt6797-pinfunc.h>
-
- soc {
- #address-cells = <2>;
- #size-cells = <2>;
-
- pio: pinctrl@10005000 {
- compatible = "mediatek,mt6797-pinctrl";
- reg = <0 0x10005000 0 0x1000>,
- <0 0x10002000 0 0x400>,
- <0 0x10002400 0 0x400>,
- <0 0x10002800 0 0x400>,
- <0 0x10002C00 0 0x400>;
- reg-names = "gpio", "iocfgl", "iocfgb", "iocfgr", "iocfgt";
- gpio-controller;
- #gpio-cells = <2>;
-
- uart_pins_a: uart-0 {
- pins1 {
- pinmux = <MT6797_GPIO232__FUNC_URXD1>,
- <MT6797_GPIO233__FUNC_UTXD1>;
- };
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,mt7986-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,mt7986-pinctrl.yaml
index 89b8f3dd67a1..216b356cd519 100644
--- a/Documentation/devicetree/bindings/pinctrl/mediatek,mt7986-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/mediatek,mt7986-pinctrl.yaml
@@ -87,6 +87,8 @@ patternProperties:
"wifi_led" "led" 1, 2
"i2c" "i2c" 3, 4
"uart1_0" "uart" 7, 8, 9, 10
+ "uart1_rx_tx" "uart" 42, 43
+ "uart1_cts_rts" "uart" 44, 45
"pcie_clk" "pcie" 9
"pcie_wake" "pcie" 10
"spi1_0" "spi" 11, 12, 13, 14
@@ -98,9 +100,11 @@ patternProperties:
"emmc_45" "emmc" 22, 23, 24, 25, 26, 27, 28, 29, 30,
31, 32
"spi1_1" "spi" 23, 24, 25, 26
- "uart1_2" "uart" 29, 30, 31, 32
+ "uart1_2_rx_tx" "uart" 29, 30
+ "uart1_2_cts_rts" "uart" 31, 32
"uart1_1" "uart" 23, 24, 25, 26
- "uart2_0" "uart" 29, 30, 31, 32
+ "uart2_0_rx_tx" "uart" 29, 30
+ "uart2_0_cts_rts" "uart" 31, 32
"spi0" "spi" 33, 34, 35, 36
"spi0_wp_hold" "spi" 37, 38
"uart1_3_rx_tx" "uart" 35, 36
@@ -157,7 +161,7 @@ patternProperties:
then:
properties:
groups:
- enum: [emmc, emmc_rst]
+ enum: [emmc_45, emmc_51]
- if:
properties:
function:
@@ -197,7 +201,9 @@ patternProperties:
then:
properties:
groups:
- enum: [pcie_clk, pcie_wake, pcie_pereset]
+ items:
+ enum: [pcie_clk, pcie_wake, pcie_pereset]
+ maxItems: 3
- if:
properties:
function:
@@ -205,7 +211,9 @@ patternProperties:
then:
properties:
groups:
- enum: [pwm0, pwm1_0, pwm1_1]
+ items:
+ enum: [pwm0, pwm1_0, pwm1_1]
+ maxItems: 2
- if:
properties:
function:
@@ -213,7 +221,9 @@ patternProperties:
then:
properties:
groups:
- enum: [spi0, spi0_wp_hold, spi1_0, spi1_1, spi1_2, spi1_3]
+ items:
+ enum: [spi0, spi0_wp_hold, spi1_0, spi1_1, spi1_2, spi1_3]
+ maxItems: 2
- if:
properties:
function:
@@ -221,8 +231,12 @@ patternProperties:
then:
properties:
groups:
- enum: [uart1_0, uart1_1, uart1_2, uart1_3_rx_tx,
- uart1_3_cts_rts, uart2_0, uart2_1, uart0, uart1, uart2]
+ items:
+ enum: [uart1_0, uart1_rx_tx, uart1_cts_rts, uart1_1,
+ uart1_2_rx_tx, uart1_2_cts_rts, uart1_3_rx_tx,
+ uart1_3_cts_rts, uart2_0_rx_tx, uart2_0_cts_rts,
+ uart2_1, uart0, uart1, uart2]
+ maxItems: 2
- if:
properties:
function:
@@ -278,9 +292,23 @@ patternProperties:
bias-disable: true
- bias-pull-up: true
-
- bias-pull-down: true
+ bias-pull-up:
+ oneOf:
+ - type: boolean
+ description: normal pull up.
+ - enum: [100, 101, 102, 103]
+ description: |
+ PUPD/R1/R0 pull down type. See MTK_PUPD_SET_R1R0 defines in
+ dt-bindings/pinctrl/mt65xx.h.
+
+ bias-pull-down:
+ oneOf:
+ - type: boolean
+ description: normal pull down.
+ - enum: [100, 101, 102, 103]
+ description: |
+ PUPD/R1/R0 pull down type. See MTK_PUPD_SET_R1R0 defines in
+ dt-bindings/pinctrl/mt65xx.h.
input-enable: true
@@ -332,6 +360,7 @@ examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/pinctrl/mt65xx.h>
soc {
#address-cells = <2>;
@@ -356,6 +385,27 @@ examples:
interrupt-parent = <&gic>;
#interrupt-cells = <2>;
+ pcie_pins: pcie-pins {
+ mux {
+ function = "pcie";
+ groups = "pcie_clk", "pcie_wake", "pcie_pereset";
+ };
+ };
+
+ pwm_pins: pwm-pins {
+ mux {
+ function = "pwm";
+ groups = "pwm0", "pwm1_0";
+ };
+ };
+
+ spi0_pins: spi0-pins {
+ mux {
+ function = "spi";
+ groups = "spi0", "spi0_wp_hold";
+ };
+ };
+
uart1_pins: uart1-pins {
mux {
function = "uart";
@@ -363,6 +413,13 @@ examples:
};
};
+ uart1_3_pins: uart1-3-pins {
+ mux {
+ function = "uart";
+ groups = "uart1_3_rx_tx", "uart1_3_cts_rts";
+ };
+ };
+
uart2_pins: uart2-pins {
mux {
function = "uart";
@@ -370,5 +427,34 @@ examples:
};
};
+ mmc0_pins_default: mmc0-pins {
+ mux {
+ function = "emmc";
+ groups = "emmc_51";
+ };
+ conf-cmd-dat {
+ pins = "EMMC_DATA_0", "EMMC_DATA_1", "EMMC_DATA_2",
+ "EMMC_DATA_3", "EMMC_DATA_4", "EMMC_DATA_5",
+ "EMMC_DATA_6", "EMMC_DATA_7", "EMMC_CMD";
+ input-enable;
+ drive-strength = <4>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>; /* pull-up 10K */
+ };
+ conf-clk {
+ pins = "EMMC_CK";
+ drive-strength = <6>;
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>; /* pull-down 50K */
+ };
+ conf-ds {
+ pins = "EMMC_DSL";
+ bias-pull-down = <MTK_PUPD_SET_R1R0_10>; /* pull-down 50K */
+ };
+ conf-rst {
+ pins = "EMMC_RSTB";
+ drive-strength = <4>;
+ bias-pull-up = <MTK_PUPD_SET_R1R0_01>; /* pull-up 10K */
+ };
+ };
+
};
};
diff --git a/Documentation/devicetree/bindings/pinctrl/mediatek,pinctrl-mt6795.yaml b/Documentation/devicetree/bindings/pinctrl/mediatek,pinctrl-mt6795.yaml
index 73ae6e11410b..9399e0215526 100644
--- a/Documentation/devicetree/bindings/pinctrl/mediatek,pinctrl-mt6795.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/mediatek,pinctrl-mt6795.yaml
@@ -46,8 +46,11 @@ properties:
const: 2
interrupts:
- description: The interrupt outputs to sysirq.
- maxItems: 1
+ description: Interrupt outputs to the system interrupt controller (sysirq).
+ minItems: 1
+ items:
+ - description: EINT interrupt
+ - description: EINT event_b interrupt
# PIN CONFIGURATION NODES
patternProperties:
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra-pinmux-common.yaml b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra-pinmux-common.yaml
new file mode 100644
index 000000000000..96c608bcb87e
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra-pinmux-common.yaml
@@ -0,0 +1,178 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/nvidia,tegra-pinmux-common.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Tegra Pinmux Controller
+
+maintainers:
+ - Thierry Reding <thierry.reding@gmail.com>
+ - Jonathan Hunter <jonathanh@nvidia.com>
+
+description: |
+ Please refer to pinctrl-bindings.txt in this directory for details of the
+ common pinctrl bindings used by client devices, including the meaning of
+ the phrase "pin configuration node".
+
+ Tegra's pin configuration nodes act as a container for an arbitrary number
+ of subnodes. Each of these subnodes represents some desired configuration
+ for a pin, a group, or a list of pins or groups. This configuration can
+ include the mux function to select on those pin(s)/ group(s), and various
+ pin configuration parameters, such as pull-up, tristate, drive strength,
+ etc.
+
+ The name of each subnode is not important; all subnodes should be
+ enumerated and processed purely based on their content.
+
+ Each subnode only affects those parameters that are explicitly listed. In
+ other words, a subnode that lists a mux function but no pin configuration
+ parameters implies no information about any pin configuration parameters.
+
+ Similarly, a pin subnode that describes a pullup parameter implies no
+ information about e.g. the mux function or tristate parameter. For this
+ reason, even seemingly boolean values are actually tristates in this
+ binding: unspecified, off, or on. Unspecified is represented as an absent
+ property, and off/on are represented as integer values 0 and 1.
+
+ Note that many of these properties are only valid for certain specific pins
+ or groups. See the Tegra TRM and various pinmux spreadsheets for complete
+ details regarding which groups support which functionality. The Linux
+ pinctrl driver may also be a useful reference, since it consolidates,
+ disambiguates, and corrects data from all those sources.
+
+properties:
+ nvidia,pins:
+ $ref: /schemas/types.yaml#/definitions/string-array
+ description: An array of strings. Each string contains the name of a pin
+ or group. Valid values for these names are listed below.
+
+ nvidia,function:
+ $ref: /schemas/types.yaml#/definitions/string
+ description: A string containing the name of the function to mux to the
+ pin or group. Valid values for function names are listed below. See the
+ Tegra TRM to determine which are valid for each pin or group.
+
+ nvidia,pull:
+ description: Pull-down/up setting to apply to the pin.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ oneOf:
+ - description: none
+ const: 0
+ - description: down
+ const: 1
+ - description: up
+ const: 2
+
+ nvidia,tristate:
+ description: Tristate setting to apply to the pin.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ oneOf:
+ - description: drive
+ const: 0
+ - description: tristate
+ const: 1
+
+ nvidia,schmitt:
+ description: Enable Schmitt trigger on the input.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ oneOf:
+ - description: disable Schmitt trigger on the input
+ const: 0
+ - description: enable Schmitt trigger on the input
+ const: 1
+
+ nvidia,pull-down-strength:
+ description: Controls drive strength. 0 is weakest. The range of valid
+ values depends on the pingroup. See "CAL_DRVDN" in the Tegra TRM.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ nvidia,pull-up-strength:
+ description: Controls drive strength. 0 is weakest. The range of valid
+ values depends on the pingroup. See "CAL_DRVUP" in the Tegra TRM.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ nvidia,high-speed-mode:
+ description: Enable high speed mode the pins.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ oneOf:
+ - description: normal speed mode
+ const: 0
+ - description: high speed mode
+ const: 1
+
+ nvidia,low-power-mode:
+ description: Controls the drive power or current. Valid values are from 0
+ through 3, where 0 specifies the least power and 3 specifies the most
+ power. See "Low Power Mode" or "LPMD1" and "LPMD0" in the Tegra TRM.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [ 0, 1, 2, 3 ]
+
+ nvidia,enable-input:
+ description: Enable the pin's input path.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ oneOf:
+ - description: disable input (i.e. output only)
+ const: 0
+ - description: enable input
+ const: 1
+
+ nvidia,open-drain:
+ description: Open-drain configuration for the pin.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ oneOf:
+ - description: disable open-drain
+ const: 0
+ - description: enable open-drain
+ const: 1
+
+ nvidia,lock:
+ description: Lock the pin configuration against further changes until
+ reset.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ oneOf:
+ - description: disable pin configuration lock
+ const: 0
+ - description: enable pin configuration lock
+ const: 1
+
+ nvidia,io-reset:
+ description: reset the I/O path
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [ 0, 1 ]
+
+ nvidia,rcv-sel:
+ description: select VIL/VIH receivers
+ $ref: /schemas/types.yaml#/definitions/uint32
+ oneOf:
+ - description: normal receivers
+ const: 0
+ - description: high-voltage receivers
+ const: 1
+
+ nvidia,drive-type:
+ description: Drive type to configure for the pin.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ enum: [ 0, 1, 2, 3 ]
+
+ nvidia,io-hv:
+ description: Select high-voltage receivers.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ oneOf:
+ - description: Use normal receivers.
+ const: 0
+ - description: Use high-voltage receivers.
+ const: 1
+
+ nvidia,slew-rate-rising:
+ description: Controls rising signal slew rate. 0 is fastest. The range of
+ valid values depends on the pingroup. See "DRVDN_SLWR" in the Tegra TRM.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+ nvidia,slew-rate-falling:
+ description: Controls falling signal slew rate. 0 is fastest. The range of
+ valid values depends on the pingroup. See "DRVUP_SLWF" in the Tegra TRM.
+ $ref: /schemas/types.yaml#/definitions/uint32
+
+additionalProperties: true
+...
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra114-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra114-pinmux.txt
deleted file mode 100644
index fb70856c5b51..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra114-pinmux.txt
+++ /dev/null
@@ -1,131 +0,0 @@
-NVIDIA Tegra114 pinmux controller
-
-The Tegra114 pinctrl binding is very similar to the Tegra20 and Tegra30
-pinctrl binding, as described in nvidia,tegra20-pinmux.txt and
-nvidia,tegra30-pinmux.txt. In fact, this document assumes that binding as
-a baseline, and only documents the differences between the two bindings.
-
-Required properties:
-- compatible: "nvidia,tegra114-pinmux"
-- reg: Should contain the register physical address and length for each of
- the pad control and mux registers. The first bank of address must be the
- driver strength pad control register address and second bank address must
- be pinmux register address.
-
-Tegra114 adds the following optional properties for pin configuration subnodes:
-- nvidia,enable-input: Integer. Enable the pin's input path. 0: no, 1: yes.
-- nvidia,open-drain: Integer. Enable open drain mode. 0: no, 1: yes.
-- nvidia,lock: Integer. Lock the pin configuration against further changes
- until reset. 0: no, 1: yes.
-- nvidia,io-reset: Integer. Reset the IO path. 0: no, 1: yes.
-- nvidia,rcv-sel: Integer. Select VIL/VIH receivers. 0: normal, 1: high.
-- nvidia,drive-type: Integer. Valid range 0...3.
-
-As with Tegra20 and Terga30, see the Tegra TRM for complete details regarding
-which groups support which functionality.
-
-Valid values for pin and group names are:
-
- per-pin mux groups:
-
- These all support nvidia,function, nvidia,tristate, nvidia,pull,
- nvidia,enable-input, nvidia,lock. Some support nvidia,open-drain,
- nvidia,io-reset and nvidia,rcv-sel.
-
- ulpi_data0_po1, ulpi_data1_po2, ulpi_data2_po3, ulpi_data3_po4,
- ulpi_data4_po5, ulpi_data5_po6, ulpi_data6_po7, ulpi_data7_po0,
- ulpi_clk_py0, ulpi_dir_py1, ulpi_nxt_py2, ulpi_stp_py3, dap3_fs_pp0,
- dap3_din_pp1, dap3_dout_pp2, dap3_sclk_pp3, pv0, pv1, sdmmc1_clk_pz0,
- sdmmc1_cmd_pz1, sdmmc1_dat3_py4, sdmmc1_dat2_py5, sdmmc1_dat1_py6,
- sdmmc1_dat0_py7, clk2_out_pw5, clk2_req_pcc5, hdmi_int_pn7, ddc_scl_pv4,
- ddc_sda_pv5, uart2_rxd_pc3, uart2_txd_pc2, uart2_rts_n_pj6,
- uart2_cts_n_pj5, uart3_txd_pw6, uart3_rxd_pw7, uart3_cts_n_pa1,
- uart3_rts_n_pc0, pu0, pu1, pu2, pu3, pu4, pu5, pu6, gen1_i2c_sda_pc5,
- gen1_i2c_scl_pc4, dap4_fs_pp4, dap4_din_pp5, dap4_dout_pp6, dap4_sclk_pp7,
- clk3_out_pee0, clk3_req_pee1, gmi_wp_n_pc7, gmi_iordy_pi5, gmi_wait_pi7,
- gmi_adv_n_pk0, gmi_clk_pk1, gmi_cs0_n_pj0, gmi_cs1_n_pj2, gmi_cs2_n_pk3,
- gmi_cs3_n_pk4, gmi_cs4_n_pk2, gmi_cs6_n_pi3, gmi_cs7_n_pi6, gmi_ad0_pg0,
- gmi_ad1_pg1, gmi_ad2_pg2, gmi_ad3_pg3, gmi_ad4_pg4, gmi_ad5_pg5,
- gmi_ad6_pg6, gmi_ad7_pg7, gmi_ad8_ph0, gmi_ad9_ph1, gmi_ad10_ph2,
- gmi_ad11_ph3, gmi_ad12_ph4, gmi_ad13_ph5, gmi_ad14_ph6, gmi_ad15_ph7,
- gmi_a16_pj7, gmi_a17_pb0, gmi_a18_pb1, gmi_a19_pk7, gmi_wr_n_pi0,
- gmi_oe_n_pi1, gmi_dqs_p_pj3, gmi_rst_n_pi4, gen2_i2c_scl_pt5,
- gen2_i2c_sda_pt6, sdmmc4_clk_pcc4, sdmmc4_cmd_pt7, sdmmc4_dat0_paa0,
- sdmmc4_dat1_paa1, sdmmc4_dat2_paa2, sdmmc4_dat3_paa3, sdmmc4_dat4_paa4,
- sdmmc4_dat5_paa5, sdmmc4_dat6_paa6, sdmmc4_dat7_paa7, cam_mclk_pcc0,
- pcc1, pbb0, cam_i2c_scl_pbb1, cam_i2c_sda_pbb2, pbb3, pbb4, pbb5, pbb6,
- pbb7, pcc2, pwr_i2c_scl_pz6, pwr_i2c_sda_pz7, kb_row0_pr0, kb_row1_pr1,
- kb_row2_pr2, kb_row3_pr3, kb_row4_pr4, kb_row5_pr5, kb_row6_pr6,
- kb_row7_pr7, kb_row8_ps0, kb_row9_ps1, kb_row10_ps2, kb_col0_pq0,
- kb_col1_pq1, kb_col2_pq2, kb_col3_pq3, kb_col4_pq4, kb_col5_pq5,
- kb_col6_pq6, kb_col7_pq7, clk_32k_out_pa0, sys_clk_req_pz5, core_pwr_req,
- cpu_pwr_req, pwr_int_n, owr, dap1_fs_pn0, dap1_din_pn1, dap1_dout_pn2,
- dap1_sclk_pn3, clk1_req_pee2, clk1_out_pw4, spdif_in_pk6, spdif_out_pk5,
- dap2_fs_pa2, dap2_din_pa4, dap2_dout_pa5, dap2_sclk_pa3, dvfs_pwm_px0,
- gpio_x1_aud_px1, gpio_x3_aud_px3, dvfs_clk_px2, gpio_x4_aud_px4,
- gpio_x5_aud_px5, gpio_x6_aud_px6, gpio_x7_aud_px7, sdmmc3_clk_pa6,
- sdmmc3_cmd_pa7, sdmmc3_dat0_pb7, sdmmc3_dat1_pb6, sdmmc3_dat2_pb5,
- sdmmc3_dat3_pb4, hdmi_cec_pee3, sdmmc1_wp_n_pv3, sdmmc3_cd_n_pv2,
- gpio_w2_aud_pw2, gpio_w3_aud_pw3, usb_vbus_en0_pn4, usb_vbus_en1_pn5,
- sdmmc3_clk_lb_in_pee5, sdmmc3_clk_lb_out_pee4, reset_out_n.
-
- drive groups:
-
- These all support nvidia,pull-down-strength, nvidia,pull-up-strength,
- nvidia,slew-rate-rising, nvidia,slew-rate-falling. Most but not all
- support nvidia,high-speed-mode, nvidia,schmitt, nvidia,low-power-mode
- and nvidia,drive-type.
-
- ao1, ao2, at1, at2, at3, at4, at5, cdev1, cdev2, dap1, dap2, dap3, dap4,
- dbg, sdio3, spi, uaa, uab, uart2, uart3, sdio1, ddc, gma, gme, gmf, gmg,
- gmh, owr, uda.
-
-Valid values for nvidia,functions are:
-
- blink, cec, cldvfs, clk12, cpu, dap, dap1, dap2, dev3, displaya,
- displaya_alt, displayb, dtv, emc_dll, extperiph1, extperiph2,
- extperiph3, gmi, gmi_alt, hda, hsi, i2c1, i2c2, i2c3, i2c4, i2cpwr,
- i2s0, i2s1, i2s2, i2s3, i2s4, irda, kbc, nand, nand_alt, owr, pmi,
- pwm0, pwm1, pwm2, pwm3, pwron, reset_out_n, rsvd1, rsvd2, rsvd3,
- rsvd4, sdmmc1, sdmmc2, sdmmc3, sdmmc4, soc, spdif, spi1, spi2, spi3,
- spi4, spi5, spi6, sysclk, trace, uarta, uartb, uartc, uartd, ulpi,
- usb, vgp1, vgp2, vgp3, vgp4, vgp5, vgp6, vi, vi_alt1, vi_alt3
-
-Example:
-
- pinmux: pinmux {
- compatible = "nvidia,tegra114-pinmux";
- reg = <0x70000868 0x148 /* Pad control registers */
- 0x70003000 0x40c>; /* PinMux registers */
- };
-
-Example board file extract:
-
- pinctrl {
- sdmmc4_default: pinmux {
- sdmmc4_clk_pcc4 {
- nvidia,pins = "sdmmc4_clk_pcc4",
- nvidia,function = "sdmmc4";
- nvidia,pull = <0>;
- nvidia,tristate = <0>;
- };
- sdmmc4_dat0_paa0 {
- nvidia,pins = "sdmmc4_dat0_paa0",
- "sdmmc4_dat1_paa1",
- "sdmmc4_dat2_paa2",
- "sdmmc4_dat3_paa3",
- "sdmmc4_dat4_paa4",
- "sdmmc4_dat5_paa5",
- "sdmmc4_dat6_paa6",
- "sdmmc4_dat7_paa7";
- nvidia,function = "sdmmc4";
- nvidia,pull = <2>;
- nvidia,tristate = <0>;
- };
- };
- };
-
- sdhci@78000400 {
- pinctrl-names = "default";
- pinctrl-0 = <&sdmmc4_default>;
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra114-pinmux.yaml b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra114-pinmux.yaml
new file mode 100644
index 000000000000..065dedb3573a
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra114-pinmux.yaml
@@ -0,0 +1,155 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/nvidia,tegra114-pinmux.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Tegra114 pinmux Controller
+
+maintainers:
+ - Thierry Reding <thierry.reding@gmail.com>
+ - Jon Hunter <jonathanh@nvidia.com>
+
+properties:
+ compatible:
+ const: nvidia,tegra114-pinmux
+
+ reg:
+ items:
+ - description: pad control registers
+ - description: mux registers
+
+patternProperties:
+ "^pinmux(-[a-z0-9-_]+)?$":
+ type: object
+ properties:
+ phandle: true
+
+ # pin groups
+ additionalProperties:
+ $ref: nvidia,tegra-pinmux-common.yaml
+ additionalProperties: false
+ properties:
+ nvidia,pins:
+ items:
+ enum: [ ulpi_data0_po1, ulpi_data1_po2, ulpi_data2_po3,
+ ulpi_data3_po4, ulpi_data4_po5, ulpi_data5_po6,
+ ulpi_data6_po7, ulpi_data7_po0, ulpi_clk_py0, ulpi_dir_py1,
+ ulpi_nxt_py2, ulpi_stp_py3, dap3_fs_pp0, dap3_din_pp1,
+ dap3_dout_pp2, dap3_sclk_pp3, pv0, pv1, sdmmc1_clk_pz0,
+ sdmmc1_cmd_pz1, sdmmc1_dat3_py4, sdmmc1_dat2_py5,
+ sdmmc1_dat1_py6, sdmmc1_dat0_py7, clk2_out_pw5,
+ clk2_req_pcc5, hdmi_int_pn7, ddc_scl_pv4, ddc_sda_pv5,
+ uart2_rxd_pc3, uart2_txd_pc2, uart2_rts_n_pj6,
+ uart2_cts_n_pj5, uart3_txd_pw6, uart3_rxd_pw7,
+ uart3_cts_n_pa1, uart3_rts_n_pc0, pu0, pu1, pu2, pu3, pu4,
+ pu5, pu6, gen1_i2c_sda_pc5, gen1_i2c_scl_pc4, dap4_fs_pp4,
+ dap4_din_pp5, dap4_dout_pp6, dap4_sclk_pp7, clk3_out_pee0,
+ clk3_req_pee1, gmi_wp_n_pc7, gmi_iordy_pi5, gmi_wait_pi7,
+ gmi_adv_n_pk0, gmi_clk_pk1, gmi_cs0_n_pj0, gmi_cs1_n_pj2,
+ gmi_cs2_n_pk3, gmi_cs3_n_pk4, gmi_cs4_n_pk2, gmi_cs6_n_pi3,
+ gmi_cs7_n_pi6, gmi_ad0_pg0, gmi_ad1_pg1, gmi_ad2_pg2,
+ gmi_ad3_pg3, gmi_ad4_pg4, gmi_ad5_pg5, gmi_ad6_pg6,
+ gmi_ad7_pg7, gmi_ad8_ph0, gmi_ad9_ph1, gmi_ad10_ph2,
+ gmi_ad11_ph3, gmi_ad12_ph4, gmi_ad13_ph5, gmi_ad14_ph6,
+ gmi_ad15_ph7, gmi_a16_pj7, gmi_a17_pb0, gmi_a18_pb1,
+ gmi_a19_pk7, gmi_wr_n_pi0, gmi_oe_n_pi1, gmi_dqs_p_pj3,
+ gmi_rst_n_pi4, gen2_i2c_scl_pt5, gen2_i2c_sda_pt6,
+ sdmmc4_clk_pcc4, sdmmc4_cmd_pt7, sdmmc4_dat0_paa0,
+ sdmmc4_dat1_paa1, sdmmc4_dat2_paa2, sdmmc4_dat3_paa3,
+ sdmmc4_dat4_paa4, sdmmc4_dat5_paa5, sdmmc4_dat6_paa6,
+ sdmmc4_dat7_paa7, cam_mclk_pcc0, pcc1, pbb0,
+ cam_i2c_scl_pbb1, cam_i2c_sda_pbb2, pbb3, pbb4, pbb5, pbb6,
+ pbb7, pcc2, pwr_i2c_scl_pz6, pwr_i2c_sda_pz7, kb_row0_pr0,
+ kb_row1_pr1, kb_row2_pr2, kb_row3_pr3, kb_row4_pr4,
+ kb_row5_pr5, kb_row6_pr6, kb_row7_pr7, kb_row8_ps0,
+ kb_row9_ps1, kb_row10_ps2, kb_col0_pq0, kb_col1_pq1,
+ kb_col2_pq2, kb_col3_pq3, kb_col4_pq4, kb_col5_pq5,
+ kb_col6_pq6, kb_col7_pq7, clk_32k_out_pa0, sys_clk_req_pz5,
+ core_pwr_req, cpu_pwr_req, pwr_int_n, owr, dap1_fs_pn0,
+ dap1_din_pn1, dap1_dout_pn2, dap1_sclk_pn3, clk1_req_pee2,
+ clk1_out_pw4, spdif_in_pk6, spdif_out_pk5, dap2_fs_pa2,
+ dap2_din_pa4, dap2_dout_pa5, dap2_sclk_pa3, dvfs_pwm_px0,
+ gpio_x1_aud_px1, gpio_x3_aud_px3, dvfs_clk_px2,
+ gpio_x4_aud_px4, gpio_x5_aud_px5, gpio_x6_aud_px6,
+ gpio_x7_aud_px7, sdmmc3_clk_pa6, sdmmc3_cmd_pa7,
+ sdmmc3_dat0_pb7, sdmmc3_dat1_pb6, sdmmc3_dat2_pb5,
+ sdmmc3_dat3_pb4, hdmi_cec_pee3, sdmmc1_wp_n_pv3,
+ sdmmc3_cd_n_pv2, gpio_w2_aud_pw2, gpio_w3_aud_pw3,
+ usb_vbus_en0_pn4, usb_vbus_en1_pn5, sdmmc3_clk_lb_in_pee5,
+ sdmmc3_clk_lb_out_pee4, reset_out_n,
+ # drive groups
+ drive_ao1, drive_ao2, drive_at1, drive_at2, drive_at3,
+ drive_at4, drive_at5, drive_cdev1, drive_cdev2, drive_dap1,
+ drive_dap2, drive_dap3, drive_dap4, drive_dbg, drive_sdio3,
+ drive_spi, drive_uaa, drive_uab, drive_uart2, drive_uart3,
+ drive_sdio1, drive_ddc, drive_gma, drive_gme, drive_gmf,
+ drive_gmg, drive_gmh, drive_owr, drive_uda ]
+
+ nvidia,function:
+ enum: [ blink, cec, cldvfs, clk12, cpu, dap, dap1, dap2, dev3,
+ displaya, displaya_alt, displayb, dtv, emc_dll, extperiph1,
+ extperiph2, extperiph3, gmi, gmi_alt, hda, hsi, i2c1, i2c2,
+ i2c3, i2c4, i2cpwr, i2s0, i2s1, i2s2, i2s3, i2s4, irda, kbc,
+ nand, nand_alt, owr, pmi, pwm0, pwm1, pwm2, pwm3, pwron,
+ reset_out_n, rsvd1, rsvd2, rsvd3, rsvd4, sdmmc1, sdmmc2,
+ sdmmc3, sdmmc4, soc, spdif, spi1, spi2, spi3, spi4, spi5,
+ spi6, sysclk, trace, uarta, uartb, uartc, uartd, ulpi, usb,
+ vgp1, vgp2, vgp3, vgp4, vgp5, vgp6, vi, vi_alt1, vi_alt3 ]
+
+ nvidia,pull: true
+ nvidia,tristate: true
+ nvidia,schmitt: true
+ nvidia,pull-down-strength: true
+ nvidia,pull-up-strength: true
+ nvidia,high-speed-mode: true
+ nvidia,low-power-mode: true
+ nvidia,enable-input: true
+ nvidia,open-drain: true
+ nvidia,lock: true
+ nvidia,io-reset: true
+ nvidia,rcv-sel: true
+ nvidia,drive-type: true
+ nvidia,slew-rate-rising: true
+ nvidia,slew-rate-falling: true
+
+ required:
+ - nvidia,pins
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+examples:
+ - |
+ pinmux@70000868 {
+ compatible = "nvidia,tegra114-pinmux";
+ reg = <0x70000868 0x148>, /* Pad control registers */
+ <0x70003000 0x40c>; /* PinMux registers */
+
+ pinmux {
+ sdmmc4_clk_pcc4 {
+ nvidia,pins = "sdmmc4_clk_pcc4";
+ nvidia,function = "sdmmc4";
+ nvidia,pull = <0>;
+ nvidia,tristate = <0>;
+ };
+
+ sdmmc4_dat0_paa0 {
+ nvidia,pins = "sdmmc4_dat0_paa0",
+ "sdmmc4_dat1_paa1",
+ "sdmmc4_dat2_paa2",
+ "sdmmc4_dat3_paa3",
+ "sdmmc4_dat4_paa4",
+ "sdmmc4_dat5_paa5",
+ "sdmmc4_dat6_paa6",
+ "sdmmc4_dat7_paa7";
+ nvidia,function = "sdmmc4";
+ nvidia,pull = <2>;
+ nvidia,tristate = <0>;
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-pinmux.txt
deleted file mode 100644
index f4d06bb0b55a..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-pinmux.txt
+++ /dev/null
@@ -1,153 +0,0 @@
-NVIDIA Tegra124 pinmux controller
-
-The Tegra124 pinctrl binding is very similar to the Tegra20 and Tegra30
-pinctrl binding, as described in nvidia,tegra20-pinmux.txt and
-nvidia,tegra30-pinmux.txt. In fact, this document assumes that binding as
-a baseline, and only documents the differences between the two bindings.
-
-Required properties:
-- compatible: For Tegra124, must contain "nvidia,tegra124-pinmux". For
- Tegra132, must contain '"nvidia,tegra132-pinmux", "nvidia-tegra124-pinmux"'.
-- reg: Should contain a list of base address and size pairs for:
- -- first entry - the drive strength and pad control registers.
- -- second entry - the pinmux registers
- -- third entry - the MIPI_PAD_CTRL register
-
-Tegra124 adds the following optional properties for pin configuration subnodes.
-The macros for options are defined in the
- include/dt-binding/pinctrl/pinctrl-tegra.h.
-- nvidia,enable-input: Integer. Enable the pin's input path.
- enable :TEGRA_PIN_ENABLE and
- disable or output only: TEGRA_PIN_DISABLE.
-- nvidia,open-drain: Integer.
- enable: TEGRA_PIN_ENABLE.
- disable: TEGRA_PIN_DISABLE.
-- nvidia,lock: Integer. Lock the pin configuration against further changes
- until reset.
- enable: TEGRA_PIN_ENABLE.
- disable: TEGRA_PIN_DISABLE.
-- nvidia,io-reset: Integer. Reset the IO path.
- enable: TEGRA_PIN_ENABLE.
- disable: TEGRA_PIN_DISABLE.
-- nvidia,rcv-sel: Integer. Select VIL/VIH receivers.
- normal: TEGRA_PIN_DISABLE
- high: TEGRA_PIN_ENABLE
-
-Please refer the Tegra TRM for complete details regarding which groups
-support which functionality.
-
-Valid values for pin and group names are:
-
- per-pin mux groups:
-
- These all support nvidia,function, nvidia,tristate, nvidia,pull,
- nvidia,enable-input. Some support nvidia,lock nvidia,open-drain,
- nvidia,io-reset and nvidia,rcv-sel.
-
- ulpi_data0_po1, ulpi_data1_po2, ulpi_data2_po3, ulpi_data3_po4,
- ulpi_data4_po5, ulpi_data5_po6, ulpi_data6_po7, ulpi_data7_po0,
- ulpi_clk_py0, ulpi_dir_py1, ulpi_nxt_py2, ulpi_stp_py3, dap3_fs_pp0,
- dap3_din_pp1, dap3_dout_pp2, dap3_sclk_pp3, pv0, pv1, sdmmc1_clk_pz0,
- sdmmc1_cmd_pz1, sdmmc1_dat3_py4, sdmmc1_dat2_py5, sdmmc1_dat1_py6,
- sdmmc1_dat0_py7, clk2_out_pw5, clk2_req_pcc5, hdmi_int_pn7, ddc_scl_pv4,
- ddc_sda_pv5, uart2_rxd_pc3, uart2_txd_pc2, uart2_rts_n_pj6,
- uart2_cts_n_pj5, uart3_txd_pw6, uart3_rxd_pw7, uart3_cts_n_pa1,
- uart3_rts_n_pc0, pu0, pu1, pu2, pu3, pu4, pu5, pu6, gen1_i2c_scl_pc4,
- gen1_i2c_sda_pc5, dap4_fs_pp4, dap4_din_pp5, dap4_dout_pp6,
- dap4_sclk_pp7, clk3_out_pee0, clk3_req_pee1, pc7, pi5, pi7, pk0, pk1,
- pj0, pj2, pk3, pk4, pk2, pi3, pi6, pg0, pg1, pg2, pg3, pg4, pg5, pg6,
- pg7, ph0, ph1, ph2, ph3, ph4, ph5, ph6, ph7, pj7, pb0, pb1, pk7, pi0,
- pi1, pi2, pi4, gen2_i2c_scl_pt5, gen2_i2c_sda_pt6, sdmmc4_clk_pcc4,
- sdmmc4_cmd_pt7, sdmmc4_dat0_paa0, sdmmc4_dat1_paa1, sdmmc4_dat2_paa2,
- sdmmc4_dat3_paa3, sdmmc4_dat4_paa4, sdmmc4_dat5_paa5, sdmmc4_dat6_paa6,
- sdmmc4_dat7_paa7, cam_mclk_pcc0, pcc1, pbb0, cam_i2c_scl_pbb1,
- cam_i2c_sda_pbb2, pbb3, pbb4, pbb5, pbb6, pbb7, pcc2, jtag_rtck,
- pwr_i2c_scl_pz6, pwr_i2c_sda_pz7, kb_row0_pr0, kb_row1_pr1, kb_row2_pr2,
- kb_row3_pr3, kb_row4_pr4, kb_row5_pr5, kb_row6_pr6, kb_row7_pr7,
- kb_row8_ps0, kb_row9_ps1, kb_row10_ps2, kb_row11_ps3, kb_row12_ps4,
- kb_row13_ps5, kb_row14_ps6, kb_row15_ps7, kb_col0_pq0, kb_col1_pq1,
- kb_col2_pq2, kb_col3_pq3, kb_col4_pq4, kb_col5_pq5, kb_col6_pq6,
- kb_col7_pq7, clk_32k_out_pa0, core_pwr_req, cpu_pwr_req, pwr_int_n,
- clk_32k_in, owr, dap1_fs_pn0, dap1_din_pn1, dap1_dout_pn2,
- dap1_sclk_pn3, dap_mclk1_req_pee2, dap_mclk1_pw4, spdif_in_pk6,
- spdif_out_pk5, dap2_fs_pa2, dap2_din_pa4, dap2_dout_pa5, dap2_sclk_pa3,
- dvfs_pwm_px0, gpio_x1_aud_px1, gpio_x3_aud_px3, dvfs_clk_px2,
- gpio_x4_aud_px4, gpio_x5_aud_px5, gpio_x6_aud_px6, gpio_x7_aud_px7,
- sdmmc3_clk_pa6, sdmmc3_cmd_pa7, sdmmc3_dat0_pb7, sdmmc3_dat1_pb6,
- sdmmc3_dat2_pb5, sdmmc3_dat3_pb4, pex_l0_rst_n_pdd1,
- pex_l0_clkreq_n_pdd2, pex_wake_n_pdd3, pex_l1_rst_n_pdd5,
- pex_l1_clkreq_n_pdd6, hdmi_cec_pee3, sdmmc1_wp_n_pv3,
- sdmmc3_cd_n_pv2, gpio_w2_aud_pw2, gpio_w3_aud_pw3, usb_vbus_en0_pn4,
- usb_vbus_en1_pn5, sdmmc3_clk_lb_out_pee4, sdmmc3_clk_lb_in_pee5,
- gmi_clk_lb, reset_out_n, kb_row16_pt0, kb_row17_pt1, usb_vbus_en2_pff1,
- pff2, dp_hpd_pff0,
-
- drive groups:
-
- These all support nvidia,pull-down-strength, nvidia,pull-up-strength,
- nvidia,slew-rate-rising, nvidia,slew-rate-falling. Most but not all
- support nvidia,high-speed-mode, nvidia,schmitt, nvidia,low-power-mode
- and nvidia,drive-type.
-
- ao1, ao2, at1, at2, at3, at4, at5, cdev1, cdev2, dap1, dap2, dap3, dap4,
- dbg, sdio3, spi, uaa, uab, uart2, uart3, sdio1, ddc, gma, gme, gmf, gmg,
- gmh, owr, uda, gpv, dev3, cec, usb_vbus_en, ao3, ao0, hv0, sdio4, ao4.
-
- MIPI pad control groups:
-
- These support only the nvidia,function property.
-
- dsi_b
-
-Valid values for nvidia,functions are:
-
- blink, cec, cldvfs, clk12, cpu, dap, dap1, dap2, dev3, displaya,
- displaya_alt, displayb, dtv, extperiph1, extperiph2, extperiph3,
- gmi, gmi_alt, hda, hsi, i2c1, i2c2, i2c3, i2c4, i2cpwr, i2s0,
- i2s1, i2s2, i2s3, i2s4, irda, kbc, owr, pmi, pwm0, pwm1, pwm2, pwm3,
- pwron, reset_out_n, rsvd1, rsvd2, rsvd3, rsvd4, sdmmc1, sdmmc2, sdmmc3,
- sdmmc4, soc, spdif, spi1, spi2, spi3, spi4, spi5, spi6, trace, uarta,
- uartb, uartc, uartd, ulpi, usb, vgp1, vgp2, vgp3, vgp4, vgp5, vgp6,
- vi, vi_alt1, vi_alt3, vimclk2, vimclk2_alt, sata, ccla, pe0, pe, pe1,
- dp, rtck, sys, clk tmds, csi, dsi_b
-
-Example:
-
- pinmux: pinmux {
- compatible = "nvidia,tegra124-pinmux";
- reg = <0x0 0x70000868 0x0 0x164>, /* Pad control registers */
- <0x0 0x70003000 0x0 0x434>, /* Mux registers */
- <0x0 0x70000820 0x0 0x8>; /* MIPI pad control */
- };
-
-Example pinmux entries:
-
- pinctrl {
- sdmmc4_default: pinmux {
- sdmmc4_clk_pcc4 {
- nvidia,pins = "sdmmc4_clk_pcc4",
- nvidia,function = "sdmmc4";
- nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- nvidia,tristate = <TEGRA_PIN_DISABLE>;
- };
-
- sdmmc4_dat0_paa0 {
- nvidia,pins = "sdmmc4_dat0_paa0",
- "sdmmc4_dat1_paa1",
- "sdmmc4_dat2_paa2",
- "sdmmc4_dat3_paa3",
- "sdmmc4_dat4_paa4",
- "sdmmc4_dat5_paa5",
- "sdmmc4_dat6_paa6",
- "sdmmc4_dat7_paa7";
- nvidia,function = "sdmmc4";
- nvidia,pull = <TEGRA_PIN_PULL_UP>;
- nvidia,tristate = <TEGRA_PIN_DISABLE>;
- };
- };
- };
-
- sdhci@78000400 {
- pinctrl-names = "default";
- pinctrl-0 = <&sdmmc4_default>;
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-pinmux.yaml b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-pinmux.yaml
new file mode 100644
index 000000000000..f924652bef0d
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra124-pinmux.yaml
@@ -0,0 +1,176 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/nvidia,tegra124-pinmux.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Tegra124 Pinmux Controller
+
+maintainers:
+ - Thierry Reding <thierry.reding@gmail.com>
+ - Jon Hunter <jonathanh@nvidia.com>
+
+description: The Tegra124 pinctrl binding is very similar to the Tegra20 and
+ Tegra30 pinctrl binding, as described in nvidia,tegra20-pinmux.yaml and
+ nvidia,tegra30-pinmux.yaml. In fact, this document assumes that binding as a
+ baseline, and only documents the differences between the two bindings.
+
+properties:
+ compatible:
+ oneOf:
+ - const: nvidia,tegra124-pinmux
+ - items:
+ - const: nvidia,tegra132-pinmux
+ - const: nvidia,tegra124-pinmux
+
+ reg:
+ items:
+ - description: driver strength and pad control registers
+ - description: pinmux registers
+ - description: MIPI_PAD_CTRL registers
+
+patternProperties:
+ "^pinmux(-[a-z0-9-_]+)?$":
+ type: object
+ properties:
+ phandle: true
+
+ # pin groups
+ additionalProperties:
+ $ref: nvidia,tegra-pinmux-common.yaml
+ additionalProperties: false
+ properties:
+ nvidia,pins:
+ $ref: /schemas/types.yaml#/definitions/string-array
+ items:
+ enum: [ ulpi_data0_po1, ulpi_data1_po2, ulpi_data2_po3,
+ ulpi_data3_po4, ulpi_data4_po5, ulpi_data5_po6,
+ ulpi_data6_po7, ulpi_data7_po0, ulpi_clk_py0, ulpi_dir_py1,
+ ulpi_nxt_py2, ulpi_stp_py3, dap3_fs_pp0, dap3_din_pp1,
+ dap3_dout_pp2, dap3_sclk_pp3, pv0, pv1, sdmmc1_clk_pz0,
+ sdmmc1_cmd_pz1, sdmmc1_dat3_py4, sdmmc1_dat2_py5,
+ sdmmc1_dat1_py6, sdmmc1_dat0_py7, clk2_out_pw5,
+ clk2_req_pcc5, hdmi_int_pn7, ddc_scl_pv4, ddc_sda_pv5,
+ uart2_rxd_pc3, uart2_txd_pc2, uart2_rts_n_pj6,
+ uart2_cts_n_pj5, uart3_txd_pw6, uart3_rxd_pw7,
+ uart3_cts_n_pa1, uart3_rts_n_pc0, pu0, pu1, pu2, pu3, pu4,
+ pu5, pu6, gen1_i2c_scl_pc4, gen1_i2c_sda_pc5, dap4_fs_pp4,
+ dap4_din_pp5, dap4_dout_pp6, dap4_sclk_pp7, clk3_out_pee0,
+ clk3_req_pee1, pc7, pi5, pi7, pk0, pk1, pj0, pj2, pk3, pk4,
+ pk2, pi3, pi6, pg0, pg1, pg2, pg3, pg4, pg5, pg6, pg7, ph0,
+ ph1, ph2, ph3, ph4, ph5, ph6, ph7, pj7, pb0, pb1, pk7, pi0,
+ pi1, pi2, pi4, gen2_i2c_scl_pt5, gen2_i2c_sda_pt6,
+ sdmmc4_clk_pcc4, sdmmc4_cmd_pt7, sdmmc4_dat0_paa0,
+ sdmmc4_dat1_paa1, sdmmc4_dat2_paa2, sdmmc4_dat3_paa3,
+ sdmmc4_dat4_paa4, sdmmc4_dat5_paa5, sdmmc4_dat6_paa6,
+ sdmmc4_dat7_paa7, cam_mclk_pcc0, pcc1, pbb0,
+ cam_i2c_scl_pbb1, cam_i2c_sda_pbb2, pbb3, pbb4, pbb5, pbb6,
+ pbb7, pcc2, jtag_rtck, pwr_i2c_scl_pz6, pwr_i2c_sda_pz7,
+ kb_row0_pr0, kb_row1_pr1, kb_row2_pr2, kb_row3_pr3,
+ kb_row4_pr4, kb_row5_pr5, kb_row6_pr6, kb_row7_pr7,
+ kb_row8_ps0, kb_row9_ps1, kb_row10_ps2, kb_row11_ps3,
+ kb_row12_ps4, kb_row13_ps5, kb_row14_ps6, kb_row15_ps7,
+ kb_col0_pq0, kb_col1_pq1, kb_col2_pq2, kb_col3_pq3,
+ kb_col4_pq4, kb_col5_pq5, kb_col6_pq6, kb_col7_pq7,
+ clk_32k_out_pa0, core_pwr_req, cpu_pwr_req, pwr_int_n,
+ clk_32k_in, owr, dap1_fs_pn0, dap1_din_pn1, dap1_dout_pn2,
+ dap1_sclk_pn3, dap_mclk1_req_pee2, dap_mclk1_pw4,
+ spdif_in_pk6, spdif_out_pk5, dap2_fs_pa2, dap2_din_pa4,
+ dap2_dout_pa5, dap2_sclk_pa3, dvfs_pwm_px0,
+ gpio_x1_aud_px1, gpio_x3_aud_px3, dvfs_clk_px2,
+ gpio_x4_aud_px4, gpio_x5_aud_px5, gpio_x6_aud_px6,
+ gpio_x7_aud_px7, sdmmc3_clk_pa6, sdmmc3_cmd_pa7,
+ sdmmc3_dat0_pb7, sdmmc3_dat1_pb6, sdmmc3_dat2_pb5,
+ sdmmc3_dat3_pb4, pex_l0_rst_n_pdd1, pex_l0_clkreq_n_pdd2,
+ pex_wake_n_pdd3, pex_l1_rst_n_pdd5, pex_l1_clkreq_n_pdd6,
+ hdmi_cec_pee3, sdmmc1_wp_n_pv3, sdmmc3_cd_n_pv2,
+ gpio_w2_aud_pw2, gpio_w3_aud_pw3, usb_vbus_en0_pn4,
+ usb_vbus_en1_pn5, sdmmc3_clk_lb_out_pee4,
+ sdmmc3_clk_lb_in_pee5, gmi_clk_lb, reset_out_n,
+ kb_row16_pt0, kb_row17_pt1, usb_vbus_en2_pff1, pff2,
+ dp_hpd_pff0,
+ # drive groups
+ drive_ao1, drive_ao2, drive_at1, drive_at2, drive_at3,
+ drive_at4, drive_at5, drive_cdev1, drive_cdev2, drive_dap1,
+ drive_dap2, drive_dap3, drive_dap4, drive_dbg, drive_sdio3,
+ drive_spi, drive_uaa, drive_uab, drive_uart2, drive_uart3,
+ drive_sdio1, drive_ddc, drive_gma, drive_gme, drive_gmf,
+ drive_gmg, drive_gmh, drive_owr, drive_uda, drive_gpv,
+ drive_dev3, drive_cec, drive_usb_vbus_en, drive_ao3,
+ drive_ao0, drive_hv0, drive_sdio4, drive_ao4,
+ # MIPI pad control groups
+ mipi_pad_ctrl_dsi_b ]
+
+ nvidia,function:
+ enum: [ blink, cec, cldvfs, clk12, cpu, dap, dap1, dap2, dev3,
+ displaya, displaya_alt, displayb, dtv, extperiph1,
+ extperiph2, extperiph3, gmi, gmi_alt, hda, hsi, i2c1, i2c2,
+ i2c3, i2c4, i2cpwr, i2s0, i2s1, i2s2, i2s3, i2s4, irda, kbc,
+ owr, pmi, pwm0, pwm1, pwm2, pwm3, pwron, reset_out_n, rsvd1,
+ rsvd2, rsvd3, rsvd4, sdmmc1, sdmmc2, sdmmc3, sdmmc4, soc,
+ spdif, spi1, spi2, spi3, spi4, spi5, spi6, trace, uarta,
+ uartb, uartc, uartd, ulpi, usb, vgp1, vgp2, vgp3, vgp4, vgp5,
+ vgp6, vi, vi_alt1, vi_alt3, vimclk2, vimclk2_alt, sata, ccla,
+ pe0, pe, pe1, dp, rtck, sys, clk, tmds, csi, dsi_b ]
+
+ nvidia,pull: true
+ nvidia,tristate: true
+ nvidia,schmitt: true
+ nvidia,pull-down-strength: true
+ nvidia,pull-up-strength: true
+ nvidia,high-speed-mode: true
+ nvidia,low-power-mode: true
+ nvidia,enable-input: true
+ nvidia,open-drain: true
+ nvidia,lock: true
+ nvidia,io-reset: true
+ nvidia,rcv-sel: true
+ nvidia,drive-type: true
+ nvidia,slew-rate-rising: true
+ nvidia,slew-rate-falling: true
+
+ required:
+ - nvidia,pins
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+examples:
+ - |
+ #include <dt-bindings/clock/tegra124-car.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/pinctrl/pinctrl-tegra.h>
+
+ pinmux@70000868 {
+ compatible = "nvidia,tegra124-pinmux";
+ reg = <0x70000868 0x164>, /* Pad control registers */
+ <0x70003000 0x434>, /* Mux registers */
+ <0x70000820 0x8>; /* MIPI pad control */
+
+ sdmmc4_default: pinmux {
+ sdmmc4_clk_pcc4 {
+ nvidia,pins = "sdmmc4_clk_pcc4";
+ nvidia,function = "sdmmc4";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+
+ sdmmc4_dat0_paa0 {
+ nvidia,pins = "sdmmc4_dat0_paa0",
+ "sdmmc4_dat1_paa1",
+ "sdmmc4_dat2_paa2",
+ "sdmmc4_dat3_paa3",
+ "sdmmc4_dat4_paa4",
+ "sdmmc4_dat5_paa5",
+ "sdmmc4_dat6_paa6",
+ "sdmmc4_dat7_paa7";
+ nvidia,function = "sdmmc4";
+ nvidia,pull = <TEGRA_PIN_PULL_UP>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra194-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra194-pinmux.txt
deleted file mode 100644
index 90d38f710635..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra194-pinmux.txt
+++ /dev/null
@@ -1,107 +0,0 @@
-NVIDIA Tegra194 pinmux controller
-
-Required properties:
-- compatible: "nvidia,tegra194-pinmux"
-- reg: Should contain a list of base address and size pairs for:
- - first entry: The APB_MISC_GP_*_PADCTRL registers (pad control)
- - second entry: The PINMUX_AUX_* registers (pinmux)
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-Tegra's pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, tristate, drive strength, etc.
-
-See the TRM to determine which properties and values apply to each pin/group.
-Macro values for property values are defined in
-include/dt-binding/pinctrl/pinctrl-tegra.h.
-
-Required subnode-properties:
-- nvidia,pins : An array of strings. Each string contains the name of a pin or
- group. Valid values for these names are listed below.
-
-Optional subnode-properties:
-- nvidia,function: A string containing the name of the function to mux to the
- pin or group.
-- nvidia,pull: Integer, representing the pull-down/up to apply to the pin.
- 0: none, 1: down, 2: up.
-- nvidia,tristate: Integer.
- 0: drive, 1: tristate.
-- nvidia,enable-input: Integer. Enable the pin's input path.
- enable :TEGRA_PIN_ENABLE and
- disable or output only: TEGRA_PIN_DISABLE.
-- nvidia,open-drain: Integer.
- enable: TEGRA_PIN_ENABLE.
- disable: TEGRA_PIN_DISABLE.
-- nvidia,lock: Integer. Lock the pin configuration against further changes
- until reset.
- enable: TEGRA_PIN_ENABLE.
- disable: TEGRA_PIN_DISABLE.
-- nvidia,io-hv: Integer. Select high-voltage receivers.
- normal: TEGRA_PIN_DISABLE
- high: TEGRA_PIN_ENABLE
-- nvidia,schmitt: Integer. Enables Schmitt Trigger on the input.
- normal: TEGRA_PIN_DISABLE
- high: TEGRA_PIN_ENABLE
-- nvidia,drive-type: Integer. Valid range 0...3.
-- nvidia,pull-down-strength: Integer. Controls drive strength. 0 is weakest.
- The range of valid values depends on the pingroup. See "CAL_DRVDN" in the
- Tegra TRM.
-- nvidia,pull-up-strength: Integer. Controls drive strength. 0 is weakest.
- The range of valid values depends on the pingroup. See "CAL_DRVUP" in the
- Tegra TRM.
-
-Valid values for pin and group names (nvidia,pin) are:
-
- These correspond to Tegra PADCTL_* (pinmux) registers.
-
- Mux groups:
-
- These correspond to Tegra PADCTL_* (pinmux) registers. Any property
- that exists in those registers may be set for the following pin names.
-
- pex_l5_clkreq_n_pgg0, pex_l5_rst_n_pgg1
-
- Drive groups:
-
- These registers controls a single pin for which a mux group exists.
- See the list above for the pin name to use when configuring the pinmux.
-
- pex_l5_clkreq_n_pgg0, pex_l5_rst_n_pgg1
-
-Valid values for nvidia,functions are:
-
- pe5
-
-Power Domain:
- pex_l5_clkreq_n_pgg0 and pex_l5_rst_n_pgg1 are part of PCIE C5 power
- partition. Client devices must enable this partition before accessing
- these pins here.
-
-
-Example:
-
- tegra_pinctrl: pinmux: pinmux@2430000 {
- compatible = "nvidia,tegra194-pinmux";
- reg = <0x2430000 0x17000
- 0xc300000 0x4000>;
-
- pinctrl-names = "pex_rst";
- pinctrl-0 = <&pex_rst_c5_out_state>;
-
- pex_rst_c5_out_state: pex_rst_c5_out {
- pex_rst {
- nvidia,pins = "pex_l5_rst_n_pgg1";
- nvidia,schmitt = <TEGRA_PIN_DISABLE>;
- nvidia,lpdr = <TEGRA_PIN_ENABLE>;
- nvidia,enable-input = <TEGRA_PIN_DISABLE>;
- nvidia,io-hv = <TEGRA_PIN_ENABLE>;
- nvidia,tristate = <TEGRA_PIN_DISABLE>;
- nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra194-pinmux.yaml b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra194-pinmux.yaml
new file mode 100644
index 000000000000..60a4bdf01bf2
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra194-pinmux.yaml
@@ -0,0 +1,284 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/nvidia,tegra194-pinmux.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Tegra194 Pinmux Controller
+
+maintainers:
+ - Thierry Reding <thierry.reding@gmail.com>
+ - Jon Hunter <jonathanh@nvidia.com>
+
+properties:
+ compatible:
+ enum:
+ - nvidia,tegra194-pinmux
+ - nvidia,tegra194-pinmux-aon
+
+ reg:
+ items:
+ - description: pinmux registers
+
+patternProperties:
+ "^pinmux(-[a-z0-9-_]+)?$":
+ type: object
+ properties:
+ phandle: true
+
+ # pin groups
+ additionalProperties:
+ $ref: nvidia,tegra-pinmux-common.yaml
+ unevaluatedProperties: false
+ properties:
+ nvidia,function:
+ enum: [ aud, can0, can1, ccla, dca, dcb, dgpu, directdc, directdc1,
+ displaya, displayb, dmic1, dmic2, dmic3, dmic4, dmic5, dp,
+ dspk0, dspk1, eqos, extperiph1, extperiph2, extperiph3,
+ extperiph4, gp, gpio, hdmi, i2c1, i2c2, i2c3, i2c5, i2c8,
+ i2s1, i2s2, i2s3, i2s4, i2s5, i2s6, igpu, iqc1, iqc2, mipi,
+ nv, pe0, pe1, pe2, pe3, pe4, pe5, qspi, qspi0, qspi1, rsvd0,
+ rsvd1, rsvd2, rsvd3, sata, sce, sdmmc1, sdmmc3, sdmmc4, slvs,
+ soc, spdif, spi1, spi2, spi3, touch, uarta, uartb, uartc,
+ uartd, uarte, uartg, ufs0, usb, vgp1, vgp2, vgp3, vgp4, vgp5,
+ vgp6, wdt ]
+
+ nvidia,pull: true
+ nvidia,tristate: true
+ nvidia,schmitt: true
+ nvidia,enable-input: true
+ nvidia,open-drain: true
+ nvidia,lock: true
+ nvidia,drive-type: true
+ nvidia,io-hv: true
+
+ required:
+ - nvidia,pins
+
+additionalProperties: false
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ const: nvidia,tegra194-pinmux
+ then:
+ patternProperties:
+ "^pinmux(-[a-z0-9-_]+)?$":
+ type: object
+ additionalProperties:
+ properties:
+ nvidia,pins:
+ description: An array of strings. Each string contains the name
+ of a pin or group. Valid values for these names are listed
+ below.
+
+ Note that the pex_l5_clkreq_n_pgg0 and pex_l5_rst_n_pgg1 pins
+ are part of PCIE C5 power partition. Client devices must
+ enable this partition before accessing the configuration for
+ these pins.
+ items:
+ enum: [ dap6_sclk_pa0, dap6_dout_pa1, dap6_din_pa2,
+ dap6_fs_pa3, dap4_sclk_pa4, dap4_dout_pa5,
+ dap4_din_pa6, dap4_fs_pa7, cpu_pwr_req_0_pb0,
+ cpu_pwr_req_1_pb1, qspi0_sck_pc0, qspi0_cs_n_pc1,
+ qspi0_io0_pc2, qspi0_io1_pc3, qspi0_io2_pc4,
+ qspi0_io3_pc5, qspi1_sck_pc6, qspi1_cs_n_pc7,
+ qspi1_io0_pd0, qspi1_io1_pd1, qspi1_io2_pd2,
+ qspi1_io3_pd3, eqos_txc_pe0, eqos_td0_pe1,
+ eqos_td1_pe2, eqos_td2_pe3, eqos_td3_pe4,
+ eqos_tx_ctl_pe5, eqos_rd0_pe6, eqos_rd1_pe7,
+ eqos_rd2_pf0, eqos_rd3_pf1, eqos_rx_ctl_pf2,
+ eqos_rxc_pf3, eqos_sma_mdio_pf4, eqos_sma_mdc_pf5,
+ soc_gpio00_pg0, soc_gpio01_pg1, soc_gpio02_pg2,
+ soc_gpio03_pg3, soc_gpio08_pg4, soc_gpio09_pg5,
+ soc_gpio10_pg6, soc_gpio11_pg7, soc_gpio12_ph0,
+ soc_gpio13_ph1, soc_gpio14_ph2, uart4_tx_ph3,
+ uart4_rx_ph4, uart4_rts_ph5, uart4_cts_ph6,
+ dap2_sclk_ph7, dap2_dout_pi0, dap2_din_pi1,
+ dap2_fs_pi2, gen1_i2c_scl_pi3, gen1_i2c_sda_pi4,
+ sdmmc1_clk_pj0, sdmmc1_cmd_pj1, sdmmc1_dat0_pj2,
+ sdmmc1_dat1_pj3, sdmmc1_dat2_pj4, sdmmc1_dat3_pj5,
+ pex_l0_clkreq_n_pk0, pex_l0_rst_n_pk1,
+ pex_l1_clkreq_n_pk2, pex_l1_rst_n_pk3,
+ pex_l2_clkreq_n_pk4, pex_l2_rst_n_pk5,
+ pex_l3_clkreq_n_pk6, pex_l3_rst_n_pk7,
+ pex_l4_clkreq_n_pl0, pex_l4_rst_n_pl1,
+ pex_wake_n_pl2, sata_dev_slp_pl3, dp_aux_ch0_hpd_pm0,
+ dp_aux_ch1_hpd_pm1, dp_aux_ch2_hpd_pm2,
+ dp_aux_ch3_hpd_pm3, hdmi_cec_pm4, soc_gpio50_pm5,
+ soc_gpio51_pm6, soc_gpio52_pm7, soc_gpio53_pn0,
+ soc_gpio54_pn1, soc_gpio55_pn2, sdmmc3_clk_po0,
+ sdmmc3_cmd_po1, sdmmc3_dat0_po2, sdmmc3_dat1_po3,
+ sdmmc3_dat2_po4, sdmmc3_dat3_po5, extperiph1_clk_pp0,
+ extperiph2_clk_pp1, cam_i2c_scl_pp2, cam_i2c_sda_pp3,
+ soc_gpio04_pp4, soc_gpio05_pp5, soc_gpio06_pp6,
+ soc_gpio07_pp7, soc_gpio20_pq0, soc_gpio21_pq1,
+ soc_gpio22_pq2, soc_gpio23_pq3, soc_gpio40_pq4,
+ soc_gpio41_pq5, soc_gpio42_pq6, soc_gpio43_pq7,
+ soc_gpio44_pr0, soc_gpio45_pr1, uart1_tx_pr2,
+ uart1_rx_pr3, uart1_rts_pr4, uart1_cts_pr5,
+ dap1_sclk_ps0, dap1_dout_ps1, dap1_din_ps2,
+ dap1_fs_ps3, aud_mclk_ps4, soc_gpio30_ps5,
+ soc_gpio31_ps6, soc_gpio32_ps7, soc_gpio33_pt0,
+ dap3_sclk_pt1, dap3_dout_pt2, dap3_din_pt3,
+ dap3_fs_pt4, dap5_sclk_pt5, dap5_dout_pt6,
+ dap5_din_pt7, dap5_fs_pu0, directdc1_clk_pv0,
+ directdc1_in_pv1, directdc1_out0_pv2,
+ directdc1_out1_pv3, directdc1_out2_pv4,
+ directdc1_out3_pv5, directdc1_out4_pv6,
+ directdc1_out5_pv7, directdc1_out6_pw0,
+ directdc1_out7_pw1, gpu_pwr_req_px0, cv_pwr_req_px1,
+ gp_pwm2_px2, gp_pwm3_px3, uart2_tx_px4, uart2_rx_px5,
+ uart2_rts_px6, uart2_cts_px7, spi3_sck_py0,
+ spi3_miso_py1, spi3_mosi_py2, spi3_cs0_py3,
+ spi3_cs1_py4, uart5_tx_py5, uart5_rx_py6,
+ uart5_rts_py7, uart5_cts_pz0, usb_vbus_en0_pz1,
+ usb_vbus_en1_pz2, spi1_sck_pz3, spi1_miso_pz4,
+ spi1_mosi_pz5, spi1_cs0_pz6, spi1_cs1_pz7,
+ ufs0_ref_clk_pff0, ufs0_rst_pff1,
+ pex_l5_clkreq_n_pgg0, pex_l5_rst_n_pgg1,
+ directdc_comp, sdmmc4_clk, sdmmc4_cmd, sdmmc4_dqs,
+ sdmmc4_dat7, sdmmc4_dat6, sdmmc4_dat5, sdmmc4_dat4,
+ sdmmc4_dat3, sdmmc4_dat2, sdmmc4_dat1, sdmmc4_dat0,
+ sdmmc1_comp, sdmmc1_hv_trim, sdmmc3_comp,
+ sdmmc3_hv_trim, eqos_comp, qspi_comp,
+ # drive groups
+ drive_soc_gpio33_pt0, drive_soc_gpio32_ps7,
+ drive_soc_gpio31_ps6, drive_soc_gpio30_ps5,
+ drive_aud_mclk_ps4, drive_dap1_fs_ps3,
+ drive_dap1_din_ps2, drive_dap1_dout_ps1,
+ drive_dap1_sclk_ps0, drive_dap3_fs_pt4,
+ drive_dap3_din_pt3, drive_dap3_dout_pt2,
+ drive_dap3_sclk_pt1, drive_dap5_fs_pu0,
+ drive_dap5_din_pt7, drive_dap5_dout_pt6,
+ drive_dap5_sclk_pt5, drive_dap6_fs_pa3,
+ drive_dap6_din_pa2, drive_dap6_dout_pa1,
+ drive_dap6_sclk_pa0, drive_dap4_fs_pa7,
+ drive_dap4_din_pa6, drive_dap4_dout_pa5,
+ drive_dap4_sclk_pa4, drive_extperiph2_clk_pp1,
+ drive_extperiph1_clk_pp0, drive_cam_i2c_sda_pp3,
+ drive_cam_i2c_scl_pp2, drive_soc_gpio40_pq4,
+ drive_soc_gpio41_pq5, drive_soc_gpio42_pq6,
+ drive_soc_gpio43_pq7, drive_soc_gpio44_pr0,
+ drive_soc_gpio45_pr1, drive_soc_gpio20_pq0,
+ drive_soc_gpio21_pq1, drive_soc_gpio22_pq2,
+ drive_soc_gpio23_pq3, drive_soc_gpio04_pp4,
+ drive_soc_gpio05_pp5, drive_soc_gpio06_pp6,
+ drive_soc_gpio07_pp7, drive_uart1_cts_pr5,
+ drive_uart1_rts_pr4, drive_uart1_rx_pr3,
+ drive_uart1_tx_pr2, drive_dap2_din_pi1,
+ drive_dap2_dout_pi0, drive_dap2_fs_pi2,
+ drive_dap2_sclk_ph7, drive_uart4_cts_ph6,
+ drive_uart4_rts_ph5, drive_uart4_rx_ph4,
+ drive_uart4_tx_ph3, drive_soc_gpio03_pg3,
+ drive_soc_gpio02_pg2, drive_soc_gpio01_pg1,
+ drive_soc_gpio00_pg0, drive_gen1_i2c_scl_pi3,
+ drive_gen1_i2c_sda_pi4, drive_soc_gpio08_pg4,
+ drive_soc_gpio09_pg5, drive_soc_gpio10_pg6,
+ drive_soc_gpio11_pg7, drive_soc_gpio12_ph0,
+ drive_soc_gpio13_ph1, drive_soc_gpio14_ph2,
+ drive_soc_gpio50_pm5, drive_soc_gpio51_pm6,
+ drive_soc_gpio52_pm7, drive_soc_gpio53_pn0,
+ drive_soc_gpio54_pn1, drive_soc_gpio55_pn2,
+ drive_dp_aux_ch0_hpd_pm0, drive_dp_aux_ch1_hpd_pm1,
+ drive_dp_aux_ch2_hpd_pm2, drive_dp_aux_ch3_hpd_pm3,
+ drive_hdmi_cec_pm4, drive_pex_l2_clkreq_n_pk4,
+ drive_pex_wake_n_pl2, drive_pex_l1_clkreq_n_pk2,
+ drive_pex_l1_rst_n_pk3, drive_pex_l0_clkreq_n_pk0,
+ drive_pex_l0_rst_n_pk1, drive_pex_l2_rst_n_pk5,
+ drive_pex_l3_clkreq_n_pk6, drive_pex_l3_rst_n_pk7,
+ drive_pex_l4_clkreq_n_pl0, drive_pex_l4_rst_n_pl1,
+ drive_sata_dev_slp_pl3, drive_pex_l5_clkreq_n_pgg0,
+ drive_pex_l5_rst_n_pgg1, drive_cpu_pwr_req_1_pb1,
+ drive_cpu_pwr_req_0_pb0, drive_sdmmc1_clk_pj0,
+ drive_sdmmc1_cmd_pj1, drive_sdmmc1_dat3_pj5,
+ drive_sdmmc1_dat2_pj4, drive_sdmmc1_dat1_pj3,
+ drive_sdmmc1_dat0_pj2, drive_sdmmc3_dat3_po5,
+ drive_sdmmc3_dat2_po4, drive_sdmmc3_dat1_po3,
+ drive_sdmmc3_dat0_po2, drive_sdmmc3_cmd_po1,
+ drive_sdmmc3_clk_po0, drive_gpu_pwr_req_px0,
+ drive_spi3_miso_py1, drive_spi1_cs0_pz6,
+ drive_spi3_cs0_py3, drive_spi1_miso_pz4,
+ drive_spi3_cs1_py4, drive_gp_pwm3_px3,
+ drive_gp_pwm2_px2, drive_spi1_sck_pz3,
+ drive_spi3_sck_py0, drive_spi1_cs1_pz7,
+ drive_spi1_mosi_pz5, drive_spi3_mosi_py2,
+ drive_cv_pwr_req_px1, drive_uart2_tx_px4,
+ drive_uart2_rx_px5, drive_uart2_rts_px6,
+ drive_uart2_cts_px7, drive_uart5_rx_py6,
+ drive_uart5_tx_py5, drive_uart5_rts_py7,
+ drive_uart5_cts_pz0, drive_usb_vbus_en0_pz1,
+ drive_usb_vbus_en1_pz2, drive_ufs0_rst_pff1,
+ drive_ufs0_ref_clk_pff0 ]
+
+ - if:
+ properties:
+ compatible:
+ const: nvidia,tegra194-pinmux-aon
+ then:
+ patternProperties:
+ "^pinmux(-[a-z0-9-_]+)?$":
+ type: object
+ additionalProperties:
+ properties:
+ nvidia,pins:
+ items:
+ enum: [ can1_dout_paa0, can1_din_paa1, can0_dout_paa2,
+ can0_din_paa3, can0_stb_paa4, can0_en_paa5,
+ can0_wake_paa6, can0_err_paa7, can1_stb_pbb0,
+ can1_en_pbb1, can1_wake_pbb2, can1_err_pbb3,
+ spi2_sck_pcc0, spi2_miso_pcc1, spi2_mosi_pcc2,
+ spi2_cs0_pcc3, touch_clk_pcc4, uart3_tx_pcc5,
+ uart3_rx_pcc6, gen2_i2c_scl_pcc7, gen2_i2c_sda_pdd0,
+ gen8_i2c_scl_pdd1, gen8_i2c_sda_pdd2,
+ safe_state_pee0, vcomp_alert_pee1,
+ ao_retention_n_pee2, batt_oc_pee3, power_on_pee4,
+ pwr_i2c_scl_pee5, pwr_i2c_sda_pee6, sys_reset_n,
+ shutdown_n, pmu_int_n, soc_pwr_req, clk_32k_in,
+ # drive groups
+ drive_shutdown_n, drive_pmu_int_n,
+ drive_safe_state_pee0, drive_vcomp_alert_pee1,
+ drive_soc_pwr_req, drive_batt_oc_pee3,
+ drive_clk_32k_in, drive_power_on_pee4,
+ drive_pwr_i2c_scl_pee5, drive_pwr_i2c_sda_pee6,
+ drive_ao_retention_n_pee2, drive_touch_clk_pcc4,
+ drive_uart3_rx_pcc6, drive_uart3_tx_pcc5,
+ drive_gen8_i2c_sda_pdd2, drive_gen8_i2c_scl_pdd1,
+ drive_spi2_mosi_pcc2, drive_gen2_i2c_scl_pcc7,
+ drive_spi2_cs0_pcc3, drive_gen2_i2c_sda_pdd0,
+ drive_spi2_sck_pcc0, drive_spi2_miso_pcc1,
+ drive_can1_dout_paa0, drive_can1_din_paa1,
+ drive_can0_dout_paa2, drive_can0_din_paa3,
+ drive_can0_stb_paa4, drive_can0_en_paa5,
+ drive_can0_wake_paa6, drive_can0_err_paa7,
+ drive_can1_stb_pbb0, drive_can1_en_pbb1,
+ drive_can1_wake_pbb2, drive_can1_err_pbb3 ]
+
+required:
+ - compatible
+ - reg
+
+examples:
+ - |
+ #include <dt-bindings/pinctrl/pinctrl-tegra.h>
+
+ pinmux@2430000 {
+ compatible = "nvidia,tegra194-pinmux";
+ reg = <0x2430000 0x17000>;
+
+ pinctrl-names = "pex_rst";
+ pinctrl-0 = <&pex_rst_c5_out_state>;
+
+ pex_rst_c5_out_state: pinmux-pex-rst-c5-out {
+ pex_rst {
+ nvidia,pins = "pex_l5_rst_n_pgg1";
+ nvidia,schmitt = <TEGRA_PIN_DISABLE>;
+ nvidia,enable-input = <TEGRA_PIN_DISABLE>;
+ nvidia,io-hv = <TEGRA_PIN_ENABLE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt
deleted file mode 100644
index 3c8ce28baad6..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.txt
+++ /dev/null
@@ -1,143 +0,0 @@
-NVIDIA Tegra20 pinmux controller
-
-Required properties:
-- compatible: "nvidia,tegra20-pinmux"
-- reg: Should contain the register physical address and length for each of
- the tri-state, mux, pull-up/down, and pad control register sets.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-Tegra's pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, tristate, drive strength, etc.
-
-The name of each subnode is not important; all subnodes should be enumerated
-and processed purely based on their content.
-
-Each subnode only affects those parameters that are explicitly listed. In
-other words, a subnode that lists a mux function but no pin configuration
-parameters implies no information about any pin configuration parameters.
-Similarly, a pin subnode that describes a pullup parameter implies no
-information about e.g. the mux function or tristate parameter. For this
-reason, even seemingly boolean values are actually tristates in this binding:
-unspecified, off, or on. Unspecified is represented as an absent property,
-and off/on are represented as integer values 0 and 1.
-
-Required subnode-properties:
-- nvidia,pins : An array of strings. Each string contains the name of a pin or
- group. Valid values for these names are listed below.
-
-Optional subnode-properties:
-- nvidia,function: A string containing the name of the function to mux to the
- pin or group. Valid values for function names are listed below. See the Tegra
- TRM to determine which are valid for each pin or group.
-- nvidia,pull: Integer, representing the pull-down/up to apply to the pin.
- 0: none, 1: down, 2: up.
-- nvidia,tristate: Integer.
- 0: drive, 1: tristate.
-- nvidia,high-speed-mode: Integer. Enable high speed mode the pins.
- 0: no, 1: yes.
-- nvidia,schmitt: Integer. Enables Schmitt Trigger on the input.
- 0: no, 1: yes.
-- nvidia,low-power-mode: Integer. Valid values 0-3. 0 is least power, 3 is
- most power. Controls the drive power or current. See "Low Power Mode"
- or "LPMD1" and "LPMD0" in the Tegra TRM.
-- nvidia,pull-down-strength: Integer. Controls drive strength. 0 is weakest.
- The range of valid values depends on the pingroup. See "CAL_DRVDN" in the
- Tegra TRM.
-- nvidia,pull-up-strength: Integer. Controls drive strength. 0 is weakest.
- The range of valid values depends on the pingroup. See "CAL_DRVUP" in the
- Tegra TRM.
-- nvidia,slew-rate-rising: Integer. Controls rising signal slew rate. 0 is
- fastest. The range of valid values depends on the pingroup. See
- "DRVDN_SLWR" in the Tegra TRM.
-- nvidia,slew-rate-falling: Integer. Controls falling signal slew rate. 0 is
- fastest. The range of valid values depends on the pingroup. See
- "DRVUP_SLWF" in the Tegra TRM.
-
-Note that many of these properties are only valid for certain specific pins
-or groups. See the Tegra TRM and various pinmux spreadsheets for complete
-details regarding which groups support which functionality. The Linux pinctrl
-driver may also be a useful reference, since it consolidates, disambiguates,
-and corrects data from all those sources.
-
-Valid values for pin and group names are:
-
- mux groups:
-
- These all support nvidia,function, nvidia,tristate, and many support
- nvidia,pull.
-
- ata, atb, atc, atd, ate, cdev1, cdev2, crtp, csus, dap1, dap2, dap3, dap4,
- ddc, dta, dtb, dtc, dtd, dte, dtf, gma, gmb, gmc, gmd, gme, gpu, gpu7,
- gpv, hdint, i2cp, irrx, irtx, kbca, kbcb, kbcc, kbcd, kbce, kbcf, lcsn,
- ld0, ld1, ld2, ld3, ld4, ld5, ld6, ld7, ld8, ld9, ld10, ld11, ld12, ld13,
- ld14, ld15, ld16, ld17, ldc, ldi, lhp0, lhp1, lhp2, lhs, lm0, lm1, lpp,
- lpw0, lpw1, lpw2, lsc0, lsc1, lsck, lsda, lsdi, lspi, lvp0, lvp1, lvs,
- owc, pmc, pta, rm, sdb, sdc, sdd, sdio1, slxa, slxc, slxd, slxk, spdi,
- spdo, spia, spib, spic, spid, spie, spif, spig, spih, uaa, uab, uac, uad,
- uca, ucb, uda.
-
- tristate groups:
-
- These only support nvidia,pull.
-
- ck32, ddrc, pmca, pmcb, pmcc, pmcd, pmce, xm2c, xm2d, ls, lc, ld17_0,
- ld19_18, ld21_20, ld23_22.
-
- drive groups:
-
- With some exceptions, these support nvidia,high-speed-mode,
- nvidia,schmitt, nvidia,low-power-mode, nvidia,pull-down-strength,
- nvidia,pull-up-strength, nvidia,slew-rate-rising, nvidia,slew-rate-falling.
-
- drive_ao1, drive_ao2, drive_at1, drive_at2, drive_cdev1, drive_cdev2,
- drive_csus, drive_dap1, drive_dap2, drive_dap3, drive_dap4, drive_dbg,
- drive_lcd1, drive_lcd2, drive_sdmmc2, drive_sdmmc3, drive_spi, drive_uaa,
- drive_uab, drive_uart2, drive_uart3, drive_vi1, drive_vi2, drive_xm2a,
- drive_xm2c, drive_xm2d, drive_xm2clk, drive_sdio1, drive_crt, drive_ddc,
- drive_gma, drive_gmb, drive_gmc, drive_gmd, drive_gme, drive_owr,
- drive_uda.
-
-Valid values for nvidia,functions are:
-
- ahb_clk, apb_clk, audio_sync, crt, dap1, dap2, dap3, dap4, dap5,
- displaya, displayb, emc_test0_dll, emc_test1_dll, gmi, gmi_int,
- hdmi, i2cp, i2c1, i2c2, i2c3, ide, irda, kbc, mio, mipi_hs, nand,
- osc, owr, pcie, plla_out, pllc_out1, pllm_out1, pllp_out2, pllp_out3,
- pllp_out4, pwm, pwr_intr, pwr_on, rsvd1, rsvd2, rsvd3, rsvd4, rtck,
- sdio1, sdio2, sdio3, sdio4, sflash, spdif, spi1, spi2, spi2_alt,
- spi3, spi4, trace, twc, uarta, uartb, uartc, uartd, uarte, ulpi,
- vi, vi_sensor_clk, xio
-
-Example:
-
- pinctrl@70000000 {
- compatible = "nvidia,tegra20-pinmux";
- reg = < 0x70000014 0x10 /* Tri-state registers */
- 0x70000080 0x20 /* Mux registers */
- 0x700000a0 0x14 /* Pull-up/down registers */
- 0x70000868 0xa8 >; /* Pad control registers */
- };
-
-Example board file extract:
-
- pinctrl@70000000 {
- sdio4_default: sdio4_default {
- atb {
- nvidia,pins = "atb", "gma", "gme";
- nvidia,function = "sdio4";
- nvidia,pull = <0>;
- nvidia,tristate = <0>;
- };
- };
- };
-
- sdhci@c8000600 {
- pinctrl-names = "default";
- pinctrl-0 = <&sdio4_default>;
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.yaml b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.yaml
new file mode 100644
index 000000000000..432ea40209a8
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra20-pinmux.yaml
@@ -0,0 +1,112 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/nvidia,tegra20-pinmux.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Tegra20 Pinmux Controller
+
+maintainers:
+ - Thierry Reding <thierry.reding@gmail.com>
+ - Jon Hunter <jonathanh@nvidia.com>
+
+properties:
+ compatible:
+ const: nvidia,tegra20-pinmux
+
+ reg:
+ items:
+ - description: tri-state registers
+ - description: mux register
+ - description: pull-up/down registers
+ - description: pad control registers
+
+patternProperties:
+ "^pinmux(-[a-z0-9-_]+)?$":
+ type: object
+ properties:
+ phandle: true
+
+ # pin groups
+ additionalProperties:
+ $ref: nvidia,tegra-pinmux-common.yaml
+ additionalProperties: false
+ properties:
+ nvidia,pins:
+ items:
+ enum: [ ata, atb, atc, atd, ate, cdev1, cdev2, crtp, csus, dap1,
+ dap2, dap3, dap4, ddc, dta, dtb, dtc, dtd, dte, dtf, gma,
+ gmb, gmc, gmd, gme, gpu, gpu7, gpv, hdint, i2cp, irrx,
+ irtx, kbca, kbcb, kbcc, kbcd, kbce, kbcf, lcsn, ld0, ld1,
+ ld2, ld3, ld4, ld5, ld6, ld7, ld8, ld9, ld10, ld11, ld12,
+ ld13, ld14, ld15, ld16, ld17, ldc, ldi, lhp0, lhp1, lhp2,
+ lhs, lm0, lm1, lpp, lpw0, lpw1, lpw2, lsc0, lsc1, lsck,
+ lsda, lsdi, lspi, lvp0, lvp1, lvs, owc, pmc, pta, rm, sdb,
+ sdc, sdd, sdio1, slxa, slxc, slxd, slxk, spdi, spdo, spia,
+ spib, spic, spid, spie, spif, spig, spih, uaa, uab, uac,
+ uad, uca, ucb, uda,
+ # tristate groups
+ ck32, ddrc, pmca, pmcb, pmcc, pmcd, pmce, xm2c, xm2d, ls,
+ lc, ld17_0, ld19_18, ld21_20, ld23_22,
+ # drive groups
+ drive_ao1, drive_ao2, drive_at1, drive_at2, drive_cdev1,
+ drive_cdev2, drive_csus, drive_dap1, drive_dap2,
+ drive_dap3, drive_dap4, drive_dbg, drive_lcd1, drive_lcd2,
+ drive_sdmmc2, drive_sdmmc3, drive_spi, drive_uaa,
+ drive_uab, drive_uart2, drive_uart3, drive_vi1, drive_vi2,
+ drive_xm2a, drive_xm2c, drive_xm2d, drive_xm2clk,
+ drive_sdio1, drive_crt, drive_ddc, drive_gma, drive_gmb,
+ drive_gmc, drive_gmd, drive_gme, drive_owr, drive_uda ]
+
+ nvidia,function:
+ enum: [ ahb_clk, apb_clk, audio_sync, crt, dap1, dap2, dap3, dap4,
+ dap5, displaya, displayb, emc_test0_dll, emc_test1_dll, gmi,
+ gmi_int, hdmi, i2cp, i2c1, i2c2, i2c3, ide, irda, kbc, mio,
+ mipi_hs, nand, osc, owr, pcie, plla_out, pllc_out1,
+ pllm_out1, pllp_out2, pllp_out3, pllp_out4, pwm, pwr_intr,
+ pwr_on, rsvd1, rsvd2, rsvd3, rsvd4, rtck, sdio1, sdio2,
+ sdio3, sdio4, sflash, spdif, spi1, spi2, spi2_alt, spi3,
+ spi4, trace, twc, uarta, uartb, uartc, uartd, uarte, ulpi,
+ vi, vi_sensor_clk, xio ]
+
+ nvidia,pull: true
+ nvidia,tristate: true
+ nvidia,schmitt: true
+ nvidia,pull-down-strength: true
+ nvidia,pull-up-strength: true
+ nvidia,high-speed-mode: true
+ nvidia,low-power-mode: true
+ nvidia,slew-rate-rising: true
+ nvidia,slew-rate-falling: true
+
+ required:
+ - nvidia,pins
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+examples:
+ - |
+ #include <dt-bindings/clock/tegra20-car.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ pinctrl@70000000 {
+ compatible = "nvidia,tegra20-pinmux";
+ reg = <0x70000014 0x10>, /* Tri-state registers */
+ <0x70000080 0x20>, /* Mux registers */
+ <0x700000a0 0x14>, /* Pull-up/down registers */
+ <0x70000868 0xa8>; /* Pad control registers */
+
+ pinmux {
+ atb {
+ nvidia,pins = "atb", "gma", "gme";
+ nvidia,function = "sdio4";
+ nvidia,pull = <0>;
+ nvidia,tristate = <0>;
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra210-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra210-pinmux.txt
deleted file mode 100644
index 85f211436b8e..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra210-pinmux.txt
+++ /dev/null
@@ -1,166 +0,0 @@
-NVIDIA Tegra210 pinmux controller
-
-Required properties:
-- compatible: "nvidia,tegra210-pinmux"
-- reg: Should contain a list of base address and size pairs for:
- - first entry: The APB_MISC_GP_*_PADCTRL registers (pad control)
- - second entry: The PINMUX_AUX_* registers (pinmux)
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-Tegra's pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, tristate, drive strength, etc.
-
-The name of each subnode is not important; all subnodes should be enumerated
-and processed purely based on their content.
-
-Each subnode only affects those parameters that are explicitly listed. In
-other words, a subnode that lists a mux function but no pin configuration
-parameters implies no information about any pin configuration parameters.
-Similarly, a pin subnode that describes a pullup parameter implies no
-information about e.g. the mux function or tristate parameter. For this
-reason, even seemingly boolean values are actually tristates in this binding:
-unspecified, off, or on. Unspecified is represented as an absent property,
-and off/on are represented as integer values 0 and 1.
-
-See the TRM to determine which properties and values apply to each pin/group.
-Macro values for property values are defined in
-include/dt-binding/pinctrl/pinctrl-tegra.h.
-
-Required subnode-properties:
-- nvidia,pins : An array of strings. Each string contains the name of a pin or
- group. Valid values for these names are listed below.
-
-Optional subnode-properties:
-- nvidia,function: A string containing the name of the function to mux to the
- pin or group.
-- nvidia,pull: Integer, representing the pull-down/up to apply to the pin.
- 0: none, 1: down, 2: up.
-- nvidia,tristate: Integer.
- 0: drive, 1: tristate.
-- nvidia,enable-input: Integer. Enable the pin's input path.
- enable :TEGRA_PIN_ENABLE and
- disable or output only: TEGRA_PIN_DISABLE.
-- nvidia,open-drain: Integer.
- enable: TEGRA_PIN_ENABLE.
- disable: TEGRA_PIN_DISABLE.
-- nvidia,lock: Integer. Lock the pin configuration against further changes
- until reset.
- enable: TEGRA_PIN_ENABLE.
- disable: TEGRA_PIN_DISABLE.
-- nvidia,io-hv: Integer. Select high-voltage receivers.
- normal: TEGRA_PIN_DISABLE
- high: TEGRA_PIN_ENABLE
-- nvidia,high-speed-mode: Integer. Enable high speed mode the pins.
- normal: TEGRA_PIN_DISABLE
- high: TEGRA_PIN_ENABLE
-- nvidia,schmitt: Integer. Enables Schmitt Trigger on the input.
- normal: TEGRA_PIN_DISABLE
- high: TEGRA_PIN_ENABLE
-- nvidia,drive-type: Integer. Valid range 0...3.
-- nvidia,pull-down-strength: Integer. Controls drive strength. 0 is weakest.
- The range of valid values depends on the pingroup. See "CAL_DRVDN" in the
- Tegra TRM.
-- nvidia,pull-up-strength: Integer. Controls drive strength. 0 is weakest.
- The range of valid values depends on the pingroup. See "CAL_DRVUP" in the
- Tegra TRM.
-- nvidia,slew-rate-rising: Integer. Controls rising signal slew rate. 0 is
- fastest. The range of valid values depends on the pingroup. See
- "DRVDN_SLWR" in the Tegra TRM.
-- nvidia,slew-rate-falling: Integer. Controls falling signal slew rate. 0 is
- fastest. The range of valid values depends on the pingroup. See
- "DRVUP_SLWF" in the Tegra TRM.
-
-Valid values for pin and group names (nvidia,pin) are:
-
- Mux groups:
-
- These correspond to Tegra PINMUX_AUX_* (pinmux) registers. Any property
- that exists in those registers may be set for the following pin names.
-
- In Tegra210, many pins also have a dedicated APB_MISC_GP_*_PADCTRL
- register. Where that is true, and property that exists in that register
- may also be set on the following pin names.
-
- als_prox_int_px3, ap_ready_pv5, ap_wake_bt_ph3, ap_wake_nfc_ph7,
- aud_mclk_pbb0, batt_bcl, bt_rst_ph4, bt_wake_ap_ph5, button_home_py1,
- button_power_on_px5, button_slide_sw_py0, button_vol_down_px7,
- button_vol_up_px6, cam1_mclk_ps0, cam1_pwdn_ps7, cam1_strobe_pt1,
- cam2_mclk_ps1, cam2_pwdn_pt0, cam_af_en_ps5, cam_flash_en_ps6,
- cam_i2c_scl_ps2, cam_i2c_sda_ps3, cam_rst_ps4cam_rst_ps4, clk_32k_in,
- clk_32k_out_py5, clk_req, core_pwr_req, cpu_pwr_req, dap1_din_pb1,
- dap1_dout_pb2, dap1_fs_pb0, dap1_sclk_pb3, dap2_din_paa2, dap2_dout_paa3,
- dap2_fs_paa0, dap2_sclk_paa1, dap4_din_pj5, dap4_dout_pj6, dap4_fs_pj4,
- dap4_sclk_pj7, dmic1_clk_pe0, dmic1_dat_pe1, dmic2_clk_pe2, dmic2_dat_pe3,
- dmic3_clk_pe4, dmic3_dat_pe5, dp_hpd0_pcc6, dvfs_clk_pbb2, dvfs_pwm_pbb1,
- gen1_i2c_scl_pj1, gen1_i2c_sda_pj0, gen2_i2c_scl_pj2, gen2_i2c_sda_pj3,
- gen3_i2c_scl_pf0, gen3_i2c_sda_pf1, gpio_x1_aud_pbb3, gpio_x3_aud_pbb4,
- gps_en_pi2, gps_rst_pi3, hdmi_cec_pcc0, hdmi_int_dp_hpd_pcc1, jtag_rtck,
- lcd_bl_en_pv1, lcd_bl_pwm_pv0, lcd_gpio1_pv3, lcd_gpio2_pv4, lcd_rst_pv2,
- lcd_te_py2, modem_wake_ap_px0, motion_int_px2, nfc_en_pi0, nfc_int_pi1,
- pa6, pcc7, pe6, pe7, pex_l0_clkreq_n_pa1, pex_l0_rst_n_pa0,
- pex_l1_clkreq_n_pa4, pex_l1_rst_n_pa3, pex_wake_n_pa2, ph6, pk0, pk1, pk2,
- pk3, pk4, pk5, pk6, pk7, pl0, pl1, pwr_i2c_scl_py3, pwr_i2c_sda_py4,
- pwr_int_n, pz0, pz1, pz2, pz3, pz4, pz5, qspi_cs_n_pee1, qspi_io0_pee2,
- qspi_io1_pee3, qspi_io2_pee4, qspi_io3_pee5, qspi_sck_pee0,
- sata_led_active_pa5, sdmmc1_clk_pm0, sdmmc1_cmd_pm1, sdmmc1_dat0_pm5,
- sdmmc1_dat1_pm4, sdmmc1_dat2_pm3, sdmmc1_dat3_pm2, sdmmc3_clk_pp0,
- sdmmc3_cmd_pp1, sdmmc3_dat0_pp5, sdmmc3_dat1_pp4, sdmmc3_dat2_pp3,
- sdmmc3_dat3_pp2, shutdown, spdif_in_pcc3, spdif_out_pcc2, spi1_cs0_pc3,
- spi1_cs1_pc4, spi1_miso_pc1, spi1_mosi_pc0, spi1_sck_pc2, spi2_cs0_pb7,
- spi2_cs1_pdd0, spi2_miso_pb5, spi2_mosi_pb4, spi2_sck_pb6, spi4_cs0_pc6,
- spi4_miso_pd0, spi4_mosi_pc7, spi4_sck_pc5, temp_alert_px4, touch_clk_pv7,
- touch_int_px1, touch_rst_pv6, uart1_cts_pu3, uart1_rts_pu2, uart1_rx_pu1,
- uart1_tx_pu0, uart2_cts_pg3, uart2_rts_pg2, uart2_rx_pg1, uart2_tx_pg0,
- uart3_cts_pd4, uart3_rts_pd3, uart3_rx_pd2, uart3_tx_pd1, uart4_cts_pi7,
- uart4_rts_pi6, uart4_rx_pi5, uart4_tx_pi4, usb_vbus_en0_pcc4,
- usb_vbus_en1_pcc5, wifi_en_ph0, wifi_rst_ph1, wifi_wake_ap_ph2
-
- Drive groups:
-
- These correspond to the Tegra APB_MISC_GP_*_PADCTRL (pad control)
- registers. Note that where one of these registers controls a single pin
- for which a PINMUX_AUX_* exists, see the list above for the pin name to
- use when configuring the pinmux.
-
- pa6, pcc7, pe6, pe7, ph6, pk0, pk1, pk2, pk3, pk4, pk5, pk6, pk7, pl0, pl1,
- pz0, pz1, pz2, pz3, pz4, pz5, sdmmc1, sdmmc2, sdmmc3, sdmmc4
-
-Valid values for nvidia,functions are:
-
- aud, bcl, blink, ccla, cec, cldvfs, clk, core, cpu, displaya, displayb,
- dmic1, dmic2, dmic3, dp, dtv, extperiph3, i2c1, i2c2, i2c3, i2cpmu, i2cvi,
- i2s1, i2s2, i2s3, i2s4a, i2s4b, i2s5a, i2s5b, iqc0, iqc1, jtag, pe, pe0,
- pe1, pmi, pwm0, pwm1, pwm2, pwm3, qspi, rsvd0, rsvd1, rsvd2, rsvd3, sata,
- sdmmc1, sdmmc3, shutdown, soc, sor0, sor1, spdif, spi1, spi2, spi3, spi4,
- sys, touch, uart, uarta, uartb, uartc, uartd, usb, vgp1, vgp2, vgp3, vgp4,
- vgp5, vgp6, vimclk, vimclk2
-
-Example:
-
- pinmux: pinmux@70000800 {
- compatible = "nvidia,tegra210-pinmux";
- reg = <0x0 0x700008d4 0x0 0x2a8>, /* Pad control registers */
- <0x0 0x70003000 0x0 0x1000>; /* Mux registers */
-
- pinctrl-names = "boot";
- pinctrl-0 = <&state_boot>;
-
- state_boot: pinmux {
- gen1_i2c_scl_pj1 {
- nvidia,pins = "gen1_i2c_scl_pj1",
- nvidia,function = "i2c1";
- nvidia,pull = <TEGRA_PIN_PULL_NONE>;
- nvidia,tristate = <TEGRA_PIN_DISABLE>;
- nvidia,enable-input = <TEGRA_PIN_ENABLE>;
- nvidia,open-drain = <TEGRA_PIN_ENABLE>;
- nvidia,io-hv = <TEGRA_PIN_ENABLE>;
- };
- };
- };
-};
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra210-pinmux.yaml b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra210-pinmux.yaml
new file mode 100644
index 000000000000..28ae2e6d0cbc
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra210-pinmux.yaml
@@ -0,0 +1,142 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/nvidia,tegra210-pinmux.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Tegra210 Pinmux Controller
+
+maintainers:
+ - Thierry Reding <thierry.reding@gmail.com>
+ - Jon Hunter <jonathanh@nvidia.com>
+
+properties:
+ compatible:
+ const: nvidia,tegra210-pinmux
+
+ reg:
+ items:
+ - description: APB_MISC_GP_*_PADCTRL register (pad control)
+ - description: PINMUX_AUX_* registers (pinmux)
+
+patternProperties:
+ "^pinmux(-[a-z0-9-_]+)?$":
+ type: object
+ properties:
+ phandle: true
+
+ # pin groups
+ additionalProperties:
+ $ref: nvidia,tegra-pinmux-common.yaml
+ additionalProperties: false
+ properties:
+ nvidia,pins:
+ items:
+ enum: [ als_prox_int_px3, ap_ready_pv5, ap_wake_bt_ph3,
+ ap_wake_nfc_ph7, aud_mclk_pbb0, batt_bcl, bt_rst_ph4,
+ bt_wake_ap_ph5, button_home_py1, button_power_on_px5,
+ button_slide_sw_py0, button_vol_down_px7,
+ button_vol_up_px6, cam1_mclk_ps0, cam1_pwdn_ps7,
+ cam1_strobe_pt1, cam2_mclk_ps1, cam2_pwdn_pt0,
+ cam_af_en_ps5, cam_flash_en_ps6, cam_i2c_scl_ps2,
+ cam_i2c_sda_ps3, cam_rst_ps4, clk_32k_in, clk_32k_out_py5,
+ clk_req, core_pwr_req, cpu_pwr_req, dap1_din_pb1,
+ dap1_dout_pb2, dap1_fs_pb0, dap1_sclk_pb3, dap2_din_paa2,
+ dap2_dout_paa3, dap2_fs_paa0, dap2_sclk_paa1, dap4_din_pj5,
+ dap4_dout_pj6, dap4_fs_pj4, dap4_sclk_pj7, dmic1_clk_pe0,
+ dmic1_dat_pe1, dmic2_clk_pe2, dmic2_dat_pe3, dmic3_clk_pe4,
+ dmic3_dat_pe5, dp_hpd0_pcc6, dvfs_clk_pbb2, dvfs_pwm_pbb1,
+ gen1_i2c_scl_pj1, gen1_i2c_sda_pj0, gen2_i2c_scl_pj2,
+ gen2_i2c_sda_pj3, gen3_i2c_scl_pf0, gen3_i2c_sda_pf1,
+ gpio_x1_aud_pbb3, gpio_x3_aud_pbb4, gps_en_pi2,
+ gps_rst_pi3, hdmi_cec_pcc0, hdmi_int_dp_hpd_pcc1,
+ jtag_rtck, lcd_bl_en_pv1, lcd_bl_pwm_pv0, lcd_gpio1_pv3,
+ lcd_gpio2_pv4, lcd_rst_pv2, lcd_te_py2, modem_wake_ap_px0,
+ motion_int_px2, nfc_en_pi0, nfc_int_pi1, pa6, pcc7, pe6,
+ pe7, pex_l0_clkreq_n_pa1, pex_l0_rst_n_pa0,
+ pex_l1_clkreq_n_pa4, pex_l1_rst_n_pa3, pex_wake_n_pa2, ph6,
+ pk0, pk1, pk2, pk3, pk4, pk5, pk6, pk7, pl0, pl1,
+ pwr_i2c_scl_py3, pwr_i2c_sda_py4, pwr_int_n, pz0, pz1, pz2,
+ pz3, pz4, pz5, qspi_cs_n_pee1, qspi_io0_pee2,
+ qspi_io1_pee3, qspi_io2_pee4, qspi_io3_pee5, qspi_sck_pee0,
+ sata_led_active_pa5, sdmmc1_clk_pm0, sdmmc1_cmd_pm1,
+ sdmmc1_dat0_pm5, sdmmc1_dat1_pm4, sdmmc1_dat2_pm3,
+ sdmmc1_dat3_pm2, sdmmc3_clk_pp0, sdmmc3_cmd_pp1,
+ sdmmc3_dat0_pp5, sdmmc3_dat1_pp4, sdmmc3_dat2_pp3,
+ sdmmc3_dat3_pp2, shutdown, spdif_in_pcc3, spdif_out_pcc2,
+ spi1_cs0_pc3, spi1_cs1_pc4, spi1_miso_pc1, spi1_mosi_pc0,
+ spi1_sck_pc2, spi2_cs0_pb7, spi2_cs1_pdd0, spi2_miso_pb5,
+ spi2_mosi_pb4, spi2_sck_pb6, spi4_cs0_pc6, spi4_miso_pd0,
+ spi4_mosi_pc7, spi4_sck_pc5, temp_alert_px4, touch_clk_pv7,
+ touch_int_px1, touch_rst_pv6, uart1_cts_pu3, uart1_rts_pu2,
+ uart1_rx_pu1, uart1_tx_pu0, uart2_cts_pg3, uart2_rts_pg2,
+ uart2_rx_pg1, uart2_tx_pg0, uart3_cts_pd4, uart3_rts_pd3,
+ uart3_rx_pd2, uart3_tx_pd1, uart4_cts_pi7, uart4_rts_pi6,
+ uart4_rx_pi5, uart4_tx_pi4, usb_vbus_en0_pcc4,
+ usb_vbus_en1_pcc5, wifi_en_ph0, wifi_rst_ph1,
+ wifi_wake_ap_ph2,
+ # drive groups
+ drive_pa6, drive_pcc7, drive_pe6, drive_pe7, drive_ph6,
+ drive_pk0, drive_pk1, drive_pk2, drive_pk3, drive_pk4,
+ drive_pk5, drive_pk6, drive_pk7, drive_pl0, drive_pl1,
+ drive_pz0, drive_pz1, drive_pz2, drive_pz3, drive_pz4,
+ drive_pz5, drive_sdmmc1, drive_sdmmc2, drive_sdmmc3,
+ drive_sdmmc4 ]
+
+ nvidia,function:
+ enum: [ aud, bcl, blink, ccla, cec, cldvfs, clk, core, cpu, displaya,
+ displayb, dmic1, dmic2, dmic3, dp, dtv, extperiph3, i2c1,
+ i2c2, i2c3, i2cpmu, i2cvi, i2s1, i2s2, i2s3, i2s4a, i2s4b,
+ i2s5a, i2s5b, iqc0, iqc1, jtag, pe, pe0, pe1, pmi, pwm0,
+ pwm1, pwm2, pwm3, qspi, rsvd0, rsvd1, rsvd2, rsvd3, sata,
+ sdmmc1, sdmmc3, shutdown, soc, sor0, sor1, spdif, spi1, spi2,
+ spi3, spi4, sys, touch, uart, uarta, uartb, uartc, uartd,
+ usb, vgp1, vgp2, vgp3, vgp4, vgp5, vgp6, vimclk, vimclk2 ]
+
+ nvidia,pull: true
+ nvidia,tristate: true
+ nvidia,pull-down-strength: true
+ nvidia,pull-up-strength: true
+ nvidia,high-speed-mode: true
+ nvidia,enable-input: true
+ nvidia,open-drain: true
+ nvidia,lock: true
+ nvidia,drive-type: true
+ nvidia,io-hv: true
+ nvidia,slew-rate-rising: true
+ nvidia,slew-rate-falling: true
+
+ required:
+ - nvidia,pins
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+examples:
+ - |
+ #include <dt-bindings/pinctrl/pinctrl-tegra.h>
+
+ pinmux: pinmux@70000800 {
+ compatible = "nvidia,tegra210-pinmux";
+ reg = <0x700008d4 0x02a8>, /* Pad control registers */
+ <0x70003000 0x1000>; /* Mux registers */
+
+ pinctrl-names = "boot";
+ pinctrl-0 = <&state_boot>;
+
+ state_boot: pinmux {
+ gen1_i2c_scl_pj1 {
+ nvidia,pins = "gen1_i2c_scl_pj1";
+ nvidia,function = "i2c1";
+ nvidia,pull = <TEGRA_PIN_PULL_NONE>;
+ nvidia,tristate = <TEGRA_PIN_DISABLE>;
+ nvidia,enable-input = <TEGRA_PIN_ENABLE>;
+ nvidia,open-drain = <TEGRA_PIN_ENABLE>;
+ nvidia,io-hv = <TEGRA_PIN_ENABLE>;
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt
deleted file mode 100644
index 0e6354c11e6d..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.txt
+++ /dev/null
@@ -1,144 +0,0 @@
-NVIDIA Tegra30 pinmux controller
-
-The Tegra30 pinctrl binding is very similar to the Tegra20 pinctrl binding,
-as described in nvidia,tegra20-pinmux.txt. In fact, this document assumes
-that binding as a baseline, and only documents the differences between the
-two bindings.
-
-Required properties:
-- compatible: "nvidia,tegra30-pinmux"
-- reg: Should contain the register physical address and length for each of
- the pad control and mux registers.
-
-Tegra30 adds the following optional properties for pin configuration subnodes:
-- nvidia,enable-input: Integer. Enable the pin's input path. 0: no, 1: yes.
-- nvidia,open-drain: Integer. Enable open drain mode. 0: no, 1: yes.
-- nvidia,lock: Integer. Lock the pin configuration against further changes
- until reset. 0: no, 1: yes.
-- nvidia,io-reset: Integer. Reset the IO path. 0: no, 1: yes.
-
-As with Tegra20, see the Tegra TRM for complete details regarding which groups
-support which functionality.
-
-Valid values for pin and group names are:
-
- per-pin mux groups:
-
- These all support nvidia,function, nvidia,tristate, nvidia,pull,
- nvidia,enable-input, nvidia,lock. Some support nvidia,open-drain,
- nvidia,io-reset.
-
- clk_32k_out_pa0, uart3_cts_n_pa1, dap2_fs_pa2, dap2_sclk_pa3,
- dap2_din_pa4, dap2_dout_pa5, sdmmc3_clk_pa6, sdmmc3_cmd_pa7, gmi_a17_pb0,
- gmi_a18_pb1, lcd_pwr0_pb2, lcd_pclk_pb3, sdmmc3_dat3_pb4, sdmmc3_dat2_pb5,
- sdmmc3_dat1_pb6, sdmmc3_dat0_pb7, uart3_rts_n_pc0, lcd_pwr1_pc1,
- uart2_txd_pc2, uart2_rxd_pc3, gen1_i2c_scl_pc4, gen1_i2c_sda_pc5,
- lcd_pwr2_pc6, gmi_wp_n_pc7, sdmmc3_dat5_pd0, sdmmc3_dat4_pd1, lcd_dc1_pd2,
- sdmmc3_dat6_pd3, sdmmc3_dat7_pd4, vi_d1_pd5, vi_vsync_pd6, vi_hsync_pd7,
- lcd_d0_pe0, lcd_d1_pe1, lcd_d2_pe2, lcd_d3_pe3, lcd_d4_pe4, lcd_d5_pe5,
- lcd_d6_pe6, lcd_d7_pe7, lcd_d8_pf0, lcd_d9_pf1, lcd_d10_pf2, lcd_d11_pf3,
- lcd_d12_pf4, lcd_d13_pf5, lcd_d14_pf6, lcd_d15_pf7, gmi_ad0_pg0,
- gmi_ad1_pg1, gmi_ad2_pg2, gmi_ad3_pg3, gmi_ad4_pg4, gmi_ad5_pg5,
- gmi_ad6_pg6, gmi_ad7_pg7, gmi_ad8_ph0, gmi_ad9_ph1, gmi_ad10_ph2,
- gmi_ad11_ph3, gmi_ad12_ph4, gmi_ad13_ph5, gmi_ad14_ph6, gmi_ad15_ph7,
- gmi_wr_n_pi0, gmi_oe_n_pi1, gmi_dqs_pi2, gmi_cs6_n_pi3, gmi_rst_n_pi4,
- gmi_iordy_pi5, gmi_cs7_n_pi6, gmi_wait_pi7, gmi_cs0_n_pj0, lcd_de_pj1,
- gmi_cs1_n_pj2, lcd_hsync_pj3, lcd_vsync_pj4, uart2_cts_n_pj5,
- uart2_rts_n_pj6, gmi_a16_pj7, gmi_adv_n_pk0, gmi_clk_pk1, gmi_cs4_n_pk2,
- gmi_cs2_n_pk3, gmi_cs3_n_pk4, spdif_out_pk5, spdif_in_pk6, gmi_a19_pk7,
- vi_d2_pl0, vi_d3_pl1, vi_d4_pl2, vi_d5_pl3, vi_d6_pl4, vi_d7_pl5,
- vi_d8_pl6, vi_d9_pl7, lcd_d16_pm0, lcd_d17_pm1, lcd_d18_pm2, lcd_d19_pm3,
- lcd_d20_pm4, lcd_d21_pm5, lcd_d22_pm6, lcd_d23_pm7, dap1_fs_pn0,
- dap1_din_pn1, dap1_dout_pn2, dap1_sclk_pn3, lcd_cs0_n_pn4, lcd_sdout_pn5,
- lcd_dc0_pn6, hdmi_int_pn7, ulpi_data7_po0, ulpi_data0_po1, ulpi_data1_po2,
- ulpi_data2_po3, ulpi_data3_po4, ulpi_data4_po5, ulpi_data5_po6,
- ulpi_data6_po7, dap3_fs_pp0, dap3_din_pp1, dap3_dout_pp2, dap3_sclk_pp3,
- dap4_fs_pp4, dap4_din_pp5, dap4_dout_pp6, dap4_sclk_pp7, kb_col0_pq0,
- kb_col1_pq1, kb_col2_pq2, kb_col3_pq3, kb_col4_pq4, kb_col5_pq5,
- kb_col6_pq6, kb_col7_pq7, kb_row0_pr0, kb_row1_pr1, kb_row2_pr2,
- kb_row3_pr3, kb_row4_pr4, kb_row5_pr5, kb_row6_pr6, kb_row7_pr7,
- kb_row8_ps0, kb_row9_ps1, kb_row10_ps2, kb_row11_ps3, kb_row12_ps4,
- kb_row13_ps5, kb_row14_ps6, kb_row15_ps7, vi_pclk_pt0, vi_mclk_pt1,
- vi_d10_pt2, vi_d11_pt3, vi_d0_pt4, gen2_i2c_scl_pt5, gen2_i2c_sda_pt6,
- sdmmc4_cmd_pt7, pu0, pu1, pu2, pu3, pu4, pu5, pu6, jtag_rtck_pu7, pv0,
- pv1, pv2, pv3, ddc_scl_pv4, ddc_sda_pv5, crt_hsync_pv6, crt_vsync_pv7,
- lcd_cs1_n_pw0, lcd_m1_pw1, spi2_cs1_n_pw2, spi2_cs2_n_pw3, clk1_out_pw4,
- clk2_out_pw5, uart3_txd_pw6, uart3_rxd_pw7, spi2_mosi_px0, spi2_miso_px1,
- spi2_sck_px2, spi2_cs0_n_px3, spi1_mosi_px4, spi1_sck_px5, spi1_cs0_n_px6,
- spi1_miso_px7, ulpi_clk_py0, ulpi_dir_py1, ulpi_nxt_py2, ulpi_stp_py3,
- sdmmc1_dat3_py4, sdmmc1_dat2_py5, sdmmc1_dat1_py6, sdmmc1_dat0_py7,
- sdmmc1_clk_pz0, sdmmc1_cmd_pz1, lcd_sdin_pz2, lcd_wr_n_pz3, lcd_sck_pz4,
- sys_clk_req_pz5, pwr_i2c_scl_pz6, pwr_i2c_sda_pz7, sdmmc4_dat0_paa0,
- sdmmc4_dat1_paa1, sdmmc4_dat2_paa2, sdmmc4_dat3_paa3, sdmmc4_dat4_paa4,
- sdmmc4_dat5_paa5, sdmmc4_dat6_paa6, sdmmc4_dat7_paa7, pbb0,
- cam_i2c_scl_pbb1, cam_i2c_sda_pbb2, pbb3, pbb4, pbb5, pbb6, pbb7,
- cam_mclk_pcc0, pcc1, pcc2, sdmmc4_rst_n_pcc3, sdmmc4_clk_pcc4,
- clk2_req_pcc5, pex_l2_rst_n_pcc6, pex_l2_clkreq_n_pcc7,
- pex_l0_prsnt_n_pdd0, pex_l0_rst_n_pdd1, pex_l0_clkreq_n_pdd2,
- pex_wake_n_pdd3, pex_l1_prsnt_n_pdd4, pex_l1_rst_n_pdd5,
- pex_l1_clkreq_n_pdd6, pex_l2_prsnt_n_pdd7, clk3_out_pee0, clk3_req_pee1,
- clk1_req_pee2, hdmi_cec_pee3, clk_32k_in, core_pwr_req, cpu_pwr_req, owr,
- pwr_int_n.
-
- drive groups:
-
- These all support nvidia,pull-down-strength, nvidia,pull-up-strength,
- nvidia,slew-rate-rising, nvidia,slew-rate-falling. Most but not all
- support nvidia,high-speed-mode, nvidia,schmitt, nvidia,low-power-mode.
-
- ao1, ao2, at1, at2, at3, at4, at5, cdev1, cdev2, cec, crt, csus, dap1,
- dap2, dap3, dap4, dbg, ddc, dev3, gma, gmb, gmc, gmd, gme, gmf, gmg,
- gmh, gpv, lcd1, lcd2, owr, sdio1, sdio2, sdio3, spi, uaa, uab, uart2,
- uart3, uda, vi1.
-
-Valid values for nvidia,functions are:
-
- blink, cec, clk_12m_out, clk_32k_in, core_pwr_req, cpu_pwr_req, crt,
- dap, ddr, dev3, displaya, displayb, dtv, extperiph1, extperiph2,
- extperiph3, gmi, gmi_alt, hda, hdcp, hdmi, hsi, i2c1, i2c2, i2c3,
- i2c4, i2cpwr, i2s0, i2s1, i2s2, i2s3, i2s4, invalid, kbc, mio, nand,
- nand_alt, owr, pcie, pwm0, pwm1, pwm2, pwm3, pwr_int_n, rsvd1, rsvd2,
- rsvd3, rsvd4, rtck, sata, sdmmc1, sdmmc2, sdmmc3, sdmmc4, spdif, spi1,
- spi2, spi2_alt, spi3, spi4, spi5, spi6, sysclk, test, trace, uarta,
- uartb, uartc, uartd, uarte, ulpi, vgp1, vgp2, vgp3, vgp4, vgp5, vgp6,
- vi, vi_alt1, vi_alt2, vi_alt3
-
-Example:
-
- pinctrl@70000000 {
- compatible = "nvidia,tegra30-pinmux";
- reg = < 0x70000868 0xd0 /* Pad control registers */
- 0x70003000 0x3e0 >; /* Mux registers */
- };
-
-Example board file extract:
-
- pinctrl@70000000 {
- sdmmc4_default: pinmux {
- sdmmc4_clk_pcc4 {
- nvidia,pins = "sdmmc4_clk_pcc4",
- "sdmmc4_rst_n_pcc3";
- nvidia,function = "sdmmc4";
- nvidia,pull = <0>;
- nvidia,tristate = <0>;
- };
- sdmmc4_dat0_paa0 {
- nvidia,pins = "sdmmc4_dat0_paa0",
- "sdmmc4_dat1_paa1",
- "sdmmc4_dat2_paa2",
- "sdmmc4_dat3_paa3",
- "sdmmc4_dat4_paa4",
- "sdmmc4_dat5_paa5",
- "sdmmc4_dat6_paa6",
- "sdmmc4_dat7_paa7";
- nvidia,function = "sdmmc4";
- nvidia,pull = <2>;
- nvidia,tristate = <0>;
- };
- };
- };
-
- sdhci@78000400 {
- pinctrl-names = "default";
- pinctrl-0 = <&sdmmc4_default>;
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.yaml b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.yaml
new file mode 100644
index 000000000000..c0eda7848767
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/nvidia,tegra30-pinmux.yaml
@@ -0,0 +1,176 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/nvidia,tegra30-pinmux.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Tegra30 pinmux Controller
+
+maintainers:
+ - Thierry Reding <thierry.reding@gmail.com>
+ - Jon Hunter <jonathanh@nvidia.com>
+
+properties:
+ compatible:
+ const: nvidia,tegra30-pinmux
+
+ reg:
+ items:
+ - description: pad control registers
+ - description: mux registers
+
+patternProperties:
+ "^pinmux(-[a-z0-9-_]+)?$":
+ type: object
+ properties:
+ phandle: true
+
+ # pin groups
+ additionalProperties:
+ $ref: nvidia,tegra-pinmux-common.yaml
+ additionalProperties: false
+ properties:
+ nvidia,pins:
+ items:
+ enum: [ clk_32k_out_pa0, uart3_cts_n_pa1, dap2_fs_pa2,
+ dap2_sclk_pa3, dap2_din_pa4, dap2_dout_pa5, sdmmc3_clk_pa6,
+ sdmmc3_cmd_pa7, gmi_a17_pb0, gmi_a18_pb1, lcd_pwr0_pb2,
+ lcd_pclk_pb3, sdmmc3_dat3_pb4, sdmmc3_dat2_pb5,
+ sdmmc3_dat1_pb6, sdmmc3_dat0_pb7, uart3_rts_n_pc0,
+ lcd_pwr1_pc1, uart2_txd_pc2, uart2_rxd_pc3,
+ gen1_i2c_scl_pc4, gen1_i2c_sda_pc5, lcd_pwr2_pc6,
+ gmi_wp_n_pc7, sdmmc3_dat5_pd0, sdmmc3_dat4_pd1,
+ lcd_dc1_pd2, sdmmc3_dat6_pd3, sdmmc3_dat7_pd4, vi_d1_pd5,
+ vi_vsync_pd6, vi_hsync_pd7, lcd_d0_pe0, lcd_d1_pe1,
+ lcd_d2_pe2, lcd_d3_pe3, lcd_d4_pe4, lcd_d5_pe5, lcd_d6_pe6,
+ lcd_d7_pe7, lcd_d8_pf0, lcd_d9_pf1, lcd_d10_pf2,
+ lcd_d11_pf3, lcd_d12_pf4, lcd_d13_pf5, lcd_d14_pf6,
+ lcd_d15_pf7, gmi_ad0_pg0, gmi_ad1_pg1, gmi_ad2_pg2,
+ gmi_ad3_pg3, gmi_ad4_pg4, gmi_ad5_pg5, gmi_ad6_pg6,
+ gmi_ad7_pg7, gmi_ad8_ph0, gmi_ad9_ph1, gmi_ad10_ph2,
+ gmi_ad11_ph3, gmi_ad12_ph4, gmi_ad13_ph5, gmi_ad14_ph6,
+ gmi_ad15_ph7, gmi_wr_n_pi0, gmi_oe_n_pi1, gmi_dqs_pi2,
+ gmi_cs6_n_pi3, gmi_rst_n_pi4, gmi_iordy_pi5, gmi_cs7_n_pi6,
+ gmi_wait_pi7, gmi_cs0_n_pj0, lcd_de_pj1, gmi_cs1_n_pj2,
+ lcd_hsync_pj3, lcd_vsync_pj4, uart2_cts_n_pj5,
+ uart2_rts_n_pj6, gmi_a16_pj7, gmi_adv_n_pk0, gmi_clk_pk1,
+ gmi_cs4_n_pk2, gmi_cs2_n_pk3, gmi_cs3_n_pk4, spdif_out_pk5,
+ spdif_in_pk6, gmi_a19_pk7, vi_d2_pl0, vi_d3_pl1, vi_d4_pl2,
+ vi_d5_pl3, vi_d6_pl4, vi_d7_pl5, vi_d8_pl6, vi_d9_pl7,
+ lcd_d16_pm0, lcd_d17_pm1, lcd_d18_pm2, lcd_d19_pm3,
+ lcd_d20_pm4, lcd_d21_pm5, lcd_d22_pm6, lcd_d23_pm7,
+ dap1_fs_pn0, dap1_din_pn1, dap1_dout_pn2, dap1_sclk_pn3,
+ lcd_cs0_n_pn4, lcd_sdout_pn5, lcd_dc0_pn6, hdmi_int_pn7,
+ ulpi_data7_po0, ulpi_data0_po1, ulpi_data1_po2,
+ ulpi_data2_po3, ulpi_data3_po4, ulpi_data4_po5,
+ ulpi_data5_po6, ulpi_data6_po7, dap3_fs_pp0, dap3_din_pp1,
+ dap3_dout_pp2, dap3_sclk_pp3, dap4_fs_pp4, dap4_din_pp5,
+ dap4_dout_pp6, dap4_sclk_pp7, kb_col0_pq0, kb_col1_pq1,
+ kb_col2_pq2, kb_col3_pq3, kb_col4_pq4, kb_col5_pq5,
+ kb_col6_pq6, kb_col7_pq7, kb_row0_pr0, kb_row1_pr1,
+ kb_row2_pr2, kb_row3_pr3, kb_row4_pr4, kb_row5_pr5,
+ kb_row6_pr6, kb_row7_pr7, kb_row8_ps0, kb_row9_ps1,
+ kb_row10_ps2, kb_row11_ps3, kb_row12_ps4, kb_row13_ps5,
+ kb_row14_ps6, kb_row15_ps7, vi_pclk_pt0, vi_mclk_pt1,
+ vi_d10_pt2, vi_d11_pt3, vi_d0_pt4, gen2_i2c_scl_pt5,
+ gen2_i2c_sda_pt6, sdmmc4_cmd_pt7, pu0, pu1, pu2, pu3, pu4,
+ pu5, pu6, jtag_rtck_pu7, pv0, pv1, pv2, pv3, ddc_scl_pv4,
+ ddc_sda_pv5, crt_hsync_pv6, crt_vsync_pv7, lcd_cs1_n_pw0,
+ lcd_m1_pw1, spi2_cs1_n_pw2, spi2_cs2_n_pw3, clk1_out_pw4,
+ clk2_out_pw5, uart3_txd_pw6, uart3_rxd_pw7, spi2_mosi_px0,
+ spi2_miso_px1, spi2_sck_px2, spi2_cs0_n_px3, spi1_mosi_px4,
+ spi1_sck_px5, spi1_cs0_n_px6, spi1_miso_px7, ulpi_clk_py0,
+ ulpi_dir_py1, ulpi_nxt_py2, ulpi_stp_py3, sdmmc1_dat3_py4,
+ sdmmc1_dat2_py5, sdmmc1_dat1_py6, sdmmc1_dat0_py7,
+ sdmmc1_clk_pz0, sdmmc1_cmd_pz1, lcd_sdin_pz2, lcd_wr_n_pz3,
+ lcd_sck_pz4, sys_clk_req_pz5, pwr_i2c_scl_pz6,
+ pwr_i2c_sda_pz7, sdmmc4_dat0_paa0, sdmmc4_dat1_paa1,
+ sdmmc4_dat2_paa2, sdmmc4_dat3_paa3, sdmmc4_dat4_paa4,
+ sdmmc4_dat5_paa5, sdmmc4_dat6_paa6, sdmmc4_dat7_paa7, pbb0,
+ cam_i2c_scl_pbb1, cam_i2c_sda_pbb2, pbb3, pbb4, pbb5, pbb6,
+ pbb7, cam_mclk_pcc0, pcc1, pcc2, sdmmc4_rst_n_pcc3,
+ sdmmc4_clk_pcc4, clk2_req_pcc5, pex_l2_rst_n_pcc6,
+ pex_l2_clkreq_n_pcc7, pex_l0_prsnt_n_pdd0,
+ pex_l0_rst_n_pdd1, pex_l0_clkreq_n_pdd2, pex_wake_n_pdd3,
+ pex_l1_prsnt_n_pdd4, pex_l1_rst_n_pdd5,
+ pex_l1_clkreq_n_pdd6, pex_l2_prsnt_n_pdd7, clk3_out_pee0,
+ clk3_req_pee1, clk1_req_pee2, hdmi_cec_pee3, clk_32k_in,
+ core_pwr_req, cpu_pwr_req, owr, pwr_int_n,
+ # drive groups
+ drive_ao1, drive_ao2, drive_at1, drive_at2, drive_at3,
+ drive_at4, drive_at5, drive_cdev1, drive_cdev2, drive_cec,
+ drive_crt, drive_csus, drive_dap1, drive_dap2, drive_dap3,
+ drive_dap4, drive_dbg, drive_ddc, drive_dev3, drive_gma,
+ drive_gmb, drive_gmc, drive_gmd, drive_gme, drive_gmf,
+ drive_gmg, drive_gmh, drive_gpv, drive_lcd1, drive_lcd2,
+ drive_owr, drive_sdio1, drive_sdio2, drive_sdio3,
+ drive_spi, drive_uaa, drive_uab, drive_uart2, drive_uart3,
+ drive_uda, drive_vi1 ]
+
+ nvidia,function:
+ enum: [ blink, cec, clk_12m_out, clk_32k_in, core_pwr_req,
+ cpu_pwr_req, crt, dap, ddr, dev3, displaya, displayb, dtv,
+ extperiph1, extperiph2, extperiph3, gmi, gmi_alt, hda, hdcp,
+ hdmi, hsi, i2c1, i2c2, i2c3, i2c4, i2cpwr, i2s0, i2s1, i2s2,
+ i2s3, i2s4, invalid, kbc, mio, nand, nand_alt, owr, pcie,
+ pwm0, pwm1, pwm2, pwm3, pwr_int_n, rsvd1, rsvd2, rsvd3,
+ rsvd4, rtck, sata, sdmmc1, sdmmc2, sdmmc3, sdmmc4, spdif,
+ spi1, spi2, spi2_alt, spi3, spi4, spi5, spi6, sysclk, test,
+ trace, uarta, uartb, uartc, uartd, uarte, ulpi, vgp1, vgp2,
+ vgp3, vgp4, vgp5, vgp6, vi, vi_alt1, vi_alt2, vi_alt3 ]
+
+ nvidia,pull: true
+ nvidia,tristate: true
+ nvidia,schmitt: true
+ nvidia,pull-down-strength: true
+ nvidia,pull-up-strength: true
+ nvidia,high-speed-mode: true
+ nvidia,low-power-mode: true
+ nvidia,enable-input: true
+ nvidia,open-drain: true
+ nvidia,lock: true
+ nvidia,io-reset: true
+ nvidia,slew-rate-rising: true
+ nvidia,slew-rate-falling: true
+
+ required:
+ - nvidia,pins
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+examples:
+ - |
+ pinctrl@70000000 {
+ compatible = "nvidia,tegra30-pinmux";
+ reg = <0x70000868 0x0d0>, /* Pad control registers */
+ <0x70003000 0x3e0>; /* Mux registers */
+
+ pinmux {
+ sdmmc4_clk_pcc4 {
+ nvidia,pins = "sdmmc4_clk_pcc4",
+ "sdmmc4_rst_n_pcc3";
+ nvidia,function = "sdmmc4";
+ nvidia,pull = <0>;
+ nvidia,tristate = <0>;
+ };
+
+ sdmmc4_dat0_paa0 {
+ nvidia,pins = "sdmmc4_dat0_paa0",
+ "sdmmc4_dat1_paa1",
+ "sdmmc4_dat2_paa2",
+ "sdmmc4_dat3_paa3",
+ "sdmmc4_dat4_paa4",
+ "sdmmc4_dat5_paa5",
+ "sdmmc4_dat6_paa6",
+ "sdmmc4_dat7_paa7";
+ nvidia,function = "sdmmc4";
+ nvidia,pull = <2>;
+ nvidia,tristate = <0>;
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt
deleted file mode 100644
index 4023bad2fe39..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-sx150x.txt
+++ /dev/null
@@ -1,72 +0,0 @@
-SEMTECH SX150x GPIO expander bindings
-
-Please refer to pinctrl-bindings.txt, ../gpio/gpio.txt, and
-../interrupt-controller/interrupts.txt for generic information regarding
-pin controller, GPIO, and interrupt bindings.
-
-Required properties:
-- compatible: should be one of :
- "semtech,sx1501q",
- "semtech,sx1502q",
- "semtech,sx1503q",
- "semtech,sx1504q",
- "semtech,sx1505q",
- "semtech,sx1506q",
- "semtech,sx1507q",
- "semtech,sx1508q",
- "semtech,sx1509q".
-
-- reg: The I2C slave address for this device.
-
-- #gpio-cells: Should be 2. The first cell is the GPIO number and the
- second cell is used to specify optional parameters:
- bit 0: polarity (0: normal, 1: inverted)
-
-- gpio-controller: Marks the device as a GPIO controller.
-
-Optional properties :
-- interrupts: Interrupt specifier for the controllers interrupt.
-
-- interrupt-controller: Marks the device as a interrupt controller.
-
-- semtech,probe-reset: Will trigger a reset of the GPIO expander on probe,
- only for sx1507q, sx1508q and sx1509q
-
-The GPIO expander can optionally be used as an interrupt controller, in
-which case it uses the default two cell specifier.
-
-Required properties for pin configuration sub-nodes:
- - pins: List of pins to which the configuration applies.
-
-Optional properties for pin configuration sub-nodes:
-----------------------------------------------------
- - bias-disable: disable any pin bias, except the OSCIO pin
- - bias-pull-up: pull up the pin, except the OSCIO pin
- - bias-pull-down: pull down the pin, except the OSCIO pin
- - bias-pull-pin-default: use pin-default pull state, except the OSCIO pin
- - drive-push-pull: drive actively high and low
- - drive-open-drain: drive with open drain only for sx1507q, sx1508q and sx1509q and except the OSCIO pin
- - output-low: set the pin to output mode with low level
- - output-high: set the pin to output mode with high level
-
-Example:
-
- i2c0gpio-expander@20{
- #gpio-cells = <2>;
- #interrupt-cells = <2>;
- compatible = "semtech,sx1506q";
- reg = <0x20>;
- interrupt-parent = <&gpio_1>;
- interrupts = <16 0>;
-
- gpio-controller;
- interrupt-controller;
-
- pinctrl-names = "default";
- pinctrl-0 = <&gpio1_cfg_pins>;
-
- gpio1_cfg_pins: gpio1-cfg {
- pins = "gpio1";
- bias-pull-up;
- };
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,ipq6018-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,ipq6018-pinctrl.yaml
index 931e5c190ead..93f231c7a3b4 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,ipq6018-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,ipq6018-pinctrl.yaml
@@ -7,11 +7,10 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies, Inc. IPQ6018 TLMM block
maintainers:
- - Sricharan R <sricharan@codeaurora.org>
+ - Bjorn Andersson <andersson@kernel.org>
-description: |
- This binding describes the Top Level Mode Multiplexer block found in the
- IPQ6018 platform.
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm IPQ6018 SoC.
properties:
compatible:
@@ -20,36 +19,28 @@ properties:
reg:
maxItems: 1
- interrupts:
- description: Specifies the TLMM summary IRQ
- maxItems: 1
-
+ interrupts: true
interrupt-controller: true
-
- '#interrupt-cells':
- description:
- Specifies the PIN numbers and Flags, as defined in defined in
- include/dt-bindings/interrupt-controller/irq.h
- const: 2
-
+ "#interrupt-cells": true
gpio-controller: true
+ "#gpio-cells": true
+ gpio-ranges: true
- '#gpio-cells':
- description: Specifying the pin number and flags, as defined in
- include/dt-bindings/gpio/gpio.h
- const: 2
-
- gpio-ranges:
- maxItems: 1
-
-#PIN CONFIGURATION NODES
patternProperties:
- '-pinmux$':
- type: object
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-ipq6018-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-ipq6018-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-ipq6018-tlmm-state:
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
Client device subnodes use below standard properties.
- $ref: "/schemas/pinctrl/pincfg-node.yaml"
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
properties:
pins:
@@ -63,7 +54,7 @@ patternProperties:
sdc2_data, qdsd_cmd, qdsd_data0, qdsd_data1, qdsd_data2,
qdsd_data3 ]
minItems: 1
- maxItems: 4
+ maxItems: 16
function:
description:
@@ -72,12 +63,12 @@ patternProperties:
enum: [ adsp_ext, alsp_int, atest_bbrx0, atest_bbrx1, atest_char,
atest_char0, atest_char1, atest_char2, atest_char3, atest_combodac,
atest_gpsadc0, atest_gpsadc1, atest_tsens, atest_wlan0,
- atest_wlan1, backlight_en, bimc_dte0, bimc_dte1, blsp1_i2c,
- blsp2_i2c, blsp3_i2c, blsp4_i2c, blsp5_i2c, blsp6_i2c, blsp1_spi,
+ atest_wlan1, backlight_en, bimc_dte0, bimc_dte1, blsp0_i2c, blsp1_i2c,
+ blsp2_i2c, blsp3_i2c, blsp4_i2c, blsp5_i2c, blsp0_spi, blsp1_spi,
blsp1_spi_cs1, blsp1_spi_cs2, blsp1_spi_cs3, blsp2_spi,
blsp2_spi_cs1, blsp2_spi_cs2, blsp2_spi_cs3, blsp3_spi,
blsp3_spi_cs1, blsp3_spi_cs2, blsp3_spi_cs3, blsp4_spi, blsp5_spi,
- blsp6_spi, blsp1_uart, blsp2_uart, blsp1_uim, blsp2_uim, cam1_rst,
+ blsp0_uart, blsp1_uart, blsp2_uart, blsp1_uim, blsp2_uim, cam1_rst,
cam1_standby, cam_mclk0, cam_mclk1, cci_async, cci_i2c, cci_timer0,
cci_timer1, cci_timer2, cdc_pdm0, codec_mad, dbg_out, display_5v,
dmic0_clk, dmic0_data, dsi_rst, ebi0_wrcdc, euro_us, ext_lpass,
@@ -92,64 +83,48 @@ patternProperties:
qdss_ctitrig_in_b0, qdss_ctitrig_in_b1, qdss_ctitrig_out_a0,
qdss_ctitrig_out_a1, qdss_ctitrig_out_b0, qdss_ctitrig_out_b1,
qdss_traceclk_a, qdss_traceclk_b, qdss_tracectl_a, qdss_tracectl_b,
- qdss_tracedata_a, qdss_tracedata_b, reset_n, sd_card, sd_write,
- sec_mi2s, smb_int, ssbi_wtr0, ssbi_wtr1, uim1, uim2, uim3,
- uim_batt, wcss_bt, wcss_fm, wcss_wlan, webcam1_rst ]
-
- drive-strength:
- enum: [2, 4, 6, 8, 10, 12, 14, 16]
- default: 2
- description:
- Selects the drive strength for the specified pins, in mA.
+ qdss_tracedata_a, qdss_tracedata_b, qpic_pad, reset_n, sd_card,
+ sd_write, sec_mi2s, smb_int, ssbi_wtr0, ssbi_wtr1, uim1, uim2,
+ uim3, uim_batt, wcss_bt, wcss_fm, wcss_wlan, webcam1_rst ]
bias-pull-down: true
-
bias-pull-up: true
-
bias-disable: true
-
+ drive-strength: true
output-high: true
-
output-low: true
required:
- pins
- - function
additionalProperties: false
allOf:
- - $ref: "pinctrl.yaml#"
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
required:
- compatible
- reg
- - interrupts
- - interrupt-controller
- - '#interrupt-cells'
- - gpio-controller
- - '#gpio-cells'
- - gpio-ranges
additionalProperties: false
examples:
- |
- #include <dt-bindings/interrupt-controller/arm-gic.h>
- tlmm: pinctrl@1000000 {
- compatible = "qcom,ipq6018-pinctrl";
- reg = <0x01000000 0x300000>;
- interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-controller;
- #interrupt-cells = <2>;
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&tlmm 0 0 80>;
-
- serial3-pinmux {
- pins = "gpio44", "gpio45";
- function = "blsp2_uart";
- drive-strength = <8>;
- bias-pull-down;
- };
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ tlmm: pinctrl@1000000 {
+ compatible = "qcom,ipq6018-pinctrl";
+ reg = <0x01000000 0x300000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&tlmm 0 0 80>;
+
+ serial3-state {
+ pins = "gpio44", "gpio45";
+ function = "blsp2_uart";
+ drive-strength = <8>;
+ bias-pull-down;
};
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,ipq8074-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,ipq8074-pinctrl.txt
deleted file mode 100644
index 7b151894f5a0..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/qcom,ipq8074-pinctrl.txt
+++ /dev/null
@@ -1,181 +0,0 @@
-Qualcomm Technologies, Inc. IPQ8074 TLMM block
-
-This binding describes the Top Level Mode Multiplexer block found in the
-IPQ8074 platform.
-
-- compatible:
- Usage: required
- Value type: <string>
- Definition: must be "qcom,ipq8074-pinctrl"
-
-- reg:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: the base address and size of the TLMM register space.
-
-- interrupts:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: should specify the TLMM summary IRQ.
-
-- interrupt-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as an interrupt controller
-
-- #interrupt-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/interrupt-controller/irq.h>
-
-- gpio-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as a gpio controller
-
-- #gpio-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/gpio/gpio.h>
-
-- gpio-ranges:
- Usage: required
- Definition: see ../gpio/gpio.txt
-
-- gpio-reserved-ranges:
- Usage: optional
- Definition: see ../gpio/gpio.txt
-
-Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
-a general description of GPIO and interrupt bindings.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-The pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, drive strength, etc.
-
-
-PIN CONFIGURATION NODES:
-
-The name of each subnode is not important; all subnodes should be enumerated
-and processed purely based on their content.
-
-Each subnode only affects those parameters that are explicitly listed. In
-other words, a subnode that lists a mux function but no pin configuration
-parameters implies no information about any pin configuration parameters.
-Similarly, a pin subnode that describes a pullup parameter implies no
-information about e.g. the mux function.
-
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pin configuration subnode:
-
-- pins:
- Usage: required
- Value type: <string-array>
- Definition: List of gpio pins affected by the properties specified in
- this subnode. Valid pins are:
- gpio0-gpio69
-
-- function:
- Usage: required
- Value type: <string>
- Definition: Specify the alternative function to be configured for the
- specified pins. Functions are only valid for gpio pins.
- Valid values are:
- atest_char, atest_char0, atest_char1, atest_char2,
- atest_char3, audio_rxbclk, audio_rxd, audio_rxfsync,
- audio_rxmclk, audio_txbclk, audio_txd, audio_txfsync,
- audio_txmclk, blsp0_i2c, blsp0_spi, blsp0_uart, blsp1_i2c,
- blsp1_spi, blsp1_uart, blsp2_i2c, blsp2_spi, blsp2_uart,
- blsp3_i2c, blsp3_spi, blsp3_spi0, blsp3_spi1, blsp3_spi2,
- blsp3_spi3, blsp3_uart, blsp4_i2c0, blsp4_i2c1, blsp4_spi0,
- blsp4_spi1, blsp4_uart0, blsp4_uart1, blsp5_i2c, blsp5_spi,
- blsp5_uart, burn0, burn1, cri_trng, cri_trng0, cri_trng1,
- cxc0, cxc1, dbg_out, gcc_plltest, gcc_tlmm, gpio, ldo_en,
- ldo_update, led0, led1, led2, mac0_sa0, mac0_sa1, mac1_sa0,
- mac1_sa1, mac1_sa2, mac1_sa3, mac2_sa0, mac2_sa1, mdc,
- mdio, pcie0_clk, pcie0_rst, pcie0_wake, pcie1_clk,
- pcie1_rst, pcie1_wake, pcm_drx, pcm_dtx, pcm_fsync,
- pcm_pclk, pcm_zsi0, pcm_zsi1, prng_rosc, pta1_0, pta1_1,
- pta1_2, pta2_0, pta2_1, pta2_2, pwm0, pwm1, pwm2, pwm3,
- qdss_cti_trig_in_a0, qdss_cti_trig_in_a1,
- qdss_cti_trig_in_b0, qdss_cti_trig_in_b1,
- qdss_cti_trig_out_a0, qdss_cti_trig_out_a1,
- qdss_cti_trig_out_b0, qdss_cti_trig_out_b1,
- qdss_traceclk_a, qdss_traceclk_b, qdss_tracectl_a,
- qdss_tracectl_b, qdss_tracedata_a, qdss_tracedata_b,
- qpic, rx0, rx1, rx2, sd_card, sd_write, tsens_max, wci2a,
- wci2b, wci2c, wci2d
-
-- bias-disable:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as no pull.
-
-- bias-pull-down:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull down.
-
-- bias-pull-up:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull up.
-
-- output-high:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- high.
-
-- output-low:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- low.
-
-- drive-strength:
- Usage: optional
- Value type: <u32>
- Definition: Selects the drive strength for the specified pins, in mA.
- Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
-
-Example:
-
- tlmm: pinctrl@1000000 {
- compatible = "qcom,ipq8074-pinctrl";
- reg = <0x1000000 0x300000>;
- interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&tlmm 0 0 70>;
- interrupt-controller;
- #interrupt-cells = <2>;
-
- uart2: uart2-default {
- mux {
- pins = "gpio23", "gpio24";
- function = "blsp4_uart1";
- };
-
- rx {
- pins = "gpio23";
- drive-strength = <4>;
- bias-disable;
- };
-
- tx {
- pins = "gpio24";
- drive-strength = <2>;
- bias-pull-up;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,ipq8074-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,ipq8074-pinctrl.yaml
new file mode 100644
index 000000000000..5687acaf19bf
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,ipq8074-pinctrl.yaml
@@ -0,0 +1,135 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,ipq8074-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm IPQ8074 TLMM pin controller
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm IPQ8074 SoC.
+
+properties:
+ compatible:
+ const: qcom,ipq8074-pinctrl
+
+ reg:
+ maxItems: 1
+
+ interrupts: true
+ interrupt-controller: true
+ "#interrupt-cells": true
+ gpio-controller: true
+ "#gpio-cells": true
+ gpio-ranges: true
+ wakeup-parent: true
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 35
+
+ gpio-line-names:
+ maxItems: 70
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-ipq8074-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-ipq8074-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-ipq8074-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ pattern: "^gpio([0-9]|[1-6][0-9]|70)$"
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ gpio, atest_char, atest_char0, atest_char1, atest_char2,
+ atest_char3, audio_rxbclk, audio_rxd, audio_rxfsync,
+ audio_rxmclk, audio_txbclk, audio_txd, audio_txfsync,
+ audio_txmclk, blsp0_i2c, blsp0_spi, blsp0_uart, blsp1_i2c,
+ blsp1_spi, blsp1_uart, blsp2_i2c, blsp2_spi, blsp2_uart,
+ blsp3_i2c, blsp3_spi, blsp3_spi0, blsp3_spi1, blsp3_spi2,
+ blsp3_spi3, blsp3_uart, blsp4_i2c0, blsp4_i2c1, blsp4_spi0,
+ blsp4_spi1, blsp4_uart0, blsp4_uart1, blsp5_i2c, blsp5_spi,
+ blsp5_uart, burn0, burn1, cri_trng, cri_trng0, cri_trng1, cxc0,
+ cxc1, dbg_out, gcc_plltest, gcc_tlmm, ldo_en, ldo_update, led0,
+ led1, led2, mac0_sa0, mac0_sa1, mac1_sa0, mac1_sa1, mac1_sa2,
+ mac1_sa3, mac2_sa0, mac2_sa1, mdc, mdio, pcie0_clk, pcie0_rst,
+ pcie0_wake, pcie1_clk, pcie1_rst, pcie1_wake, pcm_drx, pcm_dtx,
+ pcm_fsync, pcm_pclk, pcm_zsi0, pcm_zsi1, prng_rosc, pta1_0,
+ pta1_1, pta1_2, pta2_0, pta2_1, pta2_2, pwm0, pwm1, pwm2, pwm3,
+ qdss_cti_trig_in_a0, qdss_cti_trig_in_a1, qdss_cti_trig_in_b0,
+ qdss_cti_trig_in_b1, qdss_cti_trig_out_a0,
+ qdss_cti_trig_out_a1, qdss_cti_trig_out_b0,
+ qdss_cti_trig_out_b1, qdss_traceclk_a, qdss_traceclk_b,
+ qdss_tracectl_a, qdss_tracectl_b, qdss_tracedata_a,
+ qdss_tracedata_b, qpic, rx0, rx1, rx2, sd_card, sd_write,
+ tsens_max, wci2a, wci2b, wci2c, wci2d ]
+
+ bias-pull-down: true
+ bias-pull-up: true
+ bias-disable: true
+ drive-strength: true
+ input-enable: true
+ output-high: true
+ output-low: true
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ tlmm: pinctrl@1000000 {
+ compatible = "qcom,ipq8074-pinctrl";
+ reg = <0x01000000 0x300000>;
+ gpio-controller;
+ #gpio-cells = <0x2>;
+ gpio-ranges = <&tlmm 0 0 70>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <0x2>;
+
+ serial4-state {
+ pins = "gpio23", "gpio24";
+ function = "blsp4_uart1";
+ drive-strength = <8>;
+ bias-disable;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-tlmm.yaml
index f7bd4be1739e..a0a12171b6d0 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,mdm9607-tlmm.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/pinctrl/qcom,mdm9607-pinctrl.yaml#
+$id: http://devicetree.org/schemas/pinctrl/qcom,mdm9607-tlmm.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies, Inc. MDM9607 TLMM block
@@ -9,12 +9,10 @@ title: Qualcomm Technologies, Inc. MDM9607 TLMM block
maintainers:
- Konrad Dybcio <konrad.dybcio@somainline.org>
-description: |
- This binding describes the Top Level Mode Multiplexer block found in the
- MDM9607 platform.
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm MDM9607 SoC.
allOf:
- - $ref: "pinctrl.yaml#"
- $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
properties:
@@ -26,10 +24,10 @@ properties:
interrupts: true
interrupt-controller: true
- '#interrupt-cells': true
+ "#interrupt-cells": true
gpio-controller: true
gpio-reserved-ranges: true
- '#gpio-cells': true
+ "#gpio-cells": true
gpio-ranges: true
wakeup-parent: true
@@ -40,20 +38,20 @@ required:
additionalProperties: false
patternProperties:
- '-state$':
+ "-state$":
oneOf:
- $ref: "#/$defs/qcom-mdm9607-tlmm-state"
- patternProperties:
".*":
$ref: "#/$defs/qcom-mdm9607-tlmm-state"
-'$defs':
+$defs:
qcom-mdm9607-tlmm-state:
type: object
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
Client device subnodes use below standard properties.
- $ref: "qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state"
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
properties:
pins:
@@ -115,20 +113,19 @@ patternProperties:
required:
- pins
- - function
additionalProperties: false
examples:
- |
- #include <dt-bindings/interrupt-controller/arm-gic.h>
- tlmm: pinctrl@1000000 {
- compatible = "qcom,mdm9607-tlmm";
- reg = <0x01000000 0x300000>;
- interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- gpio-ranges = <&msmgpio 0 0 80>;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ tlmm: pinctrl@1000000 {
+ compatible = "qcom,mdm9607-tlmm";
+ reg = <0x01000000 0x300000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ gpio-ranges = <&msmgpio 0 0 80>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,mdm9615-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,mdm9615-pinctrl.txt
deleted file mode 100644
index d46973968873..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/qcom,mdm9615-pinctrl.txt
+++ /dev/null
@@ -1,161 +0,0 @@
-Qualcomm MDM9615 TLMM block
-
-This binding describes the Top Level Mode Multiplexer block found in the
-MDM9615 platform.
-
-- compatible:
- Usage: required
- Value type: <string>
- Definition: must be "qcom,mdm9615-pinctrl"
-
-- reg:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: the base address and size of the TLMM register space.
-
-- interrupts:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: should specify the TLMM summary IRQ.
-
-- interrupt-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as an interrupt controller
-
-- #interrupt-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/interrupt-controller/irq.h>
-
-- gpio-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as a gpio controller
-
-- #gpio-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/gpio/gpio.h>
-
-- gpio-ranges:
- Usage: required
- Definition: see ../gpio/gpio.txt
-
-- gpio-reserved-ranges:
- Usage: optional
- Definition: see ../gpio/gpio.txt
-
-Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
-a general description of GPIO and interrupt bindings.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-The pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, drive strength, etc.
-
-
-PIN CONFIGURATION NODES:
-
-The name of each subnode is not important; all subnodes should be enumerated
-and processed purely based on their content.
-
-Each subnode only affects those parameters that are explicitly listed. In
-other words, a subnode that lists a mux function but no pin configuration
-parameters implies no information about any pin configuration parameters.
-Similarly, a pin subnode that describes a pullup parameter implies no
-information about e.g. the mux function.
-
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pin configuration subnode:
-
-- pins:
- Usage: required
- Value type: <string-array>
- Definition: List of gpio pins affected by the properties specified in
- this subnode. Valid pins are:
- gpio0-gpio87
-
-- function:
- Usage: required
- Value type: <string>
- Definition: Specify the alternative function to be configured for the
- specified pins.
- Valid values are:
- gpio, gsbi2_i2c, gsbi3, gsbi4, gsbi5_i2c, gsbi5_uart,
- sdc2, ebi2_lcdc, ps_hold, prim_audio, sec_audio,
- cdc_mclk
-
-- bias-disable:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as no pull.
-
-- bias-pull-down:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull down.
-
-- bias-pull-up:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull up.
-
-- output-high:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- high.
-
-- output-low:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- low.
-
-- drive-strength:
- Usage: optional
- Value type: <u32>
- Definition: Selects the drive strength for the specified pins, in mA.
- Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
-
-Example:
-
- msmgpio: pinctrl@800000 {
- compatible = "qcom,mdm9615-pinctrl";
- reg = <0x800000 0x4000>;
-
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&msmgpio 0 0 88>;
- interrupt-controller;
- #interrupt-cells = <2>;
- interrupts = <0 16 0x4>;
-
- gsbi8_uart: gsbi8-uart {
- mux {
- pins = "gpio34", "gpio35";
- function = "gsbi8";
- };
-
- tx {
- pins = "gpio34";
- drive-strength = <4>;
- bias-disable;
- };
-
- rx {
- pins = "gpio35";
- drive-strength = <2>;
- bias-pull-up;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,mdm9615-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,mdm9615-pinctrl.yaml
new file mode 100644
index 000000000000..a4f6e4c588f4
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,mdm9615-pinctrl.yaml
@@ -0,0 +1,119 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,mdm9615-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies, Inc. MDM9615 TLMM block
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+
+description: Top Level Mode Multiplexer pin controller in Qualcomm MDM9615 SoC.
+
+$ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+properties:
+ compatible:
+ const: qcom,mdm9615-pinctrl
+
+ reg:
+ maxItems: 1
+
+ interrupts: true
+ interrupt-controller: true
+ '#interrupt-cells': true
+ gpio-controller: true
+ '#gpio-cells': true
+ gpio-ranges: true
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-mdm9615-pinctrl-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-mdm9615-pinctrl-state"
+ additionalProperties: false
+
+$defs:
+ qcom-mdm9615-pinctrl-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ pattern: "^gpio([0-9]|[1-7][0-9]|8[0-7])$"
+ minItems: 1
+ maxItems: 16
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ gpio, gsbi2_i2c, gsbi3, gsbi4, gsbi5_i2c, gsbi5_uart,
+ sdc2, ebi2_lcdc, ps_hold, prim_audio, sec_audio, cdc_mclk, ]
+
+ bias-disable: true
+ bias-pull-down: true
+ bias-pull-up: true
+ drive-strength: true
+ output-high: true
+ output-low: true
+ input-enable: true
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ tlmm: pinctrl@1000000 {
+ compatible = "qcom,mdm9615-pinctrl";
+ reg = <0x01000000 0x300000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ gpio-ranges = <&msmgpio 0 0 88>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ gsbi3-state {
+ pins = "gpio8", "gpio9", "gpio10", "gpio11";
+ function = "gsbi3";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ gsbi5-i2c-state {
+ sda-pins {
+ pins = "gpio16";
+ function = "gsbi5_i2c";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ scl-pins {
+ pins = "gpio17";
+ function = "gsbi5_i2c";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8226-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,msm8226-pinctrl.yaml
index ab4a2b4cfda2..3b79f5be860b 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,msm8226-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8226-pinctrl.yaml
@@ -9,9 +9,8 @@ title: Qualcomm Technologies, Inc. MSM8226 TLMM block
maintainers:
- Bjorn Andersson <bjorn.andersson@linaro.org>
-description: |
- This binding describes the Top Level Mode Multiplexer block found in the
- MSM8226 platform.
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm MSM8226 SoC.
properties:
compatible:
@@ -21,38 +20,32 @@ properties:
description: Specifies the base address and size of the TLMM register space
maxItems: 1
- interrupts:
- description: Specifies the TLMM summary IRQ
- maxItems: 1
-
+ interrupts: true
interrupt-controller: true
-
- '#interrupt-cells':
- description: Specifies the PIN numbers and Flags, as defined in
- include/dt-bindings/interrupt-controller/irq.h
- const: 2
-
+ "#interrupt-cells": true
gpio-controller: true
-
- '#gpio-cells':
- description: Specifying the pin number and flags, as defined in
- include/dt-bindings/gpio/gpio.h
- const: 2
-
- gpio-ranges:
- maxItems: 1
+ "#gpio-cells": true
+ gpio-ranges: true
gpio-reserved-ranges:
maxItems: 1
-#PIN CONFIGURATION NODES
patternProperties:
- '-pins$':
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-msm8226-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-msm8226-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-msm8226-tlmm-state:
type: object
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
Client device subnodes use below standard properties.
- $ref: "/schemas/pinctrl/pincfg-node.yaml"
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
properties:
pins:
@@ -71,65 +64,51 @@ patternProperties:
Specify the alternative function to be configured for the specified
pins. Functions are only valid for gpio pins.
enum: [ gpio, cci_i2c0, blsp_uim1, blsp_uim2, blsp_uim3, blsp_uim5,
- blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c5, blsp_spi1,
+ blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c4, blsp_i2c5, blsp_spi1,
blsp_spi2, blsp_spi3, blsp_spi5, blsp_uart1, blsp_uart2,
- blsp_uart3, blsp_uart5, cam_mclk0, cam_mclk1, wlan ]
-
- drive-strength:
- enum: [2, 4, 6, 8, 10, 12, 14, 16]
- default: 2
- description:
- Selects the drive strength for the specified pins, in mA.
+ blsp_uart3, blsp_uart4, blsp_uart5, cam_mclk0, cam_mclk1, sdc3,
+ wlan ]
bias-pull-down: true
-
bias-pull-up: true
-
bias-disable: true
-
+ drive-strength: true
+ input-enable: true
output-high: true
-
output-low: true
required:
- pins
- - function
additionalProperties: false
allOf:
- - $ref: "pinctrl.yaml#"
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
required:
- compatible
- reg
- - interrupts
- - interrupt-controller
- - '#interrupt-cells'
- - gpio-controller
- - '#gpio-cells'
- - gpio-ranges
additionalProperties: false
examples:
- |
- #include <dt-bindings/interrupt-controller/arm-gic.h>
- msmgpio: pinctrl@fd510000 {
- compatible = "qcom,msm8226-pinctrl";
- reg = <0xfd510000 0x4000>;
-
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&msmgpio 0 0 117>;
- interrupt-controller;
- #interrupt-cells = <2>;
- interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
-
- serial-pins {
- pins = "gpio8", "gpio9";
- function = "blsp_uart3";
- drive-strength = <8>;
- bias-disable;
- };
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ msmgpio: pinctrl@fd510000 {
+ compatible = "qcom,msm8226-pinctrl";
+ reg = <0xfd510000 0x4000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&msmgpio 0 0 117>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+
+ serial-state {
+ pins = "gpio8", "gpio9";
+ function = "blsp_uart3";
+ drive-strength = <8>;
+ bias-disable;
};
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8660-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8660-pinctrl.txt
deleted file mode 100644
index f095209848c8..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/qcom,msm8660-pinctrl.txt
+++ /dev/null
@@ -1,96 +0,0 @@
-Qualcomm MSM8660 TLMM block
-
-Required properties:
-- compatible: "qcom,msm8660-pinctrl"
-- reg: Should be the base address and length of the TLMM block.
-- interrupts: Should be the parent IRQ of the TLMM block.
-- interrupt-controller: Marks the device node as an interrupt controller.
-- #interrupt-cells: Should be two.
-- gpio-controller: Marks the device node as a GPIO controller.
-- #gpio-cells : Should be two.
- The first cell is the gpio pin number and the
- second cell is used for optional parameters.
-- gpio-ranges: see ../gpio/gpio.txt
-
-Optional properties:
-
-- gpio-reserved-ranges: see ../gpio/gpio.txt
-
-Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
-a general description of GPIO and interrupt bindings.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-Qualcomm's pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, drive strength, etc.
-
-The name of each subnode is not important; all subnodes should be enumerated
-and processed purely based on their content.
-
-Each subnode only affects those parameters that are explicitly listed. In
-other words, a subnode that lists a mux function but no pin configuration
-parameters implies no information about any pin configuration parameters.
-Similarly, a pin subnode that describes a pullup parameter implies no
-information about e.g. the mux function.
-
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pin configuration subnode:
-
- pins, function, bias-disable, bias-pull-down, bias-pull-up, drive-strength,
- output-low, output-high.
-
-Non-empty subnodes must specify the 'pins' property.
-
-Valid values for pins are:
- gpio0-gpio172, sdc3_clk, sdc3_cmd, sdc3_data sdc4_clk, sdc4_cmd, sdc4_data
-
-Valid values for function are:
- gpio, cam_mclk, dsub, ext_gps, gp_clk_0a, gp_clk_0b, gp_clk_1a, gp_clk_1b,
- gp_clk_2a, gp_clk_2b, gp_mn, gsbi1, gsbi1_spi_cs1_n, gsbi1_spi_cs2a_n,
- gsbi1_spi_cs2b_n, gsbi1_spi_cs3_n, gsbi2, gsbi2_spi_cs1_n, gsbi2_spi_cs2_n,
- gsbi2_spi_cs3_n, gsbi3, gsbi3_spi_cs1_n, gsbi3_spi_cs2_n, gsbi3_spi_cs3_n,
- gsbi4, gsbi5, gsbi6, gsbi7, gsbi8, gsbi9, gsbi10, gsbi11, gsbi12, hdmi, i2s,
- lcdc, mdp_vsync, mi2s, pcm, ps_hold, sdc1, sdc2, sdc5, tsif1, tsif2, usb_fs1,
- usb_fs1_oe_n, usb_fs2, usb_fs2_oe_n, vfe, vsens_alarm, ebi2, ebi2cs
-
-Example:
-
- msmgpio: pinctrl@800000 {
- compatible = "qcom,msm8660-pinctrl";
- reg = <0x800000 0x4000>;
-
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&msmgpio 0 0 173>;
- interrupt-controller;
- #interrupt-cells = <2>;
- interrupts = <0 16 0x4>;
-
- pinctrl-names = "default";
- pinctrl-0 = <&gsbi12_uart>;
-
- gsbi12_uart: gsbi12-uart {
- mux {
- pins = "gpio117", "gpio118";
- function = "gsbi12";
- };
-
- tx {
- pins = "gpio118";
- drive-strength = <8>;
- bias-disable;
- };
-
- rx {
- pins = "gpio117";
- drive-strength = <2>;
- bias-pull-up;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8660-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,msm8660-pinctrl.yaml
new file mode 100644
index 000000000000..ad0cad4694c0
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8660-pinctrl.yaml
@@ -0,0 +1,125 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,msm8660-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm MSM8660 TLMM pin controller
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm MSM8660 SoC.
+
+properties:
+ compatible:
+ const: qcom,msm8660-pinctrl
+
+ reg:
+ maxItems: 1
+
+ interrupts: true
+ interrupt-controller: true
+ "#interrupt-cells": true
+ gpio-controller: true
+ "#gpio-cells": true
+ gpio-ranges: true
+ wakeup-parent: true
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 86
+
+ gpio-line-names:
+ maxItems: 173
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-msm8660-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-msm8660-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-msm8660-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ oneOf:
+ - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-6][0-9]|17[0-2])$"
+ - enum: [ sdc3_clk, sdc3_cmd, sdc3_data, sdc4_clk, sdc4_cmd, sdc4_data ]
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ gpio, cam_mclk, dsub, ext_gps, gp_clk_0a, gp_clk_0b, gp_clk_1a,
+ gp_clk_1b, gp_clk_2a, gp_clk_2b, gp_mn, gsbi1, gsbi1_spi_cs1_n,
+ gsbi1_spi_cs2a_n, gsbi1_spi_cs2b_n, gsbi1_spi_cs3_n, gsbi2,
+ gsbi2_spi_cs1_n, gsbi2_spi_cs2_n, gsbi2_spi_cs3_n, gsbi3,
+ gsbi3_spi_cs1_n, gsbi3_spi_cs2_n, gsbi3_spi_cs3_n, gsbi4,
+ gsbi5, gsbi6, gsbi7, gsbi8, gsbi9, gsbi10, gsbi11, gsbi12,
+ hdmi, i2s, lcdc, mdp_vsync, mi2s, pcm, ps_hold, sdc1, sdc2,
+ sdc5, tsif1, tsif2, usb_fs1, usb_fs1_oe_n, usb_fs2,
+ usb_fs2_oe_n, vfe, vsens_alarm, ebi2, ebi2cs ]
+
+
+ bias-pull-down: true
+ bias-pull-up: true
+ bias-disable: true
+ drive-strength: true
+ input-enable: true
+ output-high: true
+ output-low: true
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ tlmm: pinctrl@800000 {
+ compatible = "qcom,msm8660-pinctrl";
+ reg = <0x800000 0x4000>;
+
+ gpio-controller;
+ gpio-ranges = <&tlmm 0 0 173>;
+ #gpio-cells = <2>;
+ interrupts = <0 16 0x4>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ gsbi3-i2c-state {
+ pins = "gpio43", "gpio44";
+ function = "gsbi3";
+ drive-strength = <8>;
+ bias-disable;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8909-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,msm8909-tlmm.yaml
index e03530091478..cc6d0c9c5100 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,msm8909-tlmm.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8909-tlmm.yaml
@@ -10,8 +10,7 @@ maintainers:
- Stephan Gerhold <stephan@gerhold.net>
description: |
- This binding describes the Top Level Mode Multiplexer (TLMM) block found
- in the MSM8909 platform.
+ Top Level Mode Multiplexer pin controller in Qualcomm MSM8909 SoC.
allOf:
- $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
@@ -25,10 +24,10 @@ properties:
interrupts: true
interrupt-controller: true
- '#interrupt-cells': true
+ "#interrupt-cells": true
gpio-controller: true
gpio-reserved-ranges: true
- '#gpio-cells': true
+ "#gpio-cells": true
gpio-ranges: true
wakeup-parent: true
@@ -39,12 +38,13 @@ required:
additionalProperties: false
patternProperties:
- '-state$':
+ "-state$":
oneOf:
- $ref: "#/$defs/qcom-msm8909-tlmm-state"
- patternProperties:
- ".*":
+ "-pins$":
$ref: "#/$defs/qcom-msm8909-tlmm-state"
+ additionalProperties: false
$defs:
qcom-msm8909-tlmm-state:
@@ -52,7 +52,7 @@ $defs:
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
Client device subnodes use below standard properties.
- $ref: "qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state"
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
properties:
pins:
@@ -112,41 +112,40 @@ $defs:
required:
- pins
- - function
additionalProperties: false
examples:
- |
- #include <dt-bindings/interrupt-controller/arm-gic.h>
-
- pinctrl@1000000 {
- compatible = "qcom,msm8909-tlmm";
- reg = <0x1000000 0x300000>;
- interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&tlmm 0 0 117>;
- interrupt-controller;
- #interrupt-cells = <2>;
-
- gpio-wo-subnode-state {
- pins = "gpio1";
- function = "gpio";
- };
-
- uart-w-subnodes-state {
- rx {
- pins = "gpio4";
- function = "blsp_uart1";
- bias-pull-up;
- };
-
- tx {
- pins = "gpio5";
- function = "blsp_uart1";
- bias-disable;
- };
- };
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ pinctrl@1000000 {
+ compatible = "qcom,msm8909-tlmm";
+ reg = <0x1000000 0x300000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&tlmm 0 0 117>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ gpio-wo-subnode-state {
+ pins = "gpio1";
+ function = "gpio";
};
+
+ uart-w-subnodes-state {
+ rx-pins {
+ pins = "gpio4";
+ function = "blsp_uart1";
+ bias-pull-up;
+ };
+
+ tx-pins {
+ pins = "gpio5";
+ function = "blsp_uart1";
+ bias-disable;
+ };
+ };
+ };
...
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8916-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8916-pinctrl.txt
deleted file mode 100644
index 3354a63296d9..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/qcom,msm8916-pinctrl.txt
+++ /dev/null
@@ -1,195 +0,0 @@
-Qualcomm MSM8916 TLMM block
-
-This binding describes the Top Level Mode Multiplexer block found in the
-MSM8916 platform.
-
-- compatible:
- Usage: required
- Value type: <string>
- Definition: must be "qcom,msm8916-pinctrl"
-
-- reg:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: the base address and size of the TLMM register space.
-
-- interrupts:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: should specify the TLMM summary IRQ.
-
-- interrupt-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as an interrupt controller
-
-- #interrupt-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/interrupt-controller/irq.h>
-
-- gpio-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as a gpio controller
-
-- #gpio-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/gpio/gpio.h>
-
-- gpio-ranges:
- Usage: required
- Definition: see ../gpio/gpio.txt
-
-- gpio-reserved-ranges:
- Usage: optional
- Definition: see ../gpio/gpio.txt
-
-Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
-a general description of GPIO and interrupt bindings.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-The pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, drive strength, etc.
-
-
-PIN CONFIGURATION NODES:
-
-The name of each subnode is not important; all subnodes should be enumerated
-and processed purely based on their content.
-
-Each subnode only affects those parameters that are explicitly listed. In
-other words, a subnode that lists a mux function but no pin configuration
-parameters implies no information about any pin configuration parameters.
-Similarly, a pin subnode that describes a pullup parameter implies no
-information about e.g. the mux function.
-
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pin configuration subnode:
-
-- pins:
- Usage: required
- Value type: <string-array>
- Definition: List of gpio pins affected by the properties specified in
- this subnode. Valid pins are:
- gpio0-gpio121,
- sdc1_clk,
- sdc1_cmd,
- sdc1_data
- sdc2_clk,
- sdc2_cmd,
- sdc2_data,
- qdsd_cmd,
- qdsd_data0,
- qdsd_data1,
- qdsd_data2,
- qdsd_data3
-
-- function:
- Usage: required
- Value type: <string>
- Definition: Specify the alternative function to be configured for the
- specified pins. Functions are only valid for gpio pins.
- Valid values are:
- adsp_ext, alsp_int, atest_bbrx0, atest_bbrx1, atest_char, atest_char0,
- atest_char1, atest_char2, atest_char3, atest_combodac, atest_gpsadc0,
- atest_gpsadc1, atest_tsens, atest_wlan0, atest_wlan1, backlight_en,
- bimc_dte0,bimc_dte1, blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c4,
- blsp_i2c5, blsp_i2c6, blsp_spi1, blsp_spi1_cs1, blsp_spi1_cs2,
- blsp_spi1_cs3, blsp_spi2, blsp_spi2_cs1, blsp_spi2_cs2, blsp_spi2_cs3,
- blsp_spi3, blsp_spi3_cs1, blsp_spi3_cs2, blsp_spi3_cs3, blsp_spi4,
- blsp_spi5, blsp_spi6, blsp_uart1, blsp_uart2, blsp_uim1, blsp_uim2,
- cam1_rst, cam1_standby, cam_mclk0, cam_mclk1, cci_async, cci_i2c,
- cci_timer0, cci_timer1, cci_timer2, cdc_pdm0, codec_mad, dbg_out,
- display_5v, dmic0_clk, dmic0_data, dsi_rst, ebi0_wrcdc, euro_us,
- ext_lpass, flash_strobe, gcc_gp1_clk_a, gcc_gp1_clk_b, gcc_gp2_clk_a,
- gcc_gp2_clk_b, gcc_gp3_clk_a, gcc_gp3_clk_b, gpio, gsm0_tx0, gsm0_tx1,
- gsm1_tx0, gsm1_tx1, gyro_accl, kpsns0, kpsns1, kpsns2, ldo_en,
- ldo_update, mag_int, mdp_vsync, modem_tsync, m_voc, nav_pps, nav_tsync,
- pa_indicator, pbs0, pbs1, pbs2, pri_mi2s, pri_mi2s_ws, prng_rosc,
- pwr_crypto_enabled_a, pwr_crypto_enabled_b, pwr_modem_enabled_a,
- pwr_modem_enabled_b, pwr_nav_enabled_a, pwr_nav_enabled_b,
- qdss_ctitrig_in_a0, qdss_ctitrig_in_a1, qdss_ctitrig_in_b0,
- qdss_ctitrig_in_b1, qdss_ctitrig_out_a0, qdss_ctitrig_out_a1,
- qdss_ctitrig_out_b0, qdss_ctitrig_out_b1, qdss_traceclk_a,
- qdss_traceclk_b, qdss_tracectl_a, qdss_tracectl_b, qdss_tracedata_a,
- qdss_tracedata_b, reset_n, sd_card, sd_write, sec_mi2s, smb_int,
- ssbi_wtr0, ssbi_wtr1, uim1, uim2, uim3, uim_batt, wcss_bt, wcss_fm,
- wcss_wlan, webcam1_rst
-
-- bias-disable:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as no pull.
-
-- bias-pull-down:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull down.
-
-- bias-pull-up:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull up.
-
-- output-high:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- high.
- Not valid for sdc pins.
-
-- output-low:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- low.
- Not valid for sdc pins.
-
-- drive-strength:
- Usage: optional
- Value type: <u32>
- Definition: Selects the drive strength for the specified pins, in mA.
- Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
-
-Example:
-
- tlmm: pinctrl@1000000 {
- compatible = "qcom,msm8916-pinctrl";
- reg = <0x1000000 0x300000>;
- interrupts = <0 208 0>;
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&tlmm 0 0 122>;
- interrupt-controller;
- #interrupt-cells = <2>;
-
- uart2: uart2-default {
- mux {
- pins = "gpio4", "gpio5";
- function = "blsp_uart2";
- };
-
- tx {
- pins = "gpio4";
- drive-strength = <4>;
- bias-disable;
- };
-
- rx {
- pins = "gpio5";
- drive-strength = <2>;
- bias-pull-up;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8916-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,msm8916-pinctrl.yaml
new file mode 100644
index 000000000000..5495f58905af
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8916-pinctrl.yaml
@@ -0,0 +1,166 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,msm8916-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm MSM8916 TLMM pin controller
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm MSM8916 SoC.
+
+properties:
+ compatible:
+ const: qcom,msm8916-pinctrl
+
+ reg:
+ maxItems: 1
+
+ interrupts: true
+ interrupt-controller: true
+ "#interrupt-cells": true
+ gpio-controller: true
+ "#gpio-cells": true
+ gpio-ranges: true
+ wakeup-parent: true
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 61
+
+ gpio-line-names:
+ maxItems: 122
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-msm8916-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-msm8916-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-msm8916-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ oneOf:
+ - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-1][0-9]|12[01])$"
+ - enum: [ qdsd_clk, qdsd_cmd, qdsd_data0, qdsd_data1, qdsd_data2,
+ qdsd_data3, sdc1_clk, sdc1_cmd, sdc1_data, sdc2_clk,
+ sdc2_cmd, sdc2_data ]
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ gpio, adsp_ext, alsp_int, atest_bbrx0, atest_bbrx1, atest_char,
+ atest_char0, atest_char1, atest_char2, atest_char3,
+ atest_combodac, atest_gpsadc0, atest_gpsadc1, atest_tsens,
+ atest_wlan0, atest_wlan1, backlight_en, bimc_dte0, bimc_dte1,
+ blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c4, blsp_i2c5,
+ blsp_i2c6, blsp_spi1, blsp_spi1_cs1, blsp_spi1_cs2,
+ blsp_spi1_cs3, blsp_spi2, blsp_spi2_cs1, blsp_spi2_cs2,
+ blsp_spi2_cs3, blsp_spi3, blsp_spi3_cs1, blsp_spi3_cs2,
+ blsp_spi3_cs3, blsp_spi4, blsp_spi5, blsp_spi6, blsp_uart1,
+ blsp_uart2, blsp_uim1, blsp_uim2, cam1_rst, cam1_standby,
+ cam_mclk0, cam_mclk1, cci_async, cci_i2c, cci_timer0,
+ cci_timer1, cci_timer2, cdc_pdm0, codec_mad, dbg_out,
+ display_5v, dmic0_clk, dmic0_data, dsi_rst, ebi0_wrcdc,
+ euro_us, ext_lpass, flash_strobe, gcc_gp1_clk_a, gcc_gp1_clk_b,
+ gcc_gp2_clk_a, gcc_gp2_clk_b, gcc_gp3_clk_a, gcc_gp3_clk_b,
+ gsm0_tx0, gsm0_tx1, gsm1_tx0, gsm1_tx1, gyro_accl, kpsns0,
+ kpsns1, kpsns2, ldo_en, ldo_update, mag_int, mdp_vsync,
+ modem_tsync, m_voc, nav_pps, nav_tsync, pa_indicator, pbs0,
+ pbs1, pbs2, pri_mi2s, pri_mi2s_ws, prng_rosc,
+ pwr_crypto_enabled_a, pwr_crypto_enabled_b,
+ pwr_modem_enabled_a, pwr_modem_enabled_b, pwr_nav_enabled_a,
+ pwr_nav_enabled_b, qdss_ctitrig_in_a0, qdss_ctitrig_in_a1,
+ qdss_ctitrig_in_b0, qdss_ctitrig_in_b1, qdss_ctitrig_out_a0,
+ qdss_ctitrig_out_a1, qdss_ctitrig_out_b0, qdss_ctitrig_out_b1,
+ qdss_traceclk_a, qdss_traceclk_b, qdss_tracectl_a,
+ qdss_tracectl_b, qdss_tracedata_a, qdss_tracedata_b, reset_n,
+ sd_card, sd_write, sec_mi2s, smb_int, ssbi_wtr0, ssbi_wtr1,
+ uim1, uim2, uim3, uim_batt, wcss_bt, wcss_fm, wcss_wlan,
+ webcam1_rst ]
+
+ bias-pull-down: true
+ bias-pull-up: true
+ bias-disable: true
+ drive-strength: true
+ input-enable: true
+ output-high: true
+ output-low: true
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ msmgpio: pinctrl@1000000 {
+ compatible = "qcom,msm8916-pinctrl";
+ reg = <0x01000000 0x300000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ gpio-ranges = <&msmgpio 0 0 122>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ blsp1-uart2-sleep-state {
+ pins = "gpio4", "gpio5";
+ function = "gpio";
+
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ spi1-default-state {
+ spi-pins {
+ pins = "gpio0", "gpio1", "gpio3";
+ function = "blsp_spi1";
+
+ drive-strength = <12>;
+ bias-disable;
+ };
+
+ cs-pins {
+ pins = "gpio2";
+ function = "gpio";
+
+ drive-strength = <16>;
+ bias-disable;
+ output-high;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8953-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,msm8953-pinctrl.yaml
index d4da558cde54..c9a4a79e8d01 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,msm8953-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8953-pinctrl.yaml
@@ -9,9 +9,8 @@ title: Qualcomm Technologies, Inc. MSM8953 TLMM block
maintainers:
- Bjorn Andersson <bjorn.andersson@linaro.org>
-description: |
- This binding describes the Top Level Mode Multiplexer block found in the
- MSM8953 platform.
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm MSM8953 SoC.
properties:
compatible:
@@ -20,38 +19,30 @@ properties:
reg:
maxItems: 1
- interrupts:
- description: Specifies the TLMM summary IRQ
- maxItems: 1
-
+ interrupts: true
interrupt-controller: true
-
- '#interrupt-cells':
- description:
- Specifies the PIN numbers and Flags, as defined in defined in
- include/dt-bindings/interrupt-controller/irq.h
- const: 2
-
+ "#interrupt-cells": true
gpio-controller: true
-
gpio-reserved-ranges: true
+ "#gpio-cells": true
+ gpio-ranges: true
- '#gpio-cells':
- description: Specifying the pin number and flags, as defined in
- include/dt-bindings/gpio/gpio.h
- const: 2
-
- gpio-ranges:
- maxItems: 1
-
-#PIN CONFIGURATION NODES
patternProperties:
- '-pins$':
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-msm8953-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-msm8953-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-msm8953-tlmm-state:
type: object
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
Client device subnodes use below standard properties.
- $ref: "/schemas/pinctrl/pincfg-node.yaml"
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
properties:
pins:
@@ -113,60 +104,44 @@ patternProperties:
uim_batt, us_emitter, us_euro, wcss_bt, wcss_fm, wcss_wlan,
wcss_wlan0, wcss_wlan1, wcss_wlan2, wsa_en, wsa_io, wsa_irq ]
- drive-strength:
- enum: [2, 4, 6, 8, 10, 12, 14, 16]
- default: 2
- description:
- Selects the drive strength for the specified pins, in mA.
-
bias-pull-down: true
-
bias-pull-up: true
-
bias-disable: true
-
+ drive-strength: true
output-high: true
-
output-low: true
required:
- pins
- - function
additionalProperties: false
allOf:
- - $ref: "pinctrl.yaml#"
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
required:
- compatible
- reg
- - interrupts
- - interrupt-controller
- - '#interrupt-cells'
- - gpio-controller
- - '#gpio-cells'
- - gpio-ranges
additionalProperties: false
examples:
- |
- #include <dt-bindings/interrupt-controller/arm-gic.h>
- tlmm: pinctrl@1000000 {
- compatible = "qcom,msm8953-pinctrl";
- reg = <0x01000000 0x300000>;
- interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-controller;
- #interrupt-cells = <2>;
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&tlmm 0 0 142>;
-
- serial_default: serial-pins {
- pins = "gpio4", "gpio5";
- function = "blsp_uart2";
- drive-strength = <2>;
- bias-disable;
- };
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ tlmm: pinctrl@1000000 {
+ compatible = "qcom,msm8953-pinctrl";
+ reg = <0x01000000 0x300000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&tlmm 0 0 142>;
+
+ serial_default: serial-state {
+ pins = "gpio4", "gpio5";
+ function = "blsp_uart2";
+ drive-strength = <2>;
+ bias-disable;
};
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.txt
deleted file mode 100644
index a7dd213c77c6..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.txt
+++ /dev/null
@@ -1,190 +0,0 @@
-Qualcomm MSM8960 TLMM block
-
-This binding describes the Top Level Mode Multiplexer block found in the
-MSM8960 platform.
-
-- compatible:
- Usage: required
- Value type: <string>
- Definition: must be "qcom,msm8960-pinctrl"
-
-- reg:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: the base address and size of the TLMM register space.
-
-- interrupts:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: should specify the TLMM summary IRQ.
-
-- interrupt-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as an interrupt controller
-
-- #interrupt-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/interrupt-controller/irq.h>
-
-- gpio-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as a gpio controller
-
-- #gpio-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/gpio/gpio.h>
-
-- gpio-ranges:
- Usage: required
- Definition: see ../gpio/gpio.txt
-
-- gpio-reserved-ranges:
- Usage: optional
- Definition: see ../gpio/gpio.txt
-
-Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
-a general description of GPIO and interrupt bindings.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-The pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, drive strength, etc.
-
-
-PIN CONFIGURATION NODES:
-
-The name of each subnode is not important; all subnodes should be enumerated
-and processed purely based on their content.
-
-Each subnode only affects those parameters that are explicitly listed. In
-other words, a subnode that lists a mux function but no pin configuration
-parameters implies no information about any pin configuration parameters.
-Similarly, a pin subnode that describes a pullup parameter implies no
-information about e.g. the mux function.
-
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pin configuration subnode:
-
-- pins:
- Usage: required
- Value type: <string-array>
- Definition: List of gpio pins affected by the properties specified in
- this subnode. Valid pins are:
- gpio0-gpio151,
- sdc1_clk,
- sdc1_cmd,
- sdc1_data
- sdc3_clk,
- sdc3_cmd,
- sdc3_data
-
-- function:
- Usage: required
- Value type: <string>
- Definition: Specify the alternative function to be configured for the
- specified pins. Functions are only valid for gpio pins.
- Valid values are:
- audio_pcm, bt, cam_mclk0, cam_mclk1, cam_mclk2,
- codec_mic_i2s, codec_spkr_i2s, ext_gps, fm, gps_blanking,
- gps_pps_in, gps_pps_out, gp_clk_0a, gp_clk_0b, gp_clk_1a,
- gp_clk_1b, gp_clk_2a, gp_clk_2b, gp_mn, gp_pdm_0a,
- gp_pdm_0b, gp_pdm_1a, gp_pdm_1b, gp_pdm_2a, gp_pdm_2b, gpio,
- gsbi1, gsbi1_spi_cs1_n, gsbi1_spi_cs2a_n, gsbi1_spi_cs2b_n,
- gsbi1_spi_cs3_n, gsbi2, gsbi2_spi_cs1_n, gsbi2_spi_cs2_n,
- gsbi2_spi_cs3_n, gsbi3, gsbi4, gsbi4_3d_cam_i2c_l,
- gsbi4_3d_cam_i2c_r, gsbi5, gsbi5_3d_cam_i2c_l,
- gsbi5_3d_cam_i2c_r, gsbi6, gsbi7, gsbi8, gsbi9, gsbi10,
- gsbi11, gsbi11_spi_cs1a_n, gsbi11_spi_cs1b_n,
- gsbi11_spi_cs2a_n, gsbi11_spi_cs2b_n, gsbi11_spi_cs3_n,
- gsbi12, hdmi_cec, hdmi_ddc_clock, hdmi_ddc_data,
- hdmi_hot_plug_detect, hsic, mdp_vsync, mi2s, mic_i2s,
- pmb_clk, pmb_ext_ctrl, ps_hold, rpm_wdog, sdc2, sdc4, sdc5,
- slimbus1, slimbus2, spkr_i2s, ssbi1, ssbi2, ssbi_ext_gps,
- ssbi_pmic2, ssbi_qpa1, ssbi_ts, tsif1, tsif2, ts_eoc,
- usb_fs1, usb_fs1_oe, usb_fs1_oe_n, usb_fs2, usb_fs2_oe,
- usb_fs2_oe_n, vfe_camif_timer1_a, vfe_camif_timer1_b,
- vfe_camif_timer2, vfe_camif_timer3_a, vfe_camif_timer3_b,
- vfe_camif_timer4_a, vfe_camif_timer4_b, vfe_camif_timer4_c,
- vfe_camif_timer5_a, vfe_camif_timer5_b, vfe_camif_timer6_a,
- vfe_camif_timer6_b, vfe_camif_timer6_c, vfe_camif_timer7_a,
- vfe_camif_timer7_b, vfe_camif_timer7_c, wlan
-
-- bias-disable:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as no pull.
-
-- bias-pull-down:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull down.
-
-- bias-pull-up:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull up.
-
-- output-high:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- high.
- Not valid for sdc pins.
-
-- output-low:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- low.
- Not valid for sdc pins.
-
-- drive-strength:
- Usage: optional
- Value type: <u32>
- Definition: Selects the drive strength for the specified pins, in mA.
- Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
-
-Example:
-
- msmgpio: pinctrl@800000 {
- compatible = "qcom,msm8960-pinctrl";
- reg = <0x800000 0x4000>;
-
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&msmgpio 0 0 152>;
- interrupt-controller;
- #interrupt-cells = <2>;
- interrupts = <0 16 0x4>;
-
- gsbi8_uart: gsbi8-uart {
- mux {
- pins = "gpio34", "gpio35";
- function = "gsbi8";
- };
-
- tx {
- pins = "gpio34";
- drive-strength = <4>;
- bias-disable;
- };
-
- rx {
- pins = "gpio35";
- drive-strength = <2>;
- bias-pull-up;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.yaml
new file mode 100644
index 000000000000..33d07d531273
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8960-pinctrl.yaml
@@ -0,0 +1,164 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,msm8960-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm MSM8960 TLMM pin controller
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm MSM8960 SoC.
+
+properties:
+ compatible:
+ const: qcom,msm8960-pinctrl
+
+ reg:
+ maxItems: 1
+
+ interrupts: true
+ interrupt-controller: true
+ "#interrupt-cells": true
+ gpio-controller: true
+ "#gpio-cells": true
+ gpio-ranges: true
+ wakeup-parent: true
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 76
+
+ gpio-line-names:
+ maxItems: 152
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-msm8960-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-msm8960-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-msm8960-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ oneOf:
+ - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-4][0-9]|15[0-1])$"
+ - enum: [ sdc1_clk, sdc1_cmd, sdc1_data, sdc3_clk, sdc3_cmd,
+ sdc3_data ]
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ gpio, audio_pcm, bt, cam_mclk0, cam_mclk1, cam_mclk2,
+ codec_mic_i2s, codec_spkr_i2s, ext_gps, fm, gps_blanking,
+ gps_pps_in, gps_pps_out, gp_clk_0a, gp_clk_0b, gp_clk_1a,
+ gp_clk_1b, gp_clk_2a, gp_clk_2b, gp_mn, gp_pdm_0a, gp_pdm_0b,
+ gp_pdm_1a, gp_pdm_1b, gp_pdm_2a, gp_pdm_2b, gsbi1,
+ gsbi1_spi_cs1_n, gsbi1_spi_cs2a_n, gsbi1_spi_cs2b_n,
+ gsbi1_spi_cs3_n, gsbi2, gsbi2_spi_cs1_n, gsbi2_spi_cs2_n,
+ gsbi2_spi_cs3_n, gsbi3, gsbi4, gsbi4_3d_cam_i2c_l,
+ gsbi4_3d_cam_i2c_r, gsbi5, gsbi5_3d_cam_i2c_l,
+ gsbi5_3d_cam_i2c_r, gsbi6, gsbi7, gsbi8, gsbi9, gsbi10, gsbi11,
+ gsbi11_spi_cs1a_n, gsbi11_spi_cs1b_n, gsbi11_spi_cs2a_n,
+ gsbi11_spi_cs2b_n, gsbi11_spi_cs3_n, gsbi12, hdmi_cec,
+ hdmi_ddc_clock, hdmi_ddc_data, hdmi_hot_plug_detect, hsic,
+ mdp_vsync, mi2s, mic_i2s, pmb_clk, pmb_ext_ctrl, ps_hold,
+ rpm_wdog, sdc2, sdc4, sdc5, slimbus1, slimbus2, spkr_i2s,
+ ssbi1, ssbi2, ssbi_ext_gps, ssbi_pmic2, ssbi_qpa1, ssbi_ts,
+ tsif1, tsif2, ts_eoc, usb_fs1, usb_fs1_oe, usb_fs1_oe_n,
+ usb_fs2, usb_fs2_oe, usb_fs2_oe_n, vfe_camif_timer1_a,
+ vfe_camif_timer1_b, vfe_camif_timer2, vfe_camif_timer3_a,
+ vfe_camif_timer3_b, vfe_camif_timer4_a, vfe_camif_timer4_b,
+ vfe_camif_timer4_c, vfe_camif_timer5_a, vfe_camif_timer5_b,
+ vfe_camif_timer6_a, vfe_camif_timer6_b, vfe_camif_timer6_c,
+ vfe_camif_timer7_a, vfe_camif_timer7_b, vfe_camif_timer7_c,
+ wlan ]
+
+ bias-pull-down: true
+ bias-pull-up: true
+ bias-disable: true
+ drive-strength: true
+ input-enable: true
+ output-high: true
+ output-low: true
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ msmgpio: pinctrl@800000 {
+ compatible = "qcom,msm8960-pinctrl";
+ reg = <0x800000 0x4000>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ gpio-ranges = <&msmgpio 0 0 152>;
+ interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ spi1-default-state {
+ mosi-pins {
+ pins = "gpio6";
+ function = "gsbi1";
+ drive-strength = <12>;
+ bias-disable;
+ };
+
+ miso-pins {
+ pins = "gpio7";
+ function = "gsbi1";
+ drive-strength = <12>;
+ bias-disable;
+ };
+
+ cs-pins {
+ pins = "gpio8";
+ function = "gpio";
+ drive-strength = <12>;
+ bias-disable;
+ output-low;
+ };
+
+ clk-pins {
+ pins = "gpio9";
+ function = "gsbi1";
+ drive-strength = <12>;
+ bias-disable;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.txt
deleted file mode 100644
index 004056506679..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.txt
+++ /dev/null
@@ -1,121 +0,0 @@
-Qualcomm MSM8974 TLMM block
-
-Required properties:
-- compatible: "qcom,msm8974-pinctrl"
-- reg: Should be the base address and length of the TLMM block.
-- interrupts: Should be the parent IRQ of the TLMM block.
-- interrupt-controller: Marks the device node as an interrupt controller.
-- #interrupt-cells: Should be two.
-- gpio-controller: Marks the device node as a GPIO controller.
-- #gpio-cells : Should be two.
- The first cell is the gpio pin number and the
- second cell is used for optional parameters.
-- gpio-ranges: see ../gpio/gpio.txt
-
-Optional properties:
-
-- gpio-reserved-ranges: see ../gpio/gpio.txt
-
-Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
-a general description of GPIO and interrupt bindings.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-Qualcomm's pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, drive strength, etc.
-
-The name of each subnode is not important; all subnodes should be enumerated
-and processed purely based on their content.
-
-Each subnode only affects those parameters that are explicitly listed. In
-other words, a subnode that lists a mux function but no pin configuration
-parameters implies no information about any pin configuration parameters.
-Similarly, a pin subnode that describes a pullup parameter implies no
-information about e.g. the mux function.
-
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pin configuration subnode:
- pins, function, bias-disable, bias-pull-down, bias-pull-up, drive-strength.
-
-Non-empty subnodes must specify the 'pins' property.
-Note that not all properties are valid for all pins.
-
-
-Valid values for pins are:
- gpio0-gpio145
- Supports mux, bias and drive-strength
-
- sdc1_clk, sdc1_cmd, sdc1_data, sdc2_clk, sdc2_cmd, sdc2_data
- Supports bias and drive-strength
-
- hsic_data, hsic_strobe
- Supports only mux
-
-Valid values for function are:
- cci_i2c0, cci_i2c1, uim1, uim2, uim_batt_alarm,
- blsp_uim1, blsp_uart1, blsp_i2c1, blsp_spi1,
- blsp_uim2, blsp_uart2, blsp_i2c2, blsp_spi2,
- blsp_uim3, blsp_uart3, blsp_i2c3, blsp_spi3,
- blsp_uim4, blsp_uart4, blsp_i2c4, blsp_spi4,
- blsp_uim5, blsp_uart5, blsp_i2c5, blsp_spi5,
- blsp_uim6, blsp_uart6, blsp_i2c6, blsp_spi6,
- blsp_uim7, blsp_uart7, blsp_i2c7, blsp_spi7,
- blsp_uim8, blsp_uart8, blsp_i2c8, blsp_spi8,
- blsp_uim9, blsp_uart9, blsp_i2c9, blsp_spi9,
- blsp_uim10, blsp_uart10, blsp_i2c10, blsp_spi10,
- blsp_uim11, blsp_uart11, blsp_i2c11, blsp_spi11,
- blsp_uim12, blsp_uart12, blsp_i2c12, blsp_spi12,
- blsp_spi1_cs1, blsp_spi2_cs2, blsp_spi_cs3, blsp_spi2_cs1, blsp_spi2_cs2
- blsp_spi2_cs3, blsp_spi10_cs1, blsp_spi10_cs2, blsp_spi10_cs3,
- sdc3, sdc4, gcc_gp_clk1, gcc_gp_clk2, gcc_gp_clk3, cci_timer0, cci_timer1,
- cci_timer2, cci_timer3, cci_async_in0, cci_async_in1, cci_async_in2,
- cam_mckl0, cam_mclk1, cam_mclk2, cam_mclk3, mdp_vsync, hdmi_cec, hdmi_ddc,
- hdmi_hpd, edp_hpd, gp_pdm0, gp_pdm1, gp_pdm2, gp_pdm3, gp0_clk, gp1_clk,
- gp_mn, tsif1, tsif2, hsic, grfc, audio_ref_clk, qua_mi2s, pri_mi2s, spkr_mi2s,
- ter_mi2s, sec_mi2s, bt, fm, wlan, slimbus, hsic_ctl, gpio
-
- (Note that this is not yet the complete list of functions)
-
-
-
-Example:
-
- msmgpio: pinctrl@fd510000 {
- compatible = "qcom,msm8974-pinctrl";
- reg = <0xfd510000 0x4000>;
-
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&msmgpio 0 0 146>;
- interrupt-controller;
- #interrupt-cells = <2>;
- interrupts = <0 208 0>;
-
- pinctrl-names = "default";
- pinctrl-0 = <&uart2_default>;
-
- uart2_default: uart2_default {
- mux {
- pins = "gpio4", "gpio5";
- function = "blsp_uart2";
- };
-
- tx {
- pins = "gpio4";
- drive-strength = <4>;
- bias-disable;
- };
-
- rx {
- pins = "gpio5";
- drive-strength = <2>;
- bias-pull-up;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.yaml
new file mode 100644
index 000000000000..9287cbbff711
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8974-pinctrl.yaml
@@ -0,0 +1,179 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,msm8974-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm MSM8974 TLMM pin controller
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm MSM8974 SoC.
+
+properties:
+ compatible:
+ const: qcom,msm8974-pinctrl
+
+ reg:
+ maxItems: 1
+
+ interrupts: true
+ interrupt-controller: true
+ "#interrupt-cells": true
+ gpio-controller: true
+ "#gpio-cells": true
+ gpio-ranges: true
+ wakeup-parent: true
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 73
+
+ gpio-line-names:
+ maxItems: 146
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-msm8974-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-msm8974-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-msm8974-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ oneOf:
+ - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-3][0-9]|14[0-5])$"
+ - enum: [ hsic_data, hsic_strobe, sdc1_clk, sdc1_cmd, sdc1_data,
+ sdc2_clk, sdc2_cmd, sdc2_data ]
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ gpio, cci_i2c0, cci_i2c1, uim1, uim2, uim_batt_alarm,
+ blsp_uim1, blsp_uart1, blsp_i2c1, blsp_spi1, blsp_uim2,
+ blsp_uart2, blsp_i2c2, blsp_spi2, blsp_uim3, blsp_uart3,
+ blsp_i2c3, blsp_spi3, blsp_uim4, blsp_uart4, blsp_i2c4,
+ blsp_spi4, blsp_uim5, blsp_uart5, blsp_i2c5, blsp_spi5,
+ blsp_uim6, blsp_uart6, blsp_i2c6, blsp_spi6, blsp_uim7,
+ blsp_uart7, blsp_i2c7, blsp_spi7, blsp_uim8, blsp_uart8,
+ blsp_i2c8, blsp_spi8, blsp_uim9, blsp_uart9, blsp_i2c9,
+ blsp_spi9, blsp_uim10, blsp_uart10, blsp_i2c10, blsp_spi10,
+ blsp_uim11, blsp_uart11, blsp_i2c11, blsp_spi11, blsp_uim12,
+ blsp_uart12, blsp_i2c12, blsp_spi12, blsp_spi1_cs1,
+ blsp_spi2_cs2, blsp_spi_cs3, blsp_spi2_cs1, blsp_spi2_cs2
+ blsp_spi2_cs3, blsp_spi10_cs1, blsp_spi10_cs2, blsp_spi10_cs3,
+ sdc3, sdc4, gcc_gp_clk1, gcc_gp_clk2, gcc_gp_clk3, cci_timer0,
+ cci_timer1, cci_timer2, cci_timer3, cci_async_in0,
+ cci_async_in1, cci_async_in2, cam_mckl0, cam_mclk1, cam_mclk2,
+ cam_mclk3, mdp_vsync, hdmi_cec, hdmi_ddc, hdmi_hpd, edp_hpd,
+ gp_pdm0, gp_pdm1, gp_pdm2, gp_pdm3, gp0_clk, gp1_clk, gp_mn,
+ tsif1, tsif2, hsic, grfc, audio_ref_clk, qua_mi2s, pri_mi2s,
+ spkr_mi2s, ter_mi2s, sec_mi2s, bt, fm, wlan, slimbus, hsic_ctl ]
+
+ bias-pull-down: true
+ bias-pull-up: true
+ bias-disable: true
+ drive-strength: true
+ input-enable: true
+ output-high: true
+ output-low: true
+
+ required:
+ - pins
+
+ allOf:
+ - if:
+ properties:
+ pins:
+ contains:
+ enum:
+ - hsic_data
+ - hsic_strobe
+ required:
+ - pins
+ then:
+ properties:
+ bias-pull-down: false
+ bias-pull-up: false
+ bias-disable: false
+ drive-strength: false
+ input-enable: false
+ output-high: false
+ output-low: false
+
+ additionalProperties: false
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ tlmm: pinctrl@fd510000 {
+ compatible = "qcom,msm8974-pinctrl";
+ reg = <0xfd510000 0x4000>;
+ gpio-controller;
+ gpio-ranges = <&tlmm 0 0 146>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+
+ sdc1-off-state {
+ clk-pins {
+ pins = "sdc1_clk";
+ bias-disable;
+ drive-strength = <2>;
+ };
+
+ cmd-pins {
+ pins = "sdc1_cmd";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+
+ data-pins {
+ pins = "sdc1_data";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+ };
+
+ blsp2-uart1-sleep-state {
+ pins = "gpio41", "gpio42", "gpio43", "gpio44";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ hsic-state {
+ pins = "hsic_data", "hsic_strobe";
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8976-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8976-pinctrl.txt
deleted file mode 100644
index 70d04d12f136..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/qcom,msm8976-pinctrl.txt
+++ /dev/null
@@ -1,183 +0,0 @@
-Qualcomm MSM8976 TLMM block
-
-This binding describes the Top Level Mode Multiplexer block found in the
-MSM8956 and MSM8976 platforms.
-
-- compatible:
- Usage: required
- Value type: <string>
- Definition: must be "qcom,msm8976-pinctrl"
-
-- reg:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: the base address and size of the TLMM register space.
-
-- interrupts:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: should specify the TLMM summary IRQ.
-
-- interrupt-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as an interrupt controller
-
-- #interrupt-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/interrupt-controller/irq.h>
-
-- gpio-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as a gpio controller
-
-- #gpio-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/gpio/gpio.h>
-
-- gpio-ranges:
- Usage: required
- Definition: see ../gpio/gpio.txt
-
-- gpio-reserved-ranges:
- Usage: optional
- Definition: see ../gpio/gpio.txt
-
-Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
-a general description of GPIO and interrupt bindings.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-The pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, drive strength, etc.
-
-
-PIN CONFIGURATION NODES:
-
-The name of each subnode is not important; all subnodes should be enumerated
-and processed purely based on their content.
-
-Each subnode only affects those parameters that are explicitly listed. In
-other words, a subnode that lists a mux function but no pin configuration
-parameters implies no information about any pin configuration parameters.
-Similarly, a pin subnode that describes a pullup parameter implies no
-information about e.g. the mux function.
-
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pin configuration subnode:
-
-- pins:
- Usage: required
- Value type: <string-array>
- Definition: List of gpio pins affected by the properties specified in
- this subnode.
-
- Valid pins are:
- gpio0-gpio145
- Supports mux, bias and drive-strength
-
- sdc1_clk, sdc1_cmd, sdc1_data,
- sdc2_clk, sdc2_cmd, sdc2_data,
- sdc3_clk, sdc3_cmd, sdc3_data
- Supports bias and drive-strength
-
-- function:
- Usage: required
- Value type: <string>
- Definition: Specify the alternative function to be configured for the
- specified pins. Functions are only valid for gpio pins.
- Valid values are:
-
- gpio, blsp_uart1, blsp_spi1, smb_int, blsp_i2c1, blsp_spi2,
- blsp_uart2, blsp_i2c2, gcc_gp1_clk_b, blsp_spi3,
- qdss_tracedata_b, blsp_i2c3, gcc_gp2_clk_b, gcc_gp3_clk_b,
- blsp_spi4, cap_int, blsp_i2c4, blsp_spi5, blsp_uart5,
- qdss_traceclk_a, m_voc, blsp_i2c5, qdss_tracectl_a,
- qdss_tracedata_a, blsp_spi6, blsp_uart6, qdss_tracectl_b,
- blsp_i2c6, qdss_traceclk_b, mdp_vsync, pri_mi2s_mclk_a,
- sec_mi2s_mclk_a, cam_mclk, cci0_i2c, cci1_i2c, blsp1_spi,
- blsp3_spi, gcc_gp1_clk_a, gcc_gp2_clk_a, gcc_gp3_clk_a,
- uim_batt, sd_write, uim1_data, uim1_clk, uim1_reset,
- uim1_present, uim2_data, uim2_clk, uim2_reset,
- uim2_present, ts_xvdd, mipi_dsi0, us_euro, ts_resout,
- ts_sample, sec_mi2s_mclk_b, pri_mi2s, codec_reset,
- cdc_pdm0, us_emitter, pri_mi2s_mclk_b, pri_mi2s_mclk_c,
- lpass_slimbus, lpass_slimbus0, lpass_slimbus1, codec_int1,
- codec_int2, wcss_bt, sdc3, wcss_wlan2, wcss_wlan1,
- wcss_wlan0, wcss_wlan, wcss_fm, key_volp, key_snapshot,
- key_focus, key_home, pwr_down, dmic0_clk, hdmi_int,
- dmic0_data, wsa_vi, wsa_en, blsp_spi8, wsa_irq, blsp_i2c8,
- pa_indicator, modem_tsync, ssbi_wtr1, gsm1_tx, gsm0_tx,
- sdcard_det, sec_mi2s, ss_switch,
-
-- bias-disable:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as no pull.
-
-- bias-pull-down:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull down.
-
-- bias-pull-up:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull up.
-
-- output-high:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- high.
- Not valid for sdc pins.
-
-- output-low:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- low.
- Not valid for sdc pins.
-
-- drive-strength:
- Usage: optional
- Value type: <u32>
- Definition: Selects the drive strength for the specified pins, in mA.
- Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
-
-Example:
-
- tlmm: pinctrl@1000000 {
- compatible = "qcom,msm8976-pinctrl";
- reg = <0x1000000 0x300000>;
- interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&tlmm 0 0 145>;
- interrupt-controller;
- #interrupt-cells = <2>;
-
- blsp1_uart2_active: blsp1_uart2_active {
- mux {
- pins = "gpio4", "gpio5", "gpio6", "gpio7";
- function = "blsp_uart2";
- };
-
- config {
- pins = "gpio4", "gpio5", "gpio6", "gpio7";
- drive-strength = <2>;
- bias-disable;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8976-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,msm8976-pinctrl.yaml
new file mode 100644
index 000000000000..858f45710fe2
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8976-pinctrl.yaml
@@ -0,0 +1,136 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,msm8976-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm MSM8976 TLMM pin controller
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm MSM8976 SoC.
+
+properties:
+ compatible:
+ const: qcom,msm8976-pinctrl
+
+ reg:
+ maxItems: 1
+
+ interrupts: true
+ interrupt-controller: true
+ "#interrupt-cells": true
+ gpio-controller: true
+ "#gpio-cells": true
+ gpio-ranges: true
+ wakeup-parent: true
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 73
+
+ gpio-line-names:
+ maxItems: 145
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-msm8976-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-msm8976-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-msm8976-tlmm-state:
+ type: object
+ description:
+ Desired pin configuration for a device or its specific state (like sleep
+ or active).
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this state.
+ items:
+ oneOf:
+ - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-3][0-9]|14[0-4])$"
+ - enum: [ qdsd_clk, qdsd_cmd, qdsd_data0, qdsd_data1, qdsd_data2,
+ qdsd_data3, sdc1_clk, sdc1_cmd, sdc1_data, sdc1_rclk,
+ sdc2_clk, sdc2_cmd, sdc2_data ]
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ gpio, blsp_uart1, blsp_spi1, smb_int, blsp_i2c1, blsp_spi2,
+ blsp_uart2, blsp_i2c2, gcc_gp1_clk_b, blsp_spi3,
+ qdss_tracedata_b, blsp_i2c3, gcc_gp2_clk_b, gcc_gp3_clk_b,
+ blsp_spi4, cap_int, blsp_i2c4, blsp_spi5, blsp_uart5,
+ qdss_traceclk_a, m_voc, blsp_i2c5, qdss_tracectl_a,
+ qdss_tracedata_a, blsp_spi6, blsp_uart6, qdss_tracectl_b,
+ blsp_i2c6, qdss_traceclk_b, mdp_vsync, pri_mi2s_mclk_a,
+ sec_mi2s_mclk_a, cam_mclk, cci0_i2c, cci1_i2c, blsp1_spi,
+ blsp3_spi, gcc_gp1_clk_a, gcc_gp2_clk_a, gcc_gp3_clk_a,
+ uim_batt, sd_write, uim1_data, uim1_clk, uim1_reset,
+ uim1_present, uim2_data, uim2_clk, uim2_reset, uim2_present,
+ ts_xvdd, mipi_dsi0, us_euro, ts_resout, ts_sample,
+ sec_mi2s_mclk_b, pri_mi2s, codec_reset, cdc_pdm0, us_emitter,
+ pri_mi2s_mclk_b, pri_mi2s_mclk_c, lpass_slimbus,
+ lpass_slimbus0, lpass_slimbus1, codec_int1, codec_int2,
+ wcss_bt, sdc3, wcss_wlan2, wcss_wlan1, wcss_wlan0, wcss_wlan,
+ wcss_fm, key_volp, key_snapshot, key_focus, key_home, pwr_down,
+ dmic0_clk, hdmi_int, dmic0_data, wsa_vi, wsa_en, blsp_spi8,
+ wsa_irq, blsp_i2c8, pa_indicator, modem_tsync, ssbi_wtr1,
+ gsm1_tx, gsm0_tx, sdcard_det, sec_mi2s, ss_switch ]
+
+ bias-pull-down: true
+ bias-pull-up: true
+ bias-disable: true
+ drive-strength: true
+ input-enable: true
+ output-high: true
+ output-low: true
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ tlmm: pinctrl@1000000 {
+ compatible = "qcom,msm8976-pinctrl";
+ reg = <0x1000000 0x300000>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ gpio-ranges = <&tlmm 0 0 145>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ blsp1-uart2-active-state {
+ pins = "gpio4", "gpio5", "gpio6", "gpio7";
+ function = "blsp_uart2";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt
deleted file mode 100644
index da52df6273bc..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.txt
+++ /dev/null
@@ -1,186 +0,0 @@
-Qualcomm MSM8994 TLMM block
-
-This binding describes the Top Level Mode Multiplexer block found in the
-MSM8994 platform.
-
-- compatible:
- Usage: required
- Value type: <string>
- Definition: Should contain one of:
- "qcom,msm8992-pinctrl",
- "qcom,msm8994-pinctrl".
-
-- reg:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: the base address and size of the TLMM register space.
-
-- interrupts:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: should specify the TLMM summary IRQ.
-
-- interrupt-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as an interrupt controller
-
-- #interrupt-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/interrupt-controller/irq.h>
-
-- gpio-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as a gpio controller
-
-- #gpio-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/gpio/gpio.h>
-
-- gpio-ranges:
- Usage: required
- Definition: see ../gpio/gpio.txt
-
-- gpio-reserved-ranges:
- Usage: optional
- Definition: see ../gpio/gpio.txt
-
-Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
-a general description of GPIO and interrupt bindings.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-The pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, drive strength, etc.
-
-
-PIN CONFIGURATION NODES:
-
-The name of each subnode is not important; all subnodes should be enumerated
-and processed purely based on their content.
-
-Each subnode only affects those parameters that are explicitly listed. In
-other words, a subnode that lists a mux function but no pin configuration
-parameters implies no information about any pin configuration parameters.
-Similarly, a pin subnode that describes a pullup parameter implies no
-information about e.g. the mux function.
-
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pin configuration subnode:
-
-- pins:
- Usage: required
- Value type: <string-array>
- Definition: List of gpio pins affected by the properties specified in
- this subnode.
-
- Valid pins are:
- gpio0-gpio145
- Supports mux, bias and drive-strength
-
- sdc1_clk, sdc1_cmd, sdc1_data sdc1_rclk, sdc2_clk,
- sdc2_cmd, sdc2_data
- Supports bias and drive-strength
-
-- function:
- Usage: required
- Value type: <string>
- Definition: Specify the alternative function to be configured for the
- specified pins. Functions are only valid for gpio pins.
- Valid values are:
-
- audio_ref_clk, blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c4, blsp_i2c5,
- blsp_i2c6, blsp_i2c7, blsp_i2c8, blsp_i2c9, blsp_i2c10, blsp_i2c11,
- blsp_i2c12, blsp_spi1, blsp_spi1_cs1, blsp_spi1_cs2, blsp_spi1_cs3,
- blsp_spi2, blsp_spi2_cs1, blsp_spi2_cs2, blsp_spi2_cs3, blsp_spi3,
- blsp_spi4, blsp_spi5, blsp_spi6, blsp_spi7, blsp_spi8, blsp_spi9,
- blsp_spi10, blsp_spi10_cs1, blsp_spi10_cs2, blsp_spi10_cs3, blsp_spi11,
- blsp_spi12, blsp_uart1, blsp_uart2, blsp_uart3, blsp_uart4, blsp_uart5,
- blsp_uart6, blsp_uart7, blsp_uart8, blsp_uart9, blsp_uart10, blsp_uart11,
- blsp_uart12, blsp_uim1, blsp_uim2, blsp_uim3, blsp_uim4, blsp_uim5,
- blsp_uim6, blsp_uim7, blsp_uim8, blsp_uim9, blsp_uim10, blsp_uim11,
- blsp_uim12, blsp11_i2c_scl_b, blsp11_i2c_sda_b, blsp11_uart_rx_b,
- blsp11_uart_tx_b, cam_mclk0, cam_mclk1, cam_mclk2, cam_mclk3,
- cci_async_in0, cci_async_in1, cci_async_in2, cci_i2c0, cci_i2c1,
- cci_timer0, cci_timer1, cci_timer2, cci_timer3, cci_timer4,
- gcc_gp1_clk_a, gcc_gp1_clk_b, gcc_gp2_clk_a, gcc_gp2_clk_b, gcc_gp3_clk_a,
- gcc_gp3_clk_b, gp_mn, gp_pdm0, gp_pdm1, gp_pdm2, gp0_clk,
- gp1_clk, gps_tx, gsm_tx, hdmi_cec, hdmi_ddc, hdmi_hpd, hdmi_rcv,
- mdp_vsync, mss_lte, nav_pps, nav_tsync, qdss_cti_trig_in_a,
- qdss_cti_trig_in_b, qdss_cti_trig_in_c, qdss_cti_trig_in_d,
- qdss_cti_trig_out_a, qdss_cti_trig_out_b, qdss_cti_trig_out_c,
- qdss_cti_trig_out_d, qdss_traceclk_a, qdss_traceclk_b, qdss_tracectl_a,
- qdss_tracectl_b, qdss_tracedata_a, qdss_tracedata_b, qua_mi2s, pci_e0,
- pci_e1, pri_mi2s, sdc4, sec_mi2s, slimbus, spkr_i2s, ter_mi2s, tsif1,
- tsif2, uim_batt_alarm, uim1, uim2, uim3, uim4, gpio
-
-- bias-disable:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as no pull.
-
-- bias-pull-down:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull down.
-
-- bias-pull-up:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull up.
-
-- output-high:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- high.
- Not valid for sdc pins.
-
-- output-low:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- low.
- Not valid for sdc pins.
-
-- drive-strength:
- Usage: optional
- Value type: <u32>
- Definition: Selects the drive strength for the specified pins, in mA.
- Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
-
-Example:
-
- msmgpio: pinctrl@fd510000 {
- compatible = "qcom,msm8994-pinctrl";
- reg = <0xfd510000 0x4000>;
- interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&msmgpio 0 0 146>;
- interrupt-controller;
- #interrupt-cells = <2>;
-
- blsp1_uart2_default: blsp1_uart2_default {
- pinmux {
- pins = "gpio4", "gpio5";
- function = "blsp_uart2";
- };
- pinconf {
- pins = "gpio4", "gpio5";
- drive-strength = <16>;
- bias-disable;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.yaml
new file mode 100644
index 000000000000..55d5439c6c24
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8994-pinctrl.yaml
@@ -0,0 +1,162 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,msm8994-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm MSM8994 TLMM pin controller
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm MSM8994 SoC.
+
+properties:
+ compatible:
+ enum:
+ - qcom,msm8992-pinctrl
+ - qcom,msm8994-pinctrl
+
+ reg:
+ maxItems: 1
+
+ interrupts: true
+ interrupt-controller: true
+ "#interrupt-cells": true
+ gpio-controller: true
+ "#gpio-cells": true
+ gpio-ranges: true
+ wakeup-parent: true
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 75
+
+ gpio-line-names:
+ maxItems: 150
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-msm8994-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-msm8994-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-msm8994-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ oneOf:
+ - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-4][0-9])$"
+ - enum: [ sdc1_clk, sdc1_cmd, sdc1_data, sdc1_rclk, sdc2_clk,
+ sdc2_cmd, sdc2_data, sdc3_clk, sdc3_cmd, sdc3_data ]
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ gpio, audio_ref_clk, blsp_i2c1, blsp_i2c2, blsp_i2c3,
+ blsp_i2c4, blsp_i2c5, blsp_i2c6, blsp_i2c7, blsp_i2c8,
+ blsp_i2c9, blsp_i2c10, blsp_i2c11, blsp_i2c12, blsp_spi1,
+ blsp_spi1_cs1, blsp_spi1_cs2, blsp_spi1_cs3, blsp_spi2,
+ blsp_spi2_cs1, blsp_spi2_cs2, blsp_spi2_cs3, blsp_spi3,
+ blsp_spi4, blsp_spi5, blsp_spi6, blsp_spi7, blsp_spi8,
+ blsp_spi9, blsp_spi10, blsp_spi10_cs1, blsp_spi10_cs2,
+ blsp_spi10_cs3, blsp_spi11, blsp_spi12, blsp_uart1, blsp_uart2,
+ blsp_uart3, blsp_uart4, blsp_uart5, blsp_uart6, blsp_uart7,
+ blsp_uart8, blsp_uart9, blsp_uart10, blsp_uart11, blsp_uart12,
+ blsp_uim1, blsp_uim2, blsp_uim3, blsp_uim4, blsp_uim5,
+ blsp_uim6, blsp_uim7, blsp_uim8, blsp_uim9, blsp_uim10,
+ blsp_uim11, blsp_uim12, blsp11_i2c_scl_b, blsp11_i2c_sda_b,
+ blsp11_uart_rx_b, blsp11_uart_tx_b, cam_mclk0, cam_mclk1,
+ cam_mclk2, cam_mclk3, cci_async_in0, cci_async_in1,
+ cci_async_in2, cci_i2c0, cci_i2c1, cci_timer0, cci_timer1,
+ cci_timer2, cci_timer3, cci_timer4, gcc_gp1_clk_a,
+ gcc_gp1_clk_b, gcc_gp2_clk_a, gcc_gp2_clk_b, gcc_gp3_clk_a,
+ gcc_gp3_clk_b, gp_mn, gp_pdm0, gp_pdm1, gp_pdm2, gp0_clk,
+ gp1_clk, gps_tx, gsm_tx, hdmi_cec, hdmi_ddc, hdmi_hpd,
+ hdmi_rcv, mdp_vsync, mss_lte, nav_pps, nav_tsync,
+ qdss_cti_trig_in_a, qdss_cti_trig_in_b, qdss_cti_trig_in_c,
+ qdss_cti_trig_in_d, qdss_cti_trig_out_a, qdss_cti_trig_out_b,
+ qdss_cti_trig_out_c, qdss_cti_trig_out_d, qdss_traceclk_a,
+ qdss_traceclk_b, qdss_tracectl_a, qdss_tracectl_b,
+ qdss_tracedata_a, qdss_tracedata_b, qua_mi2s, pci_e0, pci_e1,
+ pri_mi2s, sdc4, sec_mi2s, slimbus, spkr_i2s, ter_mi2s, tsif1,
+ tsif2, uim_batt_alarm, uim1, uim2, uim3, uim4 ]
+
+ bias-pull-down: true
+ bias-pull-up: true
+ bias-disable: true
+ drive-strength: true
+ input-enable: true
+ output-high: true
+ output-low: true
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ tlmm: pinctrl@fd510000 {
+ compatible = "qcom,msm8994-pinctrl";
+ reg = <0xfd510000 0x4000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ gpio-ranges = <&tlmm 0 0 146>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ blsp1-uart2-default-state {
+ function = "blsp_uart2";
+ pins = "gpio4", "gpio5";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ blsp1-spi1-default-state {
+ default-pins {
+ pins = "gpio0", "gpio1", "gpio3";
+ function = "blsp_spi1";
+ drive-strength = <10>;
+ bias-pull-down;
+ };
+
+ cs-pins {
+ pins = "gpio8";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8996-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8996-pinctrl.txt
deleted file mode 100644
index a56cb882830c..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/qcom,msm8996-pinctrl.txt
+++ /dev/null
@@ -1,208 +0,0 @@
-Qualcomm MSM8996 TLMM block
-
-This binding describes the Top Level Mode Multiplexer block found in the
-MSM8996 platform.
-
-- compatible:
- Usage: required
- Value type: <string>
- Definition: must be "qcom,msm8996-pinctrl"
-
-- reg:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: the base address and size of the TLMM register space.
-
-- interrupts:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: should specify the TLMM summary IRQ.
-
-- interrupt-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as an interrupt controller
-
-- #interrupt-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/interrupt-controller/irq.h>
-
-- gpio-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as a gpio controller
-
-- #gpio-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/gpio/gpio.h>
-
-- gpio-ranges:
- Usage: required
- Definition: see ../gpio/gpio.txt
-
-- gpio-reserved-ranges:
- Usage: optional
- Definition: see ../gpio/gpio.txt
-
-Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
-a general description of GPIO and interrupt bindings.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-The pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, drive strength, etc.
-
-
-PIN CONFIGURATION NODES:
-
-The name of each subnode is not important; all subnodes should be enumerated
-and processed purely based on their content.
-
-Each subnode only affects those parameters that are explicitly listed. In
-other words, a subnode that lists a mux function but no pin configuration
-parameters implies no information about any pin configuration parameters.
-Similarly, a pin subnode that describes a pullup parameter implies no
-information about e.g. the mux function.
-
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pin configuration subnode:
-
-- pins:
- Usage: required
- Value type: <string-array>
- Definition: List of gpio pins affected by the properties specified in
- this subnode.
-
- Valid pins are:
- gpio0-gpio149
- Supports mux, bias and drive-strength
-
- sdc1_clk, sdc1_cmd, sdc1_data sdc2_clk, sdc2_cmd,
- sdc2_data sdc1_rclk
- Supports bias and drive-strength
-
-- function:
- Usage: required
- Value type: <string>
- Definition: Specify the alternative function to be configured for the
- specified pins. Functions are only valid for gpio pins.
- Valid values are:
-
- blsp_uart1, blsp_spi1, blsp_i2c1, blsp_uim1, atest_tsens,
- bimc_dte1, dac_calib0, blsp_spi8, blsp_uart8, blsp_uim8,
- qdss_cti_trig_out_b, bimc_dte0, dac_calib1, qdss_cti_trig_in_b,
- dac_calib2, atest_tsens2, atest_usb1, blsp_spi10, blsp_uart10,
- blsp_uim10, atest_bbrx1, atest_usb13, atest_bbrx0, atest_usb12,
- mdp_vsync, edp_lcd, blsp_i2c10, atest_gpsadc1, atest_usb11,
- atest_gpsadc0, edp_hot, atest_usb10, m_voc, dac_gpio, atest_char,
- cam_mclk, pll_bypassnl, qdss_stm7, blsp_i2c8, qdss_tracedata_b,
- pll_reset, qdss_stm6, qdss_stm5, qdss_stm4, atest_usb2, cci_i2c,
- qdss_stm3, dac_calib3, atest_usb23, atest_char3, dac_calib4,
- qdss_stm2, atest_usb22, atest_char2, qdss_stm1, dac_calib5,
- atest_usb21, atest_char1, dbg_out, qdss_stm0, dac_calib6,
- atest_usb20, atest_char0, dac_calib10, qdss_stm10,
- qdss_cti_trig_in_a, cci_timer4, blsp_spi6, blsp_uart6, blsp_uim6,
- blsp2_spi, qdss_stm9, qdss_cti_trig_out_a, dac_calib11,
- qdss_stm8, cci_timer0, qdss_stm13, dac_calib7, cci_timer1,
- qdss_stm12, dac_calib8, cci_timer2, blsp1_spi, qdss_stm11,
- dac_calib9, cci_timer3, cci_async, dac_calib12, blsp_i2c6,
- qdss_tracectl_a, dac_calib13, qdss_traceclk_a, dac_calib14,
- dac_calib15, hdmi_rcv, dac_calib16, hdmi_cec, pwr_modem,
- dac_calib17, hdmi_ddc, pwr_nav, dac_calib18, pwr_crypto,
- dac_calib19, hdmi_hot, dac_calib20, dac_calib21, pci_e0,
- dac_calib22, dac_calib23, dac_calib24, tsif1_sync, dac_calib25,
- sd_write, tsif1_error, blsp_spi2, blsp_uart2, blsp_uim2,
- qdss_cti, blsp_i2c2, blsp_spi3, blsp_uart3, blsp_uim3, blsp_i2c3,
- uim3, blsp_spi9, blsp_uart9, blsp_uim9, blsp10_spi, blsp_i2c9,
- blsp_spi7, blsp_uart7, blsp_uim7, qdss_tracedata_a, blsp_i2c7,
- qua_mi2s, gcc_gp1_clk_a, ssc_irq, uim4, blsp_spi11, blsp_uart11,
- blsp_uim11, gcc_gp2_clk_a, gcc_gp3_clk_a, blsp_i2c11, cri_trng0,
- cri_trng1, cri_trng, qdss_stm18, pri_mi2s, qdss_stm17, blsp_spi4,
- blsp_uart4, blsp_uim4, qdss_stm16, qdss_stm15, blsp_i2c4,
- qdss_stm14, dac_calib26, spkr_i2s, audio_ref, lpass_slimbus,
- isense_dbg, tsense_pwm1, tsense_pwm2, btfm_slimbus, ter_mi2s,
- qdss_stm22, qdss_stm21, qdss_stm20, qdss_stm19, gcc_gp1_clk_b,
- sec_mi2s, blsp_spi5, blsp_uart5, blsp_uim5, gcc_gp2_clk_b,
- gcc_gp3_clk_b, blsp_i2c5, blsp_spi12, blsp_uart12, blsp_uim12,
- qdss_stm25, qdss_stm31, blsp_i2c12, qdss_stm30, qdss_stm29,
- tsif1_clk, qdss_stm28, tsif1_en, tsif1_data, sdc4_cmd, qdss_stm27,
- qdss_traceclk_b, tsif2_error, sdc43, vfr_1, qdss_stm26, tsif2_clk,
- sdc4_clk, qdss_stm24, tsif2_en, sdc42, qdss_stm23, qdss_tracectl_b,
- sd_card, tsif2_data, sdc41, tsif2_sync, sdc40, mdp_vsync_p_b,
- ldo_en, mdp_vsync_s_b, ldo_update, blsp11_uart_tx_b, blsp11_uart_rx_b,
- blsp11_i2c_sda_b, prng_rosc, blsp11_i2c_scl_b, uim2, uim1, uim_batt,
- pci_e2, pa_indicator, adsp_ext, ddr_bist, qdss_tracedata_11,
- qdss_tracedata_12, modem_tsync, nav_dr, nav_pps, pci_e1, gsm_tx,
- qspi_cs, ssbi2, ssbi1, mss_lte, qspi_clk, qspi0, qspi1, qspi2, qspi3,
- gpio
-
-- bias-disable:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as no pull.
-
-- bias-pull-down:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull down.
-
-- bias-pull-up:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull up.
-
-- output-high:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- high.
- Not valid for sdc pins.
-
-- output-low:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- low.
- Not valid for sdc pins.
-
-- drive-strength:
- Usage: optional
- Value type: <u32>
- Definition: Selects the drive strength for the specified pins, in mA.
- Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
-
-Example:
-
- tlmm: pinctrl@1010000 {
- compatible = "qcom,msm8996-pinctrl";
- reg = <0x01010000 0x300000>;
- interrupts = <0 208 0>;
- gpio-controller;
- gpio-ranges = <&tlmm 0 0 150>;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
-
- uart_console_active: uart_console_active {
- mux {
- pins = "gpio4", "gpio5";
- function = "blsp_uart8";
- };
-
- config {
- pins = "gpio4", "gpio5";
- drive-strength = <2>;
- bias-disable;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8996-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,msm8996-pinctrl.yaml
new file mode 100644
index 000000000000..8e1cd4ba1116
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8996-pinctrl.yaml
@@ -0,0 +1,182 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,msm8996-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm MSM8996 TLMM pin controller
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm MSM8996 SoC.
+
+properties:
+ compatible:
+ const: qcom,msm8996-pinctrl
+
+ reg:
+ maxItems: 1
+
+ interrupts: true
+ interrupt-controller: true
+ "#interrupt-cells": true
+ gpio-controller: true
+ "#gpio-cells": true
+ gpio-ranges: true
+ wakeup-parent: true
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 75
+
+ gpio-line-names:
+ maxItems: 150
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-msm8996-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-msm8996-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-msm8996-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ oneOf:
+ - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-4][0-9])$"
+ - enum: [ sdc1_clk, sdc1_cmd, sdc1_data, sdc1_rclk, sdc2_clk,
+ sdc2_cmd, sdc2_data ]
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ gpio, blsp_uart1, blsp_spi1, blsp_i2c1, blsp_uim1, atest_tsens,
+ bimc_dte1, dac_calib0, blsp_spi8, blsp_uart8, blsp_uim8,
+ qdss_cti_trig_out_b, bimc_dte0, dac_calib1, qdss_cti_trig_in_b,
+ dac_calib2, atest_tsens2, atest_usb1, blsp_spi10, blsp_uart10,
+ blsp_uim10, atest_bbrx1, atest_usb13, atest_bbrx0, atest_usb12,
+ mdp_vsync, edp_lcd, blsp_i2c10, atest_gpsadc1, atest_usb11,
+ atest_gpsadc0, edp_hot, atest_usb10, m_voc, dac_gpio,
+ atest_char, cam_mclk, pll_bypassnl, qdss_stm7, blsp_i2c8,
+ qdss_tracedata_b, pll_reset, qdss_stm6, qdss_stm5, qdss_stm4,
+ atest_usb2, cci_i2c, qdss_stm3, dac_calib3, atest_usb23,
+ atest_char3, dac_calib4, qdss_stm2, atest_usb22, atest_char2,
+ qdss_stm1, dac_calib5, atest_usb21, atest_char1, dbg_out,
+ qdss_stm0, dac_calib6, atest_usb20, atest_char0, dac_calib10,
+ qdss_stm10, qdss_cti_trig_in_a, cci_timer4, blsp_spi6,
+ blsp_uart6, blsp_uim6, blsp2_spi, qdss_stm9,
+ qdss_cti_trig_out_a, dac_calib11, qdss_stm8, cci_timer0,
+ qdss_stm13, dac_calib7, cci_timer1, qdss_stm12, dac_calib8,
+ cci_timer2, blsp1_spi, qdss_stm11, dac_calib9, cci_timer3,
+ cci_async, dac_calib12, blsp_i2c6, qdss_tracectl_a,
+ dac_calib13, qdss_traceclk_a, dac_calib14, dac_calib15,
+ hdmi_rcv, dac_calib16, hdmi_cec, pwr_modem, dac_calib17,
+ hdmi_ddc, pwr_nav, dac_calib18, pwr_crypto, dac_calib19,
+ hdmi_hot, dac_calib20, dac_calib21, pci_e0, dac_calib22,
+ dac_calib23, dac_calib24, tsif1_sync, dac_calib25, sd_write,
+ tsif1_error, blsp_spi2, blsp_uart2, blsp_uim2, qdss_cti,
+ blsp_i2c2, blsp_spi3, blsp_uart3, blsp_uim3, blsp_i2c3, uim3,
+ blsp_spi9, blsp_uart9, blsp_uim9, blsp10_spi, blsp_i2c9,
+ blsp_spi7, blsp_uart7, blsp_uim7, qdss_tracedata_a, blsp_i2c7,
+ qua_mi2s, gcc_gp1_clk_a, ssc_irq, uim4, blsp_spi11,
+ blsp_uart11, blsp_uim11, gcc_gp2_clk_a, gcc_gp3_clk_a,
+ blsp_i2c11, cri_trng0, cri_trng1, cri_trng, qdss_stm18,
+ pri_mi2s, qdss_stm17, blsp_spi4, blsp_uart4, blsp_uim4,
+ qdss_stm16, qdss_stm15, blsp_i2c4, qdss_stm14, dac_calib26,
+ spkr_i2s, audio_ref, lpass_slimbus, isense_dbg, tsense_pwm1,
+ tsense_pwm2, btfm_slimbus, ter_mi2s, qdss_stm22, qdss_stm21,
+ qdss_stm20, qdss_stm19, gcc_gp1_clk_b, sec_mi2s, blsp_spi5,
+ blsp_uart5, blsp_uim5, gcc_gp2_clk_b, gcc_gp3_clk_b, blsp_i2c5,
+ blsp_spi12, blsp_uart12, blsp_uim12, qdss_stm25, qdss_stm31,
+ blsp_i2c12, qdss_stm30, qdss_stm29, tsif1_clk, qdss_stm28,
+ tsif1_en, tsif1_data, sdc4_cmd, qdss_stm27, qdss_traceclk_b,
+ tsif2_error, sdc43, vfr_1, qdss_stm26, tsif2_clk, sdc4_clk,
+ qdss_stm24, tsif2_en, sdc42, qdss_stm23, qdss_tracectl_b,
+ sd_card, tsif2_data, sdc41, tsif2_sync, sdc40, mdp_vsync_p_b,
+ ldo_en, mdp_vsync_s_b, ldo_update, blsp11_uart_tx_b,
+ blsp11_uart_rx_b, blsp11_i2c_sda_b, prng_rosc,
+ blsp11_i2c_scl_b, uim2, uim1, uim_batt, pci_e2, pa_indicator,
+ adsp_ext, ddr_bist, qdss_tracedata_11, qdss_tracedata_12,
+ modem_tsync, nav_dr, nav_pps, pci_e1, gsm_tx, qspi_cs, ssbi2,
+ ssbi1, mss_lte, qspi_clk, qspi0, qspi1, qspi2, qspi3 ]
+
+ bias-pull-down: true
+ bias-pull-up: true
+ bias-disable: true
+ drive-strength: true
+ input-enable: true
+ output-high: true
+ output-low: true
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ tlmm: pinctrl@1010000 {
+ compatible = "qcom,msm8996-pinctrl";
+ reg = <0x01010000 0x300000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ gpio-ranges = <&tlmm 0 0 150>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ blsp1-spi1-default-state {
+ spi-pins {
+ pins = "gpio0", "gpio1", "gpio3";
+ function = "blsp_spi1";
+ drive-strength = <12>;
+ bias-disable;
+ };
+
+ cs-pins {
+ pins = "gpio2";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ output-high;
+ };
+ };
+
+ blsp1-spi1-sleep-state {
+ pins = "gpio0", "gpio1", "gpio2", "gpio3";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8998-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8998-pinctrl.txt
deleted file mode 100644
index c4de930f2406..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/qcom,msm8998-pinctrl.txt
+++ /dev/null
@@ -1,202 +0,0 @@
-Qualcomm MSM8998 TLMM block
-
-This binding describes the Top Level Mode Multiplexer block found in the
-MSM8998 platform.
-
-- compatible:
- Usage: required
- Value type: <string>
- Definition: must be "qcom,msm8998-pinctrl"
-
-- reg:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: the base address and size of the TLMM register space.
-
-- interrupts:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: should specify the TLMM summary IRQ.
-
-- interrupt-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as an interrupt controller
-
-- #interrupt-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/interrupt-controller/irq.h>
-
-- gpio-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as a gpio controller
-
-- #gpio-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/gpio/gpio.h>
-
-- gpio-ranges:
- Usage: required
- Definition: see ../gpio/gpio.txt
-
-- gpio-reserved-ranges:
- Usage: optional
- Definition: see ../gpio/gpio.txt
-
-Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
-a general description of GPIO and interrupt bindings.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-The pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, drive strength, etc.
-
-
-PIN CONFIGURATION NODES:
-
-The name of each subnode is not important; all subnodes should be enumerated
-and processed purely based on their content.
-
-Each subnode only affects those parameters that are explicitly listed. In
-other words, a subnode that lists a mux function but no pin configuration
-parameters implies no information about any pin configuration parameters.
-Similarly, a pin subnode that describes a pullup parameter implies no
-information about e.g. the mux function.
-
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pin configuration subnode:
-
-- pins:
- Usage: required
- Value type: <string-array>
- Definition: List of gpio pins affected by the properties specified in
- this subnode.
-
- Valid pins are:
- gpio0-gpio149
- Supports mux, bias and drive-strength
-
- sdc2_clk, sdc2_cmd, sdc2_data
- Supports bias and drive-strength
-
- ufs_reset
- Supports bias and drive-strength
-
-- function:
- Usage: required
- Value type: <string>
- Definition: Specify the alternative function to be configured for the
- specified pins. Functions are only valid for gpio pins.
- Valid values are:
-
- gpio, adsp_ext, agera_pll, atest_char, atest_gpsadc0,
- atest_gpsadc1, atest_tsens, atest_tsens2, atest_usb1,
- atest_usb10, atest_usb11, atest_usb12, atest_usb13,
- audio_ref, bimc_dte0, bimc_dte1, blsp10_spi, blsp10_spi_a,
- blsp10_spi_b, blsp11_i2c, blsp1_spi, blsp1_spi_a,
- blsp1_spi_b, blsp2_spi, blsp9_spi, blsp_i2c1, blsp_i2c2,
- blsp_i2c3, blsp_i2c4, blsp_i2c5, blsp_i2c6, blsp_i2c7,
- blsp_i2c8, blsp_i2c9, blsp_i2c10, blsp_i2c11, blsp_i2c12,
- blsp_spi1, blsp_spi2, blsp_spi3, blsp_spi4, blsp_spi5,
- blsp_spi6, blsp_spi7, blsp_spi8, blsp_spi9, blsp_spi10,
- blsp_spi11, blsp_spi12, blsp_uart1_a, blsp_uart1_b,
- blsp_uart2_a, blsp_uart2_b, blsp_uart3_a, blsp_uart3_b,
- blsp_uart7_a, blsp_uart7_b, blsp_uart8, blsp_uart8_a,
- blsp_uart8_b, blsp_uart9_a, blsp_uart9_b, blsp_uim1_a,
- blsp_uim1_b, blsp_uim2_a, blsp_uim2_b, blsp_uim3_a,
- blsp_uim3_b, blsp_uim7_a, blsp_uim7_b, blsp_uim8_a,
- blsp_uim8_b, blsp_uim9_a, blsp_uim9_b, bt_reset,
- btfm_slimbus, cam_mclk, cci_async, cci_i2c, cci_timer0,
- cci_timer1, cci_timer2, cci_timer3, cci_timer4, cri_trng,
- cri_trng0, cri_trng1, dbg_out, ddr_bist, edp_hot, edp_lcd,
- gcc_gp1_a, gcc_gp1_b, gcc_gp2_a, gcc_gp2_b, gcc_gp3_a,
- gcc_gp3_b, hdmi_cec, hdmi_ddc, hdmi_hot, hdmi_rcv,
- isense_dbg, jitter_bist, ldo_en, ldo_update, lpass_slimbus,
- m_voc, mdp_vsync, mdp_vsync0, mdp_vsync1, mdp_vsync2,
- mdp_vsync3, mdp_vsync_a, mdp_vsync_b, modem_tsync, mss_lte,
- nav_dr, nav_pps, pa_indicator, pci_e0, phase_flag,
- pll_bypassnl, pll_reset, pri_mi2s, pri_mi2s_ws, prng_rosc,
- pwr_crypto, pwr_modem, pwr_nav, qdss_cti0_a, qdss_cti0_b,
- qdss_cti1_a, qdss_cti1_b, qdss, qlink_enable,
- qlink_request, qua_mi2s, sd_card, sd_write, sdc40, sdc41,
- sdc42, sdc43, sdc4_clk, sdc4_cmd, sec_mi2s, sp_cmu,
- spkr_i2s, ssbi1, ssc_irq, ter_mi2s, tgu_ch0, tgu_ch1,
- tsense_pwm1, tsense_pwm2, tsif0, tsif1,
- uim1_clk, uim1_data, uim1_present,
- uim1_reset, uim2_clk, uim2_data, uim2_present, uim2_reset,
- uim_batt, usb_phy, vfr_1, vsense_clkout, vsense_data0,
- vsense_data1, vsense_mode, wlan1_adc0, wlan1_adc1,
- wlan2_adc0, wlan2_adc1,
-
-- bias-disable:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as no pull.
-
-- bias-pull-down:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull down.
-
-- bias-pull-up:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull up.
-
-- output-high:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- high.
- Not valid for sdc pins.
-
-- output-low:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- low.
- Not valid for sdc pins.
-
-- drive-strength:
- Usage: optional
- Value type: <u32>
- Definition: Selects the drive strength for the specified pins, in mA.
- Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
-
-Example:
-
- tlmm: pinctrl@03400000 {
- compatible = "qcom,msm8998-pinctrl";
- reg = <0x03400000 0xc00000>;
- interrupts = <0 208 0>;
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&tlmm 0 0 175>;
- gpio-reserved-ranges = <0 4>, <81 4>;
- interrupt-controller;
- #interrupt-cells = <2>;
-
- uart_console_active: uart_console_active {
- mux {
- pins = "gpio4", "gpio5";
- function = "blsp_uart8_a";
- };
-
- config {
- pins = "gpio4", "gpio5";
- drive-strength = <2>;
- bias-disable;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8998-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,msm8998-pinctrl.yaml
new file mode 100644
index 000000000000..21ba32cc204a
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8998-pinctrl.yaml
@@ -0,0 +1,171 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,msm8998-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm MSM8998 TLMM pin controller
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm MSM8998 SoC.
+
+properties:
+ compatible:
+ const: qcom,msm8998-pinctrl
+
+ reg:
+ maxItems: 1
+
+ interrupts: true
+ interrupt-controller: true
+ "#interrupt-cells": true
+ gpio-controller: true
+ "#gpio-cells": true
+ gpio-ranges: true
+ wakeup-parent: true
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 75
+
+ gpio-line-names:
+ maxItems: 150
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-msm8998-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-msm8998-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-msm8998-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ oneOf:
+ - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-4][0-9])$"
+ - enum: [ sdc2_clk, sdc2_cmd, sdc2_data, ufs_reset ]
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ gpio, adsp_ext, agera_pll, atest_char, atest_gpsadc0,
+ atest_gpsadc1, atest_tsens, atest_tsens2, atest_usb1,
+ atest_usb10, atest_usb11, atest_usb12, atest_usb13, audio_ref,
+ bimc_dte0, bimc_dte1, blsp10_spi, blsp10_spi_a, blsp10_spi_b,
+ blsp11_i2c, blsp1_spi, blsp1_spi_a, blsp1_spi_b, blsp2_spi,
+ blsp9_spi, blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c4,
+ blsp_i2c5, blsp_i2c6, blsp_i2c7, blsp_i2c8, blsp_i2c9,
+ blsp_i2c10, blsp_i2c11, blsp_i2c12, blsp_spi1, blsp_spi2,
+ blsp_spi3, blsp_spi4, blsp_spi5, blsp_spi6, blsp_spi7,
+ blsp_spi8, blsp_spi9, blsp_spi10, blsp_spi11, blsp_spi12,
+ blsp_uart1_a, blsp_uart1_b, blsp_uart2_a, blsp_uart2_b,
+ blsp_uart3_a, blsp_uart3_b, blsp_uart7_a, blsp_uart7_b,
+ blsp_uart8, blsp_uart8_a, blsp_uart8_b, blsp_uart9_a,
+ blsp_uart9_b, blsp_uim1_a, blsp_uim1_b, blsp_uim2_a,
+ blsp_uim2_b, blsp_uim3_a, blsp_uim3_b, blsp_uim7_a,
+ blsp_uim7_b, blsp_uim8_a, blsp_uim8_b, blsp_uim9_a,
+ blsp_uim9_b, bt_reset, btfm_slimbus, cam_mclk, cci_async,
+ cci_i2c, cci_timer0, cci_timer1, cci_timer2, cci_timer3,
+ cci_timer4, cri_trng, cri_trng0, cri_trng1, dbg_out, ddr_bist,
+ edp_hot, edp_lcd, gcc_gp1_a, gcc_gp1_b, gcc_gp2_a, gcc_gp2_b,
+ gcc_gp3_a, gcc_gp3_b, hdmi_cec, hdmi_ddc, hdmi_hot, hdmi_rcv,
+ isense_dbg, jitter_bist, ldo_en, ldo_update, lpass_slimbus,
+ m_voc, mdp_vsync, mdp_vsync0, mdp_vsync1, mdp_vsync2,
+ mdp_vsync3, mdp_vsync_a, mdp_vsync_b, modem_tsync, mss_lte,
+ nav_dr, nav_pps, pa_indicator, pci_e0, phase_flag,
+ pll_bypassnl, pll_reset, pri_mi2s, pri_mi2s_ws, prng_rosc,
+ pwr_crypto, pwr_modem, pwr_nav, qdss_cti0_a, qdss_cti0_b,
+ qdss_cti1_a, qdss_cti1_b, qdss, qlink_enable, qlink_request,
+ qua_mi2s, sd_card, sd_write, sdc40, sdc41, sdc42, sdc43,
+ sdc4_clk, sdc4_cmd, sec_mi2s, sp_cmu, spkr_i2s, ssbi1, ssc_irq,
+ ter_mi2s, tgu_ch0, tgu_ch1, tsense_pwm1, tsense_pwm2, tsif0,
+ tsif1, uim1_clk, uim1_data, uim1_present, uim1_reset, uim2_clk,
+ uim2_data, uim2_present, uim2_reset, uim_batt, usb_phy, vfr_1,
+ vsense_clkout, vsense_data0, vsense_data1, vsense_mode,
+ wlan1_adc0, wlan1_adc1, wlan2_adc0, wlan2_adc1 ]
+
+ bias-pull-down: true
+ bias-pull-up: true
+ bias-disable: true
+ drive-strength: true
+ input-enable: true
+ output-high: true
+ output-low: true
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ tlmm: pinctrl@3400000 {
+ compatible = "qcom,msm8998-pinctrl";
+ reg = <0x03400000 0xc00000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-ranges = <&tlmm 0 0 150>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-reserved-ranges = <0 4>, <81 4>;
+
+ sdc2-off-state {
+ clk-pins {
+ pins = "sdc2_clk";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ cmd-pins {
+ pins = "sdc2_cmd";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ data-pins {
+ pins = "sdc2_data";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ sdc2-cd-state {
+ pins = "gpio95";
+ function = "gpio";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-mpp.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-mpp.yaml
index df79274d0ec3..72cce38bc1ce 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,pmic-mpp.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,pmic-mpp.yaml
@@ -15,28 +15,29 @@ description:
properties:
compatible:
- items:
- - enum:
- - qcom,pm8018-mpp
- - qcom,pm8019-mpp
- - qcom,pm8038-mpp
- - qcom,pm8058-mpp
- - qcom,pm8226-mpp
- - qcom,pm8821-mpp
- - qcom,pm8841-mpp
- - qcom,pm8916-mpp
- - qcom,pm8917-mpp
- - qcom,pm8921-mpp
- - qcom,pm8941-mpp
- - qcom,pm8950-mpp
- - qcom,pmi8950-mpp
- - qcom,pm8994-mpp
- - qcom,pma8084-mpp
- - qcom,pmi8994-mpp
-
- - enum:
- - qcom,spmi-mpp
- - qcom,ssbi-mpp
+ oneOf:
+ - items:
+ - enum:
+ - qcom,pm8019-mpp
+ - qcom,pm8226-mpp
+ - qcom,pm8841-mpp
+ - qcom,pm8916-mpp
+ - qcom,pm8941-mpp
+ - qcom,pm8950-mpp
+ - qcom,pmi8950-mpp
+ - qcom,pm8994-mpp
+ - qcom,pma8084-mpp
+ - qcom,pmi8994-mpp
+ - const: qcom,spmi-mpp
+ - items:
+ - enum:
+ - qcom,pm8018-mpp
+ - qcom,pm8038-mpp
+ - qcom,pm8058-mpp
+ - qcom,pm8821-mpp
+ - qcom,pm8917-mpp
+ - qcom,pm8921-mpp
+ - const: qcom,ssbi-mpp
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,qcm2290-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,qcm2290-tlmm.yaml
index 3f4f1c0360b5..adf64bfaa4ed 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,qcm2290-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,qcm2290-tlmm.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/pinctrl/qcom,qcm2290-pinctrl.yaml#
+$id: http://devicetree.org/schemas/pinctrl/qcom,qcm2290-tlmm.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies, Inc. QCM2290 TLMM block
@@ -10,8 +10,7 @@ maintainers:
- Shawn Guo <shawn.guo@linaro.org>
description:
- This binding describes the Top Level Mode Multiplexer block found in the
- QCM2290 platform.
+ Top Level Mode Multiplexer pin controller in Qualcomm QCM2290 SoC.
properties:
compatible:
@@ -20,46 +19,30 @@ properties:
reg:
maxItems: 1
- interrupts:
- description: Specifies the TLMM summary IRQ
- maxItems: 1
-
+ interrupts: true
interrupt-controller: true
-
- '#interrupt-cells':
- description:
- Specifies the PIN numbers and Flags, as defined in defined in
- include/dt-bindings/interrupt-controller/irq.h
- const: 2
-
+ "#interrupt-cells": true
gpio-controller: true
-
- '#gpio-cells':
- description: Specifying the pin number and flags, as defined in
- include/dt-bindings/gpio/gpio.h
- const: 2
-
- gpio-ranges:
- maxItems: 1
-
+ "#gpio-cells": true
+ gpio-ranges: true
wakeup-parent: true
-#PIN CONFIGURATION NODES
patternProperties:
- '-state$':
+ "-state$":
oneOf:
- $ref: "#/$defs/qcom-qcm2290-tlmm-state"
- patternProperties:
- ".*":
+ "-pins$":
$ref: "#/$defs/qcom-qcm2290-tlmm-state"
+ additionalProperties: false
-'$defs':
+$defs:
qcom-qcm2290-tlmm-state:
type: object
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
Client device subnodes use below standard properties.
- $ref: "qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state"
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
properties:
pins:
@@ -96,20 +79,11 @@ patternProperties:
uim2_data, uim2_present, uim2_reset, usb_phy, vfr_1,
vsense_trigger, wlan1_adc0, wlan1_adc1 ]
- drive-strength:
- enum: [2, 4, 6, 8, 10, 12, 14, 16]
- default: 2
- description:
- Selects the drive strength for the specified pins, in mA.
-
bias-pull-down: true
-
bias-pull-up: true
-
bias-disable: true
-
+ drive-strength: true
output-high: true
-
output-low: true
required:
@@ -118,17 +92,11 @@ patternProperties:
additionalProperties: false
allOf:
- - $ref: "pinctrl.yaml#"
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
required:
- compatible
- reg
- - interrupts
- - interrupt-controller
- - '#interrupt-cells'
- - gpio-controller
- - '#gpio-cells'
- - gpio-ranges
additionalProperties: false
@@ -146,19 +114,19 @@ examples:
gpio-ranges = <&tlmm 0 0 127>;
sdc2_on_state: sdc2-on-state {
- clk {
+ clk-pins {
pins = "sdc2_clk";
bias-disable;
drive-strength = <16>;
};
- cmd {
+ cmd-pins {
pins = "sdc2_cmd";
bias-pull-up;
drive-strength = <10>;
};
- data {
+ data-pins {
pins = "sdc2_data";
bias-pull-up;
drive-strength = <10>;
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,qcs404-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,qcs404-pinctrl.txt
deleted file mode 100644
index a50e74684195..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/qcom,qcs404-pinctrl.txt
+++ /dev/null
@@ -1,199 +0,0 @@
-Qualcomm QCS404 TLMM block
-
-This binding describes the Top Level Mode Multiplexer block found in the
-QCS404 platform.
-
-- compatible:
- Usage: required
- Value type: <string>
- Definition: must be "qcom,qcs404-pinctrl"
-
-- reg:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: the base address and size of the north, south and east TLMM
- tiles.
-
-- reg-names:
- Usage: required
- Value type: <stringlist>
- Defintiion: names for the cells of reg, must contain "north", "south"
- and "east".
-
-- interrupts:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: should specify the TLMM summary IRQ.
-
-- interrupt-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as an interrupt controller
-
-- #interrupt-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/interrupt-controller/irq.h>
-
-- gpio-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as a gpio controller
-
-- #gpio-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/gpio/gpio.h>
-
-- gpio-ranges:
- Usage: required
- Definition: see ../gpio/gpio.txt
-
-Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
-a general description of GPIO and interrupt bindings.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-The pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, drive strength, etc.
-
-
-PIN CONFIGURATION NODES:
-
-The name of each subnode is not important; all subnodes should be enumerated
-and processed purely based on their content.
-
-Each subnode only affects those parameters that are explicitly listed. In
-other words, a subnode that lists a mux function but no pin configuration
-parameters implies no information about any pin configuration parameters.
-Similarly, a pin subnode that describes a pullup parameter implies no
-information about e.g. the mux function.
-
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pin configuration subnode:
-
-- pins:
- Usage: required
- Value type: <string-array>
- Definition: List of gpio pins affected by the properties specified in
- this subnode.
-
- Valid pins are:
- gpio0-gpio119
- Supports mux, bias and drive-strength
-
- sdc1_clk, sdc1_cmd, sdc1_data, sdc2_clk, sdc2_cmd,
- sdc2_data
- Supports bias and drive-strength
-
- ufs_reset
- Supports bias and drive-strength
-
-- function:
- Usage: required
- Value type: <string>
- Definition: Specify the alternative function to be configured for the
- specified pins. Functions are only valid for gpio pins.
- Valid values are:
-
- gpio, hdmi_tx, hdmi_ddc, blsp_uart_tx_a2, blsp_spi2, m_voc,
- qdss_cti_trig_in_a0, blsp_uart_rx_a2, qdss_tracectl_a,
- blsp_uart2, aud_cdc, blsp_i2c_sda_a2, qdss_tracedata_a,
- blsp_i2c_scl_a2, qdss_tracectl_b, qdss_cti_trig_in_b0,
- blsp_uart1, blsp_spi_mosi_a1, blsp_spi_miso_a1,
- qdss_tracedata_b, blsp_i2c1, blsp_spi_cs_n_a1, gcc_plltest,
- blsp_spi_clk_a1, rgb_data0, blsp_uart5, blsp_spi5,
- adsp_ext, rgb_data1, prng_rosc, rgb_data2, blsp_i2c5,
- gcc_gp1_clk_b, rgb_data3, gcc_gp2_clk_b, blsp_spi0,
- blsp_uart0, gcc_gp3_clk_b, blsp_i2c0, qdss_traceclk_b,
- pcie_clk, nfc_irq, blsp_spi4, nfc_dwl, audio_ts, rgb_data4,
- spi_lcd, blsp_uart_tx_b2, gcc_gp3_clk_a, rgb_data5,
- blsp_uart_rx_b2, blsp_i2c_sda_b2, blsp_i2c_scl_b2,
- pwm_led11, i2s_3_data0_a, ebi2_lcd, i2s_3_data1_a,
- i2s_3_data2_a, atest_char, pwm_led3, i2s_3_data3_a,
- pwm_led4, i2s_4, ebi2_a, dsd_clk_b, pwm_led5, pwm_led6,
- pwm_led7, pwm_led8, pwm_led24, spkr_dac0, blsp_i2c4,
- pwm_led9, pwm_led10, spdifrx_opt, pwm_led12, pwm_led13,
- pwm_led14, wlan1_adc1, rgb_data_b0, pwm_led15,
- blsp_spi_mosi_b1, wlan1_adc0, rgb_data_b1, pwm_led16,
- blsp_spi_miso_b1, qdss_cti_trig_out_b0, wlan2_adc1,
- rgb_data_b2, pwm_led17, blsp_spi_cs_n_b1, wlan2_adc0,
- rgb_data_b3, pwm_led18, blsp_spi_clk_b1, rgb_data_b4,
- pwm_led19, ext_mclk1_b, qdss_traceclk_a, rgb_data_b5,
- pwm_led20, atest_char3, i2s_3_sck_b, ldo_update, bimc_dte0,
- rgb_hsync, pwm_led21, i2s_3_ws_b, dbg_out, rgb_vsync,
- i2s_3_data0_b, ldo_en, hdmi_dtest, rgb_de, i2s_3_data1_b,
- hdmi_lbk9, rgb_clk, atest_char1, i2s_3_data2_b, ebi_cdc,
- hdmi_lbk8, rgb_mdp, atest_char0, i2s_3_data3_b, hdmi_lbk7,
- rgb_data_b6, rgb_data_b7, hdmi_lbk6, rgmii_int, cri_trng1,
- rgmii_wol, cri_trng0, gcc_tlmm, rgmii_ck, rgmii_tx,
- hdmi_lbk5, hdmi_pixel, hdmi_rcv, hdmi_lbk4, rgmii_ctl,
- ext_lpass, rgmii_rx, cri_trng, hdmi_lbk3, hdmi_lbk2,
- qdss_cti_trig_out_b1, rgmii_mdio, hdmi_lbk1, rgmii_mdc,
- hdmi_lbk0, ir_in, wsa_en, rgb_data6, rgb_data7,
- atest_char2, ebi_ch0, blsp_uart3, blsp_spi3, sd_write,
- blsp_i2c3, gcc_gp1_clk_a, qdss_cti_trig_in_b1,
- gcc_gp2_clk_a, ext_mclk0, mclk_in1, i2s_1, dsd_clk_a,
- qdss_cti_trig_in_a1, rgmi_dll1, pwm_led22, pwm_led23,
- qdss_cti_trig_out_a0, rgmi_dll2, pwm_led1,
- qdss_cti_trig_out_a1, pwm_led2, i2s_2, pll_bist,
- ext_mclk1_a, mclk_in2, bimc_dte1, i2s_3_sck_a, i2s_3_ws_a
-
-- bias-disable:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as no pull.
-
-- bias-pull-down:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull down.
-
-- bias-pull-up:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull up.
-
-- output-high:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- high.
- Not valid for sdc pins.
-
-- output-low:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- low.
- Not valid for sdc pins.
-
-- drive-strength:
- Usage: optional
- Value type: <u32>
- Definition: Selects the drive strength for the specified pins, in mA.
- Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
-
-Example:
-
- tlmm: pinctrl@1000000 {
- compatible = "qcom,qcs404-pinctrl";
- reg = <0x01000000 0x200000>,
- <0x01300000 0x200000>,
- <0x07b00000 0x200000>;
- reg-names = "south", "north", "east";
- interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&tlmm 0 0 120>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,qcs404-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,qcs404-pinctrl.yaml
new file mode 100644
index 000000000000..29d50c4a0034
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,qcs404-pinctrl.yaml
@@ -0,0 +1,176 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,qcs404-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm QCS404 TLMM pin controller
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm QCS404 SoC.
+
+properties:
+ compatible:
+ const: qcom,qcs404-pinctrl
+
+ reg:
+ maxItems: 3
+
+ reg-names:
+ items:
+ - const: south
+ - const: north
+ - const: east
+
+ interrupts: true
+ interrupt-controller: true
+ "#interrupt-cells": true
+ gpio-controller: true
+ "#gpio-cells": true
+ gpio-ranges: true
+ wakeup-parent: true
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 60
+
+ gpio-line-names:
+ maxItems: 120
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-qcs404-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-qcs404-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-qcs404-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ oneOf:
+ - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-1][0-9])$"
+ - enum: [ sdc1_clk, sdc1_cmd, sdc1_data, sdc1_rclk, sdc2_clk,
+ sdc2_cmd, sdc2_data, ufs_reset ]
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ gpio, adsp_ext, atest_char, atest_char0, atest_char1,
+ atest_char2, atest_char3, aud_cdc, audio_ts, bimc_dte0,
+ bimc_dte1, blsp_i2c0, blsp_i2c1, blsp_i2c3, blsp_i2c4,
+ blsp_i2c5, blsp_i2c_scl_a2, blsp_i2c_scl_b2, blsp_i2c_sda_a2,
+ blsp_i2c_sda_b2, blsp_spi0, blsp_spi2, blsp_spi3, blsp_spi4,
+ blsp_spi5, blsp_spi_clk_a1, blsp_spi_clk_b1, blsp_spi_cs_n_a1,
+ blsp_spi_cs_n_b1, blsp_spi_miso_a1, blsp_spi_miso_b1,
+ blsp_spi_mosi_a1, blsp_spi_mosi_b1, blsp_uart0, blsp_uart1,
+ blsp_uart2, blsp_uart3, blsp_uart5, blsp_uart_rx_a2,
+ blsp_uart_rx_b2, blsp_uart_tx_a2, blsp_uart_tx_b2, cri_trng,
+ cri_trng0, cri_trng1, dbg_out, dsd_clk_a, dsd_clk_b, ebi2_a,
+ ebi2_lcd, ebi_cdc, ebi_ch0, ext_lpass, ext_mclk0, ext_mclk1_a,
+ ext_mclk1_b, gcc_gp1_clk_a, gcc_gp1_clk_b, gcc_gp2_clk_a,
+ gcc_gp2_clk_b, gcc_gp3_clk_a, gcc_gp3_clk_b, gcc_plltest,
+ gcc_tlmm, hdmi_ddc, hdmi_dtest, hdmi_lbk0, hdmi_lbk1,
+ hdmi_lbk2, hdmi_lbk3, hdmi_lbk4, hdmi_lbk5, hdmi_lbk6,
+ hdmi_lbk7, hdmi_lbk8, hdmi_lbk9, hdmi_pixel, hdmi_rcv, hdmi_tx,
+ i2s_1, i2s_2, i2s_3_data0_a, i2s_3_data0_b, i2s_3_data1_a,
+ i2s_3_data1_b, i2s_3_data2_a, i2s_3_data2_b, i2s_3_data3_a,
+ i2s_3_data3_b, i2s_3_sck_a, i2s_3_sck_b, i2s_3_ws_a,
+ i2s_3_ws_b, i2s_4, ir_in, ldo_en, ldo_update, mclk_in1,
+ mclk_in2, m_voc, nfc_dwl, nfc_irq, pcie_clk, pll_bist,
+ prng_rosc, pwm_led1, pwm_led10, pwm_led11, pwm_led12,
+ pwm_led13, pwm_led14, pwm_led15, pwm_led16, pwm_led17,
+ pwm_led18, pwm_led19, pwm_led2, pwm_led20, pwm_led21,
+ pwm_led22, pwm_led23, pwm_led24, pwm_led3, pwm_led4, pwm_led5,
+ pwm_led6, pwm_led7, pwm_led8, pwm_led9, qdss_cti_trig_in_a0,
+ qdss_cti_trig_in_a1, qdss_cti_trig_in_b0, qdss_cti_trig_in_b1,
+ qdss_cti_trig_out_a0, qdss_cti_trig_out_a1,
+ qdss_cti_trig_out_b0, qdss_cti_trig_out_b1, qdss_traceclk_a,
+ qdss_traceclk_b, qdss_tracectl_a, qdss_tracectl_b,
+ qdss_tracedata_a, qdss_tracedata_b, rgb_clk, rgb_data0,
+ rgb_data1, rgb_data2, rgb_data3, rgb_data4, rgb_data5,
+ rgb_data6, rgb_data7, rgb_data_b0, rgb_data_b1, rgb_data_b2,
+ rgb_data_b3, rgb_data_b4, rgb_data_b5, rgb_data_b6,
+ rgb_data_b7, rgb_de, rgb_hsync, rgb_mdp, rgb_vsync, rgmi_dll1,
+ rgmi_dll2, rgmii_ck, rgmii_ctl, rgmii_int, rgmii_mdc,
+ rgmii_mdio, rgmii_rx, rgmii_tx, rgmii_wol, sd_write,
+ spdifrx_opt, spi_lcd, spkr_dac0, wlan1_adc0, wlan1_adc1,
+ wlan2_adc0, wlan2_adc1, wsa_en ]
+
+ bias-pull-down: true
+ bias-pull-up: true
+ bias-disable: true
+ drive-strength: true
+ input-enable: true
+ output-high: true
+ output-low: true
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ tlmm: pinctrl@1000000 {
+ compatible = "qcom,qcs404-pinctrl";
+ reg = <0x01000000 0x200000>,
+ <0x01300000 0x200000>,
+ <0x07b00000 0x200000>;
+ reg-names = "south", "north", "east";
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-ranges = <&tlmm 0 0 120>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+
+ blsp1-i2c1-default-state {
+ pins = "gpio24", "gpio25";
+ function = "blsp_i2c1";
+ };
+
+ blsp1-i2c2-default-state {
+ sda-pins {
+ pins = "gpio19";
+ function = "blsp_i2c_sda_a2";
+ };
+
+ scl-pins {
+ pins = "gpio20";
+ function = "blsp_i2c_scl_a2";
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sc7180-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,sc7180-pinctrl.txt
deleted file mode 100644
index 6ffeac9801df..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sc7180-pinctrl.txt
+++ /dev/null
@@ -1,187 +0,0 @@
-Qualcomm Technologies, Inc. SC7180 TLMM block
-
-This binding describes the Top Level Mode Multiplexer block found in the
-SC7180 platform.
-
-- compatible:
- Usage: required
- Value type: <string>
- Definition: must be "qcom,sc7180-pinctrl"
-
-- reg:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: the base address and size of the north, south and west
- TLMM tiles
-
-- reg-names:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: names for the cells of reg, must contain "north", "south"
- and "west".
-
-- interrupts:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: should specify the TLMM summary IRQ.
-
-- interrupt-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as an interrupt controller
-
-- #interrupt-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/interrupt-controller/irq.h>
-
-- gpio-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as a gpio controller
-
-- #gpio-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/gpio/gpio.h>
-
-- gpio-ranges:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: see ../gpio/gpio.txt
-
-- gpio-reserved-ranges:
- Usage: optional
- Value type: <prop-encoded-array>
- Definition: see ../gpio/gpio.txt
-
-Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
-a general description of GPIO and interrupt bindings.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-The pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, drive strength, etc.
-
-
-PIN CONFIGURATION NODES:
-
-The name of each subnode is not important; all subnodes should be enumerated
-and processed purely based on their content.
-
-Each subnode only affects those parameters that are explicitly listed. In
-other words, a subnode that lists a mux function but no pin configuration
-parameters implies no information about any pin configuration parameters.
-Similarly, a pin subnode that describes a pullup parameter implies no
-information about e.g. the mux function.
-
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pin configuration subnode:
-
-- pins:
- Usage: required
- Value type: <string-array>
- Definition: List of gpio pins affected by the properties specified in
- this subnode.
-
- Valid pins are:
- gpio0-gpio118
- Supports mux, bias and drive-strength
-
- sdc1_clk, sdc1_cmd, sdc1_data sdc2_clk, sdc2_cmd,
- sdc2_data sdc1_rclk
- Supports bias and drive-strength
-
- ufs_reset
- Supports bias and drive-strength
-
-- function:
- Usage: required
- Value type: <string>
- Definition: Specify the alternative function to be configured for the
- specified pins. Functions are only valid for gpio pins.
- Valid values are:
-
- adsp_ext, agera_pll, aoss_cti, atest_char, atest_char0,
- atest_char1, atest_char2, atest_char3, atest_tsens,
- atest_tsens2, atest_usb1, atest_usb10, atest_usb11,
- atest_usb12, atest_usb13, atest_usb2, atest_usb20,
- atest_usb21, atest_usb22, atest_usb23, audio_ref,
- btfm_slimbus, cam_mclk, cci_async, cci_i2c, cci_timer0,
- cci_timer1, cci_timer2, cci_timer3, cci_timer4,
- cri_trng, dbg_out, ddr_bist, ddr_pxi0, ddr_pxi1,
- ddr_pxi2, ddr_pxi3, dp_hot, edp_lcd, gcc_gp1, gcc_gp2,
- gcc_gp3, gpio, gp_pdm0, gp_pdm1, gp_pdm2, gps_tx,
- jitter_bist, ldo_en, ldo_update, lpass_ext, mdp_vsync,
- mdp_vsync0, mdp_vsync1, mdp_vsync2, mdp_vsync3, mi2s_0,
- mi2s_1, mi2s_2, mss_lte, m_voc, pa_indicator, phase_flag,
- PLL_BIST, pll_bypassnl, pll_reset, prng_rosc, qdss,
- qdss_cti, qlink_enable, qlink_request, qspi_clk, qspi_cs,
- qspi_data, qup00, qup01, qup02_i2c, qup02_uart, qup03,
- qup04_i2c, qup04_uart, qup05, qup10, qup11_i2c, qup11_uart,
- qup12, qup13_i2c, qup13_uart, qup14, qup15, sdc1_tb,
- sdc2_tb, sd_write, sp_cmu, tgu_ch0, tgu_ch1, tgu_ch2,
- tgu_ch3, tsense_pwm1, tsense_pwm2, uim1, uim2, uim_batt,
- usb_phy, vfr_1, _V_GPIO, _V_PPS_IN, _V_PPS_OUT,
- vsense_trigger, wlan1_adc0, wlan1_adc1, wlan2_adc0,
- wlan2_adc1,
-
-- bias-disable:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as no pull.
-
-- bias-pull-down:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull down.
-
-- bias-pull-up:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull up.
-
-- output-high:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- high.
- Not valid for sdc pins.
-
-- output-low:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- low.
- Not valid for sdc pins.
-
-- drive-strength:
- Usage: optional
- Value type: <u32>
- Definition: Selects the drive strength for the specified pins, in mA.
- Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
-
-Example:
-
- tlmm: pinctrl@3500000 {
- compatible = "qcom,sc7180-pinctrl";
- reg = <0x3500000 0x300000>,
- <0x3900000 0x300000>,
- <0x3D00000 0x300000>;
- reg-names = "west", "north", "south";
- interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&tlmm 0 0 119>;
- gpio-reserved-ranges = <0 4>, <106 4>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sc7180-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sc7180-pinctrl.yaml
new file mode 100644
index 000000000000..b40f6dc6adae
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sc7180-pinctrl.yaml
@@ -0,0 +1,158 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,sc7180-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SC7180 TLMM pin controller
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm SC7180 SoC.
+
+properties:
+ compatible:
+ const: qcom,sc7180-pinctrl
+
+ reg:
+ maxItems: 3
+
+ reg-names:
+ items:
+ - const: west
+ - const: north
+ - const: south
+
+ interrupts: true
+ interrupt-controller: true
+ "#interrupt-cells": true
+ gpio-controller: true
+ "#gpio-cells": true
+ gpio-ranges: true
+ wakeup-parent: true
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 60
+
+ gpio-line-names:
+ maxItems: 119
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-sc7180-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-sc7180-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-sc7180-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ oneOf:
+ - pattern: "^gpio([0-9]|[1-9][0-9]|10[0-9]|11[0-8])$"
+ - enum: [ sdc1_rclk, sdc1_clk, sdc1_cmd, sdc1_data, sdc2_clk,
+ sdc2_cmd, sdc2_data, ufs_reset ]
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ adsp_ext, agera_pll, aoss_cti, atest_char, atest_char0,
+ atest_char1, atest_char2, atest_char3, atest_tsens,
+ atest_tsens2, atest_usb1, atest_usb10, atest_usb11,
+ atest_usb12, atest_usb13, atest_usb2, atest_usb20, atest_usb21,
+ atest_usb22, atest_usb23, audio_ref, btfm_slimbus, cam_mclk,
+ cci_async, cci_i2c, cci_timer0, cci_timer1, cci_timer2,
+ cci_timer3, cci_timer4, cri_trng, dbg_out, ddr_bist, ddr_pxi0,
+ ddr_pxi1, ddr_pxi2, ddr_pxi3, dp_hot, edp_lcd, gcc_gp1,
+ gcc_gp2, gcc_gp3, gpio, gp_pdm0, gp_pdm1, gp_pdm2, gps_tx,
+ jitter_bist, ldo_en, ldo_update, lpass_ext, mdp_vsync,
+ mdp_vsync0, mdp_vsync1, mdp_vsync2, mdp_vsync3, mi2s_0, mi2s_1,
+ mi2s_2, mss_lte, m_voc, pa_indicator, phase_flag, PLL_BIST,
+ pll_bypassnl, pll_reset, prng_rosc, qdss, qdss_cti,
+ qlink_enable, qlink_request, qspi_clk, qspi_cs, qspi_data,
+ qup00, qup01, qup02_i2c, qup02_uart, qup03, qup04_i2c,
+ qup04_uart, qup05, qup10, qup11_i2c, qup11_uart, qup12,
+ qup13_i2c, qup13_uart, qup14, qup15, sdc1_tb, sdc2_tb,
+ sd_write, sp_cmu, tgu_ch0, tgu_ch1, tgu_ch2, tgu_ch3,
+ tsense_pwm1, tsense_pwm2, uim1, uim2, uim_batt, usb_phy, vfr_1,
+ _V_GPIO, _V_PPS_IN, _V_PPS_OUT, vsense_trigger, wlan1_adc0,
+ wlan1_adc1, wlan2_adc0, wlan2_adc1 ]
+
+ bias-pull-down: true
+ bias-pull-up: true
+ bias-disable: true
+ drive-strength: true
+ input-enable: true
+ output-high: true
+ output-low: true
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+required:
+ - compatible
+ - reg
+ - reg-names
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ tlmm: pinctrl@3500000 {
+ compatible = "qcom,sc7180-pinctrl";
+ reg = <0x03500000 0x300000>,
+ <0x03900000 0x300000>,
+ <0x03d00000 0x300000>;
+ reg-names = "west", "north", "south";
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&tlmm 0 0 120>;
+ wakeup-parent = <&pdc>;
+
+ dp_hot_plug_det: dp-hot-plug-det-state {
+ pins = "gpio117";
+ function = "dp_hot";
+ };
+
+ qup_spi11_cs_gpio: qup-spi11-cs-gpio-state {
+ spi-pins {
+ pins = "gpio53", "gpio54", "gpio55";
+ function = "qup15";
+ };
+
+ cs-pins {
+ pins = "gpio56";
+ function = "gpio";
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml
index 624e14f00790..f7ec8a4f664f 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml
@@ -4,15 +4,14 @@
$id: http://devicetree.org/schemas/pinctrl/qcom,sc7280-lpass-lpi-pinctrl.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Technologies, Inc. Low Power Audio SubSystem (LPASS)
- Low Power Island (LPI) TLMM block
+title: Qualcomm SC7280 SoC LPASS LPI TLMM
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-description: |
- This binding describes the Top Level Mode Multiplexer block found in the
- LPASS LPI IP on most Qualcomm SoCs
+description:
+ Top Level Mode Multiplexer pin controller in the Low Power Audio SubSystem
+ (LPASS) Low Power Island (LPI) of Qualcomm SC7280 SoC.
properties:
compatible:
@@ -24,12 +23,11 @@ properties:
type: boolean
reg:
- minItems: 2
maxItems: 2
gpio-controller: true
- '#gpio-cells':
+ "#gpio-cells":
description: Specifying the pin number and flags, as defined in
include/dt-bindings/gpio/gpio.h
const: 2
@@ -37,9 +35,17 @@ properties:
gpio-ranges:
maxItems: 1
-#PIN CONFIGURATION NODES
patternProperties:
- '-pins$':
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-sc7280-lpass-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-sc7280-lpass-state"
+ additionalProperties: false
+
+$defs:
+ qcom-sc7280-lpass-state:
type: object
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
@@ -83,13 +89,10 @@ patternProperties:
3: Reserved (No adjustments)
bias-pull-down: true
-
bias-pull-up: true
-
+ bias-bus-hold: true
bias-disable: true
-
output-high: true
-
output-low: true
required:
@@ -102,7 +105,7 @@ required:
- compatible
- reg
- gpio-controller
- - '#gpio-cells'
+ - "#gpio-cells"
- gpio-ranges
additionalProperties: false
@@ -116,4 +119,21 @@ examples:
gpio-controller;
#gpio-cells = <2>;
gpio-ranges = <&lpass_tlmm 0 0 15>;
+
+ dmic01-state {
+ dmic01-clk-pins {
+ pins = "gpio6";
+ function = "dmic1_clk";
+ };
+
+ dmic01-clk-sleep-pins {
+ pins = "gpio6";
+ function = "dmic1_clk";
+ };
+ };
+
+ tx-swr-data-sleep-state {
+ pins = "gpio1", "gpio2", "gpio14";
+ function = "swr_tx_data";
+ };
};
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-pinctrl.yaml
index ad3496784678..36502173cb79 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sc7280-pinctrl.yaml
@@ -9,9 +9,8 @@ title: Qualcomm Technologies, Inc. SC7280 TLMM block
maintainers:
- Bjorn Andersson <andersson@kernel.org>
-description: |
- This binding describes the Top Level Mode Multiplexer block found in the
- SC7280 platform.
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm SC7280 SoC.
properties:
compatible:
@@ -43,17 +42,26 @@ properties:
maxItems: 1
gpio-line-names:
- maxItems: 174
+ maxItems: 175
wakeup-parent: true
-#PIN CONFIGURATION NODES
patternProperties:
- '-pins$':
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-sc7280-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-sc7280-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-sc7280-tlmm-state:
type: object
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
properties:
pins:
@@ -62,7 +70,7 @@ patternProperties:
subnode.
items:
oneOf:
- - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-7][0-9]|18[0-2])$"
+ - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-6][0-9]|17[0-4])$"
- enum: [ sdc1_rclk, sdc1_clk, sdc1_cmd, sdc1_data, sdc2_clk,
sdc2_cmd, sdc2_data, ufs_reset ]
minItems: 1
@@ -102,35 +110,18 @@ patternProperties:
uim1_clk, uim1_data, uim1_present, uim1_reset, usb2phy_ac,
usb_phy, vfr_0, vfr_1, vsense_trigger ]
- drive-strength:
- enum: [2, 4, 6, 8, 10, 12, 14, 16]
- default: 2
- description:
- Selects the drive strength for the specified pins, in mA.
-
bias-pull-down: true
-
bias-pull-up: true
-
+ bias-bus-hold: true
bias-disable: true
-
+ drive-strength: true
+ input-enable: true
output-high: true
-
output-low: true
required:
- pins
- allOf:
- - $ref: /schemas/pinctrl/pincfg-node.yaml
- - if:
- properties:
- pins:
- pattern: "^gpio([0-9]|[1-9][0-9]|1[0-7][0-9]|18[0-2])$"
- then:
- required:
- - function
-
additionalProperties: false
allOf:
@@ -162,7 +153,7 @@ examples:
gpio-ranges = <&tlmm 0 0 175>;
wakeup-parent = <&pdc>;
- qup_uart5_default: qup-uart5-pins {
+ qup_uart5_default: qup-uart5-state {
pins = "gpio46", "gpio47";
function = "qup13";
drive-strength = <2>;
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sc8180x-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sc8180x-tlmm.yaml
index b98eeba2c530..24191d5f64ac 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sc8180x-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sc8180x-tlmm.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/pinctrl/qcom,sc8180x-pinctrl.yaml#
+$id: http://devicetree.org/schemas/pinctrl/qcom,sc8180x-tlmm.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies, Inc. SC8180X TLMM block
@@ -9,12 +9,10 @@ title: Qualcomm Technologies, Inc. SC8180X TLMM block
maintainers:
- Bjorn Andersson <bjorn.andersson@linaro.org>
-description: |
- This binding describes the Top Level Mode Multiplexer block found in the
- SC8180X platform.
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm SC8180X SoC.
allOf:
- - $ref: "pinctrl.yaml#"
- $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
properties:
@@ -26,9 +24,9 @@ properties:
reg-names:
items:
- - const: "west"
- - const: "east"
- - const: "south"
+ - const: west
+ - const: east
+ - const: south
interrupts: true
interrupt-controller: true
@@ -47,7 +45,7 @@ required:
additionalProperties: false
patternProperties:
- '-state$':
+ "-state$":
oneOf:
- $ref: "#/$defs/qcom-sc8180x-tlmm-state"
- patternProperties:
@@ -55,12 +53,13 @@ patternProperties:
$ref: "#/$defs/qcom-sc8180x-tlmm-state"
additionalProperties: false
-'$defs':
+$defs:
qcom-sc8180x-tlmm-state:
type: object
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
properties:
pins:
@@ -112,16 +111,6 @@ patternProperties:
required:
- pins
- allOf:
- - $ref: "qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state"
- - if:
- properties:
- pins:
- pattern: "^gpio([0-9]|[1-9][0-9]|1[0-8][0-9])$"
- then:
- required:
- - function
-
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sc8280xp-lpass-lpi-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sc8280xp-lpass-lpi-pinctrl.yaml
index 1f468303bb08..7d2589387e1a 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sc8280xp-lpass-lpi-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sc8280xp-lpass-lpi-pinctrl.yaml
@@ -4,15 +4,14 @@
$id: http://devicetree.org/schemas/pinctrl/qcom,sc8280xp-lpass-lpi-pinctrl.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Technologies, Inc. Low Power Audio SubSystem (LPASS)
- Low Power Island (LPI) TLMM block
+title: Qualcomm SC8280XP SoC LPASS LPI TLMM
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-description: |
- This binding describes the Top Level Mode Multiplexer block found in the
- LPASS LPI IP on most Qualcomm SoCs
+description:
+ Top Level Mode Multiplexer pin controller in the Low Power Audio SubSystem
+ (LPASS) Low Power Island (LPI) of Qualcomm SC8280XP SoC.
properties:
compatible:
@@ -35,7 +34,7 @@ properties:
gpio-controller: true
- '#gpio-cells':
+ "#gpio-cells":
description: Specifying the pin number and flags, as defined in
include/dt-bindings/gpio/gpio.h
const: 2
@@ -43,9 +42,17 @@ properties:
gpio-ranges:
maxItems: 1
-#PIN CONFIGURATION NODES
patternProperties:
- '-pins$':
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-sc8280xp-lpass-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-sc8280xp-lpass-state"
+ additionalProperties: false
+
+$defs:
+ qcom-sc8280xp-lpass-state:
type: object
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
@@ -58,7 +65,7 @@ patternProperties:
List of gpio pins affected by the properties specified in this
subnode.
items:
- pattern: "^gpio([0-1]|1[0-8]])$"
+ pattern: "^gpio([0-1]|1[0-8])$"
function:
enum: [ swr_tx_clk, swr_tx_data, swr_rx_clk, swr_rx_data,
@@ -112,7 +119,7 @@ required:
- clocks
- clock-names
- gpio-controller
- - '#gpio-cells'
+ - "#gpio-cells"
- gpio-ranges
additionalProperties: false
@@ -130,4 +137,21 @@ examples:
gpio-controller;
#gpio-cells = <2>;
gpio-ranges = <&lpi_tlmm 0 0 18>;
+
+ dmic01-state {
+ dmic01-clk-pins {
+ pins = "gpio16";
+ function = "dmic1_clk";
+ };
+
+ dmic01-clk-sleep-pins {
+ pins = "gpio16";
+ function = "dmic1_clk";
+ };
+ };
+
+ tx-swr-data-sleep-state {
+ pins = "gpio0", "gpio1";
+ function = "swr_tx_data";
+ };
};
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sc8280xp-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sc8280xp-tlmm.yaml
index b9ab130cd558..4efde29c36a2 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sc8280xp-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sc8280xp-tlmm.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/pinctrl/qcom,sc8280xp-pinctrl.yaml#
+$id: http://devicetree.org/schemas/pinctrl/qcom,sc8280xp-tlmm.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies, Inc. SC8280XP TLMM block
@@ -10,8 +10,7 @@ maintainers:
- Bjorn Andersson <bjorn.andersson@linaro.org>
description: |
- This binding describes the Top Level Mode Multiplexer block found in the
- SC8280XP platform.
+ Top Level Mode Multiplexer pin controller in Qualcomm SC8280XP SoC.
allOf:
- $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
@@ -25,10 +24,10 @@ properties:
interrupts: true
interrupt-controller: true
- '#interrupt-cells': true
+ "#interrupt-cells": true
gpio-controller: true
gpio-reserved-ranges: true
- '#gpio-cells': true
+ "#gpio-cells": true
gpio-ranges: true
wakeup-parent: true
@@ -39,7 +38,7 @@ required:
additionalProperties: false
patternProperties:
- '-state$':
+ "-state$":
oneOf:
- $ref: "#/$defs/qcom-sc8280xp-tlmm-state"
- patternProperties:
@@ -47,12 +46,13 @@ patternProperties:
$ref: "#/$defs/qcom-sc8280xp-tlmm-state"
additionalProperties: false
-'$defs':
+$defs:
qcom-sc8280xp-tlmm-state:
type: object
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
properties:
pins:
@@ -113,16 +113,6 @@ patternProperties:
required:
- pins
- allOf:
- - $ref: "qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state"
- - if:
- properties:
- pins:
- pattern: "^gpio([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-1][0-9]|22[0-7])$"
- then:
- required:
- - function
-
additionalProperties: false
examples:
@@ -139,8 +129,8 @@ examples:
gpio-ranges = <&tlmm 0 0 230>;
gpio-wo-subnode-state {
- pins = "gpio1";
- function = "gpio";
+ pins = "gpio1";
+ function = "gpio";
};
uart-w-subnodes-state {
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sdm630-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sdm630-pinctrl.yaml
new file mode 100644
index 000000000000..bd4fd8404aa4
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sdm630-pinctrl.yaml
@@ -0,0 +1,188 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,sdm630-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SDM630 and SDM660 TLMM pin controller
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm SDM630 and SDM660 SoC.
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+properties:
+ compatible:
+ enum:
+ - qcom,sdm630-pinctrl
+ - qcom,sdm660-pinctrl
+
+ reg:
+ maxItems: 3
+
+ reg-names:
+ items:
+ - const: south
+ - const: center
+ - const: north
+
+ interrupts: true
+ interrupt-controller: true
+ "#interrupt-cells": true
+ gpio-controller: true
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 57
+
+ gpio-line-names:
+ maxItems: 114
+
+ "#gpio-cells": true
+ gpio-ranges: true
+ wakeup-parent: true
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-sdm630-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-sdm630-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-sdm630-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ oneOf:
+ - pattern: "^gpio([0-9]|[1-9][0-9]|10[0-9]|11[0-3])$"
+ - enum: [ sdc1_clk, sdc1_cmd, sdc1_data, sdc1_rclk, sdc2_clk,
+ sdc2_cmd, sdc2_data ]
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+ enum: [ adsp_ext, agera_pll, atest_char, atest_char0, atest_char1,
+ atest_char2, atest_char3, atest_gpsadc0, atest_gpsadc1,
+ atest_tsens, atest_tsens2, atest_usb1, atest_usb10,
+ atest_usb11, atest_usb12, atest_usb13, atest_usb2, atest_usb20,
+ atest_usb21, atest_usb22, atest_usb23, audio_ref, bimc_dte0,
+ bimc_dte1, blsp_i2c1, blsp_i2c2, blsp_i2c3, blsp_i2c4,
+ blsp_i2c5, blsp_i2c6, blsp_i2c7, blsp_i2c8_a, blsp_i2c8_b,
+ blsp_spi1, blsp_spi2, blsp_spi3, blsp_spi3_cs1, blsp_spi3_cs2,
+ blsp_spi4, blsp_spi5, blsp_spi6, blsp_spi7, blsp_spi8_a,
+ blsp_spi8_b, blsp_spi8_cs1, blsp_spi8_cs2, blsp_uart1,
+ blsp_uart2, blsp_uart5, blsp_uart6_a, blsp_uart6_b, blsp_uim1,
+ blsp_uim2, blsp_uim5, blsp_uim6, cam_mclk, cci_async, cci_i2c,
+ cri_trng, cri_trng0, cri_trng1, dbg_out, ddr_bist, gcc_gp1,
+ gcc_gp2, gcc_gp3, gpio, gps_tx_a, gps_tx_b, gps_tx_c,
+ isense_dbg, jitter_bist, ldo_en, ldo_update, m_voc, mdp_vsync,
+ mdss_vsync0, mdss_vsync1, mdss_vsync2, mdss_vsync3, mss_lte,
+ nav_pps_a, nav_pps_b, nav_pps_c, pa_indicator, phase_flag0,
+ phase_flag1, phase_flag10, phase_flag11, phase_flag12,
+ phase_flag13, phase_flag14, phase_flag15, phase_flag16,
+ phase_flag17, phase_flag18, phase_flag19, phase_flag2,
+ phase_flag20, phase_flag21, phase_flag22, phase_flag23,
+ phase_flag24, phase_flag25, phase_flag26, phase_flag27,
+ phase_flag28, phase_flag29, phase_flag3, phase_flag30,
+ phase_flag31, phase_flag4, phase_flag5, phase_flag6,
+ phase_flag7, phase_flag8, phase_flag9, pll_bypassnl, pll_reset,
+ pri_mi2s, pri_mi2s_ws, prng_rosc, pwr_crypto, pwr_modem,
+ pwr_nav, qdss_cti0_a, qdss_cti0_b, qdss_cti1_a, qdss_cti1_b,
+ qdss_gpio, qdss_gpio0, qdss_gpio1, qdss_gpio10, qdss_gpio11,
+ qdss_gpio12, qdss_gpio13, qdss_gpio14, qdss_gpio15, qdss_gpio2,
+ qdss_gpio3, qdss_gpio4, qdss_gpio5, qdss_gpio6, qdss_gpio7,
+ qdss_gpio8, qdss_gpio9, qlink_enable, qlink_request, qspi_clk,
+ qspi_cs, qspi_data0, qspi_data1, qspi_data2, qspi_data3,
+ qspi_resetn, sec_mi2s, sndwire_clk, sndwire_data, sp_cmu,
+ ssc_irq, tgu_ch0, tgu_ch1, tsense_pwm1, tsense_pwm2, uim1_clk,
+ uim1_data, uim1_present, uim1_reset, uim2_clk, uim2_data,
+ uim2_present, uim2_reset, uim_batt, vfr_1, vsense_clkout,
+ vsense_data0, vsense_data1, vsense_mode, wlan1_adc0,
+ wlan1_adc1, wlan2_adc0, wlan2_adc1 ]
+
+ bias-disable: true
+ bias-pull-down: true
+ bias-pull-up: true
+ drive-strength: true
+ input-enable: true
+ output-high: true
+ output-low: true
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ tlmm: pinctrl@3100000 {
+ compatible = "qcom,sdm630-pinctrl";
+ reg = <0x03100000 0x400000>,
+ <0x03500000 0x400000>,
+ <0x03900000 0x400000>;
+ reg-names = "south", "center", "north";
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ gpio-ranges = <&tlmm 0 0 114>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ blsp1-uart1-default-state {
+ pins = "gpio0", "gpio1", "gpio2", "gpio3";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ blsp2_uart1_default: blsp2-uart1-active-state {
+ tx-rts-pins {
+ pins = "gpio16", "gpio19";
+ function = "blsp_uart5";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ rx-pins {
+ pins = "gpio17";
+ function = "blsp_uart5";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ cts-pins {
+ pins = "gpio18";
+ function = "blsp_uart5";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sdm660-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,sdm660-pinctrl.txt
deleted file mode 100644
index be034d329e10..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sdm660-pinctrl.txt
+++ /dev/null
@@ -1,191 +0,0 @@
-Qualcomm Technologies, Inc. SDM660 TLMM block
-
-This binding describes the Top Level Mode Multiplexer block found in the
-SDM660 platform.
-
-- compatible:
- Usage: required
- Value type: <string>
- Definition: must be "qcom,sdm660-pinctrl" or
- "qcom,sdm630-pinctrl".
-
-- reg:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: the base address and size of the north, center and south
- TLMM tiles.
-
-- reg-names:
- Usage: required
- Value type: <stringlist>
- Definition: names for the cells of reg, must contain "north", "center"
- and "south".
-
-- interrupts:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: should specify the TLMM summary IRQ.
-
-- interrupt-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as an interrupt controller
-
-- #interrupt-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/interrupt-controller/irq.h>
-
-- gpio-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as a gpio controller
-
-- gpio-ranges:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: Specifies the mapping between gpio controller and
- pin-controller pins.
-
-- #gpio-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/gpio/gpio.h>
-
-Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
-a general description of GPIO and interrupt bindings.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-The pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, drive strength, etc.
-
-
-PIN CONFIGURATION NODES:
-
-The name of each subnode is not important; all subnodes should be enumerated
-and processed purely based on their content.
-
-Each subnode only affects those parameters that are explicitly listed. In
-other words, a subnode that lists a mux function but no pin configuration
-parameters implies no information about any pin configuration parameters.
-Similarly, a pin subnode that describes a pullup parameter implies no
-information about e.g. the mux function.
-
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pin configuration subnode:
-
-- pins:
- Usage: required
- Value type: <string-array>
- Definition: List of gpio pins affected by the properties specified in
- this subnode. Valid pins are:
- gpio0-gpio113,
- Supports mux, bias and drive-strength
- sdc1_clk, sdc1_cmd, sdc1_data sdc2_clk, sdc2_cmd, sdc2_data sdc1_rclk,
- Supports bias and drive-strength
-
-- function:
- Usage: required
- Value type: <string>
- Definition: Specify the alternative function to be configured for the
- specified pins. Functions are only valid for gpio pins.
- Valid values are:
- adsp_ext, agera_pll, atest_char, atest_char0, atest_char1,
- atest_char2, atest_char3, atest_gpsadc0, atest_gpsadc1,
- atest_tsens, atest_tsens2, atest_usb1, atest_usb10,
- atest_usb11, atest_usb12, atest_usb13, atest_usb2,
- atest_usb20, atest_usb21, atest_usb22, atest_usb23,
- audio_ref, bimc_dte0, bimc_dte1, blsp_i2c1, blsp_i2c2,
- blsp_i2c3, blsp_i2c4, blsp_i2c5, blsp_i2c6, blsp_i2c7,
- blsp_i2c8_a, blsp_i2c8_b, blsp_spi1, blsp_spi2, blsp_spi3,
- blsp_spi3_cs1, blsp_spi3_cs2, blsp_spi4, blsp_spi5,
- blsp_spi6, blsp_spi7, blsp_spi8_a, blsp_spi8_b,
- blsp_spi8_cs1, blsp_spi8_cs2, blsp_uart1, blsp_uart2,
- blsp_uart5, blsp_uart6_a, blsp_uart6_b, blsp_uim1,
- blsp_uim2, blsp_uim5, blsp_uim6, cam_mclk, cci_async,
- cci_i2c, cri_trng, cri_trng0, cri_trng1, dbg_out, ddr_bist,
- gcc_gp1, gcc_gp2, gcc_gp3, gpio, gps_tx_a, gps_tx_b, gps_tx_c,
- isense_dbg, jitter_bist, ldo_en, ldo_update, m_voc, mdp_vsync,
- mdss_vsync0, mdss_vsync1, mdss_vsync2, mdss_vsync3, mss_lte,
- nav_pps_a, nav_pps_b, nav_pps_c, pa_indicator, phase_flag0,
- phase_flag1, phase_flag10, phase_flag11, phase_flag12,
- phase_flag13, phase_flag14, phase_flag15, phase_flag16,
- phase_flag17, phase_flag18, phase_flag19, phase_flag2,
- phase_flag20, phase_flag21, phase_flag22, phase_flag23,
- phase_flag24, phase_flag25, phase_flag26, phase_flag27,
- phase_flag28, phase_flag29, phase_flag3, phase_flag30,
- phase_flag31, phase_flag4, phase_flag5, phase_flag6,
- phase_flag7, phase_flag8, phase_flag9, pll_bypassnl,
- pll_reset, pri_mi2s, pri_mi2s_ws, prng_rosc, pwr_crypto,
- pwr_modem, pwr_nav, qdss_cti0_a, qdss_cti0_b, qdss_cti1_a,
- qdss_cti1_b, qdss_gpio, qdss_gpio0, qdss_gpio1, qdss_gpio10,
- qdss_gpio11, qdss_gpio12, qdss_gpio13, qdss_gpio14, qdss_gpio15,
- qdss_gpio2, qdss_gpio3, qdss_gpio4, qdss_gpio5, qdss_gpio6,
- qdss_gpio7, qdss_gpio8, qdss_gpio9, qlink_enable, qlink_request,
- qspi_clk, qspi_cs, qspi_data0, qspi_data1, qspi_data2,
- qspi_data3, qspi_resetn, sec_mi2s, sndwire_clk, sndwire_data,
- sp_cmu, ssc_irq, tgu_ch0, tgu_ch1, tsense_pwm1, tsense_pwm2,
- uim1_clk, uim1_data, uim1_present, uim1_reset, uim2_clk,
- uim2_data, uim2_present, uim2_reset, uim_batt, vfr_1,
- vsense_clkout, vsense_data0, vsense_data1, vsense_mode,
- wlan1_adc0, wlan1_adc1, wlan2_adc0, wlan2_adc1
-
-- bias-disable:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as no pull.
-
-- bias-pull-down:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull down.
-
-- bias-pull-up:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull up.
-
-- output-high:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- high.
- Not valid for sdc pins.
-
-- output-low:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- low.
- Not valid for sdc pins.
-
-- drive-strength:
- Usage: optional
- Value type: <u32>
- Definition: Selects the drive strength for the specified pins, in mA.
- Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
-
-Example:
-
- tlmm: pinctrl@3100000 {
- compatible = "qcom,sdm660-pinctrl";
- reg = <0x3100000 0x200000>,
- <0x3500000 0x200000>,
- <0x3900000 0x200000>;
- reg-names = "south", "center", "north";
- interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- gpio-ranges = <&tlmm 0 0 114>;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sdm670-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sdm670-tlmm.yaml
new file mode 100644
index 000000000000..7585117c0f06
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sdm670-tlmm.yaml
@@ -0,0 +1,127 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,sdm670-tlmm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Technologies, Inc. SDM670 TLMM block
+
+maintainers:
+ - Richard Acayan <mailingradian@gmail.com>
+
+description: |
+ The Top Level Mode Multiplexer (TLMM) block found in the SDM670 platform.
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+properties:
+ compatible:
+ const: qcom,sdm670-tlmm
+
+ reg:
+ maxItems: 1
+
+ interrupts: true
+ interrupt-controller: true
+ "#interrupt-cells": true
+ gpio-controller: true
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 75
+
+ "#gpio-cells": true
+ gpio-ranges: true
+ wakeup-parent: true
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-sdm670-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-sdm670-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-sdm670-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ oneOf:
+ - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-4][0-9])$"
+ - enum: [ ufs_reset, sdc1_rclk, sdc1_clk, sdc1_cmd, sdc1_data,
+ sdc2_clk, sdc2_cmd, sdc2_data ]
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ adsp_ext, agera_pll, atest_char, atest_tsens, atest_tsens2, atest_usb1, atest_usb10,
+ atest_usb11, atest_usb12, atest_usb13, atest_usb2, atest_usb20, atest_usb21,
+ atest_usb22, atest_usb23, cam_mclk, cci_async, cci_i2c, cci_timer0, cci_timer1,
+ cci_timer2, cci_timer3, cci_timer4, copy_gp, copy_phase, dbg_out, ddr_bist,
+ ddr_pxi0, ddr_pxi1, ddr_pxi2, ddr_pxi3, edp_hot, edp_lcd, gcc_gp1, gcc_gp2, gcc_gp3,
+ gp_pdm0, gp_pdm1, gp_pdm2, gpio, gps_tx, jitter_bist, ldo_en, ldo_update,
+ lpass_slimbus, m_voc, mdp_vsync, mdp_vsync0, mdp_vsync1, mdp_vsync2, mdp_vsync3,
+ mss_lte, nav_pps, pa_indicator, pci_e0, pci_e1, phase_flag, pll_bist, pll_bypassnl,
+ pll_reset, pri_mi2s, pri_mi2s_ws, prng_rosc, qdss_cti, qdss, qlink_enable,
+ qlink_request, qua_mi2s, qup0, qup1, qup10, qup11, qup12, qup13, qup14, qup15, qup2,
+ qup3, qup4, qup5, qup6, qup7, qup8, qup9, qup_l4, qup_l5, qup_l6, sdc4_clk,
+ sdc4_cmd, sdc4_data, sd_write, sec_mi2s, ter_mi2s, tgu_ch0, tgu_ch1, tgu_ch2,
+ tgu_ch3, tsif1_clk, tsif1_data, tsif1_en, tsif1_error, tsif1_sync, tsif2_clk,
+ tsif2_data, tsif2_en, tsif2_error, tsif2_sync, uim1_clk, uim1_data, uim1_present,
+ uim1_reset, uim2_clk, uim2_data, uim2_present, uim2_reset, uim_batt, usb_phy, vfr_1,
+ vsense_trigger, wlan1_adc0, wlan1_adc1, wlan2_adc0, wlan2_adc1, wsa_clk, wsa_data, ]
+
+
+ bias-disable: true
+ bias-pull-down: true
+ bias-pull-up: true
+ drive-strength: true
+ input-enable: true
+ output-high: true
+ output-low: true
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ pinctrl@3400000 {
+ compatible = "qcom,sdm670-tlmm";
+ reg = <0x03400000 0x300000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&tlmm 0 0 151>;
+
+ qup-i2c9-state {
+ pins = "gpio6", "gpio7";
+ function = "qup9";
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sdm845-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,sdm845-pinctrl.txt
deleted file mode 100644
index 7462e3743c68..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sdm845-pinctrl.txt
+++ /dev/null
@@ -1,176 +0,0 @@
-Qualcomm SDM845 TLMM block
-
-This binding describes the Top Level Mode Multiplexer block found in the
-SDM845 platform.
-
-- compatible:
- Usage: required
- Value type: <string>
- Definition: must be "qcom,sdm845-pinctrl"
-
-- reg:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: the base address and size of the TLMM register space.
-
-- interrupts:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: should specify the TLMM summary IRQ.
-
-- interrupt-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as an interrupt controller
-
-- #interrupt-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/interrupt-controller/irq.h>
-
-- gpio-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as a gpio controller
-
-- #gpio-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/gpio/gpio.h>
-
-Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
-a general description of GPIO and interrupt bindings.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-The pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, drive strength, etc.
-
-
-PIN CONFIGURATION NODES:
-
-The name of each subnode is not important; all subnodes should be enumerated
-and processed purely based on their content.
-
-Each subnode only affects those parameters that are explicitly listed. In
-other words, a subnode that lists a mux function but no pin configuration
-parameters implies no information about any pin configuration parameters.
-Similarly, a pin subnode that describes a pullup parameter implies no
-information about e.g. the mux function.
-
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pin configuration subnode:
-
-- pins:
- Usage: required
- Value type: <string-array>
- Definition: List of gpio pins affected by the properties specified in
- this subnode.
-
- Valid pins are:
- gpio0-gpio149
- Supports mux, bias and drive-strength
-
- sdc2_clk, sdc2_cmd, sdc2_data, ufs_reset
- Supports bias and drive-strength
-
-- function:
- Usage: required
- Value type: <string>
- Definition: Specify the alternative function to be configured for the
- specified pins. Functions are only valid for gpio pins.
- Valid values are:
-
- gpio, adsp_ext, agera_pll, atest_char, atest_tsens,
- atest_tsens2, atest_usb1, atest_usb10, atest_usb11,
- atest_usb12, atest_usb13, atest_usb2, atest_usb20,
- atest_usb21, atest_usb22, atest_usb23, audio_ref,
- btfm_slimbus, cam_mclk, cci_async, cci_i2c, cci_timer0,
- cci_timer1, cci_timer2, cci_timer3, cci_timer4, cri_trng,
- cri_trng0, cri_trng1, dbg_out, ddr_bist, ddr_pxi0,
- ddr_pxi1, ddr_pxi2, ddr_pxi3, edp_hot, edp_lcd, gcc_gp1,
- gcc_gp2, gcc_gp3, jitter_bist, ldo_en, ldo_update,
- lpass_slimbus, m_voc, mdp_vsync, mdp_vsync0, mdp_vsync1,
- mdp_vsync2, mdp_vsync3, mss_lte, nav_pps, pa_indicator,
- pci_e0, pci_e1, phase_flag, pll_bist, pll_bypassnl,
- pll_reset, pri_mi2s, pri_mi2s_ws, prng_rosc, qdss_cti,
- qdss, qlink_enable, qlink_request, qua_mi2s, qup0, qup1,
- qup10, qup11, qup12, qup13, qup14, qup15, qup2, qup3, qup4,
- qup5, qup6, qup7, qup8, qup9, qup_l4, qup_l5, qup_l6,
- qspi_clk, qspi_cs, qspi_data, sd_write, sdc4_clk, sdc4_cmd,
- sdc4_data, sec_mi2s, sp_cmu, spkr_i2s, ter_mi2s, tgu_ch0,
- tgu_ch1, tgu_ch2, tgu_ch3, tsense_pwm1, tsense_pwm2,
- tsif1_clk, tsif1_data, tsif1_en, tsif1_error, tsif1_sync,
- tsif2_clk, tsif2_data, tsif2_en, tsif2_error, tsif2_sync,
- uim1_clk, uim1_data, uim1_present, uim1_reset, uim2_clk,
- uim2_data, uim2_present, uim2_reset, uim_batt, usb_phy,
- vfr_1, vsense_trigger, wlan1_adc0, wlan1_adc1, wlan2_adc0,
- wlan2_adc1,
-
-- bias-disable:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as no pull.
-
-- bias-pull-down:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull down.
-
-- bias-pull-up:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configured as pull up.
-
-- output-high:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- high.
- Not valid for sdc pins.
-
-- output-low:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- low.
- Not valid for sdc pins.
-
-- drive-strength:
- Usage: optional
- Value type: <u32>
- Definition: Selects the drive strength for the specified pins, in mA.
- Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
-
-Example:
-
- tlmm: pinctrl@3400000 {
- compatible = "qcom,sdm845-pinctrl";
- reg = <0x03400000 0xc00000>;
- interrupts = <GIC_SPI 208 0>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
-
- qup9_active: qup9-active {
- mux {
- pins = "gpio4", "gpio5";
- function = "qup9";
- };
-
- config {
- pins = "gpio4", "gpio5";
- drive-strength = <2>;
- bias-disable;
- };
- };
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sdm845-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sdm845-pinctrl.yaml
new file mode 100644
index 000000000000..c9627777ceb3
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sdm845-pinctrl.yaml
@@ -0,0 +1,158 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,sdm845-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SDM845 TLMM pin controller
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm SDM845 SoC.
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+properties:
+ compatible:
+ const: qcom,sdm845-pinctrl
+
+ reg:
+ maxItems: 1
+
+ interrupts: true
+ interrupt-controller: true
+ "#interrupt-cells": true
+ gpio-controller: true
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 75
+
+ gpio-line-names:
+ maxItems: 150
+
+ "#gpio-cells": true
+ gpio-ranges: true
+ wakeup-parent: true
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-sdm845-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-sdm845-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-sdm845-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ oneOf:
+ - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-4][0-9])$"
+ - enum: [ ufs_reset, sdc2_clk, sdc2_cmd, sdc2_data ]
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+ enum: [ adsp_ext, agera_pll, atest_char, atest_tsens, atest_tsens2,
+ atest_usb1, atest_usb10, atest_usb11, atest_usb12, atest_usb13,
+ atest_usb2, atest_usb20, atest_usb21, atest_usb22, atest_usb23,
+ audio_ref, btfm_slimbus, cam_mclk, cci_async, cci_i2c,
+ cci_timer0, cci_timer1, cci_timer2, cci_timer3, cci_timer4,
+ cri_trng, cri_trng0, cri_trng1, dbg_out, ddr_bist, ddr_pxi0,
+ ddr_pxi1, ddr_pxi2, ddr_pxi3, edp_hot, edp_lcd, gcc_gp1,
+ gcc_gp2, gcc_gp3, gpio, jitter_bist, ldo_en, ldo_update,
+ lpass_slimbus, mdp_vsync, mdp_vsync0, mdp_vsync1, mdp_vsync2,
+ mdp_vsync3, mss_lte, m_voc, nav_pps, pa_indicator, pci_e0,
+ pci_e1, phase_flag, pll_bist, pll_bypassnl, pll_reset,
+ pri_mi2s, pri_mi2s_ws, prng_rosc, qdss, qdss_cti, qlink_enable,
+ qlink_request, qspi_clk, qspi_cs, qspi_data, qua_mi2s, qup0,
+ qup1, qup10, qup11, qup12, qup13, qup14, qup15, qup2, qup3,
+ qup4, qup5, qup6, qup7, qup8, qup9, qup_l4, qup_l5, qup_l6,
+ sdc4_clk, sdc4_cmd, sdc4_data, sd_write, sec_mi2s, sp_cmu,
+ spkr_i2s, ter_mi2s, tgu_ch0, tgu_ch1, tgu_ch2, tgu_ch3,
+ tsense_pwm1, tsense_pwm2, tsif1_clk, tsif1_data, tsif1_en,
+ tsif1_error, tsif1_sync, tsif2_clk, tsif2_data, tsif2_en,
+ tsif2_error, tsif2_sync, uim1_clk, uim1_data, uim1_present,
+ uim1_reset, uim2_clk, uim2_data, uim2_present, uim2_reset,
+ uim_batt, usb_phy, vfr_1, vsense_trigger, wlan1_adc0,
+ wlan1_adc1, wlan2_adc0, wlan2_adc1]
+
+ bias-disable: true
+ bias-pull-down: true
+ bias-pull-up: true
+ drive-strength: true
+ input-enable: true
+ output-high: true
+ output-low: true
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ pinctrl@3400000 {
+ compatible = "qcom,sdm845-pinctrl";
+ reg = <0x03400000 0xc00000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&tlmm 0 0 151>;
+ wakeup-parent = <&pdc_intc>;
+
+ cci0-default-state {
+ pins = "gpio17", "gpio18";
+ function = "cci_i2c";
+
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+
+ cam0-default-state {
+ rst-pins {
+ pins = "gpio9";
+ function = "gpio";
+
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ mclk0-pins {
+ pins = "gpio13";
+ function = "cam_mclk";
+
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sdx55-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sdx55-pinctrl.yaml
index a38090b14aab..a76117e41d93 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sdx55-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sdx55-pinctrl.yaml
@@ -9,9 +9,8 @@ title: Qualcomm Technologies, Inc. SDX55 TLMM block
maintainers:
- Vinod Koul <vkoul@kernel.org>
-description: |
- This binding describes the Top Level Mode Multiplexer block found in the
- SDX55 platform.
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm SDX55 SoC.
properties:
compatible:
@@ -21,38 +20,32 @@ properties:
description: Specifies the base address and size of the TLMM register space
maxItems: 1
- interrupts:
- description: Specifies the TLMM summary IRQ
- maxItems: 1
-
+ interrupts: true
interrupt-controller: true
-
- '#interrupt-cells':
- description: Specifies the PIN numbers and Flags, as defined in
- include/dt-bindings/interrupt-controller/irq.h
- const: 2
-
+ "#interrupt-cells": true
gpio-controller: true
-
- '#gpio-cells':
- description: Specifying the pin number and flags, as defined in
- include/dt-bindings/gpio/gpio.h
- const: 2
-
- gpio-ranges:
- maxItems: 1
+ "#gpio-cells": true
+ gpio-ranges: true
gpio-reserved-ranges:
maxItems: 1
-#PIN CONFIGURATION NODES
patternProperties:
- '-pins$':
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-sdx55-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-sdx55-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-sdx55-tlmm-state:
type: object
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
Client device subnodes use below standard properties.
- $ref: "/schemas/pinctrl/pincfg-node.yaml"
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
properties:
pins:
@@ -96,62 +89,46 @@ patternProperties:
uim1_present, uim1_reset, uim2_clk, uim2_data, uim2_present,
uim2_reset, usb2phy_ac, vsense_trigger ]
- drive-strength:
- enum: [2, 4, 6, 8, 10, 12, 14, 16]
- default: 2
- description:
- Selects the drive strength for the specified pins, in mA.
-
bias-pull-down: true
-
bias-pull-up: true
-
bias-disable: true
-
+ drive-strength: true
output-high: true
-
output-low: true
required:
- pins
- - function
additionalProperties: false
allOf:
- - $ref: "pinctrl.yaml#"
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
required:
- compatible
- reg
- - interrupts
- - interrupt-controller
- - '#interrupt-cells'
- - gpio-controller
- - '#gpio-cells'
- - gpio-ranges
additionalProperties: false
examples:
- |
- #include <dt-bindings/interrupt-controller/arm-gic.h>
- tlmm: pinctrl@1f00000 {
- compatible = "qcom,sdx55-pinctrl";
- reg = <0x0f100000 0x300000>;
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&tlmm 0 0 108>;
- interrupt-controller;
- #interrupt-cells = <2>;
- interrupts = <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>;
-
- serial-pins {
- pins = "gpio8", "gpio9";
- function = "blsp_uart3";
- drive-strength = <8>;
- bias-disable;
- };
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ tlmm: pinctrl@1f00000 {
+ compatible = "qcom,sdx55-pinctrl";
+ reg = <0x0f100000 0x300000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&tlmm 0 0 108>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupts = <GIC_SPI 212 IRQ_TYPE_LEVEL_HIGH>;
+
+ serial-state {
+ pins = "gpio8", "gpio9";
+ function = "blsp_uart3";
+ drive-strength = <8>;
+ bias-disable;
};
+ };
...
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sdx65-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sdx65-tlmm.yaml
index cdfcf29dffee..2f53905260e6 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sdx65-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sdx65-tlmm.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/pinctrl/qcom,sdx65-pinctrl.yaml#
+$id: http://devicetree.org/schemas/pinctrl/qcom,sdx65-tlmm.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies, Inc. SDX65 TLMM block
@@ -10,8 +10,7 @@ maintainers:
- Vamsi krishna Lanka <quic_vamslank@quicinc.com>
description:
- This binding describes the Top Level Mode Multiplexer block found in the
- SDX65 platform.
+ Top Level Mode Multiplexer pin controller in Qualcomm SDX65 SoC.
properties:
compatible:
@@ -20,44 +19,32 @@ properties:
reg:
maxItems: 1
- interrupts:
- maxItems: 1
-
+ interrupts: true
interrupt-controller: true
-
- '#interrupt-cells':
- description: Specifies the PIN numbers and Flags, as defined in
- include/dt-bindings/interrupt-controller/irq.h
- const: 2
-
+ "#interrupt-cells": true
gpio-controller: true
-
- '#gpio-cells':
- description: Specifying the pin number and flags, as defined in
- include/dt-bindings/gpio/gpio.h
- const: 2
-
- gpio-ranges:
- maxItems: 1
+ "#gpio-cells": true
+ gpio-ranges: true
gpio-reserved-ranges:
maxItems: 1
-#PIN CONFIGURATION NODES
patternProperties:
- '-state$':
+ "-state$":
oneOf:
- $ref: "#/$defs/qcom-sdx65-tlmm-state"
- patternProperties:
- ".*":
+ "-pins$":
$ref: "#/$defs/qcom-sdx65-tlmm-state"
-'$defs':
+ additionalProperties: false
+
+$defs:
qcom-sdx65-tlmm-state:
type: object
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
Client device subnodes use below standard properties.
- $ref: "qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state"
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
properties:
pins:
@@ -122,37 +109,24 @@ patternProperties:
qspi_cs, ssbi2, ssbi1, mss_lte, qspi_clk, qspi0, qspi1, qspi2, qspi3,
gpio ]
- drive-strength:
- enum: [2, 4, 6, 8, 10, 12, 14, 16]
- default: 2
- description:
- Selects the drive strength for the specified pins, in mA.
-
bias-pull-down: true
-
bias-pull-up: true
-
bias-disable: true
-
+ drive-strength: true
output-high: true
-
output-low: true
required:
- pins
- - function
additionalProperties: false
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
required:
- compatible
- reg
- - interrupts
- - interrupt-controller
- - '#interrupt-cells'
- - gpio-controller
- - '#gpio-cells'
- - gpio-ranges
additionalProperties: false
@@ -175,13 +149,13 @@ examples:
};
uart-w-subnodes-state {
- rx {
+ rx-pins {
pins = "gpio4";
function = "blsp_uart1";
bias-pull-up;
};
- tx {
+ tx-pins {
pins = "gpio5";
function = "blsp_uart1";
bias-disable;
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm6115-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm6115-tlmm.yaml
index e39fbb36d8c1..164f24db8b2b 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sm6115-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm6115-tlmm.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/pinctrl/qcom,sm6115-pinctrl.yaml#
+$id: http://devicetree.org/schemas/pinctrl/qcom,sm6115-tlmm.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies, Inc. SM6115, SM4250 TLMM block
@@ -10,15 +10,14 @@ maintainers:
- Iskren Chernev <iskren.chernev@gmail.com>
description:
- This binding describes the Top Level Mode Multiplexer block found in the
- SM4250/6115 platforms.
+ Top Level Mode Multiplexer pin controller in Qualcomm SM4250 and SM6115
+ SoCs.
properties:
compatible:
const: qcom,sm6115-tlmm
reg:
- minItems: 3
maxItems: 3
reg-names:
@@ -27,35 +26,17 @@ properties:
- const: south
- const: east
- interrupts:
- description: Specifies the TLMM summary IRQ
- maxItems: 1
-
+ interrupts: true
interrupt-controller: true
-
- '#interrupt-cells':
- description:
- Specifies the PIN numbers and Flags, as defined in defined in
- include/dt-bindings/interrupt-controller/irq.h
- const: 2
-
+ "#interrupt-cells": true
gpio-controller: true
-
- '#gpio-cells':
- description: Specifying the pin number and flags, as defined in
- include/dt-bindings/gpio/gpio.h
- const: 2
-
- gpio-ranges:
- maxItems: 1
-
+ "#gpio-cells": true
+ gpio-ranges: true
gpio-reserved-ranges: true
-
wakeup-parent: true
-#PIN CONFIGURATION NODES
patternProperties:
- '-state$':
+ "-state$":
oneOf:
- $ref: "#/$defs/qcom-sm6115-tlmm-state"
- patternProperties:
@@ -63,12 +44,13 @@ patternProperties:
$ref: "#/$defs/qcom-sm6115-tlmm-state"
additionalProperties: false
-'$defs':
+$defs:
qcom-sm6115-tlmm-state:
type: object
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
properties:
pins:
@@ -101,50 +83,25 @@ patternProperties:
uim2_present, uim2_reset, usb_phy, vfr_1, vsense_trigger,
wlan1_adc0, elan1_adc1 ]
- drive-strength:
- enum: [2, 4, 6, 8, 10, 12, 14, 16]
- default: 2
- description:
- Selects the drive strength for the specified pins, in mA.
-
bias-pull-down: true
-
bias-pull-up: true
-
bias-disable: true
-
+ drive-strength: true
output-high: true
-
output-low: true
required:
- pins
- allOf:
- - $ref: "qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state"
- - if:
- properties:
- pins:
- pattern: "^gpio([0-9]|[1-9][0-9]|10[0-9]|11[0-2])$"
- then:
- required:
- - function
-
additionalProperties: false
allOf:
- - $ref: "pinctrl.yaml#"
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
required:
- compatible
- reg
- reg-names
- - interrupts
- - interrupt-controller
- - '#interrupt-cells'
- - gpio-controller
- - '#gpio-cells'
- - gpio-ranges
additionalProperties: false
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm6125-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm6125-tlmm.yaml
index 5cb8b272cb7d..e1dd54a160d5 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sm6125-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm6125-tlmm.yaml
@@ -1,19 +1,17 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/pinctrl/qcom,sm6125-pinctrl.yaml#
+$id: http://devicetree.org/schemas/pinctrl/qcom,sm6125-tlmm.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies, Inc. SM6125 TLMM block
maintainers:
- Martin Botka <martin.botka@somainline.org>
-description: |
- This binding describes the Top Level Mode Multiplexer (TLMM) block found
- in the SM6125 platform.
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm SM6125 SoC.
allOf:
- - $ref: "pinctrl.yaml#"
- $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
properties:
@@ -21,21 +19,20 @@ properties:
const: qcom,sm6125-tlmm
reg:
- minItems: 3
maxItems: 3
reg-names:
items:
- - const: "west"
- - const: "south"
- - const: "east"
+ - const: west
+ - const: south
+ - const: east
interrupts: true
interrupt-controller: true
- '#interrupt-cells': true
+ "#interrupt-cells": true
gpio-controller: true
gpio-reserved-ranges: true
- '#gpio-cells': true
+ "#gpio-cells": true
gpio-ranges: true
wakeup-parent: true
@@ -47,7 +44,7 @@ required:
additionalProperties: false
patternProperties:
- '-state$':
+ "-state$":
oneOf:
- $ref: "#/$defs/qcom-sm6125-tlmm-state"
- patternProperties:
@@ -61,6 +58,7 @@ $defs:
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
properties:
pins:
@@ -112,16 +110,6 @@ $defs:
required:
- pins
- allOf:
- - $ref: "qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state"
- - if:
- properties:
- pins:
- pattern: "^gpio[0-9]|[1-9][0-9]|1[0-2][0-9]|13[0-2]$"
- then:
- required:
- - function
-
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm6350-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm6350-tlmm.yaml
index 856b9c567ecb..41e3e0afc9a8 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sm6350-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm6350-tlmm.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/pinctrl/qcom,sm6350-pinctrl.yaml#
+$id: http://devicetree.org/schemas/pinctrl/qcom,sm6350-tlmm.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies, Inc. SM6350 TLMM block
@@ -9,12 +9,10 @@ title: Qualcomm Technologies, Inc. SM6350 TLMM block
maintainers:
- Konrad Dybcio <konrad.dybcio@somainline.org>
-description: |
- This binding describes the Top Level Mode Multiplexer (TLMM) block found
- in the SM6350 platform.
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm SM6350 SoC.
allOf:
- - $ref: "pinctrl.yaml#"
- $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
properties:
@@ -26,10 +24,10 @@ properties:
interrupts: true
interrupt-controller: true
- '#interrupt-cells': true
+ "#interrupt-cells": true
gpio-controller: true
gpio-reserved-ranges: true
- '#gpio-cells': true
+ "#gpio-cells": true
gpio-ranges: true
wakeup-parent: true
@@ -40,7 +38,7 @@ required:
additionalProperties: false
patternProperties:
- '-state$':
+ "-state$":
oneOf:
- $ref: "#/$defs/qcom-sm6350-tlmm-state"
- patternProperties:
@@ -54,6 +52,7 @@ $defs:
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
properties:
pins:
@@ -111,16 +110,6 @@ $defs:
required:
- pins
- allOf:
- - $ref: "qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state"
- - if:
- properties:
- pins:
- pattern: "^gpio([0-9]|[1-9][0-9]|1[0-4][0-9]|15[0-7])$"
- then:
- required:
- - function
-
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm6375-tlmm.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm6375-tlmm.yaml
index 025faf87d147..d54ebb2bd5a8 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sm6375-tlmm.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm6375-tlmm.yaml
@@ -9,12 +9,10 @@ title: Qualcomm Technologies, Inc. SM6375 TLMM block
maintainers:
- Konrad Dybcio <konrad.dybcio@somainline.org>
-description: |
- This binding describes the Top Level Mode Multiplexer (TLMM) block found
- in the SM6375 platform.
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm SM6375 SoC.
allOf:
- - $ref: "pinctrl.yaml#"
- $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
properties:
@@ -26,10 +24,10 @@ properties:
interrupts: true
interrupt-controller: true
- '#interrupt-cells': true
+ "#interrupt-cells": true
gpio-controller: true
gpio-reserved-ranges: true
- '#gpio-cells': true
+ "#gpio-cells": true
gpio-ranges: true
wakeup-parent: true
@@ -40,7 +38,7 @@ required:
additionalProperties: false
patternProperties:
- '-state$':
+ "-state$":
oneOf:
- $ref: "#/$defs/qcom-sm6375-tlmm-state"
- patternProperties:
@@ -54,6 +52,7 @@ $defs:
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
properties:
pins:
@@ -120,16 +119,6 @@ $defs:
required:
- pins
- allOf:
- - $ref: "qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state"
- - if:
- properties:
- pins:
- pattern: "^gpio([0-9]|[1-9][0-9]|1[0-4][0-9]|15[0-6])$"
- then:
- required:
- - function
-
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm8150-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,sm8150-pinctrl.txt
deleted file mode 100644
index fa37733e5102..000000000000
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sm8150-pinctrl.txt
+++ /dev/null
@@ -1,190 +0,0 @@
-Qualcomm SM8150 TLMM block
-
-This binding describes the Top Level Mode Multiplexer block found in the
-QCS404 platform.
-
-- compatible:
- Usage: required
- Value type: <string>
- Definition: must be "qcom,sm8150-pinctrl"
-
-- reg:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: the base address and size of the north, south, west
- and east TLMM tiles.
-
-- reg-names:
- Usage: required
- Value type: <prop-encoded-array>
- Defintiion: names for the cells of reg, must contain "north", "south"
- "west" and "east".
-
-- interrupts:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: should specify the TLMM summary IRQ.
-
-- interrupt-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as an interrupt controller
-
-- #interrupt-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/interrupt-controller/irq.h>
-
-- gpio-controller:
- Usage: required
- Value type: <none>
- Definition: identifies this node as a gpio controller
-
-- #gpio-cells:
- Usage: required
- Value type: <u32>
- Definition: must be 2. Specifying the pin number and flags, as defined
- in <dt-bindings/gpio/gpio.h>
-
-- gpio-ranges:
- Usage: required
- Value type: <prop-encoded-array>
- Definition: see ../gpio/gpio.txt
-
-- gpio-reserved-ranges:
- Usage: optional
- Value type: <prop-encoded-array>
- Definition: see ../gpio/gpio.txt
-
-Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
-a general description of GPIO and interrupt bindings.
-
-Please refer to pinctrl-bindings.txt in this directory for details of the
-common pinctrl bindings used by client devices, including the meaning of the
-phrase "pin configuration node".
-
-The pin configuration nodes act as a container for an arbitrary number of
-subnodes. Each of these subnodes represents some desired configuration for a
-pin, a group, or a list of pins or groups. This configuration can include the
-mux function to select on those pin(s)/group(s), and various pin configuration
-parameters, such as pull-up, drive strength, etc.
-
-
-PIN CONFIGURATION NODES:
-
-The name of each subnode is not important; all subnodes should be enumerated
-and processed purely based on their content.
-
-Each subnode only affects those parameters that are explicitly listed. In
-other words, a subnode that lists a mux function but no pin configuration
-parameters implies no information about any pin configuration parameters.
-Similarly, a pin subnode that describes a pullup parameter implies no
-information about e.g. the mux function.
-
-
-The following generic properties as defined in pinctrl-bindings.txt are valid
-to specify in a pin configuration subnode:
-
-- pins:
- Usage: required
- Value type: <string-array>
- Definition: List of gpio pins affected by the properties specified in
- this subnode.
-
- Valid pins are:
- gpio0-gpio149
- Supports mux, bias and drive-strength
-
- sdc1_clk, sdc1_cmd, sdc1_data sdc2_clk, sdc2_cmd,
- sdc2_data sdc1_rclk
- Supports bias and drive-strength
-
- ufs_reset
- Supports bias and drive-strength
-
-- function:
- Usage: required
- Value type: <string>
- Definition: Specify the alternative function to be configured for the
- specified pins. Functions are only valid for gpio pins.
- Valid values are:
-
- adsp_ext, agera_pll, aoss_cti, ddr_pxi2, atest_char,
- atest_char0, atest_char1, atest_char2, atest_char3,
- audio_ref, atest_usb1, atest_usb2, atest_usb10,
- atest_usb11, atest_usb12, atest_usb13, atest_usb20,
- atest_usb21, atest_usb22, atest_usb2, atest_usb23,
- btfm_slimbus, cam_mclk, cci_async, cci_i2c, cci_timer0,
- cci_timer1, cci_timer2, cci_timer3, cci_timer4,
- cri_trng, cri_trng0, cri_trng1, dbg_out, ddr_bist,
- ddr_pxi0, ddr_pxi1, ddr_pxi3, edp_hot, edp_lcd,
- emac_phy, emac_pps, gcc_gp1, gcc_gp2, gcc_gp3, gpio,
- hs1_mi2s, hs2_mi2s, hs3_mi2s, jitter_bist,
- lpass_slimbus, mdp_vsync, mdp_vsync0, mdp_vsync1,
- mdp_vsync2, mdp_vsync3, mss_lte, m_voc, nav_pps,
- pa_indicator, pci_e0, phase_flag, pll_bypassnl,
- pll_bist, pci_e1, pll_reset, pri_mi2s, pri_mi2s_ws,
- prng_rosc, qdss, qdss_cti, qlink_request, qlink_enable,
- qspi0, qspi1, qspi2, qspi3, qspi_clk, qspi_cs, qua_mi2s,
- qup0, qup1, qup2, qup3, qup4, qup5, qup6, qup7, qup8,
- qup9, qup10, qup11, qup12, qup13, qup14, qup15, qup16,
- qup17, qup18, qup19, qup_l4, qup_l5, qup_l6, rgmii,
- sdc4, sd_write, sec_mi2s, spkr_i2s, sp_cmu, ter_mi2s,
- tgu_ch0, tgu_ch1, tgu_ch2, tgu_ch3, tsense_pwm1,
- tsense_pwm2, tsif1, tsif2, uim1, uim2, uim_batt,
- usb2phy_ac, usb_phy, vfr_1, vsense_trigger, wlan1_adc0,
- wlan1_adc1, wlan2_adc0, wlan2_adc1, wmss_reset
-
-- bias-disable:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configued as no pull.
-
-- bias-pull-down:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configued as pull down.
-
-- bias-pull-up:
- Usage: optional
- Value type: <none>
- Definition: The specified pins should be configued as pull up.
-
-- output-high:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- high.
- Not valid for sdc pins.
-
-- output-low:
- Usage: optional
- Value type: <none>
- Definition: The specified pins are configured in output mode, driven
- low.
- Not valid for sdc pins.
-
-- drive-strength:
- Usage: optional
- Value type: <u32>
- Definition: Selects the drive strength for the specified pins, in mA.
- Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
-
-Example:
-
- tlmm: pinctrl@3000000 {
- compatible = "qcom,sm8150-pinctrl";
- reg = <0x03100000 0x300000>,
- <0x03500000 0x300000>,
- <0x03900000 0x300000>,
- <0x03D00000 0x300000>;
- reg-names = "west", "east", "north", "south";
- interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- gpio-ranges = <&tlmm 0 0 175>;
- gpio-reserved-ranges = <0 4>, <126 4>;
- interrupt-controller;
- #interrupt-cells = <2>;
- };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm8150-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm8150-pinctrl.yaml
new file mode 100644
index 000000000000..85adddbdee56
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm8150-pinctrl.yaml
@@ -0,0 +1,173 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/qcom,sm8150-pinctrl.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm SM8150 TLMM pin controller
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm SM8150 SoC.
+
+properties:
+ compatible:
+ const: qcom,sm8150-pinctrl
+
+ reg:
+ maxItems: 4
+
+ reg-names:
+ items:
+ - const: west
+ - const: east
+ - const: north
+ - const: south
+
+ interrupts: true
+ interrupt-controller: true
+ "#interrupt-cells": true
+ gpio-controller: true
+ "#gpio-cells": true
+ gpio-ranges: true
+ wakeup-parent: true
+
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 88
+
+ gpio-line-names:
+ maxItems: 175
+
+patternProperties:
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-sm8150-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-sm8150-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-sm8150-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ oneOf:
+ - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-6][0-9]|17[0-4])$"
+ - enum: [ sdc2_clk, sdc2_cmd, sdc2_data, ufs_reset ]
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ adsp_ext, agera_pll, aoss_cti, ddr_pxi2, atest_char,
+ atest_char0, atest_char1, atest_char2, atest_char3, audio_ref,
+ atest_usb1, atest_usb2, atest_usb10, atest_usb11, atest_usb12,
+ atest_usb13, atest_usb20, atest_usb21, atest_usb22, atest_usb2,
+ atest_usb23, btfm_slimbus, cam_mclk, cci_async, cci_i2c,
+ cci_timer0, cci_timer1, cci_timer2, cci_timer3, cci_timer4,
+ cri_trng, cri_trng0, cri_trng1, dbg_out, ddr_bist, ddr_pxi0,
+ ddr_pxi1, ddr_pxi3, edp_hot, edp_lcd, emac_phy, emac_pps,
+ gcc_gp1, gcc_gp2, gcc_gp3, gpio, hs1_mi2s, hs2_mi2s, hs3_mi2s,
+ jitter_bist, lpass_slimbus, mdp_vsync, mdp_vsync0, mdp_vsync1,
+ mdp_vsync2, mdp_vsync3, mss_lte, m_voc, nav_pps, pa_indicator,
+ pci_e0, phase_flag, pll_bypassnl, pll_bist, pci_e1, pll_reset,
+ pri_mi2s, pri_mi2s_ws, prng_rosc, qdss, qdss_cti,
+ qlink_request, qlink_enable, qspi0, qspi1, qspi2, qspi3,
+ qspi_clk, qspi_cs, qua_mi2s, qup0, qup1, qup2, qup3, qup4,
+ qup5, qup6, qup7, qup8, qup9, qup10, qup11, qup12, qup13,
+ qup14, qup15, qup16, qup17, qup18, qup19, qup_l4, qup_l5,
+ qup_l6, rgmii, sdc4, sd_write, sec_mi2s, spkr_i2s, sp_cmu,
+ ter_mi2s, tgu_ch0, tgu_ch1, tgu_ch2, tgu_ch3, tsense_pwm1,
+ tsense_pwm2, tsif1, tsif2, uim1, uim2, uim_batt, usb2phy_ac,
+ usb_phy, vfr_1, vsense_trigger, wlan1_adc0, wlan1_adc1,
+ wlan2_adc0, wlan2_adc1, wmss_reset ]
+
+ bias-pull-down: true
+ bias-pull-up: true
+ bias-disable: true
+ drive-strength: true
+ input-enable: true
+ output-high: true
+ output-low: true
+
+ required:
+ - pins
+
+ additionalProperties: false
+
+allOf:
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
+
+required:
+ - compatible
+ - reg
+ - reg-names
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ tlmm: pinctrl@3100000 {
+ compatible = "qcom,sm8150-pinctrl";
+ reg = <0x03100000 0x300000>,
+ <0x03500000 0x300000>,
+ <0x03900000 0x300000>,
+ <0x03d00000 0x300000>;
+ reg-names = "west", "east", "north", "south";
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-ranges = <&tlmm 0 0 176>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ wakeup-parent = <&pdc>;
+
+ qup-spi0-default-state {
+ pins = "gpio0", "gpio1", "gpio2", "gpio3";
+ function = "qup0";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
+ pcie1-default-state {
+ perst-pins {
+ pins = "gpio102";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ clkreq-pins {
+ pins = "gpio103";
+ function = "pci_e1";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ wake-pins {
+ pins = "gpio104";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm8250-lpass-lpi-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm8250-lpass-lpi-pinctrl.yaml
index 06efb1382876..bd45faa3f078 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sm8250-lpass-lpi-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm8250-lpass-lpi-pinctrl.yaml
@@ -4,22 +4,20 @@
$id: http://devicetree.org/schemas/pinctrl/qcom,sm8250-lpass-lpi-pinctrl.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Technologies, Inc. Low Power Audio SubSystem (LPASS)
- Low Power Island (LPI) TLMM block
+title: Qualcomm SM8250 SoC LPASS LPI TLMM
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-description: |
- This binding describes the Top Level Mode Multiplexer block found in the
- LPASS LPI IP on most Qualcomm SoCs
+description:
+ Top Level Mode Multiplexer pin controller in the Low Power Audio SubSystem
+ (LPASS) Low Power Island (LPI) of Qualcomm SM8250 SoC.
properties:
compatible:
const: qcom,sm8250-lpass-lpi-pinctrl
reg:
- minItems: 2
maxItems: 2
clocks:
@@ -34,7 +32,7 @@ properties:
gpio-controller: true
- '#gpio-cells':
+ "#gpio-cells":
description: Specifying the pin number and flags, as defined in
include/dt-bindings/gpio/gpio.h
const: 2
@@ -42,9 +40,17 @@ properties:
gpio-ranges:
maxItems: 1
-#PIN CONFIGURATION NODES
patternProperties:
- '-pins$':
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-sm8250-lpass-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-sm8250-lpass-state"
+ additionalProperties: false
+
+$defs:
+ qcom-sm8250-lpass-state:
type: object
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
@@ -88,13 +94,11 @@ patternProperties:
3: Reserved (No adjustments)
bias-pull-down: true
-
bias-pull-up: true
-
+ bias-bus-hold: true
bias-disable: true
-
+ input-enable: true
output-high: true
-
output-low: true
required:
@@ -104,7 +108,7 @@ patternProperties:
additionalProperties: false
allOf:
- - $ref: "pinctrl.yaml#"
+ - $ref: pinctrl.yaml#
required:
- compatible
@@ -112,7 +116,7 @@ required:
- clocks
- clock-names
- gpio-controller
- - '#gpio-cells'
+ - "#gpio-cells"
- gpio-ranges
additionalProperties: false
@@ -130,4 +134,28 @@ examples:
gpio-controller;
#gpio-cells = <2>;
gpio-ranges = <&lpi_tlmm 0 0 14>;
+
+ wsa-swr-active-state {
+ clk-pins {
+ pins = "gpio10";
+ function = "wsa_swr_clk";
+ drive-strength = <2>;
+ slew-rate = <1>;
+ bias-disable;
+ };
+
+ data-pins {
+ pins = "gpio11";
+ function = "wsa_swr_data";
+ drive-strength = <2>;
+ slew-rate = <1>;
+ };
+ };
+
+ tx-swr-sleep-clk-state {
+ pins = "gpio0";
+ function = "swr_tx_clk";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
};
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm8250-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm8250-pinctrl.yaml
index c44d02d28bc9..c80f3847ac08 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sm8250-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm8250-pinctrl.yaml
@@ -9,133 +9,109 @@ title: Qualcomm Technologies, Inc. SM8250 TLMM block
maintainers:
- Bjorn Andersson <bjorn.andersson@linaro.org>
-description: |
- This binding describes the Top Level Mode Multiplexer block found in the
- SM8250 platform.
+description:
+ Top Level Mode Multiplexer pin controller in the Qualcomm SM8250 SoC.
properties:
compatible:
const: qcom,sm8250-pinctrl
reg:
- minItems: 3
maxItems: 3
reg-names:
items:
- - const: "west"
- - const: "south"
- - const: "north"
-
- interrupts:
- description: Specifies the TLMM summary IRQ
- maxItems: 1
+ - const: west
+ - const: south
+ - const: north
+ interrupts: true
interrupt-controller: true
-
- '#interrupt-cells':
- description:
- Specifies the PIN numbers and Flags, as defined in defined in
- include/dt-bindings/interrupt-controller/irq.h
- const: 2
-
+ "#interrupt-cells": true
gpio-controller: true
+ "#gpio-cells": true
+ gpio-ranges: true
+ wakeup-parent: true
- '#gpio-cells':
- description: Specifying the pin number and flags, as defined in
- include/dt-bindings/gpio/gpio.h
- const: 2
-
- gpio-ranges:
- maxItems: 1
+ gpio-reserved-ranges:
+ minItems: 1
+ maxItems: 90
- wakeup-parent: true
+ gpio-line-names:
+ maxItems: 180
-#PIN CONFIGURATION NODES
patternProperties:
- '^.*$':
- if:
- type: object
- then:
- properties:
- pins:
- description:
- List of gpio pins affected by the properties specified in this
- subnode.
- items:
- oneOf:
- - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-7][0-9])$"
- - enum: [ sdc2_clk, sdc2_cmd, sdc2_data, ufs_reset ]
- minItems: 1
- maxItems: 36
-
- function:
- description:
- Specify the alternative function to be configured for the specified
- pins.
-
- enum: [ aoss_cti, atest, audio_ref, cam_mclk, cci_async, cci_i2c,
- cci_timer0, cci_timer1, cci_timer2, cci_timer3, cci_timer4, cri_trng,
- cri_trng0, cri_trng1, dbg_out, ddr_bist, ddr_pxi0, ddr_pxi1,
- ddr_pxi2, ddr_pxi3, dp_hot, dp_lcd, gcc_gp1, gcc_gp2, gcc_gp3, gpio,
- ibi_i3c, jitter_bist, lpass_slimbus, mdp_vsync, mdp_vsync0,
- mdp_vsync1, mdp_vsync2, mdp_vsync3, mi2s0_data0, mi2s0_data1,
- mi2s0_sck, mi2s0_ws, mi2s1_data0, mi2s1_data1, mi2s1_sck, mi2s1_ws,
- mi2s2_data0, mi2s2_data1, mi2s2_sck, mi2s2_ws, pci_e0, pci_e1,
- pci_e2, phase_flag, pll_bist, pll_bypassnl, pll_clk, pll_reset,
- pri_mi2s, prng_rosc, qdss_cti, qdss_gpio, qspi0, qspi1, qspi2, qspi3,
- qspi_clk, qspi_cs, qup0, qup1, qup10, qup11, qup12, qup13, qup14,
- qup15, qup16, qup17, qup18, qup19, qup2, qup3, qup4, qup5, qup6,
- qup7, qup8, qup9, qup_l4, qup_l5, qup_l6, sd_write, sdc40, sdc41,
- sdc42, sdc43, sdc4_clk, sdc4_cmd, sec_mi2s, sp_cmu, tgu_ch0, tgu_ch1,
- tgu_ch2, tgu_ch3, tsense_pwm1, tsense_pwm2, tsif0_clk, tsif0_data,
- tsif0_en, tsif0_error, tsif0_sync, tsif1_clk, tsif1_data, tsif1_en,
- tsif1_error, tsif1_sync, usb2phy_ac, usb_phy, vsense_trigger ]
-
- drive-strength:
- enum: [2, 4, 6, 8, 10, 12, 14, 16]
- default: 2
- description:
- Selects the drive strength for the specified pins, in mA.
-
- bias-pull-down: true
-
- bias-pull-up: true
-
- bias-disable: true
-
- output-high: true
-
- output-low: true
-
- required:
- - pins
-
- allOf:
- - $ref: "qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state"
- - if:
- properties:
- pins:
- pattern: "^gpio([0-9]|[1-9][0-9]|1[0-7][0-9])$"
- then:
- required:
- - function
-
- additionalProperties: false
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-sm8250-tlmm-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-sm8250-tlmm-state"
+ additionalProperties: false
+
+$defs:
+ qcom-sm8250-tlmm-state:
+ type: object
+ description:
+ Pinctrl node's client devices use subnodes for desired pin configuration.
+ Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
+
+ properties:
+ pins:
+ description:
+ List of gpio pins affected by the properties specified in this
+ subnode.
+ items:
+ oneOf:
+ - pattern: "^gpio([0-9]|[1-9][0-9]|1[0-7][0-9])$"
+ - enum: [ sdc2_clk, sdc2_cmd, sdc2_data, ufs_reset ]
+ minItems: 1
+ maxItems: 36
+
+ function:
+ description:
+ Specify the alternative function to be configured for the specified
+ pins.
+
+ enum: [ aoss_cti, atest, audio_ref, cam_mclk, cci_async, cci_i2c,
+ cci_timer0, cci_timer1, cci_timer2, cci_timer3, cci_timer4, cri_trng,
+ cri_trng0, cri_trng1, dbg_out, ddr_bist, ddr_pxi0, ddr_pxi1,
+ ddr_pxi2, ddr_pxi3, dp_hot, dp_lcd, gcc_gp1, gcc_gp2, gcc_gp3, gpio,
+ ibi_i3c, jitter_bist, lpass_slimbus, mdp_vsync, mdp_vsync0,
+ mdp_vsync1, mdp_vsync2, mdp_vsync3, mi2s0_data0, mi2s0_data1,
+ mi2s0_sck, mi2s0_ws, mi2s1_data0, mi2s1_data1, mi2s1_sck, mi2s1_ws,
+ mi2s2_data0, mi2s2_data1, mi2s2_sck, mi2s2_ws, pci_e0, pci_e1,
+ pci_e2, phase_flag, pll_bist, pll_bypassnl, pll_clk, pll_reset,
+ pri_mi2s, prng_rosc, qdss_cti, qdss_gpio, qspi0, qspi1, qspi2, qspi3,
+ qspi_clk, qspi_cs, qup0, qup1, qup10, qup11, qup12, qup13, qup14,
+ qup15, qup16, qup17, qup18, qup19, qup2, qup3, qup4, qup5, qup6,
+ qup7, qup8, qup9, qup_l4, qup_l5, qup_l6, sd_write, sdc40, sdc41,
+ sdc42, sdc43, sdc4_clk, sdc4_cmd, sec_mi2s, sp_cmu, tgu_ch0, tgu_ch1,
+ tgu_ch2, tgu_ch3, tsense_pwm1, tsense_pwm2, tsif0_clk, tsif0_data,
+ tsif0_en, tsif0_error, tsif0_sync, tsif1_clk, tsif1_data, tsif1_en,
+ tsif1_error, tsif1_sync, usb2phy_ac, usb_phy, vsense_trigger ]
+
+ bias-pull-down: true
+ bias-pull-up: true
+ bias-disable: true
+ drive-strength: true
+ input-enable: true
+ output-high: true
+ output-low: true
+
+ required:
+ - pins
+
+ additionalProperties: false
allOf:
- - $ref: "pinctrl.yaml#"
+ - $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
required:
- compatible
- reg
- reg-names
- - interrupts
- - interrupt-controller
- - '#interrupt-cells'
- - gpio-controller
- - '#gpio-cells'
- - gpio-ranges
additionalProperties: false
@@ -143,16 +119,16 @@ examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
pinctrl@1f00000 {
- compatible = "qcom,sm8250-pinctrl";
- reg = <0x0f100000 0x300000>,
- <0x0f500000 0x300000>,
- <0x0f900000 0x300000>;
- reg-names = "west", "south", "north";
- interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
- gpio-controller;
- #gpio-cells = <2>;
- interrupt-controller;
- #interrupt-cells = <2>;
- gpio-ranges = <&tlmm 0 0 180>;
- wakeup-parent = <&pdc>;
+ compatible = "qcom,sm8250-pinctrl";
+ reg = <0x0f100000 0x300000>,
+ <0x0f500000 0x300000>,
+ <0x0f900000 0x300000>;
+ reg-names = "west", "south", "north";
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&tlmm 0 0 180>;
+ wakeup-parent = <&pdc>;
};
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm8350-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm8350-tlmm.yaml
index 6ae5571f60da..0b1e4aa5819e 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sm8350-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm8350-tlmm.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/pinctrl/qcom,sm8350-pinctrl.yaml#
+$id: http://devicetree.org/schemas/pinctrl/qcom,sm8350-tlmm.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies, Inc. SM8350 TLMM block
@@ -9,12 +9,10 @@ title: Qualcomm Technologies, Inc. SM8350 TLMM block
maintainers:
- Vinod Koul <vkoul@kernel.org>
-description: |
- This binding describes the Top Level Mode Multiplexer (TLMM) block found
- in the SM8350 platform.
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm SM8350 SoC.
allOf:
- - $ref: "pinctrl.yaml#"
- $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
properties:
@@ -26,10 +24,10 @@ properties:
interrupts: true
interrupt-controller: true
- '#interrupt-cells': true
+ "#interrupt-cells": true
gpio-controller: true
gpio-reserved-ranges: true
- '#gpio-cells': true
+ "#gpio-cells": true
gpio-ranges: true
wakeup-parent: true
@@ -40,7 +38,7 @@ required:
additionalProperties: false
patternProperties:
- '-state$':
+ "-state$":
oneOf:
- $ref: "#/$defs/qcom-sm8350-tlmm-state"
- patternProperties:
@@ -54,6 +52,7 @@ $defs:
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
properties:
pins:
@@ -108,16 +107,6 @@ $defs:
required:
- pins
- allOf:
- - $ref: "qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state"
- - if:
- properties:
- pins:
- pattern: "^gpio([0-9]|[1-9][0-9]|1[0-9][0-9]|20[0-3])$"
- then:
- required:
- - function
-
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm8450-lpass-lpi-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm8450-lpass-lpi-pinctrl.yaml
index 3694795ec793..01a0a4a40ba5 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sm8450-lpass-lpi-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm8450-lpass-lpi-pinctrl.yaml
@@ -4,15 +4,14 @@
$id: http://devicetree.org/schemas/pinctrl/qcom,sm8450-lpass-lpi-pinctrl.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Qualcomm Technologies, Inc. Low Power Audio SubSystem (LPASS)
- Low Power Island (LPI) TLMM block
+title: Qualcomm SM8450 SoC LPASS LPI TLMM
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-description: |
- This binding describes the Top Level Mode Multiplexer block found in the
- LPASS LPI IP on most Qualcomm SoCs
+description:
+ Top Level Mode Multiplexer pin controller in the Low Power Audio SubSystem
+ (LPASS) Low Power Island (LPI) of Qualcomm SM8450 SoC.
properties:
compatible:
@@ -35,7 +34,7 @@ properties:
gpio-controller: true
- '#gpio-cells':
+ "#gpio-cells":
description: Specifying the pin number and flags, as defined in
include/dt-bindings/gpio/gpio.h
const: 2
@@ -43,9 +42,17 @@ properties:
gpio-ranges:
maxItems: 1
-#PIN CONFIGURATION NODES
patternProperties:
- '-pins$':
+ "-state$":
+ oneOf:
+ - $ref: "#/$defs/qcom-sm8450-lpass-state"
+ - patternProperties:
+ "-pins$":
+ $ref: "#/$defs/qcom-sm8450-lpass-state"
+ additionalProperties: false
+
+$defs:
+ qcom-sm8450-lpass-state:
type: object
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
@@ -58,7 +65,7 @@ patternProperties:
List of gpio pins affected by the properties specified in this
subnode.
items:
- pattern: "^gpio([0-9]|[1-2][0-9]])$"
+ pattern: "^gpio([0-9]|[1-2][0-9])$"
function:
enum: [ swr_tx_clk, swr_tx_data, swr_rx_clk, swr_rx_data,
@@ -114,7 +121,7 @@ required:
- clocks
- clock-names
- gpio-controller
- - '#gpio-cells'
+ - "#gpio-cells"
- gpio-ranges
additionalProperties: false
@@ -132,4 +139,28 @@ examples:
gpio-controller;
#gpio-cells = <2>;
gpio-ranges = <&lpi_tlmm 0 0 23>;
+
+ wsa-swr-active-state {
+ clk-pins {
+ pins = "gpio10";
+ function = "wsa_swr_clk";
+ drive-strength = <2>;
+ slew-rate = <1>;
+ bias-disable;
+ };
+
+ data-pins {
+ pins = "gpio11";
+ function = "wsa_swr_data";
+ drive-strength = <2>;
+ slew-rate = <1>;
+ };
+ };
+
+ tx-swr-sleep-clk-state {
+ pins = "gpio0";
+ function = "swr_tx_clk";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
};
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,sm8450-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,sm8450-tlmm.yaml
index 9cd97a467648..4a1d10d6c5e7 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,sm8450-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,sm8450-tlmm.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/pinctrl/qcom,sm8450-pinctrl.yaml#
+$id: http://devicetree.org/schemas/pinctrl/qcom,sm8450-tlmm.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm Technologies, Inc. SM8450 TLMM block
@@ -9,9 +9,8 @@ title: Qualcomm Technologies, Inc. SM8450 TLMM block
maintainers:
- Vinod Koul <vkoul@kernel.org>
-description: |
- This binding describes the Top Level Mode Multiplexer (TLMM) block found
- in the SM8450 platform.
+description:
+ Top Level Mode Multiplexer pin controller in Qualcomm SM8450 SoC.
allOf:
- $ref: /schemas/pinctrl/qcom,tlmm-common.yaml#
@@ -25,7 +24,7 @@ properties:
interrupts: true
interrupt-controller: true
- '#interrupt-cells': true
+ "#interrupt-cells": true
gpio-controller: true
gpio-reserved-ranges:
@@ -35,7 +34,7 @@ properties:
gpio-line-names:
maxItems: 209
- '#gpio-cells': true
+ "#gpio-cells": true
gpio-ranges: true
wakeup-parent: true
@@ -46,7 +45,7 @@ required:
additionalProperties: false
patternProperties:
- '-state$':
+ "-state$":
oneOf:
- $ref: "#/$defs/qcom-sm8450-tlmm-state"
- patternProperties:
@@ -60,6 +59,7 @@ $defs:
description:
Pinctrl node's client devices use subnodes for desired pin configuration.
Client device subnodes use below standard properties.
+ $ref: qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state
properties:
pins:
@@ -112,16 +112,6 @@ $defs:
required:
- pins
- allOf:
- - $ref: "qcom,tlmm-common.yaml#/$defs/qcom-tlmm-state"
- - if:
- properties:
- pins:
- pattern: "^gpio([0-9]|[1-9][0-9]|1[0-9][0-9]|20[0-9])$"
- then:
- required:
- - function
-
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,tlmm-common.yaml b/Documentation/devicetree/bindings/pinctrl/qcom,tlmm-common.yaml
index c88c8dcb69d9..e1354f0c64f8 100644
--- a/Documentation/devicetree/bindings/pinctrl/qcom,tlmm-common.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,tlmm-common.yaml
@@ -65,10 +65,6 @@ additionalProperties: true
$defs:
qcom-tlmm-state:
- allOf:
- - $ref: pincfg-node.yaml#
- - $ref: pinmux-node.yaml#
-
properties:
drive-strength:
enum: [2, 4, 6, 8, 10, 12, 14, 16]
@@ -82,5 +78,21 @@ $defs:
output-high: true
output-low: true
+ allOf:
+ - $ref: pincfg-node.yaml#
+ - $ref: pinmux-node.yaml#
+
+ - if:
+ properties:
+ pins:
+ items:
+ pattern: "^gpio"
+ then:
+ required:
+ - function
+ else:
+ properties:
+ function: false
+
additionalProperties: true
...
diff --git a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml
index b486f41df65f..d6539723f354 100644
--- a/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/rockchip,pinctrl.yaml
@@ -132,7 +132,7 @@ additionalProperties:
description:
Pin bank index.
- minimum: 0
- maximum: 10
+ maximum: 13
description:
Mux 0 means GPIO and mux 1 to N means
the specific device function.
diff --git a/Documentation/devicetree/bindings/pinctrl/semtech,sx1501q.yaml b/Documentation/devicetree/bindings/pinctrl/semtech,sx1501q.yaml
new file mode 100644
index 000000000000..0719c03d6f4b
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/semtech,sx1501q.yaml
@@ -0,0 +1,208 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright 2022 Linaro Ltd.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pinctrl/semtech,sx1501q.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Semtech SX150x GPIO expander
+
+maintainers:
+ - Neil Armstrong <neil.armstrong@linaro.org>
+
+properties:
+ compatible:
+ enum:
+ - semtech,sx1501q
+ - semtech,sx1502q
+ - semtech,sx1503q
+ - semtech,sx1504q
+ - semtech,sx1505q
+ - semtech,sx1506q
+ - semtech,sx1507q
+ - semtech,sx1508q
+ - semtech,sx1509q
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ '#interrupt-cells':
+ const: 2
+
+ interrupt-controller: true
+
+ '#gpio-cells':
+ const: 2
+
+ gpio-controller: true
+
+ semtech,probe-reset:
+ description: Will trigger a reset of the GPIO expander on probe
+ type: boolean
+
+patternProperties:
+ '-cfg$':
+ type: object
+ properties:
+ pins: true
+
+ bias-disable: true
+ bias-pull-up: true
+ bias-pull-down: true
+ bias-pull-pin-default: true
+ drive-push-pull: true
+ output-low: true
+ output-high: true
+ drive-open-drain: true
+
+ required:
+ - pins
+
+ allOf:
+ - $ref: "pincfg-node.yaml#"
+ - $ref: "pinmux-node.yaml#"
+ - if:
+ properties:
+ pins:
+ contains:
+ const: oscio
+ then:
+ properties:
+ bias-disable: false
+ bias-pull-up: false
+ bias-pull-down: false
+ bias-pull-pin-default: false
+ drive-open-drain: false
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - '#gpio-cells'
+ - gpio-controller
+
+allOf:
+ - $ref: "pinctrl.yaml#"
+ - if:
+ not:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - semtech,sx1507q
+ - semtech,sx1508q
+ - semtech,sx1509q
+ then:
+ properties:
+ semtech,probe-reset: false
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - semtech,sx1501q
+ - semtech,sx1504q
+ then:
+ patternProperties:
+ '-cfg$':
+ properties:
+ pins:
+ items:
+ pattern: '^gpio[0-3]$'
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - semtech,sx1502q
+ - semtech,sx1505q
+ then:
+ patternProperties:
+ '-cfg$':
+ properties:
+ pins:
+ items:
+ pattern: '^gpio[0-7]$'
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - semtech,sx1503q
+ - semtech,sx1506q
+ then:
+ patternProperties:
+ '-cfg$':
+ properties:
+ pins:
+ items:
+ pattern: '^(gpio[0-9]|gpio1[0-5])$'
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: semtech,sx1507q
+ then:
+ patternProperties:
+ '-cfg$':
+ properties:
+ pins:
+ items:
+ pattern: '^(oscio|gpio[0-3])$'
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: semtech,sx1508q
+ then:
+ patternProperties:
+ '-cfg$':
+ properties:
+ pins:
+ items:
+ pattern: '^(oscio|gpio[0-7])$'
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: semtech,sx1509q
+ then:
+ patternProperties:
+ '-cfg$':
+ properties:
+ pins:
+ items:
+ pattern: '^(oscio|gpio[0-9]|gpio1[0-5])$'
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c@1000 {
+ reg = <0x1000 0x80>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pinctrl@20 {
+ compatible = "semtech,sx1501q";
+ reg = <0x20>;
+
+ #gpio-cells = <2>;
+ #interrupt-cells = <2>;
+
+ interrupts = <16 IRQ_TYPE_EDGE_FALLING>;
+
+ gpio-controller;
+ interrupt-controller;
+
+ gpio1-cfg {
+ pins = "gpio1";
+ bias-pull-up;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
index 9d59208d83c1..eeb29b4ad4d1 100644
--- a/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
+++ b/Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.yaml
@@ -34,7 +34,9 @@ properties:
const: 1
ranges: true
- pins-are-numbered: true
+ pins-are-numbered:
+ $ref: /schemas/types.yaml#/definitions/flag
+ deprecated: true
hwlocks: true
interrupts:
@@ -206,7 +208,6 @@ required:
- '#address-cells'
- '#size-cells'
- ranges
- - pins-are-numbered
additionalProperties: false
@@ -220,7 +221,6 @@ examples:
#size-cells = <1>;
compatible = "st,stm32f429-pinctrl";
ranges = <0 0x40020000 0x3000>;
- pins-are-numbered;
gpioa: gpio@0 {
gpio-controller;
@@ -238,7 +238,6 @@ examples:
#size-cells = <1>;
compatible = "st,stm32f429-pinctrl";
ranges = <0 0x50020000 0x3000>;
- pins-are-numbered;
gpiob: gpio@1000 {
gpio-controller;
diff --git a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
index 5b4eda919911..633d49884019 100644
--- a/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
+++ b/Documentation/devicetree/bindings/power/qcom,rpmpd.yaml
@@ -28,15 +28,18 @@ properties:
- qcom,msm8998-rpmpd
- qcom,qcm2290-rpmpd
- qcom,qcs404-rpmpd
+ - qcom,qdu1000-rpmhpd
- qcom,sa8540p-rpmhpd
- qcom,sdm660-rpmpd
- qcom,sc7180-rpmhpd
- qcom,sc7280-rpmhpd
- qcom,sc8180x-rpmhpd
- qcom,sc8280xp-rpmhpd
+ - qcom,sdm670-rpmhpd
- qcom,sdm845-rpmhpd
- qcom,sdx55-rpmhpd
- qcom,sdx65-rpmhpd
+ - qcom,sm4250-rpmpd
- qcom,sm6115-rpmpd
- qcom,sm6125-rpmpd
- qcom,sm6350-rpmhpd
@@ -45,6 +48,7 @@ properties:
- qcom,sm8250-rpmhpd
- qcom,sm8350-rpmhpd
- qcom,sm8450-rpmhpd
+ - qcom,sm8550-rpmhpd
'#power-domain-cells':
const: 1
diff --git a/Documentation/devicetree/bindings/power/renesas,apmu.yaml b/Documentation/devicetree/bindings/power/renesas,apmu.yaml
index f2cc89e7f4e4..2b4d802ef4b2 100644
--- a/Documentation/devicetree/bindings/power/renesas,apmu.yaml
+++ b/Documentation/devicetree/bindings/power/renesas,apmu.yaml
@@ -34,10 +34,8 @@ properties:
maxItems: 1
cpus:
- $ref: /schemas/types.yaml#/definitions/phandle-array
- items:
- minItems: 1
- maxItems: 4
+ minItems: 1
+ maxItems: 4
description: |
Array of phandles pointing to CPU cores, which should match the order of
CPU cores used by the WUPCR and PSTR registers in the Advanced Power
diff --git a/Documentation/devicetree/bindings/power/supply/mt6360_charger.yaml b/Documentation/devicetree/bindings/power/supply/mt6360_charger.yaml
index b89b15a5bfa4..4c74cc78729e 100644
--- a/Documentation/devicetree/bindings/power/supply/mt6360_charger.yaml
+++ b/Documentation/devicetree/bindings/power/supply/mt6360_charger.yaml
@@ -26,6 +26,7 @@ properties:
type: object
description: OTG boost regulator.
$ref: /schemas/regulator/regulator.yaml#
+ unevaluatedProperties: false
required:
- compatible
@@ -39,7 +40,6 @@ examples:
richtek,vinovp-microvolt = <14500000>;
otg_vbus_regulator: usb-otg-vbus-regulator {
- regulator-compatible = "usb-otg-vbus";
regulator-name = "usb-otg-vbus";
regulator-min-microvolt = <4425000>;
regulator-max-microvolt = <5825000>;
diff --git a/Documentation/devicetree/bindings/power/wakeup-source.txt b/Documentation/devicetree/bindings/power/wakeup-source.txt
index cfd74659fbed..697333a56d5e 100644
--- a/Documentation/devicetree/bindings/power/wakeup-source.txt
+++ b/Documentation/devicetree/bindings/power/wakeup-source.txt
@@ -17,15 +17,14 @@ interrupt.
List of legacy properties and respective binding document
---------------------------------------------------------
-1. "enable-sdio-wakeup" Documentation/devicetree/bindings/mmc/mmc.txt
-2. "gpio-key,wakeup" Documentation/devicetree/bindings/input/gpio-keys{,-polled}.txt
-3. "has-tpo" Documentation/devicetree/bindings/rtc/rtc-opal.txt
-4. "linux,wakeup" Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt
+1. "gpio-key,wakeup" Documentation/devicetree/bindings/input/gpio-keys{,-polled}.txt
+2. "has-tpo" Documentation/devicetree/bindings/rtc/rtc-opal.txt
+3. "linux,wakeup" Documentation/devicetree/bindings/input/gpio-matrix-keypad.txt
Documentation/devicetree/bindings/mfd/tc3589x.txt
Documentation/devicetree/bindings/input/touchscreen/ads7846.txt
-5. "linux,keypad-wakeup" Documentation/devicetree/bindings/input/qcom,pm8xxx-keypad.txt
-6. "linux,input-wakeup" Documentation/devicetree/bindings/input/samsung-keypad.txt
-7. "nvidia,wakeup-source" Documentation/devicetree/bindings/input/nvidia,tegra20-kbc.txt
+4. "linux,keypad-wakeup" Documentation/devicetree/bindings/input/qcom,pm8xxx-keypad.txt
+5. "linux,input-wakeup" Documentation/devicetree/bindings/input/samsung-keypad.txt
+6. "nvidia,wakeup-source" Documentation/devicetree/bindings/input/nvidia,tegra20-kbc.txt
Examples
--------
diff --git a/Documentation/devicetree/bindings/pwm/allwinner,sun4i-a10-pwm.yaml b/Documentation/devicetree/bindings/pwm/allwinner,sun4i-a10-pwm.yaml
index 4cc3cc7c50be..66e400f2a3a4 100644
--- a/Documentation/devicetree/bindings/pwm/allwinner,sun4i-a10-pwm.yaml
+++ b/Documentation/devicetree/bindings/pwm/allwinner,sun4i-a10-pwm.yaml
@@ -25,7 +25,9 @@ properties:
- const: allwinner,sun8i-a83t-pwm
- const: allwinner,sun8i-h3-pwm
- items:
- - const: allwinner,sun8i-v3s-pwm
+ - enum:
+ - allwinner,suniv-f1c100s-pwm
+ - allwinner,sun8i-v3s-pwm
- const: allwinner,sun7i-a20-pwm
- items:
- const: allwinner,sun50i-a64-pwm
diff --git a/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.yaml b/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.yaml
index c8577bdf6c94..3afe1480df52 100644
--- a/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.yaml
+++ b/Documentation/devicetree/bindings/pwm/google,cros-ec-pwm.yaml
@@ -48,6 +48,7 @@ examples:
cros-ec@0 {
compatible = "google,cros-ec-spi";
reg = <0>;
+ interrupts = <101 0>;
cros_ec_pwm: pwm {
compatible = "google,cros-ec-pwm";
diff --git a/Documentation/devicetree/bindings/pwm/microchip,corepwm.yaml b/Documentation/devicetree/bindings/pwm/microchip,corepwm.yaml
index a7fae1772a81..cd8e9a8907f8 100644
--- a/Documentation/devicetree/bindings/pwm/microchip,corepwm.yaml
+++ b/Documentation/devicetree/bindings/pwm/microchip,corepwm.yaml
@@ -30,7 +30,9 @@ properties:
maxItems: 1
"#pwm-cells":
- const: 2
+ enum: [2, 3]
+ description:
+ The only flag supported by the controller is PWM_POLARITY_INVERTED.
microchip,sync-update-mask:
description: |
diff --git a/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt b/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
deleted file mode 100644
index 74c41e34c3b6..000000000000
--- a/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
+++ /dev/null
@@ -1,77 +0,0 @@
-Tegra SoC PWFM controller
-
-Required properties:
-- compatible: Must be:
- - "nvidia,tegra20-pwm": for Tegra20
- - "nvidia,tegra30-pwm", "nvidia,tegra20-pwm": for Tegra30
- - "nvidia,tegra114-pwm", "nvidia,tegra20-pwm": for Tegra114
- - "nvidia,tegra124-pwm", "nvidia,tegra20-pwm": for Tegra124
- - "nvidia,tegra132-pwm", "nvidia,tegra20-pwm": for Tegra132
- - "nvidia,tegra210-pwm", "nvidia,tegra20-pwm": for Tegra210
- - "nvidia,tegra186-pwm": for Tegra186
- - "nvidia,tegra194-pwm": for Tegra194
-- reg: physical base address and length of the controller's registers
-- #pwm-cells: should be 2. See pwm.yaml in this directory for a description of
- the cells format.
-- clocks: Must contain one entry, for the module clock.
- See ../clocks/clock-bindings.txt for details.
-- resets: Must contain an entry for each entry in reset-names.
- See ../reset/reset.txt for details.
-- reset-names: Must include the following entries:
- - pwm
-
-Optional properties:
-============================
-In some of the interface like PWM based regulator device, it is required
-to configure the pins differently in different states, especially in suspend
-state of the system. The configuration of pin is provided via the pinctrl
-DT node as detailed in the pinctrl DT binding document
- Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
-
-The PWM node will have following optional properties.
-pinctrl-names: Pin state names. Must be "default" and "sleep".
-pinctrl-0: phandle for the default/active state of pin configurations.
-pinctrl-1: phandle for the sleep state of pin configurations.
-
-Example:
-
- pwm: pwm@7000a000 {
- compatible = "nvidia,tegra20-pwm";
- reg = <0x7000a000 0x100>;
- #pwm-cells = <2>;
- clocks = <&tegra_car 17>;
- resets = <&tegra_car 17>;
- reset-names = "pwm";
- };
-
-
-Example with the pin configuration for suspend and resume:
-=========================================================
-Suppose pin PE7 (On Tegra210) interfaced with the regulator device and
-it requires PWM output to be tristated when system enters suspend.
-Following will be DT binding to achieve this:
-
-#include <dt-bindings/pinctrl/pinctrl-tegra.h>
-
- pinmux@700008d4 {
- pwm_active_state: pwm_active_state {
- pe7 {
- nvidia,pins = "pe7";
- nvidia,tristate = <TEGRA_PIN_DISABLE>;
- };
- };
-
- pwm_sleep_state: pwm_sleep_state {
- pe7 {
- nvidia,pins = "pe7";
- nvidia,tristate = <TEGRA_PIN_ENABLE>;
- };
- };
- };
-
- pwm@7000a000 {
- /* Mandatory PWM properties */
- pinctrl-names = "default", "sleep";
- pinctrl-0 = <&pwm_active_state>;
- pinctrl-1 = <&pwm_sleep_state>;
- };
diff --git a/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.yaml b/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.yaml
new file mode 100644
index 000000000000..739d3155dd32
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.yaml
@@ -0,0 +1,96 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pwm/nvidia,tegra20-pwm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Tegra PWFM controller
+
+maintainers:
+ - Thierry Reding <thierry.reding@gmail.com>
+ - Jon Hunter <jonathanh@nvidia.com>
+
+properties:
+ compatible:
+ oneOf:
+ - enum:
+ - nvidia,tegra20-pwm
+ - nvidia,tegra186-pwm
+
+ - items:
+ - enum:
+ - nvidia,tegra30-pwm
+ - nvidia,tegra114-pwm
+ - nvidia,tegra124-pwm
+ - nvidia,tegra132-pwm
+ - nvidia,tegra210-pwm
+ - enum:
+ - nvidia,tegra20-pwm
+
+ - items:
+ - const: nvidia,tegra194-pwm
+ - const: nvidia,tegra186-pwm
+
+ - items:
+ - const: nvidia,tegra234-pwm
+ - const: nvidia,tegra194-pwm
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ resets:
+ items:
+ - description: module reset
+
+ reset-names:
+ items:
+ - const: pwm
+
+ "#pwm-cells":
+ const: 2
+
+ pinctrl-names:
+ items:
+ - const: default
+ - const: sleep
+
+ pinctrl-0:
+ description: configuration for the default/active state
+
+ pinctrl-1:
+ description: configuration for the sleep state
+
+ operating-points-v2:
+ $ref: /schemas/types.yaml#/definitions/phandle
+
+ power-domains:
+ items:
+ - description: phandle to the core power domain
+
+allOf:
+ - $ref: pwm.yaml
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - resets
+ - reset-names
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/tegra20-car.h>
+
+ pwm: pwm@7000a000 {
+ compatible = "nvidia,tegra20-pwm";
+ reg = <0x7000a000 0x100>;
+ #pwm-cells = <2>;
+ clocks = <&tegra_car TEGRA20_CLK_PWM>;
+ resets = <&tegra_car 17>;
+ reset-names = "pwm";
+ };
diff --git a/Documentation/devicetree/bindings/regulator/google,cros-ec-regulator.yaml b/Documentation/devicetree/bindings/regulator/google,cros-ec-regulator.yaml
index 69e5402da761..0921f012c901 100644
--- a/Documentation/devicetree/bindings/regulator/google,cros-ec-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/google,cros-ec-regulator.yaml
@@ -41,6 +41,7 @@ examples:
reg = <0>;
#address-cells = <1>;
#size-cells = <0>;
+ interrupts = <99 0>;
regulator@0 {
compatible = "google,cros-ec-regulator";
diff --git a/Documentation/devicetree/bindings/regulator/max77650-regulator.yaml b/Documentation/devicetree/bindings/regulator/max77650-regulator.yaml
index ce0a4021ae7f..01b9775a92d1 100644
--- a/Documentation/devicetree/bindings/regulator/max77650-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/max77650-regulator.yaml
@@ -26,6 +26,7 @@ properties:
patternProperties:
"^regulator-(ldo|sbb[0-2])$":
$ref: "regulator.yaml#"
+ unevaluatedProperties: false
required:
- compatible
diff --git a/Documentation/devicetree/bindings/regulator/max8660.yaml b/Documentation/devicetree/bindings/regulator/max8660.yaml
index 9c038698f880..35792a927b03 100644
--- a/Documentation/devicetree/bindings/regulator/max8660.yaml
+++ b/Documentation/devicetree/bindings/regulator/max8660.yaml
@@ -24,8 +24,9 @@ properties:
type: object
patternProperties:
- "regulator-.+":
+ "^regulator-.+$":
$ref: "regulator.yaml#"
+ unevaluatedProperties: false
additionalProperties: false
@@ -43,31 +44,26 @@ examples:
regulators {
regulator-V3 {
- regulator-compatible= "V3(DCDC)";
regulator-min-microvolt = <725000>;
regulator-max-microvolt = <1800000>;
};
regulator-V4 {
- regulator-compatible= "V4(DCDC)";
regulator-min-microvolt = <725000>;
regulator-max-microvolt = <1800000>;
};
regulator-V5 {
- regulator-compatible= "V5(LDO)";
regulator-min-microvolt = <1700000>;
regulator-max-microvolt = <2000000>;
};
regulator-V6 {
- regulator-compatible= "V6(LDO)";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
};
regulator-V7 {
- regulator-compatible= "V7(LDO)";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <3300000>;
};
diff --git a/Documentation/devicetree/bindings/regulator/maxim,max77802.yaml b/Documentation/devicetree/bindings/regulator/maxim,max77802.yaml
index 71138c611b6c..b704f05ea454 100644
--- a/Documentation/devicetree/bindings/regulator/maxim,max77802.yaml
+++ b/Documentation/devicetree/bindings/regulator/maxim,max77802.yaml
@@ -77,7 +77,7 @@ patternProperties:
regulator-initial-mode: false
patternProperties:
- regulator-state-(standby|mem|disk):
+ "^regulator-state-(standby|mem|disk)$":
type: object
additionalProperties: true
properties:
diff --git a/Documentation/devicetree/bindings/regulator/mediatek,mt6357-regulator.yaml b/Documentation/devicetree/bindings/regulator/mediatek,mt6357-regulator.yaml
new file mode 100644
index 000000000000..6327bb2f6ee0
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/mediatek,mt6357-regulator.yaml
@@ -0,0 +1,294 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/mediatek,mt6357-regulator.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek MT6357 Regulators
+
+maintainers:
+ - Chen Zhong <chen.zhong@mediatek.com>
+ - Fabien Parent <fabien.parent@linaro.org>
+ - Alexandre Mergnat <amergnat@baylibre.com>
+
+description: |
+ The MT6357 PMIC provides 5 BUCK and 29 LDO.
+ Regulators and nodes are named according to the regulator type:
+ - buck-<name>
+ - ldo-<name>.
+ MT6357 regulators node should be sub node of the MT6397 MFD node.
+
+patternProperties:
+ "^buck-v(core|modem|pa|proc|s1)$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+ description:
+ Properties for single BUCK regulator.
+
+ required:
+ - regulator-name
+ - regulator-min-microvolt
+ - regulator-max-microvolt
+
+ "^ldo-v(camio18|aud28|aux18|io18|io28|rf12|rf18|cn18|cn28|fe28)$":
+ type: object
+ $ref: fixed-regulator.yaml#
+ unevaluatedProperties: false
+ description:
+ Properties for single fixed LDO regulator.
+
+ required:
+ - regulator-name
+ - regulator-min-microvolt
+ - regulator-max-microvolt
+
+ "^ldo-v(efuse|ibr|ldo28|mch|cama|camd|cn33-bt|cn33-wifi)$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+ description:
+ Properties for single LDO regulator.
+
+ required:
+ - regulator-name
+ - regulator-min-microvolt
+ - regulator-max-microvolt
+
+ "^ldo-v(xo22|emc|mc|sim1|sim2|sram-others|sram-proc|dram|usb33)$":
+ type: object
+ $ref: regulator.yaml#
+ unevaluatedProperties: false
+ description:
+ Properties for single LDO regulator.
+
+ required:
+ - regulator-name
+ - regulator-min-microvolt
+ - regulator-max-microvolt
+
+additionalProperties: false
+
+examples:
+ - |
+ pmic {
+ regulators {
+ mt6357_vproc_reg: buck-vproc {
+ regulator-name = "vproc";
+ regulator-min-microvolt = <518750>;
+ regulator-max-microvolt = <1312500>;
+ regulator-ramp-delay = <6250>;
+ regulator-enable-ramp-delay = <220>;
+ regulator-always-on;
+ };
+ mt6357_vcore_reg: buck-vcore {
+ regulator-name = "vcore";
+ regulator-min-microvolt = <518750>;
+ regulator-max-microvolt = <1312500>;
+ regulator-ramp-delay = <6250>;
+ regulator-enable-ramp-delay = <220>;
+ regulator-always-on;
+ };
+ mt6357_vmodem_reg: buck-vmodem {
+ regulator-name = "vmodem";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1193750>;
+ regulator-ramp-delay = <6250>;
+ regulator-enable-ramp-delay = <220>;
+ };
+ mt6357_vs1_reg: buck-vs1 {
+ regulator-name = "vs1";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <2200000>;
+ regulator-ramp-delay = <12500>;
+ regulator-enable-ramp-delay = <220>;
+ regulator-always-on;
+ };
+ mt6357_vpa_reg: buck-vpa {
+ regulator-name = "vpa";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <3650000>;
+ regulator-ramp-delay = <50000>;
+ regulator-enable-ramp-delay = <220>;
+ };
+ mt6357_vfe28_reg: ldo-vfe28 {
+ compatible = "regulator-fixed";
+ regulator-name = "vfe28";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <264>;
+ };
+ mt6357_vxo22_reg: ldo-vxo22 {
+ regulator-name = "vxo22";
+ regulator-min-microvolt = <2200000>;
+ regulator-max-microvolt = <2400000>;
+ regulator-enable-ramp-delay = <110>;
+ };
+ mt6357_vrf18_reg: ldo-vrf18 {
+ compatible = "regulator-fixed";
+ regulator-name = "vrf18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <110>;
+ };
+ mt6357_vrf12_reg: ldo-vrf12 {
+ compatible = "regulator-fixed";
+ regulator-name = "vrf12";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-enable-ramp-delay = <110>;
+ };
+ mt6357_vefuse_reg: ldo-vefuse {
+ regulator-name = "vefuse";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <264>;
+ };
+ mt6357_vcn33_bt_reg: ldo-vcn33-bt {
+ regulator-name = "vcn33-bt";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3500000>;
+ regulator-enable-ramp-delay = <264>;
+ };
+ mt6357_vcn33_wifi_reg: ldo-vcn33-wifi {
+ regulator-name = "vcn33-wifi";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3500000>;
+ regulator-enable-ramp-delay = <264>;
+ };
+ mt6357_vcn28_reg: ldo-vcn28 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcn28";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <264>;
+ };
+ mt6357_vcn18_reg: ldo-vcn18 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcn18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <264>;
+ };
+ mt6357_vcama_reg: ldo-vcama {
+ regulator-name = "vcama";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <264>;
+ };
+ mt6357_vcamd_reg: ldo-vcamd {
+ regulator-name = "vcamd";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <264>;
+ };
+ mt6357_vcamio_reg: ldo-vcamio18 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcamio";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <264>;
+ };
+ mt6357_vldo28_reg: ldo-vldo28 {
+ regulator-name = "vldo28";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-enable-ramp-delay = <264>;
+ };
+ mt6357_vsram_others_reg: ldo-vsram-others {
+ regulator-name = "vsram-others";
+ regulator-min-microvolt = <518750>;
+ regulator-max-microvolt = <1312500>;
+ regulator-ramp-delay = <6250>;
+ regulator-enable-ramp-delay = <110>;
+ regulator-always-on;
+ };
+ mt6357_vsram_proc_reg: ldo-vsram-proc {
+ regulator-name = "vsram-proc";
+ regulator-min-microvolt = <518750>;
+ regulator-max-microvolt = <1312500>;
+ regulator-ramp-delay = <6250>;
+ regulator-enable-ramp-delay = <110>;
+ regulator-always-on;
+ };
+ mt6357_vaux18_reg: ldo-vaux18 {
+ compatible = "regulator-fixed";
+ regulator-name = "vaux18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <264>;
+ };
+ mt6357_vaud28_reg: ldo-vaud28 {
+ compatible = "regulator-fixed";
+ regulator-name = "vaud28";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <264>;
+ };
+ mt6357_vio28_reg: ldo-vio28 {
+ compatible = "regulator-fixed";
+ regulator-name = "vio28";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <264>;
+ };
+ mt6357_vio18_reg: ldo-vio18 {
+ compatible = "regulator-fixed";
+ regulator-name = "vio18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <264>;
+ regulator-always-on;
+ };
+ mt6357_vdram_reg: ldo-vdram {
+ regulator-name = "vdram";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-enable-ramp-delay = <3300>;
+ };
+ mt6357_vmc_reg: ldo-vmc {
+ regulator-name = "vmc";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <44>;
+ };
+ mt6357_vmch_reg: ldo-vmch {
+ regulator-name = "vmch";
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <44>;
+ };
+ mt6357_vemc_reg: ldo-vemc {
+ regulator-name = "vemc";
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <44>;
+ regulator-always-on;
+ };
+ mt6357_vsim1_reg: ldo-vsim1 {
+ regulator-name = "vsim1";
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <3100000>;
+ regulator-enable-ramp-delay = <264>;
+ };
+ mt6357_vsim2_reg: ldo-vsim2 {
+ regulator-name = "vsim2";
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <3100000>;
+ regulator-enable-ramp-delay = <264>;
+ };
+ mt6357_vibr_reg: ldo-vibr {
+ regulator-name = "vibr";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <44>;
+ };
+ mt6357_vusb33_reg: ldo-vusb33 {
+ regulator-name = "vusb33";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3100000>;
+ regulator-enable-ramp-delay = <264>;
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/regulator/mt6360-regulator.yaml b/Documentation/devicetree/bindings/regulator/mt6360-regulator.yaml
index a462d99a25cc..8a0931dc2f30 100644
--- a/Documentation/devicetree/bindings/regulator/mt6360-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/mt6360-regulator.yaml
@@ -27,9 +27,11 @@ properties:
patternProperties:
"^buck[12]$":
$ref: "regulator.yaml#"
+ unevaluatedProperties: false
"^ldo[123567]$":
$ref: "regulator.yaml#"
+ unevaluatedProperties: false
required:
- compatible
@@ -44,7 +46,6 @@ examples:
compatible = "mediatek,mt6360-regulator";
LDO_VIN3-supply = <&BUCK2>;
buck1 {
- regulator-compatible = "BUCK1";
regulator-name = "mt6360,buck1";
regulator-min-microvolt = <300000>;
regulator-max-microvolt = <1300000>;
@@ -53,7 +54,6 @@ examples:
MT6360_OPMODE_ULP>;
};
BUCK2: buck2 {
- regulator-compatible = "BUCK2";
regulator-name = "mt6360,buck2";
regulator-min-microvolt = <300000>;
regulator-max-microvolt = <1300000>;
@@ -62,7 +62,6 @@ examples:
MT6360_OPMODE_ULP>;
};
ldo6 {
- regulator-compatible = "LDO6";
regulator-name = "mt6360,ldo6";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <2100000>;
@@ -70,7 +69,6 @@ examples:
MT6360_OPMODE_LP>;
};
ldo7 {
- regulator-compatible = "LDO7";
regulator-name = "mt6360,ldo7";
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <2100000>;
@@ -78,15 +76,13 @@ examples:
MT6360_OPMODE_LP>;
};
ldo1 {
- regulator-compatible = "LDO1";
regulator-name = "mt6360,ldo1";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3600000>;
regulator-allowed-modes = <MT6360_OPMODE_NORMAL
MT6360_OPMODE_LP>;
};
- ldo2 {
- regulator-compatible = "LDO2";
+ ldo2 {
regulator-name = "mt6360,ldo2";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3600000>;
@@ -94,7 +90,6 @@ examples:
MT6360_OPMODE_LP>;
};
ldo3 {
- regulator-compatible = "LDO3";
regulator-name = "mt6360,ldo3";
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <3600000>;
@@ -102,7 +97,6 @@ examples:
MT6360_OPMODE_LP>;
};
ldo5 {
- regulator-compatible = "LDO5";
regulator-name = "mt6360,ldo5";
regulator-min-microvolt = <2700000>;
regulator-max-microvolt = <3600000>;
diff --git a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml
index 90c3bda31c23..297a75069f60 100644
--- a/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/qcom,rpmh-regulator.yaml
@@ -47,6 +47,7 @@ description: |
For PM8350, smps1 - smps12, ldo1 - ldo10
For PM8350C, smps1 - smps10, ldo1 - ldo13, bob
For PM8450, smps1 - smps6, ldo1 - ldo4
+ For PM8550, smps1 - smps6, ldo1 - ldo17, bob1 - bob2
For PM8998, smps1 - smps13, ldo1 - ldo28, lvs1 - lvs2
For PMI8998, bob
For PMR735A, smps1 - smps3, ldo1 - ldo7
@@ -70,6 +71,9 @@ properties:
- qcom,pm8350-rpmh-regulators
- qcom,pm8350c-rpmh-regulators
- qcom,pm8450-rpmh-regulators
+ - qcom,pm8550-rpmh-regulators
+ - qcom,pm8550ve-rpmh-regulators
+ - qcom,pm8550vs-rpmh-regulators
- qcom,pm8998-rpmh-regulators
- qcom,pmg1110-rpmh-regulators
- qcom,pmi8998-rpmh-regulators
@@ -83,7 +87,7 @@ properties:
RPMh resource name suffix used for the regulators found
on this PMIC.
$ref: /schemas/types.yaml#/definitions/string
- enum: [a, b, c, d, e, f, h, k]
+ enum: [a, b, c, d, e, f, g, h, k]
qcom,always-wait-for-ack:
description: |
@@ -107,7 +111,7 @@ properties:
regulator-allow-set-load: ["regulator-allowed-modes"]
patternProperties:
- "^(smps|ldo|lvs)[0-9]+$":
+ "^(smps|ldo|lvs|bob)[0-9]+$":
type: object
$ref: "regulator.yaml#"
description: smps/ldo regulator nodes(s).
@@ -303,6 +307,24 @@ allOf:
properties:
compatible:
enum:
+ - qcom,pm8550-rpmh-regulators
+ - qcom,pm8550ve-rpmh-regulators
+ - qcom,pm8550vs-rpmh-regulators
+ then:
+ properties:
+ vdd-l2-l13-l14-supply: true
+ vdd-l5-l16-supply: true
+ vdd-l6-l7-supply: true
+ vdd-l8-l9-supply: true
+ patternProperties:
+ "^vdd-l([1-4]|1[0-7])-supply$": true
+ "^vdd-s[1-6]-supply$": true
+ "^vdd-bob[1-2]-supply$": true
+
+ - if:
+ properties:
+ compatible:
+ enum:
- qcom,pm8998-rpmh-regulators
then:
properties:
@@ -412,9 +434,8 @@ examples:
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
regulator-allow-set-load;
};
@@ -431,9 +452,8 @@ examples:
bob {
regulator-min-microvolt = <3312000>;
regulator-max-microvolt = <3600000>;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_AUTO
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_AUTO
+ RPMH_REGULATOR_MODE_HPM>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>;
};
};
diff --git a/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.yaml b/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.yaml
index 961eed51912c..8c45f53212b1 100644
--- a/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/qcom,smd-rpm-regulator.yaml
@@ -71,6 +71,8 @@ description:
For pmi8998, bob
+ For pmr735a, s1, s2, s3, l1, l2, l3, l4, l5, l6, l7
+
For pms405, s1, s2, s3, s4, s5, l1, l2, l3, l4, l5, l6, l7, l8, l9, l10, l11,
l12, l13
@@ -98,6 +100,7 @@ properties:
- qcom,rpm-pma8084-regulators
- qcom,rpm-pmi8994-regulators
- qcom,rpm-pmi8998-regulators
+ - qcom,rpm-pmr735a-regulators
- qcom,rpm-pms405-regulators
patternProperties:
diff --git a/Documentation/devicetree/bindings/regulator/regulator-output.yaml b/Documentation/devicetree/bindings/regulator/regulator-output.yaml
new file mode 100644
index 000000000000..078b37a1a71a
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/regulator-output.yaml
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+
+$id: http://devicetree.org/schemas/regulator/regulator-output.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Regulator output connector
+
+maintainers:
+ - Zev Weiss <zev@bewilderbeest.net>
+
+description: |
+ This describes a power output connector supplied by a regulator,
+ such as a power outlet on a power distribution unit (PDU). The
+ connector may be standalone or merely one channel or set of pins
+ within a ganged physical connector carrying multiple independent
+ power outputs.
+
+properties:
+ compatible:
+ const: regulator-output
+
+ vout-supply:
+ description:
+ Phandle of the regulator supplying the output.
+
+required:
+ - compatible
+ - vout-supply
+
+additionalProperties: false
+
+examples:
+ - |
+ output {
+ compatible = "regulator-output";
+ vout-supply = <&output_reg>;
+ };
diff --git a/Documentation/devicetree/bindings/regulator/regulator.yaml b/Documentation/devicetree/bindings/regulator/regulator.yaml
index 6e8aa9eed3aa..53b81d8a2d41 100644
--- a/Documentation/devicetree/bindings/regulator/regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/regulator.yaml
@@ -231,7 +231,7 @@ patternProperties:
".*-supply$":
description: Input supply phandle(s) for this node
- regulator-state-(standby|mem|disk):
+ "^regulator-state-(standby|mem|disk)$":
type: object
description:
sub-nodes for regulator state in Standby, Suspend-to-RAM, and
diff --git a/Documentation/devicetree/bindings/regulator/richtek,rt6190.yaml b/Documentation/devicetree/bindings/regulator/richtek,rt6190.yaml
new file mode 100644
index 000000000000..29f7d3d5d658
--- /dev/null
+++ b/Documentation/devicetree/bindings/regulator/richtek,rt6190.yaml
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/regulator/richtek,rt6190.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Richtek RT6190 4-Switch BuckBoost controller
+
+maintainers:
+ - ChiYuan Huang <cy_huang@richtek.com>
+
+description: |
+ The RT6190 is 4-Switch BuckBoost controller designed for converting input
+ voltage to output voltage that can be equal to, higher or lower than input
+ voltage. It operates with wide input voltage range from 4.5V to 36V, and
+ the output voltage can be set from 3V to 36V by external FB pin. It's commonly
+ used for the application like as BuckBoost bus supply, docking station and USB
+ power delivery product.
+
+ Datasheet is available at
+ https://www.richtek.com/assets/product_file/RT6190/DS6190-02.pdf
+
+allOf:
+ - $ref: regulator.yaml#
+
+properties:
+ compatible:
+ enum:
+ - richtek,rt6190
+
+ reg:
+ maxItems: 1
+
+ enable-gpios:
+ maxItems: 1
+
+ wakeup-source: true
+
+ interrupts:
+ maxItems: 1
+
+ regulator-allowed-modes:
+ description: |
+ buck allowed operating mode
+ 0: PSM mode (light load Power Saving Mode)
+ 1: FCCM mode (Forced-CCM mode)
+ maxItems: 2
+ items:
+ enum: [0, 1]
+
+required:
+ - compatible
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ regulator@2c {
+ compatible = "richtek,rt6190";
+ reg = <0x2c>;
+ wakeup-source;
+ interrupts-extended = <&gpio26 0 IRQ_TYPE_LEVEL_LOW>;
+ enable-gpios = <&gpio26 1 GPIO_ACTIVE_HIGH>;
+ regulator-name = "richtek,rt6190-buckboost";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <32000000>;
+ regulator-min-microamp = <306000>;
+ regulator-max-microamp = <12114000>;
+ regulator-allowed-modes = <0 1>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/regulator/rohm,bd9576-regulator.yaml b/Documentation/devicetree/bindings/regulator/rohm,bd9576-regulator.yaml
index 7cb74cc8c5d9..54be194bb244 100644
--- a/Documentation/devicetree/bindings/regulator/rohm,bd9576-regulator.yaml
+++ b/Documentation/devicetree/bindings/regulator/rohm,bd9576-regulator.yaml
@@ -21,7 +21,7 @@ description: |
regulator-voutl1, regulator-vouts1
patternProperties:
- "regulator-.+":
+ "^regulator-.+$":
type: object
description:
Properties for single regulator.
diff --git a/Documentation/devicetree/bindings/regulator/ti,tps65219.yaml b/Documentation/devicetree/bindings/regulator/ti,tps65219.yaml
index 78be79930fda..78e64521d401 100644
--- a/Documentation/devicetree/bindings/regulator/ti,tps65219.yaml
+++ b/Documentation/devicetree/bindings/regulator/ti,tps65219.yaml
@@ -51,13 +51,6 @@ properties:
where the board has a button wired to the pin and triggers
an interrupt on pressing it.
-patternProperties:
- "^buck[1-3]-supply$":
- description: Input supply phandle of one regulator.
-
- "^ldo[1-4]-supply$":
- description: Input supply phandle of one regulator.
-
regulators:
type: object
description: |
@@ -82,6 +75,13 @@ patternProperties:
additionalProperties: false
+patternProperties:
+ "^buck[1-3]-supply$":
+ description: Input supply phandle of one regulator.
+
+ "^ldo[1-4]-supply$":
+ description: Input supply phandle of one regulator.
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/riscv/cpus.yaml b/Documentation/devicetree/bindings/riscv/cpus.yaml
index 90a7cabf58fe..83ad177a9043 100644
--- a/Documentation/devicetree/bindings/riscv/cpus.yaml
+++ b/Documentation/devicetree/bindings/riscv/cpus.yaml
@@ -28,17 +28,20 @@ properties:
oneOf:
- items:
- enum:
- - sifive,rocket0
+ - andestech,ax45mp
+ - canaan,k210
- sifive,bullet0
- sifive,e5
- sifive,e7
- sifive,e71
- - sifive,u74-mc
- - sifive,u54
- - sifive,u74
+ - sifive,rocket0
- sifive,u5
+ - sifive,u54
- sifive,u7
- - canaan,k210
+ - sifive,u74
+ - sifive,u74-mc
+ - thead,c906
+ - thead,c910
- const: riscv
- items:
- enum:
diff --git a/Documentation/devicetree/bindings/riscv/starfive.yaml b/Documentation/devicetree/bindings/riscv/starfive.yaml
index 5b36243fd674..5d3fcee52d59 100644
--- a/Documentation/devicetree/bindings/riscv/starfive.yaml
+++ b/Documentation/devicetree/bindings/riscv/starfive.yaml
@@ -19,7 +19,9 @@ properties:
compatible:
oneOf:
- items:
- - const: beagle,beaglev-starlight-jh7100-r0
+ - enum:
+ - beagle,beaglev-starlight-jh7100-r0
+ - starfive,visionfive-v1
- const: starfive,jh7100
additionalProperties: true
diff --git a/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml b/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml
index 30eaa62e1aed..74f75f669e77 100644
--- a/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml
+++ b/Documentation/devicetree/bindings/serial/fsl-lpuart.yaml
@@ -32,6 +32,9 @@ properties:
- fsl,imx8qm-lpuart
- fsl,imx8dxl-lpuart
- const: fsl,imx8qxp-lpuart
+ - items:
+ - const: fsl,imxrt1050-lpuart
+ - const: fsl,imxrt1170-lpuart
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt b/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt
index d24e2bc444be..12e4b4260b40 100644
--- a/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt
+++ b/Documentation/devicetree/bindings/soc/mediatek/pwrap.txt
@@ -30,6 +30,7 @@ Required properties in pwrap device node.
"mediatek,mt8186-pwrap" for MT8186 SoCs
"mediatek,mt8188-pwrap", "mediatek,mt8195-pwrap" for MT8188 SoCs
"mediatek,mt8195-pwrap" for MT8195 SoCs
+ "mediatek,mt8365-pwrap" for MT8365 SoCs
"mediatek,mt8516-pwrap" for MT8516 SoCs
- interrupts: IRQ for pwrap in SOC
- reg-names: "pwrap" is required; "pwrap-bridge" is optional.
@@ -39,6 +40,8 @@ Required properties in pwrap device node.
- clock-names: Must include the following entries:
"spi": SPI bus clock
"wrap": Main module clock
+ "sys": Optional system module clock
+ "tmr": Optional timer module clock
- clocks: Must contain an entry for each entry in clock-names.
Optional properities:
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml
index a4eeb7e158e5..98d087cf4fc0 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,aoss-qmp.yaml
@@ -28,12 +28,14 @@ properties:
- qcom,sc7180-aoss-qmp
- qcom,sc7280-aoss-qmp
- qcom,sc8180x-aoss-qmp
+ - qcom,sc8280xp-aoss-qmp
- qcom,sdm845-aoss-qmp
- qcom,sm6350-aoss-qmp
- qcom,sm8150-aoss-qmp
- qcom,sm8250-aoss-qmp
- qcom,sm8350-aoss-qmp
- qcom,sm8450-aoss-qmp
+ - qcom,sm8550-aoss-qmp
- const: qcom,aoss-qmp
reg:
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,apr-services.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,apr-services.yaml
new file mode 100644
index 000000000000..290555426c39
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,apr-services.yaml
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/qcom/qcom,apr-services.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm APR/GPR services shared parts
+
+maintainers:
+ - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+description:
+ Common parts of a static service in Qualcomm APR/GPR (Asynchronous/Generic
+ Packet Router).
+
+properties:
+ reg:
+ minimum: 1
+ maximum: 13
+ description: |
+ APR Service ID
+ 3 = DSP Core Service
+ 4 = Audio Front End Service.
+ 5 = Voice Stream Manager Service.
+ 6 = Voice processing manager.
+ 7 = Audio Stream Manager Service.
+ 8 = Audio Device Manager Service.
+ 9 = Multimode voice manager.
+ 10 = Core voice stream.
+ 11 = Core voice processor.
+ 12 = Ultrasound stream manager.
+ 13 = Listen stream manager.
+ GPR Service ID
+ 1 = Audio Process Manager Service
+ 2 = Proxy Resource Manager Service.
+ 3 = AMDB Service.
+ 4 = Voice processing manager.
+
+ qcom,protection-domain:
+ $ref: /schemas/types.yaml#/definitions/string-array
+ description: |
+ Protection domain service name and path for APR service
+ possible values are::
+ "avs/audio", "msm/adsp/audio_pd".
+ "kernel/elf_loader", "msm/modem/wlan_pd".
+ "tms/servreg", "msm/adsp/audio_pd".
+ "tms/servreg", "msm/modem/wlan_pd".
+ "tms/servreg", "msm/slpi/sensor_pd".
+
+required:
+ - reg
+ - qcom,protection-domain
+
+additionalProperties: true
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml
index f47491aab3b1..a6bc3197d5dd 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml
@@ -17,6 +17,7 @@ description: |
properties:
compatible:
enum:
+ - qcom,apr
- qcom,apr-v2
- qcom,gpr
@@ -58,8 +59,7 @@ properties:
qcom,glink-channels:
$ref: /schemas/types.yaml#/definitions/string-array
description: Channel name used for the communication
- items:
- - const: apr_audio_svc
+ maxItems: 1
qcom,intents:
$ref: /schemas/types.yaml#/definitions/uint32-array
@@ -81,12 +81,13 @@ properties:
'#size-cells':
const: 0
-#APR/GPR Services
patternProperties:
"^service@[1-9a-d]$":
type: object
+ $ref: /schemas/soc/qcom/qcom,apr-services.yaml
+ additionalProperties: true
description:
- APR/GPR node's client devices use subnodes for desired static port services.
+ APR/GPR static port services.
properties:
compatible:
@@ -98,99 +99,6 @@ patternProperties:
- qcom,q6apm
- qcom,q6prm
- reg:
- minimum: 1
- maximum: 13
- description:
- APR Service ID
- 3 = DSP Core Service
- 4 = Audio Front End Service.
- 5 = Voice Stream Manager Service.
- 6 = Voice processing manager.
- 7 = Audio Stream Manager Service.
- 8 = Audio Device Manager Service.
- 9 = Multimode voice manager.
- 10 = Core voice stream.
- 11 = Core voice processor.
- 12 = Ultrasound stream manager.
- 13 = Listen stream manager.
- GPR Service ID
- 1 = Audio Process Manager Service
- 2 = Proxy Resource Manager Service.
- 3 = AMDB Service.
- 4 = Voice processing manager.
-
- clock-controller:
- $ref: /schemas/sound/qcom,q6dsp-lpass-clocks.yaml#
- description: Qualcomm DSP LPASS clock controller
- unevaluatedProperties: false
-
- dais:
- type: object
- oneOf:
- - $ref: /schemas/sound/qcom,q6apm-dai.yaml#
- - $ref: /schemas/sound/qcom,q6dsp-lpass-ports.yaml#
- - $ref: /schemas/sound/qcom,q6asm-dais.yaml#
- unevaluatedProperties: false
- description: Qualcomm DSP audio ports
-
- routing:
- type: object
- $ref: /schemas/sound/qcom,q6adm-routing.yaml#
- unevaluatedProperties: false
- description: Qualcomm DSP LPASS audio routing
-
- qcom,protection-domain:
- $ref: /schemas/types.yaml#/definitions/string-array
- description: protection domain service name and path for apr service
- possible values are
- "avs/audio", "msm/adsp/audio_pd".
- "kernel/elf_loader", "msm/modem/wlan_pd".
- "tms/servreg", "msm/adsp/audio_pd".
- "tms/servreg", "msm/modem/wlan_pd".
- "tms/servreg", "msm/slpi/sensor_pd".
-
- allOf:
- - if:
- properties:
- compatible:
- enum:
- - qcom,q6afe
- then:
- properties:
- dais:
- properties:
- compatible:
- const: qcom,q6afe-dais
-
- - if:
- properties:
- compatible:
- enum:
- - qcom,q6apm
- then:
- properties:
- dais:
- properties:
- compatible:
- enum:
- - qcom,q6apm-dais
- - qcom,q6apm-lpass-dais
-
- - if:
- properties:
- compatible:
- enum:
- - qcom,q6asm
- then:
- properties:
- dais:
- properties:
- compatible:
- const: qcom,q6asm-dais
-
- additionalProperties: false
-
required:
- compatible
- qcom,domain
@@ -203,7 +111,15 @@ allOf:
- qcom,gpr
then:
properties:
+ qcom,glink-channels:
+ items:
+ - const: adsp_apps
power-domains: false
+ else:
+ properties:
+ qcom,glink-channels:
+ items:
+ - const: apr_audio_svc
- if:
required:
@@ -227,31 +143,35 @@ examples:
apr {
compatible = "qcom,apr-v2";
qcom,domain = <APR_DOMAIN_ADSP>;
+ qcom,glink-channels = "apr_audio_svc";
+ qcom,intents = <512 20>;
#address-cells = <1>;
#size-cells = <0>;
q6core: service@3 {
- compatible = "qcom,q6core";
- reg = <APR_SVC_ADSP_CORE>;
- qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
- };
-
- q6afe: service@4 {
- compatible = "qcom,q6afe";
- reg = <APR_SVC_AFE>;
- qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
- };
-
- q6asm: service@7 {
- compatible = "qcom,q6asm";
- reg = <APR_SVC_ASM>;
- qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+ compatible = "qcom,q6core";
+ reg = <APR_SVC_ADSP_CORE>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
};
- q6adm: service@8 {
- compatible = "qcom,q6adm";
- reg = <APR_SVC_ADM>;
- qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+ service@4 {
+ compatible = "qcom,q6afe";
+ reg = <APR_SVC_AFE>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+
+ clock-controller {
+ compatible = "qcom,q6afe-clocks";
+ #clock-cells = <2>;
+ };
+
+ dais {
+ compatible = "qcom,q6afe-dais";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #sound-dai-cells = <1>;
+ /* ... */
+ };
+ /* ... */
};
};
@@ -260,12 +180,25 @@ examples:
gpr {
compatible = "qcom,gpr";
qcom,domain = <GPR_DOMAIN_ID_ADSP>;
+ qcom,glink-channels = "adsp_apps";
+ qcom,intents = <512 20>;
#address-cells = <1>;
#size-cells = <0>;
service@1 {
- compatible = "qcom,q6apm";
- reg = <GPR_APM_MODULE_IID>;
- qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+ compatible = "qcom,q6apm";
+ reg = <GPR_APM_MODULE_IID>;
+ #sound-dai-cells = <0>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+
+ dais {
+ compatible = "qcom,q6apm-dais";
+ iommus = <&apps_smmu 0x1801 0x0>;
+ };
+
+ bedais {
+ compatible = "qcom,q6apm-lpass-dais";
+ #sound-dai-cells = <1>;
+ };
};
};
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,rpmh-rsc.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,rpmh-rsc.yaml
index 4a50f1d27724..b246500d3d5d 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,rpmh-rsc.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,rpmh-rsc.yaml
@@ -99,6 +99,9 @@ properties:
- const: drv-2
- const: drv-3
+ power-domains:
+ maxItems: 1
+
bcm-voter:
$ref: /schemas/interconnect/qcom,bcm-voter.yaml#
@@ -151,6 +154,7 @@ examples:
<SLEEP_TCS 3>,
<WAKE_TCS 3>,
<CONTROL_TCS 1>;
+ power-domains = <&CLUSTER_PD>;
};
- |
@@ -197,6 +201,7 @@ examples:
<SLEEP_TCS 3>,
<WAKE_TCS 3>,
<CONTROL_TCS 0>;
+ power-domains = <&CLUSTER_PD>;
clock-controller {
compatible = "qcom,sm8350-rpmh-clk";
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml
index 09d5bfa920f2..11c0f4dd797c 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.yaml
@@ -4,7 +4,7 @@
$id: "http://devicetree.org/schemas/soc/qcom/qcom,smd-rpm.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
-title: Qualcomm Resource Power Manager (RPM) over SMD
+title: Qualcomm Resource Power Manager (RPM) over SMD/GLINK
description: |
This driver is used to interface with the Resource Power Manager (RPM) found
@@ -12,9 +12,9 @@ description: |
to vote for state of the system resources, such as clocks, regulators and bus
frequencies.
- The SMD information for the RPM edge should be filled out. See qcom,smd.yaml
- for the required edge properties. All SMD related properties will reside
- within the RPM node itself.
+ The SMD or GLINK information for the RPM edge should be filled out. See
+ qcom,smd.yaml for the required edge properties. All SMD/GLINK related
+ properties will reside within the RPM node itself.
The RPM exposes resources to its subnodes. The rpm_requests node must be
present and this subnode may contain children that designate regulator
@@ -45,6 +45,7 @@ properties:
- qcom,rpm-sdm660
- qcom,rpm-sm6115
- qcom,rpm-sm6125
+ - qcom,rpm-sm6375
- qcom,rpm-qcm2290
- qcom,rpm-qcs404
@@ -55,12 +56,23 @@ properties:
power-controller:
$ref: /schemas/power/qcom,rpmpd.yaml#
+ qcom,glink-channels:
+ $ref: /schemas/types.yaml#/definitions/string-array
+ description: Channel name used for the RPM communication
+ items:
+ - const: rpm_requests
+
qcom,smd-channels:
$ref: /schemas/types.yaml#/definitions/string-array
description: Channel name used for the RPM communication
items:
- const: rpm_requests
+patternProperties:
+ "^regulators(-[01])?$":
+ $ref: /schemas/regulator/qcom,smd-rpm-regulator.yaml#
+ unevaluatedProperties: false
+
if:
properties:
compatible:
@@ -69,10 +81,18 @@ if:
- qcom,rpm-apq8084
- qcom,rpm-msm8916
- qcom,rpm-msm8974
+ - qcom,rpm-msm8976
- qcom,rpm-msm8953
then:
+ properties:
+ qcom,glink-channels: false
required:
- qcom,smd-channels
+else:
+ properties:
+ qcom,smd-channels: false
+ required:
+ - qcom,glink-channels
required:
- compatible
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.yaml
index 795bd8cd4104..58500529b90f 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.yaml
@@ -60,7 +60,7 @@ properties:
Two identifiers of the inbound and outbound smem items used for this edge.
patternProperties:
- "^master-kernel|slave-kernel|ipa-ap-to-modem|ipa-modem-to-ap$":
+ "^master-kernel|slave-kernel|ipa-ap-to-modem|ipa-modem-to-ap|wlan-ap-to-wpss|wlan-wpss-to-ap$":
type: object
description:
Each SMP2P pair contain a set of inbound and outbound entries, these are
diff --git a/Documentation/devicetree/bindings/soc/qcom/qcom,spm.yaml b/Documentation/devicetree/bindings/soc/qcom/qcom,spm.yaml
index f433e6e0a19f..38818c37c3ea 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qcom,spm.yaml
+++ b/Documentation/devicetree/bindings/soc/qcom/qcom,spm.yaml
@@ -24,8 +24,11 @@ properties:
- qcom,msm8998-silver-saw2-v4.1-l2
- qcom,msm8909-saw2-v3.0-cpu
- qcom,msm8916-saw2-v3.0-cpu
+ - qcom,msm8939-saw2-v3.0-cpu
- qcom,msm8226-saw2-v2.1-cpu
- qcom,msm8974-saw2-v2.1-cpu
+ - qcom,msm8976-gold-saw2-v2.3-l2
+ - qcom,msm8976-silver-saw2-v2.3-l2
- qcom,apq8084-saw2-v2.1-cpu
- qcom,apq8064-saw2-v1.1-cpu
- const: qcom,saw2
diff --git a/Documentation/devicetree/bindings/soc/renesas/renesas,r9a09g011-sys.yaml b/Documentation/devicetree/bindings/soc/renesas/renesas,r9a09g011-sys.yaml
new file mode 100644
index 000000000000..1cac3cb5226c
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/renesas/renesas,r9a09g011-sys.yaml
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/soc/renesas/renesas,r9a09g011-sys.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RZ/V2M System Configuration (SYS)
+
+maintainers:
+ - Geert Uytterhoeven <geert+renesas@glider.be>
+
+description:
+ The RZ/V2M-alike SYS (System Configuration) controls the overall
+ configuration of the LSI and supports the following functions,
+ - Bank address settings for DMAC
+ - Bank address settings of the units for ICB
+ - ETHER AxCACHE[1] (C bit) control function
+ - RAMA initialization control
+ - MD[7:0] pin monitoring
+ - LSI version
+ - PCIe related settings
+ - WDT stop control
+ - Temperature sensor (TSU) monitor
+
+properties:
+ compatible:
+ const: renesas,r9a09g011-sys
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ sys: system-controller@a3f03000 {
+ compatible = "renesas,r9a09g011-sys";
+ reg = <0xa3f03000 0x400>;
+ };
diff --git a/Documentation/devicetree/bindings/arm/renesas.yaml b/Documentation/devicetree/bindings/soc/renesas/renesas.yaml
index f51464a08aff..2789022b52eb 100644
--- a/Documentation/devicetree/bindings/arm/renesas.yaml
+++ b/Documentation/devicetree/bindings/soc/renesas/renesas.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
%YAML 1.2
---
-$id: http://devicetree.org/schemas/arm/renesas.yaml#
+$id: http://devicetree.org/schemas/soc/renesas/renesas.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas SH-Mobile, R-Mobile, and R-Car Platform
@@ -431,11 +431,12 @@ properties:
- renesas,rzn1d400-db # RZN1D-DB (RZ/N1D Demo Board for the RZ/N1D 400 pins package)
- const: renesas,r9a06g032
- - description: RZ/G2UL (R9A07G043)
+ - description: RZ/Five and RZ/G2UL (R9A07G043)
items:
- enum:
- renesas,smarc-evk # SMARC EVK
- enum:
+ - renesas,r9a07g043f01 # RZ/Five
- renesas,r9a07g043u11 # RZ/G2UL Type-1
- renesas,r9a07g043u12 # RZ/G2UL Type-2
- const: renesas,r9a07g043
diff --git a/Documentation/devicetree/bindings/sound/adi,adau1372.yaml b/Documentation/devicetree/bindings/sound/adi,adau1372.yaml
index 59f7c60a14ba..044bcd370d49 100644
--- a/Documentation/devicetree/bindings/sound/adi,adau1372.yaml
+++ b/Documentation/devicetree/bindings/sound/adi,adau1372.yaml
@@ -8,12 +8,15 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices ADAU1372 CODEC
maintainers:
- - Alexandre Belloni <alexandre.belloni@bootlin.om>
+ - Alexandre Belloni <alexandre.belloni@bootlin.com>
description: |
Analog Devices ADAU1372 four inputs and two outputs codec.
https://www.analog.com/media/en/technical-documentation/data-sheets/ADAU1372.pdf
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -42,7 +45,7 @@ required:
- clocks
- clock-names
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/adi,adau1977.yaml b/Documentation/devicetree/bindings/sound/adi,adau1977.yaml
index 847b83398d3d..dba3023a45e5 100644
--- a/Documentation/devicetree/bindings/sound/adi,adau1977.yaml
+++ b/Documentation/devicetree/bindings/sound/adi,adau1977.yaml
@@ -51,6 +51,7 @@ required:
- AVDD-supply
allOf:
+ - $ref: dai-common.yaml#
- $ref: /schemas/spi/spi-peripheral-props.yaml#
unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/sound/adi,adau7118.yaml b/Documentation/devicetree/bindings/sound/adi,adau7118.yaml
index fb78967ee17b..12f60507aed7 100644
--- a/Documentation/devicetree/bindings/sound/adi,adau7118.yaml
+++ b/Documentation/devicetree/bindings/sound/adi,adau7118.yaml
@@ -15,6 +15,9 @@ description: |
standalone mode.
https://www.analog.com/media/en/technical-documentation/data-sheets/ADAU7118.pdf
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -57,7 +60,7 @@ required:
- iovdd-supply
- dvdd-supply
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/ak4375.yaml b/Documentation/devicetree/bindings/sound/ak4375.yaml
index 5f0fc584bb38..587598e122c6 100644
--- a/Documentation/devicetree/bindings/sound/ak4375.yaml
+++ b/Documentation/devicetree/bindings/sound/ak4375.yaml
@@ -9,6 +9,9 @@ title: AK4375 DAC and headphones amplifier
maintainers:
- Vincent Knecht <vincent.knecht@mailoo.org>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
const: asahi-kasei,ak4375
@@ -35,7 +38,7 @@ required:
- avdd-supply
- tvdd-supply
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/ak4613.yaml b/Documentation/devicetree/bindings/sound/ak4613.yaml
index aa8a258a9f1c..010574645e6a 100644
--- a/Documentation/devicetree/bindings/sound/ak4613.yaml
+++ b/Documentation/devicetree/bindings/sound/ak4613.yaml
@@ -9,6 +9,9 @@ title: AK4613 I2C transmitter
maintainers:
- Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
const: asahi-kasei,ak4613
@@ -35,7 +38,7 @@ required:
- compatible
- reg
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/ak4642.yaml b/Documentation/devicetree/bindings/sound/ak4642.yaml
index 48a5b2c3934e..437fe5d7cae1 100644
--- a/Documentation/devicetree/bindings/sound/ak4642.yaml
+++ b/Documentation/devicetree/bindings/sound/ak4642.yaml
@@ -9,6 +9,9 @@ title: AK4642 I2C transmitter
maintainers:
- Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -37,7 +40,7 @@ required:
- compatible
- reg
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml
index 292fcb643999..78273647f766 100644
--- a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml
+++ b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml
@@ -102,6 +102,7 @@ required:
- dma-names
allOf:
+ - $ref: dai-common.yaml#
- if:
properties:
compatible:
@@ -228,7 +229,7 @@ allOf:
- Mic
- Speaker
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml
index dd30881ad2f5..739114fb6549 100644
--- a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml
+++ b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml
@@ -61,6 +61,7 @@ properties:
maxItems: 1
allOf:
+ - $ref: dai-common.yaml#
- if:
properties:
compatible:
@@ -128,7 +129,7 @@ required:
- dmas
- dma-names
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml
index 68c84e29ce57..8108c564dd78 100644
--- a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml
+++ b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml
@@ -54,6 +54,7 @@ properties:
maxItems: 1
allOf:
+ - $ref: dai-common.yaml#
- if:
properties:
compatible:
@@ -104,7 +105,7 @@ required:
- dmas
- dma-names
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun50i-h6-dmic.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun50i-h6-dmic.yaml
index 2f12cabe4c71..763b876047c1 100644
--- a/Documentation/devicetree/bindings/sound/allwinner,sun50i-h6-dmic.yaml
+++ b/Documentation/devicetree/bindings/sound/allwinner,sun50i-h6-dmic.yaml
@@ -9,9 +9,17 @@ title: Allwinner H6 DMIC
maintainers:
- Ban Tao <fengzheng923@gmail.com>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
- const: allwinner,sun50i-h6-dmic
+ oneOf:
+ - items:
+ - enum:
+ - allwinner,sun20i-d1-dmic
+ - const: allwinner,sun50i-h6-dmic
+ - const: allwinner,sun50i-h6-dmic
"#sound-dai-cells":
const: 0
@@ -54,7 +62,7 @@ required:
- dma-names
- resets
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun8i-a33-codec.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun8i-a33-codec.yaml
index 4eb11a8e622b..63eadc4200ac 100644
--- a/Documentation/devicetree/bindings/sound/allwinner,sun8i-a33-codec.yaml
+++ b/Documentation/devicetree/bindings/sound/allwinner,sun8i-a33-codec.yaml
@@ -10,6 +10,9 @@ maintainers:
- Chen-Yu Tsai <wens@csie.org>
- Maxime Ripard <mripard@kernel.org>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
"#sound-dai-cells":
minimum: 0
@@ -49,7 +52,7 @@ required:
- clocks
- clock-names
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/amlogic,aiu.yaml b/Documentation/devicetree/bindings/sound/amlogic,aiu.yaml
index 0705f91199a0..6350dfc0a926 100644
--- a/Documentation/devicetree/bindings/sound/amlogic,aiu.yaml
+++ b/Documentation/devicetree/bindings/sound/amlogic,aiu.yaml
@@ -10,7 +10,7 @@ maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
allOf:
- - $ref: name-prefix.yaml#
+ - $ref: dai-common.yaml#
properties:
$nodename:
diff --git a/Documentation/devicetree/bindings/sound/amlogic,g12a-toacodec.yaml b/Documentation/devicetree/bindings/sound/amlogic,g12a-toacodec.yaml
index 77469a45bb7a..23f82bb89750 100644
--- a/Documentation/devicetree/bindings/sound/amlogic,g12a-toacodec.yaml
+++ b/Documentation/devicetree/bindings/sound/amlogic,g12a-toacodec.yaml
@@ -10,7 +10,7 @@ maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
allOf:
- - $ref: name-prefix.yaml#
+ - $ref: dai-common.yaml#
properties:
$nodename:
diff --git a/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml b/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml
index 580a3d040abc..5f5cccdbeb34 100644
--- a/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml
+++ b/Documentation/devicetree/bindings/sound/amlogic,t9015.yaml
@@ -10,7 +10,7 @@ maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
allOf:
- - $ref: name-prefix.yaml#
+ - $ref: dai-common.yaml#
properties:
$nodename:
diff --git a/Documentation/devicetree/bindings/sound/apple,mca.yaml b/Documentation/devicetree/bindings/sound/apple,mca.yaml
index d5dc92b5b654..40e3a202f443 100644
--- a/Documentation/devicetree/bindings/sound/apple,mca.yaml
+++ b/Documentation/devicetree/bindings/sound/apple,mca.yaml
@@ -14,6 +14,9 @@ description: |
maintainers:
- Martin Povišer <povik+lin@cutebit.org>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
items:
@@ -106,7 +109,7 @@ required:
- power-domains
- '#sound-dai-cells'
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/awinic,aw8738.yaml b/Documentation/devicetree/bindings/sound/awinic,aw8738.yaml
index dce86dafe382..bc6c6b172238 100644
--- a/Documentation/devicetree/bindings/sound/awinic,aw8738.yaml
+++ b/Documentation/devicetree/bindings/sound/awinic,aw8738.yaml
@@ -15,7 +15,7 @@ description:
function (primarily the power limit for the amplifier).
allOf:
- - $ref: name-prefix.yaml#
+ - $ref: dai-common.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs35l41.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs35l41.yaml
index 51d815d0c696..82062d80d700 100644
--- a/Documentation/devicetree/bindings/sound/cirrus,cs35l41.yaml
+++ b/Documentation/devicetree/bindings/sound/cirrus,cs35l41.yaml
@@ -146,6 +146,7 @@ required:
- "#sound-dai-cells"
allOf:
+ - $ref: dai-common.yaml#
- if:
properties:
cirrus,boost-type:
@@ -171,7 +172,7 @@ allOf:
cirrus,gpio1-src-select:
enum: [1]
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs35l45.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs35l45.yaml
index 184a1344ea76..88a0ca474c3d 100644
--- a/Documentation/devicetree/bindings/sound/cirrus,cs35l45.yaml
+++ b/Documentation/devicetree/bindings/sound/cirrus,cs35l45.yaml
@@ -14,6 +14,9 @@ description: |
CS35L45 is a Boosted Mono Class D Amplifier with DSP
Speaker Protection and Adaptive Battery Management.
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -52,7 +55,7 @@ required:
- reg
- "#sound-dai-cells"
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml b/Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml
index 963a871e74da..422cbf38bfdb 100644
--- a/Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml
+++ b/Documentation/devicetree/bindings/sound/cirrus,cs42l51.yaml
@@ -9,6 +9,9 @@ title: CS42L51 audio codec DT bindings
maintainers:
- Olivier Moysan <olivier.moysan@foss.st.com>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
const: cirrus,cs42l51
@@ -46,7 +49,7 @@ required:
- reg
- "#sound-dai-cells"
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/cirrus,lochnagar.yaml b/Documentation/devicetree/bindings/sound/cirrus,lochnagar.yaml
index cea612d3d4a7..52f024f5302a 100644
--- a/Documentation/devicetree/bindings/sound/cirrus,lochnagar.yaml
+++ b/Documentation/devicetree/bindings/sound/cirrus,lochnagar.yaml
@@ -24,6 +24,9 @@ description: |
This binding must be part of the Lochnagar MFD binding:
[1] ../mfd/cirrus,lochnagar.yaml
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -49,4 +52,4 @@ required:
- clocks
- clock-names
-additionalProperties: false
+unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/sound/cirrus,madera.yaml b/Documentation/devicetree/bindings/sound/cirrus,madera.yaml
index 23138ddcb62d..014d4eaa8793 100644
--- a/Documentation/devicetree/bindings/sound/cirrus,madera.yaml
+++ b/Documentation/devicetree/bindings/sound/cirrus,madera.yaml
@@ -22,6 +22,9 @@ description: |
The properties are all contained in the parent MFD node.
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
'#sound-dai-cells':
description:
diff --git a/Documentation/devicetree/bindings/sound/name-prefix.yaml b/Documentation/devicetree/bindings/sound/dai-common.yaml
index 2fe57f87ac52..d858eea73ed7 100644
--- a/Documentation/devicetree/bindings/sound/name-prefix.yaml
+++ b/Documentation/devicetree/bindings/sound/dai-common.yaml
@@ -1,10 +1,10 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/sound/name-prefix.yaml#
+$id: http://devicetree.org/schemas/sound/dai-common.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Component sound name prefix
+title: Digital Audio Interface Common Properties
maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
@@ -18,4 +18,6 @@ properties:
sink/source names may use this property to prepend the name of their
sinks/sources with the provided string.
+ '#sound-dai-cells': true
+
additionalProperties: true
diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.yaml b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.yaml
index f46c66bc6b2d..7735e08d35ba 100644
--- a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.yaml
+++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.yaml
@@ -167,6 +167,7 @@ required:
- interrupt-names
allOf:
+ - $ref: dai-common.yaml#
- if:
properties:
opmode:
@@ -177,7 +178,7 @@ allOf:
required:
- tdm-slots
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/dmic-codec.yaml b/Documentation/devicetree/bindings/sound/dmic-codec.yaml
new file mode 100644
index 000000000000..59ef0cf6b6e5
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/dmic-codec.yaml
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: GPL-2.0
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/dmic-codec.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Generic PDM Digital microphone (DMIC) codec
+
+maintainers:
+ - Arnaud Pouliquen <arnaud.pouliquen@foss.st.com>
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ const: dmic-codec
+
+ '#sound-dai-cells':
+ const: 0
+
+ dmicen-gpios:
+ description: GPIO specifier for DMIC to control start and stop
+ maxItems: 1
+
+ num-channels:
+ description: Number of microphones on this DAI
+ $ref: /schemas/types.yaml#/definitions/uint32
+ minimum: 1
+ maximum: 8
+ default: 8
+
+ modeswitch-delay-ms:
+ description: Delay (in ms) to complete DMIC mode switch
+
+ wakeup-delay-ms:
+ description: Delay (in ms) after enabling the DMIC
+
+required:
+ - compatible
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ dmic {
+ compatible = "dmic-codec";
+ dmicen-gpios = <&gpio4 3 GPIO_ACTIVE_HIGH>;
+ num-channels = <1>;
+ wakeup-delay-ms = <50>;
+ modeswitch-delay-ms = <35>;
+ };
+...
diff --git a/Documentation/devicetree/bindings/sound/dmic.txt b/Documentation/devicetree/bindings/sound/dmic.txt
deleted file mode 100644
index 32e871037269..000000000000
--- a/Documentation/devicetree/bindings/sound/dmic.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-Device-Tree bindings for Digital microphone (DMIC) codec
-
-This device support generic PDM digital microphone.
-
-Required properties:
- - compatible: should be "dmic-codec".
-
-Optional properties:
- - dmicen-gpios: GPIO specifier for dmic to control start and stop
- - num-channels: Number of microphones on this DAI
- - wakeup-delay-ms: Delay (in ms) after enabling the DMIC
- - modeswitch-delay-ms: Delay (in ms) to complete DMIC mode switch
-
-Example node:
-
- dmic_codec: dmic@0 {
- compatible = "dmic-codec";
- dmicen-gpios = <&gpio4 3 GPIO_ACTIVE_HIGH>;
- num-channels = <1>;
- wakeup-delay-ms <50>;
- modeswitch-delay-ms <35>;
- };
diff --git a/Documentation/devicetree/bindings/sound/everest,es8316.yaml b/Documentation/devicetree/bindings/sound/everest,es8316.yaml
index 3b752bba748b..d9f8f0c7f6bb 100644
--- a/Documentation/devicetree/bindings/sound/everest,es8316.yaml
+++ b/Documentation/devicetree/bindings/sound/everest,es8316.yaml
@@ -10,6 +10,9 @@ maintainers:
- Daniel Drake <drake@endlessm.com>
- Katsuhiro Suzuki <katsuhiro@katsuster.net>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
const: everest,es8316
@@ -33,7 +36,7 @@ required:
- reg
- "#sound-dai-cells"
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/fsl,micfil.yaml b/Documentation/devicetree/bindings/sound/fsl,micfil.yaml
index 64d57758ee67..4b99a18c79a0 100644
--- a/Documentation/devicetree/bindings/sound/fsl,micfil.yaml
+++ b/Documentation/devicetree/bindings/sound/fsl,micfil.yaml
@@ -18,6 +18,7 @@ properties:
enum:
- fsl,imx8mm-micfil
- fsl,imx8mp-micfil
+ - fsl,imx93-micfil
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
index d370c98a62c7..e847611a85f7 100644
--- a/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
+++ b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
@@ -11,8 +11,11 @@ maintainers:
description: |
fsl_rpmsg is a virtual audio device. Mapping to real hardware devices
- are SAI, DMA controlled by Cortex M core. What we see from Linux
- side is a device which provides audio service by rpmsg channel.
+ are SAI, MICFIL, DMA controlled by Cortex M core. What we see from
+ Linux side is a device which provides audio service by rpmsg channel.
+ We can create different sound cards which access different hardwares
+ such as SAI, MICFIL, .etc through building rpmsg channels between
+ Cortex-A and Cortex-M.
properties:
compatible:
@@ -85,6 +88,16 @@ properties:
This is a boolean property. If present, the receiving function
will be enabled.
+ fsl,rpmsg-channel-name:
+ $ref: /schemas/types.yaml#/definitions/string
+ description: |
+ A string property to assign rpmsg channel this sound card sits on.
+ This property can be omitted if there is only one sound card and it sits
+ on "rpmsg-audio-channel".
+ enum:
+ - rpmsg-audio-channel
+ - rpmsg-micfil-channel
+
required:
- compatible
- model
@@ -107,3 +120,22 @@ examples:
<&clk IMX8MN_AUDIO_PLL2_OUT>;
clock-names = "ipg", "mclk", "dma", "pll8k", "pll11k";
};
+
+ - |
+ #include <dt-bindings/clock/imx8mm-clock.h>
+
+ rpmsg_micfil: audio-controller {
+ compatible = "fsl,imx8mm-rpmsg-audio";
+ model = "micfil-audio";
+ fsl,rpmsg-channel-name = "rpmsg-micfil-channel";
+ fsl,enable-lpa;
+ fsl,rpmsg-in;
+ clocks = <&clk IMX8MM_CLK_PDM_IPG>,
+ <&clk IMX8MM_CLK_PDM_ROOT>,
+ <&clk IMX8MM_CLK_SDMA3_ROOT>,
+ <&clk IMX8MM_AUDIO_PLL1_OUT>,
+ <&clk IMX8MM_AUDIO_PLL2_OUT>;
+ clock-names = "ipg", "mclk", "dma", "pll8k", "pll11k";
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/sound/fsl,sai.yaml b/Documentation/devicetree/bindings/sound/fsl,sai.yaml
index 70c4111d59c7..5b28d2d51327 100644
--- a/Documentation/devicetree/bindings/sound/fsl,sai.yaml
+++ b/Documentation/devicetree/bindings/sound/fsl,sai.yaml
@@ -18,14 +18,12 @@ description: |
properties:
compatible:
oneOf:
- - enum:
- - fsl,vf610-sai
- - fsl,imx6sx-sai
- - fsl,imx6ul-sai
- - fsl,imx7ulp-sai
- - fsl,imx8mq-sai
- - fsl,imx8qm-sai
- - fsl,imx8ulp-sai
+ - items:
+ - enum:
+ - fsl,imx6ul-sai
+ - fsl,imx7d-sai
+ - const: fsl,imx6sx-sai
+
- items:
- enum:
- fsl,imx8mm-sai
@@ -33,19 +31,18 @@ properties:
- fsl,imx8mp-sai
- const: fsl,imx8mq-sai
+ - items:
+ - enum:
+ - fsl,imx6sx-sai
+ - fsl,imx7ulp-sai
+ - fsl,imx8mq-sai
+ - fsl,imx8qm-sai
+ - fsl,imx8ulp-sai
+ - fsl,vf610-sai
+
reg:
maxItems: 1
- interrupts:
- items:
- - description: receive and transmit interrupt
-
- dmas:
- maxItems: 2
-
- dma-names:
- maxItems: 2
-
clocks:
items:
- description: The ipg clock for register access
@@ -67,7 +64,7 @@ properties:
- const: mclk3
- const: pll8k
- const: pll11k
- minItems: 4
+ minItems: 5
- items:
- const: bus
- const: mclk1
@@ -77,19 +74,37 @@ properties:
- const: pll11k
minItems: 4
- lsb-first:
- description: |
- Configures whether the LSB or the MSB is transmitted
- first for the fifo data. If this property is absent,
- the MSB is transmitted first as default, or the LSB
- is transmitted first.
- type: boolean
+ dmas:
+ maxItems: 2
+
+ dma-names:
+ maxItems: 2
+
+ interrupts:
+ items:
+ - description: receive and transmit interrupt
big-endian:
description: |
required if all the SAI registers are big-endian rather than little-endian.
type: boolean
+ fsl,dataline:
+ $ref: /schemas/types.yaml#/definitions/uint32-matrix
+ description: |
+ Configure the dataline. It has 3 value for each configuration
+ maxItems: 16
+ items:
+ items:
+ - description: format Default(0), I2S(1) or PDM(2)
+ enum: [0, 1, 2]
+ - description: dataline mask for 'rx'
+ - description: dataline mask for 'tx'
+
+ fsl,sai-mclk-direction-output:
+ description: SAI will output the SAI MCLK clock.
+ type: boolean
+
fsl,sai-synchronous-rx:
description: |
SAI will work in the synchronous mode (sync Tx with Rx) which means
@@ -108,31 +123,24 @@ properties:
of transmitter.
type: boolean
- fsl,dataline:
- $ref: /schemas/types.yaml#/definitions/uint32-matrix
- description: |
- Configure the dataline. It has 3 value for each configuration
- maxItems: 16
- items:
- items:
- - description: format Default(0), I2S(1) or PDM(2)
- enum: [0, 1, 2]
- - description: dataline mask for 'rx'
- - description: dataline mask for 'tx'
-
- fsl,sai-mclk-direction-output:
- description: SAI will output the SAI MCLK clock.
- type: boolean
-
fsl,shared-interrupt:
description: Interrupt is shared with other modules.
type: boolean
+ lsb-first:
+ description: |
+ Configures whether the LSB or the MSB is transmitted
+ first for the fifo data. If this property is absent,
+ the MSB is transmitted first as default, or the LSB
+ is transmitted first.
+ type: boolean
+
"#sound-dai-cells":
const: 0
description: optional, some dts node didn't add it.
allOf:
+ - $ref: dai-common.yaml#
- if:
properties:
compatible:
@@ -168,13 +176,13 @@ allOf:
required:
- compatible
- reg
- - interrupts
- - dmas
- - dma-names
- clocks
- clock-names
+ - dmas
+ - dma-names
+ - interrupts
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml b/Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml
index dea293f403d9..1434f4433738 100644
--- a/Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml
+++ b/Documentation/devicetree/bindings/sound/google,cros-ec-codec.yaml
@@ -17,6 +17,9 @@ description: |
subnode of a cros-ec node.
(see Documentation/devicetree/bindings/mfd/google,cros-ec.yaml).
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
const: google,cros-ec-codec
@@ -42,7 +45,7 @@ required:
- compatible
- '#sound-dai-cells'
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
@@ -57,6 +60,7 @@ examples:
cros-ec@0 {
compatible = "google,cros-ec-spi";
reg = <0>;
+ interrupts = <93 0>;
codecs {
#address-cells = <2>;
diff --git a/Documentation/devicetree/bindings/sound/ingenic,aic.yaml b/Documentation/devicetree/bindings/sound/ingenic,aic.yaml
index d607325f2f15..ba44406c9caf 100644
--- a/Documentation/devicetree/bindings/sound/ingenic,aic.yaml
+++ b/Documentation/devicetree/bindings/sound/ingenic,aic.yaml
@@ -9,6 +9,9 @@ title: Ingenic SoCs AC97 / I2S Controller (AIC) DT bindings
maintainers:
- Paul Cercueil <paul@crapouillou.net>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
$nodename:
pattern: '^audio-controller@'
@@ -37,15 +40,11 @@ properties:
items:
- description: AIC clock
- description: I2S clock
- - description: EXT clock
- - description: PLL/2 clock
clock-names:
items:
- const: aic
- const: i2s
- - const: ext
- - const: pll half
dmas:
items:
@@ -57,7 +56,7 @@ properties:
- const: rx
- const: tx
-additionalProperties: false
+unevaluatedProperties: false
required:
- compatible
@@ -82,10 +81,8 @@ examples:
interrupts = <18>;
clocks = <&cgu JZ4740_CLK_AIC>,
- <&cgu JZ4740_CLK_I2S>,
- <&cgu JZ4740_CLK_EXT>,
- <&cgu JZ4740_CLK_PLL_HALF>;
- clock-names = "aic", "i2s", "ext", "pll half";
+ <&cgu JZ4740_CLK_I2S>;
+ clock-names = "aic", "i2s";
dmas = <&dmac 25 0xffffffff>, <&dmac 24 0xffffffff>;
dma-names = "rx", "tx";
diff --git a/Documentation/devicetree/bindings/sound/ingenic,codec.yaml b/Documentation/devicetree/bindings/sound/ingenic,codec.yaml
index 48aae54dd643..a07d607e9b93 100644
--- a/Documentation/devicetree/bindings/sound/ingenic,codec.yaml
+++ b/Documentation/devicetree/bindings/sound/ingenic,codec.yaml
@@ -9,6 +9,9 @@ title: Ingenic JZ47xx internal codec DT bindings
maintainers:
- Paul Cercueil <paul@crapouillou.net>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
$nodename:
pattern: '^audio-codec@.*'
@@ -37,7 +40,7 @@ properties:
'#sound-dai-cells':
const: 0
-additionalProperties: false
+unevaluatedProperties: false
required:
- compatible
diff --git a/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml
index b2603f611af9..76b6f2cf25df 100644
--- a/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml
+++ b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml
@@ -8,11 +8,15 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: Intel KeemBay I2S
maintainers:
- - Sia, Jee Heng <jee.heng.sia@intel.com>
+ - Daniele Alessandrelli <daniele.alessandrelli@intel.com>
+ - Paul J. Murphy <paul.j.murphy@intel.com>
description: |
Intel KeemBay I2S
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -64,7 +68,7 @@ required:
- clock-names
- interrupts
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/linux,bt-sco.yaml b/Documentation/devicetree/bindings/sound/linux,bt-sco.yaml
index b97e0fcbdba3..a67b79cbe006 100644
--- a/Documentation/devicetree/bindings/sound/linux,bt-sco.yaml
+++ b/Documentation/devicetree/bindings/sound/linux,bt-sco.yaml
@@ -9,6 +9,9 @@ title: Bluetooth SCO Audio Codec
maintainers:
- Mark Brown <broonie@kernel.org>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
'#sound-dai-cells':
enum:
@@ -26,7 +29,7 @@ required:
- '#sound-dai-cells'
- compatible
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/linux,spdif-dit.yaml b/Documentation/devicetree/bindings/sound/linux,spdif-dit.yaml
index 808f6d2736c7..fe5f0756af2f 100644
--- a/Documentation/devicetree/bindings/sound/linux,spdif-dit.yaml
+++ b/Documentation/devicetree/bindings/sound/linux,spdif-dit.yaml
@@ -10,7 +10,7 @@ maintainers:
- Mark Brown <broonie@kernel.org>
allOf:
- - $ref: name-prefix.yaml#
+ - $ref: dai-common.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/sound/marvell,mmp-sspa.yaml b/Documentation/devicetree/bindings/sound/marvell,mmp-sspa.yaml
index 81f266d66ec5..92d896e0d323 100644
--- a/Documentation/devicetree/bindings/sound/marvell,mmp-sspa.yaml
+++ b/Documentation/devicetree/bindings/sound/marvell,mmp-sspa.yaml
@@ -9,6 +9,9 @@ title: Marvel SSPA Digital Audio Interface Bindings
maintainers:
- Lubomir Rintel <lkundrak@v3.sk>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
$nodename:
pattern: "^audio-controller(@.*)?$"
@@ -73,7 +76,7 @@ required:
- dma-names
- port
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/max98357a.txt b/Documentation/devicetree/bindings/sound/max98357a.txt
deleted file mode 100644
index 75db84d06240..000000000000
--- a/Documentation/devicetree/bindings/sound/max98357a.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-Maxim MAX98357A/MAX98360A audio DAC
-
-This node models the Maxim MAX98357A/MAX98360A DAC.
-
-Required properties:
-- compatible : "maxim,max98357a" for MAX98357A.
- "maxim,max98360a" for MAX98360A.
-
-Optional properties:
-- sdmode-gpios : GPIO specifier for the chip's SD_MODE pin.
- If this option is not specified then driver does not manage
- the pin state (e.g. chip is always on).
-- sdmode-delay : specify delay time for SD_MODE pin.
- If this option is specified, which means it's required i2s clocks
- ready before SD_MODE is unmuted in order to avoid the speaker pop noise.
- It's observed that 5ms is sufficient.
-
-Example:
-
-max98357a {
- compatible = "maxim,max98357a";
- sdmode-gpios = <&qcom_pinmux 25 0>;
-};
-
-max98360a {
- compatible = "maxim,max98360a";
- sdmode-gpios = <&qcom_pinmux 25 0>;
-};
diff --git a/Documentation/devicetree/bindings/sound/max98504.txt b/Documentation/devicetree/bindings/sound/max98504.txt
deleted file mode 100644
index 583ed5fdfb28..000000000000
--- a/Documentation/devicetree/bindings/sound/max98504.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-Maxim MAX98504 class D mono speaker amplifier
-
-This device supports I2C control interface and an IRQ output signal. It features
-a PCM and PDM digital audio interface (DAI) and a differential analog input.
-
-Required properties:
-
- - compatible : "maxim,max98504"
- - reg : should contain the I2C slave device address
- - DVDD-supply, DIOVDD-supply, PVDD-supply: power supplies for the device,
- as covered in ../regulator/regulator.txt
- - interrupts : should specify the interrupt line the device is connected to,
- as described in ../interrupt-controller/interrupts.txt
-
-Optional properties:
-
- - maxim,brownout-threshold - the PVDD brownout threshold, the value must be
- from 0, 1...21 range, corresponding to 2.6V, 2.65V...3.65V voltage range
- - maxim,brownout-attenuation - the brownout attenuation to the speaker gain
- applied during the "attack hold" and "timed hold" phase, the value must be
- from 0...6 (dB) range
- - maxim,brownout-attack-hold-ms - the brownout attack hold phase time in ms,
- 0...255 (VBATBROWN_ATTK_HOLD, register 0x0018)
- - maxim,brownout-timed-hold-ms - the brownout timed hold phase time in ms,
- 0...255 (VBATBROWN_TIME_HOLD, register 0x0019)
- - maxim,brownout-release-rate-ms - the brownout release phase step time in ms,
- 0...255 (VBATBROWN_RELEASE, register 0x001A)
-
-The default value when the above properties are not specified is 0,
-the maxim,brownout-threshold property must be specified to actually enable
-the PVDD brownout protection.
-
-Example:
-
- max98504@31 {
- compatible = "maxim,max98504";
- reg = <0x31>;
- interrupt-parent = <&gpio_bank_0>;
- interrupts = <2 0>;
-
- DVDD-supply = <&regulator>;
- DIOVDD-supply = <&regulator>;
- PVDD-supply = <&regulator>;
-};
diff --git a/Documentation/devicetree/bindings/sound/maxim,max98357a.yaml b/Documentation/devicetree/bindings/sound/maxim,max98357a.yaml
new file mode 100644
index 000000000000..83ba8666fbb4
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/maxim,max98357a.yaml
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/maxim,max98357a.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim Integrated MAX98357A/MAX98360A amplifier
+
+maintainers:
+ - Tzung-Bi Shih <tzungbi@kernel.org>
+
+description:
+ Maxim Integrated MAX98357A/MAX98360A is a digital pulse-code modulation (PCM)
+ input Class D amplifier.
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ enum:
+ - maxim,max98357a
+ - maxim,max98360a
+
+ '#sound-dai-cells':
+ const: 0
+
+ sdmode-gpios:
+ maxItems: 1
+ description:
+ Chip's SD_MODE pin. If missing the chip is always on.
+
+ sdmode-delay:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ description:
+ Delay time for SD_MODE pin changes intended to make I2S clocks ready
+ before SD_MODE is unmuted in order to avoid the speaker pop noise.
+
+required:
+ - compatible
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ amplifier {
+ compatible = "maxim,max98360a";
+ #sound-dai-cells = <0>;
+ sdmode-gpios = <&qcom_pinmux 25 GPIO_ACTIVE_HIGH>;
+ };
diff --git a/Documentation/devicetree/bindings/sound/maxim,max98504.yaml b/Documentation/devicetree/bindings/sound/maxim,max98504.yaml
new file mode 100644
index 000000000000..23f19a9d2c06
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/maxim,max98504.yaml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/maxim,max98504.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Maxim Integrated MAX98504 class D mono speaker amplifier
+
+maintainers:
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+
+description:
+ Maxim Integrated MAX98504 speaker amplifier supports I2C control interface
+ with an IRQ output signal, PCM and PDM digital audio interface (DAI) and a
+ differential analog input.
+
+properties:
+ compatible:
+ const: maxim,max98504
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ maxItems: 1
+
+ DIOVDD-supply: true
+ DVDD-supply: true
+ PVDD-supply: true
+
+ maxim,brownout-threshold:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ maximum: 21
+ default: 0
+ description:
+ PVDD brownout threshold, where values correspond to 2.6V, 2.65V...3.65V
+ voltage range. Property also enables the PVDD brownout protection.
+
+ maxim,brownout-attenuation:
+ $ref: /schemas/types.yaml#/definitions/uint32
+ maximum: 6
+ default: 0
+ description:
+ Brownout attenuation to the speaker gain applied during the "attack hold"
+ and "timed hold" phase, the value must be from 0...6 (dB) range.
+
+ maxim,brownout-attack-hold-ms:
+ maximum: 255
+ default: 0
+ description:
+ Brownout attack hold phase time in ms, VBATBROWN_ATTK_HOLD, register 0x0018.
+
+ maxim,brownout-timed-hold-ms:
+ maximum: 255
+ default: 0
+ description:
+ Brownout timed hold phase time in ms, VBATBROWN_TIME_HOLD, register 0x0019.
+
+ maxim,brownout-release-rate-ms:
+ maximum: 255
+ default: 0
+ description:
+ Brownout release phase step time in ms, VBATBROWN_RELEASE, register 0x001A.
+
+required:
+ - compatible
+ - reg
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ amplifier@31 {
+ compatible = "maxim,max98504";
+ reg = <0x31>;
+
+ DIOVDD-supply = <&ldo3_reg>;
+ DVDD-supply = <&ldo3_reg>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml b/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml
index 0481315cb5f2..621022872c8d 100644
--- a/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml
+++ b/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml
@@ -66,13 +66,15 @@ properties:
enum: [0, 1, 2, 3]
default: 0
-if:
- properties:
- compatible:
- const: microchip,sam9x60-i2smcc
-then:
- properties:
- microchip,tdm-data-pair: false
+allOf:
+ - $ref: dai-common.yaml#
+ - if:
+ properties:
+ compatible:
+ const: microchip,sam9x60-i2smcc
+ then:
+ properties:
+ microchip,tdm-data-pair: false
required:
- "#sound-dai-cells"
@@ -84,7 +86,7 @@ required:
- dmas
- dma-names
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml b/Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml
index d218e4ab9a7a..c383162140bb 100644
--- a/Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml
+++ b/Documentation/devicetree/bindings/sound/mchp,spdiftx.yaml
@@ -13,6 +13,9 @@ description:
The Microchip Sony/Philips Digital Interface Transmitter is a serial port
compliant with the IEC-60958 standard.
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
"#sound-dai-cells":
const: 0
@@ -53,7 +56,7 @@ required:
- dmas
- dma-names
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/microchip,pdmc.yaml b/Documentation/devicetree/bindings/sound/microchip,pdmc.yaml
index 04414eb4ada9..c37b89d94c12 100644
--- a/Documentation/devicetree/bindings/sound/microchip,pdmc.yaml
+++ b/Documentation/devicetree/bindings/sound/microchip,pdmc.yaml
@@ -13,6 +13,9 @@ description:
The Microchip Pulse Density Microphone Controller (PDMC) interfaces up to 4
digital microphones having Pulse Density Modulated (PDM) outputs.
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
const: microchip,sama7g5-pdmc
@@ -75,7 +78,7 @@ required:
- dma-names
- microchip,mic-pos
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml b/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml
index 4fc5b045d3cf..9d3139990237 100644
--- a/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml
+++ b/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml
@@ -21,6 +21,13 @@ properties:
$ref: "/schemas/types.yaml#/definitions/phandle"
description: The phandle of MT8186 ASoC platform.
+ dmic-gpios:
+ maxItems: 1
+ description:
+ dmic-gpios optional prop for switching between two DMICs.
+ Ex, the GPIO can control a MUX HW component to select
+ dmic clk and data form a Front or Rear dmic.
+
headset-codec:
type: object
additionalProperties: false
@@ -63,14 +70,19 @@ required:
examples:
- |
+ #include <dt-bindings/gpio/gpio.h>
sound: mt8186-sound {
compatible = "mediatek,mt8186-mt6366-rt1019-rt5682s-sound";
mediatek,platform = <&afe>;
pinctrl-names = "aud_clk_mosi_off",
- "aud_clk_mosi_on";
+ "aud_clk_mosi_on",
+ "aud_gpio_dmic_sec";
pinctrl-0 = <&aud_clk_mosi_off>;
pinctrl-1 = <&aud_clk_mosi_on>;
+ pinctrl-2 = <&aud_gpio_dmic_sec>;
+
+ dmic-gpios = <&pio 23 GPIO_ACTIVE_HIGH>;
headset-codec {
sound-dai = <&rt5682s>;
diff --git a/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml b/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml
index 478be7e3fa29..c6e614c1c30b 100644
--- a/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml
+++ b/Documentation/devicetree/bindings/sound/mt8192-mt6359-rt1015-rt5682.yaml
@@ -34,7 +34,7 @@ properties:
properties:
sound-dai:
- $ref: /schemas/types.yaml#/definitions/phandle
+ maxItems: 1
required:
- sound-dai
@@ -48,7 +48,6 @@ properties:
maxItems: 2
items:
maxItems: 1
- $ref: /schemas/types.yaml#/definitions/phandle-array
required:
- sound-dai
diff --git a/Documentation/devicetree/bindings/sound/mvebu-audio.txt b/Documentation/devicetree/bindings/sound/mvebu-audio.txt
index cb8c07c81ce4..4f5dec5cb3c2 100644
--- a/Documentation/devicetree/bindings/sound/mvebu-audio.txt
+++ b/Documentation/devicetree/bindings/sound/mvebu-audio.txt
@@ -6,9 +6,14 @@ Required properties:
"marvell,kirkwood-audio" for Kirkwood platforms
"marvell,dove-audio" for Dove platforms
"marvell,armada370-audio" for Armada 370 platforms
+ "marvell,armada-380-audio" for Armada 38x platforms
- reg: physical base address of the controller and length of memory mapped
- region.
+ region (named "i2s_regs").
+ With "marvell,armada-380-audio" two other regions are required:
+ first of those is dedicated for Audio PLL Configuration registers
+ (named "pll_regs") and the second one ("soc_ctrl") - for register
+ where one of exceptive I/O types (I2S or S/PDIF) is set.
- interrupts:
with "marvell,kirkwood-audio", the audio interrupt
@@ -23,6 +28,13 @@ Required properties:
"internal" for the internal clock
"extclk" for the external clock
+Optional properties:
+
+- spdif-mode:
+ Enable S/PDIF mode on Armada 38x SoC. Using this property
+ disables standard I2S I/O. Valid only with "marvell,armada-380-audio"
+ compatible string.
+
Example:
i2s1: audio-controller@b4000 {
diff --git a/Documentation/devicetree/bindings/sound/nau8315.txt b/Documentation/devicetree/bindings/sound/nau8315.txt
index 6eaec46f384c..1cd94517d45e 100644
--- a/Documentation/devicetree/bindings/sound/nau8315.txt
+++ b/Documentation/devicetree/bindings/sound/nau8315.txt
@@ -2,6 +2,7 @@ Nuvoton NAU8315 Mono Class-D Amplifier
Required properties:
- compatible : "nuvoton,nau8315"
+ "nuvoton,nau8318"
Optional properties:
- enable-gpios : GPIO specifier for the chip's device enable input(EN) pin.
@@ -16,3 +17,8 @@ nau8315 {
compatible = "nuvoton,nau8315";
enable-gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>;
};
+
+nau8318 {
+ compatible = "nuvoton,nau8318";
+ enable-gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>;
+};
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra186-asrc.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra186-asrc.yaml
index d82415c21271..e15f387c4c29 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra186-asrc.yaml
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra186-asrc.yaml
@@ -23,7 +23,7 @@ maintainers:
- Sameer Pujar <spujar@nvidia.com>
allOf:
- - $ref: name-prefix.yaml#
+ - $ref: dai-common.yaml#
properties:
$nodename:
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml
index 3d538df878ea..e1362c77472b 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml
@@ -18,7 +18,7 @@ maintainers:
- Sameer Pujar <spujar@nvidia.com>
allOf:
- - $ref: name-prefix.yaml#
+ - $ref: dai-common.yaml#
properties:
$nodename:
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra20-spdif.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra20-spdif.yaml
index 60a368a132b8..dc76a4dc0ed2 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra20-spdif.yaml
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra20-spdif.yaml
@@ -16,6 +16,9 @@ maintainers:
- Thierry Reding <treding@nvidia.com>
- Jon Hunter <jonathanh@nvidia.com>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
const: nvidia,tegra20-spdif
@@ -66,7 +69,7 @@ required:
- dma-names
- "#sound-dai-cells"
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-adx.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-adx.yaml
index ea0dc0ece1bc..e4c871797fa6 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-adx.yaml
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-adx.yaml
@@ -19,7 +19,7 @@ maintainers:
- Sameer Pujar <spujar@nvidia.com>
allOf:
- - $ref: name-prefix.yaml#
+ - $ref: dai-common.yaml#
properties:
$nodename:
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-amx.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-amx.yaml
index 1aff61f072bb..021b72546ba4 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-amx.yaml
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-amx.yaml
@@ -18,7 +18,7 @@ maintainers:
- Sameer Pujar <spujar@nvidia.com>
allOf:
- - $ref: name-prefix.yaml#
+ - $ref: dai-common.yaml#
properties:
$nodename:
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml
index 0f9d2b461e02..bff551c35da7 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml
@@ -17,7 +17,7 @@ maintainers:
- Sameer Pujar <spujar@nvidia.com>
allOf:
- - $ref: name-prefix.yaml#
+ - $ref: dai-common.yaml#
properties:
$nodename:
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml
index 12cd17eede99..a82f11fb6c9a 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml
@@ -17,7 +17,7 @@ maintainers:
- Sameer Pujar <spujar@nvidia.com>
allOf:
- - $ref: name-prefix.yaml#
+ - $ref: dai-common.yaml#
properties:
$nodename:
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-mixer.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-mixer.yaml
index 570b03282aeb..049898f02e85 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-mixer.yaml
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-mixer.yaml
@@ -17,7 +17,7 @@ maintainers:
- Sameer Pujar <spujar@nvidia.com>
allOf:
- - $ref: name-prefix.yaml#
+ - $ref: dai-common.yaml#
properties:
$nodename:
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-mvc.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-mvc.yaml
index 4aecbc847b98..d0280d8aa3af 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-mvc.yaml
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-mvc.yaml
@@ -20,7 +20,7 @@ maintainers:
- Sameer Pujar <spujar@nvidia.com>
allOf:
- - $ref: name-prefix.yaml#
+ - $ref: dai-common.yaml#
properties:
$nodename:
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-ope.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ope.yaml
index 9dc9ba590fa3..5fc03b8771b1 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-ope.yaml
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ope.yaml
@@ -17,7 +17,7 @@ maintainers:
- Sameer Pujar <spujar@nvidia.com>
allOf:
- - $ref: name-prefix.yaml#
+ - $ref: dai-common.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-sfc.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-sfc.yaml
index 694f890d6305..185ca0be4f02 100644
--- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-sfc.yaml
+++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-sfc.yaml
@@ -17,7 +17,7 @@ maintainers:
- Sameer Pujar <spujar@nvidia.com>
allOf:
- - $ref: name-prefix.yaml#
+ - $ref: dai-common.yaml#
properties:
$nodename:
diff --git a/Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml b/Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml
index 7f2e68ff6d34..fd2415e231eb 100644
--- a/Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml
+++ b/Documentation/devicetree/bindings/sound/nxp,tfa989x.yaml
@@ -10,7 +10,7 @@ maintainers:
- Stephan Gerhold <stephan@gerhold.net>
allOf:
- - $ref: name-prefix.yaml#
+ - $ref: dai-common.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml
index ef18a572a1ff..5e26b3e9db2c 100644
--- a/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml
@@ -109,9 +109,10 @@ required:
- interrupt-names
- '#sound-dai-cells'
-additionalProperties: false
+unevaluatedProperties: false
allOf:
+ - $ref: dai-common.yaml#
- if:
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml
index 1de11e7f33bb..23564fd394a2 100644
--- a/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,lpass-rx-macro.yaml
@@ -9,6 +9,9 @@ title: LPASS(Low Power Audio Subsystem) RX Macro audio codec DT bindings
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -43,8 +46,7 @@ properties:
- const: fsgen
clock-output-names:
- items:
- - const: mclk
+ maxItems: 1
power-domains:
maxItems: 2
@@ -59,7 +61,7 @@ required:
- reg
- "#sound-dai-cells"
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml
index de8297b358e8..38708578ee29 100644
--- a/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,lpass-tx-macro.yaml
@@ -9,6 +9,9 @@ title: LPASS(Low Power Audio Subsystem) TX Macro audio codec DT bindings
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -43,8 +46,7 @@ properties:
- const: fsgen
clock-output-names:
- items:
- - const: mclk
+ maxItems: 1
power-domains:
maxItems: 2
@@ -63,7 +65,7 @@ required:
- reg
- "#sound-dai-cells"
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml
index 9f473c08cb2e..188883a2e671 100644
--- a/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,lpass-va-macro.yaml
@@ -9,6 +9,9 @@ title: LPASS(Low Power Audio Subsystem) VA Macro audio codec DT bindings
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -39,8 +42,7 @@ properties:
- const: mclk
clock-output-names:
- items:
- - const: fsgen
+ maxItems: 1
power-domains:
maxItems: 2
@@ -62,7 +64,7 @@ required:
- reg
- "#sound-dai-cells"
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml b/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml
index 4959ad658eac..bebca3e3f86f 100644
--- a/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,lpass-wsa-macro.yaml
@@ -9,6 +9,9 @@ title: LPASS(Low Power Audio Subsystem) VA Macro audio codec DT bindings
maintainers:
- Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -38,8 +41,7 @@ properties:
- const: fsgen
clock-output-names:
- items:
- - const: mclk
+ maxItems: 1
qcom,dmic-sample-rate:
description: dmic sample rate
@@ -53,7 +55,7 @@ required:
- reg
- "#sound-dai-cells"
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6adm-routing.yaml b/Documentation/devicetree/bindings/sound/qcom,q6adm-routing.yaml
index d0f7a79e240a..3f11d2e183e1 100644
--- a/Documentation/devicetree/bindings/sound/qcom,q6adm-routing.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,q6adm-routing.yaml
@@ -14,6 +14,9 @@ description:
Qualcomm Audio Device Manager (Q6ADM) routing node represents routing
specific configuration.
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -26,27 +29,11 @@ required:
- compatible
- "#sound-dai-cells"
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
- #include <dt-bindings/soc/qcom,apr.h>
- #include <dt-bindings/sound/qcom,q6asm.h>
-
- apr {
- compatible = "qcom,apr-v2";
- qcom,domain = <APR_DOMAIN_ADSP>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- service@8 {
- compatible = "qcom,q6adm";
- reg = <APR_SVC_ADM>;
- qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
-
- routing {
- compatible = "qcom,q6adm-routing";
- #sound-dai-cells = <0>;
- };
- };
+ routing {
+ compatible = "qcom,q6adm-routing";
+ #sound-dai-cells = <0>;
};
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6adm.yaml b/Documentation/devicetree/bindings/sound/qcom,q6adm.yaml
new file mode 100644
index 000000000000..fe14a97ea616
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/qcom,q6adm.yaml
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/qcom,q6adm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Audio Device Manager (Q6ADM)
+
+maintainers:
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+ - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+allOf:
+ - $ref: /schemas/soc/qcom/qcom,apr-services.yaml#
+
+properties:
+ compatible:
+ enum:
+ - qcom,q6adm
+
+ routing:
+ type: object
+ $ref: /schemas/sound/qcom,q6adm-routing.yaml#
+ unevaluatedProperties: false
+ description: Qualcomm DSP LPASS audio routing
+
+required:
+ - compatible
+ - routing
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/soc/qcom,apr.h>
+
+ apr {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ service@8 {
+ compatible = "qcom,q6adm";
+ reg = <APR_SVC_ADM>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+
+ routing {
+ compatible = "qcom,q6adm-routing";
+ #sound-dai-cells = <0>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6afe.yaml b/Documentation/devicetree/bindings/sound/qcom,q6afe.yaml
new file mode 100644
index 000000000000..297aa362aa54
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/qcom,q6afe.yaml
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/qcom,q6afe.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Audio FrontEnd (Q6AFE)
+
+maintainers:
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+ - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+allOf:
+ - $ref: /schemas/soc/qcom/qcom,apr-services.yaml#
+
+properties:
+ compatible:
+ enum:
+ - qcom,q6afe
+
+ clock-controller:
+ $ref: /schemas/sound/qcom,q6dsp-lpass-clocks.yaml#
+ unevaluatedProperties: false
+ description: Qualcomm DSP LPASS clock controller
+
+ dais:
+ type: object
+ $ref: /schemas/sound/qcom,q6dsp-lpass-ports.yaml#
+ unevaluatedProperties: false
+ description: Qualcomm DSP audio ports
+
+required:
+ - compatible
+ - dais
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/soc/qcom,apr.h>
+ #include <dt-bindings/sound/qcom,q6afe.h>
+ apr {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ service@4 {
+ compatible = "qcom,q6afe";
+ reg = <APR_SVC_AFE>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+
+ clock-controller {
+ compatible = "qcom,q6afe-clocks";
+ #clock-cells = <2>;
+ };
+
+ dais {
+ compatible = "qcom,q6afe-dais";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #sound-dai-cells = <1>;
+
+ dai@22 {
+ reg = <QUATERNARY_MI2S_RX>;
+ qcom,sd-lines = <0 1 2 3>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml b/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml
index 24f7bf2bfd95..73a4afad5a74 100644
--- a/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,q6apm-dai.yaml
@@ -27,20 +27,7 @@ additionalProperties: false
examples:
- |
- #include <dt-bindings/soc/qcom,gpr.h>
- gpr {
- compatible = "qcom,gpr";
- #address-cells = <1>;
- #size-cells = <0>;
- qcom,domain = <GPR_DOMAIN_ID_ADSP>;
-
- service@1 {
- compatible = "qcom,q6apm";
- reg = <1>;
-
- dais {
- compatible = "qcom,q6apm-dais";
- iommus = <&apps_smmu 0x1801 0x0>;
- };
- };
+ dais {
+ compatible = "qcom,q6apm-dais";
+ iommus = <&apps_smmu 0x1801 0x0>;
};
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml b/Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml
new file mode 100644
index 000000000000..894e653d37d7
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/qcom,q6apm-lpass-dais.yaml
@@ -0,0 +1,35 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/qcom,q6apm-lpass-dais.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm DSP LPASS (Low Power Audio SubSystem) Audio Ports
+
+maintainers:
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+ - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ enum:
+ - qcom,q6apm-lpass-dais
+
+ '#sound-dai-cells':
+ const: 1
+
+required:
+ - compatible
+ - '#sound-dai-cells'
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ dais {
+ compatible = "qcom,q6apm-lpass-dais";
+ #sound-dai-cells = <1>;
+ };
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6apm.yaml b/Documentation/devicetree/bindings/sound/qcom,q6apm.yaml
new file mode 100644
index 000000000000..ef1965aca254
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/qcom,q6apm.yaml
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/qcom,q6apm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Audio Process Manager (Q6APM)
+
+maintainers:
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+ - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+allOf:
+ - $ref: dai-common.yaml#
+ - $ref: /schemas/soc/qcom/qcom,apr-services.yaml#
+
+properties:
+ compatible:
+ enum:
+ - qcom,q6apm
+
+ bedais:
+ type: object
+ $ref: /schemas/sound/qcom,q6apm-lpass-dais.yaml#
+ unevaluatedProperties: false
+ description: Qualcomm DSP audio ports
+
+ dais:
+ type: object
+ $ref: /schemas/sound/qcom,q6apm-dai.yaml#
+ unevaluatedProperties: false
+ description: Qualcomm DSP audio ports
+
+ '#sound-dai-cells':
+ const: 0
+
+required:
+ - compatible
+ - bedais
+ - dais
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/soc/qcom,gpr.h>
+
+ gpr {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ service@1 {
+ reg = <GPR_APM_MODULE_IID>;
+ compatible = "qcom,q6apm";
+ #sound-dai-cells = <0>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+
+ dais {
+ compatible = "qcom,q6apm-dais";
+ iommus = <&apps_smmu 0x1801 0x0>;
+ };
+
+ bedais {
+ compatible = "qcom,q6apm-lpass-dais";
+ #sound-dai-cells = <1>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6asm-dais.yaml b/Documentation/devicetree/bindings/sound/qcom,q6asm-dais.yaml
index 8deb8ffb143b..0110b38f6de9 100644
--- a/Documentation/devicetree/bindings/sound/qcom,q6asm-dais.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,q6asm-dais.yaml
@@ -73,40 +73,24 @@ additionalProperties: false
examples:
- |
- #include <dt-bindings/soc/qcom,apr.h>
- #include <dt-bindings/sound/qcom,q6asm.h>
-
- apr {
- compatible = "qcom,apr-v2";
- qcom,domain = <APR_DOMAIN_ADSP>;
+ dais {
+ compatible = "qcom,q6asm-dais";
+ iommus = <&apps_smmu 0x1821 0x0>;
#address-cells = <1>;
#size-cells = <0>;
+ #sound-dai-cells = <1>;
+
+ dai@0 {
+ reg = <0>;
+ };
+
+ dai@1 {
+ reg = <1>;
+ };
- service@7 {
- compatible = "qcom,q6asm";
- reg = <APR_SVC_ASM>;
- qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
-
- dais {
- compatible = "qcom,q6asm-dais";
- iommus = <&apps_smmu 0x1821 0x0>;
- #address-cells = <1>;
- #size-cells = <0>;
- #sound-dai-cells = <1>;
-
- dai@0 {
- reg = <0>;
- };
-
- dai@1 {
- reg = <1>;
- };
-
- dai@2 {
- reg = <2>;
- is-compress-dai;
- direction = <1>;
- };
- };
+ dai@2 {
+ reg = <2>;
+ is-compress-dai;
+ direction = <1>;
};
};
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6asm.yaml b/Documentation/devicetree/bindings/sound/qcom,q6asm.yaml
new file mode 100644
index 000000000000..cb49f9667cca
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/qcom,q6asm.yaml
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/qcom,q6asm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Audio Stream Manager (Q6ASM)
+
+maintainers:
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+ - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+allOf:
+ - $ref: /schemas/soc/qcom/qcom,apr-services.yaml#
+
+properties:
+ compatible:
+ enum:
+ - qcom,q6asm
+
+ dais:
+ type: object
+ $ref: /schemas/sound/qcom,q6asm-dais.yaml#
+ unevaluatedProperties: false
+ description: Qualcomm DSP audio ports
+
+required:
+ - compatible
+ - dais
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/soc/qcom,apr.h>
+
+ apr {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ service@7 {
+ compatible = "qcom,q6asm";
+ reg = <APR_SVC_ASM>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+
+ dais {
+ compatible = "qcom,q6asm-dais";
+ iommus = <&apps_smmu 0x1821 0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #sound-dai-cells = <1>;
+
+ dai@0 {
+ reg = <0>;
+ };
+
+ dai@1 {
+ reg = <1>;
+ };
+
+ dai@2 {
+ reg = <2>;
+ is-compress-dai;
+ direction = <1>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6core.yaml b/Documentation/devicetree/bindings/sound/qcom,q6core.yaml
new file mode 100644
index 000000000000..e240712de9ca
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/qcom,q6core.yaml
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/qcom,q6core.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Audio Core (Q6Core)
+
+maintainers:
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+ - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+allOf:
+ - $ref: /schemas/soc/qcom/qcom,apr-services.yaml#
+
+properties:
+ compatible:
+ enum:
+ - qcom,q6core
+
+required:
+ - compatible
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/soc/qcom,apr.h>
+
+ apr {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ service@3 {
+ compatible = "qcom,q6core";
+ reg = <APR_SVC_ADSP_CORE>;
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-clocks.yaml b/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-clocks.yaml
index fd567d20417d..aa6c0ecba5cf 100644
--- a/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-clocks.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-clocks.yaml
@@ -35,41 +35,7 @@ additionalProperties: false
examples:
- |
- #include <dt-bindings/soc/qcom,apr.h>
- #include <dt-bindings/sound/qcom,q6afe.h>
- apr {
- compatible = "qcom,apr-v2";
- qcom,domain = <APR_DOMAIN_ADSP>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- service@4 {
- compatible = "qcom,q6afe";
- reg = <APR_SVC_AFE>;
- qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
-
- clock-controller {
- compatible = "qcom,q6afe-clocks";
- #clock-cells = <2>;
- };
- };
- };
-
- - |
- #include <dt-bindings/soc/qcom,gpr.h>
- gpr {
- compatible = "qcom,gpr";
- qcom,domain = <GPR_DOMAIN_ID_ADSP>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- service@2 {
- reg = <GPR_PRM_MODULE_IID>;
- compatible = "qcom,q6prm";
-
- clock-controller {
- compatible = "qcom,q6prm-lpass-clocks";
- #clock-cells = <2>;
- };
- };
+ clock-controller {
+ compatible = "qcom,q6afe-clocks";
+ #clock-cells = <2>;
};
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-ports.yaml b/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-ports.yaml
index e53fc0960a14..d8ebf2e528d2 100644
--- a/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-ports.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,q6dsp-lpass-ports.yaml
@@ -16,7 +16,6 @@ properties:
compatible:
enum:
- qcom,q6afe-dais
- - qcom,q6apm-lpass-dais
'#sound-dai-cells':
const: 1
@@ -150,54 +149,16 @@ additionalProperties: false
examples:
- |
- #include <dt-bindings/soc/qcom,apr.h>
- #include <dt-bindings/sound/qcom,q6afe.h>
- apr {
- compatible = "qcom,apr-v2";
- #address-cells = <1>;
- #size-cells = <0>;
- qcom,domain = <APR_DOMAIN_ADSP>;
-
- service@4 {
- compatible = "qcom,q6afe";
- reg = <APR_SVC_AFE>;
- qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
-
- dais {
- compatible = "qcom,q6afe-dais";
- #address-cells = <1>;
- #size-cells = <0>;
- #sound-dai-cells = <1>;
-
- dai@22 {
- reg = <QUATERNARY_MI2S_RX>;
- qcom,sd-lines = <0 1 2 3>;
- };
- };
- };
- };
- - |
- #include <dt-bindings/soc/qcom,gpr.h>
- gpr {
- compatible = "qcom,gpr";
+ #include <dt-bindings/sound/qcom,q6dsp-lpass-ports.h>
+
+ dais {
+ compatible = "qcom,q6afe-dais";
#address-cells = <1>;
#size-cells = <0>;
- qcom,domain = <GPR_DOMAIN_ID_ADSP>;
-
- service@1 {
- compatible = "qcom,q6apm";
- reg = <GPR_APM_MODULE_IID>;
-
- dais {
- compatible = "qcom,q6apm-lpass-dais";
- #address-cells = <1>;
- #size-cells = <0>;
- #sound-dai-cells = <1>;
-
- dai@22 {
- reg = <QUATERNARY_MI2S_RX>;
- qcom,sd-lines = <0 1 2 3>;
- };
- };
+ #sound-dai-cells = <1>;
+
+ dai@22 {
+ reg = <QUATERNARY_MI2S_RX>;
+ qcom,sd-lines = <0 1 2 3>;
};
};
diff --git a/Documentation/devicetree/bindings/sound/qcom,q6prm.yaml b/Documentation/devicetree/bindings/sound/qcom,q6prm.yaml
new file mode 100644
index 000000000000..f6dbb1267bfe
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/qcom,q6prm.yaml
@@ -0,0 +1,50 @@
+# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/qcom,q6prm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Proxy Resource Manager (Q6PRM)
+
+maintainers:
+ - Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
+ - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
+
+allOf:
+ - $ref: /schemas/soc/qcom/qcom,apr-services.yaml#
+
+properties:
+ compatible:
+ enum:
+ - qcom,q6prm
+
+ clock-controller:
+ $ref: /schemas/sound/qcom,q6dsp-lpass-clocks.yaml#
+ unevaluatedProperties: false
+ description: Qualcomm DSP LPASS clock controller
+
+required:
+ - compatible
+ - clock-controller
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/soc/qcom,gpr.h>
+
+ gpr {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ service@2 {
+ reg = <GPR_PRM_MODULE_IID>;
+ compatible = "qcom,q6prm";
+ qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
+
+ clock-controller {
+ compatible = "qcom,q6prm-lpass-clocks";
+ #clock-cells = <2>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt b/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt
index 5d6ea66a863f..1f75feec3dec 100644
--- a/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt
+++ b/Documentation/devicetree/bindings/sound/qcom,wcd9335.txt
@@ -109,7 +109,7 @@ audio-codec@1{
reg = <1 0>;
interrupts = <&msmgpio 54 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "intr2"
- reset-gpios = <&msmgpio 64 0>;
+ reset-gpios = <&msmgpio 64 GPIO_ACTIVE_LOW>;
slim-ifc-dev = <&wc9335_ifd>;
clock-names = "mclk", "native";
clocks = <&rpmcc RPM_SMD_DIV_CLK1>,
diff --git a/Documentation/devicetree/bindings/sound/qcom,wcd938x.yaml b/Documentation/devicetree/bindings/sound/qcom,wcd938x.yaml
index 51547190f709..67d84463eaeb 100644
--- a/Documentation/devicetree/bindings/sound/qcom,wcd938x.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,wcd938x.yaml
@@ -13,6 +13,9 @@ description: |
Qualcomm WCD9380/WCD9385 Codec is a standalone Hi-Fi audio codec IC.
It has RX and TX Soundwire slave devices.
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -106,7 +109,7 @@ required:
- qcom,micbias4-microvolt
- "#sound-dai-cells"
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/qcom,wsa883x.yaml b/Documentation/devicetree/bindings/sound/qcom,wsa883x.yaml
index 6113f65f2990..65b0e67f82a3 100644
--- a/Documentation/devicetree/bindings/sound/qcom,wsa883x.yaml
+++ b/Documentation/devicetree/bindings/sound/qcom,wsa883x.yaml
@@ -15,6 +15,9 @@ description: |
Their primary operating mode uses a SoundWire digital audio
interface. This binding is for SoundWire interface.
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
const: sdw10217020200
@@ -23,7 +26,7 @@ properties:
maxItems: 1
powerdown-gpios:
- description: GPIO spec for Powerdown/Shutdown line to use
+ description: GPIO spec for Powerdown/Shutdown line to use (pin SD_N)
maxItems: 1
vdd-supply:
@@ -43,10 +46,12 @@ required:
- "#thermal-sensor-cells"
- "#sound-dai-cells"
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
+ #include <dt-bindings/gpio/gpio.h>
+
soundwire-controller@3250000 {
#address-cells = <2>;
#size-cells = <0>;
@@ -55,19 +60,21 @@ examples:
speaker@0,1 {
compatible = "sdw10217020200";
reg = <0 1>;
- powerdown-gpios = <&tlmm 1 0>;
+ powerdown-gpios = <&tlmm 1 GPIO_ACTIVE_LOW>;
vdd-supply = <&vreg_s10b_1p8>;
#thermal-sensor-cells = <0>;
#sound-dai-cells = <0>;
+ sound-name-prefix = "SpkrLeft";
};
speaker@0,2 {
compatible = "sdw10217020200";
reg = <0 2>;
- powerdown-gpios = <&tlmm 89 0>;
+ powerdown-gpios = <&tlmm 89 GPIO_ACTIVE_LOW>;
vdd-supply = <&vreg_s10b_1p8>;
#thermal-sensor-cells = <0>;
#sound-dai-cells = <0>;
+ sound-name-prefix = "SpkrRight";
};
};
diff --git a/Documentation/devicetree/bindings/sound/realtek,rt5682s.yaml b/Documentation/devicetree/bindings/sound/realtek,rt5682s.yaml
index ca5b8987b749..e631ace7aad1 100644
--- a/Documentation/devicetree/bindings/sound/realtek,rt5682s.yaml
+++ b/Documentation/devicetree/bindings/sound/realtek,rt5682s.yaml
@@ -12,6 +12,9 @@ maintainers:
description: |
Rt5682s(ALC5682I-VS) is a rt5682i variant which supports I2C only.
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
const: realtek,rt5682s
@@ -87,11 +90,32 @@ properties:
maxItems: 2
description: Name given for DAI word clock and bit clock outputs.
-additionalProperties: false
+ "#sound-dai-cells":
+ const: 1
+
+ AVDD-supply:
+ description: Regulator supplying analog power through the AVDD pin.
+
+ MICVDD-supply:
+ description: Regulator supplying power for the microphone bias through the
+ MICVDD pin.
+
+ DBVDD-supply:
+ description: Regulator supplying I/O power through the DBVDD pin.
+
+ LDO1-IN-supply:
+ description: Regulator supplying power to the digital core and charge pump
+ through the LDO1_IN pin.
+
+unevaluatedProperties: false
required:
- compatible
- reg
+ - AVDD-supply
+ - MICVDD-supply
+ - DBVDD-supply
+ - LDO1-IN-supply
examples:
- |
@@ -117,5 +141,10 @@ examples:
clocks = <&osc>;
clock-names = "mclk";
+
+ AVDD-supply = <&avdd_reg>;
+ MICVDD-supply = <&micvdd_reg>;
+ DBVDD-supply = <&dbvdd_reg>;
+ LDO1-IN-supply = <&ldo1_in_reg>;
};
};
diff --git a/Documentation/devicetree/bindings/sound/renesas,fsi.yaml b/Documentation/devicetree/bindings/sound/renesas,fsi.yaml
index 0dd3f7361399..df91991699a7 100644
--- a/Documentation/devicetree/bindings/sound/renesas,fsi.yaml
+++ b/Documentation/devicetree/bindings/sound/renesas,fsi.yaml
@@ -9,6 +9,9 @@ title: Renesas FIFO-buffered Serial Interface (FSI)
maintainers:
- Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
$nodename:
pattern: "^sound@.*"
@@ -64,7 +67,7 @@ required:
- power-domains
- '#sound-dai-cells'
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml
index 679a246dd666..cb90463c7297 100644
--- a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml
+++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml
@@ -115,7 +115,7 @@ properties:
ports:
$ref: /schemas/graph.yaml#/properties/ports
patternProperties:
- port(@[0-9a-f]+)?:
+ '^port(@[0-9a-f]+)?$':
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
@@ -274,6 +274,7 @@ required:
- "#sound-dai-cells"
allOf:
+ - $ref: dai-common.yaml#
- if:
properties:
compatible:
@@ -304,7 +305,7 @@ allOf:
- ssi
- audmapp
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
index 0d9840375132..196881d94396 100644
--- a/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
+++ b/Documentation/devicetree/bindings/sound/renesas,rz-ssi.yaml
@@ -9,6 +9,9 @@ title: Renesas RZ/{G2L,V2L} ASoC Sound Serial Interface (SSIF-2)
maintainers:
- Biju Das <biju.das.jz@bp.renesas.com>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
items:
@@ -90,7 +93,7 @@ required:
- resets
- '#sound-dai-cells'
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/richtek,rt9120.yaml b/Documentation/devicetree/bindings/sound/richtek,rt9120.yaml
index 5655ca568240..a1242e8e0687 100644
--- a/Documentation/devicetree/bindings/sound/richtek,rt9120.yaml
+++ b/Documentation/devicetree/bindings/sound/richtek,rt9120.yaml
@@ -16,6 +16,9 @@ description: |
applications like as TV, monitors. home entertainment, electronic music
equipment.
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -42,7 +45,7 @@ required:
- dvdd-supply
- '#sound-dai-cells'
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.yaml b/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.yaml
index 6a7c004bef17..4c95895de75e 100644
--- a/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.yaml
+++ b/Documentation/devicetree/bindings/sound/rockchip,i2s-tdm.yaml
@@ -14,6 +14,9 @@ description:
maintainers:
- Nicolas Frattaroli <frattaroli.nicolas@gmail.com>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -21,6 +24,7 @@ properties:
- rockchip,rk1808-i2s-tdm
- rockchip,rk3308-i2s-tdm
- rockchip,rk3568-i2s-tdm
+ - rockchip,rk3588-i2s-tdm
- rockchip,rv1126-i2s-tdm
reg:
@@ -135,10 +139,9 @@ required:
- clock-names
- resets
- reset-names
- - rockchip,grf
- "#sound-dai-cells"
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/rockchip,pdm.yaml b/Documentation/devicetree/bindings/sound/rockchip,pdm.yaml
index 22e1cf6c0592..ff9e400494f3 100644
--- a/Documentation/devicetree/bindings/sound/rockchip,pdm.yaml
+++ b/Documentation/devicetree/bindings/sound/rockchip,pdm.yaml
@@ -16,6 +16,9 @@ description:
maintainers:
- Heiko Stuebner <heiko@sntech.de>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -83,7 +86,7 @@ required:
- dma-names
- "#sound-dai-cells"
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.yaml b/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.yaml
index 75b3b33b5f1f..5cdb8bcc687b 100644
--- a/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.yaml
+++ b/Documentation/devicetree/bindings/sound/rockchip,rk3328-codec.yaml
@@ -8,6 +8,9 @@ title: Rockchip rk3328 internal codec
maintainers:
- Heiko Stuebner <heiko@sntech.de>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
@@ -53,7 +56,7 @@ required:
- rockchip,grf
- "#sound-dai-cells"
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml
index 7e36e389e976..1cb4da300607 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml
+++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.yaml
@@ -13,6 +13,9 @@ description:
maintainers:
- Heiko Stuebner <heiko@sntech.de>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
oneOf:
@@ -111,7 +114,7 @@ required:
- dma-names
- "#sound-dai-cells"
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml b/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml
index d0a24bf928d6..4f51b2fa82db 100644
--- a/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml
+++ b/Documentation/devicetree/bindings/sound/rockchip-spdif.yaml
@@ -75,17 +75,18 @@ required:
- dma-names
- "#sound-dai-cells"
-if:
- properties:
- compatible:
- contains:
- const: rockchip,rk3288-spdif
-
-then:
- required:
- - rockchip,grf
-
-additionalProperties: false
+allOf:
+ - $ref: dai-common.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: rockchip,rk3288-spdif
+ then:
+ required:
+ - rockchip,grf
+
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/rohm,bd28623.yaml b/Documentation/devicetree/bindings/sound/rohm,bd28623.yaml
index 859ce64da152..5abcf92bc484 100644
--- a/Documentation/devicetree/bindings/sound/rohm,bd28623.yaml
+++ b/Documentation/devicetree/bindings/sound/rohm,bd28623.yaml
@@ -14,6 +14,9 @@ description:
maintainers:
- Katsuhiro Suzuki <katsuhiro@katsuster.net>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
const: rohm,bd28623
@@ -50,7 +53,7 @@ required:
- VCCP2-supply
- "#sound-dai-cells"
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/rt5659.txt b/Documentation/devicetree/bindings/sound/rt5659.txt
index 013f534fa059..8f3f62c0226a 100644
--- a/Documentation/devicetree/bindings/sound/rt5659.txt
+++ b/Documentation/devicetree/bindings/sound/rt5659.txt
@@ -42,7 +42,7 @@ Optional properties:
- realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin.
- realtek,reset-gpios : The GPIO that controls the CODEC's RESET pin.
-- sound-name-prefix: Please refer to name-prefix.yaml
+- sound-name-prefix: Please refer to dai-common.yaml
- ports: A Codec may have a single or multiple I2S interfaces. These
interfaces on Codec side can be described under 'ports' or 'port'.
diff --git a/Documentation/devicetree/bindings/sound/rt5682.txt b/Documentation/devicetree/bindings/sound/rt5682.txt
index c5f2b8febcee..5e1d08de18a5 100644
--- a/Documentation/devicetree/bindings/sound/rt5682.txt
+++ b/Documentation/devicetree/bindings/sound/rt5682.txt
@@ -8,6 +8,21 @@ Required properties:
- reg : The I2C address of the device.
+- AVDD-supply: phandle to the regulator supplying analog power through the
+ AVDD pin
+
+- MICVDD-supply: phandle to the regulator supplying power for the microphone
+ bias through the MICVDD pin. Either MICVDD or VBAT should be present.
+
+- VBAT-supply: phandle to the regulator supplying battery power through the
+ VBAT pin. Either MICVDD or VBAT should be present.
+
+- DBVDD-supply: phandle to the regulator supplying I/O power through the DBVDD
+ pin.
+
+- LDO1-IN-supply: phandle to the regulator supplying power to the digital core
+ and charge pump through the LDO1_IN pin.
+
Optional properties:
- interrupts : The CODEC's interrupt output.
@@ -46,7 +61,7 @@ Optional properties:
- realtek,dmic-clk-driving-high : Set the high driving of the DMIC clock out.
-- #sound-dai-cells: Should be set to '<0>'.
+- #sound-dai-cells: Should be set to '<1>'.
Pins on the device (for linking into audio routes) for RT5682:
@@ -75,4 +90,9 @@ rt5682 {
clocks = <&osc>;
clock-names = "mclk";
+
+ AVDD-supply = <&avdd_reg>;
+ MICVDD-supply = <&micvdd_reg>;
+ DBVDD-supply = <&dbvdd_reg>;
+ LDO1-IN-supply = <&ldo1_in_reg>;
};
diff --git a/Documentation/devicetree/bindings/sound/samsung-i2s.yaml b/Documentation/devicetree/bindings/sound/samsung-i2s.yaml
index 84c4d6cba521..8d5dcf9cd43e 100644
--- a/Documentation/devicetree/bindings/sound/samsung-i2s.yaml
+++ b/Documentation/devicetree/bindings/sound/samsung-i2s.yaml
@@ -10,6 +10,9 @@ maintainers:
- Krzysztof Kozlowski <krzk@kernel.org>
- Sylwester Nawrocki <s.nawrocki@samsung.com>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
description: |
@@ -124,7 +127,7 @@ required:
- clocks
- clock-names
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/sgtl5000.yaml b/Documentation/devicetree/bindings/sound/sgtl5000.yaml
index 2bc7f00ce4a2..02059d66b084 100644
--- a/Documentation/devicetree/bindings/sound/sgtl5000.yaml
+++ b/Documentation/devicetree/bindings/sound/sgtl5000.yaml
@@ -9,6 +9,9 @@ title: Freescale SGTL5000 Stereo Codec
maintainers:
- Fabio Estevam <festevam@gmail.com>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
const: fsl,sgtl5000
@@ -88,7 +91,7 @@ required:
- VDDA-supply
- VDDIO-supply
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/simple-audio-amplifier.yaml b/Documentation/devicetree/bindings/sound/simple-audio-amplifier.yaml
index 5428ba9e23a6..5db1f989d050 100644
--- a/Documentation/devicetree/bindings/sound/simple-audio-amplifier.yaml
+++ b/Documentation/devicetree/bindings/sound/simple-audio-amplifier.yaml
@@ -10,7 +10,7 @@ maintainers:
- Jerome Brunet <jbrunet@baylibre.com>
allOf:
- - $ref: name-prefix.yaml#
+ - $ref: dai-common.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/sound/simple-audio-mux.yaml b/Documentation/devicetree/bindings/sound/simple-audio-mux.yaml
index b5fc35ee9b65..9f319caf3db7 100644
--- a/Documentation/devicetree/bindings/sound/simple-audio-mux.yaml
+++ b/Documentation/devicetree/bindings/sound/simple-audio-mux.yaml
@@ -14,7 +14,7 @@ description: |
their input line is connected to the output line.
allOf:
- - $ref: name-prefix.yaml#
+ - $ref: dai-common.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/sound/snps,designware-i2s.yaml b/Documentation/devicetree/bindings/sound/snps,designware-i2s.yaml
index 4b0795819064..56e623d4e168 100644
--- a/Documentation/devicetree/bindings/sound/snps,designware-i2s.yaml
+++ b/Documentation/devicetree/bindings/sound/snps,designware-i2s.yaml
@@ -50,21 +50,21 @@ properties:
- const: rx
minItems: 1
-if:
- properties:
- compatible:
- contains:
- const: canaan,k210-i2s
-
-then:
- properties:
- "#sound-dai-cells":
- const: 1
-
-else:
- properties:
- "#sound-dai-cells":
- const: 0
+allOf:
+ - $ref: dai-common.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: canaan,k210-i2s
+ then:
+ properties:
+ "#sound-dai-cells":
+ const: 1
+ else:
+ properties:
+ "#sound-dai-cells":
+ const: 0
required:
- compatible
diff --git a/Documentation/devicetree/bindings/sound/socionext,uniphier-aio.yaml b/Documentation/devicetree/bindings/sound/socionext,uniphier-aio.yaml
index 70f62ecd6eb2..9cf0efaed88e 100644
--- a/Documentation/devicetree/bindings/sound/socionext,uniphier-aio.yaml
+++ b/Documentation/devicetree/bindings/sound/socionext,uniphier-aio.yaml
@@ -9,6 +9,9 @@ title: UniPhier AIO audio system
maintainers:
- <alsa-devel@alsa-project.org>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -70,7 +73,7 @@ patternProperties:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
-additionalProperties: false
+unevaluatedProperties: false
required:
- compatible
diff --git a/Documentation/devicetree/bindings/sound/socionext,uniphier-evea.yaml b/Documentation/devicetree/bindings/sound/socionext,uniphier-evea.yaml
index be6acfda9999..985277648de1 100644
--- a/Documentation/devicetree/bindings/sound/socionext,uniphier-evea.yaml
+++ b/Documentation/devicetree/bindings/sound/socionext,uniphier-evea.yaml
@@ -9,6 +9,9 @@ title: UniPhier EVEA SoC-internal sound codec
maintainers:
- <alsa-devel@alsa-project.org>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
const: socionext,uniphier-evea
@@ -48,7 +51,7 @@ patternProperties:
$ref: audio-graph-port.yaml#
unevaluatedProperties: false
-additionalProperties: false
+unevaluatedProperties: false
required:
- compatible
diff --git a/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml
index d3966ae04ad0..a040d4d31412 100644
--- a/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml
+++ b/Documentation/devicetree/bindings/sound/st,stm32-i2s.yaml
@@ -13,6 +13,9 @@ description:
The SPI/I2S block supports I2S/PCM protocols when configured on I2S mode.
Only some SPI instances support I2S.
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -68,7 +71,7 @@ required:
- dmas
- dma-names
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml b/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml
index 837e830c47ac..bc48151b9adb 100644
--- a/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml
+++ b/Documentation/devicetree/bindings/sound/st,stm32-spdifrx.yaml
@@ -13,6 +13,9 @@ description: |
The SPDIFRX peripheral, is designed to receive an S/PDIF flow compliant with
IEC-60958 and IEC-61937.
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -57,7 +60,7 @@ required:
- dmas
- dma-names
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/tas2562.yaml b/Documentation/devicetree/bindings/sound/tas2562.yaml
index 30f6b029ac08..1085592cefcc 100644
--- a/Documentation/devicetree/bindings/sound/tas2562.yaml
+++ b/Documentation/devicetree/bindings/sound/tas2562.yaml
@@ -22,6 +22,9 @@ description: |
https://www.ti.com/lit/gpn/tas2564
https://www.ti.com/lit/gpn/tas2110
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -58,7 +61,7 @@ required:
- compatible
- reg
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/tas2770.yaml b/Documentation/devicetree/bindings/sound/tas2770.yaml
index bc90e72bf7cf..982949ba8a4b 100644
--- a/Documentation/devicetree/bindings/sound/tas2770.yaml
+++ b/Documentation/devicetree/bindings/sound/tas2770.yaml
@@ -16,6 +16,9 @@ description: |
Integrated speaker voltage and current sense provides for
real time monitoring of loudspeaker behavior.
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -60,7 +63,7 @@ required:
- compatible
- reg
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/tas27xx.yaml b/Documentation/devicetree/bindings/sound/tas27xx.yaml
index 66a0df8850ea..0957dd435bb4 100644
--- a/Documentation/devicetree/bindings/sound/tas27xx.yaml
+++ b/Documentation/devicetree/bindings/sound/tas27xx.yaml
@@ -16,6 +16,9 @@ description: |
loudspeakers. Integrated speaker voltage and current sense provides
for real time monitoring of loudspeaker behavior.
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -53,7 +56,7 @@ required:
- compatible
- reg
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/ti,src4xxx.yaml b/Documentation/devicetree/bindings/sound/ti,src4xxx.yaml
index 9681b72b4918..988ce8d8028f 100644
--- a/Documentation/devicetree/bindings/sound/ti,src4xxx.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,src4xxx.yaml
@@ -14,7 +14,7 @@ maintainers:
- Matt Flax <flatmax@flatmax.com>
allOf:
- - $ref: name-prefix.yaml#
+ - $ref: dai-common.yaml#
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/sound/ti,tlv320adc3xxx.yaml b/Documentation/devicetree/bindings/sound/ti,tlv320adc3xxx.yaml
index 83936f594d1a..ede14ca2c07a 100644
--- a/Documentation/devicetree/bindings/sound/ti,tlv320adc3xxx.yaml
+++ b/Documentation/devicetree/bindings/sound/ti,tlv320adc3xxx.yaml
@@ -14,6 +14,9 @@ description: |
https://www.ti.com/product/TLV320ADC3001
https://www.ti.com/product/TLV320ADC3101
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
enum:
@@ -106,7 +109,7 @@ required:
- reg
- clocks
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml b/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml
index ee698614862e..6b8214071115 100644
--- a/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml
+++ b/Documentation/devicetree/bindings/sound/tlv320adcx140.yaml
@@ -109,38 +109,6 @@ properties:
maximum: 7
default: [0, 0, 0, 0]
- ti,asi-tx-drive:
- type: boolean
- description: |
- When set the device will set the Tx ASI output to a Hi-Z state for unused
- data cycles. Default is to drive the output low on unused ASI cycles.
-
-patternProperties:
- '^ti,gpo-config-[1-4]$':
- $ref: /schemas/types.yaml#/definitions/uint32-array
- description: |
- Defines the configuration and output driver for the general purpose
- output pins (GPO). These values are pairs, the first value is for the
- configuration type and the second value is for the output drive type.
- The array is defined as <GPO_CFG GPO_DRV>
-
- GPO output configuration can be one of the following:
-
- 0 - (default) disabled
- 1 - GPOX is configured as a general-purpose output (GPO)
- 2 - GPOX is configured as a device interrupt output (IRQ)
- 3 - GPOX is configured as a secondary ASI output (SDOUT2)
- 4 - GPOX is configured as a PDM clock output (PDMCLK)
-
- GPO output drive configuration for the GPO pins can be one of the following:
-
- 0d - (default) Hi-Z output
- 1d - Drive active low and active high
- 2d - Drive active low and weak high
- 3d - Drive active low and Hi-Z
- 4d - Drive weak low and active high
- 5d - Drive Hi-Z and active high
-
ti,gpio-config:
description: |
Defines the configuration and output drive for the General Purpose
@@ -183,6 +151,38 @@ patternProperties:
maximum: 15
default: [2, 2]
+ ti,asi-tx-drive:
+ type: boolean
+ description: |
+ When set the device will set the Tx ASI output to a Hi-Z state for unused
+ data cycles. Default is to drive the output low on unused ASI cycles.
+
+patternProperties:
+ '^ti,gpo-config-[1-4]$':
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description: |
+ Defines the configuration and output driver for the general purpose
+ output pins (GPO). These values are pairs, the first value is for the
+ configuration type and the second value is for the output drive type.
+ The array is defined as <GPO_CFG GPO_DRV>
+
+ GPO output configuration can be one of the following:
+
+ 0 - (default) disabled
+ 1 - GPOX is configured as a general-purpose output (GPO)
+ 2 - GPOX is configured as a device interrupt output (IRQ)
+ 3 - GPOX is configured as a secondary ASI output (SDOUT2)
+ 4 - GPOX is configured as a PDM clock output (PDMCLK)
+
+ GPO output drive configuration for the GPO pins can be one of the following:
+
+ 0d - (default) Hi-Z output
+ 1d - Drive active low and active high
+ 2d - Drive active low and weak high
+ 3d - Drive active low and Hi-Z
+ 4d - Drive weak low and active high
+ 5d - Drive Hi-Z and active high
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/sound/wlf,arizona.yaml b/Documentation/devicetree/bindings/sound/wlf,arizona.yaml
index 1627c0bb69be..8156f30eadd6 100644
--- a/Documentation/devicetree/bindings/sound/wlf,arizona.yaml
+++ b/Documentation/devicetree/bindings/sound/wlf,arizona.yaml
@@ -16,6 +16,9 @@ description: |
This document lists sound specific bindings, see the primary binding
document ../mfd/arizona.yaml
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
'#sound-dai-cells':
description:
diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8731.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8731.yaml
index 15795f63b5a3..858c0f689581 100644
--- a/Documentation/devicetree/bindings/sound/wlf,wm8731.yaml
+++ b/Documentation/devicetree/bindings/sound/wlf,wm8731.yaml
@@ -61,6 +61,7 @@ required:
- DCVDD-supply
allOf:
+ - $ref: dai-common.yaml#
- $ref: /schemas/spi/spi-peripheral-props.yaml#
unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8940.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8940.yaml
index 7386abb3a250..3e809217c4ca 100644
--- a/Documentation/devicetree/bindings/sound/wlf,wm8940.yaml
+++ b/Documentation/devicetree/bindings/sound/wlf,wm8940.yaml
@@ -9,6 +9,9 @@ title: Wolfson WM8940 Codec
maintainers:
- patches@opensource.cirrus.com
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
'#sound-dai-cells':
const: 0
@@ -27,7 +30,7 @@ required:
- compatible
- reg
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8961.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8961.yaml
new file mode 100644
index 000000000000..f58078545569
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/wlf,wm8961.yaml
@@ -0,0 +1,43 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/wlf,wm8961.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Wolfson WM8961 Ultra-Low Power Stereo CODEC
+
+maintainers:
+ - patches@opensource.cirrus.com
+
+allOf:
+ - $ref: dai-common.yaml#
+
+properties:
+ compatible:
+ const: wlf,wm8961
+
+ reg:
+ maxItems: 1
+
+ '#sound-dai-cells':
+ const: 0
+
+required:
+ - compatible
+ - reg
+ - '#sound-dai-cells'
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ wm8961: codec@4a {
+ compatible = "wlf,wm8961";
+ reg = <0x4a>;
+ #sound-dai-cells = <0>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8962.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8962.yaml
index 5e172e9462b9..5fe0b2c9f99f 100644
--- a/Documentation/devicetree/bindings/sound/wlf,wm8962.yaml
+++ b/Documentation/devicetree/bindings/sound/wlf,wm8962.yaml
@@ -9,6 +9,9 @@ title: Wolfson WM8962 Ultra-Low Power Stereo CODEC
maintainers:
- patches@opensource.cirrus.com
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
const: wlf,wm8962
@@ -87,7 +90,7 @@ required:
- SPKVDD1-supply
- SPKVDD2-supply
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/wlf,wm8978.yaml b/Documentation/devicetree/bindings/sound/wlf,wm8978.yaml
index 1c8985d4dd5a..efb5f9f6cc7a 100644
--- a/Documentation/devicetree/bindings/sound/wlf,wm8978.yaml
+++ b/Documentation/devicetree/bindings/sound/wlf,wm8978.yaml
@@ -9,6 +9,9 @@ title: Wolfson WM8978 Codec
maintainers:
- patches@opensource.cirrus.com
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
'#sound-dai-cells':
const: 0
@@ -27,7 +30,7 @@ required:
- compatible
- reg
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/sound/zl38060.yaml b/Documentation/devicetree/bindings/sound/zl38060.yaml
index 338e2a13c775..2c5c02e34573 100644
--- a/Documentation/devicetree/bindings/sound/zl38060.yaml
+++ b/Documentation/devicetree/bindings/sound/zl38060.yaml
@@ -15,6 +15,9 @@ maintainers:
- Jaroslav Kysela <perex@perex.cz>
- Takashi Iwai <tiwai@suse.com>
+allOf:
+ - $ref: dai-common.yaml#
+
properties:
compatible:
const: mscc,zl38060
@@ -48,7 +51,7 @@ required:
- gpio-controller
- '#sound-dai-cells'
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/spi/amlogic,meson-gx-spicc.yaml b/Documentation/devicetree/bindings/spi/amlogic,meson-gx-spicc.yaml
index 0c10f7678178..53eb6562b979 100644
--- a/Documentation/devicetree/bindings/spi/amlogic,meson-gx-spicc.yaml
+++ b/Documentation/devicetree/bindings/spi/amlogic,meson-gx-spicc.yaml
@@ -10,9 +10,6 @@ title: Amlogic Meson SPI Communication Controller
maintainers:
- Neil Armstrong <neil.armstrong@linaro.org>
-allOf:
- - $ref: "spi-controller.yaml#"
-
description: |
The Meson SPICC is a generic SPI controller for general purpose Full-Duplex
communications with dedicated 16 words RX/TX PIO FIFOs.
@@ -43,31 +40,53 @@ properties:
minItems: 1
maxItems: 2
-if:
- properties:
- compatible:
- contains:
- enum:
- - amlogic,meson-g12a-spicc
-
-then:
- properties:
- clocks:
- minItems: 2
-
- clock-names:
- items:
- - const: core
- - const: pclk
-
-else:
- properties:
- clocks:
- maxItems: 1
-
- clock-names:
- items:
- - const: core
+allOf:
+ - $ref: "spi-controller.yaml#"
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - amlogic,meson-g12a-spicc
+
+ then:
+ properties:
+ clocks:
+ minItems: 2
+
+ clock-names:
+ items:
+ - const: core
+ - const: pclk
+
+ else:
+ properties:
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ items:
+ - const: core
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - amlogic,meson-gx-spicc
+
+ then:
+ properties:
+ pinctrl-0: true
+ pinctrl-1: true
+ pinctrl-2: true
+
+ pinctrl-names:
+ minItems: 1
+ items:
+ - const: default
+ - const: idle-high
+ - const: idle-low
required:
- compatible
diff --git a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.yaml b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.yaml
index 50df1a40bbe3..12cb76711000 100644
--- a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.yaml
+++ b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.yaml
@@ -23,6 +23,9 @@ properties:
- const: fsl,imx51-ecspi
- const: fsl,imx53-ecspi
- items:
+ - const: fsl,imx8mp-ecspi
+ - const: fsl,imx6ul-ecspi
+ - items:
- enum:
- fsl,imx50-ecspi
- fsl,imx6q-ecspi
@@ -34,7 +37,6 @@ properties:
- fsl,imx8mq-ecspi
- fsl,imx8mm-ecspi
- fsl,imx8mn-ecspi
- - fsl,imx8mp-ecspi
- const: fsl,imx51-ecspi
reg:
diff --git a/Documentation/devicetree/bindings/spi/nuvoton,npcm-fiu.txt b/Documentation/devicetree/bindings/spi/nuvoton,npcm-fiu.txt
index c63ce4cc0a80..fb38e96d395f 100644
--- a/Documentation/devicetree/bindings/spi/nuvoton,npcm-fiu.txt
+++ b/Documentation/devicetree/bindings/spi/nuvoton,npcm-fiu.txt
@@ -51,7 +51,7 @@ fiu3: spi@c00000000 {
clocks = <&clk NPCM7XX_CLK_AHB>;
pinctrl-names = "default";
pinctrl-0 = <&spi3_pins>;
- spi-nor@0 {
+ flash@0 {
...
};
};
diff --git a/Documentation/devicetree/bindings/spi/nuvoton,wpcm450-fiu.yaml b/Documentation/devicetree/bindings/spi/nuvoton,wpcm450-fiu.yaml
new file mode 100644
index 000000000000..4e0d391e1d69
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/nuvoton,wpcm450-fiu.yaml
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/nuvoton,wpcm450-fiu.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Nuvoton WPCM450 Flash Interface Unit (FIU)
+
+maintainers:
+ - Jonathan Neuschäfer <j.neuschaefer@gmx.net>
+
+allOf:
+ - $ref: /schemas/spi/spi-controller.yaml#
+
+properties:
+ compatible:
+ const: nuvoton,wpcm450-fiu
+
+ reg:
+ items:
+ - description: FIU registers
+ - description: Memory-mapped flash contents
+
+ reg-names:
+ items:
+ - const: control
+ - const: memory
+
+ interrupts:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ nuvoton,shm:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: a phandle to the SHM block (see ../arm/nuvoton,shm.yaml)
+
+required:
+ - compatible
+ - reg
+ - clocks
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ spi@c8000000 {
+ compatible = "nuvoton,wpcm450-fiu";
+ reg = <0xc8000000 0x1000>, <0xc0000000 0x4000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-names = "control", "memory";
+ clocks = <&clk 0>;
+ nuvoton,shm = <&shm>;
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ };
+ };
+
+ shm: syscon@c8001000 {
+ compatible = "nuvoton,wpcm450-shm", "syscon";
+ reg = <0xc8001000 0x1000>;
+ };
diff --git a/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml b/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml
index 6b733e5c1163..899100e783c9 100644
--- a/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml
+++ b/Documentation/devicetree/bindings/spi/nvidia,tegra210-quad.yaml
@@ -48,7 +48,7 @@ properties:
- const: tx
patternProperties:
- "@[0-9a-f]+":
+ "@[0-9a-f]+$":
type: object
properties:
diff --git a/Documentation/devicetree/bindings/spi/socionext,f-ospi.yaml b/Documentation/devicetree/bindings/spi/socionext,f-ospi.yaml
new file mode 100644
index 000000000000..9878d1446552
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/socionext,f-ospi.yaml
@@ -0,0 +1,57 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/socionext,f-ospi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Socionext F_OSPI controller
+
+description: |
+ The Socionext F_OSPI is a controller used to interface with flash
+ memories using the SPI communication interface.
+
+maintainers:
+ - Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
+
+allOf:
+ - $ref: spi-controller.yaml#
+
+properties:
+ compatible:
+ const: socionext,f-ospi
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ num-cs:
+ minimum: 1
+ maximum: 4
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - "#address-cells"
+ - "#size-cells"
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ ospi0: spi@80000000 {
+ compatible = "socionext,f-ospi";
+ reg = <0x80000000 0x1000>;
+ clocks = <&clks 0>;
+ num-cs = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ flash@0 {
+ compatible = "spansion,s25fl128s", "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <50000000>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/spi/socionext,synquacer-spi.yaml b/Documentation/devicetree/bindings/spi/socionext,synquacer-spi.yaml
new file mode 100644
index 000000000000..45cbe744c7ff
--- /dev/null
+++ b/Documentation/devicetree/bindings/spi/socionext,synquacer-spi.yaml
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/spi/socionext,synquacer-spi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Socionext SynQuacer HS-SPI Controller
+
+maintainers:
+ - Masahisa Kojima <masahisa.kojima@linaro.org>
+ - Jassi Brar <jaswinder.singh@linaro.org>
+
+allOf:
+ - $ref: spi-controller.yaml#
+
+properties:
+ compatible:
+ const: socionext,synquacer-spi
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ minItems: 1
+ items:
+ - description: core clock
+ - description: rate clock
+
+ clock-names:
+ minItems: 1
+ items:
+ - const: iHCLK
+ - const: iPCLK
+
+ interrupts:
+ items:
+ - description: Receive Interrupt
+ - description: Transmit Interrupt
+ - description: Fault Interrupt
+
+ socionext,use-rtm:
+ type: boolean
+ description: Enable using "retimed clock" for RX
+
+ socionext,set-aces:
+ type: boolean
+ description: Enable same active clock edges field to be set
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - clocks
+ - clock-names
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ spi@ff110000 {
+ compatible = "socionext,synquacer-spi";
+ reg = <0xff110000 0x1000>;
+ interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk_hsspi>;
+ clock-names = "iHCLK";
+ socionext,use-rtm;
+ socionext,set-aces;
+ };
+...
diff --git a/Documentation/devicetree/bindings/spi/spi-fsl-lpspi.yaml b/Documentation/devicetree/bindings/spi/spi-fsl-lpspi.yaml
index 8b44284d30c6..94caa2b7e241 100644
--- a/Documentation/devicetree/bindings/spi/spi-fsl-lpspi.yaml
+++ b/Documentation/devicetree/bindings/spi/spi-fsl-lpspi.yaml
@@ -56,6 +56,13 @@ properties:
this property to re-config the chipselect value in the LPSPI driver.
type: boolean
+ num-cs:
+ description:
+ number of chip selects.
+ minimum: 1
+ maximum: 2
+ default: 1
+
required:
- compatible
- reg
@@ -80,4 +87,5 @@ examples:
clock-names = "per", "ipg";
spi-slave;
fsl,spi-only-use-cs1-sel;
+ num-cs = <2>;
};
diff --git a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
index dca677f9e1b9..ead2cccf658f 100644
--- a/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
+++ b/Documentation/devicetree/bindings/spi/spi-peripheral-props.yaml
@@ -44,6 +44,11 @@ properties:
description:
Maximum SPI clocking speed of the device in Hz.
+ spi-cs-setup-ns:
+ description:
+ Delay in nanosecods to be introduced by the controller after CS is
+ asserted.
+
spi-rx-bus-width:
description:
Bus width to the SPI bus used for read transfers.
diff --git a/Documentation/devicetree/bindings/spi/spi-synquacer.txt b/Documentation/devicetree/bindings/spi/spi-synquacer.txt
deleted file mode 100644
index 291dfa692d0a..000000000000
--- a/Documentation/devicetree/bindings/spi/spi-synquacer.txt
+++ /dev/null
@@ -1,27 +0,0 @@
-* Socionext Synquacer HS-SPI bindings
-
-Required Properties:
-- compatible: should be "socionext,synquacer-spi"
-- reg: physical base address of the controller and length of memory mapped
- region.
-- interrupts: should contain the "spi_rx", "spi_tx" and "spi_fault" interrupts.
-- clocks: core clock iHCLK. Optional rate clock iPCLK (default is iHCLK)
-- clock-names: Shall be "iHCLK" and "iPCLK" respectively
-
-Optional Properties:
-- socionext,use-rtm: boolean, if required to use "retimed clock" for RX
-- socionext,set-aces: boolean, if same active clock edges field to be set.
-
-Example:
-
- spi0: spi@ff110000 {
- compatible = "socionext,synquacer-spi";
- reg = <0xff110000 0x1000>;
- interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clk_hsspi>;
- clock-names = "iHCLK";
- socionext,use-rtm;
- socionext,set-aces;
- };
diff --git a/Documentation/devicetree/bindings/spi/spi-zynqmp-qspi.yaml b/Documentation/devicetree/bindings/spi/spi-zynqmp-qspi.yaml
index 6bf0edc57f4a..546c416cdb55 100644
--- a/Documentation/devicetree/bindings/spi/spi-zynqmp-qspi.yaml
+++ b/Documentation/devicetree/bindings/spi/spi-zynqmp-qspi.yaml
@@ -14,7 +14,9 @@ allOf:
properties:
compatible:
- const: xlnx,zynqmp-qspi-1.0
+ enum:
+ - xlnx,versal-qspi-1.0
+ - xlnx,zynqmp-qspi-1.0
reg:
maxItems: 2
diff --git a/Documentation/devicetree/bindings/sram/qcom,imem.yaml b/Documentation/devicetree/bindings/sram/qcom,imem.yaml
index e9199190198d..665c06e14f79 100644
--- a/Documentation/devicetree/bindings/sram/qcom,imem.yaml
+++ b/Documentation/devicetree/bindings/sram/qcom,imem.yaml
@@ -25,6 +25,7 @@ properties:
- qcom,sdm630-imem
- qcom,sdm845-imem
- qcom,sdx55-imem
+ - qcom,sdx65-imem
- const: syscon
- const: simple-mfd
diff --git a/Documentation/devicetree/bindings/thermal/qcom-lmh.yaml b/Documentation/devicetree/bindings/thermal/qcom-lmh.yaml
index e1587ddf7de3..92762efc2120 100644
--- a/Documentation/devicetree/bindings/thermal/qcom-lmh.yaml
+++ b/Documentation/devicetree/bindings/thermal/qcom-lmh.yaml
@@ -37,7 +37,7 @@ properties:
cpus:
description:
phandle of the first cpu in the LMh cluster
- $ref: /schemas/types.yaml#/definitions/phandle
+ maxItems: 1
qcom,lmh-temp-arm-millicelsius:
description:
diff --git a/Documentation/devicetree/bindings/thermal/qcom-spmi-adc-tm5.yaml b/Documentation/devicetree/bindings/thermal/qcom-spmi-adc-tm5.yaml
index feb390d50696..d20569b9b763 100644
--- a/Documentation/devicetree/bindings/thermal/qcom-spmi-adc-tm5.yaml
+++ b/Documentation/devicetree/bindings/thermal/qcom-spmi-adc-tm5.yaml
@@ -222,8 +222,8 @@ examples:
qcom,hw-settle-time = <200>;
};
- conn-therm@47 {
- reg = <PM8350_ADC7_AMUX_THM4_100K_PU>;
+ conn-therm@147 {
+ reg = <PM8350_ADC7_AMUX_THM4_100K_PU(1)>;
qcom,ratiometric;
qcom,hw-settle-time = <200>;
};
@@ -247,7 +247,7 @@ examples:
conn-therm@1 {
reg = <1>;
- io-channels = <&pmk8350_vadc PM8350_ADC7_AMUX_THM4_100K_PU>;
+ io-channels = <&pmk8350_vadc PM8350_ADC7_AMUX_THM4_100K_PU(1)>;
qcom,avg-samples = <2>;
qcom,ratiometric;
qcom,hw-settle-time-us = <200>;
diff --git a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
index 038d81338fcf..c41fcf404117 100644
--- a/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
+++ b/Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
@@ -53,6 +53,7 @@ properties:
- qcom,sc8280xp-tsens
- qcom,sdm630-tsens
- qcom,sdm845-tsens
+ - qcom,sm6115-tsens
- qcom,sm6350-tsens
- qcom,sm8150-tsens
- qcom,sm8250-tsens
diff --git a/Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml b/Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml
index 850a9841b110..7bb9327caa13 100644
--- a/Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml
+++ b/Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml
@@ -76,9 +76,13 @@ examples:
next-level-cache = <&L2_0>;
L2_0: l2-cache {
compatible = "cache";
+ cache-unified;
+ cache-level = <2>;
next-level-cache = <&L3_0>;
L3_0: l3-cache {
compatible = "cache";
+ cache-unified;
+ cache-level = <3>;
};
};
};
diff --git a/Documentation/devicetree/bindings/thermal/thermal-idle.yaml b/Documentation/devicetree/bindings/thermal/thermal-idle.yaml
index cc938d7ad1f3..0fd6d9ae6196 100644
--- a/Documentation/devicetree/bindings/thermal/thermal-idle.yaml
+++ b/Documentation/devicetree/bindings/thermal/thermal-idle.yaml
@@ -48,99 +48,105 @@ additionalProperties: false
examples:
- |
- #include <dt-bindings/thermal/thermal.h>
+ /{
+ #include <dt-bindings/thermal/thermal.h>
- // Example: Combining idle cooling device on big CPUs with cpufreq cooling device
- cpus {
+ compatible = "foo";
+ model = "foo";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ // Example: Combining idle cooling device on big CPUs with cpufreq cooling device
+ cpus {
#address-cells = <2>;
#size-cells = <0>;
/* ... */
- cpu_b0: cpu@100 {
- device_type = "cpu";
- compatible = "arm,cortex-a72";
- reg = <0x0 0x100>;
- enable-method = "psci";
- capacity-dmips-mhz = <1024>;
- dynamic-power-coefficient = <436>;
- #cooling-cells = <2>; /* min followed by max */
- cpu-idle-states = <&CPU_SLEEP>, <&CLUSTER_SLEEP>;
- thermal-idle {
- #cooling-cells = <2>;
- duration-us = <10000>;
- exit-latency-us = <500>;
- };
+ cpu_b0: cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x0 0x100>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <1024>;
+ dynamic-power-coefficient = <436>;
+ #cooling-cells = <2>; /* min followed by max */
+ cpu-idle-states = <&CPU_SLEEP>, <&CLUSTER_SLEEP>;
+ cpu_b0_therm: thermal-idle {
+ #cooling-cells = <2>;
+ duration-us = <10000>;
+ exit-latency-us = <500>;
+ };
+ };
+
+ cpu_b1: cpu@101 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x0 0x101>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <1024>;
+ dynamic-power-coefficient = <436>;
+ #cooling-cells = <2>; /* min followed by max */
+ cpu-idle-states = <&CPU_SLEEP>, <&CLUSTER_SLEEP>;
+ cpu_b1_therm: thermal-idle {
+ #cooling-cells = <2>;
+ duration-us = <10000>;
+ exit-latency-us = <500>;
};
+ };
- cpu_b1: cpu@101 {
- device_type = "cpu";
- compatible = "arm,cortex-a72";
- reg = <0x0 0x101>;
- enable-method = "psci";
- capacity-dmips-mhz = <1024>;
- dynamic-power-coefficient = <436>;
- #cooling-cells = <2>; /* min followed by max */
- cpu-idle-states = <&CPU_SLEEP>, <&CLUSTER_SLEEP>;
- thermal-idle {
- #cooling-cells = <2>;
- duration-us = <10000>;
- exit-latency-us = <500>;
- };
- };
-
- /* ... */
+ /* ... */
- };
+ };
- /* ... */
+ /* ... */
- thermal_zones {
- cpu_thermal: cpu {
+ thermal_zones {
+ cpu_thermal: cpu {
polling-delay-passive = <100>;
polling-delay = <1000>;
/* ... */
trips {
- cpu_alert0: cpu_alert0 {
- temperature = <65000>;
- hysteresis = <2000>;
- type = "passive";
- };
-
- cpu_alert1: cpu_alert1 {
- temperature = <70000>;
- hysteresis = <2000>;
- type = "passive";
- };
-
- cpu_alert2: cpu_alert2 {
- temperature = <75000>;
- hysteresis = <2000>;
- type = "passive";
- };
-
- cpu_crit: cpu_crit {
- temperature = <95000>;
- hysteresis = <2000>;
- type = "critical";
- };
+ cpu_alert0: cpu_alert0 {
+ temperature = <65000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_alert1: cpu_alert1 {
+ temperature = <70000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_alert2: cpu_alert2 {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ cpu_crit: cpu_crit {
+ temperature = <95000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
};
cooling-maps {
- map0 {
- trip = <&cpu_alert1>;
- cooling-device = <&{/cpus/cpu@100/thermal-idle} 0 15 >,
- <&{/cpus/cpu@101/thermal-idle} 0 15>;
- };
-
- map1 {
- trip = <&cpu_alert2>;
- cooling-device =
- <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&cpu_b1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
- };
+ map0 {
+ trip = <&cpu_alert1>;
+ cooling-device = <&cpu_b0_therm 0 15 >,
+ <&cpu_b1_therm 0 15>;
+ };
+
+ map1 {
+ trip = <&cpu_alert2>;
+ cooling-device = <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu_b1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
};
- };
+ };
+ };
};
diff --git a/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml b/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml
index a4f51f46b7a1..716c6afcca1f 100644
--- a/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml
+++ b/Documentation/devicetree/bindings/timer/fsl,imxgpt.yaml
@@ -31,6 +31,8 @@ properties:
- enum:
- fsl,imx6sl-gpt
- fsl,imx6sx-gpt
+ - fsl,imxrt1050-gpt
+ - fsl,imxrt1170-gpt
- const: fsl,imx6dl-gpt
reg:
diff --git a/Documentation/devicetree/bindings/timer/nuvoton,npcm7xx-timer.yaml b/Documentation/devicetree/bindings/timer/nuvoton,npcm7xx-timer.yaml
index 737af78ad70c..d53e1bb98b8a 100644
--- a/Documentation/devicetree/bindings/timer/nuvoton,npcm7xx-timer.yaml
+++ b/Documentation/devicetree/bindings/timer/nuvoton,npcm7xx-timer.yaml
@@ -25,7 +25,13 @@ properties:
- description: The timer interrupt of timer 0
clocks:
- maxItems: 1
+ items:
+ - description: The reference clock for timer 0
+ - description: The reference clock for timer 1
+ - description: The reference clock for timer 2
+ - description: The reference clock for timer 3
+ - description: The reference clock for timer 4
+ minItems: 1
required:
- compatible
diff --git a/Documentation/devicetree/bindings/timer/renesas,cmt.yaml b/Documentation/devicetree/bindings/timer/renesas,cmt.yaml
index bde6c9b66bf4..a0be1755ea28 100644
--- a/Documentation/devicetree/bindings/timer/renesas,cmt.yaml
+++ b/Documentation/devicetree/bindings/timer/renesas,cmt.yaml
@@ -102,12 +102,14 @@ properties:
- enum:
- renesas,r8a779a0-cmt0 # 32-bit CMT0 on R-Car V3U
- renesas,r8a779f0-cmt0 # 32-bit CMT0 on R-Car S4-8
+ - renesas,r8a779g0-cmt0 # 32-bit CMT0 on R-Car V4H
- const: renesas,rcar-gen4-cmt0 # 32-bit CMT0 on R-Car Gen4
- items:
- enum:
- renesas,r8a779a0-cmt1 # 48-bit CMT on R-Car V3U
- renesas,r8a779f0-cmt1 # 48-bit CMT on R-Car S4-8
+ - renesas,r8a779g0-cmt1 # 48-bit CMT on R-Car V4H
- const: renesas,rcar-gen4-cmt1 # 48-bit CMT on R-Car Gen4
reg:
diff --git a/Documentation/devicetree/bindings/timer/renesas,tmu.yaml b/Documentation/devicetree/bindings/timer/renesas,tmu.yaml
index 60f4c059bcff..a67e427a9e7e 100644
--- a/Documentation/devicetree/bindings/timer/renesas,tmu.yaml
+++ b/Documentation/devicetree/bindings/timer/renesas,tmu.yaml
@@ -38,6 +38,7 @@ properties:
- renesas,tmu-r8a77995 # R-Car D3
- renesas,tmu-r8a779a0 # R-Car V3U
- renesas,tmu-r8a779f0 # R-Car S4-8
+ - renesas,tmu-r8a779g0 # R-Car V4H
- const: renesas,tmu
reg:
diff --git a/Documentation/devicetree/bindings/timer/rockchip,rk-timer.yaml b/Documentation/devicetree/bindings/timer/rockchip,rk-timer.yaml
index dc3bc1e62fe9..b61ed1a431bb 100644
--- a/Documentation/devicetree/bindings/timer/rockchip,rk-timer.yaml
+++ b/Documentation/devicetree/bindings/timer/rockchip,rk-timer.yaml
@@ -18,6 +18,7 @@ properties:
- enum:
- rockchip,rv1108-timer
- rockchip,rk3036-timer
+ - rockchip,rk3128-timer
- rockchip,rk3188-timer
- rockchip,rk3228-timer
- rockchip,rk3229-timer
diff --git a/Documentation/devicetree/bindings/ufs/cdns,ufshc.yaml b/Documentation/devicetree/bindings/ufs/cdns,ufshc.yaml
index fb45f66d6454..835e17269d2d 100644
--- a/Documentation/devicetree/bindings/ufs/cdns,ufshc.yaml
+++ b/Documentation/devicetree/bindings/ufs/cdns,ufshc.yaml
@@ -49,6 +49,8 @@ properties:
reg:
maxItems: 1
+ dma-coherent: true
+
required:
- compatible
- clocks
diff --git a/Documentation/devicetree/bindings/usb/generic-ehci.yaml b/Documentation/devicetree/bindings/usb/generic-ehci.yaml
index c5f629c5bc61..994818cb6044 100644
--- a/Documentation/devicetree/bindings/usb/generic-ehci.yaml
+++ b/Documentation/devicetree/bindings/usb/generic-ehci.yaml
@@ -30,6 +30,7 @@ properties:
- allwinner,sun4i-a10-ehci
- allwinner,sun50i-a64-ehci
- allwinner,sun50i-h6-ehci
+ - allwinner,sun50i-h616-ehci
- allwinner,sun5i-a13-ehci
- allwinner,sun6i-a31-ehci
- allwinner,sun7i-a20-ehci
diff --git a/Documentation/devicetree/bindings/usb/generic-ohci.yaml b/Documentation/devicetree/bindings/usb/generic-ohci.yaml
index f838f78d6164..4fcbd0add49d 100644
--- a/Documentation/devicetree/bindings/usb/generic-ohci.yaml
+++ b/Documentation/devicetree/bindings/usb/generic-ohci.yaml
@@ -20,6 +20,7 @@ properties:
- allwinner,sun4i-a10-ohci
- allwinner,sun50i-a64-ohci
- allwinner,sun50i-h6-ohci
+ - allwinner,sun50i-h616-ohci
- allwinner,sun5i-a13-ohci
- allwinner,sun6i-a31-ohci
- allwinner,sun7i-a20-ohci
diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra124-xusb.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra124-xusb.txt
deleted file mode 100644
index 5bfcc0b4d6b9..000000000000
--- a/Documentation/devicetree/bindings/usb/nvidia,tegra124-xusb.txt
+++ /dev/null
@@ -1,132 +0,0 @@
-NVIDIA Tegra xHCI controller
-============================
-
-The Tegra xHCI controller supports both USB2 and USB3 interfaces exposed by
-the Tegra XUSB pad controller.
-
-Required properties:
---------------------
-- compatible: Must be:
- - Tegra124: "nvidia,tegra124-xusb"
- - Tegra132: "nvidia,tegra132-xusb", "nvidia,tegra124-xusb"
- - Tegra210: "nvidia,tegra210-xusb"
- - Tegra186: "nvidia,tegra186-xusb"
-- reg: Must contain the base and length of the xHCI host registers, XUSB FPCI
- registers and XUSB IPFS registers.
-- reg-names: Must contain the following entries:
- - "hcd"
- - "fpci"
- - "ipfs"
-- interrupts: Must contain the xHCI host interrupt and the mailbox interrupt.
-- clocks: Must contain an entry for each entry in clock-names.
- See ../clock/clock-bindings.txt for details.
-- clock-names: Must include the following entries:
- - xusb_host
- - xusb_host_src
- - xusb_falcon_src
- - xusb_ss
- - xusb_ss_src
- - xusb_ss_div2
- - xusb_hs_src
- - xusb_fs_src
- - pll_u_480m
- - clk_m
- - pll_e
-- resets: Must contain an entry for each entry in reset-names.
- See ../reset/reset.txt for details.
-- reset-names: Must include the following entries:
- - xusb_host
- - xusb_ss
- - xusb_src
- Note that xusb_src is the shared reset for xusb_{ss,hs,fs,falcon,host}_src.
-- nvidia,xusb-padctl: phandle to the XUSB pad controller that is used to
- configure the USB pads used by the XHCI controller
-
-For Tegra124 and Tegra132:
-- avddio-pex-supply: PCIe/USB3 analog logic power supply. Must supply 1.05 V.
-- dvddio-pex-supply: PCIe/USB3 digital logic power supply. Must supply 1.05 V.
-- avdd-usb-supply: USB controller power supply. Must supply 3.3 V.
-- avdd-pll-utmip-supply: UTMI PLL power supply. Must supply 1.8 V.
-- avdd-pll-erefe-supply: PLLE reference PLL power supply. Must supply 1.05 V.
-- avdd-usb-ss-pll-supply: PCIe/USB3 PLL power supply. Must supply 1.05 V.
-- hvdd-usb-ss-supply: High-voltage PCIe/USB3 power supply. Must supply 3.3 V.
-- hvdd-usb-ss-pll-e-supply: High-voltage PLLE power supply. Must supply 3.3 V.
-
-For Tegra210:
-- dvddio-pex-supply: PCIe/USB3 analog logic power supply. Must supply 1.05 V.
-- hvddio-pex-supply: High-voltage PCIe/USB3 power supply. Must supply 1.8 V.
-- avdd-usb-supply: USB controller power supply. Must supply 3.3 V.
-- avdd-pll-utmip-supply: UTMI PLL power supply. Must supply 1.8 V.
-- avdd-pll-uerefe-supply: PLLE reference PLL power supply. Must supply 1.05 V.
-- dvdd-pex-pll-supply: PCIe/USB3 PLL power supply. Must supply 1.05 V.
-- hvdd-pex-pll-e-supply: High-voltage PLLE power supply. Must supply 1.8 V.
-
-For Tegra210 and Tegra186:
-- power-domains: A list of PM domain specifiers that reference each power-domain
- used by the xHCI controller. This list must comprise of a specifier for the
- XUSBA and XUSBC power-domains. See ../power/power_domain.txt and
- ../arm/tegra/nvidia,tegra20-pmc.txt for details.
-- power-domain-names: A list of names that represent each of the specifiers in
- the 'power-domains' property. Must include 'xusb_ss' and 'xusb_host' which
- represent the power-domains XUSBA and XUSBC, respectively. See
- ../power/power_domain.txt for details.
-
-Optional properties:
---------------------
-- phys: Must contain an entry for each entry in phy-names.
- See ../phy/phy-bindings.txt for details.
-- phy-names: Should include an entry for each PHY used by the controller. The
- following PHYs are available:
- - Tegra124: usb2-0, usb2-1, usb2-2, hsic-0, hsic-1, usb3-0, usb3-1
- - Tegra132: usb2-0, usb2-1, usb2-2, hsic-0, hsic-1, usb3-0, usb3-1
- - Tegra210: usb2-0, usb2-1, usb2-2, usb2-3, hsic-0, usb3-0, usb3-1, usb3-2,
- usb3-3
- - Tegra186: usb2-0, usb2-1, usb2-2, hsic-0, usb3-0, usb3-1, usb3-2
-
-Example:
---------
-
- usb@0,70090000 {
- compatible = "nvidia,tegra124-xusb";
- reg = <0x0 0x70090000 0x0 0x8000>,
- <0x0 0x70098000 0x0 0x1000>,
- <0x0 0x70099000 0x0 0x1000>;
- reg-names = "hcd", "fpci", "ipfs";
-
- interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
-
- clocks = <&tegra_car TEGRA124_CLK_XUSB_HOST>,
- <&tegra_car TEGRA124_CLK_XUSB_HOST_SRC>,
- <&tegra_car TEGRA124_CLK_XUSB_FALCON_SRC>,
- <&tegra_car TEGRA124_CLK_XUSB_SS>,
- <&tegra_car TEGRA124_CLK_XUSB_SS_DIV2>,
- <&tegra_car TEGRA124_CLK_XUSB_SS_SRC>,
- <&tegra_car TEGRA124_CLK_XUSB_HS_SRC>,
- <&tegra_car TEGRA124_CLK_XUSB_FS_SRC>,
- <&tegra_car TEGRA124_CLK_PLL_U_480M>,
- <&tegra_car TEGRA124_CLK_CLK_M>,
- <&tegra_car TEGRA124_CLK_PLL_E>;
- clock-names = "xusb_host", "xusb_host_src", "xusb_falcon_src",
- "xusb_ss", "xusb_ss_div2", "xusb_ss_src",
- "xusb_hs_src", "xusb_fs_src", "pll_u_480m",
- "clk_m", "pll_e";
- resets = <&tegra_car 89>, <&tegra_car 156>, <&tegra_car 143>;
- reset-names = "xusb_host", "xusb_ss", "xusb_src";
-
- nvidia,xusb-padctl = <&padctl>;
-
- phys = <&{/padctl@0,7009f000/pads/usb2/lanes/usb2-1}>, /* mini-PCIe USB */
- <&{/padctl@0,7009f000/pads/usb2/lanes/usb2-2}>, /* USB A */
- <&{/padctl@0,7009f000/pads/pcie/lanes/pcie-0}>; /* USB A */
- phy-names = "usb2-1", "usb2-2", "usb3-0";
-
- avddio-pex-supply = <&vdd_1v05_run>;
- dvddio-pex-supply = <&vdd_1v05_run>;
- avdd-usb-supply = <&vdd_3v3_lp0>;
- avdd-pll-utmip-supply = <&vddio_1v8>;
- avdd-pll-erefe-supply = <&avdd_1v05_run>;
- avdd-usb-ss-pll-supply = <&vdd_1v05_run>;
- hvdd-usb-ss-supply = <&vdd_3v3_lp0>;
- hvdd-usb-ss-pll-e-supply = <&vdd_3v3_lp0>;
- };
diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra124-xusb.yaml b/Documentation/devicetree/bindings/usb/nvidia,tegra124-xusb.yaml
new file mode 100644
index 000000000000..4a6616bf9bab
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/nvidia,tegra124-xusb.yaml
@@ -0,0 +1,202 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/nvidia,tegra124-xusb.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Tegra124 xHCI controller
+
+maintainers:
+ - Thierry Reding <thierry.reding@gmail.com>
+ - Jon Hunter <jonathanh@nvidia.com>
+
+description: The Tegra xHCI controller supports both USB2 and USB3 interfaces
+ exposed by the Tegra XUSB pad controller.
+
+properties:
+ # required
+ compatible:
+ oneOf:
+ - description: NVIDIA Tegra124
+ const: nvidia,tegra124-xusb
+
+ - description: NVIDIA Tegra132
+ items:
+ - const: nvidia,tegra132-xusb
+ - const: nvidia,tegra124-xusb
+
+ reg:
+ items:
+ - description: base and length of the xHCI host registers
+ - description: base and length of the XUSB FPCI registers
+ - description: base and length of the XUSB IPFS registers
+
+ reg-names:
+ items:
+ - const: hcd
+ - const: fpci
+ - const: ipfs
+
+ interrupts:
+ items:
+ - description: xHCI host interrupt
+ - description: mailbox interrupt
+
+ clocks:
+ items:
+ - description: XUSB host clock
+ - description: XUSB host source clock
+ - description: XUSB Falcon source clock
+ - description: XUSB SuperSpeed clock
+ - description: XUSB SuperSpeed clock divider
+ - description: XUSB SuperSpeed source clock
+ - description: XUSB HighSpeed clock source
+ - description: XUSB FullSpeed clock source
+ - description: USB PLL
+ - description: reference clock
+ - description: I/O PLL
+
+ clock-names:
+ items:
+ - const: xusb_host
+ - const: xusb_host_src
+ - const: xusb_falcon_src
+ - const: xusb_ss
+ - const: xusb_ss_div2
+ - const: xusb_ss_src
+ - const: xusb_hs_src
+ - const: xusb_fs_src
+ - const: pll_u_480m
+ - const: clk_m
+ - const: pll_e
+
+ resets:
+ items:
+ - description: reset for the XUSB host controller
+ - description: reset for the SuperSpeed logic
+ - description: shared reset for xusb_{ss,hs,fs,falcon,host}_src.
+
+ reset-names:
+ items:
+ - const: xusb_host
+ - const: xusb_ss
+ - const: xusb_src
+
+ nvidia,xusb-padctl:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: phandle to the XUSB pad controller that is used to configure
+ the USB pads used by the XHCI controller
+
+ # optional
+ phys:
+ minItems: 1
+ maxItems: 7
+
+ phy-names:
+ minItems: 1
+ maxItems: 7
+ items:
+ enum:
+ - usb2-0
+ - usb2-1
+ - usb2-2
+ - hsic-0
+ - hsic-1
+ - usb3-0
+ - usb3-1
+
+ avddio-pex-supply:
+ description: PCIe/USB3 analog logic power supply. Must supply 1.05 V.
+
+ dvddio-pex-supply:
+ description: PCIe/USB3 digital logic power supply. Must supply 1.05 V.
+
+ avdd-usb-supply:
+ description: USB controller power supply. Must supply 3.3 V.
+
+ avdd-pll-utmip-supply:
+ description: UTMI PLL power supply. Must supply 1.8 V.
+
+ avdd-pll-erefe-supply:
+ description: PLLE reference PLL power supply. Must supply 1.05 V.
+
+ avdd-usb-ss-pll-supply:
+ description: PCIe/USB3 PLL power supply. Must supply 1.05 V.
+
+ hvdd-usb-ss-supply:
+ description: High-voltage PCIe/USB3 power supply. Must supply 3.3 V.
+
+ hvdd-usb-ss-pll-e-supply:
+ description: High-voltage PLLE power supply. Must supply 3.3 V.
+
+allOf:
+ - $ref: usb-xhci.yaml
+
+unevaluatedProperties: false
+
+required:
+ - compatible
+ - reg
+ - reg-names
+ - interrupts
+ - clocks
+ - clock-names
+ - resets
+ - reset-names
+ - nvidia,xusb-padctl
+ - phys
+ - phy-names
+ - avddio-pex-supply
+ - dvddio-pex-supply
+ - avdd-usb-supply
+ - hvdd-usb-ss-supply
+
+examples:
+ - |
+ #include <dt-bindings/clock/tegra124-car.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ usb@70090000 {
+ compatible = "nvidia,tegra124-xusb";
+ reg = <0x70090000 0x8000>,
+ <0x70098000 0x1000>,
+ <0x70099000 0x1000>;
+ reg-names = "hcd", "fpci", "ipfs";
+
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&tegra_car TEGRA124_CLK_XUSB_HOST>,
+ <&tegra_car TEGRA124_CLK_XUSB_HOST_SRC>,
+ <&tegra_car TEGRA124_CLK_XUSB_FALCON_SRC>,
+ <&tegra_car TEGRA124_CLK_XUSB_SS>,
+ <&tegra_car TEGRA124_CLK_XUSB_SS_DIV2>,
+ <&tegra_car TEGRA124_CLK_XUSB_SS_SRC>,
+ <&tegra_car TEGRA124_CLK_XUSB_HS_SRC>,
+ <&tegra_car TEGRA124_CLK_XUSB_FS_SRC>,
+ <&tegra_car TEGRA124_CLK_PLL_U_480M>,
+ <&tegra_car TEGRA124_CLK_CLK_M>,
+ <&tegra_car TEGRA124_CLK_PLL_E>;
+ clock-names = "xusb_host", "xusb_host_src", "xusb_falcon_src",
+ "xusb_ss", "xusb_ss_div2", "xusb_ss_src",
+ "xusb_hs_src", "xusb_fs_src", "pll_u_480m",
+ "clk_m", "pll_e";
+ resets = <&tegra_car 89>, <&tegra_car 156>, <&tegra_car 143>;
+ reset-names = "xusb_host", "xusb_ss", "xusb_src";
+
+ nvidia,xusb-padctl = <&padctl>;
+
+ phys = <&{/padctl@0,7009f000/pads/usb2/lanes/usb2-1}>, /* mini-PCIe USB */
+ <&{/padctl@0,7009f000/pads/usb2/lanes/usb2-2}>, /* USB A */
+ <&{/padctl@0,7009f000/pads/pcie/lanes/pcie-0}>; /* USB A */
+ phy-names = "usb2-1", "usb2-2", "usb3-0";
+
+ avddio-pex-supply = <&vdd_1v05_run>;
+ dvddio-pex-supply = <&vdd_1v05_run>;
+ avdd-usb-supply = <&vdd_3v3_lp0>;
+ avdd-pll-utmip-supply = <&vddio_1v8>;
+ avdd-pll-erefe-supply = <&avdd_1v05_run>;
+ avdd-usb-ss-pll-supply = <&vdd_1v05_run>;
+ hvdd-usb-ss-supply = <&vdd_3v3_lp0>;
+ hvdd-usb-ss-pll-e-supply = <&vdd_3v3_lp0>;
+ };
diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra186-xusb.yaml b/Documentation/devicetree/bindings/usb/nvidia,tegra186-xusb.yaml
new file mode 100644
index 000000000000..6f62944fc597
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/nvidia,tegra186-xusb.yaml
@@ -0,0 +1,173 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/nvidia,tegra186-xusb.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Tegra186 xHCI controller
+
+maintainers:
+ - Thierry Reding <thierry.reding@gmail.com>
+ - Jon Hunter <jonathanh@nvidia.com>
+
+description: The Tegra xHCI controller supports both USB2 and USB3 interfaces
+ exposed by the Tegra XUSB pad controller.
+
+properties:
+ compatible:
+ const: nvidia,tegra186-xusb
+
+ reg:
+ items:
+ - description: base and length of the xHCI host registers
+ - description: base and length of the XUSB FPCI registers
+
+ reg-names:
+ items:
+ - const: hcd
+ - const: fpci
+
+ interrupts:
+ items:
+ - description: xHCI host interrupt
+ - description: mailbox interrupt
+
+ clocks:
+ items:
+ - description: XUSB host clock
+ - description: XUSB Falcon source clock
+ - description: XUSB SuperSpeed clock
+ - description: XUSB SuperSpeed source clock
+ - description: XUSB HighSpeed clock source
+ - description: XUSB FullSpeed clock source
+ - description: USB PLL
+ - description: reference clock
+ - description: I/O PLL
+
+ clock-names:
+ items:
+ - const: xusb_host
+ - const: xusb_falcon_src
+ - const: xusb_ss
+ - const: xusb_ss_src
+ - const: xusb_hs_src
+ - const: xusb_fs_src
+ - const: pll_u_480m
+ - const: clk_m
+ - const: pll_e
+
+ interconnects:
+ items:
+ - description: read client
+ - description: write client
+
+ interconnect-names:
+ items:
+ - const: dma-mem # read
+ - const: write
+
+ iommus:
+ maxItems: 1
+
+ nvidia,xusb-padctl:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: phandle to the XUSB pad controller that is used to configure
+ the USB pads used by the XHCI controller
+
+ phys:
+ minItems: 1
+ maxItems: 7
+
+ phy-names:
+ minItems: 1
+ maxItems: 7
+ items:
+ enum:
+ - usb2-0
+ - usb2-1
+ - usb2-2
+ - hsic-0
+ - usb3-0
+ - usb3-1
+ - usb3-2
+
+ power-domains:
+ items:
+ - description: XUSBC power domain (for Host and USB 2.0)
+ - description: XUSBA power domain (for SuperSpeed)
+
+ power-domain-names:
+ items:
+ - const: xusb_host
+ - const: xusb_ss
+
+ dvddio-pex-supply:
+ description: PCIe/USB3 analog logic power supply. Must supply 1.05 V.
+
+ hvddio-pex-supply:
+ description: High-voltage PCIe/USB3 power supply. Must supply 1.8 V.
+
+ avdd-usb-supply:
+ description: USB controller power supply. Must supply 3.3 V.
+
+ avdd-pll-utmip-supply:
+ description: UTMI PLL power supply. Must supply 1.8 V.
+
+ avdd-pll-uerefe-supply:
+ description: PLLE reference PLL power supply. Must supply 1.05 V.
+
+ dvdd-usb-ss-pll-supply:
+ description: PCIe/USB3 PLL power supply. Must supply 1.05 V.
+
+ hvdd-usb-ss-pll-e-supply:
+ description: High-voltage PLLE power supply. Must supply 1.8 V.
+
+allOf:
+ - $ref: usb-xhci.yaml
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/tegra186-clock.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/memory/tegra186-mc.h>
+ #include <dt-bindings/power/tegra186-powergate.h>
+ #include <dt-bindings/reset/tegra186-reset.h>
+
+ usb@3530000 {
+ compatible = "nvidia,tegra186-xusb";
+ reg = <0x03530000 0x8000>,
+ <0x03538000 0x1000>;
+ reg-names = "hcd", "fpci";
+ interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&bpmp TEGRA186_CLK_XUSB_HOST>,
+ <&bpmp TEGRA186_CLK_XUSB_FALCON>,
+ <&bpmp TEGRA186_CLK_XUSB_SS>,
+ <&bpmp TEGRA186_CLK_XUSB_CORE_SS>,
+ <&bpmp TEGRA186_CLK_CLK_M>,
+ <&bpmp TEGRA186_CLK_XUSB_FS>,
+ <&bpmp TEGRA186_CLK_PLLU>,
+ <&bpmp TEGRA186_CLK_CLK_M>,
+ <&bpmp TEGRA186_CLK_PLLE>;
+ clock-names = "xusb_host", "xusb_falcon_src", "xusb_ss",
+ "xusb_ss_src", "xusb_hs_src", "xusb_fs_src",
+ "pll_u_480m", "clk_m", "pll_e";
+ power-domains = <&bpmp TEGRA186_POWER_DOMAIN_XUSBC>,
+ <&bpmp TEGRA186_POWER_DOMAIN_XUSBA>;
+ power-domain-names = "xusb_host", "xusb_ss";
+ interconnects = <&mc TEGRA186_MEMORY_CLIENT_XUSB_HOSTR &emc>,
+ <&mc TEGRA186_MEMORY_CLIENT_XUSB_HOSTW &emc>;
+ interconnect-names = "dma-mem", "write";
+ iommus = <&smmu TEGRA186_SID_XUSB_HOST>;
+ nvidia,xusb-padctl = <&padctl>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ phys = <&{/padctl@3520000/pads/usb2/lanes/usb2-0}>,
+ <&{/padctl@3520000/pads/usb2/lanes/usb2-1}>,
+ <&{/padctl@3520000/pads/usb3/lanes/usb3-0}>;
+ phy-names = "usb2-0", "usb2-1", "usb3-0";
+ };
diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra194-xusb.yaml b/Documentation/devicetree/bindings/usb/nvidia,tegra194-xusb.yaml
new file mode 100644
index 000000000000..65ae9ae9b0b7
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/nvidia,tegra194-xusb.yaml
@@ -0,0 +1,179 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/nvidia,tegra194-xusb.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Tegra194 xHCI controller
+
+maintainers:
+ - Thierry Reding <thierry.reding@gmail.com>
+ - Jon Hunter <jonathanh@nvidia.com>
+
+description: The Tegra xHCI controller supports both USB2 and USB3 interfaces
+ exposed by the Tegra XUSB pad controller.
+
+properties:
+ compatible:
+ const: nvidia,tegra194-xusb
+
+ reg:
+ items:
+ - description: base and length of the xHCI host registers
+ - description: base and length of the XUSB FPCI registers
+
+ reg-names:
+ items:
+ - const: hcd
+ - const: fpci
+
+ interrupts:
+ items:
+ - description: xHCI host interrupt
+ - description: mailbox interrupt
+
+ clocks:
+ items:
+ - description: XUSB host clock
+ - description: XUSB Falcon source clock
+ - description: XUSB SuperSpeed clock
+ - description: XUSB SuperSpeed source clock
+ - description: XUSB HighSpeed clock source
+ - description: XUSB FullSpeed clock source
+ - description: USB PLL
+ - description: reference clock
+ - description: I/O PLL
+
+ clock-names:
+ items:
+ - const: xusb_host
+ - const: xusb_falcon_src
+ - const: xusb_ss
+ - const: xusb_ss_src
+ - const: xusb_hs_src
+ - const: xusb_fs_src
+ - const: pll_u_480m
+ - const: clk_m
+ - const: pll_e
+
+ interconnects:
+ items:
+ - description: read client
+ - description: write client
+
+ interconnect-names:
+ items:
+ - const: dma-mem # read
+ - const: write
+
+ iommus:
+ maxItems: 1
+
+ nvidia,xusb-padctl:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: phandle to the XUSB pad controller that is used to configure
+ the USB pads used by the XHCI controller
+
+ phys:
+ minItems: 1
+ maxItems: 8
+
+ phy-names:
+ minItems: 1
+ maxItems: 8
+ items:
+ enum:
+ - usb2-0
+ - usb2-1
+ - usb2-2
+ - usb2-3
+ - usb3-0
+ - usb3-1
+ - usb3-2
+ - usb3-3
+
+ power-domains:
+ items:
+ - description: XUSBC power domain (for Host and USB 2.0)
+ - description: XUSBA power domain (for SuperSpeed)
+
+ power-domain-names:
+ items:
+ - const: xusb_host
+ - const: xusb_ss
+
+ dvddio-pex-supply:
+ description: PCIe/USB3 analog logic power supply. Must supply 1.05 V.
+
+ hvddio-pex-supply:
+ description: High-voltage PCIe/USB3 power supply. Must supply 1.8 V.
+
+ avdd-usb-supply:
+ description: USB controller power supply. Must supply 3.3 V.
+
+ avdd-pll-utmip-supply:
+ description: UTMI PLL power supply. Must supply 1.8 V.
+
+ avdd-pll-uerefe-supply:
+ description: PLLE reference PLL power supply. Must supply 1.05 V.
+
+ dvdd-usb-ss-pll-supply:
+ description: PCIe/USB3 PLL power supply. Must supply 1.05 V.
+
+ hvdd-usb-ss-pll-e-supply:
+ description: High-voltage PLLE power supply. Must supply 1.8 V.
+
+allOf:
+ - $ref: usb-xhci.yaml
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/tegra194-clock.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/memory/tegra194-mc.h>
+ #include <dt-bindings/power/tegra194-powergate.h>
+ #include <dt-bindings/reset/tegra194-reset.h>
+
+ usb@3610000 {
+ compatible = "nvidia,tegra194-xusb";
+ reg = <0x03610000 0x40000>,
+ <0x03600000 0x10000>;
+ reg-names = "hcd", "fpci";
+
+ interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&bpmp TEGRA194_CLK_XUSB_CORE_HOST>,
+ <&bpmp TEGRA194_CLK_XUSB_FALCON>,
+ <&bpmp TEGRA194_CLK_XUSB_CORE_SS>,
+ <&bpmp TEGRA194_CLK_XUSB_SS>,
+ <&bpmp TEGRA194_CLK_CLK_M>,
+ <&bpmp TEGRA194_CLK_XUSB_FS>,
+ <&bpmp TEGRA194_CLK_UTMIPLL>,
+ <&bpmp TEGRA194_CLK_CLK_M>,
+ <&bpmp TEGRA194_CLK_PLLE>;
+ clock-names = "xusb_host", "xusb_falcon_src",
+ "xusb_ss", "xusb_ss_src", "xusb_hs_src",
+ "xusb_fs_src", "pll_u_480m", "clk_m",
+ "pll_e";
+ interconnects = <&mc TEGRA194_MEMORY_CLIENT_XUSB_HOSTR &emc>,
+ <&mc TEGRA194_MEMORY_CLIENT_XUSB_HOSTW &emc>;
+ interconnect-names = "dma-mem", "write";
+ iommus = <&smmu TEGRA194_SID_XUSB_HOST>;
+
+ power-domains = <&bpmp TEGRA194_POWER_DOMAIN_XUSBC>,
+ <&bpmp TEGRA194_POWER_DOMAIN_XUSBA>;
+ power-domain-names = "xusb_host", "xusb_ss";
+
+ nvidia,xusb-padctl = <&xusb_padctl>;
+
+ phys = <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-0}>,
+ <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-1}>,
+ <&{/bus@0/padctl@3520000/pads/usb2/lanes/usb2-3}>,
+ <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-0}>,
+ <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-2}>,
+ <&{/bus@0/padctl@3520000/pads/usb3/lanes/usb3-3}>;
+ phy-names = "usb2-0", "usb2-1", "usb2-3", "usb3-0", "usb3-2", "usb3-3";
+ };
diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra210-xusb.yaml b/Documentation/devicetree/bindings/usb/nvidia,tegra210-xusb.yaml
new file mode 100644
index 000000000000..da1e1ec0e7c8
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/nvidia,tegra210-xusb.yaml
@@ -0,0 +1,199 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/nvidia,tegra210-xusb.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Tegra210 xHCI controller
+
+maintainers:
+ - Thierry Reding <thierry.reding@gmail.com>
+ - Jon Hunter <jonathanh@nvidia.com>
+
+description: The Tegra xHCI controller supports both USB2 and USB3 interfaces
+ exposed by the Tegra XUSB pad controller.
+
+properties:
+ compatible:
+ const: nvidia,tegra210-xusb
+
+ reg:
+ items:
+ - description: base and length of the xHCI host registers
+ - description: base and length of the XUSB FPCI registers
+ - description: base and length of the XUSB IPFS registers
+
+ reg-names:
+ items:
+ - const: hcd
+ - const: fpci
+ - const: ipfs
+
+ interrupts:
+ items:
+ - description: xHCI host interrupt
+ - description: mailbox interrupt
+
+ clocks:
+ items:
+ - description: XUSB host clock
+ - description: XUSB host source clock
+ - description: XUSB Falcon source clock
+ - description: XUSB SuperSpeed clock
+ - description: XUSB SuperSpeed clock divider
+ - description: XUSB SuperSpeed source clock
+ - description: XUSB HighSpeed clock source
+ - description: XUSB FullSpeed clock source
+ - description: USB PLL
+ - description: reference clock
+ - description: I/O PLL
+
+ clock-names:
+ items:
+ - const: xusb_host
+ - const: xusb_host_src
+ - const: xusb_falcon_src
+ - const: xusb_ss
+ - const: xusb_ss_div2
+ - const: xusb_ss_src
+ - const: xusb_hs_src
+ - const: xusb_fs_src
+ - const: pll_u_480m
+ - const: clk_m
+ - const: pll_e
+
+ resets:
+ items:
+ - description: reset for the XUSB host controller
+ - description: reset for the SuperSpeed logic
+ - description: shared reset for xusb_{ss,hs,fs,falcon,host}_src.
+
+ reset-names:
+ items:
+ - const: xusb_host
+ - const: xusb_ss
+ - const: xusb_src
+
+ nvidia,xusb-padctl:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: phandle to the XUSB pad controller that is used to configure
+ the USB pads used by the XHCI controller
+
+ phys:
+ minItems: 1
+ maxItems: 9
+
+ phy-names:
+ minItems: 1
+ maxItems: 9
+ items:
+ enum:
+ - usb2-0
+ - usb2-1
+ - usb2-2
+ - usb2-3
+ - hsic-0
+ - usb3-0
+ - usb3-1
+ - usb3-2
+ - usb3-3
+
+ power-domains:
+ items:
+ - description: XUSBC power domain (for Host and USB 2.0)
+ - description: XUSBA power domain (for SuperSpeed)
+
+ power-domain-names:
+ items:
+ - const: xusb_host
+ - const: xusb_ss
+
+ dvddio-pex-supply:
+ description: PCIe/USB3 analog logic power supply. Must supply 1.05 V.
+
+ hvddio-pex-supply:
+ description: High-voltage PCIe/USB3 power supply. Must supply 1.8 V.
+
+ avdd-usb-supply:
+ description: USB controller power supply. Must supply 3.3 V.
+
+ avdd-pll-utmip-supply:
+ description: UTMI PLL power supply. Must supply 1.8 V.
+
+ avdd-pll-uerefe-supply:
+ description: PLLE reference PLL power supply. Must supply 1.05 V.
+
+ dvdd-usb-ss-pll-supply:
+ description: PCIe/USB3 PLL power supply. Must supply 1.05 V.
+
+ hvdd-usb-ss-pll-e-supply:
+ description: High-voltage PLLE power supply. Must supply 1.8 V.
+
+allOf:
+ - $ref: usb-xhci.yaml
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/tegra210-car.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+
+ usb@70090000 {
+ compatible = "nvidia,tegra210-xusb";
+ reg = <0x70090000 0x8000>,
+ <0x70098000 0x1000>,
+ <0x70099000 0x1000>;
+ reg-names = "hcd", "fpci", "ipfs";
+
+ interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&tegra_car TEGRA210_CLK_XUSB_HOST>,
+ <&tegra_car TEGRA210_CLK_XUSB_HOST_SRC>,
+ <&tegra_car TEGRA210_CLK_XUSB_FALCON_SRC>,
+ <&tegra_car TEGRA210_CLK_XUSB_SS>,
+ <&tegra_car TEGRA210_CLK_XUSB_SS_DIV2>,
+ <&tegra_car TEGRA210_CLK_XUSB_SS_SRC>,
+ <&tegra_car TEGRA210_CLK_XUSB_HS_SRC>,
+ <&tegra_car TEGRA210_CLK_XUSB_FS_SRC>,
+ <&tegra_car TEGRA210_CLK_PLL_U_480M>,
+ <&tegra_car TEGRA210_CLK_CLK_M>,
+ <&tegra_car TEGRA210_CLK_PLL_E>;
+ clock-names = "xusb_host", "xusb_host_src",
+ "xusb_falcon_src", "xusb_ss",
+ "xusb_ss_div2", "xusb_ss_src",
+ "xusb_hs_src", "xusb_fs_src",
+ "pll_u_480m", "clk_m", "pll_e";
+ resets = <&tegra_car 89>, <&tegra_car 156>,
+ <&tegra_car 143>;
+ reset-names = "xusb_host", "xusb_ss", "xusb_src";
+ power-domains = <&pd_xusbhost>, <&pd_xusbss>;
+ power-domain-names = "xusb_host", "xusb_ss";
+
+ nvidia,xusb-padctl = <&padctl>;
+
+ phys = <&{/padctl@7009f000/pads/usb2/lanes/usb2-0}>,
+ <&{/padctl@7009f000/pads/usb2/lanes/usb2-1}>,
+ <&{/padctl@7009f000/pads/usb2/lanes/usb2-2}>,
+ <&{/padctl@7009f000/pads/usb2/lanes/usb2-3}>,
+ <&{/padctl@7009f000/pads/pcie/lanes/pcie-6}>,
+ <&{/padctl@7009f000/pads/pcie/lanes/pcie-5}>;
+ phy-names = "usb2-0", "usb2-1", "usb2-2", "usb2-3", "usb3-0",
+ "usb3-1";
+ dvddio-pex-supply = <&vdd_pex_1v05>;
+ hvddio-pex-supply = <&vdd_1v8>;
+ avdd-usb-supply = <&vdd_3v3_sys>;
+ avdd-pll-utmip-supply = <&vdd_1v8>;
+ avdd-pll-uerefe-supply = <&vdd_pex_1v05>;
+ dvdd-usb-ss-pll-supply = <&vdd_pex_1v05>;
+ hvdd-usb-ss-pll-e-supply = <&vdd_1v8>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethernet@1 {
+ compatible = "usb955,9ff";
+ reg = <1>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 6e323a380294..d5f1c4c1ef45 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -69,6 +69,8 @@ patternProperties:
description: Annapurna Labs
"^alcatel,.*":
description: Alcatel
+ "^alfa-network,.*":
+ description: ALFA Network Inc.
"^allegro,.*":
description: Allegro DVT
"^allo,.*":
@@ -246,6 +248,8 @@ patternProperties:
description: ChipOne
"^chipspark,.*":
description: ChipSPARK
+ "^chongzhou,.*":
+ description: Shenzhen Chongzhou Electronic Technology Co., Ltd
"^chrontel,.*":
description: Chrontel, Inc.
"^chrp,.*":
@@ -260,6 +264,8 @@ patternProperties:
description: Cirrus Logic, Inc.
"^cisco,.*":
description: Cisco Systems, Inc.
+ "^cloos,.*":
+ description: Carl Cloos Schweisstechnik GmbH.
"^cloudengines,.*":
description: Cloud Engines, Inc.
"^cnm,.*":
@@ -567,6 +573,8 @@ patternProperties:
description: Hycon Technology Corp.
"^hydis,.*":
description: Hydis Technologies
+ "^hynitron,.*":
+ description: Shanghai Hynitron Microelectronics Co. Ltd.
"^hynix,.*":
description: SK Hynix Inc.
"^hyundai,.*":
@@ -605,6 +613,8 @@ patternProperties:
description: Ingenic Semiconductor
"^injoinic,.*":
description: Injoinic Technology Corp.
+ "^innocomm,.*":
+ description: InnoComm Mobile Technology Corp.
"^innolux,.*":
description: Innolux Corporation
"^inside-secure,.*":
@@ -639,6 +649,8 @@ patternProperties:
description: ITian Corporation
"^iwave,.*":
description: iWave Systems Technologies Pvt. Ltd.
+ "^jadard,.*":
+ description: Jadard Technology Inc.
"^jdi,.*":
description: Japan Display Inc.
"^jedec,.*":
@@ -883,6 +895,8 @@ patternProperties:
description: Shenzhen Netxeon Technology CO., LTD
"^neweast,.*":
description: Guangdong Neweast Optoelectronics CO., LTD
+ "^newvision,.*":
+ description: New Vision Display (Shenzhen) Co., Ltd.
"^nexbox,.*":
description: Nexbox
"^nextthing,.*":
diff --git a/Documentation/doc-guide/sphinx.rst b/Documentation/doc-guide/sphinx.rst
index c708cec889af..23edb427e76f 100644
--- a/Documentation/doc-guide/sphinx.rst
+++ b/Documentation/doc-guide/sphinx.rst
@@ -147,11 +147,9 @@ section of ``make help``. The generated documentation is placed in
format-specific subdirectories under ``Documentation/output``.
To generate documentation, Sphinx (``sphinx-build``) must obviously be
-installed. For prettier HTML output, the Read the Docs Sphinx theme
-(``sphinx_rtd_theme``) is used if available. For PDF output you'll also need
-``XeLaTeX`` and ``convert(1)`` from ImageMagick
-(https://www.imagemagick.org).\ [#ink]_
-All of these are widely available and packaged in distributions.
+installed. For PDF output you'll also need ``XeLaTeX`` and ``convert(1)``
+from ImageMagick (https://www.imagemagick.org).\ [#ink]_ All of these are
+widely available and packaged in distributions.
To pass extra options to Sphinx, you can use the ``SPHINXOPTS`` make
variable. For example, use ``make SPHINXOPTS=-v htmldocs`` to get more verbose
@@ -160,12 +158,8 @@ output.
It is also possible to pass an extra DOCS_CSS overlay file, in order to customize
the html layout, by using the ``DOCS_CSS`` make variable.
-By default, the build will try to use the Read the Docs sphinx theme:
-
- https://github.com/readthedocs/sphinx_rtd_theme
-
-If the theme is not available, it will fall-back to the classic one.
-
+By default, the "Alabaster" theme is used to build the HTML documentation;
+this theme is bundled with Sphinx and need not be installed separately.
The Sphinx theme can be overridden by using the ``DOCS_THEME`` make variable.
There is another make variable ``SPHINXDIRS``, which is useful when test
diff --git a/Documentation/driver-api/dma-buf.rst b/Documentation/driver-api/dma-buf.rst
index 36a76cbe9095..622b8156d212 100644
--- a/Documentation/driver-api/dma-buf.rst
+++ b/Documentation/driver-api/dma-buf.rst
@@ -119,6 +119,12 @@ DMA Buffer ioctls
.. kernel-doc:: include/uapi/linux/dma-buf.h
+DMA-BUF locking convention
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. kernel-doc:: drivers/dma-buf/dma-buf.c
+ :doc: locking convention
+
Kernel Functions and Structures Reference
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/Documentation/driver-api/driver-model/devres.rst b/Documentation/driver-api/driver-model/devres.rst
index 56082265e8e5..8abf9dda3241 100644
--- a/Documentation/driver-api/driver-model/devres.rst
+++ b/Documentation/driver-api/driver-model/devres.rst
@@ -287,12 +287,16 @@ IIO
devm_iio_device_register()
devm_iio_dmaengine_buffer_setup()
devm_iio_kfifo_buffer_setup()
+ devm_iio_kfifo_buffer_setup_ext()
devm_iio_map_array_register()
devm_iio_triggered_buffer_setup()
+ devm_iio_triggered_buffer_setup_ext()
devm_iio_trigger_alloc()
devm_iio_trigger_register()
devm_iio_channel_get()
devm_iio_channel_get_all()
+ devm_iio_hw_consumer_alloc()
+ devm_fwnode_iio_channel_get_by_name()
INPUT
devm_input_allocate_device()
@@ -339,7 +343,10 @@ IRQ
LED
devm_led_classdev_register()
+ devm_led_classdev_register_ext()
devm_led_classdev_unregister()
+ devm_led_trigger_register()
+ devm_of_led_get()
MDIO
devm_mdiobus_alloc()
@@ -403,12 +410,14 @@ POWER
devm_reboot_mode_unregister()
PWM
+ devm_pwmchip_add()
devm_pwm_get()
devm_fwnode_pwm_get()
REGULATOR
devm_regulator_bulk_register_supply_alias()
devm_regulator_bulk_get()
+ devm_regulator_bulk_get_const()
devm_regulator_bulk_get_enable()
devm_regulator_bulk_put()
devm_regulator_get()
diff --git a/Documentation/driver-api/eisa.rst b/Documentation/driver-api/eisa.rst
index c07565ba57da..3eac11b7eb01 100644
--- a/Documentation/driver-api/eisa.rst
+++ b/Documentation/driver-api/eisa.rst
@@ -189,7 +189,7 @@ eisa_bus.enable_dev
initialize the device in such conditions.
eisa_bus.disable_dev
- A comma-separated list of slots to be enabled, even if the firmware
+ A comma-separated list of slots to be disabled, even if the firmware
set the card as enabled. The driver won't be called to handle this
device.
diff --git a/Documentation/driver-api/pin-control.rst b/Documentation/driver-api/pin-control.rst
index 71eefe5a023f..0022e930e93e 100644
--- a/Documentation/driver-api/pin-control.rst
+++ b/Documentation/driver-api/pin-control.rst
@@ -1238,7 +1238,7 @@ default state like this::
return PTR_ERR(foo->s);
}
- ret = pinctrl_select_state(foo->s);
+ ret = pinctrl_select_state(foo->p, foo->s);
if (ret < 0) {
/* FIXME: clean up "foo" here */
return ret;
@@ -1399,11 +1399,11 @@ on the pins defined by group B::
if (IS_ERR(p))
...
- s1 = pinctrl_lookup_state(foo->p, "pos-A");
+ s1 = pinctrl_lookup_state(p, "pos-A");
if (IS_ERR(s1))
...
- s2 = pinctrl_lookup_state(foo->p, "pos-B");
+ s2 = pinctrl_lookup_state(p, "pos-B");
if (IS_ERR(s2))
...
}
@@ -1411,14 +1411,14 @@ on the pins defined by group B::
foo_switch()
{
/* Enable on position A */
- ret = pinctrl_select_state(s1);
+ ret = pinctrl_select_state(p, s1);
if (ret < 0)
...
...
/* Enable on position B */
- ret = pinctrl_select_state(s2);
+ ret = pinctrl_select_state(p, s2);
if (ret < 0)
...
diff --git a/Documentation/driver-api/spi.rst b/Documentation/driver-api/spi.rst
index f64cb666498a..f28887045049 100644
--- a/Documentation/driver-api/spi.rst
+++ b/Documentation/driver-api/spi.rst
@@ -25,8 +25,8 @@ hardware, which may be as simple as a set of GPIO pins or as complex as
a pair of FIFOs connected to dual DMA engines on the other side of the
SPI shift register (maximizing throughput). Such drivers bridge between
whatever bus they sit on (often the platform bus) and SPI, and expose
-the SPI side of their device as a :c:type:`struct spi_master
-<spi_master>`. SPI devices are children of that master,
+the SPI side of their device as a :c:type:`struct spi_controller
+<spi_controller>`. SPI devices are children of that master,
represented as a :c:type:`struct spi_device <spi_device>` and
manufactured from :c:type:`struct spi_board_info
<spi_board_info>` descriptors which are usually provided by
diff --git a/Documentation/fault-injection/fault-injection.rst b/Documentation/fault-injection/fault-injection.rst
index 17779a2772e5..5f6454b9dbd4 100644
--- a/Documentation/fault-injection/fault-injection.rst
+++ b/Documentation/fault-injection/fault-injection.rst
@@ -83,9 +83,7 @@ configuration of fault-injection capabilities.
- /sys/kernel/debug/fail*/times:
specifies how many times failures may happen at most. A value of -1
- means "no limit". Note, though, that this file only accepts unsigned
- values. So, if you want to specify -1, you better use 'printf' instead
- of 'echo', e.g.: $ printf %#x -1 > times
+ means "no limit".
- /sys/kernel/debug/fail*/space:
@@ -284,7 +282,7 @@ Application Examples
echo Y > /sys/kernel/debug/$FAILTYPE/task-filter
echo 10 > /sys/kernel/debug/$FAILTYPE/probability
echo 100 > /sys/kernel/debug/$FAILTYPE/interval
- printf %#x -1 > /sys/kernel/debug/$FAILTYPE/times
+ echo -1 > /sys/kernel/debug/$FAILTYPE/times
echo 0 > /sys/kernel/debug/$FAILTYPE/space
echo 2 > /sys/kernel/debug/$FAILTYPE/verbose
echo Y > /sys/kernel/debug/$FAILTYPE/ignore-gfp-wait
@@ -338,7 +336,7 @@ Application Examples
echo N > /sys/kernel/debug/$FAILTYPE/task-filter
echo 10 > /sys/kernel/debug/$FAILTYPE/probability
echo 100 > /sys/kernel/debug/$FAILTYPE/interval
- printf %#x -1 > /sys/kernel/debug/$FAILTYPE/times
+ echo -1 > /sys/kernel/debug/$FAILTYPE/times
echo 0 > /sys/kernel/debug/$FAILTYPE/space
echo 2 > /sys/kernel/debug/$FAILTYPE/verbose
echo Y > /sys/kernel/debug/$FAILTYPE/ignore-gfp-wait
@@ -369,7 +367,7 @@ Application Examples
echo N > /sys/kernel/debug/$FAILTYPE/task-filter
echo 100 > /sys/kernel/debug/$FAILTYPE/probability
echo 0 > /sys/kernel/debug/$FAILTYPE/interval
- printf %#x -1 > /sys/kernel/debug/$FAILTYPE/times
+ echo -1 > /sys/kernel/debug/$FAILTYPE/times
echo 0 > /sys/kernel/debug/$FAILTYPE/space
echo 1 > /sys/kernel/debug/$FAILTYPE/verbose
diff --git a/Documentation/fb/modedb.rst b/Documentation/fb/modedb.rst
index 4d2411e32ebb..e53375033146 100644
--- a/Documentation/fb/modedb.rst
+++ b/Documentation/fb/modedb.rst
@@ -26,6 +26,11 @@ Valid mode specifiers (mode_option argument)::
with <xres>, <yres>, <bpp> and <refresh> decimal numbers and <name> a string.
Things between square brackets are optional.
+Valid names are::
+
+ - NSTC: 480i output, with the CCIR System-M TV mode and NTSC color encoding
+ - PAL: 576i output, with the CCIR System-B TV mode and PAL color encoding
+
If 'M' is specified in the mode_option argument (after <yres> and before
<bpp> and <refresh>, if specified) the timings will be calculated using
VESA(TM) Coordinated Video Timings instead of looking up the mode from a table.
diff --git a/Documentation/features/core/cBPF-JIT/arch-support.txt b/Documentation/features/core/cBPF-JIT/arch-support.txt
index a053667a7a8c..0a1f5bb7eeb9 100644
--- a/Documentation/features/core/cBPF-JIT/arch-support.txt
+++ b/Documentation/features/core/cBPF-JIT/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/core/eBPF-JIT/arch-support.txt b/Documentation/features/core/eBPF-JIT/arch-support.txt
index c0bb9c92937f..6c0f3d759e6a 100644
--- a/Documentation/features/core/eBPF-JIT/arch-support.txt
+++ b/Documentation/features/core/eBPF-JIT/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/core/generic-idle-thread/arch-support.txt b/Documentation/features/core/generic-idle-thread/arch-support.txt
index c9bfff292816..0b94099cf6ac 100644
--- a/Documentation/features/core/generic-idle-thread/arch-support.txt
+++ b/Documentation/features/core/generic-idle-thread/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | ok |
| ia64: | ok |
- | loong: | ok |
+ | loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/core/jump-labels/arch-support.txt b/Documentation/features/core/jump-labels/arch-support.txt
index 35e2a44b1448..2328eada3a49 100644
--- a/Documentation/features/core/jump-labels/arch-support.txt
+++ b/Documentation/features/core/jump-labels/arch-support.txt
@@ -10,10 +10,10 @@
| arc: | ok |
| arm: | ok |
| arm64: | ok |
- | csky: | TODO |
+ | csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/core/thread-info-in-task/arch-support.txt b/Documentation/features/core/thread-info-in-task/arch-support.txt
index 9b3e2ce12b44..9c5d39eebef2 100644
--- a/Documentation/features/core/thread-info-in-task/arch-support.txt
+++ b/Documentation/features/core/thread-info-in-task/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
diff --git a/Documentation/features/core/tracehook/arch-support.txt b/Documentation/features/core/tracehook/arch-support.txt
index 9c7ffec5d51d..aed5679da651 100644
--- a/Documentation/features/core/tracehook/arch-support.txt
+++ b/Documentation/features/core/tracehook/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | ok |
| ia64: | ok |
- | loong: | ok |
+ | loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/debug/KASAN/arch-support.txt b/Documentation/features/debug/KASAN/arch-support.txt
index 2fd5fb6f5f23..bf0124fae643 100644
--- a/Documentation/features/debug/KASAN/arch-support.txt
+++ b/Documentation/features/debug/KASAN/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
@@ -25,7 +25,7 @@
| s390: | ok |
| sh: | TODO |
| sparc: | TODO |
- | um: | TODO |
+ | um: | ok |
| x86: | ok |
| xtensa: | ok |
-----------------------
diff --git a/Documentation/features/debug/debug-vm-pgtable/arch-support.txt b/Documentation/features/debug/debug-vm-pgtable/arch-support.txt
index c45711e55c7b..9ec5d13f4939 100644
--- a/Documentation/features/debug/debug-vm-pgtable/arch-support.txt
+++ b/Documentation/features/debug/debug-vm-pgtable/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
diff --git a/Documentation/features/debug/gcov-profile-all/arch-support.txt b/Documentation/features/debug/gcov-profile-all/arch-support.txt
index 0b3ba2415fac..dc4014f7e1f8 100644
--- a/Documentation/features/debug/gcov-profile-all/arch-support.txt
+++ b/Documentation/features/debug/gcov-profile-all/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | ok |
| mips: | ok |
diff --git a/Documentation/features/debug/kcov/arch-support.txt b/Documentation/features/debug/kcov/arch-support.txt
index 0a91f5ce34a9..ffcc9f2b1d74 100644
--- a/Documentation/features/debug/kcov/arch-support.txt
+++ b/Documentation/features/debug/kcov/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/debug/kgdb/arch-support.txt b/Documentation/features/debug/kgdb/arch-support.txt
index 04120d278c22..958498f9f2a4 100644
--- a/Documentation/features/debug/kgdb/arch-support.txt
+++ b/Documentation/features/debug/kgdb/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | ok |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | ok |
| mips: | ok |
diff --git a/Documentation/features/debug/kmemleak/arch-support.txt b/Documentation/features/debug/kmemleak/arch-support.txt
index e487c356ab20..0cfa5f0e4db1 100644
--- a/Documentation/features/debug/kmemleak/arch-support.txt
+++ b/Documentation/features/debug/kmemleak/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | ok |
| mips: | ok |
diff --git a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
index b3697f4c806e..bcc29d3aba9a 100644
--- a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
+++ b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
diff --git a/Documentation/features/debug/kprobes/arch-support.txt b/Documentation/features/debug/kprobes/arch-support.txt
index 452385ac9e06..8a77d62a42c5 100644
--- a/Documentation/features/debug/kprobes/arch-support.txt
+++ b/Documentation/features/debug/kprobes/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | ok |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/debug/kretprobes/arch-support.txt b/Documentation/features/debug/kretprobes/arch-support.txt
index daecf046e72b..cf4723c5ac55 100644
--- a/Documentation/features/debug/kretprobes/arch-support.txt
+++ b/Documentation/features/debug/kretprobes/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | ok |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/debug/optprobes/arch-support.txt b/Documentation/features/debug/optprobes/arch-support.txt
index adb1bd055bfd..83a4639a5c0a 100644
--- a/Documentation/features/debug/optprobes/arch-support.txt
+++ b/Documentation/features/debug/optprobes/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
diff --git a/Documentation/features/debug/stackprotector/arch-support.txt b/Documentation/features/debug/stackprotector/arch-support.txt
index ddcd7161d14c..71cd4ba18f7d 100644
--- a/Documentation/features/debug/stackprotector/arch-support.txt
+++ b/Documentation/features/debug/stackprotector/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/debug/uprobes/arch-support.txt b/Documentation/features/debug/uprobes/arch-support.txt
index 25121200f9f9..d53f2f94fbda 100644
--- a/Documentation/features/debug/uprobes/arch-support.txt
+++ b/Documentation/features/debug/uprobes/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/debug/user-ret-profiler/arch-support.txt b/Documentation/features/debug/user-ret-profiler/arch-support.txt
index f2fcff8e77b7..059110a5fa6e 100644
--- a/Documentation/features/debug/user-ret-profiler/arch-support.txt
+++ b/Documentation/features/debug/user-ret-profiler/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
diff --git a/Documentation/features/io/dma-contiguous/arch-support.txt b/Documentation/features/io/dma-contiguous/arch-support.txt
index 95e485c87e36..bfe0921a3853 100644
--- a/Documentation/features/io/dma-contiguous/arch-support.txt
+++ b/Documentation/features/io/dma-contiguous/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | ok |
+ | loongarch: | ok |
| m68k: | TODO |
| microblaze: | ok |
| mips: | ok |
diff --git a/Documentation/features/locking/cmpxchg-local/arch-support.txt b/Documentation/features/locking/cmpxchg-local/arch-support.txt
index 8b1a8d9e1c79..68329e96dffa 100644
--- a/Documentation/features/locking/cmpxchg-local/arch-support.txt
+++ b/Documentation/features/locking/cmpxchg-local/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
diff --git a/Documentation/features/locking/lockdep/arch-support.txt b/Documentation/features/locking/lockdep/arch-support.txt
index ab69e8f56a37..ddb945278589 100644
--- a/Documentation/features/locking/lockdep/arch-support.txt
+++ b/Documentation/features/locking/lockdep/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | ok |
| ia64: | TODO |
- | loong: | ok |
+ | loongarch: | ok |
| m68k: | TODO |
| microblaze: | ok |
| mips: | ok |
diff --git a/Documentation/features/locking/queued-rwlocks/arch-support.txt b/Documentation/features/locking/queued-rwlocks/arch-support.txt
index 0bfb72a08d82..5deb845477e4 100644
--- a/Documentation/features/locking/queued-rwlocks/arch-support.txt
+++ b/Documentation/features/locking/queued-rwlocks/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | ok |
+ | loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/locking/queued-spinlocks/arch-support.txt b/Documentation/features/locking/queued-spinlocks/arch-support.txt
index d2f2201febc8..2d3961bfef5d 100644
--- a/Documentation/features/locking/queued-spinlocks/arch-support.txt
+++ b/Documentation/features/locking/queued-spinlocks/arch-support.txt
@@ -10,10 +10,10 @@
| arc: | TODO |
| arm: | TODO |
| arm64: | ok |
- | csky: | TODO |
+ | csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/perf/kprobes-event/arch-support.txt b/Documentation/features/perf/kprobes-event/arch-support.txt
index 0d0647b06762..641a7d2ff2a3 100644
--- a/Documentation/features/perf/kprobes-event/arch-support.txt
+++ b/Documentation/features/perf/kprobes-event/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | ok |
| ia64: | TODO |
- | loong: | ok |
+ | loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/perf/perf-regs/arch-support.txt b/Documentation/features/perf/perf-regs/arch-support.txt
index 13c297bbf05c..33866eb242c1 100644
--- a/Documentation/features/perf/perf-regs/arch-support.txt
+++ b/Documentation/features/perf/perf-regs/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/perf/perf-stackdump/arch-support.txt b/Documentation/features/perf/perf-stackdump/arch-support.txt
index 931687eec671..c8e4c7c65012 100644
--- a/Documentation/features/perf/perf-stackdump/arch-support.txt
+++ b/Documentation/features/perf/perf-stackdump/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/sched/membarrier-sync-core/arch-support.txt b/Documentation/features/sched/membarrier-sync-core/arch-support.txt
index 336d728b8a45..1e51614c136e 100644
--- a/Documentation/features/sched/membarrier-sync-core/arch-support.txt
+++ b/Documentation/features/sched/membarrier-sync-core/arch-support.txt
@@ -36,7 +36,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
diff --git a/Documentation/features/sched/numa-balancing/arch-support.txt b/Documentation/features/sched/numa-balancing/arch-support.txt
index 76d012118372..532cc67cdf92 100644
--- a/Documentation/features/sched/numa-balancing/arch-support.txt
+++ b/Documentation/features/sched/numa-balancing/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | .. |
| hexagon: | .. |
| ia64: | TODO |
- | loong: | ok |
+ | loongarch: | ok |
| m68k: | .. |
| microblaze: | .. |
| mips: | TODO |
diff --git a/Documentation/features/scripts/features-refresh.sh b/Documentation/features/scripts/features-refresh.sh
index 9e72d38a0720..c2288124e94a 100755
--- a/Documentation/features/scripts/features-refresh.sh
+++ b/Documentation/features/scripts/features-refresh.sh
@@ -60,7 +60,7 @@ for F_FILE in Documentation/features/*/*/arch-support.txt; do
echo " | arch |status|" >> $T_FILE
echo " -----------------------" >> $T_FILE
for ARCH_DIR in arch/*/; do
- ARCH=$(echo $ARCH_DIR | sed -e 's/arch//g' | sed -e 's/\///g')
+ ARCH=$(echo $ARCH_DIR | sed -e 's/^arch//g' | sed -e 's/\///g')
K_FILES=$(find $ARCH_DIR -name "Kconfig*")
K_GREP=$(grep "$K" $K_FILES)
#
diff --git a/Documentation/features/seccomp/seccomp-filter/arch-support.txt b/Documentation/features/seccomp/seccomp-filter/arch-support.txt
index a86b8b1f3d10..dc71bf7b1a7e 100644
--- a/Documentation/features/seccomp/seccomp-filter/arch-support.txt
+++ b/Documentation/features/seccomp/seccomp-filter/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | ok |
+ | loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/time/arch-tick-broadcast/arch-support.txt b/Documentation/features/time/arch-tick-broadcast/arch-support.txt
index 364169f00ee2..9bffac80019e 100644
--- a/Documentation/features/time/arch-tick-broadcast/arch-support.txt
+++ b/Documentation/features/time/arch-tick-broadcast/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | ok |
+ | loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/time/clockevents/arch-support.txt b/Documentation/features/time/clockevents/arch-support.txt
index 6ea274790e47..625160048f68 100644
--- a/Documentation/features/time/clockevents/arch-support.txt
+++ b/Documentation/features/time/clockevents/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | ok |
| ia64: | TODO |
- | loong: | ok |
+ | loongarch: | ok |
| m68k: | TODO |
| microblaze: | ok |
| mips: | ok |
diff --git a/Documentation/features/time/context-tracking/arch-support.txt b/Documentation/features/time/context-tracking/arch-support.txt
index e59071a49090..72bc5bad0348 100644
--- a/Documentation/features/time/context-tracking/arch-support.txt
+++ b/Documentation/features/time/context-tracking/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | ok |
+ | loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/time/irq-time-acct/arch-support.txt b/Documentation/features/time/irq-time-acct/arch-support.txt
index fd17d8de5ef1..ceb036610d09 100644
--- a/Documentation/features/time/irq-time-acct/arch-support.txt
+++ b/Documentation/features/time/irq-time-acct/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | .. |
- | loong: | ok |
+ | loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/time/virt-cpuacct/arch-support.txt b/Documentation/features/time/virt-cpuacct/arch-support.txt
index 1a859ac05e9e..c063dffd5261 100644
--- a/Documentation/features/time/virt-cpuacct/arch-support.txt
+++ b/Documentation/features/time/virt-cpuacct/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | ok |
| hexagon: | TODO |
| ia64: | ok |
- | loong: | ok |
+ | loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/vm/ELF-ASLR/arch-support.txt b/Documentation/features/vm/ELF-ASLR/arch-support.txt
index b1229953391b..15164f36f224 100644
--- a/Documentation/features/vm/ELF-ASLR/arch-support.txt
+++ b/Documentation/features/vm/ELF-ASLR/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/vm/PG_uncached/arch-support.txt b/Documentation/features/vm/PG_uncached/arch-support.txt
index 02f325fbfcd0..5acd64b97dba 100644
--- a/Documentation/features/vm/PG_uncached/arch-support.txt
+++ b/Documentation/features/vm/PG_uncached/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | ok |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
diff --git a/Documentation/features/vm/THP/arch-support.txt b/Documentation/features/vm/THP/arch-support.txt
index 9bfff977ef55..9dd7d75d0465 100644
--- a/Documentation/features/vm/THP/arch-support.txt
+++ b/Documentation/features/vm/THP/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | .. |
| hexagon: | .. |
| ia64: | TODO |
- | loong: | ok |
+ | loongarch: | ok |
| m68k: | .. |
| microblaze: | .. |
| mips: | ok |
diff --git a/Documentation/features/vm/TLB/arch-support.txt b/Documentation/features/vm/TLB/arch-support.txt
index 039e4e91ada3..7f049c251a79 100644
--- a/Documentation/features/vm/TLB/arch-support.txt
+++ b/Documentation/features/vm/TLB/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | .. |
| microblaze: | .. |
| mips: | TODO |
diff --git a/Documentation/features/vm/huge-vmap/arch-support.txt b/Documentation/features/vm/huge-vmap/arch-support.txt
index 13b4940e0c3a..82b0be425775 100644
--- a/Documentation/features/vm/huge-vmap/arch-support.txt
+++ b/Documentation/features/vm/huge-vmap/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | TODO |
+ | loongarch: | TODO |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | TODO |
diff --git a/Documentation/features/vm/ioremap_prot/arch-support.txt b/Documentation/features/vm/ioremap_prot/arch-support.txt
index 6bd78eb4dc6e..a24149e59d73 100644
--- a/Documentation/features/vm/ioremap_prot/arch-support.txt
+++ b/Documentation/features/vm/ioremap_prot/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | ok |
+ | loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/features/vm/pte_special/arch-support.txt b/Documentation/features/vm/pte_special/arch-support.txt
index fc3687b5e89b..d2b22a06945e 100644
--- a/Documentation/features/vm/pte_special/arch-support.txt
+++ b/Documentation/features/vm/pte_special/arch-support.txt
@@ -13,7 +13,7 @@
| csky: | TODO |
| hexagon: | TODO |
| ia64: | TODO |
- | loong: | ok |
+ | loongarch: | ok |
| m68k: | TODO |
| microblaze: | TODO |
| mips: | ok |
diff --git a/Documentation/filesystems/configfs.rst b/Documentation/filesystems/configfs.rst
index 1d3d6f4a82a9..8c9342ed6d25 100644
--- a/Documentation/filesystems/configfs.rst
+++ b/Documentation/filesystems/configfs.rst
@@ -289,7 +289,6 @@ config_item_type::
const char *name);
struct config_group *(*make_group)(struct config_group *group,
const char *name);
- int (*commit_item)(struct config_item *item);
void (*disconnect_notify)(struct config_group *group,
struct config_item *item);
void (*drop_item)(struct config_group *group,
@@ -486,50 +485,3 @@ up. Here, the heartbeat code calls configfs_depend_item(). If it
succeeds, then heartbeat knows the region is safe to give to ocfs2.
If it fails, it was being torn down anyway, and heartbeat can gracefully
pass up an error.
-
-Committable Items
-=================
-
-Note:
- Committable items are currently unimplemented.
-
-Some config_items cannot have a valid initial state. That is, no
-default values can be specified for the item's attributes such that the
-item can do its work. Userspace must configure one or more attributes,
-after which the subsystem can start whatever entity this item
-represents.
-
-Consider the FakeNBD device from above. Without a target address *and*
-a target device, the subsystem has no idea what block device to import.
-The simple example assumes that the subsystem merely waits until all the
-appropriate attributes are configured, and then connects. This will,
-indeed, work, but now every attribute store must check if the attributes
-are initialized. Every attribute store must fire off the connection if
-that condition is met.
-
-Far better would be an explicit action notifying the subsystem that the
-config_item is ready to go. More importantly, an explicit action allows
-the subsystem to provide feedback as to whether the attributes are
-initialized in a way that makes sense. configfs provides this as
-committable items.
-
-configfs still uses only normal filesystem operations. An item is
-committed via rename(2). The item is moved from a directory where it
-can be modified to a directory where it cannot.
-
-Any group that provides the ct_group_ops->commit_item() method has
-committable items. When this group appears in configfs, mkdir(2) will
-not work directly in the group. Instead, the group will have two
-subdirectories: "live" and "pending". The "live" directory does not
-support mkdir(2) or rmdir(2) either. It only allows rename(2). The
-"pending" directory does allow mkdir(2) and rmdir(2). An item is
-created in the "pending" directory. Its attributes can be modified at
-will. Userspace commits the item by renaming it into the "live"
-directory. At this point, the subsystem receives the ->commit_item()
-callback. If all required attributes are filled to satisfaction, the
-method returns zero and the item is moved to the "live" directory.
-
-As rmdir(2) does not work in the "live" directory, an item must be
-shutdown, or "uncommitted". Again, this is done via rename(2), this
-time from the "live" directory back to the "pending" one. The subsystem
-is notified by the ct_group_ops->uncommit_object() method.
diff --git a/Documentation/filesystems/debugfs.rst b/Documentation/filesystems/debugfs.rst
index 71b1fee56d2a..dc35da8b8792 100644
--- a/Documentation/filesystems/debugfs.rst
+++ b/Documentation/filesystems/debugfs.rst
@@ -155,8 +155,8 @@ any code which does so in the mainline. Note that all files created with
debugfs_create_blob() are read-only.
If you want to dump a block of registers (something that happens quite
-often during development, even if little such code reaches mainline.
-Debugfs offers two functions: one to make a registers-only file, and
+often during development, even if little such code reaches mainline),
+debugfs offers two functions: one to make a registers-only file, and
another to insert a register block in the middle of another sequential
file::
@@ -183,7 +183,7 @@ The "base" argument may be 0, but you may want to build the reg32 array
using __stringify, and a number of register names (macros) are actually
byte offsets over a base for the register block.
-If you want to dump an u32 array in debugfs, you can create file with::
+If you want to dump a u32 array in debugfs, you can create a file with::
struct debugfs_u32_array {
u32 *array;
@@ -197,7 +197,7 @@ If you want to dump an u32 array in debugfs, you can create file with::
The "array" argument wraps a pointer to the array's data and the number
of its elements. Note: Once array is created its size can not be changed.
-There is a helper function to create device related seq_file::
+There is a helper function to create a device-related seq_file::
void debugfs_create_devm_seqfile(struct device *dev,
const char *name,
diff --git a/Documentation/filesystems/erofs.rst b/Documentation/filesystems/erofs.rst
index 05e03d54af1a..067fd1670b1f 100644
--- a/Documentation/filesystems/erofs.rst
+++ b/Documentation/filesystems/erofs.rst
@@ -30,12 +30,18 @@ It is implemented to be a better choice for the following scenarios:
especially for those embedded devices with limited memory and high-density
hosts with numerous containers.
-Here is the main features of EROFS:
+Here are the main features of EROFS:
- Little endian on-disk design;
- - 4KiB block size and 32-bit block addresses, therefore 16TiB address space
- at most for now;
+ - Block-based distribution and file-based distribution over fscache are
+ supported;
+
+ - Support multiple devices to refer to external blobs, which can be used
+ for container images;
+
+ - 4KiB block size and 32-bit block addresses for each device, therefore
+ 16TiB address space at most for now;
- Two inode layouts for different requirements:
@@ -50,28 +56,31 @@ Here is the main features of EROFS:
Metadata reserved 8 bytes 18 bytes
===================== ============ ======================================
- - Metadata and data could be mixed as an option;
-
- - Support extended attributes (xattrs) as an option;
+ - Support extended attributes as an option;
- - Support tailpacking data and xattr inline compared to byte-addressed
- unaligned metadata or smaller block size alternatives;
-
- - Support POSIX.1e ACLs by using xattrs;
+ - Support POSIX.1e ACLs by using extended attributes;
- Support transparent data compression as an option:
LZ4 and MicroLZMA algorithms can be used on a per-file basis; In addition,
inplace decompression is also supported to avoid bounce compressed buffers
and page cache thrashing.
+ - Support chunk-based data deduplication and rolling-hash compressed data
+ deduplication;
+
+ - Support tailpacking inline compared to byte-addressed unaligned metadata
+ or smaller block size alternatives;
+
+ - Support merging tail-end data into a special inode as fragments.
+
+ - Support large folios for uncompressed files.
+
- Support direct I/O on uncompressed files to avoid double caching for loop
devices;
- Support FSDAX on uncompressed images for secure containers and ramdisks in
order to get rid of unnecessary page cache.
- - Support multiple devices for multi blob container images;
-
- Support file-based on-demand loading with the Fscache infrastructure.
The following git tree provides the file system user-space tools under
@@ -259,7 +268,7 @@ By the way, chunk-based files are all uncompressed for now.
Data compression
----------------
-EROFS implements LZ4 fixed-sized output compression which generates fixed-sized
+EROFS implements fixed-sized output compression which generates fixed-sized
compressed data blocks from variable-sized input in contrast to other existing
fixed-sized input solutions. Relatively higher compression ratios can be gotten
by using fixed-sized output compression since nowadays popular data compression
@@ -314,3 +323,6 @@ to understand its delta0 is constantly 1, as illustrated below::
If another HEAD follows a HEAD lcluster, there is no room to record CBLKCNT,
but it's easy to know the size of such pcluster is 1 lcluster as well.
+
+Since Linux v6.1, each pcluster can be used for multiple variable-sized extents,
+therefore it can be used for compressed data deduplication.
diff --git a/Documentation/filesystems/fscrypt.rst b/Documentation/filesystems/fscrypt.rst
index 5ba5817c17c2..ef183387da20 100644
--- a/Documentation/filesystems/fscrypt.rst
+++ b/Documentation/filesystems/fscrypt.rst
@@ -338,6 +338,7 @@ Currently, the following pairs of encryption modes are supported:
- AES-128-CBC for contents and AES-128-CTS-CBC for filenames
- Adiantum for both contents and filenames
- AES-256-XTS for contents and AES-256-HCTR2 for filenames (v2 policies only)
+- SM4-XTS for contents and SM4-CTS-CBC for filenames (v2 policies only)
If unsure, you should use the (AES-256-XTS, AES-256-CTS-CBC) pair.
@@ -369,6 +370,12 @@ CONFIG_CRYPTO_HCTR2 must be enabled. Also, fast implementations of XCTR and
POLYVAL should be enabled, e.g. CRYPTO_POLYVAL_ARM64_CE and
CRYPTO_AES_ARM64_CE_BLK for ARM64.
+SM4 is a Chinese block cipher that is an alternative to AES. It has
+not seen as much security review as AES, and it only has a 128-bit key
+size. It may be useful in cases where its use is mandated.
+Otherwise, it should not be used. For SM4 support to be available, it
+also needs to be enabled in the kernel crypto API.
+
New encryption modes can be added relatively easily, without changes
to individual filesystems. However, authenticated encryption (AE)
modes are not currently supported because of the difficulty of dealing
diff --git a/Documentation/filesystems/locking.rst b/Documentation/filesystems/locking.rst
index 8f737e76935c..36fa2a83d714 100644
--- a/Documentation/filesystems/locking.rst
+++ b/Documentation/filesystems/locking.rst
@@ -70,7 +70,7 @@ prototypes::
const char *(*get_link) (struct dentry *, struct inode *, struct delayed_call *);
void (*truncate) (struct inode *);
int (*permission) (struct inode *, int, unsigned int);
- struct posix_acl * (*get_acl)(struct inode *, int, bool);
+ struct posix_acl * (*get_inode_acl)(struct inode *, int, bool);
int (*setattr) (struct dentry *, struct iattr *);
int (*getattr) (const struct path *, struct kstat *, u32, unsigned int);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
@@ -84,13 +84,14 @@ prototypes::
int (*fileattr_set)(struct user_namespace *mnt_userns,
struct dentry *dentry, struct fileattr *fa);
int (*fileattr_get)(struct dentry *dentry, struct fileattr *fa);
+ struct posix_acl * (*get_acl)(struct user_namespace *, struct dentry *, int);
locking rules:
all may block
-============= =============================================
+============== =============================================
ops i_rwsem(inode)
-============= =============================================
+============== =============================================
lookup: shared
create: exclusive
link: exclusive (both)
@@ -104,6 +105,7 @@ readlink: no
get_link: no
setattr: exclusive
permission: no (may not block if called in rcu-walk mode)
+get_inode_acl: no
get_acl: no
getattr: no
listxattr: no
@@ -113,7 +115,7 @@ atomic_open: shared (exclusive if O_CREAT is set in open flags)
tmpfile: no
fileattr_get: no or exclusive
fileattr_set: exclusive
-============= =============================================
+============== =============================================
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_rwsem
diff --git a/Documentation/filesystems/mount_api.rst b/Documentation/filesystems/mount_api.rst
index eb358a00be27..63204d2094fd 100644
--- a/Documentation/filesystems/mount_api.rst
+++ b/Documentation/filesystems/mount_api.rst
@@ -562,17 +562,6 @@ or looking up of superblocks.
The following helpers all wrap sget_fc():
- * ::
-
- int vfs_get_super(struct fs_context *fc,
- enum vfs_get_super_keying keying,
- int (*fill_super)(struct super_block *sb,
- struct fs_context *fc))
-
- This creates/looks up a deviceless superblock. The keying indicates how
- many superblocks of this type may exist and in what manner they may be
- shared:
-
(1) vfs_get_single_super
Only one such superblock may exist in the system. Any further
@@ -814,6 +803,7 @@ process the parameters it is given.
int fs_lookup_param(struct fs_context *fc,
struct fs_parameter *value,
bool want_bdev,
+ unsigned int flags,
struct path *_path);
This takes a parameter that carries a string or filename type and attempts
diff --git a/Documentation/filesystems/porting.rst b/Documentation/filesystems/porting.rst
index df0dc37e6f58..d2d684ae7798 100644
--- a/Documentation/filesystems/porting.rst
+++ b/Documentation/filesystems/porting.rst
@@ -462,8 +462,8 @@ ERR_PTR(...).
argument; instead of passing IPERM_FLAG_RCU we add MAY_NOT_BLOCK into mask.
generic_permission() has also lost the check_acl argument; ACL checking
-has been taken to VFS and filesystems need to provide a non-NULL ->i_op->get_acl
-to read an ACL from disk.
+has been taken to VFS and filesystems need to provide a non-NULL
+->i_op->get_inode_acl to read an ACL from disk.
---
diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst
index 898c99eae8e4..f4ee84d7b351 100644
--- a/Documentation/filesystems/proc.rst
+++ b/Documentation/filesystems/proc.rst
@@ -47,6 +47,7 @@ fixes/update part 1.1 Stefani Seibold <stefani@seibold.net> June 9 2009
3.10 /proc/<pid>/timerslack_ns - Task timerslack value
3.11 /proc/<pid>/patch_state - Livepatch patch operation state
3.12 /proc/<pid>/arch_status - Task architecture specific information
+ 3.13 /proc/<pid>/fd - List of symlinks to open files
4 Configuring procfs
4.1 Mount options
@@ -245,7 +246,8 @@ It's slow but very precise.
Ngid NUMA group ID (0 if none)
Pid process id
PPid process id of the parent process
- TracerPid PID of process tracing this process (0 if not)
+ TracerPid PID of process tracing this process (0 if not, or
+ the tracer is outside of the current pid namespace)
Uid Real, effective, saved set, and file system UIDs
Gid Real, effective, saved set, and file system GIDs
FDSize number of file descriptor slots currently allocated
@@ -2149,6 +2151,22 @@ AVX512_elapsed_ms
the task is unlikely an AVX512 user, but depends on the workload and the
scheduling scenario, it also could be a false negative mentioned above.
+3.13 /proc/<pid>/fd - List of symlinks to open files
+-------------------------------------------------------
+This directory contains symbolic links which represent open files
+the process is maintaining. Example output::
+
+ lr-x------ 1 root root 64 Sep 20 17:53 0 -> /dev/null
+ l-wx------ 1 root root 64 Sep 20 17:53 1 -> /dev/null
+ lrwx------ 1 root root 64 Sep 20 17:53 10 -> 'socket:[12539]'
+ lrwx------ 1 root root 64 Sep 20 17:53 11 -> 'socket:[12540]'
+ lrwx------ 1 root root 64 Sep 20 17:53 12 -> 'socket:[12542]'
+
+The number of open files for the process is stored in 'size' member
+of stat() output for /proc/<pid>/fd for fast access.
+-------------------------------------------------------
+
+
Chapter 4: Configuring procfs
=============================
diff --git a/Documentation/filesystems/sysfs.rst b/Documentation/filesystems/sysfs.rst
index 8bba676b1365..f8187d466b97 100644
--- a/Documentation/filesystems/sysfs.rst
+++ b/Documentation/filesystems/sysfs.rst
@@ -12,10 +12,10 @@ Mike Murphy <mamurph@cs.clemson.edu>
:Original: 10 January 2003
-What it is:
-~~~~~~~~~~~
+What it is
+~~~~~~~~~~
-sysfs is a ram-based filesystem initially based on ramfs. It provides
+sysfs is a RAM-based filesystem initially based on ramfs. It provides
a means to export kernel data structures, their attributes, and the
linkages between them to userspace.
@@ -43,7 +43,7 @@ userspace. Top-level directories in sysfs represent the common
ancestors of object hierarchies; i.e. the subsystems the objects
belong to.
-Sysfs internally stores a pointer to the kobject that implements a
+sysfs internally stores a pointer to the kobject that implements a
directory in the kernfs_node object associated with the directory. In
the past this kobject pointer has been used by sysfs to do reference
counting directly on the kobject whenever the file is opened or closed.
@@ -55,7 +55,7 @@ Attributes
~~~~~~~~~~
Attributes can be exported for kobjects in the form of regular files in
-the filesystem. Sysfs forwards file I/O operations to methods defined
+the filesystem. sysfs forwards file I/O operations to methods defined
for the attributes, providing a means to read and write kernel
attributes.
@@ -72,8 +72,8 @@ you publicly humiliated and your code rewritten without notice.
An attribute definition is simply::
struct attribute {
- char * name;
- struct module *owner;
+ char *name;
+ struct module *owner;
umode_t mode;
};
@@ -138,7 +138,7 @@ __ATTR_WO(name):
assumes a name_store only and is restricted to mode
0200 that is root write access only.
__ATTR_RO_MODE(name, mode):
- fore more restrictive RO access currently
+ for more restrictive RO access; currently
only use case is the EFI System Resource Table
(see drivers/firmware/efi/esrt.c)
__ATTR_RW(name):
@@ -207,7 +207,7 @@ IOW, they should take only an object, an attribute, and a buffer as parameters.
sysfs allocates a buffer of size (PAGE_SIZE) and passes it to the
-method. Sysfs will call the method exactly once for each read or
+method. sysfs will call the method exactly once for each read or
write. This forces the following behavior on the method
implementations:
@@ -221,7 +221,7 @@ implementations:
be called again, rearmed, to fill the buffer.
- On write(2), sysfs expects the entire buffer to be passed during the
- first write. Sysfs then passes the entire buffer to the store() method.
+ first write. sysfs then passes the entire buffer to the store() method.
A terminating null is added after the data on stores. This makes
functions like sysfs_streq() safe to use.
@@ -237,7 +237,7 @@ Other notes:
- Writing causes the show() method to be rearmed regardless of current
file position.
-- The buffer will always be PAGE_SIZE bytes in length. On i386, this
+- The buffer will always be PAGE_SIZE bytes in length. On x86, this
is 4096.
- show() methods should return the number of bytes printed into the
@@ -253,7 +253,7 @@ Other notes:
through, be sure to return an error.
- The object passed to the methods will be pinned in memory via sysfs
- referencing counting its embedded object. However, the physical
+ reference counting its embedded object. However, the physical
entity (e.g. device) the object represents may not be present. Be
sure to have a way to check this, if necessary.
@@ -295,8 +295,12 @@ The top level sysfs directory looks like::
dev/
devices/
firmware/
- net/
fs/
+ hypervisor/
+ kernel/
+ module/
+ net/
+ power/
devices/ contains a filesystem representation of the device tree. It maps
directly to the internal kernel device tree, which is a hierarchy of
@@ -317,15 +321,18 @@ span multiple bus types).
fs/ contains a directory for some filesystems. Currently each
filesystem wanting to export attributes must create its own hierarchy
-below fs/ (see ./fuse.txt for an example).
+below fs/ (see ./fuse.rst for an example).
+
+module/ contains parameter values and state information for all
+loaded system modules, for both builtin and loadable modules.
-dev/ contains two directories char/ and block/. Inside these two
+dev/ contains two directories: char/ and block/. Inside these two
directories there are symlinks named <major>:<minor>. These symlinks
point to the sysfs directory for the given device. /sys/dev provides a
quick way to lookup the sysfs interface for a device from the result of
a stat(2) operation.
-More information can driver-model specific features can be found in
+More information on driver-model specific features can be found in
Documentation/driver-api/driver-model/.
@@ -335,7 +342,7 @@ TODO: Finish this section.
Current Interfaces
~~~~~~~~~~~~~~~~~~
-The following interface layers currently exist in sysfs:
+The following interface layers currently exist in sysfs.
devices (include/linux/device.h)
diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst
index 2b55f71e2ae1..2c15e7053113 100644
--- a/Documentation/filesystems/vfs.rst
+++ b/Documentation/filesystems/vfs.rst
@@ -435,7 +435,7 @@ As of kernel 2.6.22, the following members are defined:
const char *(*get_link) (struct dentry *, struct inode *,
struct delayed_call *);
int (*permission) (struct user_namespace *, struct inode *, int);
- struct posix_acl * (*get_acl)(struct inode *, int, bool);
+ struct posix_acl * (*get_inode_acl)(struct inode *, int, bool);
int (*setattr) (struct user_namespace *, struct dentry *, struct iattr *);
int (*getattr) (struct user_namespace *, const struct path *, struct kstat *, u32, unsigned int);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
@@ -443,7 +443,8 @@ As of kernel 2.6.22, the following members are defined:
int (*atomic_open)(struct inode *, struct dentry *, struct file *,
unsigned open_flag, umode_t create_mode);
int (*tmpfile) (struct user_namespace *, struct inode *, struct file *, umode_t);
- int (*set_acl)(struct user_namespace *, struct inode *, struct posix_acl *, int);
+ struct posix_acl * (*get_acl)(struct user_namespace *, struct dentry *, int);
+ int (*set_acl)(struct user_namespace *, struct dentry *, struct posix_acl *, int);
int (*fileattr_set)(struct user_namespace *mnt_userns,
struct dentry *dentry, struct fileattr *fa);
int (*fileattr_get)(struct dentry *dentry, struct fileattr *fa);
diff --git a/Documentation/gpu/amdgpu/amdgpu-glossary.rst b/Documentation/gpu/amdgpu/amdgpu-glossary.rst
index 326896e9800d..00a47ebb0b0f 100644
--- a/Documentation/gpu/amdgpu/amdgpu-glossary.rst
+++ b/Documentation/gpu/amdgpu/amdgpu-glossary.rst
@@ -30,12 +30,35 @@ we have a dedicated glossary for Display Core at
EOP
End Of Pipe/Pipeline
+ GART
+ Graphics Address Remapping Table. This is the name we use for the GPUVM
+ page table used by the GPU kernel driver. It remaps system resources
+ (memory or MMIO space) into the GPU's address space so the GPU can access
+ them. The name GART harkens back to the days of AGP when the platform
+ provided an MMU that the GPU could use to get a contiguous view of
+ scattered pages for DMA. The MMU has since moved on to the GPU, but the
+ name stuck.
+
GC
Graphics and Compute
GMC
Graphic Memory Controller
+ GPUVM
+ GPU Virtual Memory. This is the GPU's MMU. The GPU supports multiple
+ virtual address spaces that can be in flight at any given time. These
+ allow the GPU to remap VRAM and system resources into GPU virtual address
+ spaces for use by the GPU kernel driver and applications using the GPU.
+ These provide memory protection for different applications using the GPU.
+
+ GTT
+ Graphics Translation Tables. This is a memory pool managed through TTM
+ which provides access to system resources (memory or MMIO space) for
+ use by the GPU. These addresses can be mapped into the "GART" GPUVM page
+ table for use by the kernel driver or into per process GPUVM page tables
+ for application usage.
+
IH
Interrupt Handler
diff --git a/Documentation/gpu/amdgpu/driver-core.rst b/Documentation/gpu/amdgpu/driver-core.rst
index ebf5932845a9..467e6843aef6 100644
--- a/Documentation/gpu/amdgpu/driver-core.rst
+++ b/Documentation/gpu/amdgpu/driver-core.rst
@@ -148,10 +148,10 @@ PRIME Buffer Sharing
MMU Notifier
============
-.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
+.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c
:doc: MMU Notifier
-.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
+.. kernel-doc:: drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c
:internal:
AMDGPU Virtual Memory
diff --git a/Documentation/gpu/amdgpu/index.rst b/Documentation/gpu/amdgpu/index.rst
index a24e1cfa7407..03c2966cae79 100644
--- a/Documentation/gpu/amdgpu/index.rst
+++ b/Documentation/gpu/amdgpu/index.rst
@@ -3,7 +3,7 @@
==========================
The drm/amdgpu driver supports all AMD Radeon GPUs based on the Graphics Core
-Next (GCN) architecture.
+Next (GCN), Radeon DNA (RDNA), and Compute DNA (CDNA) architectures.
.. toctree::
diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst
index dbc85fd7a971..a4860ffd6e86 100644
--- a/Documentation/gpu/drm-kms-helpers.rst
+++ b/Documentation/gpu/drm-kms-helpers.rst
@@ -116,6 +116,9 @@ fbdev Helper Functions Reference
.. kernel-doc:: drivers/gpu/drm/drm_fb_helper.c
:export:
+.. kernel-doc:: drivers/gpu/drm/drm_fbdev_generic.c
+ :export:
+
format Helper Functions Reference
=================================
diff --git a/Documentation/gpu/drm-usage-stats.rst b/Documentation/gpu/drm-usage-stats.rst
index 92c5117368d7..b46327356e80 100644
--- a/Documentation/gpu/drm-usage-stats.rst
+++ b/Documentation/gpu/drm-usage-stats.rst
@@ -126,7 +126,6 @@ percentage utilization of the engine, whereas drm-engine-<str> only reflects
time active without considering what frequency the engine is operating as a
percentage of it's maximum frequency.
-===============================
Driver specific implementations
===============================
diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst
index 4e59db1cfb00..60ea21734902 100644
--- a/Documentation/gpu/i915.rst
+++ b/Documentation/gpu/i915.rst
@@ -494,7 +494,7 @@ WOPCM
WOPCM Layout
~~~~~~~~~~~~
-.. kernel-doc:: drivers/gpu/drm/i915/intel_wopcm.c
+.. kernel-doc:: drivers/gpu/drm/i915/gt/intel_wopcm.c
:doc: WOPCM Layout
GuC
diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst
index 393d218e4a0c..b2c6aaf1edf2 100644
--- a/Documentation/gpu/todo.rst
+++ b/Documentation/gpu/todo.rst
@@ -651,17 +651,6 @@ See drivers/gpu/drm/amd/display/TODO for tasks.
Contact: Harry Wentland, Alex Deucher
-vmwgfx: Replace hashtable with Linux' implementation
-----------------------------------------------------
-
-The vmwgfx driver uses its own hashtable implementation. Replace the
-code with Linux' implementation and update the callers. It's mostly a
-refactoring task, but the interfaces are different.
-
-Contact: Zack Rusin, Thomas Zimmermann <tzimmermann@suse.de>
-
-Level: Intermediate
-
Bootsplash
==========
diff --git a/Documentation/hwmon/aquacomputer_d5next.rst b/Documentation/hwmon/aquacomputer_d5next.rst
index e238533b5fe0..637bdbc8fcad 100644
--- a/Documentation/hwmon/aquacomputer_d5next.rst
+++ b/Documentation/hwmon/aquacomputer_d5next.rst
@@ -39,7 +39,7 @@ current.
The Quadro exposes four physical and sixteen virtual temperature sensors, a flow
sensor and four PWM controllable fans, along with their speed (in RPM), power,
-voltage and current.
+voltage and current. Flow sensor pulses are also available.
The Farbwerk and Farbwerk 360 expose four temperature sensors. Additionally,
sixteen virtual temperature sensors of the Farbwerk 360 are exposed.
@@ -62,7 +62,9 @@ Sysfs entries
================ ==============================================================
temp[1-20]_input Physical/virtual temperature sensors (in millidegrees Celsius)
+temp[1-4]_offset Temperature sensor correction offset (in millidegrees Celsius)
fan[1-8]_input Pump/fan speed (in RPM) / Flow speed (in dL/h)
+fan5_pulses Quadro flow sensor pulses
power[1-8]_input Pump/fan power (in micro Watts)
in[0-7]_input Pump/fan voltage (in milli Volts)
curr[1-8]_input Pump/fan current (in milli Amperes)
diff --git a/Documentation/hwmon/index.rst b/Documentation/hwmon/index.rst
index c1d11cf13eef..fe2cc6b73634 100644
--- a/Documentation/hwmon/index.rst
+++ b/Documentation/hwmon/index.rst
@@ -160,6 +160,7 @@ Hardware Monitoring Kernel Drivers
nzxt-kraken2
nzxt-smart2
occ
+ oxp-sensors
pc87360
pc87427
pcf8591
@@ -187,6 +188,7 @@ Hardware Monitoring Kernel Drivers
sis5595
sl28cpld
smm665
+ smpro-hwmon
smsc47b397
smsc47m192
smsc47m1
diff --git a/Documentation/hwmon/oxp-sensors.rst b/Documentation/hwmon/oxp-sensors.rst
new file mode 100644
index 000000000000..39c588ec5c50
--- /dev/null
+++ b/Documentation/hwmon/oxp-sensors.rst
@@ -0,0 +1,44 @@
+.. SPDX-License-Identifier: GPL-2.0-or-later
+
+Kernel driver oxp-sensors
+=========================
+
+Author:
+ - Joaquín Ignacio Aramendía <samsagax@gmail.com>
+
+Description:
+------------
+
+One X Player devices from One Netbook provide fan readings and fan control
+through its Embedded Controller.
+
+Currently only supports AMD boards from the One X Player and AOK ZOE lineup.
+Intel boards could be supported if we could figure out the EC registers and
+values to write to since the EC layout and model is different.
+
+Supported devices
+-----------------
+
+Currently the driver supports the following handhelds:
+
+ - AOK ZOE A1
+ - OneXPlayer AMD
+ - OneXPlayer mini AMD
+ - OneXPlayer mini AMD PRO
+
+Sysfs entries
+-------------
+
+The following attributes are supported:
+
+fan1_input
+ Read Only. Reads current fan RMP.
+
+pwm1_enable
+ Read Write. Enable manual fan control. Write "1" to set to manual, write "0"
+ to let the EC control de fan speed. Read this attribute to see current status.
+
+pwm1
+ Read Write. Read this attribute to see current duty cycle in the range [0-255].
+ When pwm1_enable is set to "1" (manual) write any value in the range [0-255]
+ to set fan speed.
diff --git a/Documentation/hwmon/smpro-hwmon.rst b/Documentation/hwmon/smpro-hwmon.rst
new file mode 100644
index 000000000000..fb7b3665735b
--- /dev/null
+++ b/Documentation/hwmon/smpro-hwmon.rst
@@ -0,0 +1,102 @@
+.. SPDX-License-Identifier: GPL-2.0-only
+
+Kernel driver Ampere(R)'s Altra(R) SMpro hwmon
+==============================================
+
+Supported chips:
+
+ * Ampere(R) Altra(R)
+
+ Prefix: ``smpro``
+
+ Reference: `Altra SoC BMC Interface Specification`
+
+Author: Thu Nguyen <thu@os.amperecomputing.com>
+
+Description
+-----------
+The smpro-hwmon driver supports hardware monitoring for Ampere(R) Altra(R)
+SoCs based on the SMpro co-processor (SMpro). The following sensor metrics
+are supported by the driver:
+
+ * temperature
+ * voltage
+ * current
+ * power
+
+The interface provides the registers to query the various sensors and
+their values which are then exported to userspace by this driver.
+
+Usage Notes
+-----------
+
+The driver creates at least two sysfs files for each sensor.
+
+* ``<sensor_type><idx>_label`` reports the sensor label.
+* ``<sensor_type><idx>_input`` returns the sensor value.
+
+The sysfs files are allocated in the SMpro rootfs folder, with one root
+directory for each instance.
+
+When the SoC is turned off, the driver will fail to read registers and
+return ``-ENXIO``.
+
+Sysfs entries
+-------------
+
+The following sysfs files are supported:
+
+* Ampere(R) Altra(R):
+
+ ============ ============= ====== ===============================================
+ Name Unit Perm Description
+ ============ ============= ====== ===============================================
+ temp1_input millicelsius RO SoC temperature
+ temp2_input millicelsius RO Max temperature reported among SoC VRDs
+ temp2_crit millicelsius RO SoC VRD HOT Threshold temperature
+ temp3_input millicelsius RO Max temperature reported among DIMM VRDs
+ temp4_input millicelsius RO Max temperature reported among Core VRDs
+ temp5_input millicelsius RO Temperature of DIMM0 on CH0
+ temp5_crit millicelsius RO MEM HOT Threshold for all DIMMs
+ temp6_input millicelsius RO Temperature of DIMM0 on CH1
+ temp6_crit millicelsius RO MEM HOT Threshold for all DIMMs
+ temp7_input millicelsius RO Temperature of DIMM0 on CH2
+ temp7_crit millicelsius RO MEM HOT Threshold for all DIMMs
+ temp8_input millicelsius RO Temperature of DIMM0 on CH3
+ temp8_crit millicelsius RO MEM HOT Threshold for all DIMMs
+ temp9_input millicelsius RO Temperature of DIMM0 on CH4
+ temp9_crit millicelsius RO MEM HOT Threshold for all DIMMs
+ temp10_input millicelsius RO Temperature of DIMM0 on CH5
+ temp10_crit millicelsius RO MEM HOT Threshold for all DIMMs
+ temp11_input millicelsius RO Temperature of DIMM0 on CH6
+ temp11_crit millicelsius RO MEM HOT Threshold for all DIMMs
+ temp12_input millicelsius RO Temperature of DIMM0 on CH7
+ temp12_crit millicelsius RO MEM HOT Threshold for all DIMMs
+ temp13_input millicelsius RO Max temperature reported among RCA VRDs
+ in0_input millivolts RO Core voltage
+ in1_input millivolts RO SoC voltage
+ in2_input millivolts RO DIMM VRD1 voltage
+ in3_input millivolts RO DIMM VRD2 voltage
+ in4_input millivolts RO RCA VRD voltage
+ cur1_input milliamperes RO Core VRD current
+ cur2_input milliamperes RO SoC VRD current
+ cur3_input milliamperes RO DIMM VRD1 current
+ cur4_input milliamperes RO DIMM VRD2 current
+ cur5_input milliamperes RO RCA VRD current
+ power1_input microwatts RO Core VRD power
+ power2_input microwatts RO SoC VRD power
+ power3_input microwatts RO DIMM VRD1 power
+ power4_input microwatts RO DIMM VRD2 power
+ power5_input microwatts RO RCA VRD power
+ ============ ============= ====== ===============================================
+
+ Example::
+
+ # cat in0_input
+ 830
+ # cat temp1_input
+ 37000
+ # cat curr1_input
+ 9000
+ # cat power5_input
+ 19500000
diff --git a/Documentation/ia64/aliasing.rst b/Documentation/ia64/aliasing.rst
index a08b36aba015..36a1e1d4842b 100644
--- a/Documentation/ia64/aliasing.rst
+++ b/Documentation/ia64/aliasing.rst
@@ -61,7 +61,7 @@ Memory Map
The efi_memmap table is preserved unmodified because the original
boot-time information is required for kexec.
-Kernel Identify Mappings
+Kernel Identity Mappings
========================
Linux/ia64 identity mappings are done with large pages, currently
diff --git a/Documentation/kernel-hacking/locking.rst b/Documentation/kernel-hacking/locking.rst
index 6805ae6e86e6..c756786e17ae 100644
--- a/Documentation/kernel-hacking/locking.rst
+++ b/Documentation/kernel-hacking/locking.rst
@@ -967,7 +967,7 @@ you might do the following::
while (list) {
struct foo *next = list->next;
- del_timer(&list->timer);
+ timer_delete(&list->timer);
kfree(list);
list = next;
}
@@ -981,7 +981,7 @@ the lock after we spin_unlock_bh(), and then try to free
the element (which has already been freed!).
This can be avoided by checking the result of
-del_timer(): if it returns 1, the timer has been deleted.
+timer_delete(): if it returns 1, the timer has been deleted.
If 0, it means (in this case) that it is currently running, so we can
do::
@@ -990,7 +990,7 @@ do::
while (list) {
struct foo *next = list->next;
- if (!del_timer(&list->timer)) {
+ if (!timer_delete(&list->timer)) {
/* Give timer a chance to delete this */
spin_unlock_bh(&list_lock);
goto retry;
@@ -1005,9 +1005,12 @@ do::
Another common problem is deleting timers which restart themselves (by
calling add_timer() at the end of their timer function).
Because this is a fairly common case which is prone to races, you should
-use del_timer_sync() (``include/linux/timer.h``) to
-handle this case. It returns the number of times the timer had to be
-deleted before we finally stopped it from adding itself back in.
+use timer_delete_sync() (``include/linux/timer.h``) to handle this case.
+
+Before freeing a timer, timer_shutdown() or timer_shutdown_sync() should be
+called which will keep it from being rearmed. Any subsequent attempt to
+rearm the timer will be silently ignored by the core code.
+
Locking Speed
=============
@@ -1335,7 +1338,7 @@ lock.
- kfree()
-- add_timer() and del_timer()
+- add_timer() and timer_delete()
Mutex API reference
===================
diff --git a/Documentation/loongarch/introduction.rst b/Documentation/loongarch/introduction.rst
index 6c9160c4e9be..49135d451ced 100644
--- a/Documentation/loongarch/introduction.rst
+++ b/Documentation/loongarch/introduction.rst
@@ -375,15 +375,15 @@ Developer web site of Loongson and LoongArch (Software and Documentation):
Documentation of LoongArch ISA:
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.00-CN.pdf (in Chinese)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-CN.pdf (in Chinese)
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.00-EN.pdf (in English)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-EN.pdf (in English)
Documentation of LoongArch ELF psABI:
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v1.00-CN.pdf (in Chinese)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.00-CN.pdf (in Chinese)
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v1.00-EN.pdf (in English)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.00-EN.pdf (in English)
Linux kernel repository of Loongson and LoongArch:
diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt
index 06f80e3785c5..cc621decd943 100644
--- a/Documentation/memory-barriers.txt
+++ b/Documentation/memory-barriers.txt
@@ -1966,7 +1966,7 @@ There are some more advanced barrier functions:
(*) io_stop_wc();
For memory accesses with write-combining attributes (e.g. those returned
- by ioremap_wc(), the CPU may wait for prior accesses to be merged with
+ by ioremap_wc()), the CPU may wait for prior accesses to be merged with
subsequent ones. io_stop_wc() can be used to prevent the merging of
write-combining memory accesses before this macro with those after it when
such wait has performance implications.
diff --git a/Documentation/mm/slub.rst b/Documentation/mm/slub.rst
index 4e1578186b4f..7f652216dabe 100644
--- a/Documentation/mm/slub.rst
+++ b/Documentation/mm/slub.rst
@@ -116,6 +116,8 @@ options from the ``slub_debug`` parameter translate to the following files::
T trace
A failslab
+failslab file is writable, so writing 1 or 0 will enable or disable
+the option at runtime. Write returns -EINVAL if cache is an alias.
Careful with tracing: It may spew out lots of information and never stop if
used on the wrong slab.
diff --git a/Documentation/process/kernel-docs.rst b/Documentation/process/kernel-docs.rst
index 306ad373a002..1c6e2ab92f4e 100644
--- a/Documentation/process/kernel-docs.rst
+++ b/Documentation/process/kernel-docs.rst
@@ -3,9 +3,6 @@
Index of Further Kernel Documentation
=====================================
-Initial Author: Juan-Mariano de Goyeneche (<jmseyas@dit.upm.es>;
-email address is defunct now.)
-
The need for a document like this one became apparent in the
linux-kernel mailing list as the same questions, asking for pointers
to information, appeared again and again.
@@ -31,7 +28,9 @@ All documents are cataloged with the following fields: the document's
.. note::
The documents on each section of this document are ordered by its
- published date, from the newest to the oldest.
+ published date, from the newest to the oldest. The maintainer(s) should
+ periodically retire resources as they become obsolte or outdated; with
+ the exception of foundational books.
Docs at the Linux Kernel tree
-----------------------------
@@ -61,24 +60,6 @@ On-line docs
a brief description of some of the acronyms and terms you may hear
during discussion of the Linux kernel".
- * Title: **Tracing the Way of Data in a TCP Connection through the Linux Kernel**
-
- :Author: Richard Sailer
- :URL: https://archive.org/details/linux_kernel_data_flow_short_paper
- :Date: 2016
- :Keywords: Linux Kernel Networking, TCP, tracing, ftrace
- :Description: A seminar paper explaining ftrace and how to use it for
- understanding linux kernel internals,
- illustrated at tracing the way of a TCP packet through the kernel.
- :Abstract: *This short paper outlines the usage of ftrace a tracing framework
- as a tool to understand a running Linux system.
- Having obtained a trace-log a kernel hacker can read and understand
- source code more determined and with context.
- In a detailed example this approach is demonstrated in tracing
- and the way of data in a TCP Connection through the kernel.
- Finally this trace-log is used as base for more a exact conceptual
- exploration and description of the Linux TCP/IP implementation.*
-
* Title: **The Linux Kernel Module Programming Guide**
:Author: Peter Jay Salzman, Michael Burian, Ori Pomerantz, Bob Mottram,
@@ -91,379 +72,16 @@ On-line docs
programming. Lots of examples. Currently the new version is being
actively maintained at https://github.com/sysprog21/lkmpg.
- * Title: **On submitting kernel Patches**
-
- :Author: Andi Kleen
- :URL: http://halobates.de/on-submitting-kernel-patches.pdf
- :Date: 2008
- :Keywords: patches, review process, types of submissions, basic rules, case studies
- :Description: This paper gives several experience values on what types of patches
- there are and how likely they get merged.
- :Abstract:
- [...]. This paper examines some common problems for
- submitting larger changes and some strategies to avoid problems.
-
- * Title: **Linux Device Drivers, Third Edition**
-
- :Author: Jonathan Corbet, Alessandro Rubini, Greg Kroah-Hartman
- :URL: https://lwn.net/Kernel/LDD3/
- :Date: 2005
- :Description: A 600-page book covering the (2.6.10) driver
- programming API and kernel hacking in general. Available under the
- Creative Commons Attribution-ShareAlike 2.0 license.
- :note: You can also :ref:`purchase a copy from O'Reilly or elsewhere <ldd3_published>`.
-
- * Title: **Writing an ALSA Driver**
-
- :Author: Takashi Iwai <tiwai@suse.de>
- :URL: https://www.kernel.org/doc/html/latest/sound/kernel-api/writing-an-alsa-driver.html
- :Date: 2005
- :Keywords: ALSA, sound, soundcard, driver, lowlevel, hardware.
- :Description: Advanced Linux Sound Architecture for developers,
- both at kernel and user-level sides. ALSA is the Linux kernel
- sound architecture in the 2.6 kernel version.
-
- * Title: **Linux PCMCIA Programmer's Guide**
-
- :Author: David Hinds.
- :URL: http://pcmcia-cs.sourceforge.net/ftp/doc/PCMCIA-PROG.html
- :Date: 2003
- :Keywords: PCMCIA.
- :Description: "This document describes how to write kernel device
- drivers for the Linux PCMCIA Card Services interface. It also
- describes how to write user-mode utilities for communicating with
- Card Services.
-
- * Title: **How NOT to write kernel drivers**
-
- :Author: Arjan van de Ven.
- :URL: https://landley.net/kdocs/ols/2002/ols2002-pages-545-555.pdf
- :Date: 2002
- :Keywords: driver.
- :Description: Programming bugs and Do-nots in kernel driver development
- :Abstract: *Quit a few tutorials, articles and books give an introduction
- on how to write Linux kernel drivers. Unfortunately the things one
- should NOT do in Linux kernel code is either only a minor appendix
- or, more commonly, completely absent. This paper tries to briefly touch
- the areas in which the most common and serious bugs and do-nots are
- encountered.*
-
- * Title: **Global spinlock list and usage**
-
- :Author: Rick Lindsley.
- :URL: http://lse.sourceforge.net/lockhier/global-spin-lock
- :Date: 2001
- :Keywords: spinlock.
- :Description: This is an attempt to document both the existence and
- usage of the spinlocks in the Linux 2.4.5 kernel. Comprehensive
- list of spinlocks showing when they are used, which functions
- access them, how each lock is acquired, under what conditions it
- is held, whether interrupts can occur or not while it is held...
-
- * Title: **A Linux vm README**
-
- :Author: Kanoj Sarcar.
- :URL: http://kos.enix.org/pub/linux-vmm.html
- :Date: 2001
- :Keywords: virtual memory, mm, pgd, vma, page, page flags, page
- cache, swap cache, kswapd.
- :Description: Telegraphic, short descriptions and definitions
- relating the Linux virtual memory implementation.
-
- * Title: **Video4linux Drivers, Part 1: Video-Capture Device**
-
- :Author: Alan Cox.
- :URL: http://www.linux-mag.com/id/406
- :Date: 2000
- :Keywords: video4linux, driver, video capture, capture devices,
- camera driver.
- :Description: The title says it all.
-
- * Title: **Video4linux Drivers, Part 2: Video-capture Devices**
-
- :Author: Alan Cox.
- :URL: http://www.linux-mag.com/id/429
- :Date: 2000
- :Keywords: video4linux, driver, video capture, capture devices,
- camera driver, control, query capabilities, capability, facility.
- :Description: The title says it all.
-
- * Title: **Linux IP Networking. A Guide to the Implementation and Modification of the Linux Protocol Stack.**
-
- :Author: Glenn Herrin.
- :URL: http://www.cs.unh.edu/cnrg/gherrin
- :Date: 2000
- :Keywords: network, networking, protocol, IP, UDP, TCP, connection,
- socket, receiving, transmitting, forwarding, routing, packets,
- modules, /proc, sk_buff, FIB, tags.
- :Description: Excellent paper devoted to the Linux IP Networking,
- explaining anything from the kernel's to the user space
- configuration tools' code. Very good to get a general overview of
- the kernel networking implementation and understand all steps
- packets follow from the time they are received at the network
- device till they are delivered to applications. The studied kernel
- code is from 2.2.14 version. Provides code for a working packet
- dropper example.
-
- * Title: **How To Make Sure Your Driver Will Work On The Power Macintosh**
-
- :Author: Paul Mackerras.
- :URL: http://www.linux-mag.com/id/261
- :Date: 1999
- :Keywords: Mac, Power Macintosh, porting, drivers, compatibility.
- :Description: The title says it all.
-
- * Title: **An Introduction to SCSI Drivers**
-
- :Author: Alan Cox.
- :URL: http://www.linux-mag.com/id/284
- :Date: 1999
- :Keywords: SCSI, device, driver.
- :Description: The title says it all.
-
- * Title: **Advanced SCSI Drivers And Other Tales**
-
- :Author: Alan Cox.
- :URL: http://www.linux-mag.com/id/307
- :Date: 1999
- :Keywords: SCSI, device, driver, advanced.
- :Description: The title says it all.
-
- * Title: **Writing Linux Mouse Drivers**
-
- :Author: Alan Cox.
- :URL: http://www.linux-mag.com/id/330
- :Date: 1999
- :Keywords: mouse, driver, gpm.
- :Description: The title says it all.
-
- * Title: **More on Mouse Drivers**
-
- :Author: Alan Cox.
- :URL: http://www.linux-mag.com/id/356
- :Date: 1999
- :Keywords: mouse, driver, gpm, races, asynchronous I/O.
- :Description: The title still says it all.
-
- * Title: **Writing Video4linux Radio Driver**
-
- :Author: Alan Cox.
- :URL: http://www.linux-mag.com/id/381
- :Date: 1999
- :Keywords: video4linux, driver, radio, radio devices.
- :Description: The title says it all.
-
- * Title: **I/O Event Handling Under Linux**
-
- :Author: Richard Gooch.
- :URL: https://web.mit.edu/~yandros/doc/io-events.html
- :Date: 1999
- :Keywords: IO, I/O, select(2), poll(2), FDs, aio_read(2), readiness
- event queues.
- :Description: From the Introduction: "I/O Event handling is about
- how your Operating System allows you to manage a large number of
- open files (file descriptors in UNIX/POSIX, or FDs) in your
- application. You want the OS to notify you when FDs become active
- (have data ready to be read or are ready for writing). Ideally you
- want a mechanism that is scalable. This means a large number of
- inactive FDs cost very little in memory and CPU time to manage".
-
- * Title: **(nearly) Complete Linux Loadable Kernel Modules. The definitive guide for hackers, virus coders and system administrators.**
-
- :Author: pragmatic/THC.
- :URL: http://packetstormsecurity.org/docs/hack/LKM_HACKING.html
- :Date: 1999
- :Keywords: syscalls, intercept, hide, abuse, symbol table.
- :Description: Interesting paper on how to abuse the Linux kernel in
- order to intercept and modify syscalls, make
- files/directories/processes invisible, become root, hijack ttys,
- write kernel modules based virus... and solutions for admins to
- avoid all those abuses.
- :Notes: For 2.0.x kernels. Gives guidances to port it to 2.2.x
- kernels.
-
- * Name: **Linux Virtual File System**
-
- :Author: Peter J. Braam.
- :URL: http://www.coda.cs.cmu.edu/doc/talks/linuxvfs/
- :Date: 1998
- :Keywords: slides, VFS, inode, superblock, dentry, dcache.
- :Description: Set of slides, presumably from a presentation on the
- Linux VFS layer. Covers version 2.1.x, with dentries and the
- dcache.
-
- * Title: **The Venus kernel interface**
-
- :Author: Peter J. Braam.
- :URL: http://www.coda.cs.cmu.edu/doc/html/kernel-venus-protocol.html
- :Date: 1998
- :Keywords: coda, filesystem, venus, cache manager.
- :Description: "This document describes the communication between
- Venus and kernel level file system code needed for the operation
- of the Coda filesystem. This version document is meant to describe
- the current interface (version 1.0) as well as improvements we
- envisage".
-
- * Title: **Design and Implementation of the Second Extended Filesystem**
-
- :Author: Rémy Card, Theodore Ts'o, Stephen Tweedie.
- :URL: https://web.mit.edu/tytso/www/linux/ext2intro.html
- :Date: 1998
- :Keywords: ext2, linux fs history, inode, directory, link, devices,
- VFS, physical structure, performance, benchmarks, ext2fs library,
- ext2fs tools, e2fsck.
- :Description: Paper written by three of the top ext2 hackers.
- Covers Linux filesystems history, ext2 motivation, ext2 features,
- design, physical structure on disk, performance, benchmarks,
- e2fsck's passes description... A must read!
- :Notes: This paper was first published in the Proceedings of the
- First Dutch International Symposium on Linux, ISBN 90-367-0385-9.
-
- * Title: **The Linux RAID-1, 4, 5 Code**
-
- :Author: Ingo Molnar, Gadi Oxman and Miguel de Icaza.
- :URL: http://www.linuxjournal.com/article.php?sid=2391
- :Date: 1997
- :Keywords: RAID, MD driver.
- :Description: Linux Journal Kernel Korner article.
- :Abstract: *A description of the implementation of the RAID-1,
- RAID-4 and RAID-5 personalities of the MD device driver in the
- Linux kernel, providing users with high performance and reliable,
- secondary-storage capability using software*.
-
- * Title: **Linux Kernel Hackers' Guide**
-
- :Author: Michael K. Johnson.
- :URL: https://www.tldp.org/LDP/khg/HyperNews/get/khg.html
- :Date: 1997
- :Keywords: device drivers, files, VFS, kernel interface, character vs
- block devices, hardware interrupts, scsi, DMA, access to user memory,
- memory allocation, timers.
- :Description: A guide designed to help you get up to speed on the
- concepts that are not intuitively obvious, and to document the internal
- structures of Linux.
-
- * Title: **Dynamic Kernels: Modularized Device Drivers**
-
- :Author: Alessandro Rubini.
- :URL: http://www.linuxjournal.com/article.php?sid=1219
- :Date: 1996
- :Keywords: device driver, module, loading/unloading modules,
- allocating resources.
- :Description: Linux Journal Kernel Korner article.
- :Abstract: *This is the first of a series of four articles
- co-authored by Alessandro Rubini and Georg Zezchwitz which present
- a practical approach to writing Linux device drivers as kernel
- loadable modules. This installment presents an introduction to the
- topic, preparing the reader to understand next month's
- installment*.
-
- * Title: **Dynamic Kernels: Discovery**
-
- :Author: Alessandro Rubini.
- :URL: http://www.linuxjournal.com/article.php?sid=1220
- :Date: 1996
- :Keywords: character driver, init_module, clean_up module,
- autodetection, mayor number, minor number, file operations,
- open(), close().
- :Description: Linux Journal Kernel Korner article.
- :Abstract: *This article, the second of four, introduces part of
- the actual code to create custom module implementing a character
- device driver. It describes the code for module initialization and
- cleanup, as well as the open() and close() system calls*.
-
- * Title: **The Devil's in the Details**
-
- :Author: Georg v. Zezschwitz and Alessandro Rubini.
- :URL: http://www.linuxjournal.com/article.php?sid=1221
- :Date: 1996
- :Keywords: read(), write(), select(), ioctl(), blocking/non
- blocking mode, interrupt handler.
- :Description: Linux Journal Kernel Korner article.
- :Abstract: *This article, the third of four on writing character
- device drivers, introduces concepts of reading, writing, and using
- ioctl-calls*.
-
- * Title: **Dissecting Interrupts and Browsing DMA**
-
- :Author: Alessandro Rubini and Georg v. Zezschwitz.
- :URL: https://www.linuxjournal.com/article.php?sid=1222
- :Date: 1996
- :Keywords: interrupts, irqs, DMA, bottom halves, task queues.
- :Description: Linux Journal Kernel Korner article.
- :Abstract: *This is the fourth in a series of articles about
- writing character device drivers as loadable kernel modules. This
- month, we further investigate the field of interrupt handling.
- Though it is conceptually simple, practical limitations and
- constraints make this an ''interesting'' part of device driver
- writing, and several different facilities have been provided for
- different situations. We also investigate the complex topic of
- DMA*.
-
- * Title: **Device Drivers Concluded**
-
- :Author: Georg v. Zezschwitz.
- :URL: https://www.linuxjournal.com/article.php?sid=1287
- :Date: 1996
- :Keywords: address spaces, pages, pagination, page management,
- demand loading, swapping, memory protection, memory mapping, mmap,
- virtual memory areas (VMAs), vremap, PCI.
- :Description: Finally, the above turned out into a five articles
- series. This latest one's introduction reads: "This is the last of
- five articles about character device drivers. In this final
- section, Georg deals with memory mapping devices, beginning with
- an overall description of the Linux memory management concepts".
-
- * Title: **Network Buffers And Memory Management**
-
- :Author: Alan Cox.
- :URL: https://www.linuxjournal.com/article.php?sid=1312
- :Date: 1996
- :Keywords: sk_buffs, network devices, protocol/link layer
- variables, network devices flags, transmit, receive,
- configuration, multicast.
- :Description: Linux Journal Kernel Korner.
- :Abstract: *Writing a network device driver for Linux is fundamentally
- simple---most of the complexity (other than talking to the
- hardware) involves managing network packets in memory*.
-
- * Title: **Analysis of the Ext2fs structure**
-
- :Author: Louis-Dominique Dubeau.
- :URL: https://teaching.csse.uwa.edu.au/units/CITS2002/fs-ext2/
- :Date: 1994
- :Keywords: ext2, filesystem, ext2fs.
- :Description: Description of ext2's blocks, directories, inodes,
- bitmaps, invariants...
-
Published books
---------------
- * Title: **Linux Treiber entwickeln**
-
- :Author: Jürgen Quade, Eva-Katharina Kunst
- :Publisher: dpunkt.verlag
- :Date: Oct 2015 (4th edition)
- :Pages: 688
- :ISBN: 978-3-86490-288-8
- :Note: German. The third edition from 2011 is
- much cheaper and still quite up-to-date.
-
- * Title: **Linux Kernel Networking: Implementation and Theory**
-
- :Author: Rami Rosen
- :Publisher: Apress
- :Date: December 22, 2013
- :Pages: 648
- :ISBN: 978-1430261964
-
- * Title: **Embedded Linux Primer: A practical Real-World Approach, 2nd Edition**
+ * Title: **Linux Kernel Programming: A Comprehensive Guide to Kernel Internals, Writing Kernel Modules, and Kernel Synchronization**
- :Author: Christopher Hallinan
- :Publisher: Pearson
- :Date: November, 2010
- :Pages: 656
- :ISBN: 978-0137017836
+ :Author: Kaiwan N. Billimoria
+ :Publisher: Packt Publishing Ltd
+ :Date: 2021
+ :Pages: 754
+ :ISBN: 978-1789953435
* Title: **Linux Kernel Development, 3rd Edition**
@@ -472,14 +90,7 @@ Published books
:Date: July, 2010
:Pages: 440
:ISBN: 978-0672329463
-
- * Title: **Essential Linux Device Drivers**
-
- :Author: Sreekrishnan Venkateswaran
- :Published: Prentice Hall
- :Date: April, 2008
- :Pages: 744
- :ISBN: 978-0132396554
+ :Notes: Foundational book
.. _ldd3_published:
@@ -490,68 +101,10 @@ Published books
:Date: 2005
:Pages: 636
:ISBN: 0-596-00590-3
- :Notes: Further information in
+ :Notes: Foundational book. Further information in
http://www.oreilly.com/catalog/linuxdrive3/
PDF format, URL: https://lwn.net/Kernel/LDD3/
- * Title: **Linux Kernel Internals**
-
- :Author: Michael Beck
- :Publisher: Addison-Wesley
- :Date: 1997
- :ISBN: 0-201-33143-8 (second edition)
-
- * Title: **Programmation Linux 2.0 API systeme et fonctionnement du noyau**
-
- :Author: Remy Card, Eric Dumas, Franck Mevel
- :Publisher: Eyrolles
- :Date: 1997
- :Pages: 520
- :ISBN: 2-212-08932-5
- :Notes: French
-
- * Title: **The Design and Implementation of the 4.4 BSD UNIX Operating System**
-
- :Author: Marshall Kirk McKusick, Keith Bostic, Michael J. Karels,
- John S. Quarterman
- :Publisher: Addison-Wesley
- :Date: 1996
- :ISBN: 0-201-54979-4
-
- * Title: **Unix internals -- the new frontiers**
-
- :Author: Uresh Vahalia
- :Publisher: Prentice Hall
- :Date: 1996
- :Pages: 600
- :ISBN: 0-13-101908-2
-
- * Title: **Programming for the real world - POSIX.4**
-
- :Author: Bill O. Gallmeister
- :Publisher: O'Reilly & Associates, Inc
- :Date: 1995
- :Pages: 552
- :ISBN: I-56592-074-0
- :Notes: Though not being directly about Linux, Linux aims to be
- POSIX. Good reference.
-
- * Title: **UNIX Systems for Modern Architectures: Symmetric Multiprocessing and Caching for Kernel Programmers**
-
- :Author: Curt Schimmel
- :Publisher: Addison Wesley
- :Date: June, 1994
- :Pages: 432
- :ISBN: 0-201-63338-8
-
- * Title: **The Design and Implementation of the 4.3 BSD UNIX Operating System**
-
- :Author: Samuel J. Leffler, Marshall Kirk McKusick, Michael J
- Karels, John S. Quarterman
- :Publisher: Addison-Wesley
- :Date: 1989 (reprinted with corrections on October, 1990)
- :ISBN: 0-201-06196-1
-
* Title: **The Design of the UNIX Operating System**
:Author: Maurice J. Bach
@@ -559,6 +112,7 @@ Published books
:Date: 1986
:Pages: 471
:ISBN: 0-13-201757-1
+ :Notes: Foundational book
Miscellaneous
-------------
@@ -577,7 +131,7 @@ Miscellaneous
:Keywords: latest kernel news.
:Description: The title says it all. There's a fixed kernel section
summarizing developers' work, bug fixes, new features and versions
- produced during the week. Published every Thursday.
+ produced during the week.
* Name: **The home page of Linux-MM**
@@ -614,7 +168,8 @@ Miscellaneous
-------
-Document last updated on Tue 2016-Sep-20
+This document was originally based on:
-This document is based on:
https://www.dit.upm.es/~jmseyas/linux/kernel/hackers-docs.html
+
+and written by Juan-Mariano de Goyeneche
diff --git a/Documentation/riscv/vm-layout.rst b/Documentation/riscv/vm-layout.rst
index 5b36e45fef60..3be44e74ec5d 100644
--- a/Documentation/riscv/vm-layout.rst
+++ b/Documentation/riscv/vm-layout.rst
@@ -97,3 +97,39 @@ RISC-V Linux Kernel SV48
ffffffff00000000 | -4 GB | ffffffff7fffffff | 2 GB | modules, BPF
ffffffff80000000 | -2 GB | ffffffffffffffff | 2 GB | kernel
__________________|____________|__________________|_________|____________________________________________________________
+
+
+RISC-V Linux Kernel SV57
+------------------------
+
+::
+
+ ========================================================================================================================
+ Start addr | Offset | End addr | Size | VM area description
+ ========================================================================================================================
+ | | | |
+ 0000000000000000 | 0 | 00ffffffffffffff | 64 PB | user-space virtual memory, different per mm
+ __________________|____________|__________________|_________|___________________________________________________________
+ | | | |
+ 0100000000000000 | +64 PB | feffffffffffffff | ~16K PB | ... huge, almost 64 bits wide hole of non-canonical
+ | | | | virtual memory addresses up to the -64 PB
+ | | | | starting offset of kernel mappings.
+ __________________|____________|__________________|_________|___________________________________________________________
+ |
+ | Kernel-space virtual memory, shared between all processes:
+ ____________________________________________________________|___________________________________________________________
+ | | | |
+ ff1bfffffee00000 | -57 PB | ff1bfffffeffffff | 2 MB | fixmap
+ ff1bffffff000000 | -57 PB | ff1bffffffffffff | 16 MB | PCI io
+ ff1c000000000000 | -57 PB | ff1fffffffffffff | 1 PB | vmemmap
+ ff20000000000000 | -56 PB | ff5fffffffffffff | 16 PB | vmalloc/ioremap space
+ ff60000000000000 | -40 PB | ffdeffffffffffff | 32 PB | direct mapping of all physical memory
+ ffdf000000000000 | -8 PB | fffffffeffffffff | 8 PB | kasan
+ __________________|____________|__________________|_________|____________________________________________________________
+ |
+ | Identical layout to the 39-bit one from here on:
+ ____________________________________________________________|____________________________________________________________
+ | | | |
+ ffffffff00000000 | -4 GB | ffffffff7fffffff | 2 GB | modules, BPF
+ ffffffff80000000 | -2 GB | ffffffffffffffff | 2 GB | kernel
+ __________________|____________|__________________|_________|____________________________________________________________
diff --git a/Documentation/security/keys/trusted-encrypted.rst b/Documentation/security/keys/trusted-encrypted.rst
index 0bfb4c339748..9bc9db8ec651 100644
--- a/Documentation/security/keys/trusted-encrypted.rst
+++ b/Documentation/security/keys/trusted-encrypted.rst
@@ -350,7 +350,8 @@ Load an encrypted key "evm" from saved blob::
Instantiate an encrypted key "evm" using user-provided decrypted data::
- $ keyctl add encrypted evm "new default user:kmk 32 `cat evm_decrypted_data.blob`" @u
+ $ evmkey=$(dd if=/dev/urandom bs=1 count=32 | xxd -c32 -p)
+ $ keyctl add encrypted evm "new default user:kmk 32 $evmkey" @u
794890253
$ keyctl print 794890253
diff --git a/Documentation/sphinx-static/custom.css b/Documentation/sphinx-static/custom.css
new file mode 100644
index 000000000000..45a624fdcf2c
--- /dev/null
+++ b/Documentation/sphinx-static/custom.css
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * CSS tweaks for the Alabaster theme
+ */
+
+/* Shrink the headers a bit */
+div.body h1 { font-size: 180%; }
+div.body h2 { font-size: 150%; }
+div.body h3 { font-size: 130%; }
+
+/* Tighten up the layout slightly */
+div.body { padding: 0 15px 0 10px; }
+div.sphinxsidebarwrapper { padding: 1em 0.4em; }
+div.sphinxsidebar { font-size: inherit; }
+/* Tweak document margins and don't force width */
+div.document {
+ margin: 20px 10px 0 10px;
+ width: auto;
+}
+
+/*
+ * Parameters for the display of function prototypes and such included
+ * from C source files.
+ */
+dl.function, dl.struct, dl.enum { margin-top: 2em; background-color: #ecf0f3; }
+/* indent lines 2+ of multi-line function prototypes */
+dl.function dt { margin-left: 10em; text-indent: -10em; }
+dt.sig-object { font-size: larger; }
+div.kernelindent { margin-left: 2em; margin-right: 4em; }
diff --git a/Documentation/sphinx/requirements.txt b/Documentation/sphinx/requirements.txt
index 2c573541ab71..335b53df35e2 100644
--- a/Documentation/sphinx/requirements.txt
+++ b/Documentation/sphinx/requirements.txt
@@ -1,4 +1,3 @@
# jinja2>=3.1 is not compatible with Sphinx<4.0
jinja2<3.1
-sphinx_rtd_theme
Sphinx==2.4.4
diff --git a/Documentation/subsystem-apis.rst b/Documentation/subsystem-apis.rst
index af65004a80aa..b51f38527e14 100644
--- a/Documentation/subsystem-apis.rst
+++ b/Documentation/subsystem-apis.rst
@@ -43,6 +43,7 @@ needed).
input/index
hwmon/index
gpu/index
+ accel/index
security/index
sound/index
crypto/index
diff --git a/Documentation/timers/hrtimers.rst b/Documentation/timers/hrtimers.rst
index c1c20a693e8f..7ac448908d1f 100644
--- a/Documentation/timers/hrtimers.rst
+++ b/Documentation/timers/hrtimers.rst
@@ -118,7 +118,7 @@ existing timer wheel code, as it is mature and well suited. Sharing code
was not really a win, due to the different data structures. Also, the
hrtimer functions now have clearer behavior and clearer names - such as
hrtimer_try_to_cancel() and hrtimer_cancel() [which are roughly
-equivalent to del_timer() and del_timer_sync()] - so there's no direct
+equivalent to timer_delete() and timer_delete_sync()] - so there's no direct
1:1 mapping between them on the algorithmic level, and thus no real
potential for code sharing either.
diff --git a/Documentation/tools/index.rst b/Documentation/tools/index.rst
index 0bb1e61bdcc0..80488e290e10 100644
--- a/Documentation/tools/index.rst
+++ b/Documentation/tools/index.rst
@@ -11,6 +11,7 @@ more additions are needed here:
:maxdepth: 1
rtla/index
+ rv/index
.. only:: subproject and html
diff --git a/Documentation/tools/rv/Makefile b/Documentation/tools/rv/Makefile
new file mode 100644
index 000000000000..ec8713c1b35f
--- /dev/null
+++ b/Documentation/tools/rv/Makefile
@@ -0,0 +1,52 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+INSTALL ?= install
+RM ?= rm -f
+RMDIR ?= rmdir --ignore-fail-on-non-empty
+
+PREFIX ?= /usr/share
+MANDIR ?= $(PREFIX)/man
+MAN1DIR = $(MANDIR)/man1
+
+MAN1_RST = $(wildcard rv*.rst)
+
+_DOC_MAN1 = $(patsubst %.rst,%.1,$(MAN1_RST))
+DOC_MAN1 = $(addprefix $(OUTPUT),$(_DOC_MAN1))
+
+RST2MAN_DEP := $(shell command -v rst2man 2>/dev/null)
+RST2MAN_OPTS += --verbose
+
+TEST_RST2MAN = $(shell sh -c "rst2man --version > /dev/null 2>&1 || echo n")
+
+$(OUTPUT)%.1: %.rst
+ifndef RST2MAN_DEP
+ $(info ********************************************)
+ $(info ** NOTICE: rst2man not found)
+ $(info **)
+ $(info ** Consider installing the latest rst2man from your)
+ $(info ** distribution, e.g., 'dnf install python3-docutils' on Fedora,)
+ $(info ** or from source:)
+ $(info **)
+ $(info ** https://docutils.sourceforge.io/docs/dev/repository.html )
+ $(info **)
+ $(info ********************************************)
+ $(error NOTICE: rst2man required to generate man pages)
+endif
+ rst2man $(RST2MAN_OPTS) $< > $@
+
+man1: $(DOC_MAN1)
+man: man1
+
+clean:
+ $(RM) $(DOC_MAN1)
+
+install: man
+ $(INSTALL) -d -m 755 $(DESTDIR)$(MAN1DIR)
+ $(INSTALL) -m 644 $(DOC_MAN1) $(DESTDIR)$(MAN1DIR)
+
+uninstall:
+ $(RM) $(addprefix $(DESTDIR)$(MAN1DIR)/,$(_DOC_MAN1))
+ $(RMDIR) $(DESTDIR)$(MAN1DIR)
+
+.PHONY: man man1 clean install uninstall
+.DEFAULT_GOAL := man
diff --git a/Documentation/tools/rv/common_appendix.rst b/Documentation/tools/rv/common_appendix.rst
new file mode 100644
index 000000000000..f4239192bee8
--- /dev/null
+++ b/Documentation/tools/rv/common_appendix.rst
@@ -0,0 +1,16 @@
+REPORTING BUGS
+==============
+
+Report bugs to <linux-kernel@vger.kernel.org>
+and <linux-trace-devel@vger.kernel.org>
+
+LICENSE
+=======
+
+**rv** is Free Software licensed under the GNU GPLv2
+
+COPYING
+=======
+
+Copyright \(C) 2022 Red Hat, Inc. Free use of this software is granted under
+the terms of the GNU Public License (GPL).
diff --git a/Documentation/tools/rv/common_ikm.rst b/Documentation/tools/rv/common_ikm.rst
new file mode 100644
index 000000000000..e50a5f8a7142
--- /dev/null
+++ b/Documentation/tools/rv/common_ikm.rst
@@ -0,0 +1,21 @@
+**-h**, **--help**
+
+ Print the monitor's options and the available reactors list.
+
+**-r**, **--reactor** *reactor*
+
+ Enables the *reactor*. See **-h** for a list of available reactors.
+
+**-s**, **--self**
+
+ When tracing (**-t**), also print the events that happened during the **rv**
+ command itself. If the **rv** command itself generates too many events,
+ the tool might get busy processing its own events only.
+
+**-t**, **--trace**
+
+ Trace monitor's events and error.
+
+**-v**, **--verbose**
+
+ Print debug messages.
diff --git a/Documentation/tools/rv/index.rst b/Documentation/tools/rv/index.rst
new file mode 100644
index 000000000000..8fd16d91d639
--- /dev/null
+++ b/Documentation/tools/rv/index.rst
@@ -0,0 +1,24 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==============================
+Runtime verification (rv) tool
+==============================
+
+**rv** tool provides the interface for a collection of runtime verification
+(rv) monitors.
+
+.. toctree::
+ :maxdepth: 1
+
+ rv
+ rv-list
+ rv-mon
+ rv-mon-wip
+ rv-mon-wwnr
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
diff --git a/Documentation/tools/rv/rv-list.rst b/Documentation/tools/rv/rv-list.rst
new file mode 100644
index 000000000000..51e4608f9e99
--- /dev/null
+++ b/Documentation/tools/rv/rv-list.rst
@@ -0,0 +1,43 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=======
+rv-list
+=======
+-----------------------
+List available monitors
+-----------------------
+
+:Manual section: 1
+
+SYNOPSIS
+========
+
+**rv list** [*OPTIONS*]
+
+DESCRIPTION
+===========
+
+The **rv list** command prints all available monitors. These monitors
+can be enabled using the **rv mon** command.
+
+OPTIONS
+=======
+
+**-h**, **--help**
+
+ Print help menu.
+
+SEE ALSO
+========
+
+**rv**\(1), **rv-mon**\(1)
+
+Linux kernel *RV* documentation:
+<https://www.kernel.org/doc/html/latest/trace/rv/index.html>
+
+AUTHOR
+======
+
+Written by Daniel Bristot de Oliveira <bristot@kernel.org>
+
+.. include:: common_appendix.rst
diff --git a/Documentation/tools/rv/rv-mon-wip.rst b/Documentation/tools/rv/rv-mon-wip.rst
new file mode 100644
index 000000000000..2d42104d63d1
--- /dev/null
+++ b/Documentation/tools/rv/rv-mon-wip.rst
@@ -0,0 +1,44 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==========
+rv-mon-wip
+==========
+----------------------------
+Wakeup In Preemptive monitor
+----------------------------
+
+:Manual section: 1
+
+SYNOPSIS
+========
+
+**rv mon wip** [*OPTIONS*]
+
+DESCRIPTION
+===========
+
+The wakeup in preemptive (**wip**) monitor is a sample per-cpu monitor that
+checks if the wakeup events always take place with preemption disabled.
+
+See kernel documentation for further information about this monitor:
+<https://docs.kernel.org/trace/rv/monitor_wip.html>
+
+OPTIONS
+=======
+
+.. include:: common_ikm.rst
+
+SEE ALSO
+========
+
+**rv**\(1), **rv-mon**\(1)
+
+Linux kernel *RV* documentation:
+<https://www.kernel.org/doc/html/latest/trace/rv/index.html>
+
+AUTHOR
+======
+
+Written by Daniel Bristot de Oliveira <bristot@kernel.org>
+
+.. include:: common_appendix.rst
diff --git a/Documentation/tools/rv/rv-mon-wwnr.rst b/Documentation/tools/rv/rv-mon-wwnr.rst
new file mode 100644
index 000000000000..a18f3fd54af4
--- /dev/null
+++ b/Documentation/tools/rv/rv-mon-wwnr.rst
@@ -0,0 +1,43 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===========
+rv-mon-wwnr
+===========
+--------------------------------
+Wakeup While Not Running monitor
+--------------------------------
+
+:Manual section: 1
+
+SYNOPSIS
+========
+
+**rv mon wip** [*OPTIONS*]
+
+DESCRIPTION
+===========
+
+The wakeup while not running (**wwnr**) is a per-task sample monitor.
+
+See kernel documentation for further information about this monitor:
+<https://docs.kernel.org/trace/rv/monitor_wwnr.html>
+
+OPTIONS
+=======
+
+.. include:: common_ikm.rst
+
+SEE ALSO
+========
+
+**rv**\(1), **rv-mon**\(1)
+
+Linux kernel *RV* documentation:
+<https://www.kernel.org/doc/html/latest/trace/rv/index.html>
+
+AUTHOR
+======
+
+Written by Daniel Bristot de Oliveira <bristot@kernel.org>
+
+.. include:: common_appendix.rst
diff --git a/Documentation/tools/rv/rv-mon.rst b/Documentation/tools/rv/rv-mon.rst
new file mode 100644
index 000000000000..af0f329a7c9c
--- /dev/null
+++ b/Documentation/tools/rv/rv-mon.rst
@@ -0,0 +1,55 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=======
+rv-list
+=======
+-----------------------
+List available monitors
+-----------------------
+
+:Manual section: 1
+
+SYNOPSIS
+========
+
+**rv mon** [*-h*] **monitor_name** [*-h*] [*MONITOR OPTIONS*]
+
+DESCRIPTION
+===========
+
+The **rv mon** command runs the monitor named *monitor_name*. Each monitor
+has its own set of options. The **rv list** command shows all available
+monitors.
+
+OPTIONS
+=======
+
+**-h**, **--help**
+
+ Print help menu.
+
+AVAILABLE MONITORS
+==================
+
+The **rv** tool provides the interface for a set of monitors. Use the
+**rv list** command to list all available monitors.
+
+Each monitor has its own set of options. See man **rv-mon**-*monitor_name*
+for details about each specific monitor. Also, running **rv mon**
+**monitor_name** **-h** display the help menu with the available
+options.
+
+SEE ALSO
+========
+
+**rv**\(1), **rv-mon**\(1)
+
+Linux kernel *RV* documentation:
+<https://www.kernel.org/doc/html/latest/trace/rv/index.html>
+
+AUTHOR
+======
+
+Written by Daniel Bristot de Oliveira <bristot@kernel.org>
+
+.. include:: common_appendix.rst
diff --git a/Documentation/tools/rv/rv.rst b/Documentation/tools/rv/rv.rst
new file mode 100644
index 000000000000..cee93dc21a76
--- /dev/null
+++ b/Documentation/tools/rv/rv.rst
@@ -0,0 +1,63 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==
+rv
+==
+--------------------
+Runtime Verification
+--------------------
+
+:Manual section: 1
+
+SYNOPSIS
+========
+
+**rv** *COMMAND* [*OPTIONS*]
+
+DESCRIPTION
+===========
+
+Runtime Verification (**RV**) is a lightweight (yet rigorous) method
+for formal verification with a practical approach for complex systems.
+Instead of relying on a fine-grained model of a system (e.g., a
+re-implementation a instruction level), RV works by analyzing the trace
+of the system's actual execution, comparing it against a formal
+specification of the system behavior.
+
+The **rv** tool provides the interface for a collection of runtime
+verification (rv) monitors.
+
+COMMANDS
+========
+
+**list**
+
+ List all available monitors.
+
+**mon**
+
+ Run monitor.
+
+OPTIONS
+=======
+
+**-h**, **--help**
+
+ Display the help text.
+
+For other options, see the man page for the corresponding command.
+
+SEE ALSO
+========
+
+**rv-list**\(1), **rv-mon**\(1)
+
+Linux kernel *RV* documentation:
+<https://www.kernel.org/doc/html/latest/trace/rv/index.html>
+
+AUTHOR
+======
+
+Daniel Bristot de Oliveira <bristot@kernel.org>
+
+.. include:: common_appendix.rst
diff --git a/Documentation/trace/ftrace.rst b/Documentation/trace/ftrace.rst
index 60bceb018d6a..21f01d32c959 100644
--- a/Documentation/trace/ftrace.rst
+++ b/Documentation/trace/ftrace.rst
@@ -2940,7 +2940,7 @@ Produces::
bash-1994 [000] .... 4342.324898: ima_get_action <-process_measurement
bash-1994 [000] .... 4342.324898: ima_match_policy <-ima_get_action
bash-1994 [000] .... 4342.324899: do_truncate <-do_last
- bash-1994 [000] .... 4342.324899: should_remove_suid <-do_truncate
+ bash-1994 [000] .... 4342.324899: setattr_should_drop_suidgid <-do_truncate
bash-1994 [000] .... 4342.324899: notify_change <-do_truncate
bash-1994 [000] .... 4342.324900: current_fs_time <-notify_change
bash-1994 [000] .... 4342.324900: current_kernel_time <-current_fs_time
diff --git a/Documentation/translations/index.rst b/Documentation/translations/index.rst
index 1175a47d07f0..b826c34791c0 100644
--- a/Documentation/translations/index.rst
+++ b/Documentation/translations/index.rst
@@ -12,6 +12,7 @@ Translations
it_IT/index
ko_KR/index
ja_JP/index
+ sp_SP/index
.. _translations_disclaimer:
diff --git a/Documentation/translations/it_IT/kernel-hacking/locking.rst b/Documentation/translations/it_IT/kernel-hacking/locking.rst
index 51af37f2d621..b8ecf41273c5 100644
--- a/Documentation/translations/it_IT/kernel-hacking/locking.rst
+++ b/Documentation/translations/it_IT/kernel-hacking/locking.rst
@@ -990,7 +990,7 @@ potreste fare come segue::
while (list) {
struct foo *next = list->next;
- del_timer(&list->timer);
+ timer_delete(&list->timer);
kfree(list);
list = next;
}
@@ -1003,7 +1003,7 @@ e prenderà il *lock* solo dopo spin_unlock_bh(), e cercherà
di eliminare il suo oggetto (che però è già stato eliminato).
Questo può essere evitato controllando il valore di ritorno di
-del_timer(): se ritorna 1, il temporizzatore è stato già
+timer_delete(): se ritorna 1, il temporizzatore è stato già
rimosso. Se 0, significa (in questo caso) che il temporizzatore è in
esecuzione, quindi possiamo fare come segue::
@@ -1012,7 +1012,7 @@ esecuzione, quindi possiamo fare come segue::
while (list) {
struct foo *next = list->next;
- if (!del_timer(&list->timer)) {
+ if (!timer_delete(&list->timer)) {
/* Give timer a chance to delete this */
spin_unlock_bh(&list_lock);
goto retry;
@@ -1026,10 +1026,8 @@ esecuzione, quindi possiamo fare come segue::
Un altro problema è l'eliminazione dei temporizzatori che si riavviano
da soli (chiamando add_timer() alla fine della loro esecuzione).
Dato che questo è un problema abbastanza comune con una propensione
-alle corse critiche, dovreste usare del_timer_sync()
-(``include/linux/timer.h``) per gestire questo caso. Questa ritorna il
-numero di volte che il temporizzatore è stato interrotto prima che
-fosse in grado di fermarlo senza che si riavviasse.
+alle corse critiche, dovreste usare timer_delete_sync()
+(``include/linux/timer.h``) per gestire questo caso.
Velocità della sincronizzazione
===============================
@@ -1374,7 +1372,7 @@ contesto, o trattenendo un qualsiasi *lock*.
- kfree()
-- add_timer() e del_timer()
+- add_timer() e timer_delete()
Riferimento per l'API dei Mutex
===============================
diff --git a/Documentation/translations/ja_JP/howto.rst b/Documentation/translations/ja_JP/howto.rst
index b8eeb45a02d4..9b0b3436dfcf 100644
--- a/Documentation/translations/ja_JP/howto.rst
+++ b/Documentation/translations/ja_JP/howto.rst
@@ -86,9 +86,14 @@ info ページ( info gcc )を見ã¦ãã ã•ã„。
--------
Linux カーãƒãƒ«ã®ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã¯ GPL ライセンスã®ä¸‹ã§ãƒªãƒªãƒ¼ã‚¹ã•れã¦ã„ã¾
-ã™ã€‚ライセンスã®è©³ç´°ã«ã¤ã„ã¦ã¯ã€ã‚½ãƒ¼ã‚¹ãƒ„リーã®ãƒ¡ã‚¤ãƒ³ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«å­˜åœ¨
-ã™ã‚‹ã€COPYING ã®ãƒ•ァイルを見ã¦ãã ã•ã„。もã—ライセンスã«ã¤ã„ã¦ã•らã«è³ª
-å•ãŒã‚れã°ã€Linux Kernel メーリングリストã«è³ªå•ã™ã‚‹ã®ã§ã¯ãªãã€ã©ã†ãž
+ã™ã€‚ソースツリーã®ãƒ¡ã‚¤ãƒ³ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ã‚ã‚‹ COPYING ã®ãƒ•ァイルを見ã¦ã
+ã ã•ã„。Linux カーãƒãƒ«ã®ãƒ©ã‚¤ã‚»ãƒ³ã‚¹ãƒ«ãƒ¼ãƒ«ã¨ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰å†…ã®
+`SPDX <https://spdx.org/>`_ 識別å­ã®ä½¿ã„æ–¹ã¯
+:ref:`Documentation/process/license-rules.rst <kernel_licensing>`
+ã«èª¬æ˜Žã•れã¦ã„ã¾ã™ã€‚
+
+ã‚‚ã—ライセンスã«ã¤ã„ã¦ã•らã«è³ªå•ãŒã‚れã°ã€
+Linux Kernel メーリングリストã«è³ªå•ã™ã‚‹ã®ã§ã¯ãªãã€ã©ã†ãž
法律家ã«ç›¸è«‡ã—ã¦ãã ã•ã„。メーリングリストã®äººé”ã¯æ³•律家ã§ã¯ãªãã€æ³•çš„
å•題ã«ã¤ã„ã¦ã¯å½¼ã‚‰ã®å£°æ˜Žã¯ã‚ã¦ã«ã™ã‚‹ã¹ãã§ã¯ã‚りã¾ã›ã‚“。
@@ -111,7 +116,7 @@ linux-api@vger.kernel.org ã«é€ã‚‹ã“ã¨ã‚’å‹§ã‚ã¾ã™ã€‚
以下ã¯ã‚«ãƒ¼ãƒãƒ«ã‚½ãƒ¼ã‚¹ãƒ„リーã«å«ã¾ã‚Œã¦ã„る読んã§ãŠãã¹ãファイルã®ä¸€è¦§ã§
ã™-
- README
+ :ref:`Documentation/admin-guide/README.rst <readme>`
ã“ã®ãƒ•ァイル㯠Linuxカーãƒãƒ«ã®ç°¡å˜ãªèƒŒæ™¯ã¨ã‚«ãƒ¼ãƒãƒ«ã‚’設定(訳注
configure )ã—ã€ç”Ÿæˆ(訳注 build )ã™ã‚‹ãŸã‚ã«å¿…è¦ãªã“ã¨ã¯ä½•ã‹ãŒæ›¸ã‹ã‚Œ
ã¦ã„ã¾ã™ã€‚ カーãƒãƒ«ã«é–¢ã—ã¦åˆã‚ã¦ã®äººã¯ã“ã“ã‹ã‚‰ã‚¹ã‚¿ãƒ¼ãƒˆã™ã‚‹ã¨è‰¯ã„
@@ -145,7 +150,8 @@ linux-api@vger.kernel.org ã«é€ã‚‹ã“ã¨ã‚’å‹§ã‚ã¾ã™ã€‚
ã“ã®ä»–ã«ãƒ‘ッãƒã‚’作る方法ã«ã¤ã„ã¦ã®ã‚ˆãã§ããŸè¨˜è¿°ã¯-
"The Perfect Patch"
- http://www.ozlabs.org/~akpm/stuff/tpp.txt
+ https://www.ozlabs.org/~akpm/stuff/tpp.txt
+
"Linux kernel patch submission format"
https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html
@@ -237,13 +243,6 @@ Linux カーãƒãƒ«ã‚½ãƒ¼ã‚¹ãƒ„リーã®ä¸­ã«å«ã¾ã‚Œã‚‹ã€ãれã„ã«ã—ã€ä¿
れるãŸã‚ã®åŸºç¤Žã‚’å­¦ã¶ã“ã¨ãŒã§ãã€ãã—ã¦ã‚‚ã—ã‚ãªãŸãŒã¾ã ã‚¢ã‚¤ãƒ‡ã‚£ã‚¢ã‚’æŒã£
ã¦ã„ãªã„å ´åˆã«ã¯ã€æ¬¡ã«ã‚„ã‚‹ä»•äº‹ã®æ–¹å‘性ãŒè¦‹ãˆã¦ãã‚‹ã‹ã‚‚ã—れã¾ã›ã‚“。
-ã‚‚ã—ã‚ãªãŸãŒã€ã™ã§ã«ã²ã¨ã¾ã¨ã¾ã‚Šã‚³ãƒ¼ãƒ‰ã‚’書ã„ã¦ã„ã¦ã€ã‚«ãƒ¼ãƒãƒ«ãƒ„リーã«å…¥
-れãŸã„ã¨æ€ã£ã¦ã„ãŸã‚Šã€ãれã«é–¢ã™ã‚‹é©åˆ‡ãªæ”¯æ´ã‚’求ã‚ãŸã„å ´åˆã€ã‚«ãƒ¼ãƒãƒ«ãƒ¡
-ンターズプロジェクトã¯ãã®ã‚ˆã†ãªçš†ã•んを助ã‘ã‚‹ãŸã‚ã«ã§ãã¾ã—ãŸã€‚ã“ã“ã«
-ã¯ãƒ¡ãƒ¼ãƒªãƒ³ã‚°ãƒªã‚¹ãƒˆãŒã‚りã€ä»¥ä¸‹ã‹ã‚‰å‚ç…§ã§ãã¾ã™ -
-
- https://selenic.com/mailman/listinfo/kernel-mentors
-
実際㫠Linux カーãƒãƒ«ã®ã‚³ãƒ¼ãƒ‰ã«ã¤ã„ã¦ä¿®æ­£ã‚’加ãˆã‚‹å‰ã«ã€ã©ã†ã‚„ã£ã¦ãã®
コードãŒå‹•作ã™ã‚‹ã®ã‹ã‚’ç†è§£ã™ã‚‹ã“ã¨ãŒå¿…è¦ã§ã™ã€‚ãã®ãŸã‚ã«ã¯ã€ç‰¹åˆ¥ãªãƒ„ー
ルã®åŠ©ã‘を借りã¦ã§ã‚‚ã€ãれを直接よã読むã“ã¨ãŒæœ€è‰¯ã®æ–¹æ³•ã§ã™(ã»ã¨ã‚“ã©
@@ -280,9 +279,11 @@ https://kernel.org ã®ãƒªãƒã‚¸ãƒˆãƒªã«å­˜åœ¨ã—ã¾ã™ã€‚
大ããªå¤‰æ›´ã¯ git(カーãƒãƒ«ã®ã‚½ãƒ¼ã‚¹ç®¡ç†ãƒ„ールã€è©³ç´°ã¯
http://git-scm.com/ å‚ç…§) を使ã£ã¦é€ã‚‹ã®ãŒå¥½ã¾ã—ã„やり方ã§ã™ãŒã€ãƒ‘ッ
ãƒãƒ•ァイルã®å½¢å¼ã®ã¾ã¾é€ã‚‹ã®ã§ã‚‚å分ã§ã™ã€‚
- - 2週間後ã€-rc1 カーãƒãƒ«ãŒãƒªãƒªãƒ¼ã‚¹ã•れã€ã“ã®å¾Œã«ã¯ã‚«ãƒ¼ãƒãƒ«å…¨ä½“ã®å®‰å®š
- 性ã«å½±éŸ¿ã‚’ã‚ãŸãˆã‚‹ã‚ˆã†ãªæ–°æ©Ÿèƒ½ã¯å«ã¾ãªã„類ã®ãƒ‘ッãƒã—ã‹å–り込むã“ã¨
- ã¯ã§ãã¾ã›ã‚“。新ã—ã„ドライãƒ(ã‚‚ã—ãã¯ãƒ•ァイルシステム)ã®ãƒ‘ッãƒã¯
+ - 2週間後 -rc1 カーãƒãƒ«ãŒãƒªãƒªãƒ¼ã‚¹ã•ã‚Œã€æ–°ã—ã„カーãƒãƒ«ã‚’å¯èƒ½ãªé™ã‚Šå …牢ã«
+ ã™ã‚‹ã“ã¨ã«ç„¦ç‚¹ãŒç§»ã‚Šã¾ã™ã€‚ã“ã®æœŸé–“ã®ãƒ‘ッãƒã®ã»ã¨ã‚“ã©ã¯é€€è¡Œã‚’修正ã™ã‚‹
+ ã‚‚ã®ã¨ãªã‚Šã¾ã™ã€‚以å‰ã‹ã‚‰å­˜åœ¨ã—ã¦ã„ãŸãƒã‚°ã¯é€€è¡Œã«ã¯å½“ãŸã‚‰ãªã„ãŸã‚ã€
+ é€ã‚‹ã®ã¯é‡è¦ãªä¿®æ­£ã ã‘ã«ã—ã¦ãã ã•ã„。
+ æ–°ã—ã„ドライム(ã‚‚ã—ãã¯ãƒ•ァイルシステム) ã®ãƒ‘ッãƒã¯
-rc1 ã®å¾Œã§å—ã‘付ã‘られるã“ã¨ã‚‚ã‚ã‚‹ã“ã¨ã‚’覚ãˆã¦ãŠã„ã¦ãã ã•ã„。ãª
ãœãªã‚‰ã€å¤‰æ›´ãŒç‹¬ç«‹ã—ã¦ã„ã¦ã€è¿½åŠ ã•れãŸã‚³ãƒ¼ãƒ‰ã®å¤–ã®é ˜åŸŸã«å½±éŸ¿ã‚’与ãˆ
ãªã„é™ã‚Šã€é€€è¡Œã®ãƒªã‚¹ã‚¯ã¯ç„¡ã„ã‹ã‚‰ã§ã™ã€‚-rc1 ãŒãƒªãƒªãƒ¼ã‚¹ã•れãŸå¾Œã€
@@ -308,9 +309,12 @@ Andrew Morton ㌠Linux-kernel メーリングリストã«ã‚«ãƒ¼ãƒãƒ«ãƒªãƒªãƒ¼ã
ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ãŒ3ã¤ã®æ•°å­—ã«åˆ†ã‹ã‚Œã¦ã„るカーãƒãƒ«ã¯ -stable カーãƒãƒ«ã§ã™ã€‚
ã“れã«ã¯æœ€åˆã®2ã¤ã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ã®æ•°å­—ã«å¯¾å¿œã—ãŸã€
-メインラインリリースã§è¦‹ã¤ã‹ã£ãŸã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£å•題や
+メジャーメインラインリリースã§è¦‹ã¤ã‹ã£ãŸã‚»ã‚­ãƒ¥ãƒªãƒ†ã‚£å•題や
é‡å¤§ãªå¾Œæˆ»ã‚Šã«å¯¾ã™ã‚‹æ¯”較的å°ã•ã„é‡è¦ãªä¿®æ­£ãŒå«ã¾ã‚Œã¾ã™ã€‚
+メジャー安定版シリーズã®ãれãžã‚Œã®ãƒªãƒªãƒ¼ã‚¹ã¯
+ãƒãƒ¼ã‚¸ãƒ§ãƒ³ç•ªå·ã®3番目を増加ã•ã›ã€æœ€åˆã®2ã¤ã®ç•ªå·ã¯åŒã˜å€¤ã‚’ä¿ã¡ã¾ã™ã€‚
+
ã“れã¯ã€é–‹ç™º/実験的ãƒãƒ¼ã‚¸ãƒ§ãƒ³ã®ãƒ†ã‚¹ãƒˆã«å”力ã™ã‚‹ã“ã¨ã«èˆˆå‘³ãŒç„¡ãã€æœ€æ–°
ã®å®‰å®šã—ãŸã‚«ãƒ¼ãƒãƒ«ã‚’使ã„ãŸã„ãƒ¦ãƒ¼ã‚¶ã«æŽ¨å¥¨ã™ã‚‹ãƒ–ランãƒã§ã™ã€‚
@@ -366,16 +370,10 @@ linux-next ã®å®Ÿè¡Œãƒ†ã‚¹ãƒˆã‚’行ã†å†’険好ããªãƒ†ã‚¹ã‚¿ãƒ¼ã¯å¤§ã„ã«æ­“
ãƒã‚°ãƒ¬ãƒãƒ¼ãƒˆ
-------------
-https://bugzilla.kernel.org 㯠Linux カーãƒãƒ«é–‹ç™ºè€…ãŒã‚«ãƒ¼ãƒãƒ«ã®ãƒã‚°ã‚’追跡ã™ã‚‹
-場所ã§ã™ã€‚ユーザã¯è¦‹ã¤ã‘ãŸãƒã‚°ã®å…¨ã¦ã‚’ã“ã®ãƒ„ールã§å ±å‘Šã™ã¹ãã§ã™ã€‚ã©ã†
-kernel bugzilla を使ã†ã‹ã®è©³ç´°ã¯ã€ä»¥ä¸‹ã‚’å‚ç…§ã—ã¦ãã ã•ã„ -
-
- https://bugzilla.kernel.org/page.cgi?id=faq.html
-
メインカーãƒãƒ«ã‚½ãƒ¼ã‚¹ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ã‚るファイル
-admin-guide/reporting-bugs.rstã¯ã‚«ãƒ¼ãƒãƒ«ãƒã‚°ã‚‰ã—ã„ã‚‚ã®ã«ã¤ã„ã¦ã©ã†ãƒ¬ãƒãƒ¼
-トã™ã‚‹ã‹ã®è‰¯ã„テンプレートã§ã‚りã€å•題ã®è¿½è·¡ã‚’助ã‘ã‚‹ãŸã‚ã«ã‚«ãƒ¼ãƒãƒ«é–‹ç™º
-者ã«ã¨ã£ã¦ã©ã‚“ãªæƒ…å ±ãŒå¿…è¦ãªã®ã‹ã®è©³ç´°ãŒæ›¸ã‹ã‚Œã¦ã„ã¾ã™ã€‚
+'Documentation/admin-guide/reporting-issues.rst'
+ã¯ã€ã‚«ãƒ¼ãƒãƒ«ãƒã‚°ã‚‰ã—ãã‚‚ã®ã®å ±å‘Šã®ä»•æ–¹ã€ãŠã‚ˆã³ã€ã‚«ãƒ¼ãƒãƒ«é–‹ç™ºè€…ãŒå•題を
+追跡ã™ã‚‹éš›ã®æ‰‹ãŒã‹ã‚Šã¨ãªã‚‹æƒ…å ±ã«ã¤ã„ã¦ã®è©³ç´°ã‚’説明ã—ã¦ã„ã¾ã™ã€‚
ãƒã‚°ãƒ¬ãƒãƒ¼ãƒˆã®ç®¡ç†
-------------------
@@ -388,15 +386,13 @@ admin-guide/reporting-bugs.rstã¯ã‚«ãƒ¼ãƒãƒ«ãƒã‚°ã‚‰ã—ã„ã‚‚ã®ã«ã¤ã„ã¦ã
é“ã§ã™ã€ãªãœãªã‚‰å¤šãã®äººã¯ä»–人ã®ãƒã‚°ã®ä¿®æ­£ã«æ™‚間を浪費ã™ã‚‹ã“ã¨ã‚’好ã¾ãª
ã„ã‹ã‚‰ã§ã™ã€‚
-ã™ã§ã«ãƒ¬ãƒãƒ¼ãƒˆã•れãŸãƒã‚°ã®ãŸã‚ã«ä»•事をã™ã‚‹ãŸã‚ã«ã¯ã€
-https://bugzilla.kernel.org ã«è¡Œã£ã¦ãã ã•ã„。もã—今後ã®ãƒã‚°ãƒ¬ãƒãƒ¼ãƒˆã«
-ã¤ã„ã¦ã‚¢ãƒ‰ãƒã‚¤ã‚¹ã‚’å—ã‘ãŸã„ã®ã§ã‚れã°ã€bugme-new メーリングリスト(æ–°ã—
-ã„ãƒã‚°ãƒ¬ãƒãƒ¼ãƒˆã ã‘ãŒã“ã“ã«ãƒ¡ãƒ¼ãƒ«ã•れる) ã¾ãŸã¯ bugme-janitor メーリン
-グリスト(bugzilla ã®å¤‰æ›´æ¯Žã«ã“ã“ã«ãƒ¡ãƒ¼ãƒ«ã•れる)を購読ã§ãã¾ã™ã€‚
-
- https://lists.linux-foundation.org/mailman/listinfo/bugme-new
-
- https://lists.linux-foundation.org/mailman/listinfo/bugme-janitors
+ã™ã§ã«ãƒ¬ãƒãƒ¼ãƒˆã•れãŸãƒã‚°ã®ä½œæ¥­ã‚’ã™ã‚‹ãŸã‚ã«ã¯ã€èˆˆå‘³ã®ã‚るサブシステムを
+見ã¤ã‘ã€ãã®ã‚µãƒ–システムã®ãƒã‚°ã®å ±å‘Šå…ˆ (多ãã®å ´åˆãƒ¡ãƒ¼ãƒªãƒ³ã‚°ãƒªã‚¹ãƒˆã€
+稀ã«ãƒã‚°ãƒˆãƒ©ãƒƒã‚«ãƒ¼) ã‚’ MAINTAINERS ファイルã§èª¿ã¹ã¦ãã ã•ã„。
+ãã®ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–ã§æœ€è¿‘ã®å ±å‘Šã‚’検索ã—ã€ã§ããã†ãªã‚‚ã®ã«åŠ›ã‚’è²¸ã—ã¦ãã ã•ã„。
+https://bugzilla.kernel.org ã§ãƒã‚°å ±å‘Šã‚’調ã¹ã‚ˆã†ã¨ã™ã‚‹äººã‚‚ã„ã‚‹ã§ã—ょã†ã€‚
+ã“れã¯é™ã‚‰ã‚ŒãŸä¸€éƒ¨ã®ã‚µãƒ–システムã®ãƒã‚°å ±å‘Šã¨è¿½è·¡ã«åˆ©ç”¨ã•れるã¨ã¨ã‚‚ã«ã€
+ã¨ã‚Šã‚ã‘ã€ã‚«ãƒ¼ãƒãƒ«å…¨ä½“ã«å¯¾ã™ã‚‹ãƒã‚°ã®ç™»éŒ²å…ˆã¨ãªã£ã¦ã„ã¾ã™ã€‚
メーリングリスト
----------------
@@ -621,7 +617,7 @@ Linux カーãƒãƒ«ã‚³ãƒŸãƒ¥ãƒ‹ãƒ†ã‚£ã¯ã€ä¸€åº¦ã«å¤§é‡ã®ã‚³ãƒ¼ãƒ‰ã®å¡Šã‚’å–
ント㮠ChangeLog セクションを見ã¦ãã ã•ã„ -
"The Perfect Patch"
- http://www.ozlabs.org/~akpm/stuff/tpp.txt
+ https://www.ozlabs.org/~akpm/stuff/tpp.txt
ã“れらã¯ã©ã‚Œã‚‚ã€å®Ÿè¡Œã™ã‚‹ã“ã¨ãŒæ™‚ã«ã¯ã¨ã¦ã‚‚困難ã§ã™ã€‚ã“れらã®ä¾‹ã‚’完璧ã«
実施ã™ã‚‹ã«ã¯æ•°å¹´ã‹ã‹ã‚‹ã‹ã‚‚ã—れã¾ã›ã‚“。ã“れã¯ç¶™ç¶šçš„ãªæ”¹å–„ã®ãƒ—ロセスã§ã‚
diff --git a/Documentation/translations/ko_KR/memory-barriers.txt b/Documentation/translations/ko_KR/memory-barriers.txt
index 75aa5531cc7d..7165927a708e 100644
--- a/Documentation/translations/ko_KR/memory-barriers.txt
+++ b/Documentation/translations/ko_KR/memory-barriers.txt
@@ -80,7 +80,7 @@ Documentation/memory-barriers.txt
- 메모리 ë°°ë¦¬ì–´ì˜ ì¢…ë¥˜.
- 메모리 ë°°ë¦¬ì–´ì— ëŒ€í•´ 가정해선 ì•ˆë  ê²ƒ.
- - ë°ì´í„° ì˜ì¡´ì„± 배리어 (역사ì ).
+ - 주소 ë°ì´í„° ì˜ì¡´ì„± 배리어 (역사ì ).
- 컨트롤 ì˜ì¡´ì„±.
- SMP 배리어 ì§ë§žì¶”기.
- 메모리 배리어 ì‹œí€€ìŠ¤ì˜ ì˜ˆ.
@@ -217,7 +217,7 @@ Documentation/memory-barriers.txt
P = &B D = *Q;
D 로 ì½í˜€ì§€ëŠ” ê°’ì€ CPU 2 ì—서 P 로부터 ì½í˜€ì§„ ì£¼ì†Œê°’ì— ì˜ì¡´ì ì´ê¸° ë•Œë¬¸ì— ì—¬ê¸°ì—”
-분명한 ë°ì´í„° ì˜ì¡´ì„±ì´ 있습니다. 하지만 ì´ ì´ë²¤íŠ¸ë“¤ì˜ ì‹¤í–‰ 결과로는 아래ì˜
+분명한 주소 ì˜ì¡´ì„±ì´ 있습니다. 하지만 ì´ ì´ë²¤íŠ¸ë“¤ì˜ ì‹¤í–‰ 결과로는 아래ì˜
ê²°ê³¼ë“¤ì´ ëª¨ë‘ ë‚˜íƒ€ë‚  수 있습니다:
(Q == &A) and (D == 1)
@@ -416,19 +416,19 @@ CPU ì—게 기대할 수 있는 ìµœì†Œí•œì˜ ë³´ìž¥ì‚¬í•­ 몇가지가 있습니
하나씩 요청해 집어넣습니다. 쓰기 배리어 ì•žì˜ ëª¨ë“  스토어 오í¼ë ˆì´ì…˜ë“¤ì€
쓰기 배리어 ë’¤ì˜ ëª¨ë“  스토어 오í¼ë ˆì´ì…˜ë“¤ë³´ë‹¤ _앞서_ ìˆ˜í–‰ë  ê²ë‹ˆë‹¤.
- [!] 쓰기 ë°°ë¦¬ì–´ë“¤ì€ ì½ê¸° ë˜ëŠ” ë°ì´í„° ì˜ì¡´ì„± 배리어와 함께 ì§ì„ ë§žì¶°
+ [!] 쓰기 ë°°ë¦¬ì–´ë“¤ì€ ì½ê¸° ë˜ëŠ” 주소 ì˜ì¡´ì„± 배리어와 함께 ì§ì„ ë§žì¶°
사용ë˜ì–´ì•¼ë§Œ í•¨ì„ ì•Œì•„ë‘세요; "SMP 배리어 ì§ë§žì¶”기" ì„œë¸Œì„¹ì…˜ì„ ì°¸ê³ í•˜ì„¸ìš”.
- (2) ë°ì´í„° ì˜ì¡´ì„± 배리어.
+ (2) 주소 ì˜ì¡´ì„± 배리어 (역사ì ).
- ë°ì´í„° ì˜ì¡´ì„± 배리어는 ì½ê¸° ë°°ë¦¬ì–´ì˜ ë³´ë‹¤ ì™„í™”ëœ í˜•íƒœìž…ë‹ˆë‹¤. ë‘ê°œì˜ ë¡œë“œ
+ 주소 ì˜ì¡´ì„± 배리어는 ì½ê¸° ë°°ë¦¬ì–´ì˜ ë³´ë‹¤ ì™„í™”ëœ í˜•íƒœìž…ë‹ˆë‹¤. ë‘ê°œì˜ ë¡œë“œ
오í¼ë ˆì´ì…˜ì´ 있고 ë‘번째 ê²ƒì´ ì²«ë²ˆì§¸ ê²ƒì˜ ê²°ê³¼ì— ì˜ì¡´í•˜ê³  ìžˆì„ ë•Œ(예:
ë‘번째 로드가 참조할 주소를 첫번째 로드가 ì½ëŠ” 경우), ë‘번째 로드가 ì½ì–´ì˜¬
ë°ì´í„°ëŠ” 첫번째 ë¡œë“œì— ì˜í•´ ê·¸ 주소가 얻어진 ë’¤ì— ì—…ë°ì´íЏ ë¨ì„ 보장하기
- 위해서 ë°ì´í„° ì˜ì¡´ì„± 배리어가 필요할 수 있습니다.
+ 위해서 주소 ì˜ì¡´ì„± 배리어가 필요할 수 있습니다.
- ë°ì´í„° ì˜ì¡´ì„± 배리어는 ìƒí˜¸ ì˜ì¡´ì ì¸ 로드 오í¼ë ˆì´ì…˜ë“¤ 사ì´ì˜ ë¶€ë¶„ì  ìˆœì„œ
+ 주소 ì˜ì¡´ì„± 배리어는 ìƒí˜¸ ì˜ì¡´ì ì¸ 로드 오í¼ë ˆì´ì…˜ë“¤ 사ì´ì˜ ë¶€ë¶„ì  ìˆœì„œ
세우기입니다; 스토어 오í¼ë ˆì´ì…˜ë“¤ì´ë‚˜ ë…립ì ì¸ 로드들, ë˜ëŠ” 중복ë˜ëŠ”
ë¡œë“œë“¤ì— ëŒ€í•´ì„œëŠ” ì–´ë–¤ ì˜í–¥ë„ ë¼ì¹˜ì§€ 않습니다.
@@ -436,37 +436,41 @@ CPU ì—게 기대할 수 있는 ìµœì†Œí•œì˜ ë³´ìž¥ì‚¬í•­ 몇가지가 있습니
오í¼ë ˆì´ì…˜ë“¤ì„ ë˜ì ¸ 넣고 있으며, ê±°ê¸°ì— ê´€ì‹¬ì´ ìžˆëŠ” 다른 CPU 는 ê·¸
오í¼ë ˆì´ì…˜ë“¤ì„ 메모리 ì‹œìŠ¤í…œì´ ì‹¤í–‰í•œ 결과를 ì¸ì§€í•  수 있습니다. ì´ì²˜ëŸ¼
다른 CPU ì˜ ìŠ¤í† ì–´ 오í¼ë ˆì´ì…˜ì˜ ê²°ê³¼ì— ê´€ì‹¬ì„ ë‘ê³  있는 CPU ê°€ 수행 요청한
- ë°ì´í„° ì˜ì¡´ì„± 배리어는, 배리어 ì•žì˜ ì–´ë–¤ 로드 오í¼ë ˆì´ì…˜ì´ 다른 CPU ì—서
+ 주소 ì˜ì¡´ì„± 배리어는, 배리어 ì•žì˜ ì–´ë–¤ 로드 오í¼ë ˆì´ì…˜ì´ 다른 CPU ì—서
ë˜ì ¸ ë„£ì€ ìŠ¤í† ì–´ 오í¼ë ˆì´ì…˜ê³¼ ê°™ì€ ì˜ì—­ì„ 향했다면, 그런 스토어
- 오í¼ë ˆì´ì…˜ë“¤ì´ 만들어내는 결과가 ë°ì´í„° ì˜ì¡´ì„± 배리어 ë’¤ì˜ ë¡œë“œ
+ 오í¼ë ˆì´ì…˜ë“¤ì´ 만들어내는 결과가 주소 ì˜ì¡´ì„± 배리어 ë’¤ì˜ ë¡œë“œ
오í¼ë ˆì´ì…˜ë“¤ì—게는 ë³´ì¼ ê²ƒì„ ë³´ìž¥í•©ë‹ˆë‹¤.
ì´ ìˆœì„œ 세우기 ì œì•½ì— ëŒ€í•œ ê·¸ë¦¼ì„ ë³´ê¸° 위해선 "메모리 배리어 ì‹œí€€ìŠ¤ì˜ ì˜ˆ"
ì„œë¸Œì„¹ì…˜ì„ ì°¸ê³ í•˜ì‹œê¸° ë°”ëžë‹ˆë‹¤.
- [!] 첫번째 로드는 반드시 _ë°ì´í„°_ ì˜ì¡´ì„±ì„ 가져야지 컨트롤 ì˜ì¡´ì„±ì„ 가져야
+ [!] 첫번째 로드는 반드시 _주소_ ì˜ì¡´ì„±ì„ 가져야지 컨트롤 ì˜ì¡´ì„±ì„ 가져야
하는게 ì•„ë‹˜ì„ ì•Œì•„ë‘십시오. 만약 ë‘번째 로드를 위한 주소가 첫번째 로드ì—
ì˜ì¡´ì ì´ì§€ë§Œ ê·¸ ì˜ì¡´ì„±ì€ ì¡°ê±´ì ì´ì§€ ê·¸ 주소 ìžì²´ë¥¼ 가져오는게 아니ë¼ë©´,
ê·¸ê²ƒì€ _컨트롤_ ì˜ì¡´ì„±ì´ê³ , ì´ ê²½ìš°ì—는 ì½ê¸° 배리어나 그보다 강력한
무언가가 필요합니다. ë” ìžì„¸í•œ ë‚´ìš©ì„ ìœ„í•´ì„œëŠ” "컨트롤 ì˜ì¡´ì„±" 서브섹션ì„
참고하시기 ë°”ëžë‹ˆë‹¤.
- [!] ë°ì´í„° ì˜ì¡´ì„± 배리어는 보통 쓰기 배리어들과 함께 ì§ì„ ë§žì¶° 사용ë˜ì–´ì•¼
+ [!] 주소 ì˜ì¡´ì„± 배리어는 보통 쓰기 배리어들과 함께 ì§ì„ ë§žì¶° 사용ë˜ì–´ì•¼
합니다; "SMP 배리어 ì§ë§žì¶”기" ì„œë¸Œì„¹ì…˜ì„ ì°¸ê³ í•˜ì„¸ìš”.
+ [!] ì»¤ë„ v5.9 릴리즈ì—서 ëª…ì‹œì  ì£¼ì†Œ ì˜ì¡´ì„± 배리어를 위한 ì»¤ë„ API 들ì´
+ ì‚­ì œë˜ì—ˆìŠµë‹ˆë‹¤. 오늘날ì—는 ê³µìœ ëœ ë³€ìˆ˜ë“¤ì˜ ë¡œë“œë¥¼ 표시하는 READ_ONCE() 나
+ rcu_dereference() 와 ê°™ì€ API ë“¤ì€ ë¬µì‹œì ìœ¼ë¡œ 주소 ì˜ì¡´ì„± 배리어를 제공합니다.
+
(3) ì½ê¸° (ë˜ëŠ” 로드) 메모리 배리어.
- ì½ê¸° 배리어는 ë°ì´í„° ì˜ì¡´ì„± 배리어 ê¸°ëŠ¥ì˜ ë³´ìž¥ì‚¬í•­ì— ë”해서 배리어보다
- 앞서 ëª…ì‹œëœ ëª¨ë“  LOAD 오í¼ë ˆì´ì…˜ë“¤ì´ 배리어 ë’¤ì— ëª…ì‹œë˜ëŠ” 모든 LOAD
+ ì½ê¸° 배리어는 주소 ì˜ì¡´ì„± 배리어 ê¸°ëŠ¥ì˜ ë³´ìž¥ì‚¬í•­ì— ë”해서 배리어보다 앞서
+ ëª…ì‹œëœ ëª¨ë“  LOAD 오í¼ë ˆì´ì…˜ë“¤ì´ 배리어 ë’¤ì— ëª…ì‹œë˜ëŠ” 모든 LOAD
오í¼ë ˆì´ì…˜ë“¤ë³´ë‹¤ 먼저 행해진 것으로 ì‹œìŠ¤í…œì˜ ë‹¤ë¥¸ ì»´í¬ë„ŒíŠ¸ë“¤ì— ë³´ì—¬ì§ˆ 것ì„
보장합니다.
ì½ê¸° 배리어는 로드 오í¼ë ˆì´ì…˜ì— 행해지는 ë¶€ë¶„ì  ìˆœì„œ 세우기입니다; 스토어
오í¼ë ˆì´ì…˜ì— 대해서는 ì–´ë–¤ ì˜í–¥ë„ ë¼ì¹˜ì§€ 않습니다.
- ì½ê¸° 메모리 배리어는 ë°ì´í„° ì˜ì¡´ì„± 배리어를 내장하므로 ë°ì´í„° ì˜ì¡´ì„±
- 배리어를 대신할 수 있습니다.
+ ì½ê¸° 메모리 배리어는 주소 ì˜ì¡´ì„± 배리어를 내장하므로 주소 ì˜ì¡´ì„± 배리어를
+ 대신할 수 있습니다.
[!] ì½ê¸° 배리어는 ì¼ë°˜ì ìœ¼ë¡œ 쓰기 배리어들과 함께 ì§ì„ ë§žì¶° 사용ë˜ì–´ì•¼
합니다; "SMP 배리어 ì§ë§žì¶”기" ì„œë¸Œì„¹ì…˜ì„ ì°¸ê³ í•˜ì„¸ìš”.
@@ -571,16 +575,20 @@ ACQUIRE 는 해당 오í¼ë ˆì´ì…˜ì˜ 로드 부분ì—ë§Œ ì ìš©ë˜ê³  RELEASE ë
Documentation/core-api/dma-api.rst
-ë°ì´í„° ì˜ì¡´ì„± 배리어 (역사ì )
------------------------------
+주소 ì˜ì¡´ì„± 배리어 (역사ì )
+---------------------------
리눅스 ì»¤ë„ v4.15 기준으로, smp_mb() ê°€ DEC Alpha ìš© READ_ONCE() 코드ì—
추가ë˜ì—ˆëŠ”ë°, ì´ëŠ” ì´ ì„¹ì…˜ì— ì£¼ì˜ë¥¼ 기울여야 하는 ì‚¬ëžŒë“¤ì€ DEC Alpha 아키í…ì³
ì „ìš© 코드를 만드는 사람들과 READ_ONCE() ìžì²´ë¥¼ 만드는 사람들 ë¿ìž„ì„ ì˜ë¯¸í•©ë‹ˆë‹¤.
-그런 ë¶„ë“¤ì„ ìœ„í•´, 그리고 ì—­ì‚¬ì— ê´€ì‹¬ 있는 ë¶„ë“¤ì„ ìœ„í•´, 여기 ë°ì´í„° ì˜ì¡´ì„±
+그런 ë¶„ë“¤ì„ ìœ„í•´, 그리고 ì—­ì‚¬ì— ê´€ì‹¬ 있는 ë¶„ë“¤ì„ ìœ„í•´, 여기 주소 ì˜ì¡´ì„±
ë°°ë¦¬ì–´ì— ëŒ€í•œ ì´ì•¼ê¸°ë¥¼ ì ìŠµë‹ˆë‹¤.
-ë°ì´í„° ì˜ì¡´ì„± ë°°ë¦¬ì–´ì˜ ì‚¬ìš©ì— ìžˆì–´ 지켜야 하는 ì‚¬í•­ë“¤ì€ ì•½ê°„ 미묘하고, ë°ì´í„°
+[!] 주소 ì˜ì¡´ì„±ì€ 로드ì—서 로드로와 로드ì—서 ìŠ¤í† ì–´ë¡œì˜ ê´€ê³„ë“¤ 모ë‘ì—서
+나타나지만, 주소 ì˜ì¡´ì„± 배리어는 로드ì—서 ìŠ¤í† ì–´ë¡œì˜ ìƒí™©ì—서는 필요하지
+않습니다.
+
+주소 ì˜ì¡´ì„± ë°°ë¦¬ì–´ì˜ ì‚¬ìš©ì— ìžˆì–´ 지켜야 하는 ì‚¬í•­ë“¤ì€ ì•½ê°„ 미묘하고, ë°ì´í„°
ì˜ì¡´ì„± 배리어가 사용ë˜ì–´ì•¼ 하는 ìƒí™©ë„ í•­ìƒ ëª…ë°±í•˜ì§€ëŠ” 않습니다. ì„¤ëª…ì„ ìœ„í•´
다ìŒì˜ ì´ë²¤íЏ 시퀀스를 ìƒê°í•´ 봅시다:
@@ -590,10 +598,13 @@ ACQUIRE 는 해당 오í¼ë ˆì´ì…˜ì˜ 로드 부분ì—ë§Œ ì ìš©ë˜ê³  RELEASE ë
B = 4;
<쓰기 배리어>
WRITE_ONCE(P, &B)
- Q = READ_ONCE(P);
+ Q = READ_ONCE_OLD(P);
D = *Q;
-여기엔 분명한 ë°ì´í„° ì˜ì¡´ì„±ì´ 존재하므로, ì´ ì‹œí€€ìŠ¤ê°€ ëë‚¬ì„ ë•Œ Q 는 &A ë˜ëŠ” &B
+[!] READ_ONCE_OLD() 는 4.15 ì»¤ë„ ì „ì˜ ë²„ì „ì—서ì˜, 주소 ì˜ì¡´ì„± 배리어를 ë‚´í¬í•˜ì§€
+않는 READ_ONCE() ì— í•´ë‹¹í•©ë‹ˆë‹¤.
+
+여기엔 분명한 주소 ì˜ì¡´ì„±ì´ 존재하므로, ì´ ì‹œí€€ìŠ¤ê°€ ëë‚¬ì„ ë•Œ Q 는 &A ë˜ëŠ” &B
ì¼ ê²ƒì´ê³ , ë”°ë¼ì„œ:
(Q == &A) 는 (D == 1) 를,
@@ -608,8 +619,8 @@ ACQUIRE 는 해당 오í¼ë ˆì´ì…˜ì˜ 로드 부분ì—ë§Œ ì ìš©ë˜ê³  RELEASE ë
그렇지 않습니다, 그리고 ì´ í˜„ìƒì€ (DEC Alpha 와 ê°™ì€) 여러 CPU ì—서 실제로
ë°œê²¬ë  ìˆ˜ 있습니다.
-ì´ ë¬¸ì œ ìƒí™©ì„ 제대로 해결하기 위해, ë°ì´í„° ì˜ì¡´ì„± 배리어나 그보다 ê°•í™”ëœ
-무언가가 주소를 ì½ì–´ì˜¬ 때와 ë°ì´í„°ë¥¼ ì½ì–´ì˜¬ 때 사ì´ì— 추가ë˜ì–´ì•¼ë§Œ 합니다:
+ì´ ë¬¸ì œ ìƒí™©ì„ 제대로 해결하기 위해, READ_ONCE() 는 ì»¤ë„ v4.15 릴리즈 부터
+ë¬µì‹œì  ì£¼ì†Œ ì˜ì¡´ì„± 배리어를 제공합니다:
CPU 1 CPU 2
=============== ===============
@@ -618,7 +629,7 @@ ACQUIRE 는 해당 오í¼ë ˆì´ì…˜ì˜ 로드 부분ì—ë§Œ ì ìš©ë˜ê³  RELEASE ë
<쓰기 배리어>
WRITE_ONCE(P, &B);
Q = READ_ONCE(P);
- <ë°ì´í„° ì˜ì¡´ì„± 배리어>
+ <ë¬µì‹œì  ì£¼ì†Œ ì˜ì¡´ì„± 배리어>
D = *Q;
ì´ ë³€ê²½ì€ ì•žì˜ ì²˜ìŒ ë‘가지 ê²°ê³¼ 중 í•˜ë‚˜ë§Œì´ ë°œìƒí•  수 있고, ì„¸ë²ˆì§¸ì˜ ê²°ê³¼ëŠ”
@@ -634,7 +645,7 @@ P 는 ì§ìˆ˜ 번호 ìºì‹œ ë¼ì¸ì— 저장ë˜ì–´ 있고, 변수 B 는 홀수 ë²
중ì´ë¼ë©´ í¬ì¸í„° P (&B) ì˜ ìƒˆë¡œìš´ ê°’ê³¼ 변수 B ì˜ ê¸°ì¡´ ê°’ (2) 를 ë³¼ 수 있습니다.
-ì˜ì¡´ì  ì“°ê¸°ë“¤ì˜ ìˆœì„œë¥¼ 맞추는ë°ì—는 ë°ì´í„° ì˜ì¡´ì„± 배리어가 필요치 않ì€ë°, ì´ëŠ”
+ì˜ì¡´ì  ì“°ê¸°ë“¤ì˜ ìˆœì„œë¥¼ 맞추는ë°ì—는 주소 ì˜ì¡´ì„± 배리어가 필요치 않ì€ë°, ì´ëŠ”
리눅스 커ë„ì´ ì§€ì›í•˜ëŠ” CPU ë“¤ì€ (1) 쓰기가 ì •ë§ë¡œ ì¼ì–´ë‚ ì§€, (2) 쓰기가 ì–´ë””ì—
ì´ë£¨ì–´ì§ˆì§€, 그리고 (3) 쓰여질 ê°’ì„ í™•ì‹¤ížˆ 알기 전까지는 쓰기를 수행하지 않기
때문입니다. 하지만 "컨트롤 ì˜ì¡´ì„±" 섹션과
@@ -647,12 +658,12 @@ Documentation/RCU/rcu_dereference.rst 파ì¼ì„ ì£¼ì˜ ê¹Šê²Œ ì½ì–´ 주시기 ë
B = 4;
<쓰기 배리어>
WRITE_ONCE(P, &B);
- Q = READ_ONCE(P);
+ Q = READ_ONCE_OLD(P);
WRITE_ONCE(*Q, 5);
-ë”°ë¼ì„œ, Q ë¡œì˜ ì½ê¸°ì™€ *Q ë¡œì˜ ì“°ê¸° 사ì´ì—는 ë°ì´í„° 종ì†ì„± 배리어가 필요치
-않습니다. 달리 ë§í•˜ë©´, ë°ì´í„° 종ì†ì„± 배리어가 ì—†ë”ë¼ë„ ë‹¤ìŒ ê²°ê³¼ëŠ” ìƒê¸°ì§€
-않습니다:
+ë”°ë¼ì„œ, Q ë¡œì˜ ì½ê¸°ì™€ *Q ë¡œì˜ ì“°ê¸° 사ì´ì—는 주소 ì˜ì¡´ì„± 배리어가 필요치
+않습니다. 달리 ë§í•˜ë©´, ì˜¤ëŠ˜ë‚ ì˜ READ_ONCE() ì˜ ë¬µì‹œì  ì£¼ì†Œ ì˜ì¡´ì„± 배리어가
+ì—†ë”ë¼ë„ ë‹¤ìŒ ê²°ê³¼ëŠ” ìƒê¸°ì§€ 않습니다:
(Q == &B) && (B == 4)
@@ -663,16 +674,16 @@ Documentation/RCU/rcu_dereference.rst 파ì¼ì„ ì£¼ì˜ ê¹Šê²Œ ì½ì–´ 주시기 ë
í•´ì¤ë‹ˆë‹¤.
-ë°ì´í„° ì˜ì¡´ì„±ì— ì˜í•´ 제공ë˜ëŠ” ì´ ìˆœì„œê·œì¹™ì€ ì´ë¥¼ í¬í•¨í•˜ê³  있는 CPU ì—
+주소 ì˜ì¡´ì„±ì— ì˜í•´ 제공ë˜ëŠ” ì´ ìˆœì„œê·œì¹™ì€ ì´ë¥¼ í¬í•¨í•˜ê³  있는 CPU ì—
지역ì ìž„ì„ ì•Œì•„ë‘시기 ë°”ëžë‹ˆë‹¤. ë” ë§Žì€ ì •ë³´ë¥¼ 위해선 "Multicopy ì›ìžì„±"
ì„¹ì…˜ì„ ì°¸ê³ í•˜ì„¸ìš”.
-ë°ì´í„° ì˜ì¡´ì„± 배리어는 매우 중요한ë°, 예를 들어 RCU 시스템ì—서 그렇습니다.
+주소 ì˜ì¡´ì„± 배리어는 매우 중요한ë°, 예를 들어 RCU 시스템ì—서 그렇습니다.
include/linux/rcupdate.h ì˜ rcu_assign_pointer() 와 rcu_dereference() 를
-참고하세요. 여기서 ë°ì´í„° ì˜ì¡´ì„± 배리어는 RCU 로 관리ë˜ëŠ” í¬ì¸í„°ì˜ íƒ€ê²Ÿì„ í˜„ìž¬
-타겟ì—서 ìˆ˜ì •ëœ ìƒˆë¡œìš´ 타겟으로 바꾸는 작업ì—서 새로 ìˆ˜ì •ëœ íƒ€ê²Ÿì´ ì´ˆê¸°í™”ê°€
-완료ë˜ì§€ ì•Šì€ ì±„ë¡œ 보여지는 ì¼ì´ ì¼ì–´ë‚˜ì§€ 않게 í•´ì¤ë‹ˆë‹¤.
+참고하세요. ì´ê²ƒë“¤ì€ RCU 로 관리ë˜ëŠ” í¬ì¸í„°ì˜ íƒ€ê²Ÿì„ í˜„ìž¬ 타겟ì—서 수정ëœ
+새로운 타겟으로 바꾸는 작업ì—서 새로 ìˆ˜ì •ëœ íƒ€ê²Ÿì´ ì´ˆê¸°í™”ê°€ 완료ë˜ì§€ ì•Šì€ ì±„ë¡œ
+보여지는 ì¼ì´ ì¼ì–´ë‚˜ì§€ 않게 í•´ì¤ë‹ˆë‹¤.
ë” ë§Žì€ ì˜ˆë¥¼ 위해선 "ìºì‹œ ì¼ê´€ì„±" ì„œë¸Œì„¹ì…˜ì„ ì°¸ê³ í•˜ì„¸ìš”.
@@ -684,16 +695,17 @@ include/linux/rcupdate.h ì˜ rcu_assign_pointer() 와 rcu_dereference() 를
약간 다루기 어려울 수 있습니다. ì´ ì„¹ì…˜ì˜ ëª©ì ì€ ì—¬ëŸ¬ë¶„ì´ ì»´íŒŒì¼ëŸ¬ì˜ 무시로
ì¸í•´ ì—¬ëŸ¬ë¶„ì˜ ì½”ë“œê°€ ë§ê°€ì§€ëŠ” 걸 ë§‰ì„ ìˆ˜ 있ë„ë¡ ë•는ê²ë‹ˆë‹¤.
-로드-로드 컨트롤 ì˜ì¡´ì„±ì€ ë°ì´í„° ì˜ì¡´ì„± 배리어만으로는 정확히 ë™ìž‘í•  수가
-없어서 ì½ê¸° 메모리 배리어를 필요로 합니다. ì•„ëž˜ì˜ ì½”ë“œë¥¼ 봅시다:
+로드-로드 컨트롤 ì˜ì¡´ì„±ì€ (묵시ì ì¸) 주소 ì˜ì¡´ì„± 배리어만으로는 정확히 ë™ìž‘í• 
+수가 없어서 ì½ê¸° 메모리 배리어를 필요로 합니다. ì•„ëž˜ì˜ ì½”ë“œë¥¼ 봅시다:
q = READ_ONCE(a);
+ <ë¬µì‹œì  ì£¼ì†Œ ì˜ì¡´ì„± 배리어>
if (q) {
- <ë°ì´í„° ì˜ì¡´ì„± 배리어> /* BUG: No data dependency!!! */
+ /* BUG: No address dependency!!! */
p = READ_ONCE(b);
}
-ì´ ì½”ë“œëŠ” ì›í•˜ëŠ” ëŒ€ë¡œì˜ íš¨ê³¼ë¥¼ ë‚´ì§€ 못할 수 있는ë°, ì´ ì½”ë“œì—는 ë°ì´í„° ì˜ì¡´ì„±ì´
+ì´ ì½”ë“œëŠ” ì›í•˜ëŠ” ëŒ€ë¡œì˜ íš¨ê³¼ë¥¼ ë‚´ì§€ 못할 수 있는ë°, ì´ ì½”ë“œì—는 주소 ì˜ì¡´ì„±ì´
ì•„ë‹ˆë¼ ì»¨íŠ¸ë¡¤ ì˜ì¡´ì„±ì´ 존재하기 때문으로, ì´ëŸ° ìƒí™©ì—서 CPU 는 실행 ì†ë„를 ë”
빠르게 하기 위해 분기 ì¡°ê±´ì˜ ê²°ê³¼ë¥¼ 예측하고 코드를 재배치 í•  수 있어서 다른
CPU 는 b ë¡œë¶€í„°ì˜ ë¡œë“œ 오í¼ë ˆì´ì…˜ì´ a ë¡œë¶€í„°ì˜ ë¡œë“œ 오í¼ë ˆì´ì…˜ë³´ë‹¤ 먼저 ë°œìƒí•œ
@@ -930,9 +942,9 @@ CPU ê°„ ìƒí˜¸ìž‘ìš©ì„ ë‹¤ë£° ë•Œì— ì¼ë¶€ íƒ€ìž…ì˜ ë©”ëª¨ë¦¬ 배리어는 í•
범용 ë°°ë¦¬ì–´ë“¤ì€ ë²”ìš© 배리어ë¼ë¦¬ë„ ì§ì„ 맞추지만 multicopy ì›ìžì„±ì´ 없는
ëŒ€ë¶€ë¶„ì˜ ë‹¤ë¥¸ íƒ€ìž…ì˜ ë°°ë¦¬ì–´ë“¤ê³¼ë„ ì§ì„ 맞춥니다. ACQUIRE 배리어는 RELEASE
배리어와 ì§ì„ 맞춥니다만, 둘 다 범용 배리어를 í¬í•¨í•´ 다른 ë°°ë¦¬ì–´ë“¤ê³¼ë„ ì§ì„
-ë§žì¶œ 수 있습니다. 쓰기 배리어는 ë°ì´í„° ì˜ì¡´ì„± 배리어나 컨트롤 ì˜ì¡´ì„±, ACQUIRE
+ë§žì¶œ 수 있습니다. 쓰기 배리어는 주소 ì˜ì¡´ì„± 배리어나 컨트롤 ì˜ì¡´ì„±, ACQUIRE
배리어, RELEASE 배리어, ì½ê¸° 배리어, ë˜ëŠ” 범용 배리어와 ì§ì„ 맞춥니다.
-비슷하게 ì½ê¸° 배리어나 컨트롤 ì˜ì¡´ì„±, ë˜ëŠ” ë°ì´í„° ì˜ì¡´ì„± 배리어는 쓰기 배리어나
+비슷하게 ì½ê¸° 배리어나 컨트롤 ì˜ì¡´ì„±, ë˜ëŠ” 주소 ì˜ì¡´ì„± 배리어는 쓰기 배리어나
ACQUIRE 배리어, RELEASE 배리어, ë˜ëŠ” 범용 배리어와 ì§ì„ 맞추는ë°, 다ìŒê³¼
같습니다:
@@ -951,7 +963,7 @@ ACQUIRE 배리어, RELEASE 배리어, ë˜ëŠ” 범용 배리어와 ì§ì„ ë§žì¶”ëŠ
a = 1;
<쓰기 배리어>
WRITE_ONCE(b, &a); x = READ_ONCE(b);
- <ë°ì´í„° ì˜ì¡´ì„± 배리어>
+ <ë¬µì‹œì  ì£¼ì†Œ ì˜ì¡´ì„± 배리어>
y = *x;
ë˜ëŠ”:
@@ -970,8 +982,8 @@ ACQUIRE 배리어, RELEASE 배리어, ë˜ëŠ” 범용 배리어와 ì§ì„ ë§žì¶”ëŠ
기본ì ìœ¼ë¡œ, ì—¬ê¸°ì„œì˜ ì½ê¸° 배리어는 "ë” ì™„í™”ëœ" íƒ€ìž…ì¼ ìˆœ ìžˆì–´ë„ í•­ìƒ ì¡´ìž¬í•´ì•¼
합니다.
-[!] 쓰기 배리어 ì•žì˜ ìŠ¤í† ì–´ 오í¼ë ˆì´ì…˜ì€ ì¼ë°˜ì ìœ¼ë¡œ ì½ê¸° 배리어나 ë°ì´í„°
-ì˜ì¡´ì„± 배리어 ë’¤ì˜ ë¡œë“œ 오í¼ë ˆì´ì…˜ê³¼ ë§¤ì¹˜ë  ê²ƒì´ê³ , ë°˜ëŒ€ë„ ë§ˆì°¬ê°€ì§€ìž…ë‹ˆë‹¤:
+[!] 쓰기 배리어 ì•žì˜ ìŠ¤í† ì–´ 오í¼ë ˆì´ì…˜ì€ ì¼ë°˜ì ìœ¼ë¡œ ì½ê¸° 배리어나 주소 ì˜ì¡´ì„±
+배리어 ë’¤ì˜ ë¡œë“œ 오í¼ë ˆì´ì…˜ê³¼ ë§¤ì¹˜ë  ê²ƒì´ê³ , ë°˜ëŒ€ë„ ë§ˆì°¬ê°€ì§€ìž…ë‹ˆë‹¤:
CPU 1 CPU 2
=================== ===================
@@ -1023,7 +1035,7 @@ ACQUIRE 배리어, RELEASE 배리어, ë˜ëŠ” 범용 배리어와 ì§ì„ ë§žì¶”ëŠ
V
-둘째, ë°ì´í„° ì˜ì¡´ì„± 배리어는 ë°ì´í„° ì˜ì¡´ì  로드 오í¼ë ˆì´ì…˜ë“¤ì˜ ë¶€ë¶„ì  ìˆœì„œ
+둘째, 주소 ì˜ì¡´ì„± 배리어는 ë°ì´í„° ì˜ì¡´ì  로드 오í¼ë ˆì´ì…˜ë“¤ì˜ ë¶€ë¶„ì  ìˆœì„œ
세우기로 ë™ìž‘합니다. ë‹¤ìŒ ì¼ë ¨ì˜ ì´ë²¤íŠ¸ë“¤ì„ ë³´ì„¸ìš”:
CPU 1 CPU 2
@@ -1069,7 +1081,7 @@ ACQUIRE 배리어, RELEASE 배리어, ë˜ëŠ” 범용 배리어와 ì§ì„ ë§žì¶”ëŠ
ì•žì˜ ì˜ˆì—서, CPU 2 는 (B ì˜ ê°’ì´ ë ) *C ì˜ ê°’ ì½ê¸°ê°€ C ì˜ LOAD ë’¤ì— ì´ì–´ì§ì—ë„
B ê°€ 7 ì´ë¼ëŠ” 결과를 얻습니다.
-하지만, 만약 ë°ì´í„° ì˜ì¡´ì„± 배리어가 C ì˜ ë¡œë“œì™€ *C (즉, B) ì˜ ë¡œë“œ 사ì´ì—
+하지만, 만약 주소 ì˜ì¡´ì„± 배리어가 C ì˜ ë¡œë“œì™€ *C (즉, B) ì˜ ë¡œë“œ 사ì´ì—
있었다면:
CPU 1 CPU 2
@@ -1080,7 +1092,7 @@ B ê°€ 7 ì´ë¼ëŠ” 결과를 얻습니다.
<쓰기 배리어>
STORE C = &B LOAD X
STORE D = 4 LOAD C (gets &B)
- <ë°ì´í„° ì˜ì¡´ì„± 배리어>
+ <주소 ì˜ì¡´ì„± 배리어>
LOAD *C (reads B)
다ìŒê³¼ ê°™ì´ ë©ë‹ˆë‹¤:
@@ -1103,7 +1115,7 @@ B ê°€ 7 ì´ë¼ëŠ” 결과를 얻습니다.
| +-------+ | |
| | X->9 |------>| |
| +-------+ | |
- C ë¡œì˜ ìŠ¤í† ì–´ ì•žì˜ ---> \ ddddddddddddddddd | |
+ C ë¡œì˜ ìŠ¤í† ì–´ ì•žì˜ ---> \ aaaaaaaaaaaaaaaaa | |
모든 ì´ë²¤íЏ 결과가 \ +-------+ | |
ë’¤ì˜ ë¡œë“œì—게 ----->| B->2 |------>| |
ë³´ì´ê²Œ 강제한다 +-------+ | |
@@ -1291,7 +1303,7 @@ A ì˜ ë¡œë“œ ë‘개가 ëª¨ë‘ B ì˜ ë¡œë“œ ë’¤ì— ìžˆì§€ë§Œ, 서로 다른 ê°’ì
ì¦‰ê° ì™„ë£Œí•œë‹¤ : : +-------+
-ì½ê¸° 배리어나 ë°ì´í„° ì˜ì¡´ì„± 배리어를 ë‘번째 로드 ì§ì „ì— ë†“ëŠ”ë‹¤ë©´:
+ì½ê¸° 배리어나 주소 ì˜ì¡´ì„± 배리어를 ë‘번째 로드 ì§ì „ì— ë†“ëŠ”ë‹¤ë©´:
CPU 1 CPU 2
======================= =======================
@@ -1785,21 +1797,20 @@ READ_ONCE(jiffies) ë¼ê³  í•  필요가 없습니다. READ_ONCE() 와 WRITE_ONC
CPU 메모리 배리어
-----------------
-리눅스 커ë„ì€ ë‹¤ìŒì˜ ì—¬ëŸê°œ 기본 CPU 메모리 배리어를 가지고 있습니다:
+리눅스 커ë„ì€ ë‹¤ìŒì˜ ì¼ê³±ê°œ 기본 CPU 메모리 배리어를 가지고 있습니다:
TYPE MANDATORY SMP CONDITIONAL
- =============== ======================= ===========================
+ =============== ======================= ===============
범용 mb() smp_mb()
쓰기 wmb() smp_wmb()
ì½ê¸° rmb() smp_rmb()
- ë°ì´í„° ì˜ì¡´ì„± READ_ONCE()
+ 주소 ì˜ì¡´ì„± READ_ONCE()
-ë°ì´í„° ì˜ì¡´ì„± 배리어를 제외한 모든 메모리 배리어는 컴파ì¼ëŸ¬ 배리어를
-í¬í•¨í•©ë‹ˆë‹¤. ë°ì´í„° ì˜ì¡´ì„±ì€ 컴파ì¼ëŸ¬ì—ì˜ ì¶”ê°€ì ì¸ 순서 ë³´ìž¥ì„ í¬í•¨í•˜ì§€
-않습니다.
+주소 ì˜ì¡´ì„± 배리어를 제외한 모든 메모리 배리어는 컴파ì¼ëŸ¬ 배리어를 í¬í•¨í•©ë‹ˆë‹¤.
+주소 ì˜ì¡´ì„±ì€ 컴파ì¼ëŸ¬ì—ì˜ ì¶”ê°€ì ì¸ 순서 ë³´ìž¥ì„ í¬í•¨í•˜ì§€ 않습니다.
-ë°©ë°±: ë°ì´í„° ì˜ì¡´ì„±ì´ 있는 경우, 컴파ì¼ëŸ¬ëŠ” 해당 로드를 올바른 순서로 ì¼ìœ¼í‚¬
+ë°©ë°±: 주소 ì˜ì¡´ì„±ì´ 있는 경우, 컴파ì¼ëŸ¬ëŠ” 해당 로드를 올바른 순서로 ì¼ìœ¼í‚¬
것으로 (예: `a[b]` 는 a[b] 를 로드 하기 ì „ì— b ì˜ ê°’ì„ ë¨¼ì € 로드한다)
기대ë˜ì§€ë§Œ, C 언어 사양ì—는 컴파ì¼ëŸ¬ê°€ b ì˜ ê°’ì„ ì¶”ì¸¡ (예: 1 ê³¼ ê°™ìŒ) 해서
b 로드 ì „ì— a 로드를 하는 코드 (예: tmp = a[1]; if (b != 1) tmp = a[b]; ) 를
@@ -1863,6 +1874,7 @@ Mandatory ë°°ë¦¬ì–´ë“¤ì€ SMP 시스템ì—ì„œë„ UP 시스템ì—ì„œë„ SMP 효ê³
(*) dma_wmb();
(*) dma_rmb();
+ (*) dma_mb();
ì´ê²ƒë“¤ì€ CPU 와 DMA 가능한 디바ì´ìФì—서 ëª¨ë‘ ì•¡ì„¸ìŠ¤ 가능한 공유 메모리ì˜
ì½ê¸°, 쓰기 ìž‘ì—…ë“¤ì˜ ìˆœì„œë¥¼ 보장하기 위해 consistent memory ì—서 사용하기
@@ -1893,12 +1905,13 @@ Mandatory ë°°ë¦¬ì–´ë“¤ì€ SMP 시스템ì—ì„œë„ UP 시스템ì—ì„œë„ SMP 효ê³
dma_rmb() 는 디스í¬ë¦½í„°ë¡œë¶€í„° ë°ì´í„°ë¥¼ ì½ì–´ì˜¤ê¸° ì „ì— ë””ë°”ì´ìŠ¤ê°€ 소유권ì„
ë‚´ë ¤ë†“ì•˜ì„ ê²ƒì„ ë³´ìž¥í•˜ê³ , dma_wmb() 는 디바ì´ìŠ¤ê°€ ìžì‹ ì´ ì†Œìœ ê¶Œì„ ë‹¤ì‹œ
- 가졌ìŒì„ 보기 ì „ì— ë””ìŠ¤í¬ë¦½í„°ì— ë°ì´í„°ê°€ ì“°ì˜€ì„ ê²ƒì„ ë³´ìž¥í•©ë‹ˆë‹¤. 참고로,
- writel() ì„ ì‚¬ìš©í•˜ë©´ ìºì‹œ ì¼ê´€ì„±ì´ 있는 메모리 (cache coherent memory)
- 쓰기가 MMIO ì˜ì—­ì—ì˜ ì“°ê¸° ì „ì— ì™„ë£Œë˜ì—ˆì„ ê²ƒì„ ë³´ìž¥í•˜ë¯€ë¡œ writel() 앞ì—
- wmb() 를 실행할 필요가 ì—†ìŒì„ 알아ë‘시기 ë°”ëžë‹ˆë‹¤. writel() 보다 비용ì´
- 저렴한 writel_relaxed() 는 ì´ëŸ° ë³´ìž¥ì„ ì œê³µí•˜ì§€ 않으므로 여기선 사용ë˜ì§€
- 않아야 합니다.
+ 가졌ìŒì„ 보기 ì „ì— ë””ìŠ¤í¬ë¦½í„°ì— ë°ì´í„°ê°€ ì“°ì˜€ì„ ê²ƒì„ ë³´ìž¥í•©ë‹ˆë‹¤. dma_mb()
+ 는 dma_rmb() 와 dma_wmb() 를 ëª¨ë‘ ë‚´í¬í•©ë‹ˆë‹¤. 참고로, writel() ì„
+ 사용하면 ìºì‹œ ì¼ê´€ì„±ì´ 있는 메모리 (cache coherent memory) 쓰기가 MMIO
+ ì˜ì—­ì—ì˜ ì“°ê¸° ì „ì— ì™„ë£Œë˜ì—ˆì„ ê²ƒì„ ë³´ìž¥í•˜ë¯€ë¡œ writel() ì•žì— wmb() 를
+ 실행할 필요가 ì—†ìŒì„ 알아ë‘시기 ë°”ëžë‹ˆë‹¤. writel() 보다 ë¹„ìš©ì´ ì €ë ´í•œ
+ writel_relaxed() 는 ì´ëŸ° ë³´ìž¥ì„ ì œê³µí•˜ì§€ 않으므로 여기선 사용ë˜ì§€ 않아야
+ 합니다.
writel_relaxed() 와 ê°™ì€ ì™„í™”ëœ I/O ì ‘ê·¼ìžë“¤ì— 대한 ìžì„¸í•œ ë‚´ìš©ì„ ìœ„í•´ì„œëŠ”
"ì»¤ë„ I/O ë°°ë¦¬ì–´ì˜ íš¨ê³¼" 섹션ì„, consistent memory ì— ëŒ€í•œ ìžì„¸í•œ ë‚´ìš©ì„
@@ -1918,6 +1931,14 @@ Mandatory ë°°ë¦¬ì–´ë“¤ì€ SMP 시스템ì—ì„œë„ UP 시스템ì—ì„œë„ SMP 효ê³
Persistent memory ì—ì„œì˜ ë¡œë“œë¥¼ 위해선 í˜„ìž¬ì˜ ì½ê¸° 메모리 ë°°ë¦¬ì–´ë¡œë„ ì½ê¸°
순서를 ë³´ìž¥í•˜ëŠ”ë° ì¶©ë¶„í•©ë‹ˆë‹¤.
+ (*) io_stop_wc();
+
+ 쓰기와 ê²°í•©ëœ íŠ¹ì„±ì„ ê°–ëŠ” 메모리 ì•¡ì„¸ìŠ¤ì˜ ê²½ìš° (예: ioremap_wc() ì— ì˜í•´
+ 리턴ë˜ëŠ” 것들), CPU 는 ì•žì˜ ì•¡ì„¸ìŠ¤ë“¤ì´ ë’¤ë”°ë¥´ëŠ” 것들과 병합ë˜ê²Œë” 기다릴
+ 수 있습니다. io_stop_wc() 는 그런 ê¸°ë‹¤ë¦¼ì´ ì„±ëŠ¥ì— ì˜í–¥ì„ ë¼ì¹  수 ìžˆì„ ë•Œ,
+ ì´ ë§¤í¬ë¡œ ì•žì˜ ì“°ê¸°-ê²°í•©ëœ ë©”ëª¨ë¦¬ ì•¡ì„¸ìŠ¤ë“¤ì´ ë§¤í¬ë¡œ ë’¤ì˜ ê²ƒë“¤ê³¼ 병합ë˜ëŠ”
+ ê²ƒì„ ë°©ì§€í•˜ê¸° 위해 ì‚¬ìš©ë  ìˆ˜ 있습니다.
+
=========================
ì•”ë¬µì  ì»¤ë„ ë©”ëª¨ë¦¬ 배리어
=========================
@@ -2827,9 +2848,9 @@ ld.acq 와 stl.rel ì¸ìŠ¤íŠ¸ëŸ­ì…˜ì„ ê°ê° 만들어 ë‚´ë„ë¡ í•©ë‹ˆë‹¤.
DEC Alpha CPU 는 가장 ì™„í™”ëœ ë©”ëª¨ë¦¬ ìˆœì„œì˜ CPU 중 하나입니다. ë¿ë§Œ 아니ë¼,
Alpha CPU ì˜ ì¼ë¶€ ë²„ì „ì€ ë¶„í• ëœ ë°ì´í„° ìºì‹œë¥¼ 가지고 있어서, ì˜ë¯¸ì ìœ¼ë¡œ
관계ë˜ì–´ 있는 ë‘ê°œì˜ ìºì‹œ ë¼ì¸ì´ 서로 다른 ì‹œê°„ì— ì—…ë°ì´íЏ ë˜ëŠ”ê²Œ 가능합니다.
-ì´ê²Œ ë°ì´í„° ì˜ì¡´ì„± 배리어가 ì •ë§ í•„ìš”í•´ì§€ëŠ” 부분ì¸ë°, ë°ì´í„° ì˜ì¡´ì„± 배리어는
-메모리 ì¼ê´€ì„± 시스템과 함께 ë‘ê°œì˜ ìºì‹œë¥¼ ë™ê¸°í™” 시켜서, í¬ì¸í„° 변경과 새로운
-ë°ì´í„°ì˜ ë°œê²¬ì„ ì˜¬ë°”ë¥¸ 순서로 ì¼ì–´ë‚˜ê²Œ 하기 때문입니다.
+ì´ê²Œ 주소 ì˜ì¡´ì„± 배리어가 ì •ë§ í•„ìš”í•´ì§€ëŠ” 부분ì¸ë°, 주소 ì˜ì¡´ì„± 배리어는 메모리
+ì¼ê´€ì„± 시스템과 함께 ë‘ê°œì˜ ìºì‹œë¥¼ ë™ê¸°í™” 시켜서, í¬ì¸í„° 변경과 새로운 ë°ì´í„°ì˜
+ë°œê²¬ì„ ì˜¬ë°”ë¥¸ 순서로 ì¼ì–´ë‚˜ê²Œ 하기 때문입니다.
리눅스 커ë„ì˜ ë©”ëª¨ë¦¬ 배리어 모ë¸ì€ Alpha ì— ê¸°ì´ˆí•´ì„œ ì •ì˜ë˜ì—ˆìŠµë‹ˆë‹¤ë§Œ, v4.15
부터는 Alpha ìš© READ_ONCE() 코드 ë‚´ì— smp_mb() ê°€ 추가ë˜ì–´ì„œ 메모리 모ë¸ë¡œì˜
diff --git a/Documentation/translations/sp_SP/disclaimer-sp.rst b/Documentation/translations/sp_SP/disclaimer-sp.rst
new file mode 100644
index 000000000000..a400034e95f9
--- /dev/null
+++ b/Documentation/translations/sp_SP/disclaimer-sp.rst
@@ -0,0 +1,6 @@
+:orphan:
+
+.. warning::
+ Si tiene alguna duda sobre la exactitud del contenido de esta
+ traducción, la única referencia válida es la documentación oficial en
+ inglés.
diff --git a/Documentation/translations/sp_SP/howto.rst b/Documentation/translations/sp_SP/howto.rst
new file mode 100644
index 000000000000..f9818d687b54
--- /dev/null
+++ b/Documentation/translations/sp_SP/howto.rst
@@ -0,0 +1,617 @@
+.. include:: ./disclaimer-sp.rst
+
+:Original: :ref:`Documentation/process/howto.rst <process_howto>`
+:Translator: Carlos Bilbao <carlos.bilbao@amd.com>
+
+.. _sp_process_howto:
+
+Cómo participar en el desarrollo del kernel de Linux
+====================================================
+
+Este documento es el principal punto de partida. Contiene instrucciones
+sobre cómo convertirse en desarrollador del kernel de Linux y explica cómo
+trabajar con el y en su desarrollo. El documento no tratará ningún aspecto
+técnico relacionado con la programación del kernel, pero le ayudará
+guiándole por el camino correcto.
+
+Si algo en este documento quedara obsoleto, envíe parches al maintainer de
+este archivo, que se encuentra en la parte superior del documento.
+
+Introducción
+------------
+¿De modo que quiere descubrir como convertirse en un/a desarrollador/a del
+kernel de Linux? Tal vez su jefe le haya dicho, "Escriba un driver de
+Linux para este dispositivo." El objetivo de este documento en enseñarle
+todo cuanto necesita para conseguir esto, describiendo el proceso por el
+que debe pasar, y con indicaciones de como trabajar con la comunidad.
+También trata de explicar las razones por las cuales la comunidad trabaja
+de la forma en que lo hace.
+
+El kernel esta principalmente escrito en C, con algunas partes que son
+dependientes de la arquitectura en ensamblador. Un buen conocimiento de C
+es necesario para desarrollar en el kernel. Lenguaje ensamblador (en
+cualquier arquitectura) no es necesario excepto que planee realizar
+desarrollo de bajo nivel para dicha arquitectura. Aunque no es un perfecto
+sustituto para una educación sólida en C y/o años de experiencia, los
+siguientes libros sirven, como mínimo, como referencia:
+
+- "The C Programming Language" de Kernighan e Ritchie [Prentice Hall]
+- "Practical C Programming" de Steve Oualline [O'Reilly]
+- "C: A Reference Manual" de Harbison and Steele [Prentice Hall]
+
+El kernel está escrito usando GNU C y la cadena de herramientas GNU. Si
+bien se adhiere al estándar ISO C89, utiliza una serie de extensiones que
+no aparecen en dicho estándar. El kernel usa un C independiente de entorno,
+sin depender de la biblioteca C estándar, por lo que algunas partes del
+estándar C no son compatibles. Divisiones de long long arbitrarios o
+de coma flotante no son permitidas. En ocasiones, puede ser difícil de
+entender las suposiciones que el kernel hace respecto a la cadena de
+herramientas y las extensiones que usa, y desafortunadamente no hay
+referencia definitiva para estas. Consulte las páginas de información de
+gcc (`info gcc`) para obtener información al respecto.
+
+Recuerde que está tratando de aprender a trabajar con una comunidad de
+desarrollo existente. Es un grupo diverso de personas, con altos estándares
+de código, estilo y procedimiento. Estas normas han sido creadas a lo
+largo del tiempo en función de lo que se ha encontrado que funciona mejor
+para un equipo tan grande y geográficamente disperso. Trate de aprender
+tanto como le sea posible acerca de estos estándares antes de tiempo, ya
+que están bien documentados; no espere que la gente se adapte a usted o a
+la forma de hacer las cosas en su empresa.
+
+Cuestiones legales
+------------------
+El código fuente del kernel de Linux se publica bajo licencia GPL. Por
+favor, revise el archivo COPYING, presente en la carpeta principal del
+código fuente, para detalles de la licencia. Si tiene alguna otra pregunta
+sobre licencias, contacte a un abogado, no pregunte en listas de discusión
+del kernel de Linux. La gente en estas listas no son abogadas, y no debe
+confiar en sus opiniones en materia legal.
+
+Para preguntas y respuestas más frecuentes sobre la licencia GPL, consulte:
+
+ https://www.gnu.org/licenses/gpl-faq.html
+
+Documentación
+--------------
+El código fuente del kernel de Linux tiene una gran variedad de documentos
+que son increíblemente valiosos para aprender a interactuar con la
+comunidad del kernel. Cuando se agregan nuevas funciones al kernel, se
+recomienda que se incluyan nuevos archivos de documentación que expliquen
+cómo usar la función. Cuando un cambio en el kernel hace que la interfaz
+que el kernel expone espacio de usuario cambie, se recomienda que envíe la
+información o un parche en las páginas del manual que expliquen el cambio
+a mtk.manpages@gmail.com, y CC la lista linux-api@vger.kernel.org.
+
+Esta es la lista de archivos que están en el código fuente del kernel y son
+de obligada lectura:
+
+ :ref:`Documentation/admin-guide/README.rst <readme>`
+ Este archivo ofrece una breve descripción del kernel de Linux y
+ describe lo que es necesario hacer para configurar y compilar el
+ kernel. Quienes sean nuevos en el kernel deben comenzar aquí.
+
+ :ref:`Documentation/process/changes.rst <changes>`
+ Este archivo proporciona una lista de los niveles mínimos de varios
+ paquetes que son necesarios para construir y ejecutar el kernel
+ exitosamente.
+
+ :ref:`Documentation/process/coding-style.rst <codingstyle>`
+ Esto describe el estilo de código del kernel de Linux y algunas de los
+ razones detrás de esto. Se espera que todo el código nuevo siga las
+ directrices de este documento. La mayoría de los maintainers solo
+ aceptarán parches si se siguen estas reglas, y muchas personas solo
+ revisan el código si tiene el estilo adecuado.
+
+ :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
+ Este archivo describe en gran detalle cómo crear con éxito y enviar un
+ parche, que incluye (pero no se limita a):
+
+ - Contenidos del correo electrónico (email)
+ - Formato del email
+ - A quien se debe enviar
+
+ Seguir estas reglas no garantiza el éxito (ya que todos los parches son
+ sujetos a escrutinio de contenido y estilo), pero en caso de no seguir
+ dichas reglas, el fracaso es prácticamente garantizado.
+ Otras excelentes descripciones de cómo crear parches correctamente son:
+
+ "The Perfect Patch"
+ https://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+ "Linux kernel patch submission format"
+ https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html
+
+ :ref:`Documentation/process/stable-api-nonsense.rst <stable_api_nonsense>`
+ Este archivo describe la lógica detrás de la decisión consciente de
+ no tener una API estable dentro del kernel, incluidas cosas como:
+
+ - Capas intermedias del subsistema (por compatibilidad?)
+ - Portabilidad de drivers entre sistemas operativos
+ - Mitigar el cambio rápido dentro del árbol de fuentes del kernel (o
+ prevenir cambios rápidos)
+
+ Este documento es crucial para comprender la filosofía del desarrollo
+ de Linux y es muy importante para las personas que se mudan a Linux
+ tras desarrollar otros sistemas operativos.
+
+ :ref:`Documentation/admin-guide/security-bugs.rst <securitybugs>`
+ Si cree que ha encontrado un problema de seguridad en el kernel de
+ Linux, siga los pasos de este documento para ayudar a notificar a los
+ desarrolladores del kernel y ayudar a resolver el problema.
+
+ :ref:`Documentation/process/management-style.rst <managementstyle>`
+ Este documento describe cómo operan los maintainers del kernel de Linux
+ y los valores compartidos detrás de sus metodologías. Esta es una
+ lectura importante para cualquier persona nueva en el desarrollo del
+ kernel (o cualquier persona que simplemente sienta curiosidad por
+ el campo IT), ya que clarifica muchos conceptos erróneos y confusiones
+ comunes sobre el comportamiento único de los maintainers del kernel.
+
+ :ref:`Documentation/process/stable-kernel-rules.rst <stable_kernel_rules>`
+ Este archivo describe las reglas sobre cómo se suceden las versiones
+ del kernel estable, y qué hacer si desea obtener un cambio en una de
+ estas publicaciones.
+
+ :ref:`Documentation/process/kernel-docs.rst <kernel_docs>`
+ Una lista de documentación externa relativa al desarrollo del kernel.
+ Por favor consulte esta lista si no encuentra lo que están buscando
+ dentro de la documentación del kernel.
+
+ :ref:`Documentation/process/applying-patches.rst <applying_patches>`
+ Una buena introducción que describe exactamente qué es un parche y cómo
+ aplicarlo a las diferentes ramas de desarrollo del kernel.
+
+El kernel también tiene una gran cantidad de documentos que pueden ser
+generados automáticamente desde el propio código fuente o desde
+ReStructuredText markups (ReST), como este. Esto incluye un descripción
+completa de la API en el kernel y reglas sobre cómo manejar cerrojos
+(locking) correctamente.
+
+Todos estos documentos se pueden generar como PDF o HTML ejecutando::
+
+ make pdfdocs
+ make htmldocs
+
+respectivamente desde el directorio fuente principal del kernel.
+
+Los documentos que utilizan el markup ReST se generarán en
+Documentation/output. También se pueden generar en formatos LaTeX y ePub
+con::
+
+ make latexdocs
+ make epubdocs
+
+Convertirse en un/a desarrollador/a de kernel
+---------------------------------------------
+
+Si no sabe nada sobre el desarrollo del kernel de Linux, debería consultar
+el proyecto Linux KernelNewbies:
+
+ https://kernelnewbies.org
+
+Consiste en una útil lista de correo donde puede preguntar casi cualquier
+tipo de pregunta básica de desarrollo del kernel (asegúrese de buscar en
+los archivos primero, antes de preguntar algo que ya ha sido respondido en
+el pasado.) También tiene un canal IRC que puede usar para hacer preguntas
+en tiempo real, y una gran cantidad de documentación útil para ir
+aprendiendo sobre el desarrollo del kernel de Linux.
+
+El sitio web tiene información básica sobre la organización del código,
+subsistemas, y proyectos actuales (tanto dentro como fuera del árbol).
+También describe alguna información logística básica, como cómo compilar
+un kernel y aplicar un parche.
+
+Si no sabe por dónde quiere empezar, pero quieres buscar alguna tarea que
+comenzar a hacer para unirse a la comunidad de desarrollo del kernel,
+acuda al proyecto Linux Kernel Janitor:
+
+ https://kernelnewbies.org/KernelJanitors
+
+Es un gran lugar para comenzar. Describe una lista de problemas
+relativamente simples que deben limpiarse y corregirse dentro del código
+fuente del kernel de Linux árbol de fuentes. Trabajando con los
+desarrolladores a cargo de este proyecto, aprenderá los conceptos básicos
+para incluir su parche en el árbol del kernel de Linux, y posiblemente
+descubrir en la dirección en que trabajar a continuación, si no tiene ya
+una idea.
+
+Antes de realizar cualquier modificación real al código del kernel de
+Linux, es imperativo entender cómo funciona el código en cuestión. Para
+este propósito, nada es mejor que leerlo directamente (lo más complicado
+está bien comentado), tal vez incluso con la ayuda de herramientas
+especializadas. Una de esas herramientas que se recomienda especialmente
+es el proyecto Linux Cross-Reference, que es capaz de presentar el código
+fuente en un formato de página web indexada y autorreferencial. Una
+excelente puesta al día del repositorio del código del kernel se puede
+encontrar en:
+
+ https://elixir.bootlin.com/
+
+El proceso de desarrollo
+------------------------
+
+El proceso de desarrollo del kernel de Linux consiste actualmente de
+diferentes "branches" (ramas) con muchos distintos subsistemas específicos
+a cada una de ellas. Las diferentes ramas son:
+
+ - El código principal de Linus (mainline tree)
+ - Varios árboles estables con múltiples major numbers
+ - Subsistemas específicos
+ - linux-next, para integración y testing
+
+Mainline tree (Ãrbol principal)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+El mainline tree es mantenido por Linus Torvalds, y puede encontrarse en
+https://kernel.org o en su repo. El proceso de desarrollo es el siguiente:
+
+ - Tan pronto como se lanza un nuevo kernel, se abre una ventana de dos
+ semanas, durante este período de tiempo, los maintainers pueden enviar
+ grandes modificaciones a Linus, por lo general los parches que ya se
+ han incluido en el linux-next durante unas semanas. La forma preferida
+ de enviar grandes cambios es usando git (la herramienta de
+ administración de código fuente del kernel, más información al respecto
+ en https://git-scm.com/), pero los parches simples también son validos.
+ - Después de dos semanas, se lanza un kernel -rc1 y la atención se centra
+ en hacer el kernel nuevo lo más estable ("solido") posible. La mayoría
+ de los parches en este punto deben arreglar una regresión. Los errores
+ que siempre han existido no son regresiones, por lo tanto, solo envíe
+ este tipo de correcciones si son importantes. Tenga en cuenta que se
+ podría aceptar un controlador (o sistema de archivos) completamente
+ nuevo después de -rc1 porque no hay riesgo de causar regresiones con
+ tal cambio, siempre y cuando el cambio sea autónomo y no afecte áreas
+ fuera del código que se está agregando. git se puede usar para enviar
+ parches a Linus después de que se lance -rc1, pero los parches también
+ deben ser enviado a una lista de correo pública para su revisión.
+ - Se lanza un nuevo -rc cada vez que Linus considera que el árbol git
+ actual esta en un estado razonablemente sano y adecuado para la prueba.
+ La meta es lanzar un nuevo kernel -rc cada semana.
+ - El proceso continúa hasta que el kernel se considera "listo", y esto
+ puede durar alrededor de 6 semanas.
+
+Vale la pena mencionar lo que Andrew Morton escribió en las listas de
+correo del kernel de Linux, sobre lanzamientos del kernel (traducido):
+
+ *"Nadie sabe cuándo se publicara un nuevo kernel, pues esto sucede
+ según el estado de los bugs, no de una cronología preconcebida."*
+
+Varios árboles estables con múltiples major numbers
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Los kernels con versiones de 3 partes son kernels estables. Estos contienen
+correcciones relativamente pequeñas y críticas para problemas de seguridad
+o importantes regresiones descubiertas para una publicación de código.
+Cada lanzamiento en una gran serie estable incrementa la tercera parte de
+la versión número, manteniendo las dos primeras partes iguales.
+
+Esta es la rama recomendada para los usuarios que quieren la versión
+estable más reciente del kernel, y no están interesados en ayudar a probar
+versiones en desarrollo/experimentales.
+
+Los árboles estables son mantenidos por el equipo "estable"
+<stable@vger.kernel.org>, y se liberan (publican) según lo dicten las
+necesidades. El período de liberación normal es de aproximadamente dos
+semanas, pero puede ser más largo si no hay problemas apremiantes. Un
+problema relacionado con la seguridad, en cambio, puede causar un
+lanzamiento casi instantáneamente.
+
+El archivo :ref:`Documentación/proceso/stable-kernel-rules.rst <stable_kernel_rules>`
+en el árbol del kernel documenta qué tipos de cambios son aceptables para
+el árbol estable y cómo funciona el proceso de lanzamiento.
+
+Subsistemas específicos
+~~~~~~~~~~~~~~~~~~~~~~~~
+Los maintainers de los diversos subsistemas del kernel --- y también muchos
+desarrolladores de subsistemas del kernel --- exponen su estado actual de
+desarrollo en repositorios fuente. De esta manera, otros pueden ver lo que
+está sucediendo en las diferentes áreas del kernel. En áreas donde el
+desarrollo es rápido, se le puede pedir a un desarrollador que base sus
+envíos en tal árbol del subsistema del kernel, para evitar conflictos entre
+este y otros trabajos ya en curso.
+
+La mayoría de estos repositorios son árboles git, pero también hay otros
+SCM en uso, o colas de parches que se publican como series quilt. Las
+direcciones de estos repositorios de subsistemas se enumeran en el archivo
+MAINTAINERS. Muchos de estos se pueden ver en https://git.kernel.org/.
+
+Antes de que un parche propuesto se incluya con dicho árbol de subsistemas,
+es sujeto a revisión, que ocurre principalmente en las listas de correo
+(ver la sección respectiva a continuación). Para varios subsistemas del
+kernel, esta revisión se rastrea con la herramienta patchwork. Patchwork
+ofrece una interfaz web que muestra publicaciones de parches, cualquier
+comentario sobre un parche o revisiones a él, y los maintainers pueden
+marcar los parches como en revisión, aceptado, o rechazado. La mayoría de
+estos sitios de trabajo de parches se enumeran en
+
+https://patchwork.kernel.org/.
+
+linux-next, para integración y testing
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Antes de que las actualizaciones de los árboles de subsistemas se combinen
+con el árbol principal, necesitan probar su integración. Para ello, existe
+un repositorio especial de pruebas en el que se encuentran casi todos los
+árboles de subsistema, actualizado casi a diario:
+
+ https://git.kernel.org/?p=linux/kernel/git/next/linux-next.git
+
+De esta manera, linux-next ofrece una perspectiva resumida de lo que se
+espera que entre en el kernel principal en el próximo período de "merge"
+(fusión de código). Los testers aventureros son bienvenidos a probar
+linux-next en ejecución.
+
+Reportar bugs
+-------------
+
+El archivo 'Documentación/admin-guide/reporting-issues.rst' en el
+directorio principal del kernel describe cómo informar un posible bug del
+kernel y detalles sobre qué tipo de información necesitan los
+desarrolladores del kernel para ayudar a rastrear la fuente del problema.
+
+Gestión de informes de bugs
+------------------------------
+
+Una de las mejores formas de poner en práctica sus habilidades de hacking
+es arreglando errores reportados por otras personas. No solo ayudará a
+hacer el kernel más estable, también aprenderá a solucionar problemas del
+mundo real y mejora sus habilidades, y otros desarrolladores se darán
+cuenta de tu presencia. La corrección de errores es una de las mejores
+formas de ganar méritos entre desarrolladores, porque no a muchas personas
+les gusta perder el tiempo arreglando los errores de otras personas.
+
+Para trabajar en informes de errores ya reportados, busque un subsistema
+que le interese. Verifique el archivo MAINTAINERS donde se informan los
+errores de ese subsistema; con frecuencia será una lista de correo, rara
+vez un rastreador de errores (bugtracker). Busque en los archivos de dicho
+lugar para informes recientes y ayude donde lo crea conveniente. También es
+posible que desee revisar https://bugzilla.kernel.org para informes de
+errores; solo un puñado de subsistemas del kernel lo emplean activamente
+para informar o rastrear; sin embargo, todos los errores para todo el kernel
+se archivan allí.
+
+Listas de correo
+-----------------
+
+Como se explica en algunos de los documentos anteriores, la mayoría de
+desarrolladores del kernel participan en la lista de correo del kernel de
+Linux. Detalles sobre cómo para suscribirse y darse de baja de la lista se
+pueden encontrar en:
+
+ http://vger.kernel.org/vger-lists.html#linux-kernel
+
+Existen archivos de la lista de correo en la web en muchos lugares
+distintos. Utilice un motor de búsqueda para encontrar estos archivos. Por
+ejemplo:
+
+ http://dir.gmane.org/gmane.linux.kernel
+
+Es muy recomendable que busque en los archivos sobre el tema que desea
+tratar, antes de publicarlo en la lista. Un montón de cosas ya discutidas
+en detalle solo se registran en los archivos de la lista de correo.
+
+La mayoría de los subsistemas individuales del kernel también tienen sus
+propias lista de correo donde hacen sus esfuerzos de desarrollo. Revise el
+archivo MAINTAINERS para obtener referencias de lo que estas listas para
+los diferentes grupos.
+
+Muchas de las listas están alojadas en kernel.org. La información sobre
+estas puede ser encontrada en:
+
+ http://vger.kernel.org/vger-lists.html
+
+Recuerde mantener buenos hábitos de comportamiento al usar las listas.
+Aunque un poco cursi, la siguiente URL tiene algunas pautas simples para
+interactuar con la lista (o cualquier lista):
+
+ http://www.albion.com/netiquette/
+
+Si varias personas responden a su correo, el CC (lista de destinatarios)
+puede hacerse bastante grande. No elimine a nadie de la lista CC: sin una
+buena razón, o no responda solo a la dirección de la lista. Acostúmbrese
+a recibir correos dos veces, una del remitente y otra de la lista, y no
+intente ajustar esto agregando encabezados de correo astutos, a la gente no
+le gustará.
+
+Recuerde mantener intacto el contexto y la atribución de sus respuestas,
+mantenga las líneas "El hacker John Kernel escribió ...:" en la parte
+superior de su respuesta, y agregue sus declaraciones entre las secciones
+individuales citadas en lugar de escribiendo en la parte superior del
+correo electrónico.
+
+Si incluye parches en su correo, asegúrese de que sean texto legible sin
+formato como se indica en :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`.
+Los desarrolladores del kernel no quieren lidiar con archivos adjuntos o
+parches comprimidos; y pueden querer comentar líneas individuales de su
+parche, que funciona sólo de esa manera. Asegúrese de emplear un programa
+de correo que no altere los espacios ni los tabuladores. Una buena primera
+prueba es enviarse el correo a usted mismo, e intentar aplicar su
+propio parche. Si eso no funciona, arregle su programa de correo o
+reemplace hasta que funcione.
+
+Sobretodo, recuerde de ser respetuoso con otros subscriptores.
+
+Colaborando con la comunidad
+----------------------------
+
+El objetivo de la comunidad del kernel es proporcionar el mejor kernel
+posible. Cuando envíe un parche para su aceptación, se revisará en sus
+méritos técnicos solamente. Entonces, ¿qué deberías ser?
+
+ - críticas
+ - comentarios
+ - peticiones de cambios
+ - peticiones de justificaciones
+ - silencio
+
+Recuerde, esto es parte de introducir su parche en el kernel. Tiene que ser
+capaz de recibir críticas y comentarios sobre sus parches, evaluar
+a nivel técnico y re-elaborar sus parches o proporcionar razonamiento claro
+y conciso de por qué no se deben hacer tales cambios. Si no hay respuestas
+a su publicación, espere unos días e intente de nuevo, a veces las cosas se
+pierden dado el gran volumen.
+
+¿Qué no debería hacer?
+
+ - esperar que su parche se acepte sin preguntas
+ - actuar de forma defensiva
+ - ignorar comentarios
+ - enviar el parche de nuevo, sin haber aplicados los cambios pertinentes
+
+En una comunidad que busca la mejor solución técnica posible, siempre habrá
+diferentes opiniones sobre lo beneficioso que es un parche. Tiene que ser
+cooperativo y estar dispuesto a adaptar su idea para que encaje dentro
+del kernel, o al menos esté dispuesto a demostrar que su idea vale la pena.
+Recuerde, estar equivocado es aceptable siempre y cuando estés dispuesto a
+trabajar hacia una solución que sea correcta.
+
+Es normal que las respuestas a su primer parche sean simplemente una lista
+de una docena de cosas que debe corregir. Esto **no** implica que su
+parche no será aceptado, y **no** es personal. Simplemente corrija todos
+los problemas planteados en su parche, y envié otra vez.
+
+Diferencias entre la comunidad kernel y las estructuras corporativas
+--------------------------------------------------------------------
+
+La comunidad del kernel funciona de manera diferente a la mayoría de los
+entornos de desarrollo tradicionales en empresas. Aquí hay una lista de
+cosas que puede intentar hacer para evitar problemas:
+
+ Cosas buenas que decir respecto a los cambios propuestos:
+
+ - "Esto arregla múltiples problemas."
+ - "Esto elimina 2000 lineas de código."
+ - "Aquí hay un parche que explica lo que intento describir."
+ - "Lo he testeado en 5 arquitecturas distintas..."
+ - "Aquí hay una serie de parches menores que..."
+ - "Esto mejora el rendimiento en maquinas típicas..."
+
+ Cosas negativas que debe evitar decir:
+
+ - "Lo hicimos así en AIX/ptx/Solaris, de modo que debe ser bueno..."
+ - "Llevo haciendo esto 20 años, de modo que..."
+ - "Esto lo necesita mi empresa para ganar dinero"
+ - "Esto es para la linea de nuestros productos Enterprise"
+ - "Aquí esta el documento de 1000 paginas describiendo mi idea"
+ - "Llevo 6 meses trabajando en esto..."
+ - "Aquí esta un parche de 5000 lineas que..."
+ - "He rescrito todo el desastre actual, y aquí esta..."
+ - "Tengo un deadline, y este parche debe aplicarse ahora."
+
+Otra forma en que la comunidad del kernel es diferente a la mayoría de los
+entornos de trabajo tradicionales en ingeniería de software, es la
+naturaleza sin rostro de interacción. Una de las ventajas de utilizar el
+correo electrónico y el IRC como formas principales de comunicación es la
+no discriminación por motivos de género o raza. El entorno de trabajo del
+kernel de Linux acepta a mujeres y minorías porque todo lo que eres es una
+dirección de correo electrónico. El aspecto internacional también ayuda a
+nivelar el campo de juego porque no puede adivinar el género basado en
+el nombre de una persona. Un hombre puede llamarse Andrea y una mujer puede
+llamarse Pat. La mayoría de las mujeres que han trabajado en el kernel de
+Linux y han expresado una opinión han tenido experiencias positivas.
+
+La barrera del idioma puede causar problemas a algunas personas que no se
+sientes cómodas con el inglés. Un buen dominio del idioma puede ser
+necesario para transmitir ideas correctamente en las listas de correo, por
+lo que le recomendamos que revise sus correos electrónicos para asegurarse
+de que tengan sentido en inglés antes de enviarlos.
+
+Divida sus cambios
+---------------------
+
+La comunidad del kernel de Linux no acepta con gusto grandes fragmentos de
+código, sobretodo a la vez. Los cambios deben introducirse correctamente,
+discutidos y divididos en pequeñas porciones individuales. Esto es casi
+exactamente lo contrario de lo que las empresas están acostumbradas a hacer.
+Su propuesta también debe introducirse muy temprano en el proceso de
+desarrollo, de modo que pueda recibir comentarios sobre lo que está
+haciendo. También deje que la comunidad sienta que está trabajando con
+ellos, y no simplemente usándolos como un vertedero para su función. Sin
+embargo, no envíe 50 correos electrónicos a una vez a una lista de correo,
+su serie de parches debe casi siempre ser más pequeña que eso.
+
+Las razones para dividir las cosas son las siguientes:
+
+1) Los cambios pequeños aumentan la probabilidad de que sus parches sean
+ aplicados, ya que no requieren mucho tiempo o esfuerzo para verificar su
+ exactitud. Un parche de 5 líneas puede ser aplicado por un maintainer
+ con apenas una segunda mirada. Sin embargo, un parche de 500 líneas
+ puede tardar horas en ser revisado en términos de corrección (el tiempo
+ que toma es exponencialmente proporcional al tamaño del parche, o algo
+ así).
+
+ Los parches pequeños también facilitan la depuración cuando algo falla.
+ Es mucho más fácil retirar los parches uno por uno que diseccionar un
+ parche muy grande después de haber sido aplicado (y roto alguna cosa).
+
+2) Es importante no solo enviar pequeños parches, sino también reescribir
+ y simplificar (o simplemente reordenar) los parches antes de enviarlos.
+
+Esta es una analogía del desarrollador del kernel Al Viro (traducida):
+
+ *"Piense en un maestro que califica la tarea de un estudiante de
+ matemáticas. El maestro no quiere ver los intentos y errores del
+ estudiante antes de que se les ocurriera la solución. Quiere ver la
+ respuesta más limpia y elegante. Un buen estudiante lo sabe, y nunca
+ presentaría su trabajo intermedio antes de tener la solución final.*
+
+ *Lo mismo ocurre con el desarrollo del kernel. Los maintainers y
+ revisores no quieren ver el proceso de pensamiento detrás de la solución
+ al problema que se está resolviendo. Quieren ver un solución simple y
+ elegante."*
+
+Puede resultar un reto mantener el equilibrio entre presentar una solución
+elegante y trabajar junto a la comunidad, discutiendo su trabajo inacabado.
+Por lo tanto, es bueno comenzar temprano en el proceso para obtener
+"feedback" y mejorar su trabajo, pero también mantenga sus cambios en
+pequeños trozos que pueden ser aceptados, incluso cuando toda su labor no
+está listo para inclusión en un momento dado.
+
+También tenga en cuenta que no es aceptable enviar parches para su
+inclusión que están sin terminar y serán "arreglados más tarde".
+
+Justifique sus cambios
+----------------------
+
+Además de dividir sus parches, es muy importante que deje a la comunidad de
+Linux sabe por qué deberían agregar este cambio. Nuevas características
+debe justificarse como necesarias y útiles.
+
+Documente sus cambios
+---------------------
+
+Cuando envíe sus parches, preste especial atención a lo que dice en el
+texto de su correo electrónico. Esta información se convertirá en el
+ChangeLog del parche, y se conservará para que todos la vean, todo el
+tiempo. Debe describir el parche por completo y contener:
+
+ - por qué los cambios son necesarios
+ - el diseño general de su propuesta
+ - detalles de implementación
+ - resultados de sus experimentos
+
+Para obtener más detalles sobre cómo debería quedar todo esto, consulte la
+sección ChangeLog del documento:
+
+ "The Perfect Patch"
+ https://www.ozlabs.org/~akpm/stuff/tpp.txt
+
+Todas estas cuestiones son a veces son muy difíciles de conseguir. Puede
+llevar años perfeccionar estas prácticas (si es que lo hace). Es un proceso
+continuo de mejora que requiere mucha paciencia y determinación. Pero no se
+rinda, es posible. Muchos lo han hecho antes, y cada uno tuvo que comenzar
+exactamente donde está usted ahora.
+
+----------
+
+Gracias a Paolo Ciarrocchi que permitió que la sección "Development Process"
+se basara en el texto que había escrito (https://lwn.net/Articles/94386/),
+y a Randy Dunlap y Gerrit Huizenga por algunas de la lista de cosas que
+debes y no debes decir. También gracias a Pat Mochel, Hanna Linder, Randy
+Dunlap, Kay Sievers, Vojtech Pavlik, Jan Kara, Josh Boyer, Kees Cook,
+Andrew Morton, Andi Kleen, Vadim Lobanov, Jesper Juhl, Adrian Bunk,
+Keri Harris, Frans Pop, David A. Wheeler, Junio Hamano, Michael Kerrisk y
+Alex Shepard por su revisión, comentarios y contribuciones. Sin su ayuda,
+este documento no hubiera sido posible.
+
+Maintainer: Greg Kroah-Hartman <greg@kroah.com>
diff --git a/Documentation/translations/sp_SP/index.rst b/Documentation/translations/sp_SP/index.rst
new file mode 100644
index 000000000000..5c2a2131524b
--- /dev/null
+++ b/Documentation/translations/sp_SP/index.rst
@@ -0,0 +1,81 @@
+
+=====================
+Traducción al español
+=====================
+
+.. raw:: latex
+
+ \kerneldocCJKoff
+
+:maintainer: Carlos Bilbao <carlos.bilbao@amd.com>
+
+.. _sp_disclaimer:
+
+Advertencia
+===========
+
+El objetivo de esta traducción es facilitar la lectura y comprensión para
+aquellos que no entiendan inglés o duden de sus interpretaciones, o
+simplemente para aquellos que prefieran leer en el idioma español. Sin
+embargo, tenga en cuenta que la *única* documentación oficial es la que
+está en inglés: :ref:`linux_doc`
+
+La propagación simultánea de la traducción de una modificación en
+:ref:`linux_doc` es altamente improbable. Los maintainers y colaboradores
+de la traducción intentan mantener sus traducciones al día, en tanto les
+es posible. Por tanto, no existe ninguna garantía de que una traducción
+esté actualizada con las últimas modificaciones. Si lo que lee en una
+traducción no se corresponde con lo que ve en el código fuente, informe
+al maintainer de la traducción y, si puede, consulte la documentación en
+inglés.
+
+Una traducción no es una * bifurcación * de la documentación oficial, por
+lo que los usuarios no encontrarán aquí ninguna información que no sea la
+versión oficial. Cualquier adición, supresión o modificación de los
+contenidos deberá ser realizada anteriormente en los documentos en inglés.
+Posteriormente, y cuando sea posible, dicho cambio debería aplicarse
+también a las traducciones. Los maintainers de las traducciones aceptan
+contribuciones que son puramente de interés relativo a la traducción (por
+ejemplo, nuevas traducciones, actualizaciones, correcciones, etc.).
+
+Las traducciones tratan de ser lo más precisas posible pero no es posible
+convertir directamente un idioma a otro. Cada idioma tiene su propia
+gramática, y una cultura tras ella, por lo tanto, la traducción de una
+oración al inglés se podría modificar para adaptarla al español. Por esta
+razón, cuando lea esta traducción, puede encontrar algunas diferencias en
+la forma, pero todavía transmiten el mensaje original. A pesar de la gran
+difusión del inglés en el idioma hablado, cuando sea posible, expresiones
+en inglés serán reemplazadas por las palabras correspondientes en español.
+
+Si necesita ayuda para comunicarse con la comunidad de Linux pero no se
+siente cómodo escribiendo en inglés, puede pedir ayuda al maintainer para
+obtener una traducción.
+
+Muchos países hablan español, cada uno con su propia cultura, expresiones,
+y diferencias gramaticales en ocasiones significativas. Las traducciones de
+los maintainers pueden utilizar el español con el que dichos maintainers se
+sientan más cómodos. En principio, estas pequeñas diferencias no deberían
+suponer una gran barrera para hablantes de distintas versiones del español,
+pero en caso de duda se puede consultar a los maintainers.
+
+La documentación del kernel Linux
+=================================
+
+Este es el nivel superior de la documentación del kernel en idioma español.
+La traducción es incompleta, y podría encontrar advertencias que indiquen
+la falta de una traducción o de un grupo de traducciones.
+
+En términos más generales, la documentación, como el kernel mismo, están en
+constante desarrollo. Las mejoras en la documentación siempre son
+bienvenidas; de modo que, si desea ayudar, únase a la lista de correo
+linux-doc en vger.kernel.org.
+
+Traducciones al español
+=======================
+
+.. toctree::
+ :maxdepth: 1
+
+ howto
+ process/index
+ wrappers/memory-barriers
diff --git a/Documentation/translations/sp_SP/memory-barriers.txt b/Documentation/translations/sp_SP/memory-barriers.txt
new file mode 100644
index 000000000000..f62bd797216d
--- /dev/null
+++ b/Documentation/translations/sp_SP/memory-barriers.txt
@@ -0,0 +1,3134 @@
+NOTE:
+This is a version of Documentation/memory-barriers.txt translated into
+Spanish by Carlos Bilbao <carlos.bilbao@amd.com>. If you find any
+difference between this document and the original file or a problem with
+the translation, please contact the maintainer of this file. Please also
+note that the purpose of this file is to be easier to read for non English
+(read: Spanish) speakers and is not intended as a fork. So if you have any
+comments or updates for this file please update the original English file
+first. The English version is definitive, and readers should look there if
+they have any doubt.
+
+ ======================================
+ BARRERAS DE MEMORIA EN EL KERNEL LINUX
+ ======================================
+
+Documento original: David Howells <dhowells@redhat.com>
+ Paul E. McKenney <paulmck@linux.ibm.com>
+ Will Deacon <will.deacon@arm.com>
+ Peter Zijlstra <peterz@infradead.org>
+
+Traducido por: Carlos Bilbao <carlos.bilbao@amd.com>
+Nota: Si tiene alguna duda sobre la exactitud del contenido de esta
+traducción, la única referencia válida es la documentación oficial en
+inglés.
+
+===========
+ADVERTENCIA
+===========
+
+Este documento no es una especificación; es intencionalmente (por motivos
+de brevedad) y sin querer (por ser humanos) incompleta. Este documento
+pretende ser una guía para usar las diversas barreras de memoria
+proporcionadas por Linux, pero ante cualquier duda (y hay muchas) por favor
+pregunte. Algunas dudas pueden ser resueltas refiriéndose al modelo de
+consistencia de memoria formal y documentación en tools/memory-model/. Sin
+embargo, incluso este modelo debe ser visto como la opinión colectiva de
+sus maintainers en lugar de que como un oráculo infalible.
+
+De nuevo, este documento no es una especificación de lo que Linux espera
+del hardware.
+
+El propósito de este documento es doble:
+
+ (1) especificar la funcionalidad mínima en la que se puede confiar para
+ cualquier barrera en concreto, y
+
+ (2) proporcionar una guía sobre cómo utilizar las barreras disponibles.
+
+Tenga en cuenta que una arquitectura puede proporcionar más que el
+requisito mínimo para cualquier barrera en particular, pero si la
+arquitectura proporciona menos de eso, dicha arquitectura es incorrecta.
+
+Tenga en cuenta también que es posible que una barrera no valga (sea no-op)
+para alguna arquitectura porque por la forma en que funcione dicha
+arquitectura, la barrera explícita resulte innecesaria en ese caso.
+
+==========
+CONTENIDOS
+==========
+
+ (*) Modelo abstracto de acceso a memoria.
+
+ - Operaciones del dispositivo.
+ - Garantías.
+
+ (*) ¿Qué son las barreras de memoria?
+
+ - Variedades de barrera de memoria.
+ - ¿Qué no se puede asumir sobre las barreras de memoria?
+ - Barreras de dirección-dependencia (históricas).
+ - Dependencias de control.
+ - Emparejamiento de barreras smp.
+ - Ejemplos de secuencias de barrera de memoria.
+ - Barreras de memoria de lectura frente a especulación de carga.
+ - Atomicidad multicopia.
+
+ (*) Barreras explícitas del kernel.
+
+ - Barrera del compilador.
+ - Barreras de memoria de la CPU.
+
+ (*) Barreras de memoria implícitas del kernel.
+
+ - Funciones de adquisición de cerrojo.
+ - Funciones de desactivación de interrupciones.
+ - Funciones de dormir y despertar.
+ - Funciones varias.
+
+ (*) Efectos de barrera adquiriendo intra-CPU.
+
+ - Adquisición vs accesos a memoria.
+
+ (*) ¿Dónde se necesitan barreras de memoria?
+
+ - Interacción entre procesadores.
+ - Operaciones atómicas.
+ - Acceso a dispositivos.
+ - Interrupciones.
+
+ (*) Efectos de barrera de E/S del kernel.
+
+ (*) Modelo de orden mínimo de ejecución asumido.
+
+ (*) Efectos de la memoria caché de la CPU.
+
+ - Coherencia de caché.
+ - Coherencia de caché frente a DMA.
+ - Coherencia de caché frente a MMIO.
+
+ (*) Cosas que hacen las CPU.
+
+ - Y luego está el Alfa.
+ - Guests de máquinas virtuales.
+
+ (*) Ejemplos de usos.
+
+ - Buffers circulares.
+
+ (*) Referencias.
+
+
+====================================
+MODELO ABSTRACTO DE ACCESO A MEMORIA
+====================================
+
+Considere el siguiente modelo abstracto del sistema:
+
+ : :
+ : :
+ : :
+ +-------+ : +--------+ : +-------+
+ | | : | | : | |
+ | | : | | : | |
+ | CPU 1 |<----->| Memoria|<----->| CPU 2 |
+ | | : | | : | |
+ | | : | | : | |
+ +-------+ : +--------+ : +-------+
+ ^ : ^ : ^
+ | : | : |
+ | : | : |
+ | : v : |
+ | : +--------+ : |
+ | : | | : |
+ | : | Disposi| : |
+ +---------->| tivo |<----------+
+ : | | :
+ : | | :
+ : +--------+ :
+ : :
+
+Cada CPU ejecuta un programa que genera operaciones de acceso a la memoria.
+En la CPU abstracta, el orden de las operaciones de memoria es muy
+relajado, y una CPU en realidad puede realizar las operaciones de memoria
+en el orden que desee, siempre que la causalidad del programa parezca
+mantenerse. De manera similar, el compilador también puede organizar las
+instrucciones que emite en el orden que quiera, siempre que no afecte al
+funcionamiento aparente del programa.
+
+Entonces, en el diagrama anterior, los efectos de las operaciones de
+memoria realizadas por un CPU son percibidos por el resto del sistema a
+medida que las operaciones cruzan la interfaz entre la CPU y el resto del
+sistema (las líneas discontinuas a puntos).
+
+Por ejemplo, considere la siguiente secuencia de eventos:
+
+ CPU 1 CPU 2
+ =============== ===============
+ { A == 1; B == 2 }
+ A = 3; x = B;
+ B = 4; y = A;
+
+El conjunto de accesos visto por el sistema de memoria en el medio se puede
+organizar en 24 combinaciones diferentes (donde LOAD es cargar y STORE es
+guardar):
+
+STORE A=3, STORE B=4, y=LOAD A->3, x=LOAD B->4
+STORE A=3, STORE B=4, x=LOAD B->4, y=LOAD A->3
+STORE A=3, y=LOAD A->3, STORE B=4, x=LOAD B->4
+STORE A=3, y=LOAD A->3, x=LOAD B->2, STORE B=4
+STORE A=3, x=LOAD B->2, STORE B=4, y=LOAD A->3
+STORE A=3, x=LOAD B->2, y=LOAD A->3, STORE B=4
+STORE B=4, STORE A=3, y=LOAD A->3, x=LOAD B->4
+STORE B=4, ...
+...
+
+y por lo tanto puede resultar en cuatro combinaciones diferentes de
+valores:
+
+x == 2, y == 1
+x == 2, y == 3
+x == 4, y == 1
+x == 4, y == 3
+
+Además, los stores asignados por una CPU al sistema de memoria pueden no
+ser percibidos por los loads realizados por otra CPU en el mismo orden en
+que fueron realizados.
+
+Como otro ejemplo, considere esta secuencia de eventos:
+
+ CPU 1 CPU 2
+ =============== ===============
+ { A == 1, B == 2, C == 3, P == &A, Q == &C }
+ B = 4; Q = P;
+ P = &B; D = *Q;
+
+Aquí hay una dependencia obvia de la dirección, ya que el valor cargado en
+D depende en la dirección recuperada de P por la CPU 2. Al final de la
+secuencia, cualquiera de los siguientes resultados son posibles:
+
+ (Q == &A) y (D == 1)
+ (Q == &B) y (D == 2)
+ (Q == &B) y (D == 4)
+
+Tenga en cuenta que la CPU 2 nunca intentará cargar C en D porque la CPU
+cargará P en Q antes de emitir la carga de *Q.
+
+OPERACIONES DEL DISPOSITIVO
+---------------------------
+
+Algunos dispositivos presentan sus interfaces de control como colecciones
+de ubicaciones de memoria, pero el orden en que se accede a los registros
+de control es muy importante. Por ejemplo, imagine una tarjeta ethernet con
+un conjunto de registros a los que se accede a través de un registro de
+puerto de dirección (A) y un registro de datos del puerto (D). Para leer el
+registro interno 5, el siguiente código podría entonces ser usado:
+
+ *A = 5;
+ x = *D;
+
+pero esto podría aparecer como cualquiera de las siguientes dos secuencias:
+
+ STORE *A = 5, x = LOAD *D
+ x = LOAD *D, STORE *A = 5
+
+el segundo de las cuales casi con certeza resultará en mal funcionamiento,
+ya que se estableció la dirección _después_ de intentar leer el registro.
+
+
+GARANTÃAS
+---------
+
+Hay algunas garantías mínimas que se pueden esperar de una CPU:
+
+ (*) En cualquier CPU dada, los accesos a la memoria dependiente se
+ emitirán en orden, con respeto a sí mismo. Esto significa que para:
+
+ Q = READ_ONCE(P); D = READ_ONCE(*Q);
+
+ donde READ_ONCE() es LEER_UNA_VEZ(), la CPU emitirá las siguientes
+ operaciones de memoria:
+
+ Q = LOAD P, D = LOAD *Q
+
+ y siempre en ese orden. Sin embargo, en DEC Alpha, READ_ONCE() también
+ emite una instrucción de barrera de memoria, de modo que una CPU DEC
+ Alpha, sin embargo emite las siguientes operaciones de memoria:
+
+ Q = LOAD P, MEMORY_BARRIER, D = LOAD *Q, MEMORY_BARRIER
+
+ Ya sea en DEC Alpha o no, READ_ONCE() también evita que el compilador
+ haga cosas inapropiadas.
+
+ (*) Los loads y stores superpuestos dentro de una CPU en particular
+ parecerán ser ordenados dentro de esa CPU. Esto significa que para:
+
+ a = READ_ONCE(*X); WRITE_ONCE(*X, b);
+
+ donde WRITE_ONCE() es ESCRIBIR_UNA_VEZ(), la CPU solo emitirá la
+ siguiente secuencia de operaciones de memoria:
+
+ a = LOAD *X, STORE *X = b
+
+ Y para:
+
+ WRITE_ONCE(*X, c); d = READ_ONCE(*X);
+
+ la CPU solo emitirá:
+
+ STORE *X = c, d = LOAD *X
+
+ (Los loads y stores se superponen si están destinados a piezas
+ superpuestas de memoria).
+
+Y hay una serie de cosas que _deben_ o _no_ deben asumirse:
+
+ (*) _No_debe_ asumirse que el compilador hará lo que usted quiera
+ con referencias de memoria que no están protegidas por READ_ONCE() y
+ WRITE ONCE(). Sin ellos, el compilador tiene derecho a hacer todo tipo
+ de transformaciones "creativas", que se tratan en la sección BARRERA
+ DEL COMPILADOR.
+
+ (*) _No_debe_ suponerse que se emitirán loads y stores independientes
+ en el orden dado. Esto significa que para:
+
+ X = *A; Y = *B; *D = Z;
+
+ podemos obtener cualquiera de las siguientes secuencias:
+
+ X = LOAD *A, Y = LOAD *B, STORE *D = Z
+ X = LOAD *A, STORE *D = Z, Y = LOAD *B
+ Y = LOAD *B, X = LOAD *A, STORE *D = Z
+ Y = LOAD *B, STORE *D = Z, X = LOAD *A
+ STORE *D = Z, X = LOAD *A, Y = LOAD *B
+ STORE *D = Z, Y = LOAD *B, X = LOAD *A
+
+ (*) Se _debe_ suponer que los accesos de memoria superpuestos pueden
+ fusionarse o ser descartados. Esto significa que para:
+
+ X = *A; Y = *(A + 4);
+
+ podemos obtener cualquiera de las siguientes secuencias:
+
+X = LOAD *A; Y = LOAD *(A + 4);
+Y = LOAD *(A + 4); X = LOAD *A;
+{X, Y} = LOAD {*A, *(A + 4) };
+
+ Y para:
+
+*A = X; *(A + 4) = Y;
+
+ podemos obtener cualquiera de:
+
+STORE *A = X; STORE *(A + 4) = Y;
+STORE *(A + 4) = Y; STORE *A = X;
+STORE {*A, *(A + 4) } = {X, Y};
+
+Y hay anti-garantías:
+
+(*) Estas garantías no se aplican a los campos de bits, porque los
+ compiladores a menudo generan código para modificarlos usando
+ secuencias de lectura-modificación-escritura no atómica. No intente
+ utilizar campos de bits para sincronizar algoritmos paralelos.
+
+(*) Incluso en los casos en que los campos de bits están protegidos por
+ cerrojos (o "cerrojos", o "locks"), todos los componentes en un campo
+ de bits dado deben estar protegidos por un candado. Si dos campos en un
+ campo de bits dado están protegidos por diferentes locks, las
+ secuencias de lectura-modificación-escritura no atómicas del lock
+ pueden causar una actualización a una campo para corromper el valor de
+ un campo adyacente.
+
+(*) Estas garantías se aplican solo a escalares correctamente alineados y
+ dimensionados. De "tamaño adecuado" significa actualmente variables que
+ son del mismo tamaño que "char", "short", "int" y "long".
+ "Adecuadamente alineado" significa la alineación natural, por lo tanto,
+ no hay restricciones para "char", alineación de dos bytes para "short",
+ alineación de cuatro bytes para "int", y alineación de cuatro u ocho
+ bytes para "long", en sistemas de 32 y 64 bits, respectivamente. Tenga
+ en cuenta que estos garantías se introdujeron en el estándar C11, así
+ que tenga cuidado cuando utilice compiladores anteriores a C11 (por
+ ejemplo, gcc 4.6). La parte de la norma que contiene esta garantía es
+ la Sección 3.14, que define "ubicación de memoria" de la siguiente
+ manera:
+
+ ubicación de memoria
+ ya sea un objeto de tipo escalar, o una secuencia máxima
+ de campos de bits adyacentes, todos con ancho distinto de cero
+
+ NOTE 1: Dos hilos de ejecución pueden actualizar y acceder
+ ubicaciones de memoria separadas sin interferir entre
+ ellos.
+
+ NOTE 2: Un campo de bits y un miembro adyacente que no es un campo de
+ bits están en ubicaciones de memoria separadas. Lo mismo sucede con
+ dos campos de bits, si uno se declara dentro de un declaración de
+ estructura anidada y el otro no, o si las dos están separados por una
+ declaración de campo de bits de longitud cero, o si están separados por
+ un miembro no declarado como campo de bits. No es seguro actualizar
+ simultáneamente dos campos de bits en la misma estructura si entre
+ todos los miembros declarados también hay campos de bits, sin importar
+ cuál resulta ser el tamaño de estos campos de bits intermedios.
+
+
+==================================
+¿QUÉ SON LAS BARRERAS DE MEMORIA?
+==================================
+
+Como se puede leer arriba, las operaciones independientes de memoria se
+realizan de manera efectiva en orden aleatorio, pero esto puede ser un
+problema para la interacción CPU-CPU y para la E/S ("I/O"). Lo que se
+requiere es alguna forma de intervenir para instruir al compilador y al
+CPU para restringir el orden.
+
+Las barreras de memoria son este tipo de intervenciones. Imponen una
+percepción de orden parcial, sobre las operaciones de memoria a ambos lados
+de la barrera.
+
+Tal cumplimiento es importante porque las CPUs y otros dispositivos en un
+sistema pueden usar una variedad de trucos para mejorar el rendimiento,
+incluido el reordenamiento, diferimiento y combinación de operaciones de
+memoria; cargas especulativas; predicción de "branches" especulativos y
+varios tipos de almacenamiento en caché. Las barreras de memoria se
+utilizan para anular o suprimir estos trucos, permitiendo que el código
+controle sensatamente la interacción de múltiples CPU y/o dispositivos.
+
+
+VARIEDADES DE BARRERA DE MEMORIA
+---------------------------------
+
+Las barreras de memoria vienen en cuatro variedades básicas:
+
+ (1) Barreras de memoria al escribir o almacenar (Write or store memory
+ barriers).
+
+ Una barrera de memoria de escritura garantiza que todas las
+ operaciones de STORE especificadas antes de que la barrera aparezca
+ suceden antes de todas las operaciones STORE especificadas después
+ de la barrera, con respecto a los otros componentes del sistema.
+
+ Una barrera de escritura es un orden parcial solo en los stores; No
+ es requerido que tenga ningún efecto sobre los loads.
+
+ Se puede considerar que una CPU envía una secuencia de operaciones de
+ store al sistema de memoria a medida que pasa el tiempo. Todos los
+ stores _antes_ de una barrera de escritura ocurrirán _antes_ de todos
+ los stores después de la barrera de escritura.
+
+ [!] Tenga en cuenta que las barreras de escritura normalmente deben
+ combinarse con read o barreras de address-dependency barriers
+ (dependencia de dirección); consulte la subsección
+ "Emparejamiento de barreras smp".
+
+
+ (2) Barrera de dependencia de dirección (histórico).
+
+ Una barrera de dependencia de dirección es una forma más débil de
+ barrera de lectura. En el caso de que se realicen dos loads de manera
+ que la segunda dependa del resultado de la primera (por ejemplo: el
+ primer load recupera la dirección a la que se dirigirá el segundo
+ load), una barrera de dependencia de dirección sería necesaria para
+ asegurarse de que el objetivo de la segunda carga esté actualizado
+ después de acceder a la dirección obtenida por la primera carga.
+
+ Una barrera de dependencia de direcciones es una ordenación parcial en
+ laods de direcciones interdependientes; no se requiere que tenga
+ ningún efecto en los stores, ya sean cargas de memoria o cargas
+ de memoria superpuestas.
+
+ Como se mencionó en (1), las otras CPU en el sistema pueden verse como
+ secuencias de stores en el sistema de memoria que la considerada CPU
+ puede percibir. Una barrera de dependencia de dirección emitida por
+ la CPU en cuestión garantiza que para cualquier carga que la preceda,
+ si esa carga toca alguna secuencia de stores de otra CPU, entonces
+ en el momento en que la barrera se complete, los efectos de todos los
+ stores antes del cambio del load serán perceptibles por cualquier
+ carga emitida después la barrera de la dependencia de la dirección.
+
+ Consulte la subsección "Ejemplos de secuencias de barrera de memoria"
+ para ver los diagramas mostrando las restricciones de orden.
+
+ [!] Tenga en cuenta que la primera carga realmente tiene que tener una
+ dependencia de _dirección_ y no es una dependencia de control. Si la
+ dirección para la segunda carga depende de la primera carga, pero la
+ dependencia es a través de un condicional en lugar de -en realidad-
+ cargando la dirección en sí, entonces es una dependencia de _control_
+ y se requiere una barrera de lectura completa o superior. Consulte la
+ subsección "Dependencias de control" para más información.
+
+ [!] Tenga en cuenta que las barreras de dependencia de dirección
+ normalmente deben combinarse con barreras de escritura; consulte la
+ subsección "Emparejamiento de barreras smp".
+
+ [!] Desde el kernel v5.9, se eliminó la API del kernel para barreras
+ de memoria de direcciones explícitas. Hoy en día, las APIs para marcar
+ cargas de variables compartidas, como READ_ONCE() y rcu_dereference(),
+ proporcionan barreras de dependencia de dirección implícitas.
+
+ (3) Barreras de memoria al leer o cargar (Read or load memory
+ barriers).
+
+ Una barrera de lectura es una barrera de dependencia de direcciones,
+ más una garantía de que todas las operaciones de LOAD especificadas
+ antes de la barrera parecerán ocurrir antes de todas las operaciones
+ de LOAD especificadas después de la barrera con respecto a los demás
+ componentes del sistema.
+
+ Una barrera de lectura es un orden parcial solo en cargas; no es
+ necesario que tenga ningún efecto en los stores.
+
+ Las barreras de memoria de lectura implican barreras de dependencia de
+ direcciones, y por tanto puede sustituirlas por estas.
+
+ [!] Tenga en mente que las barreras de lectura normalmente deben
+ combinarse con barreras de escritura; consulte la subsección
+ "Emparejamiento de barreras smp".
+
+ (4) Barreras de memoria generales
+
+ Una barrera de memoria general proporciona la garantía de que todas
+ las operaciones LOAD y STORE especificadas antes de que la barrera
+ aparezca suceden antes de que todas las operaciones LOAD y STORE
+ especificadas después de la barrera con respecto a los demás
+ componentes del sistema.
+
+ Una barrera de memoria general es un orden parcial tanto en
+ operaciones de carga como de almacenamiento.
+
+ Las barreras de memoria generales implican barreras de memoria tanto
+ de lectura como de escritura, de modo que pueden sustituir a
+ cualquiera.
+
+Y un par de variedades implícitas:
+
+ (5) ACQUIRE (de adquisición).
+
+ Esto actúa como una barrera permeable unidireccional. Garantiza que
+ toda las operaciones de memoria después de la operación ACQUIRE
+ parezcan suceder después de la ACQUIRE con respecto a los demás
+ componentes del sistema. Las operaciones ACQUIRE incluyen operaciones
+ LOCK y smp_load_acquire(), y operaciones smp_cond_load_acquire().
+
+ Las operaciones de memoria que ocurren antes de una operación ACQUIRE
+ pueden parecer suceder después de que se complete.
+
+ Una operación ACQUIRE casi siempre debe estar emparejada con una
+ operación RELEASE (de liberación).
+
+
+ (6) Operaciones RELEASE (de liberación).
+
+ Esto también actúa como una barrera permeable unidireccional.
+ Garantiza que todas las operaciones de memoria antes de la operación
+ RELEASE parecerán ocurrir antes de la operación RELEASE con respecto a
+ los demás componentes del sistema. Las operaciones de RELEASE incluyen
+ operaciones de UNLOCK y operaciones smp_store_release().
+
+ Las operaciones de memoria que ocurren después de una operación
+ RELEASE pueden parecer suceder antes de que se complete.
+
+ El uso de las operaciones ACQUIRE y RELEASE generalmente excluye la
+ necesidad de otros tipos de barrera de memoria. Además, un par
+ RELEASE+ACQUIRE NO garantiza actuar como una barrera de memoria
+ completa. Sin embargo, después de un ACQUIRE de una variable dada,
+ todos los accesos a la memoria que preceden a cualquier anterior
+ RELEASE en esa misma variable están garantizados como visibles. En
+ otras palabras, dentro de la sección crítica de una variable dada,
+ todos los accesos de todas las secciones críticas anteriores para esa
+ variable habrán terminado de forma garantizada.
+
+ Esto significa que ACQUIRE actúa como una operación mínima de
+ "adquisición" y RELEASE actúa como una operación mínima de
+ "liberación".
+
+Un subconjunto de las operaciones atómicas descritas en atomic_t.txt
+contiene variantes de ACQUIRE y RELEASE, además de definiciones
+completamente ordenadas o relajadas (sin barrera semántica). Para
+composiciones atómicas que realizan tanto un load como store, la semántica
+ACQUIRE se aplica solo a la carga y la semántica RELEASE se aplica sólo a
+la parte de la operación del store.
+
+Las barreras de memoria solo son necesarias cuando existe la posibilidad de
+interacción entre dos CPU o entre una CPU y un dispositivo. Si se puede
+garantizar que no habrá tal interacción en ninguna pieza de código en
+particular, entonces las barreras de memoria son innecesarias en ese
+fragmento de código.
+
+Tenga en cuenta que estas son las garantías _mínimas_. Diferentes
+arquitecturas pueden proporcionar garantías más sustanciales, pero no se
+puede confiar en estas fuera de esa arquitectura en específico.
+
+
+¿QUÉ NO SE PUEDE ASUMIR SOBRE LAS BARRERAS DE LA MEMORIA?
+---------------------------------------------------------
+
+Hay ciertas cosas que las barreras de memoria del kernel Linux no
+garantizan:
+
+ (*) No hay garantía de que ninguno de los accesos a la memoria
+ especificados antes de una barrera de memoria estará _completo_ al
+ completarse una instrucción de barrera de memoria; se puede considerar
+ que la barrera dibuja una línea en la cola de acceso del CPU que no
+ pueden cruzar los accesos del tipo correspondiente.
+
+ (*) No hay garantía de que la emisión de una barrera de memoria en una CPU
+ tenga cualquier efecto directo en otra CPU o cualquier otro hardware
+ en el sistema. El efecto indirecto será el orden en que la segunda CPU
+ ve los efectos de los primeros accesos que ocurren de la CPU, pero lea
+ el siguiente argumento:
+
+ (*) No hay garantía de que una CPU vea el orden correcto de los efectos
+ de los accesos de una segunda CPU, incluso _si_ la segunda CPU usa una
+ barrera de memoria, a menos que la primera CPU _también_ use una
+ barrera de memoria coincidente (vea el subapartado "Emparejamiento de
+ barrera SMP").
+
+ (*) No hay garantía de que alguna pieza intermedia fuera del hardware[*]
+ del CPU no reordenará los accesos a la memoria. Los mecanismos de
+ coherencia de caché del CPU deben propagar los efectos indirectos de
+ una barrera de memoria entre las CPU, pero es posible que no lo hagan
+ en orden.
+
+ [*] Para obtener información sobre bus mastering DMA y coherencia, lea:
+
+ Documentation/driver-api/pci/pci.rst
+ Documentation/core-api/dma-api-howto.rst
+ Documentation/core-api/dma-api.rst
+
+
+BARRERA DE DEPENDENCIA DE DIRECCIÓN (HISTÓRICO)
+-----------------------------------------------
+
+A partir de la versión 4.15 del kernel Linux, se agregó un smp_mb() a
+READ_ONCE() para DEC Alpha, lo que significa que las únicas personas que
+necesitan prestar atención a esta sección son aquellas que trabajan en el
+código específico de la arquitectura DEC Alpha y aquellas que trabajan en
+READ_ONCE() por dentro. Para aquellos que lo necesitan, y para aquellos que
+estén interesados ​​desde un punto de vista histórico, aquí está la historia
+de las barreras de dependencia de dirección.
+
+[!] Si bien las dependencias de direcciones se observan tanto en carga a
+carga como en relaciones de carga a store, las barreras de dependencia de
+dirección no son necesarias para situaciones de carga a store.
+
+El requisito de las barreras de dependencia de dirección es un poco sutil,
+y no siempre es obvio que sean necesarias. Para ilustrar, considere la
+siguiente secuencia de eventos:
+
+ CPU 1 CPU 2
+ =============== ===============
+ { A == 1, B == 2, C == 3, P == &A, Q == &C }
+ B = 4;
+ <barrera de escritura>
+ WRITE_ONCE(P, &B);
+ Q = READ_ONCE_OLD(P);
+ D = *Q;
+
+[!] READ_ONCE_OLD() corresponde a READ_ONCE() del kernel anterior a 4.15,
+que no implica una barrera de dependencia de direcciones.
+
+Hay una clara dependencia de dirección aquí, y parecería que al final de
+la secuencia, Q debe ser &A o &B, y que:
+
+ (Q == &A) implica (D == 1)
+ (Q == &B) implica (D == 4)
+
+¡Pero! La percepción de la CPU 2 de P puede actualizarse _antes_ de su
+percepción de B, por lo tanto dando lugar a la siguiente situación:
+
+ (Q == &B) y (D == 2) ????
+
+Si bien esto puede parecer una falla en el mantenimiento de la coherencia
+o la causalidad, no lo es, y este comportamiento se puede observar en
+ciertas CPU reales (como DEC Alfa).
+
+Para lidiar con esto, READ_ONCE() proporciona una barrera de dependencia
+de dirección implícita desde el lanzamiento del kernel v4.15:
+
+ CPU 1 CPU 2
+ =============== ===============
+ { A == 1, B == 2, C == 3, P == &A, Q == &C }
+ B = 4;
+ <barrera de escritura>
+ WRITE_ONCE(P, &B);
+ Q = READ_ONCE(P);
+ <barrera de dependencia de dirección implícita>
+ D = *Q;
+
+Esto refuerza la ocurrencia de una de las dos implicaciones, y previene la
+tercera posibilidad de surgir.
+
+
+[!] Tenga en cuenta que esta situación extremadamente contraria a la
+intuición surge más fácilmente en máquinas con cachés divididos, de modo
+que, por ejemplo, un banco de caché procesa líneas de caché pares y el otro
+banco procesa líneas impares de caché. El puntero P podría almacenarse en
+una línea de caché impar y la variable B podría almacenarse en una línea de
+caché con número par. Entonces, si el banco de números pares de la memoria
+caché de la CPU de lectura está extremadamente ocupado mientras que el
+banco impar está inactivo, uno podría ver el nuevo valor del puntero P
+(&B), pero el antiguo valor de la variable B (2).
+
+
+No se requiere una barrera de dependencia de dirección para ordenar
+escrituras dependientes porque las CPU que admite el kernel Linux no
+escriben hasta que están seguros (1) de que la escritura realmente
+sucederá, (2) de la ubicación de la escritura, y (3) del valor a escribir.
+Pero, por favor, lea atentamente la sección "DEPENDENCIAS DEL CONTROL" y el
+archivo Documentation/RCU/rcu_dereference.rst: el compilador puede romperse
+y romper dependencias en muchas formas altamente creativas.
+
+ CPU 1 CPU 2
+ =============== ===============
+ { A == 1, B == 2, C = 3, P == &A, Q == &C }
+ B = 4;
+ <barrera de escritura>
+ WRITE_ONCE(P, &B);
+ Q = READ_ONCE_OLD(P);
+ WRITE_ONCE(*Q, 5);
+
+Por lo tanto, no se requiere ninguna barrera de dependencia de direcciones
+para ordenar la lectura en Q con el load en *Q. En otras palabras, este
+resultado está prohibido, incluso sin una barrera de dependencia de
+dirección implícita del READ_ONCE() moderno:
+
+ (Q == &B) && (B == 4)
+
+Tenga en cuenta que este patrón debe ser raro. Después de todo, el objetivo
+del orden de dependencia es -prevenir- escrituras en la estructura de
+datos, junto con los costosos errores de caché asociados con tales
+escrituras. Este patrón se puede utilizar para registrar raras condiciones
+de error y similares, y el orden natural de las CPUs evita que se pierdan
+tales registros.
+
+
+Tenga en cuenta que el orden proporcionado por una dependencia de dirección
+es local para la CPU que lo contiene. Lea la sección sobre "Atomicidad
+multicopia" para más información.
+
+
+La barrera de dependencia de dirección es muy importante para el sistema
+RCU, por ejemplo. Vea rcu_assign_pointer() y rcu_dereference() en
+include/linux/rcupdate.h. Esto permite que el objetivo actual de un puntero
+RCU sea reemplazado con un nuevo objetivo modificado, sin que el objetivo
+del reemplazo parezca estar inicializado de manera incompleta.
+
+Consulte también la subsección sobre "Coherencia de caché" para obtener un
+ejemplo más completo.
+
+DEPENDENCIAS DE CONTROL
+-----------------------
+
+Las dependencias de control pueden ser un poco complicadas porque los
+compiladores actuales no las entienden. El propósito de esta sección es
+ayudarle a prevenir que la ignorancia del compilador rompa su código.
+
+Una dependencia de control load-load (de carga a carga) requiere una
+barrera de memoria de lectura completa, no simplemente una barrera
+(implícita) de dependencia de direcciones para que funcione correctamente.
+Considere el siguiente fragmento de código:
+
+ q = READ_ONCE(a);
+ <barrera implícita de dependencia de direcciones>
+ if (q) {
+ /* BUG: No hay dependencia de dirección!!! */
+ p = READ_ONCE(b);
+ }
+
+Esto no tendrá el efecto deseado porque no hay una dependencia de dirección
+real, sino más bien una dependencia de control que la CPU puede
+cortocircuitar al intentar predecir el resultado por adelantado, para que
+otras CPU vean la carga de b como si hubiera ocurrido antes que la carga de
+a. En cuyo caso lo que realmente se requiere es:
+
+ q = READ_ONCE(a);
+ if (q) {
+ <barrera de lectura>
+ p = READ_ONCE(b);
+ }
+
+Sin embargo, los stores no se especulan. Esto significa que ordenar -es-
+provisto para dependencias de control de load-store, como en el siguiente
+ejemplo:
+
+ q = READ_ONCE(a);
+ if (q) {
+ WRITE_ONCE(b, 1);
+ }
+
+Las dependencias de control se emparejan normalmente con otros tipos de
+barreras. Dicho esto, tenga en cuenta que ni READ_ONCE() ni WRITE_ONCE()
+son opcionales! Sin READ_ONCE(), el compilador podría combinar la carga de
+'a' con otras cargas de 'a'. Sin WRITE_ONCE(), el compilador podría
+combinar el store de 'b' con otros stores de 'b'. Cualquiera de estos casos
+puede dar lugar a efectos en el orden muy contrarios a la intuición.
+
+Peor aún, si el compilador puede probar (decir) que el valor de la
+variable 'a' siempre es distinta de cero, estaría dentro de sus derechos
+para optimizar el ejemplo original eliminando la declaración "if", como:
+
+ q = a;
+ b = 1; /* BUG: Compilador y CPU pueden ambos reordernar!!! */
+
+Así que no deje de lado READ_ONCE().
+
+Es tentador tratar de hacer cumplir el orden en stores idénticos en ambos
+caminos del "if" de la siguiente manera:
+
+ q = READ_ONCE(a);
+ if (q) {
+ barrier();
+ WRITE_ONCE(b, 1);
+ hacer_algo();
+ } else {
+ barrier();
+ WRITE_ONCE(b, 1);
+ hacer_otra_cosa();
+ }
+
+Desafortunadamente, los compiladores actuales transformarán esto de la
+siguiente manera en casos de alto nivel de optimización:
+
+ q = READ_ONCE(a);
+ barrier();
+ WRITE_ONCE(b, 1); /* BUG: No hay orden en load de a!!! */
+ if (q) {
+ /* WRITE_ONCE(b, 1); -- movido arriba, BUG!!! */
+ hacer_algo();
+ } else {
+ /* WRITE_ONCE(b, 1); -- movido arriba, BUG!!! */
+ hacer_otra_cosa();
+ }
+
+Ahora no hay condicional entre la carga de 'a' y el store de 'b', lo que
+significa que la CPU está en su derecho de reordenarlos: El condicional es
+absolutamente necesario y debe estar presente en el código ensamblador
+incluso después de que se hayan aplicado todas las optimizaciones del
+compilador. Por lo tanto, si necesita ordenar en este ejemplo, necesita
+explícitamente barreras de memoria, por ejemplo, smp_store_release():
+
+
+ q = READ_ONCE(a);
+ if (q) {
+ smp_store_release(&b, 1);
+ hacer_algo();
+ } else {
+ smp_store_release(&b, 1);
+ hacer_otra_cosa();
+ }
+
+Por el contrario, sin barreras de memoria explícita, el control de un if
+con dos opciones está garantizado solo cuando los stores difieren, por
+ejemplo:
+
+ q = READ_ONCE(a);
+ if (q) {
+ WRITE_ONCE(b, 1);
+ hacer_algo();
+ } else {
+ WRITE_ONCE(b, 2);
+ hacer_otra_cosa();
+ }
+
+Aún se requiere el inicial READ_ONCE() para evitar que el compilador toque
+el valor de 'a'.
+
+Además, debe tener cuidado con lo que hace con la variable local 'q', de lo
+contrario, el compilador podría adivinar el valor y volver a eliminar el
+necesario condicional. Por ejemplo:
+
+ q = READ_ONCE(a);
+ if (q % MAX) {
+ WRITE_ONCE(b, 1);
+ hacer_algo();
+ } else {
+ WRITE_ONCE(b, 2);
+ hacer_otra_cosa();
+ }
+
+Si MAX se define como 1, entonces el compilador sabe que (q % MAX) es igual
+a cero, en cuyo caso el compilador tiene derecho a transformar el código
+anterior en el siguiente:
+
+ q = READ_ONCE(a);
+ WRITE_ONCE(b, 2);
+ hacer_otra_cosa();
+
+Dada esta transformación, la CPU no está obligada a respetar el orden entre
+la carga de la variable 'a' y el store de la variable 'b'. Es tentador
+agregar una barrier(), pero esto no ayuda. El condicional se ha ido, y la
+barrera no lo traerá de vuelta. Por lo tanto, si confia en este orden, debe
+asegurarse de que MAX sea mayor que uno, tal vez de la siguiente manera:
+
+ q = READ_ONCE(a);
+ BUILD_BUG_ON(MAX <= 1); /* Orden de carga de a con store de b */
+ if (q % MAX) {
+ WRITE_ONCE(b, 1);
+ hacer_algo();
+ } else {
+ WRITE_ONCE(b, 2);
+ hacer_otra_cosa();
+ }
+
+Tenga en cuenta una vez más que los stores de 'b' difieren. Si fueran
+idénticos, como se señaló anteriormente, el compilador podría sacar ese
+store fuera de la declaración 'if'.
+
+También debe tener cuidado de no confiar demasiado en el cortocircuito
+de la evaluación booleana. Considere este ejemplo:
+
+ q = READ_ONCE(a);
+ if (q || 1 > 0)
+ WRITE_ONCE(b, 1);
+
+Debido a que la primera condición no puede fallar y la segunda condición es
+siempre cierta, el compilador puede transformar este ejemplo de la
+siguiente manera, rompiendo la dependencia del control:
+
+ q = READ_ONCE(a);
+ WRITE_ONCE(b, 1);
+
+Este ejemplo subraya la necesidad de asegurarse de que el compilador no
+pueda adivinar su código. Más generalmente, aunque READ_ONCE() fuerza
+al compilador para emitir código para una carga dada, no fuerza al
+compilador para usar los resultados.
+
+Además, las dependencias de control se aplican solo a la cláusula then y
+la cláusula else de la sentencia if en cuestión. En particular, no se
+aplica necesariamente al código que sigue a la declaración if:
+
+ q = READ_ONCE(a);
+ if (q) {
+ WRITE_ONCE(b, 1);
+ } else {
+ WRITE_ONCE(b, 2);
+ }
+ WRITE_ONCE(c, 1); /* BUG: No hay orden para la lectura de 'a'. */
+
+Es tentador argumentar que, de hecho, existe un orden porque el compilador
+no puede reordenar accesos volátiles y tampoco puede reordenar escrituras
+en 'b' con la condición. Desafortunadamente para esta línea de
+razonamiento, el compilador podría compilar las dos escrituras en 'b' como
+instrucciones de movimiento condicional, como en este fantástico idioma
+pseudo-ensamblador:
+
+ ld r1,a
+ cmp r1,$0
+ cmov,ne r4,$1
+ cmov,eq r4,$2
+ st r4,b
+ st $1,c
+
+Una CPU débilmente ordenada no tendría dependencia de ningún tipo entre la
+carga de 'a' y el store de 'c'. Las dependencias de control se extenderían
+solo al par de instrucciones cmov y el store dependiente de ellas. En
+resumen, las dependencias de control se aplican solo a los stores en la
+cláusula then y la cláusula else de la sentencia if en cuestión (incluidas
+las funciones invocado por esas dos cláusulas), no al código que sigue a
+esa declaración if.
+
+
+Tenga muy en cuenta que el orden proporcionado por una dependencia de
+control es local a la CPU que lo contiene. Vea el apartado de "Atomicidad
+multicopia" para más información.
+
+
+En resumen:
+
+ (*) Las dependencias de control pueden ordenar cargas anteriores para
+ stores posteriores. Sin embargo, no garantizan ningún otro tipo de
+ orden: No cargas previas contra cargas posteriores, ni
+ almacenamientos previos y luego nada. Si necesita tales formas de
+ orden, use smp_rmb(), smp_wmb() o, en el caso de stores anteriores y
+ cargas posteriores, smp_mb().
+
+ (*) Si ambos caminos de la declaración "if" comienzan con stores
+ idénticos de la misma variable, entonces esos stores deben ser
+ ordenados, ya sea precediéndoles a ambos con smp_mb() o usando
+ smp_store_release() para realizar el store. Tenga en cuenta que -no-
+ es suficiente usar barrier() al comienzo de cada caso de la
+ declaración "if" porque, como se muestra en el ejemplo anterior, la
+ optimización de los compiladores puede destruir la dependencia de
+ control respetando al pie de la letra la ley de barrier().
+
+ (*) Las dependencias de control requieren al menos un condicional en
+ tiempo de ejecución entre la carga anterior y el almacenamiento
+ posterior, y este condicional debe implicar la carga previa. Si el
+ compilador es capaz de optimizar el condicional y quitarlo, también
+ habrá optimizado el ordenar. El uso cuidadoso de READ_ONCE() y
+ WRITE_ONCE() puede ayudar a preservar el necesario condicional.
+
+ (*) Las dependencias de control requieren que el compilador evite
+ reordenar las dependencia hasta su inexistencia. El uso cuidadoso de
+ READ_ONCE() o atomic{,64}_read() puede ayudarle a preservar la
+ dependencia de control. Consulte la sección BARRERA DEL COMPILADOR
+ para obtener más información al respecto.
+
+ (*) Las dependencias de control se aplican solo a la cláusula then y la
+ cláusula else de la sentencia "if" que contiene la dependencia de
+ control, incluyendo cualquier función a la que llamen dichas dos
+ cláusulas. Las dependencias de control no se aplican al código que
+ sigue a la instrucción if que contiene la dependencia de control.
+
+ (*) Las dependencias de control se emparejan normalmente con otros tipos
+ de barreras.
+
+ (*) Las dependencias de control no proporcionan atomicidad multicopia. Si
+ usted necesita todas las CPU para ver un store dado al mismo tiempo,
+ emplee smp_mb().
+
+ (*) Los compiladores no entienden las dependencias de control. Por lo
+ tanto es su trabajo asegurarse de que no rompan su código.
+
+
+EMPAREJAMIENTO DE BARRERAS SMP
+------------------------------
+
+Cuando se trata de interacciones CPU-CPU, ciertos tipos de barrera de
+memoria deben estar siempre emparejados. La falta del apropiado
+emparejamiento es casi seguro un error.
+
+Las barreras generales se emparejan entre sí, aunque también se emparejan
+con la mayoría de otro tipo de barreras, aunque sin atomicidad multicopia.
+Una barrera de adquisición se empareja con una barrera de liberación, pero
+ambas también pueden emparejarse con otras barreras, incluidas, por
+supuesto, las barreras generales. Una barrera de escritura se empareja con
+una barrera de dependencia de dirección, una dependencia de control, una
+barrera de adquisición, una barrera de liberación, una barrera de lectura
+o una barrera general. Del mismo modo, una barrera de lectura se empareja
+con una de dependencia de control o barrera de dependencia de dirección con
+una barrera de escritura, una barrera de adquisición, una barrera de
+liberación o una barrera general:
+
+ CPU 1 CPU 2
+ =============== ===============
+ WRITE_ONCE(a, 1);
+ <barrera de escritura>
+ WRITE_ONCE(b, 2); x = READ_ONCE(b);
+ <barrera de lectura>
+ y = READ_ONCE(a);
+
+O bien:
+
+ CPU 1 CPU 2
+ =============== ===============================
+ a = 1;
+ <barrera de escritura>
+ WRITE_ONCE(b, &a); x = READ_ONCE(b);
+ <barrera de dependencia de dirección implícita>
+ y = *x;
+
+O incluso:
+
+ CPU 1 CPU 2
+ =============== ===============================
+ r1 = READ_ONCE(y);
+ <barrera general>
+ WRITE_ONCE(x, 1); if (r2 = READ_ONCE(x)) {
+ <barrera de control implícita>
+ WRITE_ONCE(y, 1);
+ }
+
+ assert(r1 == 0 || r2 == 0);
+
+Básicamente, la barrera de lectura siempre tiene que estar ahí, aunque
+puede ser del tipo "más débil".
+
+[!] Tenga en cuenta que normalmente se esperaría que los stores antes de la
+barrera de escritura se hagan coincidir con los stores después de la
+barrera de lectura o la barrera de dependencia de dirección, y viceversa:
+
+ CPU 1 CPU 2
+ =================== ===================
+ WRITE_ONCE(a, 1); }---- --->{ v = READ_ONCE(c);
+ WRITE_ONCE(b, 2); } \ / { w = READ_ONCE(d);
+ <barrera de escritura> \ <barrera de lectura>
+ WRITE_ONCE(c, 3); } / \ { x = READ_ONCE(a);
+ WRITE_ONCE(d, 4); }---- --->{ y = READ_ONCE(b);
+
+
+EJEMPLOS DE SECUENCIAS DE BARRERA DE MEMORIA
+--------------------------------------------
+
+En primer lugar, las barreras de escritura actúan como orden parcial en las
+operaciones de store. Considere la siguiente secuencia de eventos:
+
+ CPU 1
+ =======================
+ STORE A = 1
+ STORE B = 2
+ STORE C = 3
+ <barrera de escritura>
+ STORE D = 4
+ STORE E = 5
+
+Esta secuencia de eventos es finalizado para con el sistema de coherencia
+de memoria en un orden que el resto del sistema podría percibir como el
+conjunto desordenado { STORE A, STORE B, STORE C} todo ocurriendo antes del
+conjunto desordenado { STORE D, STORE E}:
+
+
+ +-------+ : :
+ | | +------+
+ | |------>| C=3 | } /\
+ | | : +------+ }----- \ -----> Eventos perceptibles para
+ | | : | A=1 | } \/ el resto del sistema
+ | | : +------+ }
+ | CPU 1 | : | B=2 | }
+ | | +------+ }
+ | | wwwwwwwwwwwwwwww } <--- En este momento la barrera de
+ | | +------+ } escritura requiere que todos los
+ | | : | E=5 | } stores anteriores a la barrera
+ | | : +------+ } sean confirmados antes de que otros
+ | |------>| D=4 | } store puedan suceder
+ | | +------+
+ +-------+ : :
+ |
+ | Secuencia por la cual los stores son confirmados al
+ | sistema de memoria por parte del CPU 1
+ V
+
+En segundo lugar, las barreras de dependencia de dirección actúan como
+órdenes parciales sobre la dirección de cargas dependientes. Considere la
+siguiente secuencia de eventos:
+
+ CPU 1 CPU 2
+ ======================= =======================
+ { B = 7; X = 9; Y = 8; C = &Y }
+ STORE A = 1
+ STORE B = 2
+ <barrera de escritura>
+ STORE C = &B LOAD X
+ STORE D = 4 LOAD C (consigue &B)
+ LOAD *C (lee B)
+
+Sin intervención, la CPU 2 puede percibir los eventos en la CPU 1 en orden
+aleatorio a efectos prácticos, a pesar de la barrera de escritura emitida
+por la CPU 1:
+
+ +-------+ : : : :
+ | | +------+ +-------+ | Secuencia de
+ | |------>| B=2 |----- --->| Y->8 | | actualizado de
+ | | : +------+ \ +-------+ | percepción en CPU 2
+ | CPU 1 | : | A=1 | \ --->| C->&Y | V
+ | | +------+ | +-------+
+ | | wwwwwwwwwwwwwwww | : :
+ | | +------+ | : :
+ | | : | C=&B |--- | : : +-------+
+ | | : +------+ \ | +-------+ | |
+ | |------>| D=4 | ----------->| C->&B |------>| |
+ | | +------+ | +-------+ | |
+ +-------+ : : | : : | |
+ | : : | |
+ | : : | CPU 2 |
+ | +-------+ | |
+ Percepción de B ---> | | B->7 |------>| |
+ aparentemente incorrecta! | +-------+ | |
+ | : : | |
+ | +-------+ | |
+ La carga de X frena ---> \ | X->9 |------>| |
+ el mantenimiento de \ +-------+ | |
+ la coherencia de B ----->| B->2 | +-------+
+ +-------+
+ : :
+
+
+En el ejemplo anterior, la CPU 2 percibe que B es 7, a pesar de la carga de
+*C (que sería B) viniendo después del LOAD de C.
+
+Sin embargo, si se colocara una barrera de dependencia de dirección entre
+la carga de C y la carga de *C (es decir: B) en la CPU 2:
+
+ CPU 1 CPU 2
+ ======================= =======================
+ { B = 7; X = 9; Y = 8; C = &Y }
+ STORE A = 1
+ STORE B = 2
+ <barrera de escritura>
+ STORE C = &B LOAD X
+ STORE D = 4 LOAD C (consigue &B)
+ <barrera de dependencia de dirección>
+ LOAD *C (reads B)
+
+entonces ocurrirá lo siguiente:
+
+ +-------+ : : : :
+ | | +------+ +-------+
+ | |------>| B=2 |----- --->| Y->8 |
+ | | : +------+ \ +-------+
+ | CPU 1 | : | A=1 | \ --->| C->&Y |
+ | | +------+ | +-------+
+ | | wwwwwwwwwwwwwwww | : :
+ | | +------+ | : :
+ | | : | C=&B |--- | : : +-------+
+ | | : +------+ \ | +-------+ | |
+ | |------>| D=4 | ----------->| C->&B |------>| |
+ | | +------+ | +-------+ | |
+ +-------+ : : | : : | |
+ | : : | |
+ | : : | CPU 2 |
+ | +-------+ | |
+ | | X->9 |------>| |
+ | +-------+ | |
+ Se asegura de que ---> \ aaaaaaaaaaaaaaaaa | |
+ los efectos anteriores al \ +-------+ | |
+ store de C sean percibidos ----->| B->2 |------>| |
+ por los siguientes loads +-------+ | |
+ : : +-------+
+
+
+Y en tercer lugar, una barrera de lectura actúa como un orden parcial sobre
+las cargas. Considere la siguiente secuencia de eventos:
+
+ CPU 1 CPU 2
+ ======================= =======================
+ { A = 0, B = 9 }
+ STORE A=1
+ <barrera de escritura>
+ STORE B=2
+ LOAD B
+ LOAD A
+
+Sin intervención, la CPU 2 puede elegir percibir los eventos en la CPU 1 en
+algún orden aleatorio a efectos prácticos, a pesar de la barrera de
+escritura emitida por la CPU 1:
+
+ +-------+ : : : :
+ | | +------+ +-------+
+ | |------>| A=1 |------ --->| A->0 |
+ | | +------+ \ +-------+
+ | CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 |
+ | | +------+ | +-------+
+ | |------>| B=2 |--- | : :
+ | | +------+ \ | : : +-------+
+ +-------+ : : \ | +-------+ | |
+ ---------->| B->2 |------>| |
+ | +-------+ | CPU 2 |
+ | | A->0 |------>| |
+ | +-------+ | |
+ | : : +-------+
+ \ : :
+ \ +-------+
+ ---->| A->1 |
+ +-------+
+ : :
+
+Sin embargo, si se colocara una barrera de lectura entre la carga de B y la
+carga de A en la CPU 2:
+
+ CPU 1 CPU 2
+ ======================= =======================
+ { A = 0, B = 9 }
+ STORE A=1
+ <barrera de escritura>
+ STORE B=2
+ LOAD B
+ <barrera de lectura>
+ LOAD A
+
+entonces el orden parcial impuesto por la CPU 1 será percibido
+correctamente por la CPU 2:
+
+ +-------+ : : : :
+ | | +------+ +-------+
+ | |------>| A=1 |------ --->| A->0 |
+ | | +------+ \ +-------+
+ | CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 |
+ | | +------+ | +-------+
+ | |------>| B=2 |--- | : :
+ | | +------+ \ | : : +-------+
+ +-------+ : : \ | +-------+ | |
+ ---------->| B->2 |------>| |
+ | +-------+ | CPU 2 |
+ | : : | |
+ | : : | |
+ En este punto la barrera ----> \ rrrrrrrrrrrrrrrrr | |
+ de lectura consigue que \ +-------+ | |
+ todos los efectos anteriores ---->| A->1 |------>| |
+ al almacenamiento de B sean +-------+ | |
+ perceptibles por la CPU 2 : : +-------+
+
+
+Para ilustrar esto de manera más completa, considere lo que podría pasar si
+el código contenía una carga de A a cada lado de la barrera de lectura:
+
+ CPU 1 CPU 2
+ ======================= =======================
+ { A = 0, B = 9 }
+ STORE A=1
+ <barrera de escritura>
+ STORE B=2
+ LOAD B
+ LOAD A [primer load de A]
+ <rbarrera de lectura>
+ LOAD A [segundo load de A]
+
+Aunque las dos cargas de A ocurren después de la carga de B, ambas pueden
+obtener diferentes valores:
+
+ +-------+ : : : :
+ | | +------+ +-------+
+ | |------>| A=1 |------ --->| A->0 |
+ | | +------+ \ +-------+
+ | CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 |
+ | | +------+ | +-------+
+ | |------>| B=2 |--- | : :
+ | | +------+ \ | : : +-------+
+ +-------+ : : \ | +-------+ | |
+ ---------->| B->2 |------>| |
+ | +-------+ | CPU 2 |
+ | : : | |
+ | : : | |
+ | +-------+ | |
+ | | A->0 |------>| 1st |
+ | +-------+ | |
+ En este punto la barrera ----> \ rrrrrrrrrrrrrrrrr | |
+ de lectura consigue que \ +-------+ | |
+ todos los efectos anteriores ---->| A->1 |------>| |
+ al almacenamiento de B sean +-------+ | |
+ perceptibles por la CPU 2 : : +-------+
+
+Pero puede ser que la actualización a A desde la CPU 1 se vuelva
+perceptible para la CPU 2 antes de que la barrera de lectura se complete de
+todos modos:
+
+ +-------+ : : : :
+ | | +------+ +-------+
+ | |------>| A=1 |------ --->| A->0 |
+ | | +------+ \ +-------+
+ | CPU 1 | wwwwwwwwwwwwwwww \ --->| B->9 |
+ | | +------+ | +-------+
+ | |------>| B=2 |--- | : :
+ | | +------+ \ | : : +-------+
+ +-------+ : : \ | +-------+ | |
+ ---------->| B->2 |------>| |
+ | +-------+ | CPU 2 |
+ | : : | |
+ \ : : | |
+ \ +-------+ | |
+ ---->| A->1 |------>| 1st |
+ +-------+ | |
+ rrrrrrrrrrrrrrrrr | |
+ +-------+ | |
+ | A->1 |------>| 2nd |
+ +-------+ | |
+ : : +-------+
+
+La garantía es que la segunda carga siempre dará como resultado A == 1 si
+la carga de B resultó en B == 2. No existe tal garantía para la primera
+carga de A; esto puede dar como resultado A == 0 o A == 1.
+
+
+BARRERAS DE MEMORIA DE LECTURA FRENTE A ESPECULACIÓN DE CARGA
+-------------------------------------------------------------
+
+Muchas CPU especulan con las cargas: es decir, ven que necesitarán cargar
+un elemento de la memoria, y encuentran un momento en el que no están
+usando el bus para ningún otra carga, y también en la carga por adelantado,
+aunque en realidad no lo hayan llegado a ese punto en el flujo de ejecución
+de instrucciones todavía. Esto permite que la instrucción de carga real
+potencialmente complete de inmediato, porque la CPU ya tiene el valor a
+mano.
+
+Puede resultar que la CPU en realidad no necesitara el valor, tal vez
+porque una condición eludió la carga, en cuyo caso puede descartar el valor
+o simplemente almacenar en caché para su uso posterior.
+
+Considere:
+
+ CPU 1 CPU 2
+ ======================= =======================
+ LOAD B
+ DIVIDE } Instrucciones de división
+ DIVIDE } tardan mucho en terminar
+ LOAD A
+
+donde DIVIDE es DIVIDIR. Que podría aparecer como esto:
+
+ : : +-------+
+ +-------+ | |
+ --->| B->2 |------>| |
+ +-------+ | CPU 2 |
+ : :DIVIDE | |
+ +-------+ | |
+ La CPU ocupada con la división ---> --->| A->0 |~~~~ | |
+ especula sobre el LOAD de A +-------+ ~ | |
+ : : ~ | |
+ : :DIVIDE | |
+ : : ~ | |
+ Una vez completadas las divisiones --> : : ~-->| |
+ la CPU puede realizar el : : | |
+ LOAD con efecto inmediato : : +-------+
+
+
+Colocando una barrera de lectura o una barrera de dependencia de dirección
+justo antes de la segundo carga:
+
+
+
+ CPU 1 CPU 2
+ ======================= =======================
+ LOAD B
+ DIVIDE
+ DIVIDE
+ <rbarrera de lectura>
+ LOAD A
+
+obligará a reconsiderar cualquier valor obtenido especulativamente en una
+medida dependiente del tipo de barrera utilizada. Si no se hizo ningún
+cambio en la ubicación de memoria especulada, entonces el valor especulado
+solo se usará:
+
+ : : +-------+
+ +-------+ | |
+ --->| B->2 |------>| |
+ +-------+ | CPU 2 |
+ : :DIVIDE | |
+ +-------+ | |
+ La CPU ocupada con la división ---> --->| A->0 |~~~~ | |
+ especula sobre el LOAD de A +-------+ ~ | |
+ : : ~ | |
+ : :DIVIDE | |
+ : : ~ | |
+ : : ~ | |
+ rrrrrrrrrrrrrrrr~ | |
+ : : ~ | |
+ : : ~-->| |
+ : : | |
+ : : +-------+
+
+
+pero si había una actualización o una invalidación de otra CPU pendiente,
+entonces la especulación será cancelada y el valor recargado:
+
+ : : +-------+
+ +-------+ | |
+ --->| B->2 |------>| |
+ +-------+ | CPU 2 |
+ : :DIVIDE | |
+ +-------+ | |
+ La CPU ocupada con la división ---> --->| A->0 |~~~~ | |
+ especula sobre el LOAD de A +-------+ ~ | |
+ : : ~ | |
+ : :DIVIDE | |
+ : : ~ | |
+ : : ~ | |
+ rrrrrrrrrrrrrrrrr | |
+ +-------+ | |
+ La especulación es descartada ---> --->| A->1 |------>| |
+ y un valor actualizado +-------+ | |
+ es conseguido : : +-------+
+
+ATOMICIDAD MULTICOPIA
+---------------------
+
+La atomicidad multicopia es una noción profundamente intuitiva sobre el
+orden que no es siempre proporcionada por los sistemas informáticos reales,
+a saber, que un determinada store se vuelve visible al mismo tiempo para
+todos las CPU o, alternativamente, que todas las CPU acuerdan el orden en
+que todos los stores se vuelven visibles. Sin embargo, el soporte para
+atomicidad multicopia completa descartaría valiosas optimizaciones
+hardware, por lo que una versión más débil conocida como ``otra atomicidad
+multicopia'' en cambio, solo garantiza que un store dado se vuelva visible
+al mismo tiempo en todas las -otras- CPUs. El resto de este documento
+discute esta versión más débil, pero por brevedad lo llamaremos simplemente
+``atomicidad multicopia''.
+
+El siguiente ejemplo demuestra la atomicidad multicopia:
+
+ CPU 1 CPU 2 CPU 3
+ ======================= ======================= =======================
+ { X = 0, Y = 0 }
+ STORE X=1 r1=LOAD X (reads 1) LOAD Y (reads 1)
+ <barrera general> <barrera de lectura>
+ STORE Y=r1 LOAD X
+
+Suponga que la carga de la CPU 2 desde X devuelve 1, que luego almacena en
+Y, y la carga de la CPU 3 desde Y devuelve 1. Esto indica que el store de
+la CPU 1 a X precede a la carga de la CPU 2 desde X y el store de esa CPU 2
+a Y precede la carga de la CPU 3 desde Y. Además, las barreras de memoria
+garantizan que la CPU 2 ejecuta su carga antes que su almacenamiento, y la
+CPU 3 carga desde Y antes de cargar desde X. La pregunta entonces es
+"¿Puede la carga de la CPU 3 desde X devolver 0?"
+
+Debido a que la carga de la CPU 3 desde X en cierto sentido viene después
+de la carga de la CPU 2, es natural esperar que la carga de la CPU 3 desde
+X deba devolver 1. Esta expectativa se deriva de la atomicidad multicopia:
+si una carga que se ejecuta en la CPU B sigue una carga de la misma
+variable que se ejecuta en la CPU A (y la CPU A no almacenó originalmente
+el valor que leyó), entonces en sistemas atómicos multicopia, la carga de
+la CPU B debe devolver el mismo valor que hizo la carga de la CPU A o algún
+valor posterior. Sin embargo, el kernel Linux no requiere que los sistemas
+sean atómicos multicopia.
+
+El uso de una barrera de memoria general en el ejemplo anterior compensa
+cualquier falta de atomicidad multicopia. En el ejemplo, si la carga de la
+CPU 2 de X devuelve 1 y la carga de la CPU 3 de Y devuelve 1, entonces la
+carga de la CPU 3 desde X debe de hecho también devolver 1.
+
+Sin embargo, las dependencias, las barreras de lectura y las barreras de
+escritura no siempre son capaces de compensar la atomicidad no multicopia.
+Por ejemplo, supongamos que la barrera general de la CPU 2 se elimina del
+ejemplo anterior, dejando solo la dependencia de datos que se muestra a
+continuación:
+
+ CPU 1 CPU 2 CPU 3
+ ======================= ======================= =======================
+ { X = 0, Y = 0 }
+ STORE X=1 r1=LOAD X (escribe 1) LOAD Y (lee 1)
+ <dependencia de datos> <barrera de lectura>
+ STORE Y=r1 LOAD X (lee 0)
+
+Esta sustitución permite que la atomicidad no multicopia se desenfrene: en
+este ejemplo, es perfectamente legal que la carga de la CPU 2 desde X
+devuelva 1, la carga de la CPU 3 desde Y devuelva 1, y su carga desde X
+tenga valor 0.
+
+El punto clave es que aunque la dependencia de datos de la CPU 2 ordena su
+carga y store, no garantiza ordenar el store de la CPU 1. De forma que, si
+este ejemplo se ejecuta en un sistema atómico no multicopia donde las CPU 1
+y 2 comparten un buffer de almacenamiento o un nivel de caché, la CPU 2
+podría tener acceso anticipado de escritura a CPU 1. Por lo tanto, se
+requieren barreras generales para garantizar que todas las CPU acurden el
+orden combinado de accesos múltiples.
+
+Las barreras generales pueden compensar no solo la atomicidad no
+multicopia, pero también pueden generar orden adicional que puede asegurar
+que -todas- las CPU percibirán el mismo orden de -todas- las operaciones.
+Por el contrario, una cadena de parejas de liberación-adquisición no
+proporciona este orden adicional, lo que significa que solo se garantiza
+que las CPU de la cadena estén de acuerdo en el orden combinado de los
+accesos. Por ejemplo, cambiando a código C en deferencia al fantasma de
+Herman Hollerith:
+
+ int u, v, x, y, z;
+
+ void cpu0(void)
+ {
+ r0 = smp_load_acquire(&x);
+ WRITE_ONCE(u, 1);
+ smp_store_release(&y, 1);
+ }
+
+ void cpu1(void)
+ {
+ r1 = smp_load_acquire(&y);
+ r4 = READ_ONCE(v);
+ r5 = READ_ONCE(u);
+ smp_store_release(&z, 1);
+ }
+
+ void cpu2(void)
+ {
+ r2 = smp_load_acquire(&z);
+ smp_store_release(&x, 1);
+ }
+
+ void cpu3(void)
+ {
+ WRITE_ONCE(v, 1);
+ smp_mb();
+ r3 = READ_ONCE(u);
+ }
+
+Dado que cpu0(), cpu1() y cpu2() participan en una cadena de parejas
+smp_store_release()/smp_load_acquire(), el siguiente resultado estaría
+prohibido:
+
+ r0 == 1 && r1 == 1 && r2 == 1
+
+Además, debido a la relación liberación-adquisición entre cpu0() y cpu1(),
+cpu1() debe ver las escrituras de cpu0(), de modo que el siguiente
+resultado estaría prohibido:
+
+ r1 == 1 && r5 == 0
+
+Sin embargo, el orden proporcionado por una cadena de
+liberación-adquisición es local a las CPU que participan en esa cadena y no
+se aplica a cpu3(), al menos aparte de los stores. Por lo tanto, es posible
+el siguiente resultado:
+
+ r0 == 0 && r1 == 1 && r2 == 1 && r3 == 0 && r4 == 0
+
+Por otro lado, también el siguiente resultado es posible:
+
+ r0 == 0 && r1 == 1 && r2 == 1 && r3 == 0 && r4 == 0 && r5 == 1
+
+Aunque cpu0(), cpu1() y cpu2() verán sus respectivas lecturas y escrituras
+en orden, las CPU que no participan en la cadena de liberación-adquisición
+pueden estar en desacuerdo con el orden. Este desacuerdo se debe al hecho
+de que las instrucciones de barrera de memoria débiles utilizadas para
+implementar smp_load_acquire() y smp_store_release() no son necesarios para
+ordenar stores anteriores contra cargas posteriores en todos los casos.
+Esto significa que cpu3() puede ver el store de cpu0() suceder -después- de
+la carga de cpu1() desde v, aunque tanto cpu0() como cpu1() están de
+acuerdo en que estas dos operaciones ocurrieron en el orden previsto.
+
+Sin embargo, tenga en cuenta que smp_load_acquire() no es mágico. En
+particular, simplemente lee de su argumento en orden. Es decir, -no-
+asegura que se leerá cualquier valor en particular. Por lo tanto, los
+siguiente resultados son posibles:
+
+ r0 == 0 && r1 == 0 && r2 == 0 && r5 == 0
+
+Tenga en cuenta que este resultado puede ocurrir incluso en un mítico
+sistema, consistente en secuencia, donde nunca se reordena nada.
+
+Para reiterar, si su código requiere un orden completo de todas las
+operaciones, utilice barreras generales en todo momento.
+
+
+==============================
+BARRERAS EXPLÃCITAS DEL KERNEL
+==============================
+
+El kernel Linux tiene una variedad de diferentes barreras que actúan a
+diferentes niveles:
+
+ (*) Barrera del compilador.
+
+ (*) Barreras de memoria de la CPU.
+
+
+BARRERA DEL COMPILADOR
+-----------------------
+
+El kernel de Linux tiene una función de barrera del compilador explícita
+que evita que el el compilador mueva los accesos a la memoria de cualquier
+lado al otro:
+
+ barrier();
+
+Esta es una barrera general: no hay variantes de barrier() para casos de
+lectura-lectura o escritura-escritura. Sin embargo, READ_ONCE() y
+WRITE_ONCE() pueden ser considerado como formas débiles de barrier() que
+afectan solo específicos accesos marcados por READ_ONCE() o WRITE_ONCE().
+
+La función barrier() produce los siguientes efectos:
+
+ (*) Evita que el compilador reordene los accesos tras barrier() para
+ preceder a cualquier acceso que preceda a barrier(). Un ejemplo de uso
+ de esta propiedad es facilitar la comunicación entre código del
+ interrupt-handler (encargo de gestionar interrupciones) y el código
+ que fue interrumpido.
+
+ (*) Dentro de un bucle ("loop"), obliga al compilador a cargar las
+ variables utilizadas en ese loop condicional en cada paso a través de
+ ese loop.
+
+Las funciones READ_ONCE() y WRITE_ONCE() pueden evitar cualquier cantidad
+de optimizaciones que, si bien son perfectamente seguras en código de un
+solo subproceso, pueden resultar fatales en código concurrente. Aquí hay
+algunos ejemplos de tal tipo de optimizaciones:
+
+(*) El compilador está en su derecho de reordenar cargas y stores de la
+ misma variable, y en algunos casos, la CPU está dentro de su
+ derecho de reordenar cargas a la misma variable. Esto significa que
+ el siguiente código:
+
+ a[0] = x;
+ a[1] = x;
+
+ Podría resultar en un valor más antiguo de x almacenado en a[1] que en
+ a[0]. Evite que tanto el compilador como la CPU hagan esto de la
+ siguiente manera:
+
+ a[0] = READ_ONCE(x);
+ a[1] = READ_ONCE(x);
+
+ En resumen, READ_ONCE() y WRITE_ONCE() proporcionan coherencia de
+ caché para accesos desde múltiples CPUs a una sola variable.
+
+ (*) El compilador tiene derecho a juntar cargas sucesivas de la misma
+ variable. Tal fusión puede hacer que el compilador "optimice" el
+ siguiente código:
+
+ while (tmp = a)
+ hacer_algo_con(tmp);
+
+ en el siguiente código, que, aunque en cierto sentido es legítimo
+ para un código de un solo subproceso, es casi seguro que no es lo
+ que el desarrollador pretendía:
+
+ if (tmp = a)
+ for (;;)
+ hacer_algo_con(tmp);
+
+ Use READ_ONCE() para evitar que el compilador le haga esto:
+
+ while (tmp = READ_ONCE(a))
+ hacer_algo_con(tmp);
+
+ (*) El compilador tiene derecho a recargar una variable, por ejemplo,
+ en los casos en que la alta presión de los registros impida que el
+ compilador mantenga todos los datos de interés en registros. El
+ compilador podría por lo tanto, optimizar la variable 'tmp' de nuestro
+ ejemplo anterior:
+
+ while (tmp = a)
+ hacer_algo_con(tmp);
+
+ Esto podría resultar en el siguiente código, que es perfectamente
+ seguro en código de subproceso único, pero puede ser fatal en código
+ concurrente:
+
+ while (a)
+ hacer_algo_con(a);
+
+ Por ejemplo, la versión optimizada de este código podría resultar en
+ pasar un cero a hacer_algo_con() en el caso de que la variable a sea
+ modificada por alguna otra CPU, entre la instrucción "while" y la
+ llamada a hacer_algo_con().
+
+ De nuevo, use READ_ONCE() para evitar que el compilador haga esto:
+
+ while (tmp = READ_ONCE(a))
+ hacer_algo_con(tmp);
+
+ Tenga en cuenta que si el compilador se queda sin registros, podría
+ guardar tmp en la pila ("stack"). El overhead (coste en eficiencia) de
+ este guardado y posterior restauración es por lo que los compiladores
+ recargan las variables. Hacerlo es perfectamente seguro para código de
+ subproceso único, por lo que debe informar al compilador sobre los
+ casos donde no sea seguro.
+
+ (*) El compilador está en su derecho de omitir una carga por completo si
+ sabe cual será su valor. Por ejemplo, si el compilador puede probar
+ que el valor de la variable 'a' siempre es cero, puede optimizar este
+ código:
+
+ while (tmp = a)
+ hacer_algo_con(tmp);
+
+ En esto:
+
+ do { } while (0);
+
+ Esta transformación es una victoria para un código de un solo
+ subproceso, porque se deshace de una carga y un branch. El problema es
+ que el compilador llevará a cabo su prueba asumiendo que la CPU actual
+ es la única actualizando la variable 'a'. Si la variable 'a' es
+ compartida, entonces la prueba del compilador será errónea. Use
+ READ_ONCE() para decirle al compilador que no sabe tanto como cree:
+
+ while (tmp = READ_ONCE(a))
+ hacer_algo_con(tmp);
+
+ Pero, por favor, tenga en cuenta que el compilador también está
+ observando de cerca lo que usted hace con el valor después de
+ READ_ONCE(). Por ejemplo, suponga que Ud. hace lo siguiente y MAX es
+ una macro de preprocesador con el valor 1:
+
+ while ((tmp = READ_ONCE(a)) % MAX)
+ hacer_algo_con(tmp);
+
+ Entonces el compilador sabe que el resultado del operador "%" aplicado
+ a MAX siempre será cero, nuevamente permitiendo que el compilador
+ optimice el código hasta su casi inexistencia. (Aún se cargará desde
+ la variable 'a'.)
+
+ (*) De manera similar, el compilador tiene derecho a omitir un store por
+ completo si sabe que la variable ya tiene el valor almacenado.
+ Nuevamente, el compilador asume que la CPU actual es la única que
+ almacena la variable, lo que puede hacer que el compilador haga
+ algo incorrecto para las variables compartidas. Por ejemplo, suponga
+ que tiene lo siguiente:
+
+ a = 0;
+ ... Código que no almacena la variable a ...
+ a = 0;
+
+ El compilador observa que el valor de la variable 'a' ya es cero, por
+ lo que bien podría omitir el segundo store. Esto supondría una fatal
+ sorpresa, si alguna otra CPU hubiera almacenado la variable 'a'
+ mientras tanto.
+
+ Use WRITE_ONCE() para evitar que el compilador haga este tipo de
+ suposición equivocada:
+
+ WRITE_ONCE(a, 0);
+ ... Código que no almacena la variable a ...
+ WRITE_ONCE(a, 0);
+
+ (*) El compilador tiene derecho a reordenar los accesos a memoria a menos
+ que le diga que no. Por ejemplo, considere la siguiente interacción
+ entre el código de nivel de proceso y un controlador de interrupción:
+
+ void nivel_de_procesamiento(void)
+ {
+ msg = ACQUIRE_mensaje();
+ flag = true;
+ }
+
+ void controlador_interrupcion(void)
+ {
+ if (flag)
+ procesar_mensaje(msg);
+ }
+
+ No hay nada que impida que el compilador transforme
+ nivel_de_procesamiento() a lo siguiente, que de hecho, bien podría ser
+ una victoria para código de un solo subproceso:
+
+ void nivel_de_procesamiento(void)
+ {
+ flag = true;
+ msg = ACQUIRE_mensaje();
+ }
+
+ Si la interrupción ocurre entre estas dos declaraciones, entonces
+ controlador_interrupcion() podría recibir un mensaje ilegible. Use
+ READ_ONCE() para evitar esto de la siguiente manera:
+
+ void nivel_de_procesamiento(void)
+ {
+ WRITE_ONCE(msg, ACQUIRE_mensaje());
+ WRITE_ONCE(flag, true);
+ }
+
+ void controlador_interrupcion(void)
+ {
+ if (READ_ONCE(flag))
+ procesar_mensaje(READ_ONCE(msg));
+ }
+
+ Tenga en cuenta que los envoltorios ("wrappers") READ_ONCE() y
+ WRITE_ONCE() en controlador_interrupcion() son necesarios si este
+ controlador de interrupciones puede ser interrumpido por algo que
+ también accede a 'flag' y 'msg', por ejemplo, una interrupción anidada
+ o un NMI. De lo contrario, READ_ONCE() y WRITE_ONCE() no son
+ necesarios en controlador_interrupcion() aparte de con fines de
+ documentación. (Tenga también en cuenta que las interrupciones
+ anidadas no ocurren típicamente en los kernels Linux modernos, de
+ hecho, si un controlador de interrupciones regresa con interrupciones
+ habilitadas, obtendrá un WARN_ONCE().)
+
+ Debe suponer que el compilador puede mover READ_ONCE() y WRITE_ONCE()
+ a código que no contiene READ_ONCE(), WRITE_ONCE(), barrier(), o
+ primitivas similares.
+
+ Este efecto también podría lograrse usando barrier(), pero READ_ONCE()
+ y WRITE_ONCE() son más selectivos: Con READ_ONCE() y WRITE_ONCE(), el
+ compilador solo necesita olvidar el contenido de ubicaciones de
+ memoria indicadas, mientras que con barrier() el compilador debe
+ descartar el valor de todas las ubicaciones de memoria que tiene
+ actualmente almacenadas en caché, en cualquier registro de la máquina.
+ Por supuesto, el compilador también debe respetar el orden en que
+ ocurren READ_ONCE() y WRITE_ONCE(), aunque la CPU, efectivamente, no
+ necesita hacerlo.
+
+ (*) El compilador tiene derecho a inventar stores para una variable,
+ como en el siguiente ejemplo:
+
+ if (a)
+ b = a;
+ else
+ b = 42;
+
+ El compilador podría ahorrar un branch al optimizar esto de la
+ siguiente manera:
+
+ b = 42;
+ if (a)
+ b = a;
+
+ En el código de un solo subproceso, esto no solo es seguro, sino que
+ también ahorra un branch. Desafortunadamente, en código concurrente,
+ esta optimización podría causar que alguna otra CPU vea un valor falso
+ de 42, incluso si la variable 'a' nunca fue cero, al cargar la
+ variable 'b'. Use WRITE_ONCE() para evitar esto de la siguiente
+ manera:
+
+ if (a)
+ WRITE_ONCE(b, a);
+ else
+ WRITE_ONCE(b, 42);
+
+ El compilador también puede inventar cargas. Estos casos suelen ser
+ menos perjudiciales, pero pueden dar como resultado "bouncing" de la
+ línea de caché y, por lo tanto, bajo rendimiento y escalabilidad.
+ Utilice READ_ONCE() para evitar cargas inventadas.
+
+ (*) Para ubicaciones de memoria alineadas cuyo tamaño les permita
+ acceder con una sola instrucción de referencia de memoria, evite el
+ "desgarro de la carga" (load tearing) y "desgarro del store" (store
+ tearing), en el que un solo gran acceso es reemplazado por múltiples
+ accesos menores. Por ejemplo, dada una arquitectura que tiene
+ instrucciones de almacenamiento de 16 bits con campos inmediatos de 7
+ bits, el compilador podría tener la tentación de usar dos
+ instrucciones inmediatas de almacenamiento de 16 bits para implementar
+ el siguiente store de 32 bits:
+
+ p = 0x00010002;
+
+ Tenga en cuenta que GCC realmente usa este tipo de optimización, lo
+ cual no es sorprendente dado que probablemente costaría más de dos
+ instrucciones el construir la constante y luego almacenarla. Por lo
+ tanto, esta optimización puede ser una victoria en un código de un
+ solo subproceso. De hecho, un error reciente (desde que se solucionó)
+ hizo que GCC usara incorrectamente esta optimización en un store
+ volátil. En ausencia de tales errores, el uso de WRITE_ONCE() evita el
+ desgarro del store en el siguiente ejemplo:
+
+ struct __attribute__((__packed__)) foo {
+ short a;
+ int b;
+ short c;
+ };
+ struct foo foo1, foo2;
+ ...
+
+ foo2.a = foo1.a;
+ foo2.b = foo1.b;
+ foo2.c = foo1.c;
+
+ Debido a que no hay envoltorios READ_ONCE() o WRITE_ONCE() y no
+ hay markings volátiles, el compilador estaría en su derecho de
+ implementar estas tres declaraciones de asignación como un par de
+ cargas de 32 bits, seguido de un par de stores de 32 bits. Esto
+ resultaría en una carga con desgarro en 'foo1.b' y store del desgarro
+ en 'foo2.b'. READ_ONCE() y WRITE_ONCE() nuevamente evitan el desgarro
+ en este ejemplo:
+
+ foo2.a = foo1.a;
+ WRITE_ONCE(foo2.b, READ_ONCE(foo1.b));
+ foo2.c = foo1.c;
+
+Aparte de esto, nunca es necesario usar READ_ONCE() y WRITE_ONCE() en una
+variable que se ha marcado como volátil. Por ejemplo, dado que 'jiffies'
+está marcado como volátil, nunca es necesario usar READ_ONCE(jiffies). La
+razón de esto es que READ_ONCE() y WRITE_ONCE() se implementan como
+conversiones volátiles, lo que no tiene efecto cuando su argumento ya está
+marcado como volátil.
+
+Tenga en cuenta que estas barreras del compilador no tienen un efecto
+directo en la CPU, que luego puede reordenar las cosas como quiera.
+
+
+BARRERAS DE MEMORIA DE LA CPU
+-----------------------------
+
+El kernel de Linux tiene siete barreras básicas de memoria de CPU:
+
+TIPO OBLIGATORIO SMP CONDICIONAL
+======================= =============== ===============
+GENERAL mb() smp_mb()
+WRITE wmb() smp_wmb()
+READ rmb() smp_rmb()
+DEPEDENCIA DE DIRECCIÓN READ_ONCE()
+
+
+Todas las barreras de memoria, excepto las barreras de dependencia de
+direcciones, implican una barrera del compilador. Las dependencias de
+direcciones no imponen ningún orden de compilación adicional.
+
+Además: en el caso de las dependencias de direcciones, se esperaría que el
+compilador emita las cargas en el orden correcto (por ejemplo, `a[b]`
+tendría que cargar el valor de b antes de cargar a[b]), sin embargo, no hay
+garantía alguna en la especificación de C sobre que el compilador no puede
+especular el valor de b (por ejemplo, es igual a 1) y carga a[b] antes que
+b (ej. tmp = a[1]; if (b != 1) tmp = a[b]; ). También existe el problema de
+que un compilador vuelva a cargar b después de haber cargado a[b], teniendo
+así una copia más nueva de b que a[b]. Aún no se ha conseguido un consenso
+acerca de estos problemas, sin embargo, el macro READ_ONCE() es un buen
+lugar para empezar a buscar.
+
+Las barreras de memoria SMP se reducen a barreras de compilador cuando se
+compila a monoprocesador, porque se supone que una CPU parecerá ser
+auto-consistente, y ordenará correctamente los accesos superpuestos
+respecto a sí misma. Sin embargo, consulte la subsección "Guests de
+máquinas virtuales" mas adelante.
+
+[!] Tenga en cuenta que las barreras de memoria SMP _deben_ usarse para
+controlar el orden de referencias a memoria compartida en sistemas SMP,
+aunque el uso de bloqueo en su lugar sea suficiente.
+
+Las barreras obligatorias no deben usarse para controlar los efectos de
+SMP, ya que dichas barreras imponen una sobrecarga innecesaria en los
+sistemas SMP y UP. Se pueden, sin embargo, usar para controlar los efectos
+MMIO en los accesos a través de ventanas E/S de memoria relajada. Estas
+barreras son necesarias incluso en sistemas que no son SMP, ya que afectan
+al orden en que las operaciones de memoria aparecen en un dispositivo, al
+prohibir tanto al compilador como a la CPU que sean reordenados.
+
+
+Hay algunas funciones de barrera más avanzadas:
+
+ (*) smp_store_mb(var, valor)
+
+ Asigna el valor a la variable y luego inserta una barrera de memoria
+ completa después de ella. No se garantiza insertar nada más que una
+ barrera del compilador en una compilación UP.
+
+
+ (*) smp_mb__before_atomic();
+ (*) smp_mb__after_atomic();
+
+ Estos se pueden usar con funciones RMW atómicas que no implican
+ barreras de memoria, pero donde el código necesita una barrera de
+ memoria. Ejemplos de funciones RMW atómicas que no implican una
+ barrera de memoria son, por ejemplo, agregar, restar, operaciones
+ condicionales (fallidas), funciones _relaxed, pero no atomic_read o
+ atomic_set. Un ejemplo común donde se puede requerir una barrera es
+ cuando se usan operaciones atómicas como referencia de contador.
+
+ Estos también se utilizan para funciones atómicas RMW bitop que no
+ implican una barrera de memoria (como set_bit y clear_bit).
+
+ Como ejemplo, considere una pieza de código que marca un objeto como
+ muerto y luego disminuye el contador de referencias del objeto:
+
+ obj->dead = 1;
+ smp_mb__before_atomic();
+ atomic_dec(&obj->ref_count);
+
+ Esto asegura que la marca de muerte en el objeto se perciba como
+ fijada *antes* de que disminuya el contador de referencia.
+
+ Consulte Documentation/atomic_{t,bitops}.txt para obtener más
+ información.
+
+
+ (*) dma_wmb();
+ (*) dma_rmb();
+ (*) dma_mb();
+
+ Estos son usados con memoria consistente para garantizar el orden de
+ escrituras o lecturas de memoria compartida accesible tanto para la
+ CPU como para un dispositivo compatible con DMA.
+
+ Por ejemplo, considere un controlador de dispositivo que comparte
+ memoria con otro dispositivo y usa un valor de estado del descriptor
+ para indicar si el descriptor pertenece al dispositivo o a la CPU, y
+ un "doorbell" (timbre, punto de acceso) para avisarle cuando haya
+ nuevos descriptores disponibles:
+
+ if (desc->status != DEVICE_OWN) {
+ /* no leer los datos hasta que tengamos el descriptor */
+ dma_rmb();
+
+ /* leer/modificar datos */
+ read_data = desc->data;
+ desc->data = write_data;
+
+ /* flush de modificaciones antes de la actualización de estado */
+ dma_wmb();
+
+ /* asignar propiedad */
+ desc->status = DEVICE_OWN;
+
+ /* notificar al dispositivo de nuevos descriptores */
+ writel(DESC_NOTIFY, doorbell);
+ }
+
+ El dma_rmb() nos permite garantizar que el dispositivo ha liberado su
+ propiedad antes de que leamos los datos del descriptor, y el dma_wmb()
+ permite garantizar que los datos se escriben en el descriptor antes de
+ que el dispositivo pueda ver que ahora tiene la propiedad. El dma_mb()
+ implica tanto un dma_rmb() como un dma_wmb(). Tenga en cuenta que, al
+ usar writel(), no se necesita un wmb() anterior para garantizar que
+ las escrituras de la memoria caché coherente se hayan completado antes
+ escribiendo a la región MMIO. El writel_relaxed() más barato no
+ proporciona esta garantía y no debe utilizarse aquí.
+
+ Consulte la subsección "Efectos de barrera de E/S del kernel" para
+ obtener más información sobre accesorios de E/S relajados y el archivo
+ Documentation/core-api/dma-api.rst para más información sobre memoria
+ consistente.
+
+ (*) pmem_wmb();
+
+ Es es para uso con memoria persistente para garantizar que los stores
+ para los que las modificaciones se escriben en el almacenamiento
+ persistente llegaron a dominio de durabilidad de la plataforma.
+
+ Por ejemplo, después de una escritura no temporal en la región pmem,
+ usamos pmem_wmb() para garantizar que los stores hayan alcanzado el
+ dominio de durabilidad de la plataforma. Esto garantiza que los stores
+ han actualizado el almacenamiento persistente antes de cualquier
+ acceso a datos o transferencia de datos causada por instrucciones
+ posteriores. Esto es además del orden realizado por wmb().
+
+ Para la carga desde memoria persistente, las barreras de memoria de
+ lectura existentes son suficientes para garantizar el orden de
+ lectura.
+
+ (*) io_stop_wc();
+
+ Para accesos a memoria con atributos de combinación de escritura (por
+ ejemplo, los devueltos por ioremap_wc(), la CPU puede esperar a que
+ los accesos anteriores se junten con posteriores. io_stop_wc() se
+ puede utilizar para evitar la combinación de accesos a memoria de
+ de escritura antes de esta macro, con los posteriores, cuando dicha
+ espera tenga implicaciones en el rendimiento.
+
+=========================================
+BARRERAS DE MEMORIA IMPLÃCITAS DEL KERNEL
+=========================================
+
+Algunas de las otras funciones en el kernel Linux implican barreras de
+memoria, entre estas encontramos funciones de bloqueo y planificación
+("scheduling").
+
+Esta especificación es una garantía _mínima_; cualquier arquitectura
+particular puede proporcionar garantías más sustanciales, pero no se puede
+confiar en estas fuera de código específico de arquitectura.
+
+
+FUNCIONES DE ADQUISICIÓN DE CERROJO
+-----------------------------------
+
+El kernel Linux tiene una serie de abstracciones de bloqueo:
+
+ (*) spin locks (cerrojos en loop)
+ (*) R/W spin lock (cerrojos de escritura/lectura)
+ (*) mutex
+ (*) semáforos
+ (*) R/W semáforos
+
+En todos los casos existen variantes de las operaciones "ACQUIRE" y
+"RELEASE" para cada uno de ellos. Todas estas operaciones implican ciertas
+barreras:
+
+ (1) Implicaciones de la operación ACQUIRE:
+
+ Las operaciones de memoria emitidas después del ACQUIRE se completarán
+ después de que la operación ACQUIRE haya finalizado.
+
+ Las operaciones de memoria emitidas antes de ACQUIRE pueden
+ completarse después que la operación ACQUIRE se ha completado.
+
+ (2) Implicaciones de la operación RELEASE:
+
+ Las operaciones de memoria emitidas antes de la RELEASE se
+ completarán antes de que la operación de RELEASE se haya completado.
+
+ Las operaciones de memoria emitidas después de la RELEASE pueden
+ completarse antes de que la operación de RELEASE se haya completado.
+
+ (3) Implicación de ACQUIRE vs ACQUIRE:
+
+ Todas las operaciones ACQUIRE emitidas antes de otra operación
+ ACQUIRE serán completadas antes de esa operación ACQUIRE.
+
+ (4) Implicación de ACQUIRE vs RELEASE:
+
+ Todas las operaciones ACQUIRE emitidas antes de una operación RELEASE
+ serán completadas antes de la operación RELEASE.
+
+ (5) Implicación de ACQUIRE condicional fallido:
+
+ Ciertas variantes de bloqueo de la operación ACQUIRE pueden fallar, ya
+ sea debido a no poder obtener el bloqueo de inmediato, o debido a que
+ recibieron una señal de desbloqueo mientras dormían esperando que el
+ cerrojo estuviera disponible. Los fallos en cerrojos no implican
+ ningún tipo de barrera.
+
+[!] Nota: una de las consecuencias de que los cerrojos en ACQUIRE y RELEASE
+sean barreras unidireccionales, es que los efectos de las instrucciones
+fuera de una sección crítica pueden filtrarse al interior de la sección
+crítica.
+
+No se puede suponer que un ACQUIRE seguido de una RELEASE sea una barrera
+de memoria completa dado que es posible que un acceso anterior a ACQUIRE
+suceda después del ACQUIRE, y un acceso posterior a la RELEASE suceda antes
+del RELEASE, y los dos accesos puedan entonces cruzarse:
+
+ *A = a;
+ ACQUIRE M
+ RELEASE M
+ *B = b;
+
+puede ocurrir como:
+
+ ACQUIRE M, STORE *B, STORE *A, RELEASE M
+
+Cuando ACQUIRE y RELEASE son bloqueo de adquisición y liberación,
+respectivamente, este mismo orden puede ocurrir si el cerrojo ACQUIRE y
+RELEASE son para la misma variable de bloqueo, pero solo desde la
+perspectiva de otra CPU que no tiene ese bloqueo. En resumen, un ACQUIRE
+seguido de un RELEASE NO puede entenderse como una barrera de memoria
+completa.
+
+De manera similar, el caso inverso de un RELEASE seguido de un ACQUIRE no
+implica una barrera de memoria completa. Por lo tanto, la ejecución de la
+CPU de los tramos críticos correspondientes a la RELEASE y la ACQUIRE
+pueden cruzarse, de modo que:
+
+ *A = a;
+ RELEASE M
+ ACQUIRE N
+ *B = b;
+
+puede ocurrir como:
+
+ ACQUIRE N, STORE *B, STORE *A, RELEASE M
+
+Podría parecer que este nuevo orden podría introducir un punto muerto.
+Sin embargo, esto no puede suceder porque si tal punto muerto amenazara
+con suceder, el RELEASE simplemente se completaría, evitando así el
+interbloqueo ("deadlock", punto muerto).
+
+ ¿Por qué funciona esto?
+
+ Un punto clave es que solo estamos hablando de la CPU re-haciendo el
+ orden, no el compilador. Si el compilador (o, ya puestos, el
+ desarrollador) cambió las operaciones, un deadlock -podría- ocurrir.
+
+ Pero supongamos que la CPU reordenó las operaciones. En este caso, el
+ desbloqueo precede al bloqueo en el código ensamblador. La CPU
+ simplemente eligió intentar ejecutar primero la última operación de
+ bloqueo. Si hay un interbloqueo, esta operación de bloqueo simplemente
+ esperará (o tratará de dormir, pero hablaremos de eso más adelante). La
+ CPU eventualmente ejecutará la operación de desbloqueo (que precedió a la
+ operación de bloqueo en el código ensamblador), lo que desenmascará el
+ potencial punto muerto, permitiendo que la operación de bloqueo tenga
+ éxito.
+
+ Pero, ¿y si el cerrojo es un cerrojo que duerme ("sleeplock")? En tal
+ caso, el código intentará entrar al scheduler, donde eventualmente
+ encontrará una barrera de memoria, que forzará la operación de desbloqueo
+ anterior para completar, nuevamente desentrañando el punto muerto. Podría
+ haber una carrera de desbloqueo del sueño ("sleep-unlock race"), pero la
+ primitiva de bloqueo necesita resolver tales carreras correctamente en
+ cualquier caso.
+
+Es posible que los cerrojos y los semáforos no proporcionen ninguna
+garantía de orden en sistemas compilados en UP, por lo que no se puede
+contar con tal situación para lograr realmente nada en absoluto,
+especialmente con respecto a los accesos de E/S, a menos que se combinen
+con operaciones de inhabilitación de interrupciones.
+
+Consulte también la sección "Efectos de barrera adquiriendo intra-CPU".
+
+
+Como ejemplo, considere lo siguiente:
+
+ *A = a;
+ *B = b;
+ ACQUIRE
+ *C = c;
+ *D = d;
+ RELEASE
+ *E = e;
+ *F = f;
+
+La siguiente secuencia de eventos es aceptable:
+
+ ACQUIRE, {*F,*A}, *E, {*C,*D}, *B, RELEASE
+
+ [+] Tenga en cuenta que {*F,*A} indica un acceso combinado.
+
+Pero ninguno de los siguientes lo son:
+
+ {*F,*A}, *B, ACQUIRE, *C, *D, RELEASE, *E
+ *A, *B, *C, ACQUIRE, *D, RELEASE, *E, *F
+ *A, *B, ACQUIRE, *C, RELEASE, *D, *E, *F
+ *B, ACQUIRE, *C, *D, RELEASE, {*F,*A}, *E
+
+
+
+FUNCIONES DE DESACTIVACIÓN DE INTERRUPCIONES
+--------------------------------------------
+
+Las funciones que deshabilitan interrupciones (equivalentes a ACQUIRE) y
+habilitan interrupciones (equivalentes a RELEASE) actuarán únicamente como
+barrera del compilador. Por consiguiente, si la memoria o la E/S requieren
+barreras en tal situación, deben ser provistas por algún otro medio.
+
+
+FUNCIONES DE DORMIR Y DESPERTAR
+-------------------------------
+
+Dormir y despertar son eventos marcados ("flagged") en los datos globales
+que se pueden ver como una interacción entre dos piezas de datos: el estado
+de la task (hilo, proceso, tarea) que espera el evento y los datos globales
+utilizados para indicar el evento. Para asegurarse de que estos parezcan
+suceder en el orden correcto, las primitivas para comenzar el proceso de ir
+a dormir, y las primitivas para iniciar un despertar implican ciertas
+barreras.
+
+En primer lugar, el agente durmiente normalmente sigue algo similar a esta
+secuencia de eventos:
+
+ for (;;) {
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ if (evento_indicado)
+ break;
+ schedule(); // planificar
+ }
+
+Una barrera de memoria general se obtiene automáticamente mediante
+set_current_state() después de haber alterado el estado de la tarea:
+
+ CPU 1
+ ===============================
+ set_current_state(); // hacer_estado_actual()
+ smp_store_mb();
+ STORE current->state
+ <barrera general>
+ LOAD evento_indicado
+
+set_current_state() puede estar envuelto por:
+
+ prepare_to_wait(); // preparese_para_esperar();
+ prepare_to_wait_exclusive(); // prepararse_para_solo_esperar();
+
+que por lo tanto también implican una barrera de memoria general después de
+establecer el estado. Toda la secuencia anterior está disponible en varias
+formas, todas las cuales obtienen la barrera de memoria en el lugar
+correcto:
+
+ wait_event();
+ wait_event_interruptible();
+ wait_event_interruptible_exclusive();
+ wait_event_interruptible_timeout();
+ wait_event_killable();
+ wait_event_timeout();
+ wait_on_bit();
+ wait_on_bit_lock();
+
+
+En segundo lugar, el código que realiza una activación normalmente se
+asemeja a algo como esto:
+
+ evento_indicado = 1;
+ wake_up(&event_wait_queue); // despertar
+
+o:
+
+ evento_indicado = 1;
+ wake_up_process(event_daemon); // despertar proceso
+
+wake_up() ejecuta una barrera de memoria general si despierta algo. Si no
+despierta nada, entonces una barrera de memoria puede o no ser ejecutada;
+no debe confiar en ello. La barrera se produce antes del acceso al estado
+de la tarea. En particular, se encuentra entre el STORE para indicar el
+evento y el STORE para configurar TASK_RUNNING (hilo ejecutando):
+
+ CPU 1 (Durmiente) CPU 2 (Despertadora)
+ =============================== ===============================
+ set_current_state(); STORE evento_indicado
+ smp_store_mb(); wake_up();
+ STORE current->state ...
+ <barrera general> <barrera general>
+ LOAD evento_indicado if ((LOAD task->state) & TASK_NORMAL)
+ STORE task->state
+
+donde "task" es el subproceso que se está despertando y es igual al
+"current" (hilo actual) de la CPU 1.
+
+Para reiterar, se garantiza la ejecución de una barrera de memoria general
+mediante wake_up() si algo está realmente despierto, pero de lo contrario
+no existe tal garantía. Para entender esto, considere la siguiente
+secuencia de eventos, donde X e Y son ambos cero inicialmente:
+
+ CPU 1 CPU 2
+ =============================== ===============================
+ X = 1; Y = 1;
+ smp_mb(); wake_up();
+ LOAD Y LOAD X
+
+Si ocurre una reactivación ("wakeup"), una (al menos) de las dos cargas
+debe ver 1. Si, por otro lado, no ocurre una reactivación, ambas cargas
+pueden ver 0.
+
+wake_up_process() siempre ejecuta una barrera de memoria general. La
+barrera, de nuevo, ocurre antes de que se acceda al estado del hilo. En
+particular, si wake_up(), en el fragmento anterior, fuera reemplazado por
+una llamada a wake_up_process(), las dos cargas verían 1, garantizado.
+
+Las funciones de activación disponibles incluyen:
+
+ complete();
+ wake_up();
+ wake_up_all();
+ wake_up_bit();
+ wake_up_interruptible();
+ wake_up_interruptible_all();
+ wake_up_interruptible_nr();
+ wake_up_interruptible_poll();
+ wake_up_interruptible_sync();
+ wake_up_interruptible_sync_poll();
+ wake_up_locked();
+ wake_up_locked_poll();
+ wake_up_nr();
+ wake_up_poll();
+ wake_up_process();
+
+En términos de orden de la memoria, todas estas funciones proporcionan las
+mismas garantías que un wake_up() (o más fuertes).
+
+[!] Tenga en cuenta que las barreras de la memoria implicadas por el
+durmiente y el despierto _no_ ordenan varios stores antes del despertar con
+respecto a cargas de los valores guardados después de que el durmiente haya
+llamado a set_current_state(). Por ejemplo, si el durmiente hace:
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (evento_indicado)
+ break;
+ __set_current_state(TASK_RUNNING);
+ hacer_algo(my_data);
+
+y el que despierta hace:
+
+ my_data = valor;
+ evento_indicado = 1;
+ wake_up(&event_wait_queue);
+
+no existe garantía de que el cambio a event_indicated sea percibido por
+el durmiente de manera que venga después del cambio a my_data. En tal
+circunstancia, el código en ambos lados debe sacar sus propias barreras de
+memoria entre los separados accesos a datos. Por lo tanto, el durmiente
+anterior debería hacer:
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (evento_indicado) {
+ smp_rmb();
+ hacer_algo(my_data);
+ }
+
+y el que despierta debería hacer:
+
+ my_data = value;
+ smp_wmb();
+ evento_indicado = 1;
+ wake_up(&event_wait_queue);
+
+FUNCIONES VARIAS
+----------------
+
+Otras funciones que implican barreras:
+
+ (*) schedule() y similares implican barreras completas de memoria.
+
+
+========================================
+EFECTOS DE BARRERA ADQUIRIENDO INTRA-CPU
+========================================
+
+En los sistemas SMP, las primitivas de bloqueo proveen una forma más
+sustancial de barrera: una que afecta el orden de acceso a la memoria en
+otras CPU, dentro del contexto de conflicto en cualquier bloqueo en
+particular.
+
+
+ADQUISICIÓN VS ACCESOS A MEMORIA
+--------------------------------
+
+Considere lo siguiente: el sistema tiene un par de spinlocks (M) y (Q), y
+tres CPU; entonces la siguiente secuencia de eventos debería ocurrir:
+
+ CPU 1 CPU 2
+ =============================== ===============================
+ WRITE_ONCE(*A, a); WRITE_ONCE(*E, e);
+ ACQUIRE M ACQUIRE Q
+ WRITE_ONCE(*B, b); WRITE_ONCE(*F, f);
+ WRITE_ONCE(*C, c); WRITE_ONCE(*G, g);
+ RELEASE M RELEASE Q
+ WRITE_ONCE(*D, d); WRITE_ONCE(*H, h);
+
+Entonces no hay garantía sobre en qué orden verá la CPU 3 los accesos a *A
+hasta que *H ocurra, además de las restricciones impuestas por los bloqueos
+separados en las distintas CPUs. Podría, por ejemplo, ver:
+
+ *E, ACQUIRE M, ACQUIRE Q, *G, *C, *F, *A, *B, RELEASE Q, *D, *H, RELEASE M
+
+Pero no verá ninguno de:
+
+ *B, *C or *D preceding ACQUIRE M
+ *A, *B or *C following RELEASE M
+ *F, *G or *H preceding ACQUIRE Q
+ *E, *F or *G following RELEASE Q
+
+========================================
+¿DÓNDE SE NECESITAN BARRERAS DE MEMORIA?
+========================================
+
+Bajo operación normal, el re-ordenamiento de una operación de memoria
+generalmente no va a suponer un problema, ya que para una pieza de código
+lineal de un solo subproceso seguirá pareciendo que funciona correctamente,
+incluso si está en un kernel SMP. Existen, sin embargo, cuatro
+circunstancias en las que reordenar definitivamente _podría_ ser un
+problema:
+
+ (*) Interacción entre procesadores.
+
+ (*) Operaciones atómicas.
+
+ (*) Acceso a dispositivos.
+
+ (*) Interrupciones.
+
+
+INTERACCIÓN ENTRE PROCESADORES
+------------------------------
+
+Cuando se da un sistema con más de un procesador, más de una CPU en el
+sistema puede estar trabajando en el mismo conjunto de datos al mismo
+tiempo. Esto puede causar problemas de sincronización, y la forma habitual
+de tratar con estos es utilizar cerrojos. Sin embargo, los cerrojos son
+bastante caros, por lo que puede ser preferible operar sin el uso de un
+cerrojo a ser posible. En cuyo caso, es posible que las operaciones que
+afectan a ambas CPU deban ordenarse cuidadosamente para evitar un
+funcionamiento incorrecto.
+
+Considere, por ejemplo, la ruta lenta del semáforo R/W. Aquí hay un proceso
+de espera en cola del semáforo, en virtud de que tiene una parte de su pila
+vinculada a la lista de procesos en espera del semáforo:
+
+ struct rw_semaphore {
+ ...
+ spinlock_t lock;
+ struct list_head waiters;
+ };
+
+ struct rwsem_waiter {
+ struct list_head list;
+ struct task_struct *task;
+ };
+
+Para despertar a un proceso que espera ("waiter") en particular, las
+funciones up_read() o up_write() tienen que:
+
+ (1) leer el siguiente puntero del registro de este proceso que espera,
+ para saber dónde está el registro del siguiente waiter;
+
+ (2) leer el puntero a la estructura de tareas del waiter;
+
+ (3) borrar el puntero de la tarea para decirle al waiter que se le ha dado
+ el semáforo;
+
+ (4) llamar a wake_up_process() en la tarea; y
+
+ (5) liberar la referencia retenida en la estructura de tareas del waiter.
+
+En otras palabras, tiene que realizar esta secuencia de eventos:
+
+ LOAD waiter->list.next;
+ LOAD waiter->task;
+ STORE waiter->task;
+ CALL wakeup
+ RELEASE task
+
+y si alguno de estos pasos ocurre fuera de orden, entonces todo puede que
+funcione defectuosamente.
+
+Una vez que se ha puesto en cola y soltado el bloqueo de semáforo, el
+proceso que espera no consigue el candado de nuevo; en cambio, solo espera
+a que se borre su puntero de tarea antes de continuar. Dado que el registro
+está en la pila del proceso que espera, esto significa que si el puntero de
+la tarea se borra _antes_ de que se lea el siguiente puntero de la lista,
+otra CPU podría comenzar a procesar el proceso que espera y podría romper
+el stack del proceso que espera antes de que la función up*() tenga la
+oportunidad de leer el puntero que sigue.
+
+Considere entonces lo que podría suceder con la secuencia de eventos
+anterior:
+
+ CPU 1 CPU 2
+ =============================== ===============================
+ down_xxx()
+ Poner waiter en la "queue" (cola)
+ Dormir
+ up_yyy()
+ LOAD waiter->task;
+ STORE waiter->task;
+ Despertado por otro evento
+ <preempt>
+ Reanudar el procesamiento
+ down_xxx() regresa
+ llamada a foo()
+ foo() estropea *waiter
+ </preempt>
+ LOAD waiter->list.next;
+ --- OOPS ---
+
+Esto podría solucionarse usando el bloqueo de semáforo, pero luego la
+función down_xxx() tiene que obtener innecesariamente el spinlock
+nuevamente, después de ser despertado el hilo.
+
+La forma de lidiar con esto es insertar una barrera de memoria SMP general:
+
+ LOAD waiter->list.next;
+ LOAD waiter->task;
+ smp_mb();
+ STORE waiter->task;
+ CALL wakeup
+ RELEASE task
+
+En este caso, la barrera garantiza que todos los accesos a memoria antes de
+la barrera parecerán suceder antes de todos los accesos a memoria después
+de dicha barrera con respecto a las demás CPU del sistema. _No_ garantiza
+que todos los accesos a memoria antes de la barrera se completarán en el
+momento en que la instrucción de la barrera en sí se complete.
+
+En un sistema UP, donde esto no sería un problema, la función smp_mb() es
+solo una barrera del compilador, asegurándose así de que el compilador
+emita las instrucciones en el orden correcto sin realmente intervenir en la
+CPU. Como solo hay un CPU, la lógica de orden de dependencias de esa CPU se
+encargará de todo lo demás.
+
+
+OPERACIONES ATÓMICAS
+--------------------
+
+Si bien son, técnicamente, consideraciones de interacción entre
+procesadores, las operaciones atómicas se destacan especialmente porque
+algunas de ellas implican barreras de memoria completa y algunas otras no,
+pero se confía mucho en ellos en su conjunto a lo largo del kernel.
+
+Consulte Documentation/atomic_t.txt para obtener más información.
+
+
+ACCESO A DISPOSITIVOS
+---------------------
+
+Un driver puede ser interrumpido por su propia rutina de servicio de
+interrupción y, por lo tanto, las dos partes del driver pueden interferir
+con los intentos de controlar o acceder al dispositivo.
+
+Esto puede aliviarse, al menos en parte, desactivando las interrupciones
+locales (una forma de bloqueo), de modo que las operaciones críticas sean
+todas contenidas dentro la sección de interrupción desactivada en el
+controlador. Mientras la interrupción del driver está ejecutando la rutina,
+es posible que el "core" del controlador no se ejecute en la misma CPU y no
+se permita que su interrupción vuelva a ocurrir hasta que la interrupción
+actual haya sido resuelta, por lo tanto, el controlador de interrupción no
+necesita bloquearse contra esto.
+
+Sin embargo, considere un driver que estaba hablando con una tarjeta
+ethernet que tiene un registro de direcciones y un registro de datos. Si
+el core de ese controlador habla con la tarjeta estando en desactivación de
+interrupción y luego se invoca el controlador de interrupción del
+controlador:
+
+ IRQ LOCALES DESACTIVADAS
+ writew(ADDR, 3);
+ writew(DATA, y);
+ IRQ LOCALES ACTIVADAS
+ <interrupción>
+ writew(ADDR, 4);
+ q = readw(DATA);
+ </interrupción>
+
+El almacenamiento en el registro de datos puede ocurrir después del segundo
+almacenamiento en el registro de direcciones si las reglas de orden son lo
+suficientemente relajadas:
+
+ STORE *ADDR = 3, STORE *ADDR = 4, STORE *DATA = y, q = LOAD *DATA
+
+Si se relajan las reglas de orden, se debe asumir que los accesos
+realizados dentro de la sección con interrupción deshabilitada pueden
+filtrarse fuera de esta y pueden intercalarse con accesos realizados en una
+interrupción - y viceversa - a menos que se utilicenn barreras implícita o
+explícitas.
+
+Normalmente, esto no será un problema porque los accesos de E/S realizados
+dentro de tales secciones incluirán operaciones de carga síncronas en
+registros E/S estrictamente ordenados, que forman barreras de E/S
+implícitas.
+
+
+Una situación similar puede ocurrir entre una rutina de interrupción y dos
+rutinas ejecutándose en separadas CPU que se comunican entre sí. Si tal
+caso es probable, entonces se deben usar bloqueos de desactivación de
+interrupciones para garantizar el orden.
+
+
+=====================================
+ Efectos de barrera de E/S del kernel
+=====================================
+
+La interfaz con periféricos a través de accesos de E/S es profundamente
+específica para cada arquitectura y dispositivo. Por lo tanto, los drivers
+que son inherentemente no portátiles pueden depender de comportamientos
+específicos de sus sistemas de destino, con el fin de lograr la
+sincronización de la manera más ligera posible. Para drivers que deseen ser
+portátiles entre múltiples arquitecturas e implementaciones de bus, el
+kernel ofrece una serie de funciones de acceso que proporcionan varios
+grados de garantías de orden:
+
+ (*) readX(), writeX():
+
+ Las funciones de acceso MMIO readX() y writeX() usan un puntero al
+ periférico al que se accede como un parámetro __iomem *. para punteros
+ asignados los atributos de E/S predeterminados (por ejemplo, los
+ devueltos por ioremap()), las garantías de orden son las siguientes:
+
+ 1. Se ordenan todos los accesos readX() y writeX() a un mismo periférico
+ entre estos. Esto asegura que los registros de acceso MMIO por el
+ mismo subproceso de la CPU a un dispositivo en particular llegarán en
+ el orden del programa.
+
+ 2. Se ordena un writeX() emitido por un subproceso de CPU que contiene un
+ spinlock antes de un writeX() al mismo periférico desde otro
+ subproceso de CPU, si emitido después de una adquisición posterior del
+ mismo spinlock. Esto garantiza que ese registro MMIO escribe en un
+ dispositivo en particular, mientras que se obtiene un spinlock en un
+ orden consistente con las adquisiciones del cerrojo.
+
+ 3. Un writeX() por un subproceso de la CPU al periférico primero esperará
+ a la finalización de todas las escrituras anteriores en la memoria
+ emitidas por, o bien propagadas por, el mismo subproceso. Esto asegura
+ que las escrituras de la CPU a un búfer DMA de salida asignadas por
+ dma_alloc_coherent() serán visibles para un motor ("engine") DMA
+ cuando la CPU escriba en sus registros de control MMIO, para activar
+ la transferencia.
+
+ 4. Un readX() de un subproceso del CPU, desde el periférico, se
+ completará antes de que cualquier lectura subsiguiente de memoria por
+ el mismo subproceso pueda comenzar. Esto asegura que las lecturas de
+ la CPU desde un búfer DMA entrantes asignadas por
+ dma_alloc_coherent(), no verán datos obsoletos después de leer el
+ registro de estado MMIO del motor DMA, para establecer que la
+ transferencia DMA se haya completado.
+
+ 5. Un readX() por un subproceso del CPU, desde el periférico, se
+ completará antes de que cualquier bucle delay() subsiguiente pueda
+ comenzar a ejecutarse en el mismo subproceso. Esto asegura que dos
+ escrituras del CPU a registros MMIO en un periférico llegarán al menos
+ con 1us de diferencia, si la primera escritura se lee inmediatamente
+ de vuelta con readX() y se llama a udelay(1) antes del segundo
+ writeX():
+
+ writel(42, DEVICE_REGISTER_0); // Llega al dispositivo ...
+ readl(DEVICE_REGISTER_0);
+ udelay(1);
+ writel(42, DEVICE_REGISTER_1); // al menos 1us antes de esto....
+
+Las propiedades de orden de los punteros __iomem obtenidos con valores de
+atributos que no sean los valores por defecto (por ejemplo, los devueltos
+por ioremap_wc()) son específicos de la arquitectura subyacente y, por lo
+tanto, las garantías enumeradas anteriormente no pueden por lo general ser
+aseguradas para accesos a este tipo de "mappings" (asignaciones).
+
+ (*) readX_relaxed(), writeX_relaxed():
+
+ Son similares a readX() y writeX(), pero proporcionan una garantía de
+ orden de memoria más débil. Específicamente, no garantizan orden con
+ respecto al bloqueo, los accesos normales a la memoria o los bucles
+ delay() (es decir, los puntos 2-5 arriba) pero todavía se garantiza que
+ se ordenarán con respecto a otros accesos desde el mismo hilo de la CPU,
+ al mismo periférico, cuando se opera en punteros __iomem asignados con el
+ valor predeterminado para los atributos de E/S.
+
+ (*) readsX(), writesX():
+
+ Los puntos de entrada readsX() y writesX() MMIO están diseñados para
+ acceder FIFOs mapeados en memoria y basados en registros que residen en
+ periféricos, que no son capaces de realizar DMA. Por tanto, sólo
+ proporcionan garantías de orden readX_relaxed() y writeX_relaxed(), como
+ se documentó anteriormente.
+
+ (*) inX(), outX():
+
+ Los puntos de entrada inX() y outX() están destinados a acceder a mapas
+ de puertos "legacy" (antiguos) de periféricos de E/S, que pueden requerir
+ instrucciones especiales en algunas arquitecturas (especialmente, en
+ x86). El número de puerto del periférico que se está accedido se pasa
+ como un argumento.
+
+ Dado que muchas arquitecturas de CPU acceden finalmente a estos
+ periféricos a través de un mapeo interno de memoria virtual, las
+ garantías de orden portátiles proporcionadas por inX() y outX() son las
+ mismas que las proporcionadas por readX() y writeX(), respectivamente, al
+ acceder a una asignación con los valores de atributos de E/S
+ predeterminados (los que haya por defecto).
+
+ Los drivers de dispositivos pueden esperar que outX() emita una
+ transacción de escritura no publicada, que espera una respuesta de
+ finalización del periférico de E/S antes de regresar. Esto no está
+ garantizado por todas las arquitecturas y por lo tanto no forma parte de
+ la semántica de orden portátil.
+
+ (*) insX(), outsX():
+
+ Como arriba, los puntos de entrada insX() y outsX() proporcionan el mismo
+ orden garantizado por readsX() y writesX() respectivamente, al acceder a
+ un mapping con los atributos de E/S predeterminados.
+
+ (*) ioreadX(), iowriteX():
+
+ Estos funcionarán adecuadamente para el tipo de acceso que realmente están
+ haciendo, ya sea inX()/outX() o readX()/writeX().
+
+Con la excepción de los puntos de entrada (insX(), outsX(), readsX() y
+writesX()), todo lo anterior supone que el periférico subyacente es
+little-endian y, por lo tanto, realizará operaciones de intercambio de
+bytes en arquitecturas big-endian.
+
+
+===========================================
+MODELO DE ORDEN MÃNIMO DE EJECUCIÓN ASUMIDO
+===========================================
+
+Debe suponerse que la CPU conceptual está débilmente ordenada, pero que
+mantiene la apariencia de causalidad del programa con respecto a sí misma.
+Algunas CPU (como i386 o x86_64) están más limitadas que otras (como
+powerpc o frv), por lo que el caso más relajado (es decir, DEC Alpha) se
+debe asumir fuera de código específico de arquitectura.
+
+Esto significa que se debe considerar que la CPU ejecutará su flujo de
+instrucciones en el orden que se quiera - o incluso en paralelo - siempre
+que si una instrucción en el flujo depende de una instrucción anterior,
+entonces dicha instrucción anterior debe ser lo suficientemente completa[*]
+antes de que la posterior instrucción puede proceder; en otras palabras:
+siempre que la apariencia de causalidad se mantenga.
+
+ [*] Algunas instrucciones tienen más de un efecto, como cambiar el
+ código de condición, cambio de registros o cambio de memoria - y
+ distintas instrucciones pueden depender de diferentes efectos.
+
+Una CPU puede también descartar cualquier secuencia de instrucciones que
+termine sin tener efecto final. Por ejemplo, si dos instrucciones
+adyacentes cargan un valor inmediato en el mismo registro, la primera puede
+descartarse.
+
+
+De manera similar, se debe suponer que el compilador podría reordenar la
+corriente de instrucciones de la manera que crea conveniente, nuevamente
+siempre que la apariencia de causalidad se mantenga.
+
+
+=====================================
+EFECTOS DE LA MEMORIA CACHÉ DE LA CPU
+=====================================
+
+La forma en que se perciben las operaciones de memoria caché en todo el
+sistema se ve afectada, hasta cierto punto, por los cachés que se
+encuentran entre las CPU y la memoria, y por el sistema de coherencia en
+memoria que mantiene la consistencia de estado en el sistema.
+
+En cuanto a la forma en que una CPU interactúa con otra parte del sistema a
+través del caché, el sistema de memoria tiene que incluir los cachés de la
+CPU y barreras de memoria, que en su mayor parte actúan en la interfaz
+entre la CPU y su caché (las barreras de memoria lógicamente actúan sobre
+la línea de puntos en el siguiente diagrama):
+
+ <--- CPU ---> : <----------- Memoria ----------->
+ :
+ +--------+ +--------+ : +--------+ +-----------+
+ | Core | | Cola | : | Cache | | | +---------+
+ | CPU | | de | : | CPU | | | | |
+ | |--->| acceso |----->| |<-->| | | |
+ | | | a | : | | | |--->| Memoria |
+ | | | memoria| : | | | | | |
+ +--------+ +--------+ : +--------+ | Mecanismo | | |
+ : | de | +---------+
+ : | Coherencia|
+ : | de la | +--------+
+ +--------+ +--------+ : +--------+ | cache | | |
+ | Core | | Cola | : | Cache | | | | |
+ | CPU | | de | : | CPU | | |--->| Dispos |
+ | |--->| acceso |----->| |<-->| | | itivo |
+ | | | a | : | | | | | |
+ | | | memoria| : | | | | +--------+
+ +--------+ +--------+ : +--------+ +-----------+
+ :
+ :
+
+Aunque es posible que una carga o store en particular no aparezca fuera de
+la CPU que lo emitió, ya que puede haber sido satisfecha dentro del propio
+caché de la CPU, seguirá pareciendo como si el acceso total a la memoria
+hubiera tenido lugar para las otras CPUs, ya que los mecanismos de
+coherencia de caché migrarán la cacheline sobre la CPU que accede y se
+propagarán los efectos en caso de conflicto.
+
+El núcleo de la CPU puede ejecutar instrucciones en el orden que considere
+adecuado, siempre que parezca mantenerse la causalidad esperada del
+programa. Algunas de las instrucciones generan operaciones de carga y
+almacenamiento que luego van a la cola de accesos a memoria a realizar. El
+núcleo puede colocarlos en la cola en cualquier orden que desee, y
+continuar su ejecución hasta que se vea obligado a esperar que una
+instrucción sea completada.
+
+De lo que se ocupan las barreras de la memoria es de controlar el orden en
+que los accesos cruzan, desde el lado de la CPU, hasta el lado de memoria,
+y el orden en que los otros observadores perciben los efectos en el sistema
+que sucedan por esto.
+
+[!] Las barreras de memoria _no_ son necesarias dentro de una CPU
+determinada, ya que las CPU siempre ven sus propias cargas y stores como si
+hubieran sucedido en el orden del programa.
+
+[!] Los accesos a MMIO u otros dispositivos pueden pasar por alto el
+sistema de caché. Esto depende de las propiedades de la ventana de memoria
+a través de la cual se accede a los dispositivos y/o el uso de
+instrucciones especiales de comunicación con dispositivo que pueda tener la
+CPU.
+
+
+COHERENCIA DE CACHÉ FRENTE A DMA
+---------------------------------
+
+No todos los sistemas mantienen coherencia de caché con respecto a los
+dispositivos que realizan DMA. En tales casos, un dispositivo que intente
+DMA puede obtener datos obsoletos de la RAM, porque las líneas de caché
+"sucias" pueden residir en los cachés de varias CPU, y es posible que no
+se hayan vuelto a escribir en la RAM todavía. Para hacer frente a esto, la
+parte apropiada del kernel debe vaciar los bits superpuestos de caché en
+cada CPU (y tal vez también invalidarlos).
+
+Además, los datos enviados por DMA a RAM, por un dispositivo, pueden ser
+sobrescritos por líneas de caché sucias que se escriben de nuevo en la RAM
+desde el caché de una CPU, después de que el dispositivo haya puesto sus
+propios datos, o las líneas de caché presentes en el caché de la CPU pueden
+simplemente ocultar el hecho de que la memoria RAM se haya actualizado,
+hasta el momento en que la caché se descarta de la memoria caché de la CPU
+y se vuelve a cargar. Para hacer frente a esto, la parte apropiada del
+kernel debe invalidar los bits superpuestos del caché en cada CPU.
+
+Consulte Documentation/core-api/cachetlb.rst para obtener más información
+sobre administración de la memoria caché.
+
+
+COHERENCIA DE CACHÉ FRENTE A MMIO
+---------------------------------
+
+La E/S mapeada en memoria generalmente se lleva a cabo a través de
+ubicaciones de memoria que forman parte de una ventana del espacio de
+memoria de la CPU, que tiene diferentes propiedades asignadas que la
+ventana habitual dirigida a RAM.
+
+Entre dichas propiedades, suele existir el hecho de que tales accesos
+eluden el almacenamiento en caché por completo e ir directamente a los
+buses del dispositivo. Esto significa que los accesos MMIO pueden, en
+efecto, superar los accesos a la memoria caché que se emitieron
+anteriormente. Una barrera de memoria no es suficiente en tal caso, sino
+que el caché debe ser vaciado entre la escritura de la memoria caché, y el
+acceso MMIO, si los dos son de cualquier manera dependiente.
+
+
+=======================
+COSAS QUE HACEN LAS CPU
+=======================
+
+Un programador podría dar por sentado que la CPU realizará las operaciones
+de memoria exactamente en el orden especificado, de modo que si a la CPU se
+entrega, por ejemplo, el siguiente fragmento de código a ejecutar:
+
+ a = READ_ONCE(*A);
+ WRITE_ONCE(*B, b);
+ c = READ_ONCE(*C);
+ d = READ_ONCE(*D);
+ WRITE_ONCE(*E, e);
+
+esperarían entonces que la CPU complete la operación de memoria para cada
+instrucción antes de pasar a la siguiente, lo que lleva a una definida
+secuencia de operaciones vistas por observadores externos en el sistema:
+
+ LOAD *A, STORE *B, LOAD *C, LOAD *D, STORE *E.
+
+La realidad es, por supuesto, mucho más intrincada. Para muchas CPU y
+compiladores, la anterior suposición no se sostiene porque:
+
+ (*) es más probable que las cargas deban completarse de inmediato para
+ permitir progreso en la ejecución, mientras que los stores a menudo se
+ pueden aplazar sin problema;
+
+ (*) las cargas se pueden hacer especulativamente, y el resultado es
+ descartado si resulta innecesario;
+
+ (*) las cargas se pueden hacer de forma especulativa, lo que lleva a que
+ se haya obtenido el resultado en el momento equivocado de la secuencia
+ de eventos esperada;
+
+ (*) el orden de los accesos a memoria se puede reorganizar para promover
+ un mejor uso de los buses y cachés de la CPU;
+
+ (*) las cargas y los stores se pueden combinar para mejorar el rendimiento
+ cuando se habla con memoria o hardware de E/S, que puede realizar
+ accesos por lotes a ubicaciones adyacentes, reduciendo así los costes
+ de configuración de transacciones (la memoria y los dispositivos PCI
+ pueden ambos pueden hacer esto); y
+
+ (*) la caché de datos de la CPU puede afectar al orden, y mientras sus
+ mecanismos de coherencia pueden aliviar esto, una vez que el store
+ haya accedido al caché- no hay garantía de que la gestión de la
+ coherencia se propague en orden a otras CPU.
+
+Entonces, digamos que lo que otra CPU podría observar en el fragmento de
+código anterior es:
+
+ LOAD *A, ..., LOAD {*C,*D}, STORE *E, STORE *B
+
+ (Donde "LOAD {*C,*D}" es una carga combinada)
+
+
+Sin embargo, se garantiza que una CPU es autoconsistente: verá que sus
+ _propios_ accesos parecen estar correctamente ordenados, sin necesidad de
+barrera de memoria. Por ejemplo con el siguiente código:
+
+ U = READ_ONCE(*A);
+ WRITE_ONCE(*A, V);
+ WRITE_ONCE(*A, W);
+ X = READ_ONCE(*A);
+ WRITE_ONCE(*A, Y);
+ Z = READ_ONCE(*A);
+
+y asumiendo que no hay intervención de una influencia externa, se puede
+suponer que el resultado final se parecerá a:
+
+ U == el valor original de *A
+ X == W
+ Z == Y
+ *A == Y
+
+El código anterior puede hacer que la CPU genere la secuencia completa de
+accesos de memoria:
+
+ U=LOAD *A, STORE *A=V, STORE *A=W, X=LOAD *A, STORE *A=Y, Z=LOAD *A
+
+en ese orden, pero, sin intervención, la secuencia puede contener casi
+cualquier combinación de elementos combinados o descartados, siempre que la
+perspectiva del programa del mundo siga siendo consistente. Tenga en cuenta
+que READ_ONCE() y WRITE_ONCE() -no- son opcionales en el ejemplo anterior,
+ya que hay arquitecturas donde una CPU determinada podría reordenar cargas
+sucesivas en la misma ubicación. En tales arquitecturas, READ_ONCE() y
+WRITE_ONCE() hacen lo que sea necesario para evitar esto, por ejemplo, en
+Itanium los casts volátiles utilizados por READ_ONCE() y WRITE_ONCE() hacen
+que GCC emita las instrucciones especiales ld.acq y st.rel
+(respectivamente) que impiden dicha reordenación.
+
+El compilador también puede combinar, descartar o diferir elementos de la
+secuencia antes incluso de que la CPU los vea.
+
+Por ejemplo:
+
+ *A = V;
+ *A = W;
+
+puede reducirse a:
+
+ *A = W;
+
+ya que, sin una barrera de escritura o WRITE_ONCE(), puede que se asuma
+que el efecto del almacenamiento de V a *A se pierde. Similarmente:
+
+ *A = Y;
+ Z = *A;
+
+puede, sin una barrera de memoria o un READ_ONCE() y WRITE_ONCE(), esto
+sea reducido a:
+
+ *A = Y;
+ Z = Y;
+
+y la operación LOAD nunca aparezca fuera de la CPU.
+
+
+Y LUEGO ESTÃ EL ALFA
+--------------------
+
+La CPU DEC Alpha es una de las CPU más relajadas que existen. No solo eso,
+algunas versiones de la CPU Alpha tienen un caché de datos dividido, lo que
+les permite tener dos líneas de caché relacionadas semánticamente,
+actualizadas en momentos separados. Aquí es donde la barrera de dependencia
+de dirección realmente se vuelve necesaria, ya que se sincronizan ambos
+cachés con el sistema de coherencia de memoria, lo que hace que parezca un
+cambio en el puntero, frente a que los nuevos datos se produzcan en el
+orden correcto.
+
+Alpha define el modelo de memoria del kernel Linux, aunque a partir de
+v4.15, la adición al kernel de Linux de smp_mb() a READ_ONCE() en Alpha
+redujo en gran medida su impacto en el modelo de memoria.
+
+
+GUESTS DE MÃQUINAS VIRTUALES
+-----------------------------
+
+Los "guests" (invitados) que se ejecutan en máquinas virtuales pueden verse
+afectados por los efectos de SMP incluso si el "host" (huésped) en sí se
+compila sin compatibilidad con SMP. Este es un efecto de la interacción con
+un host SMP mientras ejecuta un kernel UP. El uso obligatorio de barreras
+para este caso de uso sería posible, pero a menudo no son óptimas.
+
+Para hacer frente a este caso de manera óptima, están disponibles macros de
+bajo nivel virt_mb() etc. Estas tienen el mismo efecto que smp_mb(), etc.
+cuando SMP está habilitado, pero generan código idéntico para sistemas SMP
+y no SMP. Por ejemplo, los invitados de máquinas virtuales debería usar
+virt_mb() en lugar de smp_mb() al sincronizar contra un (posiblemente SMP)
+anfitrión.
+
+Estos son equivalentes a sus contrapartes smp_mb() etc. en todos los demás
+aspectos, en particular, no controlan los efectos MMIO: para controlar los
+efectos MMIO, utilice barreras obligatorias.
+
+
+================
+EJEMPLOS DE USOS
+================
+
+BUFFERS CIRCULARES
+------------------
+
+Las barreras de memoria se pueden utilizar para implementar almacenamiento
+en búfer circular, sin necesidad de un cerrojo para serializar al productor
+con el consumidor. Vea:
+
+ Documentation/core-api/circular-buffers.rst
+
+para más detalles.
+
+
+===========
+REFERENCIAS
+===========
+
+Alpha AXP Architecture Reference Manual, Segunda Edición (por Sites & Witek,
+Digital Press)
+ Capítulo 5.2: Physical Address Space Characteristics
+ Capítulo 5.4: Caches and Write Buffers
+ Capítulo 5.5: Data Sharing
+ Capítulo 5.6: Read/Write Ordering
+
+AMD64 Architecture Programmer's Manual Volumen 2: System Programming
+ Capítulo 7.1: Memory-Access Ordering
+ Capítulo 7.4: Buffering and Combining Memory Writes
+
+ARM Architecture Reference Manual (ARMv8, for ARMv8-A architecture profile)
+ Capítulo B2: The AArch64 Application Level Memory Model
+
+IA-32 Intel Architecture Software Developer's Manual, Volumen 3:
+System Programming Guide
+ Capítulo 7.1: Locked Atomic Operations
+ Capítulo 7.2: Memory Ordering
+ Capítulo 7.4: Serializing Instructions
+
+The SPARC Architecture Manual, Version 9
+ Capítulo 8: Memory Models
+ Appendix D: Formal Specification of the Memory Models
+ Appendix J: Programming with the Memory Models
+
+Storage in the PowerPC (por Stone and Fitzgerald)
+
+UltraSPARC Programmer Reference Manual
+ Capítulo 5: Memory Accesses and Cacheability
+ Capítulo 15: Sparc-V9 Memory Models
+
+UltraSPARC III Cu User's Manual
+ Capítulo 9: Memory Models
+
+UltraSPARC IIIi Processor User's Manual
+ Capítulo 8: Memory Models
+
+UltraSPARC Architecture 2005
+ Capítulo 9: Memory
+ Appendix D: Formal Specifications of the Memory Models
+
+UltraSPARC T1 Supplement to the UltraSPARC Architecture 2005
+ Capítulo 8: Memory Models
+ Appendix F: Caches and Cache Coherency
+
+Solaris Internals, Core Kernel Architecture, p63-68:
+ Capítulo 3.3: Hardware Considerations for Locks and
+ Synchronization
+
+Unix Systems for Modern Architectures, Symmetric Multiprocessing and Caching
+for Kernel Programmers:
+ Capítulo 13: Other Memory Models
+
+Intel Itanium Architecture Software Developer's Manual: Volumen 1:
+ Sección 2.6: Speculation
+ Sección 4.4: Memory Access
diff --git a/Documentation/translations/sp_SP/process/coding-style.rst b/Documentation/translations/sp_SP/process/coding-style.rst
new file mode 100644
index 000000000000..a0261ba5b902
--- /dev/null
+++ b/Documentation/translations/sp_SP/process/coding-style.rst
@@ -0,0 +1,1315 @@
+.. include:: ../disclaimer-sp.rst
+
+:Original: :ref:`Documentation/process/coding-style.rst <submittingpatches>`
+:Translator: Carlos Bilbao <carlos.bilbao@amd.com>
+
+.. _sp_codingstyle:
+
+Estilo en el código del kernel Linux
+=====================================
+
+Este es un breve documento que describe el estilo preferido en el código
+del kernel Linux. El estilo de código es muy personal y no **forzaré** mi
+puntos de vista sobre nadie, pero esto vale para todo lo que tengo que
+mantener, y preferiría que para la mayoría de otras cosas también. Por
+favor, por lo menos considere los argumentos expuestos aquí.
+
+En primer lugar, sugeriría imprimir una copia de los estándares de código
+GNU, y NO leerlo. Quémelos, es un gran gesto simbólico.
+
+De todos modos, aquí va:
+
+
+1) Sangría
+-----------
+
+Las tabulaciones tienen 8 caracteres y, por lo tanto, las sangrías también
+tienen 8 caracteres. Hay movimientos heréticos que intentan hacer sangría
+de 4 (¡o incluso 2!) caracteres de longitud, y eso es similar a tratar de
+definir el valor de PI como 3.
+
+Justificación: La idea detrás de la sangría es definir claramente dónde
+comienza y termina un bloque de control. Especialmente, cuando ha estado
+buscando en su pantalla durante 20 horas seguidas, le resultará mucho más
+fácil ver cómo funciona la sangría si tiene sangrías grandes.
+
+Bueno, algunas personas dirán que tener sangrías de 8 caracteres hace que
+el código se mueva demasiado a la derecha y dificulta la lectura en una
+pantalla de terminal de 80 caracteres. La respuesta a eso es que si
+necesita más de 3 niveles de sangría, está en apuros de todos modos y
+debería arreglar su programa.
+
+En resumen, las sangrías de 8 caracteres facilitan la lectura y tienen la
+ventaja añadida de advertirle cuando está anidando sus funciones demasiado
+profundo. Preste atención a esa advertencia.
+
+La forma preferida de facilitar múltiples niveles de sangría en una
+declaración de switch es para alinear el ``switch`` y sus etiquetas
+``case`` subordinadas en la misma columna, en lugar de hacer ``doble
+sangría`` (``double-indenting``) en etiquetas ``case``. Por ejemplo:
+
+.. code-block:: c
+
+ switch (suffix) {
+ case 'G':
+ case 'g':
+ mem <<= 30;
+ break;
+ case 'M':
+ case 'm':
+ mem <<= 20;
+ break;
+ case 'K':
+ case 'k':
+ mem <<= 10;
+ fallthrough;
+ default:
+ break;
+ }
+
+No ponga varias declaraciones en una sola línea a menos que tenga algo que
+ocultar:
+
+.. code-block:: c
+
+ if (condición) haz_esto;
+ haz_otra_cosa;
+
+No use comas para evitar el uso de llaves:
+
+.. code-block:: c
+
+ if (condición)
+ haz_esto(), haz_eso();
+
+Siempre use llaves para múltiples declaraciones:
+
+.. code-block:: c
+
+ if (condición) {
+ haz_esto();
+ haz_eso();
+ }
+
+Tampoco ponga varias asignaciones en una sola línea. El estilo de código
+del kernel es súper simple. Evite las expresiones engañosas.
+
+
+Aparte de los comentarios, la documentación y excepto en Kconfig, los
+espacios nunca se utilizan para la sangría, y el ejemplo anterior se rompe
+deliberadamente.
+
+Consiga un editor decente y no deje espacios en blanco al final de las
+líneas.
+
+2) Rompiendo líneas y strings largos
+------------------------------------
+
+El estilo de código tiene todo que ver con la legibilidad y la
+mantenibilidad usando herramientas disponibles comúnmente.
+
+El límite preferido en la longitud de una sola línea es de 80 columnas.
+
+Las declaraciones de más de 80 columnas deben dividirse en partes, a menos
+que exceder las 80 columnas aumente significativamente la legibilidad y no
+oculte información.
+
+Los descendientes siempre son sustancialmente más cortos que el padre y
+se colocan sustancialmente a la derecha. Un estilo muy usado es alinear
+descendientes a un paréntesis de función abierto.
+
+Estas mismas reglas se aplican a los encabezados de funciones con una larga
+lista de argumentos.
+
+Sin embargo, nunca rompa los strings visibles para el usuario, como los
+mensajes printk, porque eso rompe la capacidad de grep a estos.
+
+
+3) Colocación de llaves y espacios
+----------------------------------
+
+El otro problema que siempre surge en el estilo C es la colocación de
+llaves. A diferencia del tamaño de la sangría, existen pocas razones
+técnicas para elegir una estrategia de ubicación sobre la otra, pero la
+forma preferida, como mostraron los profetas Kernighan y Ritchie, es poner
+la llave de apertura en la línea, y colocar la llave de cierre primero,
+así:
+
+.. code-block:: c
+
+ if (x es verdad) {
+ hacemos y
+ }
+
+Esto se aplica a todos los bloques de declaraciones que no son funciones
+(if, switch, for, while, do). Por ejemplo:
+
+.. code-block:: c
+
+ switch (action) {
+ case KOBJ_ADD:
+ return "add";
+ case KOBJ_REMOVE:
+ return "remove";
+ case KOBJ_CHANGE:
+ return "change";
+ default:
+ return NULL;
+ }
+
+Sin embargo, hay un caso especial, a saber, las funciones: tienen la llave
+de apertura al comienzo de la siguiente línea, así:
+
+.. code-block:: c
+
+ int funcion(int x)
+ {
+ cuerpo de la función
+ }
+
+Gente hereje de todo el mundo ha afirmado que esta inconsistencia es...
+bueno... inconsistente, pero todas las personas sensatas saben que
+(a) K&R tienen **razón** y (b) K&R tienen razón. Además, las funciones son
+especiales de todos modos (no puede anidarlas en C).
+
+Tenga en cuenta que la llave de cierre está vacía en su línea propia,
+**excepto** en los casos en que es seguida por una continuación de la misma
+declaración, es decir, un ``while`` en una sentencia do o un ``else`` en
+una sentencia if, como en:
+
+.. code-block:: c
+
+ do {
+ cuerpo del bucle do
+ } while (condition);
+
+y
+
+.. code-block:: c
+
+ if (x == y) {
+ ..
+ } else if (x > y) {
+ ...
+ } else {
+ ....
+ }
+
+Justificación: K&R.
+
+Además, tenga en cuenta que esta colocación de llaves también minimiza el
+número de líneas vacías (o casi vacías), sin pérdida de legibilidad. Así,
+como el suministro de nuevas líneas en su pantalla no es un recurso
+renovable (piense en pantallas de terminal de 25 líneas), tienes más líneas
+vacías para poner comentarios.
+
+No use llaves innecesariamente donde una sola declaración sea suficiente.
+
+.. code-block:: c
+
+ if (condition)
+ accion();
+
+y
+
+.. code-block:: none
+
+ if (condición)
+ haz_esto();
+ else
+ haz_eso();
+
+Esto no aplica si solo una rama de una declaración condicional es una sola
+declaración; en este último caso utilice llaves en ambas ramas:
+
+.. code-block:: c
+
+ if (condición) {
+ haz_esto();
+ haz_eso();
+ } else {
+ en_otro_caso();
+ }
+
+Además, use llaves cuando un bucle contenga más de una declaración simple:
+
+.. code-block:: c
+
+ while (condición) {
+ if (test)
+ haz_eso();
+ }
+
+3.1) Espacios
+*************
+
+El estilo del kernel Linux para el uso de espacios depende (principalmente)
+del uso de función versus uso de palabra clave. Utilice un espacio después
+de (la mayoría de) las palabras clave. Las excepciones notables son sizeof,
+typeof, alignof y __attribute__, que parecen algo así como funciones (y
+generalmente se usan con paréntesis en Linux, aunque no son requeridos en
+el idioma, como en: ``sizeof info`` después de que ``struct fileinfo info;``
+se declare).
+
+Así que use un espacio después de estas palabras clave::
+
+ if, switch, case, for, do, while
+
+pero no con sizeof, typeof, alignof, o __attribute__. Por ejemplo,
+
+.. code-block:: c
+
+
+ s = sizeof(struct file);
+
+No agregue espacios alrededor (dentro) de expresiones entre paréntesis.
+Este ejemplo es **malo**:
+
+.. code-block:: c
+
+
+ s = sizeof( struct file );
+
+Al declarar datos de puntero o una función que devuelve un tipo de puntero,
+el uso preferido de ``*`` es adyacente al nombre del dato o nombre de la
+función y no junto al nombre del tipo. Ejemplos:
+
+.. code-block:: c
+
+
+ char *linux_banner;
+ unsigned long long memparse(char *ptr, char **retptr);
+ char *match_strdup(substring_t *s);
+
+Use un espacio alrededor (a cada lado de) la mayoría de los operadores
+binarios y ternarios, como cualquiera de estos::
+
+ = + - < > * / % | & ^ <= >= == != ? :
+
+pero sin espacio después de los operadores unarios::
+
+ & * + - ~ ! sizeof typeof alignof __attribute__ defined
+
+sin espacio antes de los operadores unarios de incremento y decremento del
+sufijo::
+
+ ++ --
+
+y sin espacio alrededor de los operadores de miembros de estructura ``.`` y
+``->``.
+
+No deje espacios en blanco al final de las líneas. Algunos editores con
+``inteligente`` sangría insertarán espacios en blanco al comienzo de las
+nuevas líneas como sea apropiado, para que pueda comenzar a escribir la
+siguiente línea de código de inmediato. Sin embargo, algunos de estos
+editores no eliminan los espacios en blanco si finalmente no termina
+poniendo una línea de código allí, como si dejara una línea en blanco. Como
+resultado, termina con líneas que contienen espacios en blanco al final.
+
+Git le advertirá sobre los parches que introducen espacios en blanco al
+final y puede, opcionalmente, eliminar los espacios en blanco finales por
+usted; sin embargo, si se aplica una serie de parches, esto puede hacer que
+los parches posteriores de la serie fallen al cambiar sus líneas de
+contexto.
+
+
+4) Nomenclatura
+---------------
+
+C es un lenguaje espartano, y sus convenciones de nomenclatura deberían
+seguir su ejemplo. A diferencia de los programadores de Modula-2 y Pascal,
+los programadores de C no usan nombres cuquis como
+EstaVariableEsUnContadorTemporal. Un programador de C lo llamaría
+variable ``tmp``, que es mucho más fácil de escribir, y no es mas difícil
+de comprender.
+
+SIN EMBARGO, mientras que los nombres de mayúsculas y minúsculas están mal
+vistos, los nombres descriptivos para las variables globales son
+imprescindibles. Llamar a una función global ``foo`` es un delito.
+
+Una variable GLOBAL (para usar solo si **realmente** las necesita) necesita
+tener un nombre descriptivo, al igual que las funciones globales. Si tiene
+una función que cuenta el número de usuarios activos, debe llamar a esta
+``contar_usuarios_activos()`` o similar, **no** debe llamarlo ``cntusr()``.
+
+Codificar el tipo de una función en el nombre (lo llamado notación húngara)
+es estúpido: el compilador conoce los tipos de todos modos y puede
+verificar estos, y solo confunde al programador.
+
+Los nombres de las variables LOCALES deben ser breves y directos. Si usted
+tiene algún contador aleatorio de tipo entero, probablemente debería
+llamarse ``i``. Llamarlo ``loop_counter`` no es productivo, si no hay
+posibilidad de ser mal entendido. De manera similar, ``tmp`` puede ser casi
+cualquier tipo de variable que se utiliza para contener un valor temporal.
+
+Si tiene miedo de mezclar los nombres de las variables locales, tiene otro
+problema, que se denomina síndrome de
+función-crecimiento-desequilibrio-de-hormona. Vea el capítulo 6 (Funciones).
+
+Para nombres de símbolos y documentación, evite introducir nuevos usos de
+'master / slave' (maestro / esclavo) (o 'slave' independientemente de
+'master') y 'lista negra / lista blanca' (backlist / whitelist).
+
+Los reemplazos recomendados para 'maestro / esclavo' son:
+ '{primary,main} / {secondary,replica,subordinate}'
+ '{initiator,requester} / {target,responder}'
+ '{controller,host} / {device,worker,proxy}'
+ 'leader / follower'
+ 'director / performer'
+
+Los reemplazos recomendados para 'backlist / whitelist' son:
+ 'denylist / allowlist'
+ 'blocklist / passlist'
+
+Las excepciones para la introducción de nuevos usos son mantener en espacio
+de usuario una ABI/API, o al actualizar la especificación del código de un
+hardware o protocolo existente (a partir de 2020) que requiere esos
+términos. Para nuevas especificaciones, traduzca el uso de la terminología
+de la especificación al estándar de código del kernel donde sea posible.
+
+5) Typedefs
+-----------
+
+Por favor no use cosas como ``vps_t``.
+Es un **error** usar typedef para estructuras y punteros. cuando ve un
+
+.. code-block:: c
+
+
+ vps_t a;
+
+en el código fuente, ¿qué significa?
+En cambio, si dice
+
+.. code-block:: c
+
+ struct virtual_container *a;
+
+puede decir qué es ``a`` en realidad.
+
+Mucha gente piensa que los typedefs ``ayudan a la legibilidad``. No. Son
+útiles solamente para:
+
+ (a) objetos totalmente opacos (donde el typedef se usa activamente para
+ **ocultar** cuál es el objeto).
+
+ Ejemplo: ``pte_t`` etc. objetos opacos a los que solo puede acceder
+ usando las funciones de acceso adecuadas.
+
+ .. note::
+
+ La opacidad y las ``funciones de acceso`` no son buenas por sí
+ mismas. La razón por la que los tenemos para cosas como pte_t, etc.
+ es que hay real y absolutamente **cero** información accesible de
+ forma portátil allí.
+
+ (b) Tipos enteros claros, donde la abstracción **ayuda** a evitar
+ confusiones, ya sea ``int`` o ``long``.
+
+ u8/u16/u32 son definiciones tipográficas perfectamente correctas
+ aunque encajan en la categoría (d) mejor que aquí.
+
+ .. note::
+
+ De nuevo - debe haber una **razón** para esto. si algo es
+ ``unsigned long``, entonces no hay razón para hacerlo
+
+ typedef unsigned long mis_flags_t;
+
+ pero si hay una razón clara de por qué bajo ciertas circunstancias
+ podría ser un ``unsigned int`` y bajo otras configuraciones podría
+ ser ``unsigned long``, entonces, sin duda, adelante y use un typedef.
+
+ (c) cuando lo use para crear literalmente un tipo **nuevo** para
+ comprobación de tipos.
+
+ (d) Nuevos tipos que son idénticos a los tipos estándar C99, en ciertas
+ circunstancias excepcionales.
+
+ Aunque sólo costaría un corto período de tiempo para los ojos y
+ cerebro para acostumbrarse a los tipos estándar como ``uint32_t``,
+ algunas personas se oponen a su uso de todos modos.
+
+ Por lo tanto, los tipos ``u8/u16/u32/u64`` específicos de Linux y sus
+ equivalentes con signo, que son idénticos a los tipos estándar son
+ permitidos, aunque no son obligatorios en el nuevo código de su
+ elección.
+
+ Al editar código existente que ya usa uno u otro conjunto de tipos,
+ debe ajustarse a las opciones existentes en ese código.
+
+ (e) Tipos seguros para usar en el espacio de usuario.
+
+ En ciertas estructuras que son visibles para el espacio de usuario, no
+ podemos requerir tipos C99 y o utilizat el ``u32`` anterior. Por lo
+ tanto, usamos __u32 y tipos similares en todas las estructuras que se
+ comparten con espacio de usuario.
+
+Tal vez también haya otros casos, pero la regla básicamente debería ser
+NUNCA JAMÃS use un typedef a menos que pueda coincidir claramente con una
+de estas reglas.
+
+En general, un puntero o una estructura que tiene elementos que pueden
+ser razonablemente accedidos directamente, **nunca** deben ser un typedef.
+
+6) Funciones
+------------
+
+Las funciones deben ser cortas y dulces, y hacer una sola cosa. Deberían
+caber en una o dos pantallas de texto (el tamaño de pantalla ISO/ANSI es
+80x24, como todos sabemos), y hacer una cosa y hacerla bien.
+
+La longitud máxima de una función es inversamente proporcional a la
+complejidad y el nivel de sangría de esa función. Entonces, si tiene una
+función conceptualmente simple que es solo una larga (pero simple)
+declaración de case, donde tiene que hacer un montón de pequeñas cosas para
+un montón de diferentes casos, está bien tener una función más larga.
+
+Sin embargo, si tiene una función compleja y sospecha que un estudiante de
+primer año de secundaria menos que dotado podría no comprender de qué se
+trata la función, debe adherirse a los límites máximos tanto más de
+cerca. Use funciones auxiliares con nombres descriptivos (puede pedirle al
+compilador que los alinee si cree que es crítico para el rendimiento, y
+probablemente lo hará mejor de lo que usted hubiera hecho).
+
+Otra medida de la función es el número de variables locales. Estas no deben
+exceder de 5 a 10, o está haciendo algo mal. Piense de nuevo en la función
+y divida en partes más pequeñas. Un cerebro humano puede generalmente
+realiza un seguimiento de aproximadamente 7 cosas diferentes, cualquier
+elemento más y se confunde. Usted sabe que es brillante, pero tal vez le
+gustaría entender lo que hizo dentro de 2 semanas.
+
+En los archivos fuente, separe las funciones con una línea en blanco. Si la
+función es exportada, la macro **EXPORT** debería ponerse inmediatamente
+después de la función de cierre de línea de llave. Por ejemplo:
+
+.. code-block:: c
+
+ int sistema_corriendo(void)
+ {
+ return estado_sistema == SISTEMA_CORRIENDO;
+ }
+ EXPORT_SYMBOL(sistema_corriendo);
+
+6.1) Prototipos de funciones
+****************************
+
+En los prototipos de funciones, incluya nombres de parámetros con sus tipos
+de datos. Aunque esto no es requerido por el lenguaje C, se prefiere en
+Linux porque es una forma sencilla de añadir información valiosa para el
+lector.
+
+No utilice la palabra clave ``extern`` con declaraciones de función ya que
+esto hace las líneas más largas y no es estrictamente necesario.
+
+Al escribir prototipos de funciones, mantenga el `orden de los elementos regular
+<https://lore.kernel.org/mm-commits/CAHk-=wiOCLRny5aifWNhr621kYrJwhfURsa0vFPeUEm8mF0ufg@mail.gmail.com/>`_.
+Por ejemplo, usando este ejemplo de declaración de función::
+
+ __init void * __must_check action(enum magic value, size_t size, u8 count,
+ char *fmt, ...) __printf(4, 5) __malloc;
+
+El orden preferido de elementos para un prototipo de función es:
+
+- clase de almacenamiento (a continuación, ``static __always_inline``,
+ teniendo en cuenta que ``__always_inline`` es técnicamente un atributo
+ pero se trata como ``inline``)
+- atributos de clase de almacenamiento (aquí, ``__init`` -- es decir,
+ declaraciones de sección, pero también cosas como ``__cold``)
+- tipo de retorno (aquí, ``void *``)
+- atributos de tipo de retorno (aquí, ``__must_check``)
+- nombre de la función (aquí, ``action``)
+- parámetros de la función (aquí, ``(enum magic value, size_t size, u8 count, char *fmt, ...)``,
+ teniendo en cuenta que los nombres de los parámetros siempre deben
+ incluirse)
+- atributos de parámetros de función (aquí, ``__printf(4, 5)``)
+- atributos de comportamiento de la función (aquí, ``__malloc``)
+
+Tenga en cuenta que para una **definición** de función (es decir, el cuerpo
+real de la función), el compilador no permite atributos de parámetros de
+función después de parámetros de la función. En estos casos, deberán ir
+tras los atributos de clase (por ejemplo, tenga en cuenta el cambio de
+posición de ``__printf(4, 5)`` a continuación, en comparación con el
+ejemplo de **declaración** anterior)::
+
+ static __always_inline __init __printf(4, 5) void * __must_check action(enum magic value,
+ size_t size, u8 count, char *fmt, ...) __malloc
+ {
+ ...
+ }
+
+7) Salida centralizada de funciones
+-----------------------------------
+
+Aunque desaprobado por algunas personas, el equivalente de la instrucción
+goto es utilizado con frecuencia por los compiladores, en forma de
+instrucción de salto incondicional.
+
+La declaración goto es útil cuando una función sale desde múltiples
+ubicaciones y se deben realizar algunos trabajos comunes, como la limpieza.
+Si no se necesita limpieza, entonces simplemente haga return directamente.
+
+Elija nombres de etiquetas que digan qué hace el goto o por qué existe el
+goto. Un ejemplo de un buen nombre podría ser ``out_free_buffer:``
+(``salida_liberar_buffer``) si al irse libera ``buffer``. Evite usar
+nombres GW-BASIC como ``err1:`` y ``err2:``, ya que tendría que volver a
+numerarlos si alguna vez agrega o elimina rutas de salida, y hacen que sea
+difícil de verificar que sean correctos, de todos modos.
+
+La razón para usar gotos es:
+
+- Las declaraciones incondicionales son más fáciles de entender y seguir.
+- se reduce el anidamiento
+- errores al no actualizar los puntos de salida individuales al hacer
+ modificaciones son evitados
+- ahorra el trabajo del compilador de optimizar código redundante ;)
+
+.. code-block:: c
+
+ int fun(int a)
+ {
+ int result = 0;
+ char *buffer;
+
+ buffer = kmalloc(SIZE, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ if (condition1) {
+ while (loop1) {
+ ...
+ }
+ result = 1;
+ goto out_free_buffer;
+ }
+ ...
+ out_free_buffer:
+ kfree(buffer);
+ return result;
+ }
+
+Un tipo común de error a tener en cuenta es "un error de error" que es algo
+así:
+
+.. code-block:: c
+
+ err:
+ kfree(foo->bar);
+ kfree(foo);
+ return ret;
+
+El error en este código es que en algunas rutas de salida, ``foo`` es NULL.
+Normalmente la solución para esto es dividirlo en dos etiquetas de error
+``err_free_bar:`` y ``err_free_foo:``:
+
+.. code-block:: c
+
+ err_free_bar:
+ kfree(foo->bar);
+ err_free_foo:
+ kfree(foo);
+ return ret;
+
+Idealmente, debería simular errores para probar todas las rutas de salida.
+
+
+8) Comentarios
+--------------
+
+Los comentarios son buenos, pero también existe el peligro de comentar
+demasiado. NUNCA trate de explicar CÓMO funciona su código en un
+comentario: es mucho mejor escribir el código para que el
+**funcionamiento** sea obvio y es una pérdida de tiempo explicar código mal
+escrito.
+
+Generalmente, desea que sus comentarios digan QUÉ hace su código, no CÓMO.
+Además, trate de evitar poner comentarios dentro del cuerpo de una función:
+si la función es tan compleja que necesita comentar por separado partes de
+esta, probablemente debería volver al capítulo 6 una temporada. Puede
+hacer pequeños comentarios para notar o advertir sobre algo particularmente
+inteligente (o feo), pero trate de evitar el exceso. En su lugar, ponga los
+comentarios al principio de la función, diga a la gente lo que hace y
+posiblemente POR QUÉ hace esto.
+
+Al comentar las funciones de la API del kernel, utilice el formato
+kernel-doc. Consulte los archivos en :ref:`Documentation/doc-guide/ <doc_guide>`
+y ``scripts/kernel-doc`` para más detalles.
+
+El estilo preferido para comentarios largos (de varias líneas) es:
+
+.. code-block:: c
+
+ /*
+ * Este es el estilo preferido para comentarios
+ * multilínea en el código fuente del kernel Linux.
+ * Por favor, utilícelo constantemente.
+ *
+ * Descripción: Una columna de asteriscos en el lado izquierdo,
+ * con líneas iniciales y finales casi en blanco.
+ */
+
+Para archivos en net/ y drivers/net/, el estilo preferido para comentarios
+largos (multi-linea) es un poco diferente.
+
+.. code-block:: c
+
+ /* El estilo de comentario preferido para archivos en net/ y drivers/net
+ * se asemeja a esto.
+ *
+ * Es casi lo mismo que el estilo de comentario generalmente preferido,
+ * pero no hay una línea inicial casi en blanco.
+ */
+
+También es importante comentar los datos, ya sean tipos básicos o
+derivados. Para este fin, use solo una declaración de datos por línea (sin
+comas para múltiples declaraciones de datos). Esto le deja espacio para un
+pequeño comentario sobre cada elemento, explicando su uso.
+
+9) Has hecho un desastre
+---------------------------
+
+Está bien, todos lo hacemos. Probablemente un antiguo usuario de Unix le
+haya dicho que ``GNU emacs`` formatea automáticamente las fuentes C por
+usted, y ha notado que sí, lo hace, pero los por defecto que tiene son
+menos que deseables (de hecho, son peores que los aleatorios) escribiendo -
+un número infinito de monos escribiendo en GNU emacs nunca harán un buen
+programa).
+
+Por lo tanto, puede deshacerse de GNU emacs o cambiarlo y usar valores más
+sanos. Para hacer esto último, puede pegar lo siguiente en su archivo
+.emacs:
+
+.. code-block:: none
+
+ (defun c-lineup-arglist-tabs-only (ignored)
+ "Line up argument lists by tabs, not spaces"
+ (let* ((anchor (c-langelem-pos c-syntactic-element))
+ (column (c-langelem-2nd-pos c-syntactic-element))
+ (offset (- (1+ column) anchor))
+ (steps (floor offset c-basic-offset)))
+ (* (max steps 1)
+ c-basic-offset)))
+
+ (dir-locals-set-class-variables
+ 'linux-kernel
+ '((c-mode . (
+ (c-basic-offset . 8)
+ (c-label-minimum-indentation . 0)
+ (c-offsets-alist . (
+ (arglist-close . c-lineup-arglist-tabs-only)
+ (arglist-cont-nonempty .
+ (c-lineup-gcc-asm-reg c-lineup-arglist-tabs-only))
+ (arglist-intro . +)
+ (brace-list-intro . +)
+ (c . c-lineup-C-comments)
+ (case-label . 0)
+ (comment-intro . c-lineup-comment)
+ (cpp-define-intro . +)
+ (cpp-macro . -1000)
+ (cpp-macro-cont . +)
+ (defun-block-intro . +)
+ (else-clause . 0)
+ (func-decl-cont . +)
+ (inclass . +)
+ (inher-cont . c-lineup-multi-inher)
+ (knr-argdecl-intro . 0)
+ (label . -1000)
+ (statement . 0)
+ (statement-block-intro . +)
+ (statement-case-intro . +)
+ (statement-cont . +)
+ (substatement . +)
+ ))
+ (indent-tabs-mode . t)
+ (show-trailing-whitespace . t)
+ ))))
+
+ (dir-locals-set-directory-class
+ (expand-file-name "~/src/linux-trees")
+ 'linux-kernel)
+
+Esto hará que emacs funcione mejor con el estilo de código del kernel para
+C en archivos bajo ``~/src/linux-trees``.
+
+Pero incluso si no logra que emacs realice un formateo correcto, no todo
+está perdido: use ``indent``.
+
+Ahora bien, de nuevo, la sangría de GNU tiene la misma configuración de
+muerte cerebral que GNU emacs tiene, por lo que necesita darle algunas
+opciones de línea de comando. Sin embargo, eso no es tan malo, porque
+incluso los creadores de GNU indent reconocen la autoridad de K&R (la gente
+de GNU no es mala, solo están gravemente equivocados en este asunto), por
+lo que simplemente de a la sangría las opciones ``-kr -i8`` (significa
+``K&R, guiones de 8 caracteres``), o use ``scripts/Lindent``, que indenta
+con ese estilo.
+
+``indent`` tiene muchas opciones, y especialmente cuando se trata de
+comentar reformateos, es posible que desee echar un vistazo a la página del
+manual. Pero recuerde: ``indent`` no es la solución para una mala
+programación.
+
+Tenga en cuenta que también puede usar la herramienta ``clang-format`` para
+ayudarlo con estas reglas, para volver a formatear rápidamente partes de su
+código automáticamente, y revisar archivos completos para detectar errores
+de estilo del código, errores tipográficos y posibles mejoras. También es
+útil para ordenar ``#includes``, para alinear variables/macros, para
+redistribuir texto y otras tareas similares. Vea el archivo
+:ref:`Documentation/process/clang-format.rst <clangformat>` para más
+detalles.
+
+10) Archivos de configuración de Kconfig
+----------------------------------------
+
+Para todos los archivos de configuración de Kconfig* en todo el árbol
+fuente, la sangría es algo diferente. Las líneas bajo una definición
+``config`` están indentadas con una tabulación, mientras que el texto de
+ayuda tiene una sangría adicional de dos espacios. Ejemplo::
+
+ config AUDIT
+ bool "Soporte para auditar"
+ depends on NET
+ help
+ Habilita la infraestructura de auditoría que se puede usar con otro
+ subsistema kernel, como SELinux (que requiere esto para
+ registro de salida de mensajes avc). No hace auditoría de llamadas al
+ sistema sin CONFIG_AUDITSYSCALL.
+
+Características seriamente peligrosas (como soporte de escritura para
+ciertos filesystems) deben anunciar esto de forma destacada en su cadena de
+solicitud::
+
+ config ADFS_FS_RW
+ bool "ADFS write support (DANGEROUS)"
+ depends on ADFS_FS
+ ...
+
+Para obtener la documentación completa sobre los archivos de configuración,
+consulte el archivo Documentation/kbuild/kconfig-language.rst.
+
+
+11) Estructuras de datos
+------------------------
+
+Las estructuras de datos que tienen visibilidad fuera del contexto de un
+solo subproceso en el que son creadas y destruidas, siempre debe tener
+contadores de referencia. En el kernel, la recolección de basura no existe
+(y fuera, la recolección de basura del kernel es lenta e ineficiente), lo
+que significa que absolutamente **tiene** para hacer referencia y contar
+todos sus usos.
+
+El conteo de referencias significa que puede evitar el bloqueo y permite
+que múltiples usuarios tengan acceso a la estructura de datos en paralelo -
+y no tengan que preocuparse de que la estructura, de repente, desaparezca
+debajo de su control, solo porque durmieron o hicieron otra cosa por un
+tiempo.
+
+Tenga en cuenta que el bloqueo **no** reemplaza el recuento de referencia.
+El bloqueo se utiliza para mantener la coherencia de las estructuras de
+datos, mientras que la referencia y contar es una técnica de gestión de
+memoria. Por lo general, ambos son necesarios, y no deben confundirse entre
+sí.
+
+De hecho, muchas estructuras de datos pueden tener dos niveles de conteo de
+referencias, cuando hay usuarios de diferentes ``clases``. El conteo de
+subclases cuenta el número de usuarios de la subclase y disminuye el conteo
+global solo una vez, cuando el recuento de subclases llega a cero.
+
+Se pueden encontrar ejemplos de este tipo de ``recuento de referencias de
+niveles múltiples`` en la gestión de memoria (``struct mm_struct``:
+mm_users y mm_count), y en código del sistema de archivos
+(``struct super_block``: s_count y s_active).
+
+Recuerde: si otro hilo puede encontrar su estructura de datos y usted no
+tiene un recuento de referencias, es casi seguro que tiene un error.
+
+12) Macros, Enums y RTL
+------------------------
+
+Los nombres de macros que definen constantes y etiquetas en enumeraciones
+(enums) están en mayúsculas.
+
+.. code-block:: c
+
+ #define CONSTANTE 0x12345
+
+Se prefieren los enums cuando se definen varias constantes relacionadas.
+
+Se aprecian los nombres de macro en MAYÚSCULAS, pero las macros que se
+asemejan a funciones puede ser nombradas en minúscula.
+
+Generalmente, las funciones en línea son preferibles a las macros que se
+asemejan a funciones.
+
+Las macros con varias instrucciones deben contenerse en un bloque do-while:
+
+.. code-block:: c
+
+ #define macrofun(a, b, c) \
+ do { \
+ if (a == 5) \
+ haz_esto(b, c); \
+ } while (0)
+
+Cosas a evitar al usar macros:
+
+1) macros que afectan el flujo de control:
+
+.. code-block:: c
+
+ #define FOO(x) \
+ do { \
+ if (blah(x) < 0) \
+ return -EBUGGERED; \
+ } while (0)
+
+es una **muy** mala idea. Parece una llamada de función pero sale de la
+función de ``llamada``; no rompa los analizadores internos de aquellos que
+leerán el código.
+
+2) macros que dependen de tener una variable local con un nombre mágico:
+
+.. code-block:: c
+
+ #define FOO(val) bar(index, val)
+
+puede parecer algo bueno, pero es confuso como el infierno cuando uno lee
+el código, y es propenso a romperse por cambios aparentemente inocentes.
+
+3) macros con argumentos que se usan como valores l: FOO(x) = y; le van
+a morder si alguien, por ejemplo, convierte FOO en una función en línea.
+
+4) olvidarse de la precedencia: las macros que definen constantes usando
+expresiones deben encerrar la expresión entre paréntesis. Tenga cuidado con
+problemas similares con macros usando parámetros.
+
+.. code-block:: c
+
+ #define CONSTANTE 0x4000
+ #define CONSTEXP (CONSTANTE | 3)
+
+5) colisiones de espacio de nombres ("namespace") al definir variables
+locales en macros que se asemejan a funciones:
+
+.. code-block:: c
+
+ #define FOO(x) \
+ ({ \
+ typeof(x) ret; \
+ ret = calc_ret(x); \
+ (ret); \
+ })
+
+ret es un nombre común para una variable local -es menos probable que
+__foo_ret colisione (coincida) con una variable existente.
+
+El manual de cpp trata las macros de forma exhaustiva. El manual interno de
+gcc también cubre RTL, que se usa frecuentemente con lenguaje ensamblador
+en el kernel.
+
+13) Imprimir mensajes del kernel
+--------------------------------
+
+A los desarrolladores del kernel les gusta ser vistos como alfabetizados.
+Cuide la ortografía de los mensajes del kernel para causar una buena
+impresión. No utilice contracciones incorrectas como ``dont``; use
+``do not`` o ``don't`` en su lugar. Haga sus mensajes concisos, claros e
+inequívocos.
+
+Los mensajes del kernel no tienen que terminar con un punto.
+
+Imprimir números entre paréntesis (%d) no agrega valor y debe evitarse.
+
+Hay varias modelos de macros de diagnóstico de driver en <linux/dev_printk.h>
+que debe usar para asegurarse de que los mensajes coincidan con el
+dispositivo correcto y driver, y están etiquetados con el nivel correcto:
+dev_err(), dev_warn(), dev_info(), y así sucesivamente. Para mensajes que
+no están asociados con un dispositivo particular, <linux/printk.h> define
+pr_notice(), pr_info(), pr_warn(), pr_err(), etc.
+
+Crear buenos mensajes de depuración puede ser todo un desafío; y una vez
+los tiene, pueden ser de gran ayuda para la resolución remota de problemas.
+Sin embargo, la impresión de mensajes de depuración se maneja de manera
+diferente a la impresión de otros mensajes que no son de depuración.
+Mientras que las otras funciones pr_XXX() se imprimen incondicionalmente,
+pr_debug() no lo hace; se compila fuera por defecto, a menos que DEBUG sea
+definido o se establezca CONFIG_DYNAMIC_DEBUG. Eso es cierto para dev_dbg()
+también, y una convención relacionada usa VERBOSE_DEBUG para agregar
+mensajes dev_vdbg() a los ya habilitados por DEBUG.
+
+Muchos subsistemas tienen opciones de depuración de Kconfig para activar
+-DDEBUG en el Makefile correspondiente; en otros casos, los archivos
+usan #define DEBUG. Y cuando un mensaje de depuración debe imprimirse
+incondicionalmente, por ejemplo si es ya dentro de una sección #ifdef
+relacionada con la depuración, printk(KERN_DEBUG ...) puede ser usado.
+
+14) Reservando memoria
+----------------------
+
+El kernel proporciona los siguientes asignadores de memoria de propósito
+general: kmalloc(), kzalloc(), kmalloc_array(), kcalloc(), vmalloc() y
+vzalloc(). Consulte la documentación de la API para obtener más información.
+a cerca de ellos. :ref:`Documentation/core-api/memory-allocation.rst
+<memory_allocation>`
+
+La forma preferida para pasar el tamaño de una estructura es la siguiente:
+
+.. code-block:: c
+
+ p = kmalloc(sizeof(*p), ...);
+
+La forma alternativa donde se deletrea el nombre de la estructura perjudica
+la legibilidad, y presenta una oportunidad para un error cuando se cambia
+el tipo de variable de puntero, pero el tamaño correspondiente de eso que
+se pasa a un asignador de memoria no.
+
+Convertir el valor devuelto, que es un puntero vacío, es redundante. La
+conversión desde el puntero vacío a cualquier otro tipo de puntero está
+garantizado por la programación en idioma C.
+
+La forma preferida para asignar una matriz es la siguiente:
+
+.. code-block:: c
+
+ p = kmalloc_array(n, sizeof(...), ...);
+
+La forma preferida para asignar una matriz a cero es la siguiente:
+
+.. code-block:: c
+
+ p = kcalloc(n, sizeof(...), ...);
+
+Ambos casos verifican el desbordamiento en el tamaño de asignación n *
+sizeof (...), y devuelven NULL si esto ocurrió.
+
+Todas estas funciones de asignación genéricas emiten un volcado de pila
+(" stack dump") en caso de fallo cuando se usan sin __GFP_NOWARN, por lo
+que no sirve de nada emitir un mensaje de fallo adicional cuando se
+devuelva NULL.
+
+15) La enfermedad de inline
+----------------------------
+
+Parece haber una común percepción errónea de que gcc tiene una magica
+opción "hazme más rápido" de aceleración, llamada ``inline`` (en línea).
+Mientras que el uso de inlines puede ser apropiado (por ejemplo, como un
+medio para reemplazar macros, consulte el Capítulo 12), muy a menudo no lo
+es. El uso abundante de la palabra clave inline conduce a una mayor kernel,
+que a su vez ralentiza el sistema en su conjunto, debido a una mayor huella
+de icache para la CPU, y sencillamente porque hay menos memoria disponible
+para el pagecache. Solo piense en esto; un fallo en la memoria caché de la
+página provoca una búsqueda de disco, que tarda fácilmente 5 milisegundos.
+Hay MUCHOS ciclos de CPU que puede entrar en estos 5 milisegundos.
+
+Una razonable regla general es no poner funciones inline que tengan más de
+3 líneas de código en ellas. Una excepción a esta regla son los casos en
+que se sabe que un parámetro es una constante en tiempo de compilación, y
+como resultado de esto, usted *sabe*, el compilador podrá optimizar la
+mayor parte de su función en tiempo de compilación. Para un buen ejemplo de
+este último caso, véase la función en línea kmalloc().
+
+A menudo, la gente argumenta que agregar funciones en línea que son
+estáticas y se usan solo una vez, es siempre una victoria ya que no hay
+perdida de espacio. Mientras esto es técnicamente correcto, gcc es capaz de
+incorporarlos automáticamente sin ayuda, y esta el problema de
+mantenimiento de eliminar el inline, cuando un segundo usuario supera el
+valor potencial de la pista que le dice a gcc que haga algo que habría
+hecho de todos modos.
+
+16) Valores devueltos por función y sus nombres
+-----------------------------------------------
+
+Las funciones pueden devolver valores de muchos tipos diferentes, y uno de
+lo más común es un valor que indica si la función tuvo éxito o ha fallado.
+Dicho valor se puede representar como un número entero de código de error
+(-Exxx = falla, 0 = éxito) o un booleano ``con éxito`` (0 = falla, distinto
+de cero = éxito).
+
+La mezcla de estos dos tipos de representaciones es una fuente fértil de
+errores difíciles de encontrar. Si el lenguaje C incluyera una fuerte
+distinción entre enteros y booleanos, el compilador encontraría estos
+errores por nosotros... pero no lo hace. Para ayudar a prevenir tales
+errores, siga siempre esta convención::
+
+ Si el nombre de una función es una acción o un comando imperativo,
+ la función debe devolver un número entero de código de error. si el nombre
+ es un predicado, la función debe devolver un valor booleano "exitoso".
+
+Por ejemplo, ``agregar trabajo`` es un comando, y la función
+agregar_trabajo() devuelve 0 en caso de éxito o -EBUSY en caso de fracaso.
+De la misma manera, ``dispositivo PCI presente`` es un predicado, y la
+función pci_dev_present() devuelve 1 si tiene éxito en encontrar un
+dispositivo coincidente o 0 si no es así.
+
+Todas las funciones EXPORTed (exportadas) deben respetar esta convención,
+al igual que todas las funciones publicas. Las funciones privadas
+(estáticas) no lo necesitan, pero es recomendado que lo hagan.
+
+Las funciones cuyo valor devuelto es el resultado real de un cálculo, en
+lugar de una indicación de si el cómputo tuvo éxito, no están sujetas a
+esta regla. Generalmente indican fallo al devolver valores fuera del rango
+de resultados. Los ejemplos típicos serían funciones que devuelven
+punteros; estos usan NULL o el mecanismo ERR_PTR para informar de fallos.
+
+17) Usando bool
+----------------
+
+El tipo bool del kernel Linux es un alias para el tipo C99 _Bool. Los
+valores booleanos pueden solo evaluar a 0 o 1, y la conversión implícita o
+explícita a bool convierte automáticamente el valor en verdadero o falso.
+Cuando se utilizan tipos booleanos,
+!! no se necesita construcción, lo que elimina una clase de errores.
+
+Cuando se trabaja con valores booleanos, se deben usar las definiciones
+verdadera y falsa, en lugar de 1 y 0.
+
+Los tipos de devolución de función bool y las variables de pila siempre
+se pueden usar cuando esto sea adecuado. Se recomienda el uso de bool para
+mejorar la legibilidad y, a menudo, es una mejor opción que 'int' para
+almacenar valores booleanos.
+
+No use bool si el diseño de la línea de caché o el tamaño del valor son
+importantes, ya que su tamaño y la alineación varía según la arquitectura
+compilada. Las estructuras que son optimizadas para la alineación y el
+tamaño no debe usar bool.
+
+Si una estructura tiene muchos valores verdadero/falso, considere
+consolidarlos en un bitfield con miembros de 1 bit, o usando un tipo de
+ancho fijo apropiado, como u8.
+
+De manera similar, para los argumentos de función, se pueden consolidar
+muchos valores verdaderos/falsos en un solo argumento bit a bit 'flags' y
+'flags' a menudo, puede ser una alternativa de argumento más legible si los
+sitios de llamada tienen constantes desnudas de tipo verdaderas/falsas.
+
+De lo contrario, el uso limitado de bool en estructuras y argumentos puede
+mejorar la legibilidad.
+
+18) No reinvente las macros del kernel
+---------------------------------------
+
+El archivo de cabecera include/linux/kernel.h contiene una serie de macros
+que debe usar, en lugar de programar explícitamente alguna variante de
+estos por usted mismo. Por ejemplo, si necesita calcular la longitud de una
+matriz, aproveche la macro
+
+.. code-block:: c
+
+ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+De manera similar, si necesita calcular el tamaño de algún miembro de la
+estructura, use
+
+.. code-block:: c
+
+ #define sizeof_field(t, f) (sizeof(((t*)0)->f))
+
+También hay macros min() y max() que realizan una verificación estricta de
+tipos si lo necesita. Siéntase libre de leer detenidamente ese archivo de
+encabezado para ver qué más ya está definido y que no debe reproducir en su
+código.
+
+19) Editores modeline y otros desastres
+---------------------------------------
+
+Algunos editores pueden interpretar la información de configuración
+incrustada en los archivos fuente, indicado con marcadores especiales. Por
+ejemplo, emacs interpreta las líneas marcadas como esto:
+
+.. code-block:: c
+
+ -*- mode: c -*-
+
+O así:
+
+.. code-block:: c
+
+ /*
+ Local Variables:
+ compile-command: "gcc -DMAGIC_DEBUG_FLAG foo.c"
+ End:
+ */
+
+Vim interpreta los marcadores que se ven así:
+
+.. code-block:: c
+
+ /* vim:set sw=8 noet */
+
+No incluya ninguno de estos en los archivos fuente. La gente tiene sus
+propias configuraciones del editor, y sus archivos de origen no deben
+anularlos. Esto incluye marcadores para sangría y configuración de modo.
+La gente puede usar su propio modo personalizado, o puede tener algún otro
+método mágico para que la sangría funcione correctamente.
+
+
+20) Ensamblador inline
+-----------------------
+
+En el código específico de arquitectura, es posible que deba usar
+ensamblador en línea para interactuar con funcionalidades de CPU o
+plataforma. No dude en hacerlo cuando sea necesario. Sin embargo, no use
+ensamblador en línea de forma gratuita cuando C puede hacer el trabajo.
+Puede y debe empujar el hardware desde C cuando sea posible.
+
+Considere escribir funciones auxiliares simples que envuelvan bits comunes
+de ensamblador, en lugar de escribirlos repetidamente con ligeras
+variaciones. Recuerde que el ensamblador en línea puede usar parámetros C.
+
+Las funciones de ensamblador grandes y no triviales deben ir en archivos .S,
+con su correspondientes prototipos de C definidos en archivos de encabezado
+en C. Los prototipos de C para el ensamblador deben usar ``asmlinkage``.
+
+Es posible que deba marcar su declaración asm como volátil, para evitar que
+GCC la elimine si GCC no nota ningún efecto secundario. No siempre es
+necesario hacerlo, sin embargo, y hacerlo innecesariamente puede limitar la
+optimización.
+
+Al escribir una sola declaración de ensamblador en línea que contiene
+múltiples instrucciones, ponga cada instrucción en una línea separada en
+una string separada, y termine cada string excepto la última con ``\n\t``
+para indentar correctamente la siguiente instrucción en la salida en
+ensamblador:
+
+.. code-block:: c
+
+ asm ("magic %reg1, #42\n\t"
+ "more_magic %reg2, %reg3"
+ : /* outputs */ : /* inputs */ : /* clobbers */);
+
+21) Compilación condicional
+---------------------------
+
+Siempre que sea posible, no use condicionales de preprocesador (#if,
+#ifdef) en archivos .c; de lo contrario, el código es más difícil de leer y
+la lógica más difícil de seguir. En cambio, use dichos condicionales en un
+archivo de encabezado que defina funciones para usar en esos archivos .c,
+proporcionando versiones de código auxiliar sin operación en el caso #else,
+y luego llame a estas funciones incondicionalmente desde archivos .c. El
+compilador evitará generar cualquier código para las llamadas restantes,
+produciendo resultados idénticos, pero la lógica es fácil de seguir.
+
+Prefiera compilar funciones completas, en lugar de porciones de funciones o
+porciones de expresiones. En lugar de poner un ifdef en una expresión,
+divida la totalidad de la expresión con una función de ayuda independiente
+y aplique el condicional a esa función.
+
+Si tiene una función o variable que puede potencialmente quedar sin usar en
+una configuración en particular, y el compilador advertiría sobre su
+definición sin usar, marque la definición como __maybe_unused en lugar de
+envolverla en un preprocesador condicional. (Sin embargo, si una función o
+variable *siempre* acaba sin ser usada, bórrela.)
+
+Dentro del código, cuando sea posible, use la macro IS_ENABLED para
+convertir un símbolo Kconfig en una expresión booleana de C, y utilícelo en
+un condicional de C normal:
+
+.. code-block:: c
+
+ if (IS_ENABLED(CONFIG_SOMETHING)) {
+ ...
+ }
+
+El compilador "doblará"" constantemente el condicional e incluirá o
+excluirá el bloque de código al igual que con un #ifdef, por lo que esto no
+agregará ningún tiempo de gastos generales en ejecución. Sin embargo, este
+enfoque todavía permite que el compilador de C vea el código dentro del
+bloque, y verifique que sea correcto (sintaxis, tipos, símbolo, referencias,
+etc.). Por lo tanto, aún debe usar un #ifdef si el código dentro del bloque
+hace referencia a símbolos que no existirán si no se cumple la condición.
+
+Al final de cualquier bloque #if o #ifdef no trivial (más de unas pocas
+líneas), incluya un comentario después de #endif en la misma línea,
+anotando la expresión condicional utilizada. Por ejemplo:
+
+.. code-block:: c
+
+ #ifdef CONFIG_SOMETHING
+ ...
+ #endif /* CONFIG_SOMETHING */
+
+22) No rompa el kernel
+-----------------------
+
+En general, la decisión de romper el kernel pertenece al usuario, más que
+al desarrollador del kernel.
+
+Evite el panic()
+****************
+
+panic() debe usarse con cuidado y principalmente solo durante el arranque
+del sistema. panic() es, por ejemplo, aceptable cuando se queda sin memoria
+durante el arranque y no puede continuar.
+
+Use WARN() en lugar de BUG()
+****************************
+
+No agregue código nuevo que use cualquiera de las variantes BUG(), como
+BUG(), BUG_ON() o VM_BUG_ON(). En su lugar, use una variante WARN*(),
+preferiblemente WARN_ON_ONCE(), y posiblemente con código de recuperación.
+El código de recuperación no es requerido si no hay una forma razonable de
+recuperar, al menos parcialmente.
+
+"Soy demasiado perezoso para tener en cuenta los errores" no es una excusa
+para usar BUG(). Importantes corrupciones internas sin forma de continuar
+aún pueden usar BUG(), pero necesitan una buena justificación.
+
+Use WARN_ON_ONCE() en lugar de WARN() o WARN_ON()
+*************************************************
+
+Generalmente, se prefiere WARN_ON_ONCE() a WARN() o WARN_ON(), porque es
+común que una condición de advertencia dada, si ocurre, ocurra varias
+veces. Esto puede llenar el registro del kernel, e incluso puede ralentizar
+el sistema lo suficiente como para que el registro excesivo se convierta en
+su propio, adicional problema.
+
+No haga WARN a la ligera
+************************
+
+WARN*() está diseñado para situaciones inesperadas que nunca deberían
+suceder. Las macros WARN*() no deben usarse para nada que se espera que
+suceda durante un funcionamiento normal. No hay "checkeos" previos o
+posteriores a la condición, por ejemplo. De nuevo: WARN*() no debe usarse
+para una condición esperada que vaya a activarse fácilmente, por ejemplo,
+mediante acciones en el espacio del usuario. pr_warn_once() es una
+alternativa posible, si necesita notificar al usuario de un problema.
+
+No se preocupe sobre panic_on_warn de usuarios
+**********************************************
+
+Algunas palabras más sobre panic_on_warn: Recuerde que ``panic_on_warn`` es
+una opción disponible del kernel, y que muchos usuarios configuran esta
+opción. Esta es la razón por la que hay un artículo de "No haga WARN a la
+ligera", arriba. Sin embargo, la existencia de panic_on_warn de usuarios no
+es una razón válida para evitar el uso juicioso de WARN*(). Esto se debe a
+que quien habilita panic_on_warn, explícitamente pidió al kernel que
+fallara si se dispara un WARN*(), y tales usuarios deben estar preparados
+para afrontar las consecuencias de un sistema que es algo más probable que
+se rompa.
+
+Use BUILD_BUG_ON() para aserciones en tiempo de compilación
+***********************************************************
+
+El uso de BUILD_BUG_ON() es aceptable y recomendado, porque es una aserción
+en tiempo de compilación, que no tiene efecto en tiempo de ejecución.
+
+Apéndice I) Referencias
+-----------------------
+
+The C Programming Language, Segunda edicion
+por Brian W. Kernighan and Dennis M. Ritchie.
+Prentice Hall, Inc., 1988.
+ISBN 0-13-110362-8 (paperback), 0-13-110370-9 (hardback).
+
+The Practice of Programming
+por Brian W. Kernighan and Rob Pike.
+Addison-Wesley, Inc., 1999.
+ISBN 0-201-61586-X.
+
+manuales GCC - en cumplimiento con K&R y este texto - para cpp, gcc,
+detalles de gcc y sangría, todo disponible en https://www.gnu.org/manual/
+
+WG14 es el grupo de trabajo de estandarización internacional de la
+programación en lenguaje C, URL: http://www.open-std.org/JTC1/SC22/WG14/
+
+:ref:`process/coding-style.rst <codingstyle>` del kernel, por greg@kroah.com at OLS 2002:
+http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
diff --git a/Documentation/translations/sp_SP/process/index.rst b/Documentation/translations/sp_SP/process/index.rst
new file mode 100644
index 000000000000..49a05f6a5544
--- /dev/null
+++ b/Documentation/translations/sp_SP/process/index.rst
@@ -0,0 +1,15 @@
+.. raw:: latex
+
+ \renewcommand\thesection*
+ \renewcommand\thesubsection*
+
+.. include:: ../disclaimer-sp.rst
+
+.. _sp_process_index:
+
+.. toctree::
+ :maxdepth: 1
+
+ submitting-patches
+ kernel-docs
+ coding-style
diff --git a/Documentation/translations/sp_SP/process/kernel-docs.rst b/Documentation/translations/sp_SP/process/kernel-docs.rst
new file mode 100644
index 000000000000..2f9b3df8f8fa
--- /dev/null
+++ b/Documentation/translations/sp_SP/process/kernel-docs.rst
@@ -0,0 +1,187 @@
+.. include:: ../disclaimer-sp.rst
+
+:Original: :ref:`Documentation/process/kernel-docs.rst <kernel_docs>`
+:Translator: Carlos Bilbao <carlos.bilbao@amd.com>
+
+.. _sp_kernel_docs:
+
+Ãndice de documentación adicional del kernel
+============================================
+
+La necesidad de un documento como este se hizo evidente en la lista de
+correo de linux-kernel cuando las mismas preguntas, solicitando sugerencias
+e información, aparecieron una y otra vez.
+
+Afortunadamente, a medida que más y más gente accede a GNU/Linux, más
+desarrolladores se interesan por el kernel. Sin embargo, leer las fuentes
+no siempre es suficiente. Es fácil entender el código, pero se pierden los
+conceptos, la filosofía y decisiones de diseño detrás de dicho código.
+
+Desafortunadamente, no existen muchos documentos disponibles para que los
+principiantes comiencen. Y, aunque existieran, no habría ningún lugar
+"conocido" que les pudiera seguir la pista. Estas líneas tratan de cubrir
+esta carencia.
+
+POR FAVOR, si conoce algún documento que no figura aquí, o si escribe un
+nuevo documento, incluya una referencia aquí, siguiendo el proceso de envío
+de parches del kernel. Cualquier corrección, idea o comentario también es
+bienvenida.
+
+Todos los documentos se catalogan con los siguientes campos: el "Título",
+el "Autor"/es, la "URL" donde se encuentran, algunas "Palabras clave"
+útiles para buscar temas específicos, y una breve "Descripción" del
+documento en cuestión.
+
+.. note::
+
+ Los documentos de cada sección en este documento están ordenados por su
+ fecha de publicación, del más reciente al más antiguo. Los maintainers
+ deben ir retirando recursos obsoletos o anticuados.
+
+Documentos en el árbol del kernel Linux
+-----------------------------------------
+
+Los libros de Sphinx deben compilarse con ``make {htmldocs | pdfdocs | epubdocs}``.
+
+ * Título: **linux/Documentation**
+
+ :Autor: Many.
+ :Ubicación: Documentation/
+ :Palabras Clave: archivos de texto, Sphinx.
+ :Descripción: Documentación que viene con las fuentes del kernel,
+ dentro del directorio Documentation. Algunas páginas de este documento
+ (incluido este documento en sí) se han trasladado allí, y podrían
+ estar más actualizadas que la versión web.
+
+Documentos en línea
+-------------------
+
+ * Título: **Linux Kernel Mailing List Glossary**
+
+ :Autor: various
+ :URL: https://kernelnewbies.org/KernelGlossary
+ :Fecha: rolling version
+ :Palabras Clave: glosario terminos, linux-kernel.
+ :Descripción: De la Introducción: "This glossary is intended as
+ a brief description of some of the acronyms and terms you may hear
+ during discussion of the Linux kernel".
+
+ * Título: **The Linux Kernel Module Programming Guide**
+
+ :Autor: Peter Jay Salzman, Michael Burian, Ori Pomerantz, Bob Mottram,
+ Jim Huang.
+ :URL: https://sysprog21.github.io/lkmpg/
+ :Fecha: 2021
+ :Palabras Clave: modules, GPL book, /proc, ioctls, system calls,
+ interrupt handlers, llamadas al sistema, interrupciones.
+ :Descripción: Un muy buen libro GPL sobre el tema de la programación
+ de módulos. Muchos ejemplos. Actualmente la nueva versión está
+ siendo mantenida activamente ent https://github.com/sysprog21/lkmpg.
+
+Libros publicados
+-----------------
+
+ * Título: **Linux Kernel Programming: A Comprehensive Guide to Kernel Internals, Writing Kernel Modules, and Kernel Synchronization**
+
+ :Autor: Kaiwan N. Billimoria
+ :Publica: Packt Publishing Ltd
+ :Fecha: 2021
+ :Paginas: 754
+ :ISBN: 978-1789953435
+
+ * Título: **Linux Kernel Development, 3rd Edition**
+
+ :Autor: Robert Love
+ :Publica: Addison-Wesley
+ :Fecha: July, 2010
+ :Paginas: 440
+ :ISBN: 978-0672329463
+ :Notas: Libro fundacional
+
+.. _sp_ldd3_published:
+
+ * Título: **Linux Device Drivers, 3rd Edition**
+
+ :Authors: Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman
+ :Publica: O'Reilly & Associates
+ :Fecha: 2005
+ :Paginas: 636
+ :ISBN: 0-596-00590-3
+ :Notas: Libro fundacional. Más información en
+ http://www.oreilly.com/catalog/linuxdrive3/
+ formato PDF, URL: https://lwn.net/Kernel/LDD3/
+
+ * Título: **The Design of the UNIX Operating System**
+
+ :Autor: Maurice J. Bach
+ :Publica: Prentice Hall
+ :Fecha: 1986
+ :Paginas: 471
+ :ISBN: 0-13-201757-1
+ :Notas: Libro fundacional
+
+Recursos varios
+---------------
+
+ * Título: **Cross-Referencing Linux**
+
+ :URL: https://elixir.bootlin.com/
+ :Palabras Clave: Browsing source code.
+ :Descripción: Otro navegador de código fuente del kernel Linux que se
+ encuentra en la web. Muchas referencias cruzadas a variables y
+ funciones. Puedes ver dónde se definen y dónde se utilizan.
+
+ * Título: **Linux Weekly News**
+
+ :URL: https://lwn.net
+ :Palabras Clave: latest kernel news, noticias del kernel Linux.
+ :Descripción: El título lo dice todo (Noticias Semanales de Linux).
+ Hay una sección fija sobre el kernel, resumiendo el trabajo de sus
+ desarrolladores, correcciones de errores, nuevas funciones y
+ versiones, producido durante la semana.
+
+ * Título: **The home page of Linux-MM**
+
+ :Autor: The Linux-MM team.
+ :URL: https://linux-mm.org/
+ :Palabras Clave: memory management, Linux-MM, mm patches, TODO, docs,
+ mailing list, administración de memoria, Linux-MM, parches mm, listas
+ de correo.
+ :Descripción: Sitio dedicado al desarrollo de la gestión de memoria
+ de Linux. Parches relacionados con la memoria, HOWTOs, enlaces,
+ desarrolladores de mm... ¡Si está interesado en el desarrollo de la
+ gestión de memoria no te lo pierdas!
+
+ * Título: **Kernel Newbies IRC Channel and Website**
+
+ :URL: https://www.kernelnewbies.org
+ :Palabras Clave: IRC, newbies, channel, asking doubts, canal, dudas,
+ novatos, preguntar.
+ :Descripción: #kernelnewbies en irc.oftc.net.
+ #kernelnewbies es una red de IRC dedicada al hacker del kernel
+ 'novato'. La audiencia se compone principalmente de personas que
+ quieren aprender sobre el kernel, trabajar en proyectos del kernel
+ o hackers profesionales del kernel que quieren ayudar a la gente
+ menos experimentada.
+ #kernelnewbies es parte de la red OFTC IRC.
+ Pruebe con irc.oftc.net como su servidor y luego haga /join
+ #kernelnewbies.
+ El sitio web kernelnewbies también alberga artículos, documentos, FAQs...
+
+ * Título: **linux-kernel mailing list archives and search engines**
+
+ :URL: http://vger.kernel.org/vger-lists.html
+ :URL: http://www.uwsg.indiana.edu/hypermail/linux/kernel/index.html
+ :URL: http://groups.google.com/group/mlist.linux.kernel
+ :Palabras Clave: linux-kernel, archives, buscar, search, archivos.
+ :Descripción: Algunos de los archivadores de listas de correo del
+ kernel de Linux. Si usted tiene uno mejor/otro, por favor hágamelo
+ saber.
+
+-------
+
+Este documento se basaba originalmente en:
+
+ https://www.dit.upm.es/~jmseyas/linux/kernel/hackers-docs.html
+
+escrito por Juan-Mariano de Goyenche
diff --git a/Documentation/translations/sp_SP/process/submitting-patches.rst b/Documentation/translations/sp_SP/process/submitting-patches.rst
new file mode 100644
index 000000000000..bf95ceb5e865
--- /dev/null
+++ b/Documentation/translations/sp_SP/process/submitting-patches.rst
@@ -0,0 +1,894 @@
+.. include:: ../disclaimer-sp.rst
+
+:Original: :ref:`Documentation/process/submitting-patches.rst <submittingpatches>`
+:Translator: Carlos Bilbao <carlos.bilbao@amd.com>
+
+.. _sp_submittingpatches:
+
+Envío de parches: la guía esencial para incluir su código en el kernel
+=======================================================================
+
+Para una persona o empresa que desee enviar un cambio al kernel Linux,
+el proceso puede en ocasiones resultar desalentador si no se está
+familiarizado con "el sistema". Este texto es una colección de sugerencias
+que pueden aumentar considerablemente las posibilidades de que se acepte su
+cambio.
+
+Este documento contiene una gran cantidad de sugerencias en un formato
+relativamente conciso. Para obtener información detallada sobre cómo
+funciona el proceso de desarrollo del kernel, consulte
+Documentation/process/development-process.rst. Además, lea
+Documentation/process/submit-checklist.rst para obtener una lista de
+elementos a verificar antes de enviar código. Para los parches de
+"binding" del árbol de dispositivos, lea
+Documentation/devicetree/bindings/submitting-patches.rst.
+
+Esta documentación asume que está usando ``git`` para preparar sus parches.
+Si no está familiarizado con ``git``, le recomendamos que aprenda a
+usarlo, le hará la vida como desarrollador del kernel y en general mucho
+más sencilla.
+
+Algunos subsistemas y árboles de mantenimiento cuentan con información
+adicional sobre su flujo de trabajo y expectativas, consulte
+:ref:`Documentation/process/maintainer-handbooks.rst <maintainer_handbooks_main>`.
+
+Obtenga el código fuente actual
+--------------------------------
+
+Si no tiene a mano un repositorio con el código fuente actual del kernel,
+use ``git`` para obtener uno. Querrá comenzar con el repositorio principal,
+que se puede descargar con::
+
+ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
+
+Tenga en cuenta, sin embargo, que es posible que no desee desarrollar con
+el árbol principal directamente. La mayoría de los maintainers de
+subsistemas usan sus propios árboles de código fuente y quieren ver parches
+preparados para esos árboles. Revise el campo **T:** para el subsistema
+en el archivo MAINTAINERS para encontrar dicho árbol, o simplemente
+pregunte al maintainer si el árbol no está listado allí.
+
+.. _sp_describe_changes:
+
+Describa sus cambios
+---------------------
+
+Describa su problema. Sea su parche una corrección de un error de una
+línea o 5000 líneas para una nuevo "feature", debe haber un problema
+subyacente que le motivó a hacer ese trabajo. Convenza al revisor de que
+hay un problema que merece la pena solucionar y de que tiene sentido que
+lea más allá del primer párrafo.
+
+Describa el impacto relativo al usuario. Cosas que estropeen el kernel y
+los bloqueos son bastante convincentes, pero no todos los errores son tan
+evidentes. Incluso si se detectó un problema durante la revisión del
+código, describa el impacto que cree pueda tener en los usuarios. Tenga en
+cuenta que la mayoría de instalaciones de Linux ejecutan kernels desde
+árboles estables secundarios o árboles específicos de proveedor/producto
+que seleccionan ("cherry-pick") solo parches específicos de upstream, así
+que incluya cualquier cosa que pueda ayudar a dirigir su cambio
+aguas abajo: circunstancias que producen cierta situación, extractos de
+dmesg, descripciones del error fatal, regresiones de rendimiento, picos de
+latencia, bloqueos, etc.
+
+Cuantifique optimizaciones y beneficios/perdidas. Si asegura mejoras en
+rendimiento, consumo de memoria, huella del stack o tamaño de binario,
+incluya números que lo respalden. Pero también describa costes no obvios.
+Las optimizaciones generalmente no son gratuitas, sino un equilibrio entre
+CPU, memoria y legibilidad; o, cuando se trata de heurísticas, entre
+diferentes cargas de trabajo. Describa las desventajas esperadas de su
+optimización para que el revisor pueda comparar las perdidas con los
+beneficios.
+
+Una vez establecido el problema, describa lo que realmente está haciendo
+al respecto en detalles técnicos. Es importante describir el cambio en
+lenguaje sencillo para que el revisor verifique que el código se está
+comportando como se pretende.
+
+El maintainer le agradecerá que escriba la descripción de su parche en un
+formato que se pueda incorporar fácilmente en la gestión del código fuente
+del sistema, ``git``, como un "commit log" (registros de los commits).
+Consulte :ref:`sp_the_canonical_patch_format`.
+
+Resuelva solo un problema por parche. Si su descripción comienza a ser muy
+larga, eso es una señal de que probablemente necesite dividir su parche.
+Lea :ref:`split_changes`.
+
+Cuando envíe o vuelva a enviar un parche o una serie de parches, incluya la
+descripción completa del parche y justificación del mismo. No se limite a
+decir que esa es la versión N del parche (serie). No espere que el
+maintainer del subsistema referencie versiones de parches anteriores o use
+referencias URL para encontrar la descripción del parche y colocarla en el
+parche. Es decir, el parche (serie) y su descripción deben ser
+independientes. Esto beneficia tanto a los maintainers como a los
+revisores. Algunos revisores probablemente ni siquiera recibieran versiones
+anteriores del parche.
+
+Describa sus cambios en la forma imperativa, por ejemplo, "hacer que xyzzy
+haga frotz" en lugar de "[Este parche] hace que xyzzy haga frotz" o "[Yo]
+Cambié xyzzy para que haga frotz", como si estuviera dando órdenes al
+código fuente para cambiar su comportamiento.
+
+Si desea hacer referencia a un commit específico, no se limite a hacer
+referencia al ID SHA-1 del commit. Incluya también el resumen de una línea
+del commit, para que sea más fácil para los revisores saber de qué se
+trata.
+Ejemplo::
+
+ Commit e21d2170f36602ae2708 ("video: quitar platform_set_drvdata()
+ innecesario") eliminó innecesario platform_set_drvdata(), pero dejó la
+ variable "dev" sin usar, bórrese.
+
+También debe asegurarse de utilizar al menos los primeros doce caracteres
+del identificador SHA-1. El repositorio del kernel contiene muchos *muchos*
+objetos, por lo que las colisiones con identificaciones más cortas son una
+posibilidad real. Tenga en cuenta que, aunque no hay colisión con su
+identificación de seis caracteres ahora, esa condición puede cambiar dentro
+de cinco años.
+
+Si las discusiones relacionadas o cualquier otra información relativa al
+cambio se pueden encontrar en la web, agregue las etiquetas 'Link:' que
+apunten a estos. En caso de que su parche corrija un error, por poner un
+ejemplo, agregue una etiqueta con una URL que haga referencia al informe en
+los archivos de las listas de correo o un rastreador de errores; si el
+parche es el resultado de alguna discusión anterior de la lista de correo o
+algo documentado en la web, referencie esto.
+
+Cuando se vincule a archivos de listas de correo, preferiblemente use el
+servicio de archivador de mensajes lore.kernel.org. Para crear la URL del
+enlace, utilice el contenido del encabezado ("header") ``Message-Id`` del
+mensaje sin los corchetes angulares que lo rodean.
+Por ejemplo::
+
+ Link: https://lore.kernel.org/r/30th.anniversary.repost@klaava.Helsinki.FI/
+
+Verifique el enlace para asegurarse de que realmente funciona y apunta al
+mensaje correspondiente.
+
+Sin embargo, intente que su explicación sea comprensible sin recursos
+externos. Además de dar una URL a un archivo o error de la lista de correo,
+resuma los puntos relevantes de la discusión que condujeron al parche tal y
+como se envió.
+
+Si su parche corrige un error en un commit específico, por ejemplo
+encontró un problema usando ``git bisect``, utilice la etiqueta 'Fixes:'
+con los primeros 12 caracteres del ID SHA-1 y el resumen de una línea. No
+divida la etiqueta en varias líneas, las etiquetas están exentas de la
+regla "ajustar a 75 columnas" para simplificar análisis de scripts. Por
+ejemplo::
+
+ Fixes: 54a4f0239f2e ("KVM: MMU: hacer que kvm_mmu_zap_page()
+ devuelva la cantidad de páginas que realmente liberó")
+
+Las siguientes configuraciones de ``git config`` se pueden usar para
+agregar un bonito formato y generar este estilo con los comandos
+``git log`` o ``git show``::
+
+ [core]
+ abbrev = 12
+ [pretty]
+ fixes = Fixes: %h (\"%s\")
+
+Un ejemplo de uso::
+
+ $ git log -1 --pretty=fixes 54a4f0239f2e
+ Fixes: 54a4f0239f2e ("KVM: MMU: hacer que kvm_mmu_zap_page() devuelva la cantidad de páginas que realmente liberó")
+
+.. _sp_split_changes:
+
+Separe sus cambios
+-------------------
+
+Separe cada **cambio lógico** en un parche separado.
+
+Por ejemplo, si sus cambios incluyen correcciones de errores y mejoras en
+el rendimiento de un controlador, separe esos cambios en dos o más parches.
+Si sus cambios incluyen una actualización de la API y una nueva controlador
+que usa esta nueva API, sepárelos en dos parches.
+
+Por otro lado, si realiza un solo cambio en numerosos archivos, agrupe esos
+cambios en un solo parche. Por lo tanto, un solo cambio lógico estará
+contenido en un solo parche.
+
+El punto a recordar es que cada parche debe realizar un cambio que puede
+ser verificado por los revisores fácilmente. Cada parche debe ser
+justificable por sus propios méritos.
+
+Si un parche depende de otro parche para que un cambio sea completo, eso
+está bien. Simplemente incluya que **"este parche depende del parche X"**
+en la descripción de su parche.
+
+Cuando divida su cambio en una serie de parches, tenga especial cuidado en
+asegurarse de que el kernel se compila y ejecuta correctamente después de
+cada parche en la serie. Los desarrolladores que usan ``git bisect``
+para rastrear un problema pueden terminar dividiendo su serie de parches en
+cualquier punto; no le agradecerán si introdujo errores a la mitad.
+
+Si no puede condensar su conjunto de parches en un conjunto más pequeño de
+parches, solo publique, más o menos 15 a la vez, y espere la revisión e
+integración.
+
+
+Revise el estilo en sus cambios
+--------------------------------
+
+Revise su parche para ver si hay violaciones de estilo básico, cuyos
+detalles pueden ser encontrados en Documentation/process/coding-style.rst.
+No hacerlo simplemente desperdicia el tiempo de los revisores y su parche
+será rechazado, probablemente sin siquiera ser leído.
+
+Una excepción importante es cuando se mueve código de un archivo a otro.
+En tal caso, en absoluto debe modificar el código movido en el mismo parche
+en que lo mueve. Esto divide claramente el acto de mover el código y sus
+cambios. Esto ayuda mucho a la revisión de la diferencias reales y permite
+que las herramientas rastreen mejor el historial del código en sí.
+
+Verifique sus parches con el verificador de estilo de parches antes de
+enviarlos (scripts/checkpatch.pl). Tenga en cuenta, sin embargo, que el
+verificador de estilo debe ser visto como una guía, no como un reemplazo
+del juicio humano. Si su código es mejor con una violación entonces
+probablemente sea mejor dejarlo estar.
+
+El verificador informa a tres niveles:
+ - ERROR: cosas que es muy probable que estén mal
+ - WARNING: Advertencia. Cosas que requieren una revisión cuidadosa
+ - CHECK: Revisar. Cosas que requieren pensarlo
+
+Debe poder justificar todas las violaciones que permanezcan en su parche.
+
+
+Seleccione los destinatarios de su parche
+------------------------------------------
+
+Siempre debe incluir en copia a los apropiados maintainers del subsistema
+en cualquier parche con código que mantengan; revise a través del archivo
+MAINTAINERS y el historial de revisión del código fuente para ver quiénes
+son esos maintainers. El script scripts/get_maintainer.pl puede ser muy
+útil en este paso (pase rutas a sus parches como argumentos para
+scripts/get_maintainer.pl). Si no puede encontrar un maintainer del
+subsistema en el que está trabajando, Andrew Morton
+(akpm@linux-foundation.org) sirve como maintainer de último recurso.
+
+Normalmente, también debe elegir al menos una lista de correo para recibir
+una copia de su conjunto de parches. linux-kernel@vger.kernel.org debe
+usarse de forma predeterminada para todos los parches, pero el volumen en
+esta lista ha hecho que muchos desarrolladores se desconecten. Busque en el
+archivo MAINTAINERS una lista específica de los subsistemas; su parche
+probablemente recibirá más atención allí. Sin embargo, no envíe spam a
+listas no relacionadas.
+
+Muchas listas relacionadas con el kernel están alojadas en vger.kernel.org;
+puedes encontrar un listado de estas en
+http://vger.kernel.org/vger-lists.html. Existen listas relacionadas con el
+kernel alojadas en otros lugares, no obstante.
+
+¡No envíe más de 15 parches a la vez a las listas de correo de vger!
+
+Linus Torvalds es el árbitro final de todos los cambios aceptados en el
+kernel de Linux. Su dirección de correo electrónico es
+<torvalds@linux-foundation.org>. Recibe muchos correos electrónicos y, en
+este momento, muy pocos parches pasan por Linus directamente, por lo que
+normalmente debe hacer todo lo posible para -evitar- enviarle un correo
+electrónico.
+
+Si tiene un parche que corrige un error de seguridad explotable, envíe ese
+parche a security@kernel.org. Para errores graves, se debe mantener un
+poco de discreción y permitir que los distribuidores entreguen el parche a
+los usuarios; en esos casos, obviamente, el parche no debe enviarse a
+ninguna lista pública. Revise también
+Documentation/admin-guide/security-bugs.rst.
+
+Los parches que corrigen un error grave en un kernel en uso deben dirigirse
+hacia los maintainers estables poniendo una línea como esta::
+
+ CC: stable@vger.kernel.org
+
+en el área de sign-off de su parche (es decir, NO un destinatario de correo
+electrónico). También debe leer
+Documentation/process/stable-kernel-rules.rst además de este documento.
+
+Si los cambios afectan las interfaces del kernel para el usuario, envíe al
+maintainer de las MAN-PAGES (como se indica en el archivo MAINTAINERS) un
+parche de páginas de manual, o al menos una notificación del cambio, para
+que alguna información se abra paso en las páginas del manual. Los cambios
+de la API del espacio de usuario también deben copiarse en
+linux-api@vger.kernel.org.
+
+
+Sin MIME, enlaces, compresión o archivos adjuntos. Solo texto plano
+--------------------------------------------------------------------
+
+Linus y otros desarrolladores del kernel deben poder leer y comentar sobre
+los cambios que está enviando. Es importante para un desarrollador kernel
+poder "citar" sus cambios, utilizando herramientas estándar de correo
+electrónico, de modo que puedan comentar sobre partes específicas de su
+código.
+
+Por este motivo, todos los parches deben enviarse por correo electrónico
+"inline". La forma más sencilla de hacerlo es con ``git send-email``, que
+es muy recomendable. Un tutorial interactivo para ``git send-email`` está
+disponible en https://git-send-email.io.
+
+Si elige no usar ``git send-email``:
+
+.. warning::
+
+ Tenga cuidado con el ajuste de palabras de su editor que corrompe su
+ parche, si elige cortar y pegar su parche.
+
+No adjunte el parche como un archivo adjunto MIME, comprimido o no. Muchas
+populares aplicaciones de correo electrónico no siempre transmiten un MIME
+archivo adjunto como texto sin formato, por lo que es imposible comentar
+en su código. Linus también necesita un poco más de tiempo para procesar un
+archivo adjunto MIME, disminuyendo la probabilidad de que se acepte su
+cambio adjunto en MIME.
+
+Excepción: si su proveedor de correo está destrozando parches, entonces
+alguien puede pedir que los vuelva a enviar usando MIME.
+
+Consulte Documentation/process/email-clients.rst para obtener sugerencias
+sobre cómo configurar su cliente de correo electrónico para que envíe sus
+parches intactos.
+
+Responda a los comentarios de revisión
+---------------------------------------
+
+Es casi seguro que su parche recibirá comentarios de los revisores sobre
+maneras en que se pueda mejorar el parche, en forma de respuesta a su
+correo electrónico. Debe responder a esos comentarios; ignorar a los
+revisores es una buena manera de ser ignorado de vuelta. Simplemente puede
+responder a sus correos electrónicos para contestar a sus comentarios.
+Revisiones a los comentarios o preguntas que no conduzcan a un cambio de
+código deben casi con certeza generar un comentario o una entrada en el
+"changelog" para que el próximo revisor entienda lo que está pasando.
+
+Asegúrese de decirles a los revisores qué cambios está haciendo y de
+agradecerles que dediquen su tiempo. La revisión del código es un proceso
+agotador y lento, y los revisores a veces se ponen de mal humor. Sin
+embargo, incluso en ese caso, responda cortésmente y aborde los problemas
+que hayan señalado. Al enviar un siguiente versión, agregue un
+``patch changelog`` (registro de cambios en los parches) a la carta de
+presentación ("cover letter") o a parches individuales explicando la
+diferencia con la presentación anterior (ver
+:ref:`sp_the_canonical_patch_format`).
+
+Consulte Documentation/process/email-clients.rst para obtener
+recomendaciones sobre clientes de correo electrónico y normas de etiqueta
+en la lista de correo.
+
+.. _sp_resend_reminders:
+
+No se desanime o impaciente
+---------------------------
+
+Después de haber entregado su cambio, sea paciente y espere. Los revisores
+son personas ocupadas y es posible que no lleguen a su parche de inmediato.
+
+Érase una vez, los parches solían desaparecer en el vacío sin comentarios,
+pero el proceso de desarrollo funciona mejor que eso ahora. Debería
+recibir comentarios dentro de una semana más o menos; si eso no sucede,
+asegúrese de que ha enviado sus parches al lugar correcto. Espere un mínimo
+de una semana antes de volver a enviar o hacer ping a los revisores,
+posiblemente más durante periodos de mucho trabajo ocupados como "merge
+windows".
+
+También está bien volver a enviar el parche o la serie de parches después
+de un par de semanas con la palabra "RESEND" (reenviar) añadida a la línea
+de asunto::
+
+ [PATCH Vx RESEND] sub/sys: Resumen condensado de parche
+
+No incluya "RESEND" cuando envíe una versión modificada de su parche o
+serie de parches: "RESEND" solo se aplica al reenvío de un parche o serie
+de parches que no hayan sido modificados de ninguna manera con respecto a
+la presentación anterior.
+
+
+Incluya PATCH en el asunto
+--------------------------
+
+Debido al alto tráfico de correo electrónico a Linus y al kernel de Linux,
+es común prefijar su línea de asunto con [PATCH]. Esto le permite a Linus
+y otros desarrolladores del kernel distinguir más fácilmente los parches de
+otras discusiones por correo electrónico.
+
+``git send-email`` lo hará automáticamente.
+
+
+Firme su trabajo: el Certificado de Origen del Desarrollador
+------------------------------------------------------------
+
+Para mejorar el seguimiento de quién hizo qué, especialmente con parches
+que pueden filtrarse hasta su destino final a través de varias capas de
+maintainers, hemos introducido un procedimiento de "sign-off" (aprobación)
+en parches que se envían por correo electrónico.
+
+La aprobación es una simple línea al final de la explicación del parche,
+que certifica que usted lo escribió o que tiene derecho a enviarlo como un
+parche de código abierto. Las reglas son bastante simples: si usted puede
+certificar lo siguiente:
+
+Certificado de Origen del Desarrollador 1.1
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Al hacer una contribución a este proyecto, certifico que:
+
+ (a) La contribución fue creada en su totalidad o en parte por mí y
+ tengo derecho a enviarlo bajo la licencia de código abierto
+ indicada en el documento; o
+
+ (b) La contribución se basa en trabajo previo que, hasta donde yo
+ soy consciente, está cubierto por una licencia de código
+ abierto apropiada y tengo el derecho bajo esa licencia de
+ presentar tal trabajo con modificaciones, ya sean creadas en su
+ totalidad o en parte por mí, bajo la misma licencia de código
+ (salvo que sea permitido presentar bajo una licencia diferente),
+ tal y como se indica en el documento; o
+
+ (c) La contribución me fue proporcionada directamente por alguna
+ otra persona que certificó (a), (b) o (c) y no he modificado
+ esto.
+
+ (d) Entiendo y acepto que este proyecto y la contribución
+ son públicos y que un registro de la contribución (incluyendo
+ toda la información personal que envío con él, incluida mi
+ firma) es mantenida indefinidamente y puede ser redistribuida
+ de manera consistente con este proyecto o la(s) licencia(s) de
+ código abierto involucradas.
+
+entonces simplemente incluya una línea que rece::
+
+ Signed-off-by: Random J Developer <random@developer.example.org>
+
+usando su nombre real (lamentablemente, no pseudónimos ni contribuciones
+anónimas). Esto se hará por usted automáticamente si usa ``git commit -s``.
+Las reversiones de código también deben incluir "Signed-off-by".
+``git revert -s`` hace eso por usted.
+
+Algunas personas también ponen etiquetas adicionales al final. Simplemente
+serán ignoradas por ahora, pero puede hacer esto para marcar procedimientos
+internos de su empresa o simplemente señalar algún detalle especial sobre
+la firma.
+
+Cualquier otro SoB (Signed-off-by:) después del SoB del autor es de
+personas que manipulen y transporten el parche, pero no participaron en su
+desarrollo. Las cadenas de SoB deben reflejar la ruta **real** del parche
+de cómo se propagó a los maintainers y, en última instancia, a Linus, con
+la primera entrada de SoB que señala la autoría principal de un solo autor.
+
+
+Cuándo usar Acked-by:, Cc: y Co-developed-by por:
+-------------------------------------------------
+
+La etiqueta Signed-off-by: indica que el firmante estuvo involucrado en el
+desarrollo del parche, o que él/ella se encontraba en el camino de entrega
+del parche.
+
+Si una persona no estuvo directamente involucrada en la preparación o
+administración de un parche pero desea expresar y registrar su aprobación,
+entonces puede pedir que se agregue una línea Acked-by: al registro de
+cambios del parche.
+
+Acked-by: a menudo lo usa el maintainer del código afectado cuando ese
+maintainer no contribuyó ni envió el parche.
+
+Acked-by: no es tan formal como Signed-off-by:. Es una manera de marcar que
+el "acker" ha revisado al menos ese parche y ha indicado su aceptación. Por
+los merge de parches a veces convertirán manualmente el "sí, me parece bien"
+de un acker en un Acked-by: (pero tenga en cuenta que por lo general es
+mejor pedir un acuse de recibo explícito).
+
+Acked-by: no necesariamente indica el reconocimiento de todo el parche.
+Por ejemplo, si un parche afecta a varios subsistemas y tiene un
+Acked-by: de un maintainer del subsistema, entonces esto generalmente
+indica el reconocimiento de solo la parte que afecta el código de ese
+maintainer. Buen juicio debe ejercitarse aquí. En caso de duda, la gente
+debe consultar la discusión original en los archivos de la lista de correo.
+
+Si una persona ha tenido la oportunidad de comentar un parche, pero no lo
+ha hecho, puede incluir opcionalmente una etiqueta ``Cc:`` al parche.
+Esta es la única etiqueta que se puede agregar sin una acción explícita por
+parte de la persona a la que se nombre - pero debe indicar que esta persona
+fue copiada en el parche. Esta etiqueta documenta que las partes
+potencialmente interesadas han sido incluidas en la discusión.
+
+Co-developed-by: establece que el parche fue co-creado por múltiples
+desarrolladores; se utiliza para dar atribución a los coautores (además del
+autor atribuido por la etiqueta From:) cuando varias personas trabajan en
+un solo parche. Ya que Co-developed-by: denota autoría, cada
+Co-developed-by: debe ser inmediatamente seguido de Signed-off-by: del
+coautor asociado. Se mantiene el procedimiento estándar, es decir, el orden
+de las etiquetas Signed-off-by: debe reflejar el historial cronológico del
+parche en la medida de lo posible, independientemente de si el autor se
+atribuye a través de From: o Co-developed-by:. Cabe destacar que el último
+Signed-off-by: siempre debe ser del desarrollador que envía el parche.
+
+Tenga en cuenta que la etiqueta From: es opcional cuando el autor From: es
+también la persona (y correo electrónico) enumerados en la línea From: del
+encabezado del correo electrónico.
+
+Ejemplo de un parche enviado por el From: autor::
+
+ <changelog>
+
+ Co-developed-by: Primer coautor <primer@coauthor.example.org>
+ Signed-off-by: Primer coautor <primer@coauthor.example.org>
+ Co-developed-by: Segundo coautor <segundo@coautor.ejemplo.org>
+ Signed-off-by: Segundo coautor <segundo@coautor.ejemplo.org>
+ Signed-off-by: Autor del From <from@author.example.org>
+
+Ejemplo de un parche enviado por un Co-developed-by: autor::
+
+ From: Autor del From <from@author.example.org>
+
+ <changelog>
+
+ Co-developed-by: Co-Autor aleatorio <aleatorio@coauthor.example.org>
+ Signed-off-by: Coautor aleatorio <aleatorio@coauthor.example.org>
+ Signed-off-by: Autor del From <from@author.example.org>
+ Co-developed-by: Coautor que envió <sub@coauthor.example.org>
+ Signed-off-by: Coautor que envía <sub@coauthor.example.org>
+
+Uso de Reported-by:, Tested-by:, Reviewed-by:, Suggested-by: y Fixes:
+----------------------------------------------------------------------
+
+La etiqueta Reported-by (Reportado-por) otorga crédito a las personas que
+encuentran errores y los reportan. Por favor, tenga en cuenta que si se
+informó de un error en privado, debe pedir primero permiso antes de usar la
+etiqueta Reported-by. La etiqueta está destinada a errores; por favor no la
+use para acreditar peticiones de características.
+
+Una etiqueta Tested-by: indica que el parche se probó con éxito (en algún
+entorno) por la persona nombrada. Esta etiqueta informa a los maintainers
+de que se han realizado algunas pruebas, proporciona un medio para ubicar
+"testers" (gente que pruebe) otros parches futuros y asegura el crédito
+para los testers.
+
+Reviewed-by: en cambio, indica que el parche ha sido revisado y encontrado
+aceptable de acuerdo con la Declaración del Revisor:
+
+Declaración de Supervisión del Revisor
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Al ofrecer mi etiqueta Reviewed-by:, afirmo que:
+
+(a) He llevado a cabo una revisión técnica de este parche para
+evaluar su idoneidad y preparación para su inclusión en
+el kernel principal.
+
+(b) Cualquier problema, inquietud o pregunta relacionada con el parche
+han sido comunicados al remitente. Estoy satisfecho
+con la respuesta del remitente a mis comentarios.
+
+(c) Si bien puede haber cosas que podrían mejorarse con esta
+entrega, creo que es, en este momento, (1) una
+modificación valiosa al kernel, y (2) libre de conocidas
+cuestiones que argumentarían en contra de su inclusión.
+
+(d) Si bien he revisado el parche y creo que es correcto,
+no hago (a menos que se indique explícitamente en otro lugar) ninguna
+garantía o avales de que logrará su definido
+propósito o función en cualquier situación dada.
+
+Una etiqueta Reviewed-by es una declaración de opinión de que el parche es
+una modificación apropiada al kernel sin que haya ningún problema grave
+a nivel técnico. Cualquier revisor interesado (que haya hecho el trabajo)
+puede ofrecer una etiqueta Reviewed-by para un parche. Esta etiqueta sirve
+para dar crédito a revisores e informar a los maintainers del grado de
+revisión que se ha hecho en el parche. Las etiquetas Reviewed-by, cuando
+las otorgan revisores conocidos por entender del tema y realizar
+revisiones exhaustivas, normalmente aumentan la probabilidad de que su
+parche entre en el kernel.
+
+Las etiquetas Tested-by y Reviewed-by, una vez recibidas en la lista de
+correo por el tester o revisor, deben ser incluidas por el autor de los
+parches pertinentes al enviar próximas versiones. Sin embargo, si el parche
+ha cambiado sustancialmente en la siguiente versión, es posible que estas
+etiquetas ya no sean aplicables y, por lo tanto, deben eliminarse. Por lo
+general, se debe mencionar la eliminación de las etiquetas Tested-by o
+Reviewed-by de alguien en el registro de cambios del parche (después del
+separador '---').
+
+Una etiqueta Suggested-by: indica que la idea del parche es sugerida por la
+persona nombrada y asegura el crédito a la persona por la idea. Tenga en
+cuenta que esto no debe agregarse sin el permiso del "reporter",
+especialmente si la idea no fue publicada en un foro público. Dicho esto,
+si diligentemente acreditamos a los reporters de ideas, con suerte, se
+sentirán inspirados para ayudarnos nuevamente en el futuro.
+
+Una etiqueta Fixes: indica que el parche corrige un problema en un commit
+anterior. Esto se utiliza para facilitar descubrir dónde se originó un
+error, lo que puede ayudar a revisar una corrección de errores. Esta
+etiqueta también ayuda al equipo del kernel estable a determinar qué
+versiones estables del kernel deberían recibir su corrección. Este es el
+método preferido para indicar un error corregido por el parche. Revise
+:ref:`describe_changes` para más detalles.
+
+Nota: Adjuntar una etiqueta Fixes: no subvierte las reglas estables del
+proceso del kernel ni el requisito de CC: stable@vger.kernel.org en todos
+los parches candidatos de ramas estables. Para obtener más información, lea
+Documentation/process/stable-kernel-rules.rst.
+
+.. _sp_the_canonical_patch_format:
+
+Formato de parche canónico
+---------------------------
+
+Esta sección describe cómo debe darse formato al propio parche. Tenga en
+cuenta que, si tiene sus parches almacenados en un repositorio ``git``, el
+parche con formato adecuado se puede obtener con ``git format-patch``. Las
+herramientas no pueden crear el texto necesario, sin embargo, así que lea
+las instrucciones a continuación de todos modos.
+
+La línea de asunto del parche canónico es::
+
+ Asunto: [PATCH 001/123] subsistema: frase de resumen
+
+El cuerpo del mensaje del parche canónico contiene lo siguiente:
+
+ - Una línea ``from`` que especifica el autor del parche, seguida de una
+ línea vacía (solo es necesario si la persona que envía el parche no es
+ el autor).
+
+ - El cuerpo de la explicación, línea envuelta en 75 columnas, que se
+ copiara en el registro de cambios permanente para describir este parche.
+
+ - Una línea vacía.
+
+ - Las líneas ``Signed-off-by:``, descritas anteriormente, que
+ también vaya en el registro de cambios.
+
+ - Una línea de marcador que contiene simplemente ``---``.
+
+ - Cualquier comentario adicional que no sea adecuado para el registro de
+ cambios.
+
+ - El parche real (output de ``diff``).
+
+El formato de la línea de asunto hace que sea muy fácil ordenar los correos
+electrónicos alfabéticamente por línea de asunto - prácticamente cualquier
+lector de correo electrónico permite esto, ya que debido a que el número de
+secuencia se rellena con ceros, el orden numérico y alfabético es el mismo.
+
+El ``subsistema`` en el asunto del correo electrónico debe identificar qué
+área o subsistema del kernel está siendo parcheado.
+
+La ``frase de resumen`` en el Asunto del correo electrónico debe describir
+de forma concisa el parche que contiene ese correo electrónico. La
+``frase resumen`` no debe ser un nombre de archivo. No use la mismo ``frase
+resumen`` para cada parche en una serie completa de parches (donde una
+`` serie de parches`` (patch series) es una secuencia ordenada de múltiples
+parches relacionados).
+
+Tenga en cuenta que la ``frase de resumen`` de su correo electrónico se
+convierte en un identificador global único para ese parche. Se propaga por
+hasta el registro de cambios de ``git``. La ``frase resumida`` se puede
+usar más adelante en discusiones de desarrolladores que se refieran al
+parche. La gente querrá buscar en Google la ``frase de resumen`` para leer
+la discusión al respecto del parche. También será lo único que la gente
+podrá ver rápidamente cuando, dos o tres meses después, estén pasando por
+quizás miles de parches usando herramientas como ``gitk`` o ``git log
+--oneline``.
+
+Por estas razones, el ``resumen`` no debe tener más de 70-75 caracteres, y
+debe describir tanto lo que cambia el parche como por qué el parche podría
+ser necesario. Es un reto ser tanto sucinto como descriptivo, pero eso es
+lo que un resumen bien escrito debería hacer.
+
+La ``frase de resumen`` puede estar precedida por etiquetas encerradas en
+corchetes: "Asunto: [PATCH <etiqueta>...] <frase de resumen>". Las
+etiquetas no se consideran parte de la frase de resumen, pero describen
+cómo debería ser tratado el parche. Las etiquetas comunes pueden incluir un
+descriptor de versión si las múltiples versiones del parche se han enviado
+en respuesta a comentarios (es decir, "v1, v2, v3") o "RFC" para indicar
+una solicitud de comentarios.
+
+Si hay cuatro parches en una serie de parches, los parches individuales
+pueden enumerarse así: 1/4, 2/4, 3/4, 4/4. Esto asegura que los
+desarrolladores entiendan el orden en que se deben aplicar los parches y
+que han revisado o aplicado todos los parches de la serie de parches.
+
+Aquí hay algunos buenos ejemplos de Asuntos::
+
+ Asunto: [PATCH 2/5] ext2: mejorar la escalabilidad de la búsqueda de mapas de bits
+ Asunto: [PATCH v2 27/01] x86: corregir el seguimiento de eflags
+ Asunto: [PATCH v2] sub/sys: resumen conciso del parche
+ Asunto: [PATCH v2 M/N] sub/sys: resumen conciso del parche
+
+La línea ``from`` debe ser la primera línea en el cuerpo del mensaje,
+y tiene la forma::
+
+ From: Autor del parche <autor@ejemplo.com>
+
+La línea ``From`` especifica quién será acreditado como el autor del parche
+en el registro de cambios permanente. Si falta la línea ``from``, entonces
+la línea ``From:`` del encabezado del correo electrónico se usará para
+determinar el autor del parche en el registro de cambios.
+
+La explicación estará incluida en el commit del changelog permanente, por
+lo que debería tener sentido para un lector competente que hace mucho tiempo
+ha olvidado los detalles de la discusión que podrían haber llevado a
+este parche. Incluidos los síntomas del fallo que el parche trate
+(mensajes de registro del kernel, mensajes de oops, etc.) son especialmente
+útiles para personas que podrían estar buscando en los registros de
+commits en busca de la aplicación del parche. El texto debe estar escrito
+con tal detalle que cuando se lea semanas, meses o incluso años después,
+pueda dar al lector la información necesaria y detalles para comprender el
+razonamiento de **por qué** se creó el parche.
+
+Si un parche corrige una falla de compilación, puede que no sea necesario
+incluir _todos_ los errores de compilación; pero lo suficiente como para
+que sea probable que alguien que busque el parche puede encontrarlo. Como
+en la ``frase de resumen``, es importante ser tanto sucinto como
+descriptivo.
+
+La línea marcadora ``---`` cumple el propósito esencial de marcar para
+herramientas de manejo de parches donde termina el mensaje de registro de
+cambios.
+
+Un buen uso de los comentarios adicionales después del marcador ``---`` es
+para ``diffstat``, para mostrar qué archivos han cambiado, y el número de
+líneas insertadas y eliminadas por archivo. Un ``diffstat`` es
+especialmente útil en parches más grandes. Si va a incluir un ``diffstat``
+después del marcador ``---``, utilice las opciones ``diffstat``
+``-p 1 -w 70`` para que los nombres de archivo se enumeran desde la parte
+superior del árbol de fuentes del kernel y no use demasiado espacio
+horizontal (que encaje fácilmente en 80 columnas, tal vez con alguna
+indentación). (``git`` genera diffstats apropiados por defecto).
+
+Otros comentarios relevantes solo en el momento o para el maintainer, pero
+no adecuados para el registro de cambios permanente, también debe ir aquí.
+Un buen ejemplo de tales comentarios podría ser ``registros de cambios de
+parches`` que describen qué ha cambiado entre la versión v1 y v2 del
+parche.
+
+Por favor, ponga esta información **después** de la línea ``---`` que
+separa el registro de cambios del resto del parche. La información de la
+versión no forma parte del registro de cambios que se incluye con el árbol
+git. Es información adicional para los revisores. Si se coloca encima de la
+etiquetas de commit, necesita interacción manual para eliminarlo. Si esta
+debajo de la línea de separación, se quita automáticamente al aplicar el
+parche::
+
+ <mensaje de commit>
+ ...
+ Signed-off-by: Autor <autor@correo>
+ ---
+ V2 -> V3: función auxiliar redundante eliminada
+ V1 -> V2: estilo de código limpio y comentarios de revisión abordados
+
+ ruta/al/archivo | 5+++--
+ ...
+
+Revise más detalles sobre el formato de parche adecuado en las siguientes
+referencias
+
+.. _sp_backtraces:
+
+Retrocesos en mensajes de confirmación
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Los "backtraces" (deshacer el camino) ayuda a documentar la cadena de
+llamadas que conducen a un problema. Sin embargo, no todos los rastreos son
+útiles. Por ejemplo, las tempranas cadenas de llamadas de inicio son únicas
+y obvias. Sin embargo, al copiar la salida completa de dmesg textualmente,
+incluye información que distrae, como marcas de tiempo, listas de módulos,
+registro y volcados de pila.
+
+Por lo tanto, los backtraces más útiles deben contener los datos
+relevantes de la información vertida, lo que hace que sea más fácil
+centrarse en el verdadero tema. Este es un ejemplo de un backtrace bien
+recortado::
+
+ error de acceso de MSR no verificado: WRMSR a 0xd51 (intentó escribir 0x0000000000000064)
+ en rIP: 0xffffffffae059994 (native_write_msr+0x4/0x20)
+ Rastreo de llamadas:
+ mba_wrmsr
+ update_domains
+ rdtgroup_mkdir
+
+.. _sp_explicit_in_reply_to:
+
+In-Reply-To explicitos en las cabeceras
+---------------------------------------
+
+Puede ser útil agregar manualmente encabezados In-Reply-To: a un parche
+(por ejemplo, al usar ``git send-email``) para asociar el parche con una
+discusión anterior relevante, por ejemplo para vincular una corrección de
+errores al correo electrónico con el informe de errores. Sin embargo, para
+una serie de parches múltiples, generalmente es mejor evitar usar
+In-Reply-To: para vincular a versiones anteriores de la serie. De esta
+forma, varias versiones del parche no se convierten en un inmanejable
+bosque de referencias en clientes de correo electrónico. Si un enlace es
+útil, puede usar el redirector https://lore.kernel.org/ (por ejemplo, en
+el texto de la carta de introducción del correo electrónico) para vincular
+a una versión anterior de la serie de parches.
+
+
+Proporcionar información de árbol base
+--------------------------------------
+
+Cuando otros desarrolladores reciben sus parches y comienzan el proceso de
+revisión, a menudo es útil para ellos saber en qué parte del historial del
+árbol deben colocar su trabajo. Esto es particularmente útil para CI
+automatizado de procesos que intentan ejecutar una serie de pruebas para
+establecer la calidad de su envío antes de que el maintainer comience la
+revisión.
+
+Si está utilizando ``git format-patch`` para generar sus parches, puede
+incluir automáticamente la información del árbol base en su envío usando el
+parámetro ``--base``. La forma más fácil y conveniente de usar esta opción
+es con "topical branches" (ramas de temas)::
+
+ $ git checkout -t -b my-topical-branch master
+ Branch 'my-topical-branch' set up to track local branch 'master'.
+ Switched to a new branch 'my-topical-branch'
+
+ [realice sus cambios y ediciones]
+
+ $ git format-patch --base=auto --cover-letter -o outgoing/ master
+ outgoing/0000-cover-letter.patch
+ outgoing/0001-First-Commit.patch
+ outgoing/...
+
+Cuando abra ``outgoing/0000-cover-letter.patch`` para editar, tenga en
+cuenta que tendrá el tráiler ``base-commit:`` al final, que proporciona al
+revisor y a las herramientas de CI suficiente información para realizar
+correctamente ``git am`` sin preocuparse por los conflictos::
+
+ $ git checkout -b patch-review [base-commit-id]
+ Switched to a new branch 'patch-review'
+ $ git am patches.mbox
+ Applying: First Commit
+ Applying: ...
+
+Consulte ``man git-format-patch`` para obtener más información al respecto
+de esta opción.
+
+.. Note::
+
+ La función ``--base`` se introdujo en la versión 2.9.0 de git.
+
+Si no está utilizando git para dar forma a sus parches, aún puede incluir
+el mismo tráiler ``base-commit`` para indicar el hash de confirmación del
+árbol en que se basa su trabajo. Debe agregarlo en la carta de presentación
+o en el primer parche de la serie y debe colocarse ya sea bajo la línea
+``---`` o en la parte inferior de todos los demás contenido, justo antes de
+su firma del correo electrónico.
+
+
+Referencias
+-----------
+
+"The perfect patch" (tpp) por Andrew Morton.
+ <https://www.ozlabs.org/~akpm/stuff/tpp.txt>
+
+"Linux kernel patch submission format" por Jeff Garzik.
+ <https://web.archive.org/web/20180829112450/http://linux.yyz.us/patch-format.html>
+
+"How to piss off a kernel subsystem maintainer" por Greg Kroah-Hartman.
+ <http://www.kroah.com/log/linux/maintainer.html>
+
+ <http://www.kroah.com/log/linux/maintainer-02.html>
+
+ <http://www.kroah.com/log/linux/maintainer-03.html>
+
+ <http://www.kroah.com/log/linux/maintainer-04.html>
+
+ <http://www.kroah.com/log/linux/maintainer-05.html>
+
+ <http://www.kroah.com/log/linux/maintainer-06.html>
+
+NO!!!! Gente, no mas bombas enormes de parches a linux-kernel@vger.kernel.org!
+ <https://lore.kernel.org/r/20050711.125305.08322243.davem@davemloft.net>
+
+Kernel Documentation/process/coding-style.rst
+
+Email de Linus Torvalds sobre la forma canónica de los parches:
+ <https://lore.kernel.org/r/Pine.LNX.4.58.0504071023190.28951@ppc970.osdl.org>
+
+"On submitting kernel patches" por Andi Kleen
+ Algunas estrategias para conseguir incluir cambios complicados o
+ controvertidos.
+
+ http://halobates.de/on-submitting-patches.pdf
diff --git a/Documentation/translations/sp_SP/wrappers/memory-barriers.rst b/Documentation/translations/sp_SP/wrappers/memory-barriers.rst
new file mode 100644
index 000000000000..50715b7d51b9
--- /dev/null
+++ b/Documentation/translations/sp_SP/wrappers/memory-barriers.rst
@@ -0,0 +1,19 @@
+.. SPDX-License-Identifier: GPL-2.0
+ This is a simple wrapper to bring memory-barriers.txt (Spanish
+ translation) into the RST world until such a time as that file can be
+ converted directly.
+
+====================================
+Barreras de Memoria del kernel Linux
+====================================
+
+.. raw:: latex
+
+ \footnotesize
+
+.. include:: ../memory-barriers.txt
+ :literal:
+
+.. raw:: latex
+
+ \normalsize
diff --git a/Documentation/translations/zh_CN/core-api/errseq.rst b/Documentation/translations/zh_CN/core-api/errseq.rst
new file mode 100644
index 000000000000..815fb303ea2f
--- /dev/null
+++ b/Documentation/translations/zh_CN/core-api/errseq.rst
@@ -0,0 +1,145 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/core-api/errseq.rst
+
+:翻译:
+
+ 周彬彬 Binbin Zhou <zhoubinbin@loongson.cn>
+
+:校译:
+
+ å´æƒ³æˆ Wu Xiangcheng <bobwxc@email.cn>
+
+================
+errseq_tæ•°æ®ç±»åž‹
+================
+
+``errseq_t`` 是一ç§åœ¨ä¸€ä¸ªåœ°æ–¹è®°å½•错误的方法,并å…è®¸ä»»æ„æ•°é‡çš„ ``订阅者`` 判断自上
+æ¬¡é‡‡æ ·ç‚¹ä»¥æ¥æ˜¯å¦å‘生了å˜åŒ–。
+
+最åˆçš„ç”¨ä¾‹æ˜¯è·Ÿè¸ªæ–‡ä»¶åŒæ­¥ç³»ç»Ÿè°ƒç”¨ï¼ˆ ``fsync``, ``fdatasync``, ``msync`` å’Œ
+``sync_file_range`` )的错误,但它也å¯ä»¥ç”¨äºŽå…¶ä»–情况。
+
+它被实现为一个无符å·çš„32ä½å€¼ã€‚低ä½è¢«æŒ‡å®šä¿å­˜é”™è¯¯ä»£ç ï¼ˆåœ¨1å’ŒMAX_ERRNO之间)。高ä½
+ç”¨ä½œè®¡æ•°å™¨ã€‚è¿™é‡Œæ˜¯ç”¨åŽŸå­æ“ä½œè€Œä¸æ˜¯é”æ¥å®Œæˆçš„,因此å¯ä»¥ä»Žä»»ä½•上下文中调用这些函数。
+
+请注æ„,如果频ç¹è®°å½•新错误,则存在冲çªé£Žé™©ï¼Œå› ä¸ºæˆ‘们用作计数器的ä½å¾ˆå°‘。
+
+ä¸ºäº†ç¼“è§£è¿™ç§æƒ…况,错误值和计数器之间的ä½è¢«ç”¨ä½œä¸€ä¸ªæ ‡å¿—ï¼Œä»¥åˆ¤æ–­è‡ªè®°å½•æ–°å€¼ä»¥æ¥æ˜¯å¦
+对该值进行了采样。这使我们能够é¿å…åœ¨ä¸Šæ¬¡è®°å½•é”™è¯¯åŽæ²¡æœ‰äººå–样的情况下碰撞计数器。
+
+因此,我们得到了一个类似这样的值:
+
++--------------------------------------+------+------------------------+
+| 31..13 | 12 | 11..0 |
++--------------------------------------+------+------------------------+
+| 计数器 | 标志 | 错误值 |
++--------------------------------------+------+------------------------+
+
+总体æ€è·¯æ˜¯è®© ``观察者`` 对errseq_t值进行采样,并将其ä¿ç•™ä¸ºè¿è¡Œæ¸¸æ ‡ã€‚该值ç¨åŽå¯ç”¨
+于判断自采样完æˆåŽæ˜¯å¦å‘生了任何新错误,并原å­åœ°è®°å½•检查时的状æ€ã€‚这使得我们能在
+ä¸€ä¸ªåœ°æ–¹è®°å½•é”™è¯¯ï¼Œç„¶åŽæœ‰è®¸å¤š ``观察者`` å¯ä»¥åˆ¤æ–­è‡ªä¸Šæ¬¡æ£€æŸ¥ä»¥æ¥è¯¥å€¼æ˜¯å¦å‘生了å˜åŒ–。
+
+æ–°çš„errseq_t应始终清零。全零的errseq_t值是从未出现错误的特殊(但常è§ï¼‰æƒ…况。因此,
+如果您希望知é“自首次åˆå§‹åŒ–ä»¥æ¥æ˜¯å¦æ›¾ç»æœ‰è¿‡é”™è¯¯é›†ï¼Œåˆ™å…¨é›¶å€¼è¢«ç”¨ä½œ ``纪元`` 。
+
+API的使用方法
+=============
+
+让我给你们讲一个关于员工droneçš„æ•…äº‹ã€‚çŽ°åœ¨ï¼Œä»–æ€»ä½“ä¸Šæ˜¯ä¸ªå¥½å‘˜å·¥ï¼Œä½†å…¬å¸æœ‰ç‚¹...管ç†
+ç¹é‡ã€‚他今天必须å‘77å主管汇报,明天 ``å¤§è€æ¿`` è¦ä»Žå¤–地赶æ¥ï¼Œä»–肯定也会考验这个
+坿€œçš„家伙。
+
+他们都把工作交给他去åš---多到他都记ä¸ä½è°äº¤ç»™ä»–ä»€ä¹ˆäº†ï¼Œä½†è¿™å¹¶ä¸æ˜¯ä»€ä¹ˆå¤§é—®é¢˜ã€‚主管
+ä»¬åªæƒ³çŸ¥é“他什么时候完æˆä»–们迄今为止交给他的所有工作,以åŠè‡ªä»Žä»–们上次询问以æ¥ä»–
+是å¦çŠ¯äº†ä»»ä½•é”™è¯¯ã€‚
+
+ä»–å¯èƒ½åœ¨ä»–们实际上并没有交给他的工作上犯了错误,但他无法在那么详细的层é¢ä¸Šè®°å½•事
+æƒ…ï¼Œä»–æ‰€èƒ½è®°å¾—çš„åªæ˜¯ä»–最近犯的错误。
+
+䏋颿˜¯æˆ‘们 ``worker_drone`` 的表达å¼::
+
+ struct worker_drone {
+ errseq_t wd_err; /* 用æ¥è®°å½•错误 */
+ };
+
+æ¯å¤©ï¼Œ ``worker_drone`` 都是以一张白纸开始的::
+
+ struct worker_drone wd;
+
+ wd.wd_err = (errseq_t)0;
+
+主管们进æ¥åŽå¯¹å½“å¤©çš„å·¥ä½œè¿›è¡Œåˆæ­¥äº†è§£ã€‚他们并ä¸å…³å¿ƒåœ¨ä»–们观察开始之å‰å‘生的任何事
+情::
+
+ struct supervisor {
+ errseq_t s_wd_err; /* wd_errçš„ç§æœ‰â€œæ¸¸æ ‡â€ */
+ spinlock_t s_wd_err_lock; /* ä¿æŠ¤s_wd_err */
+ }
+
+ struct supervisor su;
+
+ su.s_wd_err = errseq_sample(&wd.wd_err);
+ spin_lock_init(&su.s_wd_err_lock);
+
+现在他们开始给他布置任务。æ¯éš”å‡ åˆ†é’Ÿï¼Œä»–ä»¬å°±è¦æ±‚他完æˆè¿„今为止交给他的所有工作。
+ç„¶åŽé—®ä»–æ˜¯å¦æœ‰çŠ¯ä»»ä½•é”™è¯¯::
+
+ spin_lock(&su.su_wd_err_lock);
+ err = errseq_check_and_advance(&wd.wd_err, &su.s_wd_err);
+ spin_unlock(&su.su_wd_err_lock);
+
+到目å‰ä¸ºæ­¢ï¼Œå®ƒåªæ˜¯ä¸æ–­è¿”回0。
+
+现在,这家公å¸çš„è€æ¿éžå¸¸å啬,给了他ä¸åˆæ ¼çš„设备æ¥å®Œæˆä»–的工作。å¶å°”设备会出现故
+障,导致他犯错。他é‡é‡åœ°å¹äº†ä¸€å£æ°”,并把它记录下æ¥::
+
+ errseq_set(&wd.wd_err, -EIO);
+
+...ç„¶åŽç»§ç»­å·¥ä½œã€‚ä¸»ç®¡ä»¬æœ€ç»ˆä¼šå†æ¬¡æ£€æŸ¥ï¼Œä»–们在下次检查时都会å‘现这个错误。åŽç»­çš„è°ƒ
+用将返回0,直到记录下å¦ä¸€ä¸ªé”™è¯¯ï¼Œæ­¤æ—¶å°†å‘æ¯ä¸ªè°ƒç”¨æŠ¥å‘Šä¸€æ¬¡ã€‚
+
+请注æ„,主管们无法知é“他们犯了多少错误,åªèƒ½çŸ¥é“è‡ªä¸Šæ¬¡æ£€æŸ¥ä»¥æ¥æ˜¯å¦çŠ¯äº†ä¸€ä¸ªé”™è¯¯ï¼Œ
+以åŠè®°å½•的最新值。
+
+å¶å°”ï¼Œå¤§è€æ¿ä¼šæ¥æŠ½æŸ¥ï¼Œè¦æ±‚员工为他åšä¸€æ¬¡æ€§çš„工作。他并ä¸åƒä¸»ç®¡ä»¬é‚£æ ·å…¨èŒè§‚察员工,
+但他确实需è¦çŸ¥é“在他的工作处ç†è¿‡ç¨‹ä¸­æ˜¯å¦å‘生了错误。
+
+ä»–åªéœ€å¯¹å‘˜å·¥å½“å‰çš„errseq_t进行采样,然åŽç”¨å®ƒæ¥åˆ¤æ–­åŽæ¥æ˜¯å¦å‘生了错误::
+
+ errseq_t since = errseq_sample(&wd.wd_err);
+ /* æäº¤ä¸€äº›å·¥ä½œï¼Œç­‰å¾…å®Œæˆ */
+ err = errseq_check(&wd.wd_err, since);
+
+ç”±äºŽä»–åªæ˜¯è¦åœ¨é‚£ä¸ªç‚¹ä¹‹åŽä¸¢å¼ƒ ``since`` ,所以他ä¸éœ€è¦åœ¨è¿™é‡ŒæŽ¨è¿›å®ƒã€‚åŒæ—¶ä»–也ä¸éœ€è¦
+任何é”,因为它ä¸èƒ½è¢«å…¶ä»–人使用。
+
+åºåˆ—化更新errseq_t游标
+======================
+
+请注æ„,errseq_t API在check_and_advance_operation期间ä¸ä¿æŠ¤errseq_tæ¸¸æ ‡ã€‚åªæœ‰å…¸åž‹
+çš„é”™è¯¯ä»£ç æ˜¯è¢«åŽŸå­åŒ–处ç†çš„ã€‚åœ¨å¤šä»»åŠ¡åŒæ—¶ä½¿ç”¨åŒä¸€ä¸ªerrseq_t游标的情况下,对该游标
+的更新进行åºåˆ—化是很é‡è¦çš„。
+
+如果ä¸è¿™æ ·åšï¼Œé‚£ä¹ˆæ¸¸æ ‡å°±æœ‰å¯èƒ½å‘åŽç§»åŠ¨ã€‚åœ¨è¿™ç§æƒ…况下,åŒä¸€ä¸ªé”™è¯¯å¯èƒ½è¢«æŠ¥å‘Šå¤šæ¬¡ã€‚
+
+因此,通常先执行errseq_checkæ£€æŸ¥æ˜¯å¦æœ‰ä»»ä½•å˜åŒ–,然åŽåœ¨èŽ·å–é”åŽæ‰æ‰§è¡Œ
+errseq_check_and_advance。例如::
+
+ if (errseq_check(&wd.wd_err, READ_ONCE(su.s_wd_err)) {
+ /* su.s_wd_err被s_wd_err_lockä¿æŠ¤ */
+ spin_lock(&su.s_wd_err_lock);
+ err = errseq_check_and_advance(&wd.wd_err, &su.s_wd_err);
+ spin_unlock(&su.s_wd_err_lock);
+ }
+
+这就é¿å…äº†è‡ªä¸Šæ¬¡æ£€æŸ¥ä»¥æ¥æ²¡æœ‰ä»»ä½•å˜åŒ–çš„å¸¸è§æƒ…况下的自旋é”。
+
+函数
+====
+
+该API在以下内核代ç ä¸­:
+
+lib/errseq.c
diff --git a/Documentation/translations/zh_CN/core-api/index.rst b/Documentation/translations/zh_CN/core-api/index.rst
index 37756d240b5e..922cabf7b5dd 100644
--- a/Documentation/translations/zh_CN/core-api/index.rst
+++ b/Documentation/translations/zh_CN/core-api/index.rst
@@ -48,12 +48,12 @@
circular-buffers
generic-radix-tree
packing
+ this_cpu_ops
-Todolist:
-
+=======
+Todolist:
- this_cpu_ops
timekeeping
errseq
diff --git a/Documentation/translations/zh_CN/core-api/local_ops.rst b/Documentation/translations/zh_CN/core-api/local_ops.rst
index 41e4525038e8..eb5423f60f17 100644
--- a/Documentation/translations/zh_CN/core-api/local_ops.rst
+++ b/Documentation/translations/zh_CN/core-api/local_ops.rst
@@ -185,7 +185,7 @@ UP之间没有ä¸åŒçš„行为,在你的架构的 ``local.h`` 中包括 ``asm-g
static void __exit test_exit(void)
{
- del_timer_sync(&test_timer);
+ timer_shutdown_sync(&test_timer);
}
module_init(test_init);
diff --git a/Documentation/translations/zh_CN/core-api/this_cpu_ops.rst b/Documentation/translations/zh_CN/core-api/this_cpu_ops.rst
new file mode 100644
index 000000000000..bea5ee8eb8a0
--- /dev/null
+++ b/Documentation/translations/zh_CN/core-api/this_cpu_ops.rst
@@ -0,0 +1,285 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/core-api/this_cpu_ops.rst
+
+:翻译:
+
+ 周彬彬 Binbin Zhou <zhoubinbin@loongson.cn>
+
+:校译:
+
+ å´æƒ³æˆ Wu Xiangcheng <bobwxc@email.cn>
+
+============
+this_cpuæ“作
+============
+
+:作者: Christoph Lameter, 2014年8月4日
+:作者: Pranith Kumar, 2014年8月2日
+
+this_cpuæ“作是一ç§ä¼˜åŒ–è®¿é—®ä¸Žå½“å‰æ‰§è¡Œå¤„ç†å™¨ç›¸å…³çš„æ¯CPUå˜é‡çš„æ–¹æ³•。这是通过使用段寄
+存器(或专用寄存器,cpu在其中永久存储特定处ç†å™¨çš„æ¯CPU区域的起始)æ¥å®Œæˆçš„。
+
+this_cpuæ“作将æ¯CPUå˜é‡çš„åç§»é‡æ·»åŠ åˆ°å¤„ç†å™¨ç‰¹å®šçš„æ¯CPU基å€ä¸Šï¼Œå¹¶å°†è¯¥æ“作编ç åˆ°å¯¹
+æ¯CPUå˜é‡è¿›è¡Œæ“作的指令中。
+
+è¿™æ„味ç€åœ¨åç§»é‡çš„计算和对数æ®çš„æ“ä½œä¹‹é—´ä¸å­˜åœ¨åŽŸå­æ€§é—®é¢˜ã€‚因此,没有必è¦ç¦ç”¨æŠ¢å 
+或中断æ¥ç¡®ä¿å¤„ç†å™¨åœ¨è®¡ç®—地å€å’Œæ•°æ®æ“作之间ä¸è¢«æ”¹å˜ã€‚
+
+读å–-修改-写入æ“作特别值得关注。通常处ç†å™¨å…·æœ‰ç‰¹æ®Šçš„低延迟指令,å¯ä»¥åœ¨æ²¡æœ‰å…¸åž‹åŒ
+步开销的情况下è¿è¡Œï¼Œä½†ä»æä¾›æŸç§å®½æ¾çš„åŽŸå­æ€§ä¿è¯ã€‚例如,x86å¯ä»¥æ‰§è¡ŒRMW(读å–,
+修改,写入)指令,如åŒinc/dec/cmpxchg,而无需é”å‰ç¼€å’Œç›¸å…³çš„延迟æŸå¤±ã€‚
+
+对没有é”å‰ç¼€çš„å˜é‡çš„访问是ä¸åŒæ­¥çš„,也ä¸éœ€è¦åŒæ­¥ï¼Œå› ä¸ºæˆ‘们处ç†çš„æ˜¯å½“剿‰§è¡Œçš„处ç†
+器所特有的æ¯CPUæ•°æ®ã€‚åªæœ‰å½“å‰çš„处ç†å™¨å¯ä»¥è®¿é—®è¯¥å˜é‡ï¼Œå› æ­¤ç³»ç»Ÿä¸­çš„其他处ç†å™¨ä¸å­˜åœ¨
+并呿€§é—®é¢˜ã€‚
+
+请注æ„,远程处ç†å™¨å¯¹æ¯CPU区域的访问是特殊情况,å¯èƒ½ä¼šå½±å“通过 ``this_cpu_*`` 的本
+地RMWæ“作的性能和正确性(远程写æ“作)。
+
+this_cpuæ“作的主è¦ç”¨é€”是优化计数器æ“作。
+
+定义了以下具有éšå«æŠ¢å ä¿æŠ¤çš„this_cpu()æ“作。å¯ä»¥ä½¿ç”¨è¿™äº›æ“作而ä¸ç”¨æ‹…心抢å å’Œä¸­æ–­::
+
+ this_cpu_read(pcp)
+ this_cpu_write(pcp, val)
+ this_cpu_add(pcp, val)
+ this_cpu_and(pcp, val)
+ this_cpu_or(pcp, val)
+ this_cpu_add_return(pcp, val)
+ this_cpu_xchg(pcp, nval)
+ this_cpu_cmpxchg(pcp, oval, nval)
+ this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+ this_cpu_sub(pcp, val)
+ this_cpu_inc(pcp)
+ this_cpu_dec(pcp)
+ this_cpu_sub_return(pcp, val)
+ this_cpu_inc_return(pcp)
+ this_cpu_dec_return(pcp)
+
+
+this_cpuæ“作的内部工作
+----------------------
+
+在x86上,fs:或gs:æ®µå¯„å­˜å™¨åŒ…å«æ¯CPU区域的基å€ã€‚这样就å¯ä»¥ç®€å•地使用段覆盖,将æ¯CPU
+相对地å€é‡å®šä½åˆ°å¤„ç†å™¨é€‚当的æ¯CPU区域。所以对æ¯CPU基å€çš„é‡å®šä½æ˜¯é€šè¿‡æ®µå¯„存器å‰ç¼€
+在指令中编ç å®Œæˆçš„。
+
+例如::
+
+ DEFINE_PER_CPU(int, x);
+ int z;
+
+ z = this_cpu_read(x);
+
+äº§ç”Ÿçš„å•æŒ‡ä»¤ä¸º::
+
+ mov ax, gs:[x]
+
+è€Œä¸æ˜¯åƒæ¯CPUæ“作那样,先是一系列的地å€è®¡ç®—,然åŽä»Žè¯¥åœ°å€èŽ·å–。在this_cpu_ops之å‰ï¼Œ
+这样的åºåˆ—还需è¦å…ˆç¦ç”¨/å¯ç”¨æŠ¢å åŠŸèƒ½ï¼Œä»¥é˜²æ­¢å†…æ ¸åœ¨è®¡ç®—è¿‡ç¨‹ä¸­å°†çº¿ç¨‹ç§»åŠ¨åˆ°ä¸åŒçš„处ç†
+器上。
+
+请æ€è€ƒä¸‹é¢this_cpuæ“作::
+
+ this_cpu_inc(x)
+
+è¿™å°†äº§ç”Ÿå¦‚ä¸‹å•æŒ‡ä»¤ï¼ˆæ— é”å‰ç¼€ï¼ï¼‰::
+
+ inc gs:[x]
+
+è€Œä¸æ˜¯åœ¨æ²¡æœ‰æ®µå¯„存器的情况下所需è¦çš„以下æ“作::
+
+ int *y;
+ int cpu;
+
+ cpu = get_cpu();
+ y = per_cpu_ptr(&x, cpu);
+ (*y)++;
+ put_cpu();
+
+请注æ„,这些æ“作åªèƒ½ç”¨äºŽä¸ºç‰¹å®šå¤„ç†å™¨ä¿ç•™çš„æ¯CPUæ•°æ®ã€‚如果ä¸åœ¨ä¸Šä¸‹æ–‡ä»£ç ä¸­ç¦ç”¨æŠ¢å ï¼Œ
+``this_cpu_inc()`` 将仅ä¿è¯æ¯CPUçš„æŸä¸€ä¸ªè®¡æ•°å™¨è¢«æ­£ç¡®åœ°é€’增,但ä¸èƒ½ä¿è¯æ“作系统ä¸
+会在this_cpu指令执行的å‰åŽç›´æŽ¥ç§»åŠ¨è¯¥è¿›ç¨‹ã€‚ä¸€èˆ¬æ¥è¯´ï¼Œè¿™æ„å‘³ç€æ¯ä¸ªå¤„ç†å™¨çš„å•个计数
+器的值是没有æ„义的。所有æ¯CPUè®¡æ•°å™¨çš„æ€»å’Œæ‰æ˜¯å”¯ä¸€æœ‰æ„义的值。
+
+æ¯CPUå˜é‡çš„使用是出于性能的考虑。如果多个处ç†å™¨åŒæ—¶å¤„ç†ç›¸åŒçš„代ç è·¯å¾„,å¯ä»¥é¿å…缓
+存行跳转。æ¯ä¸ªå¤„ç†å™¨éƒ½æœ‰è‡ªå·±çš„æ¯CPUå˜é‡ï¼Œå› æ­¤ä¸ä¼šå‘生并å‘缓存行更新。为这ç§ä¼˜åŒ–å¿…
+须付出的代价是,当需è¦è®¡æ•°å™¨çš„值时è¦å°†æ¯CPU计数器相加。
+
+
+特殊的æ“作
+----------
+
+::
+
+ y = this_cpu_ptr(&x)
+
+使用æ¯CPUå˜é‡çš„åç§»é‡(&x!)ï¼Œå¹¶è¿”å›žå±žäºŽå½“å‰æ‰§è¡Œå¤„ç†å™¨çš„æ¯CPUå˜é‡çš„地å€ã€‚
+``this_cpu_ptr`` é¿å…了通用 ``get_cpu``/``put_cpu`` åºåˆ—所需的多个步骤。没有å¯ç”¨
+的处ç†å™¨ç¼–å·ã€‚相å,本地æ¯CPU区域的åç§»é‡åªæ˜¯ç®€å•地添加到æ¯CPUåç§»é‡ä¸Šã€‚
+
+请注æ„,这个æ“作通常是在抢å è¢«ç¦ç”¨åŽå†åœ¨ä»£ç æ®µä¸­ä½¿ç”¨ã€‚ç„¶åŽè¯¥æŒ‡é’ˆç”¨æ¥è®¿é—®ä¸´ç•ŒåŒºä¸­
+的本地æ¯CPUæ•°æ®ã€‚当釿–°å¯ç”¨æŠ¢å æ—¶ï¼Œæ­¤æŒ‡é’ˆé€šå¸¸ä¸å†æœ‰ç”¨ï¼Œå› ä¸ºå®ƒå¯èƒ½ä¸å†æŒ‡å‘当å‰å¤„ç†
+器的æ¯CPUæ•°æ®ã€‚
+
+æ¯CPUå˜é‡å’Œåç§»é‡
+-----------------
+
+æ¯CPUå˜é‡ç›¸å¯¹äºŽæ¯CPU区域的起始点是有å移的。它们没有地å€ï¼Œå°½ç®¡ä»£ç é‡Œçœ‹èµ·æ¥åƒæœ‰ä¸€
+样。ä¸èƒ½ç›´æŽ¥å¯¹åç§»é‡è§£å¼•用,必须用处ç†å™¨æ¯CPU区域基指针加上åç§»é‡ï¼Œä»¥æž„æˆæœ‰æ•ˆåœ°å€ã€‚
+
+因此,在æ¯CPUæ“作的上下文之外使用x或&x是无效的,这ç§è¡Œä¸ºé€šå¸¸ä¼šè¢«å½“作一个空指针的
+解引用æ¥å¤„ç†ã€‚
+
+::
+
+ DEFINE_PER_CPU(int, x);
+
+在æ¯CPUæ“作的上下文中,上é¢è¡¨è¾¾å¼è¯´æ˜Žx是一个æ¯CPUå˜é‡ã€‚大多数this_cpuæ“作都需è¦ä¸€
+个cpuå˜é‡ã€‚
+
+::
+
+ int __percpu *p = &x;
+
+&xå’Œp是æ¯CPUå˜é‡çš„åç§»é‡ã€‚ ``this_cpu_ptr()`` 使用æ¯CPUå˜é‡çš„åç§»é‡ï¼Œè¿™è®©å®ƒçœ‹èµ·æ¥
+有点奇怪。
+
+
+æ¯CPU结构体字段的æ“作
+---------------------
+
+å‡è®¾æˆ‘们有一个æ¯CPU结构::
+
+ struct s {
+ int n,m;
+ };
+
+ DEFINE_PER_CPU(struct s, p);
+
+
+这些字段的æ“作éžå¸¸ç®€å•::
+
+ this_cpu_inc(p.m)
+
+ z = this_cpu_cmpxchg(p.m, 0, 1);
+
+
+如果我们有一个相对于结构体sçš„åç§»é‡::
+
+ struct s __percpu *ps = &p;
+
+ this_cpu_dec(ps->m);
+
+ z = this_cpu_inc_return(ps->n);
+
+
+如果我们åŽé¢ä¸ä½¿ç”¨ ``this_cpu ops`` æ¥æ“作字段,则指针的计算å¯èƒ½éœ€è¦ä½¿ç”¨
+``this_cpu_ptr()``::
+
+ struct s *pp;
+
+ pp = this_cpu_ptr(&p);
+
+ pp->m--;
+
+ z = pp->n++;
+
+
+this_cpu opsçš„å˜ä½“
+------------------
+
+this_cpuçš„æ“ä½œæ˜¯ä¸­æ–­å®‰å…¨çš„ã€‚ä¸€äº›æž¶æž„ä¸æ”¯æŒè¿™äº›æ¯CPU的本地æ“ä½œã€‚åœ¨è¿™ç§æƒ…况下,该æ“
+作必须被ç¦ç”¨ä¸­æ–­çš„ä»£ç æ‰€å–代,然åŽåšé‚£äº›ä¿è¯æ˜¯åŽŸå­çš„æ“ä½œï¼Œå†é‡æ–°å¯ç”¨ä¸­æ–­ã€‚当然这
+æ ·åšæ˜¯å¾ˆæ˜‚贵的。如果有其他原因导致调度器ä¸èƒ½æ”¹å˜æˆ‘们正在执行的处ç†å™¨ï¼Œé‚£ä¹ˆå°±æ²¡æœ‰
+ç†ç”±ç¦ç”¨ä¸­æ–­äº†ã€‚为此,我们æä¾›äº†ä»¥ä¸‹__this_cpuæ“作。
+
+这些æ“作ä¸èƒ½ä¿è¯å¹¶å‘中断或抢å ã€‚如果在中断上下文中ä¸ä½¿ç”¨æ¯CPUå˜é‡å¹¶ä¸”è°ƒåº¦ç¨‹åºæ— æ³•
+抢å ï¼Œé‚£ä¹ˆå®ƒä»¬æ˜¯å®‰å…¨çš„。如果在æ“ä½œè¿›è¡Œæ—¶ä»æœ‰ä¸­æ–­å‘生,并且中断也修改了å˜é‡ï¼Œåˆ™æ— 
+法ä¿è¯RMWæ“作是安全的::
+
+ __this_cpu_read(pcp)
+ __this_cpu_write(pcp, val)
+ __this_cpu_add(pcp, val)
+ __this_cpu_and(pcp, val)
+ __this_cpu_or(pcp, val)
+ __this_cpu_add_return(pcp, val)
+ __this_cpu_xchg(pcp, nval)
+ __this_cpu_cmpxchg(pcp, oval, nval)
+ __this_cpu_cmpxchg_double(pcp1, pcp2, oval1, oval2, nval1, nval2)
+ __this_cpu_sub(pcp, val)
+ __this_cpu_inc(pcp)
+ __this_cpu_dec(pcp)
+ __this_cpu_sub_return(pcp, val)
+ __this_cpu_inc_return(pcp)
+ __this_cpu_dec_return(pcp)
+
+
+将增加x,并且ä¸ä¼šå›žé€€åˆ°åœ¨æ— æ³•通过地å€é‡å®šä½å’ŒåŒä¸€æŒ‡ä»¤ä¸­çš„读å–-修改-写入æ“作实现原
+å­æ€§çš„å¹³å°ä¸Šç¦ç”¨ä¸­æ–­çš„代ç ã€‚
+
+
+&this_cpu_ptr(pp)->n 对比 this_cpu_ptr(&pp->n)
+----------------------------------------------
+
+第一个æ“作使用åç§»é‡å¹¶å½¢æˆä¸€ä¸ªåœ°å€ï¼Œç„¶åŽå†åŠ ä¸Šn字段的åç§»é‡ã€‚è¿™å¯èƒ½ä¼šå¯¼è‡´ç¼–译器产
+生两æ¡åŠ æ³•æŒ‡ä»¤ã€‚
+
+第二个æ“作先加上两个åç§»é‡ï¼Œç„¶åŽè¿›è¡Œé‡å®šä½ã€‚æ•æˆ‘直言,第二ç§å½¢å¼çœ‹èµ·æ¥æ›´å¹²å‡€ï¼Œè€Œ
+且更容易与 ``()`` 结åˆã€‚第二ç§å½¢å¼ä¹Ÿä¸Ž ``this_cpu_read()`` 和大家的使用方å¼ä¸€è‡´ã€‚
+
+
+远程访问æ¯CPUæ•°æ®
+-----------------
+
+æ¯CPUæ•°æ®ç»“构被设计为由一个CPU独å ä½¿ç”¨ã€‚如果您按预期使用å˜é‡ï¼Œåˆ™ ``this_cpu_ops()``
+ä¿è¯æ˜¯ ``原å­çš„`` ,因为没有其他CPUå¯ä»¥è®¿é—®è¿™äº›æ•°æ®ç»“构。
+
+在æŸäº›ç‰¹æ®Šæƒ…况下,您å¯èƒ½éœ€è¦è¿œç¨‹è®¿é—®æ¯CPUæ•°æ®ç»“构。通常情况下,进行远程读访问是安
+全的,这ç»å¸¸æ˜¯ä¸ºäº†ç»Ÿè®¡è®¡æ•°å™¨å€¼ã€‚远程写访问å¯èƒ½ä¼šå‡ºçŽ°é—®é¢˜ï¼Œå› ä¸ºthis_cpuæ“作没有é”
+语义。远程写å¯èƒ½ä¼šå¹²æ‰°this_cpu RMWæ“作。
+
+除éžç»å¯¹å¿…è¦ï¼Œå¦åˆ™å¼ºçƒˆå»ºè®®ä¸è¦å¯¹æ¯CPUæ•°æ®ç»“构进行远程写访问。请考虑使用IPIæ¥å”¤é†’
+远程CPU,并对其æ¯CPU区域进行更新。
+
+è¦è¿œç¨‹è®¿é—®æ¯CPUæ•°æ®ç»“构,通常使用 ``per_cpu_ptr()`` 函数::
+
+
+ DEFINE_PER_CPU(struct data, datap);
+
+ struct data *p = per_cpu_ptr(&datap, cpu);
+
+这清楚地表明,我们正准备远程访问æ¯CPU区域。
+
+您还å¯ä»¥æ‰§è¡Œä»¥ä¸‹æ“作以将datapåç§»é‡è½¬æ¢ä¸ºåœ°å€::
+
+ struct data *p = this_cpu_ptr(&datap);
+
+但是,将通过this_cpu_ptr计算的指针传递给其他cpu是ä¸å¯»å¸¸çš„,应该é¿å…。
+
+远程访问通常åªç”¨äºŽè¯»å–å¦ä¸€ä¸ªcpuçš„æ¯CPUæ•°æ®çжæ€ã€‚由于this_cpuæ“作宽æ¾çš„åŒæ­¥è¦æ±‚,
+写访问å¯èƒ½ä¼šå¯¼è‡´å¥‡ç‰¹çš„问题。
+
+下é¢çš„æƒ…况说明了写入æ“作的一些问题,由于两个æ¯CPUå˜é‡å…±äº«ä¸€ä¸ªç¼“存行,但宽æ¾çš„åŒæ­¥
+仅应用于更新缓存行的一个进程。
+
+考虑以下示例::
+
+
+ struct test {
+ atomic_t a;
+ int b;
+ };
+
+ DEFINE_PER_CPU(struct test, onecacheline);
+
+如果一个处ç†å™¨è¿œç¨‹æ›´æ–°å­—段 ``a`` ,而本地处ç†å™¨å°†ä½¿ç”¨this_cpu opsæ¥æ›´æ–°å­—段 ``b`` ,
+会å‘生什么情况,这一点值得注æ„。应é¿å…在åŒä¸€ç¼“å­˜è¡Œå†…åŒæ—¶è®¿é—®æ•°æ®ã€‚此外,å¯èƒ½è¿˜éœ€
+è¦è¿›è¡Œä»£ä»·é«˜æ˜‚çš„åŒæ­¥ã€‚åœ¨è¿™ç§æƒ…况下,通常建议使用IPIï¼Œè€Œä¸æ˜¯è¿œç¨‹å†™å…¥å¦ä¸€ä¸ªå¤„ç†å™¨çš„
+æ¯CPU区域。
+
+å³ä½¿åœ¨è¿œç¨‹å†™å¾ˆå°‘的情况下,请记ä½è¿œç¨‹å†™å°†ä»Žæœ€æœ‰å¯èƒ½è®¿é—®å®ƒçš„处ç†å™¨ä¸­é€å‡ºç¼“存行。如
+果处ç†å™¨å”¤é†’æ—¶å‘现æ¯CPU区域缺少本地缓存行,其性能和唤醒时间将å—到影å“。
diff --git a/Documentation/translations/zh_CN/doc-guide/index.rst b/Documentation/translations/zh_CN/doc-guide/index.rst
index 5151953c196f..78c2e9a1697f 100644
--- a/Documentation/translations/zh_CN/doc-guide/index.rst
+++ b/Documentation/translations/zh_CN/doc-guide/index.rst
@@ -19,7 +19,7 @@
contributing
maintainer-profile
-.. only:: å­é¡¹ç›®ä¸ŽHTML
+.. only:: subproject and html
目录
====
diff --git a/Documentation/translations/zh_CN/index.rst b/Documentation/translations/zh_CN/index.rst
index ec99ef5fe990..3660a3451c86 100644
--- a/Documentation/translations/zh_CN/index.rst
+++ b/Documentation/translations/zh_CN/index.rst
@@ -71,6 +71,7 @@ TODOList:
dev-tools/index
dev-tools/testing-overview
kernel-hacking/index
+ rust/index
TODOList:
@@ -90,12 +91,12 @@ TODOList:
admin-guide/index
admin-guide/reporting-issues.rst
+ userspace-api/index
TODOList:
* 内核构建系统 <kbuild/index>
* 用户空间工具 <tools/index>
-* userspace-api/index
也å¯å‚考独立于内核文档的 `Linux 手册页 <https://www.kernel.org/doc/man-pages/>`_ 。
@@ -124,13 +125,13 @@ TODOList:
其他文档
--------
-有几份未排åºçš„æ–‡æ¡£ä¼¼ä¹Žä¸é€‚åˆæ”¾åœ¨æ–‡æ¡£çš„其他部分,或者å¯èƒ½éœ€è¦è¿›è¡Œä¸€äº›è°ƒæ•´å’Œ/或
+有几份未分类的文档似乎ä¸é€‚åˆæ”¾åœ¨æ–‡æ¡£çš„其他部分,或者å¯èƒ½éœ€è¦è¿›è¡Œä¸€äº›è°ƒæ•´å’Œ/或
转æ¢ä¸ºreStructureTextæ ¼å¼ï¼Œä¹Ÿæœ‰å¯èƒ½å¤ªæ—§ã€‚
-TODOList:
-
-* staging/index
+.. toctree::
+ :maxdepth: 2
+ staging/index
索引和表格
----------
diff --git a/Documentation/translations/zh_CN/loongarch/introduction.rst b/Documentation/translations/zh_CN/loongarch/introduction.rst
index f3ec25b163d7..470c38ae2caf 100644
--- a/Documentation/translations/zh_CN/loongarch/introduction.rst
+++ b/Documentation/translations/zh_CN/loongarch/introduction.rst
@@ -338,15 +338,15 @@ Loongson与LoongArch的开å‘者网站(软件与文档资æºï¼‰ï¼š
LoongArch指令集架构的文档:
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.00-CN.pdf (中文版)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-CN.pdf (中文版)
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.00-EN.pdf (英文版)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-Vol1-v1.02-EN.pdf (英文版)
LoongArch的ELF psABI文档:
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v1.00-CN.pdf (中文版)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.00-CN.pdf (中文版)
- https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v1.00-EN.pdf (英文版)
+ https://github.com/loongson/LoongArch-Documentation/releases/latest/download/LoongArch-ELF-ABI-v2.00-EN.pdf (英文版)
Loongson与LoongArchçš„Linux内核æºç ä»“库:
diff --git a/Documentation/translations/zh_CN/rust/arch-support.rst b/Documentation/translations/zh_CN/rust/arch-support.rst
new file mode 100644
index 000000000000..afbd02afec45
--- /dev/null
+++ b/Documentation/translations/zh_CN/rust/arch-support.rst
@@ -0,0 +1,23 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/rust/arch-support.rst
+
+:翻译:
+
+ å¸å»¶è…¾ Yanteng Si <siyanteng@loongson.cn>
+
+架构支æŒ
+========
+
+ç›®å‰ï¼ŒRust编译器(``rustc``)使用LLVM进行代ç ç”Ÿæˆï¼Œè¿™é™åˆ¶äº†å¯ä»¥æ”¯æŒçš„目标架构。此外,对
+使用LLVM/Clang构建内核的支æŒä¹Ÿæœ‰æ‰€ä¸åŒï¼ˆè¯·å‚è§ Documentation/kbuild/llvm.rst )。这
+ç§æ”¯æŒå¯¹äºŽä½¿ç”¨ ``libclang`` çš„ ``bindgen`` æ¥è¯´æ˜¯å¿…需的。
+
+䏋颿˜¯ç›®å‰å¯ä»¥å·¥ä½œçš„æž¶æž„的一般总结。支æŒç¨‹åº¦ä¸Ž ``MAINTAINERS`` 文件中的``S`` 值相对应:
+
+============ ================ ==============================================
+æž¶æž„ æ”¯æŒæ°´å¹³ é™åˆ¶å› ç´ 
+============ ================ ==============================================
+``x86`` Maintained åªæœ‰ ``x86_64``
+============ ================ ==============================================
diff --git a/Documentation/translations/zh_CN/rust/coding-guidelines.rst b/Documentation/translations/zh_CN/rust/coding-guidelines.rst
new file mode 100644
index 000000000000..6c0bdbbc5a2a
--- /dev/null
+++ b/Documentation/translations/zh_CN/rust/coding-guidelines.rst
@@ -0,0 +1,192 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/rust/coding-guidelines.rst
+
+:翻译:
+
+ å¸å»¶è…¾ Yanteng Si <siyanteng@loongson.cn>
+
+ç¼–ç æŒ‡å—
+========
+
+本文档æè¿°äº†å¦‚何在内核中编写Rust代ç ã€‚
+
+
+风格和格å¼åŒ–
+------------
+
+代ç åº”该使用 ``rustfmt`` 进行格å¼åŒ–。这样一æ¥ï¼Œä¸€ä¸ªä¸æ—¶ä¸ºå†…æ ¸åšè´¡çŒ®çš„人就ä¸éœ€è¦å†å޻学
+ä¹ å’Œè®°å¿†ä¸€ä¸ªæ ·å¼æŒ‡å—了。更é‡è¦çš„æ˜¯ï¼Œå®¡é˜…者和维护者ä¸éœ€è¦å†èŠ±æ—¶é—´æŒ‡å‡ºé£Žæ ¼é—®é¢˜ï¼Œè¿™æ ·å°±å¯ä»¥
+å‡å°‘è¡¥ä¸è½åœ°æ‰€éœ€çš„邮件往返。
+
+.. note:: ``rustfmt`` 䏿£€æŸ¥æ³¨é‡Šå’Œæ–‡æ¡£çš„约定。因此,这些ä»ç„¶éœ€è¦ç…§é¡¾åˆ°ã€‚
+
+使用 ``rustfmt`` 的默认设置。这æ„味ç€éµå¾ªRust的习惯性风格。例如,缩进时使用4个空格而
+䏿˜¯åˆ¶è¡¨ç¬¦ã€‚
+
+在输入ã€ä¿å­˜æˆ–æäº¤æ—¶å‘ŠçŸ¥ç¼–辑器/IDE进行格å¼åŒ–是很方便的。然而,如果因为æŸäº›åŽŸå› éœ€è¦åœ¨æŸ
+ä¸ªæ—¶å€™é‡æ–°æ ¼å¼åŒ–整个内核Rustçš„æºä»£ç ï¼Œå¯ä»¥è¿è¡Œä»¥ä¸‹ç¨‹åº::
+
+ make LLVM=1 rustfmt
+
+也å¯ä»¥æ£€æŸ¥æ‰€æœ‰çš„东西是å¦éƒ½æ˜¯æ ¼å¼åŒ–的(å¦åˆ™å°±æ‰“å°ä¸€ä¸ªå·®å¼‚),例如对于一个CI,用::
+
+ make LLVM=1 rustfmtcheck
+
+åƒå†…核其他部分的 ``clang-format`` 一样, ``rustfmt`` 在å•个文件上工作,并且ä¸éœ€è¦
+内核é…置。有时,它甚至å¯ä»¥ä¸Žç ´ç¢Žçš„代ç ä¸€èµ·å·¥ä½œã€‚
+
+
+注释
+----
+
+â€œæ™®é€šâ€æ³¨é‡Šï¼ˆå³ä»¥ ``//`` å¼€å¤´ï¼Œè€Œä¸æ˜¯ ``///`` 或 ``//!`` å¼€å¤´çš„ä»£ç æ–‡æ¡£ï¼‰çš„写法与文
+档注释相åŒï¼Œä½¿ç”¨Markdown语法,尽管它们ä¸ä¼šè¢«æ¸²æŸ“。这æé«˜äº†ä¸€è‡´æ€§ï¼Œç®€åŒ–了规则,并å…许在
+è¿™ä¸¤ç§æ³¨é‡Šä¹‹é—´æ›´å®¹æ˜“地移动内容。比如说:
+
+.. code-block:: rust
+
+ // `object` is ready to be handled now.
+ f(object);
+
+æ­¤å¤–ï¼Œå°±åƒæ–‡æ¡£ä¸€æ ·ï¼Œæ³¨é‡Šåœ¨å¥å­çš„开头è¦å¤§å†™ï¼Œå¹¶ä»¥å¥å·ç»“æŸï¼ˆå³ä½¿æ˜¯å•å¥ï¼‰ã€‚这包括 ``// SAFETY:``,
+``// TODO:`` 和其他“标记â€çš„æ³¨é‡Šï¼Œä¾‹å¦‚:
+
+.. code-block:: rust
+
+ // FIXME: The error should be handled properly.
+
+注释ä¸åº”è¯¥è¢«ç”¨äºŽæ–‡æ¡£çš„ç›®çš„ï¼šæ³¨é‡Šæ˜¯ä¸ºäº†å®žçŽ°ç»†èŠ‚ï¼Œè€Œä¸æ˜¯ä¸ºäº†ç”¨æˆ·ã€‚å³ä½¿æºæ–‡ä»¶çš„读者既是API
+çš„å®žçŽ°è€…åˆæ˜¯ç”¨æˆ·ï¼Œè¿™ç§åŒºåˆ†ä¹Ÿæ˜¯æœ‰ç”¨çš„ã€‚äº‹å®žä¸Šï¼Œæœ‰æ—¶åŒæ—¶ä½¿ç”¨æ³¨é‡Šå’Œæ–‡æ¡£æ˜¯å¾ˆæœ‰ç”¨çš„。例如,用
+于 ``TODO`` 列表或对文档本身的注释。对于åŽä¸€ç§æƒ…况,注释å¯ä»¥æ’åœ¨ä¸­é—´ï¼›ä¹Ÿå°±æ˜¯è¯´ï¼Œç¦»è¦æ³¨
+释的文档行更近。对于其他情况,注释会写在文档之åŽï¼Œä¾‹å¦‚:
+
+.. code-block:: rust
+
+ /// Returns a new [`Foo`].
+ ///
+ /// # Examples
+ ///
+ // TODO: Find a better example.
+ /// ```
+ /// let foo = f(42);
+ /// ```
+ // FIXME: Use fallible approach.
+ pub fn f(x: i32) -> Foo {
+ // ...
+ }
+
+一ç§ç‰¹æ®Šçš„æ³¨é‡Šæ˜¯ ``// SAFETY:`` 注释。这些注释必须出现在æ¯ä¸ª ``unsafe`` å—之å‰ï¼Œå®ƒä»¬
+解释了为什么该å—å†…çš„ä»£ç æ˜¯æ­£ç¡®/å¥å…¨çš„,å³ä¸ºä»€ä¹ˆå®ƒåœ¨ä»»ä½•情况下都ä¸ä¼šè§¦å‘未定义行为,例如:
+
+.. code-block:: rust
+
+ // SAFETY: `p` is valid by the safety requirements.
+ unsafe { *p = 0; }
+
+``// SAFETY:`` 注释ä¸èƒ½ä¸Žä»£ç æ–‡æ¡£ä¸­çš„ ``# Safety`` 部分相混淆。 ``# Safety`` 部
+分指定了(函数)调用者或(特性)实现者需è¦éµå®ˆçš„契约。
+``// SAFETY:`` 注释显示了为什么一个(函数)调用者或(特性)实现者实际上尊é‡äº†
+``# Safety`` 部分或语言å‚è€ƒä¸­çš„å‰ææ¡ä»¶ã€‚
+
+
+ä»£ç æ–‡æ¡£
+--------
+
+Rust内核代ç ä¸åƒC内核代ç é‚£æ ·è¢«è®°å½•下æ¥ï¼ˆå³é€šè¿‡kernel-doc)。å–而代之的是用于记录Rust
+代ç çš„常用系统:rustdoc工具,它使用Markdown(一ç§è½»é‡çº§çš„æ ‡è®°è¯­è¨€ï¼‰ã€‚
+
+è¦å­¦ä¹ Markdownï¼Œå¤–é¢æœ‰å¾ˆå¤šæŒ‡å—。例如:
+
+https://commonmark.org/help/
+
+一个记录良好的Rust函数å¯èƒ½æ˜¯è¿™æ ·çš„:
+
+.. code-block:: rust
+
+ /// Returns the contained [`Some`] value, consuming the `self` value,
+ /// without checking that the value is not [`None`].
+ ///
+ /// # Safety
+ ///
+ /// Calling this method on [`None`] is *[undefined behavior]*.
+ ///
+ /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let x = Some("air");
+ /// assert_eq!(unsafe { x.unwrap_unchecked() }, "air");
+ /// ```
+ pub unsafe fn unwrap_unchecked(self) -> T {
+ match self {
+ Some(val) => val,
+
+ // SAFETY: The safety contract must be upheld by the caller.
+ None => unsafe { hint::unreachable_unchecked() },
+ }
+ }
+
+这个例å­å±•示了一些 ``rustdoc`` 的特性和内核中éµå¾ªçš„一些惯例:
+
+ - 第一段必须是一个简å•çš„å¥å­ï¼Œç®€è¦åœ°æè¿°è¢«è®°å½•的项目的作用。进一步的解释必须放在é¢
+ 外的段è½ä¸­ã€‚
+
+ - ä¸å®‰å…¨çš„函数必须在 ``# Safety`` éƒ¨åˆ†è®°å½•å…¶å®‰å…¨å‰ææ¡ä»¶ã€‚
+
+ - 虽然这里没有显示,但如果一个函数å¯èƒ½ä¼šææ…Œï¼Œé‚£ä¹ˆå¿…须在 ``# Panics`` 部分æè¿°å‘
+ ç”Ÿè¿™ç§æƒ…况的æ¡ä»¶ã€‚
+
+ 请注æ„ï¼Œææ…Œåº”该是éžå¸¸å°‘è§çš„ï¼Œåªæœ‰åœ¨æœ‰å……分ç†ç”±çš„æƒ…况下æ‰ä¼šä½¿ç”¨ã€‚几乎在所有的情况下,
+ 都应该使用一个å¯å¤±è´¥çš„æ–¹æ³•,通常是返回一个 ``Result``。
+
+ - 如果æä¾›ä½¿ç”¨å®žä¾‹å¯¹è¯»è€…有帮助的è¯ï¼Œå¿…须写在一个å«åš``# Examples``的部分。
+
+ - Rust项目(函数ã€ç±»åž‹ã€å¸¸é‡â€¦â€¦ï¼‰å¿…须有适当的链接(``rustdoc`` 会自动创建一个
+ 链接)。
+
+ - 任何 ``unsafe`` 的代ç å—都必须在å‰é¢åŠ ä¸Šä¸€ä¸ª ``// SAFETY:`` 的注释,æè¿°é‡Œé¢
+ 的代ç ä¸ºä»€ä¹ˆæ˜¯æ­£ç¡®çš„。
+
+ 虽然有时原因å¯èƒ½çœ‹èµ·æ¥å¾®ä¸è¶³é“,但写这些注释ä¸ä»…是记录已ç»è€ƒè™‘到的问题的好方法,
+ 最é‡è¦çš„æ˜¯ï¼Œå®ƒæä¾›äº†ä¸€ç§çŸ¥é“没有é¢å¤–éšå«çº¦æŸçš„æ–¹æ³•。
+
+è¦äº†è§£æ›´å¤šå…³äºŽå¦‚何编写Rust和拓展功能的文档,请看看 ``rustdoc`` è¿™æœ¬ä¹¦ï¼Œç½‘å€æ˜¯:
+
+ https://doc.rust-lang.org/rustdoc/how-to-write-documentation.html
+
+
+命å
+----
+
+Rust内核代ç éµå¾ªé€šå¸¸çš„Rust命å空间:
+
+ https://rust-lang.github.io/api-guidelines/naming.html
+
+当现有的C语言概念(如å®ã€å‡½æ•°ã€å¯¹è±¡......)被包装æˆRust抽象时,应该使用尽å¯èƒ½æŽ¥è¿‘C语
+言的å称,以é¿å…混淆,并在C语言和Rust语言之间æ¥å›žåˆ‡æ¢æ—¶æé«˜å¯è¯»æ€§ã€‚例如,C语言中的
+``pr_info`` 这样的å®åœ¨Rustä¸­çš„å‘½åæ˜¯ä¸€æ ·çš„。
+
+说到这里,应该调整大å°å†™ä»¥éµå¾ªRustçš„å‘½åæƒ¯ä¾‹ï¼Œæ¨¡å—和类型引入的命åé—´éš”ä¸åº”该在项目åç§°
+中é‡å¤ã€‚ä¾‹å¦‚ï¼Œåœ¨åŒ…è£…å¸¸é‡æ—¶ï¼Œå¦‚:
+
+.. code-block:: c
+
+ #define GPIO_LINE_DIRECTION_IN 0
+ #define GPIO_LINE_DIRECTION_OUT 1
+
+在Rust中的等价物å¯èƒ½æ˜¯è¿™æ ·çš„(忽略文档)。:
+
+.. code-block:: rust
+
+ pub mod gpio {
+ pub enum LineDirection {
+ In = bindings::GPIO_LINE_DIRECTION_IN as _,
+ Out = bindings::GPIO_LINE_DIRECTION_OUT as _,
+ }
+ }
+
+也就是说, ``GPIO_LINE_DIRECTION_IN`` 的等价物将被称为 ``gpio::LineDirection::In`` 。
+特别是,它ä¸åº”该被命å为 ``gpio::gpio_line_direction::GPIO_LINE_DIRECTION_IN`` 。
diff --git a/Documentation/translations/zh_CN/rust/general-information.rst b/Documentation/translations/zh_CN/rust/general-information.rst
new file mode 100644
index 000000000000..6b91dfe1834a
--- /dev/null
+++ b/Documentation/translations/zh_CN/rust/general-information.rst
@@ -0,0 +1,75 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/rust/general-information.rst
+
+:翻译:
+
+ å¸å»¶è…¾ Yanteng Si <siyanteng@loongson.cn>
+
+
+基本信æ¯
+========
+
+本文档包å«äº†åœ¨å†…核中使用Rustæ”¯æŒæ—¶éœ€è¦äº†è§£çš„æœ‰ç”¨ä¿¡æ¯ã€‚
+
+
+ä»£ç æ–‡æ¡£
+--------
+
+Rust内核代ç ä½¿ç”¨å…¶å†…置的文档生æˆå™¨ ``rustdoc`` 进行记录。
+
+生æˆçš„HTMLæ–‡æ¡£åŒ…æ‹¬é›†æˆæœç´¢ã€é“¾æŽ¥é¡¹ï¼ˆå¦‚类型ã€å‡½æ•°ã€å¸¸é‡ï¼‰ã€æºä»£ç ç­‰ã€‚它们å¯ä»¥åœ¨ä»¥ä¸‹åœ°å€é˜…读
+(TODO:当在主线中时链接,与其他文档一起生æˆï¼‰ï¼š
+
+ http://kernel.org/
+
+这些文档也å¯ä»¥å¾ˆå®¹æ˜“地在本地生æˆå’Œé˜…è¯»ã€‚è¿™ç›¸å½“å¿«ï¼ˆä¸Žç¼–è¯‘ä»£ç æœ¬èº«çš„顺åºç›¸åŒï¼‰ï¼Œè€Œä¸”ä¸éœ€è¦ç‰¹
+殊的工具或环境。这有一个é¢å¤–çš„å¥½å¤„ï¼Œé‚£å°±æ˜¯å®ƒä»¬å°†æ ¹æ®æ‰€ä½¿ç”¨çš„特定内核é…置进行定制。è¦ç”Ÿæˆå®ƒ
+们,请使用 ``rustdoc`` 目标,并使用编译时使用的相åŒè°ƒç”¨ï¼Œä¾‹å¦‚::
+
+ make LLVM=1 rustdoc
+
+è¦åœ¨ä½ çš„网络æµè§ˆå™¨ä¸­æœ¬åœ°é˜…读该文档,请è¿è¡Œå¦‚::
+
+ xdg-open rust/doc/kernel/index.html
+
+è¦äº†è§£å¦‚何编写文档,请看 coding-guidelines.rst 。
+
+
+é¢å¤–çš„lints
+-----------
+
+虽然 ``rustc`` 是一个éžå¸¸æœ‰ç”¨çš„编译器,但一些é¢å¤–çš„lints和分æžå¯ä»¥é€šè¿‡ ``clippy``
+(一个Rust linter)æ¥å®žçŽ°ã€‚è¦å¯ç”¨å®ƒï¼Œè¯·å°†CLIPPY=1传递到用于编译的åŒä¸€è°ƒç”¨ä¸­ï¼Œä¾‹å¦‚::
+
+ make LLVM=1 CLIPPY=1
+
+请注æ„,Clippyå¯èƒ½ä¼šæ”¹å˜ä»£ç ç”Ÿæˆï¼Œå› æ­¤åœ¨æž„建产å“内核时ä¸åº”该å¯ç”¨å®ƒã€‚
+
+抽象和绑定
+----------
+
+抽象是用Rust代ç åŒ…装æ¥è‡ªC端的内核功能。
+
+为了使用æ¥è‡ªC端的函数和类型,需è¦åˆ›å»ºç»‘定。绑定是Rust对那些æ¥è‡ªC端的函数和类型的声明。
+
+例如,人们å¯ä»¥åœ¨Rust中写一个 ``Mutex`` 抽象,它从C端包装一个 ``Mutex结构体`` ,并
+通过绑定调用其函数。
+
+抽象并ä¸èƒ½ç”¨äºŽæ‰€æœ‰çš„内核内部API和概念,但éšç€æ—¶é—´çš„æŽ¨ç§»ï¼Œæˆ‘们打算扩大覆盖范围。“Leafâ€
+模å—(例如,驱动程åºï¼‰ä¸åº”该直接使用C语言的绑定。相å,å­ç³»ç»Ÿåº”该根æ®éœ€è¦æä¾›å°½å¯èƒ½å®‰
+全的抽象。
+
+
+有æ¡ä»¶çš„编译
+------------
+
+Rust代ç å¯ä»¥è®¿é—®åŸºäºŽå†…æ ¸é…置的æ¡ä»¶æ€§ç¼–译:
+
+.. code-block:: rust
+
+ #[cfg(CONFIG_X)] // Enabled (`y` or `m`)
+ #[cfg(CONFIG_X="y")] // Enabled as a built-in (`y`)
+ #[cfg(CONFIG_X="m")] // Enabled as a module (`m`)
+ #[cfg(not(CONFIG_X))] // Disabled
diff --git a/Documentation/translations/zh_CN/rust/index.rst b/Documentation/translations/zh_CN/rust/index.rst
new file mode 100644
index 000000000000..b01f887e7167
--- /dev/null
+++ b/Documentation/translations/zh_CN/rust/index.rst
@@ -0,0 +1,28 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/rust/index.rst
+
+:翻译:
+
+ å¸å»¶è…¾ Yanteng Si <siyanteng@loongson.cn>
+
+Rust
+====
+
+与内核中的Rust有关的文档。若è¦å¼€å§‹åœ¨å†…核中使用Rust,请阅读quick-start.rst指å—。
+
+.. toctree::
+ :maxdepth: 1
+
+ quick-start
+ general-information
+ coding-guidelines
+ arch-support
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
diff --git a/Documentation/translations/zh_CN/rust/quick-start.rst b/Documentation/translations/zh_CN/rust/quick-start.rst
new file mode 100644
index 000000000000..a4b8e8a50a89
--- /dev/null
+++ b/Documentation/translations/zh_CN/rust/quick-start.rst
@@ -0,0 +1,211 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/rust/quick-start.rst
+
+:翻译:
+
+ å¸å»¶è…¾ Yanteng Si <siyanteng@loongson.cn>
+
+
+快速入门
+========
+
+本文介ç»äº†å¦‚何开始使用Rust进行内核开å‘。
+
+
+构建ä¾èµ–
+--------
+
+本节æè¿°äº†å¦‚ä½•èŽ·å–æž„建所需的工具。
+
+其中一些ä¾èµ–也许å¯ä»¥ä»ŽLinuxå‘行版中获得,包åå¯èƒ½æ˜¯ ``rustc`` , ``rust-src`` ,
+``rust-bindgen`` 等。然而,在写这篇文章的时候,它们很å¯èƒ½è¿˜ä¸å¤Ÿæ–°ï¼Œé™¤éžå‘行版跟踪最
+新的版本。
+
+ä¸ºäº†æ–¹ä¾¿æ£€æŸ¥æ˜¯å¦æ»¡è¶³è¦æ±‚,å¯ä»¥ä½¿ç”¨ä»¥ä¸‹ç›®æ ‡::
+
+ make LLVM=1 rustavailable
+
+这会触å‘与Kconfig用æ¥ç¡®å®šæ˜¯å¦åº”该å¯ç”¨ ``RUST_IS_AVAILABLE`` 相åŒçš„逻辑;ä¸è¿‡ï¼Œå¦‚
+æžœKconfig认为ä¸è¯¥å¯ç”¨ï¼Œå®ƒä¼šåˆ—出未满足的æ¡ä»¶ã€‚
+
+
+rustc
+*****
+
+需è¦ä¸€ä¸ªç‰¹å®šç‰ˆæœ¬çš„Rust编译器。较新的版本å¯èƒ½ä¼šä¹Ÿå¯èƒ½ä¸ä¼šå·¥ä½œï¼Œå› ä¸ºå°±ç›®å‰è€Œè¨€ï¼Œå†…æ ¸ä¾èµ–
+于一些ä¸ç¨³å®šçš„Rust特性。
+
+如果使用的是 ``rustup`` ,请进入检出的æºä»£ç ç›®å½•å¹¶è¿è¡Œ::
+
+ rustup override set $(scripts/min-tool-version.sh rustc)
+
+或者从以下网å€èŽ·å–ä¸€ä¸ªç‹¬ç«‹çš„å®‰è£…ç¨‹åºæˆ–安装 ``rustup`` :
+
+ https://www.rust-lang.org
+
+
+Rust标准库æºä»£ç 
+****************
+
+Rust标准库的æºä»£ç æ˜¯å¿…需的,因为构建系统会交å‰ç¼–译 ``core`` å’Œ ``alloc`` 。
+
+如果正在使用 ``rustup`` ,请è¿è¡Œ::
+
+ rustup component add rust-src
+
+这些组件是按工具链安装的,因此以åŽå‡çº§Rust编译器版本需è¦é‡æ–°æ·»åŠ ç»„ä»¶ã€‚
+
+å¦åˆ™ï¼Œå¦‚果使用独立的安装程åºï¼Œå¯ä»¥å°†Rust仓库克隆到工具链的安装文件夹中::
+
+ git clone --recurse-submodules \
+ --branch $(scripts/min-tool-version.sh rustc) \
+ https://github.com/rust-lang/rust \
+ $(rustc --print sysroot)/lib/rustlib/src/rust
+
+åœ¨è¿™ç§æƒ…况下,以åŽå‡çº§Rustç¼–è¯‘å™¨ç‰ˆæœ¬éœ€è¦æ‰‹åŠ¨æ›´æ–°è¿™ä¸ªå…‹éš†çš„ä»“åº“ã€‚
+
+
+libclang
+********
+
+``bindgen`` 使用 ``libclang`` (LLVM的一部分)æ¥ç†è§£å†…核中的C代ç ï¼Œè¿™æ„味ç€éœ€è¦å®‰
+装LLVMï¼›åŒåœ¨å¼€å¯ ``CC=clang`` 或 ``LLVM=1`` 时编译内核一样。
+
+Linuxå‘行版中å¯èƒ½ä¼šæœ‰åˆé€‚的包,所以最好先检查一下。
+
+适用于部分系统和架构的二进制文件也å¯åˆ°ä»¥ä¸‹ç½‘å€ä¸‹è½½ï¼š
+
+ https://releases.llvm.org/download.html
+
+或者自行构建LLVM,这需è¦ç›¸å½“é•¿çš„æ—¶é—´ï¼Œä½†å¹¶ä¸æ˜¯ä¸€ä¸ªå¤æ‚的过程:
+
+ https://llvm.org/docs/GettingStarted.html#getting-the-source-code-and-building-llvm
+
+请å‚阅 Documentation/kbuild/llvm.rst 了解更多信æ¯ï¼Œä»¥åŠèŽ·å–预构建版本和å‘行包
+的进一步方法。
+
+
+bindgen
+*******
+
+内核的C端绑定是在构建时使用 ``bindgen`` 工具生æˆçš„。这需è¦ç‰¹å®šçš„版本。
+
+通过以下方å¼å®‰è£…它(注æ„,这将从æºç ä¸‹è½½å¹¶æž„建该工具)::
+
+ cargo install --locked --version $(scripts/min-tool-version.sh bindgen) bindgen
+
+
+å¼€å‘ä¾èµ–
+--------
+
+本节解释了如何获å–开呿‰€éœ€çš„工具。也就是说,在构建内核时ä¸éœ€è¦è¿™äº›å·¥å…·ã€‚
+
+
+rustfmt
+*******
+
+``rustfmt`` 工具被用æ¥è‡ªåŠ¨æ ¼å¼åŒ–所有的Rust内核代ç ï¼ŒåŒ…括生æˆçš„C绑定(详情请è§
+coding-guidelines.rst )。
+
+如果使用的是 ``rustup`` ,它的 ``默认`` é…置文件已ç»å®‰è£…了这个工具,因此ä¸éœ€è¦åšä»€ä¹ˆã€‚
+如果使用的是其他é…置文件,å¯ä»¥æ‰‹åŠ¨å®‰è£…è¯¥ç»„ä»¶::
+
+ rustup component add rustfmt
+
+独立的安装程åºä¹Ÿå¸¦æœ‰ ``rustfmt`` 。
+
+
+clippy
+******
+
+``clippy`` 是一个Rust linter。è¿è¡Œå®ƒå¯ä»¥ä¸ºRustä»£ç æä¾›é¢å¤–的警告。它å¯ä»¥é€šè¿‡å‘ ``make``
+传递 ``CLIPPY=1`` æ¥è¿è¡Œï¼ˆå…³äºŽç»†èŠ‚ï¼Œè¯¦è§ general-information.rst )。
+
+如果正在使用 ``rustup`` ,它的 ``默认`` é…置文件已ç»å®‰è£…了这个工具,因此ä¸éœ€è¦åšä»€ä¹ˆã€‚
+如果使用的是å¦ä¸€ä¸ªé…置文件,该组件å¯ä»¥è¢«æ‰‹åŠ¨å®‰è£…::
+
+ rustup component add clippy
+
+独立的安装程åºä¹Ÿå¸¦æœ‰ ``clippy`` 。
+
+
+cargo
+*****
+
+``cargo`` 是Rust的本地构建系统。目å‰éœ€è¦å®ƒæ¥è¿è¡Œæµ‹è¯•ï¼Œå› ä¸ºå®ƒè¢«ç”¨æ¥æž„建一个自定义的标准
+库,其中包å«äº†å†…核中自定义 ``alloc`` 所æä¾›çš„设施。测试å¯ä»¥ä½¿ç”¨ ``rusttest`` Make 目标
+æ¥è¿è¡Œã€‚
+
+如果使用的是 ``rustup`` ,所有的é…置文件都已ç»å®‰è£…了该工具,因此ä¸éœ€è¦å†åšä»€ä¹ˆã€‚
+
+独立的安装程åºä¹Ÿå¸¦æœ‰ ``cargo`` 。
+
+
+rustdoc
+*******
+
+``rustdoc`` 是Rust的文档工具。它为Rust代ç ç”Ÿæˆæ¼‚亮的HTMLæ–‡æ¡£ï¼ˆè¯¦æƒ…è¯·è§ general-information.rst )。
+
+``rustdoc`` ä¹Ÿè¢«ç”¨æ¥æµ‹è¯•文档化的Rust代ç ä¸­æä¾›çš„例å­ï¼ˆç§°ä¸ºdoctests或文档测试)。
+``rusttest`` 是本功能的Make目标。
+
+如果使用的是 ``rustup`` ,所有的é…置文件都已ç»å®‰è£…了这个工具,因此ä¸éœ€è¦åšä»€ä¹ˆã€‚
+
+独立的安装程åºä¹Ÿå¸¦æœ‰ ``rustdoc`` 。
+
+
+rust-analyzer
+*************
+
+`rust-analyzer <https://rust-analyzer.github.io/>`_ 语言æœåС噍å¯ä»¥å’Œè®¸å¤šç¼–辑器
+一起使用,以实现语法高亮ã€è¡¥å…¨ã€è½¬åˆ°å®šä¹‰å’Œå…¶ä»–功能。
+
+``rust-analyzer`` 需è¦ä¸€ä¸ªé…置文件, ``rust-project.json``, 它å¯ä»¥ç”± ``rust-analyzer``
+Make 目标生æˆã€‚
+
+
+é…ç½®
+----
+
+Rust支æŒï¼ˆCONFIG_RUST)需è¦åœ¨ ``General setup`` èœå•中å¯ç”¨ã€‚åœ¨å…¶ä»–è¦æ±‚得到满足的情
+å†µä¸‹ï¼Œè¯¥é€‰é¡¹åªæœ‰åœ¨æ‰¾åˆ°åˆé€‚çš„Rust工具链时æ‰ä¼šæ˜¾ç¤ºï¼ˆè§ä¸Šæ–‡ï¼‰ã€‚相应的,这将使ä¾èµ–Rust的其
+他选项å¯è§ã€‚
+
+之åŽï¼Œè¿›å…¥::
+
+ Kernel hacking
+ -> Sample kernel code
+ -> Rust samples
+
+å¹¶å¯ç”¨ä¸€äº›å†…置或å¯åŠ è½½çš„æ ·ä¾‹æ¨¡å—。
+
+
+构建
+----
+
+用完整的LLVMå·¥å…·é“¾æž„å»ºå†…æ ¸æ˜¯ç›®å‰æ”¯æŒçš„æœ€ä½³è®¾ç½®ã€‚å³::
+
+ make LLVM=1
+
+å¯¹äºŽä¸æ”¯æŒå®Œæ•´LLVM工具链的架构,使用::
+
+ make CC=clang
+
+使用GCC对æŸäº›é…置也是å¯è¡Œçš„,但目å‰å®ƒæ˜¯éžå¸¸è¯•验性的。
+
+
+折腾
+----
+
+è¦æƒ³æ·±å…¥äº†è§£ï¼Œè¯·çœ‹ ``samples/rust/`` 下的样例æºä»£ç ã€ ``rust/`` 下的Rust支æŒä»£ç å’Œ
+``Kernel hacking`` 下的 ``Rust hacking`` èœå•。
+
+如果使用的是GDB/Binutils,而Rustç¬¦å·æ²¡æœ‰è¢«demangledï¼ŒåŽŸå› æ˜¯å·¥å…·é“¾è¿˜ä¸æ”¯æŒRust的新v0
+mangling方案。有几个办法å¯ä»¥è§£å†³ï¼š
+
+ - 安装一个较新的版本(GDB >= 10.2, Binutils >= 2.36)。
+
+ - 一些版本的GDB(例如vanilla GDB 10.1)能够使用嵌入在调试信æ¯(``CONFIG_DEBUG_INFO``)
+ 中的pre-demangledçš„å字。
diff --git a/Documentation/translations/zh_CN/staging/index.rst b/Documentation/translations/zh_CN/staging/index.rst
new file mode 100644
index 000000000000..bb55c81c84a3
--- /dev/null
+++ b/Documentation/translations/zh_CN/staging/index.rst
@@ -0,0 +1,26 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/staging/index.rst
+
+:翻译:
+
+ æŽç¿ Rui Li <me@lirui.org>
+
+未分类文档
+==========
+
+.. toctree::
+ :maxdepth: 2
+
+ xz
+
+TODOList:
+
+* crc32
+* lzo
+* remoteproc
+* rpmsg
+* speculation
+* static-keys
+* tee
diff --git a/Documentation/translations/zh_CN/staging/xz.rst b/Documentation/translations/zh_CN/staging/xz.rst
new file mode 100644
index 000000000000..211c487bcb62
--- /dev/null
+++ b/Documentation/translations/zh_CN/staging/xz.rst
@@ -0,0 +1,100 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/staging/xz.rst
+
+:翻译:
+
+ æŽç¿ Rui Li <me@lirui.org>
+
+===================
+Linux中的XZæ•°æ®åŽ‹ç¼©
+===================
+
+介ç»
+====
+
+XZ是一ç§é€šç”¨çš„æ•°æ®åŽ‹ç¼©æ ¼å¼ï¼Œå…¶å…·æœ‰é«˜åŽ‹ç¼©çŽ‡å’Œç›¸å¯¹å¿«çš„è§£åŽ‹é€Ÿåº¦ã€‚ä¸»è¦çš„压缩算法(
+过滤器)是LZMA2。é¢å¤–的过滤器å¯ä»¥è¢«ç”¨æ¥è¿›ä¸€æ­¥æé«˜åŽ‹ç¼©çŽ‡ï¼Œæ¯”å¦‚ç”¨æ¥æé«˜å¯æ‰§è¡Œæ•°æ®
+压缩率的Branch/Call/Jump (BCJ)过滤器。
+
+XZ解压器在Linux中被称作XZ Embedded。它支æŒLZMA2过滤器和å¯é€‰çš„BCJ过滤器,并支æŒ
+CRC32完整性校验。你å¯ä»¥åœ¨XZ Embedded的主页<https://tukaani.org/xz/embedded.html>
+中找到最新版本和关于在Linux内核之外使用æºç çš„ä¿¡æ¯ã€‚
+
+对于用户空间æ¥è¯´ï¼ŒXZ Utilsæä¾›äº†ç±»ä¼¼äºŽzlib的压缩库和类似于gzip的命令行工具。
+XZ Utilså¯ä»¥ä»Ž<https://tukaani.org/xz/>下载。
+
+内核中的XZ相关组件
+==================
+
+xz_dec模å—为XZ解压器æä¾›äº†å•次调用(缓冲区到缓冲区)和多次调用(有状æ€ï¼‰çš„
+API。xz_dec模å—的用法记录在include/linux/xz.h中。
+
+xz_dec_test模å—用于测试xz_dec。除éžä½ æƒ³é­”改XZ解压器,å¦åˆ™xz_dec_test是
+没有用的。xz_dec_test会动æ€åˆ†é…一个字符设备主设备å·ï¼Œä½ å¯ä»¥ä»Žç”¨æˆ·ç©ºé—´å‘它
+写入.xz文件,解压的输出会被丢弃。关注dmesgå¯ä»¥æ‰¾åˆ°xz_dec_test输出的诊断信æ¯ã€‚
+详细内容请查看xz_dec_testçš„æºç ã€‚
+
+为了解压内核镜åƒã€åˆå§‹ram文件系统和åˆå§‹ramç£ç›˜ï¼Œlib/decompress_unxz.c实现
+了一个包装函数。它的API与其他 decompress_*.c 文件相åŒï¼Œé‚£äº›API定义在
+include/linux/decompress/generic.h中。
+
+scripts/xz_wrap.sh是一个XZ Utils中的xz命令行工具包装器。这个包装器会
+设置åˆé€‚的压缩选项æ¥åŽ‹ç¼©å†…æ ¸é•œåƒã€‚
+
+在内核的makefiles中,æä¾›äº†ä½¿ç”¨$(call if_needed)的两个命令。内核镜åƒåº”该
+使用$(call if_needed,xzkern)æ¥åŽ‹ç¼©ï¼Œå®ƒä¼šä½¿ç”¨BCJ过滤器和一个大LZMA2字典。
+å®ƒè¿˜ä¼šé™„åŠ ä¸€ä¸ªå››å­—èŠ‚çš„åŒ…å«æºæ–‡ä»¶å¤§å°çš„预告,这会在å¯åЍ代ç ä¸­è¢«ç”¨åˆ°ã€‚其他文件
+应该使用$(call if_needed,xzmisc)æ¥åŽ‹ç¼©ï¼Œå®ƒä¼šä½¿ç”¨1 MiBçš„LZMA2字典并ç¦ç”¨
+BCJ过滤器。
+
+关于压缩选项的说明
+==================
+
+因为XZ Embeddedåªæ”¯æŒæ²¡æœ‰å®Œæ•´æ€§æ ¡éªŒçš„æ•°æ®æµæˆ–者CRC32,请确ä¿ä½ åœ¨ç¼–ç æœªæ¥å°†è¢«
+内核解ç çš„æ–‡ä»¶æ—¶æ²¡æœ‰ä½¿ç”¨å…¶ä»–完整性校验方å¼ã€‚使用liblzma时,你需è¦ä½¿ç”¨LZMA_CHECK_NONE
+或LZMA_CHECK_CRC32。使用xz命令行工具时,使用--check=none或--check=crc32。
+
+é™¤éžæœ‰å…¶ä»–环节会验è¯è§£åŽ‹æ•°æ®çš„完整性,å¦åˆ™å¼ºçƒˆä½¿ç”¨CRC32。åŒé‡éªŒè¯å¯èƒ½ä¼šæµªè´¹
+CPU周期。请注æ„头部总是会包å«ç”¨äºŽè§£åŽ‹å™¨éªŒè¯çš„CRC32,你åªèƒ½ä¿®æ”¹æˆ–ç¦ç”¨è§£åŽ‹åŽæ•°æ®
+的完整性校验方å¼ã€‚
+
+在用户中间中,LZMA2通常使用几兆字节大å°çš„字典。解ç å™¨éœ€è¦åœ¨RAM中放置字典,
+因此大字典ä¸èƒ½è¢«ç”¨äºŽé‚£äº›æ„在被内核解ç çš„æ–‡ä»¶ã€‚1 MiBåœ¨å†…æ ¸ä¸­å¤§æ¦‚æ˜¯å¯æŽ¥å—的最大
+字典大å°ï¼ˆå¯èƒ½å¯¹åˆå§‹ram文件系统也适用)。XZ Utils中的预设值å¯èƒ½å¹¶ä¸é€‚åˆåˆ›å»º
+内核文件,所以请别犹豫使用自定义设置。比如::
+
+ xz --check=crc32 --lzma2=dict=512KiB inputfile
+
+使用上é¢å­—典大å°çš„一个例外是在å•一调用模å¼ä¸‹ä½¿ç”¨è§£ç å™¨ã€‚解压内核自身就是一个例
+å­ã€‚在å•一调用模å¼ä¸‹ï¼Œå†…存用é‡å¹¶ä¸å’Œå­—兏大尿œ‰å…³ï¼Œè¿™ç§æƒ…况就是使用大字典的好地
+方:为了最大化压缩,字典至少应该和解压åŽçš„æ•°æ®ä¸€æ ·å¤§ã€‚
+
+未æ¥è®¡åˆ’
+========
+
+如果有人认为有用的è¯ï¼Œå¯èƒ½ä¼šè€ƒè™‘创建一个å—é™çš„XZç¼–ç å™¨ã€‚LZMA2的压缩速率比Deflate
+或LZOç­‰è¦æ…¢ï¼Œå³ä½¿åœ¨æœ€å¿«çš„é…ç½®é€‰é¡¹ä¸‹ã€‚æ‰€ä»¥å¹¶ä¸æ¸…楚LZMA2ç¼–ç å™¨æ˜¯å¦éœ€è¦å¹¶å…¥å†…核。
+
+有计划在解压代ç ä¸­æ”¯æŒæœ‰é™çš„éšæœºè®¿é—®è¯»æ•°æ®ã€‚ä¸çŸ¥é“这能å¦åœ¨å†…核中有任何用,但是我
+知é“这会在一些Linux内核以外的嵌入å¼é¡¹ç›®ä¸­æœ‰ç”¨ã€‚
+
+.xz文件格å¼è§„范的一致性
+=======================
+
+在一些边缘情况下,为了简化事情牺牲了尽早地检测错误。因为并ä¸ä¼šå¯¼è‡´å®‰å…¨é—®é¢˜ï¼Œå®žé™…
+上是没有关系的。但在测试代ç çš„æ—¶å€™çŸ¥é“这一点很好,比如测试æ¥è‡ªXZ Utils的文件。
+
+报告错误
+========
+
+请在报告错误å‰ç¡®è®¤æ˜¯å¦å·²ç»åœ¨ä¸Šæ¸¸ä¿®å¤ã€‚å¯ä»¥ä»Ž<https://tukaani.org/xz/embedded.html>
+èŽ·å–æœ€æ–°çš„æºç ã€‚
+
+å¯ä»¥é€šè¿‡è”ç³»<lasse.collin@tukaani.org>或者访问Freenode上的#tukaani
+è”ç³»Larhzu。我并ä¸ç»å¸¸é˜…读LKML或者其他内核相关的邮件列表,所以如果è¦å‘ŠçŸ¥æˆ‘什么事情
+,你应该通过我的ç§äººé‚®ç®±æˆ–者IRCè”系我。
+
+请ä¸è¦å› ä¸ºå†…核中XZ的实现或关于XZ Utils的问题打扰Igor Pavlov。虽然这两ç§å®žçް
+包å«äº†å»ºç«‹åœ¨Igor Pavlov的代ç ä¸Šçš„é‡è¦æºç ï¼Œä½†å¹¶ä¸ç”±ä»–维护和æä¾›æ”¯æŒã€‚
diff --git a/Documentation/translations/zh_CN/userspace-api/accelerators/ocxl.rst b/Documentation/translations/zh_CN/userspace-api/accelerators/ocxl.rst
new file mode 100644
index 000000000000..845b932bf935
--- /dev/null
+++ b/Documentation/translations/zh_CN/userspace-api/accelerators/ocxl.rst
@@ -0,0 +1,168 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../../disclaimer-zh_CN.rst
+
+:Original: Documentation/userspace-api/accelerators/ocxl.rst
+
+:翻译:
+
+ æŽç¿ Rui Li <me@lirui.org>
+
+=====================================
+OpenCAPI (开放相干加速器处ç†å™¨æŽ¥å£ï¼‰
+=====================================
+
+*OpenCAPI: Open Coherent Accelerator Processor Interface*
+
+OpenCAPI是处ç†å™¨å’ŒåŠ é€Ÿå™¨ä¹‹é—´çš„ä¸€ä¸ªæŽ¥å£ï¼Œè‡´åŠ›äºŽè¾¾åˆ°ä½Žå»¶è¿Ÿå’Œé«˜å¸¦å®½ã€‚è¯¥è§„èŒƒ
+ç”± `OpenCAPI Consortium <http://opencapi.org/>`_ å¼€å‘。
+
+它å…许加速器(å¯ä»¥æ˜¯FPGAã€ASIC等)使用虚拟地å€è¿žè´¯åœ°è®¿é—®ä¸»æœºå†…存。一个OpenCAPI
+设备也å¯ä»¥æ‰˜ç®¡å®ƒè‡ªå·±çš„内存,并å¯ä»¥ç”±ä¸»æœºè®¿é—®ã€‚
+
+OpenCAPI在Linux中称为“ocxlâ€ï¼Œå®ƒä½œä¸ºâ€œcxlâ€ï¼ˆç”¨äºŽpowerpcçš„IBM CAPI接å£çš„驱动)的
+开放ã€å¤„ç†å™¨æ— å…³çš„æ¼”è¿›ï¼Œè¿™ä¹ˆå‘½åæ˜¯ä¸ºäº†é¿å…与ISDN CAPIå­ç³»ç»Ÿç›¸æ··æ·†ã€‚
+
+
+高层视角
+========
+
+OpenCAPI定义了一个在物ç†é“¾è·¯å±‚上实现的数æ®é“¾è·¯å±‚(TL)和传输层(TL)。任何
+实现DLå’ŒTL的处ç†å™¨æˆ–者设备都å¯ä»¥å¼€å§‹å…±äº«å†…存。
+
+::
+
+ +-----------+ +-------------+
+ | | | |
+ | | | Accelerated |
+ | Processor | | Function |
+ | | +--------+ | Unit | +--------+
+ | |--| Memory | | (AFU) |--| Memory |
+ | | +--------+ | | +--------+
+ +-----------+ +-------------+
+ | |
+ +-----------+ +-------------+
+ | TL | | TLX |
+ +-----------+ +-------------+
+ | |
+ +-----------+ +-------------+
+ | DL | | DLX |
+ +-----------+ +-------------+
+ | |
+ | PHY |
+ +---------------------------------------+
+
+ Processor:处ç†å™¨
+ Memory:内存
+ Accelerated Function Unit:加速函数å•å…ƒ
+
+
+
+设备å‘现
+========
+
+OpenCAPIä¾èµ–一个在设备上实现的与PCI类似的é…置空间。因此主机å¯ä»¥é€šè¿‡æŸ¥è¯¢
+é…置空间æ¥å‘现AFU。
+
+OpenCAPI设备在Linux中被当作类PCI设备(有一些注æ„事项)。固件需è¦å¯¹ç¡¬ä»¶è¿›è¡Œ
+抽象,就好åƒå®ƒæ˜¯ä¸€ä¸ªPCI链路。许多已有的PCI架构被é‡ç”¨ï¼šåœ¨æ¨¡æ‹Ÿæ ‡å‡†PCI时,
+设备被扫æå¹¶ä¸”BAR(基å€å¯„存器)被分é…。åƒâ€œlspciâ€çš„命令因此å¯ä»¥è¢«ç”¨äºŽæŸ¥çœ‹
+哪些设备å¯ç”¨ã€‚
+
+é…置空间定义了å¯ä»¥åœ¨ç‰©ç†é€‚é…器上å¯ä»¥è¢«æ‰¾åˆ°çš„AFU,比如它的åå­—ã€æ”¯æŒå¤šå°‘内
+存上下文ã€å†…存映射IO(MMIO)区域的大å°ç­‰ã€‚
+
+
+
+MMIO
+====
+
+OpenCAPI为æ¯ä¸ªAFU定义了两个MMIO区域:
+
+* 全局MMIO区域,ä¿å­˜å’Œæ•´ä¸ªAFU相关的寄存器。
+* æ¯ä¸ªè¿›ç¨‹çš„MMIO区域,对于æ¯ä¸ªä¸Šä¸‹æ–‡å›ºå®šå¤§å°ã€‚
+
+
+
+AFU中断
+=======
+
+OpenCAPI拥有AFUå‘主机进程å‘é€ä¸­æ–­çš„å¯èƒ½æ€§ã€‚它通过定义在传输层的“intrp_reqâ€
+æ¥å®Œæˆï¼ŒæŒ‡å®šä¸€ä¸ªå®šä¹‰ä¸­æ–­çš„64ä½å¯¹è±¡å¥æŸ„。
+
+驱动å…许一个进程分é…中断并获å–å¯ä»¥ä¼ é€’ç»™AFUçš„64ä½å¯¹è±¡å¥æŸ„。
+
+
+
+字符设备
+========
+
+驱动为æ¯ä¸ªåœ¨ç‰©ç†è®¾å¤‡ä¸Šå‘现的AFU创建一个字符设备。一个物ç†è®¾å¤‡å¯èƒ½æ‹¥æœ‰å¤šä¸ª
+函数,一个函数å¯ä»¥æ‹¥æœ‰å¤šä¸ªAFU。ä¸è¿‡ç¼–写这篇文档之时,åªå¯¹å¯¼å‡ºä¸€ä¸ªAFU的设备
+测试过。
+
+字符设备å¯ä»¥åœ¨ /dev/ocxl/ 中被找到,其命å为:
+/dev/ocxl/<AFU åç§°>.<ä½ç½®>.<索引>
+
+<AFU åç§°> 是一个最长20个字符的å称,和在AFUé…置空间中找到的相åŒã€‚
+<ä½ç½®>由驱动添加,å¯åœ¨ç³»ç»Ÿæœ‰ä¸æ­¢ä¸€ä¸ªç›¸åŒçš„OpenCAPI设备时帮助区分设备。
+<索引>ä¹Ÿæ˜¯ä¸ºäº†åœ¨å°‘è§æƒ…况下帮助区分AFU,å³è®¾å¤‡æºå¸¦å¤šä¸ªåŒæ ·çš„AFU副本时。
+
+
+
+Sysfsç±»
+=======
+
+添加了代表AFU的ocxl类。查看/sys/class/ocxl。布局在
+Documentation/ABI/testing/sysfs-class-ocxl 中æè¿°ã€‚
+
+
+
+用户API
+=======
+
+打开
+----
+
+基于在é…置空间中找到的AFU定义,AFUå¯èƒ½æ”¯æŒåœ¨å¤šä¸ªå†…å­˜ä¸Šä¸‹æ–‡ä¸­å·¥ä½œï¼Œè¿™ç§æƒ…况
+下相关的字符设备å¯ä»¥è¢«ä¸åŒè¿›ç¨‹å¤šæ¬¡æ‰“开。
+
+
+ioctl
+-----
+
+OCXL_IOCTL_ATTACH:
+
+ 附加调用进程的内存上下文到AFU,以å…许AFU访问其内存。
+
+OCXL_IOCTL_IRQ_ALLOC:
+
+ 分é…AFU中断,返回标识符。
+
+OCXL_IOCTL_IRQ_FREE:
+
+ 释放之å‰åˆ†é…çš„AFU中断。
+
+OCXL_IOCTL_IRQ_SET_FD:
+
+ 将一个事件文件æè¿°ç¬¦å’ŒAFU中断关è”,因此用户进程å¯ä»¥åœ¨AFUå‘é€ä¸­æ–­æ—¶æ”¶åˆ°é€š
+ 知。
+
+OCXL_IOCTL_GET_METADATA:
+
+ 从å¡ä¸­èŽ·å–é…置信æ¯ï¼Œæ¯”如内存映射IO区域的大å°ã€AFU版本和当å‰ä¸Šä¸‹æ–‡çš„进程
+ 地å€ç©ºé—´ID(PASID)。
+
+OCXL_IOCTL_ENABLE_P9_WAIT:
+
+ å…许AFU唤醒执行“等待â€çš„用户空间进程。返回信æ¯ç»™ç”¨æˆ·ç©ºé—´ï¼Œå…许其é…ç½®AFU。
+ 注æ„è¿™åªåœ¨POWER9上å¯ç”¨ã€‚
+
+OCXL_IOCTL_GET_FEATURES:
+
+ 报告用户空间å¯ç”¨çš„å½±å“OpenCAPIçš„CPU特性。
+
+
+mmap
+----
+
+一个进程å¯ä»¥mmapæ¯ä¸ªè¿›ç¨‹çš„MMIO区域æ¥å’ŒAFU交互。
diff --git a/Documentation/translations/zh_CN/userspace-api/ebpf/index.rst b/Documentation/translations/zh_CN/userspace-api/ebpf/index.rst
new file mode 100644
index 000000000000..d52c7052f101
--- /dev/null
+++ b/Documentation/translations/zh_CN/userspace-api/ebpf/index.rst
@@ -0,0 +1,22 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../../disclaimer-zh_CN.rst
+
+:Original: Documentation/userspace-api/ebpf/index.rst
+
+:翻译:
+
+ æŽç¿ Rui Li <me@lirui.org>
+
+eBPF 用户空间API
+================
+
+eBPF是一ç§åœ¨Linux内核中æä¾›æ²™ç®±åŒ–è¿è¡ŒçŽ¯å¢ƒçš„æœºåˆ¶ï¼Œå®ƒå¯ä»¥åœ¨ä¸æ”¹å˜å†…æ ¸æºç æˆ–加载
+内核模å—的情况下扩展è¿è¡Œæ—¶å’Œç¼–写工具。eBPF程åºèƒ½å¤Ÿè¢«é™„加到å„ç§å†…æ ¸å­ç³»ç»Ÿä¸­ï¼ŒåŒ…
+括网络,跟踪和Linux安全模å—(LSM)等。
+
+关于eBPF的内部内核文档,请查看 Documentation/bpf/index.rst 。
+
+.. toctree::
+ :maxdepth: 1
+
+ syscall
diff --git a/Documentation/translations/zh_CN/userspace-api/ebpf/syscall.rst b/Documentation/translations/zh_CN/userspace-api/ebpf/syscall.rst
new file mode 100644
index 000000000000..47e2a59ae45d
--- /dev/null
+++ b/Documentation/translations/zh_CN/userspace-api/ebpf/syscall.rst
@@ -0,0 +1,29 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../../disclaimer-zh_CN.rst
+
+:Original: Documentation/userspace-api/ebpf/syscall.rst
+
+:翻译:
+
+ æŽç¿ Rui Li <me@lirui.org>
+
+eBPF Syscall
+------------
+
+:作者:
+ - Alexei Starovoitov <ast@kernel.org>
+ - Joe Stringer <joe@wand.net.nz>
+ - Michael Kerrisk <mtk.manpages@gmail.com>
+
+bpf syscall的主è¦ä¿¡æ¯å¯ä»¥åœ¨ `man-pages`_ 中的 `bpf(2)`_ 找到。
+
+bpf() å­å‘½ä»¤å‚考
+~~~~~~~~~~~~~~~~
+
+å­å‘½ä»¤åœ¨ä»¥ä¸‹å†…核代ç ä¸­ï¼š
+
+include/uapi/linux/bpf.h
+
+.. Links:
+.. _man-pages: https://www.kernel.org/doc/man-pages/
+.. _bpf(2): https://man7.org/linux/man-pages/man2/bpf.2.html
diff --git a/Documentation/translations/zh_CN/userspace-api/futex2.rst b/Documentation/translations/zh_CN/userspace-api/futex2.rst
new file mode 100644
index 000000000000..04f9d62db1f7
--- /dev/null
+++ b/Documentation/translations/zh_CN/userspace-api/futex2.rst
@@ -0,0 +1,80 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/userspace-api/futex2.rst
+
+:翻译:
+
+ æŽç¿ Rui Li <me@lirui.org>
+
+======
+futex2
+======
+
+:作者: André Almeida <andrealmeid@collabora.com>
+
+futex,或者称为快速用户互斥é”(fast user mutex),是一组å…è®¸ç”¨æˆ·ç©ºé—´åˆ›å»ºé«˜æ€§èƒ½åŒæ­¥
+机制的系统调用,比如用户空间中的互斥é”,信å·é‡å’Œæ¡ä»¶å˜é‡ã€‚C标准库,如glibc,使用它作
+为实现更多高级接å£çš„æ–¹å¼ï¼Œå¦‚pthreads。
+
+futex2是åˆä»£futex系统调用的åŽç»­ç‰ˆæœ¬ï¼Œæ—¨åœ¨å…‹æœåŽŸæœ‰æŽ¥å£çš„é™åˆ¶ã€‚
+
+用户API
+=======
+
+``futex_waitv()``
+-----------------
+
+等待一个futex数组,å¯ç”±å…¶ä¸­ä»»æ„一个唤醒::
+
+ futex_waitv(struct futex_waitv *waiters, unsigned int nr_futexes,
+ unsigned int flags, struct timespec *timeout, clockid_t clockid)
+
+ struct futex_waitv {
+ __u64 val;
+ __u64 uaddr;
+ __u32 flags;
+ __u32 __reserved;
+ };
+
+用户空间设置一个struct futex_waitv数组(最多128项),设置 ``uaddr`` 为等待的
+地å€ï¼Œ ``val`` 为期望值, ``flags`` 为指定的类型(如private)和futex的大å°ã€‚
+``__reserved`` 需è¦ç½®ä¸º0,但是它å¯ç”¨ä½œæœªæ¥æ‰©å±•ã€‚æŒ‡å‘æ•°ç»„第一个元素的指针作为
+``waiters`` 传递。如果 ``waiters`` 或任何的 ``uaddr`` åœ°å€æ— æ•ˆï¼Œå°†è¿”回 ``-EFAULT`` 。
+
+如果用户空间拥有32ä½çš„æŒ‡é’ˆï¼Œé‚£ä¹ˆéœ€è¦åšæ˜¾å¼è½¬æ¢æ¥ä¿è¯é«˜ä½æ¸…零。 ``uintptr_t`` 设计
+得很精巧,在32/64ä½çš„æŒ‡é’ˆä¸Šéƒ½æ­£å¸¸å·¥ä½œã€‚
+
+``nr_futexes`` 指定了数组的大å°ã€‚ä¸åœ¨[1,128]区间内的值会使系统调用返回 ``-EINVAL`` 。
+
+系统调用的 ``flags`` 傿•°éœ€è¦ç½®0,但å¯ç”¨ä½œæœªæ¥æ‰©å±•。
+
+对于æ¯ä¸ª ``waiters`` 数组中的项,在 ``uaddr`` 的当å‰å€¼ä¼šå’Œ ``val`` 比较。如果
+ä¸ä¸€è‡´ï¼Œç³»ç»Ÿè°ƒç”¨ä¼šæ’¤é”€æˆªè‡³ç›®å‰å®Œæˆçš„æ‰€æœ‰å·¥ä½œï¼Œå¹¶è¿”回 ``-EAGAIN`` 。如果所有测试
+和验è¯éƒ½é€šè¿‡ï¼Œç³»ç»Ÿè°ƒç”¨ä¼šç­‰å¾…直到以下情况之一å‘生:
+
+- 指定的timeout超时,返回 ``-ETIMEOUT`` 。
+- 一个信å·è¢«ä¼ é€’ç»™ç¡çœ ä¸­çš„任务,返回 ``-ERESTARTSYS`` 。
+- æŸä¸ªåˆ—表中的futex被唤醒,返回那个被唤醒的futex的索引。
+
+关于如何使用接å£çš„例å­å¯ä»¥åœ¨ ``tools/testing/selftests/futex/functional/futex_waitv.c``
+中找到。
+
+è¶…æ—¶
+----
+
+``struct timespec *timeout`` 是一个指å‘ç»å¯¹è¶…æ—¶æ—¶é—´çš„å¯é€‰å‚数。你需è¦åœ¨ ``clockid``
+傿•°ä¸­æŒ‡å®šè¦ä½¿ç”¨çš„æ—¶é’Ÿç±»åž‹ã€‚æ”¯æŒ ``CLOCK_MONOTONIC`` å’Œ ``CLOCK_REALTIME`` 。这个
+ç³»ç»Ÿè°ƒç”¨åªæŽ¥å—64ä½çš„timespec结构体。
+
+futex的类型
+-----------
+
+futexæ—¢å¯ä»¥æ˜¯ç§æœ‰çš„也å¯ä»¥æ˜¯å…±äº«çš„ã€‚ç§æœ‰ç”¨äºŽå¤šä¸ªè¿›ç¨‹å…±äº«åŒæ ·çš„内存空间,并且futex的虚拟
+地å€å¯¹æ‰€æœ‰è¿›ç¨‹éƒ½æ˜¯ä¸€æ ·çš„。这å…许在内核中进行优化。è¦ä½¿ç”¨ç§æœ‰futex,需è¦åœ¨futex标志中指定
+``FUTEX_PRIVATE_FLAG`` 。对于那些ä¸åœ¨åŒä¸€å†…存空间共享的进程,å¯ä»¥è®©åŒä¸€ä¸ªfutex拥有ä¸åŒ
+的虚拟地å€ï¼ˆä¾‹å¦‚使用基于文件的共享内存),这需è¦ä¸åŒçš„内部机制æ¥ä½¿å¾—正确进入队列。这是默认
+çš„è¡Œä¸ºï¼Œè€Œä¸”å¯¹ç§æœ‰futex和共享futex都适用。
+
+futexå¯ä»¥æ˜¯ä¸åŒçš„大å°ï¼š8,16,32或64ä½ã€‚ç›®å‰åªæ”¯æŒ32ä½å¤§å°çš„futex,并且需è¦é€šè¿‡ ``FUTEX_32``
+标志指定。
diff --git a/Documentation/translations/zh_CN/userspace-api/index.rst b/Documentation/translations/zh_CN/userspace-api/index.rst
new file mode 100644
index 000000000000..5dc0f2e69c17
--- /dev/null
+++ b/Documentation/translations/zh_CN/userspace-api/index.rst
@@ -0,0 +1,50 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/userspace-api/index.rst
+
+:翻译:
+
+ æŽç¿ Rui Li <me@lirui.org>
+
+=========================
+Linux 内核用户空间API指å—
+=========================
+
+.. _man-pages: https://www.kernel.org/doc/man-pages/
+
+尽管许多用户空间API的文档被记录在别处(特别是在 man-pages_ 项目中),
+åœ¨ä»£ç æ ‘中ä»ç„¶å¯ä»¥æ‰¾åˆ°æœ‰å…³ç”¨æˆ·ç©ºé—´çš„部分信æ¯ã€‚这个手册æ„在æˆä¸ºè¿™äº›ä¿¡æ¯
+èšé›†çš„地方。
+
+.. class:: toc-title
+
+ 目录
+
+.. toctree::
+ :maxdepth: 2
+
+ no_new_privs
+ seccomp_filter
+ accelerators/ocxl
+ ebpf/index
+ sysfs-platform_profile
+ futex2
+
+TODOList:
+
+* landlock
+* unshare
+* spec_ctrl
+* ioctl/index
+* iommu
+* media/index
+* netlink/index
+* vduse
+
+.. only:: subproject and html
+
+ Indices
+ =======
+
+ * :ref:`genindex`
diff --git a/Documentation/translations/zh_CN/userspace-api/no_new_privs.rst b/Documentation/translations/zh_CN/userspace-api/no_new_privs.rst
new file mode 100644
index 000000000000..81bd16ce3ad2
--- /dev/null
+++ b/Documentation/translations/zh_CN/userspace-api/no_new_privs.rst
@@ -0,0 +1,57 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/userspace-api/no_new_privs.rst
+
+:翻译:
+
+ æŽç¿ Rui Li <me@lirui.org>
+
+============
+æ— æ–°æƒé™æ ‡å¿—
+============
+
+execve系统调用å¯ä»¥ç»™ä¸€ä¸ªæ–°å¯åŠ¨çš„ç¨‹åºæŽˆäºˆå®ƒçš„çˆ¶ç¨‹åºæœ¬æ²¡æœ‰çš„æƒé™ã€‚最明显的两个
+例å­å°±æ˜¯setuid/setgid控制程åºå’Œæ–‡ä»¶çš„能力。为了é¿å…父程åºä¹ŸèŽ·å¾—è¿™äº›æƒé™ï¼Œå†…
+核和用户代ç å¿…é¡»å°å¿ƒé¿å…任何父程åºå¯ä»¥é¢ è¦†å­ç¨‹åºçš„æƒ…况。比如:
+
+ - 程åºåœ¨setuidåŽï¼ŒåЍæ€è£…è½½å™¨å¤„ç† ``LD_*`` 环境å˜é‡çš„ä¸åŒæ–¹å¼ã€‚
+
+ - 对于éžç‰¹æƒç¨‹åºï¼Œchroot是ä¸å…许的,因为这会å…许 ``/etc/passwd`` 在继承
+ chroot的程åºçœ¼ä¸­è¢«æ›¿æ¢ã€‚
+
+ - 执行代ç å¯¹ptrace有特殊处ç†ã€‚
+
+这些都是临时性的修å¤ã€‚ ``no_new_privs`` ä½ï¼ˆä»Ž Linux 3.5 起)是一个新的通
+用的机制æ¥ä¿è¯ä¸€ä¸ªè¿›ç¨‹å®‰å…¨åœ°ä¿®æ”¹å…¶æ‰§è¡ŒçŽ¯å¢ƒå¹¶è·¨execveæŒä¹…化。任何任务都å¯ä»¥è®¾
+ç½® ``no_new_privs`` 。一旦该ä½è¢«è®¾ç½®ï¼Œå®ƒä¼šåœ¨forkã€cloneå’Œexecve中继承下去
+,并且ä¸èƒ½è¢«æ’¤é”€ã€‚在 ``no_new_privs`` 被设置的情况下, ``execve()`` å°†ä¿è¯
+ä¸ä¼šæŽˆäºˆæƒé™åŽ»åšä»»ä½•没有execve调用就ä¸èƒ½åšçš„事情。比如, setuid å’Œ setgid
+ä½ä¸ä¼šå†æ”¹å˜ uid 或 gid;文件能力ä¸ä¼šè¢«æ·»åŠ åˆ°æŽˆæƒé›†åˆä¸­ï¼Œå¹¶ä¸”Linux安全模å—(
+LSM)ä¸ä¼šåœ¨execveè°ƒç”¨åŽæ”¾æ¾é™åˆ¶ã€‚
+
+设置 ``no_new_privs`` 使用::
+
+ prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+
+ä¸è¿‡è¦å°å¿ƒï¼ŒLinux安全模å—(LSM)也å¯èƒ½ä¸ä¼šåœ¨ ``no_new_privs`` 模å¼ä¸‹æ”¶ç´§çº¦æŸã€‚
+(这æ„味ç€ä¸€ä¸ªä¸€èˆ¬çš„æœåŠ¡å¯åŠ¨å™¨åœ¨æ‰§è¡Œå®ˆæŠ¤è¿›ç¨‹å‰å°±åŽ»è®¾ç½® ``no_new_privs`` å¯èƒ½
+会干扰基于LSM的沙箱。)
+
+请注æ„, ``no_new_privs`` å¹¶ä¸èƒ½é˜»æ­¢ä¸æ¶‰åŠ ``execve()`` çš„æƒé™å˜åŒ–。一个拥有
+适当æƒé™çš„任务ä»ç„¶å¯ä»¥è°ƒç”¨ ``setuid(2)`` 并接收 SCM_RIGHTS æ•°æ®æŠ¥ã€‚
+
+ç›®å‰æ¥è¯´ï¼Œ ``no_new_privs`` 有两大使用场景:
+
+ - 为seccomp模å¼2沙箱安装的过滤器会跨execveæŒä¹…åŒ–ï¼Œå¹¶èƒ½å¤Ÿæ”¹å˜æ–°æ‰§è¡Œç¨‹åºçš„行为。
+ éžç‰¹æƒç”¨æˆ·å› æ­¤åœ¨ ``no_new_privs`` 被设置的情况下åªå…许安装这样的过滤器。
+
+ - ``no_new_privs`` 本身就能被用于å‡å°‘éžç‰¹æƒç”¨æˆ·çš„æ”»å‡»é¢ã€‚如果所有以æŸä¸ª uid
+ è¿è¡Œçš„程åºéƒ½è®¾ç½®äº† ``no_new_privs`` ,那么那个 uid 将无法通过攻击 setuid,
+ setgid å’Œä½¿ç”¨æ–‡ä»¶èƒ½åŠ›çš„äºŒè¿›åˆ¶æ¥ææƒï¼›å®ƒéœ€è¦å…ˆæ”»å‡»ä¸€äº›æ²¡æœ‰è¢«è®¾ç½® ``no_new_privs``
+ ä½çš„东西。
+
+å°†æ¥ï¼Œå…¶ä»–潜在的å±é™©çš„内核特性å¯èƒ½è¢«éžç‰¹æƒä»»åŠ¡åˆ©ç”¨ï¼Œå³ä½¿ ``no_new_privs`` 被置ä½ã€‚
+原则上,当 ``no_new_privs`` è¢«ç½®ä½æ—¶ï¼Œ ``unshare(2)`` å’Œ ``clone(2)`` 的几个选
+项将是安全的,并且 ``no_new_privs`` 加上 ``chroot`` 是å¯ä»¥è¢«è®¤ä¸ºæ¯” chroot本身å±
+险性å°å¾—多的。
diff --git a/Documentation/translations/zh_CN/userspace-api/seccomp_filter.rst b/Documentation/translations/zh_CN/userspace-api/seccomp_filter.rst
new file mode 100644
index 000000000000..ede8b37c953f
--- /dev/null
+++ b/Documentation/translations/zh_CN/userspace-api/seccomp_filter.rst
@@ -0,0 +1,293 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/userspace-api/seccomp_filter.rst
+
+:翻译:
+
+ æŽç¿ Rui Li <me@lirui.org>
+
+==================================
+Seccomp BPF (基于过滤器的安全计算)
+==================================
+
+*Seccomp: SECure COMPuting*
+
+介ç»
+====
+
+大é‡ç³»ç»Ÿè°ƒç”¨è¢«æš´éœ²ç»™æ¯ä¸ªç”¨æˆ·ç©ºé—´è¿›ç¨‹ï¼Œä½†å…¶ä¸­åˆæœ‰è®¸å¤šç³»ç»Ÿè°ƒç”¨åœ¨è¿›ç¨‹çš„æ•´ä¸ªç”Ÿå‘½
+周期中都没被使用。éšç€ç³»ç»Ÿè°ƒç”¨çš„æ”¹å˜å’Œæˆç†Ÿï¼Œç¼ºé™·è¢«æ‰¾åˆ°å¹¶æ¶ˆé™¤ã€‚å…许æŸä¸€éƒ¨åˆ†åº”
+用程åºä»…能访问一部分系统调用是有好处的,这会缩å°å†…核暴露给应用程åºçš„é¢ç§¯ã€‚
+系统调用过滤器就是为这些应用程åºè€Œç”Ÿçš„。
+
+Seccomp过滤æä¾›äº†ä¸€ç§ä¸ºè¿›ç¨‹æŒ‡å®šä¸€ä¸ªå¤„ç†ç³»ç»Ÿè°ƒç”¨çš„过滤器的方法。这个过滤器体
+现为一个伯克利包过滤器(BPF)程åºï¼Œå°±åƒå¥—接字过滤器一样,ä¸åŒåœ¨äºŽå‰è€…处ç†çš„
+æ•°æ®å’Œæ­£åœ¨è¿›è¡Œçš„系统调用有关:系统调用å·å’Œç³»ç»Ÿè°ƒç”¨å‚数。这样使用一ç§é•¿æœŸä¸Ž
+ç”¨æˆ·ç©ºé—´å’Œç›´æŽ¥æ•°æ®æ‰“交é“的语言æ¥è¡¨è¾¾ç³»ç»Ÿè°ƒç”¨è¿‡æ»¤æˆä¸ºäº†å¯èƒ½ã€‚
+
+此外,BPF让seccomp用户ä¸å†æˆä¸ºåœ¨ç³»ç»Ÿè°ƒç”¨å¹²é¢„框架(system call interposition
+frameworks)中常è§çš„æ£€æŸ¥-ä½¿ç”¨ç«žæ€æ”»å‡»ï¼ˆTOCTOU)的å—害者。BPF程åºå¯èƒ½æ— æ³•解引
+用指针,这就é™åˆ¶äº†æ‰€æœ‰è¿‡æ»¤å™¨ä»…èƒ½ç›´æŽ¥è¯„ä¼°ç³»ç»Ÿè°ƒç”¨å‚æ•°ã€‚
+
+è¿™ä¸æ˜¯ä»€ä¹ˆ
+==========
+
+ç³»ç»Ÿè°ƒç”¨è¿‡æ»¤å¹¶ä¸æ˜¯ä¸€ä¸ªæ²™ç®±ã€‚它æä¾›äº†ä¸€ç§æ˜Žç¡®å®šä¹‰çš„æœºåˆ¶æ¥æœ€å°åŒ–内核暴露é¢ã€‚它
+旨在æˆä¸ºä¸€ä¸ªæ²™ç®±å¼€å‘è€…ä½¿ç”¨çš„å·¥å…·ã€‚é™¤æ­¤ä¹‹å¤–ï¼Œé€»è¾‘è¡Œä¸ºå’Œä¿¡æ¯æµçš„策略应该结åˆå…¶ä»–
+系统加固手段或者å¯èƒ½ç”±ä½ é€‰æ‹©çš„内核安全模å—(LSM)æ¥ç®¡ç†ã€‚易于表达的动æ€è¿‡æ»¤å™¨
+为这æ¡è·¯æä¾›äº†æ›´å¤šé€‰æ‹©ï¼ˆæ¯”如é¿å…ç—…æ€çš„大尿ˆ–者选择å…许 socketcall() 中的多路
+系统调用),但将其ç†è§£ä¸ºæ›´å®Œæ•´çš„æ²™ç®±è§£å†³æ–¹æ¡ˆæ˜¯é”™è¯¯çš„。
+
+用法
+====
+
+添加了一个é¢å¤–çš„seccomp模å¼ï¼Œå®ƒå¯ä»¥ä½¿ç”¨å’Œä¸¥æ ¼seccomp相åŒçš„ prctl(2) 调用æ¥å¯ç”¨ã€‚
+如果架构有 ``CONFIG_HAVE_ARCH_SECCOMP_FILTER`` 标志,那么å¯ä»¥æ·»åŠ ä»¥ä¸‹è¿‡æ»¤å™¨ï¼š
+
+``PR_SET_SECCOMP``:
+ çŽ°åœ¨éœ€è¦æ·»åŠ ä¸€ä¸ªé¢å¤–çš„å‚æ•°æ¥æŒ‡å®šä½¿ç”¨BPF程åºçš„æ–°è¿‡æ»¤å™¨ã€‚
+ BPF程åºå°†åœ¨å应系统调用å·ã€å‚数和其他元数æ®çš„seccomp_data结构体之上执行。
+ BPF程åºå¿…须返回å…许的值之一æ¥å‘ŠçŸ¥å†…核应该采å–什么行动。
+
+ 用法::
+
+ prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, prog);
+
+ 'prog' 傿•°æ˜¯ä¸€ä¸ªæŒ‡å‘ sock_fprog 结构体的指针,其中包å«äº†è¿‡æ»¤å™¨ç¨‹åºã€‚如
+ æžœç¨‹åºæ˜¯æ— æ•ˆçš„,该调用会返回 -1 并设置 errno 为 ``EINVAL`` 。
+
+ 如果 ``fork`` / ``clone`` å’Œ ``execve`` 被 @prog 所å…许,任何å­è¿›ç¨‹éƒ½å°†
+ å—到和父进程相åŒçš„过滤器和系统调用ABI的约æŸã€‚
+
+ 在调用之å‰ï¼Œè¿›ç¨‹å¿…须调用 ``prctl(PR_SET_NO_NEW_PRIVS, 1)`` 或者在它的
+ 命å空间内以 ``CAP_SYS_ADMIN`` æƒé™è¿è¡Œã€‚如果以上æ¡ä»¶ä¸æ»¡è¶³ï¼Œä¼šè¿”回
+ ``-EACCES`` ã€‚è¿™ä¸€è¦æ±‚ä¿è¯äº†è¿‡æ»¤å™¨ç¨‹åºä¸èƒ½ç”¨äºŽæ¯”安装过滤器的进程拥有更高
+ æƒé™çš„å­è¿›ç¨‹ã€‚
+
+ å¦å¤–,如果 ``prctl(2)`` 被安装的过滤器所å…许,就å¯ä»¥å åŠ é¢å¤–的过滤器。这会增
+ 加评估时间,但是å¯ä»¥è¿›ä¸€æ­¥é™ä½Žæ‰§è¡Œè¿›ç¨‹æ—¶çš„æ”»å‡»é¢ã€‚
+
+以上调用在æˆåŠŸæ—¶è¿”å›ž0,失败时返回一个éžé›¶çš„值。
+
+返回值
+======
+
+一个seccomp过滤器å¯èƒ½è¿”回下列任æ„值。如果多个过滤器存在,评估一个指定系统调用的
+返回值总会使用最高优先级的值。(比如 ``SECCOMP_RET_KILL_PROCESS`` 总是被优先
+返回。)
+
+按照优先级排åºï¼Œå®ƒä»¬æ˜¯ï¼š
+
+``SECCOMP_RET_KILL_PROCESS``:
+ 使得整个进程立å³ç»“æŸè€Œä¸æ‰§è¡Œç³»ç»Ÿè°ƒç”¨ã€‚è¿›ç¨‹çš„é€€å‡ºçŠ¶æ€ (``status & 0x7f``) å°†
+ 是 ``SIGSYS`` ï¼Œè€Œä¸æ˜¯ ``SIGKILL`` 。
+
+``SECCOMP_RET_KILL_THREAD``:
+ 使得线程立å³ç»“æŸè€Œä¸æ‰§è¡Œç³»ç»Ÿè°ƒç”¨ã€‚çº¿ç¨‹çš„é€€å‡ºçŠ¶æ€ (``status & 0x7f``) 将是
+ 是 ``SIGSYS`` ï¼Œè€Œä¸æ˜¯ ``SIGKILL`` 。
+
+``SECCOMP_RET_TRAP``:
+ 使得内核å‘触å‘进程å‘é€ä¸€ä¸ª ``SIGSYS`` ä¿¡å·è€Œä¸æ‰§è¡Œç³»ç»Ÿè°ƒç”¨ã€‚
+ ``siginfo->si_call_addr`` 会展示系统调用指令的ä½ç½®ï¼Œ ``siginfo->si_syscall``
+ å’Œ ``siginfo->si_arch`` 会指出试图进行的系统调用。程åºè®¡æ•°å™¨ä¼šå’Œå‘生了系统
+ 调用的一样(å³å®ƒä¸ä¼šæŒ‡å‘系统调用指令)。返回值寄存器会包å«ä¸€ä¸ªä¸Žæž¶æž„相关的值——
+ 如果æ¢å¤æ‰§è¡Œï¼Œéœ€è¦å°†å…¶è®¾ä¸ºåˆç†çš„值。(架构ä¾èµ–性是因为将其替æ¢ä¸º ``-ENOSYS``
+ 会导致一些有用的信æ¯è¢«è¦†ç›–。)
+
+ 返回值的 ``SECCOMP_RET_DATA`` 部分会作为 ``si_errno`` 传递。
+
+ ç”±seccomp触å‘çš„ ``SIGSYS`` 会有一个 ``SYS_SECCOMP`` çš„ si_code 。
+
+``SECCOMP_RET_ERRNO``:
+ 使得返回值的低16ä½ä½œä¸ºerrnoä¼ é€’ç»™ç”¨æˆ·ç©ºé—´ï¼Œè€Œä¸æ‰§è¡Œç³»ç»Ÿè°ƒç”¨ã€‚
+
+``SECCOMP_RET_USER_NOTIF``:
+ 使得一个 ``struct seccomp_notif`` 消æ¯è¢«å‘é€åˆ°å·²é™„加的用户空间通知文件æè¿°
+ 符。如果没有被附加则返回 ``-ENOSYS`` 。下é¢ä¼šè®¨è®ºå¦‚何处ç†ç”¨æˆ·é€šçŸ¥ã€‚
+
+``SECCOMP_RET_TRACE``:
+ 当返回的时候,这个值会使得内核在执行系统调用å‰å°è¯•去通知一个基于 ``ptrace()``
+ 的追踪器。如果没有追踪器, ``-ENOSYS`` 会返回给用户空间,并且系统调用ä¸ä¼šæ‰§è¡Œã€‚
+
+ 如果追踪器通过 ``ptrace(PTRACE_SETOPTIONS)`` 请求了 ``PTRACE_O_TRACESECCOMP``,
+ 那么它会收到 ``PTRACE_EVENT_SECCOMP`` 通知。BPF程åºè¿”回值的 ``SECCOMP_RET_DATA``
+ 部分会通过 ``PTRACE_GETEVENTMSG`` æä¾›ç»™è¿½è¸ªå™¨ã€‚
+
+ 追踪器å¯ä»¥é€šè¿‡æ”¹å˜ç³»ç»Ÿè°ƒç”¨å·åˆ°-1æ¥è·³è¿‡ç³»ç»Ÿè°ƒç”¨ã€‚或者追踪器å¯ä»¥æ”¹å˜ç³»ç»Ÿè°ƒç”¨å·åˆ°
+ ä¸€ä¸ªæœ‰æ•ˆå€¼æ¥æ”¹å˜è¯·æ±‚的系统调用。如果追踪器请求跳过系统调用,那么系统调用将返回
+ 追踪器放在返回值寄存器中的值。
+
+ 在追踪器被通知åŽï¼Œseccomp检查ä¸ä¼šå†æ¬¡è¿è¡Œã€‚(这æ„味ç€åŸºäºŽseccompçš„æ²™ç®±å¿…é¡»ç¦æ­¢
+ ptrace的使用,甚至其他沙箱进程也ä¸è¡Œï¼Œé™¤éžéžå¸¸å°å¿ƒï¼›ptraceå¯ä»¥é€šè¿‡è¿™ä¸ªæœºåˆ¶æ¥é€ƒ
+ 逸。)
+
+``SECCOMP_RET_LOG``:
+ 使得系统调用在被记录之åŽå†è¿è¡Œã€‚这应该被应用开å‘è€…ç”¨æ¥æ£€æŸ¥ä»–们的程åºéœ€è¦å“ªäº›
+ 系统调用,而ä¸éœ€è¦åå¤é€šè¿‡å¤šä¸ªæµ‹è¯•和开å‘周期æ¥å»ºç«‹æ¸…å•。
+
+ åªæœ‰åœ¨ actions_logged sysctl 字符串中出现 "log" 时,这个æ“作æ‰ä¼šè¢«è®°å½•。
+
+``SECCOMP_RET_ALLOW``:
+ 使得系统调用被执行。
+
+如果多个追踪器存在,评估系统调用的返回值将永远使用最高优先级的值。
+
+优先级åªé€šè¿‡ ``SECCOMP_RET_ACTION`` æŽ©ç æ¥å†³å®šã€‚当多个过滤器返回相åŒä¼˜å…ˆçº§çš„返回
+å€¼æ—¶ï¼Œåªæœ‰æ¥è‡ªæœ€è¿‘安装的过滤器的 ``SECCOMP_RET_DATA`` 会被返回。
+
+éšæ‚£
+====
+
+最需è¦é¿å…çš„éšæ‚£æ˜¯åœ¨è¿‡æ»¤ç³»ç»Ÿè°ƒç”¨å·æ—¶å´ä¸æ£€æŸ¥æž¶æž„值。因为在任何支æŒå¤šä¸ªç³»ç»Ÿè°ƒç”¨
+约定的架构上,系统调用å·å¯èƒ½æ ¹æ®å…·ä½“调用而ä¸åŒã€‚如果ä¸åŒè°ƒç”¨çº¦å®šä¸­çš„è°ƒç”¨å·æœ‰é‡å ï¼Œ
+那么过滤器的检查å¯èƒ½è¢«æ»¥ç”¨ã€‚请总是检查架构值ï¼
+
+例å­
+====
+
+``samples/seccomp/`` 文件夹包å«äº†x86ä¸“ç”¨å’Œæ›´é€šç”¨çš„ä½¿ç”¨é«˜å±‚å®æŽ¥å£æ¥ç”ŸæˆBPF程åºçš„
+例å­ã€‚
+
+用户空间通知
+============
+
+``SECCOMP_RET_USER_NOTIF`` 返回值会让seccomp过滤器传递一个特定的系统调用给用户
+空间处ç†ã€‚è¿™å¯èƒ½ä¼šå¯¹åƒå®¹å™¨ç®¡ç†å™¨çš„ç¨‹åºæœ‰ç”¨ï¼Œå®ƒä»¬å¸Œæœ›æ‹¦æˆªç‰¹å®šçš„系统调用(如 ``mount()``,
+``finit_module()`` 等等)并改å˜å…¶è¡Œä¸ºã€‚
+
+传递 ``SECCOMP_FILTER_FLAG_NEW_LISTENER`` 傿•°ç»™ ``seccomp()`` 系统调用å¯ä»¥å–
+得通知文件æè¿°ç¬¦ï¼š
+
+.. code-block:: c
+
+ fd = seccomp(SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_NEW_LISTENER, &prog);
+
+æˆåŠŸæƒ…å†µä¸‹ä¼šè¿”å›žä¸€ä¸ªå¯¹è¿‡æ»¤å™¨ç›‘å¬çš„æ–‡ä»¶æè¿°ç¬¦ï¼Œç„¶åŽå¯ä»¥é€šè¿‡ ``SCM_RIGHTS`` 或类似
+的方å¼ä¼ é€’ã€‚éœ€è¦æ³¨æ„的是,过滤器文件æè¿°ç¬¦é’ˆå¯¹çš„æ˜¯ä¸€ä¸ªç‰¹å®šçš„è¿‡æ»¤å™¨è€Œä¸æ˜¯ç‰¹å®šçš„进程。
+æ‰€ä»¥å¦‚æžœè¿™ä¸ªè¿›ç¨‹åŽæ¥fork了,æ¥è‡ªä¸¤ä¸ªè¿›ç¨‹çš„通知都会出现在åŒä¸€ä¸ªè¿‡æ»¤å™¨æ–‡ä»¶æè¿°ç¬¦ä¸­ã€‚
+对于过滤器文件æè¿°ç¬¦çš„è¯»å†™ä¹Ÿæ˜¯åŒæ­¥çš„,所以一个过滤器文件æè¿°ç¬¦å¯ä»¥å®‰å…¨åœ°æ‹¥æœ‰å¤šä¸ªè¯»è€…。
+
+seccomp通知文件æè¿°ç¬¦ç”±ä¸¤ä¸ªç»“构体组æˆï¼š
+
+.. code-block:: c
+
+ struct seccomp_notif_sizes {
+ __u16 seccomp_notif;
+ __u16 seccomp_notif_resp;
+ __u16 seccomp_data;
+ };
+
+ struct seccomp_notif {
+ __u64 id;
+ __u32 pid;
+ __u32 flags;
+ struct seccomp_data data;
+ };
+
+ struct seccomp_notif_resp {
+ __u64 id;
+ __s64 val;
+ __s32 error;
+ __u32 flags;
+ };
+
+``struct seccomp_notif_sizes`` 结构体å¯ä»¥ç”¨äºŽç¡®å®šseccomp通知中å„ç§ç»“构体的大å°ã€‚
+``struct seccomp_data`` 的大å°å¯èƒ½æœªæ¥ä¼šæ”¹å˜ï¼Œæ‰€ä»¥éœ€è¦ä½¿ç”¨ä¸‹é¢çš„代ç ï¼š
+
+.. code-block:: c
+
+ struct seccomp_notif_sizes sizes;
+ seccomp(SECCOMP_GET_NOTIF_SIZES, 0, &sizes);
+
+æ¥å†³å®šéœ€è¦åˆ†é…的多ç§ç»“构体的大å°ã€‚请查看 samples/seccomp/user-trap.c 中的例å­ã€‚
+
+用户å¯ä»¥é€šè¿‡ ``ioctl(SECCOMP_IOCTL_NOTIF_RECV)`` (或 ``poll()``) 读å–seccomp
+通知文件æè¿°ç¬¦æ¥æŽ¥æ”¶ä¸€ä¸ª ``struct seccomp_notif`` ,其中包å«äº”个æˆå‘˜ï¼šç»“构体的
+输入长度,æ¯ä¸ªè¿‡æ»¤å™¨å”¯ä¸€çš„ ``id`` , 触å‘请求进程的 ``pid`` (如果进程的pid命å空
+间对于监å¬è€…çš„pid命å空间ä¸å¯è§çš„è¯ï¼Œå¯èƒ½ä¸º0)。通知还包å«ä¼ é€’ç»™seccompçš„ ``data``
+和一个过滤器标志。在调用ioctlå‰ç»“构体应该被清空。
+
+之åŽç”¨æˆ·ç©ºé—´å¯ä»¥æ ¹æ®è¿™äº›ä¿¡æ¯å†³å®šåšä»€ä¹ˆï¼Œå¹¶é€šè¿‡ ``ioctl(SECCOMP_IOCTL_NOTIF_SEND)``
+å‘é€ä¸€ä¸ªå“应,表示应该给用户空间返回什么。 ``struct seccomp_notif_resp`` çš„ ``id``
+æˆå‘˜åº”该和 ``struct seccomp_notif`` çš„ ``id`` 一致。
+
+用户空间也å¯ä»¥é€šè¿‡ ``ioctl(SECCOMP_IOCTL_NOTIF_ADDFD)`` å‘通知进程添加文件æè¿°
+符。 ``struct seccomp_notif_addfd`` çš„ ``id`` æˆå‘˜åº”该和 ``struct seccomp_notif``
+çš„ ``id`` ä¿æŒä¸€è‡´ã€‚ ``newfd_flags`` 标志å¯ä»¥è¢«ç”¨äºŽåœ¨é€šçŸ¥è¿›ç¨‹çš„æ–‡ä»¶æè¿°ç¬¦ä¸Šè®¾ç½®
+O_CLOEXEC 等标志。如果监ç£è€…(supervisorï¼‰å‘æ–‡ä»¶æè¿°ç¬¦æ³¨å…¥ä¸€ä¸ªç‰¹å®šçš„æ•°å­—,å¯ä»¥ä½¿ç”¨
+``SECCOMP_ADDFD_FLAG_SETFD`` 标志,并设置 ``newfd`` æˆå‘˜ä¸ºè¦ä½¿ç”¨çš„特定数字。
+如果文件æè¿°ç¬¦å·²ç»åœ¨é€šçŸ¥è¿›ç¨‹ä¸­æ‰“开,那它将被替æ¢ã€‚监ç£è€…也å¯ä»¥æ·»åŠ ä¸€ä¸ªæ–‡ä»¶æè¿°ç¬¦ï¼Œ
+并使用 ``SECCOMP_ADDFD_FLAG_SEND`` 标志原å­å“应,返回值将是注入的文件æè¿°ç¬¦ç¼–å·ã€‚
+
+通知进程å¯ä»¥è¢«æŠ¢å ï¼Œå¯¼è‡´é€šçŸ¥è¢«ç»ˆæ­¢ã€‚è¿™å¯èƒ½åœ¨å°è¯•代表通知进程执行长时间且通常å¯é‡è¯•
+(如挂载文件系统)的æ“作时导致问题。å¦å¤–,在安装过滤器的时候,
+``SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV`` å¯ä»¥è¢«è®¾ç½®ã€‚这个标志使得当监ç£è€…收到用
+户通知时,通知进程会忽略éžè‡´å‘½ä¿¡å·ï¼Œç›´åˆ°å“应被å‘é€ã€‚在用户空间收到通知之å‰å‘出的信å·
+将被正常处ç†ã€‚
+
+值得注æ„的是, ``struct seccomp_data`` 包å«äº†ç³»ç»Ÿè°ƒç”¨å¯„å­˜å™¨å‚æ•°çš„值,但是ä¸åŒ…嫿Œ‡å‘
+内存的指针。进程的内存å¯ä»¥é€šè¿‡ ``ptrace()`` 或 ``/proc/pid/mem`` ç”±åˆé€‚的特æƒè·Ÿè¸ª
+è®¿é—®ã€‚ä½†æ˜¯ï¼Œéœ€è¦æ³¨æ„é¿å…ä¹‹å‰æåˆ°çš„TOCTOUæ”»å‡»ï¼šæ‰€æœ‰ä»Žè¢«è·Ÿè¸ªè€…å†…å­˜ä¸­è¯»åˆ°çš„å‚æ•°éƒ½åº”该先
+读到追踪器的内存中,å†åšå‡ºç­–略决定。这样就å¯ä»¥å¯¹ç³»ç»Ÿè°ƒç”¨çš„傿•°åšåŽŸå­å†³å®šã€‚
+
+Sysctls
+=======
+
+Seccompçš„sysctl文件å¯ä»¥åœ¨ ``/proc/sys/kernel/seccomp/`` 文件夹中找到。这里有对文件
+夹中æ¯ä¸ªæ–‡ä»¶çš„æè¿°ï¼š
+
+``actions_avail``:
+ 以字符串形å¼ä¿å­˜seccomp返回值(å‚考上文的 ``SECCOMP_RET_*`` å®ï¼‰çš„åªè¯»æœ‰åº
+ åˆ—è¡¨ã€‚ä»Žå·¦å¾€å³æŒ‰ç…§æœ€å°‘许å¯è¿”回值到最多许å¯è¿”回值排åºã€‚
+
+ 这个列表代表了内核支æŒçš„seccomp返回值集åˆã€‚一个用户空间程åºå¯ä»¥ä½¿ç”¨è¿™ä¸ªåˆ—表æ¥åœ¨
+ 程åºå»ºç«‹æ—¶ç¡®å®šåœ¨ ``seccomp.h`` 中找到的动作是å¦å’Œå½“å‰è¿è¡Œå†…核实际支æŒçš„动作有所
+ ä¸åŒã€‚
+
+``actions_logged``:
+ å…许被记录的seccomp返回值(å‚考上文的 ``SECCOMP_RET_*`` å®ï¼‰çš„å¯è¯»å†™æœ‰åºåˆ—表。
+ 对文件写入ä¸éœ€è¦æ˜¯æœ‰åºçš„,但从文件读å–将采用与actions_avail sysctlä¸€è‡´çš„æ–¹å¼æŽ’åºã€‚
+
+ ``allow`` 字符串在 ``actions_logged`` sysctl中ä¸è¢«æŽ¥æ”¶ï¼Œå› ä¸ºä¸å¯èƒ½è®°å½•
+ ``SECCOMP_RET_ALLOW`` 动作。å°è¯•å‘sysctl写入 ``allow`` 会导致返回一个EINVAL。
+
+添加架构支æŒ
+============
+
+请查看 ``arch/Kconfig`` 了解æƒå¨è¦æ±‚。总的æ¥è¯´å¦‚æžœä¸€ä¸ªæž¶æž„åŒæ—¶æ”¯æŒptrace_eventå’Œ
+seccomp,那么它将å¯ä»¥é€šè¿‡è¾ƒå°çš„修改支æŒseccomp过滤器: ``SIGSYS`` 支æŒå’Œseccomp
+返回值检查。然åŽå¿…须将 ``CONFIG_HAVE_ARCH_SECCOMP_FILTER`` 添加到它的架构特定
+的Kconfig中。
+
+注æ„事项
+========
+
+vDSOå¯èƒ½å¯¼è‡´ä¸€äº›ç³»ç»Ÿè°ƒç”¨å®Œå…¨åœ¨ç”¨æˆ·ç©ºé—´ä¸­è¿è¡Œï¼Œå½“你在ä¸åŒæœºå™¨ä¸Šè·‘ç¨‹åºæ—¶å¯èƒ½å¯¼è‡´å›žé€€
+到真正系统调用的æ„外å‘生。为了在x86上最å°åŒ–这些æ„外的å‘生,请确ä¿ä½ åœ¨æµ‹è¯•时把
+``/sys/devices/system/clocksource/clocksource0/current_clocksource`` 设置为
+``acpi_pm`` 之类的值。
+
+在x86-64上,vsyscall模拟默认开å¯ã€‚(vsyscalls是vDSO调用的传统å˜ä½“。)目å‰ï¼Œæ¨¡æ‹Ÿ
+vsyscalls会éµå®ˆseccomp,但是有一些奇怪情况:
+
+- ``SECCOMP_RET_TRAP`` 的返回值会设置一个指å‘给定vsyscallå…¥å£çš„ ``si_call_addr``,
+ è€Œä¸æ˜¯'syscall'指令之åŽçš„地å€ã€‚ä»»ä½•æƒ³é‡æ–°å¼€å§‹è°ƒç”¨çš„代ç éƒ½éœ€è¦æ³¨æ„ (a) ret指令
+ 已被模拟,(b) 试图æ¢å¤ç³»ç»Ÿè°ƒç”¨å°†å†æ¬¡è§¦å‘标准vsyscall模拟安全检查,使得æ¢å¤ç³»ç»Ÿ
+ 调用在大部分情况下没有æ„义。
+
+- ``SECCOMP_RET_TRACE`` 的返回值将åƒå¾€å¸¸ä¸€æ ·ç»™è¿½è¸ªå™¨å‘出信å·ï¼Œä½†æ˜¯ç³»ç»Ÿè°ƒç”¨å¯èƒ½ä¸èƒ½
+ 使用orig_rax寄存器改å˜ä¸ºå¦ä¸€ä¸ªç³»ç»Ÿè°ƒç”¨ã€‚å¯èƒ½åªèƒ½æ”¹å˜ä¸º-1æ¥è·³è¿‡å½“剿¨¡æ‹Ÿçš„调用。
+ 任何其他改å˜éƒ½å¯èƒ½ç»ˆæ­¢è¿›ç¨‹ã€‚追踪器看到的rip值将是系统调用的入å£åœ°å€ï¼›è¿™å’Œæ­£å¸¸è¡Œä¸º
+ ä¸åŒã€‚è¿½è¸ªå™¨ç¦æ­¢ä¿®æ”¹rip或者rsp。(ä¸è¦ä¾èµ–å…¶ä»–æ”¹å˜æ¥ç»ˆæ­¢è¿›ç¨‹ï¼Œå®ƒä»¬å¯èƒ½æ­£å¸¸å·¥ä½œã€‚
+ 比如在一些内核中,选择一个åªå­˜åœ¨äºŽæœªæ¥å†…核中的系统调用将被正确模拟,返回一个
+ ``-ENOSYS`` 。)
+
+è¦æ£€æµ‹è¿™ä¸ªå¤æ€ªçš„行为,å¯ä»¥æ£€æŸ¥ ``addr & ~0x0C00 == 0xFFFFFFFFFF600000``。(对于
+``SECCOMP_RET_TRACE`` ,使用rip。对于 ``SECCOMP_RET_TRAP`` ,使用
+``siginfo->si_call_addr`` 。)ä¸è¦æ£€æµ‹å…¶ä»–æ¡ä»¶ï¼šæœªæ¥å†…æ ¸å¯èƒ½ä¼šæ”¹è¿›vsyscall模拟,
+当å‰å†…核在vsyscall=native模å¼ä¸‹ä¼šæœ‰ä¸åŒè¡¨çŽ°ï¼Œä½†åœ¨è¿™äº›æƒ…å†µä¸‹ï¼Œ ``0xF...F600{0,4,8,C}00``
+å¤„çš„æŒ‡ä»¤å°†ä¸æ˜¯ç³»ç»Ÿè°ƒç”¨ã€‚
+
+请注æ„,现代系统根本ä¸å¯èƒ½ä½¿ç”¨vsyscalls —— 它们是一ç§é—留功能,而且比标准系统调用
+慢得多。 新的代ç å°†ä½¿ç”¨vDSO,而vDSOå‘出的系统调用与正常的系统调用没有区别。
diff --git a/Documentation/translations/zh_CN/userspace-api/sysfs-platform_profile.rst b/Documentation/translations/zh_CN/userspace-api/sysfs-platform_profile.rst
new file mode 100644
index 000000000000..7d21740db125
--- /dev/null
+++ b/Documentation/translations/zh_CN/userspace-api/sysfs-platform_profile.rst
@@ -0,0 +1,40 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. include:: ../disclaimer-zh_CN.rst
+
+:Original: Documentation/userspace-api/sysfs-platform_profile.rst
+
+:翻译:
+
+ æŽç¿ Rui Li <me@lirui.org>
+
+==========================================================
+å¹³å°é…置文件选择(如 /sys/firmware/acpi/platform_profile)
+==========================================================
+
+çŽ°ä»£ç³»ç»Ÿä¸­å¹³å°æ€§èƒ½ã€æ¸©åº¦ã€é£Žæ‰‡å’Œå…¶ä»–硬件相关的特性通常是å¯ä»¥åЍæ€é…置的。平å°
+é…置通常会根æ®å½“å‰çš„状æ€ç”±ä¸€äº›è‡ªåŠ¨æœºåˆ¶ï¼ˆå¾ˆå¯èƒ½å­˜åœ¨äºŽå†…核之外)æ¥è‡ªåŠ¨è°ƒæ•´ã€‚
+
+这些平å°è‡ªåŠ¨è°ƒæ•´æœºåˆ¶é€šå¸¸èƒ½å¤Ÿè¢«é…ç½®æˆå¤šä¸ªå¹³å°é…置文件中的一个,è¦ä¹ˆåå‘节能è¿
+行,è¦ä¹ˆå呿€§èƒ½è¿è¡Œã€‚
+
+platform_profile属性的目的是æä¾›ä¸€ä¸ªé€šç”¨çš„sysfs APIæ¥é€‰æ‹©è¿™äº›å¹³å°è‡ªåЍé…ç½®
+机制的é…置文件。
+
+éœ€è¦æ³¨æ„的是,这个APIåªèƒ½ç”¨ä½œé€‰æ‹©å¹³å°é…置文件,用æ¥ç›‘测所产生的性能特å¾å¹¶ä¸
+是其目标。监测性能最好使用设备/供应商æä¾›çš„工具,比如turbostat。
+
+具体æ¥è¯´ï¼Œå½“选择高性能é…置文件时,真实能达到的性能å¯èƒ½å—制于多ç§å› ç´ ï¼Œæ¯”如:
+其他组件的å‘热,房间温度,笔记本底部的自由空气æµåŠ¨ç­‰ã€‚è®©ç”¨æˆ·ç©ºé—´çŸ¥é“任何阻ç¢
+è¾¾åˆ°è¦æ±‚性能水平的局部最优æ¡ä»¶ï¼Œæ˜¾ç„¶ä¸æ˜¯è¿™ä¸ªAPI的目标。
+
+由于数字本身并ä¸èƒ½ä»£è¡¨ä¸€ä¸ªé…置文件会调整的多个å˜é‡ï¼ˆåŠŸè€—ï¼Œå‘热等),这个API
+ä½¿ç”¨å­—ç¬¦ä¸²æ¥æè¿°å¤šç§é…置文件。为了ä¿è¯ç”¨æˆ·ç©ºé—´èƒ½å¤ŸèŽ·å¾—ä¸€è‡´çš„ä½“éªŒï¼Œ
+sysfs-platform_profile ABI 文档定义了一个固定的é…置文件å集åˆã€‚驱动程åº
+*å¿…é¡»* 将它们内置的é…置文件表示映射到这个固定的集åˆä¸­ã€‚
+
+如果映射时没有很好的匹é…,å¯ä»¥æ·»åŠ ä¸€ä¸ªæ–°çš„é…置文件å称。驱动希望引入的新é…ç½®
+文件å称时必须:
+
+ 1. 解释为什么无法使用已有的é…置文件å称。
+ 2. 添加一个新的é…置文件å称,以åŠé¢„期行为的清晰æè¿°ï¼Œä¿å­˜åˆ°
+ sysfs-platform_profile ABI文档中。
diff --git a/Documentation/usb/CREDITS b/Documentation/usb/CREDITS
index 67c59cdc9959..81ea3eb29e96 100644
--- a/Documentation/usb/CREDITS
+++ b/Documentation/usb/CREDITS
@@ -1,7 +1,7 @@
Credits for the Simple Linux USB Driver:
The following people have contributed to this code (in alphabetical
-order by last name). I'm sure this list should be longer, its
+order by last name). I'm sure this list should be longer, it's
difficult to maintain, add yourself with a patch if desired.
Georg Acher <acher@informatik.tu-muenchen.de>
@@ -126,7 +126,7 @@ THANKS file in Inaky's driver):
- Jochen Karrer <karrer@wpfd25.physik.uni-wuerzburg.de>, for
pointing out mortal bugs and giving advice.
- - Edmund Humemberger <ed@atnet.at>, for it's great work on
+ - Edmund Humemberger <ed@atnet.at>, for his great work on
public relationships and general management stuff for the
Linux-USB effort.
@@ -136,7 +136,7 @@ THANKS file in Inaky's driver):
- Ric Klaren <ia_ric@cs.utwente.nl> for doing nice
introductory documents (competing with Alberto's :).
- - Christian Groessler <cpg@aladdin.de>, for it's help on those
+ - Christian Groessler <cpg@aladdin.de>, for his help on those
itchy bits ... :)
- Paul MacKerras for polishing OHCI and pushing me harder for
diff --git a/Documentation/usb/functionfs.rst b/Documentation/usb/functionfs.rst
index 7fdc6d840ac5..a3054bea38f3 100644
--- a/Documentation/usb/functionfs.rst
+++ b/Documentation/usb/functionfs.rst
@@ -49,7 +49,7 @@ level it would look like this::
$ ( cd /dev/ffs-hid && hid-daemon ) &
On kernel level the gadget checks ffs_data->dev_name to identify
-whether it's FunctionFS designed for MTP ("mtp") or HID ("hid").
+whether its FunctionFS is designed for MTP ("mtp") or HID ("hid").
If no "functions" module parameters is supplied, the driver accepts
just one function with any name.
diff --git a/Documentation/usb/gadget_multi.rst b/Documentation/usb/gadget_multi.rst
index 3a22c1b2f39e..f78a51ff2324 100644
--- a/Documentation/usb/gadget_multi.rst
+++ b/Documentation/usb/gadget_multi.rst
@@ -9,7 +9,7 @@ The Multifunction Composite Gadget (or g_multi) is a composite gadget
that makes extensive use of the composite framework to provide
a... multifunction gadget.
-In it's standard configuration it provides a single USB configuration
+In its standard configuration it provides a single USB configuration
with RNDIS[1] (that is Ethernet), USB CDC[2] ACM (that is serial) and
USB Mass Storage functions.
diff --git a/Documentation/userspace-api/landlock.rst b/Documentation/userspace-api/landlock.rst
index cec780c2f497..d8cd8cd9ce25 100644
--- a/Documentation/userspace-api/landlock.rst
+++ b/Documentation/userspace-api/landlock.rst
@@ -8,7 +8,7 @@ Landlock: unprivileged access control
=====================================
:Author: Mickaël Salaün
-:Date: September 2022
+:Date: October 2022
The goal of Landlock is to enable to restrict ambient rights (e.g. global
filesystem access) for a set of processes. Because Landlock is a stackable
@@ -60,7 +60,8 @@ the need to be explicit about the denied-by-default access rights.
LANDLOCK_ACCESS_FS_MAKE_FIFO |
LANDLOCK_ACCESS_FS_MAKE_BLOCK |
LANDLOCK_ACCESS_FS_MAKE_SYM |
- LANDLOCK_ACCESS_FS_REFER,
+ LANDLOCK_ACCESS_FS_REFER |
+ LANDLOCK_ACCESS_FS_TRUNCATE,
};
Because we may not know on which kernel version an application will be
@@ -69,16 +70,28 @@ should try to protect users as much as possible whatever the kernel they are
using. To avoid binary enforcement (i.e. either all security features or
none), we can leverage a dedicated Landlock command to get the current version
of the Landlock ABI and adapt the handled accesses. Let's check if we should
-remove the ``LANDLOCK_ACCESS_FS_REFER`` access right which is only supported
-starting with the second version of the ABI.
+remove the ``LANDLOCK_ACCESS_FS_REFER`` or ``LANDLOCK_ACCESS_FS_TRUNCATE``
+access rights, which are only supported starting with the second and third
+version of the ABI.
.. code-block:: c
int abi;
abi = landlock_create_ruleset(NULL, 0, LANDLOCK_CREATE_RULESET_VERSION);
- if (abi < 2) {
+ if (abi < 0) {
+ /* Degrades gracefully if Landlock is not handled. */
+ perror("The running kernel does not enable to use Landlock");
+ return 0;
+ }
+ switch (abi) {
+ case 1:
+ /* Removes LANDLOCK_ACCESS_FS_REFER for ABI < 2 */
ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_REFER;
+ __attribute__((fallthrough));
+ case 2:
+ /* Removes LANDLOCK_ACCESS_FS_TRUNCATE for ABI < 3 */
+ ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_TRUNCATE;
}
This enables to create an inclusive ruleset that will contain our rules.
@@ -127,8 +140,8 @@ descriptor.
It may also be required to create rules following the same logic as explained
for the ruleset creation, by filtering access rights according to the Landlock
-ABI version. In this example, this is not required because
-``LANDLOCK_ACCESS_FS_REFER`` is not allowed by any rule.
+ABI version. In this example, this is not required because all of the requested
+``allowed_access`` rights are already available in ABI 1.
We now have a ruleset with one rule allowing read access to ``/usr`` while
denying all other handled accesses for the filesystem. The next step is to
@@ -252,6 +265,37 @@ To be allowed to use :manpage:`ptrace(2)` and related syscalls on a target
process, a sandboxed process should have a subset of the target process rules,
which means the tracee must be in a sub-domain of the tracer.
+Truncating files
+----------------
+
+The operations covered by ``LANDLOCK_ACCESS_FS_WRITE_FILE`` and
+``LANDLOCK_ACCESS_FS_TRUNCATE`` both change the contents of a file and sometimes
+overlap in non-intuitive ways. It is recommended to always specify both of
+these together.
+
+A particularly surprising example is :manpage:`creat(2)`. The name suggests
+that this system call requires the rights to create and write files. However,
+it also requires the truncate right if an existing file under the same name is
+already present.
+
+It should also be noted that truncating files does not require the
+``LANDLOCK_ACCESS_FS_WRITE_FILE`` right. Apart from the :manpage:`truncate(2)`
+system call, this can also be done through :manpage:`open(2)` with the flags
+``O_RDONLY | O_TRUNC``.
+
+When opening a file, the availability of the ``LANDLOCK_ACCESS_FS_TRUNCATE``
+right is associated with the newly created file descriptor and will be used for
+subsequent truncation attempts using :manpage:`ftruncate(2)`. The behavior is
+similar to opening a file for reading or writing, where permissions are checked
+during :manpage:`open(2)`, but not during the subsequent :manpage:`read(2)` and
+:manpage:`write(2)` calls.
+
+As a consequence, it is possible to have multiple open file descriptors for the
+same file, where one grants the right to truncate the file and the other does
+not. It is also possible to pass such file descriptors between processes,
+keeping their Landlock properties, even when these processes do not have an
+enforced Landlock ruleset.
+
Compatibility
=============
@@ -398,6 +442,15 @@ Starting with the Landlock ABI version 2, it is now possible to securely
control renaming and linking thanks to the new ``LANDLOCK_ACCESS_FS_REFER``
access right.
+File truncation (ABI < 3)
+-------------------------
+
+File truncation could not be denied before the third Landlock ABI, so it is
+always allowed when using a kernel that only supports the first or second ABI.
+
+Starting with the Landlock ABI version 3, it is now possible to securely control
+truncation thanks to the new ``LANDLOCK_ACCESS_FS_TRUNCATE`` access right.
+
.. _kernel_support:
Kernel support
diff --git a/Documentation/userspace-api/media/Makefile b/Documentation/userspace-api/media/Makefile
index 00922aa7efde..3d8aaf5c253b 100644
--- a/Documentation/userspace-api/media/Makefile
+++ b/Documentation/userspace-api/media/Makefile
@@ -47,10 +47,11 @@ $(BUILDDIR)/lirc.h.rst: ${UAPI}/lirc.h ${PARSER} $(SRC_DIR)/lirc.h.rst.exception
# Media build rules
-.PHONY: all html epub xml latex
+.PHONY: all html texinfo epub xml latex
all: $(IMGDOT) $(BUILDDIR) ${TARGETS}
html: all
+texinfo: all
epub: all
xml: all
latex: $(IMGPDF) all
diff --git a/Documentation/userspace-api/media/cec/cec-pin-error-inj.rst b/Documentation/userspace-api/media/cec/cec-pin-error-inj.rst
index b0efce40471f..411d42a742f3 100644
--- a/Documentation/userspace-api/media/cec/cec-pin-error-inj.rst
+++ b/Documentation/userspace-api/media/cec/cec-pin-error-inj.rst
@@ -1,5 +1,7 @@
.. SPDX-License-Identifier: GFDL-1.1-no-invariants-or-later
+.. _cec_pin_error_inj:
+
CEC Pin Framework Error Injection
=================================
diff --git a/Documentation/userspace-api/media/drivers/aspeed-video.rst b/Documentation/userspace-api/media/drivers/aspeed-video.rst
new file mode 100644
index 000000000000..1b0cb1e3eba8
--- /dev/null
+++ b/Documentation/userspace-api/media/drivers/aspeed-video.rst
@@ -0,0 +1,65 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+.. include:: <isonum.txt>
+
+ASPEED video driver
+===================
+
+ASPEED Video Engine found on AST2400/2500/2600 SoC supports high performance
+video compressions with a wide range of video quality and compression ratio
+options. The adopted compressing algorithm is a modified JPEG algorithm.
+
+There are 2 types of compressions in this IP.
+
+* JPEG JFIF standard mode: for single frame and management compression
+* ASPEED proprietary mode: for multi-frame and differential compression.
+ Support 2-pass (high quality) video compression scheme (Patent pending by
+ ASPEED). Provide visually lossless video compression quality or to reduce
+ the network average loading under intranet KVM applications.
+
+VIDIOC_S_FMT can be used to choose which format you want. V4L2_PIX_FMT_JPEG
+stands for JPEG JFIF standard mode; V4L2_PIX_FMT_AJPG stands for ASPEED
+proprietary mode.
+
+More details on the ASPEED video hardware operations can be found in
+*chapter 6.2.16 KVM Video Driver* of SDK_User_Guide which available on
+AspeedTech-BMC/openbmc/releases.
+
+The ASPEED video driver implements the following driver-specific control:
+
+``V4L2_CID_ASPEED_HQ_MODE``
+---------------------------
+ Enable/Disable ASPEED's High quality mode. This is a private control
+ that can be used to enable high quality for aspeed proprietary mode.
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+ :widths: 1 4
+
+ * - ``(0)``
+ - ASPEED HQ mode is disabled.
+ * - ``(1)``
+ - ASPEED HQ mode is enabled.
+
+``V4L2_CID_ASPEED_HQ_JPEG_QUALITY``
+-----------------------------------
+ Define the quality of ASPEED's High quality mode. This is a private control
+ that can be used to decide compression quality if High quality mode enabled
+ . Higher the value, better the quality and bigger the size.
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+ :widths: 1 4
+
+ * - ``(1)``
+ - minimum
+ * - ``(12)``
+ - maximum
+ * - ``(1)``
+ - step
+ * - ``(1)``
+ - default
+
+**Copyright** |copy| 2022 ASPEED Technology Inc.
diff --git a/Documentation/userspace-api/media/drivers/index.rst b/Documentation/userspace-api/media/drivers/index.rst
index 32f82aed47d9..915dbf0f4db5 100644
--- a/Documentation/userspace-api/media/drivers/index.rst
+++ b/Documentation/userspace-api/media/drivers/index.rst
@@ -31,6 +31,7 @@ For more details see the file COPYING in the source distribution of Linux.
:maxdepth: 5
:numbered:
+ aspeed-video
ccs
cx2341x-uapi
dw100
@@ -38,4 +39,5 @@ For more details see the file COPYING in the source distribution of Linux.
max2175
meye-uapi
omap3isp-uapi
+ st-vgxy61
uvcvideo
diff --git a/Documentation/userspace-api/media/drivers/st-vgxy61.rst b/Documentation/userspace-api/media/drivers/st-vgxy61.rst
new file mode 100644
index 000000000000..d9e3b80e3a96
--- /dev/null
+++ b/Documentation/userspace-api/media/drivers/st-vgxy61.rst
@@ -0,0 +1,25 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+ST VGXY61 camera sensor driver
+==============================
+
+The ST VGXY61 driver implements the following controls:
+
+``V4L2_CID_HDR_SENSOR_MODE``
+-------------------------------
+ Change the sensor HDR mode. A HDR picture is obtained by merging two
+ captures of the same scene using two different exposure periods.
+
+.. flat-table::
+ :header-rows: 0
+ :stub-columns: 0
+ :widths: 1 4
+
+ * - HDR linearize
+ - The merger outputs a long exposure capture as long as it is not
+ saturated.
+ * - HDR substraction
+ - This involves subtracting the short exposure frame from the long
+ exposure frame.
+ * - No HDR
+ - This mode is used for standard dynamic range (SDR) exposures.
diff --git a/Documentation/userspace-api/media/dvb/fe_property_parameters.rst b/Documentation/userspace-api/media/dvb/fe_property_parameters.rst
index ecd84a8790a2..1717a0565fe8 100644
--- a/Documentation/userspace-api/media/dvb/fe_property_parameters.rst
+++ b/Documentation/userspace-api/media/dvb/fe_property_parameters.rst
@@ -89,16 +89,21 @@ ATSC (version 1) 8-VSB and 16-VSB.
DMTB 4-QAM, 16-QAM, 32-QAM, 64-QAM and 4-QAM-NR.
DVB-C Annex A/C 16-QAM, 32-QAM, 64-QAM and 256-QAM.
DVB-C Annex B 64-QAM.
+DVB-C2 QPSK, 16-QAM, 64-QAM, 256-QAM, 1024-QAM and 4096-QAM.
DVB-T QPSK, 16-QAM and 64-QAM.
DVB-T2 QPSK, 16-QAM, 64-QAM and 256-QAM.
DVB-S No need to set. It supports only QPSK.
DVB-S2 QPSK, 8-PSK, 16-APSK and 32-APSK.
+DVB-S2X 8-APSK-L, 16-APSK-L, 32-APSK-L, 64-APSK and 64-APSK-L.
ISDB-T QPSK, DQPSK, 16-QAM and 64-QAM.
ISDB-S 8-PSK, QPSK and BPSK.
======================= =======================================================
.. note::
+ As DVB-S2X specifies extensions to the DVB-S2 standard, the same
+ delivery system enum value is used (SYS_DVBS2).
+
Please notice that some of the above modulation types may not be
defined currently at the Kernel. The reason is simple: no driver
needed such definition yet.
@@ -854,9 +859,10 @@ The acceptable values are defined by :c:type:`fe_guard_interval`.
#. If ``DTV_GUARD_INTERVAL`` is set the ``GUARD_INTERVAL_AUTO`` the
hardware will try to find the correct guard interval (if capable) and
will use TMCC to fill in the missing parameters.
- #. Intervals ``GUARD_INTERVAL_1_128``, ``GUARD_INTERVAL_19_128``
- and ``GUARD_INTERVAL_19_256`` are used only for DVB-T2 at
- present.
+ #. Interval ``GUARD_INTERVAL_1_64`` is used only for DVB-C2.
+ #. Interval ``GUARD_INTERVAL_1_128`` is used for both DVB-C2 and DVB_T2.
+ #. Intervals ``GUARD_INTERVAL_19_128`` and ``GUARD_INTERVAL_19_256`` are
+ used only for DVB-T2.
#. Intervals ``GUARD_INTERVAL_PN420``, ``GUARD_INTERVAL_PN595`` and
``GUARD_INTERVAL_PN945`` are used only for DMTB at the present.
On such standard, only those intervals and ``GUARD_INTERVAL_AUTO``
@@ -916,14 +922,15 @@ The acceptable values are defined by :c:type:`fe_hierarchy`.
DTV_STREAM_ID
=============
-Used on DVB-S2, DVB-T2 and ISDB-S.
+Used on DVB-C2, DVB-S2, DVB-T2 and ISDB-S.
-DVB-S2, DVB-T2 and ISDB-S support the transmission of several streams on
-a single transport stream. This property enables the digital TV driver to
-handle substream filtering, when supported by the hardware. By default,
-substream filtering is disabled.
+DVB-C2, DVB-S2, DVB-T2 and ISDB-S support the transmission of several
+streams on a single transport stream. This property enables the digital
+TV driver to handle substream filtering, when supported by the hardware.
+By default, substream filtering is disabled.
-For DVB-S2 and DVB-T2, the valid substream id range is from 0 to 255.
+For DVB-C2, DVB-S2 and DVB-T2, the valid substream id range is from 0 to
+255.
For ISDB, the valid substream id range is from 1 to 65535.
diff --git a/Documentation/userspace-api/media/frontend.h.rst.exceptions b/Documentation/userspace-api/media/frontend.h.rst.exceptions
index 6283702c08c8..8b73fee11a79 100644
--- a/Documentation/userspace-api/media/frontend.h.rst.exceptions
+++ b/Documentation/userspace-api/media/frontend.h.rst.exceptions
@@ -86,6 +86,13 @@ ignore symbol APSK_16
ignore symbol APSK_32
ignore symbol DQPSK
ignore symbol QAM_4_NR
+ignore symbol QAM_1024
+ignore symbol QAM_4096
+ignore symbol APSK_8_L
+ignore symbol APSK_16_L
+ignore symbol APSK_32_L
+ignore symbol APSK_64
+ignore symbol APSK_64_L
ignore symbol SEC_VOLTAGE_13
ignore symbol SEC_VOLTAGE_18
@@ -119,6 +126,22 @@ ignore symbol FEC_AUTO
ignore symbol FEC_3_5
ignore symbol FEC_9_10
ignore symbol FEC_2_5
+ignore symbol FEC_1_3
+ignore symbol FEC_1_4
+ignore symbol FEC_5_9
+ignore symbol FEC_7_9
+ignore symbol FEC_8_15
+ignore symbol FEC_11_15
+ignore symbol FEC_13_18
+ignore symbol FEC_9_20
+ignore symbol FEC_11_20
+ignore symbol FEC_23_36
+ignore symbol FEC_25_36
+ignore symbol FEC_13_45
+ignore symbol FEC_26_45
+ignore symbol FEC_28_45
+ignore symbol FEC_32_45
+ignore symbol FEC_77_90
ignore symbol TRANSMISSION_MODE_AUTO
ignore symbol TRANSMISSION_MODE_1K
@@ -143,6 +166,7 @@ ignore symbol GUARD_INTERVAL_19_256
ignore symbol GUARD_INTERVAL_PN420
ignore symbol GUARD_INTERVAL_PN595
ignore symbol GUARD_INTERVAL_PN945
+ignore symbol GUARD_INTERVAL_1_64
ignore symbol HIERARCHY_NONE
ignore symbol HIERARCHY_AUTO
@@ -163,6 +187,9 @@ ignore symbol ROLLOFF_35
ignore symbol ROLLOFF_20
ignore symbol ROLLOFF_25
ignore symbol ROLLOFF_AUTO
+ignore symbol ROLLOFF_15
+ignore symbol ROLLOFF_10
+ignore symbol ROLLOFF_5
ignore symbol INVERSION_ON
ignore symbol INVERSION_OFF
@@ -187,6 +214,7 @@ ignore symbol SYS_DAB
ignore symbol SYS_DSS
ignore symbol SYS_CMMB
ignore symbol SYS_DVBH
+ignore symbol SYS_DVBC2
ignore symbol ATSCMH_SCCC_BLK_SEP
ignore symbol ATSCMH_SCCC_BLK_COMB
diff --git a/Documentation/userspace-api/media/v4l/buffer.rst b/Documentation/userspace-api/media/v4l/buffer.rst
index 4638ec64db00..04dec3e570ed 100644
--- a/Documentation/userspace-api/media/v4l/buffer.rst
+++ b/Documentation/userspace-api/media/v4l/buffer.rst
@@ -187,10 +187,8 @@ struct v4l2_buffer
on the negotiated data format and may change with each buffer for
compressed variable size data like JPEG images. Drivers must set
this field when ``type`` refers to a capture stream, applications
- when it refers to an output stream. If the application sets this
- to 0 for an output stream, then ``bytesused`` will be set to the
- size of the buffer (see the ``length`` field of this struct) by
- the driver. For multiplanar formats this field is ignored and the
+ when it refers to an output stream. For multiplanar formats this field
+ is ignored and the
``planes`` pointer is used instead.
* - __u32
- ``flags``
@@ -327,10 +325,7 @@ struct v4l2_plane
- ``bytesused``
- The number of bytes occupied by data in the plane (its payload).
Drivers must set this field when ``type`` refers to a capture
- stream, applications when it refers to an output stream. If the
- application sets this to 0 for an output stream, then
- ``bytesused`` will be set to the size of the plane (see the
- ``length`` field of this struct) by the driver.
+ stream, applications when it refers to an output stream.
.. note::
diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-camera.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-camera.rst
index 4c5061aa9cd4..daa4f40869f8 100644
--- a/Documentation/userspace-api/media/v4l/ext-ctrls-camera.rst
+++ b/Documentation/userspace-api/media/v4l/ext-ctrls-camera.rst
@@ -661,3 +661,11 @@ enum v4l2_scene_mode -
.. [#f1]
This control may be changed to a menu control in the future, if more
options are required.
+
+``V4L2_CID_HDR_SENSOR_MODE (menu)``
+ Change the sensor HDR mode. A HDR picture is obtained by merging two
+ captures of the same scene using two different exposure periods. HDR mode
+ describes the way these two captures are merged in the sensor.
+
+ As modes differ for each sensor, menu items are not standardized by this
+ control and are left to the programmer.
diff --git a/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst b/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst
index 0ff68cd8cf62..73cd99828010 100644
--- a/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst
+++ b/Documentation/userspace-api/media/v4l/pixfmt-reserved.rst
@@ -258,6 +258,23 @@ please make a proposal on the linux-media mailing list.
and it is used by various multimedia hardware blocks like GPU, display
controllers, ISP and video accelerators.
It contains four planes for progressive video.
+ * .. _V4L2-PIX-FMT-AJPG:
+
+ - ``V4L2_PIX_FMT_AJPG``
+ - 'AJPG'
+ - ASPEED JPEG format used by the aspeed-video driver on Aspeed platforms,
+ which is generally adapted for remote KVM.
+ On each frame compression, I will compare the new frame with previous
+ one to decide which macroblock's data is changed, and only the changed
+ macroblocks will be compressed.
+
+ The implementation is based on AST2600 A3 datasheet, revision 0.9, which
+ is not publicly available. Or you can reference Video stream data format
+ – ASPEED mode compression of SDK_User_Guide which available on
+ AspeedTech-BMC/openbmc/releases.
+
+ Decoder's implementation can be found here,
+ `aspeed_codec <https://github.com/AspeedTech-BMC/aspeed_codec/>`__
.. raw:: latex
\normalsize
diff --git a/Documentation/userspace-api/media/v4l/pixfmt-yuv-planar.rst b/Documentation/userspace-api/media/v4l/pixfmt-yuv-planar.rst
index 10b1feeb0b57..f1d5bb7b806d 100644
--- a/Documentation/userspace-api/media/v4l/pixfmt-yuv-planar.rst
+++ b/Documentation/userspace-api/media/v4l/pixfmt-yuv-planar.rst
@@ -273,7 +273,9 @@ of the luma plane.
.. _V4L2-PIX-FMT-NV12-16L16:
.. _V4L2-PIX-FMT-NV12-32L32:
.. _V4L2-PIX-FMT-NV12M-8L128:
+.. _V4L2-PIX-FMT-NV12-8L128:
.. _V4L2-PIX-FMT-NV12M-10BE-8L128:
+.. _V4L2-PIX-FMT-NV12-10BE-8L128:
.. _V4L2-PIX-FMT-MM21:
Tiled NV12
@@ -319,6 +321,9 @@ pixels in 2D 8x128 tiles, and stores tiles linearly in memory.
The image height must be aligned to a multiple of 128.
The layouts of the luma and chroma planes are identical.
+``V4L2_PIX_FMT_NV12_8L128`` is similar to ``V4L2_PIX_FMT_NV12M_8L128`` but stores
+two planes in one memory.
+
``V4L2_PIX_FMT_NV12M_10BE_8L128`` is similar to ``V4L2_PIX_FMT_NV12M`` but stores
10 bits pixels in 2D 8x128 tiles, and stores tiles linearly in memory.
the data is arranged in big endian order.
@@ -334,6 +339,9 @@ byte 2: Y1(bits 3-0) Y2(bits 9-6)
byte 3: Y2(bits 5-0) Y3(bits 9-8)
byte 4: Y3(bits 7-0)
+``V4L2_PIX_FMT_NV12_10BE_8L128`` is similar to ``V4L2_PIX_FMT_NV12M_10BE_8L128`` but stores
+two planes in one memory.
+
``V4L2_PIX_FMT_MM21`` store luma pixel in 16x32 tiles, and chroma pixels
in 16x16 tiles. The line stride must be aligned to a multiple of 16 and the
image height must be aligned to a multiple of 32. The number of luma and chroma
diff --git a/Documentation/userspace-api/media/v4l/subdev-formats.rst b/Documentation/userspace-api/media/v4l/subdev-formats.rst
index d21d532eee15..16ef3b41932e 100644
--- a/Documentation/userspace-api/media/v4l/subdev-formats.rst
+++ b/Documentation/userspace-api/media/v4l/subdev-formats.rst
@@ -6057,6 +6057,43 @@ the following codes.
- y\ :sub:`2`
- y\ :sub:`1`
- y\ :sub:`0`
+ * .. _MEDIA-BUS-FMT-Y16-1X16:
+
+ - MEDIA_BUS_FMT_Y16_1X16
+ - 0x202e
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ -
+ - y\ :sub:`15`
+ - y\ :sub:`14`
+ - y\ :sub:`13`
+ - y\ :sub:`12`
+ - y\ :sub:`11`
+ - y\ :sub:`10`
+ - y\ :sub:`9`
+ - y\ :sub:`8`
+ - y\ :sub:`7`
+ - y\ :sub:`6`
+ - y\ :sub:`5`
+ - y\ :sub:`4`
+ - y\ :sub:`3`
+ - y\ :sub:`2`
+ - y\ :sub:`1`
+ - y\ :sub:`0`
* .. _MEDIA-BUS-FMT-UYVY8-1X16:
- MEDIA_BUS_FMT_UYVY8_1X16
diff --git a/Documentation/virt/coco/tdx-guest.rst b/Documentation/virt/coco/tdx-guest.rst
new file mode 100644
index 000000000000..46e316db6bb4
--- /dev/null
+++ b/Documentation/virt/coco/tdx-guest.rst
@@ -0,0 +1,52 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===================================================================
+TDX Guest API Documentation
+===================================================================
+
+1. General description
+======================
+
+The TDX guest driver exposes IOCTL interfaces via the /dev/tdx-guest misc
+device to allow userspace to get certain TDX guest-specific details.
+
+2. API description
+==================
+
+In this section, for each supported IOCTL, the following information is
+provided along with a generic description.
+
+:Input parameters: Parameters passed to the IOCTL and related details.
+:Output: Details about output data and return value (with details about
+ the non common error values).
+
+2.1 TDX_CMD_GET_REPORT0
+-----------------------
+
+:Input parameters: struct tdx_report_req
+:Output: Upon successful execution, TDREPORT data is copied to
+ tdx_report_req.tdreport and return 0. Return -EINVAL for invalid
+ operands, -EIO on TDCALL failure or standard error number on other
+ common failures.
+
+The TDX_CMD_GET_REPORT0 IOCTL can be used by the attestation software to get
+the TDREPORT0 (a.k.a. TDREPORT subtype 0) from the TDX module using
+TDCALL[TDG.MR.REPORT].
+
+A subtype index is added at the end of this IOCTL CMD to uniquely identify the
+subtype-specific TDREPORT request. Although the subtype option is mentioned in
+the TDX Module v1.0 specification, section titled "TDG.MR.REPORT", it is not
+currently used, and it expects this value to be 0. So to keep the IOCTL
+implementation simple, the subtype option was not included as part of the input
+ABI. However, in the future, if the TDX Module supports more than one subtype,
+a new IOCTL CMD will be created to handle it. To keep the IOCTL naming
+consistent, a subtype index is added as part of the IOCTL CMD.
+
+Reference
+---------
+
+TDX reference material is collected here:
+
+https://www.intel.com/content/www/us/en/developer/articles/technical/intel-trust-domain-extensions.html
+
+The driver is based on TDX module specification v1.0 and TDX GHCI specification v1.0.
diff --git a/Documentation/virt/index.rst b/Documentation/virt/index.rst
index 2f1cffa87b1b..56e003ff28ff 100644
--- a/Documentation/virt/index.rst
+++ b/Documentation/virt/index.rst
@@ -14,6 +14,7 @@ Linux Virtualization Support
ne_overview
acrn/index
coco/sev-guest
+ coco/tdx-guest
hyperv/index
.. only:: html and subproject
diff --git a/Documentation/x86/boot.rst b/Documentation/x86/boot.rst
index 894a19897005..240d084782a6 100644
--- a/Documentation/x86/boot.rst
+++ b/Documentation/x86/boot.rst
@@ -455,6 +455,7 @@ Protocol: 2.00+
11 Minimal Linux Bootloader
<http://sebastian-plotz.blogspot.de>
12 OVMF UEFI virtualization stack
+ 13 barebox
== =======================================
Please contact <hpa@zytor.com> if you need a bootloader ID value assigned.
diff --git a/Documentation/x86/tdx.rst b/Documentation/x86/tdx.rst
index b8fa4329e1a5..dc8d9fd2c3f7 100644
--- a/Documentation/x86/tdx.rst
+++ b/Documentation/x86/tdx.rst
@@ -210,6 +210,49 @@ converted to shared on boot.
For coherent DMA allocation, the DMA buffer gets converted on the
allocation. Check force_dma_unencrypted() for details.
+Attestation
+===========
+
+Attestation is used to verify the TDX guest trustworthiness to other
+entities before provisioning secrets to the guest. For example, a key
+server may want to use attestation to verify that the guest is the
+desired one before releasing the encryption keys to mount the encrypted
+rootfs or a secondary drive.
+
+The TDX module records the state of the TDX guest in various stages of
+the guest boot process using the build time measurement register (MRTD)
+and runtime measurement registers (RTMR). Measurements related to the
+guest initial configuration and firmware image are recorded in the MRTD
+register. Measurements related to initial state, kernel image, firmware
+image, command line options, initrd, ACPI tables, etc are recorded in
+RTMR registers. For more details, as an example, please refer to TDX
+Virtual Firmware design specification, section titled "TD Measurement".
+At TDX guest runtime, the attestation process is used to attest to these
+measurements.
+
+The attestation process consists of two steps: TDREPORT generation and
+Quote generation.
+
+TDX guest uses TDCALL[TDG.MR.REPORT] to get the TDREPORT (TDREPORT_STRUCT)
+from the TDX module. TDREPORT is a fixed-size data structure generated by
+the TDX module which contains guest-specific information (such as build
+and boot measurements), platform security version, and the MAC to protect
+the integrity of the TDREPORT. A user-provided 64-Byte REPORTDATA is used
+as input and included in the TDREPORT. Typically it can be some nonce
+provided by attestation service so the TDREPORT can be verified uniquely.
+More details about the TDREPORT can be found in Intel TDX Module
+specification, section titled "TDG.MR.REPORT Leaf".
+
+After getting the TDREPORT, the second step of the attestation process
+is to send it to the Quoting Enclave (QE) to generate the Quote. TDREPORT
+by design can only be verified on the local platform as the MAC key is
+bound to the platform. To support remote verification of the TDREPORT,
+TDX leverages Intel SGX Quoting Enclave to verify the TDREPORT locally
+and convert it to a remotely verifiable Quote. Method of sending TDREPORT
+to QE is implementation specific. Attestation software can choose
+whatever communication channel available (i.e. vsock or TCP/IP) to
+send the TDREPORT to QE and receive the Quote.
+
References
==========
diff --git a/MAINTAINERS b/MAINTAINERS
index 77aa03cebd02..5a4526a171d6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -775,6 +775,24 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml
F: drivers/media/platform/sunxi/sun4i-csi/
+ALLWINNER A31 CSI DRIVER
+M: Yong Deng <yong.deng@magewell.com>
+M: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+L: linux-media@vger.kernel.org
+S: Maintained
+T: git git://linuxtv.org/media_tree.git
+F: Documentation/devicetree/bindings/media/allwinner,sun6i-a31-csi.yaml
+F: drivers/media/platform/sunxi/sun6i-csi/
+
+ALLWINNER A31 ISP DRIVER
+M: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+L: linux-media@vger.kernel.org
+S: Maintained
+T: git git://linuxtv.org/media_tree.git
+F: Documentation/devicetree/bindings/media/allwinner,sun6i-a31-isp.yaml
+F: drivers/staging/media/sunxi/sun6i-isp/
+F: drivers/staging/media/sunxi/sun6i-isp/uapi/sun6i-isp-config.h
+
ALLWINNER A31 MIPI CSI-2 BRIDGE DRIVER
M: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
L: linux-media@vger.kernel.org
@@ -1093,6 +1111,16 @@ S: Maintained
F: Documentation/hid/amd-sfh*
F: drivers/hid/amd-sfh-hid/
+AMLOGIC DDR PMU DRIVER
+M: Jiucheng Xu <jiucheng.xu@amlogic.com>
+L: linux-amlogic@lists.infradead.org
+S: Supported
+W: http://www.amlogic.com
+F: Documentation/admin-guide/perf/meson-ddr-pmu.rst
+F: Documentation/devicetree/bindings/perf/amlogic,g12-ddr-pmu.yaml
+F: drivers/perf/amlogic/
+F: include/soc/amlogic/
+
AMPHION VPU CODEC V4L2 DRIVER
M: Ming Qian <ming.qian@nxp.com>
M: Shijie Qin <shijie.qin@nxp.com>
@@ -1685,7 +1713,7 @@ M: Miquel Raynal <miquel.raynal@bootlin.com>
M: Naga Sureshkumar Relli <nagasure@xilinx.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-F: Documentation/devicetree/bindings/memory-controllers/arm,pl353-smc.yaml
+F: Documentation/devicetree/bindings/memory-controllers/arm,pl35x-smc.yaml
F: drivers/memory/pl353-smc.c
ARM PRIMECELL CLCD PL110 DRIVER
@@ -1897,6 +1925,7 @@ T: git https://github.com/AsahiLinux/linux.git
F: Documentation/devicetree/bindings/arm/apple.yaml
F: Documentation/devicetree/bindings/arm/apple/*
F: Documentation/devicetree/bindings/clock/apple,nco.yaml
+F: Documentation/devicetree/bindings/cpufreq/apple,cluster-cpufreq.yaml
F: Documentation/devicetree/bindings/dma/apple,admac.yaml
F: Documentation/devicetree/bindings/i2c/apple,i2c.yaml
F: Documentation/devicetree/bindings/interrupt-controller/apple,*
@@ -1913,6 +1942,7 @@ F: Documentation/devicetree/bindings/watchdog/apple,wdt.yaml
F: arch/arm64/boot/dts/apple/
F: drivers/bluetooth/hci_bcm4377.c
F: drivers/clk/clk-apple-nco.c
+F: drivers/cpufreq/apple-soc-cpufreq.c
F: drivers/dma/apple-admac.c
F: drivers/i2c/busses/i2c-pasemi-core.c
F: drivers/i2c/busses/i2c-pasemi-platform.c
@@ -2274,8 +2304,6 @@ F: drivers/clocksource/timer-ixp4xx.c
F: drivers/crypto/ixp4xx_crypto.c
F: drivers/gpio/gpio-ixp4xx.c
F: drivers/irqchip/irq-ixp4xx.c
-F: include/linux/irqchip/irq-ixp4xx.h
-F: include/linux/platform_data/timer-ixp4xx.h
ARM/INTEL KEEMBAY ARCHITECTURE
M: Paul J. Murphy <paul.j.murphy@intel.com>
@@ -2343,6 +2371,8 @@ M: Gregory Clement <gregory.clement@bootlin.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gclement/mvebu.git
+F: Documentation/devicetree/bindings/arm/marvell/marvell,dove.txt
+F: Documentation/devicetree/bindings/arm/marvell/marvell,orion5x.txt
F: Documentation/devicetree/bindings/soc/dove/
F: arch/arm/boot/dts/dove*
F: arch/arm/boot/dts/orion5x*
@@ -2359,6 +2389,7 @@ M: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/gclement/mvebu.git
+F: Documentation/devicetree/bindings/arm/marvell/
F: arch/arm/boot/dts/armada*
F: arch/arm/boot/dts/kirkwood*
F: arch/arm/configs/mvebu_*_defconfig
@@ -2623,7 +2654,7 @@ W: http://www.armlinux.org.uk/
ARM/QUALCOMM SUPPORT
M: Andy Gross <agross@kernel.org>
M: Bjorn Andersson <andersson@kernel.org>
-R: Konrad Dybcio <konrad.dybcio@somainline.org>
+R: Konrad Dybcio <konrad.dybcio@linaro.org>
L: linux-arm-msm@vger.kernel.org
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux.git
@@ -2694,7 +2725,7 @@ F: arch/arm/boot/dts/rtd*
F: arch/arm/mach-realtek/
F: arch/arm64/boot/dts/realtek/
-ARM/RENESAS ARCHITECTURE
+ARM/RISC-V/RENESAS ARCHITECTURE
M: Geert Uytterhoeven <geert+renesas@glider.be>
M: Magnus Damm <magnus.damm@gmail.com>
L: linux-renesas-soc@vger.kernel.org
@@ -2702,7 +2733,6 @@ S: Supported
Q: http://patchwork.kernel.org/project/linux-renesas-soc/list/
C: irc://irc.libera.chat/renesas-soc
T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel.git next
-F: Documentation/devicetree/bindings/arm/renesas.yaml
F: Documentation/devicetree/bindings/hwinfo/renesas,prr.yaml
F: Documentation/devicetree/bindings/soc/renesas/
F: arch/arm/boot/dts/emev2*
@@ -2716,6 +2746,7 @@ F: arch/arm/configs/shmobile_defconfig
F: arch/arm/include/debug/renesas-scif.S
F: arch/arm/mach-shmobile/
F: arch/arm64/boot/dts/renesas/
+F: arch/riscv/boot/dts/renesas/
F: drivers/soc/renesas/
F: include/linux/soc/renesas/
@@ -4944,6 +4975,12 @@ S: Maintained
F: drivers/platform/chrome/cros_usbpd_notify.c
F: include/linux/platform_data/cros_usbpd_notify.h
+CHROMEOS HPS DRIVER
+M: Dan Callaghan <dcallagh@chromium.org>
+R: Sami Kyöstilä <skyostil@chromium.org>
+S: Maintained
+F: drivers/platform/chrome/cros_hps_i2c.c
+
CHRONTEL CH7322 CEC DRIVER
M: Joe Tessler <jrt@google.com>
L: linux-media@vger.kernel.org
@@ -5302,7 +5339,7 @@ M: Johannes Weiner <hannes@cmpxchg.org>
M: Michal Hocko <mhocko@kernel.org>
M: Roman Gushchin <roman.gushchin@linux.dev>
M: Shakeel Butt <shakeelb@google.com>
-R: Muchun Song <songmuchun@bytedance.com>
+R: Muchun Song <muchun.song@linux.dev>
L: cgroups@vger.kernel.org
L: linux-mm@kvack.org
S: Maintained
@@ -5505,14 +5542,6 @@ M: Jaya Kumar <jayakumar.alsa@gmail.com>
S: Maintained
F: sound/pci/cs5535audio/
-CSI DRIVERS FOR ALLWINNER V3s
-M: Yong Deng <yong.deng@magewell.com>
-L: linux-media@vger.kernel.org
-S: Maintained
-T: git git://linuxtv.org/media_tree.git
-F: Documentation/devicetree/bindings/media/allwinner,sun6i-a31-csi.yaml
-F: drivers/media/platform/sunxi/sun6i-csi/
-
CTU CAN FD DRIVER
M: Pavel Pisa <pisa@cmp.felk.cvut.cz>
M: Ondrej Ille <ondrej.ille@gmail.com>
@@ -5857,6 +5886,13 @@ L: Dell.Client.Kernel@dell.com
S: Maintained
F: drivers/platform/x86/dell/dell-wmi-descriptor.c
+DELL WMI DDV DRIVER
+M: Armin Wolf <W_Armin@gmx.de>
+S: Maintained
+F: Documentation/ABI/testing/debugfs-dell-wmi-ddv
+F: Documentation/ABI/testing/sysfs-platform-dell-wmi-ddv
+F: drivers/platform/x86/dell/dell-wmi-ddv.c
+
DELL WMI SYSMAN DRIVER
M: Divya Bharathi <divya.bharathi@dell.com>
M: Prasanth Ksr <prasanth.ksr@dell.com>
@@ -6032,11 +6068,12 @@ F: include/net/devlink.h
F: include/uapi/linux/devlink.h
F: net/core/devlink.c
-DH ELECTRONICS IMX6 DHCOM BOARD SUPPORT
+DH ELECTRONICS IMX6 DHCOM/DHCOR BOARD SUPPORT
M: Christoph Niedermaier <cniedermaier@dh-electronics.com>
L: kernel@dh-electronics.com
S: Maintained
F: arch/arm/boot/dts/imx6*-dhcom-*
+F: arch/arm/boot/dts/imx6*-dhcor-*
DH ELECTRONICS STM32MP1 DHCOM/DHCOR BOARD SUPPORT
M: Marek Vasut <marex@denx.de>
@@ -6506,6 +6543,12 @@ S: Orphan / Obsolete
F: drivers/gpu/drm/i810/
F: include/uapi/drm/i810_drm.h
+DRM DRIVER FOR JADARD JD9365DA-H3 MIPI-DSI LCD PANELS
+M: Jagan Teki <jagan@edgeble.ai>
+S: Maintained
+F: Documentation/devicetree/bindings/display/panel/jadard,jd9365da-h3.yaml
+F: drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
+
DRM DRIVER FOR LOGICVC DISPLAY CONTROLLER
M: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
S: Supported
@@ -6695,10 +6738,13 @@ L: dri-devel@lists.freedesktop.org
S: Maintained
T: git git://anongit.freedesktop.org/drm/drm-misc
F: drivers/gpu/drm/drm_aperture.c
+F: drivers/gpu/drm/tiny/ofdrm.c
F: drivers/gpu/drm/tiny/simpledrm.c
F: drivers/video/aperture.c
+F: drivers/video/nomodeset.c
F: include/drm/drm_aperture.h
F: include/linux/aperture.h
+F: include/video/nomodeset.h
DRM DRIVER FOR SIS VIDEO CARDS
S: Orphan / Obsolete
@@ -6827,6 +6873,15 @@ F: include/drm/drm*
F: include/linux/vga*
F: include/uapi/drm/drm*
+DRM COMPUTE ACCELERATORS DRIVERS AND FRAMEWORK
+M: Oded Gabbay <ogabbay@kernel.org>
+L: dri-devel@lists.freedesktop.org
+S: Maintained
+C: irc://irc.oftc.net/dri-devel
+T: git https://git.kernel.org/pub/scm/linux/kernel/git/ogabbay/accel.git
+F: Documentation/accel/
+F: drivers/accel/
+
DRM DRIVERS FOR ALLWINNER A10
M: Maxime Ripard <mripard@kernel.org>
M: Chen-Yu Tsai <wens@csie.org>
@@ -7115,7 +7170,7 @@ F: drivers/gpu/drm/ttm/
F: include/drm/ttm/
DRM GPU SCHEDULER
-M: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
+M: Luben Tuikov <luben.tuikov@amd.com>
L: dri-devel@lists.freedesktop.org
S: Maintained
T: git git://anongit.freedesktop.org/drm/drm-misc
@@ -7363,9 +7418,9 @@ F: drivers/edac/thunderx_edac*
EDAC-CORE
M: Borislav Petkov <bp@alien8.de>
-M: Mauro Carvalho Chehab <mchehab@kernel.org>
M: Tony Luck <tony.luck@intel.com>
R: James Morse <james.morse@arm.com>
+R: Mauro Carvalho Chehab <mchehab@kernel.org>
R: Robert Richter <rric@kernel.org>
L: linux-edac@vger.kernel.org
S: Supported
@@ -7482,8 +7537,7 @@ S: Maintained
F: drivers/edac/pnd2_edac.[ch]
EDAC-QCOM
-M: Channagoud Kadabi <ckadabi@codeaurora.org>
-M: Venkata Narendra Kumar Gutta <vnkgutta@codeaurora.org>
+M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
L: linux-arm-msm@vger.kernel.org
L: linux-edac@vger.kernel.org
S: Maintained
@@ -7790,7 +7844,6 @@ F: Documentation/admin-guide/efi-stub.rst
F: arch/*/include/asm/efi.h
F: arch/*/kernel/efi.c
F: arch/arm/boot/compressed/efi-header.S
-F: arch/arm64/kernel/efi-entry.S
F: arch/x86/platform/efi/
F: drivers/firmware/efi/
F: include/linux/efi*.h
@@ -8750,6 +8803,7 @@ GPIO IR Transmitter
M: Sean Young <sean@mess.org>
L: linux-media@vger.kernel.org
S: Maintained
+F: Documentation/devicetree/bindings/leds/irled/gpio-ir-tx.yaml
F: drivers/media/rc/gpio-ir-tx.c
GPIO MOCKUP DRIVER
@@ -9173,6 +9227,13 @@ W: http://www.highpoint-tech.com
F: Documentation/scsi/hptiop.rst
F: drivers/scsi/hptiop.c
+HIMAX HX83112B TOUCHSCREEN SUPPORT
+M: Job Noorman <job@noorman.info>
+L: linux-input@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/input/touchscreen/himax,hx83112b.yaml
+F: drivers/input/touchscreen/himax_hx83112b.c
+
HIPPI
M: Jes Sorensen <jes@trained-monkey.org>
L: linux-hippi@sunsite.dk
@@ -9252,7 +9313,7 @@ F: drivers/misc/hisi_hikey_usb.c
HISILICON PMU DRIVER
M: Shaokun Zhang <zhangshaokun@hisilicon.com>
-M: Qi Liu <liuqi115@huawei.com>
+M: Jonathan Cameron <jonathan.cameron@huawei.com>
S: Supported
W: http://www.hisilicon.com
F: Documentation/admin-guide/perf/hisi-pcie-pmu.rst
@@ -9370,7 +9431,7 @@ F: drivers/net/wireless/intersil/hostap/
HP COMPAQ TC1100 TABLET WMI EXTRAS DRIVER
L: platform-driver-x86@vger.kernel.org
S: Orphan
-F: drivers/platform/x86/tc1100-wmi.c
+F: drivers/platform/x86/hp/tc1100-wmi.c
HPET: High Precision Event Timers driver
M: Clemens Ladisch <clemens@ladisch.de>
@@ -9448,7 +9509,7 @@ F: drivers/net/ethernet/huawei/hinic/
HUGETLB SUBSYSTEM
M: Mike Kravetz <mike.kravetz@oracle.com>
-M: Muchun Song <songmuchun@bytedance.com>
+M: Muchun Song <muchun.song@linux.dev>
L: linux-mm@kvack.org
S: Maintained
F: Documentation/ABI/testing/sysfs-kernel-mm-hugepages
@@ -10032,6 +10093,11 @@ F: Documentation/hwmon/ina2xx.rst
F: drivers/hwmon/ina2xx.c
F: include/linux/platform_data/ina2xx.h
+INDEX OF FURTHER KERNEL DOCUMENTATION
+M: Carlos Bilbao <carlos.bilbao@amd.com>
+S: Maintained
+F: Documentation/process/kernel-docs.rst
+
INDUSTRY PACK SUBSYSTEM (IPACK)
M: Samuel Iglesias Gonsalvez <siglesias@igalia.com>
M: Jens Taprogge <jens.taprogge@taprogge.org>
@@ -10061,6 +10127,7 @@ F: drivers/infiniband/
F: include/rdma/
F: include/trace/events/ib_mad.h
F: include/trace/events/ib_umad.h
+F: include/trace/misc/rdma.h
F: include/uapi/linux/if_infiniband.h
F: include/uapi/rdma/
F: samples/bpf/ibumad_kern.c
@@ -10234,6 +10301,7 @@ Q: http://patchwork.freedesktop.org/project/intel-gfx/
B: https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs
C: irc://irc.oftc.net/intel-gfx
T: git git://anongit.freedesktop.org/drm-intel
+F: Documentation/ABI/testing/sysfs-driver-intel-i915-hwmon
F: Documentation/gpu/i915.rst
F: drivers/gpu/drm/i915/
F: include/drm/i915*
@@ -10904,6 +10972,13 @@ F: drivers/isdn/Makefile
F: drivers/isdn/hardware/
F: drivers/isdn/mISDN/
+ISOFS FILESYSTEM
+M: Jan Kara <jack@suse.cz>
+L: linux-fsdevel@vger.kernel.org
+S: Maintained
+F: Documentation/filesystems/isofs.rst
+F: fs/isofs/
+
IT87 HARDWARE MONITORING DRIVER
M: Jean Delvare <jdelvare@suse.com>
L: linux-hwmon@vger.kernel.org
@@ -10965,9 +11040,9 @@ F: drivers/hwmon/jc42.c
JFS FILESYSTEM
M: Dave Kleikamp <shaggy@kernel.org>
L: jfs-discussion@lists.sourceforge.net
-S: Maintained
+S: Odd Fixes
W: http://jfs.sourceforge.net/
-T: git git://github.com/kleikamp/linux-shaggy.git
+T: git https://github.com/kleikamp/linux-shaggy.git
F: Documentation/admin-guide/jfs.rst
F: fs/jfs/
@@ -11140,11 +11215,18 @@ L: linux-nfs@vger.kernel.org
S: Supported
W: http://nfs.sourceforge.net/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux.git
+F: fs/exportfs/
F: fs/lockd/
F: fs/nfs_common/
F: fs/nfsd/
F: include/linux/lockd/
F: include/linux/sunrpc/
+F: include/trace/events/rpcgss.h
+F: include/trace/events/rpcrdma.h
+F: include/trace/events/sunrpc.h
+F: include/trace/misc/fs.h
+F: include/trace/misc/nfs.h
+F: include/trace/misc/sunrpc.h
F: include/uapi/linux/nfsd/
F: include/uapi/linux/sunrpc/
F: net/sunrpc/
@@ -11866,7 +11948,7 @@ M: Eric Piel <eric.piel@tremplin-utc.net>
S: Maintained
F: Documentation/misc-devices/lis3lv02d.rst
F: drivers/misc/lis3lv02d/
-F: drivers/platform/x86/hp_accel.c
+F: drivers/platform/x86/hp/hp_accel.c
LIST KUNIT TEST
M: David Gow <davidgow@google.com>
@@ -12021,6 +12103,21 @@ F: drivers/*/*loongarch*
F: Documentation/loongarch/
F: Documentation/translations/zh_CN/loongarch/
+LOONGSON-2 SOC SERIES GUTS DRIVER
+M: Yinbo Zhu <zhuyinbo@loongson.cn>
+L: loongarch@lists.linux.dev
+S: Maintained
+F: Documentation/devicetree/bindings/hwinfo/loongson,ls2k-chipid.yaml
+F: drivers/soc/loongson/loongson2_guts.c
+
+LOONGSON-2 SOC SERIES PINCTRL DRIVER
+M: zhanghongchen <zhanghongchen@loongson.cn>
+M: Yinbo Zhu <zhuyinbo@loongson.cn>
+L: linux-gpio@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/pinctrl/loongson,ls2k-pinctrl.yaml
+F: drivers/pinctrl/pinctrl-loongson2.c
+
LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI)
M: Sathya Prakash <sathya.prakash@broadcom.com>
M: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
@@ -12098,7 +12195,7 @@ M: Alexey Kodanev <alexey.kodanev@oracle.com>
L: ltp@lists.linux.it (subscribers-only)
S: Maintained
W: http://linux-test-project.github.io/
-T: git git://github.com/linux-test-project/ltp.git
+T: git https://github.com/linux-test-project/ltp.git
LYNX 28G SERDES PHY DRIVER
M: Ioana Ciornei <ioana.ciornei@nxp.com>
@@ -12733,7 +12830,7 @@ F: Documentation/admin-guide/media/imx7.rst
F: Documentation/devicetree/bindings/media/nxp,imx-mipi-csi2.yaml
F: Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml
F: drivers/media/platform/nxp/imx-mipi-csis.c
-F: drivers/staging/media/imx/imx7-media-csi.c
+F: drivers/media/platform/nxp/imx7-media-csi.c
MEDIA DRIVERS FOR HELENE
M: Abylay Ospan <aospan@netup.ru>
@@ -13393,7 +13490,7 @@ MESON NAND CONTROLLER DRIVER FOR AMLOGIC SOCS
M: Liang Yang <liang.yang@amlogic.com>
L: linux-mtd@lists.infradead.org
S: Maintained
-F: Documentation/devicetree/bindings/mtd/amlogic,meson-nand.txt
+F: Documentation/devicetree/bindings/mtd/amlogic,meson-nand.yaml
F: drivers/mtd/nand/raw/meson_*
MESON VIDEO DECODER DRIVER FOR AMLOGIC SOCS
@@ -13474,7 +13571,7 @@ M: Eugen Hristev <eugen.hristev@microchip.com>
L: linux-media@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/media/microchip,csi2dc.yaml
-F: drivers/media/platform/atmel/microchip-csi2dc.c
+F: drivers/media/platform/microchip/microchip-csi2dc.c
MICROCHIP ECC DRIVER
M: Tudor Ambarus <tudor.ambarus@microchip.com>
@@ -13501,8 +13598,10 @@ L: linux-media@vger.kernel.org
S: Supported
F: Documentation/devicetree/bindings/media/atmel,isc.yaml
F: Documentation/devicetree/bindings/media/microchip,xisc.yaml
-F: drivers/media/platform/atmel/atmel-isc*
-F: drivers/media/platform/atmel/atmel-sama*-isc*
+F: drivers/staging/media/deprecated/atmel/atmel-isc*
+F: drivers/staging/media/deprecated/atmel/atmel-sama*-isc*
+F: drivers/media/platform/microchip/microchip-isc*
+F: drivers/media/platform/microchip/microchip-sama*-isc*
F: include/linux/atmel-isc-media.h
MICROCHIP ISI DRIVER
@@ -15195,6 +15294,13 @@ S: Maintained
T: git git://linuxtv.org/media_tree.git
F: drivers/media/i2c/ov08d10.c
+OMNIVISION OV08X40 SENSOR DRIVER
+M: Jason Chen <jason.z.chen@intel.com>
+L: linux-media@vger.kernel.org
+S: Maintained
+T: git git://linuxtv.org/media_tree.git
+F: drivers/media/i2c/ov08x40.c
+
OMNIVISION OV13858 SENSOR DRIVER
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
@@ -15233,6 +15339,14 @@ S: Maintained
T: git git://linuxtv.org/media_tree.git
F: drivers/media/i2c/ov2740.c
+OMNIVISION OV4689 SENSOR DRIVER
+M: Mikhail Rudenko <mike.rudenko@gmail.com>
+L: linux-media@vger.kernel.org
+S: Maintained
+T: git git://linuxtv.org/media_tree.git
+F: Documentation/devicetree/bindings/media/i2c/ovti,ov4689.yaml
+F: drivers/media/i2c/ov5647.c
+
OMNIVISION OV5640 SENSOR DRIVER
M: Steve Longerbeam <slongerbeam@gmail.com>
L: linux-media@vger.kernel.org
@@ -15357,6 +15471,12 @@ S: Maintained
F: drivers/mtd/nand/onenand/
F: include/linux/mtd/onenand*.h
+ONEXPLAYER FAN DRIVER
+M: Joaquín Ignacio Aramendía <samsagax@gmail.com>
+L: linux-hwmon@vger.kernel.org
+S: Maintained
+F: drivers/hwmon/oxp-sensors.c
+
ONION OMEGA2+ BOARD
M: Harvey Hunt <harveyhuntnexus@gmail.com>
L: linux-mips@vger.kernel.org
@@ -16316,7 +16436,7 @@ M: Sean Wang <sean.wang@kernel.org>
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: Documentation/devicetree/bindings/pinctrl/mediatek,mt65xx-pinctrl.yaml
-F: Documentation/devicetree/bindings/pinctrl/mediatek,mt6797-pinctrl.yaml
+F: Documentation/devicetree/bindings/pinctrl/mediatek,mt6779-pinctrl.yaml
F: Documentation/devicetree/bindings/pinctrl/mediatek,mt7622-pinctrl.yaml
F: Documentation/devicetree/bindings/pinctrl/mediatek,mt8183-pinctrl.yaml
F: drivers/pinctrl/mediatek/
@@ -16389,13 +16509,6 @@ S: Supported
F: Documentation/devicetree/bindings/input/pine64,pinephone-keyboard.yaml
F: drivers/input/keyboard/pinephone-keyboard.c
-PKTCDVD DRIVER
-M: linux-block@vger.kernel.org
-S: Orphan
-F: drivers/block/pktcdvd.c
-F: include/linux/pktcdvd.h
-F: include/uapi/linux/pktcdvd.h
-
PLANTOWER PMS7003 AIR POLLUTION SENSOR DRIVER
M: Tomasz Duszynski <tduszyns@gmail.com>
S: Maintained
@@ -16673,10 +16786,10 @@ F: net/psample
PSTORE FILESYSTEM
M: Kees Cook <keescook@chromium.org>
-M: Anton Vorontsov <anton@enomsg.org>
-M: Colin Cross <ccross@android.com>
-M: Tony Luck <tony.luck@intel.com>
-S: Maintained
+R: Tony Luck <tony.luck@intel.com>
+R: Guilherme G. Piccoli <gpiccoli@igalia.com>
+L: linux-hardening@vger.kernel.org
+S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/pstore
F: Documentation/admin-guide/ramoops.rst
F: Documentation/admin-guide/pstore-blk.rst
@@ -16723,7 +16836,6 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
-F: Documentation/admin-guide/media/pulse8-cec.rst
F: drivers/media/cec/usb/pulse8/
PURELIFI PLFXLC DRIVER
@@ -16754,6 +16866,7 @@ PWM IR Transmitter
M: Sean Young <sean@mess.org>
L: linux-media@vger.kernel.org
S: Maintained
+F: Documentation/devicetree/bindings/leds/irled/pwm-ir-tx.yaml
F: drivers/media/rc/pwm-ir-tx.c
PWM SUBSYSTEM
@@ -16818,7 +16931,7 @@ M: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
M: Banajit Goswami <bgoswami@quicinc.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
S: Supported
-F: Documentation/devicetree/bindings/soc/qcom/qcom,apr.yaml
+F: Documentation/devicetree/bindings/soc/qcom/qcom,apr*
F: Documentation/devicetree/bindings/sound/qcom,*
F: drivers/soc/qcom/apr.c
F: include/dt-bindings/sound/qcom,wcd9335.h
@@ -17176,7 +17289,8 @@ F: Documentation/devicetree/bindings/thermal/qcom-tsens.yaml
F: drivers/thermal/qcom/
QUALCOMM VENUS VIDEO ACCELERATOR DRIVER
-M: Stanimir Varbanov <stanimir.varbanov@linaro.org>
+M: Stanimir Varbanov <stanimir.k.varbanov@gmail.com>
+M: Vikash Garodia <quic_vgarodia@quicinc.com>
L: linux-media@vger.kernel.org
L: linux-arm-msm@vger.kernel.org
S: Maintained
@@ -18509,6 +18623,7 @@ K: \bsecure_computing
K: \bTIF_SECCOMP\b
SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) Broadcom BRCMSTB DRIVER
+M: Kamal Dasu <kdasu.kdev@gmail.com>
M: Al Cooper <alcooperx@gmail.com>
R: Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
L: linux-mmc@vger.kernel.org
@@ -18519,6 +18634,7 @@ SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) DRIVER
M: Adrian Hunter <adrian.hunter@intel.com>
L: linux-mmc@vger.kernel.org
S: Supported
+F: Documentation/devicetree/bindings/mmc/sdhci-common.yaml
F: drivers/mmc/host/sdhci*
SECURE DIGITAL HOST CONTROLLER INTERFACE (SDHCI) MICROCHIP DRIVER
@@ -18928,7 +19044,7 @@ F: drivers/video/fbdev/sis/
F: include/video/sisfb.h
SIS I2C TOUCHSCREEN DRIVER
-M: Mika Penttilä <mika.penttila@nextfour.com>
+M: Mika Penttilä <mpenttil@redhat.com>
L: linux-input@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/input/touchscreen/sis_i2c.txt
@@ -19079,7 +19195,7 @@ M: Masahisa Kojima <masahisa.kojima@linaro.org>
M: Jassi Brar <jaswinder.singh@linaro.org>
L: linux-spi@vger.kernel.org
S: Maintained
-F: Documentation/devicetree/bindings/spi/spi-synquacer.txt
+F: Documentation/devicetree/bindings/spi/socionext,synquacer-spi.yaml
F: drivers/spi/spi-synquacer.c
SOCIONEXT SYNQUACER I2C DRIVER
@@ -19226,7 +19342,7 @@ M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
-F: Documentation/devicetree/bindings/media/i2c/imx290.txt
+F: Documentation/devicetree/bindings/media/i2c/sony,imx290.yaml
F: drivers/media/i2c/imx290.c
SONY IMX319 SENSOR DRIVER
@@ -19375,6 +19491,11 @@ W: https://linuxtv.org
Q: http://patchwork.linuxtv.org/project/linux-media/list/
F: drivers/media/dvb-frontends/sp2*
+SPANISH DOCUMENTATION
+M: Carlos Bilbao <carlos.bilbao@amd.com>
+S: Maintained
+F: Documentation/translations/sp_SP/
+
SPARC + UltraSPARC (sparc/sparc64)
M: "David S. Miller" <davem@davemloft.net>
L: sparclinux@vger.kernel.org
@@ -19518,7 +19639,7 @@ M: Sylvain Petinot <sylvain.petinot@foss.st.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
-F: Documentation/devicetree/bindings/media/i2c/st,st-mipid02.txt
+F: Documentation/devicetree/bindings/media/i2c/st,st-mipid02.yaml
F: drivers/media/i2c/st-mipid02.c
ST STM32 I2C/SMBUS DRIVER
@@ -19541,6 +19662,16 @@ S: Maintained
F: Documentation/hwmon/stpddc60.rst
F: drivers/hwmon/pmbus/stpddc60.c
+ST VGXY61 DRIVER
+M: Benjamin Mugnier <benjamin.mugnier@foss.st.com>
+M: Sylvain Petinot <sylvain.petinot@foss.st.com>
+L: linux-media@vger.kernel.org
+S: Maintained
+T: git git://linuxtv.org/media_tree.git
+F: Documentation/devicetree/bindings/media/i2c/st,st-vgxy61.yaml
+F: Documentation/userspace-api/media/drivers/st-vgxy61.rst
+F: drivers/media/i2c/st-vgxy61.c
+
ST VL53L0X ToF RANGER(I2C) IIO DRIVER
M: Song Qiang <songqiang1304521@gmail.com>
L: linux-iio@vger.kernel.org
@@ -19556,6 +19687,7 @@ S: Supported
F: Documentation/process/stable-kernel-rules.rst
STAGING - ATOMISP DRIVER
+M: Hans de Goede <hdegoede@redhat.com>
M: Mauro Carvalho Chehab <mchehab@kernel.org>
R: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
@@ -19765,6 +19897,13 @@ W: https://sunplus.atlassian.net/wiki/spaces/doc/overview
F: Documentation/devicetree/bindings/net/sunplus,sp7021-emac.yaml
F: drivers/net/ethernet/sunplus/
+SUNPLUS MMC DRIVER
+M: Tony Huang <tonyhuang.sunplus@gmail.com>
+M: Li-hao Kuo <lhjeff911@gmail.com>
+S: Maintained
+F: Documentation/devicetree/bindings/mmc/sunplus,mmc.yaml
+F: drivers/mmc/host/sunplus-mmc.c
+
SUNPLUS OCOTP DRIVER
M: Vincent Shih <vincent.sunplus@gmail.com>
S: Maintained
@@ -20016,6 +20155,7 @@ F: drivers/clk/clk-sc[mp]i.c
F: drivers/cpufreq/sc[mp]i-cpufreq.c
F: drivers/firmware/arm_scmi/
F: drivers/firmware/arm_scpi.c
+F: drivers/powercap/arm_scmi_powercap.c
F: drivers/regulator/scmi-regulator.c
F: drivers/reset/reset-scmi.c
F: include/linux/sc[mp]i_protocol.h
@@ -20350,7 +20490,7 @@ M: Chris Zankel <chris@zankel.net>
M: Max Filippov <jcmvbkbc@gmail.com>
L: linux-xtensa@linux-xtensa.org
S: Maintained
-T: git git://github.com/czankel/xtensa-linux.git
+T: git https://github.com/jcmvbkbc/linux-xtensa.git
F: arch/xtensa/
F: drivers/irqchip/irq-xtensa-*
@@ -21763,6 +21903,12 @@ F: include/linux/virtio*.h
F: include/uapi/linux/virtio_*.h
F: tools/virtio/
+VISL VIRTUAL STATELESS DECODER DRIVER
+M: Daniel Almeida <daniel.almeida@collabora.com>
+L: linux-media@vger.kernel.org
+S: Supported
+F: drivers/media/test-drivers/visl
+
IFCVF VIRTIO DATA PATH ACCELERATOR
R: Zhu Lingshan <lingshan.zhu@intel.com>
F: drivers/vdpa/ifcvf/
diff --git a/Makefile b/Makefile
index 0992f827888d..bb60045526c4 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
VERSION = 6
PATCHLEVEL = 1
SUBLEVEL = 0
-EXTRAVERSION = -rc8
+EXTRAVERSION =
NAME = Hurr durr I'ma ninja sloth
# *DOCUMENTATION*
@@ -562,7 +562,7 @@ KBUILD_AFLAGS := -D__ASSEMBLY__ -fno-PIE
KBUILD_CFLAGS := -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs \
-fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE \
-Werror=implicit-function-declaration -Werror=implicit-int \
- -Werror=return-type -Wno-format-security \
+ -Werror=return-type -Wno-format-security -funsigned-char \
-std=gnu11
KBUILD_CPPFLAGS := -D__KERNEL__
KBUILD_RUSTFLAGS := $(rust_common_flags) \
@@ -966,8 +966,10 @@ LDFLAGS_vmlinux += --gc-sections
endif
ifdef CONFIG_SHADOW_CALL_STACK
+ifndef CONFIG_DYNAMIC_SCS
CC_FLAGS_SCS := -fsanitize=shadow-call-stack
KBUILD_CFLAGS += $(CC_FLAGS_SCS)
+endif
export CC_FLAGS_SCS
endif
@@ -1785,7 +1787,7 @@ $(help-board-dirs): help-%:
# Documentation targets
# ---------------------------------------------------------------------------
DOC_TARGETS := xmldocs latexdocs pdfdocs htmldocs epubdocs cleandocs \
- linkcheckdocs dochelp refcheckdocs
+ linkcheckdocs dochelp refcheckdocs texinfodocs infodocs
PHONY += $(DOC_TARGETS)
$(DOC_TARGETS):
$(Q)$(MAKE) $(build)=Documentation $@
@@ -2001,7 +2003,9 @@ clean: $(clean-dirs)
@find $(or $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
\( -name '*.[aios]' -o -name '*.rsi' -o -name '*.ko' -o -name '.*.cmd' \
-o -name '*.ko.*' \
- -o -name '*.dtb' -o -name '*.dtbo' -o -name '*.dtb.S' -o -name '*.dt.yaml' \
+ -o -name '*.dtb' -o -name '*.dtbo' \
+ -o -name '*.dtb.S' -o -name '*.dtbo.S' \
+ -o -name '*.dt.yaml' \
-o -name '*.dwo' -o -name '*.lst' \
-o -name '*.su' -o -name '*.mod' -o -name '*.usyms' \
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
diff --git a/arch/Kconfig b/arch/Kconfig
index 8f138e580d1a..2d0e7099eb3f 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -468,6 +468,9 @@ config ARCH_WANT_IRQS_OFF_ACTIVATE_MM
config ARCH_HAVE_NMI_SAFE_CMPXCHG
bool
+config ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
+ bool
+
config HAVE_ALIGNED_STRUCT_PAGE
bool
help
@@ -651,6 +654,13 @@ config SHADOW_CALL_STACK
reading and writing arbitrary memory may be able to locate them
and hijack control flow by modifying the stacks.
+config DYNAMIC_SCS
+ bool
+ help
+ Set by the arch code if it relies on code patching to insert the
+ shadow call stack push and pop instructions rather than on the
+ compiler.
+
config LTO
bool
help
diff --git a/arch/alpha/include/asm/elf.h b/arch/alpha/include/asm/elf.h
index 8049997fa372..e6da23f1da83 100644
--- a/arch/alpha/include/asm/elf.h
+++ b/arch/alpha/include/asm/elf.h
@@ -120,12 +120,6 @@ extern int dump_elf_task(elf_greg_t *dest, struct task_struct *task);
#define ELF_CORE_COPY_TASK_REGS(TASK, DEST) \
dump_elf_task(*(DEST), TASK)
-/* Similar, but for the FP registers. */
-
-extern int dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task);
-#define ELF_CORE_COPY_FPREGS(TASK, DEST) \
- dump_elf_task_fp(*(DEST), TASK)
-
/* This yields a mask that user programs can use to figure out what
instruction set this CPU supports. This is trivial on Alpha,
but not so on other machines. */
diff --git a/arch/alpha/include/asm/ptrace.h b/arch/alpha/include/asm/ptrace.h
index df5f317ab3fc..3557ce64ed21 100644
--- a/arch/alpha/include/asm/ptrace.h
+++ b/arch/alpha/include/asm/ptrace.h
@@ -16,7 +16,6 @@
#define current_pt_regs() \
((struct pt_regs *) ((char *)current_thread_info() + 2*PAGE_SIZE) - 1)
-#define signal_pt_regs current_pt_regs
#define force_successful_syscall_return() (current_pt_regs()->r0 = 0)
diff --git a/arch/alpha/include/asm/thread_info.h b/arch/alpha/include/asm/thread_info.h
index fdc485d7787a..082631465074 100644
--- a/arch/alpha/include/asm/thread_info.h
+++ b/arch/alpha/include/asm/thread_info.h
@@ -75,11 +75,7 @@ register struct thread_info *__current_thread_info __asm__("$8");
/* Work to do on interrupt/exception return. */
#define _TIF_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \
- _TIF_NOTIFY_RESUME)
-
-/* Work to do on any return to userspace. */
-#define _TIF_ALLWORK_MASK (_TIF_WORK_MASK \
- | _TIF_SYSCALL_TRACE)
+ _TIF_NOTIFY_RESUME | _TIF_NOTIFY_SIGNAL)
#define TS_UAC_NOPRINT 0x0001 /* ! Preserve the following three */
#define TS_UAC_NOFIX 0x0002 /* ! flags as they match */
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index e227f3a29a43..a6207c47f089 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -469,13 +469,16 @@ entSys:
#ifdef CONFIG_AUDITSYSCALL
lda $6, _TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT
and $3, $6, $3
-#endif
bne $3, strace
+#else
+ blbs $3, strace /* check for SYSCALL_TRACE in disguise */
+#endif
beq $4, 1f
ldq $27, 0($5)
1: jsr $26, ($27), sys_ni_syscall
ldgp $gp, 0($26)
blt $0, $syscall_error /* the call failed */
+$ret_success:
stq $0, 0($sp)
stq $31, 72($sp) /* a3=0 => no error */
@@ -525,11 +528,6 @@ $syscall_error:
stq $1, 72($sp) /* a3 for return */
br ret_from_sys_call
-$ret_success:
- stq $0, 0($sp)
- stq $31, 72($sp) /* a3=0 => no error */
- br ret_from_sys_call
-
/*
* Do all cleanup when returning from all interrupts and system calls.
*
@@ -598,8 +596,8 @@ ret_from_straced:
/* check return.. */
blt $0, $strace_error /* the call failed */
- stq $31, 72($sp) /* a3=0 => no error */
$strace_success:
+ stq $31, 72($sp) /* a3=0 => no error */
stq $0, 0($sp) /* save return value */
DO_SWITCH_STACK
@@ -768,7 +766,7 @@ alpha_switch_to:
.align 4
.ent ret_from_fork
ret_from_fork:
- lda $26, ret_from_sys_call
+ lda $26, ret_to_user
mov $17, $16
jmp $31, schedule_tail
.end ret_from_fork
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index dbf1bc5e2ad2..65fdae9e48f3 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -333,14 +333,12 @@ dump_elf_task(elf_greg_t *dest, struct task_struct *task)
}
EXPORT_SYMBOL(dump_elf_task);
-int
-dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task)
+int elf_core_copy_task_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
{
- struct switch_stack *sw = (struct switch_stack *)task_pt_regs(task) - 1;
- memcpy(dest, sw->fp, 32 * 8);
+ struct switch_stack *sw = (struct switch_stack *)task_pt_regs(t) - 1;
+ memcpy(fpu, sw->fp, 32 * 8);
return 1;
}
-EXPORT_SYMBOL(dump_elf_task_fp);
/*
* Return saved PC of a blocked thread. This assumes the frame
diff --git a/arch/arc/kernel/ptrace.c b/arch/arc/kernel/ptrace.c
index da7542cea0d8..2abdcd9b09e8 100644
--- a/arch/arc/kernel/ptrace.c
+++ b/arch/arc/kernel/ptrace.c
@@ -185,7 +185,7 @@ static int genregs_set(struct task_struct *target,
#define REG_IGNORE_ONE(LOC) \
if (!ret) \
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, \
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, \
offsetof(struct user_regs_struct, LOC), \
offsetof(struct user_regs_struct, LOC) + 4);
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index a08c9d092a33..65d0daf63262 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -17,6 +17,7 @@ config ARM
select ARCH_HAS_PTE_SPECIAL if ARM_LPAE
select ARCH_HAS_SETUP_DMA_OPS
select ARCH_HAS_SET_MEMORY
+ select ARCH_STACKWALK
select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL
select ARCH_HAS_STRICT_MODULE_RWX if MMU
select ARCH_HAS_SYNC_DMA_FOR_DEVICE
@@ -27,6 +28,7 @@ config ARM
select ARCH_HAVE_NMI_SAFE_CMPXCHG if CPU_V7 || CPU_V7M || CPU_V6K
select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_KEEP_MEMBLOCK
+ select ARCH_HAS_UBSAN_SANITIZE_ALL
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT if CPU_V7
@@ -95,6 +97,7 @@ config ARM
select HAVE_EXIT_THREAD
select HAVE_FAST_GUP if ARM_LPAE
select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL
+ select HAVE_FUNCTION_ERROR_INJECTION
select HAVE_FUNCTION_GRAPH_TRACER
select HAVE_FUNCTION_TRACER if !XIP_KERNEL
select HAVE_GCC_PLUGINS
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index c846119c448f..4067f5169144 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -60,47 +60,54 @@ endif
KBUILD_CFLAGS += $(call cc-option,-fno-ipa-sra)
# This selects which instruction set is used.
+arch-$(CONFIG_CPU_32v7M) :=-march=armv7-m
+arch-$(CONFIG_CPU_32v7) :=-march=armv7-a
+arch-$(CONFIG_CPU_32v6) :=-march=armv6
+# Only override the compiler option if ARMv6. The ARMv6K extensions are
+# always available in ARMv7
+ifeq ($(CONFIG_CPU_32v6),y)
+arch-$(CONFIG_CPU_32v6K) :=-march=armv6k
+endif
+arch-$(CONFIG_CPU_32v5) :=-march=armv5te
+arch-$(CONFIG_CPU_32v4T) :=-march=armv4t
+arch-$(CONFIG_CPU_32v4) :=-march=armv4
+arch-$(CONFIG_CPU_32v3) :=-march=armv3m
+
# Note that GCC does not numerically define an architecture version
# macro, but instead defines a whole series of macros which makes
# testing for a specific architecture or later rather impossible.
-arch-$(CONFIG_CPU_32v7M) =-D__LINUX_ARM_ARCH__=7 -march=armv7-m
-arch-$(CONFIG_CPU_32v7) =-D__LINUX_ARM_ARCH__=7 -march=armv7-a
-arch-$(CONFIG_CPU_32v6) =-D__LINUX_ARM_ARCH__=6 -march=armv6
+cpp-$(CONFIG_CPU_32v7M) :=-D__LINUX_ARM_ARCH__=7
+cpp-$(CONFIG_CPU_32v7) :=-D__LINUX_ARM_ARCH__=7
+cpp-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6
# Only override the compiler option if ARMv6. The ARMv6K extensions are
# always available in ARMv7
ifeq ($(CONFIG_CPU_32v6),y)
-arch-$(CONFIG_CPU_32v6K) =-D__LINUX_ARM_ARCH__=6 -march=armv6k
+cpp-$(CONFIG_CPU_32v6K) :=-D__LINUX_ARM_ARCH__=6
endif
-arch-$(CONFIG_CPU_32v5) =-D__LINUX_ARM_ARCH__=5 -march=armv5te
-arch-$(CONFIG_CPU_32v4T) =-D__LINUX_ARM_ARCH__=4 -march=armv4t
-arch-$(CONFIG_CPU_32v4) =-D__LINUX_ARM_ARCH__=4 -march=armv4
-arch-$(CONFIG_CPU_32v3) =-D__LINUX_ARM_ARCH__=3 -march=armv3m
-
-# Evaluate arch cc-option calls now
-arch-y := $(arch-y)
+cpp-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5
+cpp-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4
+cpp-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4
+cpp-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3
# This selects how we optimise for the processor.
-tune-$(CONFIG_CPU_ARM7TDMI) =-mtune=arm7tdmi
-tune-$(CONFIG_CPU_ARM720T) =-mtune=arm7tdmi
-tune-$(CONFIG_CPU_ARM740T) =-mtune=arm7tdmi
-tune-$(CONFIG_CPU_ARM9TDMI) =-mtune=arm9tdmi
-tune-$(CONFIG_CPU_ARM940T) =-mtune=arm9tdmi
-tune-$(CONFIG_CPU_ARM946E) =-mtune=arm9e
-tune-$(CONFIG_CPU_ARM920T) =-mtune=arm9tdmi
-tune-$(CONFIG_CPU_ARM922T) =-mtune=arm9tdmi
-tune-$(CONFIG_CPU_ARM925T) =-mtune=arm9tdmi
-tune-$(CONFIG_CPU_ARM926T) =-mtune=arm9tdmi
-tune-$(CONFIG_CPU_FA526) =-mtune=arm9tdmi
-tune-$(CONFIG_CPU_SA110) =-mtune=strongarm110
-tune-$(CONFIG_CPU_SA1100) =-mtune=strongarm1100
-tune-$(CONFIG_CPU_XSCALE) =-mtune=xscale
-tune-$(CONFIG_CPU_XSC3) =-mtune=xscale
-tune-$(CONFIG_CPU_FEROCEON) =-mtune=xscale
-tune-$(CONFIG_CPU_V6) =-mtune=arm1136j-s
-tune-$(CONFIG_CPU_V6K) =-mtune=arm1136j-s
-
-# Evaluate tune cc-option calls now
-tune-y := $(tune-y)
+tune-$(CONFIG_CPU_ARM7TDMI) :=-mtune=arm7tdmi
+tune-$(CONFIG_CPU_ARM720T) :=-mtune=arm7tdmi
+tune-$(CONFIG_CPU_ARM740T) :=-mtune=arm7tdmi
+tune-$(CONFIG_CPU_ARM9TDMI) :=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_ARM940T) :=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_ARM946E) :=-mtune=arm9e
+tune-$(CONFIG_CPU_ARM920T) :=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_ARM922T) :=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_ARM925T) :=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_ARM926T) :=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_FA526) :=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_SA110) :=-mtune=strongarm110
+tune-$(CONFIG_CPU_SA1100) :=-mtune=strongarm1100
+tune-$(CONFIG_CPU_XSCALE) :=-mtune=xscale
+tune-$(CONFIG_CPU_XSC3) :=-mtune=xscale
+tune-$(CONFIG_CPU_FEROCEON) :=-mtune=xscale
+tune-$(CONFIG_CPU_V6) :=-mtune=arm1136j-s
+tune-$(CONFIG_CPU_V6K) :=-mtune=arm1136j-s
ifeq ($(CONFIG_AEABI),y)
CFLAGS_ABI :=-mabi=aapcs-linux -mfpu=vfp
@@ -117,23 +124,25 @@ CFLAGS_ABI += -meabi gnu
endif
ifeq ($(CONFIG_CURRENT_POINTER_IN_TPIDRURO),y)
-CFLAGS_ABI += -mtp=cp15
+KBUILD_CFLAGS += -mtp=cp15
endif
# Accept old syntax despite ".syntax unified"
AFLAGS_NOWARN :=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W)
ifeq ($(CONFIG_THUMB2_KERNEL),y)
-CFLAGS_ISA :=-mthumb -Wa,-mimplicit-it=always $(AFLAGS_NOWARN)
-AFLAGS_ISA :=$(CFLAGS_ISA) -Wa$(comma)-mthumb
+CFLAGS_ISA :=-Wa,-mimplicit-it=always $(AFLAGS_NOWARN)
+AFLAGS_ISA :=$(CFLAGS_ISA) -Wa$(comma)-mthumb -D__thumb2__=2
+CFLAGS_ISA +=-mthumb
else
CFLAGS_ISA :=$(call cc-option,-marm,) $(AFLAGS_NOWARN)
AFLAGS_ISA :=$(CFLAGS_ISA)
endif
# Need -Uarm for gcc < 3.x
+KBUILD_CPPFLAGS +=$(cpp-y)
KBUILD_CFLAGS +=$(CFLAGS_ABI) $(CFLAGS_ISA) $(arch-y) $(tune-y) $(call cc-option,-mshort-load-bytes,$(call cc-option,-malignment-traps,)) -msoft-float -Uarm
-KBUILD_AFLAGS +=$(CFLAGS_ABI) $(AFLAGS_ISA) $(arch-y) $(tune-y) -include asm/unified.h -msoft-float
+KBUILD_AFLAGS +=$(CFLAGS_ABI) $(AFLAGS_ISA) -Wa,$(arch-y) $(tune-y) -include asm/unified.h -msoft-float
CHECKFLAGS += -D__arm__
diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile
index 41bcbb460fac..8c63f0a26f56 100644
--- a/arch/arm/boot/compressed/Makefile
+++ b/arch/arm/boot/compressed/Makefile
@@ -27,6 +27,7 @@ KASAN_SANITIZE := n
# Prevents link failures: __sanitizer_cov_trace_pc() is not linked in.
KCOV_INSTRUMENT := n
+UBSAN_SANITIZE := n
#
# Architecture dependencies
@@ -163,4 +164,3 @@ $(obj)/piggy_data: $(obj)/../Image FORCE
$(obj)/piggy.o: $(obj)/piggy_data
CFLAGS_font.o := -Dstatic=
-AFLAGS_hyp-stub.o := -Wa,-march=armv7-a
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index 6aa7dc4db2fc..d08a3c450ce7 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -129,6 +129,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \
bcm4709-tplink-archer-c9-v1.dtb \
bcm47094-asus-rt-ac88u.dtb \
bcm47094-dlink-dir-885l.dtb \
+ bcm47094-dlink-dir-890l.dtb \
bcm47094-linksys-panamera.dtb \
bcm47094-luxul-abr-4500.dtb \
bcm47094-luxul-xap-1610.dtb \
@@ -139,6 +140,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \
bcm47094-netgear-r8500.dtb \
bcm47094-phicomm-k3.dtb \
bcm53015-meraki-mr26.dtb \
+ bcm53016-dlink-dwl-8610ap.dtb \
bcm53016-meraki-mr32.dtb \
bcm94708.dtb \
bcm94709.dtb \
@@ -355,6 +357,7 @@ dtb-$(CONFIG_MACH_KIRKWOOD) += \
kirkwood-ns2mini.dtb \
kirkwood-nsa310.dtb \
kirkwood-nsa310a.dtb \
+ kirkwood-nsa310s.dtb \
kirkwood-nsa320.dtb \
kirkwood-nsa325.dtb \
kirkwood-openblocks_a6.dtb \
@@ -681,6 +684,7 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
imx6s-dhcom-drc02.dtb
dtb-$(CONFIG_SOC_IMX6SL) += \
imx6sl-evk.dtb \
+ imx6sl-kobo-aura2.dtb \
imx6sl-tolino-shine2hd.dtb \
imx6sl-tolino-shine3.dtb \
imx6sl-tolino-vision5.dtb \
@@ -1029,7 +1033,9 @@ dtb-$(CONFIG_ARCH_OXNAS) += \
dtb-$(CONFIG_ARCH_QCOM) += \
qcom-apq8016-sbc.dtb \
qcom-apq8026-asus-sparrow.dtb \
+ qcom-apq8026-huawei-sturgeon.dtb \
qcom-apq8026-lg-lenok.dtb \
+ qcom-apq8026-samsung-matisse-wifi.dtb \
qcom-apq8060-dragonboard.dtb \
qcom-apq8064-cm-qs600.dtb \
qcom-apq8064-ifc6410.dtb \
@@ -1059,6 +1065,7 @@ dtb-$(CONFIG_ARCH_QCOM) += \
qcom-msm8974-sony-xperia-rhine-amami.dtb \
qcom-msm8974-sony-xperia-rhine-honami.dtb \
qcom-msm8974pro-fairphone-fp2.dtb \
+ qcom-msm8974pro-oneplus-bacon.dtb \
qcom-msm8974pro-samsung-klte.dtb \
qcom-msm8974pro-sony-xperia-shinano-castor.dtb \
qcom-mdm9615-wp8548-mangoh-green.dtb \
@@ -1214,6 +1221,7 @@ dtb-$(CONFIG_ARCH_STM32) += \
stm32mp151a-prtt1a.dtb \
stm32mp151a-prtt1c.dtb \
stm32mp151a-prtt1s.dtb \
+ stm32mp151a-dhcor-testbench.dtb \
stm32mp153c-dhcom-drc02.dtb \
stm32mp153c-dhcor-drc-compact.dtb \
stm32mp157a-avenger96.dtb \
@@ -1454,6 +1462,8 @@ dtb-$(CONFIG_ARCH_UNIPHIER) += \
uniphier-pro4-ace.dtb \
uniphier-pro4-ref.dtb \
uniphier-pro4-sanji.dtb \
+ uniphier-pro5-epcore.dtb \
+ uniphier-pro5-proex.dtb \
uniphier-pxs2-gentil.dtb \
uniphier-pxs2-vodka.dtb \
uniphier-sld8-ref.dtb
@@ -1588,6 +1598,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
aspeed-bmc-asrock-e3c246d4i.dtb \
aspeed-bmc-asrock-romed8hm3.dtb \
aspeed-bmc-bytedance-g220a.dtb \
+ aspeed-bmc-delta-ahe50dc.dtb \
aspeed-bmc-facebook-bletchley.dtb \
aspeed-bmc-facebook-cloudripper.dtb \
aspeed-bmc-facebook-cmm.dtb \
@@ -1601,6 +1612,7 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
aspeed-bmc-facebook-wedge400.dtb \
aspeed-bmc-facebook-yamp.dtb \
aspeed-bmc-facebook-yosemitev2.dtb \
+ aspeed-bmc-ibm-bonnell.dtb \
aspeed-bmc-ibm-everest.dtb \
aspeed-bmc-ibm-rainier.dtb \
aspeed-bmc-ibm-rainier-1s4u.dtb \
@@ -1612,7 +1624,6 @@ dtb-$(CONFIG_ARCH_ASPEED) += \
aspeed-bmc-lenovo-hr855xg2.dtb \
aspeed-bmc-microsoft-olympus.dtb \
aspeed-bmc-opp-lanyang.dtb \
- aspeed-bmc-opp-mihawk.dtb \
aspeed-bmc-opp-mowgli.dtb \
aspeed-bmc-opp-nicole.dtb \
aspeed-bmc-opp-palmetto.dtb \
diff --git a/arch/arm/boot/dts/am335x-baltos-leds.dtsi b/arch/arm/boot/dts/am335x-baltos-leds.dtsi
index 9a79f727baf6..025014657d12 100644
--- a/arch/arm/boot/dts/am335x-baltos-leds.dtsi
+++ b/arch/arm/boot/dts/am335x-baltos-leds.dtsi
@@ -17,18 +17,18 @@
compatible = "gpio-leds";
- power {
+ led-power {
label = "onrisc:red:power";
linux,default-trigger = "default-on";
gpios = <&gpio3 0 GPIO_ACTIVE_LOW>;
default-state = "on";
};
- wlan {
+ led-wlan {
label = "onrisc:blue:wlan";
gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
- app {
+ led-app {
label = "onrisc:green:app";
gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
default-state = "off";
diff --git a/arch/arm/boot/dts/am335x-boneblack-hdmi.dtsi b/arch/arm/boot/dts/am335x-boneblack-hdmi.dtsi
index 7cfddada9348..486f24deb875 100644
--- a/arch/arm/boot/dts/am335x-boneblack-hdmi.dtsi
+++ b/arch/arm/boot/dts/am335x-boneblack-hdmi.dtsi
@@ -85,8 +85,13 @@
audio-ports = < TDA998x_I2S 0x03>;
ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
port@0 {
- hdmi_0: endpoint@0 {
+ reg = <0>;
+
+ hdmi_0: endpoint {
remote-endpoint = <&lcdc_0>;
};
};
diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
index 25c6ac9913d2..5beabaa5ff6a 100644
--- a/arch/arm/boot/dts/am335x-evm.dts
+++ b/arch/arm/boot/dts/am335x-evm.dts
@@ -126,7 +126,7 @@
backlight = <&backlight>;
port {
- panel_0: endpoint@0 {
+ panel_0: endpoint {
remote-endpoint = <&lcdc_0>;
};
};
@@ -544,7 +544,7 @@
#size-cells = <1>;
partition@0 {
label = "NAND.SPL";
- reg = <0x00000000 0x000020000>;
+ reg = <0x00000000 0x00020000>;
};
partition@1 {
label = "NAND.SPL.backup1";
diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts
index 9c458e5a95b7..5b3278c0c46a 100644
--- a/arch/arm/boot/dts/am335x-evmsk.dts
+++ b/arch/arm/boot/dts/am335x-evmsk.dts
@@ -191,7 +191,7 @@
backlight = <&lcd_bl>;
port {
- panel_0: endpoint@0 {
+ panel_0: endpoint {
remote-endpoint = <&lcdc_0>;
};
};
diff --git a/arch/arm/boot/dts/am335x-guardian.dts b/arch/arm/boot/dts/am335x-guardian.dts
index f6356266564c..b357364e93f9 100644
--- a/arch/arm/boot/dts/am335x-guardian.dts
+++ b/arch/arm/boot/dts/am335x-guardian.dts
@@ -103,8 +103,9 @@
};
- guardian_beeper: dmtimer-pwm@7 {
+ guardian_beeper: pwm-7 {
compatible = "ti,omap-dmtimer-pwm";
+ #pwm-cells = <3>;
ti,timers = <&timer7>;
pinctrl-names = "default";
pinctrl-0 = <&guardian_beeper_pins>;
diff --git a/arch/arm/boot/dts/am335x-igep0033.dtsi b/arch/arm/boot/dts/am335x-igep0033.dtsi
index cc14415a4eb9..3fddf80dcf71 100644
--- a/arch/arm/boot/dts/am335x-igep0033.dtsi
+++ b/arch/arm/boot/dts/am335x-igep0033.dtsi
@@ -168,7 +168,7 @@
/* MTD partition table */
partition@0 {
label = "SPL";
- reg = <0x00000000 0x000080000>;
+ reg = <0x00000000 0x00080000>;
};
partition@1 {
@@ -188,7 +188,7 @@
partition@4 {
label = "File System";
- reg = <0x00780000 0x007880000>;
+ reg = <0x00780000 0x07880000>;
};
};
};
diff --git a/arch/arm/boot/dts/am335x-moxa-uc-2100-common.dtsi b/arch/arm/boot/dts/am335x-moxa-uc-2100-common.dtsi
index 7b40ca9483ca..49e280b42442 100644
--- a/arch/arm/boot/dts/am335x-moxa-uc-2100-common.dtsi
+++ b/arch/arm/boot/dts/am335x-moxa-uc-2100-common.dtsi
@@ -16,11 +16,11 @@
/* Power supply provides a fixed 3.3V @3A */
vmmcsd_fixed: vmmcsd-regulator {
- compatible = "regulator-fixed";
- regulator-name = "vmmcsd_fixed";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-boot-on;
+ compatible = "regulator-fixed";
+ regulator-name = "vmmcsd_fixed";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
};
buttons: push_button {
diff --git a/arch/arm/boot/dts/am335x-moxa-uc-8100-common.dtsi b/arch/arm/boot/dts/am335x-moxa-uc-8100-common.dtsi
index e0364adb8393..7d00e8b20f18 100644
--- a/arch/arm/boot/dts/am335x-moxa-uc-8100-common.dtsi
+++ b/arch/arm/boot/dts/am335x-moxa-uc-8100-common.dtsi
@@ -21,11 +21,11 @@
/* Power supply provides a fixed 3.3V @3A */
vmmcsd_fixed: vmmcsd-regulator {
- compatible = "regulator-fixed";
- regulator-name = "vmmcsd_fixed";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-boot-on;
+ compatible = "regulator-fixed";
+ regulator-name = "vmmcsd_fixed";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
};
buttons: push_button {
diff --git a/arch/arm/boot/dts/am335x-myirtech-myd.dts b/arch/arm/boot/dts/am335x-myirtech-myd.dts
index 9d81d4cc6890..425ad9b81a68 100644
--- a/arch/arm/boot/dts/am335x-myirtech-myd.dts
+++ b/arch/arm/boot/dts/am335x-myirtech-myd.dts
@@ -161,8 +161,13 @@
#sound-dai-cells = <0>;
ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
port@0 {
- hdmi_0: endpoint@0 {
+ reg = <0>;
+
+ hdmi_0: endpoint {
remote-endpoint = <&lcdc_0>;
};
};
diff --git a/arch/arm/boot/dts/am335x-pepper.dts b/arch/arm/boot/dts/am335x-pepper.dts
index 8691eec33b61..a4509e9e1056 100644
--- a/arch/arm/boot/dts/am335x-pepper.dts
+++ b/arch/arm/boot/dts/am335x-pepper.dts
@@ -555,11 +555,11 @@
};
&usb0 {
- dr_mode = "host";
+ dr_mode = "host";
};
&usb1 {
- dr_mode = "host";
+ dr_mode = "host";
};
&am33xx_pinmux {
diff --git a/arch/arm/boot/dts/am335x-pocketbeagle.dts b/arch/arm/boot/dts/am335x-pocketbeagle.dts
index 5e415d8ffdd8..0ba4883cd4ef 100644
--- a/arch/arm/boot/dts/am335x-pocketbeagle.dts
+++ b/arch/arm/boot/dts/am335x-pocketbeagle.dts
@@ -23,28 +23,28 @@
compatible = "gpio-leds";
- usr0 {
+ led-usr0 {
label = "beaglebone:green:usr0";
gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
default-state = "off";
};
- usr1 {
+ led-usr1 {
label = "beaglebone:green:usr1";
gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "mmc0";
default-state = "off";
};
- usr2 {
+ led-usr2 {
label = "beaglebone:green:usr2";
gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "cpu0";
default-state = "off";
};
- usr3 {
+ led-usr3 {
label = "beaglebone:green:usr3";
gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
default-state = "off";
diff --git a/arch/arm/boot/dts/am3517-evm.dts b/arch/arm/boot/dts/am3517-evm.dts
index 35b653014f2b..11618aa501fc 100644
--- a/arch/arm/boot/dts/am3517-evm.dts
+++ b/arch/arm/boot/dts/am3517-evm.dts
@@ -26,12 +26,12 @@
reg = <0x80000000 0x10000000>; /* 256 MB */
};
- vmmc_fixed: vmmc {
- compatible = "regulator-fixed";
- regulator-name = "vmmc_fixed";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- };
+ vmmc_fixed: vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "vmmc_fixed";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
gpio-keys {
compatible = "gpio-keys-polled";
@@ -150,7 +150,7 @@
enable-gpios = <&gpio6 22 GPIO_ACTIVE_HIGH>; /* gpio_182 */
};
- pwm11: dmtimer-pwm@11 {
+ pwm11: pwm-11 {
compatible = "ti,omap-dmtimer-pwm";
pinctrl-names = "default";
pinctrl-0 = <&pwm_pins>;
@@ -176,7 +176,7 @@
};
&davinci_mdio {
- status = "okay";
+ status = "okay";
};
&dss {
@@ -227,7 +227,7 @@
};
&mmc3 {
- status = "disabled";
+ status = "disabled";
};
&usbhshost {
diff --git a/arch/arm/boot/dts/am3517.dtsi b/arch/arm/boot/dts/am3517.dtsi
index cb316135bc7c..823f63502e9f 100644
--- a/arch/arm/boot/dts/am3517.dtsi
+++ b/arch/arm/boot/dts/am3517.dtsi
@@ -49,13 +49,35 @@
};
ocp@68000000 {
- am35x_otg_hs: am35x_otg_hs@5c040000 {
- compatible = "ti,omap3-musb";
- ti,hwmods = "am35x_otg_hs";
- status = "disabled";
- reg = <0x5c040000 0x1000>;
- interrupts = <71>;
- interrupt-names = "mc";
+ target-module@5c040000 {
+ compatible = "ti,sysc-omap2", "ti,sysc";
+ reg = <0x5c040400 0x4>,
+ <0x5c040404 0x4>,
+ <0x5c040408 0x4>;
+ reg-names = "rev", "sysc", "syss";
+ ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP |
+ SYSC_OMAP2_SOFTRESET |
+ SYSC_OMAP2_AUTOIDLE)>;
+ ti,sysc-midle = <SYSC_IDLE_FORCE>,
+ <SYSC_IDLE_NO>,
+ <SYSC_IDLE_SMART>;
+ ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+ <SYSC_IDLE_NO>,
+ <SYSC_IDLE_SMART>;
+ ti,syss-mask = <1>;
+ clocks = <&hsotgusb_ick_am35xx>;
+ clock-names = "fck";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x5c040000 0x1000>;
+
+ am35x_otg_hs: am35x_otg_hs@0 {
+ compatible = "ti,omap3-musb";
+ status = "disabled";
+ reg = <0 0x1000>;
+ interrupts = <71>;
+ interrupt-names = "mc";
+ };
};
davinci_emac: ethernet@5c000000 {
@@ -154,7 +176,7 @@
};
/* Table Table 5-79 of the TRM shows 480ab000 is reserved */
-&usb_otg_hs {
+&usb_otg_target {
status = "disabled";
};
diff --git a/arch/arm/boot/dts/am437x-idk-evm.dts b/arch/arm/boot/dts/am437x-idk-evm.dts
index 123a95f87554..e46cf2a9d075 100644
--- a/arch/arm/boot/dts/am437x-idk-evm.dts
+++ b/arch/arm/boot/dts/am437x-idk-evm.dts
@@ -452,7 +452,7 @@
*/
partition@0 {
label = "QSPI.U_BOOT";
- reg = <0x00000000 0x000080000>;
+ reg = <0x00000000 0x00080000>;
};
partition@1 {
label = "QSPI.U_BOOT.backup";
diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts
index 036f3831dc26..511a02e13e2c 100644
--- a/arch/arm/boot/dts/am437x-sk-evm.dts
+++ b/arch/arm/boot/dts/am437x-sk-evm.dts
@@ -763,7 +763,7 @@
*/
partition@0 {
label = "QSPI.U_BOOT";
- reg = <0x00000000 0x000080000>;
+ reg = <0x00000000 0x00080000>;
};
partition@1 {
label = "QSPI.U_BOOT.backup";
diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts
index 27f4ce855549..9fc915a2582e 100644
--- a/arch/arm/boot/dts/am43x-epos-evm.dts
+++ b/arch/arm/boot/dts/am43x-epos-evm.dts
@@ -919,7 +919,7 @@
*/
partition@0 {
label = "QSPI.U_BOOT";
- reg = <0x00000000 0x000080000>;
+ reg = <0x00000000 0x00080000>;
};
partition@1 {
label = "QSPI.U_BOOT.backup";
diff --git a/arch/arm/boot/dts/am57xx-idk-common.dtsi b/arch/arm/boot/dts/am57xx-idk-common.dtsi
index c06eda817242..7f092a8811e8 100644
--- a/arch/arm/boot/dts/am57xx-idk-common.dtsi
+++ b/arch/arm/boot/dts/am57xx-idk-common.dtsi
@@ -542,7 +542,7 @@
*/
partition@0 {
label = "QSPI.SPL";
- reg = <0x00000000 0x000040000>;
+ reg = <0x00000000 0x00040000>;
};
partition@1 {
label = "QSPI.u-boot";
diff --git a/arch/arm/boot/dts/armada-370-dlink-dns327l.dts b/arch/arm/boot/dts/armada-370-dlink-dns327l.dts
index 2008c6eaaa52..561195b749eb 100644
--- a/arch/arm/boot/dts/armada-370-dlink-dns327l.dts
+++ b/arch/arm/boot/dts/armada-370-dlink-dns327l.dts
@@ -86,19 +86,19 @@
pinctrl-names = "default";
- sata-r-amber-pin {
+ led-sata-r-amber {
label = "dns327l:amber:sata-r";
gpios = <&gpio1 20 GPIO_ACTIVE_HIGH>;
default-state = "keep";
};
- sata-l-amber-pin {
+ led-sata-l-amber {
label = "dns327l:amber:sata-l";
gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
default-state = "keep";
};
- backup-led-pin {
+ led-backup {
label = "dns327l:white:usb";
gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>;
default-state = "keep";
diff --git a/arch/arm/boot/dts/armada-370-netgear-rn102.dts b/arch/arm/boot/dts/armada-370-netgear-rn102.dts
index b0b640b7de40..079b37cf148a 100644
--- a/arch/arm/boot/dts/armada-370-netgear-rn102.dts
+++ b/arch/arm/boot/dts/armada-370-netgear-rn102.dts
@@ -85,11 +85,11 @@
};
clocks {
- g762_clk: g762-oscillator {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <8192>;
- };
+ g762_clk: g762-oscillator {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <8192>;
+ };
};
gpio-leds {
diff --git a/arch/arm/boot/dts/armada-370-netgear-rn104.dts b/arch/arm/boot/dts/armada-370-netgear-rn104.dts
index 85e2e9e27a9f..d752ac1d7b58 100644
--- a/arch/arm/boot/dts/armada-370-netgear-rn104.dts
+++ b/arch/arm/boot/dts/armada-370-netgear-rn104.dts
@@ -94,11 +94,11 @@
};
clocks {
- g762_clk: g762-oscillator {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <8192>;
- };
+ g762_clk: g762-oscillator {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <8192>;
+ };
};
gpio-leds {
diff --git a/arch/arm/boot/dts/armada-370-rd.dts b/arch/arm/boot/dts/armada-370-rd.dts
index 6ba7699b69ed..be005c9f42ef 100644
--- a/arch/arm/boot/dts/armada-370-rd.dts
+++ b/arch/arm/boot/dts/armada-370-rd.dts
@@ -61,8 +61,8 @@
status = "okay";
phy-mode = "rgmii-id";
fixed-link {
- speed = <1000>;
- full-duplex;
+ speed = <1000>;
+ full-duplex;
};
};
@@ -155,18 +155,18 @@
};
port@1 {
- reg = <1>;
- label = "lan1";
+ reg = <1>;
+ label = "lan1";
};
port@2 {
- reg = <2>;
- label = "lan2";
+ reg = <2>;
+ label = "lan2";
};
port@3 {
- reg = <3>;
- label = "lan3";
+ reg = <3>;
+ label = "lan3";
};
port@5 {
diff --git a/arch/arm/boot/dts/armada-370-seagate-nas-4bay.dts b/arch/arm/boot/dts/armada-370-seagate-nas-4bay.dts
index 3cf70c72c5ca..9cb69999b1db 100644
--- a/arch/arm/boot/dts/armada-370-seagate-nas-4bay.dts
+++ b/arch/arm/boot/dts/armada-370-seagate-nas-4bay.dts
@@ -72,11 +72,11 @@
};
gpio-leds {
- red-sata2 {
+ led-red-sata2 {
label = "dart:red:sata2";
gpios = <&pca9554 0 GPIO_ACTIVE_LOW>;
};
- red-sata3 {
+ led-red-sata3 {
label = "dart:red:sata3";
gpios = <&pca9554 3 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/armada-370-seagate-nas-xbay.dtsi b/arch/arm/boot/dts/armada-370-seagate-nas-xbay.dtsi
index 866b8630d407..822f10734946 100644
--- a/arch/arm/boot/dts/armada-370-seagate-nas-xbay.dtsi
+++ b/arch/arm/boot/dts/armada-370-seagate-nas-xbay.dtsi
@@ -132,21 +132,21 @@
gpio-leds {
compatible = "gpio-leds";
- white-power {
+ led-white-power {
label = "dart:white:power";
gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
- red-power {
+ led-red-power {
label = "dart:red:power";
gpios = <&gpio1 31 GPIO_ACTIVE_HIGH>;
};
- red-sata0 {
+ led-red-sata0 {
label = "dart:red:sata0";
gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
};
- red-sata1 {
+ led-red-sata1 {
label = "dart:red:sata1";
gpios = <&gpio1 21 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/armada-370-seagate-personal-cloud.dtsi b/arch/arm/boot/dts/armada-370-seagate-personal-cloud.dtsi
index 702a85af2078..124a8ba279e3 100644
--- a/arch/arm/boot/dts/armada-370-seagate-personal-cloud.dtsi
+++ b/arch/arm/boot/dts/armada-370-seagate-personal-cloud.dtsi
@@ -107,7 +107,7 @@
gpio-leds {
compatible = "gpio-leds";
- red-sata0 {
+ led-red-sata0 {
label = "cumulus:red:sata0";
gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>;
default-state = "off";
diff --git a/arch/arm/boot/dts/armada-370-synology-ds213j.dts b/arch/arm/boot/dts/armada-370-synology-ds213j.dts
index e72b8ed4b997..f0893cc06607 100644
--- a/arch/arm/boot/dts/armada-370-synology-ds213j.dts
+++ b/arch/arm/boot/dts/armada-370-synology-ds213j.dts
@@ -91,9 +91,9 @@
};
ethernet@70000 {
- status = "okay";
- phy = <&phy1>;
- phy-mode = "sgmii";
+ status = "okay";
+ phy = <&phy1>;
+ phy-mode = "sgmii";
};
sata@a0000 {
diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi
index 9dc928859ad3..2013a5ccecd3 100644
--- a/arch/arm/boot/dts/armada-370.dtsi
+++ b/arch/arm/boot/dts/armada-370.dtsi
@@ -84,7 +84,7 @@
pcie2: pcie@2,0 {
device_type = "pci";
- assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
+ assigned-addresses = <0x82001000 0 0x80000 0 0x2000>;
reg = <0x1000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
diff --git a/arch/arm/boot/dts/armada-375.dtsi b/arch/arm/boot/dts/armada-375.dtsi
index 9fbe0cfec48f..ddc49547d786 100644
--- a/arch/arm/boot/dts/armada-375.dtsi
+++ b/arch/arm/boot/dts/armada-375.dtsi
@@ -596,7 +596,7 @@
pcie1: pcie@2,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+ assigned-addresses = <0x82001000 0 0x44000 0 0x2000>;
reg = <0x1000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
diff --git a/arch/arm/boot/dts/armada-380.dtsi b/arch/arm/boot/dts/armada-380.dtsi
index ce1dddb2269b..e94f22b0e9b5 100644
--- a/arch/arm/boot/dts/armada-380.dtsi
+++ b/arch/arm/boot/dts/armada-380.dtsi
@@ -89,7 +89,7 @@
/* x1 port */
pcie@2,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+ assigned-addresses = <0x82001000 0 0x40000 0 0x2000>;
reg = <0x1000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
@@ -118,7 +118,7 @@
/* x1 port */
pcie@3,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+ assigned-addresses = <0x82001800 0 0x44000 0 0x2000>;
reg = <0x1800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
diff --git a/arch/arm/boot/dts/armada-385-linksys-caiman.dts b/arch/arm/boot/dts/armada-385-linksys-caiman.dts
index a03050c97084..88b2921fed55 100644
--- a/arch/arm/boot/dts/armada-385-linksys-caiman.dts
+++ b/arch/arm/boot/dts/armada-385-linksys-caiman.dts
@@ -62,11 +62,11 @@
};
&gpio_leds {
- power {
+ led-power {
label = "caiman:white:power";
};
- sata {
+ led-sata {
label = "caiman:white:sata";
};
};
diff --git a/arch/arm/boot/dts/armada-385-linksys-cobra.dts b/arch/arm/boot/dts/armada-385-linksys-cobra.dts
index e3e4877a6f49..88200f930d0d 100644
--- a/arch/arm/boot/dts/armada-385-linksys-cobra.dts
+++ b/arch/arm/boot/dts/armada-385-linksys-cobra.dts
@@ -62,11 +62,11 @@
};
&gpio_leds {
- power {
+ led-power {
label = "cobra:white:power";
};
- sata {
+ led-sata {
label = "cobra:white:sata";
};
};
diff --git a/arch/arm/boot/dts/armada-385-linksys-rango.dts b/arch/arm/boot/dts/armada-385-linksys-rango.dts
index 3c4af57ec2b9..4ab45f294de2 100644
--- a/arch/arm/boot/dts/armada-385-linksys-rango.dts
+++ b/arch/arm/boot/dts/armada-385-linksys-rango.dts
@@ -54,22 +54,22 @@
};
&gpio_leds {
- power {
+ led-power {
gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>;
label = "rango:white:power";
};
- sata {
+ led-sata {
gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
label = "rango:white:sata";
};
- wlan_2g {
+ led-wlan_2g {
gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
label = "rango:white:wlan_2g";
};
- wlan_5g {
+ led-wlan_5g {
gpios = <&gpio1 14 GPIO_ACTIVE_LOW>;
label = "rango:white:wlan_5g";
};
diff --git a/arch/arm/boot/dts/armada-385-linksys-shelby.dts b/arch/arm/boot/dts/armada-385-linksys-shelby.dts
index 3451cd3e5dff..f1b1f22413f1 100644
--- a/arch/arm/boot/dts/armada-385-linksys-shelby.dts
+++ b/arch/arm/boot/dts/armada-385-linksys-shelby.dts
@@ -62,11 +62,11 @@
};
&gpio_leds {
- power {
+ led-power {
label = "shelby:white:power";
};
- sata {
+ led-sata {
label = "shelby:white:sata";
};
};
diff --git a/arch/arm/boot/dts/armada-385-linksys.dtsi b/arch/arm/boot/dts/armada-385-linksys.dtsi
index 116aca5e688f..85e8d966f6c1 100644
--- a/arch/arm/boot/dts/armada-385-linksys.dtsi
+++ b/arch/arm/boot/dts/armada-385-linksys.dtsi
@@ -71,12 +71,12 @@
pinctrl-0 = <&gpio_leds_pins>;
pinctrl-names = "default";
- power {
+ led-power {
gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>;
default-state = "on";
};
- sata {
+ led-sata {
gpios = <&gpio1 22 GPIO_ACTIVE_LOW>;
default-state = "off";
linux,default-trigger = "disk-activity";
diff --git a/arch/arm/boot/dts/armada-385-synology-ds116.dts b/arch/arm/boot/dts/armada-385-synology-ds116.dts
index 2622af73c9da..ea91ff964d94 100644
--- a/arch/arm/boot/dts/armada-385-synology-ds116.dts
+++ b/arch/arm/boot/dts/armada-385-synology-ds116.dts
@@ -149,7 +149,7 @@
* sata0, and accesses to SATA disk 0 make it blink so it
* doesn't need to be declared here.
*/
- orange {
+ led-orange {
gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
label = "ds116:orange:disk";
default-state = "off";
diff --git a/arch/arm/boot/dts/armada-385-turris-omnia.dts b/arch/arm/boot/dts/armada-385-turris-omnia.dts
index 72ac807cae25..0c1f238e4c30 100644
--- a/arch/arm/boot/dts/armada-385-turris-omnia.dts
+++ b/arch/arm/boot/dts/armada-385-turris-omnia.dts
@@ -23,6 +23,12 @@
stdout-path = &uart0;
};
+ aliases {
+ ethernet0 = &eth0;
+ ethernet1 = &eth1;
+ ethernet2 = &eth2;
+ };
+
memory {
device_type = "memory";
reg = <0x00000000 0x40000000>; /* 1024 MB */
@@ -483,7 +489,17 @@
};
};
- /* port 6 is connected to eth0 */
+ ports@6 {
+ reg = <6>;
+ label = "cpu";
+ ethernet = <&eth0>;
+ phy-mode = "rgmii-id";
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+ };
};
};
};
diff --git a/arch/arm/boot/dts/armada-385.dtsi b/arch/arm/boot/dts/armada-385.dtsi
index 83392b92dae2..be8d607c59b2 100644
--- a/arch/arm/boot/dts/armada-385.dtsi
+++ b/arch/arm/boot/dts/armada-385.dtsi
@@ -93,7 +93,7 @@
/* x1 port */
pcie2: pcie@2,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+ assigned-addresses = <0x82001000 0 0x40000 0 0x2000>;
reg = <0x1000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
@@ -121,7 +121,7 @@
/* x1 port */
pcie3: pcie@3,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+ assigned-addresses = <0x82001800 0 0x44000 0 0x2000>;
reg = <0x1800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
@@ -152,7 +152,7 @@
*/
pcie4: pcie@4,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x48000 0 0x2000>;
+ assigned-addresses = <0x82002000 0 0x48000 0 0x2000>;
reg = <0x2000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
diff --git a/arch/arm/boot/dts/armada-38x.dtsi b/arch/arm/boot/dts/armada-38x.dtsi
index 446861b6b17b..12933eff419f 100644
--- a/arch/arm/boot/dts/armada-38x.dtsi
+++ b/arch/arm/boot/dts/armada-38x.dtsi
@@ -304,7 +304,7 @@
};
gpio0: gpio@18100 {
- compatible = "marvell,armada-370-gpio",
+ compatible = "marvell,armadaxp-gpio",
"marvell,orion-gpio";
reg = <0x18100 0x40>, <0x181c0 0x08>;
reg-names = "gpio", "pwm";
@@ -323,7 +323,7 @@
};
gpio1: gpio@18140 {
- compatible = "marvell,armada-370-gpio",
+ compatible = "marvell,armadaxp-gpio",
"marvell,orion-gpio";
reg = <0x18140 0x40>, <0x181c8 0x08>;
reg-names = "gpio", "pwm";
diff --git a/arch/arm/boot/dts/armada-39x.dtsi b/arch/arm/boot/dts/armada-39x.dtsi
index 923b035a3ab3..1e05208d9f34 100644
--- a/arch/arm/boot/dts/armada-39x.dtsi
+++ b/arch/arm/boot/dts/armada-39x.dtsi
@@ -213,7 +213,7 @@
};
gpio0: gpio@18100 {
- compatible = "marvell,orion-gpio";
+ compatible = "marvell,armadaxp-gpio", "marvell,orion-gpio";
reg = <0x18100 0x40>;
ngpios = <32>;
gpio-controller;
@@ -227,7 +227,7 @@
};
gpio1: gpio@18140 {
- compatible = "marvell,orion-gpio";
+ compatible = "marvell,armadaxp-gpio", "marvell,orion-gpio";
reg = <0x18140 0x40>;
ngpios = <28>;
gpio-controller;
@@ -463,7 +463,7 @@
/* x1 port */
pcie@2,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
+ assigned-addresses = <0x82001000 0 0x40000 0 0x2000>;
reg = <0x1000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
@@ -492,7 +492,7 @@
/* x1 port */
pcie@3,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+ assigned-addresses = <0x82001800 0 0x44000 0 0x2000>;
reg = <0x1800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
@@ -524,7 +524,7 @@
*/
pcie@4,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x48000 0 0x2000>;
+ assigned-addresses = <0x82002000 0 0x48000 0 0x2000>;
reg = <0x2000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
diff --git a/arch/arm/boot/dts/armada-xp-98dx3236.dtsi b/arch/arm/boot/dts/armada-xp-98dx3236.dtsi
index b21ffb819b1d..7a7e2066c498 100644
--- a/arch/arm/boot/dts/armada-xp-98dx3236.dtsi
+++ b/arch/arm/boot/dts/armada-xp-98dx3236.dtsi
@@ -296,6 +296,7 @@
compatible = "marvell,armada-xp-wdt";
clocks = <&coreclk 2>, <&refclk>;
clock-names = "nbclk", "fixed";
+ interrupts = <93>, <38>;
};
&cpurst {
diff --git a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
index 622ac40dd164..dbe8dfe236fb 100644
--- a/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
+++ b/arch/arm/boot/dts/armada-xp-linksys-mamba.dts
@@ -195,7 +195,7 @@
pinctrl-0 = <&power_led_pin>;
pinctrl-names = "default";
- power {
+ led-power {
label = "mamba:white:power";
gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
default-state = "on";
diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
index bf9360f41e0a..5ea9d509cd30 100644
--- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
@@ -107,7 +107,7 @@
pcie2: pcie@2,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+ assigned-addresses = <0x82001000 0 0x44000 0 0x2000>;
reg = <0x1000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
@@ -135,7 +135,7 @@
pcie3: pcie@3,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x48000 0 0x2000>;
+ assigned-addresses = <0x82001800 0 0x48000 0 0x2000>;
reg = <0x1800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
@@ -163,7 +163,7 @@
pcie4: pcie@4,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x4c000 0 0x2000>;
+ assigned-addresses = <0x82002000 0 0x4c000 0 0x2000>;
reg = <0x2000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
@@ -191,7 +191,7 @@
pcie5: pcie@5,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
+ assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
reg = <0x2800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
index 0714af52e607..6c6fbb9faf5a 100644
--- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
@@ -122,7 +122,7 @@
pcie2: pcie@2,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
+ assigned-addresses = <0x82001000 0 0x44000 0 0x2000>;
reg = <0x1000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
@@ -150,7 +150,7 @@
pcie3: pcie@3,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x48000 0 0x2000>;
+ assigned-addresses = <0x82001800 0 0x48000 0 0x2000>;
reg = <0x1800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
@@ -178,7 +178,7 @@
pcie4: pcie@4,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x4c000 0 0x2000>;
+ assigned-addresses = <0x82002000 0 0x4c000 0 0x2000>;
reg = <0x2000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
@@ -206,7 +206,7 @@
pcie5: pcie@5,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
+ assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
reg = <0x2800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
@@ -234,7 +234,7 @@
pcie6: pcie@6,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x84000 0 0x2000>;
+ assigned-addresses = <0x82003000 0 0x84000 0 0x2000>;
reg = <0x3000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
@@ -262,7 +262,7 @@
pcie7: pcie@7,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x88000 0 0x2000>;
+ assigned-addresses = <0x82003800 0 0x88000 0 0x2000>;
reg = <0x3800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
@@ -290,7 +290,7 @@
pcie8: pcie@8,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x8c000 0 0x2000>;
+ assigned-addresses = <0x82004000 0 0x8c000 0 0x2000>;
reg = <0x4000 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
@@ -318,7 +318,7 @@
pcie9: pcie@9,0 {
device_type = "pci";
- assigned-addresses = <0x82000800 0 0x42000 0 0x2000>;
+ assigned-addresses = <0x82004800 0 0x42000 0 0x2000>;
reg = <0x4800 0 0 0 0>;
#address-cells = <3>;
#size-cells = <2>;
diff --git a/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts b/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts
index 8ea73587db81..31933f81144e 100644
--- a/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts
+++ b/arch/arm/boot/dts/armada-xp-netgear-rn2120.dts
@@ -121,11 +121,11 @@
};
clocks {
- g762_clk: g762-oscillator {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <32768>;
- };
+ g762_clk: g762-oscillator {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ };
};
gpio-leds {
diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi
index 6c19984d668e..4297482da62f 100644
--- a/arch/arm/boot/dts/armada-xp.dtsi
+++ b/arch/arm/boot/dts/armada-xp.dtsi
@@ -260,6 +260,7 @@
compatible = "marvell,armada-xp-wdt";
clocks = <&coreclk 2>, <&refclk>;
clock-names = "nbclk", "fixed";
+ interrupts = <93>, <38>;
};
&cpurst {
diff --git a/arch/arm/boot/dts/aspeed-bmc-ampere-mtjade.dts b/arch/arm/boot/dts/aspeed-bmc-ampere-mtjade.dts
index d127cbcc7998..0a51d2e32fab 100644
--- a/arch/arm/boot/dts/aspeed-bmc-ampere-mtjade.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-ampere-mtjade.dts
@@ -342,6 +342,10 @@
&i2c0 {
status = "okay";
+ ssif-bmc@10 {
+ compatible = "ssif-bmc";
+ reg = <0x10>;
+ };
};
&i2c1 {
@@ -350,6 +354,14 @@
&i2c2 {
status = "okay";
+ smpro@4f {
+ compatible = "ampere,smpro";
+ reg = <0x4f>;
+ };
+ smpro@4e {
+ compatible = "ampere,smpro";
+ reg = <0x4e>;
+ };
};
&i2c3 {
diff --git a/arch/arm/boot/dts/aspeed-bmc-ampere-mtmitchell.dts b/arch/arm/boot/dts/aspeed-bmc-ampere-mtmitchell.dts
index 606cd4be245a..4b91600eaf62 100644
--- a/arch/arm/boot/dts/aspeed-bmc-ampere-mtmitchell.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-ampere-mtmitchell.dts
@@ -445,6 +445,10 @@
&i2c11 {
status = "okay";
+ ssif-bmc@10 {
+ compatible = "ssif-bmc";
+ reg = <0x10>;
+ };
};
&i2c14 {
diff --git a/arch/arm/boot/dts/aspeed-bmc-delta-ahe50dc.dts b/arch/arm/boot/dts/aspeed-bmc-delta-ahe50dc.dts
new file mode 100644
index 000000000000..6600f7e9bf5e
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed-bmc-delta-ahe50dc.dts
@@ -0,0 +1,418 @@
+// SPDX-License-Identifier: GPL-2.0+
+/dts-v1/;
+
+#include "aspeed-g4.dtsi"
+#include <dt-bindings/gpio/aspeed-gpio.h>
+
+#define EFUSE_OUTPUT(n) \
+ efuse##n { \
+ compatible = "regulator-output"; \
+ vout-supply = <&efuse##n>; \
+ }
+
+#define __stringify(x) #x
+
+#define EFUSE(hexaddr, num) \
+ efuse@##hexaddr { \
+ compatible = "lm25066"; \
+ reg = <0x##hexaddr>; \
+ shunt-resistor-micro-ohms = <675>; \
+ regulators { \
+ efuse##num: vout0 { \
+ regulator-name = __stringify(efuse##num##-reg); \
+ }; \
+ }; \
+ }
+
+/{
+ model = "Delta Power AHE-50DC";
+ compatible = "delta,ahe50dc-bmc", "aspeed,ast2400";
+
+ aliases {
+ serial4 = &uart5;
+
+ /*
+ * pca9541-arbitrated logical i2c buses are numbered as the
+ * corresponding physical bus plus 20
+ */
+ i2c20 = &i2carb0;
+ i2c21 = &i2carb1;
+ i2c22 = &i2carb2;
+ i2c23 = &i2carb3;
+ i2c24 = &i2carb4;
+ i2c26 = &i2carb6;
+ i2c27 = &i2carb7;
+ i2c28 = &i2carb8;
+ i2c32 = &i2carb12;
+ };
+
+ chosen {
+ stdout-path = &uart3;
+ bootargs = "console=ttyS2,115200n8 earlycon";
+ };
+
+ memory@40000000 {
+ reg = <0x40000000 0x10000000>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ heartbeat {
+ gpios = <&gpio ASPEED_GPIO(P, 0) GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+
+ panic {
+ gpios = <&gpio ASPEED_GPIO(P, 2) GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "panic";
+ };
+ };
+
+ iio-hwmon {
+ compatible = "iio-hwmon";
+ io-channels = <&adc 0>, <&adc 1>, <&adc 2>, <&adc 3>, <&adc 4>,
+ <&adc 5>, <&adc 6>, <&adc 7>, <&adc 8>, <&adc 9>;
+ };
+
+ EFUSE_OUTPUT(01);
+ EFUSE_OUTPUT(02);
+ EFUSE_OUTPUT(03);
+ EFUSE_OUTPUT(04);
+ EFUSE_OUTPUT(05);
+ EFUSE_OUTPUT(06);
+ EFUSE_OUTPUT(07);
+ EFUSE_OUTPUT(08);
+ EFUSE_OUTPUT(09);
+ EFUSE_OUTPUT(10);
+ EFUSE_OUTPUT(11);
+ EFUSE_OUTPUT(12);
+ EFUSE_OUTPUT(13);
+ EFUSE_OUTPUT(14);
+ EFUSE_OUTPUT(15);
+ EFUSE_OUTPUT(16);
+ EFUSE_OUTPUT(17);
+ EFUSE_OUTPUT(18);
+ EFUSE_OUTPUT(19);
+ EFUSE_OUTPUT(20);
+ EFUSE_OUTPUT(21);
+ EFUSE_OUTPUT(22);
+ EFUSE_OUTPUT(23);
+ EFUSE_OUTPUT(24);
+ EFUSE_OUTPUT(25);
+ EFUSE_OUTPUT(26);
+ EFUSE_OUTPUT(27);
+ EFUSE_OUTPUT(28);
+ EFUSE_OUTPUT(29);
+ EFUSE_OUTPUT(30);
+ EFUSE_OUTPUT(31);
+ EFUSE_OUTPUT(32);
+ EFUSE_OUTPUT(33);
+ EFUSE_OUTPUT(34);
+ EFUSE_OUTPUT(35);
+ EFUSE_OUTPUT(36);
+ EFUSE_OUTPUT(37);
+ EFUSE_OUTPUT(38);
+ EFUSE_OUTPUT(39);
+ EFUSE_OUTPUT(40);
+ EFUSE_OUTPUT(41);
+ EFUSE_OUTPUT(42);
+ EFUSE_OUTPUT(43);
+ EFUSE_OUTPUT(44);
+ EFUSE_OUTPUT(45);
+ EFUSE_OUTPUT(46);
+ EFUSE_OUTPUT(47);
+ EFUSE_OUTPUT(48);
+ EFUSE_OUTPUT(49);
+ EFUSE_OUTPUT(50);
+
+};
+
+&fmc {
+ status = "okay";
+
+ flash@0 {
+ status = "okay";
+ m25p,fast-read;
+ label = "flash0";
+ spi-max-frequency = <50000000>; // 50 MHz
+#include "openbmc-flash-layout.dtsi"
+ };
+};
+
+&uart3 {
+ status = "okay";
+};
+
+&mac1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rgmii2_default &pinctrl_mdio2_default>;
+};
+
+&i2c0 {
+ status = "okay";
+ bus-frequency = <200000>;
+
+ pca9541@79 {
+ compatible = "nxp,pca9541";
+ reg = <0x79>;
+
+ i2carb0: i2c-arb {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ /* lm25066 efuses @ 10-17, 40-47, 50-57 */
+ EFUSE(10, 03);
+ EFUSE(11, 04);
+ EFUSE(12, 01);
+ EFUSE(13, 02);
+ EFUSE(14, 13);
+ EFUSE(15, 14);
+ EFUSE(16, 15);
+ EFUSE(17, 16);
+ EFUSE(40, 12);
+ EFUSE(41, 11);
+ EFUSE(42, 10);
+ EFUSE(43, 09);
+ EFUSE(44, 08);
+ EFUSE(45, 07);
+ EFUSE(46, 05);
+ EFUSE(47, 06);
+ EFUSE(50, 17);
+ EFUSE(51, 18);
+ EFUSE(52, 20);
+ EFUSE(53, 19);
+ EFUSE(54, 22);
+ EFUSE(55, 21);
+ EFUSE(56, 24);
+ EFUSE(57, 23);
+ };
+ };
+};
+
+&i2c1 {
+ status = "okay";
+ bus-frequency = <200000>;
+
+ pca9541@72 {
+ compatible = "nxp,pca9541";
+ reg = <0x72>;
+
+ i2carb1: i2c-arb {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+};
+
+&i2c2 {
+ status = "okay";
+ bus-frequency = <200000>;
+
+ pca9541@73 {
+ compatible = "nxp,pca9541";
+ reg = <0x73>;
+
+ i2carb2: i2c-arb {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+};
+
+&i2c3 {
+ status = "okay";
+ bus-frequency = <200000>;
+
+ pca9541@74 {
+ compatible = "nxp,pca9541";
+ reg = <0x74>;
+
+ i2carb3: i2c-arb {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+};
+
+&i2c4 {
+ status = "okay";
+ bus-frequency = <200000>;
+
+ pca9541@7a {
+ compatible = "nxp,pca9541";
+ reg = <0x7a>;
+
+ i2carb4: i2c-arb {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio@20 {
+ compatible = "nxp,pca9534";
+ reg = <0x20>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
+ /* lm25066 efuses @ 10-17, 40-47, 50-57, 59, 5a */
+ EFUSE(10, 27);
+ EFUSE(11, 28);
+ EFUSE(12, 25);
+ EFUSE(13, 26);
+ EFUSE(14, 37);
+ EFUSE(15, 38);
+ EFUSE(16, 39);
+ EFUSE(17, 40);
+ EFUSE(40, 36);
+ EFUSE(41, 35);
+ EFUSE(42, 34);
+ EFUSE(43, 33);
+ EFUSE(44, 32);
+ EFUSE(45, 31);
+ EFUSE(46, 29);
+ EFUSE(47, 30);
+ EFUSE(50, 41);
+ EFUSE(51, 42);
+ EFUSE(52, 44);
+ EFUSE(53, 43);
+ EFUSE(54, 46);
+ EFUSE(55, 45);
+ EFUSE(56, 48);
+ EFUSE(57, 47);
+ EFUSE(59, 49);
+ EFUSE(5a, 50);
+ };
+ };
+};
+
+&i2c6 {
+ status = "okay";
+ bus-frequency = <200000>;
+
+ pca9541@75 {
+ compatible = "nxp,pca9541";
+ reg = <0x75>;
+
+ i2carb6: i2c-arb {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+};
+
+&i2c7 {
+ status = "okay";
+ bus-frequency = <200000>;
+
+ pca9541@76 {
+ compatible = "nxp,pca9541";
+ reg = <0x76>;
+
+ i2carb7: i2c-arb {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+};
+
+&i2c8 {
+ status = "okay";
+ bus-frequency = <200000>;
+
+ pca9541@7c {
+ compatible = "nxp,pca9541";
+ reg = <0x7c>;
+
+ i2carb8: i2c-arb {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fancontrol@30 {
+ compatible = "delta,ahe50dc-fan";
+ reg = <0x30>;
+ };
+
+ /* Baseboard FRU eeprom */
+ eeprom@50 {
+ compatible = "atmel,24c02";
+ reg = <0x50>;
+ };
+ };
+ };
+};
+
+&i2c12 {
+ status = "okay";
+ bus-frequency = <200000>;
+
+ pca9541@71 {
+ compatible = "nxp,pca9541";
+ reg = <0x71>;
+
+ i2carb12: i2c-arb {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+};
+
+&gpio {
+ status = "okay";
+ gpio-line-names =
+ /* A */ "", "", "", "", "", "", "", "",
+ /* B */ "", "", "", "", "", "", "", "",
+ /* C */ "RESET_PEER_N", "HEARTBEAT_OUT", "", "", "", "", "", "",
+ /* D */ "", "", "", "", "", "", "", "",
+ /* E */ "DOOM_N", "", "", "", "", "LED_PWR_BLUE", "", "",
+ /* F */ "", "", "", "", "", "", "", "",
+ /* G */ "", "", "", "", "", "", "", "",
+ /* H */ "", "", "", "", "", "", "", "",
+ /* I */ "", "", "", "", "", "", "", "",
+ /* J */ "", "", "BMC_ID", "", "", "", "", "",
+ /* K */ "", "", "", "", "", "", "", "",
+ /* L */ "", "", "", "", "", "", "", "",
+ /* M */ "", "", "", "", "", "", "", "",
+ /* N */ "", "", "", "", "", "", "", "",
+ /* O */ "", "", "", "", "", "", "", "",
+ /* P */ "LED_GREEN", "", "LED_RED", "", "", "", "", "",
+ /* Q */ "", "", "", "", "", "", "", "",
+ /* R */ "", "", "", "", "", "", "", "",
+ /* S */ "", "", "", "", "", "", "", "",
+ /* T */ "", "", "", "", "", "", "", "",
+ /* U */ "", "", "", "", "", "", "", "",
+ /* V */ "", "", "", "", "", "", "", "",
+ /* W */ "", "", "", "", "", "", "", "",
+ /* X */ "", "", "", "", "", "", "", "",
+ /* Y */ "HEARTBEAT_IN", "BOARDREV0", "BOARDREV1", "",
+ /* Z */ "", "", "", "", "", "", "", "",
+ /* AA */ "", "", "", "", "", "", "", "",
+ /* AB */ "", "", "", "";
+
+ /*
+ * I don't rightly know what this GPIO really *is*, but setting it to
+ * zero causes the fans to run at full speed, after which setting it
+ * back to one causes a power output glitch, so install a hog to keep
+ * it at one as a failsafe to ensure nothing accidentally touches it.
+ */
+ doom-guardrail {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(E, 0) GPIO_ACTIVE_LOW>;
+ output-low;
+ };
+};
+
+&adc {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_adc0_default
+ &pinctrl_adc1_default
+ &pinctrl_adc2_default
+ &pinctrl_adc3_default
+ &pinctrl_adc4_default
+ &pinctrl_adc5_default
+ &pinctrl_adc6_default
+ &pinctrl_adc7_default
+ &pinctrl_adc8_default
+ &pinctrl_adc9_default>;
+};
diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-bletchley.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-bletchley.dts
index 1fc3e7cbf0d1..a619eec70633 100644
--- a/arch/arm/boot/dts/aspeed-bmc-facebook-bletchley.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-facebook-bletchley.dts
@@ -60,7 +60,7 @@
compatible = "gpio-leds";
sys_log_id {
default-state = "off";
- gpios = <&front_leds 0 GPIO_ACTIVE_HIGH>;
+ gpios = <&front_leds 0 GPIO_ACTIVE_LOW>;
};
};
@@ -191,6 +191,95 @@
gpios = <&sled6_leds 1 GPIO_ACTIVE_LOW>;
};
};
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ presence-sled1 {
+ label = "presence-sled1";
+ gpios = <&gpio0 ASPEED_GPIO(H, 2) GPIO_ACTIVE_LOW>;
+ linux,code = <ASPEED_GPIO(H, 2)>;
+ };
+ presence-sled2 {
+ label = "presence-sled2";
+ gpios = <&gpio0 ASPEED_GPIO(H, 3) GPIO_ACTIVE_LOW>;
+ linux,code = <ASPEED_GPIO(H, 3)>;
+ };
+ presence-sled3 {
+ label = "presence-sled3";
+ gpios = <&gpio0 ASPEED_GPIO(H, 4) GPIO_ACTIVE_LOW>;
+ linux,code = <ASPEED_GPIO(H, 4)>;
+ };
+ presence-sled4 {
+ label = "presence-sled4";
+ gpios = <&gpio0 ASPEED_GPIO(H, 5) GPIO_ACTIVE_LOW>;
+ linux,code = <ASPEED_GPIO(H, 5)>;
+ };
+ presence-sled5 {
+ label = "presence-sled5";
+ gpios = <&gpio0 ASPEED_GPIO(H, 6) GPIO_ACTIVE_LOW>;
+ linux,code = <ASPEED_GPIO(H, 6)>;
+ };
+ presence-sled6 {
+ label = "presence-sled6";
+ gpios = <&gpio0 ASPEED_GPIO(H, 7) GPIO_ACTIVE_LOW>;
+ linux,code = <ASPEED_GPIO(H, 7)>;
+ };
+ };
+
+ vbus_sled1: vbus_sled1 {
+ compatible = "regulator-fixed";
+ regulator-name = "vbus_sled1";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&sled1_ioexp 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ vbus_sled2: vbus_sled2 {
+ compatible = "regulator-fixed";
+ regulator-name = "vbus_sled2";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&sled2_ioexp 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ vbus_sled3: vbus_sled3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vbus_sled3";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&sled3_ioexp 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ vbus_sled4: vbus_sled4 {
+ compatible = "regulator-fixed";
+ regulator-name = "vbus_sled4";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&sled4_ioexp 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ vbus_sled5: vbus_sled5 {
+ compatible = "regulator-fixed";
+ regulator-name = "vbus_sled5";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&sled5_ioexp 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ vbus_sled6: vbus_sled6 {
+ compatible = "regulator-fixed";
+ regulator-name = "vbus_sled6";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&sled6_ioexp 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
};
&mac2 {
@@ -302,17 +391,17 @@
compatible = "fcs,fusb302";
reg = <0x22>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <ASPEED_GPIO(B, 0) IRQ_TYPE_LEVEL_LOW>;
+ vbus-supply = <&vbus_sled1>;
+
connector {
compatible = "usb-c-connector";
label = "USB-C";
- power-role = "dual";
- try-power-role = "sink";
- data-role = "dual";
- source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
- sink-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)
- PDO_VAR(3000, 12000, 3000)
- PDO_PPS_APDO(3000, 11000, 3000)>;
- op-sink-microwatt = <10000000>;
+ power-role = "source";
+ data-role = "host";
+ pd-disable;
+ typec-power-opmode = "default";
};
};
@@ -388,17 +477,17 @@
compatible = "fcs,fusb302";
reg = <0x22>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <ASPEED_GPIO(B, 1) IRQ_TYPE_LEVEL_LOW>;
+ vbus-supply = <&vbus_sled2>;
+
connector {
compatible = "usb-c-connector";
label = "USB-C";
- power-role = "dual";
- try-power-role = "sink";
- data-role = "dual";
- source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
- sink-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)
- PDO_VAR(3000, 12000, 3000)
- PDO_PPS_APDO(3000, 11000, 3000)>;
- op-sink-microwatt = <10000000>;
+ power-role = "source";
+ data-role = "host";
+ pd-disable;
+ typec-power-opmode = "default";
};
};
@@ -474,17 +563,17 @@
compatible = "fcs,fusb302";
reg = <0x22>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <ASPEED_GPIO(B, 7) IRQ_TYPE_LEVEL_LOW>;
+ vbus-supply = <&vbus_sled3>;
+
connector {
compatible = "usb-c-connector";
label = "USB-C";
- power-role = "dual";
- try-power-role = "sink";
- data-role = "dual";
- source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
- sink-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)
- PDO_VAR(3000, 12000, 3000)
- PDO_PPS_APDO(3000, 11000, 3000)>;
- op-sink-microwatt = <10000000>;
+ power-role = "source";
+ data-role = "host";
+ pd-disable;
+ typec-power-opmode = "default";
};
};
@@ -560,17 +649,17 @@
compatible = "fcs,fusb302";
reg = <0x22>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <ASPEED_GPIO(S, 7) IRQ_TYPE_LEVEL_LOW>;
+ vbus-supply = <&vbus_sled4>;
+
connector {
compatible = "usb-c-connector";
label = "USB-C";
- power-role = "dual";
- try-power-role = "sink";
- data-role = "dual";
- source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
- sink-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)
- PDO_VAR(3000, 12000, 3000)
- PDO_PPS_APDO(3000, 11000, 3000)>;
- op-sink-microwatt = <10000000>;
+ power-role = "source";
+ data-role = "host";
+ pd-disable;
+ typec-power-opmode = "default";
};
};
@@ -646,17 +735,17 @@
compatible = "fcs,fusb302";
reg = <0x22>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <ASPEED_GPIO(Y, 3) IRQ_TYPE_LEVEL_LOW>;
+ vbus-supply = <&vbus_sled5>;
+
connector {
compatible = "usb-c-connector";
label = "USB-C";
- power-role = "dual";
- try-power-role = "sink";
- data-role = "dual";
- source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
- sink-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)
- PDO_VAR(3000, 12000, 3000)
- PDO_PPS_APDO(3000, 11000, 3000)>;
- op-sink-microwatt = <10000000>;
+ power-role = "source";
+ data-role = "host";
+ pd-disable;
+ typec-power-opmode = "default";
};
};
@@ -732,17 +821,17 @@
compatible = "fcs,fusb302";
reg = <0x22>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <ASPEED_GPIO(I, 7) IRQ_TYPE_LEVEL_LOW>;
+ vbus-supply = <&vbus_sled6>;
+
connector {
compatible = "usb-c-connector";
label = "USB-C";
- power-role = "dual";
- try-power-role = "sink";
- data-role = "dual";
- source-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)>;
- sink-pdos = <PDO_FIXED(5000, 3000, PDO_FIXED_USB_COMM)
- PDO_VAR(3000, 12000, 3000)
- PDO_PPS_APDO(3000, 11000, 3000)>;
- op-sink-microwatt = <10000000>;
+ power-role = "source";
+ data-role = "host";
+ pd-disable;
+ typec-power-opmode = "default";
};
};
@@ -863,6 +952,9 @@
};
&gpio0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpiov2_unbiased_default>;
+
gpio-line-names =
/*A0-A7*/ "","","","","","","","",
/*B0-B7*/ "FUSB302_SLED1_INT_N","FUSB302_SLED2_INT_N",
@@ -892,11 +984,11 @@
/*M0-M7*/ "ALERT_SLED1_N","ALERT_SLED2_N",
"ALERT_SLED3_N","ALERT_SLED4_N",
"ALERT_SLED5_N","ALERT_SLED6_N",
- "","",
+ "","USB_DEBUG_PWR_BTN_N",
/*N0-N7*/ "LED_POSTCODE_0","LED_POSTCODE_1",
"LED_POSTCODE_2","LED_POSTCODE_3",
"LED_POSTCODE_4","LED_POSTCODE_5",
- "LED_POSTCODE_5","LED_POSTCODE_7",
+ "LED_POSTCODE_6","LED_POSTCODE_7",
/*O0-O7*/ "","","","",
"","BOARD_ID0","BOARD_ID1","BOARD_ID2",
/*P0-P7*/ "","","","","","","","BMC_HEARTBEAT",
@@ -953,3 +1045,22 @@
&ehci0 {
status = "okay";
};
+
+&ehci1 {
+ status = "okay";
+};
+
+&emmc_controller {
+ status = "okay";
+};
+
+&emmc {
+ status = "okay";
+};
+
+&pinctrl {
+ pinctrl_gpiov2_unbiased_default: gpiov2 {
+ pins = "AD14";
+ bias-disable;
+ };
+};
diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-cloudripper.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-cloudripper.dts
index 9c6271a17ae8..5cd060029ea9 100644
--- a/arch/arm/boot/dts/aspeed-bmc-facebook-cloudripper.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-facebook-cloudripper.dts
@@ -77,7 +77,7 @@
i2c55 = &imux55;
};
- spi_gpio: spi-gpio {
+ spi_gpio: spi {
num-chipselects = <2>;
cs-gpios = <&gpio0 ASPEED_GPIO(X, 0) GPIO_ACTIVE_LOW>,
<&gpio0 ASPEED_GPIO(X, 1) GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-elbert.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-elbert.dts
index 8e1a1d1b282d..b5cd4c7800b0 100644
--- a/arch/arm/boot/dts/aspeed-bmc-facebook-elbert.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-facebook-elbert.dts
@@ -44,7 +44,7 @@
stdout-path = &uart5;
};
- spi_gpio: spi-gpio {
+ spi_gpio: spi {
num-chipselects = <1>;
cs-gpios = <&gpio0 ASPEED_GPIO(X, 0) GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-fuji.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-fuji.dts
index af58a73bbc49..6b319f34a9b9 100644
--- a/arch/arm/boot/dts/aspeed-bmc-facebook-fuji.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-facebook-fuji.dts
@@ -207,7 +207,7 @@
i2c143 = &imux143;
};
- spi_gpio: spi-gpio {
+ spi_gpio: spi {
num-chipselects = <3>;
cs-gpios = <&gpio0 ASPEED_GPIO(X, 0) GPIO_ACTIVE_LOW>,
<0>, /* device reg=<1> does not exist */
diff --git a/arch/arm/boot/dts/aspeed-bmc-facebook-wedge400.dts b/arch/arm/boot/dts/aspeed-bmc-facebook-wedge400.dts
index a901c8be49b9..ed305948386f 100644
--- a/arch/arm/boot/dts/aspeed-bmc-facebook-wedge400.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-facebook-wedge400.dts
@@ -67,7 +67,7 @@
* full-duplex SPI transactions are not supported by ASPEED SPI
* Controllers.
*/
- spi_gpio: spi-gpio {
+ spi_gpio: spi {
status = "okay";
compatible = "spi-gpio";
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/aspeed-bmc-ibm-bonnell.dts b/arch/arm/boot/dts/aspeed-bmc-ibm-bonnell.dts
new file mode 100644
index 000000000000..d1971ddf06a5
--- /dev/null
+++ b/arch/arm/boot/dts/aspeed-bmc-ibm-bonnell.dts
@@ -0,0 +1,921 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// Copyright 2022 IBM Corp.
+/dts-v1/;
+
+#include "aspeed-g6.dtsi"
+#include <dt-bindings/gpio/aspeed-gpio.h>
+#include <dt-bindings/i2c/i2c.h>
+#include <dt-bindings/leds/leds-pca955x.h>
+
+/ {
+ model = "Bonnell";
+ compatible = "ibm,bonnell-bmc", "aspeed,ast2600";
+
+ aliases {
+ i2c100 = &cfam0_i2c0;
+ i2c101 = &cfam0_i2c1;
+ i2c110 = &cfam0_i2c10;
+ i2c111 = &cfam0_i2c11;
+ i2c112 = &cfam0_i2c12;
+ i2c113 = &cfam0_i2c13;
+ i2c114 = &cfam0_i2c14;
+ i2c115 = &cfam0_i2c15;
+ i2c202 = &cfam1_i2c2;
+ i2c203 = &cfam1_i2c3;
+ i2c210 = &cfam1_i2c10;
+ i2c211 = &cfam1_i2c11;
+ i2c214 = &cfam1_i2c14;
+ i2c215 = &cfam1_i2c15;
+ i2c216 = &cfam1_i2c16;
+ i2c217 = &cfam1_i2c17;
+
+ serial4 = &uart5;
+ i2c16 = &i2c11mux0chn0;
+ i2c17 = &i2c11mux0chn1;
+ i2c18 = &i2c11mux0chn2;
+ i2c19 = &i2c11mux0chn3;
+
+ spi10 = &cfam0_spi0;
+ spi11 = &cfam0_spi1;
+ spi12 = &cfam0_spi2;
+ spi13 = &cfam0_spi3;
+ spi20 = &cfam1_spi0;
+ spi21 = &cfam1_spi1;
+ spi22 = &cfam1_spi2;
+ spi23 = &cfam1_spi3;
+
+ };
+
+ chosen {
+ stdout-path = &uart5;
+ bootargs = "console=ttyS4,115200n8 earlycon";
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x40000000>;
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ ramoops@b3e00000 {
+ compatible = "ramoops";
+ reg = <0xb3e00000 0x200000>; /* 16 * (4 * 0x8000) */
+ record-size = <0x8000>;
+ console-size = <0x8000>;
+ ftrace-size = <0x8000>;
+ pmsg-size = <0x8000>;
+ max-reason = <3>; /* KMSG_DUMP_EMERG */
+ };
+
+ /* LPC FW cycle bridge region requires natural alignment */
+ flash_memory: region@b4000000 {
+ no-map;
+ reg = <0xb4000000 0x04000000>; /* 64M */
+ };
+
+ /* VGA region is dictated by hardware strapping */
+ vga_memory: region@bf000000 {
+ no-map;
+ compatible = "shared-dma-pool";
+ reg = <0xbf000000 0x01000000>; /* 16M */
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ fan0 {
+ gpios = <&gpio0 ASPEED_GPIO(G, 0) GPIO_ACTIVE_LOW>;
+ };
+
+ fan1 {
+ gpios = <&gpio0 ASPEED_GPIO(G, 1) GPIO_ACTIVE_LOW>;
+ };
+
+ rear-enc-id0 {
+ gpios = <&gpio0 ASPEED_GPIO(H, 2) GPIO_ACTIVE_LOW>;
+ };
+
+ rear-enc-fault0 {
+ gpios = <&gpio0 ASPEED_GPIO(H, 3) GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ gpio-keys-polled {
+ compatible = "gpio-keys-polled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ poll-interval = <1000>;
+
+ fan0-presence {
+ label = "fan0-presence";
+ gpios = <&gpio0 ASPEED_GPIO(F, 4) GPIO_ACTIVE_LOW>;
+ linux,code = <6>;
+ };
+
+ fan1-presence {
+ label = "fan1-presence";
+ gpios = <&gpio0 ASPEED_GPIO(F, 5) GPIO_ACTIVE_LOW>;
+ linux,code = <7>;
+ };
+ };
+
+ iio-hwmon-battery {
+ compatible = "iio-hwmon";
+ io-channels = <&adc1 7>;
+ };
+};
+
+&adc1 {
+ status = "okay";
+ aspeed,int-vref-microvolt = <2500000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_adc8_default &pinctrl_adc9_default
+ &pinctrl_adc10_default &pinctrl_adc11_default
+ &pinctrl_adc12_default &pinctrl_adc13_default
+ &pinctrl_adc14_default &pinctrl_adc15_default>;
+};
+
+&ehci1 {
+ status = "okay";
+};
+
+&uhci {
+ status = "okay";
+};
+
+&gpio0 {
+ gpio-line-names =
+ /*A0-A7*/ "","","","","","","","",
+ /*B0-B7*/ "","","","","","","checkstop","",
+ /*C0-C7*/ "","","","","","","","",
+ /*D0-D7*/ "","","","","","","","",
+ /*E0-E7*/ "","","","","","","","",
+ /*F0-F7*/ "","","rtc-battery-voltage-read-enable","reset-cause-pinhole","","","","",
+ /*G0-G7*/ "fan0","fan1","","","","","","",
+ /*H0-H7*/ "","","rear-enc-id0","rear-enc-fault0","","","","",
+ /*I0-I7*/ "","","","","","","bmc-secure-boot","",
+ /*J0-J7*/ "","","","","","","","",
+ /*K0-K7*/ "","","","","","","","",
+ /*L0-L7*/ "","","","","","","","",
+ /*M0-M7*/ "","","","","","","","",
+ /*N0-N7*/ "","","","","","","","",
+ /*O0-O7*/ "","","","usb-power","","","","",
+ /*P0-P7*/ "","","","","","","","",
+ /*Q0-Q7*/ "cfam-reset","","regulator-standby-faulted","","","","","",
+ /*R0-R7*/ "bmc-tpm-reset","power-chassis-control","power-chassis-good","","","","","",
+ /*S0-S7*/ "presence-ps0","presence-ps1","","","power-ffs-sync-history","","","",
+ /*T0-T7*/ "","","","","","","","",
+ /*U0-U7*/ "","","","","","","","",
+ /*V0-V7*/ "","","","","","","","",
+ /*W0-W7*/ "","","","","","","","",
+ /*X0-X7*/ "","","","","","","","",
+ /*Y0-Y7*/ "","","","","","","","",
+ /*Z0-Z7*/ "","","","","","","","";
+
+ usb_power {
+ gpio-hog;
+ gpios = <ASPEED_GPIO(O, 3) GPIO_ACTIVE_LOW>;
+ output-high;
+ };
+};
+
+&emmc_controller {
+ status = "okay";
+};
+
+&pinctrl_emmc_default {
+ bias-disable;
+};
+
+&emmc {
+ status = "okay";
+ clk-phase-mmc-hs200 = <180>, <180>;
+};
+
+&fsim0 {
+ status = "okay";
+
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cfam-reset-gpios = <&gpio0 ASPEED_GPIO(Q, 0) GPIO_ACTIVE_HIGH>;
+
+ cfam@0,0 {
+ reg = <0 0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ chip-id = <0>;
+
+ scom@1000 {
+ compatible = "ibm,fsi2pib";
+ reg = <0x1000 0x400>;
+ };
+
+ i2c@1800 {
+ compatible = "ibm,fsi-i2c-master";
+ reg = <0x1800 0x400>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cfam0_i2c0: i2c-bus@0 {
+ reg = <0>; /* OMI01 */
+ };
+
+ cfam0_i2c1: i2c-bus@1 {
+ reg = <1>; /* OMI23 */
+ };
+
+ cfam0_i2c10: i2c-bus@a {
+ reg = <10>; /* OP3A */
+ };
+
+ cfam0_i2c11: i2c-bus@b {
+ reg = <11>; /* OP3B */
+ };
+
+ cfam0_i2c12: i2c-bus@c {
+ reg = <12>; /* OP4A */
+ };
+
+ cfam0_i2c13: i2c-bus@d {
+ reg = <13>; /* OP4B */
+ };
+
+ cfam0_i2c14: i2c-bus@e {
+ reg = <14>; /* OP5A */
+ };
+
+ cfam0_i2c15: i2c-bus@f {
+ reg = <15>; /* OP5B */
+ };
+ };
+
+ fsi2spi@1c00 {
+ compatible = "ibm,fsi2spi";
+ reg = <0x1c00 0x400>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cfam0_spi0: spi@0 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ eeprom@0 {
+ at25,byte-len = <0x80000>;
+ at25,addr-mode = <4>;
+ at25,page-size = <256>;
+
+ compatible = "atmel,at25";
+ reg = <0>;
+ spi-max-frequency = <1000000>;
+ };
+ };
+
+ cfam0_spi1: spi@20 {
+ reg = <0x20>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ eeprom@0 {
+ at25,byte-len = <0x80000>;
+ at25,addr-mode = <4>;
+ at25,page-size = <256>;
+
+ compatible = "atmel,at25";
+ reg = <0>;
+ spi-max-frequency = <1000000>;
+ };
+ };
+
+ cfam0_spi2: spi@40 {
+ reg = <0x40>;
+ compatible = "ibm,fsi2spi-restricted";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ eeprom@0 {
+ at25,byte-len = <0x80000>;
+ at25,addr-mode = <4>;
+ at25,page-size = <256>;
+
+ compatible = "atmel,at25";
+ reg = <0>;
+ spi-max-frequency = <1000000>;
+ };
+ };
+
+ cfam0_spi3: spi@60 {
+ reg = <0x60>;
+ compatible = "ibm,fsi2spi-restricted";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ eeprom@0 {
+ at25,byte-len = <0x80000>;
+ at25,addr-mode = <4>;
+ at25,page-size = <256>;
+
+ compatible = "atmel,at25";
+ reg = <0>;
+ spi-max-frequency = <1000000>;
+ };
+ };
+ };
+
+ sbefifo@2400 {
+ compatible = "ibm,p9-sbefifo";
+ reg = <0x2400 0x400>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fsi_occ0: occ {
+ compatible = "ibm,p10-occ";
+
+ occ-hwmon {
+ compatible = "ibm,p10-occ-hwmon";
+ ibm,no-poll-on-init;
+ };
+ };
+ };
+
+ fsi_hub0: hub@3400 {
+ compatible = "fsi-master-hub";
+ reg = <0x3400 0x400>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ };
+ };
+};
+
+&fsi_hub0 {
+ cfam@1,0 {
+ reg = <1 0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ chip-id = <1>;
+
+ scom@1000 {
+ compatible = "ibm,fsi2pib";
+ reg = <0x1000 0x400>;
+ };
+
+ i2c@1800 {
+ compatible = "ibm,fsi-i2c-master";
+ reg = <0x1800 0x400>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cfam1_i2c2: i2c-bus@2 {
+ reg = <2>; /* OMI45 */
+ };
+
+ cfam1_i2c3: i2c-bus@3 {
+ reg = <3>; /* OMI67 */
+ };
+
+ cfam1_i2c10: i2c-bus@a {
+ reg = <10>; /* OP3A */
+ };
+
+ cfam1_i2c11: i2c-bus@b {
+ reg = <11>; /* OP3B */
+ };
+
+ cfam1_i2c14: i2c-bus@e {
+ reg = <14>; /* OP5A */
+ };
+
+ cfam1_i2c15: i2c-bus@f {
+ reg = <15>; /* OP5B */
+ };
+
+ cfam1_i2c16: i2c-bus@10 {
+ reg = <16>; /* OP6A */
+ };
+
+ cfam1_i2c17: i2c-bus@11 {
+ reg = <17>; /* OP6B */
+ };
+ };
+
+ fsi2spi@1c00 {
+ compatible = "ibm,fsi2spi";
+ reg = <0x1c00 0x400>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cfam1_spi0: spi@0 {
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ eeprom@0 {
+ at25,byte-len = <0x80000>;
+ at25,addr-mode = <4>;
+ at25,page-size = <256>;
+
+ compatible = "atmel,at25";
+ reg = <0>;
+ spi-max-frequency = <1000000>;
+ };
+ };
+
+ cfam1_spi1: spi@20 {
+ reg = <0x20>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ eeprom@0 {
+ at25,byte-len = <0x80000>;
+ at25,addr-mode = <4>;
+ at25,page-size = <256>;
+
+ compatible = "atmel,at25";
+ reg = <0>;
+ spi-max-frequency = <1000000>;
+ };
+ };
+
+ cfam1_spi2: spi@40 {
+ reg = <0x40>;
+ compatible = "ibm,fsi2spi-restricted";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ eeprom@0 {
+ at25,byte-len = <0x80000>;
+ at25,addr-mode = <4>;
+ at25,page-size = <256>;
+
+ compatible = "atmel,at25";
+ reg = <0>;
+ spi-max-frequency = <1000000>;
+ };
+ };
+
+ cfam1_spi3: spi@60 {
+ reg = <0x60>;
+ compatible = "ibm,fsi2spi-restricted";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ eeprom@0 {
+ at25,byte-len = <0x80000>;
+ at25,addr-mode = <4>;
+ at25,page-size = <256>;
+
+ compatible = "atmel,at25";
+ reg = <0>;
+ spi-max-frequency = <1000000>;
+ };
+ };
+ };
+
+ sbefifo@2400 {
+ compatible = "ibm,p9-sbefifo";
+ reg = <0x2400 0x400>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fsi_occ1: occ {
+ compatible = "ibm,p10-occ";
+
+ occ-hwmon {
+ compatible = "ibm,p10-occ-hwmon";
+ ibm,no-poll-on-init;
+ };
+ };
+ };
+
+ fsi_hub1: hub@3400 {
+ compatible = "fsi-master-hub";
+ reg = <0x3400 0x400>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ no-scan-on-init;
+ };
+ };
+};
+
+&ibt {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ eeprom@51 {
+ compatible = "atmel,24c64";
+ reg = <0x51>;
+ };
+
+ tca9554@20 {
+ compatible = "ti,tca9554";
+ reg = <0x20>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ gpio-line-names = "",
+ "RUSSEL_FW_I2C_ENABLE_N",
+ "RUSSEL_OPPANEL_PRESENCE_N",
+ "BLYTH_OPPANEL_PRESENCE_N",
+ "CPU_TPM_CARD_PRESENT_N",
+ "",
+ "",
+ "DASD_BP_PRESENT_N";
+ };
+};
+
+&i2c1 {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+
+ ucd90160@64 {
+ compatible = "ti,ucd90160";
+ reg = <0x64>;
+ };
+};
+
+&i2c3 {
+ status = "okay";
+
+ power-supply@58 {
+ compatible = "ibm,cffps";
+ reg = <0x58>;
+ };
+
+ power-supply@59 {
+ compatible = "ibm,cffps";
+ reg = <0x59>;
+ };
+};
+
+&i2c4 {
+ status = "okay";
+};
+
+&i2c5 {
+ status = "okay";
+};
+
+&i2c6 {
+ status = "okay";
+};
+
+&i2c7 {
+ multi-master;
+ status = "okay";
+
+ si7021-a20@40 {
+ compatible = "silabs,si7020";
+ reg = <0x40>;
+ };
+
+ tmp275@48 {
+ compatible = "ti,tmp275";
+ reg = <0x48>;
+ };
+
+ eeprom@50 {
+ compatible = "atmel,24c64";
+ reg = <0x50>;
+ };
+
+ eeprom@51 {
+ compatible = "atmel,24c64";
+ reg = <0x51>;
+ };
+
+ max31785@52 {
+ compatible = "maxim,max31785a";
+ reg = <0x52>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ fan0: fan@0 {
+ compatible = "pmbus-fan";
+ reg = <0>;
+ tach-pulses = <2>;
+ };
+
+ fan1: fan@1 {
+ compatible = "pmbus-fan";
+ reg = <1>;
+ tach-pulses = <2>;
+ };
+ };
+
+ pca9551@60 {
+ compatible = "nxp,pca9551";
+ reg = <0x60>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ led@0 {
+ label = "front-sys-id0";
+ reg = <0>;
+ retain-state-shutdown;
+ default-state = "keep";
+ type = <PCA955X_TYPE_LED>;
+ };
+
+ led@1 {
+ label = "front-check-log0";
+ reg = <1>;
+ retain-state-shutdown;
+ default-state = "keep";
+ type = <PCA955X_TYPE_LED>;
+ };
+
+ led@2 {
+ label = "front-enc-fault1";
+ reg = <2>;
+ retain-state-shutdown;
+ default-state = "keep";
+ type = <PCA955X_TYPE_LED>;
+ };
+
+ led@3 {
+ label = "front-sys-pwron0";
+ reg = <3>;
+ retain-state-shutdown;
+ default-state = "keep";
+ type = <PCA955X_TYPE_LED>;
+ };
+ };
+
+ ibm-panel@62 {
+ compatible = "ibm,op-panel";
+ reg = <(0x62 | I2C_OWN_SLAVE_ADDRESS)>;
+ };
+
+ dps: dps310@76 {
+ compatible = "infineon,dps310";
+ reg = <0x76>;
+ #io-channel-cells = <0>;
+ };
+};
+
+&i2c8 {
+ status = "okay";
+
+ rtc@32 {
+ compatible = "epson,rx8900";
+ reg = <0x32>;
+ };
+
+ tmp275@48 {
+ compatible = "ti,tmp275";
+ reg = <0x48>;
+ };
+
+ eeprom@50 {
+ compatible = "atmel,24c64";
+ reg = <0x50>;
+ };
+
+ pca9551@60 {
+ compatible = "nxp,pca9551";
+ reg = <0x60>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ gpio-line-names = "",
+ "APSS_RESET_N",
+ "",
+ "N_MODE_CPU_N",
+ "",
+ "",
+ "P10_DCM_PRESENT",
+ "";
+ };
+};
+
+&i2c9 {
+ status = "okay";
+
+ tmp423a@4c {
+ compatible = "ti,tmp423";
+ reg = <0x4c>;
+ };
+};
+
+&i2c10 {
+ status = "okay";
+};
+
+&i2c11 {
+ status = "okay";
+
+ tca9554@20 {
+ compatible = "ti,tca9554";
+ reg = <0x20>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ gpio-line-names = "BOOT_RCVRY_TWI",
+ "BOOT_RCVRY_UART",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "PE_SWITCH_RSTB_N";
+ };
+
+ tmp435@4c {
+ compatible = "ti,tmp435";
+ reg = <0x4c>;
+ };
+
+ pca9849@75 {
+ compatible = "nxp,pca849";
+ reg = <0x75>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+ i2c-mux-idle-disconnect;
+
+ i2c11mux0chn0: i2c@0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0>;
+ };
+
+ i2c11mux0chn1: i2c@1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <1>;
+ };
+
+ i2c11mux0chn2: i2c@2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <2>;
+ };
+
+ i2c11mux0chn3: i2c@3 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <3>;
+ };
+ };
+};
+
+&i2c12 {
+ status = "okay";
+
+ tpm@2e {
+ compatible = "nuvoton,npct75x";
+ reg = <0x2e>;
+ };
+
+ eeprom@50 {
+ compatible = "atmel,24c64";
+ reg = <0x50>;
+ };
+};
+
+&i2c13 {
+ status = "okay";
+
+ eeprom@50 {
+ compatible = "atmel,24c64";
+ reg = <0x50>;
+ };
+
+ pca9551@60 {
+ compatible = "nxp,pca9551";
+ reg = <0x60>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ led@0 {
+ label = "nvme0";
+ reg = <0>;
+ retain-state-shutdown;
+ default-state = "keep";
+ type = <PCA955X_TYPE_LED>;
+ };
+
+ led@1 {
+ label = "nvme1";
+ reg = <1>;
+ retain-state-shutdown;
+ default-state = "keep";
+ type = <PCA955X_TYPE_LED>;
+ };
+
+ led@2 {
+ label = "nvme2";
+ reg = <2>;
+ retain-state-shutdown;
+ default-state = "keep";
+ type = <PCA955X_TYPE_LED>;
+ };
+
+ led@3 {
+ label = "nvme3";
+ reg = <3>;
+ retain-state-shutdown;
+ default-state = "keep";
+ type = <PCA955X_TYPE_LED>;
+ };
+ };
+};
+
+&i2c14 {
+ status = "okay";
+};
+
+&i2c15 {
+ status = "okay";
+};
+
+&vuart1 {
+ status = "okay";
+};
+
+&vuart2 {
+ status = "okay";
+};
+
+&lpc_ctrl {
+ status = "okay";
+ memory-region = <&flash_memory>;
+};
+
+&mac2 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rmii3_default>;
+ clocks = <&syscon ASPEED_CLK_GATE_MAC3CLK>,
+ <&syscon ASPEED_CLK_MAC3RCLK>;
+ clock-names = "MACCLK", "RCLK";
+ use-ncsi;
+};
+
+&mac3 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_rmii4_default>;
+ clocks = <&syscon ASPEED_CLK_GATE_MAC4CLK>,
+ <&syscon ASPEED_CLK_MAC4RCLK>;
+ clock-names = "MACCLK", "RCLK";
+ use-ncsi;
+};
+
+&wdt1 {
+ aspeed,reset-type = "none";
+ aspeed,external-signal;
+ aspeed,ext-push-pull;
+ aspeed,ext-active-high;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdtrst1_default>;
+};
+
+&wdt2 {
+ status = "okay";
+};
+
+&xdma {
+ status = "okay";
+ memory-region = <&vga_memory>;
+};
+
+&kcs2 {
+ status = "okay";
+ aspeed,lpc-io-reg = <0xca8 0xcac>;
+};
+
+&kcs3 {
+ status = "okay";
+ aspeed,lpc-io-reg = <0xca2>;
+ aspeed,lpc-interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+};
diff --git a/arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts b/arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts
index a6a2bc3b855c..1448ea895be4 100644
--- a/arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-ibm-everest.dts
@@ -162,16 +162,9 @@
#size-cells = <1>;
ranges;
- /* LPC FW cycle bridge region requires natural alignment */
- flash_memory: region@b8000000 {
- no-map;
- reg = <0xb8000000 0x04000000>; /* 64M */
- };
-
- /* 48MB region from the end of flash to start of vga memory */
- ramoops@bc000000 {
+ ramoops@b3e00000 {
compatible = "ramoops";
- reg = <0xbc000000 0x200000>; /* 16 * (4 * 0x8000) */
+ reg = <0xb3e00000 0x200000>; /* 16 * (4 * 0x8000) */
record-size = <0x8000>;
console-size = <0x8000>;
ftrace-size = <0x8000>;
@@ -179,6 +172,12 @@
max-reason = <3>; /* KMSG_DUMP_EMERG */
};
+ /* LPC FW cycle bridge region requires natural alignment */
+ flash_memory: region@b4000000 {
+ no-map;
+ reg = <0xb4000000 0x04000000>; /* 64M */
+ };
+
/* VGA region is dictated by hardware strapping */
vga_memory: region@bf000000 {
no-map;
@@ -2551,6 +2550,11 @@
fsi_occ0: occ {
compatible = "ibm,p10-occ";
+
+ occ-hwmon {
+ compatible = "ibm,p10-occ-hwmon";
+ ibm,no-poll-on-init;
+ };
};
};
@@ -2695,6 +2699,11 @@
fsi_occ1: occ {
compatible = "ibm,p10-occ";
+
+ occ-hwmon {
+ compatible = "ibm,p10-occ-hwmon";
+ ibm,no-poll-on-init;
+ };
};
};
@@ -2839,6 +2848,11 @@
fsi_occ2: occ {
compatible = "ibm,p10-occ";
+
+ occ-hwmon {
+ compatible = "ibm,p10-occ-hwmon";
+ ibm,no-poll-on-init;
+ };
};
};
@@ -2983,6 +2997,11 @@
fsi_occ3: occ {
compatible = "ibm,p10-occ";
+
+ occ-hwmon {
+ compatible = "ibm,p10-occ-hwmon";
+ ibm,no-poll-on-init;
+ };
};
};
@@ -3127,6 +3146,11 @@
fsi_occ4: occ {
compatible = "ibm,p10-occ";
+
+ occ-hwmon {
+ compatible = "ibm,p10-occ-hwmon";
+ ibm,no-poll-on-init;
+ };
};
};
@@ -3271,6 +3295,11 @@
fsi_occ5: occ {
compatible = "ibm,p10-occ";
+
+ occ-hwmon {
+ compatible = "ibm,p10-occ-hwmon";
+ ibm,no-poll-on-init;
+ };
};
};
@@ -3415,6 +3444,11 @@
fsi_occ6: occ {
compatible = "ibm,p10-occ";
+
+ occ-hwmon {
+ compatible = "ibm,p10-occ-hwmon";
+ ibm,no-poll-on-init;
+ };
};
};
@@ -3559,6 +3593,11 @@
fsi_occ7: occ {
compatible = "ibm,p10-occ";
+
+ occ-hwmon {
+ compatible = "ibm,p10-occ-hwmon";
+ ibm,no-poll-on-init;
+ };
};
};
diff --git a/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts b/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts
index bf59a9962379..20ef958698ec 100644
--- a/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts
+++ b/arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts
@@ -95,14 +95,9 @@
#size-cells = <1>;
ranges;
- flash_memory: region@b8000000 {
- no-map;
- reg = <0xb8000000 0x04000000>; /* 64M */
- };
-
- ramoops@bc000000 {
+ ramoops@b3e00000 {
compatible = "ramoops";
- reg = <0xbc000000 0x200000>; /* 16 * (4 * 0x8000) */
+ reg = <0xb3e00000 0x200000>; /* 16 * (4 * 0x8000) */
record-size = <0x8000>;
console-size = <0x8000>;
ftrace-size = <0x8000>;
@@ -110,6 +105,13 @@
max-reason = <3>; /* KMSG_DUMP_EMERG */
};
+ /* LPC FW cycle bridge region requires natural alignment */
+ flash_memory: region@b4000000 {
+ no-map;
+ reg = <0xb4000000 0x04000000>; /* 64M */
+ };
+
+ /* VGA region is dictated by hardware strapping */
vga_memory: region@bf000000 {
no-map;
compatible = "shared-dma-pool";
@@ -442,6 +444,11 @@
fsi_occ0: occ {
compatible = "ibm,p10-occ";
+
+ occ-hwmon {
+ compatible = "ibm,p10-occ-hwmon";
+ ibm,no-poll-on-init;
+ };
};
};
@@ -586,6 +593,11 @@
fsi_occ1: occ {
compatible = "ibm,p10-occ";
+
+ occ-hwmon {
+ compatible = "ibm,p10-occ-hwmon";
+ ibm,no-poll-on-init;
+ };
};
};
@@ -730,6 +742,11 @@
fsi_occ2: occ {
compatible = "ibm,p10-occ";
+
+ occ-hwmon {
+ compatible = "ibm,p10-occ-hwmon";
+ ibm,no-poll-on-init;
+ };
};
};
@@ -874,6 +891,11 @@
fsi_occ3: occ {
compatible = "ibm,p10-occ";
+
+ occ-hwmon {
+ compatible = "ibm,p10-occ-hwmon";
+ ibm,no-poll-on-init;
+ };
};
};
@@ -995,32 +1017,6 @@
reg = <0x4a>;
};
- pca9551@60 {
- compatible = "nxp,pca9551";
- reg = <0x60>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- gpio-controller;
- #gpio-cells = <2>;
-
- led@0 {
- label = "cablecard0-cxp-top";
- reg = <0>;
- retain-state-shutdown;
- default-state = "keep";
- type = <PCA955X_TYPE_LED>;
- };
-
- led@1 {
- label = "cablecard0-cxp-bot";
- reg = <1>;
- retain-state-shutdown;
- default-state = "keep";
- type = <PCA955X_TYPE_LED>;
- };
- };
-
pca9546@70 {
compatible = "nxp,pca9546";
reg = <0x70>;
@@ -1038,6 +1034,32 @@
compatible = "atmel,24c64";
reg = <0x50>;
};
+
+ pca9551@60 {
+ compatible = "nxp,pca9551";
+ reg = <0x60>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ led@0 {
+ label = "cablecard0-cxp-top";
+ reg = <0>;
+ retain-state-shutdown;
+ default-state = "keep";
+ type = <PCA955X_TYPE_LED>;
+ };
+
+ led@1 {
+ label = "cablecard0-cxp-bot";
+ reg = <1>;
+ retain-state-shutdown;
+ default-state = "keep";
+ type = <PCA955X_TYPE_LED>;
+ };
+ };
};
i2c4mux0chn1: i2c@1 {
@@ -1077,58 +1099,6 @@
reg = <0x49>;
};
- pca9551@60 {
- compatible = "nxp,pca9551";
- reg = <0x60>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- gpio-controller;
- #gpio-cells = <2>;
-
- led@0 {
- label = "cablecard3-cxp-top";
- reg = <0>;
- retain-state-shutdown;
- default-state = "keep";
- type = <PCA955X_TYPE_LED>;
- };
-
- led@1 {
- label = "cablecard3-cxp-bot";
- reg = <1>;
- retain-state-shutdown;
- default-state = "keep";
- type = <PCA955X_TYPE_LED>;
- };
- };
-
- pca9551@61 {
- compatible = "nxp,pca9551";
- reg = <0x61>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- gpio-controller;
- #gpio-cells = <2>;
-
- led@0 {
- label = "cablecard4-cxp-top";
- reg = <0>;
- retain-state-shutdown;
- default-state = "keep";
- type = <PCA955X_TYPE_LED>;
- };
-
- led@1 {
- label = "cablecard4-cxp-bot";
- reg = <1>;
- retain-state-shutdown;
- default-state = "keep";
- type = <PCA955X_TYPE_LED>;
- };
- };
-
pca9546@70 {
compatible = "nxp,pca9546";
reg = <0x70>;
@@ -1146,6 +1116,32 @@
compatible = "atmel,24c64";
reg = <0x50>;
};
+
+ pca9551@60 {
+ compatible = "nxp,pca9551";
+ reg = <0x60>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ led@0 {
+ label = "cablecard3-cxp-top";
+ reg = <0>;
+ retain-state-shutdown;
+ default-state = "keep";
+ type = <PCA955X_TYPE_LED>;
+ };
+
+ led@1 {
+ label = "cablecard3-cxp-bot";
+ reg = <1>;
+ retain-state-shutdown;
+ default-state = "keep";
+ type = <PCA955X_TYPE_LED>;
+ };
+ };
};
i2c5mux0chn1: i2c@1 {
@@ -1157,6 +1153,32 @@
compatible = "atmel,24c64";
reg = <0x51>;
};
+
+ pca9551@61 {
+ compatible = "nxp,pca9551";
+ reg = <0x61>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ led@0 {
+ label = "cablecard4-cxp-top";
+ reg = <0>;
+ retain-state-shutdown;
+ default-state = "keep";
+ type = <PCA955X_TYPE_LED>;
+ };
+
+ led@1 {
+ label = "cablecard4-cxp-bot";
+ reg = <1>;
+ retain-state-shutdown;
+ default-state = "keep";
+ type = <PCA955X_TYPE_LED>;
+ };
+ };
};
};
};
@@ -2009,32 +2031,6 @@
reg = <0x49>;
};
- pca9551@60 {
- compatible = "nxp,pca9551";
- reg = <0x60>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- gpio-controller;
- #gpio-cells = <2>;
-
- led@0 {
- label = "cablecard10-cxp-top";
- reg = <0>;
- retain-state-shutdown;
- default-state = "keep";
- type = <PCA955X_TYPE_LED>;
- };
-
- led@1 {
- label = "cablecard10-cxp-bot";
- reg = <1>;
- retain-state-shutdown;
- default-state = "keep";
- type = <PCA955X_TYPE_LED>;
- };
- };
-
pca9546@70 {
compatible = "nxp,pca9546";
reg = <0x70>;
@@ -2052,6 +2048,32 @@
compatible = "atmel,24c64";
reg = <0x50>;
};
+
+ pca9551@60 {
+ compatible = "nxp,pca9551";
+ reg = <0x60>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ led@0 {
+ label = "cablecard10-cxp-top";
+ reg = <0>;
+ retain-state-shutdown;
+ default-state = "keep";
+ type = <PCA955X_TYPE_LED>;
+ };
+
+ led@1 {
+ label = "cablecard10-cxp-bot";
+ reg = <1>;
+ retain-state-shutdown;
+ default-state = "keep";
+ type = <PCA955X_TYPE_LED>;
+ };
+ };
};
i2c11mux0chn1: i2c@1 {
diff --git a/arch/arm/boot/dts/aspeed-bmc-opp-mihawk.dts b/arch/arm/boot/dts/aspeed-bmc-opp-mihawk.dts
deleted file mode 100644
index 48776fb663fb..000000000000
--- a/arch/arm/boot/dts/aspeed-bmc-opp-mihawk.dts
+++ /dev/null
@@ -1,1381 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/dts-v1/;
-#include "aspeed-g5.dtsi"
-#include <dt-bindings/gpio/aspeed-gpio.h>
-#include <dt-bindings/leds/leds-pca955x.h>
-
-/ {
- model = "Mihawk BMC";
- compatible = "ibm,mihawk-bmc", "aspeed,ast2500";
-
- aliases {
- i2c215 = &bus6_mux215;
- i2c216 = &bus6_mux216;
- i2c217 = &bus6_mux217;
- i2c218 = &bus6_mux218;
- i2c219 = &bus6_mux219;
- i2c220 = &bus6_mux220;
- i2c221 = &bus6_mux221;
- i2c222 = &bus6_mux222;
- i2c223 = &bus7_mux223;
- i2c224 = &bus7_mux224;
- i2c225 = &bus7_mux225;
- i2c226 = &bus7_mux226;
- i2c227 = &bus7_mux227;
- i2c228 = &bus7_mux228;
- i2c229 = &bus7_mux229;
- i2c230 = &bus7_mux230;
- i2c231 = &bus9_mux231;
- i2c232 = &bus9_mux232;
- i2c233 = &bus9_mux233;
- i2c234 = &bus9_mux234;
- i2c235 = &bus9_mux235;
- i2c236 = &bus9_mux236;
- i2c237 = &bus9_mux237;
- i2c238 = &bus9_mux238;
- i2c239 = &bus10_mux239;
- i2c240 = &bus10_mux240;
- i2c241 = &bus10_mux241;
- i2c242 = &bus10_mux242;
- i2c243 = &bus10_mux243;
- i2c244 = &bus10_mux244;
- i2c245 = &bus10_mux245;
- i2c246 = &bus10_mux246;
- i2c247 = &bus12_mux247;
- i2c248 = &bus12_mux248;
- i2c249 = &bus12_mux249;
- i2c250 = &bus12_mux250;
- i2c251 = &bus13_mux251;
- i2c252 = &bus13_mux252;
- i2c253 = &bus13_mux253;
- i2c254 = &bus13_mux254;
- i2c255 = &bus13_mux255;
- i2c256 = &bus13_mux256;
- i2c257 = &bus13_mux257;
- i2c258 = &bus13_mux258;
- };
-
- chosen {
- stdout-path = &uart5;
- bootargs = "console=ttyS4,115200 earlycon";
- };
-
- memory@80000000 {
- reg = <0x80000000 0x20000000>;
- };
-
- reserved-memory {
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
-
- flash_memory: region@98000000 {
- no-map;
- reg = <0x98000000 0x04000000>; /* 64M */
- };
-
- gfx_memory: framebuffer {
- size = <0x01000000>;
- alignment = <0x01000000>;
- compatible = "shared-dma-pool";
- reusable;
- };
-
- video_engine_memory: jpegbuffer {
- size = <0x02000000>;
- alignment = <0x01000000>;
- compatible = "shared-dma-pool";
- reusable;
- };
- };
-
- gpio-keys {
- compatible = "gpio-keys";
-
- event-air-water {
- label = "air-water";
- gpios = <&gpio ASPEED_GPIO(F, 6) GPIO_ACTIVE_LOW>;
- linux,code = <ASPEED_GPIO(F, 6)>;
- };
-
- event-checkstop {
- label = "checkstop";
- gpios = <&gpio ASPEED_GPIO(J, 2) GPIO_ACTIVE_LOW>;
- linux,code = <ASPEED_GPIO(J, 2)>;
- };
-
- event-ps0-presence {
- label = "ps0-presence";
- gpios = <&gpio ASPEED_GPIO(Z, 2) GPIO_ACTIVE_LOW>;
- linux,code = <ASPEED_GPIO(Z, 2)>;
- };
-
- event-ps1-presence {
- label = "ps1-presence";
- gpios = <&gpio ASPEED_GPIO(Z, 0) GPIO_ACTIVE_LOW>;
- linux,code = <ASPEED_GPIO(Z, 0)>;
- };
-
- button-id {
- label = "id-button";
- gpios = <&gpio ASPEED_GPIO(F, 1) GPIO_ACTIVE_LOW>;
- linux,code = <ASPEED_GPIO(F, 1)>;
- };
- };
-
- gpio-keys-polled {
- compatible = "gpio-keys-polled";
- poll-interval = <1000>;
-
- event-fan0-presence {
- label = "fan0-presence";
- gpios = <&pca9552 9 GPIO_ACTIVE_LOW>;
- linux,code = <9>;
- };
-
- event-fan1-presence {
- label = "fan1-presence";
- gpios = <&pca9552 10 GPIO_ACTIVE_LOW>;
- linux,code = <10>;
- };
-
- event-fan2-presence {
- label = "fan2-presence";
- gpios = <&pca9552 11 GPIO_ACTIVE_LOW>;
- linux,code = <11>;
- };
-
- event-fan3-presence {
- label = "fan3-presence";
- gpios = <&pca9552 12 GPIO_ACTIVE_LOW>;
- linux,code = <12>;
- };
-
- event-fan4-presence {
- label = "fan4-presence";
- gpios = <&pca9552 13 GPIO_ACTIVE_LOW>;
- linux,code = <13>;
- };
-
- event-fan5-presence {
- label = "fan5-presence";
- gpios = <&pca9552 14 GPIO_ACTIVE_LOW>;
- linux,code = <14>;
- };
- };
-
- leds {
- compatible = "gpio-leds";
-
- front-fault {
- retain-state-shutdown;
- default-state = "keep";
- gpios = <&gpio ASPEED_GPIO(AA, 0) GPIO_ACTIVE_LOW>;
- };
-
- power-button {
- retain-state-shutdown;
- default-state = "keep";
- gpios = <&gpio ASPEED_GPIO(AA, 1) GPIO_ACTIVE_LOW>;
- };
-
- front-id {
- retain-state-shutdown;
- default-state = "keep";
- gpios = <&gpio ASPEED_GPIO(AA, 2) GPIO_ACTIVE_LOW>;
- };
-
-
- fan0 {
- retain-state-shutdown;
- default-state = "keep";
- gpios = <&pca9552 0 GPIO_ACTIVE_LOW>;
- };
-
- fan1 {
- retain-state-shutdown;
- default-state = "keep";
- gpios = <&pca9552 1 GPIO_ACTIVE_LOW>;
- };
-
- fan2 {
- retain-state-shutdown;
- default-state = "keep";
- gpios = <&pca9552 2 GPIO_ACTIVE_LOW>;
- };
-
- fan3 {
- retain-state-shutdown;
- default-state = "keep";
- gpios = <&pca9552 3 GPIO_ACTIVE_LOW>;
- };
-
- fan4 {
- retain-state-shutdown;
- default-state = "keep";
- gpios = <&pca9552 4 GPIO_ACTIVE_LOW>;
- };
-
- fan5 {
- retain-state-shutdown;
- default-state = "keep";
- gpios = <&pca9552 5 GPIO_ACTIVE_LOW>;
- };
- };
-
- fsi: gpio-fsi {
- compatible = "fsi-master-gpio", "fsi-master";
- #address-cells = <2>;
- #size-cells = <0>;
- no-gpio-delays;
-
- clock-gpios = <&gpio ASPEED_GPIO(E, 6) GPIO_ACTIVE_HIGH>;
- data-gpios = <&gpio ASPEED_GPIO(E, 7) GPIO_ACTIVE_HIGH>;
- mux-gpios = <&gpio ASPEED_GPIO(E, 5) GPIO_ACTIVE_HIGH>;
- enable-gpios = <&gpio ASPEED_GPIO(D, 0) GPIO_ACTIVE_HIGH>;
- trans-gpios = <&gpio ASPEED_GPIO(R, 2) GPIO_ACTIVE_HIGH>;
- };
- iio-hwmon-12v {
- compatible = "iio-hwmon";
- io-channels = <&adc 0>;
- };
-
- iio-hwmon-5v {
- compatible = "iio-hwmon";
- io-channels = <&adc 1>;
- };
-
- iio-hwmon-3v {
- compatible = "iio-hwmon";
- io-channels = <&adc 2>;
- };
-
- iio-hwmon-vdd0 {
- compatible = "iio-hwmon";
- io-channels = <&adc 3>;
- };
-
- iio-hwmon-vdd1 {
- compatible = "iio-hwmon";
- io-channels = <&adc 4>;
- };
-
- iio-hwmon-vcs0 {
- compatible = "iio-hwmon";
- io-channels = <&adc 5>;
- };
-
- iio-hwmon-vcs1 {
- compatible = "iio-hwmon";
- io-channels = <&adc 6>;
- };
-
- iio-hwmon-vdn0 {
- compatible = "iio-hwmon";
- io-channels = <&adc 7>;
- };
-
- iio-hwmon-vdn1 {
- compatible = "iio-hwmon";
- io-channels = <&adc 8>;
- };
-
- iio-hwmon-vio0 {
- compatible = "iio-hwmon";
- io-channels = <&adc 9>;
- };
-
- iio-hwmon-vio1 {
- compatible = "iio-hwmon";
- io-channels = <&adc 10>;
- };
-
- iio-hwmon-vddra {
- compatible = "iio-hwmon";
- io-channels = <&adc 11>;
- };
-
- iio-hwmon-battery {
- compatible = "iio-hwmon";
- io-channels = <&adc 12>;
- };
-
- iio-hwmon-vddrb {
- compatible = "iio-hwmon";
- io-channels = <&adc 13>;
- };
-
- iio-hwmon-vddrc {
- compatible = "iio-hwmon";
- io-channels = <&adc 14>;
- };
-
- iio-hwmon-vddrd {
- compatible = "iio-hwmon";
- io-channels = <&adc 15>;
- };
-};
-
-&pwm_tacho {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_pwm0_default &pinctrl_pwm1_default
- &pinctrl_pwm2_default &pinctrl_pwm3_default
- &pinctrl_pwm4_default &pinctrl_pwm5_default>;
-
- fan@0 {
- reg = <0x00>;
- aspeed,fan-tach-ch = /bits/ 8 <0x00>;
- };
-
- fan@1 {
- reg = <0x01>;
- aspeed,fan-tach-ch = /bits/ 8 <0x01>;
- };
-
- fan@2 {
- reg = <0x02>;
- aspeed,fan-tach-ch = /bits/ 8 <0x02>;
- };
-
- fan@3 {
- reg = <0x03>;
- aspeed,fan-tach-ch = /bits/ 8 <0x03>;
- };
-
- fan@4 {
- reg = <0x04>;
- aspeed,fan-tach-ch = /bits/ 8 <0x04>;
- };
-
- fan@5 {
- reg = <0x05>;
- aspeed,fan-tach-ch = /bits/ 8 <0x05>;
- };
-
- fan@6 {
- reg = <0x00>;
- aspeed,fan-tach-ch = /bits/ 8 <0x06>;
- };
-
- fan@7 {
- reg = <0x01>;
- aspeed,fan-tach-ch = /bits/ 8 <0x07>;
- };
-
- fan@8 {
- reg = <0x02>;
- aspeed,fan-tach-ch = /bits/ 8 <0x08>;
- };
-
- fan@9 {
- reg = <0x03>;
- aspeed,fan-tach-ch = /bits/ 8 <0x09>;
- };
-
- fan@10 {
- reg = <0x04>;
- aspeed,fan-tach-ch = /bits/ 8 <0x0a>;
- };
-
- fan@11 {
- reg = <0x05>;
- aspeed,fan-tach-ch = /bits/ 8 <0x0b>;
- };
-};
-
-&gpio {
- gpio-line-names =
- /*A0-A7*/ "","cfam-reset","","","","","","",
- /*B0-B7*/ "","","","","","","","",
- /*C0-C7*/ "","","","","","","","",
- /*D0-D7*/ "fsi-enable","","","","","","","",
- /*E0-E7*/ "","","","","","fsi-mux","fsi-clock","fsi-data",
- /*F0-F7*/ "","id-button","","","","","air-water","",
- /*G0-G7*/ "","","","","","","","",
- /*H0-H7*/ "","","","","","","","",
- /*I0-I7*/ "","","","","","","","",
- /*J0-J7*/ "","","checkstop","","","","","",
- /*K0-K7*/ "","","","","","","","",
- /*L0-L7*/ "","","","","","","","",
- /*M0-M7*/ "","","","","","","","",
- /*N0-N7*/ "","","","","","","","",
- /*O0-O7*/ "","","","","","","","",
- /*P0-P7*/ "","","","","","","","",
- /*Q0-Q7*/ "","","","","","","","",
- /*R0-R7*/ "","","fsi-trans","","","","","",
- /*S0-S7*/ "","","","","","","","",
- /*T0-T7*/ "","","","","","","","",
- /*U0-U7*/ "","","","","","","","",
- /*V0-V7*/ "","","","","","","","",
- /*W0-W7*/ "","","","","","","","",
- /*X0-X7*/ "","","","","","","","",
- /*Y0-Y7*/ "","","","","","","","",
- /*Z0-Z7*/ "presence-ps1","","presence-ps0","","","","","",
- /*AA0-AA7*/ "led-front-fault","power-button","led-front-id","","","","","",
- /*AB0-AB7*/ "","","","","","","","",
- /*AC0-AC7*/ "","","","","","","","";
-};
-
-&fmc {
- status = "okay";
- flash@0 {
- status = "okay";
- label = "bmc";
- m25p,fast-read;
- spi-max-frequency = <50000000>;
- partitions {
- #address-cells = < 1 >;
- #size-cells = < 1 >;
- compatible = "fixed-partitions";
- u-boot@0 {
- reg = < 0 0x60000 >;
- label = "u-boot";
- };
- u-boot-env@60000 {
- reg = < 0x60000 0x20000 >;
- label = "u-boot-env";
- };
- obmc-ubi@80000 {
- reg = < 0x80000 0x1F80000 >;
- label = "obmc-ubi";
- };
- };
- };
- flash@1 {
- status = "okay";
- label = "alt-bmc";
- m25p,fast-read;
- spi-max-frequency = <50000000>;
- partitions {
- #address-cells = < 1 >;
- #size-cells = < 1 >;
- compatible = "fixed-partitions";
- u-boot@0 {
- reg = < 0 0x60000 >;
- label = "alt-u-boot";
- };
- u-boot-env@60000 {
- reg = < 0x60000 0x20000 >;
- label = "alt-u-boot-env";
- };
- obmc-ubi@80000 {
- reg = < 0x80000 0x1F80000 >;
- label = "alt-obmc-ubi";
- };
- };
- };
-};
-
-&spi1 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_spi1_default>;
-
- flash@0 {
- status = "okay";
- label = "pnor";
- m25p,fast-read;
- spi-max-frequency = <100000000>;
- };
-};
-
-&lpc_ctrl {
- status = "okay";
- memory-region = <&flash_memory>;
- flash = <&spi1>;
-};
-
-&uart1 {
- /* Rear RS-232 connector */
- status = "okay";
-
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_txd1_default
- &pinctrl_rxd1_default
- &pinctrl_nrts1_default
- &pinctrl_ndtr1_default
- &pinctrl_ndsr1_default
- &pinctrl_ncts1_default
- &pinctrl_ndcd1_default
- &pinctrl_nri1_default>;
-};
-
-&uart2 {
- /* APSS */
- status = "okay";
-
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_txd2_default &pinctrl_rxd2_default>;
-};
-
-&uart5 {
- status = "okay";
-};
-
-&mac0 {
- status = "okay";
-
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_rmii1_default>;
- clocks = <&syscon ASPEED_CLK_GATE_MAC1CLK>,
- <&syscon ASPEED_CLK_MAC1RCLK>;
- clock-names = "MACCLK", "RCLK";
- use-ncsi;
-};
-
-&mac1 {
- status = "okay";
-
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_rgmii2_default &pinctrl_mdio2_default>;
-};
-
-&i2c0 {
- status = "disabled";
-};
-
-&i2c1 {
- status = "disabled";
-};
-
-&i2c2 {
- status = "okay";
-
- /* SAMTEC P0 */
- /* SAMTEC P1 */
-
-};
-
-&i2c3 {
- status = "okay";
-
- /* APSS */
- /* CPLD */
-
- /* PCA9516 (repeater) ->
- * CLK Buffer 9FGS9092
- * CLK Buffer 9DBL0651BKILFT
- * CLK Buffer 9DBL0651BKILFT
- * Power Supply 0
- * Power Supply 1
- * PCA 9552 LED
- */
-
- power-supply@58 {
- compatible = "ibm,cffps1";
- reg = <0x58>;
- };
-
- power-supply@5b {
- compatible = "ibm,cffps1";
- reg = <0x5b>;
- };
-
- pca9552: pca9552@60 {
- compatible = "nxp,pca9552";
- reg = <0x60>;
- #address-cells = <1>;
- #size-cells = <0>;
- gpio-controller;
- #gpio-cells = <2>;
-
- gpio@0 {
- reg = <0>;
- type = <PCA955X_TYPE_GPIO>;
- };
- gpio@1 {
- reg = <1>;
- type = <PCA955X_TYPE_GPIO>;
- };
- gpio@2 {
- reg = <2>;
- type = <PCA955X_TYPE_GPIO>;
- };
- gpio@3 {
- reg = <3>;
- type = <PCA955X_TYPE_GPIO>;
- };
- gpio@4 {
- reg = <4>;
- type = <PCA955X_TYPE_GPIO>;
- };
- gpio@5 {
- reg = <5>;
- type = <PCA955X_TYPE_GPIO>;
- };
- gpio@6 {
- reg = <6>;
- type = <PCA955X_TYPE_GPIO>;
- };
- gpio@7 {
- reg = <7>;
- type = <PCA955X_TYPE_GPIO>;
- };
- gpio@8 {
- reg = <8>;
- type = <PCA955X_TYPE_GPIO>;
- };
- gpio@9 {
- reg = <9>;
- type = <PCA955X_TYPE_GPIO>;
- };
- gpio@10 {
- reg = <10>;
- type = <PCA955X_TYPE_GPIO>;
- };
- gpio@11 {
- reg = <11>;
- type = <PCA955X_TYPE_GPIO>;
- };
- gpio@12 {
- reg = <12>;
- type = <PCA955X_TYPE_GPIO>;
- };
- gpio@13 {
- reg = <13>;
- type = <PCA955X_TYPE_GPIO>;
- };
- gpio@14 {
- reg = <14>;
- type = <PCA955X_TYPE_GPIO>;
- };
- gpio@15 {
- reg = <15>;
- type = <PCA955X_TYPE_GPIO>;
- };
-
- };
-
-};
-
-&i2c4 {
- status = "okay";
-
- /* CP0 VDD & VCS : IR35221 */
- /* CP0 VDN : IR35221 */
- /* CP0 VIO : IR38064 */
- /* CP0 VDDR : PXM1330 */
-
- ir35221@70 {
- compatible = "infineon,ir35221";
- reg = <0x70>;
- };
-
- ir35221@72 {
- compatible = "infineon,ir35221";
- reg = <0x72>;
- };
-
-};
-
-&i2c5 {
- status = "okay";
-
- /* CP0 VDD & VCS : IR35221 */
- /* CP0 VDN : IR35221 */
- /* CP0 VIO : IR38064 */
- /* CP0 VDDR : PXM1330 */
-
- ir35221@70 {
- compatible = "infineon,ir35221";
- reg = <0x70>;
- };
-
- ir35221@72 {
- compatible = "infineon,ir35221";
- reg = <0x72>;
- };
-
-};
-
-&i2c6 {
- status = "okay";
-
- /* pca9548 -> NVMe1 to 8 */
-
- pca9548@70 {
- compatible = "nxp,pca9548";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x70>;
-
- bus7_mux223: i2c@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0>;
- };
-
- bus7_mux224: i2c@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <1>;
- };
-
- bus7_mux225: i2c@2 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <2>;
- };
-
- bus7_mux226: i2c@3 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <3>;
- };
-
- bus7_mux227: i2c@4 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <4>;
- };
-
- bus7_mux228: i2c@5 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <5>;
- };
-
- bus7_mux229: i2c@6 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <6>;
- };
-
- bus7_mux230: i2c@7 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <7>;
- };
- };
-
-};
-
-&i2c7 {
- status = "okay";
-
- /* pca9548 -> NVMe9 to 16 */
-
- pca9548@70 {
- compatible = "nxp,pca9548";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x70>;
-
- bus6_mux215: i2c@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0>;
- };
-
- bus6_mux216: i2c@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <1>;
- };
-
- bus6_mux217: i2c@2 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <2>;
- };
-
- bus6_mux218: i2c@3 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <3>;
- };
-
- bus6_mux219: i2c@4 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <4>;
- };
-
- bus6_mux220: i2c@5 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <5>;
- };
-
- bus6_mux221: i2c@6 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <6>;
- };
-
- bus6_mux222: i2c@7 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <7>;
- };
- };
-
-};
-
-&i2c8 {
- status = "okay";
-
- eeprom@50 {
- compatible = "atmel,24c64";
- reg = <0x50>;
- };
-};
-
-&i2c9 {
- status = "okay";
-
- /* pca9545 Riser ->
- * PCIe x8 Slot3
- * PCIe x16 slot4
- * PCIe x8 slot5
- * I2C BMC RISER PCA9554
- * BMC SCL/SDA PCA9554
- * PCA9554
- */
-
- /* pca9545 ->
- * PCIe x16 Slot1
- * PCIe x8 slot2
- * PEX8748
- */
-
- pca9545riser@70 {
- compatible = "nxp,pca9545";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x70>;
-
- i2c-mux-idle-disconnect;
- interrupt-controller;
- #interrupt-cells = <2>;
-
- bus9_mux231: i2c@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0>;
-
- tca9554@39 {
- compatible = "ti,tca9554";
- reg = <0x39>;
- gpio-controller;
- #gpio-cells = <2>;
-
- smbus0-hog {
- gpio-hog;
- gpios = <4 GPIO_ACTIVE_HIGH>;
- output-high;
- line-name = "smbus0";
- };
- };
-
- tmp431@4c {
- compatible = "ti,tmp401";
- reg = <0x4c>;
- };
- };
-
- bus9_mux232: i2c@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <1>;
-
- tca9554@39 {
- compatible = "ti,tca9554";
- reg = <0x39>;
- gpio-controller;
- #gpio-cells = <2>;
-
- smbus1-hog {
- gpio-hog;
- gpios = <4 GPIO_ACTIVE_HIGH>;
- output-high;
- line-name = "smbus1";
- };
- };
-
- tmp431@4c {
- compatible = "ti,tmp401";
- reg = <0x4c>;
- };
- };
-
- bus9_mux233: i2c@2 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <2>;
- };
-
- bus9_mux234: i2c@3 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <3>;
- };
- };
-
- pca9545@71 {
- compatible = "nxp,pca9545";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x71>;
-
- i2c-mux-idle-disconnect;
- interrupt-controller;
- #interrupt-cells = <2>;
-
- bus9_mux235: i2c@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0>;
-
- tca9554@39 {
- compatible = "ti,tca9554";
- reg = <0x39>;
- gpio-controller;
- #gpio-cells = <2>;
-
- smbus2-hog {
- gpio-hog;
- gpios = <4 GPIO_ACTIVE_HIGH>;
- output-high;
- line-name = "smbus2";
- };
- };
-
- tmp431@4c {
- compatible = "ti,tmp401";
- reg = <0x4c>;
- };
- };
-
- bus9_mux236: i2c@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <1>;
-
- tca9554@39 {
- compatible = "ti,tca9554";
- reg = <0x39>;
- gpio-controller;
- #gpio-cells = <2>;
-
- smbus3-hog {
- gpio-hog;
- gpios = <4 GPIO_ACTIVE_HIGH>;
- output-high;
- line-name = "smbus3";
- };
- };
-
- tmp431@4c {
- compatible = "ti,tmp401";
- reg = <0x4c>;
- };
- };
-
- bus9_mux237: i2c@2 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <2>;
- };
-
- bus9_mux238: i2c@3 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <3>;
- };
- };
-};
-
-&i2c10 {
- status = "okay";
-
- /* pca9545 Riser ->
- * PCIe x8 Slot8
- * PCIe x16 slot9
- * PCIe x8 slot10
- * I2C BMC RISER PCA9554
- * BMC SCL/SDA PCA9554
- * PCA9554
- */
-
- /* pca9545 ->
- * PCIe x16 Slot1
- * PCIe x8 slot2
- * PEX8748
- */
-
- pca9545riser@70 {
- compatible = "nxp,pca9545";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x70>;
-
- i2c-mux-idle-disconnect;
- interrupt-controller;
- #interrupt-cells = <2>;
-
- bus10_mux239: i2c@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0>;
-
- tca9554@39 {
- compatible = "ti,tca9554";
- reg = <0x39>;
- gpio-controller;
- #gpio-cells = <2>;
-
- smbus4-hog {
- gpio-hog;
- gpios = <4 GPIO_ACTIVE_HIGH>;
- output-high;
- line-name = "smbus4";
- };
- };
-
- tmp431@4c {
- compatible = "ti,tmp401";
- reg = <0x4c>;
- };
- };
-
- bus10_mux240: i2c@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <1>;
-
- tca9554@39 {
- compatible = "ti,tca9554";
- reg = <0x39>;
- gpio-controller;
- #gpio-cells = <2>;
-
- smbus5-hog {
- gpio-hog;
- gpios = <4 GPIO_ACTIVE_HIGH>;
- output-high;
- line-name = "smbus5";
- };
- };
-
- tmp431@4c {
- compatible = "ti,tmp401";
- reg = <0x4c>;
- };
- };
-
- bus10_mux241: i2c@2 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <2>;
- };
-
- bus10_mux242: i2c@3 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <3>;
- };
- };
-
- pca9545@71 {
- compatible = "nxp,pca9545";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x71>;
-
- i2c-mux-idle-disconnect;
- interrupt-controller;
- #interrupt-cells = <2>;
-
- bus10_mux243: i2c@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0>;
-
- tca9554@39 {
- compatible = "ti,tca9554";
- reg = <0x39>;
- gpio-controller;
- #gpio-cells = <2>;
-
- smbus6-hog {
- gpio-hog;
- gpios = <4 GPIO_ACTIVE_HIGH>;
- output-high;
- line-name = "smbus6";
- };
- };
-
- tmp431@4c {
- compatible = "ti,tmp401";
- reg = <0x4c>;
- };
- };
-
- bus10_mux244: i2c@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <1>;
-
- tca9554@39 {
- compatible = "ti,tca9554";
- reg = <0x39>;
- gpio-controller;
- #gpio-cells = <2>;
-
- smbus7-hog {
- gpio-hog;
- gpios = <4 GPIO_ACTIVE_HIGH>;
- output-high;
- line-name = "smbus7";
- };
- };
-
- tmp431@4c {
- compatible = "ti,tmp401";
- reg = <0x4c>;
- };
- };
-
- bus10_mux245: i2c@2 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <2>;
- };
-
- bus10_mux246: i2c@3 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <3>;
- };
- };
-};
-
-&i2c11 {
- status = "okay";
-
- /* TPM */
- /* RTC RX8900CE */
- /* FPGA for power sequence */
- /* TMP275A */
- /* TMP275A */
- /* EMC1462 */
-
- tpm@57 {
- compatible = "infineon,slb9645tt";
- reg = <0x57>;
- };
-
- rtc@32 {
- compatible = "epson,rx8900";
- reg = <0x32>;
- };
-
- tmp275@48 {
- compatible = "ti,tmp275";
- reg = <0x48>;
- };
-
- tmp275@49 {
- compatible = "ti,tmp275";
- reg = <0x49>;
- };
-
- /* chip emc1462 use emc1403 driver */
- emc1403@4c {
- compatible = "smsc,emc1403";
- reg = <0x4c>;
- };
-
-};
-
-&i2c12 {
- status = "okay";
-
- /* pca9545 ->
- * SAS BP1
- * SAS BP2
- * NVMe BP
- * M.2 riser
- */
-
- pca9545@70 {
- compatible = "nxp,pca9545";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x70>;
-
- interrupt-controller;
- #interrupt-cells = <2>;
-
- bus12_mux247: i2c@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0>;
-
- eeprom@50 {
- compatible = "atmel,24c64";
- reg = <0x50>;
- };
- };
-
- bus12_mux248: i2c@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <1>;
-
- eeprom@50 {
- compatible = "atmel,24c64";
- reg = <0x50>;
- };
- };
-
- bus12_mux249: i2c@2 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <2>;
-
- eeprom@50 {
- compatible = "atmel,24c64";
- reg = <0x50>;
- };
- };
-
- bus12_mux250: i2c@3 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <3>;
-
- tmp275@48 {
- compatible = "ti,tmp275";
- reg = <0x48>;
- };
- };
-
- };
-
-};
-
-&i2c13 {
- status = "okay";
-
- /* pca9548 ->
- * NVMe BP
- * NVMe HDD17 to 24
- */
-
- pca9548@70 {
- compatible = "nxp,pca9548";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x70>;
- bus13_mux251: i2c@0 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0>;
- };
-
- bus13_mux252: i2c@1 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <1>;
- };
-
- bus13_mux253: i2c@2 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <2>;
- };
-
- bus13_mux254: i2c@3 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <3>;
- };
-
- bus13_mux255: i2c@4 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <4>;
- };
-
- bus13_mux256: i2c@5 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <5>;
- };
-
- bus13_mux257: i2c@6 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <6>;
- };
-
- bus13_mux258: i2c@7 {
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <7>;
- };
- };
-};
-
-&vuart {
- status = "okay";
-};
-
-&gfx {
- status = "okay";
- memory-region = <&gfx_memory>;
-};
-
-&adc {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_adc0_default
- &pinctrl_adc1_default
- &pinctrl_adc2_default
- &pinctrl_adc3_default
- &pinctrl_adc4_default
- &pinctrl_adc5_default
- &pinctrl_adc6_default
- &pinctrl_adc7_default
- &pinctrl_adc8_default
- &pinctrl_adc9_default
- &pinctrl_adc10_default
- &pinctrl_adc11_default
- &pinctrl_adc12_default
- &pinctrl_adc13_default
- &pinctrl_adc14_default
- &pinctrl_adc15_default>;
-};
-
-&wdt1 {
- aspeed,reset-type = "none";
- aspeed,external-signal;
- aspeed,ext-push-pull;
- aspeed,ext-active-high;
-
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_wdtrst1_default>;
-};
-
-&wdt2 {
- aspeed,alt-boot;
-};
-
-&ibt {
- status = "okay";
-};
-
-&vhub {
- status = "okay";
-};
-
-&video {
- status = "okay";
- memory-region = <&video_engine_memory>;
-};
-
-#include "ibm-power9-dual.dtsi"
-
diff --git a/arch/arm/boot/dts/aspeed-g6.dtsi b/arch/arm/boot/dts/aspeed-g6.dtsi
index ebbcfe445d9c..cc2f8b785917 100644
--- a/arch/arm/boot/dts/aspeed-g6.dtsi
+++ b/arch/arm/boot/dts/aspeed-g6.dtsi
@@ -36,6 +36,10 @@
serial4 = &uart5;
serial5 = &vuart1;
serial6 = &vuart2;
+ mdio0 = &mdio0;
+ mdio1 = &mdio1;
+ mdio2 = &mdio2;
+ mdio3 = &mdio3;
};
diff --git a/arch/arm/boot/dts/ast2600-facebook-netbmc-common.dtsi b/arch/arm/boot/dts/ast2600-facebook-netbmc-common.dtsi
index 051de5bec345..31590d3186a2 100644
--- a/arch/arm/boot/dts/ast2600-facebook-netbmc-common.dtsi
+++ b/arch/arm/boot/dts/ast2600-facebook-netbmc-common.dtsi
@@ -25,7 +25,7 @@
* full-duplex SPI transactions are not supported by ASPEED SPI
* Controllers.
*/
- spi_gpio: spi-gpio {
+ spi_gpio: spi {
status = "okay";
compatible = "spi-gpio";
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/at91-sam9x60ek.dts b/arch/arm/boot/dts/at91-sam9x60ek.dts
index 4ba52ba11dc6..d929c1ba5789 100644
--- a/arch/arm/boot/dts/at91-sam9x60ek.dts
+++ b/arch/arm/boot/dts/at91-sam9x60ek.dts
@@ -76,7 +76,6 @@
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
- status = "okay";
};
vdd_1v15: fixed-regulator-vdd_1v15 {
@@ -85,7 +84,6 @@
regulator-min-microvolt = <1150000>;
regulator-max-microvolt = <1150000>;
regulator-always-on;
- status = "okay";
};
vdd1_3v3: fixed-regulator-vdd1_3v3 {
@@ -94,7 +92,6 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
- status = "okay";
};
vdd2_3v3: regulator-fixed-vdd2_3v3 {
@@ -103,7 +100,6 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
- status = "okay";
};
};
diff --git a/arch/arm/boot/dts/at91-sama7g5ek.dts b/arch/arm/boot/dts/at91-sama7g5ek.dts
index 3b25c67795dd..aa5cc0e98bba 100644
--- a/arch/arm/boot/dts/at91-sama7g5ek.dts
+++ b/arch/arm/boot/dts/at91-sama7g5ek.dts
@@ -764,8 +764,9 @@
&sdmmc0 {
bus-width = <8>;
non-removable;
- no-1-8-v;
sdhci-caps-mask = <0x0 0x00200000>;
+ vmmc-supply = <&vdd_3v3>;
+ vqmmc-supply = <&vldo1>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sdmmc0_default>;
status = "okay";
@@ -775,6 +776,8 @@
bus-width = <4>;
no-1-8-v;
sdhci-caps-mask = <0x0 0x00200000>;
+ vmmc-supply = <&vdd_3v3>;
+ vqmmc-supply = <&vdd_3v3>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_sdmmc1_default>;
status = "okay";
diff --git a/arch/arm/boot/dts/axp22x.dtsi b/arch/arm/boot/dts/axp22x.dtsi
index a020c12b2884..f79650afd0a7 100644
--- a/arch/arm/boot/dts/axp22x.dtsi
+++ b/arch/arm/boot/dts/axp22x.dtsi
@@ -67,6 +67,12 @@
status = "disabled";
};
+ axp_gpio: gpio {
+ compatible = "x-powers,axp221-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
regulators {
/* Default work frequency for buck regulators */
x-powers,dcdc-freq = <3000>;
diff --git a/arch/arm/boot/dts/axp809.dtsi b/arch/arm/boot/dts/axp809.dtsi
index ab8e5f2d9246..d134d4c00bd8 100644
--- a/arch/arm/boot/dts/axp809.dtsi
+++ b/arch/arm/boot/dts/axp809.dtsi
@@ -50,4 +50,11 @@
compatible = "x-powers,axp809";
interrupt-controller;
#interrupt-cells = <1>;
+
+ axp_gpio: gpio {
+ compatible = "x-powers,axp809-gpio",
+ "x-powers,axp221-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
};
diff --git a/arch/arm/boot/dts/axp81x.dtsi b/arch/arm/boot/dts/axp81x.dtsi
index b93387b0c1c3..ebaf1c3ce8db 100644
--- a/arch/arm/boot/dts/axp81x.dtsi
+++ b/arch/arm/boot/dts/axp81x.dtsi
@@ -62,16 +62,6 @@
compatible = "x-powers,axp813-gpio";
gpio-controller;
#gpio-cells = <2>;
-
- gpio0_ldo: gpio0-ldo-pin {
- pins = "GPIO0";
- function = "ldo";
- };
-
- gpio1_ldo: gpio1-ldo-pin {
- pins = "GPIO1";
- function = "ldo";
- };
};
battery_power_supply: battery-power {
@@ -144,15 +134,11 @@
};
reg_ldo_io0: ldo-io0 {
- pinctrl-names = "default";
- pinctrl-0 = <&gpio0_ldo>;
/* Disable by default to avoid conflicts with GPIO */
status = "disabled";
};
reg_ldo_io1: ldo-io1 {
- pinctrl-names = "default";
- pinctrl-0 = <&gpio1_ldo>;
/* Disable by default to avoid conflicts with GPIO */
status = "disabled";
};
diff --git a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
index 4432412044de..d5f8823230db 100644
--- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
+++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts
@@ -2,6 +2,7 @@
/dts-v1/;
#include "bcm2711.dtsi"
#include "bcm2711-rpi.dtsi"
+#include "bcm283x-rpi-led-deprecated.dtsi"
#include "bcm283x-rpi-usb-peripheral.dtsi"
#include "bcm283x-rpi-wifi-bt.dtsi"
@@ -14,20 +15,7 @@
stdout-path = "serial1:115200n8";
};
- leds {
- led-act {
- gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;
- };
-
- led-pwr {
- label = "PWR";
- gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
- default-state = "keep";
- linux,default-trigger = "default-on";
- };
- };
-
- sd_io_1v8_reg: sd_io_1v8_reg {
+ sd_io_1v8_reg: regulator-sd-io-1v8 {
compatible = "regulator-gpio";
regulator-name = "vdd-sd-io";
regulator-min-microvolt = <1800000>;
@@ -41,7 +29,7 @@
status = "okay";
};
- sd_vcc_reg: sd_vcc_reg {
+ sd_vcc_reg: regulator-sd-vcc {
compatible = "regulator-fixed";
regulator-name = "vcc-sd";
regulator-min-microvolt = <3300000>;
@@ -156,6 +144,19 @@
status = "okay";
};
+&led_act {
+ gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;
+};
+
+&leds {
+ led_pwr: led-pwr {
+ label = "PWR";
+ gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
+ default-state = "keep";
+ linux,default-trigger = "default-on";
+ };
+};
+
&pixelvalve0 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/bcm2711-rpi-400.dts b/arch/arm/boot/dts/bcm2711-rpi-400.dts
index c53d9eb0b802..1ab8184302db 100644
--- a/arch/arm/boot/dts/bcm2711-rpi-400.dts
+++ b/arch/arm/boot/dts/bcm2711-rpi-400.dts
@@ -11,14 +11,6 @@
stdout-path = "serial1:115200n8";
};
- leds {
- /delete-node/ led-act;
-
- led-pwr {
- gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;
- };
- };
-
gpio-poweroff {
compatible = "gpio-poweroff";
gpios = <&expgpio 5 GPIO_ACTIVE_HIGH>;
@@ -40,6 +32,14 @@
clock-frequency = <1950000>;
};
+&led_pwr {
+ gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;
+};
+
+&leds {
+ /delete-node/ led_act;
+};
+
&pm {
/delete-property/ system-power-controller;
};
diff --git a/arch/arm/boot/dts/bcm2711-rpi-cm4-io.dts b/arch/arm/boot/dts/bcm2711-rpi-cm4-io.dts
index 19600b629be5..d7ba02f586d3 100644
--- a/arch/arm/boot/dts/bcm2711-rpi-cm4-io.dts
+++ b/arch/arm/boot/dts/bcm2711-rpi-cm4-io.dts
@@ -1,23 +1,11 @@
// SPDX-License-Identifier: GPL-2.0
/dts-v1/;
#include "bcm2711-rpi-cm4.dtsi"
+#include "bcm283x-rpi-led-deprecated.dtsi"
#include "bcm283x-rpi-usb-host.dtsi"
/ {
model = "Raspberry Pi Compute Module 4 IO Board";
-
- leds {
- led-act {
- gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;
- };
-
- led-pwr {
- label = "PWR";
- gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
- default-state = "keep";
- linux,default-trigger = "default-on";
- };
- };
};
&ddc0 {
@@ -113,6 +101,19 @@
status = "okay";
};
+&led_act {
+ gpios = <&gpio 42 GPIO_ACTIVE_HIGH>;
+};
+
+&leds {
+ led-pwr {
+ label = "PWR";
+ gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
+ default-state = "keep";
+ linux,default-trigger = "default-on";
+ };
+};
+
&pixelvalve0 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/bcm2711-rpi-cm4.dtsi b/arch/arm/boot/dts/bcm2711-rpi-cm4.dtsi
index a2954d466a73..48e63ab7848c 100644
--- a/arch/arm/boot/dts/bcm2711-rpi-cm4.dtsi
+++ b/arch/arm/boot/dts/bcm2711-rpi-cm4.dtsi
@@ -12,7 +12,7 @@
stdout-path = "serial1:115200n8";
};
- sd_io_1v8_reg: sd_io_1v8_reg {
+ sd_io_1v8_reg: regulator-sd-io-1v8 {
compatible = "regulator-gpio";
regulator-name = "vdd-sd-io";
regulator-min-microvolt = <1800000>;
@@ -26,7 +26,7 @@
status = "okay";
};
- sd_vcc_reg: sd_vcc_reg {
+ sd_vcc_reg: regulator-sd-vcc {
compatible = "regulator-fixed";
regulator-name = "vcc-sd";
regulator-min-microvolt = <3300000>;
diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi
index 941c4d16791b..097e9f252235 100644
--- a/arch/arm/boot/dts/bcm2711.dtsi
+++ b/arch/arm/boot/dts/bcm2711.dtsi
@@ -48,7 +48,7 @@
* This node is the provider for the enable-method for
* bringing up secondary cores.
*/
- local_intc: local_intc@40000000 {
+ local_intc: interrupt-controller@40000000 {
compatible = "brcm,bcm2836-l1-intc";
reg = <0x40000000 0x100>;
};
@@ -536,6 +536,7 @@
*/
l2: l2-cache0 {
compatible = "cache";
+ cache-unified;
cache-size = <0x100000>;
cache-line-size = <64>;
cache-sets = <1024>; // 1MiB(size)/64(line-size)=16384ways/16-way set
@@ -647,21 +648,21 @@
gpio-ranges = <&gpio 0 0 58>;
- gpclk0_gpio49: gpclk0_gpio49 {
+ gpclk0_gpio49: gpclk0-gpio49 {
pin-gpclk {
pins = "gpio49";
function = "alt1";
bias-disable;
};
};
- gpclk1_gpio50: gpclk1_gpio50 {
+ gpclk1_gpio50: gpclk1-gpio50 {
pin-gpclk {
pins = "gpio50";
function = "alt1";
bias-disable;
};
};
- gpclk2_gpio51: gpclk2_gpio51 {
+ gpclk2_gpio51: gpclk2-gpio51 {
pin-gpclk {
pins = "gpio51";
function = "alt1";
@@ -669,7 +670,7 @@
};
};
- i2c0_gpio46: i2c0_gpio46 {
+ i2c0_gpio46: i2c0-gpio46 {
pin-sda {
function = "alt0";
pins = "gpio46";
@@ -681,7 +682,7 @@
bias-disable;
};
};
- i2c1_gpio46: i2c1_gpio46 {
+ i2c1_gpio46: i2c1-gpio46 {
pin-sda {
function = "alt1";
pins = "gpio46";
@@ -693,7 +694,7 @@
bias-disable;
};
};
- i2c3_gpio2: i2c3_gpio2 {
+ i2c3_gpio2: i2c3-gpio2 {
pin-sda {
function = "alt5";
pins = "gpio2";
@@ -705,7 +706,7 @@
bias-disable;
};
};
- i2c3_gpio4: i2c3_gpio4 {
+ i2c3_gpio4: i2c3-gpio4 {
pin-sda {
function = "alt5";
pins = "gpio4";
@@ -717,7 +718,7 @@
bias-disable;
};
};
- i2c4_gpio6: i2c4_gpio6 {
+ i2c4_gpio6: i2c4-gpio6 {
pin-sda {
function = "alt5";
pins = "gpio6";
@@ -729,7 +730,7 @@
bias-disable;
};
};
- i2c4_gpio8: i2c4_gpio8 {
+ i2c4_gpio8: i2c4-gpio8 {
pin-sda {
function = "alt5";
pins = "gpio8";
@@ -741,7 +742,7 @@
bias-disable;
};
};
- i2c5_gpio10: i2c5_gpio10 {
+ i2c5_gpio10: i2c5-gpio10 {
pin-sda {
function = "alt5";
pins = "gpio10";
@@ -753,7 +754,7 @@
bias-disable;
};
};
- i2c5_gpio12: i2c5_gpio12 {
+ i2c5_gpio12: i2c5-gpio12 {
pin-sda {
function = "alt5";
pins = "gpio12";
@@ -765,7 +766,7 @@
bias-disable;
};
};
- i2c6_gpio0: i2c6_gpio0 {
+ i2c6_gpio0: i2c6-gpio0 {
pin-sda {
function = "alt5";
pins = "gpio0";
@@ -777,7 +778,7 @@
bias-disable;
};
};
- i2c6_gpio22: i2c6_gpio22 {
+ i2c6_gpio22: i2c6-gpio22 {
pin-sda {
function = "alt5";
pins = "gpio22";
@@ -789,7 +790,7 @@
bias-disable;
};
};
- i2c_slave_gpio8: i2c_slave_gpio8 {
+ i2c_slave_gpio8: i2c-slave-gpio8 {
pins-i2c-slave {
pins = "gpio8",
"gpio9",
@@ -799,7 +800,7 @@
};
};
- jtag_gpio48: jtag_gpio48 {
+ jtag_gpio48: jtag-gpio48 {
pins-jtag {
pins = "gpio48",
"gpio49",
@@ -811,7 +812,7 @@
};
};
- mii_gpio28: mii_gpio28 {
+ mii_gpio28: mii-gpio28 {
pins-mii {
pins = "gpio28",
"gpio29",
@@ -820,7 +821,7 @@
function = "alt4";
};
};
- mii_gpio36: mii_gpio36 {
+ mii_gpio36: mii-gpio36 {
pins-mii {
pins = "gpio36",
"gpio37",
@@ -830,7 +831,7 @@
};
};
- pcm_gpio50: pcm_gpio50 {
+ pcm_gpio50: pcm-gpio50 {
pins-pcm {
pins = "gpio50",
"gpio51",
@@ -840,63 +841,63 @@
};
};
- pwm0_0_gpio12: pwm0_0_gpio12 {
+ pwm0_0_gpio12: pwm0-0-gpio12 {
pin-pwm {
pins = "gpio12";
function = "alt0";
bias-disable;
};
};
- pwm0_0_gpio18: pwm0_0_gpio18 {
+ pwm0_0_gpio18: pwm0-0-gpio18 {
pin-pwm {
pins = "gpio18";
function = "alt5";
bias-disable;
};
};
- pwm1_0_gpio40: pwm1_0_gpio40 {
+ pwm1_0_gpio40: pwm1-0-gpio40 {
pin-pwm {
pins = "gpio40";
function = "alt0";
bias-disable;
};
};
- pwm0_1_gpio13: pwm0_1_gpio13 {
+ pwm0_1_gpio13: pwm0-1-gpio13 {
pin-pwm {
pins = "gpio13";
function = "alt0";
bias-disable;
};
};
- pwm0_1_gpio19: pwm0_1_gpio19 {
+ pwm0_1_gpio19: pwm0-1-gpio19 {
pin-pwm {
pins = "gpio19";
function = "alt5";
bias-disable;
};
};
- pwm1_1_gpio41: pwm1_1_gpio41 {
+ pwm1_1_gpio41: pwm1-1-gpio41 {
pin-pwm {
pins = "gpio41";
function = "alt0";
bias-disable;
};
};
- pwm0_1_gpio45: pwm0_1_gpio45 {
+ pwm0_1_gpio45: pwm0-1-gpio45 {
pin-pwm {
pins = "gpio45";
function = "alt0";
bias-disable;
};
};
- pwm0_0_gpio52: pwm0_0_gpio52 {
+ pwm0_0_gpio52: pwm0-0-gpio52 {
pin-pwm {
pins = "gpio52";
function = "alt1";
bias-disable;
};
};
- pwm0_1_gpio53: pwm0_1_gpio53 {
+ pwm0_1_gpio53: pwm0-1-gpio53 {
pin-pwm {
pins = "gpio53";
function = "alt1";
@@ -904,7 +905,7 @@
};
};
- rgmii_gpio35: rgmii_gpio35 {
+ rgmii_gpio35: rgmii-gpio35 {
pin-start-stop {
pins = "gpio35";
function = "alt4";
@@ -914,26 +915,26 @@
function = "alt4";
};
};
- rgmii_irq_gpio34: rgmii_irq_gpio34 {
+ rgmii_irq_gpio34: rgmii-irq-gpio34 {
pin-irq {
pins = "gpio34";
function = "alt5";
};
};
- rgmii_irq_gpio39: rgmii_irq_gpio39 {
+ rgmii_irq_gpio39: rgmii-irq-gpio39 {
pin-irq {
pins = "gpio39";
function = "alt4";
};
};
- rgmii_mdio_gpio28: rgmii_mdio_gpio28 {
+ rgmii_mdio_gpio28: rgmii-mdio-gpio28 {
pins-mdio {
pins = "gpio28",
"gpio29";
function = "alt5";
};
};
- rgmii_mdio_gpio37: rgmii_mdio_gpio37 {
+ rgmii_mdio_gpio37: rgmii-mdio-gpio37 {
pins-mdio {
pins = "gpio37",
"gpio38";
@@ -941,7 +942,7 @@
};
};
- spi0_gpio46: spi0_gpio46 {
+ spi0_gpio46: spi0-gpio46 {
pins-spi {
pins = "gpio46",
"gpio47",
@@ -950,7 +951,7 @@
function = "alt2";
};
};
- spi2_gpio46: spi2_gpio46 {
+ spi2_gpio46: spi2-gpio46 {
pins-spi {
pins = "gpio46",
"gpio47",
@@ -960,7 +961,7 @@
function = "alt5";
};
};
- spi3_gpio0: spi3_gpio0 {
+ spi3_gpio0: spi3-gpio0 {
pins-spi {
pins = "gpio0",
"gpio1",
@@ -969,7 +970,7 @@
function = "alt3";
};
};
- spi4_gpio4: spi4_gpio4 {
+ spi4_gpio4: spi4-gpio4 {
pins-spi {
pins = "gpio4",
"gpio5",
@@ -978,7 +979,7 @@
function = "alt3";
};
};
- spi5_gpio12: spi5_gpio12 {
+ spi5_gpio12: spi5-gpio12 {
pins-spi {
pins = "gpio12",
"gpio13",
@@ -987,7 +988,7 @@
function = "alt3";
};
};
- spi6_gpio18: spi6_gpio18 {
+ spi6_gpio18: spi6-gpio18 {
pins-spi {
pins = "gpio18",
"gpio19",
@@ -997,7 +998,7 @@
};
};
- uart2_gpio0: uart2_gpio0 {
+ uart2_gpio0: uart2-gpio0 {
pin-tx {
pins = "gpio0";
function = "alt4";
@@ -1009,7 +1010,7 @@
bias-pull-up;
};
};
- uart2_ctsrts_gpio2: uart2_ctsrts_gpio2 {
+ uart2_ctsrts_gpio2: uart2-ctsrts-gpio2 {
pin-cts {
pins = "gpio2";
function = "alt4";
@@ -1021,7 +1022,7 @@
bias-disable;
};
};
- uart3_gpio4: uart3_gpio4 {
+ uart3_gpio4: uart3-gpio4 {
pin-tx {
pins = "gpio4";
function = "alt4";
@@ -1033,7 +1034,7 @@
bias-pull-up;
};
};
- uart3_ctsrts_gpio6: uart3_ctsrts_gpio6 {
+ uart3_ctsrts_gpio6: uart3-ctsrts-gpio6 {
pin-cts {
pins = "gpio6";
function = "alt4";
@@ -1045,7 +1046,7 @@
bias-disable;
};
};
- uart4_gpio8: uart4_gpio8 {
+ uart4_gpio8: uart4-gpio8 {
pin-tx {
pins = "gpio8";
function = "alt4";
@@ -1057,7 +1058,7 @@
bias-pull-up;
};
};
- uart4_ctsrts_gpio10: uart4_ctsrts_gpio10 {
+ uart4_ctsrts_gpio10: uart4-ctsrts-gpio10 {
pin-cts {
pins = "gpio10";
function = "alt4";
@@ -1069,7 +1070,7 @@
bias-disable;
};
};
- uart5_gpio12: uart5_gpio12 {
+ uart5_gpio12: uart5-gpio12 {
pin-tx {
pins = "gpio12";
function = "alt4";
@@ -1081,7 +1082,7 @@
bias-pull-up;
};
};
- uart5_ctsrts_gpio14: uart5_ctsrts_gpio14 {
+ uart5_ctsrts_gpio14: uart5-ctsrts-gpio14 {
pin-cts {
pins = "gpio14";
function = "alt4";
diff --git a/arch/arm/boot/dts/bcm2835-common.dtsi b/arch/arm/boot/dts/bcm2835-common.dtsi
index a037d2bc5b11..bb7e8f7facaf 100644
--- a/arch/arm/boot/dts/bcm2835-common.dtsi
+++ b/arch/arm/boot/dts/bcm2835-common.dtsi
@@ -152,41 +152,41 @@
};
&gpio {
- i2c_slave_gpio18: i2c_slave_gpio18 {
+ i2c_slave_gpio18: i2c-slave-gpio18 {
brcm,pins = <18 19 20 21>;
brcm,function = <BCM2835_FSEL_ALT3>;
};
- jtag_gpio4: jtag_gpio4 {
+ jtag_gpio4: jtag-gpio4 {
brcm,pins = <4 5 6 12 13>;
brcm,function = <BCM2835_FSEL_ALT5>;
};
- pwm0_gpio12: pwm0_gpio12 {
+ pwm0_gpio12: pwm0-gpio12 {
brcm,pins = <12>;
brcm,function = <BCM2835_FSEL_ALT0>;
};
- pwm0_gpio18: pwm0_gpio18 {
+ pwm0_gpio18: pwm0-gpio18 {
brcm,pins = <18>;
brcm,function = <BCM2835_FSEL_ALT5>;
};
- pwm0_gpio40: pwm0_gpio40 {
+ pwm0_gpio40: pwm0-gpio40 {
brcm,pins = <40>;
brcm,function = <BCM2835_FSEL_ALT0>;
};
- pwm1_gpio13: pwm1_gpio13 {
+ pwm1_gpio13: pwm1-gpio13 {
brcm,pins = <13>;
brcm,function = <BCM2835_FSEL_ALT0>;
};
- pwm1_gpio19: pwm1_gpio19 {
+ pwm1_gpio19: pwm1-gpio19 {
brcm,pins = <19>;
brcm,function = <BCM2835_FSEL_ALT5>;
};
- pwm1_gpio41: pwm1_gpio41 {
+ pwm1_gpio41: pwm1-gpio41 {
brcm,pins = <41>;
brcm,function = <BCM2835_FSEL_ALT0>;
};
- pwm1_gpio45: pwm1_gpio45 {
+ pwm1_gpio45: pwm1-gpio45 {
brcm,pins = <45>;
brcm,function = <BCM2835_FSEL_ALT0>;
};
diff --git a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
index 9b9a18bbb20a..02ce817868ba 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-a-plus.dts
@@ -2,6 +2,8 @@
/dts-v1/;
#include "bcm2835.dtsi"
#include "bcm2835-rpi.dtsi"
+#include "bcm2835-rpi-common.dtsi"
+#include "bcm283x-rpi-led-deprecated.dtsi"
#include "bcm283x-rpi-usb-host.dtsi"
/ {
@@ -12,19 +14,6 @@
device_type = "memory";
reg = <0 0x10000000>;
};
-
- leds {
- led-act {
- gpios = <&gpio 47 GPIO_ACTIVE_HIGH>;
- };
-
- led-pwr {
- label = "PWR";
- gpios = <&gpio 35 GPIO_ACTIVE_HIGH>;
- default-state = "keep";
- linux,default-trigger = "default-on";
- };
- };
};
&gpio {
@@ -107,6 +96,19 @@
status = "okay";
};
+&led_act {
+ gpios = <&gpio 47 GPIO_ACTIVE_HIGH>;
+};
+
+&leds {
+ led-pwr {
+ label = "PWR";
+ gpios = <&gpio 35 GPIO_ACTIVE_HIGH>;
+ default-state = "keep";
+ linux,default-trigger = "default-on";
+ };
+};
+
&pwm {
pinctrl-names = "default";
pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio45>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi-a.dts b/arch/arm/boot/dts/bcm2835-rpi-a.dts
index f664e4fced93..3fdf60eb11dc 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-a.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-a.dts
@@ -2,6 +2,8 @@
/dts-v1/;
#include "bcm2835.dtsi"
#include "bcm2835-rpi.dtsi"
+#include "bcm2835-rpi-common.dtsi"
+#include "bcm283x-rpi-led-deprecated.dtsi"
#include "bcm283x-rpi-usb-host.dtsi"
/ {
@@ -12,12 +14,6 @@
device_type = "memory";
reg = <0 0x10000000>;
};
-
- leds {
- led-act {
- gpios = <&gpio 16 GPIO_ACTIVE_LOW>;
- };
- };
};
&gpio {
@@ -102,6 +98,10 @@
status = "okay";
};
+&led_act {
+ gpios = <&gpio 16 GPIO_ACTIVE_LOW>;
+};
+
&pwm {
pinctrl-names = "default";
pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio45>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
index 248feb2ed23d..9956fd06a4b6 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-b-plus.dts
@@ -2,6 +2,8 @@
/dts-v1/;
#include "bcm2835.dtsi"
#include "bcm2835-rpi.dtsi"
+#include "bcm2835-rpi-common.dtsi"
+#include "bcm283x-rpi-led-deprecated.dtsi"
#include "bcm283x-rpi-smsc9514.dtsi"
#include "bcm283x-rpi-usb-host.dtsi"
@@ -13,19 +15,6 @@
device_type = "memory";
reg = <0 0x20000000>;
};
-
- leds {
- led-act {
- gpios = <&gpio 47 GPIO_ACTIVE_HIGH>;
- };
-
- led-pwr {
- label = "PWR";
- gpios = <&gpio 35 GPIO_ACTIVE_HIGH>;
- default-state = "keep";
- linux,default-trigger = "default-on";
- };
- };
};
&gpio {
@@ -109,6 +98,19 @@
status = "okay";
};
+&led_act {
+ gpios = <&gpio 47 GPIO_ACTIVE_HIGH>;
+};
+
+&leds {
+ led-pwr {
+ label = "PWR";
+ gpios = <&gpio 35 GPIO_ACTIVE_HIGH>;
+ default-state = "keep";
+ linux,default-trigger = "default-on";
+ };
+};
+
&pwm {
pinctrl-names = "default";
pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio45>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
index f5b66d3f4ff3..4e1770afb145 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-b-rev2.dts
@@ -2,6 +2,8 @@
/dts-v1/;
#include "bcm2835.dtsi"
#include "bcm2835-rpi.dtsi"
+#include "bcm2835-rpi-common.dtsi"
+#include "bcm283x-rpi-led-deprecated.dtsi"
#include "bcm283x-rpi-smsc9512.dtsi"
#include "bcm283x-rpi-usb-host.dtsi"
@@ -13,12 +15,6 @@
device_type = "memory";
reg = <0 0x10000000>;
};
-
- leds {
- led-act {
- gpios = <&gpio 16 GPIO_ACTIVE_LOW>;
- };
- };
};
&gpio {
@@ -102,6 +98,10 @@
status = "okay";
};
+&led_act {
+ gpios = <&gpio 16 GPIO_ACTIVE_LOW>;
+};
+
&pwm {
pinctrl-names = "default";
pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio45>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi-b.dts b/arch/arm/boot/dts/bcm2835-rpi-b.dts
index f589bede2b11..eec1d0892d33 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-b.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-b.dts
@@ -2,6 +2,8 @@
/dts-v1/;
#include "bcm2835.dtsi"
#include "bcm2835-rpi.dtsi"
+#include "bcm2835-rpi-common.dtsi"
+#include "bcm283x-rpi-led-deprecated.dtsi"
#include "bcm283x-rpi-smsc9512.dtsi"
#include "bcm283x-rpi-usb-host.dtsi"
@@ -13,12 +15,6 @@
device_type = "memory";
reg = <0 0x10000000>;
};
-
- leds {
- led-act {
- gpios = <&gpio 16 GPIO_ACTIVE_LOW>;
- };
- };
};
&gpio {
@@ -96,6 +92,10 @@
status = "okay";
};
+&led_act {
+ gpios = <&gpio 16 GPIO_ACTIVE_LOW>;
+};
+
&pwm {
pinctrl-names = "default";
pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio45>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi b/arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi
index e4e6b6abbfc1..750cd76948e3 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi
+++ b/arch/arm/boot/dts/bcm2835-rpi-cm1.dtsi
@@ -2,6 +2,8 @@
/dts-v1/;
#include "bcm2835.dtsi"
#include "bcm2835-rpi.dtsi"
+#include "bcm2835-rpi-common.dtsi"
+#include "bcm283x-rpi-led-deprecated.dtsi"
/ {
leds {
@@ -32,6 +34,10 @@
};
};
+&led_act {
+ gpios = <&gpio 47 GPIO_ACTIVE_LOW>;
+};
+
&sdhost {
non-removable;
vmmc-supply = <&reg_3v3>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi-common.dtsi b/arch/arm/boot/dts/bcm2835-rpi-common.dtsi
index 8a55b6cded59..4e7b4a592da7 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-common.dtsi
+++ b/arch/arm/boot/dts/bcm2835-rpi-common.dtsi
@@ -7,6 +7,23 @@
#include <dt-bindings/power/raspberrypi-power.h>
+&firmware {
+ firmware_clocks: clocks {
+ compatible = "raspberrypi,firmware-clocks";
+ #clock-cells = <1>;
+ };
+};
+
+&hdmi {
+ clocks = <&firmware_clocks 9>,
+ <&firmware_clocks 13>;
+ clock-names = "pixel", "hdmi";
+};
+
&v3d {
power-domains = <&power RPI_POWER_DOMAIN_V3D>;
};
+
+&vec {
+ clocks = <&firmware_clocks 15>;
+};
diff --git a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
index 596bb1ef994e..dbf825985ec0 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-zero-w.dts
@@ -6,6 +6,8 @@
/dts-v1/;
#include "bcm2835.dtsi"
#include "bcm2835-rpi.dtsi"
+#include "bcm2835-rpi-common.dtsi"
+#include "bcm283x-rpi-led-deprecated.dtsi"
#include "bcm283x-rpi-usb-otg.dtsi"
#include "bcm283x-rpi-wifi-bt.dtsi"
@@ -22,12 +24,6 @@
/* 8250 auxiliary UART instead of pl011 */
stdout-path = "serial1:115200n8";
};
-
- leds {
- led-act {
- gpios = <&gpio 47 GPIO_ACTIVE_LOW>;
- };
- };
};
&bt {
@@ -110,6 +106,10 @@
status = "okay";
};
+&led_act {
+ gpios = <&gpio 47 GPIO_ACTIVE_LOW>;
+};
+
&sdhci {
pinctrl-0 = <&emmc_gpio34 &gpclk2_gpio43>;
};
diff --git a/arch/arm/boot/dts/bcm2835-rpi-zero.dts b/arch/arm/boot/dts/bcm2835-rpi-zero.dts
index a65c2bca69ea..f80e65a825fd 100644
--- a/arch/arm/boot/dts/bcm2835-rpi-zero.dts
+++ b/arch/arm/boot/dts/bcm2835-rpi-zero.dts
@@ -6,6 +6,8 @@
/dts-v1/;
#include "bcm2835.dtsi"
#include "bcm2835-rpi.dtsi"
+#include "bcm2835-rpi-common.dtsi"
+#include "bcm283x-rpi-led-deprecated.dtsi"
#include "bcm283x-rpi-usb-otg.dtsi"
/ {
@@ -16,12 +18,6 @@
device_type = "memory";
reg = <0 0x20000000>;
};
-
- leds {
- led-act {
- gpios = <&gpio 47 GPIO_ACTIVE_HIGH>;
- };
- };
};
&gpio {
@@ -104,6 +100,10 @@
status = "okay";
};
+&led_act {
+ gpios = <&gpio 47 GPIO_ACTIVE_HIGH>;
+};
+
&sdhost {
pinctrl-names = "default";
pinctrl-0 = <&sdhost_gpio48>;
diff --git a/arch/arm/boot/dts/bcm2835-rpi.dtsi b/arch/arm/boot/dts/bcm2835-rpi.dtsi
index 87ddcad76083..ee9ee9d1fe65 100644
--- a/arch/arm/boot/dts/bcm2835-rpi.dtsi
+++ b/arch/arm/boot/dts/bcm2835-rpi.dtsi
@@ -1,16 +1,6 @@
#include <dt-bindings/power/raspberrypi-power.h>
/ {
- leds {
- compatible = "gpio-leds";
-
- led-act {
- label = "ACT";
- default-state = "keep";
- linux,default-trigger = "heartbeat";
- };
- };
-
soc {
firmware: firmware {
compatible = "raspberrypi,bcm2835-firmware", "simple-mfd";
diff --git a/arch/arm/boot/dts/bcm2835.dtsi b/arch/arm/boot/dts/bcm2835.dtsi
index 1c90e5a44283..15cb331febbb 100644
--- a/arch/arm/boot/dts/bcm2835.dtsi
+++ b/arch/arm/boot/dts/bcm2835.dtsi
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include "bcm283x.dtsi"
#include "bcm2835-common.dtsi"
-#include "bcm2835-rpi-common.dtsi"
/ {
compatible = "brcm,bcm2835";
diff --git a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
index 3635502b1e0a..6068ec390081 100644
--- a/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
+++ b/arch/arm/boot/dts/bcm2836-rpi-2-b.dts
@@ -2,6 +2,7 @@
/dts-v1/;
#include "bcm2836.dtsi"
#include "bcm2836-rpi.dtsi"
+#include "bcm283x-rpi-led-deprecated.dtsi"
#include "bcm283x-rpi-smsc9514.dtsi"
#include "bcm283x-rpi-usb-host.dtsi"
@@ -13,19 +14,6 @@
device_type = "memory";
reg = <0 0x40000000>;
};
-
- leds {
- led-act {
- gpios = <&gpio 47 GPIO_ACTIVE_HIGH>;
- };
-
- led-pwr {
- label = "PWR";
- gpios = <&gpio 35 GPIO_ACTIVE_HIGH>;
- default-state = "keep";
- linux,default-trigger = "default-on";
- };
- };
};
&gpio {
@@ -109,6 +97,19 @@
status = "okay";
};
+&led_act {
+ gpios = <&gpio 47 GPIO_ACTIVE_HIGH>;
+};
+
+&leds {
+ led-pwr {
+ label = "PWR";
+ gpios = <&gpio 35 GPIO_ACTIVE_HIGH>;
+ default-state = "keep";
+ linux,default-trigger = "default-on";
+ };
+};
+
&pwm {
pinctrl-names = "default";
pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio45>;
diff --git a/arch/arm/boot/dts/bcm2836-rpi.dtsi b/arch/arm/boot/dts/bcm2836-rpi.dtsi
index c4c858b984c6..48b03b55ff56 100644
--- a/arch/arm/boot/dts/bcm2836-rpi.dtsi
+++ b/arch/arm/boot/dts/bcm2836-rpi.dtsi
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include "bcm2835-rpi.dtsi"
+#include "bcm2835-rpi-common.dtsi"
&vchiq {
compatible = "brcm,bcm2836-vchiq", "brcm,bcm2835-vchiq";
diff --git a/arch/arm/boot/dts/bcm2836.dtsi b/arch/arm/boot/dts/bcm2836.dtsi
index 534dacfc4dd5..783fe624ba68 100644
--- a/arch/arm/boot/dts/bcm2836.dtsi
+++ b/arch/arm/boot/dts/bcm2836.dtsi
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
#include "bcm283x.dtsi"
#include "bcm2835-common.dtsi"
-#include "bcm2835-rpi-common.dtsi"
/ {
compatible = "brcm,bcm2836";
@@ -11,7 +10,7 @@
<0x40000000 0x40000000 0x00001000>;
dma-ranges = <0xc0000000 0x00000000 0x3f000000>;
- local_intc: local_intc@40000000 {
+ local_intc: interrupt-controller@40000000 {
compatible = "brcm,bcm2836-l1-intc";
reg = <0x40000000 0x100>;
interrupt-controller;
@@ -113,6 +112,7 @@
*/
l2: l2-cache0 {
compatible = "cache";
+ cache-unified;
cache-size = <0x80000>;
cache-line-size = <64>;
cache-sets = <1024>; // 512KiB(size)/64(line-size)=8192ways/8-way set
diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts b/arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts
index f7222a28903e..3548306dfbcb 100644
--- a/arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts
+++ b/arch/arm/boot/dts/bcm2837-rpi-3-a-plus.dts
@@ -2,6 +2,7 @@
/dts-v1/;
#include "bcm2837.dtsi"
#include "bcm2836-rpi.dtsi"
+#include "bcm283x-rpi-led-deprecated.dtsi"
#include "bcm283x-rpi-usb-host.dtsi"
#include "bcm283x-rpi-wifi-bt.dtsi"
@@ -18,19 +19,6 @@
device_type = "memory";
reg = <0 0x20000000>;
};
-
- leds {
- led-act {
- gpios = <&gpio 29 GPIO_ACTIVE_HIGH>;
- };
-
- led-pwr {
- label = "PWR";
- gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
- default-state = "keep";
- linux,default-trigger = "default-on";
- };
- };
};
&firmware {
@@ -124,6 +112,19 @@
status = "okay";
};
+&led_act {
+ gpios = <&gpio 29 GPIO_ACTIVE_HIGH>;
+};
+
+&leds {
+ led-pwr {
+ label = "PWR";
+ gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
+ default-state = "keep";
+ linux,default-trigger = "default-on";
+ };
+};
+
&pwm {
pinctrl-names = "default";
pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio41>;
diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
index ec721d323ac5..2f1800cbc522 100644
--- a/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
+++ b/arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts
@@ -3,6 +3,7 @@
#include "bcm2837.dtsi"
#include "bcm2836-rpi.dtsi"
#include "bcm283x-rpi-lan7515.dtsi"
+#include "bcm283x-rpi-led-deprecated.dtsi"
#include "bcm283x-rpi-usb-host.dtsi"
#include "bcm283x-rpi-wifi-bt.dtsi"
@@ -19,19 +20,6 @@
device_type = "memory";
reg = <0 0x40000000>;
};
-
- leds {
- led-act {
- gpios = <&gpio 29 GPIO_ACTIVE_HIGH>;
- };
-
- led-pwr {
- label = "PWR";
- gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
- default-state = "keep";
- linux,default-trigger = "default-on";
- };
- };
};
&bt {
@@ -130,6 +118,19 @@
status = "okay";
};
+&led_act {
+ gpios = <&gpio 29 GPIO_ACTIVE_HIGH>;
+};
+
+&leds {
+ led-pwr {
+ label = "PWR";
+ gpios = <&expgpio 2 GPIO_ACTIVE_LOW>;
+ default-state = "keep";
+ linux,default-trigger = "default-on";
+ };
+};
+
&pwm {
pinctrl-names = "default";
pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio41>;
diff --git a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
index fb6a417d73e7..61270340075c 100644
--- a/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
+++ b/arch/arm/boot/dts/bcm2837-rpi-3-b.dts
@@ -2,6 +2,7 @@
/dts-v1/;
#include "bcm2837.dtsi"
#include "bcm2836-rpi.dtsi"
+#include "bcm283x-rpi-led-deprecated.dtsi"
#include "bcm283x-rpi-smsc9514.dtsi"
#include "bcm283x-rpi-usb-host.dtsi"
#include "bcm283x-rpi-wifi-bt.dtsi"
@@ -19,12 +20,6 @@
device_type = "memory";
reg = <0 0x40000000>;
};
-
- leds {
- led-act {
- gpios = <&expgpio 2 GPIO_ACTIVE_HIGH>;
- };
- };
};
&bt {
@@ -129,6 +124,10 @@
status = "okay";
};
+&led_act {
+ gpios = <&expgpio 2 GPIO_ACTIVE_HIGH>;
+};
+
/* uart0 communicates with the BT module */
&uart0 {
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi b/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi
index f57b4ca145dd..1e4e4946b6b6 100644
--- a/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi
+++ b/arch/arm/boot/dts/bcm2837-rpi-cm3.dtsi
@@ -9,14 +9,6 @@
reg = <0 0x40000000>;
};
- leds {
- /*
- * Since there is no upstream GPIO driver yet,
- * remove the incomplete node.
- */
- /delete-node/ led-act;
- };
-
reg_3v3: fixed-regulator {
compatible = "regulator-fixed";
regulator-name = "3V3";
diff --git a/arch/arm/boot/dts/bcm2837-rpi-zero-2-w.dts b/arch/arm/boot/dts/bcm2837-rpi-zero-2-w.dts
index 4a768562985e..b9cc4594398b 100644
--- a/arch/arm/boot/dts/bcm2837-rpi-zero-2-w.dts
+++ b/arch/arm/boot/dts/bcm2837-rpi-zero-2-w.dts
@@ -6,6 +6,7 @@
/dts-v1/;
#include "bcm2837.dtsi"
#include "bcm2836-rpi.dtsi"
+#include "bcm283x-rpi-led-deprecated.dtsi"
#include "bcm283x-rpi-usb-otg.dtsi"
#include "bcm283x-rpi-wifi-bt.dtsi"
@@ -22,12 +23,6 @@
/* 8250 auxiliary UART instead of pl011 */
stdout-path = "serial1:115200n8";
};
-
- leds {
- led-act {
- gpios = <&gpio 29 GPIO_ACTIVE_LOW>;
- };
- };
};
&bt {
@@ -109,6 +104,10 @@
status = "okay";
};
+&led_act {
+ gpios = <&gpio 29 GPIO_ACTIVE_LOW>;
+};
+
&sdhci {
pinctrl-0 = <&emmc_gpio34 &gpclk2_gpio43>;
};
diff --git a/arch/arm/boot/dts/bcm2837.dtsi b/arch/arm/boot/dts/bcm2837.dtsi
index 5dbdebc46259..84c08b46519d 100644
--- a/arch/arm/boot/dts/bcm2837.dtsi
+++ b/arch/arm/boot/dts/bcm2837.dtsi
@@ -1,6 +1,5 @@
#include "bcm283x.dtsi"
#include "bcm2835-common.dtsi"
-#include "bcm2835-rpi-common.dtsi"
/ {
compatible = "brcm,bcm2837";
@@ -115,6 +114,7 @@
*/
l2: l2-cache0 {
compatible = "cache";
+ cache-unified;
cache-size = <0x80000>;
cache-line-size = <64>;
cache-sets = <512>; // 512KiB(size)/64(line-size)=8192ways/16-way set
diff --git a/arch/arm/boot/dts/bcm283x-rpi-led-deprecated.dtsi b/arch/arm/boot/dts/bcm283x-rpi-led-deprecated.dtsi
new file mode 100644
index 000000000000..f83e56de1a72
--- /dev/null
+++ b/arch/arm/boot/dts/bcm283x-rpi-led-deprecated.dtsi
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/ {
+ /*
+ * This file provides the now deprecated ACT LED to the
+ * Raspberry Pi boards. Please don't include this file
+ * for new boards!
+ */
+ leds: leds {
+ compatible = "gpio-leds";
+
+ led_act: led-act {
+ label = "ACT";
+ default-state = "keep";
+ linux,default-trigger = "heartbeat";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/bcm283x.dtsi b/arch/arm/boot/dts/bcm283x.dtsi
index d2d9c6e67f39..c9c52a19ef3b 100644
--- a/arch/arm/boot/dts/bcm283x.dtsi
+++ b/arch/arm/boot/dts/bcm283x.dtsi
@@ -135,17 +135,17 @@
* groups only make sense to switch to a
* particular function together.
*/
- dpi_gpio0: dpi_gpio0 {
+ dpi_gpio0: dpi-gpio0 {
brcm,pins = <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>;
brcm,function = <BCM2835_FSEL_ALT2>;
};
- emmc_gpio22: emmc_gpio22 {
+ emmc_gpio22: emmc-gpio22 {
brcm,pins = <22 23 24 25 26 27>;
brcm,function = <BCM2835_FSEL_ALT3>;
};
- emmc_gpio34: emmc_gpio34 {
+ emmc_gpio34: emmc-gpio34 {
brcm,pins = <34 35 36 37 38 39>;
brcm,function = <BCM2835_FSEL_ALT3>;
brcm,pull = <BCM2835_PUD_OFF
@@ -155,95 +155,95 @@
BCM2835_PUD_UP
BCM2835_PUD_UP>;
};
- emmc_gpio48: emmc_gpio48 {
+ emmc_gpio48: emmc-gpio48 {
brcm,pins = <48 49 50 51 52 53>;
brcm,function = <BCM2835_FSEL_ALT3>;
};
- gpclk0_gpio4: gpclk0_gpio4 {
+ gpclk0_gpio4: gpclk0-gpio4 {
brcm,pins = <4>;
brcm,function = <BCM2835_FSEL_ALT0>;
};
- gpclk1_gpio5: gpclk1_gpio5 {
+ gpclk1_gpio5: gpclk1-gpio5 {
brcm,pins = <5>;
brcm,function = <BCM2835_FSEL_ALT0>;
};
- gpclk1_gpio42: gpclk1_gpio42 {
+ gpclk1_gpio42: gpclk1-gpio42 {
brcm,pins = <42>;
brcm,function = <BCM2835_FSEL_ALT0>;
};
- gpclk1_gpio44: gpclk1_gpio44 {
+ gpclk1_gpio44: gpclk1-gpio44 {
brcm,pins = <44>;
brcm,function = <BCM2835_FSEL_ALT0>;
};
- gpclk2_gpio6: gpclk2_gpio6 {
+ gpclk2_gpio6: gpclk2-gpio6 {
brcm,pins = <6>;
brcm,function = <BCM2835_FSEL_ALT0>;
};
- gpclk2_gpio43: gpclk2_gpio43 {
+ gpclk2_gpio43: gpclk2-gpio43 {
brcm,pins = <43>;
brcm,function = <BCM2835_FSEL_ALT0>;
brcm,pull = <BCM2835_PUD_OFF>;
};
- i2c0_gpio0: i2c0_gpio0 {
+ i2c0_gpio0: i2c0-gpio0 {
brcm,pins = <0 1>;
brcm,function = <BCM2835_FSEL_ALT0>;
};
- i2c0_gpio28: i2c0_gpio28 {
+ i2c0_gpio28: i2c0-gpio28 {
brcm,pins = <28 29>;
brcm,function = <BCM2835_FSEL_ALT0>;
};
- i2c0_gpio44: i2c0_gpio44 {
+ i2c0_gpio44: i2c0-gpio44 {
brcm,pins = <44 45>;
brcm,function = <BCM2835_FSEL_ALT1>;
};
- i2c1_gpio2: i2c1_gpio2 {
+ i2c1_gpio2: i2c1-gpio2 {
brcm,pins = <2 3>;
brcm,function = <BCM2835_FSEL_ALT0>;
};
- i2c1_gpio44: i2c1_gpio44 {
+ i2c1_gpio44: i2c1-gpio44 {
brcm,pins = <44 45>;
brcm,function = <BCM2835_FSEL_ALT2>;
};
- jtag_gpio22: jtag_gpio22 {
+ jtag_gpio22: jtag-gpio22 {
brcm,pins = <22 23 24 25 26 27>;
brcm,function = <BCM2835_FSEL_ALT4>;
};
- pcm_gpio18: pcm_gpio18 {
+ pcm_gpio18: pcm-gpio18 {
brcm,pins = <18 19 20 21>;
brcm,function = <BCM2835_FSEL_ALT0>;
};
- pcm_gpio28: pcm_gpio28 {
+ pcm_gpio28: pcm-gpio28 {
brcm,pins = <28 29 30 31>;
brcm,function = <BCM2835_FSEL_ALT2>;
};
- sdhost_gpio48: sdhost_gpio48 {
+ sdhost_gpio48: sdhost-gpio48 {
brcm,pins = <48 49 50 51 52 53>;
brcm,function = <BCM2835_FSEL_ALT0>;
};
- spi0_gpio7: spi0_gpio7 {
+ spi0_gpio7: spi0-gpio7 {
brcm,pins = <7 8 9 10 11>;
brcm,function = <BCM2835_FSEL_ALT0>;
};
- spi0_gpio35: spi0_gpio35 {
+ spi0_gpio35: spi0-gpio35 {
brcm,pins = <35 36 37 38 39>;
brcm,function = <BCM2835_FSEL_ALT0>;
};
- spi1_gpio16: spi1_gpio16 {
+ spi1_gpio16: spi1-gpio16 {
brcm,pins = <16 17 18 19 20 21>;
brcm,function = <BCM2835_FSEL_ALT4>;
};
- spi2_gpio40: spi2_gpio40 {
+ spi2_gpio40: spi2-gpio40 {
brcm,pins = <40 41 42 43 44 45>;
brcm,function = <BCM2835_FSEL_ALT4>;
};
- uart0_gpio14: uart0_gpio14 {
+ uart0_gpio14: uart0-gpio14 {
brcm,pins = <14 15>;
brcm,function = <BCM2835_FSEL_ALT0>;
};
@@ -252,50 +252,50 @@
* people often run uart0 on the two pins
* without flow control.
*/
- uart0_ctsrts_gpio16: uart0_ctsrts_gpio16 {
+ uart0_ctsrts_gpio16: uart0-ctsrts-gpio16 {
brcm,pins = <16 17>;
brcm,function = <BCM2835_FSEL_ALT3>;
};
- uart0_ctsrts_gpio30: uart0_ctsrts_gpio30 {
+ uart0_ctsrts_gpio30: uart0-ctsrts-gpio30 {
brcm,pins = <30 31>;
brcm,function = <BCM2835_FSEL_ALT3>;
brcm,pull = <BCM2835_PUD_UP BCM2835_PUD_OFF>;
};
- uart0_gpio32: uart0_gpio32 {
+ uart0_gpio32: uart0-gpio32 {
brcm,pins = <32 33>;
brcm,function = <BCM2835_FSEL_ALT3>;
brcm,pull = <BCM2835_PUD_OFF BCM2835_PUD_UP>;
};
- uart0_gpio36: uart0_gpio36 {
+ uart0_gpio36: uart0-gpio36 {
brcm,pins = <36 37>;
brcm,function = <BCM2835_FSEL_ALT2>;
};
- uart0_ctsrts_gpio38: uart0_ctsrts_gpio38 {
+ uart0_ctsrts_gpio38: uart0-ctsrts-gpio38 {
brcm,pins = <38 39>;
brcm,function = <BCM2835_FSEL_ALT2>;
};
- uart1_gpio14: uart1_gpio14 {
+ uart1_gpio14: uart1-gpio14 {
brcm,pins = <14 15>;
brcm,function = <BCM2835_FSEL_ALT5>;
};
- uart1_ctsrts_gpio16: uart1_ctsrts_gpio16 {
+ uart1_ctsrts_gpio16: uart1-ctsrts-gpio16 {
brcm,pins = <16 17>;
brcm,function = <BCM2835_FSEL_ALT5>;
};
- uart1_gpio32: uart1_gpio32 {
+ uart1_gpio32: uart1-gpio32 {
brcm,pins = <32 33>;
brcm,function = <BCM2835_FSEL_ALT5>;
};
- uart1_ctsrts_gpio30: uart1_ctsrts_gpio30 {
+ uart1_ctsrts_gpio30: uart1-ctsrts-gpio30 {
brcm,pins = <30 31>;
brcm,function = <BCM2835_FSEL_ALT5>;
};
- uart1_gpio40: uart1_gpio40 {
+ uart1_gpio40: uart1-gpio40 {
brcm,pins = <40 41>;
brcm,function = <BCM2835_FSEL_ALT5>;
};
- uart1_ctsrts_gpio42: uart1_ctsrts_gpio42 {
+ uart1_ctsrts_gpio42: uart1-ctsrts-gpio42 {
brcm,pins = <42 43>;
brcm,function = <BCM2835_FSEL_ALT5>;
};
diff --git a/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts b/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts
index 09ee3e46c0cc..c80ac16ad949 100644
--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts
+++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts
@@ -28,40 +28,39 @@
leds {
compatible = "gpio-leds";
- usb3 {
+ led-usb3 {
label = "bcm53xx:blue:usb3";
gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
};
- wan {
+ led-wan {
label = "bcm53xx:blue:wan";
gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
};
- lan {
+ led-lan {
label = "bcm53xx:blue:lan";
gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
};
- power {
+ led-power {
label = "bcm53xx:blue:power";
gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
};
- all {
+ led-all {
label = "bcm53xx:blue:all";
gpios = <&chipcommon 4 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
};
- 2ghz {
+ led-2ghz {
label = "bcm53xx:blue:2ghz";
gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>;
};
-
- usb2 {
+ led-usb2 {
label = "bcm53xx:blue:usb2";
gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts b/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts
index 32619c6045d3..3fe17bd7b86d 100644
--- a/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts
+++ b/arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts
@@ -28,24 +28,24 @@
leds {
compatible = "gpio-leds";
- usb2 {
+ led-usb2 {
label = "bcm53xx:blue:usb2";
gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
};
- power {
+ led-power {
label = "bcm53xx:blue:power";
gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
};
- logo {
+ led-logo {
label = "bcm53xx:white:logo";
gpios = <&chipcommon 4 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
};
- usb3 {
+ led-usb3 {
label = "bcm53xx:blue:usb3";
gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1166dhp-common.dtsi b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1166dhp-common.dtsi
index a658b9b7bcec..e583b9cbf07c 100644
--- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1166dhp-common.dtsi
+++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1166dhp-common.dtsi
@@ -37,7 +37,7 @@
leds {
compatible = "gpio-leds";
- usb {
+ led-usb {
/* label = "bcm53xx:blue:usb"; */
function = LED_FUNCTION_USB;
color = <LED_COLOR_ID_BLUE>;
@@ -48,14 +48,14 @@
linux,default-trigger = "usbport";
};
- power0 {
+ led-power0 {
/* label = "bcm53xx:red:power"; */
function = LED_FUNCTION_FAULT;
color = <LED_COLOR_ID_RED>;
gpios = <&hc595 1 GPIO_ACTIVE_HIGH>;
};
- power1 {
+ led-power1 {
/* label = "bcm53xx:white:power"; */
function = LED_FUNCTION_POWER;
color = <LED_COLOR_ID_WHITE>;
@@ -63,7 +63,7 @@
linux,default-trigger = "default-on";
};
- router0 {
+ led-router0 {
/* label = "bcm53xx:blue:router"; */
function = LED_FUNCTION_STATUS;
color = <LED_COLOR_ID_BLUE>;
@@ -71,14 +71,14 @@
linux,default-trigger = "default-on";
};
- router1 {
+ led-router1 {
/* label = "bcm53xx:amber:router"; */
function = LED_FUNCTION_STATUS;
color = <LED_COLOR_ID_AMBER>;
gpios = <&hc595 4 GPIO_ACTIVE_HIGH>;
};
- wan {
+ led-wan {
/* label = "bcm53xx:blue:wan"; */
function = LED_FUNCTION_WAN;
color = <LED_COLOR_ID_BLUE>;
@@ -86,14 +86,14 @@
linux,default-trigger = "default-on";
};
- wireless0 {
+ led-wireless0 {
/* label = "bcm53xx:blue:wireless"; */
function = LED_FUNCTION_WLAN;
color = <LED_COLOR_ID_BLUE>;
gpios = <&hc595 6 GPIO_ACTIVE_HIGH>;
};
- wireless1 {
+ led-wireless1 {
/* label = "bcm53xx:amber:wireless"; */
function = LED_FUNCTION_WLAN;
color = <LED_COLOR_ID_AMBER>;
diff --git a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
index f8f53457dd43..43c698a0a7c3 100644
--- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
+++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
@@ -49,7 +49,7 @@
leds {
compatible = "gpio-leds";
- usb {
+ led-usb {
label = "bcm53xx:blue:usb";
gpios = <&hc595 0 GPIO_ACTIVE_HIGH>;
trigger-sources = <&ohci_port1>, <&ehci_port1>,
@@ -58,40 +58,40 @@
linux,default-trigger = "usbport";
};
- power0 {
+ led-power0 {
label = "bcm53xx:red:power";
gpios = <&hc595 1 GPIO_ACTIVE_HIGH>;
};
- power1 {
+ led-power1 {
label = "bcm53xx:white:power";
gpios = <&hc595 2 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "default-on";
};
- router0 {
+ led-router0 {
label = "bcm53xx:blue:router";
gpios = <&hc595 3 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "default-on";
};
- router1 {
+ led-router1 {
label = "bcm53xx:amber:router";
gpios = <&hc595 4 GPIO_ACTIVE_HIGH>;
};
- wan {
+ led-wan {
label = "bcm53xx:blue:wan";
gpios = <&hc595 5 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "default-on";
};
- wireless0 {
+ led-wireless0 {
label = "bcm53xx:blue:wireless";
gpios = <&hc595 6 GPIO_ACTIVE_HIGH>;
};
- wireless1 {
+ led-wireless1 {
label = "bcm53xx:amber:wireless";
gpios = <&hc595 7 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts b/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
index 14ee410183af..6de7fe204b0c 100644
--- a/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
+++ b/arch/arm/boot/dts/bcm4708-luxul-xap-1510.dts
@@ -23,19 +23,19 @@
leds {
compatible = "gpio-leds";
- 5ghz {
+ led-5ghz {
label = "bcm53xx:blue:5ghz";
gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
linux,default-trigger = "none";
};
- 2ghz {
+ led-2ghz {
label = "bcm53xx:blue:2ghz";
gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
linux,default-trigger = "none";
};
- status {
+ led-status {
label = "bcm53xx:green:status";
gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>;
linux,default-trigger = "timer";
diff --git a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
index 600ab087f5e5..f5b75ba93512 100644
--- a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
+++ b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
@@ -42,7 +42,7 @@
leds {
compatible = "gpio-leds";
- status {
+ led-status {
label = "bcm53xx:green:status";
gpios = <&chipcommon 0 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
diff --git a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts
index fd6d8d2a4456..89155caf50be 100644
--- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts
+++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts
@@ -29,24 +29,24 @@
leds {
compatible = "gpio-leds";
- logo {
+ led-logo {
label = "bcm53xx:white:logo";
gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "default-on";
};
- power0 {
+ led-power0 {
label = "bcm53xx:green:power";
gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
};
- power1 {
+ led-power1 {
label = "bcm53xx:amber:power";
gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
};
- usb {
+ led-usb {
label = "bcm53xx:blue:usb";
gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
trigger-sources = <&ohci_port1>, <&ehci_port1>,
@@ -54,7 +54,7 @@
linux,default-trigger = "usbport";
};
- wireless {
+ led-wireless {
label = "bcm53xx:blue:wireless";
gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts b/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts
index 76fc1099d47d..57d00a0b4765 100644
--- a/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts
+++ b/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts
@@ -28,29 +28,29 @@
leds {
compatible = "gpio-leds";
- logo {
+ led-logo {
label = "bcm53xx:white:logo";
gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "default-on";
};
- power0 {
+ led-power0 {
label = "bcm53xx:green:power";
gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
};
- power1 {
+ led-power1 {
label = "bcm53xx:amber:power";
gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
};
- usb {
+ led-usb {
label = "bcm53xx:blue:usb";
gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
};
- wireless {
+ led-wireless {
label = "bcm53xx:blue:wireless";
gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
index 6bcdfb73cb9e..26cdeb5cc337 100644
--- a/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
+++ b/arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
@@ -28,64 +28,64 @@
leds {
compatible = "gpio-leds";
- power-white {
+ led-power-white {
label = "bcm53xx:white:power";
gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "default-on";
};
- power-amber {
+ led-power-amber {
label = "bcm53xx:amber:power";
gpios = <&chipcommon 2 GPIO_ACTIVE_HIGH>;
};
- usb2 {
+ led-usb2 {
label = "bcm53xx:white:usb2";
gpios = <&chipcommon 3 GPIO_ACTIVE_HIGH>;
trigger-sources = <&ohci_port2>, <&ehci_port2>;
linux,default-trigger = "usbport";
};
- usb3-white {
+ led-usb3-white {
label = "bcm53xx:white:usb3";
gpios = <&chipcommon 4 GPIO_ACTIVE_HIGH>;
trigger-sources = <&xhci_port1>;
linux,default-trigger = "usbport";
};
- usb3-green {
+ led-usb3-green {
label = "bcm53xx:green:usb3";
gpios = <&chipcommon 5 GPIO_ACTIVE_HIGH>;
trigger-sources = <&ohci_port1>, <&ehci_port1>;
linux,default-trigger = "usbport";
};
- wps {
+ led-wps {
label = "bcm53xx:white:wps";
gpios = <&chipcommon 6 GPIO_ACTIVE_HIGH>;
};
- status-red {
+ led-status-red {
label = "bcm53xx:red:status";
gpios = <&chipcommon 8 GPIO_ACTIVE_HIGH>;
};
- status-green {
+ led-status-green {
label = "bcm53xx:green:status";
gpios = <&chipcommon 9 GPIO_ACTIVE_HIGH>;
};
- status-blue {
+ led-status-blue {
label = "bcm53xx:blue:status";
gpios = <&chipcommon 10 GPIO_ACTIVE_HIGH>;
};
- wan-white {
+ led-wan-white {
label = "bcm53xx:white:wan";
gpios = <&chipcommon 12 GPIO_ACTIVE_HIGH>;
};
- wan-red {
+ led-wan-red {
label = "bcm53xx:red:wan";
gpios = <&chipcommon 13 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts
index ca47cc4f2ba1..3854db0118a9 100644
--- a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts
+++ b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts
@@ -28,30 +28,30 @@
leds {
compatible = "gpio-leds";
- power {
+ led-power {
label = "bcm53xx:blue:power";
gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
};
- usb2 {
+ led-usb2 {
label = "bcm53xx:blue:usb2";
gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
};
- wan {
+ led-wan {
label = "bcm53xx:blue:wan";
gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
};
- lan {
+ led-lan {
label = "bcm53xx:blue:lan";
gpios = <&chipcommon 9 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
};
- usb3 {
+ led-usb3 {
label = "bcm53xx:blue:usb3";
gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
index 0edc2543e568..407319cb5c0d 100644
--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
+++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
@@ -49,40 +49,40 @@
leds {
compatible = "gpio-leds";
- power0 {
+ led-power0 {
label = "bcm53xx:green:power";
gpios = <&hc595 1 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "default-on";
};
- power1 {
+ led-power1 {
label = "bcm53xx:red:power";
gpios = <&hc595 2 GPIO_ACTIVE_HIGH>;
};
- router0 {
+ led-router0 {
label = "bcm53xx:green:router";
gpios = <&hc595 3 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "default-on";
};
- router1 {
+ led-router1 {
label = "bcm53xx:amber:router";
gpios = <&hc595 4 GPIO_ACTIVE_HIGH>;
};
- wan {
+ led-wan {
label = "bcm53xx:green:wan";
gpios = <&hc595 5 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "default-on";
};
- wireless0 {
+ led-wireless0 {
label = "bcm53xx:green:wireless";
gpios = <&hc595 6 GPIO_ACTIVE_HIGH>;
};
- wireless1 {
+ led-wireless1 {
label = "bcm53xx:amber:wireless";
gpios = <&hc595 7 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts b/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts
index 1f0998f34afd..f8622ecce6a2 100644
--- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts
+++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts
@@ -49,45 +49,45 @@
leds {
compatible = "gpio-leds";
- usb {
+ led-usb {
label = "bcm53xx:green:usb";
gpios = <&hc595 0 GPIO_ACTIVE_HIGH>;
};
- power0 {
+ led-power0 {
label = "bcm53xx:green:power";
gpios = <&hc595 1 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "default-on";
};
- power1 {
+ led-power1 {
label = "bcm53xx:red:power";
gpios = <&hc595 2 GPIO_ACTIVE_HIGH>;
};
- router0 {
+ led-router0 {
label = "bcm53xx:green:router";
gpios = <&hc595 3 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "default-on";
};
- router1 {
+ led-router1 {
label = "bcm53xx:amber:router";
gpios = <&hc595 4 GPIO_ACTIVE_HIGH>;
};
- wan {
+ led-wan {
label = "bcm53xx:green:wan";
gpios = <&hc595 5 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "default-on";
};
- wireless0 {
+ led-wireless0 {
label = "bcm53xx:green:wireless";
gpios = <&hc595 6 GPIO_ACTIVE_HIGH>;
};
- wireless1 {
+ led-wireless1 {
label = "bcm53xx:amber:wireless";
gpios = <&hc595 7 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm/boot/dts/bcm47081-luxul-xap-1410.dts b/arch/arm/boot/dts/bcm47081-luxul-xap-1410.dts
index c8c02377543b..76c9b30b868d 100644
--- a/arch/arm/boot/dts/bcm47081-luxul-xap-1410.dts
+++ b/arch/arm/boot/dts/bcm47081-luxul-xap-1410.dts
@@ -23,19 +23,19 @@
leds {
compatible = "gpio-leds";
- 5ghz {
+ led-5ghz {
label = "bcm53xx:blue:5ghz";
gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
linux,default-trigger = "none";
};
- 2ghz {
+ led-2ghz {
label = "bcm53xx:blue:2ghz";
gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
linux,default-trigger = "none";
};
- status {
+ led-status {
label = "bcm53xx:green:status";
gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>;
linux,default-trigger = "timer";
diff --git a/arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts b/arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts
index 3b35a7af4b1c..6ef0c0788e62 100644
--- a/arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts
+++ b/arch/arm/boot/dts/bcm47081-luxul-xwr-1200.dts
@@ -29,62 +29,62 @@
leds {
compatible = "gpio-leds";
- power {
+ led-power {
label = "bcm53xx:green:power";
gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
};
- lan3 {
+ led-lan3 {
label = "bcm53xx:green:lan3";
gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
linux,default-trigger = "none";
};
- lan4 {
+ led-lan4 {
label = "bcm53xx:green:lan4";
gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
linux,default-trigger = "none";
};
- wan {
+ led-wan {
label = "bcm53xx:green:wan";
gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
linux,default-trigger = "none";
};
- lan2 {
+ led-lan2 {
label = "bcm53xx:green:lan2";
gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>;
linux,default-trigger = "none";
};
- usb {
+ led-usb {
label = "bcm53xx:green:usb";
gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
trigger-sources = <&ohci_port2>, <&ehci_port2>;
linux,default-trigger = "usbport";
};
- status {
+ led-status {
label = "bcm53xx:green:status";
gpios = <&chipcommon 10 GPIO_ACTIVE_LOW>;
linux,default-trigger = "timer";
};
- 2ghz {
+ led-2ghz {
label = "bcm53xx:green:2ghz";
gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
linux,default-trigger = "none";
};
- 5ghz {
+ led-5ghz {
label = "bcm53xx:green:5ghz";
gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
linux,default-trigger = "none";
};
- lan1 {
+ led-lan1 {
label = "bcm53xx:green:lan1";
gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>;
linux,default-trigger = "none";
diff --git a/arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts b/arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts
index 19a7971b5a00..b6a5886698b2 100644
--- a/arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts
+++ b/arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts
@@ -23,50 +23,50 @@
leds {
compatible = "gpio-leds";
- 2ghz {
+ led-2ghz {
label = "bcm53xx:green:2ghz";
gpios = <&chipcommon 0 GPIO_ACTIVE_HIGH>;
};
- lan {
+ led-lan {
label = "bcm53xx:green:lan";
gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>;
};
- usb2-port1 {
+ led-usb2-port1 {
label = "bcm53xx:green:usb2-port1";
gpios = <&chipcommon 2 GPIO_ACTIVE_HIGH>;
trigger-sources = <&ohci_port1>, <&ehci_port1>;
linux,default-trigger = "usbport";
};
- power {
+ led-power {
label = "bcm53xx:green:power";
gpios = <&chipcommon 4 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "default-on";
};
- wan-green {
+ led-wan-green {
label = "bcm53xx:green:wan";
gpios = <&chipcommon 5 GPIO_ACTIVE_HIGH>;
};
- wps {
+ led-wps {
label = "bcm53xx:green:wps";
gpios = <&chipcommon 6 GPIO_ACTIVE_HIGH>;
};
- wan-amber {
+ led-wan-amber {
label = "bcm53xx:amber:wan";
gpios = <&chipcommon 8 GPIO_ACTIVE_HIGH>;
};
- 5ghz {
+ led-5ghz {
label = "bcm53xx:green:5ghz";
gpios = <&chipcommon 12 GPIO_ACTIVE_HIGH>;
};
- usb2-port2 {
+ led-usb2-port2 {
label = "bcm53xx:green:usb2-port2";
gpios = <&chipcommon 13 GPIO_ACTIVE_HIGH>;
trigger-sources = <&ohci_port2>, <&ehci_port2>;
@@ -95,30 +95,15 @@
status = "okay";
partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- boot@0 {
- label = "boot";
- reg = <0x000000 0x040000>;
- read-only;
- };
+ compatible = "tplink,safeloader-partitions";
+ partitions-table-offset = <0xe50000>;
- os-image@100000 {
- label = "os-image";
- reg = <0x040000 0x200000>;
+ partition-os-image {
compatible = "brcm,trx";
};
- rootfs@240000 {
- label = "rootfs";
- reg = <0x240000 0xc00000>;
- };
-
- nvram@ff0000 {
- label = "nvram";
- reg = <0xff0000 0x010000>;
+ partition-file-system {
+ linux,rootfs;
};
};
};
diff --git a/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts
index f52a75c4ca09..4f44cb4df704 100644
--- a/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts
+++ b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts
@@ -28,18 +28,18 @@
leds {
compatible = "gpio-leds";
- wps {
+ led-wps {
label = "bcm53xx:blue:wps";
gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
};
- power {
+ led-power {
label = "bcm53xx:blue:power";
gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
};
- wan {
+ led-wan {
label = "bcm53xx:red:wan";
gpios = <&chipcommon 5 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
index 5ff6c588e16e..b7cd2faa30ce 100644
--- a/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
+++ b/arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
@@ -28,48 +28,48 @@
leds {
compatible = "gpio-leds";
- usb {
+ led-usb {
label = "bcm53xx:green:usb";
gpios = <&chipcommon 4 GPIO_ACTIVE_HIGH>;
};
- power-amber {
+ led-power-amber {
label = "bcm53xx:amber:power";
gpios = <&chipcommon 5 GPIO_ACTIVE_HIGH>;
};
- power-white {
+ led-power-white {
label = "bcm53xx:white:power";
gpios = <&chipcommon 6 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "default-on";
};
- router-amber {
+ led-router-amber {
label = "bcm53xx:amber:router";
gpios = <&chipcommon 7 GPIO_ACTIVE_HIGH>;
};
- router-white {
+ led-router-white {
label = "bcm53xx:white:router";
gpios = <&chipcommon 8 GPIO_ACTIVE_HIGH>;
};
- wan-amber {
+ led-wan-amber {
label = "bcm53xx:amber:wan";
gpios = <&chipcommon 9 GPIO_ACTIVE_HIGH>;
};
- wan-white {
+ led-wan-white {
label = "bcm53xx:white:wan";
gpios = <&chipcommon 10 GPIO_ACTIVE_HIGH>;
};
- wireless-amber {
+ led-wireless-amber {
label = "bcm53xx:amber:wireless";
gpios = <&chipcommon 11 GPIO_ACTIVE_HIGH>;
};
- wireless-white {
+ led-wireless-white {
label = "bcm53xx:white:wireless";
gpios = <&chipcommon 12 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm/boot/dts/bcm4709-netgear-r7000.dts b/arch/arm/boot/dts/bcm4709-netgear-r7000.dts
index de961fbb6200..24ba8f8f9bf3 100644
--- a/arch/arm/boot/dts/bcm4709-netgear-r7000.dts
+++ b/arch/arm/boot/dts/bcm4709-netgear-r7000.dts
@@ -28,43 +28,43 @@
leds {
compatible = "gpio-leds";
- power-white {
+ led-power-white {
label = "bcm53xx:white:power";
gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
};
- power-amber {
+ led-power-amber {
label = "bcm53xx:amber:power";
gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
};
- 5ghz {
+ led-5ghz {
label = "bcm53xx:white:5ghz";
gpios = <&chipcommon 12 GPIO_ACTIVE_LOW>;
};
- 2ghz {
+ led-2ghz {
label = "bcm53xx:white:2ghz";
gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
};
- wps {
+ led-wps {
label = "bcm53xx:white:wps";
gpios = <&chipcommon 14 GPIO_ACTIVE_HIGH>;
};
- wireless {
+ led-wireless {
label = "bcm53xx:white:wireless";
gpios = <&chipcommon 15 GPIO_ACTIVE_HIGH>;
};
- usb3 {
+ led-usb3 {
label = "bcm53xx:white:usb3";
gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>;
};
- usb2 {
+ led-usb2 {
label = "bcm53xx:white:usb2";
gpios = <&chipcommon 18 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts
index 087f7f60de18..14303ab521ea 100644
--- a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts
+++ b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts
@@ -39,59 +39,59 @@
leds {
compatible = "gpio-leds";
- power-white {
+ led-power-white {
label = "bcm53xx:white:power";
gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
};
- power-amber {
+ led-power-amber {
label = "bcm53xx:amber:power";
gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
};
- wan-white {
+ led-wan-white {
label = "bcm53xx:white:wan";
gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
};
- wan-amber {
+ led-wan-amber {
label = "bcm53xx:amber:wan";
gpios = <&chipcommon 9 GPIO_ACTIVE_HIGH>;
};
- 5ghz-1 {
+ led-5ghz-1 {
label = "bcm53xx:white:5ghz-1";
gpios = <&chipcommon 12 GPIO_ACTIVE_LOW>;
};
- 2ghz {
+ led-2ghz {
label = "bcm53xx:white:2ghz";
gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
};
- wireless {
+ led-wireless {
label = "bcm53xx:white:wireless";
gpios = <&chipcommon 14 GPIO_ACTIVE_HIGH>;
};
- wps {
+ led-wps {
label = "bcm53xx:white:wps";
gpios = <&chipcommon 15 GPIO_ACTIVE_HIGH>;
};
- 5ghz-2 {
+ led-5ghz-2 {
label = "bcm53xx:white:5ghz-2";
gpios = <&chipcommon 16 GPIO_ACTIVE_LOW>;
};
- usb3 {
+ led-usb3 {
label = "bcm53xx:white:usb3";
gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>;
};
- usb2 {
+ led-usb2 {
label = "bcm53xx:white:usb2";
gpios = <&chipcommon 18 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts b/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts
index 11d1068160da..5a8b2b1567e6 100644
--- a/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts
+++ b/arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts
@@ -23,27 +23,27 @@
leds {
compatible = "gpio-leds";
- lan {
+ led-lan {
label = "bcm53xx:blue:lan";
gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>;
};
- wps {
+ led-wps {
label = "bcm53xx:blue:wps";
gpios = <&chipcommon 2 GPIO_ACTIVE_HIGH>;
};
- 2ghz {
+ led-2ghz {
label = "bcm53xx:blue:2ghz";
gpios = <&chipcommon 4 GPIO_ACTIVE_HIGH>;
};
- 5ghz {
+ led-5ghz {
label = "bcm53xx:blue:5ghz";
gpios = <&chipcommon 5 GPIO_ACTIVE_HIGH>;
};
- usb3 {
+ led-usb3 {
label = "bcm53xx:blue:usb3";
gpios = <&chipcommon 6 GPIO_ACTIVE_HIGH>;
trigger-sources = <&ohci_port1>, <&ehci_port1>,
@@ -51,24 +51,24 @@
linux,default-trigger = "usbport";
};
- usb2 {
+ led-usb2 {
label = "bcm53xx:blue:usb2";
gpios = <&chipcommon 7 GPIO_ACTIVE_HIGH>;
trigger-sources = <&ohci_port2>, <&ehci_port2>;
linux,default-trigger = "usbport";
};
- wan-blue {
+ led-wan-blue {
label = "bcm53xx:blue:wan";
gpios = <&chipcommon 14 GPIO_ACTIVE_HIGH>;
};
- wan-amber {
+ led-wan-amber {
label = "bcm53xx:amber:wan";
gpios = <&chipcommon 15 GPIO_ACTIVE_HIGH>;
};
- power {
+ led-power {
label = "bcm53xx:blue:power";
gpios = <&chipcommon 18 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
@@ -104,30 +104,15 @@
status = "okay";
partitions {
- compatible = "fixed-partitions";
- #address-cells = <1>;
- #size-cells = <1>;
-
- boot@0 {
- label = "boot";
- reg = <0x000000 0x040000>;
- read-only;
- };
+ compatible = "tplink,safeloader-partitions";
+ partitions-table-offset = <0xe50000>;
- os-image@100000 {
- label = "os-image";
- reg = <0x040000 0x200000>;
+ partition-os-image {
compatible = "brcm,trx";
};
- rootfs@240000 {
- label = "rootfs";
- reg = <0x240000 0xc00000>;
- };
-
- nvram@ff0000 {
- label = "nvram";
- reg = <0xff0000 0x010000>;
+ partition-file-system {
+ linux,rootfs;
};
};
};
diff --git a/arch/arm/boot/dts/bcm47094-asus-rt-ac88u.dts b/arch/arm/boot/dts/bcm47094-asus-rt-ac88u.dts
index a5fec56d11c0..a50ff686b557 100644
--- a/arch/arm/boot/dts/bcm47094-asus-rt-ac88u.dts
+++ b/arch/arm/boot/dts/bcm47094-asus-rt-ac88u.dts
@@ -33,37 +33,37 @@
leds {
compatible = "gpio-leds";
- power {
+ led-power {
label = "white:power";
gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
};
- wan-red {
+ led-wan-red {
label = "red:wan";
gpios = <&chipcommon 5 GPIO_ACTIVE_HIGH>;
};
- lan {
+ led-lan {
label = "white:lan";
gpios = <&chipcommon 21 GPIO_ACTIVE_LOW>;
};
- usb2 {
+ led-usb2 {
label = "white:usb2";
gpios = <&chipcommon 16 GPIO_ACTIVE_LOW>;
trigger-sources = <&ehci_port2>;
linux,default-trigger = "usbport";
};
- usb3 {
+ led-usb3 {
label = "white:usb3";
gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>;
trigger-sources = <&ehci_port1>, <&xhci_port1>;
linux,default-trigger = "usbport";
};
- wps {
+ led-wps {
label = "white:wps";
gpios = <&chipcommon 19 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts b/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts
index 2c38b642a8b8..555fbe41dd8f 100644
--- a/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts
+++ b/arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts
@@ -43,28 +43,28 @@
leds {
compatible = "gpio-leds";
- power-white {
+ led-power-white {
label = "bcm53xx:white:power";
gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
};
- wan-white {
+ led-wan-white {
label = "bcm53xx:white:wan";
gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
};
- power-amber {
+ led-power-amber {
label = "bcm53xx:amber:power";
gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
};
- wan-amber {
+ led-wan-amber {
label = "bcm53xx:amber:wan";
gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
};
- usb3-white {
+ led-usb3-white {
label = "bcm53xx:white:usb3";
gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
trigger-sources = <&ohci_port1>, <&ehci_port1>,
@@ -72,12 +72,12 @@
linux,default-trigger = "usbport";
};
- 2ghz {
+ led-2ghz {
label = "bcm53xx:white:2ghz";
gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
};
- 5ghz {
+ led-5ghz {
label = "bcm53xx:white:5ghz";
gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/bcm47094-dlink-dir-890l.dts b/arch/arm/boot/dts/bcm47094-dlink-dir-890l.dts
new file mode 100644
index 000000000000..d945a20b06e0
--- /dev/null
+++ b/arch/arm/boot/dts/bcm47094-dlink-dir-890l.dts
@@ -0,0 +1,211 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Device tree for D-Link DIR-890L
+ * D-Link calls this board "WRGAC36"
+ * this router has the same looks and form factor as D-Link DIR-885L.
+ *
+ * Some differences from DIR-885L include a separate USB2 port, separate LEDs
+ * for USB2 and USB3, a separate VCC supply for the USB2 slot and no
+ * router/extender switch is mounted (there is an empty mount point on the
+ * PCB) so this device is a pure router. Also the LAN ports are in the right
+ * order.
+ *
+ * Based on the device tree for DIR-885L
+ * Copyright (C) 2016 Rafał Miłecki <zajec5@gmail.com>
+ * Copyright (C) 2022 Linus Walleij
+ */
+
+/dts-v1/;
+
+#include "bcm47094.dtsi"
+#include "bcm5301x-nand-cs0-bch1.dtsi"
+
+/ {
+ compatible = "dlink,dir-890l", "brcm,bcm47094", "brcm,bcm4708";
+ model = "D-Link DIR-890L";
+
+ chosen {
+ bootargs = "console=ttyS0,115200 earlycon";
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x00000000 0x08000000>,
+ <0x88000000 0x08000000>;
+ };
+
+ leds {
+ /*
+ * LED information is derived from the boot log which
+ * conveniently lists all the LEDs.
+ */
+ compatible = "gpio-leds";
+
+ led-power-white {
+ label = "bcm53xx:white:power";
+ gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
+ linux,default-trigger = "default-on";
+ };
+
+ led-wan-white {
+ label = "bcm53xx:white:wan";
+ gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
+ };
+
+ led-power-amber {
+ label = "bcm53xx:amber:power";
+ gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
+ };
+
+ led-wan-amber {
+ label = "bcm53xx:amber:wan";
+ gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
+ };
+
+ led-usb3-white {
+ label = "bcm53xx:white:usb3";
+ gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
+ trigger-sources = <&xhci_port1>;
+ linux,default-trigger = "usbport";
+ };
+
+ led-usb2-white {
+ label = "bcm53xx:white:usb2";
+ gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>;
+ trigger-sources = <&ohci_port1>, <&ehci_port1>;
+ linux,default-trigger = "usbport";
+ };
+
+ led-2ghz {
+ label = "bcm53xx:white:2ghz";
+ gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
+ };
+
+ led-5ghz {
+ label = "bcm53xx:white:5ghz";
+ gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ button-wps {
+ label = "WPS";
+ linux,code = <KEY_WPS_BUTTON>;
+ gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>;
+ };
+
+ /* Called "factory reset" in the vendor dmesg */
+ button-restart {
+ label = "Reset";
+ linux,code = <KEY_RESTART>;
+ gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ /*
+ * The flash memory is memory mapped at 0x1e000000-0x1fffffff
+ * 64KB blocks; total size 2MB, same that can be
+ * found attached to the spi_nor SPI controller.
+ */
+ nvram@1e1f0000 {
+ compatible = "brcm,nvram";
+ reg = <0x1e1f0000 0x00010000>;
+
+ et0macaddr: et0macaddr {
+ };
+ };
+};
+
+&gmac2 {
+ /*
+ * The NVRAM curiously does not contain a MAC address
+ * for et2 so since that is the only ethernet interface
+ * actually in use on the platform, we use this et0 MAC
+ * address for et2.
+ */
+ nvmem-cells = <&et0macaddr>;
+ nvmem-cell-names = "mac-address";
+};
+
+&spi_nor {
+ status = "okay";
+};
+
+&nandcs {
+ /* Spansion S34ML01G2, 128MB with 128KB erase blocks */
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /*
+ * This is called "nflash" in the vendor kernel with
+ * "upgrade" and "rootfs" (probably using OpenWrt
+ * splitpart). We call it "firmware" like standard tools
+ * assume. The CFE loader contains incorrect information
+ * about TRX partitions, ignore this, there are no TRX
+ * partitions: this device uses SEAMA.
+ */
+ firmware@0 {
+ label = "firmware";
+ reg = <0x00000000 0x08000000>;
+ };
+ };
+};
+
+&usb2 {
+ vcc-gpios = <&chipcommon 21 GPIO_ACTIVE_HIGH>;
+};
+
+&usb3 {
+ vcc-gpios = <&chipcommon 18 GPIO_ACTIVE_HIGH>;
+};
+
+&usb3_phy {
+ status = "okay";
+};
+
+&srab {
+ status = "okay";
+
+ ports {
+ port@0 {
+ reg = <0>;
+ label = "lan1";
+ };
+
+ port@1 {
+ reg = <1>;
+ label = "lan2";
+ };
+
+ port@2 {
+ reg = <2>;
+ label = "lan3";
+ };
+
+ port@3 {
+ reg = <3>;
+ label = "lan4";
+ };
+
+ port@4 {
+ reg = <4>;
+ label = "wan";
+ };
+
+ port@8 {
+ reg = <8>;
+ label = "cpu";
+ ethernet = <&gmac2>;
+ phy-mode = "rgmii";
+
+ fixed-link {
+ speed = <1000>;
+ full-duplex;
+ };
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/bcm47094-linksys-panamera.dts b/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
index 86c7cc0fa70e..d9a16a820e7f 100644
--- a/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
+++ b/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
@@ -52,19 +52,19 @@
leds {
compatible = "gpio-leds";
- wps {
+ led-wps {
label = "bcm53xx:white:wps";
gpios = <&chipcommon 22 GPIO_ACTIVE_LOW>;
};
- usb2 {
+ led-usb2 {
label = "bcm53xx:green:usb2";
gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
trigger-sources = <&ohci_port2>, <&ehci_port2>;
linux,default-trigger = "usbport";
};
- usb3 {
+ led-usb3 {
label = "bcm53xx:green:usb3";
gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
trigger-sources = <&ohci_port1>, <&ehci_port1>,
@@ -72,58 +72,58 @@
linux,default-trigger = "usbport";
};
- power {
+ led-power {
label = "bcm53xx:white:power";
gpios = <&chipcommon 4 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "default-on";
};
- wifi-disabled {
+ led-wifi-disabled {
label = "bcm53xx:amber:wifi-disabled";
gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
};
- wifi-enabled {
+ led-wifi-enabled {
label = "bcm53xx:white:wifi-enabled";
gpios = <&chipcommon 5 GPIO_ACTIVE_HIGH>;
};
- bluebar1 {
+ led-bluebar1 {
label = "bcm53xx:white:bluebar1";
gpios = <&chipcommon 11 GPIO_ACTIVE_HIGH>;
};
- bluebar2 {
+ led-bluebar2 {
label = "bcm53xx:white:bluebar2";
gpios = <&chipcommon 12 GPIO_ACTIVE_HIGH>;
};
- bluebar3 {
+ led-bluebar3 {
label = "bcm53xx:white:bluebar3";
gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>;
};
- bluebar4 {
+ led-bluebar4 {
label = "bcm53xx:white:bluebar4";
gpios = <&chipcommon 18 GPIO_ACTIVE_HIGH>;
};
- bluebar5 {
+ led-bluebar5 {
label = "bcm53xx:white:bluebar5";
gpios = <&chipcommon 19 GPIO_ACTIVE_HIGH>;
};
- bluebar6 {
+ led-bluebar6 {
label = "bcm53xx:white:bluebar6";
gpios = <&chipcommon 20 GPIO_ACTIVE_HIGH>;
};
- bluebar7 {
+ led-bluebar7 {
label = "bcm53xx:white:bluebar7";
gpios = <&chipcommon 21 GPIO_ACTIVE_HIGH>;
};
- bluebar8 {
+ led-bluebar8 {
label = "bcm53xx:white:bluebar8";
gpios = <&chipcommon 8 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts b/arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts
index 9ad15bcae1ca..41a0722fa64a 100644
--- a/arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts
+++ b/arch/arm/boot/dts/bcm47094-luxul-abr-4500.dts
@@ -30,13 +30,13 @@
leds {
compatible = "gpio-leds";
- status {
+ led-status {
label = "bcm53xx:green:status";
gpios = <&chipcommon 20 GPIO_ACTIVE_LOW>;
linux,default-trigger = "timer";
};
- usb3 {
+ led-usb3 {
label = "bcm53xx:green:usb3";
gpios = <&chipcommon 19 GPIO_ACTIVE_LOW>;
trigger-sources = <&ohci_port1>, <&ehci_port1>,
diff --git a/arch/arm/boot/dts/bcm47094-luxul-xap-1610.dts b/arch/arm/boot/dts/bcm47094-luxul-xap-1610.dts
index ee24d3768536..c56c7e366848 100644
--- a/arch/arm/boot/dts/bcm47094-luxul-xap-1610.dts
+++ b/arch/arm/boot/dts/bcm47094-luxul-xap-1610.dts
@@ -23,18 +23,18 @@
leds {
compatible = "gpio-leds";
- status {
+ led-status {
label = "bcm53xx:green:status";
gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
linux,default-trigger = "timer";
};
- 2ghz {
+ led-2ghz {
label = "bcm53xx:blue:2ghz";
gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
};
- 5ghz {
+ led-5ghz {
label = "bcm53xx:blue:5ghz";
gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts b/arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts
index 6549d07b9887..1b5c91a524ac 100644
--- a/arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts
+++ b/arch/arm/boot/dts/bcm47094-luxul-xbr-4500.dts
@@ -30,13 +30,13 @@
leds {
compatible = "gpio-leds";
- status {
+ led-status {
label = "bcm53xx:green:status";
gpios = <&chipcommon 20 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
- usb3 {
+ led-usb3 {
label = "bcm53xx:green:usb3";
gpios = <&chipcommon 19 GPIO_ACTIVE_HIGH>;
trigger-sources = <&ohci_port1>, <&ehci_port1>,
diff --git a/arch/arm/boot/dts/bcm47094-luxul-xwc-2000.dts b/arch/arm/boot/dts/bcm47094-luxul-xwc-2000.dts
index 654fcce9fded..739063b77b1f 100644
--- a/arch/arm/boot/dts/bcm47094-luxul-xwc-2000.dts
+++ b/arch/arm/boot/dts/bcm47094-luxul-xwc-2000.dts
@@ -25,7 +25,7 @@
leds {
compatible = "gpio-leds";
- status {
+ led-status {
label = "bcm53xx:green:status";
gpios = <&chipcommon 18 GPIO_ACTIVE_LOW>;
linux,default-trigger = "timer";
diff --git a/arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts b/arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts
index bf053a2fcc7c..7afc68d5d2c2 100644
--- a/arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts
+++ b/arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts
@@ -30,38 +30,38 @@
leds {
compatible = "gpio-leds";
- power {
+ led-power {
label = "bcm53xx:green:power";
gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
};
- lan3 {
+ led-lan3 {
label = "bcm53xx:green:lan3";
gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
};
- lan4 {
+ led-lan4 {
label = "bcm53xx:green:lan4";
gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
};
- wan {
+ led-wan {
label = "bcm53xx:green:wan";
gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
};
- lan1 {
+ led-lan1 {
label = "bcm53xx:green:lan1";
gpios = <&chipcommon 4 GPIO_ACTIVE_LOW>;
};
- lan2 {
+ led-lan2 {
label = "bcm53xx:green:lan2";
gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>;
};
- usb3 {
+ led-usb3 {
label = "bcm53xx:green:usb3";
gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
trigger-sources = <&ohci_port1>, <&ehci_port1>,
@@ -69,18 +69,18 @@
linux,default-trigger = "usbport";
};
- status {
+ led-status {
label = "bcm53xx:green:status";
gpios = <&chipcommon 10 GPIO_ACTIVE_LOW>;
linux,default-trigger = "timer";
};
- 2ghz {
+ led-2ghz {
label = "bcm53xx:green:2ghz";
gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
};
- 5ghz {
+ led-5ghz {
label = "bcm53xx:green:5ghz";
gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/bcm47094-luxul-xwr-3150-v1.dts b/arch/arm/boot/dts/bcm47094-luxul-xwr-3150-v1.dts
index 78a90dd57a4e..60a2c441d5bd 100644
--- a/arch/arm/boot/dts/bcm47094-luxul-xwr-3150-v1.dts
+++ b/arch/arm/boot/dts/bcm47094-luxul-xwr-3150-v1.dts
@@ -33,13 +33,13 @@
leds {
compatible = "gpio-leds";
- power {
+ led-power {
label = "bcm53xx:green:power";
gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
};
- usb3 {
+ led-usb3 {
label = "bcm53xx:green:usb3";
gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
trigger-sources = <&ohci_port1>, <&ehci_port1>,
@@ -47,18 +47,18 @@
linux,default-trigger = "usbport";
};
- status {
+ led-status {
label = "bcm53xx:green:status";
gpios = <&chipcommon 10 GPIO_ACTIVE_LOW>;
linux,default-trigger = "timer";
};
- 2ghz {
+ led-2ghz {
label = "bcm53xx:green:2ghz";
gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
};
- 5ghz {
+ led-5ghz {
label = "bcm53xx:green:5ghz";
gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/bcm47094-netgear-r8500.dts b/arch/arm/boot/dts/bcm47094-netgear-r8500.dts
index f850dce37b20..76d562610654 100644
--- a/arch/arm/boot/dts/bcm47094-netgear-r8500.dts
+++ b/arch/arm/boot/dts/bcm47094-netgear-r8500.dts
@@ -25,38 +25,38 @@
leds {
compatible = "gpio-leds";
- power0 {
+ led-power0 {
label = "bcm53xx:white:power";
gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-on";
};
- power1 {
+ led-power1 {
label = "bcm53xx:amber:power";
gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
};
- 5ghz-1 {
+ led-5ghz-1 {
label = "bcm53xx:white:5ghz-1";
gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
};
- 5ghz-2 {
+ led-5ghz-2 {
label = "bcm53xx:white:5ghz-2";
gpios = <&chipcommon 12 GPIO_ACTIVE_LOW>;
};
- 2ghz {
+ led-2ghz {
label = "bcm53xx:white:2ghz";
gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
};
- usb2 {
+ led-usb2 {
label = "bcm53xx:white:usb2";
gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>;
};
- usb3 {
+ led-usb3 {
label = "bcm53xx:white:usb3";
gpios = <&chipcommon 18 GPIO_ACTIVE_LOW>;
};
diff --git a/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts b/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts
index e20b6d2eb274..0734aa249b8e 100644
--- a/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts
+++ b/arch/arm/boot/dts/bcm47189-luxul-xap-1440.dts
@@ -23,13 +23,13 @@
leds {
compatible = "gpio-leds";
- wlan {
+ led-wlan {
label = "bcm53xx:blue:wlan";
gpios = <&chipcommon 10 GPIO_ACTIVE_LOW>;
linux,default-trigger = "default-off";
};
- system {
+ led-system {
label = "bcm53xx:green:system";
gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
linux,default-trigger = "timer";
diff --git a/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts b/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts
index 9d863570fcf3..e6fb6cbe6963 100644
--- a/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts
+++ b/arch/arm/boot/dts/bcm47189-luxul-xap-810.dts
@@ -20,26 +20,26 @@
reg = <0x00000000 0x08000000>;
};
- leds {
+ leds-0 {
compatible = "gpio-leds";
- 5ghz {
+ led-5ghz {
label = "bcm53xx:blue:5ghz";
gpios = <&chipcommon 11 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "default-off";
};
- system {
+ led-system {
label = "bcm53xx:green:system";
gpios = <&chipcommon 15 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
};
- pcie0_leds {
+ leds-1 {
compatible = "gpio-leds";
- 2ghz {
+ led-2ghz {
label = "bcm53xx:blue:2ghz";
gpios = <&pcie0_chipcommon 3 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "default-off";
diff --git a/arch/arm/boot/dts/bcm47189-tenda-ac9.dts b/arch/arm/boot/dts/bcm47189-tenda-ac9.dts
index 55b92645b0f1..dab2e5f63a72 100644
--- a/arch/arm/boot/dts/bcm47189-tenda-ac9.dts
+++ b/arch/arm/boot/dts/bcm47189-tenda-ac9.dts
@@ -20,37 +20,37 @@
reg = <0x00000000 0x08000000>;
};
- leds {
+ leds-0 {
compatible = "gpio-leds";
- usb {
+ led-usb {
label = "bcm53xx:blue:usb";
gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>;
trigger-sources = <&ohci_port1>, <&ehci_port1>;
linux,default-trigger = "usbport";
};
- wps {
+ led-wps {
label = "bcm53xx:blue:wps";
gpios = <&chipcommon 10 GPIO_ACTIVE_HIGH>;
};
- 5ghz {
+ led-5ghz {
label = "bcm53xx:blue:5ghz";
gpios = <&chipcommon 11 GPIO_ACTIVE_HIGH>;
};
- system {
+ led-system {
label = "bcm53xx:blue:system";
gpios = <&chipcommon 15 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "timer";
};
};
- pcie0_leds {
+ leds-1 {
compatible = "gpio-leds";
- 2ghz {
+ led-2ghz {
label = "bcm53xx:blue:2ghz";
gpios = <&pcie0_chipcommon 3 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm/boot/dts/bcm47622.dtsi b/arch/arm/boot/dts/bcm47622.dtsi
index 2df04528af82..f4b2db9bc4ab 100644
--- a/arch/arm/boot/dts/bcm47622.dtsi
+++ b/arch/arm/boot/dts/bcm47622.dtsi
@@ -51,6 +51,7 @@
L2_0: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm/boot/dts/bcm53016-dlink-dwl-8610ap.dts b/arch/arm/boot/dts/bcm53016-dlink-dwl-8610ap.dts
new file mode 100644
index 000000000000..c1f54391746f
--- /dev/null
+++ b/arch/arm/boot/dts/bcm53016-dlink-dwl-8610ap.dts
@@ -0,0 +1,131 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/dts-v1/;
+
+#include "bcm4709.dtsi"
+#include "bcm5301x-nand-cs0-bch8.dtsi"
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "D-Link DWL-8610AP";
+ compatible = "dlink,dwl-8610ap", "brcm,bcm53016", "brcm,bcm4708";
+
+ memory@0 {
+ device_type = "memory";
+ /* 512 MB RAM in 2 x Macronix D9PSH chips */
+ reg = <0x00000000 0x08000000>,
+ <0x88000000 0x08000000>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-power {
+ function = LED_FUNCTION_POWER;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
+ default-state = "on";
+ };
+
+ led-diag {
+ /* Actually "diag" unclear what this means */
+ function = LED_FUNCTION_INDICATOR;
+ color = <LED_COLOR_ID_RED>;
+ gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
+ default-state = "on";
+ linux,default-trigger = "heartbeat";
+ };
+
+ led-wlan-2g {
+ function = LED_FUNCTION_WLAN;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&chipcommon 5 GPIO_ACTIVE_LOW>;
+ };
+
+ led-wlan-5g {
+ function = LED_FUNCTION_WLAN;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ gpio_keys {
+ compatible = "gpio-keys";
+
+ button-reset {
+ debounce-interval = <100>;
+ wakeup-source;
+ linux,code = <KEY_RESTART>;
+ label = "reset";
+ /* This GPIO is actually stored in NVRAM, but it's not gonna change */
+ gpios = <&chipcommon 4 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ /*
+ * Flash memory at 0x1e000000-0x1fffffff
+ * Macronix 32 64KB blocks; total size 2MB, same that can be
+ * found attached to the spi_nor SPI controller.
+ */
+ nvram@1e080000 {
+ compatible = "brcm,nvram";
+ reg = <0x1e080000 0x00020000>;
+
+ et0macaddr: et0macaddr {
+ };
+
+ et1macaddr: et1macaddr {
+ };
+ };
+};
+
+&gmac0 {
+ nvmem-cells = <&et0macaddr>;
+ nvmem-cell-names = "mac-address";
+};
+
+&gmac1 {
+ nvmem-cells = <&et1macaddr>;
+ nvmem-cell-names = "mac-address";
+};
+
+&spi_nor {
+ /* Serial SPI NOR Flash MX 25L1606E */
+ status = "okay";
+};
+
+&nandcs {
+ /*
+ * Spansion S34ML01G100TFI00 128 MB NAND Flash memory
+ *
+ * This ECC is a bit unorthodox but it is what the stock firmware
+ * is using, so to be able to mount the original partitions
+ * this is necessary.
+ */
+ nand-ecc-strength = <5>;
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* This is named nflash1.trx in CFE */
+ trx@0 {
+ label = "firmware";
+ reg = <0x00000000 0x02800000>;
+ compatible = "brcm,trx";
+ };
+
+ /* This is named nflash1.trx2 in CFE */
+ trx2@2800000 {
+ label = "firmware2";
+ reg = <0x02800000 0x02800000>;
+ compatible = "brcm,trx";
+ };
+
+ /* This is named nflash1.rwfs in CFE */
+ free@5000000 {
+ label = "free";
+ reg = <0x05000000 0x03000000>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/bcm53016-meraki-mr32.dts b/arch/arm/boot/dts/bcm53016-meraki-mr32.dts
index e678bc03d816..46c2c93b01d8 100644
--- a/arch/arm/boot/dts/bcm53016-meraki-mr32.dts
+++ b/arch/arm/boot/dts/bcm53016-meraki-mr32.dts
@@ -58,7 +58,7 @@
pwm-leds {
compatible = "pwm-leds";
- red {
+ led-0 {
/* SYS-LED 1 - Tricolor */
function = LED_FUNCTION_INDICATOR;
color = <LED_COLOR_ID_RED>;
@@ -66,7 +66,7 @@
max-brightness = <255>;
};
- green {
+ led-1 {
/* SYS-LED 1 - Tricolor */
function = LED_FUNCTION_POWER;
color = <LED_COLOR_ID_GREEN>;
@@ -74,7 +74,7 @@
max-brightness = <255>;
};
- blue {
+ led-2 {
/* SYS-LED 1 - Tricolor */
function = LED_FUNCTION_INDICATOR;
color = <LED_COLOR_ID_BLUE>;
diff --git a/arch/arm/boot/dts/bcm63148.dtsi b/arch/arm/boot/dts/bcm63148.dtsi
index df5307b6b3af..7cd55d64de71 100644
--- a/arch/arm/boot/dts/bcm63148.dtsi
+++ b/arch/arm/boot/dts/bcm63148.dtsi
@@ -35,6 +35,7 @@
L2_0: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm/boot/dts/bcm63178.dtsi b/arch/arm/boot/dts/bcm63178.dtsi
index cbd094dde6d0..043e699cbc27 100644
--- a/arch/arm/boot/dts/bcm63178.dtsi
+++ b/arch/arm/boot/dts/bcm63178.dtsi
@@ -43,6 +43,7 @@
L2_0: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm/boot/dts/bcm6756.dtsi b/arch/arm/boot/dts/bcm6756.dtsi
index ce1b59faf800..5c72219bc194 100644
--- a/arch/arm/boot/dts/bcm6756.dtsi
+++ b/arch/arm/boot/dts/bcm6756.dtsi
@@ -51,6 +51,7 @@
L2_0: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm/boot/dts/bcm6846.dtsi b/arch/arm/boot/dts/bcm6846.dtsi
index 8aa47a2583b2..81513a793815 100644
--- a/arch/arm/boot/dts/bcm6846.dtsi
+++ b/arch/arm/boot/dts/bcm6846.dtsi
@@ -35,6 +35,7 @@
L2_0: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm/boot/dts/bcm6855.dtsi b/arch/arm/boot/dts/bcm6855.dtsi
index 620f51aee1a2..5fa5feac0e29 100644
--- a/arch/arm/boot/dts/bcm6855.dtsi
+++ b/arch/arm/boot/dts/bcm6855.dtsi
@@ -43,6 +43,7 @@
L2_0: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm/boot/dts/bcm6878.dtsi b/arch/arm/boot/dts/bcm6878.dtsi
index 1e8b5fa96c25..4ec836ac4baf 100644
--- a/arch/arm/boot/dts/bcm6878.dtsi
+++ b/arch/arm/boot/dts/bcm6878.dtsi
@@ -35,6 +35,7 @@
L2_0: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm/boot/dts/bcm947189acdbmr.dts b/arch/arm/boot/dts/bcm947189acdbmr.dts
index 16e70a264faf..3709baa2376f 100644
--- a/arch/arm/boot/dts/bcm947189acdbmr.dts
+++ b/arch/arm/boot/dts/bcm947189acdbmr.dts
@@ -25,17 +25,17 @@
leds {
compatible = "gpio-leds";
- wps {
+ led-wps {
label = "bcm53xx:blue:wps";
gpios = <&chipcommon 10 GPIO_ACTIVE_HIGH>;
};
- 5ghz {
+ led-5ghz {
label = "bcm53xx:blue:5ghz";
gpios = <&chipcommon 11 GPIO_ACTIVE_HIGH>;
};
- 2ghz {
+ led-2ghz {
label = "bcm53xx:blue:2ghz";
gpios = <&chipcommon 12 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi
index 00a36fba2fd2..9aee3cfd3e98 100644
--- a/arch/arm/boot/dts/dove.dtsi
+++ b/arch/arm/boot/dts/dove.dtsi
@@ -139,7 +139,7 @@
pcie1: pcie@2 {
device_type = "pci";
status = "disabled";
- assigned-addresses = <0x82002800 0 0x80000 0 0x2000>;
+ assigned-addresses = <0x82001000 0 0x80000 0 0x2000>;
reg = <0x1000 0 0 0 0>;
clocks = <&gate_clk 5>;
marvell,pcie-port = <1>;
diff --git a/arch/arm/boot/dts/dra7-evm-common.dtsi b/arch/arm/boot/dts/dra7-evm-common.dtsi
index 68c43eb12c1a..4cdffd6db740 100644
--- a/arch/arm/boot/dts/dra7-evm-common.dtsi
+++ b/arch/arm/boot/dts/dra7-evm-common.dtsi
@@ -151,7 +151,7 @@
*/
partition@0 {
label = "QSPI.SPL";
- reg = <0x00000000 0x000010000>;
+ reg = <0x00000000 0x00010000>;
};
partition@1 {
label = "QSPI.SPL.backup1";
diff --git a/arch/arm/boot/dts/dra7-evm.dts b/arch/arm/boot/dts/dra7-evm.dts
index 87deb6a76eff..8cbcf55a5a33 100644
--- a/arch/arm/boot/dts/dra7-evm.dts
+++ b/arch/arm/boot/dts/dra7-evm.dts
@@ -483,7 +483,7 @@
#size-cells = <1>;
partition@0 {
label = "NAND.SPL";
- reg = <0x00000000 0x000020000>;
+ reg = <0x00000000 0x00020000>;
};
partition@1 {
label = "NAND.SPL.backup1";
diff --git a/arch/arm/boot/dts/dra72-evm-common.dtsi b/arch/arm/boot/dts/dra72-evm-common.dtsi
index 8948e10dbeb8..c79ba671ec2b 100644
--- a/arch/arm/boot/dts/dra72-evm-common.dtsi
+++ b/arch/arm/boot/dts/dra72-evm-common.dtsi
@@ -356,7 +356,7 @@
#size-cells = <1>;
partition@0 {
label = "NAND.SPL";
- reg = <0x00000000 0x000020000>;
+ reg = <0x00000000 0x00020000>;
};
partition@1 {
label = "NAND.SPL.backup1";
@@ -490,7 +490,7 @@
*/
partition@0 {
label = "QSPI.SPL";
- reg = <0x00000000 0x000010000>;
+ reg = <0x00000000 0x00010000>;
};
partition@1 {
label = "QSPI.SPL.backup1";
diff --git a/arch/arm/boot/dts/e60k02.dtsi b/arch/arm/boot/dts/e60k02.dtsi
index 935e2359f8df..94944cc21931 100644
--- a/arch/arm/boot/dts/e60k02.dtsi
+++ b/arch/arm/boot/dts/e60k02.dtsi
@@ -104,7 +104,16 @@
clock-frequency = <100000>;
status = "okay";
- /* TODO: CYTTSP5 touch controller at 0x24 */
+ touchscreen@24 {
+ compatible = "cypress,tt21000";
+ reg = <0x24>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_cyttsp5_gpio>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <6 IRQ_TYPE_EDGE_FALLING>;
+ reset-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
+ vdd-supply = <&ldo5_reg>;
+ };
/* TODO: TPS65185 PMIC for E Ink at 0x68 */
diff --git a/arch/arm/boot/dts/exynos3250.dtsi b/arch/arm/boot/dts/exynos3250.dtsi
index 326b9e0ed8d3..a2d6ee7fff08 100644
--- a/arch/arm/boot/dts/exynos3250.dtsi
+++ b/arch/arm/boot/dts/exynos3250.dtsi
@@ -485,7 +485,7 @@
};
mfc: codec@13400000 {
- compatible = "samsung,mfc-v7";
+ compatible = "samsung,exynos3250-mfc", "samsung,mfc-v7";
reg = <0x13400000 0x10000>;
interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "mfc", "sclk_mfc";
diff --git a/arch/arm/boot/dts/imx6dl-colibri-aster.dts b/arch/arm/boot/dts/imx6dl-colibri-aster.dts
index 74e8a6cd8bed..a28e083f29d5 100644
--- a/arch/arm/boot/dts/imx6dl-colibri-aster.dts
+++ b/arch/arm/boot/dts/imx6dl-colibri-aster.dts
@@ -99,7 +99,6 @@
};
&usbh1 {
- vbus-supply = <&reg_usb_host_vbus>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts b/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts
index 7272edd85a49..a02981d4a3fc 100644
--- a/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts
+++ b/arch/arm/boot/dts/imx6dl-colibri-eval-v3.dts
@@ -111,7 +111,6 @@
};
&usbh1 {
- vbus-supply = <&reg_usb_host_vbus>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6dl-colibri-iris.dts b/arch/arm/boot/dts/imx6dl-colibri-iris.dts
index cf77d894f6d7..c5797ff35b71 100644
--- a/arch/arm/boot/dts/imx6dl-colibri-iris.dts
+++ b/arch/arm/boot/dts/imx6dl-colibri-iris.dts
@@ -138,7 +138,6 @@
};
&usbh1 {
- vbus-supply = <&reg_usb_host_vbus>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-colibri.dtsi b/arch/arm/boot/dts/imx6qdl-colibri.dtsi
index 023e76215064..d8f985f297e4 100644
--- a/arch/arm/boot/dts/imx6qdl-colibri.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-colibri.dtsi
@@ -24,6 +24,13 @@
status = "disabled";
};
+ extcon_usbc_det: usbc-det {
+ compatible = "linux,extcon-usb-gpio";
+ id-gpio = <&gpio7 12 GPIO_ACTIVE_HIGH>; /* SODIMM 137 / USBC_DET */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbc_det>;
+ };
+
gpio-keys {
compatible = "gpio-keys";
pinctrl-names = "default";
@@ -105,7 +112,7 @@
reg_usb_host_vbus: regulator-usb-host-vbus {
compatible = "regulator-fixed";
- gpio = <&gpio3 31 GPIO_ACTIVE_HIGH>; /* USBH_PEN */
+ gpio = <&gpio3 31 GPIO_ACTIVE_LOW>; /* SODIMM 129 / USBH_PEN */
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_regulator_usbh_pwr>;
regulator-max-microvolt = <5000000>;
@@ -670,9 +677,16 @@
status = "disabled";
};
+/* Colibri USBH */
+&usbh1 {
+ vbus-supply = <&reg_usb_host_vbus>;
+};
+
+/* Colibri USBC */
&usbotg {
disable-over-current;
- dr_mode = "peripheral";
+ dr_mode = "otg";
+ extcon = <0>, <&extcon_usbc_det>;
status = "disabled";
};
@@ -986,7 +1000,7 @@
pinctrl_regulator_usbh_pwr: gpioregusbhpwrgrp {
fsl,pins = <
- /* USBH_EN */
+ /* SODIMM 129 / USBH_PEN */
MX6QDL_PAD_EIM_D31__GPIO3_IO31 0x0f058
>;
};
@@ -1055,7 +1069,7 @@
pinctrl_usbc_det: usbcdetgrp {
fsl,pins = <
- /* USBC_DET */
+ /* SODIMM 137 / USBC_DET */
MX6QDL_PAD_GPIO_17__GPIO7_IO12 0x1b0b0
/* USBC_DET_OVERWRITE */
MX6QDL_PAD_RGMII_RXC__GPIO6_IO30 0x0f058
diff --git a/arch/arm/boot/dts/imx6qdl-pico.dtsi b/arch/arm/boot/dts/imx6qdl-pico.dtsi
index f7a56d6b160c..c39a9ebdaba1 100644
--- a/arch/arm/boot/dts/imx6qdl-pico.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-pico.dtsi
@@ -233,7 +233,6 @@
pinctrl-0 = <&pinctrl_ov5645>;
reg = <0x3c>;
clocks = <&clks IMX6QDL_CLK_CKO2>;
- clock-names = "xclk";
clock-frequency = <24000000>;
vdddo-supply = <&reg_1p8v>;
vdda-supply = <&reg_2p8v>;
diff --git a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
index 3dbb460ef102..eebcfe12142e 100644
--- a/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabreauto.dtsi
@@ -452,8 +452,8 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_egalax_int>;
interrupt-parent = <&gpio2>;
- interrupts = <28 IRQ_TYPE_EDGE_FALLING>;
- wakeup-gpios = <&gpio2 28 GPIO_ACTIVE_HIGH>;
+ interrupts = <28 IRQ_TYPE_LEVEL_LOW>;
+ wakeup-gpios = <&gpio2 28 GPIO_ACTIVE_LOW>;
};
};
diff --git a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
index 22f8e2783cdf..12573e1f917c 100644
--- a/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabrelite.dtsi
@@ -14,6 +14,11 @@
stdout-path = &uart2;
};
+ aliases {
+ mmc0 = &usdhc3;
+ mmc1 = &usdhc4;
+ };
+
memory@10000000 {
device_type = "memory";
reg = <0x10000000 0x40000000>;
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index 37482a9023fc..09f4c2fa3ad6 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -311,8 +311,8 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c2_egalax_int>;
interrupt-parent = <&gpio6>;
- interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
- wakeup-gpios = <&gpio6 8 GPIO_ACTIVE_HIGH>;
+ interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
+ wakeup-gpios = <&gpio6 8 GPIO_ACTIVE_LOW>;
};
ov5640: camera@3c {
@@ -450,8 +450,8 @@
compatible = "eeti,egalax_ts";
reg = <0x04>;
interrupt-parent = <&gpio6>;
- interrupts = <7 2>;
- wakeup-gpios = <&gpio6 7 0>;
+ interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+ wakeup-gpios = <&gpio6 7 GPIO_ACTIVE_LOW>;
};
magnetometer@e {
diff --git a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
index ec6fba5ee8fd..e4f63423d8ee 100644
--- a/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-wandboard.dtsi
@@ -131,7 +131,6 @@
pinctrl-0 = <&pinctrl_ov5645>;
reg = <0x3c>;
clocks = <&clks IMX6QDL_CLK_CKO2>;
- clock-names = "xclk";
clock-frequency = <24000000>;
vdddo-supply = <&reg_1p8v>;
vdda-supply = <&reg_2p8v>;
diff --git a/arch/arm/boot/dts/imx6sl-kobo-aura2.dts b/arch/arm/boot/dts/imx6sl-kobo-aura2.dts
new file mode 100644
index 000000000000..657d0f1b6115
--- /dev/null
+++ b/arch/arm/boot/dts/imx6sl-kobo-aura2.dts
@@ -0,0 +1,555 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device tree for the Kobo Aura 2 ebook reader
+ *
+ * Name on mainboard is: 37NB-E60QL0+4B1
+ * Serials start with: E60QL2
+ *
+ * Copyright 2022 Andreas Kemnade
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include "imx6sl.dtsi"
+
+/ {
+ model = "Kobo Aura 2";
+ compatible = "kobo,aura2", "fsl,imx6sl";
+
+ aliases {
+ mmc0 = &usdhc2;
+ mmc1 = &usdhc3;
+ };
+
+ chosen {
+ stdout-path = &uart1;
+ };
+
+ gpio_keys: gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+
+ key-cover {
+ label = "Cover";
+ gpios = <&gpio5 12 GPIO_ACTIVE_LOW>;
+ linux,code = <SW_LID>;
+ linux,input-type = <EV_SW>;
+ wakeup-source;
+ };
+
+ key-power {
+ label = "Power";
+ gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_POWER>;
+ wakeup-source;
+ };
+ };
+
+ leds: leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_led>;
+
+ led-0 {
+ label = "koboaura2:white:on";
+ gpios = <&gpio5 7 GPIO_ACTIVE_LOW>;
+ color = <LED_COLOR_ID_WHITE>;
+ linux,default-trigger = "timer";
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x10000000>;
+ };
+
+ reg_wifi: regulator-wifi {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi_power>;
+ regulator-name = "SD3_SPWR";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ gpio = <&gpio4 29 GPIO_ACTIVE_LOW>;
+ };
+
+ wifi_pwrseq: wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wifi_reset>;
+ post-power-on-delay-ms = <20>;
+ reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&i2c1 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ pinctrl-1 = <&pinctrl_i2c1_sleep>;
+ status = "okay";
+
+ lm3630a: backlight@36 {
+ compatible = "ti,lm3630a";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lm3630a_bl_gpio>;
+ reg = <0x36>;
+ enable-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@0 {
+ reg = <0>;
+ led-sources = <0>;
+ label = "backlight";
+ default-brightness = <0>;
+ max-brightness = <255>;
+ };
+ };
+};
+
+&i2c2 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ pinctrl-1 = <&pinctrl_i2c2_sleep>;
+ clock-frequency = <100000>;
+ status = "okay";
+
+ /* eKTF2232 at 0x15 */
+ /* FP9928 at 0x48 */
+};
+
+&i2c3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ clock-frequency = <400000>;
+ status = "okay";
+
+ ricoh619: pmic@32 {
+ compatible = "ricoh,rc5t619";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ricoh_gpio>;
+ reg = <0x32>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+ system-power-controller;
+
+ regulators {
+ dcdc1_reg: DCDC1 {
+ regulator-name = "DCDC1";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-max-microvolt = <900000>;
+ regulator-suspend-min-microvolt = <900000>;
+ };
+ };
+
+ /* Core3_3V3 */
+ dcdc2_reg: DCDC2 {
+ regulator-name = "DCDC2";
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-max-microvolt = <3100000>;
+ regulator-suspend-min-microvolt = <3100000>;
+ };
+ };
+
+ dcdc3_reg: DCDC3 {
+ regulator-name = "DCDC3";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <1875000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-max-microvolt = <1140000>;
+ regulator-suspend-min-microvolt = <1140000>;
+ };
+ };
+
+ /* Core4_1V2 */
+ dcdc4_reg: DCDC4 {
+ regulator-name = "DCDC4";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-max-microvolt = <1140000>;
+ regulator-suspend-min-microvolt = <1140000>;
+ };
+ };
+
+ /* Core4_1V8 */
+ dcdc5_reg: DCDC5 {
+ regulator-name = "DCDC5";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-max-microvolt = <1700000>;
+ regulator-suspend-min-microvolt = <1700000>;
+ };
+ };
+
+ /* IR_3V3 */
+ ldo1_reg: LDO1 {
+ regulator-name = "LDO1";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ /* Core1_3V3 */
+ ldo2_reg: LDO2 {
+ regulator-name = "LDO2";
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-max-microvolt = <3000000>;
+ regulator-suspend-min-microvolt = <3000000>;
+ };
+ };
+
+ /* Core5_1V2 */
+ ldo3_reg: LDO3 {
+ regulator-name = "LDO3";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo4_reg: LDO4 {
+ regulator-name = "LDO4";
+ regulator-boot-on;
+ };
+
+ /* SPD_3V3 */
+ ldo5_reg: LDO5 {
+ regulator-name = "LDO5";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ /* DDR_0V6 */
+ ldo6_reg: LDO6 {
+ regulator-name = "LDO6";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ /* VDD_PWM */
+ ldo7_reg: LDO7 {
+ regulator-name = "LDO7";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ /* ldo_1v8 */
+ ldo8_reg: LDO8 {
+ regulator-name = "LDO8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ ldo9_reg: LDO9 {
+ regulator-name = "LDO9";
+ regulator-boot-on;
+ };
+
+ ldo10_reg: LDO10 {
+ regulator-name = "LDO10";
+ regulator-boot-on;
+ };
+
+ ldortc1_reg: LDORTC1 {
+ regulator-name = "LDORTC1";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+ };
+ };
+};
+
+&reg_vdd1p1 {
+ vin-supply = <&dcdc2_reg>;
+};
+
+&reg_vdd2p5 {
+ vin-supply = <&dcdc2_reg>;
+};
+
+&reg_arm {
+ vin-supply = <&dcdc3_reg>;
+};
+
+&reg_soc {
+ vin-supply = <&dcdc1_reg>;
+};
+
+&reg_pu {
+ vin-supply = <&dcdc1_reg>;
+};
+
+&snvs_rtc {
+ /*
+ * We are using the RTC in the PMIC, but this one is not disabled
+ * in imx6sl.dtsi.
+ */
+ status = "disabled";
+};
+
+&uart1 {
+ /* J4, through-holes */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&uart4 {
+ /* TP198, next to J4, SMD pads */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
+ pinctrl-3 = <&pinctrl_usdhc2_sleep>;
+ non-removable;
+ status = "okay";
+
+ /* internal uSD card */
+};
+
+&usdhc3 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz", "sleep";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+ pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+ pinctrl-3 = <&pinctrl_usdhc3_sleep>;
+ vmmc-supply = <&reg_wifi>;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ cap-power-off-card;
+ non-removable;
+ status = "okay";
+
+ /*
+ * RTL8189F SDIO WiFi
+ */
+};
+
+&usbotg1 {
+ disable-over-current;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_gpio_keys: gpio-keysgrp {
+ fsl,pins = <
+ MX6SL_PAD_SD1_DAT1__GPIO5_IO08 0x17059
+ MX6SL_PAD_SD1_DAT4__GPIO5_IO12 0x17059
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6SL_PAD_I2C1_SCL__I2C1_SCL 0x4001f8b1
+ MX6SL_PAD_I2C1_SDA__I2C1_SDA 0x4001f8b1
+ >;
+ };
+
+ pinctrl_i2c1_sleep: i2c1-sleepgrp {
+ fsl,pins = <
+ MX6SL_PAD_I2C1_SCL__I2C1_SCL 0x400108b1
+ MX6SL_PAD_I2C1_SDA__I2C1_SDA 0x400108b1
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6SL_PAD_I2C2_SCL__I2C2_SCL 0x4001f8b1
+ MX6SL_PAD_I2C2_SDA__I2C2_SDA 0x4001f8b1
+ >;
+ };
+
+ pinctrl_i2c2_sleep: i2c2-sleepgrp {
+ fsl,pins = <
+ MX6SL_PAD_I2C2_SCL__I2C2_SCL 0x400108b1
+ MX6SL_PAD_I2C2_SDA__I2C2_SDA 0x400108b1
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6SL_PAD_REF_CLK_24M__I2C3_SCL 0x4001f8b1
+ MX6SL_PAD_REF_CLK_32K__I2C3_SDA 0x4001f8b1
+ >;
+ };
+
+ pinctrl_led: ledgrp {
+ fsl,pins = <
+ MX6SL_PAD_SD1_DAT6__GPIO5_IO07 0x17059
+ >;
+ };
+
+ pinctrl_lm3630a_bl_gpio: lm3630a-bl-gpiogrp {
+ fsl,pins = <
+ MX6SL_PAD_EPDC_PWRCTRL3__GPIO2_IO10 0x10059 /* HWEN */
+ >;
+ };
+
+ pinctrl_ricoh_gpio: ricoh-gpiogrp {
+ fsl,pins = <
+ MX6SL_PAD_SD1_CLK__GPIO5_IO15 0x1b8b1 /* ricoh619 chg */
+ MX6SL_PAD_SD1_DAT0__GPIO5_IO11 0x1b8b1 /* ricoh619 irq */
+ MX6SL_PAD_KEY_COL2__GPIO3_IO28 0x1b8b1 /* ricoh619 bat_low_int */
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6SL_PAD_UART1_TXD__UART1_TX_DATA 0x1b0b1
+ MX6SL_PAD_UART1_RXD__UART1_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX6SL_PAD_KEY_ROW6__UART4_TX_DATA 0x1b0b1
+ MX6SL_PAD_KEY_COL6__UART4_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_usbotg1: usbotg1grp {
+ fsl,pins = <
+ MX6SL_PAD_EPDC_PWRCOM__USB_OTG1_ID 0x17059
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6SL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6SL_PAD_SD2_CLK__SD2_CLK 0x13059
+ MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
+ fsl,pins = <
+ MX6SL_PAD_SD2_CMD__SD2_CMD 0x170b9
+ MX6SL_PAD_SD2_CLK__SD2_CLK 0x130b9
+ MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x170b9
+ MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x170b9
+ MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x170b9
+ MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+ fsl,pins = <
+ MX6SL_PAD_SD2_CMD__SD2_CMD 0x170f9
+ MX6SL_PAD_SD2_CLK__SD2_CLK 0x130f9
+ MX6SL_PAD_SD2_DAT0__SD2_DATA0 0x170f9
+ MX6SL_PAD_SD2_DAT1__SD2_DATA1 0x170f9
+ MX6SL_PAD_SD2_DAT2__SD2_DATA2 0x170f9
+ MX6SL_PAD_SD2_DAT3__SD2_DATA3 0x170f9
+ >;
+ };
+
+ pinctrl_usdhc2_sleep: usdhc2-sleepgrp {
+ fsl,pins = <
+ MX6SL_PAD_SD2_CMD__GPIO5_IO04 0x100f9
+ MX6SL_PAD_SD2_CLK__GPIO5_IO05 0x100f9
+ MX6SL_PAD_SD2_DAT0__GPIO5_IO01 0x100f9
+ MX6SL_PAD_SD2_DAT1__GPIO4_IO30 0x100f9
+ MX6SL_PAD_SD2_DAT2__GPIO5_IO03 0x100f9
+ MX6SL_PAD_SD2_DAT3__GPIO4_IO28 0x100f9
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6SL_PAD_SD3_CMD__SD3_CMD 0x11059
+ MX6SL_PAD_SD3_CLK__SD3_CLK 0x11059
+ MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x11059
+ MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x11059
+ MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x11059
+ MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x11059
+ >;
+ };
+
+ pinctrl_usdhc3_100mhz: usdhc3-100mhzgrp {
+ fsl,pins = <
+ MX6SL_PAD_SD3_CMD__SD3_CMD 0x170b9
+ MX6SL_PAD_SD3_CLK__SD3_CLK 0x170b9
+ MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x170b9
+ MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x170b9
+ MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x170b9
+ MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x170b9
+ >;
+ };
+
+ pinctrl_usdhc3_200mhz: usdhc3-200mhzgrp {
+ fsl,pins = <
+ MX6SL_PAD_SD3_CMD__SD3_CMD 0x170f9
+ MX6SL_PAD_SD3_CLK__SD3_CLK 0x170f9
+ MX6SL_PAD_SD3_DAT0__SD3_DATA0 0x170f9
+ MX6SL_PAD_SD3_DAT1__SD3_DATA1 0x170f9
+ MX6SL_PAD_SD3_DAT2__SD3_DATA2 0x170f9
+ MX6SL_PAD_SD3_DAT3__SD3_DATA3 0x170f9
+ >;
+ };
+
+ pinctrl_usdhc3_sleep: usdhc3-sleepgrp {
+ fsl,pins = <
+ MX6SL_PAD_SD3_CMD__GPIO5_IO21 0x100c1
+ MX6SL_PAD_SD3_CLK__GPIO5_IO18 0x100c1
+ MX6SL_PAD_SD3_DAT0__GPIO5_IO19 0x100c1
+ MX6SL_PAD_SD3_DAT1__GPIO5_IO20 0x100c1
+ MX6SL_PAD_SD3_DAT2__GPIO5_IO16 0x100c1
+ MX6SL_PAD_SD3_DAT3__GPIO5_IO17 0x100c1
+ >;
+ };
+
+ pinctrl_wifi_power: wifi-powergrp {
+ fsl,pins = <
+ MX6SL_PAD_SD2_DAT6__GPIO4_IO29 0x10059 /* WIFI_3V3_ON */
+ >;
+ };
+
+ pinctrl_wifi_reset: wifi-resetgrp {
+ fsl,pins = <
+ MX6SL_PAD_SD2_DAT7__GPIO5_IO00 0x10059 /* WIFI_RST */
+ >;
+ };
+};
diff --git a/arch/arm/boot/dts/imx6sl-tolino-shine2hd.dts b/arch/arm/boot/dts/imx6sl-tolino-shine2hd.dts
index 663ee9df79e6..da1399057634 100644
--- a/arch/arm/boot/dts/imx6sl-tolino-shine2hd.dts
+++ b/arch/arm/boot/dts/imx6sl-tolino-shine2hd.dts
@@ -18,6 +18,21 @@
model = "Tolino Shine 2 HD";
compatible = "kobo,tolino-shine2hd", "fsl,imx6sl";
+ backlight {
+ compatible = "pwm-backlight";
+ pwms = <&ec 0 50000>;
+ power-supply = <&backlight_regulator>;
+ };
+
+ backlight_regulator: regulator-backlight {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_backlight_power>;
+ regulator-name = "backlight";
+ gpio = <&gpio2 10 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
chosen {
stdout-path = &uart1;
};
@@ -65,6 +80,12 @@
gpios = <&gpio5 13 GPIO_ACTIVE_LOW>;
linux,default-trigger = "timer";
};
+
+ led-1 {
+ label = "tolinoshine2hd:white:backlightboost";
+ gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "off";
+ };
};
memory@80000000 {
@@ -299,6 +320,12 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
+ pinctrl_backlight_power: backlight-powergrp {
+ fsl,pins = <
+ MX6SL_PAD_EPDC_PWRCTRL3__GPIO2_IO10 0x10059
+ >;
+ };
+
pinctrl_gpio_keys: gpio-keysgrp {
fsl,pins = <
MX6SL_PAD_SD1_DAT1__GPIO5_IO08 0x17059
@@ -383,7 +410,8 @@
pinctrl_led: ledgrp {
fsl,pins = <
- MX6SL_PAD_SD1_DAT2__GPIO5_IO13 0x17059
+ MX6SL_PAD_SD1_DAT2__GPIO5_IO13 0x17059
+ MX6SL_PAD_EPDC_SDCE2__GPIO1_IO29 0x17059
>;
};
diff --git a/arch/arm/boot/dts/imx6sl-tolino-shine3.dts b/arch/arm/boot/dts/imx6sl-tolino-shine3.dts
index e3f1e8d79528..db5d8509935f 100644
--- a/arch/arm/boot/dts/imx6sl-tolino-shine3.dts
+++ b/arch/arm/boot/dts/imx6sl-tolino-shine3.dts
@@ -52,6 +52,13 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
+ pinctrl_cyttsp5_gpio: cyttsp5-gpiogrp {
+ fsl,pins = <
+ MX6SL_PAD_SD1_DAT3__GPIO5_IO06 0x17059 /* TP_INT */
+ MX6SL_PAD_SD1_DAT2__GPIO5_IO13 0x10059 /* TP_RST */
+ >;
+ };
+
pinctrl_gpio_keys: gpio-keysgrp {
fsl,pins = <
MX6SL_PAD_SD1_DAT1__GPIO5_IO08 0x17059 /* PWR_SW */
diff --git a/arch/arm/boot/dts/imx6sll-kobo-clarahd.dts b/arch/arm/boot/dts/imx6sll-kobo-clarahd.dts
index 90b32f5eb529..c7cfe0b70f04 100644
--- a/arch/arm/boot/dts/imx6sll-kobo-clarahd.dts
+++ b/arch/arm/boot/dts/imx6sll-kobo-clarahd.dts
@@ -62,6 +62,13 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
+ pinctrl_cyttsp5_gpio: cyttsp5-gpiogrp {
+ fsl,pins = <
+ MX6SLL_PAD_SD1_DATA3__GPIO5_IO06 0x17059 /* TP_INT */
+ MX6SLL_PAD_SD1_DATA2__GPIO5_IO13 0x10059 /* TP_RST */
+ >;
+ };
+
pinctrl_gpio_keys: gpio-keysgrp {
fsl,pins = <
MX6SLL_PAD_SD1_DATA1__GPIO5_IO08 0x17059 /* PWR_SW */
diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
index abc3572d699e..80f5efd65c2f 100644
--- a/arch/arm/boot/dts/imx6sx.dtsi
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -1391,7 +1391,7 @@
pwm8: pwm@22b0000 {
compatible = "fsl,imx6sx-pwm", "fsl,imx27-pwm";
- reg = <0x0022b0000 0x4000>;
+ reg = <0x022b0000 0x4000>;
interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6SX_CLK_PWM8>,
<&clks IMX6SX_CLK_PWM8>;
diff --git a/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi
index 3cddc68917a0..5168ed0ffec3 100644
--- a/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi
+++ b/arch/arm/boot/dts/imx6ul-phytec-phycore-som.dtsi
@@ -102,6 +102,10 @@
status = "disabled";
};
+&wdog1 {
+ fsl,suspend-in-wait;
+};
+
&iomuxc {
pinctrl_enet1: enet1grp {
fsl,pins = <
diff --git a/arch/arm/boot/dts/imx6ull-colibri-aster.dts b/arch/arm/boot/dts/imx6ull-colibri-aster.dts
index d3f2fb7c6c1e..3e0897c3a296 100644
--- a/arch/arm/boot/dts/imx6ull-colibri-aster.dts
+++ b/arch/arm/boot/dts/imx6ull-colibri-aster.dts
@@ -15,6 +15,46 @@
"fsl,imx6ull";
};
+&ad7879_ts {
+ status = "okay";
+};
+
&atmel_mxt_ts {
status = "okay";
};
+
+&backlight {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&lcdif {
+ status = "okay";
+};
+
+&panel_dpi {
+ status = "okay";
+};
+
+&pwm4 {
+ status = "okay";
+};
+
+/* PWM <B> */
+&pwm5 {
+ /* Pin already used by atmel_mxt_ts touchscreen */
+ status = "disabled";
+};
+
+/* PWM <C> */
+&pwm6 {
+ /* Pin already used by atmel_mxt_ts touchscreen */
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dts b/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dts
index 9bf7111d7b00..d6da984e518d 100644
--- a/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dts
+++ b/arch/arm/boot/dts/imx6ull-colibri-eval-v3.dts
@@ -12,3 +12,27 @@
model = "Toradex Colibri iMX6ULL 256/512MB on Colibri Evaluation Board V3";
compatible = "toradex,colibri-imx6ull-eval", "fsl,imx6ull";
};
+
+&ad7879_ts {
+ status = "okay";
+};
+
+&backlight {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&lcdif {
+ status = "okay";
+};
+
+&panel_dpi {
+ status = "okay";
+};
+
+&pwm4 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6ull-colibri-iris-v2.dts b/arch/arm/boot/dts/imx6ull-colibri-iris-v2.dts
index afc1e0119783..f6b31118be17 100644
--- a/arch/arm/boot/dts/imx6ull-colibri-iris-v2.dts
+++ b/arch/arm/boot/dts/imx6ull-colibri-iris-v2.dts
@@ -15,13 +15,21 @@
"fsl,imx6ull";
};
+&ad7879_ts {
+ status = "okay";
+};
+
&atmel_mxt_ts {
status = "okay";
};
+&backlight {
+ status = "okay";
+};
+
&gpio1 {
/* This turns the LVDS transceiver on */
- lvds-power-on {
+ lvds-power-on-hog {
gpio-hog;
gpios = <14 GPIO_ACTIVE_HIGH>; /* SODIMM 99 */
line-name = "LVDS_POWER_ON";
@@ -34,7 +42,7 @@
* This switches the LVDS transceiver to the single-channel
* output mode.
*/
- lvds-ch-mode {
+ lvds-ch-mode-hog {
gpio-hog;
gpios = <0 GPIO_ACTIVE_HIGH>; /* SODIMM 55 */
line-name = "LVDS_CH_MODE";
@@ -44,7 +52,7 @@
/*
* This switches the LVDS transceiver to the 24-bit RGB mode.
*/
- lvds-rgb-mode {
+ lvds-rgb-mode-hog {
gpio-hog;
gpios = <1 GPIO_ACTIVE_HIGH>; /* SODIMM 63 */
line-name = "LVDS_RGB_MODE";
@@ -56,10 +64,42 @@
/*
* This switches the LVDS transceiver to VESA color mapping mode.
*/
- lvds-color-map {
+ lvds-color-map-hog {
gpio-hog;
gpios = <3 GPIO_ACTIVE_HIGH>; /* SODIMM 95 */
line-name = "LVDS_COLOR_MAP";
output-low;
};
};
+
+&i2c1 {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&lcdif {
+ status = "okay";
+};
+
+&panel_dpi {
+ status = "okay";
+};
+
+&pwm4 {
+ status = "okay";
+};
+
+/* PWM <B> */
+&pwm5 {
+ /* Pin already used by atmel_mxt_ts touchscreen */
+ status = "disabled";
+};
+
+/* PWM <C> */
+&pwm6 {
+ /* Pin already used by atmel_mxt_ts touchscreen */
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6ull-colibri-iris.dts b/arch/arm/boot/dts/imx6ull-colibri-iris.dts
index 4fb97b0fe30b..2a0d0fc3b9d6 100644
--- a/arch/arm/boot/dts/imx6ull-colibri-iris.dts
+++ b/arch/arm/boot/dts/imx6ull-colibri-iris.dts
@@ -15,6 +15,26 @@
"fsl,imx6ull";
};
-&atmel_mxt_ts {
+&ad7879_ts {
+ status = "okay";
+};
+
+&backlight {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&lcdif {
+ status = "okay";
+};
+
+&panel_dpi {
+ status = "okay";
+};
+
+&pwm4 {
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6ull-colibri-iris.dtsi b/arch/arm/boot/dts/imx6ull-colibri-iris.dtsi
index 7f3b37baba88..166a0aefc869 100644
--- a/arch/arm/boot/dts/imx6ull-colibri-iris.dtsi
+++ b/arch/arm/boot/dts/imx6ull-colibri-iris.dtsi
@@ -59,7 +59,7 @@
* in userspace.
* The same applies to uart1_tx_on.
*/
- uart25_tx_on {
+ uart25_tx_on-hog {
gpio-hog;
gpios = <15 0>;
output-high;
@@ -67,7 +67,7 @@
};
&gpio2 {
- uart1_tx_on {
+ uart1_tx_on-hog {
gpio-hog;
gpios = <7 0>;
output-high;
diff --git a/arch/arm/boot/dts/imx6ull-colibri-wifi-aster.dts b/arch/arm/boot/dts/imx6ull-colibri-wifi-aster.dts
index b4f65e8c5857..c7da5b41966f 100644
--- a/arch/arm/boot/dts/imx6ull-colibri-wifi-aster.dts
+++ b/arch/arm/boot/dts/imx6ull-colibri-wifi-aster.dts
@@ -15,6 +15,46 @@
"fsl,imx6ull";
};
+&ad7879_ts {
+ status = "okay";
+};
+
&atmel_mxt_ts {
status = "okay";
};
+
+&backlight {
+ status = "okay";
+};
+
+&i2c1 {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&lcdif {
+ status = "okay";
+};
+
+&panel_dpi {
+ status = "okay";
+};
+
+&pwm4 {
+ status = "okay";
+};
+
+/* PWM <B> */
+&pwm5 {
+ /* Pin already used by atmel_mxt_ts touchscreen */
+ status = "disabled";
+};
+
+/* PWM <C> */
+&pwm6 {
+ /* Pin already used by atmel_mxt_ts touchscreen */
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/imx6ull-colibri-wifi-eval-v3.dts b/arch/arm/boot/dts/imx6ull-colibri-wifi-eval-v3.dts
index 1d64d1a5d8a7..917f5dbe64ba 100644
--- a/arch/arm/boot/dts/imx6ull-colibri-wifi-eval-v3.dts
+++ b/arch/arm/boot/dts/imx6ull-colibri-wifi-eval-v3.dts
@@ -12,3 +12,27 @@
model = "Toradex Colibri iMX6ULL 512MB on Colibri Evaluation Board V3";
compatible = "toradex,colibri-imx6ull-wifi-eval", "fsl,imx6ull";
};
+
+&ad7879_ts {
+ status = "okay";
+};
+
+&backlight {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&lcdif {
+ status = "okay";
+};
+
+&panel_dpi {
+ status = "okay";
+};
+
+&pwm4 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6ull-colibri-wifi-iris-v2.dts b/arch/arm/boot/dts/imx6ull-colibri-wifi-iris-v2.dts
index ce02f8a9ddd3..488da6df56fa 100644
--- a/arch/arm/boot/dts/imx6ull-colibri-wifi-iris-v2.dts
+++ b/arch/arm/boot/dts/imx6ull-colibri-wifi-iris-v2.dts
@@ -15,13 +15,21 @@
"fsl,imx6ull";
};
+&ad7879_ts {
+ status = "okay";
+};
+
&atmel_mxt_ts {
status = "okay";
};
+&backlight {
+ status = "okay";
+};
+
&gpio1 {
/* This turns the LVDS transceiver on */
- lvds-power-on {
+ lvds-power-on-hog {
gpio-hog;
gpios = <14 GPIO_ACTIVE_HIGH>; /* SODIMM 99 */
line-name = "LVDS_POWER_ON";
@@ -34,7 +42,7 @@
* This switches the LVDS transceiver to the single-channel
* output mode.
*/
- lvds-ch-mode {
+ lvds-ch-mode-hog {
gpio-hog;
gpios = <0 GPIO_ACTIVE_HIGH>; /* SODIMM 55 */
line-name = "LVDS_CH_MODE";
@@ -44,7 +52,7 @@
/*
* This switches the LVDS transceiver to the 24-bit RGB mode.
*/
- lvds-rgb-mode {
+ lvds-rgb-mode-hog {
gpio-hog;
gpios = <1 GPIO_ACTIVE_HIGH>; /* SODIMM 63 */
line-name = "LVDS_RGB_MODE";
@@ -56,10 +64,26 @@
/*
* This switches the LVDS transceiver to VESA color mapping mode.
*/
- lvds-color-map {
+ lvds-color-map-hog {
gpio-hog;
gpios = <3 GPIO_ACTIVE_HIGH>; /* SODIMM 95 */
line-name = "LVDS_COLOR_MAP";
output-low;
};
};
+
+&i2c2 {
+ status = "okay";
+};
+
+&lcdif {
+ status = "okay";
+};
+
+&panel_dpi {
+ status = "okay";
+};
+
+&pwm4 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6ull-colibri-wifi-iris.dts b/arch/arm/boot/dts/imx6ull-colibri-wifi-iris.dts
index 5ac1aa298ce7..e63253254754 100644
--- a/arch/arm/boot/dts/imx6ull-colibri-wifi-iris.dts
+++ b/arch/arm/boot/dts/imx6ull-colibri-wifi-iris.dts
@@ -15,6 +15,26 @@
"fsl,imx6ull";
};
+&ad7879_ts {
+ status = "okay";
+};
+
&atmel_mxt_ts {
status = "okay";
};
+
+&backlight {
+ status = "okay";
+};
+
+&i2c2 {
+ status = "okay";
+};
+
+&lcdif {
+ status = "okay";
+};
+
+&panel_dpi {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6ull-colibri.dtsi b/arch/arm/boot/dts/imx6ull-colibri.dtsi
index 577a424b0e1d..336ab2e0534c 100644
--- a/arch/arm/boot/dts/imx6ull-colibri.dtsi
+++ b/arch/arm/boot/dts/imx6ull-colibri.dtsi
@@ -21,7 +21,29 @@
pinctrl-0 = <&pinctrl_gpio_bl_on>;
power-supply = <&reg_3v3>;
pwms = <&pwm4 0 5000000 1>;
- status = "okay";
+ status = "disabled";
+ };
+
+ connector {
+ compatible = "gpio-usb-b-connector", "usb-b-connector";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_snvs_usbc_det>;
+ id-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>; /* SODIMM 137 / USBC_DET */
+ label = "USBC";
+ self-powered;
+ type = "micro";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ usb_dr_connector: endpoint {
+ remote-endpoint = <&usb1_drd_sw>;
+ };
+ };
+ };
};
gpio-keys {
@@ -42,7 +64,7 @@
compatible = "edt,et057090dhu";
backlight = <&backlight>;
power-supply = <&reg_3v3>;
- status = "okay";
+ status = "disabled";
port {
lcd_panel_in: endpoint {
@@ -159,7 +181,7 @@
pinctrl-1 = <&pinctrl_i2c1_gpio>;
sda-gpios = <&gpio1 29 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
scl-gpios = <&gpio1 28 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
- status = "okay";
+ status = "disabled";
/* Atmel maxtouch controller */
atmel_mxt_ts: touchscreen@4a {
@@ -202,6 +224,7 @@
adi,median-filter-size = /bits/ 8 <2>;
adi,averaging = /bits/ 8 <1>;
adi,conversion-interval = /bits/ 8 <255>;
+ status = "disabled";
};
};
@@ -209,6 +232,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_lcdif_dat
&pinctrl_lcdif_ctrl>;
+ status = "disabled";
port {
lcdif_out: endpoint {
@@ -278,6 +302,13 @@
srp-disable;
hnp-disable;
adp-disable;
+ usb-role-switch;
+
+ port {
+ usb1_drd_sw: endpoint {
+ remote-endpoint = <&usb_dr_connector>;
+ };
+ };
};
/* Colibri USBH */
diff --git a/arch/arm/boot/dts/imx7-colibri.dtsi b/arch/arm/boot/dts/imx7-colibri.dtsi
index a8c31ee65623..f8b8372b6851 100644
--- a/arch/arm/boot/dts/imx7-colibri.dtsi
+++ b/arch/arm/boot/dts/imx7-colibri.dtsi
@@ -29,7 +29,6 @@
extcon_usbc_det: usbc-det {
compatible = "linux,extcon-usb-gpio";
- debounce = <25>;
id-gpio = <&gpio7 14 GPIO_ACTIVE_HIGH>; /* SODIMM 137 / USBC_DET */
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usbc_det>;
@@ -652,7 +651,7 @@
* NOTE: This pin group conflicts with pin groups pinctrl_pwm2/pinctrl_pwm3.
* Don't use them simultaneously.
*/
- pinctrl_atmel_adapter: atmelconnectorgrp {
+ pinctrl_atmel_adapter: atmeladaptergrp {
fsl,pins = <
MX7D_PAD_GPIO1_IO09__GPIO1_IO9 0x74 /* SODIMM 28 / INT */
MX7D_PAD_GPIO1_IO10__GPIO1_IO10 0x14 /* SODIMM 30 / RST */
@@ -660,7 +659,7 @@
};
/* Atmel MXT touchsceen + boards with built-in Capacitive Touch Connector */
- pinctrl_atmel_connector: atmeladaptergrp {
+ pinctrl_atmel_connector: atmelconnectorgrp {
fsl,pins = <
MX7D_PAD_EPDC_BDR0__GPIO2_IO28 0x14 /* SODIMM 106 / RST */
MX7D_PAD_EPDC_DATA15__GPIO2_IO15 0x74 /* SODIMM 107 / INT */
diff --git a/arch/arm/boot/dts/imx7d-remarkable2.dts b/arch/arm/boot/dts/imx7d-remarkable2.dts
index a2a91bfdd98e..8b2f11e85e05 100644
--- a/arch/arm/boot/dts/imx7d-remarkable2.dts
+++ b/arch/arm/boot/dts/imx7d-remarkable2.dts
@@ -22,6 +22,28 @@
reg = <0x80000000 0x40000000>;
};
+ thermal-zones {
+ epd-thermal {
+ thermal-sensors = <&sy7636a>;
+ polling-delay-passive = <30000>;
+ polling-delay = <30000>;
+
+ trips {
+ trip0 {
+ temperature = <49000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <50000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+ };
+
reg_brcm: regulator-brcm {
compatible = "regulator-fixed";
regulator-name = "brcm_reg";
@@ -84,6 +106,32 @@
};
};
+&i2c4 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&pinctrl_i2c4>;
+ pinctrl-1 = <&pinctrl_i2c4>;
+ status = "okay";
+
+ sy7636a: pmic@62 {
+ compatible = "silergy,sy7636a";
+ reg = <0x62>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_epdpmic>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #thermal-sensor-cells = <0>;
+ epd-pwr-good-gpios = <&gpio6 21 GPIO_ACTIVE_HIGH>;
+
+ regulators {
+ reg_epdpmic: vcom {
+ regulator-name = "vcom";
+ regulator-boot-on;
+ };
+ };
+ };
+};
+
&snvs_pwrkey {
status = "okay";
};
@@ -177,6 +225,13 @@
>;
};
+ pinctrl_epdpmic: epdpmicgrp {
+ fsl,pins = <
+ MX7D_PAD_SAI2_RX_DATA__GPIO6_IO21 0x00000074
+ MX7D_PAD_ENET1_RGMII_TXC__GPIO7_IO11 0x00000014
+ >;
+ };
+
pinctrl_i2c1: i2c1grp {
fsl,pins = <
MX7D_PAD_I2C1_SDA__I2C1_SDA 0x4000007f
@@ -184,6 +239,13 @@
>;
};
+ pinctrl_i2c4: i2c4grp {
+ fsl,pins = <
+ MX7D_PAD_I2C4_SDA__I2C4_SDA 0x4000007f
+ MX7D_PAD_I2C4_SCL__I2C4_SCL 0x4000007f
+ >;
+ };
+
pinctrl_uart1: uart1grp {
fsl,pins = <
MX7D_PAD_UART1_TX_DATA__UART1_DCE_TX 0x79
diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi
index 03d2e8544a4e..0fc9e6b8b05d 100644
--- a/arch/arm/boot/dts/imx7s.dtsi
+++ b/arch/arm/boot/dts/imx7s.dtsi
@@ -1270,10 +1270,10 @@
clocks = <&clks IMX7D_NAND_USDHC_BUS_RAWNAND_CLK>;
};
- gpmi: nand-controller@33002000 {
+ gpmi: nand-controller@33002000{
compatible = "fsl,imx7d-gpmi-nand";
#address-cells = <1>;
- #size-cells = <0>;
+ #size-cells = <1>;
reg = <0x33002000 0x2000>, <0x33004000 0x4000>;
reg-names = "gpmi-nand", "bch";
interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm/boot/dts/kirkwood-b3.dts b/arch/arm/boot/dts/kirkwood-b3.dts
index a7636fe28501..681343c1357a 100644
--- a/arch/arm/boot/dts/kirkwood-b3.dts
+++ b/arch/arm/boot/dts/kirkwood-b3.dts
@@ -187,7 +187,7 @@
/* Wifi model has Atheros chipset on pcie port */
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-db-88f6281.dts b/arch/arm/boot/dts/kirkwood-db-88f6281.dts
index 2adb17c955aa..a9a8e6b744c7 100644
--- a/arch/arm/boot/dts/kirkwood-db-88f6281.dts
+++ b/arch/arm/boot/dts/kirkwood-db-88f6281.dts
@@ -18,7 +18,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-db-88f6282.dts b/arch/arm/boot/dts/kirkwood-db-88f6282.dts
index f84a48539917..6dc6579d4524 100644
--- a/arch/arm/boot/dts/kirkwood-db-88f6282.dts
+++ b/arch/arm/boot/dts/kirkwood-db-88f6282.dts
@@ -18,7 +18,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-dir665.dts b/arch/arm/boot/dts/kirkwood-dir665.dts
index c32300611d2c..f9f4b0143ba8 100644
--- a/arch/arm/boot/dts/kirkwood-dir665.dts
+++ b/arch/arm/boot/dts/kirkwood-dir665.dts
@@ -211,18 +211,18 @@
};
port@1 {
- reg = <1>;
- label = "lan3";
+ reg = <1>;
+ label = "lan3";
};
port@2 {
- reg = <2>;
- label = "lan2";
+ reg = <2>;
+ label = "lan2";
};
port@3 {
- reg = <3>;
- label = "lan1";
+ reg = <3>;
+ label = "lan1";
};
port@4 {
@@ -268,7 +268,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-ds112.dts b/arch/arm/boot/dts/kirkwood-ds112.dts
index f48609e95afe..3912f1b525b6 100644
--- a/arch/arm/boot/dts/kirkwood-ds112.dts
+++ b/arch/arm/boot/dts/kirkwood-ds112.dts
@@ -43,7 +43,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie1 {
diff --git a/arch/arm/boot/dts/kirkwood-ds411.dts b/arch/arm/boot/dts/kirkwood-ds411.dts
index 86907be70cf9..1d4256ef325d 100644
--- a/arch/arm/boot/dts/kirkwood-ds411.dts
+++ b/arch/arm/boot/dts/kirkwood-ds411.dts
@@ -47,7 +47,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie1 {
diff --git a/arch/arm/boot/dts/kirkwood-iconnect.dts b/arch/arm/boot/dts/kirkwood-iconnect.dts
index 95af7aa1fdcb..aed20185fd7a 100644
--- a/arch/arm/boot/dts/kirkwood-iconnect.dts
+++ b/arch/arm/boot/dts/kirkwood-iconnect.dts
@@ -187,7 +187,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-km_common.dtsi b/arch/arm/boot/dts/kirkwood-km_common.dtsi
index 75dc83914f56..52baffe45f12 100644
--- a/arch/arm/boot/dts/kirkwood-km_common.dtsi
+++ b/arch/arm/boot/dts/kirkwood-km_common.dtsi
@@ -39,7 +39,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-l-50.dts b/arch/arm/boot/dts/kirkwood-l-50.dts
index 0d81c43a6a73..60c1e94f5dd3 100644
--- a/arch/arm/boot/dts/kirkwood-l-50.dts
+++ b/arch/arm/boot/dts/kirkwood-l-50.dts
@@ -223,18 +223,18 @@
};
port@1 {
- reg = <1>;
- label = "lan1";
+ reg = <1>;
+ label = "lan1";
};
port@2 {
- reg = <2>;
- label = "lan6";
+ reg = <2>;
+ label = "lan6";
};
port@3 {
- reg = <3>;
- label = "lan2";
+ reg = <3>;
+ label = "lan2";
};
port@4 {
@@ -282,18 +282,18 @@
};
port@1 {
- reg = <1>;
- label = "lan8";
+ reg = <1>;
+ label = "lan8";
};
port@2 {
- reg = <2>;
- label = "lan4";
+ reg = <2>;
+ label = "lan4";
};
port@3 {
- reg = <3>;
- label = "dmz";
+ reg = <3>;
+ label = "dmz";
};
switch1port5: port@5 {
diff --git a/arch/arm/boot/dts/kirkwood-laplug.dts b/arch/arm/boot/dts/kirkwood-laplug.dts
index 6158214a939a..8c2b540eaf4f 100644
--- a/arch/arm/boot/dts/kirkwood-laplug.dts
+++ b/arch/arm/boot/dts/kirkwood-laplug.dts
@@ -160,7 +160,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-linkstation.dtsi b/arch/arm/boot/dts/kirkwood-linkstation.dtsi
index 407d6d8b3a7f..b54c9980f636 100644
--- a/arch/arm/boot/dts/kirkwood-linkstation.dtsi
+++ b/arch/arm/boot/dts/kirkwood-linkstation.dtsi
@@ -156,7 +156,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-mplcec4.dts b/arch/arm/boot/dts/kirkwood-mplcec4.dts
index b80d12f6aa49..e87ea7146546 100644
--- a/arch/arm/boot/dts/kirkwood-mplcec4.dts
+++ b/arch/arm/boot/dts/kirkwood-mplcec4.dts
@@ -8,10 +8,10 @@
model = "MPL CEC4";
compatible = "mpl,cec4-10", "mpl,cec4", "marvell,kirkwood-88f6281", "marvell,kirkwood";
- memory {
- device_type = "memory";
- reg = <0x00000000 0x20000000>;
- };
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x20000000>;
+ };
chosen {
bootargs = "console=ttyS0,115200n8 earlyprintk";
@@ -66,8 +66,8 @@
};
};
- i2c@11000 {
- status = "okay";
+ i2c@11000 {
+ status = "okay";
rtc@51 {
compatible = "nxp,pcf8563";
@@ -79,7 +79,7 @@
reg = <0x57>;
};
- };
+ };
serial@12000 {
status = "okay";
@@ -208,7 +208,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts b/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts
index 2e1a75348908..ced576acfb95 100644
--- a/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts
+++ b/arch/arm/boot/dts/kirkwood-mv88f6281gtw-ge.dts
@@ -170,7 +170,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-nas2big.dts b/arch/arm/boot/dts/kirkwood-nas2big.dts
index 6a2934b7d0ce..0b0a15093146 100644
--- a/arch/arm/boot/dts/kirkwood-nas2big.dts
+++ b/arch/arm/boot/dts/kirkwood-nas2big.dts
@@ -131,7 +131,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-net2big.dts b/arch/arm/boot/dts/kirkwood-net2big.dts
index 3e3ac289e5b0..d5f6bb50ba11 100644
--- a/arch/arm/boot/dts/kirkwood-net2big.dts
+++ b/arch/arm/boot/dts/kirkwood-net2big.dts
@@ -46,11 +46,11 @@
};
clocks {
- g762_clk: g762-oscillator {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <32768>;
- };
+ g762_clk: g762-oscillator {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ };
};
};
diff --git a/arch/arm/boot/dts/kirkwood-net5big.dts b/arch/arm/boot/dts/kirkwood-net5big.dts
index cba8a2b6f6d9..2497ad26b5b6 100644
--- a/arch/arm/boot/dts/kirkwood-net5big.dts
+++ b/arch/arm/boot/dts/kirkwood-net5big.dts
@@ -78,11 +78,11 @@
};
clocks {
- g762_clk: g762-oscillator {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <32768>;
- };
+ g762_clk: g762-oscillator {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ };
};
netxbig-leds {
diff --git a/arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts b/arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts
index b13aee570804..6cf76430cfab 100644
--- a/arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts
+++ b/arch/arm/boot/dts/kirkwood-netgear_readynas_nv+_v2.dts
@@ -78,11 +78,11 @@
};
clocks {
- g762_clk: g762-oscillator {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <8192>;
- };
+ g762_clk: g762-oscillator {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <8192>;
+ };
};
i2c@11000 {
@@ -266,7 +266,7 @@
/* Connected to NEC uPD720200 USB 3.0 controller */
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-nsa310.dts b/arch/arm/boot/dts/kirkwood-nsa310.dts
index 9b861c2e76c5..c1799a07816e 100644
--- a/arch/arm/boot/dts/kirkwood-nsa310.dts
+++ b/arch/arm/boot/dts/kirkwood-nsa310.dts
@@ -131,7 +131,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-nsa310s.dts b/arch/arm/boot/dts/kirkwood-nsa310s.dts
new file mode 100644
index 000000000000..49da633a1bc0
--- /dev/null
+++ b/arch/arm/boot/dts/kirkwood-nsa310s.dts
@@ -0,0 +1,259 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * ZyXEL NSA310S Board Description
+ * Copyright 2020-2022 Pawel Dembicki <paweldembicki@gmail.com>
+ * Copyright (c) 2015-2021, Tony Dinh <mibodhi@gmail.com>
+ * Copyright (c) 2014, Adam Baker <linux@baker-net.org.uk>
+ * Based upon the board setup file created by Peter Schildmann
+ */
+/dts-v1/;
+
+#include "kirkwood.dtsi"
+#include "kirkwood-6281.dtsi"
+#include <dt-bindings/leds/common.h>
+
+/ {
+ model = "ZyXEL NSA310S";
+ compatible = "zyxel,nsa310s", "marvell,kirkwood-88f6702", "marvell,kirkwood";
+
+ memory {
+ device_type = "memory";
+ reg = <0x00000000 0x10000000>;
+ };
+
+ chosen {
+ bootargs = "console=ttyS0,115200n8 earlyprintk";
+ stdout-path = &uart0;
+ };
+
+ gpio_poweroff {
+ compatible = "gpio-poweroff";
+ pinctrl-0 = <&pmx_pwr_off>;
+ pinctrl-names = "default";
+ gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>;
+ };
+
+ keys {
+ compatible = "gpio-keys";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-0 = <&pmx_buttons>;
+ pinctrl-names = "default";
+
+ power {
+ label = "Power Button";
+ linux,code = <KEY_POWER>;
+ gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>;
+ };
+
+ copy {
+ label = "Copy Button";
+ linux,code = <KEY_COPY>;
+ gpios = <&gpio0 25 GPIO_ACTIVE_LOW>;
+ };
+
+ reset {
+ label = "Reset Button";
+ linux,code = <KEY_RESTART>;
+ gpios = <&gpio0 24 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-0 = <&pmx_leds>;
+ pinctrl-names = "default";
+
+ led-1 {
+ function = LED_FUNCTION_DISK_ERR;
+ color = <LED_COLOR_ID_RED>;
+ gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
+ };
+
+ led-2 {
+ function = LED_FUNCTION_USB;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&gpio0 15 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "usb-host";
+ };
+
+ led-3 {
+ function = LED_FUNCTION_DISK;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "ata1";
+ };
+
+ led-4 {
+ function = LED_FUNCTION_INDICATOR;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>;
+ };
+
+ led-5 {
+ function = LED_FUNCTION_INDICATOR;
+ color = <LED_COLOR_ID_RED>;
+ gpios = <&gpio0 23 GPIO_ACTIVE_HIGH>;
+ };
+
+ led-6 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_GREEN>;
+ gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "default-on";
+ };
+
+ led-7 {
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_RED>;
+ gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ usb0_power: regulator@1 {
+ compatible = "regulator-fixed";
+ regulator-name = "USB Power";
+
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ regulator-boot-on;
+ gpio = <&gpio0 21 GPIO_ACTIVE_HIGH>;
+ };
+
+ sata1_power: regulator@2 {
+ compatible = "regulator-fixed";
+ regulator-name = "SATA1 Power";
+
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-always-on;
+ regulator-boot-on;
+ gpio = <&gpio1 1 GPIO_ACTIVE_HIGH>;
+ };
+
+ thermal-zones {
+ disk-thermal {
+ polling-delay = <20000>;
+ polling-delay-passive = <2000>;
+
+ thermal-sensors = <&hdd_temp>;
+
+ trips {
+ disk_alert: disk-alert {
+ temperature = <40000>;
+ hysteresis = <5000>;
+ type = "active";
+ };
+ disk_crit: disk-crit {
+ temperature = <60000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+ };
+};
+
+
+&eth0 {
+ status = "okay";
+
+ ethernet0-port@0 {
+ phy-handle = <&ethphy0>;
+ };
+};
+
+&i2c0 {
+ status = "okay";
+
+ rtc@68 {
+ compatible = "htk,ht1382";
+ reg = <0x68>;
+ };
+};
+
+&mdio {
+ status = "okay";
+
+ ethphy0: ethernet-phy@1 {
+ reg = <1>;
+ phy-mode = "rgmii-id";
+ marvell,reg-init = <0x1 0x16 0x0 0x3>,
+ <0x1 0x10 0x0 0x1017>,
+ <0x1 0x11 0x0 0x4408>,
+ <0x1 0x16 0x0 0x0>;
+ };
+};
+
+&nand {
+ status = "okay";
+ chip-delay = <35>;
+
+ partition@0 {
+ label = "uboot";
+ reg = <0x0000000 0x00c0000>;
+ read-only;
+ };
+ partition@c0000 {
+ label = "uboot_env";
+ reg = <0x00c0000 0x0080000>;
+ };
+ partition@140000 {
+ label = "ubi";
+ reg = <0x0140000 0x7ec0000>;
+ };
+};
+
+&pciec {
+ status = "okay";
+};
+
+&pcie0 {
+ status = "okay";
+};
+
+&pinctrl {
+ pinctrl-names = "default";
+
+ pmx_buttons: pmx-buttons {
+ marvell,pins = "mpp24", "mpp25", "mpp26";
+ marvell,function = "gpio";
+ };
+
+ pmx_leds: pmx-leds {
+ marvell,pins = "mpp13", "mpp15", "mpp16", "mpp22", "mpp23",
+ "mpp28", "mpp29";
+ marvell,function = "gpio";
+ };
+
+ pmx_power: pmx-power {
+ marvell,pins = "mpp21", "mpp33";
+ marvell,function = "gpio";
+ };
+
+ pmx_pwr_off: pmx-pwr-off {
+ marvell,pins = "mpp27";
+ marvell,function = "gpio";
+ };
+};
+
+&rtc {
+ status = "disabled";
+};
+
+&sata {
+ status = "okay";
+ nr-ports = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ hdd_temp: sata-port@0 {
+ reg = <0>;
+ #thermal-sensor-cells = <0>;
+ };
+};
+
+&uart0 {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/kirkwood-nsa320.dts b/arch/arm/boot/dts/kirkwood-nsa320.dts
index b69b096f267b..652405e65006 100644
--- a/arch/arm/boot/dts/kirkwood-nsa320.dts
+++ b/arch/arm/boot/dts/kirkwood-nsa320.dts
@@ -211,7 +211,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-nsa325.dts b/arch/arm/boot/dts/kirkwood-nsa325.dts
index 6f8085dbb1f4..371456de34b2 100644
--- a/arch/arm/boot/dts/kirkwood-nsa325.dts
+++ b/arch/arm/boot/dts/kirkwood-nsa325.dts
@@ -224,7 +224,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi b/arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi
index 8f73197f251a..ea3d36512e9f 100644
--- a/arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi
+++ b/arch/arm/boot/dts/kirkwood-nsa3x0-common.dtsi
@@ -150,7 +150,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-rd88f6192.dts b/arch/arm/boot/dts/kirkwood-rd88f6192.dts
index 712d6042b132..f00325ffde07 100644
--- a/arch/arm/boot/dts/kirkwood-rd88f6192.dts
+++ b/arch/arm/boot/dts/kirkwood-rd88f6192.dts
@@ -31,10 +31,10 @@
pinctrl-0 = <&pmx_usb_power>;
pinctrl-names = "default";
- pmx_usb_power: pmx-usb-power {
- marvell,pins = "mpp10";
- marvell,function = "gpo";
- };
+ pmx_usb_power: pmx-usb-power {
+ marvell,pins = "mpp10";
+ marvell,function = "gpo";
+ };
};
serial@12000 {
@@ -62,43 +62,43 @@
};
regulators {
- compatible = "simple-bus";
- #address-cells = <1>;
- #size-cells = <0>;
- pinctrl-0 = <&pmx_usb_power>;
- pinctrl-names = "default";
-
- usb_power: regulator@0 {
- compatible = "regulator-fixed";
- reg = <0>;
- regulator-name = "USB VBUS";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
- enable-active-high;
- regulator-always-on;
- regulator-boot-on;
- gpio = <&gpio0 10 GPIO_ACTIVE_HIGH>;
- };
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-0 = <&pmx_usb_power>;
+ pinctrl-names = "default";
+
+ usb_power: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "USB VBUS";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ enable-active-high;
+ regulator-always-on;
+ regulator-boot-on;
+ gpio = <&gpio0 10 GPIO_ACTIVE_HIGH>;
+ };
};
};
&mdio {
- status = "okay";
+ status = "okay";
- ethphy0: ethernet-phy@8 {
- reg = <8>;
- };
+ ethphy0: ethernet-phy@8 {
+ reg = <8>;
+ };
};
&eth0 {
- status = "okay";
- ethernet0-port@0 {
- phy-handle = <&ethphy0>;
- };
+ status = "okay";
+ ethernet0-port@0 {
+ phy-handle = <&ethphy0>;
+ };
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-rd88f6281-z0.dts b/arch/arm/boot/dts/kirkwood-rd88f6281-z0.dts
index 9d88301daf0e..72edd47e19ff 100644
--- a/arch/arm/boot/dts/kirkwood-rd88f6281-z0.dts
+++ b/arch/arm/boot/dts/kirkwood-rd88f6281-z0.dts
@@ -19,7 +19,7 @@
};
&eth1 {
- status = "disabled";
+ status = "disabled";
};
&switch {
diff --git a/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi b/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi
index f1f8eee132e8..e21aa674945d 100644
--- a/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi
+++ b/arch/arm/boot/dts/kirkwood-rd88f6281.dtsi
@@ -48,7 +48,7 @@
cd-gpios = <&gpio0 28 GPIO_ACTIVE_HIGH>;
/* No WP GPIO */
};
- };
+ };
};
&nand {
@@ -126,7 +126,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-rs212.dts b/arch/arm/boot/dts/kirkwood-rs212.dts
index c51cea883215..4ad412115a24 100644
--- a/arch/arm/boot/dts/kirkwood-rs212.dts
+++ b/arch/arm/boot/dts/kirkwood-rs212.dts
@@ -43,7 +43,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie1 {
diff --git a/arch/arm/boot/dts/kirkwood-synology.dtsi b/arch/arm/boot/dts/kirkwood-synology.dtsi
index 8f6c387d3a8b..9b6666020cdd 100644
--- a/arch/arm/boot/dts/kirkwood-synology.dtsi
+++ b/arch/arm/boot/dts/kirkwood-synology.dtsi
@@ -847,7 +847,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-t5325.dts b/arch/arm/boot/dts/kirkwood-t5325.dts
index fe63b3a03a72..ad093324e075 100644
--- a/arch/arm/boot/dts/kirkwood-t5325.dts
+++ b/arch/arm/boot/dts/kirkwood-t5325.dts
@@ -219,7 +219,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood-ts219.dtsi b/arch/arm/boot/dts/kirkwood-ts219.dtsi
index 994cabcf4b51..1939462a5f48 100644
--- a/arch/arm/boot/dts/kirkwood-ts219.dtsi
+++ b/arch/arm/boot/dts/kirkwood-ts219.dtsi
@@ -86,7 +86,7 @@
status = "okay";
ethphy0: ethernet-phy@X {
- /* overwrite reg property in board file */
+ /* overwrite reg property in board file */
};
};
@@ -98,7 +98,7 @@
};
&pciec {
- status = "okay";
+ status = "okay";
};
&pcie0 {
diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/kirkwood.dtsi
index fca31a5d5ac7..815ef7719d13 100644
--- a/arch/arm/boot/dts/kirkwood.dtsi
+++ b/arch/arm/boot/dts/kirkwood.dtsi
@@ -24,9 +24,9 @@
};
aliases {
- gpio0 = &gpio0;
- gpio1 = &gpio1;
- i2c0 = &i2c0;
+ gpio0 = &gpio0;
+ gpio1 = &gpio1;
+ i2c0 = &i2c0;
};
mbus@f1000000 {
@@ -279,15 +279,15 @@
clocks = <&gate_clk 8>;
xor00 {
- interrupts = <5>;
- dmacap,memcpy;
- dmacap,xor;
+ interrupts = <5>;
+ dmacap,memcpy;
+ dmacap,xor;
};
xor01 {
- interrupts = <6>;
- dmacap,memcpy;
- dmacap,xor;
- dmacap,memset;
+ interrupts = <6>;
+ dmacap,memcpy;
+ dmacap,xor;
+ dmacap,memset;
};
};
@@ -299,15 +299,15 @@
clocks = <&gate_clk 16>;
xor00 {
- interrupts = <7>;
- dmacap,memcpy;
- dmacap,xor;
+ interrupts = <7>;
+ dmacap,memcpy;
+ dmacap,xor;
};
xor01 {
- interrupts = <8>;
- dmacap,memcpy;
- dmacap,xor;
- dmacap,memset;
+ interrupts = <8>;
+ dmacap,memcpy;
+ dmacap,xor;
+ dmacap,memset;
};
};
diff --git a/arch/arm/boot/dts/lan966x-pcb8290.dts b/arch/arm/boot/dts/lan966x-pcb8290.dts
index 77187f59f04d..8804e8ba5370 100644
--- a/arch/arm/boot/dts/lan966x-pcb8290.dts
+++ b/arch/arm/boot/dts/lan966x-pcb8290.dts
@@ -58,41 +58,57 @@
ext_phy0: ethernet-phy@7 {
reg = <7>;
+ interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&gpio>;
coma-mode-gpios = <&gpio 60 GPIO_OPEN_DRAIN>;
};
ext_phy1: ethernet-phy@8 {
reg = <8>;
+ interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&gpio>;
coma-mode-gpios = <&gpio 60 GPIO_OPEN_DRAIN>;
};
ext_phy2: ethernet-phy@9 {
reg = <9>;
+ interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&gpio>;
coma-mode-gpios = <&gpio 60 GPIO_OPEN_DRAIN>;
};
ext_phy3: ethernet-phy@10 {
reg = <10>;
+ interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&gpio>;
coma-mode-gpios = <&gpio 60 GPIO_OPEN_DRAIN>;
};
ext_phy4: ethernet-phy@15 {
reg = <15>;
+ interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&gpio>;
coma-mode-gpios = <&gpio 60 GPIO_OPEN_DRAIN>;
};
ext_phy5: ethernet-phy@16 {
reg = <16>;
+ interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&gpio>;
coma-mode-gpios = <&gpio 60 GPIO_OPEN_DRAIN>;
};
ext_phy6: ethernet-phy@17 {
reg = <17>;
+ interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&gpio>;
coma-mode-gpios = <&gpio 60 GPIO_OPEN_DRAIN>;
};
ext_phy7: ethernet-phy@18 {
reg = <18>;
+ interrupts = <24 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&gpio>;
coma-mode-gpios = <&gpio 60 GPIO_OPEN_DRAIN>;
};
};
diff --git a/arch/arm/boot/dts/lan966x.dtsi b/arch/arm/boot/dts/lan966x.dtsi
index 0bf818713422..05b73f7cf0c7 100644
--- a/arch/arm/boot/dts/lan966x.dtsi
+++ b/arch/arm/boot/dts/lan966x.dtsi
@@ -157,6 +157,11 @@
};
};
+ otp: otp@e0021000 {
+ compatible = "microchip,lan9668-otpc", "microchip,lan9662-otpc";
+ reg = <0xe0021000 0x300>;
+ };
+
flx0: flexcom@e0040000 {
compatible = "atmel,sama5d2-flexcom";
reg = <0xe0040000 0x100>;
diff --git a/arch/arm/boot/dts/logicpd-torpedo-baseboard.dtsi b/arch/arm/boot/dts/logicpd-torpedo-baseboard.dtsi
index d3da8b1b473b..e0cbac500e17 100644
--- a/arch/arm/boot/dts/logicpd-torpedo-baseboard.dtsi
+++ b/arch/arm/boot/dts/logicpd-torpedo-baseboard.dtsi
@@ -59,7 +59,7 @@
};
};
- pwm10: dmtimer-pwm {
+ pwm10: pwm-10 {
compatible = "ti,omap-dmtimer-pwm";
pinctrl-names = "default";
pinctrl-0 = <&pwm_pins>;
diff --git a/arch/arm/boot/dts/logicpd-torpedo-som.dtsi b/arch/arm/boot/dts/logicpd-torpedo-som.dtsi
index 3a5228562b0d..72b5af475d09 100644
--- a/arch/arm/boot/dts/logicpd-torpedo-som.dtsi
+++ b/arch/arm/boot/dts/logicpd-torpedo-som.dtsi
@@ -20,7 +20,7 @@
leds {
compatible = "gpio-leds";
- user0 {
+ led-user0 {
label = "user0";
gpios = <&twl_gpio 18 GPIO_ACTIVE_LOW>; /* LEDA */
linux,default-trigger = "none";
diff --git a/arch/arm/boot/dts/lpc32xx.dtsi b/arch/arm/boot/dts/lpc32xx.dtsi
index c87066d6c995..974410918f35 100644
--- a/arch/arm/boot/dts/lpc32xx.dtsi
+++ b/arch/arm/boot/dts/lpc32xx.dtsi
@@ -315,7 +315,7 @@
/* System Control Block */
scb {
compatible = "simple-bus";
- ranges = <0x0 0x040004000 0x00001000>;
+ ranges = <0x0 0x40004000 0x00001000>;
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/ls1021a-moxa-uc-8410a.dts b/arch/arm/boot/dts/ls1021a-moxa-uc-8410a.dts
index f3ddea934f1b..d2cae8c7d7a6 100644
--- a/arch/arm/boot/dts/ls1021a-moxa-uc-8410a.dts
+++ b/arch/arm/boot/dts/ls1021a-moxa-uc-8410a.dts
@@ -30,11 +30,11 @@
};
reg_3p3v: regulator-3p3v {
- compatible = "regulator-fixed";
- regulator-name = "3P3V";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
+ compatible = "regulator-fixed";
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
};
leds {
diff --git a/arch/arm/boot/dts/motorola-mapphone-common.dtsi b/arch/arm/boot/dts/motorola-mapphone-common.dtsi
index c7a1f3ffc48c..f7cc8fc678fa 100644
--- a/arch/arm/boot/dts/motorola-mapphone-common.dtsi
+++ b/arch/arm/boot/dts/motorola-mapphone-common.dtsi
@@ -133,7 +133,7 @@
dais = <&mcbsp2_port>, <&mcbsp3_port>;
};
- pwm8: dmtimer-pwm-8 {
+ pwm8: pwm-8 {
pinctrl-names = "default";
pinctrl-0 = <&vibrator_direction_pin>;
@@ -143,7 +143,7 @@
ti,clock-source = <0x01>;
};
- pwm9: dmtimer-pwm-9 {
+ pwm9: pwm-9 {
pinctrl-names = "default";
pinctrl-0 = <&vibrator_enable_pin>;
diff --git a/arch/arm/boot/dts/nuvoton-npcm730-gbs.dts b/arch/arm/boot/dts/nuvoton-npcm730-gbs.dts
index d10669fcd527..9e9eba8bad5e 100644
--- a/arch/arm/boot/dts/nuvoton-npcm730-gbs.dts
+++ b/arch/arm/boot/dts/nuvoton-npcm730-gbs.dts
@@ -366,7 +366,7 @@
spi-max-frequency = <20000000>;
spi-rx-bus-width = <2>;
label = "bmc";
- partitions@80000000 {
+ partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/nuvoton-npcm730-gsj.dts b/arch/arm/boot/dts/nuvoton-npcm730-gsj.dts
index 491606c4f044..2a394cc15284 100644
--- a/arch/arm/boot/dts/nuvoton-npcm730-gsj.dts
+++ b/arch/arm/boot/dts/nuvoton-npcm730-gsj.dts
@@ -142,7 +142,7 @@
reg = <0>;
spi-rx-bus-width = <2>;
- partitions@80000000 {
+ partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/nuvoton-npcm730-kudo.dts b/arch/arm/boot/dts/nuvoton-npcm730-kudo.dts
index a0c2d7652625..f7b38bee039b 100644
--- a/arch/arm/boot/dts/nuvoton-npcm730-kudo.dts
+++ b/arch/arm/boot/dts/nuvoton-npcm730-kudo.dts
@@ -388,7 +388,7 @@
spi-max-frequency = <5000000>;
spi-rx-bus-width = <2>;
label = "bmc";
- partitions@80000000 {
+ partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
@@ -422,7 +422,7 @@
reg = <1>;
spi-max-frequency = <5000000>;
spi-rx-bus-width = <2>;
- partitions@88000000 {
+ partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
@@ -447,7 +447,7 @@
reg = <0>;
spi-max-frequency = <5000000>;
spi-rx-bus-width = <2>;
- partitions@A0000000 {
+ partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/nuvoton-npcm750-evb.dts b/arch/arm/boot/dts/nuvoton-npcm750-evb.dts
index 3dad32834e5e..f53d45fa1de8 100644
--- a/arch/arm/boot/dts/nuvoton-npcm750-evb.dts
+++ b/arch/arm/boot/dts/nuvoton-npcm750-evb.dts
@@ -74,7 +74,7 @@
spi-rx-bus-width = <2>;
reg = <0>;
spi-max-frequency = <5000000>;
- partitions@80000000 {
+ partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
@@ -135,7 +135,7 @@
spi-rx-bus-width = <2>;
reg = <0>;
spi-max-frequency = <5000000>;
- partitions@A0000000 {
+ partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts b/arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts
index 132e702281fc..87359ab05db3 100644
--- a/arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts
+++ b/arch/arm/boot/dts/nuvoton-npcm750-runbmc-olympus.dts
@@ -107,7 +107,7 @@
reg = <0>;
spi-rx-bus-width = <2>;
- partitions@80000000 {
+ partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
@@ -146,7 +146,7 @@
reg = <1>;
npcm,fiu-rx-bus-width = <2>;
- partitions@88000000 {
+ partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
@@ -173,7 +173,7 @@
reg = <0>;
spi-rx-bus-width = <2>;
- partitions@A0000000 {
+ partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/arm/boot/dts/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts b/arch/arm/boot/dts/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts
index 3ee61251a16d..b78c116cbc18 100644
--- a/arch/arm/boot/dts/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts
+++ b/arch/arm/boot/dts/nuvoton-wpcm450-supermicro-x9sci-ln4f.dts
@@ -15,6 +15,11 @@
model = "Supermicro X9SCi-LN4F BMC";
compatible = "supermicro,x9sci-ln4f-bmc", "nuvoton,wpcm450";
+ aliases {
+ serial0 = &serial0;
+ serial1 = &serial1;
+ };
+
chosen {
stdout-path = "serial0:115200n8";
};
@@ -53,6 +58,33 @@
};
};
+&fiu {
+ status = "okay";
+
+ flash@0 {
+ reg = <0>;
+ compatible = "jedec,spi-nor";
+ };
+};
+
+&gpio0 {
+ gpio-line-names =
+ /* 0 */ "", "host-reset-control-n", "", "", "", "", "", "",
+ /* 8 */ "", "", "", "", "power-chassis-control-n", "", "uid-button", "";
+};
+
+&gpio1 {
+ gpio-line-names =
+ /* 0 */ "", "", "", "", "led-heartbeat", "", "", "led-uid",
+ /* 8 */ "", "", "", "", "", "", "", "";
+};
+
+&gpio4 {
+ gpio-line-names =
+ /* 0 */ "", "", "", "", "", "", "", "",
+ /* 8 */ "", "", "", "", "", "", "", "power-chassis-good";
+};
+
&pinctrl {
key_pins: mux-keys {
groups = "gspi", "sspi";
@@ -77,7 +109,3 @@
/* "Serial over LAN" port. Connected to ttyS2 of the host system. */
status = "okay";
};
-
-&watchdog0 {
- status = "okay";
-};
diff --git a/arch/arm/boot/dts/nuvoton-wpcm450.dtsi b/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
index 93595850a4c3..b637241316bb 100644
--- a/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
+++ b/arch/arm/boot/dts/nuvoton-wpcm450.dtsi
@@ -37,6 +37,14 @@
#clock-cells = <0>;
};
+ refclk: clock-48mhz {
+ /* 48 MHz reference oscillator */
+ compatible = "fixed-clock";
+ clock-output-names = "ref";
+ clock-frequency = <48000000>;
+ #clock-cells = <0>;
+ };
+
soc {
compatible = "simple-bus";
#address-cells = <1>;
@@ -49,6 +57,15 @@
reg = <0xb0000000 0x200>;
};
+ clk: clock-controller@b0000200 {
+ compatible = "nuvoton,wpcm450-clk";
+ reg = <0xb0000200 0x100>;
+ clocks = <&refclk>;
+ clock-names = "ref";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
serial0: serial@b8000000 {
compatible = "nuvoton,wpcm450-uart";
reg = <0xb8000000 0x20>;
@@ -81,7 +98,6 @@
interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
reg = <0xb800101c 0x4>;
clocks = <&clk24m>;
- status = "disabled";
};
aic: interrupt-controller@b8002000 {
@@ -456,5 +472,21 @@
function = "hg7";
};
};
+
+ fiu: spi-controller@c8000000 {
+ compatible = "nuvoton,wpcm450-fiu";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xc8000000 0x1000>, <0xc0000000 0x4000000>;
+ reg-names = "control", "memory";
+ clocks = <&clk 0>;
+ status = "disabled";
+ };
+
+ shm: syscon@c8001000 {
+ compatible = "nuvoton,wpcm450-shm", "syscon";
+ reg = <0xc8001000 0x1000>;
+ reg-io-width = <1>;
+ };
};
};
diff --git a/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi b/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi
index ce6c235f68ec..3046ec572632 100644
--- a/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi
+++ b/arch/arm/boot/dts/omap-gpmc-smsc911x.dtsi
@@ -8,9 +8,9 @@
/ {
vddvario: regulator-vddvario {
- compatible = "regulator-fixed";
- regulator-name = "vddvario";
- regulator-always-on;
+ compatible = "regulator-fixed";
+ regulator-name = "vddvario";
+ regulator-always-on;
};
vdd33a: regulator-vdd33a {
diff --git a/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi b/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi
index e7534fe9c53c..bc8961f3690f 100644
--- a/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi
+++ b/arch/arm/boot/dts/omap-gpmc-smsc9221.dtsi
@@ -12,9 +12,9 @@
/ {
vddvario: regulator-vddvario {
- compatible = "regulator-fixed";
- regulator-name = "vddvario";
- regulator-always-on;
+ compatible = "regulator-fixed";
+ regulator-name = "vddvario";
+ regulator-always-on;
};
vdd33a: regulator-vdd33a {
diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts
index 0548b391334f..47ff1ffddfc5 100644
--- a/arch/arm/boot/dts/omap3-beagle.dts
+++ b/arch/arm/boot/dts/omap3-beagle.dts
@@ -28,18 +28,18 @@
leds {
compatible = "gpio-leds";
- pmu_stat {
+ led-pmu-stat {
label = "beagleboard::pmu_stat";
gpios = <&twl_gpio 19 GPIO_ACTIVE_HIGH>; /* LEDB */
};
- heartbeat {
+ led-heartbeat {
label = "beagleboard::usr0";
gpios = <&gpio5 22 GPIO_ACTIVE_HIGH>; /* 150 -> D6 LED */
linux,default-trigger = "heartbeat";
};
- mmc {
+ led-mmc {
label = "beagleboard::usr1";
gpios = <&gpio5 21 GPIO_ACTIVE_HIGH>; /* 149 -> D7 LED */
linux,default-trigger = "mmc0";
diff --git a/arch/arm/boot/dts/omap3-cm-t3517.dts b/arch/arm/boot/dts/omap3-cm-t3517.dts
index 3b8349094baa..f25c0a84a190 100644
--- a/arch/arm/boot/dts/omap3-cm-t3517.dts
+++ b/arch/arm/boot/dts/omap3-cm-t3517.dts
@@ -11,12 +11,12 @@
model = "CompuLab CM-T3517";
compatible = "compulab,omap3-cm-t3517", "ti,am3517", "ti,omap3";
- vmmc: regulator-vmmc {
- compatible = "regulator-fixed";
- regulator-name = "vmmc";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- };
+ vmmc: regulator-vmmc {
+ compatible = "regulator-fixed";
+ regulator-name = "vmmc";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
wl12xx_vmmc2: wl12xx_vmmc2 {
compatible = "regulator-fixed";
diff --git a/arch/arm/boot/dts/omap3-devkit8000-common.dtsi b/arch/arm/boot/dts/omap3-devkit8000-common.dtsi
index 54cd37336be7..38aa1febc33f 100644
--- a/arch/arm/boot/dts/omap3-devkit8000-common.dtsi
+++ b/arch/arm/boot/dts/omap3-devkit8000-common.dtsi
@@ -15,28 +15,28 @@
leds {
compatible = "gpio-leds";
- heartbeat {
+ led-heartbeat {
label = "devkit8000::led1";
gpios = <&gpio6 26 GPIO_ACTIVE_HIGH>; /* 186 -> LED1 */
default-state = "on";
linux,default-trigger = "heartbeat";
};
- mmc {
+ led-mmc {
label = "devkit8000::led2";
gpios = <&gpio6 3 GPIO_ACTIVE_HIGH>; /* 163 -> LED2 */
default-state = "on";
linux,default-trigger = "none";
};
- usr {
+ led-usr {
label = "devkit8000::led3";
gpios = <&gpio6 4 GPIO_ACTIVE_HIGH>; /* 164 -> LED3 */
default-state = "on";
linux,default-trigger = "usr";
};
- pmu_stat {
+ led-pmu-stat {
label = "devkit8000::pmu_stat";
gpios = <&twl_gpio 19 GPIO_ACTIVE_HIGH>; /* LEDB */
};
diff --git a/arch/arm/boot/dts/omap3-echo.dts b/arch/arm/boot/dts/omap3-echo.dts
index 8f02ff5e7da6..06d2377d28ad 100644
--- a/arch/arm/boot/dts/omap3-echo.dts
+++ b/arch/arm/boot/dts/omap3-echo.dts
@@ -146,7 +146,7 @@
label = "q1";
reg = <0x32>;
clock-mode = /bits/ 8 <0>; /* LP55XX_CLOCK_AUTO */
- enable-gpio = <&gpio4 13 GPIO_ACTIVE_HIGH>; /* GPIO_109 */
+ enable-gpios = <&gpio4 13 GPIO_ACTIVE_HIGH>; /* GPIO_109 */
multi-led@0 {
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/omap3-gta04.dtsi b/arch/arm/boot/dts/omap3-gta04.dtsi
index 28a6a9345be5..87e0ab1bbe95 100644
--- a/arch/arm/boot/dts/omap3-gta04.dtsi
+++ b/arch/arm/boot/dts/omap3-gta04.dtsi
@@ -147,7 +147,7 @@
pinctrl-0 = <&backlight_pins>;
};
- pwm11: dmtimer-pwm {
+ pwm11: pwm-11 {
compatible = "ti,omap-dmtimer-pwm";
ti,timers = <&timer11>;
#pwm-cells = <3>;
@@ -332,7 +332,7 @@
OMAP3_CORE1_IOPAD(0x2108, PIN_OUTPUT | MUX_MODE0) /* dss_data22.dss_data22 */
OMAP3_CORE1_IOPAD(0x210a, PIN_OUTPUT | MUX_MODE0) /* dss_data23.dss_data23 */
>;
- };
+ };
gps_pins: pinmux_gps_pins {
pinctrl-single,pins = <
@@ -853,8 +853,8 @@
};
&hdqw1w {
- pinctrl-names = "default";
- pinctrl-0 = <&hdq_pins>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hdq_pins>;
};
/* image signal processor within OMAP3 SoC */
diff --git a/arch/arm/boot/dts/omap3-ldp.dts b/arch/arm/boot/dts/omap3-ldp.dts
index 36fc8805e0c1..85f33bbb566f 100644
--- a/arch/arm/boot/dts/omap3-ldp.dts
+++ b/arch/arm/boot/dts/omap3-ldp.dts
@@ -301,5 +301,5 @@
&vaux1 {
/* Needed for ads7846 */
- regulator-name = "vcc";
+ regulator-name = "vcc";
};
diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts
index dd7971556449..6ba2e8f81973 100644
--- a/arch/arm/boot/dts/omap3-n900.dts
+++ b/arch/arm/boot/dts/omap3-n900.dts
@@ -49,7 +49,7 @@
leds {
compatible = "gpio-leds";
- heartbeat {
+ led-heartbeat {
label = "debug::sleep";
gpios = <&gpio6 2 GPIO_ACTIVE_HIGH>; /* 162 */
linux,default-trigger = "default-on";
@@ -156,7 +156,7 @@
io-channel-names = "temp", "bsi", "vbat";
};
- pwm9: dmtimer-pwm {
+ pwm9: pwm-9 {
compatible = "ti,omap-dmtimer-pwm";
#pwm-cells = <3>;
ti,timers = <&timer9>;
@@ -236,27 +236,27 @@
pinctrl-single,pins = <
/* address lines */
- OMAP3_CORE1_IOPAD(0x207a, PIN_OUTPUT | MUX_MODE0) /* gpmc_a1.gpmc_a1 */
- OMAP3_CORE1_IOPAD(0x207c, PIN_OUTPUT | MUX_MODE0) /* gpmc_a2.gpmc_a2 */
- OMAP3_CORE1_IOPAD(0x207e, PIN_OUTPUT | MUX_MODE0) /* gpmc_a3.gpmc_a3 */
+ OMAP3_CORE1_IOPAD(0x207a, PIN_OUTPUT | MUX_MODE0) /* gpmc_a1.gpmc_a1 */
+ OMAP3_CORE1_IOPAD(0x207c, PIN_OUTPUT | MUX_MODE0) /* gpmc_a2.gpmc_a2 */
+ OMAP3_CORE1_IOPAD(0x207e, PIN_OUTPUT | MUX_MODE0) /* gpmc_a3.gpmc_a3 */
/* data lines, gpmc_d0..d7 not muxable according to TRM */
- OMAP3_CORE1_IOPAD(0x209e, PIN_INPUT | MUX_MODE0) /* gpmc_d8.gpmc_d8 */
- OMAP3_CORE1_IOPAD(0x20a0, PIN_INPUT | MUX_MODE0) /* gpmc_d9.gpmc_d9 */
- OMAP3_CORE1_IOPAD(0x20a2, PIN_INPUT | MUX_MODE0) /* gpmc_d10.gpmc_d10 */
- OMAP3_CORE1_IOPAD(0x20a4, PIN_INPUT | MUX_MODE0) /* gpmc_d11.gpmc_d11 */
- OMAP3_CORE1_IOPAD(0x20a6, PIN_INPUT | MUX_MODE0) /* gpmc_d12.gpmc_d12 */
- OMAP3_CORE1_IOPAD(0x20a8, PIN_INPUT | MUX_MODE0) /* gpmc_d13.gpmc_d13 */
- OMAP3_CORE1_IOPAD(0x20aa, PIN_INPUT | MUX_MODE0) /* gpmc_d14.gpmc_d14 */
- OMAP3_CORE1_IOPAD(0x20ac, PIN_INPUT | MUX_MODE0) /* gpmc_d15.gpmc_d15 */
+ OMAP3_CORE1_IOPAD(0x209e, PIN_INPUT | MUX_MODE0) /* gpmc_d8.gpmc_d8 */
+ OMAP3_CORE1_IOPAD(0x20a0, PIN_INPUT | MUX_MODE0) /* gpmc_d9.gpmc_d9 */
+ OMAP3_CORE1_IOPAD(0x20a2, PIN_INPUT | MUX_MODE0) /* gpmc_d10.gpmc_d10 */
+ OMAP3_CORE1_IOPAD(0x20a4, PIN_INPUT | MUX_MODE0) /* gpmc_d11.gpmc_d11 */
+ OMAP3_CORE1_IOPAD(0x20a6, PIN_INPUT | MUX_MODE0) /* gpmc_d12.gpmc_d12 */
+ OMAP3_CORE1_IOPAD(0x20a8, PIN_INPUT | MUX_MODE0) /* gpmc_d13.gpmc_d13 */
+ OMAP3_CORE1_IOPAD(0x20aa, PIN_INPUT | MUX_MODE0) /* gpmc_d14.gpmc_d14 */
+ OMAP3_CORE1_IOPAD(0x20ac, PIN_INPUT | MUX_MODE0) /* gpmc_d15.gpmc_d15 */
/*
* gpmc_ncs0, gpmc_nadv_ale, gpmc_noe, gpmc_nwe, gpmc_wait0 not muxable
* according to TRM. OneNAND seems to require PIN_INPUT on clock.
*/
- OMAP3_CORE1_IOPAD(0x20b0, PIN_OUTPUT | MUX_MODE0) /* gpmc_ncs1.gpmc_ncs1 */
- OMAP3_CORE1_IOPAD(0x20be, PIN_INPUT | MUX_MODE0) /* gpmc_clk.gpmc_clk */
- >;
+ OMAP3_CORE1_IOPAD(0x20b0, PIN_OUTPUT | MUX_MODE0) /* gpmc_ncs1.gpmc_ncs1 */
+ OMAP3_CORE1_IOPAD(0x20be, PIN_INPUT | MUX_MODE0) /* gpmc_clk.gpmc_clk */
+ >;
};
i2c1_pins: pinmux_i2c1_pins {
@@ -738,12 +738,12 @@
si4713: si4713@63 {
compatible = "silabs,si4713";
- reg = <0x63>;
+ reg = <0x63>;
- interrupts-extended = <&gpio2 21 IRQ_TYPE_EDGE_FALLING>; /* 53 */
- reset-gpios = <&gpio6 3 GPIO_ACTIVE_HIGH>; /* 163 */
- vio-supply = <&vio>;
- vdd-supply = <&vaux1>;
+ interrupts-extended = <&gpio2 21 IRQ_TYPE_EDGE_FALLING>; /* 53 */
+ reset-gpios = <&gpio6 3 GPIO_ACTIVE_HIGH>; /* 163 */
+ vio-supply = <&vio>;
+ vdd-supply = <&vaux1>;
};
bq24150a: bq24150a@6b {
diff --git a/arch/arm/boot/dts/omap3-overo-alto35-common.dtsi b/arch/arm/boot/dts/omap3-overo-alto35-common.dtsi
index bb932913c9e3..a6dbbba799b2 100644
--- a/arch/arm/boot/dts/omap3-overo-alto35-common.dtsi
+++ b/arch/arm/boot/dts/omap3-overo-alto35-common.dtsi
@@ -17,19 +17,19 @@
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&led_pins>;
- gpio148 {
+ led-gpio148 {
label = "overo:red:gpio148";
gpios = <&gpio5 20 GPIO_ACTIVE_HIGH>; /* gpio 148 */
};
- gpio150 {
+ led-gpio150 {
label = "overo:yellow:gpio150";
gpios = <&gpio5 22 GPIO_ACTIVE_HIGH>; /* gpio 150 */
};
- gpio151 {
+ led-gpio151 {
label = "overo:blue:gpio151";
gpios = <&gpio5 23 GPIO_ACTIVE_HIGH>; /* gpio 151 */
};
- gpio170 {
+ led-gpio170 {
label = "overo:green:gpio170";
gpios = <&gpio6 10 GPIO_ACTIVE_HIGH>; /* gpio 170 */
};
diff --git a/arch/arm/boot/dts/omap3-overo-chestnut43-common.dtsi b/arch/arm/boot/dts/omap3-overo-chestnut43-common.dtsi
index 2d2c61d7aa86..0d0e62c00916 100644
--- a/arch/arm/boot/dts/omap3-overo-chestnut43-common.dtsi
+++ b/arch/arm/boot/dts/omap3-overo-chestnut43-common.dtsi
@@ -17,12 +17,12 @@
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&led_pins>;
- heartbeat {
+ led-heartbeat {
label = "overo:red:gpio21";
gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; /* gpio_21 */
linux,default-trigger = "heartbeat";
};
- gpio22 {
+ led-gpio22 {
label = "overo:blue:gpio22";
gpios = <&gpio1 22 GPIO_ACTIVE_LOW>; /* gpio_22 */
};
diff --git a/arch/arm/boot/dts/omap3-overo-gallop43-common.dtsi b/arch/arm/boot/dts/omap3-overo-gallop43-common.dtsi
index 155aec121400..5f6721326f86 100644
--- a/arch/arm/boot/dts/omap3-overo-gallop43-common.dtsi
+++ b/arch/arm/boot/dts/omap3-overo-gallop43-common.dtsi
@@ -17,12 +17,12 @@
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&led_pins>;
- heartbeat {
+ led-heartbeat {
label = "overo:red:gpio21";
gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; /* gpio_21 */
linux,default-trigger = "heartbeat";
};
- gpio22 {
+ led-gpio22 {
label = "overo:blue:gpio22";
gpios = <&gpio1 22 GPIO_ACTIVE_LOW>; /* gpio_22 */
};
diff --git a/arch/arm/boot/dts/omap3-overo-palo35-common.dtsi b/arch/arm/boot/dts/omap3-overo-palo35-common.dtsi
index 82a04466747a..4b66f622ac13 100644
--- a/arch/arm/boot/dts/omap3-overo-palo35-common.dtsi
+++ b/arch/arm/boot/dts/omap3-overo-palo35-common.dtsi
@@ -17,12 +17,12 @@
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&led_pins>;
- heartbeat {
+ led-heartbeat {
label = "overo:red:gpio21";
gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; /* gpio_21 */
linux,default-trigger = "heartbeat";
};
- gpio22 {
+ led-gpio22 {
label = "overo:blue:gpio22";
gpios = <&gpio1 22 GPIO_ACTIVE_LOW>; /* gpio_22 */
};
diff --git a/arch/arm/boot/dts/omap3-overo-palo43-common.dtsi b/arch/arm/boot/dts/omap3-overo-palo43-common.dtsi
index 453a55324fa1..a8f163a899f0 100644
--- a/arch/arm/boot/dts/omap3-overo-palo43-common.dtsi
+++ b/arch/arm/boot/dts/omap3-overo-palo43-common.dtsi
@@ -17,12 +17,12 @@
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&led_pins>;
- heartbeat {
+ led-heartbeat {
label = "overo:red:gpio21";
gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; /* gpio_21 */
linux,default-trigger = "heartbeat";
};
- gpio22 {
+ led-gpio22 {
label = "overo:blue:gpio22";
gpios = <&gpio1 22 GPIO_ACTIVE_LOW>; /* gpio_22 */
};
diff --git a/arch/arm/boot/dts/omap3-overo-summit-common.dtsi b/arch/arm/boot/dts/omap3-overo-summit-common.dtsi
index df7450f17ffd..ec03ca17e98b 100644
--- a/arch/arm/boot/dts/omap3-overo-summit-common.dtsi
+++ b/arch/arm/boot/dts/omap3-overo-summit-common.dtsi
@@ -15,7 +15,7 @@
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&led_pins>;
- heartbeat {
+ led-heartbeat {
label = "overo:red:gpio21";
gpios = <&gpio1 21 GPIO_ACTIVE_LOW>; /* gpio_21 */
linux,default-trigger = "heartbeat";
diff --git a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi
index 9bf4b88a4b50..5432e4e16ab5 100644
--- a/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi
+++ b/arch/arm/boot/dts/omap3-overo-tobi-common.dtsi
@@ -13,7 +13,7 @@
/ {
leds {
compatible = "gpio-leds";
- heartbeat {
+ led-heartbeat {
label = "overo:red:gpio21";
gpios = <&gpio1 21 GPIO_ACTIVE_LOW>;
linux,default-trigger = "heartbeat";
diff --git a/arch/arm/boot/dts/omap3-zoom3.dts b/arch/arm/boot/dts/omap3-zoom3.dts
index 0482676d1830..ce58b1f208e8 100644
--- a/arch/arm/boot/dts/omap3-zoom3.dts
+++ b/arch/arm/boot/dts/omap3-zoom3.dts
@@ -23,9 +23,9 @@
};
vddvario: regulator-vddvario {
- compatible = "regulator-fixed";
- regulator-name = "vddvario";
- regulator-always-on;
+ compatible = "regulator-fixed";
+ regulator-name = "vddvario";
+ regulator-always-on;
};
vdd33a: regulator-vdd33a {
@@ -84,28 +84,28 @@
uart1_pins: pinmux_uart1_pins {
pinctrl-single,pins = <
- OMAP3_CORE1_IOPAD(0x2180, PIN_INPUT | MUX_MODE0) /* uart1_cts.uart1_cts */
- OMAP3_CORE1_IOPAD(0x217e, PIN_OUTPUT | MUX_MODE0) /* uart1_rts.uart1_rts */
- OMAP3_CORE1_IOPAD(0x2182, WAKEUP_EN | PIN_INPUT | MUX_MODE0) /* uart1_rx.uart1_rx */
- OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE0) /* uart1_tx.uart1_tx */
+ OMAP3_CORE1_IOPAD(0x2180, PIN_INPUT | MUX_MODE0) /* uart1_cts.uart1_cts */
+ OMAP3_CORE1_IOPAD(0x217e, PIN_OUTPUT | MUX_MODE0) /* uart1_rts.uart1_rts */
+ OMAP3_CORE1_IOPAD(0x2182, WAKEUP_EN | PIN_INPUT | MUX_MODE0) /* uart1_rx.uart1_rx */
+ OMAP3_CORE1_IOPAD(0x217c, PIN_OUTPUT | MUX_MODE0) /* uart1_tx.uart1_tx */
>;
};
uart2_pins: pinmux_uart2_pins {
pinctrl-single,pins = <
- OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT_PULLUP | MUX_MODE0) /* uart2_cts.uart2_cts */
- OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE0) /* uart2_rts.uart2_rts */
- OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0) /* uart2_rx.uart2_rx */
- OMAP3_CORE1_IOPAD(0x2178, PIN_OUTPUT | MUX_MODE0) /* uart2_tx.uart2_tx */
+ OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT_PULLUP | MUX_MODE0) /* uart2_cts.uart2_cts */
+ OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE0) /* uart2_rts.uart2_rts */
+ OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0) /* uart2_rx.uart2_rx */
+ OMAP3_CORE1_IOPAD(0x2178, PIN_OUTPUT | MUX_MODE0) /* uart2_tx.uart2_tx */
>;
};
uart3_pins: pinmux_uart3_pins {
pinctrl-single,pins = <
- OMAP3_CORE1_IOPAD(0x219a, PIN_INPUT_PULLDOWN | MUX_MODE0) /* uart3_cts_rctx.uart3_cts_rctx */
- OMAP3_CORE1_IOPAD(0x219c, PIN_OUTPUT | MUX_MODE0) /* uart3_rts_sd.uart3_rts_sd */
- OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */
- OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx */
+ OMAP3_CORE1_IOPAD(0x219a, PIN_INPUT_PULLDOWN | MUX_MODE0) /* uart3_cts_rctx.uart3_cts_rctx */
+ OMAP3_CORE1_IOPAD(0x219c, PIN_OUTPUT | MUX_MODE0) /* uart3_rts_sd.uart3_rts_sd */
+ OMAP3_CORE1_IOPAD(0x219e, PIN_INPUT | MUX_MODE0) /* uart3_rx_irrx.uart3_rx_irrx */
+ OMAP3_CORE1_IOPAD(0x21a0, PIN_OUTPUT | MUX_MODE0) /* uart3_tx_irtx.uart3_tx_irtx */
>;
};
@@ -205,22 +205,22 @@
};
&uart1 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart1_pins>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_pins>;
};
&uart2 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart2_pins>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2_pins>;
};
&uart3 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart3_pins>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart3_pins>;
};
&uart4 {
- status = "disabled";
+ status = "disabled";
};
&usb_otg_hs {
diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi
index 825075ff0e34..92cd4c99dae7 100644
--- a/arch/arm/boot/dts/omap3.dtsi
+++ b/arch/arm/boot/dts/omap3.dtsi
@@ -893,15 +893,37 @@
#gpio-cells = <2>;
};
- usb_otg_hs: usb_otg_hs@480ab000 {
- compatible = "ti,omap3-musb";
- reg = <0x480ab000 0x1000>;
- interrupts = <92>, <93>;
- interrupt-names = "mc", "dma";
- ti,hwmods = "usb_otg_hs";
- multipoint = <1>;
- num-eps = <16>;
- ram-bits = <12>;
+ usb_otg_target: target-module@480ab000 {
+ compatible = "ti,sysc-omap2", "ti,sysc";
+ reg = <0x480ab400 0x4>,
+ <0x480ab404 0x4>,
+ <0x480ab408 0x4>;
+ reg-names = "rev", "sysc", "syss";
+ ti,sysc-mask = <(SYSC_OMAP2_ENAWAKEUP |
+ SYSC_OMAP2_SOFTRESET |
+ SYSC_OMAP2_AUTOIDLE)>;
+ ti,sysc-midle = <SYSC_IDLE_FORCE>,
+ <SYSC_IDLE_NO>,
+ <SYSC_IDLE_SMART>;
+ ti,sysc-sidle = <SYSC_IDLE_FORCE>,
+ <SYSC_IDLE_NO>,
+ <SYSC_IDLE_SMART>;
+ ti,syss-mask = <1>;
+ /* Clock defined in the SoC specific dtsi file */
+ clock-names = "fck";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x480ab000 0x1000>;
+
+ usb_otg_hs: usb@0 {
+ compatible = "ti,omap3-musb";
+ reg = <0 0x1000>;
+ interrupts = <92>, <93>;
+ interrupt-names = "mc", "dma";
+ multipoint = <1>;
+ num-eps = <16>;
+ ram-bits = <12>;
+ };
};
dss: dss@48050000 {
diff --git a/arch/arm/boot/dts/omap34xx.dtsi b/arch/arm/boot/dts/omap34xx.dtsi
index 2eb73ae7ef3e..9dbf62797f0f 100644
--- a/arch/arm/boot/dts/omap34xx.dtsi
+++ b/arch/arm/boot/dts/omap34xx.dtsi
@@ -189,6 +189,10 @@
"ssi_ick";
};
+&usb_otg_target {
+ clocks = <&hsotgusb_ick_3430es2>;
+};
+
/include/ "omap34xx-omap36xx-clocks.dtsi"
/include/ "omap36xx-omap3430es2plus-clocks.dtsi"
/include/ "omap36xx-am35xx-omap3430es2plus-clocks.dtsi"
diff --git a/arch/arm/boot/dts/omap36xx.dtsi b/arch/arm/boot/dts/omap36xx.dtsi
index 32ac7924a130..fff9c3d34193 100644
--- a/arch/arm/boot/dts/omap36xx.dtsi
+++ b/arch/arm/boot/dts/omap36xx.dtsi
@@ -240,6 +240,10 @@
"ssi_ick";
};
+&usb_otg_target {
+ clocks = <&hsotgusb_ick_3430es2>;
+};
+
/include/ "omap34xx-omap36xx-clocks.dtsi"
/include/ "omap36xx-omap3430es2plus-clocks.dtsi"
/include/ "omap36xx-am35xx-omap3430es2plus-clocks.dtsi"
diff --git a/arch/arm/boot/dts/omap4-cpu-thermal.dtsi b/arch/arm/boot/dts/omap4-cpu-thermal.dtsi
index 4d7eeb133dad..801b4f10350c 100644
--- a/arch/arm/boot/dts/omap4-cpu-thermal.dtsi
+++ b/arch/arm/boot/dts/omap4-cpu-thermal.dtsi
@@ -13,20 +13,20 @@ cpu_thermal: cpu_thermal {
polling-delay = <1000>; /* milliseconds */
/* sensor ID */
- thermal-sensors = <&bandgap 0>;
+ thermal-sensors = <&bandgap 0>;
cpu_trips: trips {
- cpu_alert0: cpu_alert {
- temperature = <100000>; /* millicelsius */
- hysteresis = <2000>; /* millicelsius */
- type = "passive";
- };
- cpu_crit: cpu_crit {
- temperature = <125000>; /* millicelsius */
- hysteresis = <2000>; /* millicelsius */
- type = "critical";
- };
- };
+ cpu_alert0: cpu_alert {
+ temperature = <100000>; /* millicelsius */
+ hysteresis = <2000>; /* millicelsius */
+ type = "passive";
+ };
+ cpu_crit: cpu_crit {
+ temperature = <125000>; /* millicelsius */
+ hysteresis = <2000>; /* millicelsius */
+ type = "critical";
+ };
+ };
cpu_cooling_maps: cooling-maps {
map0 {
diff --git a/arch/arm/boot/dts/omap4-panda-common.dtsi b/arch/arm/boot/dts/omap4-panda-common.dtsi
index 518652a599bd..0269424350aa 100644
--- a/arch/arm/boot/dts/omap4-panda-common.dtsi
+++ b/arch/arm/boot/dts/omap4-panda-common.dtsi
@@ -49,13 +49,13 @@
&led_wkgpio_pins
>;
- heartbeat {
+ led-heartbeat {
label = "pandaboard::status1";
gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
};
- mmc {
+ led-mmc {
label = "pandaboard::status2";
gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "mmc0";
diff --git a/arch/arm/boot/dts/omap4-panda-es.dts b/arch/arm/boot/dts/omap4-panda-es.dts
index 7c6886cd738f..7631029e4d7a 100644
--- a/arch/arm/boot/dts/omap4-panda-es.dts
+++ b/arch/arm/boot/dts/omap4-panda-es.dts
@@ -79,10 +79,10 @@
&led_wkgpio_pins
>;
- heartbeat {
+ led-heartbeat {
gpios = <&gpio4 14 GPIO_ACTIVE_HIGH>;
};
- mmc {
+ led-mmc {
gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
};
};
diff --git a/arch/arm/boot/dts/omap5-cm-t54.dts b/arch/arm/boot/dts/omap5-cm-t54.dts
index ca759b7b8a58..2d87b9fc230e 100644
--- a/arch/arm/boot/dts/omap5-cm-t54.dts
+++ b/arch/arm/boot/dts/omap5-cm-t54.dts
@@ -84,36 +84,36 @@
};
lcd0: display {
- compatible = "startek,startek-kd050c", "panel-dpi";
- label = "lcd";
-
- pinctrl-names = "default";
- pinctrl-0 = <&lcd_pins>;
-
- enable-gpios = <&gpio8 3 GPIO_ACTIVE_HIGH>;
-
- panel-timing {
- clock-frequency = <33000000>;
- hactive = <800>;
- vactive = <480>;
- hfront-porch = <40>;
- hback-porch = <40>;
- hsync-len = <43>;
- vback-porch = <29>;
- vfront-porch = <13>;
- vsync-len = <3>;
- hsync-active = <0>;
- vsync-active = <0>;
- de-active = <1>;
- pixelclk-active = <1>;
- };
-
- port {
- lcd_in: endpoint {
- remote-endpoint = <&dpi_lcd_out>;
- };
- };
- };
+ compatible = "startek,startek-kd050c", "panel-dpi";
+ label = "lcd";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_pins>;
+
+ enable-gpios = <&gpio8 3 GPIO_ACTIVE_HIGH>;
+
+ panel-timing {
+ clock-frequency = <33000000>;
+ hactive = <800>;
+ vactive = <480>;
+ hfront-porch = <40>;
+ hback-porch = <40>;
+ hsync-len = <43>;
+ vback-porch = <29>;
+ vfront-porch = <13>;
+ vsync-len = <3>;
+ hsync-active = <0>;
+ vsync-active = <0>;
+ de-active = <1>;
+ pixelclk-active = <1>;
+ };
+
+ port {
+ lcd_in: endpoint {
+ remote-endpoint = <&dpi_lcd_out>;
+ };
+ };
+ };
hdmi0: connector0 {
compatible = "hdmi-connector";
@@ -644,8 +644,8 @@
};
&usb3 {
- extcon = <&extcon_usb3>;
- vbus-supply = <&smps10_out1_reg>;
+ extcon = <&extcon_usb3>;
+ vbus-supply = <&smps10_out1_reg>;
};
&cpu0 {
diff --git a/arch/arm/boot/dts/pxa168.dtsi b/arch/arm/boot/dts/pxa168.dtsi
index 4fe7735c7c58..16212b912b94 100644
--- a/arch/arm/boot/dts/pxa168.dtsi
+++ b/arch/arm/boot/dts/pxa168.dtsi
@@ -53,6 +53,8 @@
compatible = "mrvl,mmp-timer";
reg = <0xd4014000 0x100>;
interrupts = <13>;
+ clocks = <&soc_clocks PXA168_CLK_TIMER>;
+ resets = <&soc_clocks PXA168_CLK_TIMER>;
};
uart1: serial@d4017000 {
diff --git a/arch/arm/boot/dts/qcom-apq8026-asus-sparrow.dts b/arch/arm/boot/dts/qcom-apq8026-asus-sparrow.dts
index 215613c65250..7a80e1c9f126 100644
--- a/arch/arm/boot/dts/qcom-apq8026-asus-sparrow.dts
+++ b/arch/arm/boot/dts/qcom-apq8026-asus-sparrow.dts
@@ -87,7 +87,7 @@
};
&rpm_requests {
- pm8226-regulators {
+ regulators {
compatible = "qcom,rpm-pm8226-regulators";
pm8226_s3: s3 {
diff --git a/arch/arm/boot/dts/qcom-apq8026-huawei-sturgeon.dts b/arch/arm/boot/dts/qcom-apq8026-huawei-sturgeon.dts
new file mode 100644
index 000000000000..d64096028ab1
--- /dev/null
+++ b/arch/arm/boot/dts/qcom-apq8026-huawei-sturgeon.dts
@@ -0,0 +1,376 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2022, Luca Weiss <luca@z3ntu.xyz>
+ */
+
+/dts-v1/;
+
+#include "qcom-msm8226.dtsi"
+#include "qcom-pm8226.dtsi"
+
+/delete-node/ &adsp_region;
+
+/ {
+ model = "Huawei Watch";
+ compatible = "huawei,sturgeon", "qcom,apq8026";
+ chassis-type = "watch";
+ qcom,msm-id = <199 0x20000>;
+ qcom,board-id = <8 4>;
+
+ reserved-memory {
+ sbl_region: sbl@2f00000 {
+ reg = <0x02f00000 0x100000>;
+ no-map;
+ };
+
+ external_image_region: external-image@3100000 {
+ reg = <0x3100000 0x200000>;
+ no-map;
+ };
+
+ peripheral_region: peripheral@3300000 {
+ reg = <0x3300000 0x600000>;
+ no-map;
+ };
+
+ adsp_region: adsp@3900000 {
+ reg = <0x3900000 0x1400000>;
+ no-map;
+ };
+
+ modem_region: modem@4d00000 {
+ reg = <0x4d00000 0x1b00000>;
+ no-map;
+ };
+
+ modem_efs_region: modem-efs@7f00000 {
+ reg = <0x7f00000 0x100000>;
+ no-map;
+ };
+ };
+
+ vreg_wlan: wlan-regulator {
+ compatible = "regulator-fixed";
+
+ regulator-name = "wl-reg";
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+
+ gpio = <&tlmm 110 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&wlan_regulator_default_state>;
+ };
+};
+
+&adsp {
+ status = "okay";
+};
+
+&blsp1_i2c5 {
+ clock-frequency = <384000>;
+
+ status = "okay";
+
+ touchscreen@20 {
+ compatible = "syna,rmi4-i2c";
+ reg = <0x20>;
+
+ interrupts-extended = <&tlmm 17 IRQ_TYPE_EDGE_FALLING>;
+ vdd-supply = <&pm8226_l19>;
+ vio-supply = <&pm8226_lvs1>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&touch_default_state>;
+
+ syna,startup-delay-ms = <160>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rmi4-f01@1 {
+ reg = <0x1>;
+ syna,nosleep-mode = <1>;
+ };
+
+ rmi4-f12@12 {
+ reg = <0x12>;
+ syna,sensor-type = <1>;
+ };
+ };
+};
+
+&blsp1_uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&blsp1_uart4_default_state>;
+
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm43430a0-bt";
+ max-speed = <3000000>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&bluetooth_default_state>;
+
+ host-wakeup-gpios = <&tlmm 64 GPIO_ACTIVE_HIGH>;
+ device-wakeup-gpios = <&tlmm 63 GPIO_ACTIVE_HIGH>;
+ shutdown-gpios = <&tlmm 67 GPIO_ACTIVE_HIGH>;
+ };
+};
+
+&rpm_requests {
+ regulators {
+ compatible = "qcom,rpm-pm8226-regulators";
+
+ pm8226_s3: s3 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ pm8226_s4: s4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2200000>;
+ };
+
+ pm8226_s5: s5 {
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1150000>;
+ };
+
+ pm8226_l1: l1 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ pm8226_l2: l2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8226_l3: l3 {
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1337500>;
+ };
+
+ pm8226_l4: l4 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8226_l5: l5 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8226_l6: l6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8226_l7: l7 {
+ regulator-min-microvolt = <1850000>;
+ regulator-max-microvolt = <1850000>;
+ };
+
+ pm8226_l8: l8 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8226_l9: l9 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ };
+
+ pm8226_l10: l10 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8226_l12: l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8226_l14: l14 {
+ regulator-min-microvolt = <2750000>;
+ regulator-max-microvolt = <2750000>;
+ };
+
+ pm8226_l15: l15 {
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ pm8226_l16: l16 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3350000>;
+ };
+
+ pm8226_l17: l17 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_l18: l18 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_l19: l19 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ };
+
+ pm8226_l20: l20 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ };
+
+ pm8226_l21: l21 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_l22: l22 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_l23: l23 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_l24: l24 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1350000>;
+ };
+
+ pm8226_l25: l25 {
+ regulator-min-microvolt = <1775000>;
+ regulator-max-microvolt = <2125000>;
+ };
+
+ pm8226_l26: l26 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ pm8226_l27: l27 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ };
+
+ pm8226_l28: l28 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_lvs1: lvs1 {};
+ };
+};
+
+&sdhc_1 {
+ vmmc-supply = <&pm8226_l17>;
+ vqmmc-supply = <&pm8226_l6>;
+
+ bus-width = <8>;
+ non-removable;
+
+ status = "okay";
+};
+
+&sdhc_3 {
+ max-frequency = <100000000>;
+ non-removable;
+
+ vmmc-supply = <&vreg_wlan>;
+ vqmmc-supply = <&pm8226_l6>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "okay";
+
+ wifi@1 {
+ compatible = "brcm,bcm43430a0-fmac", "brcm,bcm4329-fmac";
+ reg = <1>;
+
+ interrupts-extended = <&tlmm 66 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-names = "host-wake";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&wlan_hostwake_default_state>;
+ };
+};
+
+&smbb {
+ qcom,fast-charge-safe-voltage = <4370000>;
+ qcom,fast-charge-high-threshold-voltage = <4350000>;
+ qcom,minimum-input-voltage = <4350000>;
+ qcom,fast-charge-current-limit = <300000>;
+ qcom,fast-charge-safe-current = <600000>;
+ qcom,auto-recharge-threshold-voltage = <4240000>;
+};
+
+&tlmm {
+ blsp1_uart4_default_state: blsp1-uart4-default-state {
+ pins = "gpio12", "gpio13", "gpio14", "gpio15";
+ function = "blsp_uart4";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ bluetooth_default_state: bluetooth-default-state {
+ pins = "gpio63", "gpio64";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ touch_default_state: touch-default-state {
+ irq-pins {
+ pins = "gpio17";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+
+ reset-pins {
+ pins = "gpio16";
+ function = "gpio";
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+ };
+
+ wlan_hostwake_default_state: wlan-hostwake-default-state {
+ pins = "gpio66";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ input-enable;
+ };
+
+ wlan_regulator_default_state: wlan-regulator-default-state {
+ pins = "gpio110";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+};
+
+&usb {
+ extcon = <&smbb>;
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usb_hs_phy {
+ extcon = <&smbb>;
+ v1p8-supply = <&pm8226_l10>;
+ v3p3-supply = <&pm8226_l20>;
+};
diff --git a/arch/arm/boot/dts/qcom-apq8026-lg-lenok.dts b/arch/arm/boot/dts/qcom-apq8026-lg-lenok.dts
index 193569f0ca5f..de2fb1c01b6e 100644
--- a/arch/arm/boot/dts/qcom-apq8026-lg-lenok.dts
+++ b/arch/arm/boot/dts/qcom-apq8026-lg-lenok.dts
@@ -13,6 +13,7 @@
/ {
model = "LG G Watch R";
compatible = "lg,lenok", "qcom,apq8026";
+ chassis-type = "watch";
qcom,board-id = <132 0x0a>;
qcom,msm-id = <199 0x20000>;
@@ -115,7 +116,7 @@
};
&rpm_requests {
- pm8226-regulators {
+ regulators {
compatible = "qcom,rpm-pm8226-regulators";
pm8226_s3: s3 {
@@ -299,8 +300,8 @@
input-enable;
};
- touch_pins: touch {
- irq {
+ touch_pins: touch-state {
+ irq-pins {
pins = "gpio17";
function = "gpio";
@@ -309,7 +310,7 @@
input-enable;
};
- reset {
+ reset-pins {
pins = "gpio16";
function = "gpio";
diff --git a/arch/arm/boot/dts/qcom-apq8026-samsung-matisse-wifi.dts b/arch/arm/boot/dts/qcom-apq8026-samsung-matisse-wifi.dts
new file mode 100644
index 000000000000..1c52337af560
--- /dev/null
+++ b/arch/arm/boot/dts/qcom-apq8026-samsung-matisse-wifi.dts
@@ -0,0 +1,453 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2022, Matti Lehtimäki <matti.lehtimaki@gmail.com>
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include "qcom-msm8226.dtsi"
+#include "qcom-pm8226.dtsi"
+
+/ {
+ model = "Samsung Galaxy Tab 4 10.1";
+ compatible = "samsung,matisse-wifi", "qcom,apq8026";
+ chassis-type = "tablet";
+
+ aliases {
+ mmc0 = &sdhc_1; /* SDC1 eMMC slot */
+ mmc1 = &sdhc_2; /* SDC2 SD card slot */
+ display0 = &framebuffer0;
+ };
+
+ chosen {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ stdout-path = "display0";
+
+ framebuffer0: framebuffer@3200000 {
+ compatible = "simple-framebuffer";
+ reg = <0x03200000 0x800000>;
+ width = <1280>;
+ height = <800>;
+ stride = <(1280 * 3)>;
+ format = "r8g8b8";
+ };
+ };
+
+ gpio-hall-sensor {
+ compatible = "gpio-keys";
+
+ event-hall-sensor {
+ label = "Hall Effect Sensor";
+ gpios = <&tlmm 110 GPIO_ACTIVE_HIGH>;
+ interrupts = <&tlmm 110 IRQ_TYPE_EDGE_FALLING>;
+ linux,input-type = <EV_SW>;
+ linux,code = <SW_LID>;
+ debounce-interval = <15>;
+ wakeup-source;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ autorepeat;
+
+ key-home {
+ label = "Home";
+ gpios = <&tlmm 108 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_HOMEPAGE>;
+ debounce-interval = <15>;
+ };
+
+ key-volume-down {
+ label = "Volume Down";
+ gpios = <&tlmm 107 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEDOWN>;
+ debounce-interval = <15>;
+ };
+
+ key-volume-up {
+ label = "Volume Up";
+ gpios = <&tlmm 106 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ debounce-interval = <15>;
+ };
+ };
+
+ reg_tsp_1p8v: regulator-tsp-1p8v {
+ compatible = "regulator-fixed";
+ regulator-name = "tsp_1p8v";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ gpio = <&tlmm 31 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&tsp_en_default_state>;
+ };
+
+ reg_tsp_3p3v: regulator-tsp-3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "tsp_3p3v";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&tlmm 73 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&tsp_en1_default_state>;
+ };
+
+ reserved-memory {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ framebuffer@3200000 {
+ reg = <0x03200000 0x800000>;
+ no-map;
+ };
+
+ mpss@8400000 {
+ reg = <0x08400000 0x1f00000>;
+ no-map;
+ };
+
+ mba@a300000 {
+ reg = <0x0a300000 0x100000>;
+ no-map;
+ };
+
+ reserved@cb00000 {
+ reg = <0x0cb00000 0x700000>;
+ no-map;
+ };
+
+ wcnss@d200000 {
+ reg = <0x0d200000 0x700000>;
+ no-map;
+ };
+
+ adsp@d900000 {
+ reg = <0x0d900000 0x1800000>;
+ no-map;
+ };
+
+ venus@f100000 {
+ reg = <0x0f100000 0x500000>;
+ no-map;
+ };
+
+ /delete-node/ smem@3000000;
+ smem_region: smem@fa00000 {
+ reg = <0x0fa00000 0x100000>;
+ no-map;
+ };
+
+ reserved@fb00000 {
+ reg = <0x0fb00000 0x260000>;
+ no-map;
+ };
+
+ rfsa@fd60000 {
+ reg = <0x0fd60000 0x20000>;
+ no-map;
+ };
+
+ rmtfs@fd80000 {
+ compatible = "qcom,rmtfs-mem";
+ reg = <0x0fd80000 0x180000>;
+ no-map;
+
+ qcom,client-id = <1>;
+ };
+ };
+};
+
+&blsp1_i2c2 {
+ status = "okay";
+
+ accelerometer@1d {
+ compatible = "st,lis2hh12";
+ reg = <0x1d>;
+
+ interrupt-parent = <&tlmm>;
+ interrupts = <54 IRQ_TYPE_LEVEL_HIGH>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&accel_int_default_state>;
+
+ st,drdy-int-pin = <1>;
+
+ vdd-supply = <&pm8226_l19>;
+ vddio-supply = <&pm8226_lvs1>;
+ };
+};
+
+&blsp1_i2c4 {
+ status = "okay";
+
+ muic: usb-switch@25 {
+ compatible = "siliconmitus,sm5502-muic";
+ reg = <0x25>;
+
+ interrupt-parent = <&tlmm>;
+ interrupts = <67 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&muic_int_default_state>;
+ };
+};
+
+&blsp1_i2c5 {
+ status = "okay";
+
+ touchscreen@4a {
+ compatible = "atmel,maxtouch";
+ reg = <0x4a>;
+
+ interrupt-parent = <&tlmm>;
+ interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&tsp_int_rst_default_state>;
+
+ reset-gpios = <&pm8226_gpios 6 GPIO_ACTIVE_LOW>;
+
+ vdd-supply = <&reg_tsp_1p8v>;
+ vdda-supply = <&reg_tsp_3p3v>;
+ };
+};
+
+&rpm_requests {
+ regulators {
+ compatible = "qcom,rpm-pm8226-regulators";
+
+ pm8226_s3: s3 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ pm8226_s4: s4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8226_s5: s5 {
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1150000>;
+ };
+
+ pm8226_l1: l1 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ pm8226_l2: l2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8226_l3: l3 {
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1337500>;
+ regulator-always-on;
+ };
+
+ pm8226_l4: l4 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8226_l5: l5 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8226_l6: l6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ pm8226_l7: l7 {
+ regulator-min-microvolt = <1850000>;
+ regulator-max-microvolt = <1850000>;
+ };
+
+ pm8226_l8: l8 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ pm8226_l9: l9 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ };
+
+ pm8226_l10: l10 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8226_l12: l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8226_l14: l14 {
+ regulator-min-microvolt = <2750000>;
+ regulator-max-microvolt = <2750000>;
+ };
+
+ pm8226_l15: l15 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ pm8226_l16: l16 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3350000>;
+ };
+
+ pm8226_l17: l17 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+
+ regulator-system-load = <200000>;
+ regulator-allow-set-load;
+ regulator-always-on;
+ };
+
+ pm8226_l18: l18 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_l19: l19 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ pm8226_l20: l20 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ };
+
+ pm8226_l21: l21 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_l22: l22 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ pm8226_l23: l23 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ pm8226_l24: l24 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1350000>;
+ };
+
+ pm8226_l25: l25 {
+ regulator-min-microvolt = <1775000>;
+ regulator-max-microvolt = <2125000>;
+ };
+
+ pm8226_l26: l26 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ pm8226_l27: l27 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8226_l28: l28 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8226_lvs1: lvs1 {};
+ };
+};
+
+&sdhc_1 {
+ vmmc-supply = <&pm8226_l17>;
+ vqmmc-supply = <&pm8226_l6>;
+
+ bus-width = <8>;
+ non-removable;
+
+ status = "okay";
+};
+
+&sdhc_2 {
+ vmmc-supply = <&pm8226_l18>;
+ vqmmc-supply = <&pm8226_l21>;
+
+ bus-width = <4>;
+ cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>;
+
+ status = "okay";
+};
+
+&tlmm {
+ accel_int_default_state: accel-int-default-state {
+ pins = "gpio54";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ muic_int_default_state: muic-int-default-state {
+ pins = "gpio67";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ tsp_en_default_state: tsp-en-default-state {
+ pins = "gpio31";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ tsp_en1_default_state: tsp-en1-default-state {
+ pins = "gpio73";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ tsp_int_rst_default_state: tsp-int-rst-default-state {
+ pins = "gpio17";
+ function = "gpio";
+ drive-strength = <10>;
+ bias-pull-up;
+ };
+};
+
+&usb {
+ extcon = <&muic>, <&muic>;
+ status = "okay";
+};
+
+&usb_hs_phy {
+ extcon = <&muic>;
+ v1p8-supply = <&pm8226_l10>;
+ v3p3-supply = <&pm8226_l20>;
+};
diff --git a/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts b/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
index 573e4dc66bb0..7a4c59e04af6 100644
--- a/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
+++ b/arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
@@ -81,931 +81,899 @@
pinctrl-names = "default";
pinctrl-0 = <&dragon_cm3605_gpios>, <&dragon_cm3605_mpps>;
};
+};
- soc {
- pinctrl@800000 {
- /* eMMC pins, all 8 data lines connected */
- dragon_sdcc1_pins: sdcc1 {
- mux {
- pins = "gpio159", "gpio160", "gpio161",
- "gpio162", "gpio163", "gpio164",
- "gpio165", "gpio166", "gpio167",
- "gpio168";
- function = "sdc1";
- };
- clk {
- pins = "gpio167"; /* SDC1 CLK */
- drive-strength = <16>;
- bias-disable;
- };
- cmd {
- pins = "gpio168"; /* SDC1 CMD */
- drive-strength = <10>;
- bias-pull-up;
- };
- data {
- /* SDC1 D0 to D7 */
- pins = "gpio159", "gpio160", "gpio161", "gpio162",
- "gpio163", "gpio164", "gpio165", "gpio166";
- drive-strength = <10>;
- bias-pull-up;
- };
- };
+&ebi2 {
+ /* The EBI2 will instantiate first, then populate its children */
+ pinctrl-names = "default";
+ pinctrl-0 = <&dragon_ebi2_pins>;
+ status = "okay";
- /*
- * The SDCC3 pins are hardcoded (non-muxable) but need some pin
- * configuration.
- */
- dragon_sdcc3_pins: sdcc3 {
- clk {
- pins = "sdc3_clk";
- drive-strength = <8>;
- bias-disable;
- };
- cmd {
- pins = "sdc3_cmd";
- drive-strength = <8>;
- bias-pull-up;
- };
- data {
- pins = "sdc3_data";
- drive-strength = <8>;
- bias-pull-up;
- };
- };
+ /*
+ * An on-board SMSC LAN9221 chip for "debug ethernet",
+ * which is actually just an ordinary ethernet on the
+ * EBI2. This has a 25MHz chrystal next to it, so no
+ * clocking is needed.
+ */
+ ethernet@2,0 {
+ compatible = "smsc,lan9221", "smsc,lan9115";
+ reg = <2 0x0 0x100>;
+ /*
+ * The second interrupt is the PME interrupt
+ * for network wakeup, connected to the TLMM.
+ */
+ interrupts-extended = <&pm8058_gpio 7 IRQ_TYPE_EDGE_FALLING>,
+ <&tlmm 29 IRQ_TYPE_EDGE_RISING>;
+ reset-gpios = <&tlmm 30 GPIO_ACTIVE_LOW>;
+ vdd33a-supply = <&dragon_veth>;
+ vddvario-supply = <&dragon_vario>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&dragon_ethernet_gpios>;
+ phy-mode = "mii";
+ reg-io-width = <2>;
+ smsc,force-external-phy;
+ smsc,irq-push-pull;
+
+ /*
+ * SLOW chipselect config
+ * Delay 9 cycles (140ns@64MHz) between SMSC
+ * LAN9221 Ethernet controller reads and writes
+ * on CS2.
+ */
+ qcom,xmem-recovery-cycles = <0>;
+ qcom,xmem-write-hold-cycles = <3>;
+ qcom,xmem-write-delta-cycles = <31>;
+ qcom,xmem-read-delta-cycles = <28>;
+ qcom,xmem-write-wait-cycles = <9>;
+ qcom,xmem-read-wait-cycles = <9>;
+ };
+};
- /* Second SD card slot pins */
- dragon_sdcc5_pins: sdcc5 {
- mux {
- pins = "gpio95", "gpio96", "gpio97",
- "gpio98", "gpio99", "gpio100";
- function = "sdc5";
- };
- clk {
- pins = "gpio97"; /* SDC5 CLK */
- drive-strength = <16>;
- bias-disable;
- };
- cmd {
- pins = "gpio95"; /* SDC5 CMD */
- drive-strength = <10>;
- bias-pull-up;
- };
- data {
- /* SDC5 D0 to D3 */
- pins = "gpio96", "gpio98", "gpio99", "gpio100";
- drive-strength = <10>;
- bias-pull-up;
- };
- };
+&gsbi3 {
+ qcom,mode = <GSBI_PROT_I2C>;
+ status = "okay";
+};
- dragon_gsbi3_i2c_pins: gsbi3_i2c {
- mux {
- pins = "gpio43", "gpio44";
- function = "gsbi3";
- };
- pinconf {
- pins = "gpio43", "gpio44";
- drive-strength = <8>;
- /* These have external pull-up 2.2kOhm to 1.8V */
- bias-disable;
- };
- };
+&gsbi3_i2c {
+ pinctrl-names = "default";
+ pinctrl-0 = <&dragon_gsbi3_i2c_pins>;
+ status = "okay";
+
+ touchscreen@24 {
+ compatible = "cypress,cy8ctma340";
+ reg = <0x24>;
+ /* Certainly we can do at least 400 kHz */
+ clock-frequency = <400000>;
+ /* IRQ on GPIO61 called /CTP_INT */
+ interrupt-parent = <&tlmm>;
+ interrupts = <61 IRQ_TYPE_EDGE_FALLING>;
+ /*
+ * The I2C bus is using a PCA9306 level translator from L16A
+ * to L2B so these two voltages are needed and L16A is
+ * kind of the IO voltage, however L16Aisn't really fed to
+ * the TMA340, which relies entirely on L2B (PM8901 L2).
+ */
+ vcpin-supply = <&pm8058_l16>;
+ vdd-supply = <&pm8901_l2>;
+ /* GPIO58, called WAKE_CTP */
+ reset-gpios = <&tlmm 58 GPIO_ACTIVE_LOW>;
+ touchscreen-size-x = <480>;
+ touchscreen-size-y = <800>;
+ active-interval-ms = <0>;
+ touch-timeout-ms = <255>;
+ lowpower-interval-ms = <10>;
+ bootloader-key = /bits/ 8 <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&dragon_tma340_gpios>;
+ };
+};
- dragon_gsbi8_i2c_pins: gsbi8_i2c {
- mux {
- pins = "gpio64", "gpio65";
- function = "gsbi8";
- };
- pinconf {
- pins = "gpio64", "gpio65";
- drive-strength = <16>;
- /* These have external pull-up 2.2kOhm to 1.8V */
- bias-disable;
- };
- };
+&gsbi8 {
+ qcom,mode = <GSBI_PROT_I2C>;
+ status = "okay";
+};
- dragon_gsbi12_i2c_pins: gsbi12_i2c {
- mux {
- pins = "gpio115", "gpio116";
- function = "gsbi12";
- };
- pinconf {
- pins = "gpio115", "gpio116";
- drive-strength = <16>;
- /* These have external pull-up 4.7kOhm to 1.8V */
- bias-disable;
- };
- };
+&gsbi8_i2c {
+ pinctrl-names = "default";
+ pinctrl-0 = <&dragon_gsbi8_i2c_pins>;
+ status = "okay";
+
+ eeprom@52 {
+ /* A 16KiB Platform ID EEPROM on the CPU carrier board */
+ compatible = "atmel,24c128";
+ reg = <0x52>;
+ vcc-supply = <&pm8058_s3>;
+ pagesize = <64>;
+ };
+ wm8903: wm8903@1a {
+ /* This Woolfson Micro device has an unrouted interrupt line */
+ compatible = "wlf,wm8903";
+ reg = <0x1a>;
+
+ AVDD-supply = <&pm8058_l16>;
+ CPVDD-supply = <&pm8058_l16>;
+ DBVDD-supply = <&pm8058_s3>;
+ DCVDD-supply = <&pm8058_l0>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ micdet-cfg = <0>;
+ micdet-delay = <100>;
+ gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>;
+ };
+};
- /* Primary serial port uart 0 pins */
- dragon_gsbi12_serial_pins: gsbi12_serial {
- mux {
- pins = "gpio117", "gpio118";
- function = "gsbi12";
- };
- tx {
- pins = "gpio117";
- drive-strength = <8>;
- bias-disable;
- };
- rx {
- pins = "gpio118";
- drive-strength = <2>;
- bias-pull-up;
- };
- };
+&gsbi12 {
+ qcom,mode = <GSBI_PROT_I2C_UART>;
+ status = "okay";
+};
- dragon_ebi2_pins: ebi2 {
- /*
- * Pins used by EBI2 on the Dragonboard, actually only
- * CS2 is used by a real peripheral. CS0 is just
- * routed to a test point.
- */
- mux0 {
- pins =
- /* "gpio39", CS1A_N this is not good to mux */
- "gpio40", /* CS2A_N */
- "gpio134"; /* CS0_N testpoint TP29 */
- function = "ebi2cs";
- };
- mux1 {
- pins =
- /* EBI2_ADDR_7 downto EBI2_ADDR_0 address bus */
- "gpio123", "gpio124", "gpio125", "gpio126",
- "gpio127", "gpio128", "gpio129", "gpio130",
- /* EBI2_DATA_15 downto EBI2_DATA_0 data bus */
- "gpio135", "gpio136", "gpio137", "gpio138",
- "gpio139", "gpio140", "gpio141", "gpio142",
- "gpio143", "gpio144", "gpio145", "gpio146",
- "gpio147", "gpio148", "gpio149", "gpio150",
- "gpio151", /* EBI2_OE_N */
- "gpio153", /* EBI2_ADV */
- "gpio157"; /* EBI2_WE_N */
- function = "ebi2";
- };
- };
+&gsbi12_serial {
+ pinctrl-names = "default";
+ pinctrl-0 = <&dragon_gsbi12_serial_pins>;
+ status = "okay";
+};
- /* Interrupt line for the KXSD9 accelerometer */
- dragon_kxsd9_gpios: kxsd9 {
- irq {
- pins = "gpio57"; /* IRQ line */
- bias-pull-up;
- };
- };
+&gsbi12_i2c {
+ pinctrl-names = "default";
+ pinctrl-0 = <&dragon_gsbi12_i2c_pins>;
+ status = "okay";
+
+ ak8975@c {
+ compatible = "asahi-kasei,ak8975";
+ reg = <0x0c>;
+ interrupt-parent = <&pm8058_gpio>;
+ interrupts = <33 IRQ_TYPE_EDGE_RISING>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&dragon_ak8975_gpios>;
+ vid-supply = <&pm8058_lvs0>; // 1.8V
+ vdd-supply = <&pm8058_l14>; // 2.85V
+ };
+ bmp085@77 {
+ compatible = "bosch,bmp085";
+ reg = <0x77>;
+ interrupt-parent = <&pm8058_gpio>;
+ interrupts = <16 IRQ_TYPE_EDGE_RISING>;
+ reset-gpios = <&tlmm 86 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&dragon_bmp085_gpios>;
+ vddd-supply = <&pm8058_lvs0>; // 1.8V
+ vdda-supply = <&pm8058_l14>; // 2.85V
+ };
+ mpu3050@68 {
+ compatible = "invensense,mpu3050";
+ reg = <0x68>;
+ /*
+ * GPIO17 is pulled high by a 10k
+ * resistor to VLOGIC so needs to be
+ * active low/falling edge.
+ */
+ interrupts-extended = <&pm8058_gpio 17 IRQ_TYPE_EDGE_FALLING>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&dragon_mpu3050_gpios>;
+ vlogic-supply = <&pm8058_lvs0>; // 1.8V
+ vdd-supply = <&pm8058_l14>; // 2.85V
- dragon_tma340_gpios: tma340 {
- reset {
- /* RESET line, TS_ATTN, WAKE_CTP */
- pins = "gpio58";
- function = "gpio";
- drive-strength = <6>;
- bias-disable;
- };
- irq {
- pins = "gpio61"; /* IRQ line */
- function = "gpio";
- drive-strength = <2>;
- bias-pull-up;
- };
+ /*
+ * The MPU-3050 acts as a hub for the
+ * accelerometer.
+ */
+ i2c-gate {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ kxsd9@18 {
+ compatible = "kionix,kxsd9";
+ reg = <0x18>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <57 IRQ_TYPE_EDGE_FALLING>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&dragon_kxsd9_gpios>;
+ iovdd-supply = <&pm8058_lvs0>; // 1.8V
+ vdd-supply = <&pm8058_l14>; // 2.85V
};
};
+ };
+};
- qcom,ssbi@500000 {
- pmic@0 {
- keypad@148 {
- linux,keymap = <
- MATRIX_KEY(0, 0, KEY_MENU)
- MATRIX_KEY(0, 2, KEY_1)
- MATRIX_KEY(0, 3, KEY_4)
- MATRIX_KEY(0, 4, KEY_7)
- MATRIX_KEY(1, 0, KEY_UP)
- MATRIX_KEY(1, 1, KEY_LEFT)
- MATRIX_KEY(1, 2, KEY_DOWN)
- MATRIX_KEY(1, 3, KEY_5)
- MATRIX_KEY(1, 3, KEY_8)
- MATRIX_KEY(2, 0, KEY_HOME)
- MATRIX_KEY(2, 1, KEY_REPLY)
- MATRIX_KEY(2, 2, KEY_2)
- MATRIX_KEY(2, 3, KEY_6)
- MATRIX_KEY(3, 0, KEY_VOLUMEUP)
- MATRIX_KEY(3, 1, KEY_RIGHT)
- MATRIX_KEY(3, 2, KEY_3)
- MATRIX_KEY(3, 3, KEY_9)
- MATRIX_KEY(3, 4, KEY_SWITCHVIDEOMODE)
- MATRIX_KEY(4, 0, KEY_VOLUMEDOWN)
- MATRIX_KEY(4, 1, KEY_BACK)
- MATRIX_KEY(4, 2, KEY_CAMERA)
- MATRIX_KEY(4, 3, KEY_KBDILLUMTOGGLE)
- >;
- keypad,num-rows = <6>;
- keypad,num-columns = <5>;
- };
-
- gpio@150 {
- dragon_ethernet_gpios: ethernet-state {
- pinconf {
- pins = "gpio7";
- function = "normal";
- input-enable;
- bias-disable;
- power-source = <PM8058_GPIO_S3>;
- };
- };
- dragon_bmp085_gpios: bmp085-state {
- pinconf {
- pins = "gpio16";
- function = "normal";
- input-enable;
- bias-disable;
- power-source = <PM8058_GPIO_S3>;
- };
- };
- dragon_mpu3050_gpios: mpu3050-state {
- pinconf {
- pins = "gpio17";
- function = "normal";
- input-enable;
- bias-disable;
- power-source = <PM8058_GPIO_S3>;
- };
- };
- dragon_sdcc3_gpios: sdcc3-state {
- pinconf {
- pins = "gpio22";
- function = "normal";
- input-enable;
- bias-disable;
- power-source = <PM8058_GPIO_S3>;
- };
- };
- dragon_sdcc5_gpios: sdcc5-state {
- pinconf {
- pins = "gpio26";
- function = "normal";
- input-enable;
- bias-pull-up;
- qcom,pull-up-strength = <PMIC_GPIO_PULL_UP_30>;
- power-source = <PM8058_GPIO_S3>;
- };
- };
- dragon_ak8975_gpios: ak8975-state {
- pinconf {
- pins = "gpio33";
- function = "normal";
- input-enable;
- bias-disable;
- power-source = <PM8058_GPIO_S3>;
- };
- };
- dragon_cm3605_gpios: cm3605-state {
- /* Pin 34 connected to the proxy IRQ */
- gpio34-pins {
- pins = "gpio34";
- function = "normal";
- input-enable;
- bias-disable;
- power-source = <PM8058_GPIO_S3>;
- };
- /* Pin 35 connected to ASET */
- gpio35-pins {
- pins = "gpio35";
- function = "normal";
- output-high;
- bias-disable;
- power-source = <PM8058_GPIO_S3>;
- };
- };
- dragon_veth_gpios: veth-state {
- pinconf {
- pins = "gpio40";
- function = "normal";
- bias-disable;
- drive-push-pull;
- };
- };
- };
-
- mpps@50 {
- dragon_cm3605_mpps: cm3605-mpps-state {
- mpp5 {
- pins = "mpp5";
- function = "analog";
- input-enable;
- bias-high-impedance;
- /* Let's use channel 5 */
- qcom,amux-route = <PMIC_MPP_AMUX_ROUTE_CH5>;
- power-source = <PM8058_GPIO_S3>;
- };
- };
- };
-
- xoadc@197 {
- /* Reference voltage 2.2 V */
- xoadc-ref-supply = <&pm8058_l18>;
-
- /* Board-specific channels */
- mpp5@5 {
- /* Connected to AOUT of ALS sensor */
- reg = <0x00 0x05>;
- };
- mpp6@6 {
- /* Connected to test point TP43 */
- reg = <0x00 0x06>;
- };
- mpp7@7 {
- /* Connected to battery thermistor */
- reg = <0x00 0x07>;
- };
- mpp8@8 {
- /* Connected to battery ID detector */
- reg = <0x00 0x08>;
- };
- mpp9@9 {
- /* Connected to XO thermistor */
- reg = <0x00 0x09>;
- };
- };
-
- led@48 {
- /*
- * The keypad LED @0x48 is routed to
- * the sensor board where it is
- * connected to an infrared LED
- * SFH4650 (60mW, @850nm) next to the
- * ambient light and proximity sensor
- * Capella Microsystems CM3605.
- */
- compatible = "qcom,pm8058-keypad-led";
- reg = <0x48>;
- label = "pm8058:infrared:proximitysensor";
- default-state = "off";
- linux,default-trigger = "cm3605";
- };
- led@131 {
- compatible = "qcom,pm8058-led";
- reg = <0x131>;
- label = "pm8058:red";
- color = <LED_COLOR_ID_RED>;
- default-state = "off";
- };
- led@132 {
- /*
- * This is actually green too on my
- * board, but documented as yellow.
- */
- compatible = "qcom,pm8058-led";
- reg = <0x132>;
- label = "pm8058:yellow";
- color = <LED_COLOR_ID_YELLOW>;
- default-state = "off";
- linux,default-trigger = "mmc0";
- };
- led@133 {
- compatible = "qcom,pm8058-led";
- reg = <0x133>;
- label = "pm8058:green";
- function = LED_FUNCTION_HEARTBEAT;
- color = <LED_COLOR_ID_GREEN>;
- default-state = "on";
- linux,default-trigger = "heartbeat";
- };
- };
+&pm8058_gpio {
+ dragon_ethernet_gpios: ethernet-state {
+ pinconf {
+ pins = "gpio7";
+ function = "normal";
+ input-enable;
+ bias-disable;
+ power-source = <PM8058_GPIO_S3>;
+ };
+ };
+ dragon_bmp085_gpios: bmp085-state {
+ pinconf {
+ pins = "gpio16";
+ function = "normal";
+ input-enable;
+ bias-disable;
+ power-source = <PM8058_GPIO_S3>;
+ };
+ };
+ dragon_mpu3050_gpios: mpu3050-state {
+ pinconf {
+ pins = "gpio17";
+ function = "normal";
+ input-enable;
+ bias-disable;
+ power-source = <PM8058_GPIO_S3>;
+ };
+ };
+ dragon_sdcc3_gpios: sdcc3-state {
+ pinconf {
+ pins = "gpio22";
+ function = "normal";
+ input-enable;
+ bias-disable;
+ power-source = <PM8058_GPIO_S3>;
+ };
+ };
+ dragon_sdcc5_gpios: sdcc5-state {
+ pinconf {
+ pins = "gpio26";
+ function = "normal";
+ input-enable;
+ bias-pull-up;
+ qcom,pull-up-strength = <PMIC_GPIO_PULL_UP_30>;
+ power-source = <PM8058_GPIO_S3>;
+ };
+ };
+ dragon_ak8975_gpios: ak8975-state {
+ pinconf {
+ pins = "gpio33";
+ function = "normal";
+ input-enable;
+ bias-disable;
+ power-source = <PM8058_GPIO_S3>;
+ };
+ };
+ dragon_cm3605_gpios: cm3605-state {
+ /* Pin 34 connected to the proxy IRQ */
+ gpio34-pins {
+ pins = "gpio34";
+ function = "normal";
+ input-enable;
+ bias-disable;
+ power-source = <PM8058_GPIO_S3>;
+ };
+ /* Pin 35 connected to ASET */
+ gpio35-pins {
+ pins = "gpio35";
+ function = "normal";
+ output-high;
+ bias-disable;
+ power-source = <PM8058_GPIO_S3>;
+ };
+ };
+ dragon_veth_gpios: veth-state {
+ pinconf {
+ pins = "gpio40";
+ function = "normal";
+ bias-disable;
+ drive-push-pull;
};
+ };
+};
- gsbi@16200000 {
- qcom,mode = <GSBI_PROT_I2C>;
- status = "okay";
+&pm8058_keypad {
+ linux,keymap = <
+ MATRIX_KEY(0, 0, KEY_MENU)
+ MATRIX_KEY(0, 2, KEY_1)
+ MATRIX_KEY(0, 3, KEY_4)
+ MATRIX_KEY(0, 4, KEY_7)
+ MATRIX_KEY(1, 0, KEY_UP)
+ MATRIX_KEY(1, 1, KEY_LEFT)
+ MATRIX_KEY(1, 2, KEY_DOWN)
+ MATRIX_KEY(1, 3, KEY_5)
+ MATRIX_KEY(1, 3, KEY_8)
+ MATRIX_KEY(2, 0, KEY_HOME)
+ MATRIX_KEY(2, 1, KEY_REPLY)
+ MATRIX_KEY(2, 2, KEY_2)
+ MATRIX_KEY(2, 3, KEY_6)
+ MATRIX_KEY(3, 0, KEY_VOLUMEUP)
+ MATRIX_KEY(3, 1, KEY_RIGHT)
+ MATRIX_KEY(3, 2, KEY_3)
+ MATRIX_KEY(3, 3, KEY_9)
+ MATRIX_KEY(3, 4, KEY_SWITCHVIDEOMODE)
+ MATRIX_KEY(4, 0, KEY_VOLUMEDOWN)
+ MATRIX_KEY(4, 1, KEY_BACK)
+ MATRIX_KEY(4, 2, KEY_CAMERA)
+ MATRIX_KEY(4, 3, KEY_KBDILLUMTOGGLE)
+ >;
+ keypad,num-rows = <6>;
+ keypad,num-columns = <5>;
+};
- gsbi3_i2c: i2c@16280000 {
- pinctrl-names = "default";
- pinctrl-0 = <&dragon_gsbi3_i2c_pins>;
- status = "okay";
-
- touchscreen@24 {
- compatible = "cypress,cy8ctma340";
- reg = <0x24>;
- /* Certainly we can do at least 400 kHz */
- clock-frequency = <400000>;
- /* IRQ on GPIO61 called /CTP_INT */
- interrupt-parent = <&tlmm>;
- interrupts = <61 IRQ_TYPE_EDGE_FALLING>;
- /*
- * The I2C bus is using a PCA9306 level translator from L16A
- * to L2B so these two voltages are needed and L16A is
- * kind of the IO voltage, however L16Aisn't really fed to
- * the TMA340, which relies entirely on L2B (PM8901 L2).
- */
- vcpin-supply = <&pm8058_l16>;
- vdd-supply = <&pm8901_l2>;
- /* GPIO58, called WAKE_CTP */
- reset-gpios = <&tlmm 58 GPIO_ACTIVE_LOW>;
- touchscreen-size-x = <480>;
- touchscreen-size-y = <800>;
- active-interval-ms = <0>;
- touch-timeout-ms = <255>;
- lowpower-interval-ms = <10>;
- bootloader-key = /bits/ 8 <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07>;
- pinctrl-names = "default";
- pinctrl-0 = <&dragon_tma340_gpios>;
- };
- };
+&pm8058_led48 {
+ /*
+ * The keypad LED @0x48 is routed to
+ * the sensor board where it is
+ * connected to an infrared LED
+ * SFH4650 (60mW, @850nm) next to the
+ * ambient light and proximity sensor
+ * Capella Microsystems CM3605.
+ */
+ label = "pm8058:infrared:proximitysensor";
+ default-state = "off";
+ linux,default-trigger = "cm3605";
+ status = "okay";
+};
+
+&pm8058_led131 {
+ label = "pm8058:red";
+ color = <LED_COLOR_ID_RED>;
+ default-state = "off";
+ status = "okay";
+};
+
+&pm8058_led132 {
+ /*
+ * This is actually green too on my
+ * board, but documented as yellow.
+ */
+ label = "pm8058:yellow";
+ color = <LED_COLOR_ID_YELLOW>;
+ default-state = "off";
+ linux,default-trigger = "mmc0";
+ status = "okay";
+};
+
+&pm8058_led133 {
+ label = "pm8058:green";
+ function = LED_FUNCTION_HEARTBEAT;
+ color = <LED_COLOR_ID_GREEN>;
+ default-state = "on";
+ linux,default-trigger = "heartbeat";
+ status = "okay";
+};
+
+&pm8058_mpps {
+ dragon_cm3605_mpps: cm3605-mpps-state {
+ mpp5 {
+ pins = "mpp5";
+ function = "analog";
+ input-enable;
+ bias-high-impedance;
+ /* Let's use channel 5 */
+ qcom,amux-route = <PMIC_MPP_AMUX_ROUTE_CH5>;
+ power-source = <PM8058_GPIO_S3>;
};
+ };
+};
- gsbi@19800000 {
- status = "okay";
- qcom,mode = <GSBI_PROT_I2C>;
+&rpm {
+ /*
+ * Set up of the PMIC RPM regulators for this board
+ * PM8901 supplies "preliminary regulators" whatever
+ * that means
+ */
+ pm8901-regulators {
+ vdd_l0-supply = <&pm8901_s4>;
+ vdd_l1-supply = <&vph>;
+ vdd_l2-supply = <&vph>;
+ vdd_l3-supply = <&vph>;
+ vdd_l4-supply = <&vph>;
+ vdd_l5-supply = <&vph>;
+ vdd_l6-supply = <&vph>;
+ /* vdd_s0-supply, vdd_s1-supply: SAW regulators */
+ vdd_s2-supply = <&vph>;
+ vdd_s3-supply = <&vph>;
+ vdd_s4-supply = <&vph>;
+ lvs0_in-supply = <&pm8058_s3>;
+ lvs1_in-supply = <&pm8901_s4>;
+ lvs2_in-supply = <&pm8058_l0>;
+ lvs3_in-supply = <&pm8058_s2>;
+ mvs_in-supply = <&pm8058_s3>;
+
+ l0 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ bias-pull-down;
+ };
+ l1 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ bias-pull-down;
+ };
+ l2 {
+ /* TMA340 requires strictly 3.3V */
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ bias-pull-down;
+ };
+ l3 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ bias-pull-down;
+ };
+ l4 {
+ regulator-min-microvolt = <2600000>;
+ regulator-max-microvolt = <2600000>;
+ bias-pull-down;
+ };
+ l5 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ bias-pull-down;
+ };
+ l6 {
+ regulator-min-microvolt = <2200000>;
+ regulator-max-microvolt = <2200000>;
+ bias-pull-down;
+ };
- i2c@19880000 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&dragon_gsbi8_i2c_pins>;
-
- eeprom@52 {
- /* A 16KiB Platform ID EEPROM on the CPU carrier board */
- compatible = "atmel,24c128";
- reg = <0x52>;
- vcc-supply = <&pm8058_s3>;
- pagesize = <64>;
- };
- wm8903: wm8903@1a {
- /* This Woolfson Micro device has an unrouted interrupt line */
- compatible = "wlf,wm8903";
- reg = <0x1a>;
-
- AVDD-supply = <&pm8058_l16>;
- CPVDD-supply = <&pm8058_l16>;
- DBVDD-supply = <&pm8058_s3>;
- DCVDD-supply = <&pm8058_l0>;
-
- gpio-controller;
- #gpio-cells = <2>;
-
- micdet-cfg = <0>;
- micdet-delay = <100>;
- gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>;
- };
- };
+ /* s0 and s1 are SAW regulators controlled over SPM */
+ s2 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ qcom,switch-mode-frequency = <1600000>;
+ bias-pull-down;
+ };
+ s3 {
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ qcom,switch-mode-frequency = <1600000>;
+ bias-pull-down;
+ };
+ s4 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ qcom,switch-mode-frequency = <1600000>;
+ bias-pull-down;
};
- gsbi@19c00000 {
- status = "okay";
- qcom,mode = <GSBI_PROT_I2C_UART>;
+ /* LVS0 thru 3 and mvs are just switches */
+ lvs0 {
+ regulator-always-on;
+ };
+ lvs1 { };
+ lvs2 { };
+ lvs3 { };
+ mvs { };
- serial@19c40000 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&dragon_gsbi12_serial_pins>;
- };
+ };
- i2c@19c80000 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&dragon_gsbi12_i2c_pins>;
-
- ak8975@c {
- compatible = "asahi-kasei,ak8975";
- reg = <0x0c>;
- interrupt-parent = <&pm8058_gpio>;
- interrupts = <33 IRQ_TYPE_EDGE_RISING>;
- pinctrl-names = "default";
- pinctrl-0 = <&dragon_ak8975_gpios>;
- vid-supply = <&pm8058_lvs0>; // 1.8V
- vdd-supply = <&pm8058_l14>; // 2.85V
- };
- bmp085@77 {
- compatible = "bosch,bmp085";
- reg = <0x77>;
- interrupt-parent = <&pm8058_gpio>;
- interrupts = <16 IRQ_TYPE_EDGE_RISING>;
- reset-gpios = <&tlmm 86 GPIO_ACTIVE_LOW>;
- pinctrl-names = "default";
- pinctrl-0 = <&dragon_bmp085_gpios>;
- vddd-supply = <&pm8058_lvs0>; // 1.8V
- vdda-supply = <&pm8058_l14>; // 2.85V
- };
- mpu3050@68 {
- compatible = "invensense,mpu3050";
- reg = <0x68>;
- /*
- * GPIO17 is pulled high by a 10k
- * resistor to VLOGIC so needs to be
- * active low/falling edge.
- */
- interrupts-extended = <&pm8058_gpio 17 IRQ_TYPE_EDGE_FALLING>;
- pinctrl-names = "default";
- pinctrl-0 = <&dragon_mpu3050_gpios>;
- vlogic-supply = <&pm8058_lvs0>; // 1.8V
- vdd-supply = <&pm8058_l14>; // 2.85V
-
- /*
- * The MPU-3050 acts as a hub for the
- * accelerometer.
- */
- i2c-gate {
- #address-cells = <1>;
- #size-cells = <0>;
-
- kxsd9@18 {
- compatible = "kionix,kxsd9";
- reg = <0x18>;
- interrupt-parent = <&tlmm>;
- interrupts = <57 IRQ_TYPE_EDGE_FALLING>;
- pinctrl-names = "default";
- pinctrl-0 = <&dragon_kxsd9_gpios>;
- iovdd-supply = <&pm8058_lvs0>; // 1.8V
- vdd-supply = <&pm8058_l14>; // 2.85V
- };
- };
- };
- };
+ pm8058-regulators {
+ vdd_l0_l1_lvs-supply = <&pm8058_s3>;
+ vdd_l2_l11_l12-supply = <&vph>;
+ vdd_l3_l4_l5-supply = <&vph>;
+ vdd_l6_l7-supply = <&vph>;
+ vdd_l8-supply = <&vph>;
+ vdd_l9-supply = <&vph>;
+ vdd_l10-supply = <&vph>;
+ vdd_l13_l16-supply = <&pm8058_s4>;
+ vdd_l14_l15-supply = <&vph>;
+ vdd_l17_l18-supply = <&vph>;
+ vdd_l19_l20-supply = <&vph>;
+ vdd_l21-supply = <&pm8058_s3>;
+ vdd_l22-supply = <&pm8058_s3>;
+ vdd_l23_l24_l25-supply = <&pm8058_s3>;
+ vdd_s0-supply = <&vph>;
+ vdd_s1-supply = <&vph>;
+ vdd_s2-supply = <&vph>;
+ vdd_s3-supply = <&vph>;
+ vdd_s4-supply = <&vph>;
+ vdd_ncp-supply = <&vph>;
+
+ l0 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ bias-pull-down;
+ };
+ l1 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ bias-pull-down;
+ };
+ l2 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2600000>;
+ bias-pull-down;
+ };
+ l3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ bias-pull-down;
+ };
+ l4 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ bias-pull-down;
+ };
+ l5 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ bias-pull-down;
+ };
+ l6 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3600000>;
+ bias-pull-down;
+ };
+ l7 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ bias-pull-down;
+ };
+ l8 {
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <3050000>;
+ bias-pull-down;
+ };
+ l9 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ bias-pull-down;
+ };
+ l10 {
+ regulator-min-microvolt = <2600000>;
+ regulator-max-microvolt = <2600000>;
+ bias-pull-down;
+ };
+ l11 {
+ regulator-min-microvolt = <1500000>;
+ regulator-max-microvolt = <1500000>;
+ bias-pull-down;
+ };
+ l12 {
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <2900000>;
+ bias-pull-down;
+ };
+ l13 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ bias-pull-down;
+ };
+ l14 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ };
+ l15 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ bias-pull-down;
+ };
+ l16 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ bias-pull-down;
+ regulator-always-on;
+ };
+ l17 {
+ // 1.5V according to schematic
+ regulator-min-microvolt = <2600000>;
+ regulator-max-microvolt = <2600000>;
+ bias-pull-down;
+ };
+ l18 {
+ regulator-min-microvolt = <2200000>;
+ regulator-max-microvolt = <2200000>;
+ bias-pull-down;
+ };
+ l19 {
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ bias-pull-down;
+ };
+ l20 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ bias-pull-down;
+ };
+ l21 {
+ // 1.1 V according to schematic
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ bias-pull-down;
+ regulator-always-on;
+ };
+ l22 {
+ // 1.2 V according to schematic
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1150000>;
+ bias-pull-down;
+ };
+ l23 {
+ // Unused
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ bias-pull-down;
+ };
+ l24 {
+ // Unused
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ bias-pull-down;
+ };
+ l25 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ bias-pull-down;
};
- external-bus@1a100000 {
- /* The EBI2 will instantiate first, then populate its children */
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&dragon_ebi2_pins>;
-
- /*
- * An on-board SMSC LAN9221 chip for "debug ethernet",
- * which is actually just an ordinary ethernet on the
- * EBI2. This has a 25MHz chrystal next to it, so no
- * clocking is needed.
- */
- ethernet@2,0 {
- compatible = "smsc,lan9221", "smsc,lan9115";
- reg = <2 0x0 0x100>;
- /*
- * The second interrupt is the PME interrupt
- * for network wakeup, connected to the TLMM.
- */
- interrupts-extended = <&pm8058_gpio 7 IRQ_TYPE_EDGE_FALLING>,
- <&tlmm 29 IRQ_TYPE_EDGE_RISING>;
- reset-gpios = <&tlmm 30 GPIO_ACTIVE_LOW>;
- vdd33a-supply = <&dragon_veth>;
- vddvario-supply = <&dragon_vario>;
- pinctrl-names = "default";
- pinctrl-0 = <&dragon_ethernet_gpios>;
- phy-mode = "mii";
- reg-io-width = <2>;
- smsc,force-external-phy;
- smsc,irq-push-pull;
-
- /*
- * SLOW chipselect config
- * Delay 9 cycles (140ns@64MHz) between SMSC
- * LAN9221 Ethernet controller reads and writes
- * on CS2.
- */
- qcom,xmem-recovery-cycles = <0>;
- qcom,xmem-write-hold-cycles = <3>;
- qcom,xmem-write-delta-cycles = <31>;
- qcom,xmem-read-delta-cycles = <28>;
- qcom,xmem-write-wait-cycles = <9>;
- qcom,xmem-read-wait-cycles = <9>;
- };
+ s0 {
+ // regulator-min-microvolt = <500000>;
+ // regulator-max-microvolt = <1325000>;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ qcom,switch-mode-frequency = <1600000>;
+ bias-pull-down;
+ };
+ s1 {
+ // regulator-min-microvolt = <500000>;
+ // regulator-max-microvolt = <1250000>;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ qcom,switch-mode-frequency = <1600000>;
+ bias-pull-down;
+ };
+ s2 {
+ // 1.3 V according to schematic
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1400000>;
+ qcom,switch-mode-frequency = <1600000>;
+ bias-pull-down;
+ };
+ s3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,switch-mode-frequency = <1600000>;
+ regulator-always-on;
+ bias-pull-down;
+ };
+ s4 {
+ regulator-min-microvolt = <2200000>;
+ regulator-max-microvolt = <2200000>;
+ qcom,switch-mode-frequency = <1600000>;
+ regulator-always-on;
+ bias-pull-down;
};
- rpm@104000 {
- /*
- * Set up of the PMIC RPM regulators for this board
- * PM8901 supplies "preliminary regulators" whatever
- * that means
- */
- pm8901-regulators {
- vdd_l0-supply = <&pm8901_s4>;
- vdd_l1-supply = <&vph>;
- vdd_l2-supply = <&vph>;
- vdd_l3-supply = <&vph>;
- vdd_l4-supply = <&vph>;
- vdd_l5-supply = <&vph>;
- vdd_l6-supply = <&vph>;
- /* vdd_s0-supply, vdd_s1-supply: SAW regulators */
- vdd_s2-supply = <&vph>;
- vdd_s3-supply = <&vph>;
- vdd_s4-supply = <&vph>;
- lvs0_in-supply = <&pm8058_s3>;
- lvs1_in-supply = <&pm8901_s4>;
- lvs2_in-supply = <&pm8058_l0>;
- lvs3_in-supply = <&pm8058_s2>;
- mvs_in-supply = <&pm8058_s3>;
-
- l0 {
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- bias-pull-down;
- };
- l1 {
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- bias-pull-down;
- };
- l2 {
- /* TMA340 requires strictly 3.3V */
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- bias-pull-down;
- };
- l3 {
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- bias-pull-down;
- };
- l4 {
- regulator-min-microvolt = <2600000>;
- regulator-max-microvolt = <2600000>;
- bias-pull-down;
- };
- l5 {
- regulator-min-microvolt = <2850000>;
- regulator-max-microvolt = <2850000>;
- bias-pull-down;
- };
- l6 {
- regulator-min-microvolt = <2200000>;
- regulator-max-microvolt = <2200000>;
- bias-pull-down;
- };
-
- /* s0 and s1 are SAW regulators controlled over SPM */
- s2 {
- regulator-min-microvolt = <1300000>;
- regulator-max-microvolt = <1300000>;
- qcom,switch-mode-frequency = <1600000>;
- bias-pull-down;
- };
- s3 {
- regulator-min-microvolt = <1100000>;
- regulator-max-microvolt = <1100000>;
- qcom,switch-mode-frequency = <1600000>;
- bias-pull-down;
- };
- s4 {
- regulator-min-microvolt = <1225000>;
- regulator-max-microvolt = <1225000>;
- qcom,switch-mode-frequency = <1600000>;
- bias-pull-down;
- };
-
- /* LVS0 thru 3 and mvs are just switches */
- lvs0 {
- regulator-always-on;
- };
- lvs1 { };
- lvs2 { };
- lvs3 { };
- mvs { };
+ /* LVS0 and LVS1 are just switches */
+ lvs0 {
+ bias-pull-down;
+ };
+ lvs1 {
+ bias-pull-down;
+ };
- };
+ ncp {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,switch-mode-frequency = <1600000>;
+ };
+ };
+};
- pm8058-regulators {
- vdd_l0_l1_lvs-supply = <&pm8058_s3>;
- vdd_l2_l11_l12-supply = <&vph>;
- vdd_l3_l4_l5-supply = <&vph>;
- vdd_l6_l7-supply = <&vph>;
- vdd_l8-supply = <&vph>;
- vdd_l9-supply = <&vph>;
- vdd_l10-supply = <&vph>;
- vdd_l13_l16-supply = <&pm8058_s4>;
- vdd_l14_l15-supply = <&vph>;
- vdd_l17_l18-supply = <&vph>;
- vdd_l19_l20-supply = <&vph>;
- vdd_l21-supply = <&pm8058_s3>;
- vdd_l22-supply = <&pm8058_s3>;
- vdd_l23_l24_l25-supply = <&pm8058_s3>;
- vdd_s0-supply = <&vph>;
- vdd_s1-supply = <&vph>;
- vdd_s2-supply = <&vph>;
- vdd_s3-supply = <&vph>;
- vdd_s4-supply = <&vph>;
- vdd_ncp-supply = <&vph>;
-
- l0 {
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- bias-pull-down;
- };
- l1 {
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- bias-pull-down;
- };
- l2 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2600000>;
- bias-pull-down;
- };
- l3 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- bias-pull-down;
- };
- l4 {
- regulator-min-microvolt = <2850000>;
- regulator-max-microvolt = <2850000>;
- bias-pull-down;
- };
- l5 {
- regulator-min-microvolt = <2850000>;
- regulator-max-microvolt = <2850000>;
- bias-pull-down;
- };
- l6 {
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3600000>;
- bias-pull-down;
- };
- l7 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- bias-pull-down;
- };
- l8 {
- regulator-min-microvolt = <2900000>;
- regulator-max-microvolt = <3050000>;
- bias-pull-down;
- };
- l9 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- bias-pull-down;
- };
- l10 {
- regulator-min-microvolt = <2600000>;
- regulator-max-microvolt = <2600000>;
- bias-pull-down;
- };
- l11 {
- regulator-min-microvolt = <1500000>;
- regulator-max-microvolt = <1500000>;
- bias-pull-down;
- };
- l12 {
- regulator-min-microvolt = <2900000>;
- regulator-max-microvolt = <2900000>;
- bias-pull-down;
- };
- l13 {
- regulator-min-microvolt = <2050000>;
- regulator-max-microvolt = <2050000>;
- bias-pull-down;
- };
- l14 {
- regulator-min-microvolt = <2850000>;
- regulator-max-microvolt = <2850000>;
- };
- l15 {
- regulator-min-microvolt = <2850000>;
- regulator-max-microvolt = <2850000>;
- bias-pull-down;
- };
- l16 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- bias-pull-down;
- regulator-always-on;
- };
- l17 {
- // 1.5V according to schematic
- regulator-min-microvolt = <2600000>;
- regulator-max-microvolt = <2600000>;
- bias-pull-down;
- };
- l18 {
- regulator-min-microvolt = <2200000>;
- regulator-max-microvolt = <2200000>;
- bias-pull-down;
- };
- l19 {
- regulator-min-microvolt = <2500000>;
- regulator-max-microvolt = <2500000>;
- bias-pull-down;
- };
- l20 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- bias-pull-down;
- };
- l21 {
- // 1.1 V according to schematic
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- bias-pull-down;
- regulator-always-on;
- };
- l22 {
- // 1.2 V according to schematic
- regulator-min-microvolt = <1150000>;
- regulator-max-microvolt = <1150000>;
- bias-pull-down;
- };
- l23 {
- // Unused
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- bias-pull-down;
- };
- l24 {
- // Unused
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- bias-pull-down;
- };
- l25 {
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- bias-pull-down;
- };
-
- s0 {
- // regulator-min-microvolt = <500000>;
- // regulator-max-microvolt = <1325000>;
- regulator-min-microvolt = <1100000>;
- regulator-max-microvolt = <1100000>;
- qcom,switch-mode-frequency = <1600000>;
- bias-pull-down;
- };
- s1 {
- // regulator-min-microvolt = <500000>;
- // regulator-max-microvolt = <1250000>;
- regulator-min-microvolt = <1100000>;
- regulator-max-microvolt = <1100000>;
- qcom,switch-mode-frequency = <1600000>;
- bias-pull-down;
- };
- s2 {
- // 1.3 V according to schematic
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1400000>;
- qcom,switch-mode-frequency = <1600000>;
- bias-pull-down;
- };
- s3 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,switch-mode-frequency = <1600000>;
- regulator-always-on;
- bias-pull-down;
- };
- s4 {
- regulator-min-microvolt = <2200000>;
- regulator-max-microvolt = <2200000>;
- qcom,switch-mode-frequency = <1600000>;
- regulator-always-on;
- bias-pull-down;
- };
-
- /* LVS0 and LVS1 are just switches */
- lvs0 {
- bias-pull-down;
- };
- lvs1 {
- bias-pull-down;
- };
-
- ncp {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,switch-mode-frequency = <1600000>;
- };
- };
+/* Internal 3.69 GiB eMMC */
+&sdcc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&dragon_sdcc1_pins>;
+ vmmc-supply = <&pm8901_l5>;
+ vqmmc-supply = <&pm8901_lvs0>;
+ status = "okay";
+};
+
+/* External micro SD card, directly connected, pulled up to 2.85 V */
+&sdcc3 {
+ /* Enable SSBI GPIO 22 as input, use for card detect */
+ pinctrl-names = "default";
+ pinctrl-0 = <&dragon_sdcc3_pins>, <&dragon_sdcc3_gpios>;
+ cd-gpios = <&pm8058_gpio 22 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&tlmm 110 GPIO_ACTIVE_HIGH>;
+ vmmc-supply = <&pm8058_l14>;
+ status = "okay";
+};
+
+/*
+ * Second external micro SD card, using two TXB104RGYR levelshifters
+ * to lift from 1.8 V to 2.85 V
+ */
+&sdcc5 {
+ /* Enable SSBI GPIO 26 as input, use for card detect */
+ pinctrl-names = "default";
+ pinctrl-0 = <&dragon_sdcc5_pins>, <&dragon_sdcc5_gpios>;
+ cd-gpios = <&pm8058_gpio 26 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&tlmm 106 GPIO_ACTIVE_HIGH>;
+ vmmc-supply = <&pm8058_l14>;
+ vqmmc-supply = <&dragon_vio_txb>;
+ status = "okay";
+};
+
+&tlmm {
+ /* eMMC pins, all 8 data lines connected */
+ dragon_sdcc1_pins: sdcc1-state {
+ clk-pins {
+ pins = "gpio167"; /* SDC1 CLK */
+ function = "sdc1";
+ drive-strength = <16>;
+ bias-disable;
};
- amba {
- /* Internal 3.69 GiB eMMC */
- mmc@12400000 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&dragon_sdcc1_pins>;
- vmmc-supply = <&pm8901_l5>;
- vqmmc-supply = <&pm8901_lvs0>;
- };
+ cmd-pins {
+ pins = "gpio168"; /* SDC1 CMD */
+ function = "sdc1";
+ drive-strength = <10>;
+ bias-pull-up;
+ };
+ data-pins {
+ /* SDC1 D0 to D7 */
+ pins = "gpio159", "gpio160", "gpio161", "gpio162",
+ "gpio163", "gpio164", "gpio165", "gpio166";
+ function = "sdc1";
+ drive-strength = <10>;
+ bias-pull-up;
+ };
+ };
- /* External micro SD card, directly connected, pulled up to 2.85 V */
- mmc@12180000 {
- status = "okay";
- /* Enable SSBI GPIO 22 as input, use for card detect */
- pinctrl-names = "default";
- pinctrl-0 = <&dragon_sdcc3_pins>, <&dragon_sdcc3_gpios>;
- cd-gpios = <&pm8058_gpio 22 GPIO_ACTIVE_LOW>;
- wp-gpios = <&tlmm 110 GPIO_ACTIVE_HIGH>;
- vmmc-supply = <&pm8058_l14>;
- };
+ /*
+ * The SDCC3 pins are hardcoded (non-muxable) but need some pin
+ * configuration.
+ */
+ dragon_sdcc3_pins: sdcc3-state {
+ clk-pins {
+ pins = "sdc3_clk";
+ drive-strength = <8>;
+ bias-disable;
+ };
+ cmd-pins {
+ pins = "sdc3_cmd";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+ data-pins {
+ pins = "sdc3_data";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+ };
- /*
- * Second external micro SD card, using two TXB104RGYR levelshifters
- * to lift from 1.8 V to 2.85 V
- */
- mmc@12200000 {
- status = "okay";
- /* Enable SSBI GPIO 26 as input, use for card detect */
- pinctrl-names = "default";
- pinctrl-0 = <&dragon_sdcc5_pins>, <&dragon_sdcc5_gpios>;
- cd-gpios = <&pm8058_gpio 26 GPIO_ACTIVE_LOW>;
- wp-gpios = <&tlmm 106 GPIO_ACTIVE_HIGH>;
- vmmc-supply = <&pm8058_l14>;
- vqmmc-supply = <&dragon_vio_txb>;
- };
+ /* Second SD card slot pins */
+ dragon_sdcc5_pins: sdcc5-state {
+ clk-pins {
+ pins = "gpio97"; /* SDC5 CLK */
+ function = "sdc5";
+ drive-strength = <16>;
+ bias-disable;
+ };
+ cmd-pins {
+ pins = "gpio95"; /* SDC5 CMD */
+ function = "sdc5";
+ drive-strength = <10>;
+ bias-pull-up;
+ };
+ data-pins {
+ /* SDC5 D0 to D3 */
+ pins = "gpio96", "gpio98", "gpio99", "gpio100";
+ function = "sdc5";
+ drive-strength = <10>;
+ bias-pull-up;
};
};
+
+ dragon_gsbi3_i2c_pins: gsbi3-i2c-state {
+ pins = "gpio43", "gpio44";
+ function = "gsbi3";
+ drive-strength = <8>;
+ /* These have external pull-up 2.2kOhm to 1.8V */
+ bias-disable;
+ };
+
+ dragon_gsbi8_i2c_pins: gsbi8-i2c-state {
+ pins = "gpio64", "gpio65";
+ function = "gsbi8";
+ drive-strength = <16>;
+ /* These have external pull-up 2.2kOhm to 1.8V */
+ bias-disable;
+ };
+
+ dragon_gsbi12_i2c_pins: gsbi12-i2c-state {
+ pins = "gpio115", "gpio116";
+ function = "gsbi12";
+ drive-strength = <16>;
+ /* These have external pull-up 4.7kOhm to 1.8V */
+ bias-disable;
+ };
+
+ /* Primary serial port uart 0 pins */
+ dragon_gsbi12_serial_pins: gsbi12-serial-state {
+ tx-pins {
+ pins = "gpio117";
+ function = "gsbi12";
+ drive-strength = <8>;
+ bias-disable;
+ };
+ rx-pins {
+ pins = "gpio118";
+ function = "gsbi12";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ dragon_ebi2_pins: ebi2-state {
+ /*
+ * Pins used by EBI2 on the Dragonboard, actually only
+ * CS2 is used by a real peripheral. CS0 is just
+ * routed to a test point.
+ */
+ mux0-pins {
+ pins =
+ /* "gpio39", CS1A_N this is not good to mux */
+ "gpio40", /* CS2A_N */
+ "gpio134"; /* CS0_N testpoint TP29 */
+ function = "ebi2cs";
+ };
+ mux1-pins {
+ pins =
+ /* EBI2_ADDR_7 downto EBI2_ADDR_0 address bus */
+ "gpio123", "gpio124", "gpio125", "gpio126",
+ "gpio127", "gpio128", "gpio129", "gpio130",
+ /* EBI2_DATA_15 downto EBI2_DATA_0 data bus */
+ "gpio135", "gpio136", "gpio137", "gpio138",
+ "gpio139", "gpio140", "gpio141", "gpio142",
+ "gpio143", "gpio144", "gpio145", "gpio146",
+ "gpio147", "gpio148", "gpio149", "gpio150",
+ "gpio151", /* EBI2_OE_N */
+ "gpio153", /* EBI2_ADV */
+ "gpio157"; /* EBI2_WE_N */
+ function = "ebi2";
+ };
+ };
+
+ /* Interrupt line for the KXSD9 accelerometer */
+ dragon_kxsd9_gpios: kxsd9-state {
+ pins = "gpio57"; /* IRQ line */
+ function = "gpio";
+ bias-pull-up;
+ };
+
+ dragon_tma340_gpios: tma340-state {
+ reset-pins {
+ /* RESET line, TS_ATTN, WAKE_CTP */
+ pins = "gpio58";
+ function = "gpio";
+ drive-strength = <6>;
+ bias-disable;
+ };
+ irq-pins {
+ pins = "gpio61"; /* IRQ line */
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+};
+
+&xoadc {
+ /* Reference voltage 2.2 V */
+ xoadc-ref-supply = <&pm8058_l18>;
+
+ /* Board-specific channels */
+ mpp5@5 {
+ /* Connected to AOUT of ALS sensor */
+ reg = <0x00 0x05>;
+ };
+ mpp6@6 {
+ /* Connected to test point TP43 */
+ reg = <0x00 0x06>;
+ };
+ mpp7@7 {
+ /* Connected to battery thermistor */
+ reg = <0x00 0x07>;
+ };
+ mpp8@8 {
+ /* Connected to battery ID detector */
+ reg = <0x00 0x08>;
+ };
+ mpp9@9 {
+ /* Connected to XO thermistor */
+ reg = <0x00 0x09>;
+ };
};
diff --git a/arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts b/arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts
index fee278e32cb6..bf2fb0f70fe4 100644
--- a/arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts
+++ b/arch/arm/boot/dts/qcom-apq8064-asus-nexus7-flo.dts
@@ -6,6 +6,7 @@
/ {
model = "Asus Nexus7(flo)";
compatible = "asus,nexus7-flo", "qcom,apq8064";
+ chassis-type = "tablet";
aliases {
serial0 = &gsbi7_serial;
@@ -30,7 +31,7 @@
};
};
- ext_3p3v: regulator-fixed@1 {
+ ext_3p3v: regulator-ext-3p3v {
compatible = "regulator-fixed";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
@@ -57,302 +58,291 @@
};
soc {
- rpm@108000 {
- regulators {
- vdd_l1_l2_l12_l18-supply = <&pm8921_s4>;
- vin_lvs1_3_6-supply = <&pm8921_s4>;
- vin_lvs4_5_7-supply = <&pm8921_s4>;
-
-
- vdd_l24-supply = <&pm8921_s1>;
- vdd_l25-supply = <&pm8921_s1>;
- vin_lvs2-supply = <&pm8921_s1>;
-
- vdd_l26-supply = <&pm8921_s7>;
- vdd_l27-supply = <&pm8921_s7>;
- vdd_l28-supply = <&pm8921_s7>;
-
- vdd_ncp-supply = <&pm8921_l6>;
-
- /* Buck SMPS */
- s1 {
- regulator-always-on;
- regulator-min-microvolt = <1225000>;
- regulator-max-microvolt = <1225000>;
- qcom,switch-mode-frequency = <3200000>;
- bias-pull-down;
- };
-
- /* msm otg HSUSB_VDDCX */
- s3 {
- regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <1150000>;
- qcom,switch-mode-frequency = <4800000>;
- };
-
- /*
- * msm_sdcc.1-sdc-vdd_io
- * tabla2x-slim-CDC_VDDA_RX
- * tabla2x-slim-CDC_VDDA_TX
- * tabla2x-slim-CDC_VDD_CP
- * tabla2x-slim-VDDIO_CDC
- */
- s4 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,switch-mode-frequency = <3200000>;
- regulator-always-on;
- };
-
- s7 {
- regulator-min-microvolt = <1300000>;
- regulator-max-microvolt = <1300000>;
- qcom,switch-mode-frequency = <3200000>;
- };
-
- /* mipi_dsi.1-dsi1_pll_vdda */
- l2 {
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- regulator-always-on;
- };
-
- /* msm_otg-HSUSB_3p3 */
- l3 {
- regulator-min-microvolt = <3075000>;
- regulator-max-microvolt = <3075000>;
- bias-pull-down;
- };
-
- /* msm_otg-HSUSB_1p8 */
- l4 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- bias-pull-down;
- };
-
- /* msm_sdcc.1-sdc_vdd */
- l5 {
- regulator-min-microvolt = <2950000>;
- regulator-max-microvolt = <2950000>;
- regulator-always-on;
- bias-pull-down;
- };
-
- l6 {
- regulator-min-microvolt = <2950000>;
- regulator-max-microvolt = <2950000>;
- };
-
- /* mipi_dsi.1-dsi1_avdd */
- l11 {
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- bias-pull-down;
- regulator-always-on;
- };
-
- /* pwm_power for backlight */
- l17 {
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- regulator-always-on;
- };
-
- /* camera, qdsp6 */
- l23 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- bias-pull-down;
- };
-
- /*
- * tabla2x-slim-CDC_VDDA_A_1P2V
- * tabla2x-slim-VDDD_CDC_D
- */
- l25 {
- regulator-min-microvolt = <1250000>;
- regulator-max-microvolt = <1250000>;
- bias-pull-down;
- };
-
- lvs1 {
- bias-pull-down;
- };
-
- lvs4 {
- bias-pull-down;
- };
-
- lvs5 {
- bias-pull-down;
- };
-
- lvs6 {
- bias-pull-down;
- };
- /*
- * mipi_dsi.1-dsi1_vddio
- * pil_riva-pll_vdd
- */
- lvs7 {
- bias-pull-down;
- };
- };
- };
+ sram@2a03f000 {
+ compatible = "qcom,apq8064-imem", "syscon", "simple-mfd";
+ reg = <0x2a03f000 0x1000>;
+
+ reboot-mode {
+ compatible = "syscon-reboot-mode";
+ offset = <0x65c>;
- mdp@5100000 {
- status = "okay";
- ports {
- port@1 {
- mdp_dsi1_out: endpoint {
- remote-endpoint = <&dsi0_in>;
- };
- };
+ mode-normal = <0x77665501>;
+ mode-bootloader = <0x77665500>;
+ mode-recovery = <0x77665502>;
};
};
+ };
+};
- dsi0: dsi@4700000 {
- status = "okay";
- vdda-supply = <&pm8921_l2>;/*VDD_MIPI1 to 4*/
- vdd-supply = <&pm8921_l8>;
- vddio-supply = <&pm8921_lvs7>;
- avdd-supply = <&pm8921_l11>;
-
- panel@0 {
- reg = <0>;
- compatible = "jdi,lt070me05000";
-
- vddp-supply = <&pm8921_l17>;
- iovcc-supply = <&pm8921_lvs7>;
-
- enable-gpios = <&pm8921_gpio 36 GPIO_ACTIVE_HIGH>;
- reset-gpios = <&tlmm_pinmux 54 GPIO_ACTIVE_LOW>;
- dcdc-en-gpios = <&pm8921_gpio 23 GPIO_ACTIVE_HIGH>;
-
- port {
- panel_in: endpoint {
- remote-endpoint = <&dsi0_out>;
- };
- };
- };
- ports {
- port@0 {
- dsi0_in: endpoint {
- remote-endpoint = <&mdp_dsi1_out>;
- };
- };
-
- port@1 {
- dsi0_out: endpoint {
- remote-endpoint = <&panel_in>;
- data-lanes = <0 1 2 3>;
- };
- };
+&dsi0 {
+ vdda-supply = <&pm8921_l2>;/*VDD_MIPI1 to 4*/
+ vdd-supply = <&pm8921_l8>;
+ vddio-supply = <&pm8921_lvs7>;
+ avdd-supply = <&pm8921_l11>;
+ status = "okay";
+
+ panel@0 {
+ reg = <0>;
+ compatible = "jdi,lt070me05000";
+
+ vddp-supply = <&pm8921_l17>;
+ iovcc-supply = <&pm8921_lvs7>;
+
+ enable-gpios = <&pm8921_gpio 36 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&tlmm_pinmux 54 GPIO_ACTIVE_LOW>;
+ dcdc-en-gpios = <&pm8921_gpio 23 GPIO_ACTIVE_HIGH>;
+
+ port {
+ panel_in: endpoint {
+ remote-endpoint = <&dsi0_out>;
};
};
+ };
+};
+
+&dsi0_in {
+ remote-endpoint = <&mdp_dsi1_out>;
+};
+
+&dsi0_out {
+ remote-endpoint = <&panel_in>;
+ data-lanes = <0 1 2 3>;
+};
+
+&dsi0_phy {
+ vddio-supply = <&pm8921_lvs7>;/*VDD_PLL2_1 to 7*/
+ status = "okay";
+};
+
+&gsbi1 {
+ qcom,mode = <GSBI_PROT_I2C>;
+ status = "okay";
+};
+
+&gsbi1_i2c {
+ status = "okay";
+ clock-frequency = <200000>;
+ pinctrl-0 = <&i2c1_pins>;
+ pinctrl-names = "default";
+
+ eeprom@52 {
+ compatible = "atmel,24c128";
+ reg = <0x52>;
+ pagesize = <32>;
+ };
+
+ bq27541@55 {
+ compatible = "ti,bq27541";
+ reg = <0x55>;
+ };
+
+};
+
+&gsbi3 {
+ qcom,mode = <GSBI_PROT_I2C>;
+ status = "okay";
+};
+
+&gsbi3_i2c {
+ clock-frequency = <200000>;
+ pinctrl-0 = <&i2c3_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ trackpad@10 {
+ compatible = "elan,ekth3500";
+ reg = <0x10>;
+ interrupt-parent = <&tlmm_pinmux>;
+ interrupts = <6 IRQ_TYPE_EDGE_FALLING>;
+ };
+};
+
+&gsbi6 {
+ qcom,mode = <GSBI_PROT_I2C_UART>;
+ status = "okay";
+};
+
+&gsbi6_serial {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gsbi6_uart_4pins>;
+ status = "okay";
+};
- dsi-phy@4700200 {
- status = "okay";
- vddio-supply = <&pm8921_lvs7>;/*VDD_PLL2_1 to 7*/
+&gsbi7 {
+ qcom,mode = <GSBI_PROT_I2C_UART>;
+ status = "okay";
+};
+
+&gsbi7_serial {
+ status = "okay";
+};
+
+&mdp {
+ status = "okay";
+};
+
+/* eMMC */
+&sdcc1 {
+ vmmc-supply = <&pm8921_l5>;
+ vqmmc-supply = <&pm8921_s4>;
+ status = "okay";
+};
+
+&mdp_dsi1_out {
+ remote-endpoint = <&dsi0_in>;
+};
+
+&rpm {
+ regulators {
+ vdd_l1_l2_l12_l18-supply = <&pm8921_s4>;
+ vin_lvs1_3_6-supply = <&pm8921_s4>;
+ vin_lvs4_5_7-supply = <&pm8921_s4>;
+
+
+ vdd_l24-supply = <&pm8921_s1>;
+ vdd_l25-supply = <&pm8921_s1>;
+ vin_lvs2-supply = <&pm8921_s1>;
+
+ vdd_l26-supply = <&pm8921_s7>;
+ vdd_l27-supply = <&pm8921_s7>;
+ vdd_l28-supply = <&pm8921_s7>;
+
+ vdd_ncp-supply = <&pm8921_l6>;
+
+ /* Buck SMPS */
+ s1 {
+ regulator-always-on;
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ qcom,switch-mode-frequency = <3200000>;
+ bias-pull-down;
};
- gsbi@16200000 {
- status = "okay";
- qcom,mode = <GSBI_PROT_I2C>;
- i2c@16280000 {
- status = "okay";
- clock-frequency = <200000>;
- pinctrl-0 = <&i2c3_pins>;
- pinctrl-names = "default";
-
- trackpad@10 {
- compatible = "elan,ekth3500";
- reg = <0x10>;
- interrupt-parent = <&tlmm_pinmux>;
- interrupts = <6 IRQ_TYPE_EDGE_FALLING>;
- };
- };
+ /* msm otg HSUSB_VDDCX */
+ s3 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1150000>;
+ qcom,switch-mode-frequency = <4800000>;
};
+ /*
+ * msm_sdcc.1-sdc-vdd_io
+ * tabla2x-slim-CDC_VDDA_RX
+ * tabla2x-slim-CDC_VDDA_TX
+ * tabla2x-slim-CDC_VDD_CP
+ * tabla2x-slim-VDDIO_CDC
+ */
+ s4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,switch-mode-frequency = <3200000>;
+ regulator-always-on;
+ };
- gsbi@12440000 {
- status = "okay";
- qcom,mode = <GSBI_PROT_I2C>;
+ s7 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ qcom,switch-mode-frequency = <3200000>;
+ };
- i2c@12460000 {
- status = "okay";
- clock-frequency = <200000>;
- pinctrl-0 = <&i2c1_pins>;
- pinctrl-names = "default";
+ /* mipi_dsi.1-dsi1_pll_vdda */
+ l2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ };
- eeprom@52 {
- compatible = "atmel,24c128";
- reg = <0x52>;
- pagesize = <32>;
- };
+ /* msm_otg-HSUSB_3p3 */
+ l3 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ bias-pull-down;
+ };
- bq27541@55 {
- compatible = "ti,bq27541";
- reg = <0x55>;
- };
+ /* msm_otg-HSUSB_1p8 */
+ l4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ bias-pull-down;
+ };
- };
+ /* msm_sdcc.1-sdc_vdd */
+ l5 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-always-on;
+ bias-pull-down;
};
- gsbi@16500000 {
- status = "okay";
- qcom,mode = <GSBI_PROT_I2C_UART>;
+ l6 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ };
- serial@16540000 {
- status = "okay";
+ /* mipi_dsi.1-dsi1_avdd */
+ l11 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ bias-pull-down;
+ regulator-always-on;
+ };
- pinctrl-names = "default";
- pinctrl-0 = <&gsbi6_uart_4pins>;
- };
+ /* pwm_power for backlight */
+ l17 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-always-on;
};
- gsbi@16600000 {
- status = "okay";
- qcom,mode = <GSBI_PROT_I2C_UART>;
- serial@16640000 {
- status = "okay";
- };
+ /* camera, qdsp6 */
+ l23 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ bias-pull-down;
};
- /* OTG */
- usb@12500000 {
- status = "okay";
- dr_mode = "otg";
- ulpi {
- phy {
- v3p3-supply = <&pm8921_l3>;
- v1p8-supply = <&pm8921_l4>;
- };
- };
+ /*
+ * tabla2x-slim-CDC_VDDA_A_1P2V
+ * tabla2x-slim-VDDD_CDC_D
+ */
+ l25 {
+ regulator-min-microvolt = <1250000>;
+ regulator-max-microvolt = <1250000>;
+ bias-pull-down;
};
- amba {
- /* eMMC */
- mmc@12400000 {
- status = "okay";
- vmmc-supply = <&pm8921_l5>;
- vqmmc-supply = <&pm8921_s4>;
- };
+ lvs1 {
+ bias-pull-down;
};
- sram@2a03f000 {
- compatible = "qcom,apq8064-imem", "syscon", "simple-mfd";
- reg = <0x2a03f000 0x1000>;
+ lvs4 {
+ bias-pull-down;
+ };
- reboot-mode {
- compatible = "syscon-reboot-mode";
- offset = <0x65c>;
+ lvs5 {
+ bias-pull-down;
+ };
- mode-normal = <0x77665501>;
- mode-bootloader = <0x77665500>;
- mode-recovery = <0x77665502>;
- };
+ lvs6 {
+ bias-pull-down;
+ };
+ /*
+ * mipi_dsi.1-dsi1_vddio
+ * pil_riva-pll_vdd
+ */
+ lvs7 {
+ bias-pull-down;
};
};
};
+
+&usb_hs1_phy {
+ v3p3-supply = <&pm8921_l3>;
+ v1p8-supply = <&pm8921_l4>;
+};
+
+/* OTG */
+&usb1 {
+ dr_mode = "otg";
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts b/arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts
index 529629a0a9dc..d6ecfd8addb7 100644
--- a/arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts
+++ b/arch/arm/boot/dts/qcom-apq8064-cm-qs600.dts
@@ -15,232 +15,216 @@
stdout-path = "serial0:115200n8";
};
- pwrseq {
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
- compatible = "simple-bus";
-
- sdcc4_pwrseq: sdcc4_pwrseq {
- pinctrl-names = "default";
- pinctrl-0 = <&wlan_default_gpios>;
- compatible = "mmc-pwrseq-simple";
- reset-gpios = <&pm8921_gpio 43 GPIO_ACTIVE_LOW>;
- };
+ sdcc4_pwrseq: pwrseq-sdcc4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&wlan_default_gpios>;
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&pm8921_gpio 43 GPIO_ACTIVE_LOW>;
};
- soc {
- pinctrl@800000 {
- card_detect: card_detect {
- mux {
- pins = "gpio26";
- function = "gpio";
- bias-disable;
- };
- };
-
- pcie_pins: pcie_pinmux {
- mux {
- pins = "gpio27";
- function = "gpio";
- };
- conf {
- pins = "gpio27";
- drive-strength = <12>;
- bias-disable;
- };
- };
- };
+ /* on board fixed 3.3v supply */
+ v3p3_fixed: regulator-v3p3 {
+ compatible = "regulator-fixed";
+ regulator-name = "PCIE V3P3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+};
- rpm@108000 {
- regulators {
- vin_lvs1_3_6-supply = <&pm8921_s4>;
- vin_lvs2-supply = <&pm8921_s1>;
- vin_lvs4_5_7-supply = <&pm8921_s4>;
-
- vdd_l1_l2_l12_l18-supply = <&pm8921_s4>;
- vdd_l24-supply = <&pm8921_s1>;
- vdd_l25-supply = <&pm8921_s1>;
- vdd_l26-supply = <&pm8921_s7>;
- vdd_l27-supply = <&pm8921_s7>;
- vdd_l28-supply = <&pm8921_s7>;
-
-
- /* Buck SMPS */
- s1 {
- regulator-always-on;
- regulator-min-microvolt = <1225000>;
- regulator-max-microvolt = <1225000>;
- qcom,switch-mode-frequency = <3200000>;
- bias-pull-down;
- };
-
- s3 {
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1400000>;
- qcom,switch-mode-frequency = <4800000>;
- };
-
- s4 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,switch-mode-frequency = <3200000>;
- };
-
- s7 {
- regulator-min-microvolt = <1300000>;
- regulator-max-microvolt = <1300000>;
- qcom,switch-mode-frequency = <3200000>;
- };
-
- l3 {
- regulator-min-microvolt = <3050000>;
- regulator-max-microvolt = <3300000>;
- bias-pull-down;
- };
-
- l4 {
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1800000>;
- bias-pull-down;
- };
-
- l5 {
- regulator-min-microvolt = <2750000>;
- regulator-max-microvolt = <3000000>;
- bias-pull-down;
- };
-
- l23 {
- regulator-min-microvolt = <1700000>;
- regulator-max-microvolt = <1900000>;
- bias-pull-down;
- };
-
- pm8921_lvs6: lvs6 {
- bias-pull-down;
- };
-
- };
- };
+&gsbi1 {
+ qcom,mode = <GSBI_PROT_I2C>;
+ status = "okay";
+};
- gsbi@12440000 {
- status = "okay";
- qcom,mode = <GSBI_PROT_I2C>;
+&gsbi1_i2c {
+ clock-frequency = <200000>;
+ status = "okay";
- i2c@12460000 {
- status = "okay";
- clock-frequency = <200000>;
+ eeprom@50 {
+ compatible = "atmel,24c02";
+ reg = <0x50>;
+ pagesize = <32>;
+ };
+};
+
+&gsbi7 {
+ qcom,mode = <GSBI_PROT_I2C_UART>;
+ status = "okay";
+};
- eeprom@50 {
- compatible = "atmel,24c02";
- reg = <0x50>;
- pagesize = <32>;
- };
- };
+&gsbi7_serial {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gsbi7_uart_2pins>;
+ status = "okay";
+};
+
+&pcie {
+ vdda-supply = <&pm8921_s3>;
+ vdda_phy-supply = <&pm8921_lvs6>;
+ vdda_refclk-supply = <&v3p3_fixed>;
+ pinctrl-0 = <&pcie_pins>;
+ pinctrl-names = "default";
+ perst-gpios = <&tlmm_pinmux 27 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&pm8921_gpio {
+ wlan_default_gpios: wlan-gpios-state {
+ pinconf {
+ pins = "gpio43";
+ function = "normal";
+ bias-disable;
+ power-source = <PM8921_GPIO_S4>;
};
+ };
+};
+
+&rpm {
+ regulators {
+ vin_lvs1_3_6-supply = <&pm8921_s4>;
+ vin_lvs2-supply = <&pm8921_s1>;
+ vin_lvs4_5_7-supply = <&pm8921_s4>;
+
+ vdd_l1_l2_l12_l18-supply = <&pm8921_s4>;
+ vdd_l24-supply = <&pm8921_s1>;
+ vdd_l25-supply = <&pm8921_s1>;
+ vdd_l26-supply = <&pm8921_s7>;
+ vdd_l27-supply = <&pm8921_s7>;
+ vdd_l28-supply = <&pm8921_s7>;
+
- gsbi@16600000 {
- status = "okay";
- qcom,mode = <GSBI_PROT_I2C_UART>;
- serial@16640000 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&gsbi7_uart_2pins>;
- };
+ /* Buck SMPS */
+ s1 {
+ regulator-always-on;
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ qcom,switch-mode-frequency = <3200000>;
+ bias-pull-down;
};
- /* OTG */
- usb@12500000 {
- status = "okay";
- dr_mode = "otg";
- ulpi {
- phy {
- v3p3-supply = <&pm8921_l3>;
- v1p8-supply = <&pm8921_l4>;
- };
- };
+ s3 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1400000>;
+ qcom,switch-mode-frequency = <4800000>;
};
- usb@12520000 {
- status = "okay";
- dr_mode = "host";
- ulpi {
- phy {
- v3p3-supply = <&pm8921_l3>;
- v1p8-supply = <&pm8921_l23>;
- };
- };
+ s4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,switch-mode-frequency = <3200000>;
};
- usb@12530000 {
- status = "okay";
- dr_mode = "host";
- ulpi {
- phy {
- v3p3-supply = <&pm8921_l3>;
- v1p8-supply = <&pm8921_l23>;
- };
- };
+ s7 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ qcom,switch-mode-frequency = <3200000>;
};
- /* on board fixed 3.3v supply */
- v3p3_fixed: v3p3 {
- compatible = "regulator-fixed";
- regulator-name = "PCIE V3P3";
- regulator-min-microvolt = <3300000>;
+ l3 {
+ regulator-min-microvolt = <3050000>;
regulator-max-microvolt = <3300000>;
- regulator-always-on;
+ bias-pull-down;
+ };
+
+ l4 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1800000>;
+ bias-pull-down;
+ };
+
+ l5 {
+ regulator-min-microvolt = <2750000>;
+ regulator-max-microvolt = <3000000>;
+ bias-pull-down;
};
- qcom,ssbi@500000 {
- pmic@0 {
- gpio@150 {
- wlan_default_gpios: wlan-gpios-state {
- pinconf {
- pins = "gpio43";
- function = "normal";
- bias-disable;
- power-source = <PM8921_GPIO_S4>;
- };
- };
- };
- };
+ l23 {
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <1900000>;
+ bias-pull-down;
};
- pci@1b500000 {
- status = "okay";
- vdda-supply = <&pm8921_s3>;
- vdda_phy-supply = <&pm8921_lvs6>;
- vdda_refclk-supply = <&v3p3_fixed>;
- pinctrl-0 = <&pcie_pins>;
- pinctrl-names = "default";
- perst-gpios = <&tlmm_pinmux 27 GPIO_ACTIVE_LOW>;
+ lvs6 {
+ bias-pull-down;
};
- amba {
- /* eMMC */
- sdcc1: mmc@12400000 {
- status = "okay";
- vmmc-supply = <&pm8921_l5>;
- vqmmc-supply = <&pm8921_s4>;
- };
-
- /* External micro SD card */
- sdcc3: mmc@12180000 {
- status = "okay";
- vmmc-supply = <&v3p3_fixed>;
- pinctrl-names = "default";
- pinctrl-0 = <&card_detect>;
- cd-gpios = <&tlmm_pinmux 26 GPIO_ACTIVE_LOW>;
- };
- /* WLAN */
- sdcc4: mmc@121c0000 {
- status = "okay";
- vmmc-supply = <&v3p3_fixed>;
- vqmmc-supply = <&v3p3_fixed>;
- mmc-pwrseq = <&sdcc4_pwrseq>;
- };
+ };
+};
+
+/* eMMC */
+&sdcc1 {
+ vmmc-supply = <&pm8921_l5>;
+ vqmmc-supply = <&pm8921_s4>;
+ status = "okay";
+};
+
+/* External micro SD card */
+&sdcc3 {
+ vmmc-supply = <&v3p3_fixed>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&card_detect>;
+ cd-gpios = <&tlmm_pinmux 26 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+/* WLAN */
+&sdcc4 {
+ status = "okay";
+ vmmc-supply = <&v3p3_fixed>;
+ vqmmc-supply = <&v3p3_fixed>;
+ mmc-pwrseq = <&sdcc4_pwrseq>;
+};
+
+&tlmm_pinmux {
+ card_detect: card_detect {
+ mux {
+ pins = "gpio26";
+ function = "gpio";
+ bias-disable;
+ };
+ };
+
+ pcie_pins: pcie_pinmux {
+ mux {
+ pins = "gpio27";
+ function = "gpio";
+ };
+ conf {
+ pins = "gpio27";
+ drive-strength = <12>;
+ bias-disable;
};
};
};
+
+&usb_hs1_phy {
+ v3p3-supply = <&pm8921_l3>;
+ v1p8-supply = <&pm8921_l4>;
+};
+
+&usb_hs3_phy {
+ v3p3-supply = <&pm8921_l3>;
+ v1p8-supply = <&pm8921_l23>;
+};
+
+&usb_hs4_phy {
+ v3p3-supply = <&pm8921_l3>;
+ v1p8-supply = <&pm8921_l23>;
+};
+
+/* OTG */
+&usb1 {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&usb3 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usb4 {
+ dr_mode = "host";
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts b/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts
index a7f90217661b..96307550523a 100644
--- a/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts
+++ b/arch/arm/boot/dts/qcom-apq8064-ifc6410.dts
@@ -22,23 +22,12 @@
stdout-path = "serial0:115200n8";
};
- pwrseq {
- compatible = "simple-bus";
-
- sdcc4_pwrseq: sdcc4_pwrseq {
- pinctrl-names = "default";
- pinctrl-0 = <&wlan_default_gpios>;
- compatible = "mmc-pwrseq-simple";
- reset-gpios = <&pm8921_gpio 43 GPIO_ACTIVE_LOW>;
- };
- };
-
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
pinctrl-0 = <&notify_led>;
- led@1 {
+ led-user1 {
label = "apq8064:green:user1";
color = <LED_COLOR_ID_GREEN>;
gpios = <&pm8921_gpio 18 GPIO_ACTIVE_HIGH>;
@@ -57,326 +46,314 @@
};
};
- soc {
- pinctrl@800000 {
- card_detect: card_detect {
- mux {
- pins = "gpio26";
- function = "gpio";
- bias-disable;
- };
- };
+ sdcc4_pwrseq: pwrseq-sdcc4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&wlan_default_gpios>;
+ compatible = "mmc-pwrseq-simple";
+ reset-gpios = <&pm8921_gpio 43 GPIO_ACTIVE_LOW>;
+ };
- pcie_pins: pcie_pinmux {
- mux {
- pins = "gpio27";
- function = "gpio";
- };
- conf {
- pins = "gpio27";
- drive-strength = <12>;
- bias-disable;
- };
- };
- };
+ ext_3p3v: regulator-ext-3p3v {
+ compatible = "regulator-fixed";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "ext_3p3v";
+ regulator-type = "voltage";
+ startup-delay-us = <0>;
+ gpio = <&tlmm_pinmux 77 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-boot-on;
+ };
+};
- rpm@108000 {
- regulators {
- vin_lvs1_3_6-supply = <&pm8921_s4>;
- vin_lvs2-supply = <&pm8921_s1>;
- vin_lvs4_5_7-supply = <&pm8921_s4>;
-
- vdd_l1_l2_l12_l18-supply = <&pm8921_s4>;
- vdd_l24-supply = <&pm8921_s1>;
- vdd_l25-supply = <&pm8921_s1>;
- vdd_l26-supply = <&pm8921_s7>;
- vdd_l27-supply = <&pm8921_s7>;
- vdd_l28-supply = <&pm8921_s7>;
-
-
- /* Buck SMPS */
- s1 {
- regulator-always-on;
- regulator-min-microvolt = <1225000>;
- regulator-max-microvolt = <1225000>;
- qcom,switch-mode-frequency = <3200000>;
- bias-pull-down;
- };
-
- s3 {
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1400000>;
- qcom,switch-mode-frequency = <4800000>;
- };
-
- s4 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,switch-mode-frequency = <3200000>;
- };
-
- s7 {
- regulator-min-microvolt = <1300000>;
- regulator-max-microvolt = <1300000>;
- qcom,switch-mode-frequency = <3200000>;
- };
-
- l3 {
- regulator-min-microvolt = <3050000>;
- regulator-max-microvolt = <3300000>;
- bias-pull-down;
- };
-
- l4 {
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1800000>;
- bias-pull-down;
- };
-
- l5 {
- regulator-min-microvolt = <2750000>;
- regulator-max-microvolt = <3000000>;
- bias-pull-down;
- };
-
- l6 {
- regulator-min-microvolt = <2950000>;
- regulator-max-microvolt = <2950000>;
- bias-pull-down;
- };
-
- l23 {
- regulator-min-microvolt = <1700000>;
- regulator-max-microvolt = <1900000>;
- bias-pull-down;
- };
-
- lvs1 {
- bias-pull-down;
- };
-
- lvs6 {
- bias-pull-down;
- };
- };
- };
+&gsbi1 {
+ qcom,mode = <GSBI_PROT_I2C>;
+ status = "okay";
+};
- ext_3p3v: regulator-fixed@1 {
- compatible = "regulator-fixed";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-name = "ext_3p3v";
- regulator-type = "voltage";
- startup-delay-us = <0>;
- gpio = <&tlmm_pinmux 77 GPIO_ACTIVE_HIGH>;
- enable-active-high;
- regulator-boot-on;
- };
+&gsbi1_i2c {
+ clock-frequency = <200000>;
+ status = "okay";
- gsbi3: gsbi@16200000 {
- status = "okay";
- qcom,mode = <GSBI_PROT_I2C>;
- i2c@16280000 {
- status = "okay";
- };
- };
+ eeprom@52 {
+ compatible = "atmel,24c128";
+ reg = <0x52>;
+ pagesize = <32>;
+ };
+};
- gsbi@16300000 {
- status = "okay";
- qcom,mode = <GSBI_PROT_I2C>;
- /* CAM I2C MIPI-CSI connector */
- i2c@16380000 {
- status = "okay";
- };
- };
+&gsbi3 {
+ qcom,mode = <GSBI_PROT_I2C>;
+ status = "okay";
+};
+
+&gsbi3_i2c {
+ status = "okay";
+};
- gsbi@12440000 {
- status = "okay";
- qcom,mode = <GSBI_PROT_I2C>;
+&gsbi4 {
+ qcom,mode = <GSBI_PROT_I2C>;
+ status = "okay";
+};
- i2c@12460000 {
- status = "okay";
- clock-frequency = <200000>;
+/* CAM I2C MIPI-CSI connector */
+&gsbi4_i2c {
+ status = "okay";
+};
- eeprom@52 {
- compatible = "atmel,24c128";
- reg = <0x52>;
- pagesize = <32>;
- };
- };
- };
+&gsbi5 {
+ qcom,mode = <GSBI_PROT_SPI>;
+ status = "okay";
+};
- gsbi@1a200000 {
- qcom,mode = <GSBI_PROT_SPI>;
- status = "okay";
- spi4: spi@1a280000 {
- status = "okay";
- num-cs = <1>;
- cs-gpios = <&tlmm_pinmux 53 0>;
- };
- };
+&gsbi5_spi {
+ num-cs = <1>;
+ cs-gpios = <&tlmm_pinmux 53 0>;
+ status = "okay";
+};
+
+&gsbi6 {
+ qcom,mode = <GSBI_PROT_UART_W_FC>;
+ status = "okay";
+};
- gsbi@16500000 {
- status = "okay";
- qcom,mode = <GSBI_PROT_UART_W_FC>;
+&gsbi6_serial {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gsbi6_uart_4pins>;
+ status = "okay";
+};
- serial@16540000 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&gsbi6_uart_4pins>;
- };
+&gsbi7 {
+ qcom,mode = <GSBI_PROT_I2C_UART>;
+ status = "okay";
+};
+
+&gsbi7_serial {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gsbi7_uart_2pins>;
+ status = "okay";
+};
+
+&hdmi {
+ core-vdda-supply = <&pm8921_hdmi_switch>;
+ hpd-gpios = <&tlmm_pinmux 72 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+};
+
+&hdmi_in {
+ remote-endpoint = <&mdp_dtv_out>;
+};
+
+&hdmi_out {
+ remote-endpoint = <&hdmi_con>;
+};
+
+&hdmi_phy {
+ status = "okay";
+ core-vdda-supply = <&pm8921_hdmi_switch>;
+};
+
+&mdp {
+ status = "okay";
+};
+
+&mdp_dtv_out {
+ remote-endpoint = <&hdmi_in>;
+};
+
+&pcie {
+ status = "okay";
+ vdda-supply = <&pm8921_s3>;
+ vdda_phy-supply = <&pm8921_lvs6>;
+ vdda_refclk-supply = <&ext_3p3v>;
+ pinctrl-0 = <&pcie_pins>;
+ pinctrl-names = "default";
+ perst-gpios = <&tlmm_pinmux 27 GPIO_ACTIVE_LOW>;
+};
+
+&pm8921_gpio {
+ wlan_default_gpios: wlan-gpios-state {
+ pinconf {
+ pins = "gpio43";
+ function = "normal";
+ bias-disable;
+ power-source = <PM8921_GPIO_S4>;
};
+ };
- gsbi@16600000 {
- status = "okay";
- qcom,mode = <GSBI_PROT_I2C_UART>;
- serial@16640000 {
- status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&gsbi7_uart_2pins>;
- };
+ notify_led: nled-state {
+ pinconf {
+ pins = "gpio18";
+ function = "normal";
+ bias-disable;
+ power-source = <PM8921_GPIO_S4>;
};
+ };
+};
- sata_phy0: phy@1b400000 {
- status = "okay";
+&rpm {
+ regulators {
+ vin_lvs1_3_6-supply = <&pm8921_s4>;
+ vin_lvs2-supply = <&pm8921_s1>;
+ vin_lvs4_5_7-supply = <&pm8921_s4>;
+
+ vdd_l1_l2_l12_l18-supply = <&pm8921_s4>;
+ vdd_l24-supply = <&pm8921_s1>;
+ vdd_l25-supply = <&pm8921_s1>;
+ vdd_l26-supply = <&pm8921_s7>;
+ vdd_l27-supply = <&pm8921_s7>;
+ vdd_l28-supply = <&pm8921_s7>;
+
+
+ /* Buck SMPS */
+ s1 {
+ regulator-always-on;
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ qcom,switch-mode-frequency = <3200000>;
+ bias-pull-down;
};
- sata0: sata@29000000 {
- status = "okay";
- target-supply = <&pm8921_s4>;
+ s3 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1400000>;
+ qcom,switch-mode-frequency = <4800000>;
};
- /* OTG */
- usb@12500000 {
- status = "okay";
- dr_mode = "otg";
- ulpi {
- phy {
- v3p3-supply = <&pm8921_l3>;
- v1p8-supply = <&pm8921_l4>;
- };
- };
+ s4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,switch-mode-frequency = <3200000>;
};
- usb@12520000 {
- status = "okay";
- dr_mode = "host";
- ulpi {
- phy {
- v3p3-supply = <&pm8921_l3>;
- v1p8-supply = <&pm8921_l23>;
- };
- };
+ s7 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ qcom,switch-mode-frequency = <3200000>;
};
- usb@12530000 {
- status = "okay";
- dr_mode = "host";
- ulpi {
- phy {
- v3p3-supply = <&pm8921_l3>;
- v1p8-supply = <&pm8921_l23>;
- };
- };
+ l3 {
+ regulator-min-microvolt = <3050000>;
+ regulator-max-microvolt = <3300000>;
+ bias-pull-down;
};
- pci@1b500000 {
- status = "okay";
- vdda-supply = <&pm8921_s3>;
- vdda_phy-supply = <&pm8921_lvs6>;
- vdda_refclk-supply = <&ext_3p3v>;
- pinctrl-0 = <&pcie_pins>;
- pinctrl-names = "default";
- perst-gpios = <&tlmm_pinmux 27 GPIO_ACTIVE_LOW>;
+ l4 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1800000>;
+ bias-pull-down;
};
- qcom,ssbi@500000 {
- pmic@0 {
- gpio@150 {
- wlan_default_gpios: wlan-gpios-state {
- pinconf {
- pins = "gpio43";
- function = "normal";
- bias-disable;
- power-source = <PM8921_GPIO_S4>;
- };
- };
-
- notify_led: nled-state {
- pinconf {
- pins = "gpio18";
- function = "normal";
- bias-disable;
- power-source = <PM8921_GPIO_S4>;
- };
- };
- };
- };
+ l5 {
+ regulator-min-microvolt = <2750000>;
+ regulator-max-microvolt = <3000000>;
+ bias-pull-down;
};
- amba {
- /* eMMC */
- sdcc1: mmc@12400000 {
- status = "okay";
- vmmc-supply = <&pm8921_l5>;
- vqmmc-supply = <&pm8921_s4>;
- };
+ l6 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ bias-pull-down;
+ };
- /* External micro SD card */
- sdcc3: mmc@12180000 {
- status = "okay";
- vmmc-supply = <&pm8921_l6>;
- pinctrl-names = "default";
- pinctrl-0 = <&card_detect>;
- cd-gpios = <&tlmm_pinmux 26 GPIO_ACTIVE_LOW>;
- };
- /* WLAN */
- sdcc4: mmc@121c0000 {
- status = "okay";
- vmmc-supply = <&ext_3p3v>;
- vqmmc-supply = <&pm8921_lvs1>;
- mmc-pwrseq = <&sdcc4_pwrseq>;
- };
+ l23 {
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <1900000>;
+ bias-pull-down;
};
- hdmi-tx@4a00000 {
- status = "okay";
+ lvs1 {
+ bias-pull-down;
+ };
- core-vdda-supply = <&pm8921_hdmi_switch>;
+ lvs6 {
+ bias-pull-down;
+ };
+ };
+};
- hpd-gpios = <&tlmm_pinmux 72 GPIO_ACTIVE_HIGH>;
+&sata_phy0 {
+ status = "okay";
+};
- ports {
- port@0 {
- endpoint {
- remote-endpoint = <&mdp_dtv_out>;
- };
- };
+&sata0 {
+ target-supply = <&pm8921_s4>;
+ status = "okay";
+};
- port@1 {
- endpoint {
- remote-endpoint = <&hdmi_con>;
- };
- };
- };
- };
+/* eMMC */
+&sdcc1 {
+ vmmc-supply = <&pm8921_l5>;
+ vqmmc-supply = <&pm8921_s4>;
+ status = "okay";
+};
- hdmi-phy@4a00400 {
- status = "okay";
+/* External micro SD card */
+&sdcc3 {
+ vmmc-supply = <&pm8921_l6>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&card_detect>;
+ cd-gpios = <&tlmm_pinmux 26 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
- core-vdda-supply = <&pm8921_hdmi_switch>;
- };
+/* WLAN */
+&sdcc4 {
+ vmmc-supply = <&ext_3p3v>;
+ vqmmc-supply = <&pm8921_lvs1>;
+ mmc-pwrseq = <&sdcc4_pwrseq>;
+ status = "okay";
+};
- mdp@5100000 {
- status = "okay";
+&tlmm_pinmux {
+ card_detect: card_detect {
+ mux {
+ pins = "gpio26";
+ function = "gpio";
+ bias-disable;
+ };
+ };
- ports {
- port@3 {
- endpoint {
- remote-endpoint = <&hdmi_in>;
- };
- };
- };
+ pcie_pins: pcie_pinmux {
+ mux {
+ pins = "gpio27";
+ function = "gpio";
+ };
+ conf {
+ pins = "gpio27";
+ drive-strength = <12>;
+ bias-disable;
};
};
};
+
+&usb_hs1_phy {
+ v3p3-supply = <&pm8921_l3>;
+ v1p8-supply = <&pm8921_l4>;
+};
+
+&usb_hs3_phy {
+ v3p3-supply = <&pm8921_l3>;
+ v1p8-supply = <&pm8921_l23>;
+};
+
+&usb_hs4_phy {
+ v3p3-supply = <&pm8921_l3>;
+ v1p8-supply = <&pm8921_l23>;
+};
+
+/* OTG */
+&usb1 {
+ dr_mode = "otg";
+ status = "okay";
+};
+
+&usb3 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usb4 {
+ dr_mode = "host";
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom-apq8064-sony-xperia-lagan-yuga.dts b/arch/arm/boot/dts/qcom-apq8064-sony-xperia-lagan-yuga.dts
index c07c5474750d..9244512b74d1 100644
--- a/arch/arm/boot/dts/qcom-apq8064-sony-xperia-lagan-yuga.dts
+++ b/arch/arm/boot/dts/qcom-apq8064-sony-xperia-lagan-yuga.dts
@@ -8,6 +8,7 @@
/ {
model = "Sony Xperia Z";
compatible = "sony,xperia-yuga", "qcom,apq8064";
+ chassis-type = "handset";
aliases {
serial0 = &gsbi5_serial;
@@ -51,351 +52,338 @@
linux,code = <KEY_VOLUMEUP>;
};
};
+};
+
+&gsbi5 {
+ qcom,mode = <GSBI_PROT_I2C_UART>;
+ status = "okay";
+};
+
+&gsbi5_serial {
+ pinctrl-names = "default";
+ pinctrl-0 = <&gsbi5_uart_pin_a>;
+ status = "okay";
+};
+
+&pm8921_gpio {
+ gpio_keys_pin_a: gpio-keys-active-state {
+ pins = "gpio3", "gpio4", "gpio29", "gpio35";
+ function = "normal";
+
+ bias-pull-up;
+ drive-push-pull;
+ input-enable;
+ power-source = <2>;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
+ qcom,pull-up-strength = <0>;
+ };
+};
+
+&riva {
+ pinctrl-names = "default";
+ pinctrl-0 = <&riva_wlan_pin_a>, <&riva_bt_pin_a>, <&riva_fm_pin_a>;
+ status = "okay";
+};
+
+&rpm {
+ regulators {
+ vin_l1_l2_l12_l18-supply = <&pm8921_s4>;
+ vin_lvs_1_3_6-supply = <&pm8921_s4>;
+ vin_lvs_4_5_7-supply = <&pm8921_s4>;
+ vin_ncp-supply = <&pm8921_l6>;
+ vin_lvs2-supply = <&pm8921_s4>;
+ vin_l24-supply = <&pm8921_s1>;
+ vin_l25-supply = <&pm8921_s1>;
+ vin_l27-supply = <&pm8921_s7>;
+ vin_l28-supply = <&pm8921_s7>;
+
+ /* Buck SMPS */
+ s1 {
+ regulator-always-on;
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ qcom,switch-mode-frequency = <3200000>;
+ bias-pull-down;
+ };
+
+ s2 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ qcom,switch-mode-frequency = <1600000>;
+ bias-pull-down;
+ };
+
+ s3 {
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1150000>;
+ qcom,switch-mode-frequency = <4800000>;
+ bias-pull-down;
+ };
+
+ s4 {
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,switch-mode-frequency = <1600000>;
+ bias-pull-down;
+ qcom,force-mode = <QCOM_RPM_FORCE_MODE_AUTO>;
+ };
+
+ s7 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ qcom,switch-mode-frequency = <3200000>;
+ };
+
+ s8 {
+ regulator-min-microvolt = <2200000>;
+ regulator-max-microvolt = <2200000>;
+ qcom,switch-mode-frequency = <1600000>;
+ };
+
+ /* PMOS LDO */
+ l1 {
+ regulator-always-on;
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ bias-pull-down;
+ };
- soc {
- pinctrl@800000 {
- gsbi5_uart_pin_a: gsbi5-uart-pin-active {
- rx {
- pins = "gpio52";
- function = "gsbi5";
- drive-strength = <2>;
- bias-pull-up;
- };
-
- tx {
- pins = "gpio51";
- function = "gsbi5";
- drive-strength = <4>;
- bias-disable;
- };
- };
-
-
- sdcc3_cd_pin_a: sdcc3-cd-pin-active {
- pins = "gpio26";
- function = "gpio";
-
- drive-strength = <2>;
- bias-disable;
- };
- };
-
-
- rpm@108000 {
- regulators {
- vin_l1_l2_l12_l18-supply = <&pm8921_s4>;
- vin_lvs_1_3_6-supply = <&pm8921_s4>;
- vin_lvs_4_5_7-supply = <&pm8921_s4>;
- vin_ncp-supply = <&pm8921_l6>;
- vin_lvs2-supply = <&pm8921_s4>;
- vin_l24-supply = <&pm8921_s1>;
- vin_l25-supply = <&pm8921_s1>;
- vin_l27-supply = <&pm8921_s7>;
- vin_l28-supply = <&pm8921_s7>;
-
- /* Buck SMPS */
- s1 {
- regulator-always-on;
- regulator-min-microvolt = <1225000>;
- regulator-max-microvolt = <1225000>;
- qcom,switch-mode-frequency = <3200000>;
- bias-pull-down;
- };
-
- s2 {
- regulator-min-microvolt = <1300000>;
- regulator-max-microvolt = <1300000>;
- qcom,switch-mode-frequency = <1600000>;
- bias-pull-down;
- };
-
- s3 {
- regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <1150000>;
- qcom,switch-mode-frequency = <4800000>;
- bias-pull-down;
- };
-
- s4 {
- regulator-always-on;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,switch-mode-frequency = <1600000>;
- bias-pull-down;
- qcom,force-mode = <QCOM_RPM_FORCE_MODE_AUTO>;
- };
-
- s7 {
- regulator-min-microvolt = <1300000>;
- regulator-max-microvolt = <1300000>;
- qcom,switch-mode-frequency = <3200000>;
- };
-
- s8 {
- regulator-min-microvolt = <2200000>;
- regulator-max-microvolt = <2200000>;
- qcom,switch-mode-frequency = <1600000>;
- };
-
- /* PMOS LDO */
- l1 {
- regulator-always-on;
- regulator-min-microvolt = <1100000>;
- regulator-max-microvolt = <1100000>;
- bias-pull-down;
- };
-
- l2 {
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- bias-pull-down;
- };
-
- l3 {
- regulator-min-microvolt = <3075000>;
- regulator-max-microvolt = <3075000>;
- bias-pull-down;
- };
-
- l4 {
- regulator-always-on;
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- bias-pull-down;
- };
-
- l5 {
- regulator-min-microvolt = <2950000>;
- regulator-max-microvolt = <2950000>;
- bias-pull-down;
- };
-
- l6 {
- regulator-min-microvolt = <2950000>;
- regulator-max-microvolt = <2950000>;
- bias-pull-down;
- };
-
- l7 {
- regulator-min-microvolt = <1850000>;
- regulator-max-microvolt = <2950000>;
- bias-pull-down;
- };
-
- l8 {
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
- bias-pull-down;
- };
-
- l9 {
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- bias-pull-down;
- };
-
- l10 {
- regulator-min-microvolt = <2900000>;
- regulator-max-microvolt = <2900000>;
- bias-pull-down;
- };
-
- l11 {
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- bias-pull-down;
- };
-
- l12 {
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- bias-pull-down;
- };
-
- l14 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- bias-pull-down;
- };
-
- l15 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2950000>;
- bias-pull-down;
- };
-
- l16 {
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
- bias-pull-down;
- };
-
- l17 {
- regulator-min-microvolt = <2000000>;
- regulator-max-microvolt = <2000000>;
- bias-pull-down;
- };
-
- l18 {
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- bias-pull-down;
- };
-
- l21 {
- regulator-min-microvolt = <1050000>;
- regulator-max-microvolt = <1050000>;
- bias-pull-down;
- };
-
- l22 {
- regulator-min-microvolt = <2600000>;
- regulator-max-microvolt = <2600000>;
- bias-pull-down;
- };
-
- l23 {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- bias-pull-down;
- };
-
- l24 {
- regulator-min-microvolt = <750000>;
- regulator-max-microvolt = <1150000>;
- bias-pull-down;
- };
-
- l25 {
- regulator-always-on;
- regulator-min-microvolt = <1250000>;
- regulator-max-microvolt = <1250000>;
- bias-pull-down;
- };
-
- l27 {
- regulator-min-microvolt = <1100000>;
- regulator-max-microvolt = <1100000>;
- };
-
- l28 {
- regulator-min-microvolt = <1050000>;
- regulator-max-microvolt = <1050000>;
- bias-pull-down;
- };
-
- l29 {
- regulator-min-microvolt = <2000000>;
- regulator-max-microvolt = <2000000>;
- bias-pull-down;
- };
-
- /* Low Voltage Switch */
- lvs1 {
- bias-pull-down;
- };
-
- lvs2 {
- bias-pull-down;
- };
-
- lvs3 {
- bias-pull-down;
- };
-
- lvs4 {
- bias-pull-down;
- };
-
- lvs5 {
- bias-pull-down;
- };
-
- lvs6 {
- bias-pull-down;
- };
-
- lvs7 {
- bias-pull-down;
- };
-
- usb-switch {};
-
- hdmi-switch {};
-
- ncp {
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,switch-mode-frequency = <1600000>;
- };
- };
- };
-
- qcom,ssbi@500000 {
- pmic@0 {
- gpio@150 {
- gpio_keys_pin_a: gpio-keys-active-state {
- pins = "gpio3", "gpio4", "gpio29", "gpio35";
- function = "normal";
-
- bias-pull-up;
- drive-push-pull;
- input-enable;
- power-source = <2>;
- qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
- qcom,pull-up-strength = <0>;
- };
- };
- };
- };
-
- usb@12500000 {
- status = "okay";
- dr_mode = "otg";
- ulpi {
- phy {
- v3p3-supply = <&pm8921_l3>;
- v1p8-supply = <&pm8921_l4>;
- };
- };
+ l2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ bias-pull-down;
};
- gsbi@1a200000 {
- status = "okay";
- qcom,mode = <GSBI_PROT_I2C_UART>;
+ l3 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ bias-pull-down;
+ };
+
+ l4 {
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ bias-pull-down;
+ };
+
+ l5 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ bias-pull-down;
+ };
+
+ l6 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ bias-pull-down;
+ };
+
+ l7 {
+ regulator-min-microvolt = <1850000>;
+ regulator-max-microvolt = <2950000>;
+ bias-pull-down;
+ };
+
+ l8 {
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ bias-pull-down;
+ };
+
+ l9 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ bias-pull-down;
+ };
+
+ l10 {
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <2900000>;
+ bias-pull-down;
+ };
- serial@1a240000 {
- status = "okay";
+ l11 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ bias-pull-down;
+ };
+
+ l12 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ bias-pull-down;
+ };
- pinctrl-names = "default";
- pinctrl-0 = <&gsbi5_uart_pin_a>;
- };
+ l14 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ bias-pull-down;
};
- amba {
- sdcc1: mmc@12400000 {
- status = "okay";
+ l15 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ bias-pull-down;
+ };
- vmmc-supply = <&pm8921_l5>;
- vqmmc-supply = <&pm8921_s4>;
- };
+ l16 {
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ bias-pull-down;
+ };
- sdcc3: mmc@12180000 {
- status = "okay";
+ l17 {
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
+ bias-pull-down;
+ };
- vmmc-supply = <&pm8921_l6>;
- cd-gpios = <&tlmm_pinmux 26 GPIO_ACTIVE_LOW>;
+ l18 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ bias-pull-down;
+ };
- pinctrl-names = "default";
- pinctrl-0 = <&sdcc3_pins>, <&sdcc3_cd_pin_a>;
- };
+ l21 {
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ bias-pull-down;
};
- riva-pil@3204000 {
- status = "okay";
+ l22 {
+ regulator-min-microvolt = <2600000>;
+ regulator-max-microvolt = <2600000>;
+ bias-pull-down;
+ };
- pinctrl-names = "default";
- pinctrl-0 = <&riva_wlan_pin_a>, <&riva_bt_pin_a>, <&riva_fm_pin_a>;
+ l23 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ bias-pull-down;
+ };
+
+ l24 {
+ regulator-min-microvolt = <750000>;
+ regulator-max-microvolt = <1150000>;
+ bias-pull-down;
+ };
+
+ l25 {
+ regulator-always-on;
+ regulator-min-microvolt = <1250000>;
+ regulator-max-microvolt = <1250000>;
+ bias-pull-down;
+ };
+
+ l27 {
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ };
+
+ l28 {
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ bias-pull-down;
+ };
+
+ l29 {
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <2000000>;
+ bias-pull-down;
+ };
+
+ /* Low Voltage Switch */
+ lvs1 {
+ bias-pull-down;
+ };
+
+ lvs2 {
+ bias-pull-down;
+ };
+
+ lvs3 {
+ bias-pull-down;
+ };
+
+ lvs4 {
+ bias-pull-down;
+ };
+
+ lvs5 {
+ bias-pull-down;
+ };
+
+ lvs6 {
+ bias-pull-down;
+ };
+
+ lvs7 {
+ bias-pull-down;
+ };
+
+ usb-switch {};
+
+ hdmi-switch {};
+
+ ncp {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ qcom,switch-mode-frequency = <1600000>;
};
};
};
+
+&sdcc1 {
+ vmmc-supply = <&pm8921_l5>;
+ vqmmc-supply = <&pm8921_s4>;
+ status = "okay";
+};
+
+&sdcc3 {
+ vmmc-supply = <&pm8921_l6>;
+ cd-gpios = <&tlmm_pinmux 26 GPIO_ACTIVE_LOW>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdcc3_pins>, <&sdcc3_cd_pin_a>;
+
+ status = "okay";
+};
+
+&tlmm_pinmux {
+ gsbi5_uart_pin_a: gsbi5-uart-pin-active {
+ rx {
+ pins = "gpio52";
+ function = "gsbi5";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ tx {
+ pins = "gpio51";
+ function = "gsbi5";
+ drive-strength = <4>;
+ bias-disable;
+ };
+ };
+
+
+ sdcc3_cd_pin_a: sdcc3-cd-pin-active {
+ pins = "gpio26";
+ function = "gpio";
+
+ drive-strength = <2>;
+ bias-disable;
+ };
+};
+
+&usb_hs1_phy {
+ v3p3-supply = <&pm8921_l3>;
+ v1p8-supply = <&pm8921_l4>;
+};
+
+&usb1 {
+ dr_mode = "otg";
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom-apq8064.dtsi b/arch/arm/boot/dts/qcom-apq8064.dtsi
index 942aa2278355..0da9623ea084 100644
--- a/arch/arm/boot/dts/qcom-apq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8064.dtsi
@@ -672,7 +672,7 @@
reg = <0x00c00000 0x1000>;
qcom,controller-type = "pmic-arbiter";
- pm8821: pmic@1 {
+ pm8821: pmic {
compatible = "qcom,pm8821";
interrupt-parent = <&tlmm_pinmux>;
interrupts = <76 IRQ_TYPE_LEVEL_LOW>;
@@ -693,12 +693,12 @@
};
};
- qcom,ssbi@500000 {
+ ssbi@500000 {
compatible = "qcom,ssbi";
reg = <0x00500000 0x1000>;
qcom,controller-type = "pmic-arbiter";
- pmicintc: pmic@0 {
+ pmicintc: pmic {
compatible = "qcom,pm8921";
interrupt-parent = <&tlmm_pinmux>;
interrupts = <74 8>;
@@ -884,7 +884,7 @@
reg = <0x2011000 0x1000>;
};
- rpm@108000 {
+ rpm: rpm@108000 {
compatible = "qcom,rpm-apq8064";
reg = <0x108000 0x1000>;
qcom,ipc = <&l2cc 0x8 2>;
@@ -1085,15 +1085,21 @@
ports-implemented = <0x1>;
};
- /* Temporary fixed regulator */
- sdcc1bam: dma-controller@12402000{
- compatible = "qcom,bam-v1.3.0";
- reg = <0x12402000 0x8000>;
- interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&gcc SDC1_H_CLK>;
- clock-names = "bam_clk";
- #dma-cells = <1>;
- qcom,ee = <0>;
+ sdcc3: mmc@12180000 {
+ compatible = "arm,pl18x", "arm,primecell";
+ arm,primecell-periphid = <0x00051180>;
+ status = "disabled";
+ reg = <0x12180000 0x2000>;
+ interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc SDC3_CLK>, <&gcc SDC3_H_CLK>;
+ clock-names = "mclk", "apb_pclk";
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ max-frequency = <192000000>;
+ no-1-8-v;
+ dmas = <&sdcc3bam 2>, <&sdcc3bam 1>;
+ dma-names = "tx", "rx";
};
sdcc3bam: dma-controller@12182000{
@@ -1106,6 +1112,24 @@
qcom,ee = <0>;
};
+ sdcc4: mmc@121c0000 {
+ compatible = "arm,pl18x", "arm,primecell";
+ arm,primecell-periphid = <0x00051180>;
+ status = "disabled";
+ reg = <0x121c0000 0x2000>;
+ interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc SDC4_CLK>, <&gcc SDC4_H_CLK>;
+ clock-names = "mclk", "apb_pclk";
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ max-frequency = <48000000>;
+ dmas = <&sdcc4bam 2>, <&sdcc4bam 1>;
+ dma-names = "tx", "rx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdc4_gpios>;
+ };
+
sdcc4bam: dma-controller@121c2000{
compatible = "qcom,bam-v1.3.0";
reg = <0x121c2000 0x8000>;
@@ -1116,67 +1140,33 @@
qcom,ee = <0>;
};
- amba {
- compatible = "simple-bus";
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
- sdcc1: mmc@12400000 {
- status = "disabled";
- compatible = "arm,pl18x", "arm,primecell";
- pinctrl-names = "default";
- pinctrl-0 = <&sdcc1_pins>;
- arm,primecell-periphid = <0x00051180>;
- reg = <0x12400000 0x2000>;
- interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cmd_irq";
- clocks = <&gcc SDC1_CLK>, <&gcc SDC1_H_CLK>;
- clock-names = "mclk", "apb_pclk";
- bus-width = <8>;
- max-frequency = <96000000>;
- non-removable;
- cap-sd-highspeed;
- cap-mmc-highspeed;
- dmas = <&sdcc1bam 2>, <&sdcc1bam 1>;
- dma-names = "tx", "rx";
- };
-
- sdcc3: mmc@12180000 {
- compatible = "arm,pl18x", "arm,primecell";
- arm,primecell-periphid = <0x00051180>;
- status = "disabled";
- reg = <0x12180000 0x2000>;
- interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cmd_irq";
- clocks = <&gcc SDC3_CLK>, <&gcc SDC3_H_CLK>;
- clock-names = "mclk", "apb_pclk";
- bus-width = <4>;
- cap-sd-highspeed;
- cap-mmc-highspeed;
- max-frequency = <192000000>;
- no-1-8-v;
- dmas = <&sdcc3bam 2>, <&sdcc3bam 1>;
- dma-names = "tx", "rx";
- };
+ sdcc1: mmc@12400000 {
+ status = "disabled";
+ compatible = "arm,pl18x", "arm,primecell";
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdcc1_pins>;
+ arm,primecell-periphid = <0x00051180>;
+ reg = <0x12400000 0x2000>;
+ interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc SDC1_CLK>, <&gcc SDC1_H_CLK>;
+ clock-names = "mclk", "apb_pclk";
+ bus-width = <8>;
+ max-frequency = <96000000>;
+ non-removable;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ dmas = <&sdcc1bam 2>, <&sdcc1bam 1>;
+ dma-names = "tx", "rx";
+ };
- sdcc4: mmc@121c0000 {
- compatible = "arm,pl18x", "arm,primecell";
- arm,primecell-periphid = <0x00051180>;
- status = "disabled";
- reg = <0x121c0000 0x2000>;
- interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cmd_irq";
- clocks = <&gcc SDC4_CLK>, <&gcc SDC4_H_CLK>;
- clock-names = "mclk", "apb_pclk";
- bus-width = <4>;
- cap-sd-highspeed;
- cap-mmc-highspeed;
- max-frequency = <48000000>;
- dmas = <&sdcc4bam 2>, <&sdcc4bam 1>;
- dma-names = "tx", "rx";
- pinctrl-names = "default";
- pinctrl-0 = <&sdc4_gpios>;
- };
+ sdcc1bam: dma-controller@12402000{
+ compatible = "qcom,bam-v1.3.0";
+ reg = <0x12402000 0x8000>;
+ interrupts = <0 98 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc SDC1_H_CLK>;
+ clock-names = "bam_clk";
+ #dma-cells = <1>;
+ qcom,ee = <0>;
};
tcsr: syscon@1a400000 {
@@ -1316,7 +1306,6 @@
<&dsi0_phy 1>;
syscon-sfpb = <&mmss_sfpb>;
phys = <&dsi0_phy>;
- phy-names = "dsi";
status = "disabled";
ports {
@@ -1338,7 +1327,7 @@
};
- dsi0_phy: dsi-phy@4700200 {
+ dsi0_phy: phy@4700200 {
compatible = "qcom,dsi-phy-28nm-8960";
#clock-cells = <1>;
#phy-cells = <0>;
@@ -1470,6 +1459,8 @@
phys = <&hdmi_phy>;
+ status = "disabled";
+
ports {
#address-cells = <1>;
#size-cells = <0>;
@@ -1488,7 +1479,7 @@
};
};
- hdmi_phy: hdmi-phy@4a00400 {
+ hdmi_phy: phy@4a00400 {
compatible = "qcom,hdmi-phy-8960";
reg = <0x4a00400 0x60>,
<0x4a00500 0x100>;
@@ -1498,6 +1489,8 @@
clocks = <&mmcc HDMI_S_AHB_CLK>;
clock-names = "slave_iface";
#phy-cells = <0>;
+
+ status = "disabled";
};
mdp: mdp@5100000 {
@@ -1552,7 +1545,7 @@
};
};
- riva: riva-pil@3204000 {
+ riva: riva-pil@3200800 {
compatible = "qcom,riva-pil";
reg = <0x03200800 0x1000>, <0x03202000 0x2000>, <0x03204000 0x100>;
@@ -1615,7 +1608,7 @@
};
etb@1a01000 {
- compatible = "coresight-etb10", "arm,primecell";
+ compatible = "arm,coresight-etb10", "arm,primecell";
reg = <0x1a01000 0x1000>;
clocks = <&rpmcc RPM_QDSS_CLK>;
diff --git a/arch/arm/boot/dts/qcom-apq8074-dragonboard.dts b/arch/arm/boot/dts/qcom-apq8074-dragonboard.dts
index 91716298ec5e..1345df7cbd00 100644
--- a/arch/arm/boot/dts/qcom-apq8074-dragonboard.dts
+++ b/arch/arm/boot/dts/qcom-apq8074-dragonboard.dts
@@ -35,30 +35,8 @@
};
};
-&otg {
- status = "okay";
-
- phys = <&usb_hs2_phy>;
- phy-select = <&tcsr 0xb000 1>;
- extcon = <&smbb>, <&usb_id>;
- vbus-supply = <&chg_otg>;
- hnp-disable;
- srp-disable;
- adp-disable;
-
- ulpi {
- phy@b {
- status = "okay";
- v3p3-supply = <&pm8941_l24>;
- v1p8-supply = <&pm8941_l6>;
- extcon = <&smbb>;
- qcom,init-seq = /bits/ 8 <0x1 0x63>;
- };
- };
-};
-
&rpm_requests {
- pm8841-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pm8841-regulators";
pm8841_s1: s1 {
@@ -82,7 +60,7 @@
};
};
- pm8941-regulators {
+ regulators-1 {
compatible = "qcom,rpm-pm8941-regulators";
vdd_l1_l3-supply = <&pm8941_s1>;
@@ -272,34 +250,34 @@
};
&tlmm {
- sdc1_on: sdc1-on {
- clk {
+ sdc1_on: sdc1-on-state {
+ clk-pins {
pins = "sdc1_clk";
drive-strength = <16>;
bias-disable;
};
- cmd-data {
+ cmd-data-pins {
pins = "sdc1_cmd", "sdc1_data";
drive-strength = <10>;
bias-pull-up;
};
};
- sdc2_on: sdc2-on {
- clk {
+ sdc2_on: sdc2-on-state {
+ clk-pins {
pins = "sdc2_clk";
drive-strength = <10>;
bias-disable;
};
- cmd-data {
+ cmd-data-pins {
pins = "sdc2_cmd", "sdc2_data";
drive-strength = <6>;
bias-pull-up;
};
- cd {
+ cd-pins {
pins = "gpio62";
function = "gpio";
drive-strength = <2>;
@@ -307,3 +285,23 @@
};
};
};
+
+&usb {
+ status = "okay";
+
+ phys = <&usb_hs2_phy>;
+ phy-select = <&tcsr 0xb000 1>;
+ extcon = <&smbb>, <&usb_id>;
+ vbus-supply = <&chg_otg>;
+ hnp-disable;
+ srp-disable;
+ adp-disable;
+};
+
+&usb_hs2_phy {
+ status = "okay";
+ v3p3-supply = <&pm8941_l24>;
+ v1p8-supply = <&pm8941_l6>;
+ extcon = <&smbb>;
+ qcom,init-seq = /bits/ 8 <0x1 0x63>;
+};
diff --git a/arch/arm/boot/dts/qcom-apq8084.dtsi b/arch/arm/boot/dts/qcom-apq8084.dtsi
index f2fb7c975af8..fe30abfff90a 100644
--- a/arch/arm/boot/dts/qcom-apq8084.dtsi
+++ b/arch/arm/boot/dts/qcom-apq8084.dtsi
@@ -72,7 +72,7 @@
};
L2: l2-cache {
- compatible = "qcom,arch-cache";
+ compatible = "cache";
cache-level = <2>;
qcom,saw = <&saw_l2>;
};
@@ -258,12 +258,14 @@
};
tsens: thermal-sensor@fc4a8000 {
- compatible = "qcom,msm8974-tsens";
+ compatible = "qcom,msm8974-tsens", "qcom,tsens-v0_1";
reg = <0xfc4a9000 0x1000>, /* TM */
<0xfc4a8000 0x1000>; /* SROT */
nvmem-cells = <&tsens_calib>, <&tsens_backup>;
nvmem-cell-names = "calib", "calib_backup";
#qcom,sensors = <11>;
+ interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "uplow";
#thermal-sensor-cells = <1>;
};
timer@f9020000 {
@@ -394,7 +396,7 @@
#hwlock-cells = <1>;
};
- rpm_msg_ram: memory@fc428000 {
+ rpm_msg_ram: sram@fc428000 {
compatible = "qcom,rpm-msg-ram";
reg = <0xfc428000 0x4000>;
};
@@ -474,7 +476,7 @@
compatible = "qcom,rpm-apq8084";
qcom,smd-channels = "rpm_requests";
- pma8084-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pma8084-regulators";
pma8084_s1: s1 {};
diff --git a/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac-bit.dts b/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac-bit.dts
index cf7da1ab177c..1b27edce9d4f 100644
--- a/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac-bit.dts
+++ b/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac-bit.dts
@@ -9,7 +9,7 @@
leds {
compatible = "gpio-leds";
- power {
+ led-power {
label = "ap120c-ac:green:power";
function = LED_FUNCTION_POWER;
color = <LED_COLOR_ID_GREEN>;
@@ -17,14 +17,14 @@
default-state = "on";
};
- wlan {
+ led-wlan {
label = "ap120c-ac:green:wlan";
function = LED_FUNCTION_WLAN;
color = <LED_COLOR_ID_GREEN>;
gpios = <&tlmm 3 GPIO_ACTIVE_HIGH>;
};
- support {
+ led-support {
label = "ap120c-ac:green:support";
color = <LED_COLOR_ID_GREEN>;
gpios = <&tlmm 2 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts b/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts
index c4f89b712fd9..a707057c887d 100644
--- a/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts
+++ b/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dts
@@ -7,7 +7,7 @@
leds {
compatible = "gpio-leds";
- status: status {
+ status: led-status {
label = "ap120c-ac:blue:status";
function = LED_FUNCTION_STATUS;
color = <LED_COLOR_ID_BLUE>;
@@ -15,7 +15,7 @@
default-state = "keep";
};
- wlan2g {
+ led-wlan2g {
label = "ap120c-ac:green:wlan2g";
function = LED_FUNCTION_WLAN;
color = <LED_COLOR_ID_GREEN>;
@@ -23,7 +23,7 @@
linux,default-trigger = "phy0tpt";
};
- wlan5g {
+ led-wlan5g {
label = "ap120c-ac:red:wlan5g";
function = LED_FUNCTION_WLAN;
color = <LED_COLOR_ID_RED>;
diff --git a/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dtsi b/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dtsi
index af9a26fb5d4a..a5a6f3ebb274 100644
--- a/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq4018-ap120c-ac.dtsi
@@ -6,7 +6,7 @@
/ {
model = "ALFA Network AP120C-AC";
- compatible = "alfa-network,ap120c-ac";
+ compatible = "alfa-network,ap120c-ac", "qcom,ipq4018";
keys {
compatible = "gpio-keys";
diff --git a/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dts b/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dts
index 394412619894..365fbac417fd 100644
--- a/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dts
+++ b/arch/arm/boot/dts/qcom-ipq4018-jalapeno.dts
@@ -7,7 +7,7 @@
/ {
model = "8devices Jalapeno";
- compatible = "8dev,jalapeno";
+ compatible = "8dev,jalapeno", "qcom,ipq4018";
};
&tlmm {
diff --git a/arch/arm/boot/dts/qcom-ipq4019.dtsi b/arch/arm/boot/dts/qcom-ipq4019.dtsi
index b23591110bd2..acb08dcf9442 100644
--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
@@ -348,7 +348,7 @@
saw0: regulator@b089000 {
compatible = "qcom,saw2";
reg = <0x0b089000 0x1000>, <0x0b009000 0x1000>;
- regulator;
+ regulator;
};
saw1: regulator@b099000 {
diff --git a/arch/arm/boot/dts/qcom-ipq8064-rb3011.dts b/arch/arm/boot/dts/qcom-ipq8064-rb3011.dts
index 5a65cce2500c..f908889c4f95 100644
--- a/arch/arm/boot/dts/qcom-ipq8064-rb3011.dts
+++ b/arch/arm/boot/dts/qcom-ipq8064-rb3011.dts
@@ -5,7 +5,7 @@
/ {
model = "MikroTik RB3011UiAS-RM";
- compatible = "mikrotik,rb3011";
+ compatible = "mikrotik,rb3011", "qcom,ipq8064";
aliases {
serial0 = &gsbi7_serial;
@@ -264,8 +264,7 @@
&nand {
status = "okay";
- nandcs@0 {
- compatible = "qcom,nandcs";
+ nand@0 {
reg = <0>;
nand-ecc-strength = <4>;
diff --git a/arch/arm/boot/dts/qcom-ipq8064.dtsi b/arch/arm/boot/dts/qcom-ipq8064.dtsi
index 90c08b51680a..7e784b0995da 100644
--- a/arch/arm/boot/dts/qcom-ipq8064.dtsi
+++ b/arch/arm/boot/dts/qcom-ipq8064.dtsi
@@ -513,8 +513,8 @@
gcc: clock-controller@900000 {
compatible = "qcom,gcc-ipq8064", "syscon";
- clocks = <&pxo_board>, <&cxo_board>;
- clock-names = "pxo", "cxo";
+ clocks = <&pxo_board>, <&cxo_board>, <&lcc PLL4>;
+ clock-names = "pxo", "cxo", "pll4";
reg = <0x00900000 0x4000>;
#clock-cells = <1>;
#reset-cells = <1>;
@@ -728,7 +728,6 @@
status = "disabled";
reg = <0x12180000 0x2000>;
interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cmd_irq";
clocks = <&gcc SDC3_CLK>, <&gcc SDC3_H_CLK>;
clock-names = "mclk", "apb_pclk";
bus-width = <8>;
@@ -748,7 +747,6 @@
arm,primecell-periphid = <0x00051180>;
reg = <0x12400000 0x2000>;
interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cmd_irq";
clocks = <&gcc SDC1_CLK>, <&gcc SDC1_H_CLK>;
clock-names = "mclk", "apb_pclk";
bus-width = <8>;
@@ -756,7 +754,6 @@
non-removable;
cap-sd-highspeed;
cap-mmc-highspeed;
- mmc-ddr-1_8v;
vmmc-supply = <&vsdcc_fixed>;
dmas = <&sdcc1bam 2>, <&sdcc1bam 1>;
dma-names = "tx", "rx";
diff --git a/arch/arm/boot/dts/qcom-mdm9615-wp8548-mangoh-green.dts b/arch/arm/boot/dts/qcom-mdm9615-wp8548-mangoh-green.dts
index 0827de5426c1..a8304769b509 100644
--- a/arch/arm/boot/dts/qcom-mdm9615-wp8548-mangoh-green.dts
+++ b/arch/arm/boot/dts/qcom-mdm9615-wp8548-mangoh-green.dts
@@ -1,46 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
/*
* Device Tree Source for mangOH Green Board with WP8548 Module
*
* Copyright (C) 2016 BayLibre, SAS.
* Author : Neil Armstrong <narmstrong@baylibre.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- * a) This file is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This file 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.
- *
- * Or, alternatively,
- *
- * b) 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 AUTHORS OR COPYRIGHT
- * HOLDERS 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 <dt-bindings/input/input.h>
@@ -82,8 +45,8 @@
* - 42: IOT0_GPIO1 and SD Card Detect
*/
- gpioext1_pins: gpioext1_pins {
- pins {
+ gpioext1_pins: gpioext1-state {
+ gpioext1-pins {
pins = "gpio2";
function = "gpio";
input-enable;
@@ -91,8 +54,8 @@
};
};
- sdc_cd_pins: sdc_cd_pins {
- pins {
+ sdc_cd_pins: sdc-cd-state {
+ sdc-cd-pins {
pins = "gpio42";
function = "gpio";
drive-strength = <2>;
@@ -153,7 +116,7 @@
#size-cells = <0>;
reg = <4>;
- gpioext0: gpio@3e {
+ gpioext0: pinctrl@3e {
/* GPIO Expander 0 Mapping :
* - 0: ARDUINO_RESET_Level shift
* - 1: BattChrgr_PG_N
@@ -179,7 +142,7 @@
interrupt-parent = <&gpioext1>;
interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
- probe-reset;
+ semtech,probe-reset;
gpio-controller;
interrupt-controller;
@@ -191,7 +154,7 @@
#size-cells = <0>;
reg = <5>;
- gpioext1: gpio@3f {
+ gpioext1: pinctrl@3f {
/* GPIO Expander 1 Mapping :
* - 0: GPIOEXP_INT1
* - 1: Battery detect
@@ -220,7 +183,7 @@
interrupt-parent = <&msmgpio>;
interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
- probe-reset;
+ semtech,probe-reset;
gpio-controller;
interrupt-controller;
@@ -232,7 +195,7 @@
#size-cells = <0>;
reg = <6>;
- gpioext2: gpio@70 {
+ gpioext2: pinctrl@70 {
/* GPIO Expander 2 Mapping :
* - 0: USB_HUB_INTn
* - 1: HUB_CONNECT
@@ -258,7 +221,7 @@
interrupt-parent = <&gpioext1>;
interrupts = <14 IRQ_TYPE_EDGE_FALLING>;
- probe-reset;
+ semtech,probe-reset;
gpio-controller;
interrupt-controller;
diff --git a/arch/arm/boot/dts/qcom-mdm9615-wp8548.dtsi b/arch/arm/boot/dts/qcom-mdm9615-wp8548.dtsi
index 49de1821ac3a..92c8003dac25 100644
--- a/arch/arm/boot/dts/qcom-mdm9615-wp8548.dtsi
+++ b/arch/arm/boot/dts/qcom-mdm9615-wp8548.dtsi
@@ -1,46 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
/*
* Device Tree Source for Sierra Wireless WP8548 Module
*
* Copyright (C) 2016 BayLibre, SAS.
* Author : Neil Armstrong <narmstrong@baylibre.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- * a) This file is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This file 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.
- *
- * Or, alternatively,
- *
- * b) 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 AUTHORS OR COPYRIGHT
- * HOLDERS 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 "qcom-mdm9615.dtsi"
@@ -59,8 +22,8 @@
pinctrl-0 = <&reset_out_pins>;
pinctrl-names = "default";
- gsbi3_pins: gsbi3_pins {
- mux {
+ gsbi3_pins: gsbi3-state {
+ gsbi3-pins {
pins = "gpio8", "gpio9", "gpio10", "gpio11";
function = "gsbi3";
drive-strength = <8>;
@@ -68,8 +31,8 @@
};
};
- gsbi4_pins: gsbi4_pins {
- mux {
+ gsbi4_pins: gsbi4-state {
+ gsbi4-pins {
pins = "gpio12", "gpio13", "gpio14", "gpio15";
function = "gsbi4";
drive-strength = <8>;
@@ -77,15 +40,15 @@
};
};
- gsbi5_i2c_pins: gsbi5_i2c_pins {
- pin16 {
+ gsbi5_i2c_pins: gsbi5-i2c-state {
+ sda-pins {
pins = "gpio16";
function = "gsbi5_i2c";
drive-strength = <8>;
bias-disable;
};
- pin17 {
+ scl-pins {
pins = "gpio17";
function = "gsbi5_i2c";
drive-strength = <2>;
@@ -93,8 +56,8 @@
};
};
- gsbi5_uart_pins: gsbi5_uart_pins {
- mux {
+ gsbi5_uart_pins: gsbi5-uart-state {
+ gsbi5-uart-pins {
pins = "gpio18", "gpio19";
function = "gsbi5_uart";
drive-strength = <8>;
@@ -102,8 +65,8 @@
};
};
- reset_out_pins: reset_out_pins {
- pins {
+ reset_out_pins: reset-out-state {
+ reset-out-pins {
pins = "gpio66";
function = "gpio";
drive-strength = <2>;
diff --git a/arch/arm/boot/dts/qcom-mdm9615.dtsi b/arch/arm/boot/dts/qcom-mdm9615.dtsi
index b47c86412de2..b0fe1d95d88f 100644
--- a/arch/arm/boot/dts/qcom-mdm9615.dtsi
+++ b/arch/arm/boot/dts/qcom-mdm9615.dtsi
@@ -1,46 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
/*
* Device Tree Source for Qualcomm MDM9615 SoC
*
* Copyright (C) 2016 BayLibre, SAS.
* Author : Neil Armstrong <narmstrong@baylibre.com>
- *
- * This file is dual-licensed: you can use it either under the terms
- * of the GPL or the X11 license, at your option. Note that this dual
- * licensing only applies to this file, and not this project as a
- * whole.
- *
- * a) This file is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This file 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.
- *
- * Or, alternatively,
- *
- * b) 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 AUTHORS OR COPYRIGHT
- * HOLDERS 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.
*/
/dts-v1/;
@@ -64,6 +27,7 @@
cpu0: cpu@0 {
compatible = "arm,cortex-a5";
+ reg = <0>;
device_type = "cpu";
next-level-cache = <&L2>;
};
@@ -206,7 +170,6 @@
#size-cells = <0>;
reg = <0x16280000 0x1000>;
interrupts = <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
- spi-max-frequency = <24000000>;
clocks = <&gcc GSBI3_QUP_CLK>, <&gcc GSBI3_H_CLK>;
clock-names = "core", "iface";
@@ -283,7 +246,7 @@
reg = <0x500000 0x1000>;
qcom,controller-type = "pmic-arbiter";
- pmicintc: pmic@0 {
+ pmicintc: pmic {
compatible = "qcom,pm8018", "qcom,pm8921";
interrupts = <GIC_PPI 226 IRQ_TYPE_LEVEL_HIGH>;
#interrupt-cells = <2>;
@@ -351,51 +314,43 @@
qcom,ee = <0>;
};
- amba {
- compatible = "simple-bus";
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
- sdcc1: mmc@12180000 {
- status = "disabled";
- compatible = "arm,pl18x", "arm,primecell";
- arm,primecell-periphid = <0x00051180>;
- reg = <0x12180000 0x2000>;
- interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cmd_irq";
- clocks = <&gcc SDC1_CLK>, <&gcc SDC1_H_CLK>;
- clock-names = "mclk", "apb_pclk";
- bus-width = <8>;
- max-frequency = <48000000>;
- cap-sd-highspeed;
- cap-mmc-highspeed;
- vmmc-supply = <&vsdcc_fixed>;
- dmas = <&sdcc1bam 2>, <&sdcc1bam 1>;
- dma-names = "tx", "rx";
- assigned-clocks = <&gcc SDC1_CLK>;
- assigned-clock-rates = <400000>;
- };
+ sdcc1: mmc@12180000 {
+ status = "disabled";
+ compatible = "arm,pl18x", "arm,primecell";
+ arm,primecell-periphid = <0x00051180>;
+ reg = <0x12180000 0x2000>;
+ interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc SDC1_CLK>, <&gcc SDC1_H_CLK>;
+ clock-names = "mclk", "apb_pclk";
+ bus-width = <8>;
+ max-frequency = <48000000>;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ vmmc-supply = <&vsdcc_fixed>;
+ dmas = <&sdcc1bam 2>, <&sdcc1bam 1>;
+ dma-names = "tx", "rx";
+ assigned-clocks = <&gcc SDC1_CLK>;
+ assigned-clock-rates = <400000>;
+ };
- sdcc2: mmc@12140000 {
- compatible = "arm,pl18x", "arm,primecell";
- arm,primecell-periphid = <0x00051180>;
- status = "disabled";
- reg = <0x12140000 0x2000>;
- interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cmd_irq";
- clocks = <&gcc SDC2_CLK>, <&gcc SDC2_H_CLK>;
- clock-names = "mclk", "apb_pclk";
- bus-width = <4>;
- cap-sd-highspeed;
- cap-mmc-highspeed;
- max-frequency = <48000000>;
- no-1-8-v;
- vmmc-supply = <&vsdcc_fixed>;
- dmas = <&sdcc2bam 2>, <&sdcc2bam 1>;
- dma-names = "tx", "rx";
- assigned-clocks = <&gcc SDC2_CLK>;
- assigned-clock-rates = <400000>;
- };
+ sdcc2: mmc@12140000 {
+ compatible = "arm,pl18x", "arm,primecell";
+ arm,primecell-periphid = <0x00051180>;
+ status = "disabled";
+ reg = <0x12140000 0x2000>;
+ interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc SDC2_CLK>, <&gcc SDC2_H_CLK>;
+ clock-names = "mclk", "apb_pclk";
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ max-frequency = <48000000>;
+ no-1-8-v;
+ vmmc-supply = <&vsdcc_fixed>;
+ dmas = <&sdcc2bam 2>, <&sdcc2bam 1>;
+ dma-names = "tx", "rx";
+ assigned-clocks = <&gcc SDC2_CLK>;
+ assigned-clock-rates = <400000>;
};
tcsr: syscon@1a400000 {
diff --git a/arch/arm/boot/dts/qcom-msm8226-samsung-s3ve3g.dts b/arch/arm/boot/dts/qcom-msm8226-samsung-s3ve3g.dts
index 290e1df631f0..6a082ad4418a 100644
--- a/arch/arm/boot/dts/qcom-msm8226-samsung-s3ve3g.dts
+++ b/arch/arm/boot/dts/qcom-msm8226-samsung-s3ve3g.dts
@@ -8,6 +8,7 @@
/ {
model = "Samsung Galaxy S III Neo";
compatible = "samsung,s3ve3g", "qcom,msm8226";
+ chassis-type = "handset";
aliases {
serial0 = &blsp1_uart3;
diff --git a/arch/arm/boot/dts/qcom-msm8226.dtsi b/arch/arm/boot/dts/qcom-msm8226.dtsi
index cf2d56929428..4cba25dad8d6 100644
--- a/arch/arm/boot/dts/qcom-msm8226.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8226.dtsi
@@ -7,6 +7,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/qcom,gcc-msm8974.h>
+#include <dt-bindings/clock/qcom,mmcc-msm8974.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/power/qcom-rpmpd.h>
#include <dt-bindings/reset/qcom,gcc-msm8974.h>
@@ -298,6 +299,33 @@
#size-cells = <0>;
};
+ cci: cci@fda0c000 {
+ compatible = "qcom,msm8226-cci";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xfda0c000 0x1000>;
+ interrupts = <GIC_SPI 50 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&mmcc CAMSS_TOP_AHB_CLK>,
+ <&mmcc CAMSS_CCI_CCI_AHB_CLK>,
+ <&mmcc CAMSS_CCI_CCI_CLK>;
+ clock-names = "camss_top_ahb",
+ "cci_ahb",
+ "cci";
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&cci_default>;
+ pinctrl-1 = <&cci_sleep>;
+
+ status = "disabled";
+
+ cci_i2c0: i2c-bus@0 {
+ reg = <0>;
+ clock-frequency = <400000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
usb: usb@f9a55000 {
compatible = "qcom,ci-hdrc";
reg = <0xf9a55000 0x200>,
@@ -344,6 +372,14 @@
#power-domain-cells = <1>;
};
+ mmcc: clock-controller@fd8c0000 {
+ compatible = "qcom,mmcc-msm8226";
+ reg = <0xfd8c0000 0x6000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
tlmm: pinctrl@fd510000 {
compatible = "qcom,msm8226-pinctrl";
reg = <0xfd510000 0x4000>;
@@ -354,49 +390,65 @@
#interrupt-cells = <2>;
interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
- blsp1_i2c1_pins: blsp1-i2c1 {
+ blsp1_i2c1_pins: blsp1-i2c1-state {
pins = "gpio2", "gpio3";
function = "blsp_i2c1";
drive-strength = <2>;
bias-disable;
};
- blsp1_i2c2_pins: blsp1-i2c2 {
+ blsp1_i2c2_pins: blsp1-i2c2-state {
pins = "gpio6", "gpio7";
function = "blsp_i2c2";
drive-strength = <2>;
bias-disable;
};
- blsp1_i2c3_pins: blsp1-i2c3 {
+ blsp1_i2c3_pins: blsp1-i2c3-state {
pins = "gpio10", "gpio11";
function = "blsp_i2c3";
drive-strength = <2>;
bias-disable;
};
- blsp1_i2c4_pins: blsp1-i2c4 {
+ blsp1_i2c4_pins: blsp1-i2c4-state {
pins = "gpio14", "gpio15";
function = "blsp_i2c4";
drive-strength = <2>;
bias-disable;
};
- blsp1_i2c5_pins: blsp1-i2c5 {
+ blsp1_i2c5_pins: blsp1-i2c5-state {
pins = "gpio18", "gpio19";
function = "blsp_i2c5";
drive-strength = <2>;
bias-disable;
};
+ cci_default: cci-default-state {
+ pins = "gpio29", "gpio30";
+ function = "cci_i2c0";
+
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ cci_sleep: cci-sleep-state {
+ pins = "gpio29", "gpio30";
+ function = "gpio";
+
+ drive-strength = <2>;
+ bias-disable;
+ };
+
sdhc1_default_state: sdhc1-default-state {
- clk {
+ clk-pins {
pins = "sdc1_clk";
drive-strength = <10>;
bias-disable;
};
- cmd-data {
+ cmd-data-pins {
pins = "sdc1_cmd", "sdc1_data";
drive-strength = <10>;
bias-pull-up;
@@ -404,13 +456,13 @@
};
sdhc2_default_state: sdhc2-default-state {
- clk {
+ clk-pins {
pins = "sdc2_clk";
drive-strength = <10>;
bias-disable;
};
- cmd-data {
+ cmd-data-pins {
pins = "sdc2_cmd", "sdc2_data";
drive-strength = <10>;
bias-pull-up;
@@ -418,21 +470,21 @@
};
sdhc3_default_state: sdhc3-default-state {
- clk {
+ clk-pins {
pins = "gpio44";
function = "sdc3";
drive-strength = <8>;
bias-disable;
};
- cmd {
+ cmd-pins {
pins = "gpio43";
function = "sdc3";
drive-strength = <8>;
bias-pull-up;
};
- data {
+ data-pins {
pins = "gpio39", "gpio40", "gpio41", "gpio42";
function = "sdc3";
drive-strength = <8>;
@@ -527,7 +579,7 @@
};
};
- rpm_msg_ram: memory@fc428000 {
+ rpm_msg_ram: sram@fc428000 {
compatible = "qcom,rpm-msg-ram";
reg = <0xfc428000 0x4000>;
};
diff --git a/arch/arm/boot/dts/qcom-msm8660.dtsi b/arch/arm/boot/dts/qcom-msm8660.dtsi
index ddce7d64ba99..86f76d0feff4 100644
--- a/arch/arm/boot/dts/qcom-msm8660.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8660.dtsi
@@ -316,7 +316,7 @@
};
};
- external-bus@1a100000 {
+ ebi2: external-bus@1a100000 {
compatible = "qcom,msm8660-ebi2";
#address-cells = <2>;
#size-cells = <1>;
@@ -333,12 +333,12 @@
status = "disabled";
};
- qcom,ssbi@500000 {
+ ssbi@500000 {
compatible = "qcom,ssbi";
reg = <0x500000 0x1000>;
qcom,controller-type = "pmic-arbiter";
- pm8058: pmic@0 {
+ pm8058: pmic {
compatible = "qcom,pm8058";
interrupt-parent = <&tlmm>;
interrupts = <88 8>;
@@ -379,7 +379,7 @@
pull-up;
};
- keypad@148 {
+ pm8058_keypad: keypad@148 {
compatible = "qcom,pm8058-keypad";
reg = <0x148>;
interrupt-parent = <&pm8058>;
@@ -444,6 +444,31 @@
compatible = "qcom,pm8058-vib";
reg = <0x4a>;
};
+
+ pm8058_led48: led@48 {
+ compatible = "qcom,pm8058-keypad-led";
+ reg = <0x48>;
+ status = "disabled";
+ };
+
+ pm8058_led131: led@131 {
+ compatible = "qcom,pm8058-led";
+ reg = <0x131>;
+ status = "disabled";
+ };
+
+ pm8058_led132: led@132 {
+ compatible = "qcom,pm8058-led";
+ reg = <0x132>;
+ status = "disabled";
+ };
+
+ pm8058_led133: led@133 {
+ compatible = "qcom,pm8058-led";
+ reg = <0x133>;
+ status = "disabled";
+ };
+
};
};
@@ -471,7 +496,7 @@
clock-names = "pxo";
};
- pm8901-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pm8901-regulators";
pm8901_l0: l0 {};
@@ -495,7 +520,7 @@
pm8901_mvs: mvs {};
};
- pm8058-regulators {
+ regulators-1 {
compatible = "qcom,rpm-pm8058-regulators";
pm8058_l0: l0 {};
@@ -549,7 +574,6 @@
arm,primecell-periphid = <0x00051180>;
reg = <0x12400000 0x8000>;
interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cmd_irq";
clocks = <&gcc SDC1_CLK>, <&gcc SDC1_H_CLK>;
clock-names = "mclk", "apb_pclk";
bus-width = <8>;
@@ -565,7 +589,6 @@
arm,primecell-periphid = <0x00051180>;
reg = <0x12140000 0x8000>;
interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cmd_irq";
clocks = <&gcc SDC2_CLK>, <&gcc SDC2_H_CLK>;
clock-names = "mclk", "apb_pclk";
bus-width = <8>;
@@ -580,7 +603,6 @@
status = "disabled";
reg = <0x12180000 0x8000>;
interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cmd_irq";
clocks = <&gcc SDC3_CLK>, <&gcc SDC3_H_CLK>;
clock-names = "mclk", "apb_pclk";
bus-width = <4>;
@@ -596,7 +618,6 @@
status = "disabled";
reg = <0x121c0000 0x8000>;
interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cmd_irq";
clocks = <&gcc SDC4_CLK>, <&gcc SDC4_H_CLK>;
clock-names = "mclk", "apb_pclk";
bus-width = <4>;
@@ -611,7 +632,6 @@
status = "disabled";
reg = <0x12200000 0x8000>;
interrupts = <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cmd_irq";
clocks = <&gcc SDC5_CLK>, <&gcc SDC5_H_CLK>;
clock-names = "mclk", "apb_pclk";
bus-width = <4>;
diff --git a/arch/arm/boot/dts/qcom-msm8960-cdp.dts b/arch/arm/boot/dts/qcom-msm8960-cdp.dts
index 9157e3c4f48f..8fa2befa629a 100644
--- a/arch/arm/boot/dts/qcom-msm8960-cdp.dts
+++ b/arch/arm/boot/dts/qcom-msm8960-cdp.dts
@@ -18,7 +18,7 @@
regulators {
compatible = "simple-bus";
- ext_l2: gpio-regulator@91 {
+ ext_l2: gpio-regulator {
compatible = "regulator-fixed";
regulator-name = "ext_l2";
gpio = <&msmgpio 91 0>;
@@ -42,7 +42,7 @@
compatible = "micrel,ks8851";
reg = <0>;
interrupt-parent = <&msmgpio>;
- interrupts = <90 8>;
+ interrupts = <90 IRQ_TYPE_LEVEL_LOW>;
spi-max-frequency = <5400000>;
vdd-supply = <&ext_l2>;
vdd-io-supply = <&pm8921_lvs6>;
@@ -60,33 +60,32 @@
};
&msmgpio {
- spi1_default: spi1_default {
- mux {
- pins = "gpio6", "gpio7", "gpio9";
- function = "gsbi1";
- };
-
- mosi {
+ spi1_default: spi1-default-state {
+ mosi-pins {
pins = "gpio6";
+ function = "gsbi1";
drive-strength = <12>;
bias-disable;
};
- miso {
+ miso-pins {
pins = "gpio7";
+ function = "gsbi1";
drive-strength = <12>;
bias-disable;
};
- cs {
+ cs-pins {
pins = "gpio8";
+ function = "gsbi1";
drive-strength = <12>;
bias-disable;
output-low;
};
- clk {
+ clk-pins {
pins = "gpio9";
+ function = "gsbi1";
drive-strength = <12>;
bias-disable;
};
diff --git a/arch/arm/boot/dts/qcom-msm8960.dtsi b/arch/arm/boot/dts/qcom-msm8960.dtsi
index c5740da3754c..7debf9db7cb1 100644
--- a/arch/arm/boot/dts/qcom-msm8960.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8960.dtsi
@@ -17,7 +17,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
- interrupts = <1 14 0x304>;
+ interrupts = <GIC_PPI 14 0x304>;
cpu@0 {
compatible = "qcom,krait";
@@ -52,7 +52,7 @@
cpu-pmu {
compatible = "qcom,krait-pmu";
- interrupts = <1 10 0x304>;
+ interrupts = <GIC_PPI 10 0x304>;
qcom,no-pc-write;
};
@@ -105,9 +105,9 @@
timer@200a000 {
compatible = "qcom,kpss-timer",
"qcom,kpss-wdt-msm8960", "qcom,msm-timer";
- interrupts = <1 1 0x301>,
- <1 2 0x301>,
- <1 3 0x301>;
+ interrupts = <GIC_PPI 1 0x301>,
+ <GIC_PPI 2 0x301>,
+ <GIC_PPI 3 0x301>;
reg = <0x0200a000 0x100>;
clock-frequency = <27000000>,
<32768>;
@@ -119,7 +119,7 @@
gpio-controller;
gpio-ranges = <&msmgpio 0 0 152>;
#gpio-cells = <2>;
- interrupts = <0 16 0x4>;
+ interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
interrupt-controller;
#interrupt-cells = <2>;
reg = <0x800000 0x4000>;
@@ -247,15 +247,15 @@
};
};
- qcom,ssbi@500000 {
+ ssbi@500000 {
compatible = "qcom,ssbi";
reg = <0x500000 0x1000>;
qcom,controller-type = "pmic-arbiter";
- pmicintc: pmic@0 {
+ pmicintc: pmic {
compatible = "qcom,pm8921";
interrupt-parent = <&msmgpio>;
- interrupts = <104 8>;
+ interrupts = <104 IRQ_TYPE_LEVEL_LOW>;
#interrupt-cells = <2>;
interrupt-controller;
#address-cells = <1>;
@@ -265,7 +265,8 @@
compatible = "qcom,pm8921-pwrkey";
reg = <0x1c>;
interrupt-parent = <&pmicintc>;
- interrupts = <50 1>, <51 1>;
+ interrupts = <50 IRQ_TYPE_EDGE_RISING>,
+ <51 IRQ_TYPE_EDGE_RISING>;
debounce = <15625>;
pull-up;
};
@@ -274,7 +275,8 @@
compatible = "qcom,pm8921-keypad";
reg = <0x148>;
interrupt-parent = <&pmicintc>;
- interrupts = <74 1>, <75 1>;
+ interrupts = <74 IRQ_TYPE_EDGE_RISING>,
+ <75 IRQ_TYPE_EDGE_RISING>;
debounce = <15>;
scan-delay = <32>;
row-hold = <91500>;
@@ -283,7 +285,7 @@
rtc@11d {
compatible = "qcom,pm8921-rtc";
interrupt-parent = <&pmicintc>;
- interrupts = <39 1>;
+ interrupts = <39 IRQ_TYPE_EDGE_RISING>;
reg = <0x11d>;
allow-set-time;
};
@@ -297,44 +299,36 @@
clock-names = "core";
};
- amba {
- compatible = "simple-bus";
- #address-cells = <1>;
- #size-cells = <1>;
- ranges;
- sdcc1: mmc@12400000 {
- status = "disabled";
- compatible = "arm,pl18x", "arm,primecell";
- arm,primecell-periphid = <0x00051180>;
- reg = <0x12400000 0x8000>;
- interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cmd_irq";
- clocks = <&gcc SDC1_CLK>, <&gcc SDC1_H_CLK>;
- clock-names = "mclk", "apb_pclk";
- bus-width = <8>;
- max-frequency = <96000000>;
- non-removable;
- cap-sd-highspeed;
- cap-mmc-highspeed;
- vmmc-supply = <&vsdcc_fixed>;
- };
+ sdcc3: mmc@12180000 {
+ compatible = "arm,pl18x", "arm,primecell";
+ arm,primecell-periphid = <0x00051180>;
+ status = "disabled";
+ reg = <0x12180000 0x8000>;
+ interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc SDC3_CLK>, <&gcc SDC3_H_CLK>;
+ clock-names = "mclk", "apb_pclk";
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ max-frequency = <192000000>;
+ no-1-8-v;
+ vmmc-supply = <&vsdcc_fixed>;
+ };
- sdcc3: mmc@12180000 {
- compatible = "arm,pl18x", "arm,primecell";
- arm,primecell-periphid = <0x00051180>;
- status = "disabled";
- reg = <0x12180000 0x8000>;
- interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cmd_irq";
- clocks = <&gcc SDC3_CLK>, <&gcc SDC3_H_CLK>;
- clock-names = "mclk", "apb_pclk";
- bus-width = <4>;
- cap-sd-highspeed;
- cap-mmc-highspeed;
- max-frequency = <192000000>;
- no-1-8-v;
- vmmc-supply = <&vsdcc_fixed>;
- };
+ sdcc1: mmc@12400000 {
+ status = "disabled";
+ compatible = "arm,pl18x", "arm,primecell";
+ arm,primecell-periphid = <0x00051180>;
+ reg = <0x12400000 0x8000>;
+ interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc SDC1_CLK>, <&gcc SDC1_H_CLK>;
+ clock-names = "mclk", "apb_pclk";
+ bus-width = <8>;
+ max-frequency = <96000000>;
+ non-removable;
+ cap-sd-highspeed;
+ cap-mmc-highspeed;
+ vmmc-supply = <&vsdcc_fixed>;
};
tcsr: syscon@1a400000 {
diff --git a/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts b/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts
index 6daceaa87802..280e63e3ebf2 100644
--- a/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts
+++ b/arch/arm/boot/dts/qcom-msm8974-lge-nexus5-hammerhead.dts
@@ -9,6 +9,7 @@
/ {
model = "LGE MSM 8974 HAMMERHEAD";
compatible = "lge,hammerhead", "qcom,msm8974";
+ chassis-type = "handset";
aliases {
serial0 = &blsp1_uart1;
@@ -247,31 +248,6 @@
status = "okay";
};
-&otg {
- status = "okay";
-
- phys = <&usb_hs1_phy>;
- phy-select = <&tcsr 0xb000 0>;
-
- extcon = <&charger>, <&usb_id>;
- vbus-supply = <&usb_otg_vbus>;
-
- hnp-disable;
- srp-disable;
- adp-disable;
-
- ulpi {
- phy@a {
- status = "okay";
-
- v1p8-supply = <&pm8941_l6>;
- v3p3-supply = <&pm8941_l24>;
-
- qcom,init-seq = /bits/ 8 <0x1 0x64>;
- };
- };
-};
-
&pm8941_gpios {
gpio_keys_pin_a: gpio-keys-active-state {
pins = "gpio2", "gpio3";
@@ -344,7 +320,7 @@
};
&rpm_requests {
- pm8841-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pm8841-regulators";
pm8841_s1: s1 {
@@ -368,7 +344,7 @@
};
};
- pm8941-regulators {
+ regulators-1 {
compatible = "qcom,rpm-pm8941-regulators";
vdd_l1_l3-supply = <&pm8941_s1>;
@@ -573,43 +549,43 @@
};
&tlmm {
- sdc1_on: sdc1-on {
- clk {
+ sdc1_on: sdc1-on-state {
+ clk-pins {
pins = "sdc1_clk";
drive-strength = <16>;
bias-disable;
};
- cmd-data {
+ cmd-data-pins {
pins = "sdc1_cmd", "sdc1_data";
drive-strength = <10>;
bias-pull-up;
};
};
- sdc2_on: sdc2-on {
- clk {
+ sdc2_on: sdc2-on-state {
+ clk-pins {
pins = "sdc2_clk";
drive-strength = <6>;
bias-disable;
};
- cmd-data {
+ cmd-data-pins {
pins = "sdc2_cmd", "sdc2_data";
drive-strength = <6>;
bias-pull-up;
};
};
- mpu6515_pin: mpu6515 {
+ mpu6515_pin: mpu6515-state {
pins = "gpio73";
function = "gpio";
bias-disable;
input-enable;
};
- touch_pin: touch {
- int {
+ touch_pin: touch-state {
+ int-pins {
pins = "gpio5";
function = "gpio";
@@ -618,7 +594,7 @@
input-enable;
};
- reset {
+ reset-pins {
pins = "gpio8";
function = "gpio";
@@ -627,27 +603,50 @@
};
};
- panel_pin: panel {
+ panel_pin: panel-state {
pins = "gpio12";
function = "mdp_vsync";
drive-strength = <2>;
bias-disable;
};
- bt_pin: bt {
- hostwake {
+ bt_pin: bt-state {
+ hostwake-pins {
pins = "gpio42";
function = "gpio";
};
- devwake {
+ devwake-pins {
pins = "gpio62";
function = "gpio";
};
- shutdown {
+ shutdown-pins {
pins = "gpio41";
function = "gpio";
};
};
};
+
+&usb {
+ status = "okay";
+
+ phys = <&usb_hs1_phy>;
+ phy-select = <&tcsr 0xb000 0>;
+
+ extcon = <&charger>, <&usb_id>;
+ vbus-supply = <&usb_otg_vbus>;
+
+ hnp-disable;
+ srp-disable;
+ adp-disable;
+};
+
+&usb_hs1_phy {
+ status = "okay";
+
+ v1p8-supply = <&pm8941_l6>;
+ v3p3-supply = <&pm8941_l24>;
+
+ qcom,init-seq = /bits/ 8 <0x1 0x64>;
+};
diff --git a/arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine-amami.dts b/arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine-amami.dts
index 68d5626bf491..9f2ab5c122d0 100644
--- a/arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine-amami.dts
+++ b/arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine-amami.dts
@@ -4,6 +4,7 @@
/ {
model = "Sony Xperia Z1 Compact";
compatible = "sony,xperia-amami", "qcom,msm8974";
+ chassis-type = "handset";
};
&smbb {
diff --git a/arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine-honami.dts b/arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine-honami.dts
index ea6a941d8f8c..9028f17e5c4a 100644
--- a/arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine-honami.dts
+++ b/arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine-honami.dts
@@ -4,4 +4,5 @@
/ {
model = "Sony Xperia Z1";
compatible = "sony,xperia-honami", "qcom,msm8974";
+ chassis-type = "handset";
};
diff --git a/arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine.dtsi b/arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine.dtsi
index 5a70683d9103..1b683690a1ad 100644
--- a/arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974-sony-xperia-rhine.dtsi
@@ -132,31 +132,6 @@
/* sii8334 MHL HDMI bridge */
};
-&otg {
- status = "okay";
-
- phys = <&usb_hs1_phy>;
- phy-select = <&tcsr 0xb000 0>;
- extcon = <&smbb>, <&usb_id>;
- vbus-supply = <&chg_otg>;
-
- hnp-disable;
- srp-disable;
- adp-disable;
-
- ulpi {
- phy@a {
- status = "okay";
-
- v1p8-supply = <&pm8941_l6>;
- v3p3-supply = <&pm8941_l24>;
-
- extcon = <&smbb>;
- qcom,init-seq = /bits/ 8 <0x1 0x64>;
- };
- };
-};
-
&pm8941_coincell {
status = "okay";
qcom,rset-ohms = <2100>;
@@ -178,7 +153,7 @@
qcom,power-source = <1>;
- rgb-led {
+ multi-led {
color = <LED_COLOR_ID_RGB>;
function = LED_FUNCTION_STATUS;
@@ -214,7 +189,7 @@
};
&rpm_requests {
- pm8841-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pm8841-regulators";
pm8841_s1: s1 {
@@ -238,7 +213,7 @@
};
};
- pm8941-regulators {
+ regulators-1 {
compatible = "qcom,rpm-pm8941-regulators";
vdd_l1_l3-supply = <&pm8941_s1>;
@@ -442,7 +417,7 @@
};
&tlmm {
- ts_int_pin: touch-int {
+ ts_int_pin: touch-int-state {
pins = "gpio61";
function = "gpio";
drive-strength = <2>;
@@ -450,34 +425,34 @@
input-enable;
};
- sdc1_on: sdc1-on {
- clk {
+ sdc1_on: sdc1-on-state {
+ clk-pins {
pins = "sdc1_clk";
drive-strength = <16>;
bias-disable;
};
- cmd-data {
+ cmd-data-pins {
pins = "sdc1_cmd", "sdc1_data";
drive-strength = <10>;
bias-pull-up;
};
};
- sdc2_on: sdc-on {
- clk {
+ sdc2_on: sdc-on-state {
+ clk-pins {
pins = "sdc2_clk";
drive-strength = <10>;
bias-disable;
};
- cmd-data {
+ cmd-data-pins {
pins = "sdc2_cmd", "sdc2_data";
drive-strength = <6>;
bias-pull-up;
};
- cd {
+ cd-pins {
pins = "gpio62";
function = "gpio";
drive-strength = <2>;
@@ -485,3 +460,26 @@
};
};
};
+
+&usb {
+ status = "okay";
+
+ phys = <&usb_hs1_phy>;
+ phy-select = <&tcsr 0xb000 0>;
+ extcon = <&smbb>, <&usb_id>;
+ vbus-supply = <&chg_otg>;
+
+ hnp-disable;
+ srp-disable;
+ adp-disable;
+};
+
+&usb_hs1_phy {
+ status = "okay";
+
+ v1p8-supply = <&pm8941_l6>;
+ v3p3-supply = <&pm8941_l24>;
+
+ extcon = <&smbb>;
+ qcom,init-seq = /bits/ 8 <0x1 0x64>;
+};
diff --git a/arch/arm/boot/dts/qcom-msm8974.dtsi b/arch/arm/boot/dts/qcom-msm8974.dtsi
index 7a9be0acf3f5..8d216a3c0851 100644
--- a/arch/arm/boot/dts/qcom-msm8974.dtsi
+++ b/arch/arm/boot/dts/qcom-msm8974.dtsi
@@ -653,7 +653,7 @@
#size-cells = <0>;
};
- otg: usb@f9a55000 {
+ usb: usb@f9a55000 {
compatible = "qcom,ci-hdrc";
reg = <0xf9a55000 0x200>,
<0xf9a55200 0x200>;
@@ -679,7 +679,7 @@
#phy-cells = <0>;
clocks = <&xo_board>, <&gcc GCC_USB2A_PHY_SLEEP_CLK>;
clock-names = "ref", "sleep";
- resets = <&gcc GCC_USB2A_PHY_BCR>, <&otg 0>;
+ resets = <&gcc GCC_USB2A_PHY_BCR>, <&usb 0>;
reset-names = "phy", "por";
status = "disabled";
};
@@ -690,7 +690,7 @@
#phy-cells = <0>;
clocks = <&xo_board>, <&gcc GCC_USB2B_PHY_SLEEP_CLK>;
clock-names = "ref", "sleep";
- resets = <&gcc GCC_USB2B_PHY_BCR>, <&otg 1>;
+ resets = <&gcc GCC_USB2B_PHY_BCR>, <&usb 1>;
reset-names = "phy", "por";
status = "disabled";
};
@@ -1056,7 +1056,7 @@
reg = <0xfc400000 0x4000>;
};
- rpm_msg_ram: memory@fc428000 {
+ rpm_msg_ram: sram@fc428000 {
compatible = "qcom,rpm-msg-ram";
reg = <0xfc428000 0x4000>;
};
@@ -1116,7 +1116,7 @@
};
tsens: thermal-sensor@fc4a9000 {
- compatible = "qcom,msm8974-tsens";
+ compatible = "qcom,msm8974-tsens", "qcom,tsens-v0_1";
reg = <0xfc4a9000 0x1000>, /* TM */
<0xfc4a8000 0x1000>; /* SROT */
nvmem-cells = <&tsens_calib>, <&tsens_backup>;
@@ -1194,7 +1194,7 @@
resets = <&gcc GCC_MSS_RESTART>;
reset-names = "mss_restart";
- qcom,halt-regs = <&tcsr_mutex_block 0x1180 0x1200 0x1280>;
+ qcom,halt-regs = <&tcsr_mutex 0x1180 0x1200 0x1280>;
qcom,smem-states = <&modem_smp2p_out 0>;
qcom,smem-state-names = "stop";
@@ -1233,13 +1233,14 @@
};
};
- tcsr_mutex_block: syscon@fd484000 {
- compatible = "syscon";
+ tcsr_mutex: hwlock@fd484000 {
+ compatible = "qcom,msm8974-tcsr-mutex", "qcom,tcsr-mutex", "syscon";
reg = <0xfd484000 0x2000>;
+ #hwlock-cells = <1>;
};
tcsr: syscon@fd4a0000 {
- compatible = "syscon";
+ compatible = "qcom,tcsr-msm8974", "syscon";
reg = <0xfd4a0000 0x10000>;
};
@@ -1253,61 +1254,62 @@
#interrupt-cells = <2>;
interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
- sdc1_off: sdc1-off {
- clk {
+ sdc1_off: sdc1-off-state {
+ clk-pins {
pins = "sdc1_clk";
bias-disable;
drive-strength = <2>;
};
- cmd {
+ cmd-pins {
pins = "sdc1_cmd";
bias-pull-up;
drive-strength = <2>;
};
- data {
+ data-pins {
pins = "sdc1_data";
bias-pull-up;
drive-strength = <2>;
};
};
- sdc2_off: sdc2-off {
- clk {
+ sdc2_off: sdc2-off-state {
+ clk-pins {
pins = "sdc2_clk";
bias-disable;
drive-strength = <2>;
};
- cmd {
+ cmd-pins {
pins = "sdc2_cmd";
bias-pull-up;
drive-strength = <2>;
};
- data {
+ data-pins {
pins = "sdc2_data";
bias-pull-up;
drive-strength = <2>;
};
- cd {
+ cd-pins {
pins = "gpio54";
+ function = "gpio";
bias-disable;
drive-strength = <2>;
};
};
- blsp1_uart2_default: blsp1-uart2-default {
- rx {
+ blsp1_uart2_default: blsp1-uart2-default-state {
+ rx-pins {
pins = "gpio5";
function = "blsp_uart2";
drive-strength = <2>;
bias-pull-up;
};
- tx {
+ tx-pins {
pins = "gpio4";
function = "blsp_uart2";
drive-strength = <4>;
@@ -1315,15 +1317,15 @@
};
};
- blsp2_uart1_default: blsp2-uart1-default {
- tx-rts {
+ blsp2_uart1_default: blsp2-uart1-default-state {
+ tx-rts-pins {
pins = "gpio41", "gpio44";
function = "blsp_uart7";
drive-strength = <2>;
bias-disable;
};
- rx-cts {
+ rx-cts-pins {
pins = "gpio42", "gpio43";
function = "blsp_uart7";
drive-strength = <2>;
@@ -1331,22 +1333,22 @@
};
};
- blsp2_uart1_sleep: blsp2-uart1-sleep {
+ blsp2_uart1_sleep: blsp2-uart1-sleep-state {
pins = "gpio41", "gpio42", "gpio43", "gpio44";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
- blsp2_uart4_default: blsp2-uart4-default {
- tx-rts {
+ blsp2_uart4_default: blsp2-uart4-default-state {
+ tx-rts-pins {
pins = "gpio53", "gpio56";
function = "blsp_uart10";
drive-strength = <2>;
bias-disable;
};
- rx-cts {
+ rx-cts-pins {
pins = "gpio54", "gpio55";
function = "blsp_uart10";
drive-strength = <2>;
@@ -1354,42 +1356,42 @@
};
};
- blsp1_i2c1_default: blsp1-i2c1-default {
+ blsp1_i2c1_default: blsp1-i2c1-default-state {
pins = "gpio2", "gpio3";
function = "blsp_i2c1";
drive-strength = <2>;
bias-disable;
};
- blsp1_i2c1_sleep: blsp1-i2c1-sleep {
+ blsp1_i2c1_sleep: blsp1-i2c1-sleep-state {
pins = "gpio2", "gpio3";
function = "blsp_i2c1";
drive-strength = <2>;
bias-pull-up;
};
- blsp1_i2c2_default: blsp1-i2c2-default {
+ blsp1_i2c2_default: blsp1-i2c2-default-state {
pins = "gpio6", "gpio7";
function = "blsp_i2c2";
drive-strength = <2>;
bias-disable;
};
- blsp1_i2c2_sleep: blsp1-i2c2-sleep {
+ blsp1_i2c2_sleep: blsp1-i2c2-sleep-state {
pins = "gpio6", "gpio7";
function = "blsp_i2c2";
drive-strength = <2>;
bias-pull-up;
};
- blsp1_i2c3_default: blsp1-i2c3-default {
+ blsp1_i2c3_default: blsp1-i2c3-default-state {
pins = "gpio10", "gpio11";
function = "blsp_i2c3";
drive-strength = <2>;
bias-disable;
};
- blsp1_i2c3_sleep: blsp1-i2c3-sleep {
+ blsp1_i2c3_sleep: blsp1-i2c3-sleep-state {
pins = "gpio10", "gpio11";
function = "blsp_i2c3";
drive-strength = <2>;
@@ -1400,14 +1402,14 @@
/* BLSP1_I2C5 info is missing */
- blsp1_i2c6_default: blsp1-i2c6-default {
+ blsp1_i2c6_default: blsp1-i2c6-default-state {
pins = "gpio29", "gpio30";
function = "blsp_i2c6";
drive-strength = <2>;
bias-disable;
};
- blsp1_i2c6_sleep: blsp1-i2c6-sleep {
+ blsp1_i2c6_sleep: blsp1-i2c6-sleep-state {
pins = "gpio29", "gpio30";
function = "blsp_i2c6";
drive-strength = <2>;
@@ -1417,14 +1419,14 @@
/* BLSP2_I2C1 info is missing */
- blsp2_i2c2_default: blsp2-i2c2-default {
+ blsp2_i2c2_default: blsp2-i2c2-default-state {
pins = "gpio47", "gpio48";
function = "blsp_i2c8";
drive-strength = <2>;
bias-disable;
};
- blsp2_i2c2_sleep: blsp2-i2c2-sleep {
+ blsp2_i2c2_sleep: blsp2-i2c2-sleep-state {
pins = "gpio47", "gpio48";
function = "blsp_i2c8";
drive-strength = <2>;
@@ -1435,48 +1437,80 @@
/* BLSP2_I2C4 info is missing */
- blsp2_i2c5_default: blsp2-i2c5-default {
+ blsp2_i2c5_default: blsp2-i2c5-default-state {
pins = "gpio83", "gpio84";
function = "blsp_i2c11";
drive-strength = <2>;
bias-disable;
};
- blsp2_i2c5_sleep: blsp2-i2c5-sleep {
+ blsp2_i2c5_sleep: blsp2-i2c5-sleep-state {
pins = "gpio83", "gpio84";
function = "blsp_i2c11";
drive-strength = <2>;
bias-pull-up;
};
- blsp2_i2c6_default: blsp2-i2c6-default {
+ blsp2_i2c6_default: blsp2-i2c6-default-state {
pins = "gpio87", "gpio88";
function = "blsp_i2c12";
drive-strength = <2>;
bias-disable;
};
- blsp2_i2c6_sleep: blsp2-i2c6-sleep {
+ blsp2_i2c6_sleep: blsp2-i2c6-sleep-state {
pins = "gpio87", "gpio88";
function = "blsp_i2c12";
drive-strength = <2>;
bias-pull-up;
};
- spi8_default: spi8_default {
- mosi {
+ cci_default: cci-default-state {
+ cci_i2c0_default: cci-i2c0-default-pins {
+ pins = "gpio19", "gpio20";
+ function = "cci_i2c0";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ cci_i2c1_default: cci-i2c1-default-pins {
+ pins = "gpio21", "gpio22";
+ function = "cci_i2c1";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ cci_sleep: cci-sleep-state {
+ cci_i2c0_sleep: cci-i2c0-sleep-pins {
+ pins = "gpio19", "gpio20";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ cci_i2c1_sleep: cci-i2c1-sleep-pins {
+ pins = "gpio21", "gpio22";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ spi8_default: spi8_default-state {
+ mosi-pins {
pins = "gpio45";
function = "blsp_spi8";
};
- miso {
+ miso-pins {
pins = "gpio46";
function = "blsp_spi8";
};
- cs {
+ cs-pins {
pins = "gpio47";
function = "blsp_spi8";
};
- clk {
+ clk-pins {
pins = "gpio48";
function = "blsp_spi8";
};
@@ -1571,7 +1605,6 @@
"core_mmss";
phys = <&dsi0_phy>;
- phy-names = "dsi-phy";
status = "disabled";
@@ -1597,7 +1630,7 @@
};
};
- dsi0_phy: dsi-phy@fd922a00 {
+ dsi0_phy: phy@fd922a00 {
compatible = "qcom,dsi-phy-28nm-hpm";
reg = <0xfd922a00 0xd4>,
<0xfd922b00 0x280>,
@@ -1616,6 +1649,40 @@
};
};
+ cci: cci@fda0c000 {
+ compatible = "qcom,msm8974-cci";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xfda0c000 0x1000>;
+ interrupts = <GIC_SPI 50 IRQ_TYPE_EDGE_RISING>;
+ clocks = <&mmcc CAMSS_TOP_AHB_CLK>,
+ <&mmcc CAMSS_CCI_CCI_AHB_CLK>,
+ <&mmcc CAMSS_CCI_CCI_CLK>;
+ clock-names = "camss_top_ahb",
+ "cci_ahb",
+ "cci";
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&cci_default>;
+ pinctrl-1 = <&cci_sleep>;
+
+ status = "disabled";
+
+ cci_i2c0: i2c-bus@0 {
+ reg = <0>;
+ clock-frequency = <100000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ cci_i2c1: i2c-bus@1 {
+ reg = <1>;
+ clock-frequency = <100000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
gpu: adreno@fdb00000 {
compatible = "qcom,adreno-330.1", "qcom,adreno";
reg = <0xfdb00000 0x10000>;
@@ -1703,8 +1770,6 @@
qcom,ipc = <&apcs 8 8>;
qcom,smd-edge = <1>;
label = "lpass";
- #address-cells = <1>;
- #size-cells = <0>;
};
};
@@ -1719,13 +1784,6 @@
};
};
- tcsr_mutex: tcsr-mutex {
- compatible = "qcom,tcsr-mutex";
- syscon = <&tcsr_mutex_block 0 0x80>;
-
- #hwlock-cells = <1>;
- };
-
thermal-zones {
cpu0-thermal {
polling-delay-passive = <250>;
diff --git a/arch/arm/boot/dts/qcom-msm8974pro-fairphone-fp2.dts b/arch/arm/boot/dts/qcom-msm8974pro-fairphone-fp2.dts
index ff6e0066768b..f531d2679f6c 100644
--- a/arch/arm/boot/dts/qcom-msm8974pro-fairphone-fp2.dts
+++ b/arch/arm/boot/dts/qcom-msm8974pro-fairphone-fp2.dts
@@ -8,7 +8,8 @@
/ {
model = "Fairphone 2";
- compatible = "fairphone,fp2", "qcom,msm8974";
+ compatible = "fairphone,fp2", "qcom,msm8974pro", "qcom,msm8974";
+ chassis-type = "handset";
aliases {
mmc0 = &sdhc_1;
@@ -85,31 +86,6 @@
};
};
-&otg {
- status = "okay";
-
- phys = <&usb_hs1_phy>;
- phy-select = <&tcsr 0xb000 0>;
- extcon = <&smbb>, <&usb_id>;
- vbus-supply = <&chg_otg>;
-
- hnp-disable;
- srp-disable;
- adp-disable;
-
- ulpi {
- phy@a {
- status = "okay";
-
- v1p8-supply = <&pm8941_l6>;
- v3p3-supply = <&pm8941_l24>;
-
- extcon = <&smbb>;
- qcom,init-seq = /bits/ 8 <0x1 0x64>;
- };
- };
-};
-
&pm8941_gpios {
gpio_keys_pin_a: gpio-keys-active-state {
pins = "gpio1", "gpio2", "gpio5";
@@ -190,7 +166,7 @@
};
&rpm_requests {
- pm8841-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pm8841-regulators";
pm8841_s1: s1 {
@@ -209,7 +185,7 @@
};
};
- pm8941-regulators {
+ regulators-1 {
compatible = "qcom,rpm-pm8941-regulators";
vdd_l1_l3-supply = <&pm8941_s1>;
@@ -408,36 +384,36 @@
};
&tlmm {
- sdc1_on: sdc1-on {
- clk {
+ sdc1_on: sdc1-on-state {
+ clk-pins {
pins = "sdc1_clk";
drive-strength = <16>;
bias-disable;
};
- cmd-data {
+ cmd-data-pins {
pins = "sdc1_cmd", "sdc1_data";
drive-strength = <10>;
bias-pull-up;
};
};
- sdc2_on: sdc2-on {
- clk {
+ sdc2_on: sdc2-on-state {
+ clk-pins {
pins = "sdc2_clk";
drive-strength = <10>;
bias-disable;
};
- cmd-data {
+ cmd-data-pins {
pins = "sdc2_cmd", "sdc2_data";
drive-strength = <6>;
bias-pull-up;
};
};
- wcnss_pin_a: wcnss-pin-active {
- wlan {
+ wcnss_pin_a: wcnss-pin-active-state {
+ wlan-pins {
pins = "gpio36", "gpio37", "gpio38", "gpio39", "gpio40";
function = "wlan";
@@ -445,7 +421,7 @@
bias-pull-down;
};
- bt {
+ bt-pins {
pins = "gpio35", "gpio43", "gpio44";
function = "bt";
@@ -453,7 +429,7 @@
bias-pull-down;
};
- fm {
+ fm-pins {
pins = "gpio41", "gpio42";
function = "fm";
@@ -462,3 +438,26 @@
};
};
};
+
+&usb {
+ status = "okay";
+
+ phys = <&usb_hs1_phy>;
+ phy-select = <&tcsr 0xb000 0>;
+ extcon = <&smbb>, <&usb_id>;
+ vbus-supply = <&chg_otg>;
+
+ hnp-disable;
+ srp-disable;
+ adp-disable;
+};
+
+&usb_hs1_phy {
+ status = "okay";
+
+ v1p8-supply = <&pm8941_l6>;
+ v3p3-supply = <&pm8941_l24>;
+
+ extcon = <&smbb>;
+ qcom,init-seq = /bits/ 8 <0x1 0x64>;
+};
diff --git a/arch/arm/boot/dts/qcom-msm8974pro-oneplus-bacon.dts b/arch/arm/boot/dts/qcom-msm8974pro-oneplus-bacon.dts
new file mode 100644
index 000000000000..b5606623f968
--- /dev/null
+++ b/arch/arm/boot/dts/qcom-msm8974pro-oneplus-bacon.dts
@@ -0,0 +1,417 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "qcom-msm8974pro.dtsi"
+#include "qcom-pm8841.dtsi"
+#include "qcom-pm8941.dtsi"
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+
+/ {
+ model = "OnePlus One";
+ compatible = "oneplus,bacon", "qcom,msm8974pro", "qcom,msm8974";
+ chassis-type = "handset";
+ qcom,msm-id = <194 0x10000>;
+ qcom,board-id = <8 0>;
+
+ aliases {
+ serial0 = &blsp1_uart2;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&blsp1_i2c1 {
+ status = "okay";
+
+ fuel-gauge@55 {
+ compatible = "ti,bq27541";
+ reg = <0x55>;
+ power-supplies = <&bq24196_charger>;
+ };
+};
+
+&blsp1_i2c2 {
+ status = "okay";
+
+ rmi4-i2c-dev@20 {
+ compatible = "syna,rmi4-i2c";
+ reg = <0x20>;
+
+ syna,startup-delay-ms = <100>;
+
+ interrupts-extended = <&tlmm 61 IRQ_TYPE_EDGE_FALLING>;
+ vdd-supply = <&pm8941_l22>;
+ vio-supply = <&pm8941_lvs3>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&touch_default_state>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rmi4-f01@1 {
+ reg = <0x1>;
+ syna,nosleep-mode = <1>;
+ };
+
+ rmi4-f12@12 {
+ reg = <0x12>;
+ syna,sensor-type = <1>;
+ /*
+ * Touchscreen size is 2040x1080, y-values between
+ * 1920-2040 are used for touchkey (menu, home & back).
+ * For now clip it off so we don't get touch events
+ * outside of the display area.
+ */
+ syna,clip-y-high = <1920>;
+ };
+ };
+};
+
+&blsp1_i2c6 {
+ status = "okay";
+
+ bq24196_charger: charger@6b {
+ compatible = "ti,bq24196";
+ reg = <0x6b>;
+ interrupts-extended = <&tlmm 31 IRQ_TYPE_EDGE_FALLING>;
+ omit-battery-class;
+ };
+};
+
+&blsp1_uart2 {
+ status = "okay";
+};
+
+&gcc {
+ compatible = "qcom,gcc-msm8974pro-ac";
+};
+
+&pm8941_coincell {
+ qcom,rset-ohms = <800>;
+ qcom,vset-millivolts = <3200>;
+
+ status = "okay";
+};
+
+&pronto {
+ vddmx-supply = <&pm8841_s1>;
+ vddcx-supply = <&pm8841_s2>;
+ vddpx-supply = <&pm8941_s3>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&wcnss_pin_a>;
+
+ status = "okay";
+
+ iris {
+ vddxo-supply = <&pm8941_l6>;
+ vddrfa-supply = <&pm8941_l11>;
+ vddpa-supply = <&pm8941_l19>;
+ vdddig-supply = <&pm8941_s3>;
+ };
+
+ smd-edge {
+ qcom,remote-pid = <4>;
+ label = "pronto";
+
+ wcnss {
+ status = "okay";
+ };
+ };
+};
+
+&remoteproc_adsp {
+ cx-supply = <&pm8841_s2>;
+
+ status = "okay";
+};
+
+&rpm_requests {
+ regulators-0 {
+ compatible = "qcom,rpm-pm8841-regulators";
+
+ pm8841_s1: s1 {
+ regulator-min-microvolt = <675000>;
+ regulator-max-microvolt = <1050000>;
+ };
+
+ pm8841_s2: s2 {
+ regulator-min-microvolt = <875000>;
+ regulator-max-microvolt = <1050000>;
+ regulator-always-on;
+ };
+
+ pm8841_s3: s3 {
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ };
+ };
+
+ regulators-1 {
+ compatible = "qcom,rpm-pm8941-regulators";
+
+ vdd_l1_l3-supply = <&pm8941_s1>;
+ vdd_l2_lvs1_2_3-supply = <&pm8941_s3>;
+ vdd_l4_l11-supply = <&pm8941_s1>;
+ vdd_l5_l7-supply = <&pm8941_s2>;
+ vdd_l6_l12_l14_l15-supply = <&pm8941_s2>;
+ vdd_l8_l16_l18_l19-supply = <&vreg_vph_pwr>;
+ vdd_l9_l10_l17_l22-supply = <&vreg_boost>;
+ vdd_l13_l20_l23_l24-supply = <&vreg_boost>;
+ vdd_l21-supply = <&vreg_boost>;
+
+ pm8941_s1: s1 {
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ pm8941_s2: s2 {
+ regulator-min-microvolt = <2150000>;
+ regulator-max-microvolt = <2150000>;
+
+ regulator-boot-on;
+ };
+
+ pm8941_s3: s3 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-system-load = <154000>;
+
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-allow-set-load;
+ };
+
+ pm8941_l1: l1 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ pm8941_l2: l2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8941_l3: l3 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ pm8941_l4: l4 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ pm8941_l5: l5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8941_l6: l6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-boot-on;
+ };
+
+ pm8941_l7: l7 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-boot-on;
+ };
+
+ pm8941_l8: l8 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8941_l9: l9 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8941_l10: l10 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ pm8941_l11: l11 {
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1350000>;
+ };
+
+ pm8941_l12: l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-allow-set-load;
+ };
+
+ pm8941_l13: l13 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+
+ regulator-boot-on;
+ };
+
+ pm8941_l14: l14 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8941_l15: l15 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ };
+
+ pm8941_l16: l16 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ };
+
+ pm8941_l17: l17 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ };
+
+ pm8941_l18: l18 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ };
+
+ pm8941_l19: l19 {
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <3350000>;
+ };
+
+ pm8941_l20: l20 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+
+ regulator-system-load = <200000>;
+ regulator-allow-set-load;
+ regulator-boot-on;
+ };
+
+ pm8941_l21: l21 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+
+ regulator-boot-on;
+ };
+
+ pm8941_l22: l22 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-allow-set-load;
+ };
+
+ pm8941_l23: l23 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ pm8941_l24: l24 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+
+ regulator-boot-on;
+ };
+
+ pm8941_lvs3: lvs3 {};
+ };
+};
+
+&sdhc_1 {
+ vmmc-supply = <&pm8941_l20>;
+ vqmmc-supply = <&pm8941_s3>;
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdc1_on>;
+ pinctrl-1 = <&sdc1_off>;
+
+ status = "okay";
+};
+
+&tlmm {
+ sdc1_on: sdc1-on-state {
+ clk-pins {
+ pins = "sdc1_clk";
+ drive-strength = <4>;
+ bias-disable;
+ };
+
+ cmd-data-pins {
+ pins = "sdc1_cmd", "sdc1_data";
+ drive-strength = <4>;
+ bias-pull-up;
+ };
+ };
+
+ touch_default_state: touch-default-state {
+ int-pins {
+ pins = "gpio61";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ input-enable;
+ };
+
+ reset-pins {
+ pins = "gpio60";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ wcnss_pin_a: wcnss-pin-active-state {
+ wlan-pins {
+ pins = "gpio36", "gpio37", "gpio38", "gpio39", "gpio40";
+ function = "wlan";
+ drive-strength = <6>;
+ bias-pull-down;
+ };
+
+ bt-pins {
+ pins = "gpio35", "gpio43", "gpio44";
+ function = "bt";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+ };
+};
+
+&usb {
+ phys = <&usb_hs1_phy>;
+ phy-select = <&tcsr 0xb000 0>;
+ extcon = <&smbb>, <&usb_id>;
+ vbus-supply = <&chg_otg>;
+
+ hnp-disable;
+ srp-disable;
+ adp-disable;
+
+ status = "okay";
+};
+
+&usb_hs1_phy {
+ status = "okay";
+
+ v1p8-supply = <&pm8941_l6>;
+ v3p3-supply = <&pm8941_l24>;
+
+ extcon = <&smbb>;
+ qcom,init-seq = /bits/ 8 <0x1 0x64>;
+};
diff --git a/arch/arm/boot/dts/qcom-msm8974pro-samsung-klte.dts b/arch/arm/boot/dts/qcom-msm8974pro-samsung-klte.dts
index 983e10c3d863..b9698ffb66ca 100644
--- a/arch/arm/boot/dts/qcom-msm8974pro-samsung-klte.dts
+++ b/arch/arm/boot/dts/qcom-msm8974pro-samsung-klte.dts
@@ -7,7 +7,8 @@
/ {
model = "Samsung Galaxy S5";
- compatible = "samsung,klte", "qcom,msm8974";
+ compatible = "samsung,klte", "qcom,msm8974pro", "qcom,msm8974";
+ chassis-type = "handset";
aliases {
serial0 = &blsp1_uart1;
@@ -375,28 +376,6 @@
status = "okay";
};
-&otg {
- status = "okay";
-
- phys = <&usb_hs1_phy>;
- phy-select = <&tcsr 0xb000 0>;
-
- hnp-disable;
- srp-disable;
- adp-disable;
-
- ulpi {
- phy@a {
- status = "okay";
-
- v1p8-supply = <&pma8084_l6>;
- v3p3-supply = <&pma8084_l24>;
-
- qcom,init-seq = /bits/ 8 <0x1 0x64>;
- };
- };
-};
-
&pma8084_gpios {
gpio_keys_pin_a: gpio-keys-active-state {
pins = "gpio2", "gpio3", "gpio5";
@@ -470,7 +449,7 @@
};
&rpm_requests {
- pma8084-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pma8084-regulators";
pma8084_s1: s1 {
@@ -706,57 +685,57 @@
&tlmm {
/* This seems suspicious, but somebody with this device should look into it. */
- blsp2_uart2_pins_active: blsp2-uart2-pins-active {
+ blsp2_uart2_pins_active: blsp2-uart2-pins-active-state {
pins = "gpio45", "gpio46", "gpio47", "gpio48";
function = "blsp_uart8";
drive-strength = <8>;
bias-disable;
};
- blsp2_uart2_pins_sleep: blsp2-uart2-pins-sleep {
+ blsp2_uart2_pins_sleep: blsp2-uart2-pins-sleep-state {
pins = "gpio45", "gpio46", "gpio47", "gpio48";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
- bt_pins: bt-pins {
- hostwake {
+ bt_pins: bt-pins-state {
+ hostwake-pins {
pins = "gpio75";
function = "gpio";
drive-strength = <16>;
input-enable;
};
- devwake {
+ devwake-pins {
pins = "gpio91";
function = "gpio";
drive-strength = <2>;
};
};
- sdc1_on: sdhc1-on {
- clk {
+ sdc1_on: sdhc1-on-state {
+ clk-pins {
pins = "sdc1_clk";
drive-strength = <4>;
bias-disable;
};
- cmd-data {
+ cmd-data-pins {
pins = "sdc1_cmd", "sdc1_data";
drive-strength = <4>;
bias-pull-up;
};
};
- sdc3_on: sdc3-on {
+ sdc3_on: sdc3-on-state {
pins = "gpio35", "gpio36", "gpio37", "gpio38", "gpio39", "gpio40";
function = "sdc3";
drive-strength = <8>;
bias-disable;
};
- sdhc3_cd_pin: sdc3-cd-on {
+ sdhc3_cd_pin: sdc3-cd-on-state {
pins = "gpio62";
function = "gpio";
@@ -764,52 +743,72 @@
bias-disable;
};
- sdc2_on: sdhc2-on {
- clk {
+ sdc2_on: sdhc2-on-state {
+ clk-pins {
pins = "sdc2_clk";
drive-strength = <6>;
bias-disable;
};
- cmd-data {
+ cmd-data-pins {
pins = "sdc2_cmd", "sdc2_data";
drive-strength = <6>;
bias-pull-up;
};
};
- i2c_touchkey_pins: i2c-touchkey {
+ i2c_touchkey_pins: i2c-touchkey-state {
pins = "gpio95", "gpio96";
function = "gpio";
input-enable;
bias-pull-up;
};
- i2c_led_gpioex_pins: i2c-led-gpioex {
+ i2c_led_gpioex_pins: i2c-led-gpioex-state {
pins = "gpio120", "gpio121";
function = "gpio";
input-enable;
bias-pull-down;
};
- gpioex_pin: gpioex {
+ gpioex_pin: gpioex-state {
pins = "gpio145";
function = "gpio";
bias-pull-up;
drive-strength = <2>;
};
- wifi_pin: wifi {
+ wifi_pin: wifi-state {
pins = "gpio92";
function = "gpio";
input-enable;
bias-pull-down;
};
- panel_te_pin: panel {
+ panel_te_pin: panel-state {
pins = "gpio12";
function = "mdp_vsync";
drive-strength = <2>;
bias-disable;
};
};
+
+&usb {
+ status = "okay";
+
+ phys = <&usb_hs1_phy>;
+ phy-select = <&tcsr 0xb000 0>;
+
+ hnp-disable;
+ srp-disable;
+ adp-disable;
+};
+
+&usb_hs1_phy {
+ status = "okay";
+
+ v1p8-supply = <&pma8084_l6>;
+ v3p3-supply = <&pma8084_l24>;
+
+ qcom,init-seq = /bits/ 8 <0x1 0x64>;
+};
diff --git a/arch/arm/boot/dts/qcom-msm8974pro-sony-xperia-shinano-castor.dts b/arch/arm/boot/dts/qcom-msm8974pro-sony-xperia-shinano-castor.dts
index 3f45f5c5d37b..3b1cc39f2269 100644
--- a/arch/arm/boot/dts/qcom-msm8974pro-sony-xperia-shinano-castor.dts
+++ b/arch/arm/boot/dts/qcom-msm8974pro-sony-xperia-shinano-castor.dts
@@ -8,7 +8,8 @@
/ {
model = "Sony Xperia Z2 Tablet";
- compatible = "sony,xperia-castor", "qcom,msm8974";
+ compatible = "sony,xperia-castor", "qcom,msm8974pro", "qcom,msm8974";
+ chassis-type = "tablet";
aliases {
serial0 = &blsp1_uart2;
@@ -212,31 +213,6 @@
};
};
-&otg {
- status = "okay";
-
- phys = <&usb_hs1_phy>;
- phy-select = <&tcsr 0xb000 0>;
- extcon = <&smbb>, <&usb_id>;
- vbus-supply = <&chg_otg>;
-
- hnp-disable;
- srp-disable;
- adp-disable;
-
- ulpi {
- phy@a {
- status = "okay";
-
- v1p8-supply = <&pm8941_l6>;
- v3p3-supply = <&pm8941_l24>;
-
- extcon = <&smbb>;
- qcom,init-seq = /bits/ 8 <0x1 0x64>;
- };
- };
-};
-
&pm8941_coincell {
status = "okay";
@@ -294,7 +270,7 @@
qcom,power-source = <1>;
- rgb-led {
+ multi-led {
color = <LED_COLOR_ID_RGB>;
function = LED_FUNCTION_STATUS;
@@ -319,7 +295,7 @@
};
&rpm_requests {
- pm8941-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pm8941-regulators";
vdd_l1_l3-supply = <&pm8941_s1>;
@@ -548,41 +524,42 @@
};
&tlmm {
- lcd_backlight_en_pin_a: lcd-backlight-vddio {
+ lcd_backlight_en_pin_a: lcd-backlight-vddio-state {
pins = "gpio69";
+ function = "gpio";
drive-strength = <10>;
output-low;
bias-disable;
};
- sdc1_on: sdc1-on {
- clk {
+ sdc1_on: sdc1-on-state {
+ clk-pins {
pins = "sdc1_clk";
drive-strength = <16>;
bias-disable;
};
- cmd-data {
+ cmd-data-pins {
pins = "sdc1_cmd", "sdc1_data";
drive-strength = <10>;
bias-pull-up;
};
};
- sdc2_on: sdc2-on {
- clk {
+ sdc2_on: sdc2-on-state {
+ clk-pins {
pins = "sdc2_clk";
drive-strength = <6>;
bias-disable;
};
- cmd-data {
+ cmd-data-pins {
pins = "sdc2_cmd", "sdc2_data";
drive-strength = <6>;
bias-pull-up;
};
- cd {
+ cd-pins {
pins = "gpio62";
function = "gpio";
drive-strength = <2>;
@@ -590,22 +567,22 @@
};
};
- sdc3_on: sdc3-on {
- clk {
+ sdc3_on: sdc3-on-state {
+ clk-pins {
pins = "gpio40";
function = "sdc3";
drive-strength = <10>;
bias-disable;
};
- cmd {
+ cmd-pins {
pins = "gpio39";
function = "sdc3";
drive-strength = <10>;
bias-pull-up;
};
- data {
+ data-pins {
pins = "gpio35", "gpio36", "gpio37", "gpio38";
function = "sdc3";
drive-strength = <10>;
@@ -613,7 +590,7 @@
};
};
- ts_int_pin: ts-int-pin {
+ ts_int_pin: ts-int-pin-state {
pins = "gpio86";
function = "gpio";
drive-strength = <2>;
@@ -621,7 +598,7 @@
input-enable;
};
- bt_host_wake_pin: bt-host-wake {
+ bt_host_wake_pin: bt-host-wake-state {
pins = "gpio95";
function = "gpio";
drive-strength = <2>;
@@ -629,10 +606,33 @@
output-low;
};
- bt_dev_wake_pin: bt-dev-wake {
+ bt_dev_wake_pin: bt-dev-wake-state {
pins = "gpio96";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
};
+
+&usb {
+ status = "okay";
+
+ phys = <&usb_hs1_phy>;
+ phy-select = <&tcsr 0xb000 0>;
+ extcon = <&smbb>, <&usb_id>;
+ vbus-supply = <&chg_otg>;
+
+ hnp-disable;
+ srp-disable;
+ adp-disable;
+};
+
+&usb_hs1_phy {
+ status = "okay";
+
+ v1p8-supply = <&pm8941_l6>;
+ v3p3-supply = <&pm8941_l24>;
+
+ extcon = <&smbb>;
+ qcom,init-seq = /bits/ 8 <0x1 0x64>;
+};
diff --git a/arch/arm/boot/dts/qcom-pm8226.dtsi b/arch/arm/boot/dts/qcom-pm8226.dtsi
index 9b7d9d04ded6..eb36d3662464 100644
--- a/arch/arm/boot/dts/qcom-pm8226.dtsi
+++ b/arch/arm/boot/dts/qcom-pm8226.dtsi
@@ -90,6 +90,16 @@
interrupt-controller;
#interrupt-cells = <2>;
};
+
+ pm8226_gpios: gpio@c000 {
+ compatible = "qcom,pm8226-gpio", "qcom,spmi-gpio";
+ reg = <0xc000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pm8226_gpios 0 0 8>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
};
pm8226_1: pm8226@1 {
@@ -98,7 +108,7 @@
#address-cells = <1>;
#size-cells = <0>;
- pm8226_spmi_regulators: pm8226-regulators {
+ pm8226_spmi_regulators: regulators {
compatible = "qcom,pm8226-regulators";
};
diff --git a/arch/arm/boot/dts/qcom-pm8941.dtsi b/arch/arm/boot/dts/qcom-pm8941.dtsi
index 9cd49deb9fa7..cd957a1e7cdf 100644
--- a/arch/arm/boot/dts/qcom-pm8941.dtsi
+++ b/arch/arm/boot/dts/qcom-pm8941.dtsi
@@ -27,7 +27,7 @@
bias-pull-up;
};
- usb_id: misc@900 {
+ usb_id: usb-detect@900 {
compatible = "qcom,pm8941-misc";
reg = <0x900>;
interrupts = <0x0 0x9 0 IRQ_TYPE_EDGE_BOTH>;
@@ -59,7 +59,7 @@
chg_otg: otg-vbus { };
};
- pm8941_gpios: gpios@c000 {
+ pm8941_gpios: gpio@c000 {
compatible = "qcom,pm8941-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
gpio-controller;
@@ -101,37 +101,44 @@
#size-cells = <0>;
#io-channel-cells = <1>;
- bat_temp {
- reg = <VADC_LR_MUX1_BAT_THERM>;
+
+ adc-chan@6 {
+ reg = <VADC_VBAT_SNS>;
};
- die_temp {
+
+ adc-chan@8 {
reg = <VADC_DIE_TEMP>;
};
- ref_625mv {
+
+ adc-chan@9 {
reg = <VADC_REF_625MV>;
};
- ref_1250v {
+
+ adc-chan@a {
reg = <VADC_REF_1250MV>;
};
- ref_gnd {
+
+ adc-chan@e {
reg = <VADC_GND_REF>;
};
- ref_vdd {
+
+ adc-chan@f {
reg = <VADC_VDD_VADC>;
};
- vbat_sns {
- reg = <VADC_VBAT_SNS>;
+
+ adc-chan@30 {
+ reg = <VADC_LR_MUX1_BAT_THERM>;
};
};
- pm8941_iadc: iadc@3600 {
+ pm8941_iadc: adc@3600 {
compatible = "qcom,pm8941-iadc", "qcom,spmi-iadc";
reg = <0x3600>;
interrupts = <0x0 0x36 0x0 IRQ_TYPE_EDGE_RISING>;
qcom,external-resistor-micro-ohms = <10000>;
};
- pm8941_coincell: coincell@2800 {
+ pm8941_coincell: charger@2800 {
compatible = "qcom,pm8941-coincell";
reg = <0x2800>;
status = "disabled";
diff --git a/arch/arm/boot/dts/qcom-pma8084.dtsi b/arch/arm/boot/dts/qcom-pma8084.dtsi
index e77602e9f95c..2dd4c6aa71c9 100644
--- a/arch/arm/boot/dts/qcom-pma8084.dtsi
+++ b/arch/arm/boot/dts/qcom-pma8084.dtsi
@@ -27,7 +27,7 @@
bias-pull-up;
};
- pma8084_gpios: gpios@c000 {
+ pma8084_gpios: gpio@c000 {
compatible = "qcom,pma8084-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
gpio-controller;
@@ -64,22 +64,27 @@
#size-cells = <0>;
#io-channel-cells = <1>;
- die_temp {
+ adc-chan@8 {
reg = <VADC_DIE_TEMP>;
};
- ref_625mv {
+
+ adc-chan@9 {
reg = <VADC_REF_625MV>;
};
- ref_1250v {
+
+ adc-chan@a {
reg = <VADC_REF_1250MV>;
};
- ref_buf_625mv {
+
+ adc-chan@c {
reg = <VADC_SPARE1>;
};
- ref_gnd {
+
+ adc-chan@e {
reg = <VADC_GND_REF>;
};
- ref_vdd {
+
+ adc-chan@f {
reg = <VADC_VDD_VADC>;
};
};
diff --git a/arch/arm/boot/dts/qcom-pmx65.dtsi b/arch/arm/boot/dts/qcom-pmx65.dtsi
index abf229a8b75a..1c7fdf59c1f5 100644
--- a/arch/arm/boot/dts/qcom-pmx65.dtsi
+++ b/arch/arm/boot/dts/qcom-pmx65.dtsi
@@ -20,7 +20,7 @@
#thermal-sensor-cells = <0>;
};
- pmx65_gpios: pinctrl@8800 {
+ pmx65_gpios: gpio@8800 {
compatible = "qcom,pmx65-gpio", "qcom,spmi-gpio";
reg = <0x8800>;
gpio-controller;
diff --git a/arch/arm/boot/dts/qcom-sdx55-telit-fn980-tlb.dts b/arch/arm/boot/dts/qcom-sdx55-telit-fn980-tlb.dts
index a4fa468a095f..ac8b4626ae9a 100644
--- a/arch/arm/boot/dts/qcom-sdx55-telit-fn980-tlb.dts
+++ b/arch/arm/boot/dts/qcom-sdx55-telit-fn980-tlb.dts
@@ -282,40 +282,25 @@
};
&tlmm {
- pcie_ep_clkreq_default: pcie_ep_clkreq_default {
- mux {
- pins = "gpio56";
- function = "pcie_clkreq";
- };
- config {
- pins = "gpio56";
- drive-strength = <2>;
- bias-disable;
- };
+ pcie_ep_clkreq_default: pcie-ep-clkreq-default-state {
+ pins = "gpio56";
+ function = "pcie_clkreq";
+ drive-strength = <2>;
+ bias-disable;
};
- pcie_ep_perst_default: pcie_ep_perst_default {
- mux {
- pins = "gpio57";
- function = "gpio";
- };
- config {
- pins = "gpio57";
- drive-strength = <2>;
- bias-pull-down;
- };
+ pcie_ep_perst_default: pcie-ep-perst-default-state {
+ pins = "gpio57";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
};
- pcie_ep_wake_default: pcie_ep_wake_default {
- mux {
- pins = "gpio53";
- function = "gpio";
- };
- config {
- pins = "gpio53";
- drive-strength = <2>;
- bias-disable;
- };
+ pcie_ep_wake_default: pcie-ep-wake-default-state {
+ pins = "gpio53";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
};
diff --git a/arch/arm/boot/dts/qcom-sdx55.dtsi b/arch/arm/boot/dts/qcom-sdx55.dtsi
index c72540223fa9..f1c0dab40992 100644
--- a/arch/arm/boot/dts/qcom-sdx55.dtsi
+++ b/arch/arm/boot/dts/qcom-sdx55.dtsi
@@ -559,6 +559,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-ranges = <&tlmm 0 0 109>;
};
sram@1468f000 {
diff --git a/arch/arm/boot/dts/qcom-sdx65.dtsi b/arch/arm/boot/dts/qcom-sdx65.dtsi
index 4cd405db5500..b073e0c63df4 100644
--- a/arch/arm/boot/dts/qcom-sdx65.dtsi
+++ b/arch/arm/boot/dts/qcom-sdx65.dtsi
@@ -441,8 +441,8 @@
interrupt-controller;
};
- imem@1468f000 {
- compatible = "simple-mfd";
+ sram@1468f000 {
+ compatible = "qcom,sdx65-imem", "syscon", "simple-mfd";
reg = <0x1468f000 0x1000>;
ranges = <0x0 0x1468f000 0x1000>;
#address-cells = <1>;
diff --git a/arch/arm/boot/dts/r8a7742.dtsi b/arch/arm/boot/dts/r8a7742.dtsi
index 758a1bf02fae..73be346001cb 100644
--- a/arch/arm/boot/dts/r8a7742.dtsi
+++ b/arch/arm/boot/dts/r8a7742.dtsi
@@ -1298,7 +1298,7 @@
dma-names = "rx", "tx", "rxu", "txu";
};
ssi1: ssi-1 {
- interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x03>, <&audma1 0x04>,
<&audma0 0x49>, <&audma1 0x4a>;
dma-names = "rx", "tx", "rxu", "txu";
diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index db171e3c62f2..111a6d23159e 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -1252,7 +1252,7 @@
dma-names = "rx", "tx", "rxu", "txu";
};
ssi1: ssi-1 {
- interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x03>, <&audma1 0x04>,
<&audma0 0x49>, <&audma1 0x4a>;
dma-names = "rx", "tx", "rxu", "txu";
diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index d8f91d9f42ae..777b672b59cc 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -1365,7 +1365,7 @@
dma-names = "rx", "tx", "rxu", "txu";
};
ssi1: ssi-1 {
- interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x03>, <&audma1 0x04>,
<&audma0 0x49>, <&audma1 0x4a>;
dma-names = "rx", "tx", "rxu", "txu";
diff --git a/arch/arm/boot/dts/r8a7793.dtsi b/arch/arm/boot/dts/r8a7793.dtsi
index 9ebe7bfaf0ed..3e0be1b58931 100644
--- a/arch/arm/boot/dts/r8a7793.dtsi
+++ b/arch/arm/boot/dts/r8a7793.dtsi
@@ -1111,7 +1111,7 @@
dma-names = "rx", "tx", "rxu", "txu";
};
ssi1: ssi-1 {
- interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>;
dmas = <&audma0 0x03>, <&audma1 0x04>,
<&audma0 0x49>, <&audma1 0x4a>;
dma-names = "rx", "tx", "rxu", "txu";
diff --git a/arch/arm/boot/dts/r9a06g032.dtsi b/arch/arm/boot/dts/r9a06g032.dtsi
index 563024c9a4ae..41e19c0986ce 100644
--- a/arch/arm/boot/dts/r9a06g032.dtsi
+++ b/arch/arm/boot/dts/r9a06g032.dtsi
@@ -199,7 +199,7 @@
reg-io-width = <4>;
clocks = <&sysctrl R9A06G032_CLK_UART3>, <&sysctrl R9A06G032_HCLK_UART3>;
clock-names = "baudclk", "apb_pclk";
- dmas = <&dmamux 0 0 0 0 0 1>, <&dmamux 1 0 0 0 1 1>;
+ dmas = <&dmamux 0 0 0 0 0 1>, <&dmamux 1 0 0 0 1 1>;
dma-names = "rx", "tx";
status = "disabled";
};
@@ -212,7 +212,7 @@
reg-io-width = <4>;
clocks = <&sysctrl R9A06G032_CLK_UART4>, <&sysctrl R9A06G032_HCLK_UART4>;
clock-names = "baudclk", "apb_pclk";
- dmas = <&dmamux 2 0 0 0 2 1>, <&dmamux 3 0 0 0 3 1>;
+ dmas = <&dmamux 2 0 0 0 2 1>, <&dmamux 3 0 0 0 3 1>;
dma-names = "rx", "tx";
status = "disabled";
};
@@ -225,7 +225,7 @@
reg-io-width = <4>;
clocks = <&sysctrl R9A06G032_CLK_UART5>, <&sysctrl R9A06G032_HCLK_UART5>;
clock-names = "baudclk", "apb_pclk";
- dmas = <&dmamux 4 0 0 0 4 1>, <&dmamux 5 0 0 0 5 1>;
+ dmas = <&dmamux 4 0 0 0 4 1>, <&dmamux 5 0 0 0 5 1>;
dma-names = "rx", "tx";
status = "disabled";
};
@@ -238,7 +238,7 @@
reg-io-width = <4>;
clocks = <&sysctrl R9A06G032_CLK_UART6>, <&sysctrl R9A06G032_HCLK_UART6>;
clock-names = "baudclk", "apb_pclk";
- dmas = <&dmamux 6 0 0 0 6 1>, <&dmamux 7 0 0 0 7 1>;
+ dmas = <&dmamux 6 0 0 0 6 1>, <&dmamux 7 0 0 0 7 1>;
dma-names = "rx", "tx";
status = "disabled";
};
@@ -251,7 +251,7 @@
reg-io-width = <4>;
clocks = <&sysctrl R9A06G032_CLK_UART7>, <&sysctrl R9A06G032_HCLK_UART7>;
clock-names = "baudclk", "apb_pclk";
- dmas = <&dmamux 4 0 0 0 20 1>, <&dmamux 5 0 0 0 21 1>;
+ dmas = <&dmamux 4 0 0 0 20 1>, <&dmamux 5 0 0 0 21 1>;
dma-names = "rx", "tx";
status = "disabled";
};
diff --git a/arch/arm/boot/dts/sama7g5-pinfunc.h b/arch/arm/boot/dts/sama7g5-pinfunc.h
index 6e87f0d4b8fc..a67a156e26ab 100644
--- a/arch/arm/boot/dts/sama7g5-pinfunc.h
+++ b/arch/arm/boot/dts/sama7g5-pinfunc.h
@@ -673,7 +673,7 @@
#define PIN_PD8__GPIO PINMUX_PIN(PIN_PD8, 0, 0)
#define PIN_PD8__SDMMC2_DAT3 PINMUX_PIN(PIN_PD8, 1, 1)
#define PIN_PD8__I2SMCC0_DIN0 PINMUX_PIN(PIN_PD8, 3, 1)
-#define PIN_PD8__A11_NANDCLE PINMUX_PIN(PIN_PD8, 4, 2)
+#define PIN_PD8__A22_NANDCLE PINMUX_PIN(PIN_PD8, 4, 2)
#define PIN_PD8__TIOA2 PINMUX_PIN(PIN_PD8, 5, 2)
#define PIN_PD8__FLEXCOM11_IO0 PINMUX_PIN(PIN_PD8, 6, 5)
#define PIN_PD9 105
diff --git a/arch/arm/boot/dts/sama7g5.dtsi b/arch/arm/boot/dts/sama7g5.dtsi
index 7bd8ae8e8d38..ab131762ecb5 100644
--- a/arch/arm/boot/dts/sama7g5.dtsi
+++ b/arch/arm/boot/dts/sama7g5.dtsi
@@ -9,12 +9,15 @@
*
*/
+#include <dt-bindings/iio/adc/at91-sama5d2_adc.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/at91.h>
#include <dt-bindings/dma/at91.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/mfd/at91-usart.h>
+#include <dt-bindings/nvmem/microchip,sama7g5-otpc.h>
+#include <dt-bindings/thermal/thermal.h>
/ {
model = "Microchip SAMA7G5 family SoC";
@@ -34,6 +37,7 @@
clocks = <&pmc PMC_TYPE_CORE PMC_CPUPLL>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
+ #cooling-cells = <2>; /* min followed by max */
};
};
@@ -72,6 +76,46 @@
};
};
+ thermal-zones {
+ cpu_thermal: cpu-thermal {
+ polling-delay-passive = <1000>;
+ polling-delay = <5000>;
+ thermal-sensors = <&thermal_sensor>;
+
+ trips {
+ cpu_normal: cpu-alert0 {
+ temperature = <90000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ cpu_hot: cpu-alert1 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ cpu_critical: cpu-critical {
+ temperature = <100000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&cpu_normal>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+
+ map1 {
+ trip = <&cpu_hot>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+ };
+
clocks {
slow_xtal: slow_xtal {
compatible = "fixed-clock";
@@ -108,6 +152,13 @@
ranges;
};
+ thermal_sensor: thermal-sensor {
+ compatible = "generic-adc-thermal";
+ #thermal-sensor-cells = <0>;
+ io-channels = <&adc AT91_SAMA7G5_ADC_TEMP_CHANNEL>;
+ io-channel-names = "sensor-channel";
+ };
+
soc {
compatible = "simple-bus";
#address-cells = <1>;
@@ -153,7 +204,7 @@
};
};
- securam: securam@e0000000 {
+ securam: sram@e0000000 {
compatible = "microchip,sama7g5-securam", "atmel,sama5d2-securam", "mmio-sram";
reg = <0xe0000000 0x4000>;
clocks = <&pmc PMC_TYPE_PERIPHERAL 18>;
@@ -420,6 +471,9 @@
atmel,min-sample-rate-hz = <200000>;
atmel,max-sample-rate-hz = <20000000>;
atmel,startup-time-ms = <4>;
+ #io-channel-cells = <1>;
+ nvmem-cells = <&temperature_calib>;
+ nvmem-cell-names = "temperature_calib";
status = "disabled";
};
@@ -888,6 +942,17 @@
reg = <0xe3804000 0x1000>;
};
+ otpc: efuse@e8c00000 {
+ compatible = "microchip,sama7g5-otpc", "syscon";
+ reg = <0xe8c00000 0x100>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ temperature_calib: calib@1 {
+ reg = <OTP_PKT(1) 76>;
+ };
+ };
+
gic: interrupt-controller@e8c11000 {
compatible = "arm,cortex-a7-gic";
#interrupt-cells = <3>;
diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi
index 2459f3cd7dd9..6eda6fdc101b 100644
--- a/arch/arm/boot/dts/socfpga.dtsi
+++ b/arch/arm/boot/dts/socfpga.dtsi
@@ -453,7 +453,6 @@
compatible = "altr,socfpga-gate-clk";
clocks = <&f2s_periph_ref_clk>, <&main_nand_sdmmc_clk>, <&per_nand_mmc_clk>;
clk-gate = <0xa0 8>;
- clk-phase = <0 135>;
};
sdmmc_clk_divided: sdmmc_clk_divided {
@@ -755,7 +754,7 @@
reg = <0xff800000 0x1000>;
};
- mmc: dwmmc0@ff704000 {
+ mmc: mmc@ff704000 {
compatible = "altr,socfpga-dw-mshc";
reg = <0xff704000 0x1000>;
interrupts = <0 139 4>;
@@ -765,6 +764,7 @@
clocks = <&l4_mp_clk>, <&sdmmc_clk_divided>;
clock-names = "biu", "ciu";
resets = <&rst SDMMC_RESET>;
+ altr,sysmgr-syscon = <&sysmgr 0x108 3>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/socfpga_arria10.dtsi b/arch/arm/boot/dts/socfpga_arria10.dtsi
index 4370e3cbbb4b..3b2a2c9c6547 100644
--- a/arch/arm/boot/dts/socfpga_arria10.dtsi
+++ b/arch/arm/boot/dts/socfpga_arria10.dtsi
@@ -365,7 +365,6 @@
compatible = "altr,socfpga-a10-gate-clk";
clocks = <&sdmmc_free_clk>;
clk-gate = <0xC8 5>;
- clk-phase = <0 135>;
};
qspi_clk: qspi_clk {
@@ -656,7 +655,7 @@
arm,shared-override;
};
- mmc: dwmmc0@ff808000 {
+ mmc: mmc@ff808000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "altr,socfpga-dw-mshc";
@@ -666,6 +665,7 @@
clocks = <&l4_mp_clk>, <&sdmmc_clk>;
clock-names = "biu", "ciu";
resets = <&rst SDMMC_RESET>;
+ altr,sysmgr-syscon = <&sysmgr 0x28 4>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/socfpga_arria10_mercury_aa1.dtsi b/arch/arm/boot/dts/socfpga_arria10_mercury_aa1.dtsi
index ad7cd14de6b6..41f865c8c098 100644
--- a/arch/arm/boot/dts/socfpga_arria10_mercury_aa1.dtsi
+++ b/arch/arm/boot/dts/socfpga_arria10_mercury_aa1.dtsi
@@ -73,6 +73,7 @@
cap-sd-highspeed;
broken-cd;
bus-width = <4>;
+ clk-phase-sd-hs = <0>, <135>;
};
&osc1 {
diff --git a/arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts b/arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts
index 9aa897b79544..a662df319a84 100644
--- a/arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts
+++ b/arch/arm/boot/dts/socfpga_arria10_socdk_nand.dts
@@ -16,11 +16,11 @@
partition@0 {
label = "Boot and fpga data";
- reg = <0x0 0x02000000>;
+ reg = <0x0 0x02500000>;
};
partition@1c00000 {
label = "Root Filesystem - JFFS2";
- reg = <0x02000000 0x06000000>;
+ reg = <0x02500000 0x05500000>;
};
};
};
diff --git a/arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts b/arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts
index 64dc0799f3d7..d3969367f4b5 100644
--- a/arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts
+++ b/arch/arm/boot/dts/socfpga_arria10_socdk_sdmmc.dts
@@ -12,6 +12,7 @@
cap-mmc-highspeed;
broken-cd;
bus-width = <4>;
+ clk-phase-sd-hs = <0>, <135>;
};
&eccmgr {
diff --git a/arch/arm/boot/dts/socfpga_arria5.dtsi b/arch/arm/boot/dts/socfpga_arria5.dtsi
index 22dbf07afcff..40fecde65c54 100644
--- a/arch/arm/boot/dts/socfpga_arria5.dtsi
+++ b/arch/arm/boot/dts/socfpga_arria5.dtsi
@@ -18,11 +18,12 @@
};
};
- mmc0: dwmmc0@ff704000 {
+ mmc0: mmc@ff704000 {
broken-cd;
bus-width = <4>;
cap-mmc-highspeed;
cap-sd-highspeed;
+ clk-phase-sd-hs = <0>, <135>;
};
sysmgr@ffd08000 {
diff --git a/arch/arm/boot/dts/socfpga_arria5_socdk.dts b/arch/arm/boot/dts/socfpga_arria5_socdk.dts
index 7f5458d8fccc..c48385702a85 100644
--- a/arch/arm/boot/dts/socfpga_arria5_socdk.dts
+++ b/arch/arm/boot/dts/socfpga_arria5_socdk.dts
@@ -29,22 +29,22 @@
leds {
compatible = "gpio-leds";
- hps0 {
+ led-hps0 {
label = "hps_led0";
gpios = <&porta 0 1>;
};
- hps1 {
+ led-hps1 {
label = "hps_led1";
gpios = <&portb 11 1>;
};
- hps2 {
+ led-hps2 {
label = "hps_led2";
gpios = <&porta 17 1>;
};
- hps3 {
+ led-hps3 {
label = "hps_led3";
gpios = <&porta 18 1>;
};
diff --git a/arch/arm/boot/dts/socfpga_cyclone5.dtsi b/arch/arm/boot/dts/socfpga_cyclone5.dtsi
index 319a71e41ea4..305fe207b237 100644
--- a/arch/arm/boot/dts/socfpga_cyclone5.dtsi
+++ b/arch/arm/boot/dts/socfpga_cyclone5.dtsi
@@ -18,11 +18,12 @@
};
};
- mmc0: dwmmc0@ff704000 {
+ mmc0: mmc@ff704000 {
broken-cd;
bus-width = <4>;
cap-mmc-highspeed;
cap-sd-highspeed;
+ clk-phase-sd-hs = <0>, <135>;
};
sysmgr@ffd08000 {
diff --git a/arch/arm/boot/dts/socfpga_cyclone5_de0_nano_soc.dts b/arch/arm/boot/dts/socfpga_cyclone5_de0_nano_soc.dts
index c8f051fb2bf6..bedf577cb056 100644
--- a/arch/arm/boot/dts/socfpga_cyclone5_de0_nano_soc.dts
+++ b/arch/arm/boot/dts/socfpga_cyclone5_de0_nano_soc.dts
@@ -33,7 +33,7 @@
leds {
compatible = "gpio-leds";
- hps0 {
+ led-hps0 {
label = "hps_led0";
gpios = <&portb 24 0>;
linux,default-trigger = "heartbeat";
diff --git a/arch/arm/boot/dts/socfpga_cyclone5_mcv.dtsi b/arch/arm/boot/dts/socfpga_cyclone5_mcv.dtsi
index bd92806ffc12..3b9daddf91cd 100644
--- a/arch/arm/boot/dts/socfpga_cyclone5_mcv.dtsi
+++ b/arch/arm/boot/dts/socfpga_cyclone5_mcv.dtsi
@@ -18,5 +18,6 @@
&mmc0 { /* On-SoM eMMC */
bus-width = <8>;
+ clk-phase-sd-hs = <0>, <135>;
status = "okay";
};
diff --git a/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts b/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
index b2241205c7a9..c7f5fa0ba0f2 100644
--- a/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
+++ b/arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
@@ -29,22 +29,22 @@
leds {
compatible = "gpio-leds";
- hps0 {
+ led-hps0 {
label = "hps_led0";
gpios = <&portb 15 1>;
};
- hps1 {
+ led-hps1 {
label = "hps_led1";
gpios = <&portb 14 1>;
};
- hps2 {
+ led-hps2 {
label = "hps_led2";
gpios = <&portb 13 1>;
};
- hps3 {
+ led-hps3 {
label = "hps_led3";
gpios = <&portb 12 1>;
};
diff --git a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
index f24f17c2f5ee..e0630b0eed03 100644
--- a/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
+++ b/arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
@@ -141,7 +141,7 @@
reg = <0x50>;
};
- i2cswitch@70 {
+ i2c-mux@70 {
compatible = "nxp,pca9548";
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm/boot/dts/socfpga_vt.dts b/arch/arm/boot/dts/socfpga_vt.dts
index a77846f73b34..3d0d806888b7 100644
--- a/arch/arm/boot/dts/socfpga_vt.dts
+++ b/arch/arm/boot/dts/socfpga_vt.dts
@@ -29,7 +29,7 @@
};
};
- dwmmc0@ff704000 {
+ mmc@ff704000 {
broken-cd;
bus-width = <4>;
cap-mmc-highspeed;
diff --git a/arch/arm/boot/dts/spear600.dtsi b/arch/arm/boot/dts/spear600.dtsi
index fd41243a0b2c..6b67c0ceaed9 100644
--- a/arch/arm/boot/dts/spear600.dtsi
+++ b/arch/arm/boot/dts/spear600.dtsi
@@ -47,7 +47,7 @@
compatible = "arm,pl110", "arm,primecell";
reg = <0xfc200000 0x1000>;
interrupt-parent = <&vic1>;
- interrupts = <12>;
+ interrupts = <13>;
status = "disabled";
};
@@ -207,6 +207,36 @@
interrupts = <6>;
status = "disabled";
};
+
+ ssp1: spi@d0100000 {
+ compatible = "arm,pl022", "arm,primecell";
+ reg = <0xd0100000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-parent = <&vic0>;
+ interrupts = <26>;
+ status = "disabled";
+ };
+
+ ssp2: spi@d0180000 {
+ compatible = "arm,pl022", "arm,primecell";
+ reg = <0xd0180000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-parent = <&vic0>;
+ interrupts = <27>;
+ status = "disabled";
+ };
+
+ ssp3: spi@d8180000 {
+ compatible = "arm,pl022", "arm,primecell";
+ reg = <0xd8180000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupt-parent = <&vic1>;
+ interrupts = <5>;
+ status = "disabled";
+ };
};
};
};
diff --git a/arch/arm/boot/dts/ste-dbx5x0.dtsi b/arch/arm/boot/dts/ste-dbx5x0.dtsi
index 9afe8301bd47..a42a4fd69299 100644
--- a/arch/arm/boot/dts/ste-dbx5x0.dtsi
+++ b/arch/arm/boot/dts/ste-dbx5x0.dtsi
@@ -1149,17 +1149,15 @@
compatible = "stericsson,ux500-cryp";
reg = <0xa03cb000 0x1000>;
interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
-
- v-ape-supply = <&db8500_vape_reg>;
clocks = <&prcc_pclk 6 1>;
+ power-domains = <&pm_domains DOMAIN_VAPE>;
};
hash@a03c2000 {
compatible = "stericsson,ux500-hash";
reg = <0xa03c2000 0x1000>;
-
- v-ape-supply = <&db8500_vape_reg>;
clocks = <&prcc_pclk 6 2>;
+ power-domains = <&pm_domains DOMAIN_VAPE>;
};
};
};
diff --git a/arch/arm/boot/dts/ste-ux500-samsung-codina-tmo.dts b/arch/arm/boot/dts/ste-ux500-samsung-codina-tmo.dts
index 27a3ab7e25e1..e036393d5415 100644
--- a/arch/arm/boot/dts/ste-ux500-samsung-codina-tmo.dts
+++ b/arch/arm/boot/dts/ste-ux500-samsung-codina-tmo.dts
@@ -247,7 +247,7 @@
};
};
- spi-gpio-0 {
+ spi {
compatible = "spi-gpio";
/* Clock on GPIO220, pin SCL */
sck-gpios = <&gpio6 28 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/ste-ux500-samsung-codina.dts b/arch/arm/boot/dts/ste-ux500-samsung-codina.dts
index b88f0c07873d..1a6d24a7ccb8 100644
--- a/arch/arm/boot/dts/ste-ux500-samsung-codina.dts
+++ b/arch/arm/boot/dts/ste-ux500-samsung-codina.dts
@@ -333,7 +333,7 @@
};
};
- spi-gpio-0 {
+ spi {
compatible = "spi-gpio";
/* Clock on GPIO220, pin SCL */
sck-gpios = <&gpio6 28 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/ste-ux500-samsung-gavini.dts b/arch/arm/boot/dts/ste-ux500-samsung-gavini.dts
index 7231bc745200..5b445fa4c8c0 100644
--- a/arch/arm/boot/dts/ste-ux500-samsung-gavini.dts
+++ b/arch/arm/boot/dts/ste-ux500-samsung-gavini.dts
@@ -277,7 +277,7 @@
/*
* TODO: See if we can use the PL023 for this instead.
*/
- spi-gpio-0 {
+ spi {
compatible = "spi-gpio";
/* Clock on GPIO220, pin SCL */
sck-gpios = <&gpio6 28 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm/boot/dts/ste-ux500-samsung-janice.dts b/arch/arm/boot/dts/ste-ux500-samsung-janice.dts
index 69387e8754a9..e901cb76b899 100644
--- a/arch/arm/boot/dts/ste-ux500-samsung-janice.dts
+++ b/arch/arm/boot/dts/ste-ux500-samsung-janice.dts
@@ -271,7 +271,7 @@
* this derivative is 3wire support, so it cannot be used to drive
* this panel interface. We have to use GPIO bit-banging instead.
*/
- spi-gpio-0 {
+ spi {
compatible = "spi-gpio";
/* Clock on GPIO220 */
sck-gpios = <&gpio6 28 GPIO_ACTIVE_HIGH>;
@@ -373,9 +373,13 @@
#address-cells = <1>;
#size-cells = <0>;
- nfc@30 {
- compatible = "nxp,pn547", "nxp,nxp-nci-i2c";
- reg = <0x30>;
+ /* This is only mounted on the GT-I9070P */
+ nfc@2b { /* 0x30? */
+ /* NXP NFC circuit PN544 C1 marked NXP 44501 */
+ compatible = "nxp,pn544-i2c";
+ /* IF0, IF1 high, gives I2C address 0x2B */
+ reg = <0x2b>;
+ clock-frequency = <400000>;
/* NFC IRQ on GPIO32 */
interrupt-parent = <&gpio1>;
interrupts = <0 IRQ_TYPE_EDGE_FALLING>;
@@ -384,7 +388,7 @@
/* GPIO88 */
enable-gpios = <&gpio2 24 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
- pinctrl-0 = <&pn547_janice_default>;
+ pinctrl-0 = <&pn544_janice_default>;
};
};
@@ -959,7 +963,7 @@
};
};
nfc {
- pn547_janice_default: pn547_janice {
+ pn544_janice_default: pn544_janice {
/* Interrupt line */
janice_cfg1 {
pins = "GPIO32_V2";
diff --git a/arch/arm/boot/dts/ste-ux500-samsung-kyle.dts b/arch/arm/boot/dts/ste-ux500-samsung-kyle.dts
index 167846df3104..45fab5283a9d 100644
--- a/arch/arm/boot/dts/ste-ux500-samsung-kyle.dts
+++ b/arch/arm/boot/dts/ste-ux500-samsung-kyle.dts
@@ -315,6 +315,21 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&u1rxtx_a_1_default &u1ctsrts_a_1_default>;
pinctrl-1 = <&u1rxtx_a_1_sleep &u1ctsrts_a_1_sleep>;
+
+ gnss {
+ /* The CSRG05TA03-ICJE-R is a SirfStarV 5t chip */
+ compatible = "csr,csrg05ta03-icje-r";
+ /* GPS_RSTN on GPIO21 */
+ reset-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
+ /* GPS_ON_OFF on GPIO86 */
+ sirf,onoff-gpios = <&gpio2 22 GPIO_ACTIVE_HIGH>;
+ /* GPS_1V8 (VSMPS2) */
+ vcc-supply = <&db8500_vsmps2_reg>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&g05ta03_kyle_default>;
+ /* According to /etc/sirfgps.conf */
+ current-speed = <460800>;
+ };
};
/* Debugging console UART connected to AB8505 USB */
@@ -674,6 +689,20 @@
};
};
};
+ g05ta03 {
+ g05ta03_kyle_default: g05ta03 {
+ /* Reset line, start out de-asserted */
+ kyle_cfg1 {
+ pins = "GPIO21_AB3";
+ ste,config = <&gpio_out_hi>;
+ };
+ /* GPS_ON_OFF, start out deasserted (off) */
+ kyle_cfg2 {
+ pins = "GPIO86_C6";
+ ste,config = <&gpio_out_lo>;
+ };
+ };
+ };
};
&ab8505_gpio {
diff --git a/arch/arm/boot/dts/stih410-b2260.dts b/arch/arm/boot/dts/stih410-b2260.dts
index 26d93f26f6d0..240b62040000 100644
--- a/arch/arm/boot/dts/stih410-b2260.dts
+++ b/arch/arm/boot/dts/stih410-b2260.dts
@@ -27,26 +27,26 @@
leds {
compatible = "gpio-leds";
- user_green_1 {
+ led-user-green-1 {
label = "User_green_1";
gpios = <&pio1 3 GPIO_ACTIVE_LOW>;
linux,default-trigger = "heartbeat";
default-state = "off";
};
- user_green_2 {
+ led-user-green-2 {
label = "User_green_2";
gpios = <&pio4 1 GPIO_ACTIVE_LOW>;
default-state = "off";
};
- user_green_3 {
+ led-user-green-3 {
label = "User_green_3";
gpios = <&pio2 1 GPIO_ACTIVE_LOW>;
default-state = "off";
};
- user_green_4 {
+ led-user-green-4 {
label = "User_green_4";
gpios = <&pio2 5 GPIO_ACTIVE_LOW>;
default-state = "off";
diff --git a/arch/arm/boot/dts/stih418-b2199.dts b/arch/arm/boot/dts/stih418-b2199.dts
index d21bcc7c1271..53ac6c2b7b7d 100644
--- a/arch/arm/boot/dts/stih418-b2199.dts
+++ b/arch/arm/boot/dts/stih418-b2199.dts
@@ -26,12 +26,12 @@
leds {
compatible = "gpio-leds";
- red {
+ led-red {
label = "Front Panel LED";
gpios = <&pio4 1 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
};
- green {
+ led-green {
gpios = <&pio1 3 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
diff --git a/arch/arm/boot/dts/stih418-b2264.dts b/arch/arm/boot/dts/stih418-b2264.dts
index a99604bebf8c..34a518b037ab 100644
--- a/arch/arm/boot/dts/stih418-b2264.dts
+++ b/arch/arm/boot/dts/stih418-b2264.dts
@@ -76,7 +76,7 @@
soc {
leds {
compatible = "gpio-leds";
- green {
+ led-green {
gpios = <&pio1 3 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
diff --git a/arch/arm/boot/dts/stihxxx-b2120.dtsi b/arch/arm/boot/dts/stihxxx-b2120.dtsi
index 2aa94605d3d4..920a0bad7494 100644
--- a/arch/arm/boot/dts/stihxxx-b2120.dtsi
+++ b/arch/arm/boot/dts/stihxxx-b2120.dtsi
@@ -9,12 +9,12 @@
/ {
leds {
compatible = "gpio-leds";
- red {
+ led-red {
label = "Front Panel LED";
gpios = <&pio4 1 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
};
- green {
+ led-green {
gpios = <&pio1 3 GPIO_ACTIVE_HIGH>;
default-state = "off";
};
diff --git a/arch/arm/boot/dts/stm32h743.dtsi b/arch/arm/boot/dts/stm32h743.dtsi
index 2059593da21d..28e3deb20e1e 100644
--- a/arch/arm/boot/dts/stm32h743.dtsi
+++ b/arch/arm/boot/dts/stm32h743.dtsi
@@ -375,7 +375,6 @@
arm,primecell-periphid = <0x10153180>;
reg = <0x52007000 0x1000>;
interrupts = <49>;
- interrupt-names = "cmd_irq";
clocks = <&rcc SDMMC1_CK>;
clock-names = "apb_pclk";
resets = <&rcc STM32H7_AHB3_RESET(SDMMC1)>;
@@ -389,7 +388,6 @@
arm,primecell-periphid = <0x10153180>;
reg = <0x48022400 0x400>;
interrupts = <124>;
- interrupt-names = "cmd_irq";
clocks = <&rcc SDMMC2_CK>;
clock-names = "apb_pclk";
resets = <&rcc STM32H7_AHB2_RESET(SDMMC2)>;
diff --git a/arch/arm/boot/dts/stm32mp13-pinctrl.dtsi b/arch/arm/boot/dts/stm32mp13-pinctrl.dtsi
index efdd163eba30..d377d4c0bef5 100644
--- a/arch/arm/boot/dts/stm32mp13-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stm32mp13-pinctrl.dtsi
@@ -6,6 +6,13 @@
#include <dt-bindings/pinctrl/stm32-pinfunc.h>
&pinctrl {
+ adc1_usb_cc_pins_a: adc1-usb-cc-pins-0 {
+ pins {
+ pinmux = <STM32_PINMUX('F', 12, ANALOG)>, /* ADC1 in6 */
+ <STM32_PINMUX('A', 3, ANALOG)>; /* ADC1 in12 */
+ };
+ };
+
i2c1_pins_a: i2c1-0 {
pins {
pinmux = <STM32_PINMUX('D', 12, AF5)>, /* I2C1_SCL */
@@ -40,6 +47,13 @@
};
};
+ mcp23017_pins_a: mcp23017-0 {
+ pins {
+ pinmux = <STM32_PINMUX('G', 12, GPIO)>;
+ bias-pull-up;
+ };
+ };
+
sdmmc1_b4_pins_a: sdmmc1-b4-0 {
pins {
pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
@@ -165,6 +179,13 @@
};
};
+ stm32g0_intn_pins_a: stm32g0-intn-0 {
+ pins {
+ pinmux = <STM32_PINMUX('I', 2, GPIO)>;
+ bias-pull-up;
+ };
+ };
+
uart4_pins_a: uart4-0 {
pins1 {
pinmux = <STM32_PINMUX('D', 6, AF8)>; /* UART4_TX */
diff --git a/arch/arm/boot/dts/stm32mp131.dtsi b/arch/arm/boot/dts/stm32mp131.dtsi
index dd35a607073d..accc3824f7e9 100644
--- a/arch/arm/boot/dts/stm32mp131.dtsi
+++ b/arch/arm/boot/dts/stm32mp131.dtsi
@@ -77,6 +77,28 @@
always-on;
};
+ /* PWR 1v1, 1v8 and 3v3 regulators defined as fixed, waiting for SCMI */
+ reg11: reg11 {
+ compatible = "regulator-fixed";
+ regulator-name = "reg11";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ };
+
+ reg18: reg18 {
+ compatible = "regulator-fixed";
+ regulator-name = "reg18";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ usb33: usb33 {
+ compatible = "regulator-fixed";
+ regulator-name = "usb33";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
soc {
compatible = "simple-bus";
#address-cells = <1>;
@@ -231,6 +253,66 @@
dma-channels = <16>;
};
+ adc_2: adc@48004000 {
+ compatible = "st,stm32mp13-adc-core";
+ reg = <0x48004000 0x400>;
+ interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc ADC2>, <&rcc ADC2_K>;
+ clock-names = "bus", "adc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+
+ adc2: adc@0 {
+ compatible = "st,stm32mp13-adc";
+ #io-channel-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0>;
+ interrupt-parent = <&adc_2>;
+ interrupts = <0>;
+ dmas = <&dmamux1 10 0x400 0x80000001>;
+ dma-names = "rx";
+ status = "disabled";
+
+ channel@13 {
+ reg = <13>;
+ label = "vrefint";
+ };
+ channel@14 {
+ reg = <14>;
+ label = "vddcore";
+ };
+ channel@16 {
+ reg = <16>;
+ label = "vddcpu";
+ };
+ channel@17 {
+ reg = <17>;
+ label = "vddq_ddr";
+ };
+ };
+ };
+
+ usbotg_hs: usb@49000000 {
+ compatible = "st,stm32mp15-hsotg", "snps,dwc2";
+ reg = <0x49000000 0x40000>;
+ clocks = <&rcc USBO_K>;
+ clock-names = "otg";
+ resets = <&rcc USBO_R>;
+ reset-names = "dwc2";
+ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+ g-rx-fifo-size = <512>;
+ g-np-tx-fifo-size = <32>;
+ g-tx-fifo-size = <256 16 16 16 16 16 16 16>;
+ dr_mode = "otg";
+ otg-rev = <0x200>;
+ usb33d-supply = <&usb33>;
+ status = "disabled";
+ };
+
spi4: spi@4c002000 {
compatible = "st,stm32h7-spi";
reg = <0x4c002000 0x400>;
@@ -354,7 +436,6 @@
arm,primecell-periphid = <0x20253180>;
reg = <0x58005000 0x1000>, <0x58006000 0x1000>;
interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cmd_irq";
clocks = <&rcc SDMMC1_K>;
clock-names = "apb_pclk";
resets = <&rcc SDMMC1_R>;
@@ -369,7 +450,6 @@
arm,primecell-periphid = <0x20253180>;
reg = <0x58007000 0x1000>, <0x58008000 0x1000>;
interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cmd_irq";
clocks = <&rcc SDMMC2_K>;
clock-names = "apb_pclk";
resets = <&rcc SDMMC2_R>;
@@ -379,6 +459,25 @@
status = "disabled";
};
+ usbh_ohci: usb@5800c000 {
+ compatible = "generic-ohci";
+ reg = <0x5800c000 0x1000>;
+ clocks = <&usbphyc>, <&rcc USBH>;
+ resets = <&rcc USBH_R>;
+ interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ usbh_ehci: usb@5800d000 {
+ compatible = "generic-ehci";
+ reg = <0x5800d000 0x1000>;
+ clocks = <&usbphyc>, <&rcc USBH>;
+ resets = <&rcc USBH_R>;
+ interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+ companion = <&usbh_ohci>;
+ status = "disabled";
+ };
+
iwdg2: watchdog@5a002000 {
compatible = "st,stm32mp1-iwdg";
reg = <0x5a002000 0x400>;
@@ -387,6 +486,29 @@
status = "disabled";
};
+ usbphyc: usbphyc@5a006000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #clock-cells = <0>;
+ compatible = "st,stm32mp1-usbphyc";
+ reg = <0x5a006000 0x1000>;
+ clocks = <&rcc USBPHY_K>;
+ resets = <&rcc USBPHY_R>;
+ vdda1v1-supply = <&reg11>;
+ vdda1v8-supply = <&reg18>;
+ status = "disabled";
+
+ usbphyc_port0: usb-phy@0 {
+ #phy-cells = <0>;
+ reg = <0>;
+ };
+
+ usbphyc_port1: usb-phy@1 {
+ #phy-cells = <1>;
+ reg = <1>;
+ };
+ };
+
rtc: rtc@5c004000 {
compatible = "st,stm32mp1-rtc";
reg = <0x5c004000 0x400>;
diff --git a/arch/arm/boot/dts/stm32mp133.dtsi b/arch/arm/boot/dts/stm32mp133.dtsi
index 531c263c9f46..df451c3c2a26 100644
--- a/arch/arm/boot/dts/stm32mp133.dtsi
+++ b/arch/arm/boot/dts/stm32mp133.dtsi
@@ -33,5 +33,36 @@
bosch,mram-cfg = <0x1400 0 0 32 0 0 2 2>;
status = "disabled";
};
+
+ adc_1: adc@48003000 {
+ compatible = "st,stm32mp13-adc-core";
+ reg = <0x48003000 0x400>;
+ interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc ADC1>, <&rcc ADC1_K>;
+ clock-names = "bus", "adc";
+ interrupt-controller;
+ #interrupt-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+
+ adc1: adc@0 {
+ compatible = "st,stm32mp13-adc";
+ #io-channel-cells = <1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x0>;
+ interrupt-parent = <&adc_1>;
+ interrupts = <0>;
+ dmas = <&dmamux1 9 0x400 0x80000001>;
+ dma-names = "rx";
+ status = "disabled";
+
+ channel@18 {
+ reg = <18>;
+ label = "vrefint";
+ };
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/stm32mp135f-dk.dts b/arch/arm/boot/dts/stm32mp135f-dk.dts
index de341d17e87d..9ff5a3eaf55b 100644
--- a/arch/arm/boot/dts/stm32mp135f-dk.dts
+++ b/arch/arm/boot/dts/stm32mp135f-dk.dts
@@ -59,6 +59,22 @@
};
};
+ v3v3_sw: v3v3-sw {
+ compatible = "regulator-fixed";
+ regulator-name = "v3v3_sw";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ vdd_adc: vdd-adc {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd_adc";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
vdd_sd: vdd-sd {
compatible = "regulator-fixed";
regulator-name = "vdd_sd";
@@ -66,6 +82,39 @@
regulator-max-microvolt = <2900000>;
regulator-always-on;
};
+
+ vdd_usb: vdd-usb {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd_usb";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+};
+
+&adc_1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&adc1_usb_cc_pins_a>;
+ vdda-supply = <&vdd_adc>;
+ vref-supply = <&vdd_adc>;
+ status = "okay";
+ adc1: adc@0 {
+ status = "okay";
+ /*
+ * Type-C USB_PWR_CC1 & USB_PWR_CC2 on in6 & in12.
+ * Use at least 5 * RC time, e.g. 5 * (Rp + Rd) * C:
+ * 5 * (5.1 + 47kOhms) * 5pF => 1.3us.
+ * Use arbitrary margin here (e.g. 5us).
+ */
+ channel@6 {
+ reg = <6>;
+ st,min-sample-time-ns = <5000>;
+ };
+ channel@12 {
+ reg = <12>;
+ st,min-sample-time-ns = <5000>;
+ };
+ };
};
&i2c1 {
@@ -79,6 +128,42 @@
/* spare dmas for other usage */
/delete-property/dmas;
/delete-property/dma-names;
+
+ mcp23017: pinctrl@21 {
+ compatible = "microchip,mcp23017";
+ reg = <0x21>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-parent = <&gpiog>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcp23017_pins_a>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ microchip,irq-mirror;
+ };
+
+ typec@53 {
+ compatible = "st,stm32g0-typec";
+ reg = <0x53>;
+ /* Alert pin on PI2 */
+ interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-parent = <&gpioi>;
+ /* Internal pull-up on PI2 */
+ pinctrl-names = "default";
+ pinctrl-0 = <&stm32g0_intn_pins_a>;
+ firmware-name = "stm32g0-ucsi.mp135f-dk.fw";
+ connector {
+ compatible = "usb-c-connector";
+ label = "USB-C";
+
+ port {
+ con_usb_c_g0_ep: endpoint {
+ remote-endpoint = <&usbotg_hs_ep>;
+ };
+ };
+ };
+ };
};
&i2c5 {
@@ -108,7 +193,7 @@
pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_clk_pins_a>;
pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_clk_pins_a>;
pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>;
- broken-cd;
+ cd-gpios = <&gpioh 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
disable-wp;
st,neg-edge;
bus-width = <4>;
@@ -128,3 +213,60 @@
pinctrl-0 = <&uart4_pins_a>;
status = "okay";
};
+
+&usbh_ehci {
+ phys = <&usbphyc_port0>;
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ /* onboard HUB */
+ hub@1 {
+ compatible = "usb424,2514";
+ reg = <1>;
+ vdd-supply = <&v3v3_sw>;
+ };
+};
+
+&usbotg_hs {
+ phys = <&usbphyc_port1 0>;
+ phy-names = "usb2-phy";
+ usb-role-switch;
+ status = "okay";
+ port {
+ usbotg_hs_ep: endpoint {
+ remote-endpoint = <&con_usb_c_g0_ep>;
+ };
+ };
+};
+
+&usbphyc {
+ status = "okay";
+};
+
+&usbphyc_port0 {
+ phy-supply = <&vdd_usb>;
+ st,current-boost-microamp = <1000>;
+ st,decrease-hs-slew-rate;
+ st,tune-hs-dc-level = <2>;
+ st,enable-hs-rftime-reduction;
+ st,trim-hs-current = <11>;
+ st,trim-hs-impedance = <2>;
+ st,tune-squelch-level = <1>;
+ st,enable-hs-rx-gain-eq;
+ st,no-hs-ftime-ctrl;
+ st,no-lsfs-sc;
+};
+
+&usbphyc_port1 {
+ phy-supply = <&vdd_usb>;
+ st,current-boost-microamp = <1000>;
+ st,decrease-hs-slew-rate;
+ st,tune-hs-dc-level = <2>;
+ st,enable-hs-rftime-reduction;
+ st,trim-hs-current = <11>;
+ st,trim-hs-impedance = <2>;
+ st,tune-squelch-level = <1>;
+ st,enable-hs-rx-gain-eq;
+ st,no-hs-ftime-ctrl;
+ st,no-lsfs-sc;
+};
diff --git a/arch/arm/boot/dts/stm32mp151.dtsi b/arch/arm/boot/dts/stm32mp151.dtsi
index e02b3f5d44cb..5491b6c4dec2 100644
--- a/arch/arm/boot/dts/stm32mp151.dtsi
+++ b/arch/arm/boot/dts/stm32mp151.dtsi
@@ -1118,7 +1118,6 @@
arm,primecell-periphid = <0x00253180>;
reg = <0x48004000 0x400>;
interrupts = <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cmd_irq";
clocks = <&rcc SDMMC3_K>;
clock-names = "apb_pclk";
resets = <&rcc SDMMC3_R>;
@@ -1439,7 +1438,6 @@
arm,primecell-periphid = <0x00253180>;
reg = <0x58005000 0x1000>;
interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cmd_irq";
clocks = <&rcc SDMMC1_K>;
clock-names = "apb_pclk";
resets = <&rcc SDMMC1_R>;
@@ -1454,7 +1452,6 @@
arm,primecell-periphid = <0x00253180>;
reg = <0x58007000 0x1000>;
interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cmd_irq";
clocks = <&rcc SDMMC2_K>;
clock-names = "apb_pclk";
resets = <&rcc SDMMC2_R>;
diff --git a/arch/arm/boot/dts/stm32mp151a-dhcor-testbench.dts b/arch/arm/boot/dts/stm32mp151a-dhcor-testbench.dts
new file mode 100644
index 000000000000..e0f828ecc2fa
--- /dev/null
+++ b/arch/arm/boot/dts/stm32mp151a-dhcor-testbench.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Copyright (C) 2022 Marek Vasut <marex@denx.de>
+ */
+
+/dts-v1/;
+
+#include "stm32mp151.dtsi"
+#include "stm32mp15xx-dhcor-som.dtsi"
+#include "stm32mp15xx-dhcor-testbench.dtsi"
+
+/ {
+ model = "DH electronics STM32MP151A DHCOR Testbench";
+ compatible = "dh,stm32mp151a-dhcor-testbench",
+ "dh,stm32mp151a-dhcor-som",
+ "st,stm32mp151";
+};
diff --git a/arch/arm/boot/dts/stm32mp157a-dhcor-avenger96.dts b/arch/arm/boot/dts/stm32mp157a-dhcor-avenger96.dts
index 2e3c9fbb4eb3..275167f26fd9 100644
--- a/arch/arm/boot/dts/stm32mp157a-dhcor-avenger96.dts
+++ b/arch/arm/boot/dts/stm32mp157a-dhcor-avenger96.dts
@@ -13,7 +13,6 @@
/dts-v1/;
#include "stm32mp157.dtsi"
-#include "stm32mp15xc.dtsi"
#include "stm32mp15xx-dhcor-som.dtsi"
#include "stm32mp15xx-dhcor-avenger96.dtsi"
diff --git a/arch/arm/boot/dts/stm32mp157c-emstamp-argon.dtsi b/arch/arm/boot/dts/stm32mp157c-emstamp-argon.dtsi
index 30156b7546ed..aef02e6421a3 100644
--- a/arch/arm/boot/dts/stm32mp157c-emstamp-argon.dtsi
+++ b/arch/arm/boot/dts/stm32mp157c-emstamp-argon.dtsi
@@ -173,7 +173,7 @@
phy-handle = <&phy0>;
st,eth-ref-clk-sel;
- mdio0 {
+ mdio {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,dwmac-mdio";
diff --git a/arch/arm/boot/dts/stm32mp157c-ev1.dts b/arch/arm/boot/dts/stm32mp157c-ev1.dts
index 050c3c27a420..a665189fe621 100644
--- a/arch/arm/boot/dts/stm32mp157c-ev1.dts
+++ b/arch/arm/boot/dts/stm32mp157c-ev1.dts
@@ -144,7 +144,7 @@
max-speed = <1000>;
phy-handle = <&phy0>;
- mdio0 {
+ mdio {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,dwmac-mdio";
@@ -370,6 +370,14 @@
&usbh_ehci {
phys = <&usbphyc_port0>;
status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ /* onboard HUB */
+ hub@1 {
+ compatible = "usb424,2514";
+ reg = <1>;
+ vdd-supply = <&v3v3>;
+ };
};
&usbotg_hs {
@@ -393,6 +401,11 @@
st,tune-squelch-level = <3>;
st,tune-hs-rx-offset = <2>;
st,no-lsfs-sc;
+
+ connector {
+ compatible = "usb-a-connector";
+ vbus-supply = <&vbus_sw>;
+ };
};
&usbphyc_port1 {
diff --git a/arch/arm/boot/dts/stm32mp157c-lxa-mc1.dts b/arch/arm/boot/dts/stm32mp157c-lxa-mc1.dts
index e8d2ec41d537..cb00ce7cec8b 100644
--- a/arch/arm/boot/dts/stm32mp157c-lxa-mc1.dts
+++ b/arch/arm/boot/dts/stm32mp157c-lxa-mc1.dts
@@ -112,7 +112,7 @@
phy-handle = <&ethphy>;
status = "okay";
- mdio0 {
+ mdio {
compatible = "snps,dwmac-mdio";
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm/boot/dts/stm32mp157c-odyssey.dts b/arch/arm/boot/dts/stm32mp157c-odyssey.dts
index ed66d25b8bf3..a8b3f7a54703 100644
--- a/arch/arm/boot/dts/stm32mp157c-odyssey.dts
+++ b/arch/arm/boot/dts/stm32mp157c-odyssey.dts
@@ -41,7 +41,7 @@
assigned-clock-rates = <125000000>; /* Clock PLL4 to 750Mhz in ATF/U-Boot */
st,eth-clk-sel;
- mdio0 {
+ mdio {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,dwmac-mdio";
diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi b/arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi
index 5f586f024060..4709677151aa 100644
--- a/arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi
+++ b/arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi
@@ -242,7 +242,7 @@
sai2a_port: port {
sai2a_endpoint: endpoint {
remote-endpoint = <&sgtl5000_tx_endpoint>;
- format = "i2s";
+ dai-format = "i2s";
mclk-fs = <512>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <16>;
@@ -260,7 +260,7 @@
sai2b_port: port {
sai2b_endpoint: endpoint {
remote-endpoint = <&sgtl5000_rx_endpoint>;
- format = "i2s";
+ dai-format = "i2s";
mclk-fs = <512>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <16>;
diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi b/arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi
index 238a611192e7..002f221f1694 100644
--- a/arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi
+++ b/arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi
@@ -125,7 +125,7 @@
max-speed = <100>;
phy-handle = <&phy0>;
- mdio0 {
+ mdio {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,dwmac-mdio";
diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi b/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi
index 90933077d66d..50af4a27d6be 100644
--- a/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi
+++ b/arch/arm/boot/dts/stm32mp15xx-dhcor-avenger96.dtsi
@@ -66,7 +66,6 @@
led4 {
label = "green:user3";
gpios = <&gpiog 1 GPIO_ACTIVE_HIGH>;
- linux,default-trigger = "none";
default-state = "off";
panic-indicator;
};
@@ -100,7 +99,7 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
- gpios = <&gpioz 3 GPIO_ACTIVE_HIGH>;
+ gpio = <&gpioz 3 GPIO_ACTIVE_HIGH>;
enable-active-high;
};
};
@@ -151,7 +150,7 @@
max-speed = <1000>;
phy-handle = <&phy0>;
- mdio0 {
+ mdio {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,dwmac-mdio";
@@ -359,7 +358,7 @@
sai2a_port: port {
sai2a_endpoint: endpoint {
remote-endpoint = <&adv7513_i2s0>;
- format = "i2s";
+ dai-format = "i2s";
mclk-fs = <256>;
};
};
diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcor-drc-compact.dtsi b/arch/arm/boot/dts/stm32mp15xx-dhcor-drc-compact.dtsi
index 27477bb219de..c32c160f97f2 100644
--- a/arch/arm/boot/dts/stm32mp15xx-dhcor-drc-compact.dtsi
+++ b/arch/arm/boot/dts/stm32mp15xx-dhcor-drc-compact.dtsi
@@ -78,7 +78,7 @@
max-speed = <1000>;
phy-handle = <&phy0>;
- mdio0 {
+ mdio {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,dwmac-mdio";
diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcor-testbench.dtsi b/arch/arm/boot/dts/stm32mp15xx-dhcor-testbench.dtsi
new file mode 100644
index 000000000000..5fdb74b652ac
--- /dev/null
+++ b/arch/arm/boot/dts/stm32mp15xx-dhcor-testbench.dtsi
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
+/*
+ * Copyright (C) 2022 Marek Vasut <marex@denx.de>
+ */
+
+/ {
+ aliases {
+ ethernet0 = &ethernet0;
+ mmc0 = &sdmmc1;
+ mmc1 = &sdmmc2;
+ serial0 = &uart4;
+ serial1 = &uart7;
+ spi0 = &qspi;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ sd_switch: regulator-sd_switch {
+ compatible = "regulator-gpio";
+ regulator-name = "sd_switch";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2900000>;
+ regulator-type = "voltage";
+ regulator-always-on;
+
+ gpios = <&gpioi 5 GPIO_ACTIVE_HIGH>;
+ gpios-states = <0>;
+ states = <1800000 0x1>,
+ <2900000 0x0>;
+ };
+};
+
+&adc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&adc12_ain_pins_b>;
+ vdd-supply = <&vdd>;
+ vdda-supply = <&vdda>;
+ vref-supply = <&vdda>;
+ status = "okay";
+
+ adc1: adc@0 {
+ st,adc-channels = <0 1 6>;
+ st,min-sample-time-nsecs = <5000>;
+ status = "okay";
+ };
+
+ adc2: adc@100 {
+ st,adc-channels = <0 1 2>;
+ st,min-sample-time-nsecs = <5000>;
+ status = "okay";
+ };
+};
+
+&ethernet0 {
+ status = "okay";
+ pinctrl-0 = <&ethernet0_rgmii_pins_c>;
+ pinctrl-1 = <&ethernet0_rgmii_sleep_pins_c>;
+ pinctrl-names = "default", "sleep";
+ phy-mode = "rgmii";
+ max-speed = <1000>;
+ phy-handle = <&phy0>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,dwmac-mdio";
+ reset-gpios = <&gpioz 2 GPIO_ACTIVE_LOW>;
+ reset-delay-us = <1000>;
+ reset-post-delay-us = <1000>;
+
+ phy0: ethernet-phy@7 {
+ reg = <7>;
+
+ rxc-skew-ps = <1500>;
+ rxdv-skew-ps = <540>;
+ rxd0-skew-ps = <420>;
+ rxd1-skew-ps = <420>;
+ rxd2-skew-ps = <420>;
+ rxd3-skew-ps = <420>;
+
+ txc-skew-ps = <1440>;
+ txen-skew-ps = <540>;
+ txd0-skew-ps = <420>;
+ txd1-skew-ps = <420>;
+ txd2-skew-ps = <420>;
+ txd3-skew-ps = <420>;
+ };
+ };
+};
+
+&sdmmc1 {
+ pinctrl-names = "default", "opendrain", "sleep";
+ pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_b>;
+ pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_dir_pins_b>;
+ pinctrl-2 = <&sdmmc1_b4_sleep_pins_a &sdmmc1_dir_sleep_pins_b>;
+ cd-gpios = <&gpioi 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
+ disable-wp;
+ st,sig-dir;
+ st,neg-edge;
+ st,use-ckin;
+ bus-width = <4>;
+ vmmc-supply = <&vdd_sd>;
+ vqmmc-supply = <&sd_switch>;
+ status = "okay";
+};
+
+&sdmmc2 {
+ pinctrl-names = "default", "opendrain", "sleep";
+ pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_c>;
+ pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_d47_pins_c>;
+ pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_c>;
+ bus-width = <8>;
+ mmc-ddr-1_8v;
+ no-sd;
+ no-sdio;
+ non-removable;
+ st,neg-edge;
+ vmmc-supply = <&v3v3>;
+ vqmmc-supply = <&v3v3>;
+ status = "okay";
+};
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart4_pins_b>;
+ /delete-property/dmas;
+ /delete-property/dma-names;
+ status = "okay";
+};
+
+&uart7 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart7_pins_a>;
+ uart-has-rtscts;
+ /delete-property/dmas;
+ /delete-property/dma-names;
+ status = "okay";
+};
+
+&usbh_ehci {
+ phys = <&usbphyc_port0>;
+ status = "okay";
+};
+
+&usbh_ohci {
+ phys = <&usbphyc_port0>;
+ status = "okay";
+};
+
+&usbotg_hs {
+ pinctrl-0 = <&usbotg_hs_pins_a>;
+ pinctrl-names = "default";
+ phy-names = "usb2-phy";
+ phys = <&usbphyc_port1 0>;
+ status = "okay";
+ vbus-supply = <&vbus_otg>;
+};
+
+&usbphyc {
+ status = "okay";
+};
+
+&usbphyc_port0 {
+ phy-supply = <&vdd_usb>;
+};
+
+&usbphyc_port1 {
+ phy-supply = <&vdd_usb>;
+};
diff --git a/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi b/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi
index 8b48d3c89a04..7798a2e17c5c 100644
--- a/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi
+++ b/arch/arm/boot/dts/stm32mp15xx-dkx.dtsi
@@ -141,7 +141,7 @@
max-speed = <1000>;
phy-handle = <&phy0>;
- mdio0 {
+ mdio {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,dwmac-mdio";
@@ -508,7 +508,7 @@
sai2a_port: port {
sai2a_endpoint: endpoint {
remote-endpoint = <&cs42l51_tx_endpoint>;
- format = "i2s";
+ dai-format = "i2s";
mclk-fs = <256>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <32>;
@@ -526,7 +526,7 @@
sai2b_port: port {
sai2b_endpoint: endpoint {
remote-endpoint = <&cs42l51_rx_endpoint>;
- format = "i2s";
+ dai-format = "i2s";
mclk-fs = <256>;
dai-tdm-slot-num = <2>;
dai-tdm-slot-width = <32>;
diff --git a/arch/arm/boot/dts/suniv-f1c100s.dtsi b/arch/arm/boot/dts/suniv-f1c100s.dtsi
index 0edc1724407b..9455d27e516e 100644
--- a/arch/arm/boot/dts/suniv-f1c100s.dtsi
+++ b/arch/arm/boot/dts/suniv-f1c100s.dtsi
@@ -166,6 +166,12 @@
drive-strength = <30>;
};
+ /omit-if-no-ref/
+ i2c0_pd_pins: i2c0-pd-pins {
+ pins = "PD0", "PD12";
+ function = "i2c0";
+ };
+
spi0_pc_pins: spi0-pc-pins {
pins = "PC0", "PC1", "PC2", "PC3";
function = "spi0";
@@ -177,6 +183,42 @@
};
};
+ i2c0: i2c@1c27000 {
+ compatible = "allwinner,suniv-f1c100s-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x01c27000 0x400>;
+ interrupts = <7>;
+ clocks = <&ccu CLK_BUS_I2C0>;
+ resets = <&ccu RST_BUS_I2C0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c1: i2c@1c27400 {
+ compatible = "allwinner,suniv-f1c100s-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x01c27400 0x400>;
+ interrupts = <8>;
+ clocks = <&ccu CLK_BUS_I2C1>;
+ resets = <&ccu RST_BUS_I2C1>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@1c27800 {
+ compatible = "allwinner,suniv-f1c100s-i2c",
+ "allwinner,sun6i-a31-i2c";
+ reg = <0x01c27800 0x400>;
+ interrupts = <9>;
+ clocks = <&ccu CLK_BUS_I2C2>;
+ resets = <&ccu RST_BUS_I2C2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
timer@1c20c00 {
compatible = "allwinner,suniv-f1c100s-timer";
reg = <0x01c20c00 0x90>;
@@ -192,6 +234,34 @@
clocks = <&osc32k>;
};
+ pwm: pwm@1c21000 {
+ compatible = "allwinner,suniv-f1c100s-pwm",
+ "allwinner,sun7i-a20-pwm";
+ reg = <0x01c21000 0x400>;
+ clocks = <&osc24M>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ ir: ir@1c22c00 {
+ compatible = "allwinner,suniv-f1c100s-ir",
+ "allwinner,sun6i-a31-ir";
+ reg = <0x01c22c00 0x400>;
+ clocks = <&ccu CLK_BUS_IR>, <&ccu CLK_IR>;
+ clock-names = "apb", "ir";
+ resets = <&ccu RST_BUS_IR>;
+ interrupts = <6>;
+ status = "disabled";
+ };
+
+ lradc: lradc@1c23400 {
+ compatible = "allwinner,suniv-f1c100s-lradc",
+ "allwinner,sun8i-a83t-r-lradc";
+ reg = <0x01c23400 0x400>;
+ interrupts = <22>;
+ status = "disabled";
+ };
+
uart0: serial@1c25000 {
compatible = "snps,dw-apb-uart";
reg = <0x01c25000 0x400>;
diff --git a/arch/arm/boot/dts/sunplus-sp7021.dtsi b/arch/arm/boot/dts/sunplus-sp7021.dtsi
index 7dc4ce3619c7..ae9bbe0320b8 100644
--- a/arch/arm/boot/dts/sunplus-sp7021.dtsi
+++ b/arch/arm/boot/dts/sunplus-sp7021.dtsi
@@ -211,7 +211,6 @@
interrupt-names = "dma_w", "master_risc", "slave_risc";
clocks = <&clkc CLK_SPI_COMBO_1>;
resets = <&rstc RST_SPI_COMBO_1>;
- spi-max-frequency = <25000000>;
status = "disabled";
};
@@ -225,7 +224,6 @@
interrupt-names = "dma_w", "master_risc", "slave_risc";
clocks = <&clkc CLK_SPI_COMBO_2>;
resets = <&rstc RST_SPI_COMBO_2>;
- spi-max-frequency = <25000000>;
status = "disabled";
};
@@ -239,7 +237,6 @@
interrupt-names = "dma_w", "master_risc", "slave_risc";
clocks = <&clkc CLK_SPI_COMBO_3>;
resets = <&rstc RST_SPI_COMBO_3>;
- spi-max-frequency = <25000000>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi b/arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi
index e899d14f38c3..1d1d127cf38f 100644
--- a/arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi
+++ b/arch/arm/boot/dts/sunxi-bananapi-m2-plus.dtsi
@@ -89,13 +89,13 @@
};
reg_gmac_3v3: gmac-3v3 {
- compatible = "regulator-fixed";
- regulator-name = "gmac-3v3";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- startup-delay-us = <100000>;
- enable-active-high;
- gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>;
+ compatible = "regulator-fixed";
+ regulator-name = "gmac-3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <100000>;
+ enable-active-high;
+ gpio = <&pio 3 6 GPIO_ACTIVE_HIGH>;
};
wifi_pwrseq: wifi_pwrseq {
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
index 09aefb4e90f8..686193bd6bd9 100644
--- a/arch/arm/boot/dts/sunxi-h3-h5.dtsi
+++ b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
@@ -302,6 +302,8 @@
interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_EHCI0>, <&ccu CLK_BUS_OHCI0>;
resets = <&ccu RST_BUS_EHCI0>, <&ccu RST_BUS_OHCI0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
status = "disabled";
};
@@ -312,6 +314,8 @@
clocks = <&ccu CLK_BUS_EHCI0>, <&ccu CLK_BUS_OHCI0>,
<&ccu CLK_USB_OHCI0>;
resets = <&ccu RST_BUS_EHCI0>, <&ccu RST_BUS_OHCI0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
status = "disabled";
};
diff --git a/arch/arm/boot/dts/tegra114-asus-tf701t.dts b/arch/arm/boot/dts/tegra114-asus-tf701t.dts
index 284209b0bd96..9279d24db009 100644
--- a/arch/arm/boot/dts/tegra114-asus-tf701t.dts
+++ b/arch/arm/boot/dts/tegra114-asus-tf701t.dts
@@ -80,7 +80,7 @@
};
pinmux@70000868 {
- asus_pad_ec_default: asus-pad-ec-default {
+ asus_pad_ec_default: pinmux-asus-pad-ec-default {
ec-interrupt {
nvidia,pins = "kb_col5_pq5";
nvidia,function = "kbc";
@@ -98,7 +98,7 @@
};
};
- backlight_default: backlight-default {
+ backlight_default: pinmux-backlight-default {
backlight-enable {
nvidia,pins = "gmi_ad10_ph2";
nvidia,function = "gmi";
@@ -108,7 +108,7 @@
};
};
- codec_default: codec-default {
+ codec_default: pinmux-codec-default {
ldo1-en {
nvidia,pins = "sdmmc1_wp_n_pv3";
nvidia,function = "sdmmc1";
@@ -127,7 +127,7 @@
};
};
- gpio_keys_default: gpio-keys-default {
+ gpio_keys_default: pinmux-gpio-keys-default {
power {
nvidia,pins = "kb_col0_pq0";
nvidia,function = "kbc";
@@ -146,7 +146,7 @@
};
};
- gpio_hall_sensor_default: gpio-hall-sensor-default {
+ gpio_hall_sensor_default: pinmux-gpio-hall-sensor-default {
ulpi_data4_po5 {
nvidia,pins = "ulpi_data4_po5";
nvidia,function = "spi2";
@@ -156,7 +156,7 @@
};
};
- hp_det_default: hp-det-default {
+ hp_det_default: pinmux-hp-det-default {
gmi_iordy_pi5 {
nvidia,pins = "kb_row7_pr7";
nvidia,function = "rsvd2";
@@ -166,7 +166,7 @@
};
};
- imu_default: imu-default {
+ imu_default: pinmux-imu-default {
kb_row3_pr3 {
nvidia,pins = "kb_row3_pr3";
nvidia,function = "rsvd3";
@@ -176,7 +176,7 @@
};
};
- pwm_default: pwm-default {
+ pwm_default: pinmux-pwm-default {
gmi_ad9_ph1 {
nvidia,pins = "gmi_ad9_ph1";
nvidia,function = "pwm1";
@@ -187,7 +187,7 @@
};
/* XXX make this something more sensible */
- pwm_sleep: pwm-sleep {
+ pwm_sleep: pinmux-pwm-sleep {
gmi_ad9_ph1 {
nvidia,pins = "gmi_ad9_ph1";
nvidia,function = "pwm1";
@@ -197,7 +197,7 @@
};
};
- sdmmc3_default: sdmmc3-default {
+ sdmmc3_default: pinmux-sdmmc3-default {
sdmmc3_clk_pa6 {
nvidia,pins = "sdmmc3_clk_pa6";
nvidia,function = "sdmmc3";
@@ -233,7 +233,7 @@
};
};
- sdmmc3_vdd_default: sdmmc3-vdd-default {
+ sdmmc3_vdd_default: pinmux-sdmmc3-vdd-default {
gmi_clk_pk1 {
nvidia,pins = "gmi_clk_pk1";
nvidia,function = "gmi";
@@ -243,7 +243,7 @@
};
};
- vdd_lcd_default: vdd-lcd-default {
+ vdd_lcd_default: pinmux-vdd-lcd-default {
sdmmc4_clk_pcc4 {
nvidia,pins = "sdmmc4_clk_pcc4";
nvidia,function = "sdmmc4";
diff --git a/arch/arm/boot/dts/tegra124-nyan-big.dts b/arch/arm/boot/dts/tegra124-nyan-big.dts
index fdc1d64dfff9..9a01dfed1379 100644
--- a/arch/arm/boot/dts/tegra124-nyan-big.dts
+++ b/arch/arm/boot/dts/tegra124-nyan-big.dts
@@ -18,6 +18,7 @@
aux-bus {
panel: panel {
compatible = "auo,b133xtn01";
+ power-supply = <&vdd_3v3_panel>;
backlight = <&backlight>;
};
};
@@ -39,7 +40,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinmux_default>;
- pinmux_default: common {
+ pinmux_default: pinmux {
clk_32k_out_pa0 {
nvidia,pins = "clk_32k_out_pa0";
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
diff --git a/arch/arm/boot/dts/tegra124-nyan-blaze.dts b/arch/arm/boot/dts/tegra124-nyan-blaze.dts
index abdf4456826f..0beef1c03ff3 100644
--- a/arch/arm/boot/dts/tegra124-nyan-blaze.dts
+++ b/arch/arm/boot/dts/tegra124-nyan-blaze.dts
@@ -20,6 +20,7 @@
aux-bus {
panel: panel {
compatible = "samsung,ltn140at29-301";
+ power-supply = <&vdd_3v3_panel>;
backlight = <&backlight>;
};
};
@@ -37,7 +38,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinmux_default>;
- pinmux_default: common {
+ pinmux_default: pinmux {
clk_32k_out_pa0 {
nvidia,pins = "clk_32k_out_pa0";
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
diff --git a/arch/arm/boot/dts/tegra124-venice2.dts b/arch/arm/boot/dts/tegra124-venice2.dts
index 8f40fcfc11b0..7e739879c00c 100644
--- a/arch/arm/boot/dts/tegra124-venice2.dts
+++ b/arch/arm/boot/dts/tegra124-venice2.dts
@@ -52,6 +52,7 @@
aux-bus {
panel: panel {
compatible = "lg,lp129qe";
+ power-supply = <&vdd_3v3_panel>;
backlight = <&backlight>;
};
};
@@ -70,7 +71,7 @@
pinctrl-names = "boot";
pinctrl-0 = <&pinmux_boot>;
- pinmux_boot: common {
+ pinmux_boot: pinmux {
dap_mclk1_pw4 {
nvidia,pins = "dap_mclk1_pw4";
nvidia,function = "extperiph1";
diff --git a/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts b/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts
index dac6d02a1b15..17afc2c7cb37 100644
--- a/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts
+++ b/arch/arm/boot/dts/tegra20-acer-a500-picasso.dts
@@ -342,7 +342,7 @@
};
};
- state_i2cmux_ddc: pinmux_i2cmux_ddc {
+ state_i2cmux_ddc: pinmux-i2cmux-ddc {
ddc {
nvidia,pins = "ddc";
nvidia,function = "i2c2";
@@ -353,7 +353,7 @@
};
};
- state_i2cmux_pta: pinmux_i2cmux_pta {
+ state_i2cmux_pta: pinmux-i2cmux-pta {
ddc {
nvidia,pins = "ddc";
nvidia,function = "rsvd4";
@@ -364,7 +364,7 @@
};
};
- state_i2cmux_idle: pinmux_i2cmux_idle {
+ state_i2cmux_idle: pinmux-i2cmux-idle {
ddc {
nvidia,pins = "ddc";
nvidia,function = "rsvd4";
diff --git a/arch/arm/boot/dts/tegra20-asus-tf101.dts b/arch/arm/boot/dts/tegra20-asus-tf101.dts
index bf797a1f27ea..c39ddb462ad0 100644
--- a/arch/arm/boot/dts/tegra20-asus-tf101.dts
+++ b/arch/arm/boot/dts/tegra20-asus-tf101.dts
@@ -399,7 +399,7 @@
};
};
- state_i2cmux_ddc: pinmux_i2cmux_ddc {
+ state_i2cmux_ddc: pinmux-i2cmux-ddc {
ddc {
nvidia,pins = "ddc";
nvidia,function = "i2c2";
@@ -411,7 +411,7 @@
};
};
- state_i2cmux_pta: pinmux_i2cmux_pta {
+ state_i2cmux_pta: pinmux-i2cmux-pta {
ddc {
nvidia,pins = "ddc";
nvidia,function = "rsvd4";
@@ -423,7 +423,7 @@
};
};
- state_i2cmux_idle: pinmux_i2cmux_idle {
+ state_i2cmux_idle: pinmux-i2cmux-idle {
ddc {
nvidia,pins = "ddc";
nvidia,function = "rsvd4";
@@ -1019,7 +1019,7 @@
};
display-panel {
- compatible = "panel-lvds";
+ compatible = "auo,b101ew05", "panel-lvds";
/* AUO B101EW05 using custom timings */
diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts
index 5b4c5ef30996..ab33ff67fdb9 100644
--- a/arch/arm/boot/dts/tegra20-seaboard.dts
+++ b/arch/arm/boot/dts/tegra20-seaboard.dts
@@ -285,7 +285,7 @@
};
};
- state_i2cmux_ddc: pinmux_i2cmux_ddc {
+ state_i2cmux_ddc: pinmux-i2cmux-ddc {
ddc {
nvidia,pins = "ddc";
nvidia,function = "i2c2";
@@ -296,7 +296,7 @@
};
};
- state_i2cmux_pta: pinmux_i2cmux_pta {
+ state_i2cmux_pta: pinmux-i2cmux-pta {
ddc {
nvidia,pins = "ddc";
nvidia,function = "rsvd4";
@@ -307,7 +307,7 @@
};
};
- state_i2cmux_idle: pinmux_i2cmux_idle {
+ state_i2cmux_idle: pinmux-i2cmux-idle {
ddc {
nvidia,pins = "ddc";
nvidia,function = "rsvd4";
diff --git a/arch/arm/boot/dts/tegra20-tamonten.dtsi b/arch/arm/boot/dts/tegra20-tamonten.dtsi
index 0e19bd0a847c..980272ad59a4 100644
--- a/arch/arm/boot/dts/tegra20-tamonten.dtsi
+++ b/arch/arm/boot/dts/tegra20-tamonten.dtsi
@@ -249,7 +249,7 @@
};
};
- state_i2cmux_ddc: pinmux_i2cmux_ddc {
+ state_i2cmux_ddc: pinmux-i2cmux-ddc {
ddc {
nvidia,pins = "ddc";
nvidia,function = "i2c2";
@@ -260,7 +260,7 @@
};
};
- state_i2cmux_pta: pinmux_i2cmux_pta {
+ state_i2cmux_pta: pinmux-i2cmux-pta {
ddc {
nvidia,pins = "ddc";
nvidia,function = "rsvd4";
@@ -271,7 +271,7 @@
};
};
- state_i2cmux_idle: pinmux_i2cmux_idle {
+ state_i2cmux_idle: pinmux-i2cmux-idle {
ddc {
nvidia,pins = "ddc";
nvidia,function = "rsvd4";
diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts
index caa17e876e41..2d7bb442d6b6 100644
--- a/arch/arm/boot/dts/tegra20-ventana.dts
+++ b/arch/arm/boot/dts/tegra20-ventana.dts
@@ -284,7 +284,7 @@
};
};
- state_i2cmux_ddc: pinmux_i2cmux_ddc {
+ state_i2cmux_ddc: pinmux-i2cmux-ddc {
ddc {
nvidia,pins = "ddc";
nvidia,function = "i2c2";
@@ -295,7 +295,7 @@
};
};
- state_i2cmux_pta: pinmux_i2cmux_pta {
+ state_i2cmux_pta: pinmux-i2cmux-pta {
ddc {
nvidia,pins = "ddc";
nvidia,function = "rsvd4";
@@ -306,7 +306,7 @@
};
};
- state_i2cmux_idle: pinmux_i2cmux_idle {
+ state_i2cmux_idle: pinmux-i2cmux-idle {
ddc {
nvidia,pins = "ddc";
nvidia,function = "rsvd4";
diff --git a/arch/arm/boot/dts/tegra30-asus-transformer-common.dtsi b/arch/arm/boot/dts/tegra30-asus-transformer-common.dtsi
index c27e70d8bf2b..08ea9cb32d0e 100644
--- a/arch/arm/boot/dts/tegra30-asus-transformer-common.dtsi
+++ b/arch/arm/boot/dts/tegra30-asus-transformer-common.dtsi
@@ -168,7 +168,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
- nvidia,ioreset = <0>;
+ nvidia,io-reset = <0>;
};
/* SDMMC3 pinmux */
@@ -711,7 +711,7 @@
nvidia,tristate = <TEGRA_PIN_ENABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
- nvidia,ioreset = <0>;
+ nvidia,io-reset = <0>;
};
/* GPIO keys pinmux */
@@ -805,7 +805,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
- nvidia,ioreset = <0>;
+ nvidia,io-reset = <0>;
};
vi_d10_pt2 {
@@ -937,7 +937,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_DISABLE>;
nvidia,lock = <0>;
- nvidia,ioreset = <0>;
+ nvidia,io-reset = <0>;
};
vi_mclk_pt1 {
@@ -1509,7 +1509,6 @@
extcon-keys {
compatible = "gpio-keys";
- interrupt-parent = <&gpio>;
switch-dock-hall-sensor {
label = "Lid sensor";
@@ -1542,7 +1541,6 @@
gpio-keys {
compatible = "gpio-keys";
- interrupt-parent = <&gpio>;
key-power {
label = "Power";
diff --git a/arch/arm/boot/dts/tegra30-pegatron-chagall.dts b/arch/arm/boot/dts/tegra30-pegatron-chagall.dts
index 7c81f0205549..d9408a90653a 100644
--- a/arch/arm/boot/dts/tegra30-pegatron-chagall.dts
+++ b/arch/arm/boot/dts/tegra30-pegatron-chagall.dts
@@ -134,7 +134,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
- nvidia,ioreset = <0>;
+ nvidia,io-reset = <0>;
};
/* SDMMC3 pinmux */
@@ -150,7 +150,6 @@
nvidia,pins = "sdmmc3_cmd_pa7",
"sdmmc3_dat3_pb4",
"sdmmc3_dat2_pb5",
- "sdmmc3_dat2_pb5",
"sdmmc3_dat1_pb6",
"sdmmc3_dat0_pb7",
"sdmmc3_dat5_pd0",
@@ -622,7 +621,7 @@
nvidia,tristate = <TEGRA_PIN_ENABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
- nvidia,ioreset = <0>;
+ nvidia,io-reset = <0>;
};
pu1 {
@@ -689,7 +688,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_ENABLE>;
nvidia,lock = <0>;
- nvidia,ioreset = <0>;
+ nvidia,io-reset = <0>;
};
vi_d10_pt2 {
@@ -864,7 +863,7 @@
nvidia,tristate = <TEGRA_PIN_DISABLE>;
nvidia,enable-input = <TEGRA_PIN_DISABLE>;
nvidia,lock = <0>;
- nvidia,ioreset = <0>;
+ nvidia,io-reset = <0>;
};
vi_mclk_pt1 {
@@ -2653,7 +2652,6 @@
extcon-keys {
compatible = "gpio-keys";
- interrupt-parent = <&gpio>;
switch-dock-insert {
label = "Chagall Dock";
@@ -2686,7 +2684,6 @@
gpio-keys {
compatible = "gpio-keys";
- interrupt-parent = <&gpio>;
key-power {
label = "Power";
diff --git a/arch/arm/boot/dts/uniphier-pro5-epcore.dts b/arch/arm/boot/dts/uniphier-pro5-epcore.dts
new file mode 100644
index 000000000000..ed759dcc3216
--- /dev/null
+++ b/arch/arm/boot/dts/uniphier-pro5-epcore.dts
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Device Tree Source for UniPhier Pro5 EP-CORE Board (Pro5-PCIe_EP-CORE)
+ *
+ * Copyright (C) 2021 Socionext Inc.
+ * Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
+ */
+
+/dts-v1/;
+#include "uniphier-pro5.dtsi"
+#include "uniphier-support-card.dtsi"
+
+/ {
+ model = "UniPhier Pro5 EP-CORE Board";
+ compatible = "socionext,uniphier-pro5-epcore", "socionext,uniphier-pro5";
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ aliases {
+ serial0 = &serial0;
+ serial1 = &serial1;
+ serial2 = &serial2;
+ i2c0 = &i2c0;
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x40000000>;
+ };
+};
+
+&ethsc {
+ interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
+};
+
+&serialsc {
+ interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
+};
+
+&serial0 {
+ status = "okay";
+};
+
+&serial1 {
+ status = "okay";
+};
+
+&serial2 {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&usb0 {
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+};
+
+&emmc {
+ status = "okay";
+};
+
+&sd {
+ status = "okay";
+};
+
+&pcie_ep {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/uniphier-pro5-proex.dts b/arch/arm/boot/dts/uniphier-pro5-proex.dts
new file mode 100644
index 000000000000..2cfb84f73cc0
--- /dev/null
+++ b/arch/arm/boot/dts/uniphier-pro5-proex.dts
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
+/*
+ * Device Tree Source for UniPhier Pro5 ProEX Board
+ *
+ * Copyright (C) 2021 Socionext Inc.
+ * Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
+ */
+
+/dts-v1/;
+#include "uniphier-pro5.dtsi"
+
+/ {
+ model = "UniPhier Pro5 ProEX Board";
+ compatible = "socionext,uniphier-pro5-proex", "socionext,uniphier-pro5";
+
+ chosen {
+ stdout-path = "serial2:115200n8";
+ };
+
+ aliases {
+ serial1 = &serial1;
+ serial2 = &serial2;
+ i2c0 = &i2c0;
+ i2c1 = &i2c3;
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x80000000 0x40000000>;
+ };
+};
+
+&serial1 {
+ status = "okay";
+};
+
+&serial2 {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+};
+
+&i2c3 {
+ status = "okay";
+};
+
+&usb1 {
+ status = "okay";
+};
+
+&emmc {
+ status = "okay";
+};
+
+&pcie_ep {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/vexpress-v2m.dtsi b/arch/arm/boot/dts/vexpress-v2m.dtsi
index f434fe5cf4a1..def538ce8769 100644
--- a/arch/arm/boot/dts/vexpress-v2m.dtsi
+++ b/arch/arm/boot/dts/vexpress-v2m.dtsi
@@ -383,49 +383,49 @@
leds {
compatible = "gpio-leds";
- user1 {
+ led-user1 {
label = "v2m:green:user1";
gpios = <&v2m_led_gpios 0 0>;
linux,default-trigger = "heartbeat";
};
- user2 {
+ led-user2 {
label = "v2m:green:user2";
gpios = <&v2m_led_gpios 1 0>;
linux,default-trigger = "mmc0";
};
- user3 {
+ led-user3 {
label = "v2m:green:user3";
gpios = <&v2m_led_gpios 2 0>;
linux,default-trigger = "cpu0";
};
- user4 {
+ led-user4 {
label = "v2m:green:user4";
gpios = <&v2m_led_gpios 3 0>;
linux,default-trigger = "cpu1";
};
- user5 {
+ led-user5 {
label = "v2m:green:user5";
gpios = <&v2m_led_gpios 4 0>;
linux,default-trigger = "cpu2";
};
- user6 {
+ led-user6 {
label = "v2m:green:user6";
gpios = <&v2m_led_gpios 5 0>;
linux,default-trigger = "cpu3";
};
- user7 {
+ led-user7 {
label = "v2m:green:user7";
gpios = <&v2m_led_gpios 6 0>;
linux,default-trigger = "cpu4";
};
- user8 {
+ led-user8 {
label = "v2m:green:user8";
gpios = <&v2m_led_gpios 7 0>;
linux,default-trigger = "cpu5";
diff --git a/arch/arm/boot/dts/vf610-zii-dev-rev-c.dts b/arch/arm/boot/dts/vf610-zii-dev-rev-c.dts
index de79dcfd32e6..f892977da9e4 100644
--- a/arch/arm/boot/dts/vf610-zii-dev-rev-c.dts
+++ b/arch/arm/boot/dts/vf610-zii-dev-rev-c.dts
@@ -259,7 +259,7 @@
xtal-trim = /bits/ 8 <0x06>;
sleep-gpio = <&gpio0 24 GPIO_ACTIVE_HIGH>;
- reset-gpio = <&gpio6 10 GPIO_ACTIVE_HIGH>;
+ reset-gpio = <&gpio6 10 GPIO_ACTIVE_LOW>;
fsl,spi-cs-sck-delay = <180>;
fsl,spi-sck-cs-delay = <250>;
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index 7bae8cbaafe7..9733381074e0 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -13,7 +13,5 @@ obj-$(CONFIG_SHARP_SCOOP) += scoop.o
obj-$(CONFIG_CPU_V7) += secure_cntvoff.o
obj-$(CONFIG_MCPM) += mcpm_head.o mcpm_entry.o mcpm_platsmp.o vlock.o
CFLAGS_REMOVE_mcpm_entry.o = -pg
-AFLAGS_mcpm_head.o := -march=armv7-a
-AFLAGS_vlock.o := -march=armv7-a
obj-$(CONFIG_BL_SWITCHER) += bL_switcher.o
obj-$(CONFIG_BL_SWITCHER_DUMMY_IF) += bL_switcher_dummy_if.o
diff --git a/arch/arm/common/mcpm_head.S b/arch/arm/common/mcpm_head.S
index 291d969bc719..299495c43dfd 100644
--- a/arch/arm/common/mcpm_head.S
+++ b/arch/arm/common/mcpm_head.S
@@ -15,6 +15,8 @@
#include "vlock.h"
+.arch armv7-a
+
.if MCPM_SYNC_CLUSTER_CPUS
.error "cpus must be the first member of struct mcpm_sync_struct"
.endif
diff --git a/arch/arm/common/vlock.S b/arch/arm/common/vlock.S
index f1c7fd44f1b1..1fa09c4697ed 100644
--- a/arch/arm/common/vlock.S
+++ b/arch/arm/common/vlock.S
@@ -12,6 +12,8 @@
#include <linux/linkage.h>
#include "vlock.h"
+.arch armv7-a
+
/* Select different code if voting flags can fit in a single word. */
#if VLOCK_VOTING_SIZE > 4
#define FEW(x...)
diff --git a/arch/arm/configs/clps711x_defconfig b/arch/arm/configs/clps711x_defconfig
index 92481b2a88fa..adcee238822a 100644
--- a/arch/arm/configs/clps711x_defconfig
+++ b/arch/arm/configs/clps711x_defconfig
@@ -14,7 +14,8 @@ CONFIG_ARCH_EDB7211=y
CONFIG_ARCH_P720T=y
CONFIG_AEABI=y
# CONFIG_COREDUMP is not set
-CONFIG_SLOB=y
+CONFIG_SLUB=y
+CONFIG_SLUB_TINY=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
diff --git a/arch/arm/configs/collie_defconfig b/arch/arm/configs/collie_defconfig
index 2a2d2cb3ce2e..69341c33e0cc 100644
--- a/arch/arm/configs/collie_defconfig
+++ b/arch/arm/configs/collie_defconfig
@@ -13,7 +13,8 @@ CONFIG_CMDLINE="noinitrd root=/dev/mtdblock2 rootfstype=jffs2 fbcon=rotate:1"
CONFIG_FPE_NWFPE=y
CONFIG_PM=y
# CONFIG_SWAP is not set
-CONFIG_SLOB=y
+CONFIG_SLUB=y
+CONFIG_SLUB_TINY=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index 078d61b758a9..025eb333dcaa 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -166,6 +166,7 @@ CONFIG_TOUCHSCREEN_ADS7846=y
CONFIG_TOUCHSCREEN_AD7879=y
CONFIG_TOUCHSCREEN_AD7879_I2C=y
CONFIG_TOUCHSCREEN_ATMEL_MXT=y
+CONFIG_TOUCHSCREEN_CYTTSP5=y
CONFIG_TOUCHSCREEN_DA9052=y
CONFIG_TOUCHSCREEN_EGALAX=y
CONFIG_TOUCHSCREEN_GOODIX=y
@@ -222,6 +223,7 @@ CONFIG_RN5T618_POWER=m
CONFIG_SENSORS_MC13783_ADC=y
CONFIG_SENSORS_GPIO_FAN=y
CONFIG_SENSORS_IIO_HWMON=y
+CONFIG_SENSORS_SY7636A=y
CONFIG_THERMAL_STATISTICS=y
CONFIG_THERMAL_WRITABLE_TRIPS=y
CONFIG_CPU_THERMAL=y
@@ -237,6 +239,7 @@ CONFIG_MFD_DA9062=y
CONFIG_MFD_DA9063=y
CONFIG_MFD_MC13XXX_SPI=y
CONFIG_MFD_MC13XXX_I2C=y
+CONFIG_MFD_SY7636A=y
CONFIG_MFD_RN5T618=y
CONFIG_MFD_STMPE=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
@@ -250,6 +253,7 @@ CONFIG_REGULATOR_MC13783=y
CONFIG_REGULATOR_MC13892=y
CONFIG_REGULATOR_PFUZE100=y
CONFIG_REGULATOR_RN5T618=y
+CONFIG_REGULATOR_SY7636A=y
CONFIG_RC_CORE=y
CONFIG_RC_DEVICES=y
CONFIG_IR_GPIO_CIR=y
@@ -397,6 +401,7 @@ CONFIG_CLK_IMX8MN=y
CONFIG_CLK_IMX8MP=y
CONFIG_CLK_IMX8MQ=y
CONFIG_SOC_IMX8M=y
+CONFIG_EXTCON_USB_GPIO=y
CONFIG_IIO=y
CONFIG_MMA8452=y
CONFIG_IMX7D_ADC=y
diff --git a/arch/arm/configs/multi_v4t_defconfig b/arch/arm/configs/multi_v4t_defconfig
index e2fd822f741a..b60000a89aff 100644
--- a/arch/arm/configs/multi_v4t_defconfig
+++ b/arch/arm/configs/multi_v4t_defconfig
@@ -25,7 +25,8 @@ CONFIG_ARM_CLPS711X_CPUIDLE=y
CONFIG_JUMP_LABEL=y
CONFIG_PARTITION_ADVANCED=y
# CONFIG_COREDUMP is not set
-CONFIG_SLOB=y
+CONFIG_SLUB=y
+CONFIG_SLUB_TINY=y
CONFIG_MTD=y
CONFIG_MTD_CMDLINE_PARTS=y
CONFIG_MTD_BLOCK=y
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index b61b2e3d116b..ee184eb37adc 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -663,11 +663,11 @@ CONFIG_USB_VIDEO_CLASS=m
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_V4L_MEM2MEM_DRIVERS=y
CONFIG_VIDEO_ASPEED=m
-CONFIG_VIDEO_ATMEL_ISC=m
-CONFIG_VIDEO_ATMEL_XISC=m
CONFIG_VIDEO_ATMEL_ISI=m
-CONFIG_VIDEO_MICROCHIP_CSI2DC=m
CONFIG_VIDEO_MMP_CAMERA=m
+CONFIG_VIDEO_MICROCHIP_ISC=m
+CONFIG_VIDEO_MICROCHIP_XISC=m
+CONFIG_VIDEO_MICROCHIP_CSI2DC=m
CONFIG_VIDEO_TEGRA_VDE=m
CONFIG_VIDEO_RENESAS_CEU=m
CONFIG_VIDEO_RCAR_VIN=m
@@ -891,6 +891,8 @@ CONFIG_USB_CONFIGFS_F_UVC=y
CONFIG_USB_CONFIGFS_F_PRINTER=y
CONFIG_USB_ETH=m
CONFIG_TYPEC=m
+CONFIG_TYPEC_UCSI=m
+CONFIG_UCSI_STM32G0=m
CONFIG_TYPEC_STUSB160X=m
CONFIG_MMC=y
CONFIG_MMC_BLOCK_MINORS=16
diff --git a/arch/arm/configs/omap1_defconfig b/arch/arm/configs/omap1_defconfig
index 70511fe4b3ec..246f1bba7df5 100644
--- a/arch/arm/configs/omap1_defconfig
+++ b/arch/arm/configs/omap1_defconfig
@@ -42,7 +42,8 @@ CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_PARTITION_ADVANCED=y
CONFIG_BINFMT_MISC=y
# CONFIG_SWAP is not set
-CONFIG_SLOB=y
+CONFIG_SLUB=y
+CONFIG_SLUB_TINY=y
# CONFIG_VM_EVENT_COUNTERS is not set
CONFIG_NET=y
CONFIG_PACKET=y
diff --git a/arch/arm/configs/pxa_defconfig b/arch/arm/configs/pxa_defconfig
index d60cc9cc4c21..0a0f12df40b5 100644
--- a/arch/arm/configs/pxa_defconfig
+++ b/arch/arm/configs/pxa_defconfig
@@ -49,7 +49,8 @@ CONFIG_PARTITION_ADVANCED=y
CONFIG_LDM_PARTITION=y
CONFIG_CMDLINE_PARTITION=y
CONFIG_BINFMT_MISC=y
-CONFIG_SLOB=y
+CONFIG_SLUB=y
+CONFIG_SLUB_TINY=y
# CONFIG_COMPACTION is not set
CONFIG_NET=y
CONFIG_PACKET=y
diff --git a/arch/arm/configs/qcom_defconfig b/arch/arm/configs/qcom_defconfig
index 7d8b6884fd00..b41716c1ec64 100644
--- a/arch/arm/configs/qcom_defconfig
+++ b/arch/arm/configs/qcom_defconfig
@@ -131,14 +131,19 @@ CONFIG_PINCTRL_APQ8064=y
CONFIG_PINCTRL_APQ8084=y
CONFIG_PINCTRL_IPQ4019=y
CONFIG_PINCTRL_IPQ8064=y
+CONFIG_PINCTRL_MSM8226=y
CONFIG_PINCTRL_MSM8660=y
CONFIG_PINCTRL_MSM8960=y
+CONFIG_PINCTRL_MDM9607=y
CONFIG_PINCTRL_MDM9615=y
CONFIG_PINCTRL_MSM8X74=y
+CONFIG_PINCTRL_MSM8909=y
+CONFIG_PINCTRL_MSM8916=y
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
CONFIG_PINCTRL_QCOM_SSBI_PMIC=y
CONFIG_GPIOLIB=y
CONFIG_PINCTRL_SDX55=y
+CONFIG_PINCTRL_SDX65=y
CONFIG_GPIO_SYSFS=y
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_MSM=y
diff --git a/arch/arm/configs/sama5_defconfig b/arch/arm/configs/sama5_defconfig
index 877bbe7b777e..f89fd4e0d10a 100644
--- a/arch/arm/configs/sama5_defconfig
+++ b/arch/arm/configs/sama5_defconfig
@@ -150,8 +150,8 @@ CONFIG_MEDIA_PLATFORM_SUPPORT=y
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_USB_VIDEO_CLASS=m
CONFIG_V4L_PLATFORM_DRIVERS=y
-CONFIG_VIDEO_ATMEL_ISC=y
CONFIG_VIDEO_ATMEL_ISI=y
+CONFIG_VIDEO_MICROCHIP_ISC=y
CONFIG_VIDEO_MT9V032=m
CONFIG_VIDEO_OV2640=m
CONFIG_VIDEO_OV5640=m
diff --git a/arch/arm/configs/sama7_defconfig b/arch/arm/configs/sama7_defconfig
index 8f28c9d443f0..0d964c613d71 100644
--- a/arch/arm/configs/sama7_defconfig
+++ b/arch/arm/configs/sama7_defconfig
@@ -128,6 +128,10 @@ CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_AT91_RESET=y
CONFIG_POWER_RESET_AT91_SAMA5D2_SHDWC=y
# CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_STATISTICS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_GENERIC_ADC_THERMAL=y
CONFIG_WATCHDOG=y
CONFIG_SAMA5D4_WATCHDOG=y
CONFIG_MFD_ATMEL_FLEXCOM=y
@@ -140,7 +144,7 @@ CONFIG_MEDIA_SUPPORT_FILTER=y
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_PLATFORM_SUPPORT=y
CONFIG_V4L_PLATFORM_DRIVERS=y
-CONFIG_VIDEO_ATMEL_XISC=y
+CONFIG_VIDEO_MICROCHIP_XISC=y
CONFIG_VIDEO_MICROCHIP_CSI2DC=y
CONFIG_VIDEO_IMX219=m
CONFIG_VIDEO_IMX274=m
@@ -196,6 +200,7 @@ CONFIG_PWM=y
CONFIG_PWM_ATMEL=y
CONFIG_MCHP_EIC=y
CONFIG_RESET_CONTROLLER=y
+CONFIG_NVMEM_MICROCHIP_OTPC=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
CONFIG_FANOTIFY=y
@@ -211,13 +216,13 @@ CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_UTF8=y
CONFIG_LSM="N"
CONFIG_CRYPTO_AUTHENC=y
-CONFIG_CRYPTO_GCM=y
+CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_CFB=y
CONFIG_CRYPTO_OFB=y
CONFIG_CRYPTO_XTS=y
+CONFIG_CRYPTO_GCM=y
CONFIG_CRYPTO_SHA1=y
-CONFIG_CRYPTO_DES=y
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_DEV_ATMEL_AES=y
diff --git a/arch/arm/configs/spear6xx_defconfig b/arch/arm/configs/spear6xx_defconfig
index 3d631b1f3cfa..3e2c2abae5ba 100644
--- a/arch/arm/configs/spear6xx_defconfig
+++ b/arch/arm/configs/spear6xx_defconfig
@@ -11,7 +11,6 @@ CONFIG_PARTITION_ADVANCED=y
CONFIG_BINFMT_MISC=y
CONFIG_NET=y
CONFIG_MTD=y
-CONFIG_MTD_OF_PARTS=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_NAND_FSMC=y
@@ -28,23 +27,21 @@ CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_SMSC is not set
CONFIG_STMMAC_ETH=y
# CONFIG_WLAN is not set
-CONFIG_INPUT_FF_MEMLESS=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_AMBA_PL011=y
CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
-CONFIG_RAW_DRIVER=y
CONFIG_I2C=y
CONFIG_I2C_DESIGNWARE_PLATFORM=y
CONFIG_SPI=y
CONFIG_SPI_PL022=y
-CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_PL061=y
# CONFIG_HWMON is not set
CONFIG_WATCHDOG=y
CONFIG_ARM_SP805_WATCHDOG=y
+CONFIG_DRM=y
+CONFIG_DRM_PL111=y
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
diff --git a/arch/arm/configs/tct_hammer_defconfig b/arch/arm/configs/tct_hammer_defconfig
index 3b29ae1fb750..6bd38b6f22c4 100644
--- a/arch/arm/configs/tct_hammer_defconfig
+++ b/arch/arm/configs/tct_hammer_defconfig
@@ -19,7 +19,8 @@ CONFIG_FPE_NWFPE=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_SWAP is not set
-CONFIG_SLOB=y
+CONFIG_SLUB=y
+CONFIG_SLUB_TINY=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
diff --git a/arch/arm/configs/xcep_defconfig b/arch/arm/configs/xcep_defconfig
index ea59e4b6bfc5..6bd9f71b71fc 100644
--- a/arch/arm/configs/xcep_defconfig
+++ b/arch/arm/configs/xcep_defconfig
@@ -26,7 +26,8 @@ CONFIG_MODULE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
# CONFIG_BLOCK is not set
-CONFIG_SLOB=y
+CONFIG_SLUB=y
+CONFIG_SLUB_TINY=y
# CONFIG_COMPAT_BRK is not set
# CONFIG_VM_EVENT_COUNTERS is not set
CONFIG_NET=y
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 90fbe4a3f9c8..28e18f79c300 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -761,6 +761,12 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
.endif
.endm
+ .if __LINUX_ARM_ARCH__ < 6
+ .set .Lrev_l_uses_tmp, 1
+ .else
+ .set .Lrev_l_uses_tmp, 0
+ .endif
+
/*
* bl_r - branch and link to register
*
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index 775cac3c02bb..0163c3e78a67 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -25,6 +25,8 @@
#define CPUID_EXT_ISAR3 0x6c
#define CPUID_EXT_ISAR4 0x70
#define CPUID_EXT_ISAR5 0x74
+#define CPUID_EXT_ISAR6 0x7c
+#define CPUID_EXT_PFR2 0x90
#else
#define CPUID_EXT_PFR0 "c1, 0"
#define CPUID_EXT_PFR1 "c1, 1"
@@ -40,6 +42,8 @@
#define CPUID_EXT_ISAR3 "c2, 3"
#define CPUID_EXT_ISAR4 "c2, 4"
#define CPUID_EXT_ISAR5 "c2, 5"
+#define CPUID_EXT_ISAR6 "c2, 7"
+#define CPUID_EXT_PFR2 "c3, 4"
#endif
#define MPIDR_SMP_BITMASK (0x3 << 30)
diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index 4bdd930167c0..b95241b1ca65 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -43,9 +43,6 @@ void efi_virtmap_unload(void);
/* arch specific definitions used by the stub code */
-struct screen_info *alloc_screen_info(void);
-void free_screen_info(struct screen_info *si);
-
/*
* A reasonable upper bound for the uncompressed kernel size is 32 MBytes,
* so we will reserve that amount of memory. We have no easy way to tell what
diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h
index 5546c9751478..07c51a34f77d 100644
--- a/arch/arm/include/asm/module.h
+++ b/arch/arm/include/asm/module.h
@@ -37,6 +37,11 @@ struct mod_arch_specific {
struct module;
u32 get_module_plt(struct module *mod, unsigned long loc, Elf32_Addr val);
+#ifdef CONFIG_ARM_MODULE_PLTS
+bool in_module_plt(unsigned long loc);
+#else
+static inline bool in_module_plt(unsigned long loc) { return false; }
+#endif
#ifdef CONFIG_THUMB2_KERNEL
#define HAVE_ARCH_KALLSYMS_SYMBOL_VALUE
diff --git a/arch/arm/include/asm/ptdump.h b/arch/arm/include/asm/ptdump.h
index 0c2d3d0d4cc6..aad1d034136c 100644
--- a/arch/arm/include/asm/ptdump.h
+++ b/arch/arm/include/asm/ptdump.h
@@ -21,6 +21,7 @@ struct ptdump_info {
void ptdump_walk_pgd(struct seq_file *s, struct ptdump_info *info);
#ifdef CONFIG_ARM_PTDUMP_DEBUGFS
+#define EFI_RUNTIME_MAP_END SZ_1G
void ptdump_debugfs_register(struct ptdump_info *info, const char *name);
#else
static inline void ptdump_debugfs_register(struct ptdump_info *info,
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 1408a6a15d0e..483b8ddfcb82 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -163,6 +163,10 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs)
((current_stack_pointer | (THREAD_SIZE - 1)) - 7) - 1; \
})
+static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
+{
+ regs->ARM_r0 = rc;
+}
/*
* Update ITSTATE after normal execution of an IT block instruction.
diff --git a/arch/arm/include/asm/stackprotector.h b/arch/arm/include/asm/stackprotector.h
index 088d03161be5..0bd4979759f1 100644
--- a/arch/arm/include/asm/stackprotector.h
+++ b/arch/arm/include/asm/stackprotector.h
@@ -15,9 +15,6 @@
#ifndef _ASM_STACKPROTECTOR_H
#define _ASM_STACKPROTECTOR_H 1
-#include <linux/random.h>
-#include <linux/version.h>
-
#include <asm/thread_info.h>
extern unsigned long __stack_chk_guard;
@@ -30,11 +27,7 @@ extern unsigned long __stack_chk_guard;
*/
static __always_inline void boot_init_stack_canary(void)
{
- unsigned long canary;
-
- /* Try to get a semi random initial value. */
- get_random_bytes(&canary, sizeof(canary));
- canary ^= LINUX_VERSION_CODE;
+ unsigned long canary = get_random_canary();
current->stack_canary = canary;
#ifndef CONFIG_STACKPROTECTOR_PER_TASK
diff --git a/arch/arm/include/asm/stacktrace.h b/arch/arm/include/asm/stacktrace.h
index 36b2ff44fcbb..360f0d2406bf 100644
--- a/arch/arm/include/asm/stacktrace.h
+++ b/arch/arm/include/asm/stacktrace.h
@@ -44,7 +44,7 @@ void arm_get_current_stackframe(struct pt_regs *regs, struct stackframe *frame)
extern int unwind_frame(struct stackframe *frame);
extern void walk_stackframe(struct stackframe *frame,
- int (*fn)(struct stackframe *, void *), void *data);
+ bool (*fn)(void *, unsigned long), void *data);
extern void dump_mem(const char *lvl, const char *str, unsigned long bottom,
unsigned long top);
extern void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk,
diff --git a/arch/arm/include/asm/vfp.h b/arch/arm/include/asm/vfp.h
index 19928bfb4f9c..157ea3426158 100644
--- a/arch/arm/include/asm/vfp.h
+++ b/arch/arm/include/asm/vfp.h
@@ -87,6 +87,12 @@
#define MVFR0_DP_BIT (8)
#define MVFR0_DP_MASK (0xf << MVFR0_DP_BIT)
+/* MVFR1 bits */
+#define MVFR1_ASIMDHP_BIT (20)
+#define MVFR1_ASIMDHP_MASK (0xf << MVFR1_ASIMDHP_BIT)
+#define MVFR1_FPHP_BIT (24)
+#define MVFR1_FPHP_MASK (0xf << MVFR1_FPHP_BIT)
+
/* Bit patterns for decoding the packaged operation descriptors */
#define VFPOPDESC_LENGTH_BIT (9)
#define VFPOPDESC_LENGTH_MASK (0x07 << VFPOPDESC_LENGTH_BIT)
diff --git a/arch/arm/include/asm/xor.h b/arch/arm/include/asm/xor.h
index 669cad5194d3..934b549905f5 100644
--- a/arch/arm/include/asm/xor.h
+++ b/arch/arm/include/asm/xor.h
@@ -51,7 +51,7 @@ xor_arm4regs_2(unsigned long bytes, unsigned long * __restrict p1,
register unsigned int a1 __asm__("r4");
register unsigned int a2 __asm__("r5");
register unsigned int a3 __asm__("r6");
- register unsigned int a4 __asm__("r7");
+ register unsigned int a4 __asm__("r10");
register unsigned int b1 __asm__("r8");
register unsigned int b2 __asm__("r9");
register unsigned int b3 __asm__("ip");
@@ -73,7 +73,7 @@ xor_arm4regs_3(unsigned long bytes, unsigned long * __restrict p1,
register unsigned int a1 __asm__("r4");
register unsigned int a2 __asm__("r5");
register unsigned int a3 __asm__("r6");
- register unsigned int a4 __asm__("r7");
+ register unsigned int a4 __asm__("r10");
register unsigned int b1 __asm__("r8");
register unsigned int b2 __asm__("r9");
register unsigned int b3 __asm__("ip");
diff --git a/arch/arm/include/uapi/asm/hwcap.h b/arch/arm/include/uapi/asm/hwcap.h
index 990199d8b7c6..6b2023e39b6f 100644
--- a/arch/arm/include/uapi/asm/hwcap.h
+++ b/arch/arm/include/uapi/asm/hwcap.h
@@ -28,6 +28,12 @@
#define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT)
#define HWCAP_LPAE (1 << 20)
#define HWCAP_EVTSTRM (1 << 21)
+#define HWCAP_FPHP (1 << 22)
+#define HWCAP_ASIMDHP (1 << 23)
+#define HWCAP_ASIMDDP (1 << 24)
+#define HWCAP_ASIMDFHM (1 << 25)
+#define HWCAP_ASIMDBF16 (1 << 26)
+#define HWCAP_I8MM (1 << 27)
/*
* HWCAP2 flags - for elf_hwcap2 (in kernel) and AT_HWCAP2
@@ -37,5 +43,7 @@
#define HWCAP2_SHA1 (1 << 2)
#define HWCAP2_SHA2 (1 << 3)
#define HWCAP2_CRC32 (1 << 4)
+#define HWCAP2_SB (1 << 5)
+#define HWCAP2_SSBS (1 << 6)
#endif /* _UAPI__ASMARM_HWCAP_H */
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 48737ec800eb..d53f56d6f840 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -70,7 +70,6 @@ obj-$(CONFIG_HAVE_TCM) += tcm.o
obj-$(CONFIG_OF) += devtree.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
obj-$(CONFIG_SWP_EMULATE) += swp_emulate.o
-CFLAGS_swp_emulate.o := -Wa,-march=armv7-a
obj-$(CONFIG_HAVE_HW_BREAKPOINT) += hw_breakpoint.o
obj-$(CONFIG_CPU_XSCALE) += xscale-cp0.o
@@ -99,7 +98,6 @@ CFLAGS_head-inflate-data.o := $(call cc-option,-Wframe-larger-than=10240)
obj-$(CONFIG_XIP_DEFLATED_DATA) += head-inflate-data.o
obj-$(CONFIG_ARM_VIRT_EXT) += hyp-stub.o
-AFLAGS_hyp-stub.o :=-Wa,-march=armv7-a
ifeq ($(CONFIG_ARM_PSCI),y)
obj-$(CONFIG_SMP) += psci_smp.o
endif
diff --git a/arch/arm/kernel/efi.c b/arch/arm/kernel/efi.c
index e50ad7eefc02..882104f43b3b 100644
--- a/arch/arm/kernel/efi.c
+++ b/arch/arm/kernel/efi.c
@@ -75,38 +75,13 @@ int __init efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md)
return 0;
}
-static unsigned long __initdata screen_info_table = EFI_INVALID_TABLE_ADDR;
static unsigned long __initdata cpu_state_table = EFI_INVALID_TABLE_ADDR;
const efi_config_table_type_t efi_arch_tables[] __initconst = {
- {LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID, &screen_info_table},
{LINUX_EFI_ARM_CPU_STATE_TABLE_GUID, &cpu_state_table},
{}
};
-static void __init load_screen_info_table(void)
-{
- struct screen_info *si;
-
- if (screen_info_table != EFI_INVALID_TABLE_ADDR) {
- si = early_memremap_ro(screen_info_table, sizeof(*si));
- if (!si) {
- pr_err("Could not map screen_info config table\n");
- return;
- }
- screen_info = *si;
- early_memunmap(si, sizeof(*si));
-
- /* dummycon on ARM needs non-zero values for columns/lines */
- screen_info.orig_video_cols = 80;
- screen_info.orig_video_lines = 25;
-
- if (memblock_is_map_memory(screen_info.lfb_base))
- memblock_mark_nomap(screen_info.lfb_base,
- screen_info.lfb_size);
- }
-}
-
static void __init load_cpu_state_table(void)
{
if (cpu_state_table != EFI_INVALID_TABLE_ADDR) {
@@ -145,7 +120,11 @@ void __init arm_efi_init(void)
{
efi_init();
- load_screen_info_table();
+ if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI) {
+ /* dummycon on ARM needs non-zero values for columns/lines */
+ screen_info.orig_video_cols = 80;
+ screen_info.orig_video_lines = 25;
+ }
/* ARM does not permit early mappings to persist across paging_init() */
efi_memmap_unmap();
diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S
index b699b22a4db1..3a506b9095a5 100644
--- a/arch/arm/kernel/hyp-stub.S
+++ b/arch/arm/kernel/hyp-stub.S
@@ -9,6 +9,8 @@
#include <asm/assembler.h>
#include <asm/virt.h>
+.arch armv7-a
+
#ifndef ZIMAGE
/*
* For the kernel proper, we need to find out the CPU boot mode long after
diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c
index f567032a09c0..46364b699cc3 100644
--- a/arch/arm/kernel/machine_kexec.c
+++ b/arch/arm/kernel/machine_kexec.c
@@ -73,10 +73,12 @@ void machine_kexec_cleanup(struct kimage *image)
{
}
-void machine_crash_nonpanic_core(void *unused)
+static void machine_crash_nonpanic_core(void *unused)
{
struct pt_regs regs;
+ local_fiq_disable();
+
crash_setup_regs(&regs, get_irq_regs());
printk(KERN_DEBUG "CPU %u will stop doing anything useful since another CPU has crashed\n",
smp_processor_id());
diff --git a/arch/arm/kernel/module-plts.c b/arch/arm/kernel/module-plts.c
index 1fc309b41f94..af7c322ebed6 100644
--- a/arch/arm/kernel/module-plts.c
+++ b/arch/arm/kernel/module-plts.c
@@ -284,3 +284,17 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
mod->arch.core.plt->sh_size, mod->arch.init.plt->sh_size);
return 0;
}
+
+bool in_module_plt(unsigned long loc)
+{
+ struct module *mod;
+ bool ret;
+
+ preempt_disable();
+ mod = __module_text_address(loc);
+ ret = mod && (loc - (u32)mod->arch.core.plt_ent < mod->arch.core.plt_count * PLT_ENT_SIZE ||
+ loc - (u32)mod->arch.init.plt_ent < mod->arch.init.plt_count * PLT_ENT_SIZE);
+ preempt_enable();
+
+ return ret;
+}
diff --git a/arch/arm/kernel/perf_callchain.c b/arch/arm/kernel/perf_callchain.c
index bc6b246ab55e..7147edbe56c6 100644
--- a/arch/arm/kernel/perf_callchain.c
+++ b/arch/arm/kernel/perf_callchain.c
@@ -81,13 +81,12 @@ perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs
* whist unwinding the stackframe and is like a subroutine return so we use
* the PC.
*/
-static int
-callchain_trace(struct stackframe *fr,
- void *data)
+static bool
+callchain_trace(void *data, unsigned long pc)
{
struct perf_callchain_entry_ctx *entry = data;
- perf_callchain_store(entry, fr->pc);
- return 0;
+ perf_callchain_store(entry, pc);
+ return true;
}
void
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index a2b31d91a1b6..f811733a8fc5 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -371,7 +371,7 @@ static unsigned long sigpage_addr(const struct mm_struct *mm,
slots = ((last - first) >> PAGE_SHIFT) + 1;
- offset = prandom_u32_max(slots);
+ offset = get_random_u32_below(slots);
addr = first + (offset << PAGE_SHIFT);
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index bfe88c6e60d5..2d8e2516906b 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -651,11 +651,9 @@ static int vfp_set(struct task_struct *target,
if (ret)
return ret;
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- user_fpregs_offset + sizeof(new_vfp.fpregs),
- user_fpscr_offset);
- if (ret)
- return ret;
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ user_fpregs_offset + sizeof(new_vfp.fpregs),
+ user_fpscr_offset);
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
&new_vfp.fpscr,
diff --git a/arch/arm/kernel/return_address.c b/arch/arm/kernel/return_address.c
index 38f1ea9c724d..ac15db66df4c 100644
--- a/arch/arm/kernel/return_address.c
+++ b/arch/arm/kernel/return_address.c
@@ -16,17 +16,17 @@ struct return_address_data {
void *addr;
};
-static int save_return_addr(struct stackframe *frame, void *d)
+static bool save_return_addr(void *d, unsigned long pc)
{
struct return_address_data *data = d;
if (!data->level) {
- data->addr = (void *)frame->pc;
+ data->addr = (void *)pc;
- return 1;
+ return false;
} else {
--data->level;
- return 0;
+ return true;
}
}
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index cb88c6e69377..75cd4699e7b3 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -450,6 +450,8 @@ static void __init cpuid_init_hwcaps(void)
{
int block;
u32 isar5;
+ u32 isar6;
+ u32 pfr2;
if (cpu_architecture() < CPU_ARCH_ARMv7)
return;
@@ -485,6 +487,18 @@ static void __init cpuid_init_hwcaps(void)
block = cpuid_feature_extract_field(isar5, 16);
if (block >= 1)
elf_hwcap2 |= HWCAP2_CRC32;
+
+ /* Check for Speculation barrier instruction */
+ isar6 = read_cpuid_ext(CPUID_EXT_ISAR6);
+ block = cpuid_feature_extract_field(isar6, 12);
+ if (block >= 1)
+ elf_hwcap2 |= HWCAP2_SB;
+
+ /* Check for Speculative Store Bypassing control */
+ pfr2 = read_cpuid_ext(CPUID_EXT_PFR2);
+ block = cpuid_feature_extract_field(pfr2, 4);
+ if (block >= 1)
+ elf_hwcap2 |= HWCAP2_SSBS;
}
static void __init elf_hwcap_fixup(void)
@@ -1249,6 +1263,12 @@ static const char *hwcap_str[] = {
"vfpd32",
"lpae",
"evtstrm",
+ "fphp",
+ "asimdhp",
+ "asimddp",
+ "asimdfhm",
+ "asimdbf16",
+ "i8mm",
NULL
};
@@ -1258,6 +1278,8 @@ static const char *hwcap2_str[] = {
"sha1",
"sha2",
"crc32",
+ "sb",
+ "ssbs",
NULL
};
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 978db2d96b44..36e6efad89f3 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -600,6 +600,8 @@ static DEFINE_RAW_SPINLOCK(stop_lock);
*/
static void ipi_cpu_stop(unsigned int cpu)
{
+ local_fiq_disable();
+
if (system_state <= SYSTEM_RUNNING) {
raw_spin_lock(&stop_lock);
pr_crit("CPU%u: stopping\n", cpu);
@@ -609,9 +611,6 @@ static void ipi_cpu_stop(unsigned int cpu)
set_cpu_online(cpu, false);
- local_fiq_disable();
- local_irq_disable();
-
while (1) {
cpu_relax();
wfe();
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c
index 85443b5d1922..620aa82e3bdd 100644
--- a/arch/arm/kernel/stacktrace.c
+++ b/arch/arm/kernel/stacktrace.c
@@ -127,12 +127,12 @@ int notrace unwind_frame(struct stackframe *frame)
#endif
void notrace walk_stackframe(struct stackframe *frame,
- int (*fn)(struct stackframe *, void *), void *data)
+ bool (*fn)(void *, unsigned long), void *data)
{
while (1) {
int ret;
- if (fn(frame, data))
+ if (!fn(data, frame->pc))
break;
ret = unwind_frame(frame);
if (ret < 0)
@@ -142,41 +142,32 @@ void notrace walk_stackframe(struct stackframe *frame,
EXPORT_SYMBOL(walk_stackframe);
#ifdef CONFIG_STACKTRACE
-struct stack_trace_data {
- struct stack_trace *trace;
- unsigned int no_sched_functions;
- unsigned int skip;
-};
-
-static int save_trace(struct stackframe *frame, void *d)
+static void start_stack_trace(struct stackframe *frame, struct task_struct *task,
+ unsigned long fp, unsigned long sp,
+ unsigned long lr, unsigned long pc)
{
- struct stack_trace_data *data = d;
- struct stack_trace *trace = data->trace;
- unsigned long addr = frame->pc;
-
- if (data->no_sched_functions && in_sched_functions(addr))
- return 0;
- if (data->skip) {
- data->skip--;
- return 0;
- }
-
- trace->entries[trace->nr_entries++] = addr;
- return trace->nr_entries >= trace->max_entries;
+ frame->fp = fp;
+ frame->sp = sp;
+ frame->lr = lr;
+ frame->pc = pc;
+#ifdef CONFIG_KRETPROBES
+ frame->kr_cur = NULL;
+ frame->tsk = task;
+#endif
+#ifdef CONFIG_UNWINDER_FRAME_POINTER
+ frame->ex_frame = in_entry_text(frame->pc);
+#endif
}
-/* This must be noinline to so that our skip calculation works correctly */
-static noinline void __save_stack_trace(struct task_struct *tsk,
- struct stack_trace *trace, unsigned int nosched)
+void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,
+ struct task_struct *task, struct pt_regs *regs)
{
- struct stack_trace_data data;
struct stackframe frame;
- data.trace = trace;
- data.skip = trace->skip;
- data.no_sched_functions = nosched;
-
- if (tsk != current) {
+ if (regs) {
+ start_stack_trace(&frame, NULL, regs->ARM_fp, regs->ARM_sp,
+ regs->ARM_lr, regs->ARM_pc);
+ } else if (task != current) {
#ifdef CONFIG_SMP
/*
* What guarantees do we have here that 'tsk' is not
@@ -185,64 +176,22 @@ static noinline void __save_stack_trace(struct task_struct *tsk,
*/
return;
#else
- frame.fp = thread_saved_fp(tsk);
- frame.sp = thread_saved_sp(tsk);
- frame.lr = 0; /* recovered from the stack */
- frame.pc = thread_saved_pc(tsk);
+ start_stack_trace(&frame, task, thread_saved_fp(task),
+ thread_saved_sp(task), 0,
+ thread_saved_pc(task));
#endif
} else {
- /* We don't want this function nor the caller */
- data.skip += 2;
- frame.fp = (unsigned long)__builtin_frame_address(0);
- frame.sp = current_stack_pointer;
- frame.lr = (unsigned long)__builtin_return_address(0);
here:
- frame.pc = (unsigned long)&&here;
+ start_stack_trace(&frame, task,
+ (unsigned long)__builtin_frame_address(0),
+ current_stack_pointer,
+ (unsigned long)__builtin_return_address(0),
+ (unsigned long)&&here);
+ /* skip this function */
+ if (unwind_frame(&frame))
+ return;
}
-#ifdef CONFIG_KRETPROBES
- frame.kr_cur = NULL;
- frame.tsk = tsk;
-#endif
-#ifdef CONFIG_UNWINDER_FRAME_POINTER
- frame.ex_frame = false;
-#endif
-
- walk_stackframe(&frame, save_trace, &data);
-}
-
-void save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
-{
- struct stack_trace_data data;
- struct stackframe frame;
-
- data.trace = trace;
- data.skip = trace->skip;
- data.no_sched_functions = 0;
-
- frame.fp = regs->ARM_fp;
- frame.sp = regs->ARM_sp;
- frame.lr = regs->ARM_lr;
- frame.pc = regs->ARM_pc;
-#ifdef CONFIG_KRETPROBES
- frame.kr_cur = NULL;
- frame.tsk = current;
-#endif
-#ifdef CONFIG_UNWINDER_FRAME_POINTER
- frame.ex_frame = in_entry_text(frame.pc);
-#endif
-
- walk_stackframe(&frame, save_trace, &data);
-}
-void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
-{
- __save_stack_trace(tsk, trace, 1);
-}
-EXPORT_SYMBOL(save_stack_trace_tsk);
-
-void save_stack_trace(struct stack_trace *trace)
-{
- __save_stack_trace(current, trace, 0);
+ walk_stackframe(&frame, consume_entry, cookie);
}
-EXPORT_SYMBOL_GPL(save_stack_trace);
#endif
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c
index b74bfcf94fb1..fdce83c95acb 100644
--- a/arch/arm/kernel/swp_emulate.c
+++ b/arch/arm/kernel/swp_emulate.c
@@ -34,6 +34,7 @@
*/
#define __user_swpX_asm(data, addr, res, temp, B) \
__asm__ __volatile__( \
+ ".arch armv7-a\n" \
"0: ldrex"B" %2, [%3]\n" \
"1: strex"B" %0, %1, [%3]\n" \
" cmp %0, #0\n" \
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 20b2db6dcd1c..40c7c807d67f 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -178,19 +178,22 @@ static void dump_instr(const char *lvl, struct pt_regs *regs)
for (i = -4; i < 1 + !!thumb; i++) {
unsigned int val, bad;
- if (!user_mode(regs)) {
- if (thumb) {
- u16 val16;
- bad = get_kernel_nofault(val16, &((u16 *)addr)[i]);
- val = val16;
- } else {
- bad = get_kernel_nofault(val, &((u32 *)addr)[i]);
- }
+ if (thumb) {
+ u16 tmp;
+
+ if (user_mode(regs))
+ bad = get_user(tmp, &((u16 __user *)addr)[i]);
+ else
+ bad = get_kernel_nofault(tmp, &((u16 *)addr)[i]);
+
+ val = __mem_to_opcode_thumb16(tmp);
} else {
- if (thumb)
- bad = get_user(val, &((u16 *)addr)[i]);
+ if (user_mode(regs))
+ bad = get_user(val, &((u32 __user *)addr)[i]);
else
- bad = get_user(val, &((u32 *)addr)[i]);
+ bad = get_kernel_nofault(val, &((u32 *)addr)[i]);
+
+ val = __mem_to_opcode_arm(val);
}
if (!bad)
diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c
index a37ea6c772cd..53be7ea6181b 100644
--- a/arch/arm/kernel/unwind.c
+++ b/arch/arm/kernel/unwind.c
@@ -28,6 +28,7 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/list.h>
+#include <linux/module.h>
#include <asm/stacktrace.h>
#include <asm/traps.h>
@@ -395,8 +396,18 @@ int unwind_frame(struct stackframe *frame)
idx = unwind_find_idx(frame->pc);
if (!idx) {
- if (frame->pc && kernel_text_address(frame->pc))
+ if (frame->pc && kernel_text_address(frame->pc)) {
+ if (in_module_plt(frame->pc) && frame->pc != frame->lr) {
+ /*
+ * Quoting Ard: Veneers only set PC using a
+ * PC+immediate LDR, and so they don't affect
+ * the state of the stack or the register file
+ */
+ frame->pc = frame->lr;
+ return URC_OK;
+ }
pr_warn("unwind: Index not found %08lx\n", frame->pc);
+ }
return -URC_FAILURE;
}
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index 6d2ba454f25b..650404be6768 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -36,10 +36,6 @@ else
lib-y += io-readsw-armv4.o io-writesw-armv4.o
endif
-ifeq ($(CONFIG_ARCH_RPC),y)
- AFLAGS_delay-loop.o += -march=armv4
-endif
-
$(obj)/csumpartialcopy.o: $(obj)/csumpartialcopygeneric.S
$(obj)/csumpartialcopyuser.o: $(obj)/csumpartialcopygeneric.S
@@ -48,3 +44,5 @@ ifeq ($(CONFIG_KERNEL_MODE_NEON),y)
CFLAGS_xor-neon.o += $(NEON_FLAGS)
obj-$(CONFIG_XOR_BLOCKS) += xor-neon.o
endif
+
+obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o
diff --git a/arch/arm/lib/delay-loop.S b/arch/arm/lib/delay-loop.S
index 3ccade0f8130..3ac05177d097 100644
--- a/arch/arm/lib/delay-loop.S
+++ b/arch/arm/lib/delay-loop.S
@@ -8,6 +8,10 @@
#include <asm/assembler.h>
#include <asm/delay.h>
+#ifdef CONFIG_ARCH_RPC
+ .arch armv4
+#endif
+
.text
.LC0: .word loops_per_jiffy
diff --git a/arch/arm/lib/error-inject.c b/arch/arm/lib/error-inject.c
new file mode 100644
index 000000000000..5a5b405792ba
--- /dev/null
+++ b/arch/arm/lib/error-inject.c
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/error-injection.h>
+#include <linux/kprobes.h>
+
+void override_function_with_return(struct pt_regs *regs)
+{
+ instruction_pointer_set(regs, regs->ARM_lr);
+}
+NOKPROBE_SYMBOL(override_function_with_return);
diff --git a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S
index 7fd3600db8ef..b7ac2d3c0748 100644
--- a/arch/arm/lib/findbit.S
+++ b/arch/arm/lib/findbit.S
@@ -12,182 +12,128 @@
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
+#include <asm/unwind.h>
.text
-/*
- * Purpose : Find a 'zero' bit
- * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
- */
-ENTRY(_find_first_zero_bit_le)
- teq r1, #0
- beq 3f
- mov r2, #0
-1:
- ARM( ldrb r3, [r0, r2, lsr #3] )
- THUMB( lsr r3, r2, #3 )
- THUMB( ldrb r3, [r0, r3] )
- eors r3, r3, #0xff @ invert bits
- bne .L_found @ any now set - found zero bit
- add r2, r2, #8 @ next bit pointer
-2: cmp r2, r1 @ any more?
- blo 1b
-3: mov r0, r1 @ no free bits
- ret lr
-ENDPROC(_find_first_zero_bit_le)
-
-/*
- * Purpose : Find next 'zero' bit
- * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
- */
-ENTRY(_find_next_zero_bit_le)
- cmp r2, r1
- bhs 3b
- ands ip, r2, #7
- beq 1b @ If new byte, goto old routine
- ARM( ldrb r3, [r0, r2, lsr #3] )
- THUMB( lsr r3, r2, #3 )
- THUMB( ldrb r3, [r0, r3] )
- eor r3, r3, #0xff @ now looking for a 1 bit
- movs r3, r3, lsr ip @ shift off unused bits
- bne .L_found
- orr r2, r2, #7 @ if zero, then no bits here
- add r2, r2, #1 @ align bit pointer
- b 2b @ loop for next bit
-ENDPROC(_find_next_zero_bit_le)
+#ifdef __ARMEB__
+#define SWAB_ENDIAN le
+#else
+#define SWAB_ENDIAN be
+#endif
-/*
- * Purpose : Find a 'one' bit
- * Prototype: int find_first_bit(const unsigned long *addr, unsigned int maxbit);
- */
-ENTRY(_find_first_bit_le)
- teq r1, #0
+ .macro find_first, endian, set, name
+ENTRY(_find_first_\name\()bit_\endian)
+ UNWIND( .fnstart)
+ teq r1, #0
beq 3f
mov r2, #0
-1:
- ARM( ldrb r3, [r0, r2, lsr #3] )
- THUMB( lsr r3, r2, #3 )
- THUMB( ldrb r3, [r0, r3] )
- movs r3, r3
- bne .L_found @ any now set - found zero bit
- add r2, r2, #8 @ next bit pointer
+1: ldr r3, [r0], #4
+ .ifeq \set
+ mvns r3, r3 @ invert/test bits
+ .else
+ movs r3, r3 @ test bits
+ .endif
+ .ifc \endian, SWAB_ENDIAN
+ bne .L_found_swab
+ .else
+ bne .L_found @ found the bit?
+ .endif
+ add r2, r2, #32 @ next index
2: cmp r2, r1 @ any more?
blo 1b
-3: mov r0, r1 @ no free bits
+3: mov r0, r1 @ no more bits
ret lr
-ENDPROC(_find_first_bit_le)
+ UNWIND( .fnend)
+ENDPROC(_find_first_\name\()bit_\endian)
+ .endm
-/*
- * Purpose : Find next 'one' bit
- * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
- */
-ENTRY(_find_next_bit_le)
+ .macro find_next, endian, set, name
+ENTRY(_find_next_\name\()bit_\endian)
+ UNWIND( .fnstart)
cmp r2, r1
bhs 3b
- ands ip, r2, #7
- beq 1b @ If new byte, goto old routine
- ARM( ldrb r3, [r0, r2, lsr #3] )
- THUMB( lsr r3, r2, #3 )
- THUMB( ldrb r3, [r0, r3] )
+ mov ip, r2, lsr #5 @ word index
+ add r0, r0, ip, lsl #2
+ ands ip, r2, #31 @ bit position
+ beq 1b
+ ldr r3, [r0], #4
+ .ifeq \set
+ mvn r3, r3 @ invert bits
+ .endif
+ .ifc \endian, SWAB_ENDIAN
+ rev_l r3, ip
+ .if .Lrev_l_uses_tmp
+ @ we need to recompute ip because rev_l will have overwritten
+ @ it.
+ and ip, r2, #31 @ bit position
+ .endif
+ .endif
movs r3, r3, lsr ip @ shift off unused bits
bne .L_found
- orr r2, r2, #7 @ if zero, then no bits here
+ orr r2, r2, #31 @ no zero bits
add r2, r2, #1 @ align bit pointer
b 2b @ loop for next bit
-ENDPROC(_find_next_bit_le)
+ UNWIND( .fnend)
+ENDPROC(_find_next_\name\()bit_\endian)
+ .endm
-#ifdef __ARMEB__
+ .macro find_bit, endian, set, name
+ find_first \endian, \set, \name
+ find_next \endian, \set, \name
+ .endm
-ENTRY(_find_first_zero_bit_be)
- teq r1, #0
- beq 3f
- mov r2, #0
-1: eor r3, r2, #0x18 @ big endian byte ordering
- ARM( ldrb r3, [r0, r3, lsr #3] )
- THUMB( lsr r3, #3 )
- THUMB( ldrb r3, [r0, r3] )
- eors r3, r3, #0xff @ invert bits
- bne .L_found @ any now set - found zero bit
- add r2, r2, #8 @ next bit pointer
-2: cmp r2, r1 @ any more?
- blo 1b
-3: mov r0, r1 @ no free bits
- ret lr
-ENDPROC(_find_first_zero_bit_be)
+/* _find_first_zero_bit_le and _find_next_zero_bit_le */
+ find_bit le, 0, zero_
-ENTRY(_find_next_zero_bit_be)
- cmp r2, r1
- bhs 3b
- ands ip, r2, #7
- beq 1b @ If new byte, goto old routine
- eor r3, r2, #0x18 @ big endian byte ordering
- ARM( ldrb r3, [r0, r3, lsr #3] )
- THUMB( lsr r3, #3 )
- THUMB( ldrb r3, [r0, r3] )
- eor r3, r3, #0xff @ now looking for a 1 bit
- movs r3, r3, lsr ip @ shift off unused bits
- bne .L_found
- orr r2, r2, #7 @ if zero, then no bits here
- add r2, r2, #1 @ align bit pointer
- b 2b @ loop for next bit
-ENDPROC(_find_next_zero_bit_be)
+/* _find_first_bit_le and _find_next_bit_le */
+ find_bit le, 1
-ENTRY(_find_first_bit_be)
- teq r1, #0
- beq 3f
- mov r2, #0
-1: eor r3, r2, #0x18 @ big endian byte ordering
- ARM( ldrb r3, [r0, r3, lsr #3] )
- THUMB( lsr r3, #3 )
- THUMB( ldrb r3, [r0, r3] )
- movs r3, r3
- bne .L_found @ any now set - found zero bit
- add r2, r2, #8 @ next bit pointer
-2: cmp r2, r1 @ any more?
- blo 1b
-3: mov r0, r1 @ no free bits
- ret lr
-ENDPROC(_find_first_bit_be)
+#ifdef __ARMEB__
-ENTRY(_find_next_bit_be)
- cmp r2, r1
- bhs 3b
- ands ip, r2, #7
- beq 1b @ If new byte, goto old routine
- eor r3, r2, #0x18 @ big endian byte ordering
- ARM( ldrb r3, [r0, r3, lsr #3] )
- THUMB( lsr r3, #3 )
- THUMB( ldrb r3, [r0, r3] )
- movs r3, r3, lsr ip @ shift off unused bits
- bne .L_found
- orr r2, r2, #7 @ if zero, then no bits here
- add r2, r2, #1 @ align bit pointer
- b 2b @ loop for next bit
-ENDPROC(_find_next_bit_be)
+/* _find_first_zero_bit_be and _find_next_zero_bit_be */
+ find_bit be, 0, zero_
+
+/* _find_first_bit_be and _find_next_bit_be */
+ find_bit be, 1
#endif
/*
* One or more bits in the LSB of r3 are assumed to be set.
*/
+.L_found_swab:
+ UNWIND( .fnstart)
+ rev_l r3, ip
.L_found:
-#if __LINUX_ARM_ARCH__ >= 5
+#if __LINUX_ARM_ARCH__ >= 7
+ rbit r3, r3 @ reverse bits
+ clz r3, r3 @ count high zero bits
+ add r0, r2, r3 @ add offset of first set bit
+#elif __LINUX_ARM_ARCH__ >= 5
rsb r0, r3, #0
- and r3, r3, r0
- clz r3, r3
- rsb r3, r3, #31
- add r0, r2, r3
+ and r3, r3, r0 @ mask out lowest bit set
+ clz r3, r3 @ count high zero bits
+ rsb r3, r3, #31 @ offset of first set bit
+ add r0, r2, r3 @ add offset of first set bit
#else
- tst r3, #0x0f
+ mov ip, #~0
+ tst r3, ip, lsr #16 @ test bits 0-15
+ addeq r2, r2, #16
+ moveq r3, r3, lsr #16
+ tst r3, #0x00ff
+ addeq r2, r2, #8
+ moveq r3, r3, lsr #8
+ tst r3, #0x000f
addeq r2, r2, #4
- movne r3, r3, lsl #4
- tst r3, #0x30
+ moveq r3, r3, lsr #4
+ tst r3, #0x0003
addeq r2, r2, #2
- movne r3, r3, lsl #2
- tst r3, #0x40
+ moveq r3, r3, lsr #2
+ tst r3, #0x0001
addeq r2, r2, #1
mov r0, r2
#endif
cmp r1, r0 @ Clamp to maxbit
movlo r0, r1
ret lr
-
+ UNWIND( .fnend)
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index 0dcc37180588..794bd12ab0a8 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -14,9 +14,6 @@ obj-$(CONFIG_SOC_SAMV7) += samv7.o
# Power Management
obj-$(CONFIG_ATMEL_PM) += pm.o pm_suspend.o
-ifeq ($(CONFIG_CPU_V7),y)
-AFLAGS_pm_suspend.o := -march=armv7-a
-endif
ifeq ($(CONFIG_PM_DEBUG),y)
CFLAGS_pm.o += -DDEBUG
endif
diff --git a/arch/arm/mach-at91/pm_suspend.S b/arch/arm/mach-at91/pm_suspend.S
index e4904faf1753..e5869cca5e79 100644
--- a/arch/arm/mach-at91/pm_suspend.S
+++ b/arch/arm/mach-at91/pm_suspend.S
@@ -12,6 +12,10 @@
#include "pm.h"
#include "pm_data-offsets.h"
+#ifdef CONFIG_CPU_V7
+.arch armv7-a
+#endif
+
#define SRAMC_SELF_FRESH_ACTIVE 0x01
#define SRAMC_SELF_FRESH_EXIT 0x00
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 6fb3965b9ae6..5c650bf40e02 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -34,7 +34,6 @@ obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
obj-$(CONFIG_HAVE_IMX_SRC) += src.o
ifneq ($(CONFIG_SOC_IMX6)$(CONFIG_SOC_IMX7D_CA7)$(CONFIG_SOC_LS1021A),)
-AFLAGS_headsmp.o :=-Wa,-march=armv7-a
obj-$(CONFIG_SMP) += headsmp.o platsmp.o
obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
endif
@@ -48,12 +47,10 @@ obj-$(CONFIG_SOC_IMX7D_CM4) += mach-imx7d-cm4.o
obj-$(CONFIG_SOC_IMX7ULP) += mach-imx7ulp.o pm-imx7ulp.o
ifeq ($(CONFIG_SUSPEND),y)
-AFLAGS_suspend-imx6.o :=-Wa,-march=armv7-a
obj-$(CONFIG_SOC_IMX6) += suspend-imx6.o
obj-$(CONFIG_SOC_IMX53) += suspend-imx53.o
endif
ifeq ($(CONFIG_ARM_CPU_SUSPEND),y)
-AFLAGS_resume-imx6.o :=-Wa,-march=armv7-a
obj-$(CONFIG_SOC_IMX6) += resume-imx6.o
endif
obj-$(CONFIG_SOC_IMX6) += pm-imx6.o
diff --git a/arch/arm/mach-imx/headsmp.S b/arch/arm/mach-imx/headsmp.S
index fcba58be8e79..5f9c7b48ae80 100644
--- a/arch/arm/mach-imx/headsmp.S
+++ b/arch/arm/mach-imx/headsmp.S
@@ -8,6 +8,8 @@
#include <linux/init.h>
#include <asm/assembler.h>
+.arch armv7-a
+
diag_reg_offset:
.word g_diag_reg - .
diff --git a/arch/arm/mach-imx/mm-imx3.c b/arch/arm/mach-imx/mm-imx3.c
index 28db97289ee8..0788c5cc7f9e 100644
--- a/arch/arm/mach-imx/mm-imx3.c
+++ b/arch/arm/mach-imx/mm-imx3.c
@@ -12,7 +12,6 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/of_address.h>
-#include <linux/pinctrl/machine.h>
#include <asm/system_misc.h>
#include <asm/hardware/cache-l2x0.h>
diff --git a/arch/arm/mach-imx/resume-imx6.S b/arch/arm/mach-imx/resume-imx6.S
index 5bd1ba7ef15b..2c0c5c771251 100644
--- a/arch/arm/mach-imx/resume-imx6.S
+++ b/arch/arm/mach-imx/resume-imx6.S
@@ -9,6 +9,8 @@
#include <asm/hardware/cache-l2x0.h>
#include "hardware.h"
+.arch armv7-a
+
/*
* The following code must assume it is running from physical address
* where absolute virtual addresses to the data section have to be
diff --git a/arch/arm/mach-imx/suspend-imx6.S b/arch/arm/mach-imx/suspend-imx6.S
index e06f946b75b9..63ccc2d0e920 100644
--- a/arch/arm/mach-imx/suspend-imx6.S
+++ b/arch/arm/mach-imx/suspend-imx6.S
@@ -9,6 +9,8 @@
#include <asm/hardware/cache-l2x0.h>
#include "hardware.h"
+.arch armv7-a
+
/*
* ==================== low level suspend ====================
*
diff --git a/arch/arm/mach-ixp4xx/ixp4xx-of.c b/arch/arm/mach-ixp4xx/ixp4xx-of.c
index f543e2adae0c..1b4d84a5b02f 100644
--- a/arch/arm/mach-ixp4xx/ixp4xx-of.c
+++ b/arch/arm/mach-ixp4xx/ixp4xx-of.c
@@ -2,48 +2,7 @@
/*
* IXP4xx Device Tree boot support
*/
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-
#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-
-/*
- * These are the only fixed phys to virt mappings we ever need
- * we put it right after the UART mapping at 0xffc80000-0xffc81fff
- */
-#define IXP4XX_EXP_CFG_BASE_PHYS 0xC4000000
-#define IXP4XX_EXP_CFG_BASE_VIRT 0xFEC14000
-
-static struct map_desc ixp4xx_of_io_desc[] __initdata = {
- /*
- * This is needed for runtime system configuration checks,
- * such as reading if hardware so-and-so is present. This
- * could eventually be converted into a syscon once all boards
- * are converted to device tree.
- */
- {
- .virtual = IXP4XX_EXP_CFG_BASE_VIRT,
- .pfn = __phys_to_pfn(IXP4XX_EXP_CFG_BASE_PHYS),
- .length = SZ_4K,
- .type = MT_DEVICE,
- },
-#ifdef CONFIG_DEBUG_UART_8250
- /* This is needed for LL-debug/earlyprintk/debug-macro.S */
- {
- .virtual = CONFIG_DEBUG_UART_VIRT,
- .pfn = __phys_to_pfn(CONFIG_DEBUG_UART_PHYS),
- .length = SZ_4K,
- .type = MT_DEVICE,
- },
-#endif
-};
-
-static void __init ixp4xx_of_map_io(void)
-{
- iotable_init(ixp4xx_of_io_desc, ARRAY_SIZE(ixp4xx_of_io_desc));
-}
/*
* We handle 4 different SoC families. These compatible strings are enough
@@ -59,6 +18,5 @@ static const char *ixp4xx_of_board_compat[] = {
};
DT_MACHINE_START(IXP4XX_DT, "IXP4xx (Device Tree)")
- .map_io = ixp4xx_of_map_io,
.dt_compat = ixp4xx_of_board_compat,
MACHINE_END
diff --git a/arch/arm/mach-keystone/Makefile b/arch/arm/mach-keystone/Makefile
index 739b38be5696..0c1d54aec60f 100644
--- a/arch/arm/mach-keystone/Makefile
+++ b/arch/arm/mach-keystone/Makefile
@@ -1,7 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-obj-y := keystone.o smc.o
-
-obj-$(CONFIG_SMP) += platsmp.o
+obj-y := keystone.o
# PM domain driver for Keystone SOCs
obj-$(CONFIG_ARCH_KEYSTONE) += pm_domain.o
diff --git a/arch/arm/mach-keystone/keystone.c b/arch/arm/mach-keystone/keystone.c
index 2c647bdf8d25..aa352c2de313 100644
--- a/arch/arm/mach-keystone/keystone.c
+++ b/arch/arm/mach-keystone/keystone.c
@@ -18,7 +18,6 @@
#include <asm/mach/map.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
-#include <asm/smp_plat.h>
#include <asm/memory.h>
#include "memory.h"
@@ -103,7 +102,6 @@ DT_MACHINE_START(KEYSTONE, "Keystone")
#if defined(CONFIG_ZONE_DMA) && defined(CONFIG_ARM_LPAE)
.dma_zone_size = SZ_2G,
#endif
- .smp = smp_ops(keystone_smp_ops),
.init_machine = keystone_init,
.dt_compat = keystone_match,
.pv_fixup = keystone_pv_fixup,
diff --git a/arch/arm/mach-keystone/keystone.h b/arch/arm/mach-keystone/keystone.h
index 438e531cc007..71ff8cd2ee4a 100644
--- a/arch/arm/mach-keystone/keystone.h
+++ b/arch/arm/mach-keystone/keystone.h
@@ -8,13 +8,8 @@
#ifndef __KEYSTONE_H__
#define __KEYSTONE_H__
-#define KEYSTONE_MON_CPU_UP_IDX 0x00
-
#ifndef __ASSEMBLER__
-extern const struct smp_operations keystone_smp_ops;
-extern void secondary_startup(void);
-extern u32 keystone_cpu_smc(u32 command, u32 cpu, u32 addr);
extern int keystone_pm_runtime_init(void);
#endif /* __ASSEMBLER__ */
diff --git a/arch/arm/mach-keystone/platsmp.c b/arch/arm/mach-keystone/platsmp.c
deleted file mode 100644
index 673fcf3b34b1..000000000000
--- a/arch/arm/mach-keystone/platsmp.c
+++ /dev/null
@@ -1,41 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Keystone SOC SMP platform code
- *
- * Copyright 2013 Texas Instruments, Inc.
- * Cyril Chemparathy <cyril@ti.com>
- * Santosh Shilimkar <santosh.shillimkar@ti.com>
- *
- * Based on platsmp.c, Copyright (C) 2002 ARM Ltd.
- */
-
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/io.h>
-#include <linux/pgtable.h>
-
-#include <asm/smp_plat.h>
-#include <asm/prom.h>
-#include <asm/tlbflush.h>
-
-#include "keystone.h"
-
-static int keystone_smp_boot_secondary(unsigned int cpu,
- struct task_struct *idle)
-{
- unsigned long start = virt_to_idmap(&secondary_startup);
- int error;
-
- pr_debug("keystone-smp: booting cpu %d, vector %08lx\n",
- cpu, start);
-
- error = keystone_cpu_smc(KEYSTONE_MON_CPU_UP_IDX, cpu, start);
- if (error)
- pr_err("CPU %d bringup failed with %d\n", cpu, error);
-
- return error;
-}
-
-const struct smp_operations keystone_smp_ops __initconst = {
- .smp_boot_secondary = keystone_smp_boot_secondary,
-};
diff --git a/arch/arm/mach-keystone/smc.S b/arch/arm/mach-keystone/smc.S
deleted file mode 100644
index 21ef75cf5370..000000000000
--- a/arch/arm/mach-keystone/smc.S
+++ /dev/null
@@ -1,26 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Keystone Secure APIs
- *
- * Copyright (C) 2013 Texas Instruments, Inc.
- * Santosh Shilimkar <santosh.shilimkar@ti.com>
- */
-
-#include <linux/linkage.h>
-
-/**
- * u32 keystone_cpu_smc(u32 command, u32 cpu, u32 addr)
- *
- * Low level CPU monitor API
- * @command: Monitor command.
- * @cpu: CPU Number
- * @addr: Kernel jump address for boot CPU
- *
- * Return: Non zero value on failure
- */
- .arch_extension sec
-ENTRY(keystone_cpu_smc)
- stmfd sp!, {r4-r11, lr}
- smc #0
- ldmfd sp!, {r4-r11, pc}
-ENDPROC(keystone_cpu_smc)
diff --git a/arch/arm/mach-mmp/time.c b/arch/arm/mach-mmp/time.c
index 41b2e8abc9e6..708816caf859 100644
--- a/arch/arm/mach-mmp/time.c
+++ b/arch/arm/mach-mmp/time.c
@@ -43,18 +43,21 @@
static void __iomem *mmp_timer_base = TIMERS_VIRT_BASE;
/*
- * FIXME: the timer needs some delay to stablize the counter capture
+ * Read the timer through the CVWR register. Delay is required after requesting
+ * a read. The CR register cannot be directly read due to metastability issues
+ * documented in the PXA168 software manual.
*/
static inline uint32_t timer_read(void)
{
- int delay = 100;
+ uint32_t val;
+ int delay = 3;
__raw_writel(1, mmp_timer_base + TMR_CVWR(1));
while (delay--)
- cpu_relax();
+ val = __raw_readl(mmp_timer_base + TMR_CVWR(1));
- return __raw_readl(mmp_timer_base + TMR_CVWR(1));
+ return val;
}
static u64 notrace mmp_read_sched_clock(void)
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index c21733cbb4fa..569768a69ffc 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -1,9 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
ccflags-y := -I$(srctree)/arch/arm/plat-orion/include
-AFLAGS_coherency_ll.o := -Wa,-march=armv7-a
-CFLAGS_pmsu.o := -march=armv7-a
-
obj-$(CONFIG_MACH_MVEBU_ANY) += system-controller.o mvebu-soc-id.o
ifeq ($(CONFIG_MACH_MVEBU_V7),y)
diff --git a/arch/arm/mach-mvebu/coherency_ll.S b/arch/arm/mach-mvebu/coherency_ll.S
index eb81656e32d4..35930e03d9c6 100644
--- a/arch/arm/mach-mvebu/coherency_ll.S
+++ b/arch/arm/mach-mvebu/coherency_ll.S
@@ -20,6 +20,7 @@
#include <asm/assembler.h>
#include <asm/cp15.h>
+ .arch armv7-a
.text
/*
* Returns the coherency base address in r1 (r0 is untouched), or 0 if
diff --git a/arch/arm/mach-mvebu/pm-board.c b/arch/arm/mach-mvebu/pm-board.c
index 7fa1806acd65..beec22e17e89 100644
--- a/arch/arm/mach-mvebu/pm-board.c
+++ b/arch/arm/mach-mvebu/pm-board.c
@@ -8,19 +8,19 @@
*/
#include <linux/delay.h>
-#include <linux/gpio.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
-#include <linux/of_gpio.h>
#include <linux/slab.h>
#include "common.h"
#define ARMADA_PIC_NR_GPIOS 3
static void __iomem *gpio_ctrl;
-static int pic_gpios[ARMADA_PIC_NR_GPIOS];
+static struct gpio_desc *pic_gpios[ARMADA_PIC_NR_GPIOS];
static int pic_raw_gpios[ARMADA_PIC_NR_GPIOS];
static void mvebu_armada_pm_enter(void __iomem *sdram_reg, u32 srcmd)
@@ -90,27 +90,17 @@ static int __init mvebu_armada_pm_init(void)
char *name;
struct of_phandle_args args;
- pic_gpios[i] = of_get_named_gpio(np, "ctrl-gpios", i);
- if (pic_gpios[i] < 0) {
- ret = -ENODEV;
- goto out;
- }
-
name = kasprintf(GFP_KERNEL, "pic-pin%d", i);
if (!name) {
ret = -ENOMEM;
goto out;
}
- ret = gpio_request(pic_gpios[i], name);
- if (ret < 0) {
- kfree(name);
- goto out;
- }
-
- ret = gpio_direction_output(pic_gpios[i], 0);
- if (ret < 0) {
- gpio_free(pic_gpios[i]);
+ pic_gpios[i] = fwnode_gpiod_get_index(of_fwnode_handle(np),
+ "ctrl", i, GPIOD_OUT_HIGH,
+ name);
+ ret = PTR_ERR_OR_ZERO(pic_gpios[i]);
+ if (ret) {
kfree(name);
goto out;
}
@@ -118,7 +108,7 @@ static int __init mvebu_armada_pm_init(void)
ret = of_parse_phandle_with_fixed_args(np, "ctrl-gpios", 2,
i, &args);
if (ret < 0) {
- gpio_free(pic_gpios[i]);
+ gpiod_put(pic_gpios[i]);
kfree(name);
goto out;
}
diff --git a/arch/arm/mach-mvebu/pmsu.c b/arch/arm/mach-mvebu/pmsu.c
index af27a7156675..6f366d8c4231 100644
--- a/arch/arm/mach-mvebu/pmsu.c
+++ b/arch/arm/mach-mvebu/pmsu.c
@@ -291,6 +291,7 @@ int armada_370_xp_pmsu_idle_enter(unsigned long deepidle)
/* Test the CR_C bit and set it if it was cleared */
asm volatile(
+ ".arch armv7-a\n\t"
"mrc p15, 0, r0, c1, c0, 0 \n\t"
"tst r0, %0 \n\t"
"orreq r0, r0, #(1 << 2) \n\t"
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c
index 1c57ac401649..0129b7c514d7 100644
--- a/arch/arm/mach-mxs/mach-mxs.c
+++ b/arch/arm/mach-mxs/mach-mxs.c
@@ -17,7 +17,6 @@
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/phy.h>
-#include <linux/pinctrl/consumer.h>
#include <linux/sys_soc.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
diff --git a/arch/arm/mach-npcm/Makefile b/arch/arm/mach-npcm/Makefile
index 8d61fcd42fb1..ac83e1caf2ee 100644
--- a/arch/arm/mach-npcm/Makefile
+++ b/arch/arm/mach-npcm/Makefile
@@ -1,6 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
-AFLAGS_headsmp.o += -march=armv7-a
-
obj-$(CONFIG_ARCH_WPCM450) += wpcm450.o
obj-$(CONFIG_ARCH_NPCM7XX) += npcm7xx.o
obj-$(CONFIG_SMP) += platsmp.o headsmp.o
diff --git a/arch/arm/mach-npcm/headsmp.S b/arch/arm/mach-npcm/headsmp.S
index c083fe09a07b..84d2b6daaf0b 100644
--- a/arch/arm/mach-npcm/headsmp.S
+++ b/arch/arm/mach-npcm/headsmp.S
@@ -6,6 +6,8 @@
#include <linux/init.h>
#include <asm/assembler.h>
+.arch armv7-a
+
/*
* The boot ROM does not start secondary CPUs in SVC mode, so we need to do that
* here.
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index 5e86145db0e2..8897364e550b 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -22,7 +22,6 @@
#include <linux/platform_data/spi-omap2-mcspi.h>
#include <linux/platform_data/mmc-omap.h>
#include <linux/mfd/menelaus.h>
-#include <sound/tlv320aic3x.h>
#include <asm/mach/arch.h>
#include <asm/mach-types.h>
@@ -567,10 +566,6 @@ struct menelaus_platform_data n8x0_menelaus_platform_data = {
.late_init = n8x0_menelaus_late_init,
};
-struct aic3x_pdata n810_aic33_data = {
- .gpio_reset = 118,
-};
-
static int __init n8x0_late_initcall(void)
{
if (!board_caps)
diff --git a/arch/arm/mach-omap2/common-board-devices.h b/arch/arm/mach-omap2/common-board-devices.h
index b23962c38fb2..69694af71475 100644
--- a/arch/arm/mach-omap2/common-board-devices.h
+++ b/arch/arm/mach-omap2/common-board-devices.h
@@ -2,12 +2,10 @@
#ifndef __OMAP_COMMON_BOARD_DEVICES__
#define __OMAP_COMMON_BOARD_DEVICES__
-#include <sound/tlv320aic3x.h>
#include <linux/mfd/menelaus.h>
void *n8x0_legacy_init(void);
extern struct menelaus_platform_data n8x0_menelaus_platform_data;
-extern struct aic3x_pdata n810_aic33_data;
#endif /* __OMAP_COMMON_BOARD_DEVICES__ */
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index b6c7d98a9eff..4d46c56db38b 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -1135,65 +1135,6 @@ static struct omap_hwmod omap34xx_mcspi4 = {
.class = &omap34xx_mcspi_class,
};
-/* usbhsotg */
-static struct omap_hwmod_class_sysconfig omap3xxx_usbhsotg_sysc = {
- .rev_offs = 0x0400,
- .sysc_offs = 0x0404,
- .syss_offs = 0x0408,
- .sysc_flags = (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE|
- SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
- SYSC_HAS_AUTOIDLE),
- .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
- MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
- .sysc_fields = &omap_hwmod_sysc_type1,
-};
-
-static struct omap_hwmod_class usbotg_class = {
- .name = "usbotg",
- .sysc = &omap3xxx_usbhsotg_sysc,
-};
-
-/* usb_otg_hs */
-
-static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
- .name = "usb_otg_hs",
- .main_clk = "hsotgusb_ick",
- .prcm = {
- .omap2 = {
- .module_offs = CORE_MOD,
- .idlest_reg_id = 1,
- .idlest_idle_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT,
- },
- },
- .class = &usbotg_class,
-
- /*
- * Erratum ID: i479 idle_req / idle_ack mechanism potentially
- * broken when autoidle is enabled
- * workaround is to disable the autoidle bit at module level.
- *
- * Enabling the device in any other MIDLEMODE setting but force-idle
- * causes core_pwrdm not enter idle states at least on OMAP3630.
- * Note that musb has OTG_FORCESTDBY register that controls MSTANDBY
- * signal when MIDLEMODE is set to force-idle.
- */
- .flags = HWMOD_NO_OCP_AUTOIDLE | HWMOD_SWSUP_SIDLE |
- HWMOD_FORCE_MSTANDBY | HWMOD_RECONFIG_IO_CHAIN,
-};
-
-/* usb_otg_hs */
-
-static struct omap_hwmod_class am35xx_usbotg_class = {
- .name = "am35xx_usbotg",
-};
-
-static struct omap_hwmod am35xx_usbhsotg_hwmod = {
- .name = "am35x_otg_hs",
- .main_clk = "hsotgusb_fck",
- .class = &am35xx_usbotg_class,
- .flags = HWMOD_NO_IDLEST,
-};
-
/* MMC/SD/SDIO common */
static struct omap_hwmod_class_sysconfig omap34xx_mmc_sysc = {
.rev_offs = 0x1fc,
@@ -1561,22 +1502,6 @@ static struct omap_hwmod_ocp_if omap3xxx_dss__l3 = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
-/* l3_core -> usbhsotg interface */
-static struct omap_hwmod_ocp_if omap3xxx_usbhsotg__l3 = {
- .master = &omap3xxx_usbhsotg_hwmod,
- .slave = &omap3xxx_l3_main_hwmod,
- .clk = "core_l3_ick",
- .user = OCP_USER_MPU,
-};
-
-/* l3_core -> am35xx_usbhsotg interface */
-static struct omap_hwmod_ocp_if am35xx_usbhsotg__l3 = {
- .master = &am35xx_usbhsotg_hwmod,
- .slave = &omap3xxx_l3_main_hwmod,
- .clk = "hsotgusb_ick",
- .user = OCP_USER_MPU,
-};
-
/* l3_core -> sad2d interface */
static struct omap_hwmod_ocp_if omap3xxx_sad2d__l3 = {
.master = &omap3xxx_sad2d_hwmod,
@@ -1758,24 +1683,6 @@ static struct omap_hwmod_ocp_if omap36xx_l4_core__sr2 = {
.user = OCP_USER_MPU,
};
-
-/* l4_core -> usbhsotg */
-static struct omap_hwmod_ocp_if omap3xxx_l4_core__usbhsotg = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &omap3xxx_usbhsotg_hwmod,
- .clk = "l4_ick",
- .user = OCP_USER_MPU,
-};
-
-
-/* l4_core -> usbhsotg */
-static struct omap_hwmod_ocp_if am35xx_l4_core__usbhsotg = {
- .master = &omap3xxx_l4_core_hwmod,
- .slave = &am35xx_usbhsotg_hwmod,
- .clk = "hsotgusb_ick",
- .user = OCP_USER_MPU,
-};
-
/* L4_WKUP -> L4_SEC interface */
static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__l4_sec = {
.master = &omap3xxx_l4_wkup_hwmod,
@@ -2465,8 +2372,6 @@ static struct omap_hwmod_ocp_if *omap3430es1_hwmod_ocp_ifs[] __initdata = {
static struct omap_hwmod_ocp_if *omap3430es2plus_hwmod_ocp_ifs[] __initdata = {
&omap3xxx_dss__l3,
&omap3xxx_l4_core__dss,
- &omap3xxx_usbhsotg__l3,
- &omap3xxx_l4_core__usbhsotg,
&omap3xxx_usb_host_hs__l3_main_2,
&omap3xxx_l4_core__usb_host_hs,
&omap3xxx_l4_core__usb_tll_hs,
@@ -2509,8 +2414,6 @@ static struct omap_hwmod_ocp_if *omap36xx_hwmod_ocp_ifs[] __initdata = {
&omap3xxx_l4_core__dss,
&omap36xx_l4_core__sr1,
&omap36xx_l4_core__sr2,
- &omap3xxx_usbhsotg__l3,
- &omap3xxx_l4_core__usbhsotg,
&omap3xxx_l4_core__mailbox,
&omap3xxx_usb_host_hs__l3_main_2,
&omap3xxx_l4_core__usb_host_hs,
@@ -2528,8 +2431,6 @@ static struct omap_hwmod_ocp_if *omap36xx_hwmod_ocp_ifs[] __initdata = {
static struct omap_hwmod_ocp_if *am35xx_hwmod_ocp_ifs[] __initdata = {
&omap3xxx_dss__l3,
&omap3xxx_l4_core__dss,
- &am35xx_usbhsotg__l3,
- &am35xx_l4_core__usbhsotg,
&am35xx_l4_core__uart4,
&omap3xxx_usb_host_hs__l3_main_2,
&omap3xxx_l4_core__usb_host_hs,
diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c
index 9409b9f5711c..baba73fd6f11 100644
--- a/arch/arm/mach-omap2/pdata-quirks.c
+++ b/arch/arm/mach-omap2/pdata-quirks.c
@@ -439,7 +439,6 @@ static struct of_dev_auxdata omap_auxdata_lookup[] = {
#ifdef CONFIG_MACH_NOKIA_N8X0
OF_DEV_AUXDATA("ti,omap2420-mmc", 0x4809c000, "mmci-omap.0", NULL),
OF_DEV_AUXDATA("menelaus", 0x72, "1-0072", &n8x0_menelaus_platform_data),
- OF_DEV_AUXDATA("tlv320aic3x", 0x18, "2-0018", &n810_aic33_data),
#endif
#ifdef CONFIG_ARCH_OMAP3
OF_DEV_AUXDATA("ti,omap2-iommu", 0x5d000000, "5d000000.mmu",
diff --git a/arch/arm/mach-s3c/mach-crag6410.c b/arch/arm/mach-s3c/mach-crag6410.c
index 9a45474d1bf7..2ecb85856e24 100644
--- a/arch/arm/mach-s3c/mach-crag6410.c
+++ b/arch/arm/mach-s3c/mach-crag6410.c
@@ -14,6 +14,7 @@
#include <linux/fb.h>
#include <linux/io.h>
#include <linux/init.h>
+#include <linux/input-event-codes.h>
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/leds.h>
diff --git a/arch/arm/mach-shmobile/Kconfig b/arch/arm/mach-shmobile/Kconfig
index 37f862f13c8d..8d64cc7edccd 100644
--- a/arch/arm/mach-shmobile/Kconfig
+++ b/arch/arm/mach-shmobile/Kconfig
@@ -3,7 +3,5 @@ menuconfig ARCH_RENESAS
bool "Renesas ARM SoCs"
depends on ARCH_MULTI_V7
select ARM_GIC
- select GPIOLIB
select NO_IOPORT_MAP
- select PINCTRL
select ZONE_DMA if ARM_LPAE
diff --git a/arch/arm/mach-spear/time.c b/arch/arm/mach-spear/time.c
index e979e2197f8e..5371c824786d 100644
--- a/arch/arm/mach-spear/time.c
+++ b/arch/arm/mach-spear/time.c
@@ -90,7 +90,7 @@ static void __init spear_clocksource_init(void)
200, 16, clocksource_mmio_readw_up);
}
-static inline void timer_shutdown(struct clock_event_device *evt)
+static inline void spear_timer_shutdown(struct clock_event_device *evt)
{
u16 val = readw(gpt_base + CR(CLKEVT));
@@ -101,7 +101,7 @@ static inline void timer_shutdown(struct clock_event_device *evt)
static int spear_shutdown(struct clock_event_device *evt)
{
- timer_shutdown(evt);
+ spear_timer_shutdown(evt);
return 0;
}
@@ -111,7 +111,7 @@ static int spear_set_oneshot(struct clock_event_device *evt)
u16 val;
/* stop the timer */
- timer_shutdown(evt);
+ spear_timer_shutdown(evt);
val = readw(gpt_base + CR(CLKEVT));
val |= CTRL_ONE_SHOT;
@@ -126,7 +126,7 @@ static int spear_set_periodic(struct clock_event_device *evt)
u16 val;
/* stop the timer */
- timer_shutdown(evt);
+ spear_timer_shutdown(evt);
period = clk_get_rate(gpt_clk) / HZ;
period >>= CTRL_PRESCALER16;
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 07572b5373b8..a2bb55bc0081 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -1,6 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
-asflags-y += -march=armv7-a
-
obj-y += io.o
obj-y += irq.o
obj-y += pm.o
diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
index 06ca44b09381..0ea456264f3e 100644
--- a/arch/arm/mach-tegra/reset-handler.S
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -19,6 +19,8 @@
#define PMC_SCRATCH41 0x140
+.arch armv7-a
+
#ifdef CONFIG_PM_SLEEP
/*
* tegra_resume
diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S
index a5a36cce142a..d8cd487a8f63 100644
--- a/arch/arm/mach-tegra/sleep-tegra20.S
+++ b/arch/arm/mach-tegra/sleep-tegra20.S
@@ -47,6 +47,8 @@
#define PLLM_STORE_MASK (1 << 1)
#define PLLP_STORE_MASK (1 << 2)
+.arch armv7-a
+
.macro test_pll_state, rd, test_mask
ldr \rd, tegra_pll_state
tst \rd, #\test_mask
diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S
index 0cc40b6b2ba3..134ea5fe49b2 100644
--- a/arch/arm/mach-tegra/sleep-tegra30.S
+++ b/arch/arm/mach-tegra/sleep-tegra30.S
@@ -78,6 +78,8 @@
#define PLLX_STORE_MASK (1 << 4)
#define PLLM_PMC_STORE_MASK (1 << 5)
+.arch armv7-a
+
.macro emc_device_mask, rd, base
ldr \rd, [\base, #EMC_ADR_CFG]
tst \rd, #0x1
diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S
index 8f88944831c5..945f2c1474f7 100644
--- a/arch/arm/mach-tegra/sleep.S
+++ b/arch/arm/mach-tegra/sleep.S
@@ -22,6 +22,8 @@
#define CLK_RESET_CCLK_BURST 0x20
#define CLK_RESET_CCLK_DIVIDER 0x24
+.arch armv7-a
+
#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
/*
* tegra_disable_clean_inv_dcache
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index e929aaa744c0..7cc0dd8ed991 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -26,7 +26,6 @@
#include <asm/mach/map.h>
#include <asm/mach/arch.h>
-#include "db8500-regs.h"
#include "pm_domains.h"
static int __init ux500_l2x0_unlock(void)
diff --git a/arch/arm/mach-ux500/db8500-regs.h b/arch/arm/mach-ux500/db8500-regs.h
deleted file mode 100644
index 0d47d7171d9b..000000000000
--- a/arch/arm/mach-ux500/db8500-regs.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) ST-Ericsson SA 2010
- */
-
-#ifndef __MACH_DB8500_REGS_H
-#define __MACH_DB8500_REGS_H
-
-/* Base address and bank offsets for ESRAM */
-#define U8500_ESRAM_BASE 0x40000000
-#define U8500_ESRAM_BANK_SIZE 0x00020000
-#define U8500_ESRAM_BANK0 U8500_ESRAM_BASE
-#define U8500_ESRAM_BANK1 (U8500_ESRAM_BASE + U8500_ESRAM_BANK_SIZE)
-#define U8500_ESRAM_BANK2 (U8500_ESRAM_BANK1 + U8500_ESRAM_BANK_SIZE)
-#define U8500_ESRAM_BANK3 (U8500_ESRAM_BANK2 + U8500_ESRAM_BANK_SIZE)
-#define U8500_ESRAM_BANK4 (U8500_ESRAM_BANK3 + U8500_ESRAM_BANK_SIZE)
-/*
- * on V1 DMA uses 4KB for logical parameters position is right after the 64KB
- * reserved for security
- */
-#define U8500_ESRAM_DMA_LCPA_OFFSET 0x10000
-
-#define U8500_DMA_LCPA_BASE (U8500_ESRAM_BANK0 + U8500_ESRAM_DMA_LCPA_OFFSET)
-
-/* This address fulfills the 256k alignment requirement of the lcla base */
-#define U8500_DMA_LCLA_BASE U8500_ESRAM_BANK4
-
-#define U8500_PER3_BASE 0x80000000
-#define U8500_STM_BASE 0x80100000
-#define U8500_STM_REG_BASE (U8500_STM_BASE + 0xF000)
-#define U8500_PER2_BASE 0x80110000
-#define U8500_PER1_BASE 0x80120000
-#define U8500_B2R2_BASE 0x80130000
-#define U8500_HSEM_BASE 0x80140000
-#define U8500_PER4_BASE 0x80150000
-#define U8500_TPIU_BASE 0x80190000
-#define U8500_ICN_BASE 0x81000000
-
-#define U8500_BOOT_ROM_BASE 0x90000000
-/* ASIC ID is at 0xbf4 offset within this region */
-#define U8500_ASIC_ID_BASE 0x9001D000
-
-#define U8500_PER6_BASE 0xa03c0000
-#define U8500_PER7_BASE 0xa03d0000
-#define U8500_PER5_BASE 0xa03e0000
-
-#define U8500_SVA_BASE 0xa0100000
-#define U8500_SIA_BASE 0xa0200000
-
-#define U8500_SGA_BASE 0xa0300000
-#define U8500_MCDE_BASE 0xa0350000
-#define U8500_DMA_BASE 0x801C0000 /* v1 */
-
-#define U8500_SBAG_BASE 0xa0390000
-
-#define U8500_SCU_BASE 0xa0410000
-#define U8500_GIC_CPU_BASE 0xa0410100
-#define U8500_TWD_BASE 0xa0410600
-#define U8500_GIC_DIST_BASE 0xa0411000
-#define U8500_L2CC_BASE 0xa0412000
-
-#define U8500_MODEM_I2C 0xb7e02000
-
-#define U8500_GPIO0_BASE (U8500_PER1_BASE + 0xE000)
-#define U8500_GPIO1_BASE (U8500_PER3_BASE + 0xE000)
-#define U8500_GPIO2_BASE (U8500_PER2_BASE + 0xE000)
-#define U8500_GPIO3_BASE (U8500_PER5_BASE + 0x1E000)
-
-#define U8500_UART0_BASE (U8500_PER1_BASE + 0x0000)
-#define U8500_UART1_BASE (U8500_PER1_BASE + 0x1000)
-
-/* per6 base addresses */
-#define U8500_RNG_BASE (U8500_PER6_BASE + 0x0000)
-#define U8500_HASH0_BASE (U8500_PER6_BASE + 0x1000)
-#define U8500_HASH1_BASE (U8500_PER6_BASE + 0x2000)
-#define U8500_PKA_BASE (U8500_PER6_BASE + 0x4000)
-#define U8500_PKAM_BASE (U8500_PER6_BASE + 0x5100)
-#define U8500_MTU0_BASE (U8500_PER6_BASE + 0x6000) /* v1 */
-#define U8500_MTU1_BASE (U8500_PER6_BASE + 0x7000) /* v1 */
-#define U8500_CR_BASE (U8500_PER6_BASE + 0x8000) /* v1 */
-#define U8500_CRYP0_BASE (U8500_PER6_BASE + 0xa000)
-#define U8500_CRYP1_BASE (U8500_PER6_BASE + 0xb000)
-#define U8500_CLKRST6_BASE (U8500_PER6_BASE + 0xf000)
-
-/* per5 base addresses */
-#define U8500_USBOTG_BASE (U8500_PER5_BASE + 0x00000)
-#define U8500_CLKRST5_BASE (U8500_PER5_BASE + 0x1f000)
-
-/* per4 base addresses */
-#define U8500_BACKUPRAM0_BASE (U8500_PER4_BASE + 0x00000)
-#define U8500_BACKUPRAM1_BASE (U8500_PER4_BASE + 0x01000)
-#define U8500_RTT0_BASE (U8500_PER4_BASE + 0x02000)
-#define U8500_RTT1_BASE (U8500_PER4_BASE + 0x03000)
-#define U8500_RTC_BASE (U8500_PER4_BASE + 0x04000)
-#define U8500_SCR_BASE (U8500_PER4_BASE + 0x05000)
-#define U8500_DMC_BASE (U8500_PER4_BASE + 0x06000)
-#define U8500_PRCMU_BASE (U8500_PER4_BASE + 0x07000)
-#define U9540_DMC1_BASE (U8500_PER4_BASE + 0x0A000)
-#define U8500_PRCMU_TCDM_BASE (U8500_PER4_BASE + 0x68000)
-#define U8500_PRCMU_TCPM_BASE (U8500_PER4_BASE + 0x60000)
-#define U8500_PRCMU_TIMER_3_BASE (U8500_PER4_BASE + 0x07338)
-#define U8500_PRCMU_TIMER_4_BASE (U8500_PER4_BASE + 0x07450)
-
-/* per3 base addresses */
-#define U8500_FSMC_BASE (U8500_PER3_BASE + 0x0000)
-#define U8500_SSP0_BASE (U8500_PER3_BASE + 0x2000)
-#define U8500_SSP1_BASE (U8500_PER3_BASE + 0x3000)
-#define U8500_I2C0_BASE (U8500_PER3_BASE + 0x4000)
-#define U8500_SDI2_BASE (U8500_PER3_BASE + 0x5000)
-#define U8500_SKE_BASE (U8500_PER3_BASE + 0x6000)
-#define U8500_UART2_BASE (U8500_PER3_BASE + 0x7000)
-#define U8500_SDI5_BASE (U8500_PER3_BASE + 0x8000)
-#define U8500_CLKRST3_BASE (U8500_PER3_BASE + 0xf000)
-
-/* per2 base addresses */
-#define U8500_I2C3_BASE (U8500_PER2_BASE + 0x0000)
-#define U8500_SPI2_BASE (U8500_PER2_BASE + 0x1000)
-#define U8500_SPI1_BASE (U8500_PER2_BASE + 0x2000)
-#define U8500_PWL_BASE (U8500_PER2_BASE + 0x3000)
-#define U8500_SDI4_BASE (U8500_PER2_BASE + 0x4000)
-#define U8500_MSP2_BASE (U8500_PER2_BASE + 0x7000)
-#define U8500_SDI1_BASE (U8500_PER2_BASE + 0x8000)
-#define U8500_SDI3_BASE (U8500_PER2_BASE + 0x9000)
-#define U8500_SPI0_BASE (U8500_PER2_BASE + 0xa000)
-#define U8500_HSIR_BASE (U8500_PER2_BASE + 0xb000)
-#define U8500_HSIT_BASE (U8500_PER2_BASE + 0xc000)
-#define U8500_CLKRST2_BASE (U8500_PER2_BASE + 0xf000)
-
-/* per1 base addresses */
-#define U8500_I2C1_BASE (U8500_PER1_BASE + 0x2000)
-#define U8500_MSP0_BASE (U8500_PER1_BASE + 0x3000)
-#define U8500_MSP1_BASE (U8500_PER1_BASE + 0x4000)
-#define U8500_MSP3_BASE (U8500_PER1_BASE + 0x5000)
-#define U8500_SDI0_BASE (U8500_PER1_BASE + 0x6000)
-#define U8500_I2C2_BASE (U8500_PER1_BASE + 0x8000)
-#define U8500_SPI3_BASE (U8500_PER1_BASE + 0x9000)
-#define U8500_I2C4_BASE (U8500_PER1_BASE + 0xa000)
-#define U8500_SLIM0_BASE (U8500_PER1_BASE + 0xb000)
-#define U8500_CLKRST1_BASE (U8500_PER1_BASE + 0xf000)
-
-#define U8500_SHRM_GOP_INTERRUPT_BASE 0xB7C00040
-
-#define U8500_GPIOBANK0_BASE U8500_GPIO0_BASE
-#define U8500_GPIOBANK1_BASE (U8500_GPIO0_BASE + 0x80)
-#define U8500_GPIOBANK2_BASE U8500_GPIO1_BASE
-#define U8500_GPIOBANK3_BASE (U8500_GPIO1_BASE + 0x80)
-#define U8500_GPIOBANK4_BASE (U8500_GPIO1_BASE + 0x100)
-#define U8500_GPIOBANK5_BASE (U8500_GPIO1_BASE + 0x180)
-#define U8500_GPIOBANK6_BASE U8500_GPIO2_BASE
-#define U8500_GPIOBANK7_BASE (U8500_GPIO2_BASE + 0x80)
-#define U8500_GPIOBANK8_BASE U8500_GPIO3_BASE
-
-#define U8500_MCDE_SIZE 0x1000
-#define U8500_DSI_LINK_SIZE 0x1000
-#define U8500_DSI_LINK1_BASE (U8500_MCDE_BASE + U8500_MCDE_SIZE)
-#define U8500_DSI_LINK2_BASE (U8500_DSI_LINK1_BASE + U8500_DSI_LINK_SIZE)
-#define U8500_DSI_LINK3_BASE (U8500_DSI_LINK2_BASE + U8500_DSI_LINK_SIZE)
-#define U8500_DSI_LINK_COUNT 0x3
-
-/* Modem and APE physical addresses */
-#define U8500_MODEM_BASE 0xe000000
-#define U8500_APE_BASE 0x6000000
-
-/* SoC identification number information */
-#define U8500_BB_UID_BASE (U8500_BACKUPRAM1_BASE + 0xFC0)
-
-/* Offsets to specific addresses in some IP blocks for DMA */
-#define MSP_TX_RX_REG_OFFSET 0
-#define CRYP1_RX_REG_OFFSET 0x10
-#define CRYP1_TX_REG_OFFSET 0x8
-#define HASH1_TX_REG_OFFSET 0x4
-
-/*
- * Macros to get at IO space when running virtually
- * We dont map all the peripherals, let ioremap do
- * this for us. We map only very basic peripherals here.
- */
-#define U8500_IO_VIRTUAL 0xf0000000
-#define U8500_IO_PHYSICAL 0xa0000000
-/* This is where we map in the ROM to check ASIC IDs */
-#define UX500_VIRT_ROM IOMEM(0xf0000000)
-
-/* This macro is used in assembly, so no cast */
-#define IO_ADDRESS(x) \
- (((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + U8500_IO_VIRTUAL)
-
-/* typesafe io address */
-#define __io_address(n) IOMEM(IO_ADDRESS(n))
-
-/* Used by some plat-nomadik code */
-#define io_p2v(n) __io_address(n)
-
-#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
-
-#endif
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
index 415d8ad2a3c1..656b58bd296a 100644
--- a/arch/arm/mach-ux500/platsmp.c
+++ b/arch/arm/mach-ux500/platsmp.c
@@ -20,8 +20,6 @@
#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
-#include "db8500-regs.h"
-
/* Magic triggers in backup RAM */
#define UX500_CPU1_JUMPADDR_OFFSET 0x1FF4
#define UX500_CPU1_WAKEMAGIC_OFFSET 0x1FF0
diff --git a/arch/arm/mach-ux500/pm.c b/arch/arm/mach-ux500/pm.c
index ff9c375e4277..dc962d006b08 100644
--- a/arch/arm/mach-ux500/pm.c
+++ b/arch/arm/mach-ux500/pm.c
@@ -16,8 +16,6 @@
#include <linux/of.h>
#include <linux/of_address.h>
-#include "db8500-regs.h"
-
/* ARM WFI Standby signal register */
#define PRCM_ARM_WFI_STANDBY (prcmu_base + 0x130)
#define PRCM_ARM_WFI_STANDBY_WFI0 0x08
@@ -124,7 +122,7 @@ bool prcmu_pending_irq(void)
}
/*
- * This function checks if the specified cpu is in in WFI. It's usage
+ * This function checks if the specified cpu is in WFI. It's usage
* makes sense only if the gic is decoupled with the db8500_prcmu_gic_decouple
* function. Of course passing smp_processor_id() to this function will
* always return false...
diff --git a/arch/arm/mm/Makefile b/arch/arm/mm/Makefile
index 3510503bc5e6..71b858c9b10c 100644
--- a/arch/arm/mm/Makefile
+++ b/arch/arm/mm/Makefile
@@ -33,9 +33,6 @@ obj-$(CONFIG_CPU_ABRT_EV5TJ) += abort-ev5tj.o
obj-$(CONFIG_CPU_ABRT_EV6) += abort-ev6.o
obj-$(CONFIG_CPU_ABRT_EV7) += abort-ev7.o
-AFLAGS_abort-ev6.o :=-Wa,-march=armv6k
-AFLAGS_abort-ev7.o :=-Wa,-march=armv7-a
-
obj-$(CONFIG_CPU_PABRT_LEGACY) += pabort-legacy.o
obj-$(CONFIG_CPU_PABRT_V6) += pabort-v6.o
obj-$(CONFIG_CPU_PABRT_V7) += pabort-v7.o
@@ -49,10 +46,6 @@ obj-$(CONFIG_CPU_CACHE_FA) += cache-fa.o
obj-$(CONFIG_CPU_CACHE_NOP) += cache-nop.o
obj-$(CONFIG_CPU_CACHE_V7M) += cache-v7m.o
-AFLAGS_cache-v6.o :=-Wa,-march=armv6
-AFLAGS_cache-v7.o :=-Wa,-march=armv7-a
-AFLAGS_cache-v7m.o :=-Wa,-march=armv7-m
-
obj-$(CONFIG_CPU_COPY_V4WT) += copypage-v4wt.o
obj-$(CONFIG_CPU_COPY_V4WB) += copypage-v4wb.o
obj-$(CONFIG_CPU_COPY_FEROCEON) += copypage-feroceon.o
@@ -62,8 +55,6 @@ obj-$(CONFIG_CPU_XSCALE) += copypage-xscale.o
obj-$(CONFIG_CPU_XSC3) += copypage-xsc3.o
obj-$(CONFIG_CPU_COPY_FA) += copypage-fa.o
-CFLAGS_copypage-feroceon.o := -march=armv5te
-
obj-$(CONFIG_CPU_TLB_V4WT) += tlb-v4.o
obj-$(CONFIG_CPU_TLB_V4WB) += tlb-v4wb.o
obj-$(CONFIG_CPU_TLB_V4WBI) += tlb-v4wbi.o
@@ -72,9 +63,6 @@ obj-$(CONFIG_CPU_TLB_V6) += tlb-v6.o
obj-$(CONFIG_CPU_TLB_V7) += tlb-v7.o
obj-$(CONFIG_CPU_TLB_FA) += tlb-fa.o
-AFLAGS_tlb-v6.o :=-Wa,-march=armv6
-AFLAGS_tlb-v7.o :=-Wa,-march=armv7-a
-
obj-$(CONFIG_CPU_ARM7TDMI) += proc-arm7tdmi.o
obj-$(CONFIG_CPU_ARM720T) += proc-arm720.o
obj-$(CONFIG_CPU_ARM740T) += proc-arm740.o
@@ -101,9 +89,6 @@ obj-$(CONFIG_CPU_V6K) += proc-v6.o
obj-$(CONFIG_CPU_V7) += proc-v7.o proc-v7-bugs.o
obj-$(CONFIG_CPU_V7M) += proc-v7m.o
-AFLAGS_proc-v6.o :=-Wa,-march=armv6
-AFLAGS_proc-v7.o :=-Wa,-march=armv7-a
-
obj-$(CONFIG_OUTER_CACHE) += l2c-common.o
obj-$(CONFIG_CACHE_B15_RAC) += cache-b15-rac.o
obj-$(CONFIG_CACHE_FEROCEON_L2) += cache-feroceon-l2.o
diff --git a/arch/arm/mm/abort-ev6.S b/arch/arm/mm/abort-ev6.S
index c58bf8b43fea..836dc1299243 100644
--- a/arch/arm/mm/abort-ev6.S
+++ b/arch/arm/mm/abort-ev6.S
@@ -16,6 +16,7 @@
* abort here if the I-TLB and D-TLB aren't seeing the same
* picture. Unfortunately, this does happen. We live with it.
*/
+ .arch armv6k
.align 5
ENTRY(v6_early_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR
diff --git a/arch/arm/mm/abort-ev7.S b/arch/arm/mm/abort-ev7.S
index f81bceacc660..53fb41c24774 100644
--- a/arch/arm/mm/abort-ev7.S
+++ b/arch/arm/mm/abort-ev7.S
@@ -12,6 +12,7 @@
*
* Purpose : obtain information about current aborted instruction.
*/
+ .arch armv7-a
.align 5
ENTRY(v7_early_abort)
mrc p15, 0, r1, c5, c0, 0 @ get FSR
diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S
index f0f65eb073e4..250c83bf7158 100644
--- a/arch/arm/mm/cache-v6.S
+++ b/arch/arm/mm/cache-v6.S
@@ -19,6 +19,8 @@
#define D_CACHE_LINE_SIZE 32
#define BTB_FLUSH_SIZE 8
+.arch armv6
+
/*
* v6_flush_icache_all()
*
diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S
index 7c9499b728c4..127afe2096ba 100644
--- a/arch/arm/mm/cache-v7.S
+++ b/arch/arm/mm/cache-v7.S
@@ -16,6 +16,8 @@
#include "proc-macros.S"
+.arch armv7-a
+
#ifdef CONFIG_CPU_ICACHE_MISMATCH_WORKAROUND
.globl icache_size
.data
diff --git a/arch/arm/mm/cache-v7m.S b/arch/arm/mm/cache-v7m.S
index 1bc3a0a50753..eb60b5e5e2ad 100644
--- a/arch/arm/mm/cache-v7m.S
+++ b/arch/arm/mm/cache-v7m.S
@@ -18,6 +18,8 @@
#include "proc-macros.S"
+.arch armv7-m
+
/* Generic V7M read/write macros for memory mapped cache operations */
.macro v7m_cache_read, rt, reg
movw \rt, #:lower16:BASEADDR_V7M_SCB + \reg
diff --git a/arch/arm/mm/copypage-feroceon.c b/arch/arm/mm/copypage-feroceon.c
index 064b19e63571..5fc8ef1e665f 100644
--- a/arch/arm/mm/copypage-feroceon.c
+++ b/arch/arm/mm/copypage-feroceon.c
@@ -15,6 +15,7 @@ static void feroceon_copy_user_page(void *kto, const void *kfrom)
int tmp;
asm volatile ("\
+.arch armv5te \n\
1: ldmia %1!, {r2 - r7, ip, lr} \n\
pld [%1, #0] \n\
pld [%1, #32] \n\
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index d7909091cf97..c135f6e37a00 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -564,14 +564,6 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
if (mask < 0xffffffffULL)
gfp |= GFP_DMA;
- /*
- * Following is a work-around (a.k.a. hack) to prevent pages
- * with __GFP_COMP being passed to split_page() which cannot
- * handle them. The real problem is that this flag probably
- * should be 0 on ARM as it is not supported on this
- * platform; see CONFIG_HUGETLBFS.
- */
- gfp &= ~(__GFP_COMP);
args.gfp = gfp;
*handle = DMA_MAPPING_ERROR;
@@ -1093,15 +1085,6 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
return __iommu_alloc_simple(dev, size, gfp, handle,
coherent_flag, attrs);
- /*
- * Following is a work-around (a.k.a. hack) to prevent pages
- * with __GFP_COMP being passed to split_page() which cannot
- * handle them. The real problem is that this flag probably
- * should be 0 on ARM as it is not supported on this
- * platform; see CONFIG_HUGETLBFS.
- */
- gfp &= ~(__GFP_COMP);
-
pages = __iommu_alloc_buffer(dev, size, gfp, attrs, coherent_flag);
if (!pages)
return NULL;
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 46cccd6bf705..2418f1efabd8 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -105,14 +105,28 @@ static inline bool is_write_fault(unsigned int fsr)
return (fsr & FSR_WRITE) && !(fsr & FSR_CM);
}
+static inline bool is_translation_fault(unsigned int fsr)
+{
+ int fs = fsr_fs(fsr);
+#ifdef CONFIG_ARM_LPAE
+ if ((fs & FS_MMU_NOLL_MASK) == FS_TRANS_NOLL)
+ return true;
+#else
+ if (fs == FS_L1_TRANS || fs == FS_L2_TRANS)
+ return true;
+#endif
+ return false;
+}
+
static void die_kernel_fault(const char *msg, struct mm_struct *mm,
unsigned long addr, unsigned int fsr,
struct pt_regs *regs)
{
bust_spinlocks(1);
pr_alert("8<--- cut here ---\n");
- pr_alert("Unable to handle kernel %s at virtual address %08lx\n",
- msg, addr);
+ pr_alert("Unable to handle kernel %s at virtual address %08lx when %s\n",
+ msg, addr, fsr & FSR_LNX_PF ? "execute" :
+ fsr & FSR_WRITE ? "write" : "read");
show_pte(KERN_ALERT, mm, addr);
die("Oops", regs, fsr);
@@ -140,7 +154,8 @@ __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
if (addr < PAGE_SIZE) {
msg = "NULL pointer dereference";
} else {
- if (kfence_handle_page_fault(addr, is_write_fault(fsr), regs))
+ if (is_translation_fault(fsr) &&
+ kfence_handle_page_fault(addr, is_write_fault(fsr), regs))
return;
msg = "paging request";
@@ -208,7 +223,7 @@ static inline bool is_permission_fault(unsigned int fsr)
{
int fs = fsr_fs(fsr);
#ifdef CONFIG_ARM_LPAE
- if ((fs & FS_PERM_NOLL_MASK) == FS_PERM_NOLL)
+ if ((fs & FS_MMU_NOLL_MASK) == FS_PERM_NOLL)
return true;
#else
if (fs == FS_L1_PERM || fs == FS_L2_PERM)
diff --git a/arch/arm/mm/fault.h b/arch/arm/mm/fault.h
index 83b5ab32d7a4..54927ba1fa6e 100644
--- a/arch/arm/mm/fault.h
+++ b/arch/arm/mm/fault.h
@@ -14,8 +14,9 @@
#ifdef CONFIG_ARM_LPAE
#define FSR_FS_AEA 17
+#define FS_TRANS_NOLL 0x4
#define FS_PERM_NOLL 0xC
-#define FS_PERM_NOLL_MASK 0x3C
+#define FS_MMU_NOLL_MASK 0x3C
static inline int fsr_fs(unsigned int fsr)
{
@@ -23,8 +24,10 @@ static inline int fsr_fs(unsigned int fsr)
}
#else
#define FSR_FS_AEA 22
-#define FS_L1_PERM 0xD
-#define FS_L2_PERM 0xF
+#define FS_L1_TRANS 0x5
+#define FS_L2_TRANS 0x7
+#define FS_L1_PERM 0xD
+#define FS_L2_PERM 0xF
static inline int fsr_fs(unsigned int fsr)
{
diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S
index a0618f3e6836..203dff89ab1a 100644
--- a/arch/arm/mm/proc-v6.S
+++ b/arch/arm/mm/proc-v6.S
@@ -32,6 +32,8 @@
#define TTB_FLAGS_SMP TTB_RGN_WBWA|TTB_S
#define PMD_FLAGS_SMP PMD_SECT_WBWA|PMD_SECT_S
+.arch armv6
+
ENTRY(cpu_v6_proc_init)
ret lr
diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S
index 5db029c8f987..0a3083ad19c2 100644
--- a/arch/arm/mm/proc-v7-2level.S
+++ b/arch/arm/mm/proc-v7-2level.S
@@ -24,6 +24,8 @@
#define TTB_FLAGS_SMP TTB_IRGN_WBWA|TTB_S|TTB_NOS|TTB_RGN_OC_WBWA
#define PMD_FLAGS_SMP PMD_SECT_WBWA|PMD_SECT_S
+.arch armv7-a
+
/*
* cpu_v7_switch_mm(pgd_phys, tsk)
*
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 26d726a08a34..6b4ef9539b68 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -24,6 +24,8 @@
#include "proc-v7-2level.S"
#endif
+.arch armv7-a
+
ENTRY(cpu_v7_proc_init)
ret lr
ENDPROC(cpu_v7_proc_init)
diff --git a/arch/arm/mm/tlb-v6.S b/arch/arm/mm/tlb-v6.S
index 74f4b383afe3..1d91e49b2c2d 100644
--- a/arch/arm/mm/tlb-v6.S
+++ b/arch/arm/mm/tlb-v6.S
@@ -17,6 +17,8 @@
#define HARVARD_TLB
+.arch armv6
+
/*
* v6wbi_flush_user_tlb_range(start, end, vma)
*
diff --git a/arch/arm/mm/tlb-v7.S b/arch/arm/mm/tlb-v7.S
index 87bf4ab17721..35fd6d4f0d03 100644
--- a/arch/arm/mm/tlb-v7.S
+++ b/arch/arm/mm/tlb-v7.S
@@ -16,6 +16,8 @@
#include <asm/tlbflush.h>
#include "proc-macros.S"
+.arch armv7-a
+
/*
* v7wbi_flush_user_tlb_range(start, end, vma)
*
diff --git a/arch/arm/nwfpe/Makefile b/arch/arm/nwfpe/Makefile
index 303400fa2cdf..2aec85ab1e8b 100644
--- a/arch/arm/nwfpe/Makefile
+++ b/arch/arm/nwfpe/Makefile
@@ -11,3 +11,9 @@ nwfpe-y += fpa11.o fpa11_cpdo.o fpa11_cpdt.o \
entry.o
nwfpe-$(CONFIG_FPE_NWFPE_XP) += extended_cpdo.o
+
+# Try really hard to avoid generating calls to __aeabi_uldivmod() from
+# float64_rem() due to loop elision.
+ifdef CONFIG_CC_IS_CLANG
+CFLAGS_softfloat.o += -mllvm -replexitval=never
+endif
diff --git a/arch/arm/vdso/Makefile b/arch/arm/vdso/Makefile
index 8ca1c9f262a2..a7ec06ce3785 100644
--- a/arch/arm/vdso/Makefile
+++ b/arch/arm/vdso/Makefile
@@ -37,6 +37,7 @@ endif
# Disable gcov profiling for VDSO code
GCOV_PROFILE := n
+UBSAN_SANITIZE := n
# Prevents link failures: __sanitizer_cov_trace_pc() is not linked in.
KCOV_INSTRUMENT := n
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 2cb355c1b5b7..281110423871 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -774,6 +774,7 @@ static int __init vfp_init(void)
{
unsigned int vfpsid;
unsigned int cpu_arch = cpu_architecture();
+ unsigned int isar6;
/*
* Enable the access to the VFP on all online CPUs so the
@@ -831,7 +832,38 @@ static int __init vfp_init(void)
if ((fmrx(MVFR1) & 0xf0000000) == 0x10000000)
elf_hwcap |= HWCAP_VFPv4;
+ if (((fmrx(MVFR1) & MVFR1_ASIMDHP_MASK) >> MVFR1_ASIMDHP_BIT) == 0x2)
+ elf_hwcap |= HWCAP_ASIMDHP;
+ if (((fmrx(MVFR1) & MVFR1_FPHP_MASK) >> MVFR1_FPHP_BIT) == 0x3)
+ elf_hwcap |= HWCAP_FPHP;
}
+
+ /*
+ * Check for the presence of Advanced SIMD Dot Product
+ * instructions.
+ */
+ isar6 = read_cpuid_ext(CPUID_EXT_ISAR6);
+ if (cpuid_feature_extract_field(isar6, 4) == 0x1)
+ elf_hwcap |= HWCAP_ASIMDDP;
+ /*
+ * Check for the presence of Advanced SIMD Floating point
+ * half-precision multiplication instructions.
+ */
+ if (cpuid_feature_extract_field(isar6, 8) == 0x1)
+ elf_hwcap |= HWCAP_ASIMDFHM;
+ /*
+ * Check for the presence of Advanced SIMD Bfloat16
+ * floating point instructions.
+ */
+ if (cpuid_feature_extract_field(isar6, 20) == 0x1)
+ elf_hwcap |= HWCAP_ASIMDBF16;
+ /*
+ * Check for the presence of Advanced SIMD and floating point
+ * Int8 matrix multiplication instructions instructions.
+ */
+ if (cpuid_feature_extract_field(isar6, 24) == 0x1)
+ elf_hwcap |= HWCAP_I8MM;
+
/* Extract the architecture version on pre-cpuid scheme */
} else {
if (vfpsid & FPSID_NODOUBLE) {
diff --git a/arch/arm/xen/enlighten.c b/arch/arm/xen/enlighten.c
index 93c8ccbf2982..7d59765aef22 100644
--- a/arch/arm/xen/enlighten.c
+++ b/arch/arm/xen/enlighten.c
@@ -445,7 +445,7 @@ static int __init xen_guest_init(void)
return 0;
if (IS_ENABLED(CONFIG_XEN_VIRTIO))
- virtio_set_mem_acc_cb(xen_virtio_mem_acc);
+ virtio_set_mem_acc_cb(xen_virtio_restricted_mem_acc);
if (!acpi_disabled)
xen_acpi_guest_init();
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 505c8a1ccbe0..7fc3457a8891 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config ARM64
def_bool y
+ select ACPI_APMT if ACPI
select ACPI_CCA_REQUIRED if ACPI
select ACPI_GENERIC_GSI if ACPI
select ACPI_GTDT if ACPI
@@ -31,6 +32,7 @@ config ARM64
select ARCH_HAS_KCOV
select ARCH_HAS_KEEPINITRD
select ARCH_HAS_MEMBARRIER_SYNC_CORE
+ select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
select ARCH_HAS_PTE_DEVMAP
select ARCH_HAS_PTE_SPECIAL
@@ -117,6 +119,7 @@ config ARM64
select CPU_PM if (SUSPEND || CPU_IDLE)
select CRC32
select DCACHE_WORD_ACCESS
+ select DYNAMIC_FTRACE if FUNCTION_TRACER
select DMA_DIRECT_REMAP
select EDAC_SUPPORT
select FRAME_POINTER
@@ -181,8 +184,10 @@ config ARM64
select HAVE_DEBUG_KMEMLEAK
select HAVE_DMA_CONTIGUOUS
select HAVE_DYNAMIC_FTRACE
+ select HAVE_DYNAMIC_FTRACE_WITH_ARGS \
+ if $(cc-option,-fpatchable-function-entry=2)
select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY \
- if DYNAMIC_FTRACE_WITH_REGS
+ if DYNAMIC_FTRACE_WITH_ARGS
select HAVE_EFFICIENT_UNALIGNED_ACCESS
select HAVE_FAST_GUP
select HAVE_FTRACE_MCOUNT_RECORD
@@ -233,16 +238,16 @@ config ARM64
help
ARM 64-bit (AArch64) Linux support.
-config CLANG_SUPPORTS_DYNAMIC_FTRACE_WITH_REGS
+config CLANG_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS
def_bool CC_IS_CLANG
# https://github.com/ClangBuiltLinux/linux/issues/1507
depends on AS_IS_GNU || (AS_IS_LLVM && (LD_IS_LLD || LD_VERSION >= 23600))
- select HAVE_DYNAMIC_FTRACE_WITH_REGS
+ select HAVE_DYNAMIC_FTRACE_WITH_ARGS
-config GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_REGS
+config GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS
def_bool CC_IS_GCC
depends on $(cc-option,-fpatchable-function-entry=2)
- select HAVE_DYNAMIC_FTRACE_WITH_REGS
+ select HAVE_DYNAMIC_FTRACE_WITH_ARGS
config 64BIT
def_bool y
@@ -370,6 +375,9 @@ config KASAN_SHADOW_OFFSET
default 0xeffffff800000000 if ARM64_VA_BITS_36 && KASAN_SW_TAGS
default 0xffffffffffffffff
+config UNWIND_TABLES
+ bool
+
source "arch/arm64/Kconfig.platforms"
menu "Kernel Features"
@@ -964,6 +972,22 @@ config ARM64_ERRATUM_2457168
If unsure, say Y.
+config ARM64_ERRATUM_2645198
+ bool "Cortex-A715: 2645198: Workaround possible [ESR|FAR]_ELx corruption"
+ default y
+ help
+ This option adds the workaround for ARM Cortex-A715 erratum 2645198.
+
+ If a Cortex-A715 cpu sees a page mapping permissions change from executable
+ to non-executable, it may corrupt the ESR_ELx and FAR_ELx registers on the
+ next instruction abort caused by permission fault.
+
+ Only user-space does executable to non-executable permission transition via
+ mprotect() system call. Workaround the problem by doing a break-before-make
+ TLB invalidation, for all changes to executable user space mappings.
+
+ If unsure, say Y.
+
config CAVIUM_ERRATUM_22375
bool "Cavium erratum 22375, 24313"
default y
@@ -1714,7 +1738,6 @@ config ARM64_LSE_ATOMICS
config ARM64_USE_LSE_ATOMICS
bool "Atomic instructions"
- depends on JUMP_LABEL
default y
help
As part of the Large System Extensions, ARMv8.1 introduces new
@@ -1816,7 +1839,7 @@ config ARM64_PTR_AUTH_KERNEL
# which is only understood by binutils starting with version 2.33.1.
depends on LD_IS_LLD || LD_VERSION >= 23301 || (CC_IS_GCC && GCC_VERSION < 90100)
depends on !CC_IS_CLANG || AS_HAS_CFI_NEGATE_RA_STATE
- depends on (!FUNCTION_GRAPH_TRACER || DYNAMIC_FTRACE_WITH_REGS)
+ depends on (!FUNCTION_GRAPH_TRACER || DYNAMIC_FTRACE_WITH_ARGS)
help
If the compiler supports the -mbranch-protection or
-msign-return-address flag (e.g. GCC 7 or later), then this option
@@ -1826,7 +1849,7 @@ config ARM64_PTR_AUTH_KERNEL
disabled with minimal loss of protection.
This feature works with FUNCTION_GRAPH_TRACER option only if
- DYNAMIC_FTRACE_WITH_REGS is enabled.
+ DYNAMIC_FTRACE_WITH_ARGS is enabled.
config CC_HAS_BRANCH_PROT_PAC_RET
# GCC 9 or later, clang 8 or later
@@ -1924,7 +1947,7 @@ config ARM64_BTI_KERNEL
depends on !CC_IS_GCC
# https://github.com/llvm/llvm-project/commit/a88c722e687e6780dcd6a58718350dc76fcc4cc9
depends on !CC_IS_CLANG || CLANG_VERSION >= 120000
- depends on (!FUNCTION_GRAPH_TRACER || DYNAMIC_FTRACE_WITH_REGS)
+ depends on (!FUNCTION_GRAPH_TRACER || DYNAMIC_FTRACE_WITH_ARGS)
help
Build the kernel with Branch Target Identification annotations
and enable enforcement of this for kernel code. When this option
@@ -2157,6 +2180,15 @@ config ARCH_NR_GPIO
If unsure, leave the default value.
+config UNWIND_PATCH_PAC_INTO_SCS
+ bool "Enable shadow call stack dynamically using code patching"
+ # needs Clang with https://reviews.llvm.org/D111780 incorporated
+ depends on CC_IS_CLANG && CLANG_VERSION >= 150000
+ depends on ARM64_PTR_AUTH_KERNEL && CC_HAS_BRANCH_PROT_PAC_RET
+ depends on SHADOW_CALL_STACK
+ select UNWIND_TABLES
+ select DYNAMIC_SCS
+
endmenu # "Kernel Features"
menu "Boot options"
diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms
index 76580b932e44..d1970adf80ab 100644
--- a/arch/arm64/Kconfig.platforms
+++ b/arch/arm64/Kconfig.platforms
@@ -252,8 +252,6 @@ config ARCH_REALTEK
config ARCH_RENESAS
bool "Renesas SoC Platforms"
- select GPIOLIB
- select PINCTRL
help
This enables support for the ARMv8 based Renesas SoCs.
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 5e56d26a2239..d62bd221828f 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -45,8 +45,13 @@ KBUILD_CFLAGS += $(call cc-option,-mabi=lp64)
KBUILD_AFLAGS += $(call cc-option,-mabi=lp64)
# Avoid generating .eh_frame* sections.
+ifneq ($(CONFIG_UNWIND_TABLES),y)
KBUILD_CFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables
KBUILD_AFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables
+else
+KBUILD_CFLAGS += -fasynchronous-unwind-tables
+KBUILD_AFLAGS += -fasynchronous-unwind-tables
+endif
ifeq ($(CONFIG_STACKPROTECTOR_PER_TASK),y)
prepare: stack_protector_prepare
@@ -72,10 +77,16 @@ branch-prot-flags-$(CONFIG_CC_HAS_SIGN_RETURN_ADDRESS) := -msign-return-address=
# We enable additional protection for leaf functions as there is some
# narrow potential for ROP protection benefits and no substantial
# performance impact has been observed.
+PACRET-y := pac-ret+leaf
+
+# Using a shadow call stack in leaf functions is too costly, so avoid PAC there
+# as well when we may be patching PAC into SCS
+PACRET-$(CONFIG_UNWIND_PATCH_PAC_INTO_SCS) := pac-ret
+
ifeq ($(CONFIG_ARM64_BTI_KERNEL),y)
-branch-prot-flags-$(CONFIG_CC_HAS_BRANCH_PROT_PAC_RET_BTI) := -mbranch-protection=pac-ret+leaf+bti
+branch-prot-flags-$(CONFIG_CC_HAS_BRANCH_PROT_PAC_RET_BTI) := -mbranch-protection=$(PACRET-y)+bti
else
-branch-prot-flags-$(CONFIG_CC_HAS_BRANCH_PROT_PAC_RET) := -mbranch-protection=pac-ret+leaf
+branch-prot-flags-$(CONFIG_CC_HAS_BRANCH_PROT_PAC_RET) := -mbranch-protection=$(PACRET-y)
endif
# -march=armv8.3-a enables the non-nops instructions for PAC, to avoid the
# compiler to generate them and consequently to break the single image contract
@@ -128,7 +139,7 @@ endif
CHECKFLAGS += -D__aarch64__
-ifeq ($(CONFIG_DYNAMIC_FTRACE_WITH_REGS),y)
+ifeq ($(CONFIG_DYNAMIC_FTRACE_WITH_ARGS),y)
KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY
CC_FLAGS_FTRACE := -fpatchable-function-entry=2
endif
diff --git a/arch/arm64/boot/dts/allwinner/axp803.dtsi b/arch/arm64/boot/dts/allwinner/axp803.dtsi
index 578ef368e2b4..a6b4b87f185d 100644
--- a/arch/arm64/boot/dts/allwinner/axp803.dtsi
+++ b/arch/arm64/boot/dts/allwinner/axp803.dtsi
@@ -25,16 +25,6 @@
compatible = "x-powers,axp803-gpio", "x-powers,axp813-gpio";
gpio-controller;
#gpio-cells = <2>;
-
- gpio0_ldo: gpio0-ldo-pin {
- pins = "GPIO0";
- function = "ldo";
- };
-
- gpio1_ldo: gpio1-ldo-pin {
- pins = "GPIO1";
- function = "ldo";
- };
};
battery_power_supply: battery-power {
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts
index 620cb3ef5f6c..50ed2e9f10ed 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pinebook.dts
@@ -406,6 +406,20 @@
status = "okay";
};
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>;
+ uart-has-rtscts;
+ status = "okay";
+
+ bluetooth {
+ compatible = "realtek,rtl8723cs-bt";
+ device-wake-gpios = <&r_pio 0 5 GPIO_ACTIVE_LOW>; /* PL5 */
+ enable-gpios = <&r_pio 0 4 GPIO_ACTIVE_HIGH>; /* PL4 */
+ host-wake-gpios = <&r_pio 0 6 GPIO_ACTIVE_HIGH>; /* PL6 */
+ };
+};
+
&usb_otg {
dr_mode = "host";
};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
index 02893f3ac99d..cb8600d0ea1e 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-orangepi-zero2.dts
@@ -49,8 +49,24 @@
regulator-max-microvolt = <5000000>;
regulator-always-on;
};
+
+ reg_usb1_vbus: regulator-usb1-vbus {
+ compatible = "regulator-fixed";
+ regulator-name = "usb1-vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&reg_vcc5v>;
+ enable-active-high;
+ gpio = <&pio 2 16 GPIO_ACTIVE_HIGH>; /* PC16 */
+ };
};
+&ehci1 {
+ status = "okay";
+};
+
+/* USB 2 & 3 are on headers only. */
+
&emac0 {
pinctrl-names = "default";
pinctrl-0 = <&ext_rgmii_pins>;
@@ -76,6 +92,10 @@
status = "okay";
};
+&ohci1 {
+ status = "okay";
+};
+
&r_rsb {
status = "okay";
@@ -211,3 +231,24 @@
pinctrl-0 = <&uart0_ph_pins>;
status = "okay";
};
+
+&usbotg {
+ /*
+ * PHY0 pins are connected to a USB-C socket, but a role switch
+ * is not implemented: both CC pins are pulled to GND.
+ * The VBUS pins power the device, so a fixed peripheral mode
+ * is the best choice.
+ * The board can be powered via GPIOs, in this case port0 *can*
+ * act as a host (with a cable/adapter ignoring CC), as VBUS is
+ * then provided by the GPIOs. Any user of this setup would
+ * need to adjust the DT accordingly: dr_mode set to "host",
+ * enabling OHCI0 and EHCI0.
+ */
+ dr_mode = "peripheral";
+ status = "okay";
+};
+
+&usbphy {
+ usb1_vbus-supply = <&reg_usb1_vbus>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts b/arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts
index 6619db34714a..07424c28b696 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616-x96-mate.dts
@@ -32,6 +32,14 @@
};
};
+&ehci0 {
+ status = "okay";
+};
+
+&ehci2 {
+ status = "okay";
+};
+
&ir {
status = "okay";
};
@@ -54,6 +62,14 @@
status = "okay";
};
+&ohci0 {
+ status = "okay";
+};
+
+&ohci2 {
+ status = "okay";
+};
+
&r_rsb {
status = "okay";
@@ -175,3 +191,12 @@
pinctrl-0 = <&uart0_ph_pins>;
status = "okay";
};
+
+&usbotg {
+ dr_mode = "host"; /* USB A type receptable */
+ status = "okay";
+};
+
+&usbphy {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
index 622a1f7d1641..74aed0d232a9 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h616.dtsi
@@ -504,6 +504,166 @@
};
};
+ usbotg: usb@5100000 {
+ compatible = "allwinner,sun50i-h616-musb",
+ "allwinner,sun8i-h3-musb";
+ reg = <0x05100000 0x0400>;
+ clocks = <&ccu CLK_BUS_OTG>;
+ resets = <&ccu RST_BUS_OTG>;
+ interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "mc";
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ extcon = <&usbphy 0>;
+ status = "disabled";
+ };
+
+ usbphy: phy@5100400 {
+ compatible = "allwinner,sun50i-h616-usb-phy";
+ reg = <0x05100400 0x24>,
+ <0x05101800 0x14>,
+ <0x05200800 0x14>,
+ <0x05310800 0x14>,
+ <0x05311800 0x14>;
+ reg-names = "phy_ctrl",
+ "pmu0",
+ "pmu1",
+ "pmu2",
+ "pmu3";
+ clocks = <&ccu CLK_USB_PHY0>,
+ <&ccu CLK_USB_PHY1>,
+ <&ccu CLK_USB_PHY2>,
+ <&ccu CLK_USB_PHY3>,
+ <&ccu CLK_BUS_EHCI2>;
+ clock-names = "usb0_phy",
+ "usb1_phy",
+ "usb2_phy",
+ "usb3_phy",
+ "pmu2_clk";
+ resets = <&ccu RST_USB_PHY0>,
+ <&ccu RST_USB_PHY1>,
+ <&ccu RST_USB_PHY2>,
+ <&ccu RST_USB_PHY3>;
+ reset-names = "usb0_reset",
+ "usb1_reset",
+ "usb2_reset",
+ "usb3_reset";
+ status = "disabled";
+ #phy-cells = <1>;
+ };
+
+ ehci0: usb@5101000 {
+ compatible = "allwinner,sun50i-h616-ehci",
+ "generic-ehci";
+ reg = <0x05101000 0x100>;
+ interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI0>,
+ <&ccu CLK_BUS_EHCI0>,
+ <&ccu CLK_USB_OHCI0>;
+ resets = <&ccu RST_BUS_OHCI0>,
+ <&ccu RST_BUS_EHCI0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci0: usb@5101400 {
+ compatible = "allwinner,sun50i-h616-ohci",
+ "generic-ohci";
+ reg = <0x05101400 0x100>;
+ interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI0>,
+ <&ccu CLK_USB_OHCI0>;
+ resets = <&ccu RST_BUS_OHCI0>;
+ phys = <&usbphy 0>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ehci1: usb@5200000 {
+ compatible = "allwinner,sun50i-h616-ehci",
+ "generic-ehci";
+ reg = <0x05200000 0x100>;
+ interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI1>,
+ <&ccu CLK_BUS_EHCI1>,
+ <&ccu CLK_USB_OHCI1>;
+ resets = <&ccu RST_BUS_OHCI1>,
+ <&ccu RST_BUS_EHCI1>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci1: usb@5200400 {
+ compatible = "allwinner,sun50i-h616-ohci",
+ "generic-ohci";
+ reg = <0x05200400 0x100>;
+ interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI1>,
+ <&ccu CLK_USB_OHCI1>;
+ resets = <&ccu RST_BUS_OHCI1>;
+ phys = <&usbphy 1>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ehci2: usb@5310000 {
+ compatible = "allwinner,sun50i-h616-ehci",
+ "generic-ehci";
+ reg = <0x05310000 0x100>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI2>,
+ <&ccu CLK_BUS_EHCI2>,
+ <&ccu CLK_USB_OHCI2>;
+ resets = <&ccu RST_BUS_OHCI2>,
+ <&ccu RST_BUS_EHCI2>;
+ phys = <&usbphy 2>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci2: usb@5310400 {
+ compatible = "allwinner,sun50i-h616-ohci",
+ "generic-ohci";
+ reg = <0x05310400 0x100>;
+ interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI2>,
+ <&ccu CLK_USB_OHCI2>;
+ resets = <&ccu RST_BUS_OHCI2>;
+ phys = <&usbphy 2>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ehci3: usb@5311000 {
+ compatible = "allwinner,sun50i-h616-ehci",
+ "generic-ehci";
+ reg = <0x05311000 0x100>;
+ interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI3>,
+ <&ccu CLK_BUS_EHCI3>,
+ <&ccu CLK_USB_OHCI3>;
+ resets = <&ccu RST_BUS_OHCI3>,
+ <&ccu RST_BUS_EHCI3>;
+ phys = <&usbphy 3>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
+ ohci3: usb@5311400 {
+ compatible = "allwinner,sun50i-h616-ohci",
+ "generic-ohci";
+ reg = <0x05311400 0x100>;
+ interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&ccu CLK_BUS_OHCI3>,
+ <&ccu CLK_USB_OHCI3>;
+ resets = <&ccu RST_BUS_OHCI3>;
+ phys = <&usbphy 3>;
+ phy-names = "usb";
+ status = "disabled";
+ };
+
rtc: rtc@7000000 {
compatible = "allwinner,sun50i-h616-rtc";
reg = <0x07000000 0x400>;
diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
index 14c220d87807..55c5e1fdddc7 100644
--- a/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
+++ b/arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
@@ -309,6 +309,7 @@
<&clkmgr STRATIX10_SDMMC_CLK>;
clock-names = "biu", "ciu";
iommus = <&smmu 5>;
+ altr,sysmgr-syscon = <&sysmgr 0x28 4>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
index 48424e459f12..17752ca743e5 100644
--- a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
+++ b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
@@ -22,17 +22,17 @@
leds {
compatible = "gpio-leds";
- hps0 {
+ led-hps0 {
label = "hps_led0";
gpios = <&portb 20 GPIO_ACTIVE_HIGH>;
};
- hps1 {
+ led-hps1 {
label = "hps_led1";
gpios = <&portb 19 GPIO_ACTIVE_HIGH>;
};
- hps2 {
+ led-hps2 {
label = "hps_led2";
gpios = <&portb 21 GPIO_ACTIVE_HIGH>;
};
@@ -105,6 +105,7 @@
cap-mmc-highspeed;
broken-cd;
bus-width = <4>;
+ clk-phase-sd-hs = <0>, <135>;
};
&osc1 {
diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_nand.dts b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_nand.dts
index 847a7c01f5af..ede99dcc0558 100644
--- a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_nand.dts
+++ b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_nand.dts
@@ -22,17 +22,17 @@
leds {
compatible = "gpio-leds";
- hps0 {
+ led-hps0 {
label = "hps_led0";
gpios = <&portb 20 GPIO_ACTIVE_HIGH>;
};
- hps1 {
+ led-hps1 {
label = "hps_led1";
gpios = <&portb 19 GPIO_ACTIVE_HIGH>;
};
- hps2 {
+ led-hps2 {
label = "hps_led2";
gpios = <&portb 21 GPIO_ACTIVE_HIGH>;
};
diff --git a/arch/arm64/boot/dts/amlogic/Makefile b/arch/arm64/boot/dts/amlogic/Makefile
index e213aeebb774..97b42e2100e0 100644
--- a/arch/arm64/boot/dts/amlogic/Makefile
+++ b/arch/arm64/boot/dts/amlogic/Makefile
@@ -12,6 +12,7 @@ dtb-$(CONFIG_ARCH_MESON) += meson-g12b-a311d-khadas-vim3.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12b-gsking-x.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12b-gtking-pro.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12b-gtking.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-g12b-odroid-go-ultra.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12b-odroid-n2-plus.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12b-odroid-n2.dtb
dtb-$(CONFIG_ARCH_MESON) += meson-g12b-s922x-khadas-vim3.dtb
diff --git a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
index b4000cf65a9a..d2f7cb4e5375 100644
--- a/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-a1.dtsi
@@ -36,6 +36,7 @@
l2: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
index 04f797b5a012..1648e67afbb6 100644
--- a/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-axg.dtsi
@@ -105,6 +105,7 @@
l2: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
index 45947c1031c4..9dbd50820b1c 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-g12-common.dtsi
@@ -1705,6 +1705,12 @@
};
};
+ pmu: pmu@ff638000 {
+ reg = <0x0 0xff638000 0x0 0x100>,
+ <0x0 0xff638c00 0x0 0x100>;
+ interrupts = <GIC_SPI 52 IRQ_TYPE_EDGE_RISING>;
+ };
+
aobus: bus@ff800000 {
compatible = "simple-bus";
reg = <0x0 0xff800000 0x0 0x100000>;
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi
index fb0ab27d1f64..7677764eeee6 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-g12a.dtsi
@@ -50,6 +50,7 @@
l2: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
@@ -133,3 +134,7 @@
};
};
};
+
+&pmu {
+ compatible = "amlogic,g12a-ddr-pmu";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-go-ultra.dts b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-go-ultra.dts
new file mode 100644
index 000000000000..1e40709610c5
--- /dev/null
+++ b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-go-ultra.dts
@@ -0,0 +1,722 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2022 Neil Armstrong <neil.armstrong@linaro.org>
+ */
+
+/dts-v1/;
+
+#include "meson-g12b-s922x.dtsi"
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/gpio/meson-g12a-gpio.h>
+#include <dt-bindings/sound/meson-g12a-toacodec.h>
+#include <dt-bindings/sound/meson-g12a-tohdmitx.h>
+
+/ {
+ compatible = "hardkernel,odroid-go-ultra", "amlogic,s922x", "amlogic,g12b";
+ model = "Hardkernel ODROID-GO-Ultra";
+
+ aliases {
+ serial0 = &uart_AO;
+ rtc0 = &vrtc;
+ };
+
+ adc-joystick-left {
+ compatible = "adc-joystick";
+ io-channels = <&saradc 2>, <&saradc 3>;
+ poll-interval = <10>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ axis@0 {
+ reg = <0>;
+ linux,code = <ABS_Y>;
+ abs-range = <3150 950>;
+ abs-fuzz = <32>;
+ abs-flat = <64>;
+ };
+ axis@1 {
+ reg = <1>;
+ linux,code = <ABS_X>;
+ abs-range = <700 2900>;
+ abs-fuzz = <32>;
+ abs-flat = <64>;
+ };
+ };
+
+ adc-joystick-right {
+ compatible = "adc-joystick";
+ io-channels = <&saradc 0>, <&saradc 1>;
+ poll-interval = <10>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ axis@0 {
+ reg = <0>;
+ linux,code = <ABS_RY>;
+ abs-range = <3150 950>;
+ abs-fuzz = <32>;
+ abs-flat = <64>;
+ };
+ axis@1 {
+ reg = <1>;
+ linux,code = <ABS_RX>;
+ abs-range = <800 3000>;
+ abs-fuzz = <32>;
+ abs-flat = <64>;
+ };
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ codec_clk: codec-clk {
+ compatible = "fixed-clock";
+ clock-frequency = <12288000>;
+ clock-output-names = "codec_clk";
+ #clock-cells = <0>;
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys-polled";
+ poll-interval = <10>;
+ pinctrl-0 = <&keypad_gpio_pins>;
+ pinctrl-names = "default";
+
+ volume-up-button {
+ label = "VOLUME-UP";
+ linux,code = <KEY_VOLUMEUP>;
+ gpios = <&gpio GPIOX_8 GPIO_ACTIVE_LOW>;
+ };
+ volume-down-button {
+ label = "VOLUME-DOWN";
+ linux,code = <KEY_VOLUMEDOWN>;
+ gpios = <&gpio GPIOX_9 GPIO_ACTIVE_LOW>;
+ };
+ dpad-up-button {
+ label = "DPAD-UP";
+ linux,code = <BTN_DPAD_UP>;
+ gpios = <&gpio GPIOX_0 GPIO_ACTIVE_LOW>;
+ };
+ dpad-down-button {
+ label = "DPAD-DOWN";
+ linux,code = <BTN_DPAD_DOWN>;
+ gpios = <&gpio GPIOX_1 GPIO_ACTIVE_LOW>;
+ };
+ dpad-left-button {
+ label = "DPAD-LEFT";
+ linux,code = <BTN_DPAD_LEFT>;
+ gpios = <&gpio GPIOX_2 GPIO_ACTIVE_LOW>;
+ };
+ dpad-right-button {
+ label = "DPAD-RIGHT";
+ linux,code = <BTN_DPAD_RIGHT>;
+ gpios = <&gpio GPIOX_3 GPIO_ACTIVE_LOW>;
+ };
+ a-button {
+ label = "A";
+ linux,code = <BTN_EAST>;
+ gpios = <&gpio GPIOX_4 GPIO_ACTIVE_LOW>;
+ };
+ b-button {
+ label = "B";
+ linux,code = <BTN_SOUTH>;
+ gpios = <&gpio GPIOX_5 GPIO_ACTIVE_LOW>;
+ };
+ y-button {
+ label = "Y";
+ linux,code = <BTN_WEST>;
+ gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
+ };
+ x-button {
+ label = "X";
+ linux,code = <BTN_NORTH>;
+ gpios = <&gpio GPIOX_7 GPIO_ACTIVE_LOW>;
+ };
+ f1-button {
+ label = "F1";
+ linux,code = <BTN_TRIGGER_HAPPY1>;
+ gpios = <&gpio GPIOX_17 GPIO_ACTIVE_LOW>;
+ };
+ f2-button {
+ label = "F2";
+ linux,code = <BTN_TRIGGER_HAPPY2>;
+ gpios = <&gpio GPIOX_10 GPIO_ACTIVE_LOW>;
+ };
+ f3-button {
+ label = "F3";
+ linux,code = <BTN_TRIGGER_HAPPY3>;
+ gpios = <&gpio GPIOX_11 GPIO_ACTIVE_LOW>;
+ };
+ f4-button {
+ label = "F4";
+ linux,code = <BTN_TRIGGER_HAPPY4>;
+ gpios = <&gpio GPIOX_12 GPIO_ACTIVE_LOW>;
+ };
+ f5-button {
+ label = "F5";
+ linux,code = <BTN_TRIGGER_HAPPY5>;
+ gpios = <&gpio GPIOX_13 GPIO_ACTIVE_LOW>;
+ };
+ f6-button {
+ label = "F6";
+ linux,code = <BTN_TRIGGER_HAPPY6>;
+ gpios = <&gpio GPIOX_16 GPIO_ACTIVE_LOW>;
+ };
+ top-left-button {
+ label = "TOP Left";
+ linux,code = <BTN_TL>;
+ gpios = <&gpio GPIOX_14 GPIO_ACTIVE_LOW>;
+ };
+ top-left2-button {
+ label = "TOP Left 2";
+ linux,code = <BTN_TL2>;
+ gpios = <&gpio GPIOX_19 GPIO_ACTIVE_LOW>;
+ };
+ top-right-button {
+ label = "TOP Right";
+ linux,code = <BTN_TR>;
+ gpios = <&gpio GPIOX_15 GPIO_ACTIVE_LOW>;
+ };
+ top-right2-button {
+ label = "TOP Right 2";
+ linux,code = <BTN_TR2>;
+ gpios = <&gpio GPIOX_18 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x0 0x0 0x0 0x40000000>;
+ };
+
+ emmc_pwrseq: emmc-pwrseq {
+ compatible = "mmc-pwrseq-emmc";
+ reset-gpios = <&gpio BOOT_12 GPIO_ACTIVE_LOW>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-blue {
+ color = <LED_COLOR_ID_BLUE>;
+ gpios = <&gpio_ao GPIOAO_11 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ vdd_sys: regulator-vdd-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "VDD_SYS";
+ regulator-min-microvolt = <3800000>;
+ regulator-max-microvolt = <3800000>;
+ regulator-always-on;
+ };
+
+ sound {
+ compatible = "amlogic,axg-sound-card";
+ model = "Odroid GO Ultra";
+ audio-widgets = "Microphone", "Mic Jack",
+ "Headphone", "Headphones",
+ "Speaker", "Internal Speakers";
+ audio-aux-devs = <&tdmout_b>, <&tdmin_b>, <&speaker_amp>;
+ audio-routing = "TDMOUT_B IN 0", "FRDDR_A OUT 1",
+ "TDM_B Playback", "TDMOUT_B OUT",
+ "TDMIN_B IN 1", "TDM_B Capture",
+ "TDMIN_B IN 4", "TDM_B Loopback",
+ "TODDR_A IN 1", "TDMIN_B OUT",
+ "MICL", "Mic Jack",
+ "Headphones", "HPOL",
+ "Headphones", "HPOR",
+ "Speaker Amplifier INL", "HPOL",
+ "Speaker Amplifier INR", "HPOR",
+ "Internal Speakers", "Speaker Amplifier OUTL",
+ "Internal Speakers", "Speaker Amplifier OUTR";
+
+ assigned-clocks = <&clkc CLKID_MPLL2>,
+ <&clkc CLKID_MPLL0>,
+ <&clkc CLKID_MPLL1>;
+ assigned-clock-parents = <0>, <0>, <0>;
+ assigned-clock-rates = <294912000>,
+ <270950400>,
+ <393216000>;
+
+ dai-link-0 {
+ sound-dai = <&frddr_a>;
+ };
+
+ dai-link-1 {
+ sound-dai = <&toddr_a>;
+ };
+
+ dai-link-2 {
+ sound-dai = <&tdmif_b>;
+ dai-format = "i2s";
+ dai-tdm-slot-tx-mask-0 = <1 1>;
+ mclk-fs = <256>;
+
+ codec-0 {
+ sound-dai = <&rk817>;
+ };
+ };
+ };
+
+ speaker_amp: speaker-amplifier {
+ compatible = "simple-audio-amplifier";
+ sound-name-prefix = "Speaker Amplifier";
+ VCC-supply = <&hp_5v>;
+ };
+};
+
+&arb {
+ status = "okay";
+};
+
+&cpu0 {
+ cpu-supply = <&vddcpu_b>;
+ operating-points-v2 = <&cpu_opp_table_0>;
+ clocks = <&clkc CLKID_CPU_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu1 {
+ cpu-supply = <&vddcpu_b>;
+ operating-points-v2 = <&cpu_opp_table_0>;
+ clocks = <&clkc CLKID_CPU_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu100 {
+ cpu-supply = <&vddcpu_a>;
+ operating-points-v2 = <&cpub_opp_table_1>;
+ clocks = <&clkc CLKID_CPUB_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu101 {
+ cpu-supply = <&vddcpu_a>;
+ operating-points-v2 = <&cpub_opp_table_1>;
+ clocks = <&clkc CLKID_CPUB_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu102 {
+ cpu-supply = <&vddcpu_a>;
+ operating-points-v2 = <&cpub_opp_table_1>;
+ clocks = <&clkc CLKID_CPUB_CLK>;
+ clock-latency = <50000>;
+};
+
+&cpu103 {
+ cpu-supply = <&vddcpu_a>;
+ operating-points-v2 = <&cpub_opp_table_1>;
+ clocks = <&clkc CLKID_CPUB_CLK>;
+ clock-latency = <50000>;
+};
+
+/* RK817 only supports 12.5mV steps, round up the values */
+&cpu_opp_table_0 {
+ opp-1000000000 {
+ opp-microvolt = <737500>;
+ };
+ opp-1200000000 {
+ opp-microvolt = <737500>;
+ };
+ opp-1398000000 {
+ opp-microvolt = <762500>;
+ };
+ opp-1512000000 {
+ opp-microvolt = <800000>;
+ };
+ opp-1608000000 {
+ opp-microvolt = <837500>;
+ };
+ opp-1704000000 {
+ opp-microvolt = <862500>;
+ };
+ opp-1896000000 {
+ opp-microvolt = <987500>;
+ };
+ opp-1992000000 {
+ opp-microvolt = <1012500>;
+ };
+};
+
+/* RK818 only supports 12.5mV steps, round up the values */
+&cpub_opp_table_1 {
+ opp-1000000000 {
+ opp-microvolt = <775000>;
+ };
+ opp-1200000000 {
+ opp-microvolt = <775000>;
+ };
+ opp-1398000000 {
+ opp-microvolt = <800000>;
+ };
+ opp-1512000000 {
+ opp-microvolt = <825000>;
+ };
+ opp-1608000000 {
+ opp-microvolt = <862500>;
+ };
+ opp-1704000000 {
+ opp-microvolt = <900000>;
+ };
+ opp-1800000000 {
+ opp-microvolt = <987500>;
+ };
+ opp-1908000000 {
+ opp-microvolt = <1025000>;
+ };
+};
+
+&i2c_AO {
+ status = "okay";
+ pinctrl-0 = <&i2c_ao_sck_pins>, <&i2c_ao_sda_pins>;
+ pinctrl-names = "default";
+
+ rk818: pmic@1c {
+ compatible = "rockchip,rk818";
+ reg = <0x1c>;
+ interrupt-parent = <&gpio_intc>;
+ interrupts = <7 IRQ_TYPE_LEVEL_LOW>; /* GPIOAO_7 */
+
+ vcc1-supply = <&vdd_sys>;
+ vcc2-supply = <&vdd_sys>;
+ vcc3-supply = <&vdd_sys>;
+ vcc4-supply = <&vdd_sys>;
+ vcc6-supply = <&vdd_sys>;
+ vcc7-supply = <&vcc_2v3>;
+ vcc8-supply = <&vcc_2v3>;
+ vcc9-supply = <&vddao_3v3>;
+ boost-supply = <&vdd_sys>;
+ switch-supply = <&vdd_sys>;
+
+ regulators {
+ vddcpu_a: DCDC_REG1 {
+ regulator-name = "vddcpu_a";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <775000>;
+ regulator-max-microvolt = <1025000>;
+ regulator-ramp-delay = <6001>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <775000>;
+ };
+ };
+
+ vdd_ee: DCDC_REG2 {
+ regulator-name = "vdd_ee";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <875000>;
+ regulator-max-microvolt = <1250000>;
+ regulator-ramp-delay = <6001>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <875000>;
+ };
+ };
+
+ vddq_1v1: DCDC_REG3 {
+ regulator-name = "vddq_1v1";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vddao_3v3: DCDC_REG4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vddao_3v3";
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ hp_5v: DCDC_BOOST {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-name = "hp_5v";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vddio_ao1v8: LDO_REG5 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vddio_ao1v8";
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vddq_1v8: LDO_REG7 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-name = "vddq_1v8";
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vddio_c: LDO_REG9 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vddio_c";
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vcc_sd: SWITCH_REG {
+ regulator-name = "vcc_sd";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ OTG_SWITCH {
+ regulator-name = "otg_switch";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+};
+
+&i2c3 {
+ status = "okay";
+ pinctrl-0 = <&i2c3_sda_a_pins>, <&i2c3_sck_a_pins>;
+ pinctrl-names = "default";
+
+ rk817: pmic@20 {
+ compatible = "rockchip,rk817";
+ reg = <0x20>;
+ interrupt-parent = <&gpio_intc>;
+
+ interrupts = <5 IRQ_TYPE_LEVEL_LOW>; /* GPIOAO_5 */
+
+ vcc1-supply = <&vdd_sys>;
+ vcc2-supply = <&vdd_sys>;
+ vcc3-supply = <&vdd_sys>;
+ vcc4-supply = <&vdd_sys>;
+ vcc5-supply = <&vdd_sys>;
+ vcc6-supply = <&vdd_sys>;
+ vcc7-supply = <&vdd_sys>;
+ vcc8-supply = <&vdd_sys>;
+ vcc9-supply = <&rk817_boost>;
+
+ #sound-dai-cells = <0>;
+ clocks = <&codec_clk>;
+ clock-names = "mclk";
+
+ #clock-cells = <1>;
+
+ regulators {
+ vddcpu_b: DCDC_REG2 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <737500>;
+ regulator-max-microvolt = <1012500>;
+ regulator-ramp-delay = <6001>;
+ regulator-initial-mode = <0x2>;
+ regulator-name = "vddcpu_b";
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1000000>;
+ };
+ };
+
+ vcc_2v3: DCDC_REG3 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <2300000>;
+ regulator-max-microvolt = <2400000>;
+ regulator-initial-mode = <0x2>;
+ regulator-name = "vcc_2v3";
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ LDO_REG4 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vdd_codec";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_lcd: LDO_REG8 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "vcc_lcd";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ rk817_boost: BOOST {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5400000>;
+ regulator-name = "rk817_boost";
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ usb_host: OTG_SWITCH {
+ regulator-name = "usb_host";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+};
+
+&clkc_audio {
+ status = "okay";
+};
+
+&eth_phy {
+ status = "disabled";
+};
+
+&frddr_a {
+ status = "okay";
+};
+
+&periphs_pinctrl {
+ keypad_gpio_pins: keypad-gpio {
+ mux {
+ groups = "GPIOX_0", "GPIOX_1", "GPIOX_2", "GPIOX_3",
+ "GPIOX_4", "GPIOX_5", "GPIOX_6", "GPIOX_7",
+ "GPIOX_8", "GPIOX_9", "GPIOX_10", "GPIOX_11",
+ "GPIOX_12", "GPIOX_13", "GPIOX_14", "GPIOX_15",
+ "GPIOX_16", "GPIOX_17", "GPIOX_18", "GPIOX_19";
+ function = "gpio_periphs";
+ bias-pull-up;
+ output-disable;
+ };
+ };
+};
+
+&saradc {
+ status = "okay";
+ vref-supply = <&vddio_ao1v8>;
+};
+
+/* SD card */
+&sd_emmc_b {
+ status = "okay";
+ pinctrl-0 = <&sdcard_c_pins>;
+ pinctrl-1 = <&sdcard_clk_gate_c_pins>;
+ pinctrl-names = "default", "clk-gate";
+
+ bus-width = <4>;
+ cap-sd-highspeed;
+ max-frequency = <50000000>;
+ disable-wp;
+
+ cd-gpios = <&gpio GPIOC_6 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&vcc_sd>;
+ vqmmc-supply = <&vddio_c>;
+
+};
+
+/* eMMC */
+&sd_emmc_c {
+ status = "okay";
+ pinctrl-0 = <&emmc_ctrl_pins>, <&emmc_data_8b_pins>, <&emmc_ds_pins>;
+ pinctrl-1 = <&emmc_clk_gate_pins>;
+ pinctrl-names = "default", "clk-gate";
+
+ bus-width = <8>;
+ cap-mmc-highspeed;
+ mmc-ddr-1_8v;
+ mmc-hs200-1_8v;
+ max-frequency = <200000000>;
+ disable-wp;
+
+ mmc-pwrseq = <&emmc_pwrseq>;
+ vmmc-supply = <&vcc_sd>;
+ vqmmc-supply = <&vddio_ao1v8>;
+};
+
+
+&tdmif_b {
+ pinctrl-0 = <&tdm_b_dout0_pins>, <&tdm_b_fs_pins>, <&tdm_b_sclk_pins>, <&tdm_b_din1_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ assigned-clocks = <&clkc_audio AUD_CLKID_TDM_SCLK_PAD1>,
+ <&clkc_audio AUD_CLKID_TDM_LRCLK_PAD1>;
+ assigned-clock-parents = <&clkc_audio AUD_CLKID_MST_B_SCLK>,
+ <&clkc_audio AUD_CLKID_MST_B_LRCLK>;
+ assigned-clock-rates = <0>, <0>;
+};
+
+&tdmin_b {
+ status = "okay";
+};
+
+&tdmout_b {
+ status = "okay";
+};
+
+&toddr_a {
+ status = "okay";
+};
+
+&uart_AO {
+ status = "okay";
+ pinctrl-0 = <&uart_ao_a_pins>;
+ pinctrl-names = "default";
+};
+
+&usb {
+ status = "okay";
+ dr_mode = "peripheral";
+};
+
+&usb2_phy0 {
+ status = "okay";
+};
+
+&usb2_phy1 {
+ status = "okay";
+ phy-supply = <&usb_host>;
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi
index fd3fa82e4c33..667d2b774924 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-g12b-odroid-n2.dtsi
@@ -39,6 +39,14 @@
reset-gpios = <&gpio BOOT_12 GPIO_ACTIVE_LOW>;
};
+ fan: gpio-fan {
+ compatible = "gpio-fan";
+ gpios = <&gpio_ao GPIOAO_10 GPIO_ACTIVE_HIGH>;
+ /* Using Dummy Speed */
+ gpio-fan,speed-map = <0 0>, <1 1>;
+ #cooling-cells = <2>;
+ };
+
leds {
compatible = "gpio-leds";
@@ -410,6 +418,40 @@
clock-latency = <50000>;
};
+&cpu_thermal {
+ trips {
+ cpu_active: cpu-active {
+ temperature = <60000>; /* millicelsius */
+ hysteresis = <2000>; /* millicelsius */
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map {
+ trip = <&cpu_active>;
+ cooling-device = <&fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+};
+
+&ddr_thermal {
+ trips {
+ ddr_active: ddr-active {
+ temperature = <60000>; /* millicelsius */
+ hysteresis = <2000>; /* millicelsius */
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map {
+ trip = <&ddr_active>;
+ cooling-device = <&fan THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+};
+
&ext_mdio {
external_phy: ethernet-phy@0 {
/* Realtek RTL8211F (0x001cc916) */
diff --git a/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi b/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi
index ee8fcae9f9f0..75ff00fb2e4c 100644
--- a/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-g12b.dtsi
@@ -105,6 +105,7 @@
l2: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
};
@@ -139,3 +140,7 @@
&mali {
dma-coherent;
};
+
+&pmu {
+ compatible = "amlogic,g12b-ddr-pmu";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
index 023a52005494..e3c12e0be99d 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi
@@ -132,6 +132,7 @@
l2: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
index 7c029f552a23..923d2d8bbb9c 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
@@ -427,6 +427,20 @@
};
};
+ spi_idle_high_pins: spi-idle-high-pins {
+ mux {
+ groups = "spi_sclk";
+ bias-pull-up;
+ };
+ };
+
+ spi_idle_low_pins: spi-idle-low-pins {
+ mux {
+ groups = "spi_sclk";
+ bias-pull-down;
+ };
+ };
+
spi_ss0_pins: spi-ss0 {
mux {
groups = "spi_ss0";
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
index 6ab1cc125b96..202deb4e2d63 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
@@ -140,7 +140,6 @@
compatible = "haoyu,hym8563";
reg = <0x51>;
#clock-cells = <0>;
- clock-frequency = <32768>;
clock-output-names = "xin32k";
};
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
index c3ac531c4f84..04e9d0f1bde0 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
@@ -429,6 +429,20 @@
};
};
+ spi_idle_high_pins: spi-idle-high-pins {
+ mux {
+ groups = "spi_sclk";
+ bias-pull-up;
+ };
+ };
+
+ spi_idle_low_pins: spi-idle-low-pins {
+ mux {
+ groups = "spi_sclk";
+ bias-pull-down;
+ };
+ };
+
spi_ss0_pins: spi-ss0 {
mux {
groups = "spi_ss0";
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
index f43c45daf7eb..b21172ece1fa 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxm-khadas-vim2.dts
@@ -270,7 +270,6 @@
compatible = "haoyu,hym8563";
reg = <0x51>;
#clock-cells = <0>;
- clock-frequency = <32768>;
clock-output-names = "xin32k";
};
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxm-minix-neo-u9h.dts b/arch/arm64/boot/dts/amlogic/meson-gxm-minix-neo-u9h.dts
index b8ef3bd8b840..1703da3235ea 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxm-minix-neo-u9h.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxm-minix-neo-u9h.dts
@@ -89,7 +89,6 @@
compatible = "haoyu,hym8563";
reg = <0x51>;
#clock-cells = <0>;
- clock-frequency = <32768>;
clock-output-names = "xin32k";
wakeup-source;
};
diff --git a/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi b/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi
index 80737731af3f..56ca0ba2241e 100644
--- a/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi
+++ b/arch/arm64/boot/dts/amlogic/meson-sm1.dtsi
@@ -88,6 +88,7 @@
l2: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
@@ -520,6 +521,10 @@
power-domains = <&pwrc PWRC_SM1_PCIE_ID>;
};
+&pmu {
+ compatible = "amlogic,sm1-ddr-pmu";
+};
+
&pwrc {
compatible = "amlogic,meson-sm1-pwrc";
};
diff --git a/arch/arm64/boot/dts/apple/Makefile b/arch/arm64/boot/dts/apple/Makefile
index c0510c25ca6a..5a7506ff5ea3 100644
--- a/arch/arm64/boot/dts/apple/Makefile
+++ b/arch/arm64/boot/dts/apple/Makefile
@@ -4,3 +4,9 @@ dtb-$(CONFIG_ARCH_APPLE) += t8103-j293.dtb
dtb-$(CONFIG_ARCH_APPLE) += t8103-j313.dtb
dtb-$(CONFIG_ARCH_APPLE) += t8103-j456.dtb
dtb-$(CONFIG_ARCH_APPLE) += t8103-j457.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t6000-j314s.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t6001-j314c.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t6000-j316s.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t6001-j316c.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t6001-j375c.dtb
+dtb-$(CONFIG_ARCH_APPLE) += t6002-j375d.dtb
diff --git a/arch/arm64/boot/dts/apple/multi-die-cpp.h b/arch/arm64/boot/dts/apple/multi-die-cpp.h
new file mode 100644
index 000000000000..39e8953bf809
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/multi-die-cpp.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR MIT
+ *
+ * C preprocessor macros for t600x multi die support.
+ */
+
+#ifndef __DTS_APPLE_MULTI_DIE_CPP_H
+#define __DTS_APPLE_MULTI_DIE_CPP_H
+
+#ifndef __stringify
+#define __stringify_1(x...) #x
+#define __stringify(x...) __stringify_1(x)
+#endif
+
+#ifndef __concat
+#define __concat_1(x, y...) x ## y
+#define __concat(x, y...) __concat_1(x, y)
+#endif
+
+#define DIE_NODE(a) __concat(a, DIE)
+#define DIE_LABEL(a) __stringify(__concat(a, DIE))
+
+#endif /* !__DTS_APPLE_MULTI_DIE_CPP_H */
diff --git a/arch/arm64/boot/dts/apple/t6000-j314s.dts b/arch/arm64/boot/dts/apple/t6000-j314s.dts
new file mode 100644
index 000000000000..c9e192848fe3
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t6000-j314s.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * MacBook Pro (14-inch, M1 Pro, 2021)
+ *
+ * target-type: J314s
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+/dts-v1/;
+
+#include "t6000.dtsi"
+#include "t600x-j314-j316.dtsi"
+
+/ {
+ compatible = "apple,j314s", "apple,t6000", "apple,arm-platform";
+ model = "Apple MacBook Pro (14-inch, M1 Pro, 2021)";
+};
diff --git a/arch/arm64/boot/dts/apple/t6000-j316s.dts b/arch/arm64/boot/dts/apple/t6000-j316s.dts
new file mode 100644
index 000000000000..ff1803ce2300
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t6000-j316s.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * MacBook Pro (16-inch, M1 Pro, 2021)
+ *
+ * target-type: J316s
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+/dts-v1/;
+
+#include "t6000.dtsi"
+#include "t600x-j314-j316.dtsi"
+
+/ {
+ compatible = "apple,j316s", "apple,t6000", "apple,arm-platform";
+ model = "Apple MacBook Pro (16-inch, M1 Pro, 2021)";
+};
diff --git a/arch/arm64/boot/dts/apple/t6000.dtsi b/arch/arm64/boot/dts/apple/t6000.dtsi
new file mode 100644
index 000000000000..89c3b211b116
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t6000.dtsi
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple T6000 "M1 Pro" SoC
+ *
+ * Other names: H13J, "Jade Chop"
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+/* This chip is just a cut down version of t6001, so include it and disable the missing parts */
+
+#include "t6001.dtsi"
+
+/ {
+ compatible = "apple,t6000", "apple,arm-platform";
+};
+
+/delete-node/ &pmgr_south;
diff --git a/arch/arm64/boot/dts/apple/t6001-j314c.dts b/arch/arm64/boot/dts/apple/t6001-j314c.dts
new file mode 100644
index 000000000000..1761d15b98c1
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t6001-j314c.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * MacBook Pro (14-inch, M1 Max, 2021)
+ *
+ * target-type: J314c
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+/dts-v1/;
+
+#include "t6001.dtsi"
+#include "t600x-j314-j316.dtsi"
+
+/ {
+ compatible = "apple,j314c", "apple,t6001", "apple,arm-platform";
+ model = "Apple MacBook Pro (14-inch, M1 Max, 2021)";
+};
diff --git a/arch/arm64/boot/dts/apple/t6001-j316c.dts b/arch/arm64/boot/dts/apple/t6001-j316c.dts
new file mode 100644
index 000000000000..750e9beeffc0
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t6001-j316c.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * MacBook Pro (16-inch, M1 Max, 2021)
+ *
+ * target-type: J316c
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+/dts-v1/;
+
+#include "t6001.dtsi"
+#include "t600x-j314-j316.dtsi"
+
+/ {
+ compatible = "apple,j316c", "apple,t6001", "apple,arm-platform";
+ model = "Apple MacBook Pro (16-inch, M1 Max, 2021)";
+};
diff --git a/arch/arm64/boot/dts/apple/t6001-j375c.dts b/arch/arm64/boot/dts/apple/t6001-j375c.dts
new file mode 100644
index 000000000000..62ea437b58b2
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t6001-j375c.dts
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Mac Studio (M1 Max, 2022)
+ *
+ * target-type: J375c
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+/dts-v1/;
+
+#include "t6001.dtsi"
+#include "t600x-j375.dtsi"
+
+/ {
+ compatible = "apple,j375c", "apple,t6001", "apple,arm-platform";
+ model = "Apple Mac Studio (M1 Max, 2022)";
+};
diff --git a/arch/arm64/boot/dts/apple/t6001.dtsi b/arch/arm64/boot/dts/apple/t6001.dtsi
new file mode 100644
index 000000000000..620b17e4031f
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t6001.dtsi
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple T6001 "M1 Max" SoC
+ *
+ * Other names: H13J, "Jade"
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/apple-aic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/apple.h>
+
+#include "multi-die-cpp.h"
+
+#include "t600x-common.dtsi"
+
+/ {
+ compatible = "apple,t6001", "apple,arm-platform";
+
+ soc {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ ranges;
+ nonposted-mmio;
+
+ // filled via templated includes at the end of the file
+ };
+};
+
+#define DIE
+#define DIE_NO 0
+
+&{/soc} {
+ #include "t600x-die0.dtsi"
+ #include "t600x-dieX.dtsi"
+ #include "t600x-nvme.dtsi"
+};
+
+#include "t600x-gpio-pins.dtsi"
+#include "t600x-pmgr.dtsi"
+
+#undef DIE
+#undef DIE_NO
+
+
+&aic {
+ affinities {
+ e-core-pmu-affinity {
+ apple,fiq-index = <AIC_CPU_PMU_E>;
+ cpus = <&cpu_e00 &cpu_e01>;
+ };
+
+ p-core-pmu-affinity {
+ apple,fiq-index = <AIC_CPU_PMU_P>;
+ cpus = <&cpu_p00 &cpu_p01 &cpu_p02 &cpu_p03
+ &cpu_p10 &cpu_p11 &cpu_p12 &cpu_p13>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t6002-j375d.dts b/arch/arm64/boot/dts/apple/t6002-j375d.dts
new file mode 100644
index 000000000000..3365429bdc8b
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t6002-j375d.dts
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Mac Studio (M1 Ultra, 2022)
+ *
+ * target-type: J375d
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+/dts-v1/;
+
+#include "t6002.dtsi"
+#include "t600x-j375.dtsi"
+
+/ {
+ compatible = "apple,j375d", "apple,t6002", "apple,arm-platform";
+ model = "Apple Mac Studio (M1 Ultra, 2022)";
+};
+
+/* USB Type C */
+&i2c0 {
+ /* front-right */
+ hpm4: usb-pd@39 {
+ compatible = "apple,cd321x";
+ reg = <0x39>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+
+ /* front-left */
+ hpm5: usb-pd@3a {
+ compatible = "apple,cd321x";
+ reg = <0x3a>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+};
+
+/* delete unused always-on power-domains on die 1 */
+
+/delete-node/ &ps_atc2_usb_aon_die1;
+/delete-node/ &ps_atc2_usb_die1;
+
+/delete-node/ &ps_atc3_usb_aon_die1;
+/delete-node/ &ps_atc3_usb_die1;
+
+/delete-node/ &ps_disp0_cpu0_die1;
+/delete-node/ &ps_disp0_fe_die1;
diff --git a/arch/arm64/boot/dts/apple/t6002.dtsi b/arch/arm64/boot/dts/apple/t6002.dtsi
new file mode 100644
index 000000000000..a963a5011799
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t6002.dtsi
@@ -0,0 +1,301 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Apple T6002 "M1 Ultra" SoC
+ *
+ * Other names: H13J, "Jade 2C"
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/apple-aic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/apple.h>
+
+#include "multi-die-cpp.h"
+
+#include "t600x-common.dtsi"
+
+/ {
+ compatible = "apple,t6002", "apple,arm-platform";
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ cpu-map {
+ cluster3 {
+ core0 {
+ cpu = <&cpu_e10>;
+ };
+ core1 {
+ cpu = <&cpu_e11>;
+ };
+ };
+
+ cluster4 {
+ core0 {
+ cpu = <&cpu_p20>;
+ };
+ core1 {
+ cpu = <&cpu_p21>;
+ };
+ core2 {
+ cpu = <&cpu_p22>;
+ };
+ core3 {
+ cpu = <&cpu_p23>;
+ };
+ };
+
+ cluster5 {
+ core0 {
+ cpu = <&cpu_p30>;
+ };
+ core1 {
+ cpu = <&cpu_p31>;
+ };
+ core2 {
+ cpu = <&cpu_p32>;
+ };
+ core3 {
+ cpu = <&cpu_p33>;
+ };
+ };
+ };
+
+ cpu_e10: cpu@800 {
+ compatible = "apple,icestorm";
+ device_type = "cpu";
+ reg = <0x0 0x800>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_3>;
+ i-cache-size = <0x20000>;
+ d-cache-size = <0x10000>;
+ operating-points-v2 = <&icestorm_opp>;
+ capacity-dmips-mhz = <714>;
+ performance-domains = <&cpufreq_e_die1>;
+ };
+
+ cpu_e11: cpu@801 {
+ compatible = "apple,icestorm";
+ device_type = "cpu";
+ reg = <0x0 0x801>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_3>;
+ i-cache-size = <0x20000>;
+ d-cache-size = <0x10000>;
+ operating-points-v2 = <&icestorm_opp>;
+ capacity-dmips-mhz = <714>;
+ performance-domains = <&cpufreq_e_die1>;
+ };
+
+ cpu_p20: cpu@10900 {
+ compatible = "apple,firestorm";
+ device_type = "cpu";
+ reg = <0x0 0x10900>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_4>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p0_die1>;
+ };
+
+ cpu_p21: cpu@10901 {
+ compatible = "apple,firestorm";
+ device_type = "cpu";
+ reg = <0x0 0x10901>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_4>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p0_die1>;
+ };
+
+ cpu_p22: cpu@10902 {
+ compatible = "apple,firestorm";
+ device_type = "cpu";
+ reg = <0x0 0x10902>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_4>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p0_die1>;
+ };
+
+ cpu_p23: cpu@10903 {
+ compatible = "apple,firestorm";
+ device_type = "cpu";
+ reg = <0x0 0x10903>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_4>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p0_die1>;
+ };
+
+ cpu_p30: cpu@10a00 {
+ compatible = "apple,firestorm";
+ device_type = "cpu";
+ reg = <0x0 0x10a00>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_5>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p1_die1>;
+ };
+
+ cpu_p31: cpu@10a01 {
+ compatible = "apple,firestorm";
+ device_type = "cpu";
+ reg = <0x0 0x10a01>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_5>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p1_die1>;
+ };
+
+ cpu_p32: cpu@10a02 {
+ compatible = "apple,firestorm";
+ device_type = "cpu";
+ reg = <0x0 0x10a02>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_5>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p1_die1>;
+ };
+
+ cpu_p33: cpu@10a03 {
+ compatible = "apple,firestorm";
+ device_type = "cpu";
+ reg = <0x0 0x10a03>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_5>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p1_die1>;
+ };
+
+ l2_cache_3: l2-cache-3 {
+ compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
+ cache-size = <0x400000>;
+ };
+
+ l2_cache_4: l2-cache-4 {
+ compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
+ cache-size = <0xc00000>;
+ };
+
+ l2_cache_5: l2-cache-5 {
+ compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
+ cache-size = <0xc00000>;
+ };
+ };
+
+ die0: soc@200000000 {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x2 0x0 0x2 0x0 0x4 0x0>,
+ <0x5 0x80000000 0x5 0x80000000 0x1 0x80000000>,
+ <0x7 0x0 0x7 0x0 0xf 0x80000000>;
+ nonposted-mmio;
+
+ // filled via templated includes at the end of the file
+ };
+
+ die1: soc@2200000000 {
+ compatible = "simple-bus";
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x2 0x0 0x22 0x0 0x4 0x0>,
+ <0x7 0x0 0x27 0x0 0xf 0x80000000>;
+ nonposted-mmio;
+
+ // filled via templated includes at the end of the file
+ };
+};
+
+#define DIE
+#define DIE_NO 0
+
+&die0 {
+ #include "t600x-die0.dtsi"
+ #include "t600x-dieX.dtsi"
+};
+
+#include "t600x-pmgr.dtsi"
+#include "t600x-gpio-pins.dtsi"
+
+#undef DIE
+#undef DIE_NO
+
+#define DIE _die1
+#define DIE_NO 1
+
+&die1 {
+ #include "t600x-dieX.dtsi"
+ #include "t600x-nvme.dtsi"
+};
+
+#include "t600x-pmgr.dtsi"
+
+#undef DIE
+#undef DIE_NO
+
+&aic {
+ affinities {
+ e-core-pmu-affinity {
+ apple,fiq-index = <AIC_CPU_PMU_E>;
+ cpus = <&cpu_e00 &cpu_e01
+ &cpu_e10 &cpu_e11>;
+ };
+
+ p-core-pmu-affinity {
+ apple,fiq-index = <AIC_CPU_PMU_P>;
+ cpus = <&cpu_p00 &cpu_p01 &cpu_p02 &cpu_p03
+ &cpu_p10 &cpu_p11 &cpu_p12 &cpu_p13
+ &cpu_p20 &cpu_p21 &cpu_p22 &cpu_p23
+ &cpu_p30 &cpu_p31 &cpu_p32 &cpu_p33>;
+ };
+ };
+};
+
+&ps_gfx {
+ // On t6002, the die0 GPU power domain needs both AFR power domains
+ power-domains = <&ps_afr>, <&ps_afr_die1>;
+};
diff --git a/arch/arm64/boot/dts/apple/t600x-common.dtsi b/arch/arm64/boot/dts/apple/t600x-common.dtsi
new file mode 100644
index 000000000000..fa8ead699363
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t600x-common.dtsi
@@ -0,0 +1,374 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Common Apple T6000 / T6001 / T6002 "M1 Pro/Max/Ultra" SoC
+ *
+ * Other names: H13J, "Jade Chop", "Jade", "Jade 2C"
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu_e00>;
+ };
+ core1 {
+ cpu = <&cpu_e01>;
+ };
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&cpu_p00>;
+ };
+ core1 {
+ cpu = <&cpu_p01>;
+ };
+ core2 {
+ cpu = <&cpu_p02>;
+ };
+ core3 {
+ cpu = <&cpu_p03>;
+ };
+ };
+
+ cluster2 {
+ core0 {
+ cpu = <&cpu_p10>;
+ };
+ core1 {
+ cpu = <&cpu_p11>;
+ };
+ core2 {
+ cpu = <&cpu_p12>;
+ };
+ core3 {
+ cpu = <&cpu_p13>;
+ };
+ };
+ };
+
+ cpu_e00: cpu@0 {
+ compatible = "apple,icestorm";
+ device_type = "cpu";
+ reg = <0x0 0x0>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_0>;
+ i-cache-size = <0x20000>;
+ d-cache-size = <0x10000>;
+ operating-points-v2 = <&icestorm_opp>;
+ capacity-dmips-mhz = <714>;
+ performance-domains = <&cpufreq_e>;
+ };
+
+ cpu_e01: cpu@1 {
+ compatible = "apple,icestorm";
+ device_type = "cpu";
+ reg = <0x0 0x1>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_0>;
+ i-cache-size = <0x20000>;
+ d-cache-size = <0x10000>;
+ operating-points-v2 = <&icestorm_opp>;
+ capacity-dmips-mhz = <714>;
+ performance-domains = <&cpufreq_e>;
+ };
+
+ cpu_p00: cpu@10100 {
+ compatible = "apple,firestorm";
+ device_type = "cpu";
+ reg = <0x0 0x10100>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_1>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p0>;
+ };
+
+ cpu_p01: cpu@10101 {
+ compatible = "apple,firestorm";
+ device_type = "cpu";
+ reg = <0x0 0x10101>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_1>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p0>;
+ };
+
+ cpu_p02: cpu@10102 {
+ compatible = "apple,firestorm";
+ device_type = "cpu";
+ reg = <0x0 0x10102>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_1>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p0>;
+ };
+
+ cpu_p03: cpu@10103 {
+ compatible = "apple,firestorm";
+ device_type = "cpu";
+ reg = <0x0 0x10103>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_1>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p0>;
+ };
+
+ cpu_p10: cpu@10200 {
+ compatible = "apple,firestorm";
+ device_type = "cpu";
+ reg = <0x0 0x10200>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_2>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p1>;
+ };
+
+ cpu_p11: cpu@10201 {
+ compatible = "apple,firestorm";
+ device_type = "cpu";
+ reg = <0x0 0x10201>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_2>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p1>;
+ };
+
+ cpu_p12: cpu@10202 {
+ compatible = "apple,firestorm";
+ device_type = "cpu";
+ reg = <0x0 0x10202>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_2>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p1>;
+ };
+
+ cpu_p13: cpu@10203 {
+ compatible = "apple,firestorm";
+ device_type = "cpu";
+ reg = <0x0 0x10203>;
+ enable-method = "spin-table";
+ cpu-release-addr = <0 0>; /* To be filled by loader */
+ next-level-cache = <&l2_cache_2>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
+ operating-points-v2 = <&firestorm_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p1>;
+ };
+
+ l2_cache_0: l2-cache-0 {
+ compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
+ cache-size = <0x400000>;
+ };
+
+ l2_cache_1: l2-cache-1 {
+ compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
+ cache-size = <0xc00000>;
+ };
+
+ l2_cache_2: l2-cache-2 {
+ compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
+ cache-size = <0xc00000>;
+ };
+ };
+
+ icestorm_opp: opp-table-0 {
+ compatible = "operating-points-v2";
+
+ opp01 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-level = <1>;
+ clock-latency-ns = <7500>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <972000000>;
+ opp-level = <2>;
+ clock-latency-ns = <23000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <1332000000>;
+ opp-level = <3>;
+ clock-latency-ns = <29000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1704000000>;
+ opp-level = <4>;
+ clock-latency-ns = <40000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <2064000000>;
+ opp-level = <5>;
+ clock-latency-ns = <50000>;
+ };
+ };
+
+ firestorm_opp: opp-table-1 {
+ compatible = "operating-points-v2";
+
+ opp01 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-level = <1>;
+ clock-latency-ns = <8000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <828000000>;
+ opp-level = <2>;
+ clock-latency-ns = <18000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <1056000000>;
+ opp-level = <3>;
+ clock-latency-ns = <19000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1296000000>;
+ opp-level = <4>;
+ clock-latency-ns = <23000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <1524000000>;
+ opp-level = <5>;
+ clock-latency-ns = <24000>;
+ };
+ opp06 {
+ opp-hz = /bits/ 64 <1752000000>;
+ opp-level = <6>;
+ clock-latency-ns = <28000>;
+ };
+ opp07 {
+ opp-hz = /bits/ 64 <1980000000>;
+ opp-level = <7>;
+ clock-latency-ns = <31000>;
+ };
+ opp08 {
+ opp-hz = /bits/ 64 <2208000000>;
+ opp-level = <8>;
+ clock-latency-ns = <45000>;
+ };
+ opp09 {
+ opp-hz = /bits/ 64 <2448000000>;
+ opp-level = <9>;
+ clock-latency-ns = <49000>;
+ };
+ opp10 {
+ opp-hz = /bits/ 64 <2676000000>;
+ opp-level = <10>;
+ clock-latency-ns = <53000>;
+ };
+ opp11 {
+ opp-hz = /bits/ 64 <2904000000>;
+ opp-level = <11>;
+ clock-latency-ns = <56000>;
+ };
+ opp12 {
+ opp-hz = /bits/ 64 <3036000000>;
+ opp-level = <12>;
+ clock-latency-ns = <56000>;
+ };
+ /* Not available until CPU deep sleep is implemented
+ opp13 {
+ opp-hz = /bits/ 64 <3132000000>;
+ opp-level = <13>;
+ clock-latency-ns = <56000>;
+ turbo-mode;
+ };
+ opp14 {
+ opp-hz = /bits/ 64 <3168000000>;
+ opp-level = <14>;
+ clock-latency-ns = <56000>;
+ turbo-mode;
+ };
+ opp15 {
+ opp-hz = /bits/ 64 <3228000000>;
+ opp-level = <15>;
+ clock-latency-ns = <56000>;
+ turbo-mode;
+ };
+ */
+ };
+
+ pmu-e {
+ compatible = "apple,icestorm-pmu";
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_FIQ 0 AIC_CPU_PMU_E IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ pmu-p {
+ compatible = "apple,firestorm-pmu";
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_FIQ 0 AIC_CPU_PMU_P IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupt-parent = <&aic>;
+ interrupt-names = "phys", "virt", "hyp-phys", "hyp-virt";
+ interrupts = <AIC_FIQ 0 AIC_TMR_GUEST_PHYS IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_FIQ 0 AIC_TMR_GUEST_VIRT IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_FIQ 0 AIC_TMR_HV_PHYS IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_FIQ 0 AIC_TMR_HV_VIRT IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ clkref: clock-ref {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24000000>;
+ clock-output-names = "clkref";
+ };
+
+ /*
+ * This is a fabulated representation of the input clock
+ * to NCO since we don't know the true clock tree.
+ */
+ nco_clkref: clock-ref-nco {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-output-names = "nco_ref";
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t600x-die0.dtsi b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
new file mode 100644
index 000000000000..1c41954e3899
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t600x-die0.dtsi
@@ -0,0 +1,361 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Devices used on die 0 on the Apple T6002 "M1 Ultra" SoC and present on
+ * Apple T6000 / T6001 "M1 Pro" / "M1 Max".
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+
+ nco: clock-controller@28e03c000 {
+ compatible = "apple,t6000-nco", "apple,nco";
+ reg = <0x2 0x8e03c000 0x0 0x14000>;
+ clocks = <&nco_clkref>;
+ #clock-cells = <1>;
+ };
+
+ aic: interrupt-controller@28e100000 {
+ compatible = "apple,t6000-aic", "apple,aic2";
+ #interrupt-cells = <4>;
+ interrupt-controller;
+ reg = <0x2 0x8e100000 0x0 0xc000>,
+ <0x2 0x8e10c000 0x0 0x4>;
+ reg-names = "core", "event";
+ power-domains = <&ps_aic>;
+ };
+
+ pinctrl_smc: pinctrl@290820000 {
+ compatible = "apple,t6000-pinctrl", "apple,pinctrl";
+ reg = <0x2 0x90820000 0x0 0x4000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pinctrl_smc 0 0 30>;
+ apple,npins = <30>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 743 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 0 744 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 0 745 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 0 746 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 0 747 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 0 748 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 0 749 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ wdt: watchdog@2922b0000 {
+ compatible = "apple,t6000-wdt", "apple,wdt";
+ reg = <0x2 0x922b0000 0x0 0x4000>;
+ clocks = <&clkref>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 631 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ sio_dart_0: iommu@39b004000 {
+ compatible = "apple,t6000-dart";
+ reg = <0x3 0x9b004000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1130 IRQ_TYPE_LEVEL_HIGH>;
+ #iommu-cells = <1>;
+ power-domains = <&ps_sio_cpu>;
+ };
+
+ sio_dart_1: iommu@39b008000 {
+ compatible = "apple,t6000-dart";
+ reg = <0x3 0x9b008000 0x0 0x8000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1130 IRQ_TYPE_LEVEL_HIGH>;
+ #iommu-cells = <1>;
+ power-domains = <&ps_sio_cpu>;
+ };
+
+ i2c0: i2c@39b040000 {
+ compatible = "apple,t6000-i2c", "apple,i2c";
+ reg = <0x3 0x9b040000 0x0 0x4000>;
+ clocks = <&clkref>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1119 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-0 = <&i2c0_pins>;
+ pinctrl-names = "default";
+ power-domains = <&ps_i2c0>;
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+ };
+
+ i2c1: i2c@39b044000 {
+ compatible = "apple,t6000-i2c", "apple,i2c";
+ reg = <0x3 0x9b044000 0x0 0x4000>;
+ clocks = <&clkref>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1120 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-0 = <&i2c1_pins>;
+ pinctrl-names = "default";
+ power-domains = <&ps_i2c1>;
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@39b048000 {
+ compatible = "apple,t6000-i2c", "apple,i2c";
+ reg = <0x3 0x9b048000 0x0 0x4000>;
+ clocks = <&clkref>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1121 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-0 = <&i2c2_pins>;
+ pinctrl-names = "default";
+ power-domains = <&ps_i2c2>;
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@39b04c000 {
+ compatible = "apple,t6000-i2c", "apple,i2c";
+ reg = <0x3 0x9b04c000 0x0 0x4000>;
+ clocks = <&clkref>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1122 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-0 = <&i2c3_pins>;
+ pinctrl-names = "default";
+ power-domains = <&ps_i2c3>;
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+ status = "disabled";
+ };
+
+ i2c4: i2c@39b050000 {
+ compatible = "apple,t6000-i2c", "apple,i2c";
+ reg = <0x3 0x9b050000 0x0 0x4000>;
+ clocks = <&clkref>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1123 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-0 = <&i2c4_pins>;
+ pinctrl-names = "default";
+ power-domains = <&ps_i2c4>;
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+ status = "disabled";
+ };
+
+ i2c5: i2c@39b054000 {
+ compatible = "apple,t6000-i2c", "apple,i2c";
+ reg = <0x3 0x9b054000 0x0 0x4000>;
+ clocks = <&clkref>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1124 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-0 = <&i2c5_pins>;
+ pinctrl-names = "default";
+ power-domains = <&ps_i2c5>;
+ #address-cells = <0x1>;
+ #size-cells = <0x0>;
+ status = "disabled";
+ };
+
+ serial0: serial@39b200000 {
+ compatible = "apple,s5l-uart";
+ reg = <0x3 0x9b200000 0x0 0x1000>;
+ reg-io-width = <4>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1097 IRQ_TYPE_LEVEL_HIGH>;
+ /*
+ * TODO: figure out the clocking properly, there may
+ * be a third selectable clock.
+ */
+ clocks = <&clkref>, <&clkref>;
+ clock-names = "uart", "clk_uart_baud0";
+ power-domains = <&ps_uart0>;
+ status = "disabled";
+ };
+
+ admac: dma-controller@39b400000 {
+ compatible = "apple,t6000-admac", "apple,admac";
+ reg = <0x3 0x9b400000 0x0 0x34000>;
+ #dma-cells = <1>;
+ dma-channels = <16>;
+ interrupts-extended = <0>,
+ <&aic AIC_IRQ 0 1118 IRQ_TYPE_LEVEL_HIGH>,
+ <0>,
+ <0>;
+ iommus = <&sio_dart_0 2>, <&sio_dart_1 2>;
+ power-domains = <&ps_sio_adma>;
+ resets = <&ps_audio_p>;
+ };
+
+ mca: mca@39b600000 {
+ compatible = "apple,t6000-mca", "apple,mca";
+ reg = <0x3 0x9b600000 0x0 0x10000>,
+ <0x3 0x9b500000 0x0 0x20000>;
+ clocks = <&nco 0>, <&nco 1>, <&nco 2>, <&nco 3>;
+ dmas = <&admac 0>, <&admac 1>, <&admac 2>, <&admac 3>,
+ <&admac 4>, <&admac 5>, <&admac 6>, <&admac 7>,
+ <&admac 8>, <&admac 9>, <&admac 10>, <&admac 11>,
+ <&admac 12>, <&admac 13>, <&admac 14>, <&admac 15>;
+ dma-names = "tx0a", "rx0a", "tx0b", "rx0b",
+ "tx1a", "rx1a", "tx1b", "rx1b",
+ "tx2a", "rx2a", "tx2b", "rx2b",
+ "tx3a", "rx3a", "tx3b", "rx3b";
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1112 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 0 1113 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 0 1114 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 0 1115 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&ps_audio_p>, <&ps_mca0>, <&ps_mca1>,
+ <&ps_mca2>, <&ps_mca3>;
+ resets = <&ps_audio_p>;
+ #sound-dai-cells = <1>;
+ };
+
+ pcie0_dart_0: iommu@581008000 {
+ compatible = "apple,t6000-dart";
+ reg = <0x5 0x81008000 0x0 0x4000>;
+ #iommu-cells = <1>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1271 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&ps_apcie_gp_sys>;
+ };
+
+ pcie0_dart_1: iommu@582008000 {
+ compatible = "apple,t6000-dart";
+ reg = <0x5 0x82008000 0x0 0x4000>;
+ #iommu-cells = <1>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1274 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&ps_apcie_gp_sys>;
+ };
+
+ pcie0_dart_2: iommu@583008000 {
+ compatible = "apple,t6000-dart";
+ reg = <0x5 0x83008000 0x0 0x4000>;
+ #iommu-cells = <1>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1277 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&ps_apcie_gp_sys>;
+ };
+
+ pcie0_dart_3: iommu@584008000 {
+ compatible = "apple,t6000-dart";
+ reg = <0x5 0x84008000 0x0 0x4000>;
+ #iommu-cells = <1>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1280 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&ps_apcie_gp_sys>;
+ };
+
+ pcie0: pcie@590000000 {
+ compatible = "apple,t6000-pcie", "apple,pcie";
+ device_type = "pci";
+
+ reg = <0x5 0x90000000 0x0 0x1000000>,
+ <0x5 0x80000000 0x0 0x100000>,
+ <0x5 0x81000000 0x0 0x4000>,
+ <0x5 0x82000000 0x0 0x4000>,
+ <0x5 0x83000000 0x0 0x4000>,
+ <0x5 0x84000000 0x0 0x4000>;
+ reg-names = "config", "rc", "port0", "port1", "port2", "port3";
+
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 0 1270 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 0 1273 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 0 1276 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 0 1279 IRQ_TYPE_LEVEL_HIGH>;
+
+ msi-controller;
+ msi-parent = <&pcie0>;
+ msi-ranges = <&aic AIC_IRQ 0 1581 IRQ_TYPE_EDGE_RISING 32>;
+
+
+ iommu-map = <0x100 &pcie0_dart_0 1 1>,
+ <0x200 &pcie0_dart_1 1 1>,
+ <0x300 &pcie0_dart_2 1 1>,
+ <0x400 &pcie0_dart_3 1 1>;
+ iommu-map-mask = <0xff00>;
+
+ bus-range = <0 4>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges = <0x43000000 0x5 0xa0000000 0x5 0xa0000000 0x0 0x20000000>,
+ <0x02000000 0x0 0xc0000000 0x5 0xc0000000 0x0 0x40000000>;
+
+ power-domains = <&ps_apcie_gp_sys>;
+ pinctrl-0 = <&pcie_pins>;
+ pinctrl-names = "default";
+
+ port00: pci@0,0 {
+ device_type = "pci";
+ reg = <0x0 0x0 0x0 0x0 0x0>;
+ reset-gpios = <&pinctrl_ap 4 GPIO_ACTIVE_LOW>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &port00 0 0 0 0>,
+ <0 0 0 2 &port00 0 0 0 1>,
+ <0 0 0 3 &port00 0 0 0 2>,
+ <0 0 0 4 &port00 0 0 0 3>;
+ };
+
+ port01: pci@1,0 {
+ device_type = "pci";
+ reg = <0x800 0x0 0x0 0x0 0x0>;
+ reset-gpios = <&pinctrl_ap 5 GPIO_ACTIVE_LOW>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &port01 0 0 0 0>,
+ <0 0 0 2 &port01 0 0 0 1>,
+ <0 0 0 3 &port01 0 0 0 2>,
+ <0 0 0 4 &port01 0 0 0 3>;
+ };
+
+ port02: pci@2,0 {
+ device_type = "pci";
+ reg = <0x1000 0x0 0x0 0x0 0x0>;
+ reset-gpios = <&pinctrl_ap 6 GPIO_ACTIVE_LOW>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &port02 0 0 0 0>,
+ <0 0 0 2 &port02 0 0 0 1>,
+ <0 0 0 3 &port02 0 0 0 2>,
+ <0 0 0 4 &port02 0 0 0 3>;
+ };
+
+ port03: pci@3,0 {
+ device_type = "pci";
+ reg = <0x1800 0x0 0x0 0x0 0x0>;
+ reset-gpios = <&pinctrl_ap 7 GPIO_ACTIVE_LOW>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &port03 0 0 0 0>,
+ <0 0 0 2 &port03 0 0 0 1>,
+ <0 0 0 3 &port03 0 0 0 2>,
+ <0 0 0 4 &port03 0 0 0 3>;
+ };
+ };
diff --git a/arch/arm64/boot/dts/apple/t600x-dieX.dtsi b/arch/arm64/boot/dts/apple/t600x-dieX.dtsi
new file mode 100644
index 000000000000..a32ff0c9d7b0
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t600x-dieX.dtsi
@@ -0,0 +1,121 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Devices used on both dies on the Apple T6002 "M1 Ultra" and present on
+ * Apple T6000/T6001 "M1 Pro/Max".
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+ DIE_NODE(cpufreq_e): cpufreq@210e20000 {
+ compatible = "apple,t6000-cluster-cpufreq", "apple,t8103-cluster-cpufreq", "apple,cluster-cpufreq";
+ reg = <0x2 0x10e20000 0 0x1000>;
+ #performance-domain-cells = <0>;
+ };
+
+ DIE_NODE(cpufreq_p0): cpufreq@211e20000 {
+ compatible = "apple,t6000-cluster-cpufreq", "apple,t8103-cluster-cpufreq", "apple,cluster-cpufreq";
+ reg = <0x2 0x11e20000 0 0x1000>;
+ #performance-domain-cells = <0>;
+ };
+
+ DIE_NODE(cpufreq_p1): cpufreq@212e20000 {
+ compatible = "apple,t6000-cluster-cpufreq", "apple,t8103-cluster-cpufreq", "apple,cluster-cpufreq";
+ reg = <0x2 0x12e20000 0 0x1000>;
+ #performance-domain-cells = <0>;
+ };
+
+ DIE_NODE(pmgr): power-management@28e080000 {
+ compatible = "apple,t6000-pmgr", "apple,pmgr", "syscon", "simple-mfd";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x2 0x8e080000 0 0x4000>;
+ };
+
+ DIE_NODE(pmgr_east): power-management@28e580000 {
+ compatible = "apple,t6000-pmgr", "apple,pmgr", "syscon", "simple-mfd";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x2 0x8e580000 0 0xc000>;
+ };
+
+ DIE_NODE(pmgr_south): power-management@28e680000 {
+ compatible = "apple,t6000-pmgr", "apple,pmgr", "syscon", "simple-mfd";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x2 0x8e680000 0 0xc000>;
+ };
+
+ DIE_NODE(pinctrl_nub): pinctrl@2921f0000 {
+ compatible = "apple,t6000-pinctrl", "apple,pinctrl";
+ reg = <0x2 0x921f0000 0x0 0x4000>;
+ power-domains = <&DIE_NODE(ps_nub_gpio)>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&DIE_NODE(pinctrl_nub) 0 0 16>;
+ apple,npins = <16>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ DIE_NO 623 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 624 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 625 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 626 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 627 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 628 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 629 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ DIE_NODE(pmgr_mini): power-management@292280000 {
+ compatible = "apple,t6000-pmgr", "apple,pmgr", "syscon", "simple-mfd";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0x2 0x92280000 0 0x4000>;
+ };
+
+ DIE_NODE(pinctrl_aop): pinctrl@293820000 {
+ compatible = "apple,t6000-pinctrl", "apple,pinctrl";
+ reg = <0x2 0x93820000 0x0 0x4000>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&DIE_NODE(pinctrl_aop) 0 0 63>;
+ apple,npins = <63>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ DIE_NO 567 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 568 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 569 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 570 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 571 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 572 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 573 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ DIE_NODE(pinctrl_ap): pinctrl@39b028000 {
+ compatible = "apple,t6000-pinctrl", "apple,pinctrl";
+ reg = <0x3 0x9b028000 0x0 0x4000>;
+
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ DIE_NO 427 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 428 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 429 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 430 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 431 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 432 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 433 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&clkref>;
+ power-domains = <&DIE_NODE(ps_gpio)>;
+
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&DIE_NODE(pinctrl_ap) 0 0 255>;
+ apple,npins = <255>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
diff --git a/arch/arm64/boot/dts/apple/t600x-gpio-pins.dtsi b/arch/arm64/boot/dts/apple/t600x-gpio-pins.dtsi
new file mode 100644
index 000000000000..b31f1a7a2b3f
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t600x-gpio-pins.dtsi
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * GPIO pin mappings for Apple T600x SoCs.
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+&pinctrl_ap {
+ i2c0_pins: i2c0-pins {
+ pinmux = <APPLE_PINMUX(92, 1)>,
+ <APPLE_PINMUX(93, 1)>;
+ };
+
+ i2c1_pins: i2c1-pins {
+ pinmux = <APPLE_PINMUX(94, 1)>,
+ <APPLE_PINMUX(95, 1)>;
+ };
+
+ i2c2_pins: i2c2-pins {
+ pinmux = <APPLE_PINMUX(96, 1)>,
+ <APPLE_PINMUX(97, 1)>;
+ };
+
+ i2c3_pins: i2c3-pins {
+ pinmux = <APPLE_PINMUX(98, 1)>,
+ <APPLE_PINMUX(99, 1)>;
+ };
+
+ i2c4_pins: i2c4-pins {
+ pinmux = <APPLE_PINMUX(8, 1)>,
+ <APPLE_PINMUX(9, 1)>;
+ };
+
+ i2c5_pins: i2c5-pins {
+ pinmux = <APPLE_PINMUX(100, 1)>,
+ <APPLE_PINMUX(101, 1)>;
+ };
+
+ pcie_pins: pcie-pins {
+ pinmux = <APPLE_PINMUX(0, 1)>,
+ <APPLE_PINMUX(1, 1)>,
+ <APPLE_PINMUX(2, 1)>,
+ <APPLE_PINMUX(3, 1)>;
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
new file mode 100644
index 000000000000..34906d522f0a
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t600x-j314-j316.dtsi
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * MacBook Pro (14/16-inch, 2021)
+ *
+ * This file contains the parts common to J314 and J316 devices with both t6000 and t6001.
+ *
+ * target-type: J314s / J314c / J316s / J316c
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+/ {
+ aliases {
+ serial0 = &serial0;
+ wifi0 = &wifi0;
+ };
+
+ chosen {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ stdout-path = "serial0";
+
+ framebuffer0: framebuffer@0 {
+ compatible = "apple,simple-framebuffer", "simple-framebuffer";
+ reg = <0 0 0 0>; /* To be filled by loader */
+ /* Format properties will be added by loader */
+ status = "disabled";
+ };
+ };
+
+ memory@10000000000 {
+ device_type = "memory";
+ reg = <0x100 0 0x2 0>; /* To be filled by loader */
+ };
+};
+
+&serial0 {
+ status = "okay";
+};
+
+/* USB Type C */
+&i2c0 {
+ hpm0: usb-pd@38 {
+ compatible = "apple,cd321x";
+ reg = <0x38>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+
+ hpm1: usb-pd@3f {
+ compatible = "apple,cd321x";
+ reg = <0x3f>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+
+ hpm2: usb-pd@3b {
+ compatible = "apple,cd321x";
+ reg = <0x3b>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+
+ /* MagSafe port */
+ hpm5: usb-pd@3a {
+ compatible = "apple,cd321x";
+ reg = <0x3a>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+};
+
+&nco_clkref {
+ clock-frequency = <1068000000>;
+};
+
+/* PCIe devices */
+&port00 {
+ /* WLAN */
+ bus-range = <1 1>;
+ wifi0: wifi@0,0 {
+ reg = <0x10000 0x0 0x0 0x0 0x0>;
+ /* To be filled by the loader */
+ local-mac-address = [00 10 18 00 00 10];
+ };
+};
+
+&port01 {
+ /* SD card reader */
+ bus-range = <2 2>;
+ sdhci0: mmc@0,0 {
+ compatible = "pci17a0,9755";
+ reg = <0x20000 0x0 0x0 0x0 0x0>;
+ cd-inverted;
+ wp-inverted;
+ };
+};
+
+&pcie0_dart_2 {
+ status = "disabled";
+};
+
+&pcie0_dart_3 {
+ status = "disabled";
+};
+
+/delete-node/ &port02;
+/delete-node/ &port03;
diff --git a/arch/arm64/boot/dts/apple/t600x-j375.dtsi b/arch/arm64/boot/dts/apple/t600x-j375.dtsi
new file mode 100644
index 000000000000..00d3a9447c89
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t600x-j375.dtsi
@@ -0,0 +1,117 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * Mac Studio (2022)
+ *
+ * This file contains the parts common to J375 devices with both t6001 and t6002.
+ *
+ * target-type: J375c / J375d
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+/ {
+ aliases {
+ serial0 = &serial0;
+ wifi0 = &wifi0;
+ };
+
+ chosen {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ stdout-path = "serial0";
+
+ framebuffer0: framebuffer@0 {
+ compatible = "apple,simple-framebuffer", "simple-framebuffer";
+ reg = <0 0 0 0>; /* To be filled by loader */
+ /* Format properties will be added by loader */
+ status = "disabled";
+ };
+ };
+
+ memory@10000000000 {
+ device_type = "memory";
+ reg = <0x100 0 0x2 0>; /* To be filled by loader */
+ };
+};
+
+&serial0 {
+ status = "okay";
+};
+
+/* USB Type C */
+&i2c0 {
+ hpm0: usb-pd@38 {
+ compatible = "apple,cd321x";
+ reg = <0x38>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+
+ hpm1: usb-pd@3f {
+ compatible = "apple,cd321x";
+ reg = <0x3f>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+
+ hpm2: usb-pd@3b {
+ compatible = "apple,cd321x";
+ reg = <0x3b>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+
+ hpm3: usb-pd@3c {
+ compatible = "apple,cd321x";
+ reg = <0x3c>;
+ interrupt-parent = <&pinctrl_ap>;
+ interrupts = <174 IRQ_TYPE_LEVEL_LOW>;
+ interrupt-names = "irq";
+ };
+};
+
+&nco_clkref {
+ clock-frequency = <1068000000>;
+};
+
+/* PCIe devices */
+&port00 {
+ /* WLAN */
+ bus-range = <1 1>;
+ wifi0: wifi@0,0 {
+ reg = <0x10000 0x0 0x0 0x0 0x0>;
+ /* To be filled by the loader */
+ local-mac-address = [00 10 18 00 00 10];
+ };
+};
+
+&port01 {
+ /* SD card reader */
+ bus-range = <2 2>;
+ sdhci0: mmc@0,0 {
+ compatible = "pci17a0,9755";
+ reg = <0x20000 0x0 0x0 0x0 0x0>;
+ cd-inverted;
+ wp-inverted;
+ };
+};
+
+&port02 {
+ /* 10 Gbit Ethernet */
+ bus-range = <3 3>;
+ ethernet0: ethernet@0,0 {
+ reg = <0x30000 0x0 0x0 0x0 0x0>;
+ /* To be filled by the loader */
+ local-mac-address = [00 10 18 00 00 00];
+ };
+};
+
+&port03 {
+ /* USB xHCI */
+ bus-range = <4 4>;
+};
diff --git a/arch/arm64/boot/dts/apple/t600x-nvme.dtsi b/arch/arm64/boot/dts/apple/t600x-nvme.dtsi
new file mode 100644
index 000000000000..7dff738d317e
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t600x-nvme.dtsi
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * NVMe related devices for Apple T600x SoCs.
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+ DIE_NODE(ans_mbox): mbox@38f408000 {
+ compatible = "apple,t6000-asc-mailbox", "apple,asc-mailbox-v4";
+ reg = <0x3 0x8f408000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ DIE_NO 1069 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 1070 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 1071 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ DIE_NO 1072 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "send-empty", "send-not-empty",
+ "recv-empty", "recv-not-empty";
+ power-domains = <&DIE_NODE(ps_ans2)>;
+ #mbox-cells = <0>;
+ };
+
+ DIE_NODE(sart): sart@393c50000 {
+ compatible = "apple,t6000-sart";
+ reg = <0x3 0x93c50000 0x0 0x10000>;
+ power-domains = <&DIE_NODE(ps_ans2)>;
+ };
+
+ DIE_NODE(nvme): nvme@393cc0000 {
+ compatible = "apple,t6000-nvme-ans2", "apple,nvme-ans2";
+ reg = <0x3 0x93cc0000 0x0 0x40000>, <0x3 0x8f400000 0x0 0x4000>;
+ reg-names = "nvme", "ans";
+ interrupt-parent = <&aic>;
+ /* The NVME interrupt is always routed to die */
+ interrupts = <AIC_IRQ 0 1613 IRQ_TYPE_LEVEL_HIGH>;
+ mboxes = <&DIE_NODE(ans_mbox)>;
+ apple,sart = <&DIE_NODE(sart)>;
+ power-domains = <&DIE_NODE(ps_ans2)>,
+ <&DIE_NODE(ps_apcie_st_sys)>,
+ <&DIE_NODE(ps_apcie_st1_sys)>;
+ power-domain-names = "ans", "apcie0", "apcie1";
+ resets = <&DIE_NODE(ps_ans2)>;
+ };
diff --git a/arch/arm64/boot/dts/apple/t600x-pmgr.dtsi b/arch/arm64/boot/dts/apple/t600x-pmgr.dtsi
new file mode 100644
index 000000000000..0bd44753b76a
--- /dev/null
+++ b/arch/arm64/boot/dts/apple/t600x-pmgr.dtsi
@@ -0,0 +1,2012 @@
+// SPDX-License-Identifier: GPL-2.0+ OR MIT
+/*
+ * PMGR Power domains for the Apple T6001 "M1 Max" SoC
+ *
+ * Copyright The Asahi Linux Contributors
+ */
+
+&DIE_NODE(pmgr) {
+ DIE_NODE(ps_pms_bridge): power-controller@100 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x100 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(pms_bridge);
+ apple,always-on; /* Core device */
+ };
+
+ DIE_NODE(ps_aic): power-controller@108 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x108 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(aic);
+ apple,always-on; /* Core device */
+ };
+
+ DIE_NODE(ps_dwi): power-controller@110 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x110 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dwi);
+ apple,always-on; /* Core device */
+ };
+
+ DIE_NODE(ps_pms): power-controller@118 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x118 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(pms);
+ apple,always-on; /* Core device */
+ };
+
+ DIE_NODE(ps_gpio): power-controller@120 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x120 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(gpio);
+ power-domains = <&DIE_NODE(ps_pms)>, <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_soc_dpe): power-controller@128 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x128 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(soc_dpe);
+ apple,always-on; /* Core device */
+ };
+
+ DIE_NODE(ps_pmgr_soc_ocla): power-controller@130 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x130 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(pmgr_soc_ocla);
+ power-domains = <&DIE_NODE(ps_pms)>;
+ };
+
+ DIE_NODE(ps_pcie0_ref): power-controller@138 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x138 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(pcie0_ref);
+ };
+
+ DIE_NODE(ps_pcie1_ref): power-controller@140 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x140 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(pcie1_ref);
+ };
+
+ DIE_NODE(ps_apcie_st): power-controller@148 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x148 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(apcie_st);
+ power-domains = <&DIE_NODE(ps_pcie1_ref)>;
+ };
+
+ DIE_NODE(ps_apcie_gp): power-controller@150 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x150 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(apcie_gp);
+ power-domains = <&DIE_NODE(ps_pcie0_ref)>;
+ };
+
+ DIE_NODE(ps_devc0_ivdmc): power-controller@180 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x180 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(devc0_ivdmc);
+ };
+
+ DIE_NODE(ps_amcc0): power-controller@188 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x188 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(amcc0);
+ apple,always-on; /* Memory controller */
+ };
+
+ DIE_NODE(ps_amcc2): power-controller@190 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x190 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(amcc2);
+ apple,always-on; /* Memory controller */
+ };
+
+ DIE_NODE(ps_dcs_00): power-controller@198 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x198 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_00);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_01): power-controller@1a0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1a0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_01);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_02): power-controller@1a8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1a8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_02);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_03): power-controller@1b0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1b0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_03);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_08): power-controller@1b8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1b8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_08);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_09): power-controller@1c0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1c0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_09);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_10): power-controller@1c8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1c8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_10);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_11): power-controller@1d0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1d0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_11);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_afi): power-controller@1d8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1d8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afi);
+ apple,always-on; /* Apple Fabric, CPU interface is here */
+ };
+
+ DIE_NODE(ps_afc): power-controller@1e0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1e0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afc);
+ apple,always-on; /* Apple Fabric, CPU interface is here */
+ };
+
+ DIE_NODE(ps_afr): power-controller@1e8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1e8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afr);
+ /* Apple Fabric, media stuff: this can power down */
+ };
+
+ DIE_NODE(ps_afnc1_ioa): power-controller@1f0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1f0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc1_ioa);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afi)>;
+ };
+
+ DIE_NODE(ps_afnc0_ioa): power-controller@1f8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1f8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc0_ioa);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afi)>;
+ };
+
+ DIE_NODE(ps_afnc1_ls): power-controller@200 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x200 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc1_ls);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afnc1_ioa)>;
+ };
+
+ DIE_NODE(ps_afnc0_ls): power-controller@208 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x208 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc0_ls);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afnc0_ioa)>;
+ };
+
+ DIE_NODE(ps_afnc1_lw0): power-controller@210 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x210 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc1_lw0);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afnc1_ls)>;
+ };
+
+ DIE_NODE(ps_afnc1_lw1): power-controller@218 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x218 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc1_lw1);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afnc1_ls)>;
+ };
+
+ DIE_NODE(ps_afnc1_lw2): power-controller@220 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x220 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc1_lw2);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afnc1_ls)>;
+ };
+
+ DIE_NODE(ps_afnc0_lw0): power-controller@228 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x228 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc0_lw0);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afnc0_ls)>;
+ };
+
+ DIE_NODE(ps_scodec): power-controller@230 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x230 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(scodec);
+ power-domains = <&DIE_NODE(ps_afnc1_lw0)>;
+ };
+
+ DIE_NODE(ps_atc0_common): power-controller@238 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x238 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc0_common);
+ power-domains = <&DIE_NODE(ps_afnc1_lw1)>;
+ };
+
+ DIE_NODE(ps_atc1_common): power-controller@240 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x240 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc1_common);
+ power-domains = <&DIE_NODE(ps_afnc1_lw1)>;
+ };
+
+ DIE_NODE(ps_c0_usb31drd): power-controller@248 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x248 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(c0_usb31drd);
+ power-domains = <&DIE_NODE(ps_usb)>;
+ };
+
+ DIE_NODE(ps_c1_usb31drd): power-controller@250 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x250 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(c1_usb31drd);
+ power-domains = <&DIE_NODE(ps_usb)>;
+ };
+
+ DIE_NODE(ps_dispext0_fe): power-controller@258 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x258 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dispext0_fe);
+ power-domains = <&DIE_NODE(ps_afi)>;
+ };
+
+ DIE_NODE(ps_dispext1_fe): power-controller@260 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x260 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dispext1_fe);
+ power-domains = <&DIE_NODE(ps_afi)>;
+ };
+
+ DIE_NODE(ps_ane_sys): power-controller@268 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x268 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(ane_sys);
+ power-domains = <&DIE_NODE(ps_afr)>;
+ };
+
+ DIE_NODE(ps_avd_sys): power-controller@270 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x270 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(avd_sys);
+ power-domains = <&DIE_NODE(ps_afr)>;
+ };
+
+ DIE_NODE(ps_dispext0_cpu0): power-controller@280 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x280 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dispext0_cpu0);
+ power-domains = <&DIE_NODE(ps_dispext0_fe)>;
+ };
+
+ DIE_NODE(ps_dispext1_cpu0): power-controller@2a8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x2a8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dispext1_cpu0);
+ power-domains = <&DIE_NODE(ps_dispext1_fe)>;
+ };
+
+ DIE_NODE(ps_ane_sys_cpu): power-controller@2c8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x2c8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(ane_sys_cpu);
+ power-domains = <&DIE_NODE(ps_ane_sys)>;
+ };
+
+#if DIE_NO == 0
+ /* PMP is only present on die 0 of the M1 Ultra */
+ DIE_NODE(ps_pmp): power-controller@2d8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x2d8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(pmp);
+ };
+#endif
+
+ DIE_NODE(ps_pms_sram): power-controller@2e0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x2e0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(pms_sram);
+ };
+
+ DIE_NODE(ps_apcie_st_sys): power-controller@2e8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x2e8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(apcie_st_sys);
+ power-domains = <&DIE_NODE(ps_apcie_st)>, <&DIE_NODE(ps_ans2)>;
+ };
+
+ DIE_NODE(ps_apcie_st1_sys): power-controller@2f0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x2f0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(apcie_st1_sys);
+ power-domains = <&DIE_NODE(ps_apcie_st)>, <&DIE_NODE(ps_ans2)>;
+ };
+
+ DIE_NODE(ps_atc2_common): power-controller@2f8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x2f8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc2_common);
+ power-domains = <&DIE_NODE(ps_afnc1_lw1)>;
+ };
+
+ DIE_NODE(ps_atc3_common): power-controller@300 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x300 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc3_common);
+ power-domains = <&DIE_NODE(ps_afnc1_lw1)>;
+ };
+
+ DIE_NODE(ps_usb): power-controller@318 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x318 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(usb);
+ power-domains = <&DIE_NODE(ps_afnc1_lw2)>;
+ };
+
+ DIE_NODE(ps_apcie_gp_sys): power-controller@320 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x320 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(apcie_gp_sys);
+ power-domains = <&DIE_NODE(ps_afnc1_lw2)>, <&DIE_NODE(ps_apcie_gp)>;
+ apple,always-on; /* Breaks things if shut down */
+ };
+
+ DIE_NODE(ps_atc0_cio): power-controller@328 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x328 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc0_cio);
+ power-domains = <&DIE_NODE(ps_atc0_common)>;
+ };
+
+ DIE_NODE(ps_atc0_pcie): power-controller@330 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x330 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc0_pcie);
+ power-domains = <&DIE_NODE(ps_atc0_common)>;
+ };
+
+ DIE_NODE(ps_atc1_cio): power-controller@338 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x338 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc1_cio);
+ power-domains = <&DIE_NODE(ps_atc1_common)>;
+ };
+
+ DIE_NODE(ps_atc1_pcie): power-controller@340 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x340 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc1_pcie);
+ power-domains = <&DIE_NODE(ps_atc1_common)>;
+ };
+
+ DIE_NODE(ps_atc2_cio): power-controller@348 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x348 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc2_cio);
+ power-domains = <&DIE_NODE(ps_atc2_common)>;
+ };
+
+ DIE_NODE(ps_atc2_pcie): power-controller@350 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x350 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc2_pcie);
+ power-domains = <&DIE_NODE(ps_atc2_common)>;
+ };
+
+ DIE_NODE(ps_atc3_cio): power-controller@358 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x358 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc3_cio);
+ power-domains = <&DIE_NODE(ps_atc3_common)>;
+ };
+
+ DIE_NODE(ps_atc3_pcie): power-controller@360 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x360 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc3_pcie);
+ power-domains = <&DIE_NODE(ps_atc3_common)>;
+ };
+
+ DIE_NODE(ps_c0_usbctl): power-controller@368 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x368 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(c0_usbctl);
+ power-domains = <&DIE_NODE(ps_usb)>;
+ };
+
+ DIE_NODE(ps_c1_usbctl): power-controller@370 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x370 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(c1_usbctl);
+ power-domains = <&DIE_NODE(ps_usb)>;
+ };
+
+ DIE_NODE(ps_atc0_cio_pcie): power-controller@378 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x378 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc0_cio_pcie);
+ power-domains = <&DIE_NODE(ps_atc0_cio)>;
+ };
+
+ DIE_NODE(ps_atc0_cio_usb): power-controller@380 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x380 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc0_cio_usb);
+ power-domains = <&DIE_NODE(ps_atc0_cio)>;
+ };
+
+ DIE_NODE(ps_atc1_cio_pcie): power-controller@388 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x388 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc1_cio_pcie);
+ power-domains = <&DIE_NODE(ps_atc1_cio)>;
+ };
+
+ DIE_NODE(ps_atc1_cio_usb): power-controller@390 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x390 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc1_cio_usb);
+ power-domains = <&DIE_NODE(ps_atc1_cio)>;
+ };
+
+ DIE_NODE(ps_atc2_cio_pcie): power-controller@398 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x398 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc2_cio_pcie);
+ power-domains = <&DIE_NODE(ps_atc2_cio)>;
+ };
+
+ DIE_NODE(ps_atc2_cio_usb): power-controller@3a0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x3a0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc2_cio_usb);
+ power-domains = <&DIE_NODE(ps_atc2_cio)>;
+ };
+
+ DIE_NODE(ps_atc3_cio_pcie): power-controller@3a8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x3a8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc3_cio_pcie);
+ power-domains = <&DIE_NODE(ps_atc3_cio)>;
+ };
+
+ DIE_NODE(ps_atc3_cio_usb): power-controller@3b0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x3b0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc3_cio_usb);
+ power-domains = <&DIE_NODE(ps_atc3_cio)>;
+ };
+
+ DIE_NODE(ps_trace_fab): power-controller@3b8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x3b8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(trace_fab);
+ };
+};
+
+&DIE_NODE(pmgr_east) {
+ DIE_NODE(ps_clvr_spmi0): power-controller@100 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x100 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(clvr_spmi0);
+ apple,always-on; /* PCPU voltage regulator interface (used by SMC) */
+ };
+
+ DIE_NODE(ps_clvr_spmi1): power-controller@108 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x108 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(clvr_spmi1);
+ apple,always-on; /* GPU voltage regulator interface (used by SMC) */
+ };
+
+ DIE_NODE(ps_clvr_spmi2): power-controller@110 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x110 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(clvr_spmi2);
+ apple,always-on; /* ANE, fabric, AFR voltage regulator interface (used by SMC) */
+ };
+
+ DIE_NODE(ps_clvr_spmi3): power-controller@118 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x118 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(clvr_spmi3);
+ apple,always-on; /* Additional voltage regulator, probably used on T6001 (SMC) */
+ };
+
+ DIE_NODE(ps_clvr_spmi4): power-controller@120 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x120 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(clvr_spmi4);
+ apple,always-on; /* Additional voltage regulator, probably used on T6001 (SMC) */
+ };
+
+ DIE_NODE(ps_ispsens0): power-controller@128 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x128 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(ispsens0);
+ };
+
+ DIE_NODE(ps_ispsens1): power-controller@130 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x130 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(ispsens1);
+ };
+
+ DIE_NODE(ps_ispsens2): power-controller@138 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x138 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(ispsens2);
+ };
+
+ DIE_NODE(ps_ispsens3): power-controller@140 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x140 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(ispsens3);
+ };
+
+ DIE_NODE(ps_afnc2_ioa): power-controller@148 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x148 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc2_ioa);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afi)>;
+ };
+
+ DIE_NODE(ps_afnc2_ls): power-controller@150 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x150 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc2_ls);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afnc2_ioa)>;
+ };
+
+ DIE_NODE(ps_afnc2_lw0): power-controller@158 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x158 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc2_lw0);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afnc2_ls)>;
+ };
+
+ DIE_NODE(ps_afnc2_lw1): power-controller@160 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x160 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc2_lw1);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afnc2_ls)>;
+ };
+
+ DIE_NODE(ps_afnc3_ioa): power-controller@168 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x168 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc3_ioa);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afi)>;
+ };
+
+ DIE_NODE(ps_afnc3_ls): power-controller@170 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x170 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc3_ls);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afnc3_ioa)>;
+ };
+
+ DIE_NODE(ps_afnc3_lw0): power-controller@178 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x178 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc3_lw0);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afnc3_ls)>;
+ };
+
+ DIE_NODE(ps_sio): power-controller@180 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x180 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(sio);
+ power-domains = <&DIE_NODE(ps_afnc2_lw1)>;
+ };
+
+ DIE_NODE(ps_sio_cpu): power-controller@188 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x188 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(sio_cpu);
+ power-domains = <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_fpwm0): power-controller@190 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x190 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(fpwm0);
+ power-domains = <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_fpwm1): power-controller@198 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x198 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(fpwm1);
+ power-domains = <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_fpwm2): power-controller@1a0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1a0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(fpwm2);
+ power-domains = <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_i2c0): power-controller@1a8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1a8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(i2c0);
+ power-domains = <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_i2c1): power-controller@1b0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1b0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(i2c1);
+ power-domains = <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_i2c2): power-controller@1b8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1b8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(i2c2);
+ power-domains = <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_i2c3): power-controller@1c0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1c0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(i2c3);
+ power-domains = <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_i2c4): power-controller@1c8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1c8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(i2c4);
+ power-domains = <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_i2c5): power-controller@1d0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1d0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(i2c5);
+ power-domains = <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_i2c6): power-controller@1d8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1d8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(i2c6);
+ power-domains = <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_i2c7): power-controller@1e0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1e0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(i2c7);
+ power-domains = <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_spi_p): power-controller@1e8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1e8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(spi_p);
+ power-domains = <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_spi0): power-controller@1f0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1f0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(spi0);
+ power-domains = <&DIE_NODE(ps_spi_p)>;
+ };
+
+ DIE_NODE(ps_spi1): power-controller@1f8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1f8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(spi1);
+ power-domains = <&DIE_NODE(ps_spi_p)>;
+ };
+
+ DIE_NODE(ps_spi2): power-controller@200 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x200 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(spi2);
+ power-domains = <&DIE_NODE(ps_spi_p)>;
+ };
+
+ DIE_NODE(ps_spi3): power-controller@208 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x208 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(spi3);
+ power-domains = <&DIE_NODE(ps_spi_p)>;
+ };
+
+ DIE_NODE(ps_spi4): power-controller@210 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x210 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(spi4);
+ power-domains = <&DIE_NODE(ps_spi_p)>;
+ };
+
+ DIE_NODE(ps_sio_spmi0): power-controller@218 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x218 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(sio_spmi0);
+ power-domains = <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_sio_spmi1): power-controller@220 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x220 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(sio_spmi1);
+ power-domains = <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_sio_spmi2): power-controller@228 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x228 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(sio_spmi2);
+ power-domains = <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_uart_p): power-controller@230 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x230 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(uart_p);
+ power-domains = <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_uart_n): power-controller@238 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x238 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(uart_n);
+ power-domains = <&DIE_NODE(ps_uart_p)>;
+ };
+
+ DIE_NODE(ps_uart0): power-controller@240 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x240 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(uart0);
+ power-domains = <&DIE_NODE(ps_uart_p)>;
+ };
+
+ DIE_NODE(ps_uart1): power-controller@248 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x248 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(uart1);
+ power-domains = <&DIE_NODE(ps_uart_p)>;
+ };
+
+ DIE_NODE(ps_uart2): power-controller@250 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x250 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(uart2);
+ power-domains = <&DIE_NODE(ps_uart_p)>;
+ };
+
+ DIE_NODE(ps_uart3): power-controller@258 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x258 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(uart3);
+ power-domains = <&DIE_NODE(ps_uart_p)>;
+ };
+
+ DIE_NODE(ps_uart4): power-controller@260 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x260 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(uart4);
+ power-domains = <&DIE_NODE(ps_uart_p)>;
+ };
+
+ DIE_NODE(ps_uart6): power-controller@268 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x268 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(uart6);
+ power-domains = <&DIE_NODE(ps_uart_p)>;
+ };
+
+ DIE_NODE(ps_uart7): power-controller@270 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x270 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(uart7);
+ power-domains = <&DIE_NODE(ps_uart_p)>;
+ };
+
+ DIE_NODE(ps_audio_p): power-controller@278 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x278 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(audio_p);
+ power-domains = <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_sio_adma): power-controller@280 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x280 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(sio_adma);
+ power-domains = <&DIE_NODE(ps_audio_p)>, <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_mca0): power-controller@288 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x288 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(mca0);
+ power-domains = <&DIE_NODE(ps_audio_p)>, <&DIE_NODE(ps_sio_adma)>;
+ };
+
+ DIE_NODE(ps_mca1): power-controller@290 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x290 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(mca1);
+ power-domains = <&DIE_NODE(ps_audio_p)>, <&DIE_NODE(ps_sio_adma)>;
+ };
+
+ DIE_NODE(ps_mca2): power-controller@298 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x298 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(mca2);
+ power-domains = <&DIE_NODE(ps_audio_p)>, <&DIE_NODE(ps_sio_adma)>;
+ };
+
+ DIE_NODE(ps_mca3): power-controller@2a0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x2a0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(mca3);
+ power-domains = <&DIE_NODE(ps_audio_p)>, <&DIE_NODE(ps_sio_adma)>;
+ };
+
+ DIE_NODE(ps_dpa0): power-controller@2a8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x2a8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dpa0);
+ power-domains = <&DIE_NODE(ps_audio_p)>;
+ };
+
+ DIE_NODE(ps_dpa1): power-controller@2b0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x2b0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dpa1);
+ power-domains = <&DIE_NODE(ps_audio_p)>;
+ };
+
+ DIE_NODE(ps_dpa2): power-controller@2b8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x2b8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dpa2);
+ power-domains = <&DIE_NODE(ps_audio_p)>;
+ };
+
+ DIE_NODE(ps_dpa3): power-controller@2c0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x2c0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dpa3);
+ power-domains = <&DIE_NODE(ps_audio_p)>;
+ };
+
+ DIE_NODE(ps_dpa4): power-controller@2c8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x2c8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dpa4);
+ power-domains = <&DIE_NODE(ps_audio_p)>;
+ };
+
+ DIE_NODE(ps_aes): power-controller@2d0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x2d0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(aes);
+ power-domains = <&DIE_NODE(ps_sio)>;
+ };
+
+ DIE_NODE(ps_amcc1): power-controller@2d8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x2d8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(amcc1);
+ apple,always-on; /* Memory controller */
+ };
+
+ DIE_NODE(ps_amcc3): power-controller@2e0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x2e0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(amcc3);
+ apple,always-on; /* Memory controller */
+ };
+
+ DIE_NODE(ps_dcs_04): power-controller@2e8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x2e8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_04);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_05): power-controller@2f0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x2f0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_05);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_06): power-controller@2f8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x2f8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_06);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_07): power-controller@300 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x300 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_07);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_12): power-controller@308 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x308 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_12);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_13): power-controller@310 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x310 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_13);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_14): power-controller@318 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x318 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_14);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_15): power-controller@320 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x320 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_15);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_disp0_fe): power-controller@328 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x328 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(disp0_fe);
+ power-domains = <&DIE_NODE(ps_afnc2_lw0)>;
+ apple,always-on; /* TODO: figure out if we can enable PM here */
+ };
+
+ DIE_NODE(ps_disp0_cpu0): power-controller@350 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x350 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(disp0_cpu0);
+ power-domains = <&DIE_NODE(ps_disp0_fe)>;
+ apple,always-on; /* TODO: figure out if we can enable PM here */
+ apple,min-state = <4>;
+ };
+
+ DIE_NODE(ps_dispdfr_fe): power-controller@378 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x378 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dispdfr_fe);
+ power-domains = <&DIE_NODE(ps_afnc2_lw1)>;
+ };
+
+ DIE_NODE(ps_dispdfr_be): power-controller@380 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x380 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dispdfr_be);
+ power-domains = <&DIE_NODE(ps_dispdfr_fe)>;
+ };
+
+ DIE_NODE(ps_mipi_dsi): power-controller@388 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x388 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(mipi_dsi);
+ power-domains = <&DIE_NODE(ps_dispdfr_be)>;
+ };
+
+ DIE_NODE(ps_jpg): power-controller@390 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x390 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(jpg);
+ power-domains = <&DIE_NODE(ps_afr)>;
+ };
+
+ DIE_NODE(ps_msr0): power-controller@398 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x398 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(msr0);
+ power-domains = <&DIE_NODE(ps_afr)>;
+ };
+
+ DIE_NODE(ps_msr0_ase_core): power-controller@3a0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x3a0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(msr0_ase_core);
+ power-domains = <&DIE_NODE(ps_msr0)>;
+ };
+
+ DIE_NODE(ps_isp_sys): power-controller@3a8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x3a8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(isp_sys);
+ power-domains = <&DIE_NODE(ps_afnc2_lw1)>;
+ };
+
+ DIE_NODE(ps_venc_sys): power-controller@3b0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x3b0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(venc_sys);
+ power-domains = <&DIE_NODE(ps_afr)>;
+ };
+
+ DIE_NODE(ps_ans2): power-controller@3b8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x3b8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(ans2);
+ /*
+ * The ADT makes ps_apcie_st[1]_sys depend on ps_ans2 instead,
+ * but we'd rather have a single power domain for the downstream
+ * device to depend on, so use this node as the child.
+ * This makes more sense anyway (since ANS2 uses APCIE_ST).
+ */
+ power-domains = <&DIE_NODE(ps_afnc2_lw0)>;
+ };
+
+ DIE_NODE(ps_gfx): power-controller@3c0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x3c0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(gfx);
+ power-domains = <&DIE_NODE(ps_afr)>;
+ };
+
+ DIE_NODE(ps_sep): power-controller@c00 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0xc00 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(sep);
+ apple,always-on; /* Locked on */
+ };
+
+ DIE_NODE(ps_venc_dma): power-controller@8000 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x8000 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(venc_dma);
+ power-domains = <&DIE_NODE(ps_venc_sys)>;
+ };
+
+ DIE_NODE(ps_venc_pipe4): power-controller@8008 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x8008 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(venc_pipe4);
+ power-domains = <&DIE_NODE(ps_venc_dma)>;
+ };
+
+ DIE_NODE(ps_venc_pipe5): power-controller@8010 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x8010 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(venc_pipe5);
+ power-domains = <&DIE_NODE(ps_venc_dma)>;
+ };
+
+ DIE_NODE(ps_venc_me0): power-controller@8018 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x8018 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(venc_me0);
+ power-domains = <&DIE_NODE(ps_venc_pipe5)>, <&DIE_NODE(ps_venc_pipe4)>;
+ };
+
+ DIE_NODE(ps_venc_me1): power-controller@8020 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x8020 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(venc_me1);
+ power-domains = <&DIE_NODE(ps_venc_me0)>;
+ };
+};
+
+&DIE_NODE(pmgr_south) {
+ DIE_NODE(ps_amcc4): power-controller@100 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x100 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(amcc4);
+ apple,always-on; /* Memory controller */
+ };
+
+ DIE_NODE(ps_amcc5): power-controller@108 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x108 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(amcc5);
+ apple,always-on; /* Memory controller */
+ };
+
+ DIE_NODE(ps_amcc6): power-controller@110 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x110 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(amcc6);
+ apple,always-on; /* Memory controller */
+ };
+
+ DIE_NODE(ps_amcc7): power-controller@118 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x118 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(amcc7);
+ apple,always-on; /* Memory controller */
+ };
+
+ DIE_NODE(ps_dcs_16): power-controller@120 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x120 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_16);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_17): power-controller@128 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x128 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_17);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_18): power-controller@130 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x130 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_18);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_19): power-controller@138 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x138 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_19);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_20): power-controller@140 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x140 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_20);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_21): power-controller@148 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x148 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_21);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_22): power-controller@150 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x150 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_22);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_23): power-controller@158 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x158 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_23);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_24): power-controller@160 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x160 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_24);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_25): power-controller@168 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x168 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_25);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_26): power-controller@170 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x170 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_26);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_27): power-controller@178 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x178 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_27);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_28): power-controller@180 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x180 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_28);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_29): power-controller@188 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x188 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_29);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_30): power-controller@190 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x190 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_30);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_dcs_31): power-controller@198 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x198 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dcs_31);
+ apple,always-on; /* LPDDR5 interface */
+ };
+
+ DIE_NODE(ps_afnc4_ioa): power-controller@1a0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1a0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc4_ioa);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afi)>;
+ };
+
+ DIE_NODE(ps_afnc4_ls): power-controller@1a8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1a8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc4_ls);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afnc4_ioa)>;
+ };
+
+ DIE_NODE(ps_afnc4_lw0): power-controller@1b0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1b0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc4_lw0);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afnc4_ls)>;
+ };
+
+ DIE_NODE(ps_afnc5_ioa): power-controller@1b8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1b8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc5_ioa);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afi)>;
+ };
+
+ DIE_NODE(ps_afnc5_ls): power-controller@1c0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1c0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc5_ls);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afnc5_ioa)>;
+ };
+
+ DIE_NODE(ps_afnc5_lw0): power-controller@1c8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1c8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(afnc5_lw0);
+ apple,always-on; /* Apple Fabric */
+ power-domains = <&DIE_NODE(ps_afnc5_ls)>;
+ };
+
+ DIE_NODE(ps_dispext2_fe): power-controller@1d0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1d0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dispext2_fe);
+ power-domains = <&DIE_NODE(ps_afnc4_lw0)>;
+ };
+
+ DIE_NODE(ps_dispext2_cpu0): power-controller@1e8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x1e8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dispext2_cpu0);
+ power-domains = <&DIE_NODE(ps_dispext2_fe)>;
+ };
+
+ DIE_NODE(ps_dispext3_fe): power-controller@210 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x210 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dispext3_fe);
+ power-domains = <&DIE_NODE(ps_afnc4_lw0)>;
+ };
+
+ DIE_NODE(ps_dispext3_cpu0): power-controller@228 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x228 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(dispext3_cpu0);
+ power-domains = <&DIE_NODE(ps_dispext3_fe)>;
+ };
+
+ DIE_NODE(ps_msr1): power-controller@250 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x250 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(msr1);
+ power-domains = <&DIE_NODE(ps_afnc5_lw0)>, <&DIE_NODE(ps_afr)>;
+ };
+
+ DIE_NODE(ps_msr1_ase_core): power-controller@258 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x258 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(msr1_ase_core);
+ power-domains = <&DIE_NODE(ps_msr1)>;
+ };
+
+ DIE_NODE(ps_venc1_sys): power-controller@260 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x260 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(venc1_sys);
+ power-domains = <&DIE_NODE(ps_afnc5_lw0)>, <&DIE_NODE(ps_afr)>;
+ };
+
+ /* Seems to be disabled on shipping hardware */
+#if 0
+ DIE_NODE(ps_ane1_sys): power-controller@268 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x268 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(ane1_sys);
+ power-domains = <&DIE_NODE(ps_afnc5_lw0)>;
+ };
+
+ DIE_NODE(ps_ane1_sys_cpu): power-controller@270 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x270 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(ane1_sys_cpu);
+ power-domains = <&DIE_NODE(ps_ane1_sys)>;
+ };
+#endif
+
+ DIE_NODE(ps_venc1_dma): power-controller@8000 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x8000 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(venc1_dma);
+ power-domains = <&DIE_NODE(ps_venc1_sys)>;
+ };
+
+ DIE_NODE(ps_venc1_pipe4): power-controller@8008 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x8008 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(venc1_pipe4);
+ power-domains = <&DIE_NODE(ps_venc1_dma)>;
+ };
+
+ DIE_NODE(ps_venc1_pipe5): power-controller@8010 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x8010 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(venc1_pipe5);
+ power-domains = <&DIE_NODE(ps_venc1_dma)>;
+ };
+
+ DIE_NODE(ps_venc1_me0): power-controller@8018 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x8018 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(venc1_me0);
+ power-domains = <&DIE_NODE(ps_venc1_pipe4)>, <&DIE_NODE(ps_venc1_pipe5)>;
+ };
+
+ DIE_NODE(ps_venc1_me1): power-controller@8020 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x8020 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(venc1_me1);
+ power-domains = <&DIE_NODE(ps_venc1_me0)>;
+ };
+
+ DIE_NODE(ps_prores): power-controller@c000 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0xc000 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(prores);
+ power-domains = <&DIE_NODE(ps_afnc4_lw0)>;
+ };
+};
+
+&DIE_NODE(pmgr_mini) {
+ DIE_NODE(ps_debug): power-controller@58 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x58 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(debug);
+ apple,always-on; /* Core AON device */
+ };
+
+ DIE_NODE(ps_nub_spmi0): power-controller@60 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x60 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(nub_spmi0);
+ apple,always-on; /* Core AON device */
+ };
+
+ DIE_NODE(ps_nub_spmi1): power-controller@68 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x68 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(nub_spmi1);
+ apple,always-on; /* Core AON device */
+ };
+
+ DIE_NODE(ps_nub_aon): power-controller@70 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x70 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(nub_aon);
+ apple,always-on; /* Core AON device */
+ };
+
+ DIE_NODE(ps_msg): power-controller@78 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x78 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(msg);
+ };
+
+ DIE_NODE(ps_nub_gpio): power-controller@80 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x80 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(nub_gpio);
+ apple,always-on; /* Core AON device */
+ };
+
+ DIE_NODE(ps_atc0_usb_aon): power-controller@88 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x88 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc0_usb_aon);
+ apple,always-on; /* Needs to stay on for dwc3 to work */
+ };
+
+ DIE_NODE(ps_atc1_usb_aon): power-controller@90 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x90 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc1_usb_aon);
+ apple,always-on; /* Needs to stay on for dwc3 to work */
+ };
+
+ DIE_NODE(ps_atc2_usb_aon): power-controller@98 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0x98 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc2_usb_aon);
+ apple,always-on; /* Needs to stay on for dwc3 to work */
+ };
+
+ DIE_NODE(ps_atc3_usb_aon): power-controller@a0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0xa0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc3_usb_aon);
+ apple,always-on; /* Needs to stay on for dwc3 to work */
+ };
+
+ DIE_NODE(ps_gp_usb_aon): power-controller@a8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0xa8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(gp_usb_aon);
+ };
+
+ DIE_NODE(ps_nub_fabric): power-controller@b0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0xb0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(nub_fabric);
+ apple,always-on; /* Core AON device */
+ };
+
+ DIE_NODE(ps_nub_sram): power-controller@b8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0xb8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(nub_sram);
+ apple,always-on; /* Core AON device */
+ };
+
+ DIE_NODE(ps_debug_usb): power-controller@c0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0xc0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(debug_usb);
+ apple,always-on; /* Core AON device */
+ power-domains = <&DIE_NODE(ps_debug)>;
+ };
+
+ DIE_NODE(ps_debug_auth): power-controller@c8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0xc8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(debug_auth);
+ apple,always-on; /* Core AON device */
+ power-domains = <&DIE_NODE(ps_debug)>;
+ };
+
+ DIE_NODE(ps_atc0_usb): power-controller@d0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0xd0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc0_usb);
+ power-domains = <&DIE_NODE(ps_atc0_usb_aon)>, <&DIE_NODE(ps_atc0_common)>;
+ };
+
+ DIE_NODE(ps_atc1_usb): power-controller@d8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0xd8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc1_usb);
+ power-domains = <&DIE_NODE(ps_atc1_usb_aon)>, <&DIE_NODE(ps_atc1_common)>;
+ };
+
+ DIE_NODE(ps_atc2_usb): power-controller@e0 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0xe0 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc2_usb);
+ power-domains = <&DIE_NODE(ps_atc2_usb_aon)>, <&DIE_NODE(ps_atc2_common)>;
+ };
+
+ DIE_NODE(ps_atc3_usb): power-controller@e8 {
+ compatible = "apple,t6000-pmgr-pwrstate", "apple,pmgr-pwrstate";
+ reg = <0xe8 4>;
+ #power-domain-cells = <0>;
+ #reset-cells = <0>;
+ label = DIE_LABEL(atc3_usb);
+ power-domains = <&DIE_NODE(ps_atc3_usb_aon)>, <&DIE_NODE(ps_atc3_common)>;
+ };
+};
diff --git a/arch/arm64/boot/dts/apple/t8103-j456.dts b/arch/arm64/boot/dts/apple/t8103-j456.dts
index 7ea27456f33c..2db425ceb30f 100644
--- a/arch/arm64/boot/dts/apple/t8103-j456.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j456.dts
@@ -14,7 +14,7 @@
/ {
compatible = "apple,j456", "apple,t8103", "apple,arm-platform";
- model = "Apple iMac (24-inch, 4x USB-C, M1, 2020)";
+ model = "Apple iMac (24-inch, 4x USB-C, M1, 2021)";
aliases {
ethernet0 = &ethernet0;
diff --git a/arch/arm64/boot/dts/apple/t8103-j457.dts b/arch/arm64/boot/dts/apple/t8103-j457.dts
index 8ee0ac871426..3821ff146c56 100644
--- a/arch/arm64/boot/dts/apple/t8103-j457.dts
+++ b/arch/arm64/boot/dts/apple/t8103-j457.dts
@@ -14,7 +14,7 @@
/ {
compatible = "apple,j457", "apple,t8103", "apple,arm-platform";
- model = "Apple iMac (24-inch, 2x USB-C, M1, 2020)";
+ model = "Apple iMac (24-inch, 2x USB-C, M1, 2021)";
aliases {
ethernet0 = &ethernet0;
diff --git a/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi b/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi
index cc2e04035763..5988a4eb6efa 100644
--- a/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103-jxxx.dtsi
@@ -86,3 +86,7 @@
local-bd-address = [00 00 00 00 00 00];
};
};
+
+&nco_clkref {
+ clock-frequency = <900000000>;
+};
diff --git a/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi b/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi
index a6dbb1f485d8..9645861a858c 100644
--- a/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103-pmgr.dtsi
@@ -339,7 +339,7 @@
#power-domain-cells = <0>;
#reset-cells = <0>;
label = "sio_adma";
- power-domains = <&ps_sio>, <&ps_pms>;
+ power-domains = <&ps_sio>, <&ps_pms>, <&ps_audio_p>;
};
ps_aes: power-controller@238 {
diff --git a/arch/arm64/boot/dts/apple/t8103.dtsi b/arch/arm64/boot/dts/apple/t8103.dtsi
index 51a63b29d404..9859219699f4 100644
--- a/arch/arm64/boot/dts/apple/t8103.dtsi
+++ b/arch/arm64/boot/dts/apple/t8103.dtsi
@@ -22,69 +22,279 @@
#address-cells = <2>;
#size-cells = <0>;
- cpu0: cpu@0 {
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&cpu_e0>;
+ };
+ core1 {
+ cpu = <&cpu_e1>;
+ };
+ core2 {
+ cpu = <&cpu_e2>;
+ };
+ core3 {
+ cpu = <&cpu_e3>;
+ };
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&cpu_p0>;
+ };
+ core1 {
+ cpu = <&cpu_p1>;
+ };
+ core2 {
+ cpu = <&cpu_p2>;
+ };
+ core3 {
+ cpu = <&cpu_p3>;
+ };
+ };
+ };
+
+ cpu_e0: cpu@0 {
compatible = "apple,icestorm";
device_type = "cpu";
reg = <0x0 0x0>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&ecluster_opp>;
+ capacity-dmips-mhz = <714>;
+ performance-domains = <&cpufreq_e>;
+ next-level-cache = <&l2_cache_0>;
+ i-cache-size = <0x20000>;
+ d-cache-size = <0x10000>;
};
- cpu1: cpu@1 {
+ cpu_e1: cpu@1 {
compatible = "apple,icestorm";
device_type = "cpu";
reg = <0x0 0x1>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&ecluster_opp>;
+ capacity-dmips-mhz = <714>;
+ performance-domains = <&cpufreq_e>;
+ next-level-cache = <&l2_cache_0>;
+ i-cache-size = <0x20000>;
+ d-cache-size = <0x10000>;
};
- cpu2: cpu@2 {
+ cpu_e2: cpu@2 {
compatible = "apple,icestorm";
device_type = "cpu";
reg = <0x0 0x2>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&ecluster_opp>;
+ capacity-dmips-mhz = <714>;
+ performance-domains = <&cpufreq_e>;
+ next-level-cache = <&l2_cache_0>;
+ i-cache-size = <0x20000>;
+ d-cache-size = <0x10000>;
};
- cpu3: cpu@3 {
+ cpu_e3: cpu@3 {
compatible = "apple,icestorm";
device_type = "cpu";
reg = <0x0 0x3>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&ecluster_opp>;
+ capacity-dmips-mhz = <714>;
+ performance-domains = <&cpufreq_e>;
+ next-level-cache = <&l2_cache_0>;
+ i-cache-size = <0x20000>;
+ d-cache-size = <0x10000>;
};
- cpu4: cpu@10100 {
+ cpu_p0: cpu@10100 {
compatible = "apple,firestorm";
device_type = "cpu";
reg = <0x0 0x10100>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&pcluster_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p>;
+ next-level-cache = <&l2_cache_1>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
};
- cpu5: cpu@10101 {
+ cpu_p1: cpu@10101 {
compatible = "apple,firestorm";
device_type = "cpu";
reg = <0x0 0x10101>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&pcluster_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p>;
+ next-level-cache = <&l2_cache_1>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
};
- cpu6: cpu@10102 {
+ cpu_p2: cpu@10102 {
compatible = "apple,firestorm";
device_type = "cpu";
reg = <0x0 0x10102>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&pcluster_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p>;
+ next-level-cache = <&l2_cache_1>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
};
- cpu7: cpu@10103 {
+ cpu_p3: cpu@10103 {
compatible = "apple,firestorm";
device_type = "cpu";
reg = <0x0 0x10103>;
enable-method = "spin-table";
cpu-release-addr = <0 0>; /* To be filled by loader */
+ operating-points-v2 = <&pcluster_opp>;
+ capacity-dmips-mhz = <1024>;
+ performance-domains = <&cpufreq_p>;
+ next-level-cache = <&l2_cache_1>;
+ i-cache-size = <0x30000>;
+ d-cache-size = <0x20000>;
+ };
+
+ l2_cache_0: l2-cache-0 {
+ compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
+ cache-size = <0x400000>;
+ };
+
+ l2_cache_1: l2-cache-1 {
+ compatible = "cache";
+ cache-level = <2>;
+ cache-unified;
+ cache-size = <0xc00000>;
+ };
+ };
+
+ ecluster_opp: opp-table-0 {
+ compatible = "operating-points-v2";
+
+ opp01 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-level = <1>;
+ clock-latency-ns = <7500>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <972000000>;
+ opp-level = <2>;
+ clock-latency-ns = <22000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <1332000000>;
+ opp-level = <3>;
+ clock-latency-ns = <27000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1704000000>;
+ opp-level = <4>;
+ clock-latency-ns = <33000>;
+ };
+ opp05 {
+ opp-hz = /bits/ 64 <2064000000>;
+ opp-level = <5>;
+ clock-latency-ns = <50000>;
+ };
+ };
+
+ pcluster_opp: opp-table-1 {
+ compatible = "operating-points-v2";
+
+ opp01 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-level = <1>;
+ clock-latency-ns = <8000>;
+ };
+ opp02 {
+ opp-hz = /bits/ 64 <828000000>;
+ opp-level = <2>;
+ clock-latency-ns = <19000>;
+ };
+ opp03 {
+ opp-hz = /bits/ 64 <1056000000>;
+ opp-level = <3>;
+ clock-latency-ns = <21000>;
+ };
+ opp04 {
+ opp-hz = /bits/ 64 <1284000000>;
+ opp-level = <4>;
+ clock-latency-ns = <23000>;
};
+ opp05 {
+ opp-hz = /bits/ 64 <1500000000>;
+ opp-level = <5>;
+ clock-latency-ns = <24000>;
+ };
+ opp06 {
+ opp-hz = /bits/ 64 <1728000000>;
+ opp-level = <6>;
+ clock-latency-ns = <29000>;
+ };
+ opp07 {
+ opp-hz = /bits/ 64 <1956000000>;
+ opp-level = <7>;
+ clock-latency-ns = <31000>;
+ };
+ opp08 {
+ opp-hz = /bits/ 64 <2184000000>;
+ opp-level = <8>;
+ clock-latency-ns = <34000>;
+ };
+ opp09 {
+ opp-hz = /bits/ 64 <2388000000>;
+ opp-level = <9>;
+ clock-latency-ns = <36000>;
+ };
+ opp10 {
+ opp-hz = /bits/ 64 <2592000000>;
+ opp-level = <10>;
+ clock-latency-ns = <51000>;
+ };
+ opp11 {
+ opp-hz = /bits/ 64 <2772000000>;
+ opp-level = <11>;
+ clock-latency-ns = <54000>;
+ };
+ opp12 {
+ opp-hz = /bits/ 64 <2988000000>;
+ opp-level = <12>;
+ clock-latency-ns = <55000>;
+ };
+#if 0
+ /* Not available until CPU deep sleep is implemented */
+ opp13 {
+ opp-hz = /bits/ 64 <3096000000>;
+ opp-level = <13>;
+ clock-latency-ns = <55000>;
+ turbo-mode;
+ };
+ opp14 {
+ opp-hz = /bits/ 64 <3144000000>;
+ opp-level = <14>;
+ clock-latency-ns = <56000>;
+ turbo-mode;
+ };
+ opp15 {
+ opp-hz = /bits/ 64 <3204000000>;
+ opp-level = <15>;
+ clock-latency-ns = <56000>;
+ turbo-mode;
+ };
+#endif
};
timer {
@@ -116,6 +326,16 @@
clock-output-names = "clkref";
};
+ /*
+ * This is a fabulated representation of the input clock
+ * to NCO since we don't know the true clock tree.
+ */
+ nco_clkref: clock-ref-nco {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-output-names = "nco_ref";
+ };
+
soc {
compatible = "simple-bus";
#address-cells = <2>;
@@ -124,6 +344,27 @@
ranges;
nonposted-mmio;
+ cpufreq_e: performance-controller@210e20000 {
+ compatible = "apple,t8103-cluster-cpufreq", "apple,cluster-cpufreq";
+ reg = <0x2 0x10e20000 0 0x1000>;
+ #performance-domain-cells = <0>;
+ };
+
+ cpufreq_p: performance-controller@211e20000 {
+ compatible = "apple,t8103-cluster-cpufreq", "apple,cluster-cpufreq";
+ reg = <0x2 0x11e20000 0 0x1000>;
+ #performance-domain-cells = <0>;
+ };
+
+ sio_dart: iommu@235004000 {
+ compatible = "apple,t8103-dart";
+ reg = <0x2 0x35004000 0x0 0x4000>;
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 635 IRQ_TYPE_LEVEL_HIGH>;
+ #iommu-cells = <1>;
+ power-domains = <&ps_sio_cpu>;
+ };
+
i2c0: i2c@235010000 {
compatible = "apple,t8103-i2c", "apple,i2c";
reg = <0x2 0x35010000 0x0 0x4000>;
@@ -219,6 +460,61 @@
status = "disabled";
};
+ admac: dma-controller@238200000 {
+ compatible = "apple,t8103-admac", "apple,admac";
+ reg = <0x2 0x38200000 0x0 0x34000>;
+ dma-channels = <24>;
+ interrupts-extended = <0>,
+ <&aic AIC_IRQ 626 IRQ_TYPE_LEVEL_HIGH>,
+ <0>,
+ <0>;
+ #dma-cells = <1>;
+ iommus = <&sio_dart 2>;
+ power-domains = <&ps_sio_adma>;
+ resets = <&ps_audio_p>;
+ };
+
+ mca: i2s@238400000 {
+ compatible = "apple,t8103-mca", "apple,mca";
+ reg = <0x2 0x38400000 0x0 0x18000>,
+ <0x2 0x38300000 0x0 0x30000>;
+
+ interrupt-parent = <&aic>;
+ interrupts = <AIC_IRQ 619 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 620 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 621 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 622 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 623 IRQ_TYPE_LEVEL_HIGH>,
+ <AIC_IRQ 624 IRQ_TYPE_LEVEL_HIGH>;
+
+ resets = <&ps_audio_p>;
+ clocks = <&nco 0>, <&nco 1>, <&nco 2>,
+ <&nco 3>, <&nco 4>, <&nco 4>;
+ power-domains = <&ps_audio_p>, <&ps_mca0>, <&ps_mca1>,
+ <&ps_mca2>, <&ps_mca3>, <&ps_mca4>, <&ps_mca5>;
+ dmas = <&admac 0>, <&admac 1>, <&admac 2>, <&admac 3>,
+ <&admac 4>, <&admac 5>, <&admac 6>, <&admac 7>,
+ <&admac 8>, <&admac 9>, <&admac 10>, <&admac 11>,
+ <&admac 12>, <&admac 13>, <&admac 14>, <&admac 15>,
+ <&admac 16>, <&admac 17>, <&admac 18>, <&admac 19>,
+ <&admac 20>, <&admac 21>, <&admac 22>, <&admac 23>;
+ dma-names = "tx0a", "rx0a", "tx0b", "rx0b",
+ "tx1a", "rx1a", "tx1b", "rx1b",
+ "tx2a", "rx2a", "tx2b", "rx2b",
+ "tx3a", "rx3a", "tx3b", "rx3b",
+ "tx4a", "rx4a", "tx4b", "rx4b",
+ "tx5a", "rx5a", "tx5b", "rx5b";
+
+ #sound-dai-cells = <1>;
+ };
+
+ nco: clock-controller@23b044000 {
+ compatible = "apple,t8103-nco", "apple,nco";
+ reg = <0x2 0x3b044000 0x0 0x14000>;
+ clocks = <&nco_clkref>;
+ #clock-cells = <1>;
+ };
+
aic: interrupt-controller@23b100000 {
compatible = "apple,t8103-aic", "apple,aic";
#interrupt-cells = <3>;
@@ -229,12 +525,12 @@
affinities {
e-core-pmu-affinity {
apple,fiq-index = <AIC_CPU_PMU_E>;
- cpus = <&cpu0 &cpu1 &cpu2 &cpu3>;
+ cpus = <&cpu_e0 &cpu_e1 &cpu_e2 &cpu_e3>;
};
p-core-pmu-affinity {
apple,fiq-index = <AIC_CPU_PMU_P>;
- cpus = <&cpu4 &cpu5 &cpu6 &cpu7>;
+ cpus = <&cpu_p0 &cpu_p1 &cpu_p2 &cpu_p3>;
};
};
};
@@ -412,7 +708,7 @@
resets = <&ps_ans2>;
};
- pcie0_dart_0: dart@681008000 {
+ pcie0_dart_0: iommu@681008000 {
compatible = "apple,t8103-dart";
reg = <0x6 0x81008000 0x0 0x4000>;
#iommu-cells = <1>;
@@ -421,7 +717,7 @@
power-domains = <&ps_apcie_gp>;
};
- pcie0_dart_1: dart@682008000 {
+ pcie0_dart_1: iommu@682008000 {
compatible = "apple,t8103-dart";
reg = <0x6 0x82008000 0x0 0x4000>;
#iommu-cells = <1>;
@@ -430,7 +726,7 @@
power-domains = <&ps_apcie_gp>;
};
- pcie0_dart_2: dart@683008000 {
+ pcie0_dart_2: iommu@683008000 {
compatible = "apple,t8103-dart";
reg = <0x6 0x83008000 0x0 0x4000>;
#iommu-cells = <1>;
diff --git a/arch/arm64/boot/dts/arm/corstone1000.dtsi b/arch/arm64/boot/dts/arm/corstone1000.dtsi
index 4e46826f883a..21f1f952e985 100644
--- a/arch/arm64/boot/dts/arm/corstone1000.dtsi
+++ b/arch/arm64/boot/dts/arm/corstone1000.dtsi
@@ -53,6 +53,7 @@
L2_0: l2-cache0 {
compatible = "cache";
+ cache-unified;
cache-level = <2>;
cache-size = <0x80000>;
cache-line-size = <64>;
diff --git a/arch/arm64/boot/dts/arm/foundation-v8.dtsi b/arch/arm64/boot/dts/arm/foundation-v8.dtsi
index 83e3e7e3984f..029578072d8f 100644
--- a/arch/arm64/boot/dts/arm/foundation-v8.dtsi
+++ b/arch/arm64/boot/dts/arm/foundation-v8.dtsi
@@ -58,6 +58,7 @@
L2_0: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
@@ -84,6 +85,11 @@
<GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
};
+ spe-pmu {
+ compatible = "arm,statistical-profiling-extension-v1";
+ interrupts = <GIC_PPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
watchdog@2a440000 {
compatible = "arm,sbsa-gwdt";
reg = <0x0 0x2a440000 0 0x1000>,
diff --git a/arch/arm64/boot/dts/arm/fvp-base-revc.dts b/arch/arm64/boot/dts/arm/fvp-base-revc.dts
index 5f6f30c801a7..60472d65a355 100644
--- a/arch/arm64/boot/dts/arm/fvp-base-revc.dts
+++ b/arch/arm64/boot/dts/arm/fvp-base-revc.dts
@@ -47,48 +47,121 @@
compatible = "arm,armv8";
reg = <0x0 0x000>;
enable-method = "psci";
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&C0_L2>;
};
cpu1: cpu@100 {
device_type = "cpu";
compatible = "arm,armv8";
reg = <0x0 0x100>;
enable-method = "psci";
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&C0_L2>;
};
cpu2: cpu@200 {
device_type = "cpu";
compatible = "arm,armv8";
reg = <0x0 0x200>;
enable-method = "psci";
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&C0_L2>;
};
cpu3: cpu@300 {
device_type = "cpu";
compatible = "arm,armv8";
reg = <0x0 0x300>;
enable-method = "psci";
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&C0_L2>;
};
cpu4: cpu@10000 {
device_type = "cpu";
compatible = "arm,armv8";
reg = <0x0 0x10000>;
enable-method = "psci";
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&C1_L2>;
};
cpu5: cpu@10100 {
device_type = "cpu";
compatible = "arm,armv8";
reg = <0x0 0x10100>;
enable-method = "psci";
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&C1_L2>;
};
cpu6: cpu@10200 {
device_type = "cpu";
compatible = "arm,armv8";
reg = <0x0 0x10200>;
enable-method = "psci";
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&C1_L2>;
};
cpu7: cpu@10300 {
device_type = "cpu";
compatible = "arm,armv8";
reg = <0x0 0x10300>;
enable-method = "psci";
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <64>;
+ i-cache-sets = <256>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <64>;
+ d-cache-sets = <256>;
+ next-level-cache = <&C1_L2>;
+ };
+ C0_L2: l2-cache0 {
+ compatible = "cache";
+ cache-size = <0x80000>;
+ cache-line-size = <64>;
+ cache-sets = <512>;
+ cache-level = <2>;
+ cache-unified;
+ };
+
+ C1_L2: l2-cache1 {
+ compatible = "cache";
+ cache-size = <0x80000>;
+ cache-line-size = <64>;
+ cache-sets = <512>;
+ cache-level = <2>;
+ cache-unified;
};
};
diff --git a/arch/arm64/boot/dts/arm/juno-r1.dts b/arch/arm64/boot/dts/arm/juno-r1.dts
index 6451c62146fd..1d90eeebb37d 100644
--- a/arch/arm64/boot/dts/arm/juno-r1.dts
+++ b/arch/arm64/boot/dts/arm/juno-r1.dts
@@ -189,6 +189,7 @@
A57_L2: l2-cache0 {
compatible = "cache";
+ cache-unified;
cache-size = <0x200000>;
cache-line-size = <64>;
cache-sets = <2048>;
@@ -197,6 +198,7 @@
A53_L2: l2-cache1 {
compatible = "cache";
+ cache-unified;
cache-size = <0x100000>;
cache-line-size = <64>;
cache-sets = <1024>;
diff --git a/arch/arm64/boot/dts/arm/juno-r2.dts b/arch/arm64/boot/dts/arm/juno-r2.dts
index 438cd1ff4bd0..d2ada69b0a43 100644
--- a/arch/arm64/boot/dts/arm/juno-r2.dts
+++ b/arch/arm64/boot/dts/arm/juno-r2.dts
@@ -195,6 +195,7 @@
A72_L2: l2-cache0 {
compatible = "cache";
+ cache-unified;
cache-size = <0x200000>;
cache-line-size = <64>;
cache-sets = <2048>;
@@ -203,6 +204,7 @@
A53_L2: l2-cache1 {
compatible = "cache";
+ cache-unified;
cache-size = <0x100000>;
cache-line-size = <64>;
cache-sets = <1024>;
diff --git a/arch/arm64/boot/dts/arm/juno.dts b/arch/arm64/boot/dts/arm/juno.dts
index cf4a58211399..5e48a01a5b9f 100644
--- a/arch/arm64/boot/dts/arm/juno.dts
+++ b/arch/arm64/boot/dts/arm/juno.dts
@@ -194,6 +194,7 @@
A57_L2: l2-cache0 {
compatible = "cache";
+ cache-unified;
cache-size = <0x200000>;
cache-line-size = <64>;
cache-sets = <2048>;
@@ -202,6 +203,7 @@
A53_L2: l2-cache1 {
compatible = "cache";
+ cache-unified;
cache-size = <0x100000>;
cache-line-size = <64>;
cache-sets = <1024>;
diff --git a/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts
index 258991ad7cc0..ef68f5aae7dd 100644
--- a/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts
+++ b/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts
@@ -71,6 +71,7 @@
L2_0: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts b/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts
index 5b6d9d8e934d..796cd7d02eb5 100644
--- a/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts
+++ b/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts
@@ -57,6 +57,7 @@
L2_0: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908.dtsi
index dac9d3b4e91d..eb2a78f4e033 100644
--- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908.dtsi
+++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4908.dtsi
@@ -63,6 +63,7 @@
l2: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
@@ -283,6 +284,11 @@
#address-cells = <1>;
#size-cells = <1>;
+ timer@0 {
+ compatible = "brcm,bcm63138-timer";
+ reg = <0x0 0x28>;
+ };
+
watchdog@28 {
compatible = "brcm,bcm6345-wdt";
reg = <0x28 0x8>;
diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4912.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4912.dtsi
index 3d016c2ce675..d5bc31980f03 100644
--- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm4912.dtsi
+++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm4912.dtsi
@@ -51,6 +51,7 @@
L2_0: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm63146.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm63146.dtsi
index 04de96bd0a03..6f805266d3c9 100644
--- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm63146.dtsi
+++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm63146.dtsi
@@ -35,6 +35,7 @@
L2_0: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm63158.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm63158.dtsi
index 13629702f70b..b982249b80a2 100644
--- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm63158.dtsi
+++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm63158.dtsi
@@ -51,6 +51,7 @@
L2_0: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm6813.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm6813.dtsi
index c3e6197be808..a996d436e977 100644
--- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm6813.dtsi
+++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm6813.dtsi
@@ -51,6 +51,7 @@
L2_0: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm6856.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm6856.dtsi
index 0bce6497219f..62c530d4b103 100644
--- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm6856.dtsi
+++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm6856.dtsi
@@ -35,6 +35,7 @@
L2_0: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/broadcom/bcmbca/bcm6858.dtsi b/arch/arm64/boot/dts/broadcom/bcmbca/bcm6858.dtsi
index 29a880c6c858..34c7b513d363 100644
--- a/arch/arm64/boot/dts/broadcom/bcmbca/bcm6858.dtsi
+++ b/arch/arm64/boot/dts/broadcom/bcmbca/bcm6858.dtsi
@@ -50,6 +50,7 @@
};
L2_0: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
@@ -109,6 +110,25 @@
#size-cells = <1>;
ranges = <0x0 0x0 0xff800000 0x62000>;
+ twd: timer-mfd@400 {
+ compatible = "brcm,bcm4908-twd", "simple-mfd", "syscon";
+ reg = <0x400 0x4c>;
+ ranges = <0x0 0x400 0x4c>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ timer@0 {
+ compatible = "brcm,bcm63138-timer";
+ reg = <0x0 0x28>;
+ };
+
+ watchdog@28 {
+ compatible = "brcm,bcm6345-wdt";
+ reg = <0x28 0x8>;
+ };
+ };
+
uart0: serial@640 {
compatible = "brcm,bcm6345-uart";
reg = <0x640 0x18>;
diff --git a/arch/arm64/boot/dts/broadcom/northstar2/ns2-svk.dts b/arch/arm64/boot/dts/broadcom/northstar2/ns2-svk.dts
index e34172e3117e..fbf0392b8371 100644
--- a/arch/arm64/boot/dts/broadcom/northstar2/ns2-svk.dts
+++ b/arch/arm64/boot/dts/broadcom/northstar2/ns2-svk.dts
@@ -52,7 +52,7 @@
memory {
device_type = "memory";
- reg = <0x000000000 0x80000000 0x00000000 0x40000000>;
+ reg = <0x00000000 0x80000000 0x00000000 0x40000000>;
};
};
diff --git a/arch/arm64/boot/dts/broadcom/northstar2/ns2-xmc.dts b/arch/arm64/boot/dts/broadcom/northstar2/ns2-xmc.dts
index 7bf26f3e36bf..699f7742ce7f 100644
--- a/arch/arm64/boot/dts/broadcom/northstar2/ns2-xmc.dts
+++ b/arch/arm64/boot/dts/broadcom/northstar2/ns2-xmc.dts
@@ -49,7 +49,7 @@
memory {
device_type = "memory";
- reg = <0x000000000 0x80000000 0x00000001 0x00000000>;
+ reg = <0x00000000 0x80000000 0x00000001 0x00000000>;
};
};
diff --git a/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi b/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi
index fda97c47f4e9..18cdbc20f03f 100644
--- a/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi
+++ b/arch/arm64/boot/dts/broadcom/northstar2/ns2.dtsi
@@ -79,6 +79,7 @@
CLUSTER0_L2: l2-cache@0 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi b/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi
index 8f8c25e51194..e05901abe957 100644
--- a/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi
+++ b/arch/arm64/boot/dts/broadcom/stingray/stingray.dtsi
@@ -108,18 +108,22 @@
CLUSTER0_L2: l2-cache@0 {
compatible = "cache";
+ cache-level = <2>;
};
CLUSTER1_L2: l2-cache@100 {
compatible = "cache";
+ cache-level = <2>;
};
CLUSTER2_L2: l2-cache@200 {
compatible = "cache";
+ cache-level = <2>;
};
CLUSTER3_L2: l2-cache@300 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/Makefile b/arch/arm64/boot/dts/freescale/Makefile
index 3ea9edc87909..ef6f364eaa18 100644
--- a/arch/arm64/boot/dts/freescale/Makefile
+++ b/arch/arm64/boot/dts/freescale/Makefile
@@ -57,10 +57,12 @@ dtb-$(CONFIG_ARCH_MXC) += imx8mm-emcon-avari.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-icore-mx8mm-ctouch2.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-icore-mx8mm-edimm2.2.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mm-innocomm-wb15-evk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-kontron-bl.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-kontron-bl-osm-s.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-mx8menlo.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-nitrogen-r2.dtb
+dtb-$(CONFIG_ARCH_MXC) += imx8mm-phg.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-phyboard-polis-rdk.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-tqma8mqml-mba8mx.dtb
dtb-$(CONFIG_ARCH_MXC) += imx8mm-var-som-symphony.dtb
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dtso
index f826392c23fa..f826392c23fa 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-13bb.dtso
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-65bb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-65bb.dtso
index b949cac03742..b949cac03742 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-65bb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-65bb.dtso
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-7777.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-7777.dtso
index 1dff68d7484b..1dff68d7484b 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-7777.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-7777.dtso
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-85bb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-85bb.dtso
index 19424d349713..19424d349713 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-85bb.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-85bb.dtso
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-899b.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-899b.dtso
index fb85847f778f..fb85847f778f 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-899b.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-899b.dtso
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-9999.dts b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-9999.dtso
index 63e46fad22bd..63e46fad22bd 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-9999.dts
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a-qds-9999.dtso
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
index ac1c3a7e5f7a..1b33cabb4e14 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
@@ -46,6 +46,7 @@
l2: l2-cache {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
index 704f72caddd3..b9fd24cdc919 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
@@ -84,6 +84,7 @@
l2: l2-cache {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
index 3d9e29824bb2..a01e3cfec77f 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
@@ -79,6 +79,7 @@
l2: l2-cache {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
index a2cadf757148..1e5d76c4d83d 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
@@ -95,18 +95,22 @@
cluster0_l2: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
cluster1_l2: l2-cache1 {
compatible = "cache";
+ cache-level = <2>;
};
cluster2_l2: l2-cache2 {
compatible = "cache";
+ cache-level = <2>;
};
cluster3_l2: l2-cache3 {
compatible = "cache";
+ cache-level = <2>;
};
CPU_PW20: cpu-pw20 {
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi
index c3dc38188c17..c12c86915ec8 100644
--- a/arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi
@@ -95,18 +95,22 @@
cluster0_l2: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
cluster1_l2: l2-cache1 {
compatible = "cache";
+ cache-level = <2>;
};
cluster2_l2: l2-cache2 {
compatible = "cache";
+ cache-level = <2>;
};
cluster3_l2: l2-cache3 {
compatible = "cache";
+ cache-level = <2>;
};
CPU_PW20: cpu-pw20 {
diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
index 8c76d86cb756..50c19e8405d5 100644
--- a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
+++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi
@@ -300,6 +300,7 @@
cluster0_l2: l2-cache0 {
compatible = "cache";
+ cache-unified;
cache-size = <0x100000>;
cache-line-size = <64>;
cache-sets = <1024>;
@@ -308,6 +309,7 @@
cluster1_l2: l2-cache1 {
compatible = "cache";
+ cache-unified;
cache-size = <0x100000>;
cache-line-size = <64>;
cache-sets = <1024>;
@@ -316,6 +318,7 @@
cluster2_l2: l2-cache2 {
compatible = "cache";
+ cache-unified;
cache-size = <0x100000>;
cache-line-size = <64>;
cache-sets = <1024>;
@@ -324,6 +327,7 @@
cluster3_l2: l2-cache3 {
compatible = "cache";
+ cache-unified;
cache-size = <0x100000>;
cache-line-size = <64>;
cache-sets = <1024>;
@@ -332,6 +336,7 @@
cluster4_l2: l2-cache4 {
compatible = "cache";
+ cache-unified;
cache-size = <0x100000>;
cache-line-size = <64>;
cache-sets = <1024>;
@@ -340,6 +345,7 @@
cluster5_l2: l2-cache5 {
compatible = "cache";
+ cache-unified;
cache-size = <0x100000>;
cache-line-size = <64>;
cache-sets = <1024>;
@@ -348,6 +354,7 @@
cluster6_l2: l2-cache6 {
compatible = "cache";
+ cache-unified;
cache-size = <0x100000>;
cache-line-size = <64>;
cache-sets = <1024>;
@@ -356,6 +363,7 @@
cluster7_l2: l2-cache7 {
compatible = "cache";
+ cache-unified;
cache-size = <0x100000>;
cache-line-size = <64>;
cache-sets = <1024>;
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
index 10370d1a6c6d..4852760adeee 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi
@@ -34,6 +34,35 @@ conn_subsys: bus@5b000000 {
clock-output-names = "conn_ipg_clk";
};
+ usbotg1: usb@5b0d0000 {
+ compatible = "fsl,imx7ulp-usb";
+ reg = <0x5b0d0000 0x200>;
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>;
+ fsl,usbphy = <&usbphy1>;
+ fsl,usbmisc = <&usbmisc1 0>;
+ clocks = <&usb2_lpcg 0>;
+ ahb-burst-config = <0x0>;
+ tx-burst-size-dword = <0x10>;
+ rx-burst-size-dword = <0x10>;
+ power-domains = <&pd IMX_SC_R_USB_0>;
+ status = "disabled";
+ };
+
+ usbmisc1: usbmisc@5b0d0200 {
+ #index-cells = <1>;
+ compatible = "fsl,imx7ulp-usbmisc", "fsl,imx6q-usbmisc";
+ reg = <0x5b0d0200 0x200>;
+ };
+
+ usbphy1: usbphy@5b100000 {
+ compatible = "fsl,imx7ulp-usbphy";
+ reg = <0x5b100000 0x1000>;
+ clocks = <&usb2_lpcg 1>;
+ power-domains = <&pd IMX_SC_R_USB_0_PHY>;
+ status = "disabled";
+ };
+
usdhc1: mmc@5b010000 {
interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>;
reg = <0x5b010000 0x10000>;
@@ -195,4 +224,14 @@ conn_subsys: bus@5b000000 {
"enet1_lpcg_ipg_s_clk";
power-domains = <&pd IMX_SC_R_ENET_1>;
};
+
+ usb2_lpcg: clock-controller@5b270000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5b270000 0x10000>;
+ #clock-cells = <1>;
+ clocks = <&conn_ahb_clk>, <&conn_ipg_clk>;
+ clock-indices = <IMX_LPCG_CLK_6>, <IMX_LPCG_CLK_7>;
+ clock-output-names = "usboh3_ahb_clk", "usboh3_phy_ipg_clk";
+ power-domains = <&pd IMX_SC_R_USB_0_PHY>;
+ };
};
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
index d7b4229bb4a2..a943a1e2797f 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-dma.dtsi
@@ -20,6 +20,70 @@ dma_subsys: bus@5a000000 {
clock-output-names = "dma_ipg_clk";
};
+ lpspi0: spi@5a000000 {
+ compatible = "fsl,imx7ulp-spi";
+ reg = <0x5a000000 0x10000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+ clocks = <&spi0_lpcg 0>,
+ <&spi0_lpcg 1>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_SPI_0 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <20000000>;
+ power-domains = <&pd IMX_SC_R_SPI_0>;
+ status = "disabled";
+ };
+
+ lpspi1: spi@5a010000 {
+ compatible = "fsl,imx7ulp-spi";
+ reg = <0x5a010000 0x10000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+ clocks = <&spi1_lpcg 0>,
+ <&spi1_lpcg 1>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_SPI_1 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <60000000>;
+ power-domains = <&pd IMX_SC_R_SPI_1>;
+ status = "disabled";
+ };
+
+ lpspi2: spi@5a020000 {
+ compatible = "fsl,imx7ulp-spi";
+ reg = <0x5a020000 0x10000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+ clocks = <&spi2_lpcg 0>,
+ <&spi2_lpcg 1>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_SPI_2 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <60000000>;
+ power-domains = <&pd IMX_SC_R_SPI_2>;
+ status = "disabled";
+ };
+
+ lpspi3: spi@5a030000 {
+ compatible = "fsl,imx7ulp-spi";
+ reg = <0x5a030000 0x10000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+ clocks = <&spi3_lpcg 0>,
+ <&spi3_lpcg 1>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_SPI_3 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <60000000>;
+ power-domains = <&pd IMX_SC_R_SPI_3>;
+ status = "disabled";
+ };
+
lpuart0: serial@5a060000 {
reg = <0x5a060000 0x1000>;
interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
@@ -60,6 +124,54 @@ dma_subsys: bus@5a000000 {
status = "disabled";
};
+ spi0_lpcg: clock-controller@5a400000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5a400000 0x10000>;
+ #clock-cells = <1>;
+ clocks = <&clk IMX_SC_R_SPI_0 IMX_SC_PM_CLK_PER>,
+ <&dma_ipg_clk>;
+ clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_4>;
+ clock-output-names = "spi0_lpcg_clk",
+ "spi0_lpcg_ipg_clk";
+ power-domains = <&pd IMX_SC_R_SPI_0>;
+ };
+
+ spi1_lpcg: clock-controller@5a410000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5a410000 0x10000>;
+ #clock-cells = <1>;
+ clocks = <&clk IMX_SC_R_SPI_1 IMX_SC_PM_CLK_PER>,
+ <&dma_ipg_clk>;
+ clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_4>;
+ clock-output-names = "spi1_lpcg_clk",
+ "spi1_lpcg_ipg_clk";
+ power-domains = <&pd IMX_SC_R_SPI_1>;
+ };
+
+ spi2_lpcg: clock-controller@5a420000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5a420000 0x10000>;
+ #clock-cells = <1>;
+ clocks = <&clk IMX_SC_R_SPI_2 IMX_SC_PM_CLK_PER>,
+ <&dma_ipg_clk>;
+ clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_4>;
+ clock-output-names = "spi2_lpcg_clk",
+ "spi2_lpcg_ipg_clk";
+ power-domains = <&pd IMX_SC_R_SPI_2>;
+ };
+
+ spi3_lpcg: clock-controller@5a430000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5a430000 0x10000>;
+ #clock-cells = <1>;
+ clocks = <&clk IMX_SC_R_SPI_3 IMX_SC_PM_CLK_PER>,
+ <&dma_ipg_clk>;
+ clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_4>;
+ clock-output-names = "spi3_lpcg_clk",
+ "spi3_lpcg_ipg_clk";
+ power-domains = <&pd IMX_SC_R_SPI_3>;
+ };
+
uart0_lpcg: clock-controller@5a460000 {
compatible = "fsl,imx8qxp-lpcg";
reg = <0x5a460000 0x10000>;
@@ -156,6 +268,34 @@ dma_subsys: bus@5a000000 {
status = "disabled";
};
+ adc0: adc@5a880000 {
+ compatible = "nxp,imx8qxp-adc";
+ reg = <0x5a880000 0x10000>;
+ interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+ clocks = <&adc0_lpcg 0>,
+ <&adc0_lpcg 1>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_ADC_0 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+ power-domains = <&pd IMX_SC_R_ADC_0>;
+ status = "disabled";
+ };
+
+ adc1: adc@5a890000 {
+ compatible = "nxp,imx8qxp-adc";
+ reg = <0x5a890000 0x10000>;
+ interrupts = <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gic>;
+ clocks = <&adc1_lpcg 0>,
+ <&adc1_lpcg 1>;
+ clock-names = "per", "ipg";
+ assigned-clocks = <&clk IMX_SC_R_ADC_1 IMX_SC_PM_CLK_PER>;
+ assigned-clock-rates = <24000000>;
+ power-domains = <&pd IMX_SC_R_ADC_1>;
+ status = "disabled";
+ };
+
i2c0_lpcg: clock-controller@5ac00000 {
compatible = "fsl,imx8qxp-lpcg";
reg = <0x5ac00000 0x10000>;
@@ -203,4 +343,28 @@ dma_subsys: bus@5a000000 {
"i2c3_lpcg_ipg_clk";
power-domains = <&pd IMX_SC_R_I2C_3>;
};
+
+ adc0_lpcg: clock-controller@5ac80000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5ac80000 0x10000>;
+ #clock-cells = <1>;
+ clocks = <&clk IMX_SC_R_ADC_0 IMX_SC_PM_CLK_PER>,
+ <&dma_ipg_clk>;
+ clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_4>;
+ clock-output-names = "adc0_lpcg_clk",
+ "adc0_lpcg_ipg_clk";
+ power-domains = <&pd IMX_SC_R_ADC_0>;
+ };
+
+ adc1_lpcg: clock-controller@5ac90000 {
+ compatible = "fsl,imx8qxp-lpcg";
+ reg = <0x5ac90000 0x10000>;
+ #clock-cells = <1>;
+ clocks = <&clk IMX_SC_R_ADC_1 IMX_SC_PM_CLK_PER>,
+ <&dma_ipg_clk>;
+ clock-indices = <IMX_LPCG_CLK_0>, <IMX_LPCG_CLK_4>;
+ clock-output-names = "adc1_lpcg_clk",
+ "adc1_lpcg_ipg_clk";
+ power-domains = <&pd IMX_SC_R_ADC_1>;
+ };
};
diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi
index 6446e6df7a9a..1f3d225e64ec 100644
--- a/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8-ss-lsio.dtsi
@@ -11,7 +11,8 @@ lsio_subsys: bus@5d000000 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
- ranges = <0x5d000000 0x0 0x5d000000 0x1000000>;
+ ranges = <0x5d000000 0x0 0x5d000000 0x1000000>,
+ <0x08000000 0x0 0x08000000 0x10000000>;
lsio_mem_clk: clock-lsio-mem {
compatible = "fixed-clock";
@@ -107,6 +108,20 @@ lsio_subsys: bus@5d000000 {
power-domains = <&pd IMX_SC_R_GPIO_7>;
};
+ flexspi0: spi@5d120000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "nxp,imx8qxp-fspi";
+ reg = <0x5d120000 0x10000>, <0x08000000 0x10000000>;
+ reg-names = "fspi_base", "fspi_mmap";
+ interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX_SC_R_FSPI_0 IMX_SC_PM_CLK_PER>,
+ <&clk IMX_SC_R_FSPI_0 IMX_SC_PM_CLK_PER>;
+ clock-names = "fspi", "fspi_en";
+ power-domains = <&pd IMX_SC_R_FSPI_0>;
+ status = "disabled";
+ };
+
lsio_mu0: mailbox@5d1b0000 {
reg = <0x5d1b0000 0x10000>;
interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts b/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
index ca2a43e0cbf6..280a9c9d8bd9 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-evk.dts
@@ -90,6 +90,28 @@
enable-active-high;
off-on-delay-us = <3480>;
};
+
+ reg_vref_1v8: regulator-adc-vref {
+ compatible = "regulator-fixed";
+ regulator-name = "vref_1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ mii_select: regulator-4 {
+ compatible = "regulator-fixed";
+ regulator-name = "mii-select";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&scu_gpio 6 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+};
+
+&adc0 {
+ vref-supply = <&reg_vref_1v8>;
+ status = "okay";
};
&eqos {
@@ -159,6 +181,23 @@
};
};
+&flexspi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexspi0>;
+ nxp,fspi-dll-slvdly = <4>;
+ status = "okay";
+
+ mt35xu512aba0: flash@0 {
+ reg = <0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "jedec,spi-nor";
+ spi-max-frequency = <133000000>;
+ spi-tx-bus-width = <8>;
+ spi-rx-bus-width = <8>;
+ };
+};
+
&i2c2 {
#address-cells = <1>;
#size-cells = <0>;
@@ -266,6 +305,40 @@
};
};
+&usbphy1 {
+ /* USB eye diagram tests result */
+ fsl,tx-d-cal = <114>;
+ status = "okay";
+};
+
+&usbotg1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg1>;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ power-active-high;
+ disable-over-current;
+ status = "okay";
+};
+
+&usbphy2 {
+ /* USB eye diagram tests result */
+ fsl,tx-d-cal = <111>;
+ status = "okay";
+};
+
+&usbotg2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg2>;
+ srp-disable;
+ hnp-disable;
+ adp-disable;
+ power-active-high;
+ disable-over-current;
+ status = "okay";
+};
+
&usdhc1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_usdhc1>;
@@ -286,6 +359,21 @@
status = "okay";
};
+&lpspi3 {
+ fsl,spi-num-chipselects = <1>;
+ fsl,spi-only-use-cs1-sel;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lpspi3>;
+ pinctrl-assert-gpios = <&pca6416_1 7 GPIO_ACTIVE_HIGH>;
+ status = "okay";
+
+ spidev0: spi@0 {
+ reg = <0>;
+ compatible = "rohm,dh2228fv";
+ spi-max-frequency = <30000000>;
+ };
+};
+
&iomuxc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_hog>;
@@ -330,6 +418,25 @@
>;
};
+ pinctrl_flexspi0: flexspi0grp {
+ fsl,pins = <
+ IMX8DXL_QSPI0A_DATA0_LSIO_QSPI0A_DATA0 0x06000021
+ IMX8DXL_QSPI0A_DATA1_LSIO_QSPI0A_DATA1 0x06000021
+ IMX8DXL_QSPI0A_DATA2_LSIO_QSPI0A_DATA2 0x06000021
+ IMX8DXL_QSPI0A_DATA3_LSIO_QSPI0A_DATA3 0x06000021
+ IMX8DXL_QSPI0A_DQS_LSIO_QSPI0A_DQS 0x06000021
+ IMX8DXL_QSPI0A_SS0_B_LSIO_QSPI0A_SS0_B 0x06000021
+ IMX8DXL_QSPI0A_SCLK_LSIO_QSPI0A_SCLK 0x06000021
+ IMX8DXL_QSPI0B_SCLK_LSIO_QSPI0B_SCLK 0x06000021
+ IMX8DXL_QSPI0B_DATA0_LSIO_QSPI0B_DATA0 0x06000021
+ IMX8DXL_QSPI0B_DATA1_LSIO_QSPI0B_DATA1 0x06000021
+ IMX8DXL_QSPI0B_DATA2_LSIO_QSPI0B_DATA2 0x06000021
+ IMX8DXL_QSPI0B_DATA3_LSIO_QSPI0B_DATA3 0x06000021
+ IMX8DXL_QSPI0B_DQS_LSIO_QSPI0B_DQS 0x06000021
+ IMX8DXL_QSPI0B_SS0_B_LSIO_QSPI0B_SS0_B 0x06000021
+ >;
+ };
+
pinctrl_fec1: fec1grp {
fsl,pins = <
IMX8DXL_COMP_CTL_GPIO_1V8_3V3_ENET_ENETB0_PAD 0x000014a0
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi
index 795d1d472fae..6881330ab4c6 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-ss-adma.dtsi
@@ -11,6 +11,10 @@
clock-frequency = <160000000>;
};
+&adc0 {
+ interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
+};
+
&i2c0 {
compatible = "fsl,imx8dxl-lpi2c", "fsl,imx8qxp-lpi2c", "fsl,imx7ulp-lpi2c";
interrupts = <GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>;
@@ -50,3 +54,19 @@
compatible = "fsl,imx8qxp-lpuart", "fsl,imx7ulp-lpuart";
interrupts = <GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>;
};
+
+&lpspi0 {
+ interrupts = <GIC_SPI 218 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&lpspi1 {
+ interrupts = <GIC_SPI 219 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&lpspi2 {
+ interrupts = <GIC_SPI 220 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&lpspi3 {
+ interrupts = <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi
index 69c4849f2132..6b416fb760d5 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-ss-conn.dtsi
@@ -140,3 +140,13 @@
compatible = "fsl,imx8dxl-usdhc", "fsl,imx8qxp-usdhc";
interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
};
+
+&usbotg1 {
+ interrupts = <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
+ /*
+ * usbotg1 and usbotg2 share one clock
+ * scfw disable clock access and keep it always on
+ * in case other core (M4) use one of these.
+ */
+ clocks = <&clk_dummy>;
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl-ss-lsio.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl-ss-lsio.dtsi
index 815bd987b09b..5f4f789e4a73 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl-ss-lsio.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8dxl-ss-lsio.dtsi
@@ -3,44 +3,90 @@
* Copyright 2019~2020, 2022 NXP
*/
+&flexspi0 {
+ compatible = "nxp,imx8dxl-fspi";
+ interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
+};
+
&lsio_gpio0 {
compatible = "fsl,imx8dxl-gpio", "fsl,imx35-gpio";
interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-ranges = <&iomuxc 0 47 13>,
+ <&iomuxc 13 61 4>,
+ <&iomuxc 19 67 4>,
+ <&iomuxc 24 72 1>;
};
&lsio_gpio1 {
compatible = "fsl,imx8dxl-gpio", "fsl,imx35-gpio";
interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-ranges = <&iomuxc 4 74 5>,
+ <&iomuxc 9 80 16>;
};
&lsio_gpio2 {
compatible = "fsl,imx8dxl-gpio", "fsl,imx35-gpio";
interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-ranges = <&iomuxc 1 98 2>,
+ <&iomuxc 3 101 1>,
+ <&iomuxc 5 107 8>;
};
&lsio_gpio3 {
compatible = "fsl,imx8dxl-gpio", "fsl,imx35-gpio";
interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-ranges = <&iomuxc 0 115 4>,
+ <&iomuxc 9 121 1>,
+ <&iomuxc 10 120 1>,
+ <&iomuxc 11 123 1>,
+ <&iomuxc 12 122 1>,
+ <&iomuxc 13 125 1>,
+ <&iomuxc 14 124 1>,
+ <&iomuxc 16 126 1>,
+ <&iomuxc 17 128 1>,
+ <&iomuxc 18 131 1>,
+ <&iomuxc 19 130 1>,
+ <&iomuxc 20 133 1>,
+ <&iomuxc 21 132 1>,
+ <&iomuxc 22 129 1>,
+ <&iomuxc 23 134 1>;
};
&lsio_gpio4 {
compatible = "fsl,imx8dxl-gpio", "fsl,imx35-gpio";
interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-ranges = <&iomuxc 0 0 3>,
+ <&iomuxc 3 4 4>,
+ <&iomuxc 7 9 12>,
+ <&iomuxc 19 22 2>,
+ <&iomuxc 21 25 2>,
+ <&iomuxc 29 29 3>;
};
&lsio_gpio5 {
compatible = "fsl,imx8dxl-gpio", "fsl,imx35-gpio";
interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-ranges = <&iomuxc 0 32 3>,
+ <&iomuxc 3 36 6>,
+ <&iomuxc 9 43 3>;
};
&lsio_gpio6 {
compatible = "fsl,imx8dxl-gpio", "fsl,imx35-gpio";
interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-ranges = <&iomuxc 0 53 7>,
+ <&iomuxc 8 86 10>,
+ <&iomuxc 19 107 8>;
};
&lsio_gpio7 {
compatible = "fsl,imx8dxl-gpio", "fsl,imx35-gpio";
interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-ranges = <&iomuxc 0 0 3>,
+ <&iomuxc 3 4 4>,
+ <&iomuxc 8 22 2>,
+ <&iomuxc 10 25 2>,
+ <&iomuxc 16 44 2>;
};
&lsio_mu0 {
diff --git a/arch/arm64/boot/dts/freescale/imx8dxl.dtsi b/arch/arm64/boot/dts/freescale/imx8dxl.dtsi
index 5ddbda0b4def..0c64b9194621 100644
--- a/arch/arm64/boot/dts/freescale/imx8dxl.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8dxl.dtsi
@@ -59,6 +59,7 @@
A35_L2: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
@@ -133,6 +134,12 @@
clock-names = "xtal_32KHz", "xtal_24Mhz";
};
+ scu_gpio: gpio {
+ compatible = "fsl,imx8qxp-sc-gpio";
+ gpio-controller;
+ #gpio-cells = <2>;
+ };
+
iomuxc: pinctrl {
compatible = "fsl,imx8dxl-iomuxc";
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-beacon-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-beacon-som.dtsi
index cf07987ccc10..201325f566cb 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-beacon-som.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-beacon-som.dtsi
@@ -47,15 +47,15 @@
ddrc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-25M {
+ opp-25000000 {
opp-hz = /bits/ 64 <25000000>;
};
- opp-100M {
+ opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
};
- opp-750M {
+ opp-750000000 {
opp-hz = /bits/ 64 <750000000>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc.dts b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc.dts
index 778bdbe228d3..24f61db33eba 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-data-modul-edm-sbc.dts
@@ -46,6 +46,12 @@
clock-frequency = <25000000>;
};
+ clk_xtal32k: clk-xtal32k {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ };
+
panel: panel {
backlight = <&backlight>;
power-supply = <&reg_panel_vcc>;
@@ -77,12 +83,11 @@
enable-active-high;
};
- watchdog-gpio {
+ watchdog {
/* TPS3813 */
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_watchdog_gpio>;
compatible = "linux,wdt-gpio";
- always-enabled;
gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>;
hw_algo = "level";
/* Reset triggers in 2..3 seconds */
@@ -114,15 +119,15 @@
ddrc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-25M {
+ opp-25000000 {
opp-hz = /bits/ 64 <25000000>;
};
- opp-100M {
+ opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
};
- opp-750M {
+ opp-750000000 {
opp-hz = /bits/ 64 <750000000>;
};
};
@@ -183,8 +188,6 @@
reset-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>;
reset-assert-us = <10000>;
reset-deassert-us = <10000>;
- qca,clk-out-frequency = <125000000>;
- qca,clk-out-strength = <AR803X_STRENGTH_FULL>;
qca,keep-pll-enabled;
vddio-supply = <&vddio>;
@@ -271,6 +274,9 @@
pmic: pmic@4b {
compatible = "rohm,bd71847";
reg = <0x4b>;
+ #clock-cells = <0>;
+ clocks = <&clk_xtal32k 0>;
+ clock-output-names = "clk-32k-out";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pmic>;
interrupt-parent = <&gpio1>;
@@ -928,6 +934,10 @@
status = "disabled";
};
+&snvs_rtc {
+ clocks = <&pmic>;
+};
+
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart1>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk.dts b/arch/arm64/boot/dts/freescale/imx8mm-evk.dts
index a2b24d4d4e3e..b68954bcc383 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-evk.dts
@@ -23,15 +23,15 @@
ddrc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-25M {
+ opp-25000000 {
opp-hz = /bits/ 64 <25000000>;
};
- opp-100M {
+ opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
};
- opp-750M {
+ opp-750000000 {
opp-hz = /bits/ 64 <750000000>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
index 7d6317d95b13..e0b604ac0da4 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi
@@ -56,6 +56,7 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+ off-on-delay-us = <20000>;
enable-active-high;
};
@@ -343,6 +344,7 @@
reg = <0x20>;
gpio-controller;
#gpio-cells = <2>;
+ vcc-supply = <&buck4_reg>;
};
};
@@ -399,6 +401,10 @@
status = "okay";
};
+&usbphynop1 {
+ wakeup-source;
+};
+
&usbotg1 {
dr_mode = "otg";
hnp-disable;
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-innocomm-wb15-evk.dts b/arch/arm64/boot/dts/freescale/imx8mm-innocomm-wb15-evk.dts
new file mode 100644
index 000000000000..055faae79930
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-innocomm-wb15-evk.dts
@@ -0,0 +1,146 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2018 Bang & Olufsen
+ * Copyright 2022 Pengutronix
+ */
+
+/dts-v1/;
+
+#include "imx8mm-innocomm-wb15.dtsi"
+
+/ {
+ model = "InnoComm WB15-EVK";
+ compatible = "innocomm,wb15-evk", "fsl,imx8mm";
+
+ chosen {
+ stdout-path = &uart2;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_leds>;
+
+ led-0 {
+ label = "debug";
+ gpios = <&gpio4 3 GPIO_ACTIVE_HIGH>;
+ default-state = "off";
+ };
+ };
+
+ reg_vsd_3v3: regulator-vsd-3v3 {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_vsd_3v3>;
+ regulator-name = "VSD_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_ethphy: regulator-eth-phy {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec_phy_reg>;
+ regulator-name = "PHY_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy0>;
+ fsl,magic-packet;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec_phy>;
+ reset-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>;
+ phy-supply = <&reg_ethphy>;
+ };
+ };
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&usbotg1 {
+ dr_mode = "otg";
+ samsung,picophy-pre-emp-curr-control = <3>;
+ samsung,picophy-dc-vol-level-adjust = <7>;
+ disable-over-current;
+ status = "okay";
+};
+
+&usbotg2 {
+ dr_mode = "host";
+ samsung,picophy-pre-emp-curr-control = <3>;
+ samsung,picophy-dc-vol-level-adjust = <7>;
+ disable-over-current;
+ status = "okay";
+};
+
+&usdhc2 {
+ cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&reg_vsd_3v3>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_fec: fec-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ENET_MDC_ENET1_MDC 0x03
+ MX8MM_IOMUXC_ENET_MDIO_ENET1_MDIO 0x03
+ MX8MM_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f
+ MX8MM_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f
+ MX8MM_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f
+ MX8MM_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f
+ MX8MM_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91
+ MX8MM_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91
+ MX8MM_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91
+ MX8MM_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91
+ MX8MM_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f
+ MX8MM_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91
+ MX8MM_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91
+ MX8MM_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f
+ >;
+ };
+
+ pinctrl_fec_phy: fec-phy-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x19
+ >;
+ };
+
+ pinctrl_fec_phy_reg: fec-phy-reg-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO10_GPIO1_IO10 0x16
+ >;
+ };
+
+ pinctrl_gpio_leds: led-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SAI1_RXD1_GPIO4_IO3 0xd6
+ >;
+ };
+
+ pinctrl_reg_vsd_3v3: reg-vsd-3v3-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_RESET_B_GPIO2_IO19 0x41
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-innocomm-wb15.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-innocomm-wb15.dtsi
new file mode 100644
index 000000000000..44e87b1568e7
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-innocomm-wb15.dtsi
@@ -0,0 +1,480 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2018 Bang & Olufsen
+ */
+
+#include "imx8mm.dtsi"
+#include <dt-bindings/phy/phy-imx8-pcie.h>
+
+/ {
+ reg_modem: regulator-modem {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_modem_regulator>;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-name = "epdev_on";
+ gpio = <&gpio3 16 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ };
+
+ reg_3v3_out: regulator-3v3-out {
+ compatible = "regulator-fixed";
+ regulator-name = "3V3_OUT";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+};
+
+&cpu_alert0 {
+ temperature = <95000>;
+};
+
+&cpu_crit0 {
+ temperature = <105000>;
+};
+
+&ddrc {
+ operating-points-v2 = <&ddrc_opp_table>;
+
+ ddrc_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-25000000 {
+ opp-hz = /bits/ 64 <25000000>;
+ };
+
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ };
+
+ opp-600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ };
+ };
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ pinctrl-1 = <&pinctrl_i2c1_gpio>;
+ scl-gpios = <&gpio5 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+
+ pmic@4b {
+ compatible = "rohm,bd71847";
+ reg = <0x4b>;
+ pinctrl-0 = <&pinctrl_pmic>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
+ rohm,reset-snvs-powered;
+
+ regulators {
+ buck1_reg: BUCK1 {
+ regulator-name = "buck1";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <1250>;
+ rohm,dvs-run-voltage = <850000>;
+ rohm,dvs-idle-voltage = <850000>;
+ rohm,dvs-suspend-voltage = <850000>;
+ };
+
+ buck2_reg: BUCK2 {
+ regulator-name = "buck2";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ regulator-ramp-delay = <1250>;
+ rohm,dvs-run-voltage = <1000000>;
+ rohm,dvs-idle-voltage = <900000>;
+ };
+
+ buck3_reg: BUCK3 {
+ // buck5 in datasheet
+ regulator-name = "buck3";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck4_reg: BUCK4 {
+ // buck6 in datasheet
+ regulator-name = "buck4";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck5_reg: BUCK5 {
+ // buck7 in datasheet
+ regulator-name = "buck5";
+ regulator-min-microvolt = <1605000>;
+ regulator-max-microvolt = <1995000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ buck6_reg: BUCK6 {
+ // buck8 in datasheet
+ regulator-name = "buck6";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1400000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo1_reg: LDO1 {
+ regulator-name = "ldo1";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo2_reg: LDO2 {
+ regulator-name = "ldo2";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <900000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo3_reg: LDO3 {
+ regulator-name = "ldo3";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo4_reg: LDO4 {
+ regulator-name = "ldo4";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ ldo5_reg: LDO5 {
+ regulator-name = "ldo5";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ ldo6_reg: LDO6 {
+ regulator-name = "ldo6";
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+ };
+ };
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ pinctrl-1 = <&pinctrl_i2c2_gpio>;
+ scl-gpios = <&gpio5 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ status = "okay";
+};
+
+&i2c3 {
+ pinctrl-names = "default", "gpio";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ pinctrl-1 = <&pinctrl_i2c3_gpio>;
+ scl-gpios = <&gpio5 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+};
+
+&pcie_phy {
+ fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_OUTPUT>;
+ fsl,tx-deemph-gen1 = <0x2d>;
+ fsl,tx-deemph-gen2 = <0xf>;
+ status = "okay";
+};
+
+&pcie0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pcie0>;
+ reset-gpio = <&gpio5 21 GPIO_ACTIVE_LOW>;
+ clocks = <&clk IMX8MM_CLK_PCIE1_ROOT>, <&clk IMX8MM_CLK_PCIE1_PHY>,
+ <&clk IMX8MM_CLK_PCIE1_AUX>;
+ clock-names = "pcie", "pcie_bus", "pcie_aux";
+ fsl,max-link-speed = <1>;
+ assigned-clocks = <&clk IMX8MM_CLK_PCIE1_AUX>, <&clk IMX8MM_CLK_PCIE1_CTRL>;
+ assigned-clock-rates = <10000000>, <250000000>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_50M>, <&clk IMX8MM_SYS_PLL2_250M>;
+ status = "okay";
+};
+
+&uart1 { /* BT */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ assigned-clocks = <&clk IMX8MM_CLK_UART1>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_80M>;
+ uart-has-rtscts;
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm4349-bt";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_modem_bt>;
+ device-wakeup-gpios = <&gpio3 3 GPIO_ACTIVE_HIGH>;
+ host-wakeup-gpios = <&gpio3 4 GPIO_ACTIVE_HIGH>;
+ shutdown-gpios = <&gpio3 15 GPIO_ACTIVE_HIGH>;
+ vbat-supply = <&reg_3v3_out>;
+ vddio-supply = <&reg_3v3_out>;
+ clocks = <&osc_32k>;
+ max-speed = <3000000>;
+ clock-names = "extclk";
+ };
+};
+
+&uart2 { /* console */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+};
+
+&usdhc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ bus-width = <8>;
+ no-sd;
+ no-sdio;
+ non-removable;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
+ bus-width = <4>;
+};
+
+&wdog1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_wdog>;
+ fsl,ext-reset-output;
+ status = "okay";
+};
+
+&A53_0 {
+ cpu-supply = <&buck2_reg>;
+};
+
+&A53_1 {
+ cpu-supply = <&buck2_reg>;
+};
+
+&A53_2 {
+ cpu-supply = <&buck2_reg>;
+};
+
+&A53_3 {
+ cpu-supply = <&buck2_reg>;
+};
+
+/delete-node/ &sec_jr1; /* Job ring in use by OP-TEE */
+
+&iomuxc {
+ pinctrl_i2c1: i2c1-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C1_SCL_I2C1_SCL 0x400001c3
+ MX8MM_IOMUXC_I2C1_SDA_I2C1_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_i2c1_gpio: i2c1-gpio-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C1_SCL_GPIO5_IO14 0x400001c3
+ MX8MM_IOMUXC_I2C1_SDA_GPIO5_IO15 0x400001c3
+ >;
+ };
+
+ pinctrl_i2c2: i2c2-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C2_SCL_I2C2_SCL 0x400001c3
+ MX8MM_IOMUXC_I2C2_SDA_I2C2_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_i2c2_gpio: i2c2-gpio-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C2_SCL_GPIO5_IO16 0x400001c3
+ MX8MM_IOMUXC_I2C2_SDA_GPIO5_IO17 0x400001c3
+ >;
+ };
+
+ pinctrl_i2c3: i2c3-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C3_SCL_I2C3_SCL 0x400001c3
+ MX8MM_IOMUXC_I2C3_SDA_I2C3_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_i2c3_gpio: i2c3-gpio-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C3_SCL_GPIO5_IO18 0x400001c3
+ MX8MM_IOMUXC_I2C3_SDA_GPIO5_IO19 0x400001c3
+ >;
+ };
+
+ pinctrl_pcie0: pcie0-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C4_SCL_PCIE1_CLKREQ_B 0x61
+ MX8MM_IOMUXC_I2C4_SDA_GPIO5_IO21 0x6
+ >;
+ };
+
+ pinctrl_modem_bt: modem-bt-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_CLE_GPIO3_IO5 0x19
+ MX8MM_IOMUXC_NAND_CE2_B_GPIO3_IO3 0x19
+ MX8MM_IOMUXC_NAND_CE3_B_GPIO3_IO4 0x19
+ MX8MM_IOMUXC_NAND_RE_B_GPIO3_IO15 0x19
+ MX8MM_IOMUXC_GPIO1_IO00_ANAMIX_REF_CLK_32K 0x141
+ >;
+ };
+
+ pinctrl_modem_regulator: modem-reg-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_NAND_READY_B_GPIO3_IO16 0x41
+ >;
+ };
+
+ pinctrl_pmic: pmic-irq-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x41
+ >;
+ };
+
+ pinctrl_uart1: uart1-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART1_RXD_UART1_DCE_RX 0x140
+ MX8MM_IOMUXC_UART1_TXD_UART1_DCE_TX 0x140
+ MX8MM_IOMUXC_UART3_RXD_UART1_DCE_CTS_B 0x140
+ MX8MM_IOMUXC_UART3_TXD_UART1_DCE_RTS_B 0x140
+ >;
+ };
+
+ pinctrl_uart2: uart2-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x140
+ MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX 0x140
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK 0x40000190
+ MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD 0x1d0
+ MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0 0x1d0
+ MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1 0x1d0
+ MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2 0x1d0
+ MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3 0x1d0
+ MX8MM_IOMUXC_SD1_DATA4_USDHC1_DATA4 0x1d0
+ MX8MM_IOMUXC_SD1_DATA5_USDHC1_DATA5 0x1d0
+ MX8MM_IOMUXC_SD1_DATA6_USDHC1_DATA6 0x1d0
+ MX8MM_IOMUXC_SD1_DATA7_USDHC1_DATA7 0x1d0
+ MX8MM_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x190
+ MX8MM_IOMUXC_SD1_RESET_B_USDHC1_RESET_B 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc1_100mhz: usdhc1-100mhz-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK 0x40000194
+ MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD 0x1d4
+ MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0 0x1d4
+ MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1 0x1d4
+ MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2 0x1d4
+ MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3 0x1d4
+ MX8MM_IOMUXC_SD1_DATA4_USDHC1_DATA4 0x1d4
+ MX8MM_IOMUXC_SD1_DATA5_USDHC1_DATA5 0x1d4
+ MX8MM_IOMUXC_SD1_DATA6_USDHC1_DATA6 0x1d4
+ MX8MM_IOMUXC_SD1_DATA7_USDHC1_DATA7 0x1d4
+ MX8MM_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x194
+ MX8MM_IOMUXC_SD1_RESET_B_USDHC1_RESET_B 0x1d4
+ >;
+ };
+
+ pinctrl_usdhc1_200mhz: usdhc1-200mhz-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_CLK_USDHC1_CLK 0x40000196
+ MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD 0x1d6
+ MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0 0x1d6
+ MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1 0x1d6
+ MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2 0x1d6
+ MX8MM_IOMUXC_SD1_DATA3_USDHC1_DATA3 0x1d6
+ MX8MM_IOMUXC_SD1_DATA4_USDHC1_DATA4 0x1d6
+ MX8MM_IOMUXC_SD1_DATA5_USDHC1_DATA5 0x1d6
+ MX8MM_IOMUXC_SD1_DATA6_USDHC1_DATA6 0x1d6
+ MX8MM_IOMUXC_SD1_DATA7_USDHC1_DATA7 0x1d6
+ MX8MM_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x196
+ MX8MM_IOMUXC_SD1_RESET_B_USDHC1_RESET_B 0x1d6
+ >;
+ };
+
+ pinctrl_usdhc2_gpio: usdhc2-gpio-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_RESET_B_GPIO2_IO19 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x190
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d0
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d0
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d0
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d0
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d0
+ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2-100mhz-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x194
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d4
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d4
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d4
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d4
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d4
+ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2-200mhz-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x196
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d6
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d6
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d6
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d6
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d6
+ MX8MM_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0x1d0
+ >;
+ };
+
+ pinctrl_wdog: wdog-grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-kontron-osm-s.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-kontron-osm-s.dtsi
index 8d10f5b41297..5172883717d1 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-kontron-osm-s.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-kontron-osm-s.dtsi
@@ -47,11 +47,11 @@
ddrc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-100M {
+ opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
};
- opp-750M {
+ opp-750000000 {
opp-hz = /bits/ 64 <750000000>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-kontron-sl.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-kontron-sl.dtsi
index 0679728d2489..1f8326613ee9 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-kontron-sl.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-kontron-sl.dtsi
@@ -46,11 +46,11 @@
ddrc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-100M {
+ opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
};
- opp-750M {
+ opp-750000000 {
opp-hz = /bits/ 64 <750000000>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-phg.dts b/arch/arm64/boot/dts/freescale/imx8mm-phg.dts
new file mode 100644
index 000000000000..e9447738b104
--- /dev/null
+++ b/arch/arm64/boot/dts/freescale/imx8mm-phg.dts
@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright 2022 Fabio Estevam <festevam@denx.de>
+ */
+
+/dts-v1/;
+
+#include "imx8mm-tqma8mqml.dtsi"
+
+/ {
+ model = "Cloos i.MX8MM PHG board";
+ compatible = "cloos,imx8mm-phg", "tq,imx8mm-tqma8mqml", "fsl,imx8mm";
+
+ aliases {
+ mmc0 = &usdhc3;
+ mmc1 = &usdhc2;
+ };
+
+ chosen {
+ stdout-path = &uart2;
+ };
+
+ beeper {
+ compatible = "gpio-beeper";
+ pinctrl-0 = <&pinctrl_beeper>;
+ gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_led>;
+
+ led-0 {
+ label = "status1";
+ gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>;
+ };
+
+ led-1 {
+ label = "status2";
+ gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>;
+ };
+
+ led-2 {
+ label = "status3";
+ gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
+ };
+
+ led-3 {
+ label = "run";
+ gpios = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+ };
+
+ led-4 {
+ label = "powerled";
+ gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ reg_usb_otg_vbus: regulator-usb-otg-vbus {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_otg_vbus_ctrl>;
+ regulator-name = "usb_otg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio2 2 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ reg_usdhc2_vmmc: regulator-vmmc {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_reg_usdhc2_vmmc>;
+ regulator-name = "VSD_3V3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ startup-delay-us = <100>;
+ off-on-delay-us = <12000>;
+ };
+};
+
+&ecspi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi1>;
+ cs-gpios = <&gpio5 9 GPIO_ACTIVE_LOW>;
+ status = "okay";
+};
+
+&fec1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_fec1>;
+ phy-mode = "rgmii-id";
+ phy-handle = <&ethphy0>;
+ fsl,magic-packet;
+ status = "okay";
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ethphy0: ethernet-phy@0 {
+ reg = <0>;
+ compatible = "ethernet-phy-ieee802.3-c22";
+ };
+ };
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ status = "okay";
+};
+
+&usbphynop1 {
+ power-domains = <&pgc_otg1>;
+};
+
+&usbphynop2 {
+ power-domains = <&pgc_otg2>;
+};
+
+&usbotg1 {
+ dr_mode = "host";
+ vbus-supply = <&reg_usb_otg_vbus>;
+ status = "okay";
+};
+
+&usbotg2 {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usdhc2 {
+ assigned-clocks = <&clk IMX8MM_CLK_USDHC2>;
+ assigned-clock-rates = <400000000>;
+ assigned-clock-parents = <&clk IMX8MM_SYS_PLL1_400M>;
+ pinctrl-names = "default", "state_100mhz", "state_200mhz";
+ pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>;
+ pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>;
+ bus-width = <4>;
+ cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ no-mmc;
+ no-sdio;
+ sd-uhs-sdr104;
+ sd-uhs-ddr50;
+ vmmc-supply = <&reg_usdhc2_vmmc>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl_beeper: beepergrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO00_GPIO1_IO0 0x19
+ >;
+ };
+
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ECSPI1_MISO_ECSPI1_MISO 0x82
+ MX8MM_IOMUXC_ECSPI1_MOSI_ECSPI1_MOSI 0x82
+ MX8MM_IOMUXC_ECSPI1_SCLK_ECSPI1_SCLK 0x82
+ MX8MM_IOMUXC_ECSPI1_SS0_GPIO5_IO9 0x19
+ >;
+ };
+
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_ENET_MDC_ENET1_MDC 0x40000002
+ MX8MM_IOMUXC_ENET_MDIO_ENET1_MDIO 0x40000002
+ MX8MM_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x14
+ MX8MM_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x14
+ MX8MM_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x14
+ MX8MM_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x14
+ MX8MM_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x90
+ MX8MM_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x90
+ MX8MM_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x90
+ MX8MM_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x90
+ MX8MM_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x14
+ MX8MM_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x90
+ MX8MM_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x90
+ MX8MM_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x14
+ MX8MM_IOMUXC_SAI2_RXC_GPIO4_IO22 0x10
+ >;
+ };
+
+ pinctrl_gpio_led: gpioledgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_GPIO1_IO10_GPIO1_IO10 0x19
+ MX8MM_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x19
+ MX8MM_IOMUXC_GPIO1_IO06_GPIO1_IO6 0x19
+ MX8MM_IOMUXC_GPIO1_IO07_GPIO1_IO7 0x19
+ MX8MM_IOMUXC_GPIO1_IO01_GPIO1_IO1 0x19
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C2_SCL_I2C2_SCL 0x400001c3
+ MX8MM_IOMUXC_I2C2_SDA_I2C2_SDA 0x400001c3
+ >;
+ };
+
+ pinctrl_otg_vbus_ctrl: otgvbusctrlgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD1_DATA0_GPIO2_IO2 0x119
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x140
+ MX8MM_IOMUXC_UART2_TXD_UART2_DCE_TX 0x140
+ >;
+ };
+
+ pinctrl_usdhc2_gpio: usdhc2grpgpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CD_B_GPIO2_IO12 0x1c4
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x190
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d0
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d0
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d0
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d0
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d0
+ >;
+ };
+
+ pinctrl_usdhc2_100mhz: usdhc2-100mhzgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x194
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d4
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d4
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d4
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d4
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d4
+ >;
+ };
+
+ pinctrl_usdhc2_200mhz: usdhc2-200mhzgrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_SD2_CLK_USDHC2_CLK 0x196
+ MX8MM_IOMUXC_SD2_CMD_USDHC2_CMD 0x1d6
+ MX8MM_IOMUXC_SD2_DATA0_USDHC2_DATA0 0x1d6
+ MX8MM_IOMUXC_SD2_DATA1_USDHC2_DATA1 0x1d6
+ MX8MM_IOMUXC_SD2_DATA2_USDHC2_DATA2 0x1d6
+ MX8MM_IOMUXC_SD2_DATA3_USDHC2_DATA3 0x1d6
+ >;
+ };
+};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-phycore-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-phycore-som.dtsi
index 995b44efb1b6..92616bc4f71f 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-phycore-som.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-phycore-som.dtsi
@@ -53,15 +53,15 @@
ddrc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-25M {
+ opp-25000000 {
opp-hz = /bits/ 64 <25000000>;
};
- opp-100M {
+ opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
};
- opp-750M {
+ opp-750000000 {
opp-hz = /bits/ 64 <750000000>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-var-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-var-som.dtsi
index a0bd540f27d3..ae0721b807e1 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-var-som.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-var-som.dtsi
@@ -53,15 +53,15 @@
ddrc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-25M {
+ opp-25000000 {
opp-hz = /bits/ 64 <25000000>;
};
- opp-100M {
+ opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
};
- opp-750M {
+ opp-750000000 {
opp-hz = /bits/ 64 <750000000>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi
index 66a0d103c90f..9e7d38872157 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw700x.dtsi
@@ -81,15 +81,15 @@
ddrc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-25M {
+ opp-25000000 {
opp-hz = /bits/ 64 <25000000>;
};
- opp-100M {
+ opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
};
- opp-750M {
+ opp-750000000 {
opp-hz = /bits/ 64 <750000000>;
};
};
@@ -119,8 +119,11 @@
&i2c1 {
clock-frequency = <100000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c1>;
+ pinctrl-1 = <&pinctrl_i2c1_gpio>;
+ scl-gpios = <&gpio5 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
gsc: gsc@20 {
@@ -365,8 +368,11 @@
&i2c2 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c2>;
+ pinctrl-1 = <&pinctrl_i2c2_gpio>;
+ scl-gpios = <&gpio5 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
eeprom@52 {
@@ -435,6 +441,13 @@
>;
};
+ pinctrl_i2c1_gpio: i2c1gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C1_SCL_GPIO5_IO14 0x400001c3
+ MX8MM_IOMUXC_I2C1_SDA_GPIO5_IO15 0x400001c3
+ >;
+ };
+
pinctrl_i2c2: i2c2grp {
fsl,pins = <
MX8MM_IOMUXC_I2C2_SCL_I2C2_SCL 0x400001c3
@@ -442,6 +455,13 @@
>;
};
+ pinctrl_i2c2_gpio: i2c2gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C2_SCL_GPIO5_IO16 0x400001c3
+ MX8MM_IOMUXC_I2C2_SDA_GPIO5_IO17 0x400001c3
+ >;
+ };
+
pinctrl_uart2: uart2grp {
fsl,pins = <
MX8MM_IOMUXC_UART2_RXD_UART2_DCE_RX 0x140
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-imx219.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-imx219.dtso
index 4eaf8aabcbff..4eaf8aabcbff 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-imx219.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-imx219.dtso
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs232-rts.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs232-rts.dtso
index 3ea73a6886ff..3ea73a6886ff 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs232-rts.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs232-rts.dtso
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs422.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs422.dtso
index c3cd9f2b0db3..c3cd9f2b0db3 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs422.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs422.dtso
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs485.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs485.dtso
index cc0a287226ab..cc0a287226ab 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs485.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw72xx-0x-rs485.dtso
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-imx219.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-imx219.dtso
index f3ece4b7fbbd..f3ece4b7fbbd 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-imx219.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-imx219.dtso
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dtso
index 2fa635e1c1a8..2fa635e1c1a8 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs232-rts.dtso
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dtso
index 3e6404340d52..3e6404340d52 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs422.dtso
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dtso
index 2c71ab9854cb..2c71ab9854cb 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw73xx-0x-rs485.dtso
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
index d3ee6fc4baab..750a1f07ecb7 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7901.dts
@@ -248,15 +248,15 @@
ddrc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-25M {
+ opp-25000000 {
opp-hz = /bits/ 64 <25000000>;
};
- opp-100M {
+ opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
};
- opp-750M {
+ opp-750000000 {
opp-hz = /bits/ 64 <750000000>;
};
};
@@ -326,8 +326,11 @@
&i2c1 {
clock-frequency = <100000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c1>;
+ pinctrl-1 = <&pinctrl_i2c1_gpio>;
+ scl-gpios = <&gpio5 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
gsc: gsc@20 {
@@ -477,8 +480,11 @@
&i2c2 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c2>;
+ pinctrl-1 = <&pinctrl_i2c2_gpio>;
+ scl-gpios = <&gpio5 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
pmic@4b {
@@ -600,8 +606,11 @@
&i2c3 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c3>;
+ pinctrl-1 = <&pinctrl_i2c3_gpio>;
+ scl-gpios = <&gpio5 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
leds_gpio: gpio@20 {
@@ -673,8 +682,11 @@
&i2c4 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c4>;
+ pinctrl-1 = <&pinctrl_i2c4_gpio>;
+ scl-gpios = <&gpio5 20 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 21 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
};
@@ -852,6 +864,13 @@
>;
};
+ pinctrl_i2c1_gpio: i2c1gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C1_SCL_GPIO5_IO14 0x400001c3
+ MX8MM_IOMUXC_I2C1_SDA_GPIO5_IO15 0x400001c3
+ >;
+ };
+
pinctrl_i2c2: i2c2grp {
fsl,pins = <
MX8MM_IOMUXC_I2C2_SCL_I2C2_SCL 0x400001c3
@@ -859,6 +878,13 @@
>;
};
+ pinctrl_i2c2_gpio: i2c2gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C2_SCL_GPIO5_IO16 0x400001c3
+ MX8MM_IOMUXC_I2C2_SDA_GPIO5_IO17 0x400001c3
+ >;
+ };
+
pinctrl_i2c3: i2c3grp {
fsl,pins = <
MX8MM_IOMUXC_I2C3_SCL_I2C3_SCL 0x400001c3
@@ -866,6 +892,13 @@
>;
};
+ pinctrl_i2c3_gpio: i2c3gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C3_SCL_GPIO5_IO18 0x400001c3
+ MX8MM_IOMUXC_I2C3_SDA_GPIO5_IO19 0x400001c3
+ >;
+ };
+
pinctrl_i2c4: i2c4grp {
fsl,pins = <
MX8MM_IOMUXC_I2C4_SCL_I2C4_SCL 0x400001c3
@@ -873,6 +906,13 @@
>;
};
+ pinctrl_i2c4_gpio: i2c4gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C4_SCL_GPIO5_IO20 0x400001c3
+ MX8MM_IOMUXC_I2C4_SDA_GPIO5_IO21 0x400001c3
+ >;
+ };
+
pinctrl_ksz: kszgrp {
fsl,pins = <
MX8MM_IOMUXC_SAI1_TXD6_GPIO4_IO18 0x41
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts
index 31f4c735fe4f..32872b0b1aaf 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7902.dts
@@ -198,15 +198,15 @@
ddrc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-25M {
+ opp-25000000 {
opp-hz = /bits/ 64 <25000000>;
};
- opp-100M {
+ opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
};
- opp-750M {
+ opp-750000000 {
opp-hz = /bits/ 64 <750000000>;
};
};
@@ -261,7 +261,7 @@
&gpio1 {
gpio-line-names = "", "", "", "", "", "", "", "",
- "", "", "", "", "", "m2_reset", "", "m2_wdis#",
+ "m2_pwr_en", "", "", "", "", "m2_reset", "", "m2_wdis#",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "";
};
@@ -283,7 +283,8 @@
&gpio4 {
gpio-line-names = "", "", "", "", "", "", "", "",
"", "", "", "amp_gpio3", "amp_gpio2", "", "amp_gpio1", "",
- "", "", "", "", "amp_gpio4", "app_gpio1", "", "uart1_rs485",
+ "lte_pwr#", "lte_rst", "lte_int", "",
+ "amp_gpio4", "app_gpio1", "vdd_4p0_en", "uart1_rs485",
"", "uart1_term", "uart1_half", "app_gpio2",
"mipi_gpio1", "", "", "";
};
@@ -298,8 +299,11 @@
&i2c1 {
clock-frequency = <100000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c1>;
+ pinctrl-1 = <&pinctrl_i2c1_gpio>;
+ scl-gpios = <&gpio5 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
gsc: gsc@20 {
@@ -566,8 +570,11 @@
&i2c2 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c2>;
+ pinctrl-1 = <&pinctrl_i2c2_gpio>;
+ scl-gpios = <&gpio5 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
accelerometer@19 {
@@ -585,16 +592,22 @@
/* off-board header */
&i2c3 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c3>;
+ pinctrl-1 = <&pinctrl_i2c3_gpio>;
+ scl-gpios = <&gpio5 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
};
/* off-board header */
&i2c4 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c4>;
+ pinctrl-1 = <&pinctrl_i2c4_gpio>;
+ scl-gpios = <&gpio5 20 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 21 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
};
@@ -738,14 +751,19 @@
pinctrl_hog: hoggrp {
fsl,pins = <
MX8MM_IOMUXC_NAND_CE0_B_GPIO3_IO1 0x40000159 /* M2_GDIS# */
+ MX8MM_IOMUXC_GPIO1_IO08_GPIO1_IO8 0x40000041 /* M2_PWR_EN */
MX8MM_IOMUXC_GPIO1_IO13_GPIO1_IO13 0x40000041 /* M2_RESET */
MX8MM_IOMUXC_NAND_DATA01_GPIO3_IO7 0x40000119 /* M2_OFF# */
MX8MM_IOMUXC_GPIO1_IO15_GPIO1_IO15 0x40000159 /* M2_WDIS# */
+ MX8MM_IOMUXC_SAI1_TXD6_GPIO4_IO18 0x40000041 /* LTE_INT */
+ MX8MM_IOMUXC_SAI1_TXD5_GPIO4_IO17 0x40000041 /* LTE_RST# */
+ MX8MM_IOMUXC_SAI1_TXD4_GPIO4_IO16 0x40000041 /* LTE_PWR */
MX8MM_IOMUXC_SAI1_TXD2_GPIO4_IO14 0x40000041 /* AMP GPIO1 */
MX8MM_IOMUXC_SAI1_TXD0_GPIO4_IO12 0x40000041 /* AMP GPIO2 */
MX8MM_IOMUXC_SAI1_TXC_GPIO4_IO11 0x40000041 /* AMP GPIO3 */
MX8MM_IOMUXC_SAI1_MCLK_GPIO4_IO20 0x40000041 /* AMP_GPIO4 */
MX8MM_IOMUXC_SAI2_RXFS_GPIO4_IO21 0x40000041 /* APP GPIO1 */
+ MX8MM_IOMUXC_SAI2_RXC_GPIO4_IO22 0x40000041 /* VDD_4P0_EN */
MX8MM_IOMUXC_SAI2_MCLK_GPIO4_IO27 0x40000041 /* APP GPIO2 */
MX8MM_IOMUXC_SD1_DATA6_GPIO2_IO8 0x40000041 /* UART2_EN# */
MX8MM_IOMUXC_SAI3_RXFS_GPIO4_IO28 0x40000041 /* MIPI_GPIO1 */
@@ -779,8 +797,6 @@
MX8MM_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f
MX8MM_IOMUXC_GPIO1_IO10_GPIO1_IO10 0x19 /* RST# */
MX8MM_IOMUXC_GPIO1_IO11_GPIO1_IO11 0x19 /* IRQ# */
- MX8MM_IOMUXC_GPIO1_IO08_ENET1_1588_EVENT0_IN 0x141
- MX8MM_IOMUXC_GPIO1_IO09_ENET1_1588_EVENT0_OUT 0x141
>;
};
@@ -797,6 +813,13 @@
>;
};
+ pinctrl_i2c1_gpio: i2c1gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C1_SCL_GPIO5_IO14 0x400001c3
+ MX8MM_IOMUXC_I2C1_SDA_GPIO5_IO15 0x400001c3
+ >;
+ };
+
pinctrl_i2c2: i2c2grp {
fsl,pins = <
MX8MM_IOMUXC_I2C2_SCL_I2C2_SCL 0x400001c3
@@ -804,6 +827,13 @@
>;
};
+ pinctrl_i2c2_gpio: i2c2gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C2_SCL_GPIO5_IO16 0x400001c3
+ MX8MM_IOMUXC_I2C2_SDA_GPIO5_IO17 0x400001c3
+ >;
+ };
+
pinctrl_i2c3: i2c3grp {
fsl,pins = <
MX8MM_IOMUXC_I2C3_SCL_I2C3_SCL 0x400001c3
@@ -811,6 +841,13 @@
>;
};
+ pinctrl_i2c3_gpio: i2c3gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C3_SCL_GPIO5_IO18 0x400001c3
+ MX8MM_IOMUXC_I2C3_SDA_GPIO5_IO19 0x400001c3
+ >;
+ };
+
pinctrl_i2c4: i2c4grp {
fsl,pins = <
MX8MM_IOMUXC_I2C4_SCL_I2C4_SCL 0x400001c3
@@ -818,6 +855,13 @@
>;
};
+ pinctrl_i2c4_gpio: i2c4gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C4_SCL_GPIO5_IO20 0x400001c3
+ MX8MM_IOMUXC_I2C4_SDA_GPIO5_IO21 0x400001c3
+ >;
+ };
+
pinctrl_gpio_leds: gpioledgrp {
fsl,pins = <
MX8MM_IOMUXC_SAI5_RXD0_GPIO3_IO21 0x19
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts
index 19f6d2943d26..8ce562246a08 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts
@@ -207,15 +207,15 @@
ddrc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-25M {
+ opp-25000000 {
opp-hz = /bits/ 64 <25000000>;
};
- opp-100M {
+ opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
};
- opp-750M {
+ opp-750000000 {
opp-hz = /bits/ 64 <750000000>;
};
};
@@ -265,8 +265,11 @@
&i2c1 {
clock-frequency = <100000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c1>;
+ pinctrl-1 = <&pinctrl_i2c1_gpio>;
+ scl-gpios = <&gpio5 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
gsc: gsc@20 {
@@ -397,8 +400,11 @@
&i2c2 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c2>;
+ pinctrl-1 = <&pinctrl_i2c2_gpio>;
+ scl-gpios = <&gpio5 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
pmic@4b {
@@ -520,8 +526,11 @@
&i2c3 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c3>;
+ pinctrl-1 = <&pinctrl_i2c3_gpio>;
+ scl-gpios = <&gpio5 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
accelerometer@19 {
@@ -681,6 +690,13 @@
>;
};
+ pinctrl_i2c1_gpio: i2c1gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C1_SCL_GPIO5_IO14 0x400001c3
+ MX8MM_IOMUXC_I2C1_SDA_GPIO5_IO15 0x400001c3
+ >;
+ };
+
pinctrl_i2c2: i2c2grp {
fsl,pins = <
MX8MM_IOMUXC_I2C2_SCL_I2C2_SCL 0x400001c3
@@ -688,6 +704,13 @@
>;
};
+ pinctrl_i2c2_gpio: i2c2gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C2_SCL_GPIO5_IO16 0x400001c3
+ MX8MM_IOMUXC_I2C2_SDA_GPIO5_IO17 0x400001c3
+ >;
+ };
+
pinctrl_i2c3: i2c3grp {
fsl,pins = <
MX8MM_IOMUXC_I2C3_SCL_I2C3_SCL 0x400001c3
@@ -695,6 +718,13 @@
>;
};
+ pinctrl_i2c3_gpio: i2c3gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C3_SCL_GPIO5_IO18 0x400001c3
+ MX8MM_IOMUXC_I2C3_SDA_GPIO5_IO19 0x400001c3
+ >;
+ };
+
pinctrl_gpio_leds: gpioledgrp {
fsl,pins = <
MX8MM_IOMUXC_SPDIF_EXT_CLK_GPIO5_IO5 0x19
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts
index a67771d02146..eceed9816f5d 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts
@@ -266,15 +266,15 @@
ddrc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-25M {
+ opp-25000000 {
opp-hz = /bits/ 64 <25000000>;
};
- opp-100M {
+ opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
};
- opp-750M {
+ opp-750000000 {
opp-hz = /bits/ 64 <750000000>;
};
};
@@ -315,8 +315,11 @@
&i2c1 {
clock-frequency = <100000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c1>;
+ pinctrl-1 = <&pinctrl_i2c1_gpio>;
+ scl-gpios = <&gpio5 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
gsc: gsc@20 {
@@ -441,8 +444,11 @@
&i2c2 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c2>;
+ pinctrl-1 = <&pinctrl_i2c2_gpio>;
+ scl-gpios = <&gpio5 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
pmic@4b {
@@ -564,8 +570,11 @@
&i2c3 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c3>;
+ pinctrl-1 = <&pinctrl_i2c3_gpio>;
+ scl-gpios = <&gpio5 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
accelerometer@19 {
@@ -582,8 +591,11 @@
&i2c4 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c4>;
+ pinctrl-1 = <&pinctrl_i2c4_gpio>;
+ scl-gpios = <&gpio5 20 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 21 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
gpioled: gpio@27 {
@@ -738,6 +750,13 @@
>;
};
+ pinctrl_i2c1_gpio: i2c1gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C1_SCL_GPIO5_IO14 0x400001c3
+ MX8MM_IOMUXC_I2C1_SDA_GPIO5_IO15 0x400001c3
+ >;
+ };
+
pinctrl_i2c2: i2c2grp {
fsl,pins = <
MX8MM_IOMUXC_I2C2_SCL_I2C2_SCL 0x400001c3
@@ -745,6 +764,13 @@
>;
};
+ pinctrl_i2c2_gpio: i2c2gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C2_SCL_GPIO5_IO16 0x400001c3
+ MX8MM_IOMUXC_I2C2_SDA_GPIO5_IO17 0x400001c3
+ >;
+ };
+
pinctrl_i2c3: i2c3grp {
fsl,pins = <
MX8MM_IOMUXC_I2C3_SCL_I2C3_SCL 0x400001c3
@@ -752,6 +778,13 @@
>;
};
+ pinctrl_i2c3_gpio: i2c3gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C3_SCL_GPIO5_IO18 0x400001c3
+ MX8MM_IOMUXC_I2C3_SDA_GPIO5_IO19 0x400001c3
+ >;
+ };
+
pinctrl_i2c4: i2c4grp {
fsl,pins = <
MX8MM_IOMUXC_I2C4_SCL_I2C4_SCL 0x400001c3
@@ -759,6 +792,13 @@
>;
};
+ pinctrl_i2c4_gpio: i2c4gpiogrp {
+ fsl,pins = <
+ MX8MM_IOMUXC_I2C4_SCL_GPIO5_IO20 0x400001c3
+ MX8MM_IOMUXC_I2C4_SDA_GPIO5_IO21 0x400001c3
+ >;
+ };
+
pinctrl_pcie0: pciegrp {
fsl,pins = <
MX8MM_IOMUXC_ECSPI2_MOSI_GPIO5_IO11 0x41
diff --git a/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
index bcab830c6e95..0d454e0e2f7c 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm-verdin.dtsi
@@ -3,8 +3,8 @@
* Copyright 2022 Toradex
*/
-#include "dt-bindings/phy/phy-imx8-pcie.h"
-#include "dt-bindings/pwm/pwm.h"
+#include <dt-bindings/phy/phy-imx8-pcie.h>
+#include <dt-bindings/pwm/pwm.h>
#include "imx8mm.dtsi"
/ {
@@ -183,15 +183,15 @@
ddrc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-25M {
+ opp-25000000 {
opp-hz = /bits/ 64 <25000000>;
};
- opp-100M {
+ opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
};
- opp-750M {
+ opp-750000000 {
opp-hz = /bits/ 64 <750000000>;
};
};
@@ -610,7 +610,7 @@
compatible = "atmel,maxtouch";
/*
* Verdin GPIO_9_DSI
- * (TOUCH_INT#, SODIMM 17, also routed to SN65DSI83 IRQ albeit currently unused)
+ * (TOUCH_INT#, SODIMM 17, also routed to SN65DSI84 IRQ albeit currently unused)
*/
interrupt-parent = <&gpio3>;
interrupts = <15 IRQ_TYPE_EDGE_FALLING>;
@@ -653,7 +653,8 @@
assigned-clock-parents = <&clk IMX8MM_SYS_PLL2_50M>,
<&clk IMX8MM_SYS_PLL2_250M>;
assigned-clock-rates = <10000000>, <250000000>;
- clocks = <&clk IMX8MM_CLK_PCIE1_ROOT>, <&clk IMX8MM_CLK_PCIE1_AUX>,
+ clocks = <&clk IMX8MM_CLK_PCIE1_ROOT>,
+ <&clk IMX8MM_CLK_PCIE1_AUX>,
<&clk IMX8MM_CLK_PCIE1_PHY>;
clock-names = "pcie", "pcie_aux", "pcie_bus";
pinctrl-names = "default";
@@ -664,6 +665,7 @@
&pcie_phy {
clocks = <&clk IMX8MM_CLK_PCIE1_PHY>;
+ clock-names = "ref";
fsl,clkreq-unsupported;
fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_OUTPUT>;
fsl,tx-deemph-gen1 = <0x2d>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mm.dtsi b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
index 50ef92915c67..4ee89fdcf59b 100644
--- a/arch/arm64/boot/dts/freescale/imx8mm.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mm.dtsi
@@ -139,6 +139,7 @@
A53_L2: l2-cache0 {
compatible = "cache";
cache-level = <2>;
+ cache-unified;
cache-size = <0x80000>;
cache-line-size = <64>;
cache-sets = <512>;
@@ -575,9 +576,10 @@
};
};
- anatop: anatop@30360000 {
- compatible = "fsl,imx8mm-anatop", "syscon";
+ anatop: clock-controller@30360000 {
+ compatible = "fsl,imx8mm-anatop";
reg = <0x30360000 0x10000>;
+ #clock-cells = <1>;
};
snvs: snvs@30370000 {
diff --git a/arch/arm64/boot/dts/freescale/imx8mn-beacon-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mn-beacon-som.dtsi
index 1133cded9be2..8a4369d38903 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn-beacon-som.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mn-beacon-som.dtsi
@@ -55,15 +55,15 @@
ddrc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-25M {
+ opp-25000000 {
opp-hz = /bits/ 64 <25000000>;
};
- opp-100M {
+ opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
};
- opp-800M {
+ opp-800000000 {
opp-hz = /bits/ 64 <800000000>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts b/arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts
index d8ce217c6016..5110d59b719f 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mn-ddr4-evk.dts
@@ -35,15 +35,15 @@
ddrc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-25M {
+ opp-25000000 {
opp-hz = /bits/ 64 <25000000>;
};
- opp-100M {
+ opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
};
- opp-600M {
+ opp-600000000 {
opp-hz = /bits/ 64 <600000000>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mn-evk.dts b/arch/arm64/boot/dts/freescale/imx8mn-evk.dts
index 4eb467df5ba7..4839a962a170 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mn-evk.dts
@@ -47,6 +47,7 @@
regulator-boot-on;
regulator-always-on;
regulator-ramp-delay = <3125>;
+ nxp,dvs-standby-voltage = <750000>;
};
buck2: BUCK2 {
@@ -56,8 +57,6 @@
regulator-boot-on;
regulator-always-on;
regulator-ramp-delay = <3125>;
- nxp,dvs-run-voltage = <950000>;
- nxp,dvs-standby-voltage = <850000>;
};
buck4: BUCK4{
diff --git a/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi b/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi
index 261c36540079..8fef980c4ab2 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi
@@ -36,6 +36,7 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+ off-on-delay-us = <12000>;
enable-active-high;
};
@@ -159,8 +160,11 @@
&i2c2 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c2>;
+ pinctrl-1 = <&pinctrl_i2c2_gpio>;
+ scl-gpios = <&gpio5 16 GPIO_ACTIVE_HIGH>;
+ sda-gpios = <&gpio5 17 GPIO_ACTIVE_HIGH>;
status = "okay";
ptn5110: tcpc@50 {
@@ -195,8 +199,11 @@
&i2c3 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c3>;
+ pinctrl-1 = <&pinctrl_i2c3_gpio>;
+ scl-gpios = <&gpio5 18 GPIO_ACTIVE_HIGH>;
+ sda-gpios = <&gpio5 19 GPIO_ACTIVE_HIGH>;
status = "okay";
pca6416: gpio@20 {
@@ -240,6 +247,15 @@
status = "okay";
};
+&uart1 { /* BT */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ assigned-clocks = <&clk IMX8MN_CLK_UART1>;
+ assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_80M>;
+ uart-has-rtscts;
+ status = "okay";
+};
+
&uart2 { /* console */
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_uart2>;
@@ -255,6 +271,10 @@
status = "okay";
};
+&usbphynop1 {
+ wakeup-source;
+};
+
&usbotg1 {
dr_mode = "otg";
hnp-disable;
@@ -369,6 +389,13 @@
>;
};
+ pinctrl_i2c2_gpio: i2c2grp-gpio {
+ fsl,pins = <
+ MX8MN_IOMUXC_I2C2_SCL_GPIO5_IO16 0x1c3
+ MX8MN_IOMUXC_I2C2_SDA_GPIO5_IO17 0x1c3
+ >;
+ };
+
pinctrl_i2c3: i2c3grp {
fsl,pins = <
MX8MN_IOMUXC_I2C3_SCL_I2C3_SCL 0x400001c3
@@ -376,6 +403,13 @@
>;
};
+ pinctrl_i2c3_gpio: i2c3grp-gpio {
+ fsl,pins = <
+ MX8MN_IOMUXC_I2C3_SCL_GPIO5_IO18 0x1c3
+ MX8MN_IOMUXC_I2C3_SDA_GPIO5_IO19 0x1c3
+ >;
+ };
+
pinctrl_pmic: pmicirqgrp {
fsl,pins = <
MX8MN_IOMUXC_GPIO1_IO03_GPIO1_IO3 0x141
@@ -419,6 +453,15 @@
>;
};
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX8MN_IOMUXC_UART1_RXD_UART1_DCE_RX 0x140
+ MX8MN_IOMUXC_UART1_TXD_UART1_DCE_TX 0x140
+ MX8MN_IOMUXC_UART3_RXD_UART1_DCE_CTS_B 0x140
+ MX8MN_IOMUXC_UART3_TXD_UART1_DCE_RTS_B 0x140
+ >;
+ };
+
pinctrl_uart2: uart2grp {
fsl,pins = <
MX8MN_IOMUXC_UART2_RXD_UART2_DCE_RX 0x140
diff --git a/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts b/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts
index dd4302ac1de4..b9444e4a3d2d 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mn-venice-gw7902.dts
@@ -189,15 +189,15 @@
ddrc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-25M {
+ opp-25000000 {
opp-hz = /bits/ 64 <25000000>;
};
- opp-100M {
+ opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
};
- opp-750M {
+ opp-750000000 {
opp-hz = /bits/ 64 <750000000>;
};
};
@@ -256,7 +256,7 @@
&gpio1 {
gpio-line-names = "", "", "", "", "", "", "", "",
- "", "", "", "", "", "m2_reset", "", "m2_wdis#",
+ "m2_pwr_en", "", "", "", "", "m2_reset", "", "m2_wdis#",
"", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "";
};
@@ -278,7 +278,7 @@
&gpio4 {
gpio-line-names = "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "", "",
- "", "", "", "", "", "app_gpio1", "", "uart1_rs485",
+ "", "", "", "", "", "app_gpio1", "vdd_4p0_en", "uart1_rs485",
"", "uart1_term", "uart1_half", "app_gpio2",
"mipi_gpio1", "", "", "";
};
@@ -297,8 +297,11 @@
&i2c1 {
clock-frequency = <100000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c1>;
+ pinctrl-1 = <&pinctrl_i2c1_gpio>;
+ scl-gpios = <&gpio5 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
gsc: gsc@20 {
@@ -565,8 +568,11 @@
&i2c2 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c2>;
+ pinctrl-1 = <&pinctrl_i2c2_gpio>;
+ scl-gpios = <&gpio5 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
accelerometer@19 {
@@ -584,16 +590,22 @@
/* off-board header */
&i2c3 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c3>;
+ pinctrl-1 = <&pinctrl_i2c3_gpio>;
+ scl-gpios = <&gpio5 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
};
/* off-board header */
&i2c4 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c4>;
+ pinctrl-1 = <&pinctrl_i2c4_gpio>;
+ scl-gpios = <&gpio5 20 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 21 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
};
@@ -689,10 +701,12 @@
pinctrl_hog: hoggrp {
fsl,pins = <
MX8MN_IOMUXC_NAND_CE0_B_GPIO3_IO1 0x40000159 /* M2_GDIS# */
+ MX8MN_IOMUXC_GPIO1_IO08_GPIO1_IO8 0x40000041 /* M2_PWR_EN */
MX8MN_IOMUXC_GPIO1_IO13_GPIO1_IO13 0x40000041 /* M2_RESET */
MX8MN_IOMUXC_NAND_DATA01_GPIO3_IO7 0x40000119 /* M2_OFF# */
MX8MN_IOMUXC_GPIO1_IO15_GPIO1_IO15 0x40000159 /* M2_WDIS# */
MX8MN_IOMUXC_SAI2_RXFS_GPIO4_IO21 0x40000041 /* APP GPIO1 */
+ MX8MN_IOMUXC_SAI2_RXC_GPIO4_IO22 0x40000041 /* VDD_4P0_EN */
MX8MN_IOMUXC_SAI2_MCLK_GPIO4_IO27 0x40000041 /* APP GPIO2 */
MX8MN_IOMUXC_SD1_DATA6_GPIO2_IO8 0x40000041 /* UART2_EN# */
MX8MN_IOMUXC_SAI3_RXFS_GPIO4_IO28 0x40000041 /* MIPI_GPIO1 */
@@ -726,8 +740,6 @@
MX8MN_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f
MX8MN_IOMUXC_GPIO1_IO10_GPIO1_IO10 0x19 /* RST# */
MX8MN_IOMUXC_GPIO1_IO11_GPIO1_IO11 0x19 /* IRQ# */
- MX8MN_IOMUXC_GPIO1_IO08_ENET1_1588_EVENT0_IN 0x141
- MX8MN_IOMUXC_GPIO1_IO09_ENET1_1588_EVENT0_OUT 0x141
>;
};
@@ -744,6 +756,13 @@
>;
};
+ pinctrl_i2c1_gpio: i2c1gpiogrp {
+ fsl,pins = <
+ MX8MN_IOMUXC_I2C1_SCL_GPIO5_IO14 0x400001c3
+ MX8MN_IOMUXC_I2C1_SDA_GPIO5_IO15 0x400001c3
+ >;
+ };
+
pinctrl_i2c2: i2c2grp {
fsl,pins = <
MX8MN_IOMUXC_I2C2_SCL_I2C2_SCL 0x400001c3
@@ -751,6 +770,13 @@
>;
};
+ pinctrl_i2c2_gpio: i2c2gpiogrp {
+ fsl,pins = <
+ MX8MN_IOMUXC_I2C2_SCL_GPIO5_IO16 0x400001c3
+ MX8MN_IOMUXC_I2C2_SDA_GPIO5_IO17 0x400001c3
+ >;
+ };
+
pinctrl_i2c3: i2c3grp {
fsl,pins = <
MX8MN_IOMUXC_I2C3_SCL_I2C3_SCL 0x400001c3
@@ -758,6 +784,13 @@
>;
};
+ pinctrl_i2c3_gpio: i2c3gpiogrp {
+ fsl,pins = <
+ MX8MN_IOMUXC_I2C3_SCL_GPIO5_IO18 0x400001c3
+ MX8MN_IOMUXC_I2C3_SDA_GPIO5_IO19 0x400001c3
+ >;
+ };
+
pinctrl_i2c4: i2c4grp {
fsl,pins = <
MX8MN_IOMUXC_I2C4_SCL_I2C4_SCL 0x400001c3
@@ -765,6 +798,13 @@
>;
};
+ pinctrl_i2c4_gpio: i2c4gpiogrp {
+ fsl,pins = <
+ MX8MN_IOMUXC_I2C4_SCL_GPIO5_IO20 0x400001c3
+ MX8MN_IOMUXC_I2C4_SDA_GPIO5_IO21 0x400001c3
+ >;
+ };
+
pinctrl_gpio_leds: gpioledgrp {
fsl,pins = <
MX8MN_IOMUXC_SAI5_RXD0_GPIO3_IO21 0x19
diff --git a/arch/arm64/boot/dts/freescale/imx8mn.dtsi b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
index 67b554ba690c..b7d91df71cc2 100644
--- a/arch/arm64/boot/dts/freescale/imx8mn.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mn.dtsi
@@ -139,6 +139,7 @@
A53_L2: l2-cache0 {
compatible = "cache";
cache-level = <2>;
+ cache-unified;
cache-size = <0x80000>;
cache-line-size = <64>;
cache-sets = <512>;
@@ -576,10 +577,10 @@
};
};
- anatop: anatop@30360000 {
- compatible = "fsl,imx8mn-anatop", "fsl,imx8mm-anatop",
- "syscon";
+ anatop: clock-controller@30360000 {
+ compatible = "fsl,imx8mn-anatop", "fsl,imx8mm-anatop";
reg = <0x30360000 0x10000>;
+ #clock-cells = <1>;
};
snvs: snvs@30370000 {
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi
index 0f13ee362771..6e1192e751f8 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-dhcom-som.dtsi
@@ -427,6 +427,24 @@
pinctrl-0 = <&pinctrl_uart2>;
uart-has-rtscts;
status = "okay";
+
+ /*
+ * PLL3 at 320 MHz supplies UART2 root with 64 MHz clock,
+ * which with 16x oversampling yields 4 Mbdps baud base,
+ * which is exactly the maximum rate supported by muRata
+ * 2AE bluetooth UART.
+ */
+ assigned-clocks = <&clk IMX8MP_SYS_PLL3>, <&clk IMX8MP_CLK_UART2>;
+ assigned-clock-parents = <0>, <&clk IMX8MP_SYS_PLL3_OUT>;
+ assigned-clock-rates = <320000000>, <64000000>;
+
+ bluetooth {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2_bt>;
+ compatible = "cypress,cyw4373a0-bt";
+ shutdown-gpios = <&gpio1 12 GPIO_ACTIVE_HIGH>;
+ max-speed = <4000000>;
+ };
};
&uart3 {
@@ -849,6 +867,13 @@
>;
};
+ pinctrl_uart2_bt: dhcom-uart2-bt-grp {
+ fsl,pins = <
+ /* BT_REG_EN */
+ MX8MP_IOMUXC_GPIO1_IO12__GPIO1_IO12 0x144
+ >;
+ };
+
pinctrl_uart3: dhcom-uart3-grp {
fsl,pins = <
MX8MP_IOMUXC_ECSPI1_SCLK__UART3_DCE_RX 0x49
@@ -886,8 +911,6 @@
MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x1d0
MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x1d0
MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x1d0
- /* BT_REG_EN */
- MX8MP_IOMUXC_GPIO1_IO12__GPIO1_IO12 0x144
/* WL_REG_EN */
MX8MP_IOMUXC_GPIO1_IO13__GPIO1_IO13 0x144
>;
@@ -901,8 +924,6 @@
MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x1d4
MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x1d4
MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x1d4
- /* BT_REG_EN */
- MX8MP_IOMUXC_GPIO1_IO12__GPIO1_IO12 0x144
/* WL_REG_EN */
MX8MP_IOMUXC_GPIO1_IO13__GPIO1_IO13 0x144
>;
@@ -916,8 +937,6 @@
MX8MP_IOMUXC_SD1_DATA1__USDHC1_DATA1 0x1d6
MX8MP_IOMUXC_SD1_DATA2__USDHC1_DATA2 0x1d6
MX8MP_IOMUXC_SD1_DATA3__USDHC1_DATA3 0x1d6
- /* BT_REG_EN */
- MX8MP_IOMUXC_GPIO1_IO12__GPIO1_IO12 0x144
/* WL_REG_EN */
MX8MP_IOMUXC_GPIO1_IO13__GPIO1_IO13 0x144
>;
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
index b4c1ef2559f2..d4c7ca16abd0 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-evk.dts
@@ -85,6 +85,20 @@
};
};
+&flexspi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_flexspi0>;
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <80000000>;
+ spi-tx-bus-width = <1>;
+ spi-rx-bus-width = <4>;
+ };
+};
+
&A53_0 {
cpu-supply = <&reg_arm>;
};
@@ -317,6 +331,13 @@
};
};
+&i2c2 {
+ clock-frequency = <400000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+};
+
&i2c3 {
clock-frequency = <400000>;
pinctrl-names = "default";
@@ -390,10 +411,37 @@
status = "okay";
};
+&pwm1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm1>;
+ status = "okay";
+};
+
+&pwm2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm2>;
+ status = "okay";
+};
+
+&pwm4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm4>;
+ status = "okay";
+};
+
&snvs_pwrkey {
status = "okay";
};
+&uart1 { /* BT */
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ assigned-clocks = <&clk IMX8MP_CLK_UART1>;
+ assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_80M>;
+ uart-has-rtscts;
+ status = "okay";
+};
+
&uart2 {
/* console */
pinctrl-names = "default";
@@ -416,6 +464,15 @@
status = "okay";
};
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>;
+ assigned-clocks = <&clk IMX8MP_CLK_UART3>;
+ assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_80M>;
+ uart-has-rtscts;
+ status = "okay";
+};
+
&usdhc2 {
assigned-clocks = <&clk IMX8MP_CLK_USDHC2>;
assigned-clock-rates = <400000000>;
@@ -515,6 +572,17 @@
>;
};
+ pinctrl_flexspi0: flexspi0grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_NAND_ALE__FLEXSPI_A_SCLK 0x1c2
+ MX8MP_IOMUXC_NAND_CE0_B__FLEXSPI_A_SS0_B 0x82
+ MX8MP_IOMUXC_NAND_DATA00__FLEXSPI_A_DATA00 0x82
+ MX8MP_IOMUXC_NAND_DATA01__FLEXSPI_A_DATA01 0x82
+ MX8MP_IOMUXC_NAND_DATA02__FLEXSPI_A_DATA02 0x82
+ MX8MP_IOMUXC_NAND_DATA03__FLEXSPI_A_DATA03 0x82
+ >;
+ };
+
pinctrl_gpio_led: gpioledgrp {
fsl,pins = <
MX8MP_IOMUXC_NAND_READY_B__GPIO3_IO16 0x140
@@ -528,6 +596,13 @@
>;
};
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL 0x400001c2
+ MX8MP_IOMUXC_I2C2_SDA__I2C2_SDA 0x400001c2
+ >;
+ };
+
pinctrl_i2c3: i2c3grp {
fsl,pins = <
MX8MP_IOMUXC_I2C3_SCL__I2C3_SCL 0x400001c2
@@ -567,12 +642,39 @@
>;
};
+ pinctrl_pwm1: pwm1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO01__PWM1_OUT 0x116
+ >;
+ };
+
+ pinctrl_pwm2: pwm2grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_GPIO1_IO11__PWM2_OUT 0x116
+ >;
+ };
+
+ pinctrl_pwm4: pwm4grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_SAI5_RXFS__PWM4_OUT 0x116
+ >;
+ };
+
pinctrl_reg_usdhc2_vmmc: regusdhc2vmmcgrp {
fsl,pins = <
MX8MP_IOMUXC_SD2_RESET_B__GPIO2_IO19 0x40
>;
};
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_UART1_RXD__UART1_DCE_RX 0x140
+ MX8MP_IOMUXC_UART1_TXD__UART1_DCE_TX 0x140
+ MX8MP_IOMUXC_UART3_RXD__UART1_DCE_CTS 0x140
+ MX8MP_IOMUXC_UART3_TXD__UART1_DCE_RTS 0x140
+ >;
+ };
+
pinctrl_uart2: uart2grp {
fsl,pins = <
MX8MP_IOMUXC_UART2_RXD__UART2_DCE_RX 0x140
@@ -586,6 +688,15 @@
>;
};
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX8MP_IOMUXC_ECSPI1_SCLK__UART3_DCE_RX 0x140
+ MX8MP_IOMUXC_ECSPI1_MOSI__UART3_DCE_TX 0x140
+ MX8MP_IOMUXC_ECSPI1_SS0__UART3_DCE_RTS 0x140
+ MX8MP_IOMUXC_ECSPI1_MISO__UART3_DCE_CTS 0x140
+ >;
+ };
+
pinctrl_usdhc2: usdhc2grp {
fsl,pins = <
MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x190
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts
index 7bf6f81e87b4..6357f3d96ccd 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts
@@ -8,6 +8,7 @@
#include <dt-bindings/leds/common.h>
#include <dt-bindings/net/ti-dp83867.h>
+#include <dt-bindings/phy/phy-imx8-pcie.h>
#include <dt-bindings/pwm/pwm.h>
#include "imx8mp-tqma8mpql.dtsi"
@@ -48,6 +49,27 @@
status = "disabled";
};
+ clk_xtal25: clk-xtal25 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <25000000>;
+ };
+
+ fan0: pwm-fan {
+ compatible = "pwm-fan";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwmfan>;
+ fan-supply = <&reg_pwm_fan>;
+ #cooling-cells = <2>;
+ /* typical 25 kHz -> 40.000 nsec */
+ pwms = <&pwm3 0 40000 PWM_POLARITY_INVERTED>;
+ cooling-levels = <0 32 64 128 196 240>;
+ pulses-per-revolution = <2>;
+ interrupt-parent = <&gpio5>;
+ interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
+ status = "disabled";
+ };
+
gpio-keys {
compatible = "gpio-keys";
pinctrl-names = "default";
@@ -108,6 +130,18 @@
status = "disabled";
};
+ reg_pwm_fan: regulator-pwm-fan {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_regpwmfan>;
+ regulator-name = "FAN_PWR";
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ gpio = <&gpio4 27 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ vin-supply = <&reg_vcc_12v0>;
+ };
+
reg_usdhc2_vmmc: regulator-usdhc2 {
compatible = "regulator-fixed";
pinctrl-names = "default";
@@ -165,6 +199,47 @@
linux,cma-default;
};
};
+
+ thermal-zones {
+ soc-thermal {
+ trips {
+ soc_active0: trip-active0 {
+ temperature = <40000>;
+ hysteresis = <5000>;
+ type = "active";
+ };
+
+ soc_active1: trip-active1 {
+ temperature = <48000>;
+ hysteresis = <3000>;
+ type = "active";
+ };
+
+ soc_active2: trip-active2 {
+ temperature = <60000>;
+ hysteresis = <10000>;
+ type = "active";
+ };
+ };
+
+ cooling-maps {
+ map1 {
+ trip = <&soc_active0>;
+ cooling-device = <&fan0 1 1>;
+ };
+
+ map2 {
+ trip = <&soc_active1>;
+ cooling-device = <&fan0 2 2>;
+ };
+
+ map3 {
+ trip = <&soc_active2>;
+ cooling-device = <&fan0 3 3>;
+ };
+ };
+ };
+ };
};
&ecspi1 {
@@ -340,9 +415,16 @@
"", "", "", "",
"", "", "", "",
"", "", "DP_IRQ", "DSI_EN",
- "HDMI_OC#", "TEMP_EVENT#", "PCIE_CLK_OE#", "",
+ "HDMI_OC#", "TEMP_EVENT#", "PCIE_REFCLK_OE#", "",
"", "", "", "FAN_PWR",
"RTC_EVENT#", "CODEC_RST#", "", "";
+
+ pcie-refclkreq-hog {
+ gpio-hog;
+ gpios = <22 0>;
+ output-high;
+ line-name = "PCIE_REFCLK_OE#";
+ };
};
&gpio5 {
@@ -377,6 +459,13 @@
pagesize = <16>;
vcc-supply = <&reg_vcc_3v3>;
};
+
+ pcieclk: clock-generator@6a {
+ compatible = "renesas,9fgv0241";
+ reg = <0x6a>;
+ clocks = <&clk_xtal25>;
+ #clock-cells = <1>;
+ };
};
&i2c4 {
@@ -407,6 +496,25 @@
interrupts = <28 IRQ_TYPE_EDGE_FALLING>;
};
+&pcie_phy {
+ fsl,clkreq-unsupported;
+ fsl,refclk-pad-mode = <IMX8_PCIE_REFCLK_PAD_INPUT>;
+ clocks = <&pcieclk 0>;
+ clock-names = "ref";
+ status = "okay";
+};
+
+&pcie {
+ clocks = <&clk IMX8MP_CLK_HSIO_ROOT>,
+ <&clk IMX8MP_CLK_HSIO_AXI>,
+ <&clk IMX8MP_CLK_PCIE_ROOT>;
+ clock-names = "pcie", "pcie_bus", "pcie_aux";
+ assigned-clocks = <&clk IMX8MP_CLK_PCIE_AUX>;
+ assigned-clock-rates = <10000000>;
+ assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_50M>;
+ status = "okay";
+};
+
&pwm2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_pwm2>;
@@ -461,11 +569,23 @@
status = "okay";
};
+&usb3_1 {
+ fsl,disable-port-power-control;
+ fsl,permanently-attached;
+ dr_mode = "host";
+ status = "okay";
+};
+
&usb3_phy0 {
vbus-supply = <&reg_vcc_5v0>;
status = "okay";
};
+&usb3_phy1 {
+ vbus-supply = <&reg_vcc_5v0>;
+ status = "okay";
+};
+
&usb_dwc3_0 {
/* dual role is implemented, but not a full featured OTG */
hnp-disable;
@@ -486,6 +606,31 @@
};
};
+&usb_dwc3_1 {
+ dr_mode = "host";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbhub>;
+ status = "okay";
+
+ hub_2_0: hub@1 {
+ compatible = "usb451,8142";
+ reg = <1>;
+ peer-hub = <&hub_3_0>;
+ reset-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
+ vdd-supply = <&reg_vcc_3v3>;
+ };
+
+ hub_3_0: hub@2 {
+ compatible = "usb451,8140";
+ reg = <2>;
+ peer-hub = <&hub_2_0>;
+ reset-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
+ vdd-supply = <&reg_vcc_3v3>;
+ };
+};
+
&usdhc2 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>;
@@ -685,10 +830,18 @@
fsl,pins = <MX8MP_IOMUXC_I2C3_SDA__PWM3_OUT 0x14>;
};
+ pinctrl_pwmfan: pwmfangrp {
+ fsl,pins = <MX8MP_IOMUXC_I2C3_SCL__GPIO5_IO18 0x80>; /* FAN RPM */
+ };
+
pinctrl_reg12v0: reg12v0grp {
fsl,pins = <MX8MP_IOMUXC_SD1_DATA4__GPIO2_IO06 0x140>; /* VCC12V enable */
};
+ pinctrl_regpwmfan: regpwmfangrp {
+ fsl,pins = <MX8MP_IOMUXC_SAI2_MCLK__GPIO4_IO27 0x80>;
+ };
+
/* X61 */
pinctrl_uart1: uart1grp {
fsl,pins = <MX8MP_IOMUXC_SD1_CLK__UART1_DCE_TX 0x140>,
@@ -720,6 +873,10 @@
fsl,pins = <MX8MP_IOMUXC_GPIO1_IO10__GPIO1_IO10 0x1c0>;
};
+ pinctrl_usbhub: usbhubgrp {
+ fsl,pins = <MX8MP_IOMUXC_GPIO1_IO11__GPIO1_IO11 0x10>;
+ };
+
pinctrl_usdhc2: usdhc2grp {
fsl,pins = <MX8MP_IOMUXC_SD2_CLK__USDHC2_CLK 0x192>,
<MX8MP_IOMUXC_SD2_CMD__USDHC2_CMD 0x1d2>,
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts
index 06b4c93c5876..ceeca4966fc5 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mp-venice-gw74xx.dts
@@ -253,8 +253,11 @@
&i2c1 {
clock-frequency = <100000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c1>;
+ pinctrl-1 = <&pinctrl_i2c1_gpio>;
+ scl-gpios = <&gpio5 14 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 15 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
gsc: gsc@20 {
@@ -477,8 +480,11 @@
&i2c2 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c2>;
+ pinctrl-1 = <&pinctrl_i2c2_gpio>;
+ scl-gpios = <&gpio5 16 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 17 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
accelerometer@19 {
@@ -556,16 +562,22 @@
/* off-board header */
&i2c3 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c3>;
+ pinctrl-1 = <&pinctrl_i2c3_gpio>;
+ scl-gpios = <&gpio5 18 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 19 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
};
/* off-board header */
&i2c4 {
clock-frequency = <400000>;
- pinctrl-names = "default";
+ pinctrl-names = "default", "gpio";
pinctrl-0 = <&pinctrl_i2c4>;
+ pinctrl-1 = <&pinctrl_i2c4_gpio>;
+ scl-gpios = <&gpio5 20 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
+ sda-gpios = <&gpio5 21 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
status = "okay";
};
@@ -800,6 +812,13 @@
>;
};
+ pinctrl_i2c1_gpio: i2c1gpiogrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_I2C1_SCL__GPIO5_IO14 0x400001c2
+ MX8MP_IOMUXC_I2C1_SDA__GPIO5_IO15 0x400001c2
+ >;
+ };
+
pinctrl_i2c2: i2c2grp {
fsl,pins = <
MX8MP_IOMUXC_I2C2_SCL__I2C2_SCL 0x400001c2
@@ -807,6 +826,13 @@
>;
};
+ pinctrl_i2c2_gpio: i2c2gpiogrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_I2C2_SCL__GPIO5_IO16 0x400001c3
+ MX8MP_IOMUXC_I2C2_SDA__GPIO5_IO17 0x400001c3
+ >;
+ };
+
pinctrl_i2c3: i2c3grp {
fsl,pins = <
MX8MP_IOMUXC_I2C3_SCL__I2C3_SCL 0x400001c2
@@ -814,6 +840,13 @@
>;
};
+ pinctrl_i2c3_gpio: i2c3gpiogrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_I2C3_SCL__GPIO5_IO18 0x400001c3
+ MX8MP_IOMUXC_I2C3_SDA__GPIO5_IO19 0x400001c3
+ >;
+ };
+
pinctrl_i2c4: i2c4grp {
fsl,pins = <
MX8MP_IOMUXC_I2C4_SCL__I2C4_SCL 0x400001c2
@@ -821,6 +854,13 @@
>;
};
+ pinctrl_i2c4_gpio: i2c4gpiogrp {
+ fsl,pins = <
+ MX8MP_IOMUXC_I2C4_SCL__GPIO5_IO20 0x400001c3
+ MX8MP_IOMUXC_I2C4_SDA__GPIO5_IO21 0x400001c3
+ >;
+ };
+
pinctrl_ksz: kszgrp {
fsl,pins = <
MX8MP_IOMUXC_SAI3_RXC__GPIO4_IO29 0x150 /* IRQ# */
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi
index 4b8f86f63081..80db1ad7c230 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin-dahlia.dtsi
@@ -116,6 +116,7 @@
/* Verdin USB_2 */
&usb3_1 {
+ fsl,permanently-attached;
status = "okay";
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi b/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
index 5dcd1de586b5..6a1890a4b5d8 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp-verdin.dtsi
@@ -3,7 +3,8 @@
* Copyright 2022 Toradex
*/
-#include "dt-bindings/pwm/pwm.h"
+#include <dt-bindings/phy/phy-imx8-pcie.h>
+#include <dt-bindings/pwm/pwm.h>
#include "imx8mp.dtsi"
/ {
@@ -678,8 +679,8 @@
status = "disabled";
};
- lvds_ti_sn65dsi83: bridge@2c {
- compatible = "ti,sn65dsi83";
+ lvds_ti_sn65dsi84: bridge@2c {
+ compatible = "ti,sn65dsi84";
/* Verdin GPIO_9_DSI (SN65DSI84 IRQ, SODIMM 17, unused) */
/* Verdin GPIO_10_DSI (SODIMM 21) */
enable-gpios = <&gpio4 28 GPIO_ACTIVE_HIGH>;
@@ -712,7 +713,7 @@
compatible = "atmel,maxtouch";
/*
* Verdin GPIO_9_DSI
- * (TOUCH_INT#, SODIMM 17, also routed to SN65DSI83 IRQ albeit currently unused)
+ * (TOUCH_INT#, SODIMM 17, also routed to SN65DSI84 IRQ albeit currently unused)
*/
interrupt-parent = <&gpio4>;
interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
@@ -806,28 +807,45 @@
};
/* Verdin USB_1 */
-&usb3_phy0 {
- vbus-supply = <&reg_usb1_vbus>;
+&usb3_0 {
+ fsl,disable-port-power-control;
+ fsl,over-current-active-low;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_1_oc_n>;
};
&usb_dwc3_0 {
+ /* dual role only, not full featured OTG */
adp-disable;
dr_mode = "otg";
hnp-disable;
maximum-speed = "high-speed";
- over-current-active-low;
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_usb_1_id>;
+ role-switch-default-mode = "peripheral";
srp-disable;
+ usb-role-switch;
+
+ connector {
+ compatible = "gpio-usb-b-connector", "usb-b-connector";
+ id-gpios = <&gpio2 10 GPIO_ACTIVE_HIGH>;
+ label = "Type-C";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usb_1_id>;
+ self-powered;
+ type = "micro";
+ vbus-supply = <&reg_usb1_vbus>;
+ };
};
/* Verdin USB_2 */
+&usb3_1 {
+ fsl,disable-port-power-control;
+};
+
&usb3_phy1 {
vbus-supply = <&reg_usb2_vbus>;
};
&usb_dwc3_1 {
- disable-over-current;
dr_mode = "host";
};
@@ -1045,7 +1063,6 @@
pinctrl_gpio_hog3: gpiohog3grp {
fsl,pins =
- <MX8MP_IOMUXC_GPIO1_IO13__GPIO1_IO13 0x1c4>, /* SODIMM 157 */
/* CSI_1_MCLK */
<MX8MP_IOMUXC_GPIO1_IO15__GPIO1_IO15 0x1c4>; /* SODIMM 91 */
};
@@ -1220,7 +1237,7 @@
pinctrl_usb1_vbus: usb1vbusgrp {
fsl,pins =
- <MX8MP_IOMUXC_GPIO1_IO12__USB1_OTG_PWR 0x19>; /* SODIMM 155 */
+ <MX8MP_IOMUXC_GPIO1_IO12__GPIO1_IO12 0x106>; /* SODIMM 155 */
};
/* USB_1_ID */
@@ -1229,9 +1246,15 @@
<MX8MP_IOMUXC_SD1_RESET_B__GPIO2_IO10 0x1c4>; /* SODIMM 161 */
};
+ /* USB_1_OC# */
+ pinctrl_usb_1_oc_n: usb1ocngrp {
+ fsl,pins =
+ <MX8MP_IOMUXC_GPIO1_IO13__USB1_OTG_OC 0x1c4>; /* SODIMM 157 */
+ };
+
pinctrl_usb2_vbus: usb2vbusgrp {
fsl,pins =
- <MX8MP_IOMUXC_GPIO1_IO14__USB2_OTG_PWR 0x19>; /* SODIMM 185 */
+ <MX8MP_IOMUXC_GPIO1_IO14__GPIO1_IO14 0x106>; /* SODIMM 185 */
};
/* On-module Wi-Fi */
diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
index bb916a0948a8..7a6e6221f421 100644
--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi
@@ -123,6 +123,7 @@
A53_L2: l2-cache0 {
compatible = "cache";
+ cache-unified;
cache-level = <2>;
cache-size = <0x80000>;
cache-line-size = <64>;
@@ -441,10 +442,10 @@
};
};
- anatop: anatop@30360000 {
- compatible = "fsl,imx8mp-anatop", "fsl,imx8mm-anatop",
- "syscon";
+ anatop: clock-controller@30360000 {
+ compatible = "fsl,imx8mp-anatop", "fsl,imx8mm-anatop";
reg = <0x30360000 0x10000>;
+ #clock-cells = <1>;
};
snvs: snvs@30370000 {
@@ -631,6 +632,14 @@
reg = <IMX8MP_POWER_DOMAIN_VPU_VC8000E>;
clocks = <&clk IMX8MP_CLK_VPU_VC8KE_ROOT>;
};
+
+ pgc_mlmix: power-domain@24 {
+ #power-domain-cells = <0>;
+ reg = <IMX8MP_POWER_DOMAIN_MLMIX>;
+ clocks = <&clk IMX8MP_CLK_ML_AXI>,
+ <&clk IMX8MP_CLK_ML_AHB>,
+ <&clk IMX8MP_CLK_NPU_ROOT>;
+ };
};
};
};
@@ -705,12 +714,15 @@
ecspi1: spi@30820000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx8mp-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx8mp-ecspi", "fsl,imx6ul-ecspi";
reg = <0x30820000 0x10000>;
interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX8MP_CLK_ECSPI1_ROOT>,
<&clk IMX8MP_CLK_ECSPI1_ROOT>;
clock-names = "ipg", "per";
+ assigned-clock-rates = <80000000>;
+ assigned-clocks = <&clk IMX8MP_CLK_ECSPI1>;
+ assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>;
dmas = <&sdma1 0 7 1>, <&sdma1 1 7 2>;
dma-names = "rx", "tx";
status = "disabled";
@@ -719,12 +731,15 @@
ecspi2: spi@30830000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx8mp-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx8mp-ecspi", "fsl,imx6ul-ecspi";
reg = <0x30830000 0x10000>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX8MP_CLK_ECSPI2_ROOT>,
<&clk IMX8MP_CLK_ECSPI2_ROOT>;
clock-names = "ipg", "per";
+ assigned-clock-rates = <80000000>;
+ assigned-clocks = <&clk IMX8MP_CLK_ECSPI2>;
+ assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>;
dmas = <&sdma1 2 7 1>, <&sdma1 3 7 2>;
dma-names = "rx", "tx";
status = "disabled";
@@ -733,12 +748,15 @@
ecspi3: spi@30840000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "fsl,imx8mp-ecspi", "fsl,imx51-ecspi";
+ compatible = "fsl,imx8mp-ecspi", "fsl,imx6ul-ecspi";
reg = <0x30840000 0x10000>;
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX8MP_CLK_ECSPI3_ROOT>,
<&clk IMX8MP_CLK_ECSPI3_ROOT>;
clock-names = "ipg", "per";
+ assigned-clock-rates = <80000000>;
+ assigned-clocks = <&clk IMX8MP_CLK_ECSPI3>;
+ assigned-clock-parents = <&clk IMX8MP_SYS_PLL1_800M>;
dmas = <&sdma1 4 7 1>, <&sdma1 5 7 2>;
dma-names = "rx", "tx";
status = "disabled";
@@ -1063,11 +1081,11 @@
noc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-200M {
+ opp-200000000 {
opp-hz = /bits/ 64 <200000000>;
};
- opp-1000M {
+ opp-1000000000 {
opp-hz = /bits/ 64 <1000000000>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
index 82387b9cb800..78937910f403 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts
@@ -46,6 +46,7 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+ off-on-delay-us = <20000>;
enable-active-high;
};
@@ -163,22 +164,22 @@
ddrc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-25M {
+ opp-25000000 {
opp-hz = /bits/ 64 <25000000>;
};
- opp-100M {
+ opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
};
/*
* On imx8mq B0 PLL can't be bypassed so low bus is 166M
*/
- opp-166M {
+ opp-166000000 {
opp-hz = /bits/ 64 <166935483>;
};
- opp-800M {
+ opp-800000000 {
opp-hz = /bits/ 64 <800000000>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts
index 6445c6b90b5b..4c8904fba1c1 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts
+++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts
@@ -7,6 +7,7 @@
#include "dt-bindings/input/input.h"
#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/leds/common.h>
#include "dt-bindings/pwm/pwm.h"
#include "dt-bindings/usb/pd.h"
#include "imx8mq.dtsi"
@@ -61,14 +62,13 @@
};
leds {
- compatible = "gpio-leds";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_gpio_leds>;
+ compatible = "pwm-leds";
led1 {
- label = "LED 1";
- gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
- default-state = "off";
+ function = LED_FUNCTION_STATUS;
+ color = <LED_COLOR_ID_RED>;
+ max-brightness = <248>;
+ pwms = <&pwm2 0 50000 0>;
};
};
@@ -615,9 +615,9 @@
>;
};
- pinctrl_gpio_leds: gpioledgrp {
+ pinctrl_pwm_led: pwmledgrp {
fsl,pins = <
- MX8MQ_IOMUXC_GPIO1_IO13_GPIO1_IO13 0x16
+ MX8MQ_IOMUXC_GPIO1_IO13_PWM2_OUT 0x16
>;
};
@@ -920,6 +920,12 @@
status = "okay";
};
+&pwm2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_pwm_led>;
+ status = "okay";
+};
+
&snvs_pwrkey {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
index ae08556b2ef2..ddf0e330dc7c 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq-librem5.dtsi
@@ -311,15 +311,15 @@
ddrc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-25M {
+ opp-25000000 {
opp-hz = /bits/ 64 <25000000>;
};
- opp-100M {
+ opp-100000000 {
opp-hz = /bits/ 64 <100000000>;
};
- opp-800M {
+ opp-800000000 {
opp-hz = /bits/ 64 <800000000>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq-tqma8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq-tqma8mq.dtsi
index 802ad6e5cef6..9a95e30fb42d 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq-tqma8mq.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq-tqma8mq.dtsi
@@ -220,12 +220,14 @@
reg = <0x53>;
pagesize = <16>;
read-only;
+ vcc-supply = <&reg_vcc3v3>;
};
eeprom0: eeprom@57 {
compatible = "atmel,24c64";
reg = <0x57>;
pagesize = <32>;
+ vcc-supply = <&reg_vcc3v3>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8mq.dtsi b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
index 19eaa523564d..7ce99c084e54 100644
--- a/arch/arm64/boot/dts/freescale/imx8mq.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8mq.dtsi
@@ -179,6 +179,7 @@
A53_L2: l2-cache0 {
compatible = "cache";
cache-level = <2>;
+ cache-unified;
cache-size = <0x100000>;
cache-line-size = <64>;
cache-sets = <1024>;
@@ -605,10 +606,11 @@
};
};
- anatop: syscon@30360000 {
- compatible = "fsl,imx8mq-anatop", "syscon";
+ anatop: clock-controller@30360000 {
+ compatible = "fsl,imx8mq-anatop";
reg = <0x30360000 0x10000>;
interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+ #clock-cells = <1>;
};
snvs: snvs@30370000 {
@@ -1184,7 +1186,7 @@
};
csi1: csi@30a90000 {
- compatible = "fsl,imx8mq-csi", "fsl,imx7-csi";
+ compatible = "fsl,imx8mq-csi";
reg = <0x30a90000 0x10000>;
interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX8MQ_CLK_CSI1_ROOT>;
@@ -1236,7 +1238,7 @@
};
csi2: csi@30b80000 {
- compatible = "fsl,imx8mq-csi", "fsl,imx7-csi";
+ compatible = "fsl,imx8mq-csi";
reg = <0x30b80000 0x10000>;
interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX8MQ_CLK_CSI2_ROOT>;
@@ -1356,15 +1358,15 @@
noc_opp_table: opp-table {
compatible = "operating-points-v2";
- opp-133M {
+ opp-133000000 {
opp-hz = /bits/ 64 <133333333>;
};
- opp-400M {
+ opp-400000000 {
opp-hz = /bits/ 64 <400000000>;
};
- opp-800M {
+ opp-800000000 {
opp-hz = /bits/ 64 <800000000>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx8qm-ss-lsio.dtsi b/arch/arm64/boot/dts/freescale/imx8qm-ss-lsio.dtsi
index 669aa14ce9f7..b483134f84d1 100644
--- a/arch/arm64/boot/dts/freescale/imx8qm-ss-lsio.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qm-ss-lsio.dtsi
@@ -6,30 +6,68 @@
&lsio_gpio0 {
compatible = "fsl,imx8qm-gpio", "fsl,imx35-gpio";
+ gpio-ranges = <&iomuxc 0 0 6>,
+ <&iomuxc 6 7 22>,
+ <&iomuxc 28 36 4>;
};
&lsio_gpio1 {
compatible = "fsl,imx8qm-gpio", "fsl,imx35-gpio";
+ gpio-ranges = <&iomuxc 0 40 4>,
+ <&iomuxc 4 50 12>,
+ <&iomuxc 16 63 8>,
+ <&iomuxc 24 72 8>;
};
&lsio_gpio2 {
compatible = "fsl,imx8qm-gpio", "fsl,imx35-gpio";
+ gpio-ranges = <&iomuxc 0 80 4>,
+ <&iomuxc 4 85 18>,
+ <&iomuxc 22 104 10>;
};
&lsio_gpio3 {
compatible = "fsl,imx8qm-gpio", "fsl,imx35-gpio";
+ gpio-ranges = <&iomuxc 0 114 2>,
+ <&iomuxc 2 117 16>,
+ <&iomuxc 18 141 1>,
+ <&iomuxc 19 140 1>,
+ <&iomuxc 20 139 1>,
+ <&iomuxc 21 138 1>,
+ <&iomuxc 22 137 1>,
+ <&iomuxc 23 136 1>,
+ <&iomuxc 24 135 1>,
+ <&iomuxc 25 134 1>,
+ <&iomuxc 26 142 3>,
+ <&iomuxc 29 146 3>;
};
&lsio_gpio4 {
compatible = "fsl,imx8qm-gpio", "fsl,imx35-gpio";
+ gpio-ranges = <&iomuxc 0 149 3>,
+ <&iomuxc 3 153 4>,
+ <&iomuxc 7 158 6>,
+ <&iomuxc 13 165 6>,
+ <&iomuxc 19 172 8>,
+ <&iomuxc 27 198 5>;
};
&lsio_gpio5 {
compatible = "fsl,imx8qm-gpio", "fsl,imx35-gpio";
+ gpio-ranges = <&iomuxc 0 203 1>,
+ <&iomuxc 1 205 2>,
+ <&iomuxc 3 210 11>,
+ <&iomuxc 14 223 3>,
+ <&iomuxc 17 227 2>,
+ <&iomuxc 19 230 5>,
+ <&iomuxc 24 236 6>,
+ <&iomuxc 30 243 2>;
};
&lsio_gpio6 {
compatible = "fsl,imx8qm-gpio", "fsl,imx35-gpio";
+ gpio-ranges = <&iomuxc 0 245 10>,
+ <&iomuxc 10 256 12>;
};
&lsio_gpio7 {
diff --git a/arch/arm64/boot/dts/freescale/imx8qm.dtsi b/arch/arm64/boot/dts/freescale/imx8qm.dtsi
index c9c2b6536233..41ce8336f29e 100644
--- a/arch/arm64/boot/dts/freescale/imx8qm.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qm.dtsi
@@ -136,6 +136,7 @@
A53_L2: l2-cache0 {
compatible = "cache";
cache-level = <2>;
+ cache-unified;
cache-size = <0x100000>;
cache-line-size = <64>;
cache-sets = <1024>;
@@ -144,6 +145,7 @@
A72_L2: l2-cache1 {
compatible = "cache";
cache-level = <2>;
+ cache-unified;
cache-size = <0x100000>;
cache-line-size = <64>;
cache-sets = <1024>;
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-colibri-eval-v3.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp-colibri-eval-v3.dtsi
index a08e70fb7c7a..7c334b93db3b 100644
--- a/arch/arm64/boot/dts/freescale/imx8qxp-colibri-eval-v3.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-colibri-eval-v3.dtsi
@@ -3,7 +3,7 @@
* Copyright 2019 Toradex
*/
-#include "dt-bindings/input/linux-event-codes.h"
+#include <dt-bindings/input/linux-event-codes.h>
/ {
aliases {
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp-ss-lsio.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp-ss-lsio.dtsi
index 8e2152c6eb88..8f722b1dd078 100644
--- a/arch/arm64/boot/dts/freescale/imx8qxp-ss-lsio.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qxp-ss-lsio.dtsi
@@ -6,26 +6,51 @@
&lsio_gpio0 {
compatible = "fsl,imx8qxp-gpio", "fsl,imx35-gpio";
+ gpio-ranges = <&iomuxc 1 56 12>,
+ <&iomuxc 13 69 4>,
+ <&iomuxc 19 75 4>,
+ <&iomuxc 24 80 1>,
+ <&iomuxc 25 82 7>;
};
&lsio_gpio1 {
compatible = "fsl,imx8qxp-gpio", "fsl,imx35-gpio";
+ gpio-ranges = <&iomuxc 0 89 9>,
+ <&iomuxc 9 99 16>,
+ <&iomuxc 25 116 7>;
};
&lsio_gpio2 {
compatible = "fsl,imx8qxp-gpio", "fsl,imx35-gpio";
+ gpio-ranges = <&iomuxc 0 123 1>,
+ <&iomuxc 1 126 2>,
+ <&iomuxc 3 129 1>;
};
&lsio_gpio3 {
compatible = "fsl,imx8qxp-gpio", "fsl,imx35-gpio";
+ gpio-ranges = <&iomuxc 0 146 4>,
+ <&iomuxc 4 151 13>,
+ <&iomuxc 17 165 8>;
};
&lsio_gpio4 {
compatible = "fsl,imx8qxp-gpio", "fsl,imx35-gpio";
+ gpio-ranges = <&iomuxc 0 0 3>,
+ <&iomuxc 3 4 4>,
+ <&iomuxc 7 9 6>,
+ <&iomuxc 13 16 6>,
+ <&iomuxc 19 23 2>,
+ <&iomuxc 21 26 2>,
+ <&iomuxc 23 30 6>,
+ <&iomuxc 29 37 3>;
};
&lsio_gpio5 {
compatible = "fsl,imx8qxp-gpio", "fsl,imx35-gpio";
+ gpio-ranges = <&iomuxc 0 40 3>,
+ <&iomuxc 3 44 6>,
+ <&iomuxc 9 51 3>;
};
&lsio_gpio6 {
diff --git a/arch/arm64/boot/dts/freescale/imx8qxp.dtsi b/arch/arm64/boot/dts/freescale/imx8qxp.dtsi
index f4ea18bb95ab..85c0b1d2bac5 100644
--- a/arch/arm64/boot/dts/freescale/imx8qxp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8qxp.dtsi
@@ -127,6 +127,7 @@
A35_L2: l2-cache0 {
compatible = "cache";
cache-level = <2>;
+ cache-unified;
cache-size = <0x80000>;
cache-line-size = <64>;
cache-sets = <1024>;
diff --git a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
index 06ce5f19aa8a..32193a43ff49 100644
--- a/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx8ulp.dtsi
@@ -51,6 +51,7 @@
A35_L2: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/imx93.dtsi b/arch/arm64/boot/dts/freescale/imx93.dtsi
index 0247866fc86b..5d79663b3b84 100644
--- a/arch/arm64/boot/dts/freescale/imx93.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx93.dtsi
@@ -17,6 +17,10 @@
#size-cells = <2>;
aliases {
+ gpio0 = &gpio1;
+ gpio1 = &gpio2;
+ gpio2 = &gpio3;
+ gpio3 = &gpio4;
i2c0 = &lpi2c1;
i2c1 = &lpi2c2;
i2c2 = &lpi2c3;
@@ -135,6 +139,7 @@
compatible = "fsl,imx93-mu", "fsl,imx8ulp-mu";
reg = <0x44230000 0x10000>;
interrupts = <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX93_CLK_MU1_B_GATE>;
#mbox-cells = <2>;
status = "disabled";
};
@@ -145,6 +150,15 @@
interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&osc_24m>;
clock-names = "per";
+ nxp,no-divider;
+ };
+
+ tpm2: pwm@44320000 {
+ compatible = "fsl,imx7ulp-pwm";
+ reg = <0x44320000 0x10000>;
+ clocks = <&clk IMX93_CLK_TPM2_GATE>;
+ #pwm-cells = <3>;
+ status = "disabled";
};
lpi2c1: i2c@44340000 {
@@ -270,10 +284,35 @@
compatible = "fsl,imx93-mu", "fsl,imx8ulp-mu";
reg = <0x42440000 0x10000>;
interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX93_CLK_MU2_B_GATE>;
#mbox-cells = <2>;
status = "disabled";
};
+ tpm4: pwm@424f0000 {
+ compatible = "fsl,imx7ulp-pwm";
+ reg = <0x424f0000 0x10000>;
+ clocks = <&clk IMX93_CLK_TPM4_GATE>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ tpm5: pwm@42500000 {
+ compatible = "fsl,imx7ulp-pwm";
+ reg = <0x42500000 0x10000>;
+ clocks = <&clk IMX93_CLK_TPM5_GATE>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ tpm6: pwm@42510000 {
+ compatible = "fsl,imx7ulp-pwm";
+ reg = <0x42510000 0x10000>;
+ clocks = <&clk IMX93_CLK_TPM6_GATE>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
lpi2c3: i2c@42530000 {
compatible = "fsl,imx93-lpi2c", "fsl,imx7ulp-lpi2c";
reg = <0x42530000 0x10000>;
@@ -294,6 +333,30 @@
status = "disabled";
};
+ lpspi3: spi@42550000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx93-spi", "fsl,imx7ulp-spi";
+ reg = <0x42550000 0x10000>;
+ interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX93_CLK_LPSPI3_GATE>,
+ <&clk IMX93_CLK_BUS_WAKEUP>;
+ clock-names = "per", "ipg";
+ status = "disabled";
+ };
+
+ lpspi4: spi@42560000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx93-spi", "fsl,imx7ulp-spi";
+ reg = <0x42560000 0x10000>;
+ interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX93_CLK_LPSPI4_GATE>,
+ <&clk IMX93_CLK_BUS_WAKEUP>;
+ clock-names = "per", "ipg";
+ status = "disabled";
+ };
+
lpuart3: serial@42570000 {
compatible = "fsl,imx93-lpuart", "fsl,imx7ulp-lpuart";
reg = <0x42570000 0x1000>;
@@ -388,6 +451,54 @@
status = "disabled";
};
+ lpspi5: spi@426f0000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx93-spi", "fsl,imx7ulp-spi";
+ reg = <0x426f0000 0x10000>;
+ interrupts = <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX93_CLK_LPSPI5_GATE>,
+ <&clk IMX93_CLK_BUS_WAKEUP>;
+ clock-names = "per", "ipg";
+ status = "disabled";
+ };
+
+ lpspi6: spi@42700000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx93-spi", "fsl,imx7ulp-spi";
+ reg = <0x42700000 0x10000>;
+ interrupts = <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX93_CLK_LPSPI6_GATE>,
+ <&clk IMX93_CLK_BUS_WAKEUP>;
+ clock-names = "per", "ipg";
+ status = "disabled";
+ };
+
+ lpspi7: spi@42710000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx93-spi", "fsl,imx7ulp-spi";
+ reg = <0x42710000 0x10000>;
+ interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX93_CLK_LPSPI7_GATE>,
+ <&clk IMX93_CLK_BUS_WAKEUP>;
+ clock-names = "per", "ipg";
+ status = "disabled";
+ };
+
+ lpspi8: spi@42720000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "fsl,imx93-spi", "fsl,imx7ulp-spi";
+ reg = <0x42720000 0x10000>;
+ interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&clk IMX93_CLK_LPSPI8_GATE>,
+ <&clk IMX93_CLK_BUS_WAKEUP>;
+ clock-names = "per", "ipg";
+ status = "disabled";
+ };
+
};
aips3: bus@42800000 {
diff --git a/arch/arm64/boot/dts/freescale/mba8mx.dtsi b/arch/arm64/boot/dts/freescale/mba8mx.dtsi
index 104bdd4e437a..daa37adeff3b 100644
--- a/arch/arm64/boot/dts/freescale/mba8mx.dtsi
+++ b/arch/arm64/boot/dts/freescale/mba8mx.dtsi
@@ -215,6 +215,7 @@
compatible = "nxp,se97b", "atmel,24c02";
reg = <0x57>;
pagesize = <16>;
+ vcc-supply = <&reg_vcc_3v3>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/s32g2.dtsi b/arch/arm64/boot/dts/freescale/s32g2.dtsi
index 824d401e7a2c..d8c82da88ca0 100644
--- a/arch/arm64/boot/dts/freescale/s32g2.dtsi
+++ b/arch/arm64/boot/dts/freescale/s32g2.dtsi
@@ -52,10 +52,12 @@
cluster0_l2: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
cluster1_l2: l2-cache1 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/freescale/s32v234.dtsi b/arch/arm64/boot/dts/freescale/s32v234.dtsi
index ba0b5305d481..3e306218d533 100644
--- a/arch/arm64/boot/dts/freescale/s32v234.dtsi
+++ b/arch/arm64/boot/dts/freescale/s32v234.dtsi
@@ -61,10 +61,12 @@
cluster0_l2_cache: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
cluster1_l2_cache: l2-cache1 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
index 8343d0cedde3..a57f35eb5ef6 100644
--- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi
@@ -203,10 +203,12 @@
A53_L2: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
A73_L2: l2-cache1 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
index ae0a7cfeeb47..f6d3202b0d1a 100644
--- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
@@ -186,10 +186,12 @@
CLUSTER0_L2: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
CLUSTER1_L2: l2-cache1 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/hisilicon/hip05.dtsi b/arch/arm64/boot/dts/hisilicon/hip05.dtsi
index 7b2abd10d3d6..5b2b1bfd0d2a 100644
--- a/arch/arm64/boot/dts/hisilicon/hip05.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hip05.dtsi
@@ -211,18 +211,22 @@
cluster0_l2: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
cluster1_l2: l2-cache1 {
compatible = "cache";
+ cache-level = <2>;
};
cluster2_l2: l2-cache2 {
compatible = "cache";
+ cache-level = <2>;
};
cluster3_l2: l2-cache3 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/hisilicon/hip06.dtsi b/arch/arm64/boot/dts/hisilicon/hip06.dtsi
index 2f8b03b0d365..291c2ee38288 100644
--- a/arch/arm64/boot/dts/hisilicon/hip06.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hip06.dtsi
@@ -211,18 +211,22 @@
cluster0_l2: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
cluster1_l2: l2-cache1 {
compatible = "cache";
+ cache-level = <2>;
};
cluster2_l2: l2-cache2 {
compatible = "cache";
+ cache-level = <2>;
};
cluster3_l2: l2-cache3 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/hisilicon/hip07.dtsi b/arch/arm64/boot/dts/hisilicon/hip07.dtsi
index 1a16662f8867..b8746fb959b5 100644
--- a/arch/arm64/boot/dts/hisilicon/hip07.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hip07.dtsi
@@ -842,66 +842,82 @@
cluster0_l2: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
cluster1_l2: l2-cache1 {
compatible = "cache";
+ cache-level = <2>;
};
cluster2_l2: l2-cache2 {
compatible = "cache";
+ cache-level = <2>;
};
cluster3_l2: l2-cache3 {
compatible = "cache";
+ cache-level = <2>;
};
cluster4_l2: l2-cache4 {
compatible = "cache";
+ cache-level = <2>;
};
cluster5_l2: l2-cache5 {
compatible = "cache";
+ cache-level = <2>;
};
cluster6_l2: l2-cache6 {
compatible = "cache";
+ cache-level = <2>;
};
cluster7_l2: l2-cache7 {
compatible = "cache";
+ cache-level = <2>;
};
cluster8_l2: l2-cache8 {
compatible = "cache";
+ cache-level = <2>;
};
cluster9_l2: l2-cache9 {
compatible = "cache";
+ cache-level = <2>;
};
cluster10_l2: l2-cache10 {
compatible = "cache";
+ cache-level = <2>;
};
cluster11_l2: l2-cache11 {
compatible = "cache";
+ cache-level = <2>;
};
cluster12_l2: l2-cache12 {
compatible = "cache";
+ cache-level = <2>;
};
cluster13_l2: l2-cache13 {
compatible = "cache";
+ cache-level = <2>;
};
cluster14_l2: l2-cache14 {
compatible = "cache";
+ cache-level = <2>;
};
cluster15_l2: l2-cache15 {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi b/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi
index 7bbec8aafa62..849b46dd8098 100644
--- a/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi
+++ b/arch/arm64/boot/dts/intel/socfpga_agilex.dtsi
@@ -313,6 +313,7 @@
<&clkmgr AGILEX_SDMMC_CLK>;
clock-names = "biu", "ciu";
iommus = <&smmu 5>;
+ altr,sysmgr-syscon = <&sysmgr 0x28 4>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts b/arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts
index 26cd3c121757..07c3f8876613 100644
--- a/arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts
+++ b/arch/arm64/boot/dts/intel/socfpga_agilex_socdk.dts
@@ -83,6 +83,7 @@
cap-sd-highspeed;
broken-cd;
bus-width = <4>;
+ clk-phase-sd-hs = <0>, <135>;
};
&osc1 {
diff --git a/arch/arm64/boot/dts/intel/socfpga_n5x_socdk.dts b/arch/arm64/boot/dts/intel/socfpga_n5x_socdk.dts
index 62c66e52b656..08c088571270 100644
--- a/arch/arm64/boot/dts/intel/socfpga_n5x_socdk.dts
+++ b/arch/arm64/boot/dts/intel/socfpga_n5x_socdk.dts
@@ -74,6 +74,7 @@
cap-sd-highspeed;
broken-cd;
bus-width = <4>;
+ clk-phase-sd-hs = <0>, <135>;
};
&osc1 {
diff --git a/arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi b/arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi
index 44ed6f963b75..7308f7b6b22c 100644
--- a/arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi
+++ b/arch/arm64/boot/dts/marvell/ac5-98dx25xx.dtsi
@@ -49,6 +49,7 @@
l2: l2-cache {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
index ada164d423f3..cd0988317623 100644
--- a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
+++ b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
@@ -125,9 +125,12 @@
/delete-property/ mrvl,i2c-fast-mode;
status = "okay";
+ /* MCP7940MT-I/MNY RTC */
rtc@6f {
compatible = "microchip,mcp7940x";
reg = <0x6f>;
+ interrupt-parent = <&gpiosb>;
+ interrupts = <5 0>; /* GPIO2_5 */
};
};
@@ -136,6 +139,7 @@
pinctrl-0 = <&pcie_reset_pins &pcie_clkreq_pins>;
status = "okay";
reset-gpios = <&gpiosb 3 GPIO_ACTIVE_LOW>;
+ slot-power-limit-milliwatt = <10000>;
/*
* U-Boot port for Turris Mox has a bug which always expects that "ranges" DT property
* contains exactly 2 ranges with 3 (child) address cells, 2 (parent) address cells and
diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
index df152c72276b..e300145ad1a6 100644
--- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi
@@ -35,6 +35,11 @@
reg = <0 0x4000000 0 0x200000>;
no-map;
};
+
+ tee@4400000 {
+ reg = <0 0x4400000 0 0x1000000>;
+ no-map;
+ };
};
cpus {
diff --git a/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi
index fcab5173fe67..990f70303fe6 100644
--- a/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-ap806-dual.dtsi
@@ -51,6 +51,7 @@
cache-size = <0x80000>;
cache-line-size = <64>;
cache-sets = <512>;
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi b/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi
index 3db427122f9e..a7b8e001cc9c 100644
--- a/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-ap806-quad.dtsi
@@ -81,6 +81,7 @@
cache-size = <0x80000>;
cache-line-size = <64>;
cache-sets = <512>;
+ cache-level = <2>;
};
l2_1: l2-cache1 {
@@ -88,6 +89,7 @@
cache-size = <0x80000>;
cache-line-size = <64>;
cache-sets = <512>;
+ cache-level = <2>;
};
};
};
diff --git a/arch/arm64/boot/dts/marvell/armada-ap807-quad.dtsi b/arch/arm64/boot/dts/marvell/armada-ap807-quad.dtsi
index 68782f161f12..7740098fd108 100644
--- a/arch/arm64/boot/dts/marvell/armada-ap807-quad.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-ap807-quad.dtsi
@@ -81,6 +81,7 @@
cache-size = <0x80000>;
cache-line-size = <64>;
cache-sets = <512>;
+ cache-level = <2>;
};
l2_1: l2-cache1 {
@@ -88,6 +89,7 @@
cache-size = <0x80000>;
cache-line-size = <64>;
cache-sets = <512>;
+ cache-level = <2>;
};
};
};
diff --git a/arch/arm64/boot/dts/marvell/armada-ap80x.dtsi b/arch/arm64/boot/dts/marvell/armada-ap80x.dtsi
index a06a0a889c43..4e6d29ad32eb 100644
--- a/arch/arm64/boot/dts/marvell/armada-ap80x.dtsi
+++ b/arch/arm64/boot/dts/marvell/armada-ap80x.dtsi
@@ -41,6 +41,11 @@
reg = <0x0 0x4000000 0x0 0x200000>;
no-map;
};
+
+ tee@4400000 {
+ reg = <0 0x4400000 0 0x1000000>;
+ no-map;
+ };
};
AP_NAME {
diff --git a/arch/arm64/boot/dts/mediatek/Makefile b/arch/arm64/boot/dts/mediatek/Makefile
index 0ec90cb3ef28..813e735c5b96 100644
--- a/arch/arm64/boot/dts/mediatek/Makefile
+++ b/arch/arm64/boot/dts/mediatek/Makefile
@@ -3,6 +3,7 @@ dtb-$(CONFIG_ARCH_MEDIATEK) += mt2712-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6755-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6779-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6795-evb.dtb
+dtb-$(CONFIG_ARCH_MEDIATEK) += mt6795-sony-xperia-m5.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-evb.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt6797-x20-dev.dtb
dtb-$(CONFIG_ARCH_MEDIATEK) += mt7622-rfb1.dtb
diff --git a/arch/arm64/boot/dts/mediatek/mt2712-evb.dts b/arch/arm64/boot/dts/mediatek/mt2712-evb.dts
index 9b1af9c80130..d31a194124c9 100644
--- a/arch/arm64/boot/dts/mediatek/mt2712-evb.dts
+++ b/arch/arm64/boot/dts/mediatek/mt2712-evb.dts
@@ -26,14 +26,14 @@
stdout-path = "serial0:921600n8";
};
- cpus_fixed_vproc0: fixedregulator@0 {
+ cpus_fixed_vproc0: regulator-vproc-buck0 {
compatible = "regulator-fixed";
regulator-name = "vproc_buck0";
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
};
- cpus_fixed_vproc1: fixedregulator@1 {
+ cpus_fixed_vproc1: regulator-vproc-buck1 {
compatible = "regulator-fixed";
regulator-name = "vproc_buck1";
regulator-min-microvolt = <1000000>;
@@ -50,7 +50,7 @@
id-gpio = <&pio 14 GPIO_ACTIVE_HIGH>;
};
- usb_p0_vbus: regulator@2 {
+ usb_p0_vbus: regulator-usb-p0-vbus {
compatible = "regulator-fixed";
regulator-name = "p0_vbus";
regulator-min-microvolt = <5000000>;
@@ -59,7 +59,7 @@
enable-active-high;
};
- usb_p1_vbus: regulator@3 {
+ usb_p1_vbus: regulator-usb-p1-vbus {
compatible = "regulator-fixed";
regulator-name = "p1_vbus";
regulator-min-microvolt = <5000000>;
@@ -68,7 +68,7 @@
enable-active-high;
};
- usb_p2_vbus: regulator@4 {
+ usb_p2_vbus: regulator-usb-p2-vbus {
compatible = "regulator-fixed";
regulator-name = "p2_vbus";
regulator-min-microvolt = <5000000>;
@@ -77,7 +77,7 @@
enable-active-high;
};
- usb_p3_vbus: regulator@5 {
+ usb_p3_vbus: regulator-usb-p3-vbus {
compatible = "regulator-fixed";
regulator-name = "p3_vbus";
regulator-min-microvolt = <5000000>;
diff --git a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
index e6d7453e56e0..92212cddd37e 100644
--- a/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt2712e.dtsi
@@ -160,70 +160,70 @@
#clock-cells = <0>;
};
- clk26m: oscillator@0 {
+ clk26m: oscillator-26m {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <26000000>;
clock-output-names = "clk26m";
};
- clk32k: oscillator@1 {
+ clk32k: oscillator-32k {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32768>;
clock-output-names = "clk32k";
};
- clkfpc: oscillator@2 {
+ clkfpc: oscillator-50m {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <50000000>;
clock-output-names = "clkfpc";
};
- clkaud_ext_i_0: oscillator@3 {
+ clkaud_ext_i_0: oscillator-aud0 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <6500000>;
clock-output-names = "clkaud_ext_i_0";
};
- clkaud_ext_i_1: oscillator@4 {
+ clkaud_ext_i_1: oscillator-aud1 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <196608000>;
clock-output-names = "clkaud_ext_i_1";
};
- clkaud_ext_i_2: oscillator@5 {
+ clkaud_ext_i_2: oscillator-aud2 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <180633600>;
clock-output-names = "clkaud_ext_i_2";
};
- clki2si0_mck_i: oscillator@6 {
+ clki2si0_mck_i: oscillator-i2s0 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <30000000>;
clock-output-names = "clki2si0_mck_i";
};
- clki2si1_mck_i: oscillator@7 {
+ clki2si1_mck_i: oscillator-i2s1 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <30000000>;
clock-output-names = "clki2si1_mck_i";
};
- clki2si2_mck_i: oscillator@8 {
+ clki2si2_mck_i: oscillator-i2s2 {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <30000000>;
clock-output-names = "clki2si2_mck_i";
};
- clktdmin_mclk_i: oscillator@9 {
+ clktdmin_mclk_i: oscillator-mclk {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <30000000>;
@@ -266,7 +266,7 @@
reg = <0 0x10005000 0 0x1000>;
};
- pio: pinctrl@10005000 {
+ pio: pinctrl@1000b000 {
compatible = "mediatek,mt2712-pinctrl";
reg = <0 0x1000b000 0 0x1000>;
mediatek,pctl-regmap = <&syscfg_pctl_a>;
@@ -766,9 +766,9 @@
interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_LOW>;
clocks = <&pericfg CLK_PERI_MSDC30_0>,
<&pericfg CLK_PERI_MSDC50_0_HCLK_EN>,
- <&pericfg CLK_PERI_MSDC30_0_QTR_EN>,
- <&pericfg CLK_PERI_MSDC50_0_EN>;
- clock-names = "source", "hclk", "bus_clk", "source_cg";
+ <&pericfg CLK_PERI_MSDC50_0_EN>,
+ <&pericfg CLK_PERI_MSDC30_0_QTR_EN>;
+ clock-names = "source", "hclk", "source_cg", "bus_clk";
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/mediatek/mt6779.dtsi b/arch/arm64/boot/dts/mediatek/mt6779.dtsi
index 9bdf5145966c..5c579e88e749 100644
--- a/arch/arm64/boot/dts/mediatek/mt6779.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt6779.dtsi
@@ -88,14 +88,14 @@
interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW 0>;
};
- clk26m: oscillator@0 {
+ clk26m: oscillator-26m {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <26000000>;
clock-output-names = "clk26m";
};
- clk32k: oscillator@1 {
+ clk32k: oscillator-32k {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32768>;
@@ -117,7 +117,7 @@
compatible = "simple-bus";
ranges;
- gic: interrupt-controller@0c000000 {
+ gic: interrupt-controller@c000000 {
compatible = "arm,gic-v3";
#interrupt-cells = <4>;
interrupt-parent = <&gic>;
@@ -138,7 +138,7 @@
};
- sysirq: intpol-controller@0c53a650 {
+ sysirq: intpol-controller@c53a650 {
compatible = "mediatek,mt6779-sysirq",
"mediatek,mt6577-sysirq";
interrupt-controller;
@@ -160,7 +160,7 @@
};
pio: pinctrl@10005000 {
- compatible = "mediatek,mt6779-pinctrl", "syscon";
+ compatible = "mediatek,mt6779-pinctrl";
reg = <0 0x10005000 0 0x1000>,
<0 0x11c20000 0 0x1000>,
<0 0x11d10000 0 0x1000>,
diff --git a/arch/arm64/boot/dts/mediatek/mt6795-sony-xperia-m5.dts b/arch/arm64/boot/dts/mediatek/mt6795-sony-xperia-m5.dts
new file mode 100644
index 000000000000..d3415527d389
--- /dev/null
+++ b/arch/arm64/boot/dts/mediatek/mt6795-sony-xperia-m5.dts
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022, Collabora Ltd
+ * Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+ */
+
+/dts-v1/;
+#include "mt6795.dtsi"
+
+/ {
+ model = "Sony Xperia M5";
+ compatible = "sony,xperia-m5", "mediatek,mt6795";
+ chassis-type = "handset";
+
+ aliases {
+ mmc0 = &mmc0;
+ mmc1 = &mmc1;
+ serial0 = &uart0;
+ serial1 = &uart1;
+ };
+
+ memory@40000000 {
+ device_type = "memory";
+ reg = <0 0x40000000 0 0x1e800000>;
+ };
+
+ reserved_memory: reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ /* 128 KiB reserved for ARM Trusted Firmware (BL31) */
+ bl31_secmon_reserved: secmon@43000000 {
+ reg = <0 0x43000000 0 0x30000>;
+ no-map;
+ };
+
+ /* preloader and bootloader regions cannot be touched */
+ preloader-region@44800000 {
+ reg = <0 0x44800000 0 0x100000>;
+ no-map;
+ };
+
+ bootloader-region@46000000 {
+ reg = <0 0x46000000 0 0x400000>;
+ no-map;
+ };
+ };
+};
+
+&pio {
+ uart0_pins: uart0-pins {
+ pins-rx {
+ pinmux = <PINMUX_GPIO113__FUNC_URXD0>;
+ bias-pull-up;
+ input-enable;
+ };
+ pins-tx {
+ pinmux = <PINMUX_GPIO114__FUNC_UTXD0>;
+ output-high;
+ };
+ };
+
+ uart2_pins: uart2-pins {
+ pins-rx {
+ pinmux = <PINMUX_GPIO31__FUNC_URXD2>;
+ bias-pull-up;
+ input-enable;
+ };
+ pins-tx {
+ pinmux = <PINMUX_GPIO32__FUNC_UTXD2>;
+ };
+ };
+};
+
+&uart0 {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_pins>;
+};
+
+&uart2 {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2_pins>;
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt6795.dtsi b/arch/arm64/boot/dts/mediatek/mt6795.dtsi
index 46f0e54be766..bb575837e4ce 100644
--- a/arch/arm64/boot/dts/mediatek/mt6795.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt6795.dtsi
@@ -6,7 +6,9 @@
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/mediatek,mt6795-clk.h>
#include <dt-bindings/pinctrl/mt6795-pinfunc.h>
+#include <dt-bindings/reset/mediatek,mt6795-resets.h>
/ {
compatible = "mediatek,mt6795";
@@ -192,6 +194,26 @@
compatible = "simple-bus";
ranges;
+ topckgen: syscon@10000000 {
+ compatible = "mediatek,mt6795-topckgen", "syscon";
+ reg = <0 0x10000000 0 0x1000>;
+ #clock-cells = <1>;
+ };
+
+ infracfg: syscon@10001000 {
+ compatible = "mediatek,mt6795-infracfg", "syscon";
+ reg = <0 0x10001000 0 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ pericfg: syscon@10003000 {
+ compatible = "mediatek,mt6795-pericfg", "syscon";
+ reg = <0 0x10003000 0 0x1000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
pio: pinctrl@10005000 {
compatible = "mediatek,mt6795-pinctrl";
reg = <0 0x10005000 0 0x1000>, <0 0x1000b000 0 0x1000>;
@@ -292,7 +314,10 @@
"mediatek,mt6577-uart";
reg = <0 0x11002000 0 0x400>;
interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_LOW>;
- clocks = <&clk26m>;
+ clocks = <&pericfg CLK_PERI_UART0_SEL>, <&pericfg CLK_PERI_UART0>;
+ clock-names = "baud", "bus";
+ dmas = <&apdma 0>, <&apdma 1>;
+ dma-names = "tx", "rx";
status = "disabled";
};
@@ -301,16 +326,48 @@
"mediatek,mt6577-uart";
reg = <0 0x11003000 0 0x400>;
interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_LOW>;
- clocks = <&clk26m>;
+ clocks = <&pericfg CLK_PERI_UART1_SEL>, <&pericfg CLK_PERI_UART1>;
+ clock-names = "baud", "bus";
+ dmas = <&apdma 2>, <&apdma 3>;
+ dma-names = "tx", "rx";
status = "disabled";
};
+ apdma: dma-controller@11000380 {
+ compatible = "mediatek,mt6795-uart-dma",
+ "mediatek,mt6577-uart-dma";
+ reg = <0 0x11000380 0 0x60>,
+ <0 0x11000400 0 0x60>,
+ <0 0x11000480 0 0x60>,
+ <0 0x11000500 0 0x60>,
+ <0 0x11000580 0 0x60>,
+ <0 0x11000600 0 0x60>,
+ <0 0x11000680 0 0x60>,
+ <0 0x11000700 0 0x60>;
+ interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 104 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 105 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 106 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 107 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 108 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 109 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_SPI 110 IRQ_TYPE_LEVEL_LOW>;
+ dma-requests = <8>;
+ clocks = <&pericfg CLK_PERI_AP_DMA>;
+ clock-names = "apdma";
+ mediatek,dma-33bits;
+ #dma-cells = <1>;
+ };
+
uart2: serial@11004000 {
compatible = "mediatek,mt6795-uart",
"mediatek,mt6577-uart";
reg = <0 0x11004000 0 0x400>;
interrupts = <GIC_SPI 93 IRQ_TYPE_LEVEL_LOW>;
- clocks = <&clk26m>;
+ clocks = <&pericfg CLK_PERI_UART2_SEL>, <&pericfg CLK_PERI_UART2>;
+ clock-names = "baud", "bus";
+ dmas = <&apdma 4>, <&apdma 5>;
+ dma-names = "tx", "rx";
status = "disabled";
};
@@ -319,7 +376,51 @@
"mediatek,mt6577-uart";
reg = <0 0x11005000 0 0x400>;
interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_LOW>;
- clocks = <&clk26m>;
+ clocks = <&pericfg CLK_PERI_UART3_SEL>, <&pericfg CLK_PERI_UART3>;
+ clock-names = "baud", "bus";
+ dmas = <&apdma 6>, <&apdma 7>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ mmc0: mmc@11230000 {
+ compatible = "mediatek,mt6795-mmc";
+ reg = <0 0x11230000 0 0x1000>;
+ interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&pericfg CLK_PERI_MSDC30_0>,
+ <&topckgen CLK_TOP_MSDC50_0_H_SEL>,
+ <&topckgen CLK_TOP_MSDC50_0_SEL>;
+ clock-names = "source", "hclk", "source_cg";
+ status = "disabled";
+ };
+
+ mmc1: mmc@11240000 {
+ compatible = "mediatek,mt6795-mmc";
+ reg = <0 0x11240000 0 0x1000>;
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&pericfg CLK_PERI_MSDC30_1>,
+ <&topckgen CLK_TOP_AXI_SEL>;
+ clock-names = "source", "hclk";
+ status = "disabled";
+ };
+
+ mmc2: mmc@11250000 {
+ compatible = "mediatek,mt6795-mmc";
+ reg = <0 0x11250000 0 0x1000>;
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&pericfg CLK_PERI_MSDC30_2>,
+ <&topckgen CLK_TOP_AXI_SEL>;
+ clock-names = "source", "hclk";
+ status = "disabled";
+ };
+
+ mmc3: mmc@11260000 {
+ compatible = "mediatek,mt6795-mmc";
+ reg = <0 0x11260000 0 0x1000>;
+ interrupts = <GIC_SPI 82 IRQ_TYPE_LEVEL_LOW>;
+ clocks = <&pericfg CLK_PERI_MSDC30_3>,
+ <&topckgen CLK_TOP_AXI_SEL>;
+ clock-names = "source", "hclk";
status = "disabled";
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt6797.dtsi b/arch/arm64/boot/dts/mediatek/mt6797.dtsi
index 15616231022a..c3677d77e0a4 100644
--- a/arch/arm64/boot/dts/mediatek/mt6797.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt6797.dtsi
@@ -95,7 +95,7 @@
};
};
- clk26m: oscillator@0 {
+ clk26m: oscillator-26m {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <26000000>;
diff --git a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
index d3f9eab2b784..af3fe61e4093 100644
--- a/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
+++ b/arch/arm64/boot/dts/mediatek/mt7622-bananapi-bpi-r64.dts
@@ -235,7 +235,6 @@
bus-width = <4>;
max-frequency = <50000000>;
cap-sd-highspeed;
- r_smpl = <1>;
cd-gpios = <&pio 81 GPIO_ACTIVE_LOW>;
vmmc-supply = <&reg_3p3v>;
vqmmc-supply = <&reg_3p3v>;
diff --git a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
index 36722cabe626..b74e774c6eba 100644
--- a/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
+++ b/arch/arm64/boot/dts/mediatek/mt7622-rfb1.dts
@@ -208,7 +208,6 @@
bus-width = <4>;
max-frequency = <50000000>;
cap-sd-highspeed;
- r_smpl = <1>;
cd-gpios = <&pio 81 GPIO_ACTIVE_LOW>;
vmmc-supply = <&reg_3p3v>;
vqmmc-supply = <&reg_3p3v>;
diff --git a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts
index afe37b702eef..9b83925893b7 100644
--- a/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts
+++ b/arch/arm64/boot/dts/mediatek/mt7986a-rfb.dts
@@ -9,7 +9,7 @@
/ {
model = "MediaTek MT7986a RFB";
- compatible = "mediatek,mt7986a-rfb";
+ compatible = "mediatek,mt7986a-rfb", "mediatek,mt7986a";
aliases {
serial0 = &uart0;
@@ -25,6 +25,10 @@
};
};
+&crypto {
+ status = "okay";
+};
+
&eth {
status = "okay";
@@ -54,6 +58,88 @@
};
};
+&pio {
+ spi_flash_pins: spi-flash-pins {
+ mux {
+ function = "spi";
+ groups = "spi0", "spi0_wp_hold";
+ };
+ };
+
+ spic_pins: spic-pins {
+ mux {
+ function = "spi";
+ groups = "spi1_2";
+ };
+ };
+
+ uart1_pins: uart1-pins {
+ mux {
+ function = "uart";
+ groups = "uart1";
+ };
+ };
+
+ uart2_pins: uart2-pins {
+ mux {
+ function = "uart";
+ groups = "uart2";
+ };
+ };
+
+ wf_2g_5g_pins: wf-2g-5g-pins {
+ mux {
+ function = "wifi";
+ groups = "wf_2g", "wf_5g";
+ };
+ conf {
+ pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4",
+ "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6",
+ "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10",
+ "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1",
+ "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0",
+ "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8",
+ "WF1_TOP_CLK", "WF1_TOP_DATA";
+ drive-strength = <4>;
+ };
+ };
+
+ wf_dbdc_pins: wf-dbdc-pins {
+ mux {
+ function = "wifi";
+ groups = "wf_dbdc";
+ };
+ conf {
+ pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4",
+ "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6",
+ "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10",
+ "WF0_TOP_CLK", "WF0_TOP_DATA";
+ drive-strength = <4>;
+ };
+ };
+};
+
+&spi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi_flash_pins>;
+ cs-gpios = <0>, <0>;
+ status = "okay";
+ spi_nand: spi_nand@0 {
+ compatible = "spi-nand";
+ reg = <0>;
+ spi-max-frequency = <10000000>;
+ spi-tx-buswidth = <4>;
+ spi-rx-buswidth = <4>;
+ };
+};
+
+&spi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spic_pins>;
+ cs-gpios = <0>, <0>;
+ status = "okay";
+};
+
&switch {
ports {
#address-cells = <1>;
@@ -121,50 +207,3 @@
pinctrl-0 = <&wf_2g_5g_pins>;
pinctrl-1 = <&wf_dbdc_pins>;
};
-
-&pio {
- uart1_pins: uart1-pins {
- mux {
- function = "uart";
- groups = "uart1";
- };
- };
-
- uart2_pins: uart2-pins {
- mux {
- function = "uart";
- groups = "uart2";
- };
- };
-
- wf_2g_5g_pins: wf-2g-5g-pins {
- mux {
- function = "wifi";
- groups = "wf_2g", "wf_5g";
- };
- conf {
- pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4",
- "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6",
- "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10",
- "WF0_TOP_CLK", "WF0_TOP_DATA", "WF1_HB1",
- "WF1_HB2", "WF1_HB3", "WF1_HB4", "WF1_HB0",
- "WF1_HB5", "WF1_HB6", "WF1_HB7", "WF1_HB8",
- "WF1_TOP_CLK", "WF1_TOP_DATA";
- drive-strength = <4>;
- };
- };
-
- wf_dbdc_pins: wf-dbdc-pins {
- mux {
- function = "wifi";
- groups = "wf_dbdc";
- };
- conf {
- pins = "WF0_HB1", "WF0_HB2", "WF0_HB3", "WF0_HB4",
- "WF0_HB0", "WF0_HB0_B", "WF0_HB5", "WF0_HB6",
- "WF0_HB7", "WF0_HB8", "WF0_HB9", "WF0_HB10",
- "WF0_TOP_CLK", "WF0_TOP_DATA";
- drive-strength = <4>;
- };
- };
-};
diff --git a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
index 07dee1c0d281..0e9406fc63e2 100644
--- a/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7986a.dtsi
@@ -10,11 +10,12 @@
#include <dt-bindings/reset/mt7986-resets.h>
/ {
+ compatible = "mediatek,mt7986a";
interrupt-parent = <&gic>;
#address-cells = <2>;
#size-cells = <2>;
- clk40m: oscillator@0 {
+ clk40m: oscillator-40m {
compatible = "fixed-clock";
clock-frequency = <40000000>;
#clock-cells = <0>;
@@ -153,6 +154,12 @@
#clock-cells = <1>;
};
+ wed_pcie: wed-pcie@10003000 {
+ compatible = "mediatek,mt7986-wed-pcie",
+ "syscon";
+ reg = <0 0x10003000 0 0x10>;
+ };
+
topckgen: topckgen@1001b000 {
compatible = "mediatek,mt7986-topckgen", "syscon";
reg = <0 0x1001B000 0 0x1000>;
@@ -209,7 +216,7 @@
#clock-cells = <1>;
};
- trng: trng@1020f000 {
+ trng: rng@1020f000 {
compatible = "mediatek,mt7986-rng",
"mediatek,mt7623-rng";
reg = <0 0x1020f000 0 0x100>;
@@ -218,6 +225,21 @@
status = "disabled";
};
+ crypto: crypto@10320000 {
+ compatible = "inside-secure,safexcel-eip97";
+ reg = <0 0x10320000 0 0x40000>;
+ interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "ring0", "ring1", "ring2", "ring3";
+ clocks = <&infracfg CLK_INFRA_EIP97_CK>;
+ clock-names = "infra_eip97_ck";
+ assigned-clocks = <&topckgen CLK_TOP_EIP_B_SEL>;
+ assigned-clock-parents = <&apmixedsys CLK_APMIXED_NET2PLL>;
+ status = "disabled";
+ };
+
uart0: serial@11002000 {
compatible = "mediatek,mt7986-uart",
"mediatek,mt6577-uart";
@@ -259,6 +281,48 @@
status = "disabled";
};
+ i2c0: i2c@11008000 {
+ compatible = "mediatek,mt7986-i2c";
+ reg = <0 0x11008000 0 0x90>,
+ <0 0x10217080 0 0x80>;
+ interrupts = <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>;
+ clock-div = <5>;
+ clocks = <&infracfg CLK_INFRA_I2C0_CK>,
+ <&infracfg CLK_INFRA_AP_DMA_CK>;
+ clock-names = "main", "dma";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi0: spi@1100a000 {
+ compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0 0x1100a000 0 0x100>;
+ interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&topckgen CLK_TOP_MPLL_D2>,
+ <&topckgen CLK_TOP_SPI_SEL>,
+ <&infracfg CLK_INFRA_SPI0_CK>,
+ <&infracfg CLK_INFRA_SPI0_HCK_CK>;
+ clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk";
+ status = "disabled";
+ };
+
+ spi1: spi@1100b000 {
+ compatible = "mediatek,mt7986-spi-ipm", "mediatek,spi-ipm";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0 0x1100b000 0 0x100>;
+ interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&topckgen CLK_TOP_MPLL_D2>,
+ <&topckgen CLK_TOP_SPIM_MST_SEL>,
+ <&infracfg CLK_INFRA_SPI1_CK>,
+ <&infracfg CLK_INFRA_SPI1_HCK_CK>;
+ clock-names = "parent-clk", "sel-clk", "spi-clk", "hclk";
+ status = "disabled";
+ };
+
ethsys: syscon@15000000 {
#address-cells = <1>;
#size-cells = <1>;
@@ -269,12 +333,6 @@
#reset-cells = <1>;
};
- wed_pcie: wed-pcie@10003000 {
- compatible = "mediatek,mt7986-wed-pcie",
- "syscon";
- reg = <0 0x10003000 0 0x10>;
- };
-
wed0: wed@15010000 {
compatible = "mediatek,mt7986-wed",
"syscon";
diff --git a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts
index 3443013b5971..243760cd3011 100644
--- a/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts
+++ b/arch/arm64/boot/dts/mediatek/mt7986b-rfb.dts
@@ -9,7 +9,7 @@
/ {
model = "MediaTek MT7986b RFB";
- compatible = "mediatek,mt7986b-rfb";
+ compatible = "mediatek,mt7986b-rfb", "mediatek,mt7986b";
aliases {
serial0 = &uart0;
@@ -25,7 +25,7 @@
};
};
-&uart0 {
+&crypto {
status = "okay";
};
@@ -99,14 +99,21 @@
};
};
-&wifi {
- status = "okay";
- pinctrl-names = "default", "dbdc";
- pinctrl-0 = <&wf_2g_5g_pins>;
- pinctrl-1 = <&wf_dbdc_pins>;
-};
-
&pio {
+ spi_flash_pins: spi-flash-pins {
+ mux {
+ function = "spi";
+ groups = "spi0", "spi0_wp_hold";
+ };
+ };
+
+ spic_pins: spic-pins {
+ mux {
+ function = "spi";
+ groups = "spi1_2";
+ };
+ };
+
wf_2g_5g_pins: wf-2g-5g-pins {
mux {
function = "wifi";
@@ -138,3 +145,35 @@
};
};
};
+
+&spi0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi_flash_pins>;
+ cs-gpios = <0>, <0>;
+ status = "okay";
+ spi_nand: spi_nand@0 {
+ compatible = "spi-nand";
+ reg = <0>;
+ spi-max-frequency = <10000000>;
+ spi-tx-buswidth = <4>;
+ spi-rx-buswidth = <4>;
+ };
+};
+
+&spi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spic_pins>;
+ cs-gpios = <0>, <0>;
+ status = "okay";
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&wifi {
+ status = "okay";
+ pinctrl-names = "default", "dbdc";
+ pinctrl-0 = <&wf_2g_5g_pins>;
+ pinctrl-1 = <&wf_dbdc_pins>;
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
index 23923b9f8944..db5189664c29 100644
--- a/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt7986b.dtsi
@@ -5,6 +5,9 @@
*/
#include "mt7986a.dtsi"
+/ {
+ compatible = "mediatek,mt7986b";
+};
&pio {
compatible = "mediatek,mt7986b-pinctrl";
diff --git a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
index b4b86bb1f1a7..7fc4c592a908 100644
--- a/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8183-kukui.dtsi
@@ -221,11 +221,6 @@
};
};
-&afe {
- i2s3-share = "I2S2";
- i2s0-share = "I2S5";
-};
-
&auxadc {
status = "okay";
};
@@ -378,7 +373,6 @@
mmc-pwrseq = <&wifi_pwrseq>;
bus-width = <4>;
max-frequency = <200000000>;
- drv-type = <2>;
cap-sd-highspeed;
sd-uhs-sdr50;
sd-uhs-sdr104;
diff --git a/arch/arm64/boot/dts/mediatek/mt8186.dtsi b/arch/arm64/boot/dts/mediatek/mt8186.dtsi
index 64693c17af9e..c326aeb33a10 100644
--- a/arch/arm64/boot/dts/mediatek/mt8186.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8186.dtsi
@@ -198,16 +198,19 @@
l2_0: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
next-level-cache = <&l3_0>;
};
l2_1: l2-cache1 {
compatible = "cache";
+ cache-level = <2>;
next-level-cache = <&l3_0>;
};
l3_0: l3-cache {
compatible = "cache";
+ cache-level = <3>;
};
};
diff --git a/arch/arm64/boot/dts/mediatek/mt8192.dtsi b/arch/arm64/boot/dts/mediatek/mt8192.dtsi
index 6b20376191a7..424fc89cc6f7 100644
--- a/arch/arm64/boot/dts/mediatek/mt8192.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8192.dtsi
@@ -169,16 +169,19 @@
l2_0: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
next-level-cache = <&l3_0>;
};
l2_1: l2-cache1 {
compatible = "cache";
+ cache-level = <2>;
next-level-cache = <&l3_0>;
};
l3_0: l3-cache {
compatible = "cache";
+ cache-level = <3>;
};
idle-states {
diff --git a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
index 9b62e161db26..560103e29017 100644
--- a/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8195-cherry.dtsi
@@ -120,6 +120,78 @@
};
};
+&dp_intf0 {
+ status = "okay";
+
+ port {
+ dp_intf0_out: endpoint {
+ remote-endpoint = <&edp_in>;
+ };
+ };
+};
+
+&dp_intf1 {
+ status = "okay";
+
+ port {
+ dp_intf1_out: endpoint {
+ remote-endpoint = <&dptx_in>;
+ };
+ };
+};
+
+&edp_tx {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&edptx_pins_default>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ edp_in: endpoint {
+ remote-endpoint = <&dp_intf0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ edp_out: endpoint {
+ data-lanes = <0 1 2 3>;
+ };
+ };
+ };
+};
+
+&dp_tx {
+ status = "okay";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&dptx_pin>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dptx_in: endpoint {
+ remote-endpoint = <&dp_intf1_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dptx_out: endpoint {
+ data-lanes = <0 1 2 3>;
+ };
+ };
+ };
+};
+
&i2c0 {
status = "okay";
@@ -479,6 +551,20 @@
};
};
+ edptx_pins_default: edptx-default-pins {
+ pins-cmd-dat {
+ pinmux = <PINMUX_GPIO7__FUNC_EDP_TX_HPD>;
+ bias-pull-up;
+ };
+ };
+
+ dptx_pin: dptx-default-pins {
+ pins-cmd-dat {
+ pinmux = <PINMUX_GPIO18__FUNC_DP_TX_HPD>;
+ bias-pull-up;
+ };
+ };
+
i2c0_pins: i2c0-default-pins {
pins-bus {
pinmux = <PINMUX_GPIO8__FUNC_SDA0>,
diff --git a/arch/arm64/boot/dts/mediatek/mt8195.dtsi b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
index 905d1a90b406..5d31536f4c48 100644
--- a/arch/arm64/boot/dts/mediatek/mt8195.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8195.dtsi
@@ -13,6 +13,7 @@
#include <dt-bindings/phy/phy.h>
#include <dt-bindings/pinctrl/mt8195-pinfunc.h>
#include <dt-bindings/power/mt8195-power.h>
+#include <dt-bindings/reset/mt8195-resets.h>
/ {
compatible = "mediatek,mt8195";
@@ -36,7 +37,7 @@
enable-method = "psci";
performance-domains = <&performance 0>;
clock-frequency = <1701000000>;
- capacity-dmips-mhz = <578>;
+ capacity-dmips-mhz = <308>;
cpu-idle-states = <&cpu_off_l &cluster_off_l>;
next-level-cache = <&l2_0>;
#cooling-cells = <2>;
@@ -49,7 +50,7 @@
enable-method = "psci";
performance-domains = <&performance 0>;
clock-frequency = <1701000000>;
- capacity-dmips-mhz = <578>;
+ capacity-dmips-mhz = <308>;
cpu-idle-states = <&cpu_off_l &cluster_off_l>;
next-level-cache = <&l2_0>;
#cooling-cells = <2>;
@@ -62,7 +63,7 @@
enable-method = "psci";
performance-domains = <&performance 0>;
clock-frequency = <1701000000>;
- capacity-dmips-mhz = <578>;
+ capacity-dmips-mhz = <308>;
cpu-idle-states = <&cpu_off_l &cluster_off_l>;
next-level-cache = <&l2_0>;
#cooling-cells = <2>;
@@ -75,7 +76,7 @@
enable-method = "psci";
performance-domains = <&performance 0>;
clock-frequency = <1701000000>;
- capacity-dmips-mhz = <578>;
+ capacity-dmips-mhz = <308>;
cpu-idle-states = <&cpu_off_l &cluster_off_l>;
next-level-cache = <&l2_0>;
#cooling-cells = <2>;
@@ -213,16 +214,19 @@
l2_0: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
next-level-cache = <&l3_0>;
};
l2_1: l2-cache1 {
compatible = "cache";
+ cache-level = <2>;
next-level-cache = <&l3_0>;
};
l3_0: l3-cache {
compatible = "cache";
+ cache-level = <3>;
};
};
@@ -1182,6 +1186,110 @@
status = "disabled";
};
+ pcie0: pcie@112f0000 {
+ compatible = "mediatek,mt8195-pcie",
+ "mediatek,mt8192-pcie";
+ device_type = "pci";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ reg = <0 0x112f0000 0 0x4000>;
+ reg-names = "pcie-mac";
+ interrupts = <GIC_SPI 791 IRQ_TYPE_LEVEL_HIGH 0>;
+ bus-range = <0x00 0xff>;
+ ranges = <0x81000000 0 0x20000000
+ 0x0 0x20000000 0 0x200000>,
+ <0x82000000 0 0x20200000
+ 0x0 0x20200000 0 0x3e00000>;
+
+ iommu-map = <0 &iommu_infra IOMMU_PORT_INFRA_PCIE0 0x2>;
+ iommu-map-mask = <0x0>;
+
+ clocks = <&infracfg_ao CLK_INFRA_AO_PCIE_PL_P_250M_P0>,
+ <&infracfg_ao CLK_INFRA_AO_PCIE_TL_26M>,
+ <&infracfg_ao CLK_INFRA_AO_PCIE_TL_96M>,
+ <&infracfg_ao CLK_INFRA_AO_PCIE_TL_32K>,
+ <&infracfg_ao CLK_INFRA_AO_PCIE_PERI_26M>,
+ <&pericfg_ao CLK_PERI_AO_PCIE_P0_MEM>;
+ clock-names = "pl_250m", "tl_26m", "tl_96m",
+ "tl_32k", "peri_26m", "peri_mem";
+ assigned-clocks = <&topckgen CLK_TOP_TL>;
+ assigned-clock-parents = <&topckgen CLK_TOP_MAINPLL_D4_D4>;
+
+ phys = <&pciephy>;
+ phy-names = "pcie-phy";
+
+ power-domains = <&spm MT8195_POWER_DOMAIN_PCIE_MAC_P0>;
+
+ resets = <&infracfg_ao MT8195_INFRA_RST2_PCIE_P0_SWRST>;
+ reset-names = "mac";
+
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie_intc0 0>,
+ <0 0 0 2 &pcie_intc0 1>,
+ <0 0 0 3 &pcie_intc0 2>,
+ <0 0 0 4 &pcie_intc0 3>;
+ status = "disabled";
+
+ pcie_intc0: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+ };
+
+ pcie1: pcie@112f8000 {
+ compatible = "mediatek,mt8195-pcie",
+ "mediatek,mt8192-pcie";
+ device_type = "pci";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ reg = <0 0x112f8000 0 0x4000>;
+ reg-names = "pcie-mac";
+ interrupts = <GIC_SPI 792 IRQ_TYPE_LEVEL_HIGH 0>;
+ bus-range = <0x00 0xff>;
+ ranges = <0x81000000 0 0x24000000
+ 0x0 0x24000000 0 0x200000>,
+ <0x82000000 0 0x24200000
+ 0x0 0x24200000 0 0x3e00000>;
+
+ iommu-map = <0 &iommu_infra IOMMU_PORT_INFRA_PCIE1 0x2>;
+ iommu-map-mask = <0x0>;
+
+ clocks = <&infracfg_ao CLK_INFRA_AO_PCIE_PL_P_250M_P1>,
+ <&clk26m>,
+ <&infracfg_ao CLK_INFRA_AO_PCIE_TL_96M>,
+ <&clk26m>,
+ <&infracfg_ao CLK_INFRA_AO_PCIE_PERI_26M>,
+ /* Designer has connect pcie1 with peri_mem_p0 clock */
+ <&pericfg_ao CLK_PERI_AO_PCIE_P0_MEM>;
+ clock-names = "pl_250m", "tl_26m", "tl_96m",
+ "tl_32k", "peri_26m", "peri_mem";
+ assigned-clocks = <&topckgen CLK_TOP_TL_P1>;
+ assigned-clock-parents = <&topckgen CLK_TOP_MAINPLL_D4_D4>;
+
+ phys = <&u3port1 PHY_TYPE_PCIE>;
+ phy-names = "pcie-phy";
+ power-domains = <&spm MT8195_POWER_DOMAIN_PCIE_MAC_P1>;
+
+ resets = <&infracfg_ao MT8195_INFRA_RST2_PCIE_P1_SWRST>;
+ reset-names = "mac";
+
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 7>;
+ interrupt-map = <0 0 0 1 &pcie_intc1 0>,
+ <0 0 0 2 &pcie_intc1 1>,
+ <0 0 0 3 &pcie_intc1 2>,
+ <0 0 0 4 &pcie_intc1 3>;
+ status = "disabled";
+
+ pcie_intc1: interrupt-controller {
+ interrupt-controller;
+ #address-cells = <0>;
+ #interrupt-cells = <1>;
+ };
+ };
+
nor_flash: spi@1132c000 {
compatible = "mediatek,mt8195-nor",
"mediatek,mt8173-nor";
@@ -1241,6 +1349,37 @@
reg = <0x189 0x2>;
bits = <7 5>;
};
+ pciephy_rx_ln1: pciephy-rx-ln1@190,1 {
+ reg = <0x190 0x1>;
+ bits = <0 4>;
+ };
+ pciephy_tx_ln1_nmos: pciephy-tx-ln1-nmos@190,2 {
+ reg = <0x190 0x1>;
+ bits = <4 4>;
+ };
+ pciephy_tx_ln1_pmos: pciephy-tx-ln1-pmos@191,1 {
+ reg = <0x191 0x1>;
+ bits = <0 4>;
+ };
+ pciephy_rx_ln0: pciephy-rx-ln0@191,2 {
+ reg = <0x191 0x1>;
+ bits = <4 4>;
+ };
+ pciephy_tx_ln0_nmos: pciephy-tx-ln0-nmos@192,1 {
+ reg = <0x192 0x1>;
+ bits = <0 4>;
+ };
+ pciephy_tx_ln0_pmos: pciephy-tx-ln0-pmos@192,2 {
+ reg = <0x192 0x1>;
+ bits = <4 4>;
+ };
+ pciephy_glb_intr: pciephy-glb-intr@193 {
+ reg = <0x193 0x1>;
+ bits = <0 4>;
+ };
+ dp_calibration: dp-data@1ac {
+ reg = <0x1ac 0x10>;
+ };
};
u3phy2: t-phy@11c40000 {
@@ -1461,6 +1600,23 @@
};
};
+ pciephy: phy@11e80000 {
+ compatible = "mediatek,mt8195-pcie-phy";
+ reg = <0 0x11e80000 0 0x10000>;
+ reg-names = "sif";
+ nvmem-cells = <&pciephy_glb_intr>, <&pciephy_tx_ln0_pmos>,
+ <&pciephy_tx_ln0_nmos>, <&pciephy_rx_ln0>,
+ <&pciephy_tx_ln1_pmos>, <&pciephy_tx_ln1_nmos>,
+ <&pciephy_rx_ln1>;
+ nvmem-cell-names = "glb_intr", "tx_ln0_pmos",
+ "tx_ln0_nmos", "rx_ln0",
+ "tx_ln1_pmos", "tx_ln1_nmos",
+ "rx_ln1";
+ power-domains = <&spm MT8195_POWER_DOMAIN_PCIE_PHY>;
+ #phy-cells = <0>;
+ status = "disabled";
+ };
+
ufsphy: ufs-phy@11fa0000 {
compatible = "mediatek,mt8195-ufsphy", "mediatek,mt8183-ufsphy";
reg = <0 0x11fa0000 0 0xc000>;
@@ -1959,6 +2115,30 @@
power-domains = <&spm MT8195_POWER_DOMAIN_VENC>;
};
+ venc: video-codec@1a020000 {
+ compatible = "mediatek,mt8195-vcodec-enc";
+ reg = <0 0x1a020000 0 0x10000>;
+ iommus = <&iommu_vdo M4U_PORT_L19_VENC_RCPU>,
+ <&iommu_vdo M4U_PORT_L19_VENC_REC>,
+ <&iommu_vdo M4U_PORT_L19_VENC_BSDMA>,
+ <&iommu_vdo M4U_PORT_L19_VENC_SV_COMV>,
+ <&iommu_vdo M4U_PORT_L19_VENC_RD_COMV>,
+ <&iommu_vdo M4U_PORT_L19_VENC_CUR_LUMA>,
+ <&iommu_vdo M4U_PORT_L19_VENC_CUR_CHROMA>,
+ <&iommu_vdo M4U_PORT_L19_VENC_REF_LUMA>,
+ <&iommu_vdo M4U_PORT_L19_VENC_REF_CHROMA>;
+ interrupts = <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH 0>;
+ mediatek,scp = <&scp>;
+ clocks = <&vencsys CLK_VENC_VENC>;
+ clock-names = "venc_sel";
+ assigned-clocks = <&topckgen CLK_TOP_VENC>;
+ assigned-clock-parents = <&topckgen CLK_TOP_UNIVPLL_D4>;
+ power-domains = <&spm MT8195_POWER_DOMAIN_VENC>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ dma-ranges = <0x1 0x0 0x0 0x40000000 0x0 0xfff00000>;
+ };
+
vencsys_core1: clock-controller@1b000000 {
compatible = "mediatek,mt8195-vencsys_core1";
reg = <0 0x1b000000 0 0x1000>;
@@ -2067,6 +2247,17 @@
mediatek,gce-client-reg = <&gce0 SUBSYS_1c01XXXX 0x4000 0x1000>;
};
+ dp_intf0: dp-intf@1c015000 {
+ compatible = "mediatek,mt8195-dp-intf";
+ reg = <0 0x1c015000 0 0x1000>;
+ interrupts = <GIC_SPI 657 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&vdosys0 CLK_VDO0_DP_INTF0>,
+ <&vdosys0 CLK_VDO0_DP_INTF0_DP_INTF>,
+ <&apmixedsys CLK_APMIXED_TVDPLL1>;
+ clock-names = "engine", "pixel", "pll";
+ status = "disabled";
+ };
+
mutex: mutex@1c016000 {
compatible = "mediatek,mt8195-disp-mutex";
reg = <0 0x1c016000 0 0x1000>;
@@ -2155,5 +2346,39 @@
clock-names = "apb", "smi", "gals";
power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>;
};
+
+ dp_intf1: dp-intf@1c113000 {
+ compatible = "mediatek,mt8195-dp-intf";
+ reg = <0 0x1c113000 0 0x1000>;
+ interrupts = <GIC_SPI 513 IRQ_TYPE_LEVEL_HIGH 0>;
+ power-domains = <&spm MT8195_POWER_DOMAIN_VDOSYS1>;
+ clocks = <&vdosys1 CLK_VDO1_DP_INTF0_MM>,
+ <&vdosys1 CLK_VDO1_DPINTF>,
+ <&apmixedsys CLK_APMIXED_TVDPLL2>;
+ clock-names = "engine", "pixel", "pll";
+ status = "disabled";
+ };
+
+ edp_tx: edp-tx@1c500000 {
+ compatible = "mediatek,mt8195-edp-tx";
+ reg = <0 0x1c500000 0 0x8000>;
+ nvmem-cells = <&dp_calibration>;
+ nvmem-cell-names = "dp_calibration_data";
+ power-domains = <&spm MT8195_POWER_DOMAIN_EPD_TX>;
+ interrupts = <GIC_SPI 676 IRQ_TYPE_LEVEL_HIGH 0>;
+ max-linkrate-mhz = <8100>;
+ status = "disabled";
+ };
+
+ dp_tx: dp-tx@1c600000 {
+ compatible = "mediatek,mt8195-dp-tx";
+ reg = <0 0x1c600000 0 0x8000>;
+ nvmem-cells = <&dp_calibration>;
+ nvmem-cell-names = "dp_calibration_data";
+ power-domains = <&spm MT8195_POWER_DOMAIN_DP_TX>;
+ interrupts = <GIC_SPI 458 IRQ_TYPE_LEVEL_HIGH 0>;
+ max-linkrate-mhz = <8100>;
+ status = "disabled";
+ };
};
};
diff --git a/arch/arm64/boot/dts/mediatek/pumpkin-common.dtsi b/arch/arm64/boot/dts/mediatek/pumpkin-common.dtsi
index 8ee1529683a3..ec8dfb3d1c6d 100644
--- a/arch/arm64/boot/dts/mediatek/pumpkin-common.dtsi
+++ b/arch/arm64/boot/dts/mediatek/pumpkin-common.dtsi
@@ -17,7 +17,7 @@
};
firmware {
- optee: optee@4fd00000 {
+ optee: optee {
compatible = "linaro,optee-tz";
method = "smc";
};
@@ -209,7 +209,7 @@
};
};
- i2c0_pins_a: i2c0@0 {
+ i2c0_pins_a: i2c0 {
pins1 {
pinmux = <MT8516_PIN_58_SDA0__FUNC_SDA0_0>,
<MT8516_PIN_59_SCL0__FUNC_SCL0_0>;
@@ -217,7 +217,7 @@
};
};
- i2c2_pins_a: i2c2@0 {
+ i2c2_pins_a: i2c2 {
pins1 {
pinmux = <MT8516_PIN_60_SDA2__FUNC_SDA2_0>,
<MT8516_PIN_61_SCL2__FUNC_SCL2_0>;
diff --git a/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts b/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts
index d461da0b8049..3e8dee85d55f 100644
--- a/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts
+++ b/arch/arm64/boot/dts/nvidia/tegra132-norrin.dts
@@ -62,7 +62,7 @@
pinctrl-names = "default";
pinctrl-0 = <&pinmux_default>;
- pinmux_default: pinmux@0 {
+ pinmux_default: pinmux {
dap_mclk1_pw4 {
nvidia,pins = "dap_mclk1_pw4";
nvidia,function = "extperiph1";
diff --git a/arch/arm64/boot/dts/nvidia/tegra132.dtsi b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
index 3673f79adf1a..858fc01cecb6 100644
--- a/arch/arm64/boot/dts/nvidia/tegra132.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra132.dtsi
@@ -393,7 +393,6 @@
reg = <0x0 0x7000a000 0x0 0x100>;
#pwm-cells = <2>;
clocks = <&tegra_car TEGRA124_CLK_PWM>;
- clock-names = "pwm";
resets = <&tegra_car 17>;
reset-names = "pwm";
status = "disabled";
diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index 6602fe421ee8..b3f1494c02c1 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -78,7 +78,8 @@
reg = <0x0 0x2600000 0x0 0x210000>;
resets = <&bpmp TEGRA186_RESET_GPCDMA>;
reset-names = "gpcdma";
- interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
+ interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>,
@@ -112,6 +113,7 @@
#dma-cells = <1>;
iommus = <&smmu TEGRA186_SID_GPCDMA_0>;
dma-coherent;
+ dma-channel-mask = <0xfffffffe>;
status = "okay";
};
@@ -790,7 +792,6 @@
compatible = "nvidia,tegra186-pwm";
reg = <0x0 0x3280000 0x0 0x10000>;
clocks = <&bpmp TEGRA186_CLK_PWM1>;
- clock-names = "pwm";
resets = <&bpmp TEGRA186_RESET_PWM1>;
reset-names = "pwm";
status = "disabled";
@@ -801,7 +802,6 @@
compatible = "nvidia,tegra186-pwm";
reg = <0x0 0x3290000 0x0 0x10000>;
clocks = <&bpmp TEGRA186_CLK_PWM2>;
- clock-names = "pwm";
resets = <&bpmp TEGRA186_RESET_PWM2>;
reset-names = "pwm";
status = "disabled";
@@ -812,7 +812,6 @@
compatible = "nvidia,tegra186-pwm";
reg = <0x0 0x32a0000 0x0 0x10000>;
clocks = <&bpmp TEGRA186_CLK_PWM3>;
- clock-names = "pwm";
resets = <&bpmp TEGRA186_RESET_PWM3>;
reset-names = "pwm";
status = "disabled";
@@ -823,7 +822,6 @@
compatible = "nvidia,tegra186-pwm";
reg = <0x0 0x32c0000 0x0 0x10000>;
clocks = <&bpmp TEGRA186_CLK_PWM5>;
- clock-names = "pwm";
resets = <&bpmp TEGRA186_RESET_PWM5>;
reset-names = "pwm";
status = "disabled";
@@ -834,7 +832,6 @@
compatible = "nvidia,tegra186-pwm";
reg = <0x0 0x32d0000 0x0 0x10000>;
clocks = <&bpmp TEGRA186_CLK_PWM6>;
- clock-names = "pwm";
resets = <&bpmp TEGRA186_RESET_PWM6>;
reset-names = "pwm";
status = "disabled";
@@ -845,7 +842,6 @@
compatible = "nvidia,tegra186-pwm";
reg = <0x0 0x32e0000 0x0 0x10000>;
clocks = <&bpmp TEGRA186_CLK_PWM7>;
- clock-names = "pwm";
resets = <&bpmp TEGRA186_RESET_PWM7>;
reset-names = "pwm";
status = "disabled";
@@ -856,7 +852,6 @@
compatible = "nvidia,tegra186-pwm";
reg = <0x0 0x32f0000 0x0 0x10000>;
clocks = <&bpmp TEGRA186_CLK_PWM8>;
- clock-names = "pwm";
resets = <&bpmp TEGRA186_RESET_PWM8>;
reset-names = "pwm";
status = "disabled";
@@ -1274,7 +1269,6 @@
compatible = "nvidia,tegra186-pwm";
reg = <0x0 0xc340000 0x0 0x10000>;
clocks = <&bpmp TEGRA186_CLK_PWM4>;
- clock-names = "pwm";
resets = <&bpmp TEGRA186_RESET_PWM4>;
reset-names = "pwm";
status = "disabled";
diff --git a/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi b/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi
index b0f9393dd39c..cd272d407e01 100644
--- a/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra194-p2888.dtsi
@@ -23,7 +23,7 @@
};
chosen {
- bootargs = "console=ttyS0,115200n8";
+ bootargs = "console=ttyTCU0,115200n8";
stdout-path = "serial0:115200n8";
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra194-p3509-0000.dtsi b/arch/arm64/boot/dts/nvidia/tegra194-p3509-0000.dtsi
index 273a1ef716b6..f212f6aced04 100644
--- a/arch/arm64/boot/dts/nvidia/tegra194-p3509-0000.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra194-p3509-0000.dtsi
@@ -2117,8 +2117,8 @@
"usb-b-connector";
label = "micro-USB";
type = "micro";
- vbus-gpio = <&gpio TEGRA194_MAIN_GPIO(Z, 1)
- GPIO_ACTIVE_LOW>;
+ vbus-gpios = <&gpio TEGRA194_MAIN_GPIO(Z, 1)
+ GPIO_ACTIVE_LOW>;
};
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra194-p3668.dtsi b/arch/arm64/boot/dts/nvidia/tegra194-p3668.dtsi
index 0bd66f9c620b..0751edddf7d5 100644
--- a/arch/arm64/boot/dts/nvidia/tegra194-p3668.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra194-p3668.dtsi
@@ -20,7 +20,7 @@
};
chosen {
- bootargs = "console=ttyS0,115200n8";
+ bootargs = "console=ttyTCU0,115200n8";
stdout-path = "serial0:115200n8";
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra194.dtsi b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
index 41f3a7e188d0..4afcbd60e144 100644
--- a/arch/arm64/boot/dts/nvidia/tegra194.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra194.dtsi
@@ -86,6 +86,7 @@
interrupt-controller;
#gpio-cells = <2>;
gpio-controller;
+ gpio-ranges = <&pinmux 0 0 169>;
};
cbb-noc@2300000 {
@@ -142,7 +143,8 @@
reg = <0x2600000 0x210000>;
resets = <&bpmp TEGRA194_RESET_GPCDMA>;
reset-names = "gpcdma";
- interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
+ interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>,
@@ -176,6 +178,7 @@
#dma-cells = <1>;
iommus = <&smmu TEGRA194_SID_GPCDMA_0>;
dma-coherent;
+ dma-channel-mask = <0xfffffffe>;
status = "okay";
};
@@ -626,12 +629,10 @@
pinmux: pinmux@2430000 {
compatible = "nvidia,tegra194-pinmux";
- reg = <0x2430000 0x17000>,
- <0xc300000 0x4000>;
-
+ reg = <0x2430000 0x17000>;
status = "okay";
- pex_rst_c5_out_state: pex_rst_c5_out {
+ pex_rst_c5_out_state: pinmux-pex-rst-c5-out {
pex_rst {
nvidia,pins = "pex_l5_rst_n_pgg1";
nvidia,schmitt = <TEGRA_PIN_DISABLE>;
@@ -642,7 +643,7 @@
};
};
- clkreq_c5_bi_dir_state: clkreq_c5_bi_dir {
+ clkreq_c5_bi_dir_state: pinmux-clkreq-c5-bi-dir {
clkreq {
nvidia,pins = "pex_l5_clkreq_n_pgg0";
nvidia,schmitt = <TEGRA_PIN_DISABLE>;
@@ -935,7 +936,6 @@
<&bpmp TEGRA194_CLK_QSPI0_PM>;
clock-names = "qspi", "qspi_out";
resets = <&bpmp TEGRA194_RESET_QSPI0>;
- reset-names = "qspi";
status = "disabled";
};
@@ -949,7 +949,6 @@
<&bpmp TEGRA194_CLK_QSPI1_PM>;
clock-names = "qspi", "qspi_out";
resets = <&bpmp TEGRA194_RESET_QSPI1>;
- reset-names = "qspi";
status = "disabled";
};
@@ -958,7 +957,6 @@
"nvidia,tegra186-pwm";
reg = <0x3280000 0x10000>;
clocks = <&bpmp TEGRA194_CLK_PWM1>;
- clock-names = "pwm";
resets = <&bpmp TEGRA194_RESET_PWM1>;
reset-names = "pwm";
status = "disabled";
@@ -970,7 +968,6 @@
"nvidia,tegra186-pwm";
reg = <0x3290000 0x10000>;
clocks = <&bpmp TEGRA194_CLK_PWM2>;
- clock-names = "pwm";
resets = <&bpmp TEGRA194_RESET_PWM2>;
reset-names = "pwm";
status = "disabled";
@@ -982,7 +979,6 @@
"nvidia,tegra186-pwm";
reg = <0x32a0000 0x10000>;
clocks = <&bpmp TEGRA194_CLK_PWM3>;
- clock-names = "pwm";
resets = <&bpmp TEGRA194_RESET_PWM3>;
reset-names = "pwm";
status = "disabled";
@@ -994,7 +990,6 @@
"nvidia,tegra186-pwm";
reg = <0x32c0000 0x10000>;
clocks = <&bpmp TEGRA194_CLK_PWM5>;
- clock-names = "pwm";
resets = <&bpmp TEGRA194_RESET_PWM5>;
reset-names = "pwm";
status = "disabled";
@@ -1006,7 +1001,6 @@
"nvidia,tegra186-pwm";
reg = <0x32d0000 0x10000>;
clocks = <&bpmp TEGRA194_CLK_PWM6>;
- clock-names = "pwm";
resets = <&bpmp TEGRA194_RESET_PWM6>;
reset-names = "pwm";
status = "disabled";
@@ -1018,7 +1012,6 @@
"nvidia,tegra186-pwm";
reg = <0x32e0000 0x10000>;
clocks = <&bpmp TEGRA194_CLK_PWM7>;
- clock-names = "pwm";
resets = <&bpmp TEGRA194_RESET_PWM7>;
reset-names = "pwm";
status = "disabled";
@@ -1030,7 +1023,6 @@
"nvidia,tegra186-pwm";
reg = <0x32f0000 0x10000>;
clocks = <&bpmp TEGRA194_CLK_PWM8>;
- clock-names = "pwm";
resets = <&bpmp TEGRA194_RESET_PWM8>;
reset-names = "pwm";
status = "disabled";
@@ -1154,7 +1146,7 @@
};
hda@3510000 {
- compatible = "nvidia,tegra194-hda", "nvidia,tegra30-hda";
+ compatible = "nvidia,tegra194-hda";
reg = <0x3510000 0x10000>;
interrupts = <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&bpmp TEGRA194_CLK_HDA>,
@@ -1366,6 +1358,16 @@
status = "disabled";
};
+ hte_lic: hardware-timestamp@3aa0000 {
+ compatible = "nvidia,tegra194-gte-lic";
+ reg = <0x3aa0000 0x10000>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ nvidia,int-threshold = <1>;
+ nvidia,slices = <11>;
+ #timestamp-cells = <1>;
+ status = "okay";
+ };
+
hsp_top0: hsp@3c00000 {
compatible = "nvidia,tegra194-hsp";
reg = <0x03c00000 0xa0000>;
@@ -1579,6 +1581,16 @@
#mbox-cells = <2>;
};
+ hte_aon: hardware-timestamp@c1e0000 {
+ compatible = "nvidia,tegra194-gte-aon";
+ reg = <0xc1e0000 0x10000>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ nvidia,int-threshold = <1>;
+ nvidia,slices = <3>;
+ #timestamp-cells = <1>;
+ status = "okay";
+ };
+
gen2_i2c: i2c@c240000 {
compatible = "nvidia,tegra194-i2c";
reg = <0x0c240000 0x10000>;
@@ -1660,6 +1672,14 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ gpio-range = <&pinmux_aon 0 0 30>;
+ };
+
+ pinmux_aon: pinmux@c300000 {
+ compatible = "nvidia,tegra194-pinmux-aon";
+ reg = <0xc300000 0x4000>;
+
+ status = "okay";
};
pwm4: pwm@c340000 {
@@ -1667,7 +1687,6 @@
"nvidia,tegra186-pwm";
reg = <0xc340000 0x10000>;
clocks = <&bpmp TEGRA194_CLK_PWM4>;
- clock-names = "pwm";
resets = <&bpmp TEGRA194_RESET_PWM4>;
reset-names = "pwm";
status = "disabled";
@@ -1895,7 +1914,7 @@
#address-cells = <1>;
#size-cells = <1>;
- ranges = <0x15000000 0x15000000 0x01000000>;
+ ranges = <0x14800000 0x14800000 0x02800000>;
interconnects = <&mc TEGRA194_MEMORY_CLIENT_HOST1XDMAR &emc>;
interconnect-names = "dma-mem";
iommus = <&smmu TEGRA194_SID_HOST1X>;
@@ -3029,36 +3048,51 @@
};
l2c_0: l2-cache0 {
+ compatible = "cache";
+ cache-unified;
cache-size = <2097152>;
cache-line-size = <64>;
cache-sets = <2048>;
+ cache-level = <2>;
next-level-cache = <&l3c>;
};
l2c_1: l2-cache1 {
+ compatible = "cache";
+ cache-unified;
cache-size = <2097152>;
cache-line-size = <64>;
cache-sets = <2048>;
+ cache-level = <2>;
next-level-cache = <&l3c>;
};
l2c_2: l2-cache2 {
+ compatible = "cache";
+ cache-unified;
cache-size = <2097152>;
cache-line-size = <64>;
cache-sets = <2048>;
+ cache-level = <2>;
next-level-cache = <&l3c>;
};
l2c_3: l2-cache3 {
+ compatible = "cache";
+ cache-unified;
cache-size = <2097152>;
cache-line-size = <64>;
cache-sets = <2048>;
+ cache-level = <2>;
next-level-cache = <&l3c>;
};
l3c: l3-cache {
+ compatible = "cache";
+ cache-unified;
cache-size = <4194304>;
cache-line-size = <64>;
+ cache-level = <3>;
cache-sets = <4096>;
};
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
index a44c56c1e56e..dd9a17922fe5 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
@@ -1293,14 +1293,14 @@
};
};
- dvfs_pwm_active_state: dvfs_pwm_active {
+ dvfs_pwm_active_state: pinmux-dvfs-pwm-active {
dvfs_pwm_pbb1 {
nvidia,pins = "dvfs_pwm_pbb1";
nvidia,tristate = <TEGRA_PIN_DISABLE>;
};
};
- dvfs_pwm_inactive_state: dvfs_pwm_inactive {
+ dvfs_pwm_inactive_state: pinmux-dvfs-pwm-inactive {
dvfs_pwm_pbb1 {
nvidia,pins = "dvfs_pwm_pbb1";
nvidia,tristate = <TEGRA_PIN_ENABLE>;
@@ -1368,6 +1368,7 @@
#size-cells = <0>;
ethernet@1 {
+ compatible = "usb955,9ff";
reg = <1>;
};
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts b/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts
index 37678c337a34..2041371ea7ff 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts
@@ -109,14 +109,14 @@
};
pinmux@700008d4 {
- dvfs_pwm_active_state: dvfs_pwm_active {
+ dvfs_pwm_active_state: pinmux-dvfs-pwm-active {
dvfs_pwm_pbb1 {
nvidia,pins = "dvfs_pwm_pbb1";
nvidia,tristate = <TEGRA_PIN_DISABLE>;
};
};
- dvfs_pwm_inactive_state: dvfs_pwm_inactive {
+ dvfs_pwm_inactive_state: pinmux-dvfs-pwm-inactive {
dvfs_pwm_pbb1 {
nvidia,pins = "dvfs_pwm_pbb1";
nvidia,tristate = <TEGRA_PIN_ENABLE>;
diff --git a/arch/arm64/boot/dts/nvidia/tegra210.dtsi b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
index 724e87450605..bc0cacb20d7a 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
@@ -554,42 +554,48 @@
compatible = "nvidia,tegra210-pinmux";
reg = <0x0 0x700008d4 0x0 0x29c>, /* Pad control registers */
<0x0 0x70003000 0x0 0x294>; /* Mux registers */
- sdmmc1_3v3_drv: sdmmc1-3v3-drv {
+
+ sdmmc1_3v3_drv: pinmux-sdmmc1-3v3-drv {
sdmmc1 {
nvidia,pins = "drive_sdmmc1";
nvidia,pull-down-strength = <0x8>;
nvidia,pull-up-strength = <0x8>;
};
};
- sdmmc1_1v8_drv: sdmmc1-1v8-drv {
+
+ sdmmc1_1v8_drv: pinmux-sdmmc1-1v8-drv {
sdmmc1 {
nvidia,pins = "drive_sdmmc1";
nvidia,pull-down-strength = <0x4>;
nvidia,pull-up-strength = <0x3>;
};
};
- sdmmc2_1v8_drv: sdmmc2-1v8-drv {
+
+ sdmmc2_1v8_drv: pinmux-sdmmc2-1v8-drv {
sdmmc2 {
nvidia,pins = "drive_sdmmc2";
nvidia,pull-down-strength = <0x10>;
nvidia,pull-up-strength = <0x10>;
};
};
- sdmmc3_3v3_drv: sdmmc3-3v3-drv {
+
+ sdmmc3_3v3_drv: pinmux-sdmmc3-3v3-drv {
sdmmc3 {
nvidia,pins = "drive_sdmmc3";
nvidia,pull-down-strength = <0x8>;
nvidia,pull-up-strength = <0x8>;
};
};
- sdmmc3_1v8_drv: sdmmc3-1v8-drv {
+
+ sdmmc3_1v8_drv: pinmux-sdmmc3-1v8-drv {
sdmmc3 {
nvidia,pins = "drive_sdmmc3";
nvidia,pull-down-strength = <0x4>;
nvidia,pull-up-strength = <0x3>;
};
};
- sdmmc4_1v8_drv: sdmmc4-1v8-drv {
+
+ sdmmc4_1v8_drv: pinmux-sdmmc4-1v8-drv {
sdmmc4 {
nvidia,pins = "drive_sdmmc4";
nvidia,pull-down-strength = <0x10>;
@@ -667,7 +673,6 @@
reg = <0x0 0x7000a000 0x0 0x100>;
#pwm-cells = <2>;
clocks = <&tegra_car TEGRA210_CLK_PWM>;
- clock-names = "pwm";
resets = <&tegra_car 17>;
reset-names = "pwm";
status = "disabled";
@@ -912,35 +917,33 @@
};
};
- sdmmc1_3v3: sdmmc1-3v3 {
- pins = "sdmmc1";
- power-source = <TEGRA_IO_PAD_VOLTAGE_3V3>;
- };
+ pinmux {
+ sdmmc1_3v3: sdmmc1-3v3 {
+ pins = "sdmmc1";
+ power-source = <TEGRA_IO_PAD_VOLTAGE_3V3>;
+ };
- sdmmc1_1v8: sdmmc1-1v8 {
- pins = "sdmmc1";
- power-source = <TEGRA_IO_PAD_VOLTAGE_1V8>;
- };
+ sdmmc1_1v8: sdmmc1-1v8 {
+ pins = "sdmmc1";
+ power-source = <TEGRA_IO_PAD_VOLTAGE_1V8>;
+ };
- sdmmc3_3v3: sdmmc3-3v3 {
- pins = "sdmmc3";
- power-source = <TEGRA_IO_PAD_VOLTAGE_3V3>;
- };
+ sdmmc3_3v3: sdmmc3-3v3 {
+ pins = "sdmmc3";
+ power-source = <TEGRA_IO_PAD_VOLTAGE_3V3>;
+ };
- sdmmc3_1v8: sdmmc3-1v8 {
- pins = "sdmmc3";
- power-source = <TEGRA_IO_PAD_VOLTAGE_1V8>;
- };
+ sdmmc3_1v8: sdmmc3-1v8 {
+ pins = "sdmmc3";
+ power-source = <TEGRA_IO_PAD_VOLTAGE_1V8>;
+ };
- pex_dpd_disable: pex_en {
- pex-dpd-disable {
+ pex_dpd_disable: pex-dpd-disable {
pins = "pex-bias", "pex-clk1", "pex-clk2";
low-power-disable;
};
- };
- pex_dpd_enable: pex_dis {
- pex-dpd-enable {
+ pex_dpd_enable: pex-dpd-enable {
pins = "pex-bias", "pex-clk1", "pex-clk2";
low-power-enable;
};
@@ -1865,7 +1868,6 @@
<&tegra_car TEGRA210_CLK_QSPI_PM>;
clock-names = "qspi", "qspi_out";
resets = <&tegra_car 211>;
- reset-names = "qspi";
dmas = <&apbdma 5>, <&apbdma 5>;
dma-names = "rx", "tx";
status = "disabled";
@@ -2005,6 +2007,7 @@
L2: l2-cache {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3701-0000.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3701-0000.dtsi
index 9e4d72cfa69f..8b86ea9cb50c 100644
--- a/arch/arm64/boot/dts/nvidia/tegra234-p3701-0000.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra234-p3701-0000.dtsi
@@ -39,7 +39,6 @@
regulator-max-microvolt = <12000000>;
gpio = <&gpio TEGRA234_MAIN_GPIO(A, 1) GPIO_ACTIVE_LOW>;
regulator-boot-on;
- enable-active-low;
};
bus@0 {
@@ -55,6 +54,13 @@
};
};
+ mmc@3400000 {
+ status = "okay";
+ bus-width = <4>;
+ cd-gpios = <&gpio TEGRA234_MAIN_GPIO(G, 7) GPIO_ACTIVE_LOW>;
+ disable-wp;
+ };
+
mmc@3460000 {
status = "okay";
bus-width = <8>;
diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0000.dts b/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0000.dts
index 57ab75328814..96aa2267b06d 100644
--- a/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0000.dts
+++ b/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000+p3701-0000.dts
@@ -2007,6 +2007,17 @@
status = "okay";
};
+ serial@31d0000 {
+ current-speed = <115200>;
+ status = "okay";
+ };
+
+ pwm@32a0000 {
+ assigned-clocks = <&bpmp TEGRA234_CLK_PWM3>;
+ assigned-clock-parents = <&bpmp TEGRA234_CLK_PLLP_OUT0>;
+ status = "okay";
+ };
+
hda@3510000 {
nvidia,model = "NVIDIA Jetson AGX Orin HDA";
status = "okay";
@@ -2014,7 +2025,7 @@
};
chosen {
- bootargs = "console=ttyS0,115200n8";
+ bootargs = "console=ttyTCU0,115200n8";
stdout-path = "serial0:115200n8";
};
@@ -2184,4 +2195,12 @@
phy-names = "p2u-0", "p2u-1", "p2u-2", "p2u-3", "p2u-4",
"p2u-5", "p2u-6", "p2u-7";
};
+
+ pwm-fan {
+ compatible = "pwm-fan";
+ pwms = <&pwm3 0 45334>;
+
+ cooling-levels = <0 95 178 255>;
+ #cooling-cells = <2>;
+ };
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000.dtsi b/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000.dtsi
index a85993c85e45..e76894574d32 100644
--- a/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra234-p3737-0000.dtsi
@@ -2,4 +2,18 @@
/ {
compatible = "nvidia,p3737-0000";
+
+ bus@0 {
+ pwm@3280000 {
+ status = "okay";
+ };
+
+ pwm@32c0000 {
+ status = "okay";
+ };
+
+ pwm@32f0000 {
+ status = "okay";
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra234.dtsi b/arch/arm64/boot/dts/nvidia/tegra234.dtsi
index 0170bfa8a467..eaf05ee9acd1 100644
--- a/arch/arm64/boot/dts/nvidia/tegra234.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra234.dtsi
@@ -7,6 +7,7 @@
#include <dt-bindings/memory/tegra234-mc.h>
#include <dt-bindings/power/tegra234-powergate.h>
#include <dt-bindings/reset/tegra234-reset.h>
+#include <dt-bindings/pinctrl/pinctrl-tegra-io-pad.h>
/ {
compatible = "nvidia,tegra234";
@@ -27,7 +28,8 @@
reg = <0x2600000 0x210000>;
resets = <&bpmp TEGRA234_RESET_GPCDMA>;
reset-names = "gpcdma";
- interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
+ interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>,
@@ -60,6 +62,7 @@
<GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
#dma-cells = <1>;
iommus = <&smmu_niso0 TEGRA234_SID_GPCDMA>;
+ dma-channel-mask = <0xfffffffe>;
dma-coherent;
};
@@ -564,7 +567,7 @@
#address-cells = <1>;
#size-cells = <1>;
- ranges = <0x15000000 0x15000000 0x01000000>;
+ ranges = <0x14800000 0x14800000 0x02000000>;
interconnects = <&mc TEGRA234_MEMORY_CLIENT_HOST1XDMAR &emc>;
interconnect-names = "dma-mem";
iommus = <&smmu_niso1 TEGRA234_SID_HOST1X>;
@@ -603,6 +606,42 @@
iommus = <&smmu_niso1 TEGRA234_SID_VIC>;
dma-coherent;
};
+
+ nvdec@15480000 {
+ compatible = "nvidia,tegra234-nvdec";
+ reg = <0x15480000 0x00040000>;
+ clocks = <&bpmp TEGRA234_CLK_NVDEC>,
+ <&bpmp TEGRA234_CLK_FUSE>,
+ <&bpmp TEGRA234_CLK_TSEC_PKA>;
+ clock-names = "nvdec", "fuse", "tsec_pka";
+ resets = <&bpmp TEGRA234_RESET_NVDEC>;
+ reset-names = "nvdec";
+ power-domains = <&bpmp TEGRA234_POWER_DOMAIN_NVDEC>;
+ interconnects = <&mc TEGRA234_MEMORY_CLIENT_NVDECSRD &emc>,
+ <&mc TEGRA234_MEMORY_CLIENT_NVDECSWR &emc>;
+ interconnect-names = "dma-mem", "write";
+ iommus = <&smmu_niso1 TEGRA234_SID_NVDEC>;
+ dma-coherent;
+
+ nvidia,memory-controller = <&mc>;
+
+ /*
+ * Placeholder values that firmware needs to update with the real
+ * offsets parsed from the microcode headers.
+ */
+ nvidia,bl-manifest-offset = <0>;
+ nvidia,bl-data-offset = <0>;
+ nvidia,bl-code-offset = <0>;
+ nvidia,os-manifest-offset = <0>;
+ nvidia,os-data-offset = <0>;
+ nvidia,os-code-offset = <0>;
+
+ /*
+ * Firmware needs to set this to "okay" once the above values have
+ * been updated.
+ */
+ status = "disabled";
+ };
};
gpio: gpio@2200000 {
@@ -836,6 +875,13 @@
dma-names = "rx", "tx";
};
+ uarti: serial@31d0000 {
+ compatible = "arm,sbsa-uart";
+ reg = <0x31d0000 0x10000>;
+ interrupts = <GIC_SPI 285 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
dp_aux_ch3_i2c: i2c@31e0000 {
compatible = "nvidia,tegra194-i2c";
reg = <0x31e0000 0x100>;
@@ -865,22 +911,79 @@
<&bpmp TEGRA234_CLK_QSPI0_PM>;
clock-names = "qspi", "qspi_out";
resets = <&bpmp TEGRA234_RESET_QSPI0>;
- reset-names = "qspi";
status = "disabled";
};
pwm1: pwm@3280000 {
- compatible = "nvidia,tegra194-pwm",
- "nvidia,tegra186-pwm";
+ compatible = "nvidia,tegra234-pwm", "nvidia,tegra194-pwm";
reg = <0x3280000 0x10000>;
clocks = <&bpmp TEGRA234_CLK_PWM1>;
- clock-names = "pwm";
resets = <&bpmp TEGRA234_RESET_PWM1>;
reset-names = "pwm";
status = "disabled";
#pwm-cells = <2>;
};
+ pwm2: pwm@3290000 {
+ compatible = "nvidia,tegra234-pwm", "nvidia,tegra194-pwm";
+ reg = <0x3290000 0x10000>;
+ clocks = <&bpmp TEGRA234_CLK_PWM2>;
+ resets = <&bpmp TEGRA234_RESET_PWM2>;
+ reset-names = "pwm";
+ status = "disabled";
+ #pwm-cells = <2>;
+ };
+
+ pwm3: pwm@32a0000 {
+ compatible = "nvidia,tegra234-pwm", "nvidia,tegra194-pwm";
+ reg = <0x32a0000 0x10000>;
+ clocks = <&bpmp TEGRA234_CLK_PWM3>;
+ resets = <&bpmp TEGRA234_RESET_PWM3>;
+ reset-names = "pwm";
+ status = "disabled";
+ #pwm-cells = <2>;
+ };
+
+ pwm5: pwm@32c0000 {
+ compatible = "nvidia,tegra234-pwm", "nvidia,tegra194-pwm";
+ reg = <0x32c0000 0x10000>;
+ clocks = <&bpmp TEGRA234_CLK_PWM5>;
+ resets = <&bpmp TEGRA234_RESET_PWM5>;
+ reset-names = "pwm";
+ status = "disabled";
+ #pwm-cells = <2>;
+ };
+
+ pwm6: pwm@32d0000 {
+ compatible = "nvidia,tegra234-pwm", "nvidia,tegra194-pwm";
+ reg = <0x32d0000 0x10000>;
+ clocks = <&bpmp TEGRA234_CLK_PWM6>;
+ resets = <&bpmp TEGRA234_RESET_PWM6>;
+ reset-names = "pwm";
+ status = "disabled";
+ #pwm-cells = <2>;
+ };
+
+ pwm7: pwm@32e0000 {
+ compatible = "nvidia,tegra234-pwm", "nvidia,tegra194-pwm";
+ reg = <0x32e0000 0x10000>;
+ clocks = <&bpmp TEGRA234_CLK_PWM7>;
+ resets = <&bpmp TEGRA234_RESET_PWM7>;
+ reset-names = "pwm";
+ status = "disabled";
+ #pwm-cells = <2>;
+ };
+
+ pwm8: pwm@32f0000 {
+ compatible = "nvidia,tegra234-pwm", "nvidia,tegra194-pwm";
+ reg = <0x32f0000 0x10000>;
+ clocks = <&bpmp TEGRA234_CLK_PWM8>;
+ resets = <&bpmp TEGRA234_RESET_PWM8>;
+ reset-names = "pwm";
+ status = "disabled";
+ #pwm-cells = <2>;
+ };
+
spi@3300000 {
compatible = "nvidia,tegra234-qspi";
reg = <0x3300000 0x1000>;
@@ -891,7 +994,41 @@
<&bpmp TEGRA234_CLK_QSPI1_PM>;
clock-names = "qspi", "qspi_out";
resets = <&bpmp TEGRA234_RESET_QSPI1>;
- reset-names = "qspi";
+ status = "disabled";
+ };
+
+ mmc@3400000 {
+ compatible = "nvidia,tegra234-sdhci", "nvidia,tegra186-sdhci";
+ reg = <0x03400000 0x20000>;
+ interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&bpmp TEGRA234_CLK_SDMMC1>,
+ <&bpmp TEGRA234_CLK_SDMMC_LEGACY_TM>;
+ clock-names = "sdhci", "tmclk";
+ assigned-clocks = <&bpmp TEGRA234_CLK_SDMMC1>,
+ <&bpmp TEGRA234_CLK_PLLC4_MUXED>;
+ assigned-clock-parents = <&bpmp TEGRA234_CLK_PLLC4_MUXED>,
+ <&bpmp TEGRA234_CLK_PLLC4_VCO_DIV2>;
+ resets = <&bpmp TEGRA234_RESET_SDMMC1>;
+ reset-names = "sdhci";
+ interconnects = <&mc TEGRA234_MEMORY_CLIENT_SDMMCRA &emc>,
+ <&mc TEGRA234_MEMORY_CLIENT_SDMMCWA &emc>;
+ interconnect-names = "dma-mem", "write";
+ iommus = <&smmu_niso1 TEGRA234_SID_SDMMC1A>;
+ pinctrl-names = "sdmmc-3v3", "sdmmc-1v8";
+ pinctrl-0 = <&sdmmc1_3v3>;
+ pinctrl-1 = <&sdmmc1_1v8>;
+ nvidia,pad-autocal-pull-up-offset-3v3-timeout = <0x07>;
+ nvidia,pad-autocal-pull-down-offset-3v3-timeout = <0x07>;
+ nvidia,pad-autocal-pull-up-offset-1v8-timeout = <0x06>;
+ nvidia,pad-autocal-pull-down-offset-1v8-timeout = <0x07>;
+ nvidia,pad-autocal-pull-up-offset-sdr104 = <0x00>;
+ nvidia,pad-autocal-pull-down-offset-sdr104 = <0x00>;
+ nvidia,default-tap = <14>;
+ nvidia,default-trim = <0x8>;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-ddr50;
+ sd-uhs-sdr104;
status = "disabled";
};
@@ -925,7 +1062,7 @@
};
hda@3510000 {
- compatible = "nvidia,tegra234-hda", "nvidia,tegra30-hda";
+ compatible = "nvidia,tegra234-hda";
reg = <0x3510000 0x10000>;
interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&bpmp TEGRA234_CLK_AZA_BIT>,
@@ -967,6 +1104,198 @@
#mbox-cells = <2>;
};
+ p2u_hsio_0: phy@3e00000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03e00000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_hsio_1: phy@3e10000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03e10000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_hsio_2: phy@3e20000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03e20000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_hsio_3: phy@3e30000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03e30000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_hsio_4: phy@3e40000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03e40000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_hsio_5: phy@3e50000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03e50000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_hsio_6: phy@3e60000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03e60000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_hsio_7: phy@3e70000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03e70000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_nvhs_0: phy@3e90000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03e90000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_nvhs_1: phy@3ea0000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03ea0000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_nvhs_2: phy@3eb0000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03eb0000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_nvhs_3: phy@3ec0000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03ec0000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_nvhs_4: phy@3ed0000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03ed0000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_nvhs_5: phy@3ee0000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03ee0000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_nvhs_6: phy@3ef0000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03ef0000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_nvhs_7: phy@3f00000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03f00000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_gbe_0: phy@3f20000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03f20000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_gbe_1: phy@3f30000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03f30000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_gbe_2: phy@3f40000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03f40000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_gbe_3: phy@3f50000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03f50000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_gbe_4: phy@3f60000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03f60000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_gbe_5: phy@3f70000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03f70000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_gbe_6: phy@3f80000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03f80000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
+ p2u_gbe_7: phy@3f90000 {
+ compatible = "nvidia,tegra234-p2u";
+ reg = <0x03f90000 0x10000>;
+ reg-names = "ctl";
+
+ #phy-cells = <0>;
+ };
+
ethernet@6800000 {
compatible = "nvidia,tegra234-mgbe";
reg = <0x06800000 0x10000>,
@@ -1259,198 +1588,6 @@
status = "okay";
};
- p2u_hsio_0: phy@3e00000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03e00000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_hsio_1: phy@3e10000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03e10000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_hsio_2: phy@3e20000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03e20000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_hsio_3: phy@3e30000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03e30000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_hsio_4: phy@3e40000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03e40000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_hsio_5: phy@3e50000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03e50000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_hsio_6: phy@3e60000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03e60000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_hsio_7: phy@3e70000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03e70000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_nvhs_0: phy@3e90000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03e90000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_nvhs_1: phy@3ea0000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03ea0000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_nvhs_2: phy@3eb0000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03eb0000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_nvhs_3: phy@3ec0000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03ec0000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_nvhs_4: phy@3ed0000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03ed0000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_nvhs_5: phy@3ee0000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03ee0000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_nvhs_6: phy@3ef0000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03ef0000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_nvhs_7: phy@3f00000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03f00000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_gbe_0: phy@3f20000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03f20000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_gbe_1: phy@3f30000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03f30000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_gbe_2: phy@3f40000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03f40000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_gbe_3: phy@3f50000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03f50000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_gbe_4: phy@3f60000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03f60000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_gbe_5: phy@3f70000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03f70000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_gbe_6: phy@3f80000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03f80000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
- p2u_gbe_7: phy@3f90000 {
- compatible = "nvidia,tegra234-p2u";
- reg = <0x03f90000 0x10000>;
- reg-names = "ctl";
-
- #phy-cells = <0>;
- };
-
hsp_aon: hsp@c150000 {
compatible = "nvidia,tegra234-hsp", "nvidia,tegra194-hsp";
reg = <0x0c150000 0x90000>;
@@ -1488,7 +1625,6 @@
gen8_i2c: i2c@c250000 {
compatible = "nvidia,tegra194-i2c";
reg = <0xc250000 0x100>;
- nvidia,hw-instance-id = <0x7>;
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
status = "disabled";
clock-frequency = <400000>;
@@ -1530,6 +1666,16 @@
gpio-controller;
};
+ pwm4: pwm@c340000 {
+ compatible = "nvidia,tegra234-pwm", "nvidia,tegra194-pwm";
+ reg = <0xc340000 0x10000>;
+ clocks = <&bpmp TEGRA234_CLK_PWM4>;
+ resets = <&bpmp TEGRA234_RESET_PWM4>;
+ reset-names = "pwm";
+ status = "disabled";
+ #pwm-cells = <2>;
+ };
+
pmc: pmc@c360000 {
compatible = "nvidia,tegra234-pmc";
reg = <0x0c360000 0x10000>,
@@ -1541,6 +1687,26 @@
#interrupt-cells = <2>;
interrupt-controller;
+
+ sdmmc1_3v3: sdmmc1-3v3 {
+ pins = "sdmmc1-hv";
+ power-source = <TEGRA_IO_PAD_VOLTAGE_3V3>;
+ };
+
+ sdmmc1_1v8: sdmmc1-1v8 {
+ pins = "sdmmc1-hv";
+ power-source = <TEGRA_IO_PAD_VOLTAGE_1V8>;
+ };
+
+ sdmmc3_3v3: sdmmc3-3v3 {
+ pins = "sdmmc3-hv";
+ power-source = <TEGRA_IO_PAD_VOLTAGE_3V3>;
+ };
+
+ sdmmc3_1v8: sdmmc3-1v8 {
+ pins = "sdmmc3-hv";
+ power-source = <TEGRA_IO_PAD_VOLTAGE_1V8>;
+ };
};
aon-fabric@c600000 {
@@ -1576,7 +1742,7 @@
interrupt-controller;
};
- smmu_iso: iommu@10000000{
+ smmu_iso: iommu@10000000 {
compatible = "nvidia,tegra234-smmu", "nvidia,smmu-500";
reg = <0x10000000 0x1000000>;
interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>,
@@ -1879,8 +2045,9 @@
reg = <0x00 0x140a0000 0x0 0x00020000>, /* appl registers (128K) */
<0x00 0x2a000000 0x0 0x00040000>, /* configuration space (256K) */
<0x00 0x2a040000 0x0 0x00040000>, /* iATU_DMA reg space (256K) */
- <0x00 0x2a080000 0x0 0x00040000>; /* DBI reg space (256K) */
- reg-names = "appl", "config", "atu_dma", "dbi";
+ <0x00 0x2a080000 0x0 0x00040000>, /* DBI reg space (256K) */
+ <0x35 0x30000000 0x0 0x10000000>; /* ECAM (256MB) */
+ reg-names = "appl", "config", "atu_dma", "dbi", "ecam";
#address-cells = <3>;
#size-cells = <2>;
@@ -1932,8 +2099,9 @@
reg = <0x00 0x140c0000 0x0 0x00020000>, /* appl registers (128K) */
<0x00 0x2c000000 0x0 0x00040000>, /* configuration space (256K) */
<0x00 0x2c040000 0x0 0x00040000>, /* iATU_DMA reg space (256K) */
- <0x00 0x2c080000 0x0 0x00040000>; /* DBI reg space (256K) */
- reg-names = "appl", "config", "atu_dma", "dbi";
+ <0x00 0x2c080000 0x0 0x00040000>, /* DBI reg space (256K) */
+ <0x38 0x30000000 0x0 0x10000000>; /* ECAM (256MB) */
+ reg-names = "appl", "config", "atu_dma", "dbi", "ecam";
#address-cells = <3>;
#size-cells = <2>;
@@ -1965,7 +2133,7 @@
bus-range = <0x0 0xff>;
- ranges = <0x43000000 0x35 0x40000000 0x35 0x40000000 0x2 0xe8000000>, /* prefetchable memory (11904 MB) */
+ ranges = <0x43000000 0x35 0x40000000 0x35 0x40000000 0x2 0xc0000000>, /* prefetchable memory (11264 MB) */
<0x02000000 0x0 0x40000000 0x38 0x28000000 0x0 0x08000000>, /* non-prefetchable memory (128 MB) */
<0x01000000 0x0 0x2c100000 0x00 0x2c100000 0x0 0x00100000>; /* downstream I/O (1 MB) */
@@ -1985,8 +2153,9 @@
reg = <0x00 0x140e0000 0x0 0x00020000>, /* appl registers (128K) */
<0x00 0x2e000000 0x0 0x00040000>, /* configuration space (256K) */
<0x00 0x2e040000 0x0 0x00040000>, /* iATU_DMA reg space (256K) */
- <0x00 0x2e080000 0x0 0x00040000>; /* DBI reg space (256K) */
- reg-names = "appl", "config", "atu_dma", "dbi";
+ <0x00 0x2e080000 0x0 0x00040000>, /* DBI reg space (256K) */
+ <0x3b 0x30000000 0x0 0x10000000>; /* ECAM (256MB) */
+ reg-names = "appl", "config", "atu_dma", "dbi", "ecam";
#address-cells = <3>;
#size-cells = <2>;
@@ -2038,8 +2207,9 @@
reg = <0x00 0x14100000 0x0 0x00020000>, /* appl registers (128K) */
<0x00 0x30000000 0x0 0x00040000>, /* configuration space (256K) */
<0x00 0x30040000 0x0 0x00040000>, /* iATU_DMA reg space (256K) */
- <0x00 0x30080000 0x0 0x00040000>; /* DBI reg space (256K) */
- reg-names = "appl", "config", "atu_dma", "dbi";
+ <0x00 0x30080000 0x0 0x00040000>, /* DBI reg space (256K) */
+ <0x20 0xb0000000 0x0 0x10000000>; /* ECAM (256MB) */
+ reg-names = "appl", "config", "atu_dma", "dbi", "ecam";
#address-cells = <3>;
#size-cells = <2>;
@@ -2091,8 +2261,9 @@
reg = <0x00 0x14120000 0x0 0x00020000>, /* appl registers (128K) */
<0x00 0x32000000 0x0 0x00040000>, /* configuration space (256K) */
<0x00 0x32040000 0x0 0x00040000>, /* iATU_DMA reg space (256K) */
- <0x00 0x32080000 0x0 0x00040000>; /* DBI reg space (256K) */
- reg-names = "appl", "config", "atu_dma", "dbi";
+ <0x00 0x32080000 0x0 0x00040000>, /* DBI reg space (256K) */
+ <0x20 0xf0000000 0x0 0x10000000>; /* ECAM (256MB) */
+ reg-names = "appl", "config", "atu_dma", "dbi", "ecam";
#address-cells = <3>;
#size-cells = <2>;
@@ -2144,8 +2315,9 @@
reg = <0x00 0x14140000 0x0 0x00020000>, /* appl registers (128K) */
<0x00 0x34000000 0x0 0x00040000>, /* configuration space (256K) */
<0x00 0x34040000 0x0 0x00040000>, /* iATU_DMA reg space (256K) */
- <0x00 0x34080000 0x0 0x00040000>; /* DBI reg space (256K) */
- reg-names = "appl", "config", "atu_dma", "dbi";
+ <0x00 0x34080000 0x0 0x00040000>, /* DBI reg space (256K) */
+ <0x21 0x30000000 0x0 0x10000000>; /* ECAM (256MB) */
+ reg-names = "appl", "config", "atu_dma", "dbi", "ecam";
#address-cells = <3>;
#size-cells = <2>;
@@ -2178,7 +2350,7 @@
bus-range = <0x0 0xff>;
ranges = <0x43000000 0x21 0x00000000 0x21 0x00000000 0x0 0x28000000>, /* prefetchable memory (640 MB) */
- <0x02000000 0x0 0x40000000 0x21 0xe8000000 0x0 0x08000000>, /* non-prefetchable memory (128 MB) */
+ <0x02000000 0x0 0x40000000 0x21 0x28000000 0x0 0x08000000>, /* non-prefetchable memory (128 MB) */
<0x01000000 0x0 0x34100000 0x00 0x34100000 0x0 0x00100000>; /* downstream I/O (1 MB) */
interconnects = <&mc TEGRA234_MEMORY_CLIENT_PCIE3R &emc>,
@@ -2197,8 +2369,9 @@
reg = <0x00 0x14160000 0x0 0x00020000>, /* appl registers (128K) */
<0x00 0x36000000 0x0 0x00040000>, /* configuration space (256K) */
<0x00 0x36040000 0x0 0x00040000>, /* iATU_DMA reg space (256K) */
- <0x00 0x36080000 0x0 0x00040000>; /* DBI reg space (256K) */
- reg-names = "appl", "config", "atu_dma", "dbi";
+ <0x00 0x36080000 0x0 0x00040000>, /* DBI reg space (256K) */
+ <0x24 0x30000000 0x0 0x10000000>; /* ECAM (256MB) */
+ reg-names = "appl", "config", "atu_dma", "dbi", "ecam";
#address-cells = <3>;
#size-cells = <2>;
@@ -2250,8 +2423,9 @@
reg = <0x00 0x14180000 0x0 0x00020000>, /* appl registers (128K) */
<0x00 0x38000000 0x0 0x00040000>, /* configuration space (256K) */
<0x00 0x38040000 0x0 0x00040000>, /* iATU_DMA reg space (256K) */
- <0x00 0x38080000 0x0 0x00040000>; /* DBI reg space (256K) */
- reg-names = "appl", "config", "atu_dma", "dbi";
+ <0x00 0x38080000 0x0 0x00040000>, /* DBI reg space (256K) */
+ <0x27 0x30000000 0x0 0x10000000>; /* ECAM (256MB) */
+ reg-names = "appl", "config", "atu_dma", "dbi", "ecam";
#address-cells = <3>;
#size-cells = <2>;
@@ -2303,8 +2477,9 @@
reg = <0x00 0x141a0000 0x0 0x00020000>, /* appl registers (128K) */
<0x00 0x3a000000 0x0 0x00040000>, /* configuration space (256K) */
<0x00 0x3a040000 0x0 0x00040000>, /* iATU_DMA reg space (256K) */
- <0x00 0x3a080000 0x0 0x00040000>; /* DBI reg space (256K) */
- reg-names = "appl", "config", "atu_dma", "dbi";
+ <0x00 0x3a080000 0x0 0x00040000>, /* DBI reg space (256K) */
+ <0x2b 0x30000000 0x0 0x10000000>; /* ECAM (256MB) */
+ reg-names = "appl", "config", "atu_dma", "dbi", "ecam";
#address-cells = <3>;
#size-cells = <2>;
@@ -2336,7 +2511,7 @@
bus-range = <0x0 0xff>;
- ranges = <0x43000000 0x27 0x40000000 0x27 0x40000000 0x3 0xe8000000>, /* prefetchable memory (16000 MB) */
+ ranges = <0x43000000 0x28 0x00000000 0x28 0x00000000 0x3 0x28000000>, /* prefetchable memory (12928 MB) */
<0x02000000 0x0 0x40000000 0x2b 0x28000000 0x0 0x08000000>, /* non-prefetchable memory (128 MB) */
<0x01000000 0x0 0x3a100000 0x00 0x3a100000 0x0 0x00100000>; /* downstream I/O (1 MB) */
@@ -2356,8 +2531,9 @@
reg = <0x00 0x141c0000 0x0 0x00020000>, /* appl registers (128K) */
<0x00 0x3c000000 0x0 0x00040000>, /* configuration space (256K) */
<0x00 0x3c040000 0x0 0x00040000>, /* iATU_DMA reg space (256K) */
- <0x00 0x3c080000 0x0 0x00040000>; /* DBI reg space (256K) */
- reg-names = "appl", "config", "atu_dma", "dbi";
+ <0x00 0x3c080000 0x0 0x00040000>, /* DBI reg space (256K) */
+ <0x2e 0x30000000 0x0 0x10000000>; /* ECAM (256MB) */
+ reg-names = "appl", "config", "atu_dma", "dbi", "ecam";
#address-cells = <3>;
#size-cells = <2>;
@@ -2409,8 +2585,9 @@
reg = <0x00 0x141e0000 0x0 0x00020000>, /* appl registers (128K) */
<0x00 0x3e000000 0x0 0x00040000>, /* configuration space (256K) */
<0x00 0x3e040000 0x0 0x00040000>, /* iATU_DMA reg space (256K) */
- <0x00 0x3e080000 0x0 0x00040000>; /* DBI reg space (256K) */
- reg-names = "appl", "config", "atu_dma", "dbi";
+ <0x00 0x3e080000 0x0 0x00040000>, /* DBI reg space (256K) */
+ <0x32 0x30000000 0x0 0x10000000>; /* ECAM (256MB) */
+ reg-names = "appl", "config", "atu_dma", "dbi", "ecam";
#address-cells = <3>;
#size-cells = <2>;
@@ -2442,7 +2619,7 @@
bus-range = <0x0 0xff>;
- ranges = <0x43000000 0x2e 0x40000000 0x2e 0x40000000 0x3 0xe8000000>, /* prefetchable memory (16000 MB) */
+ ranges = <0x43000000 0x30 0x00000000 0x30 0x00000000 0x2 0x28000000>, /* prefetchable memory (8832 MB) */
<0x02000000 0x0 0x40000000 0x32 0x28000000 0x0 0x08000000>, /* non-prefetchable memory (128 MB) */
<0x01000000 0x0 0x3e100000 0x00 0x3e100000 0x0 0x00100000>; /* downstream I/O (1 MB) */
@@ -2905,117 +3082,150 @@
};
l2c0_0: l2-cache00 {
+ compatible = "cache";
cache-size = <262144>;
cache-line-size = <64>;
cache-sets = <512>;
cache-unified;
+ cache-level = <2>;
next-level-cache = <&l3c0>;
};
l2c0_1: l2-cache01 {
+ compatible = "cache";
cache-size = <262144>;
cache-line-size = <64>;
cache-sets = <512>;
cache-unified;
+ cache-level = <2>;
next-level-cache = <&l3c0>;
};
l2c0_2: l2-cache02 {
+ compatible = "cache";
cache-size = <262144>;
cache-line-size = <64>;
cache-sets = <512>;
cache-unified;
+ cache-level = <2>;
next-level-cache = <&l3c0>;
};
l2c0_3: l2-cache03 {
+ compatible = "cache";
cache-size = <262144>;
cache-line-size = <64>;
cache-sets = <512>;
cache-unified;
+ cache-level = <2>;
next-level-cache = <&l3c0>;
};
l2c1_0: l2-cache10 {
+ compatible = "cache";
cache-size = <262144>;
cache-line-size = <64>;
cache-sets = <512>;
cache-unified;
+ cache-level = <2>;
next-level-cache = <&l3c1>;
};
l2c1_1: l2-cache11 {
+ compatible = "cache";
cache-size = <262144>;
cache-line-size = <64>;
cache-sets = <512>;
cache-unified;
+ cache-level = <2>;
next-level-cache = <&l3c1>;
};
l2c1_2: l2-cache12 {
+ compatible = "cache";
cache-size = <262144>;
cache-line-size = <64>;
cache-sets = <512>;
cache-unified;
+ cache-level = <2>;
next-level-cache = <&l3c1>;
};
l2c1_3: l2-cache13 {
+ compatible = "cache";
cache-size = <262144>;
cache-line-size = <64>;
cache-sets = <512>;
cache-unified;
+ cache-level = <2>;
next-level-cache = <&l3c1>;
};
l2c2_0: l2-cache20 {
+ compatible = "cache";
cache-size = <262144>;
cache-line-size = <64>;
cache-sets = <512>;
cache-unified;
+ cache-level = <2>;
next-level-cache = <&l3c2>;
};
l2c2_1: l2-cache21 {
+ compatible = "cache";
cache-size = <262144>;
cache-line-size = <64>;
cache-sets = <512>;
cache-unified;
+ cache-level = <2>;
next-level-cache = <&l3c2>;
};
l2c2_2: l2-cache22 {
+ compatible = "cache";
cache-size = <262144>;
cache-line-size = <64>;
cache-sets = <512>;
cache-unified;
+ cache-level = <2>;
next-level-cache = <&l3c2>;
};
l2c2_3: l2-cache23 {
+ compatible = "cache";
cache-size = <262144>;
cache-line-size = <64>;
cache-sets = <512>;
cache-unified;
+ cache-level = <2>;
next-level-cache = <&l3c2>;
};
l3c0: l3-cache0 {
+ compatible = "cache";
+ cache-unified;
cache-size = <2097152>;
cache-line-size = <64>;
cache-sets = <2048>;
+ cache-level = <3>;
};
l3c1: l3-cache1 {
+ compatible = "cache";
+ cache-unified;
cache-size = <2097152>;
cache-line-size = <64>;
cache-sets = <2048>;
+ cache-level = <3>;
};
l3c2: l3-cache2 {
+ compatible = "cache";
+ cache-unified;
cache-size = <2097152>;
cache-line-size = <64>;
cache-sets = <2048>;
+ cache-level = <3>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index d7669a7cee9f..3e79496292e7 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -21,6 +21,8 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-grandmax.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-j5.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8916-samsung-serranove.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8916-wingtech-wt88047.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8956-sony-xperia-loire-kugo.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8956-sony-xperia-loire-suzu.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8992-lg-bullhead-rev-10.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8992-lg-bullhead-rev-101.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8992-msft-lumia-octagon-talkman.dtb
@@ -33,12 +35,14 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8994-sony-xperia-kitakami-satsuki.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8994-sony-xperia-kitakami-sumire.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8994-sony-xperia-kitakami-suzuran.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8996-mtp.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8996-oneplus3.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8996-oneplus3t.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8996-sony-xperia-tone-dora.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8996-sony-xperia-tone-kagura.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8996-sony-xperia-tone-keyaki.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8996-xiaomi-gemini.dtb
-dtb-$(CONFIG_ARCH_QCOM) += msm8996-xiaomi-natrium.dtb
-dtb-$(CONFIG_ARCH_QCOM) += msm8996-xiaomi-scorpio.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8996pro-xiaomi-natrium.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8996pro-xiaomi-scorpio.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-asus-novago-tp370ql.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-fxtec-pro1.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-hp-envy-x2.dtb
@@ -49,11 +53,14 @@ dtb-$(CONFIG_ARCH_QCOM) += msm8998-oneplus-dumpling.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-lilac.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-maple.dtb
dtb-$(CONFIG_ARCH_QCOM) += msm8998-sony-xperia-yoshino-poplar.dtb
+dtb-$(CONFIG_ARCH_QCOM) += msm8998-xiaomi-sagit.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-1000.dtb
dtb-$(CONFIG_ARCH_QCOM) += qcs404-evb-4000.dtb
dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5.dtb
+dtb-$(CONFIG_ARCH_QCOM) += qrb5165-rb5-vision-mezzanine.dtb
dtb-$(CONFIG_ARCH_QCOM) += sa8155p-adp.dtb
dtb-$(CONFIG_ARCH_QCOM) += sa8295p-adp.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sa8540p-ride.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-idp.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-coachz-r1.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-coachz-r1-lte.dtb
@@ -87,6 +94,8 @@ dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-pazquel-lte-parade.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-pazquel-lte-ti.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-pazquel-parade.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-pazquel-ti.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-pazquel360-lte.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-pazquel360-wifi.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-pompom-r1.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-pompom-r1-lte.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-pompom-r2.dtb
@@ -104,11 +113,14 @@ dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-wormdingler-rev1-boe-rt5682s.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-r1.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7180-trogdor-r1-lte.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7280-herobrine-crd.dtb
-dtb-$(CONFIG_ARCH_QCOM) += sc7280-herobrine-evoker-r0.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sc7280-herobrine-evoker.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sc7280-herobrine-evoker-lte.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7280-herobrine-herobrine-r1.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7280-herobrine-villager-r0.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7280-herobrine-villager-r1.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7280-herobrine-villager-r1-lte.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sc7280-herobrine-zombie.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sc7280-herobrine-zombie-lte.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7280-idp.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7280-idp2.dtb
dtb-$(CONFIG_ARCH_QCOM) += sc7280-crd-r3.dtb
@@ -122,25 +134,31 @@ dtb-$(CONFIG_ARCH_QCOM) += sdm630-sony-xperia-nile-voyager.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm632-fairphone-fp3.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm636-sony-xperia-ganges-mermaid.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm660-xiaomi-lavender.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sdm670-google-sargo.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r1.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r2.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-cheza-r3.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-db845c.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sdm845-db845c-navigation-mezzanine.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-lg-judyln.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-lg-judyp.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-mtp.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-oneplus-enchilada.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-oneplus-fajita.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sdm845-samsung-starqltechn.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-sony-xperia-tama-akari.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-sony-xperia-tama-akatsuki.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-sony-xperia-tama-apollo.dtb
-dtb-$(CONFIG_ARCH_QCOM) += sdm845-xiaomi-beryllium.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sdm845-xiaomi-beryllium-ebbg.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sdm845-xiaomi-beryllium-tianma.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-xiaomi-polaris.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm845-shift-axolotl.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm850-lenovo-yoga-c630.dtb
dtb-$(CONFIG_ARCH_QCOM) += sdm850-samsung-w737.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sm4250-oneplus-billie2.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm6125-sony-xperia-seine-pdx201.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm6350-sony-xperia-lena-pdx213.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sm6375-sony-xperia-murray-pdx225.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm7225-fairphone-fp4.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8150-hdk.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8150-microsoft-surface-duo.dtb
@@ -159,3 +177,4 @@ dtb-$(CONFIG_ARCH_QCOM) += sm8350-sony-xperia-sagami-pdx215.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8450-hdk.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8450-qrd.dtb
dtb-$(CONFIG_ARCH_QCOM) += sm8450-sony-xperia-nagara-pdx223.dtb
+dtb-$(CONFIG_ARCH_QCOM) += sm8450-sony-xperia-nagara-pdx224.dtb
diff --git a/arch/arm64/boot/dts/qcom/apq8016-sbc.dts b/arch/arm64/boot/dts/qcom/apq8016-sbc.dts
index 1b613098fb4a..ef5b39ba1238 100644
--- a/arch/arm64/boot/dts/qcom/apq8016-sbc.dts
+++ b/arch/arm64/boot/dts/qcom/apq8016-sbc.dts
@@ -718,14 +718,14 @@
"USR_LED_2_CTRL", /* GPIO 120 */
"SB_HS_ID";
- msmgpio_leds: msmgpio-leds {
+ msmgpio_leds: msmgpio-leds-state {
pins = "gpio21", "gpio120";
function = "gpio";
output-low;
};
- usb_id_default: usb-id-default {
+ usb_id_default: usb-id-default-state {
pins = "gpio121";
function = "gpio";
@@ -734,7 +734,7 @@
bias-pull-up;
};
- adv7533_int_active: adv533-int-active {
+ adv7533_int_active: adv533-int-active-state {
pins = "gpio31";
function = "gpio";
@@ -742,7 +742,7 @@
bias-disable;
};
- adv7533_int_suspend: adv7533-int-suspend {
+ adv7533_int_suspend: adv7533-int-suspend-state {
pins = "gpio31";
function = "gpio";
@@ -750,7 +750,7 @@
bias-disable;
};
- adv7533_switch_active: adv7533-switch-active {
+ adv7533_switch_active: adv7533-switch-active-state {
pins = "gpio32";
function = "gpio";
@@ -758,7 +758,7 @@
bias-disable;
};
- adv7533_switch_suspend: adv7533-switch-suspend {
+ adv7533_switch_suspend: adv7533-switch-suspend-state {
pins = "gpio32";
function = "gpio";
@@ -766,7 +766,7 @@
bias-disable;
};
- msm_key_volp_n_default: msm-key-volp-n-default {
+ msm_key_volp_n_default: msm-key-volp-n-default-state {
pins = "gpio107";
function = "gpio";
@@ -839,7 +839,7 @@
function = "digital";
output-low;
- power-source = <PM8916_MPP_L5>; // 1.8V
+ power-source = <PM8916_MPP_L5>; /* 1.8V */
};
pm8916_mpps_leds: pm8916-mpps-state {
diff --git a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
index 5cdc7ac1a9c0..fe6c415e8229 100644
--- a/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
+++ b/arch/arm64/boot/dts/qcom/apq8096-db820c.dts
@@ -422,82 +422,46 @@
"NC", /* GPIO_148 */
"NC"; /* GPIO_149 */
- sdc2_cd_on: sdc2_cd_on {
- mux {
- pins = "gpio38";
- function = "gpio";
- };
-
- config {
- pins = "gpio38";
- bias-pull-up; /* pull up */
- drive-strength = <16>; /* 16 MA */
- };
+ sdc2_cd_on: sdc2-cd-on-state {
+ pins = "gpio38";
+ function = "gpio";
+ bias-pull-up;
+ drive-strength = <16>;
};
- sdc2_cd_off: sdc2_cd_off {
- mux {
- pins = "gpio38";
- function = "gpio";
- };
-
- config {
- pins = "gpio38";
- bias-pull-up; /* pull up */
- drive-strength = <2>; /* 2 MA */
- };
+ sdc2_cd_off: sdc2-cd-off-state {
+ pins = "gpio38";
+ function = "gpio";
+ bias-pull-up;
+ drive-strength = <2>;
};
- hdmi_hpd_active: hdmi_hpd_active {
- mux {
- pins = "gpio34";
- function = "hdmi_hot";
- };
-
- config {
- pins = "gpio34";
- bias-pull-down;
- drive-strength = <16>;
- };
+ hdmi_hpd_active: hdmi-hpd-active-state {
+ pins = "gpio34";
+ function = "hdmi_hot";
+ bias-pull-down;
+ drive-strength = <16>;
};
- hdmi_hpd_suspend: hdmi_hpd_suspend {
- mux {
- pins = "gpio34";
- function = "hdmi_hot";
- };
-
- config {
- pins = "gpio34";
- bias-pull-down;
- drive-strength = <2>;
- };
+ hdmi_hpd_suspend: hdmi-hpd-suspend-state {
+ pins = "gpio34";
+ function = "hdmi_hot";
+ bias-pull-down;
+ drive-strength = <2>;
};
- hdmi_ddc_active: hdmi_ddc_active {
- mux {
- pins = "gpio32", "gpio33";
- function = "hdmi_ddc";
- };
-
- config {
- pins = "gpio32", "gpio33";
- drive-strength = <2>;
- bias-pull-up;
- };
+ hdmi_ddc_active: hdmi-ddc-active-state {
+ pins = "gpio32", "gpio33";
+ function = "hdmi_ddc";
+ drive-strength = <2>;
+ bias-pull-up;
};
- hdmi_ddc_suspend: hdmi_ddc_suspend {
- mux {
- pins = "gpio32", "gpio33";
- function = "hdmi_ddc";
- };
-
- config {
- pins = "gpio32", "gpio33";
- drive-strength = <2>;
- bias-pull-down;
- };
+ hdmi_ddc_suspend: hdmi-ddc-suspend-state {
+ pins = "gpio32", "gpio33";
+ function = "hdmi_ddc";
+ drive-strength = <2>;
+ bias-pull-down;
};
};
@@ -560,7 +524,7 @@
pins = "gpio5";
function = PMIC_GPIO_FUNC_NORMAL;
output-low;
- power-source = <2>; // PM8994_GPIO_S4, 1.8V
+ power-source = <PM8994_GPIO_S4>; /* 1.8V */
};
};
@@ -569,7 +533,7 @@
pins = "gpio19";
function = PMIC_GPIO_FUNC_NORMAL;
output-low;
- power-source = <PM8994_GPIO_S4>; // 1.8V
+ power-source = <PM8994_GPIO_S4>; /* 1.8V */
qcom,drive-strength = <PMIC_GPIO_STRENGTH_LOW>;
bias-pull-down;
};
@@ -580,7 +544,7 @@
pins = "gpio8";
function = PMIC_GPIO_FUNC_NORMAL;
output-low;
- power-source = <PM8994_GPIO_S4>; // 1.8V
+ power-source = <PM8994_GPIO_S4>; /* 1.8V */
qcom,drive-strength = <PMIC_GPIO_STRENGTH_LOW>;
bias-pull-down;
};
@@ -590,7 +554,7 @@
pinconf {
pins = "gpio15";
function = "func1";
- power-source = <PM8994_GPIO_S4>; // 1.8V
+ power-source = <PM8994_GPIO_S4>; /* 1.8V */
};
};
@@ -602,7 +566,7 @@
drive-push-pull;
bias-pull-up;
qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
- power-source = <PM8994_GPIO_S4>; // 1.8V
+ power-source = <PM8994_GPIO_S4>; /* 1.8V */
};
};
@@ -623,7 +587,7 @@
input-enable;
bias-pull-down;
qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
- power-source = <PM8994_GPIO_S4>; // 1.8V
+ power-source = <PM8994_GPIO_S4>; /* 1.8V */
};
};
};
@@ -679,7 +643,7 @@
input-enable;
bias-pull-down;
qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
- power-source = <PM8994_GPIO_S4>; // 1.8V
+ power-source = <PM8994_GPIO_S4>; /* 1.8V */
};
};
};
@@ -751,7 +715,7 @@
};
&rpm_requests {
- pm8994-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pm8994-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -963,7 +927,7 @@
};
};
- pmi8994-regulators {
+ regulators-1 {
compatible = "qcom,rpm-pmi8994-regulators";
vdd_s1-supply = <&vph_pwr>;
diff --git a/arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts b/arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts
index 92f264891d84..71e0a500599c 100644
--- a/arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts
+++ b/arch/arm64/boot/dts/qcom/apq8096-ifc6640.dts
@@ -104,65 +104,27 @@
status = "okay";
};
-&tlmm {
- sdc2_pins_default: sdc2-pins-default {
- clk {
- pins = "sdc2_clk";
- bias-disable;
- drive-strength = <16>;
- };
-
- cmd {
- pins = "sdc2_cmd";
- bias-pull-up;
- drive-strength = <10>;
- };
-
- data {
- pins = "sdc2_data";
- bias-pull-up;
- drive-strength = <10>;
- };
+&sdc2_state_on {
+ cd-pins {
+ pins = "gpio38";
+ function = "gpio";
- cd {
- pins = "gpio38";
- function = "gpio";
-
- bias-pull-up;
- drive-strength = <16>;
- };
+ bias-pull-up;
+ drive-strength = <16>;
};
+};
- sdc2_pins_sleep: sdc2-pins-sleep {
- clk {
- pins = "sdc2_clk";
- bias-disable;
- drive-strength = <2>;
- };
-
- cmd {
- pins = "sdc2_cmd";
- bias-pull-up;
- drive-strength = <2>;
- };
-
- data {
- pins = "sdc2_data";
- bias-pull-up;
- drive-strength = <2>;
- };
-
- cd {
- pins = "gpio38";
- function = "gpio";
- bias-pull-up;
- drive-strength = <2>;
- };
+&sdc2_state_off {
+ cd-pins {
+ pins = "gpio38";
+ function = "gpio";
+ bias-pull-up;
+ drive-strength = <2>;
};
};
&rpm_requests {
- pm8994-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pm8994-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -372,10 +334,6 @@
vmmc-supply = <&vreg_l21a_2p95>;
vqmmc-supply = <&vreg_l13a_2p95>;
-
- pinctrl-names = "default", "sleep";
- pinctrl-0 = <&sdc2_pins_default>;
- pinctrl-1 = <&sdc2_pins_sleep>;
};
&ufshc {
diff --git a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts
index 1ba2eca33c7b..2aee8594b280 100644
--- a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts
+++ b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts
@@ -19,7 +19,6 @@
chosen {
stdout-path = "serial0:115200n8";
- bootargs-append = " swiotlb=1";
};
};
@@ -37,6 +36,8 @@
&blsp1_spi1 {
cs-select = <0>;
+ pinctrl-0 = <&spi_0_pins>;
+ pinctrl-names = "default";
status = "okay";
flash@0 {
@@ -49,13 +50,13 @@
};
&tlmm {
- i2c_1_pins: i2c-1-pins {
+ i2c_1_pins: i2c-1-state {
pins = "gpio42", "gpio43";
function = "blsp2_i2c";
drive-strength = <8>;
};
- spi_0_pins: spi-0-pins {
+ spi_0_pins: spi-0-state {
pins = "gpio38", "gpio39", "gpio40", "gpio41";
function = "blsp0_spi";
drive-strength = <8>;
@@ -80,9 +81,9 @@
};
&qusb_phy_1 {
- status = "ok";
+ status = "okay";
};
&usb2 {
- status = "ok";
+ status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/ipq6018.dtsi b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
index a7c7ca980a71..5d453f11acd9 100644
--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
@@ -218,14 +218,14 @@
interrupt-controller;
#interrupt-cells = <2>;
- serial_3_pins: serial3-pinmux {
+ serial_3_pins: serial3-state {
pins = "gpio44", "gpio45";
function = "blsp2_uart";
drive-strength = <8>;
bias-pull-down;
};
- qpic_pins: qpic-pins {
+ qpic_pins: qpic-state {
pins = "gpio1", "gpio3", "gpio4",
"gpio5", "gpio6", "gpio7",
"gpio8", "gpio10", "gpio11",
@@ -348,7 +348,7 @@
status = "disabled";
};
- qpic_nand: nand@79b0000 {
+ qpic_nand: nand-controller@79b0000 {
compatible = "qcom,ipq6018-nand";
reg = <0x0 0x079b0000 0x0 0x10000>;
#address-cells = <1>;
@@ -406,7 +406,8 @@
pcie_phy0: phy@84200 {
reg = <0x0 0x84200 0x0 0x16c>, /* Serdes Tx */
<0x0 0x84400 0x0 0x200>, /* Serdes Rx */
- <0x0 0x84800 0x0 0x4f4>; /* PCS: Lane0, COM, PCIE */
+ <0x0 0x84800 0x0 0x1f0>, /* PCS: Lane0, COM, PCIE */
+ <0x0 0x84c00 0x0 0xf4>; /* pcs_misc */
#phy-cells = <0>;
clocks = <&gcc GCC_PCIE0_PIPE_CLK>;
@@ -511,14 +512,6 @@
clock-names = "xo";
};
- timer {
- compatible = "arm,armv8-timer";
- interrupts = <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
- <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
- <GIC_PPI 4 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
- <GIC_PPI 1 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
- };
-
timer@b120000 {
#address-cells = <1>;
#size-cells = <1>;
@@ -770,6 +763,14 @@
};
};
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 4 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 1 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+ };
+
wcss: wcss-smp2p {
compatible = "qcom,smp2p";
qcom,smem = <435>, <428>;
diff --git a/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts b/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts
index 7143c936de61..ca3f96646b90 100644
--- a/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts
+++ b/arch/arm64/boot/dts/qcom/ipq8074-hk01.dts
@@ -1,8 +1,11 @@
// SPDX-License-Identifier: GPL-2.0-only
/dts-v1/;
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
*/
#include "ipq8074.dtsi"
+#include "pmp8074.dtsi"
+#include <dt-bindings/gpio/gpio.h>
/ {
model = "Qualcomm Technologies, Inc. IPQ8074-HK01";
@@ -51,12 +54,12 @@
&pcie0 {
status = "okay";
- perst-gpios = <&tlmm 61 0x1>;
+ perst-gpios = <&tlmm 61 GPIO_ACTIVE_LOW>;
};
&pcie1 {
status = "okay";
- perst-gpios = <&tlmm 58 0x1>;
+ perst-gpios = <&tlmm 58 GPIO_ACTIVE_LOW>;
};
&pcie_phy0 {
@@ -84,6 +87,7 @@
&sdhc_1 {
status = "okay";
+ vqmmc-supply = <&l11>;
};
&qusb_phy_0 {
diff --git a/arch/arm64/boot/dts/qcom/ipq8074-hk10-c1.dts b/arch/arm64/boot/dts/qcom/ipq8074-hk10-c1.dts
index 2bfcf42aeabc..cc1992ca0519 100644
--- a/arch/arm64/boot/dts/qcom/ipq8074-hk10-c1.dts
+++ b/arch/arm64/boot/dts/qcom/ipq8074-hk10-c1.dts
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2020 The Linux Foundation. All rights reserved.
+/*
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
*/
/dts-v1/;
diff --git a/arch/arm64/boot/dts/qcom/ipq8074-hk10-c2.dts b/arch/arm64/boot/dts/qcom/ipq8074-hk10-c2.dts
index 7da39f1d979b..d7f0efda6b8e 100644
--- a/arch/arm64/boot/dts/qcom/ipq8074-hk10-c2.dts
+++ b/arch/arm64/boot/dts/qcom/ipq8074-hk10-c2.dts
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/dts-v1/;
-/* Copyright (c) 2020 The Linux Foundation. All rights reserved.
+/*
+ * Copyright (c) 2020 The Linux Foundation. All rights reserved.
*/
#include "ipq8074-hk10.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/ipq8074-hk10.dtsi b/arch/arm64/boot/dts/qcom/ipq8074-hk10.dtsi
index db4b87944cdf..651a231554e0 100644
--- a/arch/arm64/boot/dts/qcom/ipq8074-hk10.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq8074-hk10.dtsi
@@ -5,6 +5,7 @@
/dts-v1/;
#include "ipq8074.dtsi"
+#include <dt-bindings/gpio/gpio.h>
/ {
aliases {
@@ -22,7 +23,7 @@
};
&blsp1_spi1 {
- status = "ok";
+ status = "okay";
flash@0 {
#address-cells = <1>;
@@ -34,33 +35,33 @@
};
&blsp1_uart5 {
- status = "ok";
+ status = "okay";
};
&pcie0 {
- status = "ok";
- perst-gpios = <&tlmm 58 0x1>;
+ status = "okay";
+ perst-gpios = <&tlmm 58 GPIO_ACTIVE_LOW>;
};
&pcie1 {
- status = "ok";
- perst-gpios = <&tlmm 61 0x1>;
+ status = "okay";
+ perst-gpios = <&tlmm 61 GPIO_ACTIVE_LOW>;
};
&pcie_phy0 {
- status = "ok";
+ status = "okay";
};
&pcie_phy1 {
- status = "ok";
+ status = "okay";
};
&qpic_bam {
- status = "ok";
+ status = "okay";
};
&qpic_nand {
- status = "ok";
+ status = "okay";
nand@0 {
reg = <0>;
diff --git a/arch/arm64/boot/dts/qcom/ipq8074.dtsi b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
index a721cdd80489..4e51d8e3df04 100644
--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
@@ -129,10 +129,10 @@
status = "disabled";
usb1_ssphy: phy@58200 {
- reg = <0x00058200 0x130>, /* Tx */
+ reg = <0x00058200 0x130>, /* Tx */
<0x00058400 0x200>, /* Rx */
- <0x00058800 0x1f8>, /* PCS */
- <0x00058600 0x044>; /* PCS misc*/
+ <0x00058800 0x1f8>, /* PCS */
+ <0x00058600 0x044>; /* PCS misc */
#phy-cells = <0>;
#clock-cells = <0>;
clocks = <&gcc GCC_USB1_PIPE_CLK>;
@@ -172,10 +172,10 @@
status = "disabled";
usb0_ssphy: phy@78200 {
- reg = <0x00078200 0x130>, /* Tx */
+ reg = <0x00078200 0x130>, /* Tx */
<0x00078400 0x200>, /* Rx */
- <0x00078800 0x1f8>, /* PCS */
- <0x00078600 0x044>; /* PCS misc*/
+ <0x00078800 0x1f8>, /* PCS */
+ <0x00078600 0x044>; /* PCS misc */
#phy-cells = <0>;
#clock-cells = <0>;
clocks = <&gcc GCC_USB0_PIPE_CLK>;
@@ -273,6 +273,16 @@
status = "disabled";
};
+ tsens: thermal-sensor@4a9000 {
+ compatible = "qcom,ipq8074-tsens";
+ reg = <0x4a9000 0x1000>, /* TM */
+ <0x4a8000 0x1000>; /* SROT */
+ interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "combined";
+ #qcom,sensors = <16>;
+ #thermal-sensor-cells = <1>;
+ };
+
cryptobam: dma-controller@704000 {
compatible = "qcom,bam-v1.7.0";
reg = <0x00704000 0x20000>;
@@ -307,35 +317,35 @@
interrupt-controller;
#interrupt-cells = <0x2>;
- serial_4_pins: serial4-pinmux {
+ serial_4_pins: serial4-state {
pins = "gpio23", "gpio24";
function = "blsp4_uart1";
drive-strength = <8>;
bias-disable;
};
- i2c_0_pins: i2c-0-pinmux {
+ i2c_0_pins: i2c-0-state {
pins = "gpio42", "gpio43";
function = "blsp1_i2c";
drive-strength = <8>;
bias-disable;
};
- spi_0_pins: spi-0-pins {
+ spi_0_pins: spi-0-state {
pins = "gpio38", "gpio39", "gpio40", "gpio41";
function = "blsp0_spi";
drive-strength = <8>;
bias-disable;
};
- hsuart_pins: hsuart-pins {
+ hsuart_pins: hsuart-state {
pins = "gpio46", "gpio47", "gpio48", "gpio49";
function = "blsp2_uart";
drive-strength = <8>;
bias-disable;
};
- qpic_pins: qpic-pins {
+ qpic_pins: qpic-state {
pins = "gpio1", "gpio3", "gpio4",
"gpio5", "gpio6", "gpio7",
"gpio8", "gpio10", "gpio11",
@@ -350,9 +360,11 @@
gcc: gcc@1800000 {
compatible = "qcom,gcc-ipq8074";
reg = <0x01800000 0x80000>;
- #clock-cells = <0x1>;
+ clocks = <&xo>, <&sleep_clk>;
+ clock-names = "xo", "sleep_clk";
+ #clock-cells = <1>;
#power-domain-cells = <1>;
- #reset-cells = <0x1>;
+ #reset-cells = <1>;
};
tcsr_mutex: hwlock@1905000 {
@@ -669,11 +681,21 @@
apcs_glb: mailbox@b111000 {
compatible = "qcom,ipq8074-apcs-apps-global";
reg = <0x0b111000 0x1000>;
+ clocks = <&a53pll>, <&xo>;
+ clock-names = "pll", "xo";
#clock-cells = <1>;
#mbox-cells = <1>;
};
+ a53pll: clock@b116000 {
+ compatible = "qcom,ipq8074-a53pll";
+ reg = <0x0b116000 0x40>;
+ #clock-cells = <0>;
+ clocks = <&xo>;
+ clock-names = "xo";
+ };
+
timer@b120000 {
#address-cells = <1>;
#size-cells = <1>;
@@ -865,4 +887,90 @@
<GIC_PPI 4 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 1 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
};
+
+ thermal-zones {
+ nss-top-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 4>;
+ };
+
+ nss0-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 5>;
+ };
+
+ nss1-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 6>;
+ };
+
+ wcss-phya0-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 7>;
+ };
+
+ wcss-phya1-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 8>;
+ };
+
+ cpu0_thermal: cpu0-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 9>;
+ };
+
+ cpu1_thermal: cpu1-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 10>;
+ };
+
+ cpu2_thermal: cpu2-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 11>;
+ };
+
+ cpu3_thermal: cpu3-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 12>;
+ };
+
+ cluster_thermal: cluster-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 13>;
+ };
+
+ wcss-phyb0-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 14>;
+ };
+
+ wcss-phyb1-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 15>;
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts b/arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts
index 3dc9619fde6e..701a5585d77e 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-alcatel-idol347.dts
@@ -5,6 +5,7 @@
#include "msm8916-pm8916.dtsi"
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
/ {
model = "Alcatel OneTouch Idol 3 (4.7)";
@@ -34,6 +35,19 @@
};
};
+ gpio-leds {
+ compatible = "gpio-leds";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_leds_default>;
+
+ led-0 {
+ gpios = <&msmgpio 32 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "torch";
+ function = LED_FUNCTION_TORCH;
+ };
+ };
+
usb_id: usb-id {
compatible = "linux,extcon-usb-gpio";
id-gpio = <&msmgpio 69 GPIO_ACTIVE_HIGH>;
@@ -116,6 +130,27 @@
};
};
+&blsp_i2c6 {
+ status = "okay";
+
+ led-controller@68 {
+ compatible = "si-en,sn3190";
+ reg = <0x68>;
+ shutdown-gpios = <&msmgpio 89 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_enable_default &led_shutdown_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ led@1 {
+ reg = <1>;
+ led-max-microamp = <5000>;
+ function = LED_FUNCTION_INDICATOR;
+ color = <LED_COLOR_ID_WHITE>;
+ };
+ };
+};
+
&pm8916_resin {
status = "okay";
linux,code = <KEY_VOLUMEDOWN>;
@@ -260,7 +295,7 @@
};
&msmgpio {
- accel_int_default: accel-int-default {
+ accel_int_default: accel-int-default-state {
pins = "gpio31";
function = "gpio";
@@ -268,7 +303,7 @@
bias-disable;
};
- gpio_keys_default: gpio-keys-default {
+ gpio_keys_default: gpio-keys-default-state {
pins = "gpio107";
function = "gpio";
@@ -276,7 +311,15 @@
bias-pull-up;
};
- gyro_int_default: gyro-int-default {
+ gpio_leds_default: gpio-leds-default-state {
+ pins = "gpio32";
+ function = "gpio";
+
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ gyro_int_default: gyro-int-default-state {
pins = "gpio97", "gpio98";
function = "gpio";
@@ -284,7 +327,30 @@
bias-disable;
};
- mag_reset_default: mag-reset-default {
+ /*
+ * The OEM wired an additional GPIO to be asserted so that
+ * the si-en,sn3190 LED IC works. Since this GPIO is not
+ * part of the IC datasheet nor supported by the driver,
+ * force it asserted here.
+ */
+ led_enable_default: led-enable-default-state {
+ pins = "gpio102";
+ function = "gpio";
+
+ drive-strength = <2>;
+ bias-disable;
+ output-high;
+ };
+
+ led_shutdown_default: led-shutdown-default-state {
+ pins = "gpio89";
+ function = "gpio";
+
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ mag_reset_default: mag-reset-default-state {
pins = "gpio8";
function = "gpio";
@@ -292,7 +358,7 @@
bias-disable;
};
- proximity_int_default: proximity-int-default {
+ proximity_int_default: proximity-int-default-state {
pins = "gpio12";
function = "gpio";
@@ -300,7 +366,7 @@
bias-pull-up;
};
- ts_int_reset_default: ts-int-reset-default {
+ ts_int_reset_default: ts-int-reset-default-state {
pins = "gpio13", "gpio100";
function = "gpio";
@@ -308,7 +374,7 @@
bias-disable;
};
- usb_id_default: usb-id-default {
+ usb_id_default: usb-id-default-state {
pins = "gpio69";
function = "gpio";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-asus-z00l.dts b/arch/arm64/boot/dts/qcom/msm8916-asus-z00l.dts
index dd92070a1211..3618704a5330 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-asus-z00l.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-asus-z00l.dts
@@ -263,7 +263,7 @@
};
&msmgpio {
- gpio_keys_default: gpio-keys-default {
+ gpio_keys_default: gpio-keys-default-state {
pins = "gpio107", "gpio117";
function = "gpio";
@@ -271,7 +271,7 @@
bias-pull-up;
};
- imu_default: imu-default {
+ imu_default: imu-default-state {
pins = "gpio36";
function = "gpio";
@@ -279,7 +279,7 @@
bias-disable;
};
- mag_reset_default: mag-reset-default {
+ mag_reset_default: mag-reset-default-state {
pins = "gpio112";
function = "gpio";
@@ -287,7 +287,7 @@
bias-disable;
};
- sd_vmmc_en_default: sd-vmmc-en-default {
+ sd_vmmc_en_default: sd-vmmc-en-default-state {
pins = "gpio87";
function = "gpio";
@@ -295,14 +295,16 @@
bias-disable;
};
- touchscreen_default: touchscreen-default {
- pins = "gpio13";
- function = "gpio";
+ touchscreen_default: touchscreen-default-state {
+ touch-pins {
+ pins = "gpio13";
+ function = "gpio";
- drive-strength = <2>;
- bias-pull-up;
+ drive-strength = <2>;
+ bias-pull-up;
+ };
- reset {
+ reset-pins {
pins = "gpio12";
function = "gpio";
@@ -311,7 +313,7 @@
};
};
- usb_id_default: usb-id-default {
+ usb_id_default: usb-id-default-state {
pins = "gpio110";
function = "gpio";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-huawei-g7.dts b/arch/arm64/boot/dts/qcom/msm8916-huawei-g7.dts
index 9e470c67274e..8c07eca900d3 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-huawei-g7.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-huawei-g7.dts
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
-// Copyright (C) 2021 Stephan Gerhold
+/*
+ * Copyright (C) 2021 Stephan Gerhold
+ */
/dts-v1/;
@@ -414,7 +416,7 @@
};
&msmgpio {
- accel_irq_default: accel-irq-default {
+ accel_irq_default: accel-irq-default-state {
pins = "gpio115";
function = "gpio";
@@ -422,7 +424,7 @@
bias-disable;
};
- gpio_keys_default: gpio-keys-default {
+ gpio_keys_default: gpio-keys-default-state {
pins = "gpio107";
function = "gpio";
@@ -430,7 +432,7 @@
bias-pull-up;
};
- gpio_leds_default: gpio-leds-default {
+ gpio_leds_default: gpio-leds-default-state {
pins = "gpio8", "gpio9", "gpio10";
function = "gpio";
@@ -438,7 +440,7 @@
bias-disable;
};
- nfc_default: nfc-default {
+ nfc_default: nfc-default-state {
pins = "gpio2", "gpio20", "gpio21";
function = "gpio";
@@ -446,7 +448,7 @@
bias-disable;
};
- mag_reset_default: mag-reset-default {
+ mag_reset_default: mag-reset-default-state {
pins = "gpio36";
function = "gpio";
@@ -454,7 +456,7 @@
bias-disable;
};
- prox_irq_default: prox-irq-default {
+ prox_irq_default: prox-irq-default-state {
pins = "gpio113";
function = "gpio";
@@ -462,7 +464,7 @@
bias-disable;
};
- reg_lcd_en_default: reg-lcd-en-default {
+ reg_lcd_en_default: reg-lcd-en-default-state {
pins = "gpio32", "gpio97";
function = "gpio";
@@ -470,7 +472,7 @@
bias-disable;
};
- sdhc2_cd_default: sdhc2-cd-default {
+ sdhc2_cd_default: sdhc2-cd-default-state {
pins = "gpio56";
function = "gpio";
@@ -478,7 +480,7 @@
bias-disable;
};
- ts_irq_default: ts-irq-default {
+ ts_irq_default: ts-irq-default-state {
pins = "gpio13";
function = "gpio";
@@ -486,7 +488,7 @@
bias-disable;
};
- usb_id_default: usb-id-default {
+ usb_id_default: usb-id-default-state {
pins = "gpio117";
function = "gpio";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts b/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts
index d85e7f7c0835..d1e8cf2f50c0 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8150.dts
@@ -22,7 +22,7 @@
};
reserved-memory {
- // wcnss.mdt is not relocatable, so it must be loaded at 0x8b600000
+ /* wcnss.mdt is not relocatable, so it must be loaded at 0x8b600000 */
/delete-node/ wcnss@89300000;
wcnss_mem: wcnss@8b600000 {
@@ -204,12 +204,12 @@
rmi4-f01@1 {
reg = <0x1>;
- syna,nosleep-mode = <1>; // Allow sleeping
+ syna,nosleep-mode = <1>; /* Allow sleeping */
};
rmi4-f12@12 {
reg = <0x12>;
- syna,sensor-type = <1>; // Touchscreen
+ syna,sensor-type = <1>; /* Touchscreen */
};
};
};
@@ -367,7 +367,7 @@
};
&msmgpio {
- accel_int_default: accel-int-default {
+ accel_int_default: accel-int-default-state {
pins = "gpio116";
function = "gpio";
@@ -375,7 +375,7 @@
bias-disable;
};
- camera_flash_default: camera-flash-default {
+ camera_flash_default: camera-flash-default-state {
pins = "gpio31", "gpio32";
function = "gpio";
@@ -383,7 +383,7 @@
bias-disable;
};
- ctp_pwr_en_default: ctp-pwr-en-default {
+ ctp_pwr_en_default: ctp-pwr-en-default-state {
pins = "gpio17";
function = "gpio";
@@ -391,7 +391,7 @@
bias-disable;
};
- gpio_keys_default: gpio-keys-default {
+ gpio_keys_default: gpio-keys-default-state {
pins = "gpio107";
function = "gpio";
@@ -399,7 +399,7 @@
bias-pull-up;
};
- gyro_int_default: gyro-int-default {
+ gyro_int_default: gyro-int-default-state {
pins = "gpio22", "gpio23";
function = "gpio";
@@ -407,7 +407,7 @@
bias-disable;
};
- light_int_default: light-int-default {
+ light_int_default: light-int-default-state {
pins = "gpio115";
function = "gpio";
@@ -415,7 +415,7 @@
bias-disable;
};
- magn_int_default: magn-int-default {
+ magn_int_default: magn-int-default-state {
pins = "gpio113";
function = "gpio";
@@ -423,7 +423,7 @@
bias-disable;
};
- tp_int_default: tp-int-default {
+ tp_int_default: tp-int-default-state {
pins = "gpio13";
function = "gpio";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8910.dts b/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8910.dts
index b4812f093b17..3899e11b9843 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8910.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-longcheer-l8910.dts
@@ -234,7 +234,7 @@
};
&msmgpio {
- button_backlight_default: button-backlight-default {
+ button_backlight_default: button-backlight-default-state {
pins = "gpio17";
function = "gpio";
@@ -242,7 +242,7 @@
bias-disable;
};
- gpio_keys_default: gpio-keys-default {
+ gpio_keys_default: gpio-keys-default-state {
pins = "gpio107";
function = "gpio";
@@ -250,7 +250,7 @@
bias-pull-up;
};
- mag_reset_default: mag-reset-default {
+ mag_reset_default: mag-reset-default-state {
pins = "gpio111";
function = "gpio";
@@ -258,7 +258,7 @@
bias-disable;
};
- usb_id_default: usb-id-default {
+ usb_id_default: usb-id-default-state {
pins = "gpio110";
function = "gpio";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi b/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi
index 7dedb91b9930..33dfcf318a81 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi
@@ -5,8 +5,8 @@
&msmgpio {
- blsp1_uart1_default: blsp1-uart1-default {
- // TX, RX, CTS_N, RTS_N
+ blsp1_uart1_default: blsp1-uart1-default-state {
+ /* TX, RX, CTS_N, RTS_N */
pins = "gpio0", "gpio1", "gpio2", "gpio3";
function = "blsp_uart1";
@@ -14,7 +14,7 @@
bias-disable;
};
- blsp1_uart1_sleep: blsp1-uart1-sleep {
+ blsp1_uart1_sleep: blsp1-uart1-sleep-state {
pins = "gpio0", "gpio1", "gpio2", "gpio3";
function = "gpio";
@@ -22,7 +22,7 @@
bias-pull-down;
};
- blsp1_uart2_default: blsp1-uart2-default {
+ blsp1_uart2_default: blsp1-uart2-default-state {
pins = "gpio4", "gpio5";
function = "blsp_uart2";
@@ -30,7 +30,7 @@
bias-disable;
};
- blsp1_uart2_sleep: blsp1-uart2-sleep {
+ blsp1_uart2_sleep: blsp1-uart2-sleep-state {
pins = "gpio4", "gpio5";
function = "gpio";
@@ -38,14 +38,15 @@
bias-pull-down;
};
- spi1_default: spi1-default {
- pins = "gpio0", "gpio1", "gpio3";
- function = "blsp_spi1";
+ spi1_default: spi1-default-state {
+ spi-pins {
+ pins = "gpio0", "gpio1", "gpio3";
+ function = "blsp_spi1";
- drive-strength = <12>;
- bias-disable;
-
- cs {
+ drive-strength = <12>;
+ bias-disable;
+ };
+ cs-pins {
pins = "gpio2";
function = "gpio";
@@ -55,7 +56,7 @@
};
};
- spi1_sleep: spi1-sleep {
+ spi1_sleep: spi1-sleep-state {
pins = "gpio0", "gpio1", "gpio2", "gpio3";
function = "gpio";
@@ -63,14 +64,15 @@
bias-pull-down;
};
- spi2_default: spi2-default {
- pins = "gpio4", "gpio5", "gpio7";
- function = "blsp_spi2";
+ spi2_default: spi2-default-state {
+ spi-pins {
+ pins = "gpio4", "gpio5", "gpio7";
+ function = "blsp_spi2";
- drive-strength = <12>;
- bias-disable;
-
- cs {
+ drive-strength = <12>;
+ bias-disable;
+ };
+ cs-pins {
pins = "gpio6";
function = "gpio";
@@ -80,7 +82,7 @@
};
};
- spi2_sleep: spi2-sleep {
+ spi2_sleep: spi2-sleep-state {
pins = "gpio4", "gpio5", "gpio6", "gpio7";
function = "gpio";
@@ -88,14 +90,15 @@
bias-pull-down;
};
- spi3_default: spi3-default {
- pins = "gpio8", "gpio9", "gpio11";
- function = "blsp_spi3";
+ spi3_default: spi3-default-state {
+ spi-pins {
+ pins = "gpio8", "gpio9", "gpio11";
+ function = "blsp_spi3";
- drive-strength = <12>;
- bias-disable;
-
- cs {
+ drive-strength = <12>;
+ bias-disable;
+ };
+ cs-pins {
pins = "gpio10";
function = "gpio";
@@ -105,7 +108,7 @@
};
};
- spi3_sleep: spi3-sleep {
+ spi3_sleep: spi3-sleep-state {
pins = "gpio8", "gpio9", "gpio10", "gpio11";
function = "gpio";
@@ -113,14 +116,15 @@
bias-pull-down;
};
- spi4_default: spi4-default {
- pins = "gpio12", "gpio13", "gpio15";
- function = "blsp_spi4";
-
- drive-strength = <12>;
- bias-disable;
+ spi4_default: spi4-default-state {
+ spi-pins {
+ pins = "gpio12", "gpio13", "gpio15";
+ function = "blsp_spi4";
- cs {
+ drive-strength = <12>;
+ bias-disable;
+ };
+ cs-pins {
pins = "gpio14";
function = "gpio";
@@ -130,7 +134,7 @@
};
};
- spi4_sleep: spi4-sleep {
+ spi4_sleep: spi4-sleep-state {
pins = "gpio12", "gpio13", "gpio14", "gpio15";
function = "gpio";
@@ -138,14 +142,15 @@
bias-pull-down;
};
- spi5_default: spi5-default {
- pins = "gpio16", "gpio17", "gpio19";
- function = "blsp_spi5";
+ spi5_default: spi5-default-state {
+ spi-pins {
+ pins = "gpio16", "gpio17", "gpio19";
+ function = "blsp_spi5";
- drive-strength = <12>;
- bias-disable;
-
- cs {
+ drive-strength = <12>;
+ bias-disable;
+ };
+ cs-pins {
pins = "gpio18";
function = "gpio";
@@ -155,7 +160,7 @@
};
};
- spi5_sleep: spi5-sleep {
+ spi5_sleep: spi5-sleep-state {
pins = "gpio16", "gpio17", "gpio18", "gpio19";
function = "gpio";
@@ -163,14 +168,15 @@
bias-pull-down;
};
- spi6_default: spi6-default {
- pins = "gpio20", "gpio21", "gpio23";
- function = "blsp_spi6";
-
- drive-strength = <12>;
- bias-disable;
+ spi6_default: spi6-default-state {
+ spi-pins {
+ pins = "gpio20", "gpio21", "gpio23";
+ function = "blsp_spi6";
- cs {
+ drive-strength = <12>;
+ bias-disable;
+ };
+ cs-pins {
pins = "gpio22";
function = "gpio";
@@ -180,7 +186,7 @@
};
};
- spi6_sleep: spi6-sleep {
+ spi6_sleep: spi6-sleep-state {
pins = "gpio20", "gpio21", "gpio22", "gpio23";
function = "gpio";
@@ -188,7 +194,7 @@
bias-pull-down;
};
- i2c1_default: i2c1-default {
+ i2c1_default: i2c1-default-state {
pins = "gpio2", "gpio3";
function = "blsp_i2c1";
@@ -196,7 +202,7 @@
bias-disable;
};
- i2c1_sleep: i2c1-sleep {
+ i2c1_sleep: i2c1-sleep-state {
pins = "gpio2", "gpio3";
function = "gpio";
@@ -204,7 +210,7 @@
bias-disable;
};
- i2c2_default: i2c2-default {
+ i2c2_default: i2c2-default-state {
pins = "gpio6", "gpio7";
function = "blsp_i2c2";
@@ -212,7 +218,7 @@
bias-disable;
};
- i2c2_sleep: i2c2-sleep {
+ i2c2_sleep: i2c2-sleep-state {
pins = "gpio6", "gpio7";
function = "gpio";
@@ -220,7 +226,7 @@
bias-disable;
};
- i2c3_default: i2c3-default {
+ i2c3_default: i2c3-default-state {
pins = "gpio10", "gpio11";
function = "blsp_i2c3";
@@ -228,7 +234,7 @@
bias-disable;
};
- i2c3_sleep: i2c3-sleep {
+ i2c3_sleep: i2c3-sleep-state {
pins = "gpio10", "gpio11";
function = "gpio";
@@ -236,7 +242,7 @@
bias-disable;
};
- i2c4_default: i2c4-default {
+ i2c4_default: i2c4-default-state {
pins = "gpio14", "gpio15";
function = "blsp_i2c4";
@@ -244,7 +250,7 @@
bias-disable;
};
- i2c4_sleep: i2c4-sleep {
+ i2c4_sleep: i2c4-sleep-state {
pins = "gpio14", "gpio15";
function = "gpio";
@@ -252,7 +258,7 @@
bias-disable;
};
- i2c5_default: i2c5-default {
+ i2c5_default: i2c5-default-state {
pins = "gpio18", "gpio19";
function = "blsp_i2c5";
@@ -260,7 +266,7 @@
bias-disable;
};
- i2c5_sleep: i2c5-sleep {
+ i2c5_sleep: i2c5-sleep-state {
pins = "gpio18", "gpio19";
function = "gpio";
@@ -268,7 +274,7 @@
bias-disable;
};
- i2c6_default: i2c6-default {
+ i2c6_default: i2c6-default-state {
pins = "gpio22", "gpio23";
function = "blsp_i2c6";
@@ -276,7 +282,7 @@
bias-disable;
};
- i2c6_sleep: i2c6-sleep {
+ i2c6_sleep: i2c6-sleep-state {
pins = "gpio22", "gpio23";
function = "gpio";
@@ -284,14 +290,14 @@
bias-disable;
};
- pmx-sdc1-clk {
- sdc1_clk_on: clk-on {
+ pmx-sdc1-clk-state {
+ sdc1_clk_on: clk-on-pins {
pins = "sdc1_clk";
bias-disable;
drive-strength = <16>;
};
- sdc1_clk_off: clk-off {
+ sdc1_clk_off: clk-off-pins {
pins = "sdc1_clk";
bias-disable;
@@ -299,14 +305,14 @@
};
};
- pmx-sdc1-cmd {
- sdc1_cmd_on: cmd-on {
+ pmx-sdc1-cmd-state {
+ sdc1_cmd_on: cmd-on-pins {
pins = "sdc1_cmd";
bias-pull-up;
drive-strength = <10>;
};
- sdc1_cmd_off: cmd-off {
+ sdc1_cmd_off: cmd-off-pins {
pins = "sdc1_cmd";
bias-pull-up;
@@ -314,14 +320,14 @@
};
};
- pmx-sdc1-data {
- sdc1_data_on: data-on {
+ pmx-sdc1-data-state {
+ sdc1_data_on: data-on-pins {
pins = "sdc1_data";
bias-pull-up;
drive-strength = <10>;
};
- sdc1_data_off: data-off {
+ sdc1_data_off: data-off-pins {
pins = "sdc1_data";
bias-pull-up;
@@ -329,14 +335,14 @@
};
};
- pmx-sdc2-clk {
- sdc2_clk_on: clk-on {
+ pmx-sdc2-clk-state {
+ sdc2_clk_on: clk-on-pins {
pins = "sdc2_clk";
bias-disable;
drive-strength = <16>;
};
- sdc2_clk_off: clk-off {
+ sdc2_clk_off: clk-off-pins {
pins = "sdc2_clk";
bias-disable;
@@ -344,14 +350,14 @@
};
};
- pmx-sdc2-cmd {
- sdc2_cmd_on: cmd-on {
+ pmx-sdc2-cmd-state {
+ sdc2_cmd_on: cmd-on-pins {
pins = "sdc2_cmd";
bias-pull-up;
drive-strength = <10>;
};
- sdc2_cmd_off: cmd-off {
+ sdc2_cmd_off: cmd-off-pins {
pins = "sdc2_cmd";
bias-pull-up;
@@ -359,14 +365,14 @@
};
};
- pmx-sdc2-data {
- sdc2_data_on: data-on {
+ pmx-sdc2-data-state {
+ sdc2_data_on: data-on-pins {
pins = "sdc2_data";
bias-pull-up;
drive-strength = <10>;
};
- sdc2_data_off: data-off {
+ sdc2_data_off: data-off-pins {
pins = "sdc2_data";
bias-pull-up;
@@ -374,15 +380,15 @@
};
};
- pmx-sdc2-cd-pin {
- sdc2_cd_on: cd-on {
+ pmx-sdc2-cd-pin-state {
+ sdc2_cd_on: cd-on-pins {
pins = "gpio38";
function = "gpio";
drive-strength = <2>;
bias-pull-up;
};
- sdc2_cd_off: cd-off {
+ sdc2_cd_off: cd-off-pins {
pins = "gpio38";
function = "gpio";
@@ -391,8 +397,8 @@
};
};
- cdc-pdm-lines {
- cdc_pdm_lines_act: pdm-lines-on {
+ cdc-pdm-lines-state {
+ cdc_pdm_lines_act: pdm-lines-on-pins {
pins = "gpio63", "gpio64", "gpio65", "gpio66",
"gpio67", "gpio68";
function = "cdc_pdm0";
@@ -400,7 +406,7 @@
drive-strength = <8>;
bias-disable;
};
- cdc_pdm_lines_sus: pdm-lines-off {
+ cdc_pdm_lines_sus: pdm-lines-off-pins {
pins = "gpio63", "gpio64", "gpio65", "gpio66",
"gpio67", "gpio68";
function = "cdc_pdm0";
@@ -410,15 +416,15 @@
};
};
- ext-pri-tlmm-lines {
- ext_pri_tlmm_lines_act: ext-pa-on {
+ ext-pri-tlmm-lines-state {
+ ext_pri_tlmm_lines_act: ext-pa-on-pins {
pins = "gpio113", "gpio114", "gpio115", "gpio116";
function = "pri_mi2s";
drive-strength = <8>;
bias-disable;
};
- ext_pri_tlmm_lines_sus: ext-pa-off {
+ ext_pri_tlmm_lines_sus: ext-pa-off-pins {
pins = "gpio113", "gpio114", "gpio115", "gpio116";
function = "pri_mi2s";
@@ -427,15 +433,15 @@
};
};
- ext-pri-ws-line {
- ext_pri_ws_act: ext-pa-on {
+ ext-pri-ws-line-state {
+ ext_pri_ws_act: ext-pa-on-pins {
pins = "gpio110";
function = "pri_mi2s_ws";
drive-strength = <8>;
bias-disable;
};
- ext_pri_ws_sus: ext-pa-off {
+ ext_pri_ws_sus: ext-pa-off-pins {
pins = "gpio110";
function = "pri_mi2s_ws";
@@ -444,15 +450,15 @@
};
};
- ext-mclk-tlmm-lines {
- ext_mclk_tlmm_lines_act: mclk-lines-on {
+ ext-mclk-tlmm-lines-state {
+ ext_mclk_tlmm_lines_act: mclk-lines-on-pins {
pins = "gpio116";
function = "pri_mi2s";
drive-strength = <8>;
bias-disable;
};
- ext_mclk_tlmm_lines_sus: mclk-lines-off {
+ ext_mclk_tlmm_lines_sus: mclk-lines-off-pins {
pins = "gpio116";
function = "pri_mi2s";
@@ -462,15 +468,15 @@
};
/* secondary Mi2S */
- ext-sec-tlmm-lines {
- ext_sec_tlmm_lines_act: tlmm-lines-on {
+ ext-sec-tlmm-lines-state {
+ ext_sec_tlmm_lines_act: tlmm-lines-on-pins {
pins = "gpio112", "gpio117", "gpio118", "gpio119";
function = "sec_mi2s";
drive-strength = <8>;
bias-disable;
};
- ext_sec_tlmm_lines_sus: tlmm-lines-off {
+ ext_sec_tlmm_lines_sus: tlmm-lines-off-pins {
pins = "gpio112", "gpio117", "gpio118", "gpio119";
function = "sec_mi2s";
@@ -479,40 +485,38 @@
};
};
- cdc-dmic-lines {
- cdc_dmic_lines_act: dmic-lines-on {
- clk {
- pins = "gpio0";
- function = "dmic0_clk";
+ cdc_dmic_lines_act: cdc-dmic-lines-on-state {
+ clk-pins {
+ pins = "gpio0";
+ function = "dmic0_clk";
- drive-strength = <8>;
- };
- data {
- pins = "gpio1";
- function = "dmic0_data";
+ drive-strength = <8>;
+ };
+ data-pins {
+ pins = "gpio1";
+ function = "dmic0_data";
- drive-strength = <8>;
- };
+ drive-strength = <8>;
};
- cdc_dmic_lines_sus: dmic-lines-off {
- clk {
- pins = "gpio0";
- function = "dmic0_clk";
+ };
+ cdc_dmic_lines_sus: cdc-dmic-lines-off-state {
+ clk-pins {
+ pins = "gpio0";
+ function = "dmic0_clk";
- drive-strength = <2>;
- bias-disable;
- };
- data {
- pins = "gpio1";
- function = "dmic0_data";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ data-pins {
+ pins = "gpio1";
+ function = "dmic0_data";
- drive-strength = <2>;
- bias-disable;
- };
+ drive-strength = <2>;
+ bias-disable;
};
};
- wcnss_pin_a: wcnss-active {
+ wcnss_pin_a: wcnss-active-state {
pins = "gpio40", "gpio41", "gpio42", "gpio43", "gpio44";
function = "wcss_wlan";
@@ -520,7 +524,7 @@
bias-pull-up;
};
- cci0_default: cci0-default {
+ cci0_default: cci0-default-state {
pins = "gpio29", "gpio30";
function = "cci_i2c";
@@ -528,22 +532,22 @@
bias-disable;
};
- camera_front_default: camera-front-default {
- pwdn {
+ camera_front_default: camera-front-default-state {
+ pwdn-pins {
pins = "gpio33";
function = "gpio";
drive-strength = <16>;
bias-disable;
};
- rst {
+ rst-pins {
pins = "gpio28";
function = "gpio";
drive-strength = <16>;
bias-disable;
};
- mclk1 {
+ mclk1-pins {
pins = "gpio27";
function = "cam_mclk1";
@@ -552,22 +556,22 @@
};
};
- camera_rear_default: camera-rear-default {
- pwdn {
+ camera_rear_default: camera-rear-default-state {
+ pwdn-pins {
pins = "gpio34";
function = "gpio";
drive-strength = <16>;
bias-disable;
};
- rst {
+ rst-pins {
pins = "gpio35";
function = "gpio";
drive-strength = <16>;
bias-disable;
};
- mclk0 {
+ mclk0-pins {
pins = "gpio26";
function = "cam_mclk0";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-pm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916-pm8916.dtsi
index 539823b2c36e..8cac23b5240c 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-pm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916-pm8916.dtsi
@@ -47,7 +47,7 @@
};
&rpm_requests {
- smd_rpm_regulators: pm8916-regulators {
+ smd_rpm_regulators: regulators {
compatible = "qcom,rpm-pm8916-regulators";
/* pm8916_s1 is managed by rpmpd (MSM8916_VDDCX) */
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi
index 3255bd3fcb55..d600916a0e55 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a2015-common.dtsi
@@ -23,6 +23,17 @@
};
};
+ clk_pwm: pwm {
+ compatible = "clk-pwm";
+ #pwm-cells = <2>;
+
+ clocks = <&gcc GCC_GP2_CLK>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&motor_pwm_default>;
+ status = "disabled";
+ };
+
gpio-keys {
compatible = "gpio-keys";
@@ -61,6 +72,24 @@
};
};
+ /*
+ * NOTE: A5 connects GPIO 76 to a reglator powering the motor
+ * driver IC but A3 connects the same signal to an ENABLE pin of
+ * the driver.
+ */
+ reg_motor_vdd: regulator-motor-vdd {
+ compatible = "regulator-fixed";
+ regulator-name = "motor_vdd";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+
+ gpio = <&msmgpio 76 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&motor_en_default>;
+ };
+
reg_vdd_tsp_a: regulator-vdd-tsp-a {
compatible = "regulator-fixed";
regulator-name = "vdd_tsp_a";
@@ -144,7 +173,7 @@
interrupt-parent = <&msmgpio>;
interrupts = <21 IRQ_TYPE_EDGE_RISING>;
- en-gpios = <&msmgpio 20 GPIO_ACTIVE_HIGH>;
+ en-gpios = <&msmgpio 20 GPIO_ACTIVE_LOW>;
wake-gpios = <&msmgpio 49 GPIO_ACTIVE_HIGH>;
clocks = <&rpmcc RPM_SMD_BB_CLK2_PIN>;
@@ -153,6 +182,16 @@
pinctrl-0 = <&nfc_default &nfc_clk_req>;
};
};
+
+ vibrator: vibrator {
+ compatible = "pwm-vibrator";
+
+ pwms = <&clk_pwm 0 100000>;
+ pwm-names = "enable";
+
+ vcc-supply = <&reg_motor_vdd>;
+ status = "disabled";
+ };
};
&blsp_i2c2 {
@@ -348,7 +387,7 @@
};
&msmgpio {
- accel_int_default: accel-int-default {
+ accel_int_default: accel-int-default-state {
pins = "gpio115";
function = "gpio";
@@ -356,7 +395,7 @@
bias-disable;
};
- fg_alert_default: fg-alert-default {
+ fg_alert_default: fg-alert-default-state {
pins = "gpio121";
function = "gpio";
@@ -364,7 +403,7 @@
bias-disable;
};
- gpio_keys_default: gpio-keys-default {
+ gpio_keys_default: gpio-keys-default-state {
pins = "gpio107", "gpio109";
function = "gpio";
@@ -372,7 +411,7 @@
bias-pull-up;
};
- gpio_hall_sensor_default: gpio-hall-sensor-default {
+ gpio_hall_sensor_default: gpio-hall-sensor-default-state {
pins = "gpio52";
function = "gpio";
@@ -380,47 +419,60 @@
bias-disable;
};
- mdss {
- mdss_default: mdss-default {
- pins = "gpio25";
- function = "gpio";
+ mdss_default: mdss-default-state {
+ pins = "gpio25";
+ function = "gpio";
- drive-strength = <8>;
- bias-disable;
- };
- mdss_sleep: mdss-sleep {
- pins = "gpio25";
- function = "gpio";
+ drive-strength = <8>;
+ bias-disable;
+ };
+ mdss_sleep: mdss-sleep-state {
+ pins = "gpio25";
+ function = "gpio";
- drive-strength = <2>;
- bias-pull-down;
- };
+ drive-strength = <2>;
+ bias-pull-down;
};
- muic_i2c_default: muic-i2c-default {
- pins = "gpio105", "gpio106";
+ motor_en_default: motor-en-default-stae {
+ pins = "gpio76";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- muic_int_default: muic-int-default {
- pins = "gpio12";
+ motor_pwm_default: motor-pwm-default-state {
+ pins = "gpio50";
+ function = "gcc_gp2_clk_a";
+ };
+
+ muic_i2c_default: muic-i2c-default-state {
+ pins = "gpio105", "gpio106";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- nfc_default: nfc-default {
- pins = "gpio20", "gpio49";
+ muic_int_default: muic-int-default-state {
+ pins = "gpio12";
function = "gpio";
drive-strength = <2>;
bias-disable;
+ };
+
+ nfc_default: nfc-default-state {
+ nfc-pins {
+ pins = "gpio20", "gpio49";
+ function = "gpio";
+
+ drive-strength = <2>;
+ bias-disable;
+ };
- irq {
+ irq-pins {
pins = "gpio21";
function = "gpio";
@@ -429,7 +481,7 @@
};
};
- nfc_i2c_default: nfc-i2c-default {
+ nfc_i2c_default: nfc-i2c-default-state {
pins = "gpio0", "gpio1";
function = "gpio";
@@ -437,7 +489,7 @@
bias-disable;
};
- tkey_default: tkey-default {
+ tkey_default: tkey-default-state {
pins = "gpio98";
function = "gpio";
@@ -445,7 +497,7 @@
bias-disable;
};
- tkey_i2c_default: tkey-i2c-default {
+ tkey_i2c_default: tkey-i2c-default-state {
pins = "gpio16", "gpio17";
function = "gpio";
@@ -453,7 +505,7 @@
bias-disable;
};
- tsp_en_default: tsp-en-default {
+ tsp_en_default: tsp-en-default-state {
pins = "gpio73";
function = "gpio";
@@ -461,7 +513,7 @@
bias-disable;
};
- ts_int_default: ts-int-default {
+ ts_int_default: ts-int-default-state {
pins = "gpio13";
function = "gpio";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts
index 6db5f78ca286..c691cca2eb45 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a3u-eur.dts
@@ -81,6 +81,10 @@
};
};
+&clk_pwm {
+ status = "okay";
+};
+
&dsi0 {
panel@0 {
reg = <0>;
@@ -104,8 +108,12 @@
remote-endpoint = <&panel_in>;
};
+&vibrator {
+ status = "okay";
+};
+
&msmgpio {
- panel_vdd3_default: panel-vdd3-default {
+ panel_vdd3_default: panel-vdd3-default-state {
pins = "gpio9";
function = "gpio";
@@ -113,7 +121,7 @@
bias-disable;
};
- tkey_en_default: tkey-en-default {
+ tkey_en_default: tkey-en-default-state {
pins = "gpio86";
function = "gpio";
@@ -121,7 +129,7 @@
bias-disable;
};
- tkey_led_en_default: tkey-led-en-default {
+ tkey_led_en_default: tkey-led-en-default-state {
pins = "gpio60";
function = "gpio";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts
index 5fb8ecd0c9ca..3dd819458785 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-a5u-eur.dts
@@ -50,6 +50,10 @@
};
};
+&clk_pwm {
+ status = "okay";
+};
+
&pronto {
iris {
compatible = "qcom,wcn3660b";
@@ -61,8 +65,12 @@
vdd-supply = <&reg_touch_key>;
};
+&vibrator {
+ status = "okay";
+};
+
&msmgpio {
- tkey_en_default: tkey-en-default {
+ tkey_en_default: tkey-en-default-state {
pins = "gpio97";
function = "gpio";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-e2015-common.dtsi b/arch/arm64/boot/dts/qcom/msm8916-samsung-e2015-common.dtsi
index 542010fdfb8a..c95f0b4bc61f 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-e2015-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-e2015-common.dtsi
@@ -26,19 +26,6 @@
};
};
- reg_motor_vdd: regulator-motor-vdd {
- compatible = "regulator-fixed";
- regulator-name = "motor_vdd";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
-
- gpio = <&msmgpio 76 GPIO_ACTIVE_HIGH>;
- enable-active-high;
-
- pinctrl-names = "default";
- pinctrl-0 = <&motor_en_default>;
- };
-
reg_touch_key: regulator-touch-key {
compatible = "regulator-fixed";
regulator-name = "touch_key";
@@ -61,21 +48,18 @@
/delete-node/ magnetometer@12;
};
+&reg_motor_vdd {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+};
+
&touchkey {
vcc-supply = <&reg_touch_key>;
vdd-supply = <&reg_touch_key>;
};
&msmgpio {
- motor_en_default: motor-en-default {
- pins = "gpio76";
- function = "gpio";
-
- drive-strength = <2>;
- bias-disable;
- };
-
- tkey_en_default: tkey-en-default {
+ tkey_en_default: tkey-en-default-state {
pins = "gpio97";
function = "gpio";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-grandmax.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-grandmax.dts
index bc7134698978..a3d572d851ef 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-grandmax.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-grandmax.dts
@@ -46,7 +46,7 @@
};
&msmgpio {
- gpio_leds_default: gpio-led-default {
+ gpio_leds_default: gpio-led-default-state {
pins = "gpio60";
function = "gpio";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-j5.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-j5.dts
index eabeed18cfaa..7ac49a021563 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-j5.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-j5.dts
@@ -199,7 +199,7 @@
};
&msmgpio {
- gpio_keys_default: gpio-keys-default {
+ gpio_keys_default: gpio-keys-default-state {
pins = "gpio107", "gpio109";
function = "gpio";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-samsung-serranove.dts b/arch/arm64/boot/dts/qcom/msm8916-samsung-serranove.dts
index bbd6bb3f4fd7..d4984b3af802 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-samsung-serranove.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-samsung-serranove.dts
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
-// Copyright (C) 2019 Stephan Gerhold
+/*
+ * Copyright (C) 2019 Stephan Gerhold
+ */
/dts-v1/;
@@ -422,7 +424,7 @@
};
&msmgpio {
- fg_alert_default: fg-alert-default {
+ fg_alert_default: fg-alert-default-state {
pins = "gpio121";
function = "gpio";
@@ -430,7 +432,7 @@
bias-disable;
};
- gpio_keys_default: gpio-keys-default {
+ gpio_keys_default: gpio-keys-default-state {
pins = "gpio107", "gpio109";
function = "gpio";
@@ -438,7 +440,7 @@
bias-pull-up;
};
- gpio_hall_sensor_default: gpio-hall-sensor-default {
+ gpio_hall_sensor_default: gpio-hall-sensor-default-state {
pins = "gpio52";
function = "gpio";
@@ -446,7 +448,7 @@
bias-disable;
};
- imu_irq_default: imu-irq-default {
+ imu_irq_default: imu-irq-default-state {
pins = "gpio115";
function = "gpio";
@@ -454,7 +456,7 @@
bias-disable;
};
- muic_i2c_default: muic-i2c-default {
+ muic_i2c_default: muic-i2c-default-state {
pins = "gpio105", "gpio106";
function = "gpio";
@@ -462,7 +464,7 @@
bias-disable;
};
- muic_irq_default: muic-irq-default {
+ muic_irq_default: muic-irq-default-state {
pins = "gpio12";
function = "gpio";
@@ -470,14 +472,15 @@
bias-disable;
};
- nfc_default: nfc-default {
- pins = "gpio20", "gpio49";
- function = "gpio";
-
- drive-strength = <2>;
- bias-disable;
+ nfc_default: nfc-default-state {
+ nfc-pins {
+ pins = "gpio20", "gpio49";
+ function = "gpio";
- irq {
+ drive-strength = <2>;
+ bias-disable;
+ };
+ irq-pins {
pins = "gpio21";
function = "gpio";
@@ -486,7 +489,7 @@
};
};
- nfc_i2c_default: nfc-i2c-default {
+ nfc_i2c_default: nfc-i2c-default-state {
pins = "gpio0", "gpio1";
function = "gpio";
@@ -494,7 +497,7 @@
bias-disable;
};
- tkey_default: tkey-default {
+ tkey_default: tkey-default-state {
pins = "gpio98";
function = "gpio";
@@ -502,7 +505,7 @@
bias-disable;
};
- tkey_en_default: tkey-en-default {
+ tkey_en_default: tkey-en-default-state {
pins = "gpio86";
function = "gpio";
@@ -510,7 +513,7 @@
bias-disable;
};
- tkey_i2c_default: tkey-i2c-default {
+ tkey_i2c_default: tkey-i2c-default-state {
pins = "gpio16", "gpio17";
function = "gpio";
@@ -518,7 +521,7 @@
bias-disable;
};
- tkey_led_en_default: tkey-led-en-default {
+ tkey_led_en_default: tkey-led-en-default-state {
pins = "gpio60";
function = "gpio";
@@ -526,7 +529,7 @@
bias-disable;
};
- tsp_en_default: tsp-en-default {
+ tsp_en_default: tsp-en-default-state {
pins = "gpio73";
function = "gpio";
@@ -534,7 +537,7 @@
bias-disable;
};
- tsp_irq_default: tsp-irq-default {
+ tsp_irq_default: tsp-irq-default-state {
pins = "gpio13";
function = "gpio";
diff --git a/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dts b/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dts
index 84a352dcf9a2..a87be1d95b14 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dts
+++ b/arch/arm64/boot/dts/qcom/msm8916-wingtech-wt88047.dts
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
-// Copyright (C) 2020 Stephan Gerhold
+/*
+ * Copyright (C) 2020 Stephan Gerhold
+ */
/dts-v1/;
@@ -21,6 +23,20 @@
stdout-path = "serial0";
};
+ flash-led-controller {
+ compatible = "ocs,ocp8110";
+ enable-gpios = <&msmgpio 31 GPIO_ACTIVE_HIGH>;
+ flash-gpios = <&msmgpio 32 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&camera_flash_default>;
+
+ flash_led: led {
+ function = LED_FUNCTION_FLASH;
+ color = <LED_COLOR_ID_WHITE>;
+ };
+ };
+
gpio-keys {
compatible = "gpio-keys";
@@ -272,7 +288,15 @@
};
&msmgpio {
- gpio_keys_default: gpio-keys-default {
+ camera_flash_default: camera-flash-default-state {
+ pins = "gpio31", "gpio32";
+ function = "gpio";
+
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ gpio_keys_default: gpio-keys-default-state {
pins = "gpio107";
function = "gpio";
@@ -280,7 +304,7 @@
bias-pull-up;
};
- imu_default: imu-default {
+ imu_default: imu-default-state {
pins = "gpio115";
function = "gpio";
@@ -288,14 +312,15 @@
bias-disable;
};
- touchscreen_default: touchscreen-default {
- pins = "gpio13";
- function = "gpio";
-
- drive-strength = <2>;
- bias-pull-up;
+ touchscreen_default: touchscreen-default-state {
+ touchscreen-pins {
+ pins = "gpio13";
+ function = "gpio";
- reset {
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ reset-pins {
pins = "gpio12";
function = "gpio";
@@ -304,7 +329,7 @@
};
};
- usb_id_default: usb-id-default {
+ usb_id_default: usb-id-default-state {
pins = "gpio110";
function = "gpio";
diff --git a/arch/arm64/boot/dts/qcom/msm8916.dtsi b/arch/arm64/boot/dts/qcom/msm8916.dtsi
index a831064700ee..2ca8e977fc2a 100644
--- a/arch/arm64/boot/dts/qcom/msm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916.dtsi
@@ -1046,7 +1046,6 @@
"pixel",
"core";
phys = <&dsi_phy0>;
- phy-names = "dsi-phy";
#address-cells = <1>;
#size-cells = <0>;
@@ -1070,7 +1069,7 @@
};
};
- dsi_phy0: dsi-phy@1a98300 {
+ dsi_phy0: phy@1a98300 {
compatible = "qcom,dsi-phy-28nm-lp";
reg = <0x01a98300 0xd4>,
<0x01a98500 0x280>,
@@ -1264,21 +1263,21 @@
clock-names = "iface", "bus";
qcom,iommu-secure-id = <17>;
- // vfe:
+ /* VFE */
iommu-ctx@3000 {
compatible = "qcom,msm-iommu-v1-sec";
reg = <0x3000 0x1000>;
interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
};
- // mdp_0:
+ /* MDP_0 */
iommu-ctx@4000 {
compatible = "qcom,msm-iommu-v1-ns";
reg = <0x4000 0x1000>;
interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>;
};
- // venus_ns:
+ /* VENUS_NS */
iommu-ctx@5000 {
compatible = "qcom,msm-iommu-v1-sec";
reg = <0x5000 0x1000>;
@@ -1297,14 +1296,14 @@
clock-names = "iface", "bus";
qcom,iommu-secure-id = <18>;
- // gfx3d_user:
+ /* GFX3D_USER */
iommu-ctx@1000 {
compatible = "qcom,msm-iommu-v1-ns";
reg = <0x1000 0x1000>;
interrupts = <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>;
};
- // gfx3d_priv:
+ /* GFX3D_PRIV */
iommu-ctx@2000 {
compatible = "qcom,msm-iommu-v1-ns";
reg = <0x2000 0x1000>;
@@ -1345,7 +1344,7 @@
};
mpss: remoteproc@4080000 {
- compatible = "qcom,msm8916-mss-pil", "qcom,q6v5-pil";
+ compatible = "qcom,msm8916-mss-pil";
reg = <0x04080000 0x100>,
<0x04020000 0x040>;
@@ -1438,7 +1437,7 @@
lpass: audio-controller@7708000 {
status = "disabled";
- compatible = "qcom,lpass-cpu-apq8016";
+ compatible = "qcom,apq8016-lpass-cpu";
/*
* Note: Unlike the name would suggest, the SEC_I2S_CLK
diff --git a/arch/arm64/boot/dts/qcom/msm8953.dtsi b/arch/arm64/boot/dts/qcom/msm8953.dtsi
index 6b992a6d56c1..32349174c4bd 100644
--- a/arch/arm64/boot/dts/qcom/msm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953.dtsi
@@ -460,229 +460,229 @@
interrupt-controller;
#interrupt-cells = <2>;
- uart_console_active: uart-console-active-pins {
+ uart_console_active: uart-console-active-state {
pins = "gpio4", "gpio5";
function = "blsp_uart2";
drive-strength = <2>;
bias-disable;
};
- uart_console_sleep: uart-console-sleep-pins {
+ uart_console_sleep: uart-console-sleep-state {
pins = "gpio4", "gpio5";
function = "blsp_uart2";
drive-strength = <2>;
bias-pull-down;
};
- sdc1_clk_on: sdc1-clk-on-pins {
+ sdc1_clk_on: sdc1-clk-on-state {
pins = "sdc1_clk";
bias-disable;
drive-strength = <16>;
};
- sdc1_clk_off: sdc1-clk-off-pins {
+ sdc1_clk_off: sdc1-clk-off-state {
pins = "sdc1_clk";
bias-disable;
drive-strength = <2>;
};
- sdc1_cmd_on: sdc1-cmd-on-pins {
+ sdc1_cmd_on: sdc1-cmd-on-state {
pins = "sdc1_cmd";
bias-disable;
drive-strength = <10>;
};
- sdc1_cmd_off: sdc1-cmd-off-pins {
+ sdc1_cmd_off: sdc1-cmd-off-state {
pins = "sdc1_cmd";
bias-disable;
drive-strength = <2>;
};
- sdc1_data_on: sdc1-data-on-pins {
+ sdc1_data_on: sdc1-data-on-state {
pins = "sdc1_data";
bias-pull-up;
drive-strength = <10>;
};
- sdc1_data_off: sdc1-data-off-pins {
+ sdc1_data_off: sdc1-data-off-state {
pins = "sdc1_data";
bias-pull-up;
drive-strength = <2>;
};
- sdc1_rclk_on: sdc1-rclk-on-pins {
+ sdc1_rclk_on: sdc1-rclk-on-state {
pins = "sdc1_rclk";
bias-pull-down;
};
- sdc1_rclk_off: sdc1-rclk-off-pins {
+ sdc1_rclk_off: sdc1-rclk-off-state {
pins = "sdc1_rclk";
bias-pull-down;
};
- sdc2_clk_on: sdc2-clk-on-pins {
+ sdc2_clk_on: sdc2-clk-on-state {
pins = "sdc2_clk";
drive-strength = <16>;
bias-disable;
};
- sdc2_clk_off: sdc2-clk-off-pins {
+ sdc2_clk_off: sdc2-clk-off-state {
pins = "sdc2_clk";
bias-disable;
drive-strength = <2>;
};
- sdc2_cmd_on: sdc2-cmd-on-pins {
+ sdc2_cmd_on: sdc2-cmd-on-state {
pins = "sdc2_cmd";
bias-pull-up;
drive-strength = <10>;
};
- sdc2_cmd_off: sdc2-cmd-off-pins {
+ sdc2_cmd_off: sdc2-cmd-off-state {
pins = "sdc2_cmd";
bias-pull-up;
drive-strength = <2>;
};
- sdc2_data_on: sdc2-data-on-pins {
+ sdc2_data_on: sdc2-data-on-state {
pins = "sdc2_data";
bias-pull-up;
drive-strength = <10>;
};
- sdc2_data_off: sdc2-data-off-pins {
+ sdc2_data_off: sdc2-data-off-state {
pins = "sdc2_data";
bias-pull-up;
drive-strength = <2>;
};
- sdc2_cd_on: cd-on-pins {
+ sdc2_cd_on: cd-on-state {
pins = "gpio133";
function = "gpio";
drive-strength = <2>;
bias-pull-up;
};
- sdc2_cd_off: cd-off-pins {
+ sdc2_cd_off: cd-off-state {
pins = "gpio133";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- gpio_key_default: gpio-key-default-pins {
+ gpio_key_default: gpio-key-default-state {
pins = "gpio85";
function = "gpio";
drive-strength = <2>;
bias-pull-up;
};
- i2c_1_default: i2c-1-default-pins {
+ i2c_1_default: i2c-1-default-state {
pins = "gpio2", "gpio3";
function = "blsp_i2c1";
drive-strength = <2>;
bias-disable;
};
- i2c_1_sleep: i2c-1-sleep-pins {
+ i2c_1_sleep: i2c-1-sleep-state {
pins = "gpio2", "gpio3";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- i2c_2_default: i2c-2-default-pins {
+ i2c_2_default: i2c-2-default-state {
pins = "gpio6", "gpio7";
function = "blsp_i2c2";
drive-strength = <2>;
bias-disable;
};
- i2c_2_sleep: i2c-2-sleep-pins {
+ i2c_2_sleep: i2c-2-sleep-state {
pins = "gpio6", "gpio7";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- i2c_3_default: i2c-3-default-pins {
+ i2c_3_default: i2c-3-default-state {
pins = "gpio10", "gpio11";
function = "blsp_i2c3";
drive-strength = <2>;
bias-disable;
};
- i2c_3_sleep: i2c-3-sleep-pins {
+ i2c_3_sleep: i2c-3-sleep-state {
pins = "gpio10", "gpio11";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- i2c_4_default: i2c-4-default-pins {
+ i2c_4_default: i2c-4-default-state {
pins = "gpio14", "gpio15";
function = "blsp_i2c4";
drive-strength = <2>;
bias-disable;
};
- i2c_4_sleep: i2c-4-sleep-pins {
+ i2c_4_sleep: i2c-4-sleep-state {
pins = "gpio14", "gpio15";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- i2c_5_default: i2c-5-default-pins {
+ i2c_5_default: i2c-5-default-state {
pins = "gpio18", "gpio19";
function = "blsp_i2c5";
drive-strength = <2>;
bias-disable;
};
- i2c_5_sleep: i2c-5-sleep-pins {
+ i2c_5_sleep: i2c-5-sleep-state {
pins = "gpio18", "gpio19";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- i2c_6_default: i2c-6-default-pins {
+ i2c_6_default: i2c-6-default-state {
pins = "gpio22", "gpio23";
function = "blsp_i2c6";
drive-strength = <2>;
bias-disable;
};
- i2c_6_sleep: i2c-6-sleep-pins {
+ i2c_6_sleep: i2c-6-sleep-state {
pins = "gpio22", "gpio23";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- i2c_7_default: i2c-7-default-pins {
+ i2c_7_default: i2c-7-default-state {
pins = "gpio135", "gpio136";
function = "blsp_i2c7";
drive-strength = <2>;
bias-disable;
};
- i2c_7_sleep: i2c-7-sleep-pins {
+ i2c_7_sleep: i2c-7-sleep-state {
pins = "gpio135", "gpio136";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- i2c_8_default: i2c-8-default-pins {
+ i2c_8_default: i2c-8-default-state {
pins = "gpio98", "gpio99";
function = "blsp_i2c8";
drive-strength = <2>;
bias-disable;
};
- i2c_8_sleep: i2c-8-sleep-pins {
+ i2c_8_sleep: i2c-8-sleep-state {
pins = "gpio98", "gpio99";
function = "gpio";
drive-strength = <2>;
@@ -726,6 +726,250 @@
reg = <0x193f044 0x4>;
};
+ mdss: mdss@1a00000 {
+ compatible = "qcom,mdss";
+
+ reg = <0x1a00000 0x1000>,
+ <0x1ab0000 0x1040>;
+ reg-names = "mdss_phys",
+ "vbif_phys";
+
+ power-domains = <&gcc MDSS_GDSC>;
+ interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ clocks = <&gcc GCC_MDSS_AHB_CLK>,
+ <&gcc GCC_MDSS_AXI_CLK>,
+ <&gcc GCC_MDSS_VSYNC_CLK>,
+ <&gcc GCC_MDSS_MDP_CLK>;
+ clock-names = "iface",
+ "bus",
+ "vsync",
+ "core";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ status = "disabled";
+
+ mdp: mdp@1a01000 {
+ compatible = "qcom,msm8953-mdp5", "qcom,mdp5";
+ reg = <0x1a01000 0x89000>;
+ reg-names = "mdp_phys";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+
+ power-domains = <&gcc MDSS_GDSC>;
+
+ clocks = <&gcc GCC_MDSS_AHB_CLK>,
+ <&gcc GCC_MDSS_AXI_CLK>,
+ <&gcc GCC_MDSS_MDP_CLK>,
+ <&gcc GCC_MDSS_VSYNC_CLK>;
+ clock-names = "iface",
+ "bus",
+ "core",
+ "vsync";
+
+ iommus = <&apps_iommu 0x15>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ mdp5_intf1_out: endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ mdp5_intf2_out: endpoint {
+ remote-endpoint = <&dsi1_in>;
+ };
+ };
+ };
+ };
+
+ dsi0: dsi@1a94000 {
+ compatible = "qcom,mdss-dsi-ctrl";
+ reg = <0x1a94000 0x400>;
+ reg-names = "dsi_ctrl";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <4>;
+
+ assigned-clocks = <&gcc BYTE0_CLK_SRC>,
+ <&gcc PCLK0_CLK_SRC>;
+ assigned-clock-parents = <&dsi0_phy 0>,
+ <&dsi0_phy 1>;
+
+ clocks = <&gcc GCC_MDSS_MDP_CLK>,
+ <&gcc GCC_MDSS_AHB_CLK>,
+ <&gcc GCC_MDSS_AXI_CLK>,
+ <&gcc GCC_MDSS_BYTE0_CLK>,
+ <&gcc GCC_MDSS_PCLK0_CLK>,
+ <&gcc GCC_MDSS_ESC0_CLK>;
+ clock-names = "mdp_core",
+ "iface",
+ "bus",
+ "byte",
+ "pixel",
+ "core";
+
+ phys = <&dsi0_phy>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dsi0_in: endpoint {
+ remote-endpoint = <&mdp5_intf1_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dsi0_out: endpoint {
+ };
+ };
+ };
+ };
+
+ dsi0_phy: phy@1a94400 {
+ compatible = "qcom,dsi-phy-14nm-8953";
+ reg = <0x1a94400 0x100>,
+ <0x1a94500 0x300>,
+ <0x1a94800 0x188>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ clocks = <&gcc GCC_MDSS_AHB_CLK>, <&xo_board>;
+ clock-names = "iface", "ref";
+
+ status = "disabled";
+ };
+
+ dsi1: dsi@1a96000 {
+ compatible = "qcom,mdss-dsi-ctrl";
+ reg = <0x1a96000 0x400>;
+ reg-names = "dsi_ctrl";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <5>;
+
+ assigned-clocks = <&gcc BYTE1_CLK_SRC>,
+ <&gcc PCLK1_CLK_SRC>;
+ assigned-clock-parents = <&dsi1_phy 0>,
+ <&dsi1_phy 1>;
+
+ clocks = <&gcc GCC_MDSS_MDP_CLK>,
+ <&gcc GCC_MDSS_AHB_CLK>,
+ <&gcc GCC_MDSS_AXI_CLK>,
+ <&gcc GCC_MDSS_BYTE1_CLK>,
+ <&gcc GCC_MDSS_PCLK1_CLK>,
+ <&gcc GCC_MDSS_ESC1_CLK>;
+ clock-names = "mdp_core",
+ "iface",
+ "bus",
+ "byte",
+ "pixel",
+ "core";
+
+ phys = <&dsi1_phy>;
+
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dsi1_in: endpoint {
+ remote-endpoint = <&mdp5_intf2_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dsi1_out: endpoint {
+ };
+ };
+ };
+ };
+
+ dsi1_phy: phy@1a96400 {
+ compatible = "qcom,dsi-phy-14nm-8953";
+ reg = <0x1a96400 0x100>,
+ <0x1a96500 0x300>,
+ <0x1a96800 0x188>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ clocks = <&gcc GCC_MDSS_AHB_CLK>, <&xo_board>;
+ clock-names = "iface", "ref";
+
+ status = "disabled";
+ };
+ };
+
+ apps_iommu: iommu@1e00000 {
+ compatible = "qcom,msm8953-iommu", "qcom,msm-iommu-v1";
+ ranges = <0 0x1e20000 0x20000>;
+
+ clocks = <&gcc GCC_SMMU_CFG_CLK>,
+ <&gcc GCC_APSS_TCU_ASYNC_CLK>;
+ clock-names = "iface", "bus";
+
+ qcom,iommu-secure-id = <17>;
+
+ #address-cells = <1>;
+ #iommu-cells = <1>;
+ #size-cells = <1>;
+
+ /* VFE */
+ iommu-ctx@14000 {
+ compatible = "qcom,msm-iommu-v1-ns";
+ reg = <0x14000 0x1000>;
+ interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ /* MDP_0 */
+ iommu-ctx@15000 {
+ compatible = "qcom,msm-iommu-v1-ns";
+ reg = <0x15000 0x1000>;
+ interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ /* VENUS_NS */
+ iommu-ctx@16000 {
+ compatible = "qcom,msm-iommu-v1-ns";
+ reg = <0x16000 0x1000>;
+ interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
spmi_bus: spmi@200f000 {
compatible = "qcom,spmi-pmic-arb";
reg = <0x200f000 0x1000>,
diff --git a/arch/arm64/boot/dts/qcom/msm8956-sony-xperia-loire-kugo.dts b/arch/arm64/boot/dts/qcom/msm8956-sony-xperia-loire-kugo.dts
new file mode 100644
index 000000000000..3fb8e23e4330
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8956-sony-xperia-loire-kugo.dts
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2016-2022, AngeloGioacchino Del Regno
+ * <angelogioacchino.delregno@somainline.org>
+ * Copyright (c) 2022, Konrad Dybcio <konrad.dybcio@somainline.org>
+ * Copyright (c) 2022, Marijn Suijten <marijn.suijten@somainline.org>
+ */
+
+/dts-v1/;
+
+#include "msm8956-sony-xperia-loire.dtsi"
+
+/ {
+ model = "Sony Xperia X Compact";
+ compatible = "sony,kugo-row", "qcom,msm8956";
+ chassis-type = "handset";
+};
+
+&blsp2_i2c2 {
+ status = "okay";
+
+ /* FUSB301 USB-C Controller */
+};
+
+&blsp2_i2c4 {
+ status = "okay";
+
+ /* ST STMVL53L0 ToF @ 29 */
+ /* AMS TCS349 RGBCIR @ 72 */
+};
+
+&pm8950_l1 {
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1300000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8956-sony-xperia-loire-suzu.dts b/arch/arm64/boot/dts/qcom/msm8956-sony-xperia-loire-suzu.dts
new file mode 100644
index 000000000000..87d657f6806b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8956-sony-xperia-loire-suzu.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2016-2022, AngeloGioacchino Del Regno
+ * <angelogioacchino.delregno@somainline.org>
+ * Copyright (c) 2022, Konrad Dybcio <konrad.dybcio@somainline.org>
+ * Copyright (c) 2022, Marijn Suijten <marijn.suijten@somainline.org>
+ */
+
+/dts-v1/;
+
+#include "msm8956-sony-xperia-loire.dtsi"
+
+/ {
+ model = "Sony Xperia X";
+ compatible = "sony,suzu-row", "qcom,msm8956";
+ chassis-type = "handset";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8956-sony-xperia-loire.dtsi b/arch/arm64/boot/dts/qcom/msm8956-sony-xperia-loire.dtsi
new file mode 100644
index 000000000000..67baced639c9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8956-sony-xperia-loire.dtsi
@@ -0,0 +1,282 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2016-2022, AngeloGioacchino Del Regno
+ * <angelogioacchino.delregno@somainline.org>
+ * Copyright (c) 2022, Konrad Dybcio <konrad.dybcio@somainline.org>
+ * Copyright (c) 2022, Marijn Suijten <marijn.suijten@somainline.org>
+ */
+
+#include "msm8956.dtsi"
+
+#include "pm8004.dtsi"
+#include "pm8950.dtsi"
+#include "pmi8950.dtsi"
+
+/ {
+ qcom,msm-id = <266 0x10001>; /* MSM8956 v1.1 */
+ qcom,board-id = <8 0>;
+
+ aliases {
+ mmc0 = &sdhc_1; /* SDC1 eMMC slot */
+ mmc1 = &sdhc_2; /* SDC2 SD card slot */
+ mmc2 = &sdhc_3; /* SDC3 SDIO card slot */
+ serial0 = &blsp2_uart2;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ reserved-memory {
+ cont-splash@83000000 {
+ reg = <0x0 0x83000000 0x0 0x2800000>;
+ };
+
+ ramoops@57f00000 {
+ compatible = "ramoops";
+ reg = <0 0x57f00000 0 0x100000>;
+ record-size = <0x20000>;
+ console-size = <0x40000>;
+ ftrace-size = <0x20000>;
+ pmsg-size = <0x20000>;
+ ecc-size = <16>;
+ };
+ };
+
+ usbphy_1p2: regulator-usbphy-1p2 {
+ compatible = "regulator-fixed";
+ regulator-name = "usbphy-1p2";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ vin-supply = <&vph_pwr>;
+ };
+
+ vph_pwr: regulator-vph-pwr {
+ compatible = "regulator-fixed";
+ regulator-name = "vph-pwr";
+ regulator-always-on;
+ regulator-boot-on;
+ };
+};
+
+&blsp1_i2c4 {
+ status = "okay";
+
+ /* Synaptics RMI4 @ 2c */
+};
+
+&blsp2_uart2 {
+ status = "okay";
+};
+
+&gcc {
+ vdd_gfx-supply = <&pm8004_s5>;
+};
+
+&otg {
+ status = "okay";
+};
+
+&pm8004_spmi_regulators {
+ vdd_s2-supply = <&vph_pwr>;
+ vdd_s5-supply = <&vph_pwr>;
+
+ /* Cluster 1 supply */
+ pm8004_s2: s2 {
+ /* regulator-min-microvolt = <500000>; */
+ /* Set .95V to prevent unstabilities until CPR for this SoC is done */
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1165000>;
+ regulator-name = "vdd_apc1";
+ /* Set always on until the CPU PLL is done */
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ pm8004_s5: s5 {
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1165000>;
+ regulator-enable-ramp-delay = <500>;
+ regulator-name = "vdd_gfx";
+ /* Hack this on until the gpu driver is ready for it */
+ regulator-always-on;
+ };
+};
+
+&pm8950_spmi_regulators {
+ vdd_s5-supply = <&vph_pwr>;
+
+ /* Cluster 0 supply */
+ pm8950_spmi_s5: s5 {
+ /* Set .95V to prevent unstabilities until CPR for this SoC is done */
+ /* regulator-min-microvolt = <790000>; */
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1165000>;
+ regulator-name = "vdd_apc0";
+ /* Set always on until the CPU PLL is done */
+ regulator-always-on;
+ regulator-boot-on;
+ };
+};
+
+&rpm_requests {
+ pm8950_regulators: regulators {
+ compatible = "qcom,rpm-pm8950-regulators";
+
+ vdd_s1-supply = <&vph_pwr>;
+ vdd_s2-supply = <&vph_pwr>;
+ vdd_s3-supply = <&vph_pwr>;
+ vdd_s4-supply = <&vph_pwr>;
+ vdd_s6-supply = <&vph_pwr>;
+ vdd_l1_l19-supply = <&pm8950_s3>;
+ vdd_l2_l23-supply = <&pm8950_s3>;
+ vdd_l3-supply = <&pm8950_s3>;
+ vdd_l5_l6_l7_l16-supply = <&pm8950_s4>;
+ vdd_l8_l11_l12_l17_l22-supply = <&vph_pwr>;
+
+ pm8950_s1: s1 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1162500>;
+ };
+
+ pm8950_s3: s3 {
+ regulator-min-microvolt = <1325000>;
+ regulator-max-microvolt = <1325000>;
+ regulator-always-on;
+ };
+
+ pm8950_s4: s4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ pm8950_l1: l1 {
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1100000>;
+ };
+
+ pm8950_l2: l2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8950_l3: l3 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pm8950_l5: l5 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-system-load = <290000>;
+ regulator-allow-set-load;
+ };
+
+ pm8950_l6: l6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8950_l7: l7 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8950_l8: l8 {
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <2900000>;
+ regulator-system-load = <130000>;
+ regulator-allow-set-load;
+ };
+
+ pm8950_l9: l9 {
+ regulator-min-microvolt = <2000000>;
+ regulator-max-microvolt = <2400000>;
+ };
+
+ pm8950_l10: l10 {
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2900000>;
+ };
+
+ pm8950_l11: l11 {
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-system-load = <60000>;
+ regulator-allow-set-load;
+ };
+
+ pm8950_l12: l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-system-load = <100000>;
+ regulator-allow-set-load;
+ };
+
+ pm8950_l13: l13 {
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ };
+
+ pm8950_l14: l14 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ pm8950_l15: l15 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ pm8950_l16: l16 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8950_l17: l17 {
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2900000>;
+ };
+
+ pm8950_l22: l22 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ pm8950_l23: l23 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+ };
+};
+
+&sdhc_1 {
+ /* Toshiba THGBMHG8C4LBAU7 (032G34) */
+ bus-width = <8>;
+ non-removable;
+ vmmc-supply = <&pm8950_l8>;
+ vqmmc-supply = <&pm8950_l5>;
+ status = "okay";
+};
+
+&sdhc_2 {
+ bus-width = <4>;
+ cd-gpios = <&tlmm 100 GPIO_ACTIVE_HIGH>;
+ vmmc-supply = <&pm8950_l11>;
+ vqmmc-supply = <&pm8950_l12>;
+ status = "okay";
+};
+
+&tlmm {
+ gpio-reserved-ranges = <0 4>;
+};
+
+&usb_hs_phy {
+ vdd-supply = <&usbphy_1p2>;
+ vdda1p8-supply = <&pm8950_l7>;
+ vdda3p3-supply = <&pm8950_l13>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8956.dtsi b/arch/arm64/boot/dts/qcom/msm8956.dtsi
new file mode 100644
index 000000000000..e432512d8716
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8956.dtsi
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2016-2022, AngeloGioacchino Del Regno
+ * <angelogioacchino.delregno@collabora.com>
+ * Copyright (c) 2022, Konrad Dybcio <konrad.dybcio@somainline.org>
+ * Copyright (c) 2022, Marijn Suijten <marijn.suijten@somainline.org>
+ */
+
+#include "msm8976.dtsi"
+
+&pmu {
+ interrupts = <GIC_PPI 7 (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_HIGH)>;
+};
+
+/*
+ * You might be wondering.. why is it so empty out there?
+ * Well, the SoCs are almost identical.
+ */
diff --git a/arch/arm64/boot/dts/qcom/msm8976.dtsi b/arch/arm64/boot/dts/qcom/msm8976.dtsi
new file mode 100644
index 000000000000..05dcb30b0779
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8976.dtsi
@@ -0,0 +1,1198 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2016-2022, AngeloGioacchino Del Regno
+ * <angelogioacchino.delregno@collabora.com>
+ * Copyright (c) 2022, Konrad Dybcio <konrad.dybcio@somainline.org>
+ * Copyright (c) 2022, Marijn Suijten <marijn.suijten@somainline.org>
+ */
+
+#include <dt-bindings/clock/qcom,gcc-msm8976.h>
+#include <dt-bindings/clock/qcom,rpmcc.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/power/qcom-rpmpd.h>
+
+/ {
+ interrupt-parent = <&intc>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ chosen { };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ CPU0: cpu@0 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x0>;
+ enable-method = "psci";
+ cpu-idle-states = <&little_cpu_sleep_0>;
+ capacity-dmips-mhz = <573>;
+ next-level-cache = <&l2_0>;
+ #cooling-cells = <2>;
+ };
+
+ CPU1: cpu@1 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x1>;
+ enable-method = "psci";
+ cpu-idle-states = <&little_cpu_sleep_0>;
+ capacity-dmips-mhz = <573>;
+ next-level-cache = <&l2_0>;
+ #cooling-cells = <2>;
+ };
+
+ CPU2: cpu@2 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x2>;
+ enable-method = "psci";
+ cpu-idle-states = <&little_cpu_sleep_0>;
+ capacity-dmips-mhz = <573>;
+ next-level-cache = <&l2_0>;
+ #cooling-cells = <2>;
+ };
+
+ CPU3: cpu@3 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a53";
+ reg = <0x3>;
+ enable-method = "psci";
+ cpu-idle-states = <&little_cpu_sleep_0>;
+ capacity-dmips-mhz = <573>;
+ next-level-cache = <&l2_0>;
+ #cooling-cells = <2>;
+ };
+
+ CPU4: cpu@100 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x100>;
+ enable-method = "psci";
+ cpu-idle-states = <&big_cpu_sleep_0 &big_cpu_sleep_1>;
+ capacity-dmips-mhz = <1024>;
+ next-level-cache = <&l2_1>;
+ #cooling-cells = <2>;
+ };
+
+ CPU5: cpu@101 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x101>;
+ enable-method = "psci";
+ cpu-idle-states = <&big_cpu_sleep_0 &big_cpu_sleep_1>;
+ capacity-dmips-mhz = <1024>;
+ next-level-cache = <&l2_1>;
+ #cooling-cells = <2>;
+ };
+
+ CPU6: cpu@102 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x102>;
+ enable-method = "psci";
+ cpu-idle-states = <&big_cpu_sleep_0 &big_cpu_sleep_1>;
+ capacity-dmips-mhz = <1024>;
+ next-level-cache = <&l2_1>;
+ #cooling-cells = <2>;
+ };
+
+ CPU7: cpu@103 {
+ device_type = "cpu";
+ compatible = "arm,cortex-a72";
+ reg = <0x103>;
+ enable-method = "psci";
+ cpu-idle-states = <&big_cpu_sleep_0 &big_cpu_sleep_1>;
+ capacity-dmips-mhz = <1024>;
+ next-level-cache = <&l2_1>;
+ #cooling-cells = <2>;
+ };
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&CPU0>;
+ };
+
+ core1 {
+ cpu = <&CPU1>;
+ };
+
+ core2 {
+ cpu = <&CPU2>;
+ };
+
+ core3 {
+ cpu = <&CPU3>;
+ };
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&CPU4>;
+ };
+
+ core1 {
+ cpu = <&CPU5>;
+ };
+
+ core2 {
+ cpu = <&CPU6>;
+ };
+
+ core3 {
+ cpu = <&CPU7>;
+ };
+ };
+ };
+
+ idle-states {
+ entry-method = "psci";
+
+ little_cpu_sleep_0: cpu-sleep-0-0 {
+ compatible = "arm,idle-state";
+ idle-state-name = "little-power-collapse";
+ arm,psci-suspend-param = <0x40000003>;
+ entry-latency-us = <181>;
+ exit-latency-us = <149>;
+ min-residency-us = <703>;
+ local-timer-stop;
+ };
+
+ big_cpu_sleep_0: cpu-sleep-1-0 {
+ compatible = "arm,idle-state";
+ idle-state-name = "big-retention";
+ arm,psci-suspend-param = <0x00000002>;
+ entry-latency-us = <142>;
+ exit-latency-us = <99>;
+ min-residency-us = <242>;
+ };
+
+ big_cpu_sleep_1: cpu-sleep-1-1 {
+ compatible = "arm,idle-state";
+ idle-state-name = "big-power-collapse";
+ arm,psci-suspend-param = <0x40000003>;
+ entry-latency-us = <158>;
+ exit-latency-us = <144>;
+ min-residency-us = <863>;
+ local-timer-stop;
+ };
+ };
+
+ l2_0: l2-cache0 {
+ compatible = "cache";
+ cache-level = <2>;
+ };
+
+ l2_1: l2-cache1 {
+ compatible = "cache";
+ cache-level = <2>;
+ };
+ };
+
+ firmware {
+ scm: scm {
+ compatible = "qcom,scm-msm8976", "qcom,scm";
+ clocks = <&gcc GCC_CRYPTO_CLK>,
+ <&gcc GCC_CRYPTO_AXI_CLK>,
+ <&gcc GCC_CRYPTO_AHB_CLK>;
+ clock-names = "core", "bus", "iface";
+ #reset-cells = <1>;
+
+ qcom,dload-mode = <&tcsr 0x6100>;
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ /* We expect the bootloader to fill in the size */
+ reg = <0x0 0x80000000 0x0 0x0>;
+ };
+
+ pmu: pmu {
+ compatible = "arm,armv8-pmuv3";
+ interrupts = <GIC_PPI 7 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
+ };
+
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ ext-region@85b00000 {
+ reg = <0x0 0x85b00000 0x0 0x500000>;
+ no-map;
+ };
+
+ smem@86300000 {
+ compatible = "qcom,smem";
+ reg = <0x0 0x86300000 0x0 0x100000>;
+ no-map;
+
+ hwlocks = <&tcsr_mutex 3>;
+ qcom,rpm-msg-ram = <&rpm_msg_ram>;
+ };
+
+ reserved@86400000 {
+ reg = <0x0 0x86400000 0x0 0x800000>;
+ no-map;
+ };
+
+ mpss_mem: mpss@86c00000 {
+ reg = <0x0 0x86c00000 0x0 0x5600000>;
+ no-map;
+ };
+
+ lpass_mem: lpass@8c200000 {
+ reg = <0x0 0x8c200000 0x0 0x1800000>;
+ no-map;
+ };
+
+ venus_mem: memory@8da00000 {
+ reg = <0x0 0x8da00000 0x0 0x2600000>;
+ no-map;
+ };
+
+ tz-apps@8dd00000 {
+ reg = <0x0 0x8dd00000 0x0 0x1400000>;
+ no-map;
+ };
+ };
+
+ smp2p-hexagon {
+ compatible = "qcom,smp2p";
+ interrupts = <GIC_SPI 291 IRQ_TYPE_EDGE_RISING>;
+ qcom,ipc = <&apcs 8 10>;
+
+ qcom,local-pid = <0>;
+ qcom,remote-pid = <2>;
+ qcom,smem = <443>, <429>;
+
+ adsp_smp2p_out: master-kernel {
+ qcom,entry-name = "master-kernel";
+
+ #qcom,smem-state-cells = <1>;
+ };
+
+ adsp_smp2p_in: slave-kernel {
+ qcom,entry-name = "slave-kernel";
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ smp2p-modem {
+ compatible = "qcom,smp2p";
+ interrupts = <GIC_SPI 27 IRQ_TYPE_EDGE_RISING>;
+ qcom,ipc = <&apcs 8 13>;
+
+ qcom,local-pid = <0>;
+ qcom,remote-pid = <1>;
+ qcom,smem = <435>, <428>;
+
+ modem_smp2p_out: master-kernel {
+ qcom,entry-name = "master-kernel";
+
+ #qcom,smem-state-cells = <1>;
+ };
+
+ modem_smp2p_in: slave-kernel {
+ qcom,entry-name = "slave-kernel";
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ smp2p-wcnss {
+ compatible = "qcom,smp2p";
+ interrupts = <GIC_SPI 143 IRQ_TYPE_EDGE_RISING>;
+ qcom,ipc = <&apcs 8 17>;
+
+ qcom,local-pid = <0>;
+ qcom,remote-pid = <4>;
+ qcom,smem = <451>, <431>;
+
+ wcnss_smp2p_out: master-kernel {
+ qcom,entry-name = "master-kernel";
+
+ #qcom,smem-state-cells = <1>;
+ };
+
+ wcnss_smp2p_in: slave-kernel {
+ qcom,entry-name = "slave-kernel";
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ smd {
+ compatible = "qcom,smd";
+
+ rpm {
+ interrupts = <GIC_SPI 168 IRQ_TYPE_EDGE_RISING>;
+ qcom,ipc = <&apcs 8 0>;
+ qcom,smd-edge = <15>;
+
+ rpm_requests: rpm-requests {
+ compatible = "qcom,rpm-msm8976";
+ qcom,smd-channels = "rpm_requests";
+
+ rpmcc: clock-controller {
+ compatible = "qcom,rpmcc-msm8976", "qcom,rpmcc";
+ #clock-cells = <1>;
+ };
+
+ rpmpd: power-controller {
+ compatible = "qcom,msm8976-rpmpd";
+ #power-domain-cells = <1>;
+ operating-points-v2 = <&rpmpd_opp_table>;
+
+ rpmpd_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ rpmpd_opp_ret: opp1 {
+ opp-level = <RPM_SMD_LEVEL_RETENTION>;
+ };
+
+ rpmpd_opp_ret_plus: opp2 {
+ opp-level = <RPM_SMD_LEVEL_RETENTION_PLUS>;
+ };
+
+ rpmpd_opp_min_svs: opp3 {
+ opp-level = <RPM_SMD_LEVEL_MIN_SVS>;
+ };
+
+ rpmpd_opp_low_svs: opp4 {
+ opp-level = <RPM_SMD_LEVEL_LOW_SVS>;
+ };
+
+ rpmpd_opp_svs: opp5 {
+ opp-level = <RPM_SMD_LEVEL_SVS>;
+ };
+
+ rpmpd_opp_svs_plus: opp6 {
+ opp-level = <RPM_SMD_LEVEL_SVS_PLUS>;
+ };
+
+ rpmpd_opp_nom: opp7 {
+ opp-level = <RPM_SMD_LEVEL_NOM>;
+ };
+
+ rpmpd_opp_nom_plus: opp8 {
+ opp-level = <RPM_SMD_LEVEL_NOM_PLUS>;
+ };
+
+ rpmpd_opp_turbo: opp9 {
+ opp-level = <RPM_SMD_LEVEL_TURBO>;
+ };
+
+ rpmpd_opp_turbo_no_cpr: opp10 {
+ opp-level = <RPM_SMD_LEVEL_TURBO_NO_CPR>;
+ };
+
+ rpmpd_opp_turbo_high: opp111 {
+ opp-level = <RPM_SMD_LEVEL_TURBO_HIGH>;
+ };
+ };
+ };
+ };
+ };
+ };
+
+ smsm {
+ compatible = "qcom,smsm";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,ipc-1 = <&apcs 8 12>;
+ qcom,ipc-2 = <&apcs 8 9>;
+ qcom,ipc-3 = <&apcs 8 18>;
+
+ apps_smsm: apps@0 {
+ reg = <0>;
+ #qcom,smem-state-cells = <1>;
+ };
+
+ hexagon_smsm: hexagon@1 {
+ reg = <1>;
+ interrupts = <0 290 IRQ_TYPE_EDGE_RISING>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ wcnss_smsm: wcnss@6 {
+ reg = <6>;
+ interrupts = <GIC_SPI 144 IRQ_TYPE_EDGE_RISING>;
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ soc: soc@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0 0 0xffffffff>;
+ compatible = "simple-bus";
+
+ rng@22000 {
+ compatible = "qcom,prng";
+ reg = <0x00022000 0x140>;
+ clocks = <&gcc GCC_PRNG_AHB_CLK>;
+ clock-names = "core";
+ };
+
+ rpm_msg_ram: sram@60000 {
+ compatible = "qcom,rpm-msg-ram";
+ reg = <0x00060000 0x8000>;
+ };
+
+ usb_hs_phy: phy@6c000 {
+ compatible = "qcom,usb-hs-28nm-femtophy";
+ reg = <0x0006c000 0x200>;
+ #phy-cells = <0>;
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
+ <&gcc GCC_USB_HS_PHY_CFG_AHB_CLK>,
+ <&gcc GCC_USB2A_PHY_SLEEP_CLK>;
+ clock-names = "ref", "ahb", "sleep";
+ resets = <&gcc RST_QUSB2_PHY_BCR>,
+ <&gcc RST_USB2_HS_PHY_ONLY_BCR>;
+ reset-names = "phy", "por";
+ status = "disabled";
+ };
+
+ qfprom: qfprom@a4000 {
+ compatible = "qcom,msm8976-qfprom", "qcom,qfprom";
+ reg = <0x000a4000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ tsens_caldata: caldata@218 {
+ reg = <0x218 0x18>;
+ };
+ };
+
+ tsens: thermal-sensor@4a9000 {
+ compatible = "qcom,msm8976-tsens", "qcom,tsens-v1";
+ reg = <0x004a9000 0x1000>, /* TM */
+ <0x004a8000 0x1000>; /* SROT */
+ interrupts = <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "uplow";
+ nvmem-cells = <&tsens_caldata>;
+ nvmem-cell-names = "calib";
+ #qcom,sensors = <11>;
+ #thermal-sensor-cells = <1>;
+ };
+
+ tlmm: pinctrl@1000000 {
+ compatible = "qcom,msm8976-pinctrl";
+ reg = <0x01000000 0x300000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ gpio-ranges = <&tlmm 0 0 145>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ spi1_default: spi0-default-state {
+ spi-pins {
+ pins = "gpio0", "gpio1", "gpio3";
+ function = "blsp_spi1";
+ drive-strength = <12>;
+ bias-disable;
+ };
+
+ cs-pins {
+ pins = "gpio2";
+ function = "blsp_spi1";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ spi1_sleep: spi0-sleep-state {
+ spi-pins {
+ pins = "gpio0", "gpio1", "gpio3";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ cs-pins {
+ pins = "gpio2";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ blsp1_i2c2_default: blsp1-i2c2-default-state {
+ pins = "gpio6", "gpio7";
+ function = "blsp_i2c2";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ blsp1_i2c2_sleep: blsp1-i2c2-sleep-state {
+ pins = "gpio6", "gpio7";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ blsp1_i2c4_default: blsp1-i2c4-default-state {
+ pins = "gpio14", "gpio15";
+ function = "blsp_i2c4";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ blsp1_i2c4_sleep: blsp1-i2c4-sleep-state {
+ pins = "gpio14", "gpio15";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ blsp2_uart2_active: blsp2-uart2-active-state {
+ pins = "gpio20", "gpio21";
+ function = "blsp_uart6";
+ drive-strength = <4>;
+ bias-disable;
+ };
+
+ blsp2_uart2_sleep: blsp2-uart2-sleep-state {
+ pins = "gpio20", "gpio21";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ /* 4 (not 6!) interfaces per QUP, BLSP2 indexes are numbered (n)+4 */
+ blsp2_i2c2_default: blsp2-i2c2-default-state {
+ pins = "gpio22", "gpio23";
+ function = "blsp_i2c6";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ blsp2_i2c2_sleep: blsp2-i2c2-sleep-state {
+ pins = "gpio22", "gpio23";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ blsp2_i2c4_default: blsp2-i2c4-default-state {
+ pins = "gpio18", "gpio19";
+ function = "blsp_i2c8";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ blsp2_i2c4_sleep: blsp2-i2c4-sleep-state {
+ pins = "gpio18", "gpio19";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ gcc: clock-controller@1800000 {
+ compatible = "qcom,gcc-msm8976";
+ reg = <0x01800000 0x80000>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+
+ assigned-clocks = <&gcc GPLL3>;
+ assigned-clock-rates = <1100000000>;
+
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
+ <&rpmcc RPM_SMD_XO_A_CLK_SRC>,
+ <0>,
+ <0>,
+ <0>,
+ <0>;
+ clock-names = "xo",
+ "xo_a",
+ "dsi0pll",
+ "dsi0pllbyte",
+ "dsi1pll",
+ "dsi1pllbyte";
+ };
+
+ tcsr_mutex: hwlock@1905000 {
+ compatible = "qcom,tcsr-mutex";
+ reg = <0x01905000 0x20000>;
+ #hwlock-cells = <1>;
+ };
+
+ tcsr: syscon@1937000 {
+ compatible = "qcom,msm8976-tcsr", "syscon";
+ reg = <0x01937000 0x30000>;
+ };
+
+ spmi_bus: spmi@200f000 {
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0x0200f000 0x1000>,
+ <0x02400000 0x800000>,
+ <0x02c00000 0x800000>,
+ <0x03800000 0x200000>,
+ <0x0200a000 0x2100>;
+ reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
+ interrupts = <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "periph_irq";
+ qcom,channel = <0>;
+ qcom,ee = <0>;
+
+ #address-cells = <2>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <4>;
+ cell-index = <0>;
+ };
+
+ sdhc_1: mmc@7824000 {
+ compatible = "qcom,msm8976-sdhci", "qcom,sdhci-msm-v4";
+ reg = <0x07824900 0x500>, <0x07824000 0x800>;
+ reg-names = "hc", "core";
+
+ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ clocks = <&gcc GCC_SDCC1_AHB_CLK>,
+ <&gcc GCC_SDCC1_APPS_CLK>,
+ <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "iface", "core", "xo";
+ status = "disabled";
+ };
+
+ sdhc_2: mmc@7864000 {
+ compatible = "qcom,msm8976-sdhci", "qcom,sdhci-msm-v4";
+ reg = <0x07864900 0x11c>, <0x07864000 0x800>;
+ reg-names = "hc", "core";
+
+ interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 221 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ clocks = <&gcc GCC_SDCC2_AHB_CLK>,
+ <&gcc GCC_SDCC2_APPS_CLK>,
+ <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "iface", "core", "xo";
+ status = "disabled";
+ };
+
+ blsp1_dma: dma-controller@7884000 {
+ compatible = "qcom,bam-v1.7.0";
+ reg = <0x07884000 0x1f000>;
+ interrupts = <GIC_SPI 238 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "bam_clk";
+ #dma-cells = <1>;
+ qcom,ee = <0>;
+ };
+
+ blsp1_uart1: serial@78af000 {
+ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+ reg = <0x078af000 0x200>;
+ interrupts = <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_UART1_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "core", "iface";
+ dmas = <&blsp1_dma 0>, <&blsp1_dma 1>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ blsp1_uart2: serial@78b0000 {
+ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+ reg = <0x078b0000 0x200>;
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "core", "iface";
+ dmas = <&blsp1_dma 2>, <&blsp1_dma 3>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ blsp1_spi1: spi@78b5000 {
+ compatible = "qcom,spi-qup-v2.2.1";
+ reg = <0x078b5000 0x500>;
+ interrupts = <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_QUP1_SPI_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "core", "iface";
+ dmas = <&blsp1_dma 4>, <&blsp1_dma 5>;
+ dma-names = "tx", "rx";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&spi1_default>;
+ pinctrl-1 = <&spi1_sleep>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ blsp1_i2c2: i2c@78b6000 {
+ compatible = "qcom,i2c-qup-v2.2.1";
+ reg = <0x078b6000 0x500>;
+ interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "core", "iface";
+ clock-frequency = <400000>;
+ dmas = <&blsp1_dma 6>, <&blsp1_dma 7>;
+ dma-names = "tx", "rx";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&blsp1_i2c2_default>;
+ pinctrl-1 = <&blsp1_i2c2_default>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ blsp1_i2c4: i2c@78b8000 {
+ compatible = "qcom,i2c-qup-v2.2.1";
+ reg = <0x078b8000 0x500>;
+ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_QUP4_I2C_APPS_CLK>, <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "core", "iface";
+ clock-frequency = <400000>;
+ dmas = <&blsp1_dma 10>, <&blsp1_dma 11>;
+ dma-names = "tx", "rx";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&blsp1_i2c4_default>;
+ pinctrl-1 = <&blsp1_i2c4_sleep>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ otg: usb@78db000 {
+ compatible = "qcom,ci-hdrc";
+ reg = <0x078db000 0x200>,
+ <0x078db200 0x200>;
+ interrupts = <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_USB_HS_AHB_CLK>, <&gcc GCC_USB_HS_SYSTEM_CLK>;
+ clock-names = "iface", "core";
+ assigned-clocks = <&gcc GCC_USB_HS_SYSTEM_CLK>;
+ assigned-clock-rates = <80000000>;
+ resets = <&gcc RST_USB_HS_BCR>;
+ reset-names = "core";
+ ahb-burst-config = <0>;
+ dr_mode = "peripheral";
+ phy_type = "ulpi";
+ phy-names = "usb-phy";
+ phys = <&usb_hs_phy>;
+ status = "disabled";
+ #reset-cells = <1>;
+ };
+
+ sdhc_3: mmc@7a24000 {
+ compatible = "qcom,msm8976-sdhci", "qcom,sdhci-msm-v4";
+ reg = <0x07a24900 0x11c>, <0x07a24000 0x800>;
+ reg-names = "hc", "core";
+
+ interrupts = <GIC_SPI 295 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 297 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ clocks = <&gcc GCC_SDCC3_AHB_CLK>,
+ <&gcc GCC_SDCC3_APPS_CLK>,
+ <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "iface", "core", "xo";
+
+ status = "disabled";
+ };
+
+ blsp2_dma: dma-controller@7ac4000 {
+ compatible = "qcom,bam-v1.7.0";
+ reg = <0x07ac4000 0x1f000>;
+ interrupts = <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP2_AHB_CLK>;
+ clock-names = "bam_clk";
+ #dma-cells = <1>;
+ qcom,ee = <0>;
+ };
+
+ blsp2_uart2: serial@7af0000 {
+ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+ reg = <0x07af0000 0x200>;
+ interrupts = <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP2_UART2_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>;
+ clock-names = "core", "iface";
+ dmas = <&blsp2_dma 0>, <&blsp2_dma 1>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ blsp2_i2c2: i2c@7af6000 {
+ compatible = "qcom,i2c-qup-v2.2.1";
+ reg = <0x07af6000 0x600>;
+ interrupts = <GIC_SPI 300 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP2_QUP2_I2C_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>;
+ clock-names = "core", "iface";
+ clock-frequency = <400000>;
+ dmas = <&blsp2_dma 6>, <&blsp2_dma 7>;
+ dma-names = "tx", "rx";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&blsp2_i2c2_default>;
+ pinctrl-1 = <&blsp2_i2c2_sleep>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ blsp2_i2c4: i2c@7af8000 {
+ compatible = "qcom,i2c-qup-v2.2.1";
+ reg = <0x07af8000 0x600>;
+ interrupts = <GIC_SPI 302 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP2_QUP4_I2C_APPS_CLK>, <&gcc GCC_BLSP2_AHB_CLK>;
+ clock-names = "core", "iface";
+ clock-frequency = <400000>;
+ dmas = <&blsp2_dma 10>, <&blsp2_dma 11>;
+ dma-names = "tx", "rx";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&blsp2_i2c4_default>;
+ pinctrl-1 = <&blsp2_i2c4_sleep>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ intc: interrupt-controller@b000000 {
+ compatible = "qcom,msm-qgic2";
+ reg = <0x0b000000 0x1000>, <0x0b002000 0x1000>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ };
+
+ apcs: mailbox@b011000 {
+ compatible = "qcom,msm8976-apcs-kpss-global", "syscon";
+ reg = <0x0b011000 0x1000>;
+ #mbox-cells = <1>;
+ };
+
+ timer@b120000 {
+ compatible = "arm,armv7-timer-mem";
+ reg = <0x0b120000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ clock-frequency = <19200000>;
+
+ frame@b121000 {
+ reg = <0x0b121000 0x1000>, <0x0b122000 0x1000>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ frame-number = <0>;
+ };
+
+ frame@b123000 {
+ reg = <0x0b123000 0x1000>;
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ frame-number = <1>;
+ status = "disabled";
+ };
+
+ frame@b124000 {
+ reg = <0x0b124000 0x1000>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ frame-number = <2>;
+ status = "disabled";
+ };
+
+ frame@b125000 {
+ reg = <0x0b125000 0x1000>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ frame-number = <3>;
+ status = "disabled";
+ };
+
+ frame@b126000 {
+ reg = <0x0b126000 0x1000>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ frame-number = <4>;
+ status = "disabled";
+ };
+
+ frame@b127000 {
+ reg = <0x0b127000 0x1000>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ frame-number = <5>;
+ status = "disabled";
+ };
+
+ frame@b128000 {
+ reg = <0x0b128000 0x1000>;
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ frame-number = <6>;
+ status = "disabled";
+ };
+ };
+
+ imem: sram@8600000 {
+ compatible = "qcom,msm8976-imem", "syscon", "simple-mfd";
+ reg = <0x08600000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ ranges = <0 0x08600000 0x1000>;
+
+ pil-reloc@94c {
+ compatible = "qcom,pil-reloc-info";
+ reg = <0x94c 0xc8>;
+ };
+ };
+ };
+
+ thermal-zones {
+ aoss0-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 0>;
+
+ trips {
+ aoss0_alert0: trip-point0 {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+ };
+ };
+
+ modem-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 1>;
+ trips {
+ modem_alert0: trip-point0 {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+ };
+ };
+
+ qdsp-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 2>;
+ trips {
+ qdsp_alert0: trip-point0 {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+ };
+ };
+
+ cam-isp-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+
+ thermal-sensors = <&tsens 3>;
+ trips {
+ cam_isp_alert0: trip-point0 {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+ };
+ };
+
+ cpu4-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+ thermal-sensors = <&tsens 4>;
+
+ trips {
+ cpu4_alert0: trip-point0 {
+ temperature = <50000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+ cpu4_alert1: trip-point1 {
+ temperature = <55000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu4_crit: cpu-crit {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu5-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+ thermal-sensors = <&tsens 5>;
+
+ trips {
+ cpu5_alert0: trip-point0 {
+ temperature = <50000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+ cpu5_alert1: trip-point1 {
+ temperature = <55000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu5_crit: cpu-crit {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu6-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+ thermal-sensors = <&tsens 6>;
+
+ trips {
+ cpu6_alert0: trip-point0 {
+ temperature = <50000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+ cpu6_alert1: trip-point1 {
+ temperature = <55000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu6_crit: cpu-crit {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu7-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+ thermal-sensors = <&tsens 7>;
+
+ trips {
+ cpu7_alert0: trip-point0 {
+ temperature = <50000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+ cpu7_alert1: trip-point1 {
+ temperature = <55000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu7_crit: cpu-crit {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ big-l2-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+ thermal-sensors = <&tsens 8>;
+
+ trips {
+ l2_alert0: trip-point0 {
+ temperature = <50000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+ l2_alert1: trip-point1 {
+ temperature = <55000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ l2_crit: l2-crit {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ cpu0-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+ thermal-sensors = <&tsens 9>;
+
+ trips {
+ cpu0_alert0: trip-point0 {
+ temperature = <50000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+ cpu0_alert1: trip-point1 {
+ temperature = <55000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu0_crit: cpu-crit {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+
+ gpu-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <1000>;
+ thermal-sensors = <&tsens 10>;
+
+ trips {
+ gpu_alert0: trip-point0 {
+ temperature = <50000>;
+ hysteresis = <2000>;
+ type = "hot";
+ };
+ gpu_alert1: trip-point1 {
+ temperature = <55000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ gpu_crit: gpu-crit {
+ temperature = <75000>;
+ hysteresis = <2000>;
+ type = "critical";
+ };
+ };
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 4 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 1 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
+ clock-frequency = <19200000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8992-lg-bullhead-rev-10.dts b/arch/arm64/boot/dts/qcom/msm8992-lg-bullhead-rev-10.dts
index 7e6bce4af441..4159fc35571a 100644
--- a/arch/arm64/boot/dts/qcom/msm8992-lg-bullhead-rev-10.dts
+++ b/arch/arm64/boot/dts/qcom/msm8992-lg-bullhead-rev-10.dts
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) Jean Thomas <virgule@jeanthomas.me>
+/*
+ * Copyright (c) Jean Thomas <virgule@jeanthomas.me>
*/
/dts-v1/;
diff --git a/arch/arm64/boot/dts/qcom/msm8992-lg-bullhead-rev-101.dts b/arch/arm64/boot/dts/qcom/msm8992-lg-bullhead-rev-101.dts
index e6a5ebd30e2f..ad9702dd171b 100644
--- a/arch/arm64/boot/dts/qcom/msm8992-lg-bullhead-rev-101.dts
+++ b/arch/arm64/boot/dts/qcom/msm8992-lg-bullhead-rev-101.dts
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) Jean Thomas <virgule@jeanthomas.me>
+/*
+ * Copyright (c) Jean Thomas <virgule@jeanthomas.me>
*/
/dts-v1/;
diff --git a/arch/arm64/boot/dts/qcom/msm8992-lg-bullhead.dtsi b/arch/arm64/boot/dts/qcom/msm8992-lg-bullhead.dtsi
index 71e373b11de9..87c90e93667f 100644
--- a/arch/arm64/boot/dts/qcom/msm8992-lg-bullhead.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8992-lg-bullhead.dtsi
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015, LGE Inc. All rights reserved.
+/*
+ * Copyright (c) 2015, LGE Inc. All rights reserved.
* Copyright (c) 2016, The Linux Foundation. All rights reserved.
* Copyright (c) 2021, Petr Vorel <petr.vorel@gmail.com>
*/
@@ -58,7 +59,7 @@
};
&rpm_requests {
- pm8994_regulators: pm8994-regulators {
+ pm8994_regulators: regulators-0 {
compatible = "qcom,rpm-pm8994-regulators";
vdd_l1-supply = <&pm8994_s1>;
@@ -236,9 +237,11 @@
};
pm8994_l26: l26 {
- /* TODO: value from downstream
- regulator-min-microvolt = <987500>;
- fails to apply */
+ /*
+ * TODO: value from downstream
+ * regulator-min-microvolt = <987500>;
+ * fails to apply
+ */
};
pm8994_l27: l27 {
@@ -252,19 +255,19 @@
};
pm8994_l29: l29 {
- /* TODO: Unsupported voltage range.
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
- qcom,init-voltage = <2800000>;
- */
+ /*
+ * TODO: Unsupported voltage range.
+ * regulator-min-microvolt = <2800000>;
+ * regulator-max-microvolt = <2800000>;
+ */
};
pm8994_l30: l30 {
- /* TODO: get this verified
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,init-voltage = <1800000>;
- */
+ /*
+ * TODO: get this verified
+ * regulator-min-microvolt = <1800000>;
+ * regulator-max-microvolt = <1800000>;
+ */
};
pm8994_l31: l31 {
@@ -273,15 +276,15 @@
};
pm8994_l32: l32 {
- /* TODO: get this verified
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- qcom,init-voltage = <1800000>;
- */
+ /*
+ * TODO: get this verified
+ * regulator-min-microvolt = <1800000>;
+ * regulator-max-microvolt = <1800000>;
+ */
};
};
- pmi8994_regulators: pmi8994-regulators {
+ pmi8994_regulators: regulators-1 {
compatible = "qcom,rpm-pmi8994-regulators";
vdd_s1-supply = <&vph_pwr>;
diff --git a/arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts b/arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts
index c4e87d0aec42..b242c272d2af 100644
--- a/arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts
+++ b/arch/arm64/boot/dts/qcom/msm8992-xiaomi-libra.dts
@@ -153,7 +153,7 @@
};
&rpm_requests {
- pm8994-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pm8994-regulators";
vdd_l1-supply = <&pm8994_s7>;
@@ -363,7 +363,7 @@
pm8994_lvs2: lvs2 {};
};
- pmi8994_regulators: pmi8994-regulators {
+ pmi8994_regulators: regulators-1 {
compatible = "qcom,rpm-pmi8994-regulators";
vdd_s1-supply = <&vph_pwr>;
vdd_bst_byp-supply = <&vph_pwr>;
diff --git a/arch/arm64/boot/dts/qcom/msm8992.dtsi b/arch/arm64/boot/dts/qcom/msm8992.dtsi
index 750643763a76..10adb4986ef1 100644
--- a/arch/arm64/boot/dts/qcom/msm8992.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8992.dtsi
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/*
+ * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
*/
#include "msm8994.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/msm8994-huawei-angler-rev-101.dts b/arch/arm64/boot/dts/qcom/msm8994-huawei-angler-rev-101.dts
index dbfbb77e9ff5..85abff0e9b3f 100644
--- a/arch/arm64/boot/dts/qcom/msm8994-huawei-angler-rev-101.dts
+++ b/arch/arm64/boot/dts/qcom/msm8994-huawei-angler-rev-101.dts
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015, Huawei Inc. All rights reserved.
+/*
+ * Copyright (c) 2015, Huawei Inc. All rights reserved.
* Copyright (c) 2016, The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2022, Petr Vorel <petr.vorel@gmail.com>
*/
diff --git a/arch/arm64/boot/dts/qcom/msm8994-msft-lumia-octagon.dtsi b/arch/arm64/boot/dts/qcom/msm8994-msft-lumia-octagon.dtsi
index f9d8bd09e074..9b67f0d3820c 100644
--- a/arch/arm64/boot/dts/qcom/msm8994-msft-lumia-octagon.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8994-msft-lumia-octagon.dtsi
@@ -551,7 +551,7 @@
&rpm_requests {
/* These values were taken from the original firmware ACPI tables */
- pm8994_regulators: pm8994-regulators {
+ pm8994_regulators: regulators-0 {
compatible = "qcom,rpm-pm8994-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -835,7 +835,7 @@
vreg_lvs2a_1p8: lvs2 { };
};
- pmi8994_regulators: pmi8994-regulators {
+ pmi8994_regulators: regulators-1 {
compatible = "qcom,rpm-pmi8994-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -881,28 +881,28 @@
};
&tlmm {
- grip_default: grip-default {
+ grip_default: grip-default-state {
pins = "gpio39";
function = "gpio";
drive-strength = <6>;
bias-pull-down;
};
- grip_sleep: grip-sleep {
+ grip_sleep: grip-sleep-state {
pins = "gpio39";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
- hall_front_default: hall-front-default {
+ hall_front_default: hall-front-default-state {
pins = "gpio42";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- hall_back_default: hall-back-default {
+ hall_back_default: hall-back-default-state {
pins = "gpio75";
function = "gpio";
drive-strength = <2>;
diff --git a/arch/arm64/boot/dts/qcom/msm8994-sony-xperia-kitakami.dtsi b/arch/arm64/boot/dts/qcom/msm8994-sony-xperia-kitakami.dtsi
index ff60b7004d26..f3d153c34918 100644
--- a/arch/arm64/boot/dts/qcom/msm8994-sony-xperia-kitakami.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8994-sony-xperia-kitakami.dtsi
@@ -186,7 +186,7 @@
&rpm_requests {
/* PMI8994 should probe first, because pmi8994_bby supplies some of PM8994's regulators */
- pmi8994_regulators: pmi8994-regulators {
+ pmi8994_regulators: regulators-0 {
compatible = "qcom,rpm-pmi8994-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -205,7 +205,7 @@
};
};
- pm8994_regulators: pm8994-regulators {
+ pm8994_regulators: regulators-1 {
compatible = "qcom,rpm-pm8994-regulators";
vdd_s3-supply = <&vph_pwr>;
@@ -477,15 +477,17 @@
};
&tlmm {
- ts_int_active: ts-int-active {
+ ts_int_active: ts-int-active-state {
pins = "gpio42";
+ function = "gpio";
drive-strength = <2>;
bias-disable;
input-enable;
};
- ts_reset_active: ts-reset-active {
+ ts_reset_active: ts-reset-active-state {
pins = "gpio109";
+ function = "gpio";
drive-strength = <2>;
bias-disable;
output-low;
diff --git a/arch/arm64/boot/dts/qcom/msm8994.dtsi b/arch/arm64/boot/dts/qcom/msm8994.dtsi
index ded5b7ceeaf9..9ff9d35496d2 100644
--- a/arch/arm64/boot/dts/qcom/msm8994.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8994.dtsi
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/*
+ * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
*/
#include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -553,7 +554,6 @@
clocks = <&gcc GCC_BLSP1_QUP1_SPI_APPS_CLK>,
<&gcc GCC_BLSP1_AHB_CLK>;
clock-names = "core", "iface";
- spi-max-frequency = <19200000>;
dmas = <&blsp1_dma 12>, <&blsp1_dma 13>;
dma-names = "tx", "rx";
pinctrl-names = "default", "sleep";
@@ -691,7 +691,6 @@
clocks = <&gcc GCC_BLSP2_QUP4_SPI_APPS_CLK>,
<&gcc GCC_BLSP2_AHB_CLK>;
clock-names = "core", "iface";
- spi-max-frequency = <19200000>;
dmas = <&blsp2_dma 18>, <&blsp2_dma 19>;
dma-names = "tx", "rx";
pinctrl-names = "default", "sleep";
@@ -773,254 +772,256 @@
interrupt-controller;
#interrupt-cells = <2>;
- blsp1_uart2_default: blsp1-uart2-default {
- function = "blsp_uart2";
+ blsp1_uart2_default: blsp1-uart2-default-state {
pins = "gpio4", "gpio5";
+ function = "blsp_uart2";
drive-strength = <16>;
bias-disable;
};
- blsp1_uart2_sleep: blsp1-uart2-sleep {
- function = "gpio";
+ blsp1_uart2_sleep: blsp1-uart2-sleep-state {
pins = "gpio4", "gpio5";
+ function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
- blsp2_uart2_default: blsp2-uart2-default {
+ blsp2_uart2_default: blsp2-uart2-default-state {
+ pins = "gpio45", "gpio46", "gpio47", "gpio48";
function = "blsp_uart8";
- pins = "gpio45", "gpio46",
- "gpio47", "gpio48";
drive-strength = <16>;
bias-disable;
};
- blsp2_uart2_sleep: blsp2-uart2-sleep {
+ blsp2_uart2_sleep: blsp2-uart2-sleep-state {
+ pins = "gpio45", "gpio46", "gpio47", "gpio48";
function = "gpio";
- pins = "gpio45", "gpio46",
- "gpio47", "gpio48";
drive-strength = <2>;
bias-disable;
};
- i2c1_default: i2c1-default {
- function = "blsp_i2c1";
+ i2c1_default: i2c1-default-state {
pins = "gpio2", "gpio3";
+ function = "blsp_i2c1";
drive-strength = <2>;
bias-disable;
};
- i2c1_sleep: i2c1-sleep {
- function = "gpio";
+ i2c1_sleep: i2c1-sleep-state {
pins = "gpio2", "gpio3";
+ function = "gpio";
drive-strength = <2>;
bias-disable;
};
- i2c2_default: i2c2-default {
- function = "blsp_i2c2";
+ i2c2_default: i2c2-default-state {
pins = "gpio6", "gpio7";
+ function = "blsp_i2c2";
drive-strength = <2>;
bias-disable;
};
- i2c2_sleep: i2c2-sleep {
- function = "gpio";
+ i2c2_sleep: i2c2-sleep-state {
pins = "gpio6", "gpio7";
+ function = "gpio";
drive-strength = <2>;
bias-disable;
};
- i2c4_default: i2c4-default {
- function = "blsp_i2c4";
+ i2c4_default: i2c4-default-state {
pins = "gpio19", "gpio20";
+ function = "blsp_i2c4";
drive-strength = <2>;
bias-disable;
};
- i2c4_sleep: i2c4-sleep {
- function = "gpio";
+ i2c4_sleep: i2c4-sleep-state {
pins = "gpio19", "gpio20";
+ function = "gpio";
drive-strength = <2>;
bias-pull-down;
input-enable;
};
- i2c5_default: i2c5-default {
- function = "blsp_i2c5";
+ i2c5_default: i2c5-default-state {
pins = "gpio23", "gpio24";
+ function = "blsp_i2c5";
drive-strength = <2>;
bias-disable;
};
- i2c5_sleep: i2c5-sleep {
- function = "gpio";
+ i2c5_sleep: i2c5-sleep-state {
pins = "gpio23", "gpio24";
+ function = "gpio";
drive-strength = <2>;
bias-disable;
};
- i2c6_default: i2c6-default {
- function = "blsp_i2c6";
+ i2c6_default: i2c6-default-state {
pins = "gpio28", "gpio27";
+ function = "blsp_i2c6";
drive-strength = <2>;
bias-disable;
};
- i2c6_sleep: i2c6-sleep {
- function = "gpio";
+ i2c6_sleep: i2c6-sleep-state {
pins = "gpio28", "gpio27";
+ function = "gpio";
drive-strength = <2>;
bias-disable;
};
- i2c7_default: i2c7-default {
- function = "blsp_i2c7";
+ i2c7_default: i2c7-default-state {
pins = "gpio44", "gpio43";
+ function = "blsp_i2c7";
drive-strength = <2>;
bias-disable;
};
- i2c7_sleep: i2c7-sleep {
- function = "gpio";
+ i2c7_sleep: i2c7-sleep-state {
pins = "gpio44", "gpio43";
+ function = "gpio";
drive-strength = <2>;
bias-disable;
};
- blsp2_spi10_default: blsp2-spi10-default {
- default {
- function = "blsp_spi10";
+ blsp2_spi10_default: blsp2-spi10-default-state {
+ default-pins {
pins = "gpio53", "gpio54", "gpio55";
+ function = "blsp_spi10";
drive-strength = <10>;
bias-pull-down;
};
- cs {
+
+ cs-pins {
+ pins = "gpio67";
function = "gpio";
- pins = "gpio55";
drive-strength = <2>;
bias-disable;
};
};
- blsp2_spi10_sleep: blsp2-spi10-sleep {
+ blsp2_spi10_sleep: blsp2-spi10-sleep-state {
pins = "gpio53", "gpio54", "gpio55";
+ function = "gpio";
drive-strength = <2>;
bias-disable;
};
- i2c11_default: i2c11-default {
- function = "blsp_i2c11";
+ i2c11_default: i2c11-default-state {
pins = "gpio83", "gpio84";
+ function = "blsp_i2c11";
drive-strength = <2>;
bias-disable;
};
- i2c11_sleep: i2c11-sleep {
- function = "gpio";
+ i2c11_sleep: i2c11-sleep-state {
pins = "gpio83", "gpio84";
+ function = "gpio";
drive-strength = <2>;
bias-disable;
};
- blsp1_spi1_default: blsp1-spi1-default {
- default {
- function = "blsp_spi1";
+ blsp1_spi1_default: blsp1-spi1-default-state {
+ default-pins {
pins = "gpio0", "gpio1", "gpio3";
+ function = "blsp_spi1";
drive-strength = <10>;
bias-pull-down;
};
- cs {
- function = "gpio";
+
+ cs-pins {
pins = "gpio8";
+ function = "gpio";
drive-strength = <2>;
bias-disable;
};
};
- blsp1_spi1_sleep: blsp1-spi1-sleep {
+ blsp1_spi1_sleep: blsp1-spi1-sleep-state {
pins = "gpio0", "gpio1", "gpio3";
+ function = "gpio";
drive-strength = <2>;
bias-disable;
};
- sdc1_clk_on: clk-on {
+ sdc1_clk_on: clk-on-state {
pins = "sdc1_clk";
bias-disable;
drive-strength = <16>;
};
- sdc1_clk_off: clk-off {
+ sdc1_clk_off: clk-off-state {
pins = "sdc1_clk";
bias-disable;
drive-strength = <2>;
};
- sdc1_cmd_on: cmd-on {
+ sdc1_cmd_on: cmd-on-state {
pins = "sdc1_cmd";
bias-pull-up;
drive-strength = <8>;
};
- sdc1_cmd_off: cmd-off {
+ sdc1_cmd_off: cmd-off-state {
pins = "sdc1_cmd";
bias-pull-up;
drive-strength = <2>;
};
- sdc1_data_on: data-on {
+ sdc1_data_on: data-on-state {
pins = "sdc1_data";
bias-pull-up;
drive-strength = <8>;
};
- sdc1_data_off: data-off {
+ sdc1_data_off: data-off-state {
pins = "sdc1_data";
bias-pull-up;
drive-strength = <2>;
};
- sdc1_rclk_on: rclk-on {
+ sdc1_rclk_on: rclk-on-state {
pins = "sdc1_rclk";
bias-pull-down;
};
- sdc1_rclk_off: rclk-off {
+ sdc1_rclk_off: rclk-off-state {
pins = "sdc1_rclk";
bias-pull-down;
};
- sdc2_clk_on: sdc2-clk-on {
+ sdc2_clk_on: sdc2-clk-on-state {
pins = "sdc2_clk";
bias-disable;
drive-strength = <10>;
};
- sdc2_clk_off: sdc2-clk-off {
+ sdc2_clk_off: sdc2-clk-off-state {
pins = "sdc2_clk";
bias-disable;
drive-strength = <2>;
};
- sdc2_cmd_on: sdc2-cmd-on {
+ sdc2_cmd_on: sdc2-cmd-on-state {
pins = "sdc2_cmd";
bias-pull-up;
drive-strength = <10>;
};
- sdc2_cmd_off: sdc2-cmd-off {
+ sdc2_cmd_off: sdc2-cmd-off-state {
pins = "sdc2_cmd";
bias-pull-up;
drive-strength = <2>;
};
- sdc2_data_on: sdc2-data-on {
+ sdc2_data_on: sdc2-data-on-state {
pins = "sdc2_data";
bias-pull-up;
drive-strength = <10>;
};
- sdc2_data_off: sdc2-data-off {
+ sdc2_data_off: sdc2-data-off-state {
pins = "sdc2_data";
bias-pull-up;
drive-strength = <2>;
diff --git a/arch/arm64/boot/dts/qcom/msm8996-oneplus-common.dtsi b/arch/arm64/boot/dts/qcom/msm8996-oneplus-common.dtsi
new file mode 100644
index 000000000000..20f5c103c63b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8996-oneplus-common.dtsi
@@ -0,0 +1,787 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022, Harry Austen <hpausten@protonmail.com>
+ */
+
+#include "msm8996.dtsi"
+#include "pm8994.dtsi"
+#include "pmi8994.dtsi"
+#include "pmi8996.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+#include <dt-bindings/sound/qcom,q6afe.h>
+#include <dt-bindings/sound/qcom,q6asm.h>
+#include <dt-bindings/sound/qcom,wcd9335.h>
+
+/ {
+ aliases {
+ serial0 = &blsp1_uart2;
+ serial1 = &blsp2_uart2;
+ };
+
+ battery: battery {
+ compatible = "simple-battery";
+
+ constant-charge-current-max-microamp = <3000000>;
+ voltage-min-design-microvolt = <3400000>;
+ };
+
+ chosen {
+ stdout-path = "serial1:115200n8";
+ };
+
+ clocks {
+ div1_mclk: div1-clk {
+ compatible = "gpio-gate-clock";
+ pinctrl-names = "default";
+ pinctrl-0 = <&audio_mclk>;
+ #clock-cells = <0>;
+ clocks = <&rpmcc RPM_SMD_DIV_CLK1>;
+ enable-gpios = <&pm8994_gpios 15 GPIO_ACTIVE_HIGH>;
+ };
+
+ divclk4: div4-clk {
+ compatible = "fixed-clock";
+ pinctrl-names = "default";
+ pinctrl-0 = <&divclk4_pin_a>;
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "divclk4";
+ };
+ };
+
+ reserved-memory {
+ ramoops@ac000000 {
+ compatible = "ramoops";
+ reg = <0 0xac000000 0 0x200000>;
+ record-size = <0x20000>;
+ console-size = <0x100000>;
+ pmsg-size = <0x80000>;
+ };
+ };
+
+ vph_pwr: vph-pwr-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vph_pwr";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ wlan_en: wlan-en-regulator {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wlan_en_gpios>;
+ regulator-name = "wlan-en-regulator";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ gpio = <&pm8994_gpios 8 GPIO_ACTIVE_HIGH>;
+
+ /* WLAN card specific delay */
+ startup-delay-us = <70000>;
+ enable-active-high;
+ };
+};
+
+&adsp_pil {
+ status = "okay";
+};
+
+&blsp1_i2c3 {
+ status = "okay";
+
+ tfa9890_amp: audio-codec@36 {
+ compatible = "nxp,tfa9890";
+ reg = <0x36>;
+ #sound-dai-cells = <0>;
+ };
+};
+
+&blsp1_i2c6 {
+ status = "okay";
+
+ bq27541: fuel-gauge@55 {
+ compatible = "ti,bq27541";
+ reg = <0x55>;
+ };
+};
+
+&blsp1_uart2 {
+ label = "BT-UART";
+ uart-has-rtscts;
+ status = "okay";
+
+ bluetooth {
+ compatible = "qcom,qca6174-bt";
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_en_gpios>;
+ enable-gpios = <&pm8994_gpios 19 GPIO_ACTIVE_HIGH>;
+ clocks = <&divclk4>;
+ };
+};
+
+&blsp2_i2c1 {
+ status = "okay";
+};
+
+&blsp2_i2c6 {
+ status = "okay";
+
+ synaptics_rmi4_i2c: touchscreen@20 {
+ compatible = "syna,rmi4-i2c";
+ reg = <0x20>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts-extended = <&tlmm 125 IRQ_TYPE_EDGE_FALLING>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&touch_default>;
+ pinctrl-1 = <&touch_suspend>;
+ vdd-supply = <&vreg_l22a_3p0>;
+ vio-supply = <&vreg_s4a_1p8>;
+ syna,reset-delay-ms = <200>;
+ syna,startup-delay-ms = <200>;
+
+ rmi4-f01@1 {
+ reg = <0x1>;
+ syna,nosleep-mode = <1>;
+ };
+
+ rmi4-f12@12 {
+ reg = <0x12>;
+ syna,sensor-type = <1>;
+ touchscreen-x-mm = <68>;
+ touchscreen-y-mm = <122>;
+ };
+ };
+};
+
+&blsp2_uart2 {
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&blsp2_uart2_2pins_default>;
+ pinctrl-1 = <&blsp2_uart2_2pins_sleep>;
+ status = "okay";
+};
+
+&camss {
+ vdda-supply = <&vreg_l2a_1p25>;
+};
+
+&dsi0 {
+ vdda-supply = <&vreg_l2a_1p25>;
+ vcca-supply = <&vreg_l22a_3p0>;
+ status = "okay";
+};
+
+&dsi0_out {
+ data-lanes = <0 1 2 3>;
+};
+
+&dsi0_phy {
+ vdda-supply = <&vreg_l2a_1p25>;
+ vcca-supply = <&vreg_l28a_0p925>;
+ status = "okay";
+};
+
+&gpu {
+ status = "okay";
+};
+
+&hsusb_phy1 {
+ vdd-supply = <&vreg_l28a_0p925>;
+ vdda-pll-supply = <&vreg_l12a_1p8>;
+ vdda-phy-dpdm-supply = <&vreg_l24a_3p075>;
+ status = "okay";
+};
+
+&hsusb_phy2 {
+ vdd-supply = <&vreg_l28a_0p925>;
+ vdda-pll-supply = <&vreg_l12a_1p8>;
+ vdda-phy-dpdm-supply = <&vreg_l24a_3p075>;
+ status = "okay";
+};
+
+&mdp {
+ status = "okay";
+};
+
+&mdss {
+ status = "okay";
+};
+
+&mmcc {
+ vdd-gfx-supply = <&vdd_gfx>;
+};
+
+&mss_pil {
+ pll-supply = <&vreg_l12a_1p8>;
+ status = "okay";
+};
+
+&pcie0 {
+ perst-gpios = <&tlmm 35 GPIO_ACTIVE_LOW>;
+ vddpe-3v3-supply = <&wlan_en>;
+ vdda-supply = <&vreg_l28a_0p925>;
+ status = "okay";
+};
+
+&pcie_phy {
+ vdda-phy-supply = <&vreg_l28a_0p925>;
+ vdda-pll-supply = <&vreg_l12a_1p8>;
+ status = "okay";
+};
+
+&pm8994_gpios {
+ bt_en_gpios: bt-en-gpios-state {
+ pins = "gpio19";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ output-low;
+ power-source = <PM8994_GPIO_S4>;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_LOW>;
+ bias-pull-down;
+ };
+
+ wlan_en_gpios: wlan-en-gpios-state {
+ pins = "gpio8";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ output-low;
+ power-source = <PM8994_GPIO_S4>;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_LOW>;
+ bias-pull-down;
+ };
+
+ audio_mclk: divclk1-state {
+ pins = "gpio15";
+ function = PMIC_GPIO_FUNC_FUNC1;
+ power-source = <PM8994_GPIO_S4>;
+ };
+
+ divclk4_pin_a: divclk4-state {
+ pins = "gpio18";
+ function = PMIC_GPIO_FUNC_FUNC2;
+ bias-disable;
+ power-source = <PM8994_GPIO_S4>;
+ };
+};
+
+&pm8994_spmi_regulators {
+ qcom,saw-reg = <&saw3>;
+
+ s9 {
+ qcom,saw-slave;
+ };
+
+ s10 {
+ qcom,saw-slave;
+ };
+
+ s11 {
+ qcom,saw-leader;
+ regulator-min-microvolt = <1140000>;
+ regulator-max-microvolt = <1140000>;
+ regulator-max-step-microvolt = <150000>;
+ regulator-always-on;
+ };
+};
+
+&pmi8994_spmi_regulators {
+ vdd_gfx: s2 {
+ regulator-name = "vdd-gfx";
+ regulator-min-microvolt = <980000>;
+ regulator-max-microvolt = <1230000>;
+ };
+};
+
+&q6asmdai {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dai@0 {
+ reg = <0>;
+ };
+
+ dai@1 {
+ reg = <1>;
+ };
+
+ dai@2 {
+ reg = <2>;
+ };
+};
+
+&rpm_requests {
+ regulators {
+ compatible = "qcom,rpm-pm8994-regulators";
+
+ vreg_s3a_1p3: s3 {
+ regulator-name = "vreg_s3a_1p3";
+ regulator-min-microvolt = <1300000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ vreg_s4a_1p8: s4 {
+ regulator-name = "vreg_s4a_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ };
+
+ vreg_s5a_2p15: s5 {
+ regulator-name = "vreg_s5a_2p15";
+ regulator-min-microvolt = <2150000>;
+ regulator-max-microvolt = <2150000>;
+ };
+
+ vreg_s7a_0p8: s7 {
+ regulator-name = "vreg_s7a_0p8";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ };
+
+ vreg_l1a_1p0: l1 {
+ regulator-name = "vreg_l1a_1p0";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ };
+
+ vreg_l2a_1p25: l2 {
+ regulator-name = "vreg_l2a_1p25";
+ regulator-min-microvolt = <1250000>;
+ regulator-max-microvolt = <1250000>;
+ regulator-allow-set-load;
+ };
+
+ vreg_l3a_1p1: l3 {
+ regulator-name = "vreg_l3a_1p1";
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ };
+
+ vreg_l4a_1p225: l4 {
+ regulator-name = "vreg_l4a_1p225";
+ regulator-min-microvolt = <1225000>;
+ regulator-max-microvolt = <1225000>;
+ };
+
+ vreg_l6a_1p2: l6 {
+ regulator-name = "vreg_l6a_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ vreg_l7a_1p8: l7 {
+ regulator-name = "vreg_l7a_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vreg_l9a_1p8: l9 {
+ regulator-name = "vreg_l9a_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vreg_l10a_1p8: l10 {
+ regulator-name = "vreg_l10a_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vreg_l11a_1p15: l11 {
+ regulator-name = "vreg_l11a_1p15";
+ regulator-min-microvolt = <1150000>;
+ regulator-max-microvolt = <1150000>;
+ };
+
+ vreg_l12a_1p8: l12 {
+ regulator-name = "vreg_l12a_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-allow-set-load;
+ };
+
+ vreg_l13a_2p95: l13 {
+ regulator-name = "vreg_l13a_2p95";
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ };
+
+ vreg_l16a_2p7: l16 {
+ regulator-name = "vreg_l16a_2p7";
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2700000>;
+ };
+
+ vreg_l17a_2p6: l17 {
+ regulator-name = "vreg_l17a_2p6";
+ regulator-min-microvolt = <2600000>;
+ regulator-max-microvolt = <2600000>;
+ };
+
+ vreg_l18a_3p3: l18 {
+ regulator-name = "vreg_l18a_3p3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ vreg_l19a_3p0: l19 {
+ regulator-name = "vreg_l19a_3p0";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ };
+
+ vreg_l20a_2p95: l20 {
+ regulator-name = "vreg_l20a_2p95";
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-allow-set-load;
+ };
+
+ vreg_l21a_2p95: l21 {
+ regulator-name = "vreg_l21a_2p95";
+ regulator-min-microvolt = <2950000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-allow-set-load;
+ regulator-system-load = <200000>;
+ };
+
+ vreg_l22a_3p0: l22 {
+ regulator-name = "vreg_l22a_3p0";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3300000>;
+ };
+
+ vreg_l23a_2p8: l23 {
+ regulator-name = "vreg_l23a_2p8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ vreg_l24a_3p075: l24 {
+ regulator-name = "vreg_l24a_3p075";
+ regulator-min-microvolt = <3075000>;
+ regulator-max-microvolt = <3075000>;
+ };
+
+ vreg_l25a_1p2: l25 {
+ regulator-name = "vreg_l25a_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-allow-set-load;
+ regulator-always-on;
+ };
+
+ vreg_l27a_1p2: l27 {
+ regulator-name = "vreg_l27a_1p2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ vreg_l28a_0p925: l28 {
+ regulator-name = "vreg_l28a_0p925";
+ regulator-min-microvolt = <925000>;
+ regulator-max-microvolt = <925000>;
+ regulator-allow-set-load;
+ };
+
+ vreg_l29a_2p8: l29 {
+ regulator-name = "vreg_l29a_2p8";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+
+ vreg_l30a_1p8: l30 {
+ regulator-name = "vreg_l30a_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vreg_l32a_1p8: l32 {
+ regulator-name = "vreg_l32a_1p8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+ };
+};
+
+&slpi_pil {
+ status = "okay";
+};
+
+&sound {
+ compatible = "qcom,apq8096-sndcard";
+ model = "OnePlus3";
+ audio-routing = "RX_BIAS", "MCLK",
+ "AMIC2", "MIC BIAS2",
+ "MIC BIAS2", "Headset Mic",
+ "AMIC4", "MIC BIAS1",
+ "MIC BIAS1", "Primary Mic",
+ "AMIC5", "MIC BIAS3",
+ "MIC BIAS3", "Noise Mic";
+
+ mm1-dai-link {
+ link-name = "MultiMedia1";
+
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA1>;
+ };
+ };
+
+ mm2-dai-link {
+ link-name = "MultiMedia2";
+
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA2>;
+ };
+ };
+
+ mm3-dai-link {
+ link-name = "MultiMedia3";
+
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA3>;
+ };
+ };
+
+ mm4-dai-link {
+ link-name = "MultiMedia4";
+
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA4>;
+ };
+ };
+
+ mm5-dai-link {
+ link-name = "MultiMedia5";
+
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA5>;
+ };
+ };
+
+ mm6-dai-link {
+ link-name = "MultiMedia6";
+
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA6>;
+ };
+ };
+
+ mm7-dai-link {
+ link-name = "MultiMedia7";
+
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA7>;
+ };
+ };
+
+ mm8-dai-link {
+ link-name = "MultiMedia8";
+
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA8>;
+ };
+ };
+
+ mm9-dai-link {
+ link-name = "MultiMedia9";
+
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA9>;
+ };
+ };
+
+ mm10-dai-link {
+ link-name = "MultiMedia10";
+
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA10>;
+ };
+ };
+
+ mm11-dai-link {
+ link-name = "MultiMedia11";
+
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA11>;
+ };
+ };
+
+ mm12-dai-link {
+ link-name = "MultiMedia12";
+
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA12>;
+ };
+ };
+
+ mm13-dai-link {
+ link-name = "MultiMedia13";
+
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA13>;
+ };
+ };
+
+ mm14-dai-link {
+ link-name = "MultiMedia14";
+
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA14>;
+ };
+ };
+
+ mm15-dai-link {
+ link-name = "MultiMedia15";
+
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA15>;
+ };
+ };
+
+ mm16-dai-link {
+ link-name = "MultiMedia16";
+
+ cpu {
+ sound-dai = <&q6asmdai MSM_FRONTEND_DAI_MULTIMEDIA16>;
+ };
+ };
+
+ slim-dai-link {
+ link-name = "SLIM Playback";
+
+ cpu {
+ sound-dai = <&q6afedai SLIMBUS_6_RX>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+
+ codec {
+ sound-dai = <&wcd9335 AIF4_PB>;
+ };
+ };
+
+ slimcap-dai-link {
+ link-name = "SLIM Capture";
+
+ cpu {
+ sound-dai = <&q6afedai SLIMBUS_0_TX>;
+ };
+
+ platform {
+ sound-dai = <&q6routing>;
+ };
+
+ codec {
+ sound-dai = <&wcd9335 AIF1_CAP>;
+ };
+ };
+
+ speaker-dai-link {
+ link-name = "Speaker";
+
+ cpu {
+ sound-dai = <&q6afedai QUATERNARY_MI2S_RX>;
+ };
+
+ codec {
+ sound-dai = <&tfa9890_amp>;
+ };
+ };
+};
+
+&tlmm {
+ gpio-reserved-ranges = <81 4>;
+
+ mdss_dsi_active: mdss-dsi-active-state {
+ pins = "gpio8";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ mdss_dsi_suspend: mdss-dsi-suspend-state {
+ pins = "gpio8";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ mdss_te_active: mdss-te-active-state {
+ pins = "gpio10";
+ function = "mdp_vsync";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ mdss_te_suspend: mdss-te-suspend-state {
+ pins = "gpio10";
+ function = "mdp_vsync";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ touch_default: touch-default-state {
+ pins = "gpio89", "gpio125", "gpio49";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+
+ touch_suspend: touch-suspend-state {
+ pins = "gpio89", "gpio125", "gpio49";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+};
+
+&ufsphy {
+ vdda-phy-supply = <&vreg_l28a_0p925>;
+ vdda-pll-supply = <&vreg_l12a_1p8>;
+ vddp-ref-clk-supply = <&vreg_l25a_1p2>;
+
+ status = "okay";
+};
+
+&ufshc {
+ vcc-supply = <&vreg_l20a_2p95>;
+ vccq-supply = <&vreg_l25a_1p2>;
+ vccq2-supply = <&vreg_s4a_1p8>;
+
+ vcc-max-microamp = <600000>;
+ vccq-max-microamp = <450000>;
+ vccq2-max-microamp = <450000>;
+
+ status = "okay";
+};
+
+&usb3 {
+ status = "okay";
+};
+
+&usb3_dwc3 {
+ phys = <&hsusb_phy1>;
+ phy-names = "usb2-phy";
+
+ maximum-speed = "high-speed";
+};
+
+&venus {
+ status = "okay";
+};
+
+&wcd9335 {
+ clock-names = "mclk", "slimbus";
+ clocks = <&div1_mclk>,
+ <&rpmcc RPM_SMD_BB_CLK1>;
+
+ vdd-buck-supply = <&vreg_s4a_1p8>;
+ vdd-buck-sido-supply = <&vreg_s4a_1p8>;
+ vdd-tx-supply = <&vreg_s4a_1p8>;
+ vdd-rx-supply = <&vreg_s4a_1p8>;
+ vdd-io-supply = <&vreg_s4a_1p8>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8996-oneplus3.dts b/arch/arm64/boot/dts/qcom/msm8996-oneplus3.dts
new file mode 100644
index 000000000000..1bdc1b134305
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8996-oneplus3.dts
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022, Harry Austen <hpausten@protonmail.com>
+ */
+
+/dts-v1/;
+
+#include "msm8996-oneplus-common.dtsi"
+
+/ {
+ model = "OnePlus 3";
+ compatible = "oneplus,oneplus3", "qcom,msm8996";
+ chassis-type = "handset";
+ qcom,board-id = <8 0 15801 15>, <8 0 15801 16>;
+ qcom,msm-id = <246 0x30001>;
+};
+
+&adsp_pil {
+ firmware-name = "qcom/msm8996/oneplus3/adsp.mbn";
+};
+
+&battery {
+ charge-full-design-microamp-hours = <3000000>;
+ voltage-max-design-microvolt = <4350000>;
+};
+
+&gpu {
+ zap-shader {
+ firmware-name = "qcom/msm8996/oneplus3/a530_zap.mbn";
+ };
+};
+
+&mss_pil {
+ firmware-name = "qcom/msm8996/oneplus3/mba.mbn",
+ "qcom/msm8996/oneplus3/modem.mbn";
+};
+
+&slpi_pil {
+ firmware-name = "qcom/msm8996/oneplus3/slpi.mbn";
+};
+
+&venus {
+ firmware-name = "qcom/msm8996/oneplus3/venus.mbn";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8996-oneplus3t.dts b/arch/arm64/boot/dts/qcom/msm8996-oneplus3t.dts
new file mode 100644
index 000000000000..34f837dd0c12
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8996-oneplus3t.dts
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022, Harry Austen <hpausten@protonmail.com>
+ */
+
+/dts-v1/;
+
+#include "msm8996-oneplus-common.dtsi"
+
+/ {
+ model = "OnePlus 3T";
+ compatible = "oneplus,oneplus3t", "qcom,msm8996";
+ chassis-type = "handset";
+ qcom,board-id = <8 0 15811 26>,
+ <8 0 15811 27>,
+ <8 0 15811 28>;
+};
+
+&adsp_pil {
+ firmware-name = "qcom/msm8996/oneplus3t/adsp.mbn";
+};
+
+&battery {
+ charge-full-design-microamp-hours = <3400000>;
+ voltage-max-design-microvolt = <4400000>;
+};
+
+&gpu {
+ zap-shader {
+ firmware-name = "qcom/msm8996/oneplus3t/a530_zap.mbn";
+ };
+};
+
+&mss_pil {
+ firmware-name = "qcom/msm8996/oneplus3t/mba.mbn",
+ "qcom/msm8996/oneplus3t/modem.mbn";
+};
+
+&slpi_pil {
+ firmware-name = "qcom/msm8996/oneplus3t/slpi.mbn";
+};
+
+&venus {
+ firmware-name = "qcom/msm8996/oneplus3t/venus.mbn";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone.dtsi b/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone.dtsi
index ca7c8d2e1d3d..dec361b93cce 100644
--- a/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996-sony-xperia-tone.dtsi
@@ -629,7 +629,7 @@
};
&rpm_requests {
- pm8994-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pm8994-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -847,28 +847,28 @@
pinctrl-0 = <&sw_service_gpio>;
pinctrl-names = "default";
- disp_reset_n_gpio: disp-reset-n {
+ disp_reset_n_gpio: disp-reset-n-state {
pins = "gpio8";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- mdp_vsync_p_gpio: mdp-vsync-p {
+ mdp_vsync_p_gpio: mdp-vsync-p-state {
pins = "gpio10";
function = "mdp_vsync";
drive-strength = <2>;
bias-disable;
};
- sw_service_gpio: sw-service-gpio {
+ sw_service_gpio: sw-service-gpio-state {
pins = "gpio16";
function = "gpio";
drive-strength = <2>;
bias-pull-up;
};
- usb_detect: usb-detect {
+ usb_detect: usb-detect-state {
pins = "gpio25";
function = "gpio";
drive-strength = <2>;
@@ -876,7 +876,7 @@
output-high;
};
- uim_detect_en: uim-detect-en {
+ uim_detect_en: uim-detect-en-state {
pins = "gpio29";
function = "gpio";
drive-strength = <2>;
@@ -884,14 +884,14 @@
output-high;
};
- tray_det_pin: tray-det {
+ tray_det_pin: tray-det-state {
pins = "gpio40";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- tp_vddio_en: tp-vddio-en {
+ tp_vddio_en: tp-vddio-en-state {
pins = "gpio50";
function = "gpio";
drive-strength = <2>;
@@ -899,7 +899,7 @@
output-high;
};
- lcd_vddio_en: lcd-vddio-en {
+ lcd_vddio_en: lcd-vddio-en-state {
pins = "gpio51";
function = "gpio";
drive-strength = <2>;
@@ -907,15 +907,14 @@
output-low;
};
- wl_host_wake: wl-host-wake {
+ wl_host_wake: wl-host-wake-state {
pins = "gpio79";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
- input-high;
};
- wl_reg_on: wl-reg-on {
+ wl_reg_on: wl-reg-on-state {
pins = "gpio84";
function = "gpio";
drive-strength = <2>;
@@ -923,20 +922,20 @@
output-low;
};
- ts_reset_n: ts-rst-n {
+ ts_reset_n: ts-rst-n-state {
pins = "gpio89";
function = "gpio";
drive-strength = <2>;
};
- touch_int_n: touch-int-n {
+ touch_int_n: touch-int-n-state {
pins = "gpio125";
function = "gpio";
drive-strength = <2>;
bias-pull-up;
};
- touch_int_sleep: touch-int-sleep {
+ touch_int_sleep: touch-int-sleep-state {
pins = "gpio125";
function = "gpio";
drive-strength = <2>;
diff --git a/arch/arm64/boot/dts/qcom/msm8996-xiaomi-common.dtsi b/arch/arm64/boot/dts/qcom/msm8996-xiaomi-common.dtsi
index 77819186086a..5b47b8de69da 100644
--- a/arch/arm64/boot/dts/qcom/msm8996-xiaomi-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996-xiaomi-common.dtsi
@@ -3,9 +3,6 @@
* Copyright (c) 2020, Yassine Oudjana <y.oudjana@protonmail.com>
*/
-/dts-v1/;
-
-#include "msm8996.dtsi"
#include "pm8994.dtsi"
#include "pmi8994.dtsi"
#include <dt-bindings/input/input.h>
@@ -413,7 +410,7 @@
};
&rpm_requests {
- pm8994-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pm8994-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -598,7 +595,7 @@
};
};
- pmi8994-regulators {
+ regulators-1 {
compatible = "qcom,rpm-pmi8994-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -694,35 +691,35 @@
};
&tlmm {
- mdss_dsi_default: mdss_dsi_default {
+ mdss_dsi_default: mdss-dsi-default-state {
pins = "gpio8";
function = "gpio";
drive-strength = <8>;
bias-disable;
};
- mdss_dsi_sleep: mdss_dsi_sleep {
+ mdss_dsi_sleep: mdss-dsi-sleep-state {
pins = "gpio8";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
- mdss_te_default: mdss_te_default {
+ mdss_te_default: mdss-te-default-state {
pins = "gpio10";
function = "mdp_vsync";
drive-strength = <2>;
bias-pull-down;
};
- mdss_te_sleep: mdss_te_sleep {
+ mdss_te_sleep: mdss-te-sleep-state {
pins = "gpio10";
function = "mdp_vsync";
drive-strength = <2>;
bias-pull-down;
};
- nfc_default: nfc_default {
+ nfc_default: nfc-default-state {
pins = "gpio12", "gpio21";
function = "gpio";
drive-strength = <16>;
diff --git a/arch/arm64/boot/dts/qcom/msm8996-xiaomi-gemini.dts b/arch/arm64/boot/dts/qcom/msm8996-xiaomi-gemini.dts
index 4e5264f4116a..d8734913482f 100644
--- a/arch/arm64/boot/dts/qcom/msm8996-xiaomi-gemini.dts
+++ b/arch/arm64/boot/dts/qcom/msm8996-xiaomi-gemini.dts
@@ -5,6 +5,7 @@
/dts-v1/;
+#include "msm8996.dtsi"
#include "msm8996-xiaomi-common.dtsi"
#include <dt-bindings/sound/qcom,q6afe.h>
#include <dt-bindings/sound/qcom,q6asm.h>
@@ -219,7 +220,7 @@
};
&rpm_requests {
- pm8994-regulators {
+ regulators-0 {
vreg_l17a_2p8: l17 {
regulator-name = "vreg_l17a_2p8";
regulator-min-microvolt = <2500000>;
@@ -445,28 +446,28 @@
"RFFE1_DATA", /* GPIO_148 */
"RFFE1_CLK"; /* GPIO_149 */
- touchscreen_default: touchscreen_default {
+ touchscreen_default: touchscreen-default-state {
pins = "gpio89", "gpio125";
function = "gpio";
drive-strength = <10>;
bias-pull-up;
};
- touchscreen_sleep: touchscreen_sleep {
+ touchscreen_sleep: touchscreen-sleep-state {
pins = "gpio89", "gpio125";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- vibrator_default: vibrator_default {
+ vibrator_default: vibrator-default-state {
pins = "gpio93";
function = "gpio";
drive-strength = <8>;
bias-pull-up;
};
- vibrator_sleep: vibrator_sleep {
+ vibrator_sleep: vibrator-sleep-state {
pins = "gpio93";
function = "gpio";
drive-strength = <2>;
diff --git a/arch/arm64/boot/dts/qcom/msm8996.dtsi b/arch/arm64/boot/dts/qcom/msm8996.dtsi
index aba717644391..d31464204f69 100644
--- a/arch/arm64/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8996.dtsi
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/*
+ * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
*/
#include <dt-bindings/interrupt-controller/arm-gic.h>
@@ -144,82 +145,92 @@
/* Nominal fmax for now */
opp-307200000 {
opp-hz = /bits/ 64 <307200000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-422400000 {
opp-hz = /bits/ 64 <422400000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-480000000 {
opp-hz = /bits/ 64 <480000000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-556800000 {
opp-hz = /bits/ 64 <556800000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-652800000 {
opp-hz = /bits/ 64 <652800000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-729600000 {
opp-hz = /bits/ 64 <729600000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-844800000 {
opp-hz = /bits/ 64 <844800000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-960000000 {
opp-hz = /bits/ 64 <960000000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-1036800000 {
opp-hz = /bits/ 64 <1036800000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-1113600000 {
opp-hz = /bits/ 64 <1113600000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-1190400000 {
opp-hz = /bits/ 64 <1190400000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-1228800000 {
opp-hz = /bits/ 64 <1228800000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-1324800000 {
opp-hz = /bits/ 64 <1324800000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xd>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1363200000 {
+ opp-hz = /bits/ 64 <1363200000>;
+ opp-supported-hw = <0x2>;
clock-latency-ns = <200000>;
};
opp-1401600000 {
opp-hz = /bits/ 64 <1401600000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xd>;
clock-latency-ns = <200000>;
};
opp-1478400000 {
opp-hz = /bits/ 64 <1478400000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0x9>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1497600000 {
+ opp-hz = /bits/ 64 <1497600000>;
+ opp-supported-hw = <0x04>;
clock-latency-ns = <200000>;
};
opp-1593600000 {
opp-hz = /bits/ 64 <1593600000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0x9>;
clock-latency-ns = <200000>;
};
};
@@ -232,127 +243,137 @@
/* Nominal fmax for now */
opp-307200000 {
opp-hz = /bits/ 64 <307200000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-403200000 {
opp-hz = /bits/ 64 <403200000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-480000000 {
opp-hz = /bits/ 64 <480000000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-556800000 {
opp-hz = /bits/ 64 <556800000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-652800000 {
opp-hz = /bits/ 64 <652800000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-729600000 {
opp-hz = /bits/ 64 <729600000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-806400000 {
opp-hz = /bits/ 64 <806400000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-883200000 {
opp-hz = /bits/ 64 <883200000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-940800000 {
opp-hz = /bits/ 64 <940800000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-1036800000 {
opp-hz = /bits/ 64 <1036800000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-1113600000 {
opp-hz = /bits/ 64 <1113600000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-1190400000 {
opp-hz = /bits/ 64 <1190400000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-1248000000 {
opp-hz = /bits/ 64 <1248000000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-1324800000 {
opp-hz = /bits/ 64 <1324800000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-1401600000 {
opp-hz = /bits/ 64 <1401600000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-1478400000 {
opp-hz = /bits/ 64 <1478400000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-1555200000 {
opp-hz = /bits/ 64 <1555200000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-1632000000 {
opp-hz = /bits/ 64 <1632000000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-1708800000 {
opp-hz = /bits/ 64 <1708800000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
clock-latency-ns = <200000>;
};
opp-1785600000 {
opp-hz = /bits/ 64 <1785600000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0xf>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1804800000 {
+ opp-hz = /bits/ 64 <1804800000>;
+ opp-supported-hw = <0xe>;
clock-latency-ns = <200000>;
};
opp-1824000000 {
opp-hz = /bits/ 64 <1824000000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0x1>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1900800000 {
+ opp-hz = /bits/ 64 <1900800000>;
+ opp-supported-hw = <0x4>;
clock-latency-ns = <200000>;
};
opp-1920000000 {
opp-hz = /bits/ 64 <1920000000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0x1>;
clock-latency-ns = <200000>;
};
opp-1996800000 {
opp-hz = /bits/ 64 <1996800000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0x1>;
clock-latency-ns = <200000>;
};
opp-2073600000 {
opp-hz = /bits/ 64 <2073600000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0x1>;
clock-latency-ns = <200000>;
};
opp-2150400000 {
opp-hz = /bits/ 64 <2150400000>;
- opp-supported-hw = <0x77>;
+ opp-supported-hw = <0x1>;
clock-latency-ns = <200000>;
};
};
@@ -860,9 +881,9 @@
<&gcc GPLL0>,
<&dsi0_phy 1>,
<&dsi0_phy 0>,
- <0>,
- <0>,
- <0>;
+ <&dsi1_phy 1>,
+ <&dsi1_phy 0>,
+ <&hdmi_phy>;
clock-names = "xo",
"gcc_mmss_noc_cfg_ahb_clk",
"gpll0",
@@ -993,7 +1014,6 @@
assigned-clock-parents = <&dsi0_phy 0>, <&dsi0_phy 1>;
phys = <&dsi0_phy>;
- phy-names = "dsi";
status = "disabled";
#address-cells = <1>;
@@ -1018,7 +1038,7 @@
};
};
- dsi0_phy: dsi-phy@994400 {
+ dsi0_phy: phy@994400 {
compatible = "qcom,dsi-phy-14nm";
reg = <0x00994400 0x100>,
<0x00994500 0x300>,
@@ -1061,7 +1081,6 @@
assigned-clock-parents = <&dsi1_phy 0>, <&dsi1_phy 1>;
phys = <&dsi1_phy>;
- phy-names = "dsi";
status = "disabled";
#address-cells = <1>;
@@ -1086,7 +1105,7 @@
};
};
- dsi1_phy: dsi-phy@996400 {
+ dsi1_phy: phy@996400 {
compatible = "qcom,dsi-phy-14nm";
reg = <0x00996400 0x100>,
<0x00996500 0x300>,
@@ -1145,7 +1164,7 @@
};
};
- hdmi_phy: hdmi-phy@9a0600 {
+ hdmi_phy: phy@9a0600 {
#phy-cells = <0>;
compatible = "qcom,hdmi-phy-8996";
reg = <0x009a0600 0x1c4>,
@@ -1213,17 +1232,17 @@
compatible = "operating-points-v2";
/*
- * 624Mhz and 560Mhz are only available on speed
- * bin (1 << 0). All the rest are available on
- * all bins of the hardware
+ * 624Mhz is only available on speed bins 0 and 3.
+ * 560Mhz is only available on speed bins 0, 2 and 3.
+ * All the rest are available on all bins of the hardware.
*/
opp-624000000 {
opp-hz = /bits/ 64 <624000000>;
- opp-supported-hw = <0x01>;
+ opp-supported-hw = <0x09>;
};
opp-560000000 {
opp-hz = /bits/ 64 <560000000>;
- opp-supported-hw = <0x01>;
+ opp-supported-hw = <0x0d>;
};
opp-510000000 {
opp-hz = /bits/ 64 <510000000>;
@@ -1262,15 +1281,15 @@
interrupt-controller;
#interrupt-cells = <2>;
- blsp1_spi1_default: blsp1-spi1-default {
- spi {
+ blsp1_spi1_default: blsp1-spi1-default-state {
+ spi-pins {
pins = "gpio0", "gpio1", "gpio3";
function = "blsp_spi1";
drive-strength = <12>;
bias-disable;
};
- cs {
+ cs-pins {
pins = "gpio2";
function = "gpio";
drive-strength = <16>;
@@ -1279,42 +1298,56 @@
};
};
- blsp1_spi1_sleep: blsp1-spi1-sleep {
+ blsp1_spi1_sleep: blsp1-spi1-sleep-state {
pins = "gpio0", "gpio1", "gpio2", "gpio3";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
- blsp2_uart2_2pins_default: blsp2-uart1-2pins {
+ blsp2_uart2_2pins_default: blsp2-uart2-2pins-state {
pins = "gpio4", "gpio5";
function = "blsp_uart8";
drive-strength = <16>;
bias-disable;
};
- blsp2_uart2_2pins_sleep: blsp2-uart1-2pins-sleep {
+ blsp2_uart2_2pins_sleep: blsp2-uart2-2pins-sleep-state {
pins = "gpio4", "gpio5";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- blsp2_i2c2_default: blsp2-i2c2 {
+ blsp2_i2c2_default: blsp2-i2c2-state {
pins = "gpio6", "gpio7";
function = "blsp_i2c8";
drive-strength = <16>;
bias-disable;
};
- blsp2_i2c2_sleep: blsp2-i2c2-sleep {
+ blsp2_i2c2_sleep: blsp2-i2c2-sleep-state {
pins = "gpio6", "gpio7";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- cci0_default: cci0-default {
+ blsp1_i2c6_default: blsp1-i2c6-state {
+ pins = "gpio27", "gpio28";
+ function = "blsp_i2c6";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ blsp1_i2c6_sleep: blsp1-i2c6-sleep-state {
+ pins = "gpio27", "gpio28";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ cci0_default: cci0-default-state {
pins = "gpio17", "gpio18";
function = "cci_i2c";
drive-strength = <16>;
@@ -1322,22 +1355,22 @@
};
camera0_state_on:
- camera_rear_default: camera-rear-default {
- camera0_mclk: mclk0 {
+ camera_rear_default: camera-rear-default-state {
+ camera0_mclk: mclk0-pins {
pins = "gpio13";
function = "cam_mclk";
drive-strength = <16>;
bias-disable;
};
- camera0_rst: rst {
+ camera0_rst: rst-pins {
pins = "gpio25";
function = "gpio";
drive-strength = <16>;
bias-disable;
};
- camera0_pwdn: pwdn {
+ camera0_pwdn: pwdn-pins {
pins = "gpio26";
function = "gpio";
drive-strength = <16>;
@@ -1345,7 +1378,7 @@
};
};
- cci1_default: cci1-default {
+ cci1_default: cci1-default-state {
pins = "gpio19", "gpio20";
function = "cci_i2c";
drive-strength = <16>;
@@ -1353,22 +1386,22 @@
};
camera1_state_on:
- camera_board_default: camera-board-default {
- mclk1 {
+ camera_board_default: camera-board-default-state {
+ mclk1-pins {
pins = "gpio14";
function = "cam_mclk";
drive-strength = <16>;
bias-disable;
};
- pwdn {
+ pwdn-pins {
pins = "gpio98";
function = "gpio";
drive-strength = <16>;
bias-disable;
};
- rst {
+ rst-pins {
pins = "gpio104";
function = "gpio";
drive-strength = <16>;
@@ -1377,22 +1410,22 @@
};
camera2_state_on:
- camera_front_default: camera-front-default {
- camera2_mclk: mclk2 {
+ camera_front_default: camera-front-default-state {
+ camera2_mclk: mclk2-pins {
pins = "gpio15";
function = "cam_mclk";
drive-strength = <16>;
bias-disable;
};
- camera2_rst: rst {
+ camera2_rst: rst-pins {
pins = "gpio23";
function = "gpio";
drive-strength = <16>;
bias-disable;
};
- pwdn {
+ pwdn-pins {
pins = "gpio133";
function = "gpio";
drive-strength = <16>;
@@ -1400,22 +1433,22 @@
};
};
- pcie0_state_on: pcie0-state-on {
- perst {
+ pcie0_state_on: pcie0-state-on-state {
+ perst-pins {
pins = "gpio35";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
- clkreq {
+ clkreq-pins {
pins = "gpio36";
function = "pci_e0";
drive-strength = <2>;
bias-pull-up;
};
- wake {
+ wake-pins {
pins = "gpio37";
function = "gpio";
drive-strength = <2>;
@@ -1423,22 +1456,22 @@
};
};
- pcie0_state_off: pcie0-state-off {
- perst {
+ pcie0_state_off: pcie0-state-off-state {
+ perst-pins {
pins = "gpio35";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
- clkreq {
+ clkreq-pins {
pins = "gpio36";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- wake {
+ wake-pins {
pins = "gpio37";
function = "gpio";
drive-strength = <2>;
@@ -1446,63 +1479,63 @@
};
};
- blsp1_uart2_default: blsp1-uart2-default {
+ blsp1_uart2_default: blsp1-uart2-default-state {
pins = "gpio41", "gpio42", "gpio43", "gpio44";
function = "blsp_uart2";
drive-strength = <16>;
bias-disable;
};
- blsp1_uart2_sleep: blsp1-uart2-sleep {
+ blsp1_uart2_sleep: blsp1-uart2-sleep-state {
pins = "gpio41", "gpio42", "gpio43", "gpio44";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- blsp1_i2c3_default: blsp1-i2c2-default {
+ blsp1_i2c3_default: blsp1-i2c3-default-state {
pins = "gpio47", "gpio48";
function = "blsp_i2c3";
drive-strength = <16>;
bias-disable;
};
- blsp1_i2c3_sleep: blsp1-i2c2-sleep {
+ blsp1_i2c3_sleep: blsp1-i2c3-sleep-state {
pins = "gpio47", "gpio48";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- blsp2_uart3_4pins_default: blsp2-uart2-4pins {
+ blsp2_uart3_4pins_default: blsp2-uart3-4pins-state {
pins = "gpio49", "gpio50", "gpio51", "gpio52";
function = "blsp_uart9";
drive-strength = <16>;
bias-disable;
};
- blsp2_uart3_4pins_sleep: blsp2-uart2-4pins-sleep {
+ blsp2_uart3_4pins_sleep: blsp2-uart3-4pins-sleep-state {
pins = "gpio49", "gpio50", "gpio51", "gpio52";
function = "blsp_uart9";
drive-strength = <2>;
bias-disable;
};
- blsp2_i2c3_default: blsp2-i2c3 {
+ blsp2_i2c3_default: blsp2-i2c3-state-state {
pins = "gpio51", "gpio52";
function = "blsp_i2c9";
drive-strength = <16>;
bias-disable;
};
- blsp2_i2c3_sleep: blsp2-i2c3-sleep {
+ blsp2_i2c3_sleep: blsp2-i2c3-sleep-state {
pins = "gpio51", "gpio52";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- wcd_intr_default: wcd-intr-default{
+ wcd_intr_default: wcd-intr-default-state {
pins = "gpio54";
function = "gpio";
drive-strength = <2>;
@@ -1510,21 +1543,21 @@
input-enable;
};
- blsp2_i2c1_default: blsp2-i2c1 {
+ blsp2_i2c1_default: blsp2-i2c1-state {
pins = "gpio55", "gpio56";
function = "blsp_i2c7";
drive-strength = <16>;
bias-disable;
};
- blsp2_i2c1_sleep: blsp2-i2c0-sleep {
+ blsp2_i2c1_sleep: blsp2-i2c1-sleep-state {
pins = "gpio55", "gpio56";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- blsp2_i2c5_default: blsp2-i2c5 {
+ blsp2_i2c5_default: blsp2-i2c5-state {
pins = "gpio60", "gpio61";
function = "blsp_i2c11";
drive-strength = <2>;
@@ -1533,7 +1566,7 @@
/* Sleep state for BLSP2_I2C5 is missing.. */
- cdc_reset_active: cdc-reset-active {
+ cdc_reset_active: cdc-reset-active-state {
pins = "gpio64";
function = "gpio";
drive-strength = <16>;
@@ -1541,7 +1574,7 @@
output-high;
};
- cdc_reset_sleep: cdc-reset-sleep {
+ cdc_reset_sleep: cdc-reset-sleep-state {
pins = "gpio64";
function = "gpio";
drive-strength = <16>;
@@ -1549,15 +1582,15 @@
output-low;
};
- blsp2_spi6_default: blsp2-spi5-default {
- spi {
+ blsp2_spi6_default: blsp2-spi6-default-state {
+ spi-pins {
pins = "gpio85", "gpio86", "gpio88";
function = "blsp_spi12";
drive-strength = <12>;
bias-disable;
};
- cs {
+ cs-pins {
pins = "gpio87";
function = "gpio";
drive-strength = <16>;
@@ -1566,43 +1599,43 @@
};
};
- blsp2_spi6_sleep: blsp2-spi5-sleep {
+ blsp2_spi6_sleep: blsp2-spi6-sleep-state {
pins = "gpio85", "gpio86", "gpio87", "gpio88";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
- blsp2_i2c6_default: blsp2-i2c6 {
+ blsp2_i2c6_default: blsp2-i2c6-state {
pins = "gpio87", "gpio88";
function = "blsp_i2c12";
drive-strength = <16>;
bias-disable;
};
- blsp2_i2c6_sleep: blsp2-i2c6-sleep {
+ blsp2_i2c6_sleep: blsp2-i2c6-sleep-state {
pins = "gpio87", "gpio88";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- pcie1_state_on: pcie1-state-on {
- perst {
+ pcie1_state_on: pcie1-on-state {
+ perst-pins {
pins = "gpio130";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
- clkreq {
+ clkreq-pins {
pins = "gpio131";
function = "pci_e1";
drive-strength = <2>;
bias-pull-up;
};
- wake {
+ wake-pins {
pins = "gpio132";
function = "gpio";
drive-strength = <2>;
@@ -1610,16 +1643,16 @@
};
};
- pcie1_state_off: pcie1-state-off {
+ pcie1_state_off: pcie1-off-state {
/* Perst is missing? */
- clkreq {
+ clkreq-pins {
pins = "gpio131";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- wake {
+ wake-pins {
pins = "gpio132";
function = "gpio";
drive-strength = <2>;
@@ -1627,22 +1660,22 @@
};
};
- pcie2_state_on: pcie2-state-on {
- perst {
+ pcie2_state_on: pcie2-on-state {
+ perst-pins {
pins = "gpio114";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
- clkreq {
+ clkreq-pins {
pins = "gpio115";
function = "pci_e2";
drive-strength = <2>;
bias-pull-up;
};
- wake {
+ wake-pins {
pins = "gpio116";
function = "gpio";
drive-strength = <2>;
@@ -1650,16 +1683,16 @@
};
};
- pcie2_state_off: pcie2-state-off {
+ pcie2_state_off: pcie2-off-state {
/* Perst is missing? */
- clkreq {
+ clkreq-pins {
pins = "gpio115";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- wake {
+ wake-pins {
pins = "gpio116";
function = "gpio";
drive-strength = <2>;
@@ -1667,90 +1700,90 @@
};
};
- sdc1_state_on: sdc1-state-on {
- clk {
+ sdc1_state_on: sdc1-on-state {
+ clk-pins {
pins = "sdc1_clk";
bias-disable;
drive-strength = <16>;
};
- cmd {
+ cmd-pins {
pins = "sdc1_cmd";
bias-pull-up;
drive-strength = <10>;
};
- data {
+ data-pins {
pins = "sdc1_data";
bias-pull-up;
drive-strength = <10>;
};
- rclk {
+ rclk-pins {
pins = "sdc1_rclk";
bias-pull-down;
};
};
- sdc1_state_off: sdc1-state-off {
- clk {
+ sdc1_state_off: sdc1-off-state {
+ clk-pins {
pins = "sdc1_clk";
bias-disable;
drive-strength = <2>;
};
- cmd {
+ cmd-pins {
pins = "sdc1_cmd";
bias-pull-up;
drive-strength = <2>;
};
- data {
+ data-pins {
pins = "sdc1_data";
bias-pull-up;
drive-strength = <2>;
};
- rclk {
+ rclk-pins {
pins = "sdc1_rclk";
bias-pull-down;
};
};
- sdc2_state_on: sdc2-clk-on {
- clk {
+ sdc2_state_on: sdc2-on-state {
+ clk-pins {
pins = "sdc2_clk";
bias-disable;
drive-strength = <16>;
};
- cmd {
+ cmd-pins {
pins = "sdc2_cmd";
bias-pull-up;
drive-strength = <10>;
};
- data {
+ data-pins {
pins = "sdc2_data";
bias-pull-up;
drive-strength = <10>;
};
};
- sdc2_state_off: sdc2-clk-off {
- clk {
+ sdc2_state_off: sdc2-off-state {
+ clk-pins {
pins = "sdc2_clk";
bias-disable;
drive-strength = <2>;
};
- cmd {
+ cmd-pins {
pins = "sdc2_cmd";
bias-pull-up;
drive-strength = <2>;
};
- data {
+ data-pins {
pins = "sdc2_data";
bias-pull-up;
drive-strength = <2>;
@@ -1995,10 +2028,6 @@
lanes-per-direction = <1>;
#reset-cells = <1>;
status = "disabled";
-
- ufs_variant {
- compatible = "qcom,ufs_variant";
- };
};
ufsphy: phy@627000 {
@@ -2205,9 +2234,9 @@
<GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH>;
#iommu-cells = <1>;
- clocks = <&mmcc GPU_AHB_CLK>,
- <&gcc GCC_MMSS_BIMC_GFX_CLK>;
- clock-names = "iface", "bus";
+ clocks = <&gcc GCC_MMSS_BIMC_GFX_CLK>,
+ <&mmcc GPU_AHB_CLK>;
+ clock-names = "bus", "iface";
power-domains = <&mmcc GPU_GDSC>;
};
@@ -2272,9 +2301,9 @@
<GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH>;
#iommu-cells = <1>;
- clocks = <&mmcc SMMU_MDP_AHB_CLK>,
- <&mmcc SMMU_MDP_AXI_CLK>;
- clock-names = "iface", "bus";
+ clocks = <&mmcc SMMU_MDP_AXI_CLK>,
+ <&mmcc SMMU_MDP_AHB_CLK>;
+ clock-names = "bus", "iface";
power-domains = <&mmcc MDSS_GDSC>;
};
@@ -2292,9 +2321,9 @@
<GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>;
power-domains = <&mmcc MMAGIC_VIDEO_GDSC>;
- clocks = <&mmcc SMMU_VIDEO_AHB_CLK>,
- <&mmcc SMMU_VIDEO_AXI_CLK>;
- clock-names = "iface", "bus";
+ clocks = <&mmcc SMMU_VIDEO_AXI_CLK>,
+ <&mmcc SMMU_VIDEO_AHB_CLK>;
+ clock-names = "bus", "iface";
#iommu-cells = <1>;
status = "okay";
};
@@ -2308,10 +2337,9 @@
<GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 344 IRQ_TYPE_LEVEL_HIGH>;
power-domains = <&mmcc MMAGIC_CAMSS_GDSC>;
- clocks = <&mmcc SMMU_VFE_AHB_CLK>,
- <&mmcc SMMU_VFE_AXI_CLK>;
- clock-names = "iface",
- "bus";
+ clocks = <&mmcc SMMU_VFE_AXI_CLK>,
+ <&mmcc SMMU_VFE_AHB_CLK>;
+ clock-names = "bus", "iface";
#iommu-cells = <1>;
};
@@ -2336,9 +2364,9 @@
<GIC_SPI 402 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 403 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&gcc GCC_HLOS1_VOTE_LPASS_CORE_SMMU_CLK>,
- <&gcc GCC_HLOS1_VOTE_LPASS_ADSP_SMMU_CLK>;
- clock-names = "iface", "bus";
+ clocks = <&gcc GCC_HLOS1_VOTE_LPASS_ADSP_SMMU_CLK>,
+ <&gcc GCC_HLOS1_VOTE_LPASS_CORE_SMMU_CLK>;
+ clock-names = "bus", "iface";
};
slpi_pil: remoteproc@1c00000 {
@@ -3127,6 +3155,23 @@
status = "disabled";
};
+ blsp1_i2c6: i2c@757a000 {
+ compatible = "qcom,i2c-qup-v2.2.1";
+ reg = <0x757a000 0x1000>;
+ interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_QUP6_I2C_APPS_CLK>,
+ <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "core", "iface";
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&blsp1_i2c6_default>;
+ pinctrl-1 = <&blsp1_i2c6_sleep>;
+ dmas = <&blsp1_dma 22>, <&blsp1_dma 23>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
blsp2_dma: dma-controller@7584000 {
compatible = "qcom,bam-v1.7.0";
reg = <0x07584000 0x2b000>;
@@ -3309,27 +3354,25 @@
qcom,num-ees = <2>;
};
- slim_msm: slim@91c0000 {
+ slim_msm: slim-ngd@91c0000 {
compatible = "qcom,slim-ngd-v1.5.0";
reg = <0x091c0000 0x2C000>;
- reg-names = "ctrl";
interrupts = <0 163 IRQ_TYPE_LEVEL_HIGH>;
- dmas = <&slimbam 3>, <&slimbam 4>,
- <&slimbam 5>, <&slimbam 6>;
- dma-names = "rx", "tx", "tx2", "rx2";
+ dmas = <&slimbam 3>, <&slimbam 4>;
+ dma-names = "rx", "tx";
#address-cells = <1>;
#size-cells = <0>;
- ngd@1 {
+ slim@1 {
reg = <1>;
- #address-cells = <1>;
- #size-cells = <1>;
+ #address-cells = <2>;
+ #size-cells = <0>;
- tasha_ifd: tas-ifd {
+ tasha_ifd: tas-ifd@0,0 {
compatible = "slim217,1a0";
reg = <0 0>;
};
- wcd9335: codec@1{
+ wcd9335: codec@1,0 {
pinctrl-0 = <&cdc_reset_active &wcd_intr_default>;
pinctrl-names = "default";
@@ -3342,7 +3385,7 @@
interrupt-names = "intr1", "intr2";
interrupt-controller;
#interrupt-cells = <1>;
- reset-gpios = <&tlmm 64 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&tlmm 64 GPIO_ACTIVE_LOW>;
slim-ifc-dev = <&tasha_ifd>;
@@ -3393,12 +3436,12 @@
#address-cells = <1>;
#size-cells = <0>;
- q6core {
+ service@3 {
reg = <APR_SVC_ADSP_CORE>;
compatible = "qcom,q6core";
};
- q6afe: q6afe {
+ q6afe: service@4 {
compatible = "qcom,q6afe";
reg = <APR_SVC_AFE>;
q6afedai: dais {
@@ -3406,13 +3449,13 @@
#address-cells = <1>;
#size-cells = <0>;
#sound-dai-cells = <1>;
- hdmi@1 {
+ dai@1 {
reg = <1>;
};
};
};
- q6asm: q6asm {
+ q6asm: service@7 {
compatible = "qcom,q6asm";
reg = <APR_SVC_ASM>;
q6asmdai: dais {
@@ -3424,7 +3467,7 @@
};
};
- q6adm: q6adm {
+ q6adm: service@8 {
compatible = "qcom,q6adm";
reg = <APR_SVC_ADM>;
q6routing: routing {
diff --git a/arch/arm64/boot/dts/qcom/msm8996-xiaomi-natrium.dts b/arch/arm64/boot/dts/qcom/msm8996pro-xiaomi-natrium.dts
index ff4673ee9e81..d18d0b0eda95 100644
--- a/arch/arm64/boot/dts/qcom/msm8996-xiaomi-natrium.dts
+++ b/arch/arm64/boot/dts/qcom/msm8996pro-xiaomi-natrium.dts
@@ -5,6 +5,7 @@
/dts-v1/;
+#include "msm8996pro.dtsi"
#include "msm8996-xiaomi-common.dtsi"
#include "pmi8996.dtsi"
#include <dt-bindings/sound/qcom,q6afe.h>
@@ -12,7 +13,7 @@
/ {
model = "Xiaomi Mi 5s Plus";
- compatible = "xiaomi,natrium", "qcom,msm8996";
+ compatible = "xiaomi,natrium", "qcom,msm8996pro", "qcom,msm8996";
chassis-type = "handset";
qcom,msm-id = <305 0x10000>;
qcom,board-id = <47 0>;
@@ -164,7 +165,7 @@
};
&rpm_requests {
- pm8994-regulators {
+ regulators-0 {
vreg_l3a_0p875: l3 {
regulator-name = "vreg_l3a_0p875";
regulator-min-microvolt = <850000>;
@@ -398,14 +399,14 @@
"RFFE1_DATA", /* GPIO_148 */
"RFFE1_CLK"; /* GPIO_149 */
- touchscreen_default: touchscreen-default {
+ touchscreen_default: touchscreen-default-state {
pins = "gpio89", "gpio125";
function = "gpio";
drive-strength = <10>;
bias-pull-up;
};
- touchscreen_sleep: touchscreen-sleep {
+ touchscreen_sleep: touchscreen-sleep-state {
pins = "gpio89", "gpio125";
function = "gpio";
drive-strength = <2>;
diff --git a/arch/arm64/boot/dts/qcom/msm8996-xiaomi-scorpio.dts b/arch/arm64/boot/dts/qcom/msm8996pro-xiaomi-scorpio.dts
index 79be5fb1295b..5e3b9130e9c2 100644
--- a/arch/arm64/boot/dts/qcom/msm8996-xiaomi-scorpio.dts
+++ b/arch/arm64/boot/dts/qcom/msm8996pro-xiaomi-scorpio.dts
@@ -5,6 +5,7 @@
/dts-v1/;
+#include "msm8996pro.dtsi"
#include "msm8996-xiaomi-common.dtsi"
#include "pmi8996.dtsi"
#include <dt-bindings/sound/qcom,q6afe.h>
@@ -13,7 +14,7 @@
/ {
model = "Xiaomi Mi Note 2";
- compatible = "xiaomi,scorpio", "qcom,msm8996";
+ compatible = "xiaomi,scorpio", "qcom,msm8996pro", "qcom,msm8996";
chassis-type = "handset";
qcom,msm-id = <305 0x10000>;
qcom,board-id = <34 0>;
@@ -216,7 +217,7 @@
};
&rpm_requests {
- pm8994-regulators {
+ regulators-0 {
vreg_l3a_0p875: l3 {
regulator-name = "vreg_l3a_0p875";
regulator-min-microvolt = <850000>;
@@ -468,28 +469,28 @@
"RFFE1_DATA", /* GPIO_148 */
"RFFE1_CLK"; /* GPIO_149 */
- touchkey_default: touchkey_default {
+ touchkey_default: touchkey-default-state {
pins = "gpio77";
function = "gpio";
drive-strength = <16>;
bias-pull-up;
};
- touchkey_sleep: touchkey_sleep {
+ touchkey_sleep: touchkey-sleep-state {
pins = "gpio77";
function = "gpio";
drive-strength = <2>;
bias-disable;
};
- touchscreen_default: touchscreen_default {
+ touchscreen_default: touchscreen-default-state {
pins = "gpio75", "gpio125";
function = "gpio";
drive-strength = <10>;
bias-pull-up;
};
- touchscreen_sleep: touchscreen_sleep {
+ touchscreen_sleep: touchscreen-sleep-state {
pins = "gpio75", "gpio125";
function = "gpio";
drive-strength = <2>;
diff --git a/arch/arm64/boot/dts/qcom/msm8996pro.dtsi b/arch/arm64/boot/dts/qcom/msm8996pro.dtsi
new file mode 100644
index 000000000000..a679a9c0cf99
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8996pro.dtsi
@@ -0,0 +1,291 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+#include "msm8996.dtsi"
+
+/ {
+ /delete-node/ opp-table-cluster0;
+ /delete-node/ opp-table-cluster1;
+
+ /*
+ * On MSM8996 Pro the cpufreq driver shifts speed bins into the high
+ * nibble of supported hw, so speed bin 0 becomes 0x10, speed bin 1
+ * becomes 0x20, speed 2 becomes 0x40.
+ */
+
+ cluster0_opp: opp-table-cluster0 {
+ compatible = "operating-points-v2-kryo-cpu";
+ nvmem-cells = <&speedbin_efuse>;
+ opp-shared;
+
+ opp-307200000 {
+ opp-hz = /bits/ 64 <307200000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-384000000 {
+ opp-hz = /bits/ 64 <384000000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-460800000 {
+ opp-hz = /bits/ 64 <460800000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-537600000 {
+ opp-hz = /bits/ 64 <537600000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-614400000 {
+ opp-hz = /bits/ 64 <614400000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-691200000 {
+ opp-hz = /bits/ 64 <691200000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-768000000 {
+ opp-hz = /bits/ 64 <768000000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-844800000 {
+ opp-hz = /bits/ 64 <844800000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-902400000 {
+ opp-hz = /bits/ 64 <902400000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-979200000 {
+ opp-hz = /bits/ 64 <979200000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1056000000 {
+ opp-hz = /bits/ 64 <1056000000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1132800000 {
+ opp-hz = /bits/ 64 <1132800000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1209600000 {
+ opp-hz = /bits/ 64 <1209600000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1286400000 {
+ opp-hz = /bits/ 64 <1286400000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1363200000 {
+ opp-hz = /bits/ 64 <1363200000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1440000000 {
+ opp-hz = /bits/ 64 <1440000000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1516800000 {
+ opp-hz = /bits/ 64 <1516800000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1593600000 {
+ opp-hz = /bits/ 64 <1593600000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1996800000 {
+ opp-hz = /bits/ 64 <1996800000>;
+ opp-supported-hw = <0x20>;
+ clock-latency-ns = <200000>;
+ };
+ opp-2188800000 {
+ opp-hz = /bits/ 64 <2188800000>;
+ opp-supported-hw = <0x10>;
+ clock-latency-ns = <200000>;
+ };
+ };
+
+ cluster1_opp: opp-table-cluster1 {
+ compatible = "operating-points-v2-kryo-cpu";
+ nvmem-cells = <&speedbin_efuse>;
+ opp-shared;
+
+ opp-307200000 {
+ opp-hz = /bits/ 64 <307200000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-384000000 {
+ opp-hz = /bits/ 64 <384000000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-460800000 {
+ opp-hz = /bits/ 64 <460800000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-537600000 {
+ opp-hz = /bits/ 64 <537600000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-614400000 {
+ opp-hz = /bits/ 64 <614400000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-691200000 {
+ opp-hz = /bits/ 64 <691200000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-748800000 {
+ opp-hz = /bits/ 64 <748800000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-825600000 {
+ opp-hz = /bits/ 64 <825600000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-902400000 {
+ opp-hz = /bits/ 64 <902400000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-979200000 {
+ opp-hz = /bits/ 64 <979200000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1056000000 {
+ opp-hz = /bits/ 64 <1056000000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1132800000 {
+ opp-hz = /bits/ 64 <1132800000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1209600000 {
+ opp-hz = /bits/ 64 <1209600000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1286400000 {
+ opp-hz = /bits/ 64 <1286400000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1363200000 {
+ opp-hz = /bits/ 64 <1363200000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1440000000 {
+ opp-hz = /bits/ 64 <1440000000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1516800000 {
+ opp-hz = /bits/ 64 <1516800000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1593600000 {
+ opp-hz = /bits/ 64 <1593600000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1670400000 {
+ opp-hz = /bits/ 64 <1670400000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1747200000 {
+ opp-hz = /bits/ 64 <1747200000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1824000000 {
+ opp-hz = /bits/ 64 <1824000000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1900800000 {
+ opp-hz = /bits/ 64 <1900800000>;
+ opp-supported-hw = <0x70>;
+ clock-latency-ns = <200000>;
+ };
+ opp-1977600000 {
+ opp-hz = /bits/ 64 <1977600000>;
+ opp-supported-hw = <0x30>;
+ clock-latency-ns = <200000>;
+ };
+ opp-2054400000 {
+ opp-hz = /bits/ 64 <2054400000>;
+ opp-supported-hw = <0x30>;
+ clock-latency-ns = <200000>;
+ };
+ opp-2150400000 {
+ opp-hz = /bits/ 64 <2150400000>;
+ opp-supported-hw = <0x30>;
+ clock-latency-ns = <200000>;
+ };
+ opp-2246400000 {
+ opp-hz = /bits/ 64 <2246400000>;
+ opp-supported-hw = <0x10>;
+ clock-latency-ns = <200000>;
+ };
+ opp-2342400000 {
+ opp-hz = /bits/ 64 <2342400000>;
+ opp-supported-hw = <0x10>;
+ clock-latency-ns = <200000>;
+ };
+ };
+};
+
+&gpu_opp_table {
+ /*
+ * Unlike CPU opp tables, the GPU driver does not shift speed bins.
+ *
+ * 652.8 Mhz is available on speed bin 0 only.
+ * 624 Mhz and 560 Mhz are available on speed bins 0 and 1.
+ * All the rest are available on all bins of the hardware (like on
+ * plain 8996).
+ */
+
+ opp-652800000 {
+ opp-hz = /bits/ 64 <652800000>;
+ opp-supported-hw = <0x01>;
+ };
+ opp-624000000 {
+ opp-hz = /bits/ 64 <624000000>;
+ opp-supported-hw = <0x03>;
+ };
+ opp-560000000 {
+ opp-hz = /bits/ 64 <560000000>;
+ opp-supported-hw = <0x03>;
+ };
+ /* The rest is inherited from msm8996 */
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi b/arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi
index 7928b8197474..3b7172aa4037 100644
--- a/arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8998-clamshell.dtsi
@@ -35,7 +35,7 @@
};
&blsp1_uart3_on {
- rx {
+ rx-pins {
/delete-property/ bias-disable;
/*
* Configure a pull-up on 45 (RX). This is needed to
@@ -46,7 +46,7 @@
bias-pull-up;
};
- cts {
+ cts-pins {
/delete-property/ bias-disable;
/*
* Configure a pull-down on 47 (CTS) to match the pull
@@ -137,7 +137,7 @@
};
&rpm_requests {
- pm8998-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pm8998-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -357,8 +357,9 @@
&tlmm {
gpio-reserved-ranges = <0 4>, <81 4>;
- touchpad: touchpad-pin {
+ touchpad: touchpad-pin-state {
pins = "gpio123";
+ function = "gpio";
bias-pull-up;
};
};
diff --git a/arch/arm64/boot/dts/qcom/msm8998-fxtec-pro1.dts b/arch/arm64/boot/dts/qcom/msm8998-fxtec-pro1.dts
index 429ba57e20f7..310f7a2df1e8 100644
--- a/arch/arm64/boot/dts/qcom/msm8998-fxtec-pro1.dts
+++ b/arch/arm64/boot/dts/qcom/msm8998-fxtec-pro1.dts
@@ -216,7 +216,7 @@
};
&blsp1_uart3_on {
- rx {
+ rx-pins {
/delete-property/ bias-disable;
/*
* Configure a pull-up on 45 (RX). This is needed to
@@ -227,7 +227,7 @@
bias-pull-up;
};
- cts {
+ cts-pins {
/delete-property/ bias-disable;
/*
* Configure a pull-down on 47 (CTS) to match the pull
@@ -310,15 +310,11 @@
};
&funnel4 {
- // FIXME: Figure out why clock late_initcall crashes the board with
- // this enabled.
- // status = "okay";
+ /* FIXME: Figure out why clock late_initcall crashes the board with this enabled. */
};
&funnel5 {
- // FIXME: Figure out why clock late_initcall crashes the board with
- // this enabled.
- // status = "okay";
+ /* FIXME: Figure out why clock late_initcall crashes the board with this enabled. */
};
&pcie0 {
@@ -390,7 +386,7 @@
};
&rpm_requests {
- pm8998-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pm8998-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -588,7 +584,7 @@
};
- pmi8998-regulators {
+ regulators-1 {
compatible = "qcom,rpm-pmi8998-regulators";
vdd_bob-supply = <&vph_pwr>;
@@ -615,14 +611,14 @@
&tlmm {
gpio-reserved-ranges = <0 4>;
- mdp_vsync_n: mdp-vsync-n {
+ mdp_vsync_n: mdp-vsync-n-state {
pins = "gpio10";
function = "mdp_vsync_a";
bias-pull-down;
drive-strength = <2>;
};
- gpio_kb_pins_extra: gpio-kb-pins-extra {
+ gpio_kb_pins_extra: gpio-kb-pins-extra-state {
pins = "gpio21", "gpio32", "gpio33", "gpio114",
"gpio128", "gpio129";
function = "gpio";
@@ -630,21 +626,21 @@
bias-pull-up;
};
- ts_vio_default: ts-vio-def {
+ ts_vio_default: ts-vio-def-state {
pins = "gpio81";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
- ts_rst_n: ts-rst-n {
+ ts_rst_n: ts-rst-n-state {
pins = "gpio89";
function = "gpio";
bias-pull-up;
drive-strength = <8>;
};
- hall_sensor1_default: hall-sensor1-def {
+ hall_sensor1_default: hall-sensor1-def-state {
pins = "gpio124";
function = "gpio";
bias-disable;
@@ -652,7 +648,7 @@
input-enable;
};
- ts_int_n: ts-int-n {
+ ts_int_n: ts-int-n-state {
pins = "gpio125";
function = "gpio";
bias-disable;
diff --git a/arch/arm64/boot/dts/qcom/msm8998-lenovo-miix-630.dts b/arch/arm64/boot/dts/qcom/msm8998-lenovo-miix-630.dts
index cf81c33a9d7e..a105143bee4a 100644
--- a/arch/arm64/boot/dts/qcom/msm8998-lenovo-miix-630.dts
+++ b/arch/arm64/boot/dts/qcom/msm8998-lenovo-miix-630.dts
@@ -28,8 +28,8 @@
};
&remoteproc_mss {
- firmware-name = "qcom/LENOVO/81F1/qcdsp1v28998.mbn",
- "qcom/LENOVO/81F1/qcdsp28998.mbn";
+ firmware-name = "qcom/msm8998/LENOVO/81F1/qcdsp1v28998.mbn",
+ "qcom/msm8998/LENOVO/81F1/qcdsp28998.mbn";
};
&sdhc2 {
diff --git a/arch/arm64/boot/dts/qcom/msm8998-mtp.dts b/arch/arm64/boot/dts/qcom/msm8998-mtp.dts
index a3ca58100aee..453a1c9e9808 100644
--- a/arch/arm64/boot/dts/qcom/msm8998-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/msm8998-mtp.dts
@@ -46,7 +46,7 @@
};
&blsp1_uart3_on {
- rx {
+ rx-pins {
/delete-property/ bias-disable;
/*
* Configure a pull-up on 45 (RX). This is needed to
@@ -57,7 +57,7 @@
bias-pull-up;
};
- cts {
+ cts-pins {
/delete-property/ bias-disable;
/*
* Configure a pull-down on 47 (CTS) to match the pull
@@ -124,15 +124,11 @@
};
&funnel4 {
- // FIXME: Figure out why clock late_initcall crashes the board with
- // this enabled.
- // status = "okay";
+ /* FIXME: Figure out why clock late_initcall crashes the board with this enabled. */
};
&funnel5 {
- // FIXME: Figure out why clock late_initcall crashes the board with
- // this enabled.
- // status = "okay";
+ /* FIXME: Figure out why clock late_initcall crashes the board with this enabled. */
};
&pcie0 {
@@ -168,7 +164,7 @@
};
&rpm_requests {
- pm8998-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pm8998-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -366,7 +362,7 @@
};
- pmi8998-regulators {
+ regulators-1 {
compatible = "qcom,rpm-pmi8998-regulators";
vdd_bob-supply = <&vph_pwr>;
diff --git a/arch/arm64/boot/dts/qcom/msm8998-oneplus-cheeseburger.dts b/arch/arm64/boot/dts/qcom/msm8998-oneplus-cheeseburger.dts
index ef2a88a64d32..9fb1fb9b8529 100644
--- a/arch/arm64/boot/dts/qcom/msm8998-oneplus-cheeseburger.dts
+++ b/arch/arm64/boot/dts/qcom/msm8998-oneplus-cheeseburger.dts
@@ -22,7 +22,7 @@
pinctrl-names = "default";
pinctrl-0 = <&button_backlight_default>;
- button-backlight {
+ led-keypad-backlight {
gpios = <&pmi8998_gpio 5 GPIO_ACTIVE_HIGH>;
color = <LED_COLOR_ID_WHITE>;
function = LED_FUNCTION_KBD_BACKLIGHT;
@@ -33,11 +33,9 @@
&pmi8998_gpio {
button_backlight_default: button-backlight-state {
- pinconf {
- pins = "gpio5";
- function = "normal";
- bias-pull-down;
- qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
- };
+ pins = "gpio5";
+ function = "gpio";
+ bias-pull-down;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/msm8998-oneplus-common.dtsi b/arch/arm64/boot/dts/qcom/msm8998-oneplus-common.dtsi
index 62bda23791bb..7d4a67d07501 100644
--- a/arch/arm64/boot/dts/qcom/msm8998-oneplus-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8998-oneplus-common.dtsi
@@ -233,7 +233,7 @@
};
&blsp1_uart3_on {
- rx {
+ rx-pins {
/delete-property/ bias-disable;
/*
* Configure a pull-up on 46 (RX). This is needed to
@@ -244,7 +244,7 @@
bias-pull-up;
};
- cts {
+ cts-pins {
/delete-property/ bias-disable;
/*
* Configure a pull-down on 47 (CTS) to match the pull
@@ -279,6 +279,10 @@
};
};
+&pmi8998_rradc {
+ status = "okay";
+};
+
&qusb2phy {
status = "okay";
@@ -288,7 +292,7 @@
};
&rpm_requests {
- pm8998-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pm8998-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -477,7 +481,7 @@
vreg_lvs2a_1p8: lvs2 { };
};
- pmi8998-regulators {
+ regulators-1 {
compatible = "qcom,rpm-pmi8998-regulators";
vdd_bob-supply = <&vph_pwr>;
@@ -492,7 +496,7 @@
&tlmm {
gpio-reserved-ranges = <0 4>, <81 4>;
- hall_sensor_default: hall-sensor-default {
+ hall_sensor_default: hall-sensor-default-state {
pins = "gpio124";
function = "gpio";
drive-strength = <2>;
@@ -500,28 +504,28 @@
input-enable;
};
- ts_int_active: ts-int-active {
+ ts_int_active: ts-int-active-state {
pins = "gpio125";
function = "gpio";
drive-strength = <8>;
bias-pull-up;
};
- ts_reset_active: ts-reset-active {
+ ts_reset_active: ts-reset-active-state {
pins = "gpio89";
function = "gpio";
drive-strength = <8>;
bias-pull-up;
};
- nfc_int_active: nfc-int-active {
+ nfc_int_active: nfc-int-active-state {
pins = "gpio92";
function = "gpio";
drive-strength = <6>;
bias-pull-up;
};
- nfc_enable_active: nfc-enable-active {
+ nfc_enable_active: nfc-enable-active-state {
pins = "gpio12", "gpio116";
function = "gpio";
drive-strength = <6>;
diff --git a/arch/arm64/boot/dts/qcom/msm8998-sony-xperia-yoshino.dtsi b/arch/arm64/boot/dts/qcom/msm8998-sony-xperia-yoshino.dtsi
index d08639082247..5da87baa2b23 100644
--- a/arch/arm64/boot/dts/qcom/msm8998-sony-xperia-yoshino.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8998-sony-xperia-yoshino.dtsi
@@ -375,7 +375,7 @@
};
&rpm_requests {
- pm8998-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pm8998-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -410,135 +410,166 @@
regulator-min-microvolt = <1352000>;
regulator-max-microvolt = <1352000>;
};
+
vreg_s4a_1p8: s4 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-system-load = <100000>;
regulator-allow-set-load;
};
+
vreg_s5a_2p04: s5 {
regulator-min-microvolt = <1904000>;
regulator-max-microvolt = <2032000>;
};
+
vreg_s7a_1p025: s7 {
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <1028000>;
};
+
vreg_l1a_0p875: l1 {
regulator-min-microvolt = <880000>;
regulator-max-microvolt = <880000>;
regulator-system-load = <73400>;
regulator-allow-set-load;
};
+
vreg_l2a_1p2: l2 {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-system-load = <12560>;
regulator-allow-set-load;
};
+
vreg_l3a_1p0: l3 {
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
};
+
vreg_l5a_0p8: l5 {
regulator-min-microvolt = <800000>;
regulator-max-microvolt = <800000>;
};
+
vreg_l6a_1p8: l6 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
+
vreg_l7a_1p8: l7 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
+
vreg_l8a_1p2: l8 {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
};
+
vreg_l9a_1p8: l9 {
regulator-min-microvolt = <1808000>;
regulator-max-microvolt = <2960000>;
};
+
vreg_l10a_1p8: l10 {
regulator-min-microvolt = <1808000>;
regulator-max-microvolt = <2960000>;
};
+
vreg_l11a_1p0: l11 {
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
};
+
vreg_l12a_1p8: l12 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
+
vreg_l13a_2p95: l13 {
regulator-min-microvolt = <1808000>;
regulator-max-microvolt = <2960000>;
regulator-allow-set-load;
};
+
vreg_l14a_1p85: l14 {
regulator-min-microvolt = <1848000>;
regulator-max-microvolt = <1856000>;
regulator-system-load = <32000>;
regulator-allow-set-load;
};
+
vreg_l15a_1p8: l15 {
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
};
+
vreg_l16a_2p7: l16 {
regulator-min-microvolt = <2704000>;
regulator-max-microvolt = <2704000>;
};
+
vreg_l17a_1p3: l17 {
regulator-min-microvolt = <1304000>;
regulator-max-microvolt = <1304000>;
};
- vreg_l18a_2p85: l18 {};
+
+ vreg_l18a_2p85: l18 { };
+
vreg_l19a_2p7: l19 {
regulator-min-microvolt = <2696000>;
regulator-max-microvolt = <2704000>;
};
+
vreg_l20a_2p95: l20 {
regulator-min-microvolt = <2960000>;
regulator-max-microvolt = <2960000>;
regulator-system-load = <10000>;
regulator-allow-set-load;
};
+
vreg_l21a_2p95: l21 {
regulator-min-microvolt = <2960000>;
regulator-max-microvolt = <2960000>;
regulator-system-load = <800000>;
regulator-allow-set-load;
};
+
vreg_l22a_2p85: l22 { };
+
vreg_l23a_3p3: l23 {
regulator-min-microvolt = <3312000>;
regulator-max-microvolt = <3312000>;
};
+
vreg_l24a_3p075: l24 {
regulator-min-microvolt = <3088000>;
regulator-max-microvolt = <3088000>;
};
+
vreg_l25a_3p3: l25 {
regulator-min-microvolt = <3104000>;
regulator-max-microvolt = <3312000>;
};
+
vreg_l26a_1p2: l26 {
regulator-min-microvolt = <1200000>;
regulator-max-microvolt = <1200000>;
regulator-allow-set-load;
};
+
vreg_l28_3p0: l28 {
regulator-min-microvolt = <3000000>;
regulator-max-microvolt = <3000000>;
};
+
vreg_lvs1a_1p8: lvs1 { };
+
vreg_lvs2a_1p8: lvs2 { };
};
- pmi8998-regulators {
+ regulators-1 {
compatible = "qcom,rpm-pmi8998-regulators";
vdd_bob-supply = <&vph_pwr>;
@@ -565,14 +596,14 @@
&tlmm {
gpio-reserved-ranges = <0 4>, <81 4>;
- mdp_vsync_n: mdp-vsync-n {
+ mdp_vsync_n: mdp-vsync-n-state {
pins = "gpio10";
function = "mdp_vsync_a";
drive-strength = <2>;
bias-pull-down;
};
- nfc_ven: nfc-ven {
+ nfc_ven: nfc-ven-state {
pins = "gpio12";
function = "gpio";
bias-disable;
@@ -580,42 +611,42 @@
output-low;
};
- msm_mclk0_default: msm-mclk0-active {
+ msm_mclk0_default: msm-mclk0-active-state {
pins = "gpio13";
function = "cam_mclk";
drive-strength = <2>;
bias-disable;
};
- msm_mclk1_default: msm-mclk1-active {
+ msm_mclk1_default: msm-mclk1-active-state {
pins = "gpio14";
function = "cam_mclk";
drive-strength = <2>;
bias-disable;
};
- cci0_default: cci0-default {
+ cci0_default: cci0-default-state {
pins = "gpio18", "gpio19";
function = "cci_i2c";
bias-disable;
drive-strength = <2>;
};
- cci1_default: cci1-default {
+ cci1_default: cci1-default-state {
pins = "gpio19", "gpio20";
function = "cci_i2c";
bias-disable;
drive-strength = <2>;
};
- cam0_vdig_default: cam0-vdig-default {
+ cam0_vdig_default: cam0-vdig-default-state {
pins = "gpio21";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
- tof_int: tof-int {
+ tof_int: tof-int-state {
pins = "gpio22";
function = "gpio";
bias-pull-up;
@@ -623,28 +654,28 @@
input-enable;
};
- cam1_vdig_default: cam1-vdig-default {
+ cam1_vdig_default: cam1-vdig-default-state {
pins = "gpio25";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
- usb_extcon_active: usb-extcon-active {
+ usb_extcon_active: usb-extcon-active-state {
pins = "gpio38";
function = "gpio";
bias-disable;
drive-strength = <16>;
};
- tof_reset: tof-reset {
+ tof_reset: tof-reset-state {
pins = "gpio27";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
- hall_sensor0_default: acc-cover-open {
+ hall_sensor0_default: acc-cover-open-state {
pins = "gpio124";
function = "gpio";
bias-disable;
@@ -652,14 +683,14 @@
input-enable;
};
- ts_int_n: ts-int-n {
+ ts_int_n: ts-int-n-state {
pins = "gpio125";
function = "gpio";
drive-strength = <8>;
bias-pull-up;
};
- usb_vbus_active: usb-vbus-active {
+ usb_vbus_active: usb-vbus-active-state {
pins = "gpio128";
function = "gpio";
bias-disable;
@@ -667,7 +698,7 @@
output-low;
};
- ts_vddio_en: ts-vddio-en-default {
+ ts_vddio_en: ts-vddio-en-default-state {
pins = "gpio133";
function = "gpio";
bias-disable;
diff --git a/arch/arm64/boot/dts/qcom/msm8998-xiaomi-sagit.dts b/arch/arm64/boot/dts/qcom/msm8998-xiaomi-sagit.dts
new file mode 100644
index 000000000000..b1aac7311ef9
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8998-xiaomi-sagit.dts
@@ -0,0 +1,711 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Xiaomi Mi 6 (sagit) device tree source based on msm8998-mtp.dtsi
+ *
+ * Copyright (c) 2022, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022, Degdag Mohamed <degdagmohamed@gmail.com>
+ * Copyright (c) 2022, Dzmitry Sankouski <dsankouski@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "msm8998.dtsi"
+#include "pm8005.dtsi"
+#include "pm8998.dtsi"
+#include "pmi8998.dtsi"
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+
+/*
+ * Delete following upstream (msm8998.dtsi) reserved
+ * memory mappings which are different in this device.
+ */
+/delete-node/ &adsp_mem;
+/delete-node/ &mpss_mem;
+/delete-node/ &venus_mem;
+/delete-node/ &mba_mem;
+/delete-node/ &slpi_mem;
+/delete-node/ &ipa_fw_mem;
+/delete-node/ &ipa_gsi_mem;
+/delete-node/ &gpu_mem;
+/delete-node/ &wlan_msa_mem;
+
+/ {
+ model = "Xiaomi Mi 6";
+ compatible = "xiaomi,sagit", "qcom,msm8998";
+ chassis-type = "handset";
+ /* Required for bootloader to select correct board */
+ qcom,board-id = <30 0>;
+
+ reserved-memory {
+ /*
+ * Xiaomi's ADSP firmware requires 30 MiB in total, so increase the adsp_mem
+ * region by 4 MiB to account for this while relocating the other now
+ * conflicting memory nodes accordingly.
+ */
+ adsp_mem: memory@8b200000 {
+ reg = <0x0 0x8b200000 0x0 0x1e00000>;
+ no-map;
+ };
+
+ mpss_mem: memory@8d000000 {
+ reg = <0x0 0x8d000000 0x0 0x7000000>;
+ no-map;
+ };
+
+ venus_mem: memory@94000000 {
+ reg = <0x0 0x94000000 0x0 0x500000>;
+ no-map;
+ };
+
+ mba_mem: memory@94500000 {
+ reg = <0x0 0x94500000 0x0 0x200000>;
+ no-map;
+ };
+
+ slpi_mem: memory@94700000 {
+ reg = <0x0 0x94700000 0x0 0xf00000>;
+ no-map;
+ };
+
+ ipa_fw_mem: memory@95600000 {
+ reg = <0x0 0x95600000 0x0 0x10000>;
+ no-map;
+ };
+
+ ipa_gsi_mem: memory@95610000 {
+ reg = <0x0 0x95610000 0x0 0x5000>;
+ no-map;
+ };
+
+ gpu_mem: memory@95615000 {
+ reg = <0x0 0x95615000 0x0 0x100000>;
+ no-map;
+ };
+
+ wlan_msa_mem: memory@95715000 {
+ reg = <0x0 0x95715000 0x0 0x100000>;
+ no-map;
+ };
+
+ /* Bootloader display framebuffer region */
+ cont_splash_mem: memory@9d400000 {
+ reg = <0x0 0x9d400000 0x0 0x2400000>;
+ no-map;
+ };
+
+ /* For getting crash logs using Android downstream kernels */
+ ramoops@ac000000 {
+ compatible = "ramoops";
+ reg = <0x0 0xac000000 0x0 0x200000>;
+ console-size = <0x80000>;
+ pmsg-size = <0x40000>;
+ record-size = <0x8000>;
+ ftrace-size = <0x20000>;
+ };
+
+ /*
+ * The following memory regions on downstream are "dynamically allocated"
+ * but given the same addresses every time. Hard code them as these addresses
+ * are where the Xiaomi signed firmware expects them to be.
+ */
+ ipa_fws_region: memory@f7800000 {
+ compatible = "shared-dma-pool";
+ reg = <0x0 0xf7800000 0x0 0x5000>;
+ no-map;
+ };
+
+ zap_shader_region: memory@f7900000 {
+ compatible = "shared-dma-pool";
+ reg = <0x0 0xf7900000 0x0 0x2000>;
+ no-map;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ label = "Volume buttons";
+ autorepeat;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&vol_up_key_default>;
+
+ key-vol-up {
+ label = "Volume up";
+ gpios = <&pm8998_gpio 6 GPIO_ACTIVE_LOW>;
+ linux,code = <KEY_VOLUMEUP>;
+ debounce-interval = <15>;
+ wakeup-source;
+ };
+ };
+
+ gpio-hall-sensor {
+ compatible = "gpio-keys";
+ label = "Hall effect sensor";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&hall_sensor_default_state>;
+
+ event-hall-sensor {
+ label = "Hall Effect Sensor";
+ gpios = <&tlmm 124 GPIO_ACTIVE_LOW>;
+ linux,input-type = <EV_SW>;
+ linux,code = <SW_LID>;
+ linux,can-disable;
+ wakeup-source;
+ };
+ };
+
+ vph_pwr: vph-pwr-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vph_pwr";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ disp_vddts_vreg: disp-vddts-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "disp-vddts-regulator";
+ gpio = <&tlmm 50 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-boot-on;
+ };
+};
+
+&blsp1_i2c5 {
+ pinctrl-names = "default", "sleep";
+ status = "okay";
+
+ touchscreen@20 {
+ compatible = "syna,rmi4-i2c";
+ reg = <0x20>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ interrupt-parent = <&tlmm>;
+ interrupts = <125 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&ts_active_state>;
+ pinctrl-1 = <&ts_int_suspend_state &ts_reset_suspend_state>;
+
+ vdd-supply = <&disp_vddts_vreg>;
+ vio-supply = <&vreg_l6a_1p8>;
+
+ syna,reset-delay-ms = <20>;
+ syna,startup-delay-ms = <20>;
+
+ rmi4-f01@1 {
+ reg = <0x01>;
+ syna,nosleep-mode = <1>;
+ };
+
+ rmi4-f12@12 {
+ reg = <0x12>;
+ touchscreen-x-mm = <64>;
+ touchscreen-y-mm = <114>;
+ syna,sensor-type = <1>;
+ syna,rezero-wait-ms = <20>;
+ };
+
+ rmi4-f1a@1a {
+ reg = <0x1a>;
+ syna,codes = <KEY_BACK KEY_APPSELECT>;
+ };
+ };
+};
+
+&blsp1_i2c5_sleep {
+ /delete-property/ bias-pull-up;
+ bias-disable;
+};
+
+&blsp1_uart3 {
+ status = "okay";
+
+ bluetooth {
+ compatible = "qcom,wcn3990-bt";
+
+ vddio-supply = <&vreg_s4a_1p8>;
+ vddxo-supply = <&vreg_l7a_1p8>;
+ vddrf-supply = <&vreg_l17a_1p3>;
+ vddch0-supply = <&vreg_l25a_3p3>;
+ max-speed = <3200000>;
+ };
+};
+
+&blsp1_uart3_on {
+ rx-pins {
+ /delete-property/ bias-disable;
+ /*
+ * Configure a pull-up on 46 (RX). This is needed to
+ * avoid garbage data when the TX pin of the Bluetooth
+ * module is in tri-state (module powered off or not
+ * driving the signal yet).
+ */
+ bias-pull-up;
+ };
+
+ cts-pins {
+ /delete-property/ bias-disable;
+ /*
+ * Configure a pull-down on 47 (CTS) to match the pull
+ * of the Bluetooth module.
+ */
+ bias-pull-down;
+ };
+};
+
+&blsp2_uart1 {
+ status = "okay";
+};
+
+&pm8005_regulators {
+ compatible = "qcom,pm8005-regulators";
+
+ vdd_s1-supply = <&vph_pwr>;
+
+ pm8005_s1: s1 { /* VDD_GFX supply */
+ regulator-min-microvolt = <524000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-enable-ramp-delay = <500>;
+
+ /* hack until we rig up the gpu consumer */
+ regulator-always-on;
+ };
+};
+
+&pm8998_gpio {
+ vol_up_key_default: vol-up-key-default-state {
+ pins = "gpio6";
+ function = "normal";
+ bias-pull-up;
+ input-enable;
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
+ };
+
+ audio_mclk_pin: audio-mclk-pin-active-state {
+ pins = "gpio13";
+ function = "func2";
+ power-source = <0>;
+ };
+};
+
+&qusb2phy {
+ vdd-supply = <&vreg_l1a_0p875>;
+ vdda-pll-supply = <&vreg_l12a_1p8>;
+ vdda-phy-dpdm-supply = <&vreg_l24a_3p075>;
+ status = "okay";
+};
+
+&rpm_requests {
+ regulators-0 {
+ compatible = "qcom,rpm-pm8998-regulators";
+
+ vdd_s1-supply = <&vph_pwr>;
+ vdd_s2-supply = <&vph_pwr>;
+ vdd_s3-supply = <&vph_pwr>;
+ vdd_s4-supply = <&vph_pwr>;
+ vdd_s5-supply = <&vph_pwr>;
+ vdd_s6-supply = <&vph_pwr>;
+ vdd_s7-supply = <&vph_pwr>;
+ vdd_s8-supply = <&vph_pwr>;
+ vdd_s9-supply = <&vph_pwr>;
+ vdd_s10-supply = <&vph_pwr>;
+ vdd_s11-supply = <&vph_pwr>;
+ vdd_s12-supply = <&vph_pwr>;
+ vdd_s13-supply = <&vph_pwr>;
+ vdd_l1_l27-supply = <&vreg_s7a_1p025>;
+ vdd_l2_l8_l17-supply = <&vreg_s3a_1p35>;
+ vdd_l3_l11-supply = <&vreg_s7a_1p025>;
+ vdd_l4_l5-supply = <&vreg_s7a_1p025>;
+ vdd_l6-supply = <&vreg_s5a_2p04>;
+ vdd_l7_l12_l14_l15-supply = <&vreg_s5a_2p04>;
+ vdd_l9-supply = <&vreg_bob>;
+ vdd_l10_l23_l25-supply = <&vreg_bob>;
+ vdd_l13_l19_l21-supply = <&vreg_bob>;
+ vdd_l16_l28-supply = <&vreg_bob>;
+ vdd_l18_l22-supply = <&vreg_bob>;
+ vdd_l20_l24-supply = <&vreg_bob>;
+ vdd_l26-supply = <&vreg_s3a_1p35>;
+ vdd_lvs1_lvs2-supply = <&vreg_s4a_1p8>;
+
+ vreg_s3a_1p35: s3 {
+ regulator-min-microvolt = <1352000>;
+ regulator-max-microvolt = <1352000>;
+ };
+
+ vreg_s4a_1p8: s4 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-allow-set-load;
+ };
+
+ vreg_s5a_2p04: s5 {
+ regulator-min-microvolt = <1904000>;
+ regulator-max-microvolt = <2040000>;
+ };
+
+ vreg_s7a_1p025: s7 {
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1028000>;
+ };
+
+ vreg_l1a_0p875: l1 {
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ };
+
+ vreg_l2a_1p2: l2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ vreg_l3a_1p0: l3 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ };
+
+ vreg_l5a_0p8: l5 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ };
+
+ vreg_l6a_1p8: l6 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vreg_l7a_1p8: l7 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vreg_l8a_1p2: l8 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ vreg_l9a_1p8: l9 {
+ regulator-min-microvolt = <1808000>;
+ regulator-max-microvolt = <2960000>;
+ };
+
+ vreg_l10a_1p8: l10 {
+ regulator-min-microvolt = <1808000>;
+ regulator-max-microvolt = <2960000>;
+ };
+
+ vreg_l11a_1p0: l11 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ };
+
+ vreg_l12a_1p8: l12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vreg_l13a_2p95: l13 {
+ regulator-min-microvolt = <1808000>;
+ regulator-max-microvolt = <2960000>;
+ };
+
+ vreg_l14a_1p8: l14 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vreg_l15a_1p8: l15 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vreg_l16a_2p7: l16 {
+ regulator-min-microvolt = <2704000>;
+ regulator-max-microvolt = <2704000>;
+ };
+
+ vreg_l17a_1p3: l17 {
+ regulator-min-microvolt = <1304000>;
+ regulator-max-microvolt = <1304000>;
+ };
+
+ vreg_l18a_2p7: l18 {
+ regulator-min-microvolt = <2704000>;
+ regulator-max-microvolt = <2704000>;
+ };
+
+ vreg_l19a_3p0: l19 {
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <3008000>;
+ };
+
+ vreg_l20a_2p95: l20 {
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-allow-set-load;
+ };
+
+ vreg_l21a_2p95: l21 {
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-system-load = <800000>;
+ regulator-allow-set-load;
+ };
+
+ vreg_l22a_2p85: l22 {
+ regulator-min-microvolt = <2864000>;
+ regulator-max-microvolt = <2864000>;
+ };
+
+ vreg_l23a_3p3: l23 {
+ regulator-min-microvolt = <3312000>;
+ regulator-max-microvolt = <3312000>;
+ };
+
+ vreg_l24a_3p075: l24 {
+ regulator-min-microvolt = <3088000>;
+ regulator-max-microvolt = <3088000>;
+ };
+
+ vreg_l25a_3p3: l25 {
+ regulator-min-microvolt = <3104000>;
+ regulator-max-microvolt = <3312000>;
+ };
+
+ vreg_l26a_1p2: l26 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-allow-set-load;
+ };
+
+ vreg_l28_3p0: l28 {
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <3008000>;
+ };
+
+ vreg_lvs1a_1p8: lvs1 { };
+
+ vreg_lvs2a_1p8: lvs2 { };
+ };
+
+ regulators-1 {
+ compatible = "qcom,rpm-pmi8998-regulators";
+
+ vdd_bob-supply = <&vph_pwr>;
+
+ vreg_bob: bob {
+ regulator-min-microvolt = <3312000>;
+ regulator-max-microvolt = <3600000>;
+ };
+ };
+};
+
+&tlmm {
+ gpio-reserved-ranges = <0 4>, <81 4>;
+
+ cci1_default_state: cci1-default-state {
+ pins = "gpio19", "gpio20";
+ function = "cci_i2c";
+ bias-disable;
+ drive-strength = <2>;
+ };
+
+ cdc_reset_n_state: cdc-reset-n-state {
+ pins = "gpio64";
+ function = "gpio";
+ bias-pull-down;
+ drive-strength = <16>;
+ output-high;
+ };
+
+ hall_sensor_default_state: hall-sensor-default-state {
+ pins = "gpio124";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ input-enable;
+ };
+
+ mdss_dsi_active_state: mdss-dsi-active-state {
+ pins = "gpio94";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-disable;
+ };
+
+ mdss_dsi_suspend_state: mdss-dsi-suspend-state {
+ pins = "gpio94";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ mdss_te_active_state: mdss-te-active-state {
+ pins = "gpio10";
+ function = "mdp_vsync_a";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ mdss_te_suspend_state: mdss-te-suspend-state {
+ pins = "gpio10";
+ function = "mdp_vsync_a";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ msm_mclk0_active_state: msm-mclk0-active-state {
+ pins = "gpio13";
+ function = "cam_mclk";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ msm_mclk0_suspend_state: msm-mclk0-suspend-state {
+ pins = "gpio13";
+ function = "cam_mclk";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ msm_mclk1_active_state: msm-mclk1-active-state {
+ pins = "gpio14";
+ function = "cam_mclk";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ msm_mclk1_suspend_state: msm-mclk1-suspend-state {
+ pins = "gpio14";
+ function = "cam_mclk";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ nfc_int_active_state: nfc-int-active-state {
+ pins = "gpio92";
+ function = "gpio";
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+
+ nfc_int_suspend_state: nfc-int-suspend-state {
+ pins = "gpio92";
+ function = "gpio";
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+
+ nfc_enable_active_state: nfc-enable-active-state {
+ pins = "gpio12", "gpio116";
+ function = "gpio";
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+
+ nfc_enable_suspend_state: nfc-enable-suspend-state {
+ pins = "gpio12", "gpio116";
+ function = "gpio";
+ drive-strength = <6>;
+ bias-disable;
+ };
+
+ ts_active_state: ts-active-state {
+ pins = "gpio89", "gpio125";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-pull-up;
+ input-enable;
+ };
+
+ ts_int_suspend_state: ts-int-suspend-state {
+ pins = "gpio125";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ ts_reset_suspend_state: ts-reset-suspend-state {
+ pins = "gpio89";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ wcd_int_n_state: wcd-int-n-state {
+ pins = "gpio54";
+ function = "gpio";
+ bias-pull-down;
+ drive-strength = <2>;
+ input-enable;
+ };
+
+ wsa_leftspk_pwr_n_state: wsa-leftspk-pwr-n-state {
+ pins = "gpio65";
+ function = "gpio";
+ bias-disable;
+ drive-strength = <2>;
+ output-low;
+ };
+
+ wsa_rightspk_pwr_n_state: wsa-rightspk-pwr-n-state {
+ pins = "gpio66";
+ function = "gpio";
+ bias-disable;
+ drive-strength = <2>;
+ output-low;
+ };
+};
+
+&pm8998_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+ status = "okay";
+};
+
+&ufshc {
+ vcc-supply = <&vreg_l20a_2p95>;
+ vccq-supply = <&vreg_l26a_1p2>;
+ vccq2-supply = <&vreg_s4a_1p8>;
+ vcc-max-microamp = <750000>;
+ vccq-max-microamp = <560000>;
+ vccq2-max-microamp = <750000>;
+ status = "okay";
+};
+
+&ufsphy {
+ vdda-phy-supply = <&vreg_l1a_0p875>;
+ vdda-pll-supply = <&vreg_l2a_1p2>;
+ vddp-ref-clk-supply = <&vreg_l26a_1p2>;
+ status = "okay";
+};
+
+&usb3 {
+ /* Disable USB3 clock requirement as the device only supports USB2 */
+ qcom,select-utmi-as-pipe-clk;
+ status = "okay";
+};
+
+&usb3_dwc3 {
+ /* Drop the unused USB 3 PHY */
+ phys = <&qusb2phy>;
+ phy-names = "usb2-phy";
+
+ /* Fastest mode for USB 2 */
+ maximum-speed = "high-speed";
+
+ /* Force to peripheral until we can switch modes */
+ dr_mode = "peripheral";
+};
+
+&wifi {
+ vdd-0.8-cx-mx-supply = <&vreg_l5a_0p8>;
+ vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
+ vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
+ vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi
index f05f16ac5cc1..539382dab0ad 100644
--- a/arch/arm64/boot/dts/qcom/msm8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi
@@ -900,7 +900,7 @@
};
pcie0: pci@1c00000 {
- compatible = "qcom,pcie-msm8996";
+ compatible = "qcom,pcie-msm8998", "qcom,pcie-msm8996";
reg = <0x01c00000 0x2000>,
<0x1b000000 0xf1d>,
<0x1b000f20 0xa8>,
@@ -929,11 +929,11 @@
<0 0 0 4 &intc 0 0 139 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&gcc GCC_PCIE_0_PIPE_CLK>,
- <&gcc GCC_PCIE_0_MSTR_AXI_CLK>,
- <&gcc GCC_PCIE_0_SLV_AXI_CLK>,
+ <&gcc GCC_PCIE_0_AUX_CLK>,
<&gcc GCC_PCIE_0_CFG_AHB_CLK>,
- <&gcc GCC_PCIE_0_AUX_CLK>;
- clock-names = "pipe", "bus_master", "bus_slave", "cfg", "aux";
+ <&gcc GCC_PCIE_0_MSTR_AXI_CLK>,
+ <&gcc GCC_PCIE_0_SLV_AXI_CLK>;
+ clock-names = "pipe", "aux", "cfg", "bus_master", "bus_slave";
power-domains = <&gcc PCIE_0_GDSC>;
iommu-map = <0x100 &anoc1_smmu 0x1480 1>;
@@ -1056,81 +1056,82 @@
compatible = "qcom,msm8998-pinctrl";
reg = <0x03400000 0xc00000>;
interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-ranges = <&tlmm 0 0 150>;
gpio-controller;
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
- sdc2_on: sdc2-on {
- clk {
+ sdc2_on: sdc2-on-state {
+ clk-pins {
pins = "sdc2_clk";
drive-strength = <16>;
bias-disable;
};
- cmd {
+ cmd-pins {
pins = "sdc2_cmd";
drive-strength = <10>;
bias-pull-up;
};
- data {
+ data-pins {
pins = "sdc2_data";
drive-strength = <10>;
bias-pull-up;
};
};
- sdc2_off: sdc2-off {
- clk {
+ sdc2_off: sdc2-off-state {
+ clk-pins {
pins = "sdc2_clk";
drive-strength = <2>;
bias-disable;
};
- cmd {
+ cmd-pins {
pins = "sdc2_cmd";
drive-strength = <2>;
bias-pull-up;
};
- data {
+ data-pins {
pins = "sdc2_data";
drive-strength = <2>;
bias-pull-up;
};
};
- sdc2_cd: sdc2-cd {
+ sdc2_cd: sdc2-cd-state {
pins = "gpio95";
function = "gpio";
bias-pull-up;
drive-strength = <2>;
};
- blsp1_uart3_on: blsp1-uart3-on {
- tx {
+ blsp1_uart3_on: blsp1-uart3-on-state {
+ tx-pins {
pins = "gpio45";
function = "blsp_uart3_a";
drive-strength = <2>;
bias-disable;
};
- rx {
+ rx-pins {
pins = "gpio46";
function = "blsp_uart3_a";
drive-strength = <2>;
bias-disable;
};
- cts {
+ cts-pins {
pins = "gpio47";
function = "blsp_uart3_a";
drive-strength = <2>;
bias-disable;
};
- rfr {
+ rfr-pins {
pins = "gpio48";
function = "blsp_uart3_a";
drive-strength = <2>;
@@ -1138,168 +1139,168 @@
};
};
- blsp1_i2c1_default: blsp1-i2c1-default {
+ blsp1_i2c1_default: blsp1-i2c1-default-state {
pins = "gpio2", "gpio3";
function = "blsp_i2c1";
drive-strength = <2>;
bias-disable;
};
- blsp1_i2c1_sleep: blsp1-i2c1-sleep {
+ blsp1_i2c1_sleep: blsp1-i2c1-sleep-state-state {
pins = "gpio2", "gpio3";
function = "blsp_i2c1";
drive-strength = <2>;
bias-pull-up;
};
- blsp1_i2c2_default: blsp1-i2c2-default {
+ blsp1_i2c2_default: blsp1-i2c2-default-state {
pins = "gpio32", "gpio33";
function = "blsp_i2c2";
drive-strength = <2>;
bias-disable;
};
- blsp1_i2c2_sleep: blsp1-i2c2-sleep {
+ blsp1_i2c2_sleep: blsp1-i2c2-sleep-state-state {
pins = "gpio32", "gpio33";
function = "blsp_i2c2";
drive-strength = <2>;
bias-pull-up;
};
- blsp1_i2c3_default: blsp1-i2c3-default {
+ blsp1_i2c3_default: blsp1-i2c3-default-state {
pins = "gpio47", "gpio48";
function = "blsp_i2c3";
drive-strength = <2>;
bias-disable;
};
- blsp1_i2c3_sleep: blsp1-i2c3-sleep {
+ blsp1_i2c3_sleep: blsp1-i2c3-sleep-state {
pins = "gpio47", "gpio48";
function = "blsp_i2c3";
drive-strength = <2>;
bias-pull-up;
};
- blsp1_i2c4_default: blsp1-i2c4-default {
+ blsp1_i2c4_default: blsp1-i2c4-default-state {
pins = "gpio10", "gpio11";
function = "blsp_i2c4";
drive-strength = <2>;
bias-disable;
};
- blsp1_i2c4_sleep: blsp1-i2c4-sleep {
+ blsp1_i2c4_sleep: blsp1-i2c4-sleep-state {
pins = "gpio10", "gpio11";
function = "blsp_i2c4";
drive-strength = <2>;
bias-pull-up;
};
- blsp1_i2c5_default: blsp1-i2c5-default {
+ blsp1_i2c5_default: blsp1-i2c5-default-state {
pins = "gpio87", "gpio88";
function = "blsp_i2c5";
drive-strength = <2>;
bias-disable;
};
- blsp1_i2c5_sleep: blsp1-i2c5-sleep {
+ blsp1_i2c5_sleep: blsp1-i2c5-sleep-state {
pins = "gpio87", "gpio88";
function = "blsp_i2c5";
drive-strength = <2>;
bias-pull-up;
};
- blsp1_i2c6_default: blsp1-i2c6-default {
+ blsp1_i2c6_default: blsp1-i2c6-default-state {
pins = "gpio43", "gpio44";
function = "blsp_i2c6";
drive-strength = <2>;
bias-disable;
};
- blsp1_i2c6_sleep: blsp1-i2c6-sleep {
+ blsp1_i2c6_sleep: blsp1-i2c6-sleep-state {
pins = "gpio43", "gpio44";
function = "blsp_i2c6";
drive-strength = <2>;
bias-pull-up;
};
/* 6 interfaces per QUP, BLSP2 indexes are numbered (n)+6 */
- blsp2_i2c1_default: blsp2-i2c1-default {
+ blsp2_i2c1_default: blsp2-i2c1-default-state {
pins = "gpio55", "gpio56";
function = "blsp_i2c7";
drive-strength = <2>;
bias-disable;
};
- blsp2_i2c1_sleep: blsp2-i2c1-sleep {
+ blsp2_i2c1_sleep: blsp2-i2c1-sleep-state {
pins = "gpio55", "gpio56";
function = "blsp_i2c7";
drive-strength = <2>;
bias-pull-up;
};
- blsp2_i2c2_default: blsp2-i2c2-default {
+ blsp2_i2c2_default: blsp2-i2c2-default-state {
pins = "gpio6", "gpio7";
function = "blsp_i2c8";
drive-strength = <2>;
bias-disable;
};
- blsp2_i2c2_sleep: blsp2-i2c2-sleep {
+ blsp2_i2c2_sleep: blsp2-i2c2-sleep-state {
pins = "gpio6", "gpio7";
function = "blsp_i2c8";
drive-strength = <2>;
bias-pull-up;
};
- blsp2_i2c3_default: blsp2-i2c3-default {
+ blsp2_i2c3_default: blsp2-i2c3-default-state {
pins = "gpio51", "gpio52";
function = "blsp_i2c9";
drive-strength = <2>;
bias-disable;
};
- blsp2_i2c3_sleep: blsp2-i2c3-sleep {
+ blsp2_i2c3_sleep: blsp2-i2c3-sleep-state {
pins = "gpio51", "gpio52";
function = "blsp_i2c9";
drive-strength = <2>;
bias-pull-up;
};
- blsp2_i2c4_default: blsp2-i2c4-default {
+ blsp2_i2c4_default: blsp2-i2c4-default-state {
pins = "gpio67", "gpio68";
function = "blsp_i2c10";
drive-strength = <2>;
bias-disable;
};
- blsp2_i2c4_sleep: blsp2-i2c4-sleep {
+ blsp2_i2c4_sleep: blsp2-i2c4-sleep-state {
pins = "gpio67", "gpio68";
function = "blsp_i2c10";
drive-strength = <2>;
bias-pull-up;
};
- blsp2_i2c5_default: blsp2-i2c5-default {
+ blsp2_i2c5_default: blsp2-i2c5-default-state {
pins = "gpio60", "gpio61";
function = "blsp_i2c11";
drive-strength = <2>;
bias-disable;
};
- blsp2_i2c5_sleep: blsp2-i2c5-sleep {
+ blsp2_i2c5_sleep: blsp2-i2c5-sleep-state {
pins = "gpio60", "gpio61";
function = "blsp_i2c11";
drive-strength = <2>;
bias-pull-up;
};
- blsp2_i2c6_default: blsp2-i2c6-default {
+ blsp2_i2c6_default: blsp2-i2c6-default-state {
pins = "gpio83", "gpio84";
function = "blsp_i2c12";
drive-strength = <2>;
bias-disable;
};
- blsp2_i2c6_sleep: blsp2-i2c6-sleep {
+ blsp2_i2c6_sleep: blsp2-i2c6-sleep-state {
pins = "gpio83", "gpio84";
function = "blsp_i2c12";
drive-strength = <2>;
@@ -1903,7 +1904,7 @@
cpu = <&CPU4>;
- port{
+ port {
etm4_out: endpoint {
remote-endpoint = <&apss_funnel_in4>;
};
@@ -1920,7 +1921,7 @@
cpu = <&CPU5>;
- port{
+ port {
etm5_out: endpoint {
remote-endpoint = <&apss_funnel_in5>;
};
@@ -1937,7 +1938,7 @@
cpu = <&CPU6>;
- port{
+ port {
etm6_out: endpoint {
remote-endpoint = <&apss_funnel_in6>;
};
@@ -1954,7 +1955,7 @@
cpu = <&CPU7>;
- port{
+ port {
etm7_out: endpoint {
remote-endpoint = <&apss_funnel_in7>;
};
diff --git a/arch/arm64/boot/dts/qcom/pm6125.dtsi b/arch/arm64/boot/dts/qcom/pm6125.dtsi
new file mode 100644
index 000000000000..1c8ccda26ffb
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/pm6125.dtsi
@@ -0,0 +1,154 @@
+// SPDX-License-Identifier: BSD-3-Clause
+
+#include <dt-bindings/iio/qcom,spmi-vadc.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/spmi/spmi.h>
+
+/ {
+ thermal-zones {
+ pm6125-thermal {
+ polling-delay-passive = <100>;
+ polling-delay = <0>;
+
+ thermal-sensors = <&pm6125_temp>;
+
+ trips {
+ trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "hot";
+ };
+
+ trip2 {
+ temperature = <145000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+ };
+};
+
+&spmi_bus {
+ pmic@0 {
+ compatible = "qcom,pm6125", "qcom,spmi-pmic";
+ reg = <0x0 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pm6125_pon: pon@800 {
+ compatible = "qcom,pm8998-pon";
+ reg = <0x800>;
+ mode-bootloader = <0x2>;
+ mode-recovery = <0x1>;
+
+ pon_pwrkey: pwrkey {
+ compatible = "qcom,pm8941-pwrkey";
+ interrupts = <0x0 0x8 0x0 IRQ_TYPE_EDGE_BOTH>;
+ debounce = <15625>;
+ linux,code = <KEY_POWER>;
+ bias-pull-up;
+ status = "disabled";
+ };
+
+ pon_resin: resin {
+ compatible = "qcom,pm8941-resin";
+ interrupts = <0x0 0x8 0x1 IRQ_TYPE_EDGE_BOTH>;
+ debounce = <15625>;
+ bias-pull-up;
+ status = "disabled";
+ };
+ };
+
+ pm6125_temp: temp-alarm@2400 {
+ compatible = "qcom,spmi-temp-alarm";
+ reg = <0x2400>;
+ interrupts = <0x0 0x24 0x0 IRQ_TYPE_EDGE_RISING>;
+ io-channels = <&pm6125_adc ADC5_DIE_TEMP>;
+ io-channel-names = "thermal";
+ #thermal-sensor-cells = <0>;
+ };
+
+ pm6125_adc: adc@3100 {
+ compatible = "qcom,spmi-adc5";
+ reg = <0x3100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+ #io-channel-cells = <1>;
+
+ ref-gnd@0 {
+ reg = <ADC5_REF_GND>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ vref-1p25@1 {
+ reg = <ADC5_1P25VREF>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ die-temp@6 {
+ reg = <ADC5_DIE_TEMP>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ vph-pwr@83 {
+ reg = <ADC5_VPH_PWR>;
+ qcom,pre-scaling = <1 3>;
+ };
+
+ vcoin@85 {
+ reg = <ADC5_VCOIN>;
+ qcom,pre-scaling = <1 3>;
+ };
+
+ xo-therm@4c {
+ reg = <ADC5_XO_THERM_100K_PU>;
+ qcom,pre-scaling = <1 1>;
+ qcom,hw-settle-time = <200>;
+ qcom,ratiometric;
+ };
+ };
+
+ pm6125_adc_tm: adc-tm@3500 {
+ compatible = "qcom,spmi-adc-tm5";
+ reg = <0x3500>;
+ interrupts = <0x0 0x35 0x0 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #thermal-sensor-cells = <1>;
+ status = "disabled";
+ };
+
+ pm6125_rtc: rtc@6000 {
+ compatible = "qcom,pm8941-rtc";
+ reg = <0x6000>, <0x6100>;
+ reg-names = "rtc", "alarm";
+ interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
+ };
+
+ pm6125_gpio: gpio@c000 {
+ compatible = "qcom,pm6125-gpio", "qcom,spmi-gpio";
+ reg = <0xc000>;
+ gpio-controller;
+ gpio-ranges = <&pm6125_gpio 0 0 9>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ pmic@1 {
+ compatible = "qcom,pm6125", "qcom,spmi-pmic";
+ reg = <0x1 SPMI_USID>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/pm6150.dtsi b/arch/arm64/boot/dts/qcom/pm6150.dtsi
index 8a4972e6a24c..3d91fb405ca2 100644
--- a/arch/arm64/boot/dts/qcom/pm6150.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm6150.dtsi
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause
-// Copyright (c) 2019, The Linux Foundation. All rights reserved.
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ */
#include <dt-bindings/iio/qcom,spmi-vadc.h>
#include <dt-bindings/input/linux-event-codes.h>
@@ -86,7 +88,7 @@
status = "disabled";
};
- pm6150_gpio: gpios@c000 {
+ pm6150_gpio: gpio@c000 {
compatible = "qcom,pm6150-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
gpio-controller;
diff --git a/arch/arm64/boot/dts/qcom/pm6150l.dtsi b/arch/arm64/boot/dts/qcom/pm6150l.dtsi
index f02c223ef448..90aac61ad264 100644
--- a/arch/arm64/boot/dts/qcom/pm6150l.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm6150l.dtsi
@@ -1,10 +1,43 @@
// SPDX-License-Identifier: BSD-3-Clause
-// Copyright (c) 2019, The Linux Foundation. All rights reserved.
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ */
#include <dt-bindings/iio/qcom,spmi-vadc.h>
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/spmi/spmi.h>
+/ {
+ thermal-zones {
+ pm6150l-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+
+ thermal-sensors = <&pm6150l_temp>;
+
+ trips {
+ trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "hot";
+ };
+
+ trip2 {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+ };
+};
+
&spmi_bus {
pm6150l_lsid4: pmic@4 {
compatible = "qcom,pm6150l", "qcom,spmi-pmic";
@@ -12,6 +45,13 @@
#address-cells = <1>;
#size-cells = <0>;
+ pm6150l_temp: temp-alarm@2400 {
+ compatible = "qcom,spmi-temp-alarm";
+ reg = <0x2400>;
+ interrupts = <0x4 0x24 0x0 IRQ_TYPE_EDGE_BOTH>;
+ #thermal-sensor-cells = <0>;
+ };
+
pm6150l_adc: adc@3100 {
compatible = "qcom,spmi-adc5";
reg = <0x3100>;
@@ -55,7 +95,7 @@
status = "disabled";
};
- pm6150l_gpio: gpios@c000 {
+ pm6150l_gpio: gpio@c000 {
compatible = "qcom,pm6150l-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
gpio-controller;
diff --git a/arch/arm64/boot/dts/qcom/pm6350.dtsi b/arch/arm64/boot/dts/qcom/pm6350.dtsi
index ecf9b9919182..3a2a841e83f1 100644
--- a/arch/arm64/boot/dts/qcom/pm6350.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm6350.dtsi
@@ -3,8 +3,40 @@
* Copyright (c) 2021, Luca Weiss <luca@z3ntu.xyz>
*/
+#include <dt-bindings/input/input.h>
#include <dt-bindings/spmi/spmi.h>
+/ {
+ thermal-zones {
+ pm6350-thermal {
+ polling-delay-passive = <100>;
+ polling-delay = <0>;
+
+ thermal-sensors = <&pm6350_temp>;
+
+ trips {
+ trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "hot";
+ };
+
+ trip2 {
+ temperature = <125000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+ };
+};
+
&spmi_bus {
pmic@0 {
compatible = "qcom,pm6350", "qcom,spmi-pmic";
@@ -35,7 +67,14 @@
};
};
- pm6350_gpios: gpios@c000 {
+ pm6350_temp: temp-alarm@2400 {
+ compatible = "qcom,spmi-temp-alarm";
+ reg = <0x2400>;
+ interrupts = <0x0 0x24 0x0 IRQ_TYPE_EDGE_BOTH>;
+ #thermal-sensor-cells = <0>;
+ };
+
+ pm6350_gpios: gpio@c000 {
compatible = "qcom,pm6350-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
gpio-controller;
diff --git a/arch/arm64/boot/dts/qcom/pm660.dtsi b/arch/arm64/boot/dts/qcom/pm660.dtsi
index e1622b16c08b..fc0eccaccdf6 100644
--- a/arch/arm64/boot/dts/qcom/pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm660.dtsi
@@ -163,14 +163,14 @@
qcom,pre-scaling = <1 3>;
};
- vcoin: vcoin@83 {
+ vcoin: vcoin@85 {
reg = <ADC5_VCOIN>;
qcom,decimation = <1024>;
qcom,pre-scaling = <1 3>;
};
};
- pm660_gpios: gpios@c000 {
+ pm660_gpios: gpio@c000 {
compatible = "qcom,pm660-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
gpio-controller;
diff --git a/arch/arm64/boot/dts/qcom/pm660l.dtsi b/arch/arm64/boot/dts/qcom/pm660l.dtsi
index 8aa0a5078772..f9b3864bd3b9 100644
--- a/arch/arm64/boot/dts/qcom/pm660l.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm660l.dtsi
@@ -48,7 +48,7 @@
#thermal-sensor-cells = <0>;
};
- pm660l_gpios: gpios@c000 {
+ pm660l_gpios: gpio@c000 {
compatible = "qcom,pm660l-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
gpio-controller;
diff --git a/arch/arm64/boot/dts/qcom/pm7325.dtsi b/arch/arm64/boot/dts/qcom/pm7325.dtsi
index e7f64a9ddc9c..d1c5476af5ee 100644
--- a/arch/arm64/boot/dts/qcom/pm7325.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm7325.dtsi
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause
-// Copyright (c) 2021, The Linux Foundation. All rights reserved.
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ */
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/spmi/spmi.h>
@@ -18,7 +20,7 @@
#thermal-sensor-cells = <0>;
};
- pm7325_gpios: gpios@8800 {
+ pm7325_gpios: gpio@8800 {
compatible = "qcom,pm7325-gpio", "qcom,spmi-gpio";
reg = <0x8800>;
gpio-controller;
diff --git a/arch/arm64/boot/dts/qcom/pm8005.dtsi b/arch/arm64/boot/dts/qcom/pm8005.dtsi
index 50fb6c753bf8..8d4b081b4e9d 100644
--- a/arch/arm64/boot/dts/qcom/pm8005.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8005.dtsi
@@ -11,7 +11,7 @@
#address-cells = <1>;
#size-cells = <0>;
- pm8005_gpio: gpios@c000 {
+ pm8005_gpio: gpio@c000 {
compatible = "qcom,pm8005-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
gpio-controller;
diff --git a/arch/arm64/boot/dts/qcom/pm8150b.dtsi b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
index cdded791d96e..66752cc063d6 100644
--- a/arch/arm64/boot/dts/qcom/pm8150b.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8150b.dtsi
@@ -53,7 +53,7 @@
status = "disabled";
};
- pm8150b_vbus: dcdc@1100 {
+ pm8150b_vbus: usb-vbus-regulator@1100 {
compatible = "qcom,pm8150b-vbus-reg";
status = "disabled";
reg = <0x1100>;
diff --git a/arch/arm64/boot/dts/qcom/pm8450a.dtsi b/arch/arm64/boot/dts/qcom/pm8450a.dtsi
new file mode 100644
index 000000000000..34fc72896761
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/pm8450a.dtsi
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+#include <dt-bindings/spmi/spmi.h>
+
+&spmi_bus {
+ pm8450a: pmic@0 {
+ compatible = "qcom,pm8150", "qcom,spmi-pmic";
+ reg = <0x0 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pm8450a_gpios: gpio@c000 {
+ compatible = "qcom,pm8150-gpio", "qcom,spmi-gpio";
+ reg = <0xc000>;
+ gpio-controller;
+ gpio-ranges = <&pm8450a_gpios 0 0 10>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ pm8450c: pmic@4 {
+ compatible = "qcom,pm8150", "qcom,spmi-pmic";
+ reg = <0x4 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pm8450c_gpios: gpio@c000 {
+ compatible = "qcom,pm8150-gpio", "qcom,spmi-gpio";
+ reg = <0xc000>;
+ gpio-controller;
+ gpio-ranges = <&pm8450c_gpios 0 0 10>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ pm8450e: pmic@8 {
+ compatible = "qcom,pm8150", "qcom,spmi-pmic";
+ reg = <0x8 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pm8450e_gpios: gpio@c000 {
+ compatible = "qcom,pm8150-gpio", "qcom,spmi-gpio";
+ reg = <0xc000>;
+ gpio-controller;
+ gpio-ranges = <&pm8450e_gpios 0 0 10>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ pm8450g: pmic@c {
+ compatible = "qcom,pm8150", "qcom,spmi-pmic";
+ reg = <0xc SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pm8450g_gpios: gpio@c000 {
+ compatible = "qcom,pm8150-gpio", "qcom,spmi-gpio";
+ reg = <0xc000>;
+ gpio-controller;
+ gpio-ranges = <&pm8450g_gpios 0 0 10>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/pm8916.dtsi b/arch/arm64/boot/dts/qcom/pm8916.dtsi
index 606c2a6d1f0f..08f9ca006e72 100644
--- a/arch/arm64/boot/dts/qcom/pm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8916.dtsi
@@ -107,7 +107,7 @@
#interrupt-cells = <2>;
};
- pm8916_gpios: gpios@c000 {
+ pm8916_gpios: gpio@c000 {
compatible = "qcom,pm8916-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
gpio-controller;
diff --git a/arch/arm64/boot/dts/qcom/pm8950.dtsi b/arch/arm64/boot/dts/qcom/pm8950.dtsi
new file mode 100644
index 000000000000..07c3896bd36f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/pm8950.dtsi
@@ -0,0 +1,165 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2022, AngeloGioacchino Del Regno
+ * <angelogioacchino.delregno@somainline.org>
+ * Copyright (c) 2022, Marijn Suijten <marijn.suijten@somainline.org>
+ */
+
+#include <dt-bindings/iio/qcom,spmi-vadc.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/qcom,pmic-mpp.h>
+#include <dt-bindings/spmi/spmi.h>
+
+&spmi_bus {
+ pmic@0 {
+ compatible = "qcom,pm8950", "qcom,spmi-pmic";
+ reg = <0x0 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pon@800 {
+ compatible = "qcom,pm8916-pon";
+ reg = <0x0800>;
+ mode-bootloader = <0x2>;
+ mode-recovery = <0x1>;
+
+ pwrkey {
+ compatible = "qcom,pm8941-pwrkey";
+ interrupts = <0x0 0x8 0 IRQ_TYPE_EDGE_BOTH>;
+ debounce = <15625>;
+ bias-pull-up;
+ linux,code = <KEY_POWER>;
+ };
+ };
+
+ pm8950_temp: temp-alarm@2400 {
+ compatible = "qcom,spmi-temp-alarm";
+ reg = <0x2400>;
+ interrupts = <0 0x24 0 IRQ_TYPE_EDGE_RISING>;
+ io-channels = <&pm8950_vadc VADC_DIE_TEMP>;
+ io-channel-names = "thermal";
+ #thermal-sensor-cells = <0>;
+ };
+
+ pm8950_vadc: adc@3100 {
+ compatible = "qcom,spmi-vadc";
+ reg = <0x3100>;
+ interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+
+ vcoin@5 {
+ reg = <VADC_VCOIN>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ vph-pwr@7 {
+ reg = <VADC_VSYS>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ die-temp@8 {
+ reg = <VADC_DIE_TEMP>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ ref-625mv@9 {
+ reg = <VADC_REF_625MV>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ ref-1250mv@a {
+ reg = <VADC_REF_1250MV>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ ref-buf-625mv@c {
+ reg = <VADC_SPARE1>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ ref-gnd@e {
+ reg = <VADC_GND_REF>;
+ };
+
+ ref-vdd@f {
+ reg = <VADC_VDD_VADC>;
+ };
+
+ pa-therm1@11 {
+ reg = <VADC_P_MUX2_1_1>;
+ qcom,pre-scaling = <1 1>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+
+ case-therm@13 {
+ reg = <VADC_P_MUX4_1_1>;
+ qcom,pre-scaling = <1 1>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+
+ xo-therm@32 {
+ reg = <VADC_LR_MUX3_XO_THERM>;
+ qcom,pre-scaling = <1 1>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+
+ pa-therm0@36 {
+ reg = <VADC_LR_MUX7_HW_ID>;
+ qcom,pre-scaling = <1 1>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+
+ xo-therm-buf@3c {
+ reg = <VADC_LR_MUX3_BUF_XO_THERM>;
+ qcom,pre-scaling = <1 1>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ };
+ };
+
+ rtc@6000 {
+ compatible = "qcom,pm8941-rtc";
+ reg = <0x6000>;
+ reg-names = "rtc", "alarm";
+ interrupts = <0x0 0x61 0x1 IRQ_TYPE_NONE>;
+ };
+
+ pm8950_mpps: mpps@a000 {
+ compatible = "qcom,pm8950-mpp", "qcom,spmi-mpp";
+ reg = <0xa000>;
+ gpio-controller;
+ gpio-ranges = <&pm8950_mpps 0 0 4>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pm8950_gpio: gpio@c000 {
+ compatible = "qcom,pm8950-gpio", "qcom,spmi-gpio";
+ reg = <0xc000>;
+ gpio-controller;
+ gpio-ranges = <&pm8950_gpio 0 0 8>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ pmic@1 {
+ compatible = "qcom,pm8950", "qcom,spmi-pmic";
+ reg = <0x1 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pm8950_spmi_regulators: regulators {
+ compatible = "qcom,pm8950-regulators";
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/pm8994.dtsi b/arch/arm64/boot/dts/qcom/pm8994.dtsi
index e92e5ac414d3..672094c8ca58 100644
--- a/arch/arm64/boot/dts/qcom/pm8994.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8994.dtsi
@@ -108,7 +108,7 @@
};
};
- pm8994_gpios: gpios@c000 {
+ pm8994_gpios: gpio@c000 {
compatible = "qcom,pm8994-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
gpio-controller;
diff --git a/arch/arm64/boot/dts/qcom/pm8998.dtsi b/arch/arm64/boot/dts/qcom/pm8998.dtsi
index d09f2954b6f9..6a5854333b2b 100644
--- a/arch/arm64/boot/dts/qcom/pm8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8998.dtsi
@@ -52,6 +52,14 @@
bias-pull-up;
linux,code = <KEY_POWER>;
};
+
+ pm8998_resin: resin {
+ compatible = "qcom,pm8941-resin";
+ interrupts = <GIC_SPI 0x8 1 IRQ_TYPE_EDGE_BOTH>;
+ debounce = <15625>;
+ bias-pull-up;
+ status = "disabled";
+ };
};
pm8998_temp: temp-alarm@2400 {
@@ -63,7 +71,7 @@
#thermal-sensor-cells = <0>;
};
- pm8998_coincell: coincell@2800 {
+ pm8998_coincell: charger@2800 {
compatible = "qcom,pm8941-coincell";
reg = <0x2800>;
@@ -101,7 +109,7 @@
interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>;
};
- pm8998_gpio: gpios@c000 {
+ pm8998_gpio: gpio@c000 {
compatible = "qcom,pm8998-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
gpio-controller;
diff --git a/arch/arm64/boot/dts/qcom/pmi8950.dtsi b/arch/arm64/boot/dts/qcom/pmi8950.dtsi
new file mode 100644
index 000000000000..32d27e2187e3
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/pmi8950.dtsi
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2019, AngeloGioacchino Del Regno <kholk11@gmail.com>
+
+#include <dt-bindings/iio/qcom,spmi-vadc.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/spmi/spmi.h>
+
+&spmi_bus {
+ pmic@2 {
+ compatible = "qcom,pmi8950", "qcom,spmi-pmic";
+ reg = <0x2 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmi8950_vadc: adc@3100 {
+ compatible = "qcom,spmi-vadc";
+ reg = <0x3100>;
+ interrupts = <0x2 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+
+ adc-chan@0 {
+ reg = <VADC_USBIN>;
+ qcom,pre-scaling = <1 4>;
+ label = "usbin";
+ };
+
+ adc-chan@1 {
+ reg = <VADC_DCIN>;
+ qcom,pre-scaling = <1 4>;
+ label = "dcin";
+ };
+
+ adc-chan@2 {
+ reg = <VADC_VCHG_SNS>;
+ qcom,pre-scaling = <1 1>;
+ label = "vchg_sns";
+ };
+
+ adc-chan@9 {
+ reg = <VADC_REF_625MV>;
+ qcom,pre-scaling = <1 1>;
+ label = "ref_625mv";
+ };
+
+ adc-chan@a {
+ reg = <VADC_REF_1250MV>;
+ qcom,pre-scaling = <1 1>;
+ label = "ref_1250v";
+ };
+
+ adc-chan@d {
+ reg = <VADC_SPARE2>;
+ qcom,pre-scaling = <1 1>;
+ label = "chg_temp";
+ };
+ };
+
+ pmi8950_mpps: mpps@a000 {
+ compatible = "qcom,pmi8950-mpp", "qcom,spmi-mpp";
+ reg = <0xa000>;
+ gpio-controller;
+ gpio-ranges = <&pmi8950_mpps 0 0 4>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ pmi8950_gpio: gpio@c000 {
+ compatible = "qcom,pmi8950-gpio", "qcom,spmi-gpio";
+ reg = <0xc000>;
+ gpio-controller;
+ gpio-ranges = <&pmi8950_gpio 0 0 2>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ pmic@3 {
+ compatible = "qcom,pmi8950", "qcom,spmi-pmic";
+ reg = <0x3 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmi8950_wled: leds@d800 {
+ compatible = "qcom,pmi8950-wled";
+ reg = <0xd800>, <0xd900>;
+ interrupts = <0x3 0xd8 0x02 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "short";
+ label = "backlight";
+
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/pmi8994.dtsi b/arch/arm64/boot/dts/qcom/pmi8994.dtsi
index 542c215dde10..a0af91698d49 100644
--- a/arch/arm64/boot/dts/qcom/pmi8994.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi8994.dtsi
@@ -10,7 +10,7 @@
#address-cells = <1>;
#size-cells = <0>;
- pmi8994_gpios: gpios@c000 {
+ pmi8994_gpios: gpio@c000 {
compatible = "qcom,pmi8994-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
gpio-controller;
diff --git a/arch/arm64/boot/dts/qcom/pmi8998.dtsi b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
index 3852a012bb0f..cd1caeae8281 100644
--- a/arch/arm64/boot/dts/qcom/pmi8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
@@ -9,7 +9,7 @@
#address-cells = <1>;
#size-cells = <0>;
- pmi8998_gpio: gpios@c000 {
+ pmi8998_gpio: gpio@c000 {
compatible = "qcom,pmi8998-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
gpio-controller;
@@ -18,6 +18,14 @@
interrupt-controller;
#interrupt-cells = <2>;
};
+
+ pmi8998_rradc: adc@4500 {
+ compatible = "qcom,pmi8998-rradc";
+ reg = <0x4500>;
+ #io-channel-cells = <1>;
+
+ status = "disabled";
+ };
};
pmi8998_lsid1: pmic@3 {
diff --git a/arch/arm64/boot/dts/qcom/pmk8350.dtsi b/arch/arm64/boot/dts/qcom/pmk8350.dtsi
index a7ec9d11946d..32f5e6af8c11 100644
--- a/arch/arm64/boot/dts/qcom/pmk8350.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmk8350.dtsi
@@ -8,27 +8,33 @@
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/spmi/spmi.h>
+/* (Sadly) this PMIC can be configured to be at different SIDs */
+#ifndef PMK8350_SID
+ #define PMK8350_SID 0
+#endif
+
&spmi_bus {
- pmk8350: pmic@0 {
+ pmk8350: pmic@PMK8350_SID {
compatible = "qcom,pmk8350", "qcom,spmi-pmic";
- reg = <0x0 SPMI_USID>;
+ reg = <PMK8350_SID SPMI_USID>;
#address-cells = <1>;
#size-cells = <0>;
pmk8350_pon: pon@1300 {
compatible = "qcom,pm8998-pon";
- reg = <0x1300>;
+ reg = <0x1300>, <0x800>;
+ reg-names = "hlos", "pbs";
pon_pwrkey: pwrkey {
compatible = "qcom,pmk8350-pwrkey";
- interrupts = <0x0 0x13 0x7 IRQ_TYPE_EDGE_BOTH>;
+ interrupts = <PMK8350_SID 0x13 0x7 IRQ_TYPE_EDGE_BOTH>;
linux,code = <KEY_POWER>;
status = "disabled";
};
pon_resin: resin {
compatible = "qcom,pmk8350-resin";
- interrupts = <0x0 0x13 0x6 IRQ_TYPE_EDGE_BOTH>;
+ interrupts = <PMK8350_SID 0x13 0x6 IRQ_TYPE_EDGE_BOTH>;
status = "disabled";
};
};
@@ -38,14 +44,14 @@
reg = <0x3100>;
#address-cells = <1>;
#size-cells = <0>;
- interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <PMK8350_SID 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
#io-channel-cells = <1>;
};
pmk8350_adc_tm: adc-tm@3400 {
compatible = "qcom,adc-tm7";
reg = <0x3400>;
- interrupts = <0x0 0x34 0x0 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <PMK8350_SID 0x34 0x0 IRQ_TYPE_EDGE_RISING>;
#address-cells = <1>;
#size-cells = <0>;
#thermal-sensor-cells = <1>;
@@ -56,7 +62,7 @@
compatible = "qcom,pmk8350-rtc";
reg = <0x6100>, <0x6200>;
reg-names = "rtc", "alarm";
- interrupts = <0x0 0x62 0x1 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <PMK8350_SID 0x62 0x1 IRQ_TYPE_EDGE_RISING>;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/qcom/pmp8074.dtsi b/arch/arm64/boot/dts/qcom/pmp8074.dtsi
new file mode 100644
index 000000000000..ceb2e6358b3d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/pmp8074.dtsi
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0-only OR BSD-3-Clause
+
+#include <dt-bindings/spmi/spmi.h>
+#include <dt-bindings/iio/qcom,spmi-vadc.h>
+
+&spmi_bus {
+ pmic@0 {
+ compatible = "qcom,pmp8074", "qcom,spmi-pmic";
+ reg = <0x0 SPMI_USID>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pmp8074_adc: adc@3100 {
+ compatible = "qcom,spmi-adc-rev2";
+ reg = <0x3100>;
+ interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+
+ ref-gnd@0 {
+ reg = <ADC5_REF_GND>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ vref-1p25@1 {
+ reg = <ADC5_1P25VREF>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ vref-vadc@2 {
+ reg = <ADC5_VREF_VADC>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ pmic_die: die-temp@6 {
+ reg = <ADC5_DIE_TEMP>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ xo_therm: xo-temp@76 {
+ reg = <ADC5_XO_THERM_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ pa_therm1: thermistor1@77 {
+ reg = <ADC5_AMUX_THM1_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ pa_therm2: thermistor2@78 {
+ reg = <ADC5_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ pa_therm3: thermistor3@79 {
+ reg = <ADC5_AMUX_THM3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ vph-pwr@131 {
+ reg = <ADC5_VPH_PWR>;
+ qcom,pre-scaling = <1 3>;
+ };
+ };
+
+ pmp8074_rtc: rtc@6000 {
+ compatible = "qcom,pm8941-rtc";
+ reg = <0x6000>;
+ reg-names = "rtc", "alarm";
+ interrupts = <0x0 0x61 0x1 IRQ_TYPE_NONE>;
+ allow-set-time;
+ status = "disabled";
+ };
+
+ pmp8074_gpios: gpio@c000 {
+ compatible = "qcom,pmp8074-gpio", "qcom,spmi-gpio";
+ reg = <0xc000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&pmp8074_gpios 0 0 12>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ pmic@1 {
+ compatible = "qcom,pmp8074", "qcom,spmi-pmic";
+ reg = <0x1 SPMI_USID>;
+
+ regulators {
+ compatible = "qcom,pmp8074-regulators";
+
+ s3: s3 {
+ regulator-name = "vdd_s3";
+ regulator-min-microvolt = <592000>;
+ regulator-max-microvolt = <1064000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ s4: s4 {
+ regulator-name = "vdd_s4";
+ regulator-min-microvolt = <712000>;
+ regulator-max-microvolt = <992000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ l11: l11 {
+ regulator-name = "l11";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/pms405.dtsi b/arch/arm64/boot/dts/qcom/pms405.dtsi
index 634b0681d04c..ffe9e33808d0 100644
--- a/arch/arm64/boot/dts/qcom/pms405.dtsi
+++ b/arch/arm64/boot/dts/qcom/pms405.dtsi
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
-// Copyright (c) 2018, Linaro Limited
+/*
+ * Copyright (c) 2018, Linaro Limited
+ */
#include <dt-bindings/spmi/spmi.h>
#include <dt-bindings/input/linux-event-codes.h>
diff --git a/arch/arm64/boot/dts/qcom/qcs404-evb-1000.dts b/arch/arm64/boot/dts/qcom/qcs404-evb-1000.dts
index 937eb4555ffe..fc29b194cd34 100644
--- a/arch/arm64/boot/dts/qcom/qcs404-evb-1000.dts
+++ b/arch/arm64/boot/dts/qcom/qcs404-evb-1000.dts
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
-// Copyright (c) 2018, Linaro Limited
+/*
+ * Copyright (c) 2018, Linaro Limited
+ */
/dts-v1/;
diff --git a/arch/arm64/boot/dts/qcom/qcs404-evb-4000.dts b/arch/arm64/boot/dts/qcom/qcs404-evb-4000.dts
index 08d5d51221cf..59702ba24f35 100644
--- a/arch/arm64/boot/dts/qcom/qcs404-evb-4000.dts
+++ b/arch/arm64/boot/dts/qcom/qcs404-evb-4000.dts
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
-// Copyright (c) 2018, Linaro Limited
+/*
+ * Copyright (c) 2018, Linaro Limited
+ */
/dts-v1/;
@@ -37,54 +39,54 @@
};
&tlmm {
- ethernet_defaults: ethernet-defaults {
- int {
+ ethernet_defaults: ethernet-defaults-state {
+ int-pins {
pins = "gpio61";
function = "rgmii_int";
bias-disable;
drive-strength = <2>;
};
- mdc {
+ mdc-pins {
pins = "gpio76";
function = "rgmii_mdc";
bias-pull-up;
};
- mdio {
+ mdio-pins {
pins = "gpio75";
function = "rgmii_mdio";
bias-pull-up;
};
- tx {
+ tx-pins {
pins = "gpio67", "gpio66", "gpio65", "gpio64";
function = "rgmii_tx";
bias-pull-up;
drive-strength = <16>;
};
- rx {
+ rx-pins {
pins = "gpio73", "gpio72", "gpio71", "gpio70";
function = "rgmii_rx";
bias-disable;
drive-strength = <2>;
};
- tx-ctl {
+ tx-ctl-pins {
pins = "gpio68";
function = "rgmii_ctl";
bias-pull-up;
drive-strength = <16>;
};
- rx-ctl {
+ rx-ctl-pins {
pins = "gpio74";
function = "rgmii_ctl";
bias-disable;
drive-strength = <2>;
};
- tx-ck {
+ tx-ck-pins {
pins = "gpio63";
function = "rgmii_ck";
bias-pull-up;
drive-strength = <16>;
};
- rx-ck {
+ rx-ck-pins {
pins = "gpio69";
function = "rgmii_ck";
bias-disable;
diff --git a/arch/arm64/boot/dts/qcom/qcs404-evb.dtsi b/arch/arm64/boot/dts/qcom/qcs404-evb.dtsi
index 1678ef0f8684..04c82d1624eb 100644
--- a/arch/arm64/boot/dts/qcom/qcs404-evb.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs404-evb.dtsi
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
-// Copyright (c) 2018, Linaro Limited
+/*
+ * Copyright (c) 2018, Linaro Limited
+ */
#include <dt-bindings/gpio/gpio.h>
#include "qcs404.dtsi"
@@ -125,7 +127,7 @@
};
&rpm_requests {
- pms405-regulators {
+ regulators {
compatible = "qcom,rpm-pms405-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -229,7 +231,7 @@
};
&tlmm {
- perst_state: perst {
+ perst_state: perst-state {
pins = "gpio43";
function = "gpio";
@@ -238,68 +240,63 @@
output-low;
};
- sdc1_on: sdc1-on {
- clk {
+ sdc1_on: sdc1-on-state {
+ clk-pins {
pins = "sdc1_clk";
bias-disable;
drive-strength = <16>;
};
- cmd {
+ cmd-pins {
pins = "sdc1_cmd";
bias-pull-up;
drive-strength = <10>;
};
- data {
+ data-pins {
pins = "sdc1_data";
bias-pull-up;
drive-strength = <10>;
};
- rclk {
+ rclk-pins {
pins = "sdc1_rclk";
bias-pull-down;
};
};
- sdc1_off: sdc1-off {
- clk {
+ sdc1_off: sdc1-off-state {
+ clk-pins {
pins = "sdc1_clk";
bias-disable;
drive-strength = <2>;
};
- cmd {
+ cmd-pins {
pins = "sdc1_cmd";
bias-pull-up;
drive-strength = <2>;
};
- data {
+ data-pins {
pins = "sdc1_data";
bias-pull-up;
drive-strength = <2>;
};
- rclk {
+ rclk-pins {
pins = "sdc1_rclk";
bias-pull-down;
};
};
- usb3_id_pin: usb3-id-pin {
- pinmux {
- pins = "gpio116";
- function = "gpio";
- };
+ usb3_id_pin: usb3-id-state {
+ pins = "gpio116";
+ function = "gpio";
- pinconf {
- pins = "gpio116";
- drive-strength = <2>;
- bias-pull-up;
- input-enable;
- };
+ drive-strength = <2>;
+ bias-pull-up;
+ input-enable;
};
};
@@ -366,31 +363,28 @@
/* PINCTRL - additions to nodes defined in qcs404.dtsi */
&blsp1_uart2_default {
- rx {
+ rx-pins {
drive-strength = <2>;
bias-disable;
};
- tx {
+ tx-pins {
drive-strength = <2>;
bias-disable;
};
};
&blsp1_uart3_default {
- cts {
- pins = "gpio84";
+ cts-pins {
bias-disable;
};
- rts-tx {
- pins = "gpio85", "gpio82";
+ rts-tx-pins {
drive-strength = <2>;
bias-disable;
};
- rx {
- pins = "gpio83";
+ rx-pins {
bias-pull-up;
};
};
diff --git a/arch/arm64/boot/dts/qcom/qcs404.dtsi b/arch/arm64/boot/dts/qcom/qcs404.dtsi
index 80f2d05595fa..a5324eecb50a 100644
--- a/arch/arm64/boot/dts/qcom/qcs404.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs404.dtsi
@@ -1,5 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
-// Copyright (c) 2018, Linaro Limited
+/*
+ * Copyright (c) 2018, Linaro Limited
+ */
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/qcom,gcc-qcs404.h>
@@ -593,118 +595,130 @@
interrupt-controller;
#interrupt-cells = <2>;
- blsp1_i2c0_default: blsp1-i2c0-default {
+ blsp1_i2c0_default: blsp1-i2c0-default-state {
pins = "gpio32", "gpio33";
function = "blsp_i2c0";
};
- blsp1_i2c1_default: blsp1-i2c1-default {
+ blsp1_i2c1_default: blsp1-i2c1-default-state {
pins = "gpio24", "gpio25";
function = "blsp_i2c1";
};
- blsp1_i2c2_default: blsp1-i2c2-default {
- sda {
+ blsp1_i2c2_default: blsp1-i2c2-default-state {
+ sda-pins {
pins = "gpio19";
function = "blsp_i2c_sda_a2";
};
- scl {
+ scl-pins {
pins = "gpio20";
function = "blsp_i2c_scl_a2";
};
};
- blsp1_i2c3_default: blsp1-i2c3-default {
+ blsp1_i2c3_default: blsp1-i2c3-default-state {
pins = "gpio84", "gpio85";
function = "blsp_i2c3";
};
- blsp1_i2c4_default: blsp1-i2c4-default {
+ blsp1_i2c4_default: blsp1-i2c4-default-state {
pins = "gpio117", "gpio118";
function = "blsp_i2c4";
};
- blsp1_uart0_default: blsp1-uart0-default {
+ blsp1_uart0_default: blsp1-uart0-default-state {
pins = "gpio30", "gpio31", "gpio32", "gpio33";
function = "blsp_uart0";
};
- blsp1_uart1_default: blsp1-uart1-default {
+ blsp1_uart1_default: blsp1-uart1-default-state {
pins = "gpio22", "gpio23";
function = "blsp_uart1";
};
- blsp1_uart2_default: blsp1-uart2-default {
- rx {
+ blsp1_uart2_default: blsp1-uart2-default-state {
+ rx-pins {
pins = "gpio18";
function = "blsp_uart_rx_a2";
};
- tx {
+ tx-pins {
pins = "gpio17";
function = "blsp_uart_tx_a2";
};
};
- blsp1_uart3_default: blsp1-uart3-default {
- pins = "gpio82", "gpio83", "gpio84", "gpio85";
- function = "blsp_uart3";
+ blsp1_uart3_default: blsp1-uart3-default-state {
+ cts-pins {
+ pins = "gpio84";
+ function = "blsp_uart3";
+ };
+
+ rts-tx-pins {
+ pins = "gpio85", "gpio82";
+ function = "blsp_uart3";
+ };
+
+ rx-pins {
+ pins = "gpio83";
+ function = "blsp_uart3";
+ };
};
- blsp2_i2c0_default: blsp2-i2c0-default {
+ blsp2_i2c0_default: blsp2-i2c0-default-state {
pins = "gpio28", "gpio29";
function = "blsp_i2c5";
};
- blsp1_spi0_default: blsp1-spi0-default {
+ blsp1_spi0_default: blsp1-spi0-default-state {
pins = "gpio30", "gpio31", "gpio32", "gpio33";
function = "blsp_spi0";
};
- blsp1_spi1_default: blsp1-spi1-default {
- mosi {
+ blsp1_spi1_default: blsp1-spi1-default-state {
+ mosi-pins {
pins = "gpio22";
function = "blsp_spi_mosi_a1";
};
- miso {
+ miso-pins {
pins = "gpio23";
function = "blsp_spi_miso_a1";
};
- cs_n {
+ cs-n-pins {
pins = "gpio24";
function = "blsp_spi_cs_n_a1";
};
- clk {
+ clk-pins {
pins = "gpio25";
function = "blsp_spi_clk_a1";
};
};
- blsp1_spi2_default: blsp1-spi2-default {
+ blsp1_spi2_default: blsp1-spi2-default-state {
pins = "gpio17", "gpio18", "gpio19", "gpio20";
function = "blsp_spi2";
};
- blsp1_spi3_default: blsp1-spi3-default {
+ blsp1_spi3_default: blsp1-spi3-default-state {
pins = "gpio82", "gpio83", "gpio84", "gpio85";
function = "blsp_spi3";
};
- blsp1_spi4_default: blsp1-spi4-default {
+ blsp1_spi4_default: blsp1-spi4-default-state {
pins = "gpio37", "gpio38", "gpio117", "gpio118";
function = "blsp_spi4";
};
- blsp2_spi0_default: blsp2-spi0-default {
+ blsp2_spi0_default: blsp2-spi0-default-state {
pins = "gpio26", "gpio27", "gpio28", "gpio29";
function = "blsp_spi5";
};
- blsp2_uart0_default: blsp2-uart0-default {
+ blsp2_uart0_default: blsp2-uart0-default-state {
pins = "gpio26", "gpio27", "gpio28", "gpio29";
function = "blsp_uart5";
};
diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5-vision-mezzanine.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5-vision-mezzanine.dts
new file mode 100644
index 000000000000..bb149e577914
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5-vision-mezzanine.dts
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2022, Linaro Ltd.
+ */
+
+/dts-v1/;
+
+#include "qrb5165-rb5.dts"
+
+&camcc {
+ status = "okay";
+};
+
+&camss {
+ vdda-phy-supply = <&vreg_l5a_0p88>;
+ vdda-pll-supply = <&vreg_l9a_1p2>;
+ status = "okay";
+
+ ports {
+ /* The port index denotes CSIPHY id i.e. csiphy2 */
+ port@2 {
+ csiphy2_ep: endpoint {
+ clock-lanes = <7>;
+ data-lanes = <0 1 2 3>;
+ remote-endpoint = <&imx577_ep>;
+ };
+ };
+ };
+};
+
+&cci1 {
+ status = "okay";
+};
+
+&cci1_i2c0 {
+ camera@1a {
+ compatible = "sony,imx577";
+ reg = <0x1a>;
+
+ reset-gpios = <&tlmm 78 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default", "suspend";
+ pinctrl-0 = <&cam2_default>;
+ pinctrl-1 = <&cam2_suspend>;
+
+ clocks = <&camcc CAM_CC_MCLK2_CLK>;
+ assigned-clocks = <&camcc CAM_CC_MCLK2_CLK>;
+ assigned-clock-rates = <24000000>;
+
+ dovdd-supply = <&vreg_l7f_1p8>;
+ avdd-supply = <&vdc_5v>;
+ dvdd-supply = <&vdc_5v>;
+
+ port {
+ imx577_ep: endpoint {
+ clock-lanes = <1>;
+ link-frequencies = /bits/ 64 <600000000>;
+ data-lanes = <1 2 3 4>;
+ remote-endpoint = <&csiphy2_ep>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
index bf8077a1cf9a..8c64cb060e21 100644
--- a/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
+++ b/arch/arm64/boot/dts/qcom/qrb5165-rb5.dts
@@ -867,7 +867,7 @@
};
&q6afedai {
- qi2s@16 {
+ dai@16 {
reg = <PRIMARY_MI2S_RX>;
qcom,sd-lines = <0 1 2 3>;
};
@@ -875,7 +875,7 @@
/* TERT I2S Uses 1 I2S SD Lines for audio on LT9611 HDMI Bridge */
&q6afedai {
- qi2s@20 {
+ dai@20 {
reg = <TERTIARY_MI2S_RX>;
qcom,sd-lines = <0>;
};
@@ -904,7 +904,7 @@
cd-gpios = <&tlmm 77 GPIO_ACTIVE_LOW>;
bus-width = <4>;
no-sdio;
- no-emmc;
+ no-mmc;
};
&sound {
@@ -1007,7 +1007,7 @@
};
&swr0 {
- left_spkr: wsa8810-left{
+ left_spkr: speaker@0,3 {
compatible = "sdw10217211000";
reg = <0 3>;
powerdown-gpios = <&tlmm 130 GPIO_ACTIVE_HIGH>;
@@ -1016,7 +1016,7 @@
#sound-dai-cells = <0>;
};
- right_spkr: wsa8810-right{
+ right_spkr: speaker@0,4 {
compatible = "sdw10217211000";
reg = <0 4>;
powerdown-gpios = <&tlmm 130 GPIO_ACTIVE_HIGH>;
@@ -1210,33 +1210,33 @@
"HST_WLAN_UART_TX",
"HST_WLAN_UART_RX";
- lt9611_irq_pin: lt9611-irq {
+ lt9611_irq_pin: lt9611-irq-state {
pins = "gpio63";
function = "gpio";
bias-disable;
};
- sdc2_default_state: sdc2-default {
- clk {
+ sdc2_default_state: sdc2-default-state {
+ clk-pins {
pins = "sdc2_clk";
bias-disable;
drive-strength = <16>;
};
- cmd {
+ cmd-pins {
pins = "sdc2_cmd";
bias-pull-up;
drive-strength = <10>;
};
- data {
+ data-pins {
pins = "sdc2_data";
bias-pull-up;
drive-strength = <10>;
};
};
- sdc2_card_det_n: sd-card-det-n {
+ sdc2_card_det_n: sd-card-det-n-state {
pins = "gpio77";
function = "gpio";
bias-pull-up;
diff --git a/arch/arm64/boot/dts/qcom/sa8155p-adp.dts b/arch/arm64/boot/dts/qcom/sa8155p-adp.dts
index 4dee790f1049..f41dcc379dce 100644
--- a/arch/arm64/boot/dts/qcom/sa8155p-adp.dts
+++ b/arch/arm64/boot/dts/qcom/sa8155p-adp.dts
@@ -136,9 +136,8 @@
regulator-max-microvolt = <880000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
regulator-allow-set-load;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
vreg_l7a_1p8: ldo7 {
@@ -154,9 +153,8 @@
regulator-max-microvolt = <2960000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
regulator-allow-set-load;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
vreg_l11a_0p8: ldo11 {
@@ -263,9 +261,8 @@
regulator-max-microvolt = <1200000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
regulator-allow-set-load;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
vreg_l7c_1p8: ldo7 {
@@ -281,9 +278,8 @@
regulator-max-microvolt = <1200000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
regulator-allow-set-load;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
vreg_l10c_3p3: ldo10 {
@@ -397,7 +393,7 @@
vmmc-supply = <&vreg_l17a_2p96>; /* Card power line */
bus-width = <4>;
no-sdio;
- no-emmc;
+ no-mmc;
};
&uart2 {
@@ -488,26 +484,26 @@
&tlmm {
gpio-reserved-ranges = <0 4>;
- sdc2_on: sdc2_on {
- clk {
+ sdc2_on: sdc2-on-state {
+ clk-pins {
pins = "sdc2_clk";
bias-disable; /* No pull */
drive-strength = <16>; /* 16 MA */
};
- cmd {
+ cmd-pins {
pins = "sdc2_cmd";
bias-pull-up; /* pull up */
drive-strength = <16>; /* 16 MA */
};
- data {
+ data-pins {
pins = "sdc2_data";
bias-pull-up; /* pull up */
drive-strength = <16>; /* 16 MA */
};
- sd-cd {
+ sd-cd-pins {
pins = "gpio96";
function = "gpio";
bias-pull-up; /* pull up */
@@ -515,26 +511,26 @@
};
};
- sdc2_off: sdc2_off {
- clk {
+ sdc2_off: sdc2-off-state {
+ clk-pins {
pins = "sdc2_clk";
bias-disable; /* No pull */
drive-strength = <2>; /* 2 MA */
};
- cmd {
+ cmd-pins {
pins = "sdc2_cmd";
bias-pull-up; /* pull up */
drive-strength = <2>; /* 2 MA */
};
- data {
+ data-pins {
pins = "sdc2_data";
bias-pull-up; /* pull up */
drive-strength = <2>; /* 2 MA */
};
- sd-cd {
+ sd-cd-pins {
pins = "gpio96";
function = "gpio";
bias-pull-up; /* pull up */
@@ -542,66 +538,62 @@
};
};
- usb2phy_ac_en1_default: usb2phy_ac_en1_default {
- mux {
- pins = "gpio113";
- function = "usb2phy_ac";
- bias-disable;
- drive-strength = <2>;
- };
+ usb2phy_ac_en1_default: usb2phy-ac-en1-default-state {
+ pins = "gpio113";
+ function = "usb2phy_ac";
+ bias-disable;
+ drive-strength = <2>;
};
- usb2phy_ac_en2_default: usb2phy_ac_en2_default {
- mux {
- pins = "gpio123";
- function = "usb2phy_ac";
- bias-disable;
- drive-strength = <2>;
- };
+ usb2phy_ac_en2_default: usb2phy-ac-en2-default-state {
+ pins = "gpio123";
+ function = "usb2phy_ac";
+ bias-disable;
+ drive-strength = <2>;
};
- ethernet_defaults: ethernet-defaults {
- mdc {
+ ethernet_defaults: ethernet-defaults-state {
+ mdc-pins {
pins = "gpio7";
function = "rgmii";
bias-pull-up;
};
- mdio {
+ mdio-pins {
pins = "gpio59";
function = "rgmii";
bias-pull-up;
};
- rgmii-rx {
+ rgmii-rx-pins {
pins = "gpio117", "gpio118", "gpio119", "gpio120", "gpio115", "gpio116";
function = "rgmii";
bias-disable;
drive-strength = <2>;
};
- rgmii-tx {
+ rgmii-tx-pins {
pins = "gpio122", "gpio4", "gpio5", "gpio6", "gpio114", "gpio121";
function = "rgmii";
bias-pull-up;
drive-strength = <16>;
};
- phy-intr {
+ phy-intr-pins {
pins = "gpio124";
function = "emac_phy";
bias-disable;
drive-strength = <8>;
};
- pps {
+ pps-pins {
pins = "gpio81";
function = "emac_pps";
bias-disable;
drive-strength = <8>;
};
- phy-reset {
+ phy-reset-pins {
pins = "gpio79";
function = "gpio";
bias-pull-up;
diff --git a/arch/arm64/boot/dts/qcom/sa8295p-adp.dts b/arch/arm64/boot/dts/qcom/sa8295p-adp.dts
index 2c62ba6a49c5..84cb6f3eeb56 100644
--- a/arch/arm64/boot/dts/qcom/sa8295p-adp.dts
+++ b/arch/arm64/boot/dts/qcom/sa8295p-adp.dts
@@ -57,6 +57,13 @@
regulator-max-microvolt = <3072000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
+
+ vreg_l11a: ldo11 {
+ regulator-name = "vreg_l11a";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
};
pmm8540-c-regulators {
@@ -83,9 +90,8 @@
regulator-max-microvolt = <1200000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
regulator-allow-set-load;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
vreg_l4c: ldo4 {
@@ -101,9 +107,8 @@
regulator-max-microvolt = <1200000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
regulator-allow-set-load;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
vreg_l7c: ldo7 {
@@ -119,9 +124,8 @@
regulator-max-microvolt = <2504000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
regulator-allow-set-load;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
vreg_l17c: ldo17 {
@@ -130,9 +134,8 @@
regulator-max-microvolt = <2504000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
regulator-allow-set-load;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
};
@@ -163,6 +166,76 @@
};
};
+&pcie2a {
+ perst-gpios = <&tlmm 143 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 145 GPIO_ACTIVE_LOW>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2a_default>;
+
+ status = "okay";
+};
+
+&pcie2a_phy {
+ vdda-phy-supply = <&vreg_l11a>;
+ vdda-pll-supply = <&vreg_l3a>;
+
+ status = "okay";
+};
+
+&pcie3a {
+ num-lanes = <2>;
+
+ perst-gpios = <&tlmm 151 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 56 GPIO_ACTIVE_LOW>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie3a_default>;
+
+ status = "okay";
+};
+
+&pcie3a_phy {
+ vdda-phy-supply = <&vreg_l11a>;
+ vdda-pll-supply = <&vreg_l3a>;
+
+ status = "okay";
+};
+
+&pcie3b {
+ perst-gpios = <&tlmm 153 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 130 GPIO_ACTIVE_LOW>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie3b_default>;
+
+ status = "okay";
+};
+
+&pcie3b_phy {
+ vdda-phy-supply = <&vreg_l11a>;
+ vdda-pll-supply = <&vreg_l3a>;
+
+ status = "okay";
+};
+
+&pcie4 {
+ perst-gpios = <&tlmm 141 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 139 GPIO_ACTIVE_LOW>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie4_default>;
+
+ status = "okay";
+};
+
+&pcie4_phy {
+ vdda-phy-supply = <&vreg_l11a>;
+ vdda-pll-supply = <&vreg_l3a>;
+
+ status = "okay";
+};
+
&qup2 {
status = "okay";
};
@@ -194,6 +267,14 @@
#address-cells = <1>;
#size-cells = <0>;
+ rtc@6000 {
+ compatible = "qcom,pm8941-rtc";
+ reg = <0x6000>;
+ reg-names = "rtc", "alarm";
+ interrupts = <0x0 0x61 0x1 IRQ_TYPE_NONE>;
+ wakeup-source;
+ };
+
pm8450a_gpios: gpio@c000 {
compatible = "qcom,pm8150-gpio", "qcom,spmi-gpio";
reg = <0xc000>;
@@ -392,3 +473,97 @@
};
/* PINCTRL */
+
+&tlmm {
+ pcie2a_default: pcie2a-default-state {
+ clkreq-n-pins {
+ pins = "gpio142";
+ function = "pcie2a_clkreq";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ perst-n-pins {
+ pins = "gpio143";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ wake-n-pins {
+ pins = "gpio145";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ pcie3a_default: pcie3a-default-state {
+ clkreq-n-pins {
+ pins = "gpio150";
+ function = "pcie3a_clkreq";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ perst-n-pins {
+ pins = "gpio151";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ wake-n-pins {
+ pins = "gpio56";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ pcie3b_default: pcie3b-default-state {
+ clkreq-n-pins {
+ pins = "gpio152";
+ function = "pcie3b_clkreq";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ perst-n-pins {
+ pins = "gpio153";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ wake-n-pins {
+ pins = "gpio130";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ pcie4_default: pcie4-default-state {
+ clkreq-n-pins {
+ pins = "gpio140";
+ function = "pcie4_clkreq";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ perst-n-pins {
+ pins = "gpio141";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ wake-n-pins {
+ pins = "gpio139";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sa8540p-ride.dts b/arch/arm64/boot/dts/qcom/sa8540p-ride.dts
new file mode 100644
index 000000000000..6c547f1b13dc
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sa8540p-ride.dts
@@ -0,0 +1,270 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+
+#include "sa8540p.dtsi"
+#include "pm8450a.dtsi"
+
+/ {
+ model = "Qualcomm SA8540P Ride";
+ compatible = "qcom,sa8540p-ride", "qcom,sa8540p";
+
+ aliases {
+ serial0 = &qup2_uart17;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+};
+
+&apps_rsc {
+ regulators-0 {
+ compatible = "qcom,pm8150-rpmh-regulators";
+ qcom,pmic-id = "a";
+
+ vreg_l3a: ldo3 {
+ regulator-name = "vreg_l3a";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1208000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l5a: ldo5 {
+ regulator-name = "vreg_l5a";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7a: ldo7 {
+ regulator-name = "vreg_l7a";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l11a: ldo11 {
+ regulator-name = "vreg_l11a";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l13a: ldo13 {
+ regulator-name = "vreg_l13a";
+ regulator-min-microvolt = <3072000>;
+ regulator-max-microvolt = <3072000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-1 {
+ compatible = "qcom,pm8150-rpmh-regulators";
+ qcom,pmic-id = "c";
+
+ vreg_l1c: ldo1 {
+ regulator-name = "vreg_l1c";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l2c: ldo2 {
+ regulator-name = "vreg_l2c";
+ regulator-min-microvolt = <3072000>;
+ regulator-max-microvolt = <3072000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l4c: ldo4 {
+ regulator-name = "vreg_l4c";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1208000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l6c: ldo6 {
+ regulator-name = "vreg_l6c";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ };
+
+ vreg_l7c: ldo7 {
+ regulator-name = "vreg_l7c";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l17c: ldo17 {
+ regulator-name = "vreg_l17c";
+ regulator-min-microvolt = <2504000>;
+ regulator-max-microvolt = <2504000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ };
+ };
+
+ regulators-2 {
+ compatible = "qcom,pm8150-rpmh-regulators";
+ qcom,pmic-id = "g";
+
+ vreg_l3g: ldo3 {
+ regulator-name = "vreg_l3g";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7g: ldo7 {
+ regulator-name = "vreg_l7g";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l8g: ldo8 {
+ regulator-name = "vreg_l8g";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+};
+
+&pcie3a {
+ ranges = <0x01000000 0x0 0x40200000 0x0 0x40200000 0x0 0x100000>,
+ <0x02000000 0x0 0x40300000 0x0 0x40300000 0x0 0x20000000>,
+ <0x03000000 0x6 0x00000000 0x6 0x00000000 0x2 0x00000000>;
+
+ perst-gpios = <&tlmm 151 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 56 GPIO_ACTIVE_HIGH>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie3a_default>;
+
+ status = "okay";
+};
+
+&pcie3a_phy {
+ vdda-phy-supply = <&vreg_l11a>;
+ vdda-pll-supply = <&vreg_l3a>;
+
+ status = "okay";
+};
+
+&qup2 {
+ status = "okay";
+};
+
+&qup2_uart17 {
+ compatible = "qcom,geni-debug-uart";
+ status = "okay";
+};
+
+&remoteproc_nsp0 {
+ firmware-name = "qcom/sa8540p/cdsp.mbn";
+ status = "okay";
+};
+
+&remoteproc_nsp1 {
+ firmware-name = "qcom/sa8540p/cdsp1.mbn";
+ status = "okay";
+};
+
+&tlmm {
+ pcie3a_default: pcie3a-default-state {
+ perst-pins {
+ pins = "gpio151";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ clkreq-pins {
+ pins = "gpio150";
+ function = "pcie3a_clkreq";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ wake-pins {
+ pins = "gpio56";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+};
+
+&ufs_mem_hc {
+ reset-gpios = <&tlmm 228 GPIO_ACTIVE_LOW>;
+
+ vcc-supply = <&vreg_l17c>;
+ vccq-supply = <&vreg_l6c>;
+
+ status = "okay";
+};
+
+&ufs_mem_phy {
+ vdda-phy-supply = <&vreg_l8g>;
+ vdda-pll-supply = <&vreg_l3g>;
+
+ status = "okay";
+};
+
+&usb_0 {
+ status = "okay";
+};
+
+&usb_0_dwc3 {
+ dr_mode = "peripheral";
+};
+
+&usb_0_hsphy {
+ vdda-pll-supply = <&vreg_l5a>;
+ vdda18-supply = <&vreg_l7a>;
+ vdda33-supply = <&vreg_l13a>;
+
+ status = "okay";
+};
+
+&usb_0_qmpphy {
+ vdda-phy-supply = <&vreg_l3a>;
+ vdda-pll-supply = <&vreg_l5a>;
+
+ status = "okay";
+};
+
+&usb_2_hsphy0 {
+ vdda-pll-supply = <&vreg_l5a>;
+ vdda18-supply = <&vreg_l7g>;
+ vdda33-supply = <&vreg_l13a>;
+
+ status = "okay";
+};
+
+&usb_2_qmpphy0 {
+ vdda-phy-supply = <&vreg_l3a>;
+ vdda-pll-supply = <&vreg_l5a>;
+
+ status = "okay";
+};
+
+&xo_board_clk {
+ clock-frequency = <38400000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sa8540p.dtsi b/arch/arm64/boot/dts/qcom/sa8540p.dtsi
index 8ea2886fbab2..a88452c20d05 100644
--- a/arch/arm64/boot/dts/qcom/sa8540p.dtsi
+++ b/arch/arm64/boot/dts/qcom/sa8540p.dtsi
@@ -14,59 +14,81 @@
compatible = "operating-points-v2";
opp-shared;
+ opp-300000000 {
+ opp-hz = /bits/ 64 <300000000>;
+ opp-peak-kBps = <(300000 * 32)>;
+ };
opp-403200000 {
opp-hz = /bits/ 64 <403200000>;
+ opp-peak-kBps = <(384000 * 32)>;
};
opp-499200000 {
opp-hz = /bits/ 64 <499200000>;
+ opp-peak-kBps = <(480000 * 32)>;
};
opp-595200000 {
opp-hz = /bits/ 64 <595200000>;
+ opp-peak-kBps = <(576000 * 32)>;
};
opp-710400000 {
opp-hz = /bits/ 64 <710400000>;
+ opp-peak-kBps = <(672000 * 32)>;
};
opp-806400000 {
opp-hz = /bits/ 64 <806400000>;
+ opp-peak-kBps = <(768000 * 32)>;
};
opp-902400000 {
opp-hz = /bits/ 64 <902400000>;
+ opp-peak-kBps = <(864000 * 32)>;
};
opp-1017600000 {
opp-hz = /bits/ 64 <1017600000>;
+ opp-peak-kBps = <(960000 * 32)>;
};
opp-1113600000 {
opp-hz = /bits/ 64 <1113600000>;
+ opp-peak-kBps = <(1075200 * 32)>;
};
opp-1209600000 {
opp-hz = /bits/ 64 <1209600000>;
+ opp-peak-kBps = <(1171200 * 32)>;
};
opp-1324800000 {
opp-hz = /bits/ 64 <1324800000>;
+ opp-peak-kBps = <(1286400 * 32)>;
};
opp-1440000000 {
opp-hz = /bits/ 64 <1440000000>;
+ opp-peak-kBps = <(1382400 * 32)>;
};
opp-1555200000 {
opp-hz = /bits/ 64 <1555200000>;
+ opp-peak-kBps = <(1497600 * 32)>;
};
opp-1670400000 {
opp-hz = /bits/ 64 <1670400000>;
+ opp-peak-kBps = <(1593600 * 32)>;
};
opp-1785600000 {
opp-hz = /bits/ 64 <1785600000>;
+ opp-peak-kBps = <(1708800 * 32)>;
};
opp-1881600000 {
opp-hz = /bits/ 64 <1881600000>;
+ opp-peak-kBps = <(1708800 * 32)>;
};
opp-2016000000 {
opp-hz = /bits/ 64 <2016000000>;
+ opp-peak-kBps = <(1708800 * 32)>;
};
opp-2131200000 {
opp-hz = /bits/ 64 <2131200000>;
+ opp-peak-kBps = <(1708800 * 32)>;
};
opp-2246400000 {
opp-hz = /bits/ 64 <2246400000>;
+ opp-peak-kBps = <(1708800 * 32)>;
};
};
@@ -76,58 +98,134 @@
opp-825600000 {
opp-hz = /bits/ 64 <825600000>;
+ opp-peak-kBps = <(300000 * 32)>;
};
opp-940800000 {
opp-hz = /bits/ 64 <940800000>;
+ opp-peak-kBps = <(864000 * 32)>;
};
opp-1056000000 {
opp-hz = /bits/ 64 <1056000000>;
+ opp-peak-kBps = <(960000 * 32)>;
};
opp-1171200000 {
opp-hz = /bits/ 64 <1171200000>;
+ opp-peak-kBps = <(1171200 * 32)>;
};
opp-1286400000 {
opp-hz = /bits/ 64 <1286400000>;
+ opp-peak-kBps = <(1286400 * 32)>;
};
opp-1401600000 {
opp-hz = /bits/ 64 <1401600000>;
+ opp-peak-kBps = <(1382400 * 32)>;
};
opp-1516800000 {
opp-hz = /bits/ 64 <1516800000>;
+ opp-peak-kBps = <(1497600 * 32)>;
};
opp-1632000000 {
opp-hz = /bits/ 64 <1632000000>;
+ opp-peak-kBps = <(1593600 * 32)>;
};
opp-1747200000 {
opp-hz = /bits/ 64 <1747200000>;
+ opp-peak-kBps = <(1593600 * 32)>;
};
opp-1862400000 {
opp-hz = /bits/ 64 <1862400000>;
+ opp-peak-kBps = <(1708800 * 32)>;
};
opp-1977600000 {
opp-hz = /bits/ 64 <1977600000>;
+ opp-peak-kBps = <(1708800 * 32)>;
};
opp-2073600000 {
opp-hz = /bits/ 64 <2073600000>;
+ opp-peak-kBps = <(1708800 * 32)>;
};
opp-2169600000 {
opp-hz = /bits/ 64 <2169600000>;
+ opp-peak-kBps = <(1708800 * 32)>;
};
opp-2284800000 {
opp-hz = /bits/ 64 <2284800000>;
+ opp-peak-kBps = <(1708800 * 32)>;
};
opp-2380800000 {
opp-hz = /bits/ 64 <2380800000>;
+ opp-peak-kBps = <(1708800 * 32)>;
};
opp-2496000000 {
opp-hz = /bits/ 64 <2496000000>;
+ opp-peak-kBps = <(1708800 * 32)>;
};
opp-2592000000 {
opp-hz = /bits/ 64 <2592000000>;
+ opp-peak-kBps = <(1708800 * 32)>;
};
};
};
+&pcie2a {
+ compatible = "qcom,pcie-sa8540p";
+
+ linux,pci-domain = <0>;
+
+ interrupts = <GIC_SPI 440 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+};
+
+&pcie2b {
+ compatible = "qcom,pcie-sa8540p";
+
+ linux,pci-domain = <1>;
+
+ interrupts = <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+};
+
+&pcie3a {
+ compatible = "qcom,pcie-sa8540p";
+ reg = <0x0 0x01c10000 0x0 0x3000>,
+ <0x0 0x40000000 0x0 0xf1d>,
+ <0x0 0x40000f20 0x0 0xa8>,
+ <0x0 0x40001000 0x0 0x1000>,
+ <0x0 0x40100000 0x0 0x100000>;
+ reg-names = "parf", "dbi", "elbi", "atu", "config";
+
+ ranges = <0x01000000 0x0 0x40200000 0x0 0x40200000 0x0 0x100000>,
+ <0x02000000 0x0 0x40300000 0x0 0x40300000 0x0 0x1d00000>;
+
+ linux,pci-domain = <2>;
+
+ interrupts = <GIC_SPI 567 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+
+ interrupt-map = <0 0 0 1 &intc 0 0 GIC_SPI 541 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &intc 0 0 GIC_SPI 542 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &intc 0 0 GIC_SPI 543 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &intc 0 0 GIC_SPI 544 IRQ_TYPE_LEVEL_HIGH>;
+};
+
+&pcie3b {
+ compatible = "qcom,pcie-sa8540p";
+
+ linux,pci-domain = <3>;
+
+ interrupts = <GIC_SPI 565 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+};
+
+&pcie4 {
+ compatible = "qcom,pcie-sa8540p";
+
+ linux,pci-domain = <4>;
+
+ interrupts = <GIC_SPI 518 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi";
+};
+
&rpmhpd {
compatible = "qcom,sa8540p-rpmhpd";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-idp.dts b/arch/arm64/boot/dts/qcom/sc7180-idp.dts
index 9dee131b1e24..70fd9ff8dfa2 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-idp.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-idp.dts
@@ -481,287 +481,261 @@
};
&qspi_clk {
- pinconf {
- pins = "gpio63";
- bias-disable;
- };
+ bias-disable;
};
&qspi_cs0 {
- pinconf {
- pins = "gpio68";
- bias-disable;
- };
+ bias-disable;
};
&qspi_data01 {
- pinconf {
- pins = "gpio64", "gpio65";
-
- /* High-Z when no transfers; nice to park the lines */
- bias-pull-up;
- };
+ /* High-Z when no transfers; nice to park the lines */
+ bias-pull-up;
};
&qup_i2c2_default {
- pinconf {
- pins = "gpio15", "gpio16";
- drive-strength = <2>;
+ drive-strength = <2>;
- /* Has external pullup */
- bias-disable;
- };
+ /* Has external pullup */
+ bias-disable;
};
&qup_i2c4_default {
- pinconf {
- pins = "gpio115", "gpio116";
- drive-strength = <2>;
+ drive-strength = <2>;
- /* Has external pullup */
- bias-disable;
- };
+ /* Has external pullup */
+ bias-disable;
};
&qup_i2c7_default {
- pinconf {
- pins = "gpio6", "gpio7";
- drive-strength = <2>;
+ drive-strength = <2>;
- /* Has external pullup */
- bias-disable;
- };
+ /* Has external pullup */
+ bias-disable;
};
&qup_i2c9_default {
- pinconf {
- pins = "gpio46", "gpio47";
- drive-strength = <2>;
+ drive-strength = <2>;
- /* Has external pullup */
- bias-disable;
- };
+ /* Has external pullup */
+ bias-disable;
};
-&qup_uart3_default {
- pinconf-cts {
- /*
- * Configure a pull-down on CTS to match the pull of
- * the Bluetooth module.
- */
- pins = "gpio38";
- bias-pull-down;
- };
+&qup_uart3_cts {
+ /*
+ * Configure a pull-down on CTS to match the pull of
+ * the Bluetooth module.
+ */
+ bias-pull-down;
+};
- pinconf-rts {
- /* We'll drive RTS, so no pull */
- pins = "gpio39";
- drive-strength = <2>;
- bias-disable;
- };
+&qup_uart3_rts {
+ /* We'll drive RTS, so no pull */
+ drive-strength = <2>;
+ bias-disable;
+};
- pinconf-tx {
- /* We'll drive TX, so no pull */
- pins = "gpio40";
- drive-strength = <2>;
- bias-disable;
- };
+&qup_uart3_tx {
+ /* We'll drive TX, so no pull */
+ drive-strength = <2>;
+ bias-disable;
+};
- pinconf-rx {
- /*
- * Configure a pull-up on RX. This is needed to avoid
- * garbage data when the TX pin of the Bluetooth module is
- * in tri-state (module powered off or not driving the
- * signal yet).
- */
- pins = "gpio41";
- bias-pull-up;
- };
+&qup_uart3_rx {
+ /*
+ * Configure a pull-up on RX. This is needed to avoid
+ * garbage data when the TX pin of the Bluetooth module is
+ * in tri-state (module powered off or not driving the
+ * signal yet).
+ */
+ bias-pull-up;
};
-&qup_uart8_default {
- pinconf-tx {
- pins = "gpio44";
- drive-strength = <2>;
- bias-disable;
- };
+&qup_uart8_tx {
+ drive-strength = <2>;
+ bias-disable;
+};
- pinconf-rx {
- pins = "gpio45";
- drive-strength = <2>;
- bias-pull-up;
- };
+&qup_uart8_rx {
+ drive-strength = <2>;
+ bias-pull-up;
};
-&qup_spi0_default {
- pinconf {
- pins = "gpio34", "gpio35", "gpio36", "gpio37";
- drive-strength = <2>;
- bias-disable;
- };
+&qup_spi0_spi {
+ drive-strength = <2>;
+ bias-disable;
};
-&qup_spi6_default {
- pinconf {
- pins = "gpio59", "gpio60", "gpio61", "gpio62";
- drive-strength = <2>;
- bias-disable;
- };
+&qup_spi0_cs {
+ drive-strength = <2>;
+ bias-disable;
};
-&qup_spi10_default {
- pinconf {
- pins = "gpio86", "gpio87", "gpio88", "gpio89";
- drive-strength = <2>;
- bias-disable;
- };
+&qup_spi6_spi {
+ drive-strength = <2>;
+ bias-disable;
};
-&tlmm {
- qup_uart3_sleep: qup-uart3-sleep {
- pinmux {
- pins = "gpio38", "gpio39",
- "gpio40", "gpio41";
- function = "gpio";
- };
+&qup_spi6_cs {
+ drive-strength = <2>;
+ bias-disable;
+};
+
+&qup_spi10_spi {
+ drive-strength = <2>;
+ bias-disable;
+};
+
+&qup_spi10_cs {
+ drive-strength = <2>;
+ bias-disable;
+};
- pinconf-cts {
+&tlmm {
+ qup_uart3_sleep: qup-uart3-sleep-state {
+ cts-pins {
/*
* Configure a pull-down on CTS to match the pull of
* the Bluetooth module.
*/
pins = "gpio38";
+ function = "gpio";
bias-pull-down;
};
- pinconf-rts {
+ rts-pins {
/*
* Configure pull-down on RTS. As RTS is active low
* signal, pull it low to indicate the BT SoC that it
* can wakeup the system anytime from suspend state by
* pulling RX low (by sending wakeup bytes).
*/
- pins = "gpio39";
- bias-pull-down;
+ pins = "gpio39";
+ function = "gpio";
+ bias-pull-down;
};
- pinconf-tx {
+ tx-pins {
/*
* Configure pull-up on TX when it isn't actively driven
* to prevent BT SoC from receiving garbage during sleep.
*/
pins = "gpio40";
+ function = "gpio";
bias-pull-up;
};
- pinconf-rx {
+ rx-pins {
/*
* Configure a pull-up on RX. This is needed to avoid
* garbage data when the TX pin of the Bluetooth module
* is floating which may cause spurious wakeups.
*/
pins = "gpio41";
+ function = "gpio";
bias-pull-up;
};
};
- sdc1_on: sdc1-on {
- pinconf-clk {
+ sdc1_on: sdc1-on-state {
+ clk-pins {
pins = "sdc1_clk";
bias-disable;
drive-strength = <16>;
};
- pinconf-cmd {
+ cmd-pins {
pins = "sdc1_cmd";
bias-pull-up;
drive-strength = <10>;
};
- pinconf-data {
+ data-pins {
pins = "sdc1_data";
bias-pull-up;
drive-strength = <10>;
};
- pinconf-rclk {
+ rclk-pins {
pins = "sdc1_rclk";
bias-pull-down;
};
};
- sdc1_off: sdc1-off {
- pinconf-clk {
+ sdc1_off: sdc1-off-state {
+ clk-pins {
pins = "sdc1_clk";
bias-disable;
drive-strength = <2>;
};
- pinconf-cmd {
+ cmd-pins {
pins = "sdc1_cmd";
bias-pull-up;
drive-strength = <2>;
};
- pinconf-data {
+ data-pins {
pins = "sdc1_data";
bias-pull-up;
drive-strength = <2>;
};
- pinconf-rclk {
+ rclk-pins {
pins = "sdc1_rclk";
bias-pull-down;
};
};
- sdc2_on: sdc2-on {
- pinconf-clk {
+ sdc2_on: sdc2-on-state {
+ clk-pins {
pins = "sdc2_clk";
bias-disable;
drive-strength = <16>;
};
- pinconf-cmd {
+ cmd-pins {
pins = "sdc2_cmd";
bias-pull-up;
drive-strength = <10>;
};
- pinconf-data {
+ data-pins {
pins = "sdc2_data";
bias-pull-up;
drive-strength = <10>;
};
- pinconf-sd-cd {
+ sd-cd-pins {
pins = "gpio69";
+ function = "gpio";
bias-pull-up;
drive-strength = <2>;
};
};
- sdc2_off: sdc2-off {
- pinconf-clk {
+ sdc2_off: sdc2-off-state {
+ clk-pins {
pins = "sdc2_clk";
bias-disable;
drive-strength = <2>;
};
- pinconf-cmd {
+ cmd-pins {
pins = "sdc2_cmd";
bias-pull-up;
drive-strength = <2>;
};
- pinconf-data {
+ data-pins {
pins = "sdc2_data";
bias-pull-up;
drive-strength = <2>;
};
- pinconf-sd-cd {
+ sd-cd-pins {
pins = "gpio69";
+ function = "gpio";
bias-pull-up;
drive-strength = <2>;
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi
index 7ee407f7b6bb..8b8ea8af165d 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-coachz.dtsi
@@ -181,23 +181,15 @@ ap_ts_pen_1v8: &i2c4 {
/* PINCTRL - modifications to sc7180-trogdor.dtsi */
&en_pp3300_dx_edp {
- pinmux {
- pins = "gpio67";
- };
-
- pinconf {
- pins = "gpio67";
- };
+ pins = "gpio67";
};
&ts_reset_l {
- pinconf {
- /*
- * We want reset state by default and it will be up to the
- * driver to disable this when it's ready.
- */
- output-low;
- };
+ /*
+ * We want reset state by default and it will be up to the
+ * driver to disable this when it's ready.
+ */
+ output-low;
};
/* PINCTRL - board-specific pinctrl */
@@ -327,16 +319,10 @@ ap_ts_pen_1v8: &i2c4 {
"DP_HOT_PLUG_DET",
"EC_IN_RW_ODL";
- dmic_clk_en: dmic_clk_en {
- pinmux {
- pins = "gpio83";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio83";
- drive-strength = <8>;
- bias-pull-up;
- };
+ dmic_clk_en: dmic-clk-en-state {
+ pins = "gpio83";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-up;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi
index 1bd6c7dcd9e9..d3cf64c16dcd 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-homestar.dtsi
@@ -10,22 +10,22 @@
/ {
/* BOARD-SPECIFIC TOP LEVEL NODES */
- max98360a_1: max98360a_1 {
+ max98360a_1: amplifier-1 {
compatible = "maxim,max98360a";
#sound-dai-cells = <0>;
};
- max98360a_2: max98360a_2 {
+ max98360a_2: amplifier-2 {
compatible = "maxim,max98360a";
#sound-dai-cells = <0>;
};
- max98360a_3: max98360a_3 {
+ max98360a_3: amplifier-3 {
compatible = "maxim,max98360a";
#sound-dai-cells = <0>;
};
- pp3300_touch: pp3300-touch {
+ pp3300_touch: pp3300-touch-regulator {
compatible = "regulator-fixed";
regulator-name = "pp3300_touch";
@@ -180,30 +180,19 @@ ap_ts_pen_1v8: &i2c4 {
/* PINCTRL - modifications to sc7180-trogdor.dtsi */
&en_pp3300_dx_edp {
- pinmux {
- pins = "gpio67";
- };
-
- pinconf {
- pins = "gpio67";
- };
+ pins = "gpio67";
};
-&sec_mi2s_active{
- pinmux {
- pins = "gpio49", "gpio50", "gpio51", "gpio52";
- function = "mi2s_1";
- };
+&sec_mi2s_active {
+ pins = "gpio49", "gpio50", "gpio51", "gpio52";
};
&ts_reset_l {
- pinconf {
- /*
- * We want reset state by default and it will be up to the
- * driver to disable this when it's ready.
- */
- output-low;
- };
+ /*
+ * We want reset state by default and it will be up to the
+ * driver to disable this when it's ready.
+ */
+ output-low;
};
/* PINCTRL - board-specific pinctrl */
@@ -333,16 +322,10 @@ ap_ts_pen_1v8: &i2c4 {
"DP_HOT_PLUG_DET",
"EC_IN_RW_ODL";
- en_pp3300_touch: en-pp3300-touch {
- pinmux {
- pins = "gpio87";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio87";
- drive-strength = <2>;
- bias-disable;
- };
+ en_pp3300_touch: en-pp3300-touch-state {
+ pins = "gpio87";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown-r0.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown-r0.dts
index 1a62e8d435ab..3abd6222fe46 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown-r0.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown-r0.dts
@@ -29,16 +29,10 @@
};
&tlmm {
- en_fp_rails: en-fp-rails {
- pinmux {
- pins = "gpio74";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio74";
- drive-strength = <2>;
- bias-disable;
- };
+ en_fp_rails: en-fp-rails-state {
+ pins = "gpio74";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown.dtsi
index 74f0e07ea5cf..315ac5eb5f78 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-kingoftown.dtsi
@@ -11,6 +11,7 @@
&alc5682 {
compatible = "realtek,rt5682s";
+ /delete-property/ VBAT-supply;
realtek,dmic1-clk-pin = <2>;
realtek,dmic-clk-rate-hz = <2048000>;
};
@@ -87,13 +88,7 @@ ap_ts_pen_1v8: &i2c4 {
/* PINCTRL - modifications to sc7180-trogdor.dtsi */
&en_pp3300_dx_edp {
- pinmux {
- pins = "gpio67";
- };
-
- pinconf {
- pins = "gpio67";
- };
+ pins = "gpio67";
};
/* PINCTRL - board-specific pinctrl */
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi
index 002663d752da..269007d73162 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-lazor.dtsi
@@ -75,21 +75,13 @@ ap_ts_pen_1v8: &i2c4 {
/* PINCTRL - modifications to sc7180-trogdor.dtsi */
&trackpad_int_1v8_odl {
- pinmux {
- pins = "gpio58";
- };
-
- pinconf {
- pins = "gpio58";
- };
+ pins = "gpio58";
};
&ts_reset_l {
- pinconf {
- /* This pin is not connected on -rev0, pull up to park. */
- /delete-property/bias-disable;
- bias-pull-up;
- };
+ /* This pin is not connected on -rev0, pull up to park. */
+ /delete-property/bias-disable;
+ bias-pull-up;
};
/* PINCTRL - board-specific pinctrl */
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-mrbland-rev0.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-mrbland-rev0.dtsi
index 7bc8402c018e..f4c1f3813664 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-mrbland-rev0.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-mrbland-rev0.dtsi
@@ -24,30 +24,13 @@
/* PINCTRL - modifications to sc7180-trogdor-mrbland.dtsi */
&avdd_lcd_en {
- pinmux {
- pins = "gpio80";
- };
-
- pinconf {
- pins = "gpio80";
- };
+ pins = "gpio80";
};
&mipi_1800_en {
- pinmux {
- pins = "gpio81";
- };
-
- pinconf {
- pins = "gpio81";
- };
+ pins = "gpio81";
};
-&vdd_reset_1800 {
- pinmux {
- pins = "gpio76";
- };
- pinconf {
- pins = "gpio76";
- };
+&vdd_reset_1800 {
+ pins = "gpio76";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-mrbland.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-mrbland.dtsi
index 97cba7f8064f..ed12ee35f06b 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-mrbland.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-mrbland.dtsi
@@ -13,7 +13,7 @@
/delete-node/ &usb_c1;
/ {
- avdd_lcd: avdd-lcd {
+ avdd_lcd: avdd-lcd-regulator {
compatible = "regulator-fixed";
regulator-name = "avdd_lcd";
@@ -25,7 +25,7 @@
vin-supply = <&pp5000_a>;
};
- avee_lcd: avee-lcd {
+ avee_lcd: avee-lcd-regulator {
compatible = "regulator-fixed";
regulator-name = "avee_lcd";
@@ -37,7 +37,7 @@
vin-supply = <&pp5000_a>;
};
- v1p8_mipi: v1p8-mipi {
+ v1p8_mipi: v1p8-mipi-regulator {
compatible = "regulator-fixed";
regulator-name = "v1p8_mipi";
@@ -160,13 +160,7 @@ pp3300_disp_on: &pp3300_dx_edp {
*/
tp_en: &en_pp3300_dx_edp {
- pinmux {
- pins = "gpio85";
- };
-
- pinconf {
- pins = "gpio85";
- };
+ pins = "gpio85";
};
/* PINCTRL - board-specific pinctrl */
@@ -296,55 +290,31 @@ tp_en: &en_pp3300_dx_edp {
"DP_HOT_PLUG_DET",
"EC_IN_RW_ODL";
- avdd_lcd_en: avdd-lcd-en {
- pinmux {
- pins = "gpio88";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio88";
- drive-strength = <2>;
- bias-disable;
- };
+ avdd_lcd_en: avdd-lcd-en-state {
+ pins = "gpio88";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
- avee_lcd_en: avee-lcd-en {
- pinmux {
- pins = "gpio21";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio21";
- drive-strength = <2>;
- bias-disable;
- };
+ avee_lcd_en: avee-lcd-en-state {
+ pins = "gpio21";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
- mipi_1800_en: mipi-1800-en {
- pinmux {
- pins = "gpio86";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio86";
- drive-strength = <2>;
- bias-disable;
- };
+ mipi_1800_en: mipi-1800-en-state {
+ pins = "gpio86";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
- vdd_reset_1800: vdd-reset-1800 {
- pinmux {
- pins = "gpio87";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio87";
- drive-strength = <2>;
- bias-disable;
- };
+ vdd_reset_1800: vdd-reset-1800-state {
+ pins = "gpio87";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-parade-ps8640.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-parade-ps8640.dtsi
index 6a84fba178d6..ebd6765e2afa 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-parade-ps8640.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-parade-ps8640.dtsi
@@ -8,7 +8,7 @@
#include <dt-bindings/gpio/gpio.h>
/ {
- pp3300_brij_ps8640: pp3300-brij-ps8640 {
+ pp3300_brij_ps8640: pp3300-brij-ps8640-regulator {
compatible = "regulator-fixed";
status = "okay";
regulator-name = "pp3300_brij_ps8640";
@@ -83,29 +83,17 @@ edp_brij_i2c: &i2c2 {
};
&tlmm {
- edp_brij_ps8640_rst: edp-brij-ps8640-rst {
- pinmux {
- pins = "gpio11";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio11";
- drive-strength = <2>;
- bias-disable;
- };
+ edp_brij_ps8640_rst: edp-brij-ps8640-rst-state {
+ pins = "gpio11";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
- en_pp3300_edp_brij_ps8640: en-pp3300-edp-brij-ps8640 {
- pinmux {
- pins = "gpio32";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio32";
- drive-strength = <2>;
- bias-disable;
- };
+ en_pp3300_edp_brij_ps8640: en-pp3300-edp-brij-ps8640-state {
+ pins = "gpio32";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel.dtsi
index 56d787785fd5..d06cc4ea3375 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel.dtsi
@@ -84,13 +84,7 @@
};
&en_pp3300_dx_edp {
- pinmux {
- pins = "gpio67";
- };
-
- pinconf {
- pins = "gpio67";
- };
+ pins = "gpio67";
};
/* PINCTRL - board-specific pinctrl */
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel360-lte.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel360-lte.dts
new file mode 100644
index 000000000000..021bcafcf815
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel360-lte.dts
@@ -0,0 +1,22 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Pazquel board device tree source
+ *
+ * Copyright 2021 Google LLC.
+ */
+
+/dts-v1/;
+
+#include "sc7180-trogdor.dtsi"
+#include "sc7180-trogdor-parade-ps8640.dtsi"
+#include "sc7180-trogdor-pazquel360.dtsi"
+#include "sc7180-trogdor-lte-sku.dtsi"
+
+/ {
+ model = "Google Pazquel (Parade,LTE)";
+ compatible = "google,pazquel-sku22", "google,pazquel-sku20", "qcom,sc7180";
+};
+
+&ap_sar_sensor_i2c {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel360-wifi.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel360-wifi.dts
new file mode 100644
index 000000000000..defd84c5354a
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel360-wifi.dts
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Pazquel board device tree source
+ *
+ * Copyright 2022 Google LLC.
+ */
+
+/dts-v1/;
+
+#include "sc7180-trogdor.dtsi"
+#include "sc7180-trogdor-parade-ps8640.dtsi"
+#include "sc7180-trogdor-pazquel360.dtsi"
+
+/ {
+ model = "Google Pazquel (Parade,WIFI-only)";
+ compatible = "google,pazquel-sku21", "qcom,sc7180";
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel360.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel360.dtsi
new file mode 100644
index 000000000000..5702325d0c7b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pazquel360.dtsi
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Pazquel board device tree source
+ *
+ * Copyright 2021 Google LLC.
+ */
+
+/* This file must be included after sc7180-trogdor.dtsi */
+#include "sc7180-trogdor-pazquel.dtsi"
+
+&alc5682 {
+ compatible = "realtek,rt5682s";
+ realtek,dmic1-clk-pin = <2>;
+ realtek,dmic-clk-rate-hz = <2048000>;
+};
+
+&keyboard_controller {
+ function-row-physmap = <
+ MATRIX_KEY(0x00, 0x02, 0) /* T1 */
+ MATRIX_KEY(0x03, 0x02, 0) /* T2 */
+ MATRIX_KEY(0x02, 0x02, 0) /* T3 */
+ MATRIX_KEY(0x01, 0x02, 0) /* T4 */
+ MATRIX_KEY(0x03, 0x04, 0) /* T5 */
+ MATRIX_KEY(0x02, 0x04, 0) /* T6 */
+ MATRIX_KEY(0x01, 0x04, 0) /* T7 */
+ MATRIX_KEY(0x02, 0x09, 0) /* T8 */
+ MATRIX_KEY(0x01, 0x09, 0) /* T9 */
+ MATRIX_KEY(0x00, 0x04, 0) /* T10 */
+ MATRIX_KEY(0x03, 0x09, 0) /* T11 */
+ >;
+ linux,keymap = <
+ MATRIX_KEY(0x00, 0x02, KEY_BACK)
+ MATRIX_KEY(0x03, 0x02, KEY_REFRESH)
+ MATRIX_KEY(0x02, 0x02, KEY_ZOOM)
+ MATRIX_KEY(0x01, 0x02, KEY_SCALE)
+ MATRIX_KEY(0x03, 0x04, KEY_SYSRQ)
+ MATRIX_KEY(0x02, 0x04, KEY_BRIGHTNESSDOWN)
+ MATRIX_KEY(0x01, 0x04, KEY_BRIGHTNESSUP)
+ MATRIX_KEY(0x02, 0x09, KEY_MUTE)
+ MATRIX_KEY(0x01, 0x09, KEY_VOLUMEDOWN)
+ MATRIX_KEY(0x00, 0x04, KEY_VOLUMEUP)
+ MATRIX_KEY(0x03, 0x09, KEY_SLEEP)
+ CROS_STD_MAIN_KEYMAP
+ >;
+};
+
+&sound {
+ compatible = "google,sc7180-trogdor";
+ model = "sc7180-rt5682s-max98357a-1mic";
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi
index a7582fb547ee..6c5287bd27d6 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-pompom.dtsi
@@ -312,15 +312,9 @@ ap_ts_pen_1v8: &i2c4 {
"DP_HOT_PLUG_DET",
"EC_IN_RW_ODL";
- dmic_sel: dmic-sel {
- pinmux {
- pins = "gpio86";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio86";
- bias-pull-down;
- };
+ dmic_sel: dmic-sel-state {
+ pins = "gpio86";
+ function = "gpio";
+ bias-pull-down;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick.dtsi
index 695b04fe7221..cb41ccdaccfd 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-quackingstick.dtsi
@@ -13,7 +13,7 @@
/delete-node/ &usb_c1;
/ {
- ppvar_lcd: ppvar-lcd {
+ ppvar_lcd: ppvar-lcd-regulator {
compatible = "regulator-fixed";
regulator-name = "ppvar_lcd";
@@ -25,7 +25,7 @@
vin-supply = <&pp5000_a>;
};
- v1p8_disp: v1p8-disp {
+ v1p8_disp: v1p8-disp-regulator {
compatible = "regulator-fixed";
regulator-name = "v1p8_disp";
@@ -147,13 +147,7 @@ pp3300_disp_on: &pp3300_dx_edp {
*/
tp_en: &en_pp3300_dx_edp {
- pinmux {
- pins = "gpio67";
- };
-
- pinconf {
- pins = "gpio67";
- };
+ pins = "gpio67";
};
/* PINCTRL - board-specific pinctrl */
@@ -283,42 +277,24 @@ tp_en: &en_pp3300_dx_edp {
"DP_HOT_PLUG_DET",
"EC_IN_RW_ODL";
- lcd_rst: lcd-rst {
- pinmux {
- pins = "gpio87";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio87";
- drive-strength = <2>;
- bias-disable;
- };
+ lcd_rst: lcd-rst-state {
+ pins = "gpio87";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
- ppvar_lcd_en: ppvar-lcd-en {
- pinmux {
- pins = "gpio88";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio88";
- drive-strength = <2>;
- bias-disable;
- };
+ ppvar_lcd_en: ppvar-lcd-en-state {
+ pins = "gpio88";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
- pp1800_disp_on: pp1800-disp-on {
- pinmux {
- pins = "gpio86";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio86";
- drive-strength = <2>;
- bias-disable;
- };
+ pp1800_disp_on: pp1800-disp-on-state {
+ pins = "gpio86";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-r1.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-r1.dts
index bc097d1b1b23..671b3691f1bb 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-r1.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-r1.dts
@@ -63,13 +63,7 @@ ap_ts_pen_1v8: &i2c4 {
/* PINCTRL - modifications to sc7180-trogdor.dtsi */
&trackpad_int_1v8_odl {
- pinmux {
- pins = "gpio58";
- };
-
- pinconf {
- pins = "gpio58";
- };
+ pins = "gpio58";
};
/* PINCTRL - board-specific pinctrl */
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-ti-sn65dsi86.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-ti-sn65dsi86.dtsi
index f869e6a343c1..65333709e529 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-ti-sn65dsi86.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-ti-sn65dsi86.dtsi
@@ -76,16 +76,10 @@ edp_brij_i2c: &i2c2 {
};
&tlmm {
- edp_brij_irq: edp-brij-irq {
- pinmux {
- pins = "gpio11";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio11";
- drive-strength = <2>;
- bias-pull-down;
- };
+ edp_brij_irq: edp-brij-irq-state {
+ pins = "gpio11";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev0.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev0.dtsi
index db29e0cba29d..7f272c6e95f6 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev0.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev0.dtsi
@@ -24,30 +24,13 @@
/* PINCTRL - modifications to sc7180-trogdor-wormdingler.dtsi */
&avdd_lcd_en {
- pinmux {
- pins = "gpio80";
- };
-
- pinconf {
- pins = "gpio80";
- };
+ pins = "gpio80";
};
&mipi_1800_en {
- pinmux {
- pins = "gpio81";
- };
-
- pinconf {
- pins = "gpio81";
- };
+ pins = "gpio81";
};
-&vdd_reset_1800 {
- pinmux {
- pins = "gpio76";
- };
- pinconf {
- pins = "gpio76";
- };
+&vdd_reset_1800 {
+ pins = "gpio76";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-boe-rt5682s.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-boe-rt5682s.dts
index aa605885c371..6225ab8329c3 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-boe-rt5682s.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-boe-rt5682s.dts
@@ -19,6 +19,7 @@
&alc5682 {
compatible = "realtek,rt5682s";
+ /delete-property/ VBAT-supply;
realtek,dmic1-clk-pin = <2>;
realtek,dmic-clk-rate-hz = <2048000>;
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-inx-rt5682s.dts b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-inx-rt5682s.dts
index 7116c44c8d85..b40b068dad6a 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-inx-rt5682s.dts
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler-rev1-inx-rt5682s.dts
@@ -19,6 +19,7 @@
&alc5682 {
compatible = "realtek,rt5682s";
+ /delete-property/ VBAT-supply;
realtek,dmic1-clk-pin = <2>;
realtek,dmic-clk-rate-hz = <2048000>;
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi
index 6312108e8b3e..9832e752da35 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor-wormdingler.dtsi
@@ -10,7 +10,7 @@
#include "sc7180-trogdor.dtsi"
/ {
- avdd_lcd: avdd-lcd {
+ avdd_lcd: avdd-lcd-regulator {
compatible = "regulator-fixed";
regulator-name = "avdd_lcd";
@@ -22,7 +22,7 @@
vin-supply = <&pp5000_a>;
};
- avee_lcd: avee-lcd {
+ avee_lcd: avee-lcd-regulator {
compatible = "regulator-fixed";
regulator-name = "avee_lcd";
@@ -35,7 +35,7 @@
};
pp1800_ts:
- v1p8_mipi: v1p8-mipi {
+ v1p8_mipi: v1p8-mipi-regulator {
compatible = "regulator-fixed";
regulator-name = "v1p8_mipi";
@@ -222,13 +222,7 @@ pp3300_disp_on: &pp3300_dx_edp {
*/
tp_en: &en_pp3300_dx_edp {
- pinmux {
- pins = "gpio85";
- };
-
- pinconf {
- pins = "gpio85";
- };
+ pins = "gpio85";
};
/* PINCTRL - board-specific pinctrl */
@@ -358,55 +352,31 @@ tp_en: &en_pp3300_dx_edp {
"DP_HOT_PLUG_DET",
"EC_IN_RW_ODL";
- avdd_lcd_en: avdd-lcd-en {
- pinmux {
- pins = "gpio88";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio88";
- drive-strength = <2>;
- bias-disable;
- };
+ avdd_lcd_en: avdd-lcd-en-state {
+ pins = "gpio88";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
- avee_lcd_en: avee-lcd-en {
- pinmux {
- pins = "gpio21";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio21";
- drive-strength = <2>;
- bias-disable;
- };
+ avee_lcd_en: avee-lcd-en-state {
+ pins = "gpio21";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
- mipi_1800_en: mipi-1800-en {
- pinmux {
- pins = "gpio86";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio86";
- drive-strength = <2>;
- bias-disable;
- };
+ mipi_1800_en: mipi-1800-en-state {
+ pins = "gpio86";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
- vdd_reset_1800: vdd-reset-1800 {
- pinmux {
- pins = "gpio87";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio87";
- drive-strength = <2>;
- bias-disable;
- };
+ vdd_reset_1800: vdd-reset-1800-state {
+ pins = "gpio87";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi
index eae22e6e97c1..f1defb94d670 100644
--- a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi
@@ -354,7 +354,7 @@
pwmleds {
compatible = "pwm-leds";
- keyboard_backlight: keyboard-backlight {
+ keyboard_backlight: led-0 {
status = "disabled";
label = "cros_ec::kbd_backlight";
function = LED_FUNCTION_KBD_BACKLIGHT;
@@ -768,6 +768,8 @@ hp_i2c: &i2c9 {
interrupts = <28 IRQ_TYPE_EDGE_BOTH>;
AVDD-supply = <&pp1800_alc5682>;
+ DBVDD-supply = <&pp1800_alc5682>;
+ LDO1-IN-supply = <&pp1800_alc5682>;
MICVDD-supply = <&pp3300_codec>;
VBAT-supply = <&pp3300_audio>;
@@ -880,27 +882,30 @@ hp_i2c: &i2c9 {
};
&spi0 {
- pinctrl-0 = <&qup_spi0_cs_gpio_init_high>, <&qup_spi0_cs_gpio>;
+ pinctrl-0 = <&qup_spi0_spi>, <&qup_spi0_cs_gpio>;
cs-gpios = <&tlmm 37 GPIO_ACTIVE_LOW>;
};
&spi6 {
- pinctrl-0 = <&qup_spi6_cs_gpio_init_high>, <&qup_spi6_cs_gpio>;
+ pinctrl-0 = <&qup_spi6_spi>, <&qup_spi6_cs_gpio>;
cs-gpios = <&tlmm 62 GPIO_ACTIVE_LOW>;
};
ap_spi_fp: &spi10 {
- pinctrl-0 = <&qup_spi10_cs_gpio_init_high>, <&qup_spi10_cs_gpio>;
+ pinctrl-0 = <&qup_spi10_spi>, <&qup_spi10_cs_gpio>;
cs-gpios = <&tlmm 89 GPIO_ACTIVE_LOW>;
cros_ec_fp: ec@0 {
- compatible = "google,cros-ec-spi";
+ compatible = "google,cros-ec-fp", "google,cros-ec-spi";
reg = <0>;
interrupt-parent = <&tlmm>;
interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
- pinctrl-0 = <&fp_to_ap_irq_l>;
+ pinctrl-0 = <&fp_to_ap_irq_l>, <&fp_rst_l>, <&fpmcu_boot0>;
+ boot0-gpios = <&tlmm 10 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&tlmm 22 GPIO_ACTIVE_LOW>;
spi-max-frequency = <3000000>;
+ vdd-supply = <&pp3300_fp_tp>;
};
};
@@ -997,175 +1002,141 @@ ap_spi_fp: &spi10 {
/* PINCTRL - additions to nodes defined in sc7180.dtsi */
&dp_hot_plug_det {
- pinconf {
- pins = "gpio117";
- bias-disable;
- };
+ bias-disable;
};
&pri_mi2s_active {
- pinconf {
- pins = "gpio53", "gpio54", "gpio55", "gpio56";
- drive-strength = <2>;
- bias-pull-down;
- };
+ drive-strength = <2>;
+ bias-pull-down;
};
&pri_mi2s_mclk_active {
- pinconf {
- pins = "gpio57";
- drive-strength = <2>;
- bias-pull-down;
- };
+ drive-strength = <2>;
+ bias-pull-down;
};
&qspi_cs0 {
- pinconf {
- pins = "gpio68";
- bias-disable;
- };
+ bias-disable;
};
&qspi_clk {
- pinconf {
- pins = "gpio63";
- drive-strength = <8>;
- bias-disable;
- };
+ drive-strength = <8>;
+ bias-disable;
};
&qspi_data01 {
- pinconf {
- pins = "gpio64", "gpio65";
-
- /* High-Z when no transfers; nice to park the lines */
- bias-pull-up;
- };
+ /* High-Z when no transfers; nice to park the lines */
+ bias-pull-up;
};
&qup_i2c2_default {
- pinconf {
- pins = "gpio15", "gpio16";
- drive-strength = <2>;
+ drive-strength = <2>;
- /* Has external pullup */
- bias-disable;
- };
+ /* Has external pullup */
+ bias-disable;
};
&qup_i2c4_default {
- pinconf {
- pins = "gpio115", "gpio116";
- drive-strength = <2>;
+ drive-strength = <2>;
- /* Has external pullup */
- bias-disable;
- };
+ /* Has external pullup */
+ bias-disable;
};
&qup_i2c5_default {
- pinconf {
- pins = "gpio25", "gpio26";
- drive-strength = <2>;
+ drive-strength = <2>;
- /* Has external pullup */
- bias-disable;
- };
+ /* Has external pullup */
+ bias-disable;
};
&qup_i2c7_default {
- pinconf {
- pins = "gpio6", "gpio7";
- drive-strength = <2>;
+ drive-strength = <2>;
- /* Has external pullup */
- bias-disable;
- };
+ /* Has external pullup */
+ bias-disable;
};
&qup_i2c9_default {
- pinconf {
- pins = "gpio46", "gpio47";
- drive-strength = <2>;
+ drive-strength = <2>;
- /* Has external pullup */
- bias-disable;
- };
+ /* Has external pullup */
+ bias-disable;
+};
+
+&qup_spi0_spi {
+ drive-strength = <2>;
+ bias-disable;
};
&qup_spi0_cs_gpio {
- pinconf {
- pins = "gpio34", "gpio35", "gpio36", "gpio37";
- drive-strength = <2>;
- bias-disable;
- };
+ drive-strength = <2>;
+ bias-disable;
+};
+
+&qup_spi6_spi {
+ drive-strength = <2>;
+ bias-disable;
};
&qup_spi6_cs_gpio {
- pinconf {
- pins = "gpio59", "gpio60", "gpio61", "gpio62";
- drive-strength = <2>;
- bias-disable;
- };
+ drive-strength = <2>;
+ bias-disable;
+};
+
+&qup_spi10_spi {
+ drive-strength = <2>;
+ bias-disable;
};
&qup_spi10_cs_gpio {
- pinconf {
- pins = "gpio86", "gpio87", "gpio88", "gpio89";
- drive-strength = <2>;
- bias-disable;
- };
+ drive-strength = <2>;
+ bias-disable;
};
-&qup_uart3_default {
- pinconf-cts {
- /*
- * Configure a pull-down on CTS to match the pull of
- * the Bluetooth module.
- */
- pins = "gpio38";
- bias-pull-down;
- };
+&qup_uart3_cts {
+ /*
+ * Configure a pull-down on CTS to match the pull of
+ * the Bluetooth module.
+ */
+ bias-pull-down;
+};
- pinconf-rts-tx {
- /* We'll drive RTS and TX, so no pull */
- pins = "gpio39", "gpio40";
- drive-strength = <2>;
- bias-disable;
- };
+&qup_uart3_rts {
+ /* We'll drive RTS, so no pull */
+ drive-strength = <2>;
+ bias-disable;
+};
- pinconf-rx {
- /*
- * Configure a pull-up on RX. This is needed to avoid
- * garbage data when the TX pin of the Bluetooth module is
- * in tri-state (module powered off or not driving the
- * signal yet).
- */
- pins = "gpio41";
- bias-pull-up;
- };
+&qup_uart3_tx {
+ /* We'll drive TX, so no pull */
+ drive-strength = <2>;
+ bias-disable;
};
-&qup_uart8_default {
- pinconf-tx {
- pins = "gpio44";
- drive-strength = <2>;
- bias-disable;
- };
+&qup_uart3_rx {
+ /*
+ * Configure a pull-up on RX. This is needed to avoid
+ * garbage data when the TX pin of the Bluetooth module is
+ * in tri-state (module powered off or not driving the
+ * signal yet).
+ */
+ bias-pull-up;
+};
- pinconf-rx {
- pins = "gpio45";
- drive-strength = <2>;
- bias-pull-up;
- };
+&qup_uart8_tx {
+ drive-strength = <2>;
+ bias-disable;
+};
+
+&qup_uart8_rx {
+ drive-strength = <2>;
+ bias-pull-up;
};
&sec_mi2s_active {
- pinconf {
- pins = "gpio49", "gpio50", "gpio51";
- drive-strength = <2>;
- bias-pull-down;
- };
+ drive-strength = <2>;
+ bias-pull-down;
};
/* PINCTRL - board-specific pinctrl */
@@ -1196,468 +1167,337 @@ ap_spi_fp: &spi10 {
pinctrl-names = "default";
pinctrl-0 = <&bios_flash_wp_l>, <&ap_suspend_l_neuter>;
- amp_en: amp-en {
- pinmux {
- pins = "gpio23";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio23";
- bias-pull-down;
- };
+ amp_en: amp-en-state {
+ pins = "gpio23";
+ function = "gpio";
+ bias-pull-down;
};
- ap_ec_int_l: ap-ec-int-l {
- pinmux {
- pins = "gpio94";
- function = "gpio";
- input-enable;
- };
-
- pinconf {
- pins = "gpio94";
- bias-pull-up;
- };
+ ap_ec_int_l: ap-ec-int-l-state {
+ pins = "gpio94";
+ function = "gpio";
+ input-enable;
+ bias-pull-up;
};
- ap_edp_bklten: ap-edp-bklten {
- pinmux {
- pins = "gpio12";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio12";
- drive-strength = <2>;
- bias-disable;
+ ap_edp_bklten: ap-edp-bklten-state {
+ pins = "gpio12";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
- /* Force backlight to be disabled to match state at boot. */
- output-low;
- };
+ /* Force backlight to be disabled to match state at boot. */
+ output-low;
};
- ap_suspend_l_neuter: ap-suspend-l-neuter {
- pinmux {
- pins = "gpio27";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio27";
- bias-disable;
- };
+ ap_suspend_l_neuter: ap-suspend-l-neuter-state {
+ pins = "gpio27";
+ function = "gpio";
+ bias-disable;
};
- bios_flash_wp_l: bios-flash-wp-l {
- pinmux {
- pins = "gpio66";
- function = "gpio";
- input-enable;
- };
-
- pinconf {
- pins = "gpio66";
- bias-disable;
- };
+ bios_flash_wp_l: bios-flash-wp-l-state {
+ pins = "gpio66";
+ function = "gpio";
+ input-enable;
+ bias-disable;
};
- edp_brij_en: edp-brij-en {
- pinmux {
- pins = "gpio104";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio104";
- drive-strength = <2>;
- bias-disable;
- };
+ edp_brij_en: edp-brij-en-state {
+ pins = "gpio104";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
- en_pp3300_codec: en-pp3300-codec {
- pinmux {
- pins = "gpio83";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio83";
- drive-strength = <2>;
- bias-disable;
- };
+ en_pp3300_codec: en-pp3300-codec-state {
+ pins = "gpio83";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
- en_pp3300_dx_edp: en-pp3300-dx-edp {
- pinmux {
- pins = "gpio30";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio30";
- drive-strength = <2>;
- bias-disable;
- };
+ en_pp3300_dx_edp: en-pp3300-dx-edp-state {
+ pins = "gpio30";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
- en_pp3300_hub: en-pp3300-hub {
- pinmux {
- pins = "gpio84";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio84";
- drive-strength = <2>;
- bias-disable;
- };
+ en_pp3300_hub: en-pp3300-hub-state {
+ pins = "gpio84";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
};
- fp_to_ap_irq_l: fp-to-ap-irq-l {
- pinmux {
- pins = "gpio4";
- function = "gpio";
- input-enable;
- };
-
- pinconf {
- pins = "gpio4";
-
- /* Has external pullup */
- bias-disable;
- };
+ fp_rst_l: fp-rst-l-state {
+ pins = "gpio22";
+ function = "gpio";
+ bias-disable;
+ drive-strength = <2>;
};
- h1_ap_int_odl: h1-ap-int-odl {
- pinmux {
- pins = "gpio42";
- function = "gpio";
- input-enable;
- };
+ fp_to_ap_irq_l: fp-to-ap-irq-l-state {
+ pins = "gpio4";
+ function = "gpio";
+ input-enable;
- pinconf {
- pins = "gpio42";
- bias-pull-up;
- };
+ /* Has external pullup */
+ bias-disable;
};
- hp_irq: hp-irq {
- pinmux {
- pins = "gpio28";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio28";
- bias-pull-up;
- };
+ fpmcu_boot0: fpmcu-boot0-state {
+ pins = "gpio10";
+ function = "gpio";
+ bias-disable;
};
- pen_irq_l: pen-irq-l {
- pinmux {
- pins = "gpio21";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio21";
-
- /* Has external pullup */
- bias-disable;
- };
+ h1_ap_int_odl: h1-ap-int-odl-state {
+ pins = "gpio42";
+ function = "gpio";
+ input-enable;
+ bias-pull-up;
};
- pen_pdct_l: pen-pdct-l {
- pinmux {
- pins = "gpio52";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio52";
-
- /* Has external pullup */
- bias-disable;
- };
+ hp_irq: hp-irq-state {
+ pins = "gpio28";
+ function = "gpio";
+ bias-pull-up;
};
- pen_rst_odl: pen-rst-odl {
- pinmux {
- pins = "gpio18";
- function = "gpio";
- };
+ pen_irq_l: pen-irq-l-state {
+ pins = "gpio21";
+ function = "gpio";
- pinconf {
- pins = "gpio18";
- bias-disable;
- drive-strength = <2>;
-
- /*
- * The pen driver doesn't currently support
- * driving this reset line. By specifying
- * output-high here we're relying on the fact
- * that this pin has a default pulldown at boot
- * (which makes sure the pen was in reset if it
- * was powered) and then we set it high here to
- * take it out of reset. Better would be if the
- * pen driver could control this and we could
- * remove "output-high" here.
- */
- output-high; /* TODO: Remove this? */
- };
+ /* Has external pullup */
+ bias-disable;
};
- p_sensor_int_l: p-sensor-int-l {
- pinmux {
- pins = "gpio24";
- function = "gpio";
- input-enable;
- };
+ pen_pdct_l: pen-pdct-l-state-state {
+ pins = "gpio52";
+ function = "gpio";
- pinconf {
- pins = "gpio24";
- /* Has external pullup */
- bias-disable;
- };
+ /* Has external pullup */
+ bias-disable;
};
- qup_spi0_cs_gpio_init_high: qup-spi0-cs-gpio-init-high {
- pinconf {
- pins = "gpio37";
- output-high;
- };
- };
+ pen_rst_odl: pen-rst-odl-state {
+ pins = "gpio18";
+ function = "gpio";
+ bias-disable;
+ drive-strength = <2>;
- qup_spi6_cs_gpio_init_high: qup-spi6-cs-gpio-init-high {
- pinconf {
- pins = "gpio62";
- output-high;
- };
+ /*
+ * The pen driver doesn't currently support
+ * driving this reset line. By specifying
+ * output-high here we're relying on the fact
+ * that this pin has a default pulldown at boot
+ * (which makes sure the pen was in reset if it
+ * was powered) and then we set it high here to
+ * take it out of reset. Better would be if the
+ * pen driver could control this and we could
+ * remove "output-high" here.
+ */
+ output-high; /* TODO: Remove this? */
};
- qup_spi10_cs_gpio_init_high: qup-spi10-cs-gpio-init-high {
- pinconf {
- pins = "gpio89";
- output-high;
- };
- };
+ p_sensor_int_l: p-sensor-int-l-state {
+ pins = "gpio24";
+ function = "gpio";
+ input-enable;
- qup_uart3_sleep: qup-uart3-sleep {
- pinmux {
- pins = "gpio38", "gpio39",
- "gpio40", "gpio41";
- function = "gpio";
- };
+ /* Has external pullup */
+ bias-disable;
+ };
- pinconf-cts {
+ qup_uart3_sleep: qup-uart3-sleep-state {
+ cts-pins {
/*
* Configure a pull-down on CTS to match the pull of
* the Bluetooth module.
*/
pins = "gpio38";
+ function = "gpio";
bias-pull-down;
};
- pinconf-rts {
+ rts-pins {
/*
* Configure pull-down on RTS. As RTS is active low
* signal, pull it low to indicate the BT SoC that it
* can wakeup the system anytime from suspend state by
* pulling RX low (by sending wakeup bytes).
*/
- pins = "gpio39";
- bias-pull-down;
+ pins = "gpio39";
+ function = "gpio";
+ bias-pull-down;
};
- pinconf-tx {
+ tx-pins {
/*
* Configure pull-up on TX when it isn't actively driven
* to prevent BT SoC from receiving garbage during sleep.
*/
pins = "gpio40";
+ function = "gpio";
bias-pull-up;
};
- pinconf-rx {
+ rx-pins {
/*
* Configure a pull-up on RX. This is needed to avoid
* garbage data when the TX pin of the Bluetooth module
* is floating which may cause spurious wakeups.
*/
pins = "gpio41";
+ function = "gpio";
bias-pull-up;
};
};
/* Named trackpad_int_1v8_odl on earlier revision schematics */
trackpad_int_1v8_odl:
- tp_int_odl: tp-int-odl {
- pinmux {
- pins = "gpio0";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio0";
+ tp_int_odl: tp-int-odl-state {
+ pins = "gpio0";
+ function = "gpio";
- /* Has external pullup */
- bias-disable;
- };
+ /* Has external pullup */
+ bias-disable;
};
- ts_int_l: ts-int-l {
- pinmux {
- pins = "gpio9";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio9";
- bias-pull-up;
- };
+ ts_int_l: ts-int-l-state {
+ pins = "gpio9";
+ function = "gpio";
+ bias-pull-up;
};
- ts_reset_l: ts-reset-l {
- pinmux {
- pins = "gpio8";
- function = "gpio";
- };
-
- pinconf {
- pins = "gpio8";
- bias-disable;
- drive-strength = <2>;
- };
+ ts_reset_l: ts-reset-l-state {
+ pins = "gpio8";
+ function = "gpio";
+ bias-disable;
+ drive-strength = <2>;
};
- sdc1_on: sdc1-on {
- pinconf-clk {
+ sdc1_on: sdc1-on-state {
+ clk-pins {
pins = "sdc1_clk";
bias-disable;
drive-strength = <16>;
};
- pinconf-cmd {
+ cmd-pins {
pins = "sdc1_cmd";
bias-pull-up;
drive-strength = <16>;
};
- pinconf-data {
+ data-pins {
pins = "sdc1_data";
bias-pull-up;
drive-strength = <16>;
};
- pinconf-rclk {
+ rclk-pins {
pins = "sdc1_rclk";
bias-pull-down;
};
};
- sdc1_off: sdc1-off {
- pinconf-clk {
+ sdc1_off: sdc1-off-state {
+ clk-pins {
pins = "sdc1_clk";
bias-disable;
drive-strength = <2>;
};
- pinconf-cmd {
+ cmd-pins {
pins = "sdc1_cmd";
bias-pull-up;
drive-strength = <2>;
};
- pinconf-data {
+ data-pins {
pins = "sdc1_data";
bias-pull-up;
drive-strength = <2>;
};
- pinconf-rclk {
+ rclk-pins {
pins = "sdc1_rclk";
bias-pull-down;
};
};
- sdc2_on: sdc2-on {
- pinconf-clk {
+ sdc2_on: sdc2-on-state {
+ clk-pins {
pins = "sdc2_clk";
bias-disable;
drive-strength = <16>;
};
- pinconf-cmd {
+ cmd-pins {
pins = "sdc2_cmd";
bias-pull-up;
drive-strength = <10>;
};
- pinconf-data {
+ data-pins {
pins = "sdc2_data";
bias-pull-up;
drive-strength = <10>;
};
- pinconf-sd-cd {
+ sd-cd-pins {
pins = "gpio69";
+ function = "gpio";
bias-pull-up;
drive-strength = <2>;
};
};
- sdc2_off: sdc2-off {
- pinconf-clk {
+ sdc2_off: sdc2-off-state {
+ clk-pins {
pins = "sdc2_clk";
bias-disable;
drive-strength = <2>;
};
- pinconf-cmd {
+ cmd-pins {
pins = "sdc2_cmd";
bias-pull-up;
drive-strength = <2>;
};
- pinconf-data {
+ data-pins {
pins = "sdc2_data";
bias-pull-up;
drive-strength = <2>;
};
- pinconf-sd-cd {
+ sd-cd-pins {
pins = "gpio69";
+ function = "gpio";
bias-pull-up;
drive-strength = <2>;
};
};
- uf_cam_en: uf-cam-en {
- pinmux {
- pins = "gpio6";
- function = "gpio";
- };
+ uf_cam_en: uf-cam-en-state {
+ pins = "gpio6";
+ function = "gpio";
+ drive-strength = <2>;
- pinconf {
- pins = "gpio6";
- drive-strength = <2>;
- /* External pull down */
- bias-disable;
- };
+ /* External pull down */
+ bias-disable;
};
- wf_cam_en: wf-cam-en {
- pinmux {
- pins = "gpio7";
- function = "gpio";
- };
+ wf_cam_en: wf-cam-en-state {
+ pins = "gpio7";
+ function = "gpio";
+ drive-strength = <2>;
- pinconf {
- pins = "gpio7";
- drive-strength = <2>;
- /* External pull down */
- bias-disable;
- };
+ /* External pull down */
+ bias-disable;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc7180.dtsi b/arch/arm64/boot/dts/qcom/sc7180.dtsi
index 58976a1ba06b..f71cf21a8dd8 100644
--- a/arch/arm64/boot/dts/qcom/sc7180.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7180.dtsi
@@ -662,6 +662,7 @@
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
+ power-domains = <&rpmhpd SC7180_CX>;
};
qfprom: efuse@784000 {
@@ -795,7 +796,7 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
pinctrl-names = "default";
- pinctrl-0 = <&qup_spi0_default>;
+ pinctrl-0 = <&qup_spi0_spi>, <&qup_spi0_cs>;
interrupts = <GIC_SPI 601 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
@@ -849,7 +850,7 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>;
pinctrl-names = "default";
- pinctrl-0 = <&qup_spi1_default>;
+ pinctrl-0 = <&qup_spi1_spi>, <&qup_spi1_cs>;
interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
@@ -939,7 +940,7 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>;
pinctrl-names = "default";
- pinctrl-0 = <&qup_spi3_default>;
+ pinctrl-0 = <&qup_spi3_spi>, <&qup_spi3_cs>;
interrupts = <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
@@ -1029,7 +1030,7 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>;
pinctrl-names = "default";
- pinctrl-0 = <&qup_spi5_default>;
+ pinctrl-0 = <&qup_spi5_spi>, <&qup_spi5_cs>;
interrupts = <GIC_SPI 606 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
@@ -1096,7 +1097,7 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP1_S0_CLK>;
pinctrl-names = "default";
- pinctrl-0 = <&qup_spi6_default>;
+ pinctrl-0 = <&qup_spi6_spi>, <&qup_spi6_cs>;
interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
@@ -1186,7 +1187,7 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP1_S2_CLK>;
pinctrl-names = "default";
- pinctrl-0 = <&qup_spi8_default>;
+ pinctrl-0 = <&qup_spi8_spi>, <&qup_spi8_cs>;
interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
@@ -1276,7 +1277,7 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>;
pinctrl-names = "default";
- pinctrl-0 = <&qup_spi10_default>;
+ pinctrl-0 = <&qup_spi10_spi>, <&qup_spi10_cs>;
interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
@@ -1330,7 +1331,7 @@
clock-names = "se";
clocks = <&gcc GCC_QUPV3_WRAP1_S5_CLK>;
pinctrl-names = "default";
- pinctrl-0 = <&qup_spi11_default>;
+ pinctrl-0 = <&qup_spi11_spi>, <&qup_spi11_cs>;
interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
@@ -1486,410 +1487,443 @@
gpio-ranges = <&tlmm 0 0 120>;
wakeup-parent = <&pdc>;
- dp_hot_plug_det: dp-hot-plug-det {
- pinmux {
- pins = "gpio117";
- function = "dp_hot";
- };
+ dp_hot_plug_det: dp-hot-plug-det-state {
+ pins = "gpio117";
+ function = "dp_hot";
};
- qspi_clk: qspi-clk {
- pinmux {
- pins = "gpio63";
- function = "qspi_clk";
- };
+ qspi_clk: qspi-clk-state {
+ pins = "gpio63";
+ function = "qspi_clk";
};
- qspi_cs0: qspi-cs0 {
- pinmux {
- pins = "gpio68";
- function = "qspi_cs";
- };
+ qspi_cs0: qspi-cs0-state {
+ pins = "gpio68";
+ function = "qspi_cs";
};
- qspi_cs1: qspi-cs1 {
- pinmux {
- pins = "gpio72";
- function = "qspi_cs";
- };
+ qspi_cs1: qspi-cs1-state {
+ pins = "gpio72";
+ function = "qspi_cs";
};
- qspi_data01: qspi-data01 {
- pinmux-data {
- pins = "gpio64", "gpio65";
- function = "qspi_data";
- };
+ qspi_data01: qspi-data01-state {
+ pins = "gpio64", "gpio65";
+ function = "qspi_data";
};
- qspi_data12: qspi-data12 {
- pinmux-data {
- pins = "gpio66", "gpio67";
- function = "qspi_data";
- };
+ qspi_data12: qspi-data12-state {
+ pins = "gpio66", "gpio67";
+ function = "qspi_data";
};
- qup_i2c0_default: qup-i2c0-default {
- pinmux {
- pins = "gpio34", "gpio35";
- function = "qup00";
- };
+ qup_i2c0_default: qup-i2c0-default-state {
+ pins = "gpio34", "gpio35";
+ function = "qup00";
};
- qup_i2c1_default: qup-i2c1-default {
- pinmux {
- pins = "gpio0", "gpio1";
- function = "qup01";
- };
+ qup_i2c1_default: qup-i2c1-default-state {
+ pins = "gpio0", "gpio1";
+ function = "qup01";
};
- qup_i2c2_default: qup-i2c2-default {
- pinmux {
- pins = "gpio15", "gpio16";
- function = "qup02_i2c";
- };
+ qup_i2c2_default: qup-i2c2-default-state {
+ pins = "gpio15", "gpio16";
+ function = "qup02_i2c";
};
- qup_i2c3_default: qup-i2c3-default {
- pinmux {
- pins = "gpio38", "gpio39";
- function = "qup03";
- };
+ qup_i2c3_default: qup-i2c3-default-state {
+ pins = "gpio38", "gpio39";
+ function = "qup03";
};
- qup_i2c4_default: qup-i2c4-default {
- pinmux {
- pins = "gpio115", "gpio116";
- function = "qup04_i2c";
- };
+ qup_i2c4_default: qup-i2c4-default-state {
+ pins = "gpio115", "gpio116";
+ function = "qup04_i2c";
};
- qup_i2c5_default: qup-i2c5-default {
- pinmux {
- pins = "gpio25", "gpio26";
- function = "qup05";
- };
+ qup_i2c5_default: qup-i2c5-default-state {
+ pins = "gpio25", "gpio26";
+ function = "qup05";
};
- qup_i2c6_default: qup-i2c6-default {
- pinmux {
- pins = "gpio59", "gpio60";
- function = "qup10";
- };
+ qup_i2c6_default: qup-i2c6-default-state {
+ pins = "gpio59", "gpio60";
+ function = "qup10";
};
- qup_i2c7_default: qup-i2c7-default {
- pinmux {
- pins = "gpio6", "gpio7";
- function = "qup11_i2c";
- };
+ qup_i2c7_default: qup-i2c7-default-state {
+ pins = "gpio6", "gpio7";
+ function = "qup11_i2c";
};
- qup_i2c8_default: qup-i2c8-default {
- pinmux {
- pins = "gpio42", "gpio43";
- function = "qup12";
- };
+ qup_i2c8_default: qup-i2c8-default-state {
+ pins = "gpio42", "gpio43";
+ function = "qup12";
};
- qup_i2c9_default: qup-i2c9-default {
- pinmux {
- pins = "gpio46", "gpio47";
- function = "qup13_i2c";
- };
+ qup_i2c9_default: qup-i2c9-default-state {
+ pins = "gpio46", "gpio47";
+ function = "qup13_i2c";
};
- qup_i2c10_default: qup-i2c10-default {
- pinmux {
- pins = "gpio86", "gpio87";
- function = "qup14";
- };
+ qup_i2c10_default: qup-i2c10-default-state {
+ pins = "gpio86", "gpio87";
+ function = "qup14";
};
- qup_i2c11_default: qup-i2c11-default {
- pinmux {
- pins = "gpio53", "gpio54";
- function = "qup15";
- };
+ qup_i2c11_default: qup-i2c11-default-state {
+ pins = "gpio53", "gpio54";
+ function = "qup15";
+ };
+
+ qup_spi0_spi: qup-spi0-spi-state {
+ pins = "gpio34", "gpio35", "gpio36";
+ function = "qup00";
+ };
+
+ qup_spi0_cs: qup-spi0-cs-state {
+ pins = "gpio37";
+ function = "qup00";
+ };
+
+ qup_spi0_cs_gpio: qup-spi0-cs-gpio-state {
+ pins = "gpio37";
+ function = "gpio";
+ };
+
+ qup_spi1_spi: qup-spi1-spi-state {
+ pins = "gpio0", "gpio1", "gpio2";
+ function = "qup01";
+ };
+
+ qup_spi1_cs: qup-spi1-cs-state {
+ pins = "gpio3";
+ function = "qup01";
+ };
+
+ qup_spi1_cs_gpio: qup-spi1-cs-gpio-state {
+ pins = "gpio3";
+ function = "gpio";
+ };
+
+ qup_spi3_spi: qup-spi3-spi-state {
+ pins = "gpio38", "gpio39", "gpio40";
+ function = "qup03";
+ };
+
+ qup_spi3_cs: qup-spi3-cs-state {
+ pins = "gpio41";
+ function = "qup03";
};
- qup_spi0_default: qup-spi0-default {
- pinmux {
- pins = "gpio34", "gpio35",
- "gpio36", "gpio37";
+ qup_spi3_cs_gpio: qup-spi3-cs-gpio-state {
+ pins = "gpio41";
+ function = "gpio";
+ };
+
+ qup_spi5_spi: qup-spi5-spi-state {
+ pins = "gpio25", "gpio26", "gpio27";
+ function = "qup05";
+ };
+
+ qup_spi5_cs: qup-spi5-cs-state {
+ pins = "gpio28";
+ function = "qup05";
+ };
+
+ qup_spi5_cs_gpio: qup-spi5-cs-gpio-state {
+ pins = "gpio28";
+ function = "gpio";
+ };
+
+ qup_spi6_spi: qup-spi6-spi-state {
+ pins = "gpio59", "gpio60", "gpio61";
+ function = "qup10";
+ };
+
+ qup_spi6_cs: qup-spi6-cs-state {
+ pins = "gpio62";
+ function = "qup10";
+ };
+
+ qup_spi6_cs_gpio: qup-spi6-cs-gpio-state {
+ pins = "gpio62";
+ function = "gpio";
+ };
+
+ qup_spi8_spi: qup-spi8-spi-state {
+ pins = "gpio42", "gpio43", "gpio44";
+ function = "qup12";
+ };
+
+ qup_spi8_cs: qup-spi8-cs-state {
+ pins = "gpio45";
+ function = "qup12";
+ };
+
+ qup_spi8_cs_gpio: qup-spi8-cs-gpio-state {
+ pins = "gpio45";
+ function = "gpio";
+ };
+
+ qup_spi10_spi: qup-spi10-spi-state {
+ pins = "gpio86", "gpio87", "gpio88";
+ function = "qup14";
+ };
+
+ qup_spi10_cs: qup-spi10-cs-state {
+ pins = "gpio89";
+ function = "qup14";
+ };
+
+ qup_spi10_cs_gpio: qup-spi10-cs-gpio-state {
+ pins = "gpio89";
+ function = "gpio";
+ };
+
+ qup_spi11_spi: qup-spi11-spi-state {
+ pins = "gpio53", "gpio54", "gpio55";
+ function = "qup15";
+ };
+
+ qup_spi11_cs: qup-spi11-cs-state {
+ pins = "gpio56";
+ function = "qup15";
+ };
+
+ qup_spi11_cs_gpio: qup-spi11-cs-gpio-state {
+ pins = "gpio56";
+ function = "gpio";
+ };
+
+ qup_uart0_default: qup-uart0-default-state {
+ qup_uart0_cts: cts-pins {
+ pins = "gpio34";
function = "qup00";
};
- };
- qup_spi0_cs_gpio: qup-spi0-cs-gpio {
- pinmux {
- pins = "gpio34", "gpio35",
- "gpio36";
+ qup_uart0_rts: rts-pins {
+ pins = "gpio35";
function = "qup00";
};
- pinmux-cs {
+ qup_uart0_tx: tx-pins {
+ pins = "gpio36";
+ function = "qup00";
+ };
+
+ qup_uart0_rx: rx-pins {
pins = "gpio37";
- function = "gpio";
+ function = "qup00";
};
};
- qup_spi1_default: qup-spi1-default {
- pinmux {
- pins = "gpio0", "gpio1",
- "gpio2", "gpio3";
+ qup_uart1_default: qup-uart1-default-state {
+ qup_uart1_cts: cts-pins {
+ pins = "gpio0";
function = "qup01";
};
- };
- qup_spi1_cs_gpio: qup-spi1-cs-gpio {
- pinmux {
- pins = "gpio0", "gpio1",
- "gpio2";
+ qup_uart1_rts: rts-pins {
+ pins = "gpio1";
function = "qup01";
};
- pinmux-cs {
- pins = "gpio3";
- function = "gpio";
+ qup_uart1_tx: tx-pins {
+ pins = "gpio2";
+ function = "qup01";
};
- };
- qup_spi3_default: qup-spi3-default {
- pinmux {
- pins = "gpio38", "gpio39",
- "gpio40", "gpio41";
- function = "qup03";
+ qup_uart1_rx: rx-pins {
+ pins = "gpio3";
+ function = "qup01";
};
};
- qup_spi3_cs_gpio: qup-spi3-cs-gpio {
- pinmux {
- pins = "gpio38", "gpio39",
- "gpio40";
- function = "qup03";
+ qup_uart2_default: qup-uart2-default-state {
+ qup_uart2_tx: tx-pins {
+ pins = "gpio15";
+ function = "qup02_uart";
};
- pinmux-cs {
- pins = "gpio41";
- function = "gpio";
+ qup_uart2_rx: rx-pins {
+ pins = "gpio16";
+ function = "qup02_uart";
};
};
- qup_spi5_default: qup-spi5-default {
- pinmux {
- pins = "gpio25", "gpio26",
- "gpio27", "gpio28";
- function = "qup05";
+ qup_uart3_default: qup-uart3-default-state {
+ qup_uart3_cts: cts-pins {
+ pins = "gpio38";
+ function = "qup03";
};
- };
- qup_spi5_cs_gpio: qup-spi5-cs-gpio {
- pinmux {
- pins = "gpio25", "gpio26",
- "gpio27";
- function = "qup05";
+ qup_uart3_rts: rts-pins {
+ pins = "gpio39";
+ function = "qup03";
};
- pinmux-cs {
- pins = "gpio28";
- function = "gpio";
+ qup_uart3_tx: tx-pins {
+ pins = "gpio40";
+ function = "qup03";
};
- };
- qup_spi6_default: qup-spi6-default {
- pinmux {
- pins = "gpio59", "gpio60",
- "gpio61", "gpio62";
- function = "qup10";
+ qup_uart3_rx: rx-pins {
+ pins = "gpio41";
+ function = "qup03";
};
};
- qup_spi6_cs_gpio: qup-spi6-cs-gpio {
- pinmux {
- pins = "gpio59", "gpio60",
- "gpio61";
- function = "qup10";
+ qup_uart4_default: qup-uart4-default-state {
+ qup_uart4_tx: tx-pins {
+ pins = "gpio115";
+ function = "qup04_uart";
};
- pinmux-cs {
- pins = "gpio62";
- function = "gpio";
+ qup_uart4_rx: rx-pins {
+ pins = "gpio116";
+ function = "qup04_uart";
};
};
- qup_spi8_default: qup-spi8-default {
- pinmux {
- pins = "gpio42", "gpio43",
- "gpio44", "gpio45";
- function = "qup12";
+ qup_uart5_default: qup-uart5-default-state {
+ qup_uart5_cts: cts-pins {
+ pins = "gpio25";
+ function = "qup05";
};
- };
- qup_spi8_cs_gpio: qup-spi8-cs-gpio {
- pinmux {
- pins = "gpio42", "gpio43",
- "gpio44";
- function = "qup12";
+ qup_uart5_rts: rts-pins {
+ pins = "gpio26";
+ function = "qup05";
};
- pinmux-cs {
- pins = "gpio45";
- function = "gpio";
+ qup_uart5_tx: tx-pins {
+ pins = "gpio27";
+ function = "qup05";
};
- };
- qup_spi10_default: qup-spi10-default {
- pinmux {
- pins = "gpio86", "gpio87",
- "gpio88", "gpio89";
- function = "qup14";
+ qup_uart5_rx: rx-pins {
+ pins = "gpio28";
+ function = "qup05";
};
};
- qup_spi10_cs_gpio: qup-spi10-cs-gpio {
- pinmux {
- pins = "gpio86", "gpio87",
- "gpio88";
- function = "qup14";
+ qup_uart6_default: qup-uart6-default-state {
+ qup_uart6_cts: cts-pins {
+ pins = "gpio59";
+ function = "qup10";
};
- pinmux-cs {
- pins = "gpio89";
- function = "gpio";
+ qup_uart6_rts: rts-pins {
+ pins = "gpio60";
+ function = "qup10";
};
- };
- qup_spi11_default: qup-spi11-default {
- pinmux {
- pins = "gpio53", "gpio54",
- "gpio55", "gpio56";
- function = "qup15";
+ qup_uart6_tx: tx-pins {
+ pins = "gpio61";
+ function = "qup10";
+ };
+
+ qup_uart6_rx: rx-pins {
+ pins = "gpio62";
+ function = "qup10";
};
};
- qup_spi11_cs_gpio: qup-spi11-cs-gpio {
- pinmux {
- pins = "gpio53", "gpio54",
- "gpio55";
- function = "qup15";
+ qup_uart7_default: qup-uart7-default-state {
+ qup_uart7_tx: tx-pins {
+ pins = "gpio6";
+ function = "qup11_uart";
};
- pinmux-cs {
- pins = "gpio56";
- function = "gpio";
+ qup_uart7_rx: rx-pins {
+ pins = "gpio7";
+ function = "qup11_uart";
};
};
- qup_uart0_default: qup-uart0-default {
- pinmux {
- pins = "gpio34", "gpio35",
- "gpio36", "gpio37";
- function = "qup00";
+ qup_uart8_default: qup-uart8-default-state {
+ qup_uart8_tx: tx-pins {
+ pins = "gpio44";
+ function = "qup12";
};
- };
- qup_uart1_default: qup-uart1-default {
- pinmux {
- pins = "gpio0", "gpio1",
- "gpio2", "gpio3";
- function = "qup01";
+ qup_uart8_rx: rx-pins {
+ pins = "gpio45";
+ function = "qup12";
};
};
- qup_uart2_default: qup-uart2-default {
- pinmux {
- pins = "gpio15", "gpio16";
- function = "qup02_uart";
+ qup_uart9_default: qup-uart9-default-state {
+ qup_uart9_tx: tx-pins {
+ pins = "gpio46";
+ function = "qup13_uart";
};
- };
- qup_uart3_default: qup-uart3-default {
- pinmux {
- pins = "gpio38", "gpio39",
- "gpio40", "gpio41";
- function = "qup03";
+ qup_uart9_rx: rx-pins {
+ pins = "gpio47";
+ function = "qup13_uart";
};
};
- qup_uart4_default: qup-uart4-default {
- pinmux {
- pins = "gpio115", "gpio116";
- function = "qup04_uart";
+ qup_uart10_default: qup-uart10-default-state {
+ qup_uart10_cts: cts-pins {
+ pins = "gpio86";
+ function = "qup14";
};
- };
- qup_uart5_default: qup-uart5-default {
- pinmux {
- pins = "gpio25", "gpio26",
- "gpio27", "gpio28";
- function = "qup05";
+ qup_uart10_rts: rts-pins {
+ pins = "gpio87";
+ function = "qup14";
};
- };
- qup_uart6_default: qup-uart6-default {
- pinmux {
- pins = "gpio59", "gpio60",
- "gpio61", "gpio62";
- function = "qup10";
+ qup_uart10_tx: tx-pins {
+ pins = "gpio88";
+ function = "qup14";
};
- };
- qup_uart7_default: qup-uart7-default {
- pinmux {
- pins = "gpio6", "gpio7";
- function = "qup11_uart";
+ qup_uart10_rx: rx-pins {
+ pins = "gpio89";
+ function = "qup14";
};
};
- qup_uart8_default: qup-uart8-default {
- pinmux {
- pins = "gpio44", "gpio45";
- function = "qup12";
+ qup_uart11_default: qup-uart11-default-state {
+ qup_uart11_cts: cts-pins {
+ pins = "gpio53";
+ function = "qup15";
};
- };
- qup_uart9_default: qup-uart9-default {
- pinmux {
- pins = "gpio46", "gpio47";
- function = "qup13_uart";
+ qup_uart11_rts: rts-pins {
+ pins = "gpio54";
+ function = "qup15";
};
- };
- qup_uart10_default: qup-uart10-default {
- pinmux {
- pins = "gpio86", "gpio87",
- "gpio88", "gpio89";
- function = "qup14";
+ qup_uart11_tx: tx-pins {
+ pins = "gpio55";
+ function = "qup15";
};
- };
- qup_uart11_default: qup-uart11-default {
- pinmux {
- pins = "gpio53", "gpio54",
- "gpio55", "gpio56";
+ qup_uart11_rx: rx-pins {
+ pins = "gpio56";
function = "qup15";
};
};
- sec_mi2s_active: sec-mi2s-active {
- pinmux {
- pins = "gpio49", "gpio50", "gpio51";
- function = "mi2s_1";
- };
+ sec_mi2s_active: sec-mi2s-active-state {
+ pins = "gpio49", "gpio50", "gpio51";
+ function = "mi2s_1";
};
- pri_mi2s_active: pri-mi2s-active {
- pinmux {
- pins = "gpio53", "gpio54", "gpio55", "gpio56";
- function = "mi2s_0";
- };
+ pri_mi2s_active: pri-mi2s-active-state {
+ pins = "gpio53", "gpio54", "gpio55", "gpio56";
+ function = "mi2s_0";
};
- pri_mi2s_mclk_active: pri-mi2s-mclk-active {
- pinmux {
- pins = "gpio57";
- function = "lpass_ext";
- };
+ pri_mi2s_mclk_active: pri-mi2s-mclk-active-state {
+ pins = "gpio57";
+ function = "lpass_ext";
};
};
@@ -2775,6 +2809,7 @@
"dm_hs_phy_irq", "dp_hs_phy_irq";
power-domains = <&gcc USB30_PRIM_GDSC>;
+ required-opps = <&rpmhpd_opp_nom>;
resets = <&gcc GCC_USB30_PRIM_BCR>;
@@ -2782,6 +2817,8 @@
<&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_USB3 0>;
interconnect-names = "usb-ddr", "apps-usb";
+ wakeup-source;
+
usb_1_dwc3: usb@a600000 {
compatible = "snps,dwc3";
reg = <0 0x0a600000 0 0xe000>;
@@ -3012,7 +3049,6 @@
power-domains = <&rpmhpd SC7180_CX>;
phys = <&dsi_phy>;
- phy-names = "dsi";
#address-cells = <1>;
#size-cells = <0>;
@@ -3057,7 +3093,7 @@
};
};
- dsi_phy: dsi-phy@ae94400 {
+ dsi_phy: phy@ae94400 {
compatible = "qcom,dsi-phy-10nm";
reg = <0 0x0ae94400 0 0x200>,
<0 0x0ae94600 0 0x280>,
@@ -3522,7 +3558,7 @@
};
osm_l3: interconnect@18321000 {
- compatible = "qcom,sc7180-osm-l3";
+ compatible = "qcom,sc7180-osm-l3", "qcom,osm-l3";
reg = <0 0x18321000 0 0x1400>;
clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>;
diff --git a/arch/arm64/boot/dts/qcom/sc7280-chrome-common.dtsi b/arch/arm64/boot/dts/qcom/sc7280-chrome-common.dtsi
index 25f31c81b2b7..16fb20369c01 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-chrome-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280-chrome-common.dtsi
@@ -39,20 +39,10 @@
no-map;
};
- mpss_mem: memory@8b800000 {
- reg = <0x0 0x8b800000 0x0 0xf600000>;
- no-map;
- };
-
wpss_mem: memory@9ae00000 {
reg = <0x0 0x9ae00000 0x0 0x1900000>;
no-map;
};
-
- mba_mem: memory@9c700000 {
- reg = <0x0 0x9c700000 0x0 0x200000>;
- no-map;
- };
};
};
@@ -88,11 +78,6 @@
firmware-name = "ath11k/WCN6750/hw1.0/wpss.mdt";
};
-/* Increase the size from 2.5MB to 8MB */
-&rmtfs_mem {
- reg = <0x0 0x9c900000 0x0 0x800000>;
-};
-
&wifi {
status = "okay";
diff --git a/arch/arm64/boot/dts/qcom/sc7280-crd-r3.dts b/arch/arm64/boot/dts/qcom/sc7280-crd-r3.dts
index dddb505e220b..1185141f348e 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-crd-r3.dts
+++ b/arch/arm64/boot/dts/qcom/sc7280-crd-r3.dts
@@ -118,25 +118,25 @@ ap_ts_pen_1v8: &i2c13 {
};
&tlmm {
- tp_int_odl: tp-int-odl {
+ tp_int_odl: tp-int-odl-state {
pins = "gpio7";
function = "gpio";
bias-disable;
};
- ts_int_l: ts-int-l {
+ ts_int_l: ts-int-l-state {
pins = "gpio55";
function = "gpio";
bias-pull-up;
};
- ts_reset_l: ts-reset-l {
+ ts_reset_l: ts-reset-l-state {
pins = "gpio54";
function = "gpio";
bias-disable;
};
- us_euro_hs_sel: us-euro-hs-sel {
+ us_euro_hs_sel: us-euro-hs-sel-state {
pins = "gpio81";
function = "gpio";
bias-pull-down;
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-audio-rt5682-3mic.dtsi b/arch/arm64/boot/dts/qcom/sc7280-herobrine-audio-rt5682-3mic.dtsi
new file mode 100644
index 000000000000..1ca11a14104d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-audio-rt5682-3mic.dtsi
@@ -0,0 +1,187 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ *
+ * This file defines the common audio settings for the child boards
+ * using rt5682 codec and having 3 dmics connected to sc7280.
+ *
+ * Copyright 2022 Google LLC.
+ */
+
+/ {
+ /* BOARD-SPECIFIC TOP LEVEL NODES */
+ sound: sound {
+ compatible = "google,sc7280-herobrine";
+ model = "sc7280-rt5682-max98360a-3mic";
+
+ audio-routing = "VA DMIC0", "vdd-micb",
+ "VA DMIC1", "vdd-micb",
+ "VA DMIC2", "vdd-micb",
+ "VA DMIC3", "vdd-micb",
+
+ "Headphone Jack", "HPOL",
+ "Headphone Jack", "HPOR";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dai-link@0 {
+ link-name = "MAX98360";
+ reg = <0>;
+
+ cpu {
+ sound-dai = <&lpass_cpu MI2S_SECONDARY>;
+ };
+
+ codec {
+ sound-dai = <&max98360a>;
+ };
+ };
+
+ dai-link@1 {
+ link-name = "DisplayPort";
+ reg = <1>;
+
+ cpu {
+ sound-dai = <&lpass_cpu LPASS_DP_RX>;
+ };
+
+ codec {
+ sound-dai = <&mdss_dp>;
+ };
+ };
+
+ dai-link@2 {
+ link-name = "ALC5682";
+ reg = <2>;
+
+ cpu {
+ sound-dai = <&lpass_cpu MI2S_PRIMARY>;
+ };
+
+ codec {
+ sound-dai = <&alc5682 0 /* aif1 */>;
+ };
+ };
+
+ dai-link@4 {
+ link-name = "DMIC";
+ reg = <4>;
+
+ cpu {
+ sound-dai = <&lpass_cpu LPASS_CDC_DMA_VA_TX0>;
+ };
+
+ codec {
+ sound-dai = <&lpass_va_macro 0>;
+ };
+ };
+ };
+};
+
+hp_i2c: &i2c2 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ alc5682: codec@1a {
+ compatible = "realtek,rt5682s";
+ reg = <0x1a>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hp_irq>;
+
+ #sound-dai-cells = <1>;
+
+ interrupt-parent = <&tlmm>;
+ interrupts = <101 IRQ_TYPE_EDGE_BOTH>;
+
+ AVDD-supply = <&pp1800_alc5682>;
+ MICVDD-supply = <&pp3300_codec>;
+
+ realtek,dmic1-data-pin = <1>;
+ realtek,dmic1-clk-pin = <2>;
+ realtek,jd-src = <1>;
+ realtek,dmic-clk-rate-hz = <2048000>;
+ };
+};
+
+&lpass_cpu {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mi2s0_data0>, <&mi2s0_data1>, <&mi2s0_mclk>, <&mi2s0_sclk>, <&mi2s0_ws>,
+ <&mi2s1_data0>, <&mi2s1_sclk>, <&mi2s1_ws>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "okay";
+
+ dai-link@0 {
+ reg = <MI2S_PRIMARY>;
+ qcom,playback-sd-lines = <1>;
+ qcom,capture-sd-lines = <0>;
+ };
+
+ dai-link@1 {
+ reg = <MI2S_SECONDARY>;
+ qcom,playback-sd-lines = <0>;
+ };
+
+ dai-link@5 {
+ reg = <LPASS_DP_RX>;
+ };
+
+ dai-link@25 {
+ reg = <LPASS_CDC_DMA_VA_TX0>;
+ };
+};
+
+&lpass_va_macro {
+ vdd-micb-supply = <&pp1800_l2c>;
+ pinctrl-0 = <&lpass_dmic01_clk>, <&lpass_dmic01_data>, <&lpass_dmic23_clk>,
+ <&lpass_dmic23_data>;
+
+ status = "okay";
+};
+
+/* PINCTRL - ADDITIONS TO NODES IN PARENT DEVICE TREE FILES */
+
+&lpass_dmic01_clk {
+ drive-strength = <8>;
+ bias-disable;
+};
+
+&lpass_dmic01_data {
+ bias-pull-down;
+};
+
+&lpass_dmic23_clk {
+ drive-strength = <8>;
+ bias-disable;
+};
+
+&lpass_dmic23_data {
+ bias-pull-down;
+};
+
+&mi2s0_data0 {
+ drive-strength = <6>;
+ bias-disable;
+};
+
+&mi2s0_data1 {
+ drive-strength = <6>;
+ bias-disable;
+};
+
+&mi2s0_mclk {
+ drive-strength = <6>;
+ bias-disable;
+};
+
+&mi2s0_sclk {
+ drive-strength = <6>;
+ bias-disable;
+};
+
+&mi2s0_ws {
+ drive-strength = <6>;
+ bias-disable;
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-audio-rt5682.dtsi b/arch/arm64/boot/dts/qcom/sc7280-herobrine-audio-rt5682.dtsi
new file mode 100644
index 000000000000..af685bc35e10
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-audio-rt5682.dtsi
@@ -0,0 +1,122 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ *
+ * This file defines the common audio settings for the child boards
+ * using rt5682 codec.
+ *
+ * Copyright 2022 Google LLC.
+ */
+
+/ {
+ /* BOARD-SPECIFIC TOP LEVEL NODES */
+ sound: sound {
+ compatible = "google,sc7280-herobrine";
+ model = "sc7280-rt5682-max98360a-1mic";
+
+ audio-routing = "Headphone Jack", "HPOL",
+ "Headphone Jack", "HPOR";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dai-link@0 {
+ link-name = "MAX98360";
+ reg = <0>;
+
+ cpu {
+ sound-dai = <&lpass_cpu MI2S_SECONDARY>;
+ };
+
+ codec {
+ sound-dai = <&max98360a>;
+ };
+ };
+
+ dai-link@1 {
+ link-name = "ALC5682";
+ reg = <1>;
+
+ cpu {
+ sound-dai = <&lpass_cpu MI2S_PRIMARY>;
+ };
+
+ codec {
+ sound-dai = <&alc5682 0 /* aif1 */>;
+ };
+ };
+ };
+};
+
+hp_i2c: &i2c2 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ alc5682: codec@1a {
+ compatible = "realtek,rt5682s";
+ reg = <0x1a>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&hp_irq>;
+
+ #sound-dai-cells = <1>;
+
+ interrupt-parent = <&tlmm>;
+ interrupts = <101 IRQ_TYPE_EDGE_BOTH>;
+
+ AVDD-supply = <&pp1800_alc5682>;
+ MICVDD-supply = <&pp3300_codec>;
+
+ realtek,dmic1-data-pin = <1>;
+ realtek,dmic1-clk-pin = <2>;
+ realtek,jd-src = <1>;
+ realtek,dmic-clk-rate-hz = <2048000>;
+ };
+};
+
+&lpass_cpu {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mi2s0_data0>, <&mi2s0_data1>, <&mi2s0_mclk>, <&mi2s0_sclk>, <&mi2s0_ws>,
+ <&mi2s1_data0>, <&mi2s1_sclk>, <&mi2s1_ws>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "okay";
+
+ dai-link@0 {
+ reg = <MI2S_PRIMARY>;
+ qcom,playback-sd-lines = <1>;
+ qcom,capture-sd-lines = <0>;
+ };
+
+ dai-link@1 {
+ reg = <MI2S_SECONDARY>;
+ qcom,playback-sd-lines = <0>;
+ };
+};
+
+/* PINCTRL - ADDITIONS TO NODES IN PARENT DEVICE TREE FILES */
+
+&mi2s0_data0 {
+ drive-strength = <6>;
+ bias-disable;
+};
+
+&mi2s0_data1 {
+ drive-strength = <6>;
+ bias-disable;
+};
+
+&mi2s0_mclk {
+ drive-strength = <6>;
+ bias-disable;
+};
+
+&mi2s0_sclk {
+ drive-strength = <6>;
+ bias-disable;
+};
+
+&mi2s0_ws {
+ drive-strength = <6>;
+ bias-disable;
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-audio-wcd9385.dtsi b/arch/arm64/boot/dts/qcom/sc7280-herobrine-audio-wcd9385.dtsi
index c72e53aaf997..ae2552094cda 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-herobrine-audio-wcd9385.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-audio-wcd9385.dtsi
@@ -167,10 +167,6 @@
bias-disable;
};
-&lpass_dmic01_clk_sleep {
- drive-strength = <2>;
-};
-
&lpass_dmic01_data {
bias-pull-down;
};
@@ -180,10 +176,6 @@
bias-disable;
};
-&lpass_dmic23_clk_sleep {
- drive-strength = <2>;
-};
-
&lpass_dmic23_data {
bias-pull-down;
};
@@ -194,30 +186,18 @@
bias-disable;
};
-&lpass_rx_swr_clk_sleep {
- bias-pull-down;
-};
-
&lpass_rx_swr_data {
drive-strength = <2>;
slew-rate = <1>;
bias-bus-hold;
};
-&lpass_rx_swr_data_sleep {
- bias-pull-down;
-};
-
&lpass_tx_swr_clk {
drive-strength = <2>;
slew-rate = <1>;
bias-disable;
};
-&lpass_tx_swr_clk_sleep {
- bias-pull-down;
-};
-
&lpass_tx_swr_data {
drive-strength = <2>;
slew-rate = <1>;
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-crd.dts b/arch/arm64/boot/dts/qcom/sc7280-herobrine-crd.dts
index f0f26af1e421..4e0b013e25f4 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-herobrine-crd.dts
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-crd.dts
@@ -372,5 +372,6 @@ ap_ts_pen_1v8: &i2c13 {
"", /* 170 */
"MOS_BLE_UART_TX",
"MOS_BLE_UART_RX",
+ "",
"";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-evoker-lte.dts b/arch/arm64/boot/dts/qcom/sc7280-herobrine-evoker-lte.dts
new file mode 100644
index 000000000000..14f20e705869
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-evoker-lte.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Evoker board device tree source
+ *
+ * Copyright 2022 Google LLC.
+ */
+
+/dts-v1/;
+
+#include "sc7280-herobrine-evoker.dtsi"
+#include "sc7280-herobrine-lte-sku.dtsi"
+
+/ {
+ model = "Google Evoker with LTE";
+ compatible = "google,evoker-sku512", "qcom,sc7280";
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-evoker.dts b/arch/arm64/boot/dts/qcom/sc7280-herobrine-evoker.dts
new file mode 100644
index 000000000000..4f781fe25c9c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-evoker.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Evoker board device tree source
+ *
+ * Copyright 2022 Google LLC.
+ */
+
+/dts-v1/;
+
+#include "sc7280-herobrine-evoker.dtsi"
+#include "sc7280-herobrine-wifi-sku.dtsi"
+
+/ {
+ model = "Google Evoker";
+ compatible = "google,evoker", "qcom,sc7280";
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-evoker-r0.dts b/arch/arm64/boot/dts/qcom/sc7280-herobrine-evoker.dtsi
index ccbe50b6249a..3d639c70a06e 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-herobrine-evoker-r0.dts
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-evoker.dtsi
@@ -5,14 +5,8 @@
* Copyright 2022 Google LLC.
*/
-/dts-v1/;
-
#include "sc7280-herobrine.dtsi"
-
-/ {
- model = "Google Evoker";
- compatible = "google,evoker", "qcom,sc7280";
-};
+#include "sc7280-herobrine-audio-rt5682-3mic.dtsi"
/*
* ADDITIONS TO FIXED REGULATORS DEFINED IN PARENT DEVICE TREE FILES
@@ -30,16 +24,15 @@ ap_tp_i2c: &i2c0 {
status = "okay";
clock-frequency = <400000>;
- trackpad: trackpad@2c {
- compatible = "hid-over-i2c";
- reg = <0x2c>;
+ trackpad: trackpad@15 {
+ compatible = "elan,ekth3000";
+ reg = <0x15>;
pinctrl-names = "default";
pinctrl-0 = <&tp_int_odl>;
interrupt-parent = <&tlmm>;
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
- hid-descr-addr = <0x20>;
vcc-supply = <&pp3300_z1>;
wakeup-source;
@@ -50,9 +43,9 @@ ts_i2c: &i2c13 {
status = "okay";
clock-frequency = <400000>;
- ap_ts: touchscreen@10 {
- compatible = "elan,ekth6915";
- reg = <0x10>;
+ ap_ts: touchscreen@5d {
+ compatible = "goodix,gt7986u", "goodix,gt7375p";
+ reg = <0x5d>;
pinctrl-names = "default";
pinctrl-0 = <&ts_int_conn>, <&ts_rst_conn>;
@@ -61,7 +54,7 @@ ts_i2c: &i2c13 {
reset-gpios = <&tlmm 54 GPIO_ACTIVE_LOW>;
- vcc33-supply = <&ts_avdd>;
+ vdd-supply = <&ts_avdd>;
};
};
@@ -328,6 +321,5 @@ ts_i2c: &i2c13 {
"MOS_BLE_UART_TX",
"MOS_BLE_UART_RX",
"",
- "",
"";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-herobrine-r1.dts b/arch/arm64/boot/dts/qcom/sc7280-herobrine-herobrine-r1.dts
index c1a671968725..b04888a98203 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-herobrine-herobrine-r1.dts
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-herobrine-r1.dts
@@ -8,6 +8,7 @@
/dts-v1/;
#include "sc7280-herobrine.dtsi"
+#include "sc7280-herobrine-audio-rt5682.dtsi"
#include "sc7280-herobrine-lte-sku.dtsi"
/ {
@@ -47,10 +48,6 @@
/* ADDITIONS TO NODES DEFINED IN PARENT DEVICE TREE FILES */
-&ap_spi_fp {
- status = "okay";
-};
-
/*
* Although the trackpad is really part of the herobrine baseboard, we'll
* put the actual definition in the board device tree since different boards
@@ -358,6 +355,5 @@ ts_i2c: &i2c13 {
"MOS_BLE_UART_TX",
"MOS_BLE_UART_RX",
"",
- "",
"";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi b/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi
index a92eeccd2b2a..ad66e5e9db4e 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-lte-sku.dtsi
@@ -6,6 +6,20 @@
*/
/* Modem setup is different on Chrome setups than typical Qualcomm setup */
+/ {
+ reserved-memory {
+ mpss_mem: memory@8b800000 {
+ reg = <0x0 0x8b800000 0x0 0xf600000>;
+ no-map;
+ };
+
+ mba_mem: memory@9c700000 {
+ reg = <0x0 0x9c700000 0x0 0x200000>;
+ no-map;
+ };
+ };
+};
+
&remoteproc_mpss {
compatible = "qcom,sc7280-mss-pil";
iommus = <&apps_smmu 0x124 0x0>, <&apps_smmu 0x488 0x7>;
@@ -15,3 +29,8 @@
"qcom/sc7280-herobrine/modem/qdsp6sw.mbn";
status = "okay";
};
+
+/* Increase the size from 2.5MB to 8MB */
+&rmtfs_mem {
+ reg = <0x0 0x9c900000 0x0 0x800000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-villager-r1-lte.dts b/arch/arm64/boot/dts/qcom/sc7280-herobrine-villager-r1-lte.dts
index f1017809e5da..d71cc4bbc4b3 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-herobrine-villager-r1-lte.dts
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-villager-r1-lte.dts
@@ -5,7 +5,9 @@
* Copyright 2022 Google LLC.
*/
-#include "sc7280-herobrine-villager-r1.dts"
+/dts-v1/;
+
+#include "sc7280-herobrine-villager-r1.dtsi"
#include "sc7280-herobrine-lte-sku.dtsi"
/ {
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-villager-r1.dts b/arch/arm64/boot/dts/qcom/sc7280-herobrine-villager-r1.dts
index cfc648726930..edb52f12f0ea 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-herobrine-villager-r1.dts
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-villager-r1.dts
@@ -7,37 +7,10 @@
/dts-v1/;
-#include "sc7280-herobrine-villager.dtsi"
-#include "sc7280-herobrine-audio-wcd9385.dtsi"
+#include "sc7280-herobrine-villager-r1.dtsi"
+#include "sc7280-herobrine-wifi-sku.dtsi"
/ {
model = "Google Villager (rev1+)";
compatible = "google,villager", "qcom,sc7280";
};
-
-&lpass_va_macro {
- vdd-micb-supply = <&pp1800_l2c>;
-};
-
-&sound {
- audio-routing =
- "IN1_HPHL", "HPHL_OUT",
- "IN2_HPHR", "HPHR_OUT",
- "AMIC1", "MIC BIAS1",
- "AMIC2", "MIC BIAS2",
- "VA DMIC0", "vdd-micb",
- "VA DMIC1", "vdd-micb",
- "VA DMIC2", "vdd-micb",
- "VA DMIC3", "vdd-micb",
- "TX SWR_ADC0", "ADC1_OUTPUT",
- "TX SWR_ADC1", "ADC2_OUTPUT",
- "TX SWR_ADC2", "ADC3_OUTPUT",
- "TX SWR_DMIC0", "DMIC1_OUTPUT",
- "TX SWR_DMIC1", "DMIC2_OUTPUT",
- "TX SWR_DMIC2", "DMIC3_OUTPUT",
- "TX SWR_DMIC3", "DMIC4_OUTPUT",
- "TX SWR_DMIC4", "DMIC5_OUTPUT",
- "TX SWR_DMIC5", "DMIC6_OUTPUT",
- "TX SWR_DMIC6", "DMIC7_OUTPUT",
- "TX SWR_DMIC7", "DMIC8_OUTPUT";
-};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-villager-r1.dtsi b/arch/arm64/boot/dts/qcom/sc7280-herobrine-villager-r1.dtsi
new file mode 100644
index 000000000000..b25df5a99161
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-villager-r1.dtsi
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Villager board device tree source
+ *
+ * Copyright 2022 Google LLC.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#include "sc7280-herobrine-villager.dtsi"
+#include "sc7280-herobrine-audio-wcd9385.dtsi"
+
+&lpass_va_macro {
+ vdd-micb-supply = <&pp1800_l2c>;
+};
+
+&sound {
+ audio-routing =
+ "IN1_HPHL", "HPHL_OUT",
+ "IN2_HPHR", "HPHR_OUT",
+ "AMIC1", "MIC BIAS1",
+ "AMIC2", "MIC BIAS2",
+ "VA DMIC0", "vdd-micb",
+ "VA DMIC1", "vdd-micb",
+ "VA DMIC2", "vdd-micb",
+ "VA DMIC3", "vdd-micb",
+ "TX SWR_ADC0", "ADC1_OUTPUT",
+ "TX SWR_ADC1", "ADC2_OUTPUT",
+ "TX SWR_ADC2", "ADC3_OUTPUT",
+ "TX SWR_DMIC0", "DMIC1_OUTPUT",
+ "TX SWR_DMIC1", "DMIC2_OUTPUT",
+ "TX SWR_DMIC2", "DMIC3_OUTPUT",
+ "TX SWR_DMIC3", "DMIC4_OUTPUT",
+ "TX SWR_DMIC4", "DMIC5_OUTPUT",
+ "TX SWR_DMIC5", "DMIC6_OUTPUT",
+ "TX SWR_DMIC6", "DMIC7_OUTPUT",
+ "TX SWR_DMIC7", "DMIC8_OUTPUT";
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-villager.dtsi b/arch/arm64/boot/dts/qcom/sc7280-herobrine-villager.dtsi
index 4566722bf4dd..17553e0fd6fd 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-herobrine-villager.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-villager.dtsi
@@ -78,16 +78,6 @@ ts_i2c: &i2c13 {
status = "okay";
};
-/* For nvme */
-&pcie1 {
- status = "okay";
-};
-
-/* For nvme */
-&pcie1_phy {
- status = "okay";
-};
-
&pwmleds {
status = "okay";
};
@@ -321,6 +311,5 @@ ts_i2c: &i2c13 {
"MOS_BLE_UART_TX",
"MOS_BLE_UART_RX",
"",
- "",
"";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi b/arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi
new file mode 100644
index 000000000000..2febd6126d4c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-wifi-sku.dtsi
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Google Herobrine dts fragment for WIFI SKUs
+ *
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+/* WIFI SKUs save 256M by not having modem/mba/rmtfs memory regions defined. */
+
+/delete-node/ &remoteproc_mpss;
+/delete-node/ &rmtfs_mem;
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-zombie-lte.dts b/arch/arm64/boot/dts/qcom/sc7280-herobrine-zombie-lte.dts
new file mode 100644
index 000000000000..c9fe64529555
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-zombie-lte.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Zombie board device tree source
+ *
+ * Copyright 2022 Google LLC.
+ */
+
+/dts-v1/;
+
+#include "sc7280-herobrine-zombie.dtsi"
+#include "sc7280-herobrine-lte-sku.dtsi"
+
+/ {
+ model = "Google Zombie with LTE";
+ compatible = "google,zombie-sku512", "qcom,sc7280";
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-zombie.dts b/arch/arm64/boot/dts/qcom/sc7280-herobrine-zombie.dts
new file mode 100644
index 000000000000..0246c12b2f40
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-zombie.dts
@@ -0,0 +1,16 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Zombie board device tree source
+ *
+ * Copyright 2022 Google LLC.
+ */
+
+/dts-v1/;
+
+#include "sc7280-herobrine-zombie.dtsi"
+#include "sc7280-herobrine-wifi-sku.dtsi"
+
+/ {
+ model = "Google Zombie";
+ compatible = "google,zombie", "qcom,sc7280";
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine-zombie.dtsi b/arch/arm64/boot/dts/qcom/sc7280-herobrine-zombie.dtsi
new file mode 100644
index 000000000000..7fc0b6bfc0d6
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine-zombie.dtsi
@@ -0,0 +1,312 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Google Zombie board device tree source
+ *
+ * Copyright 2022 Google LLC.
+ */
+
+#include "sc7280-herobrine.dtsi"
+#include "sc7280-herobrine-audio-rt5682.dtsi"
+
+/*
+ * ADDITIONS TO FIXED REGULATORS DEFINED IN PARENT DEVICE TREE FILES
+ *
+ * Sort order matches the order in the parent files (parents before children).
+ */
+
+&pp3300_codec {
+ status = "okay";
+};
+
+/* ADDITIONS TO NODES DEFINED IN PARENT DEVICE TREE FILES */
+
+ap_tp_i2c: &i2c0 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ trackpad: trackpad@15 {
+ compatible = "hid-over-i2c";
+ reg = <0x15>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&tp_int_odl>;
+
+ interrupt-parent = <&tlmm>;
+ interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+
+ hid-descr-addr = <0x01>;
+ vdd-supply = <&pp3300_z1>;
+
+ wakeup-source;
+ };
+};
+
+&ap_sar_sensor_i2c {
+ status = "okay";
+};
+
+&ap_sar_sensor0 {
+ status = "okay";
+};
+
+&ap_sar_sensor1 {
+ status = "okay";
+};
+
+&mdss_edp {
+ status = "okay";
+};
+
+&mdss_edp_phy {
+ status = "okay";
+};
+
+/* For nvme */
+&pcie1 {
+ status = "okay";
+};
+
+/* For nvme */
+&pcie1_phy {
+ status = "okay";
+};
+
+&pm8350c_pwm_backlight{
+ /* Set the PWM period to 200 microseconds (5kHz duty cycle) */
+ pwms = <&pm8350c_pwm 3 200000>;
+};
+
+&pwmleds {
+ status = "okay";
+};
+
+/* For eMMC */
+&sdhc_1 {
+ status = "okay";
+};
+
+/* PINCTRL - ADDITIONS TO NODES IN PARENT DEVICE TREE FILES */
+
+&ts_rst_conn {
+ bias-disable;
+};
+
+/* PINCTRL - BOARD-SPECIFIC */
+
+/*
+ * Methodology for gpio-line-names:
+ * - If a pin goes to herobrine board and is named it gets that name.
+ * - If a pin goes to herobrine board and is not named, it gets no name.
+ * - If a pin is totally internal to Qcard then it gets Qcard name.
+ * - If a pin is not hooked up on Qcard, it gets no name.
+ */
+
+&pm8350c_gpios {
+ gpio-line-names = "FLASH_STROBE_1", /* 1 */
+ "AP_SUSPEND",
+ "PM8008_1_RST_N",
+ "",
+ "",
+ "",
+ "PMIC_EDP_BL_EN",
+ "PMIC_EDP_BL_PWM",
+ "";
+};
+
+&tlmm {
+ gpio-line-names = "AP_TP_I2C_SDA", /* 0 */
+ "AP_TP_I2C_SCL",
+ "SSD_RST_L",
+ "PE_WAKE_ODL",
+ "AP_SAR_SDA",
+ "AP_SAR_SCL",
+ "PRB_SC_GPIO_6",
+ "TP_INT_ODL",
+ "HP_I2C_SDA",
+ "HP_I2C_SCL",
+
+ "GNSS_L1_EN", /* 10 */
+ "GNSS_L5_EN",
+ "SPI_AP_MOSI",
+ "SPI_AP_MISO",
+ "SPI_AP_CLK",
+ "SPI_AP_CS0_L",
+ /*
+ * AP_FLASH_WP is crossystem ABI. Schematics
+ * call it BIOS_FLASH_WP_OD.
+ */
+ "AP_FLASH_WP",
+ "",
+ "AP_EC_INT_L",
+ "",
+
+ "UF_CAM_RST_L", /* 20 */
+ "WF_CAM_RST_L",
+ "UART_AP_TX_DBG_RX",
+ "UART_DBG_TX_AP_RX",
+ "",
+ "PM8008_IRQ_1",
+ "HOST2WLAN_SOL",
+ "WLAN2HOST_SOL",
+ "MOS_BT_UART_CTS",
+ "MOS_BT_UART_RFR",
+
+ "MOS_BT_UART_TX", /* 30 */
+ "MOS_BT_UART_RX",
+ "PRB_SC_GPIO_32",
+ "HUB_RST_L",
+ "",
+ "",
+ "AP_SPI_FP_MISO",
+ "AP_SPI_FP_MOSI",
+ "AP_SPI_FP_CLK",
+ "AP_SPI_FP_CS_L",
+
+ "AP_EC_SPI_MISO", /* 40 */
+ "AP_EC_SPI_MOSI",
+ "AP_EC_SPI_CLK",
+ "AP_EC_SPI_CS_L",
+ "LCM_RST_L",
+ "EARLY_EUD_N",
+ "",
+ "DP_HOT_PLUG_DET",
+ "IO_BRD_MLB_ID0",
+ "IO_BRD_MLB_ID1",
+
+ "IO_BRD_MLB_ID2", /* 50 */
+ "SSD_EN",
+ "TS_I2C_SDA_CONN",
+ "TS_I2C_CLK_CONN",
+ "TS_RST_CONN",
+ "TS_INT_CONN",
+ "AP_I2C_TPM_SDA",
+ "AP_I2C_TPM_SCL",
+ "PRB_SC_GPIO_58",
+ "PRB_SC_GPIO_59",
+
+ "EDP_HOT_PLUG_DET_N", /* 60 */
+ "FP_TO_AP_IRQ_L",
+ "",
+ "AMP_EN",
+ "CAM0_MCLK_GPIO_64",
+ "CAM1_MCLK_GPIO_65",
+ "WF_CAM_MCLK",
+ "PRB_SC_GPIO_67",
+ "FPMCU_BOOT0",
+ "UF_CAM_SDA",
+
+ "UF_CAM_SCL", /* 70 */
+ "",
+ "",
+ "WF_CAM_SDA",
+ "WF_CAM_SCL",
+ "",
+ "",
+ "EN_FP_RAILS",
+ "FP_RST_L",
+ "PCIE1_CLKREQ_ODL",
+
+ "EN_PP3300_DX_EDP", /* 80 */
+ "US_EURO_HS_SEL",
+ "FORCED_USB_BOOT",
+ "WCD_RESET_N",
+ "MOS_WLAN_EN",
+ "MOS_BT_EN",
+ "MOS_SW_CTRL",
+ "MOS_PCIE0_RST",
+ "MOS_PCIE0_CLKREQ_N",
+ "MOS_PCIE0_WAKE_N",
+
+ "MOS_LAA_AS_EN", /* 90 */
+ "SD_CD_ODL",
+ "",
+ "",
+ "MOS_BT_WLAN_SLIMBUS_CLK",
+ "MOS_BT_WLAN_SLIMBUS_DAT0",
+ "HP_MCLK",
+ "HP_BCLK",
+ "HP_DOUT",
+ "HP_DIN",
+
+ "HP_LRCLK", /* 100 */
+ "HP_IRQ",
+ "",
+ "",
+ "GSC_AP_INT_ODL",
+ "EN_PP3300_CODEC",
+ "AMP_BCLK",
+ "AMP_DIN",
+ "AMP_LRCLK",
+ "UIM1_DATA_GPIO_109",
+
+ "UIM1_CLK_GPIO_110", /* 110 */
+ "UIM1_RESET_GPIO_111",
+ "PRB_SC_GPIO_112",
+ "UIM0_DATA",
+ "UIM0_CLK",
+ "UIM0_RST",
+ "UIM0_PRESENT_ODL",
+ "SDM_RFFE0_CLK",
+ "SDM_RFFE0_DATA",
+ "WF_CAM_EN",
+
+ "FASTBOOT_SEL_0", /* 120 */
+ "SC_GPIO_121",
+ "FASTBOOT_SEL_1",
+ "SC_GPIO_123",
+ "FASTBOOT_SEL_2",
+ "SM_RFFE4_CLK_GRFC_8",
+ "SM_RFFE4_DATA_GRFC_9",
+ "WLAN_COEX_UART1_RX",
+ "WLAN_COEX_UART1_TX",
+ "PRB_SC_GPIO_129",
+
+ "LCM_ID0", /* 130 */
+ "LCM_ID1",
+ "",
+ "SDR_QLINK_REQ",
+ "SDR_QLINK_EN",
+ "QLINK0_WMSS_RESET_N",
+ "SMR526_QLINK1_REQ",
+ "SMR526_QLINK1_EN",
+ "SMR526_QLINK1_WMSS_RESET_N",
+ "PRB_SC_GPIO_139",
+
+ "SAR1_IRQ_ODL", /* 140 */
+ "SAR0_IRQ_ODL",
+ "PRB_SC_GPIO_142",
+ "",
+ "WCD_SWR_TX_CLK",
+ "WCD_SWR_TX_DATA0",
+ "WCD_SWR_TX_DATA1",
+ "WCD_SWR_RX_CLK",
+ "WCD_SWR_RX_DATA0",
+ "WCD_SWR_RX_DATA1",
+
+ "DMIC01_CLK", /* 150 */
+ "DMIC01_DATA",
+ "DMIC23_CLK",
+ "DMIC23_DATA",
+ "",
+ "",
+ "EC_IN_RW_ODL",
+ "HUB_EN",
+ "WCD_SWR_TX_DATA2",
+ "",
+
+ "", /* 160 */
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+
+ "", /* 170 */
+ "MOS_BLE_UART_TX",
+ "MOS_BLE_UART_RX",
+ "",
+ "";
+};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-herobrine.dtsi b/arch/arm64/boot/dts/qcom/sc7280-herobrine.dtsi
index c11e37160f34..27f479ff9d80 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-herobrine.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280-herobrine.dtsi
@@ -307,7 +307,7 @@
pwmleds: pwmleds {
compatible = "pwm-leds";
status = "disabled";
- keyboard_backlight: keyboard-backlight {
+ keyboard_backlight: led-0 {
label = "cros_ec::kbd_backlight";
function = LED_FUNCTION_KBD_BACKLIGHT;
pwms = <&cros_ec_pwm 0>;
@@ -503,13 +503,16 @@ ap_spi_fp: &spi9 {
cs-gpios = <&tlmm 39 GPIO_ACTIVE_LOW>;
cros_ec_fp: ec@0 {
- compatible = "google,cros-ec-spi";
+ compatible = "google,cros-ec-fp", "google,cros-ec-spi";
reg = <0>;
interrupt-parent = <&tlmm>;
interrupts = <61 IRQ_TYPE_LEVEL_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&fp_to_ap_irq_l>, <&fp_rst_l>, <&fpmcu_boot0>;
+ boot0-gpios = <&tlmm 68 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&tlmm 78 GPIO_ACTIVE_LOW>;
spi-max-frequency = <3000000>;
+ vdd-supply = <&pp3300_fp_mcu>;
};
};
@@ -627,6 +630,13 @@ ap_ec_spi: &spi10 {
&usb_1_hsphy {
status = "okay";
+
+ qcom,hs-rise-fall-time-bp = <0>;
+ qcom,squelch-detector-bp = <(-2090)>;
+ qcom,hs-disconnect-bp = <1743>;
+ qcom,hs-amplitude-bp = <1780>;
+ qcom,hs-crossover-voltage-microvolt = <(-31000)>;
+ qcom,hs-output-impedance-micro-ohms = <2600000>;
};
&usb_1_qmpphy {
@@ -639,6 +649,21 @@ ap_ec_spi: &spi10 {
bias-disable;
};
+&mi2s1_data0 {
+ drive-strength = <6>;
+ bias-disable;
+};
+
+&mi2s1_sclk {
+ drive-strength = <6>;
+ bias-disable;
+};
+
+&mi2s1_ws {
+ drive-strength = <6>;
+ bias-disable;
+};
+
&pcie1_clkreq_n {
bias-pull-up;
drive-strength = <2>;
@@ -744,27 +769,27 @@ ap_ec_spi: &spi10 {
pinctrl-names = "default";
pinctrl-0 = <&bios_flash_wp_od>;
- amp_en: amp-en-pins {
+ amp_en: amp-en-state {
pins = "gpio63";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
- ap_ec_int_l: ap-ec-int-l-pins {
+ ap_ec_int_l: ap-ec-int-l-state {
pins = "gpio18";
function = "gpio";
bias-pull-up;
};
- bios_flash_wp_od: bios-flash-wp-od-pins {
+ bios_flash_wp_od: bios-flash-wp-od-state {
pins = "gpio16";
function = "gpio";
/* Has external pull */
bias-disable;
};
- en_fp_rails: en-fp-rails-pins {
+ en_fp_rails: en-fp-rails-state {
pins = "gpio77";
function = "gpio";
bias-disable;
@@ -772,60 +797,60 @@ ap_ec_spi: &spi10 {
output-high;
};
- en_pp3300_codec: en-pp3300-codec-pins {
+ en_pp3300_codec: en-pp3300-codec-state {
pins = "gpio105";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
- en_pp3300_dx_edp: en-pp3300-dx-edp-pins {
+ en_pp3300_dx_edp: en-pp3300-dx-edp-state {
pins = "gpio80";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
- fp_rst_l: fp-rst-l-pins {
+ fp_rst_l: fp-rst-l-state {
pins = "gpio78";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
- fp_to_ap_irq_l: fp-to-ap-irq-l-pins {
+ fp_to_ap_irq_l: fp-to-ap-irq-l-state {
pins = "gpio61";
function = "gpio";
/* Has external pullup */
bias-disable;
};
- fpmcu_boot0: fpmcu-boot0-pins {
+ fpmcu_boot0: fpmcu-boot0-state {
pins = "gpio68";
function = "gpio";
bias-disable;
};
- gsc_ap_int_odl: gsc-ap-int-odl-pins {
+ gsc_ap_int_odl: gsc-ap-int-odl-state {
pins = "gpio104";
function = "gpio";
bias-pull-up;
};
- hp_irq: hp-irq-pins {
+ hp_irq: hp-irq-state {
pins = "gpio101";
function = "gpio";
bias-pull-up;
};
- hub_en: hub-en-pins {
+ hub_en: hub-en-state {
pins = "gpio157";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
- pe_wake_odl: pe-wake-odl-pins {
+ pe_wake_odl: pe-wake-odl-state {
pins = "gpio3";
function = "gpio";
/* Has external pull */
@@ -834,45 +859,45 @@ ap_ec_spi: &spi10 {
};
/* For ap_spi_fp */
- qup_spi9_cs_gpio_init_high: qup-spi9-cs-gpio-init-high-pins {
+ qup_spi9_cs_gpio_init_high: qup-spi9-cs-gpio-init-high-state {
pins = "gpio39";
function = "gpio";
output-high;
};
/* For ap_ec_spi */
- qup_spi10_cs_gpio_init_high: qup-spi10-cs-gpio-init-high-pins {
+ qup_spi10_cs_gpio_init_high: qup-spi10-cs-gpio-init-high-state {
pins = "gpio43";
function = "gpio";
output-high;
};
- sar0_irq_odl: sar0-irq-odl-pins {
+ sar0_irq_odl: sar0-irq-odl-state {
pins = "gpio141";
function = "gpio";
bias-pull-up;
};
- sar1_irq_odl: sar1-irq-odl-pins {
+ sar1_irq_odl: sar1-irq-odl-state {
pins = "gpio140";
function = "gpio";
bias-pull-up;
};
- sd_cd_odl: sd-cd-odl-pins {
+ sd_cd_odl: sd-cd-odl-state {
pins = "gpio91";
function = "gpio";
bias-pull-up;
};
- ssd_en: ssd-en-pins {
+ ssd_en: ssd-en-state {
pins = "gpio51";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
- ssd_rst_l: ssd-rst-l-pins {
+ ssd_rst_l: ssd-rst-l-state {
pins = "gpio2";
function = "gpio";
bias-disable;
@@ -880,14 +905,14 @@ ap_ec_spi: &spi10 {
output-low;
};
- tp_int_odl: tp-int-odl-pins {
+ tp_int_odl: tp-int-odl-state {
pins = "gpio7";
function = "gpio";
/* Has external pullup */
bias-disable;
};
- wf_cam_en: wf-cam-en-pins {
+ wf_cam_en: wf-cam-en-state {
pins = "gpio119";
function = "gpio";
/* Has external pulldown */
diff --git a/arch/arm64/boot/dts/qcom/sc7280-idp-ec-h1.dtsi b/arch/arm64/boot/dts/qcom/sc7280-idp-ec-h1.dtsi
index 7f5143e9bb80..3cfeb118d379 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-idp-ec-h1.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280-idp-ec-h1.dtsi
@@ -79,27 +79,29 @@ ap_h1_spi: &spi14 {
};
&tlmm {
- ap_ec_int_l: ap-ec-int-l-pins {
+ ap_ec_int_l: ap-ec-int-l-state {
pins = "gpio18";
function = "gpio";
input-enable;
bias-pull-up;
};
- h1_ap_int_odl: h1-ap-int-odl-pins {
+ h1_ap_int_odl: h1-ap-int-odl-state {
pins = "gpio104";
function = "gpio";
input-enable;
bias-pull-up;
};
- qup_spi10_cs_gpio_init_high: qup-spi10-cs-gpio-init-high-pins {
+ qup_spi10_cs_gpio_init_high: qup-spi10-cs-gpio-init-high-state {
pins = "gpio43";
+ function = "gpio";
output-high;
};
- qup_spi14_cs_gpio_init_high: qup-spi14-cs-gpio-init-high-pins {
+ qup_spi14_cs_gpio_init_high: qup-spi14-cs-gpio-init-high-state {
pins = "gpio59";
+ function = "gpio";
output-high;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-idp.dts b/arch/arm64/boot/dts/qcom/sc7280-idp.dts
index 7559164cdda0..ba64316b4427 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-idp.dts
+++ b/arch/arm64/boot/dts/qcom/sc7280-idp.dts
@@ -10,7 +10,6 @@
#include <dt-bindings/iio/qcom,spmi-adc7-pmr735a.h>
#include "sc7280-idp.dtsi"
#include "pmr735a.dtsi"
-#include "sc7280-herobrine-lte-sku.dtsi"
/ {
model = "Qualcomm Technologies, Inc. sc7280 IDP SKU1 platform";
@@ -61,11 +60,6 @@
vddio-supply = <&vreg_l19b_1p8>;
};
-&ipa {
- status = "okay";
- modem-init;
-};
-
&pmk8350_rtc {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi b/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi
index cd432a2856a7..f7efb9966afd 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280-idp.dtsi
@@ -13,6 +13,7 @@
#include "pmk8350.dtsi"
#include "sc7280-chrome-common.dtsi"
+#include "sc7280-herobrine-lte-sku.dtsi"
/ {
aliases {
@@ -34,7 +35,7 @@
pinctrl-0 = <&wcd_reset_n>;
pinctrl-1 = <&wcd_reset_n_sleep>;
- reset-gpios = <&tlmm 83 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&tlmm 83 GPIO_ACTIVE_LOW>;
qcom,rx-device = <&wcd_rx>;
qcom,tx-device = <&wcd_tx>;
@@ -522,6 +523,12 @@
vdda-pll-supply = <&vreg_l10c_0p8>;
vdda33-supply = <&vreg_l2b_3p0>;
vdda18-supply = <&vreg_l1c_1p8>;
+ qcom,hs-rise-fall-time-bp = <0>;
+ qcom,squelch-detector-bp = <(-2090)>;
+ qcom,hs-disconnect-bp = <1743>;
+ qcom,hs-amplitude-bp = <1780>;
+ qcom,hs-crossover-voltage-microvolt = <(-31000)>;
+ qcom,hs-output-impedance-micro-ohms = <2600000>;
};
&usb_1_qmpphy {
@@ -569,10 +576,6 @@
bias-disable;
};
-&lpass_dmic01_clk_sleep {
- drive-strength = <2>;
-};
-
&lpass_dmic01_data {
bias-pull-down;
};
@@ -582,10 +585,6 @@
bias-disable;
};
-&lpass_dmic23_clk_sleep {
- drive-strength = <2>;
-};
-
&lpass_dmic23_data {
bias-pull-down;
};
@@ -596,30 +595,18 @@
bias-disable;
};
-&lpass_rx_swr_clk_sleep {
- bias-pull-down;
-};
-
&lpass_rx_swr_data {
drive-strength = <2>;
slew-rate = <1>;
bias-bus-hold;
};
-&lpass_rx_swr_data_sleep {
- bias-pull-down;
-};
-
&lpass_tx_swr_clk {
drive-strength = <2>;
slew-rate = <1>;
bias-disable;
};
-&lpass_tx_swr_clk_sleep {
- bias-pull-down;
-};
-
&lpass_tx_swr_data {
drive-strength = <2>;
slew-rate = <1>;
@@ -747,24 +734,24 @@
};
&tlmm {
- amp_en: amp-en {
+ amp_en: amp-en-state {
pins = "gpio63";
bias-pull-down;
drive-strength = <2>;
};
- bt_en: bt-en-pins {
+ bt_en: bt-en-state {
pins = "gpio85";
function = "gpio";
output-low;
bias-disable;
};
- nvme_pwren: nvme-pwren-pins {
+ nvme_pwren: nvme-pwren-state {
function = "gpio";
};
- pcie1_reset_n: pcie1-reset-n-pins {
+ pcie1_reset_n: pcie1-reset-n-state {
pins = "gpio2";
function = "gpio";
@@ -773,7 +760,7 @@
bias-disable;
};
- pcie1_wake_n: pcie1-wake-n-pins {
+ pcie1_wake_n: pcie1-wake-n-state {
pins = "gpio3";
function = "gpio";
@@ -781,7 +768,7 @@
bias-pull-up;
};
- qup_uart7_sleep_cts: qup-uart7-sleep-cts-pins {
+ qup_uart7_sleep_cts: qup-uart7-sleep-cts-state {
pins = "gpio28";
function = "gpio";
/*
@@ -794,7 +781,7 @@
bias-bus-hold;
};
- qup_uart7_sleep_rts: qup-uart7-sleep-rts-pins {
+ qup_uart7_sleep_rts: qup-uart7-sleep-rts-state {
pins = "gpio29";
function = "gpio";
/*
@@ -806,7 +793,7 @@
bias-pull-down;
};
- qup_uart7_sleep_tx: qup-uart7-sleep-tx-pins {
+ qup_uart7_sleep_tx: qup-uart7-sleep-tx-state {
pins = "gpio30";
function = "gpio";
/*
@@ -816,7 +803,7 @@
bias-pull-up;
};
- qup_uart7_sleep_rx: qup-uart7-sleep-rx-pins {
+ qup_uart7_sleep_rx: qup-uart7-sleep-rx-state {
pins = "gpio31";
function = "gpio";
/*
@@ -827,25 +814,25 @@
bias-pull-up;
};
- sd_cd: sd-cd-pins {
+ sd_cd: sd-cd-state {
pins = "gpio91";
function = "gpio";
bias-pull-up;
};
- sw_ctrl: sw-ctrl-pins {
+ sw_ctrl: sw-ctrl-state {
pins = "gpio86";
function = "gpio";
bias-pull-down;
};
- wcd_reset_n: wcd-reset-n {
+ wcd_reset_n: wcd-reset-n-state {
pins = "gpio83";
function = "gpio";
drive-strength = <8>;
};
- wcd_reset_n_sleep: wcd-reset-n-sleep {
+ wcd_reset_n_sleep: wcd-reset-n-sleep-state {
pins = "gpio83";
function = "gpio";
drive-strength = <8>;
diff --git a/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi b/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi
index 4b8c676b0bb1..df49564ae6dc 100644
--- a/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280-qcard.dtsi
@@ -37,7 +37,7 @@
pinctrl-0 = <&wcd_reset_n>, <&us_euro_hs_sel>;
pinctrl-1 = <&wcd_reset_n_sleep>, <&us_euro_hs_sel>;
- reset-gpios = <&tlmm 83 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&tlmm 83 GPIO_ACTIVE_LOW>;
us-euro-gpios = <&tlmm 81 GPIO_ACTIVE_HIGH>;
qcom,rx-device = <&wcd_rx>;
@@ -595,7 +595,7 @@ mos_bt_uart: &uart7 {
};
&tlmm {
- mos_bt_en: mos-bt-en-pins {
+ mos_bt_en: mos-bt-en-state {
pins = "gpio85";
function = "gpio";
drive-strength = <2>;
@@ -603,7 +603,7 @@ mos_bt_uart: &uart7 {
};
/* For mos_bt_uart */
- qup_uart7_sleep_cts: qup-uart7-sleep-cts-pins {
+ qup_uart7_sleep_cts: qup-uart7-sleep-cts-state {
pins = "gpio28";
function = "gpio";
/*
@@ -617,7 +617,7 @@ mos_bt_uart: &uart7 {
};
/* For mos_bt_uart */
- qup_uart7_sleep_rts: qup-uart7-sleep-rts-pins {
+ qup_uart7_sleep_rts: qup-uart7-sleep-rts-state {
pins = "gpio29";
function = "gpio";
/*
@@ -630,7 +630,7 @@ mos_bt_uart: &uart7 {
};
/* For mos_bt_uart */
- qup_uart7_sleep_rx: qup-uart7-sleep-rx-pins {
+ qup_uart7_sleep_rx: qup-uart7-sleep-rx-state {
pins = "gpio31";
function = "gpio";
/*
@@ -642,7 +642,7 @@ mos_bt_uart: &uart7 {
};
/* For mos_bt_uart */
- qup_uart7_sleep_tx: qup-uart7-sleep-tx-pins {
+ qup_uart7_sleep_tx: qup-uart7-sleep-tx-state {
pins = "gpio30";
function = "gpio";
/*
@@ -652,32 +652,32 @@ mos_bt_uart: &uart7 {
bias-pull-up;
};
- ts_int_conn: ts-int-conn-pins {
+ ts_int_conn: ts-int-conn-state {
pins = "gpio55";
function = "gpio";
bias-pull-up;
};
- ts_rst_conn: ts-rst-conn-pins {
+ ts_rst_conn: ts-rst-conn-state {
pins = "gpio54";
function = "gpio";
drive-strength = <2>;
};
- us_euro_hs_sel: us-euro-hs-sel {
+ us_euro_hs_sel: us-euro-hs-sel-state {
pins = "gpio81";
function = "gpio";
bias-pull-down;
drive-strength = <2>;
};
- wcd_reset_n: wcd-reset-n {
+ wcd_reset_n: wcd-reset-n-state {
pins = "gpio83";
function = "gpio";
drive-strength = <8>;
};
- wcd_reset_n_sleep: wcd-reset-n-sleep {
+ wcd_reset_n_sleep: wcd-reset-n-sleep-state {
pins = "gpio83";
function = "gpio";
drive-strength = <8>;
diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi b/arch/arm64/boot/dts/qcom/sc7280.dtsi
index 4cdc88d33944..0adf13399e64 100644
--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
@@ -752,6 +752,17 @@
interrupt-controller;
#interrupt-cells = <2>;
};
+
+ wlan_smp2p_out: wlan-ap-to-wpss {
+ qcom,entry-name = "wlan";
+ #qcom,smem-state-cells = <1>;
+ };
+
+ wlan_smp2p_in: wlan-wpss-to-ap {
+ qcom,entry-name = "wlan";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
};
pmu {
@@ -920,7 +931,7 @@
gpi_dma0: dma-controller@900000 {
#dma-cells = <3>;
- compatible = "qcom,sc7280-gpi-dma";
+ compatible = "qcom,sc7280-gpi-dma", "qcom,sm6350-gpi-dma";
reg = <0 0x00900000 0 0x60000>;
interrupts = <GIC_SPI 244 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>,
@@ -967,6 +978,8 @@
<&aggre1_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI1 0>;
interconnect-names = "qup-core", "qup-config",
"qup-memory";
+ power-domains = <&rpmhpd SC7280_CX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
dmas = <&gpi_dma0 0 0 QCOM_GPI_I2C>,
<&gpi_dma0 1 0 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
@@ -1025,6 +1038,8 @@
<&aggre1_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI1 0>;
interconnect-names = "qup-core", "qup-config",
"qup-memory";
+ power-domains = <&rpmhpd SC7280_CX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
dmas = <&gpi_dma0 0 1 QCOM_GPI_I2C>,
<&gpi_dma0 1 1 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
@@ -1083,6 +1098,8 @@
<&aggre1_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI1 0>;
interconnect-names = "qup-core", "qup-config",
"qup-memory";
+ power-domains = <&rpmhpd SC7280_CX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
dmas = <&gpi_dma0 0 2 QCOM_GPI_I2C>,
<&gpi_dma0 1 2 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
@@ -1141,6 +1158,8 @@
<&aggre1_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI1 0>;
interconnect-names = "qup-core", "qup-config",
"qup-memory";
+ power-domains = <&rpmhpd SC7280_CX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
dmas = <&gpi_dma0 0 3 QCOM_GPI_I2C>,
<&gpi_dma0 1 3 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
@@ -1199,6 +1218,8 @@
<&aggre1_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI1 0>;
interconnect-names = "qup-core", "qup-config",
"qup-memory";
+ power-domains = <&rpmhpd SC7280_CX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
dmas = <&gpi_dma0 0 4 QCOM_GPI_I2C>,
<&gpi_dma0 1 4 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
@@ -1257,6 +1278,8 @@
<&aggre1_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI1 0>;
interconnect-names = "qup-core", "qup-config",
"qup-memory";
+ power-domains = <&rpmhpd SC7280_CX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
dmas = <&gpi_dma0 0 5 QCOM_GPI_I2C>,
<&gpi_dma0 1 5 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
@@ -1315,6 +1338,8 @@
<&aggre1_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI1 0>;
interconnect-names = "qup-core", "qup-config",
"qup-memory";
+ power-domains = <&rpmhpd SC7280_CX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
dmas = <&gpi_dma0 0 6 QCOM_GPI_I2C>,
<&gpi_dma0 1 6 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
@@ -1373,6 +1398,8 @@
<&aggre1_noc MASTER_QUP_0 0 &mc_virt SLAVE_EBI1 0>;
interconnect-names = "qup-core", "qup-config",
"qup-memory";
+ power-domains = <&rpmhpd SC7280_CX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
dmas = <&gpi_dma0 0 7 QCOM_GPI_I2C>,
<&gpi_dma0 1 7 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
@@ -1419,7 +1446,7 @@
gpi_dma1: dma-controller@a00000 {
#dma-cells = <3>;
- compatible = "qcom,sc7280-gpi-dma";
+ compatible = "qcom,sc7280-gpi-dma", "qcom,sm6350-gpi-dma";
reg = <0 0x00a00000 0 0x60000>;
interrupts = <GIC_SPI 279 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 280 IRQ_TYPE_LEVEL_HIGH>,
@@ -1466,6 +1493,8 @@
<&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI1 0>;
interconnect-names = "qup-core", "qup-config",
"qup-memory";
+ power-domains = <&rpmhpd SC7280_CX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
dmas = <&gpi_dma1 0 0 QCOM_GPI_I2C>,
<&gpi_dma1 1 0 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
@@ -1524,6 +1553,8 @@
<&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI1 0>;
interconnect-names = "qup-core", "qup-config",
"qup-memory";
+ power-domains = <&rpmhpd SC7280_CX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
dmas = <&gpi_dma1 0 1 QCOM_GPI_I2C>,
<&gpi_dma1 1 1 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
@@ -1582,6 +1613,8 @@
<&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI1 0>;
interconnect-names = "qup-core", "qup-config",
"qup-memory";
+ power-domains = <&rpmhpd SC7280_CX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
dmas = <&gpi_dma1 0 2 QCOM_GPI_I2C>,
<&gpi_dma1 1 2 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
@@ -1640,6 +1673,8 @@
<&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI1 0>;
interconnect-names = "qup-core", "qup-config",
"qup-memory";
+ power-domains = <&rpmhpd SC7280_CX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
dmas = <&gpi_dma1 0 3 QCOM_GPI_I2C>,
<&gpi_dma1 1 3 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
@@ -1698,6 +1733,8 @@
<&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI1 0>;
interconnect-names = "qup-core", "qup-config",
"qup-memory";
+ power-domains = <&rpmhpd SC7280_CX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
dmas = <&gpi_dma1 0 4 QCOM_GPI_I2C>,
<&gpi_dma1 1 4 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
@@ -1756,6 +1793,8 @@
<&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI1 0>;
interconnect-names = "qup-core", "qup-config",
"qup-memory";
+ power-domains = <&rpmhpd SC7280_CX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
dmas = <&gpi_dma1 0 5 QCOM_GPI_I2C>,
<&gpi_dma1 1 5 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
@@ -1814,6 +1853,8 @@
<&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI1 0>;
interconnect-names = "qup-core", "qup-config",
"qup-memory";
+ power-domains = <&rpmhpd SC7280_CX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
dmas = <&gpi_dma1 0 6 QCOM_GPI_I2C>,
<&gpi_dma1 1 6 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
@@ -1872,6 +1913,8 @@
<&aggre2_noc MASTER_QUP_1 0 &mc_virt SLAVE_EBI1 0>;
interconnect-names = "qup-core", "qup-config",
"qup-memory";
+ power-domains = <&rpmhpd SC7280_CX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
dmas = <&gpi_dma1 0 7 QCOM_GPI_I2C>,
<&gpi_dma1 1 7 QCOM_GPI_I2C>;
dma-names = "tx", "rx";
@@ -2004,6 +2047,8 @@
qcom,rproc = <&remoteproc_wpss>;
memory-region = <&wlan_fw_mem>, <&wlan_ce_mem>;
status = "disabled";
+ qcom,smem-states = <&wlan_smp2p_out 0>;
+ qcom,smem-state-names = "wlan-smp2p-out";
};
pcie1: pci@1c08000 {
@@ -2285,7 +2330,6 @@
qcom,ports-block-pack-mode = /bits/ 8 <0xff 0xff 0xff>;
qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff>;
qcom,ports-lane-control = /bits/ 8 <0x00 0x01 0x00>;
- qcom,port-offset = <1>;
#sound-dai-cells = <1>;
#address-cells = <2>;
@@ -2434,84 +2478,42 @@
#gpio-cells = <2>;
gpio-ranges = <&lpass_tlmm 0 0 15>;
- #clock-cells = <1>;
-
- lpass_dmic01_clk: dmic01-clk {
- pins = "gpio6";
- function = "dmic1_clk";
- };
-
- lpass_dmic01_clk_sleep: dmic01-clk-sleep {
+ lpass_dmic01_clk: dmic01-clk-state {
pins = "gpio6";
function = "dmic1_clk";
};
- lpass_dmic01_data: dmic01-data {
+ lpass_dmic01_data: dmic01-data-state {
pins = "gpio7";
function = "dmic1_data";
};
- lpass_dmic01_data_sleep: dmic01-data-sleep {
- pins = "gpio7";
- function = "dmic1_data";
- };
-
- lpass_dmic23_clk: dmic23-clk {
- pins = "gpio8";
- function = "dmic2_clk";
- };
-
- lpass_dmic23_clk_sleep: dmic23-clk-sleep {
+ lpass_dmic23_clk: dmic23-clk-state {
pins = "gpio8";
function = "dmic2_clk";
};
- lpass_dmic23_data: dmic23-data {
+ lpass_dmic23_data: dmic23-data-state {
pins = "gpio9";
function = "dmic2_data";
};
- lpass_dmic23_data_sleep: dmic23-data-sleep {
- pins = "gpio9";
- function = "dmic2_data";
- };
-
- lpass_rx_swr_clk: rx-swr-clk {
+ lpass_rx_swr_clk: rx-swr-clk-state {
pins = "gpio3";
function = "swr_rx_clk";
};
- lpass_rx_swr_clk_sleep: rx-swr-clk-sleep {
- pins = "gpio3";
- function = "swr_rx_clk";
- };
-
- lpass_rx_swr_data: rx-swr-data {
+ lpass_rx_swr_data: rx-swr-data-state {
pins = "gpio4", "gpio5";
function = "swr_rx_data";
};
- lpass_rx_swr_data_sleep: rx-swr-data-sleep {
- pins = "gpio4", "gpio5";
- function = "swr_rx_data";
- };
-
- lpass_tx_swr_clk: tx-swr-clk {
- pins = "gpio0";
- function = "swr_tx_clk";
- };
-
- lpass_tx_swr_clk_sleep: tx-swr-clk-sleep {
+ lpass_tx_swr_clk: tx-swr-clk-state {
pins = "gpio0";
function = "swr_tx_clk";
};
- lpass_tx_swr_data: tx-swr-data {
- pins = "gpio1", "gpio2", "gpio14";
- function = "swr_tx_data";
- };
-
- lpass_tx_swr_data_sleep: tx-swr-data-sleep {
+ lpass_tx_swr_data: tx-swr-data-state {
pins = "gpio1", "gpio2", "gpio14";
function = "swr_tx_data";
};
@@ -3924,11 +3926,13 @@
"iface",
"bus";
+ assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>, <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+ assigned-clock-parents = <&mdss_dsi_phy 0>, <&mdss_dsi_phy 1>;
+
operating-points-v2 = <&dsi_opp_table>;
power-domains = <&rpmhpd SC7280_CX>;
phys = <&mdss_dsi_phy>;
- phy-names = "dsi";
#address-cells = <1>;
#size-cells = <0>;
@@ -4259,791 +4263,791 @@
gpio-ranges = <&tlmm 0 0 175>;
wakeup-parent = <&pdc>;
- dp_hot_plug_det: dp-hot-plug-det-pins {
+ dp_hot_plug_det: dp-hot-plug-det-state {
pins = "gpio47";
function = "dp_hot";
};
- edp_hot_plug_det: edp-hot-plug-det-pins {
+ edp_hot_plug_det: edp-hot-plug-det-state {
pins = "gpio60";
function = "edp_hot";
};
- mi2s0_data0: mi2s0-data0-pins {
+ mi2s0_data0: mi2s0-data0-state {
pins = "gpio98";
function = "mi2s0_data0";
};
- mi2s0_data1: mi2s0-data1-pins {
+ mi2s0_data1: mi2s0-data1-state {
pins = "gpio99";
function = "mi2s0_data1";
};
- mi2s0_mclk: mi2s0-mclk-pins {
+ mi2s0_mclk: mi2s0-mclk-state {
pins = "gpio96";
function = "pri_mi2s";
};
- mi2s0_sclk: mi2s0-sclk-pins {
+ mi2s0_sclk: mi2s0-sclk-state {
pins = "gpio97";
function = "mi2s0_sck";
};
- mi2s0_ws: mi2s0-ws-pins {
+ mi2s0_ws: mi2s0-ws-state {
pins = "gpio100";
function = "mi2s0_ws";
};
- mi2s1_data0: mi2s1-data0-pins {
+ mi2s1_data0: mi2s1-data0-state {
pins = "gpio107";
function = "mi2s1_data0";
};
- mi2s1_sclk: mi2s1-sclk-pins {
+ mi2s1_sclk: mi2s1-sclk-state {
pins = "gpio106";
function = "mi2s1_sck";
};
- mi2s1_ws: mi2s1-ws-pins {
+ mi2s1_ws: mi2s1-ws-state {
pins = "gpio108";
function = "mi2s1_ws";
};
- pcie1_clkreq_n: pcie1-clkreq-n-pins {
+ pcie1_clkreq_n: pcie1-clkreq-n-state {
pins = "gpio79";
function = "pcie1_clkreqn";
};
- qspi_clk: qspi-clk-pins {
+ qspi_clk: qspi-clk-state {
pins = "gpio14";
function = "qspi_clk";
};
- qspi_cs0: qspi-cs0-pins {
+ qspi_cs0: qspi-cs0-state {
pins = "gpio15";
function = "qspi_cs";
};
- qspi_cs1: qspi-cs1-pins {
+ qspi_cs1: qspi-cs1-state {
pins = "gpio19";
function = "qspi_cs";
};
- qspi_data01: qspi-data01-pins {
+ qspi_data01: qspi-data01-state {
pins = "gpio12", "gpio13";
function = "qspi_data";
};
- qspi_data12: qspi-data12-pins {
+ qspi_data12: qspi-data12-state {
pins = "gpio16", "gpio17";
function = "qspi_data";
};
- qup_i2c0_data_clk: qup-i2c0-data-clk-pins {
+ qup_i2c0_data_clk: qup-i2c0-data-clk-state {
pins = "gpio0", "gpio1";
function = "qup00";
};
- qup_i2c1_data_clk: qup-i2c1-data-clk-pins {
+ qup_i2c1_data_clk: qup-i2c1-data-clk-state {
pins = "gpio4", "gpio5";
function = "qup01";
};
- qup_i2c2_data_clk: qup-i2c2-data-clk-pins {
+ qup_i2c2_data_clk: qup-i2c2-data-clk-state {
pins = "gpio8", "gpio9";
function = "qup02";
};
- qup_i2c3_data_clk: qup-i2c3-data-clk-pins {
+ qup_i2c3_data_clk: qup-i2c3-data-clk-state {
pins = "gpio12", "gpio13";
function = "qup03";
};
- qup_i2c4_data_clk: qup-i2c4-data-clk-pins {
+ qup_i2c4_data_clk: qup-i2c4-data-clk-state {
pins = "gpio16", "gpio17";
function = "qup04";
};
- qup_i2c5_data_clk: qup-i2c5-data-clk-pins {
+ qup_i2c5_data_clk: qup-i2c5-data-clk-state {
pins = "gpio20", "gpio21";
function = "qup05";
};
- qup_i2c6_data_clk: qup-i2c6-data-clk-pins {
+ qup_i2c6_data_clk: qup-i2c6-data-clk-state {
pins = "gpio24", "gpio25";
function = "qup06";
};
- qup_i2c7_data_clk: qup-i2c7-data-clk-pins {
+ qup_i2c7_data_clk: qup-i2c7-data-clk-state {
pins = "gpio28", "gpio29";
function = "qup07";
};
- qup_i2c8_data_clk: qup-i2c8-data-clk-pins {
+ qup_i2c8_data_clk: qup-i2c8-data-clk-state {
pins = "gpio32", "gpio33";
function = "qup10";
};
- qup_i2c9_data_clk: qup-i2c9-data-clk-pins {
+ qup_i2c9_data_clk: qup-i2c9-data-clk-state {
pins = "gpio36", "gpio37";
function = "qup11";
};
- qup_i2c10_data_clk: qup-i2c10-data-clk-pins {
+ qup_i2c10_data_clk: qup-i2c10-data-clk-state {
pins = "gpio40", "gpio41";
function = "qup12";
};
- qup_i2c11_data_clk: qup-i2c11-data-clk-pins {
+ qup_i2c11_data_clk: qup-i2c11-data-clk-state {
pins = "gpio44", "gpio45";
function = "qup13";
};
- qup_i2c12_data_clk: qup-i2c12-data-clk-pins {
+ qup_i2c12_data_clk: qup-i2c12-data-clk-state {
pins = "gpio48", "gpio49";
function = "qup14";
};
- qup_i2c13_data_clk: qup-i2c13-data-clk-pins {
+ qup_i2c13_data_clk: qup-i2c13-data-clk-state {
pins = "gpio52", "gpio53";
function = "qup15";
};
- qup_i2c14_data_clk: qup-i2c14-data-clk-pins {
+ qup_i2c14_data_clk: qup-i2c14-data-clk-state {
pins = "gpio56", "gpio57";
function = "qup16";
};
- qup_i2c15_data_clk: qup-i2c15-data-clk-pins {
+ qup_i2c15_data_clk: qup-i2c15-data-clk-state {
pins = "gpio60", "gpio61";
function = "qup17";
};
- qup_spi0_data_clk: qup-spi0-data-clk-pins {
+ qup_spi0_data_clk: qup-spi0-data-clk-state {
pins = "gpio0", "gpio1", "gpio2";
function = "qup00";
};
- qup_spi0_cs: qup-spi0-cs-pins {
+ qup_spi0_cs: qup-spi0-cs-state {
pins = "gpio3";
function = "qup00";
};
- qup_spi0_cs_gpio: qup-spi0-cs-gpio-pins {
+ qup_spi0_cs_gpio: qup-spi0-cs-gpio-state {
pins = "gpio3";
function = "gpio";
};
- qup_spi1_data_clk: qup-spi1-data-clk-pins {
+ qup_spi1_data_clk: qup-spi1-data-clk-state {
pins = "gpio4", "gpio5", "gpio6";
function = "qup01";
};
- qup_spi1_cs: qup-spi1-cs-pins {
+ qup_spi1_cs: qup-spi1-cs-state {
pins = "gpio7";
function = "qup01";
};
- qup_spi1_cs_gpio: qup-spi1-cs-gpio-pins {
+ qup_spi1_cs_gpio: qup-spi1-cs-gpio-state {
pins = "gpio7";
function = "gpio";
};
- qup_spi2_data_clk: qup-spi2-data-clk-pins {
+ qup_spi2_data_clk: qup-spi2-data-clk-state {
pins = "gpio8", "gpio9", "gpio10";
function = "qup02";
};
- qup_spi2_cs: qup-spi2-cs-pins {
+ qup_spi2_cs: qup-spi2-cs-state {
pins = "gpio11";
function = "qup02";
};
- qup_spi2_cs_gpio: qup-spi2-cs-gpio-pins {
+ qup_spi2_cs_gpio: qup-spi2-cs-gpio-state {
pins = "gpio11";
function = "gpio";
};
- qup_spi3_data_clk: qup-spi3-data-clk-pins {
+ qup_spi3_data_clk: qup-spi3-data-clk-state {
pins = "gpio12", "gpio13", "gpio14";
function = "qup03";
};
- qup_spi3_cs: qup-spi3-cs-pins {
+ qup_spi3_cs: qup-spi3-cs-state {
pins = "gpio15";
function = "qup03";
};
- qup_spi3_cs_gpio: qup-spi3-cs-gpio-pins {
+ qup_spi3_cs_gpio: qup-spi3-cs-gpio-state {
pins = "gpio15";
function = "gpio";
};
- qup_spi4_data_clk: qup-spi4-data-clk-pins {
+ qup_spi4_data_clk: qup-spi4-data-clk-state {
pins = "gpio16", "gpio17", "gpio18";
function = "qup04";
};
- qup_spi4_cs: qup-spi4-cs-pins {
+ qup_spi4_cs: qup-spi4-cs-state {
pins = "gpio19";
function = "qup04";
};
- qup_spi4_cs_gpio: qup-spi4-cs-gpio-pins {
+ qup_spi4_cs_gpio: qup-spi4-cs-gpio-state {
pins = "gpio19";
function = "gpio";
};
- qup_spi5_data_clk: qup-spi5-data-clk-pins {
+ qup_spi5_data_clk: qup-spi5-data-clk-state {
pins = "gpio20", "gpio21", "gpio22";
function = "qup05";
};
- qup_spi5_cs: qup-spi5-cs-pins {
+ qup_spi5_cs: qup-spi5-cs-state {
pins = "gpio23";
function = "qup05";
};
- qup_spi5_cs_gpio: qup-spi5-cs-gpio-pins {
+ qup_spi5_cs_gpio: qup-spi5-cs-gpio-state {
pins = "gpio23";
function = "gpio";
};
- qup_spi6_data_clk: qup-spi6-data-clk-pins {
+ qup_spi6_data_clk: qup-spi6-data-clk-state {
pins = "gpio24", "gpio25", "gpio26";
function = "qup06";
};
- qup_spi6_cs: qup-spi6-cs-pins {
+ qup_spi6_cs: qup-spi6-cs-state {
pins = "gpio27";
function = "qup06";
};
- qup_spi6_cs_gpio: qup-spi6-cs-gpio-pins {
+ qup_spi6_cs_gpio: qup-spi6-cs-gpio-state {
pins = "gpio27";
function = "gpio";
};
- qup_spi7_data_clk: qup-spi7-data-clk-pins {
+ qup_spi7_data_clk: qup-spi7-data-clk-state {
pins = "gpio28", "gpio29", "gpio30";
function = "qup07";
};
- qup_spi7_cs: qup-spi7-cs-pins {
+ qup_spi7_cs: qup-spi7-cs-state {
pins = "gpio31";
function = "qup07";
};
- qup_spi7_cs_gpio: qup-spi7-cs-gpio-pins {
+ qup_spi7_cs_gpio: qup-spi7-cs-gpio-state {
pins = "gpio31";
function = "gpio";
};
- qup_spi8_data_clk: qup-spi8-data-clk-pins {
+ qup_spi8_data_clk: qup-spi8-data-clk-state {
pins = "gpio32", "gpio33", "gpio34";
function = "qup10";
};
- qup_spi8_cs: qup-spi8-cs-pins {
+ qup_spi8_cs: qup-spi8-cs-state {
pins = "gpio35";
function = "qup10";
};
- qup_spi8_cs_gpio: qup-spi8-cs-gpio-pins {
+ qup_spi8_cs_gpio: qup-spi8-cs-gpio-state {
pins = "gpio35";
function = "gpio";
};
- qup_spi9_data_clk: qup-spi9-data-clk-pins {
+ qup_spi9_data_clk: qup-spi9-data-clk-state {
pins = "gpio36", "gpio37", "gpio38";
function = "qup11";
};
- qup_spi9_cs: qup-spi9-cs-pins {
+ qup_spi9_cs: qup-spi9-cs-state {
pins = "gpio39";
function = "qup11";
};
- qup_spi9_cs_gpio: qup-spi9-cs-gpio-pins {
+ qup_spi9_cs_gpio: qup-spi9-cs-gpio-state {
pins = "gpio39";
function = "gpio";
};
- qup_spi10_data_clk: qup-spi10-data-clk-pins {
+ qup_spi10_data_clk: qup-spi10-data-clk-state {
pins = "gpio40", "gpio41", "gpio42";
function = "qup12";
};
- qup_spi10_cs: qup-spi10-cs-pins {
+ qup_spi10_cs: qup-spi10-cs-state {
pins = "gpio43";
function = "qup12";
};
- qup_spi10_cs_gpio: qup-spi10-cs-gpio-pins {
+ qup_spi10_cs_gpio: qup-spi10-cs-gpio-state {
pins = "gpio43";
function = "gpio";
};
- qup_spi11_data_clk: qup-spi11-data-clk-pins {
+ qup_spi11_data_clk: qup-spi11-data-clk-state {
pins = "gpio44", "gpio45", "gpio46";
function = "qup13";
};
- qup_spi11_cs: qup-spi11-cs-pins {
+ qup_spi11_cs: qup-spi11-cs-state {
pins = "gpio47";
function = "qup13";
};
- qup_spi11_cs_gpio: qup-spi11-cs-gpio-pins {
+ qup_spi11_cs_gpio: qup-spi11-cs-gpio-state {
pins = "gpio47";
function = "gpio";
};
- qup_spi12_data_clk: qup-spi12-data-clk-pins {
+ qup_spi12_data_clk: qup-spi12-data-clk-state {
pins = "gpio48", "gpio49", "gpio50";
function = "qup14";
};
- qup_spi12_cs: qup-spi12-cs-pins {
+ qup_spi12_cs: qup-spi12-cs-state {
pins = "gpio51";
function = "qup14";
};
- qup_spi12_cs_gpio: qup-spi12-cs-gpio-pins {
+ qup_spi12_cs_gpio: qup-spi12-cs-gpio-state {
pins = "gpio51";
function = "gpio";
};
- qup_spi13_data_clk: qup-spi13-data-clk-pins {
+ qup_spi13_data_clk: qup-spi13-data-clk-state {
pins = "gpio52", "gpio53", "gpio54";
function = "qup15";
};
- qup_spi13_cs: qup-spi13-cs-pins {
+ qup_spi13_cs: qup-spi13-cs-state {
pins = "gpio55";
function = "qup15";
};
- qup_spi13_cs_gpio: qup-spi13-cs-gpio-pins {
+ qup_spi13_cs_gpio: qup-spi13-cs-gpio-state {
pins = "gpio55";
function = "gpio";
};
- qup_spi14_data_clk: qup-spi14-data-clk-pins {
+ qup_spi14_data_clk: qup-spi14-data-clk-state {
pins = "gpio56", "gpio57", "gpio58";
function = "qup16";
};
- qup_spi14_cs: qup-spi14-cs-pins {
+ qup_spi14_cs: qup-spi14-cs-state {
pins = "gpio59";
function = "qup16";
};
- qup_spi14_cs_gpio: qup-spi14-cs-gpio-pins {
+ qup_spi14_cs_gpio: qup-spi14-cs-gpio-state {
pins = "gpio59";
function = "gpio";
};
- qup_spi15_data_clk: qup-spi15-data-clk-pins {
+ qup_spi15_data_clk: qup-spi15-data-clk-state {
pins = "gpio60", "gpio61", "gpio62";
function = "qup17";
};
- qup_spi15_cs: qup-spi15-cs-pins {
+ qup_spi15_cs: qup-spi15-cs-state {
pins = "gpio63";
function = "qup17";
};
- qup_spi15_cs_gpio: qup-spi15-cs-gpio-pins {
+ qup_spi15_cs_gpio: qup-spi15-cs-gpio-state {
pins = "gpio63";
function = "gpio";
};
- qup_uart0_cts: qup-uart0-cts-pins {
+ qup_uart0_cts: qup-uart0-cts-state {
pins = "gpio0";
function = "qup00";
};
- qup_uart0_rts: qup-uart0-rts-pins {
+ qup_uart0_rts: qup-uart0-rts-state {
pins = "gpio1";
function = "qup00";
};
- qup_uart0_tx: qup-uart0-tx-pins {
+ qup_uart0_tx: qup-uart0-tx-state {
pins = "gpio2";
function = "qup00";
};
- qup_uart0_rx: qup-uart0-rx-pins {
+ qup_uart0_rx: qup-uart0-rx-state {
pins = "gpio3";
function = "qup00";
};
- qup_uart1_cts: qup-uart1-cts-pins {
+ qup_uart1_cts: qup-uart1-cts-state {
pins = "gpio4";
function = "qup01";
};
- qup_uart1_rts: qup-uart1-rts-pins {
+ qup_uart1_rts: qup-uart1-rts-state {
pins = "gpio5";
function = "qup01";
};
- qup_uart1_tx: qup-uart1-tx-pins {
+ qup_uart1_tx: qup-uart1-tx-state {
pins = "gpio6";
function = "qup01";
};
- qup_uart1_rx: qup-uart1-rx-pins {
+ qup_uart1_rx: qup-uart1-rx-state {
pins = "gpio7";
function = "qup01";
};
- qup_uart2_cts: qup-uart2-cts-pins {
+ qup_uart2_cts: qup-uart2-cts-state {
pins = "gpio8";
function = "qup02";
};
- qup_uart2_rts: qup-uart2-rts-pins {
+ qup_uart2_rts: qup-uart2-rts-state {
pins = "gpio9";
function = "qup02";
};
- qup_uart2_tx: qup-uart2-tx-pins {
+ qup_uart2_tx: qup-uart2-tx-state {
pins = "gpio10";
function = "qup02";
};
- qup_uart2_rx: qup-uart2-rx-pins {
+ qup_uart2_rx: qup-uart2-rx-state {
pins = "gpio11";
function = "qup02";
};
- qup_uart3_cts: qup-uart3-cts-pins {
+ qup_uart3_cts: qup-uart3-cts-state {
pins = "gpio12";
function = "qup03";
};
- qup_uart3_rts: qup-uart3-rts-pins {
+ qup_uart3_rts: qup-uart3-rts-state {
pins = "gpio13";
function = "qup03";
};
- qup_uart3_tx: qup-uart3-tx-pins {
+ qup_uart3_tx: qup-uart3-tx-state {
pins = "gpio14";
function = "qup03";
};
- qup_uart3_rx: qup-uart3-rx-pins {
+ qup_uart3_rx: qup-uart3-rx-state {
pins = "gpio15";
function = "qup03";
};
- qup_uart4_cts: qup-uart4-cts-pins {
+ qup_uart4_cts: qup-uart4-cts-state {
pins = "gpio16";
function = "qup04";
};
- qup_uart4_rts: qup-uart4-rts-pins {
+ qup_uart4_rts: qup-uart4-rts-state {
pins = "gpio17";
function = "qup04";
};
- qup_uart4_tx: qup-uart4-tx-pins {
+ qup_uart4_tx: qup-uart4-tx-state {
pins = "gpio18";
function = "qup04";
};
- qup_uart4_rx: qup-uart4-rx-pins {
+ qup_uart4_rx: qup-uart4-rx-state {
pins = "gpio19";
function = "qup04";
};
- qup_uart5_cts: qup-uart5-cts-pins {
+ qup_uart5_cts: qup-uart5-cts-state {
pins = "gpio20";
function = "qup05";
};
- qup_uart5_rts: qup-uart5-rts-pins {
+ qup_uart5_rts: qup-uart5-rts-state {
pins = "gpio21";
function = "qup05";
};
- qup_uart5_tx: qup-uart5-tx-pins {
+ qup_uart5_tx: qup-uart5-tx-state {
pins = "gpio22";
function = "qup05";
};
- qup_uart5_rx: qup-uart5-rx-pins {
+ qup_uart5_rx: qup-uart5-rx-state {
pins = "gpio23";
function = "qup05";
};
- qup_uart6_cts: qup-uart6-cts-pins {
+ qup_uart6_cts: qup-uart6-cts-state {
pins = "gpio24";
function = "qup06";
};
- qup_uart6_rts: qup-uart6-rts-pins {
+ qup_uart6_rts: qup-uart6-rts-state {
pins = "gpio25";
function = "qup06";
};
- qup_uart6_tx: qup-uart6-tx-pins {
+ qup_uart6_tx: qup-uart6-tx-state {
pins = "gpio26";
function = "qup06";
};
- qup_uart6_rx: qup-uart6-rx-pins {
+ qup_uart6_rx: qup-uart6-rx-state {
pins = "gpio27";
function = "qup06";
};
- qup_uart7_cts: qup-uart7-cts-pins {
+ qup_uart7_cts: qup-uart7-cts-state {
pins = "gpio28";
function = "qup07";
};
- qup_uart7_rts: qup-uart7-rts-pins {
+ qup_uart7_rts: qup-uart7-rts-state {
pins = "gpio29";
function = "qup07";
};
- qup_uart7_tx: qup-uart7-tx-pins {
+ qup_uart7_tx: qup-uart7-tx-state {
pins = "gpio30";
function = "qup07";
};
- qup_uart7_rx: qup-uart7-rx-pins {
+ qup_uart7_rx: qup-uart7-rx-state {
pins = "gpio31";
function = "qup07";
};
- qup_uart8_cts: qup-uart8-cts-pins {
+ qup_uart8_cts: qup-uart8-cts-state {
pins = "gpio32";
function = "qup10";
};
- qup_uart8_rts: qup-uart8-rts-pins {
+ qup_uart8_rts: qup-uart8-rts-state {
pins = "gpio33";
function = "qup10";
};
- qup_uart8_tx: qup-uart8-tx-pins {
+ qup_uart8_tx: qup-uart8-tx-state {
pins = "gpio34";
function = "qup10";
};
- qup_uart8_rx: qup-uart8-rx-pins {
+ qup_uart8_rx: qup-uart8-rx-state {
pins = "gpio35";
function = "qup10";
};
- qup_uart9_cts: qup-uart9-cts-pins {
+ qup_uart9_cts: qup-uart9-cts-state {
pins = "gpio36";
function = "qup11";
};
- qup_uart9_rts: qup-uart9-rts-pins {
+ qup_uart9_rts: qup-uart9-rts-state {
pins = "gpio37";
function = "qup11";
};
- qup_uart9_tx: qup-uart9-tx-pins {
+ qup_uart9_tx: qup-uart9-tx-state {
pins = "gpio38";
function = "qup11";
};
- qup_uart9_rx: qup-uart9-rx-pins {
+ qup_uart9_rx: qup-uart9-rx-state {
pins = "gpio39";
function = "qup11";
};
- qup_uart10_cts: qup-uart10-cts-pins {
+ qup_uart10_cts: qup-uart10-cts-state {
pins = "gpio40";
function = "qup12";
};
- qup_uart10_rts: qup-uart10-rts-pins {
+ qup_uart10_rts: qup-uart10-rts-state {
pins = "gpio41";
function = "qup12";
};
- qup_uart10_tx: qup-uart10-tx-pins {
+ qup_uart10_tx: qup-uart10-tx-state {
pins = "gpio42";
function = "qup12";
};
- qup_uart10_rx: qup-uart10-rx-pins {
+ qup_uart10_rx: qup-uart10-rx-state {
pins = "gpio43";
function = "qup12";
};
- qup_uart11_cts: qup-uart11-cts-pins {
+ qup_uart11_cts: qup-uart11-cts-state {
pins = "gpio44";
function = "qup13";
};
- qup_uart11_rts: qup-uart11-rts-pins {
+ qup_uart11_rts: qup-uart11-rts-state {
pins = "gpio45";
function = "qup13";
};
- qup_uart11_tx: qup-uart11-tx-pins {
+ qup_uart11_tx: qup-uart11-tx-state {
pins = "gpio46";
function = "qup13";
};
- qup_uart11_rx: qup-uart11-rx-pins {
+ qup_uart11_rx: qup-uart11-rx-state {
pins = "gpio47";
function = "qup13";
};
- qup_uart12_cts: qup-uart12-cts-pins {
+ qup_uart12_cts: qup-uart12-cts-state {
pins = "gpio48";
function = "qup14";
};
- qup_uart12_rts: qup-uart12-rts-pins {
+ qup_uart12_rts: qup-uart12-rts-state {
pins = "gpio49";
function = "qup14";
};
- qup_uart12_tx: qup-uart12-tx-pins {
+ qup_uart12_tx: qup-uart12-tx-state {
pins = "gpio50";
function = "qup14";
};
- qup_uart12_rx: qup-uart12-rx-pins {
+ qup_uart12_rx: qup-uart12-rx-state {
pins = "gpio51";
function = "qup14";
};
- qup_uart13_cts: qup-uart13-cts-pins {
+ qup_uart13_cts: qup-uart13-cts-state {
pins = "gpio52";
function = "qup15";
};
- qup_uart13_rts: qup-uart13-rts-pins {
+ qup_uart13_rts: qup-uart13-rts-state {
pins = "gpio53";
function = "qup15";
};
- qup_uart13_tx: qup-uart13-tx-pins {
+ qup_uart13_tx: qup-uart13-tx-state {
pins = "gpio54";
function = "qup15";
};
- qup_uart13_rx: qup-uart13-rx-pins {
+ qup_uart13_rx: qup-uart13-rx-state {
pins = "gpio55";
function = "qup15";
};
- qup_uart14_cts: qup-uart14-cts-pins {
+ qup_uart14_cts: qup-uart14-cts-state {
pins = "gpio56";
function = "qup16";
};
- qup_uart14_rts: qup-uart14-rts-pins {
+ qup_uart14_rts: qup-uart14-rts-state {
pins = "gpio57";
function = "qup16";
};
- qup_uart14_tx: qup-uart14-tx-pins {
+ qup_uart14_tx: qup-uart14-tx-state {
pins = "gpio58";
function = "qup16";
};
- qup_uart14_rx: qup-uart14-rx-pins {
+ qup_uart14_rx: qup-uart14-rx-state {
pins = "gpio59";
function = "qup16";
};
- qup_uart15_cts: qup-uart15-cts-pins {
+ qup_uart15_cts: qup-uart15-cts-state {
pins = "gpio60";
function = "qup17";
};
- qup_uart15_rts: qup-uart15-rts-pins {
+ qup_uart15_rts: qup-uart15-rts-state {
pins = "gpio61";
function = "qup17";
};
- qup_uart15_tx: qup-uart15-tx-pins {
+ qup_uart15_tx: qup-uart15-tx-state {
pins = "gpio62";
function = "qup17";
};
- qup_uart15_rx: qup-uart15-rx-pins {
+ qup_uart15_rx: qup-uart15-rx-state {
pins = "gpio63";
function = "qup17";
};
- sdc1_clk: sdc1-clk-pins {
+ sdc1_clk: sdc1-clk-state {
pins = "sdc1_clk";
};
- sdc1_cmd: sdc1-cmd-pins {
+ sdc1_cmd: sdc1-cmd-state {
pins = "sdc1_cmd";
};
- sdc1_data: sdc1-data-pins {
+ sdc1_data: sdc1-data-state {
pins = "sdc1_data";
};
- sdc1_rclk: sdc1-rclk-pins {
+ sdc1_rclk: sdc1-rclk-state {
pins = "sdc1_rclk";
};
- sdc1_clk_sleep: sdc1-clk-sleep-pins {
+ sdc1_clk_sleep: sdc1-clk-sleep-state {
pins = "sdc1_clk";
drive-strength = <2>;
bias-bus-hold;
};
- sdc1_cmd_sleep: sdc1-cmd-sleep-pins {
+ sdc1_cmd_sleep: sdc1-cmd-sleep-state {
pins = "sdc1_cmd";
drive-strength = <2>;
bias-bus-hold;
};
- sdc1_data_sleep: sdc1-data-sleep-pins {
+ sdc1_data_sleep: sdc1-data-sleep-state {
pins = "sdc1_data";
drive-strength = <2>;
bias-bus-hold;
};
- sdc1_rclk_sleep: sdc1-rclk-sleep-pins {
+ sdc1_rclk_sleep: sdc1-rclk-sleep-state {
pins = "sdc1_rclk";
drive-strength = <2>;
bias-bus-hold;
};
- sdc2_clk: sdc2-clk-pins {
+ sdc2_clk: sdc2-clk-state {
pins = "sdc2_clk";
};
- sdc2_cmd: sdc2-cmd-pins {
+ sdc2_cmd: sdc2-cmd-state {
pins = "sdc2_cmd";
};
- sdc2_data: sdc2-data-pins {
+ sdc2_data: sdc2-data-state {
pins = "sdc2_data";
};
- sdc2_clk_sleep: sdc2-clk-sleep-pins {
+ sdc2_clk_sleep: sdc2-clk-sleep-state {
pins = "sdc2_clk";
drive-strength = <2>;
bias-bus-hold;
};
- sdc2_cmd_sleep: sdc2-cmd-sleep-pins {
+ sdc2_cmd_sleep: sdc2-cmd-sleep-state {
pins = "sdc2_cmd";
drive-strength = <2>;
bias-bus-hold;
};
- sdc2_data_sleep: sdc2-data-sleep-pins {
+ sdc2_data_sleep: sdc2-data-sleep-state {
pins = "sdc2_data";
drive-strength = <2>;
bias-bus-hold;
@@ -5314,7 +5318,7 @@
};
epss_l3: interconnect@18590000 {
- compatible = "qcom,sc7280-epss-l3";
+ compatible = "qcom,sc7280-epss-l3", "qcom,epss-l3";
reg = <0 0x18590000 0 0x1000>;
clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GCC_GPLL0>;
clock-names = "xo", "alternate";
@@ -5322,7 +5326,7 @@
};
cpufreq_hw: cpufreq@18591000 {
- compatible = "qcom,cpufreq-epss";
+ compatible = "qcom,sc7280-cpufreq-epss", "qcom,cpufreq-epss";
reg = <0 0x18591000 0 0x1000>,
<0 0x18592000 0 0x1000>,
<0 0x18593000 0 0x1000>;
diff --git a/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts b/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts
index 5e30349efd20..551768f97729 100644
--- a/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts
+++ b/arch/arm64/boot/dts/qcom/sc8280xp-crd.dts
@@ -37,7 +37,7 @@
vreg_edp_bl: regulator-edp-bl {
compatible = "regulator-fixed";
- regulator-name = "VREG_EDP_BL";
+ regulator-name = "VBL9";
regulator-min-microvolt = <3600000>;
regulator-max-microvolt = <3600000>;
@@ -50,10 +50,24 @@
regulator-boot-on;
};
+ vreg_nvme: regulator-nvme {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VCC3_SSD";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&tlmm 135 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&nvme_reg_en>;
+ };
+
vreg_misc_3p3: regulator-misc-3p3 {
compatible = "regulator-fixed";
- regulator-name = "VREG_MISC_3P3";
+ regulator-name = "VCC3B";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
@@ -66,6 +80,38 @@
regulator-boot-on;
regulator-always-on;
};
+
+ vreg_wlan: regulator-wlan {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VCC_WLAN_3R9";
+ regulator-min-microvolt = <3900000>;
+ regulator-max-microvolt = <3900000>;
+
+ gpio = <&pmr735a_gpios 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&hastings_reg_en>;
+
+ regulator-boot-on;
+ };
+
+ vreg_wwan: regulator-wwan {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VCC3B_WAN";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&pmc8280_2_gpios 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&wwan_sw_en>;
+
+ regulator-boot-on;
+ };
};
&apps_rsc {
@@ -124,9 +170,8 @@
regulator-max-microvolt = <2504000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
regulator-allow-set-load;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
vreg_l13c: ldo13 {
@@ -149,9 +194,8 @@
regulator-max-microvolt = <1200000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
regulator-allow-set-load;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
vreg_l4d: ldo4 {
@@ -184,6 +228,63 @@
};
};
+&pcie2a {
+ perst-gpios = <&tlmm 143 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 145 GPIO_ACTIVE_LOW>;
+
+ vddpe-3v3-supply = <&vreg_nvme>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2a_default>;
+
+ status = "okay";
+};
+
+&pcie2a_phy {
+ vdda-phy-supply = <&vreg_l6d>;
+ vdda-pll-supply = <&vreg_l4d>;
+
+ status = "okay";
+};
+
+&pcie3a {
+ perst-gpios = <&tlmm 151 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 148 GPIO_ACTIVE_LOW>;
+
+ vddpe-3v3-supply = <&vreg_wwan>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie3a_default>;
+
+ status = "okay";
+};
+
+&pcie3a_phy {
+ vdda-phy-supply = <&vreg_l6d>;
+ vdda-pll-supply = <&vreg_l4d>;
+
+ status = "okay";
+};
+
+&pcie4 {
+ perst-gpios = <&tlmm 141 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 139 GPIO_ACTIVE_LOW>;
+
+ vddpe-3v3-supply = <&vreg_wlan>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie4_default>;
+
+ status = "okay";
+};
+
+&pcie4_phy {
+ vdda-phy-supply = <&vreg_l6d>;
+ vdda-pll-supply = <&vreg_l4d>;
+
+ status = "okay";
+};
+
&pmc8280c_lpg {
status = "okay";
};
@@ -369,6 +470,13 @@
};
};
+&pmc8280_2_gpios {
+ wwan_sw_en: wwan-sw-en-state {
+ pins = "gpio1";
+ function = "normal";
+ };
+};
+
&pmc8280c_gpios {
edp_bl_pwm: edp-bl-pwm-state {
pins = "gpio8";
@@ -376,29 +484,112 @@
};
};
+&pmr735a_gpios {
+ hastings_reg_en: hastings-reg-en-state {
+ pins = "gpio1";
+ function = "normal";
+ };
+};
+
&tlmm {
gpio-reserved-ranges = <74 6>, <83 4>, <125 2>, <128 2>, <154 7>;
kybd_default: kybd-default-state {
- disable {
+ disable-pins {
pins = "gpio102";
function = "gpio";
output-low;
};
- int-n {
+ int-n-pins {
pins = "gpio104";
function = "gpio";
bias-disable;
};
- reset {
+ reset-pins {
pins = "gpio105";
function = "gpio";
bias-disable;
};
};
+ nvme_reg_en: nvme-reg-en-state {
+ pins = "gpio135";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ pcie2a_default: pcie2a-default-state {
+ clkreq-n-pins {
+ pins = "gpio142";
+ function = "pcie2a_clkreq";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ perst-n-pins {
+ pins = "gpio143";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ wake-n-pins {
+ pins = "gpio145";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ pcie3a_default: pcie3a-default-state {
+ clkreq-n-pins {
+ pins = "gpio150";
+ function = "pcie3a_clkreq";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ perst-n-pins {
+ pins = "gpio151";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ wake-n-pins {
+ pins = "gpio148";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ pcie4_default: pcie4-default-state {
+ clkreq-n-pins {
+ pins = "gpio140";
+ function = "pcie4_clkreq";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ perst-n-pins {
+ pins = "gpio141";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ wake-n-pins {
+ pins = "gpio139";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
qup0_i2c4_default: qup0-i2c4-default-state {
pins = "gpio171", "gpio172";
function = "qup4";
@@ -416,7 +607,7 @@
};
tpad_default: tpad-default-state {
- int-n {
+ int-n-pins {
pins = "gpio182";
function = "gpio";
bias-disable;
@@ -424,13 +615,13 @@
};
ts0_default: ts0-default-state {
- int-n {
+ int-n-pins {
pins = "gpio175";
function = "gpio";
bias-disable;
};
- reset-n {
+ reset-n-pins {
pins = "gpio99";
function = "gpio";
output-high;
diff --git a/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts b/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts
index b2b744bb8a53..568c6be1ceaa 100644
--- a/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts
+++ b/arch/arm64/boot/dts/qcom/sc8280xp-lenovo-thinkpad-x13s.dts
@@ -7,6 +7,11 @@
/dts-v1/;
#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/iio/qcom,spmi-adc7-pm8350.h>
+#include <dt-bindings/iio/qcom,spmi-adc7-pmk8350.h>
+#include <dt-bindings/iio/qcom,spmi-adc7-pmr735a.h>
+#include <dt-bindings/input/gpio-keys.h>
+#include <dt-bindings/input/input.h>
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
#include "sc8280xp.dtsi"
@@ -26,6 +31,67 @@
pinctrl-0 = <&edp_bl_en>, <&edp_bl_pwm>;
};
+ thermal-zones {
+ skin-temp-thermal {
+ polling-delay-passive = <250>;
+ polling-delay = <0>;
+ thermal-sensors = <&pmk8280_adc_tm 5>;
+
+ trips {
+ skin_temp_alert0: trip-point0 {
+ temperature = <55000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ skin_temp_alert1: trip-point1 {
+ temperature = <58000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+
+ skin-temp-crit {
+ temperature = <73000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&skin_temp_alert0>;
+ cooling-device = <&CPU4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&CPU5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+
+ map1 {
+ trip = <&skin_temp_alert1>;
+ cooling-device = <&CPU4 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&CPU5 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&CPU6 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&CPU7 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&hall_int_n_default>;
+
+ switch-lid {
+ gpios = <&tlmm 107 GPIO_ACTIVE_LOW>;
+ linux,input-type = <EV_SW>;
+ linux,code = <SW_LID>;
+ wakeup-source;
+ wakeup-event-action = <EV_ACT_DEASSERTED>;
+ };
+ };
+
vreg_edp_bl: regulator-edp-bl {
compatible = "regulator-fixed";
@@ -58,6 +124,54 @@
regulator-boot-on;
regulator-always-on;
};
+
+ vreg_nvme: regulator-nvme {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VCC3_SSD";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&tlmm 135 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&nvme_reg_en>;
+
+ regulator-boot-on;
+ };
+
+ vreg_wlan: regulator-wlan {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VCC_WLAN_3R9";
+ regulator-min-microvolt = <3900000>;
+ regulator-max-microvolt = <3900000>;
+
+ gpio = <&pmr735a_gpios 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&hastings_reg_en>;
+
+ regulator-boot-on;
+ };
+
+ vreg_wwan: regulator-wwan {
+ compatible = "regulator-fixed";
+
+ regulator-name = "VCC3B_WAN";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ gpio = <&pmc8280_2_gpios 1 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&wwan_sw_en>;
+
+ regulator-boot-on;
+ };
};
&apps_rsc {
@@ -95,7 +209,7 @@
regulator-max-microvolt = <880000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
regulator-boot-on;
- regulator-always-on; // FIXME: VDD_A_EDP_0_0P9
+ regulator-always-on; /* FIXME: VDD_A_EDP_0_0P9 */
};
};
@@ -145,6 +259,13 @@
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
};
+ vreg_l6d: ldo6 {
+ regulator-name = "vreg_l6d";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
vreg_l7d: ldo7 {
regulator-name = "vreg_l7d";
regulator-min-microvolt = <3072000>;
@@ -161,14 +282,221 @@
};
};
+&pcie2a {
+ perst-gpios = <&tlmm 143 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 145 GPIO_ACTIVE_LOW>;
+
+ vddpe-3v3-supply = <&vreg_nvme>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie2a_default>;
+
+ status = "okay";
+};
+
+&pcie2a_phy {
+ vdda-phy-supply = <&vreg_l6d>;
+ vdda-pll-supply = <&vreg_l4d>;
+
+ status = "okay";
+};
+
+&pcie3a {
+ perst-gpios = <&tlmm 151 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 148 GPIO_ACTIVE_LOW>;
+
+ vddpe-3v3-supply = <&vreg_wwan>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie3a_default>;
+
+ status = "okay";
+};
+
+&pcie3a_phy {
+ vdda-phy-supply = <&vreg_l6d>;
+ vdda-pll-supply = <&vreg_l4d>;
+
+ status = "okay";
+};
+
+&pcie4 {
+ perst-gpios = <&tlmm 141 GPIO_ACTIVE_LOW>;
+ wake-gpios = <&tlmm 139 GPIO_ACTIVE_LOW>;
+
+ vddpe-3v3-supply = <&vreg_wlan>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie4_default>;
+
+ status = "okay";
+};
+
+&pcie4_phy {
+ vdda-phy-supply = <&vreg_l6d>;
+ vdda-pll-supply = <&vreg_l4d>;
+
+ status = "okay";
+};
+
&pmc8280c_lpg {
status = "okay";
};
+&pmk8280_adc_tm {
+ status = "okay";
+
+ sys-therm@0 {
+ reg = <0>;
+ io-channels = <&pmk8280_vadc PM8350_ADC7_AMUX_THM1_100K_PU(1)>;
+ qcom,hw-settle-time-us = <200>;
+ qcom,avg-samples = <2>;
+ qcom,ratiometric;
+ };
+
+ sys-therm@1 {
+ reg = <1>;
+ io-channels = <&pmk8280_vadc PM8350_ADC7_AMUX_THM2_100K_PU(1)>;
+ qcom,hw-settle-time-us = <200>;
+ qcom,avg-samples = <2>;
+ qcom,ratiometric;
+ };
+
+ sys-therm@2 {
+ reg = <2>;
+ io-channels = <&pmk8280_vadc PM8350_ADC7_AMUX_THM3_100K_PU(1)>;
+ qcom,hw-settle-time-us = <200>;
+ qcom,avg-samples = <2>;
+ qcom,ratiometric;
+ };
+
+ sys-therm@3 {
+ reg = <3>;
+ io-channels = <&pmk8280_vadc PM8350_ADC7_AMUX_THM4_100K_PU(1)>;
+ qcom,hw-settle-time-us = <200>;
+ qcom,avg-samples = <2>;
+ qcom,ratiometric;
+ };
+
+ sys-therm@4 {
+ reg = <4>;
+ io-channels = <&pmk8280_vadc PM8350_ADC7_AMUX_THM1_100K_PU(3)>;
+ qcom,hw-settle-time-us = <200>;
+ qcom,avg-samples = <2>;
+ qcom,ratiometric;
+ };
+
+ sys-therm@5 {
+ reg = <5>;
+ io-channels = <&pmk8280_vadc PM8350_ADC7_AMUX_THM2_100K_PU(3)>;
+ qcom,hw-settle-time-us = <200>;
+ qcom,avg-samples = <2>;
+ qcom,ratiometric;
+ };
+
+ sys-therm@6 {
+ reg = <6>;
+ io-channels = <&pmk8280_vadc PM8350_ADC7_AMUX_THM3_100K_PU(3)>;
+ qcom,hw-settle-time-us = <200>;
+ qcom,avg-samples = <2>;
+ qcom,ratiometric;
+ };
+
+ sys-therm@7 {
+ reg = <7>;
+ io-channels = <&pmk8280_vadc PM8350_ADC7_AMUX_THM4_100K_PU(3)>;
+ qcom,hw-settle-time-us = <200>;
+ qcom,avg-samples = <2>;
+ qcom,ratiometric;
+ };
+};
+
&pmk8280_pon_pwrkey {
status = "okay";
};
+&pmk8280_pon_resin {
+ status = "okay";
+};
+
+&pmk8280_vadc {
+ status = "okay";
+
+ pmic-die-temp@3 {
+ reg = <PMK8350_ADC7_DIE_TEMP>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ xo-therm@44 {
+ reg = <PMK8350_ADC7_AMUX_THM1_100K_PU>;
+ qcom,hw-settle-time = <200>;
+ qcom,ratiometric;
+ };
+
+ pmic-die-temp@103 {
+ reg = <PM8350_ADC7_DIE_TEMP(1)>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ sys-therm@144 {
+ reg = <PM8350_ADC7_AMUX_THM1_100K_PU(1)>;
+ qcom,hw-settle-time = <200>;
+ qcom,ratiometric;
+ };
+
+ sys-therm@145 {
+ reg = <PM8350_ADC7_AMUX_THM2_100K_PU(1)>;
+ qcom,hw-settle-time = <200>;
+ qcom,ratiometric;
+ };
+
+ sys-therm@146 {
+ reg = <PM8350_ADC7_AMUX_THM3_100K_PU(1)>;
+ qcom,hw-settle-time = <200>;
+ qcom,ratiometric;
+ };
+
+ sys-therm@147 {
+ reg = <PM8350_ADC7_AMUX_THM4_100K_PU(1)>;
+ qcom,hw-settle-time = <200>;
+ qcom,ratiometric;
+ };
+
+ pmic-die-temp@303 {
+ reg = <PM8350_ADC7_DIE_TEMP(3)>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ sys-therm@344 {
+ reg = <PM8350_ADC7_AMUX_THM1_100K_PU(3)>;
+ qcom,hw-settle-time = <200>;
+ qcom,ratiometric;
+ };
+
+ sys-therm@345 {
+ reg = <PM8350_ADC7_AMUX_THM2_100K_PU(3)>;
+ qcom,hw-settle-time = <200>;
+ qcom,ratiometric;
+ };
+
+ sys-therm@346 {
+ reg = <PM8350_ADC7_AMUX_THM3_100K_PU(3)>;
+ qcom,hw-settle-time = <200>;
+ qcom,ratiometric;
+ };
+
+ sys-therm@347 {
+ reg = <PM8350_ADC7_AMUX_THM4_100K_PU(3)>;
+ qcom,hw-settle-time = <200>;
+ qcom,ratiometric;
+ };
+
+ pmic-die-temp@403 {
+ reg = <PMR735A_ADC7_DIE_TEMP>;
+ qcom,pre-scaling = <1 1>;
+ };
+};
+
&qup0 {
status = "okay";
};
@@ -339,6 +667,13 @@
};
};
+&pmc8280_2_gpios {
+ wwan_sw_en: wwan-sw-en-state {
+ pins = "gpio1";
+ function = "normal";
+ };
+};
+
&pmc8280c_gpios {
edp_bl_pwm: edp-bl-pwm-state {
pins = "gpio8";
@@ -346,29 +681,119 @@
};
};
+&pmr735a_gpios {
+ hastings_reg_en: hastings-reg-en-state {
+ pins = "gpio1";
+ function = "normal";
+ };
+};
+
&tlmm {
gpio-reserved-ranges = <70 2>, <74 6>, <83 4>, <125 2>, <128 2>, <154 7>;
+ hall_int_n_default: hall-int-n-state {
+ pins = "gpio107";
+ function = "gpio";
+ input-enable;
+ bias-disable;
+ };
+
kybd_default: kybd-default-state {
- disable {
+ disable-pins {
pins = "gpio102";
function = "gpio";
output-low;
};
- int-n {
+ int-n-pins {
pins = "gpio104";
function = "gpio";
bias-disable;
};
- reset {
+ reset-pins {
pins = "gpio105";
function = "gpio";
bias-disable;
};
};
+ nvme_reg_en: nvme-reg-en-state {
+ pins = "gpio135";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ pcie2a_default: pcie2a-default-state {
+ clkreq-n-pins {
+ pins = "gpio142";
+ function = "pcie2a_clkreq";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ perst-n-pins {
+ pins = "gpio143";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ wake-n-pins {
+ pins = "gpio145";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ pcie3a_default: pcie3a-default-state {
+ clkreq-n-pins {
+ pins = "gpio150";
+ function = "pcie3a_clkreq";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ perst-n-pins {
+ pins = "gpio151";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ wake-n-pins {
+ pins = "gpio148";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ pcie4_default: pcie4-default-state {
+ clkreq-n-pins {
+ pins = "gpio140";
+ function = "pcie4_clkreq";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ perst-n-pins {
+ pins = "gpio141";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ wake-n-pins {
+ pins = "gpio139";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
qup0_i2c4_default: qup0-i2c4-default-state {
pins = "gpio171", "gpio172";
function = "qup4";
@@ -384,7 +809,7 @@
};
tpad_default: tpad-default-state {
- int-n {
+ int-n-pins {
pins = "gpio182";
function = "gpio";
bias-disable;
@@ -392,13 +817,13 @@
};
ts0_default: ts0-default-state {
- int-n {
+ int-n-pins {
pins = "gpio175";
function = "gpio";
bias-disable;
};
- reset-n {
+ reset-n-pins {
pins = "gpio99";
function = "gpio";
output-high;
diff --git a/arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi b/arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi
index 24836b6b9bbc..f2c0b71b5d8e 100644
--- a/arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc8280xp-pmics.dtsi
@@ -7,6 +7,50 @@
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/spmi/spmi.h>
+/ {
+ thermal-zones {
+ pm8280_1_thermal: pm8280-1-thermal {
+ polling-delay-passive = <100>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8280_1_temp_alarm>;
+
+ trips {
+ trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+
+ pm8280_2_thermal: pm8280-2-thermal {
+ polling-delay-passive = <100>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm8280_2_temp_alarm>;
+
+ trips {
+ trip0 {
+ temperature = <95000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+
+ trip1 {
+ temperature = <115000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+ };
+ };
+};
+
&spmi_bus {
pmk8280: pmic@0 {
compatible = "qcom,pmk8350", "qcom,spmi-pmic";
@@ -24,6 +68,32 @@
linux,code = <KEY_POWER>;
status = "disabled";
};
+
+ pmk8280_pon_resin: resin {
+ compatible = "qcom,pmk8350-resin";
+ interrupts = <0x0 0x13 0x6 IRQ_TYPE_EDGE_BOTH>;
+ status = "disabled";
+ };
+ };
+
+ pmk8280_vadc: adc@3100 {
+ compatible = "qcom,spmi-adc7";
+ reg = <0x3100>;
+ interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+ status = "disabled";
+ };
+
+ pmk8280_adc_tm: adc-tm@3400 {
+ compatible = "qcom,spmi-adc-tm5-gen2";
+ reg = <0x3400>;
+ interrupts = <0x0 0x34 0x0 IRQ_TYPE_EDGE_RISING>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #thermal-sensor-cells = <1>;
+ status = "disabled";
};
};
@@ -33,6 +103,13 @@
#address-cells = <1>;
#size-cells = <0>;
+ pm8280_1_temp_alarm: temp-alarm@a00 {
+ compatible = "qcom,spmi-temp-alarm";
+ reg = <0xa00>;
+ interrupts = <0x1 0xa 0x0 IRQ_TYPE_EDGE_BOTH>;
+ #thermal-sensor-cells = <0>;
+ };
+
pmc8280_1_gpios: gpio@8800 {
compatible = "qcom,pm8350-gpio", "qcom,spmi-gpio";
reg = <0x8800>;
@@ -78,6 +155,13 @@
#address-cells = <1>;
#size-cells = <0>;
+ pm8280_2_temp_alarm: temp-alarm@a00 {
+ compatible = "qcom,spmi-temp-alarm";
+ reg = <0xa00>;
+ interrupts = <0x2 0xa 0x0 IRQ_TYPE_EDGE_BOTH>;
+ #thermal-sensor-cells = <0>;
+ };
+
pmc8280_2_gpios: gpio@8800 {
compatible = "qcom,pm8350-gpio", "qcom,spmi-gpio";
reg = <0x8800>;
diff --git a/arch/arm64/boot/dts/qcom/sc8280xp.dtsi b/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
index 212d63d5cbf2..109c9d2b684d 100644
--- a/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc8280xp.dtsi
@@ -6,6 +6,7 @@
#include <dt-bindings/clock/qcom,gcc-sc8280xp.h>
#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interconnect/qcom,osm-l3.h>
#include <dt-bindings/interconnect/qcom,sc8280xp.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/mailbox/qcom-ipcc.h>
@@ -38,66 +39,87 @@
opp-300000000 {
opp-hz = /bits/ 64 <300000000>;
+ opp-peak-kBps = <(300000 * 32)>;
};
opp-403200000 {
opp-hz = /bits/ 64 <403200000>;
+ opp-peak-kBps = <(384000 * 32)>;
};
opp-499200000 {
opp-hz = /bits/ 64 <499200000>;
+ opp-peak-kBps = <(480000 * 32)>;
};
opp-595200000 {
opp-hz = /bits/ 64 <595200000>;
+ opp-peak-kBps = <(576000 * 32)>;
};
opp-691200000 {
opp-hz = /bits/ 64 <691200000>;
+ opp-peak-kBps = <(672000 * 32)>;
};
opp-806400000 {
opp-hz = /bits/ 64 <806400000>;
+ opp-peak-kBps = <(768000 * 32)>;
};
opp-902400000 {
opp-hz = /bits/ 64 <902400000>;
+ opp-peak-kBps = <(864000 * 32)>;
};
opp-1017600000 {
opp-hz = /bits/ 64 <1017600000>;
+ opp-peak-kBps = <(960000 * 32)>;
};
opp-1113600000 {
opp-hz = /bits/ 64 <1113600000>;
+ opp-peak-kBps = <(1075200 * 32)>;
};
opp-1209600000 {
opp-hz = /bits/ 64 <1209600000>;
+ opp-peak-kBps = <(1171200 * 32)>;
};
opp-1324800000 {
opp-hz = /bits/ 64 <1324800000>;
+ opp-peak-kBps = <(1267200 * 32)>;
};
opp-1440000000 {
opp-hz = /bits/ 64 <1440000000>;
+ opp-peak-kBps = <(1363200 * 32)>;
};
opp-1555200000 {
opp-hz = /bits/ 64 <1555200000>;
+ opp-peak-kBps = <(1536000 * 32)>;
};
opp-1670400000 {
opp-hz = /bits/ 64 <1670400000>;
+ opp-peak-kBps = <(1612800 * 32)>;
};
opp-1785600000 {
opp-hz = /bits/ 64 <1785600000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
opp-1881600000 {
opp-hz = /bits/ 64 <1881600000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
opp-1996800000 {
opp-hz = /bits/ 64 <1996800000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
opp-2112000000 {
opp-hz = /bits/ 64 <2112000000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
opp-2227200000 {
opp-hz = /bits/ 64 <2227200000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
opp-2342400000 {
opp-hz = /bits/ 64 <2342400000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
opp-2438400000 {
opp-hz = /bits/ 64 <2438400000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
};
@@ -107,66 +129,87 @@
opp-825600000 {
opp-hz = /bits/ 64 <825600000>;
+ opp-peak-kBps = <(768000 * 32)>;
};
opp-940800000 {
opp-hz = /bits/ 64 <940800000>;
+ opp-peak-kBps = <(864000 * 32)>;
};
opp-1056000000 {
opp-hz = /bits/ 64 <1056000000>;
+ opp-peak-kBps = <(960000 * 32)>;
};
opp-1171200000 {
opp-hz = /bits/ 64 <1171200000>;
+ opp-peak-kBps = <(1171200 * 32)>;
};
opp-1286400000 {
opp-hz = /bits/ 64 <1286400000>;
+ opp-peak-kBps = <(1267200 * 32)>;
};
opp-1401600000 {
opp-hz = /bits/ 64 <1401600000>;
+ opp-peak-kBps = <(1363200 * 32)>;
};
opp-1516800000 {
opp-hz = /bits/ 64 <1516800000>;
+ opp-peak-kBps = <(1459200 * 32)>;
};
opp-1632000000 {
opp-hz = /bits/ 64 <1632000000>;
+ opp-peak-kBps = <(1612800 * 32)>;
};
opp-1747200000 {
opp-hz = /bits/ 64 <1747200000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
opp-1862400000 {
opp-hz = /bits/ 64 <1862400000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
opp-1977600000 {
opp-hz = /bits/ 64 <1977600000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
opp-2073600000 {
opp-hz = /bits/ 64 <2073600000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
opp-2169600000 {
opp-hz = /bits/ 64 <2169600000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
opp-2284800000 {
opp-hz = /bits/ 64 <2284800000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
opp-2400000000 {
opp-hz = /bits/ 64 <2400000000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
opp-2496000000 {
opp-hz = /bits/ 64 <2496000000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
opp-2592000000 {
opp-hz = /bits/ 64 <2592000000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
opp-2688000000 {
opp-hz = /bits/ 64 <2688000000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
opp-2803200000 {
opp-hz = /bits/ 64 <2803200000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
opp-2899200000 {
opp-hz = /bits/ 64 <2899200000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
opp-2995200000 {
opp-hz = /bits/ 64 <2995200000>;
+ opp-peak-kBps = <(1689600 * 32)>;
};
};
@@ -185,6 +228,7 @@
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
+ interconnects = <&epss_l3 MASTER_EPSS_L3_APPS &epss_l3 SLAVE_EPSS_L3_SHARED>;
#cooling-cells = <2>;
L2_0: l2-cache {
compatible = "cache";
@@ -206,6 +250,7 @@
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
+ interconnects = <&epss_l3 MASTER_EPSS_L3_APPS &epss_l3 SLAVE_EPSS_L3_SHARED>;
#cooling-cells = <2>;
L2_100: l2-cache {
compatible = "cache";
@@ -224,6 +269,7 @@
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
+ interconnects = <&epss_l3 MASTER_EPSS_L3_APPS &epss_l3 SLAVE_EPSS_L3_SHARED>;
#cooling-cells = <2>;
L2_200: l2-cache {
compatible = "cache";
@@ -242,6 +288,7 @@
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
operating-points-v2 = <&cpu0_opp_table>;
+ interconnects = <&epss_l3 MASTER_EPSS_L3_APPS &epss_l3 SLAVE_EPSS_L3_SHARED>;
#cooling-cells = <2>;
L2_300: l2-cache {
compatible = "cache";
@@ -260,6 +307,7 @@
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
operating-points-v2 = <&cpu4_opp_table>;
+ interconnects = <&epss_l3 MASTER_EPSS_L3_APPS &epss_l3 SLAVE_EPSS_L3_SHARED>;
#cooling-cells = <2>;
L2_400: l2-cache {
compatible = "cache";
@@ -278,6 +326,7 @@
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
operating-points-v2 = <&cpu4_opp_table>;
+ interconnects = <&epss_l3 MASTER_EPSS_L3_APPS &epss_l3 SLAVE_EPSS_L3_SHARED>;
#cooling-cells = <2>;
L2_500: l2-cache {
compatible = "cache";
@@ -296,6 +345,7 @@
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
operating-points-v2 = <&cpu4_opp_table>;
+ interconnects = <&epss_l3 MASTER_EPSS_L3_APPS &epss_l3 SLAVE_EPSS_L3_SHARED>;
#cooling-cells = <2>;
L2_600: l2-cache {
compatible = "cache";
@@ -314,6 +364,7 @@
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
operating-points-v2 = <&cpu4_opp_table>;
+ interconnects = <&epss_l3 MASTER_EPSS_L3_APPS &epss_l3 SLAVE_EPSS_L3_SHARED>;
#cooling-cells = <2>;
L2_700: l2-cache {
compatible = "cache";
@@ -729,11 +780,11 @@
<0>,
<0>,
<0>,
- <0>,
- <0>,
- <0>,
- <0>,
- <0>,
+ <&pcie2a_phy>,
+ <&pcie2b_phy>,
+ <&pcie3a_phy>,
+ <&pcie3b_phy>,
+ <&pcie4_phy>,
<0>,
<0>;
power-domains = <&rpmhpd SC8280XP_CX>;
@@ -839,12 +890,505 @@
status = "disabled";
};
+ pcie4: pcie@1c00000 {
+ device_type = "pci";
+ compatible = "qcom,pcie-sc8280xp";
+ reg = <0x0 0x01c00000 0x0 0x3000>,
+ <0x0 0x30000000 0x0 0xf1d>,
+ <0x0 0x30000f20 0x0 0xa8>,
+ <0x0 0x30001000 0x0 0x1000>,
+ <0x0 0x30100000 0x0 0x100000>;
+ reg-names = "parf", "dbi", "elbi", "atu", "config";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges = <0x01000000 0x0 0x30200000 0x0 0x30200000 0x0 0x100000>,
+ <0x02000000 0x0 0x30300000 0x0 0x30300000 0x0 0x1d00000>;
+ bus-range = <0x00 0xff>;
+
+ dma-coherent;
+
+ linux,pci-domain = <6>;
+ num-lanes = <1>;
+
+ interrupts = <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi0", "msi1", "msi2", "msi3";
+
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc 0 0 GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &intc 0 0 GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &intc 0 0 GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &intc 0 0 GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&gcc GCC_PCIE_4_AUX_CLK>,
+ <&gcc GCC_PCIE_4_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_4_MSTR_AXI_CLK>,
+ <&gcc GCC_PCIE_4_SLV_AXI_CLK>,
+ <&gcc GCC_PCIE_4_SLV_Q2A_AXI_CLK>,
+ <&gcc GCC_DDRSS_PCIE_SF_TBU_CLK>,
+ <&gcc GCC_AGGRE_NOC_PCIE_4_AXI_CLK>,
+ <&gcc GCC_AGGRE_NOC_PCIE_SOUTH_SF_AXI_CLK>,
+ <&gcc GCC_CNOC_PCIE4_QX_CLK>;
+ clock-names = "aux",
+ "cfg",
+ "bus_master",
+ "bus_slave",
+ "slave_q2a",
+ "ddrss_sf_tbu",
+ "noc_aggr_4",
+ "noc_aggr_south_sf",
+ "cnoc_qx";
+
+ assigned-clocks = <&gcc GCC_PCIE_4_AUX_CLK>;
+ assigned-clock-rates = <19200000>;
+
+ interconnects = <&aggre2_noc MASTER_PCIE_4 0 &mc_virt SLAVE_EBI1 0>,
+ <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_PCIE_4 0>;
+ interconnect-names = "pcie-mem", "cpu-pcie";
+
+ resets = <&gcc GCC_PCIE_4_BCR>;
+ reset-names = "pci";
+
+ power-domains = <&gcc PCIE_4_GDSC>;
+
+ phys = <&pcie4_phy>;
+ phy-names = "pciephy";
+
+ status = "disabled";
+ };
+
+ pcie4_phy: phy@1c06000 {
+ compatible = "qcom,sc8280xp-qmp-gen3x1-pcie-phy";
+ reg = <0x0 0x01c06000 0x0 0x2000>;
+
+ clocks = <&gcc GCC_PCIE_4_AUX_CLK>,
+ <&gcc GCC_PCIE_4_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_4_CLKREF_CLK>,
+ <&gcc GCC_PCIE4_PHY_RCHNG_CLK>,
+ <&gcc GCC_PCIE_4_PIPE_CLK>,
+ <&gcc GCC_PCIE_4_PIPEDIV2_CLK>;
+ clock-names = "aux", "cfg_ahb", "ref", "rchng",
+ "pipe", "pipediv2";
+
+ assigned-clocks = <&gcc GCC_PCIE4_PHY_RCHNG_CLK>;
+ assigned-clock-rates = <100000000>;
+
+ power-domains = <&gcc PCIE_4_GDSC>;
+
+ resets = <&gcc GCC_PCIE_4_PHY_BCR>;
+ reset-names = "phy";
+
+ #clock-cells = <0>;
+ clock-output-names = "pcie_4_pipe_clk";
+
+ #phy-cells = <0>;
+
+ status = "disabled";
+ };
+
+ pcie3b: pcie@1c08000 {
+ device_type = "pci";
+ compatible = "qcom,pcie-sc8280xp";
+ reg = <0x0 0x01c08000 0x0 0x3000>,
+ <0x0 0x32000000 0x0 0xf1d>,
+ <0x0 0x32000f20 0x0 0xa8>,
+ <0x0 0x32001000 0x0 0x1000>,
+ <0x0 0x32100000 0x0 0x100000>;
+ reg-names = "parf", "dbi", "elbi", "atu", "config";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges = <0x01000000 0x0 0x32200000 0x0 0x32200000 0x0 0x100000>,
+ <0x02000000 0x0 0x32300000 0x0 0x32300000 0x0 0x1d00000>;
+ bus-range = <0x00 0xff>;
+
+ dma-coherent;
+
+ linux,pci-domain = <5>;
+ num-lanes = <2>;
+
+ interrupts = <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi0", "msi1", "msi2", "msi3";
+
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc 0 0 GIC_SPI 526 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &intc 0 0 GIC_SPI 527 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &intc 0 0 GIC_SPI 528 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &intc 0 0 GIC_SPI 529 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&gcc GCC_PCIE_3B_AUX_CLK>,
+ <&gcc GCC_PCIE_3B_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_3B_MSTR_AXI_CLK>,
+ <&gcc GCC_PCIE_3B_SLV_AXI_CLK>,
+ <&gcc GCC_PCIE_3B_SLV_Q2A_AXI_CLK>,
+ <&gcc GCC_DDRSS_PCIE_SF_TBU_CLK>,
+ <&gcc GCC_AGGRE_NOC_PCIE_4_AXI_CLK>,
+ <&gcc GCC_AGGRE_NOC_PCIE_SOUTH_SF_AXI_CLK>;
+ clock-names = "aux",
+ "cfg",
+ "bus_master",
+ "bus_slave",
+ "slave_q2a",
+ "ddrss_sf_tbu",
+ "noc_aggr_4",
+ "noc_aggr_south_sf";
+
+ assigned-clocks = <&gcc GCC_PCIE_3B_AUX_CLK>;
+ assigned-clock-rates = <19200000>;
+
+ interconnects = <&aggre2_noc MASTER_PCIE_3B 0 &mc_virt SLAVE_EBI1 0>,
+ <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_PCIE_3B 0>;
+ interconnect-names = "pcie-mem", "cpu-pcie";
+
+ resets = <&gcc GCC_PCIE_3B_BCR>;
+ reset-names = "pci";
+
+ power-domains = <&gcc PCIE_3B_GDSC>;
+
+ phys = <&pcie3b_phy>;
+ phy-names = "pciephy";
+
+ status = "disabled";
+ };
+
+ pcie3b_phy: phy@1c0e000 {
+ compatible = "qcom,sc8280xp-qmp-gen3x2-pcie-phy";
+ reg = <0x0 0x01c0e000 0x0 0x2000>;
+
+ clocks = <&gcc GCC_PCIE_3B_AUX_CLK>,
+ <&gcc GCC_PCIE_3B_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_3A3B_CLKREF_CLK>,
+ <&gcc GCC_PCIE3B_PHY_RCHNG_CLK>,
+ <&gcc GCC_PCIE_3B_PIPE_CLK>,
+ <&gcc GCC_PCIE_3B_PIPEDIV2_CLK>;
+ clock-names = "aux", "cfg_ahb", "ref", "rchng",
+ "pipe", "pipediv2";
+
+ assigned-clocks = <&gcc GCC_PCIE3B_PHY_RCHNG_CLK>;
+ assigned-clock-rates = <100000000>;
+
+ power-domains = <&gcc PCIE_3B_GDSC>;
+
+ resets = <&gcc GCC_PCIE_3B_PHY_BCR>;
+ reset-names = "phy";
+
+ #clock-cells = <0>;
+ clock-output-names = "pcie_3b_pipe_clk";
+
+ #phy-cells = <0>;
+
+ status = "disabled";
+ };
+
+ pcie3a: pcie@1c10000 {
+ device_type = "pci";
+ compatible = "qcom,pcie-sc8280xp";
+ reg = <0x0 0x01c10000 0x0 0x3000>,
+ <0x0 0x34000000 0x0 0xf1d>,
+ <0x0 0x34000f20 0x0 0xa8>,
+ <0x0 0x34001000 0x0 0x1000>,
+ <0x0 0x34100000 0x0 0x100000>;
+ reg-names = "parf", "dbi", "elbi", "atu", "config";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges = <0x01000000 0x0 0x34200000 0x0 0x34200000 0x0 0x100000>,
+ <0x02000000 0x0 0x34300000 0x0 0x34300000 0x0 0x1d00000>;
+ bus-range = <0x00 0xff>;
+
+ dma-coherent;
+
+ linux,pci-domain = <4>;
+ num-lanes = <4>;
+
+ interrupts = <GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 313 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 314 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi0", "msi1", "msi2", "msi3";
+
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc 0 0 GIC_SPI 499 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &intc 0 0 GIC_SPI 542 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &intc 0 0 GIC_SPI 543 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &intc 0 0 GIC_SPI 544 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&gcc GCC_PCIE_3A_AUX_CLK>,
+ <&gcc GCC_PCIE_3A_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_3A_MSTR_AXI_CLK>,
+ <&gcc GCC_PCIE_3A_SLV_AXI_CLK>,
+ <&gcc GCC_PCIE_3A_SLV_Q2A_AXI_CLK>,
+ <&gcc GCC_DDRSS_PCIE_SF_TBU_CLK>,
+ <&gcc GCC_AGGRE_NOC_PCIE_4_AXI_CLK>,
+ <&gcc GCC_AGGRE_NOC_PCIE_SOUTH_SF_AXI_CLK>;
+ clock-names = "aux",
+ "cfg",
+ "bus_master",
+ "bus_slave",
+ "slave_q2a",
+ "ddrss_sf_tbu",
+ "noc_aggr_4",
+ "noc_aggr_south_sf";
+
+ assigned-clocks = <&gcc GCC_PCIE_3A_AUX_CLK>;
+ assigned-clock-rates = <19200000>;
+
+ interconnects = <&aggre2_noc MASTER_PCIE_3A 0 &mc_virt SLAVE_EBI1 0>,
+ <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_PCIE_3A 0>;
+ interconnect-names = "pcie-mem", "cpu-pcie";
+
+ resets = <&gcc GCC_PCIE_3A_BCR>;
+ reset-names = "pci";
+
+ power-domains = <&gcc PCIE_3A_GDSC>;
+
+ phys = <&pcie3a_phy>;
+ phy-names = "pciephy";
+
+ status = "disabled";
+ };
+
+ pcie3a_phy: phy@1c14000 {
+ compatible = "qcom,sc8280xp-qmp-gen3x4-pcie-phy";
+ reg = <0x0 0x01c14000 0x0 0x2000>,
+ <0x0 0x01c16000 0x0 0x2000>;
+
+ clocks = <&gcc GCC_PCIE_3A_AUX_CLK>,
+ <&gcc GCC_PCIE_3A_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_3A3B_CLKREF_CLK>,
+ <&gcc GCC_PCIE3A_PHY_RCHNG_CLK>,
+ <&gcc GCC_PCIE_3A_PIPE_CLK>,
+ <&gcc GCC_PCIE_3A_PIPEDIV2_CLK>;
+ clock-names = "aux", "cfg_ahb", "ref", "rchng",
+ "pipe", "pipediv2";
+
+ assigned-clocks = <&gcc GCC_PCIE3A_PHY_RCHNG_CLK>;
+ assigned-clock-rates = <100000000>;
+
+ power-domains = <&gcc PCIE_3A_GDSC>;
+
+ resets = <&gcc GCC_PCIE_3A_PHY_BCR>;
+ reset-names = "phy";
+
+ qcom,4ln-config-sel = <&tcsr 0xa044 1>;
+
+ #clock-cells = <0>;
+ clock-output-names = "pcie_3a_pipe_clk";
+
+ #phy-cells = <0>;
+
+ status = "disabled";
+ };
+
+ pcie2b: pcie@1c18000 {
+ device_type = "pci";
+ compatible = "qcom,pcie-sc8280xp";
+ reg = <0x0 0x01c18000 0x0 0x3000>,
+ <0x0 0x38000000 0x0 0xf1d>,
+ <0x0 0x38000f20 0x0 0xa8>,
+ <0x0 0x38001000 0x0 0x1000>,
+ <0x0 0x38100000 0x0 0x100000>;
+ reg-names = "parf", "dbi", "elbi", "atu", "config";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges = <0x01000000 0x0 0x38200000 0x0 0x38200000 0x0 0x100000>,
+ <0x02000000 0x0 0x38300000 0x0 0x38300000 0x0 0x1d00000>;
+ bus-range = <0x00 0xff>;
+
+ dma-coherent;
+
+ linux,pci-domain = <3>;
+ num-lanes = <2>;
+
+ interrupts = <GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 309 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi0", "msi1", "msi2", "msi3";
+
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc 0 0 GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &intc 0 0 GIC_SPI 434 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &intc 0 0 GIC_SPI 435 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &intc 0 0 GIC_SPI 438 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&gcc GCC_PCIE_2B_AUX_CLK>,
+ <&gcc GCC_PCIE_2B_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_2B_MSTR_AXI_CLK>,
+ <&gcc GCC_PCIE_2B_SLV_AXI_CLK>,
+ <&gcc GCC_PCIE_2B_SLV_Q2A_AXI_CLK>,
+ <&gcc GCC_DDRSS_PCIE_SF_TBU_CLK>,
+ <&gcc GCC_AGGRE_NOC_PCIE_4_AXI_CLK>,
+ <&gcc GCC_AGGRE_NOC_PCIE_SOUTH_SF_AXI_CLK>;
+ clock-names = "aux",
+ "cfg",
+ "bus_master",
+ "bus_slave",
+ "slave_q2a",
+ "ddrss_sf_tbu",
+ "noc_aggr_4",
+ "noc_aggr_south_sf";
+
+ assigned-clocks = <&gcc GCC_PCIE_2B_AUX_CLK>;
+ assigned-clock-rates = <19200000>;
+
+ interconnects = <&aggre2_noc MASTER_PCIE_2B 0 &mc_virt SLAVE_EBI1 0>,
+ <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_PCIE_2B 0>;
+ interconnect-names = "pcie-mem", "cpu-pcie";
+
+ resets = <&gcc GCC_PCIE_2B_BCR>;
+ reset-names = "pci";
+
+ power-domains = <&gcc PCIE_2B_GDSC>;
+
+ phys = <&pcie2b_phy>;
+ phy-names = "pciephy";
+
+ status = "disabled";
+ };
+
+ pcie2b_phy: phy@1c1e000 {
+ compatible = "qcom,sc8280xp-qmp-gen3x2-pcie-phy";
+ reg = <0x0 0x01c1e000 0x0 0x2000>;
+
+ clocks = <&gcc GCC_PCIE_2B_AUX_CLK>,
+ <&gcc GCC_PCIE_2B_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_2A2B_CLKREF_CLK>,
+ <&gcc GCC_PCIE2B_PHY_RCHNG_CLK>,
+ <&gcc GCC_PCIE_2B_PIPE_CLK>,
+ <&gcc GCC_PCIE_2B_PIPEDIV2_CLK>;
+ clock-names = "aux", "cfg_ahb", "ref", "rchng",
+ "pipe", "pipediv2";
+
+ assigned-clocks = <&gcc GCC_PCIE2B_PHY_RCHNG_CLK>;
+ assigned-clock-rates = <100000000>;
+
+ power-domains = <&gcc PCIE_2B_GDSC>;
+
+ resets = <&gcc GCC_PCIE_2B_PHY_BCR>;
+ reset-names = "phy";
+
+ #clock-cells = <0>;
+ clock-output-names = "pcie_2b_pipe_clk";
+
+ #phy-cells = <0>;
+
+ status = "disabled";
+ };
+
+ pcie2a: pcie@1c20000 {
+ device_type = "pci";
+ compatible = "qcom,pcie-sc8280xp";
+ reg = <0x0 0x01c20000 0x0 0x3000>,
+ <0x0 0x3c000000 0x0 0xf1d>,
+ <0x0 0x3c000f20 0x0 0xa8>,
+ <0x0 0x3c001000 0x0 0x1000>,
+ <0x0 0x3c100000 0x0 0x100000>;
+ reg-names = "parf", "dbi", "elbi", "atu", "config";
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges = <0x01000000 0x0 0x3c200000 0x0 0x3c200000 0x0 0x100000>,
+ <0x02000000 0x0 0x3c300000 0x0 0x3c300000 0x0 0x1d00000>;
+ bus-range = <0x00 0xff>;
+
+ dma-coherent;
+
+ linux,pci-domain = <2>;
+ num-lanes = <4>;
+
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 523 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 524 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 525 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi0", "msi1", "msi2", "msi3";
+
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc 0 0 GIC_SPI 530 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &intc 0 0 GIC_SPI 531 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &intc 0 0 GIC_SPI 532 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &intc 0 0 GIC_SPI 533 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&gcc GCC_PCIE_2A_AUX_CLK>,
+ <&gcc GCC_PCIE_2A_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_2A_MSTR_AXI_CLK>,
+ <&gcc GCC_PCIE_2A_SLV_AXI_CLK>,
+ <&gcc GCC_PCIE_2A_SLV_Q2A_AXI_CLK>,
+ <&gcc GCC_DDRSS_PCIE_SF_TBU_CLK>,
+ <&gcc GCC_AGGRE_NOC_PCIE_4_AXI_CLK>,
+ <&gcc GCC_AGGRE_NOC_PCIE_SOUTH_SF_AXI_CLK>;
+ clock-names = "aux",
+ "cfg",
+ "bus_master",
+ "bus_slave",
+ "slave_q2a",
+ "ddrss_sf_tbu",
+ "noc_aggr_4",
+ "noc_aggr_south_sf";
+
+ assigned-clocks = <&gcc GCC_PCIE_2A_AUX_CLK>;
+ assigned-clock-rates = <19200000>;
+
+ interconnects = <&aggre2_noc MASTER_PCIE_2A 0 &mc_virt SLAVE_EBI1 0>,
+ <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_PCIE_2A 0>;
+ interconnect-names = "pcie-mem", "cpu-pcie";
+
+ resets = <&gcc GCC_PCIE_2A_BCR>;
+ reset-names = "pci";
+
+ power-domains = <&gcc PCIE_2A_GDSC>;
+
+ phys = <&pcie2a_phy>;
+ phy-names = "pciephy";
+
+ status = "disabled";
+ };
+
+ pcie2a_phy: phy@1c24000 {
+ compatible = "qcom,sc8280xp-qmp-gen3x4-pcie-phy";
+ reg = <0x0 0x01c24000 0x0 0x2000>,
+ <0x0 0x01c26000 0x0 0x2000>;
+
+ clocks = <&gcc GCC_PCIE_2A_AUX_CLK>,
+ <&gcc GCC_PCIE_2A_CFG_AHB_CLK>,
+ <&gcc GCC_PCIE_2A2B_CLKREF_CLK>,
+ <&gcc GCC_PCIE2A_PHY_RCHNG_CLK>,
+ <&gcc GCC_PCIE_2A_PIPE_CLK>,
+ <&gcc GCC_PCIE_2A_PIPEDIV2_CLK>;
+ clock-names = "aux", "cfg_ahb", "ref", "rchng",
+ "pipe", "pipediv2";
+
+ assigned-clocks = <&gcc GCC_PCIE2A_PHY_RCHNG_CLK>;
+ assigned-clock-rates = <100000000>;
+
+ power-domains = <&gcc PCIE_2A_GDSC>;
+
+ resets = <&gcc GCC_PCIE_2A_PHY_BCR>;
+ reset-names = "phy";
+
+ qcom,4ln-config-sel = <&tcsr 0xa044 0>;
+
+ #clock-cells = <0>;
+ clock-output-names = "pcie_2a_pipe_clk";
+
+ #phy-cells = <0>;
+
+ status = "disabled";
+ };
+
ufs_mem_hc: ufs@1d84000 {
compatible = "qcom,sc8280xp-ufshc", "qcom,ufshc",
"jedec,ufs-2.0";
reg = <0 0x01d84000 0 0x3000>;
interrupts = <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>;
- phys = <&ufs_mem_phy_lanes>;
+ phys = <&ufs_mem_phy>;
phy-names = "ufsphy";
lanes-per-direction = <2>;
#reset-cells = <1>;
@@ -855,12 +1399,13 @@
required-opps = <&rpmhpd_opp_nom>;
iommus = <&apps_smmu 0xe0 0x0>;
+ dma-coherent;
clocks = <&gcc GCC_UFS_PHY_AXI_CLK>,
<&gcc GCC_AGGRE_UFS_PHY_AXI_CLK>,
<&gcc GCC_UFS_PHY_AHB_CLK>,
<&gcc GCC_UFS_PHY_UNIPRO_CORE_CLK>,
- <&rpmhcc RPMH_CXO_CLK>,
+ <&gcc GCC_UFS_REF_CLKREF_CLK>,
<&gcc GCC_UFS_PHY_TX_SYMBOL_0_CLK>,
<&gcc GCC_UFS_PHY_RX_SYMBOL_0_CLK>,
<&gcc GCC_UFS_PHY_RX_SYMBOL_1_CLK>;
@@ -885,27 +1430,20 @@
ufs_mem_phy: phy@1d87000 {
compatible = "qcom,sc8280xp-qmp-ufs-phy";
- reg = <0 0x01d87000 0 0x1c8>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
- clock-names = "ref",
- "ref_aux";
- clocks = <&gcc GCC_UFS_REF_CLKREF_CLK>,
+ reg = <0 0x01d87000 0 0x1000>;
+
+ clocks = <&gcc GCC_UFS_CARD_CLKREF_CLK>,
<&gcc GCC_UFS_PHY_PHY_AUX_CLK>;
+ clock-names = "ref", "ref_aux";
+
+ power-domains = <&gcc UFS_PHY_GDSC>;
resets = <&ufs_mem_hc 0>;
reset-names = "ufsphy";
- status = "disabled";
- ufs_mem_phy_lanes: phy@1d87400 {
- reg = <0 0x01d87400 0 0x108>,
- <0 0x01d87600 0 0x1e0>,
- <0 0x01d87c00 0 0x1dc>,
- <0 0x01d87800 0 0x108>,
- <0 0x01d87a00 0 0x1e0>;
- #phy-cells = <0>;
- };
+ #phy-cells = <0>;
+
+ status = "disabled";
};
ufs_card_hc: ufs@1da4000 {
@@ -913,7 +1451,7 @@
"jedec,ufs-2.0";
reg = <0 0x01da4000 0 0x3000>;
interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
- phys = <&ufs_card_phy_lanes>;
+ phys = <&ufs_card_phy>;
phy-names = "ufsphy";
lanes-per-direction = <2>;
#reset-cells = <1>;
@@ -923,12 +1461,13 @@
power-domains = <&gcc UFS_CARD_GDSC>;
iommus = <&apps_smmu 0x4a0 0x0>;
+ dma-coherent;
clocks = <&gcc GCC_UFS_CARD_AXI_CLK>,
<&gcc GCC_AGGRE_UFS_CARD_AXI_CLK>,
<&gcc GCC_UFS_CARD_AHB_CLK>,
<&gcc GCC_UFS_CARD_UNIPRO_CORE_CLK>,
- <&rpmhcc RPMH_CXO_CLK>,
+ <&gcc GCC_UFS_REF_CLKREF_CLK>,
<&gcc GCC_UFS_CARD_TX_SYMBOL_0_CLK>,
<&gcc GCC_UFS_CARD_RX_SYMBOL_0_CLK>,
<&gcc GCC_UFS_CARD_RX_SYMBOL_1_CLK>;
@@ -953,28 +1492,20 @@
ufs_card_phy: phy@1da7000 {
compatible = "qcom,sc8280xp-qmp-ufs-phy";
- reg = <0 0x01da7000 0 0x1c8>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
- clock-names = "ref",
- "ref_aux";
- clocks = <&gcc GCC_UFS_REF_CLKREF_CLK>,
+ reg = <0 0x01da7000 0 0x1000>;
+
+ clocks = <&gcc GCC_UFS_1_CARD_CLKREF_CLK>,
<&gcc GCC_UFS_CARD_PHY_AUX_CLK>;
+ clock-names = "ref", "ref_aux";
+
+ power-domains = <&gcc UFS_CARD_GDSC>;
resets = <&ufs_card_hc 0>;
reset-names = "ufsphy";
- status = "disabled";
+ #phy-cells = <0>;
- ufs_card_phy_lanes: phy@1da7400 {
- reg = <0 0x01da7400 0 0x108>,
- <0 0x01da7600 0 0x1e0>,
- <0 0x01da7c00 0 0x1dc>,
- <0 0x01da7800 0 0x108>,
- <0 0x01da7a00 0 0x1e0>;
- #phy-cells = <0>;
- };
+ status = "disabled";
};
tcsr_mutex: hwlock@1f40000 {
@@ -983,6 +1514,11 @@
#hwlock-cells = <1>;
};
+ tcsr: syscon@1fc0000 {
+ compatible = "qcom,sc8280xp-tcsr", "syscon";
+ reg = <0x0 0x01fc0000 0x0 0x30000>;
+ };
+
usb_0_hsphy: phy@88e5000 {
compatible = "qcom,sc8280xp-usb-hs-phy",
"qcom,usb-snps-hs-5nm-phy";
@@ -1048,70 +1584,52 @@
status = "disabled";
};
- usb_2_qmpphy0: phy-wrapper@88ef000 {
+ usb_2_qmpphy0: phy@88ef000 {
compatible = "qcom,sc8280xp-qmp-usb3-uni-phy";
- reg = <0 0x088ef000 0 0x1c8>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ reg = <0 0x088ef000 0 0x2000>;
clocks = <&gcc GCC_USB3_MP_PHY_AUX_CLK>,
- <&rpmhcc RPMH_CXO_CLK>,
<&gcc GCC_USB3_MP0_CLKREF_CLK>,
- <&gcc GCC_USB3_MP_PHY_COM_AUX_CLK>;
- clock-names = "aux", "ref_clk_src", "ref", "com_aux";
+ <&gcc GCC_USB3_MP_PHY_COM_AUX_CLK>,
+ <&gcc GCC_USB3_MP_PHY_PIPE_0_CLK>;
+ clock-names = "aux", "ref", "com_aux", "pipe";
resets = <&gcc GCC_USB3_UNIPHY_MP0_BCR>,
<&gcc GCC_USB3UNIPHY_PHY_MP0_BCR>;
- reset-names = "phy", "common";
+ reset-names = "phy", "phy_phy";
power-domains = <&gcc USB30_MP_GDSC>;
- status = "disabled";
+ #clock-cells = <0>;
+ clock-output-names = "usb2_phy0_pipe_clk";
- usb_2_ssphy0: phy@88efe00 {
- reg = <0 0x088efe00 0 0x160>,
- <0 0x088f0000 0 0x1ec>,
- <0 0x088ef200 0 0x1f0>;
- #phy-cells = <0>;
- #clock-cells = <0>;
- clocks = <&gcc GCC_USB3_MP_PHY_PIPE_0_CLK>;
- clock-names = "pipe0";
- clock-output-names = "usb2_phy0_pipe_clk";
- };
+ #phy-cells = <0>;
+
+ status = "disabled";
};
- usb_2_qmpphy1: phy-wrapper@88f1000 {
+ usb_2_qmpphy1: phy@88f1000 {
compatible = "qcom,sc8280xp-qmp-usb3-uni-phy";
- reg = <0 0x088f1000 0 0x1c8>;
- #address-cells = <2>;
- #size-cells = <2>;
- ranges;
+ reg = <0 0x088f1000 0 0x2000>;
clocks = <&gcc GCC_USB3_MP_PHY_AUX_CLK>,
- <&rpmhcc RPMH_CXO_CLK>,
<&gcc GCC_USB3_MP1_CLKREF_CLK>,
- <&gcc GCC_USB3_MP_PHY_COM_AUX_CLK>;
- clock-names = "aux", "ref_clk_src", "ref", "com_aux";
+ <&gcc GCC_USB3_MP_PHY_COM_AUX_CLK>,
+ <&gcc GCC_USB3_MP_PHY_PIPE_1_CLK>;
+ clock-names = "aux", "ref", "com_aux", "pipe";
resets = <&gcc GCC_USB3_UNIPHY_MP1_BCR>,
<&gcc GCC_USB3UNIPHY_PHY_MP1_BCR>;
- reset-names = "phy", "common";
+ reset-names = "phy", "phy_phy";
power-domains = <&gcc USB30_MP_GDSC>;
- status = "disabled";
+ #clock-cells = <0>;
+ clock-output-names = "usb2_phy1_pipe_clk";
- usb_2_ssphy1: phy@88f1e00 {
- reg = <0 0x088f1e00 0 0x160>,
- <0 0x088f2000 0 0x1ec>,
- <0 0x088f1200 0 0x1f0>;
- #phy-cells = <0>;
- #clock-cells = <0>;
- clocks = <&gcc GCC_USB3_MP_PHY_PIPE_1_CLK>;
- clock-names = "pipe0";
- clock-output-names = "usb2_phy1_pipe_clk";
- };
+ #phy-cells = <0>;
+
+ status = "disabled";
};
remoteproc_adsp: remoteproc@3000000 {
@@ -1245,6 +1763,97 @@
};
};
+ pmu@9091000 {
+ compatible = "qcom,sc8280xp-llcc-bwmon", "qcom,sc7280-llcc-bwmon";
+ reg = <0 0x9091000 0 0x1000>;
+
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+
+ interconnects = <&mc_virt MASTER_LLCC 3 &mc_virt SLAVE_EBI1 3>;
+
+ operating-points-v2 = <&llcc_bwmon_opp_table>;
+
+ llcc_bwmon_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-0 {
+ opp-peak-kBps = <762000>;
+ };
+ opp-1 {
+ opp-peak-kBps = <1720000>;
+ };
+ opp-2 {
+ opp-peak-kBps = <2086000>;
+ };
+ opp-3 {
+ opp-peak-kBps = <2597000>;
+ };
+ opp-4 {
+ opp-peak-kBps = <2929000>;
+ };
+ opp-5 {
+ opp-peak-kBps = <3879000>;
+ };
+ opp-6 {
+ opp-peak-kBps = <5161000>;
+ };
+ opp-7 {
+ opp-peak-kBps = <5931000>;
+ };
+ opp-8 {
+ opp-peak-kBps = <6515000>;
+ };
+ opp-9 {
+ opp-peak-kBps = <7980000>;
+ };
+ opp-10 {
+ opp-peak-kBps = <8136000>;
+ };
+ opp-11 {
+ opp-peak-kBps = <10437000>;
+ };
+ opp-12 {
+ opp-peak-kBps = <12191000>;
+ };
+ };
+ };
+
+ pmu@90b6400 {
+ compatible = "qcom,sc8280xp-cpu-bwmon", "qcom,msm8998-bwmon";
+ reg = <0 0x090b6400 0 0x600>;
+
+ interrupts = <GIC_SPI 581 IRQ_TYPE_LEVEL_HIGH>;
+
+ interconnects = <&gem_noc MASTER_APPSS_PROC 3 &gem_noc SLAVE_LLCC 3>;
+ operating-points-v2 = <&cpu_bwmon_opp_table>;
+
+ cpu_bwmon_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-0 {
+ opp-peak-kBps = <2288000>;
+ };
+ opp-1 {
+ opp-peak-kBps = <4577000>;
+ };
+ opp-2 {
+ opp-peak-kBps = <7110000>;
+ };
+ opp-3 {
+ opp-peak-kBps = <9155000>;
+ };
+ opp-4 {
+ opp-peak-kBps = <12298000>;
+ };
+ opp-5 {
+ opp-peak-kBps = <14236000>;
+ };
+ opp-6 {
+ opp-peak-kBps = <15258001>;
+ };
+ };
+ };
+
system-cache-controller@9200000 {
compatible = "qcom,sc8280xp-llcc";
reg = <0 0x09200000 0 0x58000>, <0 0x09600000 0 0x58000>;
@@ -1456,6 +2065,11 @@
#clock-cells = <0>;
};
+ sram@c3f0000 {
+ compatible = "qcom,rpmh-stats";
+ reg = <0 0x0c3f0000 0 0x400>;
+ };
+
spmi_bus: spmi@c440000 {
compatible = "qcom,spmi-pmic-arb";
reg = <0 0x0c440000 0 0x1100>,
@@ -1786,6 +2400,16 @@
};
};
+ epss_l3: interconnect@18590000 {
+ compatible = "qcom,sc8280xp-epss-l3", "qcom,epss-l3";
+ reg = <0 0x18590000 0 0x1000>;
+
+ clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GCC_GPLL0>;
+ clock-names = "xo", "alternate";
+
+ #interconnect-cells = <1>;
+ };
+
cpufreq_hw: cpufreq@18591000 {
compatible = "qcom,sc8280xp-cpufreq-epss", "qcom,cpufreq-epss";
reg = <0 0x18591000 0 0x1000>,
diff --git a/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts b/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts
index 28050bc5f081..7c81918eee66 100644
--- a/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts
+++ b/arch/arm64/boot/dts/qcom/sda660-inforce-ifc6560.dts
@@ -99,7 +99,7 @@
};
&adsp_pil {
- firmware-name = "qcom/ifc6560/adsp.mbn";
+ firmware-name = "qcom/sda660/adsp.mbn";
};
&blsp_i2c6 {
@@ -231,7 +231,7 @@
};
&rpm_requests {
- pm660-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pm660-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -313,7 +313,7 @@
};
};
- pm660l-regulators {
+ regulators-1 {
compatible = "qcom,rpm-pm660l-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -401,16 +401,18 @@
};
&sdc2_state_on {
- sd-cd {
+ sd-cd-pins {
pins = "gpio54";
+ function = "gpio";
bias-pull-up;
drive-strength = <2>;
};
};
&sdc2_state_off {
- sd-cd {
+ sd-cd-pins {
pins = "gpio54";
+ function = "gpio";
bias-disable;
drive-strength = <2>;
};
@@ -436,7 +438,7 @@
cd-gpios = <&tlmm 54 GPIO_ACTIVE_LOW>;
no-sdio;
- no-emmc;
+ no-mmc;
};
&tlmm {
diff --git a/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile.dtsi b/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile.dtsi
index 09c07800793a..3d2b08d551d0 100644
--- a/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm630-sony-xperia-nile.dtsi
@@ -155,7 +155,7 @@
};
&adsp_pil {
- firmware-name = "adsp.mdt";
+ firmware-name = "qcom/sdm630/Sony/nile/adsp.mdt";
};
&blsp_i2c1 {
@@ -260,7 +260,7 @@
};
&rpm_requests {
- pm660l-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pm660l-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -394,7 +394,7 @@
};
};
- pm660-regulators {
+ regulators-1 {
compatible = "qcom,rpm-pm660-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -577,16 +577,18 @@
};
&sdc2_state_on {
- sd-cd {
+ sd-cd-pins {
pins = "gpio54";
+ function = "gpio";
bias-pull-up;
drive-strength = <2>;
};
};
&sdc2_state_off {
- sd-cd {
+ sd-cd-pins {
pins = "gpio54";
+ function = "gpio";
bias-disable;
drive-strength = <2>;
};
@@ -615,33 +617,35 @@
&tlmm {
gpio-reserved-ranges = <8 4>;
- ts_int_active: ts-int-active {
+ ts_int_active: ts-int-active-state {
pins = "gpio45";
+ function = "gpio";
drive-strength = <8>;
bias-pull-up;
};
- ts_lcd_id_active: ts-lcd-id-active {
+ ts_lcd_id_active: ts-lcd-id-active-state {
pins = "gpio56";
+ function = "gpio";
drive-strength = <8>;
bias-disable;
};
- imx300_vana_default: imx300-vana-default {
+ imx300_vana_default: imx300-vana-default-state {
pins = "gpio50";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
- imx219_vana_default: imx219-vana-default {
+ imx219_vana_default: imx219-vana-default-state {
pins = "gpio51";
function = "gpio";
bias-disable;
drive-strength = <2>;
};
- cam_vdig_default: cam-vdig-default {
+ cam_vdig_default: cam-vdig-default-state {
pins = "gpio52";
function = "gpio";
bias-disable;
diff --git a/arch/arm64/boot/dts/qcom/sdm630.dtsi b/arch/arm64/boot/dts/qcom/sdm630.dtsi
index b51b85f583e5..13e6a4fbba27 100644
--- a/arch/arm64/boot/dts/qcom/sdm630.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm630.dtsi
@@ -721,33 +721,36 @@
interrupt-controller;
#interrupt-cells = <2>;
- blsp1_uart1_default: blsp1-uart1-default {
+ blsp1_uart1_default: blsp1-uart1-default-state {
pins = "gpio0", "gpio1", "gpio2", "gpio3";
+ function = "blsp_uart1";
drive-strength = <2>;
bias-disable;
};
- blsp1_uart1_sleep: blsp1-uart1-sleep {
+ blsp1_uart1_sleep: blsp1-uart1-sleep-state {
pins = "gpio0", "gpio1", "gpio2", "gpio3";
+ function = "gpio";
drive-strength = <2>;
bias-disable;
};
- blsp1_uart2_default: blsp1-uart2-default {
+ blsp1_uart2_default: blsp1-uart2-default-state {
pins = "gpio4", "gpio5";
+ function = "blsp_uart2";
drive-strength = <2>;
bias-disable;
};
- blsp2_uart1_default: blsp2-uart1-active {
- tx-rts {
+ blsp2_uart1_default: blsp2-uart1-active-state {
+ tx-rts-pins {
pins = "gpio16", "gpio19";
function = "blsp_uart5";
drive-strength = <2>;
bias-disable;
};
- rx {
+ rx-pins {
/*
* Avoid garbage data while BT module
* is powered off or not driving signal
@@ -758,7 +761,7 @@
bias-pull-up;
};
- cts {
+ cts-pins {
/* Match the pull of the BT module */
pins = "gpio18";
function = "blsp_uart5";
@@ -767,244 +770,232 @@
};
};
- blsp2_uart1_sleep: blsp2-uart1-sleep {
- tx {
+ blsp2_uart1_sleep: blsp2-uart1-sleep-state {
+ tx-pins {
pins = "gpio16";
function = "gpio";
drive-strength = <2>;
bias-pull-up;
};
- rx-cts-rts {
+ rx-cts-rts-pins {
pins = "gpio17", "gpio18", "gpio19";
function = "gpio";
drive-strength = <2>;
- bias-no-pull;
+ bias-disable;
};
};
- i2c1_default: i2c1-default {
+ i2c1_default: i2c1-default-state {
pins = "gpio2", "gpio3";
function = "blsp_i2c1";
drive-strength = <2>;
bias-disable;
};
- i2c1_sleep: i2c1-sleep {
+ i2c1_sleep: i2c1-sleep-state {
pins = "gpio2", "gpio3";
function = "blsp_i2c1";
drive-strength = <2>;
bias-pull-up;
};
- i2c2_default: i2c2-default {
+ i2c2_default: i2c2-default-state {
pins = "gpio6", "gpio7";
function = "blsp_i2c2";
drive-strength = <2>;
bias-disable;
};
- i2c2_sleep: i2c2-sleep {
+ i2c2_sleep: i2c2-sleep-state {
pins = "gpio6", "gpio7";
function = "blsp_i2c2";
drive-strength = <2>;
bias-pull-up;
};
- i2c3_default: i2c3-default {
+ i2c3_default: i2c3-default-state {
pins = "gpio10", "gpio11";
function = "blsp_i2c3";
drive-strength = <2>;
bias-disable;
};
- i2c3_sleep: i2c3-sleep {
+ i2c3_sleep: i2c3-sleep-state {
pins = "gpio10", "gpio11";
function = "blsp_i2c3";
drive-strength = <2>;
bias-pull-up;
};
- i2c4_default: i2c4-default {
+ i2c4_default: i2c4-default-state {
pins = "gpio14", "gpio15";
function = "blsp_i2c4";
drive-strength = <2>;
bias-disable;
};
- i2c4_sleep: i2c4-sleep {
+ i2c4_sleep: i2c4-sleep-state {
pins = "gpio14", "gpio15";
function = "blsp_i2c4";
drive-strength = <2>;
bias-pull-up;
};
- i2c5_default: i2c5-default {
+ i2c5_default: i2c5-default-state {
pins = "gpio18", "gpio19";
function = "blsp_i2c5";
drive-strength = <2>;
bias-disable;
};
- i2c5_sleep: i2c5-sleep {
+ i2c5_sleep: i2c5-sleep-state {
pins = "gpio18", "gpio19";
function = "blsp_i2c5";
drive-strength = <2>;
bias-pull-up;
};
- i2c6_default: i2c6-default {
+ i2c6_default: i2c6-default-state {
pins = "gpio22", "gpio23";
function = "blsp_i2c6";
drive-strength = <2>;
bias-disable;
};
- i2c6_sleep: i2c6-sleep {
+ i2c6_sleep: i2c6-sleep-state {
pins = "gpio22", "gpio23";
function = "blsp_i2c6";
drive-strength = <2>;
bias-pull-up;
};
- i2c7_default: i2c7-default {
+ i2c7_default: i2c7-default-state {
pins = "gpio26", "gpio27";
function = "blsp_i2c7";
drive-strength = <2>;
bias-disable;
};
- i2c7_sleep: i2c7-sleep {
+ i2c7_sleep: i2c7-sleep-state {
pins = "gpio26", "gpio27";
function = "blsp_i2c7";
drive-strength = <2>;
bias-pull-up;
};
- i2c8_default: i2c8-default {
+ i2c8_default: i2c8-default-state {
pins = "gpio30", "gpio31";
- function = "blsp_i2c8";
+ function = "blsp_i2c8_a";
drive-strength = <2>;
bias-disable;
};
- i2c8_sleep: i2c8-sleep {
+ i2c8_sleep: i2c8-sleep-state {
pins = "gpio30", "gpio31";
- function = "blsp_i2c8";
+ function = "blsp_i2c8_a";
drive-strength = <2>;
bias-pull-up;
};
- cci0_default: cci0_default {
- pinmux {
- pins = "gpio36","gpio37";
- function = "cci_i2c";
- };
-
- pinconf {
- pins = "gpio36","gpio37";
- bias-pull-up;
- drive-strength = <2>;
- };
+ cci0_default: cci0-default-state {
+ pins = "gpio36","gpio37";
+ function = "cci_i2c";
+ bias-pull-up;
+ drive-strength = <2>;
};
- cci1_default: cci1_default {
- pinmux {
- pins = "gpio38","gpio39";
- function = "cci_i2c";
- };
-
- pinconf {
- pins = "gpio38","gpio39";
- bias-pull-up;
- drive-strength = <2>;
- };
+ cci1_default: cci1-default-state {
+ pins = "gpio38","gpio39";
+ function = "cci_i2c";
+ bias-pull-up;
+ drive-strength = <2>;
};
- sdc1_state_on: sdc1-on {
- clk {
+ sdc1_state_on: sdc1-on-state {
+ clk-pins {
pins = "sdc1_clk";
bias-disable;
drive-strength = <16>;
};
- cmd {
+ cmd-pins {
pins = "sdc1_cmd";
bias-pull-up;
drive-strength = <10>;
};
- data {
+ data-pins {
pins = "sdc1_data";
bias-pull-up;
drive-strength = <10>;
};
- rclk {
+ rclk-pins {
pins = "sdc1_rclk";
bias-pull-down;
};
};
- sdc1_state_off: sdc1-off {
- clk {
+ sdc1_state_off: sdc1-off-state {
+ clk-pins {
pins = "sdc1_clk";
bias-disable;
drive-strength = <2>;
};
- cmd {
+ cmd-pins {
pins = "sdc1_cmd";
bias-pull-up;
drive-strength = <2>;
};
- data {
+ data-pins {
pins = "sdc1_data";
bias-pull-up;
drive-strength = <2>;
};
- rclk {
+ rclk-pins {
pins = "sdc1_rclk";
bias-pull-down;
};
};
- sdc2_state_on: sdc2-on {
- clk {
+ sdc2_state_on: sdc2-on-state {
+ clk-pins {
pins = "sdc2_clk";
bias-disable;
drive-strength = <16>;
};
- cmd {
+ cmd-pins {
pins = "sdc2_cmd";
bias-pull-up;
drive-strength = <10>;
};
- data {
+ data-pins {
pins = "sdc2_data";
bias-pull-up;
drive-strength = <10>;
};
};
- sdc2_state_off: sdc2-off {
- clk {
+ sdc2_state_off: sdc2-off-state {
+ clk-pins {
pins = "sdc2_clk";
bias-disable;
drive-strength = <2>;
};
- cmd {
+ cmd-pins {
pins = "sdc2_cmd";
bias-pull-up;
drive-strength = <2>;
};
- data {
+ data-pins {
pins = "sdc2_data";
bias-pull-up;
drive-strength = <2>;
@@ -1616,7 +1607,6 @@
"core";
phys = <&dsi0_phy>;
- phy-names = "dsi";
status = "disabled";
@@ -1639,7 +1629,7 @@
};
};
- dsi0_phy: dsi-phy@c994400 {
+ dsi0_phy: phy@c994400 {
compatible = "qcom,dsi-phy-14nm-660";
reg = <0x0c994400 0x100>,
<0x0c994500 0x300>,
@@ -2224,12 +2214,12 @@
#address-cells = <1>;
#size-cells = <0>;
- q6core {
+ service@3 {
reg = <APR_SVC_ADSP_CORE>;
compatible = "qcom,q6core";
};
- q6afe: apr-service@4 {
+ q6afe: service@4 {
compatible = "qcom,q6afe";
reg = <APR_SVC_AFE>;
q6afedai: dais {
@@ -2240,7 +2230,7 @@
};
};
- q6asm: apr-service@7 {
+ q6asm: service@7 {
compatible = "qcom,q6asm";
reg = <APR_SVC_ASM>;
q6asmdai: dais {
@@ -2252,7 +2242,7 @@
};
};
- q6adm: apr-service@8 {
+ q6adm: service@8 {
compatible = "qcom,q6adm";
reg = <APR_SVC_ADM>;
q6routing: routing {
diff --git a/arch/arm64/boot/dts/qcom/sdm632-fairphone-fp3.dts b/arch/arm64/boot/dts/qcom/sdm632-fairphone-fp3.dts
index 891e314bc782..3fb513cad0a9 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-fairphone-fp3.dts
+++ b/arch/arm64/boot/dts/qcom/sdm632-fairphone-fp3.dts
@@ -49,6 +49,20 @@
vdda-phy-dpdm-supply = <&pm8953_l13>;
};
+&i2c_3 {
+ status = "okay";
+
+ touchscreen@48 {
+ compatible = "himax,hx83112b";
+ reg = <0x48>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <65 IRQ_TYPE_LEVEL_LOW>;
+ touchscreen-size-x = <1080>;
+ touchscreen-size-y = <2160>;
+ reset-gpios = <&tlmm 64 GPIO_ACTIVE_LOW>;
+ };
+};
+
&pm8953_resin {
status = "okay";
linux,code = <KEY_VOLUMEDOWN>;
@@ -69,7 +83,7 @@
};
&rpm_requests {
- pm8953-regulators {
+ regulators {
compatible = "qcom,rpm-pm8953-regulators";
vdd_l1-supply = <&pm8953_s3>;
diff --git a/arch/arm64/boot/dts/qcom/sdm636-sony-xperia-ganges-mermaid.dts b/arch/arm64/boot/dts/qcom/sdm636-sony-xperia-ganges-mermaid.dts
index 58f687fc49e0..9702e5f59a1d 100644
--- a/arch/arm64/boot/dts/qcom/sdm636-sony-xperia-ganges-mermaid.dts
+++ b/arch/arm64/boot/dts/qcom/sdm636-sony-xperia-ganges-mermaid.dts
@@ -19,7 +19,7 @@
};
&sdc2_state_on {
- clk {
+ clk-pins {
drive-strength = <14>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm660-xiaomi-lavender.dts b/arch/arm64/boot/dts/qcom/sdm660-xiaomi-lavender.dts
index a3559f6e34a5..8fb2d1788742 100644
--- a/arch/arm64/boot/dts/qcom/sdm660-xiaomi-lavender.dts
+++ b/arch/arm64/boot/dts/qcom/sdm660-xiaomi-lavender.dts
@@ -111,7 +111,7 @@
};
&rpm_requests {
- pm660l-regulators {
+ regulators-0 {
compatible = "qcom,rpm-pm660l-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -206,7 +206,7 @@
};
};
- pm660-regulators {
+ regulators-1 {
compatible = "qcom,rpm-pm660-regulators";
vdd_s1-supply = <&vph_pwr>;
@@ -372,16 +372,18 @@
};
&sdc2_state_on {
- sd-cd {
+ sd-cd-pins {
pins = "gpio54";
+ function = "gpio";
bias-pull-up;
drive-strength = <2>;
};
};
&sdc2_state_off {
- sd-cd {
+ sd-cd-pins {
pins = "gpio54";
+ function = "gpio";
bias-disable;
drive-strength = <2>;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm660.dtsi b/arch/arm64/boot/dts/qcom/sdm660.dtsi
index 43220af1b685..d52123cb5cd3 100644
--- a/arch/arm64/boot/dts/qcom/sdm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm660.dtsi
@@ -190,7 +190,6 @@
"core";
phys = <&dsi1_phy>;
- phy-names = "dsi";
status = "disabled";
@@ -213,7 +212,7 @@
};
};
- dsi1_phy: dsi-phy@c996400 {
+ dsi1_phy: phy@c996400 {
compatible = "qcom,dsi-phy-14nm-660";
reg = <0x0c996400 0x100>,
<0x0c996500 0x300>,
diff --git a/arch/arm64/boot/dts/qcom/sdm670-google-sargo.dts b/arch/arm64/boot/dts/qcom/sdm670-google-sargo.dts
new file mode 100644
index 000000000000..cf2ae540db12
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670-google-sargo.dts
@@ -0,0 +1,531 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Device tree for Google Pixel 3a, adapted from google-blueline device tree,
+ * xiaomi-lavender device tree, and oneplus-common device tree.
+ *
+ * Copyright (c) 2022, Richard Acayan. All rights reserved.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+#include <dt-bindings/power/qcom-rpmpd.h>
+#include "sdm670.dtsi"
+#include "pm660.dtsi"
+#include "pm660l.dtsi"
+
+/delete-node/ &mpss_region;
+/delete-node/ &venus_mem;
+/delete-node/ &wlan_msa_mem;
+/delete-node/ &cdsp_mem;
+/delete-node/ &mba_region;
+/delete-node/ &adsp_mem;
+/delete-node/ &ipa_fw_mem;
+/delete-node/ &ipa_gsi_mem;
+/delete-node/ &gpu_mem;
+
+/ {
+ model = "Google Pixel 3a";
+ compatible = "google,sargo", "qcom,sdm670";
+
+ aliases { };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ framebuffer@9c000000 {
+ compatible = "simple-framebuffer";
+ reg = <0 0x9c000000 0 (1080 * 2220 * 4)>;
+ width = <1080>;
+ height = <2220>;
+ stride = <(1080 * 4)>;
+ format = "a8r8g8b8";
+ };
+ };
+
+ clocks {
+ sleep_clk: sleep-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32764>;
+ };
+
+ xo_board: xo-board {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <38400000>;
+ };
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ autorepeat;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&vol_up_pin>;
+
+ key-vol-up {
+ label = "Volume Up";
+ linux,code = <KEY_VOLUMEUP>;
+ gpios = <&pm660l_gpios 7 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ mpss_region: mpss@8b000000 {
+ reg = <0 0x8b000000 0 0x9800000>;
+ no-map;
+ };
+
+ venus_mem: venus@94800000 {
+ reg = <0 0x94800000 0 0x500000>;
+ no-map;
+ };
+
+ wlan_msa_mem: wlan-msa@94d00000 {
+ reg = <0 0x94d00000 0 0x100000>;
+ no-map;
+ };
+
+ cdsp_mem: cdsp@94e00000 {
+ reg = <0 0x94e00000 0 0x800000>;
+ no-map;
+ };
+
+ mba_region: mba@95600000 {
+ reg = <0 0x95600000 0 0x200000>;
+ no-map;
+ };
+
+ adsp_mem: adsp@95800000 {
+ reg = <0 0x95800000 0 0x2200000>;
+ no-map;
+ };
+
+ ipa_fw_mem: ipa-fw@97a00000 {
+ reg = <0 0x97a00000 0 0x10000>;
+ no-map;
+ };
+
+ ipa_gsi_mem: ipa-gsi@97a10000 {
+ reg = <0 0x97a10000 0 0x5000>;
+ no-map;
+ };
+
+ gpu_mem: gpu@97a15000 {
+ reg = <0 0x97a15000 0 0x2000>;
+ no-map;
+ };
+
+ framebuffer-region@9c000000 {
+ reg = <0 0x9c000000 0 0x2400000>;
+ no-map;
+ };
+
+ /* Also includes ramoops regions */
+ debug_info_mem: debug-info@a1800000 {
+ reg = <0 0xa1800000 0 0x411000>;
+ no-map;
+ };
+ };
+
+ /*
+ * The touchscreen regulator seems to be controlled somehow by a gpio.
+ * Model it as a fixed regulator and keep it on. Without schematics we
+ * don't know how this is actually wired up...
+ */
+ ts_1p8_supply: ts-1p8-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "ts_1p8_supply";
+
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ gpio = <&pm660_gpios 12 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ vph_pwr: vph-pwr-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vph_pwr";
+ regulator-min-microvolt = <3312000>;
+ regulator-max-microvolt = <3312000>;
+
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ /*
+ * Supply map from xiaomi-lavender specifies this as the supply for
+ * ldob1, ldob9, ldob10, ldoa2, and ldoa3, while downstream specifies
+ * this as a power domain. Set this as a fixed regulator with the same
+ * voltage as lavender until display is needed to avoid unneccessarily
+ * using a deprecated binding (regulator-fixed-domain).
+ */
+ vreg_s2b_1p05: vreg-s2b-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vreg_s2b";
+ regulator-min-microvolt = <1050000>;
+ regulator-max-microvolt = <1050000>;
+ };
+};
+
+&apps_rsc {
+ regulators-0 {
+ compatible = "qcom,pm660-rpmh-regulators";
+ qcom,pmic-id = "a";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+ vdd-s4-supply = <&vph_pwr>;
+ vdd-s5-supply = <&vph_pwr>;
+ vdd-s6-supply = <&vph_pwr>;
+
+ vdd-l1-l6-l7-supply = <&vreg_s6a_0p87>;
+ vdd-l2-l3-supply = <&vreg_s2b_1p05>;
+ vdd-l5-supply = <&vreg_s2b_1p05>;
+ vdd-l8-l9-l10-l11-l12-l13-l14-supply = <&vreg_s4a_2p04>;
+ vdd-l15-l16-l17-l18-l19-supply = <&vreg_bob>;
+
+ /*
+ * S1A (FTAPC0), S2A (FTAPC1), S3A (HFAPC1) are managed
+ * by the Core Power Reduction hardened (CPRh) and the
+ * Operating State Manager (OSM) HW automatically.
+ */
+
+ vreg_s4a_2p04: smps4 {
+ regulator-min-microvolt = <1808000>;
+ regulator-max-microvolt = <2040000>;
+ regulator-enable-ramp-delay = <200>;
+ };
+
+ vreg_s6a_0p87: smps6 {
+ regulator-min-microvolt = <1224000>;
+ regulator-max-microvolt = <1352000>;
+ regulator-enable-ramp-delay = <150>;
+ };
+
+ /* LDOs */
+ vreg_l1a_1p225: ldo1 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1250000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l2a_1p0: ldo2 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l3a_1p0: ldo3 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l5a_0p848: ldo5 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l6a_1p3: ldo6 {
+ regulator-min-microvolt = <1248000>;
+ regulator-max-microvolt = <1304000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l7a_1p2: ldo7 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l8a_1p8: ldo8 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l9a_1p8: ldo9 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l10a_1p8: ldo10 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l11a_1p8: ldo11 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l12a_1p8: ldo12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l13a_1p8: ldo13 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l14a_1p8: ldo14 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l15a_1p8: ldo15 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l16a_2p7: ldo16 {
+ regulator-min-microvolt = <2696000>;
+ regulator-max-microvolt = <2696000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l17a_1p8: ldo17 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l19a_3p3: ldo19 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3312000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+ };
+
+ regulators-1 {
+ compatible = "qcom,pm660l-rpmh-regulators";
+ qcom,pmic-id = "b";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-s4-supply = <&vph_pwr>;
+ vdd-s5-supply = <&vph_pwr>;
+
+ vdd-l1-l9-l10-supply = <&vreg_s2b_1p05>;
+ vdd-l2-supply = <&vreg_bob>;
+ vdd-l3-l5-l7-l8-supply = <&vreg_bob>;
+ vdd-l4-l6-supply = <&vreg_bob>;
+ vdd-bob-supply = <&vph_pwr>;
+
+ /* LDOs */
+ vreg_l1b_0p925: ldo1 {
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <900000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l2b_2p95: ldo2 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l3b_3p0: ldo3 {
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l4b_2p95: ldo4 {
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l5b_2p95: ldo5 {
+ regulator-min-microvolt = <2960000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l6b_3p3: ldo6 {
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l7b_3p125: ldo7 {
+ regulator-min-microvolt = <3088000>;
+ regulator-max-microvolt = <3100000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ vreg_l8b_3p3: ldo8 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3312000>;
+ regulator-enable-ramp-delay = <250>;
+ };
+
+ /*
+ * Downstream specifies a fixed voltage of 3.312 V, but the
+ * PMIC4 BOB ranges don't support that. Widen the range a
+ * little to avoid adding a new BOB regulator type.
+ */
+ vreg_bob: bob {
+ regulator-min-microvolt = <3296000>;
+ regulator-max-microvolt = <3328000>;
+ regulator-enable-ramp-delay = <500>;
+ };
+ };
+
+};
+
+&gcc {
+ protected-clocks = <GCC_QSPI_CORE_CLK>,
+ <GCC_QSPI_CORE_CLK_SRC>,
+ <GCC_QSPI_CNOC_PERIPH_AHB_CLK>;
+};
+
+&gpi_dma1 {
+ status = "okay";
+};
+
+&i2c9 {
+ clock-frequency = <100000>;
+ status = "okay";
+
+ synaptics-rmi4-i2c@20 {
+ compatible = "syna,rmi4-i2c";
+ reg = <0x20>;
+ interrupts-extended = <&tlmm 125 IRQ_TYPE_EDGE_FALLING>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&touchscreen_default>;
+
+ vio-supply = <&ts_1p8_supply>;
+
+ syna,reset-delay-ms = <200>;
+ syna,startup-delay-ms = <200>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ rmi4-f01@1 {
+ reg = <0x01>;
+ syna,nosleep-mode = <1>;
+ };
+
+ rmi4-f12@12 {
+ reg = <0x12>;
+ touchscreen-x-mm = <62>;
+ touchscreen-y-mm = <127>;
+ syna,sensor-type = <1>;
+ };
+ };
+};
+
+&pm660l_gpios {
+ vol_up_pin: vol-up-state {
+ pins = "gpio7";
+ function = "normal";
+ qcom,drive-strength = <PMIC_GPIO_STRENGTH_NO>;
+ input-enable;
+ bias-pull-up;
+ };
+};
+
+&pon_pwrkey {
+ status = "okay";
+};
+
+&pon_resin {
+ linux,code = <KEY_VOLUMEDOWN>;
+ status = "okay";
+};
+
+&qupv3_id_1 {
+ status = "okay";
+};
+
+&sdhc_1 {
+ supports-cqe;
+ mmc-hs200-1_8v;
+ mmc-hs400-1_8v;
+ mmc-ddr-1_8v;
+
+ qcom,ddr-config = <0xc3040873>;
+
+ vmmc-supply = <&vreg_l4b_2p95>;
+ vqmmc-supply = <&vreg_l8a_1p8>;
+
+ status = "okay";
+};
+
+&tlmm {
+ gpio-reserved-ranges = <0 4>, <81 4>;
+
+ touchscreen_default: ts-default-state {
+ ts-reset-pins {
+ pins = "gpio99";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ output-high;
+ };
+
+ ts-irq-pins {
+ pins = "gpio125";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ ts-switch-pins {
+ pins = "gpio135";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
+ };
+};
+
+&usb_1_hsphy {
+ vdd-supply = <&vreg_l1b_0p925>;
+ vdda-pll-supply = <&vreg_l10a_1p8>;
+ vdda-phy-dpdm-supply = <&vreg_l7b_3p125>;
+
+ status = "okay";
+};
+
+&usb_1 {
+ qcom,select-utmi-as-pipe-clk;
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ /* Only peripheral works for now */
+ dr_mode = "peripheral";
+
+ /* Do not assume that sdm670.dtsi will never support USB 3.0 */
+ phys = <&usb_1_hsphy>;
+ phy-names = "usb2-phy";
+ maximum-speed = "high-speed";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
new file mode 100644
index 000000000000..47363fde64ac
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -0,0 +1,1160 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SDM670 SoC device tree source, adapted from SDM845 SoC device tree
+ *
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022, Richard Acayan. All rights reserved.
+ */
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/dma/qcom-gpi.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/phy/phy-qcom-qusb2.h>
+#include <dt-bindings/power/qcom-rpmpd.h>
+#include <dt-bindings/soc/qcom,rpmh-rsc.h>
+
+/ {
+ interrupt-parent = <&intc>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ aliases { };
+
+ chosen { };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ CPU0: cpu@0 {
+ device_type = "cpu";
+ compatible = "qcom,kryo360";
+ reg = <0x0 0x0>;
+ enable-method = "psci";
+ power-domains = <&CPU_PD0>;
+ power-domain-names = "psci";
+ next-level-cache = <&L2_0>;
+ L2_0: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ L3_0: l3-cache {
+ compatible = "cache";
+ };
+ };
+ };
+
+ CPU1: cpu@100 {
+ device_type = "cpu";
+ compatible = "qcom,kryo360";
+ reg = <0x0 0x100>;
+ enable-method = "psci";
+ power-domains = <&CPU_PD1>;
+ power-domain-names = "psci";
+ next-level-cache = <&L2_100>;
+ L2_100: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU2: cpu@200 {
+ device_type = "cpu";
+ compatible = "qcom,kryo360";
+ reg = <0x0 0x200>;
+ enable-method = "psci";
+ power-domains = <&CPU_PD2>;
+ power-domain-names = "psci";
+ next-level-cache = <&L2_200>;
+ L2_200: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU3: cpu@300 {
+ device_type = "cpu";
+ compatible = "qcom,kryo360";
+ reg = <0x0 0x300>;
+ enable-method = "psci";
+ power-domains = <&CPU_PD3>;
+ power-domain-names = "psci";
+ next-level-cache = <&L2_300>;
+ L2_300: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU4: cpu@400 {
+ device_type = "cpu";
+ compatible = "qcom,kryo360";
+ reg = <0x0 0x400>;
+ enable-method = "psci";
+ power-domains = <&CPU_PD4>;
+ power-domain-names = "psci";
+ next-level-cache = <&L2_400>;
+ L2_400: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU5: cpu@500 {
+ device_type = "cpu";
+ compatible = "qcom,kryo360";
+ reg = <0x0 0x500>;
+ enable-method = "psci";
+ power-domains = <&CPU_PD5>;
+ power-domain-names = "psci";
+ next-level-cache = <&L2_500>;
+ L2_500: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU6: cpu@600 {
+ device_type = "cpu";
+ compatible = "qcom,kryo360";
+ reg = <0x0 0x600>;
+ enable-method = "psci";
+ power-domains = <&CPU_PD6>;
+ power-domain-names = "psci";
+ next-level-cache = <&L2_600>;
+ L2_600: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU7: cpu@700 {
+ device_type = "cpu";
+ compatible = "qcom,kryo360";
+ reg = <0x0 0x700>;
+ enable-method = "psci";
+ power-domains = <&CPU_PD7>;
+ power-domain-names = "psci";
+ next-level-cache = <&L2_700>;
+ L2_700: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&CPU0>;
+ };
+
+ core1 {
+ cpu = <&CPU1>;
+ };
+
+ core2 {
+ cpu = <&CPU2>;
+ };
+
+ core3 {
+ cpu = <&CPU3>;
+ };
+
+ core4 {
+ cpu = <&CPU4>;
+ };
+
+ core5 {
+ cpu = <&CPU5>;
+ };
+
+ core6 {
+ cpu = <&CPU6>;
+ };
+
+ core7 {
+ cpu = <&CPU7>;
+ };
+ };
+ };
+
+ idle-states {
+ entry-method = "psci";
+
+ LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ compatible = "arm,idle-state";
+ idle-state-name = "little-rail-power-collapse";
+ arm,psci-suspend-param = <0x40000004>;
+ entry-latency-us = <702>;
+ exit-latency-us = <915>;
+ min-residency-us = <1617>;
+ local-timer-stop;
+ };
+
+ BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ compatible = "arm,idle-state";
+ idle-state-name = "big-rail-power-collapse";
+ arm,psci-suspend-param = <0x40000004>;
+ entry-latency-us = <526>;
+ exit-latency-us = <1854>;
+ min-residency-us = <2380>;
+ local-timer-stop;
+ };
+ };
+
+ domain-idle-states {
+ CLUSTER_SLEEP_0: cluster-sleep-0 {
+ compatible = "domain-idle-state";
+ arm,psci-suspend-param = <0x4100c244>;
+ entry-latency-us = <3263>;
+ exit-latency-us = <6562>;
+ min-residency-us = <9825>;
+ };
+ };
+ };
+
+ firmware {
+ scm {
+ compatible = "qcom,scm-sdm670", "qcom,scm";
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ /* We expect the bootloader to fill in the size */
+ reg = <0x0 0x80000000 0x0 0x0>;
+ };
+
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+
+ CPU_PD0: power-domain-cpu0 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ };
+
+ CPU_PD1: power-domain-cpu1 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ };
+
+ CPU_PD2: power-domain-cpu2 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ };
+
+ CPU_PD3: power-domain-cpu3 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ };
+
+ CPU_PD4: power-domain-cpu4 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ };
+
+ CPU_PD5: power-domain-cpu5 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ };
+
+ CPU_PD6: power-domain-cpu6 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ };
+
+ CPU_PD7: power-domain-cpu7 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ };
+
+ CLUSTER_PD: power-domain-cluster {
+ #power-domain-cells = <0>;
+ domain-idle-states = <&CLUSTER_SLEEP_0>;
+ };
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ hyp_mem: hyp-mem@85700000 {
+ reg = <0 0x85700000 0 0x600000>;
+ no-map;
+ };
+
+ xbl_mem: xbl-mem@85e00000 {
+ reg = <0 0x85e00000 0 0x100000>;
+ no-map;
+ };
+
+ aop_mem: aop-mem@85fc0000 {
+ reg = <0 0x85fc0000 0 0x20000>;
+ no-map;
+ };
+
+ aop_cmd_db_mem: aop-cmd-db-mem@85fe0000 {
+ compatible = "qcom,cmd-db";
+ reg = <0 0x85fe0000 0 0x20000>;
+ no-map;
+ };
+
+ camera_mem: camera-mem@8ab00000 {
+ reg = <0 0x8ab00000 0 0x500000>;
+ no-map;
+ };
+
+ mpss_region: mpss@8b000000 {
+ reg = <0 0x8b000000 0 0x7e00000>;
+ no-map;
+ };
+
+ venus_mem: venus@92e00000 {
+ reg = <0 0x92e00000 0 0x500000>;
+ no-map;
+ };
+
+ wlan_msa_mem: wlan-msa@93300000 {
+ reg = <0 0x93300000 0 0x100000>;
+ no-map;
+ };
+
+ cdsp_mem: cdsp@93400000 {
+ reg = <0 0x93400000 0 0x800000>;
+ no-map;
+ };
+
+ mba_region: mba@93c00000 {
+ reg = <0 0x93c00000 0 0x200000>;
+ no-map;
+ };
+
+ adsp_mem: adsp@93e00000 {
+ reg = <0 0x93e00000 0 0x1e00000>;
+ no-map;
+ };
+
+ ipa_fw_mem: ipa-fw@95c00000 {
+ reg = <0 0x95c00000 0 0x10000>;
+ no-map;
+ };
+
+ ipa_gsi_mem: ipa-gsi@95c10000 {
+ reg = <0 0x95c10000 0 0x5000>;
+ no-map;
+ };
+
+ gpu_mem: gpu@95c15000 {
+ reg = <0 0x95c15000 0 0x2000>;
+ no-map;
+ };
+
+ spss_mem: spss@97b00000 {
+ reg = <0 0x97b00000 0 0x100000>;
+ no-map;
+ };
+
+ qseecom_mem: qseecom@9e400000 {
+ reg = <0 0x9e400000 0 0x1400000>;
+ no-map;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 1 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 2 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 3 IRQ_TYPE_LEVEL_LOW>,
+ <GIC_PPI 0 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ soc: soc@0 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0 0 0 0 0x10 0>;
+ dma-ranges = <0 0 0 0 0x10 0>;
+ compatible = "simple-bus";
+
+ gcc: clock-controller@100000 {
+ compatible = "qcom,gcc-sdm670";
+ reg = <0 0x00100000 0 0x1f0000>;
+ clocks = <&rpmhcc RPMH_CXO_CLK>,
+ <&rpmhcc RPMH_CXO_CLK_A>,
+ <&sleep_clk>;
+ clock-names = "bi_tcxo",
+ "bi_tcxo_ao",
+ "sleep_clk";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
+ sdhc_1: mmc@7c4000 {
+ compatible = "qcom,sdm670-sdhci", "qcom,sdhci-msm-v5";
+ reg = <0 0x007c4000 0 0x1000>,
+ <0 0x007c5000 0 0x1000>,
+ <0 0x007c8000 0 0x8000>;
+ reg-names = "hc", "cqhci", "ice";
+
+ interrupts = <GIC_SPI 641 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 644 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ clocks = <&gcc GCC_SDCC1_AHB_CLK>,
+ <&gcc GCC_SDCC1_APPS_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>,
+ <&gcc GCC_SDCC1_ICE_CORE_CLK>,
+ <&gcc GCC_AGGRE_UFS_PHY_AXI_CLK>;
+ clock-names = "iface", "core", "xo", "ice", "bus";
+
+ iommus = <&apps_smmu 0x140 0xf>;
+
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdc1_state_on>;
+ pinctrl-1 = <&sdc1_state_off>;
+ power-domains = <&rpmhpd SDM670_CX>;
+
+ bus-width = <8>;
+ non-removable;
+
+ status = "disabled";
+ };
+
+ gpi_dma0: dma-controller@800000 {
+ #dma-cells = <3>;
+ compatible = "qcom,sdm670-gpi-dma", "qcom,sdm845-gpi-dma";
+ reg = <0 0x00800000 0 0x60000>;
+ interrupts = <GIC_SPI 244 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 248 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 249 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 250 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 251 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 252 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 253 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 254 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>;
+ dma-channels = <13>;
+ dma-channel-mask = <0xfa>;
+ iommus = <&apps_smmu 0x16 0x0>;
+ status = "disabled";
+ };
+
+ qupv3_id_0: geniqup@8c0000 {
+ compatible = "qcom,geni-se-qup";
+ reg = <0 0x008c0000 0 0x6000>;
+ clock-names = "m-ahb", "s-ahb";
+ clocks = <&gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+ <&gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+ iommus = <&apps_smmu 0x3 0x0>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ status = "disabled";
+
+ i2c0: i2c@880000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0 0x00880000 0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c0_default>;
+ interrupts = <GIC_SPI 601 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&rpmhpd SDM670_CX>;
+ dmas = <&gpi_dma0 0 0 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 0 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c1: i2c@884000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0 0x00884000 0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c1_default>;
+ interrupts = <GIC_SPI 602 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&rpmhpd SDM670_CX>;
+ dmas = <&gpi_dma0 0 1 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 1 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c2: i2c@888000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0 0x00888000 0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c2_default>;
+ interrupts = <GIC_SPI 603 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&rpmhpd SDM670_CX>;
+ dmas = <&gpi_dma0 0 2 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 2 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c3: i2c@88c000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0 0x0088c000 0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c3_default>;
+ interrupts = <GIC_SPI 604 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&rpmhpd SDM670_CX>;
+ dmas = <&gpi_dma0 0 3 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 3 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c4: i2c@890000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0 0x00890000 0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c4_default>;
+ interrupts = <GIC_SPI 605 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&rpmhpd SDM670_CX>;
+ dmas = <&gpi_dma0 0 4 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 4 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c5: i2c@894000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0 0x00894000 0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c5_default>;
+ interrupts = <GIC_SPI 606 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&rpmhpd SDM670_CX>;
+ dmas = <&gpi_dma0 0 5 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 5 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c6: i2c@898000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0 0x00898000 0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S6_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c6_default>;
+ interrupts = <GIC_SPI 607 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&rpmhpd SDM670_CX>;
+ dmas = <&gpi_dma0 0 6 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 6 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c7: i2c@89c000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0 0x0089c000 0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S7_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c7_default>;
+ interrupts = <GIC_SPI 608 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&rpmhpd SDM670_CX>;
+ dmas = <&gpi_dma0 0 7 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 7 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+ };
+
+ gpi_dma1: dma-controller@a00000 {
+ #dma-cells = <3>;
+ compatible = "qcom,sdm670-gpi-dma", "qcom,sdm845-gpi-dma";
+ reg = <0 0x00a00000 0 0x60000>;
+ interrupts = <GIC_SPI 279 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 280 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 281 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 283 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 284 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 293 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 294 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 295 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 296 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 297 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 298 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 299 IRQ_TYPE_LEVEL_HIGH>;
+ dma-channels = <13>;
+ dma-channel-mask = <0xfa>;
+ iommus = <&apps_smmu 0x6d6 0x0>;
+ status = "disabled";
+ };
+
+ qupv3_id_1: geniqup@ac0000 {
+ compatible = "qcom,geni-se-qup";
+ reg = <0 0x00ac0000 0 0x6000>;
+ clock-names = "m-ahb", "s-ahb";
+ clocks = <&gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>,
+ <&gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>;
+ iommus = <&apps_smmu 0x6c3 0x0>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ status = "disabled";
+
+ i2c8: i2c@a80000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0 0x00a80000 0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S0_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c8_default>;
+ interrupts = <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&rpmhpd SDM670_CX>;
+ dmas = <&gpi_dma1 0 0 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 0 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c9: i2c@a84000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0 0x00a84000 0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c9_default>;
+ interrupts = <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&rpmhpd SDM670_CX>;
+ dmas = <&gpi_dma1 0 1 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 1 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c10: i2c@a88000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0 0x00a88000 0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S2_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c10_default>;
+ interrupts = <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&rpmhpd SDM670_CX>;
+ dmas = <&gpi_dma1 0 2 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 2 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c11: i2c@a8c000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0 0x00a8c000 0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S3_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c11_default>;
+ interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&rpmhpd SDM670_CX>;
+ dmas = <&gpi_dma1 0 3 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 3 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c12: i2c@a90000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0 0x00a90000 0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c12_default>;
+ interrupts = <GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&rpmhpd SDM670_CX>;
+ dmas = <&gpi_dma1 0 4 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 4 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c13: i2c@a94000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0 0x00a94000 0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S5_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c13_default>;
+ interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&rpmhpd SDM670_CX>;
+ dmas = <&gpi_dma1 0 5 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 5 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c14: i2c@a98000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0 0x00a98000 0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S6_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c14_default>;
+ interrupts = <GIC_SPI 359 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&rpmhpd SDM670_CX>;
+ dmas = <&gpi_dma1 0 6 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 6 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
+ i2c15: i2c@a9c000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0 0x00a9c000 0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S7_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c15_default>;
+ interrupts = <GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ power-domains = <&rpmhpd SDM670_CX>;
+ dmas = <&gpi_dma1 0 7 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 7 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+ };
+
+ tlmm: pinctrl@3400000 {
+ compatible = "qcom,sdm670-tlmm";
+ reg = <0 0x03400000 0 0xc00000>;
+ interrupts = <GIC_SPI 208 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ gpio-ranges = <&tlmm 0 0 151>;
+
+ qup_i2c0_default: qup-i2c0-default-state {
+ pins = "gpio0", "gpio1";
+ function = "qup0";
+ };
+
+ qup_i2c1_default: qup-i2c1-default-state {
+ pins = "gpio17", "gpio18";
+ function = "qup1";
+ };
+
+ qup_i2c2_default: qup-i2c2-default-state {
+ pins = "gpio27", "gpio28";
+ function = "qup2";
+ };
+
+ qup_i2c3_default: qup-i2c3-default-state {
+ pins = "gpio41", "gpio42";
+ function = "qup3";
+ };
+
+ qup_i2c4_default: qup-i2c4-default-state {
+ pins = "gpio89", "gpio90";
+ function = "qup4";
+ };
+
+ qup_i2c5_default: qup-i2c5-default-state {
+ pins = "gpio85", "gpio86";
+ function = "qup5";
+ };
+
+ qup_i2c6_default: qup-i2c6-default-state {
+ pins = "gpio45", "gpio46";
+ function = "qup6";
+ };
+
+ qup_i2c7_default: qup-i2c7-default-state {
+ pins = "gpio93", "gpio94";
+ function = "qup7";
+ };
+
+ qup_i2c8_default: qup-i2c8-default-state {
+ pins = "gpio65", "gpio66";
+ function = "qup8";
+ };
+
+ qup_i2c9_default: qup-i2c9-default-state {
+ pins = "gpio6", "gpio7";
+ function = "qup9";
+ };
+
+ qup_i2c10_default: qup-i2c10-default-state {
+ pins = "gpio55", "gpio56";
+ function = "qup10";
+ };
+
+ qup_i2c11_default: qup-i2c11-default-state {
+ pins = "gpio31", "gpio32";
+ function = "qup11";
+ };
+
+ qup_i2c12_default: qup-i2c12-default-state {
+ pins = "gpio49", "gpio50";
+ function = "qup12";
+ };
+
+ qup_i2c13_default: qup-i2c13-default-state {
+ pins = "gpio105", "gpio106";
+ function = "qup13";
+ };
+
+ qup_i2c14_default: qup-i2c14-default-state {
+ pins = "gpio33", "gpio34";
+ function = "qup14";
+ };
+
+ qup_i2c15_default: qup-i2c15-default-state {
+ pins = "gpio81", "gpio82";
+ function = "qup15";
+ };
+
+ sdc1_state_on: sdc1-on-state {
+ clk-pins {
+ pins = "sdc1_clk";
+ bias-disable;
+ drive-strength = <16>;
+ };
+
+ cmd-pins {
+ pins = "sdc1_cmd";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ data-pins {
+ pins = "sdc1_data";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ rclk-pins {
+ pins = "sdc1_rclk";
+ bias-pull-down;
+ };
+ };
+
+ sdc1_state_off: sdc1-off-state {
+ clk-pins {
+ pins = "sdc1_clk";
+ bias-disable;
+ drive-strength = <2>;
+ };
+
+ cmd-pins {
+ pins = "sdc1_cmd";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+
+ data-pins {
+ pins = "sdc1_data";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+
+ rclk-pins {
+ pins = "sdc1_rclk";
+ bias-pull-down;
+ };
+ };
+ };
+
+ usb_1_hsphy: phy@88e2000 {
+ compatible = "qcom,sdm670-qusb2-phy", "qcom,qusb2-v2-phy";
+ reg = <0 0x088e2000 0 0x400>;
+ #phy-cells = <0>;
+
+ clocks = <&gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "cfg_ahb", "ref";
+
+ resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>;
+
+ status = "disabled";
+ };
+
+ usb_1: usb@a6f8800 {
+ compatible = "qcom,sdm670-dwc3", "qcom,dwc3";
+ reg = <0 0x0a6f8800 0 0x400>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ dma-ranges;
+
+ clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
+ <&gcc GCC_USB30_PRIM_MASTER_CLK>,
+ <&gcc GCC_AGGRE_USB3_PRIM_AXI_CLK>,
+ <&gcc GCC_USB30_PRIM_SLEEP_CLK>,
+ <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>;
+ clock-names = "cfg_noc",
+ "core",
+ "iface",
+ "sleep",
+ "mock_utmi";
+
+ assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
+ <&gcc GCC_USB30_PRIM_MASTER_CLK>;
+ assigned-clock-rates = <19200000>, <150000000>;
+
+ interrupts = <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 486 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 488 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 489 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hs_phy_irq", "ss_phy_irq",
+ "dm_hs_phy_irq", "dp_hs_phy_irq";
+
+ power-domains = <&gcc USB30_PRIM_GDSC>;
+
+ resets = <&gcc GCC_USB30_PRIM_BCR>;
+
+ status = "disabled";
+
+ usb_1_dwc3: usb@a600000 {
+ compatible = "snps,dwc3";
+ reg = <0 0x0a600000 0 0xcd00>;
+ interrupts = <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>;
+ iommus = <&apps_smmu 0x740 0>;
+ snps,dis_u2_susphy_quirk;
+ snps,dis_enblslpm_quirk;
+ phys = <&usb_1_hsphy>;
+ phy-names = "usb2-phy";
+ };
+ };
+
+ spmi_bus: spmi@c440000 {
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0 0x0c440000 0 0x1100>,
+ <0 0x0c600000 0 0x2000000>,
+ <0 0x0e600000 0 0x100000>,
+ <0 0x0e700000 0 0xa0000>,
+ <0 0x0c40a000 0 0x26000>;
+ reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
+ interrupt-names = "periph_irq";
+ interrupts = <GIC_SPI 481 IRQ_TYPE_LEVEL_HIGH>;
+ qcom,ee = <0>;
+ qcom,channel = <0>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <4>;
+ };
+
+ apps_smmu: iommu@15000000 {
+ compatible = "qcom,sdm670-smmu-500", "qcom,smmu-500", "arm,mmu-500";
+ reg = <0 0x15000000 0 0x80000>;
+ #iommu-cells = <2>;
+ #global-interrupts = <1>;
+ interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 181 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 182 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 184 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 185 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 318 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 319 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 320 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 321 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 322 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 323 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 324 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 325 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 333 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 334 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 335 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ apps_rsc: rsc@179c0000 {
+ compatible = "qcom,rpmh-rsc";
+ reg = <0 0x179c0000 0 0x10000>,
+ <0 0x179d0000 0 0x10000>,
+ <0 0x179e0000 0 0x10000>;
+ reg-names = "drv-0", "drv-1", "drv-2";
+ interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ label = "apps_rsc";
+ qcom,tcs-offset = <0xd00>;
+ qcom,drv-id = <2>;
+ qcom,tcs-config = <ACTIVE_TCS 2>,
+ <SLEEP_TCS 3>,
+ <WAKE_TCS 3>,
+ <CONTROL_TCS 1>;
+
+ apps_bcm_voter: bcm-voter {
+ compatible = "qcom,bcm-voter";
+ };
+
+ rpmhcc: clock-controller {
+ compatible = "qcom,sdm670-rpmh-clk";
+ #clock-cells = <1>;
+ clock-names = "xo";
+ clocks = <&xo_board>;
+ };
+
+ rpmhpd: power-controller {
+ compatible = "qcom,sdm670-rpmhpd";
+ #power-domain-cells = <1>;
+ operating-points-v2 = <&rpmhpd_opp_table>;
+
+ rpmhpd_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ rpmhpd_opp_ret: opp1 {
+ opp-level = <RPMH_REGULATOR_LEVEL_RETENTION>;
+ };
+
+ rpmhpd_opp_min_svs: opp2 {
+ opp-level = <RPMH_REGULATOR_LEVEL_MIN_SVS>;
+ };
+
+ rpmhpd_opp_low_svs: opp3 {
+ opp-level = <RPMH_REGULATOR_LEVEL_LOW_SVS>;
+ };
+
+ rpmhpd_opp_svs: opp4 {
+ opp-level = <RPMH_REGULATOR_LEVEL_SVS>;
+ };
+
+ rpmhpd_opp_svs_l1: opp5 {
+ opp-level = <RPMH_REGULATOR_LEVEL_SVS_L1>;
+ };
+
+ rpmhpd_opp_nom: opp6 {
+ opp-level = <RPMH_REGULATOR_LEVEL_NOM>;
+ };
+
+ rpmhpd_opp_nom_l1: opp7 {
+ opp-level = <RPMH_REGULATOR_LEVEL_NOM_L1>;
+ };
+
+ rpmhpd_opp_nom_l2: opp8 {
+ opp-level = <RPMH_REGULATOR_LEVEL_NOM_L2>;
+ };
+
+ rpmhpd_opp_turbo: opp9 {
+ opp-level = <RPMH_REGULATOR_LEVEL_TURBO>;
+ };
+
+ rpmhpd_opp_turbo_l1: opp10 {
+ opp-level = <RPMH_REGULATOR_LEVEL_TURBO_L1>;
+ };
+ };
+ };
+ };
+
+ intc: interrupt-controller@17a00000 {
+ compatible = "arm,gic-v3";
+ reg = <0 0x17a00000 0 0x10000>, /* GICD */
+ <0 0x17a60000 0 0x100000>; /* GICR * 8 */
+ interrupt-controller;
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ #interrupt-cells = <3>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi
index b5eb8f7eca1d..ca676e04687b 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cheza.dtsi
@@ -16,7 +16,7 @@
/ {
aliases {
bluetooth0 = &bluetooth;
- hsuart0 = &uart6;
+ serial1 = &uart6;
serial0 = &uart9;
wifi0 = &wifi;
};
@@ -860,6 +860,8 @@ ap_ts_i2c: &i2c14 {
&uart6 {
status = "okay";
+ pinctrl-0 = <&qup_uart6_4pin>;
+
bluetooth: wcn3990-bt {
compatible = "qcom,wcn3990-bt";
vddio-supply = <&src_pp1800_s4a>;
@@ -1079,41 +1081,6 @@ ap_ts_i2c: &i2c14 {
};
};
-&qup_uart6_default {
- /* Change pinmux to all 4 pins since CTS and RTS are connected */
- pinmux {
- pins = "gpio45", "gpio46",
- "gpio47", "gpio48";
- };
-
- pinconf-cts {
- /*
- * Configure a pull-down on 45 (CTS) to match the pull of
- * the Bluetooth module.
- */
- pins = "gpio45";
- bias-pull-down;
- };
-
- pinconf-rts-tx {
- /* We'll drive 46 (RTS) and 47 (TX), so no pull */
- pins = "gpio46", "gpio47";
- drive-strength = <2>;
- bias-disable;
- };
-
- pinconf-rx {
- /*
- * Configure a pull-up on 48 (RX). This is needed to avoid
- * garbage data when the TX pin of the Bluetooth module is
- * in tri-state (module powered off or not driving the
- * signal yet).
- */
- pins = "gpio48";
- bias-pull-up;
- };
-};
-
&qup_uart9_default {
pinconf-tx {
pins = "gpio4";
@@ -1341,7 +1308,7 @@ ap_ts_i2c: &i2c14 {
};
pen_rst_l: pen-rst-l {
- pinmux {
+ pinmux {
pins = "gpio23";
function = "gpio";
};
@@ -1408,7 +1375,7 @@ ap_ts_i2c: &i2c14 {
};
ts_int_l: ts-int-l {
- pinmux {
+ pinmux {
pins = "gpio125";
function = "gpio";
};
@@ -1420,7 +1387,7 @@ ap_ts_i2c: &i2c14 {
};
ts_reset_l: ts-reset-l {
- pinmux {
+ pinmux {
pins = "gpio118";
function = "gpio";
};
@@ -1436,7 +1403,7 @@ ap_ts_i2c: &i2c14 {
config {
pins = "gpio126";
function = "gpio";
- bias-no-pull;
+ bias-disable;
drive-strength = <2>;
output-low;
};
@@ -1446,7 +1413,7 @@ ap_ts_i2c: &i2c14 {
config {
pins = "gpio126";
function = "gpio";
- bias-no-pull;
+ bias-disable;
drive-strength = <2>;
output-high;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dts b/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dts
new file mode 100644
index 000000000000..a21caa6f3fa2
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-db845c-navigation-mezzanine.dts
@@ -0,0 +1,104 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022, Linaro Ltd.
+ */
+
+/dts-v1/;
+
+#include "sdm845-db845c.dts"
+
+&camss {
+ vdda-phy-supply = <&vreg_l1a_0p875>;
+ vdda-pll-supply = <&vreg_l26a_1p2>;
+
+ status = "okay";
+
+ ports {
+ port@0 {
+ csiphy0_ep: endpoint {
+ data-lanes = <0 1 2 3>;
+ remote-endpoint = <&ov8856_ep>;
+ };
+ };
+ };
+};
+
+&cci {
+ status = "okay";
+};
+
+&cci_i2c0 {
+ camera@10 {
+ compatible = "ovti,ov8856";
+ reg = <0x10>;
+
+ /* CAM0_RST_N */
+ reset-gpios = <&tlmm 9 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&cam0_default>;
+
+ clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+ clock-names = "xvclk";
+ clock-frequency = <19200000>;
+
+ /*
+ * The &vreg_s4a_1p8 trace is powered on as a,
+ * so it is represented by a fixed regulator.
+ *
+ * The 2.8V vdda-supply and 1.2V vddd-supply regulators
+ * both have to be enabled through the power management
+ * gpios.
+ */
+ dovdd-supply = <&vreg_lvs1a_1p8>;
+ avdd-supply = <&cam0_avdd_2v8>;
+ dvdd-supply = <&cam0_dvdd_1v2>;
+
+ port {
+ ov8856_ep: endpoint {
+ link-frequencies = /bits/ 64
+ <360000000 180000000>;
+ data-lanes = <1 2 3 4>;
+ remote-endpoint = <&csiphy0_ep>;
+ };
+ };
+ };
+};
+
+&cci_i2c1 {
+ camera@60 {
+ compatible = "ovti,ov7251";
+
+ /* I2C address as per ov7251.txt linux documentation */
+ reg = <0x60>;
+
+ /* CAM3_RST_N */
+ enable-gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&cam3_default>;
+
+ clocks = <&clock_camcc CAM_CC_MCLK3_CLK>;
+ clock-names = "xclk";
+ clock-frequency = <24000000>;
+
+ /*
+ * The &vreg_s4a_1p8 trace always powered on.
+ *
+ * The 2.8V vdda-supply regulator is enabled when the
+ * vreg_s4a_1p8 trace is pulled high.
+ * It too is represented by a fixed regulator.
+ *
+ * No 1.2V vddd-supply regulator is used.
+ */
+ vdddo-supply = <&vreg_lvs1a_1p8>;
+ vdda-supply = <&cam3_avdd_2v8>;
+
+ status = "disabled";
+
+ port {
+ ov7251_ep: endpoint {
+ data-lanes = <0 1>;
+/* remote-endpoint = <&csiphy3_ep>; */
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
index 132417e2d11e..f41c6d600ea8 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-db845c.dts
@@ -22,7 +22,7 @@
aliases {
serial0 = &uart9;
- hsuart0 = &uart6;
+ serial1 = &uart6;
};
chosen {
@@ -120,9 +120,11 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
- // TODO: make it possible to drive same GPIO from two clients
- // gpio = <&tlmm 89 GPIO_ACTIVE_HIGH>;
- // enable-active-high;
+ /*
+ * TODO: make it possible to drive same GPIO from two clients
+ * gpio = <&tlmm 89 GPIO_ACTIVE_HIGH>;
+ * enable-active-high;
+ */
};
pcie0_1p05v: pcie-0-1p05v-regulator {
@@ -133,9 +135,11 @@
regulator-min-microvolt = <1050000>;
regulator-max-microvolt = <1050000>;
- // TODO: make it possible to drive same GPIO from two clients
- // gpio = <&tlmm 90 GPIO_ACTIVE_HIGH>;
- // enable-active-high;
+ /*
+ * TODO: make it possible to drive same GPIO from two clients
+ * gpio = <&tlmm 90 GPIO_ACTIVE_HIGH>;
+ * enable-active-high;
+ */
};
cam0_dvdd_1v2: reg_cam0_dvdd_1v2 {
@@ -195,9 +199,11 @@
regulator-min-microvolt = <500000>;
regulator-max-microvolt = <500000>;
- // TODO: make it possible to drive same GPIO from two clients
- // gpio = <&tlmm 89 GPIO_ACTIVE_HIGH>;
- // enable-active-high;
+ /*
+ * TODO: make it possible to drive same GPIO from two clients
+ * gpio = <&tlmm 89 GPIO_ACTIVE_HIGH>;
+ * enable-active-high;
+ */
};
vbat: vbat-regulator {
@@ -649,9 +655,13 @@
};
};
+&pmi8998_rradc {
+ status = "okay";
+};
+
/* QUAT I2S Uses 4 I2S SD Lines for audio on LT9611 HDMI Bridge */
&q6afedai {
- qi2s@22 {
+ dai@22 {
reg = <QUATERNARY_MI2S_RX>;
qcom,sd-lines = <0 1 2 3>;
};
@@ -986,6 +996,8 @@
&uart6 {
status = "okay";
+ pinctrl-0 = <&qup_uart6_4pin>;
+
bluetooth {
compatible = "qcom,wcn3990-bt";
@@ -1076,7 +1088,7 @@
status = "okay";
};
-&wcd9340{
+&wcd9340 {
pinctrl-0 = <&wcd_intr_default>;
pinctrl-names = "default";
clock-names = "extclk";
@@ -1089,7 +1101,7 @@
vdd-io-supply = <&vreg_s4a_1p8>;
swm: swm@c85 {
- left_spkr: wsa8810-left{
+ left_spkr: speaker@0,1 {
compatible = "sdw10217201000";
reg = <0 1>;
powerdown-gpios = <&wcdgpio 1 GPIO_ACTIVE_HIGH>;
@@ -1098,7 +1110,7 @@
#sound-dai-cells = <0>;
};
- right_spkr: wsa8810-right{
+ right_spkr: speaker@0,2 {
compatible = "sdw10217201000";
powerdown-gpios = <&wcdgpio 1 GPIO_ACTIVE_HIGH>;
reg = <0 2>;
@@ -1123,10 +1135,13 @@
/* PINCTRL - additions to nodes defined in sdm845.dtsi */
&qup_spi2_default {
- drive-strength = <16>;
+ pinconf {
+ pins = "gpio27", "gpio28", "gpio29", "gpio30";
+ drive-strength = <16>;
+ };
};
-&qup_uart3_default{
+&qup_uart3_default {
pinmux {
pins = "gpio41", "gpio42", "gpio43", "gpio44";
function = "qup3";
@@ -1141,29 +1156,6 @@
};
};
-&qup_uart6_default {
- pinmux {
- pins = "gpio45", "gpio46", "gpio47", "gpio48";
- function = "qup6";
- };
-
- cts {
- pins = "gpio45";
- bias-disable;
- };
-
- rts-tx {
- pins = "gpio46", "gpio47";
- drive-strength = <2>;
- bias-disable;
- };
-
- rx {
- pins = "gpio48";
- bias-pull-up;
- };
-};
-
&qup_uart9_default {
pinconf-tx {
pins = "gpio4";
@@ -1182,105 +1174,6 @@
};
-&cci {
- status = "okay";
-};
-
-&camss {
- vdda-phy-supply = <&vreg_l1a_0p875>;
- vdda-pll-supply = <&vreg_l26a_1p2>;
-
- status = "ok";
-
- ports {
- #address-cells = <1>;
- #size-cells = <0>;
- port@0 {
- reg = <0>;
- csiphy0_ep: endpoint {
- data-lanes = <0 1 2 3>;
- remote-endpoint = <&ov8856_ep>;
- };
- };
- };
-};
-
-&cci_i2c0 {
- camera@10 {
- compatible = "ovti,ov8856";
- reg = <0x10>;
-
- // CAM0_RST_N
- reset-gpios = <&tlmm 9 GPIO_ACTIVE_LOW>;
- pinctrl-names = "default";
- pinctrl-0 = <&cam0_default>;
-
- clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
- clock-names = "xvclk";
- clock-frequency = <19200000>;
-
- /* The &vreg_s4a_1p8 trace is powered on as a,
- * so it is represented by a fixed regulator.
- *
- * The 2.8V vdda-supply and 1.2V vddd-supply regulators
- * both have to be enabled through the power management
- * gpios.
- */
- dovdd-supply = <&vreg_lvs1a_1p8>;
- avdd-supply = <&cam0_avdd_2v8>;
- dvdd-supply = <&cam0_dvdd_1v2>;
-
- status = "ok";
-
- port {
- ov8856_ep: endpoint {
- link-frequencies = /bits/ 64
- <360000000 180000000>;
- data-lanes = <1 2 3 4>;
- remote-endpoint = <&csiphy0_ep>;
- };
- };
- };
-};
-
-&cci_i2c1 {
- camera@60 {
- compatible = "ovti,ov7251";
-
- // I2C address as per ov7251.txt linux documentation
- reg = <0x60>;
-
- // CAM3_RST_N
- enable-gpios = <&tlmm 21 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default";
- pinctrl-0 = <&cam3_default>;
-
- clocks = <&clock_camcc CAM_CC_MCLK3_CLK>;
- clock-names = "xclk";
- clock-frequency = <24000000>;
-
- /* The &vreg_s4a_1p8 trace always powered on.
- *
- * The 2.8V vdda-supply regulator is enabled when the
- * vreg_s4a_1p8 trace is pulled high.
- * It too is represented by a fixed regulator.
- *
- * No 1.2V vddd-supply regulator is used.
- */
- vdddo-supply = <&vreg_lvs1a_1p8>;
- vdda-supply = <&cam3_avdd_2v8>;
-
- status = "disable";
-
- port {
- ov7251_ep: endpoint {
- data-lanes = <0 1>;
-// remote-endpoint = <&csiphy3_ep>;
- };
- };
- };
-};
-
/* PINCTRL - additions to nodes defined in sdm845.dtsi */
&qup_spi0_default {
config {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-lg-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-lg-common.dtsi
index 20f275f8694d..1eb423e4be24 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-lg-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-lg-common.dtsi
@@ -604,7 +604,7 @@
};
&pm8998_gpio {
- vol_up_pin_a: vol-up-active-pins {
+ vol_up_pin_a: vol-up-active-state {
pins = "gpio6";
function = "normal";
input-enable;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
index 392461c29e76..42cf4dd5ea28 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
@@ -19,7 +19,7 @@
/ {
aliases {
serial0 = &uart9;
- hsuart0 = &uart6;
+ serial1 = &uart6;
};
chosen {
@@ -50,7 +50,8 @@
};
reserved-memory {
- /* The rmtfs_mem needs to be guarded due to "XPU limitations"
+ /*
+ * The rmtfs_mem needs to be guarded due to "XPU limitations"
* it is otherwise possible for an allocation adjacent to the
* rmtfs_mem region to trigger an XPU violation, causing a crash.
*/
@@ -433,7 +434,7 @@
status = "okay";
};
-/* Modem/wifi*/
+/* Modem/wifi */
&mss_pil {
status = "okay";
firmware-name = "qcom/sdm845/oneplus6/mba.mbn", "qcom/sdm845/oneplus6/modem.mbn";
@@ -461,6 +462,10 @@
};
};
+&pmi8998_rradc {
+ status = "okay";
+};
+
&qupv3_id_1 {
status = "okay";
};
@@ -500,35 +505,11 @@
};
};
-/*
- * Prevent garbage data on bluetooth UART lines
- */
-&qup_uart6_default {
- pinmux {
- pins = "gpio45", "gpio46", "gpio47", "gpio48";
- function = "qup6";
- };
-
- cts {
- pins = "gpio45";
- bias-pull-down;
- };
-
- rts-tx {
- pins = "gpio46", "gpio47";
- drive-strength = <2>;
- bias-disable;
- };
-
- rx {
- pins = "gpio48";
- bias-pull-up;
- };
-};
-
&uart6 {
status = "okay";
+ pinctrl-0 = <&qup_uart6_4pin>;
+
bluetooth {
compatible = "qcom,wcn3990-bt";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
new file mode 100644
index 000000000000..e742c27fe91f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-samsung-starqltechn.dts
@@ -0,0 +1,460 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SDM845 Samsung S9 (SM-G9600) (starqltechn / star2qltechn) common device tree source
+ *
+ * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+#include "sdm845.dtsi"
+
+/ {
+ chassis-type = "handset";
+ model = "Samsung Galaxy S9 SM-G9600";
+ compatible = "samsung,starqltechn", "qcom,sdm845";
+
+ chosen {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ framebuffer: framebuffer@9d400000 {
+ compatible = "simple-framebuffer";
+ reg = <0 0x9d400000 0 (2960 * 1440 * 4)>;//2400000
+ width = <1440>;
+ height = <2960>;
+ stride = <(1440 * 4)>;
+ format = "a8r8g8b8";
+ };
+ };
+
+ vph_pwr: vph-pwr-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vph_pwr";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+ };
+
+ /*
+ * Apparently RPMh does not provide support for PM8998 S4 because it
+ * is always-on; model it as a fixed regulator.
+ */
+ vreg_s4a_1p8: pm8998-smps4 {
+ compatible = "regulator-fixed";
+ regulator-name = "vreg_s4a_1p8";
+
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-always-on;
+ regulator-boot-on;
+
+ vin-supply = <&vph_pwr>;
+ };
+
+ reserved-memory {
+ memory@9d400000 {
+ reg = <0x0 0x9d400000 0x0 0x02400000>;
+ no-map;
+ };
+
+ memory@a1300000 {
+ compatible = "ramoops";
+ reg = <0x0 0xa1300000 0x0 0x100000>;
+ record-size = <0x40000>;
+ console-size = <0x40000>;
+ ftrace-size = <0x40000>;
+ pmsg-size = <0x40000>;
+ };
+ };
+};
+
+
+&apps_rsc {
+ pm8998-rpmh-regulators {
+ compatible = "qcom,pm8998-rpmh-regulators";
+ qcom,pmic-id = "a";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+ vdd-s4-supply = <&vph_pwr>;
+ vdd-s5-supply = <&vph_pwr>;
+ vdd-s6-supply = <&vph_pwr>;
+ vdd-s7-supply = <&vph_pwr>;
+ vdd-s8-supply = <&vph_pwr>;
+ vdd-s9-supply = <&vph_pwr>;
+ vdd-s10-supply = <&vph_pwr>;
+ vdd-s11-supply = <&vph_pwr>;
+ vdd-s12-supply = <&vph_pwr>;
+ vdd-s13-supply = <&vph_pwr>;
+ vdd-l1-l27-supply = <&vreg_s7a_1p025>;
+ vdd-l2-l8-l17-supply = <&vreg_s3a_1p35>;
+ vdd-l3-l11-supply = <&vreg_s7a_1p025>;
+ vdd-l4-l5-supply = <&vreg_s7a_1p025>;
+ vdd-l6-supply = <&vph_pwr>;
+ vdd-l7-l12-l14-l15-supply = <&vreg_s5a_2p04>;
+ vdd-l26-supply = <&vreg_s3a_1p35>;
+ vin-lvs-1-2-supply = <&vreg_s4a_1p8>;
+
+ vreg_s2a_1p125: smps2 {
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1100000>;
+ };
+
+ vreg_s3a_1p35: smps3 {
+ regulator-min-microvolt = <1352000>;
+ regulator-max-microvolt = <1352000>;
+ };
+
+ vreg_s5a_2p04: smps5 {
+ regulator-min-microvolt = <1904000>;
+ regulator-max-microvolt = <2040000>;
+ };
+
+ vreg_s7a_1p025: smps7 {
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <1028000>;
+ };
+
+ vdd_qusb_hs0:
+ vdda_hp_pcie_core:
+ vdda_mipi_csi0_0p9:
+ vdda_mipi_csi1_0p9:
+ vdda_mipi_csi2_0p9:
+ vdda_mipi_dsi0_pll:
+ vdda_mipi_dsi1_pll:
+ vdda_qlink_lv:
+ vdda_qlink_lv_ck:
+ vdda_qrefs_0p875:
+ vdda_pcie_core:
+ vdda_pll_cc_ebi01:
+ vdda_pll_cc_ebi23:
+ vdda_sp_sensor:
+ vdda_ufs1_core:
+ vdda_ufs2_core:
+ vdda_usb1_ss_core:
+ vdda_usb2_ss_core:
+ vreg_l1a_0p875: ldo1 {
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vddpx_10:
+ vreg_l2a_1p2: ldo2 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-always-on;
+ };
+
+ vreg_l3a_1p0: ldo3 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_wcss_cx:
+ vdd_wcss_mx:
+ vdda_wcss_pll:
+ vreg_l5a_0p8: ldo5 {
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vddpx_13:
+ vreg_l6a_1p8: ldo6 {
+ regulator-min-microvolt = <1856000>;
+ regulator-max-microvolt = <1856000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l7a_1p8: ldo7 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l8a_1p2: ldo8 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1248000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l9a_1p8: ldo9 {
+ regulator-min-microvolt = <1704000>;
+ regulator-max-microvolt = <2928000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l10a_1p8: ldo10 {
+ regulator-min-microvolt = <1704000>;
+ regulator-max-microvolt = <2928000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l11a_1p0: ldo11 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1048000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdd_qfprom:
+ vdd_qfprom_sp:
+ vdda_apc1_cs_1p8:
+ vdda_gfx_cs_1p8:
+ vdda_qrefs_1p8:
+ vdda_qusb_hs0_1p8:
+ vddpx_11:
+ vreg_l12a_1p8: ldo12 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vddpx_2:
+ vreg_l13a_2p95: ldo13 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l14a_1p88: ldo14 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l15a_1p8: ldo15 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l16a_2p7: ldo16 {
+ regulator-min-microvolt = <2704000>;
+ regulator-max-microvolt = <2704000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l17a_1p3: ldo17 {
+ regulator-min-microvolt = <1304000>;
+ regulator-max-microvolt = <1304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l18a_2p7: ldo18 {
+ regulator-min-microvolt = <2704000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l19a_3p0: ldo19 {
+ regulator-min-microvolt = <2856000>;
+ regulator-max-microvolt = <3104000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l20a_2p95: ldo20 {
+ regulator-min-microvolt = <2704000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l21a_2p95: ldo21 {
+ regulator-min-microvolt = <2704000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l22a_2p85: ldo22 {
+ regulator-min-microvolt = <2864000>;
+ regulator-max-microvolt = <3312000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l23a_3p3: ldo23 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3312000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdda_qusb_hs0_3p1:
+ vreg_l24a_3p075: ldo24 {
+ regulator-min-microvolt = <3088000>;
+ regulator-max-microvolt = <3088000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l25a_3p3: ldo25 {
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3312000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vdda_hp_pcie_1p2:
+ vdda_hv_ebi0:
+ vdda_hv_ebi1:
+ vdda_hv_ebi2:
+ vdda_hv_ebi3:
+ vdda_mipi_csi_1p25:
+ vdda_mipi_dsi0_1p2:
+ vdda_mipi_dsi1_1p2:
+ vdda_pcie_1p2:
+ vdda_ufs1_1p2:
+ vdda_ufs2_1p2:
+ vdda_usb1_ss_1p2:
+ vdda_usb2_ss_1p2:
+ vreg_l26a_1p2: ldo26 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_l28a_3p0: ldo28 {
+ regulator-min-microvolt = <2856000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_lvs1a_1p8: lvs1 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ vreg_lvs2a_1p8: lvs2 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+ };
+
+ pm8005-rpmh-regulators {
+ compatible = "qcom,pm8005-rpmh-regulators";
+ qcom,pmic-id = "c";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+ vdd-s4-supply = <&vph_pwr>;
+
+ vreg_s3c_0p6: smps3 {
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <600000>;
+ };
+ };
+};
+
+&gcc {
+ protected-clocks = <GCC_QSPI_CORE_CLK>,
+ <GCC_QSPI_CORE_CLK_SRC>,
+ <GCC_QSPI_CNOC_PERIPH_AHB_CLK>,
+ <GCC_LPASS_Q6_AXI_CLK>,
+ <GCC_LPASS_SWAY_CLK>;
+};
+
+&i2c10 {
+ clock-frequency = <400000>;
+ status = "okay";
+};
+
+&qupv3_id_1 {
+ status = "okay";
+};
+
+&uart9 {
+ status = "okay";
+};
+
+&ufs_mem_hc {
+ reset-gpios = <&tlmm 150 GPIO_ACTIVE_LOW>;
+ vcc-supply = <&vreg_l20a_2p95>;
+ vcc-max-microamp = <600000>;
+ status = "okay";
+};
+
+&ufs_mem_phy {
+ vdda-phy-supply = <&vdda_ufs1_core>;
+ vdda-pll-supply = <&vdda_ufs1_1p2>;
+ status = "okay";
+};
+
+&sdhc_2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdc2_clk_state &sdc2_cmd_state &sdc2_data_state &sd_card_det_n_state>;
+ cd-gpios = <&tlmm 126 GPIO_ACTIVE_LOW>;
+ vmmc-supply = <&vreg_l21a_2p95>;
+ vqmmc-supply = <&vddpx_2>;
+ status = "okay";
+};
+
+&usb_1 {
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ /* Until we have Type C hooked up we'll force this as peripheral. */
+ dr_mode = "peripheral";
+};
+
+&usb_1_hsphy {
+ vdd-supply = <&vdda_usb1_ss_core>;
+ vdda-pll-supply = <&vdda_qusb_hs0_1p8>;
+ vdda-phy-dpdm-supply = <&vdda_qusb_hs0_3p1>;
+
+ qcom,imp-res-offset-value = <8>;
+ qcom,hstx-trim-value = <QUSB2_V2_HSTX_TRIM_21_6_MA>;
+ qcom,preemphasis-level = <QUSB2_V2_PREEMPHASIS_5_PERCENT>;
+ qcom,preemphasis-width = <QUSB2_V2_PREEMPHASIS_WIDTH_HALF_BIT>;
+ status = "okay";
+};
+
+&usb_1_qmpphy {
+ vdda-phy-supply = <&vdda_usb1_ss_1p2>;
+ vdda-pll-supply = <&vdda_usb1_ss_core>;
+ status = "okay";
+};
+
+&wifi {
+ vdd-0.8-cx-mx-supply = <&vreg_l5a_0p8>;
+ vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
+ vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
+ vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
+ status = "okay";
+};
+
+&tlmm {
+ gpio-reserved-ranges = <0 4>, <27 4>, <81 4>, <85 4>;
+
+ sdc2_clk_state: sdc2-clk-state {
+ pins = "sdc2_clk";
+ bias-disable;
+
+ /*
+ * It seems that mmc_test reports errors if drive
+ * strength is not 16 on clk, cmd, and data pins.
+ */
+ drive-strength = <16>;
+ };
+
+ sdc2_cmd_state: sdc2-cmd-state {
+ pins = "sdc2_cmd";
+ bias-pull-up;
+ drive-strength = <16>;
+ };
+
+ sdc2_data_state: sdc2-data-state {
+ pins = "sdc2_data";
+ bias-pull-up;
+ drive-strength = <16>;
+ };
+
+ sd_card_det_n_state: sd-card-det-n-state {
+ pins = "gpio126";
+ function = "gpio";
+ bias-pull-up;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts b/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts
index 83261c9bb4f2..bb77ccfdc68c 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-shift-axolotl.dts
@@ -23,6 +23,7 @@
aliases {
display0 = &framebuffer0;
serial0 = &uart9;
+ serial1 = &uart6;
};
chosen {
@@ -693,9 +694,17 @@
&uart6 {
status = "okay";
+ pinctrl-0 = <&qup_uart6_4pin>;
+
bluetooth {
compatible = "qcom,wcn3990-bt";
+ /*
+ * This path is relative to the qca/
+ * subdir under lib/firmware.
+ */
+ firmware-name = "axolotl/crnv21.bin";
+
vddio-supply = <&vreg_s4a_1p8>;
vddxo-supply = <&vreg_l7a_1p8>;
vddrf-supply = <&vreg_l17a_1p3>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi
index 51ee42e3c995..87dd0fc36747 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sony-xperia-tama.dtsi
@@ -376,7 +376,7 @@
pinctrl-names = "default";
bus-width = <4>;
no-sdio;
- no-emmc;
+ no-mmc;
};
&tlmm {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium.dts b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
index 0f470cf1ed1c..eb6b2b676eca 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-common.dtsi
@@ -26,8 +26,6 @@
/delete-node/ &rmtfs_mem;
/ {
- model = "Xiaomi Pocophone F1";
- compatible = "xiaomi,beryllium", "qcom,sdm845";
chassis-type = "handset";
/* required for bootloader to select correct board */
@@ -35,7 +33,7 @@
qcom,msm-id = <321 0x20001>;
aliases {
- hsuart0 = &uart6;
+ serial1 = &uart6;
};
gpio-keys {
@@ -221,8 +219,7 @@
status = "okay";
vdda-supply = <&vreg_l26a_1p2>;
- panel@0 {
- compatible = "tianma,fhd-video";
+ display_panel: panel@0 {
reg = <0>;
vddio-supply = <&vreg_l14a_1p8>;
vddpos-supply = <&lab>;
@@ -234,8 +231,10 @@
backlight = <&pmi8998_wled>;
reset-gpios = <&tlmm 6 GPIO_ACTIVE_LOW>;
+ status = "disabled";
+
port {
- tianma_nt36672a_in_0: endpoint {
+ panel_in_0: endpoint {
remote-endpoint = <&dsi0_out>;
};
};
@@ -243,7 +242,7 @@
};
&dsi0_out {
- remote-endpoint = <&tianma_nt36672a_in_0>;
+ remote-endpoint = <&panel_in_0>;
data-lanes = <0 1 2 3>;
};
@@ -336,9 +335,13 @@
};
};
+&pmi8998_rradc {
+ status = "okay";
+};
+
/* QUAT I2S Uses 1 I2S SD Line for audio on TAS2559/60 amplifiers */
&q6afedai {
- qi2s@22 {
+ dai@22 {
reg = <QUATERNARY_MI2S_RX>;
qcom,sd-lines = <0>;
};
@@ -481,6 +484,8 @@
&uart6 {
status = "okay";
+ pinctrl-0 = <&qup_uart6_4pin>;
+
bluetooth {
compatible = "qcom,wcn3990-bt";
@@ -567,28 +572,3 @@
vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
vdd-3.3-ch1-supply = <&vreg_l23a_3p3>;
};
-
-/* PINCTRL - additions to nodes defined in sdm845.dtsi */
-
-&qup_uart6_default {
- pinmux {
- pins = "gpio45", "gpio46", "gpio47", "gpio48";
- function = "qup6";
- };
-
- cts {
- pins = "gpio45";
- bias-disable;
- };
-
- rts-tx {
- pins = "gpio46", "gpio47";
- drive-strength = <2>;
- bias-disable;
- };
-
- rx {
- pins = "gpio48";
- bias-pull-up;
- };
-};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-ebbg.dts b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-ebbg.dts
new file mode 100644
index 000000000000..76931ebad065
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-ebbg.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/dts-v1/;
+
+#include "sdm845-xiaomi-beryllium-common.dtsi"
+
+/ {
+ model = "Xiaomi Pocophone F1 (EBBG)";
+ compatible = "xiaomi,beryllium-ebbg", "qcom,sdm845";
+};
+
+&display_panel {
+ compatible = "ebbg,ft8719";
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-tianma.dts b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-tianma.dts
new file mode 100644
index 000000000000..8e176111e599
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-beryllium-tianma.dts
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/dts-v1/;
+
+#include "sdm845-xiaomi-beryllium-common.dtsi"
+
+/ {
+ model = "Xiaomi Pocophone F1 (Tianma)";
+ compatible = "xiaomi,beryllium", "qcom,sdm845";
+};
+
+&display_panel {
+ compatible = "tianma,fhd-video";
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts
index afc17e4d403f..38ba809a95cd 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts
+++ b/arch/arm64/boot/dts/qcom/sdm845-xiaomi-polaris.dts
@@ -456,9 +456,6 @@
&i2c14 {
clock-frequency = <400000>;
- dmas = <&gpi_dma1 0 6 QCOM_GPI_I2C>,
- <&gpi_dma1 1 6 QCOM_GPI_I2C>;
- dma-names = "tx", "rx";
status = "okay";
touchscreen@20 {
@@ -544,8 +541,8 @@
};
&q6afedai {
- qi2s@22 {
- reg = <22>;
+ dai@22 {
+ reg = <QUATERNARY_MI2S_RX>;
qcom,sd-lines = <0>;
};
};
@@ -628,7 +625,7 @@
};
wcd_intr_default: wcd-intr-default {
- pins = "goui54";
+ pins = "gpio54";
function = "gpio";
input-enable;
bias-pull-down;
@@ -639,6 +636,8 @@
&uart6 {
status = "okay";
+ pinctrl-0 = <&qup_uart6_4pin>;
+
bluetooth {
compatible = "qcom,wcn3990-bt";
@@ -735,28 +734,3 @@
qcom,snoc-host-cap-skip-quirk;
status = "okay";
};
-
-/* PINCTRL - additions to nodes defined in sdm845.dtsi */
-
-&qup_uart6_default {
- pinmux {
- pins = "gpio45", "gpio46", "gpio47", "gpio48";
- function = "qup6";
- };
-
- cts {
- pins = "gpio45";
- bias-disable;
- };
-
- rts-tx {
- pins = "gpio46", "gpio47";
- drive-strength = <2>;
- bias-disable;
- };
-
- rx {
- pins = "gpio48";
- bias-pull-up;
- };
-};
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index d761da47220d..65032b94b46d 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -767,13 +767,13 @@
#size-cells = <0>;
qcom,intents = <512 20>;
- apr-service@3 {
+ service@3 {
reg = <APR_SVC_ADSP_CORE>;
compatible = "qcom,q6core";
qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
};
- q6afe: apr-service@4 {
+ q6afe: service@4 {
compatible = "qcom,q6afe";
reg = <APR_SVC_AFE>;
qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
@@ -785,7 +785,7 @@
};
};
- q6asm: apr-service@7 {
+ q6asm: service@7 {
compatible = "qcom,q6asm";
reg = <APR_SVC_ASM>;
qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
@@ -798,7 +798,7 @@
};
};
- q6adm: apr-service@8 {
+ q6adm: service@8 {
compatible = "qcom,q6adm";
reg = <APR_SVC_ADM>;
qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
@@ -3008,6 +3008,28 @@
};
};
+ qup_uart6_4pin: qup-uart6-4pin-state {
+
+ cts-pins {
+ pins = "gpio45";
+ function = "qup6";
+ bias-pull-down;
+ };
+
+ rts-tx-pins {
+ pins = "gpio46", "gpio47";
+ function = "qup6";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ rx-pins {
+ pins = "gpio48";
+ function = "qup6";
+ bias-pull-up;
+ };
+ };
+
qup_uart7_default: qup-uart7-default {
pinmux {
pins = "gpio95", "gpio96";
@@ -3823,33 +3845,29 @@
status = "disabled";
};
- slim: slim@171c0000 {
+ slim: slim-ngd@171c0000 {
compatible = "qcom,slim-ngd-v2.1.0";
reg = <0 0x171c0000 0 0x2c000>;
interrupts = <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>;
- qcom,apps-ch-pipes = <0x780000>;
- qcom,ea-pc = <0x270>;
- status = "okay";
- dmas = <&slimbam 3>, <&slimbam 4>,
- <&slimbam 5>, <&slimbam 6>;
- dma-names = "rx", "tx", "tx2", "rx2";
+ dmas = <&slimbam 3>, <&slimbam 4>;
+ dma-names = "rx", "tx";
iommus = <&apps_smmu 0x1806 0x0>;
#address-cells = <1>;
#size-cells = <0>;
- ngd@1 {
+ slim@1 {
reg = <1>;
#address-cells = <2>;
#size-cells = <0>;
- wcd9340_ifd: ifd@0{
+ wcd9340_ifd: ifd@0,0 {
compatible = "slim217,250";
reg = <0 0>;
};
- wcd9340: codec@1{
+ wcd9340: codec@1,0 {
compatible = "slim217,250";
reg = <1 0>;
slim-ifc-dev = <&wcd9340_ifd>;
@@ -3959,9 +3977,10 @@
};
usb_1_qmpphy: phy@88e9000 {
- compatible = "qcom,sdm845-qmp-usb3-phy";
+ compatible = "qcom,sdm845-qmp-usb3-dp-phy";
reg = <0 0x088e9000 0 0x18c>,
- <0 0x088e8000 0 0x10>;
+ <0 0x088e8000 0 0x38>,
+ <0 0x088ea000 0 0x40>;
status = "disabled";
#address-cells = <2>;
#size-cells = <2>;
@@ -3973,11 +3992,11 @@
<&gcc GCC_USB3_PRIM_PHY_COM_AUX_CLK>;
clock-names = "aux", "cfg_ahb", "ref", "com_aux";
- resets = <&gcc GCC_USB3_DP_PHY_PRIM_BCR>,
- <&gcc GCC_USB3_PHY_PRIM_BCR>;
+ resets = <&gcc GCC_USB3_PHY_PRIM_BCR>,
+ <&gcc GCC_USB3_DP_PHY_PRIM_BCR>;
reset-names = "phy", "common";
- usb_1_ssphy: phy@88e9200 {
+ usb_1_ssphy: usb3-phy@88e9200 {
reg = <0 0x088e9200 0 0x128>,
<0 0x088e9400 0 0x200>,
<0 0x088e9c00 0 0x218>,
@@ -3990,6 +4009,16 @@
clock-names = "pipe0";
clock-output-names = "usb3_phy_pipe_clk_src";
};
+
+ dp_phy: dp-phy@88ea200 {
+ reg = <0 0x088ea200 0 0x200>,
+ <0 0x088ea400 0 0x200>,
+ <0 0x088eaa00 0 0x200>,
+ <0 0x088ea600 0 0x200>,
+ <0 0x088ea800 0 0x200>;
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+ };
};
usb_2_qmpphy: phy@88eb000 {
@@ -4339,6 +4368,22 @@
ports {
#address-cells = <1>;
#size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ };
+
+ port@1 {
+ reg = <1>;
+ };
+
+ port@2 {
+ reg = <2>;
+ };
+
+ port@3 {
+ reg = <3>;
+ };
};
};
@@ -4483,13 +4528,20 @@
port@0 {
reg = <0>;
- dpu_intf1_out: endpoint {
- remote-endpoint = <&dsi0_in>;
+ dpu_intf0_out: endpoint {
+ remote-endpoint = <&dp_in>;
};
};
port@1 {
reg = <1>;
+ dpu_intf1_out: endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
dpu_intf2_out: endpoint {
remote-endpoint = <&dsi1_in>;
};
@@ -4521,6 +4573,77 @@
};
};
+ mdss_dp: displayport-controller@ae90000 {
+ status = "disabled";
+ compatible = "qcom,sdm845-dp";
+
+ reg = <0 0xae90000 0 0x200>,
+ <0 0xae90200 0 0x200>,
+ <0 0xae90400 0 0x600>,
+ <0 0xae90a00 0 0x600>,
+ <0 0xae91000 0 0x600>;
+
+ interrupt-parent = <&mdss>;
+ interrupts = <12>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_AUX_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_LINK_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_LINK_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK>;
+ clock-names = "core_iface", "core_aux", "ctrl_link",
+ "ctrl_link_iface", "stream_pixel";
+ #clock-cells = <1>;
+ assigned-clocks = <&dispcc DISP_CC_MDSS_DP_LINK_CLK_SRC>,
+ <&dispcc DISP_CC_MDSS_DP_PIXEL_CLK_SRC>;
+ assigned-clock-parents = <&dp_phy 0>, <&dp_phy 1>;
+ phys = <&dp_phy>;
+ phy-names = "dp";
+
+ operating-points-v2 = <&dp_opp_table>;
+ power-domains = <&rpmhpd SDM845_CX>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ port@0 {
+ reg = <0>;
+ dp_in: endpoint {
+ remote-endpoint = <&dpu_intf0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dp_out: endpoint { };
+ };
+ };
+
+ dp_opp_table: dp-opp-table {
+ compatible = "operating-points-v2";
+
+ opp-162000000 {
+ opp-hz = /bits/ 64 <162000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ };
+
+ opp-270000000 {
+ opp-hz = /bits/ 64 <270000000>;
+ required-opps = <&rpmhpd_opp_svs>;
+ };
+
+ opp-540000000 {
+ opp-hz = /bits/ 64 <540000000>;
+ required-opps = <&rpmhpd_opp_svs_l1>;
+ };
+
+ opp-810000000 {
+ opp-hz = /bits/ 64 <810000000>;
+ required-opps = <&rpmhpd_opp_nom>;
+ };
+ };
+ };
+
dsi0: dsi@ae94000 {
compatible = "qcom,mdss-dsi-ctrl";
reg = <0 0x0ae94000 0 0x400>;
@@ -4548,7 +4671,6 @@
power-domains = <&rpmhpd SDM845_CX>;
phys = <&dsi0_phy>;
- phy-names = "dsi";
status = "disabled";
@@ -4574,7 +4696,7 @@
};
};
- dsi0_phy: dsi-phy@ae94400 {
+ dsi0_phy: phy@ae94400 {
compatible = "qcom,dsi-phy-10nm";
reg = <0 0x0ae94400 0 0x200>,
<0 0x0ae94600 0 0x280>,
@@ -4620,7 +4742,6 @@
power-domains = <&rpmhpd SDM845_CX>;
phys = <&dsi1_phy>;
- phy-names = "dsi";
status = "disabled";
@@ -4646,7 +4767,7 @@
};
};
- dsi1_phy: dsi-phy@ae96400 {
+ dsi1_phy: phy@ae96400 {
compatible = "qcom,dsi-phy-10nm";
reg = <0 0x0ae96400 0 0x200>,
<0 0x0ae96600 0 0x280>,
@@ -4812,8 +4933,8 @@
<&dsi0_phy 1>,
<&dsi1_phy 0>,
<&dsi1_phy 1>,
- <0>,
- <0>;
+ <&dp_phy 0>,
+ <&dp_phy 1>;
clock-names = "bi_tcxo",
"gcc_disp_gpll0_clk_src",
"gcc_disp_gpll0_div_clk_src",
@@ -5197,7 +5318,7 @@
};
osm_l3: interconnect@17d41000 {
- compatible = "qcom,sdm845-osm-l3";
+ compatible = "qcom,sdm845-osm-l3", "qcom,osm-l3";
reg = <0 0x17d41000 0 0x1400>;
clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>;
diff --git a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
index be59a8ba9c1f..f32b7445f7c9 100644
--- a/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
+++ b/arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
@@ -487,8 +487,10 @@
};
&qup_i2c12_default {
- drive-strength = <2>;
- bias-disable;
+ pinmux {
+ drive-strength = <2>;
+ bias-disable;
+ };
};
&qup_uart6_default {
@@ -783,7 +785,7 @@
qcom,mbhc-headphone-vthreshold-microvolt = <50000>;
swm: swm@c85 {
- left_spkr: wsa8810-left{
+ left_spkr: speaker@0,3 {
compatible = "sdw10217211000";
reg = <0 3>;
powerdown-gpios = <&wcdgpio 1 GPIO_ACTIVE_HIGH>;
@@ -792,7 +794,7 @@
#sound-dai-cells = <0>;
};
- right_spkr: wsa8810-right{
+ right_spkr: speaker@0,4 {
compatible = "sdw10217211000";
powerdown-gpios = <&wcdgpio 2 GPIO_ACTIVE_HIGH>;
reg = <0 4>;
diff --git a/arch/arm64/boot/dts/qcom/sdm850-samsung-w737.dts b/arch/arm64/boot/dts/qcom/sdm850-samsung-w737.dts
index f954fe5cb61a..daca1e0ad62a 100644
--- a/arch/arm64/boot/dts/qcom/sdm850-samsung-w737.dts
+++ b/arch/arm64/boot/dts/qcom/sdm850-samsung-w737.dts
@@ -43,7 +43,7 @@
#size-cells = <2>;
ranges;
- // Firmware initialized the display at 1280p instead of 1440p
+ /* Firmware initialized the display at 1280p instead of 1440p */
framebuffer0: framebuffer@80400000 {
compatible = "simple-framebuffer";
reg = <0 0x80400000 0 (1920 * 1280 * 4)>;
@@ -124,7 +124,7 @@
};
&adsp_pas {
- firmware-name = "qcom/samsung/w737/qcadsp850.mbn";
+ firmware-name = "qcom/sdm850/samsung/w737/qcadsp850.mbn";
status = "okay";
};
@@ -336,7 +336,7 @@
};
&cdsp_pas {
- firmware-name = "qcom/samsung/w737/qccdsp850.mbn";
+ firmware-name = "qcom/sdm850/samsung/w737/qccdsp850.mbn";
status = "okay";
};
@@ -385,7 +385,7 @@
&ipa {
status = "okay";
memory-region = <&ipa_fw_mem>;
- firmware-name = "qcom/samsung/w737/ipa_fws.elf";
+ firmware-name = "qcom/sdm850/samsung/w737/ipa_fws.elf";
};
/* No idea why it causes an SError when enabled */
@@ -395,7 +395,7 @@
&mss_pil {
status = "okay";
- firmware-name = "qcom/samsung/w737/qcdsp1v2850.mbn", "qcom/samsung/w737/qcdsp2850.mbn";
+ firmware-name = "qcom/sdm850/samsung/w737/qcdsp1v2850.mbn", "qcom/sdm850/samsung/w737/qcdsp2850.mbn";
};
&qup_i2c10_default {
@@ -415,8 +415,10 @@
};
&qup_i2c12_default {
- drive-strength = <2>;
- bias-disable;
+ pinmux {
+ drive-strength = <2>;
+ bias-disable;
+ };
};
&qup_uart6_default {
@@ -574,7 +576,7 @@
};
pen_rst_l: pen-rst-l {
- pinmux {
+ pinmux {
pins = "gpio21";
function = "gpio";
};
@@ -696,7 +698,7 @@
&venus {
status = "okay";
- firmware-name = "qcom/samsung/w737/qcvss850.mbn";
+ firmware-name = "qcom/sdm850/samsung/w737/qcvss850.mbn";
};
&wcd9340{
@@ -715,7 +717,7 @@
qcom,mbhc-headphone-vthreshold-microvolt = <50000>;
swm: swm@c85 {
- left_spkr: wsa8810-left{
+ left_spkr: speaker@0,3 {
compatible = "sdw10217211000";
reg = <0 3>;
powerdown-gpios = <&wcdgpio 1 GPIO_ACTIVE_HIGH>;
@@ -724,7 +726,7 @@
#sound-dai-cells = <0>;
};
- right_spkr: wsa8810-right{
+ right_spkr: speaker@0,4 {
compatible = "sdw10217211000";
powerdown-gpios = <&wcdgpio 2 GPIO_ACTIVE_HIGH>;
reg = <0 4>;
diff --git a/arch/arm64/boot/dts/qcom/sm4250-oneplus-billie2.dts b/arch/arm64/boot/dts/qcom/sm4250-oneplus-billie2.dts
new file mode 100644
index 000000000000..a3f1c7c41fd7
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm4250-oneplus-billie2.dts
@@ -0,0 +1,241 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2021, Iskren Chernev <iskren.chernev@gmail.com>
+ */
+
+/dts-v1/;
+
+#include "sm4250.dtsi"
+
+/ {
+ model = "OnePlus Nord N100";
+ compatible = "oneplus,billie2", "qcom,sm4250";
+
+ /* required for bootloader to select correct board */
+ qcom,msm-id = <0x1a1 0x10000 0x1bc 0x10000>;
+ qcom,board-id = <0x1000b 0x00>;
+
+ aliases {
+ };
+
+ chosen {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ stdout-path = "framebuffer0";
+
+ framebuffer0: framebuffer@9d400000 {
+ compatible = "simple-framebuffer";
+ reg = <0 0x5c000000 0 (1600 * 720 * 4)>;
+ width = <720>;
+ height = <1600>;
+ stride = <(720 * 4)>;
+ format = "a8r8g8b8";
+ };
+ };
+};
+
+&reserved_memory {
+ bootloader_log_mem: memory@5fff7000 {
+ reg = <0x0 0x5fff7000 0x0 0x8000>;
+ no-map;
+ };
+
+ ramoops@cbe00000 {
+ compatible = "ramoops";
+ reg = <0x0 0xcbe00000 0x0 0x400000>;
+ record-size = <0x40000>;
+ pmsg-size = <0x200000>;
+ console-size = <0x40000>;
+ ftrace-size = <0x40000>;
+ };
+
+ param_mem: memory@cc200000 {
+ reg = <0x0 0xcc200000 0x0 0x100000>;
+ no-map;
+ };
+
+ mtp_mem: memory@cc300000 {
+ reg = <0x00 0xcc300000 0x00 0xb00000>;
+ no-map;
+ };
+};
+
+&rpm_requests {
+ regulators-0 {
+ compatible = "qcom,rpm-pm6125-regulators";
+
+ vreg_s6a: s6 {
+ regulator-min-microvolt = <320000>;
+ regulator-max-microvolt = <1456000>;
+ };
+
+ vreg_s7a: s7 {
+ regulator-min-microvolt = <1280000>;
+ regulator-max-microvolt = <2040000>;
+ };
+
+ vreg_s8a: s8 {
+ regulator-min-microvolt = <1064000>;
+ regulator-max-microvolt = <1304000>;
+ };
+
+ vreg_l1a: l1 {
+ regulator-min-microvolt = <952000>;
+ regulator-max-microvolt = <1152000>;
+ };
+
+ vreg_l4a: l4 {
+ regulator-min-microvolt = <488000>;
+ regulator-max-microvolt = <1000000>;
+ };
+
+ vreg_l5a: l5 {
+ regulator-min-microvolt = <1648000>;
+ regulator-max-microvolt = <3056000>;
+ };
+
+ vreg_l6a: l6 {
+ regulator-min-microvolt = <576000>;
+ regulator-max-microvolt = <656000>;
+ };
+
+ vreg_l7a: l7 {
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1304000>;
+ };
+
+ vreg_l8a: l8 {
+ regulator-min-microvolt = <400000>;
+ regulator-max-microvolt = <728000>;
+ };
+
+ vreg_l9a: l9 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2000000>;
+ };
+
+ vreg_l10a: l10 {
+ regulator-min-microvolt = <1704000>;
+ regulator-max-microvolt = <1904000>;
+ };
+
+ vreg_l11a: l11 {
+ regulator-min-microvolt = <1704000>;
+ regulator-max-microvolt = <1952000>;
+ };
+
+ vreg_l12a: l12 {
+ regulator-min-microvolt = <1624000>;
+ regulator-max-microvolt = <1984000>;
+ };
+
+ vreg_l13a: l13 {
+ regulator-min-microvolt = <1504000>;
+ regulator-max-microvolt = <1952000>;
+ };
+
+ vreg_l14a: l14 {
+ regulator-min-microvolt = <1704000>;
+ regulator-max-microvolt = <1904000>;
+ };
+
+ vreg_l15a: l15 {
+ regulator-min-microvolt = <2920000>;
+ regulator-max-microvolt = <3232000>;
+ };
+
+ vreg_l16a: l16 {
+ regulator-min-microvolt = <1704000>;
+ regulator-max-microvolt = <1904000>;
+ };
+
+ vreg_l17a: l17 {
+ regulator-min-microvolt = <1152000>;
+ regulator-max-microvolt = <1304000>;
+ };
+
+ vreg_l18a: l18 {
+ regulator-min-microvolt = <1104000>;
+ regulator-max-microvolt = <1304000>;
+ };
+
+ vreg_l19a: l19 {
+ regulator-min-microvolt = <1624000>;
+ regulator-max-microvolt = <3304000>;
+ };
+
+ vreg_l20a: l20 {
+ regulator-min-microvolt = <1624000>;
+ regulator-max-microvolt = <3304000>;
+ };
+
+ vreg_l21a: l21 {
+ regulator-min-microvolt = <2400000>;
+ regulator-max-microvolt = <3544000>;
+ };
+
+ vreg_l22a: l22 {
+ regulator-min-microvolt = <2952000>;
+ regulator-max-microvolt = <3304000>;
+ };
+
+ vreg_l23a: l23 {
+ regulator-min-microvolt = <3296000>;
+ regulator-max-microvolt = <3304000>;
+ };
+
+ vreg_l24a: l24 {
+ regulator-min-microvolt = <2704000>;
+ regulator-max-microvolt = <3544000>;
+ };
+ };
+};
+
+&sleep_clk {
+ clock-frequency = <32764>;
+};
+
+&sdhc_2 {
+ vmmc-supply = <&vreg_l22a>;
+ vqmmc-supply = <&vreg_l5a>;
+
+ cd-gpios = <&tlmm 88 GPIO_ACTIVE_HIGH>;
+
+ status = "okay";
+};
+
+&tlmm {
+ gpio-reserved-ranges = <14 4>;
+};
+
+&ufs_mem_hc {
+ vcc-supply = <&vreg_l24a>;
+ vcc-max-microamp = <600000>;
+ vccq2-supply = <&vreg_l11a>;
+ vccq2-max-microamp = <600000>;
+ status = "okay";
+};
+
+&ufs_mem_phy {
+ vdda-phy-supply = <&vreg_l4a>;
+ vdda-pll-supply = <&vreg_l12a>;
+ vddp-ref-clk-supply = <&vreg_l18a>;
+ status = "okay";
+};
+
+&usb_1 {
+ status = "okay";
+};
+
+&usb_1_hsphy {
+ vdd-supply = <&vreg_l4a>;
+ vdda-pll-supply = <&vreg_l12a>;
+ vdda-phy-dpdm-supply = <&vreg_l15a>;
+ status = "okay";
+};
+
+&xo_board {
+ clock-frequency = <19200000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sm4250.dtsi b/arch/arm64/boot/dts/qcom/sm4250.dtsi
new file mode 100644
index 000000000000..c5add8f44fc0
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm4250.dtsi
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2021, Iskren Chernev <iskren.chernev@gmail.com>
+ */
+
+#include "sm6115.dtsi"
+
+&CPU0 {
+ compatible = "qcom,kryo240";
+};
+
+&CPU1 {
+ compatible = "qcom,kryo240";
+};
+
+&CPU2 {
+ compatible = "qcom,kryo240";
+};
+
+&CPU3 {
+ compatible = "qcom,kryo240";
+};
+
+&CPU4 {
+ compatible = "qcom,kryo240";
+};
+
+&CPU5 {
+ compatible = "qcom,kryo240";
+};
+
+&CPU6 {
+ compatible = "qcom,kryo240";
+};
+
+&CPU7 {
+ compatible = "qcom,kryo240";
+};
diff --git a/arch/arm64/boot/dts/qcom/sm6115.dtsi b/arch/arm64/boot/dts/qcom/sm6115.dtsi
new file mode 100644
index 000000000000..572bf04adf90
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm6115.dtsi
@@ -0,0 +1,1425 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * Copyright (c) 2021, Iskren Chernev <iskren.chernev@gmail.com>
+ */
+
+#include <dt-bindings/clock/qcom,gcc-sm6115.h>
+#include <dt-bindings/clock/qcom,sm6115-dispcc.h>
+#include <dt-bindings/clock/qcom,rpmcc.h>
+#include <dt-bindings/dma/qcom-gpi.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/power/qcom-rpmpd.h>
+
+/ {
+ interrupt-parent = <&intc>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ chosen { };
+
+ clocks {
+ xo_board: xo-board {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+
+ sleep_clk: sleep-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+ };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ CPU0: cpu@0 {
+ device_type = "cpu";
+ compatible = "qcom,kryo260";
+ reg = <0x0 0x0>;
+ capacity-dmips-mhz = <1024>;
+ dynamic-power-coefficient = <100>;
+ enable-method = "psci";
+ next-level-cache = <&L2_0>;
+ qcom,freq-domain = <&cpufreq_hw 0>;
+ L2_0: l2-cache {
+ compatible = "cache";
+ cache-level = <2>;
+ };
+ };
+
+ CPU1: cpu@1 {
+ device_type = "cpu";
+ compatible = "qcom,kryo260";
+ reg = <0x0 0x1>;
+ capacity-dmips-mhz = <1024>;
+ dynamic-power-coefficient = <100>;
+ enable-method = "psci";
+ next-level-cache = <&L2_0>;
+ qcom,freq-domain = <&cpufreq_hw 0>;
+ };
+
+ CPU2: cpu@2 {
+ device_type = "cpu";
+ compatible = "qcom,kryo260";
+ reg = <0x0 0x2>;
+ capacity-dmips-mhz = <1024>;
+ dynamic-power-coefficient = <100>;
+ enable-method = "psci";
+ next-level-cache = <&L2_0>;
+ qcom,freq-domain = <&cpufreq_hw 0>;
+ };
+
+ CPU3: cpu@3 {
+ device_type = "cpu";
+ compatible = "qcom,kryo260";
+ reg = <0x0 0x3>;
+ capacity-dmips-mhz = <1024>;
+ dynamic-power-coefficient = <100>;
+ enable-method = "psci";
+ next-level-cache = <&L2_0>;
+ qcom,freq-domain = <&cpufreq_hw 0>;
+ };
+
+ CPU4: cpu@100 {
+ device_type = "cpu";
+ compatible = "qcom,kryo260";
+ reg = <0x0 0x100>;
+ enable-method = "psci";
+ capacity-dmips-mhz = <1638>;
+ dynamic-power-coefficient = <282>;
+ next-level-cache = <&L2_1>;
+ qcom,freq-domain = <&cpufreq_hw 1>;
+ L2_1: l2-cache {
+ compatible = "cache";
+ cache-level = <2>;
+ };
+ };
+
+ CPU5: cpu@101 {
+ device_type = "cpu";
+ compatible = "qcom,kryo260";
+ reg = <0x0 0x101>;
+ capacity-dmips-mhz = <1638>;
+ dynamic-power-coefficient = <282>;
+ enable-method = "psci";
+ next-level-cache = <&L2_1>;
+ qcom,freq-domain = <&cpufreq_hw 1>;
+ };
+
+ CPU6: cpu@102 {
+ device_type = "cpu";
+ compatible = "qcom,kryo260";
+ reg = <0x0 0x102>;
+ capacity-dmips-mhz = <1638>;
+ dynamic-power-coefficient = <282>;
+ enable-method = "psci";
+ next-level-cache = <&L2_1>;
+ qcom,freq-domain = <&cpufreq_hw 1>;
+ };
+
+ CPU7: cpu@103 {
+ device_type = "cpu";
+ compatible = "qcom,kryo260";
+ reg = <0x0 0x103>;
+ capacity-dmips-mhz = <1638>;
+ dynamic-power-coefficient = <282>;
+ enable-method = "psci";
+ next-level-cache = <&L2_1>;
+ qcom,freq-domain = <&cpufreq_hw 1>;
+ };
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&CPU0>;
+ };
+
+ core1 {
+ cpu = <&CPU1>;
+ };
+
+ core2 {
+ cpu = <&CPU2>;
+ };
+
+ core3 {
+ cpu = <&CPU3>;
+ };
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&CPU4>;
+ };
+
+ core1 {
+ cpu = <&CPU5>;
+ };
+
+ core2 {
+ cpu = <&CPU6>;
+ };
+
+ core3 {
+ cpu = <&CPU7>;
+ };
+ };
+ };
+ };
+
+ firmware {
+ scm: scm {
+ compatible = "qcom,scm-sm6115", "qcom,scm";
+ #reset-cells = <1>;
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ /* We expect the bootloader to fill in the size */
+ reg = <0 0x80000000 0 0>;
+ };
+
+ pmu {
+ compatible = "arm,armv8-pmuv3";
+ interrupts = <GIC_PPI 6 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
+ reserved_memory: reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ hyp_mem: memory@45700000 {
+ reg = <0x0 0x45700000 0x0 0x600000>;
+ no-map;
+ };
+
+ xbl_aop_mem: memory@45e00000 {
+ reg = <0x0 0x45e00000 0x0 0x140000>;
+ no-map;
+ };
+
+ sec_apps_mem: memory@45fff000 {
+ reg = <0x0 0x45fff000 0x0 0x1000>;
+ no-map;
+ };
+
+ smem_mem: memory@46000000 {
+ compatible = "qcom,smem";
+ reg = <0x0 0x46000000 0x0 0x200000>;
+ no-map;
+
+ hwlocks = <&tcsr_mutex 3>;
+ qcom,rpm-msg-ram = <&rpm_msg_ram>;
+ };
+
+ cdsp_sec_mem: memory@46200000 {
+ reg = <0x0 0x46200000 0x0 0x1e00000>;
+ no-map;
+ };
+
+ pil_modem_mem: memory@4ab00000 {
+ reg = <0x0 0x4ab00000 0x0 0x6900000>;
+ no-map;
+ };
+
+ pil_video_mem: memory@51400000 {
+ reg = <0x0 0x51400000 0x0 0x500000>;
+ no-map;
+ };
+
+ wlan_msa_mem: memory@51900000 {
+ reg = <0x0 0x51900000 0x0 0x100000>;
+ no-map;
+ };
+
+ pil_cdsp_mem: memory@51a00000 {
+ reg = <0x0 0x51a00000 0x0 0x1e00000>;
+ no-map;
+ };
+
+ pil_adsp_mem: memory@53800000 {
+ reg = <0x0 0x53800000 0x0 0x2800000>;
+ no-map;
+ };
+
+ pil_ipa_fw_mem: memory@56100000 {
+ reg = <0x0 0x56100000 0x0 0x10000>;
+ no-map;
+ };
+
+ pil_ipa_gsi_mem: memory@56110000 {
+ reg = <0x0 0x56110000 0x0 0x5000>;
+ no-map;
+ };
+
+ pil_gpu_mem: memory@56115000 {
+ reg = <0x0 0x56115000 0x0 0x2000>;
+ no-map;
+ };
+
+ cont_splash_memory: memory@5c000000 {
+ reg = <0x0 0x5c000000 0x0 0x00f00000>;
+ no-map;
+ };
+
+ dfps_data_memory: memory@5cf00000 {
+ reg = <0x0 0x5cf00000 0x0 0x0100000>;
+ no-map;
+ };
+
+ removed_mem: memory@60000000 {
+ reg = <0x0 0x60000000 0x0 0x3900000>;
+ no-map;
+ };
+ };
+
+ rpm-glink {
+ compatible = "qcom,glink-rpm";
+
+ interrupts = <GIC_SPI 194 IRQ_TYPE_EDGE_RISING>;
+ qcom,rpm-msg-ram = <&rpm_msg_ram>;
+ mboxes = <&apcs_glb 0>;
+
+ rpm_requests: rpm-requests {
+ compatible = "qcom,rpm-sm6115";
+ qcom,glink-channels = "rpm_requests";
+
+ rpmcc: clock-controller {
+ compatible = "qcom,rpmcc-sm6115", "qcom,rpmcc";
+ #clock-cells = <1>;
+ };
+
+ rpmpd: power-controller {
+ compatible = "qcom,sm6115-rpmpd";
+ #power-domain-cells = <1>;
+ operating-points-v2 = <&rpmpd_opp_table>;
+
+ rpmpd_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ rpmpd_opp_min_svs: opp1 {
+ opp-level = <RPM_SMD_LEVEL_MIN_SVS>;
+ };
+
+ rpmpd_opp_low_svs: opp2 {
+ opp-level = <RPM_SMD_LEVEL_LOW_SVS>;
+ };
+
+ rpmpd_opp_svs: opp3 {
+ opp-level = <RPM_SMD_LEVEL_SVS>;
+ };
+
+ rpmpd_opp_svs_plus: opp4 {
+ opp-level = <RPM_SMD_LEVEL_SVS_PLUS>;
+ };
+
+ rpmpd_opp_nom: opp5 {
+ opp-level = <RPM_SMD_LEVEL_NOM>;
+ };
+
+ rpmpd_opp_nom_plus: opp6 {
+ opp-level = <RPM_SMD_LEVEL_NOM_PLUS>;
+ };
+
+ rpmpd_opp_turbo: opp7 {
+ opp-level = <RPM_SMD_LEVEL_TURBO>;
+ };
+
+ rpmpd_opp_turbo_plus: opp8 {
+ opp-level = <RPM_SMD_LEVEL_TURBO_NO_CPR>;
+ };
+ };
+ };
+ };
+ };
+
+ soc: soc@0 {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0 0 0xffffffff>;
+
+ tcsr_mutex: hwlock@340000 {
+ compatible = "qcom,tcsr-mutex";
+ reg = <0x00340000 0x20000>;
+ #hwlock-cells = <1>;
+ };
+
+ tlmm: pinctrl@500000 {
+ compatible = "qcom,sm6115-tlmm";
+ reg = <0x00500000 0x400000>, <0x00900000 0x400000>, <0x00d00000 0x400000>;
+ reg-names = "west", "south", "east";
+ interrupts = <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-controller;
+ gpio-ranges = <&tlmm 0 0 121>;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+
+ qup_i2c0_default: qup-i2c0-default-state {
+ pins = "gpio0", "gpio1";
+ function = "qup0";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_i2c1_default: qup-i2c1-default-state {
+ pins = "gpio4", "gpio5";
+ function = "qup1";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_i2c2_default: qup-i2c2-default-state {
+ pins = "gpio6", "gpio7";
+ function = "qup2";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_i2c3_default: qup-i2c3-default-state {
+ pins = "gpio8", "gpio9";
+ function = "qup3";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_i2c4_default: qup-i2c4-default-state {
+ pins = "gpio12", "gpio13";
+ function = "qup4";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_i2c5_default: qup-i2c5-default-state {
+ pins = "gpio14", "gpio15";
+ function = "qup5";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_spi0_default: qup-spi0-default-state {
+ pins = "gpio0", "gpio1","gpio2", "gpio3";
+ function = "qup0";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_spi1_default: qup-spi1-default-state {
+ pins = "gpio4", "gpio5", "gpio69", "gpio70";
+ function = "qup1";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_spi2_default: qup-spi2-default-state {
+ pins = "gpio6", "gpio7", "gpio71", "gpio80";
+ function = "qup2";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_spi3_default: qup-spi3-default-state {
+ pins = "gpio8", "gpio9", "gpio10", "gpio11";
+ function = "qup3";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_spi4_default: qup-spi4-default-state {
+ pins = "gpio12", "gpio13", "gpio96", "gpio97";
+ function = "qup4";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_spi5_default: qup-spi5-default-state {
+ pins = "gpio14", "gpio15", "gpio16", "gpio17";
+ function = "qup5";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ sdc1_state_on: sdc1-on-state {
+ clk-pins {
+ pins = "sdc1_clk";
+ bias-disable;
+ drive-strength = <16>;
+ };
+
+ cmd-pins {
+ pins = "sdc1_cmd";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ data-pins {
+ pins = "sdc1_data";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ rclk-pins {
+ pins = "sdc1_rclk";
+ bias-pull-down;
+ };
+ };
+
+ sdc1_state_off: sdc1-off-state {
+ clk-pins {
+ pins = "sdc1_clk";
+ bias-disable;
+ drive-strength = <2>;
+ };
+
+ cmd-pins {
+ pins = "sdc1_cmd";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+
+ data-pins {
+ pins = "sdc1_data";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+
+ rclk-pins {
+ pins = "sdc1_rclk";
+ bias-pull-down;
+ };
+ };
+
+ sdc2_state_on: sdc2-on-state {
+ clk-pins {
+ pins = "sdc2_clk";
+ bias-disable;
+ drive-strength = <16>;
+ };
+
+ cmd-pins {
+ pins = "sdc2_cmd";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ data-pins {
+ pins = "sdc2_data";
+ bias-pull-up;
+ drive-strength = <10>;
+ };
+
+ sd-cd-pins {
+ pins = "gpio88";
+ function = "gpio";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+ };
+
+ sdc2_state_off: sdc2-off-state {
+ clk-pins {
+ pins = "sdc2_clk";
+ bias-disable;
+ drive-strength = <2>;
+ };
+
+ cmd-pins {
+ pins = "sdc2_cmd";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+
+ data-pins {
+ pins = "sdc2_data";
+ bias-pull-up;
+ drive-strength = <2>;
+ };
+
+ sd-cd-pins {
+ pins = "gpio88";
+ function = "gpio";
+ bias-disable;
+ drive-strength = <2>;
+ };
+ };
+ };
+
+ gcc: clock-controller@1400000 {
+ compatible = "qcom,gcc-sm6115";
+ reg = <0x01400000 0x1f0000>;
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, <&sleep_clk>;
+ clock-names = "bi_tcxo", "sleep_clk";
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
+ usb_1_hsphy: phy@1613000 {
+ compatible = "qcom,sm6115-qusb2-phy";
+ reg = <0x01613000 0x180>;
+ #phy-cells = <0>;
+
+ clocks = <&gcc GCC_AHB2PHY_USB_CLK>, <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "cfg_ahb", "ref";
+
+ resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>;
+ nvmem-cells = <&qusb2_hstx_trim>;
+
+ status = "disabled";
+ };
+
+ qfprom@1b40000 {
+ compatible = "qcom,sm6115-qfprom", "qcom,qfprom";
+ reg = <0x01b40000 0x7000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ qusb2_hstx_trim: hstx-trim@25b {
+ reg = <0x25b 0x1>;
+ bits = <1 4>;
+ };
+ };
+
+ rng: rng@1b53000 {
+ compatible = "qcom,prng-ee";
+ reg = <0x01b53000 0x1000>;
+ clocks = <&gcc GCC_PRNG_AHB_CLK>;
+ clock-names = "core";
+ };
+
+ spmi_bus: spmi@1c40000 {
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0x01c40000 0x1100>,
+ <0x01e00000 0x2000000>,
+ <0x03e00000 0x100000>,
+ <0x03f00000 0xa0000>,
+ <0x01c0a000 0x26000>;
+ reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
+ interrupt-names = "periph_irq";
+ interrupts = <GIC_SPI 183 IRQ_TYPE_LEVEL_HIGH>;
+ qcom,ee = <0>;
+ qcom,channel = <0>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <4>;
+ };
+
+ tsens0: thermal-sensor@4410000 {
+ compatible = "qcom,sm6115-tsens", "qcom,tsens-v2";
+ reg = <0x04411000 0x1ff>, /* TM */
+ <0x04410000 0x8>; /* SROT */
+ #qcom,sensors = <16>;
+ interrupts = <GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "uplow", "critical";
+ #thermal-sensor-cells = <1>;
+ };
+
+ rpm_msg_ram: sram@45f0000 {
+ compatible = "qcom,rpm-msg-ram";
+ reg = <0x045f0000 0x7000>;
+ };
+
+ sram@4690000 {
+ compatible = "qcom,rpm-stats";
+ reg = <0x04690000 0x10000>;
+ };
+
+ sdhc_1: mmc@4744000 {
+ compatible = "qcom,sm6115-sdhci", "qcom,sdhci-msm-v5";
+ reg = <0x04744000 0x1000>, <0x04745000 0x1000>, <0x04748000 0x8000>;
+ reg-names = "hc", "cqhci", "ice";
+
+ interrupts = <GIC_SPI 348 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ clocks = <&gcc GCC_SDCC1_AHB_CLK>,
+ <&gcc GCC_SDCC1_APPS_CLK>,
+ <&xo_board>,
+ <&gcc GCC_SDCC1_ICE_CORE_CLK>;
+ clock-names = "iface", "core", "xo", "ice";
+
+ pinctrl-0 = <&sdc1_state_on>;
+ pinctrl-1 = <&sdc1_state_off>;
+ pinctrl-names = "default", "sleep";
+
+ bus-width = <8>;
+ status = "disabled";
+ };
+
+ sdhc_2: mmc@4784000 {
+ compatible = "qcom,sm6115-sdhci", "qcom,sdhci-msm-v5";
+ reg = <0x04784000 0x1000>;
+ reg-names = "hc";
+
+ interrupts = <GIC_SPI 350 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ clocks = <&gcc GCC_SDCC2_AHB_CLK>, <&gcc GCC_SDCC2_APPS_CLK>, <&xo_board>;
+ clock-names = "iface", "core", "xo";
+
+ pinctrl-0 = <&sdc2_state_on>;
+ pinctrl-1 = <&sdc2_state_off>;
+ pinctrl-names = "default", "sleep";
+
+ power-domains = <&rpmpd SM6115_VDDCX>;
+ operating-points-v2 = <&sdhc2_opp_table>;
+ iommus = <&apps_smmu 0x00a0 0x0>;
+ resets = <&gcc GCC_SDCC2_BCR>;
+
+ bus-width = <4>;
+ qcom,dll-config = <0x0007642c>;
+ qcom,ddr-config = <0x80040868>;
+ status = "disabled";
+
+ sdhc2_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ };
+
+ opp-202000000 {
+ opp-hz = /bits/ 64 <202000000>;
+ required-opps = <&rpmpd_opp_nom>;
+ };
+ };
+ };
+
+ ufs_mem_hc: ufs@4804000 {
+ compatible = "qcom,sm6115-ufshc", "qcom,ufshc", "jedec,ufs-2.0";
+ reg = <0x04804000 0x3000>, <0x04810000 0x8000>;
+ interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>;
+ phys = <&ufs_mem_phy_lanes>;
+ phy-names = "ufsphy";
+ lanes-per-direction = <1>;
+ #reset-cells = <1>;
+ resets = <&gcc GCC_UFS_PHY_BCR>;
+ reset-names = "rst";
+
+ power-domains = <&gcc GCC_UFS_PHY_GDSC>;
+ iommus = <&apps_smmu 0x100 0>;
+
+ clocks = <&gcc GCC_UFS_PHY_AXI_CLK>,
+ <&gcc GCC_SYS_NOC_UFS_PHY_AXI_CLK>,
+ <&gcc GCC_UFS_PHY_AHB_CLK>,
+ <&gcc GCC_UFS_PHY_UNIPRO_CORE_CLK>,
+ <&rpmcc RPM_SMD_XO_CLK_SRC>,
+ <&gcc GCC_UFS_PHY_TX_SYMBOL_0_CLK>,
+ <&gcc GCC_UFS_PHY_RX_SYMBOL_0_CLK>,
+ <&gcc GCC_UFS_PHY_ICE_CORE_CLK>;
+ clock-names = "core_clk",
+ "bus_aggr_clk",
+ "iface_clk",
+ "core_clk_unipro",
+ "ref_clk",
+ "tx_lane0_sync_clk",
+ "rx_lane0_sync_clk",
+ "ice_core_clk";
+
+ freq-table-hz = <50000000 200000000>,
+ <0 0>,
+ <0 0>,
+ <37500000 150000000>,
+ <75000000 300000000>,
+ <0 0>,
+ <0 0>,
+ <0 0>;
+
+ status = "disabled";
+ };
+
+ ufs_mem_phy: phy@4807000 {
+ compatible = "qcom,sm6115-qmp-ufs-phy";
+ reg = <0x04807000 0x1c4>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ clocks = <&gcc GCC_UFS_CLKREF_CLK>, <&gcc GCC_UFS_PHY_PHY_AUX_CLK>;
+ clock-names = "ref", "ref_aux";
+
+ resets = <&ufs_mem_hc 0>;
+ reset-names = "ufsphy";
+ status = "disabled";
+
+ ufs_mem_phy_lanes: phy@4807400 {
+ reg = <0x4807400 0x098>,
+ <0x4807600 0x130>,
+ <0x4807c00 0x16c>;
+ #phy-cells = <0>;
+ };
+ };
+
+ gpi_dma0: dma-controller@4a00000 {
+ compatible = "qcom,sm6115-gpi-dma", "qcom,sm6350-gpi-dma";
+ reg = <0x04a00000 0x60000>;
+ interrupts = <GIC_SPI 335 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 344 IRQ_TYPE_LEVEL_HIGH>;
+ dma-channels = <10>;
+ dma-channel-mask = <0xf>;
+ iommus = <&apps_smmu 0xf6 0x0>;
+ #dma-cells = <3>;
+ status = "disabled";
+ };
+
+ qupv3_id_0: geniqup@4ac0000 {
+ compatible = "qcom,geni-se-qup";
+ reg = <0x04ac0000 0x2000>;
+ clock-names = "m-ahb", "s-ahb";
+ clocks = <&gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+ <&gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ iommus = <&apps_smmu 0xe3 0x0>;
+ ranges;
+ status = "disabled";
+
+ i2c0: i2c@4a80000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x04a80000 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c0_default>;
+ interrupts = <GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 0 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 0 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi0: spi@4a80000 {
+ compatible = "qcom,geni-spi";
+ reg = <0x04a80000 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi0_default>;
+ interrupts = <GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 0 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 0 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c1: i2c@4a84000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x04a84000 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c1_default>;
+ interrupts = <GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 1 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 1 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi1: spi@4a84000 {
+ compatible = "qcom,geni-spi";
+ reg = <0x04a84000 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi1_default>;
+ interrupts = <GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 1 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 1 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@4a88000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x04a88000 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c2_default>;
+ interrupts = <GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 2 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 2 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi2: spi@4a88000 {
+ compatible = "qcom,geni-spi";
+ reg = <0x04a88000 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi2_default>;
+ interrupts = <GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 2 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 2 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c3: i2c@4a8c000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x04a8c000 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c3_default>;
+ interrupts = <GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 3 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 3 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi3: spi@4a8c000 {
+ compatible = "qcom,geni-spi";
+ reg = <0x04a8c000 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S3_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi3_default>;
+ interrupts = <GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 3 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 3 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c4: i2c@4a90000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x04a90000 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c4_default>;
+ interrupts = <GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 4 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 4 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi4: spi@4a90000 {
+ compatible = "qcom,geni-spi";
+ reg = <0x04a90000 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S4_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi4_default>;
+ interrupts = <GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 4 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 4 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c5: i2c@4a94000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x04a94000 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c5_default>;
+ interrupts = <GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 5 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 5 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi5: spi@4a94000 {
+ compatible = "qcom,geni-spi";
+ reg = <0x04a94000 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S5_CLK>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi5_default>;
+ interrupts = <GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma0 0 5 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 5 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+ };
+
+ usb_1: usb@4ef8800 {
+ compatible = "qcom,sm6115-dwc3", "qcom,dwc3";
+ reg = <0x04ef8800 0x400>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
+ <&gcc GCC_USB30_PRIM_MASTER_CLK>,
+ <&gcc GCC_SYS_NOC_USB3_PRIM_AXI_CLK>,
+ <&gcc GCC_USB30_PRIM_SLEEP_CLK>,
+ <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
+ <&gcc GCC_USB3_PRIM_CLKREF_CLK>;
+ clock-names = "cfg_noc", "core", "iface", "sleep", "mock_utmi", "xo";
+
+ assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
+ <&gcc GCC_USB30_PRIM_MASTER_CLK>;
+ assigned-clock-rates = <19200000>, <66666667>;
+
+ interrupts = <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hs_phy_irq", "ss_phy_irq";
+
+ resets = <&gcc GCC_USB30_PRIM_BCR>;
+ power-domains = <&gcc GCC_USB30_PRIM_GDSC>;
+ qcom,select-utmi-as-pipe-clk;
+ status = "disabled";
+
+ usb_1_dwc3: usb@4e00000 {
+ compatible = "snps,dwc3";
+ reg = <0x04e00000 0xcd00>;
+ interrupts = <GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH>;
+ phys = <&usb_1_hsphy>;
+ phy-names = "usb2-phy";
+ iommus = <&apps_smmu 0x120 0x0>;
+ snps,dis_u2_susphy_quirk;
+ snps,dis_enblslpm_quirk;
+ snps,has-lpm-erratum;
+ snps,hird-threshold = /bits/ 8 <0x10>;
+ snps,usb3_lpm_capable;
+ maximum-speed = "high-speed";
+ dr_mode = "peripheral";
+ };
+ };
+
+ mdss: display-subsystem@5e00000 {
+ compatible = "qcom,sm6115-mdss";
+ reg = <0x05e00000 0x1000>;
+ reg-names = "mdss";
+
+ power-domains = <&dispcc MDSS_GDSC>;
+
+ clocks = <&gcc GCC_DISP_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>;
+
+ interrupts = <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <1>;
+
+ iommus = <&apps_smmu 0x420 0x2>,
+ <&apps_smmu 0x421 0x0>;
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ status = "disabled";
+
+ mdp: display-controller@5e01000 {
+ compatible = "qcom,sm6115-dpu";
+ reg = <0x05e01000 0x8f000>,
+ <0x05eb0000 0x2008>;
+ reg-names = "mdp", "vbif";
+
+ clocks = <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_CLK>,
+ <&dispcc DISP_CC_MDSS_MDP_LUT_CLK>,
+ <&dispcc DISP_CC_MDSS_ROT_CLK>,
+ <&dispcc DISP_CC_MDSS_VSYNC_CLK>;
+ clock-names = "bus",
+ "iface",
+ "core",
+ "lut",
+ "rot",
+ "vsync";
+
+ operating-points-v2 = <&mdp_opp_table>;
+ power-domains = <&rpmpd SM6115_VDDCX>;
+
+ interrupt-parent = <&mdss>;
+ interrupts = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dpu_intf1_out: endpoint {
+ remote-endpoint = <&dsi0_in>;
+ };
+ };
+ };
+
+ mdp_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-19200000 {
+ opp-hz = /bits/ 64 <19200000>;
+ required-opps = <&rpmpd_opp_min_svs>;
+ };
+
+ opp-192000000 {
+ opp-hz = /bits/ 64 <192000000>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ };
+
+ opp-256000000 {
+ opp-hz = /bits/ 64 <256000000>;
+ required-opps = <&rpmpd_opp_svs>;
+ };
+
+ opp-307200000 {
+ opp-hz = /bits/ 64 <307200000>;
+ required-opps = <&rpmpd_opp_svs_plus>;
+ };
+
+ opp-384000000 {
+ opp-hz = /bits/ 64 <384000000>;
+ required-opps = <&rpmpd_opp_nom>;
+ };
+ };
+ };
+
+ dsi0: dsi@5e94000 {
+ compatible = "qcom,dsi-ctrl-6g-qcm2290";
+ reg = <0x05e94000 0x400>;
+ reg-names = "dsi_ctrl";
+
+ interrupt-parent = <&mdss>;
+ interrupts = <4>;
+
+ clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK>,
+ <&dispcc DISP_CC_MDSS_BYTE0_INTF_CLK>,
+ <&dispcc DISP_CC_MDSS_PCLK0_CLK>,
+ <&dispcc DISP_CC_MDSS_ESC0_CLK>,
+ <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>;
+ clock-names = "byte",
+ "byte_intf",
+ "pixel",
+ "core",
+ "iface",
+ "bus";
+
+ assigned-clocks = <&dispcc DISP_CC_MDSS_BYTE0_CLK_SRC>,
+ <&dispcc DISP_CC_MDSS_PCLK0_CLK_SRC>;
+ assigned-clock-parents = <&dsi0_phy 0>, <&dsi0_phy 1>;
+
+ operating-points-v2 = <&dsi_opp_table>;
+ power-domains = <&rpmpd SM6115_VDDCX>;
+ phys = <&dsi0_phy>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ status = "disabled";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dsi0_in: endpoint {
+ remote-endpoint = <&dpu_intf1_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ dsi0_out: endpoint {
+ };
+ };
+ };
+
+ dsi_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-19200000 {
+ opp-hz = /bits/ 64 <19200000>;
+ required-opps = <&rpmpd_opp_min_svs>;
+ };
+
+ opp-164000000 {
+ opp-hz = /bits/ 64 <164000000>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ };
+
+ opp-187500000 {
+ opp-hz = /bits/ 64 <187500000>;
+ required-opps = <&rpmpd_opp_svs>;
+ };
+ };
+ };
+
+ dsi0_phy: phy@5e94400 {
+ compatible = "qcom,dsi-phy-14nm-2290";
+ reg = <0x05e94400 0x100>,
+ <0x05e94500 0x300>,
+ <0x05e94800 0x188>;
+ reg-names = "dsi_phy",
+ "dsi_phy_lane",
+ "dsi_pll";
+
+ #clock-cells = <1>;
+ #phy-cells = <0>;
+
+ clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+ <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "iface", "ref";
+
+ status = "disabled";
+ };
+ };
+
+ dispcc: clock-controller@5f00000 {
+ compatible = "qcom,sm6115-dispcc";
+ reg = <0x05f00000 0x20000>;
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
+ <&sleep_clk>,
+ <&dsi0_phy 0>,
+ <&dsi0_phy 1>,
+ <&gcc GCC_DISP_GPLL0_DIV_CLK_SRC>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ };
+
+ apps_smmu: iommu@c600000 {
+ compatible = "qcom,sm6115-smmu-500", "qcom,smmu-500", "arm,mmu-500";
+ reg = <0x0c600000 0x80000>;
+ #iommu-cells = <2>;
+ #global-interrupts = <1>;
+
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ wifi: wifi@c800000 {
+ compatible = "qcom,wcn3990-wifi";
+ reg = <0x0c800000 0x800000>;
+ reg-names = "membase";
+ memory-region = <&wlan_msa_mem>;
+ interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 359 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 361 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 362 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 363 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 364 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 365 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 366 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 367 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 368 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 369 IRQ_TYPE_LEVEL_HIGH>;
+ iommus = <&apps_smmu 0x1a0 0x1>;
+ qcom,msa-fixed-perm;
+ status = "disabled";
+ };
+
+ apcs_glb: mailbox@f111000 {
+ compatible = "qcom,sm6115-apcs-hmss-global";
+ reg = <0x0f111000 0x1000>;
+
+ #mbox-cells = <1>;
+ };
+
+ timer@f120000 {
+ compatible = "arm,armv7-timer-mem";
+ reg = <0x0f120000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+ clock-frequency = <19200000>;
+
+ frame@f121000 {
+ reg = <0x0f121000 0x1000>, <0x0f122000 0x1000>;
+ frame-number = <0>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ frame@f123000 {
+ reg = <0x0f123000 0x1000>;
+ frame-number = <1>;
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ frame@f124000 {
+ reg = <0x0f124000 0x1000>;
+ frame-number = <2>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ frame@f125000 {
+ reg = <0x0f125000 0x1000>;
+ frame-number = <3>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ frame@f126000 {
+ reg = <0x0f126000 0x1000>;
+ frame-number = <4>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ frame@f127000 {
+ reg = <0x0f127000 0x1000>;
+ frame-number = <5>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+
+ frame@f128000 {
+ reg = <0x0f128000 0x1000>;
+ frame-number = <6>;
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ status = "disabled";
+ };
+ };
+
+ intc: interrupt-controller@f200000 {
+ compatible = "arm,gic-v3";
+ reg = <0x0f200000 0x10000>, <0x0f300000 0x100000>;
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ interrupt-parent = <&intc>;
+ #redistributor-regions = <1>;
+ redistributor-stride = <0x0 0x20000>;
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ };
+
+ cpufreq_hw: cpufreq@f521000 {
+ compatible = "qcom,cpufreq-hw";
+ reg = <0x0f521000 0x1000>, <0x0f523000 0x1000>;
+
+ reg-names = "freq-domain0", "freq-domain1";
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, <&gcc GPLL0>;
+ clock-names = "xo", "alternate";
+
+ #freq-domain-cells = <1>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 1 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 0 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts b/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts
index 6a8b88cc4385..0de6c5b7f742 100644
--- a/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts
+++ b/arch/arm64/boot/dts/qcom/sm6125-sony-xperia-seine-pdx201.dts
@@ -6,9 +6,10 @@
/dts-v1/;
#include "sm6125.dtsi"
+#include "pm6125.dtsi"
#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/input/input.h>
#include <dt-bindings/input/gpio-keys.h>
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
/ {
/* required for bootloader to select correct board */
@@ -80,15 +81,175 @@
no-map;
};
};
+
+ thermal-zones {
+ rf-pa0-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm6125_adc_tm 0>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ quiet-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <5000>;
+ thermal-sensors = <&pm6125_adc_tm 1>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ xo-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm6125_adc_tm 2>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ rf-pa1-thermal {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm6125_adc_tm 3>;
+
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+ };
};
&hsusb_phy1 {
status = "okay";
};
+&pm6125_adc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&camera_flash_therm &emmc_ufs_therm &rf_pa1_therm>;
+
+ rf-pa0-therm@4d {
+ reg = <ADC5_AMUX_THM1_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ quiet-therm@4e {
+ reg = <ADC5_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ camera-flash-therm@52 {
+ reg = <ADC5_GPIO1_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ emmc-ufs-therm@54 {
+ reg = <ADC5_GPIO3_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ };
+
+ rf-pa1-therm@55 {
+ reg = <ADC5_GPIO4_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time = <200>;
+ qcom,pre-scaling = <1 1>;
+ };
+};
+
+&pm6125_adc_tm {
+ status = "okay";
+
+ rf-pa0-therm@0 {
+ reg = <0>;
+ io-channels = <&pm6125_adc ADC5_AMUX_THM1_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+
+ quiet-therm@1 {
+ reg = <1>;
+ io-channels = <&pm6125_adc ADC5_AMUX_THM2_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+
+ xo-therm@2 {
+ reg = <2>;
+ io-channels = <&pm6125_adc ADC5_XO_THERM_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+
+ rf-pa1-therm@3 {
+ reg = <3>;
+ io-channels = <&pm6125_adc ADC5_GPIO4_100K_PU>;
+ qcom,ratiometric;
+ qcom,hw-settle-time-us = <200>;
+ };
+};
+
+&pm6125_gpio {
+ camera_flash_therm: camera-flash-therm-state {
+ pins = "gpio3";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ bias-high-impedance;
+ };
+
+ emmc_ufs_therm: emmc-ufs-therm-state {
+ pins = "gpio6";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ bias-high-impedance;
+ };
+
+ rf_pa1_therm: rf-pa1-therm-state {
+ pins = "gpio7";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ bias-high-impedance;
+ };
+};
+
+&pon_pwrkey {
+ status = "okay";
+};
+
+&pon_resin {
+ status = "okay";
+ linux,code = <KEY_VOLUMEUP>;
+};
+
&sdc2_off_state {
sd-cd-pins {
pins = "gpio98";
+ function = "gpio";
drive-strength = <2>;
bias-disable;
};
@@ -97,6 +258,7 @@
&sdc2_on_state {
sd-cd-pins {
pins = "gpio98";
+ function = "gpio";
drive-strength = <2>;
bias-pull-up;
};
diff --git a/arch/arm64/boot/dts/qcom/sm6125.dtsi b/arch/arm64/boot/dts/qcom/sm6125.dtsi
index 1fe3fa3ad877..7e25a4f85594 100644
--- a/arch/arm64/boot/dts/qcom/sm6125.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6125.dtsi
@@ -407,13 +407,13 @@
};
sdc2_on_state: sdc2-on-state {
- clk {
+ clk-pins {
pins = "sdc2_clk";
drive-strength = <16>;
bias-disable;
};
- cmd-pins-pins {
+ cmd-pins {
pins = "sdc2_cmd";
drive-strength = <10>;
bias-pull-up;
@@ -458,7 +458,7 @@
sdhc_1: mmc@4744000 {
compatible = "qcom,sm6125-sdhci", "qcom,sdhci-msm-v5";
reg = <0x04744000 0x1000>, <0x04745000 0x1000>;
- reg-names = "hc", "core";
+ reg-names = "hc", "cqhci";
interrupts = <GIC_SPI 348 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>;
@@ -476,6 +476,8 @@
bus-width = <8>;
non-removable;
+ supports-cqe;
+
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/qcom/sm6350-sony-xperia-lena-pdx213.dts b/arch/arm64/boot/dts/qcom/sm6350-sony-xperia-lena-pdx213.dts
index 36911b9a5c04..94f77d376662 100644
--- a/arch/arm64/boot/dts/qcom/sm6350-sony-xperia-lena-pdx213.dts
+++ b/arch/arm64/boot/dts/qcom/sm6350-sony-xperia-lena-pdx213.dts
@@ -4,7 +4,10 @@
*/
/dts-v1/;
+#include <dt-bindings/pinctrl/qcom,pmic-gpio.h>
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
#include "sm6350.dtsi"
+#include "pm6350.dtsi"
/ {
model = "Sony Xperia 10 III";
@@ -28,16 +31,348 @@
clocks = <&gcc GCC_DISP_AXI_CLK>;
};
};
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gpio_keys_state>;
+
+ key-volume-down {
+ label = "volume_down";
+ linux,code = <KEY_VOLUMEDOWN>;
+ gpios = <&pm6350_gpios 2 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ touch_en_vreg: touch-en-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "touch_en_vreg";
+ gpio = <&tlmm 10 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+
+ vin-supply = <&pm6350_l6>;
+ };
+};
+
+&apps_rsc {
+ regulators-0 {
+ compatible = "qcom,pm6350-rpmh-regulators";
+ qcom,pmic-id = "a";
+
+ pm6350_s1: smps1 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_s2: smps2 {
+ regulator-min-microvolt = <1503000>;
+ regulator-max-microvolt = <2048000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_l2: ldo2 {
+ regulator-min-microvolt = <1503000>;
+ regulator-max-microvolt = <1980000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_l3: ldo3 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_l4: ldo4 {
+ regulator-min-microvolt = <352000>;
+ regulator-max-microvolt = <801000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_l5: ldo5 {
+ regulator-min-microvolt = <1503000>;
+ regulator-max-microvolt = <1980000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_l6: ldo6 {
+ regulator-min-microvolt = <1710000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_l7: ldo7 {
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <1980000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_l8: ldo8 {
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_l9: ldo9 {
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <3401000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_l11: ldo11 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_l12: ldo12 {
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <1980000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_l13: ldo13 {
+ regulator-min-microvolt = <570000>;
+ regulator-max-microvolt = <650000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_l14: ldo14 {
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <1900000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_l15: ldo15 {
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1305000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_l16: ldo16 {
+ regulator-min-microvolt = <830000>;
+ regulator-max-microvolt = <921000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_l18: ldo18 {
+ regulator-min-microvolt = <788000>;
+ regulator-max-microvolt = <1049000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_l19: ldo19 {
+ regulator-min-microvolt = <1080000>;
+ regulator-max-microvolt = <1305000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_l20: ldo20 {
+ regulator-min-microvolt = <530000>;
+ regulator-max-microvolt = <801000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_l21: ldo21 {
+ regulator-min-microvolt = <751000>;
+ regulator-max-microvolt = <825000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6350_l22: ldo22 {
+ regulator-min-microvolt = <1080000>;
+ regulator-max-microvolt = <1305000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ regulators-1 {
+ compatible = "qcom,pm6150l-rpmh-regulators";
+ qcom,pmic-id = "e";
+
+ pm6150l_s8: smps8 {
+ regulator-min-microvolt = <313000>;
+ regulator-max-microvolt = <1395000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6150l_l1: ldo1 {
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <1980000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6150l_l2: ldo2 {
+ regulator-min-microvolt = <1170000>;
+ regulator-max-microvolt = <1305000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6150l_l3: ldo3 {
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1299000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6150l_l4: ldo4 {
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6150l_l5: ldo5 {
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6150l_l6: ldo6 {
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <2950000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+
+ };
+
+ pm6150l_l7: ldo7 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3544000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6150l_l8: ldo8 {
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6150l_l9: ldo9 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
+
+ };
+
+ pm6150l_l10: ldo10 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3401000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6150l_l11: ldo11 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3401000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm6150l_bob: bob {
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <5492000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>;
+ regulator-allow-bypass;
+ };
+ };
+};
+
+&gpi_dma0 {
+ status = "okay";
+};
+
+&gpi_dma1 {
+ status = "okay";
+};
+
+&i2c8 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ touchscreen@48 {
+ compatible = "samsung,s6sy761";
+ reg = <0x48>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <22 0x2008>;
+ vdd-supply = <&pm6350_l11>;
+ avdd-supply = <&touch_en_vreg>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&ts_int_default &ts_active>;
+ };
+};
+
+&pm6350_gpios {
+ gpio_keys_state: gpio-keys-state {
+ key-volume-down-pins {
+ pins = "gpio2";
+ function = PMIC_GPIO_FUNC_NORMAL;
+ power-source = <0>;
+ bias-disable;
+ input-enable;
+ };
+ };
+};
+
+&pm6350_resin {
+ linux,code = <KEY_VOLUMEUP>;
+ status = "okay";
+};
+
+&qupv3_id_0 {
+ status = "okay";
+};
+
+&qupv3_id_1 {
+ status = "okay";
+};
+
+&sdc2_off_state {
+ sd-cd-pins {
+ pins = "gpio94";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+};
+
+&sdc2_on_state {
+ sd-cd-pins {
+ pins = "gpio94";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
};
&sdhc_2 {
status = "okay";
+ vmmc-supply = <&pm6150l_l9>;
+ vqmmc-supply = <&pm6150l_l6>;
+
cd-gpios = <&tlmm 94 GPIO_ACTIVE_HIGH>;
};
&tlmm {
gpio-reserved-ranges = <13 4>, <45 2>, <56 2>;
+
+ ts_active: ts-active-state {
+ pins = "gpio21";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+
+ ts_int_default: ts-int-default-state {
+ pins = "gpio22";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ input-enable;
+ };
};
&usb_1 {
diff --git a/arch/arm64/boot/dts/qcom/sm6350.dtsi b/arch/arm64/boot/dts/qcom/sm6350.dtsi
index c39de7d3ace0..43324bf291c3 100644
--- a/arch/arm64/boot/dts/qcom/sm6350.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm6350.dtsi
@@ -485,11 +485,13 @@
interrupts = <GIC_SPI 641 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 644 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "hc_irq", "pwr_irq";
+ iommus = <&apps_smmu 0x60 0x0>;
clocks = <&gcc GCC_SDCC1_AHB_CLK>,
<&gcc GCC_SDCC1_APPS_CLK>,
<&rpmhcc RPMH_CXO_CLK>;
clock-names = "iface", "core", "xo";
+ resets = <&gcc GCC_SDCC1_BCR>;
qcom,dll-config = <0x000f642c>;
qcom,ddr-config = <0x80040868>;
power-domains = <&rpmhpd SM6350_CX>;
@@ -1063,15 +1065,21 @@
interrupts = <GIC_SPI 204 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 222 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "hc_irq", "pwr_irq";
+ iommus = <&apps_smmu 0x560 0x0>;
clocks = <&gcc GCC_SDCC2_AHB_CLK>,
<&gcc GCC_SDCC2_APPS_CLK>,
<&rpmhcc RPMH_CXO_CLK>;
clock-names = "iface", "core", "xo";
+ resets = <&gcc GCC_SDCC2_BCR>;
interconnects = <&aggre2_noc MASTER_SDCC_2 0 &clk_virt SLAVE_EBI_CH0 0>,
<&gem_noc MASTER_AMPSS_M0 0 &config_noc SLAVE_SDCC_2 0>;
interconnect-names = "sdhc-ddr", "cpu-sdhc";
+ pinctrl-0 = <&sdc2_on_state>;
+ pinctrl-1 = <&sdc2_off_state>;
+ pinctrl-names = "default", "sleep";
+
qcom,dll-config = <0x0007642c>;
qcom,ddr-config = <0x80040868>;
power-domains = <&rpmhpd SM6350_CX>;
@@ -1148,15 +1156,11 @@
dp_phy: dp-phy@88ea200 {
reg = <0 0x088ea200 0 0x200>,
<0 0x088ea400 0 0x200>,
- <0 0x088eac00 0 0x400>,
+ <0 0x088eaa00 0 0x200>,
<0 0x088ea600 0 0x200>,
- <0 0x088ea800 0 0x200>,
- <0 0x088eaa00 0 0x100>;
+ <0 0x088ea800 0 0x200>;
#phy-cells = <0>;
#clock-cells = <1>;
- clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
- clock-names = "pipe0";
- clock-output-names = "usb3_phy_pipe_clk_src";
};
};
@@ -1314,6 +1318,46 @@
#interrupt-cells = <2>;
gpio-ranges = <&tlmm 0 0 157>;
+ sdc2_off_state: sdc2-off-state {
+ clk-pins {
+ pins = "sdc2_clk";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ cmd-pins {
+ pins = "sdc2_cmd";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ data-pins {
+ pins = "sdc2_data";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ sdc2_on_state: sdc2-on-state {
+ clk-pins {
+ pins = "sdc2_clk";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ cmd-pins {
+ pins = "sdc2_cmd";
+ drive-strength = <10>;
+ bias-pull-up;
+ };
+
+ data-pins {
+ pins = "sdc2_data";
+ drive-strength = <10>;
+ bias-pull-up;
+ };
+ };
+
qup_uart9_default: qup-uart9-default-state {
pins = "gpio25", "gpio26";
function = "qup13_f2";
diff --git a/arch/arm64/boot/dts/qcom/sm6375-sony-xperia-murray-pdx225.dts b/arch/arm64/boot/dts/qcom/sm6375-sony-xperia-murray-pdx225.dts
new file mode 100644
index 000000000000..b691c3834b6b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm6375-sony-xperia-murray-pdx225.dts
@@ -0,0 +1,406 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2022, Konrad Dybcio <konrad.dybcio@somainline.org>
+ */
+
+/dts-v1/;
+
+/* PMK8350 is configured to use SID6 instead of 0 */
+#define PMK8350_SID 6
+
+#include <dt-bindings/gpio/gpio.h>
+#include "sm6375.dtsi"
+#include "pm6125.dtsi"
+#include "pmk8350.dtsi"
+#include "pmr735a.dtsi"
+
+/* PM6125 PON is used and we can't have duplicate labels */
+/delete-node/ &pmk8350_pon;
+
+/ {
+ model = "Sony Xperia 10 IV";
+ compatible = "sony,pdx225", "qcom,sm6375";
+ chassis-type = "handset";
+
+ chosen {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ framebuffer: framebuffer@85200000 {
+ compatible = "simple-framebuffer";
+ reg = <0 0x85200000 0 0xc00000>;
+
+ width = <1080>;
+ height = <2520>;
+ stride = <(1080 * 4)>;
+ format = "a8r8g8b8";
+ /*
+ * That's (going to be) a lot of clocks, but it's necessary due
+ * to unused clk cleanup & no panel driver yet
+ */
+ clocks = <&gcc GCC_DISP_AHB_CLK>,
+ <&gcc GCC_DISP_HF_AXI_CLK>,
+ <&gcc GCC_DISP_THROTTLE_CORE_CLK>,
+ <&gcc GCC_DISP_GPLL0_DIV_CLK_SRC>;
+ };
+ };
+
+ reserved-memory {
+ cont_splash_mem: memory@85200000 {
+ reg = <0 0x85200000 0 0xc00000>;
+ no-map;
+ };
+
+ ramoops@ffc40000 {
+ compatible = "ramoops";
+ reg = <0 0xffc40000 0 0xb0000>;
+ record-size = <0x10000>;
+ console-size = <0x60000>;
+ ftrace-size = <0x10000>;
+ pmsg-size = <0x20000>;
+ ecc-size = <16>;
+ };
+ };
+
+ vph_pwr: vph-pwr-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vph_pwr";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+};
+
+&sdc2_off_state {
+ sd-cd-pins {
+ pins = "gpio94";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+};
+
+&sdc2_on_state {
+ sd-cd-pins {
+ pins = "gpio94";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+};
+
+&sdhc_2 {
+ status = "okay";
+
+ vmmc-supply = <&pm6125_l22>;
+ vqmmc-supply = <&pm6125_l5>;
+
+ cd-gpios = <&tlmm 94 GPIO_ACTIVE_HIGH>;
+};
+
+&gpi_dma0 {
+ status = "okay";
+};
+
+&gpi_dma1 {
+ status = "okay";
+};
+
+&i2c8 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ touchscreen@48 {
+ compatible = "samsung,s6sy761";
+ reg = <0x48>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <22 0x2008>;
+
+ vdd-supply = <&pm6125_l13>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&ts_int_default &ts_avdd_default>;
+ };
+};
+
+&pmk8350_adc_tm {
+ status = "okay";
+};
+
+&pmk8350_rtc {
+ status = "okay";
+};
+
+&pon_pwrkey {
+ status = "okay";
+};
+
+&pon_resin {
+ linux,code = <KEY_VOLUMEUP>;
+ status = "okay";
+};
+
+&qupv3_id_0 {
+ status = "okay";
+};
+
+&qupv3_id_1 {
+ status = "okay";
+};
+
+&remoteproc_adsp {
+ firmware-name = "qcom/Sony/murray/adsp.mbn";
+ status = "okay";
+};
+
+&remoteproc_cdsp {
+ firmware-name = "qcom/Sony/murray/cdsp.mbn";
+ status = "okay";
+};
+
+&rpm_requests {
+ regulators-0 {
+ compatible = "qcom,rpm-pm6125-regulators";
+
+ pm6125_s5: s5 {
+ regulator-min-microvolt = <382000>;
+ regulator-max-microvolt = <1120000>;
+ };
+
+ pm6125_s6: s6 {
+ regulator-min-microvolt = <320000>;
+ regulator-max-microvolt = <1374000>;
+ };
+
+ pm6125_s7: s7 {
+ regulator-min-microvolt = <1574000>;
+ regulator-max-microvolt = <2040000>;
+ };
+
+ /*
+ * S8 is VDD_GFX
+ * L1 is VDD_LPI_CX
+ */
+
+ pm6125_l2: l2 {
+ regulator-min-microvolt = <1170000>;
+ regulator-max-microvolt = <1304000>;
+ };
+
+ pm6125_l3: l3 {
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ pm6125_l4: l4 {
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1300000>;
+ };
+
+ pm6125_l5: l5 {
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-allow-set-load;
+ };
+
+ pm6125_l6: l6 {
+ regulator-min-microvolt = <1080000>;
+ regulator-max-microvolt = <1304000>;
+ };
+
+ pm6125_l7: l7 {
+ regulator-min-microvolt = <720000>;
+ regulator-max-microvolt = <1050000>;
+ };
+
+ pm6125_l8: l8 {
+ regulator-min-microvolt = <1100000>;
+ regulator-max-microvolt = <1304000>;
+ };
+
+ pm6125_l9: l9 {
+ regulator-min-microvolt = <1504000>;
+ regulator-max-microvolt = <2000000>;
+ };
+
+ pm6125_l10: l10 {
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <1980000>;
+ };
+
+ pm6125_l11: l11 {
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <1980000>;
+ };
+
+ pm6125_l12: l12 {
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <2000000>;
+ };
+
+ pm6125_l13: l13 {
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <1980000>;
+ };
+
+ pm6125_l14: l14 {
+ regulator-min-microvolt = <1700000>;
+ regulator-max-microvolt = <1900000>;
+ };
+
+ pm6125_l15: l15 {
+ regulator-min-microvolt = <1650000>;
+ regulator-max-microvolt = <3544000>;
+ };
+
+ pm6125_l16: l16 {
+ regulator-min-microvolt = <1620000>;
+ regulator-max-microvolt = <1980000>;
+ };
+
+ /* L17 is VDD_LPI_MX */
+
+ pm6125_l18: l18 {
+ regulator-min-microvolt = <830000>;
+ regulator-max-microvolt = <920000>;
+ };
+
+ pm6125_l19: l19 {
+ regulator-min-microvolt = <1624000>;
+ regulator-max-microvolt = <3304000>;
+ };
+
+ pm6125_l20: l20 {
+ regulator-min-microvolt = <1624000>;
+ regulator-max-microvolt = <3304000>;
+ };
+
+ pm6125_l21: l21 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3400000>;
+ };
+
+ pm6125_l22: l22 {
+ regulator-min-microvolt = <2704000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-allow-set-load;
+ };
+
+ pm6125_l23: l23 {
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3400000>;
+ };
+
+ pm6125_l24: l24 {
+ regulator-min-microvolt = <2704000>;
+ regulator-max-microvolt = <3544000>;
+ };
+ };
+
+ regulators-1 {
+ compatible = "qcom,rpm-pmr735a-regulators";
+
+ /*
+ * S1 is VDD_MX
+ * S2 is VDD_CX
+ */
+
+ pmr735a_l1: l1 {
+ regulator-min-microvolt = <570000>;
+ regulator-max-microvolt = <650000>;
+ };
+
+ pmr735a_l2: l2 {
+ regulator-min-microvolt = <352000>;
+ regulator-max-microvolt = <796000>;
+ };
+
+ pmr735a_l3: l3 {
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pmr735a_l4: l4 {
+ regulator-min-microvolt = <1504000>;
+ regulator-max-microvolt = <2000000>;
+ };
+
+ pmr735a_l5: l5 {
+ regulator-min-microvolt = <751000>;
+ regulator-max-microvolt = <824000>;
+ };
+
+ pmr735a_l6: l6 {
+ regulator-min-microvolt = <504000>;
+ regulator-max-microvolt = <868000>;
+ };
+
+ pmr735a_l7: l7 {
+ regulator-min-microvolt = <2700000>;
+ regulator-max-microvolt = <3544000>;
+ };
+ };
+};
+
+&sdc2_off_state {
+ sd-cd-pins {
+ pins = "gpio94";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+};
+
+&sdc2_on_state {
+ sd-cd-pins {
+ pins = "gpio94";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+};
+
+&sdhc_2 {
+ status = "okay";
+
+ vmmc-supply = <&pm6125_l22>;
+ vqmmc-supply = <&pm6125_l5>;
+
+ cd-gpios = <&tlmm 94 GPIO_ACTIVE_HIGH>;
+};
+
+&tlmm {
+ gpio-reserved-ranges = <13 4>;
+
+ ts_int_default: ts-int-default-state {
+ pins = "gpio22";
+ function = "gpio";
+ drive-strength = <8>;
+ bias-pull-up;
+ };
+
+ ts_avdd_default: ts-avdd-default-state {
+ pins = "gpio59";
+ function = "gpio";
+ drive-strength = <8>;
+ output-high;
+ };
+};
+
+&usb_1 {
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ dr_mode = "peripheral";
+};
+
+&usb_1_hsphy {
+ status = "okay";
+};
+
+&xo_board_clk {
+ clock-frequency = <19200000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sm6375.dtsi b/arch/arm64/boot/dts/qcom/sm6375.dtsi
new file mode 100644
index 000000000000..12cf5dbe5bd6
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm6375.dtsi
@@ -0,0 +1,1396 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2022, Konrad Dybcio <konrad.dybcio@somainline.org>
+ */
+
+#include <dt-bindings/clock/qcom,rpmcc.h>
+#include <dt-bindings/clock/qcom,sm6375-gcc.h>
+#include <dt-bindings/dma/qcom-gpi.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/mailbox/qcom-ipcc.h>
+#include <dt-bindings/power/qcom-rpmpd.h>
+
+/ {
+ interrupt-parent = <&intc>;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ chosen { };
+
+ clocks {
+ xo_board_clk: xo-board-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+
+ sleep_clk: sleep-clk {
+ compatible = "fixed-clock";
+ clock-frequency = <32000>;
+ #clock-cells = <0>;
+ };
+ };
+
+ cpus {
+ #address-cells = <2>;
+ #size-cells = <0>;
+
+ CPU0: cpu@0 {
+ device_type = "cpu";
+ compatible = "qcom,kryo660";
+ reg = <0x0 0x0>;
+ enable-method = "psci";
+ next-level-cache = <&L2_0>;
+ qcom,freq-domain = <&cpufreq_hw 0>;
+ power-domains = <&CPU_PD0>;
+ power-domain-names = "psci";
+ #cooling-cells = <2>;
+ L2_0: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ L3_0: l3-cache {
+ compatible = "cache";
+ };
+ };
+ };
+
+ CPU1: cpu@100 {
+ device_type = "cpu";
+ compatible = "qcom,kryo660";
+ reg = <0x0 0x100>;
+ enable-method = "psci";
+ next-level-cache = <&L2_100>;
+ qcom,freq-domain = <&cpufreq_hw 0>;
+ power-domains = <&CPU_PD1>;
+ power-domain-names = "psci";
+ #cooling-cells = <2>;
+ L2_100: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU2: cpu@200 {
+ device_type = "cpu";
+ compatible = "qcom,kryo660";
+ reg = <0x0 0x200>;
+ enable-method = "psci";
+ next-level-cache = <&L2_200>;
+ qcom,freq-domain = <&cpufreq_hw 0>;
+ power-domains = <&CPU_PD2>;
+ power-domain-names = "psci";
+ #cooling-cells = <2>;
+ L2_200: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU3: cpu@300 {
+ device_type = "cpu";
+ compatible = "qcom,kryo660";
+ reg = <0x0 0x300>;
+ enable-method = "psci";
+ next-level-cache = <&L2_300>;
+ qcom,freq-domain = <&cpufreq_hw 0>;
+ power-domains = <&CPU_PD3>;
+ power-domain-names = "psci";
+ #cooling-cells = <2>;
+ L2_300: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU4: cpu@400 {
+ device_type = "cpu";
+ compatible = "qcom,kryo660";
+ reg = <0x0 0x400>;
+ enable-method = "psci";
+ next-level-cache = <&L2_400>;
+ qcom,freq-domain = <&cpufreq_hw 0>;
+ power-domains = <&CPU_PD4>;
+ power-domain-names = "psci";
+ #cooling-cells = <2>;
+ L2_400: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU5: cpu@500 {
+ device_type = "cpu";
+ compatible = "qcom,kryo660";
+ reg = <0x0 0x500>;
+ enable-method = "psci";
+ next-level-cache = <&L2_500>;
+ qcom,freq-domain = <&cpufreq_hw 0>;
+ power-domains = <&CPU_PD5>;
+ power-domain-names = "psci";
+ #cooling-cells = <2>;
+ L2_500: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+
+ };
+
+ CPU6: cpu@600 {
+ device_type = "cpu";
+ compatible = "qcom,kryo660";
+ reg = <0x0 0x600>;
+ enable-method = "psci";
+ next-level-cache = <&L2_600>;
+ qcom,freq-domain = <&cpufreq_hw 1>;
+ power-domains = <&CPU_PD6>;
+ power-domain-names = "psci";
+ #cooling-cells = <2>;
+ L2_600: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ CPU7: cpu@700 {
+ device_type = "cpu";
+ compatible = "qcom,kryo660";
+ reg = <0x0 0x700>;
+ enable-method = "psci";
+ next-level-cache = <&L2_700>;
+ qcom,freq-domain = <&cpufreq_hw 1>;
+ power-domains = <&CPU_PD7>;
+ power-domain-names = "psci";
+ #cooling-cells = <2>;
+ L2_700: l2-cache {
+ compatible = "cache";
+ next-level-cache = <&L3_0>;
+ };
+ };
+
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&CPU0>;
+ };
+
+ core1 {
+ cpu = <&CPU1>;
+ };
+
+ core2 {
+ cpu = <&CPU2>;
+ };
+
+ core3 {
+ cpu = <&CPU3>;
+ };
+
+ core4 {
+ cpu = <&CPU4>;
+ };
+
+ core5 {
+ cpu = <&CPU5>;
+ };
+
+ core6 {
+ cpu = <&CPU6>;
+ };
+
+ core7 {
+ cpu = <&CPU7>;
+ };
+ };
+ };
+
+ idle-states {
+ entry-method = "psci";
+
+ LITTLE_CPU_SLEEP_0: cpu-sleep-0-0 {
+ compatible = "arm,idle-state";
+ idle-state-name = "silver-rail-power-collapse";
+ arm,psci-suspend-param = <0x40000004>;
+ entry-latency-us = <702>;
+ exit-latency-us = <915>;
+ min-residency-us = <4001>;
+ local-timer-stop;
+ };
+
+ BIG_CPU_SLEEP_0: cpu-sleep-1-0 {
+ compatible = "arm,idle-state";
+ idle-state-name = "gold-rail-power-collapse";
+ arm,psci-suspend-param = <0x40000004>;
+ entry-latency-us = <526>;
+ exit-latency-us = <1854>;
+ min-residency-us = <5555>;
+ local-timer-stop;
+ };
+ };
+
+ domain-idle-states {
+ CLUSTER_SLEEP_0: cluster-sleep-0 {
+ compatible = "domain-idle-state";
+ idle-state-name = "cluster-power-collapse";
+ arm,psci-suspend-param = <0x41000044>;
+ entry-latency-us = <2752>;
+ exit-latency-us = <3048>;
+ min-residency-us = <6118>;
+ local-timer-stop;
+ };
+ };
+ };
+
+ firmware {
+ scm {
+ compatible = "qcom,scm-sm6375", "qcom,scm";
+ clocks = <&rpmcc RPM_SMD_CE1_CLK>;
+ clock-names = "core";
+ #reset-cells = <1>;
+ };
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ /* We expect the bootloader to fill in the size */
+ reg = <0x0 0x80000000 0x0 0x0>;
+ };
+
+ pmu {
+ compatible = "arm,armv8-pmuv3";
+ interrupts = <GIC_PPI 7 IRQ_TYPE_LEVEL_LOW>;
+ };
+
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+
+ CPU_PD0: cpu0 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ };
+
+ CPU_PD1: cpu1 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ };
+
+ CPU_PD2: cpu2 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ };
+
+ CPU_PD3: cpu3 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ };
+
+ CPU_PD4: cpu4 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ };
+
+ CPU_PD5: cpu5 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&LITTLE_CPU_SLEEP_0>;
+ };
+
+ CPU_PD6: cpu6 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ };
+
+ CPU_PD7: cpu7 {
+ #power-domain-cells = <0>;
+ power-domains = <&CLUSTER_PD>;
+ domain-idle-states = <&BIG_CPU_SLEEP_0>;
+ };
+
+ CLUSTER_PD: cpu-cluster0 {
+ #power-domain-cells = <0>;
+ domain-idle-states = <&CLUSTER_SLEEP_0>;
+ };
+ };
+
+ qup_opp_table: opp-table-qup {
+ compatible = "operating-points-v2";
+
+ opp-75000000 {
+ opp-hz = /bits/ 64 <75000000>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ };
+
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ required-opps = <&rpmpd_opp_svs>;
+ };
+
+ opp-128000000 {
+ opp-hz = /bits/ 64 <128000000>;
+ required-opps = <&rpmpd_opp_nom>;
+ };
+ };
+
+ reserved_memory: reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ hyp_mem: hypervisor@80000000 {
+ reg = <0 0x80000000 0 0x600000>;
+ no-map;
+ };
+
+ xbl_aop_mem: xbl-aop@80700000 {
+ reg = <0 0x80700000 0 0x100000>;
+ no-map;
+ };
+
+ reserved_xbl_uefi: xbl-uefi-res@80880000 {
+ reg = <0 0x80880000 0 0x14000>;
+ no-map;
+ };
+
+ smem_mem: smem@80900000 {
+ compatible = "qcom,smem";
+ reg = <0 0x80900000 0 0x200000>;
+ hwlocks = <&tcsr_mutex 3>;
+ no-map;
+ };
+
+ fw_mem: fw@80b00000 {
+ reg = <0 0x80b00000 0 0x100000>;
+ no-map;
+ };
+
+ cdsp_secure_heap_mem: cdsp-sec-heap@80c00000 {
+ reg = <0 0x80c00000 0 0x1e00000>;
+ no-map;
+ };
+
+ dfps_data_mem: dpfs-data@85e00000 {
+ reg = <0 0x85e00000 0 0x100000>;
+ no-map;
+ };
+
+ pil_wlan_mem: pil-wlan@86500000 {
+ reg = <0 0x86500000 0 0x200000>;
+ no-map;
+ };
+
+ pil_adsp_mem: pil-adsp@86700000 {
+ reg = <0 0x86700000 0 0x2000000>;
+ no-map;
+ };
+
+ pil_cdsp_mem: pil-cdsp@88700000 {
+ reg = <0 0x88700000 0 0x1e00000>;
+ no-map;
+ };
+
+ pil_video_mem: pil-video@8a500000 {
+ reg = <0 0x8a500000 0 0x500000>;
+ no-map;
+ };
+
+ pil_ipa_fw_mem: pil-ipa-fw@8aa00000 {
+ reg = <0 0x8aa00000 0 0x10000>;
+ no-map;
+ };
+
+ pil_ipa_gsi_mem: pil-ipa-gsi@8aa10000 {
+ reg = <0 0x8aa10000 0 0xa000>;
+ no-map;
+ };
+
+ pil_gpu_micro_code_mem: pil-gpu-ucode@8aa1a000 {
+ reg = <0 0x8aa1a000 0 0x2000>;
+ no-map;
+ };
+
+ pil_mpss_wlan_mem: pil-mpss-wlan@8b800000 {
+ reg = <0 0x8b800000 0 0x10000000>;
+ no-map;
+ };
+
+ removed_mem: removed@c0000000 {
+ reg = <0 0xc0000000 0 0x5100000>;
+ no-map;
+ };
+
+ debug_mem: debug@ffb00000 {
+ reg = <0 0xffb00000 0 0xc0000>;
+ no-map;
+ };
+
+ last_log_mem: lastlog@ffbc0000 {
+ reg = <0 0xffbc0000 0 0x80000>;
+ no-map;
+ };
+
+ cmdline_region: cmdline@ffd00000 {
+ reg = <0 0xffd00000 0 0x1000>;
+ no-map;
+ };
+ };
+
+ rpm-glink {
+ compatible = "qcom,glink-rpm";
+ interrupts-extended = <&ipcc IPCC_CLIENT_AOP
+ IPCC_MPROC_SIGNAL_GLINK_QMP
+ IRQ_TYPE_EDGE_RISING>;
+ qcom,rpm-msg-ram = <&rpm_msg_ram>;
+ mboxes = <&ipcc IPCC_CLIENT_AOP IPCC_MPROC_SIGNAL_GLINK_QMP>;
+
+ rpm_requests: rpm-requests {
+ compatible = "qcom,rpm-sm6375";
+ qcom,glink-channels = "rpm_requests";
+
+ rpmcc: clock-controller {
+ compatible = "qcom,rpmcc-sm6375", "qcom,rpmcc";
+ clocks = <&xo_board_clk>;
+ clock-names = "xo";
+ #clock-cells = <1>;
+ };
+
+ rpmpd: power-controller {
+ compatible = "qcom,sm6375-rpmpd";
+ #power-domain-cells = <1>;
+ operating-points-v2 = <&rpmpd_opp_table>;
+
+ rpmpd_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ rpmpd_opp_ret: opp1 {
+ opp-level = <RPM_SMD_LEVEL_RETENTION>;
+ };
+
+ rpmpd_opp_min_svs: opp2 {
+ opp-level = <RPM_SMD_LEVEL_MIN_SVS>;
+ };
+
+ rpmpd_opp_low_svs: opp3 {
+ opp-level = <RPM_SMD_LEVEL_LOW_SVS>;
+ };
+
+ rpmpd_opp_svs: opp4 {
+ opp-level = <RPM_SMD_LEVEL_SVS>;
+ };
+
+ rpmpd_opp_svs_plus: opp5 {
+ opp-level = <RPM_SMD_LEVEL_SVS_PLUS>;
+ };
+
+ rpmpd_opp_nom: opp6 {
+ opp-level = <RPM_SMD_LEVEL_NOM>;
+ };
+
+ rpmpd_opp_nom_plus: opp7 {
+ opp-level = <RPM_SMD_LEVEL_NOM_PLUS>;
+ };
+
+ rpmpd_opp_turbo: opp8 {
+ opp-level = <RPM_SMD_LEVEL_TURBO>;
+ };
+
+ rpmpd_opp_turbo_no_cpr: opp9 {
+ opp-level = <RPM_SMD_LEVEL_TURBO_NO_CPR>;
+ };
+ };
+ };
+ };
+ };
+
+ smp2p-adsp {
+ compatible = "qcom,smp2p";
+ qcom,smem = <443>, <429>;
+ interrupts-extended = <&ipcc IPCC_CLIENT_LPASS
+ IPCC_MPROC_SIGNAL_SMP2P
+ IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&ipcc IPCC_CLIENT_LPASS
+ IPCC_MPROC_SIGNAL_SMP2P>;
+
+ qcom,local-pid = <0>;
+ qcom,remote-pid = <2>;
+
+ smp2p_adsp_out: master-kernel {
+ qcom,entry-name = "master-kernel";
+ #qcom,smem-state-cells = <1>;
+ };
+
+ smp2p_adsp_in: slave-kernel {
+ qcom,entry-name = "slave-kernel";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ smp2p-cdsp {
+ compatible = "qcom,smp2p";
+ qcom,smem = <94>, <432>;
+ interrupts-extended = <&ipcc IPCC_CLIENT_CDSP
+ IPCC_MPROC_SIGNAL_SMP2P
+ IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&ipcc IPCC_CLIENT_CDSP
+ IPCC_MPROC_SIGNAL_SMP2P>;
+
+ qcom,local-pid = <0>;
+ qcom,remote-pid = <5>;
+
+ smp2p_cdsp_out: master-kernel {
+ qcom,entry-name = "master-kernel";
+ #qcom,smem-state-cells = <1>;
+ };
+
+ smp2p_cdsp_in: slave-kernel {
+ qcom,entry-name = "slave-kernel";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
+ soc: soc@0 {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0 0 0 0 0x10 0>;
+ dma-ranges = <0 0 0 0 0x10 0>;
+ compatible = "simple-bus";
+
+ ipcc: mailbox@208000 {
+ compatible = "qcom,sm6375-ipcc", "qcom,ipcc";
+ reg = <0 0x00208000 0 0x1000>;
+ interrupts = <GIC_SPI 334 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ #mbox-cells = <2>;
+ };
+
+ tcsr_mutex: hwlock@340000 {
+ compatible = "qcom,tcsr-mutex";
+ reg = <0x0 0x00340000 0x0 0x40000>;
+ #hwlock-cells = <1>;
+ };
+
+ tlmm: pinctrl@500000 {
+ compatible = "qcom,sm6375-tlmm";
+ reg = <0 0x00500000 0 0x800000>;
+ interrupts = <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>;
+ gpio-ranges = <&tlmm 0 0 157>;
+ /* TODO: Hook up MPM as wakeup-parent when it's there */
+ interrupt-controller;
+ gpio-controller;
+ #interrupt-cells = <2>;
+ #gpio-cells = <2>;
+
+ sdc2_off_state: sdc2-off-state {
+ clk-pins {
+ pins = "sdc2_clk";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ cmd-pins {
+ pins = "sdc2_cmd";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ data-pins {
+ pins = "sdc2_data";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ sdc2_on_state: sdc2-on-state {
+ clk-pins {
+ pins = "sdc2_clk";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ cmd-pins {
+ pins = "sdc2_cmd";
+ drive-strength = <10>;
+ bias-pull-up;
+ };
+
+ data-pins {
+ pins = "sdc2_data";
+ drive-strength = <10>;
+ bias-pull-up;
+ };
+ };
+
+ qup_i2c0_default: qup-i2c0-default-state {
+ pins = "gpio0", "gpio1";
+ function = "qup00";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_i2c1_default: qup-i2c1-default-state {
+ pins = "gpio61", "gpio62";
+ function = "qup01";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_i2c2_default: qup-i2c2-default-state {
+ pins = "gpio45", "gpio46";
+ function = "qup02";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_i2c8_default: qup-i2c8-default-state {
+ pins = "gpio19", "gpio20";
+ /* TLMM, GCC and vendor DT all have different indices.. */
+ function = "qup12";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_i2c10_default: qup-i2c10-default-state {
+ pins = "gpio4", "gpio5";
+ function = "qup10";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ qup_spi0_default: qup-spi0-default-state {
+ pins = "gpio0", "gpio1", "gpio2", "gpio3";
+ function = "qup00";
+ drive-strength = <6>;
+ bias-disable;
+ };
+ };
+
+ gcc: clock-controller@1400000 {
+ compatible = "qcom,sm6375-gcc";
+ reg = <0 0x01400000 0 0x1f0000>;
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
+ <&rpmcc RPM_SMD_XO_A_CLK_SRC>,
+ <&sleep_clk>;
+ #power-domain-cells = <1>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ };
+
+ usb_1_hsphy: phy@162b000 {
+ compatible = "qcom,sm6375-usb-hs-phy", "qcom,usb-snps-hs-7nm-phy";
+ reg = <0 0x0162b000 0 0x400>;
+
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "ref";
+ resets = <&gcc GCC_QUSB2PHY_PRIM_BCR>;
+ #phy-cells = <0>;
+
+ status = "disabled";
+ };
+
+ spmi_bus: spmi@1c40000 {
+ compatible = "qcom,spmi-pmic-arb";
+ reg = <0 0x01c40000 0 0x1100>,
+ <0 0x01e00000 0 0x2000000>,
+ <0 0x03e00000 0 0x100000>,
+ <0 0x03f00000 0 0xa0000>,
+ <0 0x01c0a000 0 0x26000>;
+ reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
+ interrupt-names = "periph_irq";
+ interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ qcom,ee = <0>;
+ qcom,channel = <0>;
+ #address-cells = <2>;
+ #size-cells = <0>;
+ interrupt-controller;
+ #interrupt-cells = <4>;
+ };
+
+ rpm_msg_ram: sram@45f0000 {
+ compatible = "qcom,rpm-msg-ram";
+ reg = <0 0x045f0000 0 0x7000>;
+ };
+
+ sdhc_2: mmc@4784000 {
+ compatible = "qcom,sm6375-sdhci", "qcom,sdhci-msm-v5";
+ reg = <0 0x04784000 0 0x1000>;
+
+ interrupts = <GIC_SPI 350 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ clocks = <&gcc GCC_SDCC2_AHB_CLK>,
+ <&gcc GCC_SDCC2_APPS_CLK>,
+ <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "iface", "core", "xo";
+ resets = <&gcc GCC_SDCC2_BCR>;
+ iommus = <&apps_smmu 0x40 0x0>;
+
+ pinctrl-0 = <&sdc2_on_state>;
+ pinctrl-1 = <&sdc2_off_state>;
+ pinctrl-names = "default", "sleep";
+
+ qcom,dll-config = <0x0007642c>;
+ qcom,ddr-config = <0x80040868>;
+ power-domains = <&rpmpd SM6375_VDDCX>;
+ operating-points-v2 = <&sdhc2_opp_table>;
+ bus-width = <4>;
+
+ status = "disabled";
+
+ sdhc2_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ required-opps = <&rpmpd_opp_low_svs>;
+ };
+
+ opp-202000000 {
+ opp-hz = /bits/ 64 <202000000>;
+ required-opps = <&rpmpd_opp_svs_plus>;
+ };
+ };
+ };
+
+ gpi_dma0: dma-controller@4a00000 {
+ compatible = "qcom,sm6375-gpi-dma", "qcom,sm6350-gpi-dma";
+ reg = <0 0x04a00000 0 0x60000>;
+ interrupts = <GIC_SPI 335 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 336 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 337 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 339 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 340 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 341 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 342 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 343 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 344 IRQ_TYPE_LEVEL_HIGH>;
+ dma-channels = <10>;
+ dma-channel-mask = <0x1f>;
+ iommus = <&apps_smmu 0x16 0x0>;
+ #dma-cells = <3>;
+ status = "disabled";
+ };
+
+ qupv3_id_0: geniqup@4ac0000 {
+ compatible = "qcom,geni-se-qup";
+ reg = <0x0 0x04ac0000 0x0 0x2000>;
+ clock-names = "m-ahb", "s-ahb";
+ clocks = <&gcc GCC_QUPV3_WRAP_0_M_AHB_CLK>,
+ <&gcc GCC_QUPV3_WRAP_0_S_AHB_CLK>;
+ iommus = <&apps_smmu 0x3 0x0>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ status = "disabled";
+
+ i2c0: i2c@4a80000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x0 0x04a80000 0x0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
+ interrupts = <GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c0_default>;
+ dmas = <&gpi_dma0 0 0 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 0 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi0: spi@4a80000 {
+ compatible = "qcom,geni-spi";
+ reg = <0x0 0x04a80000 0x0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S0_CLK>;
+ interrupts = <GIC_SPI 327 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_spi0_default>;
+ power-domains = <&rpmpd SM6375_VDDCX>;
+ operating-points-v2 = <&qup_opp_table>;
+ dmas = <&gpi_dma0 0 0 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 0 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c1: i2c@4a84000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x0 0x04a84000 0x0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>;
+ interrupts = <GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c1_default>;
+ dmas = <&gpi_dma0 0 1 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 1 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi1: spi@4a84000 {
+ compatible = "qcom,geni-spi";
+ reg = <0x0 0x04a84000 0x0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S1_CLK>;
+ interrupts = <GIC_SPI 328 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&rpmpd SM6375_VDDCX>;
+ operating-points-v2 = <&qup_opp_table>;
+ dmas = <&gpi_dma0 0 1 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 1 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c2: i2c@4a88000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x0 0x04a88000 0x0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
+ interrupts = <GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c2_default>;
+ dmas = <&gpi_dma0 0 2 QCOM_GPI_I2C>,
+ <&gpi_dma0 1 2 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi2: spi@4a88000 {
+ compatible = "qcom,geni-spi";
+ reg = <0x0 0x04a88000 0x0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP0_S2_CLK>;
+ interrupts = <GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&rpmpd SM6375_VDDCX>;
+ operating-points-v2 = <&qup_opp_table>;
+ dmas = <&gpi_dma0 0 2 QCOM_GPI_SPI>,
+ <&gpi_dma0 1 2 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ /*
+ * As per GCC, QUP3/4/5/11 also exist, but are not even defined downstream.
+ * There is a comment in the included DTSI of another SoC saying that they
+ * are not "bolled out" (probably meaning not routed to solder balls)
+ * TLMM driver however, suggests there are as many as 15 QUPs in total!
+ * Most of which don't even have pin configurations for.. Sad stuff!
+ */
+ };
+
+ gpi_dma1: dma-controller@4c00000 {
+ compatible = "qcom,sm6375-gpi-dma", "qcom,sm6350-gpi-dma";
+ reg = <0 0x04c00000 0 0x60000>;
+ interrupts = <GIC_SPI 497 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 498 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 499 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 500 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 501 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 502 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 503 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 504 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 505 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 506 IRQ_TYPE_LEVEL_HIGH>;
+ dma-channels = <10>;
+ dma-channel-mask = <0x1f>;
+ iommus = <&apps_smmu 0xd6 0x0>;
+ #dma-cells = <3>;
+ status = "disabled";
+ };
+
+ qupv3_id_1: geniqup@4cc0000 {
+ compatible = "qcom,geni-se-qup";
+ reg = <0x0 0x04cc0000 0x0 0x2000>;
+ clock-names = "m-ahb", "s-ahb";
+ clocks = <&gcc GCC_QUPV3_WRAP_1_M_AHB_CLK>,
+ <&gcc GCC_QUPV3_WRAP_1_S_AHB_CLK>;
+ iommus = <&apps_smmu 0xc3 0x0>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ status = "disabled";
+
+ i2c6: i2c@4c80000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x0 0x04c80000 0x0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S0_CLK>;
+ interrupts = <GIC_SPI 507 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma1 0 0 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 0 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi6: spi@4c80000 {
+ compatible = "qcom,geni-spi";
+ reg = <0x0 0x04c80000 0x0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S0_CLK>;
+ interrupts = <GIC_SPI 507 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&rpmpd SM6375_VDDCX>;
+ operating-points-v2 = <&qup_opp_table>;
+ dmas = <&gpi_dma1 0 0 QCOM_GPI_SPI>,
+ <&gpi_dma1 1 0 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c7: i2c@4c84000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x0 0x04c84000 0x0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>;
+ interrupts = <GIC_SPI 508 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma1 0 1 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 1 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi7: spi@4c84000 {
+ compatible = "qcom,geni-spi";
+ reg = <0x0 0x04c84000 0x0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S1_CLK>;
+ interrupts = <GIC_SPI 508 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&rpmpd SM6375_VDDCX>;
+ operating-points-v2 = <&qup_opp_table>;
+ dmas = <&gpi_dma1 0 1 QCOM_GPI_SPI>,
+ <&gpi_dma1 1 1 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c8: i2c@4c88000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x0 0x04c88000 0x0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S2_CLK>;
+ interrupts = <GIC_SPI 509 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c8_default>;
+ dmas = <&gpi_dma1 0 2 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 2 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi8: spi@4c88000 {
+ compatible = "qcom,geni-spi";
+ reg = <0x0 0x04c88000 0x0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S2_CLK>;
+ interrupts = <GIC_SPI 509 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&rpmpd SM6375_VDDCX>;
+ operating-points-v2 = <&qup_opp_table>;
+ dmas = <&gpi_dma1 0 2 QCOM_GPI_SPI>,
+ <&gpi_dma1 1 2 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c9: i2c@4c8c000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x0 0x04c8c000 0x0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S3_CLK>;
+ interrupts = <GIC_SPI 510 IRQ_TYPE_LEVEL_HIGH>;
+ dmas = <&gpi_dma1 0 3 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 3 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi9: spi@4c8c000 {
+ compatible = "qcom,geni-spi";
+ reg = <0x0 0x04c8c000 0x0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S3_CLK>;
+ interrupts = <GIC_SPI 510 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&rpmpd SM6375_VDDCX>;
+ operating-points-v2 = <&qup_opp_table>;
+ dmas = <&gpi_dma1 0 3 QCOM_GPI_SPI>,
+ <&gpi_dma1 1 3 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ i2c10: i2c@4c90000 {
+ compatible = "qcom,geni-i2c";
+ reg = <0x0 0x04c90000 0x0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>;
+ interrupts = <GIC_SPI 511 IRQ_TYPE_LEVEL_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&qup_i2c10_default>;
+ dmas = <&gpi_dma1 0 4 QCOM_GPI_I2C>,
+ <&gpi_dma1 1 4 QCOM_GPI_I2C>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ spi10: spi@4c90000 {
+ compatible = "qcom,geni-spi";
+ reg = <0x0 0x04c90000 0x0 0x4000>;
+ clock-names = "se";
+ clocks = <&gcc GCC_QUPV3_WRAP1_S4_CLK>;
+ interrupts = <GIC_SPI 511 IRQ_TYPE_LEVEL_HIGH>;
+ power-domains = <&rpmpd SM6375_VDDCX>;
+ operating-points-v2 = <&qup_opp_table>;
+ dmas = <&gpi_dma1 0 4 QCOM_GPI_SPI>,
+ <&gpi_dma1 1 4 QCOM_GPI_SPI>;
+ dma-names = "tx", "rx";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+ };
+
+ usb_1: usb@4ef8800 {
+ compatible = "qcom,sm6375-dwc3", "qcom,dwc3";
+ reg = <0 0x04ef8800 0 0x400>;
+
+ clocks = <&gcc GCC_CFG_NOC_USB3_PRIM_AXI_CLK>,
+ <&gcc GCC_USB30_PRIM_MASTER_CLK>,
+ <&gcc GCC_SYS_NOC_USB3_PRIM_AXI_CLK>,
+ <&gcc GCC_USB30_PRIM_SLEEP_CLK>,
+ <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
+ <&gcc GCC_USB3_PRIM_CLKREF_CLK>;
+ clock-names = "cfg_noc",
+ "core",
+ "iface",
+ "sleep",
+ "mock_utmi",
+ "xo";
+
+ assigned-clocks = <&gcc GCC_USB30_PRIM_MOCK_UTMI_CLK>,
+ <&gcc GCC_USB30_PRIM_MASTER_CLK>;
+ assigned-clock-rates = <19200000>, <133333333>;
+
+ interrupts = <GIC_SPI 302 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hs_phy_irq",
+ "ss_phy_irq",
+ "dm_hs_phy_irq",
+ "dp_hs_phy_irq";
+
+ power-domains = <&gcc USB30_PRIM_GDSC>;
+
+ resets = <&gcc GCC_USB30_PRIM_BCR>;
+
+ /*
+ * This property is there to allow USB2 to work, as
+ * USB3 is not implemented yet - (re)move it when
+ * proper support is in place.
+ */
+ qcom,select-utmi-as-pipe-clk;
+
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ status = "disabled";
+
+ usb_1_dwc3: usb@4e00000 {
+ compatible = "snps,dwc3";
+ reg = <0 0x04e00000 0 0xcd00>;
+ interrupts = <GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH>;
+ maximum-speed = "high-speed";
+ phys = <&usb_1_hsphy>;
+ phy-names = "usb2-phy";
+ iommus = <&apps_smmu 0xe0 0x0>;
+
+ /* Yes, this impl *does* have an unfunny number of quirks.. */
+ snps,hird-threshold = /bits/ 8 <0x10>;
+ snps,usb2-gadget-lpm-disable;
+ snps,dis_u2_susphy_quirk;
+ snps,is-utmi-l1-suspend;
+ snps,dis-u1-entry-quirk;
+ snps,dis-u2-entry-quirk;
+ snps,usb3_lpm_capable;
+ snps,has-lpm-erratum;
+ tx-fifo-resize;
+ };
+ };
+
+ remoteproc_adsp: remoteproc@a400000 {
+ compatible = "qcom,sm6375-adsp-pas";
+ reg = <0 0x0a400000 0 0x100>;
+
+ interrupts-extended = <&intc GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>,
+ <&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 2 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_adsp_in 3 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "wdog", "fatal", "ready",
+ "handover", "stop-ack";
+
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "xo";
+
+ power-domains = <&rpmpd SM6375_VDD_LPI_CX>,
+ <&rpmpd SM6375_VDD_LPI_MX>;
+ power-domain-names = "lcx", "lmx";
+
+ memory-region = <&pil_adsp_mem>;
+
+ qcom,smem-states = <&smp2p_adsp_out 0>;
+ qcom,smem-state-names = "stop";
+
+ status = "disabled";
+
+ glink-edge {
+ interrupts-extended = <&ipcc IPCC_CLIENT_LPASS
+ IPCC_MPROC_SIGNAL_GLINK_QMP
+ IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&ipcc IPCC_CLIENT_LPASS
+ IPCC_MPROC_SIGNAL_GLINK_QMP>;
+
+ label = "lpass";
+ qcom,remote-pid = <2>;
+ };
+ };
+
+ remoteproc_cdsp: remoteproc@b000000 {
+ compatible = "qcom,sm6375-cdsp-pas";
+ reg = <0x0 0x0b000000 0x0 0x100000>;
+
+ interrupts-extended = <&intc GIC_SPI 265 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_cdsp_in 0 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_cdsp_in 1 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_cdsp_in 2 IRQ_TYPE_EDGE_RISING>,
+ <&smp2p_cdsp_in 3 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "wdog", "fatal", "ready",
+ "handover", "stop-ack";
+
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>;
+ clock-names = "xo";
+
+ power-domains = <&rpmpd SM6375_VDDCX>;
+
+ memory-region = <&pil_cdsp_mem>;
+
+ qcom,smem-states = <&smp2p_cdsp_out 0>;
+ qcom,smem-state-names = "stop";
+
+ status = "disabled";
+
+ glink-edge {
+ interrupts-extended = <&ipcc IPCC_CLIENT_CDSP
+ IPCC_MPROC_SIGNAL_GLINK_QMP
+ IRQ_TYPE_EDGE_RISING>;
+ mboxes = <&ipcc IPCC_CLIENT_CDSP
+ IPCC_MPROC_SIGNAL_GLINK_QMP>;
+ label = "cdsp";
+ qcom,remote-pid = <5>;
+ };
+ };
+
+ apps_smmu: iommu@c600000 {
+ compatible = "qcom,sm6375-smmu-500", "arm,mmu-500";
+ reg = <0 0x0c600000 0 0x100000>;
+ interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 139 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 145 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 151 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
+
+ power-domains = <&gcc HLOS1_VOTE_MM_SNOC_MMU_TBU_RT_GDSC>,
+ <&gcc HLOS1_VOTE_MM_SNOC_MMU_TBU_NRT_GDSC>,
+ <&gcc HLOS1_VOTE_TURING_MMU_TBU0_GDSC>;
+ #global-interrupts = <1>;
+ #iommu-cells = <2>;
+ };
+
+ intc: interrupt-controller@f200000 {
+ compatible = "arm,gic-v3";
+ reg = <0x0 0x0f200000 0x0 0x10000>, /* GICD */
+ <0x0 0x0f240000 0x0 0x100000>; /* GICR * 8 */
+ interrupts = <GIC_PPI 8 IRQ_TYPE_LEVEL_HIGH>;
+ #redistributor-regions = <1>;
+ #interrupt-cells = <3>;
+ redistributor-stride = <0 0x20000>;
+ interrupt-controller;
+ };
+
+ timer@f420000 {
+ compatible = "arm,armv7-timer-mem";
+ reg = <0 0x0f420000 0 0x1000>;
+ ranges = <0 0 0 0x20000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ frame@f421000 {
+ reg = <0x0f421000 0x1000>, <0x0f422000 0x1000>;
+ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 6 IRQ_TYPE_LEVEL_HIGH>;
+ frame-number = <0>;
+ };
+
+ frame@f423000 {
+ reg = <0x0f243000 0x1000>;
+ interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>;
+ frame-number = <1>;
+ status = "disabled";
+ };
+
+ frame@f425000 {
+ reg = <0x0f425000 0x1000>;
+ interrupts = <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
+ frame-number = <2>;
+ status = "disabled";
+ };
+
+ frame@f427000 {
+ reg = <0x0f427000 0x1000>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ frame-number = <3>;
+ status = "disabled";
+ };
+
+ frame@f429000 {
+ reg = <0x0f429000 0x1000>;
+ interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+ frame-number = <4>;
+ status = "disabled";
+ };
+
+ frame@f42b000 {
+ reg = <0x0f42b000 0x1000>;
+ interrupts = <GIC_SPI 13 IRQ_TYPE_LEVEL_HIGH>;
+ frame-number = <5>;
+ status = "disabled";
+ };
+
+ frame@f42d000 {
+ reg = <0x0f42d000 0x1000>;
+ interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+ frame-number = <6>;
+ status = "disabled";
+ };
+ };
+
+ cpufreq_hw: cpufreq@fd91000 {
+ compatible = "qcom,sm6375-cpufreq-epss", "qcom,cpufreq-epss";
+ reg = <0 0x0fd91000 0 0x1000>, <0 0x0fd92000 0 0x1000>;
+ reg-names = "freq-domain0", "freq-domain1";
+
+ clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>, <&gcc GPLL0>;
+ clock-names = "xo", "alternate";
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "dcvsh-irq-0", "dcvsh-irq-1";
+ #freq-domain-cells = <1>;
+ };
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts = <GIC_PPI 1 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 2 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 3 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
+ <GIC_PPI 0 (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts b/arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts
index 30c94fd4fe61..c456e9594ea5 100644
--- a/arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts
+++ b/arch/arm64/boot/dts/qcom/sm7225-fairphone-fp4.dts
@@ -279,8 +279,11 @@
vreg_l6e: ldo6 {
regulator-min-microvolt = <1700000>;
- regulator-max-microvolt = <3544000>;
+ regulator-max-microvolt = <2950000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
vreg_l7e: ldo7 {
@@ -297,8 +300,11 @@
vreg_l9e: ldo9 {
regulator-min-microvolt = <2700000>;
- regulator-max-microvolt = <3544000>;
+ regulator-max-microvolt = <2960000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
vreg_l10e: ldo10 {
@@ -424,6 +430,33 @@
status = "okay";
};
+&sdc2_off_state {
+ sd-cd-pins {
+ pins = "gpio94";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+};
+
+&sdc2_on_state {
+ sd-cd-pins {
+ pins = "gpio94";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+};
+
+&sdhc_2 {
+ vmmc-supply = <&vreg_l9e>;
+ vqmmc-supply = <&vreg_l6e>;
+
+ cd-gpios = <&tlmm 94 GPIO_ACTIVE_LOW>;
+
+ status = "okay";
+};
+
&tlmm {
gpio-reserved-ranges = <13 4>, <56 2>;
};
diff --git a/arch/arm64/boot/dts/qcom/sm8150-microsoft-surface-duo.dts b/arch/arm64/boot/dts/qcom/sm8150-microsoft-surface-duo.dts
index bb278ecac3fa..5397fba9417b 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-microsoft-surface-duo.dts
+++ b/arch/arm64/boot/dts/qcom/sm8150-microsoft-surface-duo.dts
@@ -475,7 +475,7 @@
&tlmm {
gpio-reserved-ranges = <126 4>;
- da7280_intr_default: da7280-intr-default {
+ da7280_intr_default: da7280-intr-default-state {
pins = "gpio42";
function = "gpio";
bias-pull-up;
diff --git a/arch/arm64/boot/dts/qcom/sm8150-sony-xperia-kumano.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sony-xperia-kumano.dtsi
index fb6e5a140c9f..c958a8b16730 100644
--- a/arch/arm64/boot/dts/qcom/sm8150-sony-xperia-kumano.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150-sony-xperia-kumano.dtsi
@@ -348,9 +348,8 @@
regulator-max-microvolt = <2960000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
regulator-allow-set-load;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
vreg_l7c_3p0: ldo7 {
@@ -370,9 +369,8 @@
regulator-max-microvolt = <2960000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
regulator-allow-set-load;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
vreg_l10c_3p3: ldo10 {
diff --git a/arch/arm64/boot/dts/qcom/sm8150.dtsi b/arch/arm64/boot/dts/qcom/sm8150.dtsi
index cef8c4f4f0ff..a0c57fb798d3 100644
--- a/arch/arm64/boot/dts/qcom/sm8150.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8150.dtsi
@@ -887,7 +887,7 @@
};
gpi_dma0: dma-controller@800000 {
- compatible = "qcom,sm8150-gpi-dma";
+ compatible = "qcom,sm8150-gpi-dma", "qcom,sdm845-gpi-dma";
reg = <0 0x800000 0 0x60000>;
interrupts = <GIC_SPI 244 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>,
@@ -1222,7 +1222,7 @@
};
gpi_dma1: dma-controller@a00000 {
- compatible = "qcom,sm8150-gpi-dma";
+ compatible = "qcom,sm8150-gpi-dma", "qcom,sdm845-gpi-dma";
reg = <0 0xa00000 0 0x60000>;
interrupts = <GIC_SPI 279 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 280 IRQ_TYPE_LEVEL_HIGH>,
@@ -1471,7 +1471,7 @@
};
gpi_dma2: dma-controller@c00000 {
- compatible = "qcom,sm8150-gpi-dma";
+ compatible = "qcom,sm8150-gpi-dma", "qcom,sdm845-gpi-dma";
reg = <0 0xc00000 0 0x60000>;
interrupts = <GIC_SPI 588 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 589 IRQ_TYPE_LEVEL_HIGH>,
@@ -2032,11 +2032,11 @@
status = "disabled";
ufs_mem_phy_lanes: phy@1d87400 {
- reg = <0 0x01d87400 0 0x108>,
- <0 0x01d87600 0 0x1e0>,
- <0 0x01d87c00 0 0x1dc>,
- <0 0x01d87800 0 0x108>,
- <0 0x01d87a00 0 0x1e0>;
+ reg = <0 0x01d87400 0 0x16c>,
+ <0 0x01d87600 0 0x200>,
+ <0 0x01d87c00 0 0x200>,
+ <0 0x01d87800 0 0x16c>,
+ <0 0x01d87a00 0 0x200>;
#phy-cells = <0>;
};
};
@@ -2074,8 +2074,8 @@
clocks = <&rpmhcc RPMH_CXO_CLK>;
clock-names = "xo";
- power-domains = <&rpmhpd 3>,
- <&rpmhpd 2>;
+ power-domains = <&rpmhpd SM8150_LCX>,
+ <&rpmhpd SM8150_LMX>;
power-domain-names = "lcx", "lmx";
memory-region = <&slpi_mem>;
@@ -2276,422 +2276,302 @@
#interrupt-cells = <2>;
wakeup-parent = <&pdc>;
- qup_i2c0_default: qup-i2c0-default {
- mux {
- pins = "gpio0", "gpio1";
- function = "qup0";
- };
-
- config {
- pins = "gpio0", "gpio1";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c0_default: qup-i2c0-default-state {
+ pins = "gpio0", "gpio1";
+ function = "qup0";
+ drive-strength = <0x02>;
+ bias-disable;
};
- qup_spi0_default: qup-spi0-default {
+ qup_spi0_default: qup-spi0-default-state {
pins = "gpio0", "gpio1", "gpio2", "gpio3";
function = "qup0";
drive-strength = <6>;
bias-disable;
};
- qup_i2c1_default: qup-i2c1-default {
- mux {
- pins = "gpio114", "gpio115";
- function = "qup1";
- };
-
- config {
- pins = "gpio114", "gpio115";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c1_default: qup-i2c1-default-state {
+ pins = "gpio114", "gpio115";
+ function = "qup1";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi1_default: qup-spi1-default {
+ qup_spi1_default: qup-spi1-default-state {
pins = "gpio114", "gpio115", "gpio116", "gpio117";
function = "qup1";
drive-strength = <6>;
bias-disable;
};
- qup_i2c2_default: qup-i2c2-default {
- mux {
- pins = "gpio126", "gpio127";
- function = "qup2";
- };
-
- config {
- pins = "gpio126", "gpio127";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c2_default: qup-i2c2-default-state {
+ pins = "gpio126", "gpio127";
+ function = "qup2";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi2_default: qup-spi2-default {
+ qup_spi2_default: qup-spi2-default-state {
pins = "gpio126", "gpio127", "gpio128", "gpio129";
function = "qup2";
drive-strength = <6>;
bias-disable;
};
- qup_i2c3_default: qup-i2c3-default {
- mux {
- pins = "gpio144", "gpio145";
- function = "qup3";
- };
-
- config {
- pins = "gpio144", "gpio145";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c3_default: qup-i2c3-default-state {
+ pins = "gpio144", "gpio145";
+ function = "qup3";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi3_default: qup-spi3-default {
+ qup_spi3_default: qup-spi3-default-state {
pins = "gpio144", "gpio145", "gpio146", "gpio147";
function = "qup3";
drive-strength = <6>;
bias-disable;
};
- qup_i2c4_default: qup-i2c4-default {
- mux {
- pins = "gpio51", "gpio52";
- function = "qup4";
- };
-
- config {
- pins = "gpio51", "gpio52";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c4_default: qup-i2c4-default-state {
+ pins = "gpio51", "gpio52";
+ function = "qup4";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi4_default: qup-spi4-default {
+ qup_spi4_default: qup-spi4-default-state {
pins = "gpio51", "gpio52", "gpio53", "gpio54";
function = "qup4";
drive-strength = <6>;
bias-disable;
};
- qup_i2c5_default: qup-i2c5-default {
- mux {
- pins = "gpio121", "gpio122";
- function = "qup5";
- };
-
- config {
- pins = "gpio121", "gpio122";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c5_default: qup-i2c5-default-state {
+ pins = "gpio121", "gpio122";
+ function = "qup5";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi5_default: qup-spi5-default {
+ qup_spi5_default: qup-spi5-default-state {
pins = "gpio119", "gpio120", "gpio121", "gpio122";
function = "qup5";
drive-strength = <6>;
bias-disable;
};
- qup_i2c6_default: qup-i2c6-default {
- mux {
- pins = "gpio6", "gpio7";
- function = "qup6";
- };
-
- config {
- pins = "gpio6", "gpio7";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c6_default: qup-i2c6-default-state {
+ pins = "gpio6", "gpio7";
+ function = "qup6";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi6_default: qup-spi6_default {
+ qup_spi6_default: qup-spi6_default-state {
pins = "gpio4", "gpio5", "gpio6", "gpio7";
function = "qup6";
drive-strength = <6>;
bias-disable;
};
- qup_i2c7_default: qup-i2c7-default {
- mux {
- pins = "gpio98", "gpio99";
- function = "qup7";
- };
-
- config {
- pins = "gpio98", "gpio99";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c7_default: qup-i2c7-default-state {
+ pins = "gpio98", "gpio99";
+ function = "qup7";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi7_default: qup-spi7_default {
+ qup_spi7_default: qup-spi7_default-state {
pins = "gpio98", "gpio99", "gpio100", "gpio101";
function = "qup7";
drive-strength = <6>;
bias-disable;
};
- qup_i2c8_default: qup-i2c8-default {
- mux {
- pins = "gpio88", "gpio89";
- function = "qup8";
- };
-
- config {
- pins = "gpio88", "gpio89";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c8_default: qup-i2c8-default-state {
+ pins = "gpio88", "gpio89";
+ function = "qup8";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi8_default: qup-spi8-default {
+ qup_spi8_default: qup-spi8-default-state {
pins = "gpio88", "gpio89", "gpio90", "gpio91";
function = "qup8";
drive-strength = <6>;
bias-disable;
};
- qup_i2c9_default: qup-i2c9-default {
- mux {
- pins = "gpio39", "gpio40";
- function = "qup9";
- };
-
- config {
- pins = "gpio39", "gpio40";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c9_default: qup-i2c9-default-state {
+ pins = "gpio39", "gpio40";
+ function = "qup9";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi9_default: qup-spi9-default {
+ qup_spi9_default: qup-spi9-default-state {
pins = "gpio39", "gpio40", "gpio41", "gpio42";
function = "qup9";
drive-strength = <6>;
bias-disable;
};
- qup_i2c10_default: qup-i2c10-default {
- mux {
- pins = "gpio9", "gpio10";
- function = "qup10";
- };
-
- config {
- pins = "gpio9", "gpio10";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c10_default: qup-i2c10-default-state {
+ pins = "gpio9", "gpio10";
+ function = "qup10";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi10_default: qup-spi10-default {
+ qup_spi10_default: qup-spi10-default-state {
pins = "gpio9", "gpio10", "gpio11", "gpio12";
function = "qup10";
drive-strength = <6>;
bias-disable;
};
- qup_i2c11_default: qup-i2c11-default {
- mux {
- pins = "gpio94", "gpio95";
- function = "qup11";
- };
-
- config {
- pins = "gpio94", "gpio95";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c11_default: qup-i2c11-default-state {
+ pins = "gpio94", "gpio95";
+ function = "qup11";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi11_default: qup-spi11-default {
+ qup_spi11_default: qup-spi11-default-state {
pins = "gpio92", "gpio93", "gpio94", "gpio95";
function = "qup11";
drive-strength = <6>;
bias-disable;
};
- qup_i2c12_default: qup-i2c12-default {
- mux {
- pins = "gpio83", "gpio84";
- function = "qup12";
- };
-
- config {
- pins = "gpio83", "gpio84";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c12_default: qup-i2c12-default-state {
+ pins = "gpio83", "gpio84";
+ function = "qup12";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi12_default: qup-spi12-default {
+ qup_spi12_default: qup-spi12-default-state {
pins = "gpio83", "gpio84", "gpio85", "gpio86";
function = "qup12";
drive-strength = <6>;
bias-disable;
};
- qup_i2c13_default: qup-i2c13-default {
- mux {
- pins = "gpio43", "gpio44";
- function = "qup13";
- };
-
- config {
- pins = "gpio43", "gpio44";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c13_default: qup-i2c13-default-state {
+ pins = "gpio43", "gpio44";
+ function = "qup13";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi13_default: qup-spi13-default {
+ qup_spi13_default: qup-spi13-default-state {
pins = "gpio43", "gpio44", "gpio45", "gpio46";
function = "qup13";
drive-strength = <6>;
bias-disable;
};
- qup_i2c14_default: qup-i2c14-default {
- mux {
- pins = "gpio47", "gpio48";
- function = "qup14";
- };
-
- config {
- pins = "gpio47", "gpio48";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c14_default: qup-i2c14-default-state {
+ pins = "gpio47", "gpio48";
+ function = "qup14";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi14_default: qup-spi14-default {
+ qup_spi14_default: qup-spi14-default-state {
pins = "gpio47", "gpio48", "gpio49", "gpio50";
function = "qup14";
drive-strength = <6>;
bias-disable;
};
- qup_i2c15_default: qup-i2c15-default {
- mux {
- pins = "gpio27", "gpio28";
- function = "qup15";
- };
-
- config {
- pins = "gpio27", "gpio28";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c15_default: qup-i2c15-default-state {
+ pins = "gpio27", "gpio28";
+ function = "qup15";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi15_default: qup-spi15-default {
+ qup_spi15_default: qup-spi15-default-state {
pins = "gpio27", "gpio28", "gpio29", "gpio30";
function = "qup15";
drive-strength = <6>;
bias-disable;
};
- qup_i2c16_default: qup-i2c16-default {
- mux {
- pins = "gpio86", "gpio85";
- function = "qup16";
- };
-
- config {
- pins = "gpio86", "gpio85";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c16_default: qup-i2c16-default-state {
+ pins = "gpio86", "gpio85";
+ function = "qup16";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi16_default: qup-spi16-default {
+ qup_spi16_default: qup-spi16-default-state {
pins = "gpio83", "gpio84", "gpio85", "gpio86";
function = "qup16";
drive-strength = <6>;
bias-disable;
};
- qup_i2c17_default: qup-i2c17-default {
- mux {
- pins = "gpio55", "gpio56";
- function = "qup17";
- };
-
- config {
- pins = "gpio55", "gpio56";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c17_default: qup-i2c17-default-state {
+ pins = "gpio55", "gpio56";
+ function = "qup17";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi17_default: qup-spi17-default {
+ qup_spi17_default: qup-spi17-default-state {
pins = "gpio55", "gpio56", "gpio57", "gpio58";
function = "qup17";
drive-strength = <6>;
bias-disable;
};
- qup_i2c18_default: qup-i2c18-default {
- mux {
- pins = "gpio23", "gpio24";
- function = "qup18";
- };
-
- config {
- pins = "gpio23", "gpio24";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c18_default: qup-i2c18-default-state {
+ pins = "gpio23", "gpio24";
+ function = "qup18";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi18_default: qup-spi18-default {
+ qup_spi18_default: qup-spi18-default-state {
pins = "gpio23", "gpio24", "gpio25", "gpio26";
function = "qup18";
drive-strength = <6>;
bias-disable;
};
- qup_i2c19_default: qup-i2c19-default {
- mux {
- pins = "gpio57", "gpio58";
- function = "qup19";
- };
-
- config {
- pins = "gpio57", "gpio58";
- drive-strength = <0x02>;
- bias-disable;
- };
+ qup_i2c19_default: qup-i2c19-default-state {
+ pins = "gpio57", "gpio58";
+ function = "qup19";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi19_default: qup-spi19-default {
+ qup_spi19_default: qup-spi19-default-state {
pins = "gpio55", "gpio56", "gpio57", "gpio58";
function = "qup19";
drive-strength = <6>;
bias-disable;
};
- pcie0_default_state: pcie0-default {
- perst {
+ pcie0_default_state: pcie0-default-state {
+ perst-pins {
pins = "gpio35";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
- clkreq {
+ clkreq-pins {
pins = "gpio36";
function = "pci_e0";
drive-strength = <2>;
bias-pull-up;
};
- wake {
+ wake-pins {
pins = "gpio37";
function = "gpio";
drive-strength = <2>;
@@ -2699,22 +2579,22 @@
};
};
- pcie1_default_state: pcie1-default {
- perst {
+ pcie1_default_state: pcie1-default-state {
+ perst-pins {
pins = "gpio102";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
- clkreq {
+ clkreq-pins {
pins = "gpio103";
function = "pci_e1";
drive-strength = <2>;
bias-pull-up;
};
- wake {
+ wake-pins {
pins = "gpio104";
function = "gpio";
drive-strength = <2>;
@@ -2739,8 +2619,8 @@
clocks = <&rpmhcc RPMH_CXO_CLK>;
clock-names = "xo";
- power-domains = <&rpmhpd 7>,
- <&rpmhpd 0>;
+ power-domains = <&rpmhpd SM8150_CX>,
+ <&rpmhpd SM8150_MSS>;
power-domain-names = "cx", "mss";
memory-region = <&mpss_mem>;
@@ -3366,7 +3246,7 @@
clocks = <&rpmhcc RPMH_CXO_CLK>;
clock-names = "xo";
- power-domains = <&rpmhpd 7>;
+ power-domains = <&rpmhpd SM8150_CX>;
memory-region = <&cdsp_mem>;
@@ -3867,7 +3747,7 @@
clocks = <&rpmhcc RPMH_CXO_CLK>;
clock-names = "xo";
- power-domains = <&rpmhpd 7>;
+ power-domains = <&rpmhpd SM8150_CX>;
memory-region = <&adsp_mem>;
@@ -4010,6 +3890,7 @@
<SLEEP_TCS 3>,
<WAKE_TCS 3>,
<CONTROL_TCS 1>;
+ power-domains = <&CLUSTER_PD>;
rpmhcc: clock-controller {
compatible = "qcom,sm8150-rpmh-clk";
@@ -4078,7 +3959,7 @@
};
osm_l3: interconnect@18321000 {
- compatible = "qcom,sm8150-osm-l3";
+ compatible = "qcom,sm8150-osm-l3", "qcom,osm-l3";
reg = <0 0x18321000 0 0x1400>;
clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>;
diff --git a/arch/arm64/boot/dts/qcom/sm8250-mtp.dts b/arch/arm64/boot/dts/qcom/sm8250-mtp.dts
index a102aa5efa32..3ed8c84e25b8 100644
--- a/arch/arm64/boot/dts/qcom/sm8250-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/sm8250-mtp.dts
@@ -635,7 +635,7 @@
wcd938x: codec {
compatible = "qcom,wcd9380-codec";
#sound-dai-cells = <1>;
- reset-gpios = <&tlmm 32 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&tlmm 32 GPIO_ACTIVE_LOW>;
vdd-buck-supply = <&vreg_s4a_1p8>;
vdd-rxtx-supply = <&vreg_s4a_1p8>;
vdd-io-supply = <&vreg_s4a_1p8>;
@@ -757,7 +757,7 @@
};
&swr0 {
- left_spkr: wsa8810-right@0,3{
+ left_spkr: speaker@0,3 {
compatible = "sdw10217211000";
reg = <0 3>;
powerdown-gpios = <&tlmm 26 GPIO_ACTIVE_HIGH>;
@@ -766,7 +766,7 @@
#sound-dai-cells = <0>;
};
- right_spkr: wsa8810-left@0,4{
+ right_spkr: speaker@0,4 {
compatible = "sdw10217211000";
reg = <0 4>;
powerdown-gpios = <&tlmm 127 GPIO_ACTIVE_HIGH>;
@@ -799,31 +799,19 @@
&tlmm {
gpio-reserved-ranges = <28 4>, <40 4>;
- wcd938x_reset_default: wcd938x_reset_default {
- mux {
- pins = "gpio32";
- function = "gpio";
- };
-
- config {
- pins = "gpio32";
- drive-strength = <16>;
- output-high;
- };
+ wcd938x_reset_default: wcd938x-reset-default-state {
+ pins = "gpio32";
+ function = "gpio";
+ drive-strength = <16>;
+ output-high;
};
- wcd938x_reset_sleep: wcd938x_reset_sleep {
- mux {
- pins = "gpio32";
- function = "gpio";
- };
-
- config {
- pins = "gpio32";
- drive-strength = <16>;
- bias-disable;
- output-low;
- };
+ wcd938x_reset_sleep: wcd938x-reset-sleep-state {
+ pins = "gpio32";
+ function = "gpio";
+ drive-strength = <16>;
+ bias-disable;
+ output-low;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi b/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi
index 5428aab3058d..09a31f707639 100644
--- a/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8250-sony-xperia-edo.dtsi
@@ -317,9 +317,8 @@
regulator-max-microvolt = <2960000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
regulator-allow-set-load;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
vreg_l7c_2p85: ldo7 {
@@ -342,9 +341,8 @@
regulator-max-microvolt = <2960000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
regulator-allow-set-load;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
vreg_l10c_3p3: ldo10 {
@@ -440,7 +438,16 @@
status = "okay";
clock-frequency = <400000>;
- /* NXP PN553 NFC @ 28 */
+ nfc@28 {
+ compatible = "nxp,nxp-nci-i2c";
+ reg = <0x28>;
+
+ interrupt-parent = <&tlmm>;
+ interrupts = <111 IRQ_TYPE_EDGE_RISING>;
+
+ enable-gpios = <&tlmm 6 GPIO_ACTIVE_HIGH>;
+ firmware-gpios = <&tlmm 110 GPIO_ACTIVE_HIGH>;
+ };
};
&i2c2 {
@@ -578,7 +585,7 @@
vqmmc-supply = <&vreg_l6c_2p9>;
bus-width = <4>;
no-sdio;
- no-emmc;
+ no-mmc;
};
&slpi {
@@ -588,49 +595,49 @@
&tlmm {
gpio-reserved-ranges = <40 4>, <52 4>;
- sdc2_default_state: sdc2-default {
- clk {
+ sdc2_default_state: sdc2-default-state {
+ clk-pins {
pins = "sdc2_clk";
drive-strength = <16>;
bias-disable;
};
- cmd {
+ cmd-pins {
pins = "sdc2_cmd";
drive-strength = <16>;
bias-pull-up;
};
- data {
+ data-pins {
pins = "sdc2_data";
drive-strength = <16>;
bias-pull-up;
};
};
- mdm2ap_default: mdm2ap-default {
+ mdm2ap_default: mdm2ap-default-state {
pins = "gpio1", "gpio3";
function = "gpio";
drive-strength = <8>;
bias-disable;
};
- ts_int_default: ts-int-default {
+ ts_int_default: ts-int-default-state {
pins = "gpio39";
function = "gpio";
drive-strength = <2>;
- bias-disabled;
+ bias-disable;
input-enable;
};
- ap2mdm_default: ap2mdm-default {
+ ap2mdm_default: ap2mdm-default-state {
pins = "gpio56", "gpio57";
function = "gpio";
drive-strength = <16>;
bias-disable;
};
- sdc2_card_det_n: sd-card-det-n {
+ sdc2_card_det_n: sd-card-det-n-state {
pins = "gpio77";
function = "gpio";
bias-pull-up;
diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi b/arch/arm64/boot/dts/qcom/sm8250.dtsi
index e276eed1f8e2..dab5579946f3 100644
--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi
@@ -937,7 +937,7 @@
};
gpi_dma2: dma-controller@800000 {
- compatible = "qcom,sm8250-gpi-dma";
+ compatible = "qcom,sm8250-gpi-dma", "qcom,sdm845-gpi-dma";
reg = <0 0x00800000 0 0x70000>;
interrupts = <GIC_SPI 588 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 589 IRQ_TYPE_LEVEL_HIGH>,
@@ -1188,7 +1188,7 @@
};
gpi_dma0: dma-controller@900000 {
- compatible = "qcom,sm8250-gpi-dma";
+ compatible = "qcom,sm8250-gpi-dma", "qcom,sdm845-gpi-dma";
reg = <0 0x00900000 0 0x70000>;
interrupts = <GIC_SPI 244 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>,
@@ -1506,7 +1506,7 @@
};
gpi_dma1: dma-controller@a00000 {
- compatible = "qcom,sm8250-gpi-dma";
+ compatible = "qcom,sm8250-gpi-dma", "qcom,sdm845-gpi-dma";
reg = <0 0x00a00000 0 0x70000>;
interrupts = <GIC_SPI 279 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 280 IRQ_TYPE_LEVEL_HIGH>,
@@ -2180,11 +2180,11 @@
status = "disabled";
ufs_mem_phy_lanes: phy@1d87400 {
- reg = <0 0x01d87400 0 0x108>,
- <0 0x01d87600 0 0x1e0>,
- <0 0x01d87c00 0 0x1dc>,
- <0 0x01d87800 0 0x108>,
- <0 0x01d87a00 0 0x1e0>;
+ reg = <0 0x01d87400 0 0x16c>,
+ <0 0x01d87600 0 0x200>,
+ <0 0x01d87c00 0 0x200>,
+ <0 0x01d87800 0 0x16c>,
+ <0 0x01d87a00 0 0x200>;
#phy-cells = <0>;
};
};
@@ -2361,7 +2361,6 @@
qcom,ports-word-length = /bits/ 8 <0xFF 0xFF 0xFF 0xFF 0xFF>;
qcom,ports-block-group-count = /bits/ 8 <0xFF 0xFF 0xFF 0xFF 0xFF>;
qcom,ports-lane-control = /bits/ 8 <0xFF 0x00 0x01 0x00 0x01>;
- qcom,port-offset = <1>;
#sound-dai-cells = <1>;
#address-cells = <2>;
#size-cells = <0>;
@@ -2389,8 +2388,8 @@
<&q6afecc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
clock-names = "core", "audio";
- wsa_swr_active: wsa-swr-active-pins {
- clk {
+ wsa_swr_active: wsa-swr-active-state {
+ clk-pins {
pins = "gpio10";
function = "wsa_swr_clk";
drive-strength = <2>;
@@ -2398,7 +2397,7 @@
bias-disable;
};
- data {
+ data-pins {
pins = "gpio11";
function = "wsa_swr_data";
drive-strength = <2>;
@@ -2408,8 +2407,8 @@
};
};
- wsa_swr_sleep: wsa-swr-sleep-pins {
- clk {
+ wsa_swr_sleep: wsa-swr-sleep-state {
+ clk-pins {
pins = "gpio10";
function = "wsa_swr_clk";
drive-strength = <2>;
@@ -2417,7 +2416,7 @@
bias-pull-down;
};
- data {
+ data-pins {
pins = "gpio11";
function = "wsa_swr_data";
drive-strength = <2>;
@@ -2427,14 +2426,14 @@
};
};
- dmic01_active: dmic01-active-pins {
- clk {
+ dmic01_active: dmic01-active-state {
+ clk-pins {
pins = "gpio6";
function = "dmic1_clk";
drive-strength = <8>;
output-high;
};
- data {
+ data-pins {
pins = "gpio7";
function = "dmic1_data";
drive-strength = <8>;
@@ -2442,8 +2441,8 @@
};
};
- dmic01_sleep: dmic01-sleep-pins {
- clk {
+ dmic01_sleep: dmic01-sleep-state {
+ clk-pins {
pins = "gpio6";
function = "dmic1_clk";
drive-strength = <2>;
@@ -2451,17 +2450,17 @@
output-low;
};
- data {
+ data-pins {
pins = "gpio7";
function = "dmic1_data";
drive-strength = <2>;
- pull-down;
+ bias-pull-down;
input-enable;
};
};
- rx_swr_active: rx_swr-active-pins {
- clk {
+ rx_swr_active: rx-swr-active-state {
+ clk-pins {
pins = "gpio3";
function = "swr_rx_clk";
drive-strength = <2>;
@@ -2469,7 +2468,7 @@
bias-disable;
};
- data {
+ data-pins {
pins = "gpio4", "gpio5";
function = "swr_rx_data";
drive-strength = <2>;
@@ -2478,8 +2477,8 @@
};
};
- tx_swr_active: tx_swr-active-pins {
- clk {
+ tx_swr_active: tx-swr-active-state {
+ clk-pins {
pins = "gpio0";
function = "swr_tx_clk";
drive-strength = <2>;
@@ -2487,7 +2486,7 @@
bias-disable;
};
- data {
+ data-pins {
pins = "gpio1", "gpio2";
function = "swr_tx_data";
drive-strength = <2>;
@@ -2496,8 +2495,8 @@
};
};
- tx_swr_sleep: tx_swr-sleep-pins {
- clk {
+ tx_swr_sleep: tx-swr-sleep-state {
+ clk-pins {
pins = "gpio0";
function = "swr_tx_clk";
drive-strength = <2>;
@@ -2505,7 +2504,7 @@
bias-pull-down;
};
- data1 {
+ data1-pins {
pins = "gpio1";
function = "swr_tx_data";
drive-strength = <2>;
@@ -2513,7 +2512,7 @@
bias-bus-hold;
};
- data2 {
+ data2-pins {
pins = "gpio2";
function = "swr_tx_data";
drive-strength = <2>;
@@ -2730,6 +2729,503 @@
};
};
+ stm@6002000 {
+ compatible = "arm,coresight-stm", "arm,primecell";
+ reg = <0 0x06002000 0 0x1000>, <0 0x16280000 0 0x180000>;
+ reg-names = "stm-base", "stm-stimulus-base";
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ stm_out: endpoint {
+ remote-endpoint = <&funnel0_in7>;
+ };
+ };
+ };
+ };
+
+ funnel@6041000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0 0x06041000 0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ funnel_in0_out_funnel_merg: endpoint {
+ remote-endpoint = <&funnel_merg_in_funnel_in0>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@7 {
+ reg = <7>;
+ funnel0_in7: endpoint {
+ remote-endpoint = <&stm_out>;
+ };
+ };
+ };
+ };
+
+ funnel@6042000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0 0x06042000 0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ funnel_in1_out_funnel_merg: endpoint {
+ remote-endpoint = <&funnel_merg_in_funnel_in1>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@4 {
+ reg = <4>;
+ funnel_in1_in_funnel_apss_merg: endpoint {
+ remote-endpoint = <&funnel_apss_merg_out_funnel_in1>;
+ };
+ };
+ };
+ };
+
+ funnel@6045000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0 0x06045000 0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ funnel_merg_out_funnel_swao: endpoint {
+ remote-endpoint = <&funnel_swao_in_funnel_merg>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ funnel_merg_in_funnel_in0: endpoint {
+ remote-endpoint = <&funnel_in0_out_funnel_merg>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ funnel_merg_in_funnel_in1: endpoint {
+ remote-endpoint = <&funnel_in1_out_funnel_merg>;
+ };
+ };
+ };
+ };
+
+ replicator@6046000 {
+ compatible = "arm,coresight-dynamic-replicator", "arm,primecell";
+ reg = <0 0x06046000 0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ replicator_out: endpoint {
+ remote-endpoint = <&etr_in>;
+ };
+ };
+ };
+
+ in-ports {
+ port {
+ replicator_cx_in_swao_out: endpoint {
+ remote-endpoint = <&replicator_swao_out_cx_in>;
+ };
+ };
+ };
+ };
+
+ etr@6048000 {
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0 0x06048000 0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+ arm,scatter-gather;
+
+ in-ports {
+ port {
+ etr_in: endpoint {
+ remote-endpoint = <&replicator_out>;
+ };
+ };
+ };
+ };
+
+ funnel@6b04000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ arm,primecell-periphid = <0x000bb908>;
+
+ reg = <0 0x06b04000 0 0x1000>;
+ reg-names = "funnel-base";
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ funnel_swao_out_etf: endpoint {
+ remote-endpoint = <&etf_in_funnel_swao_out>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@7 {
+ reg = <7>;
+ funnel_swao_in_funnel_merg: endpoint {
+ remote-endpoint= <&funnel_merg_out_funnel_swao>;
+ };
+ };
+ };
+
+ };
+
+ etf@6b05000 {
+ compatible = "arm,coresight-tmc", "arm,primecell";
+ reg = <0 0x06b05000 0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ etf_out: endpoint {
+ remote-endpoint = <&replicator_in>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ etf_in_funnel_swao_out: endpoint {
+ remote-endpoint = <&funnel_swao_out_etf>;
+ };
+ };
+ };
+ };
+
+ replicator@6b06000 {
+ compatible = "arm,coresight-dynamic-replicator", "arm,primecell";
+ reg = <0 0x06b06000 0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ replicator_swao_out_cx_in: endpoint {
+ remote-endpoint = <&replicator_cx_in_swao_out>;
+ };
+ };
+ };
+
+ in-ports {
+ port {
+ replicator_in: endpoint {
+ remote-endpoint = <&etf_out>;
+ };
+ };
+ };
+ };
+
+ etm@7040000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x07040000 0 0x1000>;
+
+ cpu = <&CPU0>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+ arm,coresight-loses-context-with-cpu;
+
+ out-ports {
+ port {
+ etm0_out: endpoint {
+ remote-endpoint = <&apss_funnel_in0>;
+ };
+ };
+ };
+ };
+
+ etm@7140000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x07140000 0 0x1000>;
+
+ cpu = <&CPU1>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+ arm,coresight-loses-context-with-cpu;
+
+ out-ports {
+ port {
+ etm1_out: endpoint {
+ remote-endpoint = <&apss_funnel_in1>;
+ };
+ };
+ };
+ };
+
+ etm@7240000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x07240000 0 0x1000>;
+
+ cpu = <&CPU2>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+ arm,coresight-loses-context-with-cpu;
+
+ out-ports {
+ port {
+ etm2_out: endpoint {
+ remote-endpoint = <&apss_funnel_in2>;
+ };
+ };
+ };
+ };
+
+ etm@7340000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x07340000 0 0x1000>;
+
+ cpu = <&CPU3>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+ arm,coresight-loses-context-with-cpu;
+
+ out-ports {
+ port {
+ etm3_out: endpoint {
+ remote-endpoint = <&apss_funnel_in3>;
+ };
+ };
+ };
+ };
+
+ etm@7440000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x07440000 0 0x1000>;
+
+ cpu = <&CPU4>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+ arm,coresight-loses-context-with-cpu;
+
+ out-ports {
+ port {
+ etm4_out: endpoint {
+ remote-endpoint = <&apss_funnel_in4>;
+ };
+ };
+ };
+ };
+
+ etm@7540000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x07540000 0 0x1000>;
+
+ cpu = <&CPU5>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+ arm,coresight-loses-context-with-cpu;
+
+ out-ports {
+ port {
+ etm5_out: endpoint {
+ remote-endpoint = <&apss_funnel_in5>;
+ };
+ };
+ };
+ };
+
+ etm@7640000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x07640000 0 0x1000>;
+
+ cpu = <&CPU6>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+ arm,coresight-loses-context-with-cpu;
+
+ out-ports {
+ port {
+ etm6_out: endpoint {
+ remote-endpoint = <&apss_funnel_in6>;
+ };
+ };
+ };
+ };
+
+ etm@7740000 {
+ compatible = "arm,coresight-etm4x", "arm,primecell";
+ reg = <0 0x07740000 0 0x1000>;
+
+ cpu = <&CPU7>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+ arm,coresight-loses-context-with-cpu;
+
+ out-ports {
+ port {
+ etm7_out: endpoint {
+ remote-endpoint = <&apss_funnel_in7>;
+ };
+ };
+ };
+ };
+
+ funnel@7800000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0 0x07800000 0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ port {
+ funnel_apss_out_funnel_apss_merg: endpoint {
+ remote-endpoint = <&funnel_apss_merg_in_funnel_apss>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ apss_funnel_in0: endpoint {
+ remote-endpoint = <&etm0_out>;
+ };
+ };
+
+ port@1 {
+ reg = <1>;
+ apss_funnel_in1: endpoint {
+ remote-endpoint = <&etm1_out>;
+ };
+ };
+
+ port@2 {
+ reg = <2>;
+ apss_funnel_in2: endpoint {
+ remote-endpoint = <&etm2_out>;
+ };
+ };
+
+ port@3 {
+ reg = <3>;
+ apss_funnel_in3: endpoint {
+ remote-endpoint = <&etm3_out>;
+ };
+ };
+
+ port@4 {
+ reg = <4>;
+ apss_funnel_in4: endpoint {
+ remote-endpoint = <&etm4_out>;
+ };
+ };
+
+ port@5 {
+ reg = <5>;
+ apss_funnel_in5: endpoint {
+ remote-endpoint = <&etm5_out>;
+ };
+ };
+
+ port@6 {
+ reg = <6>;
+ apss_funnel_in6: endpoint {
+ remote-endpoint = <&etm6_out>;
+ };
+ };
+
+ port@7 {
+ reg = <7>;
+ apss_funnel_in7: endpoint {
+ remote-endpoint = <&etm7_out>;
+ };
+ };
+ };
+ };
+
+ funnel@7810000 {
+ compatible = "arm,coresight-dynamic-funnel", "arm,primecell";
+ reg = <0 0x07810000 0 0x1000>;
+
+ clocks = <&aoss_qmp>;
+ clock-names = "apb_pclk";
+
+ out-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port {
+ funnel_apss_merg_out_funnel_in1: endpoint {
+ remote-endpoint = <&funnel_in1_in_funnel_apss_merg>;
+ };
+ };
+ };
+
+ in-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ funnel_apss_merg_in_funnel_apss: endpoint {
+ remote-endpoint = <&funnel_apss_out_funnel_apss_merg>;
+ };
+ };
+ };
+ };
+
cdsp: remoteproc@8300000 {
compatible = "qcom,sm8250-cdsp-pas";
reg = <0 0x08300000 0 0x10000>;
@@ -2892,15 +3388,11 @@
dp_phy: dp-phy@88ea200 {
reg = <0 0x088ea200 0 0x200>,
<0 0x088ea400 0 0x200>,
- <0 0x088eac00 0 0x400>,
+ <0 0x088eaa00 0 0x200>,
<0 0x088ea600 0 0x200>,
- <0 0x088ea800 0 0x200>,
- <0 0x088eaa00 0 0x100>;
+ <0 0x088ea800 0 0x200>;
#phy-cells = <0>;
#clock-cells = <1>;
- clocks = <&gcc GCC_USB3_PRIM_PHY_PIPE_CLK>;
- clock-names = "pipe0";
- clock-output-names = "usb3_phy_pipe_clk_src";
};
};
@@ -3416,6 +3908,35 @@
"cam_hf_0_mnoc",
"cam_sf_0_mnoc",
"cam_sf_icp_mnoc";
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ };
+
+ port@1 {
+ reg = <1>;
+ };
+
+ port@2 {
+ reg = <2>;
+ };
+
+ port@3 {
+ reg = <3>;
+ };
+
+ port@4 {
+ reg = <4>;
+ };
+
+ port@5 {
+ reg = <5>;
+ };
+ };
};
camcc: clock-controller@ad00000 {
@@ -3556,7 +4077,6 @@
power-domains = <&rpmhpd SM8250_MMCX>;
phys = <&dsi0_phy>;
- phy-names = "dsi";
status = "disabled";
@@ -3601,7 +4121,7 @@
};
};
- dsi0_phy: dsi-phy@ae94400 {
+ dsi0_phy: phy@ae94400 {
compatible = "qcom,dsi-phy-7nm";
reg = <0 0x0ae94400 0 0x200>,
<0 0x0ae94600 0 0x280>,
@@ -3648,7 +4168,6 @@
power-domains = <&rpmhpd SM8250_MMCX>;
phys = <&dsi1_phy>;
- phy-names = "dsi";
status = "disabled";
@@ -3674,7 +4193,7 @@
};
};
- dsi1_phy: dsi-phy@ae96400 {
+ dsi1_phy: phy@ae96400 {
compatible = "qcom,dsi-phy-7nm";
reg = <0 0x0ae96400 0 0x200>,
<0 0x0ae96600 0 0x280>,
@@ -3799,8 +4318,41 @@
gpio-ranges = <&tlmm 0 0 181>;
wakeup-parent = <&pdc>;
- cci0_default: cci0-default {
- cci0_i2c0_default: cci0-i2c0-default {
+ cam2_default: cam2-default-state {
+ rst-pins {
+ pins = "gpio78";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ mclk-pins {
+ pins = "gpio96";
+ function = "cam_mclk";
+ drive-strength = <16>;
+ bias-disable;
+ };
+ };
+
+ cam2_suspend: cam2-suspend-state {
+ rst-pins {
+ pins = "gpio78";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-down;
+ output-low;
+ };
+
+ mclk-pins {
+ pins = "gpio96";
+ function = "cam_mclk";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+
+ cci0_default: cci0-default-state {
+ cci0_i2c0_default: cci0-i2c0-default-pins {
/* SDA, SCL */
pins = "gpio101", "gpio102";
function = "cci_i2c";
@@ -3809,7 +4361,7 @@
drive-strength = <2>; /* 2 mA */
};
- cci0_i2c1_default: cci0-i2c1-default {
+ cci0_i2c1_default: cci0-i2c1-default-pins {
/* SDA, SCL */
pins = "gpio103", "gpio104";
function = "cci_i2c";
@@ -3819,8 +4371,8 @@
};
};
- cci0_sleep: cci0-sleep {
- cci0_i2c0_sleep: cci0-i2c0-sleep {
+ cci0_sleep: cci0-sleep-state {
+ cci0_i2c0_sleep: cci0-i2c0-sleep-pins {
/* SDA, SCL */
pins = "gpio101", "gpio102";
function = "cci_i2c";
@@ -3829,7 +4381,7 @@
bias-pull-down;
};
- cci0_i2c1_sleep: cci0-i2c1-sleep {
+ cci0_i2c1_sleep: cci0-i2c1-sleep-pins {
/* SDA, SCL */
pins = "gpio103", "gpio104";
function = "cci_i2c";
@@ -3839,8 +4391,8 @@
};
};
- cci1_default: cci1-default {
- cci1_i2c0_default: cci1-i2c0-default {
+ cci1_default: cci1-default-state {
+ cci1_i2c0_default: cci1-i2c0-default-pins {
/* SDA, SCL */
pins = "gpio105","gpio106";
function = "cci_i2c";
@@ -3849,7 +4401,7 @@
drive-strength = <2>; /* 2 mA */
};
- cci1_i2c1_default: cci1-i2c1-default {
+ cci1_i2c1_default: cci1-i2c1-default-pins {
/* SDA, SCL */
pins = "gpio107","gpio108";
function = "cci_i2c";
@@ -3859,8 +4411,8 @@
};
};
- cci1_sleep: cci1-sleep {
- cci1_i2c0_sleep: cci1-i2c0-sleep {
+ cci1_sleep: cci1-sleep-state {
+ cci1_i2c0_sleep: cci1-i2c0-sleep-pins {
/* SDA, SCL */
pins = "gpio105","gpio106";
function = "cci_i2c";
@@ -3869,7 +4421,7 @@
drive-strength = <2>; /* 2 mA */
};
- cci1_i2c1_sleep: cci1-i2c1-sleep {
+ cci1_i2c1_sleep: cci1-i2c1-sleep-pins {
/* SDA, SCL */
pins = "gpio107","gpio108";
function = "cci_i2c";
@@ -3879,22 +4431,22 @@
};
};
- pri_mi2s_active: pri-mi2s-active {
- sclk {
+ pri_mi2s_active: pri-mi2s-active-state {
+ sclk-pins {
pins = "gpio138";
function = "mi2s0_sck";
drive-strength = <8>;
bias-disable;
};
- ws {
+ ws-pins {
pins = "gpio141";
function = "mi2s0_ws";
drive-strength = <8>;
output-high;
};
- data0 {
+ data0-pins {
pins = "gpio139";
function = "mi2s0_data0";
drive-strength = <8>;
@@ -3902,7 +4454,7 @@
output-high;
};
- data1 {
+ data1-pins {
pins = "gpio140";
function = "mi2s0_data1";
drive-strength = <8>;
@@ -3910,632 +4462,500 @@
};
};
- qup_i2c0_default: qup-i2c0-default {
- mux {
- pins = "gpio28", "gpio29";
- function = "qup0";
- };
-
- config {
- pins = "gpio28", "gpio29";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c0_default: qup-i2c0-default-state {
+ pins = "gpio28", "gpio29";
+ function = "qup0";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_i2c1_default: qup-i2c1-default {
- pinmux {
- pins = "gpio4", "gpio5";
- function = "qup1";
- };
-
- config {
- pins = "gpio4", "gpio5";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c1_default: qup-i2c1-default-state {
+ pins = "gpio4", "gpio5";
+ function = "qup1";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_i2c2_default: qup-i2c2-default {
- mux {
- pins = "gpio115", "gpio116";
- function = "qup2";
- };
-
- config {
- pins = "gpio115", "gpio116";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c2_default: qup-i2c2-default-state {
+ pins = "gpio115", "gpio116";
+ function = "qup2";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_i2c3_default: qup-i2c3-default {
- mux {
- pins = "gpio119", "gpio120";
- function = "qup3";
- };
-
- config {
- pins = "gpio119", "gpio120";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c3_default: qup-i2c3-default-state {
+ pins = "gpio119", "gpio120";
+ function = "qup3";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_i2c4_default: qup-i2c4-default {
- mux {
- pins = "gpio8", "gpio9";
- function = "qup4";
- };
-
- config {
- pins = "gpio8", "gpio9";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c4_default: qup-i2c4-default-state {
+ pins = "gpio8", "gpio9";
+ function = "qup4";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_i2c5_default: qup-i2c5-default {
- mux {
- pins = "gpio12", "gpio13";
- function = "qup5";
- };
-
- config {
- pins = "gpio12", "gpio13";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c5_default: qup-i2c5-default-state {
+ pins = "gpio12", "gpio13";
+ function = "qup5";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_i2c6_default: qup-i2c6-default {
- mux {
- pins = "gpio16", "gpio17";
- function = "qup6";
- };
-
- config {
- pins = "gpio16", "gpio17";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c6_default: qup-i2c6-default-state {
+ pins = "gpio16", "gpio17";
+ function = "qup6";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_i2c7_default: qup-i2c7-default {
- mux {
- pins = "gpio20", "gpio21";
- function = "qup7";
- };
-
- config {
- pins = "gpio20", "gpio21";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c7_default: qup-i2c7-default-state {
+ pins = "gpio20", "gpio21";
+ function = "qup7";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_i2c8_default: qup-i2c8-default {
- mux {
- pins = "gpio24", "gpio25";
- function = "qup8";
- };
-
- config {
- pins = "gpio24", "gpio25";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c8_default: qup-i2c8-default-state {
+ pins = "gpio24", "gpio25";
+ function = "qup8";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_i2c9_default: qup-i2c9-default {
- mux {
- pins = "gpio125", "gpio126";
- function = "qup9";
- };
-
- config {
- pins = "gpio125", "gpio126";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c9_default: qup-i2c9-default-state {
+ pins = "gpio125", "gpio126";
+ function = "qup9";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_i2c10_default: qup-i2c10-default {
- mux {
- pins = "gpio129", "gpio130";
- function = "qup10";
- };
-
- config {
- pins = "gpio129", "gpio130";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c10_default: qup-i2c10-default-state {
+ pins = "gpio129", "gpio130";
+ function = "qup10";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_i2c11_default: qup-i2c11-default {
- mux {
- pins = "gpio60", "gpio61";
- function = "qup11";
- };
-
- config {
- pins = "gpio60", "gpio61";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c11_default: qup-i2c11-default-state {
+ pins = "gpio60", "gpio61";
+ function = "qup11";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_i2c12_default: qup-i2c12-default {
- mux {
- pins = "gpio32", "gpio33";
- function = "qup12";
- };
-
- config {
- pins = "gpio32", "gpio33";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c12_default: qup-i2c12-default-state {
+ pins = "gpio32", "gpio33";
+ function = "qup12";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_i2c13_default: qup-i2c13-default {
- mux {
- pins = "gpio36", "gpio37";
- function = "qup13";
- };
-
- config {
- pins = "gpio36", "gpio37";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c13_default: qup-i2c13-default-state {
+ pins = "gpio36", "gpio37";
+ function = "qup13";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_i2c14_default: qup-i2c14-default {
- mux {
- pins = "gpio40", "gpio41";
- function = "qup14";
- };
-
- config {
- pins = "gpio40", "gpio41";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c14_default: qup-i2c14-default-state {
+ pins = "gpio40", "gpio41";
+ function = "qup14";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_i2c15_default: qup-i2c15-default {
- mux {
- pins = "gpio44", "gpio45";
- function = "qup15";
- };
-
- config {
- pins = "gpio44", "gpio45";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c15_default: qup-i2c15-default-state {
+ pins = "gpio44", "gpio45";
+ function = "qup15";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_i2c16_default: qup-i2c16-default {
- mux {
- pins = "gpio48", "gpio49";
- function = "qup16";
- };
-
- config {
- pins = "gpio48", "gpio49";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c16_default: qup-i2c16-default-state {
+ pins = "gpio48", "gpio49";
+ function = "qup16";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_i2c17_default: qup-i2c17-default {
- mux {
- pins = "gpio52", "gpio53";
- function = "qup17";
- };
-
- config {
- pins = "gpio52", "gpio53";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c17_default: qup-i2c17-default-state {
+ pins = "gpio52", "gpio53";
+ function = "qup17";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_i2c18_default: qup-i2c18-default {
- mux {
- pins = "gpio56", "gpio57";
- function = "qup18";
- };
-
- config {
- pins = "gpio56", "gpio57";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c18_default: qup-i2c18-default-state {
+ pins = "gpio56", "gpio57";
+ function = "qup18";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_i2c19_default: qup-i2c19-default {
- mux {
- pins = "gpio0", "gpio1";
- function = "qup19";
- };
-
- config {
- pins = "gpio0", "gpio1";
- drive-strength = <2>;
- bias-disable;
- };
+ qup_i2c19_default: qup-i2c19-default-state {
+ pins = "gpio0", "gpio1";
+ function = "qup19";
+ drive-strength = <2>;
+ bias-disable;
};
- qup_spi0_cs: qup-spi0-cs {
+ qup_spi0_cs: qup-spi0-cs-state {
pins = "gpio31";
function = "qup0";
};
- qup_spi0_cs_gpio: qup-spi0-cs-gpio {
+ qup_spi0_cs_gpio: qup-spi0-cs-gpio-state {
pins = "gpio31";
function = "gpio";
};
- qup_spi0_data_clk: qup-spi0-data-clk {
+ qup_spi0_data_clk: qup-spi0-data-clk-state {
pins = "gpio28", "gpio29",
"gpio30";
function = "qup0";
};
- qup_spi1_cs: qup-spi1-cs {
+ qup_spi1_cs: qup-spi1-cs-state {
pins = "gpio7";
function = "qup1";
};
- qup_spi1_cs_gpio: qup-spi1-cs-gpio {
+ qup_spi1_cs_gpio: qup-spi1-cs-gpio-state {
pins = "gpio7";
function = "gpio";
};
- qup_spi1_data_clk: qup-spi1-data-clk {
+ qup_spi1_data_clk: qup-spi1-data-clk-state {
pins = "gpio4", "gpio5",
"gpio6";
function = "qup1";
};
- qup_spi2_cs: qup-spi2-cs {
+ qup_spi2_cs: qup-spi2-cs-state {
pins = "gpio118";
function = "qup2";
};
- qup_spi2_cs_gpio: qup-spi2-cs-gpio {
+ qup_spi2_cs_gpio: qup-spi2-cs-gpio-state {
pins = "gpio118";
function = "gpio";
};
- qup_spi2_data_clk: qup-spi2-data-clk {
+ qup_spi2_data_clk: qup-spi2-data-clk-state {
pins = "gpio115", "gpio116",
"gpio117";
function = "qup2";
};
- qup_spi3_cs: qup-spi3-cs {
+ qup_spi3_cs: qup-spi3-cs-state {
pins = "gpio122";
function = "qup3";
};
- qup_spi3_cs_gpio: qup-spi3-cs-gpio {
+ qup_spi3_cs_gpio: qup-spi3-cs-gpio-state {
pins = "gpio122";
function = "gpio";
};
- qup_spi3_data_clk: qup-spi3-data-clk {
+ qup_spi3_data_clk: qup-spi3-data-clk-state {
pins = "gpio119", "gpio120",
"gpio121";
function = "qup3";
};
- qup_spi4_cs: qup-spi4-cs {
+ qup_spi4_cs: qup-spi4-cs-state {
pins = "gpio11";
function = "qup4";
};
- qup_spi4_cs_gpio: qup-spi4-cs-gpio {
+ qup_spi4_cs_gpio: qup-spi4-cs-gpio-state {
pins = "gpio11";
function = "gpio";
};
- qup_spi4_data_clk: qup-spi4-data-clk {
+ qup_spi4_data_clk: qup-spi4-data-clk-state {
pins = "gpio8", "gpio9",
"gpio10";
function = "qup4";
};
- qup_spi5_cs: qup-spi5-cs {
+ qup_spi5_cs: qup-spi5-cs-state {
pins = "gpio15";
function = "qup5";
};
- qup_spi5_cs_gpio: qup-spi5-cs-gpio {
+ qup_spi5_cs_gpio: qup-spi5-cs-gpio-state {
pins = "gpio15";
function = "gpio";
};
- qup_spi5_data_clk: qup-spi5-data-clk {
+ qup_spi5_data_clk: qup-spi5-data-clk-state {
pins = "gpio12", "gpio13",
"gpio14";
function = "qup5";
};
- qup_spi6_cs: qup-spi6-cs {
+ qup_spi6_cs: qup-spi6-cs-state {
pins = "gpio19";
function = "qup6";
};
- qup_spi6_cs_gpio: qup-spi6-cs-gpio {
+ qup_spi6_cs_gpio: qup-spi6-cs-gpio-state {
pins = "gpio19";
function = "gpio";
};
- qup_spi6_data_clk: qup-spi6-data-clk {
+ qup_spi6_data_clk: qup-spi6-data-clk-state {
pins = "gpio16", "gpio17",
"gpio18";
function = "qup6";
};
- qup_spi7_cs: qup-spi7-cs {
+ qup_spi7_cs: qup-spi7-cs-state {
pins = "gpio23";
function = "qup7";
};
- qup_spi7_cs_gpio: qup-spi7-cs-gpio {
+ qup_spi7_cs_gpio: qup-spi7-cs-gpio-state {
pins = "gpio23";
function = "gpio";
};
- qup_spi7_data_clk: qup-spi7-data-clk {
+ qup_spi7_data_clk: qup-spi7-data-clk-state {
pins = "gpio20", "gpio21",
"gpio22";
function = "qup7";
};
- qup_spi8_cs: qup-spi8-cs {
+ qup_spi8_cs: qup-spi8-cs-state {
pins = "gpio27";
function = "qup8";
};
- qup_spi8_cs_gpio: qup-spi8-cs-gpio {
+ qup_spi8_cs_gpio: qup-spi8-cs-gpio-state {
pins = "gpio27";
function = "gpio";
};
- qup_spi8_data_clk: qup-spi8-data-clk {
+ qup_spi8_data_clk: qup-spi8-data-clk-state {
pins = "gpio24", "gpio25",
"gpio26";
function = "qup8";
};
- qup_spi9_cs: qup-spi9-cs {
+ qup_spi9_cs: qup-spi9-cs-state {
pins = "gpio128";
function = "qup9";
};
- qup_spi9_cs_gpio: qup-spi9-cs-gpio {
+ qup_spi9_cs_gpio: qup-spi9-cs-gpio-state {
pins = "gpio128";
function = "gpio";
};
- qup_spi9_data_clk: qup-spi9-data-clk {
+ qup_spi9_data_clk: qup-spi9-data-clk-state {
pins = "gpio125", "gpio126",
"gpio127";
function = "qup9";
};
- qup_spi10_cs: qup-spi10-cs {
+ qup_spi10_cs: qup-spi10-cs-state {
pins = "gpio132";
function = "qup10";
};
- qup_spi10_cs_gpio: qup-spi10-cs-gpio {
+ qup_spi10_cs_gpio: qup-spi10-cs-gpio-state {
pins = "gpio132";
function = "gpio";
};
- qup_spi10_data_clk: qup-spi10-data-clk {
+ qup_spi10_data_clk: qup-spi10-data-clk-state {
pins = "gpio129", "gpio130",
"gpio131";
function = "qup10";
};
- qup_spi11_cs: qup-spi11-cs {
+ qup_spi11_cs: qup-spi11-cs-state {
pins = "gpio63";
function = "qup11";
};
- qup_spi11_cs_gpio: qup-spi11-cs-gpio {
+ qup_spi11_cs_gpio: qup-spi11-cs-gpio-state {
pins = "gpio63";
function = "gpio";
};
- qup_spi11_data_clk: qup-spi11-data-clk {
+ qup_spi11_data_clk: qup-spi11-data-clk-state {
pins = "gpio60", "gpio61",
"gpio62";
function = "qup11";
};
- qup_spi12_cs: qup-spi12-cs {
+ qup_spi12_cs: qup-spi12-cs-state {
pins = "gpio35";
function = "qup12";
};
- qup_spi12_cs_gpio: qup-spi12-cs-gpio {
+ qup_spi12_cs_gpio: qup-spi12-cs-gpio-state {
pins = "gpio35";
function = "gpio";
};
- qup_spi12_data_clk: qup-spi12-data-clk {
+ qup_spi12_data_clk: qup-spi12-data-clk-state {
pins = "gpio32", "gpio33",
"gpio34";
function = "qup12";
};
- qup_spi13_cs: qup-spi13-cs {
+ qup_spi13_cs: qup-spi13-cs-state {
pins = "gpio39";
function = "qup13";
};
- qup_spi13_cs_gpio: qup-spi13-cs-gpio {
+ qup_spi13_cs_gpio: qup-spi13-cs-gpio-state {
pins = "gpio39";
function = "gpio";
};
- qup_spi13_data_clk: qup-spi13-data-clk {
+ qup_spi13_data_clk: qup-spi13-data-clk-state {
pins = "gpio36", "gpio37",
"gpio38";
function = "qup13";
};
- qup_spi14_cs: qup-spi14-cs {
+ qup_spi14_cs: qup-spi14-cs-state {
pins = "gpio43";
function = "qup14";
};
- qup_spi14_cs_gpio: qup-spi14-cs-gpio {
+ qup_spi14_cs_gpio: qup-spi14-cs-gpio-state {
pins = "gpio43";
function = "gpio";
};
- qup_spi14_data_clk: qup-spi14-data-clk {
+ qup_spi14_data_clk: qup-spi14-data-clk-state {
pins = "gpio40", "gpio41",
"gpio42";
function = "qup14";
};
- qup_spi15_cs: qup-spi15-cs {
+ qup_spi15_cs: qup-spi15-cs-state {
pins = "gpio47";
function = "qup15";
};
- qup_spi15_cs_gpio: qup-spi15-cs-gpio {
+ qup_spi15_cs_gpio: qup-spi15-cs-gpio-state {
pins = "gpio47";
function = "gpio";
};
- qup_spi15_data_clk: qup-spi15-data-clk {
+ qup_spi15_data_clk: qup-spi15-data-clk-state {
pins = "gpio44", "gpio45",
"gpio46";
function = "qup15";
};
- qup_spi16_cs: qup-spi16-cs {
+ qup_spi16_cs: qup-spi16-cs-state {
pins = "gpio51";
function = "qup16";
};
- qup_spi16_cs_gpio: qup-spi16-cs-gpio {
+ qup_spi16_cs_gpio: qup-spi16-cs-gpio-state {
pins = "gpio51";
function = "gpio";
};
- qup_spi16_data_clk: qup-spi16-data-clk {
+ qup_spi16_data_clk: qup-spi16-data-clk-state {
pins = "gpio48", "gpio49",
"gpio50";
function = "qup16";
};
- qup_spi17_cs: qup-spi17-cs {
+ qup_spi17_cs: qup-spi17-cs-state {
pins = "gpio55";
function = "qup17";
};
- qup_spi17_cs_gpio: qup-spi17-cs-gpio {
+ qup_spi17_cs_gpio: qup-spi17-cs-gpio-state {
pins = "gpio55";
function = "gpio";
};
- qup_spi17_data_clk: qup-spi17-data-clk {
+ qup_spi17_data_clk: qup-spi17-data-clk-state {
pins = "gpio52", "gpio53",
"gpio54";
function = "qup17";
};
- qup_spi18_cs: qup-spi18-cs {
+ qup_spi18_cs: qup-spi18-cs-state {
pins = "gpio59";
function = "qup18";
};
- qup_spi18_cs_gpio: qup-spi18-cs-gpio {
+ qup_spi18_cs_gpio: qup-spi18-cs-gpio-state {
pins = "gpio59";
function = "gpio";
};
- qup_spi18_data_clk: qup-spi18-data-clk {
+ qup_spi18_data_clk: qup-spi18-data-clk-state {
pins = "gpio56", "gpio57",
"gpio58";
function = "qup18";
};
- qup_spi19_cs: qup-spi19-cs {
+ qup_spi19_cs: qup-spi19-cs-state {
pins = "gpio3";
function = "qup19";
};
- qup_spi19_cs_gpio: qup-spi19-cs-gpio {
+ qup_spi19_cs_gpio: qup-spi19-cs-gpio-state {
pins = "gpio3";
function = "gpio";
};
- qup_spi19_data_clk: qup-spi19-data-clk {
+ qup_spi19_data_clk: qup-spi19-data-clk-state {
pins = "gpio0", "gpio1",
"gpio2";
function = "qup19";
};
- qup_uart2_default: qup-uart2-default {
- mux {
- pins = "gpio117", "gpio118";
- function = "qup2";
- };
+ qup_uart2_default: qup-uart2-default-state {
+ pins = "gpio117", "gpio118";
+ function = "qup2";
};
- qup_uart6_default: qup-uart6-default {
- mux {
- pins = "gpio16", "gpio17",
- "gpio18", "gpio19";
- function = "qup6";
- };
+ qup_uart6_default: qup-uart6-default-state {
+ pins = "gpio16", "gpio17", "gpio18", "gpio19";
+ function = "qup6";
};
- qup_uart12_default: qup-uart12-default {
- mux {
- pins = "gpio34", "gpio35";
- function = "qup12";
- };
+ qup_uart12_default: qup-uart12-default-state {
+ pins = "gpio34", "gpio35";
+ function = "qup12";
};
- qup_uart17_default: qup-uart17-default {
- mux {
- pins = "gpio52", "gpio53",
- "gpio54", "gpio55";
- function = "qup17";
- };
+ qup_uart17_default: qup-uart17-default-state {
+ pins = "gpio52", "gpio53", "gpio54", "gpio55";
+ function = "qup17";
};
- qup_uart18_default: qup-uart18-default {
- mux {
- pins = "gpio58", "gpio59";
- function = "qup18";
- };
+ qup_uart18_default: qup-uart18-default-state {
+ pins = "gpio58", "gpio59";
+ function = "qup18";
};
- tert_mi2s_active: tert-mi2s-active {
- sck {
+ tert_mi2s_active: tert-mi2s-active-state {
+ sck-pins {
pins = "gpio133";
function = "mi2s2_sck";
drive-strength = <8>;
bias-disable;
};
- data0 {
+ data0-pins {
pins = "gpio134";
function = "mi2s2_data0";
drive-strength = <8>;
@@ -4543,7 +4963,7 @@
output-high;
};
- ws {
+ ws-pins {
pins = "gpio135";
function = "mi2s2_ws";
drive-strength = <8>;
@@ -4551,42 +4971,42 @@
};
};
- sdc2_sleep_state: sdc2-sleep {
- clk {
+ sdc2_sleep_state: sdc2-sleep-state {
+ clk-pins {
pins = "sdc2_clk";
drive-strength = <2>;
bias-disable;
};
- cmd {
+ cmd-pins {
pins = "sdc2_cmd";
drive-strength = <2>;
bias-pull-up;
};
- data {
+ data-pins {
pins = "sdc2_data";
drive-strength = <2>;
bias-pull-up;
};
};
- pcie0_default_state: pcie0-default {
- perst {
+ pcie0_default_state: pcie0-default-state {
+ perst-pins {
pins = "gpio79";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
- clkreq {
+ clkreq-pins {
pins = "gpio80";
function = "pci_e0";
drive-strength = <2>;
bias-pull-up;
};
- wake {
+ wake-pins {
pins = "gpio81";
function = "gpio";
drive-strength = <2>;
@@ -4594,22 +5014,22 @@
};
};
- pcie1_default_state: pcie1-default {
- perst {
+ pcie1_default_state: pcie1-default-state {
+ perst-pins {
pins = "gpio82";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
- clkreq {
+ clkreq-pins {
pins = "gpio83";
function = "pci_e1";
drive-strength = <2>;
bias-pull-up;
};
- wake {
+ wake-pins {
pins = "gpio84";
function = "gpio";
drive-strength = <2>;
@@ -4617,22 +5037,22 @@
};
};
- pcie2_default_state: pcie2-default {
- perst {
+ pcie2_default_state: pcie2-default-state {
+ perst-pins {
pins = "gpio85";
function = "gpio";
drive-strength = <2>;
bias-pull-down;
};
- clkreq {
+ clkreq-pins {
pins = "gpio86";
function = "pci_e2";
drive-strength = <2>;
bias-pull-up;
};
- wake {
+ wake-pins {
pins = "gpio87";
function = "gpio";
drive-strength = <2>;
@@ -4791,13 +5211,13 @@
#address-cells = <1>;
#size-cells = <0>;
- apr-service@3 {
+ service@3 {
reg = <APR_SVC_ADSP_CORE>;
compatible = "qcom,q6core";
qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
};
- q6afe: apr-service@4 {
+ q6afe: service@4 {
compatible = "qcom,q6afe";
reg = <APR_SVC_AFE>;
qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
@@ -4808,13 +5228,13 @@
#sound-dai-cells = <1>;
};
- q6afecc: cc {
+ q6afecc: clock-controller {
compatible = "qcom,q6afe-clocks";
#clock-cells = <2>;
};
};
- q6asm: apr-service@7 {
+ q6asm: service@7 {
compatible = "qcom,q6asm";
reg = <APR_SVC_ASM>;
qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
@@ -4827,7 +5247,7 @@
};
};
- q6adm: apr-service@8 {
+ q6adm: service@8 {
compatible = "qcom,q6adm";
reg = <APR_SVC_ADM>;
qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
@@ -4956,6 +5376,7 @@
qcom,drv-id = <2>;
qcom,tcs-config = <ACTIVE_TCS 2>, <SLEEP_TCS 3>,
<WAKE_TCS 3>, <CONTROL_TCS 1>;
+ power-domains = <&CLUSTER_PD>;
rpmhcc: clock-controller {
compatible = "qcom,sm8250-rpmh-clk";
@@ -5020,7 +5441,7 @@
};
epss_l3: interconnect@18590000 {
- compatible = "qcom,sm8250-epss-l3";
+ compatible = "qcom,sm8250-epss-l3", "qcom,epss-l3";
reg = <0 0x18590000 0 0x1000>;
clocks = <&rpmhcc RPMH_CXO_CLK>, <&gcc GPLL0>;
diff --git a/arch/arm64/boot/dts/qcom/sm8350-hdk.dts b/arch/arm64/boot/dts/qcom/sm8350-hdk.dts
index 69ae6503c2f6..26a608144886 100644
--- a/arch/arm64/boot/dts/qcom/sm8350-hdk.dts
+++ b/arch/arm64/boot/dts/qcom/sm8350-hdk.dts
@@ -107,9 +107,8 @@
regulator-max-microvolt = <888000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
regulator-allow-set-load;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
vreg_l6b_1p2: ldo6 {
@@ -118,9 +117,8 @@
regulator-max-microvolt = <1208000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
regulator-allow-set-load;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
vreg_l7b_2p96: ldo7 {
@@ -129,9 +127,8 @@
regulator-max-microvolt = <2504000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
regulator-allow-set-load;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
vreg_l9b_1p2: ldo9 {
@@ -140,9 +137,8 @@
regulator-max-microvolt = <1200000>;
regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
regulator-allow-set-load;
- regulator-allowed-modes =
- <RPMH_REGULATOR_MODE_LPM
- RPMH_REGULATOR_MODE_HPM>;
+ regulator-allowed-modes = <RPMH_REGULATOR_MODE_LPM
+ RPMH_REGULATOR_MODE_HPM>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sm8350-sony-xperia-sagami-pdx215.dts b/arch/arm64/boot/dts/qcom/sm8350-sony-xperia-sagami-pdx215.dts
index d21bbeb603a6..c74c973a69d2 100644
--- a/arch/arm64/boot/dts/qcom/sm8350-sony-xperia-sagami-pdx215.dts
+++ b/arch/arm64/boot/dts/qcom/sm8350-sony-xperia-sagami-pdx215.dts
@@ -11,3 +11,209 @@
model = "Sony Xperia 1 III";
compatible = "sony,pdx215-generic", "qcom,sm8350";
};
+
+&tlmm {
+ gpio-line-names = "APPS_I2C_0_SDA", /* GPIO_0 */
+ "APPS_I2C_0_SCL",
+ "UWIDEC_PWR_EN",
+ "HAP_RST_N",
+ "WLC_I2C_SDA",
+ "WLC_I2C_SCL",
+ "PM8008_1_RESET_N",
+ "WLC_INT_N",
+ "OIS_TELE_I2C_SDA",
+ "OIS_TELE_I2C_SCL",
+ "PM8350_OPTION", /* GPIO_10 */
+ "NC",
+ "APPS_I2C_1_SDA",
+ "APPS_I2C_1_SCL",
+ "NC",
+ "NC",
+ "CAM1_RESET_N",
+ "LEO_CAM0_RESET_N",
+ "DEBUG_UART_TX",
+ "DEBUG_UART_RX",
+ "TS_I2C_SDA", /* GPIO_20 */
+ "TS_I2C_SCL",
+ "TS_RESET_N",
+ "TS_INT_N",
+ "DISP_RESET_N",
+ "SW_SERVICE",
+ "DISP_ERR_FG",
+ "TX_GTR_THRES_IN",
+ "NC",
+ "NC",
+ "NC", /* GPIO_30 */
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "SPK_AMP_INT_N",
+ "SPK_AMP_RESET_N",
+ "FP_INT_N",
+ "FP_RESET_N",
+ "NC", /* GPIO_40 */
+ "NC",
+ "DEBUG_GPIO0",
+ "FORCE_USB_BOOT",
+ "FP_SPI_MISO",
+ "FP_SPI_MOSI",
+ "FP_SPI_CLK",
+ "FP_SPI_CS_N",
+ "SPK_AMP_I2C_SDA",
+ "SPK_AMP_I2C_SCL",
+ "NC", /* GPIO_50 */
+ "HAP_INT_N",
+ "CAMSENSOR_I2C_SDA",
+ "CAMSENSOR_I2C_SCL",
+ "SBU_SW_OE",
+ "SBU_SW_SEL",
+ "NFC_ESE_SPI_MISO",
+ "NFC_ESE_SPI_MOSI",
+ "NFC_ESE_SPI_CLK",
+ "NFC_ESE_SPI_CS",
+ "NFC_I2C_SDA", /* GPIO_60 */
+ "NFC_I2C_SCL",
+ "NFC_EN",
+ "NFC_CLK_REQ",
+ "HST_WLAN_EN",
+ "HST_BT_EN",
+ "HW_ID_0",
+ "HW_ID_1",
+ "HST_BT_UART_CTS",
+ "HST_BT_UART_RFR",
+ "HST_BT_UART_TX", /* GPIO_70 */
+ "HST_BT_UART_RX",
+ "HAP_I2C_SDA",
+ "HAP_I2C_SCL",
+ "RF_LCD_ID_EN",
+ "RF_ID_EXTENSION",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "HALL_INT_N", /* GPIO_80 */
+ "USB_CC_DIR",
+ "DISP_VSYNC",
+ "NC",
+ "NC",
+ "CAM_SOF_TELE",
+ "NFC_DWL_REQ",
+ "NFC_IRQ",
+ "WCD_RST_N",
+ "ALS_PROX_INT_N",
+ "NC", /* GPIO_90 */
+ "NC",
+ "TRAY_DET",
+ "UDON_SWITCH_SEL",
+ "PCIE0_RESET_N",
+ "PCIE0_CLK_REQ_N",
+ "PCIE0_WAKE_N",
+ "CAM_SOF",
+ "RF_ID_EXTENSION_2",
+ "RGBC_IR_INT",
+ "CAM_MCLK0", /* GPIO_100 */
+ "CAM_MCLK1",
+ "CAM_MCLK2",
+ "CAM_MCLK3",
+ "CAM_MCLK4",
+ "NC",
+ "CAM2_RESET_N",
+ "CCI_I2C0_SDA",
+ "CCI_I2C0_SCL",
+ "CCI_I2C1_SDA",
+ "CCI_I2C1_SCL", /* GPIO_110 */
+ "CCI_I2C2_SDA",
+ "CCI_I2C2_SCL",
+ "CCI_I2C3_SDA",
+ "CCI_I2C3_SCL",
+ "NC",
+ "PM8008_1_IRQ",
+ "CAM3_RESET_N",
+ "IMU1_INT",
+ "EXT_VD0_XVS",
+ "NC", /* GPIO_120 */
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "HAP_I2S_CLK",
+ "HAP_I2S_DOUT",
+ "HAP_TRG1",
+ "HAP_I2S_SYNC",
+ "HST_BT_WLAN_SLIMBUS_CLK",
+ "HST_BT_WLAN_SLIMBUS_DAT0", /* GPIO_130 */
+ "NC",
+ "UIM2_DETECT_EN",
+ "UIM2_DATA",
+ "UIM2_CLK",
+ "UIM2_RESET",
+ "UIM2_PRESENT",
+ "UIM1_DATA",
+ "UIM1_CLK",
+ "UIM1_RESET",
+ "TRAY_DET", /* GPIO_140 */
+ "SM_RFFE0_CLK",
+ "SM_RFFE0_DATA",
+ "SM_RFFE1_CLK",
+ "SM_RFFE1_DATA",
+ "SM_MSS_GRFC4",
+ "SM_MSS_GRFC5",
+ "SM_MSS_GRFC6",
+ "SM_MSS_GRFC7",
+ "SM_RFFE4_CLK",
+ "SM_RFFE4_DATA", /* GPIO_150 */
+ "WLAN_COEX_UART1_RX",
+ "WLAN_COEX_UART1_TX",
+ "HST_SW_CTRL",
+ "DISP_VDDR_EN",
+ "NC",
+ "NC",
+ "PA_INDICATOR_OR",
+ "TOF_RST_N",
+ "QLINK0_REQ",
+ "QLINK0_EN", /* GPIO_160 */
+ "QLINK0_WMSS_RESET_N",
+ "QLINK1_REQ",
+ "QLINK1_EN",
+ "QLINK1_WMSS_RESET_N",
+ "PM8008_2_IRQ",
+ "TELEC_PWR_EN",
+ "PM8008_2_RESET_N",
+ "WCD_SWR_TX_CLK",
+ "WCD_SWR_TX_DATA0",
+ "WCD_SWR_TX_DATA1", /* GPIO_170 */
+ "WCD_SWR_RX_CLK",
+ "WCD_SWR_RX_DATA0",
+ "WCD_SWR_RX_DATA1",
+ "SM_DMIC1_CLK",
+ "SM_DMIC1_DATA",
+ "SM_DMIC2_CLK",
+ "SM_DMIC2_DATA",
+ "SPK_AMP_I2S_CLK",
+ "SPK_AMP_I2S_WS",
+ "SPK_AMP_I2S_ASP_DIN", /* GPIO_180 */
+ "SPK_AMP_I2S_ASP_DOUT",
+ "WCD_SWR_TX_DATA2",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "IMU_SPI_MISO",
+ "IMU_SPI_MOSI",
+ "IMU_SPI_CLK",
+ "IMU_SPI_CS_N", /* GPIO_190 */
+ "MAG_I2C_SDA",
+ "MAG_I2C_SCL",
+ "SENSOR_I2C_SDA",
+ "SENSOR_I2C_SCL",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "HST_BLE_UART_TX",
+ "HST_BLE_UART_RX", /* GPIO_200 */
+ "HST_WLAN_UART_TX",
+ "HST_WLAN_UART_RX";
+};
diff --git a/arch/arm64/boot/dts/qcom/sm8350-sony-xperia-sagami.dtsi b/arch/arm64/boot/dts/qcom/sm8350-sony-xperia-sagami.dtsi
index b3c9952ac173..1f2d660f8f86 100644
--- a/arch/arm64/boot/dts/qcom/sm8350-sony-xperia-sagami.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8350-sony-xperia-sagami.dtsi
@@ -3,6 +3,7 @@
* Copyright (c) 2021, Konrad Dybcio <konrad.dybcio@somainline.org>
*/
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
#include "sm8350.dtsi"
#include "pm8350.dtsi"
#include "pm8350b.dtsi"
@@ -73,16 +74,366 @@
no-map;
};
};
+
+ vph_pwr: vph-pwr-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vph_pwr";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+
+ regulator-always-on;
+ regulator-boot-on;
+ };
};
&adsp {
status = "okay";
- firmware-name = "qcom/adsp.mbn";
+ firmware-name = "qcom/sm8350/Sony/sagami/adsp.mbn";
+};
+
+&apps_rsc {
+ regulators-0 {
+ compatible = "qcom,pm8350-rpmh-regulators";
+ qcom,pmic-id = "b";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+ vdd-s4-supply = <&vph_pwr>;
+ vdd-s5-supply = <&vph_pwr>;
+ vdd-s6-supply = <&vph_pwr>;
+ vdd-s7-supply = <&vph_pwr>;
+ vdd-s8-supply = <&vph_pwr>;
+ vdd-s9-supply = <&vph_pwr>;
+ vdd-s10-supply = <&vph_pwr>;
+ vdd-s11-supply = <&vph_pwr>;
+ vdd-s12-supply = <&vph_pwr>;
+
+ vdd-l1-l4-supply = <&pm8350_s11>;
+ vdd-l2-l7-supply = <&vreg_bob>;
+ vdd-l3-l5-supply = <&vreg_bob>;
+ vdd-l6-l9-l10-supply = <&pm8350_s11>;
+
+ /*
+ * ARC regulators:
+ * S5 - mx.lvl
+ * S6 - gfx.lvl
+ * S9 - mxc.lvl
+ */
+
+ pm8350_s10: smps10 {
+ regulator-name = "pm8350_s10";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350_s11: smps11 {
+ regulator-name = "pm8350_s11";
+ regulator-min-microvolt = <752000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350_s12: smps12 {
+ regulator-name = "pm8350_s12";
+ regulator-min-microvolt = <1224000>;
+ regulator-max-microvolt = <1360000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350_l1: ldo1 {
+ regulator-name = "pm8350_l1";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <920000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350_l2: ldo2 {
+ regulator-name = "pm8350_l2";
+ regulator-min-microvolt = <3072000>;
+ regulator-max-microvolt = <3072000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350_l3: ldo3 {
+ regulator-name = "pm8350_l3";
+ regulator-min-microvolt = <904000>;
+ regulator-max-microvolt = <904000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ /* L4 - lmx.lvl (ARC) */
+
+ pm8350_l5: ldo5 {
+ regulator-name = "pm8350_l5";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <888000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ };
+
+ pm8350_l6: ldo6 {
+ regulator-name = "pm8350_l6";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1208000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ };
+
+ pm8350_l7: ldo7 {
+ regulator-name = "pm8350_l7";
+ regulator-min-microvolt = <2400000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ };
+
+ /* L8 - lcx.lvl (ARC) */
+
+ pm8350_l9: ldo9 {
+ regulator-name = "pm8350_l9";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ regulator-allow-set-load;
+ };
+ };
+
+ regulators-1 {
+ compatible = "qcom,pm8350c-rpmh-regulators";
+ qcom,pmic-id = "c";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+ vdd-s4-supply = <&vph_pwr>;
+ vdd-s5-supply = <&vph_pwr>;
+ vdd-s6-supply = <&vph_pwr>;
+ vdd-s7-supply = <&vph_pwr>;
+ vdd-s8-supply = <&vph_pwr>;
+ vdd-s9-supply = <&vph_pwr>;
+ vdd-s10-supply = <&vph_pwr>;
+
+ vdd-l1-l12-supply = <&pm8350c_s1>;
+ vdd-l2-l8-supply = <&pm8350c_s1>;
+ vdd-l3-l4-l5-l7-l13-supply = <&vreg_bob>;
+ vdd-l6-l9-l11-supply = <&vreg_bob>;
+ vdd-l10-supply = <&pm8350_s12>;
+
+ vdd-bob-supply = <&vph_pwr>;
+
+ pm8350c_s1: smps1 {
+ regulator-name = "pm8350c_s1";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1952000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ /* S2 - ebi.lvl (ARC) */
+
+ pm8350c_s3: smps3 {
+ regulator-name = "pm8350c_s3";
+ regulator-min-microvolt = <300000>;
+ regulator-max-microvolt = <704000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ /*
+ * ARC regulators:
+ * S4 - mss.lvl
+ * S6 - cx.lvl
+ * S8 - mmcx.lvl
+ */
+
+ pm8350c_s10: smps10 {
+ regulator-name = "pm8350c_s10";
+ regulator-min-microvolt = <1048000>;
+ regulator-max-microvolt = <1128000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l1: ldo1 {
+ regulator-name = "pm8350c_l1";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l2: ldo2 {
+ regulator-name = "pm8350c_l2";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l3: ldo3 {
+ regulator-name = "pm8350c_l3";
+ regulator-min-microvolt = <3304000>;
+ regulator-max-microvolt = <3304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l4: ldo4 {
+ regulator-name = "pm8350c_l4";
+ regulator-min-microvolt = <1704000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l5: ldo5 {
+ regulator-name = "pm8350c_l5";
+ regulator-min-microvolt = <1704000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l6: ldo6 {
+ regulator-name = "pm8350c_l6";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l7: ldo7 {
+ regulator-name = "pm8350c_l7";
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l8: ldo8 {
+ regulator-name = "pm8350c_l8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l9: ldo9 {
+ regulator-name = "pm8350c_l9";
+ regulator-min-microvolt = <2960000>;
+ /* Originally max = 3008000 but SDHCI expects 2960000 */
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l10: ldo10 {
+ regulator-name = "pm8350c_l10";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l11: ldo11 {
+ regulator-name = "pm8350c_l11";
+ regulator-min-microvolt = <2400000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l12: ldo12 {
+ regulator-name = "pm8350c_l12";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l13: ldo13 {
+ regulator-name = "pm8350c_l13";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ vreg_bob: bob {
+ regulator-name = "vreg_bob";
+ regulator-min-microvolt = <3400000>;
+ regulator-max-microvolt = <3960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>;
+ };
+ };
+
+ /* TODO: Add pm8350b (just one ldo) once the driver part is in */
+
+ regulators-2 {
+ compatible = "qcom,pmr735a-rpmh-regulators";
+ qcom,pmic-id = "e";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+
+ vdd-l1-l2-supply = <&pmr735a_s2>;
+ vdd-l3-supply = <&pmr735a_s1>;
+ vdd-l4-supply = <&pm8350c_s1>;
+ vdd-l5-l6-supply = <&pm8350c_s1>;
+ vdd-l7-bob-supply = <&vreg_bob>;
+
+ pmr735a_s1: smps1 {
+ regulator-name = "pmr735a_s1";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1280000>;
+ };
+
+ pmr735a_s2: smps2 {
+ regulator-name = "pmr735a_s2";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <976000>;
+ };
+
+ pmr735a_s3: smps3 {
+ regulator-name = "pmr735a_s3";
+ regulator-min-microvolt = <2208000>;
+ regulator-max-microvolt = <2352000>;
+ };
+
+ pmr735a_l1: ldo1 {
+ regulator-name = "pmr735a_l1";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <912000>;
+ };
+
+ pmr735a_l2: ldo2 {
+ regulator-name = "pmr735a_l2";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pmr735a_l3: ldo3 {
+ regulator-name = "pmr735a_l3";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pmr735a_l4: ldo4 {
+ regulator-name = "pmr735a_l4";
+ regulator-min-microvolt = <1776000>;
+ regulator-max-microvolt = <1872000>;
+ };
+
+ pmr735a_l5: ldo5 {
+ regulator-name = "pmr735a_l5";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ };
+
+ pmr735a_l6: ldo6 {
+ regulator-name = "pmr735a_l6";
+ regulator-min-microvolt = <480000>;
+ regulator-max-microvolt = <904000>;
+ };
+
+ pmr735a_l7: ldo7 {
+ regulator-name = "pmr735a_l7";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+ };
};
&cdsp {
status = "okay";
- firmware-name = "qcom/cdsp.mbn";
+ firmware-name = "qcom/sm8350/Sony/sagami/cdsp.mbn";
};
&i2c1 {
@@ -175,12 +526,12 @@
&ipa {
status = "okay";
memory-region = <&pil_ipa_fw_mem>;
- firmware-name = "qcom/ipa_fws.mbn";
+ firmware-name = "qcom/sm8350/Sony/sagami/ipa_fws.mbn";
};
&mpss {
status = "okay";
- firmware-name = "qcom/modem.mbn";
+ firmware-name = "qcom/sm8350/Sony/sagami/modem.mbn";
};
&pmk8350_rtc {
@@ -208,9 +559,21 @@
status = "okay";
};
+&sdhc_2 {
+ cd-gpios = <&tlmm 92 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdc2_default_state &sdc2_card_det_active>;
+ pinctrl-1 = <&sdc2_sleep_state &sdc2_card_det_sleep>;
+ vmmc-supply = <&pm8350c_l9>;
+ vqmmc-supply = <&pm8350c_l6>;
+ no-sdio;
+ no-mmc;
+ status = "okay";
+};
+
&slpi {
status = "okay";
- firmware-name = "qcom/slpi.mbn";
+ firmware-name = "qcom/sm8350/Sony/sagami/slpi.mbn";
};
&spi14 {
@@ -221,6 +584,209 @@
&tlmm {
gpio-reserved-ranges = <44 4>;
+ gpio-line-names = "APPS_I2C_0_SDA", /* GPIO_0 */
+ "APPS_I2C_0_SCL",
+ "UWIDEC_PWR_EN",
+ "HAP_RST_N",
+ "NC",
+ "NC",
+ "PM8008_1_RESET_N",
+ "NC",
+ "OIS_TELE_I2C_SDA",
+ "OIS_TELE_I2C_SCL",
+ "PM8350_OPTION", /* GPIO_10 */
+ "NC",
+ "APPS_I2C_1_SDA",
+ "APPS_I2C_1_SCL",
+ "NC",
+ "NC",
+ "CAM1_RESET_N",
+ "LEO_CAM0_RESET_N",
+ "DEBUG_UART_TX",
+ "DEBUG_UART_RX",
+ "TS_I2C_SDA", /* GPIO_20 */
+ "TS_I2C_SCL",
+ "TS_RESET_N",
+ "TS_INT_N",
+ "DISP_RESET_N",
+ "SW_SERVICE",
+ "DISP_ERR_FG",
+ "TX_GTR_THRES_IN",
+ "NC",
+ "NC",
+ "NC", /* GPIO_30 */
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "SPK_AMP_INT_N",
+ "SPK_AMP_RESET_N",
+ "FP_INT_N",
+ "FP_RESET_N",
+ "NC", /* GPIO_40 */
+ "NC",
+ "DEBUG_GPIO0",
+ "FORCE_USB_BOOT",
+ "FP_SPI_MISO",
+ "FP_SPI_MOSI",
+ "FP_SPI_CLK",
+ "FP_SPI_CS_N",
+ "SPK_AMP_I2C_SDA",
+ "SPK_AMP_I2C_SCL",
+ "NC", /* GPIO_50 */
+ "HAP_INT_N",
+ "CAMSENSOR_I2C_SDA",
+ "CAMSENSOR_I2C_SCL",
+ "SBU_SW_OE",
+ "SBU_SW_SEL",
+ "NFC_ESE_SPI_MISO",
+ "NFC_ESE_SPI_MOSI",
+ "NFC_ESE_SPI_CLK",
+ "NFC_ESE_SPI_CS",
+ "NFC_I2C_SDA", /* GPIO_60 */
+ "NFC_I2C_SCL",
+ "NFC_EN",
+ "NFC_CLK_REQ",
+ "HST_WLAN_EN",
+ "HST_BT_EN",
+ "HW_ID_0",
+ "HW_ID_1",
+ "HST_BT_UART_CTS",
+ "HST_BT_UART_RFR",
+ "HST_BT_UART_TX", /* GPIO_70 */
+ "HST_BT_UART_RX",
+ "HAP_I2C_SDA",
+ "HAP_I2C_SCL",
+ "RF_LCD_ID_EN",
+ "RF_ID_EXTENSION",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "HALL_INT_N", /* GPIO_80 */
+ "USB_CC_DIR",
+ "DISP_VSYNC",
+ "NC",
+ "NC",
+ "CAM_SOF_TELE",
+ "NFC_DWL_REQ",
+ "NFC_IRQ",
+ "WCD_RST_N",
+ "ALS_PROX_INT_N",
+ "NC", /* GPIO_90 */
+ "NC",
+ "TRAY_DET",
+ "UDON_SWITCH_SEL",
+ "PCIE0_RESET_N",
+ "PCIE0_CLK_REQ_N",
+ "PCIE0_WAKE_N",
+ "CAM_SOF",
+ "RF_ID_EXTENSION_2",
+ "RGBC_IR_INT",
+ "CAM_MCLK0", /* GPIO_100 */
+ "CAM_MCLK1",
+ "CAM_MCLK2",
+ "CAM_MCLK3",
+ "NC",
+ "NC",
+ "CAM2_RESET_N",
+ "CCI_I2C0_SDA",
+ "CCI_I2C0_SCL",
+ "CCI_I2C1_SDA",
+ "CCI_I2C1_SCL", /* GPIO_110 */
+ "CCI_I2C2_SDA",
+ "CCI_I2C2_SCL",
+ "CCI_I2C3_SDA",
+ "CCI_I2C3_SCL",
+ "NC",
+ "PM8008_1_IRQ",
+ "CAM3_RESET_N",
+ "IMU1_INT",
+ "EXT_VD0_XVS",
+ "NC", /* GPIO_120 */
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "HAP_I2S_CLK",
+ "HAP_I2S_DOUT",
+ "HAP_TRG1",
+ "HAP_I2S_SYNC",
+ "HST_BT_WLAN_SLIMBUS_CLK",
+ "HST_BT_WLAN_SLIMBUS_DAT0", /* GPIO_130 */
+ "NC",
+ "UIM2_DETECT_EN",
+ "UIM2_DATA",
+ "UIM2_CLK",
+ "UIM2_RESET",
+ "UIM2_PRESENT",
+ "UIM1_DATA",
+ "UIM1_CLK",
+ "UIM1_RESET",
+ "TRAY_DET", /* GPIO_140 */
+ "SM_RFFE0_CLK",
+ "SM_RFFE0_DATA",
+ "SM_RFFE1_CLK",
+ "SM_RFFE1_DATA",
+ "SM_MSS_GRFC4",
+ "SM_MSS_GRFC5",
+ "SM_MSS_GRFC6",
+ "SM_MSS_GRFC7",
+ "SM_RFFE4_CLK",
+ "SM_RFFE4_DATA", /* GPIO_150 */
+ "WLAN_COEX_UART1_RX",
+ "WLAN_COEX_UART1_TX",
+ "HST_SW_CTRL",
+ "DISP_VDDR_EN",
+ "NC",
+ "NC",
+ "PA_INDICATOR_OR",
+ "NC",
+ "QLINK0_REQ",
+ "QLINK0_EN", /* GPIO_160 */
+ "QLINK0_WMSS_RESET_N",
+ "NC",
+ "NC",
+ "NC",
+ "PM8008_2_IRQ",
+ "TELEC_PWR_EN",
+ "PM8008_2_RESET_N",
+ "WCD_SWR_TX_CLK",
+ "WCD_SWR_TX_DATA0",
+ "WCD_SWR_TX_DATA1", /* GPIO_170 */
+ "WCD_SWR_RX_CLK",
+ "WCD_SWR_RX_DATA0",
+ "WCD_SWR_RX_DATA1",
+ "SM_DMIC1_CLK",
+ "SM_DMIC1_DATA",
+ "SM_DMIC2_CLK",
+ "SM_DMIC2_DATA",
+ "SPK_AMP_I2S_CLK",
+ "SPK_AMP_I2S_WS",
+ "SPK_AMP_I2S_ASP_DIN", /* GPIO_180 */
+ "SPK_AMP_I2S_ASP_DOUT",
+ "WCD_SWR_TX_DATA2",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "IMU_SPI_MISO",
+ "IMU_SPI_MOSI",
+ "IMU_SPI_CLK",
+ "IMU_SPI_CS_N", /* GPIO_190 */
+ "MAG_I2C_SDA",
+ "MAG_I2C_SCL",
+ "SENSOR_I2C_SDA",
+ "SENSOR_I2C_SCL",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "HST_BLE_UART_TX",
+ "HST_BLE_UART_RX", /* GPIO_200 */
+ "HST_WLAN_UART_TX",
+ "HST_WLAN_UART_RX";
ts_int_default: ts-int-default-state {
pins = "gpio23";
@@ -229,31 +795,45 @@
bias-disable;
input-enable;
};
+
+ sdc2_card_det_active: sd-card-det-active-state {
+ pins = "gpio92";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ sdc2_card_det_sleep: sd-card-det-sleep-state {
+ pins = "gpio92";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ };
};
/* BIG WARNING! DO NOT TOUCH UFS, YOUR DEVICE WILL DIE! */
&ufs_mem_hc { status = "disabled"; };
&ufs_mem_phy { status = "disabled"; };
-/* TODO: Make USB3 work (perhaps needs regulators for higher-current operation?) */
&usb_1 {
status = "okay";
-
- qcom,select-utmi-as-pipe-clk;
};
&usb_1_dwc3 {
dr_mode = "peripheral";
-
- maximum-speed = "high-speed";
- phys = <&usb_1_hsphy>;
- phy-names = "usb2-phy";
};
&usb_1_hsphy {
status = "okay";
+
+ vdda-pll-supply = <&pm8350_l5>;
+ vdda18-supply = <&pm8350c_l1>;
+ vdda33-supply = <&pm8350_l2>;
};
&usb_1_qmpphy {
status = "okay";
+
+ vdda-phy-supply = <&pm8350_l6>;
+ vdda-pll-supply = <&pm8350_l1>;
};
diff --git a/arch/arm64/boot/dts/qcom/sm8350.dtsi b/arch/arm64/boot/dts/qcom/sm8350.dtsi
index a86d9ea93b9d..245dce24ec59 100644
--- a/arch/arm64/boot/dts/qcom/sm8350.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8350.dtsi
@@ -678,7 +678,7 @@
};
gpi_dma2: dma-controller@800000 {
- compatible = "qcom,sm8350-gpi-dma";
+ compatible = "qcom,sm8350-gpi-dma", "qcom,sm6350-gpi-dma";
reg = <0 0x00800000 0 0x60000>;
interrupts = <GIC_SPI 588 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 589 IRQ_TYPE_LEVEL_HIGH>,
@@ -904,7 +904,7 @@
};
gpi_dma0: dma-controller@900000 {
- compatible = "qcom,sm8350-gpi-dma";
+ compatible = "qcom,sm8350-gpi-dma", "qcom,sm6350-gpi-dma";
reg = <0 0x09800000 0 0x60000>;
interrupts = <GIC_SPI 244 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>,
@@ -1209,7 +1209,7 @@
};
gpi_dma1: dma-controller@a00000 {
- compatible = "qcom,sm8350-gpi-dma";
+ compatible = "qcom,sm8350-gpi-dma", "qcom,sm6350-gpi-dma";
reg = <0 0x00a00000 0 0x60000>;
interrupts = <GIC_SPI 279 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 280 IRQ_TYPE_LEVEL_HIGH>,
@@ -1761,6 +1761,46 @@
gpio-ranges = <&tlmm 0 0 204>;
wakeup-parent = <&pdc>;
+ sdc2_default_state: sdc2-default-state {
+ clk-pins {
+ pins = "sdc2_clk";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ cmd-pins {
+ pins = "sdc2_cmd";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+
+ data-pins {
+ pins = "sdc2_data";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+ };
+
+ sdc2_sleep_state: sdc2-sleep-state {
+ clk-pins {
+ pins = "sdc2_clk";
+ drive-strength = <2>;
+ bias-disable;
+ };
+
+ cmd-pins {
+ pins = "sdc2_cmd";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ data-pins {
+ pins = "sdc2_data";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
qup_uart3_default_state: qup-uart3-default-state {
rx-pins {
pins = "gpio18";
@@ -2004,6 +2044,7 @@
qcom,drv-id = <2>;
qcom,tcs-config = <ACTIVE_TCS 2>, <SLEEP_TCS 3>,
<WAKE_TCS 3>, <CONTROL_TCS 0>;
+ power-domains = <&CLUSTER_PD>;
rpmhcc: clock-controller {
compatible = "qcom,sm8350-rpmh-clk";
@@ -2142,11 +2183,11 @@
status = "disabled";
ufs_mem_phy_lanes: phy@1d87400 {
- reg = <0 0x01d87400 0 0x108>,
- <0 0x01d87600 0 0x1e0>,
- <0 0x01d87c00 0 0x1dc>,
- <0 0x01d87800 0 0x108>,
- <0 0x01d87a00 0 0x1e0>;
+ reg = <0 0x01d87400 0 0x188>,
+ <0 0x01d87600 0 0x200>,
+ <0 0x01d87c00 0 0x200>,
+ <0 0x01d87800 0 0x188>,
+ <0 0x01d87a00 0 0x200>;
#phy-cells = <0>;
};
};
@@ -2221,7 +2262,7 @@
cdsp: remoteproc@98900000 {
compatible = "qcom,sm8350-cdsp-pas";
- reg = <0 0x098900000 0 0x1400000>;
+ reg = <0 0x98900000 0 0x1400000>;
interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_LEVEL_HIGH>,
<&smp2p_cdsp_in 0 IRQ_TYPE_EDGE_RISING>,
@@ -2328,6 +2369,45 @@
};
};
+ sdhc_2: sdhci@8804000 {
+ compatible = "qcom,sm8350-sdhci", "qcom,sdhci-msm-v5";
+ reg = <0 0x08804000 0 0x1000>;
+
+ interrupts = <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 223 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "hc_irq", "pwr_irq";
+
+ clocks = <&gcc GCC_SDCC2_AHB_CLK>,
+ <&gcc GCC_SDCC2_APPS_CLK>,
+ <&rpmhcc RPMH_CXO_CLK>;
+ clock-names = "iface", "core", "xo";
+ resets = <&gcc GCC_SDCC2_BCR>;
+ interconnects = <&aggre2_noc MASTER_SDCC_2 0 &mc_virt SLAVE_EBI1 0>,
+ <&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_SDCC_2 0>;
+ interconnect-names = "sdhc-ddr","cpu-sdhc";
+ iommus = <&apps_smmu 0x4a0 0x0>;
+ power-domains = <&rpmhpd SM8350_CX>;
+ operating-points-v2 = <&sdhc2_opp_table>;
+ bus-width = <4>;
+ dma-coherent;
+
+ status = "disabled";
+
+ sdhc2_opp_table: opp-table {
+ compatible = "operating-points-v2";
+
+ opp-100000000 {
+ opp-hz = /bits/ 64 <100000000>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ };
+
+ opp-202000000 {
+ opp-hz = /bits/ 64 <202000000>;
+ required-opps = <&rpmhpd_opp_svs_l1>;
+ };
+ };
+ };
+
usb_1_hsphy: phy@88e3000 {
compatible = "qcom,sm8350-usb-hs-phy",
"qcom,usb-snps-hs-7nm-phy";
diff --git a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts
index 38ccd44620d0..4de3e1f1c39c 100644
--- a/arch/arm64/boot/dts/qcom/sm8450-hdk.dts
+++ b/arch/arm64/boot/dts/qcom/sm8450-hdk.dts
@@ -6,6 +6,7 @@
/dts-v1/;
#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+#include <dt-bindings/sound/qcom,q6dsp-lpass-ports.h>
#include "sm8450.dtsi"
/ {
@@ -394,8 +395,181 @@
status = "okay";
};
+&sdhc_2 {
+ cd-gpios = <&tlmm 92 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdc2_default_state &sdc2_card_det_n>;
+ pinctrl-1 = <&sdc2_sleep_state &sdc2_card_det_n>;
+ vmmc-supply = <&vreg_l9c_2p96>;
+ vqmmc-supply = <&vreg_l6c_1p8>;
+ no-sdio;
+ no-mmc;
+ status = "okay";
+};
+
+&soc {
+ wcd938x: codec {
+ compatible = "qcom,wcd9380-codec";
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&wcd_default>;
+
+ qcom,micbias1-microvolt = <1800000>;
+ qcom,micbias2-microvolt = <1800000>;
+ qcom,micbias3-microvolt = <1800000>;
+ qcom,micbias4-microvolt = <1800000>;
+ qcom,mbhc-buttons-vthreshold-microvolt = <75000 150000 237000 500000 500000 500000 500000 500000>;
+ qcom,mbhc-headset-vthreshold-microvolt = <1700000>;
+ qcom,mbhc-headphone-vthreshold-microvolt = <50000>;
+ qcom,rx-device = <&wcd_rx>;
+ qcom,tx-device = <&wcd_tx>;
+
+ reset-gpios = <&tlmm 43 GPIO_ACTIVE_LOW>;
+ #sound-dai-cells = <1>;
+
+ vdd-buck-supply = <&vreg_s10b_1p8>;
+ vdd-rxtx-supply = <&vreg_s10b_1p8>;
+ vdd-io-supply = <&vreg_s10b_1p8>;
+ vdd-mic-bias-supply = <&vreg_bob>;
+ };
+};
+
+&sound {
+ compatible = "qcom,sm8450-sndcard";
+ model = "SM8450-HDK";
+ audio-routing = "SpkrLeft IN", "WSA_SPK1 OUT",
+ "SpkrRight IN", "WSA_SPK2 OUT",
+ "IN1_HPHL", "HPHL_OUT",
+ "IN2_HPHR", "HPHR_OUT",
+ "AMIC2", "MIC BIAS2",
+ "VA DMIC0", "MIC BIAS1",
+ "VA DMIC1", "MIC BIAS1",
+ "VA DMIC2", "MIC BIAS3",
+ "TX DMIC0", "MIC BIAS1",
+ "TX DMIC1", "MIC BIAS2",
+ "TX DMIC2", "MIC BIAS3",
+ "TX SWR_ADC1", "ADC2_OUTPUT";
+
+ wcd-playback-dai-link {
+ link-name = "WCD Playback";
+
+ cpu {
+ sound-dai = <&q6apmbedai RX_CODEC_DMA_RX_0>;
+ };
+
+ codec {
+ sound-dai = <&wcd938x 0>, <&swr1 0>, <&rxmacro 0>;
+ };
+
+ platform {
+ sound-dai = <&q6apm>;
+ };
+ };
+
+ wcd-capture-dai-link {
+ link-name = "WCD Capture";
+
+ cpu {
+ sound-dai = <&q6apmbedai TX_CODEC_DMA_TX_3>;
+ };
+
+ codec {
+ sound-dai = <&wcd938x 1>, <&swr2 0>, <&txmacro 0>;
+ };
+
+ platform {
+ sound-dai = <&q6apm>;
+ };
+ };
+
+ wsa-dai-link {
+ link-name = "WSA Playback";
+
+ cpu {
+ sound-dai = <&q6apmbedai WSA_CODEC_DMA_RX_0>;
+ };
+
+ codec {
+ sound-dai = <&left_spkr>, <&right_spkr>, <&swr0 0>, <&wsamacro 0>;
+ };
+
+ platform {
+ sound-dai = <&q6apm>;
+ };
+ };
+
+ va-dai-link {
+ link-name = "VA Capture";
+
+ cpu {
+ sound-dai = <&q6apmbedai TX_CODEC_DMA_TX_3>;
+ };
+
+ codec {
+ sound-dai = <&vamacro 0>;
+ };
+
+ platform {
+ sound-dai = <&q6apm>;
+ };
+ };
+};
+
+&swr0 {
+ left_spkr: speaker@0,1 {
+ compatible = "sdw10217020200";
+ reg = <0 1>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spkr_1_sd_n_active>;
+ powerdown-gpios = <&tlmm 1 GPIO_ACTIVE_LOW>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "SpkrLeft";
+ #thermal-sensor-cells = <0>;
+ vdd-supply = <&vreg_s10b_1p8>;
+ };
+
+ right_spkr: speaker@0,2 {
+ compatible = "sdw10217020200";
+ reg = <0 2>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&spkr_2_sd_n_active>;
+ powerdown-gpios = <&tlmm 89 GPIO_ACTIVE_LOW>;
+ #sound-dai-cells = <0>;
+ sound-name-prefix = "SpkrRight";
+ #thermal-sensor-cells = <0>;
+ vdd-supply = <&vreg_s10b_1p8>;
+ };
+};
+
+&swr1 {
+ status = "okay";
+
+ wcd_rx: codec@0,4 {
+ compatible = "sdw20217010d00";
+ reg = <0 4>;
+ qcom,rx-port-mapping = <1 2 3 4 5>;
+ };
+};
+
+&swr2 {
+ status = "okay";
+
+ wcd_tx: codec@0,3 {
+ compatible = "sdw20217010d00";
+ reg = <0 3>;
+ qcom,tx-port-mapping = <1 1 2 3>;
+ };
+};
+
&tlmm {
gpio-reserved-ranges = <28 4>, <36 4>;
+
+ sdc2_card_det_n: sd-card-det-n-state {
+ pins = "gpio92";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
};
&uart7 {
@@ -442,3 +616,34 @@
vdda-phy-supply = <&vreg_l6b_1p2>;
vdda-pll-supply = <&vreg_l1b_0p91>;
};
+
+&vamacro {
+ pinctrl-0 = <&dmic01_default>, <&dmic02_default>;
+ pinctrl-names = "default";
+ vdd-micb-supply = <&vreg_s10b_1p8>;
+ qcom,dmic-sample-rate = <600000>;
+};
+
+&tlmm {
+ spkr_1_sd_n_active: spkr-1-sd-n-active-state {
+ pins = "gpio1";
+ function = "gpio";
+ drive-strength = <4>;
+ bias-disable;
+ output-low;
+ };
+
+ spkr_2_sd_n_active: spkr-2-sd-n-active-state {
+ pins = "gpio89";
+ function = "gpio";
+ drive-strength = <4>;
+ bias-disable;
+ output-low;
+ };
+
+ wcd_default: wcd-default-state {
+ pins = "gpio43";
+ function = "gpio";
+ bias-disable;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sm8450-qrd.dts b/arch/arm64/boot/dts/qcom/sm8450-qrd.dts
index e58fc7399799..ee62514fff68 100644
--- a/arch/arm64/boot/dts/qcom/sm8450-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sm8450-qrd.dts
@@ -388,6 +388,18 @@
firmware-name = "qcom/sm8450/slpi.mbn";
};
+&sdhc_2 {
+ cd-gpios = <&tlmm 92 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdc2_default_state &sdc2_card_det_n>;
+ pinctrl-1 = <&sdc2_sleep_state &sdc2_card_det_n>;
+ vmmc-supply = <&vreg_l9c_2p96>;
+ vqmmc-supply = <&vreg_l6c_1p8>;
+ no-sdio;
+ no-mmc;
+ status = "okay";
+};
+
&spi4 {
status = "okay";
};
@@ -402,6 +414,13 @@
&tlmm {
gpio-reserved-ranges = <28 4>, <36 4>;
+
+ sdc2_card_det_n: sd-card-det-n-state {
+ pins = "gpio92";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
};
&uart7 {
diff --git a/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara-pdx223.dts b/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara-pdx223.dts
index d68765eb6d4f..b83500316a81 100644
--- a/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara-pdx223.dts
+++ b/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara-pdx223.dts
@@ -1,634 +1,227 @@
// SPDX-License-Identifier: BSD-3-Clause
/*
* Copyright (c) 2022, Konrad Dybcio <konrad.dybcio@somainline.org>
+ * Copyright (c) 2022, Linaro Limited
*/
/dts-v1/;
-#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
-#include "sm8450.dtsi"
-
-/delete-node/ &adsp_mem;
-/delete-node/ &rmtfs_mem;
-/delete-node/ &video_mem;
+#include "sm8450-sony-xperia-nagara.dtsi"
/ {
model = "Sony Xperia 1 IV";
compatible = "sony,pdx223", "qcom,sm8450";
- chassis-type = "handset";
-
- aliases {
- serial0 = &uart7;
- };
-
- chosen {
- stdout-path = "serial0:115200n8";
- };
-
- reserved-memory {
- adsp_mem: memory@85700000 {
- reg = <0x0 0x85700000 0x0 0x2800000>;
- no-map;
- };
-
- video_mem: memory@9fd00000 {
- reg = <0x0 0x9fd00000 0x0 0x700000>;
- no-map;
- };
-
- rmtfs_mem: memory@f3300000 {
- compatible = "qcom,rmtfs-mem";
- reg = <0x0 0xf3300000 0x0 0x280000>;
- no-map;
-
- qcom,client-id = <1>;
- qcom,vmid = <15>;
- };
-
- ramoops@ffc00000 {
- compatible = "ramoops";
- reg = <0 0xffc00000 0 0x200000>;
- console-size = <0x40000>;
- record-size = <0x1000>;
- ecc-size = <16>;
- no-map;
- };
- };
-
- /* Sadly, the voltages for these GPIO regulators are unknown. */
- imx650_vana_vreg: imx650-vana-regulator {
- compatible = "regulator-fixed";
- regulator-name = "imx650_vana_vreg";
- gpio = <&tlmm 23 GPIO_ACTIVE_HIGH>;
- enable-active-high;
- };
-
- vph_pwr: vph-pwr-regulator {
- compatible = "regulator-fixed";
- regulator-name = "vph_pwr";
- regulator-min-microvolt = <3700000>;
- regulator-max-microvolt = <3700000>;
-
- regulator-always-on;
- regulator-boot-on;
- };
-};
-
-&apps_rsc {
- pm8350-rpmh-regulators {
- compatible = "qcom,pm8350-rpmh-regulators";
- qcom,pmic-id = "b";
-
- vdd-s1-supply = <&vph_pwr>;
- vdd-s2-supply = <&vph_pwr>;
- vdd-s3-supply = <&vph_pwr>;
- vdd-s4-supply = <&vph_pwr>;
- vdd-s5-supply = <&vph_pwr>;
- vdd-s6-supply = <&vph_pwr>;
- vdd-s7-supply = <&vph_pwr>;
- vdd-s8-supply = <&vph_pwr>;
- vdd-s9-supply = <&vph_pwr>;
- vdd-s10-supply = <&vph_pwr>;
- vdd-s11-supply = <&vph_pwr>;
- vdd-s12-supply = <&vph_pwr>;
-
- vdd-l1-l4-supply = <&pm8350_s11>;
- vdd-l2-l7-supply = <&vreg_bob>;
- vdd-l3-l5-supply = <&vreg_bob>;
- vdd-l6-l9-l10-supply = <&pm8350_s12>;
-
- /*
- * ARC regulators:
- * s5 - gfx.lvl
- * l8 - lcx.lvl
- */
-
- pm8350_s10: smps10 {
- regulator-name = "pm8350_s10";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- };
-
- pm8350_s11: smps11 {
- regulator-name = "pm8350_s11";
- regulator-min-microvolt = <848000>;
- regulator-max-microvolt = <1104000>;
- };
-
- pm8350_s12: smps12 {
- regulator-name = "pm8350_s12";
- regulator-min-microvolt = <1224000>;
- regulator-max-microvolt = <1400000>;
- };
-
- pm8350_l1: ldo1 {
- regulator-name = "pm8350_l1";
- regulator-min-microvolt = <912000>;
- regulator-max-microvolt = <920000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- pm8350_l2: ldo2 {
- regulator-name = "pm8350_l2";
- regulator-min-microvolt = <3072000>;
- regulator-max-microvolt = <3072000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- pm8350_l3: ldo3 {
- regulator-name = "pm8350_l3";
- regulator-min-microvolt = <904000>;
- regulator-max-microvolt = <904000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- pm8350_l5: ldo5 {
- regulator-name = "pm8350_l5";
- regulator-min-microvolt = <880000>;
- regulator-max-microvolt = <912000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- pm8350_l6: ldo6 {
- regulator-name = "pm8350_l6";
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- pm8350_l7: ldo7 {
- regulator-name = "pm8350_l7";
- regulator-min-microvolt = <2504000>;
- regulator-max-microvolt = <2504000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- pm8350_l9: ldo9 {
- regulator-name = "pm8350_l9";
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
- };
-
- pm8350c-rpmh-regulators {
- compatible = "qcom,pm8350c-rpmh-regulators";
- qcom,pmic-id = "c";
-
- vdd-s1-supply = <&vph_pwr>;
- vdd-s2-supply = <&vph_pwr>;
- vdd-s3-supply = <&vph_pwr>;
- vdd-s4-supply = <&vph_pwr>;
- vdd-s5-supply = <&vph_pwr>;
- vdd-s6-supply = <&vph_pwr>;
- vdd-s7-supply = <&vph_pwr>;
- vdd-s8-supply = <&vph_pwr>;
- vdd-s9-supply = <&vph_pwr>;
- vdd-s10-supply = <&vph_pwr>;
-
- vdd-l1-l12-supply = <&vreg_bob>;
- vdd-l2-l8-supply = <&vreg_bob>;
- vdd-l3-l4-l5-l7-l13-supply = <&vreg_bob>;
- vdd-l6-l9-l11-supply = <&vreg_bob>;
- vdd-l10-supply = <&pm8350_s12>;
-
- vdd-bob-supply = <&vph_pwr>;
-
- /*
- * ARC regulators:
- * s2 - mxc.lvl
- * s4 - mss.lvl
- * s6 - cx.lvl
- */
-
- pm8350c_s1: smps1 {
- regulator-name = "pm8350c_s1";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2024000>;
- };
-
- pm8350c_s10: smps10 {
- regulator-name = "pm8350c_s10";
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1100000>;
- };
-
- vreg_bob: bob {
- regulator-name = "vreg_bob";
- regulator-min-microvolt = <3400000>;
- regulator-max-microvolt = <3960000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>;
- };
-
- pm8350c_l1: ldo1 {
- regulator-name = "pm8350c_l1";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- pm8350c_l2: ldo2 {
- regulator-name = "pm8350c_l2";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- pm8350c_l3: ldo3 {
- regulator-name = "pm8350c_l3";
- regulator-min-microvolt = <3296000>;
- regulator-max-microvolt = <3304000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- pm8350c_l4: ldo4 {
- regulator-name = "pm8350c_l4";
- regulator-min-microvolt = <1704000>;
- regulator-max-microvolt = <3000000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- pm8350c_l5: ldo5 {
- regulator-name = "pm8350c_l5";
- regulator-min-microvolt = <1704000>;
- regulator-max-microvolt = <3000000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- pm8350c_l6: ldo6 {
- regulator-name = "pm8350c_l6";
- regulator-min-microvolt = <2960000>;
- /* Originally max = 3008000 but SDHCI expects 2960000 */
- regulator-max-microvolt = <2960000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- pm8350c_l7: ldo7 {
- regulator-name = "pm8350c_l7";
- regulator-min-microvolt = <3008000>;
- regulator-max-microvolt = <3008000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- pm8350c_l8: ldo8 {
- regulator-name = "pm8350c_l8";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- pm8350c_l9: ldo9 {
- regulator-name = "pm8350c_l9";
- regulator-min-microvolt = <2960000>;
- /* Originally max = 3008000 but SDHCI expects 2960000 */
- regulator-max-microvolt = <2960000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- pm8350c_l10: ldo10 {
- regulator-name = "pm8350c_l10";
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- pm8350c_l12: ldo12 {
- regulator-name = "pm8350c_l12";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1968000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- pm8350c_l13: ldo13 {
- regulator-name = "pm8350c_l13";
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
- };
-
- pm8450-rpmh-regulators {
- compatible = "qcom,pm8450-rpmh-regulators";
- qcom,pmic-id = "h";
-
- vdd-s1-supply = <&vph_pwr>;
- vdd-s2-supply = <&vph_pwr>;
- vdd-s3-supply = <&vph_pwr>;
- vdd-s4-supply = <&vph_pwr>;
- vdd-s5-supply = <&vph_pwr>;
- vdd-s6-supply = <&vph_pwr>;
-
- vdd-l2-supply = <&vreg_bob>;
- vdd-l3-supply = <&vreg_bob>;
- vdd-l4-supply = <&vreg_bob>;
-
- /*
- * ARC regulators:
- * S2 - ebi.lvl
- * S4 - mmcx.lvl
- * S6 - mx.lvl
- * L1 - lmx.lvl
- */
-
- pm8450_s3: smps3 {
- regulator-name = "pm8450_s3";
- regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <600000>;
- };
-
- pm8450_l2: ldo2 {
- regulator-name = "pm8450_l2";
- regulator-min-microvolt = <880000>;
- regulator-max-microvolt = <912000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
-
- pm8450_l3: ldo3 {
- regulator-name = "pm8450_l3";
- regulator-min-microvolt = <912000>;
- regulator-max-microvolt = <912000>;
- regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
- };
- };
-
- pmr735a-rpmh-regulators {
- compatible = "qcom,pmr735a-rpmh-regulators";
- qcom,pmic-id = "e";
-
- vdd-s1-supply = <&vph_pwr>;
- vdd-s2-supply = <&vph_pwr>;
- vdd-s3-supply = <&vph_pwr>;
-
- vdd-l1-l2-supply = <&pmr735a_s2>;
- vdd-l3-supply = <&pmr735a_s1>;
- vdd-l4-supply = <&pm8350c_s1>;
- vdd-l5-l6-supply = <&pm8350c_s1>;
- vdd-l7-bob-supply = <&vreg_bob>;
-
- pmr735a_s1: smps1 {
- regulator-name = "pmr735a_s1";
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1296000>;
- };
-
- pmr735a_s2: smps2 {
- regulator-name = "pmr735a_s2";
- regulator-min-microvolt = <500000>;
- regulator-max-microvolt = <1040000>;
- };
-
- pmr735a_s3: smps3 {
- regulator-name = "pmr735a_s3";
- regulator-min-microvolt = <435000>;
- regulator-max-microvolt = <2352000>;
- };
-
- pmr735a_l1: ldo1 {
- regulator-name = "pmr735a_l1";
- regulator-min-microvolt = <800000>;
- regulator-max-microvolt = <800000>;
- };
-
- pmr735a_l2: ldo2 {
- regulator-name = "pmr735a_l2";
- regulator-min-microvolt = <480000>;
- regulator-max-microvolt = <912000>;
- };
-
- pmr735a_l3: ldo3 {
- regulator-name = "pmr735a_l3";
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- };
-
- pmr735a_l4: ldo4 {
- regulator-name = "pmr735a_l4";
- regulator-min-microvolt = <1776000>;
- regulator-max-microvolt = <1776000>;
- };
-
- pmr735a_l5: ldo5 {
- regulator-name = "pmr735a_l5";
- regulator-min-microvolt = <880000>;
- regulator-max-microvolt = <880000>;
- };
-
- pmr735a_l6: ldo6 {
- regulator-name = "pmr735a_l6";
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- };
-
- pmr735a_l7: ldo7 {
- regulator-name = "pmr735a_l7";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
- };
- };
-};
-
-&gpi_dma0 {
- status = "okay";
-};
-
-&gpi_dma1 {
- status = "okay";
-};
-
-&gpi_dma2 {
- status = "okay";
-};
-
-/* I2C4 is used, it hosts a Samsung touchscreen, but GPI DMA is broken.. */
-
-&i2c5 {
- clock-frequency = <400000>;
- status = "okay";
-
- /* Dialog SLG51000 CMIC @ 75 */
-};
-
-&i2c9 {
- clock-frequency = <400000>;
- status = "okay";
-
- /* NXP SN1X0 NFC @ 28 */
-};
-
-&i2c13 {
- clock-frequency = <400000>;
- status = "okay";
-
- /* Richwave RTC6226 FM Radio Receiver @ 64 */
-};
-
-&i2c14 {
- clock-frequency = <1000000>;
- status = "okay";
-
- cs35l41_l: speaker-amp@40 {
- compatible = "cirrus,cs35l41";
- reg = <0x40>;
- interrupt-parent = <&tlmm>;
- interrupts = <182 IRQ_TYPE_LEVEL_LOW>;
- reset-gpios = <&tlmm 183 GPIO_ACTIVE_HIGH>;
- cirrus,boost-peak-milliamp = <4000>;
- cirrus,boost-ind-nanohenry = <1000>;
- cirrus,boost-cap-microfarad = <15>;
- cirrus,gpio2-src-select = <2>;
- cirrus,gpio2-output-enable;
- cirrus,asp-sdout-hiz = <3>;
- #sound-dai-cells = <1>;
- };
-
- cs35l41_r: speaker-amp@41 {
- compatible = "cirrus,cs35l41";
- reg = <0x41>;
- interrupt-parent = <&tlmm>;
- interrupts = <182 IRQ_TYPE_LEVEL_LOW>;
- reset-gpios = <&tlmm 183 GPIO_ACTIVE_HIGH>;
- cirrus,boost-peak-milliamp = <4000>;
- cirrus,boost-ind-nanohenry = <1000>;
- cirrus,boost-cap-microfarad = <15>;
- cirrus,gpio2-src-select = <2>;
- cirrus,gpio2-output-enable;
- cirrus,asp-sdout-hiz = <3>;
- #sound-dai-cells = <1>;
- };
-};
-
-&i2c15 {
- clock-frequency = <400000>;
- status = "okay";
-
- /* AMS TCS3490 RGB+IR color sensor @ 72 */
-};
-
-&i2c19 {
- clock-frequency = <1000000>;
- status = "okay";
-
- /* Cirrus Logic CS40L25A boosted haptics driver @ 40 */
-};
-
-&pcie0 {
- max-link-speed = <2>;
- status = "okay";
-};
-
-&pcie0_phy {
- vdda-phy-supply = <&pm8350_l5>;
- vdda-pll-supply = <&pm8350_l6>;
- status = "okay";
-};
-
-&remoteproc_adsp {
- firmware-name = "qcom/adsp.mbn";
- status = "okay";
-};
-
-&remoteproc_cdsp {
- firmware-name = "qcom/cdsp.mbn";
- status = "okay";
-};
-
-&remoteproc_slpi {
- firmware-name = "qcom/slpi.mbn";
- status = "okay";
-};
-
-&qupv3_id_0 {
- status = "okay";
-};
-
-&qupv3_id_1 {
- status = "okay";
-};
-
-&qupv3_id_2 {
- status = "okay";
-};
-
-&sdhc_2 {
- cd-gpios = <&tlmm 92 GPIO_ACTIVE_HIGH>;
- pinctrl-names = "default", "sleep";
- pinctrl-0 = <&sdc2_default_state &sdc2_card_det_n>;
- pinctrl-1 = <&sdc2_sleep_state &sdc2_card_det_n>;
- vmmc-supply = <&pm8350c_l9>;
- vqmmc-supply = <&pm8350c_l6>;
- /* Forbid SDR104/SDR50 - broken hw! */
- sdhci-caps-mask = <0x3 0x0>;
- no-sdio;
- no-mmc;
- status = "okay";
-};
-
-&spi10 {
- status = "okay";
-
- /* NXP SN1X0 NFC Secure Element @ 0 */
};
&tlmm {
- gpio-reserved-ranges = <28 4>;
-
- sdc2_default_state: sdc2-default-state {
- clk-pins {
- pins = "sdc2_clk";
- drive-strength = <16>;
- bias-disable;
- };
-
- cmd-pins {
- pins = "sdc2_cmd";
- drive-strength = <16>;
- bias-pull-up;
- };
-
- data-pins {
- pins = "sdc2_data";
- drive-strength = <16>;
- bias-pull-up;
- };
- };
-
- ts_int_default: ts-int-default-state {
- pins = "gpio23";
- function = "gpio";
- drive-strength = <2>;
- bias-disable;
- input-enable;
- };
-
- sdc2_card_det_n: sd-card-det-n-state {
- pins = "gpio92";
- function = "gpio";
- drive-strength = <2>;
- bias-pull-up;
- };
-};
-
-&uart7 {
- status = "okay";
-};
-
-&usb_1 {
- status = "okay";
-};
-
-&usb_1_dwc3 {
- dr_mode = "peripheral";
-};
-
-&usb_1_hsphy {
- vdda-pll-supply = <&pm8350_l5>;
- vdda18-supply = <&pm8350c_l1>;
- vdda33-supply = <&pm8350_l2>;
- status = "okay";
-};
-
-&usb_1_qmpphy {
- vdda-phy-supply = <&pm8350_l6>;
- vdda-pll-supply = <&pm8350_l1>;
- status = "okay";
+ gpio-line-names = "NC", /* GPIO_0 */
+ "NC",
+ "NC",
+ "NC",
+ "WLC_I2C_SDA",
+ "WLC_I2C_SCL",
+ "NC",
+ "PM8010_1_RESET_N",
+ "WLC_INT_N",
+ "NC",
+ "NC", /* GPIO_10 */
+ "PM8010_2_RESET_N",
+ "DISP_ERR_FG",
+ "HALL_INT_N",
+ "ALS_PROX_INT_N",
+ "IMU1_INT",
+ "TS_I2C_SDA",
+ "TS_I2C_SCL",
+ "DISP_RESET_N",
+ "DISP_VDDR_EN",
+ "TS_RESET_N", /* GPIO_20 */
+ "TS_INT_N",
+ "NC",
+ "TELEC_PWR_EN",
+ "CAM1_RESET_N",
+ "LEO_CAM0_RESET_N",
+ "DEBUG_UART_TX",
+ "DEBUG_UART_RX",
+ "FP_SPI_MISO",
+ "FP_SPI_MOSI",
+ "FP_SPI_CLK", /* GPIO_30 */
+ "FP_SPI_CS_N",
+ "NFC_I2C_SDA",
+ "NFC_I2C_SCL",
+ "NFC_EN",
+ "NFC_CLK_REQ",
+ "NFC_ESE_SPI_MISO",
+ "NFC_ESE_SPI_MOSI",
+ "NFC_ESE_SPI_CLK",
+ "NFC_ESE_SPI_CS",
+ "FP_INT_N", /* GPIO_40 */
+ "NC",
+ "FP_RESET_N",
+ "WCD_RST_N",
+ "NC",
+ "NFC_DWL_REQ",
+ "NFC_IRQ",
+ "FORCE_USB_BOOT",
+ "APPS_I2C_1_SDA",
+ "APPS_I2C_1_SCL",
+ "SBU_SW_OE", /* GPIO_50 */
+ "SBU_SW_SEL",
+ "SPK_AMP_I2C_SDA",
+ "SPK_AMP_I2C_SCL",
+ "NC",
+ "NC",
+ "CAMSENSOR_I2C_SDA",
+ "CAMSENSOR_I2C_SCL",
+ "GNSS_ELNA_EN0",
+ "NC",
+ "NC", /* GPIO_60 */
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "RGBC_IR_INT",
+ "NC",
+ "NC",
+ "NC",
+ "NC", /* GPIO_70 */
+ "NC",
+ "HAP_I2C_SDA",
+ "HAP_I2C_SCL",
+ "HAP_RST_N",
+ "HAP_INT_N",
+ "HST_BT_UART_CTS",
+ "HST_BT_UART_RFR",
+ "HST_BT_UART_TX",
+ "HST_BT_UART_RX",
+ "HST_WLAN_EN", /* GPIO_80 */
+ "HST_BT_EN",
+ "HST_SW_CTRL",
+ "NC",
+ "NC",
+ "NC",
+ "DISP_VSYNC",
+ "NC",
+ "NC",
+ "HW_ID_0",
+ "HW_ID_1", /* GPIO_90 */
+ "USB_CC_DIR",
+ "TRAY_DET",
+ "SW_SERVICE",
+ "PCIE0_RESET_N",
+ "PCIE0_CLK_REQ_N",
+ "PCIE0_WAKE_N",
+ "OIS_ENABLE_WIDE",
+ "DEBUG_GPIO0",
+ "NC",
+ "CAM_MCLK0", /* GPIO_100 */
+ "CAM_MCLK1",
+ "CAM_MCLK2",
+ "CAM_MCLK3",
+ "NC",
+ "NC",
+ "TOF_RST_N",
+ "CAM_SOF",
+ "NC",
+ "AFEXPTMG_TELE",
+ "CCI_I2C0_SDA", /* GPIO_110 */
+ "CCI_I2C0_SCL",
+ "CCI_I2C1_SDA",
+ "CCI_I2C1_SCL",
+ "CCI_I2C2_SDA",
+ "CCI_I2C2_SCL",
+ "NC",
+ "CAM2_RESET_N",
+ "NC",
+ "EXT_VD0_XVS",
+ "CAM3_RESET_N", /* GPIO_120 */
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "RF_ID_EXTENSION_2",
+ "HAP_I2S_CLK",
+ "HAP_I2S_DOUT",
+ "HAP_TRG1",
+ "HAP_I2S_SYNC",
+ "UIM1_DATA", /* GPIO_130 */
+ "UIM1_CLK",
+ "UIM1_RESET",
+ "TRAY_DET",
+ "UIM2_DATA",
+ "UIM2_CLK",
+ "UIM2_RESET",
+ "UIM2_PRESENT",
+ "SM_RFFE0_CLK",
+ "SM_RFFE0_DATA",
+ "SM_RFFE1_CLK", /* GPIO_140 */
+ "SM_RFFE1_DATA",
+ "SM_MSS_GRFC4",
+ "HST_AS_EN",
+ "LAA_RX_EN",
+ "NC",
+ "SM_RFFE4_CLK",
+ "SM_RFFE4_DATA",
+ "WLAN_COEX_UART1_RX",
+ "WLAN_COEX_UART1_TX",
+ "RF_LCD_ID_EN", /* GPIO_150 */
+ "RF_ID_EXTENSION",
+ "SM_MSS_GRFC12",
+ "NFC_COLD_RST",
+ "NC",
+ "NC",
+ "SDR1_QLINK0_REQ",
+ "SDR1_QLINK0_EN",
+ "SDR1_QLINK0_WMSS_RESET_N",
+ "QLINK1_REQ",
+ "QLINK1_EN", /* GPIO_160 */
+ "QLINK1_WMSS_RESET_N",
+ "SDR2_QLINK2_REQ",
+ "SDR2_QLINK2_EN",
+ "SDR2_QLINK2_WMSS_RESET_N",
+ "WCD_SWR_TX_CLK",
+ "WCD_SWR_TX_DATA0",
+ "WCD_SWR_TX_DATA1",
+ "WCD_SWR_RX_CLK",
+ "WCD_SWR_RX_DATA0",
+ "WCD_SWR_RX_DATA1", /* GPIO_170 */
+ "SM_DMIC1_CLK",
+ "SM_DMIC1_DATA",
+ "SM_DMIC2_CLK",
+ "SM_DMIC2_DATA",
+ "SPK_AMP_I2S_CLK",
+ "SPK_AMP_I2S_WS",
+ "NC",
+ "NC",
+ "WCD_SWR_TX_DATA2",
+ "SPK_AMP_I2S_ASP_DIN", /* GPIO_180 */
+ "SPK_AMP_I2S_ASP_DOUT",
+ "SPK_AMP_INT_N",
+ "SPK_AMP_RESET_N",
+ "HST_BT_WLAN_SLIMBUS_CLK",
+ "HST_BT_WLAN_SLIMBUS_DAT0",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "MAG_I2C_SDA", /* GPIO_190 */
+ "MAG_I2C_SCL",
+ "IMU_SPI_MISO",
+ "IMU_SPI_MOSI",
+ "IMU_SPI_CLK",
+ "IMU_SPI_CS_N",
+ "SENSOR_I2C_SDA",
+ "SENSOR_I2C_SCL",
+ "OIS_TELE_I2C_SDA",
+ "OIS_TELE_I2C_SCL",
+ "NC", /* GPIO_200 */
+ "OIS_ENABLE_TELE",
+ "HST_BLE_UART_TX",
+ "HST_BLE_UART_RX",
+ "HSTP_CLK_CFG_SEL",
+ "NC",
+ "APPS_I2C_0_SDA",
+ "APPS_I2C_0_SCL",
+ "CCI_I2C3_SDA",
+ "CCI_I2C3_SCL";
};
diff --git a/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara-pdx224.dts b/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara-pdx224.dts
new file mode 100644
index 000000000000..13c2fc4bccfc
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara-pdx224.dts
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2022, Konrad Dybcio <konrad.dybcio@somainline.org>
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+/dts-v1/;
+
+#include "sm8450-sony-xperia-nagara.dtsi"
+
+/ {
+ model = "Sony Xperia 5 IV";
+ compatible = "sony,pdx224", "qcom,sm8450";
+
+ imx563_vdig_vreg: imx563-vdig-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "imx563_vdig_vreg";
+ gpio = <&tlmm 22 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+};
+
+&tlmm {
+ gpio-line-names = "TELE_SPI_MISO", /* GPIO_0 */
+ "TELE_SPI_MOSI", /* SONY says NC, but it only makes sense this way.. */
+ "TELE_SPI_CLK",
+ "TELE_SPI_CS_N",
+ "WLC_I2C_SDA",
+ "WLC_I2C_SCL",
+ "NC",
+ "PM8010_1_RESET_N",
+ "WLC_INT_N",
+ "NC",
+ "NC", /* GPIO_10 */
+ "NC",
+ "DISP_ERR_FG",
+ "HALL_INT_N",
+ "ALS_PROX_INT_N",
+ "IMU1_INT",
+ "TS_I2C_SDA",
+ "TS_I2C_SCL",
+ "DISP_RESET_N",
+ "DISP_VDDR_EN",
+ "TS_RESET_N", /* GPIO_20 */
+ "TS_INT_N",
+ "UWIDEC_PWR_EN",
+ "TELEC_PWR_EN",
+ "CAM1_RESET_N",
+ "LEO_CAM0_RESET_N",
+ "DEBUG_UART_TX",
+ "DEBUG_UART_RX",
+ "FP_SPI_MISO",
+ "FP_SPI_MOSI",
+ "FP_SPI_CLK", /* GPIO_30 */
+ "FP_SPI_CS_N",
+ "NFC_I2C_SDA",
+ "NFC_I2C_SCL",
+ "NFC_EN",
+ "NFC_CLK_REQ",
+ "NFC_ESE_SPI_MISO",
+ "NFC_ESE_SPI_MOSI",
+ "NFC_ESE_SPI_CLK",
+ "NFC_ESE_SPI_CS",
+ "FP_INT_N", /* GPIO_40 */
+ "NC",
+ "FP_RESET_N",
+ "WCD_RST_N",
+ "NC",
+ "NFC_DWL_REQ",
+ "NFC_IRQ",
+ "FORCE_USB_BOOT",
+ "APPS_I2C_1_SDA",
+ "APPS_I2C_1_SCL",
+ "SBU_SW_OE", /* GPIO_50 */
+ "SBU_SW_SEL",
+ "SPK_AMP_I2C_SDA",
+ "SPK_AMP_I2C_SCL",
+ "NC",
+ "NC",
+ "CAMSENSOR_I2C_SDA",
+ "CAMSENSOR_I2C_SCL",
+ "GNSS_ELNA_EN0",
+ "NC",
+ "NC", /* GPIO_60 */
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "RGBC_IR_INT",
+ "NC",
+ "NC",
+ "NC",
+ "NC", /* GPIO_70 */
+ "NC",
+ "HAP_I2C_SDA",
+ "HAP_I2C_SCL",
+ "HAP_RST_N",
+ "HAP_INT_N",
+ "HST_BT_UART_CTS",
+ "HST_BT_UART_RFR",
+ "HST_BT_UART_TX",
+ "HST_BT_UART_RX",
+ "HST_WLAN_EN", /* GPIO_80 */
+ "HST_BT_EN",
+ "HST_SW_CTRL",
+ "NC",
+ "NC",
+ "NC",
+ "DISP_VSYNC",
+ "NC",
+ "NC",
+ "HW_ID_0",
+ "HW_ID_1", /* GPIO_90 */
+ "USB_CC_DIR",
+ "TRAY_DET",
+ "SW_SERVICE",
+ "PCIE0_RESET_N",
+ "PCIE0_CLK_REQ_N",
+ "PCIE0_WAKE_N",
+ "OIS_ENABLE_WIDE",
+ "DEBUG_GPIO0",
+ "NC",
+ "CAM_MCLK0", /* GPIO_100 */
+ "CAM_MCLK1",
+ "CAM_MCLK2",
+ "CAM_MCLK3",
+ "NC",
+ "NC",
+ "NC", /* SONY didn't rename this, but there's no ToF so it's likely NC */
+ "CAM_SOF",
+ "NC",
+ "AFEXPTMG_TELE",
+ "CCI_I2C0_SDA", /* GPIO_110 */
+ "CCI_I2C0_SCL",
+ "CCI_I2C1_SDA",
+ "CCI_I2C1_SCL",
+ "CCI_I2C2_SDA",
+ "CCI_I2C2_SCL",
+ "NC",
+ "CAM2_RESET_N",
+ "NC",
+ "EXT_VD0_XVS",
+ "CAM3_RESET_N", /* GPIO_120 */
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "RF_ID_EXTENSION_2",
+ "HAP_I2S_CLK",
+ "HAP_I2S_DOUT",
+ "HAP_TRG1",
+ "HAP_I2S_SYNC",
+ "UIM1_DATA", /* GPIO_130 */
+ "UIM1_CLK",
+ "UIM1_RESET",
+ "TRAY_DET",
+ "UIM2_DATA",
+ "UIM2_CLK",
+ "UIM2_RESET",
+ "UIM2_PRESENT",
+ "SM_RFFE0_CLK",
+ "SM_RFFE0_DATA",
+ "SM_RFFE1_CLK", /* GPIO_140 */
+ "SM_RFFE1_DATA",
+ "SM_MSS_GRFC4",
+ "HST_AS_EN",
+ "LAA_RX_EN",
+ "NC",
+ "SM_RFFE4_CLK",
+ "SM_RFFE4_DATA",
+ "WLAN_COEX_UART1_RX",
+ "WLAN_COEX_UART1_TX",
+ "RF_LCD_ID_EN", /* GPIO_150 */
+ "RF_ID_EXTENSION",
+ "SM_MSS_GRFC12",
+ "NFC_COLD_RST",
+ "NC",
+ "NC",
+ "SDR1_QLINK0_REQ",
+ "SDR1_QLINK0_EN",
+ "SDR1_QLINK0_WMSS_RESET_N",
+ "NC",
+ "NC", /* GPIO_160 */
+ "NC",
+ "SDR2_QLINK2_REQ",
+ "SDR2_QLINK2_EN",
+ "SDR2_QLINK2_WMSS_RESET_N",
+ "WCD_SWR_TX_CLK",
+ "WCD_SWR_TX_DATA0",
+ "WCD_SWR_TX_DATA1",
+ "WCD_SWR_RX_CLK",
+ "WCD_SWR_RX_DATA0",
+ "WCD_SWR_RX_DATA1", /* GPIO_170 */
+ "SM_DMIC1_CLK",
+ "SM_DMIC1_DATA",
+ "SM_DMIC2_CLK",
+ "SM_DMIC2_DATA",
+ "SPK_AMP_I2S_CLK",
+ "SPK_AMP_I2S_WS",
+ "NC",
+ "NC",
+ "WCD_SWR_TX_DATA2",
+ "SPK_AMP_I2S_ASP_DIN", /* GPIO_180 */
+ "SPK_AMP_I2S_ASP_DOUT",
+ "SPK_AMP_INT_N",
+ "SPK_AMP_RESET_N",
+ "HST_BT_WLAN_SLIMBUS_CLK",
+ "HST_BT_WLAN_SLIMBUS_DAT0",
+ "NC",
+ "NC",
+ "NC",
+ "NC",
+ "MAG_I2C_SDA", /* GPIO_190 */
+ "MAG_I2C_SCL",
+ "IMU_SPI_MISO",
+ "IMU_SPI_MOSI",
+ "IMU_SPI_CLK",
+ "IMU_SPI_CS_N",
+ "SENSOR_I2C_SDA",
+ "SENSOR_I2C_SCL",
+ "OIS_TELE_I2C_SDA",
+ "OIS_TELE_I2C_SCL",
+ "NC", /* GPIO_200 */
+ "OIS_ENABLE_TELE",
+ "HST_BLE_UART_TX",
+ "HST_BLE_UART_RX",
+ "HSTP_CLK_CFG_SEL",
+ "NC",
+ "APPS_I2C_0_SDA",
+ "APPS_I2C_0_SCL",
+ "CCI_I2C3_SDA",
+ "CCI_I2C3_SCL";
+};
diff --git a/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara.dtsi b/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara.dtsi
new file mode 100644
index 000000000000..38256226d229
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sm8450-sony-xperia-nagara.dtsi
@@ -0,0 +1,631 @@
+// SPDX-License-Identifier: BSD-3-Clause
+/*
+ * Copyright (c) 2022, Konrad Dybcio <konrad.dybcio@somainline.org>
+ */
+
+#include <dt-bindings/regulator/qcom,rpmh-regulator.h>
+#include "sm8450.dtsi"
+
+/delete-node/ &adsp_mem;
+/delete-node/ &rmtfs_mem;
+/delete-node/ &video_mem;
+
+/ {
+ chassis-type = "handset";
+
+ aliases {
+ serial0 = &uart7;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ reserved-memory {
+ adsp_mem: memory@85700000 {
+ reg = <0x0 0x85700000 0x0 0x2800000>;
+ no-map;
+ };
+
+ video_mem: memory@9fd00000 {
+ reg = <0x0 0x9fd00000 0x0 0x700000>;
+ no-map;
+ };
+
+ rmtfs_mem: memory@f3300000 {
+ compatible = "qcom,rmtfs-mem";
+ reg = <0x0 0xf3300000 0x0 0x280000>;
+ no-map;
+
+ qcom,client-id = <1>;
+ qcom,vmid = <15>;
+ };
+
+ ramoops@ffc00000 {
+ compatible = "ramoops";
+ reg = <0 0xffc00000 0 0x200000>;
+ console-size = <0x40000>;
+ record-size = <0x1000>;
+ ecc-size = <16>;
+ no-map;
+ };
+ };
+
+ /* Sadly, the voltages for these GPIO regulators are unknown. */
+ imx650_vana_vreg: imx650-vana-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "imx650_vana_vreg";
+ gpio = <&tlmm 23 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ };
+
+ vph_pwr: vph-pwr-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vph_pwr";
+ regulator-min-microvolt = <3700000>;
+ regulator-max-microvolt = <3700000>;
+
+ regulator-always-on;
+ regulator-boot-on;
+ };
+};
+
+&apps_rsc {
+ pm8350-rpmh-regulators {
+ compatible = "qcom,pm8350-rpmh-regulators";
+ qcom,pmic-id = "b";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+ vdd-s4-supply = <&vph_pwr>;
+ vdd-s5-supply = <&vph_pwr>;
+ vdd-s6-supply = <&vph_pwr>;
+ vdd-s7-supply = <&vph_pwr>;
+ vdd-s8-supply = <&vph_pwr>;
+ vdd-s9-supply = <&vph_pwr>;
+ vdd-s10-supply = <&vph_pwr>;
+ vdd-s11-supply = <&vph_pwr>;
+ vdd-s12-supply = <&vph_pwr>;
+
+ vdd-l1-l4-supply = <&pm8350_s11>;
+ vdd-l2-l7-supply = <&vreg_bob>;
+ vdd-l3-l5-supply = <&vreg_bob>;
+ vdd-l6-l9-l10-supply = <&pm8350_s12>;
+
+ /*
+ * ARC regulators:
+ * s5 - gfx.lvl
+ * l8 - lcx.lvl
+ */
+
+ pm8350_s10: smps10 {
+ regulator-name = "pm8350_s10";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ };
+
+ pm8350_s11: smps11 {
+ regulator-name = "pm8350_s11";
+ regulator-min-microvolt = <848000>;
+ regulator-max-microvolt = <1104000>;
+ };
+
+ pm8350_s12: smps12 {
+ regulator-name = "pm8350_s12";
+ regulator-min-microvolt = <1224000>;
+ regulator-max-microvolt = <1400000>;
+ };
+
+ pm8350_l1: ldo1 {
+ regulator-name = "pm8350_l1";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <920000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350_l2: ldo2 {
+ regulator-name = "pm8350_l2";
+ regulator-min-microvolt = <3072000>;
+ regulator-max-microvolt = <3072000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350_l3: ldo3 {
+ regulator-name = "pm8350_l3";
+ regulator-min-microvolt = <904000>;
+ regulator-max-microvolt = <904000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350_l5: ldo5 {
+ regulator-name = "pm8350_l5";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350_l6: ldo6 {
+ regulator-name = "pm8350_l6";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350_l7: ldo7 {
+ regulator-name = "pm8350_l7";
+ regulator-min-microvolt = <2504000>;
+ regulator-max-microvolt = <2504000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350_l9: ldo9 {
+ regulator-name = "pm8350_l9";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ pm8350c-rpmh-regulators {
+ compatible = "qcom,pm8350c-rpmh-regulators";
+ qcom,pmic-id = "c";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+ vdd-s4-supply = <&vph_pwr>;
+ vdd-s5-supply = <&vph_pwr>;
+ vdd-s6-supply = <&vph_pwr>;
+ vdd-s7-supply = <&vph_pwr>;
+ vdd-s8-supply = <&vph_pwr>;
+ vdd-s9-supply = <&vph_pwr>;
+ vdd-s10-supply = <&vph_pwr>;
+
+ vdd-l1-l12-supply = <&vreg_bob>;
+ vdd-l2-l8-supply = <&vreg_bob>;
+ vdd-l3-l4-l5-l7-l13-supply = <&vreg_bob>;
+ vdd-l6-l9-l11-supply = <&vreg_bob>;
+ vdd-l10-supply = <&pm8350_s12>;
+
+ vdd-bob-supply = <&vph_pwr>;
+
+ /*
+ * ARC regulators:
+ * s2 - mxc.lvl
+ * s4 - mss.lvl
+ * s6 - cx.lvl
+ */
+
+ pm8350c_s1: smps1 {
+ regulator-name = "pm8350c_s1";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2024000>;
+ };
+
+ pm8350c_s10: smps10 {
+ regulator-name = "pm8350c_s10";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1100000>;
+ };
+
+ vreg_bob: bob {
+ regulator-name = "vreg_bob";
+ regulator-min-microvolt = <3400000>;
+ regulator-max-microvolt = <3960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_AUTO>;
+ };
+
+ pm8350c_l1: ldo1 {
+ regulator-name = "pm8350c_l1";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l2: ldo2 {
+ regulator-name = "pm8350c_l2";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l3: ldo3 {
+ regulator-name = "pm8350c_l3";
+ regulator-min-microvolt = <3296000>;
+ regulator-max-microvolt = <3304000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l4: ldo4 {
+ regulator-name = "pm8350c_l4";
+ regulator-min-microvolt = <1704000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l5: ldo5 {
+ regulator-name = "pm8350c_l5";
+ regulator-min-microvolt = <1704000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l6: ldo6 {
+ regulator-name = "pm8350c_l6";
+ regulator-min-microvolt = <2960000>;
+ /* Originally max = 3008000 but SDHCI expects 2960000 */
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l7: ldo7 {
+ regulator-name = "pm8350c_l7";
+ regulator-min-microvolt = <3008000>;
+ regulator-max-microvolt = <3008000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l8: ldo8 {
+ regulator-name = "pm8350c_l8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l9: ldo9 {
+ regulator-name = "pm8350c_l9";
+ regulator-min-microvolt = <2960000>;
+ /* Originally max = 3008000 but SDHCI expects 2960000 */
+ regulator-max-microvolt = <2960000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l10: ldo10 {
+ regulator-name = "pm8350c_l10";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l12: ldo12 {
+ regulator-name = "pm8350c_l12";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1968000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8350c_l13: ldo13 {
+ regulator-name = "pm8350c_l13";
+ regulator-min-microvolt = <3000000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ pm8450-rpmh-regulators {
+ compatible = "qcom,pm8450-rpmh-regulators";
+ qcom,pmic-id = "h";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+ vdd-s4-supply = <&vph_pwr>;
+ vdd-s5-supply = <&vph_pwr>;
+ vdd-s6-supply = <&vph_pwr>;
+
+ vdd-l2-supply = <&vreg_bob>;
+ vdd-l3-supply = <&vreg_bob>;
+ vdd-l4-supply = <&vreg_bob>;
+
+ /*
+ * ARC regulators:
+ * S2 - ebi.lvl
+ * S4 - mmcx.lvl
+ * S6 - mx.lvl
+ * L1 - lmx.lvl
+ */
+
+ pm8450_s3: smps3 {
+ regulator-name = "pm8450_s3";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <600000>;
+ };
+
+ pm8450_l2: ldo2 {
+ regulator-name = "pm8450_l2";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+
+ pm8450_l3: ldo3 {
+ regulator-name = "pm8450_l3";
+ regulator-min-microvolt = <912000>;
+ regulator-max-microvolt = <912000>;
+ regulator-initial-mode = <RPMH_REGULATOR_MODE_HPM>;
+ };
+ };
+
+ pmr735a-rpmh-regulators {
+ compatible = "qcom,pmr735a-rpmh-regulators";
+ qcom,pmic-id = "e";
+
+ vdd-s1-supply = <&vph_pwr>;
+ vdd-s2-supply = <&vph_pwr>;
+ vdd-s3-supply = <&vph_pwr>;
+
+ vdd-l1-l2-supply = <&pmr735a_s2>;
+ vdd-l3-supply = <&pmr735a_s1>;
+ vdd-l4-supply = <&pm8350c_s1>;
+ vdd-l5-l6-supply = <&pm8350c_s1>;
+ vdd-l7-bob-supply = <&vreg_bob>;
+
+ pmr735a_s1: smps1 {
+ regulator-name = "pmr735a_s1";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1296000>;
+ };
+
+ pmr735a_s2: smps2 {
+ regulator-name = "pmr735a_s2";
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1040000>;
+ };
+
+ pmr735a_s3: smps3 {
+ regulator-name = "pmr735a_s3";
+ regulator-min-microvolt = <435000>;
+ regulator-max-microvolt = <2352000>;
+ };
+
+ pmr735a_l1: ldo1 {
+ regulator-name = "pmr735a_l1";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <800000>;
+ };
+
+ pmr735a_l2: ldo2 {
+ regulator-name = "pmr735a_l2";
+ regulator-min-microvolt = <480000>;
+ regulator-max-microvolt = <912000>;
+ };
+
+ pmr735a_l3: ldo3 {
+ regulator-name = "pmr735a_l3";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pmr735a_l4: ldo4 {
+ regulator-name = "pmr735a_l4";
+ regulator-min-microvolt = <1776000>;
+ regulator-max-microvolt = <1776000>;
+ };
+
+ pmr735a_l5: ldo5 {
+ regulator-name = "pmr735a_l5";
+ regulator-min-microvolt = <880000>;
+ regulator-max-microvolt = <880000>;
+ };
+
+ pmr735a_l6: ldo6 {
+ regulator-name = "pmr735a_l6";
+ regulator-min-microvolt = <1200000>;
+ regulator-max-microvolt = <1200000>;
+ };
+
+ pmr735a_l7: ldo7 {
+ regulator-name = "pmr735a_l7";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ };
+ };
+};
+
+&gpi_dma0 {
+ status = "okay";
+};
+
+&gpi_dma1 {
+ status = "okay";
+};
+
+&gpi_dma2 {
+ status = "okay";
+};
+
+&i2c4 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ touchscreen@48 {
+ compatible = "samsung,s6sy761";
+ reg = <0x48>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <21 0x2008>;
+ vdd-supply = <&pm8350c_l2>;
+ avdd-supply = <&pm8350c_l3>;
+
+ pinctrl-names = "default";
+ pinctrl-0 = <&ts_reset_default &ts_int_default>;
+ };
+};
+
+&i2c5 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ /* Dialog SLG51000 CMIC @ 75 */
+};
+
+&i2c9 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ /* NXP SN1X0 NFC @ 28 */
+};
+
+&i2c13 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ /* Richwave RTC6226 FM Radio Receiver @ 64 */
+};
+
+&i2c14 {
+ clock-frequency = <1000000>;
+ status = "okay";
+
+ cs35l41_l: speaker-amp@40 {
+ compatible = "cirrus,cs35l41";
+ reg = <0x40>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <182 IRQ_TYPE_LEVEL_LOW>;
+ reset-gpios = <&tlmm 183 GPIO_ACTIVE_HIGH>;
+ cirrus,boost-peak-milliamp = <4000>;
+ cirrus,boost-ind-nanohenry = <1000>;
+ cirrus,boost-cap-microfarad = <15>;
+ cirrus,gpio2-src-select = <2>;
+ cirrus,gpio2-output-enable;
+ cirrus,asp-sdout-hiz = <3>;
+ #sound-dai-cells = <1>;
+ };
+
+ cs35l41_r: speaker-amp@41 {
+ compatible = "cirrus,cs35l41";
+ reg = <0x41>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <182 IRQ_TYPE_LEVEL_LOW>;
+ reset-gpios = <&tlmm 183 GPIO_ACTIVE_HIGH>;
+ cirrus,boost-peak-milliamp = <4000>;
+ cirrus,boost-ind-nanohenry = <1000>;
+ cirrus,boost-cap-microfarad = <15>;
+ cirrus,gpio2-src-select = <2>;
+ cirrus,gpio2-output-enable;
+ cirrus,asp-sdout-hiz = <3>;
+ #sound-dai-cells = <1>;
+ };
+};
+
+&i2c15 {
+ clock-frequency = <400000>;
+ status = "okay";
+
+ /* AMS TCS3490 RGB+IR color sensor @ 72 */
+};
+
+&i2c19 {
+ clock-frequency = <1000000>;
+ status = "okay";
+
+ /* Cirrus Logic CS40L25A boosted haptics driver @ 40 */
+};
+
+&pcie0 {
+ max-link-speed = <2>;
+ status = "okay";
+};
+
+&pcie0_phy {
+ vdda-phy-supply = <&pm8350_l5>;
+ vdda-pll-supply = <&pm8350_l6>;
+ status = "okay";
+};
+
+&remoteproc_adsp {
+ firmware-name = "qcom/sm8350/Sony/nagara/adsp.mbn";
+ status = "okay";
+};
+
+&remoteproc_cdsp {
+ firmware-name = "qcom/sm8350/Sony/nagara/cdsp.mbn";
+ status = "okay";
+};
+
+&remoteproc_slpi {
+ firmware-name = "qcom/sm8350/Sony/nagara/slpi.mbn";
+ status = "okay";
+};
+
+&qupv3_id_0 {
+ status = "okay";
+};
+
+&qupv3_id_1 {
+ status = "okay";
+};
+
+&qupv3_id_2 {
+ status = "okay";
+};
+
+&sdhc_2 {
+ cd-gpios = <&tlmm 92 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&sdc2_default_state &sdc2_card_det_n>;
+ pinctrl-1 = <&sdc2_sleep_state &sdc2_card_det_n>;
+ vmmc-supply = <&pm8350c_l9>;
+ vqmmc-supply = <&pm8350c_l6>;
+ no-sdio;
+ no-mmc;
+ status = "okay";
+};
+
+&spi10 {
+ status = "okay";
+
+ /* NXP SN1X0 NFC Secure Element @ 0 */
+};
+
+&tlmm {
+ gpio-reserved-ranges = <28 4>;
+
+ ts_reset_default: ts-reset-default-state {
+ pins = "gpio20";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ output-high;
+ };
+
+ ts_int_default: ts-int-default-state {
+ pins = "gpio21";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-disable;
+ input-enable;
+ };
+
+ sdc2_card_det_n: sd-card-det-n-state {
+ pins = "gpio92";
+ function = "gpio";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+};
+
+&uart7 {
+ status = "okay";
+};
+
+&usb_1 {
+ status = "okay";
+};
+
+&usb_1_dwc3 {
+ dr_mode = "peripheral";
+};
+
+&usb_1_hsphy {
+ vdda-pll-supply = <&pm8350_l5>;
+ vdda18-supply = <&pm8350c_l1>;
+ vdda33-supply = <&pm8350_l2>;
+ status = "okay";
+};
+
+&usb_1_qmpphy {
+ vdda-phy-supply = <&pm8350_l6>;
+ vdda-pll-supply = <&pm8350_l1>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/sm8450.dtsi b/arch/arm64/boot/dts/qcom/sm8450.dtsi
index d32f08df743d..570475040d95 100644
--- a/arch/arm64/boot/dts/qcom/sm8450.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8450.dtsi
@@ -7,12 +7,15 @@
#include <dt-bindings/clock/qcom,gcc-sm8450.h>
#include <dt-bindings/clock/qcom,rpmh.h>
#include <dt-bindings/clock/qcom,sm8450-camcc.h>
+#include <dt-bindings/clock/qcom,sm8450-dispcc.h>
#include <dt-bindings/dma/qcom-gpi.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/mailbox/qcom-ipcc.h>
#include <dt-bindings/power/qcom-rpmpd.h>
#include <dt-bindings/interconnect/qcom,sm8450.h>
+#include <dt-bindings/soc/qcom,gpr.h>
#include <dt-bindings/soc/qcom,rpmh-rsc.h>
+#include <dt-bindings/sound/qcom,q6dsp-lpass-ports.h>
#include <dt-bindings/thermal/thermal.h>
/ {
@@ -51,6 +54,7 @@
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
+ clocks = <&cpufreq_hw 0>;
L2_0: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
@@ -70,6 +74,7 @@
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
+ clocks = <&cpufreq_hw 0>;
L2_100: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
@@ -86,6 +91,7 @@
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
+ clocks = <&cpufreq_hw 0>;
L2_200: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
@@ -102,6 +108,7 @@
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 0>;
#cooling-cells = <2>;
+ clocks = <&cpufreq_hw 0>;
L2_300: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
@@ -118,6 +125,7 @@
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
+ clocks = <&cpufreq_hw 1>;
L2_400: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
@@ -134,6 +142,7 @@
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
+ clocks = <&cpufreq_hw 1>;
L2_500: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
@@ -151,6 +160,7 @@
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 1>;
#cooling-cells = <2>;
+ clocks = <&cpufreq_hw 1>;
L2_600: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
@@ -167,6 +177,7 @@
power-domain-names = "psci";
qcom,freq-domain = <&cpufreq_hw 2>;
#cooling-cells = <2>;
+ clocks = <&cpufreq_hw 2>;
L2_700: l2-cache {
compatible = "cache";
next-level-cache = <&L3_0>;
@@ -730,7 +741,7 @@
};
gpi_dma2: dma-controller@800000 {
- compatible = "qcom,sm8450-gpi-dma";
+ compatible = "qcom,sm8450-gpi-dma", "qcom,sm6350-gpi-dma";
#dma-cells = <3>;
reg = <0 0x800000 0 0x60000>;
interrupts = <GIC_SPI 588 IRQ_TYPE_LEVEL_HIGH>,
@@ -791,7 +802,6 @@
interrupts = <GIC_SPI 373 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&qup_spi15_data_clk>, <&qup_spi15_cs>;
- spi-max-frequency = <50000000>;
interconnects = <&clk_virt MASTER_QUP_CORE_2 0 &clk_virt SLAVE_QUP_CORE_2 0>,
<&system_noc MASTER_A2NOC_SNOC 0 &gem_noc SLAVE_LLCC 0>;
interconnect-names = "qup-core", "qup-config";
@@ -831,7 +841,6 @@
interrupts = <GIC_SPI 583 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&qup_spi16_data_clk>, <&qup_spi16_cs>;
- spi-max-frequency = <50000000>;
interconnects = <&clk_virt MASTER_QUP_CORE_2 0 &clk_virt SLAVE_QUP_CORE_2 0>,
<&system_noc MASTER_A2NOC_SNOC 0 &gem_noc SLAVE_LLCC 0>;
interconnect-names = "qup-core", "qup-config";
@@ -871,7 +880,6 @@
interrupts = <GIC_SPI 584 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&qup_spi17_data_clk>, <&qup_spi17_cs>;
- spi-max-frequency = <50000000>;
interconnects = <&clk_virt MASTER_QUP_CORE_2 0 &clk_virt SLAVE_QUP_CORE_2 0>,
<&system_noc MASTER_A2NOC_SNOC 0 &gem_noc SLAVE_LLCC 0>;
interconnect-names = "qup-core", "qup-config";
@@ -911,7 +919,6 @@
interrupts = <GIC_SPI 585 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&qup_spi18_data_clk>, <&qup_spi18_cs>;
- spi-max-frequency = <50000000>;
interconnects = <&clk_virt MASTER_QUP_CORE_2 0 &clk_virt SLAVE_QUP_CORE_2 0>,
<&system_noc MASTER_A2NOC_SNOC 0 &gem_noc SLAVE_LLCC 0>;
interconnect-names = "qup-core", "qup-config";
@@ -951,7 +958,6 @@
interrupts = <GIC_SPI 586 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&qup_spi19_data_clk>, <&qup_spi19_cs>;
- spi-max-frequency = <50000000>;
interconnects = <&clk_virt MASTER_QUP_CORE_2 0 &clk_virt SLAVE_QUP_CORE_2 0>,
<&system_noc MASTER_A2NOC_SNOC 0 &gem_noc SLAVE_LLCC 0>;
interconnect-names = "qup-core", "qup-config";
@@ -1004,7 +1010,6 @@
interrupts = <GIC_SPI 587 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&qup_spi20_data_clk>, <&qup_spi20_cs>;
- spi-max-frequency = <50000000>;
interconnects = <&clk_virt MASTER_QUP_CORE_2 0 &clk_virt SLAVE_QUP_CORE_2 0>,
<&system_noc MASTER_A2NOC_SNOC 0 &gem_noc SLAVE_LLCC 0>;
interconnect-names = "qup-core", "qup-config";
@@ -1044,7 +1049,6 @@
interrupts = <GIC_SPI 579 IRQ_TYPE_LEVEL_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&qup_spi21_data_clk>, <&qup_spi21_cs>;
- spi-max-frequency = <50000000>;
interconnects = <&clk_virt MASTER_QUP_CORE_2 0 &clk_virt SLAVE_QUP_CORE_2 0>,
<&system_noc MASTER_A2NOC_SNOC 0 &gem_noc SLAVE_LLCC 0>;
interconnect-names = "qup-core", "qup-config";
@@ -1058,7 +1062,7 @@
};
gpi_dma0: dma-controller@900000 {
- compatible = "qcom,sm8450-gpi-dma";
+ compatible = "qcom,sm8450-gpi-dma", "qcom,sm6350-gpi-dma";
#dma-cells = <3>;
reg = <0 0x900000 0 0x60000>;
interrupts = <GIC_SPI 244 IRQ_TYPE_LEVEL_HIGH>,
@@ -1394,7 +1398,7 @@
};
gpi_dma1: dma-controller@a00000 {
- compatible = "qcom,sm8450-gpi-dma";
+ compatible = "qcom,sm8450-gpi-dma", "qcom,sm6350-gpi-dma";
#dma-cells = <3>;
reg = <0 0xa00000 0 0x60000>;
interrupts = <GIC_SPI 279 IRQ_TYPE_LEVEL_HIGH>,
@@ -2095,9 +2099,212 @@
};
};
+ wsa2macro: codec@31e0000 {
+ compatible = "qcom,sm8450-lpass-wsa-macro";
+ reg = <0 0x031e0000 0 0x1000>;
+ clocks = <&q6prmcc LPASS_CLK_ID_WSA2_CORE_TX_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_CLK_ID_WSA2_CORE_TX_2X_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&vamacro>;
+ clock-names = "mclk", "npl", "macro", "dcodec", "fsgen";
+ assigned-clocks = <&q6prmcc LPASS_CLK_ID_WSA_CORE_TX_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_CLK_ID_WSA_CORE_TX_2X_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+ assigned-clock-rates = <19200000>, <19200000>;
+
+ #clock-cells = <0>;
+ clock-output-names = "wsa2-mclk";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wsa2_swr_active>;
+ #sound-dai-cells = <1>;
+ };
+
+ /* WSA2 */
+ swr4: soundwire-controller@31f0000 {
+ compatible = "qcom,soundwire-v1.7.0";
+ reg = <0 0x031f0000 0 0x2000>;
+ interrupts = <GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&wsa2macro>;
+ clock-names = "iface";
+
+ qcom,din-ports = <2>;
+ qcom,dout-ports = <6>;
+
+ qcom,ports-sinterval-low = /bits/ 8 <0x07 0x1f 0x3f 0x07 0x1f 0x3f 0x0f 0x0f>;
+ qcom,ports-offset1 = /bits/ 8 <0x01 0x02 0x0c 0x06 0x12 0x0d 0x07 0x0a>;
+ qcom,ports-offset2 = /bits/ 8 <0xff 0x00 0x1f 0xff 0x00 0x1f 0x00 0x00>;
+ qcom,ports-hstart = /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff>;
+ qcom,ports-hstop = /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff>;
+ qcom,ports-word-length = /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff>;
+ qcom,ports-block-pack-mode = /bits/ 8 <0xff 0xff 0x01 0xff 0xff 0x01 0xff 0xff>;
+ qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff>;
+ qcom,ports-lane-control = /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff>;
+
+ #address-cells = <2>;
+ #size-cells = <0>;
+ #sound-dai-cells = <1>;
+ };
+
+ rxmacro: codec@3200000 {
+ compatible = "qcom,sm8450-lpass-rx-macro";
+ reg = <0 0x3200000 0 0x1000>;
+ clocks = <&q6prmcc LPASS_CLK_ID_RX_CORE_TX_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_CLK_ID_RX_CORE_MCLK2_2X_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&vamacro>;
+ clock-names = "mclk", "npl", "macro", "dcodec", "fsgen";
+
+ assigned-clocks = <&q6prmcc LPASS_CLK_ID_RX_CORE_TX_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_CLK_ID_RX_CORE_MCLK2_2X_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+ assigned-clock-rates = <19200000>, <19200000>;
+
+ #clock-cells = <0>;
+ clock-output-names = "mclk";
+ pinctrl-names = "default";
+ pinctrl-0 = <&rx_swr_active>;
+ #sound-dai-cells = <1>;
+ };
+
+ swr1: soundwire-controller@3210000 {
+ compatible = "qcom,soundwire-v1.7.0";
+ reg = <0 0x3210000 0 0x2000>;
+ interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rxmacro>;
+ clock-names = "iface";
+ label = "RX";
+ qcom,din-ports = <0>;
+ qcom,dout-ports = <5>;
+
+ qcom,ports-sinterval-low = /bits/ 8 <0x03 0x1f 0x1f 0x07 0x00>;
+ qcom,ports-offset1 = /bits/ 8 <0x00 0x00 0x0b 0x01 0x00>;
+ qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x0b 0x00 0x00>;
+ qcom,ports-hstart = /bits/ 8 <0xff 0x03 0xff 0xff 0xff>;
+ qcom,ports-hstop = /bits/ 8 <0xff 0x06 0xff 0xff 0xff>;
+ qcom,ports-word-length = /bits/ 8 <0x01 0x07 0x04 0xff 0xff>;
+ qcom,ports-block-pack-mode = /bits/ 8 <0xff 0x00 0x01 0xff 0xff>;
+ qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff 0xff 0x00>;
+ qcom,ports-lane-control = /bits/ 8 <0x01 0x00 0x00 0x00 0x00>;
+
+ #address-cells = <2>;
+ #size-cells = <0>;
+ #sound-dai-cells = <1>;
+ };
+
+ txmacro: codec@3220000 {
+ compatible = "qcom,sm8450-lpass-tx-macro";
+ reg = <0 0x3220000 0 0x1000>;
+ clocks = <&q6prmcc LPASS_CLK_ID_RX_CORE_TX_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_CLK_ID_RX_CORE_MCLK2_2X_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&vamacro>;
+ clock-names = "mclk", "npl", "macro", "dcodec", "fsgen";
+ assigned-clocks = <&q6prmcc LPASS_CLK_ID_RX_CORE_TX_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_CLK_ID_RX_CORE_MCLK2_2X_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+ assigned-clock-rates = <19200000>, <19200000>;
+
+ #clock-cells = <0>;
+ clock-output-names = "mclk";
+ pinctrl-names = "default";
+ pinctrl-0 = <&tx_swr_active>;
+ #sound-dai-cells = <1>;
+ };
+
+ wsamacro: codec@3240000 {
+ compatible = "qcom,sm8450-lpass-wsa-macro";
+ reg = <0 0x03240000 0 0x1000>;
+ clocks = <&q6prmcc LPASS_CLK_ID_WSA_CORE_TX_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_CLK_ID_WSA_CORE_TX_2X_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&vamacro>;
+ clock-names = "mclk", "npl", "macro", "dcodec", "fsgen";
+
+ assigned-clocks = <&q6prmcc LPASS_CLK_ID_WSA_CORE_TX_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_CLK_ID_WSA_CORE_TX_2X_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+ assigned-clock-rates = <19200000>, <19200000>;
+
+ #clock-cells = <0>;
+ clock-output-names = "mclk";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wsa_swr_active>;
+ #sound-dai-cells = <1>;
+ };
+
+ /* WSA */
+ swr0: soundwire-controller@3250000 {
+ compatible = "qcom,soundwire-v1.7.0";
+ reg = <0 0x03250000 0 0x2000>;
+ interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&wsamacro>;
+ clock-names = "iface";
+
+ qcom,din-ports = <2>;
+ qcom,dout-ports = <6>;
+
+ qcom,ports-sinterval-low = /bits/ 8 <0x07 0x1f 0x3f 0x07 0x1f 0x3f 0x0f 0x0f>;
+ qcom,ports-offset1 = /bits/ 8 <0x01 0x02 0x0c 0x06 0x12 0x0d 0x07 0x0a>;
+ qcom,ports-offset2 = /bits/ 8 <0xff 0x00 0x1f 0xff 0x00 0x1f 0x00 0x00>;
+ qcom,ports-hstart = /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff>;
+ qcom,ports-hstop = /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff>;
+ qcom,ports-word-length = /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff>;
+ qcom,ports-block-pack-mode = /bits/ 8 <0xff 0xff 0x01 0xff 0xff 0x01 0xff 0xff>;
+ qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff>;
+ qcom,ports-lane-control = /bits/ 8 <0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff>;
+
+ #address-cells = <2>;
+ #size-cells = <0>;
+ #sound-dai-cells = <1>;
+ };
+
+ swr2: soundwire-controller@33b0000 {
+ compatible = "qcom,soundwire-v1.7.0";
+ reg = <0 0x33b0000 0 0x2000>;
+ interrupts-extended = <&intc GIC_SPI 496 IRQ_TYPE_LEVEL_HIGH>,
+ <&intc GIC_SPI 520 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "core", "wake";
+
+ clocks = <&vamacro>;
+ clock-names = "iface";
+ label = "TX";
+
+ qcom,din-ports = <4>;
+ qcom,dout-ports = <0>;
+ qcom,ports-sinterval-low = /bits/ 8 <0x01 0x01 0x03 0x03>;
+ qcom,ports-offset1 = /bits/ 8 <0x00 0x00 0x01 0x01>;
+ qcom,ports-offset2 = /bits/ 8 <0x00 0x00 0x00 0x00>;
+ qcom,ports-hstart = /bits/ 8 <0xff 0xff 0xff 0xff>;
+ qcom,ports-hstop = /bits/ 8 <0xff 0xff 0xff 0xff>;
+ qcom,ports-word-length = /bits/ 8 <0xff 0xff 0xff 0xff>;
+ qcom,ports-block-pack-mode = /bits/ 8 <0xff 0xff 0xff 0xff>;
+ qcom,ports-block-group-count = /bits/ 8 <0xff 0xff 0xff 0xff>;
+ qcom,ports-lane-control = /bits/ 8 <0x01 0x02 0x00 0x00>;
+
+ #address-cells = <2>;
+ #size-cells = <0>;
+ #sound-dai-cells = <1>;
+ };
+
+ vamacro: codec@33f0000 {
+ compatible = "qcom,sm8450-lpass-va-macro";
+ reg = <0 0x033f0000 0 0x1000>;
+ clocks = <&q6prmcc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_CLK_ID_RX_CORE_MCLK2_2X_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+ clock-names = "mclk", "macro", "dcodec", "npl";
+ assigned-clocks = <&q6prmcc LPASS_CLK_ID_TX_CORE_MCLK LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+ assigned-clock-rates = <19200000>;
+
+ #clock-cells = <0>;
+ clock-output-names = "fsgen";
+ #sound-dai-cells = <1>;
+ };
+
remoteproc_adsp: remoteproc@30000000 {
compatible = "qcom,sm8450-adsp-pas";
- reg = <0 0x030000000 0 0x100>;
+ reg = <0 0x30000000 0 0x100>;
interrupts-extended = <&pdc 6 IRQ_TYPE_EDGE_RISING>,
<&smp2p_adsp_in 0 IRQ_TYPE_EDGE_RISING>,
@@ -2133,6 +2340,45 @@
label = "lpass";
qcom,remote-pid = <2>;
+ gpr {
+ compatible = "qcom,gpr";
+ qcom,glink-channels = "adsp_apps";
+ qcom,domain = <GPR_DOMAIN_ID_ADSP>;
+ qcom,intents = <512 20>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ q6apm: service@1 {
+ compatible = "qcom,q6apm";
+ reg = <GPR_APM_MODULE_IID>;
+ #sound-dai-cells = <0>;
+ qcom,protection-domain = "avs/audio",
+ "msm/adsp/audio_pd";
+
+ q6apmdai: dais {
+ compatible = "qcom,q6apm-dais";
+ iommus = <&apps_smmu 0x1801 0x0>;
+ };
+
+ q6apmbedai: bedais {
+ compatible = "qcom,q6apm-lpass-dais";
+ #sound-dai-cells = <1>;
+ };
+ };
+
+ q6prm: service@2 {
+ compatible = "qcom,q6prm";
+ reg = <GPR_PRM_MODULE_IID>;
+ qcom,protection-domain = "avs/audio",
+ "msm/adsp/audio_pd";
+
+ q6prmcc: clock-controller {
+ compatible = "qcom,q6prm-lpass-clocks";
+ #clock-cells = <2>;
+ };
+ };
+ };
+
fastrpc {
compatible = "qcom,fastrpc";
qcom,glink-channels = "fastrpcglink-apps-dsp";
@@ -2163,7 +2409,7 @@
remoteproc_cdsp: remoteproc@32300000 {
compatible = "qcom,sm8450-cdsp-pas";
- reg = <0 0x032300000 0 0x1400000>;
+ reg = <0 0x32300000 0 0x1400000>;
interrupts-extended = <&intc GIC_SPI 578 IRQ_TYPE_EDGE_RISING>,
<&smp2p_cdsp_in 0 IRQ_TYPE_EDGE_RISING>,
@@ -2283,8 +2529,8 @@
clocks = <&rpmhcc RPMH_CXO_CLK>;
clock-names = "xo";
- power-domains = <&rpmhpd 0>,
- <&rpmhpd 12>;
+ power-domains = <&rpmhpd SM8450_CX>,
+ <&rpmhpd SM8450_MSS>;
power-domain-names = "cx", "mss";
memory-region = <&mpss_mem>;
@@ -2307,6 +2553,84 @@
};
};
+ cci0: cci@ac15000 {
+ compatible = "qcom,sm8450-cci";
+ reg = <0 0xac15000 0 0x1000>;
+ interrupts = <GIC_SPI 460 IRQ_TYPE_EDGE_RISING>;
+ power-domains = <&camcc TITAN_TOP_GDSC>;
+
+ clocks = <&camcc CAM_CC_CAMNOC_AXI_CLK>,
+ <&camcc CAM_CC_SLOW_AHB_CLK_SRC>,
+ <&camcc CAM_CC_CPAS_AHB_CLK>,
+ <&camcc CAM_CC_CCI_0_CLK>,
+ <&camcc CAM_CC_CCI_0_CLK_SRC>;
+ clock-names = "camnoc_axi",
+ "slow_ahb_src",
+ "cpas_ahb",
+ "cci",
+ "cci_src";
+ pinctrl-0 = <&cci0_default &cci1_default>;
+ pinctrl-1 = <&cci0_sleep &cci1_sleep>;
+ pinctrl-names = "default", "sleep";
+
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cci0_i2c0: i2c-bus@0 {
+ reg = <0>;
+ clock-frequency = <1000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ cci0_i2c1: i2c-bus@1 {
+ reg = <1>;
+ clock-frequency = <1000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
+ cci1: cci@ac16000 {
+ compatible = "qcom,sm8450-cci";
+ reg = <0 0xac16000 0 0x1000>;
+ interrupts = <GIC_SPI 271 IRQ_TYPE_EDGE_RISING>;
+ power-domains = <&camcc TITAN_TOP_GDSC>;
+
+ clocks = <&camcc CAM_CC_CAMNOC_AXI_CLK>,
+ <&camcc CAM_CC_SLOW_AHB_CLK_SRC>,
+ <&camcc CAM_CC_CPAS_AHB_CLK>,
+ <&camcc CAM_CC_CCI_1_CLK>,
+ <&camcc CAM_CC_CCI_1_CLK_SRC>;
+ clock-names = "camnoc_axi",
+ "slow_ahb_src",
+ "cpas_ahb",
+ "cci",
+ "cci_src";
+ pinctrl-0 = <&cci2_default &cci3_default>;
+ pinctrl-1 = <&cci2_sleep &cci3_sleep>;
+ pinctrl-names = "default", "sleep";
+
+ status = "disabled";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cci1_i2c0: i2c-bus@0 {
+ reg = <0>;
+ clock-frequency = <1000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+
+ cci1_i2c1: i2c-bus@1 {
+ reg = <1>;
+ clock-frequency = <1000000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
+ };
+
camcc: clock-controller@ade0000 {
compatible = "qcom,sm8450-camcc";
reg = <0 0x0ade0000 0 0x20000>;
@@ -2322,6 +2646,33 @@
status = "disabled";
};
+ dispcc: clock-controller@af00000 {
+ compatible = "qcom,sm8450-dispcc";
+ reg = <0 0x0af00000 0 0x20000>;
+ clocks = <&rpmhcc RPMH_CXO_CLK>,
+ <&rpmhcc RPMH_CXO_CLK_A>,
+ <&gcc GCC_DISP_AHB_CLK>,
+ <&sleep_clk>,
+ <0>, /* dsi0 */
+ <0>,
+ <0>, /* dsi1 */
+ <0>,
+ <0>, /* dp0 */
+ <0>,
+ <0>, /* dp1 */
+ <0>,
+ <0>, /* dp2 */
+ <0>,
+ <0>, /* dp3 */
+ <0>;
+ power-domains = <&rpmhpd SM8450_MMCX>;
+ required-opps = <&rpmhpd_opp_low_svs>;
+ #clock-cells = <1>;
+ #reset-cells = <1>;
+ #power-domain-cells = <1>;
+ status = "disabled";
+ };
+
pdc: interrupt-controller@b220000 {
compatible = "qcom,sm8450-pdc", "qcom,pdc";
reg = <0 0x0b220000 0 0x30000>, <0 0x174000f0 0 0x64>;
@@ -2384,6 +2735,26 @@
gpio-ranges = <&tlmm 0 0 211>;
wakeup-parent = <&pdc>;
+ sdc2_default_state: sdc2-default-state {
+ clk-pins {
+ pins = "sdc2_clk";
+ drive-strength = <16>;
+ bias-disable;
+ };
+
+ cmd-pins {
+ pins = "sdc2_cmd";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+
+ data-pins {
+ pins = "sdc2_data";
+ drive-strength = <16>;
+ bias-pull-up;
+ };
+ };
+
sdc2_sleep_state: sdc2-sleep-state {
clk-pins {
pins = "sdc2_clk";
@@ -2404,6 +2775,70 @@
};
};
+ cci0_default: cci0-default-state {
+ /* SDA, SCL */
+ pins = "gpio110", "gpio111";
+ function = "cci_i2c";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ cci0_sleep: cci0-sleep-state {
+ /* SDA, SCL */
+ pins = "gpio110", "gpio111";
+ function = "cci_i2c";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ cci1_default: cci1-default-state {
+ /* SDA, SCL */
+ pins = "gpio112", "gpio113";
+ function = "cci_i2c";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ cci1_sleep: cci1-sleep-state {
+ /* SDA, SCL */
+ pins = "gpio112", "gpio113";
+ function = "cci_i2c";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ cci2_default: cci2-default-state {
+ /* SDA, SCL */
+ pins = "gpio114", "gpio115";
+ function = "cci_i2c";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ cci2_sleep: cci2-sleep-state {
+ /* SDA, SCL */
+ pins = "gpio114", "gpio115";
+ function = "cci_i2c";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
+ cci3_default: cci3-default-state {
+ /* SDA, SCL */
+ pins = "gpio208", "gpio209";
+ function = "cci_i2c";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+
+ cci3_sleep: cci3-sleep-state {
+ /* SDA, SCL */
+ pins = "gpio208", "gpio209";
+ function = "cci_i2c";
+ drive-strength = <2>;
+ bias-pull-down;
+ };
+
pcie0_default_state: pcie0-default-state {
perst-pins {
pins = "gpio94";
@@ -2800,6 +3235,123 @@
};
+ lpass_tlmm: pinctrl@3440000{
+ compatible = "qcom,sm8450-lpass-lpi-pinctrl";
+ reg = <0 0x3440000 0x0 0x20000>,
+ <0 0x34d0000 0x0 0x10000>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ gpio-ranges = <&lpass_tlmm 0 0 23>;
+
+ clocks = <&q6prmcc LPASS_HW_MACRO_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>,
+ <&q6prmcc LPASS_HW_DCODEC_VOTE LPASS_CLK_ATTRIBUTE_COUPLE_NO>;
+ clock-names = "core", "audio";
+
+ tx_swr_active: tx-swr-active-state {
+ clk-pins {
+ pins = "gpio0";
+ function = "swr_tx_clk";
+ drive-strength = <2>;
+ slew-rate = <1>;
+ bias-disable;
+ };
+
+ data-pins {
+ pins = "gpio1", "gpio2", "gpio14";
+ function = "swr_tx_data";
+ drive-strength = <2>;
+ slew-rate = <1>;
+ bias-bus-hold;
+ };
+ };
+
+ rx_swr_active: rx-swr-active-state {
+ clk-pins {
+ pins = "gpio3";
+ function = "swr_rx_clk";
+ drive-strength = <2>;
+ slew-rate = <1>;
+ bias-disable;
+ };
+
+ data-pins {
+ pins = "gpio4", "gpio5";
+ function = "swr_rx_data";
+ drive-strength = <2>;
+ slew-rate = <1>;
+ bias-bus-hold;
+ };
+ };
+
+ dmic01_default: dmic01-default-state {
+ clk-pins {
+ pins = "gpio6";
+ function = "dmic1_clk";
+ drive-strength = <8>;
+ output-high;
+ };
+
+ data-pins {
+ pins = "gpio7";
+ function = "dmic1_data";
+ drive-strength = <8>;
+ input-enable;
+ };
+ };
+
+ dmic02_default: dmic02-default-state {
+ clk-pins {
+ pins = "gpio8";
+ function = "dmic2_clk";
+ drive-strength = <8>;
+ output-high;
+ };
+
+ data-pins {
+ pins = "gpio9";
+ function = "dmic2_data";
+ drive-strength = <8>;
+ input-enable;
+ };
+ };
+
+ wsa_swr_active: wsa-swr-active-state {
+ clk-pins {
+ pins = "gpio10";
+ function = "wsa_swr_clk";
+ drive-strength = <2>;
+ slew-rate = <1>;
+ bias-disable;
+ };
+
+ data-pins {
+ pins = "gpio11";
+ function = "wsa_swr_data";
+ drive-strength = <2>;
+ slew-rate = <1>;
+ bias-bus-hold;
+ };
+ };
+
+ wsa2_swr_active: wsa2-swr-active-state {
+ clk-pins {
+ pins = "gpio15";
+ function = "wsa2_swr_clk";
+ drive-strength = <2>;
+ slew-rate = <1>;
+ bias-disable;
+ };
+
+ data-pins {
+ pins = "gpio16";
+ function = "wsa2_swr_data";
+ drive-strength = <2>;
+ slew-rate = <1>;
+ bias-bus-hold;
+ };
+ };
+ };
+
apps_smmu: iommu@15000000 {
compatible = "qcom,sm8450-smmu-500", "arm,mmu-500";
reg = <0 0x15000000 0 0x100000>;
@@ -2999,6 +3551,7 @@
qcom,drv-id = <2>;
qcom,tcs-config = <ACTIVE_TCS 3>, <SLEEP_TCS 2>,
<WAKE_TCS 2>, <CONTROL_TCS 0>;
+ power-domains = <&CLUSTER_PD>;
apps_bcm_voter: bcm-voter {
compatible = "qcom,bcm-voter";
@@ -3075,6 +3628,7 @@
<GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "dcvsh-irq-0", "dcvsh-irq-1", "dcvsh-irq-2";
#freq-domain-cells = <1>;
+ #clock-cells = <1>;
};
gem_noc: interconnect@19100000 {
@@ -3161,16 +3715,16 @@
status = "disabled";
ufs_mem_phy_lanes: phy@1d87400 {
- reg = <0 0x01d87400 0 0x108>,
- <0 0x01d87600 0 0x1e0>,
- <0 0x01d87c00 0 0x1dc>,
- <0 0x01d87800 0 0x108>,
- <0 0x01d87a00 0 0x1e0>;
+ reg = <0 0x01d87400 0 0x188>,
+ <0 0x01d87600 0 0x200>,
+ <0 0x01d87c00 0 0x200>,
+ <0 0x01d87800 0 0x188>,
+ <0 0x01d87a00 0 0x200>;
#phy-cells = <0>;
};
};
- sdhc_2: sdhci@8804000 {
+ sdhc_2: mmc@8804000 {
compatible = "qcom,sm8450-sdhci", "qcom,sdhci-msm-v5";
reg = <0 0x08804000 0 0x1000>;
@@ -3192,6 +3746,9 @@
bus-width = <4>;
dma-coherent;
+ /* Forbid SDR104/SDR50 - broken hw! */
+ sdhci-caps-mask = <0x3 0x0>;
+
status = "disabled";
sdhc2_opp_table: opp-table {
@@ -3274,6 +3831,9 @@
};
};
+ sound: sound {
+ };
+
thermal-zones {
aoss0-thermal {
polling-delay-passive = <0>;
diff --git a/arch/arm64/boot/dts/renesas/aistarvision-mipi-adapter-2.1.dtsi b/arch/arm64/boot/dts/renesas/aistarvision-mipi-adapter-2.1.dtsi
index 7ce986f0a06f..7cb5c958aece 100644
--- a/arch/arm64/boot/dts/renesas/aistarvision-mipi-adapter-2.1.dtsi
+++ b/arch/arm64/boot/dts/renesas/aistarvision-mipi-adapter-2.1.dtsi
@@ -65,7 +65,6 @@
ov5645: ov5645@3c {
compatible = "ovti,ov5645";
reg = <0x3c>;
- clock-names = "xclk";
clocks = <&osc25250_clk>;
clock-frequency = <24000000>;
vdddo-supply = <&ov5645_vdddo_1v8>;
diff --git a/arch/arm64/boot/dts/renesas/condor-common.dtsi b/arch/arm64/boot/dts/renesas/condor-common.dtsi
index dfbe35bf46e0..7c34d14dcd7e 100644
--- a/arch/arm64/boot/dts/renesas/condor-common.dtsi
+++ b/arch/arm64/boot/dts/renesas/condor-common.dtsi
@@ -21,6 +21,7 @@
chosen {
stdout-path = "serial0:115200n8";
+ bootargs = "ignore_loglevel rw root=/dev/nfs ip=on";
};
d1_8v: regulator-2 {
diff --git a/arch/arm64/boot/dts/renesas/draak-ebisu-panel-aa104xd12.dts b/arch/arm64/boot/dts/renesas/draak-ebisu-panel-aa104xd12.dtso
index 258f8668ca36..258f8668ca36 100644
--- a/arch/arm64/boot/dts/renesas/draak-ebisu-panel-aa104xd12.dts
+++ b/arch/arm64/boot/dts/renesas/draak-ebisu-panel-aa104xd12.dtso
diff --git a/arch/arm64/boot/dts/renesas/r8a779a0.dtsi b/arch/arm64/boot/dts/renesas/r8a779a0.dtsi
index ed9400f903c9..41fbb9998cf8 100644
--- a/arch/arm64/boot/dts/renesas/r8a779a0.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779a0.dtsi
@@ -656,7 +656,7 @@
avb0: ethernet@e6800000 {
compatible = "renesas,etheravb-r8a779a0",
- "renesas,etheravb-rcar-gen3";
+ "renesas,etheravb-rcar-gen4";
reg = <0 0xe6800000 0 0x800>;
interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH>,
@@ -704,7 +704,7 @@
avb1: ethernet@e6810000 {
compatible = "renesas,etheravb-r8a779a0",
- "renesas,etheravb-rcar-gen3";
+ "renesas,etheravb-rcar-gen4";
reg = <0 0xe6810000 0 0x800>;
interrupts = <GIC_SPI 281 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>,
@@ -752,7 +752,7 @@
avb2: ethernet@e6820000 {
compatible = "renesas,etheravb-r8a779a0",
- "renesas,etheravb-rcar-gen3";
+ "renesas,etheravb-rcar-gen4";
reg = <0 0xe6820000 0 0x1000>;
interrupts = <GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 307 IRQ_TYPE_LEVEL_HIGH>,
@@ -800,7 +800,7 @@
avb3: ethernet@e6830000 {
compatible = "renesas,etheravb-r8a779a0",
- "renesas,etheravb-rcar-gen3";
+ "renesas,etheravb-rcar-gen4";
reg = <0 0xe6830000 0 0x1000>;
interrupts = <GIC_SPI 331 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 332 IRQ_TYPE_LEVEL_HIGH>,
@@ -848,7 +848,7 @@
avb4: ethernet@e6840000 {
compatible = "renesas,etheravb-r8a779a0",
- "renesas,etheravb-rcar-gen3";
+ "renesas,etheravb-rcar-gen4";
reg = <0 0xe6840000 0 0x1000>;
interrupts = <GIC_SPI 356 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 357 IRQ_TYPE_LEVEL_HIGH>,
@@ -896,7 +896,7 @@
avb5: ethernet@e6850000 {
compatible = "renesas,etheravb-r8a779a0",
- "renesas,etheravb-rcar-gen3";
+ "renesas,etheravb-rcar-gen4";
reg = <0 0xe6850000 0 0x1000>;
interrupts = <GIC_SPI 381 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 382 IRQ_TYPE_LEVEL_HIGH>,
@@ -1019,7 +1019,7 @@
msiof0: spi@e6e90000 {
compatible = "renesas,msiof-r8a779a0",
- "renesas,rcar-gen3-msiof";
+ "renesas,rcar-gen4-msiof";
reg = <0 0xe6e90000 0 0x0064>;
interrupts = <GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 618>;
@@ -1034,7 +1034,7 @@
msiof1: spi@e6ea0000 {
compatible = "renesas,msiof-r8a779a0",
- "renesas,rcar-gen3-msiof";
+ "renesas,rcar-gen4-msiof";
reg = <0 0xe6ea0000 0 0x0064>;
interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 619>;
@@ -1049,7 +1049,7 @@
msiof2: spi@e6c00000 {
compatible = "renesas,msiof-r8a779a0",
- "renesas,rcar-gen3-msiof";
+ "renesas,rcar-gen4-msiof";
reg = <0 0xe6c00000 0 0x0064>;
interrupts = <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 620>;
@@ -1064,7 +1064,7 @@
msiof3: spi@e6c10000 {
compatible = "renesas,msiof-r8a779a0",
- "renesas,rcar-gen3-msiof";
+ "renesas,rcar-gen4-msiof";
reg = <0 0xe6c10000 0 0x0064>;
interrupts = <GIC_SPI 248 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 621>;
@@ -1079,7 +1079,7 @@
msiof4: spi@e6c20000 {
compatible = "renesas,msiof-r8a779a0",
- "renesas,rcar-gen3-msiof";
+ "renesas,rcar-gen4-msiof";
reg = <0 0xe6c20000 0 0x0064>;
interrupts = <GIC_SPI 249 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 622>;
@@ -1094,7 +1094,7 @@
msiof5: spi@e6c28000 {
compatible = "renesas,msiof-r8a779a0",
- "renesas,rcar-gen3-msiof";
+ "renesas,rcar-gen4-msiof";
reg = <0 0xe6c28000 0 0x0064>;
interrupts = <GIC_SPI 250 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 623>;
diff --git a/arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi b/arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi
index a45df1041705..045d70535519 100644
--- a/arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779f0-spider-cpu.dtsi
@@ -12,13 +12,13 @@
compatible = "renesas,spider-cpu", "renesas,r8a779f0";
aliases {
- serial0 = &scif3;
+ serial0 = &hscif0;
serial1 = &scif0;
};
chosen {
bootargs = "ignore_loglevel rw root=/dev/nfs ip=on";
- stdout-path = "serial0:115200n8";
+ stdout-path = "serial0:1843200n8";
};
memory@48000000 {
@@ -59,6 +59,14 @@
clock-frequency = <32768>;
};
+&hscif0 {
+ pinctrl-0 = <&hscif0_pins>;
+ pinctrl-names = "default";
+
+ uart-has-rtscts;
+ status = "okay";
+};
+
&i2c4 {
pinctrl-0 = <&i2c4_pins>;
pinctrl-names = "default";
@@ -99,6 +107,11 @@
pinctrl-0 = <&scif_clk_pins>;
pinctrl-names = "default";
+ hscif0_pins: hscif0 {
+ groups = "hscif0_data", "hscif0_ctrl";
+ function = "hscif0";
+ };
+
i2c4_pins: i2c4 {
groups = "i2c4";
function = "i2c4";
@@ -115,11 +128,6 @@
function = "scif0";
};
- scif3_pins: scif3 {
- groups = "scif3_data", "scif3_ctrl";
- function = "scif3";
- };
-
scif_clk_pins: scif_clk {
groups = "scif_clk";
function = "scif_clk";
@@ -139,14 +147,6 @@
status = "okay";
};
-&scif3 {
- pinctrl-0 = <&scif3_pins>;
- pinctrl-names = "default";
-
- uart-has-rtscts;
- status = "okay";
-};
-
&scif_clk {
clock-frequency = <24000000>;
};
diff --git a/arch/arm64/boot/dts/renesas/r8a779f0-spider-ethernet.dtsi b/arch/arm64/boot/dts/renesas/r8a779f0-spider-ethernet.dtsi
index 15e8d1ebf575..33c1015e9ab3 100644
--- a/arch/arm64/boot/dts/renesas/r8a779f0-spider-ethernet.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779f0-spider-ethernet.dtsi
@@ -5,6 +5,10 @@
* Copyright (C) 2021 Renesas Electronics Corp.
*/
+&eth_serdes {
+ status = "okay";
+};
+
&i2c4 {
eeprom@52 {
compatible = "rohm,br24g01", "atmel,24c01";
@@ -13,3 +17,89 @@
pagesize = <8>;
};
};
+
+&pfc {
+ tsn0_pins: tsn0 {
+ groups = "tsn0_mdio_b", "tsn0_link_b";
+ function = "tsn0";
+ power-source = <1800>;
+ };
+
+ tsn1_pins: tsn1 {
+ groups = "tsn1_mdio_b", "tsn1_link_b";
+ function = "tsn1";
+ power-source = <1800>;
+ };
+
+ tsn2_pins: tsn2 {
+ groups = "tsn2_mdio_b", "tsn2_link_b";
+ function = "tsn2";
+ power-source = <1800>;
+ };
+};
+
+&rswitch {
+ pinctrl-0 = <&tsn0_pins>, <&tsn1_pins>, <&tsn2_pins>;
+ pinctrl-names = "default";
+ status = "okay";
+
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ phy-handle = <&u101>;
+ phy-mode = "sgmii";
+ phys = <&eth_serdes 0>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ u101: ethernet-phy@1 {
+ reg = <1>;
+ compatible = "ethernet-phy-ieee802.3-c45";
+ interrupt-parent = <&gpio3>;
+ interrupts = <10 IRQ_TYPE_LEVEL_LOW>;
+ };
+ };
+ };
+ port@1 {
+ reg = <1>;
+ phy-handle = <&u201>;
+ phy-mode = "sgmii";
+ phys = <&eth_serdes 1>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ u201: ethernet-phy@2 {
+ reg = <2>;
+ compatible = "ethernet-phy-ieee802.3-c45";
+ interrupt-parent = <&gpio3>;
+ interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
+ };
+ };
+ };
+ port@2 {
+ reg = <2>;
+ phy-handle = <&u301>;
+ phy-mode = "sgmii";
+ phys = <&eth_serdes 2>;
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ u301: ethernet-phy@3 {
+ reg = <3>;
+ compatible = "ethernet-phy-ieee802.3-c45";
+ interrupt-parent = <&gpio3>;
+ interrupts = <9 IRQ_TYPE_LEVEL_LOW>;
+ };
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a779f0.dtsi b/arch/arm64/boot/dts/renesas/r8a779f0.dtsi
index c2f152bcf10e..67a4f2d4480d 100644
--- a/arch/arm64/boot/dts/renesas/r8a779f0.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779f0.dtsi
@@ -469,6 +469,16 @@
status = "disabled";
};
+ eth_serdes: phy@e6444000 {
+ compatible = "renesas,r8a779f0-ether-serdes";
+ reg = <0 0xe6444000 0 0x2800>;
+ clocks = <&cpg CPG_MOD 1506>;
+ power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
+ resets = <&cpg 1506>;
+ #phy-cells = <1>;
+ status = "disabled";
+ };
+
i2c0: i2c@e6500000 {
compatible = "renesas,i2c-r8a779f0",
"renesas,rcar-gen4-i2c";
@@ -577,7 +587,7 @@
reg = <0 0xe6540000 0 0x60>;
interrupts = <GIC_SPI 245 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 514>,
- <&cpg CPG_CORE R8A779F0_CLK_S0D3>,
+ <&cpg CPG_CORE R8A779F0_CLK_SASYNCPERD1>,
<&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
dmas = <&dmac0 0x31>, <&dmac0 0x30>,
@@ -594,7 +604,7 @@
reg = <0 0xe6550000 0 0x60>;
interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 515>,
- <&cpg CPG_CORE R8A779F0_CLK_S0D3>,
+ <&cpg CPG_CORE R8A779F0_CLK_SASYNCPERD1>,
<&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
dmas = <&dmac0 0x33>, <&dmac0 0x32>,
@@ -611,7 +621,7 @@
reg = <0 0xe6560000 0 0x60>;
interrupts = <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 516>,
- <&cpg CPG_CORE R8A779F0_CLK_S0D3>,
+ <&cpg CPG_CORE R8A779F0_CLK_SASYNCPERD1>,
<&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
dmas = <&dmac0 0x35>, <&dmac0 0x34>,
@@ -628,7 +638,7 @@
reg = <0 0xe66a0000 0 0x60>;
interrupts = <GIC_SPI 248 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 517>,
- <&cpg CPG_CORE R8A779F0_CLK_S0D3>,
+ <&cpg CPG_CORE R8A779F0_CLK_SASYNCPERD1>,
<&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
dmas = <&dmac0 0x37>, <&dmac0 0x36>,
@@ -651,13 +661,113 @@
status = "disabled";
};
+ rswitch: ethernet@e6880000 {
+ compatible = "renesas,r8a779f0-ether-switch";
+ reg = <0 0xe6880000 0 0x20000>, <0 0xe68c0000 0 0x20000>;
+ reg-names = "base", "secure_base";
+ interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 257 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 258 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 259 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 269 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 271 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 276 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 277 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 278 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 280 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 281 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 283 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 284 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 285 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 289 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 291 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 292 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 293 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 294 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 295 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 296 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 297 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 298 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 299 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 300 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 301 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 302 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 304 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 305 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "mfwd_error", "race_error",
+ "coma_error", "gwca0_error",
+ "gwca1_error", "etha0_error",
+ "etha1_error", "etha2_error",
+ "gptp0_status", "gptp1_status",
+ "mfwd_status", "race_status",
+ "coma_status", "gwca0_status",
+ "gwca1_status", "etha0_status",
+ "etha1_status", "etha2_status",
+ "rmac0_status", "rmac1_status",
+ "rmac2_status",
+ "gwca0_rxtx0", "gwca0_rxtx1",
+ "gwca0_rxtx2", "gwca0_rxtx3",
+ "gwca0_rxtx4", "gwca0_rxtx5",
+ "gwca0_rxtx6", "gwca0_rxtx7",
+ "gwca1_rxtx0", "gwca1_rxtx1",
+ "gwca1_rxtx2", "gwca1_rxtx3",
+ "gwca1_rxtx4", "gwca1_rxtx5",
+ "gwca1_rxtx6", "gwca1_rxtx7",
+ "gwca0_rxts0", "gwca0_rxts1",
+ "gwca1_rxts0", "gwca1_rxts1",
+ "rmac0_mdio", "rmac1_mdio",
+ "rmac2_mdio",
+ "rmac0_phy", "rmac1_phy",
+ "rmac2_phy";
+ clocks = <&cpg CPG_MOD 1505>;
+ power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
+ resets = <&cpg 1505>;
+ status = "disabled";
+
+ ethernet-ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ phys = <&eth_serdes 0>;
+ };
+ port@1 {
+ reg = <1>;
+ phys = <&eth_serdes 1>;
+ };
+ port@2 {
+ reg = <2>;
+ phys = <&eth_serdes 2>;
+ };
+ };
+ };
+
scif0: serial@e6e60000 {
compatible = "renesas,scif-r8a779f0",
"renesas,rcar-gen4-scif", "renesas,scif";
reg = <0 0xe6e60000 0 64>;
interrupts = <GIC_SPI 249 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 702>,
- <&cpg CPG_CORE R8A779F0_CLK_S0D3_PER>,
+ <&cpg CPG_CORE R8A779F0_CLK_SASYNCPERD1>,
<&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
dmas = <&dmac0 0x51>, <&dmac0 0x50>,
@@ -674,7 +784,7 @@
reg = <0 0xe6e68000 0 64>;
interrupts = <GIC_SPI 250 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 703>,
- <&cpg CPG_CORE R8A779F0_CLK_S0D3_PER>,
+ <&cpg CPG_CORE R8A779F0_CLK_SASYNCPERD1>,
<&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
dmas = <&dmac0 0x53>, <&dmac0 0x52>,
@@ -691,7 +801,7 @@
reg = <0 0xe6c50000 0 64>;
interrupts = <GIC_SPI 252 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 704>,
- <&cpg CPG_CORE R8A779F0_CLK_S0D3_PER>,
+ <&cpg CPG_CORE R8A779F0_CLK_SASYNCPERD1>,
<&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
dmas = <&dmac0 0x57>, <&dmac0 0x56>,
@@ -708,7 +818,7 @@
reg = <0 0xe6c40000 0 64>;
interrupts = <GIC_SPI 253 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 705>,
- <&cpg CPG_CORE R8A779F0_CLK_S0D3_PER>,
+ <&cpg CPG_CORE R8A779F0_CLK_SASYNCPERD1>,
<&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
dmas = <&dmac0 0x59>, <&dmac0 0x58>,
diff --git a/arch/arm64/boot/dts/renesas/r8a779g0-white-hawk-cpu.dtsi b/arch/arm64/boot/dts/renesas/r8a779g0-white-hawk-cpu.dtsi
index 895f0bd9f754..c10740aee9f6 100644
--- a/arch/arm64/boot/dts/renesas/r8a779g0-white-hawk-cpu.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779g0-white-hawk-cpu.dtsi
@@ -96,6 +96,24 @@
device_type = "memory";
reg = <0x6 0x00000000 0x1 0x00000000>;
};
+
+ reg_1p8v: regulator-1p8v {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-1.8V";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ reg_3p3v: regulator-3p3v {
+ compatible = "regulator-fixed";
+ regulator-name = "fixed-3.3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
};
&avb0 {
@@ -135,6 +153,17 @@
status = "okay";
clock-frequency = <400000>;
+ io_expander_a: gpio@20 {
+ compatible = "onnn,pca9654";
+ reg = <0x20>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
eeprom@50 {
compatible = "rohm,br24g01", "atmel,24c01";
label = "cpu-board";
@@ -143,6 +172,23 @@
};
};
+&mmc0 {
+ pinctrl-0 = <&mmc_pins>;
+ pinctrl-1 = <&mmc_pins>;
+ pinctrl-names = "default", "state_uhs";
+
+ vmmc-supply = <&reg_3p3v>;
+ vqmmc-supply = <&reg_1p8v>;
+ mmc-hs200-1_8v;
+ mmc-hs400-1_8v;
+ bus-width = <8>;
+ no-sd;
+ no-sdio;
+ non-removable;
+ full-pwr-cycle-in-suspend;
+ status = "okay";
+};
+
&pfc {
pinctrl-0 = <&scif_clk_pins>;
pinctrl-names = "default";
@@ -180,17 +226,56 @@
bias-pull-up;
};
+ mmc_pins: mmc {
+ groups = "mmc_data8", "mmc_ctrl", "mmc_ds";
+ function = "mmc";
+ power-source = <1800>;
+ };
+
+ qspi0_pins: qspi0 {
+ groups = "qspi0_ctrl", "qspi0_data4";
+ function = "qspi0";
+ };
+
scif_clk_pins: scif_clk {
groups = "scif_clk";
function = "scif_clk";
};
};
-&scif_clk {
- clock-frequency = <24000000>;
+&rpc {
+ pinctrl-0 = <&qspi0_pins>;
+ pinctrl-names = "default";
+
+ status = "okay";
+
+ flash@0 {
+ compatible = "spansion,s25fs512s", "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <40000000>;
+ spi-rx-bus-width = <4>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ boot@0 {
+ reg = <0x0 0x1200000>;
+ read-only;
+ };
+ user@1200000 {
+ reg = <0x1200000 0x2e00000>;
+ };
+ };
+ };
};
&rwdt {
timeout-sec = <60>;
status = "okay";
};
+
+&scif_clk {
+ clock-frequency = <24000000>;
+};
diff --git a/arch/arm64/boot/dts/renesas/r8a779g0.dtsi b/arch/arm64/boot/dts/renesas/r8a779g0.dtsi
index d70f0600ae5a..45d8d927ad26 100644
--- a/arch/arm64/boot/dts/renesas/r8a779g0.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779g0.dtsi
@@ -14,18 +14,138 @@
#address-cells = <2>;
#size-cells = <2>;
+ cluster0_opp: opp-table-0 {
+ compatible = "operating-points-v2";
+ opp-shared;
+
+ opp-500000000 {
+ opp-hz = /bits/ 64 <500000000>;
+ opp-microvolt = <825000>;
+ clock-latency-ns = <500000>;
+ };
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-microvolt = <825000>;
+ clock-latency-ns = <500000>;
+ };
+ opp-1500000000 {
+ opp-hz = /bits/ 64 <1500000000>;
+ opp-microvolt = <825000>;
+ clock-latency-ns = <500000>;
+ };
+ opp-1700000000 {
+ opp-hz = /bits/ 64 <1700000000>;
+ opp-microvolt = <825000>;
+ clock-latency-ns = <500000>;
+ opp-suspend;
+ };
+ };
+
cpus {
#address-cells = <1>;
#size-cells = <0>;
+ cpu-map {
+ cluster0 {
+ core0 {
+ cpu = <&a76_0>;
+ };
+ core1 {
+ cpu = <&a76_1>;
+ };
+ };
+
+ cluster1 {
+ core0 {
+ cpu = <&a76_2>;
+ };
+ core1 {
+ cpu = <&a76_3>;
+ };
+ };
+ };
+
a76_0: cpu@0 {
compatible = "arm,cortex-a76";
reg = <0>;
device_type = "cpu";
power-domains = <&sysc R8A779G0_PD_A1E0D0C0>;
+ next-level-cache = <&L3_CA76_0>;
+ enable-method = "psci";
+ cpu-idle-states = <&CPU_SLEEP_0>;
+ clocks = <&cpg CPG_CORE R8A779G0_CLK_Z0>;
+ operating-points-v2 = <&cluster0_opp>;
+ };
+
+ a76_1: cpu@100 {
+ compatible = "arm,cortex-a76";
+ reg = <0x100>;
+ device_type = "cpu";
+ power-domains = <&sysc R8A779G0_PD_A1E0D0C1>;
+ next-level-cache = <&L3_CA76_0>;
+ enable-method = "psci";
+ cpu-idle-states = <&CPU_SLEEP_0>;
+ clocks = <&cpg CPG_CORE R8A779G0_CLK_Z0>;
+ operating-points-v2 = <&cluster0_opp>;
+ };
+
+ a76_2: cpu@10000 {
+ compatible = "arm,cortex-a76";
+ reg = <0x10000>;
+ device_type = "cpu";
+ power-domains = <&sysc R8A779G0_PD_A1E0D1C0>;
+ next-level-cache = <&L3_CA76_1>;
+ enable-method = "psci";
+ cpu-idle-states = <&CPU_SLEEP_0>;
+ clocks = <&cpg CPG_CORE R8A779G0_CLK_Z0>;
+ operating-points-v2 = <&cluster0_opp>;
+ };
+
+ a76_3: cpu@10100 {
+ compatible = "arm,cortex-a76";
+ reg = <0x10100>;
+ device_type = "cpu";
+ power-domains = <&sysc R8A779G0_PD_A1E0D1C1>;
+ next-level-cache = <&L3_CA76_1>;
+ enable-method = "psci";
+ cpu-idle-states = <&CPU_SLEEP_0>;
+ clocks = <&cpg CPG_CORE R8A779G0_CLK_Z0>;
+ operating-points-v2 = <&cluster0_opp>;
+ };
+
+ idle-states {
+ entry-method = "psci";
+
+ CPU_SLEEP_0: cpu-sleep-0 {
+ compatible = "arm,idle-state";
+ arm,psci-suspend-param = <0x0010000>;
+ local-timer-stop;
+ entry-latency-us = <400>;
+ exit-latency-us = <500>;
+ min-residency-us = <4000>;
+ };
+ };
+
+ L3_CA76_0: cache-controller-0 {
+ compatible = "cache";
+ power-domains = <&sysc R8A779G0_PD_A2E0D0>;
+ cache-unified;
+ cache-level = <3>;
+ };
+
+ L3_CA76_1: cache-controller-1 {
+ compatible = "cache";
+ power-domains = <&sysc R8A779G0_PD_A2E0D1>;
+ cache-unified;
+ cache-level = <3>;
};
};
+ psci {
+ compatible = "arm,psci-1.0", "arm,psci-0.2";
+ method = "smc";
+ };
+
extal_clk: extal {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -214,6 +334,76 @@
#interrupt-cells = <2>;
};
+ cmt0: timer@e60f0000 {
+ compatible = "renesas,r8a779g0-cmt0",
+ "renesas,rcar-gen4-cmt0";
+ reg = <0 0xe60f0000 0 0x1004>;
+ interrupts = <GIC_SPI 260 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 910>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 910>;
+ status = "disabled";
+ };
+
+ cmt1: timer@e6130000 {
+ compatible = "renesas,r8a779g0-cmt1",
+ "renesas,rcar-gen4-cmt1";
+ reg = <0 0xe6130000 0 0x1004>;
+ interrupts = <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 264 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 265 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 266 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 267 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 269 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 911>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 911>;
+ status = "disabled";
+ };
+
+ cmt2: timer@e6140000 {
+ compatible = "renesas,r8a779g0-cmt1",
+ "renesas,rcar-gen4-cmt1";
+ reg = <0 0xe6140000 0 0x1004>;
+ interrupts = <GIC_SPI 270 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 271 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 273 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 276 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 277 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 912>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 912>;
+ status = "disabled";
+ };
+
+ cmt3: timer@e6148000 {
+ compatible = "renesas,r8a779g0-cmt1",
+ "renesas,rcar-gen4-cmt1";
+ reg = <0 0xe6148000 0 0x1004>;
+ interrupts = <GIC_SPI 278 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 279 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 280 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 281 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 283 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 284 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 285 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 913>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 913>;
+ status = "disabled";
+ };
+
cpg: clock-controller@e6150000 {
compatible = "renesas,r8a779g0-cpg-mssr";
reg = <0 0xe6150000 0 0x4000>;
@@ -235,12 +425,96 @@
#power-domain-cells = <1>;
};
+ intc_ex: interrupt-controller@e61c0000 {
+ compatible = "renesas,intc-ex-r8a779g0", "renesas,irqc";
+ #interrupt-cells = <2>;
+ interrupt-controller;
+ reg = <0 0xe61c0000 0 0x200>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 611>;
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 611>;
+ };
+
+ tmu0: timer@e61e0000 {
+ compatible = "renesas,tmu-r8a779g0", "renesas,tmu";
+ reg = <0 0xe61e0000 0 0x30>;
+ interrupts = <GIC_SPI 289 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 291 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 713>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 713>;
+ status = "disabled";
+ };
+
+ tmu1: timer@e6fc0000 {
+ compatible = "renesas,tmu-r8a779g0", "renesas,tmu";
+ reg = <0 0xe6fc0000 0 0x30>;
+ interrupts = <GIC_SPI 292 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 293 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 294 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 714>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 714>;
+ status = "disabled";
+ };
+
+ tmu2: timer@e6fd0000 {
+ compatible = "renesas,tmu-r8a779g0", "renesas,tmu";
+ reg = <0 0xe6fd0000 0 0x30>;
+ interrupts = <GIC_SPI 296 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 297 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 298 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 715>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 715>;
+ status = "disabled";
+ };
+
+ tmu3: timer@e6fe0000 {
+ compatible = "renesas,tmu-r8a779g0", "renesas,tmu";
+ reg = <0 0xe6fe0000 0 0x30>;
+ interrupts = <GIC_SPI 300 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 301 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 302 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 716>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 716>;
+ status = "disabled";
+ };
+
+ tmu4: timer@ffc00000 {
+ compatible = "renesas,tmu-r8a779g0", "renesas,tmu";
+ reg = <0 0xffc00000 0 0x30>;
+ interrupts = <GIC_SPI 304 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 305 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 717>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 717>;
+ status = "disabled";
+ };
+
i2c0: i2c@e6500000 {
compatible = "renesas,i2c-r8a779g0",
"renesas,rcar-gen4-i2c";
reg = <0 0xe6500000 0 0x40>;
interrupts = <GIC_SPI 610 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 518>;
+ dmas = <&dmac0 0x91>, <&dmac0 0x90>,
+ <&dmac1 0x91>, <&dmac1 0x90>;
+ dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
resets = <&cpg 518>;
i2c-scl-internal-delay-ns = <110>;
@@ -255,6 +529,9 @@
reg = <0 0xe6508000 0 0x40>;
interrupts = <GIC_SPI 611 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 519>;
+ dmas = <&dmac0 0x93>, <&dmac0 0x92>,
+ <&dmac1 0x93>, <&dmac1 0x92>;
+ dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
resets = <&cpg 519>;
i2c-scl-internal-delay-ns = <110>;
@@ -269,6 +546,9 @@
reg = <0 0xe6510000 0 0x40>;
interrupts = <GIC_SPI 612 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 520>;
+ dmas = <&dmac0 0x95>, <&dmac0 0x94>,
+ <&dmac1 0x95>, <&dmac1 0x94>;
+ dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
resets = <&cpg 520>;
i2c-scl-internal-delay-ns = <110>;
@@ -283,6 +563,9 @@
reg = <0 0xe66d0000 0 0x40>;
interrupts = <GIC_SPI 613 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 521>;
+ dmas = <&dmac0 0x97>, <&dmac0 0x96>,
+ <&dmac1 0x97>, <&dmac1 0x96>;
+ dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
resets = <&cpg 521>;
i2c-scl-internal-delay-ns = <110>;
@@ -297,6 +580,9 @@
reg = <0 0xe66d8000 0 0x40>;
interrupts = <GIC_SPI 614 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 522>;
+ dma-names = "tx", "rx", "tx", "rx";
+ dmas = <&dmac0 0x99>, <&dmac0 0x98>,
+ <&dmac1 0x99>, <&dmac1 0x98>;
power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
resets = <&cpg 522>;
i2c-scl-internal-delay-ns = <110>;
@@ -311,6 +597,9 @@
reg = <0 0xe66e0000 0 0x40>;
interrupts = <GIC_SPI 615 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 523>;
+ dmas = <&dmac0 0x9b>, <&dmac0 0x9a>,
+ <&dmac1 0x9b>, <&dmac1 0x9a>;
+ dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
resets = <&cpg 523>;
i2c-scl-internal-delay-ns = <110>;
@@ -321,19 +610,72 @@
hscif0: serial@e6540000 {
compatible = "renesas,hscif-r8a779g0",
- "renesas,rcar-gen4-hscif",
- "renesas,hscif";
- reg = <0 0xe6540000 0 96>;
+ "renesas,rcar-gen4-hscif", "renesas,hscif";
+ reg = <0 0xe6540000 0 0x60>;
interrupts = <GIC_SPI 246 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 514>,
- <&cpg CPG_CORE R8A779G0_CLK_S0D3_PER>,
+ <&cpg CPG_CORE R8A779G0_CLK_SASYNCPERD1>,
<&scif_clk>;
clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x31>, <&dmac0 0x30>,
+ <&dmac1 0x31>, <&dmac1 0x30>;
+ dma-names = "tx", "rx", "tx", "rx";
power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
resets = <&cpg 514>;
status = "disabled";
};
+ hscif1: serial@e6550000 {
+ compatible = "renesas,hscif-r8a779g0",
+ "renesas,rcar-gen4-hscif", "renesas,hscif";
+ reg = <0 0xe6550000 0 0x60>;
+ interrupts = <GIC_SPI 247 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 515>,
+ <&cpg CPG_CORE R8A779G0_CLK_SASYNCPERD1>,
+ <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x33>, <&dmac0 0x32>,
+ <&dmac1 0x33>, <&dmac1 0x32>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 515>;
+ status = "disabled";
+ };
+
+ hscif2: serial@e6560000 {
+ compatible = "renesas,hscif-r8a779g0",
+ "renesas,rcar-gen4-hscif", "renesas,hscif";
+ reg = <0 0xe6560000 0 0x60>;
+ interrupts = <GIC_SPI 248 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 516>,
+ <&cpg CPG_CORE R8A779G0_CLK_SASYNCPERD1>,
+ <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x35>, <&dmac0 0x34>,
+ <&dmac1 0x35>, <&dmac1 0x34>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 516>;
+ status = "disabled";
+ };
+
+ hscif3: serial@e66a0000 {
+ compatible = "renesas,hscif-r8a779g0",
+ "renesas,rcar-gen4-hscif", "renesas,hscif";
+ reg = <0 0xe66a0000 0 0x60>;
+ interrupts = <GIC_SPI 249 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 517>,
+ <&cpg CPG_CORE R8A779G0_CLK_SASYNCPERD1>,
+ <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x37>, <&dmac0 0x36>,
+ <&dmac1 0x37>, <&dmac1 0x36>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 517>;
+ status = "disabled";
+ };
+
avb0: ethernet@e6800000 {
compatible = "renesas,etheravb-r8a779g0",
"renesas,etheravb-rcar-gen4";
@@ -475,6 +817,381 @@
status = "disabled";
};
+ pwm0: pwm@e6e30000 {
+ compatible = "renesas,pwm-r8a779g0", "renesas,pwm-rcar";
+ reg = <0 0xe6e30000 0 0x10>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 628>;
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 628>;
+ status = "disabled";
+ };
+
+ pwm1: pwm@e6e31000 {
+ compatible = "renesas,pwm-r8a779g0", "renesas,pwm-rcar";
+ reg = <0 0xe6e31000 0 0x10>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 628>;
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 628>;
+ status = "disabled";
+ };
+
+ pwm2: pwm@e6e32000 {
+ compatible = "renesas,pwm-r8a779g0", "renesas,pwm-rcar";
+ reg = <0 0xe6e32000 0 0x10>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 628>;
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 628>;
+ status = "disabled";
+ };
+
+ pwm3: pwm@e6e33000 {
+ compatible = "renesas,pwm-r8a779g0", "renesas,pwm-rcar";
+ reg = <0 0xe6e33000 0 0x10>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 628>;
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 628>;
+ status = "disabled";
+ };
+
+ pwm4: pwm@e6e34000 {
+ compatible = "renesas,pwm-r8a779g0", "renesas,pwm-rcar";
+ reg = <0 0xe6e34000 0 0x10>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 628>;
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 628>;
+ status = "disabled";
+ };
+
+ pwm5: pwm@e6e35000 {
+ compatible = "renesas,pwm-r8a779g0", "renesas,pwm-rcar";
+ reg = <0 0xe6e35000 0 0x10>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 628>;
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 628>;
+ status = "disabled";
+ };
+
+ pwm6: pwm@e6e36000 {
+ compatible = "renesas,pwm-r8a779g0", "renesas,pwm-rcar";
+ reg = <0 0xe6e36000 0 0x10>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 628>;
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 628>;
+ status = "disabled";
+ };
+
+ pwm7: pwm@e6e37000 {
+ compatible = "renesas,pwm-r8a779g0", "renesas,pwm-rcar";
+ reg = <0 0xe6e37000 0 0x10>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 628>;
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 628>;
+ status = "disabled";
+ };
+
+ pwm8: pwm@e6e38000 {
+ compatible = "renesas,pwm-r8a779g0", "renesas,pwm-rcar";
+ reg = <0 0xe6e38000 0 0x10>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 628>;
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 628>;
+ status = "disabled";
+ };
+
+ pwm9: pwm@e6e39000 {
+ compatible = "renesas,pwm-r8a779g0", "renesas,pwm-rcar";
+ reg = <0 0xe6e39000 0 0x10>;
+ #pwm-cells = <2>;
+ clocks = <&cpg CPG_MOD 628>;
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 628>;
+ status = "disabled";
+ };
+
+ scif0: serial@e6e60000 {
+ compatible = "renesas,scif-r8a779g0",
+ "renesas,rcar-gen4-scif", "renesas,scif";
+ reg = <0 0xe6e60000 0 64>;
+ interrupts = <GIC_SPI 251 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 702>,
+ <&cpg CPG_CORE R8A779G0_CLK_SASYNCPERD1>,
+ <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x51>, <&dmac0 0x50>,
+ <&dmac1 0x51>, <&dmac1 0x50>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 702>;
+ status = "disabled";
+ };
+
+ scif1: serial@e6e68000 {
+ compatible = "renesas,scif-r8a779g0",
+ "renesas,rcar-gen4-scif", "renesas,scif";
+ reg = <0 0xe6e68000 0 64>;
+ interrupts = <GIC_SPI 252 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 703>,
+ <&cpg CPG_CORE R8A779G0_CLK_SASYNCPERD1>,
+ <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x53>, <&dmac0 0x52>,
+ <&dmac1 0x53>, <&dmac1 0x52>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 703>;
+ status = "disabled";
+ };
+
+ scif3: serial@e6c50000 {
+ compatible = "renesas,scif-r8a779g0",
+ "renesas,rcar-gen4-scif", "renesas,scif";
+ reg = <0 0xe6c50000 0 64>;
+ interrupts = <GIC_SPI 253 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 704>,
+ <&cpg CPG_CORE R8A779G0_CLK_SASYNCPERD1>,
+ <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x57>, <&dmac0 0x56>,
+ <&dmac1 0x57>, <&dmac1 0x56>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 704>;
+ status = "disabled";
+ };
+
+ scif4: serial@e6c40000 {
+ compatible = "renesas,scif-r8a779g0",
+ "renesas,rcar-gen4-scif", "renesas,scif";
+ reg = <0 0xe6c40000 0 64>;
+ interrupts = <GIC_SPI 254 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 705>,
+ <&cpg CPG_CORE R8A779G0_CLK_SASYNCPERD1>,
+ <&scif_clk>;
+ clock-names = "fck", "brg_int", "scif_clk";
+ dmas = <&dmac0 0x59>, <&dmac0 0x58>,
+ <&dmac1 0x59>, <&dmac1 0x58>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 705>;
+ status = "disabled";
+ };
+
+ tpu: pwm@e6e80000 {
+ compatible = "renesas,tpu-r8a779g0", "renesas,tpu";
+ reg = <0 0xe6e80000 0 0x148>;
+ interrupts = <GIC_SPI 308 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 718>;
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 718>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
+ msiof0: spi@e6e90000 {
+ compatible = "renesas,msiof-r8a779g0",
+ "renesas,rcar-gen4-msiof";
+ reg = <0 0xe6e90000 0 0x0064>;
+ interrupts = <GIC_SPI 239 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 618>;
+ dmas = <&dmac0 0x41>, <&dmac0 0x40>,
+ <&dmac1 0x41>, <&dmac1 0x40>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 618>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ msiof1: spi@e6ea0000 {
+ compatible = "renesas,msiof-r8a779g0",
+ "renesas,rcar-gen4-msiof";
+ reg = <0 0xe6ea0000 0 0x0064>;
+ interrupts = <GIC_SPI 240 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 619>;
+ dmas = <&dmac0 0x43>, <&dmac0 0x42>,
+ <&dmac1 0x43>, <&dmac1 0x42>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 619>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ msiof2: spi@e6c00000 {
+ compatible = "renesas,msiof-r8a779g0",
+ "renesas,rcar-gen4-msiof";
+ reg = <0 0xe6c00000 0 0x0064>;
+ interrupts = <GIC_SPI 241 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 620>;
+ dmas = <&dmac0 0x45>, <&dmac0 0x44>,
+ <&dmac1 0x45>, <&dmac1 0x44>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 620>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ msiof3: spi@e6c10000 {
+ compatible = "renesas,msiof-r8a779g0",
+ "renesas,rcar-gen4-msiof";
+ reg = <0 0xe6c10000 0 0x0064>;
+ interrupts = <GIC_SPI 242 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 621>;
+ dmas = <&dmac0 0x47>, <&dmac0 0x46>,
+ <&dmac1 0x47>, <&dmac1 0x46>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 621>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ msiof4: spi@e6c20000 {
+ compatible = "renesas,msiof-r8a779g0",
+ "renesas,rcar-gen4-msiof";
+ reg = <0 0xe6c20000 0 0x0064>;
+ interrupts = <GIC_SPI 243 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 622>;
+ dmas = <&dmac0 0x49>, <&dmac0 0x48>,
+ <&dmac1 0x49>, <&dmac1 0x48>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 622>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ msiof5: spi@e6c28000 {
+ compatible = "renesas,msiof-r8a779g0",
+ "renesas,rcar-gen4-msiof";
+ reg = <0 0xe6c28000 0 0x0064>;
+ interrupts = <GIC_SPI 244 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 623>;
+ dmas = <&dmac0 0x4b>, <&dmac0 0x4a>,
+ <&dmac1 0x4b>, <&dmac1 0x4a>;
+ dma-names = "tx", "rx", "tx", "rx";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 623>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
+ dmac0: dma-controller@e7350000 {
+ compatible = "renesas,dmac-r8a779g0",
+ "renesas,rcar-gen4-dmac";
+ reg = <0 0xe7350000 0 0x1000>,
+ <0 0xe7300000 0 0x10000>;
+ interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 82 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 93 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3", "ch4",
+ "ch5", "ch6", "ch7", "ch8", "ch9",
+ "ch10", "ch11", "ch12", "ch13",
+ "ch14", "ch15";
+ clocks = <&cpg CPG_MOD 709>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 709>;
+ #dma-cells = <1>;
+ dma-channels = <16>;
+ };
+
+ dmac1: dma-controller@e7351000 {
+ compatible = "renesas,dmac-r8a779g0",
+ "renesas,rcar-gen4-dmac";
+ reg = <0 0xe7351000 0 0x1000>,
+ <0 0xe7310000 0 0x10000>;
+ interrupts = <GIC_SPI 98 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "error",
+ "ch0", "ch1", "ch2", "ch3", "ch4",
+ "ch5", "ch6", "ch7", "ch8", "ch9",
+ "ch10", "ch11", "ch12", "ch13",
+ "ch14", "ch15";
+ clocks = <&cpg CPG_MOD 710>;
+ clock-names = "fck";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 710>;
+ #dma-cells = <1>;
+ dma-channels = <16>;
+ };
+
+ mmc0: mmc@ee140000 {
+ compatible = "renesas,sdhi-r8a779g0",
+ "renesas,rcar-gen4-sdhi";
+ reg = <0 0xee140000 0 0x2000>;
+ interrupts = <GIC_SPI 440 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 706>,
+ <&cpg CPG_CORE R8A779G0_CLK_SD0H>;
+ clock-names = "core", "clkh";
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 706>;
+ max-frequency = <200000000>;
+ status = "disabled";
+ };
+
+ rpc: spi@ee200000 {
+ compatible = "renesas,r8a779g0-rpc-if",
+ "renesas,rcar-gen4-rpc-if";
+ reg = <0 0xee200000 0 0x200>,
+ <0 0x08000000 0 0x04000000>,
+ <0 0xee208000 0 0x100>;
+ reg-names = "regs", "dirmap", "wbuf";
+ interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cpg CPG_MOD 629>;
+ power-domains = <&sysc R8A779G0_PD_ALWAYS_ON>;
+ resets = <&cpg 629>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
+
gic: interrupt-controller@f1000000 {
compatible = "arm,gic-v3";
#interrupt-cells = <3>;
@@ -483,7 +1200,7 @@
reg = <0x0 0xf1000000 0 0x20000>,
<0x0 0xf1060000 0 0x110000>;
interrupts = <GIC_PPI 9
- (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
+ (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
};
prr: chipid@fff00044 {
@@ -494,9 +1211,9 @@
timer {
compatible = "arm,armv8-timer";
- interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
};
};
diff --git a/arch/arm64/boot/dts/renesas/r9a07g043.dtsi b/arch/arm64/boot/dts/renesas/r9a07g043.dtsi
index 689aa4ba416b..3f7d451b1199 100644
--- a/arch/arm64/boot/dts/renesas/r9a07g043.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a07g043.dtsi
@@ -1,11 +1,10 @@
// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
/*
- * Device Tree Source for the RZ/G2UL SoC
+ * Device Tree Source for the RZ/Five and RZ/G2UL SoCs
*
* Copyright (C) 2022 Renesas Electronics Corp.
*/
-#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/r9a07g043-cpg.h>
/ {
@@ -69,36 +68,8 @@
};
};
- cpus {
- #address-cells = <1>;
- #size-cells = <0>;
-
- cpu0: cpu@0 {
- compatible = "arm,cortex-a55";
- reg = <0>;
- device_type = "cpu";
- #cooling-cells = <2>;
- next-level-cache = <&L3_CA55>;
- enable-method = "psci";
- clocks = <&cpg CPG_CORE R9A07G043_CLK_I>;
- operating-points-v2 = <&cluster0_opp>;
- };
-
- L3_CA55: cache-controller-0 {
- compatible = "cache";
- cache-unified;
- cache-size = <0x40000>;
- };
- };
-
- psci {
- compatible = "arm,psci-1.0", "arm,psci-0.2";
- method = "smc";
- };
-
soc: soc {
compatible = "simple-bus";
- interrupt-parent = <&gic>;
#address-cells = <2>;
#size-cells = <2>;
ranges;
@@ -107,10 +78,10 @@
compatible = "renesas,r9a07g043-ssi",
"renesas,rz-ssi";
reg = <0 0x10049c00 0 0x400>;
- interrupts = <GIC_SPI 326 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 327 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 328 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 329 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <SOC_PERIPHERAL_IRQ(326) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(327) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(328) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(329) IRQ_TYPE_EDGE_RISING>;
interrupt-names = "int_req", "dma_rx", "dma_tx", "dma_rt";
clocks = <&cpg CPG_MOD R9A07G043_SSI0_PCLK2>,
<&cpg CPG_MOD R9A07G043_SSI0_PCLK_SFR>,
@@ -128,10 +99,10 @@
compatible = "renesas,r9a07g043-ssi",
"renesas,rz-ssi";
reg = <0 0x1004a000 0 0x400>;
- interrupts = <GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 331 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 332 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 333 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <SOC_PERIPHERAL_IRQ(330) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(331) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(332) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(333) IRQ_TYPE_EDGE_RISING>;
interrupt-names = "int_req", "dma_rx", "dma_tx", "dma_rt";
clocks = <&cpg CPG_MOD R9A07G043_SSI1_PCLK2>,
<&cpg CPG_MOD R9A07G043_SSI1_PCLK_SFR>,
@@ -149,10 +120,10 @@
compatible = "renesas,r9a07g043-ssi",
"renesas,rz-ssi";
reg = <0 0x1004a400 0 0x400>;
- interrupts = <GIC_SPI 334 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 335 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 336 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 337 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <SOC_PERIPHERAL_IRQ(334) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(335) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(336) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(337) IRQ_TYPE_EDGE_RISING>;
interrupt-names = "int_req", "dma_rx", "dma_tx", "dma_rt";
clocks = <&cpg CPG_MOD R9A07G043_SSI2_PCLK2>,
<&cpg CPG_MOD R9A07G043_SSI2_PCLK_SFR>,
@@ -170,10 +141,10 @@
compatible = "renesas,r9a07g043-ssi",
"renesas,rz-ssi";
reg = <0 0x1004a800 0 0x400>;
- interrupts = <GIC_SPI 338 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 339 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 340 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 341 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <SOC_PERIPHERAL_IRQ(338) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(339) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(340) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(341) IRQ_TYPE_EDGE_RISING>;
interrupt-names = "int_req", "dma_rx", "dma_tx", "dma_rt";
clocks = <&cpg CPG_MOD R9A07G043_SSI3_PCLK2>,
<&cpg CPG_MOD R9A07G043_SSI3_PCLK_SFR>,
@@ -190,9 +161,9 @@
spi0: spi@1004ac00 {
compatible = "renesas,r9a07g043-rspi", "renesas,rspi-rz";
reg = <0 0x1004ac00 0 0x400>;
- interrupts = <GIC_SPI 415 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 413 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 414 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(415) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(413) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(414) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "error", "rx", "tx";
clocks = <&cpg CPG_MOD R9A07G043_RSPI0_CLKB>;
resets = <&cpg R9A07G043_RSPI0_RST>;
@@ -208,9 +179,9 @@
spi1: spi@1004b000 {
compatible = "renesas,r9a07g043-rspi", "renesas,rspi-rz";
reg = <0 0x1004b000 0 0x400>;
- interrupts = <GIC_SPI 418 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 416 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 417 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(418) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(416) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(417) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "error", "rx", "tx";
clocks = <&cpg CPG_MOD R9A07G043_RSPI1_CLKB>;
resets = <&cpg R9A07G043_RSPI1_RST>;
@@ -226,9 +197,9 @@
spi2: spi@1004b400 {
compatible = "renesas,r9a07g043-rspi", "renesas,rspi-rz";
reg = <0 0x1004b400 0 0x400>;
- interrupts = <GIC_SPI 421 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 419 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 420 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(421) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(419) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(420) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "error", "rx", "tx";
clocks = <&cpg CPG_MOD R9A07G043_RSPI2_CLKB>;
resets = <&cpg R9A07G043_RSPI2_RST>;
@@ -245,12 +216,12 @@
compatible = "renesas,scif-r9a07g043",
"renesas,scif-r9a07g044";
reg = <0 0x1004b800 0 0x400>;
- interrupts = <GIC_SPI 380 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 382 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 383 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 381 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 384 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 384 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(380) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(382) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(383) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(381) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(384) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(384) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "eri", "rxi", "txi",
"bri", "dri", "tei";
clocks = <&cpg CPG_MOD R9A07G043_SCIF0_CLK_PCK>;
@@ -264,12 +235,12 @@
compatible = "renesas,scif-r9a07g043",
"renesas,scif-r9a07g044";
reg = <0 0x1004bc00 0 0x400>;
- interrupts = <GIC_SPI 385 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 387 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 388 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 386 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 389 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 389 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(385) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(387) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(388) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(386) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(389) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(389) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "eri", "rxi", "txi",
"bri", "dri", "tei";
clocks = <&cpg CPG_MOD R9A07G043_SCIF1_CLK_PCK>;
@@ -283,12 +254,12 @@
compatible = "renesas,scif-r9a07g043",
"renesas,scif-r9a07g044";
reg = <0 0x1004c000 0 0x400>;
- interrupts = <GIC_SPI 390 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 392 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 393 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 391 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 394 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 394 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(390) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(392) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(393) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(391) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(394) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(394) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "eri", "rxi", "txi",
"bri", "dri", "tei";
clocks = <&cpg CPG_MOD R9A07G043_SCIF2_CLK_PCK>;
@@ -302,12 +273,12 @@
compatible = "renesas,scif-r9a07g043",
"renesas,scif-r9a07g044";
reg = <0 0x1004c400 0 0x400>;
- interrupts = <GIC_SPI 395 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 397 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 398 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 396 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 399 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 399 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(395) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(397) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(398) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(396) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(399) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(399) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "eri", "rxi", "txi",
"bri", "dri", "tei";
clocks = <&cpg CPG_MOD R9A07G043_SCIF3_CLK_PCK>;
@@ -321,12 +292,12 @@
compatible = "renesas,scif-r9a07g043",
"renesas,scif-r9a07g044";
reg = <0 0x1004c800 0 0x400>;
- interrupts = <GIC_SPI 400 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 402 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 403 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 401 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 404 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 404 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(400) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(402) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(403) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(401) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(404) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(404) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "eri", "rxi", "txi",
"bri", "dri", "tei";
clocks = <&cpg CPG_MOD R9A07G043_SCIF4_CLK_PCK>;
@@ -339,10 +310,10 @@
sci0: serial@1004d000 {
compatible = "renesas,r9a07g043-sci", "renesas,sci";
reg = <0 0x1004d000 0 0x400>;
- interrupts = <GIC_SPI 405 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 406 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 407 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 408 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(405) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(406) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(407) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(408) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "eri", "rxi", "txi", "tei";
clocks = <&cpg CPG_MOD R9A07G043_SCI0_CLKP>;
clock-names = "fck";
@@ -354,10 +325,10 @@
sci1: serial@1004d400 {
compatible = "renesas,r9a07g043-sci", "renesas,sci";
reg = <0 0x1004d400 0 0x400>;
- interrupts = <GIC_SPI 409 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 410 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 411 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 412 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(409) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(410) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(411) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(412) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "eri", "rxi", "txi", "tei";
clocks = <&cpg CPG_MOD R9A07G043_SCI1_CLKP>;
clock-names = "fck";
@@ -369,14 +340,14 @@
canfd: can@10050000 {
compatible = "renesas,r9a07g043-canfd", "renesas,rzg2l-canfd";
reg = <0 0x10050000 0 0x8000>;
- interrupts = <GIC_SPI 426 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 427 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 422 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 424 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 428 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 423 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 425 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 429 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(426) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(427) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(422) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(424) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(428) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(423) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(425) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(429) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "g_err", "g_recc",
"ch0_err", "ch0_rec", "ch0_trx",
"ch1_err", "ch1_rec", "ch1_trx";
@@ -405,14 +376,14 @@
#size-cells = <0>;
compatible = "renesas,riic-r9a07g043", "renesas,riic-rz";
reg = <0 0x10058000 0 0x400>;
- interrupts = <GIC_SPI 350 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 348 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 349 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 352 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 353 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 351 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 354 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 355 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(350) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(348) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(349) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(352) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(353) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(351) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(354) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(355) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "tei", "ri", "ti", "spi", "sti",
"naki", "ali", "tmoi";
clocks = <&cpg CPG_MOD R9A07G043_I2C0_PCLK>;
@@ -427,14 +398,14 @@
#size-cells = <0>;
compatible = "renesas,riic-r9a07g043", "renesas,riic-rz";
reg = <0 0x10058400 0 0x400>;
- interrupts = <GIC_SPI 358 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 356 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 357 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 361 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 359 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 362 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 363 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(358) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(356) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(357) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(360) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(361) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(359) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(362) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(363) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "tei", "ri", "ti", "spi", "sti",
"naki", "ali", "tmoi";
clocks = <&cpg CPG_MOD R9A07G043_I2C1_PCLK>;
@@ -449,14 +420,14 @@
#size-cells = <0>;
compatible = "renesas,riic-r9a07g043", "renesas,riic-rz";
reg = <0 0x10058800 0 0x400>;
- interrupts = <GIC_SPI 366 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 364 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 365 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 368 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 369 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 367 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 370 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 371 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(366) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(364) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(365) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(368) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(369) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(367) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(370) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(371) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "tei", "ri", "ti", "spi", "sti",
"naki", "ali", "tmoi";
clocks = <&cpg CPG_MOD R9A07G043_I2C2_PCLK>;
@@ -471,14 +442,14 @@
#size-cells = <0>;
compatible = "renesas,riic-r9a07g043", "renesas,riic-rz";
reg = <0 0x10058c00 0 0x400>;
- interrupts = <GIC_SPI 374 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 372 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 373 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 376 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 377 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 375 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 378 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 379 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(374) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(372) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(373) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(376) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(377) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(375) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(378) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(379) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "tei", "ri", "ti", "spi", "sti",
"naki", "ali", "tmoi";
clocks = <&cpg CPG_MOD R9A07G043_I2C3_PCLK>;
@@ -491,7 +462,7 @@
adc: adc@10059000 {
compatible = "renesas,r9a07g043-adc", "renesas,rzg2l-adc";
reg = <0 0x10059000 0 0x400>;
- interrupts = <GIC_SPI 347 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <SOC_PERIPHERAL_IRQ(347) IRQ_TYPE_EDGE_RISING>;
clocks = <&cpg CPG_MOD R9A07G043_ADC_ADCLK>,
<&cpg CPG_MOD R9A07G043_ADC_PCLK>;
clock-names = "adclk", "pclk";
@@ -551,12 +522,6 @@
sysc: system-controller@11020000 {
compatible = "renesas,r9a07g043-sysc";
reg = <0 0x11020000 0 0x10000>;
- interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "lpm_int", "ca55stbydone_int",
- "cm33stbyr_int", "ca55_deny";
status = "disabled";
};
@@ -578,23 +543,23 @@
"renesas,rz-dmac";
reg = <0 0x11820000 0 0x10000>,
<0 0x11830000 0 0x10000>;
- interrupts = <GIC_SPI 141 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 125 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 126 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 127 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 128 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 129 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 130 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 131 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 132 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 133 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 134 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 135 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 136 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 137 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 138 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 139 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 140 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <SOC_PERIPHERAL_IRQ(141) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(125) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(126) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(127) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(128) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(129) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(130) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(131) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(132) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(133) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(134) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(135) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(136) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(137) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(138) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(139) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(140) IRQ_TYPE_EDGE_RISING>;
interrupt-names = "error",
"ch0", "ch1", "ch2", "ch3",
"ch4", "ch5", "ch6", "ch7",
@@ -609,22 +574,12 @@
dma-channels = <16>;
};
- gic: interrupt-controller@11900000 {
- compatible = "arm,gic-v3";
- #interrupt-cells = <3>;
- #address-cells = <0>;
- interrupt-controller;
- reg = <0x0 0x11900000 0 0x40000>,
- <0x0 0x11940000 0 0x60000>;
- interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>;
- };
-
sdhi0: mmc@11c00000 {
compatible = "renesas,sdhi-r9a07g043",
"renesas,rcar-gen3-sdhi";
reg = <0x0 0x11c00000 0 0x10000>;
- interrupts = <GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(104) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(105) IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD R9A07G043_SDHI0_IMCLK>,
<&cpg CPG_MOD R9A07G043_SDHI0_CLK_HS>,
<&cpg CPG_MOD R9A07G043_SDHI0_IMCLK2>,
@@ -639,8 +594,8 @@
compatible = "renesas,sdhi-r9a07g043",
"renesas,rcar-gen3-sdhi";
reg = <0x0 0x11c10000 0 0x10000>;
- interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 107 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(106) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(107) IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD R9A07G043_SDHI1_IMCLK>,
<&cpg CPG_MOD R9A07G043_SDHI1_CLK_HS>,
<&cpg CPG_MOD R9A07G043_SDHI1_IMCLK2>,
@@ -655,9 +610,9 @@
compatible = "renesas,r9a07g043-gbeth",
"renesas,rzg2l-gbeth";
reg = <0 0x11c20000 0 0x10000>;
- interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(84) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(85) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(86) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "mux", "fil", "arp_ns";
phy-mode = "rgmii";
clocks = <&cpg CPG_MOD R9A07G043_ETH0_CLK_AXI>,
@@ -675,9 +630,9 @@
compatible = "renesas,r9a07g043-gbeth",
"renesas,rzg2l-gbeth";
reg = <0 0x11c30000 0 0x10000>;
- interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 88 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(87) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(88) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(89) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "mux", "fil", "arp_ns";
phy-mode = "rgmii";
clocks = <&cpg CPG_MOD R9A07G043_ETH1_CLK_AXI>,
@@ -705,7 +660,7 @@
ohci0: usb@11c50000 {
compatible = "generic-ohci";
reg = <0 0x11c50000 0 0x100>;
- interrupts = <GIC_SPI 91 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(91) IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD R9A07G043_USB_PCLK>,
<&cpg CPG_MOD R9A07G043_USB_U2H0_HCLK>;
resets = <&phyrst 0>,
@@ -719,7 +674,7 @@
ohci1: usb@11c70000 {
compatible = "generic-ohci";
reg = <0 0x11c70000 0 0x100>;
- interrupts = <GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(96) IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD R9A07G043_USB_PCLK>,
<&cpg CPG_MOD R9A07G043_USB_U2H1_HCLK>;
resets = <&phyrst 1>,
@@ -733,7 +688,7 @@
ehci0: usb@11c50100 {
compatible = "generic-ehci";
reg = <0 0x11c50100 0 0x100>;
- interrupts = <GIC_SPI 92 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(92) IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD R9A07G043_USB_PCLK>,
<&cpg CPG_MOD R9A07G043_USB_U2H0_HCLK>;
resets = <&phyrst 0>,
@@ -748,7 +703,7 @@
ehci1: usb@11c70100 {
compatible = "generic-ehci";
reg = <0 0x11c70100 0 0x100>;
- interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(97) IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD R9A07G043_USB_PCLK>,
<&cpg CPG_MOD R9A07G043_USB_U2H1_HCLK>;
resets = <&phyrst 1>,
@@ -764,7 +719,7 @@
compatible = "renesas,usb2-phy-r9a07g043",
"renesas,rzg2l-usb2-phy";
reg = <0 0x11c50200 0 0x700>;
- interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(94) IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD R9A07G043_USB_PCLK>,
<&cpg CPG_MOD R9A07G043_USB_U2H0_HCLK>;
resets = <&phyrst 0>;
@@ -777,7 +732,7 @@
compatible = "renesas,usb2-phy-r9a07g043",
"renesas,rzg2l-usb2-phy";
reg = <0 0x11c70200 0 0x700>;
- interrupts = <GIC_SPI 99 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(99) IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD R9A07G043_USB_PCLK>,
<&cpg CPG_MOD R9A07G043_USB_U2H1_HCLK>;
resets = <&phyrst 1>;
@@ -790,10 +745,10 @@
compatible = "renesas,usbhs-r9a07g043",
"renesas,rza2-usbhs";
reg = <0 0x11c60000 0 0x10000>;
- interrupts = <GIC_SPI 100 IRQ_TYPE_EDGE_RISING>,
- <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(100) IRQ_TYPE_EDGE_RISING>,
+ <SOC_PERIPHERAL_IRQ(101) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(102) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(103) IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD R9A07G043_USB_PCLK>,
<&cpg CPG_MOD R9A07G043_USB_U2P_EXR_CPUCLK>;
resets = <&phyrst 0>,
@@ -812,34 +767,19 @@
clocks = <&cpg CPG_MOD R9A07G043_WDT0_PCLK>,
<&cpg CPG_MOD R9A07G043_WDT0_CLK>;
clock-names = "pclk", "oscclk";
- interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+ interrupts = <SOC_PERIPHERAL_IRQ(49) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(50) IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "wdt", "perrout";
resets = <&cpg R9A07G043_WDT0_PRESETN>;
power-domains = <&cpg>;
status = "disabled";
};
- wdt2: watchdog@12800400 {
- compatible = "renesas,r9a07g043-wdt",
- "renesas,rzg2l-wdt";
- reg = <0 0x12800400 0 0x400>;
- clocks = <&cpg CPG_MOD R9A07G043_WDT2_PCLK>,
- <&cpg CPG_MOD R9A07G043_WDT2_CLK>;
- clock-names = "pclk", "oscclk";
- interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "wdt", "perrout";
- resets = <&cpg R9A07G043_WDT2_PRESETN>;
- power-domains = <&cpg>;
- status = "disabled";
- };
-
ostm0: timer@12801000 {
compatible = "renesas,r9a07g043-ostm",
"renesas,ostm";
reg = <0x0 0x12801000 0x0 0x400>;
- interrupts = <GIC_SPI 46 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <SOC_PERIPHERAL_IRQ(46) IRQ_TYPE_EDGE_RISING>;
clocks = <&cpg CPG_MOD R9A07G043_OSTM0_PCLK>;
resets = <&cpg R9A07G043_OSTM0_PRESETZ>;
power-domains = <&cpg>;
@@ -850,7 +790,7 @@
compatible = "renesas,r9a07g043-ostm",
"renesas,ostm";
reg = <0x0 0x12801400 0x0 0x400>;
- interrupts = <GIC_SPI 47 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <SOC_PERIPHERAL_IRQ(47) IRQ_TYPE_EDGE_RISING>;
clocks = <&cpg CPG_MOD R9A07G043_OSTM1_PCLK>;
resets = <&cpg R9A07G043_OSTM1_PRESETZ>;
power-domains = <&cpg>;
@@ -861,7 +801,7 @@
compatible = "renesas,r9a07g043-ostm",
"renesas,ostm";
reg = <0x0 0x12801800 0x0 0x400>;
- interrupts = <GIC_SPI 48 IRQ_TYPE_EDGE_RISING>;
+ interrupts = <SOC_PERIPHERAL_IRQ(48) IRQ_TYPE_EDGE_RISING>;
clocks = <&cpg CPG_MOD R9A07G043_OSTM2_PCLK>;
resets = <&cpg R9A07G043_OSTM2_PRESETZ>;
power-domains = <&cpg>;
@@ -899,12 +839,4 @@
};
};
};
-
- timer {
- compatible = "arm,armv8-timer";
- interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
- <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>;
- };
};
diff --git a/arch/arm64/boot/dts/renesas/r9a07g043u.dtsi b/arch/arm64/boot/dts/renesas/r9a07g043u.dtsi
new file mode 100644
index 000000000000..6af5f3bca2d1
--- /dev/null
+++ b/arch/arm64/boot/dts/renesas/r9a07g043u.dtsi
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/*
+ * Device Tree Source for the RZ/G2UL SoC
+ *
+ * Copyright (C) 2022 Renesas Electronics Corp.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#define SOC_PERIPHERAL_IRQ(nr) GIC_SPI nr
+
+#include "r9a07g043.dtsi"
+
+/ {
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu0: cpu@0 {
+ compatible = "arm,cortex-a55";
+ reg = <0>;
+ device_type = "cpu";
+ #cooling-cells = <2>;
+ next-level-cache = <&L3_CA55>;
+ enable-method = "psci";
+ clocks = <&cpg CPG_CORE R9A07G043_CLK_I>;
+ operating-points-v2 = <&cluster0_opp>;
+ };
+
+ L3_CA55: cache-controller-0 {
+ compatible = "cache";
+ cache-unified;
+ cache-size = <0x40000>;
+ cache-level = <3>;
+ };
+ };
+
+ psci {
+ compatible = "arm,psci-1.0", "arm,psci-0.2";
+ method = "smc";
+ };
+
+ timer {
+ compatible = "arm,armv8-timer";
+ interrupts-extended = <&gic GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+ <&gic GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>;
+ };
+};
+
+&soc {
+ interrupt-parent = <&gic>;
+
+ gic: interrupt-controller@11900000 {
+ compatible = "arm,gic-v3";
+ #interrupt-cells = <3>;
+ #address-cells = <0>;
+ interrupt-controller;
+ reg = <0x0 0x11900000 0 0x40000>,
+ <0x0 0x11940000 0 0x60000>;
+ interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>;
+ };
+};
+
+&sysc {
+ interrupts = <SOC_PERIPHERAL_IRQ(42) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(43) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(44) IRQ_TYPE_LEVEL_HIGH>,
+ <SOC_PERIPHERAL_IRQ(45) IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "lpm_int", "ca55stbydone_int",
+ "cm33stbyr_int", "ca55_deny";
+};
diff --git a/arch/arm64/boot/dts/renesas/r9a07g043u11-smarc.dts b/arch/arm64/boot/dts/renesas/r9a07g043u11-smarc.dts
index 059885a01ede..01483b4302c2 100644
--- a/arch/arm64/boot/dts/renesas/r9a07g043u11-smarc.dts
+++ b/arch/arm64/boot/dts/renesas/r9a07g043u11-smarc.dts
@@ -17,7 +17,7 @@
#define SW_SW0_DEV_SEL 1
#define SW_ET0_EN_N 1
-#include "r9a07g043.dtsi"
+#include "r9a07g043u.dtsi"
#include "rzg2ul-smarc-som.dtsi"
#include "rzg2ul-smarc.dtsi"
diff --git a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
index 2283d4fb8736..487536696d90 100644
--- a/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a07g044.dtsi
@@ -109,6 +109,7 @@
compatible = "cache";
cache-unified;
cache-size = <0x40000>;
+ cache-level = <3>;
};
};
@@ -644,7 +645,6 @@
reg = <0 0x11030000 0 0x10000>;
gpio-controller;
#gpio-cells = <2>;
- #address-cells = <2>;
#interrupt-cells = <2>;
interrupt-parent = <&irqc>;
interrupt-controller;
@@ -994,21 +994,6 @@
status = "disabled";
};
- wdt2: watchdog@12800400 {
- compatible = "renesas,r9a07g044-wdt",
- "renesas,rzg2l-wdt";
- reg = <0 0x12800400 0 0x400>;
- clocks = <&cpg CPG_MOD R9A07G044_WDT2_PCLK>,
- <&cpg CPG_MOD R9A07G044_WDT2_CLK>;
- clock-names = "pclk", "oscclk";
- interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "wdt", "perrout";
- resets = <&cpg R9A07G044_WDT2_PRESETN>;
- power-domains = <&cpg>;
- status = "disabled";
- };
-
ostm0: timer@12801000 {
compatible = "renesas,r9a07g044-ostm",
"renesas,ostm";
diff --git a/arch/arm64/boot/dts/renesas/r9a07g044c2-smarc.dts b/arch/arm64/boot/dts/renesas/r9a07g044c2-smarc.dts
index fc34058002e2..f67a6f125d9c 100644
--- a/arch/arm64/boot/dts/renesas/r9a07g044c2-smarc.dts
+++ b/arch/arm64/boot/dts/renesas/r9a07g044c2-smarc.dts
@@ -6,7 +6,37 @@
*/
/dts-v1/;
+
+/*
+ * DIP-Switch SW1 setting on SoM
+ * 1 : High; 0: Low
+ * SW1-2 : SW_SD0_DEV_SEL (1: eMMC; 0: uSD)
+ * SW1-3 : SW_SCIF_CAN (1: CAN1; 0: SCIF1)
+ * SW1-4 : SW_RSPI_CAN (1: CAN1; 0: RSPI1)
+ * SW1-5 : SW_I2S0_I2S1 (1: I2S2 (HDMI audio); 0: I2S0)
+ * Please change below macros according to SW1 setting
+ */
+
+#define SW_SD0_DEV_SEL 1
+
+#define SW_SCIF_CAN 0
+#if (SW_SCIF_CAN)
+/* Due to HW routing, SW_RSPI_CAN is always 0 when SW_SCIF_CAN is set to 1 */
+#define SW_RSPI_CAN 0
+#else
+/* Please set SW_RSPI_CAN. Default value is 1 */
+#define SW_RSPI_CAN 1
+#endif
+
+#if (SW_SCIF_CAN && SW_RSPI_CAN)
+#error "Can not set 1 to both SW_SCIF_CAN and SW_RSPI_CAN due to HW routing"
+#endif
+
+/* comment the #define statement to disable SCIF1 (SER0) on PMOD1 (CN7) */
+#define PMOD1_SER0 1
+
#include "r9a07g044c2.dtsi"
+#include "rzg2lc-smarc-som.dtsi"
#include "rzg2lc-smarc.dtsi"
/ {
diff --git a/arch/arm64/boot/dts/renesas/r9a07g054.dtsi b/arch/arm64/boot/dts/renesas/r9a07g054.dtsi
index 358d4c34465f..304ade54425b 100644
--- a/arch/arm64/boot/dts/renesas/r9a07g054.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a07g054.dtsi
@@ -109,6 +109,7 @@
compatible = "cache";
cache-unified;
cache-size = <0x40000>;
+ cache-level = <3>;
};
};
@@ -650,7 +651,6 @@
reg = <0 0x11030000 0 0x10000>;
gpio-controller;
#gpio-cells = <2>;
- #address-cells = <2>;
#interrupt-cells = <2>;
interrupt-parent = <&irqc>;
interrupt-controller;
@@ -1000,21 +1000,6 @@
status = "disabled";
};
- wdt2: watchdog@12800400 {
- compatible = "renesas,r9a07g054-wdt",
- "renesas,rzg2l-wdt";
- reg = <0 0x12800400 0 0x400>;
- clocks = <&cpg CPG_MOD R9A07G054_WDT2_PCLK>,
- <&cpg CPG_MOD R9A07G054_WDT2_CLK>;
- clock-names = "pclk", "oscclk";
- interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
- <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "wdt", "perrout";
- resets = <&cpg R9A07G054_WDT2_PRESETN>;
- power-domains = <&cpg>;
- status = "disabled";
- };
-
ostm0: timer@12801000 {
compatible = "renesas,r9a07g054-ostm",
"renesas,ostm";
diff --git a/arch/arm64/boot/dts/renesas/r9a09g011-v2mevk2.dts b/arch/arm64/boot/dts/renesas/r9a09g011-v2mevk2.dts
index 5c15d73d059f..11e1d51c7c0e 100644
--- a/arch/arm64/boot/dts/renesas/r9a09g011-v2mevk2.dts
+++ b/arch/arm64/boot/dts/renesas/r9a09g011-v2mevk2.dts
@@ -83,3 +83,7 @@
&uart0 {
status = "okay";
};
+
+&wdt0 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/renesas/r9a09g011.dtsi b/arch/arm64/boot/dts/renesas/r9a09g011.dtsi
index fb1a97202c38..0373ec409d54 100644
--- a/arch/arm64/boot/dts/renesas/r9a09g011.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a09g011.dtsi
@@ -37,8 +37,15 @@
compatible = "arm,cortex-a53";
reg = <0>;
device_type = "cpu";
+ next-level-cache = <&L2_CA53>;
clocks = <&cpg CPG_MOD R9A09G011_CA53_CLK>;
};
+
+ L2_CA53: cache-controller-0 {
+ compatible = "cache";
+ cache-unified;
+ cache-level = <2>;
+ };
};
soc: soc {
@@ -48,7 +55,7 @@
#size-cells = <2>;
ranges;
- gic: interrupt-controller@82000000 {
+ gic: interrupt-controller@82010000 {
compatible = "arm,gic-400";
#interrupt-cells = <3>;
#address-cells = <0>;
@@ -123,10 +130,15 @@
#power-domain-cells = <0>;
};
+ sys: system-controller@a3f03000 {
+ compatible = "renesas,r9a09g011-sys";
+ reg = <0 0xa3f03000 0 0x400>;
+ };
+
i2c0: i2c@a4030000 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "renesas,i2c-r9a09g011", "renesas,rzv2m-i2c";
+ compatible = "renesas,r9a09g011-i2c", "renesas,rzv2m-i2c";
reg = <0 0xa4030000 0 0x80>;
interrupts = <GIC_SPI 232 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 236 IRQ_TYPE_EDGE_RISING>;
@@ -140,7 +152,7 @@
i2c2: i2c@a4030100 {
#address-cells = <1>;
#size-cells = <0>;
- compatible = "renesas,i2c-r9a09g011", "renesas,rzv2m-i2c";
+ compatible = "renesas,r9a09g011-i2c", "renesas,rzv2m-i2c";
reg = <0 0xa4030100 0 0x80>;
interrupts = <GIC_SPI 234 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 238 IRQ_TYPE_EDGE_RISING>;
@@ -161,6 +173,19 @@
status = "disabled";
};
+ wdt0: watchdog@a4050000 {
+ compatible = "renesas,r9a09g011-wdt",
+ "renesas,rzv2m-wdt";
+ reg = <0 0xa4050000 0 0x80>;
+ clocks = <&cpg CPG_MOD R9A09G011_WDT0_PCLK>,
+ <&cpg CPG_MOD R9A09G011_WDT0_CLK>;
+ clock-names = "pclk", "oscclk";
+ interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+ resets = <&cpg R9A09G011_WDT0_PRESETN>;
+ power-domains = <&cpg>;
+ status = "disabled";
+ };
+
pinctrl: pinctrl@b6250000 {
compatible = "renesas,r9a09g011-pinctrl";
reg = <0 0xb6250000 0 0x800>;
diff --git a/arch/arm64/boot/dts/renesas/rzg2l-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg2l-smarc-som.dtsi
index c4faff092380..fbbb4f03440b 100644
--- a/arch/arm64/boot/dts/renesas/rzg2l-smarc-som.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg2l-smarc-som.dtsi
@@ -351,8 +351,3 @@
status = "okay";
timeout-sec = <60>;
};
-
-&wdt2 {
- status = "okay";
- timeout-sec = <60>;
-};
diff --git a/arch/arm64/boot/dts/renesas/rzg2lc-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg2lc-smarc-som.dtsi
index 78e6e2376b01..8a0d56872de7 100644
--- a/arch/arm64/boot/dts/renesas/rzg2lc-smarc-som.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg2lc-smarc-som.dtsi
@@ -276,8 +276,3 @@
status = "okay";
timeout-sec = <60>;
};
-
-&wdt2 {
- status = "okay";
- timeout-sec = <60>;
-};
diff --git a/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi b/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi
index 6be25a8a28db..b6bd27196d88 100644
--- a/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg2lc-smarc.dtsi
@@ -8,37 +8,9 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/rzg2l-pinctrl.h>
-/*
- * DIP-Switch SW1 setting on SoM
- * 1 : High; 0: Low
- * SW1-2 : SW_SD0_DEV_SEL (1: eMMC; 0: uSD)
- * SW1-3 : SW_SCIF_CAN (1: CAN1; 0: SCIF1)
- * SW1-4 : SW_RSPI_CAN (1: CAN1; 0: RSPI1)
- * SW1-5 : SW_I2S0_I2S1 (1: I2S2 (HDMI audio); 0: I2S0)
- * Please change below macros according to SW1 setting
- */
-
-#define SW_SD0_DEV_SEL 1
-
-#define SW_SCIF_CAN 0
-#if (SW_SCIF_CAN)
-/* Due to HW routing, SW_RSPI_CAN is always 0 when SW_SCIF_CAN is set to 1 */
-#define SW_RSPI_CAN 0
-#else
-/* Please set SW_RSPI_CAN. Default value is 1 */
-#define SW_RSPI_CAN 1
-#endif
-
-#if (SW_SCIF_CAN && SW_RSPI_CAN)
-#error "Can not set 1 to both SW_SCIF_CAN and SW_RSPI_CAN due to HW routing"
-#endif
-
-#include "rzg2lc-smarc-som.dtsi"
#include "rzg2lc-smarc-pinfunction.dtsi"
#include "rz-smarc-common.dtsi"
-/* comment the #define statement to disable SCIF1 (SER0) on PMOD1 (CN7) */
-#define PMOD1_SER0 1
/ {
aliases {
diff --git a/arch/arm64/boot/dts/renesas/rzg2ul-smarc-pinfunction.dtsi b/arch/arm64/boot/dts/renesas/rzg2ul-smarc-pinfunction.dtsi
index bd8bc858c28c..58923dc83faa 100644
--- a/arch/arm64/boot/dts/renesas/rzg2ul-smarc-pinfunction.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg2ul-smarc-pinfunction.dtsi
@@ -99,6 +99,13 @@
input-enable;
};
+ spi1_pins: spi1 {
+ pinmux = <RZG2L_PORT_PINMUX(4, 0, 2)>, /* CK */
+ <RZG2L_PORT_PINMUX(4, 1, 2)>, /* MOSI */
+ <RZG2L_PORT_PINMUX(4, 2, 2)>, /* MISO */
+ <RZG2L_PORT_PINMUX(4, 3, 2)>; /* SSL */
+ };
+
ssi1_pins: ssi1 {
pinmux = <RZG2L_PORT_PINMUX(3, 0, 2)>, /* BCK */
<RZG2L_PORT_PINMUX(3, 1, 2)>, /* RCK */
diff --git a/arch/arm64/boot/dts/renesas/rzg2ul-smarc-som.dtsi b/arch/arm64/boot/dts/renesas/rzg2ul-smarc-som.dtsi
index 2a0feb53f0dc..931efc07d6fb 100644
--- a/arch/arm64/boot/dts/renesas/rzg2ul-smarc-som.dtsi
+++ b/arch/arm64/boot/dts/renesas/rzg2ul-smarc-som.dtsi
@@ -221,13 +221,6 @@
pinmux = <RZG2L_PORT_PINMUX(0, 0, 1)>; /* SD0_CD */
};
};
-
- spi1_pins: rspi1 {
- pinmux = <RZG2L_PORT_PINMUX(4, 0, 2)>, /* CK */
- <RZG2L_PORT_PINMUX(4, 1, 2)>, /* MOSI */
- <RZG2L_PORT_PINMUX(4, 2, 2)>, /* MISO */
- <RZG2L_PORT_PINMUX(4, 3, 2)>; /* SSL */
- };
};
#if (SW_SW0_DEV_SEL)
diff --git a/arch/arm64/boot/dts/renesas/salvator-panel-aa104xd12.dts b/arch/arm64/boot/dts/renesas/salvator-panel-aa104xd12.dtso
index c83a30adc6ad..c83a30adc6ad 100644
--- a/arch/arm64/boot/dts/renesas/salvator-panel-aa104xd12.dts
+++ b/arch/arm64/boot/dts/renesas/salvator-panel-aa104xd12.dtso
diff --git a/arch/arm64/boot/dts/rockchip/Makefile b/arch/arm64/boot/dts/rockchip/Makefile
index 8c15593c0ca4..0a76a2ebb5f6 100644
--- a/arch/arm64/boot/dts/rockchip/Makefile
+++ b/arch/arm64/boot/dts/rockchip/Makefile
@@ -3,11 +3,15 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-evb.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-engicam-px30-core-ctouch2.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-engicam-px30-core-ctouch2-of10.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-engicam-px30-core-edimm2.2.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += px30-ringneck-haikou.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3308-evb.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3308-roc-cc.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3308-rock-pi-s.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3318-a95x-z2.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-anbernic-rg351m.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-odroid-go2.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-odroid-go2-v11.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3326-odroid-go3.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-a1.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-nanopi-r2s.dtb
@@ -62,13 +66,19 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sapphire.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-sapphire-excavator.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399pro-rock-pi-n10.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg353p.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg353v.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg353vs.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-anbernic-rg503.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-pinenote-v1.1.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-pinenote-v1.2.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-quartz64-a.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-quartz64-b.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-roc-pc.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-soquartz-blade.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-soquartz-cm4.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-soquartz-model-a.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3566-box-demo.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-bpi-r2-pro.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-evb1-v10.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-odroid-m1.dtb
dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3568-rock-3a.dtb
diff --git a/arch/arm64/boot/dts/rockchip/px30-ringneck-haikou.dts b/arch/arm64/boot/dts/rockchip/px30-ringneck-haikou.dts
new file mode 100644
index 000000000000..08a3ad3e7ae9
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/px30-ringneck-haikou.dts
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2022 Theobroma Systems Design und Consulting GmbH
+ */
+
+/dts-v1/;
+#include "px30-ringneck.dtsi"
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+
+/ {
+ model = "Theobroma Systems PX30-uQ7 SoM on Haikou devkit";
+ compatible = "tsd,px30-ringneck-haikou", "rockchip,px30";
+
+ aliases {
+ mmc2 = &sdmmc;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-0 = <&haikou_keys_pin>;
+ pinctrl-names = "default";
+
+ button-batlow-n {
+ label = "BATLOW#";
+ linux,code = <KEY_BATTERY>;
+ gpios = <&gpio3 RK_PA7 GPIO_ACTIVE_LOW>;
+ };
+
+ button-slp-btn-n {
+ label = "SLP_BTN#";
+ linux,code = <KEY_SLEEP>;
+ gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>;
+ };
+
+ button-wake-n {
+ label = "WAKE#";
+ linux,code = <KEY_WAKEUP>;
+ gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>;
+ wakeup-source;
+ };
+
+ switch-lid-btn-n {
+ label = "LID_BTN#";
+ linux,code = <SW_LID>;
+ linux,input-type = <EV_SW>;
+ gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ leds {
+ pinctrl-0 = <&module_led_pin>, <&sd_card_led_pin>;
+
+ sd_card_led: led-1 {
+ gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "mmc2";
+ function = LED_FUNCTION_SD;
+ color = <LED_COLOR_ID_BLUE>;
+ };
+ };
+
+ i2s0-sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,name = "Haikou,I2S-codec";
+ simple-audio-card,mclk-fs = <512>;
+
+ simple-audio-card,codec {
+ clocks = <&sgtl5000_clk>;
+ sound-dai = <&sgtl5000>;
+ };
+
+ simple-audio-card,cpu {
+ bitclock-master;
+ frame-master;
+ sound-dai = <&i2s0_8ch>;
+ };
+ };
+
+ sgtl5000_clk: sgtl5000-oscillator {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <24576000>;
+ };
+
+ dc_12v: dc-12v-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "dc_12v";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ };
+
+ vcc3v3_baseboard: vcc3v3-baseboard-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_baseboard";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&dc_12v>;
+ };
+
+ vcc5v0_baseboard: vcc5v0-baseboard-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_baseboard";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&dc_12v>;
+ };
+
+ vdda_codec: vdda-codec-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vdda_codec";
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc5v0_baseboard>;
+ };
+
+ vddd_codec: vddd-codec-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vddd_codec";
+ regulator-boot-on;
+ regulator-min-microvolt = <1600000>;
+ regulator-max-microvolt = <1600000>;
+ vin-supply = <&vcc5v0_baseboard>;
+ };
+};
+
+&i2c2 {
+ status = "okay";
+ clock-frequency = <400000>;
+
+ sgtl5000: codec@a {
+ compatible = "fsl,sgtl5000";
+ reg = <0x0a>;
+ clocks = <&sgtl5000_clk>;
+ #sound-dai-cells = <0>;
+ VDDA-supply = <&vdda_codec>;
+ VDDIO-supply = <&vcc3v3_baseboard>;
+ VDDD-supply = <&vddd_codec>;
+ };
+};
+
+&i2c3 {
+ eeprom@50 {
+ reg = <0x50>;
+ compatible = "atmel,24c01";
+ pagesize = <8>;
+ size = <128>;
+ vcc-supply = <&vcc3v3_baseboard>;
+ };
+};
+
+&i2s0_8ch {
+ status = "okay";
+};
+
+&gmac {
+ status = "okay";
+};
+
+&pinctrl {
+ haikou {
+ haikou_keys_pin: haikou-keys-pin {
+ rockchip,pins =
+ /* WAKE# */
+ <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>,
+ /* SLP_BTN# */
+ <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>,
+ /* LID_BTN */
+ <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>,
+ /* BATLOW# */
+ <3 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>,
+ /* BIOS_DISABLE# */
+ <2 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ leds {
+ sd_card_led_pin: sd-card-led-pin {
+ rockchip,pins =
+ <3 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&pwm0 {
+ status = "okay";
+};
+
+&sdmmc {
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ bus-width = <4>;
+ cap-mmc-highspeed;
+ cap-sd-highspeed;
+ cd-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ vmmc-supply = <&vcc3v3_baseboard>;
+ status = "okay";
+};
+
+&spi1 {
+ status = "okay";
+};
+
+&u2phy_otg {
+ status = "okay";
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart5 {
+ pinctrl-0 = <&uart5_xfer>;
+ status = "okay";
+};
+
+&usb20_otg {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi b/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi
new file mode 100644
index 000000000000..12397755830b
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi
@@ -0,0 +1,382 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2022 Theobroma Systems Design und Consulting GmbH
+ */
+
+/dts-v1/;
+#include "px30.dtsi"
+#include <dt-bindings/leds/common.h>
+
+/ {
+ aliases {
+ mmc0 = &emmc;
+ mmc1 = &sdio;
+ rtc0 = &rtc_twi;
+ rtc1 = &rk809;
+ };
+
+ emmc_pwrseq: emmc-pwrseq {
+ compatible = "mmc-pwrseq-emmc";
+ pinctrl-0 = <&emmc_reset>;
+ pinctrl-names = "default";
+ reset-gpios = <&gpio1 RK_PB3 GPIO_ACTIVE_HIGH>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&module_led_pin>;
+ status = "okay";
+
+ module_led: led-0 {
+ gpios = <&gpio1 RK_PB0 GPIO_ACTIVE_HIGH>;
+ function = LED_FUNCTION_HEARTBEAT;
+ linux,default-trigger = "heartbeat";
+ color = <LED_COLOR_ID_AMBER>;
+ };
+ };
+
+ vcc5v0_sys: vccsys-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu1 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu2 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu3 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&emmc {
+ bus-width = <8>;
+ cap-mmc-highspeed;
+ mmc-hs200-1_8v;
+ supports-emmc;
+ mmc-pwrseq = <&emmc_pwrseq>;
+ non-removable;
+ vmmc-supply = <&vcc_3v3>;
+ vqmmc-supply = <&vcc_emmc>;
+
+ status = "okay";
+};
+
+/* On-module TI DP83825I PHY but no connector, enable in carrierboard */
+&gmac {
+ snps,reset-gpio = <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>;
+ snps,reset-active-low;
+ snps,reset-delays-us = <0 50000 50000>;
+ phy-supply = <&vcc_3v3>;
+ clock_in_out = "output";
+};
+
+&gpio2 {
+ /*
+ * The Qseven BIOS_DISABLE signal on the PX30-µQ7 keeps the on-module
+ * eMMC powered-down initially (in fact it keeps the reset signal
+ * asserted). BIOS_DISABLE_OVERRIDE pin allows to re-enable eMMC after
+ * the SPL has been booted from SD Card.
+ */
+ bios-disable-override-hog {
+ gpios = <RK_PB5 GPIO_ACTIVE_LOW>;
+ output-high;
+ line-name = "bios_disable_override";
+ gpio-hog;
+ };
+
+ /*
+ * The BIOS_DISABLE hog is a feedback pin for the actual status of the
+ * signal, ignoring the BIOS_DISABLE_OVERRIDE logic. This usually
+ * represents the state of a switch on the baseboard.
+ */
+ bios-disable-n-hog {
+ gpios = <RK_PC2 GPIO_ACTIVE_LOW>;
+ line-name = "bios_disable";
+ input;
+ gpio-hog;
+ };
+};
+
+&gpu {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ rk809: pmic@20 {
+ compatible = "rockchip,rk809";
+ reg = <0x20>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <7 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-0 = <&pmic_int>;
+ pinctrl-names = "default";
+ #clock-cells = <0>;
+ clock-output-names = "xin32k";
+ rockchip,system-power-controller;
+ wakeup-source;
+
+ vcc1-supply = <&vcc5v0_sys>;
+ vcc2-supply = <&vcc5v0_sys>;
+ vcc3-supply = <&vcc5v0_sys>;
+ vcc4-supply = <&vcc5v0_sys>;
+ vcc5-supply = <&vcc_3v3>;
+ vcc6-supply = <&vcc_3v3>;
+ vcc7-supply = <&vcc_3v3>;
+ vcc9-supply = <&vcc5v0_sys>;
+
+ regulators {
+ vdd_log: DCDC_REG1 {
+ regulator-name = "vdd_log";
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <6001>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <950000>;
+ };
+ };
+
+ vdd_arm: DCDC_REG2 {
+ regulator-name = "vdd_arm";
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <6001>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <950000>;
+ };
+ };
+
+ vcc_ddr: DCDC_REG3 {
+ regulator-name = "vcc_ddr";
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc_3v0_1v8: vcc_emmc: DCDC_REG4 {
+ regulator-name = "vcc_3v0_1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3000000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3000000>;
+ };
+ };
+
+ vcc_3v3: DCDC_REG5 {
+ regulator-name = "vcc_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vcc_1v8: LDO_REG2 {
+ regulator-name = "vcc_1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vcc_1v0: LDO_REG3 {
+ regulator-name = "vcc_1v0";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1000000>;
+ };
+ };
+
+ vccio_sd: LDO_REG5 {
+ regulator-name = "vccio_sd";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vcc_lcd: LDO_REG7 {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-name = "vcc_lcd";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <1000000>;
+ };
+ };
+
+ vcc_1v8_lcd: LDO_REG8 {
+ regulator-name = "vcc_1v8_lcd";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vcca_1v8: LDO_REG9 {
+ regulator-name = "vcca_1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+ };
+ };
+};
+
+&i2c1 {
+ status = "okay";
+
+ /* SE05x is limited to Fast Mode */
+ clock-frequency = <400000>;
+
+ fan: fan@18 {
+ compatible = "ti,amc6821";
+ reg = <0x18>;
+ #cooling-cells = <2>;
+ };
+
+ rtc_twi: rtc@6f {
+ compatible = "isil,isl1208";
+ reg = <0x6f>;
+ };
+};
+
+&i2c3 {
+ status = "okay";
+};
+
+&i2s0_8ch {
+ rockchip,trcm-sync-tx-only;
+
+ pinctrl-0 = <&i2s0_8ch_sclktx &i2s0_8ch_lrcktx
+ &i2s0_8ch_sdo0 &i2s0_8ch_sdi0>;
+};
+
+&io_domains {
+ vccio1-supply = <&vcc_3v3>;
+ vccio2-supply = <&vccio_sd>;
+ vccio3-supply = <&vcc_3v3>;
+ vccio4-supply = <&vcc_3v3>;
+ vccio5-supply = <&vcc_3v3>;
+ vccio6-supply = <&vcc_emmc>;
+ vccio-oscgpi-supply = <&vcc_3v3>;
+
+ status = "okay";
+};
+
+&pinctrl {
+ emmc {
+ emmc_reset: emmc-reset {
+ rockchip,pins = <1 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ leds {
+ module_led_pin: module-led-pin {
+ rockchip,pins = <1 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pmic {
+ pmic_int: pmic-int {
+ rockchip,pins =
+ <0 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+};
+
+&saradc {
+ vref-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&sdmmc {
+ vqmmc-supply = <&vccio_sd>;
+};
+
+&tsadc {
+ status = "okay";
+};
+
+&u2phy {
+ status = "okay";
+};
+
+&u2phy_host {
+ status = "okay";
+};
+
+/* Mule UCAN */
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+&wdt {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3308.dtsi b/arch/arm64/boot/dts/rockchip/rk3308.dtsi
index 2dfa67f1cd67..dd228a256a32 100644
--- a/arch/arm64/boot/dts/rockchip/rk3308.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3308.dtsi
@@ -96,6 +96,7 @@
l2: l2-cache {
compatible = "cache";
+ cache-level = <2>;
};
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3326-anbernic-rg351m.dts b/arch/arm64/boot/dts/rockchip/rk3326-anbernic-rg351m.dts
new file mode 100644
index 000000000000..61b31688b469
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3326-anbernic-rg351m.dts
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Hardkernel Co., Ltd
+ * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH
+ * Copyright (c) 2022 Maya Matuszczyk <maccraft123mc@gmail.com>
+ */
+
+/dts-v1/;
+#include "rk3326-odroid-go.dtsi"
+
+/ {
+ model = "Anbernic RG351M";
+ compatible = "anbernic,rg351m", "rockchip,rk3326";
+
+ vibrator {
+ compatible = "pwm-vibrator";
+ pwms = <&pwm0 0 1000000 0>;
+ pwm-names = "enable";
+ };
+};
+
+/delete-node/ &builtin_gamepad;
+/delete-node/ &vcc_host; /* conflicts with pwm vibration motor */
+
+&internal_display {
+ compatible = "elida,kd35t133";
+};
+
+&pwm0 {
+ status = "okay";
+};
+
+/delete-node/ &rk817_charger;
diff --git a/arch/arm64/boot/dts/rockchip/rk3326-odroid-go.dtsi b/arch/arm64/boot/dts/rockchip/rk3326-odroid-go.dtsi
new file mode 100644
index 000000000000..fbc6bfbaa5c1
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3326-odroid-go.dtsi
@@ -0,0 +1,600 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Hardkernel Co., Ltd
+ * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH
+ * Copyright (c) 2022 Maya Matuszczyk <maccraft123mc@gmail.com>
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include "rk3326.dtsi"
+
+/ {
+ aliases {
+ mmc0 = &sdmmc;
+ };
+
+ chosen {
+ stdout-path = "serial2:115200n8";
+ };
+
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ power-supply = <&vcc_bl>;
+ pwms = <&pwm1 0 25000 0>;
+ };
+
+ builtin_gamepad: gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&btn_pins>;
+
+ button-sw1 {
+ gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>;
+ label = "DPAD-UP";
+ linux,code = <BTN_DPAD_UP>;
+ };
+ button-sw2 {
+ gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>;
+ label = "DPAD-DOWN";
+ linux,code = <BTN_DPAD_DOWN>;
+ };
+ button-sw3 {
+ gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>;
+ label = "DPAD-LEFT";
+ linux,code = <BTN_DPAD_LEFT>;
+ };
+ button-sw4 {
+ gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>;
+ label = "DPAD-RIGHT";
+ linux,code = <BTN_DPAD_RIGHT>;
+ };
+ button-sw5 {
+ gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>;
+ label = "BTN-A";
+ linux,code = <BTN_EAST>;
+ };
+ button-sw6 {
+ gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>;
+ label = "BTN-B";
+ linux,code = <BTN_SOUTH>;
+ };
+ button-sw7 {
+ gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>;
+ label = "BTN-Y";
+ linux,code = <BTN_WEST>;
+ };
+ button-sw8 {
+ gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>;
+ label = "BTN-X";
+ linux,code = <BTN_NORTH>;
+ };
+ btn_f1: button-sw9 {
+ gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>;
+ label = "F1";
+ linux,code = <BTN_TRIGGER_HAPPY1>;
+ };
+ btn_f2: button-sw10 {
+ gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>;
+ label = "F2";
+ linux,code = <BTN_TRIGGER_HAPPY2>;
+ };
+ btn_f3: button-sw11 {
+ gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>;
+ label = "F3";
+ linux,code = <BTN_TRIGGER_HAPPY3>;
+ };
+ btn_f4: button-sw12 {
+ gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>;
+ label = "F4";
+ linux,code = <BTN_TRIGGER_HAPPY4>;
+ };
+ btn_f5: button-sw13 {
+ gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>;
+ label = "F5";
+ linux,code = <BTN_TRIGGER_HAPPY5>;
+ };
+ btn_f6: button-sw14 {
+ gpios = <&gpio2 RK_PA5 GPIO_ACTIVE_LOW>;
+ label = "F6";
+ linux,code = <BTN_TRIGGER_HAPPY6>;
+ };
+ button-sw15 {
+ gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>;
+ label = "TOP-LEFT";
+ linux,code = <BTN_TL>;
+ };
+ button-sw16 {
+ gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>;
+ label = "TOP-RIGHT";
+ linux,code = <BTN_TR>;
+ };
+ };
+
+ leds: gpio-leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&blue_led_pin>;
+
+ blue_led: led-0 {
+ label = "blue:heartbeat";
+ gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>;
+ linux,default-trigger = "heartbeat";
+ };
+ };
+
+ rk817-sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "Analog";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>;
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,widgets =
+ "Microphone", "Mic Jack",
+ "Headphone", "Headphones",
+ "Speaker", "Speaker";
+ simple-audio-card,routing =
+ "MICL", "Mic Jack",
+ "Headphones", "HPOL",
+ "Headphones", "HPOR",
+ "Speaker", "SPKO";
+
+ simple-audio-card,codec {
+ sound-dai = <&rk817>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s1_2ch>;
+ };
+ };
+
+ vccsys: vccsys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v8_sys";
+ regulator-always-on;
+ regulator-min-microvolt = <3800000>;
+ regulator-max-microvolt = <3800000>;
+ };
+
+ vcc_host: vcc_host {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_host";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+
+ gpio = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>;
+ enable-active-high;
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <&usb_midu>;
+ };
+};
+
+&cpu0 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu1 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu2 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cpu3 {
+ cpu-supply = <&vdd_arm>;
+};
+
+&cru {
+ assigned-clocks = <&cru PLL_NPLL>,
+ <&cru ACLK_BUS_PRE>, <&cru ACLK_PERI_PRE>,
+ <&cru HCLK_BUS_PRE>, <&cru HCLK_PERI_PRE>,
+ <&cru PCLK_BUS_PRE>, <&cru SCLK_GPU>,
+ <&cru PLL_CPLL>;
+
+ assigned-clock-rates = <1188000000>,
+ <200000000>, <200000000>,
+ <150000000>, <150000000>,
+ <100000000>, <200000000>,
+ <17000000>;
+};
+
+&display_subsystem {
+ status = "okay";
+};
+
+&dsi {
+ status = "okay";
+
+ ports {
+ mipi_out: port@1 {
+ reg = <1>;
+
+ mipi_out_panel: endpoint {
+ remote-endpoint = <&mipi_in_panel>;
+ };
+ };
+ };
+
+ internal_display: panel@0 {
+ reg = <0>;
+ backlight = <&backlight>;
+ iovcc-supply = <&vcc_lcd>;
+ reset-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_LOW>;
+ rotation = <270>;
+ vdd-supply = <&vcc_lcd>;
+
+ port {
+ mipi_in_panel: endpoint {
+ remote-endpoint = <&mipi_out_panel>;
+ };
+ };
+ };
+};
+
+&dsi_dphy {
+ status = "okay";
+};
+
+&gpu {
+ mali-supply = <&vdd_logic>;
+ status = "okay";
+};
+
+&i2c0 {
+ clock-frequency = <400000>;
+ i2c-scl-falling-time-ns = <16>;
+ i2c-scl-rising-time-ns = <280>;
+ status = "okay";
+
+ rk817: pmic@20 {
+ compatible = "rockchip,rk817";
+ reg = <0x20>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PB2 IRQ_TYPE_LEVEL_LOW>;
+ clock-output-names = "rk808-clkout1", "xin32k";
+ clock-names = "mclk";
+ clocks = <&cru SCLK_I2S1_OUT>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_int>, <&i2s1_2ch_mclk>;
+ wakeup-source;
+ #clock-cells = <1>;
+ #sound-dai-cells = <0>;
+
+ vcc1-supply = <&vccsys>;
+ vcc2-supply = <&vccsys>;
+ vcc3-supply = <&vccsys>;
+ vcc4-supply = <&vccsys>;
+ vcc5-supply = <&vccsys>;
+ vcc6-supply = <&vccsys>;
+ vcc7-supply = <&vccsys>;
+ vcc8-supply = <&vccsys>;
+
+ regulators {
+ vdd_logic: DCDC_REG1 {
+ regulator-name = "vdd_logic";
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1150000>;
+ regulator-ramp-delay = <6001>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <950000>;
+ };
+ };
+
+ vdd_arm: DCDC_REG2 {
+ regulator-name = "vdd_arm";
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <6001>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <950000>;
+ };
+ };
+
+ vcc_ddr: DCDC_REG3 {
+ regulator-name = "vcc_ddr";
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vcc_3v3: DCDC_REG4 {
+ regulator-name = "vcc_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vcc_1v8: LDO_REG2 {
+ regulator-name = "vcc_1v8";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vdd_1v0: LDO_REG3 {
+ regulator-name = "vdd_1v0";
+ regulator-min-microvolt = <1000000>;
+ regulator-max-microvolt = <1000000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1000000>;
+ };
+ };
+
+ vcc3v3_pmu: LDO_REG4 {
+ regulator-name = "vcc3v3_pmu";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vccio_sd: LDO_REG5 {
+ regulator-name = "vccio_sd";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vcc_sd: LDO_REG6 {
+ regulator-name = "vcc_sd";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vcc_bl: LDO_REG7 {
+ regulator-name = "vcc_bl";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vcc_lcd: LDO_REG8 {
+ regulator-name = "vcc_lcd";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ regulator-suspend-microvolt = <2800000>;
+ };
+ };
+
+ LDO_REG9 {
+ /* unused */
+ };
+
+ usb_midu: BOOST {
+ regulator-name = "usb_midu";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5400000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+ };
+
+ rk817_charger: charger {
+ rockchip,resistor-sense-micro-ohms = <10000>;
+ rockchip,sleep-enter-current-microamp = <300000>;
+ rockchip,sleep-filter-current-microamp = <100000>;
+ };
+
+ rk817_codec: codec {
+ rockchip,mic-in-differential;
+ };
+ };
+};
+
+/* EXT Header(P2): 7(SCL:GPIO0.C2), 8(SDA:GPIO0.C3) */
+&i2c1 {
+ clock-frequency = <400000>;
+ status = "okay";
+};
+
+/* I2S 1 Channel Used */
+&i2s1_2ch {
+ status = "okay";
+};
+
+&io_domains {
+ vccio1-supply = <&vcc_3v3>;
+ vccio2-supply = <&vccio_sd>;
+ vccio3-supply = <&vcc_3v3>;
+ vccio4-supply = <&vcc_3v3>;
+ vccio5-supply = <&vcc_3v3>;
+ vccio6-supply = <&vcc_3v3>;
+ status = "okay";
+};
+
+&pmu_io_domains {
+ pmuio1-supply = <&vcc3v3_pmu>;
+ pmuio2-supply = <&vcc3v3_pmu>;
+ status = "okay";
+};
+
+&pwm1 {
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&sdmmc {
+ cap-sd-highspeed;
+ card-detect-delay = <200>;
+ cd-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_LOW>; /*[> CD GPIO <]*/
+ sd-uhs-sdr12;
+ sd-uhs-sdr25;
+ sd-uhs-sdr50;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc_sd>;
+ vqmmc-supply = <&vccio_sd>;
+ status = "okay";
+};
+
+&sfc {
+ pinctrl-0 = <&sfc_clk &sfc_cs0 &sfc_bus2>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <108000000>;
+ spi-rx-bus-width = <2>;
+ spi-tx-bus-width = <1>;
+ };
+};
+
+&tsadc {
+ status = "okay";
+};
+
+&u2phy {
+ status = "okay";
+
+ u2phy_host: host-port {
+ status = "okay";
+ };
+
+ u2phy_otg: otg-port {
+ status = "disabled";
+ };
+};
+
+&usb20_otg {
+ status = "okay";
+};
+
+/* EXT Header(P2): 2(RXD:GPIO1.C0),3(TXD:.C1),4(CTS:.C2),5(RTS:.C3) */
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1_xfer &uart1_cts>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart2m1_xfer>;
+ status = "okay";
+};
+
+&vopb {
+ status = "okay";
+};
+
+&vopb_mmu {
+ status = "okay";
+};
+
+&pinctrl {
+ btns {
+ btn_pins: btn-pins {
+ rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ headphone {
+ hp_det: hp-det {
+ rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+ };
+
+ leds {
+ blue_led_pin: blue-led-pin {
+ rockchip,pins = <0 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pmic {
+ dc_det: dc-det {
+ rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ pmic_int: pmic-int {
+ rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+
+ soc_slppin_gpio: soc_slppin_gpio {
+ rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_output_low>;
+ };
+
+ soc_slppin_rst: soc_slppin_rst {
+ rockchip,pins = <0 RK_PA4 2 &pcfg_pull_none>;
+ };
+
+ soc_slppin_slp: soc_slppin_slp {
+ rockchip,pins = <0 RK_PA4 1 &pcfg_pull_none>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3326-odroid-go2-v11.dts b/arch/arm64/boot/dts/rockchip/rk3326-odroid-go2-v11.dts
new file mode 100644
index 000000000000..139c898e590e
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3326-odroid-go2-v11.dts
@@ -0,0 +1,156 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Hardkernel Co., Ltd
+ * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH
+ * Copyright (c) 2022 Maya Matuszczyk <maccraft123mc@gmail.com>
+ */
+
+/dts-v1/;
+#include "rk3326-odroid-go.dtsi"
+
+/ {
+ model = "ODROID-GO Advance Black Edition";
+ compatible = "hardkernel,rk3326-odroid-go2-v11", "rockchip,rk3326";
+
+ aliases {
+ mmc1 = &sdio;
+ };
+
+ analog_sticks: adc-joystick {
+ compatible = "adc-joystick";
+ io-channels = <&saradc 1>,
+ <&saradc 2>;
+ poll-interval = <60>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ axis@0 {
+ reg = <0>;
+ abs-flat = <10>;
+ abs-fuzz = <10>;
+ abs-range = <172 772>;
+ linux,code = <ABS_X>;
+ };
+
+ axis@1 {
+ reg = <1>;
+ abs-flat = <10>;
+ abs-fuzz = <10>;
+ abs-range = <278 815>;
+ linux,code = <ABS_Y>;
+ };
+ };
+
+ battery: battery {
+ compatible = "simple-battery";
+ charge-full-design-microamp-hours = <3000000>;
+ charge-term-current-microamp = <300000>;
+ constant-charge-current-max-microamp = <2000000>;
+ constant-charge-voltage-max-microvolt = <4200000>;
+ factory-internal-resistance-micro-ohms = <180000>;
+ voltage-max-design-microvolt = <4100000>;
+ voltage-min-design-microvolt = <3500000>;
+
+ ocv-capacity-celsius = <20>;
+ ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>,
+ <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>,
+ <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>,
+ <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>,
+ <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>,
+ <3574170 0>;
+ };
+
+ wifi_pwrseq: wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_pwrseq_pins>;
+ reset-gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&builtin_gamepad {
+ button-sw20 {
+ gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>;
+ label = "TOP-LEFT 2";
+ linux,code = <BTN_TL2>;
+ };
+ button-sw21 {
+ gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>;
+ label = "TOP-RIGHT 2";
+ linux,code = <BTN_TR2>;
+ };
+};
+
+&internal_display {
+ compatible = "elida,kd35t133";
+};
+
+&rk817 {
+ regulators {
+ vcc_wifi: LDO_REG9 {
+ regulator-name = "vcc_wifi";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+ };
+};
+
+&rk817_charger {
+ monitored-battery = <&battery>;
+};
+
+&sdio {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cap-sdio-irq;
+ disable-wp;
+ keep-power-in-suspend;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ non-removable;
+ vmmc-supply = <&vcc_wifi>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ esp8089: wifi@1 {
+ compatible = "esp,esp8089";
+ reg = <1>;
+ };
+};
+
+&pinctrl {
+ btns {
+ btn_pins: btn-pins {
+ rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>,
+ <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>,
+ <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ wifi {
+ wifi_pwrseq_pins: wifi-pwrseq-pins {
+ rockchip,pins = <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>,
+ <3 RK_PB6 RK_FUNC_GPIO &pcfg_output_high>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts b/arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts
index 72899a714310..4702183b673c 100644
--- a/arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3326-odroid-go2.dts
@@ -2,30 +2,21 @@
/*
* Copyright (c) 2019 Hardkernel Co., Ltd
* Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH
+ * Copyright (c) 2022 Maya Matuszczyk <maccraft123mc@gmail.com>
*/
/dts-v1/;
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/rockchip.h>
-#include "rk3326.dtsi"
+#include "rk3326-odroid-go.dtsi"
/ {
model = "ODROID-GO Advance";
compatible = "hardkernel,rk3326-odroid-go2", "rockchip,rk3326";
- aliases {
- mmc0 = &sdmmc;
- };
-
- chosen {
- stdout-path = "serial2:115200n8";
- };
-
- adc-joystick {
+ analog_sticks: adc-joystick {
compatible = "adc-joystick";
io-channels = <&saradc 1>,
<&saradc 2>;
+ poll-interval = <60>;
#address-cells = <1>;
#size-cells = <0>;
@@ -46,12 +37,6 @@
};
};
- backlight: backlight {
- compatible = "pwm-backlight";
- power-supply = <&vcc_bl>;
- pwms = <&pwm1 0 25000 0>;
- };
-
battery: battery {
compatible = "simple-battery";
charge-full-design-microamp-hours = <3000000>;
@@ -63,606 +48,19 @@
voltage-min-design-microvolt = <3500000>;
ocv-capacity-celsius = <20>;
- ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>,
+ ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>,
<3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>,
<3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>,
<3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>,
<3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>,
<3574170 0>;
};
-
- gpio-keys {
- compatible = "gpio-keys";
- pinctrl-names = "default";
- pinctrl-0 = <&btn_pins>;
-
- /*
- * *** ODROIDGO2-Advance Switch layout ***
- * |------------------------------------------------|
- * | sw15 sw16 |
- * |------------------------------------------------|
- * | sw1 |-------------------| sw8 |
- * | sw3 sw4 | | sw7 sw5 |
- * | sw2 | LCD Display | sw6 |
- * | | | |
- * | |-------------------| |
- * | sw9 sw10 sw11 sw12 sw13 sw14 |
- * |------------------------------------------------|
- */
-
- button-sw1 {
- gpios = <&gpio1 RK_PB4 GPIO_ACTIVE_LOW>;
- label = "DPAD-UP";
- linux,code = <BTN_DPAD_UP>;
- };
- button-sw2 {
- gpios = <&gpio1 RK_PB5 GPIO_ACTIVE_LOW>;
- label = "DPAD-DOWN";
- linux,code = <BTN_DPAD_DOWN>;
- };
- button-sw3 {
- gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_LOW>;
- label = "DPAD-LEFT";
- linux,code = <BTN_DPAD_LEFT>;
- };
- button-sw4 {
- gpios = <&gpio1 RK_PB7 GPIO_ACTIVE_LOW>;
- label = "DPAD-RIGHT";
- linux,code = <BTN_DPAD_RIGHT>;
- };
- button-sw5 {
- gpios = <&gpio1 RK_PA2 GPIO_ACTIVE_LOW>;
- label = "BTN-A";
- linux,code = <BTN_EAST>;
- };
- button-sw6 {
- gpios = <&gpio1 RK_PA5 GPIO_ACTIVE_LOW>;
- label = "BTN-B";
- linux,code = <BTN_SOUTH>;
- };
- button-sw7 {
- gpios = <&gpio1 RK_PA6 GPIO_ACTIVE_LOW>;
- label = "BTN-Y";
- linux,code = <BTN_WEST>;
- };
- button-sw8 {
- gpios = <&gpio1 RK_PA7 GPIO_ACTIVE_LOW>;
- label = "BTN-X";
- linux,code = <BTN_NORTH>;
- };
- button-sw9 {
- gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>;
- label = "F1";
- linux,code = <BTN_TRIGGER_HAPPY1>;
- };
- button-sw10 {
- gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>;
- label = "F2";
- linux,code = <BTN_TRIGGER_HAPPY2>;
- };
- button-sw11 {
- gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>;
- label = "F3";
- linux,code = <BTN_TRIGGER_HAPPY3>;
- };
- button-sw12 {
- gpios = <&gpio2 RK_PA3 GPIO_ACTIVE_LOW>;
- label = "F4";
- linux,code = <BTN_TRIGGER_HAPPY4>;
- };
- button-sw13 {
- gpios = <&gpio2 RK_PA4 GPIO_ACTIVE_LOW>;
- label = "F5";
- linux,code = <BTN_TRIGGER_HAPPY5>;
- };
- button-sw14 {
- gpios = <&gpio2 RK_PA5 GPIO_ACTIVE_LOW>;
- label = "F6";
- linux,code = <BTN_TRIGGER_HAPPY6>;
- };
- button-sw15 {
- gpios = <&gpio2 RK_PA6 GPIO_ACTIVE_LOW>;
- label = "TOP-LEFT";
- linux,code = <BTN_TL>;
- };
- button-sw16 {
- gpios = <&gpio2 RK_PA7 GPIO_ACTIVE_LOW>;
- label = "TOP-RIGHT";
- linux,code = <BTN_TR>;
- };
- };
-
- leds: gpio-leds {
- compatible = "gpio-leds";
- pinctrl-names = "default";
- pinctrl-0 = <&blue_led_pin>;
-
- blue_led: led-0 {
- label = "blue:heartbeat";
- gpios = <&gpio0 RK_PC1 GPIO_ACTIVE_HIGH>;
- linux,default-trigger = "heartbeat";
- };
- };
-
- rk817-sound {
- compatible = "simple-audio-card";
- simple-audio-card,name = "Analog";
- simple-audio-card,format = "i2s";
- simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>;
- simple-audio-card,mclk-fs = <256>;
- simple-audio-card,widgets =
- "Microphone", "Mic Jack",
- "Headphone", "Headphones",
- "Speaker", "Speaker";
- simple-audio-card,routing =
- "MICL", "Mic Jack",
- "Headphones", "HPOL",
- "Headphones", "HPOR",
- "Speaker", "SPKO";
-
- simple-audio-card,codec {
- sound-dai = <&rk817>;
- };
-
- simple-audio-card,cpu {
- sound-dai = <&i2s1_2ch>;
- };
- };
-
- vccsys: vccsys {
- compatible = "regulator-fixed";
- regulator-name = "vcc3v8_sys";
- regulator-always-on;
- regulator-min-microvolt = <3800000>;
- regulator-max-microvolt = <3800000>;
- };
-
- vcc_host: vcc_host {
- compatible = "regulator-fixed";
- regulator-name = "vcc_host";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5000000>;
-
- gpio = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>;
- enable-active-high;
- regulator-always-on;
- regulator-boot-on;
- vin-supply = <&usb_midu>;
- };
-};
-
-&cpu0 {
- cpu-supply = <&vdd_arm>;
-};
-
-&cpu1 {
- cpu-supply = <&vdd_arm>;
-};
-
-&cpu2 {
- cpu-supply = <&vdd_arm>;
-};
-
-&cpu3 {
- cpu-supply = <&vdd_arm>;
-};
-
-&cru {
- assigned-clocks = <&cru PLL_NPLL>,
- <&cru ACLK_BUS_PRE>, <&cru ACLK_PERI_PRE>,
- <&cru HCLK_BUS_PRE>, <&cru HCLK_PERI_PRE>,
- <&cru PCLK_BUS_PRE>, <&cru SCLK_GPU>,
- <&cru PLL_CPLL>;
-
- assigned-clock-rates = <1188000000>,
- <200000000>, <200000000>,
- <150000000>, <150000000>,
- <100000000>, <200000000>,
- <17000000>;
};
-&display_subsystem {
- status = "okay";
+&internal_display {
+ compatible = "elida,kd35t133";
};
-&dsi {
- status = "okay";
-
- ports {
- mipi_out: port@1 {
- reg = <1>;
-
- mipi_out_panel: endpoint {
- remote-endpoint = <&mipi_in_panel>;
- };
- };
- };
-
- panel@0 {
- compatible = "elida,kd35t133";
- reg = <0>;
- backlight = <&backlight>;
- iovcc-supply = <&vcc_lcd>;
- reset-gpios = <&gpio3 RK_PC0 GPIO_ACTIVE_LOW>;
- rotation = <270>;
- vdd-supply = <&vcc_lcd>;
-
- port {
- mipi_in_panel: endpoint {
- remote-endpoint = <&mipi_out_panel>;
- };
- };
- };
-};
-
-&dsi_dphy {
- status = "okay";
-};
-
-&gpu {
- mali-supply = <&vdd_logic>;
- status = "okay";
-};
-
-&i2c0 {
- clock-frequency = <400000>;
- i2c-scl-falling-time-ns = <16>;
- i2c-scl-rising-time-ns = <280>;
- status = "okay";
-
- rk817: pmic@20 {
- compatible = "rockchip,rk817";
- reg = <0x20>;
- interrupt-parent = <&gpio0>;
- interrupts = <RK_PB2 IRQ_TYPE_LEVEL_LOW>;
- clock-output-names = "rk808-clkout1", "xin32k";
- clock-names = "mclk";
- clocks = <&cru SCLK_I2S1_OUT>;
- pinctrl-names = "default";
- pinctrl-0 = <&pmic_int>, <&i2s1_2ch_mclk>;
- wakeup-source;
- #clock-cells = <1>;
- #sound-dai-cells = <0>;
-
- vcc1-supply = <&vccsys>;
- vcc2-supply = <&vccsys>;
- vcc3-supply = <&vccsys>;
- vcc4-supply = <&vccsys>;
- vcc5-supply = <&vccsys>;
- vcc6-supply = <&vccsys>;
- vcc7-supply = <&vccsys>;
- vcc8-supply = <&vccsys>;
-
- regulators {
- vdd_logic: DCDC_REG1 {
- regulator-name = "vdd_logic";
- regulator-min-microvolt = <950000>;
- regulator-max-microvolt = <1150000>;
- regulator-ramp-delay = <6001>;
- regulator-always-on;
- regulator-boot-on;
-
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <950000>;
- };
- };
-
- vdd_arm: DCDC_REG2 {
- regulator-name = "vdd_arm";
- regulator-min-microvolt = <950000>;
- regulator-max-microvolt = <1350000>;
- regulator-ramp-delay = <6001>;
- regulator-always-on;
- regulator-boot-on;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- regulator-suspend-microvolt = <950000>;
- };
- };
-
- vcc_ddr: DCDC_REG3 {
- regulator-name = "vcc_ddr";
- regulator-always-on;
- regulator-boot-on;
-
- regulator-state-mem {
- regulator-on-in-suspend;
- };
- };
-
- vcc_3v3: DCDC_REG4 {
- regulator-name = "vcc_3v3";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- regulator-boot-on;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- regulator-suspend-microvolt = <3300000>;
- };
- };
-
- vcc_1v8: LDO_REG2 {
- regulator-name = "vcc_1v8";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <1800000>;
- regulator-always-on;
- regulator-boot-on;
-
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <1800000>;
- };
- };
-
- vdd_1v0: LDO_REG3 {
- regulator-name = "vdd_1v0";
- regulator-min-microvolt = <1000000>;
- regulator-max-microvolt = <1000000>;
- regulator-always-on;
- regulator-boot-on;
-
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <1000000>;
- };
- };
-
- vcc3v3_pmu: LDO_REG4 {
- regulator-name = "vcc3v3_pmu";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- regulator-boot-on;
-
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <3300000>;
- };
- };
-
- vccio_sd: LDO_REG5 {
- regulator-name = "vccio_sd";
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- regulator-boot-on;
-
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <3300000>;
- };
- };
-
- vcc_sd: LDO_REG6 {
- regulator-name = "vcc_sd";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-boot-on;
-
- regulator-state-mem {
- regulator-on-in-suspend;
- regulator-suspend-microvolt = <3300000>;
- };
- };
-
- vcc_bl: LDO_REG7 {
- regulator-name = "vcc_bl";
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- regulator-suspend-microvolt = <3300000>;
- };
- };
-
- vcc_lcd: LDO_REG8 {
- regulator-name = "vcc_lcd";
- regulator-min-microvolt = <2800000>;
- regulator-max-microvolt = <2800000>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- regulator-suspend-microvolt = <2800000>;
- };
- };
-
- vcc_cam: LDO_REG9 {
- regulator-name = "vcc_cam";
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
-
- regulator-state-mem {
- regulator-off-in-suspend;
- regulator-suspend-microvolt = <3000000>;
- };
- };
-
- usb_midu: BOOST {
- regulator-name = "usb_midu";
- regulator-min-microvolt = <5000000>;
- regulator-max-microvolt = <5400000>;
- regulator-always-on;
- regulator-boot-on;
- };
- };
-
- rk817_charger: charger {
- monitored-battery = <&battery>;
- rockchip,resistor-sense-micro-ohms = <10000>;
- rockchip,sleep-enter-current-microamp = <300000>;
- rockchip,sleep-filter-current-microamp = <100000>;
- };
-
- rk817_codec: codec {
- rockchip,mic-in-differential;
- };
- };
-};
-
-/* EXT Header(P2): 7(SCL:GPIO0.C2), 8(SDA:GPIO0.C3) */
-&i2c1 {
- clock-frequency = <400000>;
- status = "okay";
-};
-
-/* I2S 1 Channel Used */
-&i2s1_2ch {
- status = "okay";
-};
-
-&io_domains {
- vccio1-supply = <&vcc_3v3>;
- vccio2-supply = <&vccio_sd>;
- vccio3-supply = <&vcc_3v3>;
- vccio4-supply = <&vcc_3v3>;
- vccio5-supply = <&vcc_3v3>;
- vccio6-supply = <&vcc_3v3>;
- status = "okay";
-};
-
-&pmu_io_domains {
- pmuio1-supply = <&vcc3v3_pmu>;
- pmuio2-supply = <&vcc3v3_pmu>;
- status = "okay";
-};
-
-&pwm1 {
- status = "okay";
-};
-
-&saradc {
- vref-supply = <&vcc_1v8>;
- status = "okay";
-};
-
-&sdmmc {
- cap-sd-highspeed;
- card-detect-delay = <200>;
- cd-gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_LOW>; /*[> CD GPIO <]*/
- sd-uhs-sdr12;
- sd-uhs-sdr25;
- sd-uhs-sdr50;
- sd-uhs-sdr104;
- vmmc-supply = <&vcc_sd>;
- vqmmc-supply = <&vccio_sd>;
- status = "okay";
-};
-
-&sfc {
- pinctrl-0 = <&sfc_clk &sfc_cs0 &sfc_bus2>;
- pinctrl-names = "default";
- #address-cells = <1>;
- #size-cells = <0>;
- status = "okay";
-
- flash@0 {
- compatible = "jedec,spi-nor";
- reg = <0>;
- spi-max-frequency = <108000000>;
- spi-rx-bus-width = <2>;
- spi-tx-bus-width = <1>;
- };
-};
-
-&tsadc {
- status = "okay";
-};
-
-&u2phy {
- status = "okay";
-
- u2phy_host: host-port {
- status = "okay";
- };
-
- u2phy_otg: otg-port {
- status = "disabled";
- };
-};
-
-&usb20_otg {
- status = "okay";
-};
-
-/* EXT Header(P2): 2(RXD:GPIO1.C0),3(TXD:.C1),4(CTS:.C2),5(RTS:.C3) */
-&uart1 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart1_xfer &uart1_cts>;
- status = "okay";
-};
-
-&uart2 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart2m1_xfer>;
- status = "okay";
-};
-
-&vopb {
- status = "okay";
-};
-
-&vopb_mmu {
- status = "okay";
-};
-
-&pinctrl {
- btns {
- btn_pins: btn-pins {
- rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>,
- <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>,
- <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>,
- <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>,
- <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>,
- <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>,
- <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>,
- <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>,
- <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>,
- <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>,
- <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>,
- <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>,
- <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>,
- <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>,
- <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>,
- <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>;
- };
- };
-
- headphone {
- hp_det: hp-det {
- rockchip,pins = <2 RK_PC6 RK_FUNC_GPIO &pcfg_pull_down>;
- };
- };
-
- leds {
- blue_led_pin: blue-led-pin {
- rockchip,pins = <0 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
- pmic {
- dc_det: dc-det {
- rockchip,pins = <0 RK_PB3 RK_FUNC_GPIO &pcfg_pull_none>;
- };
-
- pmic_int: pmic-int {
- rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>;
- };
-
- soc_slppin_gpio: soc_slppin_gpio {
- rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_output_low>;
- };
-
- soc_slppin_rst: soc_slppin_rst {
- rockchip,pins = <0 RK_PA4 2 &pcfg_pull_none>;
- };
-
- soc_slppin_slp: soc_slppin_slp {
- rockchip,pins = <0 RK_PA4 1 &pcfg_pull_none>;
- };
- };
+&rk817_charger {
+ monitored-battery = <&battery>;
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3326-odroid-go3.dts b/arch/arm64/boot/dts/rockchip/rk3326-odroid-go3.dts
new file mode 100644
index 000000000000..842efbaf1a6a
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3326-odroid-go3.dts
@@ -0,0 +1,185 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2019 Hardkernel Co., Ltd
+ * Copyright (c) 2020 Theobroma Systems Design und Consulting GmbH
+ * Copyright (c) 2022 Maya Matuszczyk <maccraft123mc@gmail.com>
+ */
+
+/dts-v1/;
+#include "rk3326-odroid-go.dtsi"
+
+/ {
+ model = "ODROID-GO Super";
+ compatible = "hardkernel,rk3326-odroid-go3", "rockchip,rk3326";
+
+ joystick_mux_controller: mux-controller {
+ compatible = "gpio-mux";
+ pinctrl = <&mux_en_pins>;
+ #mux-control-cells = <0>;
+
+ mux-gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>,
+ <&gpio3 RK_PB0 GPIO_ACTIVE_LOW>;
+ };
+
+ joystick_mux: adc-mux {
+ compatible = "io-channel-mux";
+ io-channels = <&saradc 1>;
+ io-channel-names = "parent";
+ #io-channel-cells = <1>;
+
+ mux-controls = <&joystick_mux_controller>;
+ channels = "0", "1", "2", "3";
+ };
+
+ analog_sticks: adc-joystick {
+ compatible = "adc-joystick";
+ io-channels = <&joystick_mux 0>,
+ <&joystick_mux 1>,
+ <&joystick_mux 2>,
+ <&joystick_mux 3>;
+ poll-interval = <60>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ axis@0 {
+ reg = <0>;
+ abs-flat = <10>;
+ abs-fuzz = <10>;
+ abs-range = <180 800>;
+ linux,code = <ABS_X>;
+ };
+
+ axis@1 {
+ reg = <1>;
+ abs-flat = <10>;
+ abs-fuzz = <10>;
+ abs-range = <180 800>;
+ linux,code = <ABS_RX>;
+ };
+
+ axis@2 {
+ reg = <2>;
+ abs-flat = <10>;
+ abs-fuzz = <10>;
+ abs-range = <180 800>;
+ linux,code = <ABS_Y>;
+ };
+
+ axis@3 {
+ reg = <3>;
+ abs-flat = <10>;
+ abs-fuzz = <10>;
+ abs-range = <180 800>;
+ linux,code = <ABS_RY>;
+ };
+ };
+
+ battery: battery {
+ compatible = "simple-battery";
+ charge-full-design-microamp-hours = <4000000>;
+ charge-term-current-microamp = <300000>;
+ constant-charge-current-max-microamp = <2000000>;
+ constant-charge-voltage-max-microvolt = <4200000>;
+ factory-internal-resistance-micro-ohms = <180000>;
+ voltage-max-design-microvolt = <4100000>;
+ voltage-min-design-microvolt = <3500000>;
+
+ ocv-capacity-celsius = <20>;
+ ocv-capacity-table-0 = <4046950 100>, <4001920 95>, <3967900 90>, <3919950 85>,
+ <3888450 80>, <3861850 75>, <3831540 70>, <3799130 65>,
+ <3768190 60>, <3745650 55>, <3726610 50>, <3711630 45>,
+ <3696720 40>, <3685660 35>, <3674950 30>, <3663050 25>,
+ <3649470 20>, <3635260 15>, <3616920 10>, <3592440 5>,
+ <3574170 0>;
+ };
+
+ gpio-keys-vol {
+ compatible = "gpio-keys";
+ autorepeat;
+ pinctrl-0 = <&btn_pins_vol>;
+ pinctrl-names = "default";
+
+ button-vol-down {
+ gpios = <&gpio2 RK_PA1 GPIO_ACTIVE_LOW>;
+ label = "VOLUMEDOWN";
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+
+ button-volume-up {
+ gpios = <&gpio2 RK_PA0 GPIO_ACTIVE_LOW>;
+ label = "VOLUMEUP";
+ linux,code = <KEY_VOLUMEUP>;
+ };
+ };
+};
+
+/* f1 and f2 conflict with volume buttons */
+/delete-node/ &btn_f1;
+/delete-node/ &btn_f2;
+
+&builtin_gamepad {
+ button-sw19 {
+ gpios = <&gpio3 RK_PB1 GPIO_ACTIVE_LOW>;
+ label = "SELECT";
+ linux,code = <BTN_SELECT>;
+ };
+ /* note that TR2 and TL2 are swapped */
+ button-sw20 {
+ gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>;
+ label = "TOP-RIGHT 2";
+ linux,code = <BTN_TR2>;
+ };
+ button-sw21 {
+ gpios = <&gpio3 RK_PB2 GPIO_ACTIVE_LOW>;
+ label = "TOP-LEFT 2";
+ linux,code = <BTN_TL2>;
+ };
+ button-sw22 {
+ gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>;
+ label = "START";
+ linux,code = <BTN_START>;
+ };
+};
+
+&internal_display {
+ status = "disabled";
+};
+
+&rk817_charger {
+ monitored-battery = <&battery>;
+};
+
+&pinctrl {
+ btns {
+ btn_pins: btn-pins {
+ rockchip,pins = <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up>,
+ <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up>,
+ <3 RK_PB1 RK_FUNC_GPIO &pcfg_pull_up>,
+ <3 RK_PB2 RK_FUNC_GPIO &pcfg_pull_up>,
+ <3 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up>,
+ <3 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ btn_pins_vol: btn-pins-vol {
+ rockchip,pins = <2 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>,
+ <2 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ joystick {
+ mux_en_pins: mux-pins {
+ rockchip,pins = <3 RK_PB5 RK_FUNC_GPIO &pcfg_output_low>;
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
index 49ae15708a0b..6d7a7bf72ac7 100644
--- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
@@ -102,6 +102,7 @@
l2: l2-cache0 {
compatible = "cache";
+ cache-level = <2>;
};
};
@@ -1025,6 +1026,17 @@
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
};
+ crypto: crypto@ff060000 {
+ compatible = "rockchip,rk3328-crypto";
+ reg = <0x0 0xff060000 0x0 0x4000>;
+ interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&cru HCLK_CRYPTO_MST>, <&cru HCLK_CRYPTO_SLV>,
+ <&cru SCLK_CRYPTO>;
+ clock-names = "hclk_master", "hclk_slave", "sclk";
+ resets = <&cru SRST_CRYPTO>;
+ reset-names = "crypto-rst";
+ };
+
pinctrl: pinctrl {
compatible = "rockchip,rk3328-pinctrl";
rockchip,grf = <&grf>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
index 2e058c315025..04403a76238b 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-pinephone-pro.dts
@@ -81,6 +81,27 @@
regulator-max-microvolt = <1800000>;
vin-supply = <&vcc3v3_sys>;
};
+
+ wifi_pwrseq: sdio-wifi-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ clocks = <&rk818 1>;
+ clock-names = "ext_clock";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_enable_h_pin>;
+ /*
+ * Wait between power-on and SDIO access for CYP43455
+ * POR circuit.
+ */
+ post-power-on-delay-ms = <110>;
+ /*
+ * Wait between consecutive toggles for CYP43455 CBUCK
+ * regulator discharge.
+ */
+ power-off-delay-us = <10000>;
+
+ /* WL_REG_ON on module */
+ reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
+ };
};
&cpu_l0 {
@@ -360,11 +381,45 @@
};
};
+ sdio-pwrseq {
+ wifi_enable_h_pin: wifi-enable-h-pin {
+ rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
sound {
vcc1v8_codec_en: vcc1v8-codec-en {
rockchip,pins = <3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_down>;
};
};
+
+ wireless-bluetooth {
+ bt_wake_pin: bt-wake-pin {
+ rockchip,pins = <2 RK_PD2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bt_host_wake_pin: bt-host-wake-pin {
+ rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bt_reset_pin: bt-reset-pin {
+ rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&sdio0 {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cap-sdio-irq;
+ disable-wp;
+ keep-power-in-suspend;
+ mmc-pwrseq = <&wifi_pwrseq>;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>;
+ sd-uhs-sdr104;
+ status = "okay";
};
&sdmmc {
@@ -393,6 +448,27 @@
status = "okay";
};
+&uart0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
+ uart-has-rtscts;
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm4345c5";
+ clocks = <&rk818 1>;
+ clock-names = "lpo";
+ device-wakeup-gpios = <&gpio2 RK_PD2 GPIO_ACTIVE_HIGH>;
+ host-wakeup-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>;
+ max-speed = <1500000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_host_wake_pin &bt_wake_pin &bt_reset_pin>;
+ shutdown-gpios = <&gpio0 RK_PB1 GPIO_ACTIVE_HIGH>;
+ vbat-supply = <&vcc3v3_sys>;
+ vddio-supply = <&vcc_1v8>;
+ };
+};
+
&uart2 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock-4c-plus.dts b/arch/arm64/boot/dts/rockchip/rk3399-rock-4c-plus.dts
index f9884902f874..309c35d7fca8 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-rock-4c-plus.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3399-rock-4c-plus.dts
@@ -601,6 +601,12 @@
status = "okay";
};
+&tsadc {
+ rockchip,hw-tshut-mode = <1>;
+ rockchip,hw-tshut-polarity = <1>;
+ status = "okay";
+};
+
&u2phy0 {
status = "okay";
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi
index 94e39ed63397..c920ddf44baf 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi
@@ -128,6 +128,8 @@
};
&hdmi {
+ avdd-0v9-supply = <&vcca0v9_hdmi>;
+ avdd-1v8-supply = <&vcca1v8_hdmi>;
ddc-i2c-bus = <&i2c3>;
pinctrl-names = "default";
pinctrl-0 = <&hdmi_cec>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399.dtsi b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
index 92c2207e686c..4391aea25984 100644
--- a/arch/arm64/boot/dts/rockchip/rk3399.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3399.dtsi
@@ -582,6 +582,26 @@
status = "disabled";
};
+ crypto0: crypto@ff8b0000 {
+ compatible = "rockchip,rk3399-crypto";
+ reg = <0x0 0xff8b0000 0x0 0x4000>;
+ interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru HCLK_M_CRYPTO0>, <&cru HCLK_S_CRYPTO0>, <&cru SCLK_CRYPTO0>;
+ clock-names = "hclk_master", "hclk_slave", "sclk";
+ resets = <&cru SRST_CRYPTO0>, <&cru SRST_CRYPTO0_S>, <&cru SRST_CRYPTO0_M>;
+ reset-names = "master", "lave", "crypto";
+ };
+
+ crypto1: crypto@ff8b8000 {
+ compatible = "rockchip,rk3399-crypto";
+ reg = <0x0 0xff8b8000 0x0 0x4000>;
+ interrupts = <GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&cru HCLK_M_CRYPTO1>, <&cru HCLK_S_CRYPTO1>, <&cru SCLK_CRYPTO1>;
+ clock-names = "hclk_master", "hclk_slave", "sclk";
+ resets = <&cru SRST_CRYPTO1>, <&cru SRST_CRYPTO1_S>, <&cru SRST_CRYPTO1_M>;
+ reset-names = "master", "slave", "crypto";
+ };
+
i2c1: i2c@ff110000 {
compatible = "rockchip,rk3399-i2c";
reg = <0x0 0xff110000 0x0 0x1000>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353p.dts b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353p.dts
index 7a20e2d6876a..63cff402f3a8 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353p.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353p.dts
@@ -5,7 +5,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/input/linux-event-codes.h>
#include <dt-bindings/pinctrl/rockchip.h>
-#include "rk3566-anbernic-rgxx3.dtsi"
+#include "rk3566-anbernic-rg353x.dtsi"
/ {
model = "RG353P";
@@ -18,26 +18,66 @@
mmc3 = &sdmmc2;
};
- backlight: backlight {
- compatible = "pwm-backlight";
- power-supply = <&vcc_sys>;
- pwms = <&pwm4 0 25000 0>;
+ battery: battery {
+ compatible = "simple-battery";
+ charge-full-design-microamp-hours = <3472000>;
+ charge-term-current-microamp = <300000>;
+ constant-charge-current-max-microamp = <2000000>;
+ constant-charge-voltage-max-microvolt = <4200000>;
+ factory-internal-resistance-micro-ohms = <117000>;
+ voltage-max-design-microvolt = <4172000>;
+ voltage-min-design-microvolt = <3400000>;
+
+ ocv-capacity-celsius = <20>;
+ ocv-capacity-table-0 = <4172000 100>, <4054000 95>, <3984000 90>, <3926000 85>,
+ <3874000 80>, <3826000 75>, <3783000 70>, <3746000 65>,
+ <3714000 60>, <3683000 55>, <3650000 50>, <3628000 45>,
+ <3612000 40>, <3600000 35>, <3587000 30>, <3571000 25>,
+ <3552000 20>, <3525000 15>, <3492000 10>, <3446000 5>,
+ <3400000 0>;
};
-};
-&gpio_keys_control {
- button-a {
- gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>;
- label = "EAST";
- linux,code = <BTN_EAST>;
+ /* Channels reversed for both headphones and speakers. */
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "rk817_ext";
+ simple-audio-card,aux-devs = <&spk_amp>;
+ simple-audio-card,format = "i2s";
+ simple-audio-card,hp-det-gpio = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,widgets =
+ "Microphone", "Mic Jack",
+ "Headphone", "Headphones",
+ "Speaker", "Internal Speakers";
+ simple-audio-card,routing =
+ "MICL", "Mic Jack",
+ "Headphones", "HPOL",
+ "Headphones", "HPOR",
+ "Internal Speakers", "Speaker Amp OUTL",
+ "Internal Speakers", "Speaker Amp OUTR",
+ "Speaker Amp INL", "HPOL",
+ "Speaker Amp INR", "HPOR";
+ simple-audio-card,pin-switches = "Internal Speakers";
+
+ simple-audio-card,codec {
+ sound-dai = <&rk817>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s1_8ch>;
+ };
};
- button-left {
- gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>;
- label = "DPAD-LEFT";
- linux,code = <BTN_DPAD_LEFT>;
+ spk_amp: audio-amplifier {
+ compatible = "simple-audio-amplifier";
+ enable-gpios = <&gpio4 RK_PC2 GPIO_ACTIVE_HIGH>;
+ pinctrl-0 = <&spk_amp_enable_h>;
+ pinctrl-names = "default";
+ sound-name-prefix = "Speaker Amp";
};
+};
+&gpio_keys_control {
button-r1 {
gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>;
label = "TR";
@@ -49,27 +89,6 @@
label = "TR2";
linux,code = <BTN_TR2>;
};
-
- button-right {
- gpios = <&gpio3 RK_PA5 GPIO_ACTIVE_LOW>;
- label = "DPAD-RIGHT";
- linux,code = <BTN_DPAD_RIGHT>;
- };
-
- button-y {
- gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_LOW>;
- label = "WEST";
- linux,code = <BTN_WEST>;
- };
-};
-
-&i2c0 {
- /* This hardware is physically present but unused. */
- power-monitor@62 {
- compatible = "cellwise,cw2015";
- reg = <0x62>;
- status = "disabled";
- };
};
&i2c2 {
@@ -78,8 +97,22 @@
status = "okay";
};
-&pwm4 {
- status = "okay";
+&pinctrl {
+ audio-amplifier {
+ spk_amp_enable_h: spk-amp-enable-h {
+ rockchip,pins =
+ <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&rk817 {
+ rk817_charger: charger {
+ monitored-battery = <&battery>;
+ rockchip,resistor-sense-micro-ohms = <10000>;
+ rockchip,sleep-enter-current-microamp = <300000>;
+ rockchip,sleep-filter-current-microamp = <100000>;
+ };
};
&sdhci {
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353v.dts b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353v.dts
new file mode 100644
index 000000000000..885234a023e1
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353v.dts
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include "rk3566-anbernic-rg353x.dtsi"
+
+/ {
+ model = "RG353V";
+ compatible = "anbernic,rg353v", "rockchip,rk3566";
+
+ aliases {
+ mmc0 = &sdhci;
+ mmc1 = &sdmmc0;
+ mmc2 = &sdmmc1;
+ mmc3 = &sdmmc2;
+ };
+
+ battery: battery {
+ compatible = "simple-battery";
+ charge-full-design-microamp-hours = <3151000>;
+ charge-term-current-microamp = <300000>;
+ constant-charge-current-max-microamp = <2000000>;
+ constant-charge-voltage-max-microvolt = <4200000>;
+ factory-internal-resistance-micro-ohms = <117000>;
+ voltage-max-design-microvolt = <4172000>;
+ voltage-min-design-microvolt = <3400000>;
+
+ ocv-capacity-celsius = <20>;
+ ocv-capacity-table-0 = <4172000 100>, <4054000 95>, <3984000 90>, <3926000 85>,
+ <3874000 80>, <3826000 75>, <3783000 70>, <3746000 65>,
+ <3714000 60>, <3683000 55>, <3650000 50>, <3628000 45>,
+ <3612000 40>, <3600000 35>, <3587000 30>, <3571000 25>,
+ <3552000 20>, <3525000 15>, <3492000 10>, <3446000 5>,
+ <3400000 0>;
+ };
+
+ /* Channels reversed for headphones. */
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "rk817_int";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,hp-det-gpio = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,widgets =
+ "Microphone", "Mic Jack",
+ "Headphone", "Headphones",
+ "Speaker", "Internal Speakers";
+ simple-audio-card,routing =
+ "MICL", "Mic Jack",
+ "Headphones", "HPOL",
+ "Headphones", "HPOR",
+ "Internal Speakers", "SPKO";
+
+ simple-audio-card,codec {
+ sound-dai = <&rk817>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s1_8ch>;
+ };
+ };
+};
+
+&gpio_keys_control {
+ button-r1 {
+ gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>;
+ label = "TR";
+ linux,code = <BTN_TR>;
+ };
+
+ button-r2 {
+ gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>;
+ label = "TR2";
+ linux,code = <BTN_TR2>;
+ };
+};
+
+&i2c2 {
+ pintctrl-names = "default";
+ pinctrl-0 = <&i2c2m1_xfer>;
+ status = "okay";
+};
+
+&pinctrl {
+ touch {
+ touch_rst: touch-rst {
+ rockchip,pins =
+ <4 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+};
+
+&rk817 {
+ rk817_charger: charger {
+ monitored-battery = <&battery>;
+ rockchip,resistor-sense-micro-ohms = <10000>;
+ rockchip,sleep-enter-current-microamp = <300000>;
+ rockchip,sleep-filter-current-microamp = <100000>;
+ };
+};
+
+&sdhci {
+ pinctrl-0 = <&emmc_bus8>, <&emmc_clk>, <&emmc_cmd>, <&emmc_datastrobe>, <&emmc_rstnout>;
+ pinctrl-names = "default";
+ bus-width = <8>;
+ mmc-hs200-1_8v;
+ non-removable;
+ vmmc-supply = <&vcc_3v3>;
+ vqmmc-supply = <&vcc_1v8>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353vs.dts b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353vs.dts
new file mode 100644
index 000000000000..a7dc462fe21f
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353vs.dts
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include "rk3566-anbernic-rg353x.dtsi"
+
+/ {
+ model = "RG353VS";
+ compatible = "anbernic,rg353vs", "rockchip,rk3566";
+
+ aliases {
+ mmc0 = &sdmmc0;
+ mmc1 = &sdmmc1;
+ mmc2 = &sdmmc2;
+ };
+
+ battery: battery {
+ compatible = "simple-battery";
+ charge-full-design-microamp-hours = <3151000>;
+ charge-term-current-microamp = <300000>;
+ constant-charge-current-max-microamp = <2000000>;
+ constant-charge-voltage-max-microvolt = <4200000>;
+ factory-internal-resistance-micro-ohms = <117000>;
+ voltage-max-design-microvolt = <4172000>;
+ voltage-min-design-microvolt = <3400000>;
+
+ ocv-capacity-celsius = <20>;
+ ocv-capacity-table-0 = <4172000 100>, <4054000 95>, <3984000 90>, <3926000 85>,
+ <3874000 80>, <3826000 75>, <3783000 70>, <3746000 65>,
+ <3714000 60>, <3683000 55>, <3650000 50>, <3628000 45>,
+ <3612000 40>, <3600000 35>, <3587000 30>, <3571000 25>,
+ <3552000 20>, <3525000 15>, <3492000 10>, <3446000 5>,
+ <3400000 0>;
+ };
+
+ /* Channels reversed for headphones. */
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "rk817_int";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,hp-det-gpio = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,widgets =
+ "Microphone", "Mic Jack",
+ "Headphone", "Headphones",
+ "Speaker", "Internal Speakers";
+ simple-audio-card,routing =
+ "MICL", "Mic Jack",
+ "Headphones", "HPOL",
+ "Headphones", "HPOR",
+ "Internal Speakers", "SPKO";
+
+ simple-audio-card,codec {
+ sound-dai = <&rk817>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s1_8ch>;
+ };
+ };
+};
+
+&gpio_keys_control {
+ button-r1 {
+ gpios = <&gpio3 RK_PB3 GPIO_ACTIVE_LOW>;
+ label = "TR";
+ linux,code = <BTN_TR>;
+ };
+
+ button-r2 {
+ gpios = <&gpio3 RK_PB4 GPIO_ACTIVE_LOW>;
+ label = "TR2";
+ linux,code = <BTN_TR2>;
+ };
+};
+
+&rk817 {
+ rk817_charger: charger {
+ monitored-battery = <&battery>;
+ rockchip,resistor-sense-micro-ohms = <10000>;
+ rockchip,sleep-enter-current-microamp = <300000>;
+ rockchip,sleep-filter-current-microamp = <100000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353x.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353x.dtsi
new file mode 100644
index 000000000000..65a80d1f6d91
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg353x.dtsi
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/linux-event-codes.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include "rk3566-anbernic-rgxx3.dtsi"
+
+/ {
+ backlight: backlight {
+ compatible = "pwm-backlight";
+ power-supply = <&vcc_sys>;
+ pwms = <&pwm4 0 25000 0>;
+ };
+};
+
+&cru {
+ assigned-clocks = <&cru PLL_GPLL>, <&pmucru PLL_PPLL>, <&cru PLL_VPLL>;
+ assigned-clock-rates = <1200000000>, <200000000>, <241500000>;
+};
+
+&gpio_keys_control {
+ button-a {
+ gpios = <&gpio3 RK_PC2 GPIO_ACTIVE_LOW>;
+ label = "EAST";
+ linux,code = <BTN_EAST>;
+ };
+
+ button-left {
+ gpios = <&gpio3 RK_PA6 GPIO_ACTIVE_LOW>;
+ label = "DPAD-LEFT";
+ linux,code = <BTN_DPAD_LEFT>;
+ };
+
+ button-right {
+ gpios = <&gpio3 RK_PA5 GPIO_ACTIVE_LOW>;
+ label = "DPAD-RIGHT";
+ linux,code = <BTN_DPAD_RIGHT>;
+ };
+
+ button-y {
+ gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_LOW>;
+ label = "WEST";
+ linux,code = <BTN_WEST>;
+ };
+};
+
+&i2c0 {
+ /* This hardware is physically present but unused. */
+ power-monitor@62 {
+ compatible = "cellwise,cw2015";
+ reg = <0x62>;
+ status = "disabled";
+ };
+};
+
+&pwm4 {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg503.dts b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg503.dts
index 3dc01549a5b4..5dafcc86296b 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg503.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rg503.dts
@@ -17,6 +17,25 @@
mmc2 = &sdmmc2;
};
+ battery: battery {
+ compatible = "simple-battery";
+ charge-full-design-microamp-hours = <3472000>;
+ charge-term-current-microamp = <300000>;
+ constant-charge-current-max-microamp = <2000000>;
+ constant-charge-voltage-max-microvolt = <4200000>;
+ factory-internal-resistance-micro-ohms = <117000>;
+ voltage-max-design-microvolt = <4172000>;
+ voltage-min-design-microvolt = <3400000>;
+
+ ocv-capacity-celsius = <20>;
+ ocv-capacity-table-0 = <4172000 100>, <4054000 95>, <3984000 90>, <3926000 85>,
+ <3874000 80>, <3826000 75>, <3783000 70>, <3746000 65>,
+ <3714000 60>, <3683000 55>, <3650000 50>, <3628000 45>,
+ <3612000 40>, <3600000 35>, <3587000 30>, <3571000 25>,
+ <3552000 20>, <3525000 15>, <3492000 10>, <3446000 5>,
+ <3400000 0>;
+ };
+
gpio_spi: spi {
compatible = "spi-gpio";
pinctrl-names = "default";
@@ -29,6 +48,50 @@
cs-gpios = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
num-chipselects = <0>;
};
+
+ /* Channels reversed for both headphones and speakers. */
+ sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "rk817_ext";
+ simple-audio-card,aux-devs = <&spk_amp>;
+ simple-audio-card,format = "i2s";
+ simple-audio-card,hp-det-gpio = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,widgets =
+ "Microphone", "Mic Jack",
+ "Headphone", "Headphones",
+ "Speaker", "Internal Speakers";
+ simple-audio-card,routing =
+ "MICL", "Mic Jack",
+ "Headphones", "HPOL",
+ "Headphones", "HPOR",
+ "Internal Speakers", "Speaker Amp OUTL",
+ "Internal Speakers", "Speaker Amp OUTR",
+ "Speaker Amp INL", "HPOL",
+ "Speaker Amp INR", "HPOR";
+ simple-audio-card,pin-switches = "Internal Speakers";
+
+ simple-audio-card,codec {
+ sound-dai = <&rk817>;
+ };
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s1_8ch>;
+ };
+ };
+
+ spk_amp: audio-amplifier {
+ compatible = "simple-audio-amplifier";
+ enable-gpios = <&gpio4 RK_PC2 GPIO_ACTIVE_HIGH>;
+ pinctrl-0 = <&spk_amp_enable_h>;
+ pinctrl-names = "default";
+ sound-name-prefix = "Speaker Amp";
+ };
+};
+
+&cru {
+ assigned-clocks = <&cru PLL_GPLL>, <&pmucru PLL_PPLL>, <&cru PLL_VPLL>;
+ assigned-clock-rates = <1200000000>, <200000000>, <500000000>;
};
&gpio_keys_control {
@@ -76,6 +139,13 @@
};
&pinctrl {
+ audio-amplifier {
+ spk_amp_enable_h: spk-amp-enable-h {
+ rockchip,pins =
+ <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
gpio-spi {
spi_pins: spi-pins {
rockchip,pins =
@@ -85,3 +155,12 @@
};
};
};
+
+&rk817 {
+ rk817_charger: charger {
+ monitored-battery = <&battery>;
+ rockchip,resistor-sense-micro-ohms = <10000>;
+ rockchip,sleep-enter-current-microamp = <300000>;
+ rockchip,sleep-filter-current-microamp = <100000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rgxx3.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rgxx3.dtsi
index 2b455143b86d..41262a69d33e 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rgxx3.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3566-anbernic-rgxx3.dtsi
@@ -22,6 +22,7 @@
<&adc_mux 3>;
pinctrl-0 = <&joy_mux_en>;
pinctrl-names = "default";
+ poll-interval = <60>;
#address-cells = <1>;
#size-cells = <0>;
@@ -217,37 +218,6 @@
};
};
- /* Channels reversed for both headphones and speakers. */
- sound {
- compatible = "simple-audio-card";
- simple-audio-card,name = "anbernic_rk817";
- simple-audio-card,aux-devs = <&spk_amp>;
- simple-audio-card,format = "i2s";
- simple-audio-card,hp-det-gpio = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
- simple-audio-card,mclk-fs = <256>;
- simple-audio-card,widgets =
- "Microphone", "Mic Jack",
- "Headphone", "Headphones",
- "Speaker", "Internal Speakers";
- simple-audio-card,routing =
- "MICL", "Mic Jack",
- "Headphones", "HPOL",
- "Headphones", "HPOR",
- "Internal Speakers", "Speaker Amp OUTL",
- "Internal Speakers", "Speaker Amp OUTR",
- "Speaker Amp INL", "HPOL",
- "Speaker Amp INR", "HPOR";
- simple-audio-card,pin-switches = "Internal Speakers";
-
- simple-audio-card,codec {
- sound-dai = <&rk817>;
- };
-
- simple-audio-card,cpu {
- sound-dai = <&i2s1_8ch>;
- };
- };
-
sdio_pwrseq: sdio-pwrseq {
compatible = "mmc-pwrseq-simple";
clocks = <&rk817 1>;
@@ -258,14 +228,6 @@
reset-gpios = <&gpio4 RK_PA2 GPIO_ACTIVE_LOW>;
};
- spk_amp: audio-amplifier {
- compatible = "simple-audio-amplifier";
- enable-gpios = <&gpio4 RK_PC2 GPIO_ACTIVE_HIGH>;
- pinctrl-0 = <&spk_amp_enable_h>;
- pinctrl-names = "default";
- sound-name-prefix = "Speaker Amp";
- };
-
vcc3v3_lcd0_n: regulator-vcc3v3-lcd0 {
compatible = "regulator-fixed";
gpio = <&gpio0 RK_PC2 GPIO_ACTIVE_HIGH>;
@@ -607,13 +569,6 @@
};
&pinctrl {
- audio-amplifier {
- spk_amp_enable_h: spk-amp-enable-h {
- rockchip,pins =
- <4 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
- };
- };
-
gpio-btns {
btn_pins_ctrl: btn-pins-ctrl {
rockchip,pins =
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-box-demo.dts b/arch/arm64/boot/dts/rockchip/rk3566-box-demo.dts
new file mode 100644
index 000000000000..4c7f9abd594f
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3566-box-demo.dts
@@ -0,0 +1,503 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/*
+ * Author: Piotr Oniszczuk piotr.oniszczuk@gmail.com
+ * Based on Quartz64 DT by: Peter Geis pgwipeout@gmail.com
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
+#include "rk3566.dtsi"
+
+/ {
+ model = "Rockchip RK3566 BOX DEMO Board";
+ compatible = "rockchip,rk3566-box-demo", "rockchip,rk3566";
+
+ aliases {
+ ethernet0 = &gmac1;
+ mmc0 = &sdmmc0;
+ mmc1 = &sdmmc1;
+ mmc2 = &sdhci;
+ };
+
+ chosen: chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ gmac1_clkin: external-gmac1-clock {
+ compatible = "fixed-clock";
+ clock-frequency = <125000000>;
+ clock-output-names = "gmac1_clkin";
+ #clock-cells = <0>;
+ };
+
+ hdmi-con {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
+ ir-receiver {
+ compatible = "gpio-ir-receiver";
+ gpios = <&gpio4 RK_PC3 GPIO_ACTIVE_LOW>;
+ pinctrl-0 = <&ir_int>;
+ linux,rc-map-name = "rc-beelink-gs1";
+ status = "okay";
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led_work: led-0 {
+ gpios = <&gpio0 RK_PC3 GPIO_ACTIVE_HIGH>;
+ function = LED_FUNCTION_HEARTBEAT;
+ color = <LED_COLOR_ID_BLUE>;
+ linux,default-trigger = "heartbeat";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_work_en>;
+ };
+ };
+
+ sdio_pwrseq: sdio-pwrseq {
+ status = "okay";
+ compatible = "mmc-pwrseq-simple";
+ clocks = <&pmucru CLK_RTC_32K>;
+ clock-names = "ext_clock";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_enable_h &wifi_32k>;
+ reset-gpios = <&gpio2 RK_PB1 GPIO_ACTIVE_LOW>;
+ };
+
+ spdif_dit: spdif-dit {
+ compatible = "linux,spdif-dit";
+ #sound-dai-cells = <0>;
+ };
+
+ spdif_sound: spdif-sound {
+ compatible = "simple-audio-card";
+ simple-audio-card,name = "SPDIF";
+
+ simple-audio-card,cpu {
+ sound-dai = <&spdif>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&spdif_dit>;
+ };
+ };
+
+ vcc12v0_dcin: regulator-vcc12v0-dcin {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc12v0_dcin";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ };
+
+ vcc5v0_sys: regulator-vcc5v0-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc12v0_dcin>;
+ };
+
+ vcc3v3_sys: regulator-vcc3v3-sys {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc12v0_dcin>;
+ };
+
+ vcc_3v3: regulator-vcc-3v3 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc_3v3";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc3v3_sys>;
+ };
+
+ vcc5v0_usb_host: regulator-vcc5v0-usb-host {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc5v0_usb_host_en>;
+ regulator-name = "vcc5v0_usb_host";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc5v0_usb2_otg: regulator-vcc5v0-usb2-otg {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc5v0_usb2_otg_en>;
+ regulator-name = "vcc5v0_usb_otg";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcca_1v8: regulator-vcca-1v8 {
+ compatible = "regulator-fixed";
+ regulator-name = "vcca_1v8";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vcc3v3_sys>;
+ };
+
+ vdda_0v9: regulator-vdda-0v9 {
+ compatible = "regulator-fixed";
+ regulator-name = "vdda_0v9";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+ vin-supply = <&vcc3v3_sys>;
+ };
+
+ vdd_fixed: regulator-vdd-fixed {
+ compatible = "regulator-fixed";
+ regulator-name = "vdd_fixed";
+ regulator-min-microvolt = <950000>;
+ regulator-max-microvolt = <950000>;
+ regulator-always-on;
+ regulator-boot-on;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vdd_cpu: regulator-vdd-cpu {
+ compatible = "pwm-regulator";
+ pwms = <&pwm0 0 5000 1>;
+ regulator-name = "vdd_cpu";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1200000>;
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-settling-time-up-us = <250>;
+ pwm-supply = <&vcc5v0_sys>;
+ };
+
+ vdd_logic: regulator-vdd-logic {
+ compatible = "pwm-regulator";
+ pwms = <&pwm1 0 5000 1>;
+ regulator-name = "vdd_logic";
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1100000>;
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-settling-time-up-us = <250>;
+ pwm-supply = <&vcc5v0_sys>;
+ };
+};
+
+&combphy1 {
+ status = "okay";
+};
+
+&combphy2 {
+ status = "okay";
+};
+
+&cpu0 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&cpu1 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&cpu2 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&cpu3 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&gmac1 {
+ assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>;
+ assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>, <&gmac1_clkin>;
+ phy-mode = "rgmii";
+ clock_in_out = "input";
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac1m1_miim
+ &gmac1m1_tx_bus2
+ &gmac1m1_rx_bus2
+ &gmac1m1_rgmii_clk
+ &gmac1m1_rgmii_bus
+ &gmac1m1_clkinout>;
+ snps,reset-gpio = <&gpio4 RK_PC2 GPIO_ACTIVE_LOW>;
+ snps,reset-active-low;
+ /* Reset time is 20ms, 100ms for rtl8211f */
+ snps,reset-delays-us = <0 20000 100000>;
+
+ tx_delay = <0x4f>;
+ rx_delay = <0x2d>;
+ phy-handle = <&rgmii_phy1>;
+ status = "okay";
+};
+
+&mdio1 {
+ rgmii_phy1: ethernet-phy@1 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x1>;
+ };
+};
+
+&hdmi {
+ assigned-clocks = <&cru CLK_HDMI_CEC>;
+ assigned-clock-rates = <32768>;
+ avdd-0v9-supply = <&vdda_0v9>;
+ avdd-1v8-supply = <&vcca_1v8>;
+ status = "okay";
+};
+
+&hdmi_in {
+ hdmi_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi>;
+ };
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&hdmi_sound {
+ status = "okay";
+};
+
+&gpu {
+ status = "okay";
+};
+
+&i2s0_8ch {
+ status = "okay";
+};
+
+&i2s1_8ch {
+ rockchip,trcm-sync-tx-only;
+ status = "okay";
+};
+
+&pinctrl {
+ bt {
+ bt_enable_h: bt-enable-h {
+ rockchip,pins = <2 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bt_host_wake_l: bt-host-wake-l {
+ rockchip,pins = <2 RK_PC0 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+
+ bt_wake_l: bt-wake-l {
+ rockchip,pins = <2 RK_PC1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ sdio-pwrseq {
+ wifi_enable_h: wifi-enable-h {
+ rockchip,pins = <2 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ wifi_32k: wifi-32k {
+ rockchip,pins = <0 RK_PB0 2 &pcfg_pull_none>;
+ };
+ };
+
+ usb {
+ vcc5v0_usb_host_en: vcc5v0_usb_host_en {
+ rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ vcc5v0_usb2_otg_en: vcc5v0_usb2_otg_en {
+ rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ };
+
+ ir {
+ ir_int: ir-int {
+ rockchip,pins = <4 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ led {
+ led_work_en: led_work_en {
+ rockchip,pins = <0 RK_PC3 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&pwm0 {
+ status = "okay";
+};
+
+&pwm1 {
+ status = "okay";
+};
+
+&sdhci {
+ bus-width = <8>;
+ mmc-hs200-1_8v;
+ non-removable;
+ status = "okay";
+};
+
+&sdmmc0 {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>;
+ vmmc-supply = <&vcc_3v3>;
+ status = "okay";
+};
+
+&sdmmc1 {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ disable-wp;
+ mmc-pwrseq = <&sdio_pwrseq>;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc1_bus4 &sdmmc1_cmd &sdmmc1_clk>;
+ vmmc-supply = <&vcc_3v3>;
+ vqmmc-supply = <&vcca_1v8>;
+ status = "okay";
+};
+
+&spdif {
+ status = "okay";
+};
+
+&spi1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&spi1m1_cs0 &spi1m1_pins>;
+};
+
+&tsadc {
+ /* tshut mode 0:CRU 1:GPIO */
+ rockchip,hw-tshut-mode = <1>;
+ /* tshut polarity 0:LOW 1:HIGH */
+ rockchip,hw-tshut-polarity = <0>;
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1m0_xfer &uart1m0_ctsn>;
+ status = "okay";
+ uart-has-rtscts;
+
+ bluetooth {
+ compatible = "brcm,bcm43438-bt";
+ clocks = <&pmucru CLK_RTC_32K>;
+ clock-names = "ext_clock";
+ device-wake-gpios = <&gpio2 RK_PC1 GPIO_ACTIVE_HIGH>;
+ host-wake-gpios = <&gpio2 RK_PC0 GPIO_ACTIVE_HIGH>;
+ shutdown-gpios = <&gpio2 RK_PB7 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_host_wake_l &bt_wake_l &bt_enable_h>;
+ vbat-supply = <&vcc3v3_sys>;
+ vddio-supply = <&vcca_1v8>;
+ };
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&vop {
+ assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
+ assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi_in_vp0>;
+ };
+};
+
+&vpu {
+ status = "okay";
+};
+
+&vdpu_mmu {
+ status = "okay";
+};
+
+&usb2phy0_host {
+ phy-supply = <&vcc5v0_usb_host>;
+ status = "okay";
+};
+
+&usb2phy0_otg {
+ vbus-supply = <&vcc5v0_usb2_otg>;
+ status = "okay";
+};
+
+&usb2phy1_host {
+ phy-supply = <&vcc5v0_usb_host>;
+ status = "okay";
+};
+
+&usb2phy1_otg {
+ phy-supply = <&vcc5v0_usb_host>;
+ status = "okay";
+};
+
+&usb2phy1 {
+ status = "okay";
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+&usb_host1_ehci {
+ status = "okay";
+};
+
+&usb_host1_ohci {
+ status = "okay";
+};
+
+&usb_host1_xhci {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-roc-pc.dts b/arch/arm64/boot/dts/rockchip/rk3566-roc-pc.dts
index 9fd262334d77..61c7a3ad7387 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-roc-pc.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-roc-pc.dts
@@ -82,6 +82,18 @@
vin-supply = <&usb_5v>;
};
+ vcc3v3_pcie: vcc3v3-pcie-regulator {
+ compatible = "regulator-fixed";
+ enable-active-high;
+ gpio = <&gpio0 RK_PC4 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_enable_h>;
+ regulator-name = "vcc3v3_pcie";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
vcc3v3_sys: vcc3v3-sys-regulator {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
@@ -122,6 +134,10 @@
status = "okay";
};
+&combphy2 {
+ status = "okay";
+};
+
&cpu0 {
cpu-supply = <&vdd_cpu>;
};
@@ -443,6 +459,14 @@
};
};
+&pcie2x1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_reset_h>;
+ reset-gpios = <&gpio1 RK_PB2 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie>;
+ status = "okay";
+};
+
&pinctrl {
bt {
bt_enable_h: bt-enable-h {
@@ -464,6 +488,16 @@
};
};
+ pcie {
+ pcie_enable_h: pcie-enable-h {
+ rockchip,pins = <0 RK_PC4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ pcie_reset_h: pcie-reset-h {
+ rockchip,pins = <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
pmic {
pmic_int: pmic_int {
rockchip,pins =
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-blade.dts b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-blade.dts
new file mode 100644
index 000000000000..4e49bebf548b
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-blade.dts
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+
+#include "rk3566-soquartz.dtsi"
+
+/ {
+ model = "PINE64 RK3566 SOQuartz on Blade carrier board";
+ compatible = "pine64,soquartz-blade", "pine64,soquartz", "rockchip,rk3566";
+
+ /* labeled VCC3V0_SD in schematic to not conflict with PMIC regulator */
+ vcc3v0_sd: vcc3v0-sd-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v0_sd";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc3v3_sys>;
+ };
+
+ /* labeled VCC_SSD in schematic */
+ vcc3v3_pcie_p: vcc3v3-pcie-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_pcie_p";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vbus>;
+ };
+
+ vcc5v_dcin: vcc5v-dcin-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v_dcin";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ };
+};
+
+&combphy2 {
+ phy-supply = <&vcc3v3_sys>;
+ status = "okay";
+};
+
+&gmac1 {
+ status = "okay";
+};
+
+/*
+ * i2c1 is exposed on CM1 / Module1A
+ * pin 80 - SCL0 - i2c1_scl_m0, pullup to vcc3v3_pmu
+ * pin 82 - SDA0 - i2c1_sda_m0, pullup to vcc3v3_pmu
+ */
+&i2c1 {
+ status = "okay";
+
+};
+
+/*
+ * i2c2 is exposed on CM1 / Module1A - to PI40
+ * pin 56 - GPIO3 - i2c2_scl_m1, pullup to vcc_3v3, shared with i2s1_8ch
+ * pin 58 - GPIO2 - i2c2_sda_m1, pullup to vcc_3v3
+ */
+&i2c2 {
+ status = "disabled";
+};
+
+/*
+ * i2c3 is exposed on CM1 / Module1A - to PI40
+ * pin 35 - ID_SC(GPIO28) - i2c3_scl_m0, pullup to vcc_3v3
+ * pin 36 - ID_SD(GPIO27) - i2c3_sda_m0, pullup to vcc_3v3
+ */
+&i2c3 {
+ status = "disabled";
+};
+
+/*
+ * i2c4 is exposed on CM2 / Module1B - to PI40
+ * pin 45 - GPIO24 - i2c4_scl_m1
+ * pin 47 - GPIO23 - i2c4_sda_m1
+ */
+&i2c4 {
+ status = "disabled";
+};
+
+/*
+ * i2s1_8ch is exposed on CM1 / Module1A - to PI40
+ * pin 24 - GPIO26 - i2s1_sdi1_m1
+ * pin 25 - GPIO21 - i2s1_sdo0_m1
+ * pin 26 - GPIO19 - i2s1_lrck_tx_m1
+ * pin 27 - GPIO20 - i2s1_sdi0_m1
+ * pin 29 - GPIO16 - i2s1_sdi3_m1
+ * pin 30 - GPIO6 - i2s1_sdi2_m1
+ * pin 40 - GPIO9 - i2s1_sdo1_m1, shared with spi3
+ * pin 41 - GPIO25 - i2s1_sdo2_m1
+ * pin 49 - GPIO18 - i2s1_sclk_tx_m1
+ * pin 50 - GPIO17 - i2s1_mclk_m1
+ * pin 56 - GPIO3 - i2s1_sdo3_m1, shared with i2c2
+ */
+&i2s1_8ch {
+ status = "disabled";
+};
+
+&led_diy {
+ color = <LED_COLOR_ID_RED>;
+ function = LED_FUNCTION_DISK_ACTIVITY;
+ linux,default-trigger = "disk-activity";
+ status = "okay";
+};
+
+&led_work {
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_STATUS;
+ linux,default-trigger = "heartbeat";
+ status = "okay";
+};
+
+&pcie2x1 {
+ vpcie3v3-supply = <&vcc3v3_pcie_p>;
+ status = "okay";
+};
+
+&rgmii_phy1 {
+ status = "okay";
+};
+
+/*
+ * saradc is exposed on CM1 / Module1A - to J2
+ * pin 94 - AIN1 - saradc_vin3
+ * pin 96 - AIN0 - saradc_vin2
+ */
+&saradc {
+ status = "disabled";
+};
+
+&sdmmc0 {
+ vmmc-supply = <&vcc3v0_sd>;
+ status = "okay";
+};
+
+/*
+ * spi3 is exposed on CM1 / Module1A - to PI40
+ * pin 37 - GPIO7 - spi3_cs1_m0
+ * pin 38 - GPIO11 - spi3_clk_m0
+ * pin 39 - GPIO8 - spi3_cs0_m0
+ * pin 40 - GPIO9 - spi3_miso_m0, shared with i2s1_8ch
+ * pin 44 - GPIO10 - spi3_mosi_m0
+ */
+&spi3 {
+ status = "disabled";
+};
+
+/*
+ * uart2 is exposed on CM1 / Module1A - to PI40
+ * pin 51 - GPIO15 - uart2_rx_m0
+ * pin 55 - GPIO14 - uart2_tx_m0
+ */
+&uart2 {
+ status = "okay";
+};
+
+/*
+ * uart7 is exposed on CM1 / Module1A - to PI40
+ * pin 46 - GPIO22 - uart7_tx_m2
+ * pin 47 - GPIO23 - uart7_rx_m2
+ */
+&uart7 {
+ status = "okay";
+};
+
+&usb2phy0 {
+ status = "okay";
+};
+
+&usb2phy0_otg {
+ phy-supply = <&vbus>;
+ status = "okay";
+};
+
+&usb_host0_xhci {
+ status = "okay";
+};
+
+&vbus {
+ vin-supply = <&vcc5v_dcin>;
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts
index e00568a6be5c..263ce40770dd 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-cm4.dts
@@ -30,6 +30,12 @@
};
};
+/* phy for pcie */
+&combphy2 {
+ phy-supply = <&vcc3v3_sys>;
+ status = "okay";
+};
+
&gmac1 {
status = "okay";
};
@@ -105,6 +111,11 @@
status = "okay";
};
+&pcie2x1 {
+ vpcie3v3-supply = <&vcc_3v3>;
+ status = "okay";
+};
+
&rgmii_phy1 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz-model-a.dts b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-model-a.dts
new file mode 100644
index 000000000000..2208dbfb7f0a
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz-model-a.dts
@@ -0,0 +1,232 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+
+/dts-v1/;
+
+#include "rk3566-soquartz.dtsi"
+
+/ {
+ model = "PINE64 RK3566 SOQuartz on Model A carrier board";
+ compatible = "pine64,soquartz-model-a", "pine64,soquartz", "rockchip,rk3566";
+
+ /* labeled DCIN_12V in schematic */
+ vcc12v_dcin: vcc12v-dcin-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc12v_dcin";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ };
+
+ vcc5v0_usb: vcc5v0-usb-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_usb";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc12v_dcin>;
+ };
+
+ /*
+ * Labelled VCC3V0_SD in schematic to not conflict with PMIC
+ * regulator, it's 3.3v in actuality
+ */
+ vcc3v0_sd: vcc3v0-sd-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v0_sd";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc3v3_sys>;
+ };
+
+ vcc3v3_pcie: vcc3v3-pcie-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_pcie";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc12v_dcin>;
+ };
+
+ vcc12v_pcie: vcc12v-pcie-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc12v_pcie";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ vin-supply = <&vcc12v_dcin>;
+ };
+};
+
+/* phy for pcie */
+&combphy2 {
+ phy-supply = <&vcc3v3_sys>;
+ status = "okay";
+};
+
+&gmac1 {
+ status = "okay";
+};
+
+/*
+ * i2c1 is exposed on CM1 / Module1A
+ * pin 80 - SCL0 - i2c1_scl_m0, pullup to vcc3v3_pmu
+ * pin 82 - SDA0 - i2c1_sda_m0, pullup to vcc3v3_pmu
+ */
+&i2c1 {
+ status = "okay";
+
+ /*
+ * the rtc interrupt is tied to PMIC_PWRON,
+ * it will force reset the board if triggered.
+ */
+ pcf85063: rtc@51 {
+ compatible = "nxp,pcf85063";
+ reg = <0x51>;
+ };
+};
+
+/*
+ * i2c2 is exposed on CM1 / Module1A - to PI40
+ * pin 56 - GPIO3 - i2c2_scl_m1, pullup to vcc_3v3, shared with i2s1_8ch
+ * pin 58 - GPIO2 - i2c2_sda_m1, pullup to vcc_3v3
+ */
+&i2c2 {
+ status = "disabled";
+};
+
+/*
+ * i2c3 is exposed on CM1 / Module1A - to PI40
+ * pin 35 - ID_SC(GPIO28) - i2c3_scl_m0, pullup to vcc_3v3
+ * pin 36 - ID_SD(GPIO27) - i2c3_sda_m0, pullup to vcc_3v3
+ */
+&i2c3 {
+ status = "disabled";
+};
+
+/*
+ * i2c4 is exposed on CM2 / Module1B - to PI40
+ * pin 45 - GPIO24 - i2c4_scl_m1
+ * pin 47 - GPIO23 - i2c4_sda_m1
+ */
+&i2c4 {
+ status = "disabled";
+};
+
+/*
+ * i2s1_8ch is exposed on CM1 / Module1A - to PI40
+ * pin 24 - GPIO26 - i2s1_sdi1_m1
+ * pin 25 - GPIO21 - i2s1_sdo0_m1
+ * pin 26 - GPIO19 - i2s1_lrck_tx_m1
+ * pin 27 - GPIO20 - i2s1_sdi0_m1
+ * pin 29 - GPIO16 - i2s1_sdi3_m1
+ * pin 30 - GPIO6 - i2s1_sdi2_m1
+ * pin 40 - GPIO9 - i2s1_sdo1_m1, shared with spi3
+ * pin 41 - GPIO25 - i2s1_sdo2_m1
+ * pin 49 - GPIO18 - i2s1_sclk_tx_m1
+ * pin 50 - GPIO17 - i2s1_mclk_m1
+ * pin 56 - GPIO3 - i2s1_sdo3_m1, shared with i2c2
+ */
+&i2s1_8ch {
+ status = "disabled";
+};
+
+&led_diy {
+ status = "okay";
+};
+
+&led_work {
+ status = "okay";
+};
+
+&pcie2x1 {
+ vpcie3v3-supply = <&vcc3v3_pcie>;
+ status = "okay";
+};
+
+&rgmii_phy1 {
+ status = "okay";
+};
+
+&rgmii_phy1 {
+ status = "okay";
+};
+
+/*
+ * saradc is exposed on CM1 / Module1A - to J2
+ * pin 94 - AIN1 - saradc_vin3
+ * pin 96 - AIN0 - saradc_vin2
+ */
+&saradc {
+ status = "disabled";
+};
+
+/*
+ * vmmc-supply is vcc3v3_sd on v1.0 and vcc3v0_sd on v1.1+
+ * the soquartz SoM has SDMMC_PWR (CM1 pin 75) hardwired to vcc3v3_sys,
+ * so we use vcc3v3_sd here to ensure the regulator is enabled on older boards.
+ */
+&sdmmc0 {
+ vmmc-supply = <&vcc3v3_sd>;
+ status = "okay";
+};
+
+/*
+ * spi3 is exposed on CM1 / Module1A - to PI40
+ * pin 37 - GPIO7 - spi3_cs1_m0
+ * pin 38 - GPIO11 - spi3_clk_m0
+ * pin 39 - GPIO8 - spi3_cs0_m0
+ * pin 40 - GPIO9 - spi3_miso_m0, shared with i2s1_8ch
+ * pin 44 - GPIO10 - spi3_mosi_m0
+ */
+&spi3 {
+ status = "disabled";
+};
+
+/*
+ * uart2 is exposed on CM1 / Module1A - to PI40
+ * pin 51 - GPIO15 - uart2_rx_m0
+ * pin 55 - GPIO14 - uart2_tx_m0
+ */
+&uart2 {
+ status = "okay";
+};
+
+/*
+ * uart7 is exposed on CM1 / Module1A - to PI40
+ * pin 46 - GPIO22 - uart7_tx_m2
+ * pin 47 - GPIO23 - uart7_rx_m2
+ */
+&uart7 {
+ status = "okay";
+};
+
+&usb2phy0 {
+ status = "okay";
+};
+
+&usb2phy0_otg {
+ phy-supply = <&vcc5v0_usb>;
+ status = "okay";
+};
+
+&usb_host0_xhci {
+ status = "okay";
+};
+
+&vbus {
+ vin-supply = <&vcc5v0_usb>;
+};
+
+&vcc3v3_sd {
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi b/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
index 5bcd4be32964..ce7165d7f1a1 100644
--- a/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk3566-soquartz.dtsi
@@ -4,6 +4,7 @@
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
#include "rk3566.dtsi"
/ {
@@ -28,6 +29,17 @@
#clock-cells = <0>;
};
+ hdmi-con {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
leds {
compatible = "gpio-leds";
@@ -143,6 +155,33 @@
status = "disabled";
};
+&gpu {
+ mali-supply = <&vdd_gpu>;
+ status = "okay";
+};
+
+&hdmi {
+ avdd-0v9-supply = <&vdda0v9_image>;
+ avdd-1v8-supply = <&vcca1v8_image>;
+ status = "okay";
+};
+
+&hdmi_in {
+ hdmi_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi>;
+ };
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&hdmi_sound {
+ status = "okay";
+};
+
&i2c0 {
status = "okay";
@@ -411,6 +450,10 @@
status = "disabled";
};
+&i2s0_8ch {
+ status = "okay";
+};
+
/*
* i2s1_8ch is exposed on CM1 / Module1A
* pin 24 - i2s1_sdi1_m1
@@ -444,6 +487,12 @@
};
};
+&pcie2x1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_reset_h>;
+ reset-gpios = <&gpio1 RK_PB2 GPIO_ACTIVE_HIGH>;
+};
+
&pinctrl {
bt {
bt_enable_h: bt-enable-h {
@@ -469,6 +518,15 @@
};
};
+ pcie {
+ pcie_clkreq_h: pcie-clkreq-h {
+ rockchip,pins = <1 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ pcie_reset_h: pcie-reset-h {
+ rockchip,pins = <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
pmic {
pmic_int_l: pmic-int-l {
rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
@@ -614,3 +672,20 @@
&usb_host0_xhci {
status = "disabled";
};
+
+&vop {
+ assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
+ assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
new file mode 100644
index 000000000000..59ecf868dbd0
--- /dev/null
+++ b/arch/arm64/boot/dts/rockchip/rk3568-odroid-m1.dts
@@ -0,0 +1,744 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+/*
+ * Copyright (c) 2022 Hardkernel Co., Ltd.
+ *
+ */
+
+/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/soc/rockchip,vop2.h>
+#include "rk3568.dtsi"
+
+/ {
+ model = "Hardkernel ODROID-M1";
+ compatible = "rockchip,rk3568-odroid-m1", "rockchip,rk3568";
+
+ aliases {
+ ethernet0 = &gmac0;
+ i2c0 = &i2c3;
+ i2c3 = &i2c0;
+ mmc0 = &sdhci;
+ mmc1 = &sdmmc0;
+ serial0 = &uart1;
+ serial1 = &uart0;
+ };
+
+ chosen {
+ stdout-path = "serial2:1500000n8";
+ };
+
+ dc_12v: dc-12v-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "dc_12v";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ };
+
+ hdmi-con {
+ compatible = "hdmi-connector";
+ type = "a";
+
+ port {
+ hdmi_con_in: endpoint {
+ remote-endpoint = <&hdmi_out_con>;
+ };
+ };
+ };
+
+ ir-receiver {
+ compatible = "gpio-ir-receiver";
+ gpios = <&gpio0 RK_PC2 GPIO_ACTIVE_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&ir_receiver_pin>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led_power: led-0 {
+ gpios = <&gpio0 RK_PC6 GPIO_ACTIVE_HIGH>;
+ function = LED_FUNCTION_POWER;
+ color = <LED_COLOR_ID_RED>;
+ default-state = "keep";
+ linux,default-trigger = "default-on";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_power_pin>;
+ };
+ led_work: led-1 {
+ gpios = <&gpio0 RK_PB7 GPIO_ACTIVE_HIGH>;
+ function = LED_FUNCTION_HEARTBEAT;
+ color = <LED_COLOR_ID_BLUE>;
+ linux,default-trigger = "heartbeat";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_work_pin>;
+ };
+ };
+
+ rk809-sound {
+ compatible = "simple-audio-card";
+ pinctrl-names = "default";
+ pinctrl-0 = <&hp_det_pin>;
+ simple-audio-card,name = "Analog RK817";
+ simple-audio-card,format = "i2s";
+ simple-audio-card,hp-det-gpio = <&gpio0 RK_PB0 GPIO_ACTIVE_HIGH>;
+ simple-audio-card,mclk-fs = <256>;
+ simple-audio-card,widgets =
+ "Headphone", "Headphones",
+ "Speaker", "Speaker";
+ simple-audio-card,routing =
+ "Headphones", "HPOL",
+ "Headphones", "HPOR",
+ "Speaker", "SPKO";
+
+ simple-audio-card,cpu {
+ sound-dai = <&i2s1_8ch>;
+ };
+
+ simple-audio-card,codec {
+ sound-dai = <&rk809>;
+ };
+ };
+
+ vcc3v3_pcie: vcc3v3-pcie-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_pcie";
+ enable-active-high;
+ gpio = <&gpio4 RK_PA7 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc3v3_pcie_en_pin>;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ startup-delay-us = <5000>;
+ vin-supply = <&vcc3v3_sys>;
+ };
+
+ vcc3v3_sys: vcc3v3-sys-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&dc_12v>;
+ };
+
+ vcc5v0_sys: vcc5v0-sys-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_sys";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&dc_12v>;
+ };
+
+ vcc5v0_usb_host: vcc5v0-usb-host-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_usb_host";
+ enable-active-high;
+ gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc5v0_usb_host_en_pin>;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
+ vcc5v0_usb_otg: vcc5v0-usb-otg-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc5v0_usb_otg";
+ enable-active-high;
+ gpio = <&gpio0 RK_PA5 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&vcc5v0_usb_otg_en_pin>;
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+};
+
+&combphy0 {
+ /* Used for USB3 */
+ phy-supply = <&vcc5v0_usb_host>;
+ status = "okay";
+};
+
+&combphy1 {
+ /* Used for USB3 */
+ phy-supply = <&vcc5v0_usb_otg>;
+ status = "okay";
+};
+
+&combphy2 {
+ /* used for SATA */
+ status = "okay";
+};
+
+&cpu0 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&cpu1 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&cpu2 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&cpu3 {
+ cpu-supply = <&vdd_cpu>;
+};
+
+&gmac0 {
+ assigned-clocks = <&cru SCLK_GMAC0_RX_TX>, <&cru SCLK_GMAC0>;
+ assigned-clock-parents = <&cru SCLK_GMAC0_RGMII_SPEED>;
+ assigned-clock-rates = <0>, <125000000>;
+ clock_in_out = "output";
+ phy-handle = <&rgmii_phy0>;
+ phy-mode = "rgmii";
+ phy-supply = <&vcc3v3_sys>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&gmac0_miim
+ &gmac0_tx_bus2
+ &gmac0_rx_bus2
+ &gmac0_rgmii_clk
+ &gmac0_rgmii_bus>;
+ status = "okay";
+
+ tx_delay = <0x4f>;
+ rx_delay = <0x2d>;
+};
+
+&gpu {
+ mali-supply = <&vdd_gpu>;
+ status = "okay";
+};
+
+&hdmi {
+ avdd-0v9-supply = <&vdda0v9_image>;
+ avdd-1v8-supply = <&vcca1v8_image>;
+ status = "okay";
+};
+
+&hdmi_in {
+ hdmi_in_vp0: endpoint {
+ remote-endpoint = <&vp0_out_hdmi>;
+ };
+};
+
+&hdmi_out {
+ hdmi_out_con: endpoint {
+ remote-endpoint = <&hdmi_con_in>;
+ };
+};
+
+&hdmi_sound {
+ status = "okay";
+};
+
+&i2c0 {
+ status = "okay";
+
+ vdd_cpu: regulator@1c {
+ compatible = "tcs,tcs4525";
+ reg = <0x1c>;
+ fcs,suspend-voltage-selector = <1>;
+ regulator-name = "vdd_cpu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <800000>;
+ regulator-max-microvolt = <1150000>;
+ regulator-ramp-delay = <2300>;
+ vin-supply = <&vcc3v3_sys>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ rk809: pmic@20 {
+ compatible = "rockchip,rk809";
+ reg = <0x20>;
+ interrupt-parent = <&gpio0>;
+ interrupts = <RK_PA3 IRQ_TYPE_LEVEL_LOW>;
+ assigned-clocks = <&cru I2S1_MCLKOUT_TX>;
+ assigned-clock-parents = <&cru CLK_I2S1_8CH_TX>;
+ #clock-cells = <1>;
+ clock-names = "mclk";
+ clocks = <&cru I2S1_MCLKOUT_TX>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pmic_int_l>, <&i2s1m0_mclk>;
+ rockchip,system-power-controller;
+ #sound-dai-cells = <0>;
+ vcc1-supply = <&vcc3v3_sys>;
+ vcc2-supply = <&vcc3v3_sys>;
+ vcc3-supply = <&vcc3v3_sys>;
+ vcc4-supply = <&vcc3v3_sys>;
+ vcc5-supply = <&vcc3v3_sys>;
+ vcc6-supply = <&vcc3v3_sys>;
+ vcc7-supply = <&vcc3v3_sys>;
+ vcc8-supply = <&vcc3v3_sys>;
+ vcc9-supply = <&vcc3v3_sys>;
+ wakeup-source;
+
+ regulators {
+ vdd_logic: DCDC_REG1 {
+ regulator-name = "vdd_logic";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-init-microvolt = <900000>;
+ regulator-initial-mode = <0x2>;
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <6001>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdd_gpu: DCDC_REG2 {
+ regulator-name = "vdd_gpu";
+ regulator-always-on;
+ regulator-init-microvolt = <900000>;
+ regulator-initial-mode = <0x2>;
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <6001>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_ddr: DCDC_REG3 {
+ regulator-name = "vcc_ddr";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-initial-mode = <0x2>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ };
+ };
+
+ vdd_npu: DCDC_REG4 {
+ regulator-name = "vdd_npu";
+ regulator-init-microvolt = <900000>;
+ regulator-initial-mode = <0x2>;
+ regulator-min-microvolt = <500000>;
+ regulator-max-microvolt = <1350000>;
+ regulator-ramp-delay = <6001>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_1v8: DCDC_REG5 {
+ regulator-name = "vcc_1v8";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdda0v9_image: LDO_REG1 {
+ regulator-name = "vdda0v9_image";
+ regulator-always-on;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdda_0v9: LDO_REG2 {
+ regulator-name = "vdda_0v9";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vdda0v9_pmu: LDO_REG3 {
+ regulator-name = "vdda0v9_pmu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <900000>;
+ };
+ };
+
+ vccio_acodec: LDO_REG4 {
+ regulator-name = "vccio_acodec";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vccio_sd: LDO_REG5 {
+ regulator-name = "vccio_sd";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc3v3_pmu: LDO_REG6 {
+ regulator-name = "vcc3v3_pmu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <3300000>;
+ };
+ };
+
+ vcca_1v8: LDO_REG7 {
+ regulator-name = "vcca_1v8";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcca1v8_pmu: LDO_REG8 {
+ regulator-name = "vcca1v8_pmu";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-on-in-suspend;
+ regulator-suspend-microvolt = <1800000>;
+ };
+ };
+
+ vcca1v8_image: LDO_REG9 {
+ regulator-name = "vcca1v8_image";
+ regulator-always-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc_3v3: SWITCH_REG1 {
+ regulator-name = "vcc_3v3";
+ regulator-always-on;
+ regulator-boot-on;
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+
+ vcc3v3_sd: SWITCH_REG2 {
+ regulator-name = "vcc3v3_sd";
+
+ regulator-state-mem {
+ regulator-off-in-suspend;
+ };
+ };
+ };
+ };
+};
+
+&i2s0_8ch {
+ status = "okay";
+};
+
+&i2s1_8ch {
+ rockchip,trcm-sync-tx-only;
+ status = "okay";
+};
+
+&mdio0 {
+ rgmii_phy0: ethernet-phy@0 {
+ compatible = "ethernet-phy-ieee802.3-c22";
+ reg = <0x0>;
+ reset-assert-us = <20000>;
+ reset-deassert-us = <100000>;
+ reset-gpios = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>;
+ };
+};
+
+&pcie30phy {
+ status = "okay";
+};
+
+&pcie3x2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_reset_pin>;
+ reset-gpios = <&gpio2 RK_PD6 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie>;
+ status = "okay";
+};
+
+&pinctrl {
+ fspi {
+ fspi_dual_io_pins: fspi-dual-io-pins {
+ rockchip,pins =
+ /* fspi_clk */
+ <1 RK_PD0 1 &pcfg_pull_none>,
+ /* fspi_cs0n */
+ <1 RK_PD3 1 &pcfg_pull_none>,
+ /* fspi_d0 */
+ <1 RK_PD1 1 &pcfg_pull_none>,
+ /* fspi_d1 */
+ <1 RK_PD2 1 &pcfg_pull_none>;
+ };
+ };
+
+ ir-receiver {
+ ir_receiver_pin: ir-receiver-pin {
+ /* external pullup to VCC3V3_SYS */
+ rockchip,pins = <0 RK_PC2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ leds {
+ led_power_pin: led-power-pin {
+ rockchip,pins = <0 RK_PC6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ led_work_pin: led-work-pin {
+ rockchip,pins = <0 RK_PB7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pcie {
+ pcie_reset_pin: pcie-reset-pin {
+ rockchip,pins = <2 RK_PD6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ vcc3v3_pcie_en_pin: vcc3v3-pcie-en-pin {
+ rockchip,pins = <4 RK_PA7 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ pmic {
+ pmic_int_l: pmic-int-l {
+ rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
+ };
+ };
+
+ rk809 {
+ hp_det_pin: hp-det-pin {
+ rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ usb {
+ vcc5v0_usb_host_en_pin: vcc5v0-usb-host-en-pin {
+ rockchip,pins = <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ vcc5v0_usb_otg_en_pin: vcc5v0-usb-dr-en-pin {
+ rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+};
+
+&pmu_io_domains {
+ pmuio1-supply = <&vcc3v3_pmu>;
+ pmuio2-supply = <&vcc3v3_pmu>;
+ vccio1-supply = <&vccio_acodec>;
+ vccio2-supply = <&vcc_1v8>;
+ vccio3-supply = <&vccio_sd>;
+ vccio4-supply = <&vcc_1v8>;
+ vccio5-supply = <&vcc_3v3>;
+ vccio6-supply = <&vcc_3v3>;
+ vccio7-supply = <&vcc_3v3>;
+ status = "okay";
+};
+
+&saradc {
+ vref-supply = <&vcca_1v8>;
+ status = "okay";
+};
+
+&sata2 {
+ status = "okay";
+};
+
+&sdhci {
+ bus-width = <8>;
+ max-frequency = <200000000>;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&emmc_bus8 &emmc_clk &emmc_cmd &emmc_datastrobe &emmc_rstnout>;
+ vmmc-supply = <&vcc_3v3>;
+ vqmmc-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
+&sdmmc0 {
+ bus-width = <4>;
+ cap-sd-highspeed;
+ cd-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
+ disable-wp;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc0_bus4 &sdmmc0_clk &sdmmc0_cmd &sdmmc0_det>;
+ sd-uhs-sdr50;
+ vmmc-supply = <&vcc3v3_sd>;
+ vqmmc-supply = <&vccio_sd>;
+ status = "okay";
+};
+
+&sfc {
+ /* Dual I/O mode as the D2 pin conflicts with the eMMC */
+ pinctrl-0 = <&fspi_dual_io_pins>;
+ pinctrl-names = "default";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "okay";
+
+ flash@0 {
+ compatible = "jedec,spi-nor";
+ reg = <0>;
+ spi-max-frequency = <100000000>;
+ spi-rx-bus-width = <2>;
+ spi-tx-bus-width = <1>;
+
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "SPL";
+ reg = <0x0 0xe0000>;
+ };
+ partition@e0000 {
+ label = "U-Boot Env";
+ reg = <0xe0000 0x20000>;
+ };
+ partition@100000 {
+ label = "U-Boot";
+ reg = <0x100000 0x200000>;
+ };
+ partition@300000 {
+ label = "splash";
+ reg = <0x300000 0x100000>;
+ };
+ partition@400000 {
+ label = "Filesystem";
+ reg = <0x400000 0xc00000>;
+ };
+ };
+ };
+};
+
+&tsadc {
+ rockchip,hw-tshut-mode = <1>;
+ rockchip,hw-tshut-polarity = <0>;
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
+
+&usb_host0_ehci {
+ status = "okay";
+};
+
+&usb_host0_ohci {
+ status = "okay";
+};
+
+&usb_host0_xhci {
+ dr_mode = "host";
+ status = "okay";
+};
+
+&usb_host1_ehci {
+ status = "okay";
+};
+
+&usb_host1_ohci {
+ status = "okay";
+};
+
+&usb_host1_xhci {
+ status = "okay";
+};
+
+&usb2phy0 {
+ status = "okay";
+};
+
+&usb2phy0_host {
+ phy-supply = <&vcc5v0_usb_host>;
+ status = "okay";
+};
+
+&usb2phy0_otg {
+ phy-supply = <&vcc5v0_usb_otg>;
+ status = "okay";
+};
+
+&usb2phy1 {
+ status = "okay";
+};
+
+&usb2phy1_host {
+ phy-supply = <&vcc5v0_usb_host>;
+ status = "okay";
+};
+
+&usb2phy1_otg {
+ phy-supply = <&vcc5v0_usb_host>;
+ status = "okay";
+};
+
+&vop {
+ assigned-clocks = <&cru DCLK_VOP0>, <&cru DCLK_VOP1>;
+ assigned-clock-parents = <&pmucru PLL_HPLL>, <&cru PLL_VPLL>;
+ status = "okay";
+};
+
+&vop_mmu {
+ status = "okay";
+};
+
+&vp0 {
+ vp0_out_hdmi: endpoint@ROCKCHIP_VOP2_EP_HDMI0 {
+ reg = <ROCKCHIP_VOP2_EP_HDMI0>;
+ remote-endpoint = <&hdmi_in_vp0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts b/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts
index 539ef8cc7792..a1c5fdf7d68f 100644
--- a/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts
+++ b/arch/arm64/boot/dts/rockchip/rk3568-rock-3a.dts
@@ -32,6 +32,13 @@
};
};
+ gmac1_clkin: external-gmac1-clock {
+ compatible = "fixed-clock";
+ clock-frequency = <125000000>;
+ clock-output-names = "gmac1_clkin";
+ #clock-cells = <0>;
+ };
+
leds {
compatible = "gpio-leds";
@@ -60,13 +67,55 @@
};
};
- vcc12v_dcin: vcc12v-dcin {
+ sdio_pwrseq: sdio-pwrseq {
+ compatible = "mmc-pwrseq-simple";
+ clocks = <&rk809 1>;
+ clock-names = "ext_clock";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wifi_enable>;
+ post-power-on-delay-ms = <100>;
+ power-off-delay-us = <5000000>;
+ reset-gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_LOW>;
+ };
+
+ vcc12v_dcin: vcc12v-dcin-regulator {
compatible = "regulator-fixed";
regulator-name = "vcc12v_dcin";
regulator-always-on;
regulator-boot-on;
};
+ pcie30_avdd0v9: pcie30-avdd0v9-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "pcie30_avdd0v9";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <900000>;
+ regulator-max-microvolt = <900000>;
+ vin-supply = <&vcc3v3_sys>;
+ };
+
+ pcie30_avdd1v8: pcie30-avdd1v8-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "pcie30_avdd1v8";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ vin-supply = <&vcc3v3_sys>;
+ };
+
+ /* pi6c pcie clock generator */
+ vcc3v3_pi6c_03: vcc3v3-pi6c-03-regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "vcc3v3_pi6c_03";
+ regulator-always-on;
+ regulator-boot-on;
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&vcc5v0_sys>;
+ };
+
vcc3v3_pcie: vcc3v3-pcie-regulator {
compatible = "regulator-fixed";
enable-active-high;
@@ -79,7 +128,7 @@
vin-supply = <&vcc5v0_sys>;
};
- vcc3v3_sys: vcc3v3-sys {
+ vcc3v3_sys: vcc3v3-sys-regulator {
compatible = "regulator-fixed";
regulator-name = "vcc3v3_sys";
regulator-always-on;
@@ -89,7 +138,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc5v0_sys: vcc5v0-sys {
+ vcc5v0_sys: vcc5v0-sys-regulator {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_sys";
regulator-always-on;
@@ -99,7 +148,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc5v0_usb: vcc5v0-usb {
+ vcc5v0_usb: vcc5v0-usb-regulator {
compatible = "regulator-fixed";
regulator-name = "vcc5v0_usb";
regulator-always-on;
@@ -109,7 +158,7 @@
vin-supply = <&vcc12v_dcin>;
};
- vcc5v0_usb_host: vcc5v0-usb-host {
+ vcc5v0_usb_host: vcc5v0-usb-host-regulator {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio0 RK_PA6 GPIO_ACTIVE_HIGH>;
@@ -144,7 +193,7 @@
vin-supply = <&vcc5v0_usb>;
};
- vcc_cam: vcc-cam {
+ vcc_cam: vcc-cam-regulator {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio1 RK_PB1 GPIO_ACTIVE_HIGH>;
@@ -160,7 +209,7 @@
};
};
- vcc_mipi: vcc-mipi {
+ vcc_mipi: vcc-mipi-regulator {
compatible = "regulator-fixed";
enable-active-high;
gpio = <&gpio3 RK_PC0 GPIO_ACTIVE_HIGH>;
@@ -207,16 +256,17 @@
&gmac1 {
assigned-clocks = <&cru SCLK_GMAC1_RX_TX>, <&cru SCLK_GMAC1>;
- assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>;
- assigned-clock-rates = <0>, <125000000>;
- clock_in_out = "output";
+ assigned-clock-parents = <&cru SCLK_GMAC1_RGMII_SPEED>, <&gmac1_clkin>;
+ clock_in_out = "input";
phy-handle = <&rgmii_phy1>;
phy-mode = "rgmii-id";
+ phy-supply = <&vcc_3v3>;
pinctrl-names = "default";
pinctrl-0 = <&gmac1m1_miim
&gmac1m1_tx_bus2
&gmac1m1_rx_bus2
&gmac1m1_rgmii_clk
+ &gmac1m1_clkinout
&gmac1m1_rgmii_bus>;
status = "okay";
};
@@ -525,6 +575,11 @@
status = "okay";
};
+&i2s2_2ch {
+ rockchip,trcm-sync-tx-only;
+ status = "okay";
+};
+
&mdio1 {
rgmii_phy1: ethernet-phy@0 {
compatible = "ethernet-phy-ieee802.3-c22";
@@ -545,6 +600,19 @@
status = "okay";
};
+&pcie30phy {
+ phy-supply = <&vcc3v3_pi6c_03>;
+ status = "okay";
+};
+
+&pcie3x2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie30x2m1_pins>;
+ reset-gpios = <&gpio2 RK_PD6 GPIO_ACTIVE_HIGH>;
+ vpcie3v3-supply = <&vcc3v3_pcie>;
+ status = "okay";
+};
+
&pinctrl {
cam {
vcc_cam_en: vcc_cam_en {
@@ -604,6 +672,26 @@
rockchip,pins = <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
};
};
+
+ bt {
+ bt_enable: bt-enable {
+ rockchip,pins = <4 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+
+ bt_host_wake: bt-host-wake {
+ rockchip,pins = <4 RK_PB4 RK_FUNC_GPIO &pcfg_pull_down>;
+ };
+
+ bt_wake: bt-wake {
+ rockchip,pins = <4 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
+
+ sdio-pwrseq {
+ wifi_enable: wifi-enable {
+ rockchip,pins = <3 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
+ };
+ };
};
&pmu_io_domains {
@@ -648,12 +736,50 @@
status = "okay";
};
+&sdmmc2 {
+ supports-sdio;
+ bus-width = <4>;
+ disable-wp;
+ cap-sd-highspeed;
+ cap-sdio-irq;
+ keep-power-in-suspend;
+ mmc-pwrseq = <&sdio_pwrseq>;
+ non-removable;
+ pinctrl-names = "default";
+ pinctrl-0 = <&sdmmc2m0_bus4 &sdmmc2m0_cmd &sdmmc2m0_clk>;
+ sd-uhs-sdr104;
+ vmmc-supply = <&vcc3v3_sys>;
+ vqmmc-supply = <&vcc_1v8>;
+ status = "okay";
+};
+
&tsadc {
rockchip,hw-tshut-mode = <1>;
rockchip,hw-tshut-polarity = <0>;
status = "okay";
};
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart1m0_xfer &uart1m0_ctsn &uart1m0_rtsn>;
+ uart-has-rtscts;
+ status = "okay";
+
+ bluetooth {
+ compatible = "brcm,bcm43438-bt";
+ clocks = <&rk809 1>;
+ clock-names = "lpo";
+ device-wakeup-gpios = <&gpio4 RK_PB5 GPIO_ACTIVE_HIGH>;
+ host-wakeup-gpios = <&gpio4 RK_PB4 GPIO_ACTIVE_HIGH>;
+ shutdown-gpios = <&gpio4 RK_PB2 GPIO_ACTIVE_HIGH>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&bt_host_wake &bt_wake &bt_enable>;
+ vbat-supply = <&vcc3v3_sys>;
+ vddio-supply = <&vcc_1v8>;
+ /* vddio comes from regulator on module, use IO bank voltage instead */
+ };
+};
+
&uart2 {
status = "okay";
};
diff --git a/arch/arm64/boot/dts/rockchip/rk356x.dtsi b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
index 164708f1eb67..5706c3e24f0a 100644
--- a/arch/arm64/boot/dts/rockchip/rk356x.dtsi
+++ b/arch/arm64/boot/dts/rockchip/rk356x.dtsi
@@ -1049,20 +1049,6 @@
status = "disabled";
};
- spdif: spdif@fe460000 {
- compatible = "rockchip,rk3568-spdif";
- reg = <0x0 0xfe460000 0x0 0x1000>;
- interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
- clock-names = "mclk", "hclk";
- clocks = <&cru MCLK_SPDIF_8CH>, <&cru HCLK_SPDIF_8CH>;
- dmas = <&dmac1 1>;
- dma-names = "tx";
- pinctrl-names = "default";
- pinctrl-0 = <&spdifm0_tx>;
- #sound-dai-cells = <0>;
- status = "disabled";
- };
-
i2s0_8ch: i2s@fe400000 {
compatible = "rockchip,rk3568-i2s-tdm";
reg = <0x0 0xfe400000 0x0 0x1000>;
@@ -1105,6 +1091,28 @@
status = "disabled";
};
+ i2s2_2ch: i2s@fe420000 {
+ compatible = "rockchip,rk3568-i2s-tdm";
+ reg = <0x0 0xfe420000 0x0 0x1000>;
+ interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+ assigned-clocks = <&cru CLK_I2S2_2CH_SRC>;
+ assigned-clock-rates = <1188000000>;
+ clocks = <&cru MCLK_I2S2_2CH>, <&cru MCLK_I2S2_2CH>, <&cru HCLK_I2S2_2CH>;
+ clock-names = "mclk_tx", "mclk_rx", "hclk";
+ dmas = <&dmac1 4>, <&dmac1 5>;
+ dma-names = "tx", "rx";
+ resets = <&cru SRST_M_I2S2_2CH>;
+ reset-names = "m";
+ rockchip,grf = <&grf>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2s2m0_sclktx
+ &i2s2m0_lrcktx
+ &i2s2m0_sdi
+ &i2s2m0_sdo>;
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
i2s3_2ch: i2s@fe430000 {
compatible = "rockchip,rk3568-i2s-tdm";
reg = <0x0 0xfe430000 0x0 0x1000>;
@@ -1142,6 +1150,20 @@
status = "disabled";
};
+ spdif: spdif@fe460000 {
+ compatible = "rockchip,rk3568-spdif";
+ reg = <0x0 0xfe460000 0x0 0x1000>;
+ interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
+ clock-names = "mclk", "hclk";
+ clocks = <&cru MCLK_SPDIF_8CH>, <&cru HCLK_SPDIF_8CH>;
+ dmas = <&dmac1 1>;
+ dma-names = "tx";
+ pinctrl-names = "default";
+ pinctrl-0 = <&spdifm0_tx>;
+ #sound-dai-cells = <0>;
+ status = "disabled";
+ };
+
dmac0: dma-controller@fe530000 {
compatible = "arm,pl330", "arm,primecell";
reg = <0x0 0xfe530000 0x0 0x4000>;
diff --git a/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi b/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi
index d0abb9aa0e9e..e3852c946352 100644
--- a/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/tesla/fsd-pinctrl.dtsi
@@ -55,14 +55,14 @@
samsung,pins = "gpf5-0";
samsung,pin-function = <FSD_PIN_FUNC_2>;
samsung,pin-pud = <FSD_PIN_PULL_NONE>;
- samsung,pin-drv = <FSD_PIN_DRV_LV2>;
+ samsung,pin-drv = <FSD_PIN_DRV_LV4>;
};
ufs_refclk_out: ufs-refclk-out-pins {
samsung,pins = "gpf5-1";
samsung,pin-function = <FSD_PIN_FUNC_2>;
samsung,pin-pud = <FSD_PIN_PULL_NONE>;
- samsung,pin-drv = <FSD_PIN_DRV_LV2>;
+ samsung,pin-drv = <FSD_PIN_DRV_LV4>;
};
};
@@ -239,105 +239,105 @@
samsung,pins = "gpb6-1";
samsung,pin-function = <FSD_PIN_FUNC_2>;
samsung,pin-pud = <FSD_PIN_PULL_UP>;
- samsung,pin-drv = <FSD_PIN_DRV_LV2>;
+ samsung,pin-drv = <FSD_PIN_DRV_LV4>;
};
pwm1_out: pwm1-out-pins {
samsung,pins = "gpb6-5";
samsung,pin-function = <FSD_PIN_FUNC_2>;
samsung,pin-pud = <FSD_PIN_PULL_UP>;
- samsung,pin-drv = <FSD_PIN_DRV_LV2>;
+ samsung,pin-drv = <FSD_PIN_DRV_LV4>;
};
hs_i2c0_bus: hs-i2c0-bus-pins {
samsung,pins = "gpb0-0", "gpb0-1";
samsung,pin-function = <FSD_PIN_FUNC_2>;
samsung,pin-pud = <FSD_PIN_PULL_UP>;
- samsung,pin-drv = <FSD_PIN_DRV_LV1>;
+ samsung,pin-drv = <FSD_PIN_DRV_LV4>;
};
hs_i2c1_bus: hs-i2c1-bus-pins {
samsung,pins = "gpb0-2", "gpb0-3";
samsung,pin-function = <FSD_PIN_FUNC_2>;
samsung,pin-pud = <FSD_PIN_PULL_UP>;
- samsung,pin-drv = <FSD_PIN_DRV_LV1>;
+ samsung,pin-drv = <FSD_PIN_DRV_LV4>;
};
hs_i2c2_bus: hs-i2c2-bus-pins {
samsung,pins = "gpb0-4", "gpb0-5";
samsung,pin-function = <FSD_PIN_FUNC_2>;
samsung,pin-pud = <FSD_PIN_PULL_UP>;
- samsung,pin-drv = <FSD_PIN_DRV_LV1>;
+ samsung,pin-drv = <FSD_PIN_DRV_LV4>;
};
hs_i2c3_bus: hs-i2c3-bus-pins {
samsung,pins = "gpb0-6", "gpb0-7";
samsung,pin-function = <FSD_PIN_FUNC_2>;
samsung,pin-pud = <FSD_PIN_PULL_UP>;
- samsung,pin-drv = <FSD_PIN_DRV_LV1>;
+ samsung,pin-drv = <FSD_PIN_DRV_LV4>;
};
hs_i2c4_bus: hs-i2c4-bus-pins {
samsung,pins = "gpb1-0", "gpb1-1";
samsung,pin-function = <FSD_PIN_FUNC_2>;
samsung,pin-pud = <FSD_PIN_PULL_UP>;
- samsung,pin-drv = <FSD_PIN_DRV_LV1>;
+ samsung,pin-drv = <FSD_PIN_DRV_LV4>;
};
hs_i2c5_bus: hs-i2c5-bus-pins {
samsung,pins = "gpb1-2", "gpb1-3";
samsung,pin-function = <FSD_PIN_FUNC_2>;
samsung,pin-pud = <FSD_PIN_PULL_UP>;
- samsung,pin-drv = <FSD_PIN_DRV_LV1>;
+ samsung,pin-drv = <FSD_PIN_DRV_LV4>;
};
hs_i2c6_bus: hs-i2c6-bus-pins {
samsung,pins = "gpb1-4", "gpb1-5";
samsung,pin-function = <FSD_PIN_FUNC_2>;
samsung,pin-pud = <FSD_PIN_PULL_UP>;
- samsung,pin-drv = <FSD_PIN_DRV_LV1>;
+ samsung,pin-drv = <FSD_PIN_DRV_LV4>;
};
hs_i2c7_bus: hs-i2c7-bus-pins {
samsung,pins = "gpb1-6", "gpb1-7";
samsung,pin-function = <FSD_PIN_FUNC_2>;
samsung,pin-pud = <FSD_PIN_PULL_UP>;
- samsung,pin-drv = <FSD_PIN_DRV_LV1>;
+ samsung,pin-drv = <FSD_PIN_DRV_LV4>;
};
uart0_data: uart0-data-pins {
samsung,pins = "gpb7-0", "gpb7-1";
samsung,pin-function = <FSD_PIN_FUNC_2>;
samsung,pin-pud = <FSD_PIN_PULL_NONE>;
- samsung,pin-drv = <FSD_PIN_DRV_LV1>;
+ samsung,pin-drv = <FSD_PIN_DRV_LV4>;
};
uart1_data: uart1-data-pins {
samsung,pins = "gpb7-4", "gpb7-5";
samsung,pin-function = <FSD_PIN_FUNC_2>;
samsung,pin-pud = <FSD_PIN_PULL_NONE>;
- samsung,pin-drv = <FSD_PIN_DRV_LV1>;
+ samsung,pin-drv = <FSD_PIN_DRV_LV4>;
};
spi0_bus: spi0-bus-pins {
samsung,pins = "gpb4-0", "gpb4-2", "gpb4-3";
samsung,pin-function = <FSD_PIN_FUNC_2>;
samsung,pin-pud = <FSD_PIN_PULL_UP>;
- samsung,pin-drv = <FSD_PIN_DRV_LV1>;
+ samsung,pin-drv = <FSD_PIN_DRV_LV4>;
};
spi1_bus: spi1-bus-pins {
samsung,pins = "gpb4-4", "gpb4-6", "gpb4-7";
samsung,pin-function = <FSD_PIN_FUNC_2>;
samsung,pin-pud = <FSD_PIN_PULL_UP>;
- samsung,pin-drv = <FSD_PIN_DRV_LV1>;
+ samsung,pin-drv = <FSD_PIN_DRV_LV4>;
};
spi2_bus: spi2-bus-pins {
samsung,pins = "gpb5-0", "gpb5-2", "gpb5-3";
samsung,pin-function = <FSD_PIN_FUNC_2>;
samsung,pin-pud = <FSD_PIN_PULL_UP>;
- samsung,pin-drv = <FSD_PIN_DRV_LV1>;
+ samsung,pin-drv = <FSD_PIN_DRV_LV4>;
};
};
diff --git a/arch/arm64/boot/dts/tesla/fsd-pinctrl.h b/arch/arm64/boot/dts/tesla/fsd-pinctrl.h
index 6ffbda362493..c397d02208a0 100644
--- a/arch/arm64/boot/dts/tesla/fsd-pinctrl.h
+++ b/arch/arm64/boot/dts/tesla/fsd-pinctrl.h
@@ -16,9 +16,9 @@
#define FSD_PIN_PULL_UP 3
#define FSD_PIN_DRV_LV1 0
-#define FSD_PIN_DRV_LV2 2
-#define FSD_PIN_DRV_LV3 1
-#define FSD_PIN_DRV_LV4 3
+#define FSD_PIN_DRV_LV2 1
+#define FSD_PIN_DRV_LV4 2
+#define FSD_PIN_DRV_LV6 3
#define FSD_PIN_FUNC_INPUT 0
#define FSD_PIN_FUNC_OUTPUT 1
diff --git a/arch/arm64/boot/dts/ti/Makefile b/arch/arm64/boot/dts/ti/Makefile
index 4555a5be2257..cf7c509538a4 100644
--- a/arch/arm64/boot/dts/ti/Makefile
+++ b/arch/arm64/boot/dts/ti/Makefile
@@ -12,6 +12,7 @@ dtb-$(CONFIG_ARCH_K3) += k3-am6528-iot2050-basic-pg2.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am6548-iot2050-advanced.dtb
dtb-$(CONFIG_ARCH_K3) += k3-am6548-iot2050-advanced-pg2.dtb
+dtb-$(CONFIG_ARCH_K3) += k3-j721e-beagleboneai64.dtb
dtb-$(CONFIG_ARCH_K3) += k3-j721e-common-proc-board.dtb
dtb-$(CONFIG_ARCH_K3) += k3-j721e-sk.dtb
diff --git a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
index 03660476364f..072903649d6e 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-main.dtsi
@@ -192,6 +192,102 @@
pinctrl-single,function-mask = <0xffffffff>;
};
+ main_timer0: timer@2400000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2400000 0x00 0x400>;
+ interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 36 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 36 2>;
+ assigned-clock-parents = <&k3_clks 36 3>;
+ power-domains = <&k3_pds 36 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer1: timer@2410000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2410000 0x00 0x400>;
+ interrupts = <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 37 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 37 2>;
+ assigned-clock-parents = <&k3_clks 37 3>;
+ power-domains = <&k3_pds 37 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer2: timer@2420000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2420000 0x00 0x400>;
+ interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 38 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 38 2>;
+ assigned-clock-parents = <&k3_clks 38 3>;
+ power-domains = <&k3_pds 38 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer3: timer@2430000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2430000 0x00 0x400>;
+ interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 39 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 39 2>;
+ assigned-clock-parents = <&k3_clks 39 3>;
+ power-domains = <&k3_pds 39 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer4: timer@2440000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2440000 0x00 0x400>;
+ interrupts = <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 40 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 40 2>;
+ assigned-clock-parents = <&k3_clks 40 3>;
+ power-domains = <&k3_pds 40 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer5: timer@2450000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2450000 0x00 0x400>;
+ interrupts = <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 41 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 41 2>;
+ assigned-clock-parents = <&k3_clks 41 3>;
+ power-domains = <&k3_pds 41 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer6: timer@2460000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2460000 0x00 0x400>;
+ interrupts = <GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 42 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 42 2>;
+ assigned-clock-parents = <&k3_clks 42 3>;
+ power-domains = <&k3_pds 42 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer7: timer@2470000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2470000 0x00 0x400>;
+ interrupts = <GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 43 2>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 43 2>;
+ assigned-clock-parents = <&k3_clks 43 3>;
+ power-domains = <&k3_pds 43 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
main_uart0: serial@2800000 {
compatible = "ti,am64-uart", "ti,am654-uart";
reg = <0x00 0x02800000 0x00 0x100>;
@@ -199,6 +295,7 @@
power-domains = <&k3_pds 146 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 146 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart1: serial@2810000 {
@@ -208,6 +305,7 @@
power-domains = <&k3_pds 152 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 152 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart2: serial@2820000 {
@@ -217,6 +315,7 @@
power-domains = <&k3_pds 153 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 153 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart3: serial@2830000 {
@@ -226,6 +325,7 @@
power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 154 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart4: serial@2840000 {
@@ -235,6 +335,7 @@
power-domains = <&k3_pds 155 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 155 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart5: serial@2850000 {
@@ -244,6 +345,7 @@
power-domains = <&k3_pds 156 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 156 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart6: serial@2860000 {
@@ -253,6 +355,7 @@
power-domains = <&k3_pds 158 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 158 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_i2c0: i2c@20000000 {
@@ -264,6 +367,7 @@
power-domains = <&k3_pds 102 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 102 2>;
clock-names = "fck";
+ status = "disabled";
};
main_i2c1: i2c@20010000 {
@@ -275,6 +379,7 @@
power-domains = <&k3_pds 103 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 103 2>;
clock-names = "fck";
+ status = "disabled";
};
main_i2c2: i2c@20020000 {
@@ -286,6 +391,7 @@
power-domains = <&k3_pds 104 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 104 2>;
clock-names = "fck";
+ status = "disabled";
};
main_i2c3: i2c@20030000 {
@@ -297,6 +403,7 @@
power-domains = <&k3_pds 105 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 105 2>;
clock-names = "fck";
+ status = "disabled";
};
main_spi0: spi@20100000 {
@@ -307,6 +414,7 @@
#size-cells = <0>;
power-domains = <&k3_pds 141 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 172 0>;
+ status = "disabled";
};
main_spi1: spi@20110000 {
@@ -317,6 +425,7 @@
#size-cells = <0>;
power-domains = <&k3_pds 142 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 173 0>;
+ status = "disabled";
};
main_spi2: spi@20120000 {
@@ -327,6 +436,7 @@
#size-cells = <0>;
power-domains = <&k3_pds 143 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 174 0>;
+ status = "disabled";
};
main_gpio_intr: interrupt-controller@a00000 {
@@ -393,6 +503,7 @@
ti,otap-del-sel-mmc-hs = <0x0>;
ti,otap-del-sel-ddr52 = <0x9>;
ti,otap-del-sel-hs200 = <0x6>;
+ status = "disabled";
};
sdhci1: mmc@fa00000 {
@@ -416,6 +527,7 @@
ti,itap-del-sel-sdr25 = <0x0>;
ti,clkbuf-sel = <0x7>;
bus-width = <4>;
+ status = "disabled";
};
sdhci2: mmc@fa20000 {
@@ -438,6 +550,7 @@
ti,itap-del-sel-sdr12 = <0x0>;
ti,itap-del-sel-sdr25 = <0x0>;
ti,clkbuf-sel = <0x7>;
+ status = "disabled";
};
fss: bus@fc00000 {
@@ -462,6 +575,7 @@
power-domains = <&k3_pds 75 TI_SCI_PD_EXCLUSIVE>;
#address-cells = <1>;
#size-cells = <0>;
+ status = "disabled";
};
};
@@ -520,6 +634,7 @@
clocks = <&k3_clks 13 0>;
clock-names = "fck";
bus_freq = <1000000>;
+ status = "disabled";
};
cpts@3d000 {
@@ -557,6 +672,7 @@
power-domains = <&k3_pds 51 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 51 0>;
clock-names = "fck";
+ status = "disabled";
};
ecap1: pwm@23110000 {
@@ -566,6 +682,7 @@
power-domains = <&k3_pds 52 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 52 0>;
clock-names = "fck";
+ status = "disabled";
};
ecap2: pwm@23120000 {
@@ -575,6 +692,7 @@
power-domains = <&k3_pds 53 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 53 0>;
clock-names = "fck";
+ status = "disabled";
};
main_mcan0: can@20701000 {
@@ -589,6 +707,7 @@
<GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
epwm0: pwm@23000000 {
@@ -598,6 +717,7 @@
power-domains = <&k3_pds 86 TI_SCI_PD_EXCLUSIVE>;
clocks = <&epwm_tbclk 0>, <&k3_clks 86 0>;
clock-names = "tbclk", "fck";
+ status = "disabled";
};
epwm1: pwm@23010000 {
@@ -607,6 +727,7 @@
power-domains = <&k3_pds 87 TI_SCI_PD_EXCLUSIVE>;
clocks = <&epwm_tbclk 1>, <&k3_clks 87 0>;
clock-names = "tbclk", "fck";
+ status = "disabled";
};
epwm2: pwm@23020000 {
@@ -616,5 +737,6 @@
power-domains = <&k3_pds 88 TI_SCI_PD_EXCLUSIVE>;
clocks = <&epwm_tbclk 2>, <&k3_clks 88 0>;
clock-names = "tbclk", "fck";
+ status = "disabled";
};
};
diff --git a/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi
index f56c803560f2..a427231527c3 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-mcu.dtsi
@@ -14,6 +14,51 @@
pinctrl-single,function-mask = <0xffffffff>;
};
+ /*
+ * The MCU domain timer interrupts are routed only to the ESM module,
+ * and not currently available for Linux. The MCU domain timers are
+ * of limited use without interrupts, and likely reserved by the ESM.
+ */
+ mcu_timer0: timer@4800000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x4800000 0x00 0x400>;
+ clocks = <&k3_clks 35 2>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 35 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ status = "reserved";
+ };
+
+ mcu_timer1: timer@4810000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x4810000 0x00 0x400>;
+ clocks = <&k3_clks 48 2>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 48 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ status = "reserved";
+ };
+
+ mcu_timer2: timer@4820000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x4820000 0x00 0x400>;
+ clocks = <&k3_clks 49 2>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 49 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ status = "reserved";
+ };
+
+ mcu_timer3: timer@4830000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x4830000 0x00 0x400>;
+ clocks = <&k3_clks 50 2>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 50 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ status = "reserved";
+ };
+
mcu_uart0: serial@4a00000 {
compatible = "ti,am64-uart", "ti,am654-uart";
reg = <0x00 0x04a00000 0x00 0x100>;
@@ -21,6 +66,7 @@
power-domains = <&k3_pds 149 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 149 0>;
clock-names = "fclk";
+ status = "disabled";
};
mcu_i2c0: i2c@4900000 {
@@ -32,6 +78,7 @@
power-domains = <&k3_pds 106 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 106 2>;
clock-names = "fck";
+ status = "disabled";
};
mcu_spi0: spi@4b00000 {
@@ -42,6 +89,7 @@
#size-cells = <0>;
power-domains = <&k3_pds 147 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 147 0>;
+ status = "disabled";
};
mcu_spi1: spi@4b10000 {
@@ -52,6 +100,7 @@
#size-cells = <0>;
power-domains = <&k3_pds 148 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 148 0>;
+ status = "disabled";
};
mcu_gpio_intr: interrupt-controller@4210000 {
diff --git a/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi
index 4090134676cf..38dced6b4fef 100644
--- a/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62-wakeup.dtsi
@@ -26,16 +26,18 @@
power-domains = <&k3_pds 114 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 114 0>;
clock-names = "fclk";
+ status = "disabled";
};
wkup_i2c0: i2c@2b200000 {
compatible = "ti,am64-i2c", "ti,omap4-i2c";
- reg = <0x00 0x02b200000 0x00 0x100>;
+ reg = <0x00 0x2b200000 0x00 0x100>;
interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
power-domains = <&k3_pds 107 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 107 4>;
clock-names = "fck";
+ status = "disabled";
};
};
diff --git a/arch/arm64/boot/dts/ti/k3-am625-sk.dts b/arch/arm64/boot/dts/ti/k3-am625-sk.dts
index 93a5f0817efc..4f179b146cab 100644
--- a/arch/arm64/boot/dts/ti/k3-am625-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am625-sk.dts
@@ -31,6 +31,15 @@
bootargs = "console=ttyS2,115200n8 earlycon=ns16550a,mmio32,0x02800000";
};
+ opp-table {
+ /* Add 1.4GHz OPP for am625-sk board. Requires VDD_CORE to be at 0.85V */
+ opp-1400000000 {
+ opp-hz = /bits/ 64 <1400000000>;
+ opp-supported-hw = <0x01 0x0004>;
+ clock-latency-ns = <6000000>;
+ };
+ };
+
memory@80000000 {
device_type = "memory";
/* 2G RAM */
@@ -282,11 +291,8 @@
status = "reserved";
};
-&mcu_uart0 {
- status = "disabled";
-};
-
&main_uart0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_uart0_pins_default>;
};
@@ -296,41 +302,15 @@
status = "reserved";
};
-&main_uart2 {
- status = "disabled";
-};
-
-&main_uart3 {
- status = "disabled";
-};
-
-&main_uart4 {
- status = "disabled";
-};
-
-&main_uart5 {
- status = "disabled";
-};
-
-&main_uart6 {
- status = "disabled";
-};
-
-&mcu_i2c0 {
- status = "disabled";
-};
-
-&wkup_i2c0 {
- status = "disabled";
-};
-
&main_i2c0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c0_pins_default>;
clock-frequency = <400000>;
};
&main_i2c1 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c1_pins_default>;
clock-frequency = <400000>;
@@ -363,15 +343,8 @@
};
};
-&main_i2c2 {
- status = "disabled";
-};
-
-&main_i2c3 {
- status = "disabled";
-};
-
&sdhci0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_mmc0_pins_default>;
ti,driver-strength-ohm = <50>;
@@ -380,6 +353,7 @@
&sdhci1 {
/* SD/MMC */
+ status = "okay";
vmmc-supply = <&vdd_mmc1>;
vqmmc-supply = <&vdd_sd_dv>;
pinctrl-names = "default";
@@ -390,8 +364,7 @@
&cpsw3g {
pinctrl-names = "default";
- pinctrl-0 = <&main_mdio1_pins_default
- &main_rgmii1_pins_default
+ pinctrl-0 = <&main_rgmii1_pins_default
&main_rgmii2_pins_default>;
};
@@ -406,6 +379,10 @@
};
&cpsw3g_mdio {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mdio1_pins_default>;
+
cpsw3g_phy0: ethernet-phy@0 {
reg = <0>;
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
@@ -429,6 +406,7 @@
};
&ospi0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&ospi0_pins_default>;
@@ -486,31 +464,3 @@
};
};
};
-
-&ecap0 {
- status = "disabled";
-};
-
-&ecap1 {
- status = "disabled";
-};
-
-&ecap2 {
- status = "disabled";
-};
-
-&main_mcan0 {
- status = "disabled";
-};
-
-&epwm0 {
- status = "disabled";
-};
-
-&epwm1 {
- status = "disabled";
-};
-
-&epwm2 {
- status = "disabled";
-};
diff --git a/arch/arm64/boot/dts/ti/k3-am625.dtsi b/arch/arm64/boot/dts/ti/k3-am625.dtsi
index 887f31c23fef..cea2cc7de5dd 100644
--- a/arch/arm64/boot/dts/ti/k3-am625.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am625.dtsi
@@ -48,6 +48,8 @@
d-cache-line-size = <64>;
d-cache-sets = <128>;
next-level-cache = <&L2_0>;
+ operating-points-v2 = <&a53_opp_table>;
+ clocks = <&k3_clks 135 0>;
};
cpu1: cpu@1 {
@@ -62,6 +64,8 @@
d-cache-line-size = <64>;
d-cache-sets = <128>;
next-level-cache = <&L2_0>;
+ operating-points-v2 = <&a53_opp_table>;
+ clocks = <&k3_clks 136 0>;
};
cpu2: cpu@2 {
@@ -76,6 +80,8 @@
d-cache-line-size = <64>;
d-cache-sets = <128>;
next-level-cache = <&L2_0>;
+ operating-points-v2 = <&a53_opp_table>;
+ clocks = <&k3_clks 137 0>;
};
cpu3: cpu@3 {
@@ -90,6 +96,51 @@
d-cache-line-size = <64>;
d-cache-sets = <128>;
next-level-cache = <&L2_0>;
+ operating-points-v2 = <&a53_opp_table>;
+ clocks = <&k3_clks 138 0>;
+ };
+ };
+
+ a53_opp_table: opp-table {
+ compatible = "operating-points-v2-ti-cpu";
+ opp-shared;
+ syscon = <&wkup_conf>;
+
+ opp-200000000 {
+ opp-hz = /bits/ 64 <200000000>;
+ opp-supported-hw = <0x01 0x0007>;
+ clock-latency-ns = <6000000>;
+ };
+
+ opp-400000000 {
+ opp-hz = /bits/ 64 <400000000>;
+ opp-supported-hw = <0x01 0x0007>;
+ clock-latency-ns = <6000000>;
+ };
+
+ opp-600000000 {
+ opp-hz = /bits/ 64 <600000000>;
+ opp-supported-hw = <0x01 0x0007>;
+ clock-latency-ns = <6000000>;
+ };
+
+ opp-800000000 {
+ opp-hz = /bits/ 64 <800000000>;
+ opp-supported-hw = <0x01 0x0007>;
+ clock-latency-ns = <6000000>;
+ };
+
+ opp-1000000000 {
+ opp-hz = /bits/ 64 <1000000000>;
+ opp-supported-hw = <0x01 0x0006>;
+ clock-latency-ns = <6000000>;
+ };
+
+ opp-1250000000 {
+ opp-hz = /bits/ 64 <1250000000>;
+ opp-supported-hw = <0x01 0x0004>;
+ clock-latency-ns = <6000000>;
+ opp-suspend;
};
};
diff --git a/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi
index 99afac40e8d4..81d984414fd4 100644
--- a/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am62a-wakeup.dtsi
@@ -31,7 +31,7 @@
wkup_i2c0: i2c@2b200000 {
compatible = "ti,am64-i2c", "ti,omap4-i2c";
- reg = <0x00 0x02b200000 0x00 0x100>;
+ reg = <0x00 0x2b200000 0x00 0x100>;
interrupts = <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>;
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
index d6aa23681bbe..5e8036f32d79 100644
--- a/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am64-main.dtsi
@@ -237,6 +237,7 @@
power-domains = <&k3_pds 146 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 146 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart1: serial@2810000 {
@@ -248,6 +249,7 @@
power-domains = <&k3_pds 152 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 152 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart2: serial@2820000 {
@@ -259,6 +261,7 @@
power-domains = <&k3_pds 153 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 153 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart3: serial@2830000 {
@@ -270,6 +273,7 @@
power-domains = <&k3_pds 154 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 154 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart4: serial@2840000 {
@@ -281,6 +285,7 @@
power-domains = <&k3_pds 155 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 155 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart5: serial@2850000 {
@@ -292,6 +297,7 @@
power-domains = <&k3_pds 156 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 156 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart6: serial@2860000 {
@@ -303,6 +309,7 @@
power-domains = <&k3_pds 158 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 158 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_i2c0: i2c@20000000 {
@@ -314,6 +321,7 @@
power-domains = <&k3_pds 102 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 102 2>;
clock-names = "fck";
+ status = "disabled";
};
main_i2c1: i2c@20010000 {
@@ -325,6 +333,7 @@
power-domains = <&k3_pds 103 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 103 2>;
clock-names = "fck";
+ status = "disabled";
};
main_i2c2: i2c@20020000 {
@@ -336,6 +345,7 @@
power-domains = <&k3_pds 104 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 104 2>;
clock-names = "fck";
+ status = "disabled";
};
main_i2c3: i2c@20030000 {
@@ -347,6 +357,7 @@
power-domains = <&k3_pds 105 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 105 2>;
clock-names = "fck";
+ status = "disabled";
};
main_spi0: spi@20100000 {
@@ -359,6 +370,7 @@
clocks = <&k3_clks 141 0>;
dmas = <&main_pktdma 0xc300 0>, <&main_pktdma 0x4300 0>;
dma-names = "tx0", "rx0";
+ status = "disabled";
};
main_spi1: spi@20110000 {
@@ -369,6 +381,7 @@
#size-cells = <0>;
power-domains = <&k3_pds 142 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 142 0>;
+ status = "disabled";
};
main_spi2: spi@20120000 {
@@ -379,6 +392,7 @@
#size-cells = <0>;
power-domains = <&k3_pds 143 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 143 0>;
+ status = "disabled";
};
main_spi3: spi@20130000 {
@@ -389,6 +403,7 @@
#size-cells = <0>;
power-domains = <&k3_pds 144 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 144 0>;
+ status = "disabled";
};
main_spi4: spi@20140000 {
@@ -399,6 +414,7 @@
#size-cells = <0>;
power-domains = <&k3_pds 145 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 145 0>;
+ status = "disabled";
};
main_gpio_intr: interrupt-controller@a00000 {
@@ -536,6 +552,7 @@
clocks = <&k3_clks 13 0>;
clock-names = "fck";
bus_freq = <1000000>;
+ status = "disabled";
};
cpts@3d000 {
@@ -612,7 +629,7 @@
assigned-clocks = <&k3_clks 0 0>;
assigned-clock-parents = <&k3_clks 0 3>;
assigned-clock-rates = <60000000>;
- clock-names = "adc_tsc_fck";
+ clock-names = "fck";
adc {
#io-channel-cells = <1>;
@@ -855,6 +872,7 @@
ranges = <0x01000000 0x00 0x68001000 0x00 0x68001000 0x00 0x0010000>,
<0x02000000 0x00 0x68011000 0x00 0x68011000 0x00 0x7fef000>;
dma-ranges = <0x02000000 0x0 0x0 0x0 0x0 0x00000010 0x0>;
+ status = "disabled";
};
pcie0_ep: pcie-ep@f102000 {
@@ -873,6 +891,7 @@
clocks = <&k3_clks 114 0>;
clock-names = "fck";
max-functions = /bits/ 8 <1>;
+ status = "disabled";
};
epwm0: pwm@23000000 {
@@ -882,6 +901,7 @@
power-domains = <&k3_pds 86 TI_SCI_PD_EXCLUSIVE>;
clocks = <&epwm_tbclk 0>, <&k3_clks 86 0>;
clock-names = "tbclk", "fck";
+ status = "disabled";
};
epwm1: pwm@23010000 {
@@ -891,6 +911,7 @@
power-domains = <&k3_pds 87 TI_SCI_PD_EXCLUSIVE>;
clocks = <&epwm_tbclk 1>, <&k3_clks 87 0>;
clock-names = "tbclk", "fck";
+ status = "disabled";
};
epwm2: pwm@23020000 {
@@ -900,6 +921,7 @@
power-domains = <&k3_pds 88 TI_SCI_PD_EXCLUSIVE>;
clocks = <&epwm_tbclk 2>, <&k3_clks 88 0>;
clock-names = "tbclk", "fck";
+ status = "disabled";
};
epwm3: pwm@23030000 {
@@ -909,6 +931,7 @@
power-domains = <&k3_pds 89 TI_SCI_PD_EXCLUSIVE>;
clocks = <&epwm_tbclk 3>, <&k3_clks 89 0>;
clock-names = "tbclk", "fck";
+ status = "disabled";
};
epwm4: pwm@23040000 {
@@ -918,6 +941,7 @@
power-domains = <&k3_pds 90 TI_SCI_PD_EXCLUSIVE>;
clocks = <&epwm_tbclk 4>, <&k3_clks 90 0>;
clock-names = "tbclk", "fck";
+ status = "disabled";
};
epwm5: pwm@23050000 {
@@ -927,6 +951,7 @@
power-domains = <&k3_pds 91 TI_SCI_PD_EXCLUSIVE>;
clocks = <&epwm_tbclk 5>, <&k3_clks 91 0>;
clock-names = "tbclk", "fck";
+ status = "disabled";
};
epwm6: pwm@23060000 {
@@ -936,6 +961,7 @@
power-domains = <&k3_pds 92 TI_SCI_PD_EXCLUSIVE>;
clocks = <&epwm_tbclk 6>, <&k3_clks 92 0>;
clock-names = "tbclk", "fck";
+ status = "disabled";
};
epwm7: pwm@23070000 {
@@ -945,6 +971,7 @@
power-domains = <&k3_pds 93 TI_SCI_PD_EXCLUSIVE>;
clocks = <&epwm_tbclk 7>, <&k3_clks 93 0>;
clock-names = "tbclk", "fck";
+ status = "disabled";
};
epwm8: pwm@23080000 {
@@ -954,6 +981,7 @@
power-domains = <&k3_pds 94 TI_SCI_PD_EXCLUSIVE>;
clocks = <&epwm_tbclk 8>, <&k3_clks 94 0>;
clock-names = "tbclk", "fck";
+ status = "disabled";
};
ecap0: pwm@23100000 {
@@ -963,6 +991,7 @@
power-domains = <&k3_pds 51 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 51 0>;
clock-names = "fck";
+ status = "disabled";
};
ecap1: pwm@23110000 {
@@ -972,6 +1001,7 @@
power-domains = <&k3_pds 52 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 52 0>;
clock-names = "fck";
+ status = "disabled";
};
ecap2: pwm@23120000 {
@@ -981,6 +1011,7 @@
power-domains = <&k3_pds 53 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 53 0>;
clock-names = "fck";
+ status = "disabled";
};
main_rti0: watchdog@e000000 {
@@ -1138,6 +1169,7 @@
#address-cells = <1>;
#size-cells = <0>;
bus_freq = <1000000>;
+ status = "disabled";
};
};
@@ -1278,6 +1310,7 @@
clocks = <&k3_clks 82 0>;
clock-names = "fck";
bus_freq = <1000000>;
+ status = "disabled";
};
};
@@ -1293,6 +1326,7 @@
<GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan1: can@20711000 {
@@ -1307,6 +1341,7 @@
<GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
crypto: crypto@40900000 {
@@ -1324,7 +1359,6 @@
compatible = "inside-secure,safexcel-eip76";
reg = <0x00 0x40910000 0x00 0x7d>;
interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 133 1>;
status = "disabled"; /* Used by OP-TEE */
};
};
@@ -1334,8 +1368,8 @@
power-domains = <&k3_pds 80 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 80 0>;
clock-names = "fck";
- reg = <0x00 0x03b000000 0x00 0x400>,
- <0x00 0x050000000 0x00 0x8000000>;
+ reg = <0x00 0x3b000000 0x00 0x400>,
+ <0x00 0x50000000 0x00 0x8000000>;
reg-names = "cfg", "data";
interrupts = <GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>;
gpmc,num-cs = <3>;
@@ -1346,6 +1380,7 @@
#interrupt-cells = <2>;
gpio-controller;
#gpio-cells = <2>;
+ status = "disabled";
};
elm0: ecc@25010000 {
@@ -1355,5 +1390,6 @@
power-domains = <&k3_pds 54 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 54 0>;
clock-names = "fck";
+ status = "disabled";
};
};
diff --git a/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi
index 02d4285acbb8..38ddf0b3b8a0 100644
--- a/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am64-mcu.dtsi
@@ -14,6 +14,7 @@
power-domains = <&k3_pds 149 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 149 0>;
clock-names = "fclk";
+ status = "disabled";
};
mcu_uart1: serial@4a10000 {
@@ -24,6 +25,7 @@
power-domains = <&k3_pds 160 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 160 0>;
clock-names = "fclk";
+ status = "disabled";
};
mcu_i2c0: i2c@4900000 {
@@ -35,6 +37,7 @@
power-domains = <&k3_pds 106 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 106 2>;
clock-names = "fck";
+ status = "disabled";
};
mcu_i2c1: i2c@4910000 {
@@ -46,6 +49,7 @@
power-domains = <&k3_pds 107 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 107 2>;
clock-names = "fck";
+ status = "disabled";
};
mcu_spi0: spi@4b00000 {
@@ -56,6 +60,7 @@
#size-cells = <0>;
power-domains = <&k3_pds 147 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 147 0>;
+ status = "disabled";
};
mcu_spi1: spi@4b10000 {
@@ -66,6 +71,7 @@
#size-cells = <0>;
power-domains = <&k3_pds 148 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 148 0>;
+ status = "disabled";
};
mcu_gpio_intr: interrupt-controller@4210000 {
diff --git a/arch/arm64/boot/dts/ti/k3-am642-evm.dts b/arch/arm64/boot/dts/ti/k3-am642-evm.dts
index 5cf913860f80..39feea78a084 100644
--- a/arch/arm64/boot/dts/ti/k3-am642-evm.dts
+++ b/arch/arm64/boot/dts/ti/k3-am642-evm.dts
@@ -325,6 +325,7 @@
};
&main_uart0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_uart0_pins_default>;
};
@@ -334,35 +335,8 @@
status = "reserved";
};
-&main_uart2 {
- status = "disabled";
-};
-
-&main_uart3 {
- status = "disabled";
-};
-
-&main_uart4 {
- status = "disabled";
-};
-
-&main_uart5 {
- status = "disabled";
-};
-
-&main_uart6 {
- status = "disabled";
-};
-
-&mcu_uart0 {
- status = "disabled";
-};
-
-&mcu_uart1 {
- status = "disabled";
-};
-
&main_i2c1 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c1_pins_default>;
clock-frequency = <400000>;
@@ -405,23 +379,8 @@
status = "reserved";
};
-&mcu_i2c0 {
- status = "disabled";
-};
-
-&mcu_i2c1 {
- status = "disabled";
-};
-
-&mcu_spi0 {
- status = "disabled";
-};
-
-&mcu_spi1 {
- status = "disabled";
-};
-
&main_spi0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_spi0_pins_default>;
ti,pindir-d0-out-d1-in;
@@ -466,8 +425,7 @@
&cpsw3g {
pinctrl-names = "default";
- pinctrl-0 = <&mdio1_pins_default
- &rgmii1_pins_default
+ pinctrl-0 = <&rgmii1_pins_default
&rgmii2_pins_default>;
};
@@ -482,6 +440,10 @@
};
&cpsw3g_mdio {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mdio1_pins_default>;
+
cpsw3g_phy0: ethernet-phy@0 {
reg = <0>;
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
@@ -594,6 +556,7 @@
};
&pcie0_rc {
+ status = "okay";
reset-gpios = <&exp1 5 GPIO_ACTIVE_HIGH>;
phys = <&serdes0_pcie_link>;
phy-names = "pcie-phy";
@@ -604,83 +567,25 @@
phys = <&serdes0_pcie_link>;
phy-names = "pcie-phy";
num-lanes = <1>;
- status = "disabled";
};
&ecap0 {
+ status = "okay";
/* PWM is available on Pin 1 of header J12 */
pinctrl-names = "default";
pinctrl-0 = <&main_ecap0_pins_default>;
};
-&ecap1 {
- status = "disabled";
-};
-
-&ecap2 {
- status = "disabled";
-};
-
-&epwm0 {
- status = "disabled";
-};
-
-&epwm1 {
- status = "disabled";
-};
-
-&epwm2 {
- status = "disabled";
-};
-
-&epwm3 {
- status = "disabled";
-};
-
-&epwm4 {
- status = "disabled";
-};
-
-&epwm5 {
- status = "disabled";
-};
-
-&epwm6 {
- status = "disabled";
-};
-
-&epwm7 {
- status = "disabled";
-};
-
-&epwm8 {
- status = "disabled";
-};
-
-&icssg0_mdio {
- status = "disabled";
-};
-
-&icssg1_mdio {
- status = "disabled";
-};
-
&main_mcan0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_mcan0_pins_default>;
phys = <&transceiver1>;
};
&main_mcan1 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_mcan1_pins_default>;
phys = <&transceiver2>;
};
-
-&gpmc0 {
- status = "disabled";
-};
-
-&elm0 {
- status = "disabled";
-};
diff --git a/arch/arm64/boot/dts/ti/k3-am642-sk.dts b/arch/arm64/boot/dts/ti/k3-am642-sk.dts
index 738d0cf6c40a..2e2d40da360a 100644
--- a/arch/arm64/boot/dts/ti/k3-am642-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-am642-sk.dts
@@ -338,15 +338,8 @@
};
};
-&mcu_uart0 {
- status = "disabled";
-};
-
-&mcu_uart1 {
- status = "disabled";
-};
-
&main_uart0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_uart0_pins_default>;
};
@@ -356,35 +349,8 @@
status = "reserved";
};
-&main_uart2 {
- status = "disabled";
-};
-
-&main_uart3 {
- status = "disabled";
-};
-
-&main_uart4 {
- status = "disabled";
-};
-
-&main_uart5 {
- status = "disabled";
-};
-
-&main_uart6 {
- status = "disabled";
-};
-
-&mcu_i2c0 {
- status = "disabled";
-};
-
-&mcu_i2c1 {
- status = "disabled";
-};
-
&main_i2c1 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c1_pins_default>;
clock-frequency = <400000>;
@@ -409,18 +375,6 @@
};
};
-&main_i2c3 {
- status = "disabled";
-};
-
-&mcu_spi0 {
- status = "disabled";
-};
-
-&mcu_spi1 {
- status = "disabled";
-};
-
/* mcu_gpio0 is reserved for mcu firmware usage */
&mcu_gpio0 {
status = "reserved";
@@ -485,8 +439,7 @@
&cpsw3g {
pinctrl-names = "default";
- pinctrl-0 = <&mdio1_pins_default
- &rgmii1_pins_default
+ pinctrl-0 = <&rgmii1_pins_default
&rgmii2_pins_default>;
};
@@ -501,6 +454,10 @@
};
&cpsw3g_mdio {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mdio1_pins_default>;
+
cpsw3g_phy0: ethernet-phy@0 {
reg = <0>;
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
@@ -603,92 +560,9 @@
<&main_r5fss1_core1_memory_region>;
};
-&pcie0_rc {
- status = "disabled";
-};
-
-&pcie0_ep {
- status = "disabled";
-};
-
&ecap0 {
+ status = "okay";
/* PWM is available on Pin 1 of header J3 */
pinctrl-names = "default";
pinctrl-0 = <&main_ecap0_pins_default>;
};
-
-&ecap1 {
- status = "disabled";
-};
-
-&ecap2 {
- status = "disabled";
-};
-
-&epwm0 {
- status = "disabled";
-};
-
-&epwm1 {
- status = "disabled";
-};
-
-&epwm2 {
- status = "disabled";
-};
-
-&epwm3 {
- status = "disabled";
-};
-
-&epwm4 {
- /*
- * EPWM4_A, EPWM4_B is available on Pin 32 and 33 on J4 (RPi hat)
- * But RPi Hat will be used for other use cases, so marking epwm4 as disabled.
- */
- status = "disabled";
-};
-
-&epwm5 {
- /*
- * EPWM5_A, EPWM5_B is available on Pin 29 and 31 on J4 (RPi hat)
- * But RPi Hat will be used for other use cases, so marking epwm5 as disabled.
- */
- status = "disabled";
-};
-
-&epwm6 {
- status = "disabled";
-};
-
-&epwm7 {
- status = "disabled";
-};
-
-&epwm8 {
- status = "disabled";
-};
-
-&icssg0_mdio {
- status = "disabled";
-};
-
-&icssg1_mdio {
- status = "disabled";
-};
-
-&main_mcan0 {
- status = "disabled";
-};
-
-&main_mcan1 {
- status = "disabled";
-};
-
-&gpmc0 {
- status = "disabled";
-};
-
-&elm0 {
- status = "disabled";
-};
diff --git a/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi b/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi
index 32b797237581..3cced26b520a 100644
--- a/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am65-iot2050-common.dtsi
@@ -360,15 +360,13 @@
};
&main_uart1 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_uart1_pins_default>;
};
-&main_uart2 {
- status = "disabled";
-};
-
&mcu_uart0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&arduino_uart_pins_default>;
};
@@ -413,12 +411,14 @@
};
&wkup_i2c0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&wkup_i2c0_pins_default>;
clock-frequency = <400000>;
};
&mcu_i2c0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&mcu_i2c0_pins_default>;
clock-frequency = <400000>;
@@ -478,6 +478,7 @@
};
&main_i2c0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c0_pins_default>;
clock-frequency = <400000>;
@@ -495,18 +496,21 @@
};
&main_i2c1 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c1_pins_default>;
clock-frequency = <400000>;
};
&main_i2c2 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c2_pins_default>;
clock-frequency = <400000>;
};
&main_i2c3 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c3_pins_default>;
clock-frequency = <400000>;
@@ -546,6 +550,7 @@
};
&ecap0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&ecap0_pins_default>;
};
@@ -570,6 +575,7 @@
};
&mcu_spi0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&mcu_spi0_pins_default>;
@@ -626,15 +632,8 @@
};
};
-&pcie0_rc {
- status = "disabled";
-};
-
-&pcie0_ep {
- status = "disabled";
-};
-
&pcie1_rc {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&minipcie_pins_default>;
@@ -644,19 +643,8 @@
reset-gpios = <&wkup_gpio0 27 GPIO_ACTIVE_HIGH>;
};
-&m_can0 {
- status = "disabled";
-};
-
-&m_can1 {
- status = "disabled";
-};
-
-&pcie1_ep {
- status = "disabled";
-};
-
&mailbox0_cluster0 {
+ status = "okay";
interrupts = <436>;
mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
@@ -666,6 +654,7 @@
};
&mailbox0_cluster1 {
+ status = "okay";
interrupts = <432>;
mbox_mcu_r5fss0_core1: mbox-mcu-r5fss0-core1 {
@@ -674,46 +663,6 @@
};
};
-&mailbox0_cluster2 {
- status = "disabled";
-};
-
-&mailbox0_cluster3 {
- status = "disabled";
-};
-
-&mailbox0_cluster4 {
- status = "disabled";
-};
-
-&mailbox0_cluster5 {
- status = "disabled";
-};
-
-&mailbox0_cluster6 {
- status = "disabled";
-};
-
-&mailbox0_cluster7 {
- status = "disabled";
-};
-
-&mailbox0_cluster8 {
- status = "disabled";
-};
-
-&mailbox0_cluster9 {
- status = "disabled";
-};
-
-&mailbox0_cluster10 {
- status = "disabled";
-};
-
-&mailbox0_cluster11 {
- status = "disabled";
-};
-
&mcu_r5fss0_core0 {
memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
<&mcu_r5fss0_core0_memory_region>;
@@ -725,27 +674,3 @@
<&mcu_r5fss0_core1_memory_region>;
mboxes = <&mailbox0_cluster1 &mbox_mcu_r5fss0_core1>;
};
-
-&icssg0_mdio {
- status = "disabled";
-};
-
-&icssg1_mdio {
- status = "disabled";
-};
-
-&icssg2_mdio {
- status = "disabled";
-};
-
-&mcasp0 {
- status = "disabled";
-};
-
-&mcasp1 {
- status = "disabled";
-};
-
-&mcasp2 {
- status = "disabled";
-};
diff --git a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
index 4005a73cfea9..1adba2f2c153 100644
--- a/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am65-main.dtsi
@@ -91,6 +91,7 @@
clock-frequency = <48000000>;
current-speed = <115200>;
power-domains = <&k3_pds 146 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_uart1: serial@2810000 {
@@ -99,6 +100,7 @@
interrupts = <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>;
clock-frequency = <48000000>;
power-domains = <&k3_pds 147 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_uart2: serial@2820000 {
@@ -107,6 +109,7 @@
interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>;
clock-frequency = <48000000>;
power-domains = <&k3_pds 148 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
crypto: crypto@4e00000 {
@@ -120,17 +123,33 @@
dmas = <&main_udmap 0xc001>, <&main_udmap 0x4002>,
<&main_udmap 0x4003>;
dma-names = "tx", "rx1", "rx2";
- dma-coherent;
rng: rng@4e10000 {
compatible = "inside-secure,safexcel-eip76";
reg = <0x0 0x4e10000 0x0 0x7d>;
interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 136 1>;
status = "disabled"; /* Used by OP-TEE */
};
};
+ /* TIMERIO pad input CTRLMMR_TIMER*_CTRL registers */
+ main_timerio_input: pinctrl@104200 {
+ compatible = "pinctrl-single";
+ reg = <0x0 0x104200 0x0 0x30>;
+ #pinctrl-cells = <1>;
+ pinctrl-single,register-width = <32>;
+ pinctrl-single,function-mask = <0x0000001ff>;
+ };
+
+ /* TIMERIO pad output CTCTRLMMR_TIMERIO*_CTRL registers */
+ main_timerio_output: pinctrl@104280 {
+ compatible = "pinctrl-single";
+ reg = <0x0 0x104280 0x0 0x20>;
+ #pinctrl-cells = <1>;
+ pinctrl-single,register-width = <32>;
+ pinctrl-single,function-mask = <0x0000000f>;
+ };
+
main_pmx0: pinctrl@11c000 {
compatible = "pinctrl-single";
reg = <0x0 0x11c000 0x0 0x2e4>;
@@ -156,6 +175,7 @@
clock-names = "fck";
clocks = <&k3_clks 110 1>;
power-domains = <&k3_pds 110 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_i2c1: i2c@2010000 {
@@ -167,6 +187,7 @@
clock-names = "fck";
clocks = <&k3_clks 111 1>;
power-domains = <&k3_pds 111 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_i2c2: i2c@2020000 {
@@ -178,6 +199,7 @@
clock-names = "fck";
clocks = <&k3_clks 112 1>;
power-domains = <&k3_pds 112 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_i2c3: i2c@2030000 {
@@ -189,6 +211,7 @@
clock-names = "fck";
clocks = <&k3_clks 113 1>;
power-domains = <&k3_pds 113 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
ecap0: pwm@3100000 {
@@ -198,6 +221,7 @@
power-domains = <&k3_pds 39 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 39 0>;
clock-names = "fck";
+ status = "disabled";
};
main_spi0: spi@2100000 {
@@ -210,6 +234,7 @@
#size-cells = <0>;
dmas = <&main_udmap 0xc500>, <&main_udmap 0x4500>;
dma-names = "tx0", "rx0";
+ status = "disabled";
};
main_spi1: spi@2110000 {
@@ -222,6 +247,7 @@
#size-cells = <0>;
assigned-clocks = <&k3_clks 137 1>;
assigned-clock-rates = <48000000>;
+ status = "disabled";
};
main_spi2: spi@2120000 {
@@ -232,6 +258,7 @@
power-domains = <&k3_pds 139 TI_SCI_PD_EXCLUSIVE>;
#address-cells = <1>;
#size-cells = <0>;
+ status = "disabled";
};
main_spi3: spi@2130000 {
@@ -242,6 +269,7 @@
power-domains = <&k3_pds 140 TI_SCI_PD_EXCLUSIVE>;
#address-cells = <1>;
#size-cells = <0>;
+ status = "disabled";
};
main_spi4: spi@2140000 {
@@ -252,6 +280,151 @@
power-domains = <&k3_pds 141 TI_SCI_PD_EXCLUSIVE>;
#address-cells = <1>;
#size-cells = <0>;
+ status = "disabled";
+ };
+
+ main_timer0: timer@2400000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2400000 0x00 0x400>;
+ interrupts = <GIC_SPI 224 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 23 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 23 0>;
+ assigned-clock-parents = <&k3_clks 23 1>;
+ power-domains = <&k3_pds 23 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer1: timer@2410000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2410000 0x00 0x400>;
+ interrupts = <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 24 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 24 0>;
+ assigned-clock-parents = <&k3_clks 24 1>;
+ power-domains = <&k3_pds 24 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer2: timer@2420000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2420000 0x00 0x400>;
+ interrupts = <GIC_SPI 226 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 27 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 27 0>;
+ assigned-clock-parents = <&k3_clks 27 1>;
+ power-domains = <&k3_pds 27 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer3: timer@2430000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2430000 0x00 0x400>;
+ interrupts = <GIC_SPI 227 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 28 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 28 0>;
+ assigned-clock-parents = <&k3_clks 28 1>;
+ power-domains = <&k3_pds 28 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer4: timer@2440000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2440000 0x00 0x400>;
+ interrupts = <GIC_SPI 228 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 29 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 29 0>;
+ assigned-clock-parents = <&k3_clks 29 1>;
+ power-domains = <&k3_pds 29 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer5: timer@2450000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2450000 0x00 0x400>;
+ interrupts = <GIC_SPI 229 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 30 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 30 0>;
+ assigned-clock-parents = <&k3_clks 30 1>;
+ power-domains = <&k3_pds 30 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer6: timer@2460000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2460000 0x00 0x400>;
+ interrupts = <GIC_SPI 230 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 31 0>;
+ assigned-clocks = <&k3_clks 31 0>;
+ assigned-clock-parents = <&k3_clks 31 1>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 31 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer7: timer@2470000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2470000 0x00 0x400>;
+ interrupts = <GIC_SPI 231 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 32 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 32 0>;
+ assigned-clock-parents = <&k3_clks 32 1>;
+ power-domains = <&k3_pds 32 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer8: timer@2480000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2480000 0x00 0x400>;
+ interrupts = <GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 33 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 33 0>;
+ assigned-clock-parents = <&k3_clks 33 1>;
+ power-domains = <&k3_pds 33 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer9: timer@2490000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x2490000 0x00 0x400>;
+ interrupts = <GIC_SPI 233 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 34 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 34 0>;
+ assigned-clock-parents = <&k3_clks 34 1>;
+ power-domains = <&k3_pds 34 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer10: timer@24a0000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x24a0000 0x00 0x400>;
+ interrupts = <GIC_SPI 234 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 25 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 25 0>;
+ assigned-clock-parents = <&k3_clks 25 1>;
+ power-domains = <&k3_pds 25 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ };
+
+ main_timer11: timer@24b0000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x24b0000 0x00 0x400>;
+ interrupts = <GIC_SPI 235 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&k3_clks 26 0>;
+ clock-names = "fck";
+ assigned-clocks = <&k3_clks 26 0>;
+ assigned-clock-parents = <&k3_clks 26 1>;
+ power-domains = <&k3_pds 26 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
};
sdhci0: mmc@4f80000 {
@@ -342,7 +515,7 @@
dss_oldi_io_ctrl: dss-oldi-io-ctrl@41e0 {
compatible = "syscon";
- reg = <0x0000041e0 0x14>;
+ reg = <0x000041e0 0x14>;
};
ehrpwm_tbclk: clock@4140 {
@@ -501,6 +674,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&intr_main_navss>;
+ status = "disabled";
};
mailbox0_cluster1: mailbox@31f81000 {
@@ -510,6 +684,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&intr_main_navss>;
+ status = "disabled";
};
mailbox0_cluster2: mailbox@31f82000 {
@@ -519,6 +694,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&intr_main_navss>;
+ status = "disabled";
};
mailbox0_cluster3: mailbox@31f83000 {
@@ -528,6 +704,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&intr_main_navss>;
+ status = "disabled";
};
mailbox0_cluster4: mailbox@31f84000 {
@@ -537,6 +714,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&intr_main_navss>;
+ status = "disabled";
};
mailbox0_cluster5: mailbox@31f85000 {
@@ -546,6 +724,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&intr_main_navss>;
+ status = "disabled";
};
mailbox0_cluster6: mailbox@31f86000 {
@@ -555,6 +734,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&intr_main_navss>;
+ status = "disabled";
};
mailbox0_cluster7: mailbox@31f87000 {
@@ -564,6 +744,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&intr_main_navss>;
+ status = "disabled";
};
mailbox0_cluster8: mailbox@31f88000 {
@@ -573,6 +754,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&intr_main_navss>;
+ status = "disabled";
};
mailbox0_cluster9: mailbox@31f89000 {
@@ -582,6 +764,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&intr_main_navss>;
+ status = "disabled";
};
mailbox0_cluster10: mailbox@31f8a000 {
@@ -591,6 +774,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&intr_main_navss>;
+ status = "disabled";
};
mailbox0_cluster11: mailbox@31f8b000 {
@@ -600,6 +784,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&intr_main_navss>;
+ status = "disabled";
};
ringacc: ringacc@3c000000 {
@@ -707,6 +892,7 @@
interrupts = <GIC_SPI 340 IRQ_TYPE_EDGE_RISING>;
msi-map = <0x0 &gic_its 0x0 0x10000>;
device_type = "pci";
+ status = "disabled";
};
pcie0_ep: pcie-ep@5500000 {
@@ -720,6 +906,7 @@
max-link-speed = <2>;
dma-coherent;
interrupts = <GIC_SPI 340 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
};
pcie1_rc: pcie@5600000 {
@@ -740,6 +927,7 @@
interrupts = <GIC_SPI 355 IRQ_TYPE_EDGE_RISING>;
msi-map = <0x0 &gic_its 0x10000 0x10000>;
device_type = "pci";
+ status = "disabled";
};
pcie1_ep: pcie-ep@5600000 {
@@ -753,6 +941,7 @@
max-link-speed = <2>;
dma-coherent;
interrupts = <GIC_SPI 355 IRQ_TYPE_EDGE_RISING>;
+ status = "disabled";
};
mcasp0: mcasp@2b00000 {
@@ -770,6 +959,7 @@
clocks = <&k3_clks 104 0>;
clock-names = "fck";
power-domains = <&k3_pds 104 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcasp1: mcasp@2b10000 {
@@ -787,6 +977,7 @@
clocks = <&k3_clks 105 0>;
clock-names = "fck";
power-domains = <&k3_pds 105 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcasp2: mcasp@2b20000 {
@@ -804,6 +995,7 @@
clocks = <&k3_clks 106 0>;
clock-names = "fck";
power-domains = <&k3_pds 106 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
cal: cal@6f03000 {
@@ -874,6 +1066,7 @@
power-domains = <&k3_pds 40 TI_SCI_PD_EXCLUSIVE>;
clocks = <&ehrpwm_tbclk 0>, <&k3_clks 40 0>;
clock-names = "tbclk", "fck";
+ status = "disabled";
};
ehrpwm1: pwm@3010000 {
@@ -883,6 +1076,7 @@
power-domains = <&k3_pds 41 TI_SCI_PD_EXCLUSIVE>;
clocks = <&ehrpwm_tbclk 1>, <&k3_clks 41 0>;
clock-names = "tbclk", "fck";
+ status = "disabled";
};
ehrpwm2: pwm@3020000 {
@@ -892,6 +1086,7 @@
power-domains = <&k3_pds 42 TI_SCI_PD_EXCLUSIVE>;
clocks = <&ehrpwm_tbclk 2>, <&k3_clks 42 0>;
clock-names = "tbclk", "fck";
+ status = "disabled";
};
ehrpwm3: pwm@3030000 {
@@ -901,6 +1096,7 @@
power-domains = <&k3_pds 43 TI_SCI_PD_EXCLUSIVE>;
clocks = <&ehrpwm_tbclk 3>, <&k3_clks 43 0>;
clock-names = "tbclk", "fck";
+ status = "disabled";
};
ehrpwm4: pwm@3040000 {
@@ -910,6 +1106,7 @@
power-domains = <&k3_pds 44 TI_SCI_PD_EXCLUSIVE>;
clocks = <&ehrpwm_tbclk 4>, <&k3_clks 44 0>;
clock-names = "tbclk", "fck";
+ status = "disabled";
};
ehrpwm5: pwm@3050000 {
@@ -919,6 +1116,7 @@
power-domains = <&k3_pds 45 TI_SCI_PD_EXCLUSIVE>;
clocks = <&ehrpwm_tbclk 5>, <&k3_clks 45 0>;
clock-names = "tbclk", "fck";
+ status = "disabled";
};
icssg0: icssg@b000000 {
@@ -1059,6 +1257,7 @@
#address-cells = <1>;
#size-cells = <0>;
bus_freq = <1000000>;
+ status = "disabled";
};
};
@@ -1200,6 +1399,7 @@
#address-cells = <1>;
#size-cells = <0>;
bus_freq = <1000000>;
+ status = "disabled";
};
};
@@ -1341,6 +1541,7 @@
#address-cells = <1>;
#size-cells = <0>;
bus_freq = <1000000>;
+ status = "disabled";
};
};
};
diff --git a/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi b/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi
index 8d592bf41d6f..5dfa31840e9c 100644
--- a/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am65-mcu.dtsi
@@ -20,13 +20,32 @@
};
};
+ /* MCU_TIMERIO pad input CTRLMMR_MCU_TIMER*_CTRL registers */
+ mcu_timerio_input: pinctrl@40f04200 {
+ compatible = "pinctrl-single";
+ reg = <0x0 0x40f04200 0x0 0x10>;
+ #pinctrl-cells = <1>;
+ pinctrl-single,register-width = <32>;
+ pinctrl-single,function-mask = <0x00000101>;
+ };
+
+ /* MCU_TIMERIO pad output CTRLMMR_MCU_TIMERIO*_CTRL registers */
+ mcu_timerio_output: pinctrl@40f04280 {
+ compatible = "pinctrl-single";
+ reg = <0x0 0x40f04280 0x0 0x8>;
+ #pinctrl-cells = <1>;
+ pinctrl-single,register-width = <32>;
+ pinctrl-single,function-mask = <0x00000003>;
+ };
+
mcu_uart0: serial@40a00000 {
compatible = "ti,am654-uart";
- reg = <0x00 0x40a00000 0x00 0x100>;
- interrupts = <GIC_SPI 565 IRQ_TYPE_LEVEL_HIGH>;
- clock-frequency = <96000000>;
- current-speed = <115200>;
- power-domains = <&k3_pds 149 TI_SCI_PD_EXCLUSIVE>;
+ reg = <0x00 0x40a00000 0x00 0x100>;
+ interrupts = <GIC_SPI 565 IRQ_TYPE_LEVEL_HIGH>;
+ clock-frequency = <96000000>;
+ current-speed = <115200>;
+ power-domains = <&k3_pds 149 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcu_ram: sram@41c00000 {
@@ -46,6 +65,7 @@
clock-names = "fck";
clocks = <&k3_clks 114 1>;
power-domains = <&k3_pds 114 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcu_spi0: spi@40300000 {
@@ -56,6 +76,7 @@
power-domains = <&k3_pds 142 TI_SCI_PD_EXCLUSIVE>;
#address-cells = <1>;
#size-cells = <0>;
+ status = "disabled";
};
mcu_spi1: spi@40310000 {
@@ -66,6 +87,7 @@
power-domains = <&k3_pds 143 TI_SCI_PD_EXCLUSIVE>;
#address-cells = <1>;
#size-cells = <0>;
+ status = "disabled";
};
mcu_spi2: spi@40320000 {
@@ -76,6 +98,7 @@
power-domains = <&k3_pds 144 TI_SCI_PD_EXCLUSIVE>;
#address-cells = <1>;
#size-cells = <0>;
+ status = "disabled";
};
tscadc0: tscadc@40200000 {
@@ -85,7 +108,7 @@
clocks = <&k3_clks 0 2>;
assigned-clocks = <&k3_clks 0 2>;
assigned-clock-rates = <60000000>;
- clock-names = "adc_tsc_fck";
+ clock-names = "fck";
dmas = <&mcu_udmap 0x7100>,
<&mcu_udmap 0x7101 >;
dma-names = "fifo0", "fifo1";
@@ -103,7 +126,7 @@
clocks = <&k3_clks 1 2>;
assigned-clocks = <&k3_clks 1 2>;
assigned-clock-rates = <60000000>;
- clock-names = "adc_tsc_fck";
+ clock-names = "fck";
dmas = <&mcu_udmap 0x7102>,
<&mcu_udmap 0x7103>;
dma-names = "fifo0", "fifo1";
@@ -114,6 +137,51 @@
};
};
+ /*
+ * The MCU domain timer interrupts are routed only to the ESM module,
+ * and not currently available for Linux. The MCU domain timers are
+ * of limited use without interrupts, and likely reserved by the ESM.
+ */
+ mcu_timer0: timer@40400000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x40400000 0x00 0x400>;
+ clocks = <&k3_clks 35 0>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 35 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ status = "reserved";
+ };
+
+ mcu_timer1: timer@40410000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x40410000 0x00 0x400>;
+ clocks = <&k3_clks 36 0>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 36 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ status = "reserved";
+ };
+
+ mcu_timer2: timer@40420000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x40420000 0x00 0x400>;
+ clocks = <&k3_clks 37 0>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 37 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ status = "reserved";
+ };
+
+ mcu_timer3: timer@40430000 {
+ compatible = "ti,am654-timer";
+ reg = <0x00 0x40430000 0x00 0x400>;
+ clocks = <&k3_clks 38 0>;
+ clock-names = "fck";
+ power-domains = <&k3_pds 38 TI_SCI_PD_EXCLUSIVE>;
+ ti,timer-pwm;
+ status = "reserved";
+ };
+
mcu_navss: bus@28380000 {
compatible = "simple-mfd";
#address-cells = <2>;
@@ -172,6 +240,7 @@
<GIC_SPI 545 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
m_can1: mcan@40568000 {
@@ -187,6 +256,7 @@
<GIC_SPI 548 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
fss: fss@47000000 {
@@ -273,6 +343,7 @@
clocks = <&k3_clks 5 10>;
clock-names = "fck";
bus_freq = <1000000>;
+ status = "disabled";
};
cpts@3d000 {
diff --git a/arch/arm64/boot/dts/ti/k3-am65-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-am65-wakeup.dtsi
index fa11d7142006..fd2b998ebddc 100644
--- a/arch/arm64/boot/dts/ti/k3-am65-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am65-wakeup.dtsi
@@ -54,6 +54,7 @@
clock-frequency = <48000000>;
current-speed = <115200>;
power-domains = <&k3_pds 150 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
wkup_i2c0: i2c@42120000 {
@@ -65,6 +66,7 @@
clock-names = "fck";
clocks = <&k3_clks 115 1>;
power-domains = <&k3_pds 115 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
intr_wkup_gpio: interrupt-controller@42200000 {
diff --git a/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic-common.dtsi b/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic-common.dtsi
index 4a9bf7d7c07d..cd43fd11a5c2 100644
--- a/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic-common.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am6528-iot2050-basic-common.dtsi
@@ -50,6 +50,7 @@
};
&main_uart0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_uart0_pins_default>;
};
diff --git a/arch/arm64/boot/dts/ti/k3-am654-base-board.dts b/arch/arm64/boot/dts/ti/k3-am654-base-board.dts
index 5850582dd4ed..592ab2b54cb3 100644
--- a/arch/arm64/boot/dts/ti/k3-am654-base-board.dts
+++ b/arch/arm64/boot/dts/ti/k3-am654-base-board.dts
@@ -271,13 +271,20 @@
status = "reserved";
};
+&mcu_uart0 {
+ status = "okay";
+ /* Default pinmux */
+};
+
&main_uart0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_uart0_pins_default>;
power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>;
};
&wkup_i2c0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&wkup_i2c0_pins_default>;
clock-frequency = <400000>;
@@ -296,7 +303,13 @@
};
};
+&mcu_i2c0 {
+ status = "okay";
+ /* Default pinmux */
+};
+
&main_i2c0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c0_pins_default>;
clock-frequency = <400000>;
@@ -310,23 +323,27 @@
};
&main_i2c1 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c1_pins_default>;
clock-frequency = <400000>;
};
&main_i2c2 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c2_pins_default>;
clock-frequency = <400000>;
};
&ecap0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&ecap0_pins_default>;
};
&main_spi0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_spi0_pins_default>;
#address-cells = <1>;
@@ -398,31 +415,8 @@
status = "disabled";
};
-&pcie0_rc {
- status = "disabled";
-};
-
-&pcie0_ep {
- status = "disabled";
-};
-
-&pcie1_rc {
- status = "disabled";
-};
-
-&pcie1_ep {
- status = "disabled";
-};
-
-&m_can0 {
- status = "disabled";
-};
-
-&m_can1 {
- status = "disabled";
-};
-
&mailbox0_cluster0 {
+ status = "okay";
interrupts = <436>;
mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
@@ -432,6 +426,7 @@
};
&mailbox0_cluster1 {
+ status = "okay";
interrupts = <432>;
mbox_mcu_r5fss0_core1: mbox-mcu-r5fss0-core1 {
@@ -440,46 +435,6 @@
};
};
-&mailbox0_cluster2 {
- status = "disabled";
-};
-
-&mailbox0_cluster3 {
- status = "disabled";
-};
-
-&mailbox0_cluster4 {
- status = "disabled";
-};
-
-&mailbox0_cluster5 {
- status = "disabled";
-};
-
-&mailbox0_cluster6 {
- status = "disabled";
-};
-
-&mailbox0_cluster7 {
- status = "disabled";
-};
-
-&mailbox0_cluster8 {
- status = "disabled";
-};
-
-&mailbox0_cluster9 {
- status = "disabled";
-};
-
-&mailbox0_cluster10 {
- status = "disabled";
-};
-
-&mailbox0_cluster11 {
- status = "disabled";
-};
-
&mcu_r5fss0_core0 {
memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
<&mcu_r5fss0_core0_memory_region>;
@@ -512,10 +467,14 @@
&mcu_cpsw {
pinctrl-names = "default";
- pinctrl-0 = <&mcu_cpsw_pins_default &mcu_mdio_pins_default>;
+ pinctrl-0 = <&mcu_cpsw_pins_default>;
};
&davinci_mdio {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_mdio_pins_default>;
+
phy0: ethernet-phy@0 {
reg = <0>;
ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
@@ -528,30 +487,6 @@
phy-handle = <&phy0>;
};
-&mcasp0 {
- status = "disabled";
-};
-
-&mcasp1 {
- status = "disabled";
-};
-
-&mcasp2 {
- status = "disabled";
-};
-
&dss {
status = "disabled";
};
-
-&icssg0_mdio {
- status = "disabled";
-};
-
-&icssg1_mdio {
- status = "disabled";
-};
-
-&icssg2_mdio {
- status = "disabled";
-};
diff --git a/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-common.dtsi b/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-common.dtsi
index d25e8b26187f..0f67e1ec0fb8 100644
--- a/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-common.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-am6548-iot2050-advanced-common.dtsi
@@ -50,7 +50,3 @@
ti,driver-strength-ohm = <50>;
disable-wp;
};
-
-&main_uart0 {
- status = "disabled";
-};
diff --git a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
index 7e8552fd2b6a..6240856e4863 100644
--- a/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
+++ b/arch/arm64/boot/dts/ti/k3-j7200-common-proc-board.dts
@@ -154,51 +154,27 @@
status = "reserved";
};
+&mcu_uart0 {
+ status = "okay";
+ /* Default pinmux */
+};
+
&main_uart0 {
+ status = "okay";
/* Shared with ATF on this platform */
power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>;
};
+&main_uart1 {
+ status = "okay";
+ /* Default pinmux */
+};
+
&main_uart2 {
/* MAIN UART 2 is used by R5F firmware */
status = "reserved";
};
-&main_uart3 {
- /* UART not brought out */
- status = "disabled";
-};
-
-&main_uart4 {
- /* UART not brought out */
- status = "disabled";
-};
-
-&main_uart5 {
- /* UART not brought out */
- status = "disabled";
-};
-
-&main_uart6 {
- /* UART not brought out */
- status = "disabled";
-};
-
-&main_uart7 {
- /* UART not brought out */
- status = "disabled";
-};
-
-&main_uart8 {
- /* UART not brought out */
- status = "disabled";
-};
-
-&main_uart9 {
- /* UART not brought out */
- status = "disabled";
-};
-
&main_gpio2 {
status = "disabled";
};
@@ -234,6 +210,7 @@
};
&main_i2c0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c0_pins_default>;
clock-frequency = <400000>;
@@ -261,6 +238,7 @@
* The i2c1 of the CPB (as it is labeled) is not connected to j7200.
*/
&main_i2c1 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c1_pins_default>;
clock-frequency = <400000>;
diff --git a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
index 80a57916bcb3..138381f43ce4 100644
--- a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi
@@ -142,6 +142,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster1: mailbox@31f81000 {
@@ -151,6 +152,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster2: mailbox@31f82000 {
@@ -160,6 +162,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster3: mailbox@31f83000 {
@@ -169,6 +172,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster4: mailbox@31f84000 {
@@ -178,6 +182,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster5: mailbox@31f85000 {
@@ -187,6 +192,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster6: mailbox@31f86000 {
@@ -196,6 +202,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster7: mailbox@31f87000 {
@@ -205,6 +212,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster8: mailbox@31f88000 {
@@ -214,6 +222,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster9: mailbox@31f89000 {
@@ -223,6 +232,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster10: mailbox@31f8a000 {
@@ -232,6 +242,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster11: mailbox@31f8b000 {
@@ -241,6 +252,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
main_ringacc: ringacc@3c000000 {
@@ -319,6 +331,7 @@
power-domains = <&k3_pds 146 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 146 2>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart1: serial@2810000 {
@@ -330,6 +343,7 @@
power-domains = <&k3_pds 278 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 278 2>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart2: serial@2820000 {
@@ -341,6 +355,7 @@
power-domains = <&k3_pds 279 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 279 2>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart3: serial@2830000 {
@@ -352,6 +367,7 @@
power-domains = <&k3_pds 280 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 280 2>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart4: serial@2840000 {
@@ -363,6 +379,7 @@
power-domains = <&k3_pds 281 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 281 2>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart5: serial@2850000 {
@@ -374,6 +391,7 @@
power-domains = <&k3_pds 282 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 282 2>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart6: serial@2860000 {
@@ -385,6 +403,7 @@
power-domains = <&k3_pds 283 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 283 2>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart7: serial@2870000 {
@@ -396,6 +415,7 @@
power-domains = <&k3_pds 284 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 284 2>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart8: serial@2880000 {
@@ -407,6 +427,7 @@
power-domains = <&k3_pds 285 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 285 2>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart9: serial@2890000 {
@@ -418,6 +439,7 @@
power-domains = <&k3_pds 286 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 286 2>;
clock-names = "fclk";
+ status = "disabled";
};
main_i2c0: i2c@2000000 {
@@ -429,6 +451,7 @@
clock-names = "fck";
clocks = <&k3_clks 187 1>;
power-domains = <&k3_pds 187 TI_SCI_PD_SHARED>;
+ status = "disabled";
};
main_i2c1: i2c@2010000 {
@@ -440,6 +463,7 @@
clock-names = "fck";
clocks = <&k3_clks 188 1>;
power-domains = <&k3_pds 188 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_i2c2: i2c@2020000 {
@@ -451,6 +475,7 @@
clock-names = "fck";
clocks = <&k3_clks 189 1>;
power-domains = <&k3_pds 189 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_i2c3: i2c@2030000 {
@@ -462,6 +487,7 @@
clock-names = "fck";
clocks = <&k3_clks 190 1>;
power-domains = <&k3_pds 190 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_i2c4: i2c@2040000 {
@@ -473,6 +499,7 @@
clock-names = "fck";
clocks = <&k3_clks 191 1>;
power-domains = <&k3_pds 191 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_i2c5: i2c@2050000 {
@@ -484,6 +511,7 @@
clock-names = "fck";
clocks = <&k3_clks 192 1>;
power-domains = <&k3_pds 192 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_i2c6: i2c@2060000 {
@@ -495,6 +523,7 @@
clock-names = "fck";
clocks = <&k3_clks 193 1>;
power-domains = <&k3_pds 193 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_sdhci0: mmc@4f80000 {
diff --git a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi
index e5be78a58682..fe669deba489 100644
--- a/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j7200-mcu-wakeup.dtsi
@@ -79,6 +79,7 @@
power-domains = <&k3_pds 287 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 287 2>;
clock-names = "fclk";
+ status = "disabled";
};
mcu_uart0: serial@40a00000 {
@@ -90,6 +91,7 @@
power-domains = <&k3_pds 149 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 149 2>;
clock-names = "fclk";
+ status = "disabled";
};
wkup_gpio_intr: interrupt-controller@42200000 {
@@ -249,6 +251,7 @@
clock-names = "fck";
clocks = <&k3_clks 194 1>;
power-domains = <&k3_pds 194 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcu_i2c1: i2c@40b10000 {
@@ -260,6 +263,7 @@
clock-names = "fck";
clocks = <&k3_clks 195 1>;
power-domains = <&k3_pds 195 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
wkup_i2c0: i2c@42120000 {
@@ -271,6 +275,7 @@
clock-names = "fck";
clocks = <&k3_clks 197 1>;
power-domains = <&k3_pds 197 TI_SCI_PD_SHARED>;
+ status = "disabled";
};
fss: syscon@47000000 {
@@ -325,7 +330,7 @@
clocks = <&k3_clks 0 1>;
assigned-clocks = <&k3_clks 0 3>;
assigned-clock-rates = <60000000>;
- clock-names = "adc_tsc_fck";
+ clock-names = "fck";
dmas = <&main_udmap 0x7400>,
<&main_udmap 0x7401>;
dma-names = "fifo0", "fifo1";
@@ -386,7 +391,6 @@
dmas = <&mcu_udmap 0xf501>, <&mcu_udmap 0x7502>,
<&mcu_udmap 0x7503>;
dma-names = "tx", "rx1", "rx2";
- dma-coherent;
rng: rng@40910000 {
compatible = "inside-secure,safexcel-eip76";
diff --git a/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi
index 2d615c3e9fa1..fa44ed4c17d5 100644
--- a/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j7200-som-p0.dtsi
@@ -144,6 +144,7 @@
};
&mailbox0_cluster0 {
+ status = "okay";
interrupts = <436>;
mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
@@ -158,6 +159,7 @@
};
&mailbox0_cluster1 {
+ status = "okay";
interrupts = <432>;
mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 {
@@ -171,46 +173,6 @@
};
};
-&mailbox0_cluster2 {
- status = "disabled";
-};
-
-&mailbox0_cluster3 {
- status = "disabled";
-};
-
-&mailbox0_cluster4 {
- status = "disabled";
-};
-
-&mailbox0_cluster5 {
- status = "disabled";
-};
-
-&mailbox0_cluster6 {
- status = "disabled";
-};
-
-&mailbox0_cluster7 {
- status = "disabled";
-};
-
-&mailbox0_cluster8 {
- status = "disabled";
-};
-
-&mailbox0_cluster9 {
- status = "disabled";
-};
-
-&mailbox0_cluster10 {
- status = "disabled";
-};
-
-&mailbox0_cluster11 {
- status = "disabled";
-};
-
&mcu_r5fss0_core0 {
mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>;
memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
diff --git a/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts b/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts
new file mode 100644
index 000000000000..37c24b077b6a
--- /dev/null
+++ b/arch/arm64/boot/dts/ti/k3-j721e-beagleboneai64.dts
@@ -0,0 +1,1055 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * https://beagleboard.org/ai-64
+ * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com/
+ * Copyright (C) 2022 Jason Kridner, BeagleBoard.org Foundation
+ * Copyright (C) 2022 Robert Nelson, BeagleBoard.org Foundation
+ */
+
+/dts-v1/;
+
+#include "k3-j721e.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/net/ti-dp83867.h>
+#include <dt-bindings/phy/phy-cadence.h>
+
+/ {
+ compatible = "beagle,j721e-beagleboneai64", "ti,j721e";
+ model = "BeagleBoard.org BeagleBone AI-64";
+
+ aliases {
+ serial2 = &main_uart0;
+ mmc0 = &main_sdhci0;
+ mmc1 = &main_sdhci1;
+ i2c0 = &wkup_i2c0;
+ i2c1 = &main_i2c6;
+ i2c2 = &main_i2c2;
+ i2c3 = &main_i2c4;
+ };
+
+ chosen {
+ stdout-path = "serial2:115200n8";
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ /* 4G RAM */
+ reg = <0x00000000 0x80000000 0x00000000 0x80000000>,
+ <0x00000008 0x80000000 0x00000000 0x80000000>;
+ };
+
+ reserved_memory: reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ secure_ddr: optee@9e800000 {
+ reg = <0x00 0x9e800000 0x00 0x01800000>;
+ no-map;
+ };
+
+ mcu_r5fss0_core0_dma_memory_region: r5f-dma-memory@a0000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa0000000 0x00 0x100000>;
+ no-map;
+ };
+
+ mcu_r5fss0_core0_memory_region: r5f-memory@a0100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa0100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ mcu_r5fss0_core1_dma_memory_region: r5f-dma-memory@a1000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa1000000 0x00 0x100000>;
+ no-map;
+ };
+
+ mcu_r5fss0_core1_memory_region: r5f-memory@a1100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa1100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ main_r5fss0_core0_dma_memory_region: r5f-dma-memory@a2000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa2000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss0_core0_memory_region: r5f-memory@a2100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa2100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ main_r5fss0_core1_dma_memory_region: r5f-dma-memory@a3000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa3000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss0_core1_memory_region: r5f-memory@a3100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa3100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ main_r5fss1_core0_dma_memory_region: r5f-dma-memory@a4000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa4000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss1_core0_memory_region: r5f-memory@a4100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa4100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ main_r5fss1_core1_dma_memory_region: r5f-dma-memory@a5000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa5000000 0x00 0x100000>;
+ no-map;
+ };
+
+ main_r5fss1_core1_memory_region: r5f-memory@a5100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa5100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ c66_1_dma_memory_region: c66-dma-memory@a6000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa6000000 0x00 0x100000>;
+ no-map;
+ };
+
+ c66_0_memory_region: c66-memory@a6100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa6100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ c66_0_dma_memory_region: c66-dma-memory@a7000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa7000000 0x00 0x100000>;
+ no-map;
+ };
+
+ c66_1_memory_region: c66-memory@a7100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa7100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ c71_0_dma_memory_region: c71-dma-memory@a8000000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa8000000 0x00 0x100000>;
+ no-map;
+ };
+
+ c71_0_memory_region: c71-memory@a8100000 {
+ compatible = "shared-dma-pool";
+ reg = <0x00 0xa8100000 0x00 0xf00000>;
+ no-map;
+ };
+
+ rtos_ipc_memory_region: ipc-memories@aa000000 {
+ reg = <0x00 0xaa000000 0x00 0x01c00000>;
+ alignment = <0x1000>;
+ no-map;
+ };
+ };
+
+ gpio_keys: gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&sw_pwr_pins_default>;
+
+ button-1 {
+ label = "BOOT";
+ linux,code = <BTN_0>;
+ gpios = <&wkup_gpio0 0 GPIO_ACTIVE_LOW>;
+ };
+
+ button-2 {
+ label = "POWER";
+ linux,code = <KEY_POWER>;
+ gpios = <&wkup_gpio0 4 GPIO_ACTIVE_LOW>;
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&led_pins_default>;
+
+ led-0 {
+ gpios = <&main_gpio0 96 GPIO_ACTIVE_HIGH>;
+ function = LED_FUNCTION_HEARTBEAT;
+ linux,default-trigger = "heartbeat";
+ };
+
+ led-1 {
+ gpios = <&main_gpio0 95 GPIO_ACTIVE_HIGH>;
+ function = LED_FUNCTION_DISK_ACTIVITY;
+ linux,default-trigger = "mmc0";
+ };
+
+ led-2 {
+ gpios = <&main_gpio0 97 GPIO_ACTIVE_HIGH>;
+ function = LED_FUNCTION_CPU;
+ linux,default-trigger = "cpu";
+ };
+
+ led-3 {
+ gpios = <&main_gpio0 110 GPIO_ACTIVE_HIGH>;
+ function = LED_FUNCTION_DISK_ACTIVITY;
+ linux,default-trigger = "mmc1";
+ };
+
+ led-4 {
+ gpios = <&main_gpio0 109 GPIO_ACTIVE_HIGH>;
+ function = LED_FUNCTION_WLAN;
+ default-state = "off";
+ };
+ };
+
+ evm_12v0: regulator-0 {
+ /* main supply */
+ compatible = "regulator-fixed";
+ regulator-name = "evm_12v0";
+ regulator-min-microvolt = <12000000>;
+ regulator-max-microvolt = <12000000>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vsys_3v3: regulator-1 {
+ /* Output of LMS140 */
+ compatible = "regulator-fixed";
+ regulator-name = "vsys_3v3";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ vin-supply = <&evm_12v0>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vsys_5v0: regulator-2 {
+ /* Output of LM5140 */
+ compatible = "regulator-fixed";
+ regulator-name = "vsys_5v0";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ vin-supply = <&evm_12v0>;
+ regulator-always-on;
+ regulator-boot-on;
+ };
+
+ vdd_mmc1: regulator-3 {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&sd_pwr_en_pins_default>;
+ regulator-name = "vdd_mmc1";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ enable-active-high;
+ vin-supply = <&vsys_3v3>;
+ gpio = <&main_gpio0 82 GPIO_ACTIVE_HIGH>;
+ };
+
+ vdd_sd_dv_alt: regulator-4 {
+ compatible = "regulator-gpio";
+ pinctrl-names = "default";
+ pinctrl-0 = <&vdd_sd_dv_alt_pins_default>;
+ regulator-name = "tlv71033";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-boot-on;
+ vin-supply = <&vsys_5v0>;
+ gpios = <&main_gpio0 117 GPIO_ACTIVE_HIGH>;
+ states = <1800000 0x0>,
+ <3300000 0x1>;
+ };
+
+ dp_pwr_3v3: regulator-5 {
+ compatible = "regulator-fixed";
+ pinctrl-names = "default";
+ pinctrl-0 = <&dp0_3v3_en_pins_default>;
+ regulator-name = "dp-pwr";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ gpio = <&main_gpio0 49 GPIO_ACTIVE_HIGH>; /* DP0_PWR_SW_EN */
+ enable-active-high;
+ };
+
+ dp0: connector {
+ compatible = "dp-connector";
+ label = "DP0";
+ type = "full-size";
+ dp-pwr-supply = <&dp_pwr_3v3>;
+
+ port {
+ dp_connector_in: endpoint {
+ remote-endpoint = <&dp0_out>;
+ };
+ };
+ };
+};
+
+&main_pmx0 {
+ led_pins_default: led-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x184, PIN_INPUT, 7) /* (T23) RGMII5_RD0.GPIO0_96 */
+ J721E_IOPAD(0x180, PIN_INPUT, 7) /* (R23) RGMII5_RD1.GPIO0_95 */
+ J721E_IOPAD(0x188, PIN_INPUT, 7) /* (Y28) RGMII6_TX_CTL.GPIO0_97 */
+ J721E_IOPAD(0x1bc, PIN_INPUT, 7) /* (V24) MDIO0_MDC.GPIO0_110 */
+ J721E_IOPAD(0x1b8, PIN_INPUT, 7) /* (V26) MDIO0_MDIO.GPIO0_109 */
+ >;
+ };
+
+ main_mmc1_pins_default: main-mmc1-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x254, PIN_INPUT, 0) /* (R29) MMC1_CMD */
+ J721E_IOPAD(0x250, PIN_INPUT, 0) /* (P25) MMC1_CLK */
+ J721E_IOPAD(0x2ac, PIN_INPUT, 0) /* (P25) MMC1_CLKLB */
+ J721E_IOPAD(0x24c, PIN_INPUT, 0) /* (R24) MMC1_DAT0 */
+ J721E_IOPAD(0x248, PIN_INPUT, 0) /* (P24) MMC1_DAT1 */
+ J721E_IOPAD(0x244, PIN_INPUT, 0) /* (R25) MMC1_DAT2 */
+ J721E_IOPAD(0x240, PIN_INPUT, 0) /* (R26) MMC1_DAT3 */
+ J721E_IOPAD(0x258, PIN_INPUT, 0) /* (P23) MMC1_SDCD */
+ >;
+ };
+
+ main_uart0_pins_default: main-uart0-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x1e8, PIN_INPUT, 0) /* (AB2) UART0_RXD */
+ J721E_IOPAD(0x1ec, PIN_OUTPUT, 0) /* (AB3) UART0_TXD */
+ >;
+ };
+
+ sd_pwr_en_pins_default: sd-pwr-en-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x14c, PIN_INPUT, 7) /* (AA29) PRG0_PRU1_GPO19.GPIO0_82 */
+ >;
+ };
+
+ vdd_sd_dv_alt_pins_default: vdd-sd-dv-alt-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x1d8, PIN_INPUT, 7) /* (W4) SPI1_CS1.GPIO0_117 */
+ >;
+ };
+
+ main_usbss0_pins_default: main-usbss0-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x210, PIN_INPUT, 7) /* (W3) MCAN1_RX.GPIO1_3 - USBC_DIR */
+ >;
+ };
+
+ main_usbss1_pins_default: main-usbss1-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x290, INPUT_DISABLE, 1) /* (U6) USB0_DRVVBUS.USB1_DRVVBUS */
+ >;
+ };
+
+ dp0_3v3_en_pins_default:dp0-3v3-en-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0xc8, PIN_INPUT, 7) /* (AE26) PRG0_PRU0_GPO6.GPIO0_49 */
+ >;
+ };
+
+ dp0_pins_default: dp0-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x1c4, PIN_INPUT, 5) /* (Y4) SPI0_CS1.DP0_HPD */
+ >;
+ };
+
+ main_i2c0_pins_default: main-i2c0-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x220, PIN_INPUT_PULLUP, 0) /* (AC5) I2C0_SCL */
+ J721E_IOPAD(0x224, PIN_INPUT_PULLUP, 0) /* (AA5) I2C0_SDA */
+ >;
+ };
+
+ main_i2c1_pins_default: main-i2c1-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x228, PIN_INPUT_PULLUP, 0) /* (Y6) I2C1_SCL */
+ J721E_IOPAD(0x22c, PIN_INPUT_PULLUP, 0) /* (AA6) I2C1_SDA */
+ >;
+ };
+
+ main_i2c2_pins_default: main-i2c2-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x208, PIN_INPUT_PULLUP, 4) /* (W5) MCAN0_RX.I2C2_SCL */
+ J721E_IOPAD(0x20c, PIN_INPUT_PULLUP, 4) /* (W6) MCAN0_TX.I2C2_SDA */
+ J721E_IOPAD(0x138, PIN_INPUT, 7) /* (AE25) PRG0_PRU1_GPO14.GPIO0_77 */
+ J721E_IOPAD(0x13c, PIN_INPUT, 7) /* (AF29) PRG0_PRU1_GPO15.GPIO0_78 */
+ >;
+ };
+
+ main_i2c3_pins_default: main-i2c3-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x270, PIN_INPUT_PULLUP, 4) /* (T26) MMC2_CLK.I2C3_SCL */
+ J721E_IOPAD(0x274, PIN_INPUT_PULLUP, 4) /* (T25) MMC2_CMD.I2C3_SDA */
+ >;
+ };
+
+ main_i2c4_pins_default: main-i2c4-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x1e0, PIN_INPUT_PULLUP, 2) /* (Y5) SPI1_D0.I2C4_SCL */
+ J721E_IOPAD(0x1dc, PIN_INPUT_PULLUP, 2) /* (Y1) SPI1_CLK.I2C4_SDA */
+ J721E_IOPAD(0x30, PIN_INPUT, 7) /* (AF24) PRG1_PRU0_GPO11.GPIO0_12 */
+ J721E_IOPAD(0x34, PIN_INPUT, 7) /* (AJ24) PRG1_PRU0_GPO12.GPIO0_13 */
+ >;
+ };
+
+ main_i2c5_pins_default: main-i2c5-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x150, PIN_INPUT_PULLUP, 2) /* (Y26) PRG0_MDIO0_MDIO.I2C5_SCL */
+ J721E_IOPAD(0x154, PIN_INPUT_PULLUP, 2) /* (AA27) PRG0_MDIO0_MDC.I2C5_SDA */
+ >;
+ };
+
+ main_i2c6_pins_default: main-i2c6-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x1d0, PIN_INPUT_PULLUP, 2) /* (AA3) SPI0_D1.I2C6_SCL */
+ J721E_IOPAD(0x1e4, PIN_INPUT_PULLUP, 2) /* (Y2) SPI1_D1.I2C6_SDA */
+ J721E_IOPAD(0x74, PIN_INPUT, 7) /* (AC21) PRG1_PRU1_GPO7.GPIO0_28 */
+ J721E_IOPAD(0xa4, PIN_INPUT, 7) /* (AH22) PRG1_PRU1_GPO19.GPIO0_40 */
+ >;
+ };
+
+ csi0_gpio_pins_default: csi0-gpio-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x19c, PIN_INPUT_PULLDOWN, 7) /* (W27) RGMII6_TD0.GPIO0_102 */
+ J721E_IOPAD(0x1a0, PIN_INPUT_PULLDOWN, 7) /* (W29) RGMII6_TXC.GPIO0_103 */
+ >;
+ };
+
+ csi1_gpio_pins_default: csi1-gpio-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x198, PIN_INPUT_PULLDOWN, 7) /* (V25) RGMII6_TD1.GPIO0_101 */
+ J721E_IOPAD(0x1b0, PIN_INPUT_PULLDOWN, 7) /* (W24) RGMII6_RD1.GPIO0_107 */
+ >;
+ };
+
+ pcie1_rst_pins_default: pcie1-rst-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x5c, PIN_INPUT, 7) /* (AG23) PRG1_PRU1_GPO1.GPIO0_22 */
+ >;
+ };
+};
+
+&wkup_pmx0 {
+ eeprom_wp_pins_default: eeprom-wp-pins-default {
+ pinctrl-single,pins = <
+ J721E_WKUP_IOPAD(0xc4, PIN_OUTPUT_PULLUP, 7) /* (G24) WKUP_GPIO0_5 */
+ >;
+ };
+
+ mcu_adc0_pins_default: mcu-adc0-pins-default {
+ pinctrl-single,pins = <
+ J721E_WKUP_IOPAD(0x130, PIN_INPUT, 0) /* (K25) MCU_ADC0_AIN0 */
+ J721E_WKUP_IOPAD(0x134, PIN_INPUT, 0) /* (K26) MCU_ADC0_AIN1 */
+ J721E_WKUP_IOPAD(0x138, PIN_INPUT, 0) /* (K28) MCU_ADC0_AIN2 */
+ J721E_WKUP_IOPAD(0x13c, PIN_INPUT, 0) /* (L28) MCU_ADC0_AIN3 */
+ J721E_WKUP_IOPAD(0x140, PIN_INPUT, 0) /* (K24) MCU_ADC0_AIN4 */
+ J721E_WKUP_IOPAD(0x144, PIN_INPUT, 0) /* (K27) MCU_ADC0_AIN5 */
+ J721E_WKUP_IOPAD(0x148, PIN_INPUT, 0) /* (K29) MCU_ADC0_AIN6 */
+ >;
+ };
+
+ mcu_adc1_pins_default: mcu-adc1-pins-default {
+ pinctrl-single,pins = <
+ J721E_WKUP_IOPAD(0x150, PIN_INPUT, 0) /* (N23) MCU_ADC1_AIN0 */
+ >;
+ };
+
+ mikro_bus_pins_default: mikro-bus-pins-default {
+ pinctrl-single,pins = <
+ J721E_WKUP_IOPAD(0x108, PIN_INPUT, 7) /* SDAPULLEN (E26) PMIC_POWER_EN0.WKUP_GPIO0_66 */
+ J721E_WKUP_IOPAD(0xd4, PIN_INPUT, 7) /* SDA (G26) WKUP_GPIO0_9.MCU_I2C1_SDA */
+ J721E_WKUP_IOPAD(0xf4, PIN_INPUT, 7) /* SDA (D25) MCU_I3C0_SDA.WKUP_GPIO0_61 */
+ J721E_WKUP_IOPAD(0xd0, PIN_INPUT, 7) /* SCL (G27) WKUP_GPIO0_8.MCU_I2C1_SCL */
+ J721E_WKUP_IOPAD(0xf0, PIN_INPUT, 7) /* SCL (D26) MCU_I3C0_SCL.WKUP_GPIO0_60 */
+
+ J721E_WKUP_IOPAD(0xb8, PIN_INPUT, 7) /* MOSI (F28) WKUP_GPIO0_2.MCU_SPI1_D1 */
+ J721E_WKUP_IOPAD(0xb4, PIN_INPUT, 7) /* MISO (F25) WKUP_GPIO0_1.MCU_SPI1_D0 */
+ J721E_WKUP_IOPAD(0xb0, PIN_INPUT, 7) /* CLK (F26) WKUP_GPIO0_0.MCU_SPI1_CLK */
+ J721E_WKUP_IOPAD(0xbc, PIN_INPUT, 7) /* CS (F27) WKUP_GPIO0_3.MCU_SPI1_CS0 */
+
+ J721E_WKUP_IOPAD(0x44, PIN_INPUT, 7) /* RX (G22) MCU_OSPI1_D1.WKUP_GPIO0_33 */
+ J721E_WKUP_IOPAD(0x48, PIN_INPUT, 7) /* TX (D23) MCU_OSPI1_D2.WKUP_GPIO0_34 */
+
+ J721E_WKUP_IOPAD(0x4c, PIN_INPUT, 7) /* INT (C23) MCU_OSPI1_D3.WKUP_GPIO0_35 */
+ J721E_WKUP_IOPAD(0x54, PIN_INPUT, 7) /* RST (E22) MCU_OSPI1_CSn1.WKUP_GPIO0_37 */
+ J721E_WKUP_IOPAD(0xdc, PIN_INPUT, 7) /* PWM (H27) WKUP_GPIO0_11 */
+ J721E_WKUP_IOPAD(0xac, PIN_INPUT, 7) /* AN (C29) MCU_MCAN0_RX.WKUP_GPIO0_59 */
+ >;
+ };
+
+ mcu_cpsw_pins_default: mcu-cpsw-pins-default {
+ pinctrl-single,pins = <
+ J721E_WKUP_IOPAD(0x84, PIN_INPUT, 0) /* (B24) MCU_RGMII1_RD0 */
+ J721E_WKUP_IOPAD(0x80, PIN_INPUT, 0) /* (A24) MCU_RGMII1_RD1 */
+ J721E_WKUP_IOPAD(0x7c, PIN_INPUT, 0) /* (D24) MCU_RGMII1_RD2 */
+ J721E_WKUP_IOPAD(0x78, PIN_INPUT, 0) /* (A25) MCU_RGMII1_RD3 */
+ J721E_WKUP_IOPAD(0x74, PIN_INPUT, 0) /* (C24) MCU_RGMII1_RXC */
+ J721E_WKUP_IOPAD(0x5c, PIN_INPUT, 0) /* (C25) MCU_RGMII1_RX_CTL */
+ J721E_WKUP_IOPAD(0x6c, PIN_OUTPUT, 0) /* (B25) MCU_RGMII1_TD0 */
+ J721E_WKUP_IOPAD(0x68, PIN_OUTPUT, 0) /* (A26) MCU_RGMII1_TD1 */
+ J721E_WKUP_IOPAD(0x64, PIN_OUTPUT, 0) /* (A27) MCU_RGMII1_TD2 */
+ J721E_WKUP_IOPAD(0x60, PIN_OUTPUT, 0) /* (A28) MCU_RGMII1_TD3 */
+ J721E_WKUP_IOPAD(0x70, PIN_OUTPUT, 0) /* (B26) MCU_RGMII1_TXC */
+ J721E_WKUP_IOPAD(0x58, PIN_OUTPUT, 0) /* (B27) MCU_RGMII1_TX_CTL */
+ >;
+ };
+
+ mcu_mdio_pins_default: mcu-mdio1-pins-default {
+ pinctrl-single,pins = <
+ J721E_WKUP_IOPAD(0x8c, PIN_OUTPUT, 0) /* (F23) MCU_MDIO0_MDC */
+ J721E_WKUP_IOPAD(0x88, PIN_INPUT, 0) /* (E23) MCU_MDIO0_MDIO */
+ >;
+ };
+
+ sw_pwr_pins_default: sw-pwr-pins-default {
+ pinctrl-single,pins = <
+ J721E_WKUP_IOPAD(0xc0, PIN_INPUT, 7) /* (G25) WKUP_GPIO0_4 */
+ >;
+ };
+
+ wkup_i2c0_pins_default: wkup-i2c0-pins-default {
+ pinctrl-single,pins = <
+ J721E_WKUP_IOPAD(0xf8, PIN_INPUT_PULLUP, 0) /* (J25) WKUP_I2C0_SCL */
+ J721E_WKUP_IOPAD(0xfc, PIN_INPUT_PULLUP, 0) /* (H24) WKUP_I2C0_SDA */
+ >;
+ };
+
+ mcu_usbss1_pins_default: mcu-usbss1-pins-default {
+ pinctrl-single,pins = <
+ J721E_WKUP_IOPAD(0x3c, PIN_OUTPUT_PULLUP, 5) /* (A23) MCU_OSPI1_LBCLKO.WKUP_GPIO0_30 */
+ >;
+ };
+};
+
+&wkup_uart0 {
+ /* Wakeup UART is used by TIFS firmware. */
+ status = "reserved";
+};
+
+&main_uart0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_uart0_pins_default>;
+ /* Shared with ATF on this platform */
+ power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>;
+};
+
+&main_sdhci0 {
+ /* eMMC */
+ non-removable;
+ ti,driver-strength-ohm = <50>;
+ disable-wp;
+};
+
+&main_sdhci1 {
+ /* SD Card */
+ vmmc-supply = <&vdd_mmc1>;
+ vqmmc-supply = <&vdd_sd_dv_alt>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_mmc1_pins_default>;
+ ti,driver-strength-ohm = <50>;
+ disable-wp;
+};
+
+&main_sdhci2 {
+ /* Unused */
+ status = "disabled";
+};
+
+&ospi0 {
+ /* Unused */
+ status = "disabled";
+};
+
+&ospi1 {
+ /* Unused */
+ status = "disabled";
+};
+
+&main_i2c0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c0_pins_default>;
+ clock-frequency = <400000>;
+};
+
+&main_i2c1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c1_pins_default &csi1_gpio_pins_default>;
+ clock-frequency = <400000>;
+};
+
+&main_i2c2 {
+ /* BBB Header: P9.19 and P9.20 */
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c2_pins_default>;
+ clock-frequency = <100000>;
+};
+
+&main_i2c3 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c3_pins_default>;
+ clock-frequency = <400000>;
+};
+
+&main_i2c4 {
+ /* BBB Header: P9.24 and P9.26 */
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c4_pins_default>;
+ clock-frequency = <100000>;
+};
+
+&main_i2c5 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c5_pins_default &csi0_gpio_pins_default>;
+ clock-frequency = <400000>;
+};
+
+&main_i2c6 {
+ /* BBB Header: P9.17 and P9.18 */
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c6_pins_default>;
+ clock-frequency = <100000>;
+ status = "okay";
+};
+
+&wkup_i2c0 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&wkup_i2c0_pins_default &eeprom_wp_pins_default>;
+ clock-frequency = <400000>;
+
+ eeprom@50 {
+ compatible = "atmel,24c04";
+ reg = <0x50>;
+ };
+};
+
+&main_gpio2 {
+ /* Unused */
+ status = "disabled";
+};
+
+&main_gpio3 {
+ /* Unused */
+ status = "disabled";
+};
+
+&main_gpio4 {
+ /* Unused */
+ status = "disabled";
+};
+
+&main_gpio5 {
+ /* Unused */
+ status = "disabled";
+};
+
+&main_gpio6 {
+ /* Unused */
+ status = "disabled";
+};
+
+&main_gpio7 {
+ /* Unused */
+ status = "disabled";
+};
+
+&wkup_gpio0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_adc0_pins_default &mcu_adc1_pins_default &mikro_bus_pins_default>;
+};
+
+&wkup_gpio1 {
+ /* Unused */
+ status = "disabled";
+};
+
+&usb_serdes_mux {
+ idle-states = <1>, <1>; /* USB0 to SERDES3, USB1 to SERDES2 */
+};
+
+&serdes_ln_ctrl {
+ idle-states = <J721E_SERDES0_LANE0_IP4_UNUSED>, <J721E_SERDES0_LANE1_IP4_UNUSED>,
+ <J721E_SERDES1_LANE0_PCIE1_LANE0>, <J721E_SERDES1_LANE1_PCIE1_LANE1>,
+ <J721E_SERDES2_LANE0_IP1_UNUSED>, <J721E_SERDES2_LANE1_USB3_1>,
+ <J721E_SERDES3_LANE0_USB3_0_SWAP>, <J721E_SERDES3_LANE1_USB3_0>,
+ <J721E_SERDES4_LANE0_EDP_LANE0>, <J721E_SERDES4_LANE1_EDP_LANE1>,
+ <J721E_SERDES4_LANE2_EDP_LANE2>, <J721E_SERDES4_LANE3_EDP_LANE3>;
+};
+
+&serdes_wiz3 {
+ typec-dir-gpios = <&main_gpio1 3 GPIO_ACTIVE_LOW>;
+ typec-dir-debounce-ms = <700>; /* TUSB321, tCCB_DEFAULT 133 ms */
+};
+
+&serdes3 {
+ serdes3_usb_link: phy@0 {
+ reg = <0>;
+ cdns,num-lanes = <2>;
+ #phy-cells = <0>;
+ cdns,phy-type = <PHY_TYPE_USB3>;
+ resets = <&serdes_wiz3 1>, <&serdes_wiz3 2>;
+ };
+};
+
+&serdes4 {
+ torrent_phy_dp: phy@0 {
+ reg = <0>;
+ resets = <&serdes_wiz4 1>;
+ cdns,phy-type = <PHY_TYPE_DP>;
+ cdns,num-lanes = <4>;
+ cdns,max-bit-rate = <5400>;
+ #phy-cells = <0>;
+ };
+};
+
+&mhdp {
+ phys = <&torrent_phy_dp>;
+ phy-names = "dpphy";
+ pinctrl-names = "default";
+ pinctrl-0 = <&dp0_pins_default>;
+};
+
+&usbss0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_usbss0_pins_default>;
+ ti,vbus-divider;
+};
+
+&usb0 {
+ dr_mode = "peripheral";
+ maximum-speed = "super-speed";
+ phys = <&serdes3_usb_link>;
+ phy-names = "cdns3,usb3-phy";
+};
+
+&serdes2 {
+ serdes2_usb_link: phy@1 {
+ reg = <1>;
+ cdns,num-lanes = <1>;
+ #phy-cells = <0>;
+ cdns,phy-type = <PHY_TYPE_USB3>;
+ resets = <&serdes_wiz2 2>;
+ };
+};
+
+&usbss1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_usbss1_pins_default &mcu_usbss1_pins_default>;
+ ti,vbus-divider;
+};
+
+&usb1 {
+ dr_mode = "host";
+ maximum-speed = "super-speed";
+ phys = <&serdes2_usb_link>;
+ phy-names = "cdns3,usb3-phy";
+};
+
+&tscadc0 {
+ /* BBB Header: P9.39, P9.40, P9.37, P9.38, P9.33, P9.36, P9.35 */
+ adc {
+ ti,adc-channels = <0 1 2 3 4 5 6>;
+ };
+};
+
+&tscadc1 {
+ /* MCU mikroBUS Header J10.1 - MCU_ADC1_AIN0 */
+ adc {
+ ti,adc-channels = <0>;
+ };
+};
+
+&mcu_cpsw {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_cpsw_pins_default>;
+};
+
+&davinci_mdio {
+ pinctrl-names = "default";
+ pinctrl-0 = <&mcu_mdio_pins_default>;
+
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+ ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+ };
+};
+
+&cpsw_port1 {
+ phy-mode = "rgmii-rxid";
+ phy-handle = <&phy0>;
+};
+
+&dss {
+ /*
+ * These clock assignments are chosen to enable the following outputs:
+ *
+ * VP0 - DisplayPort SST
+ * VP1 - DPI0
+ * VP2 - DSI
+ * VP3 - DPI1
+ */
+
+ assigned-clocks = <&k3_clks 152 1>, /* VP 1 pixel clock */
+ <&k3_clks 152 4>, /* VP 2 pixel clock */
+ <&k3_clks 152 9>, /* VP 3 pixel clock */
+ <&k3_clks 152 13>; /* VP 4 pixel clock */
+ assigned-clock-parents = <&k3_clks 152 2>, /* PLL16_HSDIV0 */
+ <&k3_clks 152 6>, /* PLL19_HSDIV0 */
+ <&k3_clks 152 11>, /* PLL18_HSDIV0 */
+ <&k3_clks 152 18>; /* PLL23_HSDIV0 */
+};
+
+&dss_ports {
+ port {
+ dpi0_out: endpoint {
+ remote-endpoint = <&dp0_in>;
+ };
+ };
+};
+
+&dp0_ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ dp0_in: endpoint {
+ remote-endpoint = <&dpi0_out>;
+ };
+ };
+
+ port@4 {
+ reg = <4>;
+ dp0_out: endpoint {
+ remote-endpoint = <&dp_connector_in>;
+ };
+ };
+};
+
+&serdes0 {
+ serdes0_pcie_link: phy@0 {
+ reg = <0>;
+ cdns,num-lanes = <1>;
+ #phy-cells = <0>;
+ cdns,phy-type = <PHY_TYPE_PCIE>;
+ resets = <&serdes_wiz0 1>;
+ };
+};
+
+&serdes1 {
+ serdes1_pcie_link: phy@0 {
+ reg = <0>;
+ cdns,num-lanes = <2>;
+ #phy-cells = <0>;
+ cdns,phy-type = <PHY_TYPE_PCIE>;
+ resets = <&serdes_wiz1 1>, <&serdes_wiz1 2>;
+ };
+};
+
+&pcie0_rc {
+ /* Unused */
+ status = "disabled";
+};
+
+&pcie1_rc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie1_rst_pins_default>;
+ phys = <&serdes1_pcie_link>;
+ phy-names = "pcie-phy";
+ num-lanes = <2>;
+ max-link-speed = <3>;
+ reset-gpios = <&main_gpio0 22 GPIO_ACTIVE_HIGH>;
+};
+
+&pcie2_rc {
+ /* Unused */
+ status = "disabled";
+};
+
+&pcie0_ep {
+ status = "disabled";
+ phys = <&serdes0_pcie_link>;
+ phy-names = "pcie-phy";
+ num-lanes = <1>;
+};
+
+&pcie1_ep {
+ status = "disabled";
+ phys = <&serdes1_pcie_link>;
+ phy-names = "pcie-phy";
+ num-lanes = <2>;
+};
+
+&pcie2_ep {
+ /* Unused */
+ status = "disabled";
+};
+
+&pcie3_rc {
+ /* Unused */
+ status = "disabled";
+};
+
+&pcie3_ep {
+ /* Unused */
+ status = "disabled";
+};
+
+&icssg0_mdio {
+ /* Unused */
+ status = "disabled";
+};
+
+&icssg1_mdio {
+ /* Unused */
+ status = "disabled";
+};
+
+&ufs_wrapper {
+ status = "disabled";
+};
+
+&mailbox0_cluster0 {
+ interrupts = <436>;
+
+ mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_mcu_r5fss0_core1: mbox-mcu-r5fss0-core1 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
+&mailbox0_cluster1 {
+ interrupts = <432>;
+
+ mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_main_r5fss0_core1: mbox-main-r5fss0-core1 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
+&mailbox0_cluster2 {
+ interrupts = <428>;
+
+ mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_main_r5fss1_core1: mbox-main-r5fss1-core1 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
+&mailbox0_cluster3 {
+ interrupts = <424>;
+
+ mbox_c66_0: mbox-c66-0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+
+ mbox_c66_1: mbox-c66-1 {
+ ti,mbox-rx = <2 0 0>;
+ ti,mbox-tx = <3 0 0>;
+ };
+};
+
+&mailbox0_cluster4 {
+ interrupts = <420>;
+
+ mbox_c71_0: mbox-c71-0 {
+ ti,mbox-rx = <0 0 0>;
+ ti,mbox-tx = <1 0 0>;
+ };
+};
+
+&mcu_r5fss0_core0 {
+ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>;
+ memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
+ <&mcu_r5fss0_core0_memory_region>;
+};
+
+&mcu_r5fss0_core1 {
+ mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core1>;
+ memory-region = <&mcu_r5fss0_core1_dma_memory_region>,
+ <&mcu_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss0_core0 {
+ mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core0>;
+ memory-region = <&main_r5fss0_core0_dma_memory_region>,
+ <&main_r5fss0_core0_memory_region>;
+};
+
+&main_r5fss0_core1 {
+ mboxes = <&mailbox0_cluster1 &mbox_main_r5fss0_core1>;
+ memory-region = <&main_r5fss0_core1_dma_memory_region>,
+ <&main_r5fss0_core1_memory_region>;
+};
+
+&main_r5fss1_core0 {
+ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core0>;
+ memory-region = <&main_r5fss1_core0_dma_memory_region>,
+ <&main_r5fss1_core0_memory_region>;
+};
+
+&main_r5fss1_core1 {
+ mboxes = <&mailbox0_cluster2 &mbox_main_r5fss1_core1>;
+ memory-region = <&main_r5fss1_core1_dma_memory_region>,
+ <&main_r5fss1_core1_memory_region>;
+};
+
+&c66_0 {
+ mboxes = <&mailbox0_cluster3 &mbox_c66_0>;
+ memory-region = <&c66_0_dma_memory_region>,
+ <&c66_0_memory_region>;
+};
+
+&c66_1 {
+ mboxes = <&mailbox0_cluster3 &mbox_c66_1>;
+ memory-region = <&c66_1_dma_memory_region>,
+ <&c66_1_memory_region>;
+};
+
+&c71_0 {
+ mboxes = <&mailbox0_cluster4 &mbox_c71_0>;
+ memory-region = <&c71_0_dma_memory_region>,
+ <&c71_0_memory_region>;
+};
diff --git a/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts
index b1691ac3442d..7db0603125aa 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts
+++ b/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts
@@ -96,7 +96,7 @@
<3300000 0x1>;
};
- sound0: sound@0 {
+ sound0: sound-0 {
compatible = "ti,j721e-cpb-audio";
model = "j721e-cpb";
@@ -370,38 +370,30 @@
status = "reserved";
};
-&main_uart0 {
- power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>;
-};
-
-&main_uart3 {
- /* UART not brought out */
- status = "disabled";
+&mcu_uart0 {
+ status = "okay";
+ /* Default pinmux */
};
-&main_uart5 {
- /* UART not brought out */
- status = "disabled";
+&main_uart0 {
+ status = "okay";
+ /* Shared with ATF on this platform */
+ power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>;
};
-&main_uart6 {
- /* UART not brought out */
- status = "disabled";
+&main_uart1 {
+ status = "okay";
+ /* Default pinmux */
};
-&main_uart7 {
- /* UART not brought out */
- status = "disabled";
+&main_uart2 {
+ status = "okay";
+ /* Default pinmux */
};
-&main_uart8 {
- /* UART not brought out */
- status = "disabled";
-};
-
-&main_uart9 {
- /* UART not brought out */
- status = "disabled";
+&main_uart4 {
+ status = "okay";
+ /* Default pinmux */
};
&main_gpio2 {
@@ -537,6 +529,7 @@
};
&main_i2c0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c0_pins_default>;
clock-frequency = <400000>;
@@ -573,6 +566,7 @@
};
&main_i2c1 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c1_pins_default>;
clock-frequency = <400000>;
@@ -598,6 +592,7 @@
};
&main_i2c3 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c3_pins_default>;
clock-frequency = <400000>;
@@ -636,6 +631,7 @@
};
&main_i2c6 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c6_pins_default>;
clock-frequency = <400000>;
@@ -713,47 +709,8 @@
};
};
-&mcasp0 {
- status = "disabled";
-};
-
-&mcasp1 {
- status = "disabled";
-};
-
-&mcasp2 {
- status = "disabled";
-};
-
-&mcasp3 {
- status = "disabled";
-};
-
-&mcasp4 {
- status = "disabled";
-};
-
-&mcasp5 {
- status = "disabled";
-};
-
-&mcasp6 {
- status = "disabled";
-};
-
-&mcasp7 {
- status = "disabled";
-};
-
-&mcasp8 {
- status = "disabled";
-};
-
-&mcasp9 {
- status = "disabled";
-};
-
&mcasp10 {
+ status = "okay";
#sound-dai-cells = <0>;
pinctrl-names = "default";
@@ -771,10 +728,6 @@
rx-num-evt = <0>;
};
-&mcasp11 {
- status = "disabled";
-};
-
&cmn_refclk1 {
clock-frequency = <100000000>;
};
@@ -925,73 +878,29 @@
};
&mcu_mcan0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&mcu_mcan0_pins_default>;
phys = <&transceiver1>;
};
&mcu_mcan1 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&mcu_mcan1_pins_default>;
phys = <&transceiver2>;
};
&main_mcan0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_mcan0_pins_default>;
phys = <&transceiver3>;
};
-&main_mcan1 {
- status = "disabled";
-};
-
&main_mcan2 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_mcan2_pins_default>;
phys = <&transceiver4>;
};
-
-&main_mcan3 {
- status = "disabled";
-};
-
-&main_mcan4 {
- status = "disabled";
-};
-
-&main_mcan5 {
- status = "disabled";
-};
-
-&main_mcan6 {
- status = "disabled";
-};
-
-&main_mcan7 {
- status = "disabled";
-};
-
-&main_mcan8 {
- status = "disabled";
-};
-
-&main_mcan9 {
- status = "disabled";
-};
-
-&main_mcan10 {
- status = "disabled";
-};
-
-&main_mcan11 {
- status = "disabled";
-};
-
-&main_mcan12 {
- status = "disabled";
-};
-
-&main_mcan13 {
- status = "disabled";
-};
diff --git a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
index 917c9dc99efa..c935622f0102 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi
@@ -66,7 +66,73 @@
#mux-control-cells = <1>;
mux-reg-masks = <0x4000 0x8000000>, /* USB0 to SERDES0/3 mux */
<0x4010 0x8000000>; /* USB1 to SERDES1/2 mux */
- };
+ };
+
+ ehrpwm_tbclk: clock-controller@4140 {
+ compatible = "ti,am654-ehrpwm-tbclk", "syscon";
+ reg = <0x4140 0x18>;
+ #clock-cells = <1>;
+ };
+ };
+
+ main_ehrpwm0: pwm@3000000 {
+ compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x00 0x3000000 0x00 0x100>;
+ power-domains = <&k3_pds 83 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&ehrpwm_tbclk 0>, <&k3_clks 83 0>;
+ clock-names = "tbclk", "fck";
+ status = "disabled";
+ };
+
+ main_ehrpwm1: pwm@3010000 {
+ compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x00 0x3010000 0x00 0x100>;
+ power-domains = <&k3_pds 84 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&ehrpwm_tbclk 1>, <&k3_clks 84 0>;
+ clock-names = "tbclk", "fck";
+ status = "disabled";
+ };
+
+ main_ehrpwm2: pwm@3020000 {
+ compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x00 0x3020000 0x00 0x100>;
+ power-domains = <&k3_pds 85 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&ehrpwm_tbclk 2>, <&k3_clks 85 0>;
+ clock-names = "tbclk", "fck";
+ status = "disabled";
+ };
+
+ main_ehrpwm3: pwm@3030000 {
+ compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x00 0x3030000 0x00 0x100>;
+ power-domains = <&k3_pds 86 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&ehrpwm_tbclk 3>, <&k3_clks 86 0>;
+ clock-names = "tbclk", "fck";
+ status = "disabled";
+ };
+
+ main_ehrpwm4: pwm@3040000 {
+ compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x00 0x3040000 0x00 0x100>;
+ power-domains = <&k3_pds 87 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&ehrpwm_tbclk 4>, <&k3_clks 87 0>;
+ clock-names = "tbclk", "fck";
+ status = "disabled";
+ };
+
+ main_ehrpwm5: pwm@3050000 {
+ compatible = "ti,am654-ehrpwm", "ti,am3352-ehrpwm";
+ #pwm-cells = <3>;
+ reg = <0x00 0x3050000 0x00 0x100>;
+ power-domains = <&k3_pds 88 TI_SCI_PD_EXCLUSIVE>;
+ clocks = <&ehrpwm_tbclk 5>, <&k3_clks 88 0>;
+ clock-names = "tbclk", "fck";
+ status = "disabled";
};
gic500: interrupt-controller@1800000 {
@@ -176,6 +242,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster1: mailbox@31f81000 {
@@ -185,6 +252,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster2: mailbox@31f82000 {
@@ -194,6 +262,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster3: mailbox@31f83000 {
@@ -203,6 +272,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster4: mailbox@31f84000 {
@@ -212,6 +282,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster5: mailbox@31f85000 {
@@ -221,6 +292,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster6: mailbox@31f86000 {
@@ -230,6 +302,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster7: mailbox@31f87000 {
@@ -239,6 +312,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster8: mailbox@31f88000 {
@@ -248,6 +322,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster9: mailbox@31f89000 {
@@ -257,6 +332,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster10: mailbox@31f8a000 {
@@ -266,6 +342,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster11: mailbox@31f8b000 {
@@ -275,6 +352,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
main_ringacc: ringacc@3c000000 {
@@ -337,13 +415,11 @@
dmas = <&main_udmap 0xc000>, <&main_udmap 0x4000>,
<&main_udmap 0x4001>;
dma-names = "tx", "rx1", "rx2";
- dma-coherent;
rng: rng@4e10000 {
compatible = "inside-secure,safexcel-eip76";
reg = <0x0 0x4e10000 0x0 0x7d>;
interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&k3_clks 264 2>;
};
};
@@ -840,6 +916,7 @@
power-domains = <&k3_pds 146 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 146 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart1: serial@2810000 {
@@ -851,6 +928,7 @@
power-domains = <&k3_pds 278 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 278 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart2: serial@2820000 {
@@ -862,6 +940,7 @@
power-domains = <&k3_pds 279 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 279 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart3: serial@2830000 {
@@ -873,6 +952,7 @@
power-domains = <&k3_pds 280 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 280 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart4: serial@2840000 {
@@ -884,6 +964,7 @@
power-domains = <&k3_pds 281 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 281 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart5: serial@2850000 {
@@ -895,6 +976,7 @@
power-domains = <&k3_pds 282 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 282 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart6: serial@2860000 {
@@ -906,6 +988,7 @@
power-domains = <&k3_pds 283 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 283 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart7: serial@2870000 {
@@ -917,6 +1000,7 @@
power-domains = <&k3_pds 284 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 284 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart8: serial@2880000 {
@@ -928,6 +1012,7 @@
power-domains = <&k3_pds 285 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 285 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_uart9: serial@2890000 {
@@ -939,6 +1024,7 @@
power-domains = <&k3_pds 286 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 286 0>;
clock-names = "fclk";
+ status = "disabled";
};
main_gpio0: gpio@600000 {
@@ -1219,6 +1305,7 @@
clock-names = "fck";
clocks = <&k3_clks 187 0>;
power-domains = <&k3_pds 187 TI_SCI_PD_SHARED>;
+ status = "disabled";
};
main_i2c1: i2c@2010000 {
@@ -1230,6 +1317,7 @@
clock-names = "fck";
clocks = <&k3_clks 188 0>;
power-domains = <&k3_pds 188 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_i2c2: i2c@2020000 {
@@ -1241,6 +1329,7 @@
clock-names = "fck";
clocks = <&k3_clks 189 0>;
power-domains = <&k3_pds 189 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_i2c3: i2c@2030000 {
@@ -1252,6 +1341,7 @@
clock-names = "fck";
clocks = <&k3_clks 190 0>;
power-domains = <&k3_pds 190 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_i2c4: i2c@2040000 {
@@ -1263,6 +1353,7 @@
clock-names = "fck";
clocks = <&k3_clks 191 0>;
power-domains = <&k3_pds 191 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_i2c5: i2c@2050000 {
@@ -1274,6 +1365,7 @@
clock-names = "fck";
clocks = <&k3_clks 192 0>;
power-domains = <&k3_pds 192 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_i2c6: i2c@2060000 {
@@ -1285,6 +1377,7 @@
clock-names = "fck";
clocks = <&k3_clks 193 0>;
power-domains = <&k3_pds 193 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
ufs_wrapper: ufs-wrapper@4e80000 {
@@ -1408,6 +1501,7 @@
clocks = <&k3_clks 174 1>;
clock-names = "fck";
power-domains = <&k3_pds 174 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcasp1: mcasp@2b10000 {
@@ -1425,6 +1519,7 @@
clocks = <&k3_clks 175 1>;
clock-names = "fck";
power-domains = <&k3_pds 175 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcasp2: mcasp@2b20000 {
@@ -1442,6 +1537,7 @@
clocks = <&k3_clks 176 1>;
clock-names = "fck";
power-domains = <&k3_pds 176 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcasp3: mcasp@2b30000 {
@@ -1459,6 +1555,7 @@
clocks = <&k3_clks 177 1>;
clock-names = "fck";
power-domains = <&k3_pds 177 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcasp4: mcasp@2b40000 {
@@ -1476,6 +1573,7 @@
clocks = <&k3_clks 178 1>;
clock-names = "fck";
power-domains = <&k3_pds 178 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcasp5: mcasp@2b50000 {
@@ -1493,6 +1591,7 @@
clocks = <&k3_clks 179 1>;
clock-names = "fck";
power-domains = <&k3_pds 179 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcasp6: mcasp@2b60000 {
@@ -1510,6 +1609,7 @@
clocks = <&k3_clks 180 1>;
clock-names = "fck";
power-domains = <&k3_pds 180 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcasp7: mcasp@2b70000 {
@@ -1527,6 +1627,7 @@
clocks = <&k3_clks 181 1>;
clock-names = "fck";
power-domains = <&k3_pds 181 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcasp8: mcasp@2b80000 {
@@ -1544,6 +1645,7 @@
clocks = <&k3_clks 182 1>;
clock-names = "fck";
power-domains = <&k3_pds 182 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcasp9: mcasp@2b90000 {
@@ -1561,6 +1663,7 @@
clocks = <&k3_clks 183 1>;
clock-names = "fck";
power-domains = <&k3_pds 183 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcasp10: mcasp@2ba0000 {
@@ -1578,6 +1681,7 @@
clocks = <&k3_clks 184 1>;
clock-names = "fck";
power-domains = <&k3_pds 184 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcasp11: mcasp@2bb0000 {
@@ -1595,6 +1699,7 @@
clocks = <&k3_clks 185 1>;
clock-names = "fck";
power-domains = <&k3_pds 185 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
watchdog0: watchdog@2200000 {
@@ -2027,6 +2132,7 @@
<GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan1: can@2711000 {
@@ -2041,6 +2147,7 @@
<GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan2: can@2721000 {
@@ -2055,6 +2162,7 @@
<GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan3: can@2731000 {
@@ -2069,6 +2177,7 @@
<GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan4: can@2741000 {
@@ -2083,6 +2192,7 @@
<GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan5: can@2751000 {
@@ -2097,6 +2207,7 @@
<GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan6: can@2761000 {
@@ -2111,6 +2222,7 @@
<GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan7: can@2771000 {
@@ -2125,6 +2237,7 @@
<GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan8: can@2781000 {
@@ -2139,6 +2252,7 @@
<GIC_SPI 577 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan9: can@2791000 {
@@ -2153,6 +2267,7 @@
<GIC_SPI 580 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan10: can@27a1000 {
@@ -2167,6 +2282,7 @@
<GIC_SPI 583 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan11: can@27b1000 {
@@ -2181,6 +2297,7 @@
<GIC_SPI 586 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan12: can@27c1000 {
@@ -2195,6 +2312,7 @@
<GIC_SPI 589 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan13: can@27d1000 {
@@ -2209,5 +2327,6 @@
<GIC_SPI 592 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
};
diff --git a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi
index df08724bbf1c..8ac78034d5d6 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721e-mcu-wakeup.dtsi
@@ -79,6 +79,7 @@
power-domains = <&k3_pds 287 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 287 0>;
clock-names = "fclk";
+ status = "disabled";
};
mcu_uart0: serial@40a00000 {
@@ -90,6 +91,7 @@
power-domains = <&k3_pds 149 TI_SCI_PD_EXCLUSIVE>;
clocks = <&k3_clks 149 0>;
clock-names = "fclk";
+ status = "disabled";
};
wkup_gpio_intr: interrupt-controller@42200000 {
@@ -145,6 +147,7 @@
clock-names = "fck";
clocks = <&k3_clks 194 0>;
power-domains = <&k3_pds 194 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcu_i2c1: i2c@40b10000 {
@@ -156,6 +159,7 @@
clock-names = "fck";
clocks = <&k3_clks 195 0>;
power-domains = <&k3_pds 195 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
wkup_i2c0: i2c@42120000 {
@@ -167,6 +171,7 @@
clock-names = "fck";
clocks = <&k3_clks 197 0>;
power-domains = <&k3_pds 197 TI_SCI_PD_SHARED>;
+ status = "disabled";
};
fss: fss@47000000 {
@@ -216,7 +221,7 @@
clocks = <&k3_clks 0 1>;
assigned-clocks = <&k3_clks 0 3>;
assigned-clock-rates = <60000000>;
- clock-names = "adc_tsc_fck";
+ clock-names = "fck";
dmas = <&main_udmap 0x7400>,
<&main_udmap 0x7401>;
dma-names = "fifo0", "fifo1";
@@ -235,7 +240,7 @@
clocks = <&k3_clks 1 1>;
assigned-clocks = <&k3_clks 1 3>;
assigned-clock-rates = <60000000>;
- clock-names = "adc_tsc_fck";
+ clock-names = "fck";
dmas = <&main_udmap 0x7402>,
<&main_udmap 0x7403>;
dma-names = "fifo0", "fifo1";
@@ -403,6 +408,7 @@
<GIC_SPI 833 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
mcu_mcan1: can@40568000 {
@@ -417,5 +423,6 @@
<GIC_SPI 836 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
};
diff --git a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts
index 80358cba6954..4640d280c85c 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e-sk.dts
+++ b/arch/arm64/boot/dts/ti/k3-j721e-sk.dts
@@ -400,6 +400,47 @@
J721E_IOPAD(0x124, PIN_INPUT, 7) /* (Y24) PRG0_PRU1_GPO9.GPIO0_72 */
>;
};
+
+ main_i2c5_pins_default: main-i2c5-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x150, PIN_INPUT_PULLUP, 2) /* (Y26) PRG0_MDIO0_MDIO.I2C5_SCL */
+ J721E_IOPAD(0x154, PIN_INPUT_PULLUP, 2) /* (AA27) PRG0_MDIO0_MDC.I2C5_SDA */
+ >;
+ };
+
+ rpi_header_gpio0_pins_default: rpi-header-gpio0-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x01C, PIN_INPUT, 7) /* (AD22) PRG1_PRU0_GPO6.GPIO0_7 */
+ J721E_IOPAD(0x120, PIN_INPUT, 7) /* (AA28) PRG0_PRU1_GPO8.GPIO0_71 */
+ J721E_IOPAD(0x14C, PIN_INPUT, 7) /* (AA29) PRG0_PRU1_GPO19.GPIO0_82 */
+ J721E_IOPAD(0x02C, PIN_INPUT, 7) /* (AD21) PRG1_PRU0_GPO10.GPIO0_11 */
+ J721E_IOPAD(0x198, PIN_INPUT, 7) /* (V25) RGMII6_TD1.GPIO0_101 */
+ J721E_IOPAD(0x1B0, PIN_INPUT, 7) /* (W24) RGMII6_RD1.GPIO0_107 */
+ J721E_IOPAD(0x1A0, PIN_INPUT, 7) /* (W29) RGMII6_TXC.GPIO0_103 */
+ J721E_IOPAD(0x008, PIN_INPUT, 7) /* (AG22) PRG1_PRU0_GPO1.GPIO0_2 */
+ J721E_IOPAD(0x1D0, PIN_INPUT, 7) /* (AA3) SPI0_D1.GPIO0_115 */
+ J721E_IOPAD(0x11C, PIN_INPUT, 7) /* (AA24) PRG0_PRU1_GPO7.GPIO0_70 */
+ J721E_IOPAD(0x148, PIN_INPUT, 7) /* (AA26) PRG0_PRU1_GPO18.GPIO0_81 */
+ J721E_IOPAD(0x004, PIN_INPUT, 7) /* (AC23) PRG1_PRU0_GPO0.GPIO0_1 */
+ J721E_IOPAD(0x014, PIN_INPUT, 7) /* (AH23) PRG1_PRU0_GPO4.GPIO0_5 */
+ J721E_IOPAD(0x020, PIN_INPUT, 7) /* (AE20) PRG1_PRU0_GPO7.GPIO0_8 */
+ J721E_IOPAD(0x19C, PIN_INPUT, 7) /* (W27) RGMII6_TD0.GPIO0_102 */
+ J721E_IOPAD(0x1B4, PIN_INPUT, 7) /* (W25) RGMII6_RD0.GPIO0_108 */
+ J721E_IOPAD(0x188, PIN_INPUT, 7) /* (Y28) RGMII6_TX_CTL.GPIO0_97 */
+ J721E_IOPAD(0x00C, PIN_INPUT, 7) /* (AF22) PRG1_PRU0_GPO2.GPIO0_3 */
+ J721E_IOPAD(0x010, PIN_INPUT, 7) /* (AJ23) PRG1_PRU0_GPO3.GPIO0_4 */
+ J721E_IOPAD(0x178, PIN_INPUT, 7) /* (U27) RGMII5_RD3.GPIO0_93 */
+ J721E_IOPAD(0x17C, PIN_INPUT, 7) /* (U24) RGMII5_RD2.GPIO0_94 */
+ J721E_IOPAD(0x190, PIN_INPUT, 7) /* (W23) RGMII6_TD3.GPIO0_99 */
+ J721E_IOPAD(0x18C, PIN_INPUT, 7) /* (V23) RGMII6_RX_CTL.GPIO0_98 */
+ >;
+ };
+
+ rpi_header_gpio1_pins_default: rpi-header-gpio1-pins-default {
+ pinctrl-single,pins = <
+ J721E_IOPAD(0x234, PIN_INPUT, 7) /* (U3) EXT_REFCLK1.GPIO1_12 */
+ >;
+ };
};
&wkup_pmx0 {
@@ -475,46 +516,22 @@
status = "reserved";
};
+&mcu_uart0 {
+ status = "okay";
+ /* Default pinmux */
+};
+
&main_uart0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_uart0_pins_default>;
/* Shared with ATF on this platform */
power-domains = <&k3_pds 146 TI_SCI_PD_SHARED>;
};
-&main_uart2 {
- /* Brought out on RPi header */
- status = "disabled";
-};
-
-&main_uart3 {
- /* UART not brought out */
- status = "disabled";
-};
-
-&main_uart5 {
- /* UART not brought out */
- status = "disabled";
-};
-
-&main_uart6 {
- /* UART not brought out */
- status = "disabled";
-};
-
-&main_uart7 {
- /* UART not brought out */
- status = "disabled";
-};
-
-&main_uart8 {
- /* UART not brought out */
- status = "disabled";
-};
-
-&main_uart9 {
- /* Brought out on M.2 E Key */
- status = "disabled";
+&main_uart1 {
+ status = "okay";
+ /* Default pinmux */
};
&main_sdhci0 {
@@ -561,6 +578,7 @@
};
&main_i2c0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c0_pins_default>;
clock-frequency = <400000>;
@@ -588,18 +606,15 @@
};
&main_i2c1 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c1_pins_default>;
/* i2c1 is used for DVI DDC, so we need to use 100kHz */
clock-frequency = <100000>;
};
-&main_i2c2 {
- /* Unused */
- status = "disabled";
-};
-
&main_i2c3 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c3_pins_default>;
clock-frequency = <400000>;
@@ -626,19 +641,22 @@
};
};
-&main_i2c4 {
- /* Unused */
- status = "disabled";
-};
-
&main_i2c5 {
/* Brought out on RPi Header */
- status = "disabled";
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&main_i2c5_pins_default>;
+ clock-frequency = <400000>;
};
-&main_i2c6 {
- /* Unused */
- status = "disabled";
+&main_gpio0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&rpi_header_gpio0_pins_default>;
+};
+
+&main_gpio1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&rpi_header_gpio1_pins_default>;
};
&main_gpio2 {
@@ -837,66 +855,6 @@
};
};
-&mcasp0 {
- /* Unused */
- status = "disabled";
-};
-
-&mcasp1 {
- /* Unused */
- status = "disabled";
-};
-
-&mcasp2 {
- /* Unused */
- status = "disabled";
-};
-
-&mcasp3 {
- /* Unused */
- status = "disabled";
-};
-
-&mcasp4 {
- /* Unused */
- status = "disabled";
-};
-
-&mcasp5 {
- /* Unused */
- status = "disabled";
-};
-
-&mcasp6 {
- /* Brought out on RPi header */
- status = "disabled";
-};
-
-&mcasp7 {
- /* Unused */
- status = "disabled";
-};
-
-&mcasp8 {
- /* Unused */
- status = "disabled";
-};
-
-&mcasp9 {
- /* Unused */
- status = "disabled";
-};
-
-&mcasp10 {
- /* Unused */
- status = "disabled";
-};
-
-&mcasp11 {
- /* Brought out on M.2 E Key */
- status = "disabled";
-};
-
&serdes0 {
serdes0_pcie_link: phy@0 {
reg = <0>;
@@ -984,6 +942,7 @@
};
&mailbox0_cluster0 {
+ status = "okay";
interrupts = <436>;
mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
@@ -998,6 +957,7 @@
};
&mailbox0_cluster1 {
+ status = "okay";
interrupts = <432>;
mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 {
@@ -1012,6 +972,7 @@
};
&mailbox0_cluster2 {
+ status = "okay";
interrupts = <428>;
mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 {
@@ -1026,6 +987,7 @@
};
&mailbox0_cluster3 {
+ status = "okay";
interrupts = <424>;
mbox_c66_0: mbox-c66-0 {
@@ -1040,6 +1002,7 @@
};
&mailbox0_cluster4 {
+ status = "okay";
interrupts = <420>;
mbox_c71_0: mbox-c71-0 {
@@ -1048,34 +1011,6 @@
};
};
-&mailbox0_cluster5 {
- status = "disabled";
-};
-
-&mailbox0_cluster6 {
- status = "disabled";
-};
-
-&mailbox0_cluster7 {
- status = "disabled";
-};
-
-&mailbox0_cluster8 {
- status = "disabled";
-};
-
-&mailbox0_cluster9 {
- status = "disabled";
-};
-
-&mailbox0_cluster10 {
- status = "disabled";
-};
-
-&mailbox0_cluster11 {
- status = "disabled";
-};
-
&mcu_r5fss0_core0 {
mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>;
memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
diff --git a/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi
index e36335232cf8..e289d5b44356 100644
--- a/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721e-som-p0.dtsi
@@ -186,6 +186,7 @@
};
&mailbox0_cluster0 {
+ status = "okay";
interrupts = <436>;
mbox_mcu_r5fss0_core0: mbox-mcu-r5fss0-core0 {
@@ -200,6 +201,7 @@
};
&mailbox0_cluster1 {
+ status = "okay";
interrupts = <432>;
mbox_main_r5fss0_core0: mbox-main-r5fss0-core0 {
@@ -214,6 +216,7 @@
};
&mailbox0_cluster2 {
+ status = "okay";
interrupts = <428>;
mbox_main_r5fss1_core0: mbox-main-r5fss1-core0 {
@@ -228,6 +231,7 @@
};
&mailbox0_cluster3 {
+ status = "okay";
interrupts = <424>;
mbox_c66_0: mbox-c66-0 {
@@ -242,6 +246,7 @@
};
&mailbox0_cluster4 {
+ status = "okay";
interrupts = <420>;
mbox_c71_0: mbox-c71-0 {
@@ -250,34 +255,6 @@
};
};
-&mailbox0_cluster5 {
- status = "disabled";
-};
-
-&mailbox0_cluster6 {
- status = "disabled";
-};
-
-&mailbox0_cluster7 {
- status = "disabled";
-};
-
-&mailbox0_cluster8 {
- status = "disabled";
-};
-
-&mailbox0_cluster9 {
- status = "disabled";
-};
-
-&mailbox0_cluster10 {
- status = "disabled";
-};
-
-&mailbox0_cluster11 {
- status = "disabled";
-};
-
&mcu_r5fss0_core0 {
mboxes = <&mailbox0_cluster0 &mbox_mcu_r5fss0_core0>;
memory-region = <&mcu_r5fss0_core0_dma_memory_region>,
diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts
index b210cc07c539..a7aa6cf08acd 100644
--- a/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-common-proc-board.dts
@@ -219,49 +219,19 @@
status = "reserved";
};
-&main_uart0 {
- status = "disabled";
-};
-
-&main_uart1 {
- status = "disabled";
-};
-
-&main_uart2 {
- status = "disabled";
-};
-
-&main_uart3 {
- status = "disabled";
-};
-
-&main_uart4 {
- status = "disabled";
-};
-
-&main_uart5 {
- status = "disabled";
-};
-
-&main_uart6 {
- status = "disabled";
-};
-
-&main_uart7 {
- status = "disabled";
+&mcu_uart0 {
+ status = "okay";
+ /* Default pinmux */
};
&main_uart8 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_uart8_pins_default>;
/* Shared with TFA on this platform */
power-domains = <&k3_pds 357 TI_SCI_PD_SHARED>;
};
-&main_uart9 {
- status = "disabled";
-};
-
&main_i2c0 {
clock-frequency = <400000>;
@@ -291,30 +261,6 @@
};
};
-&main_i2c1 {
- status = "disabled";
-};
-
-&main_i2c2 {
- status = "disabled";
-};
-
-&main_i2c3 {
- status = "disabled";
-};
-
-&main_i2c4 {
- status = "disabled";
-};
-
-&main_i2c5 {
- status = "disabled";
-};
-
-&main_i2c6 {
- status = "disabled";
-};
-
&main_sdhci0 {
/* eMMC */
non-removable;
@@ -351,81 +297,15 @@
};
&mcu_mcan0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&mcu_mcan0_pins_default>;
phys = <&transceiver1>;
};
&mcu_mcan1 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&mcu_mcan1_pins_default>;
phys = <&transceiver2>;
};
-
-&main_mcan0 {
- status = "disabled";
-};
-
-&main_mcan1 {
- status = "disabled";
-};
-
-&main_mcan2 {
- status = "disabled";
-};
-
-&main_mcan3 {
- status = "disabled";
-};
-
-&main_mcan4 {
- status = "disabled";
-};
-
-&main_mcan5 {
- status = "disabled";
-};
-
-&main_mcan6 {
- status = "disabled";
-};
-
-&main_mcan7 {
- status = "disabled";
-};
-
-&main_mcan8 {
- status = "disabled";
-};
-
-&main_mcan9 {
- status = "disabled";
-};
-
-&main_mcan10 {
- status = "disabled";
-};
-
-&main_mcan11 {
- status = "disabled";
-};
-
-&main_mcan12 {
- status = "disabled";
-};
-
-&main_mcan13 {
- status = "disabled";
-};
-
-&main_mcan14 {
- status = "disabled";
-};
-
-&main_mcan15 {
- status = "disabled";
-};
-
-&main_mcan17 {
- status = "disabled";
-};
diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
index 34e7d577ae13..8915132efcc1 100644
--- a/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-main.dtsi
@@ -60,7 +60,7 @@
#interrupt-cells = <1>;
ti,sci = <&sms>;
ti,sci-dev-id = <148>;
- ti,interrupt-ranges = <8 360 56>;
+ ti,interrupt-ranges = <8 392 56>;
};
main_pmx0: pinctrl@11c000 {
@@ -72,6 +72,25 @@
pinctrl-single,function-mask = <0xffffffff>;
};
+ main_crypto: crypto@4e00000 {
+ compatible = "ti,j721e-sa2ul";
+ reg = <0x00 0x04e00000 0x00 0x1200>;
+ power-domains = <&k3_pds 297 TI_SCI_PD_EXCLUSIVE>;
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges = <0x00 0x04e00000 0x00 0x04e00000 0x00 0x30000>;
+
+ dmas = <&main_udmap 0xca40>, <&main_udmap 0x4a40>,
+ <&main_udmap 0x4a41>;
+ dma-names = "tx", "rx1", "rx2";
+
+ rng: rng@4e10000 {
+ compatible = "inside-secure,safexcel-eip76";
+ reg = <0x00 0x04e10000 0x00 0x7d>;
+ interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>;
+ };
+ };
+
main_uart0: serial@2800000 {
compatible = "ti,j721e-uart", "ti,am654-uart";
reg = <0x00 0x02800000 0x00 0x200>;
@@ -80,6 +99,7 @@
clocks = <&k3_clks 146 3>;
clock-names = "fclk";
power-domains = <&k3_pds 146 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_uart1: serial@2810000 {
@@ -90,6 +110,7 @@
clocks = <&k3_clks 350 3>;
clock-names = "fclk";
power-domains = <&k3_pds 350 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_uart2: serial@2820000 {
@@ -100,6 +121,7 @@
clocks = <&k3_clks 351 3>;
clock-names = "fclk";
power-domains = <&k3_pds 351 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_uart3: serial@2830000 {
@@ -110,6 +132,7 @@
clocks = <&k3_clks 352 3>;
clock-names = "fclk";
power-domains = <&k3_pds 352 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_uart4: serial@2840000 {
@@ -120,6 +143,7 @@
clocks = <&k3_clks 353 3>;
clock-names = "fclk";
power-domains = <&k3_pds 353 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_uart5: serial@2850000 {
@@ -130,6 +154,7 @@
clocks = <&k3_clks 354 3>;
clock-names = "fclk";
power-domains = <&k3_pds 354 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_uart6: serial@2860000 {
@@ -140,6 +165,7 @@
clocks = <&k3_clks 355 3>;
clock-names = "fclk";
power-domains = <&k3_pds 355 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_uart7: serial@2870000 {
@@ -150,6 +176,7 @@
clocks = <&k3_clks 356 3>;
clock-names = "fclk";
power-domains = <&k3_pds 356 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_uart8: serial@2880000 {
@@ -160,6 +187,7 @@
clocks = <&k3_clks 357 3>;
clock-names = "fclk";
power-domains = <&k3_pds 357 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_uart9: serial@2890000 {
@@ -170,6 +198,7 @@
clocks = <&k3_clks 358 3>;
clock-names = "fclk";
power-domains = <&k3_pds 358 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_gpio0: gpio@600000 {
@@ -256,6 +285,7 @@
clocks = <&k3_clks 215 1>;
clock-names = "fck";
power-domains = <&k3_pds 215 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_i2c2: i2c@2020000 {
@@ -267,6 +297,7 @@
clocks = <&k3_clks 216 1>;
clock-names = "fck";
power-domains = <&k3_pds 216 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_i2c3: i2c@2030000 {
@@ -278,6 +309,7 @@
clocks = <&k3_clks 217 1>;
clock-names = "fck";
power-domains = <&k3_pds 217 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_i2c4: i2c@2040000 {
@@ -289,6 +321,7 @@
clocks = <&k3_clks 218 1>;
clock-names = "fck";
power-domains = <&k3_pds 218 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_i2c5: i2c@2050000 {
@@ -300,6 +333,7 @@
clocks = <&k3_clks 219 1>;
clock-names = "fck";
power-domains = <&k3_pds 219 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_i2c6: i2c@2060000 {
@@ -311,6 +345,7 @@
clocks = <&k3_clks 220 1>;
clock-names = "fck";
power-domains = <&k3_pds 220 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
main_sdhci0: mmc@4f80000 {
@@ -428,6 +463,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster1: mailbox@31f81000 {
@@ -437,6 +473,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster2: mailbox@31f82000 {
@@ -446,6 +483,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster3: mailbox@31f83000 {
@@ -455,6 +493,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster4: mailbox@31f84000 {
@@ -464,6 +503,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster5: mailbox@31f85000 {
@@ -473,6 +513,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster6: mailbox@31f86000 {
@@ -482,6 +523,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster7: mailbox@31f87000 {
@@ -491,6 +533,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster8: mailbox@31f88000 {
@@ -500,6 +543,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster9: mailbox@31f89000 {
@@ -509,6 +553,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster10: mailbox@31f8a000 {
@@ -518,6 +563,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox0_cluster11: mailbox@31f8b000 {
@@ -527,6 +573,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox1_cluster0: mailbox@31f90000 {
@@ -536,6 +583,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox1_cluster1: mailbox@31f91000 {
@@ -545,6 +593,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox1_cluster2: mailbox@31f92000 {
@@ -554,6 +603,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox1_cluster3: mailbox@31f93000 {
@@ -563,6 +613,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox1_cluster4: mailbox@31f94000 {
@@ -572,6 +623,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox1_cluster5: mailbox@31f95000 {
@@ -581,6 +633,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox1_cluster6: mailbox@31f96000 {
@@ -590,6 +643,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox1_cluster7: mailbox@31f97000 {
@@ -599,6 +653,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox1_cluster8: mailbox@31f98000 {
@@ -608,6 +663,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox1_cluster9: mailbox@31f99000 {
@@ -617,6 +673,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox1_cluster10: mailbox@31f9a000 {
@@ -626,6 +683,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
mailbox1_cluster11: mailbox@31f9b000 {
@@ -635,6 +693,7 @@
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <16>;
interrupt-parent = <&main_navss_intr>;
+ status = "disabled";
};
main_ringacc: ringacc@3c000000 {
@@ -698,6 +757,7 @@
<GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan1: can@2711000 {
@@ -712,6 +772,7 @@
<GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan2: can@2721000 {
@@ -726,6 +787,7 @@
<GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan3: can@2731000 {
@@ -740,6 +802,7 @@
<GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan4: can@2741000 {
@@ -754,6 +817,7 @@
<GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan5: can@2751000 {
@@ -768,6 +832,7 @@
<GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan6: can@2761000 {
@@ -782,6 +847,7 @@
<GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan7: can@2771000 {
@@ -796,6 +862,7 @@
<GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan8: can@2781000 {
@@ -810,6 +877,7 @@
<GIC_SPI 577 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan9: can@2791000 {
@@ -824,6 +892,7 @@
<GIC_SPI 580 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan10: can@27a1000 {
@@ -838,6 +907,7 @@
<GIC_SPI 583 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan11: can@27b1000 {
@@ -852,6 +922,7 @@
<GIC_SPI 586 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan12: can@27c1000 {
@@ -866,6 +937,7 @@
<GIC_SPI 589 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan13: can@27d1000 {
@@ -880,6 +952,7 @@
<GIC_SPI 592 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan14: can@2681000 {
@@ -894,6 +967,7 @@
<GIC_SPI 595 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan15: can@2691000 {
@@ -908,6 +982,7 @@
<GIC_SPI 598 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan16: can@26a1000 {
@@ -922,6 +997,7 @@
<GIC_SPI 785 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
main_mcan17: can@26b1000 {
@@ -936,5 +1012,6 @@
<GIC_SPI 788 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
};
diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
index 4d1bfabd1313..0af242aa9816 100644
--- a/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-mcu-wakeup.dtsi
@@ -65,7 +65,7 @@
#interrupt-cells = <1>;
ti,sci = <&sms>;
ti,sci-dev-id = <125>;
- ti,interrupt-ranges = <16 928 16>;
+ ti,interrupt-ranges = <16 960 16>;
};
mcu_conf: syscon@40f00000 {
@@ -91,6 +91,7 @@
clocks = <&k3_clks 359 3>;
clock-names = "fclk";
power-domains = <&k3_pds 359 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcu_uart0: serial@40a00000 {
@@ -101,6 +102,7 @@
clocks = <&k3_clks 149 3>;
clock-names = "fclk";
power-domains = <&k3_pds 149 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
wkup_gpio0: gpio@42110000 {
@@ -144,6 +146,7 @@
clocks = <&k3_clks 223 1>;
clock-names = "fck";
power-domains = <&k3_pds 223 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcu_i2c0: i2c@40b00000 {
@@ -155,6 +158,7 @@
clocks = <&k3_clks 221 1>;
clock-names = "fck";
power-domains = <&k3_pds 221 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcu_i2c1: i2c@40b10000 {
@@ -166,6 +170,7 @@
clocks = <&k3_clks 222 1>;
clock-names = "fck";
power-domains = <&k3_pds 222 TI_SCI_PD_EXCLUSIVE>;
+ status = "disabled";
};
mcu_mcan0: can@40528000 {
@@ -180,6 +185,7 @@
<GIC_SPI 833 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
mcu_mcan1: can@40568000 {
@@ -194,6 +200,7 @@
<GIC_SPI 836 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "int0", "int1";
bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>;
+ status = "disabled";
};
mcu_navss: bus@28380000{
diff --git a/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi b/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi
index 76f0ceacb6d4..6930efff8a5a 100644
--- a/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi
+++ b/arch/arm64/boot/dts/ti/k3-j721s2-som-p0.dtsi
@@ -56,6 +56,7 @@
};
&main_i2c0 {
+ status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&main_i2c0_pins_default>;
clock-frequency = <400000>;
@@ -73,103 +74,8 @@
};
&main_mcan16 {
+ status = "okay";
pinctrl-0 = <&main_mcan16_pins_default>;
pinctrl-names = "default";
phys = <&transceiver0>;
};
-
-&mailbox0_cluster0 {
- status = "disabled";
-};
-
-&mailbox0_cluster1 {
- status = "disabled";
-};
-
-&mailbox0_cluster2 {
- status = "disabled";
-};
-
-&mailbox0_cluster3 {
- status = "disabled";
-};
-
-&mailbox0_cluster4 {
- status = "disabled";
-};
-
-&mailbox0_cluster5 {
- status = "disabled";
-};
-
-&mailbox0_cluster6 {
- status = "disabled";
-};
-
-&mailbox0_cluster7 {
- status = "disabled";
-};
-
-&mailbox0_cluster8 {
- status = "disabled";
-};
-
-&mailbox0_cluster9 {
- status = "disabled";
-};
-
-&mailbox0_cluster10 {
- status = "disabled";
-};
-
-&mailbox0_cluster11 {
- status = "disabled";
-};
-
-&mailbox1_cluster0 {
- status = "disabled";
-};
-
-&mailbox1_cluster1 {
- status = "disabled";
-};
-
-&mailbox1_cluster2 {
- status = "disabled";
-};
-
-&mailbox1_cluster3 {
- status = "disabled";
-};
-
-&mailbox1_cluster4 {
- status = "disabled";
-};
-
-&mailbox1_cluster5 {
- status = "disabled";
-};
-
-&mailbox1_cluster6 {
- status = "disabled";
-};
-
-&mailbox1_cluster7 {
- status = "disabled";
-};
-
-&mailbox1_cluster8 {
- status = "disabled";
-};
-
-&mailbox1_cluster9 {
- status = "disabled";
-};
-
-&mailbox1_cluster10 {
- status = "disabled";
-};
-
-&mailbox1_cluster11 {
- status = "disabled";
-};
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-zcu106-revA.dts b/arch/arm64/boot/dts/xilinx/zynqmp-zcu106-revA.dts
index e2dd72fe33ce..24a252317150 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp-zcu106-revA.dts
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-zcu106-revA.dts
@@ -150,6 +150,18 @@
#clock-cells = <0>;
clock-frequency = <114285000>;
};
+
+ dpcon {
+ compatible = "dp-connector";
+ label = "P11";
+ type = "full-size";
+
+ port {
+ dpcon_in: endpoint {
+ remote-endpoint = <&dpsub_dp_out>;
+ };
+ };
+ };
};
&can1 {
@@ -1015,4 +1027,12 @@
phy-names = "dp-phy0", "dp-phy1";
phys = <&psgtr 1 PHY_TYPE_DP 0 3>,
<&psgtr 0 PHY_TYPE_DP 1 3>;
+
+ ports {
+ port@5 {
+ dpsub_dp_out: endpoint {
+ remote-endpoint = <&dpcon_in>;
+ };
+ };
+ };
};
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index a549265e55f6..307c76cd8544 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -930,6 +930,30 @@
<&zynqmp_dpdma ZYNQMP_DPDMA_VIDEO1>,
<&zynqmp_dpdma ZYNQMP_DPDMA_VIDEO2>,
<&zynqmp_dpdma ZYNQMP_DPDMA_GRAPHICS>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port@0 {
+ reg = <0>;
+ };
+ port@1 {
+ reg = <1>;
+ };
+ port@2 {
+ reg = <2>;
+ };
+ port@3 {
+ reg = <3>;
+ };
+ port@4 {
+ reg = <4>;
+ };
+ port@5 {
+ reg = <5>;
+ };
+ };
};
};
};
diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig
index 0b6af3348e79..851e8f9be06d 100644
--- a/arch/arm64/configs/defconfig
+++ b/arch/arm64/configs/defconfig
@@ -357,6 +357,7 @@ CONFIG_RMNET=m
CONFIG_R8169=m
CONFIG_SH_ETH=y
CONFIG_RAVB=y
+CONFIG_RENESAS_ETHER_SWITCH=y
CONFIG_SMC91X=y
CONFIG_SMSC911X=y
CONFIG_SNI_AVE=y
@@ -369,7 +370,7 @@ CONFIG_MESON_GXL_PHY=m
CONFIG_AQUANTIA_PHY=y
CONFIG_BCM54140_PHY=m
CONFIG_MARVELL_PHY=m
-CONFIG_MARVELL_10G_PHY=m
+CONFIG_MARVELL_10G_PHY=y
CONFIG_MICREL_PHY=y
CONFIG_MICROSEMI_PHY=y
CONFIG_AT803X_PHY=y
@@ -392,6 +393,7 @@ CONFIG_USB_NET_PLUSB=m
CONFIG_USB_NET_MCS7830=m
CONFIG_ATH10K=m
CONFIG_ATH10K_PCI=m
+CONFIG_ATH10K_SDIO=m
CONFIG_ATH10K_SNOC=m
CONFIG_WCN36XX=m
CONFIG_ATH11K=m
@@ -412,6 +414,7 @@ CONFIG_KEYBOARD_CROS_EC=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_ATMEL_MXT=m
CONFIG_TOUCHSCREEN_GOODIX=m
+CONFIG_TOUCHSCREEN_ELAN=m
CONFIG_TOUCHSCREEN_EDT_FT5X06=m
CONFIG_INPUT_MISC=y
CONFIG_INPUT_PM8941_PWRKEY=y
@@ -462,6 +465,10 @@ CONFIG_IPMI_HANDLER=m
CONFIG_IPMI_DEVICE_INTERFACE=m
CONFIG_IPMI_SI=m
CONFIG_TCG_TPM=y
+CONFIG_TCG_TIS=m
+CONFIG_TCG_TIS_SPI=m
+CONFIG_TCG_TIS_SPI_CR50=y
+CONFIG_TCG_TIS_I2C_CR50=m
CONFIG_TCG_TIS_I2C_INFINEON=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_MUX=y
@@ -505,6 +512,7 @@ CONFIG_SPI_IMX=m
CONFIG_SPI_FSL_DSPI=y
CONFIG_SPI_MESON_SPICC=m
CONFIG_SPI_MESON_SPIFC=m
+CONFIG_SPI_MT65XX=y
CONFIG_SPI_ORION=y
CONFIG_SPI_PL022=y
CONFIG_SPI_ROCKCHIP=y
@@ -538,9 +546,12 @@ CONFIG_PINCTRL_MSM=y
CONFIG_PINCTRL_IPQ8074=y
CONFIG_PINCTRL_IPQ6018=y
CONFIG_PINCTRL_MSM8916=y
+CONFIG_PINCTRL_MSM8953=y
+CONFIG_PINCTRL_MSM8976=y
CONFIG_PINCTRL_MSM8994=y
CONFIG_PINCTRL_MSM8996=y
CONFIG_PINCTRL_MSM8998=y
+CONFIG_PINCTRL_QCM2290=y
CONFIG_PINCTRL_QCS404=y
CONFIG_PINCTRL_QDF2XXX=y
CONFIG_PINCTRL_QCOM_SPMI_PMIC=y
@@ -549,6 +560,7 @@ CONFIG_PINCTRL_SC7280=y
CONFIG_PINCTRL_SC8180X=y
CONFIG_PINCTRL_SC8280XP=y
CONFIG_PINCTRL_SDM845=y
+CONFIG_PINCTRL_SM6115=y
CONFIG_PINCTRL_SM8150=y
CONFIG_PINCTRL_SM8250=y
CONFIG_PINCTRL_SM8350=y
@@ -614,6 +626,7 @@ CONFIG_BRCMSTB_THERMAL=m
CONFIG_EXYNOS_THERMAL=y
CONFIG_TEGRA_SOCTHERM=m
CONFIG_TEGRA_BPMP_THERMAL=m
+CONFIG_GENERIC_ADC_THERMAL=m
CONFIG_QCOM_TSENS=y
CONFIG_QCOM_SPMI_ADC_TM5=m
CONFIG_QCOM_SPMI_TEMP_ALARM=m
@@ -698,6 +711,7 @@ CONFIG_USB_VIDEO_CLASS=m
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_SDR_PLATFORM_DRIVERS=y
CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_MEDIATEK_JPEG=m
CONFIG_VIDEO_QCOM_CAMSS=m
CONFIG_VIDEO_QCOM_VENUS=m
CONFIG_VIDEO_RCAR_ISP=m
@@ -759,7 +773,9 @@ CONFIG_DRM_PARADE_PS8640=m
CONFIG_DRM_SII902X=m
CONFIG_DRM_SIMPLE_BRIDGE=m
CONFIG_DRM_THINE_THC63LVD1024=m
+CONFIG_DRM_TI_TFP410=m
CONFIG_DRM_TI_SN65DSI86=m
+CONFIG_DRM_ANALOGIX_ANX7625=m
CONFIG_DRM_I2C_ADV7511=m
CONFIG_DRM_I2C_ADV7511_AUDIO=y
CONFIG_DRM_CDNS_MHDP8546=m
@@ -789,6 +805,7 @@ CONFIG_LOGO=y
# CONFIG_LOGO_LINUX_VGA16 is not set
CONFIG_SOUND=y
CONFIG_SND=y
+CONFIG_SND_ALOOP=m
CONFIG_SND_HDA_TEGRA=m
CONFIG_SND_HDA_CODEC_HDMI=m
CONFIG_SND_SOC=y
@@ -801,6 +818,9 @@ CONFIG_SND_SOC_IMX_SGTL5000=m
CONFIG_SND_SOC_IMX_SPDIF=m
CONFIG_SND_SOC_FSL_ASOC_CARD=m
CONFIG_SND_SOC_IMX_AUDMIX=m
+CONFIG_SND_SOC_MT8183=m
+CONFIG_SND_SOC_MT8183_MT6358_TS3A227E_MAX98357A=m
+CONFIG_SND_SOC_MT8183_DA7219_MAX98357A=m
CONFIG_SND_MESON_AXG_SOUND_CARD=m
CONFIG_SND_MESON_GX_SOUND_CARD=m
CONFIG_SND_SOC_QCOM=m
@@ -843,9 +863,11 @@ CONFIG_SND_SOC_GTM601=m
CONFIG_SND_SOC_MSM8916_WCD_ANALOG=m
CONFIG_SND_SOC_MSM8916_WCD_DIGITAL=m
CONFIG_SND_SOC_PCM3168A_I2C=m
+CONFIG_SND_SOC_RT5640=m
CONFIG_SND_SOC_RT5659=m
CONFIG_SND_SOC_SIMPLE_AMPLIFIER=m
CONFIG_SND_SOC_SIMPLE_MUX=m
+CONFIG_SND_SOC_TAS2552=m
CONFIG_SND_SOC_TAS571X=m
CONFIG_SND_SOC_TLV320AIC32X4_I2C=m
CONFIG_SND_SOC_WCD9335=m
@@ -1003,6 +1025,7 @@ CONFIG_RTC_DRV_SNVS=m
CONFIG_RTC_DRV_IMX_SC=m
CONFIG_RTC_DRV_MT6397=m
CONFIG_RTC_DRV_XGENE=y
+CONFIG_TEGRA186_TIMER=y
CONFIG_DMADEVICES=y
CONFIG_DMA_BCM2835=y
CONFIG_DMA_SUN6I=m
@@ -1049,6 +1072,7 @@ CONFIG_COMMON_CLK_CS2000_CP=y
CONFIG_COMMON_CLK_FSL_SAI=y
CONFIG_COMMON_CLK_S2MPS11=y
CONFIG_COMMON_CLK_PWM=y
+CONFIG_COMMON_CLK_RS9_PCIE=y
CONFIG_COMMON_CLK_VC5=y
CONFIG_COMMON_CLK_NPCM8XX=y
CONFIG_COMMON_CLK_BD718XX=m
@@ -1083,6 +1107,7 @@ CONFIG_SDM_GPUCC_845=y
CONFIG_SDM_VIDEOCC_845=y
CONFIG_SDM_DISPCC_845=y
CONFIG_SM_DISPCC_8250=y
+CONFIG_SM_GCC_6115=y
CONFIG_SM_GCC_8350=y
CONFIG_SM_GCC_8450=y
CONFIG_SM_GPUCC_8150=y
@@ -1107,6 +1132,7 @@ CONFIG_ARM_SMMU_V3=y
CONFIG_MTK_IOMMU=y
CONFIG_QCOM_IOMMU=y
CONFIG_REMOTEPROC=y
+CONFIG_MTK_SCP=m
CONFIG_QCOM_Q6V5_ADSP=m
CONFIG_QCOM_Q6V5_MSS=m
CONFIG_QCOM_Q6V5_PAS=m
@@ -1124,8 +1150,10 @@ CONFIG_RASPBERRYPI_POWER=y
CONFIG_FSL_DPAA=y
CONFIG_FSL_MC_DPIO=y
CONFIG_FSL_RCPM=y
+CONFIG_MTK_CMDQ=m
CONFIG_MTK_DEVAPC=m
CONFIG_MTK_PMIC_WRAP=y
+CONFIG_MTK_SVS=m
CONFIG_QCOM_AOSS_QMP=y
CONFIG_QCOM_COMMAND_DB=y
CONFIG_QCOM_CPR=y
@@ -1176,6 +1204,7 @@ CONFIG_ARCH_TEGRA_234_SOC=y
CONFIG_TI_SCI_PM_DOMAINS=y
CONFIG_ARM_IMX_BUS_DEVFREQ=m
CONFIG_ARM_IMX8M_DDRC_DEVFREQ=m
+CONFIG_ARM_MEDIATEK_CCI_DEVFREQ=m
CONFIG_EXTCON_PTN5150=m
CONFIG_EXTCON_USB_GPIO=y
CONFIG_EXTCON_USBC_CROS_EC=y
@@ -1183,6 +1212,7 @@ CONFIG_RENESAS_RPCIF=m
CONFIG_IIO=y
CONFIG_EXYNOS_ADC=y
CONFIG_MAX9611=m
+CONFIG_MEDIATEK_MT6577_AUXADC=m
CONFIG_QCOM_SPMI_VADC=m
CONFIG_QCOM_SPMI_ADC5=m
CONFIG_ROCKCHIP_SARADC=m
@@ -1239,6 +1269,7 @@ CONFIG_PHY_QCOM_USB_HS=m
CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2=m
CONFIG_PHY_QCOM_USB_HS_28NM=m
CONFIG_PHY_QCOM_USB_SS=m
+CONFIG_PHY_R8A779F0_ETHERNET_SERDES=y
CONFIG_PHY_RCAR_GEN3_PCIE=y
CONFIG_PHY_RCAR_GEN3_USB2=y
CONFIG_PHY_RCAR_GEN3_USB3=m
@@ -1270,6 +1301,7 @@ CONFIG_NVMEM_IMX_OCOTP_SCU=y
CONFIG_NVMEM_MTK_EFUSE=y
CONFIG_NVMEM_QCOM_QFPROM=y
CONFIG_NVMEM_ROCKCHIP_EFUSE=y
+CONFIG_NVMEM_SNVS_LPGPR=y
CONFIG_NVMEM_SUNXI_SID=y
CONFIG_NVMEM_UNIPHIER_EFUSE=y
CONFIG_NVMEM_MESON_EFUSE=m
@@ -1293,12 +1325,13 @@ CONFIG_INTERCONNECT_IMX=m
CONFIG_INTERCONNECT_IMX8MM=m
CONFIG_INTERCONNECT_IMX8MN=m
CONFIG_INTERCONNECT_IMX8MQ=m
+CONFIG_INTERCONNECT_IMX8MP=m
CONFIG_INTERCONNECT_QCOM=y
CONFIG_INTERCONNECT_QCOM_MSM8916=m
CONFIG_INTERCONNECT_QCOM_MSM8996=m
CONFIG_INTERCONNECT_QCOM_OSM_L3=m
CONFIG_INTERCONNECT_QCOM_QCS404=m
-CONFIG_INTERCONNECT_QCOM_SC7180=m
+CONFIG_INTERCONNECT_QCOM_SC7180=y
CONFIG_INTERCONNECT_QCOM_SC7280=y
CONFIG_INTERCONNECT_QCOM_SC8180X=y
CONFIG_INTERCONNECT_QCOM_SC8280XP=y
@@ -1306,7 +1339,10 @@ CONFIG_INTERCONNECT_QCOM_SDM845=y
CONFIG_INTERCONNECT_QCOM_SM8150=m
CONFIG_INTERCONNECT_QCOM_SM8250=m
CONFIG_INTERCONNECT_QCOM_SM8350=m
-CONFIG_INTERCONNECT_QCOM_SM8450=m
+CONFIG_INTERCONNECT_QCOM_SM8450=y
+CONFIG_HTE=y
+CONFIG_HTE_TEGRA194=y
+CONFIG_HTE_TEGRA194_TEST=m
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
@@ -1341,6 +1377,7 @@ CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_DEV_SUN8I_CE=m
CONFIG_CRYPTO_DEV_FSL_CAAM=m
CONFIG_CRYPTO_DEV_FSL_DPAA2_CAAM=m
+CONFIG_CRYPTO_DEV_QCE=m
CONFIG_CRYPTO_DEV_QCOM_RNG=m
CONFIG_CRYPTO_DEV_CCREE=m
CONFIG_CRYPTO_DEV_HISI_SEC2=m
diff --git a/arch/arm64/include/asm/alternative-macros.h b/arch/arm64/include/asm/alternative-macros.h
index 3622e9f4fb44..bdf1f6bcd010 100644
--- a/arch/arm64/include/asm/alternative-macros.h
+++ b/arch/arm64/include/asm/alternative-macros.h
@@ -224,7 +224,7 @@ alternative_endif
#include <linux/types.h>
static __always_inline bool
-alternative_has_feature_likely(unsigned long feature)
+alternative_has_feature_likely(const unsigned long feature)
{
compiletime_assert(feature < ARM64_NCAPS,
"feature must be < ARM64_NCAPS");
@@ -242,7 +242,7 @@ l_no:
}
static __always_inline bool
-alternative_has_feature_unlikely(unsigned long feature)
+alternative_has_feature_unlikely(const unsigned long feature)
{
compiletime_assert(feature < ARM64_NCAPS,
"feature must be < ARM64_NCAPS");
diff --git a/arch/arm64/include/asm/archrandom.h b/arch/arm64/include/asm/archrandom.h
index 109e2a4454be..2f5f3da34782 100644
--- a/arch/arm64/include/asm/archrandom.h
+++ b/arch/arm64/include/asm/archrandom.h
@@ -5,6 +5,7 @@
#include <linux/arm-smccc.h>
#include <linux/bug.h>
#include <linux/kernel.h>
+#include <linux/irqflags.h>
#include <asm/cpufeature.h>
#define ARM_SMCCC_TRNG_MIN_VERSION 0x10000UL
@@ -58,6 +59,13 @@ static inline bool __arm64_rndrrs(unsigned long *v)
return ok;
}
+static __always_inline bool __cpu_has_rng(void)
+{
+ if (unlikely(!system_capabilities_finalized() && !preemptible()))
+ return this_cpu_has_cap(ARM64_HAS_RNG);
+ return cpus_have_const_cap(ARM64_HAS_RNG);
+}
+
static inline size_t __must_check arch_get_random_longs(unsigned long *v, size_t max_longs)
{
/*
@@ -66,7 +74,7 @@ static inline size_t __must_check arch_get_random_longs(unsigned long *v, size_t
* cpufeature code and with potential scheduling between CPUs
* with and without the feature.
*/
- if (max_longs && cpus_have_const_cap(ARM64_HAS_RNG) && __arm64_rndr(v))
+ if (max_longs && __cpu_has_rng() && __arm64_rndr(v))
return 1;
return 0;
}
@@ -108,7 +116,7 @@ static inline size_t __must_check arch_get_random_seed_longs(unsigned long *v, s
* reseeded after each invocation. This is not a 100% fit but good
* enough to implement this API if no other entropy source exists.
*/
- if (cpus_have_const_cap(ARM64_HAS_RNG) && __arm64_rndrrs(v))
+ if (__cpu_has_rng() && __arm64_rndrrs(v))
return 1;
return 0;
@@ -121,40 +129,4 @@ static inline bool __init __early_cpu_has_rndr(void)
return (ftr >> ID_AA64ISAR0_EL1_RNDR_SHIFT) & 0xf;
}
-static inline size_t __init __must_check
-arch_get_random_seed_longs_early(unsigned long *v, size_t max_longs)
-{
- WARN_ON(system_state != SYSTEM_BOOTING);
-
- if (!max_longs)
- return 0;
-
- if (smccc_trng_available) {
- struct arm_smccc_res res;
-
- max_longs = min_t(size_t, 3, max_longs);
- arm_smccc_1_1_invoke(ARM_SMCCC_TRNG_RND64, max_longs * 64, &res);
- if ((int)res.a0 >= 0) {
- switch (max_longs) {
- case 3:
- *v++ = res.a1;
- fallthrough;
- case 2:
- *v++ = res.a2;
- fallthrough;
- case 1:
- *v++ = res.a3;
- break;
- }
- return max_longs;
- }
- }
-
- if (__early_cpu_has_rndr() && __arm64_rndr(v))
- return 1;
-
- return 0;
-}
-#define arch_get_random_seed_longs_early arch_get_random_seed_longs_early
-
#endif /* _ASM_ARCHRANDOM_H */
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index e5957a53be39..376a980f2bad 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -34,11 +34,6 @@
wx\n .req w\n
.endr
- .macro save_and_disable_daif, flags
- mrs \flags, daif
- msr daifset, #0xf
- .endm
-
.macro disable_daif
msr daifset, #0xf
.endm
@@ -47,15 +42,6 @@
msr daifclr, #0xf
.endm
- .macro restore_daif, flags:req
- msr daif, \flags
- .endm
-
- /* IRQ/FIQ are the lowest priority flags, unconditionally unmask the rest. */
- .macro enable_da
- msr daifclr, #(8 | 4)
- .endm
-
/*
* Save/restore interrupts.
*/
@@ -620,17 +606,6 @@ alternative_endif
.endm
/*
- * Perform the reverse of offset_ttbr1.
- * bic is used as it can cover the immediate value and, in future, won't need
- * to be nop'ed out when dealing with 52-bit kernel VAs.
- */
- .macro restore_ttbr1, ttbr
-#ifdef CONFIG_ARM64_VA_BITS_52
- bic \ttbr, \ttbr, #TTBR1_BADDR_4852_OFFSET
-#endif
- .endm
-
-/*
* Arrange a physical address in a TTBR register, taking care of 52-bit
* addresses.
*
@@ -660,12 +635,10 @@ alternative_endif
.endm
.macro pte_to_phys, phys, pte
-#ifdef CONFIG_ARM64_PA_BITS_52
- ubfiz \phys, \pte, #(48 - 16 - 12), #16
- bfxil \phys, \pte, #16, #32
- lsl \phys, \phys, #16
-#else
and \phys, \pte, #PTE_ADDR_MASK
+#ifdef CONFIG_ARM64_PA_BITS_52
+ orr \phys, \phys, \phys, lsl #PTE_ADDR_HIGH_SHIFT
+ and \phys, \phys, GENMASK_ULL(PHYS_MASK_SHIFT - 1, PAGE_SHIFT)
#endif
.endm
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index f73f11b55042..03d1c9d7af82 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -832,7 +832,8 @@ static inline bool system_supports_tlb_range(void)
cpus_have_const_cap(ARM64_HAS_TLB_RANGE);
}
-extern int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
+int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt);
+bool try_emulate_mrs(struct pt_regs *regs, u32 isn);
static inline u32 id_aa64mmfr0_parange_to_phys_shift(int parange)
{
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 65e53ef5a396..4e8b66c74ea2 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -80,6 +80,7 @@
#define ARM_CPU_PART_CORTEX_X1 0xD44
#define ARM_CPU_PART_CORTEX_A510 0xD46
#define ARM_CPU_PART_CORTEX_A710 0xD47
+#define ARM_CPU_PART_CORTEX_A715 0xD4D
#define ARM_CPU_PART_CORTEX_X2 0xD48
#define ARM_CPU_PART_NEOVERSE_N2 0xD49
#define ARM_CPU_PART_CORTEX_A78C 0xD4B
@@ -142,6 +143,7 @@
#define MIDR_CORTEX_X1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X1)
#define MIDR_CORTEX_A510 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A510)
#define MIDR_CORTEX_A710 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A710)
+#define MIDR_CORTEX_A715 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A715)
#define MIDR_CORTEX_X2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_X2)
#define MIDR_NEOVERSE_N2 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N2)
#define MIDR_CORTEX_A78C MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A78C)
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 439e2bc5d5d8..31d13a6001df 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -14,8 +14,16 @@
#ifdef CONFIG_EFI
extern void efi_init(void);
+
+bool efi_runtime_fixup_exception(struct pt_regs *regs, const char *msg);
#else
#define efi_init()
+
+static inline
+bool efi_runtime_fixup_exception(struct pt_regs *regs, const char *msg)
+{
+ return false;
+}
#endif
int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
@@ -25,6 +33,7 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
({ \
efi_virtmap_load(); \
__efi_fpsimd_begin(); \
+ spin_lock(&efi_rt_lock); \
})
#undef arch_efi_call_virt
@@ -33,10 +42,12 @@ int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);
#define arch_efi_call_virt_teardown() \
({ \
+ spin_unlock(&efi_rt_lock); \
__efi_fpsimd_end(); \
efi_virtmap_unload(); \
})
+extern spinlock_t efi_rt_lock;
efi_status_t __efi_rt_asm_wrapper(void *, const char *, ...);
#define ARCH_EFI_IRQ_FLAGS_MASK (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT)
@@ -76,13 +87,23 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long image_addr)
return (image_addr & ~(SZ_1G - 1UL)) + (1UL << (VA_BITS_MIN - 1));
}
-#define alloc_screen_info(x...) &screen_info
-
-static inline void free_screen_info(struct screen_info *si)
+static inline unsigned long efi_get_kimg_min_align(void)
{
+ extern bool efi_nokaslr;
+
+ /*
+ * Although relocatable kernels can fix up the misalignment with
+ * respect to MIN_KIMG_ALIGN, the resulting virtual text addresses are
+ * subtly out of sync with those recorded in the vmlinux when kaslr is
+ * disabled but the image required relocation anyway. Therefore retain
+ * 2M alignment if KASLR was explicitly disabled, even if it was not
+ * going to be activated to begin with.
+ */
+ return efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN;
}
#define EFI_ALLOC_ALIGN SZ_64K
+#define EFI_ALLOC_LIMIT ((1UL << 48) - 1)
/*
* On ARM systems, virtually remapped UEFI runtime services are set up in two
diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h
index 19713d0f013b..92963f98afec 100644
--- a/arch/arm64/include/asm/exception.h
+++ b/arch/arm64/include/asm/exception.h
@@ -58,7 +58,8 @@ asmlinkage void call_on_irq_stack(struct pt_regs *regs,
asmlinkage void asm_exit_to_user_mode(struct pt_regs *regs);
void do_mem_abort(unsigned long far, unsigned long esr, struct pt_regs *regs);
-void do_undefinstr(struct pt_regs *regs, unsigned long esr);
+void do_el0_undef(struct pt_regs *regs, unsigned long esr);
+void do_el1_undef(struct pt_regs *regs, unsigned long esr);
void do_el0_bti(struct pt_regs *regs);
void do_el1_bti(struct pt_regs *regs, unsigned long esr);
void do_debug_exception(unsigned long addr_if_watchpoint, unsigned long esr,
@@ -67,10 +68,10 @@ void do_fpsimd_acc(unsigned long esr, struct pt_regs *regs);
void do_sve_acc(unsigned long esr, struct pt_regs *regs);
void do_sme_acc(unsigned long esr, struct pt_regs *regs);
void do_fpsimd_exc(unsigned long esr, struct pt_regs *regs);
-void do_sysinstr(unsigned long esr, struct pt_regs *regs);
+void do_el0_sys(unsigned long esr, struct pt_regs *regs);
void do_sp_pc_abort(unsigned long addr, unsigned long esr, struct pt_regs *regs);
void bad_el0_sync(struct pt_regs *regs, int reason, unsigned long esr);
-void do_cp15instr(unsigned long esr, struct pt_regs *regs);
+void do_el0_cp15(unsigned long esr, struct pt_regs *regs);
int do_compat_alignment_fixup(unsigned long addr, struct pt_regs *regs);
void do_el0_svc(struct pt_regs *regs);
void do_el0_svc_compat(struct pt_regs *regs);
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 6f86b7ab6c28..e6fa1e2982c8 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -56,11 +56,20 @@ extern void fpsimd_signal_preserve_current_state(void);
extern void fpsimd_preserve_current_state(void);
extern void fpsimd_restore_current_state(void);
extern void fpsimd_update_current_state(struct user_fpsimd_state const *state);
+extern void fpsimd_kvm_prepare(void);
+
+struct cpu_fp_state {
+ struct user_fpsimd_state *st;
+ void *sve_state;
+ void *za_state;
+ u64 *svcr;
+ unsigned int sve_vl;
+ unsigned int sme_vl;
+ enum fp_type *fp_type;
+ enum fp_type to_save;
+};
-extern void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *state,
- void *sve_state, unsigned int sve_vl,
- void *za_state, unsigned int sme_vl,
- u64 *svcr);
+extern void fpsimd_bind_state_to_cpu(struct cpu_fp_state *fp_state);
extern void fpsimd_flush_task_state(struct task_struct *target);
extern void fpsimd_save_and_flush_cpu_state(void);
diff --git a/arch/arm64/include/asm/ftrace.h b/arch/arm64/include/asm/ftrace.h
index 329dbbd4d50b..5664729800ae 100644
--- a/arch/arm64/include/asm/ftrace.h
+++ b/arch/arm64/include/asm/ftrace.h
@@ -23,7 +23,7 @@
*/
#define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
-#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
#define ARCH_SUPPORTS_FTRACE_OPS 1
#else
#define MCOUNT_ADDR ((unsigned long)_mcount)
@@ -33,8 +33,7 @@
#define MCOUNT_INSN_SIZE AARCH64_INSN_SIZE
#define FTRACE_PLT_IDX 0
-#define FTRACE_REGS_PLT_IDX 1
-#define NR_FTRACE_PLTS 2
+#define NR_FTRACE_PLTS 1
/*
* Currently, gcc tends to save the link register after the local variables
@@ -69,7 +68,7 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
* Adjust addr to point at the BL in the callsite.
* See ftrace_init_nop() for the callsite sequence.
*/
- if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS))
+ if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_ARGS))
return addr + AARCH64_INSN_SIZE;
/*
* addr is the address of the mcount call instruction.
@@ -78,10 +77,71 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
return addr;
}
-#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
struct dyn_ftrace;
struct ftrace_ops;
-struct ftrace_regs;
+
+#define arch_ftrace_get_regs(regs) NULL
+
+struct ftrace_regs {
+ /* x0 - x8 */
+ unsigned long regs[9];
+ unsigned long __unused;
+
+ unsigned long fp;
+ unsigned long lr;
+
+ unsigned long sp;
+ unsigned long pc;
+};
+
+static __always_inline unsigned long
+ftrace_regs_get_instruction_pointer(const struct ftrace_regs *fregs)
+{
+ return fregs->pc;
+}
+
+static __always_inline void
+ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
+ unsigned long pc)
+{
+ fregs->pc = pc;
+}
+
+static __always_inline unsigned long
+ftrace_regs_get_stack_pointer(const struct ftrace_regs *fregs)
+{
+ return fregs->sp;
+}
+
+static __always_inline unsigned long
+ftrace_regs_get_argument(struct ftrace_regs *fregs, unsigned int n)
+{
+ if (n < 8)
+ return fregs->regs[n];
+ return 0;
+}
+
+static __always_inline unsigned long
+ftrace_regs_get_return_value(const struct ftrace_regs *fregs)
+{
+ return fregs->regs[0];
+}
+
+static __always_inline void
+ftrace_regs_set_return_value(struct ftrace_regs *fregs,
+ unsigned long ret)
+{
+ fregs->regs[0] = ret;
+}
+
+static __always_inline void
+ftrace_override_function_with_return(struct ftrace_regs *fregs)
+{
+ fregs->pc = fregs->lr;
+}
+
+int ftrace_regs_query_register_offset(const char *name);
int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec);
#define ftrace_init_nop ftrace_init_nop
diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
index d20f5da2d76f..6a4a1ab8eb23 100644
--- a/arch/arm64/include/asm/hugetlb.h
+++ b/arch/arm64/include/asm/hugetlb.h
@@ -49,6 +49,15 @@ extern pte_t huge_ptep_get(pte_t *ptep);
void __init arm64_hugetlb_cma_reserve(void);
+#define huge_ptep_modify_prot_start huge_ptep_modify_prot_start
+extern pte_t huge_ptep_modify_prot_start(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep);
+
+#define huge_ptep_modify_prot_commit huge_ptep_modify_prot_commit
+extern void huge_ptep_modify_prot_commit(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep,
+ pte_t old_pte, pte_t new_pte);
+
#include <asm-generic/hugetlb.h>
#endif /* __ASM_HUGETLB_H */
diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h
index 298b386d3ebe..06dd12c514e6 100644
--- a/arch/arm64/include/asm/hwcap.h
+++ b/arch/arm64/include/asm/hwcap.h
@@ -120,6 +120,9 @@
#define KERNEL_HWCAP_WFXT __khwcap2_feature(WFXT)
#define KERNEL_HWCAP_EBF16 __khwcap2_feature(EBF16)
#define KERNEL_HWCAP_SVE_EBF16 __khwcap2_feature(SVE_EBF16)
+#define KERNEL_HWCAP_CSSC __khwcap2_feature(CSSC)
+#define KERNEL_HWCAP_RPRFM __khwcap2_feature(RPRFM)
+#define KERNEL_HWCAP_SVE2P1 __khwcap2_feature(SVE2P1)
/*
* This yields a mask that user programs can use to figure out what
diff --git a/arch/arm64/include/asm/insn.h b/arch/arm64/include/asm/insn.h
index 834bff720582..aaf1f52fbf3e 100644
--- a/arch/arm64/include/asm/insn.h
+++ b/arch/arm64/include/asm/insn.h
@@ -13,31 +13,6 @@
#include <asm/insn-def.h>
#ifndef __ASSEMBLY__
-/*
- * ARM Architecture Reference Manual for ARMv8 Profile-A, Issue A.a
- * Section C3.1 "A64 instruction index by encoding":
- * AArch64 main encoding table
- * Bit position
- * 28 27 26 25 Encoding Group
- * 0 0 - - Unallocated
- * 1 0 0 - Data processing, immediate
- * 1 0 1 - Branch, exception generation and system instructions
- * - 1 - 0 Loads and stores
- * - 1 0 1 Data processing - register
- * 0 1 1 1 Data processing - SIMD and floating point
- * 1 1 1 1 Data processing - SIMD and floating point
- * "-" means "don't care"
- */
-enum aarch64_insn_encoding_class {
- AARCH64_INSN_CLS_UNKNOWN, /* UNALLOCATED */
- AARCH64_INSN_CLS_SVE, /* SVE instructions */
- AARCH64_INSN_CLS_DP_IMM, /* Data processing - immediate */
- AARCH64_INSN_CLS_DP_REG, /* Data processing - register */
- AARCH64_INSN_CLS_DP_FPSIMD, /* Data processing - SIMD and FP */
- AARCH64_INSN_CLS_LDST, /* Loads and stores */
- AARCH64_INSN_CLS_BR_SYS, /* Branch, exception generation and
- * system instructions */
-};
enum aarch64_insn_hint_cr_op {
AARCH64_INSN_HINT_NOP = 0x0 << 5,
@@ -326,6 +301,23 @@ static __always_inline u32 aarch64_insn_get_##abbr##_value(void) \
return (val); \
}
+/*
+ * ARM Architecture Reference Manual for ARMv8 Profile-A, Issue A.a
+ * Section C3.1 "A64 instruction index by encoding":
+ * AArch64 main encoding table
+ * Bit position
+ * 28 27 26 25 Encoding Group
+ * 0 0 - - Unallocated
+ * 1 0 0 - Data processing, immediate
+ * 1 0 1 - Branch, exception generation and system instructions
+ * - 1 - 0 Loads and stores
+ * - 1 0 1 Data processing - register
+ * 0 1 1 1 Data processing - SIMD and floating point
+ * 1 1 1 1 Data processing - SIMD and floating point
+ * "-" means "don't care"
+ */
+__AARCH64_INSN_FUNCS(class_branch_sys, 0x1c000000, 0x14000000)
+
__AARCH64_INSN_FUNCS(adr, 0x9F000000, 0x10000000)
__AARCH64_INSN_FUNCS(adrp, 0x9F000000, 0x90000000)
__AARCH64_INSN_FUNCS(prfm, 0x3FC00000, 0x39800000)
@@ -431,58 +423,122 @@ __AARCH64_INSN_FUNCS(pssbb, 0xFFFFFFFF, 0xD503349F)
#undef __AARCH64_INSN_FUNCS
-bool aarch64_insn_is_steppable_hint(u32 insn);
-bool aarch64_insn_is_branch_imm(u32 insn);
+static __always_inline bool aarch64_insn_is_steppable_hint(u32 insn)
+{
+ if (!aarch64_insn_is_hint(insn))
+ return false;
+
+ switch (insn & 0xFE0) {
+ case AARCH64_INSN_HINT_XPACLRI:
+ case AARCH64_INSN_HINT_PACIA_1716:
+ case AARCH64_INSN_HINT_PACIB_1716:
+ case AARCH64_INSN_HINT_PACIAZ:
+ case AARCH64_INSN_HINT_PACIASP:
+ case AARCH64_INSN_HINT_PACIBZ:
+ case AARCH64_INSN_HINT_PACIBSP:
+ case AARCH64_INSN_HINT_BTI:
+ case AARCH64_INSN_HINT_BTIC:
+ case AARCH64_INSN_HINT_BTIJ:
+ case AARCH64_INSN_HINT_BTIJC:
+ case AARCH64_INSN_HINT_NOP:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static __always_inline bool aarch64_insn_is_branch(u32 insn)
+{
+ /* b, bl, cb*, tb*, ret*, b.cond, br*, blr* */
+
+ return aarch64_insn_is_b(insn) ||
+ aarch64_insn_is_bl(insn) ||
+ aarch64_insn_is_cbz(insn) ||
+ aarch64_insn_is_cbnz(insn) ||
+ aarch64_insn_is_tbz(insn) ||
+ aarch64_insn_is_tbnz(insn) ||
+ aarch64_insn_is_ret(insn) ||
+ aarch64_insn_is_ret_auth(insn) ||
+ aarch64_insn_is_br(insn) ||
+ aarch64_insn_is_br_auth(insn) ||
+ aarch64_insn_is_blr(insn) ||
+ aarch64_insn_is_blr_auth(insn) ||
+ aarch64_insn_is_bcond(insn);
+}
-static inline bool aarch64_insn_is_adr_adrp(u32 insn)
+static __always_inline bool aarch64_insn_is_branch_imm(u32 insn)
{
- return aarch64_insn_is_adr(insn) || aarch64_insn_is_adrp(insn);
+ return aarch64_insn_is_b(insn) ||
+ aarch64_insn_is_bl(insn) ||
+ aarch64_insn_is_tbz(insn) ||
+ aarch64_insn_is_tbnz(insn) ||
+ aarch64_insn_is_cbz(insn) ||
+ aarch64_insn_is_cbnz(insn) ||
+ aarch64_insn_is_bcond(insn);
}
-static inline bool aarch64_insn_is_dsb(u32 insn)
+static __always_inline bool aarch64_insn_is_adr_adrp(u32 insn)
{
- return aarch64_insn_is_dsb_base(insn) || aarch64_insn_is_dsb_nxs(insn);
+ return aarch64_insn_is_adr(insn) ||
+ aarch64_insn_is_adrp(insn);
}
-static inline bool aarch64_insn_is_barrier(u32 insn)
+static __always_inline bool aarch64_insn_is_dsb(u32 insn)
{
- return aarch64_insn_is_dmb(insn) || aarch64_insn_is_dsb(insn) ||
- aarch64_insn_is_isb(insn) || aarch64_insn_is_sb(insn) ||
- aarch64_insn_is_clrex(insn) || aarch64_insn_is_ssbb(insn) ||
+ return aarch64_insn_is_dsb_base(insn) ||
+ aarch64_insn_is_dsb_nxs(insn);
+}
+
+static __always_inline bool aarch64_insn_is_barrier(u32 insn)
+{
+ return aarch64_insn_is_dmb(insn) ||
+ aarch64_insn_is_dsb(insn) ||
+ aarch64_insn_is_isb(insn) ||
+ aarch64_insn_is_sb(insn) ||
+ aarch64_insn_is_clrex(insn) ||
+ aarch64_insn_is_ssbb(insn) ||
aarch64_insn_is_pssbb(insn);
}
-static inline bool aarch64_insn_is_store_single(u32 insn)
+static __always_inline bool aarch64_insn_is_store_single(u32 insn)
{
return aarch64_insn_is_store_imm(insn) ||
aarch64_insn_is_store_pre(insn) ||
aarch64_insn_is_store_post(insn);
}
-static inline bool aarch64_insn_is_store_pair(u32 insn)
+static __always_inline bool aarch64_insn_is_store_pair(u32 insn)
{
return aarch64_insn_is_stp(insn) ||
aarch64_insn_is_stp_pre(insn) ||
aarch64_insn_is_stp_post(insn);
}
-static inline bool aarch64_insn_is_load_single(u32 insn)
+static __always_inline bool aarch64_insn_is_load_single(u32 insn)
{
return aarch64_insn_is_load_imm(insn) ||
aarch64_insn_is_load_pre(insn) ||
aarch64_insn_is_load_post(insn);
}
-static inline bool aarch64_insn_is_load_pair(u32 insn)
+static __always_inline bool aarch64_insn_is_load_pair(u32 insn)
{
return aarch64_insn_is_ldp(insn) ||
aarch64_insn_is_ldp_pre(insn) ||
aarch64_insn_is_ldp_post(insn);
}
+static __always_inline bool aarch64_insn_uses_literal(u32 insn)
+{
+ /* ldr/ldrsw (literal), prfm */
+
+ return aarch64_insn_is_ldr_lit(insn) ||
+ aarch64_insn_is_ldrsw_lit(insn) ||
+ aarch64_insn_is_adr_adrp(insn) ||
+ aarch64_insn_is_prfm_lit(insn);
+}
+
enum aarch64_insn_encoding_class aarch64_get_insn_class(u32 insn);
-bool aarch64_insn_uses_literal(u32 insn);
-bool aarch64_insn_is_branch(u32 insn);
u64 aarch64_insn_decode_immediate(enum aarch64_insn_imm_type type, u32 insn);
u32 aarch64_insn_encode_immediate(enum aarch64_insn_imm_type type,
u32 insn, u64 imm);
@@ -496,8 +552,18 @@ u32 aarch64_insn_gen_comp_branch_imm(unsigned long pc, unsigned long addr,
enum aarch64_insn_branch_type type);
u32 aarch64_insn_gen_cond_branch_imm(unsigned long pc, unsigned long addr,
enum aarch64_insn_condition cond);
-u32 aarch64_insn_gen_hint(enum aarch64_insn_hint_cr_op op);
-u32 aarch64_insn_gen_nop(void);
+
+static __always_inline u32
+aarch64_insn_gen_hint(enum aarch64_insn_hint_cr_op op)
+{
+ return aarch64_insn_get_hint_value() | op;
+}
+
+static __always_inline u32 aarch64_insn_gen_nop(void)
+{
+ return aarch64_insn_gen_hint(AARCH64_INSN_HINT_NOP);
+}
+
u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg,
enum aarch64_insn_branch_type type);
u32 aarch64_insn_gen_load_store_reg(enum aarch64_insn_register reg,
@@ -580,10 +646,6 @@ u32 aarch64_insn_gen_extr(enum aarch64_insn_variant variant,
enum aarch64_insn_register Rn,
enum aarch64_insn_register Rd,
u8 lsb);
-u32 aarch64_insn_gen_prefetch(enum aarch64_insn_register base,
- enum aarch64_insn_prfm_type type,
- enum aarch64_insn_prfm_target target,
- enum aarch64_insn_prfm_policy policy);
#ifdef CONFIG_ARM64_LSE_ATOMICS
u32 aarch64_insn_gen_atomic_ld_op(enum aarch64_insn_register result,
enum aarch64_insn_register address,
diff --git a/arch/arm64/include/asm/jump_label.h b/arch/arm64/include/asm/jump_label.h
index cea441b6aa5d..48ddc0f45d22 100644
--- a/arch/arm64/include/asm/jump_label.h
+++ b/arch/arm64/include/asm/jump_label.h
@@ -15,8 +15,8 @@
#define JUMP_LABEL_NOP_SIZE AARCH64_INSN_SIZE
-static __always_inline bool arch_static_branch(struct static_key *key,
- bool branch)
+static __always_inline bool arch_static_branch(struct static_key * const key,
+ const bool branch)
{
asm_volatile_goto(
"1: nop \n\t"
@@ -32,8 +32,8 @@ l_yes:
return true;
}
-static __always_inline bool arch_static_branch_jump(struct static_key *key,
- bool branch)
+static __always_inline bool arch_static_branch_jump(struct static_key * const key,
+ const bool branch)
{
asm_volatile_goto(
"1: b %l[l_yes] \n\t"
diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h
index 32d14f481f0c..fcd14197756f 100644
--- a/arch/arm64/include/asm/kernel-pgtable.h
+++ b/arch/arm64/include/asm/kernel-pgtable.h
@@ -18,11 +18,6 @@
* with 4K (section size = 2M) but not with 16K (section size = 32M) or
* 64K (section size = 512M).
*/
-#ifdef CONFIG_ARM64_4K_PAGES
-#define ARM64_KERNEL_USES_PMD_MAPS 1
-#else
-#define ARM64_KERNEL_USES_PMD_MAPS 0
-#endif
/*
* The idmap and swapper page tables need some space reserved in the kernel
@@ -34,7 +29,7 @@
* VA range, so pages required to map highest possible PA are reserved in all
* cases.
*/
-#if ARM64_KERNEL_USES_PMD_MAPS
+#ifdef CONFIG_ARM64_4K_PAGES
#define SWAPPER_PGTABLE_LEVELS (CONFIG_PGTABLE_LEVELS - 1)
#else
#define SWAPPER_PGTABLE_LEVELS (CONFIG_PGTABLE_LEVELS)
@@ -96,7 +91,7 @@
#define INIT_IDMAP_DIR_PAGES EARLY_PAGES(KIMAGE_VADDR, _end + MAX_FDT_SIZE + SWAPPER_BLOCK_SIZE, 1)
/* Initial memory map size */
-#if ARM64_KERNEL_USES_PMD_MAPS
+#ifdef CONFIG_ARM64_4K_PAGES
#define SWAPPER_BLOCK_SHIFT PMD_SHIFT
#define SWAPPER_BLOCK_SIZE PMD_SIZE
#define SWAPPER_TABLE_SHIFT PUD_SHIFT
@@ -112,7 +107,7 @@
#define SWAPPER_PTE_FLAGS (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED)
#define SWAPPER_PMD_FLAGS (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S)
-#if ARM64_KERNEL_USES_PMD_MAPS
+#ifdef CONFIG_ARM64_4K_PAGES
#define SWAPPER_RW_MMUFLAGS (PMD_ATTRINDX(MT_NORMAL) | SWAPPER_PMD_FLAGS)
#define SWAPPER_RX_MMUFLAGS (SWAPPER_RW_MMUFLAGS | PMD_SECT_RDONLY)
#else
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 45e2136322ba..fd34ab155d0b 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -306,8 +306,18 @@ struct vcpu_reset_state {
struct kvm_vcpu_arch {
struct kvm_cpu_context ctxt;
- /* Guest floating point state */
+ /*
+ * Guest floating point state
+ *
+ * The architecture has two main floating point extensions,
+ * the original FPSIMD and SVE. These have overlapping
+ * register views, with the FPSIMD V registers occupying the
+ * low 128 bits of the SVE Z registers. When the core
+ * floating point code saves the register state of a task it
+ * records which view it saved in fp_type.
+ */
void *sve_state;
+ enum fp_type fp_type;
unsigned int sve_max_vl;
u64 svcr;
diff --git a/arch/arm64/include/asm/lse.h b/arch/arm64/include/asm/lse.h
index c503db8e73b0..f99d74826a7e 100644
--- a/arch/arm64/include/asm/lse.h
+++ b/arch/arm64/include/asm/lse.h
@@ -10,7 +10,6 @@
#include <linux/compiler_types.h>
#include <linux/export.h>
-#include <linux/jump_label.h>
#include <linux/stringify.h>
#include <asm/alternative.h>
#include <asm/alternative-macros.h>
diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
index d3f8b5df0c1f..72dbd6400549 100644
--- a/arch/arm64/include/asm/mmu_context.h
+++ b/arch/arm64/include/asm/mmu_context.h
@@ -18,6 +18,7 @@
#include <asm/cacheflush.h>
#include <asm/cpufeature.h>
+#include <asm/daifflags.h>
#include <asm/proc-fns.h>
#include <asm-generic/mm_hooks.h>
#include <asm/cputype.h>
@@ -152,6 +153,7 @@ static inline void cpu_replace_ttbr1(pgd_t *pgdp, pgd_t *idmap)
typedef void (ttbr_replace_func)(phys_addr_t);
extern ttbr_replace_func idmap_cpu_replace_ttbr1;
ttbr_replace_func *replace_phys;
+ unsigned long daif;
/* phys_to_ttbr() zeros lower 2 bits of ttbr with 52-bit PA */
phys_addr_t ttbr1 = phys_to_ttbr(virt_to_phys(pgdp));
@@ -171,7 +173,15 @@ static inline void cpu_replace_ttbr1(pgd_t *pgdp, pgd_t *idmap)
replace_phys = (void *)__pa_symbol(idmap_cpu_replace_ttbr1);
__cpu_install_idmap(idmap);
+
+ /*
+ * We really don't want to take *any* exceptions while TTBR1 is
+ * in the process of being replaced so mask everything.
+ */
+ daif = local_daif_save();
replace_phys(ttbr1);
+ local_daif_restore(daif);
+
cpu_uninstall_idmap();
}
diff --git a/arch/arm64/include/asm/module.lds.h b/arch/arm64/include/asm/module.lds.h
index 094701ec5500..dbba4b7559aa 100644
--- a/arch/arm64/include/asm/module.lds.h
+++ b/arch/arm64/include/asm/module.lds.h
@@ -17,4 +17,12 @@ SECTIONS {
*/
.text.hot : { *(.text.hot) }
#endif
+
+#ifdef CONFIG_UNWIND_TABLES
+ /*
+ * Currently, we only use unwind info at module load time, so we can
+ * put it into the .init allocation.
+ */
+ .init.eh_frame : { *(.eh_frame) }
+#endif
}
diff --git a/arch/arm64/include/asm/pgtable-hwdef.h b/arch/arm64/include/asm/pgtable-hwdef.h
index 5ab8d163198f..f658aafc47df 100644
--- a/arch/arm64/include/asm/pgtable-hwdef.h
+++ b/arch/arm64/include/asm/pgtable-hwdef.h
@@ -159,6 +159,7 @@
#ifdef CONFIG_ARM64_PA_BITS_52
#define PTE_ADDR_HIGH (_AT(pteval_t, 0xf) << 12)
#define PTE_ADDR_MASK (PTE_ADDR_LOW | PTE_ADDR_HIGH)
+#define PTE_ADDR_HIGH_SHIFT 36
#else
#define PTE_ADDR_MASK PTE_ADDR_LOW
#endif
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index edf6625ce965..c36d56dbf940 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -77,11 +77,11 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
static inline phys_addr_t __pte_to_phys(pte_t pte)
{
return (pte_val(pte) & PTE_ADDR_LOW) |
- ((pte_val(pte) & PTE_ADDR_HIGH) << 36);
+ ((pte_val(pte) & PTE_ADDR_HIGH) << PTE_ADDR_HIGH_SHIFT);
}
static inline pteval_t __phys_to_pte_val(phys_addr_t phys)
{
- return (phys | (phys >> 36)) & PTE_ADDR_MASK;
+ return (phys | (phys >> PTE_ADDR_HIGH_SHIFT)) & PTE_ADDR_MASK;
}
#else
#define __pte_to_phys(pte) (pte_val(pte) & PTE_ADDR_MASK)
@@ -609,7 +609,6 @@ extern pgd_t init_pg_dir[PTRS_PER_PGD];
extern pgd_t init_pg_end[];
extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
extern pgd_t idmap_pg_dir[PTRS_PER_PGD];
-extern pgd_t idmap_pg_end[];
extern pgd_t tramp_pg_dir[PTRS_PER_PGD];
extern pgd_t reserved_pg_dir[PTRS_PER_PGD];
@@ -1096,6 +1095,15 @@ static inline bool pud_sect_supported(void)
}
+#define __HAVE_ARCH_PTEP_MODIFY_PROT_TRANSACTION
+#define ptep_modify_prot_start ptep_modify_prot_start
+extern pte_t ptep_modify_prot_start(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep);
+
+#define ptep_modify_prot_commit ptep_modify_prot_commit
+extern void ptep_modify_prot_commit(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep,
+ pte_t old_pte, pte_t new_pte);
#endif /* !__ASSEMBLY__ */
#endif /* __ASM_PGTABLE_H */
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h
index 445aa3af3b76..d51b32a69309 100644
--- a/arch/arm64/include/asm/processor.h
+++ b/arch/arm64/include/asm/processor.h
@@ -122,6 +122,12 @@ enum vec_type {
ARM64_VEC_MAX,
};
+enum fp_type {
+ FP_STATE_CURRENT, /* Save based on current task state. */
+ FP_STATE_FPSIMD,
+ FP_STATE_SVE,
+};
+
struct cpu_context {
unsigned long x19;
unsigned long x20;
@@ -152,6 +158,7 @@ struct thread_struct {
struct user_fpsimd_state fpsimd_state;
} uw;
+ enum fp_type fp_type; /* registers FPSIMD or SVE? */
unsigned int fpsimd_cpu;
void *sve_state; /* SVE registers, if any */
void *za_state; /* ZA register, if any */
@@ -308,13 +315,13 @@ static inline void compat_start_thread(struct pt_regs *regs, unsigned long pc,
}
#endif
-static inline bool is_ttbr0_addr(unsigned long addr)
+static __always_inline bool is_ttbr0_addr(unsigned long addr)
{
/* entry assembly clears tags for TTBR0 addrs */
return addr < TASK_SIZE;
}
-static inline bool is_ttbr1_addr(unsigned long addr)
+static __always_inline bool is_ttbr1_addr(unsigned long addr)
{
/* TTBR1 addresses may have a tag if KASAN_SW_TAGS is in use */
return arch_kasan_reset_tag(addr) >= PAGE_OFFSET;
@@ -396,18 +403,5 @@ long get_tagged_addr_ctrl(struct task_struct *task);
#define GET_TAGGED_ADDR_CTRL() get_tagged_addr_ctrl(current)
#endif
-/*
- * For CONFIG_GCC_PLUGIN_STACKLEAK
- *
- * These need to be macros because otherwise we get stuck in a nightmare
- * of header definitions for the use of task_stack_page.
- */
-
-/*
- * The top of the current task's task stack
- */
-#define current_top_of_stack() ((unsigned long)current->stack + THREAD_SIZE)
-#define on_thread_stack() (on_task_stack(current, current_stack_pointer, 1))
-
#endif /* __ASSEMBLY__ */
#endif /* __ASM_PROCESSOR_H */
diff --git a/arch/arm64/include/asm/ptdump.h b/arch/arm64/include/asm/ptdump.h
index b1dd7ecff7ef..581caac525b0 100644
--- a/arch/arm64/include/asm/ptdump.h
+++ b/arch/arm64/include/asm/ptdump.h
@@ -23,6 +23,7 @@ struct ptdump_info {
void ptdump_walk(struct seq_file *s, struct ptdump_info *info);
#ifdef CONFIG_PTDUMP_DEBUGFS
+#define EFI_RUNTIME_MAP_END DEFAULT_MAP_WINDOW_64
void __init ptdump_debugfs_register(struct ptdump_info *info, const char *name);
#else
static inline void ptdump_debugfs_register(struct ptdump_info *info,
diff --git a/arch/arm64/include/asm/scs.h b/arch/arm64/include/asm/scs.h
index 8297bccf0784..ff7da1268a52 100644
--- a/arch/arm64/include/asm/scs.h
+++ b/arch/arm64/include/asm/scs.h
@@ -5,6 +5,7 @@
#ifdef __ASSEMBLY__
#include <asm/asm-offsets.h>
+#include <asm/sysreg.h>
#ifdef CONFIG_SHADOW_CALL_STACK
scs_sp .req x18
@@ -24,6 +25,54 @@
.endm
#endif /* CONFIG_SHADOW_CALL_STACK */
+
+#else
+
+#include <linux/scs.h>
+#include <asm/cpufeature.h>
+
+#ifdef CONFIG_UNWIND_PATCH_PAC_INTO_SCS
+static inline bool should_patch_pac_into_scs(void)
+{
+ u64 reg;
+
+ /*
+ * We only enable the shadow call stack dynamically if we are running
+ * on a system that does not implement PAC or BTI. PAC and SCS provide
+ * roughly the same level of protection, and BTI relies on the PACIASP
+ * instructions serving as landing pads, preventing us from patching
+ * those instructions into something else.
+ */
+ reg = read_sysreg_s(SYS_ID_AA64ISAR1_EL1);
+ if (SYS_FIELD_GET(ID_AA64ISAR1_EL1, APA, reg) |
+ SYS_FIELD_GET(ID_AA64ISAR1_EL1, API, reg))
+ return false;
+
+ reg = read_sysreg_s(SYS_ID_AA64ISAR2_EL1);
+ if (SYS_FIELD_GET(ID_AA64ISAR2_EL1, APA3, reg))
+ return false;
+
+ if (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL)) {
+ reg = read_sysreg_s(SYS_ID_AA64PFR1_EL1);
+ if (reg & (0xf << ID_AA64PFR1_EL1_BT_SHIFT))
+ return false;
+ }
+ return true;
+}
+
+static inline void dynamic_scs_init(void)
+{
+ if (should_patch_pac_into_scs()) {
+ pr_info("Enabling dynamic shadow call stack\n");
+ static_branch_enable(&dynamic_scs_enabled);
+ }
+}
+#else
+static inline void dynamic_scs_init(void) {}
+#endif
+
+int scs_patch(const u8 eh_frame[], int size);
+
#endif /* __ASSEMBLY __ */
#endif /* _ASM_SCS_H */
diff --git a/arch/arm64/include/asm/spectre.h b/arch/arm64/include/asm/spectre.h
index aa3d3607d5c8..db7b371b367c 100644
--- a/arch/arm64/include/asm/spectre.h
+++ b/arch/arm64/include/asm/spectre.h
@@ -26,6 +26,7 @@ enum mitigation_state {
SPECTRE_VULNERABLE,
};
+struct pt_regs;
struct task_struct;
/*
@@ -98,5 +99,6 @@ enum mitigation_state arm64_get_spectre_bhb_state(void);
bool is_spectre_bhb_affected(const struct arm64_cpu_capabilities *entry, int scope);
u8 spectre_bhb_loop_affected(int scope);
void spectre_bhb_enable_mitigation(const struct arm64_cpu_capabilities *__unused);
+bool try_emulate_el1_ssbs(struct pt_regs *regs, u32 instr);
#endif /* __ASSEMBLY__ */
#endif /* __ASM_SPECTRE_H */
diff --git a/arch/arm64/include/asm/stackprotector.h b/arch/arm64/include/asm/stackprotector.h
index 33f1bb453150..ae3ad80f51fe 100644
--- a/arch/arm64/include/asm/stackprotector.h
+++ b/arch/arm64/include/asm/stackprotector.h
@@ -13,8 +13,6 @@
#ifndef __ASM_STACKPROTECTOR_H
#define __ASM_STACKPROTECTOR_H
-#include <linux/random.h>
-#include <linux/version.h>
#include <asm/pointer_auth.h>
extern unsigned long __stack_chk_guard;
@@ -28,12 +26,7 @@ extern unsigned long __stack_chk_guard;
static __always_inline void boot_init_stack_canary(void)
{
#if defined(CONFIG_STACKPROTECTOR)
- unsigned long canary;
-
- /* Try to get a semi random initial value. */
- get_random_bytes(&canary, sizeof(canary));
- canary ^= LINUX_VERSION_CODE;
- canary &= CANARY_MASK;
+ unsigned long canary = get_random_canary();
current->stack_canary = canary;
if (!IS_ENABLED(CONFIG_STACKPROTECTOR_PER_TASK))
diff --git a/arch/arm64/include/asm/stacktrace.h b/arch/arm64/include/asm/stacktrace.h
index 5a0edb064ea4..4e5354beafb0 100644
--- a/arch/arm64/include/asm/stacktrace.h
+++ b/arch/arm64/include/asm/stacktrace.h
@@ -57,6 +57,8 @@ static inline bool on_task_stack(const struct task_struct *tsk,
return stackinfo_on_stack(&info, sp, size);
}
+#define on_thread_stack() (on_task_stack(current, current_stack_pointer, 1))
+
#ifdef CONFIG_VMAP_STACK
DECLARE_PER_CPU(unsigned long [OVERFLOW_STACK_SIZE/sizeof(long)], overflow_stack);
diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 7d301700d1a9..1312fb48f18b 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -90,20 +90,24 @@
*/
#define pstate_field(op1, op2) ((op1) << Op1_shift | (op2) << Op2_shift)
#define PSTATE_Imm_shift CRm_shift
+#define SET_PSTATE(x, r) __emit_inst(0xd500401f | PSTATE_ ## r | ((!!x) << PSTATE_Imm_shift))
#define PSTATE_PAN pstate_field(0, 4)
#define PSTATE_UAO pstate_field(0, 3)
#define PSTATE_SSBS pstate_field(3, 1)
+#define PSTATE_DIT pstate_field(3, 2)
#define PSTATE_TCO pstate_field(3, 4)
-#define SET_PSTATE_PAN(x) __emit_inst(0xd500401f | PSTATE_PAN | ((!!x) << PSTATE_Imm_shift))
-#define SET_PSTATE_UAO(x) __emit_inst(0xd500401f | PSTATE_UAO | ((!!x) << PSTATE_Imm_shift))
-#define SET_PSTATE_SSBS(x) __emit_inst(0xd500401f | PSTATE_SSBS | ((!!x) << PSTATE_Imm_shift))
-#define SET_PSTATE_TCO(x) __emit_inst(0xd500401f | PSTATE_TCO | ((!!x) << PSTATE_Imm_shift))
+#define SET_PSTATE_PAN(x) SET_PSTATE((x), PAN)
+#define SET_PSTATE_UAO(x) SET_PSTATE((x), UAO)
+#define SET_PSTATE_SSBS(x) SET_PSTATE((x), SSBS)
+#define SET_PSTATE_DIT(x) SET_PSTATE((x), DIT)
+#define SET_PSTATE_TCO(x) SET_PSTATE((x), TCO)
#define set_pstate_pan(x) asm volatile(SET_PSTATE_PAN(x))
#define set_pstate_uao(x) asm volatile(SET_PSTATE_UAO(x))
#define set_pstate_ssbs(x) asm volatile(SET_PSTATE_SSBS(x))
+#define set_pstate_dit(x) asm volatile(SET_PSTATE_DIT(x))
#define __SYS_BARRIER_INSN(CRm, op2, Rt) \
__emit_inst(0xd5000000 | sys_insn(0, 3, 3, (CRm), (op2)) | ((Rt) & 0x1f))
@@ -165,31 +169,6 @@
#define SYS_MPIDR_EL1 sys_reg(3, 0, 0, 0, 5)
#define SYS_REVIDR_EL1 sys_reg(3, 0, 0, 0, 6)
-#define SYS_ID_PFR0_EL1 sys_reg(3, 0, 0, 1, 0)
-#define SYS_ID_PFR1_EL1 sys_reg(3, 0, 0, 1, 1)
-#define SYS_ID_PFR2_EL1 sys_reg(3, 0, 0, 3, 4)
-#define SYS_ID_DFR0_EL1 sys_reg(3, 0, 0, 1, 2)
-#define SYS_ID_DFR1_EL1 sys_reg(3, 0, 0, 3, 5)
-#define SYS_ID_AFR0_EL1 sys_reg(3, 0, 0, 1, 3)
-#define SYS_ID_MMFR0_EL1 sys_reg(3, 0, 0, 1, 4)
-#define SYS_ID_MMFR1_EL1 sys_reg(3, 0, 0, 1, 5)
-#define SYS_ID_MMFR2_EL1 sys_reg(3, 0, 0, 1, 6)
-#define SYS_ID_MMFR3_EL1 sys_reg(3, 0, 0, 1, 7)
-#define SYS_ID_MMFR4_EL1 sys_reg(3, 0, 0, 2, 6)
-#define SYS_ID_MMFR5_EL1 sys_reg(3, 0, 0, 3, 6)
-
-#define SYS_ID_ISAR0_EL1 sys_reg(3, 0, 0, 2, 0)
-#define SYS_ID_ISAR1_EL1 sys_reg(3, 0, 0, 2, 1)
-#define SYS_ID_ISAR2_EL1 sys_reg(3, 0, 0, 2, 2)
-#define SYS_ID_ISAR3_EL1 sys_reg(3, 0, 0, 2, 3)
-#define SYS_ID_ISAR4_EL1 sys_reg(3, 0, 0, 2, 4)
-#define SYS_ID_ISAR5_EL1 sys_reg(3, 0, 0, 2, 5)
-#define SYS_ID_ISAR6_EL1 sys_reg(3, 0, 0, 2, 7)
-
-#define SYS_MVFR0_EL1 sys_reg(3, 0, 0, 3, 0)
-#define SYS_MVFR1_EL1 sys_reg(3, 0, 0, 3, 1)
-#define SYS_MVFR2_EL1 sys_reg(3, 0, 0, 3, 2)
-
#define SYS_ACTLR_EL1 sys_reg(3, 0, 1, 0, 1)
#define SYS_RGSR_EL1 sys_reg(3, 0, 1, 0, 5)
#define SYS_GCR_EL1 sys_reg(3, 0, 1, 0, 6)
@@ -692,112 +671,6 @@
#define ID_AA64MMFR0_EL1_PARANGE_MAX ID_AA64MMFR0_EL1_PARANGE_48
#endif
-#define ID_DFR0_PERFMON_SHIFT 24
-
-#define ID_DFR0_PERFMON_8_0 0x3
-#define ID_DFR0_PERFMON_8_1 0x4
-#define ID_DFR0_PERFMON_8_4 0x5
-#define ID_DFR0_PERFMON_8_5 0x6
-
-#define ID_ISAR4_SWP_FRAC_SHIFT 28
-#define ID_ISAR4_PSR_M_SHIFT 24
-#define ID_ISAR4_SYNCH_PRIM_FRAC_SHIFT 20
-#define ID_ISAR4_BARRIER_SHIFT 16
-#define ID_ISAR4_SMC_SHIFT 12
-#define ID_ISAR4_WRITEBACK_SHIFT 8
-#define ID_ISAR4_WITHSHIFTS_SHIFT 4
-#define ID_ISAR4_UNPRIV_SHIFT 0
-
-#define ID_DFR1_MTPMU_SHIFT 0
-
-#define ID_ISAR0_DIVIDE_SHIFT 24
-#define ID_ISAR0_DEBUG_SHIFT 20
-#define ID_ISAR0_COPROC_SHIFT 16
-#define ID_ISAR0_CMPBRANCH_SHIFT 12
-#define ID_ISAR0_BITFIELD_SHIFT 8
-#define ID_ISAR0_BITCOUNT_SHIFT 4
-#define ID_ISAR0_SWAP_SHIFT 0
-
-#define ID_ISAR5_RDM_SHIFT 24
-#define ID_ISAR5_CRC32_SHIFT 16
-#define ID_ISAR5_SHA2_SHIFT 12
-#define ID_ISAR5_SHA1_SHIFT 8
-#define ID_ISAR5_AES_SHIFT 4
-#define ID_ISAR5_SEVL_SHIFT 0
-
-#define ID_ISAR6_I8MM_SHIFT 24
-#define ID_ISAR6_BF16_SHIFT 20
-#define ID_ISAR6_SPECRES_SHIFT 16
-#define ID_ISAR6_SB_SHIFT 12
-#define ID_ISAR6_FHM_SHIFT 8
-#define ID_ISAR6_DP_SHIFT 4
-#define ID_ISAR6_JSCVT_SHIFT 0
-
-#define ID_MMFR0_INNERSHR_SHIFT 28
-#define ID_MMFR0_FCSE_SHIFT 24
-#define ID_MMFR0_AUXREG_SHIFT 20
-#define ID_MMFR0_TCM_SHIFT 16
-#define ID_MMFR0_SHARELVL_SHIFT 12
-#define ID_MMFR0_OUTERSHR_SHIFT 8
-#define ID_MMFR0_PMSA_SHIFT 4
-#define ID_MMFR0_VMSA_SHIFT 0
-
-#define ID_MMFR4_EVT_SHIFT 28
-#define ID_MMFR4_CCIDX_SHIFT 24
-#define ID_MMFR4_LSM_SHIFT 20
-#define ID_MMFR4_HPDS_SHIFT 16
-#define ID_MMFR4_CNP_SHIFT 12
-#define ID_MMFR4_XNX_SHIFT 8
-#define ID_MMFR4_AC2_SHIFT 4
-#define ID_MMFR4_SPECSEI_SHIFT 0
-
-#define ID_MMFR5_ETS_SHIFT 0
-
-#define ID_PFR0_DIT_SHIFT 24
-#define ID_PFR0_CSV2_SHIFT 16
-#define ID_PFR0_STATE3_SHIFT 12
-#define ID_PFR0_STATE2_SHIFT 8
-#define ID_PFR0_STATE1_SHIFT 4
-#define ID_PFR0_STATE0_SHIFT 0
-
-#define ID_DFR0_PERFMON_SHIFT 24
-#define ID_DFR0_MPROFDBG_SHIFT 20
-#define ID_DFR0_MMAPTRC_SHIFT 16
-#define ID_DFR0_COPTRC_SHIFT 12
-#define ID_DFR0_MMAPDBG_SHIFT 8
-#define ID_DFR0_COPSDBG_SHIFT 4
-#define ID_DFR0_COPDBG_SHIFT 0
-
-#define ID_PFR2_SSBS_SHIFT 4
-#define ID_PFR2_CSV3_SHIFT 0
-
-#define MVFR0_FPROUND_SHIFT 28
-#define MVFR0_FPSHVEC_SHIFT 24
-#define MVFR0_FPSQRT_SHIFT 20
-#define MVFR0_FPDIVIDE_SHIFT 16
-#define MVFR0_FPTRAP_SHIFT 12
-#define MVFR0_FPDP_SHIFT 8
-#define MVFR0_FPSP_SHIFT 4
-#define MVFR0_SIMD_SHIFT 0
-
-#define MVFR1_SIMDFMAC_SHIFT 28
-#define MVFR1_FPHP_SHIFT 24
-#define MVFR1_SIMDHP_SHIFT 20
-#define MVFR1_SIMDSP_SHIFT 16
-#define MVFR1_SIMDINT_SHIFT 12
-#define MVFR1_SIMDLS_SHIFT 8
-#define MVFR1_FPDNAN_SHIFT 4
-#define MVFR1_FPFTZ_SHIFT 0
-
-#define ID_PFR1_GIC_SHIFT 28
-#define ID_PFR1_VIRT_FRAC_SHIFT 24
-#define ID_PFR1_SEC_FRAC_SHIFT 20
-#define ID_PFR1_GENTIMER_SHIFT 16
-#define ID_PFR1_VIRTUALIZATION_SHIFT 12
-#define ID_PFR1_MPROGMOD_SHIFT 8
-#define ID_PFR1_SECURITY_SHIFT 4
-#define ID_PFR1_PROGMOD_SHIFT 0
-
#if defined(CONFIG_ARM64_4K_PAGES)
#define ID_AA64MMFR0_EL1_TGRAN_SHIFT ID_AA64MMFR0_EL1_TGRAN4_SHIFT
#define ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MIN ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED_MIN
@@ -815,9 +688,6 @@
#define ID_AA64MMFR0_EL1_TGRAN_2_SHIFT ID_AA64MMFR0_EL1_TGRAN64_2_SHIFT
#endif
-#define MVFR2_FPMISC_SHIFT 4
-#define MVFR2_SIMDMISC_SHIFT 0
-
#define CPACR_EL1_FPEN_EL1EN (BIT(20)) /* enable EL1 access */
#define CPACR_EL1_FPEN_EL0EN (BIT(21)) /* enable EL0 access, if EL1EN set */
@@ -851,10 +721,6 @@
#define SYS_RGSR_EL1_SEED_SHIFT 8
#define SYS_RGSR_EL1_SEED_MASK 0xffffUL
-/* GMID_EL1 field definitions */
-#define GMID_EL1_BS_SHIFT 0
-#define GMID_EL1_BS_SIZE 4
-
/* TFSR{,E0}_EL1 bit definitions */
#define SYS_TFSR_EL1_TF0_SHIFT 0
#define SYS_TFSR_EL1_TF1_SHIFT 1
diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h
index 6e5826470bea..1f361e2da516 100644
--- a/arch/arm64/include/asm/traps.h
+++ b/arch/arm64/include/asm/traps.h
@@ -13,17 +13,16 @@
struct pt_regs;
-struct undef_hook {
- struct list_head node;
- u32 instr_mask;
- u32 instr_val;
- u64 pstate_mask;
- u64 pstate_val;
- int (*fn)(struct pt_regs *regs, u32 instr);
-};
+#ifdef CONFIG_ARMV8_DEPRECATED
+bool try_emulate_armv8_deprecated(struct pt_regs *regs, u32 insn);
+#else
+static inline bool
+try_emulate_armv8_deprecated(struct pt_regs *regs, u32 insn)
+{
+ return false;
+}
+#endif /* CONFIG_ARMV8_DEPRECATED */
-void register_undef_hook(struct undef_hook *hook);
-void unregister_undef_hook(struct undef_hook *hook);
void force_signal_inject(int signal, int code, unsigned long address, unsigned long err);
void arm64_notify_segfault(unsigned long addr);
void arm64_force_sig_fault(int signo, int code, unsigned long far, const char *str);
diff --git a/arch/arm64/include/asm/uprobes.h b/arch/arm64/include/asm/uprobes.h
index 315eef654e39..ba4bff5ca674 100644
--- a/arch/arm64/include/asm/uprobes.h
+++ b/arch/arm64/include/asm/uprobes.h
@@ -12,7 +12,7 @@
#define MAX_UINSN_BYTES AARCH64_INSN_SIZE
-#define UPROBE_SWBP_INSN BRK64_OPCODE_UPROBES
+#define UPROBE_SWBP_INSN cpu_to_le32(BRK64_OPCODE_UPROBES)
#define UPROBE_SWBP_INSN_SIZE AARCH64_INSN_SIZE
#define UPROBE_XOL_SLOT_BYTES MAX_UINSN_BYTES
diff --git a/arch/arm64/include/uapi/asm/hwcap.h b/arch/arm64/include/uapi/asm/hwcap.h
index 9b245da6f507..b713d30544f1 100644
--- a/arch/arm64/include/uapi/asm/hwcap.h
+++ b/arch/arm64/include/uapi/asm/hwcap.h
@@ -93,5 +93,8 @@
#define HWCAP2_WFXT (1UL << 31)
#define HWCAP2_EBF16 (1UL << 32)
#define HWCAP2_SVE_EBF16 (1UL << 33)
+#define HWCAP2_CSSC (1UL << 34)
+#define HWCAP2_RPRFM (1UL << 35)
+#define HWCAP2_SVE2P1 (1UL << 36)
#endif /* _UAPI__ASM_HWCAP_H */
diff --git a/arch/arm64/include/uapi/asm/sigcontext.h b/arch/arm64/include/uapi/asm/sigcontext.h
index 4aaf31e3bf16..9525041e4a14 100644
--- a/arch/arm64/include/uapi/asm/sigcontext.h
+++ b/arch/arm64/include/uapi/asm/sigcontext.h
@@ -62,6 +62,10 @@ struct sigcontext {
* context. Such structures must be placed after the rt_sigframe on the stack
* and be 16-byte aligned. The last structure must be a dummy one with the
* magic and size set to 0.
+ *
+ * Note that the values allocated for use as magic should be chosen to
+ * be meaningful in ASCII to aid manual parsing, ZA doesn't follow this
+ * convention due to oversight but it should be observed for future additions.
*/
struct _aarch64_ctx {
__u32 magic;
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2f361a883d8c..ceba6792f5b3 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -36,12 +36,6 @@ obj-y := debug-monitors.o entry.o irq.o fpsimd.o \
syscall.o proton-pack.o idreg-override.o idle.o \
patching.o
-targets += efi-entry.o
-
-OBJCOPYFLAGS := --prefix-symbols=__efistub_
-$(obj)/%.stub.o: $(obj)/%.o FORCE
- $(call if_changed,objcopy)
-
obj-$(CONFIG_COMPAT) += sys32.o signal32.o \
sys_compat.o
obj-$(CONFIG_COMPAT) += sigreturn32.o
@@ -57,8 +51,7 @@ obj-$(CONFIG_CPU_PM) += sleep.o suspend.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_JUMP_LABEL) += jump_label.o
obj-$(CONFIG_KGDB) += kgdb.o
-obj-$(CONFIG_EFI) += efi.o efi-entry.stub.o \
- efi-rt-wrapper.o
+obj-$(CONFIG_EFI) += efi.o efi-rt-wrapper.o
obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o
obj-$(CONFIG_ACPI) += acpi.o
@@ -80,6 +73,8 @@ obj-$(CONFIG_ARM64_PTR_AUTH) += pointer_auth.o
obj-$(CONFIG_ARM64_MTE) += mte.o
obj-y += vdso-wrap.o
obj-$(CONFIG_COMPAT_VDSO) += vdso32-wrap.o
+obj-$(CONFIG_UNWIND_PATCH_PAC_INTO_SCS) += patch-scs.o
+CFLAGS_patch-scs.o += -mbranch-protection=none
# Force dependency (vdso*-wrap.S includes vdso.so through incbin)
$(obj)/vdso-wrap.o: $(obj)/vdso/vdso.so
diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
index a5a256e3f9fe..378453faa87e 100644
--- a/arch/arm64/kernel/acpi.c
+++ b/arch/arm64/kernel/acpi.c
@@ -13,6 +13,7 @@
#define pr_fmt(fmt) "ACPI: " fmt
#include <linux/acpi.h>
+#include <linux/arm-smccc.h>
#include <linux/cpumask.h>
#include <linux/efi.h>
#include <linux/efi-bgrt.h>
@@ -411,3 +412,108 @@ void arch_reserve_mem_area(acpi_physical_address addr, size_t size)
{
memblock_mark_nomap(addr, size);
}
+
+#ifdef CONFIG_ACPI_FFH
+/*
+ * Implements ARM64 specific callbacks to support ACPI FFH Operation Region as
+ * specified in https://developer.arm.com/docs/den0048/latest
+ */
+struct acpi_ffh_data {
+ struct acpi_ffh_info info;
+ void (*invoke_ffh_fn)(unsigned long a0, unsigned long a1,
+ unsigned long a2, unsigned long a3,
+ unsigned long a4, unsigned long a5,
+ unsigned long a6, unsigned long a7,
+ struct arm_smccc_res *args,
+ struct arm_smccc_quirk *res);
+ void (*invoke_ffh64_fn)(const struct arm_smccc_1_2_regs *args,
+ struct arm_smccc_1_2_regs *res);
+};
+
+int acpi_ffh_address_space_arch_setup(void *handler_ctxt, void **region_ctxt)
+{
+ enum arm_smccc_conduit conduit;
+ struct acpi_ffh_data *ffh_ctxt;
+
+ ffh_ctxt = kzalloc(sizeof(*ffh_ctxt), GFP_KERNEL);
+ if (!ffh_ctxt)
+ return -ENOMEM;
+
+ if (arm_smccc_get_version() < ARM_SMCCC_VERSION_1_2)
+ return -EOPNOTSUPP;
+
+ conduit = arm_smccc_1_1_get_conduit();
+ if (conduit == SMCCC_CONDUIT_NONE) {
+ pr_err("%s: invalid SMCCC conduit\n", __func__);
+ return -EOPNOTSUPP;
+ }
+
+ if (conduit == SMCCC_CONDUIT_SMC) {
+ ffh_ctxt->invoke_ffh_fn = __arm_smccc_smc;
+ ffh_ctxt->invoke_ffh64_fn = arm_smccc_1_2_smc;
+ } else {
+ ffh_ctxt->invoke_ffh_fn = __arm_smccc_hvc;
+ ffh_ctxt->invoke_ffh64_fn = arm_smccc_1_2_hvc;
+ }
+
+ memcpy(ffh_ctxt, handler_ctxt, sizeof(ffh_ctxt->info));
+
+ *region_ctxt = ffh_ctxt;
+ return AE_OK;
+}
+
+static bool acpi_ffh_smccc_owner_allowed(u32 fid)
+{
+ int owner = ARM_SMCCC_OWNER_NUM(fid);
+
+ if (owner == ARM_SMCCC_OWNER_STANDARD ||
+ owner == ARM_SMCCC_OWNER_SIP || owner == ARM_SMCCC_OWNER_OEM)
+ return true;
+
+ return false;
+}
+
+int acpi_ffh_address_space_arch_handler(acpi_integer *value, void *region_context)
+{
+ int ret = 0;
+ struct acpi_ffh_data *ffh_ctxt = region_context;
+
+ if (ffh_ctxt->info.offset == 0) {
+ /* SMC/HVC 32bit call */
+ struct arm_smccc_res res;
+ u32 a[8] = { 0 }, *ptr = (u32 *)value;
+
+ if (!ARM_SMCCC_IS_FAST_CALL(*ptr) || ARM_SMCCC_IS_64(*ptr) ||
+ !acpi_ffh_smccc_owner_allowed(*ptr) ||
+ ffh_ctxt->info.length > 32) {
+ ret = AE_ERROR;
+ } else {
+ int idx, len = ffh_ctxt->info.length >> 2;
+
+ for (idx = 0; idx < len; idx++)
+ a[idx] = *(ptr + idx);
+
+ ffh_ctxt->invoke_ffh_fn(a[0], a[1], a[2], a[3], a[4],
+ a[5], a[6], a[7], &res, NULL);
+ memcpy(value, &res, sizeof(res));
+ }
+
+ } else if (ffh_ctxt->info.offset == 1) {
+ /* SMC/HVC 64bit call */
+ struct arm_smccc_1_2_regs *r = (struct arm_smccc_1_2_regs *)value;
+
+ if (!ARM_SMCCC_IS_FAST_CALL(r->a0) || !ARM_SMCCC_IS_64(r->a0) ||
+ !acpi_ffh_smccc_owner_allowed(r->a0) ||
+ ffh_ctxt->info.length > sizeof(*r)) {
+ ret = AE_ERROR;
+ } else {
+ ffh_ctxt->invoke_ffh64_fn(r, r);
+ memcpy(value, r, ffh_ctxt->info.length);
+ }
+ } else {
+ ret = AE_ERROR;
+ }
+
+ return ret;
+}
+#endif /* CONFIG_ACPI_FFH */
diff --git a/arch/arm64/kernel/alternative.c b/arch/arm64/kernel/alternative.c
index 91263d09ea65..d32d4ed5519b 100644
--- a/arch/arm64/kernel/alternative.c
+++ b/arch/arm64/kernel/alternative.c
@@ -196,7 +196,7 @@ static void __apply_alternatives(const struct alt_region *region,
}
}
-void apply_alternatives_vdso(void)
+static void __init apply_alternatives_vdso(void)
{
struct alt_region region;
const struct elf64_hdr *hdr;
@@ -220,7 +220,7 @@ void apply_alternatives_vdso(void)
__apply_alternatives(&region, false, &all_capabilities[0]);
}
-static const struct alt_region kernel_alternatives = {
+static const struct alt_region kernel_alternatives __initconst = {
.begin = (struct alt_instr *)__alt_instructions,
.end = (struct alt_instr *)__alt_instructions_end,
};
@@ -229,7 +229,7 @@ static const struct alt_region kernel_alternatives = {
* We might be patching the stop_machine state machine, so implement a
* really simple polling protocol here.
*/
-static int __apply_alternatives_multi_stop(void *unused)
+static int __init __apply_alternatives_multi_stop(void *unused)
{
/* We always have a CPU 0 at this point (__init) */
if (smp_processor_id()) {
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c
index fb0e7c7b2e20..8a9052cf3013 100644
--- a/arch/arm64/kernel/armv8_deprecated.c
+++ b/arch/arm64/kernel/armv8_deprecated.c
@@ -17,7 +17,6 @@
#include <asm/sysreg.h>
#include <asm/system_misc.h>
#include <asm/traps.h>
-#include <asm/kprobes.h>
#define CREATE_TRACE_POINTS
#include "trace-events-emulation.h"
@@ -39,226 +38,46 @@ enum insn_emulation_mode {
enum legacy_insn_status {
INSN_DEPRECATED,
INSN_OBSOLETE,
-};
-
-struct insn_emulation_ops {
- const char *name;
- enum legacy_insn_status status;
- struct undef_hook *hooks;
- int (*set_hw_mode)(bool enable);
+ INSN_UNAVAILABLE,
};
struct insn_emulation {
- struct list_head node;
- struct insn_emulation_ops *ops;
+ const char *name;
+ enum legacy_insn_status status;
+ bool (*try_emulate)(struct pt_regs *regs,
+ u32 insn);
+ int (*set_hw_mode)(bool enable);
+
int current_mode;
int min;
int max;
-};
-
-static LIST_HEAD(insn_emulation);
-static int nr_insn_emulated __initdata;
-static DEFINE_RAW_SPINLOCK(insn_emulation_lock);
-static DEFINE_MUTEX(insn_emulation_mutex);
-
-static void register_emulation_hooks(struct insn_emulation_ops *ops)
-{
- struct undef_hook *hook;
-
- BUG_ON(!ops->hooks);
-
- for (hook = ops->hooks; hook->instr_mask; hook++)
- register_undef_hook(hook);
-
- pr_notice("Registered %s emulation handler\n", ops->name);
-}
-
-static void remove_emulation_hooks(struct insn_emulation_ops *ops)
-{
- struct undef_hook *hook;
-
- BUG_ON(!ops->hooks);
-
- for (hook = ops->hooks; hook->instr_mask; hook++)
- unregister_undef_hook(hook);
-
- pr_notice("Removed %s emulation handler\n", ops->name);
-}
-
-static void enable_insn_hw_mode(void *data)
-{
- struct insn_emulation *insn = (struct insn_emulation *)data;
- if (insn->ops->set_hw_mode)
- insn->ops->set_hw_mode(true);
-}
-
-static void disable_insn_hw_mode(void *data)
-{
- struct insn_emulation *insn = (struct insn_emulation *)data;
- if (insn->ops->set_hw_mode)
- insn->ops->set_hw_mode(false);
-}
-
-/* Run set_hw_mode(mode) on all active CPUs */
-static int run_all_cpu_set_hw_mode(struct insn_emulation *insn, bool enable)
-{
- if (!insn->ops->set_hw_mode)
- return -EINVAL;
- if (enable)
- on_each_cpu(enable_insn_hw_mode, (void *)insn, true);
- else
- on_each_cpu(disable_insn_hw_mode, (void *)insn, true);
- return 0;
-}
-
-/*
- * Run set_hw_mode for all insns on a starting CPU.
- * Returns:
- * 0 - If all the hooks ran successfully.
- * -EINVAL - At least one hook is not supported by the CPU.
- */
-static int run_all_insn_set_hw_mode(unsigned int cpu)
-{
- int rc = 0;
- unsigned long flags;
- struct insn_emulation *insn;
-
- raw_spin_lock_irqsave(&insn_emulation_lock, flags);
- list_for_each_entry(insn, &insn_emulation, node) {
- bool enable = (insn->current_mode == INSN_HW);
- if (insn->ops->set_hw_mode && insn->ops->set_hw_mode(enable)) {
- pr_warn("CPU[%u] cannot support the emulation of %s",
- cpu, insn->ops->name);
- rc = -EINVAL;
- }
- }
- raw_spin_unlock_irqrestore(&insn_emulation_lock, flags);
- return rc;
-}
-
-static int update_insn_emulation_mode(struct insn_emulation *insn,
- enum insn_emulation_mode prev)
-{
- int ret = 0;
-
- switch (prev) {
- case INSN_UNDEF: /* Nothing to be done */
- break;
- case INSN_EMULATE:
- remove_emulation_hooks(insn->ops);
- break;
- case INSN_HW:
- if (!run_all_cpu_set_hw_mode(insn, false))
- pr_notice("Disabled %s support\n", insn->ops->name);
- break;
- }
-
- switch (insn->current_mode) {
- case INSN_UNDEF:
- break;
- case INSN_EMULATE:
- register_emulation_hooks(insn->ops);
- break;
- case INSN_HW:
- ret = run_all_cpu_set_hw_mode(insn, true);
- if (!ret)
- pr_notice("Enabled %s support\n", insn->ops->name);
- break;
- }
- return ret;
-}
-
-static void __init register_insn_emulation(struct insn_emulation_ops *ops)
-{
- unsigned long flags;
- struct insn_emulation *insn;
-
- insn = kzalloc(sizeof(*insn), GFP_KERNEL);
- if (!insn)
- return;
-
- insn->ops = ops;
- insn->min = INSN_UNDEF;
-
- switch (ops->status) {
- case INSN_DEPRECATED:
- insn->current_mode = INSN_EMULATE;
- /* Disable the HW mode if it was turned on at early boot time */
- run_all_cpu_set_hw_mode(insn, false);
- insn->max = INSN_HW;
- break;
- case INSN_OBSOLETE:
- insn->current_mode = INSN_UNDEF;
- insn->max = INSN_EMULATE;
- break;
- }
-
- raw_spin_lock_irqsave(&insn_emulation_lock, flags);
- list_add(&insn->node, &insn_emulation);
- nr_insn_emulated++;
- raw_spin_unlock_irqrestore(&insn_emulation_lock, flags);
-
- /* Register any handlers if required */
- update_insn_emulation_mode(insn, INSN_UNDEF);
-}
-
-static int emulation_proc_handler(struct ctl_table *table, int write,
- void *buffer, size_t *lenp,
- loff_t *ppos)
-{
- int ret = 0;
- struct insn_emulation *insn = container_of(table->data, struct insn_emulation, current_mode);
- enum insn_emulation_mode prev_mode = insn->current_mode;
-
- mutex_lock(&insn_emulation_mutex);
- ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+ /*
+ * sysctl for this emulation + a sentinal entry.
+ */
+ struct ctl_table sysctl[2];
+};
- if (ret || !write || prev_mode == insn->current_mode)
- goto ret;
+#define ARM_OPCODE_CONDTEST_FAIL 0
+#define ARM_OPCODE_CONDTEST_PASS 1
+#define ARM_OPCODE_CONDTEST_UNCOND 2
- ret = update_insn_emulation_mode(insn, prev_mode);
- if (ret) {
- /* Mode change failed, revert to previous mode. */
- insn->current_mode = prev_mode;
- update_insn_emulation_mode(insn, INSN_UNDEF);
- }
-ret:
- mutex_unlock(&insn_emulation_mutex);
- return ret;
-}
+#define ARM_OPCODE_CONDITION_UNCOND 0xf
-static void __init register_insn_emulation_sysctl(void)
+static unsigned int __maybe_unused aarch32_check_condition(u32 opcode, u32 psr)
{
- unsigned long flags;
- int i = 0;
- struct insn_emulation *insn;
- struct ctl_table *insns_sysctl, *sysctl;
-
- insns_sysctl = kcalloc(nr_insn_emulated + 1, sizeof(*sysctl),
- GFP_KERNEL);
- if (!insns_sysctl)
- return;
-
- raw_spin_lock_irqsave(&insn_emulation_lock, flags);
- list_for_each_entry(insn, &insn_emulation, node) {
- sysctl = &insns_sysctl[i];
-
- sysctl->mode = 0644;
- sysctl->maxlen = sizeof(int);
+ u32 cc_bits = opcode >> 28;
- sysctl->procname = insn->ops->name;
- sysctl->data = &insn->current_mode;
- sysctl->extra1 = &insn->min;
- sysctl->extra2 = &insn->max;
- sysctl->proc_handler = emulation_proc_handler;
- i++;
+ if (cc_bits != ARM_OPCODE_CONDITION_UNCOND) {
+ if ((*aarch32_opcode_cond_checks[cc_bits])(psr))
+ return ARM_OPCODE_CONDTEST_PASS;
+ else
+ return ARM_OPCODE_CONDTEST_FAIL;
}
- raw_spin_unlock_irqrestore(&insn_emulation_lock, flags);
-
- register_sysctl("abi", insns_sysctl);
+ return ARM_OPCODE_CONDTEST_UNCOND;
}
+#ifdef CONFIG_SWP_EMULATION
/*
* Implement emulation of the SWP/SWPB instructions using load-exclusive and
* store-exclusive.
@@ -339,25 +158,6 @@ static int emulate_swpX(unsigned int address, unsigned int *data,
return res;
}
-#define ARM_OPCODE_CONDTEST_FAIL 0
-#define ARM_OPCODE_CONDTEST_PASS 1
-#define ARM_OPCODE_CONDTEST_UNCOND 2
-
-#define ARM_OPCODE_CONDITION_UNCOND 0xf
-
-static unsigned int __kprobes aarch32_check_condition(u32 opcode, u32 psr)
-{
- u32 cc_bits = opcode >> 28;
-
- if (cc_bits != ARM_OPCODE_CONDITION_UNCOND) {
- if ((*aarch32_opcode_cond_checks[cc_bits])(psr))
- return ARM_OPCODE_CONDTEST_PASS;
- else
- return ARM_OPCODE_CONDTEST_FAIL;
- }
- return ARM_OPCODE_CONDTEST_UNCOND;
-}
-
/*
* swp_handler logs the id of calling process, dissects the instruction, sanity
* checks the memory location, calls emulate_swpX for the actual operation and
@@ -430,28 +230,27 @@ fault:
return 0;
}
-/*
- * Only emulate SWP/SWPB executed in ARM state/User mode.
- * The kernel must be SWP free and SWP{B} does not exist in Thumb.
- */
-static struct undef_hook swp_hooks[] = {
- {
- .instr_mask = 0x0fb00ff0,
- .instr_val = 0x01000090,
- .pstate_mask = PSR_AA32_MODE_MASK,
- .pstate_val = PSR_AA32_MODE_USR,
- .fn = swp_handler
- },
- { }
-};
+static bool try_emulate_swp(struct pt_regs *regs, u32 insn)
+{
+ /* SWP{B} only exists in ARM state and does not exist in Thumb */
+ if (!compat_user_mode(regs) || compat_thumb_mode(regs))
+ return false;
-static struct insn_emulation_ops swp_ops = {
+ if ((insn & 0x0fb00ff0) != 0x01000090)
+ return false;
+
+ return swp_handler(regs, insn) == 0;
+}
+
+static struct insn_emulation insn_swp = {
.name = "swp",
.status = INSN_OBSOLETE,
- .hooks = swp_hooks,
+ .try_emulate = try_emulate_swp,
.set_hw_mode = NULL,
};
+#endif /* CONFIG_SWP_EMULATION */
+#ifdef CONFIG_CP15_BARRIER_EMULATION
static int cp15barrier_handler(struct pt_regs *regs, u32 instr)
{
perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, regs->pc);
@@ -514,31 +313,29 @@ static int cp15_barrier_set_hw_mode(bool enable)
return 0;
}
-static struct undef_hook cp15_barrier_hooks[] = {
- {
- .instr_mask = 0x0fff0fdf,
- .instr_val = 0x0e070f9a,
- .pstate_mask = PSR_AA32_MODE_MASK,
- .pstate_val = PSR_AA32_MODE_USR,
- .fn = cp15barrier_handler,
- },
- {
- .instr_mask = 0x0fff0fff,
- .instr_val = 0x0e070f95,
- .pstate_mask = PSR_AA32_MODE_MASK,
- .pstate_val = PSR_AA32_MODE_USR,
- .fn = cp15barrier_handler,
- },
- { }
-};
+static bool try_emulate_cp15_barrier(struct pt_regs *regs, u32 insn)
+{
+ if (!compat_user_mode(regs) || compat_thumb_mode(regs))
+ return false;
+
+ if ((insn & 0x0fff0fdf) == 0x0e070f9a)
+ return cp15barrier_handler(regs, insn) == 0;
+
+ if ((insn & 0x0fff0fff) == 0x0e070f95)
+ return cp15barrier_handler(regs, insn) == 0;
-static struct insn_emulation_ops cp15_barrier_ops = {
+ return false;
+}
+
+static struct insn_emulation insn_cp15_barrier = {
.name = "cp15_barrier",
.status = INSN_DEPRECATED,
- .hooks = cp15_barrier_hooks,
+ .try_emulate = try_emulate_cp15_barrier,
.set_hw_mode = cp15_barrier_set_hw_mode,
};
+#endif /* CONFIG_CP15_BARRIER_EMULATION */
+#ifdef CONFIG_SETEND_EMULATION
static int setend_set_hw_mode(bool enable)
{
if (!cpu_supports_mixed_endian_el0())
@@ -586,31 +383,218 @@ static int t16_setend_handler(struct pt_regs *regs, u32 instr)
return rc;
}
-static struct undef_hook setend_hooks[] = {
- {
- .instr_mask = 0xfffffdff,
- .instr_val = 0xf1010000,
- .pstate_mask = PSR_AA32_MODE_MASK,
- .pstate_val = PSR_AA32_MODE_USR,
- .fn = a32_setend_handler,
- },
- {
- /* Thumb mode */
- .instr_mask = 0xfffffff7,
- .instr_val = 0x0000b650,
- .pstate_mask = (PSR_AA32_T_BIT | PSR_AA32_MODE_MASK),
- .pstate_val = (PSR_AA32_T_BIT | PSR_AA32_MODE_USR),
- .fn = t16_setend_handler,
- },
- {}
-};
+static bool try_emulate_setend(struct pt_regs *regs, u32 insn)
+{
+ if (compat_thumb_mode(regs) &&
+ (insn & 0xfffffff7) == 0x0000b650)
+ return t16_setend_handler(regs, insn) == 0;
+
+ if (compat_user_mode(regs) &&
+ (insn & 0xfffffdff) == 0xf1010000)
+ return a32_setend_handler(regs, insn) == 0;
-static struct insn_emulation_ops setend_ops = {
+ return false;
+}
+
+static struct insn_emulation insn_setend = {
.name = "setend",
.status = INSN_DEPRECATED,
- .hooks = setend_hooks,
+ .try_emulate = try_emulate_setend,
.set_hw_mode = setend_set_hw_mode,
};
+#endif /* CONFIG_SETEND_EMULATION */
+
+static struct insn_emulation *insn_emulations[] = {
+#ifdef CONFIG_SWP_EMULATION
+ &insn_swp,
+#endif
+#ifdef CONFIG_CP15_BARRIER_EMULATION
+ &insn_cp15_barrier,
+#endif
+#ifdef CONFIG_SETEND_EMULATION
+ &insn_setend,
+#endif
+};
+
+static DEFINE_MUTEX(insn_emulation_mutex);
+
+static void enable_insn_hw_mode(void *data)
+{
+ struct insn_emulation *insn = (struct insn_emulation *)data;
+ if (insn->set_hw_mode)
+ insn->set_hw_mode(true);
+}
+
+static void disable_insn_hw_mode(void *data)
+{
+ struct insn_emulation *insn = (struct insn_emulation *)data;
+ if (insn->set_hw_mode)
+ insn->set_hw_mode(false);
+}
+
+/* Run set_hw_mode(mode) on all active CPUs */
+static int run_all_cpu_set_hw_mode(struct insn_emulation *insn, bool enable)
+{
+ if (!insn->set_hw_mode)
+ return -EINVAL;
+ if (enable)
+ on_each_cpu(enable_insn_hw_mode, (void *)insn, true);
+ else
+ on_each_cpu(disable_insn_hw_mode, (void *)insn, true);
+ return 0;
+}
+
+/*
+ * Run set_hw_mode for all insns on a starting CPU.
+ * Returns:
+ * 0 - If all the hooks ran successfully.
+ * -EINVAL - At least one hook is not supported by the CPU.
+ */
+static int run_all_insn_set_hw_mode(unsigned int cpu)
+{
+ int rc = 0;
+ unsigned long flags;
+
+ /*
+ * Disable IRQs to serialize against an IPI from
+ * run_all_cpu_set_hw_mode(), ensuring the HW is programmed to the most
+ * recent enablement state if the two race with one another.
+ */
+ local_irq_save(flags);
+ for (int i = 0; i < ARRAY_SIZE(insn_emulations); i++) {
+ struct insn_emulation *insn = insn_emulations[i];
+ bool enable = READ_ONCE(insn->current_mode) == INSN_HW;
+ if (insn->set_hw_mode && insn->set_hw_mode(enable)) {
+ pr_warn("CPU[%u] cannot support the emulation of %s",
+ cpu, insn->name);
+ rc = -EINVAL;
+ }
+ }
+ local_irq_restore(flags);
+
+ return rc;
+}
+
+static int update_insn_emulation_mode(struct insn_emulation *insn,
+ enum insn_emulation_mode prev)
+{
+ int ret = 0;
+
+ switch (prev) {
+ case INSN_UNDEF: /* Nothing to be done */
+ break;
+ case INSN_EMULATE:
+ break;
+ case INSN_HW:
+ if (!run_all_cpu_set_hw_mode(insn, false))
+ pr_notice("Disabled %s support\n", insn->name);
+ break;
+ }
+
+ switch (insn->current_mode) {
+ case INSN_UNDEF:
+ break;
+ case INSN_EMULATE:
+ break;
+ case INSN_HW:
+ ret = run_all_cpu_set_hw_mode(insn, true);
+ if (!ret)
+ pr_notice("Enabled %s support\n", insn->name);
+ break;
+ }
+
+ return ret;
+}
+
+static int emulation_proc_handler(struct ctl_table *table, int write,
+ void *buffer, size_t *lenp,
+ loff_t *ppos)
+{
+ int ret = 0;
+ struct insn_emulation *insn = container_of(table->data, struct insn_emulation, current_mode);
+ enum insn_emulation_mode prev_mode = insn->current_mode;
+
+ mutex_lock(&insn_emulation_mutex);
+ ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+
+ if (ret || !write || prev_mode == insn->current_mode)
+ goto ret;
+
+ ret = update_insn_emulation_mode(insn, prev_mode);
+ if (ret) {
+ /* Mode change failed, revert to previous mode. */
+ WRITE_ONCE(insn->current_mode, prev_mode);
+ update_insn_emulation_mode(insn, INSN_UNDEF);
+ }
+ret:
+ mutex_unlock(&insn_emulation_mutex);
+ return ret;
+}
+
+static void __init register_insn_emulation(struct insn_emulation *insn)
+{
+ struct ctl_table *sysctl;
+
+ insn->min = INSN_UNDEF;
+
+ switch (insn->status) {
+ case INSN_DEPRECATED:
+ insn->current_mode = INSN_EMULATE;
+ /* Disable the HW mode if it was turned on at early boot time */
+ run_all_cpu_set_hw_mode(insn, false);
+ insn->max = INSN_HW;
+ break;
+ case INSN_OBSOLETE:
+ insn->current_mode = INSN_UNDEF;
+ insn->max = INSN_EMULATE;
+ break;
+ case INSN_UNAVAILABLE:
+ insn->current_mode = INSN_UNDEF;
+ insn->max = INSN_UNDEF;
+ break;
+ }
+
+ /* Program the HW if required */
+ update_insn_emulation_mode(insn, INSN_UNDEF);
+
+ if (insn->status != INSN_UNAVAILABLE) {
+ sysctl = &insn->sysctl[0];
+
+ sysctl->mode = 0644;
+ sysctl->maxlen = sizeof(int);
+
+ sysctl->procname = insn->name;
+ sysctl->data = &insn->current_mode;
+ sysctl->extra1 = &insn->min;
+ sysctl->extra2 = &insn->max;
+ sysctl->proc_handler = emulation_proc_handler;
+
+ register_sysctl("abi", sysctl);
+ }
+}
+
+bool try_emulate_armv8_deprecated(struct pt_regs *regs, u32 insn)
+{
+ for (int i = 0; i < ARRAY_SIZE(insn_emulations); i++) {
+ struct insn_emulation *ie = insn_emulations[i];
+
+ if (ie->status == INSN_UNAVAILABLE)
+ continue;
+
+ /*
+ * A trap may race with the mode being changed
+ * INSN_EMULATE<->INSN_HW. Try to emulate the instruction to
+ * avoid a spurious UNDEF.
+ */
+ if (READ_ONCE(ie->current_mode) == INSN_UNDEF)
+ continue;
+
+ if (ie->try_emulate(regs, insn))
+ return true;
+ }
+
+ return false;
+}
/*
* Invoked as core_initcall, which guarantees that the instruction
@@ -618,24 +602,25 @@ static struct insn_emulation_ops setend_ops = {
*/
static int __init armv8_deprecated_init(void)
{
- if (IS_ENABLED(CONFIG_SWP_EMULATION))
- register_insn_emulation(&swp_ops);
+#ifdef CONFIG_SETEND_EMULATION
+ if (!system_supports_mixed_endian_el0()) {
+ insn_setend.status = INSN_UNAVAILABLE;
+ pr_info("setend instruction emulation is not supported on this system\n");
+ }
- if (IS_ENABLED(CONFIG_CP15_BARRIER_EMULATION))
- register_insn_emulation(&cp15_barrier_ops);
+#endif
+ for (int i = 0; i < ARRAY_SIZE(insn_emulations); i++) {
+ struct insn_emulation *ie = insn_emulations[i];
- if (IS_ENABLED(CONFIG_SETEND_EMULATION)) {
- if (system_supports_mixed_endian_el0())
- register_insn_emulation(&setend_ops);
- else
- pr_info("setend instruction emulation is not supported on this system\n");
+ if (ie->status == INSN_UNAVAILABLE)
+ continue;
+
+ register_insn_emulation(ie);
}
cpuhp_setup_state_nocalls(CPUHP_AP_ARM64_ISNDEP_STARTING,
"arm64/isndep:starting",
run_all_insn_set_hw_mode, NULL);
- register_insn_emulation_sysctl();
-
return 0;
}
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 1197e7679882..2234624536d9 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -82,6 +82,19 @@ int main(void)
DEFINE(S_STACKFRAME, offsetof(struct pt_regs, stackframe));
DEFINE(PT_REGS_SIZE, sizeof(struct pt_regs));
BLANK();
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
+ DEFINE(FREGS_X0, offsetof(struct ftrace_regs, regs[0]));
+ DEFINE(FREGS_X2, offsetof(struct ftrace_regs, regs[2]));
+ DEFINE(FREGS_X4, offsetof(struct ftrace_regs, regs[4]));
+ DEFINE(FREGS_X6, offsetof(struct ftrace_regs, regs[6]));
+ DEFINE(FREGS_X8, offsetof(struct ftrace_regs, regs[8]));
+ DEFINE(FREGS_FP, offsetof(struct ftrace_regs, fp));
+ DEFINE(FREGS_LR, offsetof(struct ftrace_regs, lr));
+ DEFINE(FREGS_SP, offsetof(struct ftrace_regs, sp));
+ DEFINE(FREGS_PC, offsetof(struct ftrace_regs, pc));
+ DEFINE(FREGS_SIZE, sizeof(struct ftrace_regs));
+ BLANK();
+#endif
#ifdef CONFIG_COMPAT
DEFINE(COMPAT_SIGFRAME_REGS_OFFSET, offsetof(struct compat_sigframe, uc.uc_mcontext.arm_r0));
DEFINE(COMPAT_RT_SIGFRAME_REGS_OFFSET, offsetof(struct compat_rt_sigframe, sig.uc.uc_mcontext.arm_r0));
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 89ac00084f38..307faa2b4395 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -661,6 +661,13 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
CAP_MIDR_RANGE_LIST(trbe_write_out_of_range_cpus),
},
#endif
+#ifdef CONFIG_ARM64_ERRATUM_2645198
+ {
+ .desc = "ARM erratum 2645198",
+ .capability = ARM64_WORKAROUND_2645198,
+ ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A715)
+ },
+#endif
#ifdef CONFIG_ARM64_ERRATUM_2077057
{
.desc = "ARM erratum 2077057",
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
index b3f37e2209ad..7e76e1fda2a1 100644
--- a/arch/arm64/kernel/cpufeature.c
+++ b/arch/arm64/kernel/cpufeature.c
@@ -212,6 +212,8 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
};
static const struct arm64_ftr_bits ftr_id_aa64isar2[] = {
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_CSSC_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64ISAR2_EL1_RPRFM_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_HIGHER_SAFE, ID_AA64ISAR2_EL1_BC_SHIFT, 4, 0),
ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_PTR_AUTH),
FTR_STRICT, FTR_EXACT, ID_AA64ISAR2_EL1_APA3_SHIFT, 4, 0),
@@ -402,14 +404,14 @@ struct arm64_ftr_reg arm64_ftr_reg_ctrel0 = {
};
static const struct arm64_ftr_bits ftr_id_mmfr0[] = {
- S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_INNERSHR_SHIFT, 4, 0xf),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_FCSE_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_MMFR0_AUXREG_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_TCM_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_SHARELVL_SHIFT, 4, 0),
- S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_OUTERSHR_SHIFT, 4, 0xf),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_PMSA_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_VMSA_SHIFT, 4, 0),
+ S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_EL1_InnerShr_SHIFT, 4, 0xf),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_EL1_FCSE_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_MMFR0_EL1_AuxReg_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_EL1_TCM_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_EL1_ShareLvl_SHIFT, 4, 0),
+ S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_EL1_OuterShr_SHIFT, 4, 0xf),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_EL1_PMSA_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR0_EL1_VMSA_SHIFT, 4, 0),
ARM64_FTR_END,
};
@@ -429,32 +431,32 @@ static const struct arm64_ftr_bits ftr_id_aa64dfr0[] = {
};
static const struct arm64_ftr_bits ftr_mvfr0[] = {
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPROUND_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPSHVEC_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPSQRT_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPDIVIDE_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPTRAP_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPDP_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_FPSP_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_SIMD_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_EL1_FPRound_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_EL1_FPShVec_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_EL1_FPSqrt_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_EL1_FPDivide_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_EL1_FPTrap_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_EL1_FPDP_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_EL1_FPSP_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR0_EL1_SIMDReg_SHIFT, 4, 0),
ARM64_FTR_END,
};
static const struct arm64_ftr_bits ftr_mvfr1[] = {
- ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDFMAC_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_FPHP_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDHP_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDSP_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDINT_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_SIMDLS_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_FPDNAN_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_FPFTZ_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_EL1_SIMDFMAC_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_EL1_FPHP_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_EL1_SIMDHP_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_EL1_SIMDSP_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_EL1_SIMDInt_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_EL1_SIMDLS_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_EL1_FPDNaN_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR1_EL1_FPFtZ_SHIFT, 4, 0),
ARM64_FTR_END,
};
static const struct arm64_ftr_bits ftr_mvfr2[] = {
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR2_FPMISC_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR2_SIMDMISC_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR2_EL1_FPMisc_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, MVFR2_EL1_SIMDMisc_SHIFT, 4, 0),
ARM64_FTR_END,
};
@@ -470,34 +472,34 @@ static const struct arm64_ftr_bits ftr_gmid[] = {
};
static const struct arm64_ftr_bits ftr_id_isar0[] = {
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_DIVIDE_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_DEBUG_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_COPROC_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_CMPBRANCH_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_BITFIELD_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_BITCOUNT_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_SWAP_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_EL1_Divide_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_EL1_Debug_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_EL1_Coproc_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_EL1_CmpBranch_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_EL1_BitField_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_EL1_BitCount_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR0_EL1_Swap_SHIFT, 4, 0),
ARM64_FTR_END,
};
static const struct arm64_ftr_bits ftr_id_isar5[] = {
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_RDM_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_CRC32_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA2_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SHA1_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_AES_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_SEVL_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_EL1_RDM_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_EL1_CRC32_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_EL1_SHA2_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_EL1_SHA1_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_EL1_AES_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR5_EL1_SEVL_SHIFT, 4, 0),
ARM64_FTR_END,
};
static const struct arm64_ftr_bits ftr_id_mmfr4[] = {
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_EVT_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_CCIDX_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_LSM_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_HPDS_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_CNP_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_XNX_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_AC2_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_EL1_EVT_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_EL1_CCIDX_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_EL1_LSM_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_EL1_HPDS_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_EL1_CnP_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_EL1_XNX_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR4_EL1_AC2_SHIFT, 4, 0),
/*
* SpecSEI = 1 indicates that the PE might generate an SError on an
@@ -505,80 +507,80 @@ static const struct arm64_ftr_bits ftr_id_mmfr4[] = {
* SError might be generated than it will not be. Hence it has been
* classified as FTR_HIGHER_SAFE.
*/
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_HIGHER_SAFE, ID_MMFR4_SPECSEI_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_HIGHER_SAFE, ID_MMFR4_EL1_SpecSEI_SHIFT, 4, 0),
ARM64_FTR_END,
};
static const struct arm64_ftr_bits ftr_id_isar4[] = {
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_SWP_FRAC_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_PSR_M_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_SYNCH_PRIM_FRAC_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_BARRIER_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_SMC_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_WRITEBACK_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_WITHSHIFTS_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_UNPRIV_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_EL1_SWP_frac_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_EL1_PSR_M_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_EL1_SynchPrim_frac_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_EL1_Barrier_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_EL1_SMC_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_EL1_Writeback_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_EL1_WithShifts_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR4_EL1_Unpriv_SHIFT, 4, 0),
ARM64_FTR_END,
};
static const struct arm64_ftr_bits ftr_id_mmfr5[] = {
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR5_ETS_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_MMFR5_EL1_ETS_SHIFT, 4, 0),
ARM64_FTR_END,
};
static const struct arm64_ftr_bits ftr_id_isar6[] = {
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_I8MM_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_BF16_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_SPECRES_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_SB_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_FHM_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_DP_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_JSCVT_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_EL1_I8MM_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_EL1_BF16_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_EL1_SPECRES_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_EL1_SB_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_EL1_FHM_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_EL1_DP_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_ISAR6_EL1_JSCVT_SHIFT, 4, 0),
ARM64_FTR_END,
};
static const struct arm64_ftr_bits ftr_id_pfr0[] = {
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR0_DIT_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_PFR0_CSV2_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR0_STATE3_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR0_STATE2_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR0_STATE1_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR0_STATE0_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR0_EL1_DIT_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_PFR0_EL1_CSV2_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR0_EL1_State3_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR0_EL1_State2_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR0_EL1_State1_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR0_EL1_State0_SHIFT, 4, 0),
ARM64_FTR_END,
};
static const struct arm64_ftr_bits ftr_id_pfr1[] = {
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_GIC_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_VIRT_FRAC_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_SEC_FRAC_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_GENTIMER_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_VIRTUALIZATION_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_MPROGMOD_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_SECURITY_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_PROGMOD_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_EL1_GIC_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_EL1_Virt_frac_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_EL1_Sec_frac_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_EL1_GenTimer_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_EL1_Virtualization_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_EL1_MProgMod_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_EL1_Security_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_PFR1_EL1_ProgMod_SHIFT, 4, 0),
ARM64_FTR_END,
};
static const struct arm64_ftr_bits ftr_id_pfr2[] = {
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_PFR2_SSBS_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_PFR2_CSV3_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_PFR2_EL1_SSBS_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_PFR2_EL1_CSV3_SHIFT, 4, 0),
ARM64_FTR_END,
};
static const struct arm64_ftr_bits ftr_id_dfr0[] = {
/* [31:28] TraceFilt */
- S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_DFR0_PERFMON_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_MPROFDBG_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_MMAPTRC_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_COPTRC_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_MMAPDBG_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_COPSDBG_SHIFT, 4, 0),
- ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_COPDBG_SHIFT, 4, 0),
+ S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_DFR0_EL1_PerfMon_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_MProfDbg_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_MMapTrc_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_CopTrc_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_MMapDbg_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_CopSDbg_SHIFT, 4, 0),
+ ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR0_EL1_CopDbg_SHIFT, 4, 0),
ARM64_FTR_END,
};
static const struct arm64_ftr_bits ftr_id_dfr1[] = {
- S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR1_MTPMU_SHIFT, 4, 0),
+ S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_DFR1_EL1_MTPMU_SHIFT, 4, 0),
ARM64_FTR_END,
};
@@ -1119,12 +1121,12 @@ static int update_32bit_cpu_features(int cpu, struct cpuinfo_32bit *info,
* EL1-dependent register fields to avoid spurious sanity check fails.
*/
if (!id_aa64pfr0_32bit_el1(pfr0)) {
- relax_cpu_ftr_reg(SYS_ID_ISAR4_EL1, ID_ISAR4_SMC_SHIFT);
- relax_cpu_ftr_reg(SYS_ID_PFR1_EL1, ID_PFR1_VIRT_FRAC_SHIFT);
- relax_cpu_ftr_reg(SYS_ID_PFR1_EL1, ID_PFR1_SEC_FRAC_SHIFT);
- relax_cpu_ftr_reg(SYS_ID_PFR1_EL1, ID_PFR1_VIRTUALIZATION_SHIFT);
- relax_cpu_ftr_reg(SYS_ID_PFR1_EL1, ID_PFR1_SECURITY_SHIFT);
- relax_cpu_ftr_reg(SYS_ID_PFR1_EL1, ID_PFR1_PROGMOD_SHIFT);
+ relax_cpu_ftr_reg(SYS_ID_ISAR4_EL1, ID_ISAR4_EL1_SMC_SHIFT);
+ relax_cpu_ftr_reg(SYS_ID_PFR1_EL1, ID_PFR1_EL1_Virt_frac_SHIFT);
+ relax_cpu_ftr_reg(SYS_ID_PFR1_EL1, ID_PFR1_EL1_Sec_frac_SHIFT);
+ relax_cpu_ftr_reg(SYS_ID_PFR1_EL1, ID_PFR1_EL1_Virtualization_SHIFT);
+ relax_cpu_ftr_reg(SYS_ID_PFR1_EL1, ID_PFR1_EL1_Security_SHIFT);
+ relax_cpu_ftr_reg(SYS_ID_PFR1_EL1, ID_PFR1_EL1_ProgMod_SHIFT);
}
taint |= check_update_ftr_reg(SYS_ID_DFR0_EL1, cpu,
@@ -2101,6 +2103,11 @@ static void cpu_trap_el0_impdef(const struct arm64_cpu_capabilities *__unused)
sysreg_clear_set(sctlr_el1, 0, SCTLR_EL1_TIDCP);
}
+static void cpu_enable_dit(const struct arm64_cpu_capabilities *__unused)
+{
+ set_pstate_dit(1);
+}
+
/* Internal helper functions to match cpu capability type */
static bool
cpucap_late_cpu_optional(const struct arm64_cpu_capabilities *cap)
@@ -2664,6 +2671,18 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.matches = has_cpuid_feature,
.cpu_enable = cpu_trap_el0_impdef,
},
+ {
+ .desc = "Data independent timing control (DIT)",
+ .capability = ARM64_HAS_DIT,
+ .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+ .sys_reg = SYS_ID_AA64PFR0_EL1,
+ .sign = FTR_UNSIGNED,
+ .field_pos = ID_AA64PFR0_EL1_DIT_SHIFT,
+ .field_width = 4,
+ .min_field_value = ID_AA64PFR0_EL1_DIT_IMP,
+ .matches = has_cpuid_feature,
+ .cpu_enable = cpu_enable_dit,
+ },
{},
};
@@ -2772,6 +2791,7 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
HWCAP_CAP(SYS_ID_AA64MMFR2_EL1, ID_AA64MMFR2_EL1_AT_SHIFT, 4, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_USCAT),
#ifdef CONFIG_ARM64_SVE
HWCAP_CAP(SYS_ID_AA64PFR0_EL1, ID_AA64PFR0_EL1_SVE_SHIFT, 4, FTR_UNSIGNED, ID_AA64PFR0_EL1_SVE_IMP, CAP_HWCAP, KERNEL_HWCAP_SVE),
+ HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_EL1_SVEver_SHIFT, 4, FTR_UNSIGNED, ID_AA64ZFR0_EL1_SVEver_SVE2p1, CAP_HWCAP, KERNEL_HWCAP_SVE2P1),
HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_EL1_SVEver_SHIFT, 4, FTR_UNSIGNED, ID_AA64ZFR0_EL1_SVEver_SVE2, CAP_HWCAP, KERNEL_HWCAP_SVE2),
HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_EL1_AES_SHIFT, 4, FTR_UNSIGNED, ID_AA64ZFR0_EL1_AES_IMP, CAP_HWCAP, KERNEL_HWCAP_SVEAES),
HWCAP_CAP(SYS_ID_AA64ZFR0_EL1, ID_AA64ZFR0_EL1_AES_SHIFT, 4, FTR_UNSIGNED, ID_AA64ZFR0_EL1_AES_PMULL128, CAP_HWCAP, KERNEL_HWCAP_SVEPMULL),
@@ -2798,6 +2818,8 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = {
#endif /* CONFIG_ARM64_MTE */
HWCAP_CAP(SYS_ID_AA64MMFR0_EL1, ID_AA64MMFR0_EL1_ECV_SHIFT, 4, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_ECV),
HWCAP_CAP(SYS_ID_AA64MMFR1_EL1, ID_AA64MMFR1_EL1_AFP_SHIFT, 4, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_AFP),
+ HWCAP_CAP(SYS_ID_AA64ISAR2_EL1, ID_AA64ISAR2_EL1_CSSC_SHIFT, 4, FTR_UNSIGNED, ID_AA64ISAR2_EL1_CSSC_IMP, CAP_HWCAP, KERNEL_HWCAP_CSSC),
+ HWCAP_CAP(SYS_ID_AA64ISAR2_EL1, ID_AA64ISAR2_EL1_RPRFM_SHIFT, 4, FTR_UNSIGNED, ID_AA64ISAR2_EL1_RPRFM_IMP, CAP_HWCAP, KERNEL_HWCAP_RPRFM),
HWCAP_CAP(SYS_ID_AA64ISAR2_EL1, ID_AA64ISAR2_EL1_RPRES_SHIFT, 4, FTR_UNSIGNED, 1, CAP_HWCAP, KERNEL_HWCAP_RPRES),
HWCAP_CAP(SYS_ID_AA64ISAR2_EL1, ID_AA64ISAR2_EL1_WFxT_SHIFT, 4, FTR_UNSIGNED, ID_AA64ISAR2_EL1_WFxT_IMP, CAP_HWCAP, KERNEL_HWCAP_WFXT),
#ifdef CONFIG_ARM64_SME
@@ -2829,24 +2851,24 @@ static bool compat_has_neon(const struct arm64_cpu_capabilities *cap, int scope)
else
mvfr1 = read_sysreg_s(SYS_MVFR1_EL1);
- return cpuid_feature_extract_unsigned_field(mvfr1, MVFR1_SIMDSP_SHIFT) &&
- cpuid_feature_extract_unsigned_field(mvfr1, MVFR1_SIMDINT_SHIFT) &&
- cpuid_feature_extract_unsigned_field(mvfr1, MVFR1_SIMDLS_SHIFT);
+ return cpuid_feature_extract_unsigned_field(mvfr1, MVFR1_EL1_SIMDSP_SHIFT) &&
+ cpuid_feature_extract_unsigned_field(mvfr1, MVFR1_EL1_SIMDInt_SHIFT) &&
+ cpuid_feature_extract_unsigned_field(mvfr1, MVFR1_EL1_SIMDLS_SHIFT);
}
#endif
static const struct arm64_cpu_capabilities compat_elf_hwcaps[] = {
#ifdef CONFIG_COMPAT
HWCAP_CAP_MATCH(compat_has_neon, CAP_COMPAT_HWCAP, COMPAT_HWCAP_NEON),
- HWCAP_CAP(SYS_MVFR1_EL1, MVFR1_SIMDFMAC_SHIFT, 4, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP, COMPAT_HWCAP_VFPv4),
+ HWCAP_CAP(SYS_MVFR1_EL1, MVFR1_EL1_SIMDFMAC_SHIFT, 4, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP, COMPAT_HWCAP_VFPv4),
/* Arm v8 mandates MVFR0.FPDP == {0, 2}. So, piggy back on this for the presence of VFP support */
- HWCAP_CAP(SYS_MVFR0_EL1, MVFR0_FPDP_SHIFT, 4, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP, COMPAT_HWCAP_VFP),
- HWCAP_CAP(SYS_MVFR0_EL1, MVFR0_FPDP_SHIFT, 4, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP, COMPAT_HWCAP_VFPv3),
- HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, 4, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_PMULL),
- HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_AES_SHIFT, 4, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_AES),
- HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_SHA1_SHIFT, 4, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_SHA1),
- HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_SHA2_SHIFT, 4, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_SHA2),
- HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_CRC32_SHIFT, 4, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_CRC32),
+ HWCAP_CAP(SYS_MVFR0_EL1, MVFR0_EL1_FPDP_SHIFT, 4, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP, COMPAT_HWCAP_VFP),
+ HWCAP_CAP(SYS_MVFR0_EL1, MVFR0_EL1_FPDP_SHIFT, 4, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP, COMPAT_HWCAP_VFPv3),
+ HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_EL1_AES_SHIFT, 4, FTR_UNSIGNED, 2, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_PMULL),
+ HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_EL1_AES_SHIFT, 4, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_AES),
+ HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_EL1_SHA1_SHIFT, 4, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_SHA1),
+ HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_EL1_SHA2_SHIFT, 4, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_SHA2),
+ HWCAP_CAP(SYS_ID_ISAR5_EL1, ID_ISAR5_EL1_CRC32_SHIFT, 4, FTR_UNSIGNED, 1, CAP_COMPAT_HWCAP2, COMPAT_HWCAP2_CRC32),
#endif
{},
};
@@ -3435,35 +3457,22 @@ int do_emulate_mrs(struct pt_regs *regs, u32 sys_reg, u32 rt)
return rc;
}
-static int emulate_mrs(struct pt_regs *regs, u32 insn)
+bool try_emulate_mrs(struct pt_regs *regs, u32 insn)
{
u32 sys_reg, rt;
+ if (compat_user_mode(regs) || !aarch64_insn_is_mrs(insn))
+ return false;
+
/*
* sys_reg values are defined as used in mrs/msr instruction.
* shift the imm value to get the encoding.
*/
sys_reg = (u32)aarch64_insn_decode_immediate(AARCH64_INSN_IMM_16, insn) << 5;
rt = aarch64_insn_decode_register(AARCH64_INSN_REGTYPE_RT, insn);
- return do_emulate_mrs(regs, sys_reg, rt);
+ return do_emulate_mrs(regs, sys_reg, rt) == 0;
}
-static struct undef_hook mrs_hook = {
- .instr_mask = 0xffff0000,
- .instr_val = 0xd5380000,
- .pstate_mask = PSR_AA32_MODE_MASK,
- .pstate_val = PSR_MODE_EL0t,
- .fn = emulate_mrs,
-};
-
-static int __init enable_mrs_emulation(void)
-{
- register_undef_hook(&mrs_hook);
- return 0;
-}
-
-core_initcall(enable_mrs_emulation);
-
enum mitigation_state arm64_get_meltdown_state(void)
{
if (__meltdown_safe)
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 28d4f442b0bc..379695262b77 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -116,6 +116,9 @@ static const char *const hwcap_str[] = {
[KERNEL_HWCAP_WFXT] = "wfxt",
[KERNEL_HWCAP_EBF16] = "ebf16",
[KERNEL_HWCAP_SVE_EBF16] = "sveebf16",
+ [KERNEL_HWCAP_CSSC] = "cssc",
+ [KERNEL_HWCAP_RPRFM] = "rprfm",
+ [KERNEL_HWCAP_SVE2P1] = "sve2p1",
};
#ifdef CONFIG_COMPAT
diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S
deleted file mode 100644
index 61a87fa1c305..000000000000
--- a/arch/arm64/kernel/efi-entry.S
+++ /dev/null
@@ -1,69 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * EFI entry point.
- *
- * Copyright (C) 2013, 2014 Red Hat, Inc.
- * Author: Mark Salter <msalter@redhat.com>
- */
-#include <linux/linkage.h>
-#include <linux/init.h>
-
-#include <asm/assembler.h>
-
- __INIT
-
-SYM_CODE_START(efi_enter_kernel)
- /*
- * efi_pe_entry() will have copied the kernel image if necessary and we
- * end up here with device tree address in x1 and the kernel entry
- * point stored in x0. Save those values in registers which are
- * callee preserved.
- */
- ldr w2, =primary_entry_offset
- add x19, x0, x2 // relocated Image entrypoint
- mov x20, x1 // DTB address
-
- /*
- * Clean the copied Image to the PoC, and ensure it is not shadowed by
- * stale icache entries from before relocation.
- */
- ldr w1, =kernel_size
- add x1, x0, x1
- bl dcache_clean_poc
- ic ialluis
-
- /*
- * Clean the remainder of this routine to the PoC
- * so that we can safely disable the MMU and caches.
- */
- adr x0, 0f
- adr x1, 3f
- bl dcache_clean_poc
-0:
- /* Turn off Dcache and MMU */
- mrs x0, CurrentEL
- cmp x0, #CurrentEL_EL2
- b.ne 1f
- mrs x0, sctlr_el2
- bic x0, x0, #1 << 0 // clear SCTLR.M
- bic x0, x0, #1 << 2 // clear SCTLR.C
- pre_disable_mmu_workaround
- msr sctlr_el2, x0
- isb
- b 2f
-1:
- mrs x0, sctlr_el1
- bic x0, x0, #1 << 0 // clear SCTLR.M
- bic x0, x0, #1 << 2 // clear SCTLR.C
- pre_disable_mmu_workaround
- msr sctlr_el1, x0
- isb
-2:
- /* Jump to kernel entry point */
- mov x0, x20
- mov x1, xzr
- mov x2, xzr
- mov x3, xzr
- br x19
-3:
-SYM_CODE_END(efi_enter_kernel)
diff --git a/arch/arm64/kernel/efi-rt-wrapper.S b/arch/arm64/kernel/efi-rt-wrapper.S
index 75691a2641c1..a00886410537 100644
--- a/arch/arm64/kernel/efi-rt-wrapper.S
+++ b/arch/arm64/kernel/efi-rt-wrapper.S
@@ -6,7 +6,7 @@
#include <linux/linkage.h>
SYM_FUNC_START(__efi_rt_asm_wrapper)
- stp x29, x30, [sp, #-32]!
+ stp x29, x30, [sp, #-112]!
mov x29, sp
/*
@@ -17,6 +17,22 @@ SYM_FUNC_START(__efi_rt_asm_wrapper)
stp x1, x18, [sp, #16]
/*
+ * Preserve all callee saved registers and preserve the stack pointer
+ * value at the base of the EFI runtime stack so we can recover from
+ * synchronous exceptions occurring while executing the firmware
+ * routines.
+ */
+ stp x19, x20, [sp, #32]
+ stp x21, x22, [sp, #48]
+ stp x23, x24, [sp, #64]
+ stp x25, x26, [sp, #80]
+ stp x27, x28, [sp, #96]
+
+ ldr_l x16, efi_rt_stack_top
+ mov sp, x16
+ stp x18, x29, [sp, #-16]!
+
+ /*
* We are lucky enough that no EFI runtime services take more than
* 5 arguments, so all are passed in registers rather than via the
* stack.
@@ -29,9 +45,10 @@ SYM_FUNC_START(__efi_rt_asm_wrapper)
mov x4, x6
blr x8
+ mov sp, x29
ldp x1, x2, [sp, #16]
cmp x2, x18
- ldp x29, x30, [sp], #32
+ ldp x29, x30, [sp], #112
b.ne 0f
ret
0:
@@ -42,6 +59,22 @@ SYM_FUNC_START(__efi_rt_asm_wrapper)
* called with preemption disabled and a separate shadow stack is used
* for interrupts.
*/
- mov x18, x2
+#ifdef CONFIG_SHADOW_CALL_STACK
+ ldr_l x18, efi_rt_stack_top
+ ldr x18, [x18, #-16]
+#endif
+
b efi_handle_corrupted_x18 // tail call
SYM_FUNC_END(__efi_rt_asm_wrapper)
+
+SYM_CODE_START(__efi_rt_asm_recover)
+ mov sp, x30
+
+ ldp x19, x20, [sp, #32]
+ ldp x21, x22, [sp, #48]
+ ldp x23, x24, [sp, #64]
+ ldp x25, x26, [sp, #80]
+ ldp x27, x28, [sp, #96]
+ ldp x29, x30, [sp], #112
+ ret
+SYM_CODE_END(__efi_rt_asm_recover)
diff --git a/arch/arm64/kernel/efi.c b/arch/arm64/kernel/efi.c
index a908a37f0367..fab05de2e12d 100644
--- a/arch/arm64/kernel/efi.c
+++ b/arch/arm64/kernel/efi.c
@@ -144,3 +144,52 @@ asmlinkage efi_status_t efi_handle_corrupted_x18(efi_status_t s, const char *f)
pr_err_ratelimited(FW_BUG "register x18 corrupted by EFI %s\n", f);
return s;
}
+
+DEFINE_SPINLOCK(efi_rt_lock);
+
+asmlinkage u64 *efi_rt_stack_top __ro_after_init;
+
+asmlinkage efi_status_t __efi_rt_asm_recover(void);
+
+bool efi_runtime_fixup_exception(struct pt_regs *regs, const char *msg)
+{
+ /* Check whether the exception occurred while running the firmware */
+ if (current_work() != &efi_rts_work.work || regs->pc >= TASK_SIZE_64)
+ return false;
+
+ pr_err(FW_BUG "Unable to handle %s in EFI runtime service\n", msg);
+ add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
+ clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
+
+ regs->regs[0] = EFI_ABORTED;
+ regs->regs[30] = efi_rt_stack_top[-1];
+ regs->pc = (u64)__efi_rt_asm_recover;
+
+ if (IS_ENABLED(CONFIG_SHADOW_CALL_STACK))
+ regs->regs[18] = efi_rt_stack_top[-2];
+
+ return true;
+}
+
+/* EFI requires 8 KiB of stack space for runtime services */
+static_assert(THREAD_SIZE >= SZ_8K);
+
+static int __init arm64_efi_rt_init(void)
+{
+ void *p;
+
+ if (!efi_enabled(EFI_RUNTIME_SERVICES))
+ return 0;
+
+ p = __vmalloc_node(THREAD_SIZE, THREAD_ALIGN, GFP_KERNEL,
+ NUMA_NO_NODE, &&l);
+l: if (!p) {
+ pr_warn("Failed to allocate EFI runtime stack\n");
+ clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
+ return -ENOMEM;
+ }
+
+ efi_rt_stack_top = p + THREAD_SIZE;
+ return 0;
+}
+core_initcall(arm64_efi_rt_init);
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index 27369fa1c032..cce1167199e3 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -30,7 +30,7 @@
/*
* Handle IRQ/context state management when entering from kernel mode.
* Before this function is called it is not safe to call regular kernel code,
- * intrumentable code, or any code which may trigger an exception.
+ * instrumentable code, or any code which may trigger an exception.
*
* This is intended to match the logic in irqentry_enter(), handling the kernel
* mode transitions only.
@@ -63,7 +63,7 @@ static void noinstr enter_from_kernel_mode(struct pt_regs *regs)
/*
* Handle IRQ/context state management when exiting to kernel mode.
* After this function returns it is not safe to call regular kernel code,
- * intrumentable code, or any code which may trigger an exception.
+ * instrumentable code, or any code which may trigger an exception.
*
* This is intended to match the logic in irqentry_exit(), handling the kernel
* mode transitions only, and with preemption handled elsewhere.
@@ -97,7 +97,7 @@ static void noinstr exit_to_kernel_mode(struct pt_regs *regs)
/*
* Handle IRQ/context state management when entering from user mode.
* Before this function is called it is not safe to call regular kernel code,
- * intrumentable code, or any code which may trigger an exception.
+ * instrumentable code, or any code which may trigger an exception.
*/
static __always_inline void __enter_from_user_mode(void)
{
@@ -116,7 +116,7 @@ static __always_inline void enter_from_user_mode(struct pt_regs *regs)
/*
* Handle IRQ/context state management when exiting to user mode.
* After this function returns it is not safe to call regular kernel code,
- * intrumentable code, or any code which may trigger an exception.
+ * instrumentable code, or any code which may trigger an exception.
*/
static __always_inline void __exit_to_user_mode(void)
{
@@ -152,7 +152,7 @@ asmlinkage void noinstr asm_exit_to_user_mode(struct pt_regs *regs)
/*
* Handle IRQ/context state management when entering an NMI from user/kernel
* mode. Before this function is called it is not safe to call regular kernel
- * code, intrumentable code, or any code which may trigger an exception.
+ * code, instrumentable code, or any code which may trigger an exception.
*/
static void noinstr arm64_enter_nmi(struct pt_regs *regs)
{
@@ -170,7 +170,7 @@ static void noinstr arm64_enter_nmi(struct pt_regs *regs)
/*
* Handle IRQ/context state management when exiting an NMI from user/kernel
* mode. After this function returns it is not safe to call regular kernel
- * code, intrumentable code, or any code which may trigger an exception.
+ * code, instrumentable code, or any code which may trigger an exception.
*/
static void noinstr arm64_exit_nmi(struct pt_regs *regs)
{
@@ -192,7 +192,7 @@ static void noinstr arm64_exit_nmi(struct pt_regs *regs)
/*
* Handle IRQ/context state management when entering a debug exception from
* kernel mode. Before this function is called it is not safe to call regular
- * kernel code, intrumentable code, or any code which may trigger an exception.
+ * kernel code, instrumentable code, or any code which may trigger an exception.
*/
static void noinstr arm64_enter_el1_dbg(struct pt_regs *regs)
{
@@ -207,7 +207,7 @@ static void noinstr arm64_enter_el1_dbg(struct pt_regs *regs)
/*
* Handle IRQ/context state management when exiting a debug exception from
* kernel mode. After this function returns it is not safe to call regular
- * kernel code, intrumentable code, or any code which may trigger an exception.
+ * kernel code, instrumentable code, or any code which may trigger an exception.
*/
static void noinstr arm64_exit_el1_dbg(struct pt_regs *regs)
{
@@ -384,7 +384,7 @@ static void noinstr el1_undef(struct pt_regs *regs, unsigned long esr)
{
enter_from_kernel_mode(regs);
local_daif_inherit(regs);
- do_undefinstr(regs, esr);
+ do_el1_undef(regs, esr);
local_daif_mask();
exit_to_kernel_mode(regs);
}
@@ -570,7 +570,7 @@ static void noinstr el0_sys(struct pt_regs *regs, unsigned long esr)
{
enter_from_user_mode(regs);
local_daif_restore(DAIF_PROCCTX);
- do_sysinstr(esr, regs);
+ do_el0_sys(esr, regs);
exit_to_user_mode(regs);
}
@@ -599,7 +599,7 @@ static void noinstr el0_undef(struct pt_regs *regs, unsigned long esr)
{
enter_from_user_mode(regs);
local_daif_restore(DAIF_PROCCTX);
- do_undefinstr(regs, esr);
+ do_el0_undef(regs, esr);
exit_to_user_mode(regs);
}
@@ -762,7 +762,7 @@ static void noinstr el0_cp15(struct pt_regs *regs, unsigned long esr)
{
enter_from_user_mode(regs);
local_daif_restore(DAIF_PROCCTX);
- do_cp15instr(esr, regs);
+ do_el0_cp15(esr, regs);
exit_to_user_mode(regs);
}
diff --git a/arch/arm64/kernel/entry-ftrace.S b/arch/arm64/kernel/entry-ftrace.S
index 322a831f8ede..3b625f76ffba 100644
--- a/arch/arm64/kernel/entry-ftrace.S
+++ b/arch/arm64/kernel/entry-ftrace.S
@@ -13,83 +13,58 @@
#include <asm/ftrace.h>
#include <asm/insn.h>
-#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
/*
* Due to -fpatchable-function-entry=2, the compiler has placed two NOPs before
* the regular function prologue. For an enabled callsite, ftrace_init_nop() and
* ftrace_make_call() have patched those NOPs to:
*
* MOV X9, LR
- * BL <entry>
- *
- * ... where <entry> is either ftrace_caller or ftrace_regs_caller.
+ * BL ftrace_caller
*
* Each instrumented function follows the AAPCS, so here x0-x8 and x18-x30 are
* live (x18 holds the Shadow Call Stack pointer), and x9-x17 are safe to
* clobber.
*
- * We save the callsite's context into a pt_regs before invoking any ftrace
- * callbacks. So that we can get a sensible backtrace, we create a stack record
- * for the callsite and the ftrace entry assembly. This is not sufficient for
- * reliable stacktrace: until we create the callsite stack record, its caller
- * is missing from the LR and existing chain of frame records.
+ * We save the callsite's context into a struct ftrace_regs before invoking any
+ * ftrace callbacks. So that we can get a sensible backtrace, we create frame
+ * records for the callsite and the ftrace entry assembly. This is not
+ * sufficient for reliable stacktrace: until we create the callsite stack
+ * record, its caller is missing from the LR and existing chain of frame
+ * records.
*/
- .macro ftrace_regs_entry, allregs=0
- /* Make room for pt_regs, plus a callee frame */
- sub sp, sp, #(PT_REGS_SIZE + 16)
-
- /* Save function arguments (and x9 for simplicity) */
- stp x0, x1, [sp, #S_X0]
- stp x2, x3, [sp, #S_X2]
- stp x4, x5, [sp, #S_X4]
- stp x6, x7, [sp, #S_X6]
- stp x8, x9, [sp, #S_X8]
-
- /* Optionally save the callee-saved registers, always save the FP */
- .if \allregs == 1
- stp x10, x11, [sp, #S_X10]
- stp x12, x13, [sp, #S_X12]
- stp x14, x15, [sp, #S_X14]
- stp x16, x17, [sp, #S_X16]
- stp x18, x19, [sp, #S_X18]
- stp x20, x21, [sp, #S_X20]
- stp x22, x23, [sp, #S_X22]
- stp x24, x25, [sp, #S_X24]
- stp x26, x27, [sp, #S_X26]
- stp x28, x29, [sp, #S_X28]
- .else
- str x29, [sp, #S_FP]
- .endif
-
- /* Save the callsite's SP and LR */
- add x10, sp, #(PT_REGS_SIZE + 16)
- stp x9, x10, [sp, #S_LR]
+SYM_CODE_START(ftrace_caller)
+ bti c
- /* Save the PC after the ftrace callsite */
- str x30, [sp, #S_PC]
+ /* Save original SP */
+ mov x10, sp
- /* Create a frame record for the callsite above pt_regs */
- stp x29, x9, [sp, #PT_REGS_SIZE]
- add x29, sp, #PT_REGS_SIZE
+ /* Make room for ftrace regs, plus two frame records */
+ sub sp, sp, #(FREGS_SIZE + 32)
- /* Create our frame record within pt_regs. */
- stp x29, x30, [sp, #S_STACKFRAME]
- add x29, sp, #S_STACKFRAME
- .endm
+ /* Save function arguments */
+ stp x0, x1, [sp, #FREGS_X0]
+ stp x2, x3, [sp, #FREGS_X2]
+ stp x4, x5, [sp, #FREGS_X4]
+ stp x6, x7, [sp, #FREGS_X6]
+ str x8, [sp, #FREGS_X8]
-SYM_CODE_START(ftrace_regs_caller)
- bti c
- ftrace_regs_entry 1
- b ftrace_common
-SYM_CODE_END(ftrace_regs_caller)
+ /* Save the callsite's FP, LR, SP */
+ str x29, [sp, #FREGS_FP]
+ str x9, [sp, #FREGS_LR]
+ str x10, [sp, #FREGS_SP]
-SYM_CODE_START(ftrace_caller)
- bti c
- ftrace_regs_entry 0
- b ftrace_common
-SYM_CODE_END(ftrace_caller)
+ /* Save the PC after the ftrace callsite */
+ str x30, [sp, #FREGS_PC]
+
+ /* Create a frame record for the callsite above the ftrace regs */
+ stp x29, x9, [sp, #FREGS_SIZE + 16]
+ add x29, sp, #FREGS_SIZE + 16
+
+ /* Create our frame record above the ftrace regs */
+ stp x29, x30, [sp, #FREGS_SIZE]
+ add x29, sp, #FREGS_SIZE
-SYM_CODE_START(ftrace_common)
sub x0, x30, #AARCH64_INSN_SIZE // ip (callsite's BL insn)
mov x1, x9 // parent_ip (callsite's LR)
ldr_l x2, function_trace_op // op
@@ -104,24 +79,24 @@ SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL)
* to restore x0-x8, x29, and x30.
*/
/* Restore function arguments */
- ldp x0, x1, [sp]
- ldp x2, x3, [sp, #S_X2]
- ldp x4, x5, [sp, #S_X4]
- ldp x6, x7, [sp, #S_X6]
- ldr x8, [sp, #S_X8]
+ ldp x0, x1, [sp, #FREGS_X0]
+ ldp x2, x3, [sp, #FREGS_X2]
+ ldp x4, x5, [sp, #FREGS_X4]
+ ldp x6, x7, [sp, #FREGS_X6]
+ ldr x8, [sp, #FREGS_X8]
/* Restore the callsite's FP, LR, PC */
- ldr x29, [sp, #S_FP]
- ldr x30, [sp, #S_LR]
- ldr x9, [sp, #S_PC]
+ ldr x29, [sp, #FREGS_FP]
+ ldr x30, [sp, #FREGS_LR]
+ ldr x9, [sp, #FREGS_PC]
/* Restore the callsite's SP */
- add sp, sp, #PT_REGS_SIZE + 16
+ add sp, sp, #FREGS_SIZE + 32
ret x9
-SYM_CODE_END(ftrace_common)
+SYM_CODE_END(ftrace_caller)
-#else /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */
+#else /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */
/*
* Gcc with -pg will put the following code in the beginning of each function:
@@ -195,44 +170,6 @@ SYM_CODE_END(ftrace_common)
add \reg, \reg, #8
.endm
-#ifndef CONFIG_DYNAMIC_FTRACE
-/*
- * void _mcount(unsigned long return_address)
- * @return_address: return address to instrumented function
- *
- * This function makes calls, if enabled, to:
- * - tracer function to probe instrumented function's entry,
- * - ftrace_graph_caller to set up an exit hook
- */
-SYM_FUNC_START(_mcount)
- mcount_enter
-
- ldr_l x2, ftrace_trace_function
- adr x0, ftrace_stub
- cmp x0, x2 // if (ftrace_trace_function
- b.eq skip_ftrace_call // != ftrace_stub) {
-
- mcount_get_pc x0 // function's pc
- mcount_get_lr x1 // function's lr (= parent's pc)
- blr x2 // (*ftrace_trace_function)(pc, lr);
-
-skip_ftrace_call: // }
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
- ldr_l x2, ftrace_graph_return
- cmp x0, x2 // if ((ftrace_graph_return
- b.ne ftrace_graph_caller // != ftrace_stub)
-
- ldr_l x2, ftrace_graph_entry // || (ftrace_graph_entry
- adr_l x0, ftrace_graph_entry_stub // != ftrace_graph_entry_stub))
- cmp x0, x2
- b.ne ftrace_graph_caller // ftrace_graph_caller();
-#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
- mcount_exit
-SYM_FUNC_END(_mcount)
-EXPORT_SYMBOL(_mcount)
-NOKPROBE(_mcount)
-
-#else /* CONFIG_DYNAMIC_FTRACE */
/*
* _mcount() is used to build the kernel with -pg option, but all the branch
* instructions to _mcount() are replaced to NOP initially at kernel start up,
@@ -272,7 +209,6 @@ SYM_INNER_LABEL(ftrace_graph_call, SYM_L_GLOBAL) // ftrace_graph_caller();
mcount_exit
SYM_FUNC_END(ftrace_caller)
-#endif /* CONFIG_DYNAMIC_FTRACE */
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
/*
@@ -293,7 +229,7 @@ SYM_FUNC_START(ftrace_graph_caller)
mcount_exit
SYM_FUNC_END(ftrace_graph_caller)
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
-#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */
+#endif /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */
SYM_TYPED_FUNC_START(ftrace_stub)
ret
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index e28137d64b76..11cb99c4d298 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -197,6 +197,9 @@ alternative_cb_end
.endm
.macro kernel_entry, el, regsize = 64
+ .if \el == 0
+ alternative_insn nop, SET_PSTATE_DIT(1), ARM64_HAS_DIT
+ .endif
.if \regsize == 32
mov w0, w0 // zero upper 32 bits of x0
.endif
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 23834d96d1e7..dcc81e7200d4 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -118,16 +118,8 @@
* returned from the 2nd syscall yet, TIF_FOREIGN_FPSTATE is still set so
* whatever is in the FPSIMD registers is not saved to memory, but discarded.
*/
-struct fpsimd_last_state_struct {
- struct user_fpsimd_state *st;
- void *sve_state;
- void *za_state;
- u64 *svcr;
- unsigned int sve_vl;
- unsigned int sme_vl;
-};
-static DEFINE_PER_CPU(struct fpsimd_last_state_struct, fpsimd_last_state);
+static DEFINE_PER_CPU(struct cpu_fp_state, fpsimd_last_state);
__ro_after_init struct vl_info vl_info[ARM64_VEC_MAX] = {
#ifdef CONFIG_ARM64_SVE
@@ -330,15 +322,6 @@ void task_set_vl_onexec(struct task_struct *task, enum vec_type type,
* The task can execute SVE instructions while in userspace without
* trapping to the kernel.
*
- * When stored, Z0-Z31 (incorporating Vn in bits[127:0] or the
- * corresponding Zn), P0-P15 and FFR are encoded in
- * task->thread.sve_state, formatted appropriately for vector
- * length task->thread.sve_vl or, if SVCR.SM is set,
- * task->thread.sme_vl.
- *
- * task->thread.sve_state must point to a valid buffer at least
- * sve_state_size(task) bytes in size.
- *
* During any syscall, the kernel may optionally clear TIF_SVE and
* discard the vector state except for the FPSIMD subset.
*
@@ -348,7 +331,15 @@ void task_set_vl_onexec(struct task_struct *task, enum vec_type type,
* do_sve_acc() to be called, which does some preparation and then
* sets TIF_SVE.
*
- * When stored, FPSIMD registers V0-V31 are encoded in
+ * During any syscall, the kernel may optionally clear TIF_SVE and
+ * discard the vector state except for the FPSIMD subset.
+ *
+ * The data will be stored in one of two formats:
+ *
+ * * FPSIMD only - FP_STATE_FPSIMD:
+ *
+ * When the FPSIMD only state stored task->thread.fp_type is set to
+ * FP_STATE_FPSIMD, the FPSIMD registers V0-V31 are encoded in
* task->thread.uw.fpsimd_state; bits [max : 128] for each of Z0-Z31 are
* logically zero but not stored anywhere; P0-P15 and FFR are not
* stored and have unspecified values from userspace's point of
@@ -356,7 +347,23 @@ void task_set_vl_onexec(struct task_struct *task, enum vec_type type,
* but userspace is discouraged from relying on this.
*
* task->thread.sve_state does not need to be non-NULL, valid or any
- * particular size: it must not be dereferenced.
+ * particular size: it must not be dereferenced and any data stored
+ * there should be considered stale and not referenced.
+ *
+ * * SVE state - FP_STATE_SVE:
+ *
+ * When the full SVE state is stored task->thread.fp_type is set to
+ * FP_STATE_SVE and Z0-Z31 (incorporating Vn in bits[127:0] or the
+ * corresponding Zn), P0-P15 and FFR are encoded in in
+ * task->thread.sve_state, formatted appropriately for vector
+ * length task->thread.sve_vl or, if SVCR.SM is set,
+ * task->thread.sme_vl. The storage for the vector registers in
+ * task->thread.uw.fpsimd_state should be ignored.
+ *
+ * task->thread.sve_state must point to a valid buffer at least
+ * sve_state_size(task) bytes in size. The data stored in
+ * task->thread.uw.fpsimd_state.vregs should be considered stale
+ * and not referenced.
*
* * FPSR and FPCR are always stored in task->thread.uw.fpsimd_state
* irrespective of whether TIF_SVE is clear or set, since these are
@@ -378,11 +385,37 @@ static void task_fpsimd_load(void)
WARN_ON(!system_supports_fpsimd());
WARN_ON(!have_cpu_fpsimd_context());
- /* Check if we should restore SVE first */
- if (IS_ENABLED(CONFIG_ARM64_SVE) && test_thread_flag(TIF_SVE)) {
- sve_set_vq(sve_vq_from_vl(task_get_sve_vl(current)) - 1);
- restore_sve_regs = true;
- restore_ffr = true;
+ if (system_supports_sve()) {
+ switch (current->thread.fp_type) {
+ case FP_STATE_FPSIMD:
+ /* Stop tracking SVE for this task until next use. */
+ if (test_and_clear_thread_flag(TIF_SVE))
+ sve_user_disable();
+ break;
+ case FP_STATE_SVE:
+ if (!thread_sm_enabled(&current->thread) &&
+ !WARN_ON_ONCE(!test_and_set_thread_flag(TIF_SVE)))
+ sve_user_enable();
+
+ if (test_thread_flag(TIF_SVE))
+ sve_set_vq(sve_vq_from_vl(task_get_sve_vl(current)) - 1);
+
+ restore_sve_regs = true;
+ restore_ffr = true;
+ break;
+ default:
+ /*
+ * This indicates either a bug in
+ * fpsimd_save() or memory corruption, we
+ * should always record an explicit format
+ * when we save. We always at least have the
+ * memory allocated for FPSMID registers so
+ * try that and hope for the best.
+ */
+ WARN_ON_ONCE(1);
+ clear_thread_flag(TIF_SVE);
+ break;
+ }
}
/* Restore SME, override SVE register configuration if needed */
@@ -398,18 +431,19 @@ static void task_fpsimd_load(void)
if (thread_za_enabled(&current->thread))
za_load_state(current->thread.za_state);
- if (thread_sm_enabled(&current->thread)) {
- restore_sve_regs = true;
+ if (thread_sm_enabled(&current->thread))
restore_ffr = system_supports_fa64();
- }
}
- if (restore_sve_regs)
+ if (restore_sve_regs) {
+ WARN_ON_ONCE(current->thread.fp_type != FP_STATE_SVE);
sve_load_state(sve_pffr(&current->thread),
&current->thread.uw.fpsimd_state.fpsr,
restore_ffr);
- else
+ } else {
+ WARN_ON_ONCE(current->thread.fp_type != FP_STATE_FPSIMD);
fpsimd_load_state(&current->thread.uw.fpsimd_state);
+ }
}
/*
@@ -419,12 +453,12 @@ static void task_fpsimd_load(void)
* last, if KVM is involved this may be the guest VM context rather
* than the host thread for the VM pointed to by current. This means
* that we must always reference the state storage via last rather
- * than via current, other than the TIF_ flags which KVM will
- * carefully maintain for us.
+ * than via current, if we are saving KVM state then it will have
+ * ensured that the type of registers to save is set in last->to_save.
*/
static void fpsimd_save(void)
{
- struct fpsimd_last_state_struct const *last =
+ struct cpu_fp_state const *last =
this_cpu_ptr(&fpsimd_last_state);
/* set by fpsimd_bind_task_to_cpu() or fpsimd_bind_state_to_cpu() */
bool save_sve_regs = false;
@@ -437,7 +471,14 @@ static void fpsimd_save(void)
if (test_thread_flag(TIF_FOREIGN_FPSTATE))
return;
- if (test_thread_flag(TIF_SVE)) {
+ /*
+ * If a task is in a syscall the ABI allows us to only
+ * preserve the state shared with FPSIMD so don't bother
+ * saving the full SVE state in that case.
+ */
+ if ((last->to_save == FP_STATE_CURRENT && test_thread_flag(TIF_SVE) &&
+ !in_syscall(current_pt_regs())) ||
+ last->to_save == FP_STATE_SVE) {
save_sve_regs = true;
save_ffr = true;
vl = last->sve_vl;
@@ -474,8 +515,10 @@ static void fpsimd_save(void)
sve_save_state((char *)last->sve_state +
sve_ffr_offset(vl),
&last->st->fpsr, save_ffr);
+ *last->fp_type = FP_STATE_SVE;
} else {
fpsimd_save_state(last->st);
+ *last->fp_type = FP_STATE_FPSIMD;
}
}
@@ -768,8 +811,7 @@ void fpsimd_sync_to_sve(struct task_struct *task)
*/
void sve_sync_to_fpsimd(struct task_struct *task)
{
- if (test_tsk_thread_flag(task, TIF_SVE) ||
- thread_sm_enabled(&task->thread))
+ if (task->thread.fp_type == FP_STATE_SVE)
sve_to_fpsimd(task);
}
@@ -848,8 +890,10 @@ int vec_set_vector_length(struct task_struct *task, enum vec_type type,
fpsimd_flush_task_state(task);
if (test_and_clear_tsk_thread_flag(task, TIF_SVE) ||
- thread_sm_enabled(&task->thread))
+ thread_sm_enabled(&task->thread)) {
sve_to_fpsimd(task);
+ task->thread.fp_type = FP_STATE_FPSIMD;
+ }
if (system_supports_sme() && type == ARM64_VEC_SME) {
task->thread.svcr &= ~(SVCR_SM_MASK |
@@ -1368,6 +1412,7 @@ static void sve_init_regs(void)
fpsimd_bind_task_to_cpu();
} else {
fpsimd_to_sve(current);
+ current->thread.fp_type = FP_STATE_SVE;
}
}
@@ -1596,6 +1641,8 @@ void fpsimd_flush_thread(void)
current->thread.svcr = 0;
}
+ current->thread.fp_type = FP_STATE_FPSIMD;
+
put_cpu_fpsimd_context();
kfree(sve_state);
kfree(za_state);
@@ -1628,14 +1675,38 @@ void fpsimd_signal_preserve_current_state(void)
}
/*
+ * Called by KVM when entering the guest.
+ */
+void fpsimd_kvm_prepare(void)
+{
+ if (!system_supports_sve())
+ return;
+
+ /*
+ * KVM does not save host SVE state since we can only enter
+ * the guest from a syscall so the ABI means that only the
+ * non-saved SVE state needs to be saved. If we have left
+ * SVE enabled for performance reasons then update the task
+ * state to be FPSIMD only.
+ */
+ get_cpu_fpsimd_context();
+
+ if (test_and_clear_thread_flag(TIF_SVE)) {
+ sve_to_fpsimd(current);
+ current->thread.fp_type = FP_STATE_FPSIMD;
+ }
+
+ put_cpu_fpsimd_context();
+}
+
+/*
* Associate current's FPSIMD context with this cpu
* The caller must have ownership of the cpu FPSIMD context before calling
* this function.
*/
static void fpsimd_bind_task_to_cpu(void)
{
- struct fpsimd_last_state_struct *last =
- this_cpu_ptr(&fpsimd_last_state);
+ struct cpu_fp_state *last = this_cpu_ptr(&fpsimd_last_state);
WARN_ON(!system_supports_fpsimd());
last->st = &current->thread.uw.fpsimd_state;
@@ -1644,6 +1715,8 @@ static void fpsimd_bind_task_to_cpu(void)
last->sve_vl = task_get_sve_vl(current);
last->sme_vl = task_get_sme_vl(current);
last->svcr = &current->thread.svcr;
+ last->fp_type = &current->thread.fp_type;
+ last->to_save = FP_STATE_CURRENT;
current->thread.fpsimd_cpu = smp_processor_id();
/*
@@ -1665,22 +1738,14 @@ static void fpsimd_bind_task_to_cpu(void)
}
}
-void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st, void *sve_state,
- unsigned int sve_vl, void *za_state,
- unsigned int sme_vl, u64 *svcr)
+void fpsimd_bind_state_to_cpu(struct cpu_fp_state *state)
{
- struct fpsimd_last_state_struct *last =
- this_cpu_ptr(&fpsimd_last_state);
+ struct cpu_fp_state *last = this_cpu_ptr(&fpsimd_last_state);
WARN_ON(!system_supports_fpsimd());
WARN_ON(!in_softirq() && !irqs_disabled());
- last->st = st;
- last->svcr = svcr;
- last->sve_state = sve_state;
- last->za_state = za_state;
- last->sve_vl = sve_vl;
- last->sme_vl = sme_vl;
+ *last = *state;
}
/*
@@ -1838,7 +1903,7 @@ void kernel_neon_begin(void)
/* Invalidate any task state remaining in the fpsimd regs: */
fpsimd_flush_cpu_state();
}
-EXPORT_SYMBOL(kernel_neon_begin);
+EXPORT_SYMBOL_GPL(kernel_neon_begin);
/*
* kernel_neon_end(): give the CPU FPSIMD registers back to the current task
@@ -1856,7 +1921,7 @@ void kernel_neon_end(void)
put_cpu_fpsimd_context();
}
-EXPORT_SYMBOL(kernel_neon_end);
+EXPORT_SYMBOL_GPL(kernel_neon_end);
#ifdef CONFIG_EFI
diff --git a/arch/arm64/kernel/ftrace.c b/arch/arm64/kernel/ftrace.c
index 8745175f4a75..b30b955a8921 100644
--- a/arch/arm64/kernel/ftrace.c
+++ b/arch/arm64/kernel/ftrace.c
@@ -17,7 +17,49 @@
#include <asm/insn.h>
#include <asm/patching.h>
-#ifdef CONFIG_DYNAMIC_FTRACE
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
+struct fregs_offset {
+ const char *name;
+ int offset;
+};
+
+#define FREGS_OFFSET(n, field) \
+{ \
+ .name = n, \
+ .offset = offsetof(struct ftrace_regs, field), \
+}
+
+static const struct fregs_offset fregs_offsets[] = {
+ FREGS_OFFSET("x0", regs[0]),
+ FREGS_OFFSET("x1", regs[1]),
+ FREGS_OFFSET("x2", regs[2]),
+ FREGS_OFFSET("x3", regs[3]),
+ FREGS_OFFSET("x4", regs[4]),
+ FREGS_OFFSET("x5", regs[5]),
+ FREGS_OFFSET("x6", regs[6]),
+ FREGS_OFFSET("x7", regs[7]),
+ FREGS_OFFSET("x8", regs[8]),
+
+ FREGS_OFFSET("x29", fp),
+ FREGS_OFFSET("x30", lr),
+ FREGS_OFFSET("lr", lr),
+
+ FREGS_OFFSET("sp", sp),
+ FREGS_OFFSET("pc", pc),
+};
+
+int ftrace_regs_query_register_offset(const char *name)
+{
+ for (int i = 0; i < ARRAY_SIZE(fregs_offsets); i++) {
+ const struct fregs_offset *roff = &fregs_offsets[i];
+ if (!strcmp(roff->name, name))
+ return roff->offset;
+ }
+
+ return -EINVAL;
+}
+#endif
+
/*
* Replace a single instruction, which may be a branch or NOP.
* If @validate == true, a replaced instruction is checked against 'old'.
@@ -70,9 +112,6 @@ static struct plt_entry *get_ftrace_plt(struct module *mod, unsigned long addr)
if (addr == FTRACE_ADDR)
return &plt[FTRACE_PLT_IDX];
- if (addr == FTRACE_REGS_ADDR &&
- IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS))
- return &plt[FTRACE_REGS_PLT_IDX];
#endif
return NULL;
}
@@ -154,25 +193,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
return ftrace_modify_code(pc, old, new, true);
}
-#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
-int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
- unsigned long addr)
-{
- unsigned long pc = rec->ip;
- u32 old, new;
-
- if (!ftrace_find_callable_addr(rec, NULL, &old_addr))
- return -EINVAL;
- if (!ftrace_find_callable_addr(rec, NULL, &addr))
- return -EINVAL;
-
- old = aarch64_insn_gen_branch_imm(pc, old_addr,
- AARCH64_INSN_BRANCH_LINK);
- new = aarch64_insn_gen_branch_imm(pc, addr, AARCH64_INSN_BRANCH_LINK);
-
- return ftrace_modify_code(pc, old, new, true);
-}
-
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
/*
* The compiler has inserted two NOPs before the regular function prologue.
* All instrumented functions follow the AAPCS, so x0-x8 and x19-x30 are live,
@@ -228,7 +249,7 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
*
* Note: 'mod' is only set at module load time.
*/
- if (!IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS) &&
+ if (!IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_ARGS) &&
IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) && mod) {
return aarch64_insn_patch_text_nosync((void *)pc, new);
}
@@ -246,7 +267,6 @@ void arch_ftrace_update_code(int command)
command |= FTRACE_MAY_SLEEP;
ftrace_modify_all_code(command);
}
-#endif /* CONFIG_DYNAMIC_FTRACE */
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
/*
@@ -277,21 +297,11 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
}
}
-#ifdef CONFIG_DYNAMIC_FTRACE
-
-#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *op, struct ftrace_regs *fregs)
{
- /*
- * When DYNAMIC_FTRACE_WITH_REGS is selected, `fregs` can never be NULL
- * and arch_ftrace_get_regs(fregs) will always give a non-NULL pt_regs
- * in which we can safely modify the LR.
- */
- struct pt_regs *regs = arch_ftrace_get_regs(fregs);
- unsigned long *parent = (unsigned long *)&procedure_link_pointer(regs);
-
- prepare_ftrace_return(ip, parent, frame_pointer(regs));
+ prepare_ftrace_return(ip, &fregs->lr, fregs->fp);
}
#else
/*
@@ -323,6 +333,5 @@ int ftrace_disable_ftrace_graph_caller(void)
{
return ftrace_modify_graph_caller(false);
}
-#endif /* CONFIG_DYNAMIC_FTRACE_WITH_REGS */
-#endif /* CONFIG_DYNAMIC_FTRACE */
+#endif /* CONFIG_DYNAMIC_FTRACE_WITH_ARGS */
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index 2196aad7b55b..952e17bd1c0b 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -462,6 +462,9 @@ SYM_FUNC_START_LOCAL(__primary_switched)
bl early_fdt_map // Try mapping the FDT early
mov x0, x20 // pass the full boot status
bl init_feature_override // Parse cpu feature overrides
+#ifdef CONFIG_UNWIND_PATCH_PAC_INTO_SCS
+ bl scs_patch_vmlinux
+#endif
mov x0, x20
bl finalise_el2 // Prefer VHE if possible
ldp x29, x30, [sp], #16
diff --git a/arch/arm64/kernel/image-vars.h b/arch/arm64/kernel/image-vars.h
index 8151412653de..f31130ba0233 100644
--- a/arch/arm64/kernel/image-vars.h
+++ b/arch/arm64/kernel/image-vars.h
@@ -10,7 +10,6 @@
#error This file should only be included in vmlinux.lds.S
#endif
-PROVIDE(__efistub_kernel_size = _edata - _text);
PROVIDE(__efistub_primary_entry_offset = primary_entry - _text);
/*
@@ -22,13 +21,6 @@ PROVIDE(__efistub_primary_entry_offset = primary_entry - _text);
* linked at. The routines below are all implemented in assembler in a
* position independent manner
*/
-PROVIDE(__efistub_memcmp = __pi_memcmp);
-PROVIDE(__efistub_memchr = __pi_memchr);
-PROVIDE(__efistub_strlen = __pi_strlen);
-PROVIDE(__efistub_strnlen = __pi_strnlen);
-PROVIDE(__efistub_strcmp = __pi_strcmp);
-PROVIDE(__efistub_strncmp = __pi_strncmp);
-PROVIDE(__efistub_strrchr = __pi_strrchr);
PROVIDE(__efistub_dcache_clean_poc = __pi_dcache_clean_poc);
PROVIDE(__efistub__text = _text);
diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c
index 38dbd3828f13..6ad5c6ef5329 100644
--- a/arch/arm64/kernel/irq.c
+++ b/arch/arm64/kernel/irq.c
@@ -10,20 +10,21 @@
* Copyright (C) 2012 ARM Ltd.
*/
-#include <linux/irq.h>
-#include <linux/memory.h>
-#include <linux/smp.h>
#include <linux/hardirq.h>
#include <linux/init.h>
+#include <linux/irq.h>
#include <linux/irqchip.h>
#include <linux/kprobes.h>
+#include <linux/memory.h>
#include <linux/scs.h>
#include <linux/seq_file.h>
+#include <linux/smp.h>
#include <linux/vmalloc.h>
#include <asm/daifflags.h>
#include <asm/exception.h>
-#include <asm/vmap_stack.h>
#include <asm/softirq_stack.h>
+#include <asm/stacktrace.h>
+#include <asm/vmap_stack.h>
/* Only access this in an NMI enter/exit */
DEFINE_PER_CPU(struct nmi_ctx, nmi_contexts);
@@ -41,7 +42,7 @@ static void init_irq_scs(void)
{
int cpu;
- if (!IS_ENABLED(CONFIG_SHADOW_CALL_STACK))
+ if (!scs_is_enabled())
return;
for_each_possible_cpu(cpu)
diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c
index 76b41e4ca9fa..5af4975caeb5 100644
--- a/arch/arm64/kernel/module.c
+++ b/arch/arm64/kernel/module.c
@@ -15,9 +15,11 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/moduleloader.h>
+#include <linux/scs.h>
#include <linux/vmalloc.h>
#include <asm/alternative.h>
#include <asm/insn.h>
+#include <asm/scs.h>
#include <asm/sections.h>
void *module_alloc(unsigned long size)
@@ -497,9 +499,6 @@ static int module_init_ftrace_plt(const Elf_Ehdr *hdr,
__init_plt(&plts[FTRACE_PLT_IDX], FTRACE_ADDR);
- if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS))
- __init_plt(&plts[FTRACE_REGS_PLT_IDX], FTRACE_REGS_ADDR);
-
mod->arch.ftrace_trampolines = plts;
#endif
return 0;
@@ -514,5 +513,11 @@ int module_finalize(const Elf_Ehdr *hdr,
if (s)
apply_alternatives_module((void *)s->sh_addr, s->sh_size);
+ if (scs_is_dynamic()) {
+ s = find_section(hdr, sechdrs, ".init.eh_frame");
+ if (s)
+ scs_patch((void *)s->sh_addr, s->sh_size);
+ }
+
return module_init_ftrace_plt(hdr, sechdrs, me);
}
diff --git a/arch/arm64/kernel/paravirt.c b/arch/arm64/kernel/paravirt.c
index 57c7c211f8c7..aa718d6a9274 100644
--- a/arch/arm64/kernel/paravirt.c
+++ b/arch/arm64/kernel/paravirt.c
@@ -141,10 +141,6 @@ static bool __init has_pv_steal_clock(void)
{
struct arm_smccc_res res;
- /* To detect the presence of PV time support we require SMCCC 1.1+ */
- if (arm_smccc_1_1_get_conduit() == SMCCC_CONDUIT_NONE)
- return false;
-
arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
ARM_SMCCC_HV_PV_TIME_FEATURES, &res);
diff --git a/arch/arm64/kernel/patch-scs.c b/arch/arm64/kernel/patch-scs.c
new file mode 100644
index 000000000000..1b3da02d5b74
--- /dev/null
+++ b/arch/arm64/kernel/patch-scs.c
@@ -0,0 +1,257 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2022 - Google LLC
+ * Author: Ard Biesheuvel <ardb@google.com>
+ */
+
+#include <linux/bug.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <linux/printk.h>
+#include <linux/types.h>
+
+#include <asm/cacheflush.h>
+#include <asm/scs.h>
+
+//
+// This minimal DWARF CFI parser is partially based on the code in
+// arch/arc/kernel/unwind.c, and on the document below:
+// https://refspecs.linuxbase.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
+//
+
+#define DW_CFA_nop 0x00
+#define DW_CFA_set_loc 0x01
+#define DW_CFA_advance_loc1 0x02
+#define DW_CFA_advance_loc2 0x03
+#define DW_CFA_advance_loc4 0x04
+#define DW_CFA_offset_extended 0x05
+#define DW_CFA_restore_extended 0x06
+#define DW_CFA_undefined 0x07
+#define DW_CFA_same_value 0x08
+#define DW_CFA_register 0x09
+#define DW_CFA_remember_state 0x0a
+#define DW_CFA_restore_state 0x0b
+#define DW_CFA_def_cfa 0x0c
+#define DW_CFA_def_cfa_register 0x0d
+#define DW_CFA_def_cfa_offset 0x0e
+#define DW_CFA_def_cfa_expression 0x0f
+#define DW_CFA_expression 0x10
+#define DW_CFA_offset_extended_sf 0x11
+#define DW_CFA_def_cfa_sf 0x12
+#define DW_CFA_def_cfa_offset_sf 0x13
+#define DW_CFA_val_offset 0x14
+#define DW_CFA_val_offset_sf 0x15
+#define DW_CFA_val_expression 0x16
+#define DW_CFA_lo_user 0x1c
+#define DW_CFA_negate_ra_state 0x2d
+#define DW_CFA_GNU_args_size 0x2e
+#define DW_CFA_GNU_negative_offset_extended 0x2f
+#define DW_CFA_hi_user 0x3f
+
+extern const u8 __eh_frame_start[], __eh_frame_end[];
+
+enum {
+ PACIASP = 0xd503233f,
+ AUTIASP = 0xd50323bf,
+ SCS_PUSH = 0xf800865e,
+ SCS_POP = 0xf85f8e5e,
+};
+
+static void __always_inline scs_patch_loc(u64 loc)
+{
+ u32 insn = le32_to_cpup((void *)loc);
+
+ switch (insn) {
+ case PACIASP:
+ *(u32 *)loc = cpu_to_le32(SCS_PUSH);
+ break;
+ case AUTIASP:
+ *(u32 *)loc = cpu_to_le32(SCS_POP);
+ break;
+ default:
+ /*
+ * While the DW_CFA_negate_ra_state directive is guaranteed to
+ * appear right after a PACIASP/AUTIASP instruction, it may
+ * also appear after a DW_CFA_restore_state directive that
+ * restores a state that is only partially accurate, and is
+ * followed by DW_CFA_negate_ra_state directive to toggle the
+ * PAC bit again. So we permit other instructions here, and ignore
+ * them.
+ */
+ return;
+ }
+ dcache_clean_pou(loc, loc + sizeof(u32));
+}
+
+/*
+ * Skip one uleb128/sleb128 encoded quantity from the opcode stream. All bytes
+ * except the last one have bit #7 set.
+ */
+static int __always_inline skip_xleb128(const u8 **opcode, int size)
+{
+ u8 c;
+
+ do {
+ c = *(*opcode)++;
+ size--;
+ } while (c & BIT(7));
+
+ return size;
+}
+
+struct eh_frame {
+ /*
+ * The size of this frame if 0 < size < U32_MAX, 0 terminates the list.
+ */
+ u32 size;
+
+ /*
+ * The first frame is a Common Information Entry (CIE) frame, followed
+ * by one or more Frame Description Entry (FDE) frames. In the former
+ * case, this field is 0, otherwise it is the negated offset relative
+ * to the associated CIE frame.
+ */
+ u32 cie_id_or_pointer;
+
+ union {
+ struct { // CIE
+ u8 version;
+ u8 augmentation_string[];
+ };
+
+ struct { // FDE
+ s32 initial_loc;
+ s32 range;
+ u8 opcodes[];
+ };
+ };
+};
+
+static int noinstr scs_handle_fde_frame(const struct eh_frame *frame,
+ bool fde_has_augmentation_data,
+ int code_alignment_factor)
+{
+ int size = frame->size - offsetof(struct eh_frame, opcodes) + 4;
+ u64 loc = (u64)offset_to_ptr(&frame->initial_loc);
+ const u8 *opcode = frame->opcodes;
+
+ if (fde_has_augmentation_data) {
+ int l;
+
+ // assume single byte uleb128_t
+ if (WARN_ON(*opcode & BIT(7)))
+ return -ENOEXEC;
+
+ l = *opcode++;
+ opcode += l;
+ size -= l + 1;
+ }
+
+ /*
+ * Starting from 'loc', apply the CFA opcodes that advance the location
+ * pointer, and identify the locations of the PAC instructions.
+ */
+ while (size-- > 0) {
+ switch (*opcode++) {
+ case DW_CFA_nop:
+ case DW_CFA_remember_state:
+ case DW_CFA_restore_state:
+ break;
+
+ case DW_CFA_advance_loc1:
+ loc += *opcode++ * code_alignment_factor;
+ size--;
+ break;
+
+ case DW_CFA_advance_loc2:
+ loc += *opcode++ * code_alignment_factor;
+ loc += (*opcode++ << 8) * code_alignment_factor;
+ size -= 2;
+ break;
+
+ case DW_CFA_def_cfa:
+ case DW_CFA_offset_extended:
+ size = skip_xleb128(&opcode, size);
+ fallthrough;
+ case DW_CFA_def_cfa_offset:
+ case DW_CFA_def_cfa_offset_sf:
+ case DW_CFA_def_cfa_register:
+ case DW_CFA_same_value:
+ case DW_CFA_restore_extended:
+ case 0x80 ... 0xbf:
+ size = skip_xleb128(&opcode, size);
+ break;
+
+ case DW_CFA_negate_ra_state:
+ scs_patch_loc(loc - 4);
+ break;
+
+ case 0x40 ... 0x7f:
+ // advance loc
+ loc += (opcode[-1] & 0x3f) * code_alignment_factor;
+ break;
+
+ case 0xc0 ... 0xff:
+ break;
+
+ default:
+ pr_err("unhandled opcode: %02x in FDE frame %lx\n", opcode[-1], (uintptr_t)frame);
+ return -ENOEXEC;
+ }
+ }
+ return 0;
+}
+
+int noinstr scs_patch(const u8 eh_frame[], int size)
+{
+ const u8 *p = eh_frame;
+
+ while (size > 4) {
+ const struct eh_frame *frame = (const void *)p;
+ bool fde_has_augmentation_data = true;
+ int code_alignment_factor = 1;
+ int ret;
+
+ if (frame->size == 0 ||
+ frame->size == U32_MAX ||
+ frame->size > size)
+ break;
+
+ if (frame->cie_id_or_pointer == 0) {
+ const u8 *p = frame->augmentation_string;
+
+ /* a 'z' in the augmentation string must come first */
+ fde_has_augmentation_data = *p == 'z';
+
+ /*
+ * The code alignment factor is a uleb128 encoded field
+ * but given that the only sensible values are 1 or 4,
+ * there is no point in decoding the whole thing.
+ */
+ p += strlen(p) + 1;
+ if (!WARN_ON(*p & BIT(7)))
+ code_alignment_factor = *p;
+ } else {
+ ret = scs_handle_fde_frame(frame,
+ fde_has_augmentation_data,
+ code_alignment_factor);
+ if (ret)
+ return ret;
+ }
+
+ p += sizeof(frame->size) + frame->size;
+ size -= sizeof(frame->size) + frame->size;
+ }
+ return 0;
+}
+
+asmlinkage void __init scs_patch_vmlinux(void)
+{
+ if (!should_patch_pac_into_scs())
+ return;
+
+ WARN_ON(scs_patch(__eh_frame_start, __eh_frame_end - __eh_frame_start));
+ icache_inval_all_pou();
+ isb();
+}
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index 7b0643fe2f13..a5193f2146a6 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -806,10 +806,14 @@ static void armv8pmu_disable_event(struct perf_event *event)
static void armv8pmu_start(struct arm_pmu *cpu_pmu)
{
- struct perf_event_context *task_ctx =
- this_cpu_ptr(cpu_pmu->pmu.pmu_cpu_context)->task_ctx;
+ struct perf_event_context *ctx;
+ int nr_user = 0;
- if (sysctl_perf_user_access && task_ctx && task_ctx->nr_user)
+ ctx = perf_cpu_task_ctx();
+ if (ctx)
+ nr_user = ctx->nr_user;
+
+ if (sysctl_perf_user_access && nr_user)
armv8pmu_enable_user_access(cpu_pmu);
else
armv8pmu_disable_user_access();
@@ -1019,10 +1023,10 @@ static int armv8pmu_set_event_filter(struct hw_perf_event *event,
return 0;
}
-static int armv8pmu_filter_match(struct perf_event *event)
+static bool armv8pmu_filter(struct pmu *pmu, int cpu)
{
- unsigned long evtype = event->hw.config_base & ARMV8_PMU_EVTYPE_EVENT;
- return evtype != ARMV8_PMUV3_PERFCTR_CHAIN;
+ struct arm_pmu *armpmu = to_arm_pmu(pmu);
+ return !cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus);
}
static void armv8pmu_reset(void *info)
@@ -1146,7 +1150,8 @@ static void __armv8pmu_probe_pmu(void *info)
dfr0 = read_sysreg(id_aa64dfr0_el1);
pmuver = cpuid_feature_extract_unsigned_field(dfr0,
ID_AA64DFR0_EL1_PMUVer_SHIFT);
- if (pmuver == ID_AA64DFR0_EL1_PMUVer_IMP_DEF || pmuver == 0)
+ if (pmuver == ID_AA64DFR0_EL1_PMUVer_IMP_DEF ||
+ pmuver == ID_AA64DFR0_EL1_PMUVer_NI)
return;
cpu_pmu->pmuver = pmuver;
@@ -1253,7 +1258,7 @@ static int armv8_pmu_init(struct arm_pmu *cpu_pmu, char *name,
cpu_pmu->stop = armv8pmu_stop;
cpu_pmu->reset = armv8pmu_reset;
cpu_pmu->set_event_filter = armv8pmu_set_event_filter;
- cpu_pmu->filter_match = armv8pmu_filter_match;
+ cpu_pmu->filter = armv8pmu_filter;
cpu_pmu->pmu.event_idx = armv8pmu_user_event_idx;
diff --git a/arch/arm64/kernel/pi/Makefile b/arch/arm64/kernel/pi/Makefile
index 839291430cb3..4c0ea3cd4ea4 100644
--- a/arch/arm64/kernel/pi/Makefile
+++ b/arch/arm64/kernel/pi/Makefile
@@ -7,6 +7,7 @@ KBUILD_CFLAGS := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) -fpie \
-I$(srctree)/scripts/dtc/libfdt -fno-stack-protector \
-include $(srctree)/include/linux/hidden.h \
-D__DISABLE_EXPORTS -ffreestanding -D__NO_FORTIFY \
+ -fno-asynchronous-unwind-tables -fno-unwind-tables \
$(call cc-option,-fno-addrsig)
# remove SCS flags from all objects in this directory
diff --git a/arch/arm64/kernel/probes/decode-insn.c b/arch/arm64/kernel/probes/decode-insn.c
index 104101f633b1..968d5fffe233 100644
--- a/arch/arm64/kernel/probes/decode-insn.c
+++ b/arch/arm64/kernel/probes/decode-insn.c
@@ -24,7 +24,7 @@ static bool __kprobes aarch64_insn_is_steppable(u32 insn)
* currently safe. Lastly, MSR instructions can do any number of nasty
* things we can't handle during single-stepping.
*/
- if (aarch64_get_insn_class(insn) == AARCH64_INSN_CLS_BR_SYS) {
+ if (aarch64_insn_is_class_branch_sys(insn)) {
if (aarch64_insn_is_branch(insn) ||
aarch64_insn_is_msr_imm(insn) ||
aarch64_insn_is_msr_reg(insn) ||
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index c9e4d0720285..f35d059a9a36 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -294,19 +294,12 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
}
break;
- case KPROBE_HIT_ACTIVE:
- case KPROBE_HIT_SSDONE:
- /*
- * In case the user-specified fault handler returned
- * zero, try to fix up.
- */
- if (fixup_exception(regs))
- return 1;
}
return 0;
}
-static void __kprobes kprobe_handler(struct pt_regs *regs)
+static int __kprobes
+kprobe_breakpoint_handler(struct pt_regs *regs, unsigned long esr)
{
struct kprobe *p, *cur_kprobe;
struct kprobe_ctlblk *kcb;
@@ -316,39 +309,44 @@ static void __kprobes kprobe_handler(struct pt_regs *regs)
cur_kprobe = kprobe_running();
p = get_kprobe((kprobe_opcode_t *) addr);
+ if (WARN_ON_ONCE(!p)) {
+ /*
+ * Something went wrong. This BRK used an immediate reserved
+ * for kprobes, but we couldn't find any corresponding probe.
+ */
+ return DBG_HOOK_ERROR;
+ }
- if (p) {
- if (cur_kprobe) {
- if (reenter_kprobe(p, regs, kcb))
- return;
- } else {
- /* Probe hit */
- set_current_kprobe(p);
- kcb->kprobe_status = KPROBE_HIT_ACTIVE;
-
- /*
- * If we have no pre-handler or it returned 0, we
- * continue with normal processing. If we have a
- * pre-handler and it returned non-zero, it will
- * modify the execution path and no need to single
- * stepping. Let's just reset current kprobe and exit.
- */
- if (!p->pre_handler || !p->pre_handler(p, regs)) {
- setup_singlestep(p, regs, kcb, 0);
- } else
- reset_current_kprobe();
- }
+ if (cur_kprobe) {
+ /* Hit a kprobe inside another kprobe */
+ if (!reenter_kprobe(p, regs, kcb))
+ return DBG_HOOK_ERROR;
+ } else {
+ /* Probe hit */
+ set_current_kprobe(p);
+ kcb->kprobe_status = KPROBE_HIT_ACTIVE;
+
+ /*
+ * If we have no pre-handler or it returned 0, we
+ * continue with normal processing. If we have a
+ * pre-handler and it returned non-zero, it will
+ * modify the execution path and not need to single-step
+ * Let's just reset current kprobe and exit.
+ */
+ if (!p->pre_handler || !p->pre_handler(p, regs))
+ setup_singlestep(p, regs, kcb, 0);
+ else
+ reset_current_kprobe();
}
- /*
- * The breakpoint instruction was removed right
- * after we hit it. Another cpu has removed
- * either a probepoint or a debugger breakpoint
- * at this address. In either case, no further
- * handling of this interrupt is appropriate.
- * Return back to original instruction, and continue.
- */
+
+ return DBG_HOOK_HANDLED;
}
+static struct break_hook kprobes_break_hook = {
+ .imm = KPROBES_BRK_IMM,
+ .fn = kprobe_breakpoint_handler,
+};
+
static int __kprobes
kprobe_breakpoint_ss_handler(struct pt_regs *regs, unsigned long esr)
{
@@ -373,18 +371,6 @@ static struct break_hook kprobes_break_ss_hook = {
.fn = kprobe_breakpoint_ss_handler,
};
-static int __kprobes
-kprobe_breakpoint_handler(struct pt_regs *regs, unsigned long esr)
-{
- kprobe_handler(regs);
- return DBG_HOOK_HANDLED;
-}
-
-static struct break_hook kprobes_break_hook = {
- .imm = KPROBES_BRK_IMM,
- .fn = kprobe_breakpoint_handler,
-};
-
/*
* Provide a blacklist of symbols identifying ranges which cannot be kprobed.
* This blacklist is exposed to userspace via debugfs (kprobes/blacklist).
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 044a7d7f1f6a..269ac1c25ae2 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -331,6 +331,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
clear_tsk_thread_flag(dst, TIF_SME);
}
+ dst->thread.fp_type = FP_STATE_FPSIMD;
+
/* clear any pending asynchronous tag fault raised by the parent */
clear_tsk_thread_flag(dst, TIF_MTE_ASYNC_FAULT);
@@ -591,7 +593,7 @@ unsigned long __get_wchan(struct task_struct *p)
unsigned long arch_align_stack(unsigned long sp)
{
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
- sp -= prandom_u32_max(PAGE_SIZE);
+ sp -= get_random_u32_below(PAGE_SIZE);
return sp & ~0xf;
}
diff --git a/arch/arm64/kernel/proton-pack.c b/arch/arm64/kernel/proton-pack.c
index bfce41c2a53b..fca9cc6f5581 100644
--- a/arch/arm64/kernel/proton-pack.c
+++ b/arch/arm64/kernel/proton-pack.c
@@ -521,10 +521,13 @@ bool has_spectre_v4(const struct arm64_cpu_capabilities *cap, int scope)
return state != SPECTRE_UNAFFECTED;
}
-static int ssbs_emulation_handler(struct pt_regs *regs, u32 instr)
+bool try_emulate_el1_ssbs(struct pt_regs *regs, u32 instr)
{
- if (user_mode(regs))
- return 1;
+ const u32 instr_mask = ~(1U << PSTATE_Imm_shift);
+ const u32 instr_val = 0xd500401f | PSTATE_SSBS;
+
+ if ((instr & instr_mask) != instr_val)
+ return false;
if (instr & BIT(PSTATE_Imm_shift))
regs->pstate |= PSR_SSBS_BIT;
@@ -532,19 +535,11 @@ static int ssbs_emulation_handler(struct pt_regs *regs, u32 instr)
regs->pstate &= ~PSR_SSBS_BIT;
arm64_skip_faulting_instruction(regs, 4);
- return 0;
+ return true;
}
-static struct undef_hook ssbs_emulation_hook = {
- .instr_mask = ~(1U << PSTATE_Imm_shift),
- .instr_val = 0xd500401f | PSTATE_SSBS,
- .fn = ssbs_emulation_handler,
-};
-
static enum mitigation_state spectre_v4_enable_hw_mitigation(void)
{
- static bool undef_hook_registered = false;
- static DEFINE_RAW_SPINLOCK(hook_lock);
enum mitigation_state state;
/*
@@ -555,13 +550,6 @@ static enum mitigation_state spectre_v4_enable_hw_mitigation(void)
if (state != SPECTRE_MITIGATED || !this_cpu_has_cap(ARM64_SSBS))
return state;
- raw_spin_lock(&hook_lock);
- if (!undef_hook_registered) {
- register_undef_hook(&ssbs_emulation_hook);
- undef_hook_registered = true;
- }
- raw_spin_unlock(&hook_lock);
-
if (spectre_v4_mitigations_off()) {
sysreg_clear_set(sctlr_el1, 0, SCTLR_ELx_DSSBS);
set_pstate_ssbs(1);
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index c2fb5755bbec..2686ab157601 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -514,9 +514,7 @@ static int hw_break_set(struct task_struct *target,
/* Resource info and pad */
offset = offsetof(struct user_hwdebug_state, dbg_regs);
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, offset);
- if (ret)
- return ret;
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, offset);
/* (address, ctrl) registers */
limit = regset->n * regset->size;
@@ -543,11 +541,8 @@ static int hw_break_set(struct task_struct *target,
return ret;
offset += PTRACE_HBP_CTRL_SZ;
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- offset,
- offset + PTRACE_HBP_PAD_SZ);
- if (ret)
- return ret;
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ offset, offset + PTRACE_HBP_PAD_SZ);
offset += PTRACE_HBP_PAD_SZ;
idx++;
}
@@ -907,8 +902,7 @@ static int sve_set_common(struct task_struct *target,
ret = __fpr_set(target, regset, pos, count, kbuf, ubuf,
SVE_PT_FPSIMD_OFFSET);
clear_tsk_thread_flag(target, TIF_SVE);
- if (type == ARM64_VEC_SME)
- fpsimd_force_sync_to_sve(target);
+ target->thread.fp_type = FP_STATE_FPSIMD;
goto out;
}
@@ -931,6 +925,7 @@ static int sve_set_common(struct task_struct *target,
if (!target->thread.sve_state) {
ret = -ENOMEM;
clear_tsk_thread_flag(target, TIF_SVE);
+ target->thread.fp_type = FP_STATE_FPSIMD;
goto out;
}
@@ -942,6 +937,7 @@ static int sve_set_common(struct task_struct *target,
*/
fpsimd_sync_to_sve(target);
set_tsk_thread_flag(target, TIF_SVE);
+ target->thread.fp_type = FP_STATE_SVE;
BUILD_BUG_ON(SVE_PT_SVE_OFFSET != sizeof(header));
start = SVE_PT_SVE_OFFSET;
@@ -954,10 +950,7 @@ static int sve_set_common(struct task_struct *target,
start = end;
end = SVE_PT_SVE_FPSR_OFFSET(vq);
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- start, end);
- if (ret)
- goto out;
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, start, end);
/*
* Copy fpsr, and fpcr which must follow contiguously in
diff --git a/arch/arm64/kernel/sdei.c b/arch/arm64/kernel/sdei.c
index d56e170e1ca7..830be01af32d 100644
--- a/arch/arm64/kernel/sdei.c
+++ b/arch/arm64/kernel/sdei.c
@@ -144,7 +144,7 @@ static int init_sdei_scs(void)
int cpu;
int err = 0;
- if (!IS_ENABLED(CONFIG_SHADOW_CALL_STACK))
+ if (!scs_is_enabled())
return 0;
for_each_possible_cpu(cpu) {
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index fea3223704b6..12cfe9d0d3fa 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -30,6 +30,7 @@
#include <linux/efi.h>
#include <linux/psci.h>
#include <linux/sched/task.h>
+#include <linux/scs.h>
#include <linux/mm.h>
#include <asm/acpi.h>
@@ -42,6 +43,7 @@
#include <asm/cpu_ops.h>
#include <asm/kasan.h>
#include <asm/numa.h>
+#include <asm/scs.h>
#include <asm/sections.h>
#include <asm/setup.h>
#include <asm/smp_plat.h>
@@ -312,6 +314,8 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p)
jump_label_init();
parse_early_param();
+ dynamic_scs_init();
+
/*
* Unmask asynchronous aborts and fiq after bringing up possible
* earlycon. (Report possible System Errors once we can report this
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 9ad911f1647c..e0d09bf5b01b 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -207,6 +207,7 @@ static int restore_fpsimd_context(struct fpsimd_context __user *ctx)
__get_user_error(fpsimd.fpcr, &ctx->fpcr, err);
clear_thread_flag(TIF_SVE);
+ current->thread.fp_type = FP_STATE_FPSIMD;
/* load the hardware registers from the fpsimd_state structure */
if (!err)
@@ -292,6 +293,7 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
if (sve.head.size <= sizeof(*user->sve)) {
clear_thread_flag(TIF_SVE);
current->thread.svcr &= ~SVCR_SM_MASK;
+ current->thread.fp_type = FP_STATE_FPSIMD;
goto fpsimd_only;
}
@@ -327,6 +329,7 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
current->thread.svcr |= SVCR_SM_MASK;
else
set_thread_flag(TIF_SVE);
+ current->thread.fp_type = FP_STATE_SVE;
fpsimd_only:
/* copy the FP and status/control registers */
@@ -932,9 +935,11 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
* FPSIMD register state - flush the saved FPSIMD
* register state in case it gets loaded.
*/
- if (current->thread.svcr & SVCR_SM_MASK)
+ if (current->thread.svcr & SVCR_SM_MASK) {
memset(&current->thread.uw.fpsimd_state, 0,
sizeof(current->thread.uw.fpsimd_state));
+ current->thread.fp_type = FP_STATE_FPSIMD;
+ }
current->thread.svcr &= ~(SVCR_ZA_MASK |
SVCR_SM_MASK);
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index 634279b3b03d..117e2c180f3c 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -23,8 +23,8 @@
*
* The regs must be on a stack currently owned by the calling task.
*/
-static inline void unwind_init_from_regs(struct unwind_state *state,
- struct pt_regs *regs)
+static __always_inline void unwind_init_from_regs(struct unwind_state *state,
+ struct pt_regs *regs)
{
unwind_init_common(state, current);
@@ -58,8 +58,8 @@ static __always_inline void unwind_init_from_caller(struct unwind_state *state)
* duration of the unwind, or the unwind will be bogus. It is never valid to
* call this for the current task.
*/
-static inline void unwind_init_from_task(struct unwind_state *state,
- struct task_struct *task)
+static __always_inline void unwind_init_from_task(struct unwind_state *state,
+ struct task_struct *task)
{
unwind_init_common(state, task);
@@ -186,7 +186,7 @@ void show_stack(struct task_struct *tsk, unsigned long *sp, const char *loglvl)
: stackinfo_get_unknown(); \
})
-noinline notrace void arch_stack_walk(stack_trace_consume_fn consume_entry,
+noinline noinstr void arch_stack_walk(stack_trace_consume_fn consume_entry,
void *cookie, struct task_struct *task,
struct pt_regs *regs)
{
diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c
index 8b02d310838f..e7163f31f716 100644
--- a/arch/arm64/kernel/suspend.c
+++ b/arch/arm64/kernel/suspend.c
@@ -60,6 +60,8 @@ void notrace __cpu_suspend_exit(void)
* PSTATE was not saved over suspend/resume, re-enable any detected
* features that might not have been set correctly.
*/
+ if (cpus_have_const_cap(ARM64_HAS_DIT))
+ set_pstate_dit(1);
__uaccess_enable_hw_pan();
/*
diff --git a/arch/arm64/kernel/syscall.c b/arch/arm64/kernel/syscall.c
index d72e8f23422d..a5de47e3df2b 100644
--- a/arch/arm64/kernel/syscall.c
+++ b/arch/arm64/kernel/syscall.c
@@ -183,21 +183,12 @@ static inline void fp_user_discard(void)
if (!system_supports_sve())
return;
- /*
- * If SME is not active then disable SVE, the registers will
- * be cleared when userspace next attempts to access them and
- * we do not need to track the SVE register state until then.
- */
- clear_thread_flag(TIF_SVE);
+ if (test_thread_flag(TIF_SVE)) {
+ unsigned int sve_vq_minus_one;
- /*
- * task_fpsimd_load() won't be called to update CPACR_EL1 in
- * ret_to_user unless TIF_FOREIGN_FPSTATE is still set, which only
- * happens if a context switch or kernel_neon_begin() or context
- * modification (sigreturn, ptrace) intervenes.
- * So, ensure that CPACR_EL1 is already correct for the fast-path case.
- */
- sve_user_disable();
+ sve_vq_minus_one = sve_vq_from_vl(task_get_sve_vl(current)) - 1;
+ sve_flush_live(true, sve_vq_minus_one);
+ }
}
void do_el0_svc(struct pt_regs *regs)
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 23d281ed7621..4c0caa589e12 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -373,51 +373,22 @@ void arm64_skip_faulting_instruction(struct pt_regs *regs, unsigned long size)
regs->pstate &= ~PSR_BTYPE_MASK;
}
-static LIST_HEAD(undef_hook);
-static DEFINE_RAW_SPINLOCK(undef_lock);
-
-void register_undef_hook(struct undef_hook *hook)
+static int user_insn_read(struct pt_regs *regs, u32 *insnp)
{
- unsigned long flags;
-
- raw_spin_lock_irqsave(&undef_lock, flags);
- list_add(&hook->node, &undef_hook);
- raw_spin_unlock_irqrestore(&undef_lock, flags);
-}
-
-void unregister_undef_hook(struct undef_hook *hook)
-{
- unsigned long flags;
-
- raw_spin_lock_irqsave(&undef_lock, flags);
- list_del(&hook->node);
- raw_spin_unlock_irqrestore(&undef_lock, flags);
-}
-
-static int call_undef_hook(struct pt_regs *regs)
-{
- struct undef_hook *hook;
- unsigned long flags;
u32 instr;
- int (*fn)(struct pt_regs *regs, u32 instr) = NULL;
unsigned long pc = instruction_pointer(regs);
- if (!user_mode(regs)) {
- __le32 instr_le;
- if (get_kernel_nofault(instr_le, (__le32 *)pc))
- goto exit;
- instr = le32_to_cpu(instr_le);
- } else if (compat_thumb_mode(regs)) {
+ if (compat_thumb_mode(regs)) {
/* 16-bit Thumb instruction */
__le16 instr_le;
if (get_user(instr_le, (__le16 __user *)pc))
- goto exit;
+ return -EFAULT;
instr = le16_to_cpu(instr_le);
if (aarch32_insn_is_wide(instr)) {
u32 instr2;
if (get_user(instr_le, (__le16 __user *)(pc + 2)))
- goto exit;
+ return -EFAULT;
instr2 = le16_to_cpu(instr_le);
instr = (instr << 16) | instr2;
}
@@ -425,19 +396,12 @@ static int call_undef_hook(struct pt_regs *regs)
/* 32-bit ARM instruction */
__le32 instr_le;
if (get_user(instr_le, (__le32 __user *)pc))
- goto exit;
+ return -EFAULT;
instr = le32_to_cpu(instr_le);
}
- raw_spin_lock_irqsave(&undef_lock, flags);
- list_for_each_entry(hook, &undef_hook, node)
- if ((instr & hook->instr_mask) == hook->instr_val &&
- (regs->pstate & hook->pstate_mask) == hook->pstate_val)
- fn = hook->fn;
-
- raw_spin_unlock_irqrestore(&undef_lock, flags);
-exit:
- return fn ? fn(regs, instr) : 1;
+ *insnp = instr;
+ return 0;
}
void force_signal_inject(int signal, int code, unsigned long address, unsigned long err)
@@ -486,21 +450,40 @@ void arm64_notify_segfault(unsigned long addr)
force_signal_inject(SIGSEGV, code, addr, 0);
}
-void do_undefinstr(struct pt_regs *regs, unsigned long esr)
+void do_el0_undef(struct pt_regs *regs, unsigned long esr)
{
+ u32 insn;
+
/* check for AArch32 breakpoint instructions */
if (!aarch32_break_handler(regs))
return;
- if (call_undef_hook(regs) == 0)
+ if (user_insn_read(regs, &insn))
+ goto out_err;
+
+ if (try_emulate_mrs(regs, insn))
return;
- if (!user_mode(regs))
- die("Oops - Undefined instruction", regs, esr);
+ if (try_emulate_armv8_deprecated(regs, insn))
+ return;
+out_err:
force_signal_inject(SIGILL, ILL_ILLOPC, regs->pc, 0);
}
-NOKPROBE_SYMBOL(do_undefinstr);
+
+void do_el1_undef(struct pt_regs *regs, unsigned long esr)
+{
+ u32 insn;
+
+ if (aarch64_insn_read((void *)regs->pc, &insn))
+ goto out_err;
+
+ if (try_emulate_el1_ssbs(regs, insn))
+ return;
+
+out_err:
+ die("Oops - Undefined instruction", regs, esr);
+}
void do_el0_bti(struct pt_regs *regs)
{
@@ -511,7 +494,6 @@ void do_el1_bti(struct pt_regs *regs, unsigned long esr)
{
die("Oops - BTI", regs, esr);
}
-NOKPROBE_SYMBOL(do_el1_bti);
void do_el0_fpac(struct pt_regs *regs, unsigned long esr)
{
@@ -526,7 +508,6 @@ void do_el1_fpac(struct pt_regs *regs, unsigned long esr)
*/
die("Oops - FPAC", regs, esr);
}
-NOKPROBE_SYMBOL(do_el1_fpac)
#define __user_cache_maint(insn, address, res) \
if (address >= TASK_SIZE_MAX) { \
@@ -748,7 +729,7 @@ static const struct sys64_hook cp15_64_hooks[] = {
{},
};
-void do_cp15instr(unsigned long esr, struct pt_regs *regs)
+void do_el0_cp15(unsigned long esr, struct pt_regs *regs)
{
const struct sys64_hook *hook, *hook_base;
@@ -769,7 +750,7 @@ void do_cp15instr(unsigned long esr, struct pt_regs *regs)
hook_base = cp15_64_hooks;
break;
default:
- do_undefinstr(regs, esr);
+ do_el0_undef(regs, esr);
return;
}
@@ -784,12 +765,11 @@ void do_cp15instr(unsigned long esr, struct pt_regs *regs)
* EL0. Fall back to our usual undefined instruction handler
* so that we handle these consistently.
*/
- do_undefinstr(regs, esr);
+ do_el0_undef(regs, esr);
}
-NOKPROBE_SYMBOL(do_cp15instr);
#endif
-void do_sysinstr(unsigned long esr, struct pt_regs *regs)
+void do_el0_sys(unsigned long esr, struct pt_regs *regs)
{
const struct sys64_hook *hook;
@@ -804,9 +784,8 @@ void do_sysinstr(unsigned long esr, struct pt_regs *regs)
* back to our usual undefined instruction handler so that we handle
* these consistently.
*/
- do_undefinstr(regs, esr);
+ do_el0_undef(regs, esr);
}
-NOKPROBE_SYMBOL(do_sysinstr);
static const char *esr_class_str[] = {
[0 ... ESR_ELx_EC_MAX] = "UNRECOGNIZED EC",
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index 99ae81ab91a7..e59a32aa0c49 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -151,28 +151,6 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
mmap_read_unlock(mm);
return 0;
}
-
-static struct page *find_timens_vvar_page(struct vm_area_struct *vma)
-{
- if (likely(vma->vm_mm == current->mm))
- return current->nsproxy->time_ns->vvar_page;
-
- /*
- * VM_PFNMAP | VM_IO protect .fault() handler from being called
- * through interfaces like /proc/$pid/mem or
- * process_vm_{readv,writev}() as long as there's no .access()
- * in special_mapping_vmops.
- * For more details check_vma_flags() and __access_remote_vm()
- */
- WARN(1, "vvar_page accessed remotely");
-
- return NULL;
-}
-#else
-static struct page *find_timens_vvar_page(struct vm_area_struct *vma)
-{
- return NULL;
-}
#endif
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
index 45131e354e27..4c13dafc98b8 100644
--- a/arch/arm64/kernel/vmlinux.lds.S
+++ b/arch/arm64/kernel/vmlinux.lds.S
@@ -121,6 +121,17 @@ jiffies = jiffies_64;
#define TRAMP_TEXT
#endif
+#ifdef CONFIG_UNWIND_TABLES
+#define UNWIND_DATA_SECTIONS \
+ .eh_frame : { \
+ __eh_frame_start = .; \
+ *(.eh_frame) \
+ __eh_frame_end = .; \
+ }
+#else
+#define UNWIND_DATA_SECTIONS
+#endif
+
/*
* The size of the PE/COFF section that covers the kernel image, which
* runs from _stext to _edata, must be a round multiple of the PE/COFF
@@ -231,6 +242,8 @@ SECTIONS
__alt_instructions_end = .;
}
+ UNWIND_DATA_SECTIONS
+
. = ALIGN(SEGMENT_ALIGN);
__inittext_end = .;
__initdata_begin = .;
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index ec8e4494873d..02dd7e9ebd39 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -75,11 +75,12 @@ int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu)
void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
{
BUG_ON(!current->mm);
- BUG_ON(test_thread_flag(TIF_SVE));
if (!system_supports_fpsimd())
return;
+ fpsimd_kvm_prepare();
+
vcpu->arch.fp_state = FP_STATE_HOST_OWNED;
vcpu_clear_flag(vcpu, HOST_SVE_ENABLED);
@@ -129,20 +130,31 @@ void kvm_arch_vcpu_ctxflush_fp(struct kvm_vcpu *vcpu)
*/
void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
{
+ struct cpu_fp_state fp_state;
+
WARN_ON_ONCE(!irqs_disabled());
if (vcpu->arch.fp_state == FP_STATE_GUEST_OWNED) {
+
/*
* Currently we do not support SME guests so SVCR is
* always 0 and we just need a variable to point to.
*/
- fpsimd_bind_state_to_cpu(&vcpu->arch.ctxt.fp_regs,
- vcpu->arch.sve_state,
- vcpu->arch.sve_max_vl,
- NULL, 0, &vcpu->arch.svcr);
+ fp_state.st = &vcpu->arch.ctxt.fp_regs;
+ fp_state.sve_state = vcpu->arch.sve_state;
+ fp_state.sve_vl = vcpu->arch.sve_max_vl;
+ fp_state.za_state = NULL;
+ fp_state.svcr = &vcpu->arch.svcr;
+ fp_state.fp_type = &vcpu->arch.fp_type;
+
+ if (vcpu_has_sve(vcpu))
+ fp_state.to_save = FP_STATE_SVE;
+ else
+ fp_state.to_save = FP_STATE_FPSIMD;
+
+ fpsimd_bind_state_to_cpu(&fp_state);
clear_thread_flag(TIF_FOREIGN_FPSTATE);
- update_thread_flag(TIF_SVE, vcpu_has_sve(vcpu));
}
}
@@ -199,7 +211,5 @@ void kvm_arch_vcpu_put_fp(struct kvm_vcpu *vcpu)
sysreg_clear_set(CPACR_EL1, CPACR_EL1_ZEN_EL0EN, 0);
}
- update_thread_flag(TIF_SVE, 0);
-
local_irq_restore(flags);
}
diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile
index be0a2bc3e20d..530347cdebe3 100644
--- a/arch/arm64/kvm/hyp/nvhe/Makefile
+++ b/arch/arm64/kvm/hyp/nvhe/Makefile
@@ -96,6 +96,7 @@ KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS) $(CC_FLAGS_CFI)
# when profile optimization is applied. gen-hyprel does not support SHT_REL and
# causes a build failure. Remove profile optimization flags.
KBUILD_CFLAGS := $(filter-out -fprofile-sample-use=% -fprofile-use=%, $(KBUILD_CFLAGS))
+KBUILD_CFLAGS += -fno-asynchronous-unwind-tables -fno-unwind-tables
# KVM nVHE code is run at a different exception code with a different map, so
# compiler instrumentation that inserts callbacks or checks into the code may
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index f4a7c5abcbca..608e4f25161d 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1121,8 +1121,8 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu, struct sys_reg_desc const *r
case SYS_ID_DFR0_EL1:
/* Limit guests to PMUv3 for ARMv8.4 */
val = cpuid_feature_cap_perfmon_field(val,
- ID_DFR0_PERFMON_SHIFT,
- kvm_vcpu_has_pmu(vcpu) ? ID_DFR0_PERFMON_8_4 : 0);
+ ID_DFR0_EL1_PerfMon_SHIFT,
+ kvm_vcpu_has_pmu(vcpu) ? ID_DFR0_EL1_PerfMon_PMUv3p4 : 0);
break;
}
diff --git a/arch/arm64/lib/insn.c b/arch/arm64/lib/insn.c
index 49e972beeac7..924934cb85ee 100644
--- a/arch/arm64/lib/insn.c
+++ b/arch/arm64/lib/insn.c
@@ -20,91 +20,6 @@
#define AARCH64_INSN_N_BIT BIT(22)
#define AARCH64_INSN_LSL_12 BIT(22)
-static const int aarch64_insn_encoding_class[] = {
- AARCH64_INSN_CLS_UNKNOWN,
- AARCH64_INSN_CLS_UNKNOWN,
- AARCH64_INSN_CLS_SVE,
- AARCH64_INSN_CLS_UNKNOWN,
- AARCH64_INSN_CLS_LDST,
- AARCH64_INSN_CLS_DP_REG,
- AARCH64_INSN_CLS_LDST,
- AARCH64_INSN_CLS_DP_FPSIMD,
- AARCH64_INSN_CLS_DP_IMM,
- AARCH64_INSN_CLS_DP_IMM,
- AARCH64_INSN_CLS_BR_SYS,
- AARCH64_INSN_CLS_BR_SYS,
- AARCH64_INSN_CLS_LDST,
- AARCH64_INSN_CLS_DP_REG,
- AARCH64_INSN_CLS_LDST,
- AARCH64_INSN_CLS_DP_FPSIMD,
-};
-
-enum aarch64_insn_encoding_class __kprobes aarch64_get_insn_class(u32 insn)
-{
- return aarch64_insn_encoding_class[(insn >> 25) & 0xf];
-}
-
-bool __kprobes aarch64_insn_is_steppable_hint(u32 insn)
-{
- if (!aarch64_insn_is_hint(insn))
- return false;
-
- switch (insn & 0xFE0) {
- case AARCH64_INSN_HINT_XPACLRI:
- case AARCH64_INSN_HINT_PACIA_1716:
- case AARCH64_INSN_HINT_PACIB_1716:
- case AARCH64_INSN_HINT_PACIAZ:
- case AARCH64_INSN_HINT_PACIASP:
- case AARCH64_INSN_HINT_PACIBZ:
- case AARCH64_INSN_HINT_PACIBSP:
- case AARCH64_INSN_HINT_BTI:
- case AARCH64_INSN_HINT_BTIC:
- case AARCH64_INSN_HINT_BTIJ:
- case AARCH64_INSN_HINT_BTIJC:
- case AARCH64_INSN_HINT_NOP:
- return true;
- default:
- return false;
- }
-}
-
-bool aarch64_insn_is_branch_imm(u32 insn)
-{
- return (aarch64_insn_is_b(insn) || aarch64_insn_is_bl(insn) ||
- aarch64_insn_is_tbz(insn) || aarch64_insn_is_tbnz(insn) ||
- aarch64_insn_is_cbz(insn) || aarch64_insn_is_cbnz(insn) ||
- aarch64_insn_is_bcond(insn));
-}
-
-bool __kprobes aarch64_insn_uses_literal(u32 insn)
-{
- /* ldr/ldrsw (literal), prfm */
-
- return aarch64_insn_is_ldr_lit(insn) ||
- aarch64_insn_is_ldrsw_lit(insn) ||
- aarch64_insn_is_adr_adrp(insn) ||
- aarch64_insn_is_prfm_lit(insn);
-}
-
-bool __kprobes aarch64_insn_is_branch(u32 insn)
-{
- /* b, bl, cb*, tb*, ret*, b.cond, br*, blr* */
-
- return aarch64_insn_is_b(insn) ||
- aarch64_insn_is_bl(insn) ||
- aarch64_insn_is_cbz(insn) ||
- aarch64_insn_is_cbnz(insn) ||
- aarch64_insn_is_tbz(insn) ||
- aarch64_insn_is_tbnz(insn) ||
- aarch64_insn_is_ret(insn) ||
- aarch64_insn_is_ret_auth(insn) ||
- aarch64_insn_is_br(insn) ||
- aarch64_insn_is_br_auth(insn) ||
- aarch64_insn_is_blr(insn) ||
- aarch64_insn_is_blr_auth(insn) ||
- aarch64_insn_is_bcond(insn);
-}
-
static int __kprobes aarch64_get_imm_shift_mask(enum aarch64_insn_imm_type type,
u32 *maskp, int *shiftp)
{
@@ -435,16 +350,6 @@ u32 aarch64_insn_gen_cond_branch_imm(unsigned long pc, unsigned long addr,
offset >> 2);
}
-u32 __kprobes aarch64_insn_gen_hint(enum aarch64_insn_hint_cr_op op)
-{
- return aarch64_insn_get_hint_value() | op;
-}
-
-u32 __kprobes aarch64_insn_gen_nop(void)
-{
- return aarch64_insn_gen_hint(AARCH64_INSN_HINT_NOP);
-}
-
u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg,
enum aarch64_insn_branch_type type)
{
@@ -816,76 +721,6 @@ u32 aarch64_insn_gen_cas(enum aarch64_insn_register result,
}
#endif
-static u32 aarch64_insn_encode_prfm_imm(enum aarch64_insn_prfm_type type,
- enum aarch64_insn_prfm_target target,
- enum aarch64_insn_prfm_policy policy,
- u32 insn)
-{
- u32 imm_type = 0, imm_target = 0, imm_policy = 0;
-
- switch (type) {
- case AARCH64_INSN_PRFM_TYPE_PLD:
- break;
- case AARCH64_INSN_PRFM_TYPE_PLI:
- imm_type = BIT(0);
- break;
- case AARCH64_INSN_PRFM_TYPE_PST:
- imm_type = BIT(1);
- break;
- default:
- pr_err("%s: unknown prfm type encoding %d\n", __func__, type);
- return AARCH64_BREAK_FAULT;
- }
-
- switch (target) {
- case AARCH64_INSN_PRFM_TARGET_L1:
- break;
- case AARCH64_INSN_PRFM_TARGET_L2:
- imm_target = BIT(0);
- break;
- case AARCH64_INSN_PRFM_TARGET_L3:
- imm_target = BIT(1);
- break;
- default:
- pr_err("%s: unknown prfm target encoding %d\n", __func__, target);
- return AARCH64_BREAK_FAULT;
- }
-
- switch (policy) {
- case AARCH64_INSN_PRFM_POLICY_KEEP:
- break;
- case AARCH64_INSN_PRFM_POLICY_STRM:
- imm_policy = BIT(0);
- break;
- default:
- pr_err("%s: unknown prfm policy encoding %d\n", __func__, policy);
- return AARCH64_BREAK_FAULT;
- }
-
- /* In this case, imm5 is encoded into Rt field. */
- insn &= ~GENMASK(4, 0);
- insn |= imm_policy | (imm_target << 1) | (imm_type << 3);
-
- return insn;
-}
-
-u32 aarch64_insn_gen_prefetch(enum aarch64_insn_register base,
- enum aarch64_insn_prfm_type type,
- enum aarch64_insn_prfm_target target,
- enum aarch64_insn_prfm_policy policy)
-{
- u32 insn = aarch64_insn_get_prfm_value();
-
- insn = aarch64_insn_encode_ldst_size(AARCH64_INSN_SIZE_64, insn);
-
- insn = aarch64_insn_encode_prfm_imm(type, target, policy, insn);
-
- insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn,
- base);
-
- return aarch64_insn_encode_immediate(AARCH64_INSN_IMM_12, insn, 0);
-}
-
u32 aarch64_insn_gen_add_sub_imm(enum aarch64_insn_register dst,
enum aarch64_insn_register src,
int imm, enum aarch64_insn_variant variant,
diff --git a/arch/arm64/lib/mte.S b/arch/arm64/lib/mte.S
index 1b7c93ae7e63..5018ac03b6bf 100644
--- a/arch/arm64/lib/mte.S
+++ b/arch/arm64/lib/mte.S
@@ -18,7 +18,7 @@
*/
.macro multitag_transfer_size, reg, tmp
mrs_s \reg, SYS_GMID_EL1
- ubfx \reg, \reg, #GMID_EL1_BS_SHIFT, #GMID_EL1_BS_SIZE
+ ubfx \reg, \reg, #GMID_EL1_BS_SHIFT, #GMID_EL1_BS_WIDTH
mov \tmp, #4
lsl \reg, \tmp, \reg
.endm
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 5b391490e045..3eb2825d08cf 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -30,6 +30,7 @@
#include <asm/bug.h>
#include <asm/cmpxchg.h>
#include <asm/cpufeature.h>
+#include <asm/efi.h>
#include <asm/exception.h>
#include <asm/daifflags.h>
#include <asm/debug-monitors.h>
@@ -353,6 +354,11 @@ static bool is_el1_mte_sync_tag_check_fault(unsigned long esr)
return false;
}
+static bool is_translation_fault(unsigned long esr)
+{
+ return (esr & ESR_ELx_FSC_TYPE) == ESR_ELx_FSC_FAULT;
+}
+
static void __do_kernel_fault(unsigned long addr, unsigned long esr,
struct pt_regs *regs)
{
@@ -385,12 +391,16 @@ static void __do_kernel_fault(unsigned long addr, unsigned long esr,
} else if (addr < PAGE_SIZE) {
msg = "NULL pointer dereference";
} else {
- if (kfence_handle_page_fault(addr, esr & ESR_ELx_WNR, regs))
+ if (is_translation_fault(esr) &&
+ kfence_handle_page_fault(addr, esr & ESR_ELx_WNR, regs))
return;
msg = "paging request";
}
+ if (efi_runtime_fixup_exception(regs, msg))
+ return;
+
die_kernel_fault(msg, addr, esr, regs);
}
diff --git a/arch/arm64/mm/hugetlbpage.c b/arch/arm64/mm/hugetlbpage.c
index 35e9a468d13e..cd8d96e1fa1a 100644
--- a/arch/arm64/mm/hugetlbpage.c
+++ b/arch/arm64/mm/hugetlbpage.c
@@ -559,3 +559,24 @@ bool __init arch_hugetlb_valid_size(unsigned long size)
{
return __hugetlb_valid_size(size);
}
+
+pte_t huge_ptep_modify_prot_start(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
+{
+ if (IS_ENABLED(CONFIG_ARM64_WORKAROUND_2645198) &&
+ cpus_have_const_cap(ARM64_WORKAROUND_2645198)) {
+ /*
+ * Break-before-make (BBM) is required for all user space mappings
+ * when the permission changes from executable to non-executable
+ * in cases where cpu is affected with errata #2645198.
+ */
+ if (pte_user_exec(READ_ONCE(*ptep)))
+ return huge_ptep_clear_flush(vma, addr, ptep);
+ }
+ return huge_ptep_get_and_clear(vma->vm_mm, addr, ptep);
+}
+
+void huge_ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep,
+ pte_t old_pte, pte_t pte)
+{
+ set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
+}
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 4b4651ee47f2..58a0bb2c17f1 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -96,6 +96,8 @@ phys_addr_t __ro_after_init arm64_dma_phys_limit = PHYS_MASK + 1;
#define CRASH_ADDR_LOW_MAX arm64_dma_phys_limit
#define CRASH_ADDR_HIGH_MAX (PHYS_MASK + 1)
+#define DEFAULT_CRASH_KERNEL_LOW_SIZE (128UL << 20)
+
static int __init reserve_crashkernel_low(unsigned long long low_size)
{
unsigned long long low_base;
@@ -130,6 +132,7 @@ static void __init reserve_crashkernel(void)
unsigned long long crash_max = CRASH_ADDR_LOW_MAX;
char *cmdline = boot_command_line;
int ret;
+ bool fixed_base = false;
if (!IS_ENABLED(CONFIG_KEXEC_CORE))
return;
@@ -147,7 +150,9 @@ static void __init reserve_crashkernel(void)
* is not allowed.
*/
ret = parse_crashkernel_low(cmdline, 0, &crash_low_size, &crash_base);
- if (ret && (ret != -ENOENT))
+ if (ret == -ENOENT)
+ crash_low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
+ else if (ret)
return;
crash_max = CRASH_ADDR_HIGH_MAX;
@@ -159,18 +164,32 @@ static void __init reserve_crashkernel(void)
crash_size = PAGE_ALIGN(crash_size);
/* User specifies base address explicitly. */
- if (crash_base)
+ if (crash_base) {
+ fixed_base = true;
crash_max = crash_base + crash_size;
+ }
+retry:
crash_base = memblock_phys_alloc_range(crash_size, CRASH_ALIGN,
crash_base, crash_max);
if (!crash_base) {
+ /*
+ * If the first attempt was for low memory, fall back to
+ * high memory, the minimum required low memory will be
+ * reserved later.
+ */
+ if (!fixed_base && (crash_max == CRASH_ADDR_LOW_MAX)) {
+ crash_max = CRASH_ADDR_HIGH_MAX;
+ crash_low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE;
+ goto retry;
+ }
+
pr_warn("cannot allocate crashkernel (size:0x%llx)\n",
crash_size);
return;
}
- if ((crash_base >= CRASH_ADDR_LOW_MAX) &&
+ if ((crash_base > CRASH_ADDR_LOW_MAX - crash_low_size) &&
crash_low_size && reserve_crashkernel_low(crash_low_size)) {
memblock_phys_free(crash_base, crash_size);
return;
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index 9a7c38965154..2368e4daa23d 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -1196,7 +1196,7 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
WARN_ON((start < VMEMMAP_START) || (end > VMEMMAP_END));
- if (!ARM64_KERNEL_USES_PMD_MAPS)
+ if (!IS_ENABLED(CONFIG_ARM64_4K_PAGES))
return vmemmap_populate_basepages(start, end, node, altmap);
do {
@@ -1702,3 +1702,24 @@ static int __init prevent_bootmem_remove_init(void)
}
early_initcall(prevent_bootmem_remove_init);
#endif
+
+pte_t ptep_modify_prot_start(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep)
+{
+ if (IS_ENABLED(CONFIG_ARM64_WORKAROUND_2645198) &&
+ cpus_have_const_cap(ARM64_WORKAROUND_2645198)) {
+ /*
+ * Break-before-make (BBM) is required for all user space mappings
+ * when the permission changes from executable to non-executable
+ * in cases where cpu is affected with errata #2645198.
+ */
+ if (pte_user_exec(READ_ONCE(*ptep)))
+ return ptep_clear_flush(vma, addr, ptep);
+ }
+ return ptep_get_and_clear(vma->vm_mm, addr, ptep);
+}
+
+void ptep_modify_prot_commit(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep,
+ pte_t old_pte, pte_t pte)
+{
+ set_pte_at(vma->vm_mm, addr, ptep, pte);
+}
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index b9ecbbae1e1a..066fa60b93d2 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -189,16 +189,12 @@ SYM_FUNC_END(cpu_do_resume)
* called by anything else. It can only be executed from a TTBR0 mapping.
*/
SYM_TYPED_FUNC_START(idmap_cpu_replace_ttbr1)
- save_and_disable_daif flags=x2
-
__idmap_cpu_set_reserved_ttbr1 x1, x3
offset_ttbr1 x0, x3
msr ttbr1_el1, x0
isb
- restore_daif x2
-
ret
SYM_FUNC_END(idmap_cpu_replace_ttbr1)
.popsection
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index f1c0347ec31a..dfeb2c51e257 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -20,6 +20,7 @@ HAS_CNP
HAS_CRC32
HAS_DCPODP
HAS_DCPOP
+HAS_DIT
HAS_E0PD
HAS_ECV
HAS_EPAN
@@ -70,6 +71,7 @@ WORKAROUND_2038923
WORKAROUND_2064142
WORKAROUND_2077057
WORKAROUND_2457168
+WORKAROUND_2645198
WORKAROUND_2658417
WORKAROUND_TRBE_OVERWRITE_FILL_MODE
WORKAROUND_TSB_FLUSH_FAILURE
diff --git a/arch/arm64/tools/gen-sysreg.awk b/arch/arm64/tools/gen-sysreg.awk
index db461921d256..c350164a3955 100755
--- a/arch/arm64/tools/gen-sysreg.awk
+++ b/arch/arm64/tools/gen-sysreg.awk
@@ -33,7 +33,7 @@ function expect_fields(nf) {
# Print a CPP macro definition, padded with spaces so that the macro bodies
# line up in a column
function define(name, val) {
- printf "%-48s%s\n", "#define " name, val
+ printf "%-56s%s\n", "#define " name, val
}
# Print standard BITMASK/SHIFT/WIDTH CPP definitions for a field
diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
index 384757a7eda9..184e58fd5631 100644
--- a/arch/arm64/tools/sysreg
+++ b/arch/arm64/tools/sysreg
@@ -46,6 +46,760 @@
# feature that introduces them (eg, FEAT_LS64_ACCDATA introduces enumeration
# item ACCDATA) though it may be more taseful to do something else.
+Sysreg ID_PFR0_EL1 3 0 0 1 0
+Res0 63:32
+Enum 31:28 RAS
+ 0b0000 NI
+ 0b0001 RAS
+ 0b0010 RASv1p1
+EndEnum
+Enum 27:24 DIT
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 23:20 AMU
+ 0b0000 NI
+ 0b0001 AMUv1
+ 0b0010 AMUv1p1
+EndEnum
+Enum 19:16 CSV2
+ 0b0000 UNDISCLOSED
+ 0b0001 IMP
+ 0b0010 CSV2p1
+EndEnum
+Enum 15:12 State3
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 11:8 State2
+ 0b0000 NI
+ 0b0001 NO_CV
+ 0b0010 CV
+EndEnum
+Enum 7:4 State1
+ 0b0000 NI
+ 0b0001 THUMB
+ 0b0010 THUMB2
+EndEnum
+Enum 3:0 State0
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+EndSysreg
+
+Sysreg ID_PFR1_EL1 3 0 0 1 1
+Res0 63:32
+Enum 31:28 GIC
+ 0b0000 NI
+ 0b0001 GICv3
+ 0b0010 GICv4p1
+EndEnum
+Enum 27:24 Virt_frac
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 23:20 Sec_frac
+ 0b0000 NI
+ 0b0001 WALK_DISABLE
+ 0b0010 SECURE_MEMORY
+EndEnum
+Enum 19:16 GenTimer
+ 0b0000 NI
+ 0b0001 IMP
+ 0b0010 ECV
+EndEnum
+Enum 15:12 Virtualization
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 11:8 MProgMod
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 7:4 Security
+ 0b0000 NI
+ 0b0001 EL3
+ 0b0001 NSACR_RFR
+EndEnum
+Enum 3:0 ProgMod
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+EndSysreg
+
+Sysreg ID_DFR0_EL1 3 0 0 1 2
+Res0 63:32
+Enum 31:28 TraceFilt
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 27:24 PerfMon
+ 0b0000 NI
+ 0b0001 PMUv1
+ 0b0010 PMUv2
+ 0b0011 PMUv3
+ 0b0100 PMUv3p1
+ 0b0101 PMUv3p4
+ 0b0110 PMUv3p5
+ 0b0111 PMUv3p7
+ 0b1000 PMUv3p8
+ 0b1111 IMPDEF
+EndEnum
+Enum 23:20 MProfDbg
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 19:16 MMapTrc
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 15:12 CopTrc
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 11:8 MMapDbg
+ 0b0000 NI
+ 0b0100 Armv7
+ 0b0101 Armv7p1
+EndEnum
+Field 7:4 CopSDbg
+Enum 3:0 CopDbg
+ 0b0000 NI
+ 0b0010 Armv6
+ 0b0011 Armv6p1
+ 0b0100 Armv7
+ 0b0101 Armv7p1
+ 0b0110 Armv8
+ 0b0111 VHE
+ 0b1000 Debugv8p2
+ 0b1001 Debugv8p4
+ 0b1010 Debugv8p8
+EndEnum
+EndSysreg
+
+Sysreg ID_AFR0_EL1 3 0 0 1 3
+Res0 63:16
+Field 15:12 IMPDEF3
+Field 11:8 IMPDEF2
+Field 7:4 IMPDEF1
+Field 3:0 IMPDEF0
+EndSysreg
+
+Sysreg ID_MMFR0_EL1 3 0 0 1 4
+Res0 63:32
+Enum 31:28 InnerShr
+ 0b0000 NC
+ 0b0001 HW
+ 0b1111 IGNORED
+EndEnum
+Enum 27:24 FCSE
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 23:20 AuxReg
+ 0b0000 NI
+ 0b0001 ACTLR
+ 0b0010 AIFSR
+EndEnum
+Enum 19:16 TCM
+ 0b0000 NI
+ 0b0001 IMPDEF
+ 0b0010 TCM
+ 0b0011 TCM_DMA
+EndEnum
+Enum 15:12 ShareLvl
+ 0b0000 ONE
+ 0b0001 TWO
+EndEnum
+Enum 11:8 OuterShr
+ 0b0000 NC
+ 0b0001 HW
+ 0b1111 IGNORED
+EndEnum
+Enum 7:4 PMSA
+ 0b0000 NI
+ 0b0001 IMPDEF
+ 0b0010 PMSAv6
+ 0b0011 PMSAv7
+EndEnum
+Enum 3:0 VMSA
+ 0b0000 NI
+ 0b0001 IMPDEF
+ 0b0010 VMSAv6
+ 0b0011 VMSAv7
+ 0b0100 VMSAv7_PXN
+ 0b0101 VMSAv7_LONG
+EndEnum
+EndSysreg
+
+Sysreg ID_MMFR1_EL1 3 0 0 1 5
+Res0 63:32
+Enum 31:28 BPred
+ 0b0000 NI
+ 0b0001 BP_SW_MANGED
+ 0b0010 BP_ASID_AWARE
+ 0b0011 BP_NOSNOOP
+ 0b0100 BP_INVISIBLE
+EndEnum
+Enum 27:24 L1TstCln
+ 0b0000 NI
+ 0b0001 NOINVALIDATE
+ 0b0010 INVALIDATE
+EndEnum
+Enum 23:20 L1Uni
+ 0b0000 NI
+ 0b0001 INVALIDATE
+ 0b0010 CLEAN_AND_INVALIDATE
+EndEnum
+Enum 19:16 L1Hvd
+ 0b0000 NI
+ 0b0001 INVALIDATE_ISIDE_ONLY
+ 0b0010 INVALIDATE
+ 0b0011 CLEAN_AND_INVALIDATE
+EndEnum
+Enum 15:12 L1UniSW
+ 0b0000 NI
+ 0b0001 CLEAN
+ 0b0010 CLEAN_AND_INVALIDATE
+ 0b0011 INVALIDATE
+EndEnum
+Enum 11:8 L1HvdSW
+ 0b0000 NI
+ 0b0001 CLEAN_AND_INVALIDATE
+ 0b0010 INVALIDATE_DSIDE_ONLY
+ 0b0011 INVALIDATE
+EndEnum
+Enum 7:4 L1UniVA
+ 0b0000 NI
+ 0b0001 CLEAN_AND_INVALIDATE
+ 0b0010 INVALIDATE_BP
+EndEnum
+Enum 3:0 L1HvdVA
+ 0b0000 NI
+ 0b0001 CLEAN_AND_INVALIDATE
+ 0b0010 INVALIDATE_BP
+EndEnum
+EndSysreg
+
+Sysreg ID_MMFR2_EL1 3 0 0 1 6
+Res0 63:32
+Enum 31:28 HWAccFlg
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 27:24 WFIStall
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 23:20 MemBarr
+ 0b0000 NI
+ 0b0001 DSB_ONLY
+ 0b0010 IMP
+EndEnum
+Enum 19:16 UniTLB
+ 0b0000 NI
+ 0b0001 BY_VA
+ 0b0010 BY_MATCH_ASID
+ 0b0011 BY_ALL_ASID
+ 0b0100 OTHER_TLBS
+ 0b0101 BROADCAST
+ 0b0110 BY_IPA
+EndEnum
+Enum 15:12 HvdTLB
+ 0b0000 NI
+EndEnum
+Enum 11:8 L1HvdRng
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 7:4 L1HvdBG
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 3:0 L1HvdFG
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+EndSysreg
+
+Sysreg ID_MMFR3_EL1 3 0 0 1 7
+Res0 63:32
+Enum 31:28 Supersec
+ 0b0000 IMP
+ 0b1111 NI
+EndEnum
+Enum 27:24 CMemSz
+ 0b0000 4GB
+ 0b0001 64GB
+ 0b0010 1TB
+EndEnum
+Enum 23:20 CohWalk
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 19:16 PAN
+ 0b0000 NI
+ 0b0001 PAN
+ 0b0010 PAN2
+EndEnum
+Enum 15:12 MaintBcst
+ 0b0000 NI
+ 0b0001 NO_TLB
+ 0b0010 ALL
+EndEnum
+Enum 11:8 BPMaint
+ 0b0000 NI
+ 0b0001 ALL
+ 0b0010 BY_VA
+EndEnum
+Enum 7:4 CMaintSW
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 3:0 CMaintVA
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+EndSysreg
+
+Sysreg ID_ISAR0_EL1 3 0 0 2 0
+Res0 63:28
+Enum 27:24 Divide
+ 0b0000 NI
+ 0b0001 xDIV_T32
+ 0b0010 xDIV_A32
+EndEnum
+Enum 23:20 Debug
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 19:16 Coproc
+ 0b0000 NI
+ 0b0001 MRC
+ 0b0010 MRC2
+ 0b0011 MRRC
+ 0b0100 MRRC2
+EndEnum
+Enum 15:12 CmpBranch
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 11:8 BitField
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 7:4 BitCount
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 3:0 Swap
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+EndSysreg
+
+Sysreg ID_ISAR1_EL1 3 0 0 2 1
+Res0 63:32
+Enum 31:28 Jazelle
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 27:24 Interwork
+ 0b0000 NI
+ 0b0001 BX
+ 0b0010 BLX
+ 0b0011 A32_BX
+EndEnum
+Enum 23:20 Immediate
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 19:16 IfThen
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 15:12 Extend
+ 0b0000 NI
+ 0b0001 SXTB
+ 0b0010 SXTB16
+EndEnum
+Enum 11:8 Except_AR
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 7:4 Except
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 3:0 Endian
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+EndSysreg
+
+Sysreg ID_ISAR2_EL1 3 0 0 2 2
+Res0 63:32
+Enum 31:28 Reversal
+ 0b0000 NI
+ 0b0001 REV
+ 0b0010 RBIT
+EndEnum
+Enum 27:24 PSR_AR
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 23:20 MultU
+ 0b0000 NI
+ 0b0001 UMULL
+ 0b0010 UMAAL
+EndEnum
+Enum 19:16 MultS
+ 0b0000 NI
+ 0b0001 SMULL
+ 0b0010 SMLABB
+ 0b0011 SMLAD
+EndEnum
+Enum 15:12 Mult
+ 0b0000 NI
+ 0b0001 MLA
+ 0b0010 MLS
+EndEnum
+Enum 11:8 MultiAccessInt
+ 0b0000 NI
+ 0b0001 RESTARTABLE
+ 0b0010 CONTINUABLE
+EndEnum
+Enum 7:4 MemHint
+ 0b0000 NI
+ 0b0001 PLD
+ 0b0010 PLD2
+ 0b0011 PLI
+ 0b0100 PLDW
+EndEnum
+Enum 3:0 LoadStore
+ 0b0000 NI
+ 0b0001 DOUBLE
+ 0b0010 ACQUIRE
+EndEnum
+EndSysreg
+
+Sysreg ID_ISAR3_EL1 3 0 0 2 3
+Res0 63:32
+Enum 31:28 T32EE
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 27:24 TrueNOP
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 23:20 T32Copy
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 19:16 TabBranch
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 15:12 SynchPrim
+ 0b0000 NI
+ 0b0001 EXCLUSIVE
+ 0b0010 DOUBLE
+EndEnum
+Enum 11:8 SVC
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 7:4 SIMD
+ 0b0000 NI
+ 0b0001 SSAT
+ 0b0011 PKHBT
+EndEnum
+Enum 3:0 Saturate
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+EndSysreg
+
+Sysreg ID_ISAR4_EL1 3 0 0 2 4
+Res0 63:32
+Enum 31:28 SWP_frac
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 27:24 PSR_M
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 23:20 SynchPrim_frac
+ 0b0000 NI
+ 0b0011 IMP
+EndEnum
+Enum 19:16 Barrier
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 15:12 SMC
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 11:8 Writeback
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 7:4 WithShifts
+ 0b0000 NI
+ 0b0001 LSL3
+ 0b0011 LS
+ 0b0100 REG
+EndEnum
+Enum 3:0 Unpriv
+ 0b0000 NI
+ 0b0001 REG_BYTE
+ 0b0010 SIGNED_HALFWORD
+EndEnum
+EndSysreg
+
+Sysreg ID_ISAR5_EL1 3 0 0 2 5
+Res0 63:32
+Enum 31:28 VCMA
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 27:24 RDM
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Res0 23:20
+Enum 19:16 CRC32
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 15:12 SHA2
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 11:8 SHA1
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 7:4 AES
+ 0b0000 NI
+ 0b0001 IMP
+ 0b0010 VMULL
+EndEnum
+Enum 3:0 SEVL
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+EndSysreg
+
+Sysreg ID_ISAR6_EL1 3 0 0 2 7
+Res0 63:28
+Enum 27:24 I8MM
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 23:20 BF16
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 19:16 SPECRES
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 15:12 SB
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 11:8 FHM
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 7:4 DP
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 3:0 JSCVT
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+EndSysreg
+
+Sysreg ID_MMFR4_EL1 3 0 0 2 6
+Res0 63:32
+Enum 31:28 EVT
+ 0b0000 NI
+ 0b0001 NO_TLBIS
+ 0b0010 TLBIS
+EndEnum
+Enum 27:24 CCIDX
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 23:20 LSM
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 19:16 HPDS
+ 0b0000 NI
+ 0b0001 AA32HPD
+ 0b0010 HPDS2
+EndEnum
+Enum 15:12 CnP
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 11:8 XNX
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 7:4 AC2
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 3:0 SpecSEI
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+EndSysreg
+
+Sysreg MVFR0_EL1 3 0 0 3 0
+Res0 63:32
+Enum 31:28 FPRound
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 27:24 FPShVec
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 23:20 FPSqrt
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 19:16 FPDivide
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 15:12 FPTrap
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 11:8 FPDP
+ 0b0000 NI
+ 0b0001 VFPv2
+ 0b0001 VFPv3
+EndEnum
+Enum 7:4 FPSP
+ 0b0000 NI
+ 0b0001 VFPv2
+ 0b0001 VFPv3
+EndEnum
+Enum 3:0 SIMDReg
+ 0b0000 NI
+ 0b0001 IMP_16x64
+ 0b0001 IMP_32x64
+EndEnum
+EndSysreg
+
+Sysreg MVFR1_EL1 3 0 0 3 1
+Res0 63:32
+Enum 31:28 SIMDFMAC
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 27:24 FPHP
+ 0b0000 NI
+ 0b0001 FPHP
+ 0b0010 FPHP_CONV
+ 0b0011 FP16
+EndEnum
+Enum 23:20 SIMDHP
+ 0b0000 NI
+ 0b0001 SIMDHP
+ 0b0001 SIMDHP_FLOAT
+EndEnum
+Enum 19:16 SIMDSP
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 15:12 SIMDInt
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 11:8 SIMDLS
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 7:4 FPDNaN
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 3:0 FPFtZ
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+EndSysreg
+
+Sysreg MVFR2_EL1 3 0 0 3 2
+Res0 63:8
+Enum 7:4 FPMisc
+ 0b0000 NI
+ 0b0001 FP
+ 0b0010 FP_DIRECTED_ROUNDING
+ 0b0011 FP_ROUNDING
+ 0b0100 FP_MAX_MIN
+EndEnum
+Enum 3:0 SIMDMisc
+ 0b0000 NI
+ 0b0001 SIMD_DIRECTED_ROUNDING
+ 0b0010 SIMD_ROUNDING
+ 0b0011 SIMD_MAX_MIN
+EndEnum
+EndSysreg
+
+Sysreg ID_PFR2_EL1 3 0 0 3 4
+Res0 63:12
+Enum 11:8 RAS_frac
+ 0b0000 NI
+ 0b0001 RASv1p1
+EndEnum
+Enum 7:4 SSBS
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 3:0 CSV3
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+EndSysreg
+
+Sysreg ID_DFR1_EL1 3 0 0 3 5
+Res0 63:8
+Enum 7:4 HPMN0
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 3:0 MTPMU
+ 0b0000 IMPDEF
+ 0b0001 IMP
+ 0b1111 NI
+EndEnum
+EndSysreg
+
+Sysreg ID_MMFR5_EL1 3 0 0 3 6
+Res0 63:8
+Enum 7:4 nTLBPA
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 3:0 ETS
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+EndSysreg
+
Sysreg ID_AA64PFR0_EL1 3 0 0 4 0
Enum 63:60 CSV3
0b0000 NI
@@ -210,6 +964,7 @@ EndEnum
Enum 3:0 SVEver
0b0000 IMP
0b0001 SVE2
+ 0b0010 SVE2p1
EndEnum
EndSysreg
@@ -484,7 +1239,16 @@ EndEnum
EndSysreg
Sysreg ID_AA64ISAR2_EL1 3 0 0 6 2
-Res0 63:28
+Res0 63:56
+Enum 55:52 CSSC
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Enum 51:48 RPRFM
+ 0b0000 NI
+ 0b0001 IMP
+EndEnum
+Res0 47:28
Enum 27:24 PAC_frac
0b0000 NI
0b0001 IMP
diff --git a/arch/csky/include/asm/stackprotector.h b/arch/csky/include/asm/stackprotector.h
index d7cd4e51edd9..d23747447166 100644
--- a/arch/csky/include/asm/stackprotector.h
+++ b/arch/csky/include/asm/stackprotector.h
@@ -2,9 +2,6 @@
#ifndef _ASM_STACKPROTECTOR_H
#define _ASM_STACKPROTECTOR_H 1
-#include <linux/random.h>
-#include <linux/version.h>
-
extern unsigned long __stack_chk_guard;
/*
@@ -15,12 +12,7 @@ extern unsigned long __stack_chk_guard;
*/
static __always_inline void boot_init_stack_canary(void)
{
- unsigned long canary;
-
- /* Try to get a semi random initial value. */
- get_random_bytes(&canary, sizeof(canary));
- canary ^= LINUX_VERSION_CODE;
- canary &= CANARY_MASK;
+ unsigned long canary = get_random_canary();
current->stack_canary = canary;
__stack_chk_guard = current->stack_canary;
diff --git a/arch/csky/kernel/process.c b/arch/csky/kernel/process.c
index eedddb155669..2b0ed515a88e 100644
--- a/arch/csky/kernel/process.c
+++ b/arch/csky/kernel/process.c
@@ -9,6 +9,7 @@
#include <linux/kallsyms.h>
#include <linux/uaccess.h>
#include <linux/ptrace.h>
+#include <linux/elfcore.h>
#include <asm/elf.h>
#include <abi/reg_ops.h>
@@ -69,12 +70,11 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
}
/* Fill in the fpu structure for a core dump. */
-int dump_fpu(struct pt_regs *regs, struct user_fp *fpu)
+int elf_core_copy_task_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
{
memcpy(fpu, &current->thread.user_fp, sizeof(*fpu));
return 1;
}
-EXPORT_SYMBOL(dump_fpu);
int dump_task_regs(struct task_struct *tsk, elf_gregset_t *pr_regs)
{
diff --git a/arch/hexagon/kernel/ptrace.c b/arch/hexagon/kernel/ptrace.c
index 8975f9b4cedf..125f19995b76 100644
--- a/arch/hexagon/kernel/ptrace.c
+++ b/arch/hexagon/kernel/ptrace.c
@@ -115,10 +115,9 @@ static int genregs_set(struct task_struct *target,
/* Ignore the rest, if needed */
if (!ret)
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- offsetof(struct user_regs_struct, pad1), -1);
-
- if (ret)
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ offsetof(struct user_regs_struct, pad1), -1);
+ else
return ret;
/*
diff --git a/arch/ia64/hp/common/aml_nfw.c b/arch/ia64/hp/common/aml_nfw.c
index 684667ade525..901df49461a0 100644
--- a/arch/ia64/hp/common/aml_nfw.c
+++ b/arch/ia64/hp/common/aml_nfw.c
@@ -187,9 +187,9 @@ static int aml_nfw_add(struct acpi_device *device)
return aml_nfw_add_global_handler();
}
-static int aml_nfw_remove(struct acpi_device *device)
+static void aml_nfw_remove(struct acpi_device *device)
{
- return aml_nfw_remove_global_handler();
+ aml_nfw_remove_global_handler();
}
static const struct acpi_device_id aml_nfw_ids[] = {
diff --git a/arch/ia64/include/asm/io.h b/arch/ia64/include/asm/io.h
index ce66dfc0e719..83a492c8d298 100644
--- a/arch/ia64/include/asm/io.h
+++ b/arch/ia64/include/asm/io.h
@@ -23,10 +23,6 @@
#include <asm/unaligned.h>
#include <asm/early_ioremap.h>
-/* We don't use IO slowdowns on the ia64, but.. */
-#define __SLOW_DOWN_IO do { } while (0)
-#define SLOW_DOWN_IO do { } while (0)
-
#define __IA64_UNCACHED_OFFSET RGN_BASE(RGN_UNCACHED)
/*
diff --git a/arch/ia64/include/asm/kprobes.h b/arch/ia64/include/asm/kprobes.h
index c5cf5e4fb338..9e956768946c 100644
--- a/arch/ia64/include/asm/kprobes.h
+++ b/arch/ia64/include/asm/kprobes.h
@@ -110,8 +110,6 @@ extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
extern int kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data);
-extern void invalidate_stacked_regs(void);
-extern void flush_register_stack(void);
extern void arch_remove_kprobe(struct kprobe *p);
#endif /* CONFIG_KPROBES */
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index ab8aeb34d1d9..4c41912c550f 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -1481,12 +1481,10 @@ static void do_gpregs_set(struct unw_frame_info *info, void *arg)
return;
/* Skip r0 */
if (dst->pos < ELF_GR_OFFSET(1)) {
- dst->ret = user_regset_copyin_ignore(&dst->pos, &dst->count,
- &dst->u.set.kbuf,
- &dst->u.set.ubuf,
- 0, ELF_GR_OFFSET(1));
- if (dst->ret)
- return;
+ user_regset_copyin_ignore(&dst->pos, &dst->count,
+ &dst->u.set.kbuf, &dst->u.set.ubuf,
+ 0, ELF_GR_OFFSET(1));
+ dst->ret = 0;
}
while (dst->count && dst->pos < ELF_AR_END_OFFSET) {
@@ -1560,11 +1558,11 @@ static void do_fpregs_set(struct unw_frame_info *info, void *arg)
/* Skip pos 0 and 1 */
if (dst->count > 0 && dst->pos < ELF_FP_OFFSET(2)) {
- dst->ret = user_regset_copyin_ignore(&dst->pos, &dst->count,
- &dst->u.set.kbuf,
- &dst->u.set.ubuf,
- 0, ELF_FP_OFFSET(2));
- if (dst->count == 0 || dst->ret)
+ user_regset_copyin_ignore(&dst->pos, &dst->count,
+ &dst->u.set.kbuf, &dst->u.set.ubuf,
+ 0, ELF_FP_OFFSET(2));
+ dst->ret = 0;
+ if (dst->count == 0)
return;
}
diff --git a/arch/ia64/kernel/sys_ia64.c b/arch/ia64/kernel/sys_ia64.c
index 215bf3f8cb20..f6a502e8f02c 100644
--- a/arch/ia64/kernel/sys_ia64.c
+++ b/arch/ia64/kernel/sys_ia64.c
@@ -140,7 +140,7 @@ asmlinkage unsigned long
sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff)
{
addr = ksys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
- if (!IS_ERR((void *) addr))
+ if (!IS_ERR_VALUE(addr))
force_successful_syscall_return();
return addr;
}
@@ -152,7 +152,7 @@ sys_mmap (unsigned long addr, unsigned long len, int prot, int flags, int fd, lo
return -EINVAL;
addr = ksys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
- if (!IS_ERR((void *) addr))
+ if (!IS_ERR_VALUE(addr))
force_successful_syscall_return();
return addr;
}
@@ -162,7 +162,7 @@ ia64_mremap (unsigned long addr, unsigned long old_len, unsigned long new_len, u
unsigned long new_addr)
{
addr = sys_mremap(addr, old_len, new_len, flags, new_addr);
- if (!IS_ERR((void *) addr))
+ if (!IS_ERR_VALUE(addr))
force_successful_syscall_return();
return addr;
}
diff --git a/arch/loongarch/Kconfig b/arch/loongarch/Kconfig
index 903096bd87f8..386adde2feff 100644
--- a/arch/loongarch/Kconfig
+++ b/arch/loongarch/Kconfig
@@ -10,6 +10,7 @@ config LOONGARCH
select ARCH_ENABLE_MEMORY_HOTPLUG
select ARCH_ENABLE_MEMORY_HOTREMOVE
select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
+ select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
select ARCH_HAS_PTE_SPECIAL
select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
select ARCH_INLINE_READ_LOCK if !PREEMPTION
diff --git a/arch/loongarch/include/asm/acpi.h b/arch/loongarch/include/asm/acpi.h
index 17162f494b9b..825c2519b9d1 100644
--- a/arch/loongarch/include/asm/acpi.h
+++ b/arch/loongarch/include/asm/acpi.h
@@ -31,148 +31,6 @@ static inline bool acpi_has_cpu_in_madt(void)
extern struct list_head acpi_wakeup_device_list;
-/*
- * Temporary definitions until the core ACPICA code gets updated (see
- * 1656837932-18257-1-git-send-email-lvjianmin@loongson.cn and its
- * follow-ups for the "rationale").
- *
- * Once the "legal reasons" are cleared and that the code is merged,
- * this can be dropped entierely.
- */
-#if (ACPI_CA_VERSION == 0x20220331 && !defined(LOONGARCH_ACPICA_EXT))
-
-#define LOONGARCH_ACPICA_EXT 1
-
-#define ACPI_MADT_TYPE_CORE_PIC 17
-#define ACPI_MADT_TYPE_LIO_PIC 18
-#define ACPI_MADT_TYPE_HT_PIC 19
-#define ACPI_MADT_TYPE_EIO_PIC 20
-#define ACPI_MADT_TYPE_MSI_PIC 21
-#define ACPI_MADT_TYPE_BIO_PIC 22
-#define ACPI_MADT_TYPE_LPC_PIC 23
-
-/* Values for Version field above */
-
-enum acpi_madt_core_pic_version {
- ACPI_MADT_CORE_PIC_VERSION_NONE = 0,
- ACPI_MADT_CORE_PIC_VERSION_V1 = 1,
- ACPI_MADT_CORE_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */
-};
-
-enum acpi_madt_lio_pic_version {
- ACPI_MADT_LIO_PIC_VERSION_NONE = 0,
- ACPI_MADT_LIO_PIC_VERSION_V1 = 1,
- ACPI_MADT_LIO_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */
-};
-
-enum acpi_madt_eio_pic_version {
- ACPI_MADT_EIO_PIC_VERSION_NONE = 0,
- ACPI_MADT_EIO_PIC_VERSION_V1 = 1,
- ACPI_MADT_EIO_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */
-};
-
-enum acpi_madt_ht_pic_version {
- ACPI_MADT_HT_PIC_VERSION_NONE = 0,
- ACPI_MADT_HT_PIC_VERSION_V1 = 1,
- ACPI_MADT_HT_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */
-};
-
-enum acpi_madt_bio_pic_version {
- ACPI_MADT_BIO_PIC_VERSION_NONE = 0,
- ACPI_MADT_BIO_PIC_VERSION_V1 = 1,
- ACPI_MADT_BIO_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */
-};
-
-enum acpi_madt_msi_pic_version {
- ACPI_MADT_MSI_PIC_VERSION_NONE = 0,
- ACPI_MADT_MSI_PIC_VERSION_V1 = 1,
- ACPI_MADT_MSI_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */
-};
-
-enum acpi_madt_lpc_pic_version {
- ACPI_MADT_LPC_PIC_VERSION_NONE = 0,
- ACPI_MADT_LPC_PIC_VERSION_V1 = 1,
- ACPI_MADT_LPC_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */
-};
-
-#pragma pack(1)
-
-/* Core Interrupt Controller */
-
-struct acpi_madt_core_pic {
- struct acpi_subtable_header header;
- u8 version;
- u32 processor_id;
- u32 core_id;
- u32 flags;
-};
-
-/* Legacy I/O Interrupt Controller */
-
-struct acpi_madt_lio_pic {
- struct acpi_subtable_header header;
- u8 version;
- u64 address;
- u16 size;
- u8 cascade[2];
- u32 cascade_map[2];
-};
-
-/* Extend I/O Interrupt Controller */
-
-struct acpi_madt_eio_pic {
- struct acpi_subtable_header header;
- u8 version;
- u8 cascade;
- u8 node;
- u64 node_map;
-};
-
-/* HT Interrupt Controller */
-
-struct acpi_madt_ht_pic {
- struct acpi_subtable_header header;
- u8 version;
- u64 address;
- u16 size;
- u8 cascade[8];
-};
-
-/* Bridge I/O Interrupt Controller */
-
-struct acpi_madt_bio_pic {
- struct acpi_subtable_header header;
- u8 version;
- u64 address;
- u16 size;
- u16 id;
- u16 gsi_base;
-};
-
-/* MSI Interrupt Controller */
-
-struct acpi_madt_msi_pic {
- struct acpi_subtable_header header;
- u8 version;
- u64 msg_address;
- u32 start;
- u32 count;
-};
-
-/* LPC Interrupt Controller */
-
-struct acpi_madt_lpc_pic {
- struct acpi_subtable_header header;
- u8 version;
- u64 address;
- u16 size;
- u8 cascade;
-};
-
-#pragma pack()
-
-#endif
-
#endif /* !CONFIG_ACPI */
#define ACPI_TABLE_UPGRADE_MAX_PHYS ARCH_LOW_ADDRESS_LIMIT
diff --git a/arch/loongarch/include/asm/efi.h b/arch/loongarch/include/asm/efi.h
index 174567b00ddb..97f16e60c6ff 100644
--- a/arch/loongarch/include/asm/efi.h
+++ b/arch/loongarch/include/asm/efi.h
@@ -19,18 +19,18 @@ void efifb_setup_from_dmi(struct screen_info *si, const char *opt);
#define EFI_ALLOC_ALIGN SZ_64K
#define EFI_RT_VIRTUAL_OFFSET CSR_DMW0_BASE
-static inline struct screen_info *alloc_screen_info(void)
+static inline unsigned long efi_get_max_initrd_addr(unsigned long image_addr)
{
- return &screen_info;
+ return ULONG_MAX;
}
-static inline void free_screen_info(struct screen_info *si)
+static inline unsigned long efi_get_kimg_min_align(void)
{
+ return SZ_2M;
}
-static inline unsigned long efi_get_max_initrd_addr(unsigned long image_addr)
-{
- return ULONG_MAX;
-}
+#define EFI_KIMG_PREFERRED_ADDRESS PHYSADDR(VMLINUX_LOAD_ADDRESS)
+
+unsigned long kernel_entry_address(void);
#endif /* _ASM_LOONGARCH_EFI_H */
diff --git a/arch/loongarch/include/asm/irq.h b/arch/loongarch/include/asm/irq.h
index 5332b1433f38..a115e8999c69 100644
--- a/arch/loongarch/include/asm/irq.h
+++ b/arch/loongarch/include/asm/irq.h
@@ -93,7 +93,7 @@ int liointc_acpi_init(struct irq_domain *parent,
int eiointc_acpi_init(struct irq_domain *parent,
struct acpi_madt_eio_pic *acpi_eiointc);
-struct irq_domain *htvec_acpi_init(struct irq_domain *parent,
+int htvec_acpi_init(struct irq_domain *parent,
struct acpi_madt_ht_pic *acpi_htvec);
int pch_lpc_acpi_init(struct irq_domain *parent,
struct acpi_madt_lpc_pic *acpi_pchlpc);
diff --git a/arch/loongarch/kernel/efi.c b/arch/loongarch/kernel/efi.c
index a31329971133..d75ce73e8ff8 100644
--- a/arch/loongarch/kernel/efi.c
+++ b/arch/loongarch/kernel/efi.c
@@ -52,6 +52,27 @@ void __init efi_runtime_init(void)
set_bit(EFI_RUNTIME_SERVICES, &efi.flags);
}
+unsigned long __initdata screen_info_table = EFI_INVALID_TABLE_ADDR;
+
+static void __init init_screen_info(void)
+{
+ struct screen_info *si;
+
+ if (screen_info_table == EFI_INVALID_TABLE_ADDR)
+ return;
+
+ si = early_memremap(screen_info_table, sizeof(*si));
+ if (!si) {
+ pr_err("Could not map screen_info config table\n");
+ return;
+ }
+ screen_info = *si;
+ memset(si, 0, sizeof(*si));
+ early_memunmap(si, sizeof(*si));
+
+ memblock_reserve(screen_info.lfb_base, screen_info.lfb_size);
+}
+
void __init efi_init(void)
{
int size;
@@ -80,8 +101,7 @@ void __init efi_init(void)
set_bit(EFI_CONFIG_TABLES, &efi.flags);
- if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI)
- memblock_reserve(screen_info.lfb_base, screen_info.lfb_size);
+ init_screen_info();
if (boot_memmap == EFI_INVALID_TABLE_ADDR)
return;
diff --git a/arch/loongarch/kernel/head.S b/arch/loongarch/kernel/head.S
index 84970e266658..57bada6b4e93 100644
--- a/arch/loongarch/kernel/head.S
+++ b/arch/loongarch/kernel/head.S
@@ -25,7 +25,8 @@ _head:
.dword kernel_entry /* Kernel entry point */
.dword _end - _text /* Kernel image effective size */
.quad 0 /* Kernel image load offset from start of RAM */
- .org 0x3c /* 0x20 ~ 0x3b reserved */
+ .org 0x38 /* 0x20 ~ 0x37 reserved */
+ .long LINUX_PE_MAGIC
.long pe_header - _head /* Offset to the PE header */
pe_header:
diff --git a/arch/loongarch/kernel/image-vars.h b/arch/loongarch/kernel/image-vars.h
index 88f5d81702df..e561989d02de 100644
--- a/arch/loongarch/kernel/image-vars.h
+++ b/arch/loongarch/kernel/image-vars.h
@@ -7,15 +7,7 @@
#ifdef CONFIG_EFI_STUB
-__efistub_memcmp = memcmp;
-__efistub_memchr = memchr;
-__efistub_strcat = strcat;
__efistub_strcmp = strcmp;
-__efistub_strlen = strlen;
-__efistub_strncat = strncat;
-__efistub_strnstr = strnstr;
-__efistub_strnlen = strnlen;
-__efistub_strrchr = strrchr;
__efistub_kernel_entry = kernel_entry;
__efistub_kernel_asize = kernel_asize;
__efistub_kernel_fsize = kernel_fsize;
diff --git a/arch/loongarch/kernel/process.c b/arch/loongarch/kernel/process.c
index ddb8ba4eb399..d61c9f465b95 100644
--- a/arch/loongarch/kernel/process.c
+++ b/arch/loongarch/kernel/process.c
@@ -294,7 +294,7 @@ unsigned long stack_top(void)
unsigned long arch_align_stack(unsigned long sp)
{
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
- sp -= prandom_u32_max(PAGE_SIZE);
+ sp -= get_random_u32_below(PAGE_SIZE);
return sp & STACK_ALIGN;
}
diff --git a/arch/loongarch/kernel/vdso.c b/arch/loongarch/kernel/vdso.c
index 8c9826062652..eaebd2e0f725 100644
--- a/arch/loongarch/kernel/vdso.c
+++ b/arch/loongarch/kernel/vdso.c
@@ -78,7 +78,7 @@ static unsigned long vdso_base(void)
unsigned long base = STACK_TOP;
if (current->flags & PF_RANDOMIZE) {
- base += prandom_u32_max(VDSO_RANDOMIZE_SIZE);
+ base += get_random_u32_below(VDSO_RANDOMIZE_SIZE);
base = PAGE_ALIGN(base);
}
diff --git a/arch/m68k/configs/amiga_defconfig b/arch/m68k/configs/amiga_defconfig
index e2038d9499e4..7b49fe6f7cb3 100644
--- a/arch/m68k/configs/amiga_defconfig
+++ b/arch/m68k/configs/amiga_defconfig
@@ -562,29 +562,10 @@ CONFIG_CRYPTO_ECDSA=m
CONFIG_CRYPTO_ECRDSA=m
CONFIG_CRYPTO_SM2=m
CONFIG_CRYPTO_CURVE25519=m
-CONFIG_CRYPTO_CHACHA20POLY1305=m
-CONFIG_CRYPTO_AEGIS128=m
-CONFIG_CRYPTO_CFB=m
-CONFIG_CRYPTO_CTS=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_OFB=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_KEYWRAP=m
-CONFIG_CRYPTO_ADIANTUM=m
-CONFIG_CRYPTO_HCTR2=m
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_SHA3=m
-CONFIG_CRYPTO_SM3_GENERIC=m
-CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -593,11 +574,30 @@ CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SEED=m
-CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_SM4_GENERIC=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_CFB=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_HCTR2=m
+CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_SM3_GENERIC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
diff --git a/arch/m68k/configs/apollo_defconfig b/arch/m68k/configs/apollo_defconfig
index ddd201259e43..656a06d97d4c 100644
--- a/arch/m68k/configs/apollo_defconfig
+++ b/arch/m68k/configs/apollo_defconfig
@@ -519,29 +519,10 @@ CONFIG_CRYPTO_ECDSA=m
CONFIG_CRYPTO_ECRDSA=m
CONFIG_CRYPTO_SM2=m
CONFIG_CRYPTO_CURVE25519=m
-CONFIG_CRYPTO_CHACHA20POLY1305=m
-CONFIG_CRYPTO_AEGIS128=m
-CONFIG_CRYPTO_CFB=m
-CONFIG_CRYPTO_CTS=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_OFB=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_KEYWRAP=m
-CONFIG_CRYPTO_ADIANTUM=m
-CONFIG_CRYPTO_HCTR2=m
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_SHA3=m
-CONFIG_CRYPTO_SM3_GENERIC=m
-CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -550,11 +531,30 @@ CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SEED=m
-CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_SM4_GENERIC=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_CFB=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_HCTR2=m
+CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_SM3_GENERIC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
diff --git a/arch/m68k/configs/atari_defconfig b/arch/m68k/configs/atari_defconfig
index d9f783707387..8972b822875d 100644
--- a/arch/m68k/configs/atari_defconfig
+++ b/arch/m68k/configs/atari_defconfig
@@ -539,29 +539,10 @@ CONFIG_CRYPTO_ECDSA=m
CONFIG_CRYPTO_ECRDSA=m
CONFIG_CRYPTO_SM2=m
CONFIG_CRYPTO_CURVE25519=m
-CONFIG_CRYPTO_CHACHA20POLY1305=m
-CONFIG_CRYPTO_AEGIS128=m
-CONFIG_CRYPTO_CFB=m
-CONFIG_CRYPTO_CTS=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_OFB=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_KEYWRAP=m
-CONFIG_CRYPTO_ADIANTUM=m
-CONFIG_CRYPTO_HCTR2=m
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_SHA3=m
-CONFIG_CRYPTO_SM3_GENERIC=m
-CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -570,11 +551,30 @@ CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SEED=m
-CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_SM4_GENERIC=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_CFB=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_HCTR2=m
+CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_SM3_GENERIC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
diff --git a/arch/m68k/configs/bvme6000_defconfig b/arch/m68k/configs/bvme6000_defconfig
index 68957c6bcff1..7b86e1277a1a 100644
--- a/arch/m68k/configs/bvme6000_defconfig
+++ b/arch/m68k/configs/bvme6000_defconfig
@@ -511,29 +511,10 @@ CONFIG_CRYPTO_ECDSA=m
CONFIG_CRYPTO_ECRDSA=m
CONFIG_CRYPTO_SM2=m
CONFIG_CRYPTO_CURVE25519=m
-CONFIG_CRYPTO_CHACHA20POLY1305=m
-CONFIG_CRYPTO_AEGIS128=m
-CONFIG_CRYPTO_CFB=m
-CONFIG_CRYPTO_CTS=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_OFB=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_KEYWRAP=m
-CONFIG_CRYPTO_ADIANTUM=m
-CONFIG_CRYPTO_HCTR2=m
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_SHA3=m
-CONFIG_CRYPTO_SM3_GENERIC=m
-CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -542,11 +523,30 @@ CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SEED=m
-CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_SM4_GENERIC=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_CFB=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_HCTR2=m
+CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_SM3_GENERIC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
diff --git a/arch/m68k/configs/hp300_defconfig b/arch/m68k/configs/hp300_defconfig
index 825c6a02fa9d..d0d5c0a9aee6 100644
--- a/arch/m68k/configs/hp300_defconfig
+++ b/arch/m68k/configs/hp300_defconfig
@@ -521,29 +521,10 @@ CONFIG_CRYPTO_ECDSA=m
CONFIG_CRYPTO_ECRDSA=m
CONFIG_CRYPTO_SM2=m
CONFIG_CRYPTO_CURVE25519=m
-CONFIG_CRYPTO_CHACHA20POLY1305=m
-CONFIG_CRYPTO_AEGIS128=m
-CONFIG_CRYPTO_CFB=m
-CONFIG_CRYPTO_CTS=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_OFB=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_KEYWRAP=m
-CONFIG_CRYPTO_ADIANTUM=m
-CONFIG_CRYPTO_HCTR2=m
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_SHA3=m
-CONFIG_CRYPTO_SM3_GENERIC=m
-CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -552,11 +533,30 @@ CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SEED=m
-CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_SM4_GENERIC=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_CFB=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_HCTR2=m
+CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_SM3_GENERIC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
diff --git a/arch/m68k/configs/mac_defconfig b/arch/m68k/configs/mac_defconfig
index 17f64c562bf1..ac1d0c86b6ff 100644
--- a/arch/m68k/configs/mac_defconfig
+++ b/arch/m68k/configs/mac_defconfig
@@ -541,29 +541,10 @@ CONFIG_CRYPTO_ECDSA=m
CONFIG_CRYPTO_ECRDSA=m
CONFIG_CRYPTO_SM2=m
CONFIG_CRYPTO_CURVE25519=m
-CONFIG_CRYPTO_CHACHA20POLY1305=m
-CONFIG_CRYPTO_AEGIS128=m
-CONFIG_CRYPTO_CFB=m
-CONFIG_CRYPTO_CTS=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_OFB=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_KEYWRAP=m
-CONFIG_CRYPTO_ADIANTUM=m
-CONFIG_CRYPTO_HCTR2=m
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_SHA3=m
-CONFIG_CRYPTO_SM3_GENERIC=m
-CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -572,11 +553,30 @@ CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SEED=m
-CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_SM4_GENERIC=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_CFB=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_HCTR2=m
+CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_SM3_GENERIC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig
index f5f4c572b694..c5f7603c9830 100644
--- a/arch/m68k/configs/multi_defconfig
+++ b/arch/m68k/configs/multi_defconfig
@@ -627,29 +627,10 @@ CONFIG_CRYPTO_ECDSA=m
CONFIG_CRYPTO_ECRDSA=m
CONFIG_CRYPTO_SM2=m
CONFIG_CRYPTO_CURVE25519=m
-CONFIG_CRYPTO_CHACHA20POLY1305=m
-CONFIG_CRYPTO_AEGIS128=m
-CONFIG_CRYPTO_CFB=m
-CONFIG_CRYPTO_CTS=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_OFB=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_KEYWRAP=m
-CONFIG_CRYPTO_ADIANTUM=m
-CONFIG_CRYPTO_HCTR2=m
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_SHA3=m
-CONFIG_CRYPTO_SM3_GENERIC=m
-CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -658,11 +639,30 @@ CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SEED=m
-CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_SM4_GENERIC=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_CFB=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_HCTR2=m
+CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_SM3_GENERIC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig
index b4a0bbef7e39..26f5b59e3bc0 100644
--- a/arch/m68k/configs/mvme147_defconfig
+++ b/arch/m68k/configs/mvme147_defconfig
@@ -510,29 +510,10 @@ CONFIG_CRYPTO_ECDSA=m
CONFIG_CRYPTO_ECRDSA=m
CONFIG_CRYPTO_SM2=m
CONFIG_CRYPTO_CURVE25519=m
-CONFIG_CRYPTO_CHACHA20POLY1305=m
-CONFIG_CRYPTO_AEGIS128=m
-CONFIG_CRYPTO_CFB=m
-CONFIG_CRYPTO_CTS=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_OFB=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_KEYWRAP=m
-CONFIG_CRYPTO_ADIANTUM=m
-CONFIG_CRYPTO_HCTR2=m
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_SHA3=m
-CONFIG_CRYPTO_SM3_GENERIC=m
-CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -541,11 +522,30 @@ CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SEED=m
-CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_SM4_GENERIC=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_CFB=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_HCTR2=m
+CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_SM3_GENERIC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig
index c6a6d5926793..3045c7f0bde3 100644
--- a/arch/m68k/configs/mvme16x_defconfig
+++ b/arch/m68k/configs/mvme16x_defconfig
@@ -511,29 +511,10 @@ CONFIG_CRYPTO_ECDSA=m
CONFIG_CRYPTO_ECRDSA=m
CONFIG_CRYPTO_SM2=m
CONFIG_CRYPTO_CURVE25519=m
-CONFIG_CRYPTO_CHACHA20POLY1305=m
-CONFIG_CRYPTO_AEGIS128=m
-CONFIG_CRYPTO_CFB=m
-CONFIG_CRYPTO_CTS=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_OFB=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_KEYWRAP=m
-CONFIG_CRYPTO_ADIANTUM=m
-CONFIG_CRYPTO_HCTR2=m
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_SHA3=m
-CONFIG_CRYPTO_SM3_GENERIC=m
-CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -542,11 +523,30 @@ CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SEED=m
-CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_SM4_GENERIC=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_CFB=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_HCTR2=m
+CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_SM3_GENERIC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
diff --git a/arch/m68k/configs/q40_defconfig b/arch/m68k/configs/q40_defconfig
index 49c9c89f0caf..f2a486be651b 100644
--- a/arch/m68k/configs/q40_defconfig
+++ b/arch/m68k/configs/q40_defconfig
@@ -528,29 +528,10 @@ CONFIG_CRYPTO_ECDSA=m
CONFIG_CRYPTO_ECRDSA=m
CONFIG_CRYPTO_SM2=m
CONFIG_CRYPTO_CURVE25519=m
-CONFIG_CRYPTO_CHACHA20POLY1305=m
-CONFIG_CRYPTO_AEGIS128=m
-CONFIG_CRYPTO_CFB=m
-CONFIG_CRYPTO_CTS=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_OFB=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_KEYWRAP=m
-CONFIG_CRYPTO_ADIANTUM=m
-CONFIG_CRYPTO_HCTR2=m
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_SHA3=m
-CONFIG_CRYPTO_SM3_GENERIC=m
-CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -559,11 +540,30 @@ CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SEED=m
-CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_SM4_GENERIC=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_CFB=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_HCTR2=m
+CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_SM3_GENERIC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
diff --git a/arch/m68k/configs/sun3_defconfig b/arch/m68k/configs/sun3_defconfig
index 9b44eeb9c07f..8a7db7be10c0 100644
--- a/arch/m68k/configs/sun3_defconfig
+++ b/arch/m68k/configs/sun3_defconfig
@@ -510,29 +510,10 @@ CONFIG_CRYPTO_ECDSA=m
CONFIG_CRYPTO_ECRDSA=m
CONFIG_CRYPTO_SM2=m
CONFIG_CRYPTO_CURVE25519=m
-CONFIG_CRYPTO_CHACHA20POLY1305=m
-CONFIG_CRYPTO_AEGIS128=m
-CONFIG_CRYPTO_CFB=m
-CONFIG_CRYPTO_CTS=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_OFB=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_KEYWRAP=m
-CONFIG_CRYPTO_ADIANTUM=m
-CONFIG_CRYPTO_HCTR2=m
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_SHA3=m
-CONFIG_CRYPTO_SM3_GENERIC=m
-CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -541,11 +522,30 @@ CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SEED=m
-CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_SM4_GENERIC=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_CFB=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_HCTR2=m
+CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_SM3_GENERIC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
diff --git a/arch/m68k/configs/sun3x_defconfig b/arch/m68k/configs/sun3x_defconfig
index d2ffb0a65b44..7ed49ee0b9e0 100644
--- a/arch/m68k/configs/sun3x_defconfig
+++ b/arch/m68k/configs/sun3x_defconfig
@@ -509,29 +509,10 @@ CONFIG_CRYPTO_ECDSA=m
CONFIG_CRYPTO_ECRDSA=m
CONFIG_CRYPTO_SM2=m
CONFIG_CRYPTO_CURVE25519=m
-CONFIG_CRYPTO_CHACHA20POLY1305=m
-CONFIG_CRYPTO_AEGIS128=m
-CONFIG_CRYPTO_CFB=m
-CONFIG_CRYPTO_CTS=m
-CONFIG_CRYPTO_LRW=m
-CONFIG_CRYPTO_OFB=m
-CONFIG_CRYPTO_PCBC=m
-CONFIG_CRYPTO_XTS=m
-CONFIG_CRYPTO_KEYWRAP=m
-CONFIG_CRYPTO_ADIANTUM=m
-CONFIG_CRYPTO_HCTR2=m
-CONFIG_CRYPTO_XCBC=m
-CONFIG_CRYPTO_VMAC=m
-CONFIG_CRYPTO_MD4=m
-CONFIG_CRYPTO_MICHAEL_MIC=m
-CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_SHA3=m
-CONFIG_CRYPTO_SM3_GENERIC=m
-CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_TI=m
CONFIG_CRYPTO_ANUBIS=m
-CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_CAMELLIA=m
CONFIG_CRYPTO_CAST5=m
@@ -540,11 +521,30 @@ CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_FCRYPT=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SEED=m
-CONFIG_CRYPTO_ARIA=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_SM4_GENERIC=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_ADIANTUM=m
+CONFIG_CRYPTO_ARC4=m
+CONFIG_CRYPTO_CFB=m
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_HCTR2=m
+CONFIG_CRYPTO_KEYWRAP=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_OFB=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+CONFIG_CRYPTO_AEGIS128=m
+CONFIG_CRYPTO_CHACHA20POLY1305=m
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_SHA3=m
+CONFIG_CRYPTO_SM3_GENERIC=m
+CONFIG_CRYPTO_VMAC=m
+CONFIG_CRYPTO_WP512=m
+CONFIG_CRYPTO_XCBC=m
CONFIG_CRYPTO_LZO=m
CONFIG_CRYPTO_842=m
CONFIG_CRYPTO_LZ4=m
diff --git a/arch/m68k/emu/nfcon.c b/arch/m68k/emu/nfcon.c
index 557d60867f98..6fdc13610565 100644
--- a/arch/m68k/emu/nfcon.c
+++ b/arch/m68k/emu/nfcon.c
@@ -49,7 +49,7 @@ static void nfcon_write(struct console *con, const char *str,
static struct tty_driver *nfcon_device(struct console *con, int *index)
{
*index = 0;
- return (con->flags & CON_ENABLED) ? nfcon_tty_driver : NULL;
+ return console_is_registered(con) ? nfcon_tty_driver : NULL;
}
static struct console nf_console = {
@@ -107,6 +107,11 @@ static int __init nf_debug_setup(char *arg)
stderr_id = nf_get_id("NF_STDERR");
if (stderr_id) {
+ /*
+ * The console will be enabled when debug=nfcon is specified
+ * as a kernel parameter. Since this is a non-standard way
+ * of enabling consoles, it must be explicitly enabled.
+ */
nf_console.flags |= CON_ENABLED;
register_console(&nf_console);
}
@@ -151,7 +156,7 @@ static int __init nfcon_init(void)
nfcon_tty_driver = driver;
- if (!(nf_console.flags & CON_ENABLED))
+ if (!console_is_registered(&nf_console))
register_console(&nf_console);
return 0;
diff --git a/arch/m68k/include/asm/mac_via.h b/arch/m68k/include/asm/mac_via.h
index 1149251ea58d..a9ef1e9ba6c4 100644
--- a/arch/m68k/include/asm/mac_via.h
+++ b/arch/m68k/include/asm/mac_via.h
@@ -267,14 +267,6 @@ extern void via1_irq(struct irq_desc *desc);
extern void via1_set_head(int);
extern int via2_scsi_drq_pending(void);
-static inline int rbv_set_video_bpp(int bpp)
-{
- char val = (bpp==1)?0:(bpp==2)?1:(bpp==4)?2:(bpp==8)?3:-1;
- if (!rbv_present || val<0) return -1;
- via2[rMonP] = (via2[rMonP] & ~RBV_DEPTH) | val;
- return 0;
-}
-
#endif /* __ASSEMBLY__ */
#endif /* _ASM_MAC_VIA_H_ */
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index 2cb4a61bcfac..e06ce147c0b7 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -32,6 +32,7 @@
#include <linux/rcupdate.h>
#include <linux/syscalls.h>
#include <linux/uaccess.h>
+#include <linux/elfcore.h>
#include <asm/traps.h>
#include <asm/machdep.h>
@@ -213,7 +214,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
}
/* Fill in the fpu structure for a core dump. */
-int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
+int elf_core_copy_task_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
{
if (FPU_IS_EMU) {
int i;
@@ -262,7 +263,6 @@ int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
return 1;
}
-EXPORT_SYMBOL(dump_fpu);
unsigned long __get_wchan(struct task_struct *p)
{
diff --git a/arch/m68k/mac/misc.c b/arch/m68k/mac/misc.c
index 4fab34791758..c7cb29f0ff01 100644
--- a/arch/m68k/mac/misc.c
+++ b/arch/m68k/mac/misc.c
@@ -126,7 +126,7 @@ static void via_rtc_send(__u8 data)
reg = via1[vBufB] & ~(VIA1B_vRTCClk | VIA1B_vRTCData);
- /* The bits of the byte go in in MSB order */
+ /* The bits of the byte go into the RTC in MSB order */
for (i = 0 ; i < 8 ; i++) {
bit = data & 0x80? 1 : 0;
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index 4ebb56d6d959..cc88af6fa7a4 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -215,11 +215,3 @@ config MB_MANAGER
Say N here unless you know what you are doing.
endmenu
-
-menu "Bus Options"
-
-config PCI_XILINX
- bool "Xilinx PCI host bridge support"
- depends on PCI
-
-endmenu
diff --git a/arch/microblaze/configs/mmu_defconfig b/arch/microblaze/configs/mmu_defconfig
index 8150daf04a76..756feb9369a6 100644
--- a/arch/microblaze/configs/mmu_defconfig
+++ b/arch/microblaze/configs/mmu_defconfig
@@ -19,7 +19,6 @@ CONFIG_HZ_100=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE_FORCE=y
CONFIG_HIGHMEM=y
-CONFIG_PCI_XILINX=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
# CONFIG_BLK_DEV_BSG is not set
diff --git a/arch/microblaze/include/asm/pci-bridge.h b/arch/microblaze/include/asm/pci-bridge.h
index 171b40a2d905..be5f504bead4 100644
--- a/arch/microblaze/include/asm/pci-bridge.h
+++ b/arch/microblaze/include/asm/pci-bridge.h
@@ -25,75 +25,17 @@ static inline int pcibios_vaddr_is_ioport(void __iomem *address)
*/
struct pci_controller {
struct pci_bus *bus;
- char is_dynamic;
- struct device_node *dn;
struct list_head list_node;
- struct device *parent;
-
- int first_busno;
- int last_busno;
-
- int self_busno;
void __iomem *io_base_virt;
- resource_size_t io_base_phys;
-
- resource_size_t pci_io_size;
-
- /* Some machines (PReP) have a non 1:1 mapping of
- * the PCI memory space in the CPU bus space
- */
- resource_size_t pci_mem_offset;
-
- /* Some machines have a special region to forward the ISA
- * "memory" cycles such as VGA memory regions. Left to 0
- * if unsupported
- */
- resource_size_t isa_mem_phys;
- resource_size_t isa_mem_size;
-
- struct pci_ops *ops;
- unsigned int __iomem *cfg_addr;
- void __iomem *cfg_data;
-
- /*
- * Used for variants of PCI indirect handling and possible quirks:
- * SET_CFG_TYPE - used on 4xx or any PHB that does explicit type0/1
- * EXT_REG - provides access to PCI-e extended registers
- * SURPRESS_PRIMARY_BUS - we suppress the setting of PCI_PRIMARY_BUS
- * on Freescale PCI-e controllers since they used the PCI_PRIMARY_BUS
- * to determine which bus number to match on when generating type0
- * config cycles
- * NO_PCIE_LINK - the Freescale PCI-e controllers have issues with
- * hanging if we don't have link and try to do config cycles to
- * anything but the PHB. Only allow talking to the PHB if this is
- * set.
- * BIG_ENDIAN - cfg_addr is a big endian register
- * BROKEN_MRM - the 440EPx/GRx chips have an errata that causes hangs
- * on the PLB4. Effectively disable MRM commands by setting this.
- */
-#define INDIRECT_TYPE_SET_CFG_TYPE 0x00000001
-#define INDIRECT_TYPE_EXT_REG 0x00000002
-#define INDIRECT_TYPE_SURPRESS_PRIMARY_BUS 0x00000004
-#define INDIRECT_TYPE_NO_PCIE_LINK 0x00000008
-#define INDIRECT_TYPE_BIG_ENDIAN 0x00000010
-#define INDIRECT_TYPE_BROKEN_MRM 0x00000020
- u32 indirect_type;
/* Currently, we limit ourselves to 1 IO range and 3 mem
* ranges since the common pci_bus structure can't handle more
*/
struct resource io_resource;
- struct resource mem_resources[3];
- int global_number; /* PCI domain number */
};
#ifdef CONFIG_PCI
-static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
-{
- return bus->sysdata;
-}
-
static inline int isa_vaddr_is_ioport(void __iomem *address)
{
/* No specific ISA handling on ppc32 at this stage, it
@@ -103,39 +45,5 @@ static inline int isa_vaddr_is_ioport(void __iomem *address)
}
#endif /* CONFIG_PCI */
-/* These are used for config access before all the PCI probing
- has been done. */
-extern int early_read_config_byte(struct pci_controller *hose, int bus,
- int dev_fn, int where, u8 *val);
-extern int early_read_config_word(struct pci_controller *hose, int bus,
- int dev_fn, int where, u16 *val);
-extern int early_read_config_dword(struct pci_controller *hose, int bus,
- int dev_fn, int where, u32 *val);
-extern int early_write_config_byte(struct pci_controller *hose, int bus,
- int dev_fn, int where, u8 val);
-extern int early_write_config_word(struct pci_controller *hose, int bus,
- int dev_fn, int where, u16 val);
-extern int early_write_config_dword(struct pci_controller *hose, int bus,
- int dev_fn, int where, u32 val);
-
-extern int early_find_capability(struct pci_controller *hose, int bus,
- int dev_fn, int cap);
-
-extern void setup_indirect_pci(struct pci_controller *hose,
- resource_size_t cfg_addr,
- resource_size_t cfg_data, u32 flags);
-
-/* Get the PCI host controller for an OF device */
-extern struct pci_controller *pci_find_hose_for_OF_device(
- struct device_node *node);
-
-/* Fill up host controller resources from the OF node */
-extern void pci_process_bridge_OF_ranges(struct pci_controller *hose,
- struct device_node *dev, int primary);
-
-/* Allocate & free a PCI host bridge structure */
-extern struct pci_controller *pcibios_alloc_controller(struct device_node *dev);
-extern void pcibios_free_controller(struct pci_controller *phb);
-
#endif /* __KERNEL__ */
#endif /* _ASM_MICROBLAZE_PCI_BRIDGE_H */
diff --git a/arch/microblaze/include/asm/pci.h b/arch/microblaze/include/asm/pci.h
index d90528064604..91f1f71c266a 100644
--- a/arch/microblaze/include/asm/pci.h
+++ b/arch/microblaze/include/asm/pci.h
@@ -21,15 +21,6 @@
#define PCIBIOS_MIN_IO 0x1000
#define PCIBIOS_MIN_MEM 0x10000000
-/* Values for the `which' argument to sys_pciconfig_iobase syscall. */
-#define IOBASE_BRIDGE_NUMBER 0
-#define IOBASE_MEMORY 1
-#define IOBASE_IO 2
-#define IOBASE_ISA_IO 3
-#define IOBASE_ISA_MEM 4
-
-#define pcibios_scan_all_fns(a, b) 0
-
/*
* Set this to 1 if you want the kernel to re-assign all PCI
* bus numbers (don't do that on ppc64 yet !)
@@ -41,33 +32,13 @@ extern int pci_domain_nr(struct pci_bus *bus);
/* Decide whether to display the domain number in /proc */
extern int pci_proc_domain(struct pci_bus *bus);
-struct vm_area_struct;
-
/* Tell PCI code what kind of PCI resource mappings we support */
#define HAVE_PCI_MMAP 1
#define ARCH_GENERIC_PCI_MMAP_RESOURCE 1
-#define arch_can_pci_mmap_io() 1
-
-extern int pci_legacy_read(struct pci_bus *bus, loff_t port, u32 *val,
- size_t count);
-extern int pci_legacy_write(struct pci_bus *bus, loff_t port, u32 val,
- size_t count);
-extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
- struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state);
-
-#define HAVE_PCI_LEGACY 1
-
-extern void pcibios_resource_survey(void);
struct file;
-/* This part of code was originally in xilinx-pci.h */
-#ifdef CONFIG_PCI_XILINX
-extern void __init xilinx_pci_init(void);
-#else
static inline void __init xilinx_pci_init(void) { return; }
-#endif
#endif /* __KERNEL__ */
#endif /* __ASM_MICROBLAZE_PCI_H */
diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c
index 3c6241bcaea8..1f802aab2b96 100644
--- a/arch/microblaze/kernel/process.c
+++ b/arch/microblaze/kernel/process.c
@@ -133,7 +133,7 @@ void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp)
/*
* Set up a thread for executing a new program
*/
-int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpregs)
+int elf_core_copy_task_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
{
return 0; /* MicroBlaze has no separate FPU registers */
}
diff --git a/arch/microblaze/pci/Makefile b/arch/microblaze/pci/Makefile
index 0251c20e1d62..f8267d20e067 100644
--- a/arch/microblaze/pci/Makefile
+++ b/arch/microblaze/pci/Makefile
@@ -3,5 +3,4 @@
# Makefile
#
-obj-$(CONFIG_PCI) += pci-common.o indirect_pci.o iomap.o
-obj-$(CONFIG_PCI_XILINX) += xilinx_pci.o
+obj-$(CONFIG_PCI) += iomap.o
diff --git a/arch/microblaze/pci/indirect_pci.c b/arch/microblaze/pci/indirect_pci.c
deleted file mode 100644
index 1caf7d3e0eef..000000000000
--- a/arch/microblaze/pci/indirect_pci.c
+++ /dev/null
@@ -1,158 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Support for indirect PCI bridges.
- *
- * Copyright (C) 1998 Gabriel Paubert.
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/delay.h>
-#include <linux/string.h>
-#include <linux/init.h>
-
-#include <linux/io.h>
-#include <asm/pci-bridge.h>
-
-static int
-indirect_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 *val)
-{
- struct pci_controller *hose = pci_bus_to_host(bus);
- volatile void __iomem *cfg_data;
- u8 cfg_type = 0;
- u32 bus_no, reg;
-
- if (hose->indirect_type & INDIRECT_TYPE_NO_PCIE_LINK) {
- if (bus->number != hose->first_busno)
- return PCIBIOS_DEVICE_NOT_FOUND;
- if (devfn != 0)
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
-
- if (hose->indirect_type & INDIRECT_TYPE_SET_CFG_TYPE)
- if (bus->number != hose->first_busno)
- cfg_type = 1;
-
- bus_no = (bus->number == hose->first_busno) ?
- hose->self_busno : bus->number;
-
- if (hose->indirect_type & INDIRECT_TYPE_EXT_REG)
- reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
- else
- reg = offset & 0xfc; /* Only 3 bits for function */
-
- if (hose->indirect_type & INDIRECT_TYPE_BIG_ENDIAN)
- out_be32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
- (devfn << 8) | reg | cfg_type));
- else
- out_le32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
- (devfn << 8) | reg | cfg_type));
-
- /*
- * Note: the caller has already checked that offset is
- * suitably aligned and that len is 1, 2 or 4.
- */
- cfg_data = hose->cfg_data + (offset & 3); /* Only 3 bits for function */
- switch (len) {
- case 1:
- *val = in_8(cfg_data);
- break;
- case 2:
- *val = in_le16(cfg_data);
- break;
- default:
- *val = in_le32(cfg_data);
- break;
- }
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-indirect_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 val)
-{
- struct pci_controller *hose = pci_bus_to_host(bus);
- volatile void __iomem *cfg_data;
- u8 cfg_type = 0;
- u32 bus_no, reg;
-
- if (hose->indirect_type & INDIRECT_TYPE_NO_PCIE_LINK) {
- if (bus->number != hose->first_busno)
- return PCIBIOS_DEVICE_NOT_FOUND;
- if (devfn != 0)
- return PCIBIOS_DEVICE_NOT_FOUND;
- }
-
- if (hose->indirect_type & INDIRECT_TYPE_SET_CFG_TYPE)
- if (bus->number != hose->first_busno)
- cfg_type = 1;
-
- bus_no = (bus->number == hose->first_busno) ?
- hose->self_busno : bus->number;
-
- if (hose->indirect_type & INDIRECT_TYPE_EXT_REG)
- reg = ((offset & 0xf00) << 16) | (offset & 0xfc);
- else
- reg = offset & 0xfc;
-
- if (hose->indirect_type & INDIRECT_TYPE_BIG_ENDIAN)
- out_be32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
- (devfn << 8) | reg | cfg_type));
- else
- out_le32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
- (devfn << 8) | reg | cfg_type));
-
- /* suppress setting of PCI_PRIMARY_BUS */
- if (hose->indirect_type & INDIRECT_TYPE_SURPRESS_PRIMARY_BUS)
- if ((offset == PCI_PRIMARY_BUS) &&
- (bus->number == hose->first_busno))
- val &= 0xffffff00;
-
- /* Workaround for PCI_28 Errata in 440EPx/GRx */
- if ((hose->indirect_type & INDIRECT_TYPE_BROKEN_MRM) &&
- offset == PCI_CACHE_LINE_SIZE) {
- val = 0;
- }
-
- /*
- * Note: the caller has already checked that offset is
- * suitably aligned and that len is 1, 2 or 4.
- */
- cfg_data = hose->cfg_data + (offset & 3);
- switch (len) {
- case 1:
- out_8(cfg_data, val);
- break;
- case 2:
- out_le16(cfg_data, val);
- break;
- default:
- out_le32(cfg_data, val);
- break;
- }
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops indirect_pci_ops = {
- .read = indirect_read_config,
- .write = indirect_write_config,
-};
-
-void __init
-setup_indirect_pci(struct pci_controller *hose,
- resource_size_t cfg_addr,
- resource_size_t cfg_data, u32 flags)
-{
- resource_size_t base = cfg_addr & PAGE_MASK;
- void __iomem *mbase;
-
- mbase = ioremap(base, PAGE_SIZE);
- hose->cfg_addr = mbase + (cfg_addr & ~PAGE_MASK);
- if ((cfg_data & PAGE_MASK) != base)
- mbase = ioremap(cfg_data & PAGE_MASK, PAGE_SIZE);
- hose->cfg_data = mbase + (cfg_data & ~PAGE_MASK);
- hose->ops = &indirect_pci_ops;
- hose->indirect_type = flags;
-}
diff --git a/arch/microblaze/pci/iomap.c b/arch/microblaze/pci/iomap.c
index bde74af4c1cd..b2ee8ace9b6e 100644
--- a/arch/microblaze/pci/iomap.c
+++ b/arch/microblaze/pci/iomap.c
@@ -11,6 +11,42 @@
#include <linux/io.h>
#include <asm/pci-bridge.h>
+static DEFINE_SPINLOCK(hose_spinlock);
+LIST_HEAD(hose_list);
+
+unsigned long isa_io_base;
+EXPORT_SYMBOL(isa_io_base);
+
+static resource_size_t pcibios_io_size(const struct pci_controller *hose)
+{
+ return resource_size(&hose->io_resource);
+}
+
+int pcibios_vaddr_is_ioport(void __iomem *address)
+{
+ int ret = 0;
+ struct pci_controller *hose;
+ resource_size_t size;
+
+ spin_lock(&hose_spinlock);
+ list_for_each_entry(hose, &hose_list, list_node) {
+ size = pcibios_io_size(hose);
+ if (address >= hose->io_base_virt &&
+ address < (hose->io_base_virt + size)) {
+ ret = 1;
+ break;
+ }
+ }
+ spin_unlock(&hose_spinlock);
+ return ret;
+}
+
+/* Display the domain number in /proc */
+int pci_proc_domain(struct pci_bus *bus)
+{
+ return pci_domain_nr(bus);
+}
+
void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
{
if (isa_vaddr_is_ioport(addr))
diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
deleted file mode 100644
index 33bab7eec731..000000000000
--- a/arch/microblaze/pci/pci-common.c
+++ /dev/null
@@ -1,1067 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Contains common pci routines for ALL ppc platform
- * (based on pci_32.c and pci_64.c)
- *
- * Port for PPC64 David Engebretsen, IBM Corp.
- * Contains common pci routines for ppc64 platform, pSeries and iSeries brands.
- *
- * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM
- * Rework, based on alpha PCI code.
- *
- * Common pmac/prep/chrp pci routines. -- Cort
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/memblock.h>
-#include <linux/mm.h>
-#include <linux/shmem_fs.h>
-#include <linux/list.h>
-#include <linux/syscalls.h>
-#include <linux/irq.h>
-#include <linux/vmalloc.h>
-#include <linux/slab.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/of_pci.h>
-#include <linux/export.h>
-
-#include <asm/processor.h>
-#include <linux/io.h>
-#include <asm/pci-bridge.h>
-#include <asm/byteorder.h>
-
-static DEFINE_SPINLOCK(hose_spinlock);
-LIST_HEAD(hose_list);
-
-/* XXX kill that some day ... */
-static int global_phb_number; /* Global phb counter */
-
-/* ISA Memory physical address */
-resource_size_t isa_mem_base;
-
-unsigned long isa_io_base;
-EXPORT_SYMBOL(isa_io_base);
-
-static int pci_bus_count;
-
-struct pci_controller *pcibios_alloc_controller(struct device_node *dev)
-{
- struct pci_controller *phb;
-
- phb = zalloc_maybe_bootmem(sizeof(struct pci_controller), GFP_KERNEL);
- if (!phb)
- return NULL;
- spin_lock(&hose_spinlock);
- phb->global_number = global_phb_number++;
- list_add_tail(&phb->list_node, &hose_list);
- spin_unlock(&hose_spinlock);
- phb->dn = dev;
- phb->is_dynamic = mem_init_done;
- return phb;
-}
-
-void pcibios_free_controller(struct pci_controller *phb)
-{
- spin_lock(&hose_spinlock);
- list_del(&phb->list_node);
- spin_unlock(&hose_spinlock);
-
- if (phb->is_dynamic)
- kfree(phb);
-}
-
-static resource_size_t pcibios_io_size(const struct pci_controller *hose)
-{
- return resource_size(&hose->io_resource);
-}
-
-int pcibios_vaddr_is_ioport(void __iomem *address)
-{
- int ret = 0;
- struct pci_controller *hose;
- resource_size_t size;
-
- spin_lock(&hose_spinlock);
- list_for_each_entry(hose, &hose_list, list_node) {
- size = pcibios_io_size(hose);
- if (address >= hose->io_base_virt &&
- address < (hose->io_base_virt + size)) {
- ret = 1;
- break;
- }
- }
- spin_unlock(&hose_spinlock);
- return ret;
-}
-
-unsigned long pci_address_to_pio(phys_addr_t address)
-{
- struct pci_controller *hose;
- resource_size_t size;
- unsigned long ret = ~0;
-
- spin_lock(&hose_spinlock);
- list_for_each_entry(hose, &hose_list, list_node) {
- size = pcibios_io_size(hose);
- if (address >= hose->io_base_phys &&
- address < (hose->io_base_phys + size)) {
- unsigned long base =
- (unsigned long)hose->io_base_virt - _IO_BASE;
- ret = base + (address - hose->io_base_phys);
- break;
- }
- }
- spin_unlock(&hose_spinlock);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(pci_address_to_pio);
-
-/* This routine is meant to be used early during boot, when the
- * PCI bus numbers have not yet been assigned, and you need to
- * issue PCI config cycles to an OF device.
- * It could also be used to "fix" RTAS config cycles if you want
- * to set pci_assign_all_buses to 1 and still use RTAS for PCI
- * config cycles.
- */
-struct pci_controller *pci_find_hose_for_OF_device(struct device_node *node)
-{
- while (node) {
- struct pci_controller *hose, *tmp;
- list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
- if (hose->dn == node)
- return hose;
- node = node->parent;
- }
- return NULL;
-}
-
-void pcibios_set_master(struct pci_dev *dev)
-{
- /* No special bus mastering setup handling */
-}
-
-/*
- * Platform support for /proc/bus/pci/X/Y mmap()s.
- */
-
-int pci_iobar_pfn(struct pci_dev *pdev, int bar, struct vm_area_struct *vma)
-{
- struct pci_controller *hose = pci_bus_to_host(pdev->bus);
- resource_size_t ioaddr = pci_resource_start(pdev, bar);
-
- if (!hose)
- return -EINVAL; /* should never happen */
-
- /* Convert to an offset within this PCI controller */
- ioaddr -= (unsigned long)hose->io_base_virt - _IO_BASE;
-
- vma->vm_pgoff += (ioaddr + hose->io_base_phys) >> PAGE_SHIFT;
- return 0;
-}
-
-/* This provides legacy IO read access on a bus */
-int pci_legacy_read(struct pci_bus *bus, loff_t port, u32 *val, size_t size)
-{
- unsigned long offset;
- struct pci_controller *hose = pci_bus_to_host(bus);
- struct resource *rp = &hose->io_resource;
- void __iomem *addr;
-
- /* Check if port can be supported by that bus. We only check
- * the ranges of the PHB though, not the bus itself as the rules
- * for forwarding legacy cycles down bridges are not our problem
- * here. So if the host bridge supports it, we do it.
- */
- offset = (unsigned long)hose->io_base_virt - _IO_BASE;
- offset += port;
-
- if (!(rp->flags & IORESOURCE_IO))
- return -ENXIO;
- if (offset < rp->start || (offset + size) > rp->end)
- return -ENXIO;
- addr = hose->io_base_virt + port;
-
- switch (size) {
- case 1:
- *((u8 *)val) = in_8(addr);
- return 1;
- case 2:
- if (port & 1)
- return -EINVAL;
- *((u16 *)val) = in_le16(addr);
- return 2;
- case 4:
- if (port & 3)
- return -EINVAL;
- *((u32 *)val) = in_le32(addr);
- return 4;
- }
- return -EINVAL;
-}
-
-/* This provides legacy IO write access on a bus */
-int pci_legacy_write(struct pci_bus *bus, loff_t port, u32 val, size_t size)
-{
- unsigned long offset;
- struct pci_controller *hose = pci_bus_to_host(bus);
- struct resource *rp = &hose->io_resource;
- void __iomem *addr;
-
- /* Check if port can be supported by that bus. We only check
- * the ranges of the PHB though, not the bus itself as the rules
- * for forwarding legacy cycles down bridges are not our problem
- * here. So if the host bridge supports it, we do it.
- */
- offset = (unsigned long)hose->io_base_virt - _IO_BASE;
- offset += port;
-
- if (!(rp->flags & IORESOURCE_IO))
- return -ENXIO;
- if (offset < rp->start || (offset + size) > rp->end)
- return -ENXIO;
- addr = hose->io_base_virt + port;
-
- /* WARNING: The generic code is idiotic. It gets passed a pointer
- * to what can be a 1, 2 or 4 byte quantity and always reads that
- * as a u32, which means that we have to correct the location of
- * the data read within those 32 bits for size 1 and 2
- */
- switch (size) {
- case 1:
- out_8(addr, val >> 24);
- return 1;
- case 2:
- if (port & 1)
- return -EINVAL;
- out_le16(addr, val >> 16);
- return 2;
- case 4:
- if (port & 3)
- return -EINVAL;
- out_le32(addr, val);
- return 4;
- }
- return -EINVAL;
-}
-
-/* This provides legacy IO or memory mmap access on a bus */
-int pci_mmap_legacy_page_range(struct pci_bus *bus,
- struct vm_area_struct *vma,
- enum pci_mmap_state mmap_state)
-{
- struct pci_controller *hose = pci_bus_to_host(bus);
- resource_size_t offset =
- ((resource_size_t)vma->vm_pgoff) << PAGE_SHIFT;
- resource_size_t size = vma->vm_end - vma->vm_start;
- struct resource *rp;
-
- pr_debug("pci_mmap_legacy_page_range(%04x:%02x, %s @%llx..%llx)\n",
- pci_domain_nr(bus), bus->number,
- mmap_state == pci_mmap_mem ? "MEM" : "IO",
- (unsigned long long)offset,
- (unsigned long long)(offset + size - 1));
-
- if (mmap_state == pci_mmap_mem) {
- /* Hack alert !
- *
- * Because X is lame and can fail starting if it gets an error
- * trying to mmap legacy_mem (instead of just moving on without
- * legacy memory access) we fake it here by giving it anonymous
- * memory, effectively behaving just like /dev/zero
- */
- if ((offset + size) > hose->isa_mem_size) {
- pr_debug("Process %s (pid:%d) mapped non-existing PCI",
- current->comm, current->pid);
- pr_debug("legacy memory for 0%04x:%02x\n",
- pci_domain_nr(bus), bus->number);
- if (vma->vm_flags & VM_SHARED)
- return shmem_zero_setup(vma);
- return 0;
- }
- offset += hose->isa_mem_phys;
- } else {
- unsigned long io_offset = (unsigned long)hose->io_base_virt -
- _IO_BASE;
- unsigned long roffset = offset + io_offset;
- rp = &hose->io_resource;
- if (!(rp->flags & IORESOURCE_IO))
- return -ENXIO;
- if (roffset < rp->start || (roffset + size) > rp->end)
- return -ENXIO;
- offset += hose->io_base_phys;
- }
- pr_debug(" -> mapping phys %llx\n", (unsigned long long)offset);
-
- vma->vm_pgoff = offset >> PAGE_SHIFT;
- vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
- return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
- vma->vm_end - vma->vm_start,
- vma->vm_page_prot);
-}
-
-void pci_resource_to_user(const struct pci_dev *dev, int bar,
- const struct resource *rsrc,
- resource_size_t *start, resource_size_t *end)
-{
- struct pci_bus_region region;
-
- if (rsrc->flags & IORESOURCE_IO) {
- pcibios_resource_to_bus(dev->bus, &region,
- (struct resource *) rsrc);
- *start = region.start;
- *end = region.end;
- return;
- }
-
- /* We pass a CPU physical address to userland for MMIO instead of a
- * BAR value because X is lame and expects to be able to use that
- * to pass to /dev/mem!
- *
- * That means we may have 64-bit values where some apps only expect
- * 32 (like X itself since it thinks only Sparc has 64-bit MMIO).
- */
- *start = rsrc->start;
- *end = rsrc->end;
-}
-
-/**
- * pci_process_bridge_OF_ranges - Parse PCI bridge resources from device tree
- * @hose: newly allocated pci_controller to be setup
- * @dev: device node of the host bridge
- * @primary: set if primary bus (32 bits only, soon to be deprecated)
- *
- * This function will parse the "ranges" property of a PCI host bridge device
- * node and setup the resource mapping of a pci controller based on its
- * content.
- *
- * Life would be boring if it wasn't for a few issues that we have to deal
- * with here:
- *
- * - We can only cope with one IO space range and up to 3 Memory space
- * ranges. However, some machines (thanks Apple !) tend to split their
- * space into lots of small contiguous ranges. So we have to coalesce.
- *
- * - We can only cope with all memory ranges having the same offset
- * between CPU addresses and PCI addresses. Unfortunately, some bridges
- * are setup for a large 1:1 mapping along with a small "window" which
- * maps PCI address 0 to some arbitrary high address of the CPU space in
- * order to give access to the ISA memory hole.
- * The way out of here that I've chosen for now is to always set the
- * offset based on the first resource found, then override it if we
- * have a different offset and the previous was set by an ISA hole.
- *
- * - Some busses have IO space not starting at 0, which causes trouble with
- * the way we do our IO resource renumbering. The code somewhat deals with
- * it for 64 bits but I would expect problems on 32 bits.
- *
- * - Some 32 bits platforms such as 4xx can have physical space larger than
- * 32 bits so we need to use 64 bits values for the parsing
- */
-void pci_process_bridge_OF_ranges(struct pci_controller *hose,
- struct device_node *dev, int primary)
-{
- int memno = 0, isa_hole = -1;
- unsigned long long isa_mb = 0;
- struct resource *res;
- struct of_pci_range range;
- struct of_pci_range_parser parser;
-
- pr_info("PCI host bridge %pOF %s ranges:\n",
- dev, primary ? "(primary)" : "");
-
- /* Check for ranges property */
- if (of_pci_range_parser_init(&parser, dev))
- return;
-
- pr_debug("Parsing ranges property...\n");
- for_each_of_pci_range(&parser, &range) {
- /* Read next ranges element */
-
- /* If we failed translation or got a zero-sized region
- * (some FW try to feed us with non sensical zero sized regions
- * such as power3 which look like some kind of attempt
- * at exposing the VGA memory hole)
- */
- if (range.cpu_addr == OF_BAD_ADDR || range.size == 0)
- continue;
-
- /* Act based on address space type */
- res = NULL;
- switch (range.flags & IORESOURCE_TYPE_BITS) {
- case IORESOURCE_IO:
- pr_info(" IO 0x%016llx..0x%016llx -> 0x%016llx\n",
- range.cpu_addr, range.cpu_addr + range.size - 1,
- range.pci_addr);
-
- /* We support only one IO range */
- if (hose->pci_io_size) {
- pr_info(" \\--> Skipped (too many) !\n");
- continue;
- }
- /* On 32 bits, limit I/O space to 16MB */
- if (range.size > 0x01000000)
- range.size = 0x01000000;
-
- /* 32 bits needs to map IOs here */
- hose->io_base_virt = ioremap(range.cpu_addr,
- range.size);
-
- /* Expect trouble if pci_addr is not 0 */
- if (primary)
- isa_io_base =
- (unsigned long)hose->io_base_virt;
- /* pci_io_size and io_base_phys always represent IO
- * space starting at 0 so we factor in pci_addr
- */
- hose->pci_io_size = range.pci_addr + range.size;
- hose->io_base_phys = range.cpu_addr - range.pci_addr;
-
- /* Build resource */
- res = &hose->io_resource;
- range.cpu_addr = range.pci_addr;
-
- break;
- case IORESOURCE_MEM:
- pr_info(" MEM 0x%016llx..0x%016llx -> 0x%016llx %s\n",
- range.cpu_addr, range.cpu_addr + range.size - 1,
- range.pci_addr,
- (range.flags & IORESOURCE_PREFETCH) ?
- "Prefetch" : "");
-
- /* We support only 3 memory ranges */
- if (memno >= 3) {
- pr_info(" \\--> Skipped (too many) !\n");
- continue;
- }
- /* Handles ISA memory hole space here */
- if (range.pci_addr == 0) {
- isa_mb = range.cpu_addr;
- isa_hole = memno;
- if (primary || isa_mem_base == 0)
- isa_mem_base = range.cpu_addr;
- hose->isa_mem_phys = range.cpu_addr;
- hose->isa_mem_size = range.size;
- }
-
- /* We get the PCI/Mem offset from the first range or
- * the, current one if the offset came from an ISA
- * hole. If they don't match, bugger.
- */
- if (memno == 0 ||
- (isa_hole >= 0 && range.pci_addr != 0 &&
- hose->pci_mem_offset == isa_mb))
- hose->pci_mem_offset = range.cpu_addr -
- range.pci_addr;
- else if (range.pci_addr != 0 &&
- hose->pci_mem_offset != range.cpu_addr -
- range.pci_addr) {
- pr_info(" \\--> Skipped (offset mismatch) !\n");
- continue;
- }
-
- /* Build resource */
- res = &hose->mem_resources[memno++];
- break;
- }
- if (res != NULL) {
- res->name = dev->full_name;
- res->flags = range.flags;
- res->start = range.cpu_addr;
- res->end = range.cpu_addr + range.size - 1;
- res->parent = res->child = res->sibling = NULL;
- }
- }
-
- /* If there's an ISA hole and the pci_mem_offset is -not- matching
- * the ISA hole offset, then we need to remove the ISA hole from
- * the resource list for that brige
- */
- if (isa_hole >= 0 && hose->pci_mem_offset != isa_mb) {
- unsigned int next = isa_hole + 1;
- pr_info(" Removing ISA hole at 0x%016llx\n", isa_mb);
- if (next < memno)
- memmove(&hose->mem_resources[isa_hole],
- &hose->mem_resources[next],
- sizeof(struct resource) * (memno - next));
- hose->mem_resources[--memno].flags = 0;
- }
-}
-
-/* Display the domain number in /proc */
-int pci_proc_domain(struct pci_bus *bus)
-{
- return pci_domain_nr(bus);
-}
-
-/* This header fixup will do the resource fixup for all devices as they are
- * probed, but not for bridge ranges
- */
-static void pcibios_fixup_resources(struct pci_dev *dev)
-{
- struct pci_controller *hose = pci_bus_to_host(dev->bus);
- int i;
-
- if (!hose) {
- pr_err("No host bridge for PCI dev %s !\n",
- pci_name(dev));
- return;
- }
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- struct resource *res = dev->resource + i;
- if (!res->flags)
- continue;
- if (res->start == 0) {
- pr_debug("PCI:%s Resource %d %016llx-%016llx [%x]",
- pci_name(dev), i,
- (unsigned long long)res->start,
- (unsigned long long)res->end,
- (unsigned int)res->flags);
- pr_debug("is unassigned\n");
- res->end -= res->start;
- res->start = 0;
- res->flags |= IORESOURCE_UNSET;
- continue;
- }
-
- pr_debug("PCI:%s Resource %d %016llx-%016llx [%x]\n",
- pci_name(dev), i,
- (unsigned long long)res->start,
- (unsigned long long)res->end,
- (unsigned int)res->flags);
- }
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_resources);
-
-int pcibios_device_add(struct pci_dev *dev)
-{
- dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
-
- return 0;
-}
-
-/*
- * Reparent resource children of pr that conflict with res
- * under res, and make res replace those children.
- */
-static int __init reparent_resources(struct resource *parent,
- struct resource *res)
-{
- struct resource *p, **pp;
- struct resource **firstpp = NULL;
-
- for (pp = &parent->child; (p = *pp) != NULL; pp = &p->sibling) {
- if (p->end < res->start)
- continue;
- if (res->end < p->start)
- break;
- if (p->start < res->start || p->end > res->end)
- return -1; /* not completely contained */
- if (firstpp == NULL)
- firstpp = pp;
- }
- if (firstpp == NULL)
- return -1; /* didn't find any conflicting entries? */
- res->parent = parent;
- res->child = *firstpp;
- res->sibling = *pp;
- *firstpp = res;
- *pp = NULL;
- for (p = res->child; p != NULL; p = p->sibling) {
- p->parent = res;
- pr_debug("PCI: Reparented %s [%llx..%llx] under %s\n",
- p->name,
- (unsigned long long)p->start,
- (unsigned long long)p->end, res->name);
- }
- return 0;
-}
-
-/*
- * Handle resources of PCI devices. If the world were perfect, we could
- * just allocate all the resource regions and do nothing more. It isn't.
- * On the other hand, we cannot just re-allocate all devices, as it would
- * require us to know lots of host bridge internals. So we attempt to
- * keep as much of the original configuration as possible, but tweak it
- * when it's found to be wrong.
- *
- * Known BIOS problems we have to work around:
- * - I/O or memory regions not configured
- * - regions configured, but not enabled in the command register
- * - bogus I/O addresses above 64K used
- * - expansion ROMs left enabled (this may sound harmless, but given
- * the fact the PCI specs explicitly allow address decoders to be
- * shared between expansion ROMs and other resource regions, it's
- * at least dangerous)
- *
- * Our solution:
- * (1) Allocate resources for all buses behind PCI-to-PCI bridges.
- * This gives us fixed barriers on where we can allocate.
- * (2) Allocate resources for all enabled devices. If there is
- * a collision, just mark the resource as unallocated. Also
- * disable expansion ROMs during this step.
- * (3) Try to allocate resources for disabled devices. If the
- * resources were assigned correctly, everything goes well,
- * if they weren't, they won't disturb allocation of other
- * resources.
- * (4) Assign new addresses to resources which were either
- * not configured at all or misconfigured. If explicitly
- * requested by the user, configure expansion ROM address
- * as well.
- */
-
-static void pcibios_allocate_bus_resources(struct pci_bus *bus)
-{
- struct pci_bus *b;
- int i;
- struct resource *res, *pr;
-
- pr_debug("PCI: Allocating bus resources for %04x:%02x...\n",
- pci_domain_nr(bus), bus->number);
-
- pci_bus_for_each_resource(bus, res, i) {
- if (!res || !res->flags
- || res->start > res->end || res->parent)
- continue;
- if (bus->parent == NULL)
- pr = (res->flags & IORESOURCE_IO) ?
- &ioport_resource : &iomem_resource;
- else {
- /* Don't bother with non-root busses when
- * re-assigning all resources. We clear the
- * resource flags as if they were colliding
- * and as such ensure proper re-allocation
- * later.
- */
- pr = pci_find_parent_resource(bus->self, res);
- if (pr == res) {
- /* this happens when the generic PCI
- * code (wrongly) decides that this
- * bridge is transparent -- paulus
- */
- continue;
- }
- }
-
- pr_debug("PCI: %s (bus %d) bridge rsrc %d: %016llx-%016llx ",
- bus->self ? pci_name(bus->self) : "PHB",
- bus->number, i,
- (unsigned long long)res->start,
- (unsigned long long)res->end);
- pr_debug("[0x%x], parent %p (%s)\n",
- (unsigned int)res->flags,
- pr, (pr && pr->name) ? pr->name : "nil");
-
- if (pr && !(pr->flags & IORESOURCE_UNSET)) {
- struct pci_dev *dev = bus->self;
-
- if (request_resource(pr, res) == 0)
- continue;
- /*
- * Must be a conflict with an existing entry.
- * Move that entry (or entries) under the
- * bridge resource and try again.
- */
- if (reparent_resources(pr, res) == 0)
- continue;
-
- if (dev && i < PCI_BRIDGE_RESOURCE_NUM &&
- pci_claim_bridge_resource(dev,
- i + PCI_BRIDGE_RESOURCES) == 0)
- continue;
-
- }
- pr_warn("PCI: Cannot allocate resource region ");
- pr_cont("%d of PCI bridge %d, will remap\n", i, bus->number);
- res->start = res->end = 0;
- res->flags = 0;
- }
-
- list_for_each_entry(b, &bus->children, node)
- pcibios_allocate_bus_resources(b);
-}
-
-static inline void alloc_resource(struct pci_dev *dev, int idx)
-{
- struct resource *pr, *r = &dev->resource[idx];
-
- pr_debug("PCI: Allocating %s: Resource %d: %016llx..%016llx [%x]\n",
- pci_name(dev), idx,
- (unsigned long long)r->start,
- (unsigned long long)r->end,
- (unsigned int)r->flags);
-
- pr = pci_find_parent_resource(dev, r);
- if (!pr || (pr->flags & IORESOURCE_UNSET) ||
- request_resource(pr, r) < 0) {
- pr_warn("PCI: Cannot allocate resource region %d ", idx);
- pr_cont("of device %s, will remap\n", pci_name(dev));
- if (pr)
- pr_debug("PCI: parent is %p: %016llx-%016llx [%x]\n",
- pr,
- (unsigned long long)pr->start,
- (unsigned long long)pr->end,
- (unsigned int)pr->flags);
- /* We'll assign a new address later */
- r->flags |= IORESOURCE_UNSET;
- r->end -= r->start;
- r->start = 0;
- }
-}
-
-static void __init pcibios_allocate_resources(int pass)
-{
- struct pci_dev *dev = NULL;
- int idx, disabled;
- u16 command;
- struct resource *r;
-
- for_each_pci_dev(dev) {
- pci_read_config_word(dev, PCI_COMMAND, &command);
- for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) {
- r = &dev->resource[idx];
- if (r->parent) /* Already allocated */
- continue;
- if (!r->flags || (r->flags & IORESOURCE_UNSET))
- continue; /* Not assigned at all */
- /* We only allocate ROMs on pass 1 just in case they
- * have been screwed up by firmware
- */
- if (idx == PCI_ROM_RESOURCE)
- disabled = 1;
- if (r->flags & IORESOURCE_IO)
- disabled = !(command & PCI_COMMAND_IO);
- else
- disabled = !(command & PCI_COMMAND_MEMORY);
- if (pass == disabled)
- alloc_resource(dev, idx);
- }
- if (pass)
- continue;
- r = &dev->resource[PCI_ROM_RESOURCE];
- if (r->flags) {
- /* Turn the ROM off, leave the resource region,
- * but keep it unregistered.
- */
- u32 reg;
- pci_read_config_dword(dev, dev->rom_base_reg, &reg);
- if (reg & PCI_ROM_ADDRESS_ENABLE) {
- pr_debug("PCI: Switching off ROM of %s\n",
- pci_name(dev));
- r->flags &= ~IORESOURCE_ROM_ENABLE;
- pci_write_config_dword(dev, dev->rom_base_reg,
- reg & ~PCI_ROM_ADDRESS_ENABLE);
- }
- }
- }
-}
-
-static void __init pcibios_reserve_legacy_regions(struct pci_bus *bus)
-{
- struct pci_controller *hose = pci_bus_to_host(bus);
- resource_size_t offset;
- struct resource *res, *pres;
- int i;
-
- pr_debug("Reserving legacy ranges for domain %04x\n",
- pci_domain_nr(bus));
-
- /* Check for IO */
- if (!(hose->io_resource.flags & IORESOURCE_IO))
- goto no_io;
- offset = (unsigned long)hose->io_base_virt - _IO_BASE;
- res = kzalloc(sizeof(struct resource), GFP_KERNEL);
- BUG_ON(res == NULL);
- res->name = "Legacy IO";
- res->flags = IORESOURCE_IO;
- res->start = offset;
- res->end = (offset + 0xfff) & 0xfffffffful;
- pr_debug("Candidate legacy IO: %pR\n", res);
- if (request_resource(&hose->io_resource, res)) {
- pr_debug("PCI %04x:%02x Cannot reserve Legacy IO %pR\n",
- pci_domain_nr(bus), bus->number, res);
- kfree(res);
- }
-
- no_io:
- /* Check for memory */
- offset = hose->pci_mem_offset;
- pr_debug("hose mem offset: %016llx\n", (unsigned long long)offset);
- for (i = 0; i < 3; i++) {
- pres = &hose->mem_resources[i];
- if (!(pres->flags & IORESOURCE_MEM))
- continue;
- pr_debug("hose mem res: %pR\n", pres);
- if ((pres->start - offset) <= 0xa0000 &&
- (pres->end - offset) >= 0xbffff)
- break;
- }
- if (i >= 3)
- return;
- res = kzalloc(sizeof(struct resource), GFP_KERNEL);
- BUG_ON(res == NULL);
- res->name = "Legacy VGA memory";
- res->flags = IORESOURCE_MEM;
- res->start = 0xa0000 + offset;
- res->end = 0xbffff + offset;
- pr_debug("Candidate VGA memory: %pR\n", res);
- if (request_resource(pres, res)) {
- pr_debug("PCI %04x:%02x Cannot reserve VGA memory %pR\n",
- pci_domain_nr(bus), bus->number, res);
- kfree(res);
- }
-}
-
-void __init pcibios_resource_survey(void)
-{
- struct pci_bus *b;
-
- /* Allocate and assign resources. If we re-assign everything, then
- * we skip the allocate phase
- */
- list_for_each_entry(b, &pci_root_buses, node)
- pcibios_allocate_bus_resources(b);
-
- pcibios_allocate_resources(0);
- pcibios_allocate_resources(1);
-
- /* Before we start assigning unassigned resource, we try to reserve
- * the low IO area and the VGA memory area if they intersect the
- * bus available resources to avoid allocating things on top of them
- */
- list_for_each_entry(b, &pci_root_buses, node)
- pcibios_reserve_legacy_regions(b);
-
- /* Now proceed to assigning things that were left unassigned */
- pr_debug("PCI: Assigning unassigned resources...\n");
- pci_assign_unassigned_resources();
-}
-
-static void pcibios_setup_phb_resources(struct pci_controller *hose,
- struct list_head *resources)
-{
- unsigned long io_offset;
- struct resource *res;
- int i;
-
- /* Hookup PHB IO resource */
- res = &hose->io_resource;
-
- /* Fixup IO space offset */
- io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
- res->start = (res->start + io_offset) & 0xffffffffu;
- res->end = (res->end + io_offset) & 0xffffffffu;
-
- if (!res->flags) {
- pr_warn("PCI: I/O resource not set for host ");
- pr_cont("bridge %pOF (domain %d)\n",
- hose->dn, hose->global_number);
- /* Workaround for lack of IO resource only on 32-bit */
- res->start = (unsigned long)hose->io_base_virt - isa_io_base;
- res->end = res->start + IO_SPACE_LIMIT;
- res->flags = IORESOURCE_IO;
- }
- pci_add_resource_offset(resources, res,
- (__force resource_size_t)(hose->io_base_virt - _IO_BASE));
-
- pr_debug("PCI: PHB IO resource = %016llx-%016llx [%lx]\n",
- (unsigned long long)res->start,
- (unsigned long long)res->end,
- (unsigned long)res->flags);
-
- /* Hookup PHB Memory resources */
- for (i = 0; i < 3; ++i) {
- res = &hose->mem_resources[i];
- if (!res->flags) {
- if (i > 0)
- continue;
- pr_err("PCI: Memory resource 0 not set for ");
- pr_cont("host bridge %pOF (domain %d)\n",
- hose->dn, hose->global_number);
-
- /* Workaround for lack of MEM resource only on 32-bit */
- res->start = hose->pci_mem_offset;
- res->end = (resource_size_t)-1LL;
- res->flags = IORESOURCE_MEM;
-
- }
- pci_add_resource_offset(resources, res, hose->pci_mem_offset);
-
- pr_debug("PCI: PHB MEM resource %d = %016llx-%016llx [%lx]\n",
- i, (unsigned long long)res->start,
- (unsigned long long)res->end,
- (unsigned long)res->flags);
- }
-
- pr_debug("PCI: PHB MEM offset = %016llx\n",
- (unsigned long long)hose->pci_mem_offset);
- pr_debug("PCI: PHB IO offset = %08lx\n",
- (unsigned long)hose->io_base_virt - _IO_BASE);
-}
-
-static void pcibios_scan_phb(struct pci_controller *hose)
-{
- LIST_HEAD(resources);
- struct pci_bus *bus;
- struct device_node *node = hose->dn;
-
- pr_debug("PCI: Scanning PHB %pOF\n", node);
-
- pcibios_setup_phb_resources(hose, &resources);
-
- bus = pci_scan_root_bus(hose->parent, hose->first_busno,
- hose->ops, hose, &resources);
- if (bus == NULL) {
- pr_err("Failed to create bus for PCI domain %04x\n",
- hose->global_number);
- pci_free_resource_list(&resources);
- return;
- }
- bus->busn_res.start = hose->first_busno;
- hose->bus = bus;
-
- hose->last_busno = bus->busn_res.end;
-}
-
-static int __init pcibios_init(void)
-{
- struct pci_controller *hose, *tmp;
- int next_busno = 0;
-
- pr_info("PCI: Probing PCI hardware\n");
-
- /* Scan all of the recorded PCI controllers. */
- list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
- hose->last_busno = 0xff;
- pcibios_scan_phb(hose);
- if (next_busno <= hose->last_busno)
- next_busno = hose->last_busno + 1;
- }
- pci_bus_count = next_busno;
-
- /* Call common code to handle resource allocation */
- pcibios_resource_survey();
- list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
- if (hose->bus)
- pci_bus_add_devices(hose->bus);
- }
-
- return 0;
-}
-
-subsys_initcall(pcibios_init);
-
-static struct pci_controller *pci_bus_to_hose(int bus)
-{
- struct pci_controller *hose, *tmp;
-
- list_for_each_entry_safe(hose, tmp, &hose_list, list_node)
- if (bus >= hose->first_busno && bus <= hose->last_busno)
- return hose;
- return NULL;
-}
-
-/* Provide information on locations of various I/O regions in physical
- * memory. Do this on a per-card basis so that we choose the right
- * root bridge.
- * Note that the returned IO or memory base is a physical address
- */
-
-long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn)
-{
- struct pci_controller *hose;
- long result = -EOPNOTSUPP;
-
- hose = pci_bus_to_hose(bus);
- if (!hose)
- return -ENODEV;
-
- switch (which) {
- case IOBASE_BRIDGE_NUMBER:
- return (long)hose->first_busno;
- case IOBASE_MEMORY:
- return (long)hose->pci_mem_offset;
- case IOBASE_IO:
- return (long)hose->io_base_phys;
- case IOBASE_ISA_IO:
- return (long)isa_io_base;
- case IOBASE_ISA_MEM:
- return (long)isa_mem_base;
- }
-
- return result;
-}
-
-/*
- * Null PCI config access functions, for the case when we can't
- * find a hose.
- */
-#define NULL_PCI_OP(rw, size, type) \
-static int \
-null_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \
-{ \
- return PCIBIOS_DEVICE_NOT_FOUND; \
-}
-
-static int
-null_read_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 *val)
-{
- return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-static int
-null_write_config(struct pci_bus *bus, unsigned int devfn, int offset,
- int len, u32 val)
-{
- return PCIBIOS_DEVICE_NOT_FOUND;
-}
-
-static struct pci_ops null_pci_ops = {
- .read = null_read_config,
- .write = null_write_config,
-};
-
-/*
- * These functions are used early on before PCI scanning is done
- * and all of the pci_dev and pci_bus structures have been created.
- */
-static struct pci_bus *
-fake_pci_bus(struct pci_controller *hose, int busnr)
-{
- static struct pci_bus bus;
-
- if (!hose)
- pr_err("Can't find hose for PCI bus %d!\n", busnr);
-
- bus.number = busnr;
- bus.sysdata = hose;
- bus.ops = hose ? hose->ops : &null_pci_ops;
- return &bus;
-}
-
-#define EARLY_PCI_OP(rw, size, type) \
-int early_##rw##_config_##size(struct pci_controller *hose, int bus, \
- int devfn, int offset, type value) \
-{ \
- return pci_bus_##rw##_config_##size(fake_pci_bus(hose, bus), \
- devfn, offset, value); \
-}
-
-EARLY_PCI_OP(read, byte, u8 *)
-EARLY_PCI_OP(read, word, u16 *)
-EARLY_PCI_OP(read, dword, u32 *)
-EARLY_PCI_OP(write, byte, u8)
-EARLY_PCI_OP(write, word, u16)
-EARLY_PCI_OP(write, dword, u32)
-
-int early_find_capability(struct pci_controller *hose, int bus, int devfn,
- int cap)
-{
- return pci_bus_find_capability(fake_pci_bus(hose, bus), devfn, cap);
-}
diff --git a/arch/microblaze/pci/xilinx_pci.c b/arch/microblaze/pci/xilinx_pci.c
deleted file mode 100644
index f4cb86fffcee..000000000000
--- a/arch/microblaze/pci/xilinx_pci.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * PCI support for Xilinx plbv46_pci soft-core which can be used on
- * Xilinx Virtex ML410 / ML510 boards.
- *
- * Copyright 2009 Roderick Colenbrander
- * Copyright 2009 Secret Lab Technologies Ltd.
- *
- * The pci bridge fixup code was copied from ppc4xx_pci.c and was written
- * by Benjamin Herrenschmidt.
- * Copyright 2007 Ben. Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
- *
- * 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/ioport.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/pci.h>
-#include <linux/io.h>
-
-#define XPLB_PCI_ADDR 0x10c
-#define XPLB_PCI_DATA 0x110
-#define XPLB_PCI_BUS 0x114
-
-#define PCI_HOST_ENABLE_CMD (PCI_COMMAND_SERR | PCI_COMMAND_PARITY | \
- PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY)
-
-static const struct of_device_id xilinx_pci_match[] = {
- { .compatible = "xlnx,plbv46-pci-1.03.a", },
- {}
-};
-
-/**
- * xilinx_pci_fixup_bridge - Block Xilinx PHB configuration.
- */
-static void xilinx_pci_fixup_bridge(struct pci_dev *dev)
-{
- struct pci_controller *hose;
- int i;
-
- if (dev->devfn || dev->bus->self)
- return;
-
- hose = pci_bus_to_host(dev->bus);
- if (!hose)
- return;
-
- if (!of_match_node(xilinx_pci_match, hose->dn))
- return;
-
- /* Hide the PCI host BARs from the kernel as their content doesn't
- * fit well in the resource management
- */
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- dev->resource[i].start = 0;
- dev->resource[i].end = 0;
- dev->resource[i].flags = 0;
- }
-
- dev_info(&dev->dev, "Hiding Xilinx plb-pci host bridge resources %s\n",
- pci_name(dev));
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, xilinx_pci_fixup_bridge);
-
-#ifdef DEBUG
-/**
- * xilinx_pci_exclude_device - Don't do config access for non-root bus
- *
- * This is a hack. Config access to any bus other than bus 0 does not
- * currently work on the ML510 so we prevent it here.
- */
-static int
-xilinx_pci_exclude_device(struct pci_controller *hose, u_char bus, u8 devfn)
-{
- return (bus != 0);
-}
-
-/**
- * xilinx_early_pci_scan - List pci config space for available devices
- *
- * List pci devices in very early phase.
- */
-static void __init xilinx_early_pci_scan(struct pci_controller *hose)
-{
- u32 bus = 0;
- u32 val, dev, func, offset;
-
- /* Currently we have only 2 device connected - up-to 32 devices */
- for (dev = 0; dev < 2; dev++) {
- /* List only first function number - up-to 8 functions */
- for (func = 0; func < 1; func++) {
- pr_info("%02x:%02x:%02x", bus, dev, func);
- /* read the first 64 standardized bytes */
- /* Up-to 192 bytes can be list of capabilities */
- for (offset = 0; offset < 64; offset += 4) {
- early_read_config_dword(hose, bus,
- PCI_DEVFN(dev, func), offset, &val);
- if (offset == 0 && val == 0xFFFFFFFF) {
- pr_cont("\nABSENT");
- break;
- }
- if (!(offset % 0x10))
- pr_cont("\n%04x: ", offset);
-
- pr_cont("%08x ", val);
- }
- pr_info("\n");
- }
- }
-}
-#else
-static void __init xilinx_early_pci_scan(struct pci_controller *hose)
-{
-}
-#endif
-
-/**
- * xilinx_pci_init - Find and register a Xilinx PCI host bridge
- */
-void __init xilinx_pci_init(void)
-{
- struct pci_controller *hose;
- struct resource r;
- void __iomem *pci_reg;
- struct device_node *pci_node;
-
- pci_node = of_find_matching_node(NULL, xilinx_pci_match);
- if (!pci_node)
- return;
-
- if (of_address_to_resource(pci_node, 0, &r)) {
- pr_err("xilinx-pci: cannot resolve base address\n");
- return;
- }
-
- hose = pcibios_alloc_controller(pci_node);
- if (!hose) {
- pr_err("xilinx-pci: pcibios_alloc_controller() failed\n");
- return;
- }
-
- /* Setup config space */
- setup_indirect_pci(hose, r.start + XPLB_PCI_ADDR,
- r.start + XPLB_PCI_DATA,
- INDIRECT_TYPE_SET_CFG_TYPE);
-
- /* According to the xilinx plbv46_pci documentation the soft-core starts
- * a self-init when the bus master enable bit is set. Without this bit
- * set the pci bus can't be scanned.
- */
- early_write_config_word(hose, 0, 0, PCI_COMMAND, PCI_HOST_ENABLE_CMD);
-
- /* Set the max latency timer to 255 */
- early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0xff);
-
- /* Set the max bus number to 255, and bus/subbus no's to 0 */
- pci_reg = of_iomap(pci_node, 0);
- WARN_ON(!pci_reg);
- out_be32(pci_reg + XPLB_PCI_BUS, 0x000000ff);
- iounmap(pci_reg);
-
- /* Register the host bridge with the linux kernel! */
- pci_process_bridge_OF_ranges(hose, pci_node,
- INDIRECT_TYPE_SET_CFG_TYPE);
-
- pr_info("xilinx-pci: Registered PCI host bridge\n");
- xilinx_early_pci_scan(hose);
-}
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index b296e33f8e33..490dea07d4e0 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -318,7 +318,7 @@ KBUILD_LDFLAGS += -m $(ld-emul)
ifdef CONFIG_MIPS
CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \
- egrep -vw '__GNUC_(MINOR_|PATCHLEVEL_)?_' | \
+ grep -E -vw '__GNUC_(MINOR_|PATCHLEVEL_)?_' | \
sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/" -e 's/\$$/&&/g')
endif
diff --git a/arch/mips/bcm63xx/clk.c b/arch/mips/bcm63xx/clk.c
index 6e6756e8fa0a..86a6e2590866 100644
--- a/arch/mips/bcm63xx/clk.c
+++ b/arch/mips/bcm63xx/clk.c
@@ -361,6 +361,8 @@ static struct clk clk_periph = {
*/
int clk_enable(struct clk *clk)
{
+ if (!clk)
+ return 0;
mutex_lock(&clocks_mutex);
clk_enable_unlocked(clk);
mutex_unlock(&clocks_mutex);
diff --git a/arch/mips/boot/dts/brcm/bcm63268.dtsi b/arch/mips/boot/dts/brcm/bcm63268.dtsi
index 8926417a8fbc..c663efce91cf 100644
--- a/arch/mips/boot/dts/brcm/bcm63268.dtsi
+++ b/arch/mips/boot/dts/brcm/bcm63268.dtsi
@@ -110,6 +110,11 @@
reg = <0x10000080 0x30>;
ranges = <0x0 0x10000080 0x30>;
+ timer@0 {
+ compatible = "brcm,bcm6345-timer";
+ reg = <0x0 0x1c>;
+ };
+
wdt: watchdog@1c {
compatible = "brcm,bcm7038-wdt";
reg = <0x1c 0xc>;
diff --git a/arch/mips/boot/dts/brcm/bcm7435.dtsi b/arch/mips/boot/dts/brcm/bcm7435.dtsi
index 8c001b944c8b..cfdf9804e126 100644
--- a/arch/mips/boot/dts/brcm/bcm7435.dtsi
+++ b/arch/mips/boot/dts/brcm/bcm7435.dtsi
@@ -422,6 +422,7 @@
reg = <0x41c800 0x600>, <0x41d000 0x100>;
interrupt-parent = <&hif_l2_intc>;
interrupts = <24>, <4>;
+ interrupt-names = "nand_ctlrdy", "flash_dma_done";
status = "disabled";
};
diff --git a/arch/mips/boot/dts/ingenic/ci20.dts b/arch/mips/boot/dts/ingenic/ci20.dts
index 37c46720c719..f38c39572a9e 100644
--- a/arch/mips/boot/dts/ingenic/ci20.dts
+++ b/arch/mips/boot/dts/ingenic/ci20.dts
@@ -438,7 +438,7 @@
ingenic,nemc-tAW = <50>;
ingenic,nemc-tSTRV = <100>;
- reset-gpios = <&gpf 12 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpf 12 GPIO_ACTIVE_LOW>;
vcc-supply = <&eth0_power>;
interrupt-parent = <&gpe>;
diff --git a/arch/mips/boot/dts/mscc/jaguar2_pcb110.dts b/arch/mips/boot/dts/mscc/jaguar2_pcb110.dts
index 0ea7bc5b5746..1813f4e32e55 100644
--- a/arch/mips/boot/dts/mscc/jaguar2_pcb110.dts
+++ b/arch/mips/boot/dts/mscc/jaguar2_pcb110.dts
@@ -208,7 +208,7 @@
};
&i2c0 {
- pca9545@70 {
+ i2c-mux@70 {
compatible = "nxp,pca9545";
reg = <0x70>;
#address-cells = <1>;
@@ -236,7 +236,7 @@
reg = <3>;
};
};
- pca9545@71 {
+ i2c-mux@71 {
compatible = "nxp,pca9545";
reg = <0x71>;
#address-cells = <1>;
diff --git a/arch/mips/boot/dts/qca/ar9331.dtsi b/arch/mips/boot/dts/qca/ar9331.dtsi
index c4102b280b47..768ac0f869b1 100644
--- a/arch/mips/boot/dts/qca/ar9331.dtsi
+++ b/arch/mips/boot/dts/qca/ar9331.dtsi
@@ -176,7 +176,6 @@
switch_port0: port@0 {
reg = <0x0>;
- label = "cpu";
ethernet = <&eth1>;
phy-mode = "gmii";
diff --git a/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts b/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts
index 7515555388ae..e31417569e09 100644
--- a/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts
+++ b/arch/mips/boot/dts/ralink/mt7621-gnubee-gb-pc2.dts
@@ -113,13 +113,13 @@
&gmac1 {
status = "okay";
+ phy-mode = "rgmii-rxid";
phy-handle = <&ethphy5>;
};
&mdio {
ethphy5: ethernet-phy@5 {
reg = <5>;
- phy-mode = "rgmii-rxid";
};
};
diff --git a/arch/mips/boot/dts/ralink/mt7621.dtsi b/arch/mips/boot/dts/ralink/mt7621.dtsi
index f3f4c1f26e01..aec85c779359 100644
--- a/arch/mips/boot/dts/ralink/mt7621.dtsi
+++ b/arch/mips/boot/dts/ralink/mt7621.dtsi
@@ -357,36 +357,35 @@
port@0 {
status = "disabled";
reg = <0>;
- label = "lan0";
+ label = "swp0";
};
port@1 {
status = "disabled";
reg = <1>;
- label = "lan1";
+ label = "swp1";
};
port@2 {
status = "disabled";
reg = <2>;
- label = "lan2";
+ label = "swp2";
};
port@3 {
status = "disabled";
reg = <3>;
- label = "lan3";
+ label = "swp3";
};
port@4 {
status = "disabled";
reg = <4>;
- label = "lan4";
+ label = "swp4";
};
port@6 {
reg = <6>;
- label = "cpu";
ethernet = <&gmac0>;
phy-mode = "trgmii";
diff --git a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
index 306cee07ce3f..334bf8e577e5 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
@@ -780,9 +780,8 @@ int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr,
if (addr_allocated >= 0) {
named_block_desc_ptr->base_addr = addr_allocated;
named_block_desc_ptr->size = size;
- strncpy(named_block_desc_ptr->name, name,
+ strscpy(named_block_desc_ptr->name, name,
cvmx_bootmem_desc->named_block_name_len);
- named_block_desc_ptr->name[cvmx_bootmem_desc->named_block_name_len - 1] = 0;
}
if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
index d09d0769f549..0fd9ac76eb74 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper-board.c
@@ -211,7 +211,7 @@ union cvmx_helper_link_info __cvmx_helper_board_link_get(int ipd_port)
{
union cvmx_helper_link_info result;
- WARN(!octeon_is_simulation(),
+ WARN_ONCE(!octeon_is_simulation(),
"Using deprecated link status - please update your DT");
/* Unless we fix it later, all links are defaulted to down */
diff --git a/arch/mips/cavium-octeon/executive/cvmx-helper.c b/arch/mips/cavium-octeon/executive/cvmx-helper.c
index 6f49fd9be1f3..9abfc4bf9bd8 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-helper.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-helper.c
@@ -1096,7 +1096,7 @@ union cvmx_helper_link_info cvmx_helper_link_get(int ipd_port)
if (index == 0)
result = __cvmx_helper_rgmii_link_get(ipd_port);
else {
- WARN(1, "Using deprecated link status - please update your DT");
+ WARN_ONCE(1, "Using deprecated link status - please update your DT");
result.s.full_duplex = 1;
result.s.link_up = 1;
result.s.speed = 1000;
diff --git a/arch/mips/include/asm/asm-prototypes.h b/arch/mips/include/asm/asm-prototypes.h
index f901ed043c71..8e8fc38b0941 100644
--- a/arch/mips/include/asm/asm-prototypes.h
+++ b/arch/mips/include/asm/asm-prototypes.h
@@ -6,3 +6,6 @@
#include <linux/uaccess.h>
#include <asm/ftrace.h>
#include <asm/mmu_context.h>
+
+extern void clear_page_cpu(void *page);
+extern void copy_page_cpu(void *to, void *from);
diff --git a/arch/mips/include/asm/mach-ralink/mt7621.h b/arch/mips/include/asm/mach-ralink/mt7621.h
index 6bbf082dd149..79d5bb0e06d6 100644
--- a/arch/mips/include/asm/mach-ralink/mt7621.h
+++ b/arch/mips/include/asm/mach-ralink/mt7621.h
@@ -7,10 +7,12 @@
#ifndef _MT7621_REGS_H_
#define _MT7621_REGS_H_
+#define IOMEM(x) ((void __iomem *)(KSEG1ADDR(x)))
+
#define MT7621_PALMBUS_BASE 0x1C000000
#define MT7621_PALMBUS_SIZE 0x03FFFFFF
-#define MT7621_SYSC_BASE 0x1E000000
+#define MT7621_SYSC_BASE IOMEM(0x1E000000)
#define SYSC_REG_CHIP_NAME0 0x00
#define SYSC_REG_CHIP_NAME1 0x04
diff --git a/arch/mips/include/asm/stackprotector.h b/arch/mips/include/asm/stackprotector.h
index 68d4be9e1254..518c192ad982 100644
--- a/arch/mips/include/asm/stackprotector.h
+++ b/arch/mips/include/asm/stackprotector.h
@@ -15,9 +15,6 @@
#ifndef _ASM_STACKPROTECTOR_H
#define _ASM_STACKPROTECTOR_H 1
-#include <linux/random.h>
-#include <linux/version.h>
-
extern unsigned long __stack_chk_guard;
/*
@@ -28,11 +25,7 @@ extern unsigned long __stack_chk_guard;
*/
static __always_inline void boot_init_stack_canary(void)
{
- unsigned long canary;
-
- /* Try to get a semi random initial value. */
- get_random_bytes(&canary, sizeof(canary));
- canary ^= LINUX_VERSION_CODE;
+ unsigned long canary = get_random_canary();
current->stack_canary = canary;
__stack_chk_guard = current->stack_canary;
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index bbe9ce471791..093dbbd6b843 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -711,7 +711,7 @@ unsigned long mips_stack_top(void)
unsigned long arch_align_stack(unsigned long sp)
{
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
- sp -= prandom_u32_max(PAGE_SIZE);
+ sp -= get_random_u32_below(PAGE_SIZE);
return sp & ALMASK;
}
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index 567aec4abac0..d9df543f7e2c 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -531,10 +531,11 @@ static int fpr_set(struct task_struct *target,
ptrace_setfcr31(target, fcr31);
}
- if (count > 0)
- err = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- fir_pos,
- fir_pos + sizeof(u32));
+ if (count > 0) {
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ fir_pos, fir_pos + sizeof(u32));
+ return 0;
+ }
return err;
}
diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c
index 5fd9bf1d596c..f6d40e43f108 100644
--- a/arch/mips/kernel/vdso.c
+++ b/arch/mips/kernel/vdso.c
@@ -79,7 +79,7 @@ static unsigned long vdso_base(void)
}
if (current->flags & PF_RANDOMIZE) {
- base += prandom_u32_max(VDSO_RANDOMIZE_SIZE);
+ base += get_random_u32_below(VDSO_RANDOMIZE_SIZE);
base = PAGE_ALIGN(base);
}
diff --git a/arch/mips/kernel/vpe-cmp.c b/arch/mips/kernel/vpe-cmp.c
index e673603e11e5..92140edb3ce3 100644
--- a/arch/mips/kernel/vpe-cmp.c
+++ b/arch/mips/kernel/vpe-cmp.c
@@ -75,7 +75,6 @@ ATTRIBUTE_GROUPS(vpe);
static void vpe_device_release(struct device *cd)
{
- kfree(cd);
}
static struct class vpe_class = {
@@ -157,6 +156,7 @@ out_dev:
device_del(&vpe_device);
out_class:
+ put_device(&vpe_device);
class_unregister(&vpe_class);
out_chrdev:
@@ -169,7 +169,7 @@ void __exit vpe_module_exit(void)
{
struct vpe *v, *n;
- device_del(&vpe_device);
+ device_unregister(&vpe_device);
class_unregister(&vpe_class);
unregister_chrdev(major, VPE_MODULE_NAME);
diff --git a/arch/mips/kernel/vpe-mt.c b/arch/mips/kernel/vpe-mt.c
index bad6b0891b2b..84a82b551ec3 100644
--- a/arch/mips/kernel/vpe-mt.c
+++ b/arch/mips/kernel/vpe-mt.c
@@ -313,7 +313,6 @@ ATTRIBUTE_GROUPS(vpe);
static void vpe_device_release(struct device *cd)
{
- kfree(cd);
}
static struct class vpe_class = {
@@ -497,6 +496,7 @@ out_dev:
device_del(&vpe_device);
out_class:
+ put_device(&vpe_device);
class_unregister(&vpe_class);
out_chrdev:
@@ -509,7 +509,7 @@ void __exit vpe_module_exit(void)
{
struct vpe *v, *n;
- device_del(&vpe_device);
+ device_unregister(&vpe_device);
class_unregister(&vpe_class);
unregister_chrdev(major, VPE_MODULE_NAME);
diff --git a/arch/mips/pci/pci-rt3883.c b/arch/mips/pci/pci-rt3883.c
index e07ae098bdd8..d59888aaed81 100644
--- a/arch/mips/pci/pci-rt3883.c
+++ b/arch/mips/pci/pci-rt3883.c
@@ -404,7 +404,6 @@ static int rt3883_pci_probe(struct platform_device *pdev)
struct rt3883_pci_controller *rpc;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
- struct resource *res;
struct device_node *child;
u32 val;
int err;
@@ -414,8 +413,7 @@ static int rt3883_pci_probe(struct platform_device *pdev)
if (!rpc)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- rpc->base = devm_ioremap_resource(dev, res);
+ rpc->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(rpc->base))
return PTR_ERR(rpc->base);
diff --git a/arch/mips/ralink/mt7621.c b/arch/mips/ralink/mt7621.c
index fb0565bc34fd..bbf5811afbf2 100644
--- a/arch/mips/ralink/mt7621.c
+++ b/arch/mips/ralink/mt7621.c
@@ -25,6 +25,7 @@
#define MT7621_MEM_TEST_PATTERN 0xaa5555aa
static u32 detect_magic __initdata;
+static struct ralink_soc_info *soc_info_ptr;
int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
{
@@ -97,41 +98,83 @@ void __init ralink_of_remap(void)
panic("Failed to remap core resources");
}
-static void soc_dev_init(struct ralink_soc_info *soc_info, u32 rev)
+static unsigned int __init mt7621_get_soc_name0(void)
+{
+ return __raw_readl(MT7621_SYSC_BASE + SYSC_REG_CHIP_NAME0);
+}
+
+static unsigned int __init mt7621_get_soc_name1(void)
+{
+ return __raw_readl(MT7621_SYSC_BASE + SYSC_REG_CHIP_NAME1);
+}
+
+static bool __init mt7621_soc_valid(void)
+{
+ if (mt7621_get_soc_name0() == MT7621_CHIP_NAME0 &&
+ mt7621_get_soc_name1() == MT7621_CHIP_NAME1)
+ return true;
+ else
+ return false;
+}
+
+static const char __init *mt7621_get_soc_id(void)
+{
+ if (mt7621_soc_valid())
+ return "MT7621";
+ else
+ return "invalid";
+}
+
+static unsigned int __init mt7621_get_soc_rev(void)
+{
+ return __raw_readl(MT7621_SYSC_BASE + SYSC_REG_CHIP_REV);
+}
+
+static unsigned int __init mt7621_get_soc_ver(void)
+{
+ return (mt7621_get_soc_rev() >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK;
+}
+
+static unsigned int __init mt7621_get_soc_eco(void)
+{
+ return (mt7621_get_soc_rev() & CHIP_REV_ECO_MASK);
+}
+
+static const char __init *mt7621_get_soc_revision(void)
+{
+ if (mt7621_get_soc_rev() == 1 && mt7621_get_soc_eco() == 1)
+ return "E2";
+ else
+ return "E1";
+}
+
+static int __init mt7621_soc_dev_init(void)
{
struct soc_device *soc_dev;
struct soc_device_attribute *soc_dev_attr;
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
if (!soc_dev_attr)
- return;
+ return -ENOMEM;
soc_dev_attr->soc_id = "mt7621";
soc_dev_attr->family = "Ralink";
+ soc_dev_attr->revision = mt7621_get_soc_revision();
- if (((rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK) == 1 &&
- (rev & CHIP_REV_ECO_MASK) == 1)
- soc_dev_attr->revision = "E2";
- else
- soc_dev_attr->revision = "E1";
-
- soc_dev_attr->data = soc_info;
+ soc_dev_attr->data = soc_info_ptr;
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev)) {
kfree(soc_dev_attr);
- return;
+ return PTR_ERR(soc_dev);
}
+
+ return 0;
}
+device_initcall(mt7621_soc_dev_init);
void __init prom_soc_init(struct ralink_soc_info *soc_info)
{
- void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7621_SYSC_BASE);
- unsigned char *name = NULL;
- u32 n0;
- u32 n1;
- u32 rev;
-
/* Early detection of CMP support */
mips_cm_probe();
mips_cpc_probe();
@@ -154,27 +197,23 @@ void __init prom_soc_init(struct ralink_soc_info *soc_info)
__sync();
}
- n0 = __raw_readl(sysc + SYSC_REG_CHIP_NAME0);
- n1 = __raw_readl(sysc + SYSC_REG_CHIP_NAME1);
-
- if (n0 == MT7621_CHIP_NAME0 && n1 == MT7621_CHIP_NAME1) {
- name = "MT7621";
+ if (mt7621_soc_valid())
soc_info->compatible = "mediatek,mt7621-soc";
- } else {
- panic("mt7621: unknown SoC, n0:%08x n1:%08x\n", n0, n1);
- }
+ else
+ panic("mt7621: unknown SoC, n0:%08x n1:%08x\n",
+ mt7621_get_soc_name0(),
+ mt7621_get_soc_name1());
ralink_soc = MT762X_SOC_MT7621AT;
- rev = __raw_readl(sysc + SYSC_REG_CHIP_REV);
snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN,
"MediaTek %s ver:%u eco:%u",
- name,
- (rev >> CHIP_REV_VER_SHIFT) & CHIP_REV_VER_MASK,
- (rev & CHIP_REV_ECO_MASK));
+ mt7621_get_soc_id(),
+ mt7621_get_soc_ver(),
+ mt7621_get_soc_eco());
soc_info->mem_detect = mt7621_memory_detect;
- soc_dev_init(soc_info, rev);
+ soc_info_ptr = soc_info;
if (!register_cps_smp_ops())
return;
diff --git a/arch/mips/vdso/Makefile b/arch/mips/vdso/Makefile
index f72658b3a53f..1f7d5c6c10b0 100644
--- a/arch/mips/vdso/Makefile
+++ b/arch/mips/vdso/Makefile
@@ -71,7 +71,7 @@ KCOV_INSTRUMENT := n
# Check that we don't have PIC 'jalr t9' calls left
quiet_cmd_vdso_mips_check = VDSOCHK $@
- cmd_vdso_mips_check = if $(OBJDUMP) --disassemble $@ | egrep -h "jalr.*t9" > /dev/null; \
+ cmd_vdso_mips_check = if $(OBJDUMP) --disassemble $@ | grep -E -h "jalr.*t9" > /dev/null; \
then (echo >&2 "$@: PIC 'jalr t9' calls are not supported"; \
rm -f $@; /bin/false); fi
diff --git a/arch/nios2/kernel/ptrace.c b/arch/nios2/kernel/ptrace.c
index cd62f310778b..9221c15972e6 100644
--- a/arch/nios2/kernel/ptrace.c
+++ b/arch/nios2/kernel/ptrace.c
@@ -54,7 +54,7 @@ static int genregs_set(struct task_struct *target,
#define REG_IGNORE_RANGE(START, END) \
if (!ret) \
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, \
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, \
START * 4, (END * 4) + 4);
#define REG_IN_ONE(PTR, LOC) \
@@ -80,8 +80,8 @@ static int genregs_set(struct task_struct *target,
REG_IN_ONE(&regs->ra, PTR_RA);
REG_IN_ONE(&regs->ea, PTR_PC); /* use ea for PC */
if (!ret)
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- PTR_STATUS * 4, -1);
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ PTR_STATUS * 4, -1);
return ret;
}
diff --git a/arch/openrisc/configs/or1ksim_defconfig b/arch/openrisc/configs/or1ksim_defconfig
index 6e1e004047c7..0116e465238f 100644
--- a/arch/openrisc/configs/or1ksim_defconfig
+++ b/arch/openrisc/configs/or1ksim_defconfig
@@ -10,7 +10,8 @@ CONFIG_EXPERT=y
# CONFIG_AIO is not set
# CONFIG_VM_EVENT_COUNTERS is not set
# CONFIG_COMPAT_BRK is not set
-CONFIG_SLOB=y
+CONFIG_SLUB=y
+CONFIG_SLUB_TINY=y
CONFIG_MODULES=y
# CONFIG_BLOCK is not set
CONFIG_OPENRISC_BUILTIN_DTB="or1ksim"
diff --git a/arch/openrisc/configs/simple_smp_defconfig b/arch/openrisc/configs/simple_smp_defconfig
index ff49d868e040..b990cb6c9309 100644
--- a/arch/openrisc/configs/simple_smp_defconfig
+++ b/arch/openrisc/configs/simple_smp_defconfig
@@ -16,7 +16,8 @@ CONFIG_EXPERT=y
# CONFIG_AIO is not set
# CONFIG_VM_EVENT_COUNTERS is not set
# CONFIG_COMPAT_BRK is not set
-CONFIG_SLOB=y
+CONFIG_SLUB=y
+CONFIG_SLUB_TINY=y
CONFIG_MODULES=y
# CONFIG_BLOCK is not set
CONFIG_OPENRISC_BUILTIN_DTB="simple_smp"
diff --git a/arch/openrisc/kernel/ptrace.c b/arch/openrisc/kernel/ptrace.c
index b971740fc2aa..85ace93fc251 100644
--- a/arch/openrisc/kernel/ptrace.c
+++ b/arch/openrisc/kernel/ptrace.c
@@ -66,10 +66,9 @@ static int genregs_set(struct task_struct *target,
int ret;
/* ignore r0 */
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, 4);
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 0, 4);
/* r1 - r31 */
- if (!ret)
- ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
regs->gpr+1, 4, 4*32);
/* PC */
if (!ret)
@@ -80,8 +79,7 @@ static int genregs_set(struct task_struct *target,
* the Supervision register
*/
if (!ret)
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- 4*33, -1);
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 4*33, -1);
return ret;
}
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 96ef6a6b66e5..69c62933e952 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -424,8 +424,9 @@ static int fpr_set(struct task_struct *target,
ubuf = u;
pos *= sizeof(reg);
count *= sizeof(reg);
- return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- ELF_NFPREG * sizeof(reg), -1);
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ ELF_NFPREG * sizeof(reg), -1);
+ return 0;
}
#define RI(reg) (offsetof(struct user_regs_struct,reg) / sizeof(long))
@@ -543,8 +544,9 @@ static int gpr_set(struct task_struct *target,
ubuf = u;
pos *= sizeof(reg);
count *= sizeof(reg);
- return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- ELF_NGREG * sizeof(reg), -1);
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ ELF_NGREG * sizeof(reg), -1);
+ return 0;
}
static const struct user_regset native_regsets[] = {
@@ -606,8 +608,9 @@ static int gpr32_set(struct task_struct *target,
ubuf = u;
pos *= sizeof(reg);
count *= sizeof(reg);
- return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- ELF_NGREG * sizeof(reg), -1);
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ ELF_NGREG * sizeof(reg), -1);
+ return 0;
}
/*
diff --git a/arch/parisc/kernel/vdso.c b/arch/parisc/kernel/vdso.c
index 47e5960a2f96..c5cbfce7a84c 100644
--- a/arch/parisc/kernel/vdso.c
+++ b/arch/parisc/kernel/vdso.c
@@ -75,7 +75,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm,
map_base = mm->mmap_base;
if (current->flags & PF_RANDOMIZE)
- map_base -= prandom_u32_max(0x20) * PAGE_SIZE;
+ map_base -= get_random_u32_below(0x20) * PAGE_SIZE;
vdso_text_start = get_unmapped_area(NULL, map_base, vdso_text_len, 0, 0);
diff --git a/arch/powerpc/configs/microwatt_defconfig b/arch/powerpc/configs/microwatt_defconfig
index ea2dbd778aad..18d4fe4108cb 100644
--- a/arch/powerpc/configs/microwatt_defconfig
+++ b/arch/powerpc/configs/microwatt_defconfig
@@ -68,7 +68,6 @@ CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_NONSTANDARD=y
# CONFIG_NVRAM is not set
-CONFIG_RANDOM_TRUST_CPU=y
CONFIG_SPI=y
CONFIG_SPI_DEBUG=y
CONFIG_SPI_BITBANG=y
diff --git a/arch/powerpc/crypto/crc-vpmsum_test.c b/arch/powerpc/crypto/crc-vpmsum_test.c
index 273c527868db..c61a874a3a5c 100644
--- a/arch/powerpc/crypto/crc-vpmsum_test.c
+++ b/arch/powerpc/crypto/crc-vpmsum_test.c
@@ -77,8 +77,8 @@ static int __init crc_test_init(void)
pr_info("crc-vpmsum_test begins, %lu iterations\n", iterations);
for (i=0; i<iterations; i++) {
- size_t offset = prandom_u32_max(16);
- size_t len = prandom_u32_max(MAX_CRC_LENGTH);
+ size_t offset = get_random_u32_below(16);
+ size_t len = get_random_u32_below(MAX_CRC_LENGTH);
if (len <= offset)
continue;
diff --git a/arch/powerpc/include/asm/ftrace.h b/arch/powerpc/include/asm/ftrace.h
index 3cee7115441b..259b9dd5fe1c 100644
--- a/arch/powerpc/include/asm/ftrace.h
+++ b/arch/powerpc/include/asm/ftrace.h
@@ -37,12 +37,32 @@ static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *
return fregs->regs.msr ? &fregs->regs : NULL;
}
-static __always_inline void ftrace_instruction_pointer_set(struct ftrace_regs *fregs,
- unsigned long ip)
+static __always_inline void
+ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
+ unsigned long ip)
{
regs_set_return_ip(&fregs->regs, ip);
}
+static __always_inline unsigned long
+ftrace_regs_get_instruction_pointer(struct ftrace_regs *fregs)
+{
+ return instruction_pointer(&fregs->regs);
+}
+
+#define ftrace_regs_get_argument(fregs, n) \
+ regs_get_kernel_argument(&(fregs)->regs, n)
+#define ftrace_regs_get_stack_pointer(fregs) \
+ kernel_stack_pointer(&(fregs)->regs)
+#define ftrace_regs_return_value(fregs) \
+ regs_return_value(&(fregs)->regs)
+#define ftrace_regs_set_return_value(fregs, ret) \
+ regs_set_return_value(&(fregs)->regs, ret)
+#define ftrace_override_function_with_return(fregs) \
+ override_function_with_return(&(fregs)->regs)
+#define ftrace_regs_query_register_offset(name) \
+ regs_query_register_offset(name)
+
struct ftrace_ops;
#define ftrace_graph_func ftrace_graph_func
diff --git a/arch/powerpc/include/asm/stackprotector.h b/arch/powerpc/include/asm/stackprotector.h
index 1c8460e23583..283c34647856 100644
--- a/arch/powerpc/include/asm/stackprotector.h
+++ b/arch/powerpc/include/asm/stackprotector.h
@@ -7,8 +7,6 @@
#ifndef _ASM_STACKPROTECTOR_H
#define _ASM_STACKPROTECTOR_H
-#include <linux/random.h>
-#include <linux/version.h>
#include <asm/reg.h>
#include <asm/current.h>
#include <asm/paca.h>
@@ -21,13 +19,7 @@
*/
static __always_inline void boot_init_stack_canary(void)
{
- unsigned long canary;
-
- /* Try to get a semi random initial value. */
- canary = get_random_canary();
- canary ^= mftb();
- canary ^= LINUX_VERSION_CODE;
- canary &= CANARY_MASK;
+ unsigned long canary = get_random_canary();
current->stack_canary = canary;
#ifdef CONFIG_PPC64
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
index 67da147fe34d..fcf604370c66 100644
--- a/arch/powerpc/kernel/process.c
+++ b/arch/powerpc/kernel/process.c
@@ -2303,6 +2303,6 @@ void notrace __ppc64_runlatch_off(void)
unsigned long arch_align_stack(unsigned long sp)
{
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
- sp -= prandom_u32_max(PAGE_SIZE);
+ sp -= get_random_u32_below(PAGE_SIZE);
return sp & ~0xf;
}
diff --git a/arch/powerpc/kernel/ptrace/ptrace-tm.c b/arch/powerpc/kernel/ptrace/ptrace-tm.c
index 44045363a903..210ea834e603 100644
--- a/arch/powerpc/kernel/ptrace/ptrace-tm.c
+++ b/arch/powerpc/kernel/ptrace/ptrace-tm.c
@@ -170,9 +170,9 @@ int tm_cgpr_set(struct task_struct *target, const struct user_regset *regset,
(PT_MAX_PUT_REG + 1) * sizeof(reg));
if (PT_MAX_PUT_REG + 1 < PT_TRAP && !ret)
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- (PT_MAX_PUT_REG + 1) * sizeof(reg),
- PT_TRAP * sizeof(reg));
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ (PT_MAX_PUT_REG + 1) * sizeof(reg),
+ PT_TRAP * sizeof(reg));
if (!ret && count > 0) {
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &reg,
@@ -183,8 +183,8 @@ int tm_cgpr_set(struct task_struct *target, const struct user_regset *regset,
}
if (!ret)
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- (PT_TRAP + 1) * sizeof(reg), -1);
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ (PT_TRAP + 1) * sizeof(reg), -1);
return ret;
}
diff --git a/arch/powerpc/kernel/ptrace/ptrace-view.c b/arch/powerpc/kernel/ptrace/ptrace-view.c
index 076d867412c7..2087a785f05f 100644
--- a/arch/powerpc/kernel/ptrace/ptrace-view.c
+++ b/arch/powerpc/kernel/ptrace/ptrace-view.c
@@ -267,9 +267,9 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset,
(PT_MAX_PUT_REG + 1) * sizeof(reg));
if (PT_MAX_PUT_REG + 1 < PT_TRAP && !ret)
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- (PT_MAX_PUT_REG + 1) * sizeof(reg),
- PT_TRAP * sizeof(reg));
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ (PT_MAX_PUT_REG + 1) * sizeof(reg),
+ PT_TRAP * sizeof(reg));
if (!ret && count > 0) {
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &reg,
@@ -280,8 +280,8 @@ static int gpr_set(struct task_struct *target, const struct user_regset *regset,
}
if (!ret)
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- (PT_TRAP + 1) * sizeof(reg), -1);
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ (PT_TRAP + 1) * sizeof(reg), -1);
return ret;
}
@@ -706,8 +706,9 @@ int gpr32_set_common(struct task_struct *target,
ubuf = u;
pos *= sizeof(reg);
count *= sizeof(reg);
- return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- (PT_TRAP + 1) * sizeof(reg), -1);
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ (PT_TRAP + 1) * sizeof(reg), -1);
+ return 0;
Efault:
user_read_access_end();
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c
index 4abc01949702..507f8228f983 100644
--- a/arch/powerpc/kernel/vdso.c
+++ b/arch/powerpc/kernel/vdso.c
@@ -129,28 +129,6 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
return 0;
}
-
-static struct page *find_timens_vvar_page(struct vm_area_struct *vma)
-{
- if (likely(vma->vm_mm == current->mm))
- return current->nsproxy->time_ns->vvar_page;
-
- /*
- * VM_PFNMAP | VM_IO protect .fault() handler from being called
- * through interfaces like /proc/$pid/mem or
- * process_vm_{readv,writev}() as long as there's no .access()
- * in special_mapping_vmops.
- * For more details check_vma_flags() and __access_remote_vm()
- */
- WARN(1, "vvar_page accessed remotely");
-
- return NULL;
-}
-#else
-static struct page *find_timens_vvar_page(struct vm_area_struct *vma)
-{
- return NULL;
-}
#endif
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
diff --git a/arch/powerpc/kexec/file_load_64.c b/arch/powerpc/kexec/file_load_64.c
index 349a781cea0b..60e12b716d3c 100644
--- a/arch/powerpc/kexec/file_load_64.c
+++ b/arch/powerpc/kexec/file_load_64.c
@@ -35,7 +35,7 @@ struct umem_info {
/* usable memory ranges to look up */
unsigned int nr_ranges;
- const struct crash_mem_range *ranges;
+ const struct range *ranges;
};
const struct kexec_file_ops * const kexec_file_loaders[] = {
diff --git a/arch/powerpc/kexec/ranges.c b/arch/powerpc/kexec/ranges.c
index 563e9989a5bf..5fc53a5fcfdf 100644
--- a/arch/powerpc/kexec/ranges.c
+++ b/arch/powerpc/kexec/ranges.c
@@ -33,7 +33,7 @@
static inline unsigned int get_max_nr_ranges(size_t size)
{
return ((size - sizeof(struct crash_mem)) /
- sizeof(struct crash_mem_range));
+ sizeof(struct range));
}
/**
@@ -51,7 +51,7 @@ static inline size_t get_mem_rngs_size(struct crash_mem *mem_rngs)
return 0;
size = (sizeof(struct crash_mem) +
- (mem_rngs->max_nr_ranges * sizeof(struct crash_mem_range)));
+ (mem_rngs->max_nr_ranges * sizeof(struct range)));
/*
* Memory is allocated in size multiple of MEM_RANGE_CHUNK_SZ.
@@ -98,7 +98,7 @@ static int __add_mem_range(struct crash_mem **mem_ranges, u64 base, u64 size)
*/
static void __merge_memory_ranges(struct crash_mem *mem_rngs)
{
- struct crash_mem_range *ranges;
+ struct range *ranges;
int i, idx;
if (!mem_rngs)
@@ -123,7 +123,7 @@ static void __merge_memory_ranges(struct crash_mem *mem_rngs)
/* cmp_func_t callback to sort ranges with sort() */
static int rngcmp(const void *_x, const void *_y)
{
- const struct crash_mem_range *x = _x, *y = _y;
+ const struct range *x = _x, *y = _y;
if (x->start > y->start)
return 1;
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 942aa830e110..bf318dd9b709 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -132,7 +132,7 @@ static unsigned long ebb_switch_in(bool ebb, struct cpu_hw_events *cpuhw)
static inline void power_pmu_bhrb_enable(struct perf_event *event) {}
static inline void power_pmu_bhrb_disable(struct perf_event *event) {}
-static void power_pmu_sched_task(struct perf_event_context *ctx, bool sched_in) {}
+static void power_pmu_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in) {}
static inline void power_pmu_bhrb_read(struct perf_event *event, struct cpu_hw_events *cpuhw) {}
static void pmao_restore_workaround(bool ebb) { }
#endif /* CONFIG_PPC32 */
@@ -424,7 +424,7 @@ static void power_pmu_bhrb_enable(struct perf_event *event)
cpuhw->bhrb_context = event->ctx;
}
cpuhw->bhrb_users++;
- perf_sched_cb_inc(event->ctx->pmu);
+ perf_sched_cb_inc(event->pmu);
}
static void power_pmu_bhrb_disable(struct perf_event *event)
@@ -436,7 +436,7 @@ static void power_pmu_bhrb_disable(struct perf_event *event)
WARN_ON_ONCE(!cpuhw->bhrb_users);
cpuhw->bhrb_users--;
- perf_sched_cb_dec(event->ctx->pmu);
+ perf_sched_cb_dec(event->pmu);
if (!cpuhw->disabled && !cpuhw->bhrb_users) {
/* BHRB cannot be turned off when other
@@ -451,7 +451,7 @@ static void power_pmu_bhrb_disable(struct perf_event *event)
/* Called from ctxsw to prevent one process's branch entries to
* mingle with the other process's entries during context switch.
*/
-static void power_pmu_sched_task(struct perf_event_context *ctx, bool sched_in)
+static void power_pmu_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in)
{
if (!ppmu->bhrb_nr)
return;
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index a3a71d37cb9a..3f05507e444d 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -447,21 +447,18 @@ static void pseries_msi_ops_msi_free(struct irq_domain *domain,
* RTAS can not disable one MSI at a time. It's all or nothing. Do it
* at the end after all IRQs have been freed.
*/
-static void pseries_msi_domain_free_irqs(struct irq_domain *domain,
- struct device *dev)
+static void pseries_msi_post_free(struct irq_domain *domain, struct device *dev)
{
if (WARN_ON_ONCE(!dev_is_pci(dev)))
return;
- __msi_domain_free_irqs(domain, dev);
-
rtas_disable_msi(to_pci_dev(dev));
}
static struct msi_domain_ops pseries_pci_msi_domain_ops = {
.msi_prepare = pseries_msi_ops_prepare,
.msi_free = pseries_msi_ops_msi_free,
- .domain_free_irqs = pseries_msi_domain_free_irqs,
+ .msi_post_free = pseries_msi_post_free,
};
static void pseries_msi_shutdown(struct irq_data *d)
diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs
index 69774bb362d6..75fb0390d6bd 100644
--- a/arch/riscv/Kconfig.socs
+++ b/arch/riscv/Kconfig.socs
@@ -7,6 +7,11 @@ config SOC_MICROCHIP_POLARFIRE
help
This enables support for Microchip PolarFire SoC platforms.
+config ARCH_RENESAS
+ bool "Renesas RISC-V SoCs"
+ help
+ This enables support for the RISC-V based Renesas SoCs.
+
config SOC_SIFIVE
bool "SiFive SoCs"
select SERIAL_SIFIVE if TTY
diff --git a/arch/riscv/boot/dts/Makefile b/arch/riscv/boot/dts/Makefile
index ff174996cdfd..b0ff5fbabb0c 100644
--- a/arch/riscv/boot/dts/Makefile
+++ b/arch/riscv/boot/dts/Makefile
@@ -3,5 +3,6 @@ subdir-y += sifive
subdir-y += starfive
subdir-$(CONFIG_SOC_CANAAN_K210_DTB_BUILTIN) += canaan
subdir-y += microchip
+subdir-y += renesas
obj-$(CONFIG_BUILTIN_DTB) := $(addsuffix /, $(subdir-y))
diff --git a/arch/riscv/boot/dts/microchip/mpfs-icicle-kit-fabric.dtsi b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit-fabric.dtsi
index 24b1cfb9a73e..1069134f2e12 100644
--- a/arch/riscv/boot/dts/microchip/mpfs-icicle-kit-fabric.dtsi
+++ b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit-fabric.dtsi
@@ -9,8 +9,8 @@
compatible = "microchip,corepwm-rtl-v4";
reg = <0x0 0x40000000 0x0 0xF0>;
microchip,sync-update-mask = /bits/ 32 <0>;
- #pwm-cells = <2>;
- clocks = <&fabric_clk3>;
+ #pwm-cells = <3>;
+ clocks = <&ccc_nw CLK_CCC_PLL0_OUT3>;
status = "disabled";
};
@@ -19,25 +19,13 @@
reg = <0x0 0x40000200 0x0 0x100>;
#address-cells = <1>;
#size-cells = <0>;
- clocks = <&fabric_clk3>;
+ clocks = <&ccc_nw CLK_CCC_PLL0_OUT3>;
interrupt-parent = <&plic>;
interrupts = <122>;
clock-frequency = <100000>;
status = "disabled";
};
- fabric_clk3: fabric-clk3 {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <50000000>;
- };
-
- fabric_clk1: fabric-clk1 {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <125000000>;
- };
-
pcie: pcie@3000000000 {
compatible = "microchip,pcie-host-1.0";
#address-cells = <0x3>;
@@ -54,7 +42,7 @@
<0 0 0 3 &pcie_intc 2>,
<0 0 0 4 &pcie_intc 3>;
interrupt-map-mask = <0 0 0 7>;
- clocks = <&fabric_clk1>, <&fabric_clk3>;
+ clocks = <&ccc_nw CLK_CCC_PLL0_OUT1>, <&ccc_nw CLK_CCC_PLL0_OUT3>;
clock-names = "fic1", "fic3";
ranges = <0x3000000 0x0 0x8000000 0x30 0x8000000 0x0 0x80000000>;
dma-ranges = <0x02000000 0x0 0x00000000 0x0 0x00000000 0x1 0x00000000>;
@@ -67,4 +55,17 @@
interrupt-controller;
};
};
+
+ refclk_ccc: cccrefclk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ };
+};
+
+&ccc_nw {
+ clocks = <&refclk_ccc>, <&refclk_ccc>, <&refclk_ccc>, <&refclk_ccc>,
+ <&refclk_ccc>, <&refclk_ccc>;
+ clock-names = "pll0_ref0", "pll0_ref1", "pll1_ref0", "pll1_ref1",
+ "dll0_ref", "dll1_ref";
+ status = "okay";
};
diff --git a/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts
index ec7b7c2a3ce2..90b261114763 100644
--- a/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts
+++ b/arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts
@@ -5,6 +5,8 @@
#include "mpfs.dtsi"
#include "mpfs-icicle-kit-fabric.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
/* Clock frequency (in Hz) of the rtcclk */
#define RTCCLK_FREQ 1000000
@@ -31,13 +33,41 @@
timebase-frequency = <RTCCLK_FREQ>;
};
+ leds {
+ compatible = "gpio-leds";
+
+ led-1 {
+ gpios = <&gpio2 16 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_RED>;
+ label = "led1";
+ };
+
+ led-2 {
+ gpios = <&gpio2 17 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_RED>;
+ label = "led2";
+ };
+
+ led-3 {
+ gpios = <&gpio2 18 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_AMBER>;
+ label = "led3";
+ };
+
+ led-4 {
+ gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_AMBER>;
+ label = "led4";
+ };
+ };
+
ddrc_cache_lo: memory@80000000 {
device_type = "memory";
reg = <0x0 0x80000000 0x0 0x40000000>;
status = "okay";
};
- ddrc_cache_hi: memory@1000000000 {
+ ddrc_cache_hi: memory@1040000000 {
device_type = "memory";
reg = <0x10 0x40000000 0x0 0x40000000>;
status = "okay";
@@ -149,6 +179,10 @@
clock-frequency = <125000000>;
};
+&refclk_ccc {
+ clock-frequency = <50000000>;
+};
+
&rtc {
status = "okay";
};
diff --git a/arch/riscv/boot/dts/microchip/mpfs-m100pfs-fabric.dtsi b/arch/riscv/boot/dts/microchip/mpfs-m100pfs-fabric.dtsi
index 7b9ee13b6a3a..8230f06ddf48 100644
--- a/arch/riscv/boot/dts/microchip/mpfs-m100pfs-fabric.dtsi
+++ b/arch/riscv/boot/dts/microchip/mpfs-m100pfs-fabric.dtsi
@@ -30,8 +30,8 @@
<0 0 0 3 &pcie_intc 2>,
<0 0 0 4 &pcie_intc 3>;
interrupt-map-mask = <0 0 0 7>;
- clocks = <&fabric_clk1>, <&fabric_clk1>, <&fabric_clk3>;
- clock-names = "fic0", "fic1", "fic3";
+ clocks = <&fabric_clk1>, <&fabric_clk3>;
+ clock-names = "fic0", "fic3";
ranges = <0x3000000 0x0 0x8000000 0x20 0x8000000 0x0 0x80000000>;
msi-parent = <&pcie>;
msi-controller;
diff --git a/arch/riscv/boot/dts/microchip/mpfs-polarberry-fabric.dtsi b/arch/riscv/boot/dts/microchip/mpfs-polarberry-fabric.dtsi
index 67303bc0e451..9a56de7b91d6 100644
--- a/arch/riscv/boot/dts/microchip/mpfs-polarberry-fabric.dtsi
+++ b/arch/riscv/boot/dts/microchip/mpfs-polarberry-fabric.dtsi
@@ -30,8 +30,8 @@
<0 0 0 3 &pcie_intc 2>,
<0 0 0 4 &pcie_intc 3>;
interrupt-map-mask = <0 0 0 7>;
- clocks = <&fabric_clk1>, <&fabric_clk1>, <&fabric_clk3>;
- clock-names = "fic0", "fic1", "fic3";
+ clocks = <&fabric_clk1>, <&fabric_clk3>;
+ clock-names = "fic0", "fic3";
ranges = <0x3000000 0x0 0x8000000 0x20 0x8000000 0x0 0x80000000>;
msi-parent = <&pcie>;
msi-controller;
diff --git a/arch/riscv/boot/dts/microchip/mpfs-sev-kit-fabric.dtsi b/arch/riscv/boot/dts/microchip/mpfs-sev-kit-fabric.dtsi
index 8545baf4d129..39a77df489ab 100644
--- a/arch/riscv/boot/dts/microchip/mpfs-sev-kit-fabric.dtsi
+++ b/arch/riscv/boot/dts/microchip/mpfs-sev-kit-fabric.dtsi
@@ -13,33 +13,4 @@
#clock-cells = <0>;
clock-frequency = <125000000>;
};
-
- pcie: pcie@2000000000 {
- compatible = "microchip,pcie-host-1.0";
- #address-cells = <0x3>;
- #interrupt-cells = <0x1>;
- #size-cells = <0x2>;
- device_type = "pci";
- reg = <0x20 0x0 0x0 0x8000000>, <0x0 0x43000000 0x0 0x10000>;
- reg-names = "cfg", "apb";
- bus-range = <0x0 0x7f>;
- interrupt-parent = <&plic>;
- interrupts = <119>;
- interrupt-map = <0 0 0 1 &pcie_intc 0>,
- <0 0 0 2 &pcie_intc 1>,
- <0 0 0 3 &pcie_intc 2>,
- <0 0 0 4 &pcie_intc 3>;
- interrupt-map-mask = <0 0 0 7>;
- clocks = <&fabric_clk1>, <&fabric_clk1>, <&fabric_clk3>;
- clock-names = "fic0", "fic1", "fic3";
- ranges = <0x3000000 0x0 0x8000000 0x20 0x8000000 0x0 0x80000000>;
- msi-parent = <&pcie>;
- msi-controller;
- status = "disabled";
- pcie_intc: interrupt-controller {
- #address-cells = <0>;
- #interrupt-cells = <1>;
- interrupt-controller;
- };
- };
};
diff --git a/arch/riscv/boot/dts/microchip/mpfs.dtsi b/arch/riscv/boot/dts/microchip/mpfs.dtsi
index 8f463399a568..0a9bb84af438 100644
--- a/arch/riscv/boot/dts/microchip/mpfs.dtsi
+++ b/arch/riscv/boot/dts/microchip/mpfs.dtsi
@@ -236,6 +236,38 @@
#clock-cells = <1>;
};
+ ccc_se: clock-controller@38010000 {
+ compatible = "microchip,mpfs-ccc";
+ reg = <0x0 0x38010000 0x0 0x1000>, <0x0 0x38020000 0x0 0x1000>,
+ <0x0 0x39010000 0x0 0x1000>, <0x0 0x39020000 0x0 0x1000>;
+ #clock-cells = <1>;
+ status = "disabled";
+ };
+
+ ccc_ne: clock-controller@38040000 {
+ compatible = "microchip,mpfs-ccc";
+ reg = <0x0 0x38040000 0x0 0x1000>, <0x0 0x38080000 0x0 0x1000>,
+ <0x0 0x39040000 0x0 0x1000>, <0x0 0x39080000 0x0 0x1000>;
+ #clock-cells = <1>;
+ status = "disabled";
+ };
+
+ ccc_nw: clock-controller@38100000 {
+ compatible = "microchip,mpfs-ccc";
+ reg = <0x0 0x38100000 0x0 0x1000>, <0x0 0x38200000 0x0 0x1000>,
+ <0x0 0x39100000 0x0 0x1000>, <0x0 0x39200000 0x0 0x1000>;
+ #clock-cells = <1>;
+ status = "disabled";
+ };
+
+ ccc_sw: clock-controller@38400000 {
+ compatible = "microchip,mpfs-ccc";
+ reg = <0x0 0x38400000 0x0 0x1000>, <0x0 0x38800000 0x0 0x1000>,
+ <0x0 0x39400000 0x0 0x1000>, <0x0 0x39800000 0x0 0x1000>;
+ #clock-cells = <1>;
+ status = "disabled";
+ };
+
mmuart0: serial@20000000 {
compatible = "ns16550a";
reg = <0x0 0x20000000 0x0 0x400>;
diff --git a/arch/riscv/boot/dts/renesas/Makefile b/arch/riscv/boot/dts/renesas/Makefile
new file mode 100644
index 000000000000..2d3f5751a649
--- /dev/null
+++ b/arch/riscv/boot/dts/renesas/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+dtb-$(CONFIG_ARCH_R9A07G043) += r9a07g043f01-smarc.dtb
diff --git a/arch/riscv/boot/dts/renesas/r9a07g043f.dtsi b/arch/riscv/boot/dts/renesas/r9a07g043f.dtsi
new file mode 100644
index 000000000000..6ec1c6f9a403
--- /dev/null
+++ b/arch/riscv/boot/dts/renesas/r9a07g043f.dtsi
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/*
+ * Device Tree Source for the RZ/Five SoC
+ *
+ * Copyright (C) 2022 Renesas Electronics Corp.
+ */
+
+#include <dt-bindings/interrupt-controller/irq.h>
+
+#define SOC_PERIPHERAL_IRQ(nr) (nr + 32)
+
+#include <arm64/renesas/r9a07g043.dtsi>
+
+/ {
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ timebase-frequency = <12000000>;
+
+ cpu0: cpu@0 {
+ compatible = "andestech,ax45mp", "riscv";
+ device_type = "cpu";
+ #cooling-cells = <2>;
+ reg = <0x0>;
+ status = "okay";
+ riscv,isa = "rv64imafdc";
+ mmu-type = "riscv,sv39";
+ i-cache-size = <0x8000>;
+ i-cache-line-size = <0x40>;
+ d-cache-size = <0x8000>;
+ d-cache-line-size = <0x40>;
+ clocks = <&cpg CPG_CORE R9A07G043_CLK_I>;
+ operating-points-v2 = <&cluster0_opp>;
+
+ cpu0_intc: interrupt-controller {
+ #interrupt-cells = <1>;
+ compatible = "riscv,cpu-intc";
+ interrupt-controller;
+ };
+ };
+ };
+};
+
+&soc {
+ interrupt-parent = <&plic>;
+
+ plic: interrupt-controller@12c00000 {
+ compatible = "renesas,r9a07g043-plic", "andestech,nceplic100";
+ #interrupt-cells = <2>;
+ #address-cells = <0>;
+ riscv,ndev = <511>;
+ interrupt-controller;
+ reg = <0x0 0x12c00000 0 0x400000>;
+ clocks = <&cpg CPG_MOD R9A07G043_NCEPLIC_ACLK>;
+ power-domains = <&cpg>;
+ resets = <&cpg R9A07G043_NCEPLIC_ARESETN>;
+ interrupts-extended = <&cpu0_intc 11 &cpu0_intc 9>;
+ };
+};
diff --git a/arch/riscv/boot/dts/renesas/r9a07g043f01-smarc.dts b/arch/riscv/boot/dts/renesas/r9a07g043f01-smarc.dts
new file mode 100644
index 000000000000..2aa8515451d3
--- /dev/null
+++ b/arch/riscv/boot/dts/renesas/r9a07g043f01-smarc.dts
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/*
+ * Device Tree Source for the RZ/Five SMARC EVK
+ *
+ * Copyright (C) 2022 Renesas Electronics Corp.
+ */
+
+/dts-v1/;
+
+/*
+ * DIP-Switch SW1 setting
+ * 1 : High; 0: Low
+ * SW1-2 : SW_SD0_DEV_SEL (0: uSD; 1: eMMC)
+ * SW1-3 : SW_ET0_EN_N (0: ETHER0; 1: CAN0, CAN1, SSI1, RSPI1)
+ * Please change below macros according to SW1 setting on the SoM
+ */
+#define SW_SW0_DEV_SEL 1
+#define SW_ET0_EN_N 1
+
+#include "r9a07g043f.dtsi"
+#include "rzfive-smarc-som.dtsi"
+#include "rzfive-smarc.dtsi"
+
+/ {
+ model = "Renesas SMARC EVK based on r9a07g043f01";
+ compatible = "renesas,smarc-evk", "renesas,r9a07g043f01", "renesas,r9a07g043";
+};
diff --git a/arch/riscv/boot/dts/renesas/rzfive-smarc-som.dtsi b/arch/riscv/boot/dts/renesas/rzfive-smarc-som.dtsi
new file mode 100644
index 000000000000..2b7672bc4b52
--- /dev/null
+++ b/arch/riscv/boot/dts/renesas/rzfive-smarc-som.dtsi
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/*
+ * Device Tree Source for the RZ/Five SMARC EVK SOM
+ *
+ * Copyright (C) 2022 Renesas Electronics Corp.
+ */
+
+#include <arm64/renesas/rzg2ul-smarc-som.dtsi>
+
+/ {
+ aliases {
+ /delete-property/ ethernet0;
+ /delete-property/ ethernet1;
+ };
+
+ chosen {
+ bootargs = "ignore_loglevel";
+ };
+};
+
+&dmac {
+ status = "disabled";
+};
+
+&eth0 {
+ status = "disabled";
+};
+
+&eth1 {
+ status = "disabled";
+};
+
+&ostm1 {
+ status = "disabled";
+};
+
+&ostm2 {
+ status = "disabled";
+};
+
+&sdhi0 {
+ status = "disabled";
+};
+
+&wdt0 {
+ status = "disabled";
+};
diff --git a/arch/riscv/boot/dts/renesas/rzfive-smarc.dtsi b/arch/riscv/boot/dts/renesas/rzfive-smarc.dtsi
new file mode 100644
index 000000000000..c07a487c4e5a
--- /dev/null
+++ b/arch/riscv/boot/dts/renesas/rzfive-smarc.dtsi
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/*
+ * Device Tree Source for the RZ/Five SMARC EVK carrier board
+ *
+ * Copyright (C) 2022 Renesas Electronics Corp.
+ */
+
+#include <arm64/renesas/rzg2ul-smarc.dtsi>
+
+&ehci0 {
+ status = "disabled";
+};
+
+&ehci1 {
+ status = "disabled";
+};
+
+&hsusb {
+ status = "disabled";
+};
+
+&ohci0 {
+ status = "disabled";
+};
+
+&ohci1 {
+ status = "disabled";
+};
+
+&phyrst {
+ status = "disabled";
+};
+
+&sdhi1 {
+ status = "disabled";
+};
+
+&snd_rzg2l {
+ status = "disabled";
+};
+
+&spi1 {
+ status = "disabled";
+};
+
+&ssi1 {
+ status = "disabled";
+};
+
+&usb0_vbus_otg {
+ status = "disabled";
+};
+
+&usb2_phy0 {
+ status = "disabled";
+};
+
+&usb2_phy1 {
+ status = "disabled";
+};
+
+&vccq_sdhi1 {
+ status = "disabled";
+};
diff --git a/arch/riscv/boot/dts/starfive/Makefile b/arch/riscv/boot/dts/starfive/Makefile
index 0ea1bc15ab30..039c143cba33 100644
--- a/arch/riscv/boot/dts/starfive/Makefile
+++ b/arch/riscv/boot/dts/starfive/Makefile
@@ -1,2 +1,2 @@
# SPDX-License-Identifier: GPL-2.0
-dtb-$(CONFIG_SOC_STARFIVE) += jh7100-beaglev-starlight.dtb
+dtb-$(CONFIG_SOC_STARFIVE) += jh7100-beaglev-starlight.dtb jh7100-starfive-visionfive-v1.dtb
diff --git a/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts b/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts
index f7a230110512..7cda3a89020a 100644
--- a/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts
+++ b/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts
@@ -5,160 +5,9 @@
*/
/dts-v1/;
-#include "jh7100.dtsi"
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/leds/common.h>
-#include <dt-bindings/pinctrl/pinctrl-starfive-jh7100.h>
+#include "jh7100-common.dtsi"
/ {
model = "BeagleV Starlight Beta";
compatible = "beagle,beaglev-starlight-jh7100-r0", "starfive,jh7100";
-
- aliases {
- serial0 = &uart3;
- };
-
- chosen {
- stdout-path = "serial0:115200n8";
- };
-
- cpus {
- timebase-frequency = <6250000>;
- };
-
- memory@80000000 {
- device_type = "memory";
- reg = <0x0 0x80000000 0x2 0x0>;
- };
-
- leds {
- compatible = "gpio-leds";
-
- led-ack {
- gpios = <&gpio 43 GPIO_ACTIVE_HIGH>;
- color = <LED_COLOR_ID_GREEN>;
- function = LED_FUNCTION_HEARTBEAT;
- linux,default-trigger = "heartbeat";
- label = "ack";
- };
- };
-};
-
-&gpio {
- i2c0_pins: i2c0-0 {
- i2c-pins {
- pinmux = <GPIOMUX(62, GPO_LOW,
- GPO_I2C0_PAD_SCK_OEN,
- GPI_I2C0_PAD_SCK_IN)>,
- <GPIOMUX(61, GPO_LOW,
- GPO_I2C0_PAD_SDA_OEN,
- GPI_I2C0_PAD_SDA_IN)>;
- bias-disable; /* external pull-up */
- input-enable;
- input-schmitt-enable;
- };
- };
-
- i2c1_pins: i2c1-0 {
- i2c-pins {
- pinmux = <GPIOMUX(47, GPO_LOW,
- GPO_I2C1_PAD_SCK_OEN,
- GPI_I2C1_PAD_SCK_IN)>,
- <GPIOMUX(48, GPO_LOW,
- GPO_I2C1_PAD_SDA_OEN,
- GPI_I2C1_PAD_SDA_IN)>;
- bias-pull-up;
- input-enable;
- input-schmitt-enable;
- };
- };
-
- i2c2_pins: i2c2-0 {
- i2c-pins {
- pinmux = <GPIOMUX(60, GPO_LOW,
- GPO_I2C2_PAD_SCK_OEN,
- GPI_I2C2_PAD_SCK_IN)>,
- <GPIOMUX(59, GPO_LOW,
- GPO_I2C2_PAD_SDA_OEN,
- GPI_I2C2_PAD_SDA_IN)>;
- bias-disable; /* external pull-up */
- input-enable;
- input-schmitt-enable;
- };
- };
-
- uart3_pins: uart3-0 {
- rx-pins {
- pinmux = <GPIOMUX(13, GPO_LOW, GPO_DISABLE,
- GPI_UART3_PAD_SIN)>;
- bias-pull-up;
- drive-strength = <14>;
- input-enable;
- input-schmitt-enable;
- slew-rate = <0>;
- };
- tx-pins {
- pinmux = <GPIOMUX(14, GPO_UART3_PAD_SOUT,
- GPO_ENABLE, GPI_NONE)>;
- bias-disable;
- drive-strength = <35>;
- input-disable;
- input-schmitt-disable;
- slew-rate = <0>;
- };
- };
-};
-
-&i2c0 {
- clock-frequency = <100000>;
- i2c-sda-hold-time-ns = <300>;
- i2c-sda-falling-time-ns = <500>;
- i2c-scl-falling-time-ns = <500>;
- pinctrl-names = "default";
- pinctrl-0 = <&i2c0_pins>;
- status = "okay";
-
- pmic@5e {
- compatible = "ti,tps65086";
- reg = <0x5e>;
- gpio-controller;
- #gpio-cells = <2>;
-
- regulators {
- };
- };
-};
-
-&i2c1 {
- clock-frequency = <400000>;
- i2c-sda-hold-time-ns = <300>;
- i2c-sda-falling-time-ns = <100>;
- i2c-scl-falling-time-ns = <100>;
- pinctrl-names = "default";
- pinctrl-0 = <&i2c1_pins>;
- status = "okay";
-};
-
-&i2c2 {
- clock-frequency = <100000>;
- i2c-sda-hold-time-ns = <300>;
- i2c-sda-falling-time-ns = <500>;
- i2c-scl-falling-time-ns = <500>;
- pinctrl-names = "default";
- pinctrl-0 = <&i2c2_pins>;
- status = "okay";
-};
-
-&osc_sys {
- clock-frequency = <25000000>;
-};
-
-&osc_aud {
- clock-frequency = <27000000>;
-};
-
-&uart3 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart3_pins>;
- status = "okay";
};
diff --git a/arch/riscv/boot/dts/starfive/jh7100-common.dtsi b/arch/riscv/boot/dts/starfive/jh7100-common.dtsi
new file mode 100644
index 000000000000..b93ce351a90f
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7100-common.dtsi
@@ -0,0 +1,161 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2021 StarFive Technology Co., Ltd.
+ * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
+ */
+
+/dts-v1/;
+#include "jh7100.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/pinctrl/pinctrl-starfive-jh7100.h>
+
+/ {
+ aliases {
+ serial0 = &uart3;
+ };
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ cpus {
+ timebase-frequency = <6250000>;
+ };
+
+ memory@80000000 {
+ device_type = "memory";
+ reg = <0x0 0x80000000 0x2 0x0>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ led-ack {
+ gpios = <&gpio 43 GPIO_ACTIVE_HIGH>;
+ color = <LED_COLOR_ID_GREEN>;
+ function = LED_FUNCTION_HEARTBEAT;
+ linux,default-trigger = "heartbeat";
+ label = "ack";
+ };
+ };
+};
+
+&gpio {
+ i2c0_pins: i2c0-0 {
+ i2c-pins {
+ pinmux = <GPIOMUX(62, GPO_LOW,
+ GPO_I2C0_PAD_SCK_OEN,
+ GPI_I2C0_PAD_SCK_IN)>,
+ <GPIOMUX(61, GPO_LOW,
+ GPO_I2C0_PAD_SDA_OEN,
+ GPI_I2C0_PAD_SDA_IN)>;
+ bias-disable; /* external pull-up */
+ input-enable;
+ input-schmitt-enable;
+ };
+ };
+
+ i2c1_pins: i2c1-0 {
+ i2c-pins {
+ pinmux = <GPIOMUX(47, GPO_LOW,
+ GPO_I2C1_PAD_SCK_OEN,
+ GPI_I2C1_PAD_SCK_IN)>,
+ <GPIOMUX(48, GPO_LOW,
+ GPO_I2C1_PAD_SDA_OEN,
+ GPI_I2C1_PAD_SDA_IN)>;
+ bias-pull-up;
+ input-enable;
+ input-schmitt-enable;
+ };
+ };
+
+ i2c2_pins: i2c2-0 {
+ i2c-pins {
+ pinmux = <GPIOMUX(60, GPO_LOW,
+ GPO_I2C2_PAD_SCK_OEN,
+ GPI_I2C2_PAD_SCK_IN)>,
+ <GPIOMUX(59, GPO_LOW,
+ GPO_I2C2_PAD_SDA_OEN,
+ GPI_I2C2_PAD_SDA_IN)>;
+ bias-disable; /* external pull-up */
+ input-enable;
+ input-schmitt-enable;
+ };
+ };
+
+ uart3_pins: uart3-0 {
+ rx-pins {
+ pinmux = <GPIOMUX(13, GPO_LOW, GPO_DISABLE,
+ GPI_UART3_PAD_SIN)>;
+ bias-pull-up;
+ drive-strength = <14>;
+ input-enable;
+ input-schmitt-enable;
+ slew-rate = <0>;
+ };
+ tx-pins {
+ pinmux = <GPIOMUX(14, GPO_UART3_PAD_SOUT,
+ GPO_ENABLE, GPI_NONE)>;
+ bias-disable;
+ drive-strength = <35>;
+ input-disable;
+ input-schmitt-disable;
+ slew-rate = <0>;
+ };
+ };
+};
+
+&i2c0 {
+ clock-frequency = <100000>;
+ i2c-sda-hold-time-ns = <300>;
+ i2c-sda-falling-time-ns = <500>;
+ i2c-scl-falling-time-ns = <500>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c0_pins>;
+ status = "okay";
+
+ pmic@5e {
+ compatible = "ti,tps65086";
+ reg = <0x5e>;
+ gpio-controller;
+ #gpio-cells = <2>;
+
+ regulators {
+ };
+ };
+};
+
+&i2c1 {
+ clock-frequency = <400000>;
+ i2c-sda-hold-time-ns = <300>;
+ i2c-sda-falling-time-ns = <100>;
+ i2c-scl-falling-time-ns = <100>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c1_pins>;
+ status = "okay";
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ i2c-sda-hold-time-ns = <300>;
+ i2c-sda-falling-time-ns = <500>;
+ i2c-scl-falling-time-ns = <500>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&i2c2_pins>;
+ status = "okay";
+};
+
+&osc_sys {
+ clock-frequency = <25000000>;
+};
+
+&osc_aud {
+ clock-frequency = <27000000>;
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&uart3_pins>;
+ status = "okay";
+};
diff --git a/arch/riscv/boot/dts/starfive/jh7100-starfive-visionfive-v1.dts b/arch/riscv/boot/dts/starfive/jh7100-starfive-visionfive-v1.dts
new file mode 100644
index 000000000000..e82af72f1aaf
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/jh7100-starfive-visionfive-v1.dts
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0 OR MIT
+/*
+ * Copyright (C) 2021 StarFive Technology Co., Ltd.
+ * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
+ */
+
+/dts-v1/;
+#include "jh7100-common.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+ model = "StarFive VisionFive V1";
+ compatible = "starfive,visionfive-v1", "starfive,jh7100";
+
+ gpio-restart {
+ compatible = "gpio-restart";
+ gpios = <&gpio 63 GPIO_ACTIVE_HIGH>;
+ priority = <224>;
+ };
+};
diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig
index 05fd5fcf24f9..f7f32448f160 100644
--- a/arch/riscv/configs/defconfig
+++ b/arch/riscv/configs/defconfig
@@ -26,6 +26,7 @@ CONFIG_EXPERT=y
# CONFIG_SYSFS_SYSCALL is not set
CONFIG_PROFILING=y
CONFIG_SOC_MICROCHIP_POLARFIRE=y
+CONFIG_ARCH_RENESAS=y
CONFIG_SOC_SIFIVE=y
CONFIG_SOC_STARFIVE=y
CONFIG_SOC_VIRT=y
@@ -123,6 +124,7 @@ CONFIG_INPUT_MOUSEDEV=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SERIAL_SH_SCI=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_VIRTIO=y
@@ -159,6 +161,7 @@ CONFIG_VIRTIO_MMIO=y
CONFIG_RPMSG_CHAR=y
CONFIG_RPMSG_CTRL=y
CONFIG_RPMSG_VIRTIO=y
+CONFIG_ARCH_R9A07G043=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
diff --git a/arch/riscv/configs/nommu_k210_defconfig b/arch/riscv/configs/nommu_k210_defconfig
index 96fe8def644c..79b3ccd58ff0 100644
--- a/arch/riscv/configs/nommu_k210_defconfig
+++ b/arch/riscv/configs/nommu_k210_defconfig
@@ -25,7 +25,8 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_EMBEDDED=y
# CONFIG_VM_EVENT_COUNTERS is not set
# CONFIG_COMPAT_BRK is not set
-CONFIG_SLOB=y
+CONFIG_SLUB=y
+CONFIG_SLUB_TINY=y
# CONFIG_MMU is not set
CONFIG_SOC_CANAAN=y
CONFIG_NONPORTABLE=y
diff --git a/arch/riscv/configs/nommu_k210_sdcard_defconfig b/arch/riscv/configs/nommu_k210_sdcard_defconfig
index 379740654373..6b80bb13b8ed 100644
--- a/arch/riscv/configs/nommu_k210_sdcard_defconfig
+++ b/arch/riscv/configs/nommu_k210_sdcard_defconfig
@@ -17,7 +17,8 @@ CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_EMBEDDED=y
# CONFIG_VM_EVENT_COUNTERS is not set
# CONFIG_COMPAT_BRK is not set
-CONFIG_SLOB=y
+CONFIG_SLUB=y
+CONFIG_SLUB_TINY=y
# CONFIG_MMU is not set
CONFIG_SOC_CANAAN=y
CONFIG_NONPORTABLE=y
diff --git a/arch/riscv/configs/nommu_virt_defconfig b/arch/riscv/configs/nommu_virt_defconfig
index 1a56eda5ce46..4cf0f297091e 100644
--- a/arch/riscv/configs/nommu_virt_defconfig
+++ b/arch/riscv/configs/nommu_virt_defconfig
@@ -22,7 +22,8 @@ CONFIG_EXPERT=y
# CONFIG_KALLSYMS is not set
# CONFIG_VM_EVENT_COUNTERS is not set
# CONFIG_COMPAT_BRK is not set
-CONFIG_SLOB=y
+CONFIG_SLUB=y
+CONFIG_SLUB_TINY=y
# CONFIG_MMU is not set
CONFIG_SOC_VIRT=y
CONFIG_NONPORTABLE=y
diff --git a/arch/riscv/include/asm/efi.h b/arch/riscv/include/asm/efi.h
index e229d7be4b66..47d3ab0fcc36 100644
--- a/arch/riscv/include/asm/efi.h
+++ b/arch/riscv/include/asm/efi.h
@@ -35,13 +35,20 @@ static inline unsigned long efi_get_max_initrd_addr(unsigned long image_addr)
return ULONG_MAX;
}
-#define alloc_screen_info(x...) (&screen_info)
-
-static inline void free_screen_info(struct screen_info *si)
+static inline unsigned long efi_get_kimg_min_align(void)
{
+ /*
+ * RISC-V requires the kernel image to placed 2 MB aligned base for 64
+ * bit and 4MB for 32 bit.
+ */
+ return IS_ENABLED(CONFIG_64BIT) ? SZ_2M : SZ_4M;
}
+#define EFI_KIMG_PREFERRED_ADDRESS efi_get_kimg_min_align()
+
void efi_virtmap_load(void);
void efi_virtmap_unload(void);
+unsigned long stext_offset(void);
+
#endif /* _ASM_EFI_H */
diff --git a/arch/riscv/include/asm/stackprotector.h b/arch/riscv/include/asm/stackprotector.h
index 09093af46565..43895b90fe3f 100644
--- a/arch/riscv/include/asm/stackprotector.h
+++ b/arch/riscv/include/asm/stackprotector.h
@@ -3,9 +3,6 @@
#ifndef _ASM_RISCV_STACKPROTECTOR_H
#define _ASM_RISCV_STACKPROTECTOR_H
-#include <linux/random.h>
-#include <linux/version.h>
-
extern unsigned long __stack_chk_guard;
/*
@@ -16,12 +13,7 @@ extern unsigned long __stack_chk_guard;
*/
static __always_inline void boot_init_stack_canary(void)
{
- unsigned long canary;
-
- /* Try to get a semi random initial value. */
- get_random_bytes(&canary, sizeof(canary));
- canary ^= LINUX_VERSION_CODE;
- canary &= CANARY_MASK;
+ unsigned long canary = get_random_canary();
current->stack_canary = canary;
if (!IS_ENABLED(CONFIG_STACKPROTECTOR_PER_TASK))
diff --git a/arch/riscv/kernel/image-vars.h b/arch/riscv/kernel/image-vars.h
index d6e5f739905e..7e2962ef73f9 100644
--- a/arch/riscv/kernel/image-vars.h
+++ b/arch/riscv/kernel/image-vars.h
@@ -23,13 +23,7 @@
* linked at. The routines below are all implemented in assembler in a
* position independent manner
*/
-__efistub_memcmp = memcmp;
-__efistub_memchr = memchr;
-__efistub_strlen = strlen;
-__efistub_strnlen = strnlen;
__efistub_strcmp = strcmp;
-__efistub_strncmp = strncmp;
-__efistub_strrchr = strrchr;
__efistub__start = _start;
__efistub__start_kernel = _start_kernel;
diff --git a/arch/riscv/kernel/vdso.c b/arch/riscv/kernel/vdso.c
index 123d05255fcf..e410275918ac 100644
--- a/arch/riscv/kernel/vdso.c
+++ b/arch/riscv/kernel/vdso.c
@@ -137,28 +137,6 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
mmap_read_unlock(mm);
return 0;
}
-
-static struct page *find_timens_vvar_page(struct vm_area_struct *vma)
-{
- if (likely(vma->vm_mm == current->mm))
- return current->nsproxy->time_ns->vvar_page;
-
- /*
- * VM_PFNMAP | VM_IO protect .fault() handler from being called
- * through interfaces like /proc/$pid/mem or
- * process_vm_{readv,writev}() as long as there's no .access()
- * in special_mapping_vmops.
- * For more details check_vma_flags() and __access_remote_vm()
- */
- WARN(1, "vvar_page accessed remotely");
-
- return NULL;
-}
-#else
-static struct page *find_timens_vvar_page(struct vm_area_struct *vma)
-{
- return NULL;
-}
#endif
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index de575af02ffe..7fd08755a1f9 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -26,6 +26,10 @@ config GENERIC_BUG
config GENERIC_BUG_RELATIVE_POINTERS
def_bool y
+config GENERIC_CSUM
+ bool
+ default y if KASAN
+
config GENERIC_LOCKBREAK
def_bool y if PREEMPTION
@@ -73,6 +77,7 @@ config S390
select ARCH_HAS_GIGANTIC_PAGE
select ARCH_HAS_KCOV
select ARCH_HAS_MEM_ENCRYPT
+ select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
select ARCH_HAS_PTE_SPECIAL
select ARCH_HAS_SCALED_CPUTIME
select ARCH_HAS_SET_MEMORY
@@ -121,6 +126,7 @@ config S390
select ARCH_WANTS_NO_INSTR
select ARCH_WANT_DEFAULT_BPF_JIT
select ARCH_WANT_IPC_PARSE_VERSION
+ select ARCH_WANT_HUGETLB_PAGE_OPTIMIZE_VMEMMAP
select BUILDTIME_TABLE_SORT
select CLONE_BACKWARDS2
select DMA_OPS if PCI
@@ -196,6 +202,7 @@ config S390
select HAVE_RSEQ
select HAVE_SAMPLE_FTRACE_DIRECT
select HAVE_SAMPLE_FTRACE_DIRECT_MULTI
+ select HAVE_SETUP_PER_CPU_AREA
select HAVE_SOFTIRQ_ON_OWN_STACK
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_VIRT_CPU_ACCOUNTING
@@ -207,6 +214,7 @@ config S390
select MMU_GATHER_MERGE_VMAS
select MODULES_USE_ELF_RELA
select NEED_DMA_MAP_STATE if PCI
+ select NEED_PER_CPU_EMBED_FIRST_CHUNK
select NEED_SG_DMA_LENGTH if PCI
select OLD_SIGACTION
select OLD_SIGSUSPEND3
diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c
index d74a4c7d5df6..c0fd29133f27 100644
--- a/arch/s390/appldata/appldata_base.c
+++ b/arch/s390/appldata/appldata_base.c
@@ -26,8 +26,6 @@
#include <linux/notifier.h>
#include <linux/cpu.h>
#include <linux/workqueue.h>
-#include <linux/suspend.h>
-#include <linux/platform_device.h>
#include <asm/appldata.h>
#include <asm/vtimer.h>
#include <linux/uaccess.h>
@@ -44,8 +42,6 @@
#define TOD_MICRO 0x01000 /* nr. of TOD clock units
for 1 microsecond */
-static struct platform_device *appldata_pdev;
-
/*
* /proc entries (sysctl)
*/
@@ -88,7 +84,6 @@ static struct vtimer_list appldata_timer;
static DEFINE_SPINLOCK(appldata_timer_lock);
static int appldata_interval = APPLDATA_CPU_INTERVAL;
static int appldata_timer_active;
-static int appldata_timer_suspended = 0;
/*
* Work queue
@@ -412,88 +407,6 @@ void appldata_unregister_ops(struct appldata_ops *ops)
/********************** module-ops management <END> **************************/
-/**************************** suspend / resume *******************************/
-static int appldata_freeze(struct device *dev)
-{
- struct appldata_ops *ops;
- int rc;
- struct list_head *lh;
-
- spin_lock(&appldata_timer_lock);
- if (appldata_timer_active) {
- __appldata_vtimer_setup(APPLDATA_DEL_TIMER);
- appldata_timer_suspended = 1;
- }
- spin_unlock(&appldata_timer_lock);
-
- mutex_lock(&appldata_ops_mutex);
- list_for_each(lh, &appldata_ops_list) {
- ops = list_entry(lh, struct appldata_ops, list);
- if (ops->active == 1) {
- rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC,
- (unsigned long) ops->data, ops->size,
- ops->mod_lvl);
- if (rc != 0)
- pr_err("Stopping the data collection for %s "
- "failed with rc=%d\n", ops->name, rc);
- }
- }
- mutex_unlock(&appldata_ops_mutex);
- return 0;
-}
-
-static int appldata_restore(struct device *dev)
-{
- struct appldata_ops *ops;
- int rc;
- struct list_head *lh;
-
- spin_lock(&appldata_timer_lock);
- if (appldata_timer_suspended) {
- __appldata_vtimer_setup(APPLDATA_ADD_TIMER);
- appldata_timer_suspended = 0;
- }
- spin_unlock(&appldata_timer_lock);
-
- mutex_lock(&appldata_ops_mutex);
- list_for_each(lh, &appldata_ops_list) {
- ops = list_entry(lh, struct appldata_ops, list);
- if (ops->active == 1) {
- ops->callback(ops->data); // init record
- rc = appldata_diag(ops->record_nr,
- APPLDATA_START_INTERVAL_REC,
- (unsigned long) ops->data, ops->size,
- ops->mod_lvl);
- if (rc != 0) {
- pr_err("Starting the data collection for %s "
- "failed with rc=%d\n", ops->name, rc);
- }
- }
- }
- mutex_unlock(&appldata_ops_mutex);
- return 0;
-}
-
-static int appldata_thaw(struct device *dev)
-{
- return appldata_restore(dev);
-}
-
-static const struct dev_pm_ops appldata_pm_ops = {
- .freeze = appldata_freeze,
- .thaw = appldata_thaw,
- .restore = appldata_restore,
-};
-
-static struct platform_driver appldata_pdrv = {
- .driver = {
- .name = "appldata",
- .pm = &appldata_pm_ops,
- },
-};
-/************************* suspend / resume <END> ****************************/
-
-
/******************************* init / exit *********************************/
/*
@@ -503,36 +416,14 @@ static struct platform_driver appldata_pdrv = {
*/
static int __init appldata_init(void)
{
- int rc;
-
init_virt_timer(&appldata_timer);
appldata_timer.function = appldata_timer_function;
appldata_timer.data = (unsigned long) &appldata_work;
-
- rc = platform_driver_register(&appldata_pdrv);
- if (rc)
- return rc;
-
- appldata_pdev = platform_device_register_simple("appldata", -1, NULL,
- 0);
- if (IS_ERR(appldata_pdev)) {
- rc = PTR_ERR(appldata_pdev);
- goto out_driver;
- }
appldata_wq = alloc_ordered_workqueue("appldata", 0);
- if (!appldata_wq) {
- rc = -ENOMEM;
- goto out_device;
- }
-
+ if (!appldata_wq)
+ return -ENOMEM;
appldata_sysctl_header = register_sysctl_table(appldata_dir_table);
return 0;
-
-out_device:
- platform_device_unregister(appldata_pdev);
-out_driver:
- platform_driver_unregister(&appldata_pdrv);
- return rc;
}
__initcall(appldata_init);
diff --git a/arch/s390/boot/ipl_parm.c b/arch/s390/boot/ipl_parm.c
index ca78d6162245..c1f8f7999fed 100644
--- a/arch/s390/boot/ipl_parm.c
+++ b/arch/s390/boot/ipl_parm.c
@@ -77,6 +77,9 @@ bool is_ipl_block_dump(void)
if (ipl_block.pb0_hdr.pbt == IPL_PBT_NVME &&
ipl_block.nvme.opt == IPL_PB0_NVME_OPT_DUMP)
return true;
+ if (ipl_block.pb0_hdr.pbt == IPL_PBT_ECKD &&
+ ipl_block.eckd.opt == IPL_PB0_ECKD_OPT_DUMP)
+ return true;
return false;
}
@@ -108,6 +111,11 @@ static size_t ipl_block_get_ascii_scpdata(char *dest, size_t size,
scp_data_len = ipb->nvme.scp_data_len;
scp_data = ipb->nvme.scp_data;
break;
+ case IPL_PBT_ECKD:
+ scp_data_len = ipb->eckd.scp_data_len;
+ scp_data = ipb->eckd.scp_data;
+ break;
+
default:
goto out;
}
@@ -153,6 +161,7 @@ static void append_ipl_block_parm(void)
break;
case IPL_PBT_FCP:
case IPL_PBT_NVME:
+ case IPL_PBT_ECKD:
rc = ipl_block_get_ascii_scpdata(
parm, COMMAND_LINE_SIZE - len - 1, &ipl_block);
break;
diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig
index 63807bd0b536..a7b4e1d82758 100644
--- a/arch/s390/configs/debug_defconfig
+++ b/arch/s390/configs/debug_defconfig
@@ -573,8 +573,6 @@ CONFIG_VIRTIO_CONSOLE=m
CONFIG_HW_RANDOM_VIRTIO=m
CONFIG_HANGCHECK_TIMER=m
CONFIG_TN3270_FS=y
-# CONFIG_RANDOM_TRUST_CPU is not set
-# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
CONFIG_PPS=m
# CONFIG_PTP_1588_CLOCK is not set
# CONFIG_HWMON is not set
diff --git a/arch/s390/configs/defconfig b/arch/s390/configs/defconfig
index 4f9a98247442..2bc2d0fe5774 100644
--- a/arch/s390/configs/defconfig
+++ b/arch/s390/configs/defconfig
@@ -563,8 +563,6 @@ CONFIG_VIRTIO_CONSOLE=m
CONFIG_HW_RANDOM_VIRTIO=m
CONFIG_HANGCHECK_TIMER=m
CONFIG_TN3270_FS=y
-# CONFIG_RANDOM_TRUST_CPU is not set
-# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
# CONFIG_PTP_1588_CLOCK is not set
# CONFIG_HWMON is not set
CONFIG_WATCHDOG=y
diff --git a/arch/s390/configs/zfcpdump_defconfig b/arch/s390/configs/zfcpdump_defconfig
index 5fe9948be644..ae14ab0b864d 100644
--- a/arch/s390/configs/zfcpdump_defconfig
+++ b/arch/s390/configs/zfcpdump_defconfig
@@ -58,7 +58,6 @@ CONFIG_ZFCP=y
# CONFIG_VMCP is not set
# CONFIG_MONWRITER is not set
# CONFIG_S390_VMUR is not set
-# CONFIG_RANDOM_TRUST_BOOTLOADER is not set
# CONFIG_HID is not set
# CONFIG_VIRTIO_MENU is not set
# CONFIG_VHOST_MENU is not set
diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c
index 6511d15ace45..c3be533c4cd3 100644
--- a/arch/s390/hypfs/hypfs_diag.c
+++ b/arch/s390/hypfs/hypfs_diag.c
@@ -68,14 +68,6 @@ static inline __u8 info_blk_hdr__flags(enum diag204_format type, void *hdr)
return ((struct diag204_x_info_blk_hdr *)hdr)->flags;
}
-static inline __u16 info_blk_hdr__pcpus(enum diag204_format type, void *hdr)
-{
- if (type == DIAG204_INFO_SIMPLE)
- return ((struct diag204_info_blk_hdr *)hdr)->phys_cpus;
- else /* DIAG204_INFO_EXT */
- return ((struct diag204_x_info_blk_hdr *)hdr)->phys_cpus;
-}
-
/* Partition header */
static inline int part_hdr__size(enum diag204_format type)
diff --git a/arch/s390/include/asm/bugs.h b/arch/s390/include/asm/bugs.h
deleted file mode 100644
index aa42a179be33..000000000000
--- a/arch/s390/include/asm/bugs.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * S390 version
- * Copyright IBM Corp. 1999
- * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
- *
- * Derived from "include/asm-i386/bugs.h"
- * Copyright (C) 1994 Linus Torvalds
- */
-
-/*
- * This is included by init/main.c to check for architecture-dependent bugs.
- *
- * Needs:
- * void check_bugs(void);
- */
-
-static inline void check_bugs(void)
-{
- /* s390 has no bugs ... */
-}
diff --git a/arch/s390/include/asm/checksum.h b/arch/s390/include/asm/checksum.h
index cdd19d326345..d977a3a2f619 100644
--- a/arch/s390/include/asm/checksum.h
+++ b/arch/s390/include/asm/checksum.h
@@ -12,6 +12,12 @@
#ifndef _S390_CHECKSUM_H
#define _S390_CHECKSUM_H
+#ifdef CONFIG_GENERIC_CSUM
+
+#include <asm-generic/checksum.h>
+
+#else /* CONFIG_GENERIC_CSUM */
+
#include <linux/uaccess.h>
#include <linux/in6.h>
@@ -129,4 +135,5 @@ static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
return csum_fold((__force __wsum)(sum >> 32));
}
+#endif /* CONFIG_GENERIC_CSUM */
#endif /* _S390_CHECKSUM_H */
diff --git a/arch/s390/include/asm/ftrace.h b/arch/s390/include/asm/ftrace.h
index 6f80ec9c04be..e5c5cb1207e2 100644
--- a/arch/s390/include/asm/ftrace.h
+++ b/arch/s390/include/asm/ftrace.h
@@ -54,12 +54,33 @@ static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *
return NULL;
}
-static __always_inline void ftrace_instruction_pointer_set(struct ftrace_regs *fregs,
- unsigned long ip)
+static __always_inline unsigned long
+ftrace_regs_get_instruction_pointer(const struct ftrace_regs *fregs)
+{
+ return fregs->regs.psw.addr;
+}
+
+static __always_inline void
+ftrace_regs_set_instruction_pointer(struct ftrace_regs *fregs,
+ unsigned long ip)
{
fregs->regs.psw.addr = ip;
}
+#define ftrace_regs_get_argument(fregs, n) \
+ regs_get_kernel_argument(&(fregs)->regs, n)
+#define ftrace_regs_get_stack_pointer(fregs) \
+ kernel_stack_pointer(&(fregs)->regs)
+#define ftrace_regs_return_value(fregs) \
+ regs_return_value(&(fregs)->regs)
+#define ftrace_regs_set_return_value(fregs, ret) \
+ regs_set_return_value(&(fregs)->regs, ret)
+#define ftrace_override_function_with_return(fregs) \
+ override_function_with_return(&(fregs)->regs)
+#define ftrace_regs_query_register_offset(name) \
+ regs_query_register_offset(name)
+
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
/*
* When an ftrace registered caller is tracing a function that is
* also set by a register_ftrace_direct() call, it needs to be
@@ -67,10 +88,12 @@ static __always_inline void ftrace_instruction_pointer_set(struct ftrace_regs *f
* place the direct caller in the ORIG_GPR2 part of pt_regs. This
* tells the ftrace_caller that there's a direct caller.
*/
-static inline void arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr)
+static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, unsigned long addr)
{
+ struct pt_regs *regs = &fregs->regs;
regs->orig_gpr2 = addr;
}
+#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
/*
* Even though the system call numbers are identical for s390/s390x a
diff --git a/arch/s390/include/asm/ipl.h b/arch/s390/include/asm/ipl.h
index a405b6bb89fb..b0d00032479d 100644
--- a/arch/s390/include/asm/ipl.h
+++ b/arch/s390/include/asm/ipl.h
@@ -22,6 +22,7 @@ struct ipl_parameter_block {
struct ipl_pb0_common common;
struct ipl_pb0_fcp fcp;
struct ipl_pb0_ccw ccw;
+ struct ipl_pb0_eckd eckd;
struct ipl_pb0_nvme nvme;
char raw[PAGE_SIZE - sizeof(struct ipl_pl_hdr)];
};
@@ -41,6 +42,10 @@ struct ipl_parameter_block {
sizeof(struct ipl_pb0_ccw))
#define IPL_BP0_CCW_LEN (sizeof(struct ipl_pb0_ccw))
+#define IPL_BP_ECKD_LEN (sizeof(struct ipl_pl_hdr) + \
+ sizeof(struct ipl_pb0_eckd))
+#define IPL_BP0_ECKD_LEN (sizeof(struct ipl_pb0_eckd))
+
#define IPL_MAX_SUPPORTED_VERSION (0)
#define IPL_RB_CERT_UNKNOWN ((unsigned short)-1)
@@ -68,6 +73,8 @@ enum ipl_type {
IPL_TYPE_NSS = 16,
IPL_TYPE_NVME = 32,
IPL_TYPE_NVME_DUMP = 64,
+ IPL_TYPE_ECKD = 128,
+ IPL_TYPE_ECKD_DUMP = 256,
};
struct ipl_info
@@ -79,6 +86,9 @@ struct ipl_info
} ccw;
struct {
struct ccw_dev_id dev_id;
+ } eckd;
+ struct {
+ struct ccw_dev_id dev_id;
u64 wwpn;
u64 lun;
} fcp;
@@ -99,6 +109,7 @@ extern void set_os_info_reipl_block(void);
static inline bool is_ipl_type_dump(void)
{
return (ipl_info.type == IPL_TYPE_FCP_DUMP) ||
+ (ipl_info.type == IPL_TYPE_ECKD_DUMP) ||
(ipl_info.type == IPL_TYPE_NVME_DUMP);
}
diff --git a/arch/s390/include/asm/pai.h b/arch/s390/include/asm/pai.h
index 1a8a6b15d121..7d1888e3dee6 100644
--- a/arch/s390/include/asm/pai.h
+++ b/arch/s390/include/asm/pai.h
@@ -75,4 +75,10 @@ static __always_inline void pai_kernel_exit(struct pt_regs *regs)
WRITE_ONCE(S390_lowcore.ccd, S390_lowcore.ccd & ~PAI_CRYPTO_KERNEL_OFFSET);
}
+enum paievt_mode {
+ PAI_MODE_NONE,
+ PAI_MODE_SAMPLING,
+ PAI_MODE_COUNTING,
+};
+
#endif
diff --git a/arch/s390/include/asm/sclp.h b/arch/s390/include/asm/sclp.h
index 9d4c7f71e070..dac7da88f61f 100644
--- a/arch/s390/include/asm/sclp.h
+++ b/arch/s390/include/asm/sclp.h
@@ -87,6 +87,7 @@ struct sclp_info {
unsigned char has_gisaf : 1;
unsigned char has_diag318 : 1;
unsigned char has_sipl : 1;
+ unsigned char has_sipl_eckd : 1;
unsigned char has_dirq : 1;
unsigned char has_iplcc : 1;
unsigned char has_zpci_lsi : 1;
@@ -131,6 +132,7 @@ void sclp_early_get_ipl_info(struct sclp_ipl_info *info);
void sclp_early_detect(void);
void sclp_early_printk(const char *s);
void __sclp_early_printk(const char *s, unsigned int len);
+void sclp_emergency_printk(const char *s);
int sclp_early_get_memsize(unsigned long *mem);
int sclp_early_get_hsa_size(unsigned long *hsa_size);
diff --git a/arch/s390/include/asm/serial.h b/arch/s390/include/asm/serial.h
deleted file mode 100644
index aaf85a69061c..000000000000
--- a/arch/s390/include/asm/serial.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_S390_SERIAL_H
-#define _ASM_S390_SERIAL_H
-
-#define BASE_BAUD 0
-
-#endif /* _ASM_S390_SERIAL_H */
diff --git a/arch/s390/include/asm/shmparam.h b/arch/s390/include/asm/shmparam.h
deleted file mode 100644
index e75d45649c54..000000000000
--- a/arch/s390/include/asm/shmparam.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * S390 version
- *
- * Derived from "include/asm-i386/shmparam.h"
- */
-#ifndef _ASM_S390_SHMPARAM_H
-#define _ASM_S390_SHMPARAM_H
-
-#define SHMLBA PAGE_SIZE /* attach addr a multiple of this */
-
-#endif /* _ASM_S390_SHMPARAM_H */
diff --git a/arch/s390/include/asm/vga.h b/arch/s390/include/asm/vga.h
deleted file mode 100644
index 605dc46bac5e..000000000000
--- a/arch/s390/include/asm/vga.h
+++ /dev/null
@@ -1,7 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_S390_VGA_H
-#define _ASM_S390_VGA_H
-
-/* Avoid compile errors due to missing asm/vga.h */
-
-#endif /* _ASM_S390_VGA_H */
diff --git a/arch/s390/include/asm/vx-insn-asm.h b/arch/s390/include/asm/vx-insn-asm.h
new file mode 100644
index 000000000000..360f8b36d962
--- /dev/null
+++ b/arch/s390/include/asm/vx-insn-asm.h
@@ -0,0 +1,681 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Support for Vector Instructions
+ *
+ * Assembler macros to generate .byte/.word code for particular
+ * vector instructions that are supported by recent binutils (>= 2.26) only.
+ *
+ * Copyright IBM Corp. 2015
+ * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
+ */
+
+#ifndef __ASM_S390_VX_INSN_INTERNAL_H
+#define __ASM_S390_VX_INSN_INTERNAL_H
+
+#ifndef __ASM_S390_VX_INSN_H
+#error only <asm/vx-insn.h> can be included directly
+#endif
+
+#ifdef __ASSEMBLY__
+
+/* Macros to generate vector instruction byte code */
+
+/* GR_NUM - Retrieve general-purpose register number
+ *
+ * @opd: Operand to store register number
+ * @r64: String designation register in the format "%rN"
+ */
+.macro GR_NUM opd gr
+ \opd = 255
+ .ifc \gr,%r0
+ \opd = 0
+ .endif
+ .ifc \gr,%r1
+ \opd = 1
+ .endif
+ .ifc \gr,%r2
+ \opd = 2
+ .endif
+ .ifc \gr,%r3
+ \opd = 3
+ .endif
+ .ifc \gr,%r4
+ \opd = 4
+ .endif
+ .ifc \gr,%r5
+ \opd = 5
+ .endif
+ .ifc \gr,%r6
+ \opd = 6
+ .endif
+ .ifc \gr,%r7
+ \opd = 7
+ .endif
+ .ifc \gr,%r8
+ \opd = 8
+ .endif
+ .ifc \gr,%r9
+ \opd = 9
+ .endif
+ .ifc \gr,%r10
+ \opd = 10
+ .endif
+ .ifc \gr,%r11
+ \opd = 11
+ .endif
+ .ifc \gr,%r12
+ \opd = 12
+ .endif
+ .ifc \gr,%r13
+ \opd = 13
+ .endif
+ .ifc \gr,%r14
+ \opd = 14
+ .endif
+ .ifc \gr,%r15
+ \opd = 15
+ .endif
+ .if \opd == 255
+ \opd = \gr
+ .endif
+.endm
+
+/* VX_NUM - Retrieve vector register number
+ *
+ * @opd: Operand to store register number
+ * @vxr: String designation register in the format "%vN"
+ *
+ * The vector register number is used for as input number to the
+ * instruction and, as well as, to compute the RXB field of the
+ * instruction.
+ */
+.macro VX_NUM opd vxr
+ \opd = 255
+ .ifc \vxr,%v0
+ \opd = 0
+ .endif
+ .ifc \vxr,%v1
+ \opd = 1
+ .endif
+ .ifc \vxr,%v2
+ \opd = 2
+ .endif
+ .ifc \vxr,%v3
+ \opd = 3
+ .endif
+ .ifc \vxr,%v4
+ \opd = 4
+ .endif
+ .ifc \vxr,%v5
+ \opd = 5
+ .endif
+ .ifc \vxr,%v6
+ \opd = 6
+ .endif
+ .ifc \vxr,%v7
+ \opd = 7
+ .endif
+ .ifc \vxr,%v8
+ \opd = 8
+ .endif
+ .ifc \vxr,%v9
+ \opd = 9
+ .endif
+ .ifc \vxr,%v10
+ \opd = 10
+ .endif
+ .ifc \vxr,%v11
+ \opd = 11
+ .endif
+ .ifc \vxr,%v12
+ \opd = 12
+ .endif
+ .ifc \vxr,%v13
+ \opd = 13
+ .endif
+ .ifc \vxr,%v14
+ \opd = 14
+ .endif
+ .ifc \vxr,%v15
+ \opd = 15
+ .endif
+ .ifc \vxr,%v16
+ \opd = 16
+ .endif
+ .ifc \vxr,%v17
+ \opd = 17
+ .endif
+ .ifc \vxr,%v18
+ \opd = 18
+ .endif
+ .ifc \vxr,%v19
+ \opd = 19
+ .endif
+ .ifc \vxr,%v20
+ \opd = 20
+ .endif
+ .ifc \vxr,%v21
+ \opd = 21
+ .endif
+ .ifc \vxr,%v22
+ \opd = 22
+ .endif
+ .ifc \vxr,%v23
+ \opd = 23
+ .endif
+ .ifc \vxr,%v24
+ \opd = 24
+ .endif
+ .ifc \vxr,%v25
+ \opd = 25
+ .endif
+ .ifc \vxr,%v26
+ \opd = 26
+ .endif
+ .ifc \vxr,%v27
+ \opd = 27
+ .endif
+ .ifc \vxr,%v28
+ \opd = 28
+ .endif
+ .ifc \vxr,%v29
+ \opd = 29
+ .endif
+ .ifc \vxr,%v30
+ \opd = 30
+ .endif
+ .ifc \vxr,%v31
+ \opd = 31
+ .endif
+ .if \opd == 255
+ \opd = \vxr
+ .endif
+.endm
+
+/* RXB - Compute most significant bit used vector registers
+ *
+ * @rxb: Operand to store computed RXB value
+ * @v1: First vector register designated operand
+ * @v2: Second vector register designated operand
+ * @v3: Third vector register designated operand
+ * @v4: Fourth vector register designated operand
+ */
+.macro RXB rxb v1 v2=0 v3=0 v4=0
+ \rxb = 0
+ .if \v1 & 0x10
+ \rxb = \rxb | 0x08
+ .endif
+ .if \v2 & 0x10
+ \rxb = \rxb | 0x04
+ .endif
+ .if \v3 & 0x10
+ \rxb = \rxb | 0x02
+ .endif
+ .if \v4 & 0x10
+ \rxb = \rxb | 0x01
+ .endif
+.endm
+
+/* MRXB - Generate Element Size Control and RXB value
+ *
+ * @m: Element size control
+ * @v1: First vector register designated operand (for RXB)
+ * @v2: Second vector register designated operand (for RXB)
+ * @v3: Third vector register designated operand (for RXB)
+ * @v4: Fourth vector register designated operand (for RXB)
+ */
+.macro MRXB m v1 v2=0 v3=0 v4=0
+ rxb = 0
+ RXB rxb, \v1, \v2, \v3, \v4
+ .byte (\m << 4) | rxb
+.endm
+
+/* MRXBOPC - Generate Element Size Control, RXB, and final Opcode fields
+ *
+ * @m: Element size control
+ * @opc: Opcode
+ * @v1: First vector register designated operand (for RXB)
+ * @v2: Second vector register designated operand (for RXB)
+ * @v3: Third vector register designated operand (for RXB)
+ * @v4: Fourth vector register designated operand (for RXB)
+ */
+.macro MRXBOPC m opc v1 v2=0 v3=0 v4=0
+ MRXB \m, \v1, \v2, \v3, \v4
+ .byte \opc
+.endm
+
+/* Vector support instructions */
+
+/* VECTOR GENERATE BYTE MASK */
+.macro VGBM vr imm2
+ VX_NUM v1, \vr
+ .word (0xE700 | ((v1&15) << 4))
+ .word \imm2
+ MRXBOPC 0, 0x44, v1
+.endm
+.macro VZERO vxr
+ VGBM \vxr, 0
+.endm
+.macro VONE vxr
+ VGBM \vxr, 0xFFFF
+.endm
+
+/* VECTOR LOAD VR ELEMENT FROM GR */
+.macro VLVG v, gr, disp, m
+ VX_NUM v1, \v
+ GR_NUM b2, "%r0"
+ GR_NUM r3, \gr
+ .word 0xE700 | ((v1&15) << 4) | r3
+ .word (b2 << 12) | (\disp)
+ MRXBOPC \m, 0x22, v1
+.endm
+.macro VLVGB v, gr, index, base
+ VLVG \v, \gr, \index, \base, 0
+.endm
+.macro VLVGH v, gr, index
+ VLVG \v, \gr, \index, 1
+.endm
+.macro VLVGF v, gr, index
+ VLVG \v, \gr, \index, 2
+.endm
+.macro VLVGG v, gr, index
+ VLVG \v, \gr, \index, 3
+.endm
+
+/* VECTOR LOAD REGISTER */
+.macro VLR v1, v2
+ VX_NUM v1, \v1
+ VX_NUM v2, \v2
+ .word 0xE700 | ((v1&15) << 4) | (v2&15)
+ .word 0
+ MRXBOPC 0, 0x56, v1, v2
+.endm
+
+/* VECTOR LOAD */
+.macro VL v, disp, index="%r0", base
+ VX_NUM v1, \v
+ GR_NUM x2, \index
+ GR_NUM b2, \base
+ .word 0xE700 | ((v1&15) << 4) | x2
+ .word (b2 << 12) | (\disp)
+ MRXBOPC 0, 0x06, v1
+.endm
+
+/* VECTOR LOAD ELEMENT */
+.macro VLEx vr1, disp, index="%r0", base, m3, opc
+ VX_NUM v1, \vr1
+ GR_NUM x2, \index
+ GR_NUM b2, \base
+ .word 0xE700 | ((v1&15) << 4) | x2
+ .word (b2 << 12) | (\disp)
+ MRXBOPC \m3, \opc, v1
+.endm
+.macro VLEB vr1, disp, index="%r0", base, m3
+ VLEx \vr1, \disp, \index, \base, \m3, 0x00
+.endm
+.macro VLEH vr1, disp, index="%r0", base, m3
+ VLEx \vr1, \disp, \index, \base, \m3, 0x01
+.endm
+.macro VLEF vr1, disp, index="%r0", base, m3
+ VLEx \vr1, \disp, \index, \base, \m3, 0x03
+.endm
+.macro VLEG vr1, disp, index="%r0", base, m3
+ VLEx \vr1, \disp, \index, \base, \m3, 0x02
+.endm
+
+/* VECTOR LOAD ELEMENT IMMEDIATE */
+.macro VLEIx vr1, imm2, m3, opc
+ VX_NUM v1, \vr1
+ .word 0xE700 | ((v1&15) << 4)
+ .word \imm2
+ MRXBOPC \m3, \opc, v1
+.endm
+.macro VLEIB vr1, imm2, index
+ VLEIx \vr1, \imm2, \index, 0x40
+.endm
+.macro VLEIH vr1, imm2, index
+ VLEIx \vr1, \imm2, \index, 0x41
+.endm
+.macro VLEIF vr1, imm2, index
+ VLEIx \vr1, \imm2, \index, 0x43
+.endm
+.macro VLEIG vr1, imm2, index
+ VLEIx \vr1, \imm2, \index, 0x42
+.endm
+
+/* VECTOR LOAD GR FROM VR ELEMENT */
+.macro VLGV gr, vr, disp, base="%r0", m
+ GR_NUM r1, \gr
+ GR_NUM b2, \base
+ VX_NUM v3, \vr
+ .word 0xE700 | (r1 << 4) | (v3&15)
+ .word (b2 << 12) | (\disp)
+ MRXBOPC \m, 0x21, v3
+.endm
+.macro VLGVB gr, vr, disp, base="%r0"
+ VLGV \gr, \vr, \disp, \base, 0
+.endm
+.macro VLGVH gr, vr, disp, base="%r0"
+ VLGV \gr, \vr, \disp, \base, 1
+.endm
+.macro VLGVF gr, vr, disp, base="%r0"
+ VLGV \gr, \vr, \disp, \base, 2
+.endm
+.macro VLGVG gr, vr, disp, base="%r0"
+ VLGV \gr, \vr, \disp, \base, 3
+.endm
+
+/* VECTOR LOAD MULTIPLE */
+.macro VLM vfrom, vto, disp, base, hint=3
+ VX_NUM v1, \vfrom
+ VX_NUM v3, \vto
+ GR_NUM b2, \base
+ .word 0xE700 | ((v1&15) << 4) | (v3&15)
+ .word (b2 << 12) | (\disp)
+ MRXBOPC \hint, 0x36, v1, v3
+.endm
+
+/* VECTOR STORE */
+.macro VST vr1, disp, index="%r0", base
+ VX_NUM v1, \vr1
+ GR_NUM x2, \index
+ GR_NUM b2, \base
+ .word 0xE700 | ((v1&15) << 4) | (x2&15)
+ .word (b2 << 12) | (\disp)
+ MRXBOPC 0, 0x0E, v1
+.endm
+
+/* VECTOR STORE MULTIPLE */
+.macro VSTM vfrom, vto, disp, base, hint=3
+ VX_NUM v1, \vfrom
+ VX_NUM v3, \vto
+ GR_NUM b2, \base
+ .word 0xE700 | ((v1&15) << 4) | (v3&15)
+ .word (b2 << 12) | (\disp)
+ MRXBOPC \hint, 0x3E, v1, v3
+.endm
+
+/* VECTOR PERMUTE */
+.macro VPERM vr1, vr2, vr3, vr4
+ VX_NUM v1, \vr1
+ VX_NUM v2, \vr2
+ VX_NUM v3, \vr3
+ VX_NUM v4, \vr4
+ .word 0xE700 | ((v1&15) << 4) | (v2&15)
+ .word ((v3&15) << 12)
+ MRXBOPC (v4&15), 0x8C, v1, v2, v3, v4
+.endm
+
+/* VECTOR UNPACK LOGICAL LOW */
+.macro VUPLL vr1, vr2, m3
+ VX_NUM v1, \vr1
+ VX_NUM v2, \vr2
+ .word 0xE700 | ((v1&15) << 4) | (v2&15)
+ .word 0x0000
+ MRXBOPC \m3, 0xD4, v1, v2
+.endm
+.macro VUPLLB vr1, vr2
+ VUPLL \vr1, \vr2, 0
+.endm
+.macro VUPLLH vr1, vr2
+ VUPLL \vr1, \vr2, 1
+.endm
+.macro VUPLLF vr1, vr2
+ VUPLL \vr1, \vr2, 2
+.endm
+
+/* VECTOR PERMUTE DOUBLEWORD IMMEDIATE */
+.macro VPDI vr1, vr2, vr3, m4
+ VX_NUM v1, \vr1
+ VX_NUM v2, \vr2
+ VX_NUM v3, \vr3
+ .word 0xE700 | ((v1&15) << 4) | (v2&15)
+ .word ((v3&15) << 12)
+ MRXBOPC \m4, 0x84, v1, v2, v3
+.endm
+
+/* VECTOR REPLICATE */
+.macro VREP vr1, vr3, imm2, m4
+ VX_NUM v1, \vr1
+ VX_NUM v3, \vr3
+ .word 0xE700 | ((v1&15) << 4) | (v3&15)
+ .word \imm2
+ MRXBOPC \m4, 0x4D, v1, v3
+.endm
+.macro VREPB vr1, vr3, imm2
+ VREP \vr1, \vr3, \imm2, 0
+.endm
+.macro VREPH vr1, vr3, imm2
+ VREP \vr1, \vr3, \imm2, 1
+.endm
+.macro VREPF vr1, vr3, imm2
+ VREP \vr1, \vr3, \imm2, 2
+.endm
+.macro VREPG vr1, vr3, imm2
+ VREP \vr1, \vr3, \imm2, 3
+.endm
+
+/* VECTOR MERGE HIGH */
+.macro VMRH vr1, vr2, vr3, m4
+ VX_NUM v1, \vr1
+ VX_NUM v2, \vr2
+ VX_NUM v3, \vr3
+ .word 0xE700 | ((v1&15) << 4) | (v2&15)
+ .word ((v3&15) << 12)
+ MRXBOPC \m4, 0x61, v1, v2, v3
+.endm
+.macro VMRHB vr1, vr2, vr3
+ VMRH \vr1, \vr2, \vr3, 0
+.endm
+.macro VMRHH vr1, vr2, vr3
+ VMRH \vr1, \vr2, \vr3, 1
+.endm
+.macro VMRHF vr1, vr2, vr3
+ VMRH \vr1, \vr2, \vr3, 2
+.endm
+.macro VMRHG vr1, vr2, vr3
+ VMRH \vr1, \vr2, \vr3, 3
+.endm
+
+/* VECTOR MERGE LOW */
+.macro VMRL vr1, vr2, vr3, m4
+ VX_NUM v1, \vr1
+ VX_NUM v2, \vr2
+ VX_NUM v3, \vr3
+ .word 0xE700 | ((v1&15) << 4) | (v2&15)
+ .word ((v3&15) << 12)
+ MRXBOPC \m4, 0x60, v1, v2, v3
+.endm
+.macro VMRLB vr1, vr2, vr3
+ VMRL \vr1, \vr2, \vr3, 0
+.endm
+.macro VMRLH vr1, vr2, vr3
+ VMRL \vr1, \vr2, \vr3, 1
+.endm
+.macro VMRLF vr1, vr2, vr3
+ VMRL \vr1, \vr2, \vr3, 2
+.endm
+.macro VMRLG vr1, vr2, vr3
+ VMRL \vr1, \vr2, \vr3, 3
+.endm
+
+
+/* Vector integer instructions */
+
+/* VECTOR AND */
+.macro VN vr1, vr2, vr3
+ VX_NUM v1, \vr1
+ VX_NUM v2, \vr2
+ VX_NUM v3, \vr3
+ .word 0xE700 | ((v1&15) << 4) | (v2&15)
+ .word ((v3&15) << 12)
+ MRXBOPC 0, 0x68, v1, v2, v3
+.endm
+
+/* VECTOR EXCLUSIVE OR */
+.macro VX vr1, vr2, vr3
+ VX_NUM v1, \vr1
+ VX_NUM v2, \vr2
+ VX_NUM v3, \vr3
+ .word 0xE700 | ((v1&15) << 4) | (v2&15)
+ .word ((v3&15) << 12)
+ MRXBOPC 0, 0x6D, v1, v2, v3
+.endm
+
+/* VECTOR GALOIS FIELD MULTIPLY SUM */
+.macro VGFM vr1, vr2, vr3, m4
+ VX_NUM v1, \vr1
+ VX_NUM v2, \vr2
+ VX_NUM v3, \vr3
+ .word 0xE700 | ((v1&15) << 4) | (v2&15)
+ .word ((v3&15) << 12)
+ MRXBOPC \m4, 0xB4, v1, v2, v3
+.endm
+.macro VGFMB vr1, vr2, vr3
+ VGFM \vr1, \vr2, \vr3, 0
+.endm
+.macro VGFMH vr1, vr2, vr3
+ VGFM \vr1, \vr2, \vr3, 1
+.endm
+.macro VGFMF vr1, vr2, vr3
+ VGFM \vr1, \vr2, \vr3, 2
+.endm
+.macro VGFMG vr1, vr2, vr3
+ VGFM \vr1, \vr2, \vr3, 3
+.endm
+
+/* VECTOR GALOIS FIELD MULTIPLY SUM AND ACCUMULATE */
+.macro VGFMA vr1, vr2, vr3, vr4, m5
+ VX_NUM v1, \vr1
+ VX_NUM v2, \vr2
+ VX_NUM v3, \vr3
+ VX_NUM v4, \vr4
+ .word 0xE700 | ((v1&15) << 4) | (v2&15)
+ .word ((v3&15) << 12) | (\m5 << 8)
+ MRXBOPC (v4&15), 0xBC, v1, v2, v3, v4
+.endm
+.macro VGFMAB vr1, vr2, vr3, vr4
+ VGFMA \vr1, \vr2, \vr3, \vr4, 0
+.endm
+.macro VGFMAH vr1, vr2, vr3, vr4
+ VGFMA \vr1, \vr2, \vr3, \vr4, 1
+.endm
+.macro VGFMAF vr1, vr2, vr3, vr4
+ VGFMA \vr1, \vr2, \vr3, \vr4, 2
+.endm
+.macro VGFMAG vr1, vr2, vr3, vr4
+ VGFMA \vr1, \vr2, \vr3, \vr4, 3
+.endm
+
+/* VECTOR SHIFT RIGHT LOGICAL BY BYTE */
+.macro VSRLB vr1, vr2, vr3
+ VX_NUM v1, \vr1
+ VX_NUM v2, \vr2
+ VX_NUM v3, \vr3
+ .word 0xE700 | ((v1&15) << 4) | (v2&15)
+ .word ((v3&15) << 12)
+ MRXBOPC 0, 0x7D, v1, v2, v3
+.endm
+
+/* VECTOR REPLICATE IMMEDIATE */
+.macro VREPI vr1, imm2, m3
+ VX_NUM v1, \vr1
+ .word 0xE700 | ((v1&15) << 4)
+ .word \imm2
+ MRXBOPC \m3, 0x45, v1
+.endm
+.macro VREPIB vr1, imm2
+ VREPI \vr1, \imm2, 0
+.endm
+.macro VREPIH vr1, imm2
+ VREPI \vr1, \imm2, 1
+.endm
+.macro VREPIF vr1, imm2
+ VREPI \vr1, \imm2, 2
+.endm
+.macro VREPIG vr1, imm2
+ VREP \vr1, \imm2, 3
+.endm
+
+/* VECTOR ADD */
+.macro VA vr1, vr2, vr3, m4
+ VX_NUM v1, \vr1
+ VX_NUM v2, \vr2
+ VX_NUM v3, \vr3
+ .word 0xE700 | ((v1&15) << 4) | (v2&15)
+ .word ((v3&15) << 12)
+ MRXBOPC \m4, 0xF3, v1, v2, v3
+.endm
+.macro VAB vr1, vr2, vr3
+ VA \vr1, \vr2, \vr3, 0
+.endm
+.macro VAH vr1, vr2, vr3
+ VA \vr1, \vr2, \vr3, 1
+.endm
+.macro VAF vr1, vr2, vr3
+ VA \vr1, \vr2, \vr3, 2
+.endm
+.macro VAG vr1, vr2, vr3
+ VA \vr1, \vr2, \vr3, 3
+.endm
+.macro VAQ vr1, vr2, vr3
+ VA \vr1, \vr2, \vr3, 4
+.endm
+
+/* VECTOR ELEMENT SHIFT RIGHT ARITHMETIC */
+.macro VESRAV vr1, vr2, vr3, m4
+ VX_NUM v1, \vr1
+ VX_NUM v2, \vr2
+ VX_NUM v3, \vr3
+ .word 0xE700 | ((v1&15) << 4) | (v2&15)
+ .word ((v3&15) << 12)
+ MRXBOPC \m4, 0x7A, v1, v2, v3
+.endm
+
+.macro VESRAVB vr1, vr2, vr3
+ VESRAV \vr1, \vr2, \vr3, 0
+.endm
+.macro VESRAVH vr1, vr2, vr3
+ VESRAV \vr1, \vr2, \vr3, 1
+.endm
+.macro VESRAVF vr1, vr2, vr3
+ VESRAV \vr1, \vr2, \vr3, 2
+.endm
+.macro VESRAVG vr1, vr2, vr3
+ VESRAV \vr1, \vr2, \vr3, 3
+.endm
+
+/* VECTOR ELEMENT ROTATE LEFT LOGICAL */
+.macro VERLL vr1, vr3, disp, base="%r0", m4
+ VX_NUM v1, \vr1
+ VX_NUM v3, \vr3
+ GR_NUM b2, \base
+ .word 0xE700 | ((v1&15) << 4) | (v3&15)
+ .word (b2 << 12) | (\disp)
+ MRXBOPC \m4, 0x33, v1, v3
+.endm
+.macro VERLLB vr1, vr3, disp, base="%r0"
+ VERLL \vr1, \vr3, \disp, \base, 0
+.endm
+.macro VERLLH vr1, vr3, disp, base="%r0"
+ VERLL \vr1, \vr3, \disp, \base, 1
+.endm
+.macro VERLLF vr1, vr3, disp, base="%r0"
+ VERLL \vr1, \vr3, \disp, \base, 2
+.endm
+.macro VERLLG vr1, vr3, disp, base="%r0"
+ VERLL \vr1, \vr3, \disp, \base, 3
+.endm
+
+/* VECTOR SHIFT LEFT DOUBLE BY BYTE */
+.macro VSLDB vr1, vr2, vr3, imm4
+ VX_NUM v1, \vr1
+ VX_NUM v2, \vr2
+ VX_NUM v3, \vr3
+ .word 0xE700 | ((v1&15) << 4) | (v2&15)
+ .word ((v3&15) << 12) | (\imm4)
+ MRXBOPC 0, 0x77, v1, v2, v3
+.endm
+
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_S390_VX_INSN_INTERNAL_H */
diff --git a/arch/s390/include/asm/vx-insn.h b/arch/s390/include/asm/vx-insn.h
index 95480ed9149e..8c188f1c6d27 100644
--- a/arch/s390/include/asm/vx-insn.h
+++ b/arch/s390/include/asm/vx-insn.h
@@ -2,677 +2,18 @@
/*
* Support for Vector Instructions
*
- * Assembler macros to generate .byte/.word code for particular
- * vector instructions that are supported by recent binutils (>= 2.26) only.
- *
- * Copyright IBM Corp. 2015
- * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
+ * This wrapper header file allows to use the vector instruction macros in
+ * both assembler files as well as in inline assemblies in C files.
*/
#ifndef __ASM_S390_VX_INSN_H
#define __ASM_S390_VX_INSN_H
-#ifdef __ASSEMBLY__
-
-
-/* Macros to generate vector instruction byte code */
-
-/* GR_NUM - Retrieve general-purpose register number
- *
- * @opd: Operand to store register number
- * @r64: String designation register in the format "%rN"
- */
-.macro GR_NUM opd gr
- \opd = 255
- .ifc \gr,%r0
- \opd = 0
- .endif
- .ifc \gr,%r1
- \opd = 1
- .endif
- .ifc \gr,%r2
- \opd = 2
- .endif
- .ifc \gr,%r3
- \opd = 3
- .endif
- .ifc \gr,%r4
- \opd = 4
- .endif
- .ifc \gr,%r5
- \opd = 5
- .endif
- .ifc \gr,%r6
- \opd = 6
- .endif
- .ifc \gr,%r7
- \opd = 7
- .endif
- .ifc \gr,%r8
- \opd = 8
- .endif
- .ifc \gr,%r9
- \opd = 9
- .endif
- .ifc \gr,%r10
- \opd = 10
- .endif
- .ifc \gr,%r11
- \opd = 11
- .endif
- .ifc \gr,%r12
- \opd = 12
- .endif
- .ifc \gr,%r13
- \opd = 13
- .endif
- .ifc \gr,%r14
- \opd = 14
- .endif
- .ifc \gr,%r15
- \opd = 15
- .endif
- .if \opd == 255
- \opd = \gr
- .endif
-.endm
-
-/* VX_NUM - Retrieve vector register number
- *
- * @opd: Operand to store register number
- * @vxr: String designation register in the format "%vN"
- *
- * The vector register number is used for as input number to the
- * instruction and, as well as, to compute the RXB field of the
- * instruction.
- */
-.macro VX_NUM opd vxr
- \opd = 255
- .ifc \vxr,%v0
- \opd = 0
- .endif
- .ifc \vxr,%v1
- \opd = 1
- .endif
- .ifc \vxr,%v2
- \opd = 2
- .endif
- .ifc \vxr,%v3
- \opd = 3
- .endif
- .ifc \vxr,%v4
- \opd = 4
- .endif
- .ifc \vxr,%v5
- \opd = 5
- .endif
- .ifc \vxr,%v6
- \opd = 6
- .endif
- .ifc \vxr,%v7
- \opd = 7
- .endif
- .ifc \vxr,%v8
- \opd = 8
- .endif
- .ifc \vxr,%v9
- \opd = 9
- .endif
- .ifc \vxr,%v10
- \opd = 10
- .endif
- .ifc \vxr,%v11
- \opd = 11
- .endif
- .ifc \vxr,%v12
- \opd = 12
- .endif
- .ifc \vxr,%v13
- \opd = 13
- .endif
- .ifc \vxr,%v14
- \opd = 14
- .endif
- .ifc \vxr,%v15
- \opd = 15
- .endif
- .ifc \vxr,%v16
- \opd = 16
- .endif
- .ifc \vxr,%v17
- \opd = 17
- .endif
- .ifc \vxr,%v18
- \opd = 18
- .endif
- .ifc \vxr,%v19
- \opd = 19
- .endif
- .ifc \vxr,%v20
- \opd = 20
- .endif
- .ifc \vxr,%v21
- \opd = 21
- .endif
- .ifc \vxr,%v22
- \opd = 22
- .endif
- .ifc \vxr,%v23
- \opd = 23
- .endif
- .ifc \vxr,%v24
- \opd = 24
- .endif
- .ifc \vxr,%v25
- \opd = 25
- .endif
- .ifc \vxr,%v26
- \opd = 26
- .endif
- .ifc \vxr,%v27
- \opd = 27
- .endif
- .ifc \vxr,%v28
- \opd = 28
- .endif
- .ifc \vxr,%v29
- \opd = 29
- .endif
- .ifc \vxr,%v30
- \opd = 30
- .endif
- .ifc \vxr,%v31
- \opd = 31
- .endif
- .if \opd == 255
- \opd = \vxr
- .endif
-.endm
-
-/* RXB - Compute most significant bit used vector registers
- *
- * @rxb: Operand to store computed RXB value
- * @v1: First vector register designated operand
- * @v2: Second vector register designated operand
- * @v3: Third vector register designated operand
- * @v4: Fourth vector register designated operand
- */
-.macro RXB rxb v1 v2=0 v3=0 v4=0
- \rxb = 0
- .if \v1 & 0x10
- \rxb = \rxb | 0x08
- .endif
- .if \v2 & 0x10
- \rxb = \rxb | 0x04
- .endif
- .if \v3 & 0x10
- \rxb = \rxb | 0x02
- .endif
- .if \v4 & 0x10
- \rxb = \rxb | 0x01
- .endif
-.endm
-
-/* MRXB - Generate Element Size Control and RXB value
- *
- * @m: Element size control
- * @v1: First vector register designated operand (for RXB)
- * @v2: Second vector register designated operand (for RXB)
- * @v3: Third vector register designated operand (for RXB)
- * @v4: Fourth vector register designated operand (for RXB)
- */
-.macro MRXB m v1 v2=0 v3=0 v4=0
- rxb = 0
- RXB rxb, \v1, \v2, \v3, \v4
- .byte (\m << 4) | rxb
-.endm
-
-/* MRXBOPC - Generate Element Size Control, RXB, and final Opcode fields
- *
- * @m: Element size control
- * @opc: Opcode
- * @v1: First vector register designated operand (for RXB)
- * @v2: Second vector register designated operand (for RXB)
- * @v3: Third vector register designated operand (for RXB)
- * @v4: Fourth vector register designated operand (for RXB)
- */
-.macro MRXBOPC m opc v1 v2=0 v3=0 v4=0
- MRXB \m, \v1, \v2, \v3, \v4
- .byte \opc
-.endm
-
-/* Vector support instructions */
-
-/* VECTOR GENERATE BYTE MASK */
-.macro VGBM vr imm2
- VX_NUM v1, \vr
- .word (0xE700 | ((v1&15) << 4))
- .word \imm2
- MRXBOPC 0, 0x44, v1
-.endm
-.macro VZERO vxr
- VGBM \vxr, 0
-.endm
-.macro VONE vxr
- VGBM \vxr, 0xFFFF
-.endm
-
-/* VECTOR LOAD VR ELEMENT FROM GR */
-.macro VLVG v, gr, disp, m
- VX_NUM v1, \v
- GR_NUM b2, "%r0"
- GR_NUM r3, \gr
- .word 0xE700 | ((v1&15) << 4) | r3
- .word (b2 << 12) | (\disp)
- MRXBOPC \m, 0x22, v1
-.endm
-.macro VLVGB v, gr, index, base
- VLVG \v, \gr, \index, \base, 0
-.endm
-.macro VLVGH v, gr, index
- VLVG \v, \gr, \index, 1
-.endm
-.macro VLVGF v, gr, index
- VLVG \v, \gr, \index, 2
-.endm
-.macro VLVGG v, gr, index
- VLVG \v, \gr, \index, 3
-.endm
-
-/* VECTOR LOAD REGISTER */
-.macro VLR v1, v2
- VX_NUM v1, \v1
- VX_NUM v2, \v2
- .word 0xE700 | ((v1&15) << 4) | (v2&15)
- .word 0
- MRXBOPC 0, 0x56, v1, v2
-.endm
-
-/* VECTOR LOAD */
-.macro VL v, disp, index="%r0", base
- VX_NUM v1, \v
- GR_NUM x2, \index
- GR_NUM b2, \base
- .word 0xE700 | ((v1&15) << 4) | x2
- .word (b2 << 12) | (\disp)
- MRXBOPC 0, 0x06, v1
-.endm
-
-/* VECTOR LOAD ELEMENT */
-.macro VLEx vr1, disp, index="%r0", base, m3, opc
- VX_NUM v1, \vr1
- GR_NUM x2, \index
- GR_NUM b2, \base
- .word 0xE700 | ((v1&15) << 4) | x2
- .word (b2 << 12) | (\disp)
- MRXBOPC \m3, \opc, v1
-.endm
-.macro VLEB vr1, disp, index="%r0", base, m3
- VLEx \vr1, \disp, \index, \base, \m3, 0x00
-.endm
-.macro VLEH vr1, disp, index="%r0", base, m3
- VLEx \vr1, \disp, \index, \base, \m3, 0x01
-.endm
-.macro VLEF vr1, disp, index="%r0", base, m3
- VLEx \vr1, \disp, \index, \base, \m3, 0x03
-.endm
-.macro VLEG vr1, disp, index="%r0", base, m3
- VLEx \vr1, \disp, \index, \base, \m3, 0x02
-.endm
-
-/* VECTOR LOAD ELEMENT IMMEDIATE */
-.macro VLEIx vr1, imm2, m3, opc
- VX_NUM v1, \vr1
- .word 0xE700 | ((v1&15) << 4)
- .word \imm2
- MRXBOPC \m3, \opc, v1
-.endm
-.macro VLEIB vr1, imm2, index
- VLEIx \vr1, \imm2, \index, 0x40
-.endm
-.macro VLEIH vr1, imm2, index
- VLEIx \vr1, \imm2, \index, 0x41
-.endm
-.macro VLEIF vr1, imm2, index
- VLEIx \vr1, \imm2, \index, 0x43
-.endm
-.macro VLEIG vr1, imm2, index
- VLEIx \vr1, \imm2, \index, 0x42
-.endm
-
-/* VECTOR LOAD GR FROM VR ELEMENT */
-.macro VLGV gr, vr, disp, base="%r0", m
- GR_NUM r1, \gr
- GR_NUM b2, \base
- VX_NUM v3, \vr
- .word 0xE700 | (r1 << 4) | (v3&15)
- .word (b2 << 12) | (\disp)
- MRXBOPC \m, 0x21, v3
-.endm
-.macro VLGVB gr, vr, disp, base="%r0"
- VLGV \gr, \vr, \disp, \base, 0
-.endm
-.macro VLGVH gr, vr, disp, base="%r0"
- VLGV \gr, \vr, \disp, \base, 1
-.endm
-.macro VLGVF gr, vr, disp, base="%r0"
- VLGV \gr, \vr, \disp, \base, 2
-.endm
-.macro VLGVG gr, vr, disp, base="%r0"
- VLGV \gr, \vr, \disp, \base, 3
-.endm
-
-/* VECTOR LOAD MULTIPLE */
-.macro VLM vfrom, vto, disp, base, hint=3
- VX_NUM v1, \vfrom
- VX_NUM v3, \vto
- GR_NUM b2, \base
- .word 0xE700 | ((v1&15) << 4) | (v3&15)
- .word (b2 << 12) | (\disp)
- MRXBOPC \hint, 0x36, v1, v3
-.endm
-
-/* VECTOR STORE */
-.macro VST vr1, disp, index="%r0", base
- VX_NUM v1, \vr1
- GR_NUM x2, \index
- GR_NUM b2, \base
- .word 0xE700 | ((v1&15) << 4) | (x2&15)
- .word (b2 << 12) | (\disp)
- MRXBOPC 0, 0x0E, v1
-.endm
-
-/* VECTOR STORE MULTIPLE */
-.macro VSTM vfrom, vto, disp, base, hint=3
- VX_NUM v1, \vfrom
- VX_NUM v3, \vto
- GR_NUM b2, \base
- .word 0xE700 | ((v1&15) << 4) | (v3&15)
- .word (b2 << 12) | (\disp)
- MRXBOPC \hint, 0x3E, v1, v3
-.endm
-
-/* VECTOR PERMUTE */
-.macro VPERM vr1, vr2, vr3, vr4
- VX_NUM v1, \vr1
- VX_NUM v2, \vr2
- VX_NUM v3, \vr3
- VX_NUM v4, \vr4
- .word 0xE700 | ((v1&15) << 4) | (v2&15)
- .word ((v3&15) << 12)
- MRXBOPC (v4&15), 0x8C, v1, v2, v3, v4
-.endm
-
-/* VECTOR UNPACK LOGICAL LOW */
-.macro VUPLL vr1, vr2, m3
- VX_NUM v1, \vr1
- VX_NUM v2, \vr2
- .word 0xE700 | ((v1&15) << 4) | (v2&15)
- .word 0x0000
- MRXBOPC \m3, 0xD4, v1, v2
-.endm
-.macro VUPLLB vr1, vr2
- VUPLL \vr1, \vr2, 0
-.endm
-.macro VUPLLH vr1, vr2
- VUPLL \vr1, \vr2, 1
-.endm
-.macro VUPLLF vr1, vr2
- VUPLL \vr1, \vr2, 2
-.endm
-
-/* VECTOR PERMUTE DOUBLEWORD IMMEDIATE */
-.macro VPDI vr1, vr2, vr3, m4
- VX_NUM v1, \vr1
- VX_NUM v2, \vr2
- VX_NUM v3, \vr3
- .word 0xE700 | ((v1&15) << 4) | (v2&15)
- .word ((v3&15) << 12)
- MRXBOPC \m4, 0x84, v1, v2, v3
-.endm
-
-/* VECTOR REPLICATE */
-.macro VREP vr1, vr3, imm2, m4
- VX_NUM v1, \vr1
- VX_NUM v3, \vr3
- .word 0xE700 | ((v1&15) << 4) | (v3&15)
- .word \imm2
- MRXBOPC \m4, 0x4D, v1, v3
-.endm
-.macro VREPB vr1, vr3, imm2
- VREP \vr1, \vr3, \imm2, 0
-.endm
-.macro VREPH vr1, vr3, imm2
- VREP \vr1, \vr3, \imm2, 1
-.endm
-.macro VREPF vr1, vr3, imm2
- VREP \vr1, \vr3, \imm2, 2
-.endm
-.macro VREPG vr1, vr3, imm2
- VREP \vr1, \vr3, \imm2, 3
-.endm
-
-/* VECTOR MERGE HIGH */
-.macro VMRH vr1, vr2, vr3, m4
- VX_NUM v1, \vr1
- VX_NUM v2, \vr2
- VX_NUM v3, \vr3
- .word 0xE700 | ((v1&15) << 4) | (v2&15)
- .word ((v3&15) << 12)
- MRXBOPC \m4, 0x61, v1, v2, v3
-.endm
-.macro VMRHB vr1, vr2, vr3
- VMRH \vr1, \vr2, \vr3, 0
-.endm
-.macro VMRHH vr1, vr2, vr3
- VMRH \vr1, \vr2, \vr3, 1
-.endm
-.macro VMRHF vr1, vr2, vr3
- VMRH \vr1, \vr2, \vr3, 2
-.endm
-.macro VMRHG vr1, vr2, vr3
- VMRH \vr1, \vr2, \vr3, 3
-.endm
-
-/* VECTOR MERGE LOW */
-.macro VMRL vr1, vr2, vr3, m4
- VX_NUM v1, \vr1
- VX_NUM v2, \vr2
- VX_NUM v3, \vr3
- .word 0xE700 | ((v1&15) << 4) | (v2&15)
- .word ((v3&15) << 12)
- MRXBOPC \m4, 0x60, v1, v2, v3
-.endm
-.macro VMRLB vr1, vr2, vr3
- VMRL \vr1, \vr2, \vr3, 0
-.endm
-.macro VMRLH vr1, vr2, vr3
- VMRL \vr1, \vr2, \vr3, 1
-.endm
-.macro VMRLF vr1, vr2, vr3
- VMRL \vr1, \vr2, \vr3, 2
-.endm
-.macro VMRLG vr1, vr2, vr3
- VMRL \vr1, \vr2, \vr3, 3
-.endm
-
-
-/* Vector integer instructions */
-
-/* VECTOR AND */
-.macro VN vr1, vr2, vr3
- VX_NUM v1, \vr1
- VX_NUM v2, \vr2
- VX_NUM v3, \vr3
- .word 0xE700 | ((v1&15) << 4) | (v2&15)
- .word ((v3&15) << 12)
- MRXBOPC 0, 0x68, v1, v2, v3
-.endm
-
-/* VECTOR EXCLUSIVE OR */
-.macro VX vr1, vr2, vr3
- VX_NUM v1, \vr1
- VX_NUM v2, \vr2
- VX_NUM v3, \vr3
- .word 0xE700 | ((v1&15) << 4) | (v2&15)
- .word ((v3&15) << 12)
- MRXBOPC 0, 0x6D, v1, v2, v3
-.endm
-
-/* VECTOR GALOIS FIELD MULTIPLY SUM */
-.macro VGFM vr1, vr2, vr3, m4
- VX_NUM v1, \vr1
- VX_NUM v2, \vr2
- VX_NUM v3, \vr3
- .word 0xE700 | ((v1&15) << 4) | (v2&15)
- .word ((v3&15) << 12)
- MRXBOPC \m4, 0xB4, v1, v2, v3
-.endm
-.macro VGFMB vr1, vr2, vr3
- VGFM \vr1, \vr2, \vr3, 0
-.endm
-.macro VGFMH vr1, vr2, vr3
- VGFM \vr1, \vr2, \vr3, 1
-.endm
-.macro VGFMF vr1, vr2, vr3
- VGFM \vr1, \vr2, \vr3, 2
-.endm
-.macro VGFMG vr1, vr2, vr3
- VGFM \vr1, \vr2, \vr3, 3
-.endm
-
-/* VECTOR GALOIS FIELD MULTIPLY SUM AND ACCUMULATE */
-.macro VGFMA vr1, vr2, vr3, vr4, m5
- VX_NUM v1, \vr1
- VX_NUM v2, \vr2
- VX_NUM v3, \vr3
- VX_NUM v4, \vr4
- .word 0xE700 | ((v1&15) << 4) | (v2&15)
- .word ((v3&15) << 12) | (\m5 << 8)
- MRXBOPC (v4&15), 0xBC, v1, v2, v3, v4
-.endm
-.macro VGFMAB vr1, vr2, vr3, vr4
- VGFMA \vr1, \vr2, \vr3, \vr4, 0
-.endm
-.macro VGFMAH vr1, vr2, vr3, vr4
- VGFMA \vr1, \vr2, \vr3, \vr4, 1
-.endm
-.macro VGFMAF vr1, vr2, vr3, vr4
- VGFMA \vr1, \vr2, \vr3, \vr4, 2
-.endm
-.macro VGFMAG vr1, vr2, vr3, vr4
- VGFMA \vr1, \vr2, \vr3, \vr4, 3
-.endm
-
-/* VECTOR SHIFT RIGHT LOGICAL BY BYTE */
-.macro VSRLB vr1, vr2, vr3
- VX_NUM v1, \vr1
- VX_NUM v2, \vr2
- VX_NUM v3, \vr3
- .word 0xE700 | ((v1&15) << 4) | (v2&15)
- .word ((v3&15) << 12)
- MRXBOPC 0, 0x7D, v1, v2, v3
-.endm
-
-/* VECTOR REPLICATE IMMEDIATE */
-.macro VREPI vr1, imm2, m3
- VX_NUM v1, \vr1
- .word 0xE700 | ((v1&15) << 4)
- .word \imm2
- MRXBOPC \m3, 0x45, v1
-.endm
-.macro VREPIB vr1, imm2
- VREPI \vr1, \imm2, 0
-.endm
-.macro VREPIH vr1, imm2
- VREPI \vr1, \imm2, 1
-.endm
-.macro VREPIF vr1, imm2
- VREPI \vr1, \imm2, 2
-.endm
-.macro VREPIG vr1, imm2
- VREP \vr1, \imm2, 3
-.endm
-
-/* VECTOR ADD */
-.macro VA vr1, vr2, vr3, m4
- VX_NUM v1, \vr1
- VX_NUM v2, \vr2
- VX_NUM v3, \vr3
- .word 0xE700 | ((v1&15) << 4) | (v2&15)
- .word ((v3&15) << 12)
- MRXBOPC \m4, 0xF3, v1, v2, v3
-.endm
-.macro VAB vr1, vr2, vr3
- VA \vr1, \vr2, \vr3, 0
-.endm
-.macro VAH vr1, vr2, vr3
- VA \vr1, \vr2, \vr3, 1
-.endm
-.macro VAF vr1, vr2, vr3
- VA \vr1, \vr2, \vr3, 2
-.endm
-.macro VAG vr1, vr2, vr3
- VA \vr1, \vr2, \vr3, 3
-.endm
-.macro VAQ vr1, vr2, vr3
- VA \vr1, \vr2, \vr3, 4
-.endm
-
-/* VECTOR ELEMENT SHIFT RIGHT ARITHMETIC */
-.macro VESRAV vr1, vr2, vr3, m4
- VX_NUM v1, \vr1
- VX_NUM v2, \vr2
- VX_NUM v3, \vr3
- .word 0xE700 | ((v1&15) << 4) | (v2&15)
- .word ((v3&15) << 12)
- MRXBOPC \m4, 0x7A, v1, v2, v3
-.endm
-
-.macro VESRAVB vr1, vr2, vr3
- VESRAV \vr1, \vr2, \vr3, 0
-.endm
-.macro VESRAVH vr1, vr2, vr3
- VESRAV \vr1, \vr2, \vr3, 1
-.endm
-.macro VESRAVF vr1, vr2, vr3
- VESRAV \vr1, \vr2, \vr3, 2
-.endm
-.macro VESRAVG vr1, vr2, vr3
- VESRAV \vr1, \vr2, \vr3, 3
-.endm
+#include <asm/vx-insn-asm.h>
-/* VECTOR ELEMENT ROTATE LEFT LOGICAL */
-.macro VERLL vr1, vr3, disp, base="%r0", m4
- VX_NUM v1, \vr1
- VX_NUM v3, \vr3
- GR_NUM b2, \base
- .word 0xE700 | ((v1&15) << 4) | (v3&15)
- .word (b2 << 12) | (\disp)
- MRXBOPC \m4, 0x33, v1, v3
-.endm
-.macro VERLLB vr1, vr3, disp, base="%r0"
- VERLL \vr1, \vr3, \disp, \base, 0
-.endm
-.macro VERLLH vr1, vr3, disp, base="%r0"
- VERLL \vr1, \vr3, \disp, \base, 1
-.endm
-.macro VERLLF vr1, vr3, disp, base="%r0"
- VERLL \vr1, \vr3, \disp, \base, 2
-.endm
-.macro VERLLG vr1, vr3, disp, base="%r0"
- VERLL \vr1, \vr3, \disp, \base, 3
-.endm
+#ifndef __ASSEMBLY__
-/* VECTOR SHIFT LEFT DOUBLE BY BYTE */
-.macro VSLDB vr1, vr2, vr3, imm4
- VX_NUM v1, \vr1
- VX_NUM v2, \vr2
- VX_NUM v3, \vr3
- .word 0xE700 | ((v1&15) << 4) | (v2&15)
- .word ((v3&15) << 12) | (\imm4)
- MRXBOPC 0, 0x77, v1, v2, v3
-.endm
+asm(".include \"asm/vx-insn-asm.h\"\n");
-#endif /* __ASSEMBLY__ */
+#endif /* __ASSEMBLY__ */
#endif /* __ASM_S390_VX_INSN_H */
diff --git a/arch/s390/include/uapi/asm/ipl.h b/arch/s390/include/uapi/asm/ipl.h
index d1ecd5d722a0..2cd28af50dd4 100644
--- a/arch/s390/include/uapi/asm/ipl.h
+++ b/arch/s390/include/uapi/asm/ipl.h
@@ -27,6 +27,7 @@ enum ipl_pbt {
IPL_PBT_FCP = 0,
IPL_PBT_SCP_DATA = 1,
IPL_PBT_CCW = 2,
+ IPL_PBT_ECKD = 3,
IPL_PBT_NVME = 4,
};
@@ -111,6 +112,34 @@ struct ipl_pb0_ccw {
__u8 reserved5[8];
} __packed;
+/* IPL Parameter Block 0 for ECKD */
+struct ipl_pb0_eckd {
+ __u32 len;
+ __u8 pbt;
+ __u8 reserved1[3];
+ __u32 reserved2[78];
+ __u8 opt;
+ __u8 reserved4[4];
+ __u8 reserved5:5;
+ __u8 ssid:3;
+ __u16 devno;
+ __u32 reserved6[5];
+ __u32 bootprog;
+ __u8 reserved7[12];
+ struct {
+ __u16 cyl;
+ __u8 head;
+ __u8 record;
+ __u32 reserved;
+ } br_chr __packed;
+ __u32 scp_data_len;
+ __u8 reserved8[260];
+ __u8 scp_data[];
+} __packed;
+
+#define IPL_PB0_ECKD_OPT_IPL 0x10
+#define IPL_PB0_ECKD_OPT_DUMP 0x20
+
#define IPL_PB0_CCW_VM_FLAG_NSS 0x80
#define IPL_PB0_CCW_VM_FLAG_VP 0x40
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c
index e4ef67e4da0a..c13b1455ec8c 100644
--- a/arch/s390/kernel/crash_dump.c
+++ b/arch/s390/kernel/crash_dump.c
@@ -153,7 +153,7 @@ int copy_oldmem_kernel(void *dst, unsigned long src, size_t count)
kvec.iov_base = dst;
kvec.iov_len = count;
- iov_iter_kvec(&iter, WRITE, &kvec, 1, count);
+ iov_iter_kvec(&iter, ITER_DEST, &kvec, 1, count);
if (copy_oldmem_iter(&iter, src, count) < count)
return -EFAULT;
return 0;
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index d7a82066a638..b376f0377a2c 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -92,7 +92,7 @@ static int debug_input_flush_fn(debug_info_t *id, struct debug_view *view,
static int debug_hex_ascii_format_fn(debug_info_t *id, struct debug_view *view,
char *out_buf, const char *in_buf);
static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
- char *out_buf, debug_sprintf_entry_t *curr_event);
+ char *out_buf, const char *inbuf);
static void debug_areas_swap(debug_info_t *a, debug_info_t *b);
static void debug_events_append(debug_info_t *dest, debug_info_t *src);
@@ -139,7 +139,7 @@ struct debug_view debug_sprintf_view = {
"sprintf",
NULL,
&debug_dflt_header_fn,
- (debug_format_proc_t *)&debug_sprintf_format_fn,
+ &debug_sprintf_format_fn,
NULL,
NULL
};
@@ -1532,8 +1532,9 @@ EXPORT_SYMBOL(debug_dflt_header_fn);
#define DEBUG_SPRINTF_MAX_ARGS 10
static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
- char *out_buf, debug_sprintf_entry_t *curr_event)
+ char *out_buf, const char *inbuf)
{
+ debug_sprintf_entry_t *curr_event = (debug_sprintf_entry_t *)inbuf;
int num_longs, num_used_args = 0, i, rc = 0;
int index[DEBUG_SPRINTF_MAX_ARGS];
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index d2a1f2f4f5b8..e0d11f3adfcc 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -122,24 +122,6 @@ _LPP_OFFSET = __LC_LPP
"jnz .+8; .insn rrf,0xb2e80000,0,0,13,0", 82
.endm
- /*
- * The CHKSTG macro jumps to the provided label in case the
- * machine check interruption code reports one of unrecoverable
- * storage errors:
- * - Storage error uncorrected
- * - Storage key error uncorrected
- * - Storage degradation with Failing-storage-address validity
- */
- .macro CHKSTG errlabel
- TSTMSK __LC_MCCK_CODE,(MCCK_CODE_STG_ERROR|MCCK_CODE_STG_KEY_ERROR)
- jnz \errlabel
- TSTMSK __LC_MCCK_CODE,MCCK_CODE_STG_DEGRAD
- jz .Loklabel\@
- TSTMSK __LC_MCCK_CODE,MCCK_CODE_STG_FAIL_ADDR
- jnz \errlabel
-.Loklabel\@:
- .endm
-
#if IS_ENABLED(CONFIG_KVM)
/*
* The OUTSIDE macro jumps to the provided label in case the value
@@ -546,26 +528,18 @@ ENTRY(mcck_int_handler)
3: TSTMSK __LC_MCCK_CODE,MCCK_CODE_PSW_MWP_VALID
jno .Lmcck_panic
tmhh %r8,0x0001 # interrupting from user ?
- jnz 6f
+ jnz .Lmcck_user
TSTMSK __LC_MCCK_CODE,MCCK_CODE_PSW_IA_VALID
jno .Lmcck_panic
#if IS_ENABLED(CONFIG_KVM)
- OUTSIDE %r9,.Lsie_gmap,.Lsie_done,6f
+ OUTSIDE %r9,.Lsie_gmap,.Lsie_done,.Lmcck_stack
OUTSIDE %r9,.Lsie_entry,.Lsie_leave,4f
oi __LC_CPU_FLAGS+7, _CIF_MCCK_GUEST
- j 5f
-4: CHKSTG .Lmcck_panic
-5: larl %r14,.Lstosm_tmp
- stosm 0(%r14),0x04 # turn dat on, keep irqs off
- BPENTER __SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
+4: BPENTER __SF_SIE_FLAGS(%r15),(_TIF_ISOLATE_BP|_TIF_ISOLATE_BP_GUEST)
SIEEXIT
j .Lmcck_stack
#endif
-6: CHKSTG .Lmcck_panic
- larl %r14,.Lstosm_tmp
- stosm 0(%r14),0x04 # turn dat on, keep irqs off
- tmhh %r8,0x0001 # interrupting from user ?
- jz .Lmcck_stack
+.Lmcck_user:
BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP
.Lmcck_stack:
lg %r15,__LC_MCCK_STACK
diff --git a/arch/s390/kernel/fpu.c b/arch/s390/kernel/fpu.c
index d864c9a325e2..4666b29ac8a1 100644
--- a/arch/s390/kernel/fpu.c
+++ b/arch/s390/kernel/fpu.c
@@ -10,8 +10,7 @@
#include <linux/sched.h>
#include <asm/fpu/types.h>
#include <asm/fpu/api.h>
-
-asm(".include \"asm/vx-insn.h\"\n");
+#include <asm/vx-insn.h>
void __kernel_fpu_begin(struct kernel_fpu *state, u32 flags)
{
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 325cbf69ebbd..fbd646dbf440 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/delay.h>
+#include <linux/kstrtox.h>
#include <linux/panic_notifier.h>
#include <linux/reboot.h>
#include <linux/ctype.h>
@@ -39,6 +40,8 @@
#define IPL_UNKNOWN_STR "unknown"
#define IPL_CCW_STR "ccw"
+#define IPL_ECKD_STR "eckd"
+#define IPL_ECKD_DUMP_STR "eckd_dump"
#define IPL_FCP_STR "fcp"
#define IPL_FCP_DUMP_STR "fcp_dump"
#define IPL_NVME_STR "nvme"
@@ -46,6 +49,7 @@
#define IPL_NSS_STR "nss"
#define DUMP_CCW_STR "ccw"
+#define DUMP_ECKD_STR "eckd"
#define DUMP_FCP_STR "fcp"
#define DUMP_NVME_STR "nvme"
#define DUMP_NONE_STR "none"
@@ -92,6 +96,10 @@ static char *ipl_type_str(enum ipl_type type)
switch (type) {
case IPL_TYPE_CCW:
return IPL_CCW_STR;
+ case IPL_TYPE_ECKD:
+ return IPL_ECKD_STR;
+ case IPL_TYPE_ECKD_DUMP:
+ return IPL_ECKD_DUMP_STR;
case IPL_TYPE_FCP:
return IPL_FCP_STR;
case IPL_TYPE_FCP_DUMP:
@@ -113,6 +121,7 @@ enum dump_type {
DUMP_TYPE_CCW = 2,
DUMP_TYPE_FCP = 4,
DUMP_TYPE_NVME = 8,
+ DUMP_TYPE_ECKD = 16,
};
static char *dump_type_str(enum dump_type type)
@@ -122,6 +131,8 @@ static char *dump_type_str(enum dump_type type)
return DUMP_NONE_STR;
case DUMP_TYPE_CCW:
return DUMP_CCW_STR;
+ case DUMP_TYPE_ECKD:
+ return DUMP_ECKD_STR;
case DUMP_TYPE_FCP:
return DUMP_FCP_STR;
case DUMP_TYPE_NVME:
@@ -147,6 +158,7 @@ static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN;
static struct ipl_parameter_block *reipl_block_fcp;
static struct ipl_parameter_block *reipl_block_nvme;
static struct ipl_parameter_block *reipl_block_ccw;
+static struct ipl_parameter_block *reipl_block_eckd;
static struct ipl_parameter_block *reipl_block_nss;
static struct ipl_parameter_block *reipl_block_actual;
@@ -155,12 +167,14 @@ static enum dump_type dump_type = DUMP_TYPE_NONE;
static struct ipl_parameter_block *dump_block_fcp;
static struct ipl_parameter_block *dump_block_nvme;
static struct ipl_parameter_block *dump_block_ccw;
+static struct ipl_parameter_block *dump_block_eckd;
static struct sclp_ipl_info sclp_ipl_info;
static bool reipl_nvme_clear;
static bool reipl_fcp_clear;
static bool reipl_ccw_clear;
+static bool reipl_eckd_clear;
static inline int __diag308(unsigned long subcode, void *addr)
{
@@ -218,14 +232,14 @@ IPL_ATTR_SHOW_FN(_prefix, _name, "0.%x.%04x\n", \
_ipl_blk.ssid, _ipl_blk.devno); \
IPL_ATTR_CCW_STORE_FN(_prefix, _name, _ipl_blk); \
static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
- __ATTR(_name, (S_IRUGO | S_IWUSR), \
+ __ATTR(_name, 0644, \
sys_##_prefix##_##_name##_show, \
sys_##_prefix##_##_name##_store) \
#define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value) \
IPL_ATTR_SHOW_FN(_prefix, _name, _format, _value) \
static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
- __ATTR(_name, S_IRUGO, sys_##_prefix##_##_name##_show, NULL)
+ __ATTR(_name, 0444, sys_##_prefix##_##_name##_show, NULL)
#define DEFINE_IPL_ATTR_RW(_prefix, _name, _fmt_out, _fmt_in, _value) \
IPL_ATTR_SHOW_FN(_prefix, _name, _fmt_out, (unsigned long long) _value) \
@@ -240,7 +254,7 @@ static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \
return len; \
} \
static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
- __ATTR(_name,(S_IRUGO | S_IWUSR), \
+ __ATTR(_name, 0644, \
sys_##_prefix##_##_name##_show, \
sys_##_prefix##_##_name##_store)
@@ -255,7 +269,7 @@ static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \
return len; \
} \
static struct kobj_attribute sys_##_prefix##_##_name##_attr = \
- __ATTR(_name,(S_IRUGO | S_IWUSR), \
+ __ATTR(_name, 0644, \
sys_##_prefix##_##_name##_show, \
sys_##_prefix##_##_name##_store)
@@ -281,6 +295,11 @@ static __init enum ipl_type get_ipl_type(void)
return IPL_TYPE_NVME_DUMP;
else
return IPL_TYPE_NVME;
+ case IPL_PBT_ECKD:
+ if (ipl_block.eckd.opt == IPL_PB0_ECKD_OPT_DUMP)
+ return IPL_TYPE_ECKD_DUMP;
+ else
+ return IPL_TYPE_ECKD;
}
return IPL_TYPE_UNKNOWN;
}
@@ -325,7 +344,7 @@ static ssize_t ipl_vm_parm_show(struct kobject *kobj,
}
static struct kobj_attribute sys_ipl_vm_parm_attr =
- __ATTR(parm, S_IRUGO, ipl_vm_parm_show, NULL);
+ __ATTR(parm, 0444, ipl_vm_parm_show, NULL);
static ssize_t sys_ipl_device_show(struct kobject *kobj,
struct kobj_attribute *attr, char *page)
@@ -334,6 +353,10 @@ static ssize_t sys_ipl_device_show(struct kobject *kobj,
case IPL_TYPE_CCW:
return sprintf(page, "0.%x.%04x\n", ipl_block.ccw.ssid,
ipl_block.ccw.devno);
+ case IPL_TYPE_ECKD:
+ case IPL_TYPE_ECKD_DUMP:
+ return sprintf(page, "0.%x.%04x\n", ipl_block.eckd.ssid,
+ ipl_block.eckd.devno);
case IPL_TYPE_FCP:
case IPL_TYPE_FCP_DUMP:
return sprintf(page, "0.0.%04x\n", ipl_block.fcp.devno);
@@ -346,7 +369,7 @@ static ssize_t sys_ipl_device_show(struct kobject *kobj,
}
static struct kobj_attribute sys_ipl_device_attr =
- __ATTR(device, S_IRUGO, sys_ipl_device_show, NULL);
+ __ATTR(device, 0444, sys_ipl_device_show, NULL);
static ssize_t ipl_parameter_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *attr, char *buf,
@@ -356,7 +379,7 @@ static ssize_t ipl_parameter_read(struct file *filp, struct kobject *kobj,
ipl_block.hdr.len);
}
static struct bin_attribute ipl_parameter_attr =
- __BIN_ATTR(binary_parameter, S_IRUGO, ipl_parameter_read, NULL,
+ __BIN_ATTR(binary_parameter, 0444, ipl_parameter_read, NULL,
PAGE_SIZE);
static ssize_t ipl_scp_data_read(struct file *filp, struct kobject *kobj,
@@ -379,11 +402,24 @@ static ssize_t ipl_nvme_scp_data_read(struct file *filp, struct kobject *kobj,
return memory_read_from_buffer(buf, count, &off, scp_data, size);
}
+static ssize_t ipl_eckd_scp_data_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr, char *buf,
+ loff_t off, size_t count)
+{
+ unsigned int size = ipl_block.eckd.scp_data_len;
+ void *scp_data = &ipl_block.eckd.scp_data;
+
+ return memory_read_from_buffer(buf, count, &off, scp_data, size);
+}
+
static struct bin_attribute ipl_scp_data_attr =
- __BIN_ATTR(scp_data, S_IRUGO, ipl_scp_data_read, NULL, PAGE_SIZE);
+ __BIN_ATTR(scp_data, 0444, ipl_scp_data_read, NULL, PAGE_SIZE);
static struct bin_attribute ipl_nvme_scp_data_attr =
- __BIN_ATTR(scp_data, S_IRUGO, ipl_nvme_scp_data_read, NULL, PAGE_SIZE);
+ __BIN_ATTR(scp_data, 0444, ipl_nvme_scp_data_read, NULL, PAGE_SIZE);
+
+static struct bin_attribute ipl_eckd_scp_data_attr =
+ __BIN_ATTR(scp_data, 0444, ipl_eckd_scp_data_read, NULL, PAGE_SIZE);
static struct bin_attribute *ipl_fcp_bin_attrs[] = {
&ipl_parameter_attr,
@@ -397,6 +433,12 @@ static struct bin_attribute *ipl_nvme_bin_attrs[] = {
NULL,
};
+static struct bin_attribute *ipl_eckd_bin_attrs[] = {
+ &ipl_parameter_attr,
+ &ipl_eckd_scp_data_attr,
+ NULL,
+};
+
/* FCP ipl device attributes */
DEFINE_IPL_ATTR_RO(ipl_fcp, wwpn, "0x%016llx\n",
@@ -418,6 +460,84 @@ DEFINE_IPL_ATTR_RO(ipl_nvme, bootprog, "%lld\n",
DEFINE_IPL_ATTR_RO(ipl_nvme, br_lba, "%lld\n",
(unsigned long long)ipl_block.nvme.br_lba);
+/* ECKD ipl device attributes */
+DEFINE_IPL_ATTR_RO(ipl_eckd, bootprog, "%lld\n",
+ (unsigned long long)ipl_block.eckd.bootprog);
+
+#define IPL_ATTR_BR_CHR_SHOW_FN(_name, _ipb) \
+static ssize_t eckd_##_name##_br_chr_show(struct kobject *kobj, \
+ struct kobj_attribute *attr, \
+ char *buf) \
+{ \
+ struct ipl_pb0_eckd *ipb = &(_ipb); \
+ \
+ if (!ipb->br_chr.cyl && \
+ !ipb->br_chr.head && \
+ !ipb->br_chr.record) \
+ return sprintf(buf, "auto\n"); \
+ \
+ return sprintf(buf, "0x%x,0x%x,0x%x\n", \
+ ipb->br_chr.cyl, \
+ ipb->br_chr.head, \
+ ipb->br_chr.record); \
+}
+
+#define IPL_ATTR_BR_CHR_STORE_FN(_name, _ipb) \
+static ssize_t eckd_##_name##_br_chr_store(struct kobject *kobj, \
+ struct kobj_attribute *attr, \
+ const char *buf, size_t len) \
+{ \
+ struct ipl_pb0_eckd *ipb = &(_ipb); \
+ unsigned long args[3] = { 0 }; \
+ char *p, *p1, *tmp = NULL; \
+ int i, rc; \
+ \
+ if (!strncmp(buf, "auto", 4)) \
+ goto out; \
+ \
+ tmp = kstrdup(buf, GFP_KERNEL); \
+ p = tmp; \
+ for (i = 0; i < 3; i++) { \
+ p1 = strsep(&p, ", "); \
+ if (!p1) { \
+ rc = -EINVAL; \
+ goto err; \
+ } \
+ rc = kstrtoul(p1, 0, args + i); \
+ if (rc) \
+ goto err; \
+ } \
+ \
+ rc = -EINVAL; \
+ if (i != 3) \
+ goto err; \
+ \
+ if ((args[0] || args[1]) && !args[2]) \
+ goto err; \
+ \
+ if (args[0] > UINT_MAX || args[1] > 255 || args[2] > 255) \
+ goto err; \
+ \
+out: \
+ ipb->br_chr.cyl = args[0]; \
+ ipb->br_chr.head = args[1]; \
+ ipb->br_chr.record = args[2]; \
+ rc = len; \
+err: \
+ kfree(tmp); \
+ return rc; \
+}
+
+IPL_ATTR_BR_CHR_SHOW_FN(ipl, ipl_block.eckd);
+static struct kobj_attribute sys_ipl_eckd_br_chr_attr =
+ __ATTR(br_chr, 0644, eckd_ipl_br_chr_show, NULL);
+
+IPL_ATTR_BR_CHR_SHOW_FN(reipl, reipl_block_eckd->eckd);
+IPL_ATTR_BR_CHR_STORE_FN(reipl, reipl_block_eckd->eckd);
+
+static struct kobj_attribute sys_reipl_eckd_br_chr_attr =
+ __ATTR(br_chr, 0644, eckd_reipl_br_chr_show, eckd_reipl_br_chr_store);
+
static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
struct kobj_attribute *attr, char *page)
{
@@ -469,6 +589,20 @@ static struct attribute_group ipl_nvme_attr_group = {
.bin_attrs = ipl_nvme_bin_attrs,
};
+static struct attribute *ipl_eckd_attrs[] = {
+ &sys_ipl_type_attr.attr,
+ &sys_ipl_eckd_bootprog_attr.attr,
+ &sys_ipl_eckd_br_chr_attr.attr,
+ &sys_ipl_device_attr.attr,
+ &sys_ipl_secure_attr.attr,
+ &sys_ipl_has_secure_attr.attr,
+ NULL,
+};
+
+static struct attribute_group ipl_eckd_attr_group = {
+ .attrs = ipl_eckd_attrs,
+ .bin_attrs = ipl_eckd_bin_attrs,
+};
/* CCW ipl device attributes */
@@ -541,6 +675,9 @@ static int __init ipl_init(void)
rc = sysfs_create_group(&ipl_kset->kobj,
&ipl_ccw_attr_group_lpar);
break;
+ case IPL_TYPE_ECKD:
+ rc = sysfs_create_group(&ipl_kset->kobj, &ipl_eckd_attr_group);
+ break;
case IPL_TYPE_FCP:
case IPL_TYPE_FCP_DUMP:
rc = sysfs_create_group(&ipl_kset->kobj, &ipl_fcp_attr_group);
@@ -642,11 +779,11 @@ static ssize_t reipl_ccw_vmparm_store(struct kobject *kobj,
}
static struct kobj_attribute sys_reipl_nss_vmparm_attr =
- __ATTR(parm, S_IRUGO | S_IWUSR, reipl_nss_vmparm_show,
- reipl_nss_vmparm_store);
+ __ATTR(parm, 0644, reipl_nss_vmparm_show,
+ reipl_nss_vmparm_store);
static struct kobj_attribute sys_reipl_ccw_vmparm_attr =
- __ATTR(parm, S_IRUGO | S_IWUSR, reipl_ccw_vmparm_show,
- reipl_ccw_vmparm_store);
+ __ATTR(parm, 0644, reipl_ccw_vmparm_show,
+ reipl_ccw_vmparm_store);
/* FCP reipl device attributes */
@@ -686,7 +823,7 @@ static ssize_t reipl_fcp_scpdata_write(struct file *filp, struct kobject *kobj,
return count;
}
static struct bin_attribute sys_reipl_fcp_scp_data_attr =
- __BIN_ATTR(scp_data, (S_IRUGO | S_IWUSR), reipl_fcp_scpdata_read,
+ __BIN_ATTR(scp_data, 0644, reipl_fcp_scpdata_read,
reipl_fcp_scpdata_write, DIAG308_SCPDATA_SIZE);
static struct bin_attribute *reipl_fcp_bin_attrs[] = {
@@ -766,8 +903,8 @@ static ssize_t reipl_fcp_loadparm_store(struct kobject *kobj,
}
static struct kobj_attribute sys_reipl_fcp_loadparm_attr =
- __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_fcp_loadparm_show,
- reipl_fcp_loadparm_store);
+ __ATTR(loadparm, 0644, reipl_fcp_loadparm_show,
+ reipl_fcp_loadparm_store);
static ssize_t reipl_fcp_clear_show(struct kobject *kobj,
struct kobj_attribute *attr, char *page)
@@ -779,7 +916,7 @@ static ssize_t reipl_fcp_clear_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t len)
{
- if (strtobool(buf, &reipl_fcp_clear) < 0)
+ if (kstrtobool(buf, &reipl_fcp_clear) < 0)
return -EINVAL;
return len;
}
@@ -840,7 +977,7 @@ static ssize_t reipl_nvme_scpdata_write(struct file *filp, struct kobject *kobj,
}
static struct bin_attribute sys_reipl_nvme_scp_data_attr =
- __BIN_ATTR(scp_data, (S_IRUGO | S_IWUSR), reipl_nvme_scpdata_read,
+ __BIN_ATTR(scp_data, 0644, reipl_nvme_scpdata_read,
reipl_nvme_scpdata_write, DIAG308_SCPDATA_SIZE);
static struct bin_attribute *reipl_nvme_bin_attrs[] = {
@@ -872,8 +1009,8 @@ static ssize_t reipl_nvme_loadparm_store(struct kobject *kobj,
}
static struct kobj_attribute sys_reipl_nvme_loadparm_attr =
- __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_nvme_loadparm_show,
- reipl_nvme_loadparm_store);
+ __ATTR(loadparm, 0644, reipl_nvme_loadparm_show,
+ reipl_nvme_loadparm_store);
static struct attribute *reipl_nvme_attrs[] = {
&sys_reipl_nvme_fid_attr.attr,
@@ -899,7 +1036,7 @@ static ssize_t reipl_nvme_clear_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t len)
{
- if (strtobool(buf, &reipl_nvme_clear) < 0)
+ if (kstrtobool(buf, &reipl_nvme_clear) < 0)
return -EINVAL;
return len;
}
@@ -939,8 +1076,8 @@ static ssize_t reipl_ccw_loadparm_store(struct kobject *kobj,
}
static struct kobj_attribute sys_reipl_ccw_loadparm_attr =
- __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_ccw_loadparm_show,
- reipl_ccw_loadparm_store);
+ __ATTR(loadparm, 0644, reipl_ccw_loadparm_show,
+ reipl_ccw_loadparm_store);
static ssize_t reipl_ccw_clear_show(struct kobject *kobj,
struct kobj_attribute *attr, char *page)
@@ -952,7 +1089,7 @@ static ssize_t reipl_ccw_clear_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t len)
{
- if (strtobool(buf, &reipl_ccw_clear) < 0)
+ if (kstrtobool(buf, &reipl_ccw_clear) < 0)
return -EINVAL;
return len;
}
@@ -985,6 +1122,85 @@ static struct attribute_group reipl_ccw_attr_group_lpar = {
.attrs = reipl_ccw_attrs_lpar,
};
+/* ECKD reipl device attributes */
+
+static ssize_t reipl_eckd_scpdata_read(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ size_t size = reipl_block_eckd->eckd.scp_data_len;
+ void *scp_data = reipl_block_eckd->eckd.scp_data;
+
+ return memory_read_from_buffer(buf, count, &off, scp_data, size);
+}
+
+static ssize_t reipl_eckd_scpdata_write(struct file *filp, struct kobject *kobj,
+ struct bin_attribute *attr,
+ char *buf, loff_t off, size_t count)
+{
+ size_t scpdata_len = count;
+ size_t padding;
+
+ if (off)
+ return -EINVAL;
+
+ memcpy(reipl_block_eckd->eckd.scp_data, buf, count);
+ if (scpdata_len % 8) {
+ padding = 8 - (scpdata_len % 8);
+ memset(reipl_block_eckd->eckd.scp_data + scpdata_len,
+ 0, padding);
+ scpdata_len += padding;
+ }
+
+ reipl_block_eckd->hdr.len = IPL_BP_ECKD_LEN + scpdata_len;
+ reipl_block_eckd->eckd.len = IPL_BP0_ECKD_LEN + scpdata_len;
+ reipl_block_eckd->eckd.scp_data_len = scpdata_len;
+
+ return count;
+}
+
+static struct bin_attribute sys_reipl_eckd_scp_data_attr =
+ __BIN_ATTR(scp_data, 0644, reipl_eckd_scpdata_read,
+ reipl_eckd_scpdata_write, DIAG308_SCPDATA_SIZE);
+
+static struct bin_attribute *reipl_eckd_bin_attrs[] = {
+ &sys_reipl_eckd_scp_data_attr,
+ NULL,
+};
+
+DEFINE_IPL_CCW_ATTR_RW(reipl_eckd, device, reipl_block_eckd->eckd);
+DEFINE_IPL_ATTR_RW(reipl_eckd, bootprog, "%lld\n", "%lld\n",
+ reipl_block_eckd->eckd.bootprog);
+
+static struct attribute *reipl_eckd_attrs[] = {
+ &sys_reipl_eckd_device_attr.attr,
+ &sys_reipl_eckd_bootprog_attr.attr,
+ &sys_reipl_eckd_br_chr_attr.attr,
+ NULL,
+};
+
+static struct attribute_group reipl_eckd_attr_group = {
+ .attrs = reipl_eckd_attrs,
+ .bin_attrs = reipl_eckd_bin_attrs
+};
+
+static ssize_t reipl_eckd_clear_show(struct kobject *kobj,
+ struct kobj_attribute *attr, char *page)
+{
+ return sprintf(page, "%u\n", reipl_eckd_clear);
+}
+
+static ssize_t reipl_eckd_clear_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf, size_t len)
+{
+ if (strtobool(buf, &reipl_eckd_clear) < 0)
+ return -EINVAL;
+ return len;
+}
+
+static struct kobj_attribute sys_reipl_eckd_clear_attr =
+ __ATTR(clear, 0644, reipl_eckd_clear_show, reipl_eckd_clear_store);
/* NSS reipl device attributes */
static void reipl_get_ascii_nss_name(char *dst,
@@ -1032,12 +1248,12 @@ static ssize_t reipl_nss_name_store(struct kobject *kobj,
}
static struct kobj_attribute sys_reipl_nss_name_attr =
- __ATTR(name, S_IRUGO | S_IWUSR, reipl_nss_name_show,
- reipl_nss_name_store);
+ __ATTR(name, 0644, reipl_nss_name_show,
+ reipl_nss_name_store);
static struct kobj_attribute sys_reipl_nss_loadparm_attr =
- __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_nss_loadparm_show,
- reipl_nss_loadparm_store);
+ __ATTR(loadparm, 0644, reipl_nss_loadparm_show,
+ reipl_nss_loadparm_store);
static struct attribute *reipl_nss_attrs[] = {
&sys_reipl_nss_name_attr.attr,
@@ -1068,6 +1284,9 @@ static int reipl_set_type(enum ipl_type type)
case IPL_TYPE_CCW:
reipl_block_actual = reipl_block_ccw;
break;
+ case IPL_TYPE_ECKD:
+ reipl_block_actual = reipl_block_eckd;
+ break;
case IPL_TYPE_FCP:
reipl_block_actual = reipl_block_fcp;
break;
@@ -1098,6 +1317,8 @@ static ssize_t reipl_type_store(struct kobject *kobj,
if (strncmp(buf, IPL_CCW_STR, strlen(IPL_CCW_STR)) == 0)
rc = reipl_set_type(IPL_TYPE_CCW);
+ else if (strncmp(buf, IPL_ECKD_STR, strlen(IPL_ECKD_STR)) == 0)
+ rc = reipl_set_type(IPL_TYPE_ECKD);
else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0)
rc = reipl_set_type(IPL_TYPE_FCP);
else if (strncmp(buf, IPL_NVME_STR, strlen(IPL_NVME_STR)) == 0)
@@ -1113,6 +1334,7 @@ static struct kobj_attribute reipl_type_attr =
static struct kset *reipl_kset;
static struct kset *reipl_fcp_kset;
static struct kset *reipl_nvme_kset;
+static struct kset *reipl_eckd_kset;
static void __reipl_run(void *unused)
{
@@ -1124,6 +1346,13 @@ static void __reipl_run(void *unused)
else
diag308(DIAG308_LOAD_NORMAL_DUMP, NULL);
break;
+ case IPL_TYPE_ECKD:
+ diag308(DIAG308_SET, reipl_block_eckd);
+ if (reipl_eckd_clear)
+ diag308(DIAG308_LOAD_CLEAR, NULL);
+ else
+ diag308(DIAG308_LOAD_NORMAL, NULL);
+ break;
case IPL_TYPE_FCP:
diag308(DIAG308_SET, reipl_block_fcp);
if (reipl_fcp_clear)
@@ -1147,6 +1376,7 @@ static void __reipl_run(void *unused)
break;
case IPL_TYPE_FCP_DUMP:
case IPL_TYPE_NVME_DUMP:
+ case IPL_TYPE_ECKD_DUMP:
break;
}
disabled_wait();
@@ -1344,6 +1574,58 @@ out1:
return rc;
}
+static int __init reipl_eckd_init(void)
+{
+ int rc;
+
+ if (!sclp.has_sipl_eckd)
+ return 0;
+
+ reipl_block_eckd = (void *)get_zeroed_page(GFP_KERNEL);
+ if (!reipl_block_eckd)
+ return -ENOMEM;
+
+ /* sysfs: create kset for mixing attr group and bin attrs */
+ reipl_eckd_kset = kset_create_and_add(IPL_ECKD_STR, NULL,
+ &reipl_kset->kobj);
+ if (!reipl_eckd_kset) {
+ free_page((unsigned long)reipl_block_eckd);
+ return -ENOMEM;
+ }
+
+ rc = sysfs_create_group(&reipl_eckd_kset->kobj, &reipl_eckd_attr_group);
+ if (rc)
+ goto out1;
+
+ if (test_facility(141)) {
+ rc = sysfs_create_file(&reipl_eckd_kset->kobj,
+ &sys_reipl_eckd_clear_attr.attr);
+ if (rc)
+ goto out2;
+ } else {
+ reipl_eckd_clear = true;
+ }
+
+ if (ipl_info.type == IPL_TYPE_ECKD) {
+ memcpy(reipl_block_eckd, &ipl_block, sizeof(ipl_block));
+ } else {
+ reipl_block_eckd->hdr.len = IPL_BP_ECKD_LEN;
+ reipl_block_eckd->hdr.version = IPL_PARM_BLOCK_VERSION;
+ reipl_block_eckd->eckd.len = IPL_BP0_ECKD_LEN;
+ reipl_block_eckd->eckd.pbt = IPL_PBT_ECKD;
+ reipl_block_eckd->eckd.opt = IPL_PB0_ECKD_OPT_IPL;
+ }
+ reipl_capabilities |= IPL_TYPE_ECKD;
+ return 0;
+
+out2:
+ sysfs_remove_group(&reipl_eckd_kset->kobj, &reipl_eckd_attr_group);
+out1:
+ kset_unregister(reipl_eckd_kset);
+ free_page((unsigned long)reipl_block_eckd);
+ return rc;
+}
+
static int __init reipl_type_init(void)
{
enum ipl_type reipl_type = ipl_info.type;
@@ -1365,6 +1647,9 @@ static int __init reipl_type_init(void)
} else if (reipl_block->pb0_hdr.pbt == IPL_PBT_CCW) {
memcpy(reipl_block_ccw, reipl_block, size);
reipl_type = IPL_TYPE_CCW;
+ } else if (reipl_block->pb0_hdr.pbt == IPL_PBT_ECKD) {
+ memcpy(reipl_block_eckd, reipl_block, size);
+ reipl_type = IPL_TYPE_ECKD;
}
out:
return reipl_set_type(reipl_type);
@@ -1385,6 +1670,9 @@ static int __init reipl_init(void)
rc = reipl_ccw_init();
if (rc)
return rc;
+ rc = reipl_eckd_init();
+ if (rc)
+ return rc;
rc = reipl_fcp_init();
if (rc)
return rc;
@@ -1457,6 +1745,29 @@ static struct attribute_group dump_nvme_attr_group = {
.attrs = dump_nvme_attrs,
};
+/* ECKD dump device attributes */
+DEFINE_IPL_CCW_ATTR_RW(dump_eckd, device, dump_block_eckd->eckd);
+DEFINE_IPL_ATTR_RW(dump_eckd, bootprog, "%lld\n", "%llx\n",
+ dump_block_eckd->eckd.bootprog);
+
+IPL_ATTR_BR_CHR_SHOW_FN(dump, dump_block_eckd->eckd);
+IPL_ATTR_BR_CHR_STORE_FN(dump, dump_block_eckd->eckd);
+
+static struct kobj_attribute sys_dump_eckd_br_chr_attr =
+ __ATTR(br_chr, 0644, eckd_dump_br_chr_show, eckd_dump_br_chr_store);
+
+static struct attribute *dump_eckd_attrs[] = {
+ &sys_dump_eckd_device_attr.attr,
+ &sys_dump_eckd_bootprog_attr.attr,
+ &sys_dump_eckd_br_chr_attr.attr,
+ NULL,
+};
+
+static struct attribute_group dump_eckd_attr_group = {
+ .name = IPL_ECKD_STR,
+ .attrs = dump_eckd_attrs,
+};
+
/* CCW dump device attributes */
DEFINE_IPL_CCW_ATTR_RW(dump_ccw, device, dump_block_ccw->ccw);
@@ -1496,6 +1807,8 @@ static ssize_t dump_type_store(struct kobject *kobj,
rc = dump_set_type(DUMP_TYPE_NONE);
else if (strncmp(buf, DUMP_CCW_STR, strlen(DUMP_CCW_STR)) == 0)
rc = dump_set_type(DUMP_TYPE_CCW);
+ else if (strncmp(buf, DUMP_ECKD_STR, strlen(DUMP_ECKD_STR)) == 0)
+ rc = dump_set_type(DUMP_TYPE_ECKD);
else if (strncmp(buf, DUMP_FCP_STR, strlen(DUMP_FCP_STR)) == 0)
rc = dump_set_type(DUMP_TYPE_FCP);
else if (strncmp(buf, DUMP_NVME_STR, strlen(DUMP_NVME_STR)) == 0)
@@ -1524,6 +1837,9 @@ static void __dump_run(void *unused)
case DUMP_TYPE_CCW:
diag308_dump(dump_block_ccw);
break;
+ case DUMP_TYPE_ECKD:
+ diag308_dump(dump_block_eckd);
+ break;
case DUMP_TYPE_FCP:
diag308_dump(dump_block_fcp);
break;
@@ -1609,6 +1925,29 @@ static int __init dump_nvme_init(void)
return 0;
}
+static int __init dump_eckd_init(void)
+{
+ int rc;
+
+ if (!sclp_ipl_info.has_dump || !sclp.has_sipl_eckd)
+ return 0; /* LDIPL DUMP is not installed */
+ dump_block_eckd = (void *)get_zeroed_page(GFP_KERNEL);
+ if (!dump_block_eckd)
+ return -ENOMEM;
+ rc = sysfs_create_group(&dump_kset->kobj, &dump_eckd_attr_group);
+ if (rc) {
+ free_page((unsigned long)dump_block_eckd);
+ return rc;
+ }
+ dump_block_eckd->hdr.len = IPL_BP_ECKD_LEN;
+ dump_block_eckd->hdr.version = IPL_PARM_BLOCK_VERSION;
+ dump_block_eckd->eckd.len = IPL_BP0_ECKD_LEN;
+ dump_block_eckd->eckd.pbt = IPL_PBT_ECKD;
+ dump_block_eckd->eckd.opt = IPL_PB0_ECKD_OPT_DUMP;
+ dump_capabilities |= DUMP_TYPE_ECKD;
+ return 0;
+}
+
static int __init dump_init(void)
{
int rc;
@@ -1624,6 +1963,9 @@ static int __init dump_init(void)
rc = dump_ccw_init();
if (rc)
return rc;
+ rc = dump_eckd_init();
+ if (rc)
+ return rc;
rc = dump_fcp_init();
if (rc)
return rc;
@@ -2057,6 +2399,11 @@ void __init setup_ipl(void)
ipl_info.data.ccw.dev_id.ssid = ipl_block.ccw.ssid;
ipl_info.data.ccw.dev_id.devno = ipl_block.ccw.devno;
break;
+ case IPL_TYPE_ECKD:
+ case IPL_TYPE_ECKD_DUMP:
+ ipl_info.data.eckd.dev_id.ssid = ipl_block.eckd.ssid;
+ ipl_info.data.eckd.dev_id.devno = ipl_block.eckd.devno;
+ break;
case IPL_TYPE_FCP:
case IPL_TYPE_FCP_DUMP:
ipl_info.data.fcp.dev_id.ssid = 0;
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 0032bdbe8e3f..401f9c933ff9 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -24,6 +24,7 @@
#include <asm/set_memory.h>
#include <asm/sections.h>
#include <asm/dis.h>
+#include "kprobes.h"
#include "entry.h"
DEFINE_PER_CPU(struct kprobe *, current_kprobe);
@@ -31,8 +32,6 @@ DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
struct kretprobe_blackpoint kretprobe_blacklist[] = { };
-DEFINE_INSN_CACHE_OPS(s390_insn);
-
static int insn_page_in_use;
void *alloc_insn_page(void)
diff --git a/arch/s390/kernel/kprobes.h b/arch/s390/kernel/kprobes.h
new file mode 100644
index 000000000000..dc3ed5098ee7
--- /dev/null
+++ b/arch/s390/kernel/kprobes.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+#ifndef _ARCH_S390_KPROBES_H
+#define _ARCH_S390_KPROBES_H
+
+#include <linux/kprobes.h>
+
+DEFINE_INSN_CACHE_OPS(s390_insn);
+
+#endif
diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c
index 31cb9b00a36b..5dbf274719a9 100644
--- a/arch/s390/kernel/nmi.c
+++ b/arch/s390/kernel/nmi.c
@@ -19,7 +19,7 @@
#include <linux/time.h>
#include <linux/module.h>
#include <linux/sched/signal.h>
-
+#include <linux/kvm_host.h>
#include <linux/export.h>
#include <asm/lowcore.h>
#include <asm/smp.h>
@@ -31,8 +31,7 @@
#include <asm/ctl_reg.h>
#include <asm/asm-offsets.h>
#include <asm/pai.h>
-
-#include <linux/kvm_host.h>
+#include <asm/vx-insn.h>
struct mcck_struct {
unsigned int kill_task : 1;
@@ -43,21 +42,12 @@ struct mcck_struct {
};
static DEFINE_PER_CPU(struct mcck_struct, cpu_mcck);
-static struct kmem_cache *mcesa_cache;
-static unsigned long mcesa_origin_lc;
static inline int nmi_needs_mcesa(void)
{
return MACHINE_HAS_VX || MACHINE_HAS_GS;
}
-static inline unsigned long nmi_get_mcesa_size(void)
-{
- if (MACHINE_HAS_GS)
- return MCESA_MAX_SIZE;
- return MCESA_MIN_SIZE;
-}
-
/*
* The initial machine check extended save area for the boot CPU.
* It will be replaced on the boot CPU reinit with an allocated
@@ -75,36 +65,23 @@ void __init nmi_alloc_mcesa_early(u64 *mcesad)
*mcesad |= ilog2(MCESA_MAX_SIZE);
}
-static void __init nmi_alloc_cache(void)
+int nmi_alloc_mcesa(u64 *mcesad)
{
unsigned long size;
-
- if (!nmi_needs_mcesa())
- return;
- size = nmi_get_mcesa_size();
- if (size > MCESA_MIN_SIZE)
- mcesa_origin_lc = ilog2(size);
- /* create slab cache for the machine-check-extended-save-areas */
- mcesa_cache = kmem_cache_create("nmi_save_areas", size, size, 0, NULL);
- if (!mcesa_cache)
- panic("Couldn't create nmi save area cache");
-}
-
-int __ref nmi_alloc_mcesa(u64 *mcesad)
-{
- unsigned long origin;
+ void *origin;
*mcesad = 0;
if (!nmi_needs_mcesa())
return 0;
- if (!mcesa_cache)
- nmi_alloc_cache();
- origin = (unsigned long) kmem_cache_alloc(mcesa_cache, GFP_KERNEL);
+ size = MACHINE_HAS_GS ? MCESA_MAX_SIZE : MCESA_MIN_SIZE;
+ origin = kmalloc(size, GFP_KERNEL);
if (!origin)
return -ENOMEM;
/* The pointer is stored with mcesa_bits ORed in */
- kmemleak_not_leak((void *) origin);
- *mcesad = __pa(origin) | mcesa_origin_lc;
+ kmemleak_not_leak(origin);
+ *mcesad = __pa(origin);
+ if (MACHINE_HAS_GS)
+ *mcesad |= ilog2(MCESA_MAX_SIZE);
return 0;
}
@@ -112,12 +89,64 @@ void nmi_free_mcesa(u64 *mcesad)
{
if (!nmi_needs_mcesa())
return;
- kmem_cache_free(mcesa_cache, __va(*mcesad & MCESA_ORIGIN_MASK));
+ kfree(__va(*mcesad & MCESA_ORIGIN_MASK));
+}
+
+static __always_inline char *nmi_puts(char *dest, const char *src)
+{
+ while (*src)
+ *dest++ = *src++;
+ *dest = 0;
+ return dest;
+}
+
+static __always_inline char *u64_to_hex(char *dest, u64 val)
+{
+ int i, num;
+
+ for (i = 1; i <= 16; i++) {
+ num = (val >> (64 - 4 * i)) & 0xf;
+ if (num >= 10)
+ *dest++ = 'A' + num - 10;
+ else
+ *dest++ = '0' + num;
+ }
+ *dest = 0;
+ return dest;
}
static notrace void s390_handle_damage(void)
{
+ union ctlreg0 cr0, cr0_new;
+ char message[100];
+ psw_t psw_save;
+ char *ptr;
+
smp_emergency_stop();
+ diag_amode31_ops.diag308_reset();
+ ptr = nmi_puts(message, "System stopped due to unrecoverable machine check, code: 0x");
+ u64_to_hex(ptr, S390_lowcore.mcck_interruption_code);
+
+ /*
+ * Disable low address protection and make machine check new PSW a
+ * disabled wait PSW. Any additional machine check cannot be handled.
+ */
+ __ctl_store(cr0.val, 0, 0);
+ cr0_new = cr0;
+ cr0_new.lap = 0;
+ __ctl_load(cr0_new.val, 0, 0);
+ psw_save = S390_lowcore.mcck_new_psw;
+ psw_bits(S390_lowcore.mcck_new_psw).io = 0;
+ psw_bits(S390_lowcore.mcck_new_psw).ext = 0;
+ psw_bits(S390_lowcore.mcck_new_psw).wait = 1;
+ sclp_emergency_printk(message);
+
+ /*
+ * Restore machine check new PSW and control register 0 to original
+ * values. This makes possible system dump analysis easier.
+ */
+ S390_lowcore.mcck_new_psw = psw_save;
+ __ctl_load(cr0.val, 0, 0);
disabled_wait();
while (1);
}
@@ -181,10 +210,10 @@ void noinstr s390_handle_mcck(struct pt_regs *regs)
trace_hardirqs_on();
}
/*
- * returns 0 if all required registers are available
+ * returns 0 if register contents could be validated
* returns 1 otherwise
*/
-static int notrace s390_validate_registers(union mci mci, int umode)
+static int notrace s390_validate_registers(union mci mci)
{
struct mcesa *mcesa;
void *fpt_save_area;
@@ -195,45 +224,15 @@ static int notrace s390_validate_registers(union mci mci, int umode)
kill_task = 0;
zero = 0;
- if (!mci.gr) {
- /*
- * General purpose registers couldn't be restored and have
- * unknown contents. Stop system or terminate process.
- */
- if (!umode)
- s390_handle_damage();
+ if (!mci.gr || !mci.fp)
kill_task = 1;
- }
- if (!mci.fp) {
- /*
- * Floating point registers can't be restored. If the
- * kernel currently uses floating point registers the
- * system is stopped. If the process has its floating
- * pointer registers loaded it is terminated.
- */
- if (S390_lowcore.fpu_flags & KERNEL_VXR_V0V7)
- s390_handle_damage();
- if (!test_cpu_flag(CIF_FPU))
- kill_task = 1;
- }
fpt_save_area = &S390_lowcore.floating_pt_save_area;
if (!mci.fc) {
- /*
- * Floating point control register can't be restored.
- * If the kernel currently uses the floating pointer
- * registers and needs the FPC register the system is
- * stopped. If the process has its floating pointer
- * registers loaded it is terminated. Otherwise the
- * FPC is just validated.
- */
- if (S390_lowcore.fpu_flags & KERNEL_FPC)
- s390_handle_damage();
+ kill_task = 1;
asm volatile(
" lfpc %0\n"
:
: "Q" (zero));
- if (!test_cpu_flag(CIF_FPU))
- kill_task = 1;
} else {
asm volatile(
" lfpc %0\n"
@@ -275,26 +274,15 @@ static int notrace s390_validate_registers(union mci mci, int umode)
* appropriate actions. The host vector or FPU values have been
* saved by KVM and will be restored by KVM.
*/
- if (!mci.vr && !test_cpu_flag(CIF_MCCK_GUEST)) {
- /*
- * Vector registers can't be restored. If the kernel
- * currently uses vector registers the system is
- * stopped. If the process has its vector registers
- * loaded it is terminated. Otherwise just validate
- * the registers.
- */
- if (S390_lowcore.fpu_flags & KERNEL_VXR)
- s390_handle_damage();
- if (!test_cpu_flag(CIF_FPU))
- kill_task = 1;
- }
+ if (!mci.vr && !test_cpu_flag(CIF_MCCK_GUEST))
+ kill_task = 1;
cr0.val = S390_lowcore.cregs_save_area[0];
cr0.afp = cr0.vx = 1;
__ctl_load(cr0.val, 0, 0);
asm volatile(
" la 1,%0\n"
- " .word 0xe70f,0x1000,0x0036\n" /* vlm 0,15,0(1) */
- " .word 0xe70f,0x1100,0x0c36\n" /* vlm 16,31,256(1) */
+ " VLM 0,15,0,1\n"
+ " VLM 16,31,256,1\n"
:
: "Q" (*(struct vx_array *)mcesa->vector_save_area)
: "1");
@@ -306,13 +294,8 @@ static int notrace s390_validate_registers(union mci mci, int umode)
:
: "a" (&S390_lowcore.access_regs_save_area)
: "memory");
- if (!mci.ar) {
- /*
- * Access registers have unknown contents.
- * Terminating task.
- */
+ if (!mci.ar)
kill_task = 1;
- }
/* Validate guarded storage registers */
cr2.val = S390_lowcore.cregs_save_area[2];
if (cr2.gse) {
@@ -451,7 +434,9 @@ int notrace s390_do_machine_check(struct pt_regs *regs)
s390_handle_damage();
}
}
- if (s390_validate_registers(mci, user_mode(regs))) {
+ if (s390_validate_registers(mci)) {
+ if (!user_mode(regs))
+ s390_handle_damage();
/*
* Couldn't restore all register contents for the
* user space process -> mark task for termination.
@@ -480,7 +465,21 @@ int notrace s390_do_machine_check(struct pt_regs *regs)
mcck->stp_queue |= stp_island_check();
mcck_pending = 1;
}
-
+ /*
+ * Reinject storage related machine checks into the guest if they
+ * happen when the guest is running.
+ */
+ if (!test_cpu_flag(CIF_MCCK_GUEST)) {
+ /* Storage error uncorrected */
+ if (mci.se)
+ s390_handle_damage();
+ /* Storage key-error uncorrected */
+ if (mci.ke)
+ s390_handle_damage();
+ /* Storage degradation */
+ if (mci.ds && mci.fa)
+ s390_handle_damage();
+ }
if (mci.cp) {
/* Channel report word pending */
mcck->channel_report = 1;
diff --git a/arch/s390/kernel/perf_pai_crypto.c b/arch/s390/kernel/perf_pai_crypto.c
index 6826e2a69a21..985e243a2ed8 100644
--- a/arch/s390/kernel/perf_pai_crypto.c
+++ b/arch/s390/kernel/perf_pai_crypto.c
@@ -35,9 +35,9 @@ struct pai_userdata {
struct paicrypt_map {
unsigned long *page; /* Page for CPU to store counters */
struct pai_userdata *save; /* Page to store no-zero counters */
- unsigned int users; /* # of PAI crypto users */
- unsigned int sampler; /* # of PAI crypto samplers */
- unsigned int counter; /* # of PAI crypto counters */
+ unsigned int active_events; /* # of PAI crypto users */
+ unsigned int refcnt; /* Reference count mapped buffers */
+ enum paievt_mode mode; /* Type of event */
struct perf_event *event; /* Perf event for sampling */
};
@@ -56,15 +56,11 @@ static void paicrypt_event_destroy(struct perf_event *event)
cpump->event = NULL;
static_branch_dec(&pai_key);
mutex_lock(&pai_reserve_mutex);
- if (event->attr.sample_period)
- cpump->sampler -= 1;
- else
- cpump->counter -= 1;
- debug_sprintf_event(cfm_dbg, 5, "%s event %#llx cpu %d"
- " sampler %d counter %d\n", __func__,
- event->attr.config, event->cpu, cpump->sampler,
- cpump->counter);
- if (!cpump->counter && !cpump->sampler) {
+ debug_sprintf_event(cfm_dbg, 5, "%s event %#llx cpu %d users %d"
+ " mode %d refcnt %d\n", __func__,
+ event->attr.config, event->cpu,
+ cpump->active_events, cpump->mode, cpump->refcnt);
+ if (!--cpump->refcnt) {
debug_sprintf_event(cfm_dbg, 4, "%s page %#lx save %p\n",
__func__, (unsigned long)cpump->page,
cpump->save);
@@ -72,6 +68,7 @@ static void paicrypt_event_destroy(struct perf_event *event)
cpump->page = NULL;
kvfree(cpump->save);
cpump->save = NULL;
+ cpump->mode = PAI_MODE_NONE;
}
mutex_unlock(&pai_reserve_mutex);
}
@@ -136,17 +133,14 @@ static u64 paicrypt_getall(struct perf_event *event)
*/
static int paicrypt_busy(struct perf_event_attr *a, struct paicrypt_map *cpump)
{
- unsigned int *use_ptr;
int rc = 0;
mutex_lock(&pai_reserve_mutex);
if (a->sample_period) { /* Sampling requested */
- use_ptr = &cpump->sampler;
- if (cpump->counter || cpump->sampler)
+ if (cpump->mode != PAI_MODE_NONE)
rc = -EBUSY; /* ... sampling/counting active */
} else { /* Counting requested */
- use_ptr = &cpump->counter;
- if (cpump->sampler)
+ if (cpump->mode == PAI_MODE_SAMPLING)
rc = -EBUSY; /* ... and sampling active */
}
if (rc)
@@ -172,12 +166,16 @@ static int paicrypt_busy(struct perf_event_attr *a, struct paicrypt_map *cpump)
rc = 0;
unlock:
- /* If rc is non-zero, do not increment counter/sampler. */
- if (!rc)
- *use_ptr += 1;
- debug_sprintf_event(cfm_dbg, 5, "%s sample_period %#llx sampler %d"
- " counter %d page %#lx save %p rc %d\n", __func__,
- a->sample_period, cpump->sampler, cpump->counter,
+ /* If rc is non-zero, do not set mode and reference count */
+ if (!rc) {
+ cpump->refcnt++;
+ cpump->mode = a->sample_period ? PAI_MODE_SAMPLING
+ : PAI_MODE_COUNTING;
+ }
+ debug_sprintf_event(cfm_dbg, 5, "%s sample_period %#llx users %d"
+ " mode %d refcnt %d page %#lx save %p rc %d\n",
+ __func__, a->sample_period, cpump->active_events,
+ cpump->mode, cpump->refcnt,
(unsigned long)cpump->page, cpump->save, rc);
mutex_unlock(&pai_reserve_mutex);
return rc;
@@ -262,7 +260,7 @@ static int paicrypt_add(struct perf_event *event, int flags)
struct paicrypt_map *cpump = this_cpu_ptr(&paicrypt_map);
unsigned long ccd;
- if (cpump->users++ == 0) {
+ if (++cpump->active_events == 1) {
ccd = virt_to_phys(cpump->page) | PAI_CRYPTO_KERNEL_OFFSET;
WRITE_ONCE(S390_lowcore.ccd, ccd);
__ctl_set_bit(0, 50);
@@ -293,7 +291,7 @@ static void paicrypt_del(struct perf_event *event, int flags)
if (!event->attr.sample_period)
/* Only counting needs to read counter */
paicrypt_stop(event, PERF_EF_UPDATE);
- if (cpump->users-- == 1) {
+ if (--cpump->active_events == 0) {
__ctl_clear_bit(0, 50);
WRITE_ONCE(S390_lowcore.ccd, 0);
}
@@ -379,7 +377,7 @@ static int paicrypt_push_sample(void)
/* Called on schedule-in and schedule-out. No access to event structure,
* but for sampling only event CRYPTO_ALL is allowed.
*/
-static void paicrypt_sched_task(struct perf_event_context *ctx, bool sched_in)
+static void paicrypt_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in)
{
/* We started with a clean page on event installation. So read out
* results on schedule_out and if page was dirty, clear values.
diff --git a/arch/s390/kernel/perf_pai_ext.c b/arch/s390/kernel/perf_pai_ext.c
index 74b53c531e0c..1138f57baae3 100644
--- a/arch/s390/kernel/perf_pai_ext.c
+++ b/arch/s390/kernel/perf_pai_ext.c
@@ -28,12 +28,6 @@
static debug_info_t *paiext_dbg;
static unsigned int paiext_cnt; /* Extracted with QPACI instruction */
-enum paiext_mode {
- PAI_MODE_NONE,
- PAI_MODE_SAMPLING,
- PAI_MODE_COUNTER,
-};
-
struct pai_userdata {
u16 num;
u64 value;
@@ -54,7 +48,7 @@ struct paiext_cb { /* PAI extension 1 control block */
struct paiext_map {
unsigned long *area; /* Area for CPU to store counters */
struct pai_userdata *save; /* Area to store non-zero counters */
- enum paiext_mode mode; /* Type of event */
+ enum paievt_mode mode; /* Type of event */
unsigned int active_events; /* # of PAI Extension users */
unsigned int refcnt;
struct perf_event *event; /* Perf event for sampling */
@@ -192,14 +186,14 @@ static int paiext_alloc(struct perf_event_attr *a, struct perf_event *event)
goto unlock;
}
cpump->mode = a->sample_period ? PAI_MODE_SAMPLING
- : PAI_MODE_COUNTER;
+ : PAI_MODE_COUNTING;
} else {
/* Multiple invocation, check whats active.
* Supported are multiple counter events or only one sampling
* event concurrently at any one time.
*/
if (cpump->mode == PAI_MODE_SAMPLING ||
- (cpump->mode == PAI_MODE_COUNTER && a->sample_period)) {
+ (cpump->mode == PAI_MODE_COUNTING && a->sample_period)) {
rc = -EBUSY;
goto unlock;
}
@@ -472,7 +466,7 @@ static int paiext_push_sample(void)
/* Called on schedule-in and schedule-out. No access to event structure,
* but for sampling only event NNPA_ALL is allowed.
*/
-static void paiext_sched_task(struct perf_event_context *ctx, bool sched_in)
+static void paiext_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in)
{
/* We started with a clean page on event installation. So read out
* results on schedule_out and if page was dirty, clear values.
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 42af4b3aa02b..3f5d2db0b854 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -224,7 +224,7 @@ unsigned long __get_wchan(struct task_struct *p)
unsigned long arch_align_stack(unsigned long sp)
{
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
- sp -= prandom_u32_max(PAGE_SIZE);
+ sp -= get_random_u32_below(PAGE_SIZE);
return sp & ~0xf;
}
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index ab19ddb09d65..2094f575c532 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -437,7 +437,7 @@ static void __init setup_lowcore_dat_off(void)
lc->svc_new_psw.addr = (unsigned long) system_call;
lc->program_new_psw.mask = int_psw_mask | PSW_MASK_MCHECK;
lc->program_new_psw.addr = (unsigned long) pgm_check_handler;
- lc->mcck_new_psw.mask = PSW_KERNEL_BITS;
+ lc->mcck_new_psw.mask = int_psw_mask;
lc->mcck_new_psw.addr = (unsigned long) mcck_int_handler;
lc->io_new_psw.mask = int_psw_mask | PSW_MASK_MCHECK;
lc->io_new_psw.addr = (unsigned long) io_int_handler;
@@ -512,6 +512,7 @@ static void __init setup_lowcore_dat_on(void)
S390_lowcore.external_new_psw.mask |= PSW_MASK_DAT;
S390_lowcore.svc_new_psw.mask |= PSW_MASK_DAT;
S390_lowcore.program_new_psw.mask |= PSW_MASK_DAT;
+ S390_lowcore.mcck_new_psw.mask |= PSW_MASK_DAT;
S390_lowcore.io_new_psw.mask |= PSW_MASK_DAT;
__ctl_set_bit(0, 28);
__ctl_store(S390_lowcore.cregs_save_area, 0, 15);
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c
index 3105ca5bd470..ff7bf4432229 100644
--- a/arch/s390/kernel/vdso.c
+++ b/arch/s390/kernel/vdso.c
@@ -44,21 +44,6 @@ struct vdso_data *arch_get_vdso_data(void *vvar_page)
return (struct vdso_data *)(vvar_page);
}
-static struct page *find_timens_vvar_page(struct vm_area_struct *vma)
-{
- if (likely(vma->vm_mm == current->mm))
- return current->nsproxy->time_ns->vvar_page;
- /*
- * VM_PFNMAP | VM_IO protect .fault() handler from being called
- * through interfaces like /proc/$pid/mem or
- * process_vm_{readv,writev}() as long as there's no .access()
- * in special_mapping_vmops().
- * For more details check_vma_flags() and __access_remote_vm()
- */
- WARN(1, "vvar_page accessed remotely");
- return NULL;
-}
-
/*
* The VVAR page layout depends on whether a task belongs to the root or
* non-root time namespace. Whenever a task changes its namespace, the VVAR
@@ -84,11 +69,6 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
mmap_read_unlock(mm);
return 0;
}
-#else
-static inline struct page *find_timens_vvar_page(struct vm_area_struct *vma)
-{
- return NULL;
-}
#endif
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
@@ -227,7 +207,7 @@ static unsigned long vdso_addr(unsigned long start, unsigned long len)
end -= len;
if (end > start) {
- offset = prandom_u32_max(((end - start) >> PAGE_SHIFT) + 1);
+ offset = get_random_u32_below(((end - start) >> PAGE_SHIFT) + 1);
addr = start + (offset << PAGE_SHIFT);
} else {
addr = start;
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 97d66a3e60fb..1a25d456d865 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -31,6 +31,7 @@
#include <linux/cma.h>
#include <linux/gfp.h>
#include <linux/dma-direct.h>
+#include <linux/percpu.h>
#include <asm/processor.h>
#include <linux/uaccess.h>
#include <asm/pgalloc.h>
@@ -207,9 +208,6 @@ void free_initmem(void)
__set_memory((unsigned long)_sinittext,
(unsigned long)(_einittext - _sinittext) >> PAGE_SHIFT,
SET_MEMORY_RW | SET_MEMORY_NX);
- free_reserved_area(sclp_early_sccb,
- sclp_early_sccb + EXT_SCCB_READ_SCP,
- POISON_FREE_INITMEM, "unused early sccb");
free_initmem_default(POISON_FREE_INITMEM);
}
@@ -222,6 +220,41 @@ unsigned long memory_block_size_bytes(void)
return max_t(unsigned long, MIN_MEMORY_BLOCK_SIZE, sclp.rzm);
}
+unsigned long __per_cpu_offset[NR_CPUS] __read_mostly;
+EXPORT_SYMBOL(__per_cpu_offset);
+
+static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
+{
+ return LOCAL_DISTANCE;
+}
+
+static int __init pcpu_cpu_to_node(int cpu)
+{
+ return 0;
+}
+
+void __init setup_per_cpu_areas(void)
+{
+ unsigned long delta;
+ unsigned int cpu;
+ int rc;
+
+ /*
+ * Always reserve area for module percpu variables. That's
+ * what the legacy allocator did.
+ */
+ rc = pcpu_embed_first_chunk(PERCPU_MODULE_RESERVE,
+ PERCPU_DYNAMIC_RESERVE, PAGE_SIZE,
+ pcpu_cpu_distance,
+ pcpu_cpu_to_node);
+ if (rc < 0)
+ panic("Failed to initialize percpu areas.");
+
+ delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;
+ for_each_possible_cpu(cpu)
+ __per_cpu_offset[cpu] = delta + pcpu_unit_offsets[cpu];
+}
+
#ifdef CONFIG_MEMORY_HOTPLUG
#ifdef CONFIG_CMA
diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c
index 1571cdcb0c50..4824d1cd33d8 100644
--- a/arch/s390/mm/maccess.c
+++ b/arch/s390/mm/maccess.c
@@ -128,7 +128,7 @@ int memcpy_real(void *dest, unsigned long src, size_t count)
kvec.iov_base = dest;
kvec.iov_len = count;
- iov_iter_kvec(&iter, WRITE, &kvec, 1, count);
+ iov_iter_kvec(&iter, ITER_DEST, &kvec, 1, count);
if (memcpy_real_iter(&iter, src, count) < count)
return -EFAULT;
return 0;
diff --git a/arch/s390/mm/page-states.c b/arch/s390/mm/page-states.c
index d5ea09d78938..1e2ea706aa22 100644
--- a/arch/s390/mm/page-states.c
+++ b/arch/s390/mm/page-states.c
@@ -58,17 +58,6 @@ void __init cmma_init(void)
cmma_flag = 2;
}
-static inline unsigned char get_page_state(struct page *page)
-{
- unsigned char state;
-
- asm volatile(" .insn rrf,0xb9ab0000,%0,%1,%2,0"
- : "=&d" (state)
- : "a" (page_to_phys(page)),
- "i" (ESSA_GET_STATE));
- return state & 0x3f;
-}
-
static inline void set_page_unused(struct page *page, int order)
{
int i, rc;
diff --git a/arch/s390/pci/pci_irq.c b/arch/s390/pci/pci_irq.c
index a2b42a63a53b..4ab0cf829999 100644
--- a/arch/s390/pci/pci_irq.c
+++ b/arch/s390/pci/pci_irq.c
@@ -132,7 +132,7 @@ static int zpci_clear_irq(struct zpci_dev *zdev)
static int zpci_set_irq_affinity(struct irq_data *data, const struct cpumask *dest,
bool force)
{
- struct msi_desc *entry = irq_get_msi_desc(data->irq);
+ struct msi_desc *entry = irq_data_get_msi_desc(data);
struct msi_msg msg = entry->msg;
int cpu_addr = smp_cpu_get_cpu_address(cpumask_first(dest));
diff --git a/arch/sh/configs/rsk7201_defconfig b/arch/sh/configs/rsk7201_defconfig
index 619c18699459..376e95fa77bc 100644
--- a/arch/sh/configs/rsk7201_defconfig
+++ b/arch/sh/configs/rsk7201_defconfig
@@ -10,7 +10,8 @@ CONFIG_USER_NS=y
CONFIG_PID_NS=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_AIO is not set
-CONFIG_SLOB=y
+CONFIG_SLUB=y
+CONFIG_SLUB_TINY=y
CONFIG_PROFILING=y
CONFIG_MODULES=y
# CONFIG_BLK_DEV_BSG is not set
diff --git a/arch/sh/configs/rsk7203_defconfig b/arch/sh/configs/rsk7203_defconfig
index d00fafc021e1..1d5fd67a3949 100644
--- a/arch/sh/configs/rsk7203_defconfig
+++ b/arch/sh/configs/rsk7203_defconfig
@@ -11,7 +11,8 @@ CONFIG_USER_NS=y
CONFIG_PID_NS=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_KALLSYMS_ALL=y
-CONFIG_SLOB=y
+CONFIG_SLUB=y
+CONFIG_SLUB_TINY=y
CONFIG_PROFILING=y
CONFIG_MODULES=y
# CONFIG_BLK_DEV_BSG is not set
diff --git a/arch/sh/configs/se7206_defconfig b/arch/sh/configs/se7206_defconfig
index 122216123e63..78e0e7be57ee 100644
--- a/arch/sh/configs/se7206_defconfig
+++ b/arch/sh/configs/se7206_defconfig
@@ -21,7 +21,8 @@ CONFIG_BLK_DEV_INITRD=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_ELF_CORE is not set
# CONFIG_COMPAT_BRK is not set
-CONFIG_SLOB=y
+CONFIG_SLUB=y
+CONFIG_SLUB_TINY=y
CONFIG_PROFILING=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
diff --git a/arch/sh/configs/shmin_defconfig b/arch/sh/configs/shmin_defconfig
index c0b6f40d01cc..e078b193a78a 100644
--- a/arch/sh/configs/shmin_defconfig
+++ b/arch/sh/configs/shmin_defconfig
@@ -9,7 +9,8 @@ CONFIG_LOG_BUF_SHIFT=14
# CONFIG_FUTEX is not set
# CONFIG_EPOLL is not set
# CONFIG_SHMEM is not set
-CONFIG_SLOB=y
+CONFIG_SLUB=y
+CONFIG_SLUB_TINY=y
# CONFIG_BLK_DEV_BSG is not set
CONFIG_CPU_SUBTYPE_SH7706=y
CONFIG_MEMORY_START=0x0c000000
diff --git a/arch/sh/configs/shx3_defconfig b/arch/sh/configs/shx3_defconfig
index 32ec6eb1eabc..aa353dff7f19 100644
--- a/arch/sh/configs/shx3_defconfig
+++ b/arch/sh/configs/shx3_defconfig
@@ -20,7 +20,8 @@ CONFIG_USER_NS=y
CONFIG_PID_NS=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_KALLSYMS_ALL=y
-CONFIG_SLOB=y
+CONFIG_SLUB=y
+CONFIG_SLUB_TINY=y
CONFIG_PROFILING=y
CONFIG_KPROBES=y
CONFIG_MODULES=y
diff --git a/arch/sh/include/asm/stackprotector.h b/arch/sh/include/asm/stackprotector.h
index 35616841d0a1..665dafac376f 100644
--- a/arch/sh/include/asm/stackprotector.h
+++ b/arch/sh/include/asm/stackprotector.h
@@ -2,9 +2,6 @@
#ifndef __ASM_SH_STACKPROTECTOR_H
#define __ASM_SH_STACKPROTECTOR_H
-#include <linux/random.h>
-#include <linux/version.h>
-
extern unsigned long __stack_chk_guard;
/*
@@ -15,12 +12,7 @@ extern unsigned long __stack_chk_guard;
*/
static __always_inline void boot_init_stack_canary(void)
{
- unsigned long canary;
-
- /* Try to get a semi random initial value. */
- get_random_bytes(&canary, sizeof(canary));
- canary ^= LINUX_VERSION_CODE;
- canary &= CANARY_MASK;
+ unsigned long canary = get_random_canary();
current->stack_canary = canary;
__stack_chk_guard = current->stack_canary;
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c
index d417988d9770..36f50ad81e83 100644
--- a/arch/sh/kernel/ptrace_32.c
+++ b/arch/sh/kernel/ptrace_32.c
@@ -157,8 +157,8 @@ static int genregs_set(struct task_struct *target,
offsetof(struct pt_regs, pc),
sizeof(struct pt_regs));
if (!ret)
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- sizeof(struct pt_regs), -1);
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ sizeof(struct pt_regs), -1);
return ret;
}
@@ -229,8 +229,8 @@ static int dspregs_set(struct task_struct *target,
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, regs,
0, sizeof(struct pt_dspregs));
if (!ret)
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- sizeof(struct pt_dspregs), -1);
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ sizeof(struct pt_dspregs), -1);
return ret;
}
diff --git a/arch/sparc/kernel/ptrace_32.c b/arch/sparc/kernel/ptrace_32.c
index e7db48acb838..c273ccebea46 100644
--- a/arch/sparc/kernel/ptrace_32.c
+++ b/arch/sparc/kernel/ptrace_32.c
@@ -158,8 +158,9 @@ static int genregs32_set(struct task_struct *target,
35 * sizeof(u32), 36 * sizeof(u32));
if (ret || !count)
return ret;
- return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- 36 * sizeof(u32), 38 * sizeof(u32));
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf, 36 * sizeof(u32),
+ 38 * sizeof(u32));
+ return 0;
}
static int fpregs32_get(struct task_struct *target,
@@ -203,8 +204,8 @@ static int fpregs32_set(struct task_struct *target,
33 * sizeof(u32),
34 * sizeof(u32));
if (!ret)
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- 34 * sizeof(u32), -1);
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ 34 * sizeof(u32), -1);
return ret;
}
diff --git a/arch/sparc/kernel/ptrace_64.c b/arch/sparc/kernel/ptrace_64.c
index 86a7eb5c27ba..4deba5b6eddb 100644
--- a/arch/sparc/kernel/ptrace_64.c
+++ b/arch/sparc/kernel/ptrace_64.c
@@ -332,8 +332,8 @@ static int genregs64_set(struct task_struct *target,
}
if (!ret)
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- 36 * sizeof(u64), -1);
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ 36 * sizeof(u64), -1);
return ret;
}
@@ -406,8 +406,8 @@ static int fpregs64_set(struct task_struct *target,
task_thread_info(target)->fpsaved[0] = fprs;
if (!ret)
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- 35 * sizeof(u64), -1);
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ 35 * sizeof(u64), -1);
return ret;
}
@@ -473,10 +473,8 @@ static int setregs64_set(struct task_struct *target,
15 * sizeof(u64));
if (ret)
return ret;
- ret =user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- 15 * sizeof(u64), 16 * sizeof(u64));
- if (ret)
- return ret;
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ 15 * sizeof(u64), 16 * sizeof(u64));
/* TSTATE */
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
&tstate,
@@ -670,8 +668,9 @@ finish:
pos *= sizeof(reg);
count *= sizeof(reg);
- return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- 38 * sizeof(reg), -1);
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ 38 * sizeof(reg), -1);
+ return 0;
}
static int fpregs32_get(struct task_struct *target,
@@ -737,8 +736,8 @@ static int fpregs32_set(struct task_struct *target,
task_thread_info(target)->fpsaved[0] = fprs;
if (!ret)
- ret = user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
- 34 * sizeof(u32), -1);
+ user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
+ 34 * sizeof(u32), -1);
return ret;
}
diff --git a/arch/sparc/vdso/vma.c b/arch/sparc/vdso/vma.c
index ae9a86cb6f3d..136c78f28f8b 100644
--- a/arch/sparc/vdso/vma.c
+++ b/arch/sparc/vdso/vma.c
@@ -354,7 +354,7 @@ static unsigned long vdso_addr(unsigned long start, unsigned int len)
unsigned int offset;
/* This loses some more bits than a modulo, but is cheaper */
- offset = prandom_u32_max(PTRS_PER_PTE);
+ offset = get_random_u32_below(PTRS_PER_PTE);
return start + (offset << PAGE_SHIFT);
}
diff --git a/arch/um/drivers/Kconfig b/arch/um/drivers/Kconfig
index 5903e2b598aa..a4f0a19fbe14 100644
--- a/arch/um/drivers/Kconfig
+++ b/arch/um/drivers/Kconfig
@@ -381,7 +381,6 @@ config UML_PCI_OVER_VIRTIO
select UML_IOMEM_EMULATION
select UML_DMA_EMULATION
select PCI_MSI
- select PCI_MSI_IRQ_DOMAIN
select PCI_LOCKLESS_CONFIG
config UML_PCI_OVER_VIRTIO_DEVICE_ID
diff --git a/arch/um/include/asm/pci.h b/arch/um/include/asm/pci.h
index 34fe4921b5fa..238d2e7faff8 100644
--- a/arch/um/include/asm/pci.h
+++ b/arch/um/include/asm/pci.h
@@ -7,7 +7,7 @@
/* Generic PCI */
#include <asm-generic/pci.h>
-#ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
+#ifdef CONFIG_PCI_MSI
/*
* This is a bit of an annoying hack, and it assumes we only have
* the virt-pci (if anything). Which is true, but still.
diff --git a/arch/um/kernel/kmsg_dump.c b/arch/um/kernel/kmsg_dump.c
index 0224fcb36e22..427dd5a61a38 100644
--- a/arch/um/kernel/kmsg_dump.c
+++ b/arch/um/kernel/kmsg_dump.c
@@ -16,20 +16,26 @@ static void kmsg_dumper_stdout(struct kmsg_dumper *dumper,
struct console *con;
unsigned long flags;
size_t len = 0;
+ int cookie;
- /* only dump kmsg when no console is available */
- if (!console_trylock())
- return;
+ /*
+ * If no consoles are available to output crash information, dump
+ * the kmsg buffer to stdout.
+ */
- for_each_console(con) {
- if(strcmp(con->name, "tty") == 0 &&
- (con->flags & (CON_ENABLED | CON_CONSDEV)) != 0) {
+ cookie = console_srcu_read_lock();
+ for_each_console_srcu(con) {
+ /*
+ * The ttynull console and disabled consoles are ignored
+ * since they cannot output. All other consoles are
+ * expected to output the crash information.
+ */
+ if (strcmp(con->name, "ttynull") != 0 &&
+ (console_srcu_read_flags(con) & CON_ENABLED)) {
break;
}
}
-
- console_unlock();
-
+ console_srcu_read_unlock(cookie);
if (con)
return;
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 010bc422a09d..47830ade35ed 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -33,6 +33,7 @@
#include <skas.h>
#include <registers.h>
#include <linux/time-internal.h>
+#include <linux/elfcore.h>
/*
* This is a per-cpu array. A processor only modifies its entry and it only
@@ -356,7 +357,7 @@ int singlestepping(void * t)
unsigned long arch_align_stack(unsigned long sp)
{
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
- sp -= prandom_u32_max(8192);
+ sp -= get_random_u32_below(8192);
return sp & ~0xf;
}
#endif
@@ -393,7 +394,7 @@ unsigned long __get_wchan(struct task_struct *p)
return 0;
}
-int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
+int elf_core_copy_task_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
{
int cpu = current_thread_info()->cpu;
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 67745ceab0db..9f8c03b347f9 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -69,6 +69,7 @@ config X86
select ARCH_ENABLE_THP_MIGRATION if X86_64 && TRANSPARENT_HUGEPAGE
select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI
select ARCH_HAS_CACHE_LINE_SIZE
+ select ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION
select ARCH_HAS_CURRENT_STACK_POINTER
select ARCH_HAS_DEBUG_VIRTUAL
select ARCH_HAS_DEBUG_VM_PGTABLE if !X86_PAE
@@ -81,6 +82,7 @@ config X86
select ARCH_HAS_KCOV if X86_64
select ARCH_HAS_MEM_ENCRYPT
select ARCH_HAS_MEMBARRIER_SYNC_CORE
+ select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
select ARCH_HAS_PMEM_API if X86_64
select ARCH_HAS_PTE_DEVMAP if X86_64
@@ -462,8 +464,8 @@ config X86_X2APIC
Some Intel systems circa 2022 and later are locked into x2APIC mode
and can not fall back to the legacy APIC modes if SGX or TDX are
- enabled in the BIOS. They will be unable to boot without enabling
- this option.
+ enabled in the BIOS. They will boot with very reduced functionality
+ without enabling this option.
If you don't know what to do here, say N.
@@ -1109,7 +1111,6 @@ config X86_LOCAL_APIC
def_bool y
depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC || PCI_MSI
select IRQ_DOMAIN_HIERARCHY
- select PCI_MSI_IRQ_DOMAIN if PCI_MSI
config X86_IO_APIC
def_bool y
@@ -1980,6 +1981,23 @@ config EFI_STUB
See Documentation/admin-guide/efi-stub.rst for more information.
+config EFI_HANDOVER_PROTOCOL
+ bool "EFI handover protocol (DEPRECATED)"
+ depends on EFI_STUB
+ default y
+ help
+ Select this in order to include support for the deprecated EFI
+ handover protocol, which defines alternative entry points into the
+ EFI stub. This is a practice that has no basis in the UEFI
+ specification, and requires a priori knowledge on the part of the
+ bootloader about Linux/x86 specific ways of passing the command line
+ and initrd, and where in memory those assets may be loaded.
+
+ If in doubt, say Y. Even though the corresponding support is not
+ present in upstream GRUB or other bootloaders, most distros build
+ GRUB with numerous downstream patches applied, and may rely on the
+ handover protocol as as result.
+
config EFI_MIXED
bool "EFI mixed-mode support"
depends on EFI_STUB && X86_64
@@ -1994,6 +2012,37 @@ config EFI_MIXED
If unsure, say N.
+config EFI_FAKE_MEMMAP
+ bool "Enable EFI fake memory map"
+ depends on EFI
+ help
+ Saying Y here will enable "efi_fake_mem" boot option. By specifying
+ this parameter, you can add arbitrary attribute to specific memory
+ range by updating original (firmware provided) EFI memmap. This is
+ useful for debugging of EFI memmap related feature, e.g., Address
+ Range Mirroring feature.
+
+config EFI_MAX_FAKE_MEM
+ int "maximum allowable number of ranges in efi_fake_mem boot option"
+ depends on EFI_FAKE_MEMMAP
+ range 1 128
+ default 8
+ help
+ Maximum allowable number of ranges in efi_fake_mem boot option.
+ Ranges can be set up to this value using comma-separated list.
+ The default value is 8.
+
+config EFI_RUNTIME_MAP
+ bool "Export EFI runtime maps to sysfs" if EXPERT
+ depends on EFI
+ default KEXEC_CORE
+ help
+ Export EFI runtime memory regions to /sys/firmware/efi/runtime-map.
+ That memory map is required by the 2nd kernel to set up EFI virtual
+ mappings after kexec, but can also be used for debugging purposes.
+
+ See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map.
+
source "kernel/Kconfig.hz"
config KEXEC
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 3a261abb6d15..3dc5db651dd0 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -100,7 +100,7 @@ vmlinux-objs-$(CONFIG_RANDOMIZE_BASE) += $(obj)/kaslr.o
ifdef CONFIG_X86_64
vmlinux-objs-y += $(obj)/ident_map_64.o
vmlinux-objs-y += $(obj)/idt_64.o $(obj)/idt_handlers_64.o
- vmlinux-objs-y += $(obj)/mem_encrypt.o
+ vmlinux-objs-$(CONFIG_AMD_MEM_ENCRYPT) += $(obj)/mem_encrypt.o
vmlinux-objs-y += $(obj)/pgtable_64.o
vmlinux-objs-$(CONFIG_AMD_MEM_ENCRYPT) += $(obj)/sev.o
endif
@@ -108,11 +108,11 @@ endif
vmlinux-objs-$(CONFIG_ACPI) += $(obj)/acpi.o
vmlinux-objs-$(CONFIG_INTEL_TDX_GUEST) += $(obj)/tdx.o $(obj)/tdcall.o
-vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o
vmlinux-objs-$(CONFIG_EFI) += $(obj)/efi.o
-efi-obj-$(CONFIG_EFI_STUB) = $(objtree)/drivers/firmware/efi/libstub/lib.a
+vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_mixed.o
+vmlinux-objs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
-$(obj)/vmlinux: $(vmlinux-objs-y) $(efi-obj-y) FORCE
+$(obj)/vmlinux: $(vmlinux-objs-y) FORCE
$(call if_changed,ld)
OBJCOPYFLAGS_vmlinux.bin := -R .comment -S
diff --git a/arch/x86/boot/compressed/efi_mixed.S b/arch/x86/boot/compressed/efi_mixed.S
new file mode 100644
index 000000000000..4ca70bf93dc0
--- /dev/null
+++ b/arch/x86/boot/compressed/efi_mixed.S
@@ -0,0 +1,345 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2014, 2015 Intel Corporation; author Matt Fleming
+ *
+ * Early support for invoking 32-bit EFI services from a 64-bit kernel.
+ *
+ * Because this thunking occurs before ExitBootServices() we have to
+ * restore the firmware's 32-bit GDT and IDT before we make EFI service
+ * calls.
+ *
+ * On the plus side, we don't have to worry about mangling 64-bit
+ * addresses into 32-bits because we're executing with an identity
+ * mapped pagetable and haven't transitioned to 64-bit virtual addresses
+ * yet.
+ */
+
+#include <linux/linkage.h>
+#include <asm/msr.h>
+#include <asm/page_types.h>
+#include <asm/processor-flags.h>
+#include <asm/segment.h>
+
+ .code64
+ .text
+/*
+ * When booting in 64-bit mode on 32-bit EFI firmware, startup_64_mixed_mode()
+ * is the first thing that runs after switching to long mode. Depending on
+ * whether the EFI handover protocol or the compat entry point was used to
+ * enter the kernel, it will either branch to the 64-bit EFI handover
+ * entrypoint at offset 0x390 in the image, or to the 64-bit EFI PE/COFF
+ * entrypoint efi_pe_entry(). In the former case, the bootloader must provide a
+ * struct bootparams pointer as the third argument, so the presence of such a
+ * pointer is used to disambiguate.
+ *
+ * +--------------+
+ * +------------------+ +------------+ +------>| efi_pe_entry |
+ * | efi32_pe_entry |---->| | | +-----------+--+
+ * +------------------+ | | +------+----------------+ |
+ * | startup_32 |---->| startup_64_mixed_mode | |
+ * +------------------+ | | +------+----------------+ V
+ * | efi32_stub_entry |---->| | | +------------------+
+ * +------------------+ +------------+ +---->| efi64_stub_entry |
+ * +-------------+----+
+ * +------------+ +----------+ |
+ * | startup_64 |<----| efi_main |<--------------+
+ * +------------+ +----------+
+ */
+SYM_FUNC_START(startup_64_mixed_mode)
+ lea efi32_boot_args(%rip), %rdx
+ mov 0(%rdx), %edi
+ mov 4(%rdx), %esi
+ mov 8(%rdx), %edx // saved bootparams pointer
+ test %edx, %edx
+ jnz efi64_stub_entry
+ /*
+ * efi_pe_entry uses MS calling convention, which requires 32 bytes of
+ * shadow space on the stack even if all arguments are passed in
+ * registers. We also need an additional 8 bytes for the space that
+ * would be occupied by the return address, and this also results in
+ * the correct stack alignment for entry.
+ */
+ sub $40, %rsp
+ mov %rdi, %rcx // MS calling convention
+ mov %rsi, %rdx
+ jmp efi_pe_entry
+SYM_FUNC_END(startup_64_mixed_mode)
+
+SYM_FUNC_START(__efi64_thunk)
+ push %rbp
+ push %rbx
+
+ movl %ds, %eax
+ push %rax
+ movl %es, %eax
+ push %rax
+ movl %ss, %eax
+ push %rax
+
+ /* Copy args passed on stack */
+ movq 0x30(%rsp), %rbp
+ movq 0x38(%rsp), %rbx
+ movq 0x40(%rsp), %rax
+
+ /*
+ * Convert x86-64 ABI params to i386 ABI
+ */
+ subq $64, %rsp
+ movl %esi, 0x0(%rsp)
+ movl %edx, 0x4(%rsp)
+ movl %ecx, 0x8(%rsp)
+ movl %r8d, 0xc(%rsp)
+ movl %r9d, 0x10(%rsp)
+ movl %ebp, 0x14(%rsp)
+ movl %ebx, 0x18(%rsp)
+ movl %eax, 0x1c(%rsp)
+
+ leaq 0x20(%rsp), %rbx
+ sgdt (%rbx)
+ sidt 16(%rbx)
+
+ leaq 1f(%rip), %rbp
+
+ /*
+ * Switch to IDT and GDT with 32-bit segments. These are the firmware
+ * GDT and IDT that were installed when the kernel started executing.
+ * The pointers were saved by the efi32_entry() routine below.
+ *
+ * Pass the saved DS selector to the 32-bit code, and use far return to
+ * restore the saved CS selector.
+ */
+ lidt efi32_boot_idt(%rip)
+ lgdt efi32_boot_gdt(%rip)
+
+ movzwl efi32_boot_ds(%rip), %edx
+ movzwq efi32_boot_cs(%rip), %rax
+ pushq %rax
+ leaq efi_enter32(%rip), %rax
+ pushq %rax
+ lretq
+
+1: addq $64, %rsp
+ movq %rdi, %rax
+
+ pop %rbx
+ movl %ebx, %ss
+ pop %rbx
+ movl %ebx, %es
+ pop %rbx
+ movl %ebx, %ds
+ /* Clear out 32-bit selector from FS and GS */
+ xorl %ebx, %ebx
+ movl %ebx, %fs
+ movl %ebx, %gs
+
+ pop %rbx
+ pop %rbp
+ RET
+SYM_FUNC_END(__efi64_thunk)
+
+ .code32
+/*
+ * EFI service pointer must be in %edi.
+ *
+ * The stack should represent the 32-bit calling convention.
+ */
+SYM_FUNC_START_LOCAL(efi_enter32)
+ /* Load firmware selector into data and stack segment registers */
+ movl %edx, %ds
+ movl %edx, %es
+ movl %edx, %fs
+ movl %edx, %gs
+ movl %edx, %ss
+
+ /* Reload pgtables */
+ movl %cr3, %eax
+ movl %eax, %cr3
+
+ /* Disable paging */
+ movl %cr0, %eax
+ btrl $X86_CR0_PG_BIT, %eax
+ movl %eax, %cr0
+
+ /* Disable long mode via EFER */
+ movl $MSR_EFER, %ecx
+ rdmsr
+ btrl $_EFER_LME, %eax
+ wrmsr
+
+ call *%edi
+
+ /* We must preserve return value */
+ movl %eax, %edi
+
+ /*
+ * Some firmware will return with interrupts enabled. Be sure to
+ * disable them before we switch GDTs and IDTs.
+ */
+ cli
+
+ lidtl 16(%ebx)
+ lgdtl (%ebx)
+
+ movl %cr4, %eax
+ btsl $(X86_CR4_PAE_BIT), %eax
+ movl %eax, %cr4
+
+ movl %cr3, %eax
+ movl %eax, %cr3
+
+ movl $MSR_EFER, %ecx
+ rdmsr
+ btsl $_EFER_LME, %eax
+ wrmsr
+
+ xorl %eax, %eax
+ lldt %ax
+
+ pushl $__KERNEL_CS
+ pushl %ebp
+
+ /* Enable paging */
+ movl %cr0, %eax
+ btsl $X86_CR0_PG_BIT, %eax
+ movl %eax, %cr0
+ lret
+SYM_FUNC_END(efi_enter32)
+
+/*
+ * This is the common EFI stub entry point for mixed mode.
+ *
+ * Arguments: %ecx image handle
+ * %edx EFI system table pointer
+ * %esi struct bootparams pointer (or NULL when not using
+ * the EFI handover protocol)
+ *
+ * Since this is the point of no return for ordinary execution, no registers
+ * are considered live except for the function parameters. [Note that the EFI
+ * stub may still exit and return to the firmware using the Exit() EFI boot
+ * service.]
+ */
+SYM_FUNC_START(efi32_entry)
+ call 1f
+1: pop %ebx
+
+ /* Save firmware GDTR and code/data selectors */
+ sgdtl (efi32_boot_gdt - 1b)(%ebx)
+ movw %cs, (efi32_boot_cs - 1b)(%ebx)
+ movw %ds, (efi32_boot_ds - 1b)(%ebx)
+
+ /* Store firmware IDT descriptor */
+ sidtl (efi32_boot_idt - 1b)(%ebx)
+
+ /* Store boot arguments */
+ leal (efi32_boot_args - 1b)(%ebx), %ebx
+ movl %ecx, 0(%ebx)
+ movl %edx, 4(%ebx)
+ movl %esi, 8(%ebx)
+ movb $0x0, 12(%ebx) // efi_is64
+
+ /* Disable paging */
+ movl %cr0, %eax
+ btrl $X86_CR0_PG_BIT, %eax
+ movl %eax, %cr0
+
+ jmp startup_32
+SYM_FUNC_END(efi32_entry)
+
+#define ST32_boottime 60 // offsetof(efi_system_table_32_t, boottime)
+#define BS32_handle_protocol 88 // offsetof(efi_boot_services_32_t, handle_protocol)
+#define LI32_image_base 32 // offsetof(efi_loaded_image_32_t, image_base)
+
+/*
+ * efi_status_t efi32_pe_entry(efi_handle_t image_handle,
+ * efi_system_table_32_t *sys_table)
+ */
+SYM_FUNC_START(efi32_pe_entry)
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %eax // dummy push to allocate loaded_image
+
+ pushl %ebx // save callee-save registers
+ pushl %edi
+
+ call verify_cpu // check for long mode support
+ testl %eax, %eax
+ movl $0x80000003, %eax // EFI_UNSUPPORTED
+ jnz 2f
+
+ call 1f
+1: pop %ebx
+
+ /* Get the loaded image protocol pointer from the image handle */
+ leal -4(%ebp), %eax
+ pushl %eax // &loaded_image
+ leal (loaded_image_proto - 1b)(%ebx), %eax
+ pushl %eax // pass the GUID address
+ pushl 8(%ebp) // pass the image handle
+
+ /*
+ * Note the alignment of the stack frame.
+ * sys_table
+ * handle <-- 16-byte aligned on entry by ABI
+ * return address
+ * frame pointer
+ * loaded_image <-- local variable
+ * saved %ebx <-- 16-byte aligned here
+ * saved %edi
+ * &loaded_image
+ * &loaded_image_proto
+ * handle <-- 16-byte aligned for call to handle_protocol
+ */
+
+ movl 12(%ebp), %eax // sys_table
+ movl ST32_boottime(%eax), %eax // sys_table->boottime
+ call *BS32_handle_protocol(%eax) // sys_table->boottime->handle_protocol
+ addl $12, %esp // restore argument space
+ testl %eax, %eax
+ jnz 2f
+
+ movl 8(%ebp), %ecx // image_handle
+ movl 12(%ebp), %edx // sys_table
+ movl -4(%ebp), %esi // loaded_image
+ movl LI32_image_base(%esi), %esi // loaded_image->image_base
+ leal (startup_32 - 1b)(%ebx), %ebp // runtime address of startup_32
+ /*
+ * We need to set the image_offset variable here since startup_32() will
+ * use it before we get to the 64-bit efi_pe_entry() in C code.
+ */
+ subl %esi, %ebp // calculate image_offset
+ movl %ebp, (image_offset - 1b)(%ebx) // save image_offset
+ xorl %esi, %esi
+ jmp efi32_entry // pass %ecx, %edx, %esi
+ // no other registers remain live
+
+2: popl %edi // restore callee-save registers
+ popl %ebx
+ leave
+ RET
+SYM_FUNC_END(efi32_pe_entry)
+
+ .section ".rodata"
+ /* EFI loaded image protocol GUID */
+ .balign 4
+SYM_DATA_START_LOCAL(loaded_image_proto)
+ .long 0x5b1b31a1
+ .word 0x9562, 0x11d2
+ .byte 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b
+SYM_DATA_END(loaded_image_proto)
+
+ .data
+ .balign 8
+SYM_DATA_START_LOCAL(efi32_boot_gdt)
+ .word 0
+ .quad 0
+SYM_DATA_END(efi32_boot_gdt)
+
+SYM_DATA_START_LOCAL(efi32_boot_idt)
+ .word 0
+ .quad 0
+SYM_DATA_END(efi32_boot_idt)
+
+SYM_DATA_LOCAL(efi32_boot_cs, .word 0)
+SYM_DATA_LOCAL(efi32_boot_ds, .word 0)
+SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0, 0)
+SYM_DATA(efi_is64, .byte 1)
diff --git a/arch/x86/boot/compressed/efi_thunk_64.S b/arch/x86/boot/compressed/efi_thunk_64.S
deleted file mode 100644
index 67e7edcdfea8..000000000000
--- a/arch/x86/boot/compressed/efi_thunk_64.S
+++ /dev/null
@@ -1,195 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2014, 2015 Intel Corporation; author Matt Fleming
- *
- * Early support for invoking 32-bit EFI services from a 64-bit kernel.
- *
- * Because this thunking occurs before ExitBootServices() we have to
- * restore the firmware's 32-bit GDT and IDT before we make EFI service
- * calls.
- *
- * On the plus side, we don't have to worry about mangling 64-bit
- * addresses into 32-bits because we're executing with an identity
- * mapped pagetable and haven't transitioned to 64-bit virtual addresses
- * yet.
- */
-
-#include <linux/linkage.h>
-#include <asm/msr.h>
-#include <asm/page_types.h>
-#include <asm/processor-flags.h>
-#include <asm/segment.h>
-
- .code64
- .text
-SYM_FUNC_START(__efi64_thunk)
- push %rbp
- push %rbx
-
- movl %ds, %eax
- push %rax
- movl %es, %eax
- push %rax
- movl %ss, %eax
- push %rax
-
- /* Copy args passed on stack */
- movq 0x30(%rsp), %rbp
- movq 0x38(%rsp), %rbx
- movq 0x40(%rsp), %rax
-
- /*
- * Convert x86-64 ABI params to i386 ABI
- */
- subq $64, %rsp
- movl %esi, 0x0(%rsp)
- movl %edx, 0x4(%rsp)
- movl %ecx, 0x8(%rsp)
- movl %r8d, 0xc(%rsp)
- movl %r9d, 0x10(%rsp)
- movl %ebp, 0x14(%rsp)
- movl %ebx, 0x18(%rsp)
- movl %eax, 0x1c(%rsp)
-
- leaq 0x20(%rsp), %rbx
- sgdt (%rbx)
-
- addq $16, %rbx
- sidt (%rbx)
-
- leaq 1f(%rip), %rbp
-
- /*
- * Switch to IDT and GDT with 32-bit segments. This is the firmware GDT
- * and IDT that was installed when the kernel started executing. The
- * pointers were saved at the EFI stub entry point in head_64.S.
- *
- * Pass the saved DS selector to the 32-bit code, and use far return to
- * restore the saved CS selector.
- */
- leaq efi32_boot_idt(%rip), %rax
- lidt (%rax)
- leaq efi32_boot_gdt(%rip), %rax
- lgdt (%rax)
-
- movzwl efi32_boot_ds(%rip), %edx
- movzwq efi32_boot_cs(%rip), %rax
- pushq %rax
- leaq efi_enter32(%rip), %rax
- pushq %rax
- lretq
-
-1: addq $64, %rsp
- movq %rdi, %rax
-
- pop %rbx
- movl %ebx, %ss
- pop %rbx
- movl %ebx, %es
- pop %rbx
- movl %ebx, %ds
- /* Clear out 32-bit selector from FS and GS */
- xorl %ebx, %ebx
- movl %ebx, %fs
- movl %ebx, %gs
-
- /*
- * Convert 32-bit status code into 64-bit.
- */
- roll $1, %eax
- rorq $1, %rax
-
- pop %rbx
- pop %rbp
- RET
-SYM_FUNC_END(__efi64_thunk)
-
- .code32
-/*
- * EFI service pointer must be in %edi.
- *
- * The stack should represent the 32-bit calling convention.
- */
-SYM_FUNC_START_LOCAL(efi_enter32)
- /* Load firmware selector into data and stack segment registers */
- movl %edx, %ds
- movl %edx, %es
- movl %edx, %fs
- movl %edx, %gs
- movl %edx, %ss
-
- /* Reload pgtables */
- movl %cr3, %eax
- movl %eax, %cr3
-
- /* Disable paging */
- movl %cr0, %eax
- btrl $X86_CR0_PG_BIT, %eax
- movl %eax, %cr0
-
- /* Disable long mode via EFER */
- movl $MSR_EFER, %ecx
- rdmsr
- btrl $_EFER_LME, %eax
- wrmsr
-
- call *%edi
-
- /* We must preserve return value */
- movl %eax, %edi
-
- /*
- * Some firmware will return with interrupts enabled. Be sure to
- * disable them before we switch GDTs and IDTs.
- */
- cli
-
- lidtl (%ebx)
- subl $16, %ebx
-
- lgdtl (%ebx)
-
- movl %cr4, %eax
- btsl $(X86_CR4_PAE_BIT), %eax
- movl %eax, %cr4
-
- movl %cr3, %eax
- movl %eax, %cr3
-
- movl $MSR_EFER, %ecx
- rdmsr
- btsl $_EFER_LME, %eax
- wrmsr
-
- xorl %eax, %eax
- lldt %ax
-
- pushl $__KERNEL_CS
- pushl %ebp
-
- /* Enable paging */
- movl %cr0, %eax
- btsl $X86_CR0_PG_BIT, %eax
- movl %eax, %cr0
- lret
-SYM_FUNC_END(efi_enter32)
-
- .data
- .balign 8
-SYM_DATA_START(efi32_boot_gdt)
- .word 0
- .quad 0
-SYM_DATA_END(efi32_boot_gdt)
-
-SYM_DATA_START(efi32_boot_idt)
- .word 0
- .quad 0
-SYM_DATA_END(efi32_boot_idt)
-
-SYM_DATA_START(efi32_boot_cs)
- .word 0
-SYM_DATA_END(efi32_boot_cs)
-
-SYM_DATA_START(efi32_boot_ds)
- .word 0
-SYM_DATA_END(efi32_boot_ds)
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index 3b354eb9516d..6589ddd4cfaf 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -208,10 +208,6 @@ SYM_DATA_START_LOCAL(gdt)
.quad 0x00cf92000000ffff /* __KERNEL_DS */
SYM_DATA_END_LABEL(gdt, SYM_L_LOCAL, gdt_end)
-#ifdef CONFIG_EFI_STUB
-SYM_DATA(image_offset, .long 0)
-#endif
-
/*
* Stack and heap for uncompression
*/
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index d33f060900d2..d4c4281db635 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -118,7 +118,9 @@ SYM_FUNC_START(startup_32)
1:
/* Setup Exception handling for SEV-ES */
+#ifdef CONFIG_AMD_MEM_ENCRYPT
call startup32_load_idt
+#endif
/* Make sure cpu supports long mode. */
call verify_cpu
@@ -178,12 +180,13 @@ SYM_FUNC_START(startup_32)
*/
/*
* If SEV is active then set the encryption mask in the page tables.
- * This will insure that when the kernel is copied and decompressed
+ * This will ensure that when the kernel is copied and decompressed
* it will be done so encrypted.
*/
- call get_sev_encryption_bit
xorl %edx, %edx
#ifdef CONFIG_AMD_MEM_ENCRYPT
+ call get_sev_encryption_bit
+ xorl %edx, %edx
testl %eax, %eax
jz 1f
subl $32, %eax /* Encryption bit is always above bit 31 */
@@ -249,6 +252,11 @@ SYM_FUNC_START(startup_32)
movl $__BOOT_TSS, %eax
ltr %ax
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+ /* Check if the C-bit position is correct when SEV is active */
+ call startup32_check_sev_cbit
+#endif
+
/*
* Setup for the jump to 64bit mode
*
@@ -261,29 +269,11 @@ SYM_FUNC_START(startup_32)
*/
leal rva(startup_64)(%ebp), %eax
#ifdef CONFIG_EFI_MIXED
- movl rva(efi32_boot_args)(%ebp), %edi
- testl %edi, %edi
- jz 1f
- leal rva(efi64_stub_entry)(%ebp), %eax
- movl rva(efi32_boot_args+4)(%ebp), %esi
- movl rva(efi32_boot_args+8)(%ebp), %edx // saved bootparams pointer
- testl %edx, %edx
- jnz 1f
- /*
- * efi_pe_entry uses MS calling convention, which requires 32 bytes of
- * shadow space on the stack even if all arguments are passed in
- * registers. We also need an additional 8 bytes for the space that
- * would be occupied by the return address, and this also results in
- * the correct stack alignment for entry.
- */
- subl $40, %esp
- leal rva(efi_pe_entry)(%ebp), %eax
- movl %edi, %ecx // MS calling convention
- movl %esi, %edx
+ cmpb $1, rva(efi_is64)(%ebp)
+ je 1f
+ leal rva(startup_64_mixed_mode)(%ebp), %eax
1:
#endif
- /* Check if the C-bit position is correct when SEV is active */
- call startup32_check_sev_cbit
pushl $__KERNEL_CS
pushl %eax
@@ -296,38 +286,14 @@ SYM_FUNC_START(startup_32)
lret
SYM_FUNC_END(startup_32)
-#ifdef CONFIG_EFI_MIXED
+#if IS_ENABLED(CONFIG_EFI_MIXED) && IS_ENABLED(CONFIG_EFI_HANDOVER_PROTOCOL)
.org 0x190
SYM_FUNC_START(efi32_stub_entry)
add $0x4, %esp /* Discard return address */
popl %ecx
popl %edx
popl %esi
-
- call 1f
-1: pop %ebp
- subl $ rva(1b), %ebp
-
- movl %esi, rva(efi32_boot_args+8)(%ebp)
-SYM_INNER_LABEL(efi32_pe_stub_entry, SYM_L_LOCAL)
- movl %ecx, rva(efi32_boot_args)(%ebp)
- movl %edx, rva(efi32_boot_args+4)(%ebp)
- movb $0, rva(efi_is64)(%ebp)
-
- /* Save firmware GDTR and code/data selectors */
- sgdtl rva(efi32_boot_gdt)(%ebp)
- movw %cs, rva(efi32_boot_cs)(%ebp)
- movw %ds, rva(efi32_boot_ds)(%ebp)
-
- /* Store firmware IDT descriptor */
- sidtl rva(efi32_boot_idt)(%ebp)
-
- /* Disable paging */
- movl %cr0, %eax
- btrl $X86_CR0_PG_BIT, %eax
- movl %eax, %cr0
-
- jmp startup_32
+ jmp efi32_entry
SYM_FUNC_END(efi32_stub_entry)
#endif
@@ -550,7 +516,9 @@ trampoline_return:
SYM_CODE_END(startup_64)
#ifdef CONFIG_EFI_STUB
+#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
.org 0x390
+#endif
SYM_FUNC_START(efi64_stub_entry)
and $~0xf, %rsp /* realign the stack */
movq %rdx, %rbx /* save boot_params pointer */
@@ -713,6 +681,7 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lno_longmode)
jmp 1b
SYM_FUNC_END(.Lno_longmode)
+ .globl verify_cpu
#include "../../kernel/verify_cpu.S"
.data
@@ -744,242 +713,6 @@ SYM_DATA_START(boot_idt)
.endr
SYM_DATA_END_LABEL(boot_idt, SYM_L_GLOBAL, boot_idt_end)
-#ifdef CONFIG_AMD_MEM_ENCRYPT
-SYM_DATA_START(boot32_idt_desc)
- .word boot32_idt_end - boot32_idt - 1
- .long 0
-SYM_DATA_END(boot32_idt_desc)
- .balign 8
-SYM_DATA_START(boot32_idt)
- .rept 32
- .quad 0
- .endr
-SYM_DATA_END_LABEL(boot32_idt, SYM_L_GLOBAL, boot32_idt_end)
-#endif
-
-#ifdef CONFIG_EFI_STUB
-SYM_DATA(image_offset, .long 0)
-#endif
-#ifdef CONFIG_EFI_MIXED
-SYM_DATA_LOCAL(efi32_boot_args, .long 0, 0, 0)
-SYM_DATA(efi_is64, .byte 1)
-
-#define ST32_boottime 60 // offsetof(efi_system_table_32_t, boottime)
-#define BS32_handle_protocol 88 // offsetof(efi_boot_services_32_t, handle_protocol)
-#define LI32_image_base 32 // offsetof(efi_loaded_image_32_t, image_base)
-
- __HEAD
- .code32
-SYM_FUNC_START(efi32_pe_entry)
-/*
- * efi_status_t efi32_pe_entry(efi_handle_t image_handle,
- * efi_system_table_32_t *sys_table)
- */
-
- pushl %ebp
- movl %esp, %ebp
- pushl %eax // dummy push to allocate loaded_image
-
- pushl %ebx // save callee-save registers
- pushl %edi
-
- call verify_cpu // check for long mode support
- testl %eax, %eax
- movl $0x80000003, %eax // EFI_UNSUPPORTED
- jnz 2f
-
- call 1f
-1: pop %ebx
- subl $ rva(1b), %ebx
-
- /* Get the loaded image protocol pointer from the image handle */
- leal -4(%ebp), %eax
- pushl %eax // &loaded_image
- leal rva(loaded_image_proto)(%ebx), %eax
- pushl %eax // pass the GUID address
- pushl 8(%ebp) // pass the image handle
-
- /*
- * Note the alignment of the stack frame.
- * sys_table
- * handle <-- 16-byte aligned on entry by ABI
- * return address
- * frame pointer
- * loaded_image <-- local variable
- * saved %ebx <-- 16-byte aligned here
- * saved %edi
- * &loaded_image
- * &loaded_image_proto
- * handle <-- 16-byte aligned for call to handle_protocol
- */
-
- movl 12(%ebp), %eax // sys_table
- movl ST32_boottime(%eax), %eax // sys_table->boottime
- call *BS32_handle_protocol(%eax) // sys_table->boottime->handle_protocol
- addl $12, %esp // restore argument space
- testl %eax, %eax
- jnz 2f
-
- movl 8(%ebp), %ecx // image_handle
- movl 12(%ebp), %edx // sys_table
- movl -4(%ebp), %esi // loaded_image
- movl LI32_image_base(%esi), %esi // loaded_image->image_base
- movl %ebx, %ebp // startup_32 for efi32_pe_stub_entry
- /*
- * We need to set the image_offset variable here since startup_32() will
- * use it before we get to the 64-bit efi_pe_entry() in C code.
- */
- subl %esi, %ebx
- movl %ebx, rva(image_offset)(%ebp) // save image_offset
- jmp efi32_pe_stub_entry
-
-2: popl %edi // restore callee-save registers
- popl %ebx
- leave
- RET
-SYM_FUNC_END(efi32_pe_entry)
-
- .section ".rodata"
- /* EFI loaded image protocol GUID */
- .balign 4
-SYM_DATA_START_LOCAL(loaded_image_proto)
- .long 0x5b1b31a1
- .word 0x9562, 0x11d2
- .byte 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b
-SYM_DATA_END(loaded_image_proto)
-#endif
-
-#ifdef CONFIG_AMD_MEM_ENCRYPT
- __HEAD
- .code32
-/*
- * Write an IDT entry into boot32_idt
- *
- * Parameters:
- *
- * %eax: Handler address
- * %edx: Vector number
- *
- * Physical offset is expected in %ebp
- */
-SYM_FUNC_START(startup32_set_idt_entry)
- push %ebx
- push %ecx
-
- /* IDT entry address to %ebx */
- leal rva(boot32_idt)(%ebp), %ebx
- shl $3, %edx
- addl %edx, %ebx
-
- /* Build IDT entry, lower 4 bytes */
- movl %eax, %edx
- andl $0x0000ffff, %edx # Target code segment offset [15:0]
- movl $__KERNEL32_CS, %ecx # Target code segment selector
- shl $16, %ecx
- orl %ecx, %edx
-
- /* Store lower 4 bytes to IDT */
- movl %edx, (%ebx)
-
- /* Build IDT entry, upper 4 bytes */
- movl %eax, %edx
- andl $0xffff0000, %edx # Target code segment offset [31:16]
- orl $0x00008e00, %edx # Present, Type 32-bit Interrupt Gate
-
- /* Store upper 4 bytes to IDT */
- movl %edx, 4(%ebx)
-
- pop %ecx
- pop %ebx
- RET
-SYM_FUNC_END(startup32_set_idt_entry)
-#endif
-
-SYM_FUNC_START(startup32_load_idt)
-#ifdef CONFIG_AMD_MEM_ENCRYPT
- /* #VC handler */
- leal rva(startup32_vc_handler)(%ebp), %eax
- movl $X86_TRAP_VC, %edx
- call startup32_set_idt_entry
-
- /* Load IDT */
- leal rva(boot32_idt)(%ebp), %eax
- movl %eax, rva(boot32_idt_desc+2)(%ebp)
- lidt rva(boot32_idt_desc)(%ebp)
-#endif
- RET
-SYM_FUNC_END(startup32_load_idt)
-
-/*
- * Check for the correct C-bit position when the startup_32 boot-path is used.
- *
- * The check makes use of the fact that all memory is encrypted when paging is
- * disabled. The function creates 64 bits of random data using the RDRAND
- * instruction. RDRAND is mandatory for SEV guests, so always available. If the
- * hypervisor violates that the kernel will crash right here.
- *
- * The 64 bits of random data are stored to a memory location and at the same
- * time kept in the %eax and %ebx registers. Since encryption is always active
- * when paging is off the random data will be stored encrypted in main memory.
- *
- * Then paging is enabled. When the C-bit position is correct all memory is
- * still mapped encrypted and comparing the register values with memory will
- * succeed. An incorrect C-bit position will map all memory unencrypted, so that
- * the compare will use the encrypted random data and fail.
- */
-SYM_FUNC_START(startup32_check_sev_cbit)
-#ifdef CONFIG_AMD_MEM_ENCRYPT
- pushl %eax
- pushl %ebx
- pushl %ecx
- pushl %edx
-
- /* Check for non-zero sev_status */
- movl rva(sev_status)(%ebp), %eax
- testl %eax, %eax
- jz 4f
-
- /*
- * Get two 32-bit random values - Don't bail out if RDRAND fails
- * because it is better to prevent forward progress if no random value
- * can be gathered.
- */
-1: rdrand %eax
- jnc 1b
-2: rdrand %ebx
- jnc 2b
-
- /* Store to memory and keep it in the registers */
- movl %eax, rva(sev_check_data)(%ebp)
- movl %ebx, rva(sev_check_data+4)(%ebp)
-
- /* Enable paging to see if encryption is active */
- movl %cr0, %edx /* Backup %cr0 in %edx */
- movl $(X86_CR0_PG | X86_CR0_PE), %ecx /* Enable Paging and Protected mode */
- movl %ecx, %cr0
-
- cmpl %eax, rva(sev_check_data)(%ebp)
- jne 3f
- cmpl %ebx, rva(sev_check_data+4)(%ebp)
- jne 3f
-
- movl %edx, %cr0 /* Restore previous %cr0 */
-
- jmp 4f
-
-3: /* Check failed - hlt the machine */
- hlt
- jmp 3b
-
-4:
- popl %edx
- popl %ecx
- popl %ebx
- popl %eax
-#endif
- RET
-SYM_FUNC_END(startup32_check_sev_cbit)
-
/*
* Stack and heap for uncompression
*/
diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
index e476bcbd9b42..454757fbdfe5 100644
--- a/arch/x86/boot/compressed/kaslr.c
+++ b/arch/x86/boot/compressed/kaslr.c
@@ -668,7 +668,7 @@ static bool process_mem_region(struct mem_vector *region,
}
}
#endif
- return 0;
+ return false;
}
#ifdef CONFIG_EFI
diff --git a/arch/x86/boot/compressed/mem_encrypt.S b/arch/x86/boot/compressed/mem_encrypt.S
index a73e4d783cae..32f7cc8a8625 100644
--- a/arch/x86/boot/compressed/mem_encrypt.S
+++ b/arch/x86/boot/compressed/mem_encrypt.S
@@ -12,16 +12,13 @@
#include <asm/processor-flags.h>
#include <asm/msr.h>
#include <asm/asm-offsets.h>
+#include <asm/segment.h>
+#include <asm/trapnr.h>
.text
.code32
SYM_FUNC_START(get_sev_encryption_bit)
- xor %eax, %eax
-
-#ifdef CONFIG_AMD_MEM_ENCRYPT
push %ebx
- push %ecx
- push %edx
movl $0x80000000, %eax /* CPUID to check the highest leaf */
cpuid
@@ -52,12 +49,7 @@ SYM_FUNC_START(get_sev_encryption_bit)
xor %eax, %eax
.Lsev_exit:
- pop %edx
- pop %ecx
pop %ebx
-
-#endif /* CONFIG_AMD_MEM_ENCRYPT */
-
RET
SYM_FUNC_END(get_sev_encryption_bit)
@@ -98,7 +90,7 @@ SYM_CODE_START_LOCAL(sev_es_req_cpuid)
jmp 1b
SYM_CODE_END(sev_es_req_cpuid)
-SYM_CODE_START(startup32_vc_handler)
+SYM_CODE_START_LOCAL(startup32_vc_handler)
pushl %eax
pushl %ebx
pushl %ecx
@@ -184,15 +176,149 @@ SYM_CODE_START(startup32_vc_handler)
jmp .Lfail
SYM_CODE_END(startup32_vc_handler)
+/*
+ * Write an IDT entry into boot32_idt
+ *
+ * Parameters:
+ *
+ * %eax: Handler address
+ * %edx: Vector number
+ * %ecx: IDT address
+ */
+SYM_FUNC_START_LOCAL(startup32_set_idt_entry)
+ /* IDT entry address to %ecx */
+ leal (%ecx, %edx, 8), %ecx
+
+ /* Build IDT entry, lower 4 bytes */
+ movl %eax, %edx
+ andl $0x0000ffff, %edx # Target code segment offset [15:0]
+ orl $(__KERNEL32_CS << 16), %edx # Target code segment selector
+
+ /* Store lower 4 bytes to IDT */
+ movl %edx, (%ecx)
+
+ /* Build IDT entry, upper 4 bytes */
+ movl %eax, %edx
+ andl $0xffff0000, %edx # Target code segment offset [31:16]
+ orl $0x00008e00, %edx # Present, Type 32-bit Interrupt Gate
+
+ /* Store upper 4 bytes to IDT */
+ movl %edx, 4(%ecx)
+
+ RET
+SYM_FUNC_END(startup32_set_idt_entry)
+
+SYM_FUNC_START(startup32_load_idt)
+ push %ebp
+ push %ebx
+
+ call 1f
+1: pop %ebp
+
+ leal (boot32_idt - 1b)(%ebp), %ebx
+
+ /* #VC handler */
+ leal (startup32_vc_handler - 1b)(%ebp), %eax
+ movl $X86_TRAP_VC, %edx
+ movl %ebx, %ecx
+ call startup32_set_idt_entry
+
+ /* Load IDT */
+ leal (boot32_idt_desc - 1b)(%ebp), %ecx
+ movl %ebx, 2(%ecx)
+ lidt (%ecx)
+
+ pop %ebx
+ pop %ebp
+ RET
+SYM_FUNC_END(startup32_load_idt)
+
+/*
+ * Check for the correct C-bit position when the startup_32 boot-path is used.
+ *
+ * The check makes use of the fact that all memory is encrypted when paging is
+ * disabled. The function creates 64 bits of random data using the RDRAND
+ * instruction. RDRAND is mandatory for SEV guests, so always available. If the
+ * hypervisor violates that the kernel will crash right here.
+ *
+ * The 64 bits of random data are stored to a memory location and at the same
+ * time kept in the %eax and %ebx registers. Since encryption is always active
+ * when paging is off the random data will be stored encrypted in main memory.
+ *
+ * Then paging is enabled. When the C-bit position is correct all memory is
+ * still mapped encrypted and comparing the register values with memory will
+ * succeed. An incorrect C-bit position will map all memory unencrypted, so that
+ * the compare will use the encrypted random data and fail.
+ */
+SYM_FUNC_START(startup32_check_sev_cbit)
+ pushl %ebx
+ pushl %ebp
+
+ call 0f
+0: popl %ebp
+
+ /* Check for non-zero sev_status */
+ movl (sev_status - 0b)(%ebp), %eax
+ testl %eax, %eax
+ jz 4f
+
+ /*
+ * Get two 32-bit random values - Don't bail out if RDRAND fails
+ * because it is better to prevent forward progress if no random value
+ * can be gathered.
+ */
+1: rdrand %eax
+ jnc 1b
+2: rdrand %ebx
+ jnc 2b
+
+ /* Store to memory and keep it in the registers */
+ leal (sev_check_data - 0b)(%ebp), %ebp
+ movl %eax, 0(%ebp)
+ movl %ebx, 4(%ebp)
+
+ /* Enable paging to see if encryption is active */
+ movl %cr0, %edx /* Backup %cr0 in %edx */
+ movl $(X86_CR0_PG | X86_CR0_PE), %ecx /* Enable Paging and Protected mode */
+ movl %ecx, %cr0
+
+ cmpl %eax, 0(%ebp)
+ jne 3f
+ cmpl %ebx, 4(%ebp)
+ jne 3f
+
+ movl %edx, %cr0 /* Restore previous %cr0 */
+
+ jmp 4f
+
+3: /* Check failed - hlt the machine */
+ hlt
+ jmp 3b
+
+4:
+ popl %ebp
+ popl %ebx
+ RET
+SYM_FUNC_END(startup32_check_sev_cbit)
+
.code64
#include "../../kernel/sev_verify_cbit.S"
.data
-#ifdef CONFIG_AMD_MEM_ENCRYPT
.balign 8
SYM_DATA(sme_me_mask, .quad 0)
SYM_DATA(sev_status, .quad 0)
SYM_DATA(sev_check_data, .quad 0)
-#endif
+
+SYM_DATA_START_LOCAL(boot32_idt)
+ .rept 32
+ .quad 0
+ .endr
+SYM_DATA_END(boot32_idt)
+
+SYM_DATA_START_LOCAL(boot32_idt_desc)
+ .word . - boot32_idt - 1
+ .long 0
+SYM_DATA_END(boot32_idt_desc)
diff --git a/arch/x86/boot/cpuflags.c b/arch/x86/boot/cpuflags.c
index a83d67ec627d..d75237ba7ce9 100644
--- a/arch/x86/boot/cpuflags.c
+++ b/arch/x86/boot/cpuflags.c
@@ -64,20 +64,11 @@ int has_eflag(unsigned long mask)
return !!((f0^f1) & mask);
}
-/* Handle x86_32 PIC using ebx. */
-#if defined(__i386__) && defined(__PIC__)
-# define EBX_REG "=r"
-#else
-# define EBX_REG "=b"
-#endif
-
void cpuid_count(u32 id, u32 count, u32 *a, u32 *b, u32 *c, u32 *d)
{
- asm volatile(".ifnc %%ebx,%3 ; movl %%ebx,%3 ; .endif \n\t"
- "cpuid \n\t"
- ".ifnc %%ebx,%3 ; xchgl %%ebx,%3 ; .endif \n\t"
- : "=a" (*a), "=c" (*c), "=d" (*d), EBX_REG (*b)
- : "a" (id), "c" (count)
+ asm volatile("cpuid"
+ : "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d)
+ : "0" (id), "2" (count)
);
}
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index f912d7770130..9338c68e7413 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -80,10 +80,11 @@ bs_die:
ljmp $0xf000,$0xfff0
#ifdef CONFIG_EFI_STUB
- .org 0x3c
+ .org 0x38
#
# Offset to the PE header.
#
+ .long LINUX_PE_MAGIC
.long pe_header
#endif /* CONFIG_EFI_STUB */
@@ -406,7 +407,7 @@ xloadflags:
# define XLF1 0
#endif
-#ifdef CONFIG_EFI_STUB
+#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
# ifdef CONFIG_EFI_MIXED
# define XLF23 (XLF_EFI_HANDOVER_32|XLF_EFI_HANDOVER_64)
# else
diff --git a/arch/x86/boot/string.c b/arch/x86/boot/string.c
index 8a3fff9128bb..1c8541ae3b3a 100644
--- a/arch/x86/boot/string.c
+++ b/arch/x86/boot/string.c
@@ -350,7 +350,7 @@ static int _kstrtoul(const char *s, unsigned int base, unsigned long *res)
}
/**
- * kstrtoul - convert a string to an unsigned long
+ * boot_kstrtoul - convert a string to an unsigned long
* @s: The start of the string. The string must be null-terminated, and may also
* include a single newline before its terminating null. The first character
* may also be a plus sign, but not a minus sign.
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
index a3725ad46c5a..bd247692b701 100644
--- a/arch/x86/boot/tools/build.c
+++ b/arch/x86/boot/tools/build.c
@@ -290,6 +290,7 @@ static void efi_stub_entry_update(void)
{
unsigned long addr = efi32_stub_entry;
+#ifdef CONFIG_EFI_HANDOVER_PROTOCOL
#ifdef CONFIG_X86_64
/* Yes, this is really how we defined it :( */
addr = efi64_stub_entry - 0x200;
@@ -299,6 +300,7 @@ static void efi_stub_entry_update(void)
if (efi32_stub_entry != addr)
die("32-bit and 64-bit EFI entry points do not match\n");
#endif
+#endif
put_unaligned_le32(addr, &buf[0x264]);
}
diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
index b8998cf0508a..cfd4c95b9f04 100644
--- a/arch/x86/coco/tdx/tdx.c
+++ b/arch/x86/coco/tdx/tdx.c
@@ -5,6 +5,8 @@
#define pr_fmt(fmt) "tdx: " fmt
#include <linux/cpufeature.h>
+#include <linux/export.h>
+#include <linux/io.h>
#include <asm/coco.h>
#include <asm/tdx.h>
#include <asm/vmx.h>
@@ -15,6 +17,7 @@
/* TDX module Call Leaf IDs */
#define TDX_GET_INFO 1
#define TDX_GET_VEINFO 3
+#define TDX_GET_REPORT 4
#define TDX_ACCEPT_PAGE 6
/* TDX hypercall Leaf IDs */
@@ -36,6 +39,12 @@
#define ATTR_SEPT_VE_DISABLE BIT(28)
+/* TDX Module call error codes */
+#define TDCALL_RETURN_CODE(a) ((a) >> 32)
+#define TDCALL_INVALID_OPERAND 0xc0000100
+
+#define TDREPORT_SUBTYPE_0 0
+
/*
* Wrapper for standard use of __tdx_hypercall with no output aside from
* return code.
@@ -100,6 +109,37 @@ static inline void tdx_module_call(u64 fn, u64 rcx, u64 rdx, u64 r8, u64 r9,
panic("TDCALL %lld failed (Buggy TDX module!)\n", fn);
}
+/**
+ * tdx_mcall_get_report0() - Wrapper to get TDREPORT0 (a.k.a. TDREPORT
+ * subtype 0) using TDG.MR.REPORT TDCALL.
+ * @reportdata: Address of the input buffer which contains user-defined
+ * REPORTDATA to be included into TDREPORT.
+ * @tdreport: Address of the output buffer to store TDREPORT.
+ *
+ * Refer to section titled "TDG.MR.REPORT leaf" in the TDX Module
+ * v1.0 specification for more information on TDG.MR.REPORT TDCALL.
+ * It is used in the TDX guest driver module to get the TDREPORT0.
+ *
+ * Return 0 on success, -EINVAL for invalid operands, or -EIO on
+ * other TDCALL failures.
+ */
+int tdx_mcall_get_report0(u8 *reportdata, u8 *tdreport)
+{
+ u64 ret;
+
+ ret = __tdx_module_call(TDX_GET_REPORT, virt_to_phys(tdreport),
+ virt_to_phys(reportdata), TDREPORT_SUBTYPE_0,
+ 0, NULL);
+ if (ret) {
+ if (TDCALL_RETURN_CODE(ret) == TDCALL_INVALID_OPERAND)
+ return -EINVAL;
+ return -EIO;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tdx_mcall_get_report0);
+
static void tdx_parse_tdinfo(u64 *cc_mask)
{
struct tdx_module_output out;
diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S
index 4dd19819053a..59b93901660d 100644
--- a/arch/x86/entry/entry_64_compat.S
+++ b/arch/x86/entry/entry_64_compat.S
@@ -61,7 +61,7 @@ SYM_CODE_START(entry_SYSENTER_compat)
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
/* Construct struct pt_regs on stack */
- pushq $__USER32_DS /* pt_regs->ss */
+ pushq $__USER_DS /* pt_regs->ss */
pushq $0 /* pt_regs->sp = 0 (placeholder) */
/*
@@ -197,7 +197,7 @@ SYM_INNER_LABEL(entry_SYSCALL_compat_safe_stack, SYM_L_GLOBAL)
ANNOTATE_NOENDBR
/* Construct struct pt_regs on stack */
- pushq $__USER32_DS /* pt_regs->ss */
+ pushq $__USER_DS /* pt_regs->ss */
pushq %r8 /* pt_regs->sp */
pushq %r11 /* pt_regs->flags */
pushq $__USER32_CS /* pt_regs->cs */
diff --git a/arch/x86/entry/vdso/vdso.lds.S b/arch/x86/entry/vdso/vdso.lds.S
index 4bf48462fca7..e8c60ae7a7c8 100644
--- a/arch/x86/entry/vdso/vdso.lds.S
+++ b/arch/x86/entry/vdso/vdso.lds.S
@@ -27,7 +27,9 @@ VERSION {
__vdso_time;
clock_getres;
__vdso_clock_getres;
+#ifdef CONFIG_X86_SGX
__vdso_sgx_enter_enclave;
+#endif
local: *;
};
}
diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c
index 311eae30e089..b8f3f9b9e53c 100644
--- a/arch/x86/entry/vdso/vma.c
+++ b/arch/x86/entry/vdso/vma.c
@@ -98,24 +98,6 @@ static int vdso_mremap(const struct vm_special_mapping *sm,
}
#ifdef CONFIG_TIME_NS
-static struct page *find_timens_vvar_page(struct vm_area_struct *vma)
-{
- if (likely(vma->vm_mm == current->mm))
- return current->nsproxy->time_ns->vvar_page;
-
- /*
- * VM_PFNMAP | VM_IO protect .fault() handler from being called
- * through interfaces like /proc/$pid/mem or
- * process_vm_{readv,writev}() as long as there's no .access()
- * in special_mapping_vmops().
- * For more details check_vma_flags() and __access_remote_vm()
- */
-
- WARN(1, "vvar_page accessed remotely");
-
- return NULL;
-}
-
/*
* The vvar page layout depends on whether a task belongs to the root or
* non-root time namespace. Whenever a task changes its namespace, the VVAR
@@ -140,11 +122,6 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
return 0;
}
-#else
-static inline struct page *find_timens_vvar_page(struct vm_area_struct *vma)
-{
- return NULL;
-}
#endif
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
@@ -210,11 +187,10 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
pgprot_decrypted(vma->vm_page_prot));
}
} else if (sym_offset == image->sym_hvclock_page) {
- struct ms_hyperv_tsc_page *tsc_pg = hv_get_tsc_page();
+ pfn = hv_get_tsc_pfn();
- if (tsc_pg && vclock_was_used(VDSO_CLOCKMODE_HVCLOCK))
- return vmf_insert_pfn(vma, vmf->address,
- virt_to_phys(tsc_pg) >> PAGE_SHIFT);
+ if (pfn && vclock_was_used(VDSO_CLOCKMODE_HVCLOCK))
+ return vmf_insert_pfn(vma, vmf->address, pfn);
} else if (sym_offset == image->sym_timens_page) {
struct page *timens_page = find_timens_vvar_page(vma);
@@ -327,7 +303,7 @@ static unsigned long vdso_addr(unsigned long start, unsigned len)
end -= len;
if (end > start) {
- offset = prandom_u32_max(((end - start) >> PAGE_SHIFT) + 1);
+ offset = get_random_u32_below(((end - start) >> PAGE_SHIFT) + 1);
addr = start + (offset << PAGE_SHIFT);
} else {
addr = start;
diff --git a/arch/x86/events/amd/brs.c b/arch/x86/events/amd/brs.c
index f1bff153d945..58461fa18b6f 100644
--- a/arch/x86/events/amd/brs.c
+++ b/arch/x86/events/amd/brs.c
@@ -384,7 +384,7 @@ static void amd_brs_poison_buffer(void)
* On ctxswin, sched_in = true, called after the PMU has started
* On ctxswout, sched_in = false, called before the PMU is stopped
*/
-void amd_pmu_brs_sched_task(struct perf_event_context *ctx, bool sched_in)
+void amd_pmu_brs_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in)
{
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
diff --git a/arch/x86/events/amd/ibs.c b/arch/x86/events/amd/ibs.c
index 4cb710efbdd9..da3f5ebac4e1 100644
--- a/arch/x86/events/amd/ibs.c
+++ b/arch/x86/events/amd/ibs.c
@@ -631,7 +631,7 @@ static const struct attribute_group *op_attr_update[] = {
static struct perf_ibs perf_ibs_fetch = {
.pmu = {
- .task_ctx_nr = perf_invalid_context,
+ .task_ctx_nr = perf_hw_context,
.event_init = perf_ibs_init,
.add = perf_ibs_add,
@@ -655,7 +655,7 @@ static struct perf_ibs perf_ibs_fetch = {
static struct perf_ibs perf_ibs_op = {
.pmu = {
- .task_ctx_nr = perf_invalid_context,
+ .task_ctx_nr = perf_hw_context,
.event_init = perf_ibs_init,
.add = perf_ibs_add,
diff --git a/arch/x86/events/amd/lbr.c b/arch/x86/events/amd/lbr.c
index 38a75216c12c..eb31f850841a 100644
--- a/arch/x86/events/amd/lbr.c
+++ b/arch/x86/events/amd/lbr.c
@@ -352,7 +352,7 @@ void amd_pmu_lbr_add(struct perf_event *event)
cpuc->br_sel = reg->reg;
}
- perf_sched_cb_inc(event->ctx->pmu);
+ perf_sched_cb_inc(event->pmu);
if (!cpuc->lbr_users++ && !event->total_time_running)
amd_pmu_lbr_reset();
@@ -370,10 +370,10 @@ void amd_pmu_lbr_del(struct perf_event *event)
cpuc->lbr_users--;
WARN_ON_ONCE(cpuc->lbr_users < 0);
- perf_sched_cb_dec(event->ctx->pmu);
+ perf_sched_cb_dec(event->pmu);
}
-void amd_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in)
+void amd_pmu_lbr_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in)
{
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index b30b8bbcd1e2..85a63a41c471 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -90,6 +90,8 @@ DEFINE_STATIC_CALL_NULL(x86_pmu_swap_task_ctx, *x86_pmu.swap_task_ctx);
DEFINE_STATIC_CALL_NULL(x86_pmu_drain_pebs, *x86_pmu.drain_pebs);
DEFINE_STATIC_CALL_NULL(x86_pmu_pebs_aliases, *x86_pmu.pebs_aliases);
+DEFINE_STATIC_CALL_NULL(x86_pmu_filter, *x86_pmu.filter);
+
/*
* This one is magic, it will get called even when PMU init fails (because
* there is no PMU), in which case it should simply return NULL.
@@ -2031,6 +2033,7 @@ static void x86_pmu_static_call_update(void)
static_call_update(x86_pmu_pebs_aliases, x86_pmu.pebs_aliases);
static_call_update(x86_pmu_guest_get_msrs, x86_pmu.guest_get_msrs);
+ static_call_update(x86_pmu_filter, x86_pmu.filter);
}
static void _x86_pmu_read(struct perf_event *event)
@@ -2052,23 +2055,6 @@ void x86_pmu_show_pmu_cap(int num_counters, int num_counters_fixed,
pr_info("... event mask: %016Lx\n", intel_ctrl);
}
-/*
- * The generic code is not hybrid friendly. The hybrid_pmu->pmu
- * of the first registered PMU is unconditionally assigned to
- * each possible cpuctx->ctx.pmu.
- * Update the correct hybrid PMU to the cpuctx->ctx.pmu.
- */
-void x86_pmu_update_cpu_context(struct pmu *pmu, int cpu)
-{
- struct perf_cpu_context *cpuctx;
-
- if (!pmu->pmu_cpu_context)
- return;
-
- cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu);
- cpuctx->ctx.pmu = pmu;
-}
-
static int __init init_hw_perf_events(void)
{
struct x86_pmu_quirk *quirk;
@@ -2175,13 +2161,9 @@ static int __init init_hw_perf_events(void)
if (err)
goto out2;
} else {
- u8 cpu_type = get_this_hybrid_cpu_type();
struct x86_hybrid_pmu *hybrid_pmu;
int i, j;
- if (!cpu_type && x86_pmu.get_hybrid_cpu_type)
- cpu_type = x86_pmu.get_hybrid_cpu_type();
-
for (i = 0; i < x86_pmu.num_hybrid_pmus; i++) {
hybrid_pmu = &x86_pmu.hybrid_pmu[i];
@@ -2195,9 +2177,6 @@ static int __init init_hw_perf_events(void)
(hybrid_pmu->cpu_type == hybrid_big) ? PERF_TYPE_RAW : -1);
if (err)
break;
-
- if (cpu_type == hybrid_pmu->cpu_type)
- x86_pmu_update_cpu_context(&hybrid_pmu->pmu, raw_smp_processor_id());
}
if (i < x86_pmu.num_hybrid_pmus) {
@@ -2646,15 +2625,15 @@ static const struct attribute_group *x86_pmu_attr_groups[] = {
NULL,
};
-static void x86_pmu_sched_task(struct perf_event_context *ctx, bool sched_in)
+static void x86_pmu_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in)
{
- static_call_cond(x86_pmu_sched_task)(ctx, sched_in);
+ static_call_cond(x86_pmu_sched_task)(pmu_ctx, sched_in);
}
-static void x86_pmu_swap_task_ctx(struct perf_event_context *prev,
- struct perf_event_context *next)
+static void x86_pmu_swap_task_ctx(struct perf_event_pmu_context *prev_epc,
+ struct perf_event_pmu_context *next_epc)
{
- static_call_cond(x86_pmu_swap_task_ctx)(prev, next);
+ static_call_cond(x86_pmu_swap_task_ctx)(prev_epc, next_epc);
}
void perf_check_microcode(void)
@@ -2689,12 +2668,13 @@ static int x86_pmu_aux_output_match(struct perf_event *event)
return 0;
}
-static int x86_pmu_filter_match(struct perf_event *event)
+static bool x86_pmu_filter(struct pmu *pmu, int cpu)
{
- if (x86_pmu.filter_match)
- return x86_pmu.filter_match(event);
+ bool ret = false;
- return 1;
+ static_call_cond(x86_pmu_filter)(pmu, cpu, &ret);
+
+ return ret;
}
static struct pmu pmu = {
@@ -2725,7 +2705,7 @@ static struct pmu pmu = {
.aux_output_match = x86_pmu_aux_output_match,
- .filter_match = x86_pmu_filter_match,
+ .filter = x86_pmu_filter,
};
void arch_perf_update_userpage(struct perf_event *event,
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 1b92bf05fd65..dfd2c124cdf8 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -4536,8 +4536,6 @@ end:
cpumask_set_cpu(cpu, &pmu->supported_cpus);
cpuc->pmu = &pmu->pmu;
- x86_pmu_update_cpu_context(&pmu->pmu, cpu);
-
return true;
}
@@ -4671,17 +4669,17 @@ static void intel_pmu_cpu_dead(int cpu)
cpumask_clear_cpu(cpu, &hybrid_pmu(cpuc->pmu)->supported_cpus);
}
-static void intel_pmu_sched_task(struct perf_event_context *ctx,
+static void intel_pmu_sched_task(struct perf_event_pmu_context *pmu_ctx,
bool sched_in)
{
- intel_pmu_pebs_sched_task(ctx, sched_in);
- intel_pmu_lbr_sched_task(ctx, sched_in);
+ intel_pmu_pebs_sched_task(pmu_ctx, sched_in);
+ intel_pmu_lbr_sched_task(pmu_ctx, sched_in);
}
-static void intel_pmu_swap_task_ctx(struct perf_event_context *prev,
- struct perf_event_context *next)
+static void intel_pmu_swap_task_ctx(struct perf_event_pmu_context *prev_epc,
+ struct perf_event_pmu_context *next_epc)
{
- intel_pmu_lbr_swap_task_ctx(prev, next);
+ intel_pmu_lbr_swap_task_ctx(prev_epc, next_epc);
}
static int intel_pmu_check_period(struct perf_event *event, u64 value)
@@ -4705,12 +4703,11 @@ static int intel_pmu_aux_output_match(struct perf_event *event)
return is_intel_pt_event(event);
}
-static int intel_pmu_filter_match(struct perf_event *event)
+static void intel_pmu_filter(struct pmu *pmu, int cpu, bool *ret)
{
- struct x86_hybrid_pmu *pmu = hybrid_pmu(event->pmu);
- unsigned int cpu = smp_processor_id();
+ struct x86_hybrid_pmu *hpmu = hybrid_pmu(pmu);
- return cpumask_test_cpu(cpu, &pmu->supported_cpus);
+ *ret = !cpumask_test_cpu(cpu, &hpmu->supported_cpus);
}
PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63");
@@ -6413,7 +6410,7 @@ __init int intel_pmu_init(void)
static_call_update(intel_pmu_set_topdown_event_period,
&adl_set_topdown_event_period);
- x86_pmu.filter_match = intel_pmu_filter_match;
+ x86_pmu.filter = intel_pmu_filter;
x86_pmu.get_event_constraints = adl_get_event_constraints;
x86_pmu.hw_config = adl_hw_config;
x86_pmu.limit_period = spr_limit_period;
diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
index 446d2833efa7..88e58b6ee73c 100644
--- a/arch/x86/events/intel/ds.c
+++ b/arch/x86/events/intel/ds.c
@@ -1069,7 +1069,7 @@ static inline bool pebs_needs_sched_cb(struct cpu_hw_events *cpuc)
return cpuc->n_pebs && (cpuc->n_pebs == cpuc->n_large_pebs);
}
-void intel_pmu_pebs_sched_task(struct perf_event_context *ctx, bool sched_in)
+void intel_pmu_pebs_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in)
{
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
@@ -1177,7 +1177,7 @@ static void
pebs_update_state(bool needed_cb, struct cpu_hw_events *cpuc,
struct perf_event *event, bool add)
{
- struct pmu *pmu = event->ctx->pmu;
+ struct pmu *pmu = event->pmu;
/*
* Make sure we get updated with the first PEBS
* event. It will trigger also during removal, but
diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
index 8259d725054d..017baba56b01 100644
--- a/arch/x86/events/intel/lbr.c
+++ b/arch/x86/events/intel/lbr.c
@@ -515,21 +515,21 @@ static void __intel_pmu_lbr_save(void *ctx)
cpuc->last_log_id = ++task_context_opt(ctx)->log_id;
}
-void intel_pmu_lbr_swap_task_ctx(struct perf_event_context *prev,
- struct perf_event_context *next)
+void intel_pmu_lbr_swap_task_ctx(struct perf_event_pmu_context *prev_epc,
+ struct perf_event_pmu_context *next_epc)
{
void *prev_ctx_data, *next_ctx_data;
- swap(prev->task_ctx_data, next->task_ctx_data);
+ swap(prev_epc->task_ctx_data, next_epc->task_ctx_data);
/*
- * Architecture specific synchronization makes sense in
- * case both prev->task_ctx_data and next->task_ctx_data
+ * Architecture specific synchronization makes sense in case
+ * both prev_epc->task_ctx_data and next_epc->task_ctx_data
* pointers are allocated.
*/
- prev_ctx_data = next->task_ctx_data;
- next_ctx_data = prev->task_ctx_data;
+ prev_ctx_data = next_epc->task_ctx_data;
+ next_ctx_data = prev_epc->task_ctx_data;
if (!prev_ctx_data || !next_ctx_data)
return;
@@ -538,7 +538,7 @@ void intel_pmu_lbr_swap_task_ctx(struct perf_event_context *prev,
task_context_opt(next_ctx_data)->lbr_callstack_users);
}
-void intel_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in)
+void intel_pmu_lbr_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in)
{
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
void *task_ctx;
@@ -551,7 +551,7 @@ void intel_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in)
* the task was scheduled out, restore the stack. Otherwise flush
* the LBR stack.
*/
- task_ctx = ctx ? ctx->task_ctx_data : NULL;
+ task_ctx = pmu_ctx ? pmu_ctx->task_ctx_data : NULL;
if (task_ctx) {
if (sched_in)
__intel_pmu_lbr_restore(task_ctx);
@@ -587,8 +587,8 @@ void intel_pmu_lbr_add(struct perf_event *event)
cpuc->br_sel = event->hw.branch_reg.reg;
- if (branch_user_callstack(cpuc->br_sel) && event->ctx->task_ctx_data)
- task_context_opt(event->ctx->task_ctx_data)->lbr_callstack_users++;
+ if (branch_user_callstack(cpuc->br_sel) && event->pmu_ctx->task_ctx_data)
+ task_context_opt(event->pmu_ctx->task_ctx_data)->lbr_callstack_users++;
/*
* Request pmu::sched_task() callback, which will fire inside the
@@ -611,7 +611,7 @@ void intel_pmu_lbr_add(struct perf_event *event)
*/
if (x86_pmu.intel_cap.pebs_baseline && event->attr.precise_ip > 0)
cpuc->lbr_pebs_users++;
- perf_sched_cb_inc(event->ctx->pmu);
+ perf_sched_cb_inc(event->pmu);
if (!cpuc->lbr_users++ && !event->total_time_running)
intel_pmu_lbr_reset();
}
@@ -664,8 +664,8 @@ void intel_pmu_lbr_del(struct perf_event *event)
return;
if (branch_user_callstack(cpuc->br_sel) &&
- event->ctx->task_ctx_data)
- task_context_opt(event->ctx->task_ctx_data)->lbr_callstack_users--;
+ event->pmu_ctx->task_ctx_data)
+ task_context_opt(event->pmu_ctx->task_ctx_data)->lbr_callstack_users--;
if (event->hw.flags & PERF_X86_EVENT_LBR_SELECT)
cpuc->lbr_select = 0;
@@ -675,7 +675,7 @@ void intel_pmu_lbr_del(struct perf_event *event)
cpuc->lbr_users--;
WARN_ON_ONCE(cpuc->lbr_users < 0);
WARN_ON_ONCE(cpuc->lbr_pebs_users < 0);
- perf_sched_cb_dec(event->ctx->pmu);
+ perf_sched_cb_dec(event->pmu);
}
static inline bool vlbr_exclude_host(void)
diff --git a/arch/x86/events/intel/p4.c b/arch/x86/events/intel/p4.c
index 03bbcc2fa2ff..35936188db01 100644
--- a/arch/x86/events/intel/p4.c
+++ b/arch/x86/events/intel/p4.c
@@ -24,7 +24,7 @@ struct p4_event_bind {
unsigned int escr_msr[2]; /* ESCR MSR for this event */
unsigned int escr_emask; /* valid ESCR EventMask bits */
unsigned int shared; /* event is shared across threads */
- char cntr[2][P4_CNTR_LIMIT]; /* counter index (offset), -1 on absence */
+ signed char cntr[2][P4_CNTR_LIMIT]; /* counter index (offset), -1 on absence */
};
struct p4_pebs_bind {
diff --git a/arch/x86/events/intel/uncore.h b/arch/x86/events/intel/uncore.h
index 2adeaf4de4df..e278e2e7c051 100644
--- a/arch/x86/events/intel/uncore.h
+++ b/arch/x86/events/intel/uncore.h
@@ -2,6 +2,7 @@
#include <linux/slab.h>
#include <linux/pci.h>
#include <asm/apicdef.h>
+#include <asm/intel-family.h>
#include <linux/io-64-nonatomic-lo-hi.h>
#include <linux/perf_event.h>
@@ -88,12 +89,12 @@ struct intel_uncore_type {
* to identify which platform component each PMON block of that type is
* supposed to monitor.
*/
- struct intel_uncore_topology *topology;
+ struct intel_uncore_topology **topology;
/*
* Optional callbacks for managing mapping of Uncore units to PMONs
*/
int (*get_topology)(struct intel_uncore_type *type);
- int (*set_mapping)(struct intel_uncore_type *type);
+ void (*set_mapping)(struct intel_uncore_type *type);
void (*cleanup_mapping)(struct intel_uncore_type *type);
};
@@ -178,11 +179,26 @@ struct freerunning_counters {
unsigned *box_offsets;
};
-struct intel_uncore_topology {
- u64 configuration;
+struct uncore_iio_topology {
+ int pci_bus_no;
int segment;
};
+struct uncore_upi_topology {
+ int die_to;
+ int pmu_idx_to;
+ int enabled;
+};
+
+struct intel_uncore_topology {
+ int pmu_idx;
+ union {
+ void *untyped;
+ struct uncore_iio_topology *iio;
+ struct uncore_upi_topology *upi;
+ };
+};
+
struct pci2phy_map {
struct list_head list;
int segment;
diff --git a/arch/x86/events/intel/uncore_snb.c b/arch/x86/events/intel/uncore_snb.c
index 1ef4f7861e2e..1f4869227efb 100644
--- a/arch/x86/events/intel/uncore_snb.c
+++ b/arch/x86/events/intel/uncore_snb.c
@@ -1338,6 +1338,7 @@ static void __uncore_imc_init_box(struct intel_uncore_box *box,
/* MCHBAR is disabled */
if (!(mch_bar & BIT(0))) {
pr_warn("perf uncore: MCHBAR is disabled. Failed to map IMC free-running counters.\n");
+ pci_dev_put(pdev);
return;
}
mch_bar &= ~BIT(0);
@@ -1352,6 +1353,8 @@ static void __uncore_imc_init_box(struct intel_uncore_box *box,
box->io_addr = ioremap(addr, type->mmio_map_size);
if (!box->io_addr)
pr_warn("perf uncore: Failed to ioremap for %s.\n", type->name);
+
+ pci_dev_put(pdev);
}
static void tgl_uncore_imc_freerunning_init_box(struct intel_uncore_box *box)
diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index ed869443efb2..44c2f879f708 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -445,6 +445,7 @@
#define ICX_UPI_PCI_PMON_CTR0 0x320
#define ICX_UPI_PCI_PMON_BOX_CTL 0x318
#define ICX_UPI_CTL_UMASK_EXT 0xffffff
+#define ICX_UBOX_DID 0x3450
/* ICX M3UPI*/
#define ICX_M3UPI_PCI_PMON_CTL0 0xd8
@@ -457,6 +458,7 @@
/* SPR */
#define SPR_RAW_EVENT_MASK_EXT 0xffffff
+#define SPR_UBOX_DID 0x3250
/* SPR CHA */
#define SPR_CHA_PMON_CTL_TID_EN (1 << 16)
@@ -1372,6 +1374,28 @@ static struct pci_driver snbep_uncore_pci_driver = {
#define NODE_ID_MASK 0x7
+/* Each three bits from 0 to 23 of GIDNIDMAP register correspond Node ID. */
+#define GIDNIDMAP(config, id) (((config) >> (3 * (id))) & 0x7)
+
+static int upi_nodeid_groupid(struct pci_dev *ubox_dev, int nodeid_loc, int idmap_loc,
+ int *nodeid, int *groupid)
+{
+ int ret;
+
+ /* get the Node ID of the local register */
+ ret = pci_read_config_dword(ubox_dev, nodeid_loc, nodeid);
+ if (ret)
+ goto err;
+
+ *nodeid = *nodeid & NODE_ID_MASK;
+ /* get the Node ID mapping */
+ ret = pci_read_config_dword(ubox_dev, idmap_loc, groupid);
+ if (ret)
+ goto err;
+err:
+ return ret;
+}
+
/*
* build pci bus to socket mapping
*/
@@ -1397,13 +1421,8 @@ static int snbep_pci2phy_map_init(int devid, int nodeid_loc, int idmap_loc, bool
* the topology.
*/
if (nr_node_ids <= 8) {
- /* get the Node ID of the local register */
- err = pci_read_config_dword(ubox_dev, nodeid_loc, &config);
- if (err)
- break;
- nodeid = config & NODE_ID_MASK;
- /* get the Node ID mapping */
- err = pci_read_config_dword(ubox_dev, idmap_loc, &config);
+ err = upi_nodeid_groupid(ubox_dev, nodeid_loc, idmap_loc,
+ &nodeid, &config);
if (err)
break;
@@ -1421,7 +1440,7 @@ static int snbep_pci2phy_map_init(int devid, int nodeid_loc, int idmap_loc, bool
* to a particular node.
*/
for (i = 0; i < 8; i++) {
- if (nodeid == ((config >> (3 * i)) & 0x7)) {
+ if (nodeid == GIDNIDMAP(config, i)) {
if (topology_max_die_per_package() > 1)
die_id = i;
else
@@ -2891,6 +2910,7 @@ static bool hswep_has_limit_sbox(unsigned int device)
return false;
pci_read_config_dword(dev, HSWEP_PCU_CAPID4_OFFET, &capid4);
+ pci_dev_put(dev);
if (!hswep_get_chop(capid4))
return true;
@@ -3699,10 +3719,16 @@ static struct intel_uncore_ops skx_uncore_iio_ops = {
.read_counter = uncore_msr_read_counter,
};
-static inline u8 skx_iio_stack(struct intel_uncore_pmu *pmu, int die)
+static struct intel_uncore_topology *pmu_topology(struct intel_uncore_pmu *pmu, int die)
{
- return pmu->type->topology[die].configuration >>
- (pmu->pmu_idx * BUS_NUM_STRIDE);
+ int idx;
+
+ for (idx = 0; idx < pmu->type->num_boxes; idx++) {
+ if (pmu->type->topology[die][idx].pmu_idx == pmu->pmu_idx)
+ return &pmu->type->topology[die][idx];
+ }
+
+ return NULL;
}
static umode_t
@@ -3710,8 +3736,9 @@ pmu_iio_mapping_visible(struct kobject *kobj, struct attribute *attr,
int die, int zero_bus_pmu)
{
struct intel_uncore_pmu *pmu = dev_to_uncore_pmu(kobj_to_dev(kobj));
+ struct intel_uncore_topology *pmut = pmu_topology(pmu, die);
- return (!skx_iio_stack(pmu, die) && pmu->pmu_idx != zero_bus_pmu) ? 0 : attr->mode;
+ return (pmut && !pmut->iio->pci_bus_no && pmu->pmu_idx != zero_bus_pmu) ? 0 : attr->mode;
}
static umode_t
@@ -3727,9 +3754,10 @@ static ssize_t skx_iio_mapping_show(struct device *dev,
struct intel_uncore_pmu *pmu = dev_to_uncore_pmu(dev);
struct dev_ext_attribute *ea = to_dev_ext_attribute(attr);
long die = (long)ea->var;
+ struct intel_uncore_topology *pmut = pmu_topology(pmu, die);
- return sprintf(buf, "%04x:%02x\n", pmu->type->topology[die].segment,
- skx_iio_stack(pmu, die));
+ return sprintf(buf, "%04x:%02x\n", pmut ? pmut->iio->segment : 0,
+ pmut ? pmut->iio->pci_bus_no : 0);
}
static int skx_msr_cpu_bus_read(int cpu, u64 *topology)
@@ -3764,18 +3792,79 @@ static int die_to_cpu(int die)
return res;
}
-static int skx_iio_get_topology(struct intel_uncore_type *type)
+enum {
+ IIO_TOPOLOGY_TYPE,
+ UPI_TOPOLOGY_TYPE,
+ TOPOLOGY_MAX
+};
+
+static const size_t topology_size[TOPOLOGY_MAX] = {
+ sizeof(*((struct intel_uncore_topology *)NULL)->iio),
+ sizeof(*((struct intel_uncore_topology *)NULL)->upi)
+};
+
+static int pmu_alloc_topology(struct intel_uncore_type *type, int topology_type)
{
- int die, ret = -EPERM;
+ int die, idx;
+ struct intel_uncore_topology **topology;
+
+ if (!type->num_boxes)
+ return -EPERM;
- type->topology = kcalloc(uncore_max_dies(), sizeof(*type->topology),
- GFP_KERNEL);
- if (!type->topology)
- return -ENOMEM;
+ topology = kcalloc(uncore_max_dies(), sizeof(*topology), GFP_KERNEL);
+ if (!topology)
+ goto err;
for (die = 0; die < uncore_max_dies(); die++) {
- ret = skx_msr_cpu_bus_read(die_to_cpu(die),
- &type->topology[die].configuration);
+ topology[die] = kcalloc(type->num_boxes, sizeof(**topology), GFP_KERNEL);
+ if (!topology[die])
+ goto clear;
+ for (idx = 0; idx < type->num_boxes; idx++) {
+ topology[die][idx].untyped = kcalloc(type->num_boxes,
+ topology_size[topology_type],
+ GFP_KERNEL);
+ if (!topology[die][idx].untyped)
+ goto clear;
+ }
+ }
+
+ type->topology = topology;
+
+ return 0;
+clear:
+ for (; die >= 0; die--) {
+ for (idx = 0; idx < type->num_boxes; idx++)
+ kfree(topology[die][idx].untyped);
+ kfree(topology[die]);
+ }
+ kfree(topology);
+err:
+ return -ENOMEM;
+}
+
+static void pmu_free_topology(struct intel_uncore_type *type)
+{
+ int die, idx;
+
+ if (type->topology) {
+ for (die = 0; die < uncore_max_dies(); die++) {
+ for (idx = 0; idx < type->num_boxes; idx++)
+ kfree(type->topology[die][idx].untyped);
+ kfree(type->topology[die]);
+ }
+ kfree(type->topology);
+ type->topology = NULL;
+ }
+}
+
+static int skx_pmu_get_topology(struct intel_uncore_type *type,
+ int (*topology_cb)(struct intel_uncore_type*, int, int, u64))
+{
+ int die, ret = -EPERM;
+ u64 cpu_bus_msr;
+
+ for (die = 0; die < uncore_max_dies(); die++) {
+ ret = skx_msr_cpu_bus_read(die_to_cpu(die), &cpu_bus_msr);
if (ret)
break;
@@ -3783,15 +3872,33 @@ static int skx_iio_get_topology(struct intel_uncore_type *type)
if (ret < 0)
break;
- type->topology[die].segment = ret;
+ ret = topology_cb(type, ret, die, cpu_bus_msr);
+ if (ret)
+ break;
}
- if (ret < 0) {
- kfree(type->topology);
- type->topology = NULL;
+ return ret;
+}
+
+static int skx_iio_topology_cb(struct intel_uncore_type *type, int segment,
+ int die, u64 cpu_bus_msr)
+{
+ int idx;
+ struct intel_uncore_topology *t;
+
+ for (idx = 0; idx < type->num_boxes; idx++) {
+ t = &type->topology[die][idx];
+ t->pmu_idx = idx;
+ t->iio->segment = segment;
+ t->iio->pci_bus_no = (cpu_bus_msr >> (idx * BUS_NUM_STRIDE)) & 0xff;
}
- return ret;
+ return 0;
+}
+
+static int skx_iio_get_topology(struct intel_uncore_type *type)
+{
+ return skx_pmu_get_topology(type, skx_iio_topology_cb);
}
static struct attribute_group skx_iio_mapping_group = {
@@ -3803,8 +3910,25 @@ static const struct attribute_group *skx_iio_attr_update[] = {
NULL,
};
-static int
-pmu_iio_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
+static void pmu_clear_mapping_attr(const struct attribute_group **groups,
+ struct attribute_group *ag)
+{
+ int i;
+
+ for (i = 0; groups[i]; i++) {
+ if (groups[i] == ag) {
+ for (i++; groups[i]; i++)
+ groups[i - 1] = groups[i];
+ groups[i - 1] = NULL;
+ break;
+ }
+ }
+}
+
+static void
+pmu_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag,
+ ssize_t (*show)(struct device*, struct device_attribute*, char*),
+ int topology_type)
{
char buf[64];
int ret;
@@ -3812,11 +3936,13 @@ pmu_iio_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
struct attribute **attrs = NULL;
struct dev_ext_attribute *eas = NULL;
- ret = type->get_topology(type);
+ ret = pmu_alloc_topology(type, topology_type);
if (ret < 0)
goto clear_attr_update;
- ret = -ENOMEM;
+ ret = type->get_topology(type);
+ if (ret < 0)
+ goto clear_topology;
/* One more for NULL. */
attrs = kcalloc((uncore_max_dies() + 1), sizeof(*attrs), GFP_KERNEL);
@@ -3828,20 +3954,20 @@ pmu_iio_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
goto clear_attrs;
for (die = 0; die < uncore_max_dies(); die++) {
- sprintf(buf, "die%ld", die);
+ snprintf(buf, sizeof(buf), "die%ld", die);
sysfs_attr_init(&eas[die].attr.attr);
eas[die].attr.attr.name = kstrdup(buf, GFP_KERNEL);
if (!eas[die].attr.attr.name)
goto err;
eas[die].attr.attr.mode = 0444;
- eas[die].attr.show = skx_iio_mapping_show;
+ eas[die].attr.show = show;
eas[die].attr.store = NULL;
eas[die].var = (void *)die;
attrs[die] = &eas[die].attr.attr;
}
ag->attrs = attrs;
- return 0;
+ return;
err:
for (; die >= 0; die--)
kfree(eas[die].attr.attr.name);
@@ -3849,14 +3975,13 @@ err:
clear_attrs:
kfree(attrs);
clear_topology:
- kfree(type->topology);
+ pmu_free_topology(type);
clear_attr_update:
- type->attr_update = NULL;
- return ret;
+ pmu_clear_mapping_attr(type->attr_update, ag);
}
static void
-pmu_iio_cleanup_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
+pmu_cleanup_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
{
struct attribute **attr = ag->attrs;
@@ -3868,17 +3993,23 @@ pmu_iio_cleanup_mapping(struct intel_uncore_type *type, struct attribute_group *
kfree(attr_to_ext_attr(*ag->attrs));
kfree(ag->attrs);
ag->attrs = NULL;
- kfree(type->topology);
+ pmu_free_topology(type);
+}
+
+static void
+pmu_iio_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
+{
+ pmu_set_mapping(type, ag, skx_iio_mapping_show, IIO_TOPOLOGY_TYPE);
}
-static int skx_iio_set_mapping(struct intel_uncore_type *type)
+static void skx_iio_set_mapping(struct intel_uncore_type *type)
{
- return pmu_iio_set_mapping(type, &skx_iio_mapping_group);
+ pmu_iio_set_mapping(type, &skx_iio_mapping_group);
}
static void skx_iio_cleanup_mapping(struct intel_uncore_type *type)
{
- pmu_iio_cleanup_mapping(type, &skx_iio_mapping_group);
+ pmu_cleanup_mapping(type, &skx_iio_mapping_group);
}
static struct intel_uncore_type skx_uncore_iio = {
@@ -4139,6 +4270,132 @@ static struct intel_uncore_ops skx_upi_uncore_pci_ops = {
.read_counter = snbep_uncore_pci_read_counter,
};
+static umode_t
+skx_upi_mapping_visible(struct kobject *kobj, struct attribute *attr, int die)
+{
+ struct intel_uncore_pmu *pmu = dev_to_uncore_pmu(kobj_to_dev(kobj));
+
+ return pmu->type->topology[die][pmu->pmu_idx].upi->enabled ? attr->mode : 0;
+}
+
+static ssize_t skx_upi_mapping_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct intel_uncore_pmu *pmu = dev_to_uncore_pmu(dev);
+ struct dev_ext_attribute *ea = to_dev_ext_attribute(attr);
+ long die = (long)ea->var;
+ struct uncore_upi_topology *upi = pmu->type->topology[die][pmu->pmu_idx].upi;
+
+ return sysfs_emit(buf, "upi_%d,die_%d\n", upi->pmu_idx_to, upi->die_to);
+}
+
+#define SKX_UPI_REG_DID 0x2058
+#define SKX_UPI_REGS_ADDR_DEVICE_LINK0 0x0e
+#define SKX_UPI_REGS_ADDR_FUNCTION 0x00
+
+/*
+ * UPI Link Parameter 0
+ * | Bit | Default | Description
+ * | 19:16 | 0h | base_nodeid - The NodeID of the sending socket.
+ * | 12:8 | 00h | sending_port - The processor die port number of the sending port.
+ */
+#define SKX_KTILP0_OFFSET 0x94
+
+/*
+ * UPI Pcode Status. This register is used by PCode to store the link training status.
+ * | Bit | Default | Description
+ * | 4 | 0h | ll_status_valid — Bit indicates the valid training status
+ * logged from PCode to the BIOS.
+ */
+#define SKX_KTIPCSTS_OFFSET 0x120
+
+static int upi_fill_topology(struct pci_dev *dev, struct intel_uncore_topology *tp,
+ int pmu_idx)
+{
+ int ret;
+ u32 upi_conf;
+ struct uncore_upi_topology *upi = tp->upi;
+
+ tp->pmu_idx = pmu_idx;
+ ret = pci_read_config_dword(dev, SKX_KTIPCSTS_OFFSET, &upi_conf);
+ if (ret) {
+ ret = pcibios_err_to_errno(ret);
+ goto err;
+ }
+ upi->enabled = (upi_conf >> 4) & 1;
+ if (upi->enabled) {
+ ret = pci_read_config_dword(dev, SKX_KTILP0_OFFSET,
+ &upi_conf);
+ if (ret) {
+ ret = pcibios_err_to_errno(ret);
+ goto err;
+ }
+ upi->die_to = (upi_conf >> 16) & 0xf;
+ upi->pmu_idx_to = (upi_conf >> 8) & 0x1f;
+ }
+err:
+ return ret;
+}
+
+static int skx_upi_topology_cb(struct intel_uncore_type *type, int segment,
+ int die, u64 cpu_bus_msr)
+{
+ int idx, ret;
+ struct intel_uncore_topology *upi;
+ unsigned int devfn;
+ struct pci_dev *dev = NULL;
+ u8 bus = cpu_bus_msr >> (3 * BUS_NUM_STRIDE);
+
+ for (idx = 0; idx < type->num_boxes; idx++) {
+ upi = &type->topology[die][idx];
+ devfn = PCI_DEVFN(SKX_UPI_REGS_ADDR_DEVICE_LINK0 + idx,
+ SKX_UPI_REGS_ADDR_FUNCTION);
+ dev = pci_get_domain_bus_and_slot(segment, bus, devfn);
+ if (dev) {
+ ret = upi_fill_topology(dev, upi, idx);
+ if (ret)
+ break;
+ }
+ }
+
+ pci_dev_put(dev);
+ return ret;
+}
+
+static int skx_upi_get_topology(struct intel_uncore_type *type)
+{
+ /* CPX case is not supported */
+ if (boot_cpu_data.x86_stepping == 11)
+ return -EPERM;
+
+ return skx_pmu_get_topology(type, skx_upi_topology_cb);
+}
+
+static struct attribute_group skx_upi_mapping_group = {
+ .is_visible = skx_upi_mapping_visible,
+};
+
+static const struct attribute_group *skx_upi_attr_update[] = {
+ &skx_upi_mapping_group,
+ NULL
+};
+
+static void
+pmu_upi_set_mapping(struct intel_uncore_type *type, struct attribute_group *ag)
+{
+ pmu_set_mapping(type, ag, skx_upi_mapping_show, UPI_TOPOLOGY_TYPE);
+}
+
+static void skx_upi_set_mapping(struct intel_uncore_type *type)
+{
+ pmu_upi_set_mapping(type, &skx_upi_mapping_group);
+}
+
+static void skx_upi_cleanup_mapping(struct intel_uncore_type *type)
+{
+ pmu_cleanup_mapping(type, &skx_upi_mapping_group);
+}
+
static struct intel_uncore_type skx_uncore_upi = {
.name = "upi",
.num_counters = 4,
@@ -4151,6 +4408,10 @@ static struct intel_uncore_type skx_uncore_upi = {
.box_ctl = SKX_UPI_PCI_PMON_BOX_CTL,
.ops = &skx_upi_uncore_pci_ops,
.format_group = &skx_upi_uncore_format_group,
+ .attr_update = skx_upi_attr_update,
+ .get_topology = skx_upi_get_topology,
+ .set_mapping = skx_upi_set_mapping,
+ .cleanup_mapping = skx_upi_cleanup_mapping,
};
static void skx_m2m_uncore_pci_init_box(struct intel_uncore_box *box)
@@ -4461,11 +4722,6 @@ static int sad_cfg_iio_topology(struct intel_uncore_type *type, u8 *sad_pmon_map
int die, stack_id, ret = -EPERM;
struct pci_dev *dev = NULL;
- type->topology = kcalloc(uncore_max_dies(), sizeof(*type->topology),
- GFP_KERNEL);
- if (!type->topology)
- return -ENOMEM;
-
while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL, SNR_ICX_MESH2IIO_MMAP_DID, dev))) {
ret = pci_read_config_dword(dev, SNR_ICX_SAD_CONTROL_CFG, &sad_cfg);
if (ret) {
@@ -4483,14 +4739,12 @@ static int sad_cfg_iio_topology(struct intel_uncore_type *type, u8 *sad_pmon_map
/* Convert stack id from SAD_CONTROL to PMON notation. */
stack_id = sad_pmon_mapping[stack_id];
- ((u8 *)&(type->topology[die].configuration))[stack_id] = dev->bus->number;
- type->topology[die].segment = pci_domain_nr(dev->bus);
+ type->topology[die][stack_id].iio->segment = pci_domain_nr(dev->bus);
+ type->topology[die][stack_id].pmu_idx = stack_id;
+ type->topology[die][stack_id].iio->pci_bus_no = dev->bus->number;
}
- if (ret) {
- kfree(type->topology);
- type->topology = NULL;
- }
+ pci_dev_put(dev);
return ret;
}
@@ -4519,14 +4773,14 @@ static int snr_iio_get_topology(struct intel_uncore_type *type)
return sad_cfg_iio_topology(type, snr_sad_pmon_mapping);
}
-static int snr_iio_set_mapping(struct intel_uncore_type *type)
+static void snr_iio_set_mapping(struct intel_uncore_type *type)
{
- return pmu_iio_set_mapping(type, &snr_iio_mapping_group);
+ pmu_iio_set_mapping(type, &snr_iio_mapping_group);
}
static void snr_iio_cleanup_mapping(struct intel_uncore_type *type)
{
- pmu_iio_cleanup_mapping(type, &snr_iio_mapping_group);
+ pmu_cleanup_mapping(type, &snr_iio_mapping_group);
}
static struct event_constraint snr_uncore_iio_constraints[] = {
@@ -4857,6 +5111,8 @@ static int snr_uncore_mmio_map(struct intel_uncore_box *box,
addr += box_ctl;
+ pci_dev_put(pdev);
+
box->io_addr = ioremap(addr, type->mmio_map_size);
if (!box->io_addr) {
pr_warn("perf uncore: Failed to ioremap for %s.\n", type->name);
@@ -5137,14 +5393,19 @@ static int icx_iio_get_topology(struct intel_uncore_type *type)
return sad_cfg_iio_topology(type, icx_sad_pmon_mapping);
}
-static int icx_iio_set_mapping(struct intel_uncore_type *type)
+static void icx_iio_set_mapping(struct intel_uncore_type *type)
{
- return pmu_iio_set_mapping(type, &icx_iio_mapping_group);
+ /* Detect ICX-D system. This case is not supported */
+ if (boot_cpu_data.x86_model == INTEL_FAM6_ICELAKE_D) {
+ pmu_clear_mapping_attr(type->attr_update, &icx_iio_mapping_group);
+ return;
+ }
+ pmu_iio_set_mapping(type, &icx_iio_mapping_group);
}
static void icx_iio_cleanup_mapping(struct intel_uncore_type *type)
{
- pmu_iio_cleanup_mapping(type, &icx_iio_mapping_group);
+ pmu_cleanup_mapping(type, &icx_iio_mapping_group);
}
static struct intel_uncore_type icx_uncore_iio = {
@@ -5337,6 +5598,76 @@ static const struct attribute_group icx_upi_uncore_format_group = {
.attrs = icx_upi_uncore_formats_attr,
};
+#define ICX_UPI_REGS_ADDR_DEVICE_LINK0 0x02
+#define ICX_UPI_REGS_ADDR_FUNCTION 0x01
+
+static int discover_upi_topology(struct intel_uncore_type *type, int ubox_did, int dev_link0)
+{
+ struct pci_dev *ubox = NULL;
+ struct pci_dev *dev = NULL;
+ u32 nid, gid;
+ int i, idx, ret = -EPERM;
+ struct intel_uncore_topology *upi;
+ unsigned int devfn;
+
+ /* GIDNIDMAP method supports machines which have less than 8 sockets. */
+ if (uncore_max_dies() > 8)
+ goto err;
+
+ while ((ubox = pci_get_device(PCI_VENDOR_ID_INTEL, ubox_did, ubox))) {
+ ret = upi_nodeid_groupid(ubox, SKX_CPUNODEID, SKX_GIDNIDMAP, &nid, &gid);
+ if (ret) {
+ ret = pcibios_err_to_errno(ret);
+ break;
+ }
+
+ for (i = 0; i < 8; i++) {
+ if (nid != GIDNIDMAP(gid, i))
+ continue;
+ for (idx = 0; idx < type->num_boxes; idx++) {
+ upi = &type->topology[nid][idx];
+ devfn = PCI_DEVFN(dev_link0 + idx, ICX_UPI_REGS_ADDR_FUNCTION);
+ dev = pci_get_domain_bus_and_slot(pci_domain_nr(ubox->bus),
+ ubox->bus->number,
+ devfn);
+ if (dev) {
+ ret = upi_fill_topology(dev, upi, idx);
+ if (ret)
+ goto err;
+ }
+ }
+ }
+ }
+err:
+ pci_dev_put(ubox);
+ pci_dev_put(dev);
+ return ret;
+}
+
+static int icx_upi_get_topology(struct intel_uncore_type *type)
+{
+ return discover_upi_topology(type, ICX_UBOX_DID, ICX_UPI_REGS_ADDR_DEVICE_LINK0);
+}
+
+static struct attribute_group icx_upi_mapping_group = {
+ .is_visible = skx_upi_mapping_visible,
+};
+
+static const struct attribute_group *icx_upi_attr_update[] = {
+ &icx_upi_mapping_group,
+ NULL
+};
+
+static void icx_upi_set_mapping(struct intel_uncore_type *type)
+{
+ pmu_upi_set_mapping(type, &icx_upi_mapping_group);
+}
+
+static void icx_upi_cleanup_mapping(struct intel_uncore_type *type)
+{
+ pmu_cleanup_mapping(type, &icx_upi_mapping_group);
+}
+
static struct intel_uncore_type icx_uncore_upi = {
.name = "upi",
.num_counters = 4,
@@ -5349,6 +5680,10 @@ static struct intel_uncore_type icx_uncore_upi = {
.box_ctl = ICX_UPI_PCI_PMON_BOX_CTL,
.ops = &skx_upi_uncore_pci_ops,
.format_group = &icx_upi_uncore_format_group,
+ .attr_update = icx_upi_attr_update,
+ .get_topology = icx_upi_get_topology,
+ .set_mapping = icx_upi_set_mapping,
+ .cleanup_mapping = icx_upi_cleanup_mapping,
};
static struct event_constraint icx_uncore_m3upi_constraints[] = {
@@ -5780,9 +6115,43 @@ static struct intel_uncore_type spr_uncore_m2m = {
.name = "m2m",
};
+static struct attribute_group spr_upi_mapping_group = {
+ .is_visible = skx_upi_mapping_visible,
+};
+
+static const struct attribute_group *spr_upi_attr_update[] = {
+ &uncore_alias_group,
+ &spr_upi_mapping_group,
+ NULL
+};
+
+#define SPR_UPI_REGS_ADDR_DEVICE_LINK0 0x01
+
+static void spr_upi_set_mapping(struct intel_uncore_type *type)
+{
+ pmu_upi_set_mapping(type, &spr_upi_mapping_group);
+}
+
+static void spr_upi_cleanup_mapping(struct intel_uncore_type *type)
+{
+ pmu_cleanup_mapping(type, &spr_upi_mapping_group);
+}
+
+static int spr_upi_get_topology(struct intel_uncore_type *type)
+{
+ return discover_upi_topology(type, SPR_UBOX_DID, SPR_UPI_REGS_ADDR_DEVICE_LINK0);
+}
+
static struct intel_uncore_type spr_uncore_upi = {
- SPR_UNCORE_PCI_COMMON_FORMAT(),
+ .event_mask = SNBEP_PMON_RAW_EVENT_MASK,
+ .event_mask_ext = SPR_RAW_EVENT_MASK_EXT,
+ .format_group = &spr_uncore_raw_format_group,
+ .ops = &spr_uncore_pci_ops,
.name = "upi",
+ .attr_update = spr_upi_attr_update,
+ .get_topology = spr_upi_get_topology,
+ .set_mapping = spr_upi_set_mapping,
+ .cleanup_mapping = spr_upi_cleanup_mapping,
};
static struct intel_uncore_type spr_uncore_m3upi = {
@@ -5986,6 +6355,12 @@ static void uncore_type_customized_copy(struct intel_uncore_type *to_type,
to_type->format_group = from_type->format_group;
if (from_type->attr_update)
to_type->attr_update = from_type->attr_update;
+ if (from_type->set_mapping)
+ to_type->set_mapping = from_type->set_mapping;
+ if (from_type->get_topology)
+ to_type->get_topology = from_type->get_topology;
+ if (from_type->cleanup_mapping)
+ to_type->cleanup_mapping = from_type->cleanup_mapping;
}
static struct intel_uncore_type **
diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
index 332d2e6d8ae4..0e849f28a5c1 100644
--- a/arch/x86/events/perf_event.h
+++ b/arch/x86/events/perf_event.h
@@ -811,7 +811,7 @@ struct x86_pmu {
void (*cpu_dead)(int cpu);
void (*check_microcode)(void);
- void (*sched_task)(struct perf_event_context *ctx,
+ void (*sched_task)(struct perf_event_pmu_context *pmu_ctx,
bool sched_in);
/*
@@ -894,12 +894,12 @@ struct x86_pmu {
int num_topdown_events;
/*
- * perf task context (i.e. struct perf_event_context::task_ctx_data)
+ * perf task context (i.e. struct perf_event_pmu_context::task_ctx_data)
* switch helper to bridge calls from perf/core to perf/x86.
* See struct pmu::swap_task_ctx() usage for examples;
*/
- void (*swap_task_ctx)(struct perf_event_context *prev,
- struct perf_event_context *next);
+ void (*swap_task_ctx)(struct perf_event_pmu_context *prev_epc,
+ struct perf_event_pmu_context *next_epc);
/*
* AMD bits
@@ -925,7 +925,7 @@ struct x86_pmu {
int (*aux_output_match) (struct perf_event *event);
- int (*filter_match)(struct perf_event *event);
+ void (*filter)(struct pmu *pmu, int cpu, bool *ret);
/*
* Hybrid support
*
@@ -1180,8 +1180,6 @@ int x86_pmu_handle_irq(struct pt_regs *regs);
void x86_pmu_show_pmu_cap(int num_counters, int num_counters_fixed,
u64 intel_ctrl);
-void x86_pmu_update_cpu_context(struct pmu *pmu, int cpu);
-
extern struct event_constraint emptyconstraint;
extern struct event_constraint unconstrained;
@@ -1306,7 +1304,7 @@ void amd_pmu_lbr_reset(void);
void amd_pmu_lbr_read(void);
void amd_pmu_lbr_add(struct perf_event *event);
void amd_pmu_lbr_del(struct perf_event *event);
-void amd_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in);
+void amd_pmu_lbr_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in);
void amd_pmu_lbr_enable_all(void);
void amd_pmu_lbr_disable_all(void);
int amd_pmu_lbr_hw_config(struct perf_event *event);
@@ -1322,7 +1320,6 @@ void amd_brs_enable_all(void);
void amd_brs_disable_all(void);
void amd_brs_drain(void);
void amd_brs_lopwr_init(void);
-void amd_brs_disable_all(void);
int amd_brs_hw_config(struct perf_event *event);
void amd_brs_reset(void);
@@ -1330,7 +1327,7 @@ static inline void amd_pmu_brs_add(struct perf_event *event)
{
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
- perf_sched_cb_inc(event->ctx->pmu);
+ perf_sched_cb_inc(event->pmu);
cpuc->lbr_users++;
/*
* No need to reset BRS because it is reset
@@ -1345,10 +1342,10 @@ static inline void amd_pmu_brs_del(struct perf_event *event)
cpuc->lbr_users--;
WARN_ON_ONCE(cpuc->lbr_users < 0);
- perf_sched_cb_dec(event->ctx->pmu);
+ perf_sched_cb_dec(event->pmu);
}
-void amd_pmu_brs_sched_task(struct perf_event_context *ctx, bool sched_in);
+void amd_pmu_brs_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in);
#else
static inline int amd_brs_init(void)
{
@@ -1373,7 +1370,7 @@ static inline void amd_pmu_brs_del(struct perf_event *event)
{
}
-static inline void amd_pmu_brs_sched_task(struct perf_event_context *ctx, bool sched_in)
+static inline void amd_pmu_brs_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in)
{
}
@@ -1533,7 +1530,7 @@ void intel_pmu_pebs_enable_all(void);
void intel_pmu_pebs_disable_all(void);
-void intel_pmu_pebs_sched_task(struct perf_event_context *ctx, bool sched_in);
+void intel_pmu_pebs_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in);
void intel_pmu_auto_reload_read(struct perf_event *event);
@@ -1541,10 +1538,10 @@ void intel_pmu_store_pebs_lbrs(struct lbr_entry *lbr);
void intel_ds_init(void);
-void intel_pmu_lbr_swap_task_ctx(struct perf_event_context *prev,
- struct perf_event_context *next);
+void intel_pmu_lbr_swap_task_ctx(struct perf_event_pmu_context *prev_epc,
+ struct perf_event_pmu_context *next_epc);
-void intel_pmu_lbr_sched_task(struct perf_event_context *ctx, bool sched_in);
+void intel_pmu_lbr_sched_task(struct perf_event_pmu_context *pmu_ctx, bool sched_in);
u64 lbr_from_signext_quirk_wr(u64 val);
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index a269049a43ce..41ef036ebb7b 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -462,6 +462,8 @@ void __init hyperv_init(void)
BUG_ON(!src);
memcpy_to_page(pg, 0, src, HV_HYP_PAGE_SIZE);
memunmap(src);
+
+ hv_remap_tsc_clocksource();
} else {
hypercall_msr.guest_physical_address = vmalloc_to_pfn(hv_hypercall_pg);
wrmsrl(HV_X64_MSR_HYPERCALL, hypercall_msr.as_uint64);
@@ -535,8 +537,6 @@ void hyperv_cleanup(void)
union hv_x64_msr_hypercall_contents hypercall_msr;
union hv_reference_tsc_msr tsc_msr;
- unregister_syscore_ops(&hv_syscore_ops);
-
/* Reset our OS id */
wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
hv_ghcb_msr_write(HV_X64_MSR_GUEST_OS_ID, 0);
diff --git a/arch/x86/ia32/Makefile b/arch/x86/ia32/Makefile
index e481056698de..333556a86b2a 100644
--- a/arch/x86/ia32/Makefile
+++ b/arch/x86/ia32/Makefile
@@ -3,7 +3,5 @@
# Makefile for the ia32 kernel emulation subsystem.
#
-obj-$(CONFIG_IA32_EMULATION) := ia32_signal.o
-
audit-class-$(CONFIG_AUDIT) := audit.o
obj-$(CONFIG_IA32_EMULATION) += $(audit-class-y)
diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h
index 3415321c8240..3216da7074ba 100644
--- a/arch/x86/include/asm/apic.h
+++ b/arch/x86/include/asm/apic.h
@@ -249,7 +249,6 @@ static inline u64 native_x2apic_icr_read(void)
extern int x2apic_mode;
extern int x2apic_phys;
extern void __init x2apic_set_max_apicid(u32 apicid);
-extern void __init check_x2apic(void);
extern void x2apic_setup(void);
static inline int x2apic_enabled(void)
{
@@ -258,13 +257,13 @@ static inline int x2apic_enabled(void)
#define x2apic_supported() (boot_cpu_has(X86_FEATURE_X2APIC))
#else /* !CONFIG_X86_X2APIC */
-static inline void check_x2apic(void) { }
static inline void x2apic_setup(void) { }
static inline int x2apic_enabled(void) { return 0; }
#define x2apic_mode (0)
#define x2apic_supported() (0)
#endif /* !CONFIG_X86_X2APIC */
+extern void __init check_x2apic(void);
struct irq_data;
diff --git a/arch/x86/include/asm/cacheinfo.h b/arch/x86/include/asm/cacheinfo.h
index 86b2e0dcc4bf..ce9685fc78d8 100644
--- a/arch/x86/include/asm/cacheinfo.h
+++ b/arch/x86/include/asm/cacheinfo.h
@@ -2,7 +2,20 @@
#ifndef _ASM_X86_CACHEINFO_H
#define _ASM_X86_CACHEINFO_H
+/* Kernel controls MTRR and/or PAT MSRs. */
+extern unsigned int memory_caching_control;
+#define CACHE_MTRR 0x01
+#define CACHE_PAT 0x02
+
void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu);
void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu);
+void cache_disable(void);
+void cache_enable(void);
+void set_cache_aps_delayed_init(bool val);
+bool get_cache_aps_delayed_init(void);
+void cache_bp_init(void);
+void cache_bp_restore(void);
+void cache_aps_init(void);
+
#endif /* _ASM_X86_CACHEINFO_H */
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index b472ef76826a..78796b98a544 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -95,5 +95,7 @@ static inline bool intel_cpu_signatures_match(unsigned int s1, unsigned int p1,
}
extern u64 x86_read_arch_cap_msr(void);
+int intel_find_matching_signature(void *mc, unsigned int csig, int cpf);
+int intel_microcode_sanity_check(void *mc, bool print_err, int hdr_type);
#endif /* _ASM_X86_CPU_H */
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index b2da7cb64b31..c9f4730bb113 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -304,6 +304,7 @@
#define X86_FEATURE_UNRET (11*32+15) /* "" AMD BTB untrain return */
#define X86_FEATURE_USE_IBPB_FW (11*32+16) /* "" Use IBPB during runtime firmware calls */
#define X86_FEATURE_RSB_VMEXIT_LITE (11*32+17) /* "" Fill RSB on VM exit when EIBRS is enabled */
+#define X86_FEATURE_SGX_EDECCSSA (11*32+18) /* "" SGX EDECCSSA user leaf function */
#define X86_FEATURE_MSR_TSX_CTRL (11*32+20) /* "" MSR IA32_TSX_CTRL (Intel) implemented */
diff --git a/arch/x86/include/asm/cpuid.h b/arch/x86/include/asm/cpuid.h
index 70b2db18165e..9bee3e7bf973 100644
--- a/arch/x86/include/asm/cpuid.h
+++ b/arch/x86/include/asm/cpuid.h
@@ -1,13 +1,132 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* CPUID-related helpers/definitions
- *
- * Derived from arch/x86/kvm/cpuid.c
*/
#ifndef _ASM_X86_CPUID_H
#define _ASM_X86_CPUID_H
+#include <asm/string.h>
+
+struct cpuid_regs {
+ u32 eax, ebx, ecx, edx;
+};
+
+enum cpuid_regs_idx {
+ CPUID_EAX = 0,
+ CPUID_EBX,
+ CPUID_ECX,
+ CPUID_EDX,
+};
+
+#ifdef CONFIG_X86_32
+extern int have_cpuid_p(void);
+#else
+static inline int have_cpuid_p(void)
+{
+ return 1;
+}
+#endif
+static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
+{
+ /* ecx is often an input as well as an output. */
+ asm volatile("cpuid"
+ : "=a" (*eax),
+ "=b" (*ebx),
+ "=c" (*ecx),
+ "=d" (*edx)
+ : "0" (*eax), "2" (*ecx)
+ : "memory");
+}
+
+#define native_cpuid_reg(reg) \
+static inline unsigned int native_cpuid_##reg(unsigned int op) \
+{ \
+ unsigned int eax = op, ebx, ecx = 0, edx; \
+ \
+ native_cpuid(&eax, &ebx, &ecx, &edx); \
+ \
+ return reg; \
+}
+
+/*
+ * Native CPUID functions returning a single datum.
+ */
+native_cpuid_reg(eax)
+native_cpuid_reg(ebx)
+native_cpuid_reg(ecx)
+native_cpuid_reg(edx)
+
+#ifdef CONFIG_PARAVIRT_XXL
+#include <asm/paravirt.h>
+#else
+#define __cpuid native_cpuid
+#endif
+
+/*
+ * Generic CPUID function
+ * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
+ * resulting in stale register contents being returned.
+ */
+static inline void cpuid(unsigned int op,
+ unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
+{
+ *eax = op;
+ *ecx = 0;
+ __cpuid(eax, ebx, ecx, edx);
+}
+
+/* Some CPUID calls want 'count' to be placed in ecx */
+static inline void cpuid_count(unsigned int op, int count,
+ unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
+{
+ *eax = op;
+ *ecx = count;
+ __cpuid(eax, ebx, ecx, edx);
+}
+
+/*
+ * CPUID functions returning a single datum
+ */
+static inline unsigned int cpuid_eax(unsigned int op)
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ cpuid(op, &eax, &ebx, &ecx, &edx);
+
+ return eax;
+}
+
+static inline unsigned int cpuid_ebx(unsigned int op)
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ cpuid(op, &eax, &ebx, &ecx, &edx);
+
+ return ebx;
+}
+
+static inline unsigned int cpuid_ecx(unsigned int op)
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ cpuid(op, &eax, &ebx, &ecx, &edx);
+
+ return ecx;
+}
+
+static inline unsigned int cpuid_edx(unsigned int op)
+{
+ unsigned int eax, ebx, ecx, edx;
+
+ cpuid(op, &eax, &ebx, &ecx, &edx);
+
+ return edx;
+}
+
static __always_inline bool cpuid_function_is_indexed(u32 function)
{
switch (function) {
@@ -31,4 +150,22 @@ static __always_inline bool cpuid_function_is_indexed(u32 function)
return false;
}
+#define for_each_possible_hypervisor_cpuid_base(function) \
+ for (function = 0x40000000; function < 0x40010000; function += 0x100)
+
+static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves)
+{
+ uint32_t base, eax, signature[3];
+
+ for_each_possible_hypervisor_cpuid_base(base) {
+ cpuid(base, &eax, &signature[0], &signature[1], &signature[2]);
+
+ if (!memcmp(sig, signature, 12) &&
+ (leaves == 0 || ((eax - base) >= leaves)))
+ return base;
+ }
+
+ return 0;
+}
+
#endif /* _ASM_X86_CPUID_H */
diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h
index 33d2cd04d254..c862552d7d6d 100644
--- a/arch/x86/include/asm/disabled-features.h
+++ b/arch/x86/include/asm/disabled-features.h
@@ -81,6 +81,12 @@
# define DISABLE_SGX (1 << (X86_FEATURE_SGX & 31))
#endif
+#ifdef CONFIG_XEN_PV
+# define DISABLE_XENPV 0
+#else
+# define DISABLE_XENPV (1 << (X86_FEATURE_XENPV & 31))
+#endif
+
#ifdef CONFIG_INTEL_TDX_GUEST
# define DISABLE_TDX_GUEST 0
#else
@@ -98,7 +104,7 @@
#define DISABLED_MASK5 0
#define DISABLED_MASK6 0
#define DISABLED_MASK7 (DISABLE_PTI)
-#define DISABLED_MASK8 (DISABLE_TDX_GUEST)
+#define DISABLED_MASK8 (DISABLE_XENPV|DISABLE_TDX_GUEST)
#define DISABLED_MASK9 (DISABLE_SGX)
#define DISABLED_MASK10 0
#define DISABLED_MASK11 (DISABLE_RETPOLINE|DISABLE_RETHUNK|DISABLE_UNRET)
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 233ae6986d6f..a63154e049d7 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -178,7 +178,7 @@ struct efi_setup_data {
extern u64 efi_setup;
#ifdef CONFIG_EFI
-extern efi_status_t __efi64_thunk(u32, ...);
+extern u64 __efi64_thunk(u32, ...);
#define efi64_thunk(...) ({ \
u64 __pad[3]; /* must have space for 3 args on the stack */ \
@@ -228,16 +228,15 @@ static inline bool efi_is_native(void)
return efi_is_64bit();
}
-#define efi_mixed_mode_cast(attr) \
- __builtin_choose_expr( \
- __builtin_types_compatible_p(u32, __typeof__(attr)), \
- (unsigned long)(attr), (attr))
-
#define efi_table_attr(inst, attr) \
- (efi_is_native() \
- ? inst->attr \
- : (__typeof__(inst->attr)) \
- efi_mixed_mode_cast(inst->mixed_mode.attr))
+ (efi_is_native() ? (inst)->attr \
+ : efi_mixed_table_attr((inst), attr))
+
+#define efi_mixed_table_attr(inst, attr) \
+ (__typeof__(inst->attr)) \
+ _Generic(inst->mixed_mode.attr, \
+ u32: (unsigned long)(inst->mixed_mode.attr), \
+ default: (inst->mixed_mode.attr))
/*
* The following macros allow translating arguments if necessary from native to
@@ -325,6 +324,17 @@ static inline u32 efi64_convert_status(efi_status_t status)
#define __efi64_argmap_set_memory_space_attributes(phys, size, flags) \
(__efi64_split(phys), __efi64_split(size), __efi64_split(flags))
+/* file protocol */
+#define __efi64_argmap_open(prot, newh, fname, mode, attr) \
+ ((prot), efi64_zero_upper(newh), (fname), __efi64_split(mode), \
+ __efi64_split(attr))
+
+#define __efi64_argmap_set_position(pos) (__efi64_split(pos))
+
+/* file system protocol */
+#define __efi64_argmap_open_volume(prot, file) \
+ ((prot), efi64_zero_upper(file))
+
/*
* The macros below handle the plumbing for the argument mapping. To add a
* mapping for a specific EFI method, simply define a macro
@@ -344,31 +354,27 @@ static inline u32 efi64_convert_status(efi_status_t status)
#define __efi_eat(...)
#define __efi_eval(...) __VA_ARGS__
-/* The three macros below handle dispatching via the thunk if needed */
-
-#define efi_call_proto(inst, func, ...) \
- (efi_is_native() \
- ? inst->func(inst, ##__VA_ARGS__) \
- : __efi64_thunk_map(inst, func, inst, ##__VA_ARGS__))
+static inline efi_status_t __efi64_widen_efi_status(u64 status)
+{
+ /* use rotate to move the value of bit #31 into position #63 */
+ return ror64(rol32(status, 1), 1);
+}
-#define efi_bs_call(func, ...) \
- (efi_is_native() \
- ? efi_system_table->boottime->func(__VA_ARGS__) \
- : __efi64_thunk_map(efi_table_attr(efi_system_table, \
- boottime), \
- func, __VA_ARGS__))
+/* The macro below handles dispatching via the thunk if needed */
-#define efi_rt_call(func, ...) \
- (efi_is_native() \
- ? efi_system_table->runtime->func(__VA_ARGS__) \
- : __efi64_thunk_map(efi_table_attr(efi_system_table, \
- runtime), \
- func, __VA_ARGS__))
+#define efi_fn_call(inst, func, ...) \
+ (efi_is_native() ? (inst)->func(__VA_ARGS__) \
+ : efi_mixed_call((inst), func, ##__VA_ARGS__))
-#define efi_dxe_call(func, ...) \
- (efi_is_native() \
- ? efi_dxe_table->func(__VA_ARGS__) \
- : __efi64_thunk_map(efi_dxe_table, func, __VA_ARGS__))
+#define efi_mixed_call(inst, func, ...) \
+ _Generic(inst->func(__VA_ARGS__), \
+ efi_status_t: \
+ __efi64_widen_efi_status( \
+ __efi64_thunk_map(inst, func, ##__VA_ARGS__)), \
+ u64: ({ BUILD_BUG(); ULONG_MAX; }), \
+ default: \
+ (__typeof__(inst->func(__VA_ARGS__))) \
+ __efi64_thunk_map(inst, func, ##__VA_ARGS__))
#else /* CONFIG_EFI_MIXED */
@@ -400,13 +406,52 @@ static inline void efi_reserve_boot_services(void)
#ifdef CONFIG_EFI_FAKE_MEMMAP
extern void __init efi_fake_memmap_early(void);
+extern void __init efi_fake_memmap(void);
#else
static inline void efi_fake_memmap_early(void)
{
}
+
+static inline void efi_fake_memmap(void)
+{
+}
#endif
+extern int __init efi_memmap_alloc(unsigned int num_entries,
+ struct efi_memory_map_data *data);
+extern void __efi_memmap_free(u64 phys, unsigned long size,
+ unsigned long flags);
+#define __efi_memmap_free __efi_memmap_free
+
+extern int __init efi_memmap_install(struct efi_memory_map_data *data);
+extern int __init efi_memmap_split_count(efi_memory_desc_t *md,
+ struct range *range);
+extern void __init efi_memmap_insert(struct efi_memory_map *old_memmap,
+ void *buf, struct efi_mem_range *mem);
+
#define arch_ima_efi_boot_mode \
({ extern struct boot_params boot_params; boot_params.secure_boot; })
+#ifdef CONFIG_EFI_RUNTIME_MAP
+int efi_get_runtime_map_size(void);
+int efi_get_runtime_map_desc_size(void);
+int efi_runtime_map_copy(void *buf, size_t bufsz);
+#else
+static inline int efi_get_runtime_map_size(void)
+{
+ return 0;
+}
+
+static inline int efi_get_runtime_map_desc_size(void)
+{
+ return 0;
+}
+
+static inline int efi_runtime_map_copy(void *buf, size_t bufsz)
+{
+ return 0;
+}
+
+#endif
+
#endif /* _ASM_X86_EFI_H */
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h
index cb0ff1055ab1..18fd06f7936a 100644
--- a/arch/x86/include/asm/elf.h
+++ b/arch/x86/include/asm/elf.h
@@ -152,10 +152,6 @@ do { \
(elf_check_arch_ia32(x) || \
(IS_ENABLED(CONFIG_X86_X32_ABI) && (x)->e_machine == EM_X86_64))
-#if __USER32_DS != __USER_DS
-# error "The following code assumes __USER32_DS == __USER_DS"
-#endif
-
static inline void elf_common_init(struct thread_struct *t,
struct pt_regs *regs, const u16 ds)
{
@@ -226,7 +222,6 @@ do { \
/* I'm not sure if we can use '-' here */
#define ELF_PLATFORM ("x86_64")
extern void set_personality_64bit(void);
-extern unsigned int sysctl_vsyscall32;
extern int force_personality32;
#endif /* !CONFIG_X86_32 */
diff --git a/arch/x86/include/asm/entry-common.h b/arch/x86/include/asm/entry-common.h
index 674ed46d3ced..117903881fe4 100644
--- a/arch/x86/include/asm/entry-common.h
+++ b/arch/x86/include/asm/entry-common.h
@@ -24,8 +24,8 @@ static __always_inline void arch_enter_from_user_mode(struct pt_regs *regs)
/*
* For !SMAP hardware we patch out CLAC on entry.
*/
- if (boot_cpu_has(X86_FEATURE_SMAP) ||
- (IS_ENABLED(CONFIG_64BIT) && boot_cpu_has(X86_FEATURE_XENPV)))
+ if (cpu_feature_enabled(X86_FEATURE_SMAP) ||
+ cpu_feature_enabled(X86_FEATURE_XENPV))
mask |= X86_EFLAGS_AC;
WARN_ON_ONCE(flags & mask);
diff --git a/arch/x86/include/asm/fpu/signal.h b/arch/x86/include/asm/fpu/signal.h
index e1c9df9102a5..611fa41711af 100644
--- a/arch/x86/include/asm/fpu/signal.h
+++ b/arch/x86/include/asm/fpu/signal.h
@@ -13,16 +13,9 @@
#ifdef CONFIG_X86_64
# include <uapi/asm/sigcontext.h>
# include <asm/user32.h>
-struct ksignal;
-int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
- compat_sigset_t *set, struct pt_regs *regs);
-int ia32_setup_frame(int sig, struct ksignal *ksig,
- compat_sigset_t *set, struct pt_regs *regs);
#else
# define user_i387_ia32_struct user_i387_struct
# define user32_fxsr_struct user_fxsr_struct
-# define ia32_setup_frame __setup_frame
-# define ia32_setup_rt_frame __setup_rt_frame
#endif
extern void convert_from_fxsr(struct user_i387_ia32_struct *env,
diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h
index 908d99b127d3..5061ac98ffa1 100644
--- a/arch/x86/include/asm/ftrace.h
+++ b/arch/x86/include/asm/ftrace.h
@@ -34,19 +34,6 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr)
return addr;
}
-/*
- * When a ftrace registered caller is tracing a function that is
- * also set by a register_ftrace_direct() call, it needs to be
- * differentiated in the ftrace_caller trampoline. To do this, we
- * place the direct caller in the ORIG_AX part of pt_regs. This
- * tells the ftrace_caller that there's a direct caller.
- */
-static inline void arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr)
-{
- /* Emulate a call */
- regs->orig_ax = addr;
-}
-
#ifdef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS
struct ftrace_regs {
struct pt_regs regs;
@@ -61,9 +48,25 @@ arch_ftrace_get_regs(struct ftrace_regs *fregs)
return &fregs->regs;
}
-#define ftrace_instruction_pointer_set(fregs, _ip) \
+#define ftrace_regs_set_instruction_pointer(fregs, _ip) \
do { (fregs)->regs.ip = (_ip); } while (0)
+#define ftrace_regs_get_instruction_pointer(fregs) \
+ ((fregs)->regs.ip)
+
+#define ftrace_regs_get_argument(fregs, n) \
+ regs_get_kernel_argument(&(fregs)->regs, n)
+#define ftrace_regs_get_stack_pointer(fregs) \
+ kernel_stack_pointer(&(fregs)->regs)
+#define ftrace_regs_return_value(fregs) \
+ regs_return_value(&(fregs)->regs)
+#define ftrace_regs_set_return_value(fregs, ret) \
+ regs_set_return_value(&(fregs)->regs, ret)
+#define ftrace_override_function_with_return(fregs) \
+ override_function_with_return(&(fregs)->regs)
+#define ftrace_regs_query_register_offset(name) \
+ regs_query_register_offset(name)
+
struct ftrace_ops;
#define ftrace_graph_func ftrace_graph_func
void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
@@ -72,6 +75,24 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
#define FTRACE_GRAPH_TRAMP_ADDR FTRACE_GRAPH_ADDR
#endif
+#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+/*
+ * When a ftrace registered caller is tracing a function that is
+ * also set by a register_ftrace_direct() call, it needs to be
+ * differentiated in the ftrace_caller trampoline. To do this, we
+ * place the direct caller in the ORIG_AX part of pt_regs. This
+ * tells the ftrace_caller that there's a direct caller.
+ */
+static inline void
+__arch_ftrace_set_direct_caller(struct pt_regs *regs, unsigned long addr)
+{
+ /* Emulate a call */
+ regs->orig_ax = addr;
+}
+#define arch_ftrace_set_direct_caller(fregs, addr) \
+ __arch_ftrace_set_direct_caller(&(fregs)->regs, addr)
+#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
+
#ifdef CONFIG_DYNAMIC_FTRACE
struct dyn_arch_ftrace {
diff --git a/arch/x86/include/asm/hyperv-tlfs.h b/arch/x86/include/asm/hyperv-tlfs.h
index 3089ec352743..6d9368ea3701 100644
--- a/arch/x86/include/asm/hyperv-tlfs.h
+++ b/arch/x86/include/asm/hyperv-tlfs.h
@@ -374,11 +374,20 @@ struct hv_nested_enlightenments_control {
struct hv_vp_assist_page {
__u32 apic_assist;
__u32 reserved1;
- __u64 vtl_control[3];
+ __u32 vtl_entry_reason;
+ __u32 vtl_reserved;
+ __u64 vtl_ret_x64rax;
+ __u64 vtl_ret_x64rcx;
struct hv_nested_enlightenments_control nested_control;
__u8 enlighten_vmentry;
__u8 reserved2[7];
__u64 current_nested_vmcs;
+ __u8 synthetic_time_unhalted_timer_expired;
+ __u8 reserved3[7];
+ __u8 virtualization_fault_information[40];
+ __u8 reserved4[8];
+ __u8 intercept_message[256];
+ __u8 vtl_ret_actions[256];
} __packed;
struct hv_enlightened_vmcs {
diff --git a/arch/x86/include/asm/hyperv_timer.h b/arch/x86/include/asm/hyperv_timer.h
new file mode 100644
index 000000000000..388fa81b8f38
--- /dev/null
+++ b/arch/x86/include/asm/hyperv_timer.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_X86_HYPERV_TIMER_H
+#define _ASM_X86_HYPERV_TIMER_H
+
+#include <asm/msr.h>
+
+#define hv_get_raw_timer() rdtsc_ordered()
+
+#endif
diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h
index 7cc49432187f..7a2ed154a5e1 100644
--- a/arch/x86/include/asm/irq_remapping.h
+++ b/arch/x86/include/asm/irq_remapping.h
@@ -44,10 +44,6 @@ extern int irq_remapping_reenable(int);
extern int irq_remap_enable_fault_handling(void);
extern void panic_if_irq_remap(const char *msg);
-/* Create PCI MSI/MSIx irqdomain, use @parent as the parent irqdomain. */
-extern struct irq_domain *
-arch_create_remap_msi_irq_domain(struct irq_domain *par, const char *n, int id);
-
/* Get parent irqdomain for interrupt remapping irqdomain */
static inline struct irq_domain *arch_get_ir_parent_domain(void)
{
diff --git a/arch/x86/include/asm/irqdomain.h b/arch/x86/include/asm/irqdomain.h
index 125c23b7bad3..30c325c235c0 100644
--- a/arch/x86/include/asm/irqdomain.h
+++ b/arch/x86/include/asm/irqdomain.h
@@ -7,9 +7,7 @@
#ifdef CONFIG_X86_LOCAL_APIC
enum {
- /* Allocate contiguous CPU vectors */
- X86_IRQ_ALLOC_CONTIGUOUS_VECTORS = 0x1,
- X86_IRQ_ALLOC_LEGACY = 0x2,
+ X86_IRQ_ALLOC_LEGACY = 0x1,
};
extern int x86_fwspec_is_ioapic(struct irq_fwspec *fwspec);
diff --git a/arch/x86/include/asm/memtype.h b/arch/x86/include/asm/memtype.h
index 9ca760e430b9..113b2fa51849 100644
--- a/arch/x86/include/asm/memtype.h
+++ b/arch/x86/include/asm/memtype.h
@@ -6,9 +6,8 @@
#include <asm/pgtable_types.h>
extern bool pat_enabled(void);
-extern void pat_disable(const char *reason);
-extern void pat_init(void);
-extern void init_cache_modes(void);
+extern void pat_bp_init(void);
+extern void pat_cpu_init(void);
extern int memtype_reserve(u64 start, u64 end,
enum page_cache_mode req_pcm, enum page_cache_mode *ret_pcm);
diff --git a/arch/x86/include/asm/microcode.h b/arch/x86/include/asm/microcode.h
index 74ecc2bd6cd0..d5a58bde091c 100644
--- a/arch/x86/include/asm/microcode.h
+++ b/arch/x86/include/asm/microcode.h
@@ -33,8 +33,7 @@ enum ucode_state {
};
struct microcode_ops {
- enum ucode_state (*request_microcode_fw) (int cpu, struct device *,
- bool refresh_fw);
+ enum ucode_state (*request_microcode_fw) (int cpu, struct device *);
void (*microcode_fini_cpu) (int cpu);
@@ -50,7 +49,6 @@ struct microcode_ops {
struct ucode_cpu_info {
struct cpu_signature cpu_sig;
- int valid;
void *mc;
};
extern struct ucode_cpu_info ucode_cpu_info[];
diff --git a/arch/x86/include/asm/microcode_intel.h b/arch/x86/include/asm/microcode_intel.h
index 4c92cea7e4b5..f1fa979e05bf 100644
--- a/arch/x86/include/asm/microcode_intel.h
+++ b/arch/x86/include/asm/microcode_intel.h
@@ -14,7 +14,8 @@ struct microcode_header_intel {
unsigned int pf;
unsigned int datasize;
unsigned int totalsize;
- unsigned int reserved[3];
+ unsigned int metasize;
+ unsigned int reserved[2];
};
struct microcode_intel {
@@ -41,6 +42,8 @@ struct extended_sigtable {
#define DEFAULT_UCODE_TOTALSIZE (DEFAULT_UCODE_DATASIZE + MC_HEADER_SIZE)
#define EXT_HEADER_SIZE (sizeof(struct extended_sigtable))
#define EXT_SIGNATURE_SIZE (sizeof(struct extended_signature))
+#define MC_HEADER_TYPE_MICROCODE 1
+#define MC_HEADER_TYPE_IFS 2
#define get_totalsize(mc) \
(((struct microcode_intel *)mc)->hdr.datasize ? \
diff --git a/arch/x86/include/asm/mshyperv.h b/arch/x86/include/asm/mshyperv.h
index 61f0c206bff0..6d502f3efb0f 100644
--- a/arch/x86/include/asm/mshyperv.h
+++ b/arch/x86/include/asm/mshyperv.h
@@ -19,8 +19,6 @@ typedef int (*hyperv_fill_flush_list_func)(
struct hv_guest_mapping_flush_list *flush,
void *data);
-#define hv_get_raw_timer() rdtsc_ordered()
-
void hyperv_vector_handler(struct pt_regs *regs);
#if IS_ENABLED(CONFIG_HYPERV)
diff --git a/arch/x86/include/asm/msi.h b/arch/x86/include/asm/msi.h
index d71c7e8b738d..935c6d470341 100644
--- a/arch/x86/include/asm/msi.h
+++ b/arch/x86/include/asm/msi.h
@@ -62,4 +62,10 @@ typedef struct x86_msi_addr_hi {
struct msi_msg;
u32 x86_msi_msg_get_destid(struct msi_msg *msg, bool extid);
+#define X86_VECTOR_MSI_FLAGS_SUPPORTED \
+ (MSI_GENERIC_FLAGS_MASK | MSI_FLAG_PCI_MSIX | MSI_FLAG_PCI_MSIX_ALLOC_DYN)
+
+#define X86_VECTOR_MSI_FLAGS_REQUIRED \
+ (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS)
+
#endif /* _ASM_X86_MSI_H */
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index 4a2af82553e4..37ff47552bcb 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -4,12 +4,7 @@
#include <linux/bits.h>
-/*
- * CPU model specific register (MSR) numbers.
- *
- * Do not add new entries to this file unless the definitions are shared
- * between multiple compilation units.
- */
+/* CPU model specific register (MSR) numbers. */
/* x86-64 specific MSRs */
#define MSR_EFER 0xc0000080 /* extended feature register */
@@ -798,6 +793,7 @@
#define ENERGY_PERF_BIAS_PERFORMANCE 0
#define ENERGY_PERF_BIAS_BALANCE_PERFORMANCE 4
#define ENERGY_PERF_BIAS_NORMAL 6
+#define ENERGY_PERF_BIAS_NORMAL_POWERSAVE 7
#define ENERGY_PERF_BIAS_BALANCE_POWERSAVE 8
#define ENERGY_PERF_BIAS_POWERSAVE 15
@@ -1052,6 +1048,20 @@
#define VMX_BASIC_MEM_TYPE_WB 6LLU
#define VMX_BASIC_INOUT 0x0040000000000000LLU
+/* Resctrl MSRs: */
+/* - Intel: */
+#define MSR_IA32_L3_QOS_CFG 0xc81
+#define MSR_IA32_L2_QOS_CFG 0xc82
+#define MSR_IA32_QM_EVTSEL 0xc8d
+#define MSR_IA32_QM_CTR 0xc8e
+#define MSR_IA32_PQR_ASSOC 0xc8f
+#define MSR_IA32_L3_CBM_BASE 0xc90
+#define MSR_IA32_L2_CBM_BASE 0xd10
+#define MSR_IA32_MBA_THRTL_BASE 0xd50
+
+/* - AMD: */
+#define MSR_IA32_MBA_BW_BASE 0xc0000200
+
/* MSR_IA32_VMX_MISC bits */
#define MSR_IA32_VMX_MISC_INTEL_PT (1ULL << 14)
#define MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS (1ULL << 29)
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
index 76d726074c16..f0eeaf6e5f5f 100644
--- a/arch/x86/include/asm/mtrr.h
+++ b/arch/x86/include/asm/mtrr.h
@@ -25,13 +25,12 @@
#include <uapi/asm/mtrr.h>
-void mtrr_bp_init(void);
-
/*
* The following functions are for use by other drivers that cannot use
* arch_phys_wc_add and arch_phys_wc_del.
*/
# ifdef CONFIG_MTRR
+void mtrr_bp_init(void);
extern u8 mtrr_type_lookup(u64 addr, u64 end, u8 *uniform);
extern void mtrr_save_fixed_ranges(void *);
extern void mtrr_save_state(void);
@@ -42,12 +41,12 @@ extern int mtrr_add_page(unsigned long base, unsigned long size,
extern int mtrr_del(int reg, unsigned long base, unsigned long size);
extern int mtrr_del_page(int reg, unsigned long base, unsigned long size);
extern void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi);
-extern void mtrr_ap_init(void);
-extern void set_mtrr_aps_delayed_init(void);
-extern void mtrr_aps_init(void);
extern void mtrr_bp_restore(void);
extern int mtrr_trim_uncached_memory(unsigned long end_pfn);
extern int amd_special_default_mtrr(void);
+void mtrr_disable(void);
+void mtrr_enable(void);
+void mtrr_generic_set_state(void);
# else
static inline u8 mtrr_type_lookup(u64 addr, u64 end, u8 *uniform)
{
@@ -83,10 +82,11 @@ static inline int mtrr_trim_uncached_memory(unsigned long end_pfn)
static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi)
{
}
-#define mtrr_ap_init() do {} while (0)
-#define set_mtrr_aps_delayed_init() do {} while (0)
-#define mtrr_aps_init() do {} while (0)
+#define mtrr_bp_init() do {} while (0)
#define mtrr_bp_restore() do {} while (0)
+#define mtrr_disable() do {} while (0)
+#define mtrr_enable() do {} while (0)
+#define mtrr_generic_set_state() do {} while (0)
# endif
#ifdef CONFIG_COMPAT
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index f3d601574730..f72bf0f6ccf7 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -2,37 +2,6 @@
#ifndef _ASM_X86_PARAVIRT_TYPES_H
#define _ASM_X86_PARAVIRT_TYPES_H
-/* Bitmask of what can be clobbered: usually at least eax. */
-#define CLBR_EAX (1 << 0)
-#define CLBR_ECX (1 << 1)
-#define CLBR_EDX (1 << 2)
-#define CLBR_EDI (1 << 3)
-
-#ifdef CONFIG_X86_32
-/* CLBR_ANY should match all regs platform has. For i386, that's just it */
-#define CLBR_ANY ((1 << 4) - 1)
-
-#define CLBR_ARG_REGS (CLBR_EAX | CLBR_EDX | CLBR_ECX)
-#define CLBR_RET_REG (CLBR_EAX | CLBR_EDX)
-#else
-#define CLBR_RAX CLBR_EAX
-#define CLBR_RCX CLBR_ECX
-#define CLBR_RDX CLBR_EDX
-#define CLBR_RDI CLBR_EDI
-#define CLBR_RSI (1 << 4)
-#define CLBR_R8 (1 << 5)
-#define CLBR_R9 (1 << 6)
-#define CLBR_R10 (1 << 7)
-#define CLBR_R11 (1 << 8)
-
-#define CLBR_ANY ((1 << 9) - 1)
-
-#define CLBR_ARG_REGS (CLBR_RDI | CLBR_RSI | CLBR_RDX | \
- CLBR_RCX | CLBR_R8 | CLBR_R9)
-#define CLBR_RET_REG (CLBR_RAX)
-
-#endif /* X86_64 */
-
#ifndef __ASSEMBLY__
#include <asm/desc_defs.h>
@@ -279,27 +248,23 @@ extern struct paravirt_patch_template pv_ops;
#define paravirt_type(op) \
[paravirt_typenum] "i" (PARAVIRT_PATCH(op)), \
[paravirt_opptr] "m" (pv_ops.op)
-#define paravirt_clobber(clobber) \
- [paravirt_clobber] "i" (clobber)
-
/*
* Generate some code, and mark it as patchable by the
* apply_paravirt() alternate instruction patcher.
*/
-#define _paravirt_alt(insn_string, type, clobber) \
+#define _paravirt_alt(insn_string, type) \
"771:\n\t" insn_string "\n" "772:\n" \
".pushsection .parainstructions,\"a\"\n" \
_ASM_ALIGN "\n" \
_ASM_PTR " 771b\n" \
" .byte " type "\n" \
" .byte 772b-771b\n" \
- " .short " clobber "\n" \
_ASM_ALIGN "\n" \
".popsection\n"
/* Generate patchable code, with the default asm parameters. */
#define paravirt_alt(insn_string) \
- _paravirt_alt(insn_string, "%c[paravirt_typenum]", "%c[paravirt_clobber]")
+ _paravirt_alt(insn_string, "%c[paravirt_typenum]")
/* Simple instruction patching code. */
#define NATIVE_LABEL(a,x,b) "\n\t.globl " a #x "_" #b "\n" a #x "_" #b ":\n\t"
@@ -451,20 +416,19 @@ int paravirt_disable_iospace(void);
})
-#define ____PVOP_CALL(ret, op, clbr, call_clbr, extra_clbr, ...) \
+#define ____PVOP_CALL(ret, op, call_clbr, extra_clbr, ...) \
({ \
PVOP_CALL_ARGS; \
PVOP_TEST_NULL(op); \
asm volatile(paravirt_alt(PARAVIRT_CALL) \
: call_clbr, ASM_CALL_CONSTRAINT \
: paravirt_type(op), \
- paravirt_clobber(clbr), \
##__VA_ARGS__ \
: "memory", "cc" extra_clbr); \
ret; \
})
-#define ____PVOP_ALT_CALL(ret, op, alt, cond, clbr, call_clbr, \
+#define ____PVOP_ALT_CALL(ret, op, alt, cond, call_clbr, \
extra_clbr, ...) \
({ \
PVOP_CALL_ARGS; \
@@ -473,45 +437,44 @@ int paravirt_disable_iospace(void);
alt, cond) \
: call_clbr, ASM_CALL_CONSTRAINT \
: paravirt_type(op), \
- paravirt_clobber(clbr), \
##__VA_ARGS__ \
: "memory", "cc" extra_clbr); \
ret; \
})
#define __PVOP_CALL(rettype, op, ...) \
- ____PVOP_CALL(PVOP_RETVAL(rettype), op, CLBR_ANY, \
+ ____PVOP_CALL(PVOP_RETVAL(rettype), op, \
PVOP_CALL_CLOBBERS, EXTRA_CLOBBERS, ##__VA_ARGS__)
#define __PVOP_ALT_CALL(rettype, op, alt, cond, ...) \
- ____PVOP_ALT_CALL(PVOP_RETVAL(rettype), op, alt, cond, CLBR_ANY,\
+ ____PVOP_ALT_CALL(PVOP_RETVAL(rettype), op, alt, cond, \
PVOP_CALL_CLOBBERS, EXTRA_CLOBBERS, \
##__VA_ARGS__)
#define __PVOP_CALLEESAVE(rettype, op, ...) \
- ____PVOP_CALL(PVOP_RETVAL(rettype), op.func, CLBR_RET_REG, \
+ ____PVOP_CALL(PVOP_RETVAL(rettype), op.func, \
PVOP_CALLEE_CLOBBERS, , ##__VA_ARGS__)
#define __PVOP_ALT_CALLEESAVE(rettype, op, alt, cond, ...) \
____PVOP_ALT_CALL(PVOP_RETVAL(rettype), op.func, alt, cond, \
- CLBR_RET_REG, PVOP_CALLEE_CLOBBERS, , ##__VA_ARGS__)
+ PVOP_CALLEE_CLOBBERS, , ##__VA_ARGS__)
#define __PVOP_VCALL(op, ...) \
- (void)____PVOP_CALL(, op, CLBR_ANY, PVOP_VCALL_CLOBBERS, \
+ (void)____PVOP_CALL(, op, PVOP_VCALL_CLOBBERS, \
VEXTRA_CLOBBERS, ##__VA_ARGS__)
#define __PVOP_ALT_VCALL(op, alt, cond, ...) \
- (void)____PVOP_ALT_CALL(, op, alt, cond, CLBR_ANY, \
+ (void)____PVOP_ALT_CALL(, op, alt, cond, \
PVOP_VCALL_CLOBBERS, VEXTRA_CLOBBERS, \
##__VA_ARGS__)
#define __PVOP_VCALLEESAVE(op, ...) \
- (void)____PVOP_CALL(, op.func, CLBR_RET_REG, \
+ (void)____PVOP_CALL(, op.func, \
PVOP_VCALLEE_CLOBBERS, , ##__VA_ARGS__)
#define __PVOP_ALT_VCALLEESAVE(op, alt, cond, ...) \
- (void)____PVOP_ALT_CALL(, op.func, alt, cond, CLBR_RET_REG, \
+ (void)____PVOP_ALT_CALL(, op.func, alt, cond, \
PVOP_VCALLEE_CLOBBERS, , ##__VA_ARGS__)
diff --git a/arch/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
index 736793d65bcb..b40c462b4af3 100644
--- a/arch/x86/include/asm/pci.h
+++ b/arch/x86/include/asm/pci.h
@@ -21,7 +21,7 @@ struct pci_sysdata {
#ifdef CONFIG_X86_64
void *iommu; /* IOMMU private data */
#endif
-#ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
+#ifdef CONFIG_PCI_MSI
void *fwnode; /* IRQ domain for MSI assignment */
#endif
#if IS_ENABLED(CONFIG_VMD)
@@ -52,7 +52,7 @@ static inline int pci_proc_domain(struct pci_bus *bus)
}
#endif
-#ifdef CONFIG_PCI_MSI_IRQ_DOMAIN
+#ifdef CONFIG_PCI_MSI
static inline void *_pci_root_bus_fwnode(struct pci_bus *bus)
{
return to_pci_sysdata(bus)->fwnode;
@@ -92,6 +92,7 @@ void pcibios_scan_root(int bus);
struct irq_routing_table *pcibios_get_irq_routing_table(void);
int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
+bool pci_dev_has_default_msi_parent_domain(struct pci_dev *dev);
#define HAVE_PCI_MMAP
#define arch_can_pci_mmap_wc() pat_enabled()
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 67c9d73b31fa..6836c64b9819 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -16,6 +16,7 @@ struct vm86;
#include <uapi/asm/sigcontext.h>
#include <asm/current.h>
#include <asm/cpufeatures.h>
+#include <asm/cpuid.h>
#include <asm/page.h>
#include <asm/pgtable_types.h>
#include <asm/percpu.h>
@@ -146,17 +147,6 @@ struct cpuinfo_x86 {
unsigned initialized : 1;
} __randomize_layout;
-struct cpuid_regs {
- u32 eax, ebx, ecx, edx;
-};
-
-enum cpuid_regs_idx {
- CPUID_EAX = 0,
- CPUID_EBX,
- CPUID_ECX,
- CPUID_EDX,
-};
-
#define X86_VENDOR_INTEL 0
#define X86_VENDOR_CYRIX 1
#define X86_VENDOR_AMD 2
@@ -205,45 +195,6 @@ extern void identify_secondary_cpu(struct cpuinfo_x86 *);
extern void print_cpu_info(struct cpuinfo_x86 *);
void print_cpu_msr(struct cpuinfo_x86 *);
-#ifdef CONFIG_X86_32
-extern int have_cpuid_p(void);
-#else
-static inline int have_cpuid_p(void)
-{
- return 1;
-}
-#endif
-static inline void native_cpuid(unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
-{
- /* ecx is often an input as well as an output. */
- asm volatile("cpuid"
- : "=a" (*eax),
- "=b" (*ebx),
- "=c" (*ecx),
- "=d" (*edx)
- : "0" (*eax), "2" (*ecx)
- : "memory");
-}
-
-#define native_cpuid_reg(reg) \
-static inline unsigned int native_cpuid_##reg(unsigned int op) \
-{ \
- unsigned int eax = op, ebx, ecx = 0, edx; \
- \
- native_cpuid(&eax, &ebx, &ecx, &edx); \
- \
- return reg; \
-}
-
-/*
- * Native CPUID functions returning a single datum.
- */
-native_cpuid_reg(eax)
-native_cpuid_reg(ebx)
-native_cpuid_reg(ecx)
-native_cpuid_reg(edx)
-
/*
* Friendlier CR3 helpers.
*/
@@ -578,7 +529,6 @@ static __always_inline bool on_thread_stack(void)
#ifdef CONFIG_PARAVIRT_XXL
#include <asm/paravirt.h>
#else
-#define __cpuid native_cpuid
static inline void load_sp0(unsigned long sp0)
{
@@ -589,69 +539,6 @@ static inline void load_sp0(unsigned long sp0)
unsigned long __get_wchan(struct task_struct *p);
-/*
- * Generic CPUID function
- * clear %ecx since some cpus (Cyrix MII) do not set or clear %ecx
- * resulting in stale register contents being returned.
- */
-static inline void cpuid(unsigned int op,
- unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
-{
- *eax = op;
- *ecx = 0;
- __cpuid(eax, ebx, ecx, edx);
-}
-
-/* Some CPUID calls want 'count' to be placed in ecx */
-static inline void cpuid_count(unsigned int op, int count,
- unsigned int *eax, unsigned int *ebx,
- unsigned int *ecx, unsigned int *edx)
-{
- *eax = op;
- *ecx = count;
- __cpuid(eax, ebx, ecx, edx);
-}
-
-/*
- * CPUID functions returning a single datum
- */
-static inline unsigned int cpuid_eax(unsigned int op)
-{
- unsigned int eax, ebx, ecx, edx;
-
- cpuid(op, &eax, &ebx, &ecx, &edx);
-
- return eax;
-}
-
-static inline unsigned int cpuid_ebx(unsigned int op)
-{
- unsigned int eax, ebx, ecx, edx;
-
- cpuid(op, &eax, &ebx, &ecx, &edx);
-
- return ebx;
-}
-
-static inline unsigned int cpuid_ecx(unsigned int op)
-{
- unsigned int eax, ebx, ecx, edx;
-
- cpuid(op, &eax, &ebx, &ecx, &edx);
-
- return ecx;
-}
-
-static inline unsigned int cpuid_edx(unsigned int op)
-{
- unsigned int eax, ebx, ecx, edx;
-
- cpuid(op, &eax, &ebx, &ecx, &edx);
-
- return edx;
-}
-
extern void select_idle_routine(const struct cpuinfo_x86 *c);
extern void amd_e400_c1e_apic_setup(void);
@@ -805,24 +692,6 @@ static inline u32 amd_get_nodes_per_socket(void) { return 0; }
static inline u32 amd_get_highest_perf(void) { return 0; }
#endif
-#define for_each_possible_hypervisor_cpuid_base(function) \
- for (function = 0x40000000; function < 0x40010000; function += 0x100)
-
-static inline uint32_t hypervisor_cpuid_base(const char *sig, uint32_t leaves)
-{
- uint32_t base, eax, signature[3];
-
- for_each_possible_hypervisor_cpuid_base(base) {
- cpuid(base, &eax, &signature[0], &signature[1], &signature[2]);
-
- if (!memcmp(sig, signature, 12) &&
- (leaves == 0 || ((eax - base) >= leaves)))
- return base;
- }
-
- return 0;
-}
-
extern unsigned long arch_align_stack(unsigned long sp);
void free_init_pages(const char *what, unsigned long begin, unsigned long end);
extern void free_kernel_image_pages(const char *what, void *begin, void *end);
diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
index fd6f6e5b755a..a336feef0af1 100644
--- a/arch/x86/include/asm/realmode.h
+++ b/arch/x86/include/asm/realmode.h
@@ -91,6 +91,7 @@ static inline void set_real_mode_mem(phys_addr_t mem)
void reserve_real_mode(void);
void load_trampoline_pgtable(void);
+void init_real_mode(void);
#endif /* __ASSEMBLY__ */
diff --git a/arch/x86/include/asm/resctrl.h b/arch/x86/include/asm/resctrl.h
index d24b04ebf950..52788f79786f 100644
--- a/arch/x86/include/asm/resctrl.h
+++ b/arch/x86/include/asm/resctrl.h
@@ -7,8 +7,6 @@
#include <linux/sched.h>
#include <linux/jump_label.h>
-#define IA32_PQR_ASSOC 0x0c8f
-
/**
* struct resctrl_pqr_state - State cache for the PQR MSR
* @cur_rmid: The cached Resource Monitoring ID
@@ -16,8 +14,8 @@
* @default_rmid: The user assigned Resource Monitoring ID
* @default_closid: The user assigned cached Class Of Service ID
*
- * The upper 32 bits of IA32_PQR_ASSOC contain closid and the
- * lower 10 bits rmid. The update to IA32_PQR_ASSOC always
+ * The upper 32 bits of MSR_IA32_PQR_ASSOC contain closid and the
+ * lower 10 bits rmid. The update to MSR_IA32_PQR_ASSOC always
* contains both parts, so we need to cache them. This also
* stores the user configured per cpu CLOSID and RMID.
*
@@ -77,7 +75,7 @@ static void __resctrl_sched_in(void)
if (closid != state->cur_closid || rmid != state->cur_rmid) {
state->cur_closid = closid;
state->cur_rmid = rmid;
- wrmsr(IA32_PQR_ASSOC, rmid, closid);
+ wrmsr(MSR_IA32_PQR_ASSOC, rmid, closid);
}
}
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
index 2e7890dd58a4..c390a672d560 100644
--- a/arch/x86/include/asm/segment.h
+++ b/arch/x86/include/asm/segment.h
@@ -135,6 +135,7 @@
#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS*8)
#define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS*8 + 3)
#define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS*8 + 3)
+#define __USER32_CS __USER_CS
#define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS*8)
/* segment for calling fn: */
@@ -210,7 +211,6 @@
#define __KERNEL_DS (GDT_ENTRY_KERNEL_DS*8)
#define __USER32_CS (GDT_ENTRY_DEFAULT_USER32_CS*8 + 3)
#define __USER_DS (GDT_ENTRY_DEFAULT_USER_DS*8 + 3)
-#define __USER32_DS __USER_DS
#define __USER_CS (GDT_ENTRY_DEFAULT_USER_CS*8 + 3)
#define __CPUNODE_SEG (GDT_ENTRY_CPUNODE*8 + 3)
diff --git a/arch/x86/include/asm/sgx.h b/arch/x86/include/asm/sgx.h
index eae20fa52b93..6a0069761508 100644
--- a/arch/x86/include/asm/sgx.h
+++ b/arch/x86/include/asm/sgx.h
@@ -115,17 +115,36 @@ enum sgx_miscselect {
* %SGX_ATTR_EINITTOKENKEY: Allow to use token signing key that is used to
* sign cryptographic tokens that can be passed to
* EINIT as an authorization to run an enclave.
+ * %SGX_ATTR_ASYNC_EXIT_NOTIFY: Allow enclaves to be notified after an
+ * asynchronous exit has occurred.
*/
enum sgx_attribute {
- SGX_ATTR_INIT = BIT(0),
- SGX_ATTR_DEBUG = BIT(1),
- SGX_ATTR_MODE64BIT = BIT(2),
- SGX_ATTR_PROVISIONKEY = BIT(4),
- SGX_ATTR_EINITTOKENKEY = BIT(5),
- SGX_ATTR_KSS = BIT(7),
+ SGX_ATTR_INIT = BIT(0),
+ SGX_ATTR_DEBUG = BIT(1),
+ SGX_ATTR_MODE64BIT = BIT(2),
+ /* BIT(3) is reserved */
+ SGX_ATTR_PROVISIONKEY = BIT(4),
+ SGX_ATTR_EINITTOKENKEY = BIT(5),
+ /* BIT(6) is for CET */
+ SGX_ATTR_KSS = BIT(7),
+ /* BIT(8) is reserved */
+ /* BIT(9) is reserved */
+ SGX_ATTR_ASYNC_EXIT_NOTIFY = BIT(10),
};
-#define SGX_ATTR_RESERVED_MASK (BIT_ULL(3) | BIT_ULL(6) | GENMASK_ULL(63, 8))
+#define SGX_ATTR_RESERVED_MASK (BIT_ULL(3) | \
+ BIT_ULL(6) | \
+ BIT_ULL(8) | \
+ BIT_ULL(9) | \
+ GENMASK_ULL(63, 11))
+
+#define SGX_ATTR_UNPRIV_MASK (SGX_ATTR_DEBUG | \
+ SGX_ATTR_MODE64BIT | \
+ SGX_ATTR_KSS | \
+ SGX_ATTR_ASYNC_EXIT_NOTIFY)
+
+#define SGX_ATTR_PRIV_MASK (SGX_ATTR_PROVISIONKEY | \
+ SGX_ATTR_EINITTOKENKEY)
/**
* struct sgx_secs - SGX Enclave Control Structure (SECS)
diff --git a/arch/x86/include/asm/sighandling.h b/arch/x86/include/asm/sighandling.h
index 65e667279e0f..e770c4fc47f4 100644
--- a/arch/x86/include/asm/sighandling.h
+++ b/arch/x86/include/asm/sighandling.h
@@ -15,4 +15,13 @@
void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
+void __user *
+get_sigframe(struct ksignal *ksig, struct pt_regs *regs, size_t frame_size,
+ void __user **fpstate);
+
+int ia32_setup_frame(struct ksignal *ksig, struct pt_regs *regs);
+int ia32_setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs);
+int x64_setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs);
+int x32_setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs);
+
#endif /* _ASM_X86_SIGHANDLING_H */
diff --git a/arch/x86/include/asm/signal.h b/arch/x86/include/asm/signal.h
index 2dfb5fea13af..4a4043ca6493 100644
--- a/arch/x86/include/asm/signal.h
+++ b/arch/x86/include/asm/signal.h
@@ -28,11 +28,6 @@ typedef struct {
#define SA_IA32_ABI 0x02000000u
#define SA_X32_ABI 0x01000000u
-#ifndef CONFIG_COMPAT
-#define compat_sigset_t compat_sigset_t
-typedef sigset_t compat_sigset_t;
-#endif
-
#endif /* __ASSEMBLY__ */
#include <uapi/asm/signal.h>
#ifndef __ASSEMBLY__
diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h
index 24a8d6c4fb18..00473a650f51 100644
--- a/arch/x86/include/asm/stackprotector.h
+++ b/arch/x86/include/asm/stackprotector.h
@@ -34,7 +34,6 @@
#include <asm/percpu.h>
#include <asm/desc.h>
-#include <linux/random.h>
#include <linux/sched.h>
/*
@@ -50,22 +49,11 @@
*/
static __always_inline void boot_init_stack_canary(void)
{
- u64 canary;
- u64 tsc;
+ unsigned long canary = get_random_canary();
#ifdef CONFIG_X86_64
BUILD_BUG_ON(offsetof(struct fixed_percpu_data, stack_canary) != 40);
#endif
- /*
- * We both use the random pool and the current TSC as a source
- * of randomness. The TSC only matters for very early init,
- * there it already has some randomness on most systems. Later
- * on during the bootup the random pool has true entropy too.
- */
- get_random_bytes(&canary, sizeof(canary));
- tsc = rdtsc();
- canary += tsc + (tsc << 32UL);
- canary &= CANARY_MASK;
current->stack_canary = canary;
#ifdef CONFIG_X86_64
diff --git a/arch/x86/include/asm/switch_to.h b/arch/x86/include/asm/switch_to.h
index c08eb0fdd11f..5c91305d09d2 100644
--- a/arch/x86/include/asm/switch_to.h
+++ b/arch/x86/include/asm/switch_to.h
@@ -66,13 +66,10 @@ static inline void update_task_stack(struct task_struct *task)
{
/* sp0 always points to the entry trampoline stack, which is constant: */
#ifdef CONFIG_X86_32
- if (static_cpu_has(X86_FEATURE_XENPV))
- load_sp0(task->thread.sp0);
- else
- this_cpu_write(cpu_tss_rw.x86_tss.sp1, task->thread.sp0);
+ this_cpu_write(cpu_tss_rw.x86_tss.sp1, task->thread.sp0);
#else
/* Xen PV enters the kernel on the thread stack. */
- if (static_cpu_has(X86_FEATURE_XENPV))
+ if (cpu_feature_enabled(X86_FEATURE_XENPV))
load_sp0(task_top_of_stack(task));
#endif
}
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index 020c81a7c729..28d889c9aa16 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -67,6 +67,8 @@ void tdx_safe_halt(void);
bool tdx_early_handle_ve(struct pt_regs *regs);
+int tdx_mcall_get_report0(u8 *reportdata, u8 *tdreport);
+
#else
static inline void tdx_early_init(void) { };
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index e9170457697e..c1c8c581759d 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -285,6 +285,8 @@ struct x86_hyper_runtime {
* possible in x86_early_init_platform_quirks() by
* only using the current x86_hardware_subarch
* semantics.
+ * @realmode_reserve: reserve memory for realmode trampoline
+ * @realmode_init: initialize realmode trampoline
* @hyper: x86 hypervisor specific runtime callbacks
*/
struct x86_platform_ops {
@@ -301,6 +303,8 @@ struct x86_platform_ops {
void (*apic_post_init)(void);
struct x86_legacy_features legacy;
void (*set_legacy_features)(void);
+ void (*realmode_reserve)(void);
+ void (*realmode_init)(void);
struct x86_hyper_runtime hyper;
struct x86_guest guest;
};
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index f901658d9f7c..cceaafdd2d84 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -44,7 +44,7 @@ obj-y += head_$(BITS).o
obj-y += head$(BITS).o
obj-y += ebda.o
obj-y += platform-quirks.o
-obj-y += process_$(BITS).o signal.o
+obj-y += process_$(BITS).o signal.o signal_$(BITS).o
obj-$(CONFIG_COMPAT) += signal_compat.o
obj-y += traps.o idt.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
obj-y += time.o ioport.o dumpstack.o nmi.o
@@ -54,7 +54,7 @@ obj-$(CONFIG_JUMP_LABEL) += jump_label.o
obj-$(CONFIG_IRQ_WORK) += irq_work.o
obj-y += probe_roms.o
obj-$(CONFIG_X86_32) += sys_ia32.o
-obj-$(CONFIG_IA32_EMULATION) += sys_ia32.o
+obj-$(CONFIG_IA32_EMULATION) += sys_ia32.o signal_32.o
obj-$(CONFIG_X86_64) += sys_x86_64.o
obj-$(CONFIG_X86_ESPFIX64) += espfix_64.o
obj-$(CONFIG_SYSFS) += ksysfs.o
diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
index 7945eae5b315..401808b47af3 100644
--- a/arch/x86/kernel/acpi/cstate.c
+++ b/arch/x86/kernel/acpi/cstate.c
@@ -52,17 +52,25 @@ void acpi_processor_power_init_bm_check(struct acpi_processor_flags *flags,
if (c->x86_vendor == X86_VENDOR_INTEL &&
(c->x86 > 0xf || (c->x86 == 6 && c->x86_model >= 0x0f)))
flags->bm_control = 0;
- /*
- * For all recent Centaur CPUs, the ucode will make sure that each
- * core can keep cache coherence with each other while entering C3
- * type state. So, set bm_check to 1 to indicate that the kernel
- * doesn't need to execute a cache flush operation (WBINVD) when
- * entering C3 type state.
- */
+
if (c->x86_vendor == X86_VENDOR_CENTAUR) {
if (c->x86 > 6 || (c->x86 == 6 && c->x86_model == 0x0f &&
- c->x86_stepping >= 0x0e))
+ c->x86_stepping >= 0x0e)) {
+ /*
+ * For all recent Centaur CPUs, the ucode will make sure that each
+ * core can keep cache coherence with each other while entering C3
+ * type state. So, set bm_check to 1 to indicate that the kernel
+ * doesn't need to execute a cache flush operation (WBINVD) when
+ * entering C3 type state.
+ */
flags->bm_check = 1;
+ /*
+ * For all recent Centaur platforms, ARB_DISABLE is a nop.
+ * Set bm_control to zero to indicate that ARB_DISABLE is
+ * not required while entering C3 type state.
+ */
+ flags->bm_control = 0;
+ }
}
if (c->x86_vendor == X86_VENDOR_ZHAOXIN) {
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 5cadcea035e0..a9bea860e22a 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -624,7 +624,7 @@ void __init_or_module noinline apply_ibt_endbr(s32 *start, s32 *end)
#else
-void __init_or_module noinline apply_ibt_endbr(s32 *start, s32 *end) { }
+void __init_or_module apply_ibt_endbr(s32 *start, s32 *end) { }
#endif /* CONFIG_X86_KERNEL_IBT */
@@ -1608,7 +1608,7 @@ static void text_poke_loc_init(struct text_poke_loc *tp, void *addr,
default:
BUG_ON(len != insn.length);
- };
+ }
switch (tp->opcode) {
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index c6876d3ea4b1..20d9a604da7c 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1931,16 +1931,19 @@ void __init check_x2apic(void)
}
}
#else /* CONFIG_X86_X2APIC */
-static int __init validate_x2apic(void)
+void __init check_x2apic(void)
{
if (!apic_is_x2apic_enabled())
- return 0;
+ return;
/*
- * Checkme: Can we simply turn off x2apic here instead of panic?
+ * Checkme: Can we simply turn off x2APIC here instead of disabling the APIC?
*/
- panic("BIOS has enabled x2apic but kernel doesn't support x2apic, please disable x2apic in BIOS.\n");
+ pr_err("Kernel does not support x2APIC, please recompile with CONFIG_X86_X2APIC.\n");
+ pr_err("Disabling APIC, expect reduced performance and functionality.\n");
+
+ disable_apic = 1;
+ setup_clear_cpu_cap(X86_FEATURE_APIC);
}
-early_initcall(validate_x2apic);
static inline void try_to_enable_x2apic(int remap_mode) { }
static inline void __x2apic_enable(void) { }
diff --git a/arch/x86/kernel/apic/msi.c b/arch/x86/kernel/apic/msi.c
index 7517eb05bdc1..35d5b8fb18ef 100644
--- a/arch/x86/kernel/apic/msi.c
+++ b/arch/x86/kernel/apic/msi.c
@@ -142,70 +142,139 @@ msi_set_affinity(struct irq_data *irqd, const struct cpumask *mask, bool force)
return ret;
}
-/*
- * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
- * which implement the MSI or MSI-X Capability Structure.
+/**
+ * pci_dev_has_default_msi_parent_domain - Check whether the device has the default
+ * MSI parent domain associated
+ * @dev: Pointer to the PCI device
*/
-static struct irq_chip pci_msi_controller = {
- .name = "PCI-MSI",
- .irq_unmask = pci_msi_unmask_irq,
- .irq_mask = pci_msi_mask_irq,
- .irq_ack = irq_chip_ack_parent,
- .irq_retrigger = irq_chip_retrigger_hierarchy,
- .irq_set_affinity = msi_set_affinity,
- .flags = IRQCHIP_SKIP_SET_WAKE |
- IRQCHIP_AFFINITY_PRE_STARTUP,
-};
+bool pci_dev_has_default_msi_parent_domain(struct pci_dev *dev)
+{
+ struct irq_domain *domain = dev_get_msi_domain(&dev->dev);
-int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec,
- msi_alloc_info_t *arg)
+ if (!domain)
+ domain = dev_get_msi_domain(&dev->bus->dev);
+ if (!domain)
+ return false;
+
+ return domain == x86_vector_domain;
+}
+
+/**
+ * x86_msi_prepare - Setup of msi_alloc_info_t for allocations
+ * @domain: The domain for which this setup happens
+ * @dev: The device for which interrupts are allocated
+ * @nvec: The number of vectors to allocate
+ * @alloc: The allocation info structure to initialize
+ *
+ * This function is to be used for all types of MSI domains above the x86
+ * vector domain and any intermediates. It is always invoked from the
+ * top level interrupt domain. The domain specific allocation
+ * functionality is determined via the @domain's bus token which allows to
+ * map the X86 specific allocation type.
+ */
+static int x86_msi_prepare(struct irq_domain *domain, struct device *dev,
+ int nvec, msi_alloc_info_t *alloc)
{
- init_irq_alloc_info(arg, NULL);
- if (to_pci_dev(dev)->msix_enabled) {
- arg->type = X86_IRQ_ALLOC_TYPE_PCI_MSIX;
- } else {
- arg->type = X86_IRQ_ALLOC_TYPE_PCI_MSI;
- arg->flags |= X86_IRQ_ALLOC_CONTIGUOUS_VECTORS;
+ struct msi_domain_info *info = domain->host_data;
+
+ init_irq_alloc_info(alloc, NULL);
+
+ switch (info->bus_token) {
+ case DOMAIN_BUS_PCI_DEVICE_MSI:
+ alloc->type = X86_IRQ_ALLOC_TYPE_PCI_MSI;
+ return 0;
+ case DOMAIN_BUS_PCI_DEVICE_MSIX:
+ case DOMAIN_BUS_PCI_DEVICE_IMS:
+ alloc->type = X86_IRQ_ALLOC_TYPE_PCI_MSIX;
+ return 0;
+ default:
+ return -EINVAL;
}
-
- return 0;
}
-EXPORT_SYMBOL_GPL(pci_msi_prepare);
-static struct msi_domain_ops pci_msi_domain_ops = {
- .msi_prepare = pci_msi_prepare,
-};
+/**
+ * x86_init_dev_msi_info - Domain info setup for MSI domains
+ * @dev: The device for which the domain should be created
+ * @domain: The (root) domain providing this callback
+ * @real_parent: The real parent domain of the to initialize domain
+ * @info: The domain info for the to initialize domain
+ *
+ * This function is to be used for all types of MSI domains above the x86
+ * vector domain and any intermediates. The domain specific functionality
+ * is determined via the @real_parent.
+ */
+static bool x86_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
+ struct irq_domain *real_parent, struct msi_domain_info *info)
+{
+ const struct msi_parent_ops *pops = real_parent->msi_parent_ops;
+
+ /* MSI parent domain specific settings */
+ switch (real_parent->bus_token) {
+ case DOMAIN_BUS_ANY:
+ /* Only the vector domain can have the ANY token */
+ if (WARN_ON_ONCE(domain != real_parent))
+ return false;
+ info->chip->irq_set_affinity = msi_set_affinity;
+ /* See msi_set_affinity() for the gory details */
+ info->flags |= MSI_FLAG_NOMASK_QUIRK;
+ break;
+ case DOMAIN_BUS_DMAR:
+ case DOMAIN_BUS_AMDVI:
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ return false;
+ }
+
+ /* Is the target supported? */
+ switch(info->bus_token) {
+ case DOMAIN_BUS_PCI_DEVICE_MSI:
+ case DOMAIN_BUS_PCI_DEVICE_MSIX:
+ break;
+ case DOMAIN_BUS_PCI_DEVICE_IMS:
+ if (!(pops->supported_flags & MSI_FLAG_PCI_IMS))
+ return false;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ return false;
+ }
+
+ /*
+ * Mask out the domain specific MSI feature flags which are not
+ * supported by the real parent.
+ */
+ info->flags &= pops->supported_flags;
+ /* Enforce the required flags */
+ info->flags |= X86_VECTOR_MSI_FLAGS_REQUIRED;
+
+ /* This is always invoked from the top level MSI domain! */
+ info->ops->msi_prepare = x86_msi_prepare;
+
+ info->chip->irq_ack = irq_chip_ack_parent;
+ info->chip->irq_retrigger = irq_chip_retrigger_hierarchy;
+ info->chip->flags |= IRQCHIP_SKIP_SET_WAKE |
+ IRQCHIP_AFFINITY_PRE_STARTUP;
-static struct msi_domain_info pci_msi_domain_info = {
- .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
- MSI_FLAG_PCI_MSIX,
- .ops = &pci_msi_domain_ops,
- .chip = &pci_msi_controller,
- .handler = handle_edge_irq,
- .handler_name = "edge",
+ info->handler = handle_edge_irq;
+ info->handler_name = "edge";
+
+ return true;
+}
+
+static const struct msi_parent_ops x86_vector_msi_parent_ops = {
+ .supported_flags = X86_VECTOR_MSI_FLAGS_SUPPORTED,
+ .init_dev_msi_info = x86_init_dev_msi_info,
};
struct irq_domain * __init native_create_pci_msi_domain(void)
{
- struct fwnode_handle *fn;
- struct irq_domain *d;
-
if (disable_apic)
return NULL;
- fn = irq_domain_alloc_named_fwnode("PCI-MSI");
- if (!fn)
- return NULL;
-
- d = pci_msi_create_irq_domain(fn, &pci_msi_domain_info,
- x86_vector_domain);
- if (!d) {
- irq_domain_free_fwnode(fn);
- pr_warn("Failed to initialize PCI-MSI irqdomain.\n");
- } else {
- d->flags |= IRQ_DOMAIN_MSI_NOMASK_QUIRK;
- }
- return d;
+ x86_vector_domain->flags |= IRQ_DOMAIN_FLAG_MSI_PARENT;
+ x86_vector_domain->msi_parent_ops = &x86_vector_msi_parent_ops;
+ return x86_vector_domain;
}
void __init x86_create_pci_msi_domain(void)
@@ -213,41 +282,19 @@ void __init x86_create_pci_msi_domain(void)
x86_pci_msi_default_domain = x86_init.irqs.create_pci_msi_domain();
}
-#ifdef CONFIG_IRQ_REMAP
-static struct irq_chip pci_msi_ir_controller = {
- .name = "IR-PCI-MSI",
- .irq_unmask = pci_msi_unmask_irq,
- .irq_mask = pci_msi_mask_irq,
- .irq_ack = irq_chip_ack_parent,
- .irq_retrigger = irq_chip_retrigger_hierarchy,
- .flags = IRQCHIP_SKIP_SET_WAKE |
- IRQCHIP_AFFINITY_PRE_STARTUP,
-};
-
-static struct msi_domain_info pci_msi_ir_domain_info = {
- .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
- MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX,
- .ops = &pci_msi_domain_ops,
- .chip = &pci_msi_ir_controller,
- .handler = handle_edge_irq,
- .handler_name = "edge",
-};
-
-struct irq_domain *arch_create_remap_msi_irq_domain(struct irq_domain *parent,
- const char *name, int id)
+/* Keep around for hyperV */
+int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec,
+ msi_alloc_info_t *arg)
{
- struct fwnode_handle *fn;
- struct irq_domain *d;
+ init_irq_alloc_info(arg, NULL);
- fn = irq_domain_alloc_named_id_fwnode(name, id);
- if (!fn)
- return NULL;
- d = pci_msi_create_irq_domain(fn, &pci_msi_ir_domain_info, parent);
- if (!d)
- irq_domain_free_fwnode(fn);
- return d;
+ if (to_pci_dev(dev)->msix_enabled)
+ arg->type = X86_IRQ_ALLOC_TYPE_PCI_MSIX;
+ else
+ arg->type = X86_IRQ_ALLOC_TYPE_PCI_MSI;
+ return 0;
}
-#endif
+EXPORT_SYMBOL_GPL(pci_msi_prepare);
#ifdef CONFIG_DMAR_TABLE
/*
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
index 3e6f6b448f6a..c1efebd27e6c 100644
--- a/arch/x86/kernel/apic/vector.c
+++ b/arch/x86/kernel/apic/vector.c
@@ -539,10 +539,6 @@ static int x86_vector_alloc_irqs(struct irq_domain *domain, unsigned int virq,
if (disable_apic)
return -ENXIO;
- /* Currently vector allocator can't guarantee contiguous allocations */
- if ((info->flags & X86_IRQ_ALLOC_CONTIGUOUS_VECTORS) && nr_irqs > 1)
- return -ENOSYS;
-
/*
* Catch any attempt to touch the cascade interrupt on a PIC
* equipped system.
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index c75d75b9f11a..f769d6d08b43 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -983,7 +983,7 @@ static void init_amd(struct cpuinfo_x86 *c)
set_cpu_cap(c, X86_FEATURE_3DNOWPREFETCH);
/* AMD CPUs don't reset SS attributes on SYSRET, Xen does. */
- if (!cpu_has(c, X86_FEATURE_XENPV))
+ if (!cpu_feature_enabled(X86_FEATURE_XENPV))
set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
/*
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index 6daf84229548..a8a5033a804d 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -1302,7 +1302,7 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
return SPECTRE_V2_CMD_AUTO;
}
- if (cmd == SPECTRE_V2_CMD_IBRS && boot_cpu_has(X86_FEATURE_XENPV)) {
+ if (cmd == SPECTRE_V2_CMD_IBRS && cpu_feature_enabled(X86_FEATURE_XENPV)) {
pr_err("%s selected but running as XenPV guest. Switching to AUTO select\n",
mitigation_options[i].option);
return SPECTRE_V2_CMD_AUTO;
@@ -2206,74 +2206,74 @@ static const char * const l1tf_vmx_states[] = {
static ssize_t l1tf_show_state(char *buf)
{
if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_AUTO)
- return sprintf(buf, "%s\n", L1TF_DEFAULT_MSG);
+ return sysfs_emit(buf, "%s\n", L1TF_DEFAULT_MSG);
if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_EPT_DISABLED ||
(l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_NEVER &&
sched_smt_active())) {
- return sprintf(buf, "%s; VMX: %s\n", L1TF_DEFAULT_MSG,
- l1tf_vmx_states[l1tf_vmx_mitigation]);
+ return sysfs_emit(buf, "%s; VMX: %s\n", L1TF_DEFAULT_MSG,
+ l1tf_vmx_states[l1tf_vmx_mitigation]);
}
- return sprintf(buf, "%s; VMX: %s, SMT %s\n", L1TF_DEFAULT_MSG,
- l1tf_vmx_states[l1tf_vmx_mitigation],
- sched_smt_active() ? "vulnerable" : "disabled");
+ return sysfs_emit(buf, "%s; VMX: %s, SMT %s\n", L1TF_DEFAULT_MSG,
+ l1tf_vmx_states[l1tf_vmx_mitigation],
+ sched_smt_active() ? "vulnerable" : "disabled");
}
static ssize_t itlb_multihit_show_state(char *buf)
{
if (!boot_cpu_has(X86_FEATURE_MSR_IA32_FEAT_CTL) ||
!boot_cpu_has(X86_FEATURE_VMX))
- return sprintf(buf, "KVM: Mitigation: VMX unsupported\n");
+ return sysfs_emit(buf, "KVM: Mitigation: VMX unsupported\n");
else if (!(cr4_read_shadow() & X86_CR4_VMXE))
- return sprintf(buf, "KVM: Mitigation: VMX disabled\n");
+ return sysfs_emit(buf, "KVM: Mitigation: VMX disabled\n");
else if (itlb_multihit_kvm_mitigation)
- return sprintf(buf, "KVM: Mitigation: Split huge pages\n");
+ return sysfs_emit(buf, "KVM: Mitigation: Split huge pages\n");
else
- return sprintf(buf, "KVM: Vulnerable\n");
+ return sysfs_emit(buf, "KVM: Vulnerable\n");
}
#else
static ssize_t l1tf_show_state(char *buf)
{
- return sprintf(buf, "%s\n", L1TF_DEFAULT_MSG);
+ return sysfs_emit(buf, "%s\n", L1TF_DEFAULT_MSG);
}
static ssize_t itlb_multihit_show_state(char *buf)
{
- return sprintf(buf, "Processor vulnerable\n");
+ return sysfs_emit(buf, "Processor vulnerable\n");
}
#endif
static ssize_t mds_show_state(char *buf)
{
if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
- return sprintf(buf, "%s; SMT Host state unknown\n",
- mds_strings[mds_mitigation]);
+ return sysfs_emit(buf, "%s; SMT Host state unknown\n",
+ mds_strings[mds_mitigation]);
}
if (boot_cpu_has(X86_BUG_MSBDS_ONLY)) {
- return sprintf(buf, "%s; SMT %s\n", mds_strings[mds_mitigation],
- (mds_mitigation == MDS_MITIGATION_OFF ? "vulnerable" :
- sched_smt_active() ? "mitigated" : "disabled"));
+ return sysfs_emit(buf, "%s; SMT %s\n", mds_strings[mds_mitigation],
+ (mds_mitigation == MDS_MITIGATION_OFF ? "vulnerable" :
+ sched_smt_active() ? "mitigated" : "disabled"));
}
- return sprintf(buf, "%s; SMT %s\n", mds_strings[mds_mitigation],
- sched_smt_active() ? "vulnerable" : "disabled");
+ return sysfs_emit(buf, "%s; SMT %s\n", mds_strings[mds_mitigation],
+ sched_smt_active() ? "vulnerable" : "disabled");
}
static ssize_t tsx_async_abort_show_state(char *buf)
{
if ((taa_mitigation == TAA_MITIGATION_TSX_DISABLED) ||
(taa_mitigation == TAA_MITIGATION_OFF))
- return sprintf(buf, "%s\n", taa_strings[taa_mitigation]);
+ return sysfs_emit(buf, "%s\n", taa_strings[taa_mitigation]);
if (boot_cpu_has(X86_FEATURE_HYPERVISOR)) {
- return sprintf(buf, "%s; SMT Host state unknown\n",
- taa_strings[taa_mitigation]);
+ return sysfs_emit(buf, "%s; SMT Host state unknown\n",
+ taa_strings[taa_mitigation]);
}
- return sprintf(buf, "%s; SMT %s\n", taa_strings[taa_mitigation],
- sched_smt_active() ? "vulnerable" : "disabled");
+ return sysfs_emit(buf, "%s; SMT %s\n", taa_strings[taa_mitigation],
+ sched_smt_active() ? "vulnerable" : "disabled");
}
static ssize_t mmio_stale_data_show_state(char *buf)
@@ -2341,73 +2341,72 @@ static char *pbrsb_eibrs_state(void)
static ssize_t spectre_v2_show_state(char *buf)
{
if (spectre_v2_enabled == SPECTRE_V2_LFENCE)
- return sprintf(buf, "Vulnerable: LFENCE\n");
+ return sysfs_emit(buf, "Vulnerable: LFENCE\n");
if (spectre_v2_enabled == SPECTRE_V2_EIBRS && unprivileged_ebpf_enabled())
- return sprintf(buf, "Vulnerable: eIBRS with unprivileged eBPF\n");
+ return sysfs_emit(buf, "Vulnerable: eIBRS with unprivileged eBPF\n");
if (sched_smt_active() && unprivileged_ebpf_enabled() &&
spectre_v2_enabled == SPECTRE_V2_EIBRS_LFENCE)
- return sprintf(buf, "Vulnerable: eIBRS+LFENCE with unprivileged eBPF and SMT\n");
+ return sysfs_emit(buf, "Vulnerable: eIBRS+LFENCE with unprivileged eBPF and SMT\n");
- return sprintf(buf, "%s%s%s%s%s%s%s\n",
- spectre_v2_strings[spectre_v2_enabled],
- ibpb_state(),
- boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
- stibp_state(),
- boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "",
- pbrsb_eibrs_state(),
- spectre_v2_module_string());
+ return sysfs_emit(buf, "%s%s%s%s%s%s%s\n",
+ spectre_v2_strings[spectre_v2_enabled],
+ ibpb_state(),
+ boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
+ stibp_state(),
+ boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "",
+ pbrsb_eibrs_state(),
+ spectre_v2_module_string());
}
static ssize_t srbds_show_state(char *buf)
{
- return sprintf(buf, "%s\n", srbds_strings[srbds_mitigation]);
+ return sysfs_emit(buf, "%s\n", srbds_strings[srbds_mitigation]);
}
static ssize_t retbleed_show_state(char *buf)
{
if (retbleed_mitigation == RETBLEED_MITIGATION_UNRET ||
retbleed_mitigation == RETBLEED_MITIGATION_IBPB) {
- if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
- boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
- return sprintf(buf, "Vulnerable: untrained return thunk / IBPB on non-AMD based uarch\n");
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
+ boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
+ return sysfs_emit(buf, "Vulnerable: untrained return thunk / IBPB on non-AMD based uarch\n");
- return sprintf(buf, "%s; SMT %s\n",
- retbleed_strings[retbleed_mitigation],
- !sched_smt_active() ? "disabled" :
- spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
- spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED ?
- "enabled with STIBP protection" : "vulnerable");
+ return sysfs_emit(buf, "%s; SMT %s\n", retbleed_strings[retbleed_mitigation],
+ !sched_smt_active() ? "disabled" :
+ spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT ||
+ spectre_v2_user_stibp == SPECTRE_V2_USER_STRICT_PREFERRED ?
+ "enabled with STIBP protection" : "vulnerable");
}
- return sprintf(buf, "%s\n", retbleed_strings[retbleed_mitigation]);
+ return sysfs_emit(buf, "%s\n", retbleed_strings[retbleed_mitigation]);
}
static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
char *buf, unsigned int bug)
{
if (!boot_cpu_has_bug(bug))
- return sprintf(buf, "Not affected\n");
+ return sysfs_emit(buf, "Not affected\n");
switch (bug) {
case X86_BUG_CPU_MELTDOWN:
if (boot_cpu_has(X86_FEATURE_PTI))
- return sprintf(buf, "Mitigation: PTI\n");
+ return sysfs_emit(buf, "Mitigation: PTI\n");
if (hypervisor_is_type(X86_HYPER_XEN_PV))
- return sprintf(buf, "Unknown (XEN PV detected, hypervisor mitigation required)\n");
+ return sysfs_emit(buf, "Unknown (XEN PV detected, hypervisor mitigation required)\n");
break;
case X86_BUG_SPECTRE_V1:
- return sprintf(buf, "%s\n", spectre_v1_strings[spectre_v1_mitigation]);
+ return sysfs_emit(buf, "%s\n", spectre_v1_strings[spectre_v1_mitigation]);
case X86_BUG_SPECTRE_V2:
return spectre_v2_show_state(buf);
case X86_BUG_SPEC_STORE_BYPASS:
- return sprintf(buf, "%s\n", ssb_strings[ssb_mode]);
+ return sysfs_emit(buf, "%s\n", ssb_strings[ssb_mode]);
case X86_BUG_L1TF:
if (boot_cpu_has(X86_FEATURE_L1TF_PTEINV))
@@ -2437,7 +2436,7 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
break;
}
- return sprintf(buf, "Vulnerable\n");
+ return sysfs_emit(buf, "Vulnerable\n");
}
ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf)
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index 66556833d7af..f4e5aa27eec6 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -11,15 +11,19 @@
#include <linux/slab.h>
#include <linux/cacheinfo.h>
#include <linux/cpu.h>
+#include <linux/cpuhotplug.h>
#include <linux/sched.h>
#include <linux/capability.h>
#include <linux/sysfs.h>
#include <linux/pci.h>
+#include <linux/stop_machine.h>
#include <asm/cpufeature.h>
#include <asm/cacheinfo.h>
#include <asm/amd_nb.h>
#include <asm/smp.h>
+#include <asm/mtrr.h>
+#include <asm/tlbflush.h>
#include "cpu.h"
@@ -35,6 +39,9 @@ DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_llc_shared_map);
/* Shared L2 cache maps */
DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_l2c_shared_map);
+/* Kernel controls MTRR and/or PAT MSRs. */
+unsigned int memory_caching_control __ro_after_init;
+
struct _cache_table {
unsigned char descriptor;
char cache_type;
@@ -1040,3 +1047,175 @@ int populate_cache_leaves(unsigned int cpu)
return 0;
}
+
+/*
+ * Disable and enable caches. Needed for changing MTRRs and the PAT MSR.
+ *
+ * Since we are disabling the cache don't allow any interrupts,
+ * they would run extremely slow and would only increase the pain.
+ *
+ * The caller must ensure that local interrupts are disabled and
+ * are reenabled after cache_enable() has been called.
+ */
+static unsigned long saved_cr4;
+static DEFINE_RAW_SPINLOCK(cache_disable_lock);
+
+void cache_disable(void) __acquires(cache_disable_lock)
+{
+ unsigned long cr0;
+
+ /*
+ * Note that this is not ideal
+ * since the cache is only flushed/disabled for this CPU while the
+ * MTRRs are changed, but changing this requires more invasive
+ * changes to the way the kernel boots
+ */
+
+ raw_spin_lock(&cache_disable_lock);
+
+ /* Enter the no-fill (CD=1, NW=0) cache mode and flush caches. */
+ cr0 = read_cr0() | X86_CR0_CD;
+ write_cr0(cr0);
+
+ /*
+ * Cache flushing is the most time-consuming step when programming
+ * the MTRRs. Fortunately, as per the Intel Software Development
+ * Manual, we can skip it if the processor supports cache self-
+ * snooping.
+ */
+ if (!static_cpu_has(X86_FEATURE_SELFSNOOP))
+ wbinvd();
+
+ /* Save value of CR4 and clear Page Global Enable (bit 7) */
+ if (cpu_feature_enabled(X86_FEATURE_PGE)) {
+ saved_cr4 = __read_cr4();
+ __write_cr4(saved_cr4 & ~X86_CR4_PGE);
+ }
+
+ /* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */
+ count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
+ flush_tlb_local();
+
+ if (cpu_feature_enabled(X86_FEATURE_MTRR))
+ mtrr_disable();
+
+ /* Again, only flush caches if we have to. */
+ if (!static_cpu_has(X86_FEATURE_SELFSNOOP))
+ wbinvd();
+}
+
+void cache_enable(void) __releases(cache_disable_lock)
+{
+ /* Flush TLBs (no need to flush caches - they are disabled) */
+ count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
+ flush_tlb_local();
+
+ if (cpu_feature_enabled(X86_FEATURE_MTRR))
+ mtrr_enable();
+
+ /* Enable caches */
+ write_cr0(read_cr0() & ~X86_CR0_CD);
+
+ /* Restore value of CR4 */
+ if (cpu_feature_enabled(X86_FEATURE_PGE))
+ __write_cr4(saved_cr4);
+
+ raw_spin_unlock(&cache_disable_lock);
+}
+
+static void cache_cpu_init(void)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ cache_disable();
+
+ if (memory_caching_control & CACHE_MTRR)
+ mtrr_generic_set_state();
+
+ if (memory_caching_control & CACHE_PAT)
+ pat_cpu_init();
+
+ cache_enable();
+ local_irq_restore(flags);
+}
+
+static bool cache_aps_delayed_init = true;
+
+void set_cache_aps_delayed_init(bool val)
+{
+ cache_aps_delayed_init = val;
+}
+
+bool get_cache_aps_delayed_init(void)
+{
+ return cache_aps_delayed_init;
+}
+
+static int cache_rendezvous_handler(void *unused)
+{
+ if (get_cache_aps_delayed_init() || !cpu_online(smp_processor_id()))
+ cache_cpu_init();
+
+ return 0;
+}
+
+void __init cache_bp_init(void)
+{
+ mtrr_bp_init();
+ pat_bp_init();
+
+ if (memory_caching_control)
+ cache_cpu_init();
+}
+
+void cache_bp_restore(void)
+{
+ if (memory_caching_control)
+ cache_cpu_init();
+}
+
+static int cache_ap_init(unsigned int cpu)
+{
+ if (!memory_caching_control || get_cache_aps_delayed_init())
+ return 0;
+
+ /*
+ * Ideally we should hold mtrr_mutex here to avoid MTRR entries
+ * changed, but this routine will be called in CPU boot time,
+ * holding the lock breaks it.
+ *
+ * This routine is called in two cases:
+ *
+ * 1. very early time of software resume, when there absolutely
+ * isn't MTRR entry changes;
+ *
+ * 2. CPU hotadd time. We let mtrr_add/del_page hold cpuhotplug
+ * lock to prevent MTRR entry changes
+ */
+ stop_machine_from_inactive_cpu(cache_rendezvous_handler, NULL,
+ cpu_callout_mask);
+
+ return 0;
+}
+
+/*
+ * Delayed cache initialization for all AP's
+ */
+void cache_aps_init(void)
+{
+ if (!memory_caching_control || !get_cache_aps_delayed_init())
+ return;
+
+ stop_machine(cache_rendezvous_handler, NULL, cpu_online_mask);
+ set_cache_aps_delayed_init(false);
+}
+
+static int __init cache_ap_register(void)
+{
+ cpuhp_setup_state_nocalls(CPUHP_AP_CACHECTRL_STARTING,
+ "x86/cachectrl:starting",
+ cache_ap_init, NULL);
+ return 0;
+}
+core_initcall(cache_ap_register);
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 3e508f239098..62b83bc5b4b9 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -22,9 +22,9 @@
#include <linux/io.h>
#include <linux/syscore_ops.h>
#include <linux/pgtable.h>
+#include <linux/stackprotector.h>
#include <asm/cmdline.h>
-#include <asm/stackprotector.h>
#include <asm/perf_event.h>
#include <asm/mmu_context.h>
#include <asm/doublefault.h>
@@ -52,6 +52,7 @@
#include <asm/cpu.h>
#include <asm/mce.h>
#include <asm/msr.h>
+#include <asm/cacheinfo.h>
#include <asm/memtype.h>
#include <asm/microcode.h>
#include <asm/microcode_intel.h>
@@ -1948,7 +1949,6 @@ void identify_secondary_cpu(struct cpuinfo_x86 *c)
#ifdef CONFIG_X86_32
enable_sep_cpu();
#endif
- mtrr_ap_init();
validate_apic_and_package_id(c);
x86_spec_ctrl_setup_ap();
update_srbds_msr();
diff --git a/arch/x86/kernel/cpu/cpuid-deps.c b/arch/x86/kernel/cpu/cpuid-deps.c
index c881bcafba7d..d95221117129 100644
--- a/arch/x86/kernel/cpu/cpuid-deps.c
+++ b/arch/x86/kernel/cpu/cpuid-deps.c
@@ -75,6 +75,7 @@ static const struct cpuid_dep cpuid_deps[] = {
{ X86_FEATURE_SGX_LC, X86_FEATURE_SGX },
{ X86_FEATURE_SGX1, X86_FEATURE_SGX },
{ X86_FEATURE_SGX2, X86_FEATURE_SGX1 },
+ { X86_FEATURE_SGX_EDECCSSA, X86_FEATURE_SGX1 },
{ X86_FEATURE_XFD, X86_FEATURE_XSAVES },
{ X86_FEATURE_XFD, X86_FEATURE_XGETBV1 },
{ X86_FEATURE_AMX_TILE, X86_FEATURE_XFD },
diff --git a/arch/x86/kernel/cpu/hygon.c b/arch/x86/kernel/cpu/hygon.c
index c393b8773ace..5a2962c492d3 100644
--- a/arch/x86/kernel/cpu/hygon.c
+++ b/arch/x86/kernel/cpu/hygon.c
@@ -339,7 +339,7 @@ static void init_hygon(struct cpuinfo_x86 *c)
set_cpu_cap(c, X86_FEATURE_ARAT);
/* Hygon CPUs don't reset SS attributes on SYSRET, Xen does. */
- if (!cpu_has(c, X86_FEATURE_XENPV))
+ if (!cpu_feature_enabled(X86_FEATURE_XENPV))
set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
check_null_seg_clears_base(c);
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 2d7ea5480ec3..291d4167fab8 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -210,12 +210,154 @@ int intel_cpu_collect_info(struct ucode_cpu_info *uci)
csig.rev = intel_get_microcode_revision();
uci->cpu_sig = csig;
- uci->valid = 1;
return 0;
}
EXPORT_SYMBOL_GPL(intel_cpu_collect_info);
+/*
+ * Returns 1 if update has been found, 0 otherwise.
+ */
+int intel_find_matching_signature(void *mc, unsigned int csig, int cpf)
+{
+ struct microcode_header_intel *mc_hdr = mc;
+ struct extended_sigtable *ext_hdr;
+ struct extended_signature *ext_sig;
+ int i;
+
+ if (intel_cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
+ return 1;
+
+ /* Look for ext. headers: */
+ if (get_totalsize(mc_hdr) <= get_datasize(mc_hdr) + MC_HEADER_SIZE)
+ return 0;
+
+ ext_hdr = mc + get_datasize(mc_hdr) + MC_HEADER_SIZE;
+ ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE;
+
+ for (i = 0; i < ext_hdr->count; i++) {
+ if (intel_cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
+ return 1;
+ ext_sig++;
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(intel_find_matching_signature);
+
+/**
+ * intel_microcode_sanity_check() - Sanity check microcode file.
+ * @mc: Pointer to the microcode file contents.
+ * @print_err: Display failure reason if true, silent if false.
+ * @hdr_type: Type of file, i.e. normal microcode file or In Field Scan file.
+ * Validate if the microcode header type matches with the type
+ * specified here.
+ *
+ * Validate certain header fields and verify if computed checksum matches
+ * with the one specified in the header.
+ *
+ * Return: 0 if the file passes all the checks, -EINVAL if any of the checks
+ * fail.
+ */
+int intel_microcode_sanity_check(void *mc, bool print_err, int hdr_type)
+{
+ unsigned long total_size, data_size, ext_table_size;
+ struct microcode_header_intel *mc_header = mc;
+ struct extended_sigtable *ext_header = NULL;
+ u32 sum, orig_sum, ext_sigcount = 0, i;
+ struct extended_signature *ext_sig;
+
+ total_size = get_totalsize(mc_header);
+ data_size = get_datasize(mc_header);
+
+ if (data_size + MC_HEADER_SIZE > total_size) {
+ if (print_err)
+ pr_err("Error: bad microcode data file size.\n");
+ return -EINVAL;
+ }
+
+ if (mc_header->ldrver != 1 || mc_header->hdrver != hdr_type) {
+ if (print_err)
+ pr_err("Error: invalid/unknown microcode update format. Header type %d\n",
+ mc_header->hdrver);
+ return -EINVAL;
+ }
+
+ ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
+ if (ext_table_size) {
+ u32 ext_table_sum = 0;
+ u32 *ext_tablep;
+
+ if (ext_table_size < EXT_HEADER_SIZE ||
+ ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
+ if (print_err)
+ pr_err("Error: truncated extended signature table.\n");
+ return -EINVAL;
+ }
+
+ ext_header = mc + MC_HEADER_SIZE + data_size;
+ if (ext_table_size != exttable_size(ext_header)) {
+ if (print_err)
+ pr_err("Error: extended signature table size mismatch.\n");
+ return -EFAULT;
+ }
+
+ ext_sigcount = ext_header->count;
+
+ /*
+ * Check extended table checksum: the sum of all dwords that
+ * comprise a valid table must be 0.
+ */
+ ext_tablep = (u32 *)ext_header;
+
+ i = ext_table_size / sizeof(u32);
+ while (i--)
+ ext_table_sum += ext_tablep[i];
+
+ if (ext_table_sum) {
+ if (print_err)
+ pr_warn("Bad extended signature table checksum, aborting.\n");
+ return -EINVAL;
+ }
+ }
+
+ /*
+ * Calculate the checksum of update data and header. The checksum of
+ * valid update data and header including the extended signature table
+ * must be 0.
+ */
+ orig_sum = 0;
+ i = (MC_HEADER_SIZE + data_size) / sizeof(u32);
+ while (i--)
+ orig_sum += ((u32 *)mc)[i];
+
+ if (orig_sum) {
+ if (print_err)
+ pr_err("Bad microcode data checksum, aborting.\n");
+ return -EINVAL;
+ }
+
+ if (!ext_table_size)
+ return 0;
+
+ /*
+ * Check extended signature checksum: 0 => valid.
+ */
+ for (i = 0; i < ext_sigcount; i++) {
+ ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
+ EXT_SIGNATURE_SIZE * i;
+
+ sum = (mc_header->sig + mc_header->pf + mc_header->cksum) -
+ (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
+ if (sum) {
+ if (print_err)
+ pr_err("Bad extended signature checksum, aborting.\n");
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(intel_microcode_sanity_check);
+
static void early_init_intel(struct cpuinfo_x86 *c)
{
u64 misc_enable;
@@ -1034,8 +1176,32 @@ static const struct {
static struct ratelimit_state bld_ratelimit;
+static unsigned int sysctl_sld_mitigate = 1;
static DEFINE_SEMAPHORE(buslock_sem);
+#ifdef CONFIG_PROC_SYSCTL
+static struct ctl_table sld_sysctls[] = {
+ {
+ .procname = "split_lock_mitigate",
+ .data = &sysctl_sld_mitigate,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_douintvec_minmax,
+ .extra1 = SYSCTL_ZERO,
+ .extra2 = SYSCTL_ONE,
+ },
+ {}
+};
+
+static int __init sld_mitigate_sysctl_init(void)
+{
+ register_sysctl_init("kernel", sld_sysctls);
+ return 0;
+}
+
+late_initcall(sld_mitigate_sysctl_init);
+#endif
+
static inline bool match_option(const char *arg, int arglen, const char *opt)
{
int len = strlen(opt), ratelimit;
@@ -1146,12 +1312,20 @@ static void split_lock_init(void)
split_lock_verify_msr(sld_state != sld_off);
}
-static void __split_lock_reenable(struct work_struct *work)
+static void __split_lock_reenable_unlock(struct work_struct *work)
{
sld_update_msr(true);
up(&buslock_sem);
}
+static DECLARE_DELAYED_WORK(sl_reenable_unlock, __split_lock_reenable_unlock);
+
+static void __split_lock_reenable(struct work_struct *work)
+{
+ sld_update_msr(true);
+}
+static DECLARE_DELAYED_WORK(sl_reenable, __split_lock_reenable);
+
/*
* If a CPU goes offline with pending delayed work to re-enable split lock
* detection then the delayed work will be executed on some other CPU. That
@@ -1169,10 +1343,9 @@ static int splitlock_cpu_offline(unsigned int cpu)
return 0;
}
-static DECLARE_DELAYED_WORK(split_lock_reenable, __split_lock_reenable);
-
static void split_lock_warn(unsigned long ip)
{
+ struct delayed_work *work;
int cpu;
if (!current->reported_split_lock)
@@ -1180,14 +1353,26 @@ static void split_lock_warn(unsigned long ip)
current->comm, current->pid, ip);
current->reported_split_lock = 1;
- /* misery factor #1, sleep 10ms before trying to execute split lock */
- if (msleep_interruptible(10) > 0)
- return;
- /* Misery factor #2, only allow one buslocked disabled core at a time */
- if (down_interruptible(&buslock_sem) == -EINTR)
- return;
+ if (sysctl_sld_mitigate) {
+ /*
+ * misery factor #1:
+ * sleep 10ms before trying to execute split lock.
+ */
+ if (msleep_interruptible(10) > 0)
+ return;
+ /*
+ * Misery factor #2:
+ * only allow one buslocked disabled core at a time.
+ */
+ if (down_interruptible(&buslock_sem) == -EINTR)
+ return;
+ work = &sl_reenable_unlock;
+ } else {
+ work = &sl_reenable;
+ }
+
cpu = get_cpu();
- schedule_delayed_work_on(cpu, &split_lock_reenable, 2);
+ schedule_delayed_work_on(cpu, work, 2);
/* Disable split lock detection on this CPU to make progress */
sld_update_msr(false);
diff --git a/arch/x86/kernel/cpu/intel_epb.c b/arch/x86/kernel/cpu/intel_epb.c
index fbaf12e43f41..3b8476158236 100644
--- a/arch/x86/kernel/cpu/intel_epb.c
+++ b/arch/x86/kernel/cpu/intel_epb.c
@@ -204,7 +204,12 @@ static int intel_epb_offline(unsigned int cpu)
}
static const struct x86_cpu_id intel_epb_normal[] = {
- X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, 7),
+ X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L,
+ ENERGY_PERF_BIAS_NORMAL_POWERSAVE),
+ X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N,
+ ENERGY_PERF_BIAS_NORMAL_POWERSAVE),
+ X86_MATCH_INTEL_FAM6_MODEL(RAPTORLAKE_P,
+ ENERGY_PERF_BIAS_NORMAL_POWERSAVE),
{}
};
diff --git a/arch/x86/kernel/cpu/mce/amd.c b/arch/x86/kernel/cpu/mce/amd.c
index 1c87501e0fa3..10fb5b5c9efa 100644
--- a/arch/x86/kernel/cpu/mce/amd.c
+++ b/arch/x86/kernel/cpu/mce/amd.c
@@ -788,6 +788,24 @@ _log_error_bank(unsigned int bank, u32 msr_stat, u32 msr_addr, u64 misc)
return status & MCI_STATUS_DEFERRED;
}
+static bool _log_error_deferred(unsigned int bank, u32 misc)
+{
+ if (!_log_error_bank(bank, mca_msr_reg(bank, MCA_STATUS),
+ mca_msr_reg(bank, MCA_ADDR), misc))
+ return false;
+
+ /*
+ * Non-SMCA systems don't have MCA_DESTAT/MCA_DEADDR registers.
+ * Return true here to avoid accessing these registers.
+ */
+ if (!mce_flags.smca)
+ return true;
+
+ /* Clear MCA_DESTAT if the deferred error was logged from MCA_STATUS. */
+ wrmsrl(MSR_AMD64_SMCA_MCx_DESTAT(bank), 0);
+ return true;
+}
+
/*
* We have three scenarios for checking for Deferred errors:
*
@@ -799,19 +817,8 @@ _log_error_bank(unsigned int bank, u32 msr_stat, u32 msr_addr, u64 misc)
*/
static void log_error_deferred(unsigned int bank)
{
- bool defrd;
-
- defrd = _log_error_bank(bank, mca_msr_reg(bank, MCA_STATUS),
- mca_msr_reg(bank, MCA_ADDR), 0);
-
- if (!mce_flags.smca)
- return;
-
- /* Clear MCA_DESTAT if we logged the deferred error from MCA_STATUS. */
- if (defrd) {
- wrmsrl(MSR_AMD64_SMCA_MCx_DESTAT(bank), 0);
+ if (_log_error_deferred(bank, 0))
return;
- }
/*
* Only deferred errors are logged in MCA_DE{STAT,ADDR} so just check
@@ -832,7 +839,7 @@ static void amd_deferred_error_interrupt(void)
static void log_error_thresholding(unsigned int bank, u64 misc)
{
- _log_error_bank(bank, mca_msr_reg(bank, MCA_STATUS), mca_msr_reg(bank, MCA_ADDR), misc);
+ _log_error_deferred(bank, misc);
}
static void log_and_reset_block(struct threshold_block *block)
diff --git a/arch/x86/kernel/cpu/mce/severity.c b/arch/x86/kernel/cpu/mce/severity.c
index 00483d1c27e4..c4477162c07d 100644
--- a/arch/x86/kernel/cpu/mce/severity.c
+++ b/arch/x86/kernel/cpu/mce/severity.c
@@ -203,6 +203,11 @@ static struct severity {
BITSET(MCI_STATUS_OVER|MCI_STATUS_UC)
),
MCESEV(
+ PANIC, "Uncorrected in kernel",
+ BITSET(MCI_STATUS_UC),
+ KERNEL
+ ),
+ MCESEV(
UC, "Uncorrected",
BITSET(MCI_STATUS_UC)
),
@@ -391,9 +396,6 @@ static noinstr int mce_severity_intel(struct mce *m, struct pt_regs *regs, char
*msg = s->msg;
s->covered = 1;
- if (s->sev >= MCE_UC_SEVERITY && ctx == IN_KERNEL)
- return MCE_PANIC_SEVERITY;
-
return s->sev;
}
}
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index 3a35dec3ec55..56471f750762 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -901,8 +901,7 @@ load_microcode_amd(bool save, u8 family, const u8 *data, size_t size)
*
* These might be larger than 2K.
*/
-static enum ucode_state request_microcode_amd(int cpu, struct device *device,
- bool refresh_fw)
+static enum ucode_state request_microcode_amd(int cpu, struct device *device)
{
char fw_name[36] = "amd-ucode/microcode_amd.bin";
struct cpuinfo_x86 *c = &cpu_data(cpu);
@@ -911,7 +910,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device,
const struct firmware *fw;
/* reload ucode container only on the boot cpu */
- if (!refresh_fw || !bsp)
+ if (!bsp)
return UCODE_OK;
if (c->x86 >= 0x15)
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 6a41cee242f6..712aafff96e0 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -319,60 +319,6 @@ void reload_early_microcode(void)
}
}
-static void collect_cpu_info_local(void *arg)
-{
- struct cpu_info_ctx *ctx = arg;
-
- ctx->err = microcode_ops->collect_cpu_info(smp_processor_id(),
- ctx->cpu_sig);
-}
-
-static int collect_cpu_info_on_target(int cpu, struct cpu_signature *cpu_sig)
-{
- struct cpu_info_ctx ctx = { .cpu_sig = cpu_sig, .err = 0 };
- int ret;
-
- ret = smp_call_function_single(cpu, collect_cpu_info_local, &ctx, 1);
- if (!ret)
- ret = ctx.err;
-
- return ret;
-}
-
-static int collect_cpu_info(int cpu)
-{
- struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
- int ret;
-
- memset(uci, 0, sizeof(*uci));
-
- ret = collect_cpu_info_on_target(cpu, &uci->cpu_sig);
- if (!ret)
- uci->valid = 1;
-
- return ret;
-}
-
-static void apply_microcode_local(void *arg)
-{
- enum ucode_state *err = arg;
-
- *err = microcode_ops->apply_microcode(smp_processor_id());
-}
-
-static int apply_microcode_on_target(int cpu)
-{
- enum ucode_state err;
- int ret;
-
- ret = smp_call_function_single(cpu, apply_microcode_local, &err, 1);
- if (!ret) {
- if (err == UCODE_ERROR)
- ret = 1;
- }
- return ret;
-}
-
/* fake device for request_firmware */
static struct platform_device *microcode_pdev;
@@ -458,7 +404,7 @@ static int __reload_late(void *info)
* below.
*/
if (cpumask_first(topology_sibling_cpumask(cpu)) == cpu)
- apply_microcode_local(&err);
+ err = microcode_ops->apply_microcode(cpu);
else
goto wait_for_siblings;
@@ -480,7 +426,7 @@ wait_for_siblings:
* revision.
*/
if (cpumask_first(topology_sibling_cpumask(cpu)) != cpu)
- apply_microcode_local(&err);
+ err = microcode_ops->apply_microcode(cpu);
return ret;
}
@@ -531,7 +477,7 @@ static ssize_t reload_store(struct device *dev,
if (ret)
goto put;
- tmp_ret = microcode_ops->request_microcode_fw(bsp, &microcode_pdev->dev, true);
+ tmp_ret = microcode_ops->request_microcode_fw(bsp, &microcode_pdev->dev);
if (tmp_ret != UCODE_NEW)
goto put;
@@ -589,91 +535,17 @@ static void microcode_fini_cpu(int cpu)
microcode_ops->microcode_fini_cpu(cpu);
}
-static enum ucode_state microcode_resume_cpu(int cpu)
+static enum ucode_state microcode_init_cpu(int cpu)
{
- if (apply_microcode_on_target(cpu))
- return UCODE_ERROR;
-
- pr_debug("CPU%d updated upon resume\n", cpu);
-
- return UCODE_OK;
-}
-
-static enum ucode_state microcode_init_cpu(int cpu, bool refresh_fw)
-{
- enum ucode_state ustate;
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
- if (uci->valid)
- return UCODE_OK;
-
- if (collect_cpu_info(cpu))
- return UCODE_ERROR;
-
- /* --dimm. Trigger a delayed update? */
- if (system_state != SYSTEM_RUNNING)
- return UCODE_NFOUND;
-
- ustate = microcode_ops->request_microcode_fw(cpu, &microcode_pdev->dev, refresh_fw);
- if (ustate == UCODE_NEW) {
- pr_debug("CPU%d updated upon init\n", cpu);
- apply_microcode_on_target(cpu);
- }
-
- return ustate;
-}
-
-static enum ucode_state microcode_update_cpu(int cpu)
-{
- struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
-
- /* Refresh CPU microcode revision after resume. */
- collect_cpu_info(cpu);
-
- if (uci->valid)
- return microcode_resume_cpu(cpu);
-
- return microcode_init_cpu(cpu, false);
-}
-
-static int mc_device_add(struct device *dev, struct subsys_interface *sif)
-{
- int err, cpu = dev->id;
-
- if (!cpu_online(cpu))
- return 0;
-
- pr_debug("CPU%d added\n", cpu);
-
- err = sysfs_create_group(&dev->kobj, &mc_attr_group);
- if (err)
- return err;
+ memset(uci, 0, sizeof(*uci));
- if (microcode_init_cpu(cpu, true) == UCODE_ERROR)
- return -EINVAL;
+ microcode_ops->collect_cpu_info(cpu, &uci->cpu_sig);
- return err;
+ return microcode_ops->apply_microcode(cpu);
}
-static void mc_device_remove(struct device *dev, struct subsys_interface *sif)
-{
- int cpu = dev->id;
-
- if (!cpu_online(cpu))
- return;
-
- pr_debug("CPU%d removed\n", cpu);
- microcode_fini_cpu(cpu);
- sysfs_remove_group(&dev->kobj, &mc_attr_group);
-}
-
-static struct subsys_interface mc_cpu_interface = {
- .name = "microcode",
- .subsys = &cpu_subsys,
- .add_dev = mc_device_add,
- .remove_dev = mc_device_remove,
-};
-
/**
* microcode_bsp_resume - Update boot CPU microcode during resume.
*/
@@ -682,21 +554,23 @@ void microcode_bsp_resume(void)
int cpu = smp_processor_id();
struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
- if (uci->valid && uci->mc)
+ if (uci->mc)
microcode_ops->apply_microcode(cpu);
- else if (!uci->mc)
+ else
reload_early_microcode();
}
static struct syscore_ops mc_syscore_ops = {
- .resume = microcode_bsp_resume,
+ .resume = microcode_bsp_resume,
};
static int mc_cpu_starting(unsigned int cpu)
{
- microcode_update_cpu(cpu);
- pr_debug("CPU%d added\n", cpu);
- return 0;
+ enum ucode_state err = microcode_ops->apply_microcode(cpu);
+
+ pr_debug("%s: CPU%d, err: %d\n", __func__, cpu, err);
+
+ return err == UCODE_ERROR;
}
static int mc_cpu_online(unsigned int cpu)
@@ -713,13 +587,30 @@ static int mc_cpu_down_prep(unsigned int cpu)
struct device *dev;
dev = get_cpu_device(cpu);
+
+ microcode_fini_cpu(cpu);
+
/* Suspend is in progress, only remove the interface */
sysfs_remove_group(&dev->kobj, &mc_attr_group);
- pr_debug("CPU%d removed\n", cpu);
+ pr_debug("%s: CPU%d\n", __func__, cpu);
return 0;
}
+static void setup_online_cpu(struct work_struct *work)
+{
+ int cpu = smp_processor_id();
+ enum ucode_state err;
+
+ err = microcode_init_cpu(cpu);
+ if (err == UCODE_ERROR) {
+ pr_err("Error applying microcode on CPU%d\n", cpu);
+ return;
+ }
+
+ mc_cpu_online(cpu);
+}
+
static struct attribute *cpu_root_microcode_attrs[] = {
#ifdef CONFIG_MICROCODE_LATE_LOADING
&dev_attr_reload.attr,
@@ -750,28 +641,19 @@ static int __init microcode_init(void)
if (!microcode_ops)
return -ENODEV;
- microcode_pdev = platform_device_register_simple("microcode", -1,
- NULL, 0);
+ microcode_pdev = platform_device_register_simple("microcode", -1, NULL, 0);
if (IS_ERR(microcode_pdev))
return PTR_ERR(microcode_pdev);
- cpus_read_lock();
- mutex_lock(&microcode_mutex);
- error = subsys_interface_register(&mc_cpu_interface);
- mutex_unlock(&microcode_mutex);
- cpus_read_unlock();
-
- if (error)
- goto out_pdev;
-
- error = sysfs_create_group(&cpu_subsys.dev_root->kobj,
- &cpu_root_microcode_group);
-
+ error = sysfs_create_group(&cpu_subsys.dev_root->kobj, &cpu_root_microcode_group);
if (error) {
pr_err("Error creating microcode group!\n");
- goto out_driver;
+ goto out_pdev;
}
+ /* Do per-CPU setup */
+ schedule_on_each_cpu(setup_online_cpu);
+
register_syscore_ops(&mc_syscore_ops);
cpuhp_setup_state_nocalls(CPUHP_AP_MICROCODE_LOADER, "x86/microcode:starting",
mc_cpu_starting, NULL);
@@ -782,15 +664,6 @@ static int __init microcode_init(void)
return 0;
- out_driver:
- cpus_read_lock();
- mutex_lock(&microcode_mutex);
-
- subsys_interface_unregister(&mc_cpu_interface);
-
- mutex_unlock(&microcode_mutex);
- cpus_read_unlock();
-
out_pdev:
platform_device_unregister(microcode_pdev);
return error;
diff --git a/arch/x86/kernel/cpu/microcode/intel.c b/arch/x86/kernel/cpu/microcode/intel.c
index 1fcbd671f1df..cac2bdb57f0b 100644
--- a/arch/x86/kernel/cpu/microcode/intel.c
+++ b/arch/x86/kernel/cpu/microcode/intel.c
@@ -48,34 +48,6 @@ static int llc_size_per_core;
/*
* Returns 1 if update has been found, 0 otherwise.
*/
-static int find_matching_signature(void *mc, unsigned int csig, int cpf)
-{
- struct microcode_header_intel *mc_hdr = mc;
- struct extended_sigtable *ext_hdr;
- struct extended_signature *ext_sig;
- int i;
-
- if (intel_cpu_signatures_match(csig, cpf, mc_hdr->sig, mc_hdr->pf))
- return 1;
-
- /* Look for ext. headers: */
- if (get_totalsize(mc_hdr) <= get_datasize(mc_hdr) + MC_HEADER_SIZE)
- return 0;
-
- ext_hdr = mc + get_datasize(mc_hdr) + MC_HEADER_SIZE;
- ext_sig = (void *)ext_hdr + EXT_HEADER_SIZE;
-
- for (i = 0; i < ext_hdr->count; i++) {
- if (intel_cpu_signatures_match(csig, cpf, ext_sig->sig, ext_sig->pf))
- return 1;
- ext_sig++;
- }
- return 0;
-}
-
-/*
- * Returns 1 if update has been found, 0 otherwise.
- */
static int has_newer_microcode(void *mc, unsigned int csig, int cpf, int new_rev)
{
struct microcode_header_intel *mc_hdr = mc;
@@ -83,7 +55,7 @@ static int has_newer_microcode(void *mc, unsigned int csig, int cpf, int new_rev
if (mc_hdr->rev <= new_rev)
return 0;
- return find_matching_signature(mc, csig, cpf);
+ return intel_find_matching_signature(mc, csig, cpf);
}
static struct ucode_patch *memdup_patch(void *data, unsigned int size)
@@ -117,7 +89,7 @@ static void save_microcode_patch(struct ucode_cpu_info *uci, void *data, unsigne
sig = mc_saved_hdr->sig;
pf = mc_saved_hdr->pf;
- if (find_matching_signature(data, sig, pf)) {
+ if (intel_find_matching_signature(data, sig, pf)) {
prev_found = true;
if (mc_hdr->rev <= mc_saved_hdr->rev)
@@ -149,7 +121,7 @@ static void save_microcode_patch(struct ucode_cpu_info *uci, void *data, unsigne
if (!p)
return;
- if (!find_matching_signature(p->data, uci->cpu_sig.sig, uci->cpu_sig.pf))
+ if (!intel_find_matching_signature(p->data, uci->cpu_sig.sig, uci->cpu_sig.pf))
return;
/*
@@ -163,104 +135,6 @@ static void save_microcode_patch(struct ucode_cpu_info *uci, void *data, unsigne
intel_ucode_patch = p->data;
}
-static int microcode_sanity_check(void *mc, int print_err)
-{
- unsigned long total_size, data_size, ext_table_size;
- struct microcode_header_intel *mc_header = mc;
- struct extended_sigtable *ext_header = NULL;
- u32 sum, orig_sum, ext_sigcount = 0, i;
- struct extended_signature *ext_sig;
-
- total_size = get_totalsize(mc_header);
- data_size = get_datasize(mc_header);
-
- if (data_size + MC_HEADER_SIZE > total_size) {
- if (print_err)
- pr_err("Error: bad microcode data file size.\n");
- return -EINVAL;
- }
-
- if (mc_header->ldrver != 1 || mc_header->hdrver != 1) {
- if (print_err)
- pr_err("Error: invalid/unknown microcode update format.\n");
- return -EINVAL;
- }
-
- ext_table_size = total_size - (MC_HEADER_SIZE + data_size);
- if (ext_table_size) {
- u32 ext_table_sum = 0;
- u32 *ext_tablep;
-
- if ((ext_table_size < EXT_HEADER_SIZE)
- || ((ext_table_size - EXT_HEADER_SIZE) % EXT_SIGNATURE_SIZE)) {
- if (print_err)
- pr_err("Error: truncated extended signature table.\n");
- return -EINVAL;
- }
-
- ext_header = mc + MC_HEADER_SIZE + data_size;
- if (ext_table_size != exttable_size(ext_header)) {
- if (print_err)
- pr_err("Error: extended signature table size mismatch.\n");
- return -EFAULT;
- }
-
- ext_sigcount = ext_header->count;
-
- /*
- * Check extended table checksum: the sum of all dwords that
- * comprise a valid table must be 0.
- */
- ext_tablep = (u32 *)ext_header;
-
- i = ext_table_size / sizeof(u32);
- while (i--)
- ext_table_sum += ext_tablep[i];
-
- if (ext_table_sum) {
- if (print_err)
- pr_warn("Bad extended signature table checksum, aborting.\n");
- return -EINVAL;
- }
- }
-
- /*
- * Calculate the checksum of update data and header. The checksum of
- * valid update data and header including the extended signature table
- * must be 0.
- */
- orig_sum = 0;
- i = (MC_HEADER_SIZE + data_size) / sizeof(u32);
- while (i--)
- orig_sum += ((u32 *)mc)[i];
-
- if (orig_sum) {
- if (print_err)
- pr_err("Bad microcode data checksum, aborting.\n");
- return -EINVAL;
- }
-
- if (!ext_table_size)
- return 0;
-
- /*
- * Check extended signature checksum: 0 => valid.
- */
- for (i = 0; i < ext_sigcount; i++) {
- ext_sig = (void *)ext_header + EXT_HEADER_SIZE +
- EXT_SIGNATURE_SIZE * i;
-
- sum = (mc_header->sig + mc_header->pf + mc_header->cksum) -
- (ext_sig->sig + ext_sig->pf + ext_sig->cksum);
- if (sum) {
- if (print_err)
- pr_err("Bad extended signature checksum, aborting.\n");
- return -EINVAL;
- }
- }
- return 0;
-}
-
/*
* Get microcode matching with BSP's model. Only CPUs with the same model as
* BSP can stay in the platform.
@@ -281,13 +155,13 @@ scan_microcode(void *data, size_t size, struct ucode_cpu_info *uci, bool save)
mc_size = get_totalsize(mc_header);
if (!mc_size ||
mc_size > size ||
- microcode_sanity_check(data, 0) < 0)
+ intel_microcode_sanity_check(data, false, MC_HEADER_TYPE_MICROCODE) < 0)
break;
size -= mc_size;
- if (!find_matching_signature(data, uci->cpu_sig.sig,
- uci->cpu_sig.pf)) {
+ if (!intel_find_matching_signature(data, uci->cpu_sig.sig,
+ uci->cpu_sig.pf)) {
data += mc_size;
continue;
}
@@ -621,7 +495,6 @@ void load_ucode_intel_ap(void)
else
iup = &intel_ucode_patch;
-reget:
if (!*iup) {
patch = __load_ucode_intel(&uci);
if (!patch)
@@ -632,12 +505,7 @@ reget:
uci.mc = *iup;
- if (apply_microcode_early(&uci, true)) {
- /* Mixed-silicon system? Try to refetch the proper patch: */
- *iup = NULL;
-
- goto reget;
- }
+ apply_microcode_early(&uci, true);
}
static struct microcode_intel *find_patch(struct ucode_cpu_info *uci)
@@ -652,9 +520,9 @@ static struct microcode_intel *find_patch(struct ucode_cpu_info *uci)
if (phdr->rev <= uci->cpu_sig.rev)
continue;
- if (!find_matching_signature(phdr,
- uci->cpu_sig.sig,
- uci->cpu_sig.pf))
+ if (!intel_find_matching_signature(phdr,
+ uci->cpu_sig.sig,
+ uci->cpu_sig.pf))
continue;
return iter->data;
@@ -680,7 +548,6 @@ void reload_ucode_intel(void)
static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
{
- static struct cpu_signature prev;
struct cpuinfo_x86 *c = &cpu_data(cpu_num);
unsigned int val[2];
@@ -696,13 +563,6 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig)
csig->rev = c->microcode;
- /* No extra locking on prev, races are harmless. */
- if (csig->sig != prev.sig || csig->pf != prev.pf || csig->rev != prev.rev) {
- pr_info("sig=0x%x, pf=0x%x, revision=0x%x\n",
- csig->sig, csig->pf, csig->rev);
- prev = *csig;
- }
-
return 0;
}
@@ -820,7 +680,7 @@ static enum ucode_state generic_load_microcode(int cpu, struct iov_iter *iter)
memcpy(mc, &mc_header, sizeof(mc_header));
data = mc + sizeof(mc_header);
if (!copy_from_iter_full(data, data_size, iter) ||
- microcode_sanity_check(mc, 1) < 0) {
+ intel_microcode_sanity_check(mc, true, MC_HEADER_TYPE_MICROCODE) < 0) {
break;
}
@@ -885,8 +745,7 @@ static bool is_blacklisted(unsigned int cpu)
return false;
}
-static enum ucode_state request_microcode_fw(int cpu, struct device *device,
- bool refresh_fw)
+static enum ucode_state request_microcode_fw(int cpu, struct device *device)
{
struct cpuinfo_x86 *c = &cpu_data(cpu);
const struct firmware *firmware;
@@ -908,7 +767,7 @@ static enum ucode_state request_microcode_fw(int cpu, struct device *device,
kvec.iov_base = (void *)firmware->data;
kvec.iov_len = firmware->size;
- iov_iter_kvec(&iter, WRITE, &kvec, 1, firmware->size);
+ iov_iter_kvec(&iter, ITER_SOURCE, &kvec, 1, firmware->size);
ret = generic_load_microcode(cpu, &iter);
release_firmware(firmware);
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index 831613959a92..46668e255421 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -475,6 +475,12 @@ static bool __init ms_hyperv_x2apic_available(void)
* (logically) generates MSIs directly to the system APIC irq domain.
* There is no HPET, and PCI MSI/MSI-X interrupts are remapped by the
* pci-hyperv host bridge.
+ *
+ * Note: for a Hyper-V root partition, this will always return false.
+ * The hypervisor doesn't expose these HYPERV_CPUID_VIRT_STACK_* cpuids by
+ * default, they are implemented as intercepts by the Windows Hyper-V stack.
+ * Even a nested root partition (L2 root) will not get them because the
+ * nested (L1) hypervisor filters them out.
*/
static bool __init ms_hyperv_msi_ext_dest_id(void)
{
diff --git a/arch/x86/kernel/cpu/mtrr/amd.c b/arch/x86/kernel/cpu/mtrr/amd.c
index a65a0272096d..eff6ac62c0ff 100644
--- a/arch/x86/kernel/cpu/mtrr/amd.c
+++ b/arch/x86/kernel/cpu/mtrr/amd.c
@@ -109,7 +109,7 @@ amd_validate_add_page(unsigned long base, unsigned long size, unsigned int type)
return 0;
}
-static const struct mtrr_ops amd_mtrr_ops = {
+const struct mtrr_ops amd_mtrr_ops = {
.vendor = X86_VENDOR_AMD,
.set = amd_set_mtrr,
.get = amd_get_mtrr,
@@ -117,9 +117,3 @@ static const struct mtrr_ops amd_mtrr_ops = {
.validate_add_page = amd_validate_add_page,
.have_wrcomb = positive_have_wrcomb,
};
-
-int __init amd_init_mtrr(void)
-{
- set_mtrr_ops(&amd_mtrr_ops);
- return 0;
-}
diff --git a/arch/x86/kernel/cpu/mtrr/centaur.c b/arch/x86/kernel/cpu/mtrr/centaur.c
index f27177816569..b8a74eddde83 100644
--- a/arch/x86/kernel/cpu/mtrr/centaur.c
+++ b/arch/x86/kernel/cpu/mtrr/centaur.c
@@ -111,7 +111,7 @@ centaur_validate_add_page(unsigned long base, unsigned long size, unsigned int t
return 0;
}
-static const struct mtrr_ops centaur_mtrr_ops = {
+const struct mtrr_ops centaur_mtrr_ops = {
.vendor = X86_VENDOR_CENTAUR,
.set = centaur_set_mcr,
.get = centaur_get_mcr,
@@ -119,9 +119,3 @@ static const struct mtrr_ops centaur_mtrr_ops = {
.validate_add_page = centaur_validate_add_page,
.have_wrcomb = positive_have_wrcomb,
};
-
-int __init centaur_init_mtrr(void)
-{
- set_mtrr_ops(&centaur_mtrr_ops);
- return 0;
-}
diff --git a/arch/x86/kernel/cpu/mtrr/cyrix.c b/arch/x86/kernel/cpu/mtrr/cyrix.c
index ca670919b561..173b9e01e623 100644
--- a/arch/x86/kernel/cpu/mtrr/cyrix.c
+++ b/arch/x86/kernel/cpu/mtrr/cyrix.c
@@ -234,51 +234,11 @@ static void cyrix_set_arr(unsigned int reg, unsigned long base,
post_set();
}
-typedef struct {
- unsigned long base;
- unsigned long size;
- mtrr_type type;
-} arr_state_t;
-
-static arr_state_t arr_state[8] = {
- {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL},
- {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}, {0UL, 0UL, 0UL}
-};
-
-static unsigned char ccr_state[7] = { 0, 0, 0, 0, 0, 0, 0 };
-
-static void cyrix_set_all(void)
-{
- int i;
-
- prepare_set();
-
- /* the CCRs are not contiguous */
- for (i = 0; i < 4; i++)
- setCx86(CX86_CCR0 + i, ccr_state[i]);
- for (; i < 7; i++)
- setCx86(CX86_CCR4 + i, ccr_state[i]);
-
- for (i = 0; i < 8; i++) {
- cyrix_set_arr(i, arr_state[i].base,
- arr_state[i].size, arr_state[i].type);
- }
-
- post_set();
-}
-
-static const struct mtrr_ops cyrix_mtrr_ops = {
+const struct mtrr_ops cyrix_mtrr_ops = {
.vendor = X86_VENDOR_CYRIX,
- .set_all = cyrix_set_all,
.set = cyrix_set_arr,
.get = cyrix_get_arr,
.get_free_region = cyrix_get_free_region,
.validate_add_page = generic_validate_add_page,
.have_wrcomb = positive_have_wrcomb,
};
-
-int __init cyrix_init_mtrr(void)
-{
- set_mtrr_ops(&cyrix_mtrr_ops);
- return 0;
-}
diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
index 558108296f3c..ee09d359e08f 100644
--- a/arch/x86/kernel/cpu/mtrr/generic.c
+++ b/arch/x86/kernel/cpu/mtrr/generic.c
@@ -10,6 +10,7 @@
#include <linux/mm.h>
#include <asm/processor-flags.h>
+#include <asm/cacheinfo.h>
#include <asm/cpufeature.h>
#include <asm/tlbflush.h>
#include <asm/mtrr.h>
@@ -396,9 +397,6 @@ print_fixed(unsigned base, unsigned step, const mtrr_type *types)
}
}
-static void prepare_set(void);
-static void post_set(void);
-
static void __init print_mtrr_state(void)
{
unsigned int i;
@@ -444,20 +442,6 @@ static void __init print_mtrr_state(void)
pr_debug("TOM2: %016llx aka %lldM\n", mtrr_tom2, mtrr_tom2>>20);
}
-/* PAT setup for BP. We need to go through sync steps here */
-void __init mtrr_bp_pat_init(void)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- prepare_set();
-
- pat_init();
-
- post_set();
- local_irq_restore(flags);
-}
-
/* Grab all of the MTRR state for this CPU into *state */
bool __init get_mtrr_state(void)
{
@@ -684,7 +668,10 @@ static u32 deftype_lo, deftype_hi;
/**
* set_mtrr_state - Set the MTRR state for this CPU.
*
- * NOTE: The CPU must already be in a safe state for MTRR changes.
+ * NOTE: The CPU must already be in a safe state for MTRR changes, including
+ * measures that only a single CPU can be active in set_mtrr_state() in
+ * order to not be subject to races for usage of deftype_lo. This is
+ * accomplished by taking cache_disable_lock.
* RETURNS: 0 if no changes made, else a mask indicating what was changed.
*/
static unsigned long set_mtrr_state(void)
@@ -715,106 +702,34 @@ static unsigned long set_mtrr_state(void)
return change_mask;
}
-
-static unsigned long cr4;
-static DEFINE_RAW_SPINLOCK(set_atomicity_lock);
-
-/*
- * Since we are disabling the cache don't allow any interrupts,
- * they would run extremely slow and would only increase the pain.
- *
- * The caller must ensure that local interrupts are disabled and
- * are reenabled after post_set() has been called.
- */
-static void prepare_set(void) __acquires(set_atomicity_lock)
+void mtrr_disable(void)
{
- unsigned long cr0;
-
- /*
- * Note that this is not ideal
- * since the cache is only flushed/disabled for this CPU while the
- * MTRRs are changed, but changing this requires more invasive
- * changes to the way the kernel boots
- */
-
- raw_spin_lock(&set_atomicity_lock);
-
- /* Enter the no-fill (CD=1, NW=0) cache mode and flush caches. */
- cr0 = read_cr0() | X86_CR0_CD;
- write_cr0(cr0);
-
- /*
- * Cache flushing is the most time-consuming step when programming
- * the MTRRs. Fortunately, as per the Intel Software Development
- * Manual, we can skip it if the processor supports cache self-
- * snooping.
- */
- if (!static_cpu_has(X86_FEATURE_SELFSNOOP))
- wbinvd();
-
- /* Save value of CR4 and clear Page Global Enable (bit 7) */
- if (boot_cpu_has(X86_FEATURE_PGE)) {
- cr4 = __read_cr4();
- __write_cr4(cr4 & ~X86_CR4_PGE);
- }
-
- /* Flush all TLBs via a mov %cr3, %reg; mov %reg, %cr3 */
- count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
- flush_tlb_local();
-
/* Save MTRR state */
rdmsr(MSR_MTRRdefType, deftype_lo, deftype_hi);
/* Disable MTRRs, and set the default type to uncached */
mtrr_wrmsr(MSR_MTRRdefType, deftype_lo & ~0xcff, deftype_hi);
-
- /* Again, only flush caches if we have to. */
- if (!static_cpu_has(X86_FEATURE_SELFSNOOP))
- wbinvd();
}
-static void post_set(void) __releases(set_atomicity_lock)
+void mtrr_enable(void)
{
- /* Flush TLBs (no need to flush caches - they are disabled) */
- count_vm_tlb_event(NR_TLB_LOCAL_FLUSH_ALL);
- flush_tlb_local();
-
/* Intel (P6) standard MTRRs */
mtrr_wrmsr(MSR_MTRRdefType, deftype_lo, deftype_hi);
-
- /* Enable caches */
- write_cr0(read_cr0() & ~X86_CR0_CD);
-
- /* Restore value of CR4 */
- if (boot_cpu_has(X86_FEATURE_PGE))
- __write_cr4(cr4);
- raw_spin_unlock(&set_atomicity_lock);
}
-static void generic_set_all(void)
+void mtrr_generic_set_state(void)
{
unsigned long mask, count;
- unsigned long flags;
-
- local_irq_save(flags);
- prepare_set();
/* Actually set the state */
mask = set_mtrr_state();
- /* also set PAT */
- pat_init();
-
- post_set();
- local_irq_restore(flags);
-
/* Use the atomic bitops to update the global mask */
for (count = 0; count < sizeof(mask) * 8; ++count) {
if (mask & 0x01)
set_bit(count, &smp_changes_mask);
mask >>= 1;
}
-
}
/**
@@ -836,7 +751,7 @@ static void generic_set_mtrr(unsigned int reg, unsigned long base,
vr = &mtrr_state.var_ranges[reg];
local_irq_save(flags);
- prepare_set();
+ cache_disable();
if (size == 0) {
/*
@@ -855,7 +770,7 @@ static void generic_set_mtrr(unsigned int reg, unsigned long base,
mtrr_wrmsr(MTRRphysMask_MSR(reg), vr->mask_lo, vr->mask_hi);
}
- post_set();
+ cache_enable();
local_irq_restore(flags);
}
@@ -914,8 +829,6 @@ int positive_have_wrcomb(void)
* Generic structure...
*/
const struct mtrr_ops generic_mtrr_ops = {
- .use_intel_if = 1,
- .set_all = generic_set_all,
.get = generic_get_mtrr,
.get_free_region = generic_get_free_region,
.set = generic_set_mtrr,
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.c b/arch/x86/kernel/cpu/mtrr/mtrr.c
index 2746cac9d8a9..783f3210d582 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.c
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.c
@@ -46,6 +46,7 @@
#include <linux/syscore_ops.h>
#include <linux/rcupdate.h>
+#include <asm/cacheinfo.h>
#include <asm/cpufeature.h>
#include <asm/e820/api.h>
#include <asm/mtrr.h>
@@ -58,32 +59,18 @@
#define MTRR_TO_PHYS_WC_OFFSET 1000
u32 num_var_ranges;
-static bool __mtrr_enabled;
-
static bool mtrr_enabled(void)
{
- return __mtrr_enabled;
+ return !!mtrr_if;
}
unsigned int mtrr_usage_table[MTRR_MAX_VAR_RANGES];
static DEFINE_MUTEX(mtrr_mutex);
u64 size_or_mask, size_and_mask;
-static bool mtrr_aps_delayed_init;
-
-static const struct mtrr_ops *mtrr_ops[X86_VENDOR_NUM] __ro_after_init;
const struct mtrr_ops *mtrr_if;
-static void set_mtrr(unsigned int reg, unsigned long base,
- unsigned long size, mtrr_type type);
-
-void __init set_mtrr_ops(const struct mtrr_ops *ops)
-{
- if (ops->vendor && ops->vendor < X86_VENDOR_NUM)
- mtrr_ops[ops->vendor] = ops;
-}
-
/* Returns non-zero if we have the write-combining memory type */
static int have_wrcomb(void)
{
@@ -119,11 +106,11 @@ static int have_wrcomb(void)
}
/* This function returns the number of variable MTRRs */
-static void __init set_num_var_ranges(void)
+static void __init set_num_var_ranges(bool use_generic)
{
unsigned long config = 0, dummy;
- if (use_intel())
+ if (use_generic)
rdmsr(MSR_MTRRcap, config, dummy);
else if (is_cpu(AMD) || is_cpu(HYGON))
config = 2;
@@ -160,25 +147,8 @@ static int mtrr_rendezvous_handler(void *info)
{
struct set_mtrr_data *data = info;
- /*
- * We use this same function to initialize the mtrrs during boot,
- * resume, runtime cpu online and on an explicit request to set a
- * specific MTRR.
- *
- * During boot or suspend, the state of the boot cpu's mtrrs has been
- * saved, and we want to replicate that across all the cpus that come
- * online (either at the end of boot or resume or during a runtime cpu
- * online). If we're doing that, @reg is set to something special and on
- * all the cpu's we do mtrr_if->set_all() (On the logical cpu that
- * started the boot/resume sequence, this might be a duplicate
- * set_all()).
- */
- if (data->smp_reg != ~0U) {
- mtrr_if->set(data->smp_reg, data->smp_base,
- data->smp_size, data->smp_type);
- } else if (mtrr_aps_delayed_init || !cpu_online(smp_processor_id())) {
- mtrr_if->set_all();
- }
+ mtrr_if->set(data->smp_reg, data->smp_base,
+ data->smp_size, data->smp_type);
return 0;
}
@@ -248,19 +218,6 @@ static void set_mtrr_cpuslocked(unsigned int reg, unsigned long base,
stop_machine_cpuslocked(mtrr_rendezvous_handler, &data, cpu_online_mask);
}
-static void set_mtrr_from_inactive_cpu(unsigned int reg, unsigned long base,
- unsigned long size, mtrr_type type)
-{
- struct set_mtrr_data data = { .smp_reg = reg,
- .smp_base = base,
- .smp_size = size,
- .smp_type = type
- };
-
- stop_machine_from_inactive_cpu(mtrr_rendezvous_handler, &data,
- cpu_callout_mask);
-}
-
/**
* mtrr_add_page - Add a memory type region
* @base: Physical base address of region in pages (in units of 4 kB!)
@@ -617,20 +574,6 @@ int arch_phys_wc_index(int handle)
}
EXPORT_SYMBOL_GPL(arch_phys_wc_index);
-/*
- * HACK ALERT!
- * These should be called implicitly, but we can't yet until all the initcall
- * stuff is done...
- */
-static void __init init_ifs(void)
-{
-#ifndef CONFIG_X86_64
- amd_init_mtrr();
- cyrix_init_mtrr();
- centaur_init_mtrr();
-#endif
-}
-
/* The suspend/resume methods are only for CPU without MTRR. CPU using generic
* MTRR driver doesn't require this
*/
@@ -686,10 +629,9 @@ int __initdata changed_by_mtrr_cleanup;
*/
void __init mtrr_bp_init(void)
{
+ const char *why = "(not available)";
u32 phys_addr;
- init_ifs();
-
phys_addr = 32;
if (boot_cpu_has(X86_FEATURE_MTRR)) {
@@ -730,21 +672,21 @@ void __init mtrr_bp_init(void)
case X86_VENDOR_AMD:
if (cpu_feature_enabled(X86_FEATURE_K6_MTRR)) {
/* Pre-Athlon (K6) AMD CPU MTRRs */
- mtrr_if = mtrr_ops[X86_VENDOR_AMD];
+ mtrr_if = &amd_mtrr_ops;
size_or_mask = SIZE_OR_MASK_BITS(32);
size_and_mask = 0;
}
break;
case X86_VENDOR_CENTAUR:
if (cpu_feature_enabled(X86_FEATURE_CENTAUR_MCR)) {
- mtrr_if = mtrr_ops[X86_VENDOR_CENTAUR];
+ mtrr_if = &centaur_mtrr_ops;
size_or_mask = SIZE_OR_MASK_BITS(32);
size_and_mask = 0;
}
break;
case X86_VENDOR_CYRIX:
if (cpu_feature_enabled(X86_FEATURE_CYRIX_ARR)) {
- mtrr_if = mtrr_ops[X86_VENDOR_CYRIX];
+ mtrr_if = &cyrix_mtrr_ops;
size_or_mask = SIZE_OR_MASK_BITS(32);
size_and_mask = 0;
}
@@ -754,58 +696,23 @@ void __init mtrr_bp_init(void)
}
}
- if (mtrr_if) {
- __mtrr_enabled = true;
- set_num_var_ranges();
+ if (mtrr_enabled()) {
+ set_num_var_ranges(mtrr_if == &generic_mtrr_ops);
init_table();
- if (use_intel()) {
+ if (mtrr_if == &generic_mtrr_ops) {
/* BIOS may override */
- __mtrr_enabled = get_mtrr_state();
-
- if (mtrr_enabled())
- mtrr_bp_pat_init();
-
- if (mtrr_cleanup(phys_addr)) {
- changed_by_mtrr_cleanup = 1;
- mtrr_if->set_all();
+ if (get_mtrr_state()) {
+ memory_caching_control |= CACHE_MTRR;
+ changed_by_mtrr_cleanup = mtrr_cleanup(phys_addr);
+ } else {
+ mtrr_if = NULL;
+ why = "by BIOS";
}
}
}
- if (!mtrr_enabled()) {
- pr_info("Disabled\n");
-
- /*
- * PAT initialization relies on MTRR's rendezvous handler.
- * Skip PAT init until the handler can initialize both
- * features independently.
- */
- pat_disable("MTRRs disabled, skipping PAT initialization too.");
- }
-}
-
-void mtrr_ap_init(void)
-{
if (!mtrr_enabled())
- return;
-
- if (!use_intel() || mtrr_aps_delayed_init)
- return;
-
- /*
- * Ideally we should hold mtrr_mutex here to avoid mtrr entries
- * changed, but this routine will be called in cpu boot time,
- * holding the lock breaks it.
- *
- * This routine is called in two cases:
- *
- * 1. very early time of software resume, when there absolutely
- * isn't mtrr entry changes;
- *
- * 2. cpu hotadd time. We let mtrr_add/del_page hold cpuhotplug
- * lock to prevent mtrr entry changes
- */
- set_mtrr_from_inactive_cpu(~0U, 0, 0, 0);
+ pr_info("MTRRs disabled %s\n", why);
}
/**
@@ -823,50 +730,12 @@ void mtrr_save_state(void)
smp_call_function_single(first_cpu, mtrr_save_fixed_ranges, NULL, 1);
}
-void set_mtrr_aps_delayed_init(void)
-{
- if (!mtrr_enabled())
- return;
- if (!use_intel())
- return;
-
- mtrr_aps_delayed_init = true;
-}
-
-/*
- * Delayed MTRR initialization for all AP's
- */
-void mtrr_aps_init(void)
-{
- if (!use_intel() || !mtrr_enabled())
- return;
-
- /*
- * Check if someone has requested the delay of AP MTRR initialization,
- * by doing set_mtrr_aps_delayed_init(), prior to this point. If not,
- * then we are done.
- */
- if (!mtrr_aps_delayed_init)
- return;
-
- set_mtrr(~0U, 0, 0, 0);
- mtrr_aps_delayed_init = false;
-}
-
-void mtrr_bp_restore(void)
-{
- if (!use_intel() || !mtrr_enabled())
- return;
-
- mtrr_if->set_all();
-}
-
static int __init mtrr_init_finialize(void)
{
if (!mtrr_enabled())
return 0;
- if (use_intel()) {
+ if (memory_caching_control & CACHE_MTRR) {
if (!changed_by_mtrr_cleanup)
mtrr_state_warn();
return 0;
diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.h b/arch/x86/kernel/cpu/mtrr/mtrr.h
index 2ac99e561181..02eb5871492d 100644
--- a/arch/x86/kernel/cpu/mtrr/mtrr.h
+++ b/arch/x86/kernel/cpu/mtrr/mtrr.h
@@ -14,11 +14,8 @@ extern unsigned int mtrr_usage_table[MTRR_MAX_VAR_RANGES];
struct mtrr_ops {
u32 vendor;
- u32 use_intel_if;
void (*set)(unsigned int reg, unsigned long base,
unsigned long size, mtrr_type type);
- void (*set_all)(void);
-
void (*get)(unsigned int reg, unsigned long *base,
unsigned long *size, mtrr_type *type);
int (*get_free_region)(unsigned long base, unsigned long size,
@@ -53,15 +50,11 @@ void set_mtrr_prepare_save(struct set_mtrr_context *ctxt);
void fill_mtrr_var_range(unsigned int index,
u32 base_lo, u32 base_hi, u32 mask_lo, u32 mask_hi);
bool get_mtrr_state(void);
-void mtrr_bp_pat_init(void);
-
-extern void __init set_mtrr_ops(const struct mtrr_ops *ops);
extern u64 size_or_mask, size_and_mask;
extern const struct mtrr_ops *mtrr_if;
#define is_cpu(vnd) (mtrr_if && mtrr_if->vendor == X86_VENDOR_##vnd)
-#define use_intel() (mtrr_if && mtrr_if->use_intel_if == 1)
extern unsigned int num_var_ranges;
extern u64 mtrr_tom2;
@@ -71,10 +64,10 @@ void mtrr_state_warn(void);
const char *mtrr_attrib_to_str(int x);
void mtrr_wrmsr(unsigned, unsigned, unsigned);
-/* CPU specific mtrr init functions */
-int amd_init_mtrr(void);
-int cyrix_init_mtrr(void);
-int centaur_init_mtrr(void);
+/* CPU specific mtrr_ops vectors. */
+extern const struct mtrr_ops amd_mtrr_ops;
+extern const struct mtrr_ops cyrix_mtrr_ops;
+extern const struct mtrr_ops centaur_mtrr_ops;
extern int changed_by_mtrr_cleanup;
extern int mtrr_cleanup(unsigned address_bits);
diff --git a/arch/x86/kernel/cpu/resctrl/core.c b/arch/x86/kernel/cpu/resctrl/core.c
index 3266ea36667c..c98e52ff5f20 100644
--- a/arch/x86/kernel/cpu/resctrl/core.c
+++ b/arch/x86/kernel/cpu/resctrl/core.c
@@ -575,7 +575,7 @@ static void clear_closid_rmid(int cpu)
state->default_rmid = 0;
state->cur_closid = 0;
state->cur_rmid = 0;
- wrmsr(IA32_PQR_ASSOC, 0, 0);
+ wrmsr(MSR_IA32_PQR_ASSOC, 0, 0);
}
static int resctrl_online_cpu(unsigned int cpu)
@@ -828,7 +828,6 @@ static __init void rdt_init_res_defs_intel(void)
if (r->rid == RDT_RESOURCE_L3 ||
r->rid == RDT_RESOURCE_L2) {
r->cache.arch_has_sparse_bitmaps = false;
- r->cache.arch_has_empty_bitmaps = false;
r->cache.arch_has_per_cpu_cfg = false;
r->cache.min_cbm_bits = 1;
} else if (r->rid == RDT_RESOURCE_MBA) {
@@ -849,7 +848,6 @@ static __init void rdt_init_res_defs_amd(void)
if (r->rid == RDT_RESOURCE_L3 ||
r->rid == RDT_RESOURCE_L2) {
r->cache.arch_has_sparse_bitmaps = true;
- r->cache.arch_has_empty_bitmaps = true;
r->cache.arch_has_per_cpu_cfg = true;
r->cache.min_cbm_bits = 0;
} else if (r->rid == RDT_RESOURCE_MBA) {
diff --git a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
index 1dafbdc5ac31..1df0e3262bca 100644
--- a/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
+++ b/arch/x86/kernel/cpu/resctrl/ctrlmondata.c
@@ -105,8 +105,7 @@ static bool cbm_validate(char *buf, u32 *data, struct rdt_resource *r)
return false;
}
- if ((!r->cache.arch_has_empty_bitmaps && val == 0) ||
- val > r->default_ctrl) {
+ if ((r->cache.min_cbm_bits > 0 && val == 0) || val > r->default_ctrl) {
rdt_last_cmd_puts("Mask out of range\n");
return false;
}
diff --git a/arch/x86/kernel/cpu/resctrl/internal.h b/arch/x86/kernel/cpu/resctrl/internal.h
index 5f7128686cfd..5ebd28e6aa0c 100644
--- a/arch/x86/kernel/cpu/resctrl/internal.h
+++ b/arch/x86/kernel/cpu/resctrl/internal.h
@@ -8,16 +8,6 @@
#include <linux/fs_context.h>
#include <linux/jump_label.h>
-#define MSR_IA32_L3_QOS_CFG 0xc81
-#define MSR_IA32_L2_QOS_CFG 0xc82
-#define MSR_IA32_L3_CBM_BASE 0xc90
-#define MSR_IA32_L2_CBM_BASE 0xd10
-#define MSR_IA32_MBA_THRTL_BASE 0xd50
-#define MSR_IA32_MBA_BW_BASE 0xc0000200
-
-#define MSR_IA32_QM_CTR 0x0c8e
-#define MSR_IA32_QM_EVTSEL 0x0c8d
-
#define L3_QOS_CDP_ENABLE 0x01ULL
#define L2_QOS_CDP_ENABLE 0x01ULL
diff --git a/arch/x86/kernel/cpu/resctrl/pseudo_lock.c b/arch/x86/kernel/cpu/resctrl/pseudo_lock.c
index d961ae3ed96e..ba8d0763b36b 100644
--- a/arch/x86/kernel/cpu/resctrl/pseudo_lock.c
+++ b/arch/x86/kernel/cpu/resctrl/pseudo_lock.c
@@ -477,7 +477,7 @@ static int pseudo_lock_fn(void *_rdtgrp)
* pseudo-locked followed by reading of kernel memory to load it
* into the cache.
*/
- __wrmsr(IA32_PQR_ASSOC, rmid_p, rdtgrp->closid);
+ __wrmsr(MSR_IA32_PQR_ASSOC, rmid_p, rdtgrp->closid);
/*
* Cache was flushed earlier. Now access kernel memory to read it
* into cache region associated with just activated plr->closid.
@@ -513,7 +513,7 @@ static int pseudo_lock_fn(void *_rdtgrp)
* Critical section end: restore closid with capacity bitmask that
* does not overlap with pseudo-locked region.
*/
- __wrmsr(IA32_PQR_ASSOC, rmid_p, closid_p);
+ __wrmsr(MSR_IA32_PQR_ASSOC, rmid_p, closid_p);
/* Re-enable the hardware prefetcher(s) */
wrmsrl(MSR_MISC_FEATURE_CONTROL, saved_msr);
diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c
index fc01f81f6e2a..f53944fb8f7f 100644
--- a/arch/x86/kernel/cpu/scattered.c
+++ b/arch/x86/kernel/cpu/scattered.c
@@ -40,6 +40,7 @@ static const struct cpuid_bit cpuid_bits[] = {
{ X86_FEATURE_PER_THREAD_MBA, CPUID_ECX, 0, 0x00000010, 3 },
{ X86_FEATURE_SGX1, CPUID_EAX, 0, 0x00000012, 0 },
{ X86_FEATURE_SGX2, CPUID_EAX, 1, 0x00000012, 0 },
+ { X86_FEATURE_SGX_EDECCSSA, CPUID_EAX, 11, 0x00000012, 0 },
{ X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 },
{ X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 },
{ X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 },
diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c
index 1ec20807de1e..68f8b18d2278 100644
--- a/arch/x86/kernel/cpu/sgx/encl.c
+++ b/arch/x86/kernel/cpu/sgx/encl.c
@@ -160,8 +160,8 @@ static int __sgx_encl_eldu(struct sgx_encl_page *encl_page,
return ret;
pginfo.addr = encl_page->desc & PAGE_MASK;
- pginfo.contents = (unsigned long)kmap_atomic(b.contents);
- pcmd_page = kmap_atomic(b.pcmd);
+ pginfo.contents = (unsigned long)kmap_local_page(b.contents);
+ pcmd_page = kmap_local_page(b.pcmd);
pginfo.metadata = (unsigned long)pcmd_page + b.pcmd_offset;
if (secs_page)
@@ -187,8 +187,8 @@ static int __sgx_encl_eldu(struct sgx_encl_page *encl_page,
*/
pcmd_page_empty = !memchr_inv(pcmd_page, 0, PAGE_SIZE);
- kunmap_atomic(pcmd_page);
- kunmap_atomic((void *)(unsigned long)pginfo.contents);
+ kunmap_local(pcmd_page);
+ kunmap_local((void *)(unsigned long)pginfo.contents);
get_page(b.pcmd);
sgx_encl_put_backing(&b);
@@ -197,10 +197,10 @@ static int __sgx_encl_eldu(struct sgx_encl_page *encl_page,
if (pcmd_page_empty && !reclaimer_writing_to_pcmd(encl, pcmd_first_page)) {
sgx_encl_truncate_backing_page(encl, PFN_DOWN(page_pcmd_off));
- pcmd_page = kmap_atomic(b.pcmd);
+ pcmd_page = kmap_local_page(b.pcmd);
if (memchr_inv(pcmd_page, 0, PAGE_SIZE))
pr_warn("PCMD page not empty after truncate.\n");
- kunmap_atomic(pcmd_page);
+ kunmap_local(pcmd_page);
}
put_page(b.pcmd);
@@ -680,11 +680,15 @@ const struct vm_operations_struct sgx_vm_ops = {
void sgx_encl_release(struct kref *ref)
{
struct sgx_encl *encl = container_of(ref, struct sgx_encl, refcount);
+ unsigned long max_page_index = PFN_DOWN(encl->base + encl->size - 1);
struct sgx_va_page *va_page;
struct sgx_encl_page *entry;
- unsigned long index;
+ unsigned long count = 0;
+
+ XA_STATE(xas, &encl->page_array, PFN_DOWN(encl->base));
- xa_for_each(&encl->page_array, index, entry) {
+ xas_lock(&xas);
+ xas_for_each(&xas, entry, max_page_index) {
if (entry->epc_page) {
/*
* The page and its radix tree entry cannot be freed
@@ -699,9 +703,20 @@ void sgx_encl_release(struct kref *ref)
}
kfree(entry);
- /* Invoke scheduler to prevent soft lockups. */
- cond_resched();
+ /*
+ * Invoke scheduler on every XA_CHECK_SCHED iteration
+ * to prevent soft lockups.
+ */
+ if (!(++count % XA_CHECK_SCHED)) {
+ xas_pause(&xas);
+ xas_unlock(&xas);
+
+ cond_resched();
+
+ xas_lock(&xas);
+ }
}
+ xas_unlock(&xas);
xa_destroy(&encl->page_array);
diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c
index da8b8ea6b063..21ca0a831b70 100644
--- a/arch/x86/kernel/cpu/sgx/ioctl.c
+++ b/arch/x86/kernel/cpu/sgx/ioctl.c
@@ -111,7 +111,7 @@ static int sgx_encl_create(struct sgx_encl *encl, struct sgx_secs *secs)
encl->base = secs->base;
encl->size = secs->size;
encl->attributes = secs->attributes;
- encl->attributes_mask = SGX_ATTR_DEBUG | SGX_ATTR_MODE64BIT | SGX_ATTR_KSS;
+ encl->attributes_mask = SGX_ATTR_UNPRIV_MASK;
/* Set only after completion, as encl->lock has not been taken. */
set_bit(SGX_ENCL_CREATED, &encl->flags);
@@ -221,11 +221,11 @@ static int __sgx_encl_add_page(struct sgx_encl *encl,
pginfo.secs = (unsigned long)sgx_get_epc_virt_addr(encl->secs.epc_page);
pginfo.addr = encl_page->desc & PAGE_MASK;
pginfo.metadata = (unsigned long)secinfo;
- pginfo.contents = (unsigned long)kmap_atomic(src_page);
+ pginfo.contents = (unsigned long)kmap_local_page(src_page);
ret = __eadd(&pginfo, sgx_get_epc_virt_addr(epc_page));
- kunmap_atomic((void *)pginfo.contents);
+ kunmap_local((void *)pginfo.contents);
put_page(src_page);
return ret ? -EIO : 0;
diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c
index 0aad028f04d4..e5a37b6e9aa5 100644
--- a/arch/x86/kernel/cpu/sgx/main.c
+++ b/arch/x86/kernel/cpu/sgx/main.c
@@ -165,17 +165,17 @@ static int __sgx_encl_ewb(struct sgx_epc_page *epc_page, void *va_slot,
pginfo.addr = 0;
pginfo.secs = 0;
- pginfo.contents = (unsigned long)kmap_atomic(backing->contents);
- pginfo.metadata = (unsigned long)kmap_atomic(backing->pcmd) +
+ pginfo.contents = (unsigned long)kmap_local_page(backing->contents);
+ pginfo.metadata = (unsigned long)kmap_local_page(backing->pcmd) +
backing->pcmd_offset;
ret = __ewb(&pginfo, sgx_get_epc_virt_addr(epc_page), va_slot);
set_page_dirty(backing->pcmd);
set_page_dirty(backing->contents);
- kunmap_atomic((void *)(unsigned long)(pginfo.metadata -
+ kunmap_local((void *)(unsigned long)(pginfo.metadata -
backing->pcmd_offset));
- kunmap_atomic((void *)(unsigned long)pginfo.contents);
+ kunmap_local((void *)(unsigned long)pginfo.contents);
return ret;
}
diff --git a/arch/x86/kernel/crash_dump_64.c b/arch/x86/kernel/crash_dump_64.c
index e75bc2f217ff..32d710f7eb84 100644
--- a/arch/x86/kernel/crash_dump_64.c
+++ b/arch/x86/kernel/crash_dump_64.c
@@ -57,7 +57,7 @@ ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos)
struct kvec kvec = { .iov_base = buf, .iov_len = count };
struct iov_iter iter;
- iov_iter_kvec(&iter, READ, &kvec, 1, count);
+ iov_iter_kvec(&iter, ITER_DEST, &kvec, 1, count);
return read_from_oldmem(&iter, count, ppos,
cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT));
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index 5cd51f25f446..28da5dd83fc0 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -31,11 +31,6 @@ char __initdata cmd_line[COMMAND_LINE_SIZE];
int __initdata of_ioapic;
-void __init early_init_dt_add_memory_arch(u64 base, u64 size)
-{
- BUG();
-}
-
void __init add_dtb(u64 data)
{
initial_dtb = data + offsetof(struct setup_data, data);
@@ -167,7 +162,14 @@ static void __init dtb_lapic_setup(void)
return;
}
smp_found_config = 1;
- pic_mode = 1;
+ if (of_property_read_bool(dn, "intel,virtual-wire-mode")) {
+ pr_info("Virtual Wire compatibility mode.\n");
+ pic_mode = 0;
+ } else {
+ pr_info("IMCR and PIC compatibility mode.\n");
+ pic_mode = 1;
+ }
+
register_lapic_address(lapic_addr);
}
@@ -248,7 +250,7 @@ static void __init dtb_add_ioapic(struct device_node *dn)
ret = of_address_to_resource(dn, 0, &r);
if (ret) {
- printk(KERN_ERR "Can't obtain address from device node %pOF.\n", dn);
+ pr_err("Can't obtain address from device node %pOF.\n", dn);
return;
}
mp_register_ioapic(++ioapic_id, r.start, gsi_top, &cfg);
@@ -265,7 +267,7 @@ static void __init dtb_ioapic_setup(void)
of_ioapic = 1;
return;
}
- printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
+ pr_err("Error: No information about IO-APIC in OF.\n");
}
#else
static void __init dtb_ioapic_setup(void) {}
diff --git a/arch/x86/kernel/espfix_64.c b/arch/x86/kernel/espfix_64.c
index 9417d5aa7305..16f9814c9be0 100644
--- a/arch/x86/kernel/espfix_64.c
+++ b/arch/x86/kernel/espfix_64.c
@@ -94,17 +94,7 @@ static inline unsigned long espfix_base_addr(unsigned int cpu)
static void init_espfix_random(void)
{
- unsigned long rand;
-
- /*
- * This is run before the entropy pools are initialized,
- * but this is hopefully better than nothing.
- */
- if (!arch_get_random_longs(&rand, 1)) {
- /* The constant is an arbitrary large prime */
- rand = rdtsc();
- rand *= 0xc345c6b72fd16123UL;
- }
+ unsigned long rand = get_random_long();
slot_random = rand % ESPFIX_STACKS_PER_PAGE;
page_random = (rand / ESPFIX_STACKS_PER_PAGE)
diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
index d00db56a8868..9baa89a8877d 100644
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -391,8 +391,6 @@ int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, const void *buf,
{
struct fpstate *kstate = gfpu->fpstate;
const union fpregs_state *ustate = buf;
- struct pkru_state *xpkru;
- int ret;
if (!cpu_feature_enabled(X86_FEATURE_XSAVE)) {
if (ustate->xsave.header.xfeatures & ~XFEATURE_MASK_FPSSE)
@@ -406,16 +404,15 @@ int fpu_copy_uabi_to_guest_fpstate(struct fpu_guest *gfpu, const void *buf,
if (ustate->xsave.header.xfeatures & ~xcr0)
return -EINVAL;
- ret = copy_uabi_from_kernel_to_xstate(kstate, ustate);
- if (ret)
- return ret;
+ /*
+ * Nullify @vpkru to preserve its current value if PKRU's bit isn't set
+ * in the header. KVM's odd ABI is to leave PKRU untouched in this
+ * case (all other components are eventually re-initialized).
+ */
+ if (!(ustate->xsave.header.xfeatures & XFEATURE_MASK_PKRU))
+ vpkru = NULL;
- /* Retrieve PKRU if not in init state */
- if (kstate->regs.xsave.header.xfeatures & XFEATURE_MASK_PKRU) {
- xpkru = get_xsave_addr(&kstate->regs.xsave, XFEATURE_PKRU);
- *vpkru = xpkru->pkru;
- }
- return 0;
+ return copy_uabi_from_kernel_to_xstate(kstate, ustate, vpkru);
}
EXPORT_SYMBOL_GPL(fpu_copy_uabi_to_guest_fpstate);
#endif /* CONFIG_KVM */
diff --git a/arch/x86/kernel/fpu/init.c b/arch/x86/kernel/fpu/init.c
index 8946f89761cc..851eb13edc01 100644
--- a/arch/x86/kernel/fpu/init.c
+++ b/arch/x86/kernel/fpu/init.c
@@ -133,9 +133,6 @@ static void __init fpu__init_system_generic(void)
fpu__init_system_mxcsr();
}
-/* Get alignment of the TYPE. */
-#define TYPE_ALIGN(TYPE) offsetof(struct { char x; TYPE test; }, test)
-
/*
* Enforce that 'MEMBER' is the last field of 'TYPE'.
*
@@ -143,8 +140,8 @@ static void __init fpu__init_system_generic(void)
* because that's how C aligns structs.
*/
#define CHECK_MEMBER_AT_END_OF(TYPE, MEMBER) \
- BUILD_BUG_ON(sizeof(TYPE) != ALIGN(offsetofend(TYPE, MEMBER), \
- TYPE_ALIGN(TYPE)))
+ BUILD_BUG_ON(sizeof(TYPE) != \
+ ALIGN(offsetofend(TYPE, MEMBER), _Alignof(TYPE)))
/*
* We append the 'struct fpu' to the task_struct:
diff --git a/arch/x86/kernel/fpu/regset.c b/arch/x86/kernel/fpu/regset.c
index 75ffaef8c299..6d056b68f4ed 100644
--- a/arch/x86/kernel/fpu/regset.c
+++ b/arch/x86/kernel/fpu/regset.c
@@ -167,7 +167,7 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset,
}
fpu_force_restore(fpu);
- ret = copy_uabi_from_kernel_to_xstate(fpu->fpstate, kbuf ?: tmpbuf);
+ ret = copy_uabi_from_kernel_to_xstate(fpu->fpstate, kbuf ?: tmpbuf, &target->thread.pkru);
out:
vfree(tmpbuf);
diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c
index 91d4b6de58ab..558076dbde5b 100644
--- a/arch/x86/kernel/fpu/signal.c
+++ b/arch/x86/kernel/fpu/signal.c
@@ -396,7 +396,7 @@ static bool __fpu_restore_sig(void __user *buf, void __user *buf_fx,
fpregs = &fpu->fpstate->regs;
if (use_xsave() && !fx_only) {
- if (copy_sigframe_from_user_to_xstate(fpu->fpstate, buf_fx))
+ if (copy_sigframe_from_user_to_xstate(tsk, buf_fx))
return false;
} else {
if (__copy_from_user(&fpregs->fxsave, buf_fx,
diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c
index 59e543b95a3c..714166cc25f2 100644
--- a/arch/x86/kernel/fpu/xstate.c
+++ b/arch/x86/kernel/fpu/xstate.c
@@ -440,8 +440,8 @@ static void __init __xstate_dump_leaves(void)
}
}
-#define XSTATE_WARN_ON(x) do { \
- if (WARN_ONCE(x, "XSAVE consistency problem, dumping leaves")) { \
+#define XSTATE_WARN_ON(x, fmt, ...) do { \
+ if (WARN_ONCE(x, "XSAVE consistency problem: " fmt, ##__VA_ARGS__)) { \
__xstate_dump_leaves(); \
} \
} while (0)
@@ -554,8 +554,7 @@ static bool __init check_xstate_against_struct(int nr)
(nr >= XFEATURE_MAX) ||
(nr == XFEATURE_PT_UNIMPLEMENTED_SO_FAR) ||
((nr >= XFEATURE_RSRVD_COMP_11) && (nr <= XFEATURE_RSRVD_COMP_16))) {
- WARN_ONCE(1, "no structure for xstate: %d\n", nr);
- XSTATE_WARN_ON(1);
+ XSTATE_WARN_ON(1, "No structure for xstate: %d\n", nr);
return false;
}
return true;
@@ -598,12 +597,13 @@ static bool __init paranoid_xstate_size_valid(unsigned int kernel_size)
* XSAVES.
*/
if (!xsaves && xfeature_is_supervisor(i)) {
- XSTATE_WARN_ON(1);
+ XSTATE_WARN_ON(1, "Got supervisor feature %d, but XSAVES not advertised\n", i);
return false;
}
}
size = xstate_calculate_size(fpu_kernel_cfg.max_features, compacted);
- XSTATE_WARN_ON(size != kernel_size);
+ XSTATE_WARN_ON(size != kernel_size,
+ "size %u != kernel_size %u\n", size, kernel_size);
return size == kernel_size;
}
@@ -1200,8 +1200,36 @@ static int copy_from_buffer(void *dst, unsigned int offset, unsigned int size,
}
+/**
+ * copy_uabi_to_xstate - Copy a UABI format buffer to the kernel xstate
+ * @fpstate: The fpstate buffer to copy to
+ * @kbuf: The UABI format buffer, if it comes from the kernel
+ * @ubuf: The UABI format buffer, if it comes from userspace
+ * @pkru: The location to write the PKRU value to
+ *
+ * Converts from the UABI format into the kernel internal hardware
+ * dependent format.
+ *
+ * This function ultimately has three different callers with distinct PKRU
+ * behavior.
+ * 1. When called from sigreturn the PKRU register will be restored from
+ * @fpstate via an XRSTOR. Correctly copying the UABI format buffer to
+ * @fpstate is sufficient to cover this case, but the caller will also
+ * pass a pointer to the thread_struct's pkru field in @pkru and updating
+ * it is harmless.
+ * 2. When called from ptrace the PKRU register will be restored from the
+ * thread_struct's pkru field. A pointer to that is passed in @pkru.
+ * The kernel will restore it manually, so the XRSTOR behavior that resets
+ * the PKRU register to the hardware init value (0) if the corresponding
+ * xfeatures bit is not set is emulated here.
+ * 3. When called from KVM the PKRU register will be restored from the vcpu's
+ * pkru field. A pointer to that is passed in @pkru. KVM hasn't used
+ * XRSTOR and hasn't had the PKRU resetting behavior described above. To
+ * preserve that KVM behavior, it passes NULL for @pkru if the xfeatures
+ * bit is not set.
+ */
static int copy_uabi_to_xstate(struct fpstate *fpstate, const void *kbuf,
- const void __user *ubuf)
+ const void __user *ubuf, u32 *pkru)
{
struct xregs_state *xsave = &fpstate->regs.xsave;
unsigned int offset, size;
@@ -1250,6 +1278,20 @@ static int copy_uabi_to_xstate(struct fpstate *fpstate, const void *kbuf,
}
}
+ if (hdr.xfeatures & XFEATURE_MASK_PKRU) {
+ struct pkru_state *xpkru;
+
+ xpkru = __raw_xsave_addr(xsave, XFEATURE_PKRU);
+ *pkru = xpkru->pkru;
+ } else {
+ /*
+ * KVM may pass NULL here to indicate that it does not need
+ * PKRU updated.
+ */
+ if (pkru)
+ *pkru = 0;
+ }
+
/*
* The state that came in from userspace was user-state only.
* Mask all the user states out of 'xfeatures':
@@ -1268,9 +1310,9 @@ static int copy_uabi_to_xstate(struct fpstate *fpstate, const void *kbuf,
* Convert from a ptrace standard-format kernel buffer to kernel XSAVE[S]
* format and copy to the target thread. Used by ptrace and KVM.
*/
-int copy_uabi_from_kernel_to_xstate(struct fpstate *fpstate, const void *kbuf)
+int copy_uabi_from_kernel_to_xstate(struct fpstate *fpstate, const void *kbuf, u32 *pkru)
{
- return copy_uabi_to_xstate(fpstate, kbuf, NULL);
+ return copy_uabi_to_xstate(fpstate, kbuf, NULL, pkru);
}
/*
@@ -1278,10 +1320,10 @@ int copy_uabi_from_kernel_to_xstate(struct fpstate *fpstate, const void *kbuf)
* XSAVE[S] format and copy to the target thread. This is called from the
* sigreturn() and rt_sigreturn() system calls.
*/
-int copy_sigframe_from_user_to_xstate(struct fpstate *fpstate,
+int copy_sigframe_from_user_to_xstate(struct task_struct *tsk,
const void __user *ubuf)
{
- return copy_uabi_to_xstate(fpstate, NULL, ubuf);
+ return copy_uabi_to_xstate(tsk->thread.fpu.fpstate, NULL, ubuf, &tsk->thread.pkru);
}
static bool validate_independent_components(u64 mask)
diff --git a/arch/x86/kernel/fpu/xstate.h b/arch/x86/kernel/fpu/xstate.h
index 5ad47031383b..a4ecb04d8d64 100644
--- a/arch/x86/kernel/fpu/xstate.h
+++ b/arch/x86/kernel/fpu/xstate.h
@@ -46,8 +46,8 @@ extern void __copy_xstate_to_uabi_buf(struct membuf to, struct fpstate *fpstate,
u32 pkru_val, enum xstate_copy_mode copy_mode);
extern void copy_xstate_to_uabi_buf(struct membuf to, struct task_struct *tsk,
enum xstate_copy_mode mode);
-extern int copy_uabi_from_kernel_to_xstate(struct fpstate *fpstate, const void *kbuf);
-extern int copy_sigframe_from_user_to_xstate(struct fpstate *fpstate, const void __user *ubuf);
+extern int copy_uabi_from_kernel_to_xstate(struct fpstate *fpstate, const void *kbuf, u32 *pkru);
+extern int copy_sigframe_from_user_to_xstate(struct task_struct *tsk, const void __user *ubuf);
extern void fpu__init_cpu_xstate(void);
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 9b7acc9c7874..67c8ed99144b 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -261,16 +261,6 @@ SYM_FUNC_START(startup_32_smp)
addl $__PAGE_OFFSET, %esp
/*
- * start system 32-bit setup. We need to re-do some of the things done
- * in 16-bit mode for the "real" operations.
- */
- movl setup_once_ref,%eax
- andl %eax,%eax
- jz 1f # Did we do this already?
- call *%eax
-1:
-
-/*
* Check if it is 486
*/
movb $4,X86 # at least 486
@@ -331,18 +321,7 @@ SYM_FUNC_END(startup_32_smp)
#include "verify_cpu.S"
-/*
- * setup_once
- *
- * The setup work we only want to run on the BSP.
- *
- * Warning: %esi is live across this function.
- */
__INIT
-setup_once:
- andl $0,setup_once_ref /* Once is enough, thanks */
- RET
-
SYM_FUNC_START(early_idt_handler_array)
# 36(%esp) %eflags
# 32(%esp) %cs
@@ -458,7 +437,6 @@ SYM_DATA(early_recursion_flag, .long 0)
__REFDATA
.align 4
SYM_DATA(initial_code, .long i386_start_kernel)
-SYM_DATA(setup_once_ref, .long setup_once)
#ifdef CONFIG_PAGE_TABLE_ISOLATION
#define PGD_ALIGN (2 * PAGE_SIZE)
diff --git a/arch/x86/kernel/i8259.c b/arch/x86/kernel/i8259.c
index 15aefa3f3e18..3aa5304200c5 100644
--- a/arch/x86/kernel/i8259.c
+++ b/arch/x86/kernel/i8259.c
@@ -407,7 +407,7 @@ struct legacy_pic null_legacy_pic = {
.make_irq = legacy_pic_uint_noop,
};
-struct legacy_pic default_legacy_pic = {
+static struct legacy_pic default_legacy_pic = {
.nr_legacy_irqs = NR_IRQS_LEGACY,
.chip = &i8259A_chip,
.mask = mask_8259A_irq,
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c
index c032edcd3d95..d85a6980e263 100644
--- a/arch/x86/kernel/module.c
+++ b/arch/x86/kernel/module.c
@@ -53,7 +53,7 @@ static unsigned long int get_module_load_offset(void)
*/
if (module_load_offset == 0)
module_load_offset =
- (prandom_u32_max(1024) + 1) * PAGE_SIZE;
+ get_random_u32_inclusive(1, 1024) * PAGE_SIZE;
mutex_unlock(&module_kaslr_mutex);
}
return module_load_offset;
@@ -251,14 +251,12 @@ int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *me)
{
- const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL,
+ const Elf_Shdr *s, *alt = NULL, *locks = NULL,
*para = NULL, *orc = NULL, *orc_ip = NULL,
*retpolines = NULL, *returns = NULL, *ibt_endbr = NULL;
char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
- if (!strcmp(".text", secstrings + s->sh_name))
- text = s;
if (!strcmp(".altinstructions", secstrings + s->sh_name))
alt = s;
if (!strcmp(".smp_locks", secstrings + s->sh_name))
@@ -302,12 +300,13 @@ int module_finalize(const Elf_Ehdr *hdr,
void *iseg = (void *)ibt_endbr->sh_addr;
apply_ibt_endbr(iseg, iseg + ibt_endbr->sh_size);
}
- if (locks && text) {
+ if (locks) {
void *lseg = (void *)locks->sh_addr;
- void *tseg = (void *)text->sh_addr;
+ void *text = me->core_layout.base;
+ void *text_end = text + me->core_layout.text_size;
alternatives_smp_module_add(me, me->name,
lseg, lseg + locks->sh_size,
- tseg, tseg + text->sh_size);
+ text, text_end);
}
if (orc && orc_ip)
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index e436c9c1ef3b..40d156a31676 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -965,7 +965,7 @@ early_param("idle", idle_setup);
unsigned long arch_align_stack(unsigned long sp)
{
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
- sp -= prandom_u32_max(8192);
+ sp -= get_random_u32_below(8192);
return sp & ~0xf;
}
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 6b3418bff326..e2f469175be8 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -165,7 +165,7 @@ static noinstr unsigned long __rdgsbase_inactive(void)
lockdep_assert_irqs_disabled();
- if (!static_cpu_has(X86_FEATURE_XENPV)) {
+ if (!cpu_feature_enabled(X86_FEATURE_XENPV)) {
native_swapgs();
gsbase = rdgsbase();
native_swapgs();
@@ -190,7 +190,7 @@ static noinstr void __wrgsbase_inactive(unsigned long gsbase)
{
lockdep_assert_irqs_disabled();
- if (!static_cpu_has(X86_FEATURE_XENPV)) {
+ if (!cpu_feature_enabled(X86_FEATURE_XENPV)) {
native_swapgs();
wrgsbase(gsbase);
native_swapgs();
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 37c12fb92906..dfaa270a7cc9 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -44,16 +44,35 @@
#include "tls.h"
-enum x86_regset {
- REGSET_GENERAL,
- REGSET_FP,
- REGSET_XFP,
- REGSET_IOPERM64 = REGSET_XFP,
- REGSET_XSTATE,
- REGSET_TLS,
- REGSET_IOPERM32,
+enum x86_regset_32 {
+ REGSET32_GENERAL,
+ REGSET32_FP,
+ REGSET32_XFP,
+ REGSET32_XSTATE,
+ REGSET32_TLS,
+ REGSET32_IOPERM,
};
+enum x86_regset_64 {
+ REGSET64_GENERAL,
+ REGSET64_FP,
+ REGSET64_IOPERM,
+ REGSET64_XSTATE,
+};
+
+#define REGSET_GENERAL \
+({ \
+ BUILD_BUG_ON((int)REGSET32_GENERAL != (int)REGSET64_GENERAL); \
+ REGSET32_GENERAL; \
+})
+
+#define REGSET_FP \
+({ \
+ BUILD_BUG_ON((int)REGSET32_FP != (int)REGSET64_FP); \
+ REGSET32_FP; \
+})
+
+
struct pt_regs_offset {
const char *name;
int offset;
@@ -788,13 +807,13 @@ long arch_ptrace(struct task_struct *child, long request,
#ifdef CONFIG_X86_32
case PTRACE_GETFPXREGS: /* Get the child extended FPU state. */
return copy_regset_to_user(child, &user_x86_32_view,
- REGSET_XFP,
+ REGSET32_XFP,
0, sizeof(struct user_fxsr_struct),
datap) ? -EIO : 0;
case PTRACE_SETFPXREGS: /* Set the child extended FPU state. */
return copy_regset_from_user(child, &user_x86_32_view,
- REGSET_XFP,
+ REGSET32_XFP,
0, sizeof(struct user_fxsr_struct),
datap) ? -EIO : 0;
#endif
@@ -1086,13 +1105,13 @@ static long ia32_arch_ptrace(struct task_struct *child, compat_long_t request,
case PTRACE_GETFPXREGS: /* Get the child extended FPU state. */
return copy_regset_to_user(child, &user_x86_32_view,
- REGSET_XFP, 0,
+ REGSET32_XFP, 0,
sizeof(struct user32_fxsr_struct),
datap);
case PTRACE_SETFPXREGS: /* Set the child extended FPU state. */
return copy_regset_from_user(child, &user_x86_32_view,
- REGSET_XFP, 0,
+ REGSET32_XFP, 0,
sizeof(struct user32_fxsr_struct),
datap);
@@ -1215,29 +1234,38 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
#ifdef CONFIG_X86_64
static struct user_regset x86_64_regsets[] __ro_after_init = {
- [REGSET_GENERAL] = {
- .core_note_type = NT_PRSTATUS,
- .n = sizeof(struct user_regs_struct) / sizeof(long),
- .size = sizeof(long), .align = sizeof(long),
- .regset_get = genregs_get, .set = genregs_set
+ [REGSET64_GENERAL] = {
+ .core_note_type = NT_PRSTATUS,
+ .n = sizeof(struct user_regs_struct) / sizeof(long),
+ .size = sizeof(long),
+ .align = sizeof(long),
+ .regset_get = genregs_get,
+ .set = genregs_set
},
- [REGSET_FP] = {
- .core_note_type = NT_PRFPREG,
- .n = sizeof(struct fxregs_state) / sizeof(long),
- .size = sizeof(long), .align = sizeof(long),
- .active = regset_xregset_fpregs_active, .regset_get = xfpregs_get, .set = xfpregs_set
+ [REGSET64_FP] = {
+ .core_note_type = NT_PRFPREG,
+ .n = sizeof(struct fxregs_state) / sizeof(long),
+ .size = sizeof(long),
+ .align = sizeof(long),
+ .active = regset_xregset_fpregs_active,
+ .regset_get = xfpregs_get,
+ .set = xfpregs_set
},
- [REGSET_XSTATE] = {
- .core_note_type = NT_X86_XSTATE,
- .size = sizeof(u64), .align = sizeof(u64),
- .active = xstateregs_active, .regset_get = xstateregs_get,
- .set = xstateregs_set
+ [REGSET64_XSTATE] = {
+ .core_note_type = NT_X86_XSTATE,
+ .size = sizeof(u64),
+ .align = sizeof(u64),
+ .active = xstateregs_active,
+ .regset_get = xstateregs_get,
+ .set = xstateregs_set
},
- [REGSET_IOPERM64] = {
- .core_note_type = NT_386_IOPERM,
- .n = IO_BITMAP_LONGS,
- .size = sizeof(long), .align = sizeof(long),
- .active = ioperm_active, .regset_get = ioperm_get
+ [REGSET64_IOPERM] = {
+ .core_note_type = NT_386_IOPERM,
+ .n = IO_BITMAP_LONGS,
+ .size = sizeof(long),
+ .align = sizeof(long),
+ .active = ioperm_active,
+ .regset_get = ioperm_get
},
};
@@ -1256,43 +1284,57 @@ static const struct user_regset_view user_x86_64_view = {
#if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION
static struct user_regset x86_32_regsets[] __ro_after_init = {
- [REGSET_GENERAL] = {
- .core_note_type = NT_PRSTATUS,
- .n = sizeof(struct user_regs_struct32) / sizeof(u32),
- .size = sizeof(u32), .align = sizeof(u32),
- .regset_get = genregs32_get, .set = genregs32_set
+ [REGSET32_GENERAL] = {
+ .core_note_type = NT_PRSTATUS,
+ .n = sizeof(struct user_regs_struct32) / sizeof(u32),
+ .size = sizeof(u32),
+ .align = sizeof(u32),
+ .regset_get = genregs32_get,
+ .set = genregs32_set
},
- [REGSET_FP] = {
- .core_note_type = NT_PRFPREG,
- .n = sizeof(struct user_i387_ia32_struct) / sizeof(u32),
- .size = sizeof(u32), .align = sizeof(u32),
- .active = regset_fpregs_active, .regset_get = fpregs_get, .set = fpregs_set
+ [REGSET32_FP] = {
+ .core_note_type = NT_PRFPREG,
+ .n = sizeof(struct user_i387_ia32_struct) / sizeof(u32),
+ .size = sizeof(u32),
+ .align = sizeof(u32),
+ .active = regset_fpregs_active,
+ .regset_get = fpregs_get,
+ .set = fpregs_set
},
- [REGSET_XFP] = {
- .core_note_type = NT_PRXFPREG,
- .n = sizeof(struct fxregs_state) / sizeof(u32),
- .size = sizeof(u32), .align = sizeof(u32),
- .active = regset_xregset_fpregs_active, .regset_get = xfpregs_get, .set = xfpregs_set
+ [REGSET32_XFP] = {
+ .core_note_type = NT_PRXFPREG,
+ .n = sizeof(struct fxregs_state) / sizeof(u32),
+ .size = sizeof(u32),
+ .align = sizeof(u32),
+ .active = regset_xregset_fpregs_active,
+ .regset_get = xfpregs_get,
+ .set = xfpregs_set
},
- [REGSET_XSTATE] = {
- .core_note_type = NT_X86_XSTATE,
- .size = sizeof(u64), .align = sizeof(u64),
- .active = xstateregs_active, .regset_get = xstateregs_get,
- .set = xstateregs_set
+ [REGSET32_XSTATE] = {
+ .core_note_type = NT_X86_XSTATE,
+ .size = sizeof(u64),
+ .align = sizeof(u64),
+ .active = xstateregs_active,
+ .regset_get = xstateregs_get,
+ .set = xstateregs_set
},
- [REGSET_TLS] = {
- .core_note_type = NT_386_TLS,
- .n = GDT_ENTRY_TLS_ENTRIES, .bias = GDT_ENTRY_TLS_MIN,
- .size = sizeof(struct user_desc),
- .align = sizeof(struct user_desc),
- .active = regset_tls_active,
- .regset_get = regset_tls_get, .set = regset_tls_set
+ [REGSET32_TLS] = {
+ .core_note_type = NT_386_TLS,
+ .n = GDT_ENTRY_TLS_ENTRIES,
+ .bias = GDT_ENTRY_TLS_MIN,
+ .size = sizeof(struct user_desc),
+ .align = sizeof(struct user_desc),
+ .active = regset_tls_active,
+ .regset_get = regset_tls_get,
+ .set = regset_tls_set
},
- [REGSET_IOPERM32] = {
- .core_note_type = NT_386_IOPERM,
- .n = IO_BITMAP_BYTES / sizeof(u32),
- .size = sizeof(u32), .align = sizeof(u32),
- .active = ioperm_active, .regset_get = ioperm_get
+ [REGSET32_IOPERM] = {
+ .core_note_type = NT_386_IOPERM,
+ .n = IO_BITMAP_BYTES / sizeof(u32),
+ .size = sizeof(u32),
+ .align = sizeof(u32),
+ .active = ioperm_active,
+ .regset_get = ioperm_get
},
};
@@ -1311,10 +1353,10 @@ u64 xstate_fx_sw_bytes[USER_XSTATE_FX_SW_WORDS];
void __init update_regset_xstate_info(unsigned int size, u64 xstate_mask)
{
#ifdef CONFIG_X86_64
- x86_64_regsets[REGSET_XSTATE].n = size / sizeof(u64);
+ x86_64_regsets[REGSET64_XSTATE].n = size / sizeof(u64);
#endif
#if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION
- x86_32_regsets[REGSET_XSTATE].n = size / sizeof(u64);
+ x86_32_regsets[REGSET32_XSTATE].n = size / sizeof(u64);
#endif
xstate_fx_sw_bytes[USER_XSTATE_XCR0_WORD] = xstate_mask;
}
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 216fee7144ee..88188549647c 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -31,9 +31,11 @@
#include <xen/xen.h>
#include <asm/apic.h>
+#include <asm/efi.h>
#include <asm/numa.h>
#include <asm/bios_ebda.h>
#include <asm/bugs.h>
+#include <asm/cacheinfo.h>
#include <asm/cpu.h>
#include <asm/efi.h>
#include <asm/gart.h>
@@ -1074,24 +1076,13 @@ void __init setup_arch(char **cmdline_p)
max_pfn = e820__end_of_ram_pfn();
/* update e820 for memory not covered by WB MTRRs */
- if (IS_ENABLED(CONFIG_MTRR))
- mtrr_bp_init();
- else
- pat_disable("PAT support disabled because CONFIG_MTRR is disabled in the kernel.");
-
+ cache_bp_init();
if (mtrr_trim_uncached_memory(max_pfn))
max_pfn = e820__end_of_ram_pfn();
max_possible_pfn = max_pfn;
/*
- * This call is required when the CPU does not support PAT. If
- * mtrr_bp_init() invoked it already via pat_init() the call has no
- * effect.
- */
- init_cache_modes();
-
- /*
* Define random base addresses for memory sections after max_pfn is
* defined and before each memory section base is used.
*/
@@ -1175,7 +1166,7 @@ void __init setup_arch(char **cmdline_p)
* Moreover, on machines with SandyBridge graphics or in setups that use
* crashkernel the entire 1M is reserved anyway.
*/
- reserve_real_mode();
+ x86_platform.realmode_reserve();
init_mem_mapping();
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c
index 49325caa7307..b26123c90b4f 100644
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -11,6 +11,7 @@
#include <linux/smp.h>
#include <linux/topology.h>
#include <linux/pfn.h>
+#include <linux/stackprotector.h>
#include <asm/sections.h>
#include <asm/processor.h>
#include <asm/desc.h>
@@ -21,7 +22,6 @@
#include <asm/proto.h>
#include <asm/cpumask.h>
#include <asm/cpu.h>
-#include <asm/stackprotector.h>
DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number);
EXPORT_PER_CPU_SYMBOL(cpu_number);
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 9c7265b524c7..1504eb8d25aa 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -37,180 +37,27 @@
#include <asm/sighandling.h>
#include <asm/vm86.h>
-#ifdef CONFIG_X86_64
-#include <linux/compat.h>
-#include <asm/proto.h>
-#include <asm/ia32_unistd.h>
-#include <asm/fpu/xstate.h>
-#endif /* CONFIG_X86_64 */
-
#include <asm/syscall.h>
#include <asm/sigframe.h>
#include <asm/signal.h>
-#ifdef CONFIG_X86_64
-/*
- * If regs->ss will cause an IRET fault, change it. Otherwise leave it
- * alone. Using this generally makes no sense unless
- * user_64bit_mode(regs) would return true.
- */
-static void force_valid_ss(struct pt_regs *regs)
+static inline int is_ia32_compat_frame(struct ksignal *ksig)
{
- u32 ar;
- asm volatile ("lar %[old_ss], %[ar]\n\t"
- "jz 1f\n\t" /* If invalid: */
- "xorl %[ar], %[ar]\n\t" /* set ar = 0 */
- "1:"
- : [ar] "=r" (ar)
- : [old_ss] "rm" ((u16)regs->ss));
-
- /*
- * For a valid 64-bit user context, we need DPL 3, type
- * read-write data or read-write exp-down data, and S and P
- * set. We can't use VERW because VERW doesn't check the
- * P bit.
- */
- ar &= AR_DPL_MASK | AR_S | AR_P | AR_TYPE_MASK;
- if (ar != (AR_DPL3 | AR_S | AR_P | AR_TYPE_RWDATA) &&
- ar != (AR_DPL3 | AR_S | AR_P | AR_TYPE_RWDATA_EXPDOWN))
- regs->ss = __USER_DS;
+ return IS_ENABLED(CONFIG_IA32_EMULATION) &&
+ ksig->ka.sa.sa_flags & SA_IA32_ABI;
}
-# define CONTEXT_COPY_SIZE offsetof(struct sigcontext, reserved1)
-#else
-# define CONTEXT_COPY_SIZE sizeof(struct sigcontext)
-#endif
-static bool restore_sigcontext(struct pt_regs *regs,
- struct sigcontext __user *usc,
- unsigned long uc_flags)
+static inline int is_ia32_frame(struct ksignal *ksig)
{
- struct sigcontext sc;
-
- /* Always make any pending restarted system calls return -EINTR */
- current->restart_block.fn = do_no_restart_syscall;
-
- if (copy_from_user(&sc, usc, CONTEXT_COPY_SIZE))
- return false;
-
-#ifdef CONFIG_X86_32
- loadsegment(gs, sc.gs);
- regs->fs = sc.fs;
- regs->es = sc.es;
- regs->ds = sc.ds;
-#endif /* CONFIG_X86_32 */
-
- regs->bx = sc.bx;
- regs->cx = sc.cx;
- regs->dx = sc.dx;
- regs->si = sc.si;
- regs->di = sc.di;
- regs->bp = sc.bp;
- regs->ax = sc.ax;
- regs->sp = sc.sp;
- regs->ip = sc.ip;
-
-#ifdef CONFIG_X86_64
- regs->r8 = sc.r8;
- regs->r9 = sc.r9;
- regs->r10 = sc.r10;
- regs->r11 = sc.r11;
- regs->r12 = sc.r12;
- regs->r13 = sc.r13;
- regs->r14 = sc.r14;
- regs->r15 = sc.r15;
-#endif /* CONFIG_X86_64 */
-
- /* Get CS/SS and force CPL3 */
- regs->cs = sc.cs | 0x03;
- regs->ss = sc.ss | 0x03;
-
- regs->flags = (regs->flags & ~FIX_EFLAGS) | (sc.flags & FIX_EFLAGS);
- /* disable syscall checks */
- regs->orig_ax = -1;
-
-#ifdef CONFIG_X86_64
- /*
- * Fix up SS if needed for the benefit of old DOSEMU and
- * CRIU.
- */
- if (unlikely(!(uc_flags & UC_STRICT_RESTORE_SS) && user_64bit_mode(regs)))
- force_valid_ss(regs);
-#endif
-
- return fpu__restore_sig((void __user *)sc.fpstate,
- IS_ENABLED(CONFIG_X86_32));
+ return IS_ENABLED(CONFIG_X86_32) || is_ia32_compat_frame(ksig);
}
-static __always_inline int
-__unsafe_setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
- struct pt_regs *regs, unsigned long mask)
+static inline int is_x32_frame(struct ksignal *ksig)
{
-#ifdef CONFIG_X86_32
- unsigned int gs;
- savesegment(gs, gs);
-
- unsafe_put_user(gs, (unsigned int __user *)&sc->gs, Efault);
- unsafe_put_user(regs->fs, (unsigned int __user *)&sc->fs, Efault);
- unsafe_put_user(regs->es, (unsigned int __user *)&sc->es, Efault);
- unsafe_put_user(regs->ds, (unsigned int __user *)&sc->ds, Efault);
-#endif /* CONFIG_X86_32 */
-
- unsafe_put_user(regs->di, &sc->di, Efault);
- unsafe_put_user(regs->si, &sc->si, Efault);
- unsafe_put_user(regs->bp, &sc->bp, Efault);
- unsafe_put_user(regs->sp, &sc->sp, Efault);
- unsafe_put_user(regs->bx, &sc->bx, Efault);
- unsafe_put_user(regs->dx, &sc->dx, Efault);
- unsafe_put_user(regs->cx, &sc->cx, Efault);
- unsafe_put_user(regs->ax, &sc->ax, Efault);
-#ifdef CONFIG_X86_64
- unsafe_put_user(regs->r8, &sc->r8, Efault);
- unsafe_put_user(regs->r9, &sc->r9, Efault);
- unsafe_put_user(regs->r10, &sc->r10, Efault);
- unsafe_put_user(regs->r11, &sc->r11, Efault);
- unsafe_put_user(regs->r12, &sc->r12, Efault);
- unsafe_put_user(regs->r13, &sc->r13, Efault);
- unsafe_put_user(regs->r14, &sc->r14, Efault);
- unsafe_put_user(regs->r15, &sc->r15, Efault);
-#endif /* CONFIG_X86_64 */
-
- unsafe_put_user(current->thread.trap_nr, &sc->trapno, Efault);
- unsafe_put_user(current->thread.error_code, &sc->err, Efault);
- unsafe_put_user(regs->ip, &sc->ip, Efault);
-#ifdef CONFIG_X86_32
- unsafe_put_user(regs->cs, (unsigned int __user *)&sc->cs, Efault);
- unsafe_put_user(regs->flags, &sc->flags, Efault);
- unsafe_put_user(regs->sp, &sc->sp_at_signal, Efault);
- unsafe_put_user(regs->ss, (unsigned int __user *)&sc->ss, Efault);
-#else /* !CONFIG_X86_32 */
- unsafe_put_user(regs->flags, &sc->flags, Efault);
- unsafe_put_user(regs->cs, &sc->cs, Efault);
- unsafe_put_user(0, &sc->gs, Efault);
- unsafe_put_user(0, &sc->fs, Efault);
- unsafe_put_user(regs->ss, &sc->ss, Efault);
-#endif /* CONFIG_X86_32 */
-
- unsafe_put_user(fpstate, (unsigned long __user *)&sc->fpstate, Efault);
-
- /* non-iBCS2 extensions.. */
- unsafe_put_user(mask, &sc->oldmask, Efault);
- unsafe_put_user(current->thread.cr2, &sc->cr2, Efault);
- return 0;
-Efault:
- return -EFAULT;
+ return IS_ENABLED(CONFIG_X86_X32_ABI) &&
+ ksig->ka.sa.sa_flags & SA_X32_ABI;
}
-#define unsafe_put_sigcontext(sc, fp, regs, set, label) \
-do { \
- if (__unsafe_setup_sigcontext(sc, fp, regs, set->sig[0])) \
- goto label; \
-} while(0);
-
-#define unsafe_put_sigmask(set, frame, label) \
- unsafe_put_user(*(__u64 *)(set), \
- (__u64 __user *)&(frame)->uc.uc_sigmask, \
- label)
-
/*
* Set up a signal frame.
*/
@@ -223,24 +70,12 @@ do { \
/*
* Determine which stack to use..
*/
-static unsigned long align_sigframe(unsigned long sp)
-{
-#ifdef CONFIG_X86_32
- /*
- * Align the stack pointer according to the i386 ABI,
- * i.e. so that on function entry ((sp + 4) & 15) == 0.
- */
- sp = ((sp + 4) & -FRAME_ALIGNMENT) - 4;
-#else /* !CONFIG_X86_32 */
- sp = round_down(sp, FRAME_ALIGNMENT) - 8;
-#endif
- return sp;
-}
-
-static void __user *
-get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
+void __user *
+get_sigframe(struct ksignal *ksig, struct pt_regs *regs, size_t frame_size,
void __user **fpstate)
{
+ struct k_sigaction *ka = &ksig->ka;
+ int ia32_frame = is_ia32_frame(ksig);
/* Default to using normal stack */
bool nested_altstack = on_sig_stack(regs->sp);
bool entering_altstack = false;
@@ -249,7 +84,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
unsigned long buf_fx = 0;
/* redzone */
- if (IS_ENABLED(CONFIG_X86_64))
+ if (!ia32_frame)
sp -= 128;
/* This is the X/Open sanctioned signal stack switching. */
@@ -263,7 +98,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
sp = current->sas_ss_sp + current->sas_ss_size;
entering_altstack = true;
}
- } else if (IS_ENABLED(CONFIG_X86_32) &&
+ } else if (ia32_frame &&
!nested_altstack &&
regs->ss != __USER_DS &&
!(ka->sa.sa_flags & SA_RESTORER) &&
@@ -273,11 +108,19 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
entering_altstack = true;
}
- sp = fpu__alloc_mathframe(sp, IS_ENABLED(CONFIG_X86_32),
- &buf_fx, &math_size);
+ sp = fpu__alloc_mathframe(sp, ia32_frame, &buf_fx, &math_size);
*fpstate = (void __user *)sp;
- sp = align_sigframe(sp - frame_size);
+ sp -= frame_size;
+
+ if (ia32_frame)
+ /*
+ * Align the stack pointer according to the i386 ABI,
+ * i.e. so that on function entry ((sp + 4) & 15) == 0.
+ */
+ sp = ((sp + 4) & -FRAME_ALIGNMENT) - 4;
+ else
+ sp = round_down(sp, FRAME_ALIGNMENT) - 8;
/*
* If we are on the alternate signal stack and would overflow it, don't.
@@ -300,391 +143,6 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
return (void __user *)sp;
}
-#ifdef CONFIG_X86_32
-static const struct {
- u16 poplmovl;
- u32 val;
- u16 int80;
-} __attribute__((packed)) retcode = {
- 0xb858, /* popl %eax; movl $..., %eax */
- __NR_sigreturn,
- 0x80cd, /* int $0x80 */
-};
-
-static const struct {
- u8 movl;
- u32 val;
- u16 int80;
- u8 pad;
-} __attribute__((packed)) rt_retcode = {
- 0xb8, /* movl $..., %eax */
- __NR_rt_sigreturn,
- 0x80cd, /* int $0x80 */
- 0
-};
-
-static int
-__setup_frame(int sig, struct ksignal *ksig, sigset_t *set,
- struct pt_regs *regs)
-{
- struct sigframe __user *frame;
- void __user *restorer;
- void __user *fp = NULL;
-
- frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fp);
-
- if (!user_access_begin(frame, sizeof(*frame)))
- return -EFAULT;
-
- unsafe_put_user(sig, &frame->sig, Efault);
- unsafe_put_sigcontext(&frame->sc, fp, regs, set, Efault);
- unsafe_put_user(set->sig[1], &frame->extramask[0], Efault);
- if (current->mm->context.vdso)
- restorer = current->mm->context.vdso +
- vdso_image_32.sym___kernel_sigreturn;
- else
- restorer = &frame->retcode;
- if (ksig->ka.sa.sa_flags & SA_RESTORER)
- restorer = ksig->ka.sa.sa_restorer;
-
- /* Set up to return from userspace. */
- unsafe_put_user(restorer, &frame->pretcode, Efault);
-
- /*
- * This is popl %eax ; movl $__NR_sigreturn, %eax ; int $0x80
- *
- * WE DO NOT USE IT ANY MORE! It's only left here for historical
- * reasons and because gdb uses it as a signature to notice
- * signal handler stack frames.
- */
- unsafe_put_user(*((u64 *)&retcode), (u64 *)frame->retcode, Efault);
- user_access_end();
-
- /* Set up registers for signal handler */
- regs->sp = (unsigned long)frame;
- regs->ip = (unsigned long)ksig->ka.sa.sa_handler;
- regs->ax = (unsigned long)sig;
- regs->dx = 0;
- regs->cx = 0;
-
- regs->ds = __USER_DS;
- regs->es = __USER_DS;
- regs->ss = __USER_DS;
- regs->cs = __USER_CS;
-
- return 0;
-
-Efault:
- user_access_end();
- return -EFAULT;
-}
-
-static int __setup_rt_frame(int sig, struct ksignal *ksig,
- sigset_t *set, struct pt_regs *regs)
-{
- struct rt_sigframe __user *frame;
- void __user *restorer;
- void __user *fp = NULL;
-
- frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fp);
-
- if (!user_access_begin(frame, sizeof(*frame)))
- return -EFAULT;
-
- unsafe_put_user(sig, &frame->sig, Efault);
- unsafe_put_user(&frame->info, &frame->pinfo, Efault);
- unsafe_put_user(&frame->uc, &frame->puc, Efault);
-
- /* Create the ucontext. */
- if (static_cpu_has(X86_FEATURE_XSAVE))
- unsafe_put_user(UC_FP_XSTATE, &frame->uc.uc_flags, Efault);
- else
- unsafe_put_user(0, &frame->uc.uc_flags, Efault);
- unsafe_put_user(0, &frame->uc.uc_link, Efault);
- unsafe_save_altstack(&frame->uc.uc_stack, regs->sp, Efault);
-
- /* Set up to return from userspace. */
- restorer = current->mm->context.vdso +
- vdso_image_32.sym___kernel_rt_sigreturn;
- if (ksig->ka.sa.sa_flags & SA_RESTORER)
- restorer = ksig->ka.sa.sa_restorer;
- unsafe_put_user(restorer, &frame->pretcode, Efault);
-
- /*
- * This is movl $__NR_rt_sigreturn, %ax ; int $0x80
- *
- * WE DO NOT USE IT ANY MORE! It's only left here for historical
- * reasons and because gdb uses it as a signature to notice
- * signal handler stack frames.
- */
- unsafe_put_user(*((u64 *)&rt_retcode), (u64 *)frame->retcode, Efault);
- unsafe_put_sigcontext(&frame->uc.uc_mcontext, fp, regs, set, Efault);
- unsafe_put_sigmask(set, frame, Efault);
- user_access_end();
-
- if (copy_siginfo_to_user(&frame->info, &ksig->info))
- return -EFAULT;
-
- /* Set up registers for signal handler */
- regs->sp = (unsigned long)frame;
- regs->ip = (unsigned long)ksig->ka.sa.sa_handler;
- regs->ax = (unsigned long)sig;
- regs->dx = (unsigned long)&frame->info;
- regs->cx = (unsigned long)&frame->uc;
-
- regs->ds = __USER_DS;
- regs->es = __USER_DS;
- regs->ss = __USER_DS;
- regs->cs = __USER_CS;
-
- return 0;
-Efault:
- user_access_end();
- return -EFAULT;
-}
-#else /* !CONFIG_X86_32 */
-static unsigned long frame_uc_flags(struct pt_regs *regs)
-{
- unsigned long flags;
-
- if (boot_cpu_has(X86_FEATURE_XSAVE))
- flags = UC_FP_XSTATE | UC_SIGCONTEXT_SS;
- else
- flags = UC_SIGCONTEXT_SS;
-
- if (likely(user_64bit_mode(regs)))
- flags |= UC_STRICT_RESTORE_SS;
-
- return flags;
-}
-
-static int __setup_rt_frame(int sig, struct ksignal *ksig,
- sigset_t *set, struct pt_regs *regs)
-{
- struct rt_sigframe __user *frame;
- void __user *fp = NULL;
- unsigned long uc_flags;
-
- /* x86-64 should always use SA_RESTORER. */
- if (!(ksig->ka.sa.sa_flags & SA_RESTORER))
- return -EFAULT;
-
- frame = get_sigframe(&ksig->ka, regs, sizeof(struct rt_sigframe), &fp);
- uc_flags = frame_uc_flags(regs);
-
- if (!user_access_begin(frame, sizeof(*frame)))
- return -EFAULT;
-
- /* Create the ucontext. */
- unsafe_put_user(uc_flags, &frame->uc.uc_flags, Efault);
- unsafe_put_user(0, &frame->uc.uc_link, Efault);
- unsafe_save_altstack(&frame->uc.uc_stack, regs->sp, Efault);
-
- /* Set up to return from userspace. If provided, use a stub
- already in userspace. */
- unsafe_put_user(ksig->ka.sa.sa_restorer, &frame->pretcode, Efault);
- unsafe_put_sigcontext(&frame->uc.uc_mcontext, fp, regs, set, Efault);
- unsafe_put_sigmask(set, frame, Efault);
- user_access_end();
-
- if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
- if (copy_siginfo_to_user(&frame->info, &ksig->info))
- return -EFAULT;
- }
-
- /* Set up registers for signal handler */
- regs->di = sig;
- /* In case the signal handler was declared without prototypes */
- regs->ax = 0;
-
- /* This also works for non SA_SIGINFO handlers because they expect the
- next argument after the signal number on the stack. */
- regs->si = (unsigned long)&frame->info;
- regs->dx = (unsigned long)&frame->uc;
- regs->ip = (unsigned long) ksig->ka.sa.sa_handler;
-
- regs->sp = (unsigned long)frame;
-
- /*
- * Set up the CS and SS registers to run signal handlers in
- * 64-bit mode, even if the handler happens to be interrupting
- * 32-bit or 16-bit code.
- *
- * SS is subtle. In 64-bit mode, we don't need any particular
- * SS descriptor, but we do need SS to be valid. It's possible
- * that the old SS is entirely bogus -- this can happen if the
- * signal we're trying to deliver is #GP or #SS caused by a bad
- * SS value. We also have a compatibility issue here: DOSEMU
- * relies on the contents of the SS register indicating the
- * SS value at the time of the signal, even though that code in
- * DOSEMU predates sigreturn's ability to restore SS. (DOSEMU
- * avoids relying on sigreturn to restore SS; instead it uses
- * a trampoline.) So we do our best: if the old SS was valid,
- * we keep it. Otherwise we replace it.
- */
- regs->cs = __USER_CS;
-
- if (unlikely(regs->ss != __USER_DS))
- force_valid_ss(regs);
-
- return 0;
-
-Efault:
- user_access_end();
- return -EFAULT;
-}
-#endif /* CONFIG_X86_32 */
-
-#ifdef CONFIG_X86_X32_ABI
-static int x32_copy_siginfo_to_user(struct compat_siginfo __user *to,
- const struct kernel_siginfo *from)
-{
- struct compat_siginfo new;
-
- copy_siginfo_to_external32(&new, from);
- if (from->si_signo == SIGCHLD) {
- new._sifields._sigchld_x32._utime = from->si_utime;
- new._sifields._sigchld_x32._stime = from->si_stime;
- }
- if (copy_to_user(to, &new, sizeof(struct compat_siginfo)))
- return -EFAULT;
- return 0;
-}
-
-int copy_siginfo_to_user32(struct compat_siginfo __user *to,
- const struct kernel_siginfo *from)
-{
- if (in_x32_syscall())
- return x32_copy_siginfo_to_user(to, from);
- return __copy_siginfo_to_user32(to, from);
-}
-#endif /* CONFIG_X86_X32_ABI */
-
-static int x32_setup_rt_frame(struct ksignal *ksig,
- compat_sigset_t *set,
- struct pt_regs *regs)
-{
-#ifdef CONFIG_X86_X32_ABI
- struct rt_sigframe_x32 __user *frame;
- unsigned long uc_flags;
- void __user *restorer;
- void __user *fp = NULL;
-
- if (!(ksig->ka.sa.sa_flags & SA_RESTORER))
- return -EFAULT;
-
- frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fp);
-
- uc_flags = frame_uc_flags(regs);
-
- if (!user_access_begin(frame, sizeof(*frame)))
- return -EFAULT;
-
- /* Create the ucontext. */
- unsafe_put_user(uc_flags, &frame->uc.uc_flags, Efault);
- unsafe_put_user(0, &frame->uc.uc_link, Efault);
- unsafe_compat_save_altstack(&frame->uc.uc_stack, regs->sp, Efault);
- unsafe_put_user(0, &frame->uc.uc__pad0, Efault);
- restorer = ksig->ka.sa.sa_restorer;
- unsafe_put_user(restorer, (unsigned long __user *)&frame->pretcode, Efault);
- unsafe_put_sigcontext(&frame->uc.uc_mcontext, fp, regs, set, Efault);
- unsafe_put_sigmask(set, frame, Efault);
- user_access_end();
-
- if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
- if (x32_copy_siginfo_to_user(&frame->info, &ksig->info))
- return -EFAULT;
- }
-
- /* Set up registers for signal handler */
- regs->sp = (unsigned long) frame;
- regs->ip = (unsigned long) ksig->ka.sa.sa_handler;
-
- /* We use the x32 calling convention here... */
- regs->di = ksig->sig;
- regs->si = (unsigned long) &frame->info;
- regs->dx = (unsigned long) &frame->uc;
-
- loadsegment(ds, __USER_DS);
- loadsegment(es, __USER_DS);
-
- regs->cs = __USER_CS;
- regs->ss = __USER_DS;
-#endif /* CONFIG_X86_X32_ABI */
-
- return 0;
-#ifdef CONFIG_X86_X32_ABI
-Efault:
- user_access_end();
- return -EFAULT;
-#endif
-}
-
-/*
- * Do a signal return; undo the signal stack.
- */
-#ifdef CONFIG_X86_32
-SYSCALL_DEFINE0(sigreturn)
-{
- struct pt_regs *regs = current_pt_regs();
- struct sigframe __user *frame;
- sigset_t set;
-
- frame = (struct sigframe __user *)(regs->sp - 8);
-
- if (!access_ok(frame, sizeof(*frame)))
- goto badframe;
- if (__get_user(set.sig[0], &frame->sc.oldmask) ||
- __get_user(set.sig[1], &frame->extramask[0]))
- goto badframe;
-
- set_current_blocked(&set);
-
- /*
- * x86_32 has no uc_flags bits relevant to restore_sigcontext.
- * Save a few cycles by skipping the __get_user.
- */
- if (!restore_sigcontext(regs, &frame->sc, 0))
- goto badframe;
- return regs->ax;
-
-badframe:
- signal_fault(regs, frame, "sigreturn");
-
- return 0;
-}
-#endif /* CONFIG_X86_32 */
-
-SYSCALL_DEFINE0(rt_sigreturn)
-{
- struct pt_regs *regs = current_pt_regs();
- struct rt_sigframe __user *frame;
- sigset_t set;
- unsigned long uc_flags;
-
- frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long));
- if (!access_ok(frame, sizeof(*frame)))
- goto badframe;
- if (__get_user(*(__u64 *)&set, (__u64 __user *)&frame->uc.uc_sigmask))
- goto badframe;
- if (__get_user(uc_flags, &frame->uc.uc_flags))
- goto badframe;
-
- set_current_blocked(&set);
-
- if (!restore_sigcontext(regs, &frame->uc.uc_mcontext, uc_flags))
- goto badframe;
-
- if (restore_altstack(&frame->uc.uc_stack))
- goto badframe;
-
- return regs->ax;
-
-badframe:
- signal_fault(regs, frame, "rt_sigreturn");
- return 0;
-}
-
/*
* There are four different struct types for signal frame: sigframe_ia32,
* rt_sigframe_ia32, rt_sigframe_x32, and rt_sigframe. Use the worst case
@@ -743,43 +201,22 @@ unsigned long get_sigframe_size(void)
return max_frame_size;
}
-static inline int is_ia32_compat_frame(struct ksignal *ksig)
-{
- return IS_ENABLED(CONFIG_IA32_EMULATION) &&
- ksig->ka.sa.sa_flags & SA_IA32_ABI;
-}
-
-static inline int is_ia32_frame(struct ksignal *ksig)
-{
- return IS_ENABLED(CONFIG_X86_32) || is_ia32_compat_frame(ksig);
-}
-
-static inline int is_x32_frame(struct ksignal *ksig)
-{
- return IS_ENABLED(CONFIG_X86_X32_ABI) &&
- ksig->ka.sa.sa_flags & SA_X32_ABI;
-}
-
static int
setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
{
- int usig = ksig->sig;
- sigset_t *set = sigmask_to_save();
- compat_sigset_t *cset = (compat_sigset_t *) set;
-
/* Perform fixup for the pre-signal frame. */
rseq_signal_deliver(ksig, regs);
/* Set up the stack frame */
if (is_ia32_frame(ksig)) {
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
- return ia32_setup_rt_frame(usig, ksig, cset, regs);
+ return ia32_setup_rt_frame(ksig, regs);
else
- return ia32_setup_frame(usig, ksig, cset, regs);
+ return ia32_setup_frame(ksig, regs);
} else if (is_x32_frame(ksig)) {
- return x32_setup_rt_frame(ksig, cset, regs);
+ return x32_setup_rt_frame(ksig, regs);
} else {
- return __setup_rt_frame(ksig->sig, ksig, set, regs);
+ return x64_setup_rt_frame(ksig, regs);
}
}
@@ -969,36 +406,3 @@ bool sigaltstack_size_valid(size_t ss_size)
return true;
}
#endif /* CONFIG_DYNAMIC_SIGFRAME */
-
-#ifdef CONFIG_X86_X32_ABI
-COMPAT_SYSCALL_DEFINE0(x32_rt_sigreturn)
-{
- struct pt_regs *regs = current_pt_regs();
- struct rt_sigframe_x32 __user *frame;
- sigset_t set;
- unsigned long uc_flags;
-
- frame = (struct rt_sigframe_x32 __user *)(regs->sp - 8);
-
- if (!access_ok(frame, sizeof(*frame)))
- goto badframe;
- if (__get_user(set.sig[0], (__u64 __user *)&frame->uc.uc_sigmask))
- goto badframe;
- if (__get_user(uc_flags, &frame->uc.uc_flags))
- goto badframe;
-
- set_current_blocked(&set);
-
- if (!restore_sigcontext(regs, &frame->uc.uc_mcontext, uc_flags))
- goto badframe;
-
- if (compat_restore_altstack(&frame->uc.uc_stack))
- goto badframe;
-
- return regs->ax;
-
-badframe:
- signal_fault(regs, frame, "x32 rt_sigreturn");
- return 0;
-}
-#endif
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/kernel/signal_32.c
index c9c3859322fa..2553136cf39b 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/kernel/signal_32.c
@@ -1,7 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * linux/arch/x86_64/ia32/ia32_signal.c
- *
* Copyright (C) 1991, 1992 Linus Torvalds
*
* 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
@@ -26,7 +24,6 @@
#include <linux/uaccess.h>
#include <asm/fpu/signal.h>
#include <asm/ptrace.h>
-#include <asm/ia32_unistd.h>
#include <asm/user32.h>
#include <uapi/asm/sigcontext.h>
#include <asm/proto.h>
@@ -35,6 +32,9 @@
#include <asm/sighandling.h>
#include <asm/smap.h>
+#ifdef CONFIG_IA32_EMULATION
+#include <asm/ia32_unistd.h>
+
static inline void reload_segments(struct sigcontext_32 *sc)
{
unsigned int cur;
@@ -53,6 +53,21 @@ static inline void reload_segments(struct sigcontext_32 *sc)
loadsegment(es, sc->es | 0x03);
}
+#define sigset32_t compat_sigset_t
+#define restore_altstack32 compat_restore_altstack
+#define unsafe_save_altstack32 unsafe_compat_save_altstack
+
+#else
+
+#define sigset32_t sigset_t
+#define __NR_ia32_sigreturn __NR_sigreturn
+#define __NR_ia32_rt_sigreturn __NR_rt_sigreturn
+#define restore_altstack32 restore_altstack
+#define unsafe_save_altstack32 unsafe_save_altstack
+#define __copy_siginfo_to_user32 copy_siginfo_to_user
+
+#endif
+
/*
* Do a signal return; undo the signal stack.
*/
@@ -86,6 +101,7 @@ static bool ia32_restore_sigcontext(struct pt_regs *regs,
/* disable syscall checks */
regs->orig_ax = -1;
+#ifdef CONFIG_IA32_EMULATION
/*
* Reload fs and gs if they have changed in the signal
* handler. This does not handle long fs/gs base changes in
@@ -93,10 +109,17 @@ static bool ia32_restore_sigcontext(struct pt_regs *regs,
* normal case.
*/
reload_segments(&sc);
+#else
+ loadsegment(gs, sc.gs);
+ regs->fs = sc.fs;
+ regs->es = sc.es;
+ regs->ds = sc.ds;
+#endif
+
return fpu__restore_sig(compat_ptr(sc.fpstate), 1);
}
-COMPAT_SYSCALL_DEFINE0(sigreturn)
+SYSCALL32_DEFINE0(sigreturn)
{
struct pt_regs *regs = current_pt_regs();
struct sigframe_ia32 __user *frame = (struct sigframe_ia32 __user *)(regs->sp-8);
@@ -119,7 +142,7 @@ badframe:
return 0;
}
-COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
+SYSCALL32_DEFINE0(rt_sigreturn)
{
struct pt_regs *regs = current_pt_regs();
struct rt_sigframe_ia32 __user *frame;
@@ -129,7 +152,7 @@ COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
if (!access_ok(frame, sizeof(*frame)))
goto badframe;
- if (__get_user(set.sig[0], (__u64 __user *)&frame->uc.uc_sigmask))
+ if (__get_user(*(__u64 *)&set, (__u64 __user *)&frame->uc.uc_sigmask))
goto badframe;
set_current_blocked(&set);
@@ -137,7 +160,7 @@ COMPAT_SYSCALL_DEFINE0(rt_sigreturn)
if (!ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext))
goto badframe;
- if (compat_restore_altstack(&frame->uc.uc_stack))
+ if (restore_altstack32(&frame->uc.uc_stack))
goto badframe;
return regs->ax;
@@ -159,9 +182,15 @@ __unsafe_setup_sigcontext32(struct sigcontext_32 __user *sc,
struct pt_regs *regs, unsigned int mask)
{
unsafe_put_user(get_user_seg(gs), (unsigned int __user *)&sc->gs, Efault);
+#ifdef CONFIG_IA32_EMULATION
unsafe_put_user(get_user_seg(fs), (unsigned int __user *)&sc->fs, Efault);
unsafe_put_user(get_user_seg(ds), (unsigned int __user *)&sc->ds, Efault);
unsafe_put_user(get_user_seg(es), (unsigned int __user *)&sc->es, Efault);
+#else
+ unsafe_put_user(regs->fs, (unsigned int __user *)&sc->fs, Efault);
+ unsafe_put_user(regs->es, (unsigned int __user *)&sc->es, Efault);
+ unsafe_put_user(regs->ds, (unsigned int __user *)&sc->ds, Efault);
+#endif
unsafe_put_user(regs->di, &sc->di, Efault);
unsafe_put_user(regs->si, &sc->si, Efault);
@@ -196,43 +225,9 @@ do { \
goto label; \
} while(0)
-/*
- * Determine which stack to use..
- */
-static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
- size_t frame_size,
- void __user **fpstate)
-{
- unsigned long sp, fx_aligned, math_size;
-
- /* Default to using normal stack */
- sp = regs->sp;
-
- /* This is the X/Open sanctioned signal stack switching. */
- if (ksig->ka.sa.sa_flags & SA_ONSTACK)
- sp = sigsp(sp, ksig);
- /* This is the legacy signal stack switching. */
- else if (regs->ss != __USER32_DS &&
- !(ksig->ka.sa.sa_flags & SA_RESTORER) &&
- ksig->ka.sa.sa_restorer)
- sp = (unsigned long) ksig->ka.sa.sa_restorer;
-
- sp = fpu__alloc_mathframe(sp, 1, &fx_aligned, &math_size);
- *fpstate = (struct _fpstate_32 __user *) sp;
- if (!copy_fpstate_to_sigframe(*fpstate, (void __user *)fx_aligned,
- math_size))
- return (void __user *) -1L;
-
- sp -= frame_size;
- /* Align the stack pointer according to the i386 ABI,
- * i.e. so that on function entry ((sp + 4) & 15) == 0. */
- sp = ((sp + 4) & -16ul) - 4;
- return (void __user *) sp;
-}
-
-int ia32_setup_frame(int sig, struct ksignal *ksig,
- compat_sigset_t *set, struct pt_regs *regs)
+int ia32_setup_frame(struct ksignal *ksig, struct pt_regs *regs)
{
+ sigset32_t *set = (sigset32_t *) sigmask_to_save();
struct sigframe_ia32 __user *frame;
void __user *restorer;
void __user *fp = NULL;
@@ -264,7 +259,7 @@ int ia32_setup_frame(int sig, struct ksignal *ksig,
if (!user_access_begin(frame, sizeof(*frame)))
return -EFAULT;
- unsafe_put_user(sig, &frame->sig, Efault);
+ unsafe_put_user(ksig->sig, &frame->sig, Efault);
unsafe_put_sigcontext32(&frame->sc, fp, regs, set, Efault);
unsafe_put_user(set->sig[1], &frame->extramask[0], Efault);
unsafe_put_user(ptr_to_compat(restorer), &frame->pretcode, Efault);
@@ -280,15 +275,20 @@ int ia32_setup_frame(int sig, struct ksignal *ksig,
regs->ip = (unsigned long) ksig->ka.sa.sa_handler;
/* Make -mregparm=3 work */
- regs->ax = sig;
+ regs->ax = ksig->sig;
regs->dx = 0;
regs->cx = 0;
- loadsegment(ds, __USER32_DS);
- loadsegment(es, __USER32_DS);
+#ifdef CONFIG_IA32_EMULATION
+ loadsegment(ds, __USER_DS);
+ loadsegment(es, __USER_DS);
+#else
+ regs->ds = __USER_DS;
+ regs->es = __USER_DS;
+#endif
regs->cs = __USER32_CS;
- regs->ss = __USER32_DS;
+ regs->ss = __USER_DS;
return 0;
Efault:
@@ -296,9 +296,9 @@ Efault:
return -EFAULT;
}
-int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
- compat_sigset_t *set, struct pt_regs *regs)
+int ia32_setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
{
+ sigset32_t *set = (sigset32_t *) sigmask_to_save();
struct rt_sigframe_ia32 __user *frame;
void __user *restorer;
void __user *fp = NULL;
@@ -321,7 +321,7 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
if (!user_access_begin(frame, sizeof(*frame)))
return -EFAULT;
- unsafe_put_user(sig, &frame->sig, Efault);
+ unsafe_put_user(ksig->sig, &frame->sig, Efault);
unsafe_put_user(ptr_to_compat(&frame->info), &frame->pinfo, Efault);
unsafe_put_user(ptr_to_compat(&frame->uc), &frame->puc, Efault);
@@ -331,7 +331,7 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
else
unsafe_put_user(0, &frame->uc.uc_flags, Efault);
unsafe_put_user(0, &frame->uc.uc_link, Efault);
- unsafe_compat_save_altstack(&frame->uc.uc_stack, regs->sp, Efault);
+ unsafe_save_altstack32(&frame->uc.uc_stack, regs->sp, Efault);
if (ksig->ka.sa.sa_flags & SA_RESTORER)
restorer = ksig->ka.sa.sa_restorer;
@@ -357,15 +357,20 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
regs->ip = (unsigned long) ksig->ka.sa.sa_handler;
/* Make -mregparm=3 work */
- regs->ax = sig;
+ regs->ax = ksig->sig;
regs->dx = (unsigned long) &frame->info;
regs->cx = (unsigned long) &frame->uc;
- loadsegment(ds, __USER32_DS);
- loadsegment(es, __USER32_DS);
+#ifdef CONFIG_IA32_EMULATION
+ loadsegment(ds, __USER_DS);
+ loadsegment(es, __USER_DS);
+#else
+ regs->ds = __USER_DS;
+ regs->es = __USER_DS;
+#endif
regs->cs = __USER32_CS;
- regs->ss = __USER32_DS;
+ regs->ss = __USER_DS;
return 0;
Efault:
diff --git a/arch/x86/kernel/signal_64.c b/arch/x86/kernel/signal_64.c
new file mode 100644
index 000000000000..ff9c55064223
--- /dev/null
+++ b/arch/x86/kernel/signal_64.c
@@ -0,0 +1,383 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 2000, 2001, 2002 Andi Kleen SuSE Labs
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/unistd.h>
+#include <linux/uaccess.h>
+#include <linux/syscalls.h>
+
+#include <asm/ucontext.h>
+#include <asm/fpu/signal.h>
+#include <asm/sighandling.h>
+
+#include <asm/syscall.h>
+#include <asm/sigframe.h>
+#include <asm/signal.h>
+
+/*
+ * If regs->ss will cause an IRET fault, change it. Otherwise leave it
+ * alone. Using this generally makes no sense unless
+ * user_64bit_mode(regs) would return true.
+ */
+static void force_valid_ss(struct pt_regs *regs)
+{
+ u32 ar;
+ asm volatile ("lar %[old_ss], %[ar]\n\t"
+ "jz 1f\n\t" /* If invalid: */
+ "xorl %[ar], %[ar]\n\t" /* set ar = 0 */
+ "1:"
+ : [ar] "=r" (ar)
+ : [old_ss] "rm" ((u16)regs->ss));
+
+ /*
+ * For a valid 64-bit user context, we need DPL 3, type
+ * read-write data or read-write exp-down data, and S and P
+ * set. We can't use VERW because VERW doesn't check the
+ * P bit.
+ */
+ ar &= AR_DPL_MASK | AR_S | AR_P | AR_TYPE_MASK;
+ if (ar != (AR_DPL3 | AR_S | AR_P | AR_TYPE_RWDATA) &&
+ ar != (AR_DPL3 | AR_S | AR_P | AR_TYPE_RWDATA_EXPDOWN))
+ regs->ss = __USER_DS;
+}
+
+static bool restore_sigcontext(struct pt_regs *regs,
+ struct sigcontext __user *usc,
+ unsigned long uc_flags)
+{
+ struct sigcontext sc;
+
+ /* Always make any pending restarted system calls return -EINTR */
+ current->restart_block.fn = do_no_restart_syscall;
+
+ if (copy_from_user(&sc, usc, offsetof(struct sigcontext, reserved1)))
+ return false;
+
+ regs->bx = sc.bx;
+ regs->cx = sc.cx;
+ regs->dx = sc.dx;
+ regs->si = sc.si;
+ regs->di = sc.di;
+ regs->bp = sc.bp;
+ regs->ax = sc.ax;
+ regs->sp = sc.sp;
+ regs->ip = sc.ip;
+ regs->r8 = sc.r8;
+ regs->r9 = sc.r9;
+ regs->r10 = sc.r10;
+ regs->r11 = sc.r11;
+ regs->r12 = sc.r12;
+ regs->r13 = sc.r13;
+ regs->r14 = sc.r14;
+ regs->r15 = sc.r15;
+
+ /* Get CS/SS and force CPL3 */
+ regs->cs = sc.cs | 0x03;
+ regs->ss = sc.ss | 0x03;
+
+ regs->flags = (regs->flags & ~FIX_EFLAGS) | (sc.flags & FIX_EFLAGS);
+ /* disable syscall checks */
+ regs->orig_ax = -1;
+
+ /*
+ * Fix up SS if needed for the benefit of old DOSEMU and
+ * CRIU.
+ */
+ if (unlikely(!(uc_flags & UC_STRICT_RESTORE_SS) && user_64bit_mode(regs)))
+ force_valid_ss(regs);
+
+ return fpu__restore_sig((void __user *)sc.fpstate, 0);
+}
+
+static __always_inline int
+__unsafe_setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
+ struct pt_regs *regs, unsigned long mask)
+{
+ unsafe_put_user(regs->di, &sc->di, Efault);
+ unsafe_put_user(regs->si, &sc->si, Efault);
+ unsafe_put_user(regs->bp, &sc->bp, Efault);
+ unsafe_put_user(regs->sp, &sc->sp, Efault);
+ unsafe_put_user(regs->bx, &sc->bx, Efault);
+ unsafe_put_user(regs->dx, &sc->dx, Efault);
+ unsafe_put_user(regs->cx, &sc->cx, Efault);
+ unsafe_put_user(regs->ax, &sc->ax, Efault);
+ unsafe_put_user(regs->r8, &sc->r8, Efault);
+ unsafe_put_user(regs->r9, &sc->r9, Efault);
+ unsafe_put_user(regs->r10, &sc->r10, Efault);
+ unsafe_put_user(regs->r11, &sc->r11, Efault);
+ unsafe_put_user(regs->r12, &sc->r12, Efault);
+ unsafe_put_user(regs->r13, &sc->r13, Efault);
+ unsafe_put_user(regs->r14, &sc->r14, Efault);
+ unsafe_put_user(regs->r15, &sc->r15, Efault);
+
+ unsafe_put_user(current->thread.trap_nr, &sc->trapno, Efault);
+ unsafe_put_user(current->thread.error_code, &sc->err, Efault);
+ unsafe_put_user(regs->ip, &sc->ip, Efault);
+ unsafe_put_user(regs->flags, &sc->flags, Efault);
+ unsafe_put_user(regs->cs, &sc->cs, Efault);
+ unsafe_put_user(0, &sc->gs, Efault);
+ unsafe_put_user(0, &sc->fs, Efault);
+ unsafe_put_user(regs->ss, &sc->ss, Efault);
+
+ unsafe_put_user(fpstate, (unsigned long __user *)&sc->fpstate, Efault);
+
+ /* non-iBCS2 extensions.. */
+ unsafe_put_user(mask, &sc->oldmask, Efault);
+ unsafe_put_user(current->thread.cr2, &sc->cr2, Efault);
+ return 0;
+Efault:
+ return -EFAULT;
+}
+
+#define unsafe_put_sigcontext(sc, fp, regs, set, label) \
+do { \
+ if (__unsafe_setup_sigcontext(sc, fp, regs, set->sig[0])) \
+ goto label; \
+} while(0);
+
+#define unsafe_put_sigmask(set, frame, label) \
+ unsafe_put_user(*(__u64 *)(set), \
+ (__u64 __user *)&(frame)->uc.uc_sigmask, \
+ label)
+
+static unsigned long frame_uc_flags(struct pt_regs *regs)
+{
+ unsigned long flags;
+
+ if (boot_cpu_has(X86_FEATURE_XSAVE))
+ flags = UC_FP_XSTATE | UC_SIGCONTEXT_SS;
+ else
+ flags = UC_SIGCONTEXT_SS;
+
+ if (likely(user_64bit_mode(regs)))
+ flags |= UC_STRICT_RESTORE_SS;
+
+ return flags;
+}
+
+int x64_setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
+{
+ sigset_t *set = sigmask_to_save();
+ struct rt_sigframe __user *frame;
+ void __user *fp = NULL;
+ unsigned long uc_flags;
+
+ /* x86-64 should always use SA_RESTORER. */
+ if (!(ksig->ka.sa.sa_flags & SA_RESTORER))
+ return -EFAULT;
+
+ frame = get_sigframe(ksig, regs, sizeof(struct rt_sigframe), &fp);
+ uc_flags = frame_uc_flags(regs);
+
+ if (!user_access_begin(frame, sizeof(*frame)))
+ return -EFAULT;
+
+ /* Create the ucontext. */
+ unsafe_put_user(uc_flags, &frame->uc.uc_flags, Efault);
+ unsafe_put_user(0, &frame->uc.uc_link, Efault);
+ unsafe_save_altstack(&frame->uc.uc_stack, regs->sp, Efault);
+
+ /* Set up to return from userspace. If provided, use a stub
+ already in userspace. */
+ unsafe_put_user(ksig->ka.sa.sa_restorer, &frame->pretcode, Efault);
+ unsafe_put_sigcontext(&frame->uc.uc_mcontext, fp, regs, set, Efault);
+ unsafe_put_sigmask(set, frame, Efault);
+ user_access_end();
+
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
+ if (copy_siginfo_to_user(&frame->info, &ksig->info))
+ return -EFAULT;
+ }
+
+ /* Set up registers for signal handler */
+ regs->di = ksig->sig;
+ /* In case the signal handler was declared without prototypes */
+ regs->ax = 0;
+
+ /* This also works for non SA_SIGINFO handlers because they expect the
+ next argument after the signal number on the stack. */
+ regs->si = (unsigned long)&frame->info;
+ regs->dx = (unsigned long)&frame->uc;
+ regs->ip = (unsigned long) ksig->ka.sa.sa_handler;
+
+ regs->sp = (unsigned long)frame;
+
+ /*
+ * Set up the CS and SS registers to run signal handlers in
+ * 64-bit mode, even if the handler happens to be interrupting
+ * 32-bit or 16-bit code.
+ *
+ * SS is subtle. In 64-bit mode, we don't need any particular
+ * SS descriptor, but we do need SS to be valid. It's possible
+ * that the old SS is entirely bogus -- this can happen if the
+ * signal we're trying to deliver is #GP or #SS caused by a bad
+ * SS value. We also have a compatibility issue here: DOSEMU
+ * relies on the contents of the SS register indicating the
+ * SS value at the time of the signal, even though that code in
+ * DOSEMU predates sigreturn's ability to restore SS. (DOSEMU
+ * avoids relying on sigreturn to restore SS; instead it uses
+ * a trampoline.) So we do our best: if the old SS was valid,
+ * we keep it. Otherwise we replace it.
+ */
+ regs->cs = __USER_CS;
+
+ if (unlikely(regs->ss != __USER_DS))
+ force_valid_ss(regs);
+
+ return 0;
+
+Efault:
+ user_access_end();
+ return -EFAULT;
+}
+
+/*
+ * Do a signal return; undo the signal stack.
+ */
+SYSCALL_DEFINE0(rt_sigreturn)
+{
+ struct pt_regs *regs = current_pt_regs();
+ struct rt_sigframe __user *frame;
+ sigset_t set;
+ unsigned long uc_flags;
+
+ frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long));
+ if (!access_ok(frame, sizeof(*frame)))
+ goto badframe;
+ if (__get_user(*(__u64 *)&set, (__u64 __user *)&frame->uc.uc_sigmask))
+ goto badframe;
+ if (__get_user(uc_flags, &frame->uc.uc_flags))
+ goto badframe;
+
+ set_current_blocked(&set);
+
+ if (!restore_sigcontext(regs, &frame->uc.uc_mcontext, uc_flags))
+ goto badframe;
+
+ if (restore_altstack(&frame->uc.uc_stack))
+ goto badframe;
+
+ return regs->ax;
+
+badframe:
+ signal_fault(regs, frame, "rt_sigreturn");
+ return 0;
+}
+
+#ifdef CONFIG_X86_X32_ABI
+static int x32_copy_siginfo_to_user(struct compat_siginfo __user *to,
+ const struct kernel_siginfo *from)
+{
+ struct compat_siginfo new;
+
+ copy_siginfo_to_external32(&new, from);
+ if (from->si_signo == SIGCHLD) {
+ new._sifields._sigchld_x32._utime = from->si_utime;
+ new._sifields._sigchld_x32._stime = from->si_stime;
+ }
+ if (copy_to_user(to, &new, sizeof(struct compat_siginfo)))
+ return -EFAULT;
+ return 0;
+}
+
+int copy_siginfo_to_user32(struct compat_siginfo __user *to,
+ const struct kernel_siginfo *from)
+{
+ if (in_x32_syscall())
+ return x32_copy_siginfo_to_user(to, from);
+ return __copy_siginfo_to_user32(to, from);
+}
+
+int x32_setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
+{
+ compat_sigset_t *set = (compat_sigset_t *) sigmask_to_save();
+ struct rt_sigframe_x32 __user *frame;
+ unsigned long uc_flags;
+ void __user *restorer;
+ void __user *fp = NULL;
+
+ if (!(ksig->ka.sa.sa_flags & SA_RESTORER))
+ return -EFAULT;
+
+ frame = get_sigframe(ksig, regs, sizeof(*frame), &fp);
+
+ uc_flags = frame_uc_flags(regs);
+
+ if (!user_access_begin(frame, sizeof(*frame)))
+ return -EFAULT;
+
+ /* Create the ucontext. */
+ unsafe_put_user(uc_flags, &frame->uc.uc_flags, Efault);
+ unsafe_put_user(0, &frame->uc.uc_link, Efault);
+ unsafe_compat_save_altstack(&frame->uc.uc_stack, regs->sp, Efault);
+ unsafe_put_user(0, &frame->uc.uc__pad0, Efault);
+ restorer = ksig->ka.sa.sa_restorer;
+ unsafe_put_user(restorer, (unsigned long __user *)&frame->pretcode, Efault);
+ unsafe_put_sigcontext(&frame->uc.uc_mcontext, fp, regs, set, Efault);
+ unsafe_put_sigmask(set, frame, Efault);
+ user_access_end();
+
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
+ if (x32_copy_siginfo_to_user(&frame->info, &ksig->info))
+ return -EFAULT;
+ }
+
+ /* Set up registers for signal handler */
+ regs->sp = (unsigned long) frame;
+ regs->ip = (unsigned long) ksig->ka.sa.sa_handler;
+
+ /* We use the x32 calling convention here... */
+ regs->di = ksig->sig;
+ regs->si = (unsigned long) &frame->info;
+ regs->dx = (unsigned long) &frame->uc;
+
+ loadsegment(ds, __USER_DS);
+ loadsegment(es, __USER_DS);
+
+ regs->cs = __USER_CS;
+ regs->ss = __USER_DS;
+
+ return 0;
+
+Efault:
+ user_access_end();
+ return -EFAULT;
+}
+
+COMPAT_SYSCALL_DEFINE0(x32_rt_sigreturn)
+{
+ struct pt_regs *regs = current_pt_regs();
+ struct rt_sigframe_x32 __user *frame;
+ sigset_t set;
+ unsigned long uc_flags;
+
+ frame = (struct rt_sigframe_x32 __user *)(regs->sp - 8);
+
+ if (!access_ok(frame, sizeof(*frame)))
+ goto badframe;
+ if (__get_user(set.sig[0], (__u64 __user *)&frame->uc.uc_sigmask))
+ goto badframe;
+ if (__get_user(uc_flags, &frame->uc.uc_flags))
+ goto badframe;
+
+ set_current_blocked(&set);
+
+ if (!restore_sigcontext(regs, &frame->uc.uc_mcontext, uc_flags))
+ goto badframe;
+
+ if (compat_restore_altstack(&frame->uc.uc_stack))
+ goto badframe;
+
+ return regs->ax;
+
+badframe:
+ signal_fault(regs, frame, "x32 rt_sigreturn");
+ return 0;
+}
+#endif /* CONFIG_X86_X32_ABI */
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 3f3ea0287f69..c295f0e008a3 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -56,8 +56,10 @@
#include <linux/numa.h>
#include <linux/pgtable.h>
#include <linux/overflow.h>
+#include <linux/stackprotector.h>
#include <asm/acpi.h>
+#include <asm/cacheinfo.h>
#include <asm/desc.h>
#include <asm/nmi.h>
#include <asm/irq.h>
@@ -1428,8 +1430,6 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
uv_system_init();
- set_mtrr_aps_delayed_init();
-
smp_quirk_init_udelay();
speculative_store_bypass_ht_init();
@@ -1439,12 +1439,12 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
void arch_thaw_secondary_cpus_begin(void)
{
- set_mtrr_aps_delayed_init();
+ set_cache_aps_delayed_init(true);
}
void arch_thaw_secondary_cpus_end(void)
{
- mtrr_aps_init();
+ cache_aps_init();
}
/*
@@ -1487,7 +1487,7 @@ void __init native_smp_cpus_done(unsigned int max_cpus)
nmi_selftest();
impress_friends();
- mtrr_aps_init();
+ cache_aps_init();
}
static int __initdata setup_possible_cpus = -1;
diff --git a/arch/x86/kernel/topology.c b/arch/x86/kernel/topology.c
index 8617d1ed9d31..1b83377274b8 100644
--- a/arch/x86/kernel/topology.c
+++ b/arch/x86/kernel/topology.c
@@ -106,7 +106,7 @@ int arch_register_cpu(int num)
* Xen PV guests don't support CPU0 hotplug at all.
*/
if (c->x86_vendor != X86_VENDOR_INTEL ||
- boot_cpu_has(X86_FEATURE_XENPV))
+ cpu_feature_enabled(X86_FEATURE_XENPV))
cpu0_hotpluggable = 0;
/*
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index d3fdec706f1d..d1e1679f32cf 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -68,13 +68,13 @@
#ifdef CONFIG_X86_64
#include <asm/x86_init.h>
-#include <asm/proto.h>
#else
#include <asm/processor-flags.h>
#include <asm/setup.h>
-#include <asm/proto.h>
#endif
+#include <asm/proto.h>
+
DECLARE_BITMAP(system_vectors, NR_VECTORS);
static inline void cond_local_irq_enable(struct pt_regs *regs)
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index cafacb2e58cc..a78e73da4a74 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -51,7 +51,7 @@ int tsc_clocksource_reliable;
static u32 art_to_tsc_numerator;
static u32 art_to_tsc_denominator;
static u64 art_to_tsc_offset;
-struct clocksource *art_related_clocksource;
+static struct clocksource *art_related_clocksource;
struct cyc2ns {
struct cyc2ns_data data[2]; /* 0 + 2*16 = 32 */
diff --git a/arch/x86/kernel/uprobes.c b/arch/x86/kernel/uprobes.c
index b63cf8f7745e..6c07f6daaa22 100644
--- a/arch/x86/kernel/uprobes.c
+++ b/arch/x86/kernel/uprobes.c
@@ -722,8 +722,9 @@ static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn)
switch (opc1) {
case 0xeb: /* jmp 8 */
case 0xe9: /* jmp 32 */
- case 0x90: /* prefix* + nop; same as jmp with .offs = 0 */
break;
+ case 0x90: /* prefix* + nop; same as jmp with .offs = 0 */
+ goto setup;
case 0xe8: /* call relative */
branch_clear_offset(auprobe, insn);
@@ -753,6 +754,7 @@ static int branch_setup_xol_ops(struct arch_uprobe *auprobe, struct insn *insn)
return -ENOTSUPP;
}
+setup:
auprobe->branch.opc1 = opc1;
auprobe->branch.ilen = insn->length;
auprobe->branch.offs = insn->immediate.value;
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index 57353519bc11..ef80d361b463 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -25,6 +25,7 @@
#include <asm/iommu.h>
#include <asm/mach_traps.h>
#include <asm/irqdomain.h>
+#include <asm/realmode.h>
void x86_init_noop(void) { }
void __init x86_init_uint_noop(unsigned int unused) { }
@@ -145,6 +146,8 @@ struct x86_platform_ops x86_platform __ro_after_init = {
.get_nmi_reason = default_get_nmi_reason,
.save_sched_clock_state = tsc_save_sched_clock_state,
.restore_sched_clock_state = tsc_restore_sched_clock_state,
+ .realmode_reserve = reserve_real_mode,
+ .realmode_init = init_real_mode,
.hyper.pin_vcpu = x86_op_int_noop,
.guest = {
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 62bc7a01cecc..c92c49a0b35b 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -665,7 +665,7 @@ void kvm_set_cpu_caps(void)
);
kvm_cpu_cap_init_scattered(CPUID_12_EAX,
- SF(SGX1) | SF(SGX2)
+ SF(SGX1) | SF(SGX2) | SF(SGX_EDECCSSA)
);
kvm_cpu_cap_mask(CPUID_8000_0001_ECX,
@@ -1047,9 +1047,7 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
* userspace. ATTRIBUTES.XFRM is not adjusted as userspace is
* expected to derive it from supported XCR0.
*/
- entry->eax &= SGX_ATTR_DEBUG | SGX_ATTR_MODE64BIT |
- SGX_ATTR_PROVISIONKEY | SGX_ATTR_EINITTOKENKEY |
- SGX_ATTR_KSS;
+ entry->eax &= SGX_ATTR_PRIV_MASK | SGX_ATTR_UNPRIV_MASK;
entry->ebx &= 0;
break;
/* Intel PT */
diff --git a/arch/x86/kvm/reverse_cpuid.h b/arch/x86/kvm/reverse_cpuid.h
index a19d473d0184..4e5b8444f161 100644
--- a/arch/x86/kvm/reverse_cpuid.h
+++ b/arch/x86/kvm/reverse_cpuid.h
@@ -23,6 +23,7 @@ enum kvm_only_cpuid_leafs {
/* Intel-defined SGX sub-features, CPUID level 0x12 (EAX). */
#define KVM_X86_FEATURE_SGX1 KVM_X86_FEATURE(CPUID_12_EAX, 0)
#define KVM_X86_FEATURE_SGX2 KVM_X86_FEATURE(CPUID_12_EAX, 1)
+#define KVM_X86_FEATURE_SGX_EDECCSSA KVM_X86_FEATURE(CPUID_12_EAX, 11)
struct cpuid_reg {
u32 function;
@@ -78,6 +79,8 @@ static __always_inline u32 __feature_translate(int x86_feature)
return KVM_X86_FEATURE_SGX1;
else if (x86_feature == X86_FEATURE_SGX2)
return KVM_X86_FEATURE_SGX2;
+ else if (x86_feature == X86_FEATURE_SGX_EDECCSSA)
+ return KVM_X86_FEATURE_SGX_EDECCSSA;
return x86_feature;
}
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
index 7ba5f61d7273..4f1a40a86534 100644
--- a/arch/x86/lib/Makefile
+++ b/arch/x86/lib/Makefile
@@ -60,6 +60,7 @@ ifeq ($(CONFIG_X86_32),y)
lib-y += checksum_32.o
lib-y += strstr_32.o
lib-y += string_32.o
+ lib-y += memmove_32.o
ifneq ($(CONFIG_X86_CMPXCHG64),y)
lib-y += cmpxchg8b_emu.o atomic64_386_32.o
endif
diff --git a/arch/x86/lib/memcpy_32.c b/arch/x86/lib/memcpy_32.c
index ef3af7ff2c8a..a29b64befb93 100644
--- a/arch/x86/lib/memcpy_32.c
+++ b/arch/x86/lib/memcpy_32.c
@@ -17,190 +17,3 @@ __visible void *memset(void *s, int c, size_t count)
return __memset(s, c, count);
}
EXPORT_SYMBOL(memset);
-
-__visible void *memmove(void *dest, const void *src, size_t n)
-{
- int d0,d1,d2,d3,d4,d5;
- char *ret = dest;
-
- __asm__ __volatile__(
- /* Handle more 16 bytes in loop */
- "cmp $0x10, %0\n\t"
- "jb 1f\n\t"
-
- /* Decide forward/backward copy mode */
- "cmp %2, %1\n\t"
- "jb 2f\n\t"
-
- /*
- * movs instruction have many startup latency
- * so we handle small size by general register.
- */
- "cmp $680, %0\n\t"
- "jb 3f\n\t"
- /*
- * movs instruction is only good for aligned case.
- */
- "mov %1, %3\n\t"
- "xor %2, %3\n\t"
- "and $0xff, %3\n\t"
- "jz 4f\n\t"
- "3:\n\t"
- "sub $0x10, %0\n\t"
-
- /*
- * We gobble 16 bytes forward in each loop.
- */
- "3:\n\t"
- "sub $0x10, %0\n\t"
- "mov 0*4(%1), %3\n\t"
- "mov 1*4(%1), %4\n\t"
- "mov %3, 0*4(%2)\n\t"
- "mov %4, 1*4(%2)\n\t"
- "mov 2*4(%1), %3\n\t"
- "mov 3*4(%1), %4\n\t"
- "mov %3, 2*4(%2)\n\t"
- "mov %4, 3*4(%2)\n\t"
- "lea 0x10(%1), %1\n\t"
- "lea 0x10(%2), %2\n\t"
- "jae 3b\n\t"
- "add $0x10, %0\n\t"
- "jmp 1f\n\t"
-
- /*
- * Handle data forward by movs.
- */
- ".p2align 4\n\t"
- "4:\n\t"
- "mov -4(%1, %0), %3\n\t"
- "lea -4(%2, %0), %4\n\t"
- "shr $2, %0\n\t"
- "rep movsl\n\t"
- "mov %3, (%4)\n\t"
- "jmp 11f\n\t"
- /*
- * Handle data backward by movs.
- */
- ".p2align 4\n\t"
- "6:\n\t"
- "mov (%1), %3\n\t"
- "mov %2, %4\n\t"
- "lea -4(%1, %0), %1\n\t"
- "lea -4(%2, %0), %2\n\t"
- "shr $2, %0\n\t"
- "std\n\t"
- "rep movsl\n\t"
- "mov %3,(%4)\n\t"
- "cld\n\t"
- "jmp 11f\n\t"
-
- /*
- * Start to prepare for backward copy.
- */
- ".p2align 4\n\t"
- "2:\n\t"
- "cmp $680, %0\n\t"
- "jb 5f\n\t"
- "mov %1, %3\n\t"
- "xor %2, %3\n\t"
- "and $0xff, %3\n\t"
- "jz 6b\n\t"
-
- /*
- * Calculate copy position to tail.
- */
- "5:\n\t"
- "add %0, %1\n\t"
- "add %0, %2\n\t"
- "sub $0x10, %0\n\t"
-
- /*
- * We gobble 16 bytes backward in each loop.
- */
- "7:\n\t"
- "sub $0x10, %0\n\t"
-
- "mov -1*4(%1), %3\n\t"
- "mov -2*4(%1), %4\n\t"
- "mov %3, -1*4(%2)\n\t"
- "mov %4, -2*4(%2)\n\t"
- "mov -3*4(%1), %3\n\t"
- "mov -4*4(%1), %4\n\t"
- "mov %3, -3*4(%2)\n\t"
- "mov %4, -4*4(%2)\n\t"
- "lea -0x10(%1), %1\n\t"
- "lea -0x10(%2), %2\n\t"
- "jae 7b\n\t"
- /*
- * Calculate copy position to head.
- */
- "add $0x10, %0\n\t"
- "sub %0, %1\n\t"
- "sub %0, %2\n\t"
-
- /*
- * Move data from 8 bytes to 15 bytes.
- */
- ".p2align 4\n\t"
- "1:\n\t"
- "cmp $8, %0\n\t"
- "jb 8f\n\t"
- "mov 0*4(%1), %3\n\t"
- "mov 1*4(%1), %4\n\t"
- "mov -2*4(%1, %0), %5\n\t"
- "mov -1*4(%1, %0), %1\n\t"
-
- "mov %3, 0*4(%2)\n\t"
- "mov %4, 1*4(%2)\n\t"
- "mov %5, -2*4(%2, %0)\n\t"
- "mov %1, -1*4(%2, %0)\n\t"
- "jmp 11f\n\t"
-
- /*
- * Move data from 4 bytes to 7 bytes.
- */
- ".p2align 4\n\t"
- "8:\n\t"
- "cmp $4, %0\n\t"
- "jb 9f\n\t"
- "mov 0*4(%1), %3\n\t"
- "mov -1*4(%1, %0), %4\n\t"
- "mov %3, 0*4(%2)\n\t"
- "mov %4, -1*4(%2, %0)\n\t"
- "jmp 11f\n\t"
-
- /*
- * Move data from 2 bytes to 3 bytes.
- */
- ".p2align 4\n\t"
- "9:\n\t"
- "cmp $2, %0\n\t"
- "jb 10f\n\t"
- "movw 0*2(%1), %%dx\n\t"
- "movw -1*2(%1, %0), %%bx\n\t"
- "movw %%dx, 0*2(%2)\n\t"
- "movw %%bx, -1*2(%2, %0)\n\t"
- "jmp 11f\n\t"
-
- /*
- * Move data for 1 byte.
- */
- ".p2align 4\n\t"
- "10:\n\t"
- "cmp $1, %0\n\t"
- "jb 11f\n\t"
- "movb (%1), %%cl\n\t"
- "movb %%cl, (%2)\n\t"
- ".p2align 4\n\t"
- "11:"
- : "=&c" (d0), "=&S" (d1), "=&D" (d2),
- "=r" (d3),"=r" (d4), "=r"(d5)
- :"0" (n),
- "1" (src),
- "2" (dest)
- :"memory");
-
- return ret;
-
-}
-EXPORT_SYMBOL(memmove);
diff --git a/arch/x86/lib/memmove_32.S b/arch/x86/lib/memmove_32.S
new file mode 100644
index 000000000000..0588b2c0fc95
--- /dev/null
+++ b/arch/x86/lib/memmove_32.S
@@ -0,0 +1,200 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <linux/linkage.h>
+#include <asm/export.h>
+
+SYM_FUNC_START(memmove)
+/*
+ * void *memmove(void *dest_in, const void *src_in, size_t n)
+ * -mregparm=3 passes these in registers:
+ * dest_in: %eax
+ * src_in: %edx
+ * n: %ecx
+ * See also: arch/x86/entry/calling.h for description of the calling convention.
+ *
+ * n can remain in %ecx, but for `rep movsl`, we'll need dest in %edi and src
+ * in %esi.
+ */
+.set dest_in, %eax
+.set dest, %edi
+.set src_in, %edx
+.set src, %esi
+.set n, %ecx
+.set tmp0, %edx
+.set tmp0w, %dx
+.set tmp1, %ebx
+.set tmp1w, %bx
+.set tmp2, %eax
+.set tmp3b, %cl
+
+/*
+ * Save all callee-saved registers, because this function is going to clobber
+ * all of them:
+ */
+ pushl %ebp
+ movl %esp, %ebp // set standard frame pointer
+
+ pushl %ebx
+ pushl %edi
+ pushl %esi
+ pushl %eax // save 'dest_in' parameter [eax] as the return value
+
+ movl src_in, src
+ movl dest_in, dest
+
+ /* Handle more 16 bytes in loop */
+ cmpl $0x10, n
+ jb .Lmove_16B
+
+ /* Decide forward/backward copy mode */
+ cmpl dest, src
+ jb .Lbackwards_header
+
+ /*
+ * movs instruction have many startup latency
+ * so we handle small size by general register.
+ */
+ cmpl $680, n
+ jb .Ltoo_small_forwards
+ /* movs instruction is only good for aligned case. */
+ movl src, tmp0
+ xorl dest, tmp0
+ andl $0xff, tmp0
+ jz .Lforward_movs
+.Ltoo_small_forwards:
+ subl $0x10, n
+
+ /* We gobble 16 bytes forward in each loop. */
+.Lmove_16B_forwards_loop:
+ subl $0x10, n
+ movl 0*4(src), tmp0
+ movl 1*4(src), tmp1
+ movl tmp0, 0*4(dest)
+ movl tmp1, 1*4(dest)
+ movl 2*4(src), tmp0
+ movl 3*4(src), tmp1
+ movl tmp0, 2*4(dest)
+ movl tmp1, 3*4(dest)
+ leal 0x10(src), src
+ leal 0x10(dest), dest
+ jae .Lmove_16B_forwards_loop
+ addl $0x10, n
+ jmp .Lmove_16B
+
+ /* Handle data forward by movs. */
+.p2align 4
+.Lforward_movs:
+ movl -4(src, n), tmp0
+ leal -4(dest, n), tmp1
+ shrl $2, n
+ rep movsl
+ movl tmp0, (tmp1)
+ jmp .Ldone
+
+ /* Handle data backward by movs. */
+.p2align 4
+.Lbackwards_movs:
+ movl (src), tmp0
+ movl dest, tmp1
+ leal -4(src, n), src
+ leal -4(dest, n), dest
+ shrl $2, n
+ std
+ rep movsl
+ movl tmp0,(tmp1)
+ cld
+ jmp .Ldone
+
+ /* Start to prepare for backward copy. */
+.p2align 4
+.Lbackwards_header:
+ cmpl $680, n
+ jb .Ltoo_small_backwards
+ movl src, tmp0
+ xorl dest, tmp0
+ andl $0xff, tmp0
+ jz .Lbackwards_movs
+
+ /* Calculate copy position to tail. */
+.Ltoo_small_backwards:
+ addl n, src
+ addl n, dest
+ subl $0x10, n
+
+ /* We gobble 16 bytes backward in each loop. */
+.Lmove_16B_backwards_loop:
+ subl $0x10, n
+
+ movl -1*4(src), tmp0
+ movl -2*4(src), tmp1
+ movl tmp0, -1*4(dest)
+ movl tmp1, -2*4(dest)
+ movl -3*4(src), tmp0
+ movl -4*4(src), tmp1
+ movl tmp0, -3*4(dest)
+ movl tmp1, -4*4(dest)
+ leal -0x10(src), src
+ leal -0x10(dest), dest
+ jae .Lmove_16B_backwards_loop
+ /* Calculate copy position to head. */
+ addl $0x10, n
+ subl n, src
+ subl n, dest
+
+ /* Move data from 8 bytes to 15 bytes. */
+.p2align 4
+.Lmove_16B:
+ cmpl $8, n
+ jb .Lmove_8B
+ movl 0*4(src), tmp0
+ movl 1*4(src), tmp1
+ movl -2*4(src, n), tmp2
+ movl -1*4(src, n), src
+
+ movl tmp0, 0*4(dest)
+ movl tmp1, 1*4(dest)
+ movl tmp2, -2*4(dest, n)
+ movl src, -1*4(dest, n)
+ jmp .Ldone
+
+ /* Move data from 4 bytes to 7 bytes. */
+.p2align 4
+.Lmove_8B:
+ cmpl $4, n
+ jb .Lmove_4B
+ movl 0*4(src), tmp0
+ movl -1*4(src, n), tmp1
+ movl tmp0, 0*4(dest)
+ movl tmp1, -1*4(dest, n)
+ jmp .Ldone
+
+ /* Move data from 2 bytes to 3 bytes. */
+.p2align 4
+.Lmove_4B:
+ cmpl $2, n
+ jb .Lmove_1B
+ movw 0*2(src), tmp0w
+ movw -1*2(src, n), tmp1w
+ movw tmp0w, 0*2(dest)
+ movw tmp1w, -1*2(dest, n)
+ jmp .Ldone
+
+ /* Move data for 1 byte. */
+.p2align 4
+.Lmove_1B:
+ cmpl $1, n
+ jb .Ldone
+ movb (src), tmp3b
+ movb tmp3b, (dest)
+.p2align 4
+.Ldone:
+ popl dest_in // restore 'dest_in' [eax] as the return value
+ /* Restore all callee-saved registers: */
+ popl %esi
+ popl %edi
+ popl %ebx
+ popl %ebp
+
+ RET
+SYM_FUNC_END(memmove)
+EXPORT_SYMBOL(memmove)
diff --git a/arch/x86/mm/cpu_entry_area.c b/arch/x86/mm/cpu_entry_area.c
index 6c2f1b76a0b6..42cd96e7d733 100644
--- a/arch/x86/mm/cpu_entry_area.c
+++ b/arch/x86/mm/cpu_entry_area.c
@@ -138,17 +138,13 @@ static void __init setup_cpu_entry_area(unsigned int cpu)
pgprot_t tss_prot = PAGE_KERNEL_RO;
#else
/*
- * On native 32-bit systems, the GDT cannot be read-only because
+ * On 32-bit systems, the GDT cannot be read-only because
* our double fault handler uses a task gate, and entering through
* a task gate needs to change an available TSS to busy. If the
* GDT is read-only, that will triple fault. The TSS cannot be
* read-only because the CPU writes to it on task switches.
- *
- * On Xen PV, the GDT must be read-only because the hypervisor
- * requires it.
*/
- pgprot_t gdt_prot = boot_cpu_has(X86_FEATURE_XENPV) ?
- PAGE_KERNEL_RO : PAGE_KERNEL;
+ pgprot_t gdt_prot = PAGE_KERNEL;
pgprot_t tss_prot = PAGE_KERNEL;
#endif
diff --git a/arch/x86/mm/pat/cpa-test.c b/arch/x86/mm/pat/cpa-test.c
index 423b21e80929..3d2f7f0a6ed1 100644
--- a/arch/x86/mm/pat/cpa-test.c
+++ b/arch/x86/mm/pat/cpa-test.c
@@ -136,10 +136,10 @@ static int pageattr_test(void)
failed += print_split(&sa);
for (i = 0; i < NTEST; i++) {
- unsigned long pfn = prandom_u32_max(max_pfn_mapped);
+ unsigned long pfn = get_random_u32_below(max_pfn_mapped);
addr[i] = (unsigned long)__va(pfn << PAGE_SHIFT);
- len[i] = prandom_u32_max(NPAGES);
+ len[i] = get_random_u32_below(NPAGES);
len[i] = min_t(unsigned long, len[i], max_pfn_mapped - pfn - 1);
if (len[i] == 0)
diff --git a/arch/x86/mm/pat/memtype.c b/arch/x86/mm/pat/memtype.c
index 66a209f7eb86..46de9cf5c91d 100644
--- a/arch/x86/mm/pat/memtype.c
+++ b/arch/x86/mm/pat/memtype.c
@@ -43,6 +43,7 @@
#include <linux/rbtree.h>
#include <asm/cacheflush.h>
+#include <asm/cacheinfo.h>
#include <asm/processor.h>
#include <asm/tlbflush.h>
#include <asm/x86_init.h>
@@ -60,41 +61,34 @@
#undef pr_fmt
#define pr_fmt(fmt) "" fmt
-static bool __read_mostly pat_bp_initialized;
static bool __read_mostly pat_disabled = !IS_ENABLED(CONFIG_X86_PAT);
-static bool __initdata pat_force_disabled = !IS_ENABLED(CONFIG_X86_PAT);
-static bool __read_mostly pat_bp_enabled;
-static bool __read_mostly pat_cm_initialized;
+static u64 __ro_after_init pat_msr_val;
/*
* PAT support is enabled by default, but can be disabled for
* various user-requested or hardware-forced reasons:
*/
-void pat_disable(const char *msg_reason)
+static void __init pat_disable(const char *msg_reason)
{
if (pat_disabled)
return;
- if (pat_bp_initialized) {
- WARN_ONCE(1, "x86/PAT: PAT cannot be disabled after initialization\n");
- return;
- }
-
pat_disabled = true;
pr_info("x86/PAT: %s\n", msg_reason);
+
+ memory_caching_control &= ~CACHE_PAT;
}
static int __init nopat(char *str)
{
pat_disable("PAT support disabled via boot option.");
- pat_force_disabled = true;
return 0;
}
early_param("nopat", nopat);
bool pat_enabled(void)
{
- return pat_bp_enabled;
+ return !pat_disabled;
}
EXPORT_SYMBOL_GPL(pat_enabled);
@@ -192,7 +186,8 @@ enum {
#define CM(c) (_PAGE_CACHE_MODE_ ## c)
-static enum page_cache_mode pat_get_cache_mode(unsigned pat_val, char *msg)
+static enum page_cache_mode __init pat_get_cache_mode(unsigned int pat_val,
+ char *msg)
{
enum page_cache_mode cache;
char *cache_mode;
@@ -219,14 +214,12 @@ static enum page_cache_mode pat_get_cache_mode(unsigned pat_val, char *msg)
* configuration.
* Using lower indices is preferred, so we start with highest index.
*/
-static void __init_cache_modes(u64 pat)
+static void __init init_cache_modes(u64 pat)
{
enum page_cache_mode cache;
char pat_msg[33];
int i;
- WARN_ON_ONCE(pat_cm_initialized);
-
pat_msg[32] = 0;
for (i = 7; i >= 0; i--) {
cache = pat_get_cache_mode((pat >> (i * 8)) & 7,
@@ -234,34 +227,9 @@ static void __init_cache_modes(u64 pat)
update_cache_mode_entry(i, cache);
}
pr_info("x86/PAT: Configuration [0-7]: %s\n", pat_msg);
-
- pat_cm_initialized = true;
}
-#define PAT(x, y) ((u64)PAT_ ## y << ((x)*8))
-
-static void pat_bp_init(u64 pat)
-{
- u64 tmp_pat;
-
- if (!boot_cpu_has(X86_FEATURE_PAT)) {
- pat_disable("PAT not supported by the CPU.");
- return;
- }
-
- rdmsrl(MSR_IA32_CR_PAT, tmp_pat);
- if (!tmp_pat) {
- pat_disable("PAT support disabled by the firmware.");
- return;
- }
-
- wrmsrl(MSR_IA32_CR_PAT, pat);
- pat_bp_enabled = true;
-
- __init_cache_modes(pat);
-}
-
-static void pat_ap_init(u64 pat)
+void pat_cpu_init(void)
{
if (!boot_cpu_has(X86_FEATURE_PAT)) {
/*
@@ -271,30 +239,39 @@ static void pat_ap_init(u64 pat)
panic("x86/PAT: PAT enabled, but not supported by secondary CPU\n");
}
- wrmsrl(MSR_IA32_CR_PAT, pat);
+ wrmsrl(MSR_IA32_CR_PAT, pat_msr_val);
}
-void __init init_cache_modes(void)
+/**
+ * pat_bp_init - Initialize the PAT MSR value and PAT table
+ *
+ * This function initializes PAT MSR value and PAT table with an OS-defined
+ * value to enable additional cache attributes, WC, WT and WP.
+ *
+ * This function prepares the calls of pat_cpu_init() via cache_cpu_init()
+ * on all CPUs.
+ */
+void __init pat_bp_init(void)
{
- u64 pat = 0;
+ struct cpuinfo_x86 *c = &boot_cpu_data;
+#define PAT(p0, p1, p2, p3, p4, p5, p6, p7) \
+ (((u64)PAT_ ## p0) | ((u64)PAT_ ## p1 << 8) | \
+ ((u64)PAT_ ## p2 << 16) | ((u64)PAT_ ## p3 << 24) | \
+ ((u64)PAT_ ## p4 << 32) | ((u64)PAT_ ## p5 << 40) | \
+ ((u64)PAT_ ## p6 << 48) | ((u64)PAT_ ## p7 << 56))
- if (pat_cm_initialized)
- return;
- if (boot_cpu_has(X86_FEATURE_PAT)) {
- /*
- * CPU supports PAT. Set PAT table to be consistent with
- * PAT MSR. This case supports "nopat" boot option, and
- * virtual machine environments which support PAT without
- * MTRRs. In specific, Xen has unique setup to PAT MSR.
- *
- * If PAT MSR returns 0, it is considered invalid and emulates
- * as No PAT.
- */
- rdmsrl(MSR_IA32_CR_PAT, pat);
- }
+ if (!IS_ENABLED(CONFIG_X86_PAT))
+ pr_info_once("x86/PAT: PAT support disabled because CONFIG_X86_PAT is disabled in the kernel.\n");
+
+ if (!cpu_feature_enabled(X86_FEATURE_PAT))
+ pat_disable("PAT not supported by the CPU.");
+ else
+ rdmsrl(MSR_IA32_CR_PAT, pat_msr_val);
+
+ if (!pat_msr_val) {
+ pat_disable("PAT support disabled by the firmware.");
- if (!pat) {
/*
* No PAT. Emulate the PAT table that corresponds to the two
* cache bits, PWT (Write Through) and PCD (Cache Disable).
@@ -313,40 +290,22 @@ void __init init_cache_modes(void)
* NOTE: When WC or WP is used, it is redirected to UC- per
* the default setup in __cachemode2pte_tbl[].
*/
- pat = PAT(0, WB) | PAT(1, WT) | PAT(2, UC_MINUS) | PAT(3, UC) |
- PAT(4, WB) | PAT(5, WT) | PAT(6, UC_MINUS) | PAT(7, UC);
- } else if (!pat_force_disabled && cpu_feature_enabled(X86_FEATURE_HYPERVISOR)) {
- /*
- * Clearly PAT is enabled underneath. Allow pat_enabled() to
- * reflect this.
- */
- pat_bp_enabled = true;
+ pat_msr_val = PAT(WB, WT, UC_MINUS, UC, WB, WT, UC_MINUS, UC);
}
- __init_cache_modes(pat);
-}
-
-/**
- * pat_init - Initialize the PAT MSR and PAT table on the current CPU
- *
- * This function initializes PAT MSR and PAT table with an OS-defined value
- * to enable additional cache attributes, WC, WT and WP.
- *
- * This function must be called on all CPUs using the specific sequence of
- * operations defined in Intel SDM. mtrr_rendezvous_handler() provides this
- * procedure for PAT.
- */
-void pat_init(void)
-{
- u64 pat;
- struct cpuinfo_x86 *c = &boot_cpu_data;
-
-#ifndef CONFIG_X86_PAT
- pr_info_once("x86/PAT: PAT support disabled because CONFIG_X86_PAT is disabled in the kernel.\n");
-#endif
-
- if (pat_disabled)
+ /*
+ * Xen PV doesn't allow to set PAT MSR, but all cache modes are
+ * supported.
+ * When running as TDX guest setting the PAT MSR won't work either
+ * due to the requirement to set CR0.CD when doing so. Rely on
+ * firmware to have set the PAT MSR correctly.
+ */
+ if (pat_disabled ||
+ cpu_feature_enabled(X86_FEATURE_XENPV) ||
+ cpu_feature_enabled(X86_FEATURE_TDX_GUEST)) {
+ init_cache_modes(pat_msr_val);
return;
+ }
if ((c->x86_vendor == X86_VENDOR_INTEL) &&
(((c->x86 == 0x6) && (c->x86_model <= 0xd)) ||
@@ -371,8 +330,7 @@ void pat_init(void)
* NOTE: When WT or WP is used, it is redirected to UC- per
* the default setup in __cachemode2pte_tbl[].
*/
- pat = PAT(0, WB) | PAT(1, WC) | PAT(2, UC_MINUS) | PAT(3, UC) |
- PAT(4, WB) | PAT(5, WC) | PAT(6, UC_MINUS) | PAT(7, UC);
+ pat_msr_val = PAT(WB, WC, UC_MINUS, UC, WB, WC, UC_MINUS, UC);
} else {
/*
* Full PAT support. We put WT in slot 7 to improve
@@ -400,19 +358,14 @@ void pat_init(void)
* The reserved slots are unused, but mapped to their
* corresponding types in the presence of PAT errata.
*/
- pat = PAT(0, WB) | PAT(1, WC) | PAT(2, UC_MINUS) | PAT(3, UC) |
- PAT(4, WB) | PAT(5, WP) | PAT(6, UC_MINUS) | PAT(7, WT);
+ pat_msr_val = PAT(WB, WC, UC_MINUS, UC, WB, WP, UC_MINUS, WT);
}
- if (!pat_bp_initialized) {
- pat_bp_init(pat);
- pat_bp_initialized = true;
- } else {
- pat_ap_init(pat);
- }
-}
+ memory_caching_control |= CACHE_PAT;
+ init_cache_modes(pat_msr_val);
#undef PAT
+}
static DEFINE_SPINLOCK(memtype_lock); /* protects memtype accesses */
diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
index 2e5a045731de..ef34ba21aa92 100644
--- a/arch/x86/mm/pat/set_memory.c
+++ b/arch/x86/mm/pat/set_memory.c
@@ -20,6 +20,7 @@
#include <linux/kernel.h>
#include <linux/cc_platform.h>
#include <linux/set_memory.h>
+#include <linux/memregion.h>
#include <asm/e820/api.h>
#include <asm/processor.h>
@@ -330,6 +331,23 @@ void arch_invalidate_pmem(void *addr, size_t size)
EXPORT_SYMBOL_GPL(arch_invalidate_pmem);
#endif
+#ifdef CONFIG_ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION
+bool cpu_cache_has_invalidate_memregion(void)
+{
+ return !cpu_feature_enabled(X86_FEATURE_HYPERVISOR);
+}
+EXPORT_SYMBOL_NS_GPL(cpu_cache_has_invalidate_memregion, DEVMEM);
+
+int cpu_cache_invalidate_memregion(int res_desc)
+{
+ if (WARN_ON_ONCE(!cpu_cache_has_invalidate_memregion()))
+ return -ENXIO;
+ wbinvd_on_all_cpus();
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(cpu_cache_invalidate_memregion, DEVMEM);
+#endif
+
static void __cpa_flush_all(void *arg)
{
unsigned long cache = (unsigned long)arg;
diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile
index a50245157685..543df9a1379d 100644
--- a/arch/x86/platform/efi/Makefile
+++ b/arch/x86/platform/efi/Makefile
@@ -2,5 +2,8 @@
KASAN_SANITIZE := n
GCOV_PROFILE := n
-obj-$(CONFIG_EFI) += quirks.o efi.o efi_$(BITS).o efi_stub_$(BITS).o
+obj-$(CONFIG_EFI) += memmap.o quirks.o efi.o efi_$(BITS).o \
+ efi_stub_$(BITS).o
obj-$(CONFIG_EFI_MIXED) += efi_thunk_$(BITS).o
+obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_mem.o
+obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index ebc98a68c400..7e51c14a1ef0 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -214,9 +214,11 @@ int __init efi_memblock_x86_reserve_range(void)
data.desc_size = e->efi_memdesc_size;
data.desc_version = e->efi_memdesc_version;
- rv = efi_memmap_init_early(&data);
- if (rv)
- return rv;
+ if (!efi_enabled(EFI_PARAVIRT)) {
+ rv = efi_memmap_init_early(&data);
+ if (rv)
+ return rv;
+ }
if (add_efi_memmap || do_efi_soft_reserve())
do_add_efi_memmap();
diff --git a/drivers/firmware/efi/fake_mem.c b/arch/x86/platform/efi/fake_mem.c
index 6e0f34a38171..41d57cad3d84 100644
--- a/drivers/firmware/efi/fake_mem.c
+++ b/arch/x86/platform/efi/fake_mem.c
@@ -17,10 +17,13 @@
#include <linux/memblock.h>
#include <linux/types.h>
#include <linux/sort.h>
-#include "fake_mem.h"
+#include <asm/e820/api.h>
+#include <asm/efi.h>
-struct efi_mem_range efi_fake_mems[EFI_MAX_FAKEMEM];
-int nr_fake_mem;
+#define EFI_MAX_FAKEMEM CONFIG_EFI_MAX_FAKE_MEM
+
+static struct efi_mem_range efi_fake_mems[EFI_MAX_FAKEMEM];
+static int nr_fake_mem;
static int __init cmp_fake_mem(const void *x1, const void *x2)
{
@@ -122,3 +125,73 @@ static int __init setup_fake_mem(char *p)
}
early_param("efi_fake_mem", setup_fake_mem);
+
+void __init efi_fake_memmap_early(void)
+{
+ int i;
+
+ /*
+ * The late efi_fake_mem() call can handle all requests if
+ * EFI_MEMORY_SP support is disabled.
+ */
+ if (!efi_soft_reserve_enabled())
+ return;
+
+ if (!efi_enabled(EFI_MEMMAP) || !nr_fake_mem)
+ return;
+
+ /*
+ * Given that efi_fake_memmap() needs to perform memblock
+ * allocations it needs to run after e820__memblock_setup().
+ * However, if efi_fake_mem specifies EFI_MEMORY_SP for a given
+ * address range that potentially needs to mark the memory as
+ * reserved prior to e820__memblock_setup(). Update e820
+ * directly if EFI_MEMORY_SP is specified for an
+ * EFI_CONVENTIONAL_MEMORY descriptor.
+ */
+ for (i = 0; i < nr_fake_mem; i++) {
+ struct efi_mem_range *mem = &efi_fake_mems[i];
+ efi_memory_desc_t *md;
+ u64 m_start, m_end;
+
+ if ((mem->attribute & EFI_MEMORY_SP) == 0)
+ continue;
+
+ m_start = mem->range.start;
+ m_end = mem->range.end;
+ for_each_efi_memory_desc(md) {
+ u64 start, end, size;
+
+ if (md->type != EFI_CONVENTIONAL_MEMORY)
+ continue;
+
+ start = md->phys_addr;
+ end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
+
+ if (m_start <= end && m_end >= start)
+ /* fake range overlaps descriptor */;
+ else
+ continue;
+
+ /*
+ * Trim the boundary of the e820 update to the
+ * descriptor in case the fake range overlaps
+ * !EFI_CONVENTIONAL_MEMORY
+ */
+ start = max(start, m_start);
+ end = min(end, m_end);
+ size = end - start + 1;
+
+ if (end <= start)
+ continue;
+
+ /*
+ * Ensure each efi_fake_mem instance results in
+ * a unique e820 resource
+ */
+ e820__range_remove(start, size, E820_TYPE_RAM, 1);
+ e820__range_add(start, size, E820_TYPE_SOFT_RESERVED);
+ e820__update_table(e820_table);
+ }
+ }
+}
diff --git a/arch/x86/platform/efi/memmap.c b/arch/x86/platform/efi/memmap.c
new file mode 100644
index 000000000000..c69f8471e6d0
--- /dev/null
+++ b/arch/x86/platform/efi/memmap.c
@@ -0,0 +1,239 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Common EFI memory map functions.
+ */
+
+#define pr_fmt(fmt) "efi: " fmt
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/efi.h>
+#include <linux/io.h>
+#include <asm/early_ioremap.h>
+#include <asm/efi.h>
+#include <linux/memblock.h>
+#include <linux/slab.h>
+
+static phys_addr_t __init __efi_memmap_alloc_early(unsigned long size)
+{
+ return memblock_phys_alloc(size, SMP_CACHE_BYTES);
+}
+
+static phys_addr_t __init __efi_memmap_alloc_late(unsigned long size)
+{
+ unsigned int order = get_order(size);
+ struct page *p = alloc_pages(GFP_KERNEL, order);
+
+ if (!p)
+ return 0;
+
+ return PFN_PHYS(page_to_pfn(p));
+}
+
+void __init __efi_memmap_free(u64 phys, unsigned long size, unsigned long flags)
+{
+ if (flags & EFI_MEMMAP_MEMBLOCK) {
+ if (slab_is_available())
+ memblock_free_late(phys, size);
+ else
+ memblock_phys_free(phys, size);
+ } else if (flags & EFI_MEMMAP_SLAB) {
+ struct page *p = pfn_to_page(PHYS_PFN(phys));
+ unsigned int order = get_order(size);
+
+ free_pages((unsigned long) page_address(p), order);
+ }
+}
+
+/**
+ * efi_memmap_alloc - Allocate memory for the EFI memory map
+ * @num_entries: Number of entries in the allocated map.
+ * @data: efi memmap installation parameters
+ *
+ * Depending on whether mm_init() has already been invoked or not,
+ * either memblock or "normal" page allocation is used.
+ *
+ * Returns zero on success, a negative error code on failure.
+ */
+int __init efi_memmap_alloc(unsigned int num_entries,
+ struct efi_memory_map_data *data)
+{
+ /* Expect allocation parameters are zero initialized */
+ WARN_ON(data->phys_map || data->size);
+
+ data->size = num_entries * efi.memmap.desc_size;
+ data->desc_version = efi.memmap.desc_version;
+ data->desc_size = efi.memmap.desc_size;
+ data->flags &= ~(EFI_MEMMAP_SLAB | EFI_MEMMAP_MEMBLOCK);
+ data->flags |= efi.memmap.flags & EFI_MEMMAP_LATE;
+
+ if (slab_is_available()) {
+ data->flags |= EFI_MEMMAP_SLAB;
+ data->phys_map = __efi_memmap_alloc_late(data->size);
+ } else {
+ data->flags |= EFI_MEMMAP_MEMBLOCK;
+ data->phys_map = __efi_memmap_alloc_early(data->size);
+ }
+
+ if (!data->phys_map)
+ return -ENOMEM;
+ return 0;
+}
+
+/**
+ * efi_memmap_install - Install a new EFI memory map in efi.memmap
+ * @ctx: map allocation parameters (address, size, flags)
+ *
+ * Unlike efi_memmap_init_*(), this function does not allow the caller
+ * to switch from early to late mappings. It simply uses the existing
+ * mapping function and installs the new memmap.
+ *
+ * Returns zero on success, a negative error code on failure.
+ */
+int __init efi_memmap_install(struct efi_memory_map_data *data)
+{
+ efi_memmap_unmap();
+
+ if (efi_enabled(EFI_PARAVIRT))
+ return 0;
+
+ return __efi_memmap_init(data);
+}
+
+/**
+ * efi_memmap_split_count - Count number of additional EFI memmap entries
+ * @md: EFI memory descriptor to split
+ * @range: Address range (start, end) to split around
+ *
+ * Returns the number of additional EFI memmap entries required to
+ * accommodate @range.
+ */
+int __init efi_memmap_split_count(efi_memory_desc_t *md, struct range *range)
+{
+ u64 m_start, m_end;
+ u64 start, end;
+ int count = 0;
+
+ start = md->phys_addr;
+ end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1;
+
+ /* modifying range */
+ m_start = range->start;
+ m_end = range->end;
+
+ if (m_start <= start) {
+ /* split into 2 parts */
+ if (start < m_end && m_end < end)
+ count++;
+ }
+
+ if (start < m_start && m_start < end) {
+ /* split into 3 parts */
+ if (m_end < end)
+ count += 2;
+ /* split into 2 parts */
+ if (end <= m_end)
+ count++;
+ }
+
+ return count;
+}
+
+/**
+ * efi_memmap_insert - Insert a memory region in an EFI memmap
+ * @old_memmap: The existing EFI memory map structure
+ * @buf: Address of buffer to store new map
+ * @mem: Memory map entry to insert
+ *
+ * It is suggested that you call efi_memmap_split_count() first
+ * to see how large @buf needs to be.
+ */
+void __init efi_memmap_insert(struct efi_memory_map *old_memmap, void *buf,
+ struct efi_mem_range *mem)
+{
+ u64 m_start, m_end, m_attr;
+ efi_memory_desc_t *md;
+ u64 start, end;
+ void *old, *new;
+
+ /* modifying range */
+ m_start = mem->range.start;
+ m_end = mem->range.end;
+ m_attr = mem->attribute;
+
+ /*
+ * The EFI memory map deals with regions in EFI_PAGE_SIZE
+ * units. Ensure that the region described by 'mem' is aligned
+ * correctly.
+ */
+ if (!IS_ALIGNED(m_start, EFI_PAGE_SIZE) ||
+ !IS_ALIGNED(m_end + 1, EFI_PAGE_SIZE)) {
+ WARN_ON(1);
+ return;
+ }
+
+ for (old = old_memmap->map, new = buf;
+ old < old_memmap->map_end;
+ old += old_memmap->desc_size, new += old_memmap->desc_size) {
+
+ /* copy original EFI memory descriptor */
+ memcpy(new, old, old_memmap->desc_size);
+ md = new;
+ start = md->phys_addr;
+ end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
+
+ if (m_start <= start && end <= m_end)
+ md->attribute |= m_attr;
+
+ if (m_start <= start &&
+ (start < m_end && m_end < end)) {
+ /* first part */
+ md->attribute |= m_attr;
+ md->num_pages = (m_end - md->phys_addr + 1) >>
+ EFI_PAGE_SHIFT;
+ /* latter part */
+ new += old_memmap->desc_size;
+ memcpy(new, old, old_memmap->desc_size);
+ md = new;
+ md->phys_addr = m_end + 1;
+ md->num_pages = (end - md->phys_addr + 1) >>
+ EFI_PAGE_SHIFT;
+ }
+
+ if ((start < m_start && m_start < end) && m_end < end) {
+ /* first part */
+ md->num_pages = (m_start - md->phys_addr) >>
+ EFI_PAGE_SHIFT;
+ /* middle part */
+ new += old_memmap->desc_size;
+ memcpy(new, old, old_memmap->desc_size);
+ md = new;
+ md->attribute |= m_attr;
+ md->phys_addr = m_start;
+ md->num_pages = (m_end - m_start + 1) >>
+ EFI_PAGE_SHIFT;
+ /* last part */
+ new += old_memmap->desc_size;
+ memcpy(new, old, old_memmap->desc_size);
+ md = new;
+ md->phys_addr = m_end + 1;
+ md->num_pages = (end - m_end) >>
+ EFI_PAGE_SHIFT;
+ }
+
+ if ((start < m_start && m_start < end) &&
+ (end <= m_end)) {
+ /* first part */
+ md->num_pages = (m_start - md->phys_addr) >>
+ EFI_PAGE_SHIFT;
+ /* latter part */
+ new += old_memmap->desc_size;
+ memcpy(new, old, old_memmap->desc_size);
+ md = new;
+ md->phys_addr = m_start;
+ md->num_pages = (end - md->phys_addr + 1) >>
+ EFI_PAGE_SHIFT;
+ md->attribute |= m_attr;
+ }
+ }
+}
diff --git a/drivers/firmware/efi/runtime-map.c b/arch/x86/platform/efi/runtime-map.c
index 92a3d45a795c..bbee682ef8cd 100644
--- a/drivers/firmware/efi/runtime-map.c
+++ b/arch/x86/platform/efi/runtime-map.c
@@ -1,6 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * linux/drivers/efi/runtime-map.c
* Copyright (C) 2013 Red Hat, Inc., Dave Young <dyoung@redhat.com>
*/
@@ -11,6 +10,7 @@
#include <linux/efi.h>
#include <linux/slab.h>
+#include <asm/efi.h>
#include <asm/setup.h>
struct efi_runtime_map_entry {
@@ -157,13 +157,13 @@ int efi_runtime_map_copy(void *buf, size_t bufsz)
return 0;
}
-int __init efi_runtime_map_init(struct kobject *efi_kobj)
+static int __init efi_runtime_map_init(void)
{
int i, j, ret = 0;
struct efi_runtime_map_entry *entry;
efi_memory_desc_t *md;
- if (!efi_enabled(EFI_MEMMAP))
+ if (!efi_enabled(EFI_MEMMAP) || !efi_kobj)
return 0;
map_entries = kcalloc(efi.memmap.nr_map, sizeof(entry), GFP_KERNEL);
@@ -191,3 +191,4 @@ out_add_entry:
out:
return ret;
}
+subsys_initcall_sync(efi_runtime_map_init);
diff --git a/arch/x86/platform/olpc/olpc-xo15-sci.c b/arch/x86/platform/olpc/olpc-xo15-sci.c
index 994a229cb79f..68244a3422d1 100644
--- a/arch/x86/platform/olpc/olpc-xo15-sci.c
+++ b/arch/x86/platform/olpc/olpc-xo15-sci.c
@@ -183,13 +183,12 @@ err_sysfs:
return r;
}
-static int xo15_sci_remove(struct acpi_device *device)
+static void xo15_sci_remove(struct acpi_device *device)
{
acpi_disable_gpe(NULL, xo15_sci_gpe);
acpi_remove_gpe_handler(NULL, xo15_sci_gpe, xo15_sci_gpe_handler);
cancel_work_sync(&sci_work);
sysfs_remove_file(&device->dev.kobj, &lid_wake_on_close_attr.attr);
- return 0;
}
#ifdef CONFIG_PM_SLEEP
diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c
index 93ae33248f42..236447ee9beb 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu.c
@@ -23,6 +23,7 @@
#include <asm/fpu/api.h>
#include <asm/debugreg.h>
#include <asm/cpu.h>
+#include <asm/cacheinfo.h>
#include <asm/mmu_context.h>
#include <asm/cpu_device_id.h>
#include <asm/microcode.h>
@@ -261,7 +262,7 @@ static void notrace __restore_processor_state(struct saved_context *ctxt)
do_fpu_end();
tsc_verify_tsc_adjust(true);
x86_platform.restore_sched_clock_state();
- mtrr_bp_restore();
+ cache_bp_restore();
perf_restore_debug_store();
c = &cpu_data(smp_processor_id());
diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index 41d7669a97ad..af565816d2ba 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -200,14 +200,18 @@ static void __init set_real_mode_permissions(void)
set_memory_x((unsigned long) text_start, text_size >> PAGE_SHIFT);
}
-static int __init init_real_mode(void)
+void __init init_real_mode(void)
{
if (!real_mode_header)
panic("Real mode trampoline was not allocated");
setup_real_mode();
set_real_mode_permissions();
+}
+static int __init do_init_real_mode(void)
+{
+ x86_platform.realmode_init();
return 0;
}
-early_initcall(init_real_mode);
+early_initcall(do_init_real_mode);
diff --git a/arch/x86/um/asm/elf.h b/arch/x86/um/asm/elf.h
index dcaf3b38a9e0..6523eb7c3bd1 100644
--- a/arch/x86/um/asm/elf.h
+++ b/arch/x86/um/asm/elf.h
@@ -201,10 +201,6 @@ typedef struct user_i387_struct elf_fpregset_t;
struct task_struct;
-extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu);
-
-#define ELF_CORE_COPY_FPREGS(t, fpu) elf_core_copy_fpregs(t, fpu)
-
#define ELF_EXEC_PAGESIZE 4096
#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index 038da45f057a..468e8c8cce01 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -33,6 +33,7 @@
#include <linux/edd.h>
#include <linux/reboot.h>
#include <linux/virtio_anchor.h>
+#include <linux/stackprotector.h>
#include <xen/xen.h>
#include <xen/events.h>
@@ -65,7 +66,6 @@
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#include <asm/reboot.h>
-#include <asm/stackprotector.h>
#include <asm/hypervisor.h>
#include <asm/mach_traps.h>
#include <asm/mwait.h>
@@ -1266,6 +1266,8 @@ asmlinkage __visible void __init xen_start_kernel(struct start_info *si)
xen_vcpu_info_reset(0);
x86_platform.get_nmi_reason = xen_get_nmi_reason;
+ x86_platform.realmode_reserve = x86_init_noop;
+ x86_platform.realmode_init = x86_init_noop;
x86_init.resources.memory_setup = xen_memory_setup;
x86_init.irqs.intr_mode_select = x86_init_noop;
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index c3e1f9a7d43a..4b0d6fff88de 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -32,30 +32,30 @@ static irqreturn_t xen_reschedule_interrupt(int irq, void *dev_id)
void xen_smp_intr_free(unsigned int cpu)
{
+ kfree(per_cpu(xen_resched_irq, cpu).name);
+ per_cpu(xen_resched_irq, cpu).name = NULL;
if (per_cpu(xen_resched_irq, cpu).irq >= 0) {
unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu).irq, NULL);
per_cpu(xen_resched_irq, cpu).irq = -1;
- kfree(per_cpu(xen_resched_irq, cpu).name);
- per_cpu(xen_resched_irq, cpu).name = NULL;
}
+ kfree(per_cpu(xen_callfunc_irq, cpu).name);
+ per_cpu(xen_callfunc_irq, cpu).name = NULL;
if (per_cpu(xen_callfunc_irq, cpu).irq >= 0) {
unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu).irq, NULL);
per_cpu(xen_callfunc_irq, cpu).irq = -1;
- kfree(per_cpu(xen_callfunc_irq, cpu).name);
- per_cpu(xen_callfunc_irq, cpu).name = NULL;
}
+ kfree(per_cpu(xen_debug_irq, cpu).name);
+ per_cpu(xen_debug_irq, cpu).name = NULL;
if (per_cpu(xen_debug_irq, cpu).irq >= 0) {
unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu).irq, NULL);
per_cpu(xen_debug_irq, cpu).irq = -1;
- kfree(per_cpu(xen_debug_irq, cpu).name);
- per_cpu(xen_debug_irq, cpu).name = NULL;
}
+ kfree(per_cpu(xen_callfuncsingle_irq, cpu).name);
+ per_cpu(xen_callfuncsingle_irq, cpu).name = NULL;
if (per_cpu(xen_callfuncsingle_irq, cpu).irq >= 0) {
unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu).irq,
NULL);
per_cpu(xen_callfuncsingle_irq, cpu).irq = -1;
- kfree(per_cpu(xen_callfuncsingle_irq, cpu).name);
- per_cpu(xen_callfuncsingle_irq, cpu).name = NULL;
}
}
@@ -65,6 +65,7 @@ int xen_smp_intr_init(unsigned int cpu)
char *resched_name, *callfunc_name, *debug_name;
resched_name = kasprintf(GFP_KERNEL, "resched%d", cpu);
+ per_cpu(xen_resched_irq, cpu).name = resched_name;
rc = bind_ipi_to_irqhandler(XEN_RESCHEDULE_VECTOR,
cpu,
xen_reschedule_interrupt,
@@ -74,9 +75,9 @@ int xen_smp_intr_init(unsigned int cpu)
if (rc < 0)
goto fail;
per_cpu(xen_resched_irq, cpu).irq = rc;
- per_cpu(xen_resched_irq, cpu).name = resched_name;
callfunc_name = kasprintf(GFP_KERNEL, "callfunc%d", cpu);
+ per_cpu(xen_callfunc_irq, cpu).name = callfunc_name;
rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_VECTOR,
cpu,
xen_call_function_interrupt,
@@ -86,10 +87,10 @@ int xen_smp_intr_init(unsigned int cpu)
if (rc < 0)
goto fail;
per_cpu(xen_callfunc_irq, cpu).irq = rc;
- per_cpu(xen_callfunc_irq, cpu).name = callfunc_name;
if (!xen_fifo_events) {
debug_name = kasprintf(GFP_KERNEL, "debug%d", cpu);
+ per_cpu(xen_debug_irq, cpu).name = debug_name;
rc = bind_virq_to_irqhandler(VIRQ_DEBUG, cpu,
xen_debug_interrupt,
IRQF_PERCPU | IRQF_NOBALANCING,
@@ -97,10 +98,10 @@ int xen_smp_intr_init(unsigned int cpu)
if (rc < 0)
goto fail;
per_cpu(xen_debug_irq, cpu).irq = rc;
- per_cpu(xen_debug_irq, cpu).name = debug_name;
}
callfunc_name = kasprintf(GFP_KERNEL, "callfuncsingle%d", cpu);
+ per_cpu(xen_callfuncsingle_irq, cpu).name = callfunc_name;
rc = bind_ipi_to_irqhandler(XEN_CALL_FUNCTION_SINGLE_VECTOR,
cpu,
xen_call_function_single_interrupt,
@@ -110,7 +111,6 @@ int xen_smp_intr_init(unsigned int cpu)
if (rc < 0)
goto fail;
per_cpu(xen_callfuncsingle_irq, cpu).irq = rc;
- per_cpu(xen_callfuncsingle_irq, cpu).name = callfunc_name;
return 0;
diff --git a/arch/x86/xen/smp_pv.c b/arch/x86/xen/smp_pv.c
index 480be82e9b7b..6175f2c5c822 100644
--- a/arch/x86/xen/smp_pv.c
+++ b/arch/x86/xen/smp_pv.c
@@ -97,18 +97,18 @@ asmlinkage __visible void cpu_bringup_and_idle(void)
void xen_smp_intr_free_pv(unsigned int cpu)
{
+ kfree(per_cpu(xen_irq_work, cpu).name);
+ per_cpu(xen_irq_work, cpu).name = NULL;
if (per_cpu(xen_irq_work, cpu).irq >= 0) {
unbind_from_irqhandler(per_cpu(xen_irq_work, cpu).irq, NULL);
per_cpu(xen_irq_work, cpu).irq = -1;
- kfree(per_cpu(xen_irq_work, cpu).name);
- per_cpu(xen_irq_work, cpu).name = NULL;
}
+ kfree(per_cpu(xen_pmu_irq, cpu).name);
+ per_cpu(xen_pmu_irq, cpu).name = NULL;
if (per_cpu(xen_pmu_irq, cpu).irq >= 0) {
unbind_from_irqhandler(per_cpu(xen_pmu_irq, cpu).irq, NULL);
per_cpu(xen_pmu_irq, cpu).irq = -1;
- kfree(per_cpu(xen_pmu_irq, cpu).name);
- per_cpu(xen_pmu_irq, cpu).name = NULL;
}
}
@@ -118,6 +118,7 @@ int xen_smp_intr_init_pv(unsigned int cpu)
char *callfunc_name, *pmu_name;
callfunc_name = kasprintf(GFP_KERNEL, "irqwork%d", cpu);
+ per_cpu(xen_irq_work, cpu).name = callfunc_name;
rc = bind_ipi_to_irqhandler(XEN_IRQ_WORK_VECTOR,
cpu,
xen_irq_work_interrupt,
@@ -127,10 +128,10 @@ int xen_smp_intr_init_pv(unsigned int cpu)
if (rc < 0)
goto fail;
per_cpu(xen_irq_work, cpu).irq = rc;
- per_cpu(xen_irq_work, cpu).name = callfunc_name;
if (is_xen_pmu) {
pmu_name = kasprintf(GFP_KERNEL, "pmu%d", cpu);
+ per_cpu(xen_pmu_irq, cpu).name = pmu_name;
rc = bind_virq_to_irqhandler(VIRQ_XENPMU, cpu,
xen_pmu_irq_handler,
IRQF_PERCPU|IRQF_NOBALANCING,
@@ -138,7 +139,6 @@ int xen_smp_intr_init_pv(unsigned int cpu)
if (rc < 0)
goto fail;
per_cpu(xen_pmu_irq, cpu).irq = rc;
- per_cpu(xen_pmu_irq, cpu).name = pmu_name;
}
return 0;
diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c
index 043c73dfd2c9..5c6fc16e4b92 100644
--- a/arch/x86/xen/spinlock.c
+++ b/arch/x86/xen/spinlock.c
@@ -75,6 +75,7 @@ void xen_init_lock_cpu(int cpu)
cpu, per_cpu(lock_kicker_irq, cpu));
name = kasprintf(GFP_KERNEL, "spinlock%d", cpu);
+ per_cpu(irq_name, cpu) = name;
irq = bind_ipi_to_irqhandler(XEN_SPIN_UNLOCK_VECTOR,
cpu,
dummy_handler,
@@ -85,7 +86,6 @@ void xen_init_lock_cpu(int cpu)
if (irq >= 0) {
disable_irq(irq); /* make sure it's never delivered */
per_cpu(lock_kicker_irq, cpu) = irq;
- per_cpu(irq_name, cpu) = name;
}
printk("cpu %d spinlock event irq %d\n", cpu, irq);
@@ -98,6 +98,8 @@ void xen_uninit_lock_cpu(int cpu)
if (!xen_pvspin)
return;
+ kfree(per_cpu(irq_name, cpu));
+ per_cpu(irq_name, cpu) = NULL;
/*
* When booting the kernel with 'mitigations=auto,nosmt', the secondary
* CPUs are not activated, and lock_kicker_irq is not initialized.
@@ -108,8 +110,6 @@ void xen_uninit_lock_cpu(int cpu)
unbind_from_irqhandler(irq, NULL);
per_cpu(lock_kicker_irq, cpu) = -1;
- kfree(per_cpu(irq_name, cpu));
- per_cpu(irq_name, cpu) = NULL;
}
PV_CALLEE_SAVE_REGS_THUNK(xen_vcpu_stolen);
diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S
index 6b4fdf6b9542..4a184f6e4e4d 100644
--- a/arch/x86/xen/xen-asm.S
+++ b/arch/x86/xen/xen-asm.S
@@ -262,10 +262,10 @@ SYM_CODE_START(xen_entry_SYSCALL_compat)
/*
* Neither Xen nor the kernel really knows what the old SS and
- * CS were. The kernel expects __USER32_DS and __USER32_CS, so
+ * CS were. The kernel expects __USER_DS and __USER32_CS, so
* report those values even though Xen will guess its own values.
*/
- movq $__USER32_DS, 4*8(%rsp)
+ movq $__USER_DS, 4*8(%rsp)
movq $__USER32_CS, 1*8(%rsp)
jmp entry_SYSCALL_compat_after_hwframe
@@ -284,10 +284,10 @@ SYM_CODE_START(xen_entry_SYSENTER_compat)
/*
* Neither Xen nor the kernel really knows what the old SS and
- * CS were. The kernel expects __USER32_DS and __USER32_CS, so
+ * CS were. The kernel expects __USER_DS and __USER32_CS, so
* report those values even though Xen will guess its own values.
*/
- movq $__USER32_DS, 4*8(%rsp)
+ movq $__USER_DS, 4*8(%rsp)
movq $__USER32_CS, 1*8(%rsp)
jmp entry_SYSENTER_compat_after_hwframe
diff --git a/arch/xtensa/configs/audio_kc705_defconfig b/arch/xtensa/configs/audio_kc705_defconfig
index ef0ebcfbccf9..436b7cac9694 100644
--- a/arch/xtensa/configs/audio_kc705_defconfig
+++ b/arch/xtensa/configs/audio_kc705_defconfig
@@ -125,7 +125,6 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_LOCKUP_DETECTOR=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_SCHEDSTATS=y
-CONFIG_TIMER_STATS=y
CONFIG_DEBUG_RT_MUTEXES=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
diff --git a/arch/xtensa/configs/cadence_csp_defconfig b/arch/xtensa/configs/cadence_csp_defconfig
index 2665962d247a..8c66b9307f34 100644
--- a/arch/xtensa/configs/cadence_csp_defconfig
+++ b/arch/xtensa/configs/cadence_csp_defconfig
@@ -48,9 +48,6 @@ CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
# CONFIG_INET_DIAG is not set
# CONFIG_IPV6 is not set
# CONFIG_WIRELESS is not set
@@ -105,7 +102,6 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_LOCKUP_DETECTOR=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_SCHEDSTATS=y
-CONFIG_TIMER_STATS=y
CONFIG_DEBUG_RT_MUTEXES=y
CONFIG_PROVE_LOCKING=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
diff --git a/arch/xtensa/configs/generic_kc705_defconfig b/arch/xtensa/configs/generic_kc705_defconfig
index 236c7f23cc10..e376238bc5ca 100644
--- a/arch/xtensa/configs/generic_kc705_defconfig
+++ b/arch/xtensa/configs/generic_kc705_defconfig
@@ -112,7 +112,6 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_LOCKUP_DETECTOR=y
# CONFIG_SCHED_DEBUG is not set
CONFIG_SCHEDSTATS=y
-CONFIG_TIMER_STATS=y
CONFIG_DEBUG_RT_MUTEXES=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
diff --git a/arch/xtensa/configs/nommu_kc705_defconfig b/arch/xtensa/configs/nommu_kc705_defconfig
index 8263da9e078d..c2ab4306ee20 100644
--- a/arch/xtensa/configs/nommu_kc705_defconfig
+++ b/arch/xtensa/configs/nommu_kc705_defconfig
@@ -113,7 +113,6 @@ CONFIG_DEBUG_NOMMU_REGIONS=y
CONFIG_DEBUG_SHIRQ=y
CONFIG_LOCKUP_DETECTOR=y
CONFIG_SCHEDSTATS=y
-CONFIG_TIMER_STATS=y
CONFIG_DEBUG_RT_MUTEXES=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
diff --git a/arch/xtensa/configs/smp_lx200_defconfig b/arch/xtensa/configs/smp_lx200_defconfig
index 7bdffa3a69c6..63b56ce79f83 100644
--- a/arch/xtensa/configs/smp_lx200_defconfig
+++ b/arch/xtensa/configs/smp_lx200_defconfig
@@ -116,7 +116,6 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_VM=y
CONFIG_LOCKUP_DETECTOR=y
CONFIG_SCHEDSTATS=y
-CONFIG_TIMER_STATS=y
CONFIG_DEBUG_RT_MUTEXES=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
diff --git a/arch/xtensa/configs/xip_kc705_defconfig b/arch/xtensa/configs/xip_kc705_defconfig
index 1c3cebaaa71b..165652c45b85 100644
--- a/arch/xtensa/configs/xip_kc705_defconfig
+++ b/arch/xtensa/configs/xip_kc705_defconfig
@@ -55,7 +55,6 @@ CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_NETDEVICES=y
# CONFIG_NET_VENDOR_ARC is not set
-# CONFIG_NET_VENDOR_AURORA is not set
# CONFIG_NET_VENDOR_BROADCOM is not set
# CONFIG_NET_VENDOR_INTEL is not set
# CONFIG_NET_VENDOR_MARVELL is not set
diff --git a/arch/xtensa/include/asm/stackprotector.h b/arch/xtensa/include/asm/stackprotector.h
index e368f94fd2af..dd10279a2378 100644
--- a/arch/xtensa/include/asm/stackprotector.h
+++ b/arch/xtensa/include/asm/stackprotector.h
@@ -14,9 +14,6 @@
#ifndef _ASM_STACKPROTECTOR_H
#define _ASM_STACKPROTECTOR_H 1
-#include <linux/random.h>
-#include <linux/version.h>
-
extern unsigned long __stack_chk_guard;
/*
@@ -27,11 +24,7 @@ extern unsigned long __stack_chk_guard;
*/
static __always_inline void boot_init_stack_canary(void)
{
- unsigned long canary;
-
- /* Try to get a semi random initial value. */
- get_random_bytes(&canary, sizeof(canary));
- canary ^= LINUX_VERSION_CODE;
+ unsigned long canary = get_random_canary();
current->stack_canary = canary;
__stack_chk_guard = current->stack_canary;
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c
index b0bc8897c924..2a31b1ab0c9f 100644
--- a/arch/xtensa/kernel/xtensa_ksyms.c
+++ b/arch/xtensa/kernel/xtensa_ksyms.c
@@ -62,6 +62,7 @@ extern int __modsi3(int, int);
extern int __mulsi3(int, int);
extern unsigned int __udivsi3(unsigned int, unsigned int);
extern unsigned int __umodsi3(unsigned int, unsigned int);
+extern unsigned long long __umulsidi3(unsigned int, unsigned int);
EXPORT_SYMBOL(__ashldi3);
EXPORT_SYMBOL(__ashrdi3);
@@ -71,6 +72,7 @@ EXPORT_SYMBOL(__modsi3);
EXPORT_SYMBOL(__mulsi3);
EXPORT_SYMBOL(__udivsi3);
EXPORT_SYMBOL(__umodsi3);
+EXPORT_SYMBOL(__umulsidi3);
unsigned int __sync_fetch_and_and_4(volatile void *p, unsigned int v)
{
diff --git a/arch/xtensa/lib/Makefile b/arch/xtensa/lib/Makefile
index d4e9c397e3fd..7ecef0519a27 100644
--- a/arch/xtensa/lib/Makefile
+++ b/arch/xtensa/lib/Makefile
@@ -5,7 +5,7 @@
lib-y += memcopy.o memset.o checksum.o \
ashldi3.o ashrdi3.o lshrdi3.o \
- divsi3.o udivsi3.o modsi3.o umodsi3.o mulsi3.o \
+ divsi3.o udivsi3.o modsi3.o umodsi3.o mulsi3.o umulsidi3.o \
usercopy.o strncpy_user.o strnlen_user.o
lib-$(CONFIG_PCI) += pci-auto.o
lib-$(CONFIG_KCSAN) += kcsan-stubs.o
diff --git a/arch/xtensa/lib/umulsidi3.S b/arch/xtensa/lib/umulsidi3.S
new file mode 100644
index 000000000000..136081647942
--- /dev/null
+++ b/arch/xtensa/lib/umulsidi3.S
@@ -0,0 +1,230 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 */
+#include <linux/linkage.h>
+#include <asm/asmmacro.h>
+#include <asm/core.h>
+
+#if !XCHAL_HAVE_MUL16 && !XCHAL_HAVE_MUL32 && !XCHAL_HAVE_MAC16
+#define XCHAL_NO_MUL 1
+#endif
+
+ENTRY(__umulsidi3)
+
+#ifdef __XTENSA_CALL0_ABI__
+ abi_entry(32)
+ s32i a12, sp, 16
+ s32i a13, sp, 20
+ s32i a14, sp, 24
+ s32i a15, sp, 28
+#elif XCHAL_NO_MUL
+ /* This is not really a leaf function; allocate enough stack space
+ to allow CALL12s to a helper function. */
+ abi_entry(32)
+#else
+ abi_entry_default
+#endif
+
+#ifdef __XTENSA_EB__
+#define wh a2
+#define wl a3
+#else
+#define wh a3
+#define wl a2
+#endif /* __XTENSA_EB__ */
+
+ /* This code is taken from the mulsf3 routine in ieee754-sf.S.
+ See more comments there. */
+
+#if XCHAL_HAVE_MUL32_HIGH
+ mull a6, a2, a3
+ muluh wh, a2, a3
+ mov wl, a6
+
+#else /* ! MUL32_HIGH */
+
+#if defined(__XTENSA_CALL0_ABI__) && XCHAL_NO_MUL
+ /* a0 and a8 will be clobbered by calling the multiply function
+ but a8 is not used here and need not be saved. */
+ s32i a0, sp, 0
+#endif
+
+#if XCHAL_HAVE_MUL16 || XCHAL_HAVE_MUL32
+
+#define a2h a4
+#define a3h a5
+
+ /* Get the high halves of the inputs into registers. */
+ srli a2h, a2, 16
+ srli a3h, a3, 16
+
+#define a2l a2
+#define a3l a3
+
+#if XCHAL_HAVE_MUL32 && !XCHAL_HAVE_MUL16
+ /* Clear the high halves of the inputs. This does not matter
+ for MUL16 because the high bits are ignored. */
+ extui a2, a2, 0, 16
+ extui a3, a3, 0, 16
+#endif
+#endif /* MUL16 || MUL32 */
+
+
+#if XCHAL_HAVE_MUL16
+
+#define do_mul(dst, xreg, xhalf, yreg, yhalf) \
+ mul16u dst, xreg ## xhalf, yreg ## yhalf
+
+#elif XCHAL_HAVE_MUL32
+
+#define do_mul(dst, xreg, xhalf, yreg, yhalf) \
+ mull dst, xreg ## xhalf, yreg ## yhalf
+
+#elif XCHAL_HAVE_MAC16
+
+/* The preprocessor insists on inserting a space when concatenating after
+ a period in the definition of do_mul below. These macros are a workaround
+ using underscores instead of periods when doing the concatenation. */
+#define umul_aa_ll umul.aa.ll
+#define umul_aa_lh umul.aa.lh
+#define umul_aa_hl umul.aa.hl
+#define umul_aa_hh umul.aa.hh
+
+#define do_mul(dst, xreg, xhalf, yreg, yhalf) \
+ umul_aa_ ## xhalf ## yhalf xreg, yreg; \
+ rsr dst, ACCLO
+
+#else /* no multiply hardware */
+
+#define set_arg_l(dst, src) \
+ extui dst, src, 0, 16
+#define set_arg_h(dst, src) \
+ srli dst, src, 16
+
+#ifdef __XTENSA_CALL0_ABI__
+#define do_mul(dst, xreg, xhalf, yreg, yhalf) \
+ set_arg_ ## xhalf (a13, xreg); \
+ set_arg_ ## yhalf (a14, yreg); \
+ call0 .Lmul_mulsi3; \
+ mov dst, a12
+#else
+#define do_mul(dst, xreg, xhalf, yreg, yhalf) \
+ set_arg_ ## xhalf (a14, xreg); \
+ set_arg_ ## yhalf (a15, yreg); \
+ call12 .Lmul_mulsi3; \
+ mov dst, a14
+#endif /* __XTENSA_CALL0_ABI__ */
+
+#endif /* no multiply hardware */
+
+ /* Add pp1 and pp2 into a6 with carry-out in a9. */
+ do_mul(a6, a2, l, a3, h) /* pp 1 */
+ do_mul(a11, a2, h, a3, l) /* pp 2 */
+ movi a9, 0
+ add a6, a6, a11
+ bgeu a6, a11, 1f
+ addi a9, a9, 1
+1:
+ /* Shift the high half of a9/a6 into position in a9. Note that
+ this value can be safely incremented without any carry-outs. */
+ ssai 16
+ src a9, a9, a6
+
+ /* Compute the low word into a6. */
+ do_mul(a11, a2, l, a3, l) /* pp 0 */
+ sll a6, a6
+ add a6, a6, a11
+ bgeu a6, a11, 1f
+ addi a9, a9, 1
+1:
+ /* Compute the high word into wh. */
+ do_mul(wh, a2, h, a3, h) /* pp 3 */
+ add wh, wh, a9
+ mov wl, a6
+
+#endif /* !MUL32_HIGH */
+
+#if defined(__XTENSA_CALL0_ABI__) && XCHAL_NO_MUL
+ /* Restore the original return address. */
+ l32i a0, sp, 0
+#endif
+#ifdef __XTENSA_CALL0_ABI__
+ l32i a12, sp, 16
+ l32i a13, sp, 20
+ l32i a14, sp, 24
+ l32i a15, sp, 28
+ abi_ret(32)
+#else
+ abi_ret_default
+#endif
+
+#if XCHAL_NO_MUL
+
+ .macro do_addx2 dst, as, at, tmp
+#if XCHAL_HAVE_ADDX
+ addx2 \dst, \as, \at
+#else
+ slli \tmp, \as, 1
+ add \dst, \tmp, \at
+#endif
+ .endm
+
+ .macro do_addx4 dst, as, at, tmp
+#if XCHAL_HAVE_ADDX
+ addx4 \dst, \as, \at
+#else
+ slli \tmp, \as, 2
+ add \dst, \tmp, \at
+#endif
+ .endm
+
+ .macro do_addx8 dst, as, at, tmp
+#if XCHAL_HAVE_ADDX
+ addx8 \dst, \as, \at
+#else
+ slli \tmp, \as, 3
+ add \dst, \tmp, \at
+#endif
+ .endm
+
+ /* For Xtensa processors with no multiply hardware, this simplified
+ version of _mulsi3 is used for multiplying 16-bit chunks of
+ the floating-point mantissas. When using CALL0, this function
+ uses a custom ABI: the inputs are passed in a13 and a14, the
+ result is returned in a12, and a8 and a15 are clobbered. */
+ .align 4
+.Lmul_mulsi3:
+ abi_entry_default
+
+ .macro mul_mulsi3_body dst, src1, src2, tmp1, tmp2
+ movi \dst, 0
+1: add \tmp1, \src2, \dst
+ extui \tmp2, \src1, 0, 1
+ movnez \dst, \tmp1, \tmp2
+
+ do_addx2 \tmp1, \src2, \dst, \tmp1
+ extui \tmp2, \src1, 1, 1
+ movnez \dst, \tmp1, \tmp2
+
+ do_addx4 \tmp1, \src2, \dst, \tmp1
+ extui \tmp2, \src1, 2, 1
+ movnez \dst, \tmp1, \tmp2
+
+ do_addx8 \tmp1, \src2, \dst, \tmp1
+ extui \tmp2, \src1, 3, 1
+ movnez \dst, \tmp1, \tmp2
+
+ srli \src1, \src1, 4
+ slli \src2, \src2, 4
+ bnez \src1, 1b
+ .endm
+
+#ifdef __XTENSA_CALL0_ABI__
+ mul_mulsi3_body a12, a13, a14, a15, a8
+#else
+ /* The result will be written into a2, so save that argument in a4. */
+ mov a4, a2
+ mul_mulsi3_body a2, a4, a3, a5, a6
+#endif
+ abi_ret_default
+#endif /* XCHAL_NO_MUL */
+
+ENDPROC(__umulsidi3)
diff --git a/block/bdev.c b/block/bdev.c
index d699ecdb3260..edc110d90df4 100644
--- a/block/bdev.c
+++ b/block/bdev.c
@@ -224,7 +224,7 @@ int fsync_bdev(struct block_device *bdev)
EXPORT_SYMBOL(fsync_bdev);
/**
- * freeze_bdev -- lock a filesystem and force it into a consistent state
+ * freeze_bdev - lock a filesystem and force it into a consistent state
* @bdev: blockdevice to lock
*
* If a superblock is found on this device, we take the s_umount semaphore
@@ -268,7 +268,7 @@ done:
EXPORT_SYMBOL(freeze_bdev);
/**
- * thaw_bdev -- unlock filesystem
+ * thaw_bdev - unlock filesystem
* @bdev: blockdevice to unlock
*
* Unlocks the filesystem and marks it writeable again after freeze_bdev().
diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
index 7d624a3a3f0f..627476bc6495 100644
--- a/block/bfq-cgroup.c
+++ b/block/bfq-cgroup.c
@@ -224,7 +224,7 @@ void bfqg_stats_update_io_add(struct bfq_group *bfqg, struct bfq_queue *bfqq,
{
blkg_rwstat_add(&bfqg->stats.queued, opf, 1);
bfqg_stats_end_empty_time(&bfqg->stats);
- if (!(bfqq == ((struct bfq_data *)bfqg->bfqd)->in_service_queue))
+ if (!(bfqq == bfqg->bfqd->in_service_queue))
bfqg_stats_set_start_group_wait_time(bfqg, bfqq_group(bfqq));
}
@@ -552,6 +552,7 @@ static void bfq_pd_init(struct blkg_policy_data *pd)
*/
bfqg->bfqd = bfqd;
bfqg->active_entities = 0;
+ bfqg->num_queues_with_pending_reqs = 0;
bfqg->online = true;
bfqg->rq_pos_tree = RB_ROOT;
}
@@ -645,6 +646,7 @@ void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
{
struct bfq_entity *entity = &bfqq->entity;
struct bfq_group *old_parent = bfqq_group(bfqq);
+ bool has_pending_reqs = false;
/*
* No point to move bfqq to the same group, which can happen when
@@ -665,6 +667,11 @@ void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
*/
bfqq->ref++;
+ if (entity->in_groups_with_pending_reqs) {
+ has_pending_reqs = true;
+ bfq_del_bfqq_in_groups_with_pending_reqs(bfqq);
+ }
+
/* If bfqq is empty, then bfq_bfqq_expire also invokes
* bfq_del_bfqq_busy, thereby removing bfqq and its entity
* from data structures related to current group. Otherwise we
@@ -692,6 +699,9 @@ void bfq_bfqq_move(struct bfq_data *bfqd, struct bfq_queue *bfqq,
/* pin down bfqg and its associated blkg */
bfqg_and_blkg_get(bfqg);
+ if (has_pending_reqs)
+ bfq_add_bfqq_in_groups_with_pending_reqs(bfqq);
+
if (bfq_bfqq_busy(bfqq)) {
if (unlikely(!bfqd->nonrot_with_queueing))
bfq_pos_tree_add_move(bfqd, bfqq);
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index 7ea427817f7f..a72304c728fc 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -820,7 +820,7 @@ bfq_pos_tree_add_move(struct bfq_data *bfqd, struct bfq_queue *bfqq)
* much easier to maintain the needed state:
* 1) all active queues have the same weight,
* 2) all active queues belong to the same I/O-priority class,
- * 3) there are no active groups.
+ * 3) there is at most one active group.
* In particular, the last condition is always true if hierarchical
* support or the cgroups interface are not enabled, thus no state
* needs to be maintained in this case.
@@ -852,7 +852,7 @@ static bool bfq_asymmetric_scenario(struct bfq_data *bfqd,
return varied_queue_weights || multiple_classes_busy
#ifdef CONFIG_BFQ_GROUP_IOSCHED
- || bfqd->num_groups_with_pending_reqs > 0
+ || bfqd->num_groups_with_pending_reqs > 1
#endif
;
}
@@ -870,9 +870,9 @@ static bool bfq_asymmetric_scenario(struct bfq_data *bfqd,
* In most scenarios, the rate at which nodes are created/destroyed
* should be low too.
*/
-void bfq_weights_tree_add(struct bfq_data *bfqd, struct bfq_queue *bfqq,
- struct rb_root_cached *root)
+void bfq_weights_tree_add(struct bfq_queue *bfqq)
{
+ struct rb_root_cached *root = &bfqq->bfqd->queue_weights_tree;
struct bfq_entity *entity = &bfqq->entity;
struct rb_node **new = &(root->rb_root.rb_node), *parent = NULL;
bool leftmost = true;
@@ -944,13 +944,14 @@ inc_counter:
* See the comments to the function bfq_weights_tree_add() for considerations
* about overhead.
*/
-void __bfq_weights_tree_remove(struct bfq_data *bfqd,
- struct bfq_queue *bfqq,
- struct rb_root_cached *root)
+void bfq_weights_tree_remove(struct bfq_queue *bfqq)
{
+ struct rb_root_cached *root;
+
if (!bfqq->weight_counter)
return;
+ root = &bfqq->bfqd->queue_weights_tree;
bfqq->weight_counter->num_active--;
if (bfqq->weight_counter->num_active > 0)
goto reset_entity_pointer;
@@ -964,59 +965,6 @@ reset_entity_pointer:
}
/*
- * Invoke __bfq_weights_tree_remove on bfqq and decrement the number
- * of active groups for each queue's inactive parent entity.
- */
-void bfq_weights_tree_remove(struct bfq_data *bfqd,
- struct bfq_queue *bfqq)
-{
- struct bfq_entity *entity = bfqq->entity.parent;
-
- for_each_entity(entity) {
- struct bfq_sched_data *sd = entity->my_sched_data;
-
- if (sd->next_in_service || sd->in_service_entity) {
- /*
- * entity is still active, because either
- * next_in_service or in_service_entity is not
- * NULL (see the comments on the definition of
- * next_in_service for details on why
- * in_service_entity must be checked too).
- *
- * As a consequence, its parent entities are
- * active as well, and thus this loop must
- * stop here.
- */
- break;
- }
-
- /*
- * The decrement of num_groups_with_pending_reqs is
- * not performed immediately upon the deactivation of
- * entity, but it is delayed to when it also happens
- * that the first leaf descendant bfqq of entity gets
- * all its pending requests completed. The following
- * instructions perform this delayed decrement, if
- * needed. See the comments on
- * num_groups_with_pending_reqs for details.
- */
- if (entity->in_groups_with_pending_reqs) {
- entity->in_groups_with_pending_reqs = false;
- bfqd->num_groups_with_pending_reqs--;
- }
- }
-
- /*
- * Next function is invoked last, because it causes bfqq to be
- * freed if the following holds: bfqq is not in service and
- * has no dispatched request. DO NOT use bfqq after the next
- * function invocation.
- */
- __bfq_weights_tree_remove(bfqd, bfqq,
- &bfqd->queue_weights_tree);
-}
-
-/*
* Return expired entry, or NULL to just start from scratch in rbtree.
*/
static struct request *bfq_check_fifo(struct bfq_queue *bfqq,
@@ -2135,7 +2083,9 @@ static void bfq_check_waker(struct bfq_data *bfqd, struct bfq_queue *bfqq,
if (!bfqd->last_completed_rq_bfqq ||
bfqd->last_completed_rq_bfqq == bfqq ||
bfq_bfqq_has_short_ttime(bfqq) ||
- now_ns - bfqd->last_completion >= 4 * NSEC_PER_MSEC)
+ now_ns - bfqd->last_completion >= 4 * NSEC_PER_MSEC ||
+ bfqd->last_completed_rq_bfqq == &bfqd->oom_bfqq ||
+ bfqq == &bfqd->oom_bfqq)
return;
/*
@@ -2373,22 +2323,6 @@ static sector_t get_sdist(sector_t last_pos, struct request *rq)
return 0;
}
-#if 0 /* Still not clear if we can do without next two functions */
-static void bfq_activate_request(struct request_queue *q, struct request *rq)
-{
- struct bfq_data *bfqd = q->elevator->elevator_data;
-
- bfqd->rq_in_driver++;
-}
-
-static void bfq_deactivate_request(struct request_queue *q, struct request *rq)
-{
- struct bfq_data *bfqd = q->elevator->elevator_data;
-
- bfqd->rq_in_driver--;
-}
-#endif
-
static void bfq_remove_request(struct request_queue *q,
struct request *rq)
{
@@ -6261,7 +6195,8 @@ static void bfq_completed_request(struct bfq_queue *bfqq, struct bfq_data *bfqd)
*/
bfqq->budget_timeout = jiffies;
- bfq_weights_tree_remove(bfqd, bfqq);
+ bfq_del_bfqq_in_groups_with_pending_reqs(bfqq);
+ bfq_weights_tree_remove(bfqq);
}
now_ns = ktime_get_ns();
@@ -6784,6 +6719,12 @@ static struct bfq_queue *bfq_init_rq(struct request *rq)
bfqq = bfq_get_bfqq_handle_split(bfqd, bic, bio,
true, is_sync,
NULL);
+ if (unlikely(bfqq == &bfqd->oom_bfqq))
+ bfqq_already_existing = true;
+ } else
+ bfqq_already_existing = true;
+
+ if (!bfqq_already_existing) {
bfqq->waker_bfqq = old_bfqq->waker_bfqq;
bfqq->tentative_waker_bfqq = NULL;
@@ -6797,8 +6738,7 @@ static struct bfq_queue *bfq_init_rq(struct request *rq)
if (bfqq->waker_bfqq)
hlist_add_head(&bfqq->woken_list_node,
&bfqq->waker_bfqq->woken_list);
- } else
- bfqq_already_existing = true;
+ }
}
}
@@ -7045,6 +6985,7 @@ static void bfq_exit_queue(struct elevator_queue *e)
#endif
blk_stat_disable_accounting(bfqd->queue);
+ clear_bit(ELEVATOR_FLAG_DISABLE_WBT, &e->flags);
wbt_enable_default(bfqd->queue);
kfree(bfqd);
@@ -7190,6 +7131,7 @@ static int bfq_init_queue(struct request_queue *q, struct elevator_type *e)
/* We dispatch from request queue wide instead of hw queue */
blk_queue_flag_set(QUEUE_FLAG_SQ_SCHED, q);
+ set_bit(ELEVATOR_FLAG_DISABLE_WBT, &eq->flags);
wbt_disable_default(q);
blk_stat_enable_accounting(q);
diff --git a/block/bfq-iosched.h b/block/bfq-iosched.h
index 71f721670ab6..9fa89577322d 100644
--- a/block/bfq-iosched.h
+++ b/block/bfq-iosched.h
@@ -492,27 +492,27 @@ struct bfq_data {
struct rb_root_cached queue_weights_tree;
/*
- * Number of groups with at least one descendant process that
+ * Number of groups with at least one process that
* has at least one request waiting for completion. Note that
* this accounts for also requests already dispatched, but not
* yet completed. Therefore this number of groups may differ
* (be larger) than the number of active groups, as a group is
* considered active only if its corresponding entity has
- * descendant queues with at least one request queued. This
+ * queues with at least one request queued. This
* number is used to decide whether a scenario is symmetric.
* For a detailed explanation see comments on the computation
* of the variable asymmetric_scenario in the function
* bfq_better_to_idle().
*
* However, it is hard to compute this number exactly, for
- * groups with multiple descendant processes. Consider a group
- * that is inactive, i.e., that has no descendant process with
+ * groups with multiple processes. Consider a group
+ * that is inactive, i.e., that has no process with
* pending I/O inside BFQ queues. Then suppose that
* num_groups_with_pending_reqs is still accounting for this
- * group, because the group has descendant processes with some
+ * group, because the group has processes with some
* I/O request still in flight. num_groups_with_pending_reqs
* should be decremented when the in-flight request of the
- * last descendant process is finally completed (assuming that
+ * last process is finally completed (assuming that
* nothing else has changed for the group in the meantime, in
* terms of composition of the group and active/inactive state of child
* groups and processes). To accomplish this, an additional
@@ -521,7 +521,7 @@ struct bfq_data {
* we resort to the following tradeoff between simplicity and
* accuracy: for an inactive group that is still counted in
* num_groups_with_pending_reqs, we decrement
- * num_groups_with_pending_reqs when the first descendant
+ * num_groups_with_pending_reqs when the first
* process of the group remains with no request waiting for
* completion.
*
@@ -529,12 +529,12 @@ struct bfq_data {
* carefulness: to avoid multiple decrements, we flag a group,
* more precisely an entity representing a group, as still
* counted in num_groups_with_pending_reqs when it becomes
- * inactive. Then, when the first descendant queue of the
+ * inactive. Then, when the first queue of the
* entity remains with no request waiting for completion,
* num_groups_with_pending_reqs is decremented, and this flag
* is reset. After this flag is reset for the entity,
* num_groups_with_pending_reqs won't be decremented any
- * longer in case a new descendant queue of the entity remains
+ * longer in case a new queue of the entity remains
* with no request waiting for completion.
*/
unsigned int num_groups_with_pending_reqs;
@@ -931,7 +931,7 @@ struct bfq_group {
struct bfq_entity entity;
struct bfq_sched_data sched_data;
- void *bfqd;
+ struct bfq_data *bfqd;
struct bfq_queue *async_bfqq[2][IOPRIO_NR_LEVELS];
struct bfq_queue *async_idle_bfqq;
@@ -939,6 +939,7 @@ struct bfq_group {
struct bfq_entity *my_entity;
int active_entities;
+ int num_queues_with_pending_reqs;
struct rb_root rq_pos_tree;
@@ -968,13 +969,8 @@ struct bfq_queue *bic_to_bfqq(struct bfq_io_cq *bic, bool is_sync);
void bic_set_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq, bool is_sync);
struct bfq_data *bic_to_bfqd(struct bfq_io_cq *bic);
void bfq_pos_tree_add_move(struct bfq_data *bfqd, struct bfq_queue *bfqq);
-void bfq_weights_tree_add(struct bfq_data *bfqd, struct bfq_queue *bfqq,
- struct rb_root_cached *root);
-void __bfq_weights_tree_remove(struct bfq_data *bfqd,
- struct bfq_queue *bfqq,
- struct rb_root_cached *root);
-void bfq_weights_tree_remove(struct bfq_data *bfqd,
- struct bfq_queue *bfqq);
+void bfq_weights_tree_add(struct bfq_queue *bfqq);
+void bfq_weights_tree_remove(struct bfq_queue *bfqq);
void bfq_bfqq_expire(struct bfq_data *bfqd, struct bfq_queue *bfqq,
bool compensate, enum bfqq_expiration reason);
void bfq_put_queue(struct bfq_queue *bfqq);
@@ -1078,6 +1074,8 @@ void bfq_requeue_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq,
bool expiration);
void bfq_del_bfqq_busy(struct bfq_queue *bfqq, bool expiration);
void bfq_add_bfqq_busy(struct bfq_queue *bfqq);
+void bfq_add_bfqq_in_groups_with_pending_reqs(struct bfq_queue *bfqq);
+void bfq_del_bfqq_in_groups_with_pending_reqs(struct bfq_queue *bfqq);
/* --------------- end of interface of B-WF2Q+ ---------------- */
diff --git a/block/bfq-wf2q.c b/block/bfq-wf2q.c
index 8fc3da4c23bb..b02b53658ed4 100644
--- a/block/bfq-wf2q.c
+++ b/block/bfq-wf2q.c
@@ -218,6 +218,24 @@ static bool bfq_no_longer_next_in_service(struct bfq_entity *entity)
return false;
}
+static void bfq_inc_active_entities(struct bfq_entity *entity)
+{
+ struct bfq_sched_data *sd = entity->sched_data;
+ struct bfq_group *bfqg = container_of(sd, struct bfq_group, sched_data);
+
+ if (bfqg != bfqg->bfqd->root_group)
+ bfqg->active_entities++;
+}
+
+static void bfq_dec_active_entities(struct bfq_entity *entity)
+{
+ struct bfq_sched_data *sd = entity->sched_data;
+ struct bfq_group *bfqg = container_of(sd, struct bfq_group, sched_data);
+
+ if (bfqg != bfqg->bfqd->root_group)
+ bfqg->active_entities--;
+}
+
#else /* CONFIG_BFQ_GROUP_IOSCHED */
static bool bfq_update_parent_budget(struct bfq_entity *next_in_service)
@@ -230,6 +248,14 @@ static bool bfq_no_longer_next_in_service(struct bfq_entity *entity)
return true;
}
+static void bfq_inc_active_entities(struct bfq_entity *entity)
+{
+}
+
+static void bfq_dec_active_entities(struct bfq_entity *entity)
+{
+}
+
#endif /* CONFIG_BFQ_GROUP_IOSCHED */
/*
@@ -456,11 +482,6 @@ static void bfq_active_insert(struct bfq_service_tree *st,
{
struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
struct rb_node *node = &entity->rb_node;
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
- struct bfq_sched_data *sd = NULL;
- struct bfq_group *bfqg = NULL;
- struct bfq_data *bfqd = NULL;
-#endif
bfq_insert(&st->active, entity);
@@ -471,17 +492,10 @@ static void bfq_active_insert(struct bfq_service_tree *st,
bfq_update_active_tree(node);
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
- sd = entity->sched_data;
- bfqg = container_of(sd, struct bfq_group, sched_data);
- bfqd = (struct bfq_data *)bfqg->bfqd;
-#endif
if (bfqq)
list_add(&bfqq->bfqq_list, &bfqq->bfqd->active_list);
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
- if (bfqg != bfqd->root_group)
- bfqg->active_entities++;
-#endif
+
+ bfq_inc_active_entities(entity);
}
/**
@@ -558,29 +572,16 @@ static void bfq_active_extract(struct bfq_service_tree *st,
{
struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
struct rb_node *node;
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
- struct bfq_sched_data *sd = NULL;
- struct bfq_group *bfqg = NULL;
- struct bfq_data *bfqd = NULL;
-#endif
node = bfq_find_deepest(&entity->rb_node);
bfq_extract(&st->active, entity);
if (node)
bfq_update_active_tree(node);
-
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
- sd = entity->sched_data;
- bfqg = container_of(sd, struct bfq_group, sched_data);
- bfqd = (struct bfq_data *)bfqg->bfqd;
-#endif
if (bfqq)
list_del(&bfqq->bfqq_list);
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
- if (bfqg != bfqd->root_group)
- bfqg->active_entities--;
-#endif
+
+ bfq_dec_active_entities(entity);
}
/**
@@ -706,22 +707,6 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st,
if (entity->prio_changed) {
struct bfq_queue *bfqq = bfq_entity_to_bfqq(entity);
unsigned int prev_weight, new_weight;
- struct bfq_data *bfqd = NULL;
- struct rb_root_cached *root;
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
- struct bfq_sched_data *sd;
- struct bfq_group *bfqg;
-#endif
-
- if (bfqq)
- bfqd = bfqq->bfqd;
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
- else {
- sd = entity->my_sched_data;
- bfqg = container_of(sd, struct bfq_group, sched_data);
- bfqd = (struct bfq_data *)bfqg->bfqd;
- }
-#endif
/* Matches the smp_wmb() in bfq_group_set_weight. */
smp_rmb();
@@ -770,19 +755,15 @@ __bfq_entity_update_weight_prio(struct bfq_service_tree *old_st,
* queue, remove the entity from its old weight counter (if
* there is a counter associated with the entity).
*/
- if (prev_weight != new_weight && bfqq) {
- root = &bfqd->queue_weights_tree;
- __bfq_weights_tree_remove(bfqd, bfqq, root);
- }
+ if (prev_weight != new_weight && bfqq)
+ bfq_weights_tree_remove(bfqq);
entity->weight = new_weight;
/*
* Add the entity, if it is not a weight-raised queue,
* to the counter associated with its new weight.
*/
- if (prev_weight != new_weight && bfqq && bfqq->wr_coeff == 1) {
- /* If we get here, root has been initialized. */
- bfq_weights_tree_add(bfqd, bfqq, root);
- }
+ if (prev_weight != new_weight && bfqq && bfqq->wr_coeff == 1)
+ bfq_weights_tree_add(bfqq);
new_st->wsum += entity->weight;
@@ -984,19 +965,6 @@ static void __bfq_activate_entity(struct bfq_entity *entity,
entity->on_st_or_in_serv = true;
}
-#ifdef CONFIG_BFQ_GROUP_IOSCHED
- if (!bfq_entity_to_bfqq(entity)) { /* bfq_group */
- struct bfq_group *bfqg =
- container_of(entity, struct bfq_group, entity);
- struct bfq_data *bfqd = bfqg->bfqd;
-
- if (!entity->in_groups_with_pending_reqs) {
- entity->in_groups_with_pending_reqs = true;
- bfqd->num_groups_with_pending_reqs++;
- }
- }
-#endif
-
bfq_update_fin_time_enqueue(entity, st, backshifted);
}
@@ -1082,12 +1050,12 @@ static void __bfq_requeue_entity(struct bfq_entity *entity)
}
static void __bfq_activate_requeue_entity(struct bfq_entity *entity,
- struct bfq_sched_data *sd,
bool non_blocking_wait_rq)
{
struct bfq_service_tree *st = bfq_entity_service_tree(entity);
- if (sd->in_service_entity == entity || entity->tree == &st->active)
+ if (entity->sched_data->in_service_entity == entity ||
+ entity->tree == &st->active)
/*
* in service or already queued on the active tree,
* requeue or reposition
@@ -1119,14 +1087,10 @@ static void bfq_activate_requeue_entity(struct bfq_entity *entity,
bool non_blocking_wait_rq,
bool requeue, bool expiration)
{
- struct bfq_sched_data *sd;
-
for_each_entity(entity) {
- sd = entity->sched_data;
- __bfq_activate_requeue_entity(entity, sd, non_blocking_wait_rq);
-
- if (!bfq_update_next_in_service(sd, entity, expiration) &&
- !requeue)
+ __bfq_activate_requeue_entity(entity, non_blocking_wait_rq);
+ if (!bfq_update_next_in_service(entity->sched_data, entity,
+ expiration) && !requeue)
break;
}
}
@@ -1646,6 +1610,32 @@ void bfq_requeue_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq,
bfqq == bfqd->in_service_queue, expiration);
}
+void bfq_add_bfqq_in_groups_with_pending_reqs(struct bfq_queue *bfqq)
+{
+ struct bfq_entity *entity = &bfqq->entity;
+
+ if (!entity->in_groups_with_pending_reqs) {
+ entity->in_groups_with_pending_reqs = true;
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
+ if (!(bfqq_group(bfqq)->num_queues_with_pending_reqs++))
+ bfqq->bfqd->num_groups_with_pending_reqs++;
+#endif
+ }
+}
+
+void bfq_del_bfqq_in_groups_with_pending_reqs(struct bfq_queue *bfqq)
+{
+ struct bfq_entity *entity = &bfqq->entity;
+
+ if (entity->in_groups_with_pending_reqs) {
+ entity->in_groups_with_pending_reqs = false;
+#ifdef CONFIG_BFQ_GROUP_IOSCHED
+ if (!(--bfqq_group(bfqq)->num_queues_with_pending_reqs))
+ bfqq->bfqd->num_groups_with_pending_reqs--;
+#endif
+ }
+}
+
/*
* Called when the bfqq no longer has requests pending, remove it from
* the service tree. As a special case, it can be invoked during an
@@ -1668,8 +1658,14 @@ void bfq_del_bfqq_busy(struct bfq_queue *bfqq, bool expiration)
bfq_deactivate_bfqq(bfqd, bfqq, true, expiration);
- if (!bfqq->dispatched)
- bfq_weights_tree_remove(bfqd, bfqq);
+ if (!bfqq->dispatched) {
+ bfq_del_bfqq_in_groups_with_pending_reqs(bfqq);
+ /*
+ * Next function is invoked last, because it causes bfqq to be
+ * freed. DO NOT use bfqq after the next function invocation.
+ */
+ bfq_weights_tree_remove(bfqq);
+ }
}
/*
@@ -1686,10 +1682,11 @@ void bfq_add_bfqq_busy(struct bfq_queue *bfqq)
bfq_mark_bfqq_busy(bfqq);
bfqd->busy_queues[bfqq->ioprio_class - 1]++;
- if (!bfqq->dispatched)
+ if (!bfqq->dispatched) {
+ bfq_add_bfqq_in_groups_with_pending_reqs(bfqq);
if (bfqq->wr_coeff == 1)
- bfq_weights_tree_add(bfqd, bfqq,
- &bfqd->queue_weights_tree);
+ bfq_weights_tree_add(bfqq);
+ }
if (bfqq->wr_coeff > 1)
bfqd->wr_busy_queues++;
diff --git a/block/bio.c b/block/bio.c
index 57c2f327225b..5f96fcae3f75 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -25,9 +25,15 @@
#include "blk-rq-qos.h"
#include "blk-cgroup.h"
+#define ALLOC_CACHE_THRESHOLD 16
+#define ALLOC_CACHE_SLACK 64
+#define ALLOC_CACHE_MAX 256
+
struct bio_alloc_cache {
struct bio *free_list;
+ struct bio *free_list_irq;
unsigned int nr;
+ unsigned int nr_irq;
};
static struct biovec_slab {
@@ -408,6 +414,22 @@ static void punt_bios_to_rescuer(struct bio_set *bs)
queue_work(bs->rescue_workqueue, &bs->rescue_work);
}
+static void bio_alloc_irq_cache_splice(struct bio_alloc_cache *cache)
+{
+ unsigned long flags;
+
+ /* cache->free_list must be empty */
+ if (WARN_ON_ONCE(cache->free_list))
+ return;
+
+ local_irq_save(flags);
+ cache->free_list = cache->free_list_irq;
+ cache->free_list_irq = NULL;
+ cache->nr += cache->nr_irq;
+ cache->nr_irq = 0;
+ local_irq_restore(flags);
+}
+
static struct bio *bio_alloc_percpu_cache(struct block_device *bdev,
unsigned short nr_vecs, blk_opf_t opf, gfp_t gfp,
struct bio_set *bs)
@@ -417,8 +439,12 @@ static struct bio *bio_alloc_percpu_cache(struct block_device *bdev,
cache = per_cpu_ptr(bs->cache, get_cpu());
if (!cache->free_list) {
- put_cpu();
- return NULL;
+ if (READ_ONCE(cache->nr_irq) >= ALLOC_CACHE_THRESHOLD)
+ bio_alloc_irq_cache_splice(cache);
+ if (!cache->free_list) {
+ put_cpu();
+ return NULL;
+ }
}
bio = cache->free_list;
cache->free_list = bio->bi_next;
@@ -462,9 +488,6 @@ static struct bio *bio_alloc_percpu_cache(struct block_device *bdev,
* submit_bio_noacct() should be avoided - instead, use bio_set's front_pad
* for per bio allocations.
*
- * If REQ_ALLOC_CACHE is set, the final put of the bio MUST be done from process
- * context, not hard/soft IRQ.
- *
* Returns: Pointer to new bio on success, NULL on failure.
*/
struct bio *bio_alloc_bioset(struct block_device *bdev, unsigned short nr_vecs,
@@ -526,6 +549,8 @@ struct bio *bio_alloc_bioset(struct block_device *bdev, unsigned short nr_vecs,
}
if (unlikely(!p))
return NULL;
+ if (!mempool_is_saturated(&bs->bio_pool))
+ opf &= ~REQ_ALLOC_CACHE;
bio = p + bs->front_pad;
if (nr_vecs > BIO_INLINE_VECS) {
@@ -676,11 +701,8 @@ void guard_bio_eod(struct bio *bio)
bio_truncate(bio, maxsector << 9);
}
-#define ALLOC_CACHE_MAX 512
-#define ALLOC_CACHE_SLACK 64
-
-static void bio_alloc_cache_prune(struct bio_alloc_cache *cache,
- unsigned int nr)
+static int __bio_alloc_cache_prune(struct bio_alloc_cache *cache,
+ unsigned int nr)
{
unsigned int i = 0;
struct bio *bio;
@@ -692,6 +714,17 @@ static void bio_alloc_cache_prune(struct bio_alloc_cache *cache,
if (++i == nr)
break;
}
+ return i;
+}
+
+static void bio_alloc_cache_prune(struct bio_alloc_cache *cache,
+ unsigned int nr)
+{
+ nr -= __bio_alloc_cache_prune(cache, nr);
+ if (!READ_ONCE(cache->free_list)) {
+ bio_alloc_irq_cache_splice(cache);
+ __bio_alloc_cache_prune(cache, nr);
+ }
}
static int bio_cpu_dead(unsigned int cpu, struct hlist_node *node)
@@ -725,6 +758,35 @@ static void bio_alloc_cache_destroy(struct bio_set *bs)
bs->cache = NULL;
}
+static inline void bio_put_percpu_cache(struct bio *bio)
+{
+ struct bio_alloc_cache *cache;
+
+ cache = per_cpu_ptr(bio->bi_pool->cache, get_cpu());
+ if (READ_ONCE(cache->nr_irq) + cache->nr > ALLOC_CACHE_MAX) {
+ put_cpu();
+ bio_free(bio);
+ return;
+ }
+
+ bio_uninit(bio);
+
+ if ((bio->bi_opf & REQ_POLLED) && !WARN_ON_ONCE(in_interrupt())) {
+ bio->bi_next = cache->free_list;
+ cache->free_list = bio;
+ cache->nr++;
+ } else {
+ unsigned long flags;
+
+ local_irq_save(flags);
+ bio->bi_next = cache->free_list_irq;
+ cache->free_list_irq = bio;
+ cache->nr_irq++;
+ local_irq_restore(flags);
+ }
+ put_cpu();
+}
+
/**
* bio_put - release a reference to a bio
* @bio: bio to release reference to
@@ -740,20 +802,10 @@ void bio_put(struct bio *bio)
if (!atomic_dec_and_test(&bio->__bi_cnt))
return;
}
-
- if ((bio->bi_opf & REQ_ALLOC_CACHE) && !WARN_ON_ONCE(in_interrupt())) {
- struct bio_alloc_cache *cache;
-
- bio_uninit(bio);
- cache = per_cpu_ptr(bio->bi_pool->cache, get_cpu());
- bio->bi_next = cache->free_list;
- cache->free_list = bio;
- if (++cache->nr > ALLOC_CACHE_MAX + ALLOC_CACHE_SLACK)
- bio_alloc_cache_prune(cache, ALLOC_CACHE_SLACK);
- put_cpu();
- } else {
+ if (bio->bi_opf & REQ_ALLOC_CACHE)
+ bio_put_percpu_cache(bio);
+ else
bio_free(bio);
- }
}
EXPORT_SYMBOL(bio_put);
@@ -863,6 +915,8 @@ static inline bool page_is_mergeable(const struct bio_vec *bv,
return false;
if (xen_domain() && !xen_biovec_phys_mergeable(bv, page))
return false;
+ if (!zone_device_pages_have_same_pgmap(bv->bv_page, page))
+ return false;
*same_page = ((vec_end_addr & PAGE_MASK) == page_addr);
if (*same_page)
@@ -1195,6 +1249,7 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
unsigned short entries_left = bio->bi_max_vecs - bio->bi_vcnt;
struct bio_vec *bv = bio->bi_io_vec + bio->bi_vcnt;
struct page **pages = (struct page **)bv;
+ unsigned int gup_flags = 0;
ssize_t size, left;
unsigned len, i = 0;
size_t offset, trim;
@@ -1208,6 +1263,9 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
BUILD_BUG_ON(PAGE_PTRS_PER_BVEC < 2);
pages += entries_left * (PAGE_PTRS_PER_BVEC - 1);
+ if (bio->bi_bdev && blk_queue_pci_p2pdma(bio->bi_bdev->bd_disk->queue))
+ gup_flags |= FOLL_PCI_P2PDMA;
+
/*
* Each segment in the iov is required to be a block size multiple.
* However, we may not be able to get the entire segment if it spans
@@ -1215,8 +1273,9 @@ static int __bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter)
* result to ensure the bio's total size is correct. The remainder of
* the iov data will be picked up in the next bio iteration.
*/
- size = iov_iter_get_pages2(iter, pages, UINT_MAX - bio->bi_iter.bi_size,
- nr_pages, &offset);
+ size = iov_iter_get_pages(iter, pages,
+ UINT_MAX - bio->bi_iter.bi_size,
+ nr_pages, &offset, gup_flags);
if (unlikely(size <= 0))
return size ? size : -EFAULT;
@@ -1342,27 +1401,6 @@ void __bio_advance(struct bio *bio, unsigned bytes)
}
EXPORT_SYMBOL(__bio_advance);
-void bio_copy_data_iter(struct bio *dst, struct bvec_iter *dst_iter,
- struct bio *src, struct bvec_iter *src_iter)
-{
- while (src_iter->bi_size && dst_iter->bi_size) {
- struct bio_vec src_bv = bio_iter_iovec(src, *src_iter);
- struct bio_vec dst_bv = bio_iter_iovec(dst, *dst_iter);
- unsigned int bytes = min(src_bv.bv_len, dst_bv.bv_len);
- void *src_buf = bvec_kmap_local(&src_bv);
- void *dst_buf = bvec_kmap_local(&dst_bv);
-
- memcpy(dst_buf, src_buf, bytes);
-
- kunmap_local(dst_buf);
- kunmap_local(src_buf);
-
- bio_advance_iter_single(src, src_iter, bytes);
- bio_advance_iter_single(dst, dst_iter, bytes);
- }
-}
-EXPORT_SYMBOL(bio_copy_data_iter);
-
/**
* bio_copy_data - copy contents of data buffers from one bio to another
* @src: source bio
@@ -1376,7 +1414,21 @@ void bio_copy_data(struct bio *dst, struct bio *src)
struct bvec_iter src_iter = src->bi_iter;
struct bvec_iter dst_iter = dst->bi_iter;
- bio_copy_data_iter(dst, &dst_iter, src, &src_iter);
+ while (src_iter.bi_size && dst_iter.bi_size) {
+ struct bio_vec src_bv = bio_iter_iovec(src, src_iter);
+ struct bio_vec dst_bv = bio_iter_iovec(dst, dst_iter);
+ unsigned int bytes = min(src_bv.bv_len, dst_bv.bv_len);
+ void *src_buf = bvec_kmap_local(&src_bv);
+ void *dst_buf = bvec_kmap_local(&dst_bv);
+
+ memcpy(dst_buf, src_buf, bytes);
+
+ kunmap_local(dst_buf);
+ kunmap_local(src_buf);
+
+ bio_advance_iter_single(src, &src_iter, bytes);
+ bio_advance_iter_single(dst, &dst_iter, bytes);
+ }
}
EXPORT_SYMBOL(bio_copy_data);
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index ed761c62ad0a..50ac0dce95b8 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -59,6 +59,37 @@ static struct workqueue_struct *blkcg_punt_bio_wq;
#define BLKG_DESTROY_BATCH_SIZE 64
+/*
+ * Lockless lists for tracking IO stats update
+ *
+ * New IO stats are stored in the percpu iostat_cpu within blkcg_gq (blkg).
+ * There are multiple blkg's (one for each block device) attached to each
+ * blkcg. The rstat code keeps track of which cpu has IO stats updated,
+ * but it doesn't know which blkg has the updated stats. If there are many
+ * block devices in a system, the cost of iterating all the blkg's to flush
+ * out the IO stats can be high. To reduce such overhead, a set of percpu
+ * lockless lists (lhead) per blkcg are used to track the set of recently
+ * updated iostat_cpu's since the last flush. An iostat_cpu will be put
+ * onto the lockless list on the update side [blk_cgroup_bio_start()] if
+ * not there yet and then removed when being flushed [blkcg_rstat_flush()].
+ * References to blkg are gotten and then put back in the process to
+ * protect against blkg removal.
+ *
+ * Return: 0 if successful or -ENOMEM if allocation fails.
+ */
+static int init_blkcg_llists(struct blkcg *blkcg)
+{
+ int cpu;
+
+ blkcg->lhead = alloc_percpu_gfp(struct llist_head, GFP_KERNEL);
+ if (!blkcg->lhead)
+ return -ENOMEM;
+
+ for_each_possible_cpu(cpu)
+ init_llist_head(per_cpu_ptr(blkcg->lhead, cpu));
+ return 0;
+}
+
/**
* blkcg_css - find the current css
*
@@ -236,8 +267,10 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct gendisk *disk,
blkg->blkcg = blkcg;
u64_stats_init(&blkg->iostat.sync);
- for_each_possible_cpu(cpu)
+ for_each_possible_cpu(cpu) {
u64_stats_init(&per_cpu_ptr(blkg->iostat_cpu, cpu)->sync);
+ per_cpu_ptr(blkg->iostat_cpu, cpu)->blkg = blkg;
+ }
for (i = 0; i < BLKCG_MAX_POLS; i++) {
struct blkcg_policy *pol = blkcg_policy[i];
@@ -577,7 +610,7 @@ EXPORT_SYMBOL_GPL(blkcg_print_blkgs);
* @pd: policy private data of interest
* @v: value to print
*
- * Print @v to @sf for the device assocaited with @pd.
+ * Print @v to @sf for the device associated with @pd.
*/
u64 __blkg_prfill_u64(struct seq_file *sf, struct blkg_policy_data *pd, u64 v)
{
@@ -765,7 +798,7 @@ EXPORT_SYMBOL_GPL(blkg_conf_prep);
/**
* blkg_conf_finish - finish up per-blkg config update
- * @ctx: blkg_conf_ctx intiailized by blkg_conf_prep()
+ * @ctx: blkg_conf_ctx initialized by blkg_conf_prep()
*
* Finish up after per-blkg config update. This function must be paired
* with blkg_conf_prep().
@@ -827,7 +860,9 @@ static void blkcg_iostat_update(struct blkcg_gq *blkg, struct blkg_iostat *cur,
static void blkcg_rstat_flush(struct cgroup_subsys_state *css, int cpu)
{
struct blkcg *blkcg = css_to_blkcg(css);
- struct blkcg_gq *blkg;
+ struct llist_head *lhead = per_cpu_ptr(blkcg->lhead, cpu);
+ struct llist_node *lnode;
+ struct blkg_iostat_set *bisc, *next_bisc;
/* Root-level stats are sourced from system-wide IO stats */
if (!cgroup_parent(css->cgroup))
@@ -835,12 +870,21 @@ static void blkcg_rstat_flush(struct cgroup_subsys_state *css, int cpu)
rcu_read_lock();
- hlist_for_each_entry_rcu(blkg, &blkcg->blkg_list, blkcg_node) {
+ lnode = llist_del_all(lhead);
+ if (!lnode)
+ goto out;
+
+ /*
+ * Iterate only the iostat_cpu's queued in the lockless list.
+ */
+ llist_for_each_entry_safe(bisc, next_bisc, lnode, lnode) {
+ struct blkcg_gq *blkg = bisc->blkg;
struct blkcg_gq *parent = blkg->parent;
- struct blkg_iostat_set *bisc = per_cpu_ptr(blkg->iostat_cpu, cpu);
struct blkg_iostat cur;
unsigned int seq;
+ WRITE_ONCE(bisc->lqueued, false);
+
/* fetch the current per-cpu values */
do {
seq = u64_stats_fetch_begin(&bisc->sync);
@@ -853,8 +897,10 @@ static void blkcg_rstat_flush(struct cgroup_subsys_state *css, int cpu)
if (parent && parent->parent)
blkcg_iostat_update(parent, &blkg->iostat.cur,
&blkg->iostat.last);
+ percpu_ref_put(&blkg->refcnt);
}
+out:
rcu_read_unlock();
}
@@ -1132,6 +1178,7 @@ static void blkcg_css_free(struct cgroup_subsys_state *css)
mutex_unlock(&blkcg_pol_mutex);
+ free_percpu(blkcg->lhead);
kfree(blkcg);
}
@@ -1139,7 +1186,6 @@ static struct cgroup_subsys_state *
blkcg_css_alloc(struct cgroup_subsys_state *parent_css)
{
struct blkcg *blkcg;
- struct cgroup_subsys_state *ret;
int i;
mutex_lock(&blkcg_pol_mutex);
@@ -1148,12 +1194,13 @@ blkcg_css_alloc(struct cgroup_subsys_state *parent_css)
blkcg = &blkcg_root;
} else {
blkcg = kzalloc(sizeof(*blkcg), GFP_KERNEL);
- if (!blkcg) {
- ret = ERR_PTR(-ENOMEM);
+ if (!blkcg)
goto unlock;
- }
}
+ if (init_blkcg_llists(blkcg))
+ goto free_blkcg;
+
for (i = 0; i < BLKCG_MAX_POLS ; i++) {
struct blkcg_policy *pol = blkcg_policy[i];
struct blkcg_policy_data *cpd;
@@ -1168,10 +1215,9 @@ blkcg_css_alloc(struct cgroup_subsys_state *parent_css)
continue;
cpd = pol->cpd_alloc_fn(GFP_KERNEL);
- if (!cpd) {
- ret = ERR_PTR(-ENOMEM);
+ if (!cpd)
goto free_pd_blkcg;
- }
+
blkcg->cpd[i] = cpd;
cpd->blkcg = blkcg;
cpd->plid = i;
@@ -1195,12 +1241,13 @@ free_pd_blkcg:
for (i--; i >= 0; i--)
if (blkcg->cpd[i])
blkcg_policy[i]->cpd_free_fn(blkcg->cpd[i]);
-
+ free_percpu(blkcg->lhead);
+free_blkcg:
if (blkcg != &blkcg_root)
kfree(blkcg);
unlock:
mutex_unlock(&blkcg_pol_mutex);
- return ret;
+ return ERR_PTR(-ENOMEM);
}
static int blkcg_css_online(struct cgroup_subsys_state *css)
@@ -1784,7 +1831,7 @@ out:
/**
* blkcg_schedule_throttle - this task needs to check for throttling
- * @gendisk: disk to throttle
+ * @disk: disk to throttle
* @use_memdelay: do we charge this to memory delay for PSI
*
* This is called by the IO controller when we know there's delay accumulated
@@ -1943,6 +1990,7 @@ static int blk_cgroup_io_type(struct bio *bio)
void blk_cgroup_bio_start(struct bio *bio)
{
+ struct blkcg *blkcg = bio->bi_blkg->blkcg;
int rwd = blk_cgroup_io_type(bio), cpu;
struct blkg_iostat_set *bis;
unsigned long flags;
@@ -1961,9 +2009,21 @@ void blk_cgroup_bio_start(struct bio *bio)
}
bis->cur.ios[rwd]++;
+ /*
+ * If the iostat_cpu isn't in a lockless list, put it into the
+ * list to indicate that a stat update is pending.
+ */
+ if (!READ_ONCE(bis->lqueued)) {
+ struct llist_head *lhead = this_cpu_ptr(blkcg->lhead);
+
+ llist_add(&bis->lnode, lhead);
+ WRITE_ONCE(bis->lqueued, true);
+ percpu_ref_get(&bis->blkg->refcnt);
+ }
+
u64_stats_update_end_irqrestore(&bis->sync, flags);
if (cgroup_subsys_on_dfl(io_cgrp_subsys))
- cgroup_rstat_updated(bio->bi_blkg->blkcg->css.cgroup, cpu);
+ cgroup_rstat_updated(blkcg->css.cgroup, cpu);
put_cpu();
}
diff --git a/block/blk-cgroup.h b/block/blk-cgroup.h
index aa2b286bc825..1e94e404eaa8 100644
--- a/block/blk-cgroup.h
+++ b/block/blk-cgroup.h
@@ -18,6 +18,7 @@
#include <linux/cgroup.h>
#include <linux/kthread.h>
#include <linux/blk-mq.h>
+#include <linux/llist.h>
struct blkcg_gq;
struct blkg_policy_data;
@@ -43,6 +44,9 @@ struct blkg_iostat {
struct blkg_iostat_set {
struct u64_stats_sync sync;
+ struct blkcg_gq *blkg;
+ struct llist_node lnode;
+ int lqueued; /* queued in llist */
struct blkg_iostat cur;
struct blkg_iostat last;
};
@@ -97,6 +101,12 @@ struct blkcg {
struct blkcg_policy_data *cpd[BLKCG_MAX_POLS];
struct list_head all_blkcgs_node;
+
+ /*
+ * List of updated percpu blkg_iostat_set's since the last flush.
+ */
+ struct llist_head __percpu *lhead;
+
#ifdef CONFIG_BLK_CGROUP_FC_APPID
char fc_app_id[FC_APPID_LEN];
#endif
diff --git a/block/blk-core.c b/block/blk-core.c
index 5487912befe8..3866b6c4cd88 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -59,13 +59,12 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(block_split);
EXPORT_TRACEPOINT_SYMBOL_GPL(block_unplug);
EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_insert);
-DEFINE_IDA(blk_queue_ida);
+static DEFINE_IDA(blk_queue_ida);
/*
* For queue allocation
*/
-struct kmem_cache *blk_requestq_cachep;
-struct kmem_cache *blk_requestq_srcu_cachep;
+static struct kmem_cache *blk_requestq_cachep;
/*
* Controlling structure to kblockd
@@ -253,19 +252,44 @@ void blk_clear_pm_only(struct request_queue *q)
}
EXPORT_SYMBOL_GPL(blk_clear_pm_only);
+static void blk_free_queue_rcu(struct rcu_head *rcu_head)
+{
+ kmem_cache_free(blk_requestq_cachep,
+ container_of(rcu_head, struct request_queue, rcu_head));
+}
+
+static void blk_free_queue(struct request_queue *q)
+{
+ percpu_ref_exit(&q->q_usage_counter);
+
+ if (q->poll_stat)
+ blk_stat_remove_callback(q, q->poll_cb);
+ blk_stat_free_callback(q->poll_cb);
+
+ blk_free_queue_stats(q->stats);
+ kfree(q->poll_stat);
+
+ if (queue_is_mq(q))
+ blk_mq_release(q);
+
+ ida_free(&blk_queue_ida, q->id);
+ call_rcu(&q->rcu_head, blk_free_queue_rcu);
+}
+
/**
* blk_put_queue - decrement the request_queue refcount
* @q: the request_queue structure to decrement the refcount for
*
- * Decrements the refcount of the request_queue kobject. When this reaches 0
- * we'll have blk_release_queue() called.
+ * Decrements the refcount of the request_queue and free it when the refcount
+ * reaches 0.
*
- * Context: Any context, but the last reference must not be dropped from
- * atomic context.
+ * Context: Can sleep.
*/
void blk_put_queue(struct request_queue *q)
{
- kobject_put(&q->kobj);
+ might_sleep();
+ if (refcount_dec_and_test(&q->refs))
+ blk_free_queue(q);
}
EXPORT_SYMBOL(blk_put_queue);
@@ -373,26 +397,20 @@ static void blk_timeout_work(struct work_struct *work)
{
}
-struct request_queue *blk_alloc_queue(int node_id, bool alloc_srcu)
+struct request_queue *blk_alloc_queue(int node_id)
{
struct request_queue *q;
- q = kmem_cache_alloc_node(blk_get_queue_kmem_cache(alloc_srcu),
- GFP_KERNEL | __GFP_ZERO, node_id);
+ q = kmem_cache_alloc_node(blk_requestq_cachep, GFP_KERNEL | __GFP_ZERO,
+ node_id);
if (!q)
return NULL;
- if (alloc_srcu) {
- blk_queue_flag_set(QUEUE_FLAG_HAS_SRCU, q);
- if (init_srcu_struct(q->srcu) != 0)
- goto fail_q;
- }
-
q->last_merge = NULL;
q->id = ida_alloc(&blk_queue_ida, GFP_KERNEL);
if (q->id < 0)
- goto fail_srcu;
+ goto fail_q;
q->stats = blk_alloc_queue_stats();
if (!q->stats)
@@ -406,8 +424,7 @@ struct request_queue *blk_alloc_queue(int node_id, bool alloc_srcu)
INIT_WORK(&q->timeout_work, blk_timeout_work);
INIT_LIST_HEAD(&q->icq_list);
- kobject_init(&q->kobj, &blk_queue_ktype);
-
+ refcount_set(&q->refs, 1);
mutex_init(&q->debugfs_mutex);
mutex_init(&q->sysfs_lock);
mutex_init(&q->sysfs_dir_lock);
@@ -434,11 +451,8 @@ fail_stats:
blk_free_queue_stats(q->stats);
fail_id:
ida_free(&blk_queue_ida, q->id);
-fail_srcu:
- if (alloc_srcu)
- cleanup_srcu_struct(q->srcu);
fail_q:
- kmem_cache_free(blk_get_queue_kmem_cache(alloc_srcu), q);
+ kmem_cache_free(blk_requestq_cachep, q);
return NULL;
}
@@ -454,7 +468,7 @@ bool blk_get_queue(struct request_queue *q)
{
if (unlikely(blk_queue_dying(q)))
return false;
- kobject_get(&q->kobj);
+ refcount_inc(&q->refs);
return true;
}
EXPORT_SYMBOL(blk_get_queue);
@@ -945,18 +959,6 @@ unsigned long bdev_start_io_acct(struct block_device *bdev,
EXPORT_SYMBOL(bdev_start_io_acct);
/**
- * bio_start_io_acct_time - start I/O accounting for bio based drivers
- * @bio: bio to start account for
- * @start_time: start time that should be passed back to bio_end_io_acct().
- */
-void bio_start_io_acct_time(struct bio *bio, unsigned long start_time)
-{
- bdev_start_io_acct(bio->bi_bdev, bio_sectors(bio),
- bio_op(bio), start_time);
-}
-EXPORT_SYMBOL_GPL(bio_start_io_acct_time);
-
-/**
* bio_start_io_acct - start I/O accounting for bio based drivers
* @bio: bio to start account for
*
@@ -1183,9 +1185,6 @@ int __init blk_dev_init(void)
sizeof_field(struct request, cmd_flags));
BUILD_BUG_ON(REQ_OP_BITS + REQ_FLAG_BITS > 8 *
sizeof_field(struct bio, bi_opf));
- BUILD_BUG_ON(ALIGN(offsetof(struct request_queue, srcu),
- __alignof__(struct request_queue)) !=
- sizeof(struct request_queue));
/* used for unplugging and affects IO latency/throughput - HIGHPRI */
kblockd_workqueue = alloc_workqueue("kblockd",
@@ -1196,10 +1195,6 @@ int __init blk_dev_init(void)
blk_requestq_cachep = kmem_cache_create("request_queue",
sizeof(struct request_queue), 0, SLAB_PANIC, NULL);
- blk_requestq_srcu_cachep = kmem_cache_create("request_queue_srcu",
- sizeof(struct request_queue) +
- sizeof(struct srcu_struct), 0, SLAB_PANIC, NULL);
-
blk_debugfs_root = debugfs_create_dir("block", NULL);
return 0;
diff --git a/block/blk-crypto-internal.h b/block/blk-crypto-internal.h
index e6818ffaddbf..a8cdaf26851e 100644
--- a/block/blk-crypto-internal.h
+++ b/block/blk-crypto-internal.h
@@ -21,9 +21,9 @@ extern const struct blk_crypto_mode blk_crypto_modes[];
#ifdef CONFIG_BLK_INLINE_ENCRYPTION
-int blk_crypto_sysfs_register(struct request_queue *q);
+int blk_crypto_sysfs_register(struct gendisk *disk);
-void blk_crypto_sysfs_unregister(struct request_queue *q);
+void blk_crypto_sysfs_unregister(struct gendisk *disk);
void bio_crypt_dun_increment(u64 dun[BLK_CRYPTO_DUN_ARRAY_SIZE],
unsigned int inc);
@@ -65,14 +65,28 @@ static inline bool blk_crypto_rq_is_encrypted(struct request *rq)
return rq->crypt_ctx;
}
+blk_status_t blk_crypto_get_keyslot(struct blk_crypto_profile *profile,
+ const struct blk_crypto_key *key,
+ struct blk_crypto_keyslot **slot_ptr);
+
+void blk_crypto_put_keyslot(struct blk_crypto_keyslot *slot);
+
+int __blk_crypto_evict_key(struct blk_crypto_profile *profile,
+ const struct blk_crypto_key *key);
+
+bool __blk_crypto_cfg_supported(struct blk_crypto_profile *profile,
+ const struct blk_crypto_config *cfg);
+
#else /* CONFIG_BLK_INLINE_ENCRYPTION */
-static inline int blk_crypto_sysfs_register(struct request_queue *q)
+static inline int blk_crypto_sysfs_register(struct gendisk *disk)
{
return 0;
}
-static inline void blk_crypto_sysfs_unregister(struct request_queue *q) { }
+static inline void blk_crypto_sysfs_unregister(struct gendisk *disk)
+{
+}
static inline bool bio_crypt_rq_ctx_compatible(struct request *rq,
struct bio *bio)
diff --git a/block/blk-crypto-profile.c b/block/blk-crypto-profile.c
index 96c511967386..0307fb0d95d3 100644
--- a/block/blk-crypto-profile.c
+++ b/block/blk-crypto-profile.c
@@ -32,6 +32,7 @@
#include <linux/wait.h>
#include <linux/blkdev.h>
#include <linux/blk-integrity.h>
+#include "blk-crypto-internal.h"
struct blk_crypto_keyslot {
atomic_t slot_refs;
diff --git a/block/blk-crypto-sysfs.c b/block/blk-crypto-sysfs.c
index fd93bd2f33b7..55268edc0625 100644
--- a/block/blk-crypto-sysfs.c
+++ b/block/blk-crypto-sysfs.c
@@ -126,8 +126,9 @@ static struct kobj_type blk_crypto_ktype = {
* If the request_queue has a blk_crypto_profile, create the "crypto"
* subdirectory in sysfs (/sys/block/$disk/queue/crypto/).
*/
-int blk_crypto_sysfs_register(struct request_queue *q)
+int blk_crypto_sysfs_register(struct gendisk *disk)
{
+ struct request_queue *q = disk->queue;
struct blk_crypto_kobj *obj;
int err;
@@ -139,8 +140,8 @@ int blk_crypto_sysfs_register(struct request_queue *q)
return -ENOMEM;
obj->profile = q->crypto_profile;
- err = kobject_init_and_add(&obj->kobj, &blk_crypto_ktype, &q->kobj,
- "crypto");
+ err = kobject_init_and_add(&obj->kobj, &blk_crypto_ktype,
+ &disk->queue_kobj, "crypto");
if (err) {
kobject_put(&obj->kobj);
return err;
@@ -149,9 +150,9 @@ int blk_crypto_sysfs_register(struct request_queue *q)
return 0;
}
-void blk_crypto_sysfs_unregister(struct request_queue *q)
+void blk_crypto_sysfs_unregister(struct gendisk *disk)
{
- kobject_put(q->crypto_kobject);
+ kobject_put(disk->queue->crypto_kobject);
}
static int __init blk_crypto_sysfs_init(void)
diff --git a/block/blk-crypto.c b/block/blk-crypto.c
index a496aaef85ba..45378586151f 100644
--- a/block/blk-crypto.c
+++ b/block/blk-crypto.c
@@ -36,6 +36,12 @@ const struct blk_crypto_mode blk_crypto_modes[] = {
.keysize = 32,
.ivsize = 32,
},
+ [BLK_ENCRYPTION_MODE_SM4_XTS] = {
+ .name = "SM4-XTS",
+ .cipher_str = "xts(sm4)",
+ .keysize = 32,
+ .ivsize = 16,
+ },
};
/*
@@ -267,7 +273,6 @@ bool __blk_crypto_bio_prep(struct bio **bio_ptr)
{
struct bio *bio = *bio_ptr;
const struct blk_crypto_key *bc_key = bio->bi_crypt_context->bc_key;
- struct blk_crypto_profile *profile;
/* Error if bio has no data. */
if (WARN_ON_ONCE(!bio_has_data(bio))) {
@@ -284,10 +289,9 @@ bool __blk_crypto_bio_prep(struct bio **bio_ptr)
* Success if device supports the encryption context, or if we succeeded
* in falling back to the crypto API.
*/
- profile = bdev_get_queue(bio->bi_bdev)->crypto_profile;
- if (__blk_crypto_cfg_supported(profile, &bc_key->crypto_cfg))
+ if (blk_crypto_config_supported_natively(bio->bi_bdev,
+ &bc_key->crypto_cfg))
return true;
-
if (blk_crypto_fallback_bio_prep(bio_ptr))
return true;
fail:
@@ -352,22 +356,29 @@ int blk_crypto_init_key(struct blk_crypto_key *blk_key, const u8 *raw_key,
return 0;
}
+bool blk_crypto_config_supported_natively(struct block_device *bdev,
+ const struct blk_crypto_config *cfg)
+{
+ return __blk_crypto_cfg_supported(bdev_get_queue(bdev)->crypto_profile,
+ cfg);
+}
+
/*
* Check if bios with @cfg can be en/decrypted by blk-crypto (i.e. either the
- * request queue it's submitted to supports inline crypto, or the
+ * block_device it's submitted to supports inline crypto, or the
* blk-crypto-fallback is enabled and supports the cfg).
*/
-bool blk_crypto_config_supported(struct request_queue *q,
+bool blk_crypto_config_supported(struct block_device *bdev,
const struct blk_crypto_config *cfg)
{
return IS_ENABLED(CONFIG_BLK_INLINE_ENCRYPTION_FALLBACK) ||
- __blk_crypto_cfg_supported(q->crypto_profile, cfg);
+ blk_crypto_config_supported_natively(bdev, cfg);
}
/**
* blk_crypto_start_using_key() - Start using a blk_crypto_key on a device
+ * @bdev: block device to operate on
* @key: A key to use on the device
- * @q: the request queue for the device
*
* Upper layers must call this function to ensure that either the hardware
* supports the key's crypto settings, or the crypto API fallback has transforms
@@ -379,10 +390,10 @@ bool blk_crypto_config_supported(struct request_queue *q,
* blk-crypto-fallback is either disabled or the needed algorithm
* is disabled in the crypto API; or another -errno code.
*/
-int blk_crypto_start_using_key(const struct blk_crypto_key *key,
- struct request_queue *q)
+int blk_crypto_start_using_key(struct block_device *bdev,
+ const struct blk_crypto_key *key)
{
- if (__blk_crypto_cfg_supported(q->crypto_profile, &key->crypto_cfg))
+ if (blk_crypto_config_supported_natively(bdev, &key->crypto_cfg))
return 0;
return blk_crypto_fallback_start_using_mode(key->crypto_cfg.crypto_mode);
}
@@ -390,7 +401,7 @@ int blk_crypto_start_using_key(const struct blk_crypto_key *key,
/**
* blk_crypto_evict_key() - Evict a key from any inline encryption hardware
* it may have been programmed into
- * @q: The request queue who's associated inline encryption hardware this key
+ * @bdev: The block_device who's associated inline encryption hardware this key
* might have been programmed into
* @key: The key to evict
*
@@ -400,14 +411,16 @@ int blk_crypto_start_using_key(const struct blk_crypto_key *key,
*
* Return: 0 on success or if the key wasn't in any keyslot; -errno on error.
*/
-int blk_crypto_evict_key(struct request_queue *q,
+int blk_crypto_evict_key(struct block_device *bdev,
const struct blk_crypto_key *key)
{
- if (__blk_crypto_cfg_supported(q->crypto_profile, &key->crypto_cfg))
+ struct request_queue *q = bdev_get_queue(bdev);
+
+ if (blk_crypto_config_supported_natively(bdev, &key->crypto_cfg))
return __blk_crypto_evict_key(q->crypto_profile, key);
/*
- * If the request_queue didn't support the key, then blk-crypto-fallback
+ * If the block_device didn't support the key, then blk-crypto-fallback
* may have been used, so try to evict the key from blk-crypto-fallback.
*/
return blk_crypto_fallback_evict_key(key);
diff --git a/block/blk-ia-ranges.c b/block/blk-ia-ranges.c
index 2bd1d311033b..2141931ddd37 100644
--- a/block/blk-ia-ranges.c
+++ b/block/blk-ia-ranges.c
@@ -123,7 +123,8 @@ int disk_register_independent_access_ranges(struct gendisk *disk)
*/
WARN_ON(iars->sysfs_registered);
ret = kobject_init_and_add(&iars->kobj, &blk_ia_ranges_ktype,
- &q->kobj, "%s", "independent_access_ranges");
+ &disk->queue_kobj, "%s",
+ "independent_access_ranges");
if (ret) {
disk->ia_ranges = NULL;
kobject_put(&iars->kobj);
diff --git a/block/blk-iocost.c b/block/blk-iocost.c
index 495396425bad..d1bdc12deaa7 100644
--- a/block/blk-iocost.c
+++ b/block/blk-iocost.c
@@ -111,7 +111,7 @@
* busy signal.
*
* As devices can have deep queues and be unfair in how the queued commands
- * are executed, soley depending on rq wait may not result in satisfactory
+ * are executed, solely depending on rq wait may not result in satisfactory
* control quality. For a better control quality, completion latency QoS
* parameters can be configured so that the device is considered saturated
* if N'th percentile completion latency rises above the set point.
@@ -556,7 +556,6 @@ struct ioc_now {
u64 now_ns;
u64 now;
u64 vnow;
- u64 vrate;
};
struct iocg_wait {
@@ -906,8 +905,10 @@ static bool ioc_refresh_params(struct ioc *ioc, bool force)
if (idx == ioc->autop_idx && !force)
return false;
- if (idx != ioc->autop_idx)
+ if (idx != ioc->autop_idx) {
atomic64_set(&ioc->vtime_rate, VTIME_PER_USEC);
+ ioc->vtime_base_rate = VTIME_PER_USEC;
+ }
ioc->autop_idx = idx;
ioc->autop_too_fast_at = 0;
@@ -975,7 +976,7 @@ static void ioc_adjust_base_vrate(struct ioc *ioc, u32 rq_wait_pct,
if (!ioc->busy_level || (ioc->busy_level < 0 && nr_lagging)) {
if (ioc->busy_level != prev_busy_level || nr_lagging)
- trace_iocost_ioc_vrate_adj(ioc, atomic64_read(&ioc->vtime_rate),
+ trace_iocost_ioc_vrate_adj(ioc, vrate,
missed_ppm, rq_wait_pct,
nr_lagging, nr_shortages);
@@ -1018,10 +1019,11 @@ static void ioc_adjust_base_vrate(struct ioc *ioc, u32 rq_wait_pct,
static void ioc_now(struct ioc *ioc, struct ioc_now *now)
{
unsigned seq;
+ u64 vrate;
now->now_ns = ktime_get();
now->now = ktime_to_us(now->now_ns);
- now->vrate = atomic64_read(&ioc->vtime_rate);
+ vrate = atomic64_read(&ioc->vtime_rate);
/*
* The current vtime is
@@ -1034,7 +1036,7 @@ static void ioc_now(struct ioc *ioc, struct ioc_now *now)
do {
seq = read_seqcount_begin(&ioc->period_seqcount);
now->vnow = ioc->period_at_vtime +
- (now->now - ioc->period_at) * now->vrate;
+ (now->now - ioc->period_at) * vrate;
} while (read_seqcount_retry(&ioc->period_seqcount, seq));
}
@@ -2203,8 +2205,8 @@ static void ioc_timer_fn(struct timer_list *timer)
LIST_HEAD(surpluses);
int nr_debtors, nr_shortages = 0, nr_lagging = 0;
u64 usage_us_sum = 0;
- u32 ppm_rthr = MILLION - ioc->params.qos[QOS_RPPM];
- u32 ppm_wthr = MILLION - ioc->params.qos[QOS_WPPM];
+ u32 ppm_rthr;
+ u32 ppm_wthr;
u32 missed_ppm[2], rq_wait_pct;
u64 period_vtime;
int prev_busy_level;
@@ -2215,6 +2217,8 @@ static void ioc_timer_fn(struct timer_list *timer)
/* take care of active iocgs */
spin_lock_irq(&ioc->lock);
+ ppm_rthr = MILLION - ioc->params.qos[QOS_RPPM];
+ ppm_wthr = MILLION - ioc->params.qos[QOS_WPPM];
ioc_now(ioc, &now);
period_vtime = now.vnow - ioc->period_at_vtime;
@@ -2878,7 +2882,7 @@ static int blk_iocost_init(struct gendisk *disk)
spin_unlock_irq(&ioc->lock);
/*
- * rqos must be added before activation to allow iocg_pd_init() to
+ * rqos must be added before activation to allow ioc_pd_init() to
* lookup the ioc from q. This means that the rqos methods may get
* called before policy activation completion, can't assume that the
* target bio has an iocg associated and need to test for NULL iocg.
@@ -3187,11 +3191,13 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
ioc = q_to_ioc(disk->queue);
}
+ blk_mq_freeze_queue(disk->queue);
+ blk_mq_quiesce_queue(disk->queue);
+
spin_lock_irq(&ioc->lock);
memcpy(qos, ioc->params.qos, sizeof(qos));
enable = ioc->enabled;
user = ioc->user_qos_params;
- spin_unlock_irq(&ioc->lock);
while ((p = strsep(&input, " \t\n"))) {
substring_t args[MAX_OPT_ARGS];
@@ -3258,15 +3264,15 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
if (qos[QOS_MIN] > qos[QOS_MAX])
goto einval;
- spin_lock_irq(&ioc->lock);
-
if (enable) {
blk_stat_enable_accounting(disk->queue);
blk_queue_flag_set(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue);
ioc->enabled = true;
+ wbt_disable_default(disk->queue);
} else {
blk_queue_flag_clear(QUEUE_FLAG_RQ_ALLOC_TIME, disk->queue);
ioc->enabled = false;
+ wbt_enable_default(disk->queue);
}
if (user) {
@@ -3279,9 +3285,17 @@ static ssize_t ioc_qos_write(struct kernfs_open_file *of, char *input,
ioc_refresh_params(ioc, true);
spin_unlock_irq(&ioc->lock);
+ blk_mq_unquiesce_queue(disk->queue);
+ blk_mq_unfreeze_queue(disk->queue);
+
blkdev_put_no_open(bdev);
return nbytes;
einval:
+ spin_unlock_irq(&ioc->lock);
+
+ blk_mq_unquiesce_queue(disk->queue);
+ blk_mq_unfreeze_queue(disk->queue);
+
ret = -EINVAL;
err:
blkdev_put_no_open(bdev);
@@ -3336,6 +3350,7 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
size_t nbytes, loff_t off)
{
struct block_device *bdev;
+ struct request_queue *q;
struct ioc *ioc;
u64 u[NR_I_LCOEFS];
bool user;
@@ -3346,18 +3361,21 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
if (IS_ERR(bdev))
return PTR_ERR(bdev);
- ioc = q_to_ioc(bdev_get_queue(bdev));
+ q = bdev_get_queue(bdev);
+ ioc = q_to_ioc(q);
if (!ioc) {
ret = blk_iocost_init(bdev->bd_disk);
if (ret)
goto err;
- ioc = q_to_ioc(bdev_get_queue(bdev));
+ ioc = q_to_ioc(q);
}
+ blk_mq_freeze_queue(q);
+ blk_mq_quiesce_queue(q);
+
spin_lock_irq(&ioc->lock);
memcpy(u, ioc->params.i_lcoefs, sizeof(u));
user = ioc->user_cost_model;
- spin_unlock_irq(&ioc->lock);
while ((p = strsep(&input, " \t\n"))) {
substring_t args[MAX_OPT_ARGS];
@@ -3394,7 +3412,6 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
user = true;
}
- spin_lock_irq(&ioc->lock);
if (user) {
memcpy(ioc->params.i_lcoefs, u, sizeof(u));
ioc->user_cost_model = true;
@@ -3404,10 +3421,18 @@ static ssize_t ioc_cost_model_write(struct kernfs_open_file *of, char *input,
ioc_refresh_params(ioc, true);
spin_unlock_irq(&ioc->lock);
+ blk_mq_unquiesce_queue(q);
+ blk_mq_unfreeze_queue(q);
+
blkdev_put_no_open(bdev);
return nbytes;
einval:
+ spin_unlock_irq(&ioc->lock);
+
+ blk_mq_unquiesce_queue(q);
+ blk_mq_unfreeze_queue(q);
+
ret = -EINVAL;
err:
blkdev_put_no_open(bdev);
diff --git a/block/blk-iolatency.c b/block/blk-iolatency.c
index 571fa95aafe9..778a0057193e 100644
--- a/block/blk-iolatency.c
+++ b/block/blk-iolatency.c
@@ -141,7 +141,7 @@ struct iolatency_grp {
struct latency_stat __percpu *stats;
struct latency_stat cur_stat;
struct blk_iolatency *blkiolat;
- struct rq_depth rq_depth;
+ unsigned int max_depth;
struct rq_wait rq_wait;
atomic64_t window_start;
atomic_t scale_cookie;
@@ -280,7 +280,7 @@ static void iolat_cleanup_cb(struct rq_wait *rqw, void *private_data)
static bool iolat_acquire_inflight(struct rq_wait *rqw, void *private_data)
{
struct iolatency_grp *iolat = private_data;
- return rq_wait_inc_below(rqw, iolat->rq_depth.max_depth);
+ return rq_wait_inc_below(rqw, iolat->max_depth);
}
static void __blkcg_iolatency_throttle(struct rq_qos *rqos,
@@ -364,15 +364,17 @@ static void scale_cookie_change(struct blk_iolatency *blkiolat,
}
/*
- * Change the queue depth of the iolatency_grp. We add/subtract 1/16th of the
+ * Change the queue depth of the iolatency_grp. We add 1/16th of the
* queue depth at a time so we don't get wild swings and hopefully dial in to
- * fairer distribution of the overall queue depth.
+ * fairer distribution of the overall queue depth. We halve the queue depth
+ * at a time so we can scale down queue depth quickly from default unlimited
+ * to target.
*/
static void scale_change(struct iolatency_grp *iolat, bool up)
{
unsigned long qd = iolat->blkiolat->rqos.q->nr_requests;
unsigned long scale = scale_amount(qd, up);
- unsigned long old = iolat->rq_depth.max_depth;
+ unsigned long old = iolat->max_depth;
if (old > qd)
old = qd;
@@ -384,12 +386,12 @@ static void scale_change(struct iolatency_grp *iolat, bool up)
if (old < qd) {
old += scale;
old = min(old, qd);
- iolat->rq_depth.max_depth = old;
+ iolat->max_depth = old;
wake_up_all(&iolat->rq_wait.wait);
}
} else {
old >>= 1;
- iolat->rq_depth.max_depth = max(old, 1UL);
+ iolat->max_depth = max(old, 1UL);
}
}
@@ -403,9 +405,6 @@ static void check_scale_change(struct iolatency_grp *iolat)
u64 scale_lat;
int direction = 0;
- if (lat_to_blkg(iolat)->parent == NULL)
- return;
-
parent = blkg_to_lat(lat_to_blkg(iolat)->parent);
if (!parent)
return;
@@ -445,7 +444,7 @@ static void check_scale_change(struct iolatency_grp *iolat)
}
/* We're as low as we can go. */
- if (iolat->rq_depth.max_depth == 1 && direction < 0) {
+ if (iolat->max_depth == 1 && direction < 0) {
blkcg_use_delay(lat_to_blkg(iolat));
return;
}
@@ -453,7 +452,7 @@ static void check_scale_change(struct iolatency_grp *iolat)
/* We're back to the default cookie, unthrottle all the things. */
if (cur_cookie == DEFAULT_SCALE_COOKIE) {
blkcg_clear_delay(lat_to_blkg(iolat));
- iolat->rq_depth.max_depth = UINT_MAX;
+ iolat->max_depth = UINT_MAX;
wake_up_all(&iolat->rq_wait.wait);
return;
}
@@ -508,7 +507,7 @@ static void iolatency_record_time(struct iolatency_grp *iolat,
* We don't want to count issue_as_root bio's in the cgroups latency
* statistics as it could skew the numbers downwards.
*/
- if (unlikely(issue_as_root && iolat->rq_depth.max_depth != UINT_MAX)) {
+ if (unlikely(issue_as_root && iolat->max_depth != UINT_MAX)) {
u64 sub = iolat->min_lat_nsec;
if (req_time < sub)
blkcg_add_delay(lat_to_blkg(iolat), now, sub - req_time);
@@ -920,7 +919,7 @@ static void iolatency_ssd_stat(struct iolatency_grp *iolat, struct seq_file *s)
}
preempt_enable();
- if (iolat->rq_depth.max_depth == UINT_MAX)
+ if (iolat->max_depth == UINT_MAX)
seq_printf(s, " missed=%llu total=%llu depth=max",
(unsigned long long)stat.ps.missed,
(unsigned long long)stat.ps.total);
@@ -928,7 +927,7 @@ static void iolatency_ssd_stat(struct iolatency_grp *iolat, struct seq_file *s)
seq_printf(s, " missed=%llu total=%llu depth=%u",
(unsigned long long)stat.ps.missed,
(unsigned long long)stat.ps.total,
- iolat->rq_depth.max_depth);
+ iolat->max_depth);
}
static void iolatency_pd_stat(struct blkg_policy_data *pd, struct seq_file *s)
@@ -945,12 +944,12 @@ static void iolatency_pd_stat(struct blkg_policy_data *pd, struct seq_file *s)
avg_lat = div64_u64(iolat->lat_avg, NSEC_PER_USEC);
cur_win = div64_u64(iolat->cur_win_nsec, NSEC_PER_MSEC);
- if (iolat->rq_depth.max_depth == UINT_MAX)
+ if (iolat->max_depth == UINT_MAX)
seq_printf(s, " depth=max avg_lat=%llu win=%llu",
avg_lat, cur_win);
else
seq_printf(s, " depth=%u avg_lat=%llu win=%llu",
- iolat->rq_depth.max_depth, avg_lat, cur_win);
+ iolat->max_depth, avg_lat, cur_win);
}
static struct blkg_policy_data *iolatency_pd_alloc(gfp_t gfp,
@@ -994,9 +993,7 @@ static void iolatency_pd_init(struct blkg_policy_data *pd)
latency_stat_init(iolat, &iolat->cur_stat);
rq_wait_init(&iolat->rq_wait);
spin_lock_init(&iolat->child_lat.lock);
- iolat->rq_depth.queue_depth = blkg->q->nr_requests;
- iolat->rq_depth.max_depth = UINT_MAX;
- iolat->rq_depth.default_depth = iolat->rq_depth.queue_depth;
+ iolat->max_depth = UINT_MAX;
iolat->blkiolat = blkiolat;
iolat->cur_win_nsec = 100 * NSEC_PER_MSEC;
atomic64_set(&iolat->window_start, now);
diff --git a/block/blk-map.c b/block/blk-map.c
index 34735626b00f..19940c978c73 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -267,6 +267,7 @@ static int bio_map_user_iov(struct request *rq, struct iov_iter *iter,
{
unsigned int max_sectors = queue_max_hw_sectors(rq->q);
unsigned int nr_vecs = iov_iter_npages(iter, BIO_MAX_VECS);
+ unsigned int gup_flags = 0;
struct bio *bio;
int ret;
int j;
@@ -278,6 +279,9 @@ static int bio_map_user_iov(struct request *rq, struct iov_iter *iter,
if (bio == NULL)
return -ENOMEM;
+ if (blk_queue_pci_p2pdma(rq->q))
+ gup_flags |= FOLL_PCI_P2PDMA;
+
while (iov_iter_count(iter)) {
struct page **pages, *stack_pages[UIO_FASTIOV];
ssize_t bytes;
@@ -286,11 +290,11 @@ static int bio_map_user_iov(struct request *rq, struct iov_iter *iter,
if (nr_vecs <= ARRAY_SIZE(stack_pages)) {
pages = stack_pages;
- bytes = iov_iter_get_pages2(iter, pages, LONG_MAX,
- nr_vecs, &offs);
+ bytes = iov_iter_get_pages(iter, pages, LONG_MAX,
+ nr_vecs, &offs, gup_flags);
} else {
- bytes = iov_iter_get_pages_alloc2(iter, &pages,
- LONG_MAX, &offs);
+ bytes = iov_iter_get_pages_alloc(iter, &pages,
+ LONG_MAX, &offs, gup_flags);
}
if (unlikely(bytes <= 0)) {
ret = bytes ? bytes : -EFAULT;
@@ -555,7 +559,7 @@ static int blk_rq_map_user_bvec(struct request *rq, const struct iov_iter *iter)
size_t nr_iter = iov_iter_count(iter);
size_t nr_segs = iter->nr_segs;
struct bio_vec *bvecs, *bvprvp = NULL;
- struct queue_limits *lim = &q->limits;
+ const struct queue_limits *lim = &q->limits;
unsigned int nsegs = 0, bytes = 0;
struct bio *bio;
size_t i;
diff --git a/block/blk-merge.c b/block/blk-merge.c
index ff04e9290715..35a8f75cc45d 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -100,13 +100,14 @@ static inline bool req_gap_front_merge(struct request *req, struct bio *bio)
* is defined as 'unsigned int', meantime it has to be aligned to with the
* logical block size, which is the minimum accepted unit by hardware.
*/
-static unsigned int bio_allowed_max_sectors(struct queue_limits *lim)
+static unsigned int bio_allowed_max_sectors(const struct queue_limits *lim)
{
return round_down(UINT_MAX, lim->logical_block_size) >> SECTOR_SHIFT;
}
-static struct bio *bio_split_discard(struct bio *bio, struct queue_limits *lim,
- unsigned *nsegs, struct bio_set *bs)
+static struct bio *bio_split_discard(struct bio *bio,
+ const struct queue_limits *lim,
+ unsigned *nsegs, struct bio_set *bs)
{
unsigned int max_discard_sectors, granularity;
sector_t tmp;
@@ -146,7 +147,8 @@ static struct bio *bio_split_discard(struct bio *bio, struct queue_limits *lim,
}
static struct bio *bio_split_write_zeroes(struct bio *bio,
- struct queue_limits *lim, unsigned *nsegs, struct bio_set *bs)
+ const struct queue_limits *lim,
+ unsigned *nsegs, struct bio_set *bs)
{
*nsegs = 0;
if (!lim->max_write_zeroes_sectors)
@@ -165,7 +167,7 @@ static struct bio *bio_split_write_zeroes(struct bio *bio,
* aligned to a physical block boundary.
*/
static inline unsigned get_max_io_size(struct bio *bio,
- struct queue_limits *lim)
+ const struct queue_limits *lim)
{
unsigned pbs = lim->physical_block_size >> SECTOR_SHIFT;
unsigned lbs = lim->logical_block_size >> SECTOR_SHIFT;
@@ -184,7 +186,15 @@ static inline unsigned get_max_io_size(struct bio *bio,
return max_sectors & ~(lbs - 1);
}
-static inline unsigned get_max_segment_size(struct queue_limits *lim,
+/**
+ * get_max_segment_size() - maximum number of bytes to add as a single segment
+ * @lim: Request queue limits.
+ * @start_page: See below.
+ * @offset: Offset from @start_page where to add a segment.
+ *
+ * Returns the maximum number of bytes that can be added as a single segment.
+ */
+static inline unsigned get_max_segment_size(const struct queue_limits *lim,
struct page *start_page, unsigned long offset)
{
unsigned long mask = lim->seg_boundary_mask;
@@ -192,11 +202,10 @@ static inline unsigned get_max_segment_size(struct queue_limits *lim,
offset = mask & (page_to_phys(start_page) + offset);
/*
- * overflow may be triggered in case of zero page physical address
- * on 32bit arch, use queue's max segment size when that happens.
+ * Prevent an overflow if mask = ULONG_MAX and offset = 0 by adding 1
+ * after having calculated the minimum.
*/
- return min_not_zero(mask - offset + 1,
- (unsigned long)lim->max_segment_size);
+ return min(mask - offset, (unsigned long)lim->max_segment_size - 1) + 1;
}
/**
@@ -219,9 +228,9 @@ static inline unsigned get_max_segment_size(struct queue_limits *lim,
* *@nsegs segments and *@sectors sectors would make that bio unacceptable for
* the block driver.
*/
-static bool bvec_split_segs(struct queue_limits *lim, const struct bio_vec *bv,
- unsigned *nsegs, unsigned *bytes, unsigned max_segs,
- unsigned max_bytes)
+static bool bvec_split_segs(const struct queue_limits *lim,
+ const struct bio_vec *bv, unsigned *nsegs, unsigned *bytes,
+ unsigned max_segs, unsigned max_bytes)
{
unsigned max_len = min(max_bytes, UINT_MAX) - *bytes;
unsigned len = min(bv->bv_len, max_len);
@@ -267,7 +276,7 @@ static bool bvec_split_segs(struct queue_limits *lim, const struct bio_vec *bv,
* responsible for ensuring that @bs is only destroyed after processing of the
* split bio has finished.
*/
-static struct bio *bio_split_rw(struct bio *bio, struct queue_limits *lim,
+static struct bio *bio_split_rw(struct bio *bio, const struct queue_limits *lim,
unsigned *segs, struct bio_set *bs, unsigned max_bytes)
{
struct bio_vec bv, bvprv, *bvprvp = NULL;
@@ -331,8 +340,9 @@ split:
* The split bio is allocated from @q->bio_split, which is provided by the
* block layer.
*/
-struct bio *__bio_split_to_limits(struct bio *bio, struct queue_limits *lim,
- unsigned int *nr_segs)
+struct bio *__bio_split_to_limits(struct bio *bio,
+ const struct queue_limits *lim,
+ unsigned int *nr_segs)
{
struct bio_set *bs = &bio->bi_bdev->bd_disk->bio_split;
struct bio *split;
@@ -377,7 +387,7 @@ struct bio *__bio_split_to_limits(struct bio *bio, struct queue_limits *lim,
*/
struct bio *bio_split_to_limits(struct bio *bio)
{
- struct queue_limits *lim = &bdev_get_queue(bio->bi_bdev)->limits;
+ const struct queue_limits *lim = &bdev_get_queue(bio->bi_bdev)->limits;
unsigned int nr_segs;
if (bio_may_exceed_limits(bio, lim))
diff --git a/block/blk-mq-sched.c b/block/blk-mq-sched.c
index a4f7c101b53b..23d1a90fec42 100644
--- a/block/blk-mq-sched.c
+++ b/block/blk-mq-sched.c
@@ -555,6 +555,7 @@ static int blk_mq_init_sched_shared_tags(struct request_queue *queue)
return 0;
}
+/* caller must have a reference to @e, will grab another one if successful */
int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e)
{
unsigned int flags = q->tag_set->flags;
@@ -563,13 +564,6 @@ int blk_mq_init_sched(struct request_queue *q, struct elevator_type *e)
unsigned long i;
int ret;
- if (!e) {
- blk_queue_flag_clear(QUEUE_FLAG_SQ_SCHED, q);
- q->elevator = NULL;
- q->nr_requests = q->tag_set->queue_depth;
- return 0;
- }
-
/*
* Default to double of smaller one between hw queue_depth and 128,
* since we don't split into sync/async like the old code did.
diff --git a/block/blk-mq-sysfs.c b/block/blk-mq-sysfs.c
index 93997d297d42..4515288fbe35 100644
--- a/block/blk-mq-sysfs.c
+++ b/block/blk-mq-sysfs.c
@@ -185,7 +185,7 @@ static int blk_mq_register_hctx(struct blk_mq_hw_ctx *hctx)
{
struct request_queue *q = hctx->queue;
struct blk_mq_ctx *ctx;
- int i, ret;
+ int i, j, ret;
if (!hctx->nr_ctx)
return 0;
@@ -197,9 +197,16 @@ static int blk_mq_register_hctx(struct blk_mq_hw_ctx *hctx)
hctx_for_each_ctx(hctx, ctx, i) {
ret = kobject_add(&ctx->kobj, &hctx->kobj, "cpu%u", ctx->cpu);
if (ret)
- break;
+ goto out;
}
+ return 0;
+out:
+ hctx_for_each_ctx(hctx, ctx, j) {
+ if (j < i)
+ kobject_del(&ctx->kobj);
+ }
+ kobject_del(&hctx->kobj);
return ret;
}
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 228a6696d835..c5cf0dbca1db 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -254,15 +254,17 @@ EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue_nowait);
/**
* blk_mq_wait_quiesce_done() - wait until in-progress quiesce is done
- * @q: request queue.
+ * @set: tag_set to wait on
*
* Note: it is driver's responsibility for making sure that quiesce has
- * been started.
+ * been started on or more of the request_queues of the tag_set. This
+ * function only waits for the quiesce on those request_queues that had
+ * the quiesce flag set using blk_mq_quiesce_queue_nowait.
*/
-void blk_mq_wait_quiesce_done(struct request_queue *q)
+void blk_mq_wait_quiesce_done(struct blk_mq_tag_set *set)
{
- if (blk_queue_has_srcu(q))
- synchronize_srcu(q->srcu);
+ if (set->flags & BLK_MQ_F_BLOCKING)
+ synchronize_srcu(set->srcu);
else
synchronize_rcu();
}
@@ -280,7 +282,9 @@ EXPORT_SYMBOL_GPL(blk_mq_wait_quiesce_done);
void blk_mq_quiesce_queue(struct request_queue *q)
{
blk_mq_quiesce_queue_nowait(q);
- blk_mq_wait_quiesce_done(q);
+ /* nothing to wait for non-mq queues */
+ if (queue_is_mq(q))
+ blk_mq_wait_quiesce_done(q->tag_set);
}
EXPORT_SYMBOL_GPL(blk_mq_quiesce_queue);
@@ -311,6 +315,33 @@ void blk_mq_unquiesce_queue(struct request_queue *q)
}
EXPORT_SYMBOL_GPL(blk_mq_unquiesce_queue);
+void blk_mq_quiesce_tagset(struct blk_mq_tag_set *set)
+{
+ struct request_queue *q;
+
+ mutex_lock(&set->tag_list_lock);
+ list_for_each_entry(q, &set->tag_list, tag_set_list) {
+ if (!blk_queue_skip_tagset_quiesce(q))
+ blk_mq_quiesce_queue_nowait(q);
+ }
+ blk_mq_wait_quiesce_done(set);
+ mutex_unlock(&set->tag_list_lock);
+}
+EXPORT_SYMBOL_GPL(blk_mq_quiesce_tagset);
+
+void blk_mq_unquiesce_tagset(struct blk_mq_tag_set *set)
+{
+ struct request_queue *q;
+
+ mutex_lock(&set->tag_list_lock);
+ list_for_each_entry(q, &set->tag_list, tag_set_list) {
+ if (!blk_queue_skip_tagset_quiesce(q))
+ blk_mq_unquiesce_queue(q);
+ }
+ mutex_unlock(&set->tag_list_lock);
+}
+EXPORT_SYMBOL_GPL(blk_mq_unquiesce_tagset);
+
void blk_mq_wake_waiters(struct request_queue *q)
{
struct blk_mq_hw_ctx *hctx;
@@ -544,25 +575,26 @@ static struct request *blk_mq_alloc_cached_request(struct request_queue *q,
if (!plug)
return NULL;
+
if (rq_list_empty(plug->cached_rq)) {
if (plug->nr_ios == 1)
return NULL;
rq = blk_mq_rq_cache_fill(q, plug, opf, flags);
- if (rq)
- goto got_it;
- return NULL;
- }
- rq = rq_list_peek(&plug->cached_rq);
- if (!rq || rq->q != q)
- return NULL;
+ if (!rq)
+ return NULL;
+ } else {
+ rq = rq_list_peek(&plug->cached_rq);
+ if (!rq || rq->q != q)
+ return NULL;
- if (blk_mq_get_hctx_type(opf) != rq->mq_hctx->type)
- return NULL;
- if (op_is_flush(rq->cmd_flags) != op_is_flush(opf))
- return NULL;
+ if (blk_mq_get_hctx_type(opf) != rq->mq_hctx->type)
+ return NULL;
+ if (op_is_flush(rq->cmd_flags) != op_is_flush(opf))
+ return NULL;
+
+ plug->cached_rq = rq_list_next(rq);
+ }
- plug->cached_rq = rq_list_next(rq);
-got_it:
rq->cmd_flags = opf;
INIT_LIST_HEAD(&rq->queuelist);
return rq;
@@ -1529,7 +1561,13 @@ static void blk_mq_rq_timed_out(struct request *req)
blk_add_timer(req);
}
-static bool blk_mq_req_expired(struct request *rq, unsigned long *next)
+struct blk_expired_data {
+ bool has_timedout_rq;
+ unsigned long next;
+ unsigned long timeout_start;
+};
+
+static bool blk_mq_req_expired(struct request *rq, struct blk_expired_data *expired)
{
unsigned long deadline;
@@ -1539,13 +1577,13 @@ static bool blk_mq_req_expired(struct request *rq, unsigned long *next)
return false;
deadline = READ_ONCE(rq->deadline);
- if (time_after_eq(jiffies, deadline))
+ if (time_after_eq(expired->timeout_start, deadline))
return true;
- if (*next == 0)
- *next = deadline;
- else if (time_after(*next, deadline))
- *next = deadline;
+ if (expired->next == 0)
+ expired->next = deadline;
+ else if (time_after(expired->next, deadline))
+ expired->next = deadline;
return false;
}
@@ -1561,7 +1599,7 @@ void blk_mq_put_rq_ref(struct request *rq)
static bool blk_mq_check_expired(struct request *rq, void *priv)
{
- unsigned long *next = priv;
+ struct blk_expired_data *expired = priv;
/*
* blk_mq_queue_tag_busy_iter() has locked the request, so it cannot
@@ -1570,7 +1608,18 @@ static bool blk_mq_check_expired(struct request *rq, void *priv)
* it was completed and reallocated as a new request after returning
* from blk_mq_check_expired().
*/
- if (blk_mq_req_expired(rq, next))
+ if (blk_mq_req_expired(rq, expired)) {
+ expired->has_timedout_rq = true;
+ return false;
+ }
+ return true;
+}
+
+static bool blk_mq_handle_expired(struct request *rq, void *priv)
+{
+ struct blk_expired_data *expired = priv;
+
+ if (blk_mq_req_expired(rq, expired))
blk_mq_rq_timed_out(rq);
return true;
}
@@ -1579,7 +1628,9 @@ static void blk_mq_timeout_work(struct work_struct *work)
{
struct request_queue *q =
container_of(work, struct request_queue, timeout_work);
- unsigned long next = 0;
+ struct blk_expired_data expired = {
+ .timeout_start = jiffies,
+ };
struct blk_mq_hw_ctx *hctx;
unsigned long i;
@@ -1599,10 +1650,23 @@ static void blk_mq_timeout_work(struct work_struct *work)
if (!percpu_ref_tryget(&q->q_usage_counter))
return;
- blk_mq_queue_tag_busy_iter(q, blk_mq_check_expired, &next);
+ /* check if there is any timed-out request */
+ blk_mq_queue_tag_busy_iter(q, blk_mq_check_expired, &expired);
+ if (expired.has_timedout_rq) {
+ /*
+ * Before walking tags, we must ensure any submit started
+ * before the current time has finished. Since the submit
+ * uses srcu or rcu, wait for a synchronization point to
+ * ensure all running submits have finished
+ */
+ blk_mq_wait_quiesce_done(q->tag_set);
+
+ expired.next = 0;
+ blk_mq_queue_tag_busy_iter(q, blk_mq_handle_expired, &expired);
+ }
- if (next != 0) {
- mod_timer(&q->timeout, next);
+ if (expired.next != 0) {
+ mod_timer(&q->timeout, expired.next);
} else {
/*
* Request timeouts are handled as a forward rolling timer. If
@@ -3248,21 +3312,22 @@ static struct blk_mq_tags *blk_mq_alloc_rq_map(struct blk_mq_tag_set *set,
tags->rqs = kcalloc_node(nr_tags, sizeof(struct request *),
GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY,
node);
- if (!tags->rqs) {
- blk_mq_free_tags(tags);
- return NULL;
- }
+ if (!tags->rqs)
+ goto err_free_tags;
tags->static_rqs = kcalloc_node(nr_tags, sizeof(struct request *),
GFP_NOIO | __GFP_NOWARN | __GFP_NORETRY,
node);
- if (!tags->static_rqs) {
- kfree(tags->rqs);
- blk_mq_free_tags(tags);
- return NULL;
- }
+ if (!tags->static_rqs)
+ goto err_free_rqs;
return tags;
+
+err_free_rqs:
+ kfree(tags->rqs);
+err_free_tags:
+ blk_mq_free_tags(tags);
+ return NULL;
}
static int blk_mq_init_request(struct blk_mq_tag_set *set, struct request *rq,
@@ -3975,7 +4040,7 @@ static struct request_queue *blk_mq_init_queue_data(struct blk_mq_tag_set *set,
struct request_queue *q;
int ret;
- q = blk_alloc_queue(set->numa_node, set->flags & BLK_MQ_F_BLOCKING);
+ q = blk_alloc_queue(set->numa_node);
if (!q)
return ERR_PTR(-ENOMEM);
q->queuedata = queuedata;
@@ -4011,14 +4076,11 @@ void blk_mq_destroy_queue(struct request_queue *q)
blk_queue_flag_set(QUEUE_FLAG_DYING, q);
blk_queue_start_drain(q);
- blk_freeze_queue(q);
+ blk_mq_freeze_queue_wait(q);
blk_sync_queue(q);
blk_mq_cancel_work_sync(q);
blk_mq_exit_queue(q);
-
- /* @q is and will stay empty, shutdown and put */
- blk_put_queue(q);
}
EXPORT_SYMBOL(blk_mq_destroy_queue);
@@ -4035,6 +4097,7 @@ struct gendisk *__blk_mq_alloc_disk(struct blk_mq_tag_set *set, void *queuedata,
disk = __alloc_disk_node(q, set->numa_node, lkclass);
if (!disk) {
blk_mq_destroy_queue(q);
+ blk_put_queue(q);
return ERR_PTR(-ENOMEM);
}
set_bit(GD_OWNS_QUEUE, &disk->state);
@@ -4147,9 +4210,6 @@ static void blk_mq_update_poll_flag(struct request_queue *q)
int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
struct request_queue *q)
{
- WARN_ON_ONCE(blk_queue_has_srcu(q) !=
- !!(set->flags & BLK_MQ_F_BLOCKING));
-
/* mark the queue as mq asap */
q->mq_ops = set->ops;
@@ -4325,12 +4385,12 @@ static void blk_mq_update_queue_map(struct blk_mq_tag_set *set)
}
static int blk_mq_realloc_tag_set_tags(struct blk_mq_tag_set *set,
- int cur_nr_hw_queues, int new_nr_hw_queues)
+ int new_nr_hw_queues)
{
struct blk_mq_tags **new_tags;
- if (cur_nr_hw_queues >= new_nr_hw_queues)
- return 0;
+ if (set->nr_hw_queues >= new_nr_hw_queues)
+ goto done;
new_tags = kcalloc_node(new_nr_hw_queues, sizeof(struct blk_mq_tags *),
GFP_KERNEL, set->numa_node);
@@ -4338,21 +4398,15 @@ static int blk_mq_realloc_tag_set_tags(struct blk_mq_tag_set *set,
return -ENOMEM;
if (set->tags)
- memcpy(new_tags, set->tags, cur_nr_hw_queues *
+ memcpy(new_tags, set->tags, set->nr_hw_queues *
sizeof(*set->tags));
kfree(set->tags);
set->tags = new_tags;
+done:
set->nr_hw_queues = new_nr_hw_queues;
-
return 0;
}
-static int blk_mq_alloc_tag_set_tags(struct blk_mq_tag_set *set,
- int new_nr_hw_queues)
-{
- return blk_mq_realloc_tag_set_tags(set, 0, new_nr_hw_queues);
-}
-
/*
* Alloc a tag set to be associated with one or more request queues.
* May fail with EINVAL for various error conditions. May adjust the
@@ -4406,10 +4460,22 @@ int blk_mq_alloc_tag_set(struct blk_mq_tag_set *set)
if (set->nr_maps == 1 && set->nr_hw_queues > nr_cpu_ids)
set->nr_hw_queues = nr_cpu_ids;
- if (blk_mq_alloc_tag_set_tags(set, set->nr_hw_queues) < 0)
- return -ENOMEM;
+ if (set->flags & BLK_MQ_F_BLOCKING) {
+ set->srcu = kmalloc(sizeof(*set->srcu), GFP_KERNEL);
+ if (!set->srcu)
+ return -ENOMEM;
+ ret = init_srcu_struct(set->srcu);
+ if (ret)
+ goto out_free_srcu;
+ }
ret = -ENOMEM;
+ set->tags = kcalloc_node(set->nr_hw_queues,
+ sizeof(struct blk_mq_tags *), GFP_KERNEL,
+ set->numa_node);
+ if (!set->tags)
+ goto out_cleanup_srcu;
+
for (i = 0; i < set->nr_maps; i++) {
set->map[i].mq_map = kcalloc_node(nr_cpu_ids,
sizeof(set->map[i].mq_map[0]),
@@ -4437,6 +4503,12 @@ out_free_mq_map:
}
kfree(set->tags);
set->tags = NULL;
+out_cleanup_srcu:
+ if (set->flags & BLK_MQ_F_BLOCKING)
+ cleanup_srcu_struct(set->srcu);
+out_free_srcu:
+ if (set->flags & BLK_MQ_F_BLOCKING)
+ kfree(set->srcu);
return ret;
}
EXPORT_SYMBOL(blk_mq_alloc_tag_set);
@@ -4476,6 +4548,10 @@ void blk_mq_free_tag_set(struct blk_mq_tag_set *set)
kfree(set->tags);
set->tags = NULL;
+ if (set->flags & BLK_MQ_F_BLOCKING) {
+ cleanup_srcu_struct(set->srcu);
+ kfree(set->srcu);
+ }
}
EXPORT_SYMBOL(blk_mq_free_tag_set);
@@ -4564,17 +4640,10 @@ static bool blk_mq_elv_switch_none(struct list_head *head,
INIT_LIST_HEAD(&qe->node);
qe->q = q;
qe->type = q->elevator->type;
+ /* keep a reference to the elevator module as we'll switch back */
+ __elevator_get(qe->type);
list_add(&qe->node, head);
-
- /*
- * After elevator_switch, the previous elevator_queue will be
- * released by elevator_release. The reference of the io scheduler
- * module get by elevator_get will also be put. So we need to get
- * a reference of the io scheduler module here to prevent it to be
- * removed.
- */
- __module_get(qe->type->elevator_owner);
- elevator_switch(q, NULL);
+ elevator_disable(q);
mutex_unlock(&q->sysfs_lock);
return true;
@@ -4607,6 +4676,8 @@ static void blk_mq_elv_switch_back(struct list_head *head,
mutex_lock(&q->sysfs_lock);
elevator_switch(q, t);
+ /* drop the reference acquired in blk_mq_elv_switch_none */
+ elevator_put(t);
mutex_unlock(&q->sysfs_lock);
}
@@ -4643,11 +4714,9 @@ static void __blk_mq_update_nr_hw_queues(struct blk_mq_tag_set *set,
}
prev_nr_hw_queues = set->nr_hw_queues;
- if (blk_mq_realloc_tag_set_tags(set, set->nr_hw_queues, nr_hw_queues) <
- 0)
+ if (blk_mq_realloc_tag_set_tags(set, nr_hw_queues) < 0)
goto reregister;
- set->nr_hw_queues = nr_hw_queues;
fallback:
blk_mq_update_queue_map(set);
list_for_each_entry(q, &set->tag_list, tag_set_list) {
@@ -4867,15 +4936,13 @@ EXPORT_SYMBOL(blk_mq_rq_cpu);
void blk_mq_cancel_work_sync(struct request_queue *q)
{
- if (queue_is_mq(q)) {
- struct blk_mq_hw_ctx *hctx;
- unsigned long i;
+ struct blk_mq_hw_ctx *hctx;
+ unsigned long i;
- cancel_delayed_work_sync(&q->requeue_work);
+ cancel_delayed_work_sync(&q->requeue_work);
- queue_for_each_hw_ctx(q, hctx, i)
- cancel_delayed_work_sync(&hctx->run_work);
- }
+ queue_for_each_hw_ctx(q, hctx, i)
+ cancel_delayed_work_sync(&hctx->run_work);
}
static int __init blk_mq_init(void)
diff --git a/block/blk-mq.h b/block/blk-mq.h
index 0b2870839cdd..ef59fee62780 100644
--- a/block/blk-mq.h
+++ b/block/blk-mq.h
@@ -377,17 +377,17 @@ static inline bool hctx_may_queue(struct blk_mq_hw_ctx *hctx,
/* run the code block in @dispatch_ops with rcu/srcu read lock held */
#define __blk_mq_run_dispatch_ops(q, check_sleep, dispatch_ops) \
do { \
- if (!blk_queue_has_srcu(q)) { \
- rcu_read_lock(); \
- (dispatch_ops); \
- rcu_read_unlock(); \
- } else { \
+ if ((q)->tag_set->flags & BLK_MQ_F_BLOCKING) { \
int srcu_idx; \
\
might_sleep_if(check_sleep); \
- srcu_idx = srcu_read_lock((q)->srcu); \
+ srcu_idx = srcu_read_lock((q)->tag_set->srcu); \
(dispatch_ops); \
- srcu_read_unlock((q)->srcu, srcu_idx); \
+ srcu_read_unlock((q)->tag_set->srcu, srcu_idx); \
+ } else { \
+ rcu_read_lock(); \
+ (dispatch_ops); \
+ rcu_read_unlock(); \
} \
} while (0)
diff --git a/block/blk-settings.c b/block/blk-settings.c
index 8ac1038d0c79..0477c4d527fe 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -481,7 +481,7 @@ void blk_queue_io_opt(struct request_queue *q, unsigned int opt)
}
EXPORT_SYMBOL(blk_queue_io_opt);
-static int queue_limit_alignment_offset(struct queue_limits *lim,
+static int queue_limit_alignment_offset(const struct queue_limits *lim,
sector_t sector)
{
unsigned int granularity = max(lim->physical_block_size, lim->io_min);
@@ -491,8 +491,8 @@ static int queue_limit_alignment_offset(struct queue_limits *lim,
return (granularity + lim->alignment_offset - alignment) % granularity;
}
-static unsigned int queue_limit_discard_alignment(struct queue_limits *lim,
- sector_t sector)
+static unsigned int queue_limit_discard_alignment(
+ const struct queue_limits *lim, sector_t sector)
{
unsigned int alignment, granularity, offset;
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index e71b3b43927c..93d9e9c9a6ea 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -470,6 +470,9 @@ static ssize_t queue_wb_lat_show(struct request_queue *q, char *page)
if (!wbt_rq_qos(q))
return -EINVAL;
+ if (wbt_disabled(q))
+ return sprintf(page, "0\n");
+
return sprintf(page, "%llu\n", div_u64(wbt_get_min_lat(q), 1000));
}
@@ -680,8 +683,8 @@ static struct attribute *queue_attrs[] = {
static umode_t queue_attr_visible(struct kobject *kobj, struct attribute *attr,
int n)
{
- struct request_queue *q =
- container_of(kobj, struct request_queue, kobj);
+ struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj);
+ struct request_queue *q = disk->queue;
if (attr == &queue_io_timeout_entry.attr &&
(!q->mq_ops || !q->mq_ops->timeout))
@@ -707,8 +710,8 @@ static ssize_t
queue_attr_show(struct kobject *kobj, struct attribute *attr, char *page)
{
struct queue_sysfs_entry *entry = to_queue(attr);
- struct request_queue *q =
- container_of(kobj, struct request_queue, kobj);
+ struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj);
+ struct request_queue *q = disk->queue;
ssize_t res;
if (!entry->show)
@@ -724,68 +727,19 @@ queue_attr_store(struct kobject *kobj, struct attribute *attr,
const char *page, size_t length)
{
struct queue_sysfs_entry *entry = to_queue(attr);
- struct request_queue *q;
+ struct gendisk *disk = container_of(kobj, struct gendisk, queue_kobj);
+ struct request_queue *q = disk->queue;
ssize_t res;
if (!entry->store)
return -EIO;
- q = container_of(kobj, struct request_queue, kobj);
mutex_lock(&q->sysfs_lock);
res = entry->store(q, page, length);
mutex_unlock(&q->sysfs_lock);
return res;
}
-static void blk_free_queue_rcu(struct rcu_head *rcu_head)
-{
- struct request_queue *q = container_of(rcu_head, struct request_queue,
- rcu_head);
-
- kmem_cache_free(blk_get_queue_kmem_cache(blk_queue_has_srcu(q)), q);
-}
-
-/**
- * blk_release_queue - releases all allocated resources of the request_queue
- * @kobj: pointer to a kobject, whose container is a request_queue
- *
- * This function releases all allocated resources of the request queue.
- *
- * The struct request_queue refcount is incremented with blk_get_queue() and
- * decremented with blk_put_queue(). Once the refcount reaches 0 this function
- * is called.
- *
- * Drivers exist which depend on the release of the request_queue to be
- * synchronous, it should not be deferred.
- *
- * Context: can sleep
- */
-static void blk_release_queue(struct kobject *kobj)
-{
- struct request_queue *q =
- container_of(kobj, struct request_queue, kobj);
-
- might_sleep();
-
- percpu_ref_exit(&q->q_usage_counter);
-
- if (q->poll_stat)
- blk_stat_remove_callback(q, q->poll_cb);
- blk_stat_free_callback(q->poll_cb);
-
- blk_free_queue_stats(q->stats);
- kfree(q->poll_stat);
-
- if (queue_is_mq(q))
- blk_mq_release(q);
-
- if (blk_queue_has_srcu(q))
- cleanup_srcu_struct(q->srcu);
-
- ida_free(&blk_queue_ida, q->id);
- call_rcu(&q->rcu_head, blk_free_queue_rcu);
-}
-
static const struct sysfs_ops queue_sysfs_ops = {
.show = queue_attr_show,
.store = queue_attr_store,
@@ -796,12 +750,30 @@ static const struct attribute_group *blk_queue_attr_groups[] = {
NULL
};
-struct kobj_type blk_queue_ktype = {
+static void blk_queue_release(struct kobject *kobj)
+{
+ /* nothing to do here, all data is associated with the parent gendisk */
+}
+
+static struct kobj_type blk_queue_ktype = {
.default_groups = blk_queue_attr_groups,
.sysfs_ops = &queue_sysfs_ops,
- .release = blk_release_queue,
+ .release = blk_queue_release,
};
+static void blk_debugfs_remove(struct gendisk *disk)
+{
+ struct request_queue *q = disk->queue;
+
+ mutex_lock(&q->debugfs_mutex);
+ blk_trace_shutdown(q);
+ debugfs_remove_recursive(q->debugfs_dir);
+ q->debugfs_dir = NULL;
+ q->sched_debugfs_dir = NULL;
+ q->rqos_debugfs_dir = NULL;
+ mutex_unlock(&q->debugfs_mutex);
+}
+
/**
* blk_register_queue - register a block layer queue with sysfs
* @disk: Disk of which the request queue should be registered with sysfs.
@@ -812,47 +784,47 @@ int blk_register_queue(struct gendisk *disk)
int ret;
mutex_lock(&q->sysfs_dir_lock);
-
- ret = kobject_add(&q->kobj, &disk_to_dev(disk)->kobj, "queue");
+ kobject_init(&disk->queue_kobj, &blk_queue_ktype);
+ ret = kobject_add(&disk->queue_kobj, &disk_to_dev(disk)->kobj, "queue");
if (ret < 0)
- goto unlock;
+ goto out_put_queue_kobj;
- if (queue_is_mq(q))
- blk_mq_sysfs_register(disk);
+ if (queue_is_mq(q)) {
+ ret = blk_mq_sysfs_register(disk);
+ if (ret)
+ goto out_put_queue_kobj;
+ }
mutex_lock(&q->sysfs_lock);
mutex_lock(&q->debugfs_mutex);
- q->debugfs_dir = debugfs_create_dir(kobject_name(q->kobj.parent),
- blk_debugfs_root);
+ q->debugfs_dir = debugfs_create_dir(disk->disk_name, blk_debugfs_root);
if (queue_is_mq(q))
blk_mq_debugfs_register(q);
mutex_unlock(&q->debugfs_mutex);
ret = disk_register_independent_access_ranges(disk);
if (ret)
- goto put_dev;
+ goto out_debugfs_remove;
if (q->elevator) {
ret = elv_register_queue(q, false);
if (ret)
- goto put_dev;
+ goto out_unregister_ia_ranges;
}
- ret = blk_crypto_sysfs_register(q);
+ ret = blk_crypto_sysfs_register(disk);
if (ret)
- goto put_dev;
+ goto out_elv_unregister;
blk_queue_flag_set(QUEUE_FLAG_REGISTERED, q);
wbt_enable_default(q);
blk_throtl_register(disk);
/* Now everything is ready and send out KOBJ_ADD uevent */
- kobject_uevent(&q->kobj, KOBJ_ADD);
+ kobject_uevent(&disk->queue_kobj, KOBJ_ADD);
if (q->elevator)
kobject_uevent(&q->elevator->kobj, KOBJ_ADD);
mutex_unlock(&q->sysfs_lock);
-
-unlock:
mutex_unlock(&q->sysfs_dir_lock);
/*
@@ -871,13 +843,16 @@ unlock:
return ret;
-put_dev:
+out_elv_unregister:
elv_unregister_queue(q);
+out_unregister_ia_ranges:
disk_unregister_independent_access_ranges(disk);
+out_debugfs_remove:
+ blk_debugfs_remove(disk);
mutex_unlock(&q->sysfs_lock);
+out_put_queue_kobj:
+ kobject_put(&disk->queue_kobj);
mutex_unlock(&q->sysfs_dir_lock);
- kobject_del(&q->kobj);
-
return ret;
}
@@ -915,7 +890,7 @@ void blk_unregister_queue(struct gendisk *disk)
*/
if (queue_is_mq(q))
blk_mq_sysfs_unregister(disk);
- blk_crypto_sysfs_unregister(q);
+ blk_crypto_sysfs_unregister(disk);
mutex_lock(&q->sysfs_lock);
elv_unregister_queue(q);
@@ -923,15 +898,9 @@ void blk_unregister_queue(struct gendisk *disk)
mutex_unlock(&q->sysfs_lock);
/* Now that we've deleted all child objects, we can delete the queue. */
- kobject_uevent(&q->kobj, KOBJ_REMOVE);
- kobject_del(&q->kobj);
+ kobject_uevent(&disk->queue_kobj, KOBJ_REMOVE);
+ kobject_del(&disk->queue_kobj);
mutex_unlock(&q->sysfs_dir_lock);
- mutex_lock(&q->debugfs_mutex);
- blk_trace_shutdown(q);
- debugfs_remove_recursive(q->debugfs_dir);
- q->debugfs_dir = NULL;
- q->sched_debugfs_dir = NULL;
- q->rqos_debugfs_dir = NULL;
- mutex_unlock(&q->debugfs_mutex);
+ blk_debugfs_remove(disk);
}
diff --git a/block/blk-throttle.c b/block/blk-throttle.c
index 847721dc2b2b..6fb5a2f9e1ee 100644
--- a/block/blk-throttle.c
+++ b/block/blk-throttle.c
@@ -129,7 +129,7 @@ static struct throtl_data *sq_to_td(struct throtl_service_queue *sq)
/*
* cgroup's limit in LIMIT_MAX is scaled if low limit is set. This scale is to
* make the IO dispatch more smooth.
- * Scale up: linearly scale up according to lapsed time since upgrade. For
+ * Scale up: linearly scale up according to elapsed time since upgrade. For
* every throtl_slice, the limit scales up 1/2 .low limit till the
* limit hits .max limit
* Scale down: exponentially scale down if a cgroup doesn't hit its .low limit
@@ -395,8 +395,9 @@ static void throtl_pd_init(struct blkg_policy_data *pd)
* If on the default hierarchy, we switch to properly hierarchical
* behavior where limits on a given throtl_grp are applied to the
* whole subtree rather than just the group itself. e.g. If 16M
- * read_bps limit is set on the root group, the whole system can't
- * exceed 16M for the device.
+ * read_bps limit is set on a parent group, summary bps of
+ * parent group and its subtree groups can't exceed 16M for the
+ * device.
*
* If not on the default hierarchy, the broken flat hierarchy
* behavior is retained where all throtl_grps are treated as if
@@ -644,7 +645,7 @@ static inline void throtl_start_new_slice_with_credit(struct throtl_grp *tg,
* that bandwidth. Do try to make use of that bandwidth while giving
* credit.
*/
- if (time_after_eq(start, tg->slice_start[rw]))
+ if (time_after(start, tg->slice_start[rw]))
tg->slice_start[rw] = start;
tg->slice_end[rw] = jiffies + tg->td->throtl_slice;
@@ -821,17 +822,15 @@ static void tg_update_carryover(struct throtl_grp *tg)
tg->carryover_ios[READ], tg->carryover_ios[WRITE]);
}
-static bool tg_within_iops_limit(struct throtl_grp *tg, struct bio *bio,
- u32 iops_limit, unsigned long *wait)
+static unsigned long tg_within_iops_limit(struct throtl_grp *tg, struct bio *bio,
+ u32 iops_limit)
{
bool rw = bio_data_dir(bio);
unsigned int io_allowed;
unsigned long jiffy_elapsed, jiffy_wait, jiffy_elapsed_rnd;
if (iops_limit == UINT_MAX) {
- if (wait)
- *wait = 0;
- return true;
+ return 0;
}
jiffy_elapsed = jiffies - tg->slice_start[rw];
@@ -841,21 +840,16 @@ static bool tg_within_iops_limit(struct throtl_grp *tg, struct bio *bio,
io_allowed = calculate_io_allowed(iops_limit, jiffy_elapsed_rnd) +
tg->carryover_ios[rw];
if (tg->io_disp[rw] + 1 <= io_allowed) {
- if (wait)
- *wait = 0;
- return true;
+ return 0;
}
/* Calc approx time to dispatch */
jiffy_wait = jiffy_elapsed_rnd - jiffy_elapsed;
-
- if (wait)
- *wait = jiffy_wait;
- return false;
+ return jiffy_wait;
}
-static bool tg_within_bps_limit(struct throtl_grp *tg, struct bio *bio,
- u64 bps_limit, unsigned long *wait)
+static unsigned long tg_within_bps_limit(struct throtl_grp *tg, struct bio *bio,
+ u64 bps_limit)
{
bool rw = bio_data_dir(bio);
u64 bytes_allowed, extra_bytes;
@@ -864,9 +858,7 @@ static bool tg_within_bps_limit(struct throtl_grp *tg, struct bio *bio,
/* no need to throttle if this bio's bytes have been accounted */
if (bps_limit == U64_MAX || bio_flagged(bio, BIO_BPS_THROTTLED)) {
- if (wait)
- *wait = 0;
- return true;
+ return 0;
}
jiffy_elapsed = jiffy_elapsed_rnd = jiffies - tg->slice_start[rw];
@@ -879,9 +871,7 @@ static bool tg_within_bps_limit(struct throtl_grp *tg, struct bio *bio,
bytes_allowed = calculate_bytes_allowed(bps_limit, jiffy_elapsed_rnd) +
tg->carryover_bytes[rw];
if (tg->bytes_disp[rw] + bio_size <= bytes_allowed) {
- if (wait)
- *wait = 0;
- return true;
+ return 0;
}
/* Calc approx time to dispatch */
@@ -896,9 +886,7 @@ static bool tg_within_bps_limit(struct throtl_grp *tg, struct bio *bio,
* up we did. Add that time also.
*/
jiffy_wait = jiffy_wait + (jiffy_elapsed_rnd - jiffy_elapsed);
- if (wait)
- *wait = jiffy_wait;
- return false;
+ return jiffy_wait;
}
/*
@@ -946,8 +934,9 @@ static bool tg_may_dispatch(struct throtl_grp *tg, struct bio *bio,
jiffies + tg->td->throtl_slice);
}
- if (tg_within_bps_limit(tg, bio, bps_limit, &bps_wait) &&
- tg_within_iops_limit(tg, bio, iops_limit, &iops_wait)) {
+ bps_wait = tg_within_bps_limit(tg, bio, bps_limit);
+ iops_wait = tg_within_iops_limit(tg, bio, iops_limit);
+ if (bps_wait + iops_wait == 0) {
if (wait)
*wait = 0;
return true;
@@ -1066,7 +1055,6 @@ static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw)
sq->nr_queued[rw]--;
throtl_charge_bio(tg, bio);
- bio_set_flag(bio, BIO_BPS_THROTTLED);
/*
* If our parent is another tg, we just need to transfer @bio to
@@ -1079,6 +1067,7 @@ static void tg_dispatch_one_bio(struct throtl_grp *tg, bool rw)
throtl_add_bio_tg(bio, &tg->qnode_on_parent[rw], parent_tg);
start_parent_slice_with_credit(tg, parent_tg, rw);
} else {
+ bio_set_flag(bio, BIO_BPS_THROTTLED);
throtl_qnode_add_bio(bio, &tg->qnode_on_parent[rw],
&parent_sq->queued[rw]);
BUG_ON(tg->td->nr_queued[rw] <= 0);
@@ -1737,7 +1726,18 @@ void blk_throtl_cancel_bios(struct gendisk *disk)
* Set the flag to make sure throtl_pending_timer_fn() won't
* stop until all throttled bios are dispatched.
*/
- blkg_to_tg(blkg)->flags |= THROTL_TG_CANCELING;
+ tg->flags |= THROTL_TG_CANCELING;
+
+ /*
+ * Do not dispatch cgroup without THROTL_TG_PENDING or cgroup
+ * will be inserted to service queue without THROTL_TG_PENDING
+ * set in tg_update_disptime below. Then IO dispatched from
+ * child in tg_dispatch_one_bio will trigger double insertion
+ * and corrupt the tree.
+ */
+ if (!(tg->flags & THROTL_TG_PENDING))
+ continue;
+
/*
* Update disptime after setting the above flag to make sure
* throtl_select_dispatch() won't exit without dispatching.
@@ -1762,7 +1762,6 @@ static unsigned long __tg_last_low_overflow_time(struct throtl_grp *tg)
return min(rtime, wtime);
}
-/* tg should not be an intermediate node */
static unsigned long tg_last_low_overflow_time(struct throtl_grp *tg)
{
struct throtl_service_queue *parent_sq;
@@ -1816,24 +1815,29 @@ static bool throtl_tg_is_idle(struct throtl_grp *tg)
return ret;
}
-static bool throtl_tg_can_upgrade(struct throtl_grp *tg)
+static bool throtl_low_limit_reached(struct throtl_grp *tg, int rw)
{
struct throtl_service_queue *sq = &tg->service_queue;
- bool read_limit, write_limit;
+ bool limit = tg->bps[rw][LIMIT_LOW] || tg->iops[rw][LIMIT_LOW];
/*
- * if cgroup reaches low limit (if low limit is 0, the cgroup always
- * reaches), it's ok to upgrade to next limit
+ * if low limit is zero, low limit is always reached.
+ * if low limit is non-zero, we can check if there is any request
+ * is queued to determine if low limit is reached as we throttle
+ * request according to limit.
*/
- read_limit = tg->bps[READ][LIMIT_LOW] || tg->iops[READ][LIMIT_LOW];
- write_limit = tg->bps[WRITE][LIMIT_LOW] || tg->iops[WRITE][LIMIT_LOW];
- if (!read_limit && !write_limit)
- return true;
- if (read_limit && sq->nr_queued[READ] &&
- (!write_limit || sq->nr_queued[WRITE]))
- return true;
- if (write_limit && sq->nr_queued[WRITE] &&
- (!read_limit || sq->nr_queued[READ]))
+ return !limit || sq->nr_queued[rw];
+}
+
+static bool throtl_tg_can_upgrade(struct throtl_grp *tg)
+{
+ /*
+ * cgroup reaches low limit when low limit of READ and WRITE are
+ * both reached, it's ok to upgrade to next limit if cgroup reaches
+ * low limit
+ */
+ if (throtl_low_limit_reached(tg, READ) &&
+ throtl_low_limit_reached(tg, WRITE))
return true;
if (time_after_eq(jiffies,
@@ -1951,8 +1955,7 @@ static bool throtl_tg_can_downgrade(struct throtl_grp *tg)
* If cgroup is below low limit, consider downgrade and throttle other
* cgroups
*/
- if (time_after_eq(now, td->low_upgrade_time + td->throtl_slice) &&
- time_after_eq(now, tg_last_low_overflow_time(tg) +
+ if (time_after_eq(now, tg_last_low_overflow_time(tg) +
td->throtl_slice) &&
(!throtl_tg_is_idle(tg) ||
!list_empty(&tg_to_blkg(tg)->blkcg->css.children)))
@@ -1962,6 +1965,11 @@ static bool throtl_tg_can_downgrade(struct throtl_grp *tg)
static bool throtl_hierarchy_can_downgrade(struct throtl_grp *tg)
{
+ struct throtl_data *td = tg->td;
+
+ if (time_before(jiffies, td->low_upgrade_time + td->throtl_slice))
+ return false;
+
while (true) {
if (!throtl_tg_can_downgrade(tg))
return false;
diff --git a/block/blk-wbt.c b/block/blk-wbt.c
index c293e08b301f..68a774d7a7c9 100644
--- a/block/blk-wbt.c
+++ b/block/blk-wbt.c
@@ -27,6 +27,7 @@
#include "blk-wbt.h"
#include "blk-rq-qos.h"
+#include "elevator.h"
#define CREATE_TRACE_POINTS
#include <trace/events/wbt.h>
@@ -422,6 +423,14 @@ static void wbt_update_limits(struct rq_wb *rwb)
rwb_wake_all(rwb);
}
+bool wbt_disabled(struct request_queue *q)
+{
+ struct rq_qos *rqos = wbt_rq_qos(q);
+
+ return !rqos || RQWB(rqos)->enable_state == WBT_STATE_OFF_DEFAULT ||
+ RQWB(rqos)->enable_state == WBT_STATE_OFF_MANUAL;
+}
+
u64 wbt_get_min_lat(struct request_queue *q)
{
struct rq_qos *rqos = wbt_rq_qos(q);
@@ -435,8 +444,13 @@ void wbt_set_min_lat(struct request_queue *q, u64 val)
struct rq_qos *rqos = wbt_rq_qos(q);
if (!rqos)
return;
+
RQWB(rqos)->min_lat_nsec = val;
- RQWB(rqos)->enable_state = WBT_STATE_ON_MANUAL;
+ if (val)
+ RQWB(rqos)->enable_state = WBT_STATE_ON_MANUAL;
+ else
+ RQWB(rqos)->enable_state = WBT_STATE_OFF_MANUAL;
+
wbt_update_limits(RQWB(rqos));
}
@@ -638,11 +652,15 @@ void wbt_set_write_cache(struct request_queue *q, bool write_cache_on)
*/
void wbt_enable_default(struct request_queue *q)
{
- struct rq_qos *rqos = wbt_rq_qos(q);
+ struct rq_qos *rqos;
+ bool disable_flag = q->elevator &&
+ test_bit(ELEVATOR_FLAG_DISABLE_WBT, &q->elevator->flags);
/* Throttling already enabled? */
+ rqos = wbt_rq_qos(q);
if (rqos) {
- if (RQWB(rqos)->enable_state == WBT_STATE_OFF_DEFAULT)
+ if (!disable_flag &&
+ RQWB(rqos)->enable_state == WBT_STATE_OFF_DEFAULT)
RQWB(rqos)->enable_state = WBT_STATE_ON_DEFAULT;
return;
}
@@ -651,7 +669,7 @@ void wbt_enable_default(struct request_queue *q)
if (!blk_queue_registered(q))
return;
- if (queue_is_mq(q) && IS_ENABLED(CONFIG_BLK_WBT_MQ))
+ if (queue_is_mq(q) && !disable_flag)
wbt_init(q);
}
EXPORT_SYMBOL_GPL(wbt_enable_default);
diff --git a/block/blk-wbt.h b/block/blk-wbt.h
index 7e44eccc676d..e3ea6e7e2900 100644
--- a/block/blk-wbt.h
+++ b/block/blk-wbt.h
@@ -28,13 +28,15 @@ enum {
};
/*
- * Enable states. Either off, or on by default (done at init time),
- * or on through manual setup in sysfs.
+ * If current state is WBT_STATE_ON/OFF_DEFAULT, it can be covered to any other
+ * state, if current state is WBT_STATE_ON/OFF_MANUAL, it can only be covered
+ * to WBT_STATE_OFF/ON_MANUAL.
*/
enum {
- WBT_STATE_ON_DEFAULT = 1,
- WBT_STATE_ON_MANUAL = 2,
- WBT_STATE_OFF_DEFAULT
+ WBT_STATE_ON_DEFAULT = 1, /* on by default */
+ WBT_STATE_ON_MANUAL = 2, /* on manually by sysfs */
+ WBT_STATE_OFF_DEFAULT = 3, /* off by default */
+ WBT_STATE_OFF_MANUAL = 4, /* off manually by sysfs */
};
struct rq_wb {
@@ -94,6 +96,7 @@ void wbt_enable_default(struct request_queue *);
u64 wbt_get_min_lat(struct request_queue *q);
void wbt_set_min_lat(struct request_queue *q, u64 val);
+bool wbt_disabled(struct request_queue *);
void wbt_set_write_cache(struct request_queue *, bool);
@@ -125,6 +128,10 @@ static inline u64 wbt_default_latency_nsec(struct request_queue *q)
{
return 0;
}
+static inline bool wbt_disabled(struct request_queue *q)
+{
+ return true;
+}
#endif /* CONFIG_BLK_WBT */
diff --git a/block/blk.h b/block/blk.h
index a186ea20f39d..4c3b3325219a 100644
--- a/block/blk.h
+++ b/block/blk.h
@@ -26,11 +26,6 @@ struct blk_flush_queue {
spinlock_t mq_flush_lock;
};
-extern struct kmem_cache *blk_requestq_cachep;
-extern struct kmem_cache *blk_requestq_srcu_cachep;
-extern struct kobj_type blk_queue_ktype;
-extern struct ida blk_queue_ida;
-
bool is_flush_rq(struct request *req);
struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size,
@@ -104,7 +99,7 @@ static inline bool biovec_phys_mergeable(struct request_queue *q,
return true;
}
-static inline bool __bvec_gap_to_prev(struct queue_limits *lim,
+static inline bool __bvec_gap_to_prev(const struct queue_limits *lim,
struct bio_vec *bprv, unsigned int offset)
{
return (offset & lim->virt_boundary_mask) ||
@@ -115,7 +110,7 @@ static inline bool __bvec_gap_to_prev(struct queue_limits *lim,
* Check if adding a bio_vec after bprv with offset would create a gap in
* the SG list. Most drivers don't care about this, but some do.
*/
-static inline bool bvec_gap_to_prev(struct queue_limits *lim,
+static inline bool bvec_gap_to_prev(const struct queue_limits *lim,
struct bio_vec *bprv, unsigned int offset)
{
if (!lim->virt_boundary_mask)
@@ -278,6 +273,7 @@ bool blk_bio_list_merge(struct request_queue *q, struct list_head *list,
void blk_insert_flush(struct request *rq);
int elevator_switch(struct request_queue *q, struct elevator_type *new_e);
+void elevator_disable(struct request_queue *q);
void elevator_exit(struct request_queue *q);
int elv_register_queue(struct request_queue *q, bool uevent);
void elv_unregister_queue(struct request_queue *q);
@@ -297,7 +293,7 @@ ssize_t part_timeout_store(struct device *, struct device_attribute *,
const char *, size_t);
static inline bool bio_may_exceed_limits(struct bio *bio,
- struct queue_limits *lim)
+ const struct queue_limits *lim)
{
switch (bio_op(bio)) {
case REQ_OP_DISCARD:
@@ -320,8 +316,9 @@ static inline bool bio_may_exceed_limits(struct bio *bio,
bio->bi_io_vec->bv_len + bio->bi_io_vec->bv_offset > PAGE_SIZE;
}
-struct bio *__bio_split_to_limits(struct bio *bio, struct queue_limits *lim,
- unsigned int *nr_segs);
+struct bio *__bio_split_to_limits(struct bio *bio,
+ const struct queue_limits *lim,
+ unsigned int *nr_segs);
int ll_back_merge_fn(struct request *req, struct bio *bio,
unsigned int nr_segs);
bool blk_attempt_req_merge(struct request_queue *q, struct request *rq,
@@ -428,15 +425,9 @@ int bio_add_hw_page(struct request_queue *q, struct bio *bio,
struct page *page, unsigned int len, unsigned int offset,
unsigned int max_sectors, bool *same_page);
-static inline struct kmem_cache *blk_get_queue_kmem_cache(bool srcu)
-{
- if (srcu)
- return blk_requestq_srcu_cachep;
- return blk_requestq_cachep;
-}
-struct request_queue *blk_alloc_queue(int node_id, bool alloc_srcu);
+struct request_queue *blk_alloc_queue(int node_id);
-int disk_scan_partitions(struct gendisk *disk, fmode_t mode);
+int disk_scan_partitions(struct gendisk *disk, fmode_t mode, void *owner);
int disk_alloc_events(struct gendisk *disk);
void disk_add_events(struct gendisk *disk);
diff --git a/block/bsg-lib.c b/block/bsg-lib.c
index d6f5dcdce748..435c32373cd6 100644
--- a/block/bsg-lib.c
+++ b/block/bsg-lib.c
@@ -325,6 +325,7 @@ void bsg_remove_queue(struct request_queue *q)
bsg_unregister_queue(bset->bd);
blk_mq_destroy_queue(q);
+ blk_put_queue(q);
blk_mq_free_tag_set(&bset->tag_set);
kfree(bset);
}
@@ -400,6 +401,7 @@ struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
return q;
out_cleanup_queue:
blk_mq_destroy_queue(q);
+ blk_put_queue(q);
out_queue:
blk_mq_free_tag_set(set);
out_tag_set:
diff --git a/block/bsg.c b/block/bsg.c
index 2ab1351eb082..8eba57b9bb46 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -175,8 +175,10 @@ static void bsg_device_release(struct device *dev)
void bsg_unregister_queue(struct bsg_device *bd)
{
- if (bd->queue->kobj.sd)
- sysfs_remove_link(&bd->queue->kobj, "bsg");
+ struct gendisk *disk = bd->queue->disk;
+
+ if (disk && disk->queue_kobj.sd)
+ sysfs_remove_link(&disk->queue_kobj, "bsg");
cdev_device_del(&bd->cdev, &bd->device);
put_device(&bd->device);
}
@@ -216,8 +218,9 @@ struct bsg_device *bsg_register_queue(struct request_queue *q,
if (ret)
goto out_put_device;
- if (q->kobj.sd) {
- ret = sysfs_create_link(&q->kobj, &bd->device.kobj, "bsg");
+ if (q->disk && q->disk->queue_kobj.sd) {
+ ret = sysfs_create_link(&q->disk->queue_kobj, &bd->device.kobj,
+ "bsg");
if (ret)
goto out_device_del;
}
diff --git a/block/elevator.c b/block/elevator.c
index bd71f0fc4e4b..adee58e48e2d 100644
--- a/block/elevator.c
+++ b/block/elevator.c
@@ -57,7 +57,7 @@ static LIST_HEAD(elv_list);
* Query io scheduler to see if the current process issuing bio may be
* merged with rq.
*/
-static int elv_iosched_allow_bio_merge(struct request *rq, struct bio *bio)
+static bool elv_iosched_allow_bio_merge(struct request *rq, struct bio *bio)
{
struct request_queue *q = rq->q;
struct elevator_queue *e = q->elevator;
@@ -65,7 +65,7 @@ static int elv_iosched_allow_bio_merge(struct request *rq, struct bio *bio)
if (e->type->ops.allow_merge)
return e->type->ops.allow_merge(q, rq, bio);
- return 1;
+ return true;
}
/*
@@ -83,78 +83,45 @@ bool elv_bio_merge_ok(struct request *rq, struct bio *bio)
}
EXPORT_SYMBOL(elv_bio_merge_ok);
-static inline bool elv_support_features(unsigned int elv_features,
- unsigned int required_features)
+static inline bool elv_support_features(struct request_queue *q,
+ const struct elevator_type *e)
{
- return (required_features & elv_features) == required_features;
+ return (q->required_elevator_features & e->elevator_features) ==
+ q->required_elevator_features;
}
/**
- * elevator_match - Test an elevator name and features
+ * elevator_match - Check whether @e's name or alias matches @name
* @e: Scheduler to test
* @name: Elevator name to test
- * @required_features: Features that the elevator must provide
*
- * Return true if the elevator @e name matches @name and if @e provides all
- * the features specified by @required_features.
+ * Return true if the elevator @e's name or alias matches @name.
*/
-static bool elevator_match(const struct elevator_type *e, const char *name,
- unsigned int required_features)
+static bool elevator_match(const struct elevator_type *e, const char *name)
{
- if (!elv_support_features(e->elevator_features, required_features))
- return false;
- if (!strcmp(e->elevator_name, name))
- return true;
- if (e->elevator_alias && !strcmp(e->elevator_alias, name))
- return true;
-
- return false;
+ return !strcmp(e->elevator_name, name) ||
+ (e->elevator_alias && !strcmp(e->elevator_alias, name));
}
-/**
- * elevator_find - Find an elevator
- * @name: Name of the elevator to find
- * @required_features: Features that the elevator must provide
- *
- * Return the first registered scheduler with name @name and supporting the
- * features @required_features and NULL otherwise.
- */
-static struct elevator_type *elevator_find(const char *name,
- unsigned int required_features)
+static struct elevator_type *__elevator_find(const char *name)
{
struct elevator_type *e;
- list_for_each_entry(e, &elv_list, list) {
- if (elevator_match(e, name, required_features))
+ list_for_each_entry(e, &elv_list, list)
+ if (elevator_match(e, name))
return e;
- }
-
return NULL;
}
-static void elevator_put(struct elevator_type *e)
-{
- module_put(e->elevator_owner);
-}
-
-static struct elevator_type *elevator_get(struct request_queue *q,
- const char *name, bool try_loading)
+static struct elevator_type *elevator_find_get(struct request_queue *q,
+ const char *name)
{
struct elevator_type *e;
spin_lock(&elv_list_lock);
-
- e = elevator_find(name, q->required_elevator_features);
- if (!e && try_loading) {
- spin_unlock(&elv_list_lock);
- request_module("%s-iosched", name);
- spin_lock(&elv_list_lock);
- e = elevator_find(name, q->required_elevator_features);
- }
-
- if (e && !try_module_get(e->elevator_owner))
+ e = __elevator_find(name);
+ if (e && (!elv_support_features(q, e) || !elevator_tryget(e)))
e = NULL;
-
spin_unlock(&elv_list_lock);
return e;
}
@@ -170,6 +137,7 @@ struct elevator_queue *elevator_alloc(struct request_queue *q,
if (unlikely(!eq))
return NULL;
+ __elevator_get(e);
eq->type = e;
kobject_init(&eq->kobj, &elv_ktype);
mutex_init(&eq->sysfs_lock);
@@ -499,7 +467,7 @@ int elv_register_queue(struct request_queue *q, bool uevent)
lockdep_assert_held(&q->sysfs_lock);
- error = kobject_add(&e->kobj, &q->kobj, "%s", "iosched");
+ error = kobject_add(&e->kobj, &q->disk->queue_kobj, "iosched");
if (!error) {
struct elv_fs_entry *attr = e->type->elevator_attrs;
if (attr) {
@@ -512,7 +480,7 @@ int elv_register_queue(struct request_queue *q, bool uevent)
if (uevent)
kobject_uevent(&e->kobj, KOBJ_ADD);
- e->registered = 1;
+ set_bit(ELEVATOR_FLAG_REGISTERED, &e->flags);
}
return error;
}
@@ -523,13 +491,9 @@ void elv_unregister_queue(struct request_queue *q)
lockdep_assert_held(&q->sysfs_lock);
- if (e && e->registered) {
- struct elevator_queue *e = q->elevator;
-
+ if (e && test_and_clear_bit(ELEVATOR_FLAG_REGISTERED, &e->flags)) {
kobject_uevent(&e->kobj, KOBJ_REMOVE);
kobject_del(&e->kobj);
-
- e->registered = 0;
}
}
@@ -555,7 +519,7 @@ int elv_register(struct elevator_type *e)
/* register, don't allow duplicate names */
spin_lock(&elv_list_lock);
- if (elevator_find(e->elevator_name, 0)) {
+ if (__elevator_find(e->elevator_name)) {
spin_unlock(&elv_list_lock);
kmem_cache_destroy(e->icq_cache);
return -EBUSY;
@@ -588,39 +552,6 @@ void elv_unregister(struct elevator_type *e)
}
EXPORT_SYMBOL_GPL(elv_unregister);
-static int elevator_switch_mq(struct request_queue *q,
- struct elevator_type *new_e)
-{
- int ret;
-
- lockdep_assert_held(&q->sysfs_lock);
-
- if (q->elevator) {
- elv_unregister_queue(q);
- elevator_exit(q);
- }
-
- ret = blk_mq_init_sched(q, new_e);
- if (ret)
- goto out;
-
- if (new_e) {
- ret = elv_register_queue(q, true);
- if (ret) {
- elevator_exit(q);
- goto out;
- }
- }
-
- if (new_e)
- blk_add_trace_msg(q, "elv switch: %s", new_e->elevator_name);
- else
- blk_add_trace_msg(q, "elv switch: none");
-
-out:
- return ret;
-}
-
static inline bool elv_support_iosched(struct request_queue *q)
{
if (!queue_is_mq(q) ||
@@ -642,7 +573,7 @@ static struct elevator_type *elevator_get_default(struct request_queue *q)
!blk_mq_is_shared_tags(q->tag_set->flags))
return NULL;
- return elevator_get(q, "mq-deadline", false);
+ return elevator_find_get(q, "mq-deadline");
}
/*
@@ -656,14 +587,13 @@ static struct elevator_type *elevator_get_by_features(struct request_queue *q)
spin_lock(&elv_list_lock);
list_for_each_entry(e, &elv_list, list) {
- if (elv_support_features(e->elevator_features,
- q->required_elevator_features)) {
+ if (elv_support_features(q, e)) {
found = e;
break;
}
}
- if (found && !try_module_get(found->elevator_owner))
+ if (found && !elevator_tryget(found))
found = NULL;
spin_unlock(&elv_list_lock);
@@ -713,115 +643,147 @@ void elevator_init_mq(struct request_queue *q)
if (err) {
pr_warn("\"%s\" elevator initialization failed, "
"falling back to \"none\"\n", e->elevator_name);
- elevator_put(e);
}
+
+ elevator_put(e);
}
/*
- * switch to new_e io scheduler. be careful not to introduce deadlocks -
- * we don't free the old io scheduler, before we have allocated what we
- * need for the new one. this way we have a chance of going back to the old
- * one, if the new one fails init for some reason.
+ * Switch to new_e io scheduler.
+ *
+ * If switching fails, we are most likely running out of memory and not able
+ * to restore the old io scheduler, so leaving the io scheduler being none.
*/
int elevator_switch(struct request_queue *q, struct elevator_type *new_e)
{
- int err;
+ int ret;
lockdep_assert_held(&q->sysfs_lock);
blk_mq_freeze_queue(q);
blk_mq_quiesce_queue(q);
- err = elevator_switch_mq(q, new_e);
+ if (q->elevator) {
+ elv_unregister_queue(q);
+ elevator_exit(q);
+ }
+
+ ret = blk_mq_init_sched(q, new_e);
+ if (ret)
+ goto out_unfreeze;
+
+ ret = elv_register_queue(q, true);
+ if (ret) {
+ elevator_exit(q);
+ goto out_unfreeze;
+ }
+ blk_add_trace_msg(q, "elv switch: %s", new_e->elevator_name);
+out_unfreeze:
blk_mq_unquiesce_queue(q);
blk_mq_unfreeze_queue(q);
- return err;
+ if (ret) {
+ pr_warn("elv: switch to \"%s\" failed, falling back to \"none\"\n",
+ new_e->elevator_name);
+ }
+
+ return ret;
+}
+
+void elevator_disable(struct request_queue *q)
+{
+ lockdep_assert_held(&q->sysfs_lock);
+
+ blk_mq_freeze_queue(q);
+ blk_mq_quiesce_queue(q);
+
+ elv_unregister_queue(q);
+ elevator_exit(q);
+ blk_queue_flag_clear(QUEUE_FLAG_SQ_SCHED, q);
+ q->elevator = NULL;
+ q->nr_requests = q->tag_set->queue_depth;
+ blk_add_trace_msg(q, "elv switch: none");
+
+ blk_mq_unquiesce_queue(q);
+ blk_mq_unfreeze_queue(q);
}
/*
* Switch this queue to the given IO scheduler.
*/
-static int __elevator_change(struct request_queue *q, const char *name)
+static int elevator_change(struct request_queue *q, const char *elevator_name)
{
- char elevator_name[ELV_NAME_MAX];
struct elevator_type *e;
+ int ret;
/* Make sure queue is not in the middle of being removed */
if (!blk_queue_registered(q))
return -ENOENT;
- /*
- * Special case for mq, turn off scheduling
- */
- if (!strncmp(name, "none", 4)) {
- if (!q->elevator)
- return 0;
- return elevator_switch(q, NULL);
+ if (!strncmp(elevator_name, "none", 4)) {
+ if (q->elevator)
+ elevator_disable(q);
+ return 0;
}
- strlcpy(elevator_name, name, sizeof(elevator_name));
- e = elevator_get(q, strstrip(elevator_name), true);
- if (!e)
- return -EINVAL;
-
- if (q->elevator &&
- elevator_match(q->elevator->type, elevator_name, 0)) {
- elevator_put(e);
+ if (q->elevator && elevator_match(q->elevator->type, elevator_name))
return 0;
- }
- return elevator_switch(q, e);
+ e = elevator_find_get(q, elevator_name);
+ if (!e) {
+ request_module("%s-iosched", elevator_name);
+ e = elevator_find_get(q, elevator_name);
+ if (!e)
+ return -EINVAL;
+ }
+ ret = elevator_switch(q, e);
+ elevator_put(e);
+ return ret;
}
-ssize_t elv_iosched_store(struct request_queue *q, const char *name,
+ssize_t elv_iosched_store(struct request_queue *q, const char *buf,
size_t count)
{
+ char elevator_name[ELV_NAME_MAX];
int ret;
if (!elv_support_iosched(q))
return count;
- ret = __elevator_change(q, name);
+ strlcpy(elevator_name, buf, sizeof(elevator_name));
+ ret = elevator_change(q, strstrip(elevator_name));
if (!ret)
return count;
-
return ret;
}
ssize_t elv_iosched_show(struct request_queue *q, char *name)
{
- struct elevator_queue *e = q->elevator;
- struct elevator_type *elv = NULL;
- struct elevator_type *__e;
+ struct elevator_queue *eq = q->elevator;
+ struct elevator_type *cur = NULL, *e;
int len = 0;
- if (!queue_is_mq(q))
+ if (!elv_support_iosched(q))
return sprintf(name, "none\n");
- if (!q->elevator)
+ if (!q->elevator) {
len += sprintf(name+len, "[none] ");
- else
- elv = e->type;
+ } else {
+ len += sprintf(name+len, "none ");
+ cur = eq->type;
+ }
spin_lock(&elv_list_lock);
- list_for_each_entry(__e, &elv_list, list) {
- if (elv && elevator_match(elv, __e->elevator_name, 0)) {
- len += sprintf(name+len, "[%s] ", elv->elevator_name);
- continue;
- }
- if (elv_support_iosched(q) &&
- elevator_match(__e, __e->elevator_name,
- q->required_elevator_features))
- len += sprintf(name+len, "%s ", __e->elevator_name);
+ list_for_each_entry(e, &elv_list, list) {
+ if (e == cur)
+ len += sprintf(name+len, "[%s] ", e->elevator_name);
+ else if (elv_support_features(q, e))
+ len += sprintf(name+len, "%s ", e->elevator_name);
}
spin_unlock(&elv_list_lock);
- if (q->elevator)
- len += sprintf(name+len, "none");
-
- len += sprintf(len+name, "\n");
+ len += sprintf(name+len, "\n");
return len;
}
diff --git a/block/elevator.h b/block/elevator.h
index 3f0593b3bf9d..774a8f6b99e6 100644
--- a/block/elevator.h
+++ b/block/elevator.h
@@ -84,6 +84,21 @@ struct elevator_type
struct list_head list;
};
+static inline bool elevator_tryget(struct elevator_type *e)
+{
+ return try_module_get(e->elevator_owner);
+}
+
+static inline void __elevator_get(struct elevator_type *e)
+{
+ __module_get(e->elevator_owner);
+}
+
+static inline void elevator_put(struct elevator_type *e)
+{
+ module_put(e->elevator_owner);
+}
+
#define ELV_HASH_BITS 6
void elv_rqhash_del(struct request_queue *q, struct request *rq);
@@ -100,10 +115,13 @@ struct elevator_queue
void *elevator_data;
struct kobject kobj;
struct mutex sysfs_lock;
- unsigned int registered:1;
+ unsigned long flags;
DECLARE_HASHTABLE(hash, ELV_HASH_BITS);
};
+#define ELEVATOR_FLAG_REGISTERED 0
+#define ELEVATOR_FLAG_DISABLE_WBT 1
+
/*
* block elevator interface
*/
diff --git a/block/fops.c b/block/fops.c
index b90742595317..50d245e8c913 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -405,12 +405,6 @@ static int blkdev_write_end(struct file *file, struct address_space *mapping,
return ret;
}
-static int blkdev_writepages(struct address_space *mapping,
- struct writeback_control *wbc)
-{
- return generic_writepages(mapping, wbc);
-}
-
const struct address_space_operations def_blk_aops = {
.dirty_folio = block_dirty_folio,
.invalidate_folio = block_invalidate_folio,
@@ -419,7 +413,6 @@ const struct address_space_operations def_blk_aops = {
.writepage = blkdev_writepage,
.write_begin = blkdev_write_begin,
.write_end = blkdev_write_end,
- .writepages = blkdev_writepages,
.direct_IO = blkdev_direct_IO,
.migrate_folio = buffer_migrate_folio_norefs,
.is_dirty_writeback = buffer_check_dirty_writeback,
diff --git a/block/genhd.c b/block/genhd.c
index 0f9769db2de8..08f76135a637 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -356,7 +356,7 @@ void disk_uevent(struct gendisk *disk, enum kobject_action action)
}
EXPORT_SYMBOL_GPL(disk_uevent);
-int disk_scan_partitions(struct gendisk *disk, fmode_t mode)
+int disk_scan_partitions(struct gendisk *disk, fmode_t mode, void *owner)
{
struct block_device *bdev;
@@ -366,6 +366,9 @@ int disk_scan_partitions(struct gendisk *disk, fmode_t mode)
return -EINVAL;
if (disk->open_partitions)
return -EBUSY;
+ /* Someone else has bdev exclusively open? */
+ if (disk->part0->bd_holder && disk->part0->bd_holder != owner)
+ return -EBUSY;
set_bit(GD_NEED_PART_SCAN, &disk->state);
bdev = blkdev_get_by_dev(disk_devt(disk), mode, NULL);
@@ -479,10 +482,6 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
goto out_put_holder_dir;
}
- ret = bd_register_pending_holders(disk);
- if (ret < 0)
- goto out_put_slave_dir;
-
ret = blk_register_queue(disk);
if (ret)
goto out_put_slave_dir;
@@ -500,7 +499,7 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
bdev_add(disk->part0, ddev->devt);
if (get_capacity(disk))
- disk_scan_partitions(disk, FMODE_READ);
+ disk_scan_partitions(disk, FMODE_READ, NULL);
/*
* Announce the disk and partitions after all partitions are
@@ -530,6 +529,7 @@ out_unregister_queue:
rq_qos_exit(disk->queue);
out_put_slave_dir:
kobject_put(disk->slave_dir);
+ disk->slave_dir = NULL;
out_put_holder_dir:
kobject_put(disk->part0->bd_holder_dir);
out_del_integrity:
@@ -560,6 +560,11 @@ void blk_mark_disk_dead(struct gendisk *disk)
{
set_bit(GD_DEAD, &disk->state);
blk_queue_start_drain(disk->queue);
+
+ /*
+ * Stop buffered writers from dirtying pages that can't be written out.
+ */
+ set_capacity_and_notify(disk, 0);
}
EXPORT_SYMBOL_GPL(blk_mark_disk_dead);
@@ -629,6 +634,7 @@ void del_gendisk(struct gendisk *disk)
kobject_put(disk->part0->bd_holder_dir);
kobject_put(disk->slave_dir);
+ disk->slave_dir = NULL;
part_stat_set_all(disk->part0, 0);
disk->part0->bd_stamp = 0;
@@ -643,7 +649,9 @@ void del_gendisk(struct gendisk *disk)
blk_sync_queue(q);
blk_flush_integrity();
- blk_mq_cancel_work_sync(q);
+
+ if (queue_is_mq(q))
+ blk_mq_cancel_work_sync(q);
blk_mq_quiesce_queue(q);
if (q->elevator) {
@@ -1193,21 +1201,10 @@ struct class block_class = {
.dev_uevent = block_uevent,
};
-static char *block_devnode(struct device *dev, umode_t *mode,
- kuid_t *uid, kgid_t *gid)
-{
- struct gendisk *disk = dev_to_disk(dev);
-
- if (disk->fops->devnode)
- return disk->fops->devnode(disk, mode);
- return NULL;
-}
-
const struct device_type disk_type = {
.name = "disk",
.groups = disk_attr_groups,
.release = disk_release,
- .devnode = block_devnode,
};
#ifdef CONFIG_PROC_FS
@@ -1412,7 +1409,7 @@ struct gendisk *__blk_alloc_disk(int node, struct lock_class_key *lkclass)
struct request_queue *q;
struct gendisk *disk;
- q = blk_alloc_queue(node, false);
+ q = blk_alloc_queue(node);
if (!q)
return NULL;
diff --git a/block/holder.c b/block/holder.c
index 5283bc804cc1..37d18c13d958 100644
--- a/block/holder.c
+++ b/block/holder.c
@@ -4,7 +4,7 @@
struct bd_holder_disk {
struct list_head list;
- struct block_device *bdev;
+ struct kobject *holder_dir;
int refcnt;
};
@@ -14,7 +14,7 @@ static struct bd_holder_disk *bd_find_holder_disk(struct block_device *bdev,
struct bd_holder_disk *holder;
list_for_each_entry(holder, &disk->slave_bdevs, list)
- if (holder->bdev == bdev)
+ if (holder->holder_dir == bdev->bd_holder_dir)
return holder;
return NULL;
}
@@ -29,19 +29,6 @@ static void del_symlink(struct kobject *from, struct kobject *to)
sysfs_remove_link(from, kobject_name(to));
}
-static int __link_disk_holder(struct block_device *bdev, struct gendisk *disk)
-{
- int ret;
-
- ret = add_symlink(disk->slave_dir, bdev_kobj(bdev));
- if (ret)
- return ret;
- ret = add_symlink(bdev->bd_holder_dir, &disk_to_dev(disk)->kobj);
- if (ret)
- del_symlink(disk->slave_dir, bdev_kobj(bdev));
- return ret;
-}
-
/**
* bd_link_disk_holder - create symlinks between holding disk and slave bdev
* @bdev: the claimed slave bdev
@@ -75,12 +62,30 @@ int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk)
struct bd_holder_disk *holder;
int ret = 0;
- mutex_lock(&disk->open_mutex);
+ if (WARN_ON_ONCE(!disk->slave_dir))
+ return -EINVAL;
+
+ if (bdev->bd_disk == disk)
+ return -EINVAL;
+
+ /*
+ * del_gendisk drops the initial reference to bd_holder_dir, so we
+ * need to keep our own here to allow for cleanup past that point.
+ */
+ mutex_lock(&bdev->bd_disk->open_mutex);
+ if (!disk_live(bdev->bd_disk)) {
+ mutex_unlock(&bdev->bd_disk->open_mutex);
+ return -ENODEV;
+ }
+ kobject_get(bdev->bd_holder_dir);
+ mutex_unlock(&bdev->bd_disk->open_mutex);
+ mutex_lock(&disk->open_mutex);
WARN_ON_ONCE(!bdev->bd_holder);
holder = bd_find_holder_disk(bdev, disk);
if (holder) {
+ kobject_put(bdev->bd_holder_dir);
holder->refcnt++;
goto out_unlock;
}
@@ -92,36 +97,32 @@ int bd_link_disk_holder(struct block_device *bdev, struct gendisk *disk)
}
INIT_LIST_HEAD(&holder->list);
- holder->bdev = bdev;
holder->refcnt = 1;
- if (disk->slave_dir) {
- ret = __link_disk_holder(bdev, disk);
- if (ret) {
- kfree(holder);
- goto out_unlock;
- }
- }
+ holder->holder_dir = bdev->bd_holder_dir;
+ ret = add_symlink(disk->slave_dir, bdev_kobj(bdev));
+ if (ret)
+ goto out_free_holder;
+ ret = add_symlink(bdev->bd_holder_dir, &disk_to_dev(disk)->kobj);
+ if (ret)
+ goto out_del_symlink;
list_add(&holder->list, &disk->slave_bdevs);
- /*
- * del_gendisk drops the initial reference to bd_holder_dir, so we need
- * to keep our own here to allow for cleanup past that point.
- */
- kobject_get(bdev->bd_holder_dir);
+ mutex_unlock(&disk->open_mutex);
+ return 0;
+
+out_del_symlink:
+ del_symlink(disk->slave_dir, bdev_kobj(bdev));
+out_free_holder:
+ kfree(holder);
out_unlock:
mutex_unlock(&disk->open_mutex);
+ if (ret)
+ kobject_put(bdev->bd_holder_dir);
return ret;
}
EXPORT_SYMBOL_GPL(bd_link_disk_holder);
-static void __unlink_disk_holder(struct block_device *bdev,
- struct gendisk *disk)
-{
- del_symlink(disk->slave_dir, bdev_kobj(bdev));
- del_symlink(bdev->bd_holder_dir, &disk_to_dev(disk)->kobj);
-}
-
/**
* bd_unlink_disk_holder - destroy symlinks created by bd_link_disk_holder()
* @bdev: the calimed slave bdev
@@ -136,36 +137,18 @@ void bd_unlink_disk_holder(struct block_device *bdev, struct gendisk *disk)
{
struct bd_holder_disk *holder;
+ if (WARN_ON_ONCE(!disk->slave_dir))
+ return;
+
mutex_lock(&disk->open_mutex);
holder = bd_find_holder_disk(bdev, disk);
if (!WARN_ON_ONCE(holder == NULL) && !--holder->refcnt) {
- if (disk->slave_dir)
- __unlink_disk_holder(bdev, disk);
- kobject_put(bdev->bd_holder_dir);
+ del_symlink(disk->slave_dir, bdev_kobj(bdev));
+ del_symlink(holder->holder_dir, &disk_to_dev(disk)->kobj);
+ kobject_put(holder->holder_dir);
list_del_init(&holder->list);
kfree(holder);
}
mutex_unlock(&disk->open_mutex);
}
EXPORT_SYMBOL_GPL(bd_unlink_disk_holder);
-
-int bd_register_pending_holders(struct gendisk *disk)
-{
- struct bd_holder_disk *holder;
- int ret;
-
- mutex_lock(&disk->open_mutex);
- list_for_each_entry(holder, &disk->slave_bdevs, list) {
- ret = __link_disk_holder(holder->bdev, disk);
- if (ret)
- goto out_undo;
- }
- mutex_unlock(&disk->open_mutex);
- return 0;
-
-out_undo:
- list_for_each_entry_continue_reverse(holder, &disk->slave_bdevs, list)
- __unlink_disk_holder(holder->bdev, disk);
- mutex_unlock(&disk->open_mutex);
- return ret;
-}
diff --git a/block/ioctl.c b/block/ioctl.c
index 60121e89052b..96617512982e 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -467,9 +467,10 @@ static int blkdev_bszset(struct block_device *bdev, fmode_t mode,
* user space. Note the separate arg/argp parameters that are needed
* to deal with the compat_ptr() conversion.
*/
-static int blkdev_common_ioctl(struct block_device *bdev, fmode_t mode,
- unsigned cmd, unsigned long arg, void __user *argp)
+static int blkdev_common_ioctl(struct file *file, fmode_t mode, unsigned cmd,
+ unsigned long arg, void __user *argp)
{
+ struct block_device *bdev = I_BDEV(file->f_mapping->host);
unsigned int max_sectors;
switch (cmd) {
@@ -527,7 +528,8 @@ static int blkdev_common_ioctl(struct block_device *bdev, fmode_t mode,
return -EACCES;
if (bdev_is_partition(bdev))
return -EINVAL;
- return disk_scan_partitions(bdev->bd_disk, mode & ~FMODE_EXCL);
+ return disk_scan_partitions(bdev->bd_disk, mode & ~FMODE_EXCL,
+ file);
case BLKTRACESTART:
case BLKTRACESTOP:
case BLKTRACETEARDOWN:
@@ -605,7 +607,7 @@ long blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
break;
}
- ret = blkdev_common_ioctl(bdev, mode, cmd, arg, argp);
+ ret = blkdev_common_ioctl(file, mode, cmd, arg, argp);
if (ret != -ENOIOCTLCMD)
return ret;
@@ -674,7 +676,7 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
break;
}
- ret = blkdev_common_ioctl(bdev, mode, cmd, arg, argp);
+ ret = blkdev_common_ioctl(file, mode, cmd, arg, argp);
if (ret == -ENOIOCTLCMD && disk->fops->compat_ioctl)
ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
diff --git a/block/mq-deadline.c b/block/mq-deadline.c
index 5639921dfa92..f10c2a0d18d4 100644
--- a/block/mq-deadline.c
+++ b/block/mq-deadline.c
@@ -131,6 +131,20 @@ static u8 dd_rq_ioclass(struct request *rq)
}
/*
+ * get the request before `rq' in sector-sorted order
+ */
+static inline struct request *
+deadline_earlier_request(struct request *rq)
+{
+ struct rb_node *node = rb_prev(&rq->rb_node);
+
+ if (node)
+ return rb_entry_rq(node);
+
+ return NULL;
+}
+
+/*
* get the request after `rq' in sector-sorted order
*/
static inline struct request *
@@ -278,6 +292,39 @@ static inline int deadline_check_fifo(struct dd_per_prio *per_prio,
}
/*
+ * Check if rq has a sequential request preceding it.
+ */
+static bool deadline_is_seq_write(struct deadline_data *dd, struct request *rq)
+{
+ struct request *prev = deadline_earlier_request(rq);
+
+ if (!prev)
+ return false;
+
+ return blk_rq_pos(prev) + blk_rq_sectors(prev) == blk_rq_pos(rq);
+}
+
+/*
+ * Skip all write requests that are sequential from @rq, even if we cross
+ * a zone boundary.
+ */
+static struct request *deadline_skip_seq_writes(struct deadline_data *dd,
+ struct request *rq)
+{
+ sector_t pos = blk_rq_pos(rq);
+ sector_t skipped_sectors = 0;
+
+ while (rq) {
+ if (blk_rq_pos(rq) != pos + skipped_sectors)
+ break;
+ skipped_sectors += blk_rq_sectors(rq);
+ rq = deadline_latter_request(rq);
+ }
+
+ return rq;
+}
+
+/*
* For the specified data direction, return the next request to
* dispatch using arrival ordered lists.
*/
@@ -297,11 +344,16 @@ deadline_fifo_request(struct deadline_data *dd, struct dd_per_prio *per_prio,
/*
* Look for a write request that can be dispatched, that is one with
- * an unlocked target zone.
+ * an unlocked target zone. For some HDDs, breaking a sequential
+ * write stream can lead to lower throughput, so make sure to preserve
+ * sequential write streams, even if that stream crosses into the next
+ * zones and these zones are unlocked.
*/
spin_lock_irqsave(&dd->zone_lock, flags);
list_for_each_entry(rq, &per_prio->fifo_list[DD_WRITE], queuelist) {
- if (blk_req_can_dispatch_to_zone(rq))
+ if (blk_req_can_dispatch_to_zone(rq) &&
+ (blk_queue_nonrot(rq->q) ||
+ !deadline_is_seq_write(dd, rq)))
goto out;
}
rq = NULL;
@@ -331,13 +383,19 @@ deadline_next_request(struct deadline_data *dd, struct dd_per_prio *per_prio,
/*
* Look for a write request that can be dispatched, that is one with
- * an unlocked target zone.
+ * an unlocked target zone. For some HDDs, breaking a sequential
+ * write stream can lead to lower throughput, so make sure to preserve
+ * sequential write streams, even if that stream crosses into the next
+ * zones and these zones are unlocked.
*/
spin_lock_irqsave(&dd->zone_lock, flags);
while (rq) {
if (blk_req_can_dispatch_to_zone(rq))
break;
- rq = deadline_latter_request(rq);
+ if (blk_queue_nonrot(rq->q))
+ rq = deadline_latter_request(rq);
+ else
+ rq = deadline_skip_seq_writes(dd, rq);
}
spin_unlock_irqrestore(&dd->zone_lock, flags);
@@ -789,6 +847,18 @@ static void dd_prepare_request(struct request *rq)
rq->elv.priv[0] = NULL;
}
+static bool dd_has_write_work(struct blk_mq_hw_ctx *hctx)
+{
+ struct deadline_data *dd = hctx->queue->elevator->elevator_data;
+ enum dd_prio p;
+
+ for (p = 0; p <= DD_PRIO_MAX; p++)
+ if (!list_empty_careful(&dd->per_prio[p].fifo_list[DD_WRITE]))
+ return true;
+
+ return false;
+}
+
/*
* Callback from inside blk_mq_free_request().
*
@@ -828,9 +898,10 @@ static void dd_finish_request(struct request *rq)
spin_lock_irqsave(&dd->zone_lock, flags);
blk_req_zone_write_unlock(rq);
- if (!list_empty(&per_prio->fifo_list[DD_WRITE]))
- blk_mq_sched_mark_restart_hctx(rq->mq_hctx);
spin_unlock_irqrestore(&dd->zone_lock, flags);
+
+ if (dd_has_write_work(rq->mq_hctx))
+ blk_mq_sched_mark_restart_hctx(rq->mq_hctx);
}
}
diff --git a/block/sed-opal.c b/block/sed-opal.c
index 9bdb833e5817..463873f61e01 100644
--- a/block/sed-opal.c
+++ b/block/sed-opal.c
@@ -2461,6 +2461,44 @@ static int __opal_set_mbr_done(struct opal_dev *dev, struct opal_key *key)
return execute_steps(dev, mbrdone_step, ARRAY_SIZE(mbrdone_step));
}
+static void opal_lock_check_for_saved_key(struct opal_dev *dev,
+ struct opal_lock_unlock *lk_unlk)
+{
+ struct opal_suspend_data *iter;
+
+ if (lk_unlk->l_state != OPAL_LK ||
+ lk_unlk->session.opal_key.key_len > 0)
+ return;
+
+ /*
+ * Usually when closing a crypto device (eg: dm-crypt with LUKS) the
+ * volume key is not required, as it requires root privileges anyway,
+ * and root can deny access to a disk in many ways regardless.
+ * Requiring the volume key to lock the device is a peculiarity of the
+ * OPAL specification. Given we might already have saved the key if
+ * the user requested it via the 'IOC_OPAL_SAVE' ioctl, we can use
+ * that key to lock the device if no key was provided here, the
+ * locking range matches and the appropriate flag was passed with
+ * 'IOC_OPAL_SAVE'.
+ * This allows integrating OPAL with tools and libraries that are used
+ * to the common behaviour and do not ask for the volume key when
+ * closing a device.
+ */
+ setup_opal_dev(dev);
+ list_for_each_entry(iter, &dev->unlk_lst, node) {
+ if ((iter->unlk.flags & OPAL_SAVE_FOR_LOCK) &&
+ iter->lr == lk_unlk->session.opal_key.lr &&
+ iter->unlk.session.opal_key.key_len > 0) {
+ lk_unlk->session.opal_key.key_len =
+ iter->unlk.session.opal_key.key_len;
+ memcpy(lk_unlk->session.opal_key.key,
+ iter->unlk.session.opal_key.key,
+ iter->unlk.session.opal_key.key_len);
+ break;
+ }
+ }
+}
+
static int opal_lock_unlock(struct opal_dev *dev,
struct opal_lock_unlock *lk_unlk)
{
@@ -2470,6 +2508,7 @@ static int opal_lock_unlock(struct opal_dev *dev,
return -EINVAL;
mutex_lock(&dev->dev_lock);
+ opal_lock_check_for_saved_key(dev, lk_unlk);
ret = __opal_lock_unlock(dev, lk_unlk);
mutex_unlock(&dev->dev_lock);
diff --git a/crypto/rsa-pkcs1pad.c b/crypto/rsa-pkcs1pad.c
index 3285e3af43e1..e75728f87ce5 100644
--- a/crypto/rsa-pkcs1pad.c
+++ b/crypto/rsa-pkcs1pad.c
@@ -253,7 +253,7 @@ static int pkcs1pad_encrypt(struct akcipher_request *req)
ps_end = ctx->key_size - req->src_len - 2;
req_ctx->in_buf[0] = 0x02;
for (i = 1; i < ps_end; i++)
- req_ctx->in_buf[i] = 1 + prandom_u32_max(255);
+ req_ctx->in_buf[i] = get_random_u32_inclusive(1, 255);
req_ctx->in_buf[ps_end] = 0x00;
pkcs1pad_sg_set_buf(req_ctx->in_sg, req_ctx->in_buf,
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index bcd059caa1c8..589189c9fced 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -766,7 +766,7 @@ static int build_cipher_test_sglists(struct cipher_test_sglists *tsgls,
struct iov_iter input;
int err;
- iov_iter_kvec(&input, WRITE, inputs, nr_inputs, src_total_len);
+ iov_iter_kvec(&input, ITER_SOURCE, inputs, nr_inputs, src_total_len);
err = build_test_sglist(&tsgls->src, cfg->src_divs, alignmask,
cfg->inplace_mode != OUT_OF_PLACE ?
max(dst_total_len, src_total_len) :
@@ -855,9 +855,9 @@ static int prepare_keybuf(const u8 *key, unsigned int ksize,
/* Generate a random length in range [0, max_len], but prefer smaller values */
static unsigned int generate_random_length(unsigned int max_len)
{
- unsigned int len = prandom_u32_max(max_len + 1);
+ unsigned int len = get_random_u32_below(max_len + 1);
- switch (prandom_u32_max(4)) {
+ switch (get_random_u32_below(4)) {
case 0:
return len % 64;
case 1:
@@ -874,14 +874,14 @@ static void flip_random_bit(u8 *buf, size_t size)
{
size_t bitpos;
- bitpos = prandom_u32_max(size * 8);
+ bitpos = get_random_u32_below(size * 8);
buf[bitpos / 8] ^= 1 << (bitpos % 8);
}
/* Flip a random byte in the given nonempty data buffer */
static void flip_random_byte(u8 *buf, size_t size)
{
- buf[prandom_u32_max(size)] ^= 0xff;
+ buf[get_random_u32_below(size)] ^= 0xff;
}
/* Sometimes make some random changes to the given nonempty data buffer */
@@ -891,15 +891,15 @@ static void mutate_buffer(u8 *buf, size_t size)
size_t i;
/* Sometimes flip some bits */
- if (prandom_u32_max(4) == 0) {
- num_flips = min_t(size_t, 1 << prandom_u32_max(8), size * 8);
+ if (get_random_u32_below(4) == 0) {
+ num_flips = min_t(size_t, 1 << get_random_u32_below(8), size * 8);
for (i = 0; i < num_flips; i++)
flip_random_bit(buf, size);
}
/* Sometimes flip some bytes */
- if (prandom_u32_max(4) == 0) {
- num_flips = min_t(size_t, 1 << prandom_u32_max(8), size);
+ if (get_random_u32_below(4) == 0) {
+ num_flips = min_t(size_t, 1 << get_random_u32_below(8), size);
for (i = 0; i < num_flips; i++)
flip_random_byte(buf, size);
}
@@ -915,11 +915,11 @@ static void generate_random_bytes(u8 *buf, size_t count)
if (count == 0)
return;
- switch (prandom_u32_max(8)) { /* Choose a generation strategy */
+ switch (get_random_u32_below(8)) { /* Choose a generation strategy */
case 0:
case 1:
/* All the same byte, plus optional mutations */
- switch (prandom_u32_max(4)) {
+ switch (get_random_u32_below(4)) {
case 0:
b = 0x00;
break;
@@ -959,24 +959,24 @@ static char *generate_random_sgl_divisions(struct test_sg_division *divs,
unsigned int this_len;
const char *flushtype_str;
- if (div == &divs[max_divs - 1] || prandom_u32_max(2) == 0)
+ if (div == &divs[max_divs - 1] || get_random_u32_below(2) == 0)
this_len = remaining;
else
- this_len = 1 + prandom_u32_max(remaining);
+ this_len = get_random_u32_inclusive(1, remaining);
div->proportion_of_total = this_len;
- if (prandom_u32_max(4) == 0)
- div->offset = (PAGE_SIZE - 128) + prandom_u32_max(128);
- else if (prandom_u32_max(2) == 0)
- div->offset = prandom_u32_max(32);
+ if (get_random_u32_below(4) == 0)
+ div->offset = get_random_u32_inclusive(PAGE_SIZE - 128, PAGE_SIZE - 1);
+ else if (get_random_u32_below(2) == 0)
+ div->offset = get_random_u32_below(32);
else
- div->offset = prandom_u32_max(PAGE_SIZE);
- if (prandom_u32_max(8) == 0)
+ div->offset = get_random_u32_below(PAGE_SIZE);
+ if (get_random_u32_below(8) == 0)
div->offset_relative_to_alignmask = true;
div->flush_type = FLUSH_TYPE_NONE;
if (gen_flushes) {
- switch (prandom_u32_max(4)) {
+ switch (get_random_u32_below(4)) {
case 0:
div->flush_type = FLUSH_TYPE_REIMPORT;
break;
@@ -988,7 +988,7 @@ static char *generate_random_sgl_divisions(struct test_sg_division *divs,
if (div->flush_type != FLUSH_TYPE_NONE &&
!(req_flags & CRYPTO_TFM_REQ_MAY_SLEEP) &&
- prandom_u32_max(2) == 0)
+ get_random_u32_below(2) == 0)
div->nosimd = true;
switch (div->flush_type) {
@@ -1035,7 +1035,7 @@ static void generate_random_testvec_config(struct testvec_config *cfg,
p += scnprintf(p, end - p, "random:");
- switch (prandom_u32_max(4)) {
+ switch (get_random_u32_below(4)) {
case 0:
case 1:
cfg->inplace_mode = OUT_OF_PLACE;
@@ -1050,12 +1050,12 @@ static void generate_random_testvec_config(struct testvec_config *cfg,
break;
}
- if (prandom_u32_max(2) == 0) {
+ if (get_random_u32_below(2) == 0) {
cfg->req_flags |= CRYPTO_TFM_REQ_MAY_SLEEP;
p += scnprintf(p, end - p, " may_sleep");
}
- switch (prandom_u32_max(4)) {
+ switch (get_random_u32_below(4)) {
case 0:
cfg->finalization_type = FINALIZATION_TYPE_FINAL;
p += scnprintf(p, end - p, " use_final");
@@ -1071,7 +1071,7 @@ static void generate_random_testvec_config(struct testvec_config *cfg,
}
if (!(cfg->req_flags & CRYPTO_TFM_REQ_MAY_SLEEP) &&
- prandom_u32_max(2) == 0) {
+ get_random_u32_below(2) == 0) {
cfg->nosimd = true;
p += scnprintf(p, end - p, " nosimd");
}
@@ -1084,7 +1084,7 @@ static void generate_random_testvec_config(struct testvec_config *cfg,
cfg->req_flags);
p += scnprintf(p, end - p, "]");
- if (cfg->inplace_mode == OUT_OF_PLACE && prandom_u32_max(2) == 0) {
+ if (cfg->inplace_mode == OUT_OF_PLACE && get_random_u32_below(2) == 0) {
p += scnprintf(p, end - p, " dst_divs=[");
p = generate_random_sgl_divisions(cfg->dst_divs,
ARRAY_SIZE(cfg->dst_divs),
@@ -1093,13 +1093,13 @@ static void generate_random_testvec_config(struct testvec_config *cfg,
p += scnprintf(p, end - p, "]");
}
- if (prandom_u32_max(2) == 0) {
- cfg->iv_offset = 1 + prandom_u32_max(MAX_ALGAPI_ALIGNMASK);
+ if (get_random_u32_below(2) == 0) {
+ cfg->iv_offset = get_random_u32_inclusive(1, MAX_ALGAPI_ALIGNMASK);
p += scnprintf(p, end - p, " iv_offset=%u", cfg->iv_offset);
}
- if (prandom_u32_max(2) == 0) {
- cfg->key_offset = 1 + prandom_u32_max(MAX_ALGAPI_ALIGNMASK);
+ if (get_random_u32_below(2) == 0) {
+ cfg->key_offset = get_random_u32_inclusive(1, MAX_ALGAPI_ALIGNMASK);
p += scnprintf(p, end - p, " key_offset=%u", cfg->key_offset);
}
@@ -1180,7 +1180,7 @@ static int build_hash_sglist(struct test_sglist *tsgl,
kv.iov_base = (void *)vec->plaintext;
kv.iov_len = vec->psize;
- iov_iter_kvec(&input, WRITE, &kv, 1, vec->psize);
+ iov_iter_kvec(&input, ITER_SOURCE, &kv, 1, vec->psize);
return build_test_sglist(tsgl, cfg->src_divs, alignmask, vec->psize,
&input, divs);
}
@@ -1652,8 +1652,8 @@ static void generate_random_hash_testvec(struct shash_desc *desc,
vec->ksize = 0;
if (maxkeysize) {
vec->ksize = maxkeysize;
- if (prandom_u32_max(4) == 0)
- vec->ksize = 1 + prandom_u32_max(maxkeysize);
+ if (get_random_u32_below(4) == 0)
+ vec->ksize = get_random_u32_inclusive(1, maxkeysize);
generate_random_bytes((u8 *)vec->key, vec->ksize);
vec->setkey_error = crypto_shash_setkey(desc->tfm, vec->key,
@@ -2218,13 +2218,13 @@ static void mutate_aead_message(struct aead_testvec *vec, bool aad_iv,
const unsigned int aad_tail_size = aad_iv ? ivsize : 0;
const unsigned int authsize = vec->clen - vec->plen;
- if (prandom_u32_max(2) == 0 && vec->alen > aad_tail_size) {
+ if (get_random_u32_below(2) == 0 && vec->alen > aad_tail_size) {
/* Mutate the AAD */
flip_random_bit((u8 *)vec->assoc, vec->alen - aad_tail_size);
- if (prandom_u32_max(2) == 0)
+ if (get_random_u32_below(2) == 0)
return;
}
- if (prandom_u32_max(2) == 0) {
+ if (get_random_u32_below(2) == 0) {
/* Mutate auth tag (assuming it's at the end of ciphertext) */
flip_random_bit((u8 *)vec->ctext + vec->plen, authsize);
} else {
@@ -2249,7 +2249,7 @@ static void generate_aead_message(struct aead_request *req,
const unsigned int ivsize = crypto_aead_ivsize(tfm);
const unsigned int authsize = vec->clen - vec->plen;
const bool inauthentic = (authsize >= MIN_COLLISION_FREE_AUTHSIZE) &&
- (prefer_inauthentic || prandom_u32_max(4) == 0);
+ (prefer_inauthentic || get_random_u32_below(4) == 0);
/* Generate the AAD. */
generate_random_bytes((u8 *)vec->assoc, vec->alen);
@@ -2257,7 +2257,7 @@ static void generate_aead_message(struct aead_request *req,
/* Avoid implementation-defined behavior. */
memcpy((u8 *)vec->assoc + vec->alen - ivsize, vec->iv, ivsize);
- if (inauthentic && prandom_u32_max(2) == 0) {
+ if (inauthentic && get_random_u32_below(2) == 0) {
/* Generate a random ciphertext. */
generate_random_bytes((u8 *)vec->ctext, vec->clen);
} else {
@@ -2321,8 +2321,8 @@ static void generate_random_aead_testvec(struct aead_request *req,
/* Key: length in [0, maxkeysize], but usually choose maxkeysize */
vec->klen = maxkeysize;
- if (prandom_u32_max(4) == 0)
- vec->klen = prandom_u32_max(maxkeysize + 1);
+ if (get_random_u32_below(4) == 0)
+ vec->klen = get_random_u32_below(maxkeysize + 1);
generate_random_bytes((u8 *)vec->key, vec->klen);
vec->setkey_error = crypto_aead_setkey(tfm, vec->key, vec->klen);
@@ -2331,8 +2331,8 @@ static void generate_random_aead_testvec(struct aead_request *req,
/* Tag length: in [0, maxauthsize], but usually choose maxauthsize */
authsize = maxauthsize;
- if (prandom_u32_max(4) == 0)
- authsize = prandom_u32_max(maxauthsize + 1);
+ if (get_random_u32_below(4) == 0)
+ authsize = get_random_u32_below(maxauthsize + 1);
if (prefer_inauthentic && authsize < MIN_COLLISION_FREE_AUTHSIZE)
authsize = MIN_COLLISION_FREE_AUTHSIZE;
if (WARN_ON(authsize > maxdatasize))
@@ -2342,7 +2342,7 @@ static void generate_random_aead_testvec(struct aead_request *req,
/* AAD, plaintext, and ciphertext lengths */
total_len = generate_random_length(maxdatasize);
- if (prandom_u32_max(4) == 0)
+ if (get_random_u32_below(4) == 0)
vec->alen = 0;
else
vec->alen = generate_random_length(total_len);
@@ -2958,8 +2958,8 @@ static void generate_random_cipher_testvec(struct skcipher_request *req,
/* Key: length in [0, maxkeysize], but usually choose maxkeysize */
vec->klen = maxkeysize;
- if (prandom_u32_max(4) == 0)
- vec->klen = prandom_u32_max(maxkeysize + 1);
+ if (get_random_u32_below(4) == 0)
+ vec->klen = get_random_u32_below(maxkeysize + 1);
generate_random_bytes((u8 *)vec->key, vec->klen);
vec->setkey_error = crypto_skcipher_setkey(tfm, vec->key, vec->klen);
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 19ee995bd0ae..968bd0a6fd78 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -99,6 +99,8 @@ source "drivers/media/Kconfig"
source "drivers/video/Kconfig"
+source "drivers/accel/Kconfig"
+
source "sound/Kconfig"
source "drivers/hid/Kconfig"
diff --git a/drivers/accel/Kconfig b/drivers/accel/Kconfig
new file mode 100644
index 000000000000..c9ce849b2984
--- /dev/null
+++ b/drivers/accel/Kconfig
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Compute Acceleration device configuration
+#
+# This framework provides support for compute acceleration devices, such
+# as, but not limited to, Machine-Learning and Deep-Learning acceleration
+# devices
+#
+menuconfig DRM_ACCEL
+ bool "Compute Acceleration Framework"
+ depends on DRM
+ help
+ Framework for device drivers of compute acceleration devices, such
+ as, but not limited to, Machine-Learning and Deep-Learning
+ acceleration devices.
+ If you say Y here, you need to select the module that's right for
+ your acceleration device from the list below.
+ This framework is integrated with the DRM subsystem as compute
+ accelerators and GPUs share a lot in common and can use almost the
+ same infrastructure code.
+ Having said that, acceleration devices will have a different
+ major number than GPUs, and will be exposed to user-space using
+ different device files, called accel/accel* (in /dev, sysfs
+ and debugfs).
diff --git a/drivers/accel/drm_accel.c b/drivers/accel/drm_accel.c
new file mode 100644
index 000000000000..a5ee84a4017a
--- /dev/null
+++ b/drivers/accel/drm_accel.c
@@ -0,0 +1,323 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Copyright 2022 HabanaLabs, Ltd.
+ * All Rights Reserved.
+ *
+ */
+
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/idr.h>
+
+#include <drm/drm_accel.h>
+#include <drm/drm_debugfs.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_file.h>
+#include <drm/drm_ioctl.h>
+#include <drm/drm_print.h>
+
+static DEFINE_SPINLOCK(accel_minor_lock);
+static struct idr accel_minors_idr;
+
+static struct dentry *accel_debugfs_root;
+static struct class *accel_class;
+
+static struct device_type accel_sysfs_device_minor = {
+ .name = "accel_minor"
+};
+
+static char *accel_devnode(struct device *dev, umode_t *mode)
+{
+ return kasprintf(GFP_KERNEL, "accel/%s", dev_name(dev));
+}
+
+static int accel_sysfs_init(void)
+{
+ accel_class = class_create(THIS_MODULE, "accel");
+ if (IS_ERR(accel_class))
+ return PTR_ERR(accel_class);
+
+ accel_class->devnode = accel_devnode;
+
+ return 0;
+}
+
+static void accel_sysfs_destroy(void)
+{
+ if (IS_ERR_OR_NULL(accel_class))
+ return;
+ class_destroy(accel_class);
+ accel_class = NULL;
+}
+
+static int accel_name_info(struct seq_file *m, void *data)
+{
+ struct drm_info_node *node = (struct drm_info_node *) m->private;
+ struct drm_minor *minor = node->minor;
+ struct drm_device *dev = minor->dev;
+ struct drm_master *master;
+
+ mutex_lock(&dev->master_mutex);
+ master = dev->master;
+ seq_printf(m, "%s", dev->driver->name);
+ if (dev->dev)
+ seq_printf(m, " dev=%s", dev_name(dev->dev));
+ if (master && master->unique)
+ seq_printf(m, " master=%s", master->unique);
+ if (dev->unique)
+ seq_printf(m, " unique=%s", dev->unique);
+ seq_puts(m, "\n");
+ mutex_unlock(&dev->master_mutex);
+
+ return 0;
+}
+
+static const struct drm_info_list accel_debugfs_list[] = {
+ {"name", accel_name_info, 0}
+};
+#define ACCEL_DEBUGFS_ENTRIES ARRAY_SIZE(accel_debugfs_list)
+
+/**
+ * accel_debugfs_init() - Initialize debugfs for accel minor
+ * @minor: Pointer to the drm_minor instance.
+ * @minor_id: The minor's id
+ *
+ * This function initializes the drm minor's debugfs members and creates
+ * a root directory for the minor in debugfs. It also creates common files
+ * for accelerators and calls the driver's debugfs init callback.
+ */
+void accel_debugfs_init(struct drm_minor *minor, int minor_id)
+{
+ struct drm_device *dev = minor->dev;
+ char name[64];
+
+ INIT_LIST_HEAD(&minor->debugfs_list);
+ mutex_init(&minor->debugfs_lock);
+ sprintf(name, "%d", minor_id);
+ minor->debugfs_root = debugfs_create_dir(name, accel_debugfs_root);
+
+ drm_debugfs_create_files(accel_debugfs_list, ACCEL_DEBUGFS_ENTRIES,
+ minor->debugfs_root, minor);
+
+ if (dev->driver->debugfs_init)
+ dev->driver->debugfs_init(minor);
+}
+
+/**
+ * accel_set_device_instance_params() - Set some device parameters for accel device
+ * @kdev: Pointer to the device instance.
+ * @index: The minor's index
+ *
+ * This function creates the dev_t of the device using the accel major and
+ * the device's minor number. In addition, it sets the class and type of the
+ * device instance to the accel sysfs class and device type, respectively.
+ */
+void accel_set_device_instance_params(struct device *kdev, int index)
+{
+ kdev->devt = MKDEV(ACCEL_MAJOR, index);
+ kdev->class = accel_class;
+ kdev->type = &accel_sysfs_device_minor;
+}
+
+/**
+ * accel_minor_alloc() - Allocates a new accel minor
+ *
+ * This function access the accel minors idr and allocates from it
+ * a new id to represent a new accel minor
+ *
+ * Return: A new id on success or error code in case idr_alloc failed
+ */
+int accel_minor_alloc(void)
+{
+ unsigned long flags;
+ int r;
+
+ spin_lock_irqsave(&accel_minor_lock, flags);
+ r = idr_alloc(&accel_minors_idr, NULL, 0, ACCEL_MAX_MINORS, GFP_NOWAIT);
+ spin_unlock_irqrestore(&accel_minor_lock, flags);
+
+ return r;
+}
+
+/**
+ * accel_minor_remove() - Remove an accel minor
+ * @index: The minor id to remove.
+ *
+ * This function access the accel minors idr and removes from
+ * it the member with the id that is passed to this function.
+ */
+void accel_minor_remove(int index)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&accel_minor_lock, flags);
+ idr_remove(&accel_minors_idr, index);
+ spin_unlock_irqrestore(&accel_minor_lock, flags);
+}
+
+/**
+ * accel_minor_replace() - Replace minor pointer in accel minors idr.
+ * @minor: Pointer to the new minor.
+ * @index: The minor id to replace.
+ *
+ * This function access the accel minors idr structure and replaces the pointer
+ * that is associated with an existing id. Because the minor pointer can be
+ * NULL, we need to explicitly pass the index.
+ *
+ * Return: 0 for success, negative value for error
+ */
+void accel_minor_replace(struct drm_minor *minor, int index)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&accel_minor_lock, flags);
+ idr_replace(&accel_minors_idr, minor, index);
+ spin_unlock_irqrestore(&accel_minor_lock, flags);
+}
+
+/*
+ * Looks up the given minor-ID and returns the respective DRM-minor object. The
+ * refence-count of the underlying device is increased so you must release this
+ * object with accel_minor_release().
+ *
+ * The object can be only a drm_minor that represents an accel device.
+ *
+ * As long as you hold this minor, it is guaranteed that the object and the
+ * minor->dev pointer will stay valid! However, the device may get unplugged and
+ * unregistered while you hold the minor.
+ */
+static struct drm_minor *accel_minor_acquire(unsigned int minor_id)
+{
+ struct drm_minor *minor;
+ unsigned long flags;
+
+ spin_lock_irqsave(&accel_minor_lock, flags);
+ minor = idr_find(&accel_minors_idr, minor_id);
+ if (minor)
+ drm_dev_get(minor->dev);
+ spin_unlock_irqrestore(&accel_minor_lock, flags);
+
+ if (!minor) {
+ return ERR_PTR(-ENODEV);
+ } else if (drm_dev_is_unplugged(minor->dev)) {
+ drm_dev_put(minor->dev);
+ return ERR_PTR(-ENODEV);
+ }
+
+ return minor;
+}
+
+static void accel_minor_release(struct drm_minor *minor)
+{
+ drm_dev_put(minor->dev);
+}
+
+/**
+ * accel_open - open method for ACCEL file
+ * @inode: device inode
+ * @filp: file pointer.
+ *
+ * This function must be used by drivers as their &file_operations.open method.
+ * It looks up the correct ACCEL device and instantiates all the per-file
+ * resources for it. It also calls the &drm_driver.open driver callback.
+ *
+ * Return: 0 on success or negative errno value on failure.
+ */
+int accel_open(struct inode *inode, struct file *filp)
+{
+ struct drm_device *dev;
+ struct drm_minor *minor;
+ int retcode;
+
+ minor = accel_minor_acquire(iminor(inode));
+ if (IS_ERR(minor))
+ return PTR_ERR(minor);
+
+ dev = minor->dev;
+
+ atomic_fetch_inc(&dev->open_count);
+
+ /* share address_space across all char-devs of a single device */
+ filp->f_mapping = dev->anon_inode->i_mapping;
+
+ retcode = drm_open_helper(filp, minor);
+ if (retcode)
+ goto err_undo;
+
+ return 0;
+
+err_undo:
+ atomic_dec(&dev->open_count);
+ accel_minor_release(minor);
+ return retcode;
+}
+EXPORT_SYMBOL_GPL(accel_open);
+
+static int accel_stub_open(struct inode *inode, struct file *filp)
+{
+ const struct file_operations *new_fops;
+ struct drm_minor *minor;
+ int err;
+
+ minor = accel_minor_acquire(iminor(inode));
+ if (IS_ERR(minor))
+ return PTR_ERR(minor);
+
+ new_fops = fops_get(minor->dev->driver->fops);
+ if (!new_fops) {
+ err = -ENODEV;
+ goto out;
+ }
+
+ replace_fops(filp, new_fops);
+ if (filp->f_op->open)
+ err = filp->f_op->open(inode, filp);
+ else
+ err = 0;
+
+out:
+ accel_minor_release(minor);
+
+ return err;
+}
+
+static const struct file_operations accel_stub_fops = {
+ .owner = THIS_MODULE,
+ .open = accel_stub_open,
+ .llseek = noop_llseek,
+};
+
+void accel_core_exit(void)
+{
+ unregister_chrdev(ACCEL_MAJOR, "accel");
+ debugfs_remove(accel_debugfs_root);
+ accel_sysfs_destroy();
+ idr_destroy(&accel_minors_idr);
+}
+
+int __init accel_core_init(void)
+{
+ int ret;
+
+ idr_init(&accel_minors_idr);
+
+ ret = accel_sysfs_init();
+ if (ret < 0) {
+ DRM_ERROR("Cannot create ACCEL class: %d\n", ret);
+ goto error;
+ }
+
+ accel_debugfs_root = debugfs_create_dir("accel", NULL);
+
+ ret = register_chrdev(ACCEL_MAJOR, "accel", &accel_stub_fops);
+ if (ret < 0)
+ DRM_ERROR("Cannot register ACCEL major: %d\n", ret);
+
+error:
+ /*
+ * Any cleanup due to errors will be done in drm_core_exit() that
+ * will call accel_core_exit()
+ */
+ return ret;
+}
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index 473241b5193f..ccbeab9500ec 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -90,7 +90,7 @@ config ACPI_SPCR_TABLE
config ACPI_FPDT
bool "ACPI Firmware Performance Data Table (FPDT) support"
- depends on X86_64
+ depends on X86_64 || ARM64
help
Enable support for the Firmware Performance Data Table (FPDT).
This table provides information on the timing of the system
@@ -564,6 +564,16 @@ config ACPI_PCC
Enable this feature if you want to set up and install the PCC Address
Space handler to handle PCC OpRegion in the firmware.
+config ACPI_FFH
+ bool "ACPI FFH Address Space"
+ default n
+ help
+ The FFH(Fixed Function Hardware) Address Space also referred as FFH
+ Operation Region allows to define platform specific opregion.
+
+ Enable this feature if you want to set up and install the FFH Address
+ Space handler to handle FFH OpRegion in the firmware.
+
source "drivers/acpi/pmic/Kconfig"
config ACPI_VIOT
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index 0002eecbf870..feb36c0b9446 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -68,6 +68,7 @@ acpi-$(CONFIG_ACPI_GENERIC_GSI) += irq.o
acpi-$(CONFIG_ACPI_WATCHDOG) += acpi_watchdog.o
acpi-$(CONFIG_ACPI_PRMT) += prmt.o
acpi-$(CONFIG_ACPI_PCC) += acpi_pcc.o
+acpi-$(CONFIG_ACPI_FFH) += acpi_ffh.o
# Address translation
acpi-$(CONFIG_ACPI_ADXL) += acpi_adxl.o
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index bb9fe7984b1a..1ace70b831cd 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -33,7 +33,7 @@ MODULE_DESCRIPTION("ACPI AC Adapter Driver");
MODULE_LICENSE("GPL");
static int acpi_ac_add(struct acpi_device *device);
-static int acpi_ac_remove(struct acpi_device *device);
+static void acpi_ac_remove(struct acpi_device *device);
static void acpi_ac_notify(struct acpi_device *device, u32 event);
static const struct acpi_device_id ac_device_ids[] = {
@@ -288,12 +288,12 @@ static int acpi_ac_resume(struct device *dev)
#define acpi_ac_resume NULL
#endif
-static int acpi_ac_remove(struct acpi_device *device)
+static void acpi_ac_remove(struct acpi_device *device)
{
struct acpi_ac *ac = NULL;
if (!device || !acpi_driver_data(device))
- return -EINVAL;
+ return;
ac = acpi_driver_data(device);
@@ -301,8 +301,6 @@ static int acpi_ac_remove(struct acpi_device *device)
unregister_acpi_notifier(&ac->battery_nb);
kfree(ac);
-
- return 0;
}
static int __init acpi_ac_init(void)
diff --git a/drivers/acpi/acpi_ffh.c b/drivers/acpi/acpi_ffh.c
new file mode 100644
index 000000000000..19aff808bbb8
--- /dev/null
+++ b/drivers/acpi/acpi_ffh.c
@@ -0,0 +1,55 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Author: Sudeep Holla <sudeep.holla@arm.com>
+ * Copyright 2022 Arm Limited
+ */
+#include <linux/kernel.h>
+#include <linux/acpi.h>
+#include <linux/completion.h>
+#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,
+ void **region_ctxt)
+{
+ return -EOPNOTSUPP;
+}
+
+int __weak acpi_ffh_address_space_arch_handler(acpi_integer *value,
+ void *region_context)
+{
+ return -EOPNOTSUPP;
+}
+
+static acpi_status
+acpi_ffh_address_space_setup(acpi_handle region_handle, u32 function,
+ void *handler_context, void **region_context)
+{
+ return acpi_ffh_address_space_arch_setup(handler_context,
+ region_context);
+}
+
+static acpi_status
+acpi_ffh_address_space_handler(u32 function, acpi_physical_address addr,
+ u32 bits, acpi_integer *value,
+ void *handler_context, void *region_context)
+{
+ return acpi_ffh_address_space_arch_handler(value, region_context);
+}
+
+void __init acpi_init_ffh(void)
+{
+ acpi_status status;
+
+ status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
+ ACPI_ADR_SPACE_FIXED_HARDWARE,
+ &acpi_ffh_address_space_handler,
+ &acpi_ffh_address_space_setup,
+ &ffh_ctx);
+ if (ACPI_FAILURE(status))
+ pr_alert("OperationRegion handler could not be installed\n");
+}
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c
index ec0e22a1e25d..02f1a1b1143c 100644
--- a/drivers/acpi/acpi_pad.c
+++ b/drivers/acpi/acpi_pad.c
@@ -287,7 +287,7 @@ static ssize_t rrtime_store(struct device *dev,
static ssize_t rrtime_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return scnprintf(buf, PAGE_SIZE, "%d\n", round_robin_time);
+ return sysfs_emit(buf, "%d\n", round_robin_time);
}
static DEVICE_ATTR_RW(rrtime);
@@ -309,7 +309,7 @@ static ssize_t idlepct_store(struct device *dev,
static ssize_t idlepct_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return scnprintf(buf, PAGE_SIZE, "%d\n", idle_pct);
+ return sysfs_emit(buf, "%d\n", idle_pct);
}
static DEVICE_ATTR_RW(idlepct);
@@ -449,7 +449,7 @@ static int acpi_pad_add(struct acpi_device *device)
return 0;
}
-static int acpi_pad_remove(struct acpi_device *device)
+static void acpi_pad_remove(struct acpi_device *device)
{
mutex_lock(&isolated_cpus_lock);
acpi_pad_idle_cpus(0);
@@ -458,7 +458,6 @@ static int acpi_pad_remove(struct acpi_device *device)
acpi_remove_notify_handler(device->handle,
ACPI_DEVICE_NOTIFY, acpi_pad_notify);
acpi_pad_remove_sysfs(device);
- return 0;
}
static const struct acpi_device_id pad_device_ids[] = {
diff --git a/drivers/acpi/acpi_pcc.c b/drivers/acpi/acpi_pcc.c
index 3e252be047b8..07a034a53aca 100644
--- a/drivers/acpi/acpi_pcc.c
+++ b/drivers/acpi/acpi_pcc.c
@@ -53,6 +53,7 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function,
struct pcc_data *data;
struct acpi_pcc_info *ctx = handler_context;
struct pcc_mbox_chan *pcc_chan;
+ static acpi_status ret;
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data)
@@ -69,23 +70,35 @@ acpi_pcc_address_space_setup(acpi_handle region_handle, u32 function,
if (IS_ERR(data->pcc_chan)) {
pr_err("Failed to find PCC channel for subspace %d\n",
ctx->subspace_id);
- kfree(data);
- return AE_NOT_FOUND;
+ ret = AE_NOT_FOUND;
+ goto err_free_data;
}
pcc_chan = data->pcc_chan;
+ if (!pcc_chan->mchan->mbox->txdone_irq) {
+ pr_err("This channel-%d does not support interrupt.\n",
+ ctx->subspace_id);
+ ret = AE_SUPPORT;
+ goto err_free_channel;
+ }
data->pcc_comm_addr = acpi_os_ioremap(pcc_chan->shmem_base_addr,
pcc_chan->shmem_size);
if (!data->pcc_comm_addr) {
pr_err("Failed to ioremap PCC comm region mem for %d\n",
ctx->subspace_id);
- pcc_mbox_free_channel(data->pcc_chan);
- kfree(data);
- return AE_NO_MEMORY;
+ ret = AE_NO_MEMORY;
+ goto err_free_channel;
}
*region_context = data;
return AE_OK;
+
+err_free_channel:
+ pcc_mbox_free_channel(data->pcc_chan);
+err_free_data:
+ kfree(data);
+
+ return ret;
}
static acpi_status
@@ -106,19 +119,17 @@ acpi_pcc_address_space_handler(u32 function, acpi_physical_address addr,
if (ret < 0)
return AE_ERROR;
- if (data->pcc_chan->mchan->mbox->txdone_irq) {
- /*
- * pcc_chan->latency is just a Nominal value. In reality the remote
- * processor could be much slower to reply. So add an arbitrary
- * amount of wait on top of Nominal.
- */
- usecs_lat = PCC_CMD_WAIT_RETRIES_NUM * data->pcc_chan->latency;
- ret = wait_for_completion_timeout(&data->done,
- usecs_to_jiffies(usecs_lat));
- if (ret == 0) {
- pr_err("PCC command executed timeout!\n");
- return AE_TIME;
- }
+ /*
+ * pcc_chan->latency is just a Nominal value. In reality the remote
+ * processor could be much slower to reply. So add an arbitrary
+ * amount of wait on top of Nominal.
+ */
+ usecs_lat = PCC_CMD_WAIT_RETRIES_NUM * data->pcc_chan->latency;
+ ret = wait_for_completion_timeout(&data->done,
+ usecs_to_jiffies(usecs_lat));
+ if (ret == 0) {
+ pr_err("PCC command executed timeout!\n");
+ return AE_TIME;
}
mbox_chan_txdone(data->pcc_chan->mchan, ret);
diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c
index 32953646caeb..30d8fd03fec7 100644
--- a/drivers/acpi/acpi_video.c
+++ b/drivers/acpi/acpi_video.c
@@ -86,7 +86,7 @@ static DEFINE_MUTEX(register_count_mutex);
static DEFINE_MUTEX(video_list_lock);
static LIST_HEAD(video_bus_head);
static int acpi_video_bus_add(struct acpi_device *device);
-static int acpi_video_bus_remove(struct acpi_device *device);
+static void acpi_video_bus_remove(struct acpi_device *device);
static void acpi_video_bus_notify(struct acpi_device *device, u32 event);
static void acpi_video_bus_register_backlight_work(struct work_struct *ignored);
static DECLARE_DELAYED_WORK(video_bus_register_backlight_work,
@@ -2067,13 +2067,13 @@ err_free_video:
return error;
}
-static int acpi_video_bus_remove(struct acpi_device *device)
+static void acpi_video_bus_remove(struct acpi_device *device)
{
struct acpi_video_bus *video = NULL;
if (!device || !acpi_driver_data(device))
- return -EINVAL;
+ return;
video = acpi_driver_data(device);
@@ -2087,8 +2087,6 @@ static int acpi_video_bus_remove(struct acpi_device *device)
kfree(video->attached_array);
kfree(video);
-
- return 0;
}
static void acpi_video_bus_register_backlight_work(struct work_struct *ignored)
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile
index 59700433a96e..9e0d95d76fff 100644
--- a/drivers/acpi/acpica/Makefile
+++ b/drivers/acpi/acpica/Makefile
@@ -155,6 +155,7 @@ acpi-y += \
utalloc.o \
utascii.o \
utbuffer.o \
+ utcksum.o \
utcopy.o \
utexcep.o \
utdebug.o \
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 088d6a7d052c..777457a58340 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -24,6 +24,7 @@ ACPI_GLOBAL(struct acpi_table_list, acpi_gbl_root_table_list);
ACPI_GLOBAL(struct acpi_table_header *, acpi_gbl_DSDT);
ACPI_GLOBAL(struct acpi_table_header, acpi_gbl_original_dsdt_header);
+ACPI_INIT_GLOBAL(char *, acpi_gbl_CDAT, NULL);
ACPI_INIT_GLOBAL(u32, acpi_gbl_dsdt_index, ACPI_INVALID_TABLE_INDEX);
ACPI_INIT_GLOBAL(u32, acpi_gbl_facs_index, ACPI_INVALID_TABLE_INDEX);
ACPI_INIT_GLOBAL(u32, acpi_gbl_xfacs_index, ACPI_INVALID_TABLE_INDEX);
diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h
index f8d7bfd737df..1c29325e4c7f 100644
--- a/drivers/acpi/acpica/actables.h
+++ b/drivers/acpi/acpica/actables.h
@@ -124,11 +124,6 @@ void
acpi_tb_print_table_header(acpi_physical_address address,
struct acpi_table_header *header);
-u8 acpi_tb_checksum(u8 *buffer, u32 length);
-
-acpi_status
-acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length);
-
void acpi_tb_check_dsdt_header(void);
struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index);
diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h
index 6e6270f96bfb..71175b664f49 100644
--- a/drivers/acpi/acpica/acutils.h
+++ b/drivers/acpi/acpica/acutils.h
@@ -159,6 +159,19 @@ u8 acpi_ut_valid_name_char(char character, u32 position);
void acpi_ut_check_and_repair_ascii(u8 *name, char *repaired_name, u32 count);
/*
+ * utcksum - Checksum utilities
+ */
+u8 acpi_ut_generate_checksum(void *table, u32 length, u8 original_checksum);
+
+u8 acpi_ut_checksum(u8 *buffer, u32 length);
+
+acpi_status
+acpi_ut_verify_cdat_checksum(struct acpi_table_cdat *cdat_table, u32 length);
+
+acpi_status
+acpi_ut_verify_checksum(struct acpi_table_header *table, u32 length);
+
+/*
* utnonansi - Non-ANSI C library functions
*/
void acpi_ut_strupr(char *src_string);
diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c
index ae2e768830bf..9332bc688713 100644
--- a/drivers/acpi/acpica/dsmethod.c
+++ b/drivers/acpi/acpica/dsmethod.c
@@ -517,7 +517,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
if (!info) {
status = AE_NO_MEMORY;
- goto cleanup;
+ goto pop_walk_state;
}
info->parameters = &this_walk_state->operands[0];
@@ -529,7 +529,7 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
ACPI_FREE(info);
if (ACPI_FAILURE(status)) {
- goto cleanup;
+ goto pop_walk_state;
}
next_walk_state->method_nesting_depth =
@@ -575,6 +575,12 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread,
return_ACPI_STATUS(status);
+pop_walk_state:
+
+ /* On error, pop the walk state to be deleted from thread */
+
+ acpi_ds_pop_walk_state(thread);
+
cleanup:
/* On error, we must terminate the method properly */
diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c
index df596d46dd97..82d1728b9bc6 100644
--- a/drivers/acpi/acpica/evevent.c
+++ b/drivers/acpi/acpica/evevent.c
@@ -142,6 +142,9 @@ static acpi_status acpi_ev_fixed_event_initialize(void)
status =
acpi_write_bit_register(acpi_gbl_fixed_event_info
[i].enable_register_id,
+ (i ==
+ ACPI_EVENT_PCIE_WAKE) ?
+ ACPI_ENABLE_EVENT :
ACPI_DISABLE_EVENT);
if (ACPI_FAILURE(status)) {
return (status);
@@ -185,6 +188,11 @@ u32 acpi_ev_fixed_event_detect(void)
return (int_status);
}
+ if (fixed_enable & ACPI_BITMASK_PCIEXP_WAKE_DISABLE)
+ fixed_enable &= ~ACPI_BITMASK_PCIEXP_WAKE_DISABLE;
+ else
+ fixed_enable |= ACPI_BITMASK_PCIEXP_WAKE_DISABLE;
+
ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS,
"Fixed Event Block: Enable %08X Status %08X\n",
fixed_enable, fixed_status));
@@ -250,6 +258,9 @@ static u32 acpi_ev_fixed_event_dispatch(u32 event)
if (!acpi_gbl_fixed_event_handlers[event].handler) {
(void)acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
enable_register_id,
+ (event ==
+ ACPI_EVENT_PCIE_WAKE) ?
+ ACPI_ENABLE_EVENT :
ACPI_DISABLE_EVENT);
ACPI_ERROR((AE_INFO,
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c
index b96b3a7e78e5..d035092799eb 100644
--- a/drivers/acpi/acpica/evregion.c
+++ b/drivers/acpi/acpica/evregion.c
@@ -172,6 +172,15 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,
ctx->subspace_id = (u8)region_obj->region.address;
}
+ if (region_obj->region.space_id ==
+ ACPI_ADR_SPACE_FIXED_HARDWARE) {
+ struct acpi_ffh_info *ctx =
+ handler_desc->address_space.context;
+
+ ctx->length = region_obj->region.length;
+ ctx->offset = region_obj->region.address;
+ }
+
/*
* We must exit the interpreter because the region setup will
* potentially execute control methods (for example, the _REG method
diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c
index d7d74ef87b18..e82faabdf907 100644
--- a/drivers/acpi/acpica/exconfig.c
+++ b/drivers/acpi/acpica/exconfig.c
@@ -295,8 +295,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc,
target));
}
if (target->common.type != ACPI_TYPE_INTEGER) {
- ACPI_EXCEPTION((AE_INFO, AE_TYPE,
- "Type not integer: %X\n", target->common.type));
+ ACPI_ERROR((AE_INFO, "Type not integer: %X",
+ target->common.type));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c
index 2b89a496de65..657f4002f9dc 100644
--- a/drivers/acpi/acpica/exfield.c
+++ b/drivers/acpi/acpica/exfield.c
@@ -141,7 +141,9 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state,
|| obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_IPMI
|| obj_desc->field.region_obj->region.space_id ==
- ACPI_ADR_SPACE_PLATFORM_RT)) {
+ ACPI_ADR_SPACE_PLATFORM_RT
+ || obj_desc->field.region_obj->region.space_id ==
+ ACPI_ADR_SPACE_FIXED_HARDWARE)) {
/* SMBus, GSBus, IPMI serial */
@@ -305,7 +307,9 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
|| obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_IPMI
|| obj_desc->field.region_obj->region.space_id ==
- ACPI_ADR_SPACE_PLATFORM_RT)) {
+ ACPI_ADR_SPACE_PLATFORM_RT
+ || obj_desc->field.region_obj->region.space_id ==
+ ACPI_ADR_SPACE_FIXED_HARDWARE)) {
/* SMBus, GSBus, IPMI serial */
diff --git a/drivers/acpi/acpica/exserial.c b/drivers/acpi/acpica/exserial.c
index 4da20d7845df..fd63f2042514 100644
--- a/drivers/acpi/acpica/exserial.c
+++ b/drivers/acpi/acpica/exserial.c
@@ -323,6 +323,12 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,
function = ACPI_WRITE;
break;
+ case ACPI_ADR_SPACE_FIXED_HARDWARE:
+
+ buffer_length = ACPI_FFH_INPUT_BUFFER_SIZE;
+ function = ACPI_WRITE;
+ break;
+
default:
return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
}
diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c
index bd936476dda9..37b3f641feaa 100644
--- a/drivers/acpi/acpica/hwsleep.c
+++ b/drivers/acpi/acpica/hwsleep.c
@@ -311,6 +311,20 @@ acpi_status acpi_hw_legacy_wake(u8 sleep_state)
[ACPI_EVENT_SLEEP_BUTTON].
status_register_id, ACPI_CLEAR_STATUS);
+ /* Enable pcie wake event if support */
+ if ((acpi_gbl_FADT.flags & ACPI_FADT_PCI_EXPRESS_WAKE)) {
+ (void)
+ acpi_write_bit_register(acpi_gbl_fixed_event_info
+ [ACPI_EVENT_PCIE_WAKE].
+ enable_register_id,
+ ACPI_DISABLE_EVENT);
+ (void)
+ acpi_write_bit_register(acpi_gbl_fixed_event_info
+ [ACPI_EVENT_PCIE_WAKE].
+ status_register_id,
+ ACPI_CLEAR_STATUS);
+ }
+
acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING);
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/tbdata.c b/drivers/acpi/acpica/tbdata.c
index a7642b34ce48..1f7677e0dbbe 100644
--- a/drivers/acpi/acpica/tbdata.c
+++ b/drivers/acpi/acpica/tbdata.c
@@ -522,7 +522,7 @@ acpi_tb_verify_temp_table(struct acpi_table_desc *table_desc,
/* Verify the checksum */
status =
- acpi_tb_verify_checksum(table_desc->pointer,
+ acpi_ut_verify_checksum(table_desc->pointer,
table_desc->length);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY,
diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c
index 31d7ea84a360..f04dc6051320 100644
--- a/drivers/acpi/acpica/tbfadt.c
+++ b/drivers/acpi/acpica/tbfadt.c
@@ -298,7 +298,7 @@ void acpi_tb_parse_fadt(void)
* Validate the FADT checksum before we copy the table. Ignore
* checksum error as we want to try to get the DSDT and FACS.
*/
- (void)acpi_tb_verify_checksum(table, length);
+ (void)acpi_ut_verify_checksum(table, length);
/* Create a local copy of the FADT in common ACPI 2.0+ format */
diff --git a/drivers/acpi/acpica/tbprint.c b/drivers/acpi/acpica/tbprint.c
index 595547db28c0..f07aa9b46f3f 100644
--- a/drivers/acpi/acpica/tbprint.c
+++ b/drivers/acpi/acpica/tbprint.c
@@ -10,6 +10,7 @@
#include <acpi/acpi.h>
#include "accommon.h"
#include "actables.h"
+#include "acutils.h"
#define _COMPONENT ACPI_TABLES
ACPI_MODULE_NAME("tbprint")
@@ -39,7 +40,7 @@ static void acpi_tb_fix_string(char *string, acpi_size length)
{
while (length && *string) {
- if (!isprint((int)*string)) {
+ if (!isprint((int)(u8)*string)) {
*string = '?';
}
@@ -135,77 +136,3 @@ acpi_tb_print_table_header(acpi_physical_address address,
local_header.asl_compiler_revision));
}
}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_tb_validate_checksum
- *
- * PARAMETERS: table - ACPI table to verify
- * length - Length of entire table
- *
- * RETURN: Status
- *
- * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns
- * exception on bad checksum.
- *
- ******************************************************************************/
-
-acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length)
-{
- u8 checksum;
-
- /*
- * FACS/S3PT:
- * They are the odd tables, have no standard ACPI header and no checksum
- */
-
- if (ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_S3PT) ||
- ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_FACS)) {
- return (AE_OK);
- }
-
- /* Compute the checksum on the table */
-
- checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length);
-
- /* Checksum ok? (should be zero) */
-
- if (checksum) {
- ACPI_BIOS_WARNING((AE_INFO,
- "Incorrect checksum in table [%4.4s] - 0x%2.2X, "
- "should be 0x%2.2X",
- table->signature, table->checksum,
- (u8)(table->checksum - checksum)));
-
-#if (ACPI_CHECKSUM_ABORT)
- return (AE_BAD_CHECKSUM);
-#endif
- }
-
- return (AE_OK);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_tb_checksum
- *
- * PARAMETERS: buffer - Pointer to memory region to be checked
- * length - Length of this memory region
- *
- * RETURN: Checksum (u8)
- *
- * DESCRIPTION: Calculates circular checksum of memory region.
- *
- ******************************************************************************/
-
-u8 acpi_tb_checksum(u8 *buffer, u32 length)
-{
- u8 sum = 0;
- u8 *end = buffer + length;
-
- while (buffer < end) {
- sum = (u8)(sum + *(buffer++));
- }
-
- return (sum);
-}
diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c
index 633a823be65f..17ad9c227d42 100644
--- a/drivers/acpi/acpica/tbutils.c
+++ b/drivers/acpi/acpica/tbutils.c
@@ -299,7 +299,7 @@ acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
/* Validate the root table checksum */
- status = acpi_tb_verify_checksum(table, length);
+ status = acpi_ut_verify_checksum(table, length);
if (ACPI_FAILURE(status)) {
acpi_os_unmap_memory(table, length);
return_ACPI_STATUS(status);
diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c
index 3d09e3f6bd43..53afd75bbc06 100644
--- a/drivers/acpi/acpica/tbxfroot.c
+++ b/drivers/acpi/acpica/tbxfroot.c
@@ -74,14 +74,14 @@ acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp)
/* Check the standard checksum */
- if (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
+ if (acpi_ut_checksum((u8 *)rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) {
return (AE_BAD_CHECKSUM);
}
/* Check extended checksum if table version >= 2 */
if ((rsdp->revision >= 2) &&
- (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) {
+ (acpi_ut_checksum((u8 *)rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) {
return (AE_BAD_CHECKSUM);
}
@@ -114,6 +114,7 @@ acpi_find_root_pointer(acpi_physical_address *table_address)
u8 *table_ptr;
u8 *mem_rover;
u32 physical_address;
+ u32 ebda_window_size;
ACPI_FUNCTION_TRACE(acpi_find_root_pointer);
@@ -139,26 +140,37 @@ acpi_find_root_pointer(acpi_physical_address *table_address)
/* EBDA present? */
- if (physical_address > 0x400) {
+ /*
+ * Check that the EBDA pointer from memory is sane and does not point
+ * above valid low memory
+ */
+ if (physical_address > 0x400 && physical_address < 0xA0000) {
+ /*
+ * Calculate the scan window size
+ * The EBDA is not guaranteed to be larger than a ki_b and in case
+ * that it is smaller, the scanning function would leave the low
+ * memory and continue to the VGA range.
+ */
+ ebda_window_size = ACPI_MIN(ACPI_EBDA_WINDOW_SIZE,
+ 0xA0000 - physical_address);
+
/*
- * 1b) Search EBDA paragraphs (EBDA is required to be a
- * minimum of 1K length)
+ * 1b) Search EBDA paragraphs
*/
table_ptr = acpi_os_map_memory((acpi_physical_address)
physical_address,
- ACPI_EBDA_WINDOW_SIZE);
+ ebda_window_size);
if (!table_ptr) {
ACPI_ERROR((AE_INFO,
"Could not map memory at 0x%8.8X for length %u",
- physical_address, ACPI_EBDA_WINDOW_SIZE));
+ physical_address, ebda_window_size));
return_ACPI_STATUS(AE_NO_MEMORY);
}
mem_rover =
- acpi_tb_scan_memory_for_rsdp(table_ptr,
- ACPI_EBDA_WINDOW_SIZE);
- acpi_os_unmap_memory(table_ptr, ACPI_EBDA_WINDOW_SIZE);
+ acpi_tb_scan_memory_for_rsdp(table_ptr, ebda_window_size);
+ acpi_os_unmap_memory(table_ptr, ebda_window_size);
if (mem_rover) {
diff --git a/drivers/acpi/acpica/utcksum.c b/drivers/acpi/acpica/utcksum.c
new file mode 100644
index 000000000000..c166e4c05ab6
--- /dev/null
+++ b/drivers/acpi/acpica/utcksum.c
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/******************************************************************************
+ *
+ * Module Name: utcksum - Support generating table checksums
+ *
+ * Copyright (C) 2000 - 2022, Intel Corp.
+ *
+ *****************************************************************************/
+
+#include <acpi/acpi.h>
+#include "accommon.h"
+#include "acutils.h"
+
+/* This module used for application-level code only */
+
+#define _COMPONENT ACPI_CA_DISASSEMBLER
+ACPI_MODULE_NAME("utcksum")
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_verify_checksum
+ *
+ * PARAMETERS: table - ACPI table to verify
+ * length - Length of entire table
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns
+ * exception on bad checksum.
+ * Note: We don't have to check for a CDAT here, since CDAT is
+ * not in the RSDT/XSDT, and the CDAT table is never installed
+ * via ACPICA.
+ *
+ ******************************************************************************/
+acpi_status acpi_ut_verify_checksum(struct acpi_table_header *table, u32 length)
+{
+ u8 checksum;
+
+ /*
+ * FACS/S3PT:
+ * They are the odd tables, have no standard ACPI header and no checksum
+ */
+ if (ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_S3PT) ||
+ ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_FACS)) {
+ return (AE_OK);
+ }
+
+ /* Compute the checksum on the table */
+
+ length = table->length;
+ checksum =
+ acpi_ut_generate_checksum(ACPI_CAST_PTR(u8, table), length,
+ table->checksum);
+
+ /* Computed checksum matches table? */
+
+ if (checksum != table->checksum) {
+ ACPI_BIOS_WARNING((AE_INFO,
+ "Incorrect checksum in table [%4.4s] - 0x%2.2X, "
+ "should be 0x%2.2X",
+ table->signature, table->checksum,
+ table->checksum - checksum));
+
+#if (ACPI_CHECKSUM_ABORT)
+ return (AE_BAD_CHECKSUM);
+#endif
+ }
+
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_verify_cdat_checksum
+ *
+ * PARAMETERS: table - CDAT ACPI table to verify
+ * length - Length of entire table
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Verifies that the CDAT table checksums to zero. Optionally
+ * returns an exception on bad checksum.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ut_verify_cdat_checksum(struct acpi_table_cdat *cdat_table, u32 length)
+{
+ u8 checksum;
+
+ /* Compute the checksum on the table */
+
+ checksum = acpi_ut_generate_checksum(ACPI_CAST_PTR(u8, cdat_table),
+ cdat_table->length,
+ cdat_table->checksum);
+
+ /* Computed checksum matches table? */
+
+ if (checksum != cdat_table->checksum) {
+ ACPI_BIOS_WARNING((AE_INFO,
+ "Incorrect checksum in table [%4.4s] - 0x%2.2X, "
+ "should be 0x%2.2X",
+ acpi_gbl_CDAT, cdat_table->checksum,
+ checksum));
+
+#if (ACPI_CHECKSUM_ABORT)
+ return (AE_BAD_CHECKSUM);
+#endif
+ }
+
+ cdat_table->checksum = checksum;
+ return (AE_OK);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_generate_checksum
+ *
+ * PARAMETERS: table - Pointer to table to be checksummed
+ * length - Length of the table
+ * original_checksum - Value of the checksum field
+ *
+ * RETURN: 8 bit checksum of buffer
+ *
+ * DESCRIPTION: Computes an 8 bit checksum of the table.
+ *
+ ******************************************************************************/
+
+u8 acpi_ut_generate_checksum(void *table, u32 length, u8 original_checksum)
+{
+ u8 checksum;
+
+ /* Sum the entire table as-is */
+
+ checksum = acpi_ut_checksum((u8 *)table, length);
+
+ /* Subtract off the existing checksum value in the table */
+
+ checksum = (u8)(checksum - original_checksum);
+
+ /* Compute and return the final checksum */
+
+ checksum = (u8)(0 - checksum);
+ return (checksum);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ut_checksum
+ *
+ * PARAMETERS: buffer - Pointer to memory region to be checked
+ * length - Length of this memory region
+ *
+ * RETURN: Checksum (u8)
+ *
+ * DESCRIPTION: Calculates circular checksum of memory region.
+ *
+ ******************************************************************************/
+
+u8 acpi_ut_checksum(u8 *buffer, u32 length)
+{
+ u8 sum = 0;
+ u8 *end = buffer + length;
+
+ while (buffer < end) {
+ sum = (u8)(sum + *(buffer++));
+ }
+
+ return (sum);
+}
diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c
index 400b9e15a709..63c17f420fb8 100644
--- a/drivers/acpi/acpica/utcopy.c
+++ b/drivers/acpi/acpica/utcopy.c
@@ -916,13 +916,6 @@ acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj,
status = acpi_ut_walk_package_tree(source_obj, dest_obj,
acpi_ut_copy_ielement_to_ielement,
walk_state);
- if (ACPI_FAILURE(status)) {
-
- /* On failure, delete the destination package object */
-
- acpi_ut_remove_reference(dest_obj);
- }
-
return_ACPI_STATUS(status);
}
diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c
index cda6e16dddf7..53afa5edb6ec 100644
--- a/drivers/acpi/acpica/utglobal.c
+++ b/drivers/acpi/acpica/utglobal.c
@@ -186,6 +186,10 @@ struct acpi_fixed_event_info acpi_gbl_fixed_event_info[ACPI_NUM_FIXED_EVENTS] =
ACPI_BITREG_RT_CLOCK_ENABLE,
ACPI_BITMASK_RT_CLOCK_STATUS,
ACPI_BITMASK_RT_CLOCK_ENABLE},
+ /* ACPI_EVENT_PCIE_WAKE */ {ACPI_BITREG_PCIEXP_WAKE_STATUS,
+ ACPI_BITREG_PCIEXP_WAKE_DISABLE,
+ ACPI_BITMASK_PCIEXP_WAKE_STATUS,
+ ACPI_BITMASK_PCIEXP_WAKE_DISABLE},
};
#endif /* !ACPI_REDUCED_HARDWARE */
diff --git a/drivers/acpi/acpica/utstring.c b/drivers/acpi/acpica/utstring.c
index c39b5483045d..aae71b8c55d2 100644
--- a/drivers/acpi/acpica/utstring.c
+++ b/drivers/acpi/acpica/utstring.c
@@ -145,7 +145,7 @@ void acpi_ut_repair_name(char *name)
return;
}
- ACPI_COPY_NAMESEG(&original_name, name);
+ ACPI_COPY_NAMESEG(&original_name, &name[0]);
/* Check each character in the name */
@@ -156,10 +156,10 @@ void acpi_ut_repair_name(char *name)
/*
* Replace a bad character with something printable, yet technically
- * still invalid. This prevents any collisions with existing "good"
+ * "odd". This prevents any collisions with existing "good"
* names in the namespace.
*/
- name[i] = '*';
+ name[i] = '_';
found_bad_char = TRUE;
}
@@ -169,8 +169,8 @@ void acpi_ut_repair_name(char *name)
if (!acpi_gbl_enable_interpreter_slack) {
ACPI_WARNING((AE_INFO,
- "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]",
- original_name, name));
+ "Invalid character(s) in name (0x%.8X) %p, repaired: [%4.4s]",
+ original_name, name, &name[0]));
} else {
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"Invalid character(s) in name (0x%.8X), repaired: [%4.4s]",
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c
index 9b52482b4ed5..c7c26872f4ce 100644
--- a/drivers/acpi/apei/apei-base.c
+++ b/drivers/acpi/apei/apei-base.c
@@ -25,9 +25,9 @@
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/kref.h>
-#include <linux/rculist.h>
#include <linux/interrupt.h>
#include <linux/debugfs.h>
+#include <acpi/apei.h>
#include <asm/unaligned.h>
#include "apei-internal.h"
diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c
index 6b583373c58a..ab86b2f4e719 100644
--- a/drivers/acpi/apei/einj.c
+++ b/drivers/acpi/apei/einj.c
@@ -358,6 +358,7 @@ static int __einj_error_trigger(u64 trigger_paddr, u32 type,
*/
if ((param_extension || acpi5) && (type & MEM_ERROR_MASK) && param2) {
struct apei_resources addr_resources;
+
apei_resources_init(&addr_resources);
trigger_param_region = einj_get_trigger_parameter_region(
trigger_tab, param1, param2);
@@ -432,11 +433,11 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
}
v5param->flags = vendor_flags;
} else if (flags) {
- v5param->flags = flags;
- v5param->memory_address = param1;
- v5param->memory_address_range = param2;
- v5param->apicid = param3;
- v5param->pcie_sbdf = param4;
+ v5param->flags = flags;
+ v5param->memory_address = param1;
+ v5param->memory_address_range = param2;
+ v5param->apicid = param3;
+ v5param->pcie_sbdf = param4;
} else {
switch (type) {
case ACPI_EINJ_PROCESSOR_CORRECTABLE:
@@ -466,6 +467,7 @@ static int __einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2,
return rc;
if (einj_param) {
struct einj_parameter *v4param = einj_param;
+
v4param->param1 = param1;
v4param->param2 = param2;
}
@@ -569,6 +571,20 @@ static u64 error_param2;
static u64 error_param3;
static u64 error_param4;
static struct dentry *einj_debug_dir;
+static const char * const einj_error_type_string[] = {
+ "0x00000001\tProcessor Correctable\n",
+ "0x00000002\tProcessor Uncorrectable non-fatal\n",
+ "0x00000004\tProcessor Uncorrectable fatal\n",
+ "0x00000008\tMemory Correctable\n",
+ "0x00000010\tMemory Uncorrectable non-fatal\n",
+ "0x00000020\tMemory Uncorrectable fatal\n",
+ "0x00000040\tPCI Express Correctable\n",
+ "0x00000080\tPCI Express Uncorrectable non-fatal\n",
+ "0x00000100\tPCI Express Uncorrectable fatal\n",
+ "0x00000200\tPlatform Correctable\n",
+ "0x00000400\tPlatform Uncorrectable non-fatal\n",
+ "0x00000800\tPlatform Uncorrectable fatal\n",
+};
static int available_error_type_show(struct seq_file *m, void *v)
{
@@ -578,30 +594,9 @@ static int available_error_type_show(struct seq_file *m, void *v)
rc = einj_get_available_error_type(&available_error_type);
if (rc)
return rc;
- if (available_error_type & 0x0001)
- seq_printf(m, "0x00000001\tProcessor Correctable\n");
- if (available_error_type & 0x0002)
- seq_printf(m, "0x00000002\tProcessor Uncorrectable non-fatal\n");
- if (available_error_type & 0x0004)
- seq_printf(m, "0x00000004\tProcessor Uncorrectable fatal\n");
- if (available_error_type & 0x0008)
- seq_printf(m, "0x00000008\tMemory Correctable\n");
- if (available_error_type & 0x0010)
- seq_printf(m, "0x00000010\tMemory Uncorrectable non-fatal\n");
- if (available_error_type & 0x0020)
- seq_printf(m, "0x00000020\tMemory Uncorrectable fatal\n");
- if (available_error_type & 0x0040)
- seq_printf(m, "0x00000040\tPCI Express Correctable\n");
- if (available_error_type & 0x0080)
- seq_printf(m, "0x00000080\tPCI Express Uncorrectable non-fatal\n");
- if (available_error_type & 0x0100)
- seq_printf(m, "0x00000100\tPCI Express Uncorrectable fatal\n");
- if (available_error_type & 0x0200)
- seq_printf(m, "0x00000200\tPlatform Correctable\n");
- if (available_error_type & 0x0400)
- seq_printf(m, "0x00000400\tPlatform Uncorrectable non-fatal\n");
- if (available_error_type & 0x0800)
- seq_printf(m, "0x00000800\tPlatform Uncorrectable fatal\n");
+ for (int pos = 0; pos < ARRAY_SIZE(einj_error_type_string); pos++)
+ if (available_error_type & BIT(pos))
+ seq_puts(m, einj_error_type_string[pos]);
return 0;
}
@@ -689,8 +684,7 @@ static int __init einj_init(void)
if (status == AE_NOT_FOUND) {
pr_warn("EINJ table not found.\n");
return -ENODEV;
- }
- else if (ACPI_FAILURE(status)) {
+ } else if (ACPI_FAILURE(status)) {
pr_err("Failed to get EINJ table: %s\n",
acpi_format_exception(status));
return -EINVAL;
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index 9952f3a792ba..066dc1f5c235 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -94,6 +94,8 @@
#define FIX_APEI_GHES_SDEI_CRITICAL __end_of_fixed_addresses
#endif
+static ATOMIC_NOTIFIER_HEAD(ghes_report_chain);
+
static inline bool is_hest_type_generic_v2(struct ghes *ghes)
{
return ghes->generic->header.type == ACPI_HEST_TYPE_GENERIC_ERROR_V2;
@@ -108,6 +110,13 @@ bool ghes_disable;
module_param_named(disable, ghes_disable, bool, 0);
/*
+ * "ghes.edac_force_enable" forcibly enables ghes_edac and skips the platform
+ * check.
+ */
+static bool ghes_edac_force_enable;
+module_param_named(edac_force_enable, ghes_edac_force_enable, bool, 0);
+
+/*
* All error sources notified with HED (Hardware Error Device) share a
* single notifier callback, so they need to be linked and checked one
* by one. This holds true for NMI too.
@@ -119,6 +128,13 @@ static LIST_HEAD(ghes_hed);
static DEFINE_MUTEX(ghes_list_mutex);
/*
+ * A list of GHES devices which are given to the corresponding EDAC driver
+ * ghes_edac for further use.
+ */
+static LIST_HEAD(ghes_devs);
+static DEFINE_MUTEX(ghes_devs_mutex);
+
+/*
* Because the memory area used to transfer hardware error information
* from BIOS to Linux can be determined only in NMI, IRQ or timer
* handler, but general ioremap can not be used in atomic context, so
@@ -138,7 +154,7 @@ 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 *ghes_estatus_caches[GHES_ESTATUS_CACHES_SIZE];
+static struct ghes_estatus_cache __rcu *ghes_estatus_caches[GHES_ESTATUS_CACHES_SIZE];
static atomic_t ghes_estatus_cache_alloced;
static int ghes_panic_timeout __read_mostly = 30;
@@ -645,7 +661,7 @@ static bool ghes_do_proc(struct ghes *ghes,
if (guid_equal(sec_type, &CPER_SEC_PLATFORM_MEM)) {
struct cper_sec_mem_err *mem_err = acpi_hest_get_payload(gdata);
- ghes_edac_report_mem_error(sev, mem_err);
+ atomic_notifier_call_chain(&ghes_report_chain, sev, mem_err);
arch_apei_report_mem_error(sev, mem_err);
queued = ghes_handle_memory_failure(gdata, sev);
@@ -773,48 +789,42 @@ static struct ghes_estatus_cache *ghes_estatus_cache_alloc(
return cache;
}
-static void ghes_estatus_cache_free(struct ghes_estatus_cache *cache)
+static void ghes_estatus_cache_rcu_free(struct rcu_head *head)
{
+ struct ghes_estatus_cache *cache;
u32 len;
+ cache = container_of(head, struct ghes_estatus_cache, rcu);
len = cper_estatus_len(GHES_ESTATUS_FROM_CACHE(cache));
len = GHES_ESTATUS_CACHE_LEN(len);
gen_pool_free(ghes_estatus_pool, (unsigned long)cache, len);
atomic_dec(&ghes_estatus_cache_alloced);
}
-static void ghes_estatus_cache_rcu_free(struct rcu_head *head)
+static void
+ghes_estatus_cache_add(struct acpi_hest_generic *generic,
+ struct acpi_hest_generic_status *estatus)
{
- struct ghes_estatus_cache *cache;
-
- cache = container_of(head, struct ghes_estatus_cache, rcu);
- ghes_estatus_cache_free(cache);
-}
-
-static void ghes_estatus_cache_add(
- struct acpi_hest_generic *generic,
- struct acpi_hest_generic_status *estatus)
-{
- int i, slot = -1, count;
unsigned long long now, duration, period, max_period = 0;
- struct ghes_estatus_cache *cache, *slot_cache = NULL, *new_cache;
+ struct ghes_estatus_cache *cache, *new_cache;
+ struct ghes_estatus_cache __rcu *victim;
+ int i, slot = -1, count;
new_cache = ghes_estatus_cache_alloc(generic, estatus);
- if (new_cache == NULL)
+ if (!new_cache)
return;
+
rcu_read_lock();
now = sched_clock();
for (i = 0; i < GHES_ESTATUS_CACHES_SIZE; i++) {
cache = rcu_dereference(ghes_estatus_caches[i]);
if (cache == NULL) {
slot = i;
- slot_cache = NULL;
break;
}
duration = now - cache->time_in;
if (duration >= GHES_ESTATUS_IN_CACHE_MAX_NSEC) {
slot = i;
- slot_cache = cache;
break;
}
count = atomic_read(&cache->count);
@@ -823,18 +833,30 @@ static void ghes_estatus_cache_add(
if (period > max_period) {
max_period = period;
slot = i;
- slot_cache = cache;
}
}
- /* new_cache must be put into array after its contents are written */
- smp_wmb();
- if (slot != -1 && cmpxchg(ghes_estatus_caches + slot,
- slot_cache, new_cache) == slot_cache) {
- if (slot_cache)
- call_rcu(&slot_cache->rcu, ghes_estatus_cache_rcu_free);
- } else
- ghes_estatus_cache_free(new_cache);
rcu_read_unlock();
+
+ if (slot != -1) {
+ /*
+ * Use release semantics to ensure that ghes_estatus_cached()
+ * running on another CPU will see the updated cache fields if
+ * it can see the new value of the pointer.
+ */
+ victim = xchg_release(&ghes_estatus_caches[slot],
+ RCU_INITIALIZER(new_cache));
+
+ /*
+ * At this point, victim may point to a cached item different
+ * from the one based on which we selected the slot. Instead of
+ * going to the loop again to pick another slot, let's just
+ * drop the other item anyway: this may cause a false cache
+ * miss later on, but that won't cause any problems.
+ */
+ if (victim)
+ call_rcu(&unrcu_pointer(victim)->rcu,
+ ghes_estatus_cache_rcu_free);
+ }
}
static void __ghes_panic(struct ghes *ghes,
@@ -1376,7 +1398,11 @@ static int ghes_probe(struct platform_device *ghes_dev)
platform_set_drvdata(ghes_dev, ghes);
- ghes_edac_register(ghes, &ghes_dev->dev);
+ ghes->dev = &ghes_dev->dev;
+
+ mutex_lock(&ghes_devs_mutex);
+ list_add_tail(&ghes->elist, &ghes_devs);
+ mutex_unlock(&ghes_devs_mutex);
/* Handle any pending errors right away */
spin_lock_irqsave(&ghes_notify_lock_irq, flags);
@@ -1440,12 +1466,12 @@ static int ghes_remove(struct platform_device *ghes_dev)
ghes_fini(ghes);
- ghes_edac_unregister(ghes);
+ mutex_lock(&ghes_devs_mutex);
+ list_del(&ghes->elist);
+ mutex_unlock(&ghes_devs_mutex);
kfree(ghes);
- platform_set_drvdata(ghes_dev, NULL);
-
return 0;
}
@@ -1497,3 +1523,41 @@ void __init acpi_ghes_init(void)
else
pr_info(GHES_PFX "Failed to enable APEI firmware first mode.\n");
}
+
+/*
+ * Known x86 systems that prefer GHES error reporting:
+ */
+static struct acpi_platform_list plat_list[] = {
+ {"HPE ", "Server ", 0, ACPI_SIG_FADT, all_versions},
+ { } /* End */
+};
+
+struct list_head *ghes_get_devices(void)
+{
+ int idx = -1;
+
+ if (IS_ENABLED(CONFIG_X86)) {
+ idx = acpi_match_platform_list(plat_list);
+ if (idx < 0) {
+ if (!ghes_edac_force_enable)
+ return NULL;
+
+ pr_warn_once("Force-loading ghes_edac on an unsupported platform. You're on your own!\n");
+ }
+ }
+
+ return &ghes_devs;
+}
+EXPORT_SYMBOL_GPL(ghes_get_devices);
+
+void ghes_register_report_chain(struct notifier_block *nb)
+{
+ atomic_notifier_chain_register(&ghes_report_chain, nb);
+}
+EXPORT_SYMBOL_GPL(ghes_register_report_chain);
+
+void ghes_unregister_report_chain(struct notifier_block *nb)
+{
+ atomic_notifier_chain_unregister(&ghes_report_chain, nb);
+}
+EXPORT_SYMBOL_GPL(ghes_unregister_report_chain);
diff --git a/drivers/acpi/arm64/Kconfig b/drivers/acpi/arm64/Kconfig
index d4a72835f328..b3ed6212244c 100644
--- a/drivers/acpi/arm64/Kconfig
+++ b/drivers/acpi/arm64/Kconfig
@@ -18,3 +18,6 @@ config ACPI_AGDI
reset command.
If set, the kernel parses AGDI table and listens for the command.
+
+config ACPI_APMT
+ bool
diff --git a/drivers/acpi/arm64/Makefile b/drivers/acpi/arm64/Makefile
index 7b9e4045659d..e21a9e84e394 100644
--- a/drivers/acpi/arm64/Makefile
+++ b/drivers/acpi/arm64/Makefile
@@ -2,4 +2,5 @@
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
diff --git a/drivers/acpi/arm64/apmt.c b/drivers/acpi/arm64/apmt.c
new file mode 100644
index 000000000000..8cab69fa5d59
--- /dev/null
+++ b/drivers/acpi/arm64/apmt.c
@@ -0,0 +1,178 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ARM APMT table support.
+ * Design document number: ARM DEN0117.
+ *
+ * Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES.
+ *
+ */
+
+#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>
+
+#define DEV_NAME "arm-cs-arch-pmu"
+
+/* There can be up to 3 resources: page 0 and 1 address, and interrupt. */
+#define DEV_MAX_RESOURCE_COUNT 3
+
+/* Root pointer to the mapped APMT table */
+static struct acpi_table_header *apmt_table;
+
+static int __init apmt_init_resources(struct resource *res,
+ struct acpi_apmt_node *node)
+{
+ int irq, trigger;
+ int num_res = 0;
+
+ res[num_res].start = node->base_address0;
+ res[num_res].end = node->base_address0 + SZ_4K - 1;
+ res[num_res].flags = IORESOURCE_MEM;
+
+ 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;
+
+ num_res++;
+
+ if (node->ovflw_irq != 0) {
+ trigger = (node->ovflw_irq_flags & ACPI_APMT_OVFLW_IRQ_FLAGS_MODE);
+ trigger = (trigger == ACPI_APMT_OVFLW_IRQ_FLAGS_MODE_LEVEL) ?
+ ACPI_LEVEL_SENSITIVE : ACPI_EDGE_SENSITIVE;
+ irq = acpi_register_gsi(NULL, node->ovflw_irq, trigger,
+ ACPI_ACTIVE_HIGH);
+
+ if (irq <= 0) {
+ pr_warn("APMT could not register gsi hwirq %d\n", irq);
+ return num_res;
+ }
+
+ res[num_res].start = irq;
+ res[num_res].end = irq;
+ res[num_res].flags = IORESOURCE_IRQ;
+
+ num_res++;
+ }
+
+ return num_res;
+}
+
+/**
+ * apmt_add_platform_device() - Allocate a platform device for APMT node
+ * @node: Pointer to device ACPI APMT node
+ * @fwnode: fwnode associated with the APMT node
+ *
+ * Returns: 0 on success, <0 failure
+ */
+static int __init apmt_add_platform_device(struct acpi_apmt_node *node,
+ struct fwnode_handle *fwnode)
+{
+ struct platform_device *pdev;
+ int ret, count;
+ struct resource res[DEV_MAX_RESOURCE_COUNT];
+
+ pdev = platform_device_alloc(DEV_NAME, PLATFORM_DEVID_AUTO);
+ if (!pdev)
+ return -ENOMEM;
+
+ memset(res, 0, sizeof(res));
+
+ count = apmt_init_resources(res, node);
+
+ ret = platform_device_add_resources(pdev, res, count);
+ if (ret)
+ goto dev_put;
+
+ /*
+ * Add a copy of APMT node pointer to platform_data to be used to
+ * retrieve APMT data information.
+ */
+ ret = platform_device_add_data(pdev, &node, sizeof(node));
+ if (ret)
+ goto dev_put;
+
+ pdev->dev.fwnode = fwnode;
+
+ ret = platform_device_add(pdev);
+
+ if (ret)
+ goto dev_put;
+
+ return 0;
+
+dev_put:
+ platform_device_put(pdev);
+
+ return ret;
+}
+
+static int __init apmt_init_platform_devices(void)
+{
+ struct acpi_apmt_node *apmt_node;
+ struct acpi_table_apmt *apmt;
+ struct fwnode_handle *fwnode;
+ u64 offset, end;
+ int ret;
+
+ /*
+ * apmt_table and apmt both point to the start of APMT table, but
+ * have different struct types
+ */
+ apmt = (struct acpi_table_apmt *)apmt_table;
+ offset = sizeof(*apmt);
+ end = apmt->header.length;
+
+ while (offset < end) {
+ apmt_node = ACPI_ADD_PTR(struct acpi_apmt_node, apmt,
+ offset);
+
+ fwnode = acpi_alloc_fwnode_static();
+ if (!fwnode)
+ return -ENOMEM;
+
+ ret = apmt_add_platform_device(apmt_node, fwnode);
+ if (ret) {
+ acpi_free_fwnode_static(fwnode);
+ return ret;
+ }
+
+ offset += apmt_node->length;
+ }
+
+ return 0;
+}
+
+void __init acpi_apmt_init(void)
+{
+ acpi_status status;
+ int ret;
+
+ /**
+ * APMT table nodes will be used at runtime after the apmt init,
+ * so we don't need to call acpi_put_table() to release
+ * the APMT table mapping.
+ */
+ status = acpi_get_table(ACPI_SIG_APMT, 0, &apmt_table);
+
+ if (ACPI_FAILURE(status)) {
+ if (status != AE_NOT_FOUND) {
+ const char *msg = acpi_format_exception(status);
+
+ pr_err("Failed to get APMT table, %s\n", msg);
+ }
+
+ return;
+ }
+
+ ret = apmt_init_platform_devices();
+ if (ret) {
+ pr_err("Failed to initialize APMT platform devices, ret: %d\n", ret);
+ acpi_put_table(apmt_table);
+ }
+}
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 8059baf4ef27..38fb84974f35 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -402,6 +402,10 @@ static struct acpi_iort_node *iort_node_get_id(struct acpi_iort_node *node,
return NULL;
}
+#ifndef ACPI_IORT_SMMU_V3_DEVICEID_VALID
+#define ACPI_IORT_SMMU_V3_DEVICEID_VALID (1 << 4)
+#endif
+
static int iort_get_id_mapping_index(struct acpi_iort_node *node)
{
struct acpi_iort_smmu_v3 *smmu;
@@ -418,12 +422,16 @@ static int iort_get_id_mapping_index(struct acpi_iort_node *node)
smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
/*
- * ID mapping index is only ignored if all interrupts are
- * GSIV based
+ * Until IORT E.e (node rev. 5), the ID mapping index was
+ * defined to be valid unless all interrupts are GSIV-based.
*/
- if (smmu->event_gsiv && smmu->pri_gsiv && smmu->gerr_gsiv
- && smmu->sync_gsiv)
+ if (node->revision < 5) {
+ if (smmu->event_gsiv && smmu->pri_gsiv &&
+ smmu->gerr_gsiv && smmu->sync_gsiv)
+ return -EINVAL;
+ } else if (!(smmu->flags & ACPI_IORT_SMMU_V3_DEVICEID_VALID)) {
return -EINVAL;
+ }
if (smmu->id_mapping_index >= node->mapping_count) {
pr_err(FW_BUG "[node %p type %d] ID mapping index overflows valid mappings\n",
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 306513fec1e1..f4badcdde76e 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -696,7 +696,8 @@ static void __battery_hook_unregister(struct acpi_battery_hook *hook, int lock)
if (lock)
mutex_lock(&hook_mutex);
list_for_each_entry(battery, &acpi_battery_list, list) {
- hook->remove_battery(battery->bat);
+ if (!hook->remove_battery(battery->bat, hook))
+ power_supply_changed(battery->bat);
}
list_del(&hook->list);
if (lock)
@@ -724,7 +725,7 @@ void battery_hook_register(struct acpi_battery_hook *hook)
* its attributes.
*/
list_for_each_entry(battery, &acpi_battery_list, list) {
- if (hook->add_battery(battery->bat)) {
+ if (hook->add_battery(battery->bat, hook)) {
/*
* If a add-battery returns non-zero,
* the registration of the extension has failed,
@@ -735,6 +736,8 @@ void battery_hook_register(struct acpi_battery_hook *hook)
__battery_hook_unregister(hook, 0);
goto end;
}
+
+ power_supply_changed(battery->bat);
}
pr_info("new extension: %s\n", hook->name);
end:
@@ -762,7 +765,7 @@ static void battery_hook_add_battery(struct acpi_battery *battery)
* during the battery module initialization.
*/
list_for_each_entry_safe(hook_node, tmp, &battery_hook_list, list) {
- if (hook_node->add_battery(battery->bat)) {
+ if (hook_node->add_battery(battery->bat, hook_node)) {
/*
* The notification of the extensions has failed, to
* prevent further errors we will unload the extension.
@@ -785,7 +788,7 @@ static void battery_hook_remove_battery(struct acpi_battery *battery)
* custom attributes from the battery.
*/
list_for_each_entry(hook, &battery_hook_list, list) {
- hook->remove_battery(battery->bat);
+ hook->remove_battery(battery->bat, hook);
}
/* Then, just remove the battery from the list */
list_del(&battery->list);
@@ -1208,12 +1211,12 @@ fail:
return result;
}
-static int acpi_battery_remove(struct acpi_device *device)
+static void acpi_battery_remove(struct acpi_device *device)
{
struct acpi_battery *battery = NULL;
if (!device || !acpi_driver_data(device))
- return -EINVAL;
+ return;
device_init_wakeup(&device->dev, 0);
battery = acpi_driver_data(device);
unregister_pm_notifier(&battery->pm_nb);
@@ -1221,7 +1224,6 @@ static int acpi_battery_remove(struct acpi_device *device)
mutex_destroy(&battery->lock);
mutex_destroy(&battery->sysfs_lock);
kfree(battery);
- return 0;
}
#ifdef CONFIG_PM_SLEEP
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index d466c8195314..0c05ccde1f7a 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -27,6 +27,7 @@
#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>
@@ -323,6 +324,8 @@ static void acpi_bus_osc_negotiate_platform_control(void)
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PCLPI_SUPPORT;
if (IS_ENABLED(CONFIG_ACPI_PRMT))
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_PRM_SUPPORT;
+ if (IS_ENABLED(CONFIG_ACPI_FFH))
+ capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_FFH_OPR_SUPPORT;
#ifdef CONFIG_ARM64
capbuf[OSC_SUPPORT_DWORD] |= OSC_SB_GENERIC_INITIATOR_SUPPORT;
@@ -1408,6 +1411,7 @@ static int __init acpi_init(void)
disable_acpi();
return result;
}
+ acpi_init_ffh();
pci_mmcfg_late_init();
acpi_iort_init();
@@ -1423,6 +1427,7 @@ static int __init acpi_init(void)
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 1f9b9a4c38c7..475e1eddfa3b 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -125,7 +125,7 @@ static const struct dmi_system_id dmi_lid_quirks[] = {
};
static int acpi_button_add(struct acpi_device *device);
-static int acpi_button_remove(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
@@ -580,14 +580,13 @@ static int acpi_button_add(struct acpi_device *device)
return error;
}
-static int acpi_button_remove(struct acpi_device *device)
+static void acpi_button_remove(struct acpi_device *device)
{
struct acpi_button *button = acpi_driver_data(device);
acpi_button_remove_fs(device);
input_unregister_device(button->input);
kfree(button);
- return 0;
}
static int param_set_lid_init_state(const char *val,
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index 093675b1a1ff..0f17b1c32718 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -148,7 +148,7 @@ __ATTR(_name, 0444, show_##_name, NULL)
if (ret) \
return ret; \
\
- return scnprintf(buf, PAGE_SIZE, "%llu\n", \
+ return sysfs_emit(buf, "%llu\n", \
(u64)st_name.member_name); \
} \
define_one_cppc_ro(member_name)
@@ -174,7 +174,7 @@ static ssize_t show_feedback_ctrs(struct kobject *kobj,
if (ret)
return ret;
- return scnprintf(buf, PAGE_SIZE, "ref:%llu del:%llu\n",
+ return sysfs_emit(buf, "ref:%llu del:%llu\n",
fb_ctrs.reference, fb_ctrs.delivered);
}
define_one_cppc_ro(feedback_ctrs);
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 9b42628cf21b..2520fb998ce6 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -1663,12 +1663,12 @@ err:
return ret;
}
-static int acpi_ec_remove(struct acpi_device *device)
+static void acpi_ec_remove(struct acpi_device *device)
{
struct acpi_ec *ec;
if (!device)
- return -EINVAL;
+ return;
ec = acpi_driver_data(device);
release_region(ec->data_addr, 1);
@@ -1678,7 +1678,6 @@ static int acpi_ec_remove(struct acpi_device *device)
ec_remove_handlers(ec);
acpi_ec_free(ec);
}
- return 0;
}
static acpi_status
@@ -1877,6 +1876,16 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = {
},
{
/*
+ * HP Pavilion Gaming Laptop 15-cx0041ur
+ */
+ .callback = ec_honor_dsdt_gpe,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP 15-cx0041ur"),
+ },
+ },
+ {
+ /*
* Samsung hardware
* https://bugzilla.kernel.org/show_bug.cgi?id=44161
*/
diff --git a/drivers/acpi/fan_attr.c b/drivers/acpi/fan_attr.c
index f15157d40713..f4f6e2381f1d 100644
--- a/drivers/acpi/fan_attr.c
+++ b/drivers/acpi/fan_attr.c
@@ -27,24 +27,24 @@ static ssize_t show_state(struct device *dev, struct device_attribute *attr, cha
count = scnprintf(buf, PAGE_SIZE, "%lld:", fps->control);
if (fps->trip_point == 0xFFFFFFFF || fps->trip_point > 9)
- count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined:");
+ count += sysfs_emit_at(buf, count, "not-defined:");
else
- count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld:", fps->trip_point);
+ count += sysfs_emit_at(buf, count, "%lld:", fps->trip_point);
if (fps->speed == 0xFFFFFFFF)
- count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined:");
+ count += sysfs_emit_at(buf, count, "not-defined:");
else
- count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld:", fps->speed);
+ count += sysfs_emit_at(buf, count, "%lld:", fps->speed);
if (fps->noise_level == 0xFFFFFFFF)
- count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined:");
+ count += sysfs_emit_at(buf, count, "not-defined:");
else
- count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld:", fps->noise_level * 100);
+ count += sysfs_emit_at(buf, count, "%lld:", fps->noise_level * 100);
if (fps->power == 0xFFFFFFFF)
- count += scnprintf(&buf[count], PAGE_SIZE - count, "not-defined\n");
+ count += sysfs_emit_at(buf, count, "not-defined\n");
else
- count += scnprintf(&buf[count], PAGE_SIZE - count, "%lld\n", fps->power);
+ count += sysfs_emit_at(buf, count, "%lld\n", fps->power);
return count;
}
diff --git a/drivers/acpi/fan_core.c b/drivers/acpi/fan_core.c
index 52a0b303b70a..9dccbae9e8ea 100644
--- a/drivers/acpi/fan_core.c
+++ b/drivers/acpi/fan_core.c
@@ -236,6 +236,7 @@ static int acpi_fan_get_fif(struct acpi_device *device)
if (ACPI_FAILURE(status)) {
dev_err(&device->dev, "Invalid _FIF element\n");
status = -EINVAL;
+ goto err;
}
fan->fif.revision = fields[0];
diff --git a/drivers/acpi/hed.c b/drivers/acpi/hed.c
index 60a2939cde6c..78d44e3fe129 100644
--- a/drivers/acpi/hed.c
+++ b/drivers/acpi/hed.c
@@ -56,10 +56,9 @@ static int acpi_hed_add(struct acpi_device *device)
return 0;
}
-static int acpi_hed_remove(struct acpi_device *device)
+static void acpi_hed_remove(struct acpi_device *device)
{
hed_handle = NULL;
- return 0;
}
static struct acpi_driver acpi_hed_driver = {
diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
index 1cc4647f78b8..c2c786eb95ab 100644
--- a/drivers/acpi/irq.c
+++ b/drivers/acpi/irq.c
@@ -94,6 +94,7 @@ EXPORT_SYMBOL_GPL(acpi_unregister_gsi);
/**
* acpi_get_irq_source_fwhandle() - Retrieve fwhandle from IRQ resource source.
* @source: acpi_resource_source to use for the lookup.
+ * @gsi: GSI IRQ number
*
* Description:
* Retrieve the fwhandle of the device referenced by the given IRQ resource
@@ -297,8 +298,8 @@ EXPORT_SYMBOL_GPL(acpi_irq_get);
/**
* acpi_set_irq_model - Setup the GSI irqdomain information
* @model: the value assigned to acpi_irq_model
- * @fwnode: the irq_domain identifier for mapping and looking up
- * GSI interrupts
+ * @fn: a dispatcher function that will return the domain fwnode
+ * for a given GSI
*/
void __init acpi_set_irq_model(enum acpi_irq_model_id model,
struct fwnode_handle *(*fn)(u32))
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index ae5f4acf2675..f1cc5ec6a3b6 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -3371,10 +3371,9 @@ static int acpi_nfit_add(struct acpi_device *adev)
return devm_add_action_or_reset(dev, acpi_nfit_shutdown, acpi_desc);
}
-static int acpi_nfit_remove(struct acpi_device *adev)
+static void acpi_nfit_remove(struct acpi_device *adev)
{
/* see acpi_nfit_unregister */
- return 0;
}
static void acpi_nfit_update_notify(struct device *dev, acpi_handle handle)
diff --git a/drivers/acpi/nfit/intel.c b/drivers/acpi/nfit/intel.c
index 8dd792a55730..3902759abcba 100644
--- a/drivers/acpi/nfit/intel.c
+++ b/drivers/acpi/nfit/intel.c
@@ -3,6 +3,7 @@
#include <linux/libnvdimm.h>
#include <linux/ndctl.h>
#include <linux/acpi.h>
+#include <linux/memregion.h>
#include <asm/smp.h>
#include "intel.h"
#include "nfit.h"
@@ -190,8 +191,6 @@ static int intel_security_change_key(struct nvdimm *nvdimm,
}
}
-static void nvdimm_invalidate_cache(void);
-
static int __maybe_unused intel_security_unlock(struct nvdimm *nvdimm,
const struct nvdimm_key_data *key_data)
{
@@ -227,9 +226,6 @@ static int __maybe_unused intel_security_unlock(struct nvdimm *nvdimm,
return -EIO;
}
- /* DIMM unlocked, invalidate all CPU caches before we read it */
- nvdimm_invalidate_cache();
-
return 0;
}
@@ -297,8 +293,6 @@ static int __maybe_unused intel_security_erase(struct nvdimm *nvdimm,
if (!test_bit(cmd, &nfit_mem->dsm_mask))
return -ENOTTY;
- /* flush all cache before we erase DIMM */
- nvdimm_invalidate_cache();
memcpy(nd_cmd.cmd.passphrase, key->data,
sizeof(nd_cmd.cmd.passphrase));
rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
@@ -317,8 +311,6 @@ static int __maybe_unused intel_security_erase(struct nvdimm *nvdimm,
return -ENXIO;
}
- /* DIMM erased, invalidate all CPU caches before we read it */
- nvdimm_invalidate_cache();
return 0;
}
@@ -354,8 +346,6 @@ static int __maybe_unused intel_security_query_overwrite(struct nvdimm *nvdimm)
return -ENXIO;
}
- /* flush all cache before we make the nvdimms available */
- nvdimm_invalidate_cache();
return 0;
}
@@ -380,8 +370,6 @@ static int __maybe_unused intel_security_overwrite(struct nvdimm *nvdimm,
if (!test_bit(NVDIMM_INTEL_OVERWRITE, &nfit_mem->dsm_mask))
return -ENOTTY;
- /* flush all cache before we erase DIMM */
- nvdimm_invalidate_cache();
memcpy(nd_cmd.cmd.passphrase, nkey->data,
sizeof(nd_cmd.cmd.passphrase));
rc = nvdimm_ctl(nvdimm, ND_CMD_CALL, &nd_cmd, sizeof(nd_cmd), NULL);
@@ -401,22 +389,6 @@ static int __maybe_unused intel_security_overwrite(struct nvdimm *nvdimm,
}
}
-/*
- * TODO: define a cross arch wbinvd equivalent when/if
- * NVDIMM_FAMILY_INTEL command support arrives on another arch.
- */
-#ifdef CONFIG_X86
-static void nvdimm_invalidate_cache(void)
-{
- wbinvd_on_all_cpus();
-}
-#else
-static void nvdimm_invalidate_cache(void)
-{
- WARN_ON_ONCE("cache invalidation required after unlock\n");
-}
-#endif
-
static const struct nvdimm_security_ops __intel_security_ops = {
.get_flags = intel_security_flags,
.freeze = intel_security_freeze,
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 08e15774fb9f..ff30ceca2203 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -387,13 +387,15 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
u8 pin;
int triggering = ACPI_LEVEL_SENSITIVE;
/*
- * On ARM systems with the GIC interrupt model, level interrupts
+ * On ARM systems with the GIC interrupt model, or LoongArch
+ * systems with the LPIC interrupt model, level interrupts
* are always polarity high by specification; PCI legacy
* IRQs lines are inverted before reaching the interrupt
* controller and must therefore be considered active high
* as default.
*/
- int polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC ?
+ int polarity = acpi_irq_model == ACPI_IRQ_MODEL_GIC ||
+ acpi_irq_model == ACPI_IRQ_MODEL_LPIC ?
ACPI_ACTIVE_HIGH : ACPI_ACTIVE_LOW;
char *link = NULL;
char link_desc[16];
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 4e3db20e9cbb..b3c202d2a433 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -493,6 +493,7 @@ static u32 calculate_cxl_support(void)
u32 support;
support = OSC_CXL_2_0_PORT_DEV_REG_ACCESS_SUPPORT;
+ support |= OSC_CXL_1_1_PORT_REG_ACCESS_SUPPORT;
if (pci_aer_available())
support |= OSC_CXL_PROTOCOL_ERR_REPORTING_SUPPORT;
if (IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE))
diff --git a/drivers/acpi/pfr_telemetry.c b/drivers/acpi/pfr_telemetry.c
index 9abf350bd7a5..27fb6cdad75f 100644
--- a/drivers/acpi/pfr_telemetry.c
+++ b/drivers/acpi/pfr_telemetry.c
@@ -144,7 +144,7 @@ static int get_pfrt_log_data_info(struct pfrt_log_data_info *data_info,
ret = 0;
free_acpi_buffer:
- kfree(out_obj);
+ ACPI_FREE(out_obj);
return ret;
}
@@ -180,7 +180,7 @@ static int set_pfrt_log_level(int level, struct pfrt_log_device *pfrt_log_dev)
ret = -EBUSY;
}
- kfree(out_obj);
+ ACPI_FREE(out_obj);
return ret;
}
@@ -218,7 +218,7 @@ static int get_pfrt_log_level(struct pfrt_log_device *pfrt_log_dev)
ret = obj->integer.value;
free_acpi_buffer:
- kfree(out_obj);
+ ACPI_FREE(out_obj);
return ret;
}
diff --git a/drivers/acpi/pfr_update.c b/drivers/acpi/pfr_update.c
index 6bb0b778b5da..98267f163e2b 100644
--- a/drivers/acpi/pfr_update.c
+++ b/drivers/acpi/pfr_update.c
@@ -178,7 +178,7 @@ static int query_capability(struct pfru_update_cap_info *cap_hdr,
ret = 0;
free_acpi_buffer:
- kfree(out_obj);
+ ACPI_FREE(out_obj);
return ret;
}
@@ -224,7 +224,7 @@ static int query_buffer(struct pfru_com_buf_info *info,
ret = 0;
free_acpi_buffer:
- kfree(out_obj);
+ ACPI_FREE(out_obj);
return ret;
}
@@ -385,7 +385,7 @@ static int start_update(int action, struct pfru_device *pfru_dev)
ret = 0;
free_acpi_buffer:
- kfree(out_obj);
+ ACPI_FREE(out_obj);
return ret;
}
@@ -455,7 +455,7 @@ static ssize_t pfru_write(struct file *file, const char __user *buf,
iov.iov_base = (void __user *)buf;
iov.iov_len = len;
- iov_iter_init(&iter, WRITE, &iov, 1, len);
+ iov_iter_init(&iter, ITER_SOURCE, &iov, 1, len);
/* map the communication buffer */
phy_addr = (phys_addr_t)((buf_info.addr_hi << 32) | buf_info.addr_lo);
diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c
index f2588aba8421..23507d29f000 100644
--- a/drivers/acpi/power.c
+++ b/drivers/acpi/power.c
@@ -967,7 +967,7 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle)
if (acpi_power_get_state(resource, &state_dummy))
__acpi_power_on(resource);
- pr_info("%s [%s]\n", acpi_device_name(device), acpi_device_bid(device));
+ acpi_handle_info(handle, "New power resource\n");
result = acpi_tie_acpi_dev(device);
if (result)
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index acfabfe07c4f..7bf882fcd64b 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -324,7 +324,7 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
* the erratum), but this is known to disrupt certain ISA
* devices thus we take the conservative approach.
*/
- else if (errata.piix4.fdma) {
+ if (errata.piix4.fdma) {
acpi_handle_debug(pr->handle,
"C3 not supported on PIIX4 with Type-F DMA\n");
return;
@@ -384,8 +384,6 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
* handle BM_RLD is to set it and leave it set.
*/
acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, 1);
-
- return;
}
static int acpi_cst_latency_cmp(const void *a, const void *b)
@@ -459,7 +457,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
lapic_timer_propagate_broadcast(pr);
- return (working);
+ return working;
}
static int acpi_processor_get_cstate_info(struct acpi_processor *pr)
@@ -1134,6 +1132,9 @@ static int acpi_processor_get_lpi_info(struct acpi_processor *pr)
status = acpi_get_parent(handle, &pr_ahandle);
while (ACPI_SUCCESS(status)) {
d = acpi_fetch_acpi_dev(pr_ahandle);
+ if (!d)
+ break;
+
handle = pr_ahandle;
if (strcmp(acpi_device_hid(d), ACPI_PROCESSOR_CONTAINER_HID))
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 757a98f6d7a2..970f04a958cd 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -142,6 +142,7 @@ int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
pr = per_cpu(processors, cpu);
if (!pr || !pr->performance || !pr->performance->state_count)
return -ENODEV;
+
*limit = pr->performance->states[pr->performance_platform_limit].
core_frequency * 1000;
return 0;
@@ -201,8 +202,7 @@ static int acpi_processor_get_performance_control(struct acpi_processor *pr)
}
pct = (union acpi_object *)buffer.pointer;
- if (!pct || (pct->type != ACPI_TYPE_PACKAGE)
- || (pct->package.count != 2)) {
+ if (!pct || pct->type != ACPI_TYPE_PACKAGE || pct->package.count != 2) {
pr_err("Invalid _PCT data\n");
result = -EFAULT;
goto end;
@@ -214,9 +214,8 @@ static int acpi_processor_get_performance_control(struct acpi_processor *pr)
obj = pct->package.elements[0];
- if ((obj.type != ACPI_TYPE_BUFFER)
- || (obj.buffer.length < sizeof(struct acpi_pct_register))
- || (obj.buffer.pointer == NULL)) {
+ if (!obj.buffer.pointer || obj.type != ACPI_TYPE_BUFFER ||
+ obj.buffer.length < sizeof(struct acpi_pct_register)) {
pr_err("Invalid _PCT data (control_register)\n");
result = -EFAULT;
goto end;
@@ -230,9 +229,8 @@ static int acpi_processor_get_performance_control(struct acpi_processor *pr)
obj = pct->package.elements[1];
- if ((obj.type != ACPI_TYPE_BUFFER)
- || (obj.buffer.length < sizeof(struct acpi_pct_register))
- || (obj.buffer.pointer == NULL)) {
+ if (!obj.buffer.pointer || obj.type != ACPI_TYPE_BUFFER ||
+ obj.buffer.length < sizeof(struct acpi_pct_register)) {
pr_err("Invalid _PCT data (status_register)\n");
result = -EFAULT;
goto end;
@@ -260,8 +258,8 @@ static void amd_fixup_frequency(struct acpi_processor_px *px, int i)
if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
return;
- if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10)
- || boot_cpu_data.x86 == 0x11) {
+ if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) ||
+ boot_cpu_data.x86 == 0x11) {
rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi);
/*
* MSR C001_0064+:
@@ -300,7 +298,7 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr)
}
pss = buffer.pointer;
- if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) {
+ if (!pss || pss->type != ACPI_TYPE_PACKAGE) {
pr_err("Invalid _PSS data\n");
result = -EFAULT;
goto end;
@@ -353,8 +351,7 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr)
* Check that ACPI's u64 MHz will be valid as u32 KHz in cpufreq
*/
if (!px->core_frequency ||
- ((u32)(px->core_frequency * 1000) !=
- (px->core_frequency * 1000))) {
+ (u32)(px->core_frequency * 1000) != px->core_frequency * 1000) {
pr_err(FW_BUG
"Invalid BIOS _PSS frequency found for processor %d: 0x%llx MHz\n",
pr->id, px->core_frequency);
@@ -456,7 +453,7 @@ int acpi_processor_pstate_control(void)
int acpi_processor_notify_smm(struct module *calling_module)
{
static int is_done;
- int result;
+ int result = 0;
if (!acpi_processor_cpufreq_init)
return -EBUSY;
@@ -464,42 +461,41 @@ int acpi_processor_notify_smm(struct module *calling_module)
if (!try_module_get(calling_module))
return -EINVAL;
- /* is_done is set to negative if an error occurred,
- * and to postitive if _no_ error occurred, but SMM
- * was already notified. This avoids double notification
- * which might lead to unexpected results...
+ /*
+ * is_done is set to negative if an error occurs and to 1 if no error
+ * occurrs, but SMM has been notified already. This avoids repeated
+ * notification which might lead to unexpected results.
*/
- if (is_done > 0) {
- module_put(calling_module);
- return 0;
- } else if (is_done < 0) {
- module_put(calling_module);
- return is_done;
- }
+ if (is_done != 0) {
+ if (is_done < 0)
+ result = is_done;
- is_done = -EIO;
+ goto out_put;
+ }
result = acpi_processor_pstate_control();
- if (!result) {
- pr_debug("No SMI port or pstate_control\n");
- module_put(calling_module);
- return 0;
- }
- if (result < 0) {
- module_put(calling_module);
- return result;
+ if (result <= 0) {
+ if (result) {
+ is_done = result;
+ } else {
+ pr_debug("No SMI port or pstate_control\n");
+ is_done = 1;
+ }
+ goto out_put;
}
- /* Success. If there's no _PPC, we need to fear nothing, so
- * we can allow the cpufreq driver to be rmmod'ed. */
is_done = 1;
+ /*
+ * Success. If there _PPC, unloading the cpufreq driver would be risky,
+ * so disallow it in that case.
+ */
+ if (acpi_processor_ppc_in_use)
+ return 0;
- if (!acpi_processor_ppc_in_use)
- module_put(calling_module);
-
- return 0;
+out_put:
+ module_put(calling_module);
+ return result;
}
-
EXPORT_SYMBOL(acpi_processor_notify_smm);
int acpi_processor_get_psd(acpi_handle handle, struct acpi_psd_package *pdomain)
@@ -517,7 +513,7 @@ int acpi_processor_get_psd(acpi_handle handle, struct acpi_psd_package *pdomain)
}
psd = buffer.pointer;
- if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) {
+ if (!psd || psd->type != ACPI_TYPE_PACKAGE) {
pr_err("Invalid _PSD data\n");
result = -EFAULT;
goto end;
@@ -532,8 +528,7 @@ int acpi_processor_get_psd(acpi_handle handle, struct acpi_psd_package *pdomain)
state.length = sizeof(struct acpi_psd_package);
state.pointer = pdomain;
- status = acpi_extract_package(&(psd->package.elements[0]),
- &format, &state);
+ status = acpi_extract_package(&(psd->package.elements[0]), &format, &state);
if (ACPI_FAILURE(status)) {
pr_err("Invalid _PSD data\n");
result = -EFAULT;
@@ -716,9 +711,8 @@ err_out:
}
EXPORT_SYMBOL(acpi_processor_preregister_performance);
-int
-acpi_processor_register_performance(struct acpi_processor_performance
- *performance, unsigned int cpu)
+int acpi_processor_register_performance(struct acpi_processor_performance
+ *performance, unsigned int cpu)
{
struct acpi_processor *pr;
@@ -751,7 +745,6 @@ acpi_processor_register_performance(struct acpi_processor_performance
mutex_unlock(&performance_mutex);
return 0;
}
-
EXPORT_SYMBOL(acpi_processor_register_performance);
void acpi_processor_unregister_performance(unsigned int cpu)
@@ -761,18 +754,15 @@ void acpi_processor_unregister_performance(unsigned int cpu)
mutex_lock(&performance_mutex);
pr = per_cpu(processors, cpu);
- if (!pr) {
- mutex_unlock(&performance_mutex);
- return;
- }
+ if (!pr)
+ goto unlock;
if (pr->performance)
kfree(pr->performance->states);
+
pr->performance = NULL;
+unlock:
mutex_unlock(&performance_mutex);
-
- return;
}
-
EXPORT_SYMBOL(acpi_processor_unregister_performance);
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c
index a822fe410dda..00d045e5f524 100644
--- a/drivers/acpi/processor_throttling.c
+++ b/drivers/acpi/processor_throttling.c
@@ -50,7 +50,7 @@ static int __acpi_processor_set_throttling(struct acpi_processor *pr,
static int acpi_processor_update_tsd_coord(void)
{
- int count, count_target;
+ int count_target;
int retval = 0;
unsigned int i, j;
cpumask_var_t covered_cpus;
@@ -107,7 +107,6 @@ static int acpi_processor_update_tsd_coord(void)
/* Validate the Domain info */
count_target = pdomain->num_processors;
- count = 1;
for_each_possible_cpu(j) {
if (i == j)
@@ -140,7 +139,6 @@ static int acpi_processor_update_tsd_coord(void)
cpumask_set_cpu(j, covered_cpus);
cpumask_set_cpu(j, pthrottling->shared_cpu_map);
- count++;
}
for_each_possible_cpu(j) {
if (i == j)
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index e6a01a8df1b8..e90752d4f488 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -96,7 +96,7 @@ struct acpi_sbs {
#define to_acpi_sbs(x) power_supply_get_drvdata(x)
-static int acpi_sbs_remove(struct acpi_device *device);
+static void acpi_sbs_remove(struct acpi_device *device);
static int acpi_battery_get_state(struct acpi_battery *battery);
static inline int battery_scale(int log)
@@ -664,16 +664,16 @@ end:
return result;
}
-static int acpi_sbs_remove(struct acpi_device *device)
+static void acpi_sbs_remove(struct acpi_device *device)
{
struct acpi_sbs *sbs;
int id;
if (!device)
- return -EINVAL;
+ return;
sbs = acpi_driver_data(device);
if (!sbs)
- return -EINVAL;
+ return;
mutex_lock(&sbs->lock);
acpi_smbus_unregister_callback(sbs->hc);
for (id = 0; id < MAX_SBS_BAT; ++id)
@@ -682,7 +682,6 @@ static int acpi_sbs_remove(struct acpi_device *device)
mutex_unlock(&sbs->lock);
mutex_destroy(&sbs->lock);
kfree(sbs);
- return 0;
}
#ifdef CONFIG_PM_SLEEP
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index 340e0b61587e..16f2daaa2c45 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -30,7 +30,7 @@ struct acpi_smb_hc {
};
static int acpi_smbus_hc_add(struct acpi_device *device);
-static int acpi_smbus_hc_remove(struct acpi_device *device);
+static void acpi_smbus_hc_remove(struct acpi_device *device);
static const struct acpi_device_id sbs_device_ids[] = {
{"ACPI0001", 0},
@@ -280,19 +280,18 @@ static int acpi_smbus_hc_add(struct acpi_device *device)
extern void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit);
-static int acpi_smbus_hc_remove(struct acpi_device *device)
+static void acpi_smbus_hc_remove(struct acpi_device *device)
{
struct acpi_smb_hc *hc;
if (!device)
- return -EINVAL;
+ return;
hc = acpi_driver_data(device);
acpi_ec_remove_query_handler(hc->ec, hc->query_bit);
acpi_os_wait_events_complete();
kfree(hc);
device->driver_data = NULL;
- return 0;
}
module_acpi_driver(acpi_smb_hc_driver);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index b47e93a24a9a..274344434282 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -30,7 +30,7 @@ extern struct acpi_device *acpi_root;
#define ACPI_BUS_HID "LNXSYBUS"
#define ACPI_BUS_DEVICE_NAME "System Bus"
-#define INVALID_ACPI_HANDLE ((acpi_handle)empty_zero_page)
+#define INVALID_ACPI_HANDLE ((acpi_handle)ZERO_PAGE(0))
static const char *dummy_hid = "device";
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index cc2fe0618178..7db3b530279b 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -9,6 +9,7 @@
#include <linux/bitmap.h>
#include <linux/init.h>
#include <linux/kernel.h>
+#include <linux/kstrtox.h>
#include <linux/moduleparam.h>
#include "internal.h"
@@ -197,7 +198,7 @@ static int param_set_trace_method_name(const char *val,
static int param_get_trace_method_name(char *buffer, const struct kernel_param *kp)
{
- return scnprintf(buffer, PAGE_SIZE, "%s\n", acpi_gbl_trace_method_name);
+ return sysfs_emit(buffer, "%s\n", acpi_gbl_trace_method_name);
}
static const struct kernel_param_ops param_ops_trace_method = {
@@ -992,7 +993,7 @@ static ssize_t force_remove_store(struct kobject *kobj,
bool val;
int ret;
- ret = strtobool(buf, &val);
+ ret = kstrtobool(buf, &val);
if (ret < 0)
return ret;
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c
index 47ec11d4c68e..5fbc32b802d0 100644
--- a/drivers/acpi/tables.c
+++ b/drivers/acpi/tables.c
@@ -210,6 +210,16 @@ void acpi_table_print_madt_entry(struct acpi_subtable_header *header)
}
break;
+ case ACPI_MADT_TYPE_CORE_PIC:
+ {
+ struct acpi_madt_core_pic *p = (struct acpi_madt_core_pic *)header;
+
+ pr_debug("CORE PIC (processor_id[0x%02x] core_id[0x%02x] %s)\n",
+ p->processor_id, p->core_id,
+ (p->flags & ACPI_MADT_ENABLED) ? "enabled" : "disabled");
+ }
+ break;
+
default:
pr_warn("Found unsupported MADT entry (type = 0x%x)\n",
header->type);
@@ -838,12 +848,11 @@ acpi_status acpi_os_table_override(struct acpi_table_header *existing_table,
/*
* acpi_locate_initial_tables()
*
- * find RSDP, find and checksum SDT/XSDT.
- * checksum all tables, print SDT/XSDT
+ * Get the RSDP, then find and checksum all the ACPI tables.
*
- * result: sdt_entry[] is initialized
+ * result: initial_tables[] is initialized, and points to
+ * a list of ACPI tables.
*/
-
int __init acpi_locate_initial_tables(void)
{
acpi_status status;
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 40b07057983e..0b4b844f9d4c 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -74,7 +74,7 @@ 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 int acpi_thermal_remove(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[] = {
@@ -291,7 +291,7 @@ static int acpi_thermal_trips_update(struct acpi_thermal *tz, int flag)
"Found critical threshold [%lu]\n",
tz->trips.critical.temperature);
}
- if (tz->trips.critical.flags.valid == 1) {
+ if (tz->trips.critical.flags.valid) {
if (crt == -1) {
tz->trips.critical.flags.valid = 0;
} else if (crt > 0) {
@@ -1059,19 +1059,18 @@ end:
return result;
}
-static int acpi_thermal_remove(struct acpi_device *device)
+static void acpi_thermal_remove(struct acpi_device *device)
{
struct acpi_thermal *tz;
if (!device || !acpi_driver_data(device))
- return -EINVAL;
+ return;
flush_workqueue(acpi_thermal_pm_queue);
tz = acpi_driver_data(device);
acpi_thermal_unregister_thermal_zone(tz);
kfree(tz);
- return 0;
}
#ifdef CONFIG_PM_SLEEP
diff --git a/drivers/acpi/tiny-power-button.c b/drivers/acpi/tiny-power-button.c
index a19f0e4e69f7..598f548b21f3 100644
--- a/drivers/acpi/tiny-power-button.c
+++ b/drivers/acpi/tiny-power-button.c
@@ -19,11 +19,15 @@ 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_remove(struct acpi_device *device)
+static int acpi_noop_add(struct acpi_device *device)
{
return 0;
}
+static void acpi_noop_remove(struct acpi_device *device)
+{
+}
+
static void acpi_tiny_power_button_notify(struct acpi_device *device, u32 event)
{
kill_cad_pid(power_signal, 1);
@@ -34,8 +38,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,
- .remove = acpi_noop_add_remove,
+ .add = acpi_noop_add,
+ .remove = acpi_noop_remove,
.notify = acpi_tiny_power_button_notify,
},
};
diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c
index b2a616287638..a934bbc9dd37 100644
--- a/drivers/acpi/video_detect.c
+++ b/drivers/acpi/video_detect.c
@@ -132,6 +132,10 @@ static int video_detect_force_none(const struct dmi_system_id *d)
}
static const struct dmi_system_id video_detect_dmi_table[] = {
+ /*
+ * Models which should use the vendor backlight interface,
+ * because of broken ACPI video backlight control.
+ */
{
/* https://bugzilla.redhat.com/show_bug.cgi?id=1128309 */
.callback = video_detect_force_vendor,
@@ -166,6 +170,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
},
},
{
+ /* https://bugs.launchpad.net/bugs/1000146 */
.callback = video_detect_force_vendor,
/* Asus X101CH */
.matches = {
@@ -190,6 +195,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
},
},
{
+ /* https://bugs.launchpad.net/bugs/1000146 */
.callback = video_detect_force_vendor,
/* Asus 1015CX */
.matches = {
@@ -199,14 +205,6 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
},
{
.callback = video_detect_force_vendor,
- /* GIGABYTE GB-BXBT-2807 */
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
- DMI_MATCH(DMI_PRODUCT_NAME, "GB-BXBT-2807"),
- },
- },
- {
- .callback = video_detect_force_vendor,
/* Samsung N150/N210/N220 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
@@ -234,18 +232,23 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
},
{
.callback = video_detect_force_vendor,
- /* Sony VPCEH3U1E */
+ /* Xiaomi Mi Pad 2 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
- DMI_MATCH(DMI_PRODUCT_NAME, "VPCEH3U1E"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
},
},
+
+ /*
+ * Models which should use the vendor backlight interface,
+ * because of broken native backlight control.
+ */
{
.callback = video_detect_force_vendor,
- /* Xiaomi Mi Pad 2 */
+ /* Sony Vaio PCG-FRV35 */
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "PCG-FRV35"),
},
},
@@ -400,8 +403,8 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "530U4E/540U4E"),
},
},
- /* https://bugs.launchpad.net/bugs/1894667 */
{
+ /* https://bugs.launchpad.net/bugs/1894667 */
.callback = video_detect_force_video,
/* HP 635 Notebook */
.matches = {
@@ -609,6 +612,23 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
DMI_MATCH(DMI_BOARD_NAME, "N250P"),
},
},
+ {
+ /* https://bugzilla.kernel.org/show_bug.cgi?id=202401 */
+ .callback = video_detect_force_native,
+ /* Sony Vaio VPCEH3U1E */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VPCEH3U1E"),
+ },
+ },
+ {
+ .callback = video_detect_force_native,
+ /* Sony Vaio VPCY11S1E */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VPCY11S1E"),
+ },
+ },
/*
* These Toshibas have a broken acpi-video interface for brightness
@@ -673,6 +693,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
},
{
.callback = video_detect_force_none,
+ /* GIGABYTE GB-BXBT-2807 */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "GB-BXBT-2807"),
+ },
+ },
+ {
+ .callback = video_detect_force_none,
/* MSI MS-7721 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "MSI"),
@@ -688,6 +716,16 @@ static bool google_cros_ec_present(void)
}
/*
+ * Windows 8 and newer no longer use the ACPI video interface, so it often
+ * does not work. So on win8+ systems prefer native brightness control.
+ * Chromebooks should always prefer native backlight control.
+ */
+static bool prefer_native_over_acpi_video(void)
+{
+ return acpi_osi_is_win8() || google_cros_ec_present();
+}
+
+/*
* Determine which type of backlight interface to use on this system,
* First check cmdline, then dmi quirks, then do autodetect.
*/
@@ -732,28 +770,16 @@ static enum acpi_backlight_type __acpi_video_get_backlight_type(bool native)
if (apple_gmux_present())
return acpi_backlight_apple_gmux;
- /* Chromebooks should always prefer native backlight control. */
- if (google_cros_ec_present() && native_available)
- return acpi_backlight_native;
+ /* Use ACPI video if available, except when native should be preferred. */
+ if ((video_caps & ACPI_VIDEO_BACKLIGHT) &&
+ !(native_available && prefer_native_over_acpi_video()))
+ return acpi_backlight_video;
- /* On systems with ACPI video use either native or ACPI video. */
- if (video_caps & ACPI_VIDEO_BACKLIGHT) {
- /*
- * Windows 8 and newer no longer use the ACPI video interface,
- * so it often does not work. If the ACPI tables are written
- * for win8 and native brightness ctl is available, use that.
- *
- * The native check deliberately is inside the if acpi-video
- * block on older devices without acpi-video support native
- * is usually not the best choice.
- */
- if (acpi_osi_is_win8() && native_available)
- return acpi_backlight_native;
- else
- return acpi_backlight_video;
- }
+ /* Use native if available */
+ if (native_available)
+ return acpi_backlight_native;
- /* No ACPI video (old hw), use vendor specific fw methods. */
+ /* No ACPI video/native (old hw), use vendor specific fw methods. */
return acpi_backlight_vendor;
}
@@ -765,18 +791,6 @@ EXPORT_SYMBOL(acpi_video_get_backlight_type);
bool acpi_video_backlight_use_native(void)
{
- /*
- * Call __acpi_video_get_backlight_type() to let it know that
- * a native backlight is available.
- */
- __acpi_video_get_backlight_type(true);
-
- /*
- * For now just always return true. There is a whole bunch of laptop
- * models where (video_caps & ACPI_VIDEO_BACKLIGHT) is false causing
- * __acpi_video_get_backlight_type() to return vendor, while these
- * models only have a native backlight control.
- */
- return true;
+ return __acpi_video_get_backlight_type(true) == acpi_backlight_native;
}
EXPORT_SYMBOL(acpi_video_backlight_use_native);
diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c
index d7d3f1669d4c..4e816bb402f6 100644
--- a/drivers/acpi/x86/utils.c
+++ b/drivers/acpi/x86/utils.c
@@ -308,7 +308,7 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
},
{
- /* Lenovo Yoga Tablet 1050F/L */
+ /* Lenovo Yoga Tablet 2 1050F/L */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."),
DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"),
@@ -320,6 +320,27 @@ static const struct dmi_system_id acpi_quirk_skip_dmi_ids[] = {
ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
},
{
+ /* Lenovo Yoga Tab 3 Pro X90F */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Blade3-10A-001"),
+ },
+ .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
+ ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
+ },
+ {
+ /* Medion Lifetab S10346 */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
+ /* Way too generic, also match on BIOS data */
+ DMI_MATCH(DMI_BIOS_DATE, "10/22/2015"),
+ },
+ .driver_data = (void *)(ACPI_QUIRK_SKIP_I2C_CLIENTS |
+ ACPI_QUIRK_SKIP_ACPI_AC_AND_BATTERY),
+ },
+ {
/* Nextbook Ares 8 */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Insyde"),
@@ -348,6 +369,7 @@ static const struct acpi_device_id i2c_acpi_known_good_ids[] = {
{ "10EC5640", 0 }, /* RealTek ALC5640 audio codec */
{ "INT33F4", 0 }, /* X-Powers AXP288 PMIC */
{ "INT33FD", 0 }, /* Intel Crystal Cove PMIC */
+ { "INT34D3", 0 }, /* Intel Whiskey Cove PMIC */
{ "NPCE69A", 0 }, /* Asus Transformer keyboard dock */
{}
};
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index 110a535648d2..ff7454a38058 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -421,12 +421,6 @@ static int amba_pm_runtime_resume(struct device *dev)
#endif /* CONFIG_PM */
static const struct dev_pm_ops amba_pm = {
- .suspend = pm_generic_suspend,
- .resume = pm_generic_resume,
- .freeze = pm_generic_freeze,
- .thaw = pm_generic_thaw,
- .poweroff = pm_generic_poweroff,
- .restore = pm_generic_restore,
SET_RUNTIME_PM_OPS(
amba_pm_runtime_suspend,
amba_pm_runtime_resume,
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 36833a862998..eceaec33af65 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -295,7 +295,7 @@ config SATA_FSL
config SATA_GEMINI
tristate "Gemini SATA bridge support"
- depends on ARCH_GEMINI || (OF && COMPILE_TEST)
+ depends on ARCH_GEMINI || COMPILE_TEST
select SATA_HOST
default ARCH_GEMINI
help
@@ -609,16 +609,6 @@ config PATA_ATP867X
If unsure, say N.
-config PATA_BK3710
- tristate "Palmchip BK3710 PATA support"
- depends on ARCH_DAVINCI || COMPILE_TEST
- select PATA_TIMINGS
- help
- This option enables support for the integrated IDE controller on
- the TI DaVinci SoC.
-
- If unsure, say N.
-
config PATA_CMD64X
tristate "CMD64x PATA support"
depends on PCI
@@ -696,7 +686,6 @@ config PATA_EP93XX
config PATA_FTIDE010
tristate "Faraday Technology FTIDE010 PATA support"
- depends on OF
depends on ARM || COMPILE_TEST
depends on SATA_GEMINI
help
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 34623365d9a6..d2e36d367274 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -54,7 +54,6 @@ obj-$(CONFIG_PATA_AMD) += pata_amd.o
obj-$(CONFIG_PATA_ARTOP) += pata_artop.o
obj-$(CONFIG_PATA_ATIIXP) += pata_atiixp.o
obj-$(CONFIG_PATA_ATP867X) += pata_atp867x.o
-obj-$(CONFIG_PATA_BK3710) += pata_bk3710.o
obj-$(CONFIG_PATA_CMD64X) += pata_cmd64x.o
obj-$(CONFIG_PATA_CS5520) += pata_cs5520.o
obj-$(CONFIG_PATA_CS5530) += pata_cs5530.o
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 639de2d75d63..0cfd0ec6229b 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -26,7 +26,6 @@
#include <linux/device.h>
#include <linux/dmi.h>
#include <linux/gfp.h>
-#include <linux/msi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_cmnd.h>
#include <linux/libata.h>
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h
index 7add8e79912b..ff8e6ae1c636 100644
--- a/drivers/ata/ahci.h
+++ b/drivers/ata/ahci.h
@@ -24,6 +24,7 @@
#include <linux/libata.h>
#include <linux/phy/phy.h>
#include <linux/regulator/consumer.h>
+#include <linux/bits.h>
/* Enclosure Management Control */
#define EM_CTRL_MSG_TYPE 0x000f0000
@@ -53,12 +54,12 @@ enum {
AHCI_PORT_PRIV_FBS_DMA_SZ = AHCI_CMD_SLOT_SZ +
AHCI_CMD_TBL_AR_SZ +
(AHCI_RX_FIS_SZ * 16),
- AHCI_IRQ_ON_SG = (1 << 31),
- AHCI_CMD_ATAPI = (1 << 5),
- AHCI_CMD_WRITE = (1 << 6),
- AHCI_CMD_PREFETCH = (1 << 7),
- AHCI_CMD_RESET = (1 << 8),
- AHCI_CMD_CLR_BUSY = (1 << 10),
+ AHCI_IRQ_ON_SG = BIT(31),
+ AHCI_CMD_ATAPI = BIT(5),
+ AHCI_CMD_WRITE = BIT(6),
+ AHCI_CMD_PREFETCH = BIT(7),
+ AHCI_CMD_RESET = BIT(8),
+ AHCI_CMD_CLR_BUSY = BIT(10),
RX_FIS_PIO_SETUP = 0x20, /* offset of PIO Setup FIS data */
RX_FIS_D2H_REG = 0x40, /* offset of D2H Register FIS data */
@@ -76,37 +77,37 @@ enum {
HOST_CAP2 = 0x24, /* host capabilities, extended */
/* HOST_CTL bits */
- HOST_RESET = (1 << 0), /* reset controller; self-clear */
- HOST_IRQ_EN = (1 << 1), /* global IRQ enable */
- HOST_MRSM = (1 << 2), /* MSI Revert to Single Message */
- HOST_AHCI_EN = (1 << 31), /* AHCI enabled */
+ HOST_RESET = BIT(0), /* reset controller; self-clear */
+ HOST_IRQ_EN = BIT(1), /* global IRQ enable */
+ HOST_MRSM = BIT(2), /* MSI Revert to Single Message */
+ HOST_AHCI_EN = BIT(31), /* AHCI enabled */
/* HOST_CAP bits */
- HOST_CAP_SXS = (1 << 5), /* Supports External SATA */
- HOST_CAP_EMS = (1 << 6), /* Enclosure Management support */
- HOST_CAP_CCC = (1 << 7), /* Command Completion Coalescing */
- HOST_CAP_PART = (1 << 13), /* Partial state capable */
- HOST_CAP_SSC = (1 << 14), /* Slumber state capable */
- HOST_CAP_PIO_MULTI = (1 << 15), /* PIO multiple DRQ support */
- HOST_CAP_FBS = (1 << 16), /* FIS-based switching support */
- HOST_CAP_PMP = (1 << 17), /* Port Multiplier support */
- HOST_CAP_ONLY = (1 << 18), /* Supports AHCI mode only */
- HOST_CAP_CLO = (1 << 24), /* Command List Override support */
- HOST_CAP_LED = (1 << 25), /* Supports activity LED */
- HOST_CAP_ALPM = (1 << 26), /* Aggressive Link PM support */
- HOST_CAP_SSS = (1 << 27), /* Staggered Spin-up */
- HOST_CAP_MPS = (1 << 28), /* Mechanical presence switch */
- HOST_CAP_SNTF = (1 << 29), /* SNotification register */
- HOST_CAP_NCQ = (1 << 30), /* Native Command Queueing */
- HOST_CAP_64 = (1 << 31), /* PCI DAC (64-bit DMA) support */
+ HOST_CAP_SXS = BIT(5), /* Supports External SATA */
+ HOST_CAP_EMS = BIT(6), /* Enclosure Management support */
+ HOST_CAP_CCC = BIT(7), /* Command Completion Coalescing */
+ HOST_CAP_PART = BIT(13), /* Partial state capable */
+ HOST_CAP_SSC = BIT(14), /* Slumber state capable */
+ HOST_CAP_PIO_MULTI = BIT(15), /* PIO multiple DRQ support */
+ HOST_CAP_FBS = BIT(16), /* FIS-based switching support */
+ HOST_CAP_PMP = BIT(17), /* Port Multiplier support */
+ HOST_CAP_ONLY = BIT(18), /* Supports AHCI mode only */
+ HOST_CAP_CLO = BIT(24), /* Command List Override support */
+ HOST_CAP_LED = BIT(25), /* Supports activity LED */
+ HOST_CAP_ALPM = BIT(26), /* Aggressive Link PM support */
+ HOST_CAP_SSS = BIT(27), /* Staggered Spin-up */
+ HOST_CAP_MPS = BIT(28), /* Mechanical presence switch */
+ HOST_CAP_SNTF = BIT(29), /* SNotification register */
+ HOST_CAP_NCQ = BIT(30), /* Native Command Queueing */
+ HOST_CAP_64 = BIT(31), /* PCI DAC (64-bit DMA) support */
/* HOST_CAP2 bits */
- HOST_CAP2_BOH = (1 << 0), /* BIOS/OS handoff supported */
- HOST_CAP2_NVMHCI = (1 << 1), /* NVMHCI supported */
- HOST_CAP2_APST = (1 << 2), /* Automatic partial to slumber */
- HOST_CAP2_SDS = (1 << 3), /* Support device sleep */
- HOST_CAP2_SADM = (1 << 4), /* Support aggressive DevSlp */
- HOST_CAP2_DESO = (1 << 5), /* DevSlp from slumber only */
+ HOST_CAP2_BOH = BIT(0), /* BIOS/OS handoff supported */
+ HOST_CAP2_NVMHCI = BIT(1), /* NVMHCI supported */
+ HOST_CAP2_APST = BIT(2), /* Automatic partial to slumber */
+ HOST_CAP2_SDS = BIT(3), /* Support device sleep */
+ HOST_CAP2_SADM = BIT(4), /* Support aggressive DevSlp */
+ HOST_CAP2_DESO = BIT(5), /* DevSlp from slumber only */
/* registers for each SATA port */
PORT_LST_ADDR = 0x00, /* command list DMA addr */
@@ -128,24 +129,24 @@ enum {
PORT_DEVSLP = 0x44, /* device sleep */
/* PORT_IRQ_{STAT,MASK} bits */
- PORT_IRQ_COLD_PRES = (1 << 31), /* cold presence detect */
- PORT_IRQ_TF_ERR = (1 << 30), /* task file error */
- PORT_IRQ_HBUS_ERR = (1 << 29), /* host bus fatal error */
- PORT_IRQ_HBUS_DATA_ERR = (1 << 28), /* host bus data error */
- PORT_IRQ_IF_ERR = (1 << 27), /* interface fatal error */
- PORT_IRQ_IF_NONFATAL = (1 << 26), /* interface non-fatal error */
- PORT_IRQ_OVERFLOW = (1 << 24), /* xfer exhausted available S/G */
- PORT_IRQ_BAD_PMP = (1 << 23), /* incorrect port multiplier */
-
- PORT_IRQ_PHYRDY = (1 << 22), /* PhyRdy changed */
- PORT_IRQ_DMPS = (1 << 7), /* mechanical presence status */
- PORT_IRQ_CONNECT = (1 << 6), /* port connect change status */
- PORT_IRQ_SG_DONE = (1 << 5), /* descriptor processed */
- PORT_IRQ_UNK_FIS = (1 << 4), /* unknown FIS rx'd */
- PORT_IRQ_SDB_FIS = (1 << 3), /* Set Device Bits FIS rx'd */
- PORT_IRQ_DMAS_FIS = (1 << 2), /* DMA Setup FIS rx'd */
- PORT_IRQ_PIOS_FIS = (1 << 1), /* PIO Setup FIS rx'd */
- PORT_IRQ_D2H_REG_FIS = (1 << 0), /* D2H Register FIS rx'd */
+ PORT_IRQ_COLD_PRES = BIT(31), /* cold presence detect */
+ PORT_IRQ_TF_ERR = BIT(30), /* task file error */
+ PORT_IRQ_HBUS_ERR = BIT(29), /* host bus fatal error */
+ PORT_IRQ_HBUS_DATA_ERR = BIT(28), /* host bus data error */
+ PORT_IRQ_IF_ERR = BIT(27), /* interface fatal error */
+ PORT_IRQ_IF_NONFATAL = BIT(26), /* interface non-fatal error */
+ PORT_IRQ_OVERFLOW = BIT(24), /* xfer exhausted available S/G */
+ PORT_IRQ_BAD_PMP = BIT(23), /* incorrect port multiplier */
+
+ PORT_IRQ_PHYRDY = BIT(22), /* PhyRdy changed */
+ PORT_IRQ_DMPS = BIT(7), /* mechanical presence status */
+ PORT_IRQ_CONNECT = BIT(6), /* port connect change status */
+ PORT_IRQ_SG_DONE = BIT(5), /* descriptor processed */
+ PORT_IRQ_UNK_FIS = BIT(4), /* unknown FIS rx'd */
+ PORT_IRQ_SDB_FIS = BIT(3), /* Set Device Bits FIS rx'd */
+ PORT_IRQ_DMAS_FIS = BIT(2), /* DMA Setup FIS rx'd */
+ PORT_IRQ_PIOS_FIS = BIT(1), /* PIO Setup FIS rx'd */
+ PORT_IRQ_D2H_REG_FIS = BIT(0), /* D2H Register FIS rx'd */
PORT_IRQ_FREEZE = PORT_IRQ_HBUS_ERR |
PORT_IRQ_IF_ERR |
@@ -161,27 +162,27 @@ enum {
PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS,
/* PORT_CMD bits */
- PORT_CMD_ASP = (1 << 27), /* Aggressive Slumber/Partial */
- PORT_CMD_ALPE = (1 << 26), /* Aggressive Link PM enable */
- PORT_CMD_ATAPI = (1 << 24), /* Device is ATAPI */
- PORT_CMD_FBSCP = (1 << 22), /* FBS Capable Port */
- PORT_CMD_ESP = (1 << 21), /* External Sata Port */
- PORT_CMD_CPD = (1 << 20), /* Cold Presence Detection */
- PORT_CMD_MPSP = (1 << 19), /* Mechanical Presence Switch */
- PORT_CMD_HPCP = (1 << 18), /* HotPlug Capable Port */
- PORT_CMD_PMP = (1 << 17), /* PMP attached */
- PORT_CMD_LIST_ON = (1 << 15), /* cmd list DMA engine running */
- PORT_CMD_FIS_ON = (1 << 14), /* FIS DMA engine running */
- PORT_CMD_FIS_RX = (1 << 4), /* Enable FIS receive DMA engine */
- PORT_CMD_CLO = (1 << 3), /* Command list override */
- PORT_CMD_POWER_ON = (1 << 2), /* Power up device */
- PORT_CMD_SPIN_UP = (1 << 1), /* Spin up device */
- PORT_CMD_START = (1 << 0), /* Enable port DMA engine */
-
- PORT_CMD_ICC_MASK = (0xf << 28), /* i/f ICC state mask */
- PORT_CMD_ICC_ACTIVE = (0x1 << 28), /* Put i/f in active state */
- PORT_CMD_ICC_PARTIAL = (0x2 << 28), /* Put i/f in partial state */
- PORT_CMD_ICC_SLUMBER = (0x6 << 28), /* Put i/f in slumber state */
+ PORT_CMD_ASP = BIT(27), /* Aggressive Slumber/Partial */
+ PORT_CMD_ALPE = BIT(26), /* Aggressive Link PM enable */
+ PORT_CMD_ATAPI = BIT(24), /* Device is ATAPI */
+ PORT_CMD_FBSCP = BIT(22), /* FBS Capable Port */
+ PORT_CMD_ESP = BIT(21), /* External Sata Port */
+ PORT_CMD_CPD = BIT(20), /* Cold Presence Detection */
+ PORT_CMD_MPSP = BIT(19), /* Mechanical Presence Switch */
+ PORT_CMD_HPCP = BIT(18), /* HotPlug Capable Port */
+ PORT_CMD_PMP = BIT(17), /* PMP attached */
+ PORT_CMD_LIST_ON = BIT(15), /* cmd list DMA engine running */
+ PORT_CMD_FIS_ON = BIT(14), /* FIS DMA engine running */
+ PORT_CMD_FIS_RX = BIT(4), /* Enable FIS receive DMA engine */
+ PORT_CMD_CLO = BIT(3), /* Command list override */
+ PORT_CMD_POWER_ON = BIT(2), /* Power up device */
+ PORT_CMD_SPIN_UP = BIT(1), /* Spin up device */
+ PORT_CMD_START = BIT(0), /* Enable port DMA engine */
+
+ PORT_CMD_ICC_MASK = (0xfu << 28), /* i/f ICC state mask */
+ PORT_CMD_ICC_ACTIVE = (0x1u << 28), /* Put i/f in active state */
+ PORT_CMD_ICC_PARTIAL = (0x2u << 28), /* Put i/f in partial state */
+ PORT_CMD_ICC_SLUMBER = (0x6u << 28), /* Put i/f in slumber state */
/* PORT_CMD capabilities mask */
PORT_CMD_CAP = PORT_CMD_HPCP | PORT_CMD_MPSP |
@@ -192,9 +193,9 @@ enum {
PORT_FBS_ADO_OFFSET = 12, /* FBS active dev optimization offset */
PORT_FBS_DEV_OFFSET = 8, /* FBS device to issue offset */
PORT_FBS_DEV_MASK = (0xf << PORT_FBS_DEV_OFFSET), /* FBS.DEV */
- PORT_FBS_SDE = (1 << 2), /* FBS single device error */
- PORT_FBS_DEC = (1 << 1), /* FBS device error clear */
- PORT_FBS_EN = (1 << 0), /* Enable FBS */
+ PORT_FBS_SDE = BIT(2), /* FBS single device error */
+ PORT_FBS_DEC = BIT(1), /* FBS device error clear */
+ PORT_FBS_EN = BIT(0), /* Enable FBS */
/* PORT_DEVSLP bits */
PORT_DEVSLP_DM_OFFSET = 25, /* DITO multiplier offset */
@@ -202,50 +203,50 @@ enum {
PORT_DEVSLP_DITO_OFFSET = 15, /* DITO offset */
PORT_DEVSLP_MDAT_OFFSET = 10, /* Minimum assertion time */
PORT_DEVSLP_DETO_OFFSET = 2, /* DevSlp exit timeout */
- PORT_DEVSLP_DSP = (1 << 1), /* DevSlp present */
- PORT_DEVSLP_ADSE = (1 << 0), /* Aggressive DevSlp enable */
+ PORT_DEVSLP_DSP = BIT(1), /* DevSlp present */
+ PORT_DEVSLP_ADSE = BIT(0), /* Aggressive DevSlp enable */
/* hpriv->flags bits */
#define AHCI_HFLAGS(flags) .private_data = (void *)(flags)
- AHCI_HFLAG_NO_NCQ = (1 << 0),
- AHCI_HFLAG_IGN_IRQ_IF_ERR = (1 << 1), /* ignore IRQ_IF_ERR */
- AHCI_HFLAG_IGN_SERR_INTERNAL = (1 << 2), /* ignore SERR_INTERNAL */
- AHCI_HFLAG_32BIT_ONLY = (1 << 3), /* force 32bit */
- AHCI_HFLAG_MV_PATA = (1 << 4), /* PATA port */
- AHCI_HFLAG_NO_MSI = (1 << 5), /* no PCI MSI */
- AHCI_HFLAG_NO_PMP = (1 << 6), /* no PMP */
- AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */
- AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */
- AHCI_HFLAG_NO_SUSPEND = (1 << 10), /* don't suspend */
- AHCI_HFLAG_SRST_TOUT_IS_OFFLINE = (1 << 11), /* treat SRST timeout as
- link offline */
- AHCI_HFLAG_NO_SNTF = (1 << 12), /* no sntf */
- AHCI_HFLAG_NO_FPDMA_AA = (1 << 13), /* no FPDMA AA */
- AHCI_HFLAG_YES_FBS = (1 << 14), /* force FBS cap on */
- AHCI_HFLAG_DELAY_ENGINE = (1 << 15), /* do not start engine on
- port start (wait until
- error-handling stage) */
- AHCI_HFLAG_NO_DEVSLP = (1 << 17), /* no device sleep */
- AHCI_HFLAG_NO_FBS = (1 << 18), /* no FBS */
+ AHCI_HFLAG_NO_NCQ = BIT(0),
+ AHCI_HFLAG_IGN_IRQ_IF_ERR = BIT(1), /* ignore IRQ_IF_ERR */
+ AHCI_HFLAG_IGN_SERR_INTERNAL = BIT(2), /* ignore SERR_INTERNAL */
+ AHCI_HFLAG_32BIT_ONLY = BIT(3), /* force 32bit */
+ AHCI_HFLAG_MV_PATA = BIT(4), /* PATA port */
+ AHCI_HFLAG_NO_MSI = BIT(5), /* no PCI MSI */
+ AHCI_HFLAG_NO_PMP = BIT(6), /* no PMP */
+ AHCI_HFLAG_SECT255 = BIT(8), /* max 255 sectors */
+ AHCI_HFLAG_YES_NCQ = BIT(9), /* force NCQ cap on */
+ AHCI_HFLAG_NO_SUSPEND = BIT(10), /* don't suspend */
+ AHCI_HFLAG_SRST_TOUT_IS_OFFLINE = BIT(11), /* treat SRST timeout as
+ link offline */
+ AHCI_HFLAG_NO_SNTF = BIT(12), /* no sntf */
+ AHCI_HFLAG_NO_FPDMA_AA = BIT(13), /* no FPDMA AA */
+ AHCI_HFLAG_YES_FBS = BIT(14), /* force FBS cap on */
+ AHCI_HFLAG_DELAY_ENGINE = BIT(15), /* do not start engine on
+ port start (wait until
+ error-handling stage) */
+ AHCI_HFLAG_NO_DEVSLP = BIT(17), /* no device sleep */
+ AHCI_HFLAG_NO_FBS = BIT(18), /* no FBS */
#ifdef CONFIG_PCI_MSI
- AHCI_HFLAG_MULTI_MSI = (1 << 20), /* per-port MSI(-X) */
+ AHCI_HFLAG_MULTI_MSI = BIT(20), /* per-port MSI(-X) */
#else
/* compile out MSI infrastructure */
AHCI_HFLAG_MULTI_MSI = 0,
#endif
- AHCI_HFLAG_WAKE_BEFORE_STOP = (1 << 22), /* wake before DMA stop */
- AHCI_HFLAG_YES_ALPM = (1 << 23), /* force ALPM cap on */
- AHCI_HFLAG_NO_WRITE_TO_RO = (1 << 24), /* don't write to read
- only registers */
- AHCI_HFLAG_USE_LPM_POLICY = (1 << 25), /* chipset that should use
- SATA_MOBILE_LPM_POLICY
- as default lpm_policy */
- AHCI_HFLAG_SUSPEND_PHYS = (1 << 26), /* handle PHYs during
- suspend/resume */
- AHCI_HFLAG_NO_SXS = (1 << 28), /* SXS not supported */
+ AHCI_HFLAG_WAKE_BEFORE_STOP = BIT(22), /* wake before DMA stop */
+ AHCI_HFLAG_YES_ALPM = BIT(23), /* force ALPM cap on */
+ AHCI_HFLAG_NO_WRITE_TO_RO = BIT(24), /* don't write to read
+ only registers */
+ AHCI_HFLAG_USE_LPM_POLICY = BIT(25), /* chipset that should use
+ SATA_MOBILE_LPM_POLICY
+ as default lpm_policy */
+ AHCI_HFLAG_SUSPEND_PHYS = BIT(26), /* handle PHYs during
+ suspend/resume */
+ AHCI_HFLAG_NO_SXS = BIT(28), /* SXS not supported */
/* ap->flags bits */
@@ -261,22 +262,22 @@ enum {
EM_MAX_RETRY = 5,
/* em_ctl bits */
- EM_CTL_RST = (1 << 9), /* Reset */
- EM_CTL_TM = (1 << 8), /* Transmit Message */
- EM_CTL_MR = (1 << 0), /* Message Received */
- EM_CTL_ALHD = (1 << 26), /* Activity LED */
- EM_CTL_XMT = (1 << 25), /* Transmit Only */
- EM_CTL_SMB = (1 << 24), /* Single Message Buffer */
- EM_CTL_SGPIO = (1 << 19), /* SGPIO messages supported */
- EM_CTL_SES = (1 << 18), /* SES-2 messages supported */
- EM_CTL_SAFTE = (1 << 17), /* SAF-TE messages supported */
- EM_CTL_LED = (1 << 16), /* LED messages supported */
+ EM_CTL_RST = BIT(9), /* Reset */
+ EM_CTL_TM = BIT(8), /* Transmit Message */
+ EM_CTL_MR = BIT(0), /* Message Received */
+ EM_CTL_ALHD = BIT(26), /* Activity LED */
+ EM_CTL_XMT = BIT(25), /* Transmit Only */
+ EM_CTL_SMB = BIT(24), /* Single Message Buffer */
+ EM_CTL_SGPIO = BIT(19), /* SGPIO messages supported */
+ EM_CTL_SES = BIT(18), /* SES-2 messages supported */
+ EM_CTL_SAFTE = BIT(17), /* SAF-TE messages supported */
+ EM_CTL_LED = BIT(16), /* LED messages supported */
/* em message type */
- EM_MSG_TYPE_LED = (1 << 0), /* LED */
- EM_MSG_TYPE_SAFTE = (1 << 1), /* SAF-TE */
- EM_MSG_TYPE_SES2 = (1 << 2), /* SES-2 */
- EM_MSG_TYPE_SGPIO = (1 << 3), /* SGPIO */
+ EM_MSG_TYPE_LED = BIT(0), /* LED */
+ EM_MSG_TYPE_SAFTE = BIT(1), /* SAF-TE */
+ EM_MSG_TYPE_SES2 = BIT(2), /* SES-2 */
+ EM_MSG_TYPE_SGPIO = BIT(3), /* SGPIO */
};
struct ahci_cmd_hdr {
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 954386a2b500..29acc35bf4a6 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -2071,6 +2071,20 @@ static bool ahci_qc_fill_rtf(struct ata_queued_cmd *qc)
!(qc->flags & ATA_QCFLAG_FAILED)) {
ata_tf_from_fis(rx_fis + RX_FIS_PIO_SETUP, &qc->result_tf);
qc->result_tf.status = (rx_fis + RX_FIS_PIO_SETUP)[15];
+
+ /*
+ * For NCQ commands, we never get a D2H FIS, so reading the D2H Register
+ * FIS area of the Received FIS Structure (which contains a copy of the
+ * last D2H FIS received) will contain an outdated status code.
+ * For NCQ commands, we instead get a SDB FIS, so read the SDB FIS area
+ * instead. However, the SDB FIS does not contain the LBA, so we can't
+ * use the ata_tf_from_fis() helper.
+ */
+ } else if (ata_is_ncq(qc->tf.protocol)) {
+ const u8 *fis = rx_fis + RX_FIS_SDB;
+
+ qc->result_tf.status = fis[2];
+ qc->result_tf.error = fis[3];
} else
ata_tf_from_fis(rx_fis + RX_FIS_D2H_REG, &qc->result_tf);
@@ -2106,7 +2120,7 @@ void ahci_error_handler(struct ata_port *ap)
{
struct ahci_host_priv *hpriv = ap->host->private_data;
- if (!(ap->pflags & ATA_PFLAG_FROZEN)) {
+ if (!ata_port_is_frozen(ap)) {
/* restart engine */
hpriv->stop_engine(ap);
hpriv->start_engine(ap);
@@ -2297,7 +2311,7 @@ static void ahci_pmp_attach(struct ata_port *ap)
* Note that during initialization, the port is marked as
* frozen since the irq handler is not yet registered.
*/
- if (!(ap->pflags & ATA_PFLAG_FROZEN))
+ if (!ata_port_is_frozen(ap))
writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
}
@@ -2316,7 +2330,7 @@ static void ahci_pmp_detach(struct ata_port *ap)
pp->intr_mask &= ~PORT_IRQ_BAD_PMP;
/* see comment above in ahci_pmp_attach() */
- if (!(ap->pflags & ATA_PFLAG_FROZEN))
+ if (!ata_port_is_frozen(ap))
writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
}
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 61b4ccf88bf1..d36e71f475ab 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -992,7 +992,7 @@ int ata_acpi_on_devcfg(struct ata_device *dev)
acpi_err:
/* ignore evaluation failure if we can continue safely */
- if (rc == -EINVAL && !nr_executed && !(ap->pflags & ATA_PFLAG_FROZEN))
+ if (rc == -EINVAL && !nr_executed && !ata_port_is_frozen(ap))
return 0;
/* fail and let EH retry once more for unknown IO errors */
@@ -1007,7 +1007,7 @@ int ata_acpi_on_devcfg(struct ata_device *dev)
/* We can safely continue if no _GTF command has been executed
* and port is not frozen.
*/
- if (!nr_executed && !(ap->pflags & ATA_PFLAG_FROZEN))
+ if (!nr_executed && !ata_port_is_frozen(ap))
return 0;
return rc;
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index d3ce5c383f3a..884ae73b11ea 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1489,7 +1489,7 @@ static unsigned ata_exec_internal_sg(struct ata_device *dev,
spin_lock_irqsave(ap->lock, flags);
/* no internal command while frozen */
- if (ap->pflags & ATA_PFLAG_FROZEN) {
+ if (ata_port_is_frozen(ap)) {
spin_unlock_irqrestore(ap->lock, flags);
return AC_ERR_SYSTEM;
}
@@ -2000,7 +2000,8 @@ retry:
if (err_mask) {
if (dma) {
dev->horkage |= ATA_HORKAGE_NO_DMA_LOG;
- goto retry;
+ if (!ata_port_is_frozen(dev->link->ap))
+ goto retry;
}
ata_dev_err(dev,
"Read log 0x%02x page 0x%02x failed, Emask 0x%x\n",
@@ -4721,7 +4722,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
return;
}
- WARN_ON_ONCE(ap->pflags & ATA_PFLAG_FROZEN);
+ WARN_ON_ONCE(ata_port_is_frozen(ap));
/* read result TF if requested */
if (qc->flags & ATA_QCFLAG_RESULT_TF)
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 08e11bc312c2..34303ce67c14 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1406,7 +1406,7 @@ static void ata_eh_request_sense(struct ata_queued_cmd *qc)
struct ata_taskfile tf;
unsigned int err_mask;
- if (qc->ap->pflags & ATA_PFLAG_FROZEN) {
+ if (ata_port_is_frozen(qc->ap)) {
ata_dev_warn(dev, "sense data available but port frozen\n");
return;
}
@@ -1428,8 +1428,10 @@ static void ata_eh_request_sense(struct ata_queued_cmd *qc)
err_mask = ata_exec_internal(dev, &tf, NULL, DMA_NONE, NULL, 0, 0);
/* Ignore err_mask; ATA_ERR might be set */
if (tf.status & ATA_SENSE) {
- ata_scsi_set_sense(dev, cmd, tf.lbah, tf.lbam, tf.lbal);
- qc->flags |= ATA_QCFLAG_SENSE_VALID;
+ if (ata_scsi_sense_is_valid(tf.lbah, tf.lbam, tf.lbal)) {
+ ata_scsi_set_sense(dev, cmd, tf.lbah, tf.lbam, tf.lbal);
+ qc->flags |= ATA_QCFLAG_SENSE_VALID;
+ }
} else {
ata_dev_warn(dev, "request sense failed stat %02x emask %x\n",
tf.status, err_mask);
@@ -1574,11 +1576,17 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc)
}
switch (qc->dev->class) {
+ case ATA_DEV_ATA:
case ATA_DEV_ZAC:
- if (stat & ATA_SENSE)
+ /*
+ * Fetch the sense data explicitly if:
+ * -It was a non-NCQ command that failed, or
+ * -It was a NCQ command that failed, but the sense data
+ * 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);
- fallthrough;
- case ATA_DEV_ATA:
if (err & ATA_ICRC)
qc->err_mask |= AC_ERR_ATA_BUS;
if (err & (ATA_UNC | ATA_AMNF))
@@ -1588,7 +1596,7 @@ static unsigned int ata_eh_analyze_tf(struct ata_queued_cmd *qc)
break;
case ATA_DEV_ATAPI:
- if (!(qc->ap->pflags & ATA_PFLAG_FROZEN)) {
+ if (!ata_port_is_frozen(qc->ap)) {
tmp = atapi_eh_request_sense(qc->dev,
qc->scsicmd->sense_buffer,
qc->result_tf.error >> 4);
@@ -1947,6 +1955,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
ata_qc_for_each_raw(ap, qc, tag) {
if (!(qc->flags & ATA_QCFLAG_FAILED) ||
+ qc->flags & ATA_QCFLAG_RETRY ||
ata_dev_phys_link(qc->dev) != link)
continue;
@@ -1995,7 +2004,7 @@ static void ata_eh_link_autopsy(struct ata_link *link)
ehc->i.flags |= ATA_EHI_QUIET;
/* enforce default EH actions */
- if (ap->pflags & ATA_PFLAG_FROZEN ||
+ if (ata_port_is_frozen(ap) ||
all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
ehc->i.action |= ATA_EH_RESET;
else if (((eflags & ATA_EFLAG_IS_IO) && all_err_mask) ||
@@ -2238,7 +2247,7 @@ static void ata_eh_link_report(struct ata_link *link)
return;
frozen = "";
- if (ap->pflags & ATA_PFLAG_FROZEN)
+ if (ata_port_is_frozen(ap))
frozen = " frozen";
if (ap->eh_tries < ATA_EH_MAX_TRIES)
@@ -2559,8 +2568,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
if (reset && !(ehc->i.action & ATA_EH_RESET)) {
ata_for_each_dev(dev, link, ALL)
classes[dev->devno] = ATA_DEV_NONE;
- if ((ap->pflags & ATA_PFLAG_FROZEN) &&
- ata_is_host_link(link))
+ if (ata_port_is_frozen(ap) && ata_is_host_link(link))
ata_eh_thaw_port(ap);
rc = 0;
goto out;
@@ -2718,7 +2726,7 @@ int ata_eh_reset(struct ata_link *link, int classify,
ap->pflags &= ~ATA_PFLAG_EH_PENDING;
spin_unlock_irqrestore(link->ap->lock, flags);
- if (ap->pflags & ATA_PFLAG_FROZEN)
+ if (ata_port_is_frozen(ap))
ata_eh_thaw_port(ap);
/*
@@ -3225,7 +3233,7 @@ static int ata_eh_maybe_retry_flush(struct ata_device *dev)
if (err_mask & AC_ERR_DEV) {
qc->err_mask |= AC_ERR_DEV;
qc->result_tf = tf;
- if (!(ap->pflags & ATA_PFLAG_FROZEN))
+ if (!ata_port_is_frozen(ap))
rc = 0;
}
}
@@ -3402,7 +3410,7 @@ static int ata_eh_skip_recovery(struct ata_link *link)
return 1;
/* thaw frozen port and recover failed devices */
- if ((ap->pflags & ATA_PFLAG_FROZEN) || ata_link_nr_enabled(link))
+ if (ata_port_is_frozen(ap) || ata_link_nr_enabled(link))
return 0;
/* reset at least once if reset is requested */
@@ -3757,7 +3765,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
if (dev)
ata_eh_handle_dev_fail(dev, rc);
- if (ap->pflags & ATA_PFLAG_FROZEN) {
+ if (ata_port_is_frozen(ap)) {
/* PMP reset requires working host port.
* Can't retry if it's frozen.
*/
@@ -3931,7 +3939,7 @@ static void ata_eh_handle_port_suspend(struct ata_port *ap)
ap->pflags &= ~ATA_PFLAG_PM_PENDING;
if (rc == 0)
ap->pflags |= ATA_PFLAG_SUSPENDED;
- else if (ap->pflags & ATA_PFLAG_FROZEN)
+ else if (ata_port_is_frozen(ap))
ata_port_schedule_eh(ap);
spin_unlock_irqrestore(ap->lock, flags);
diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c
index b6806d41a8c5..18ef14e749a0 100644
--- a/drivers/ata/libata-sata.c
+++ b/drivers/ata/libata-sata.c
@@ -1392,7 +1392,7 @@ static int ata_eh_read_log_10h(struct ata_device *dev,
tf->hob_lbah = buf[10];
tf->nsect = buf[12];
tf->hob_nsect = buf[13];
- if (dev->class == ATA_DEV_ZAC && ata_id_has_ncq_autosense(dev->id))
+ if (ata_id_has_ncq_autosense(dev->id) && (tf->status & ATA_SENSE))
tf->auxiliary = buf[14] << 16 | buf[15] << 8 | buf[16];
return 0;
@@ -1420,7 +1420,7 @@ void ata_eh_analyze_ncq_error(struct ata_link *link)
int tag, rc;
/* if frozen, we can't do much */
- if (ap->pflags & ATA_PFLAG_FROZEN)
+ if (ata_port_is_frozen(ap))
return;
/* is it NCQ device error? */
@@ -1456,17 +1456,51 @@ void ata_eh_analyze_ncq_error(struct ata_link *link)
memcpy(&qc->result_tf, &tf, sizeof(tf));
qc->result_tf.flags = ATA_TFLAG_ISADDR | ATA_TFLAG_LBA | ATA_TFLAG_LBA48;
qc->err_mask |= AC_ERR_DEV | AC_ERR_NCQ;
- if (dev->class == ATA_DEV_ZAC &&
- ((qc->result_tf.status & ATA_SENSE) || qc->result_tf.auxiliary)) {
+
+ /*
+ * If the device supports NCQ autosense, ata_eh_read_log_10h() will have
+ * stored the sense data in qc->result_tf.auxiliary.
+ */
+ if (qc->result_tf.auxiliary) {
char sense_key, asc, ascq;
sense_key = (qc->result_tf.auxiliary >> 16) & 0xff;
asc = (qc->result_tf.auxiliary >> 8) & 0xff;
ascq = qc->result_tf.auxiliary & 0xff;
- ata_scsi_set_sense(dev, qc->scsicmd, sense_key, asc, ascq);
- ata_scsi_set_sense_information(dev, qc->scsicmd,
- &qc->result_tf);
- qc->flags |= ATA_QCFLAG_SENSE_VALID;
+ if (ata_scsi_sense_is_valid(sense_key, asc, ascq)) {
+ ata_scsi_set_sense(dev, qc->scsicmd, sense_key, asc,
+ ascq);
+ ata_scsi_set_sense_information(dev, qc->scsicmd,
+ &qc->result_tf);
+ qc->flags |= ATA_QCFLAG_SENSE_VALID;
+ }
+ }
+
+ ata_qc_for_each_raw(ap, qc, tag) {
+ if (!(qc->flags & ATA_QCFLAG_FAILED) ||
+ ata_dev_phys_link(qc->dev) != link)
+ continue;
+
+ /* Skip the single QC which caused the NCQ error. */
+ if (qc->err_mask)
+ continue;
+
+ /*
+ * For SATA, the STATUS and ERROR fields are shared for all NCQ
+ * commands that were completed with the same SDB FIS.
+ * Therefore, we have to clear the ATA_ERR bit for all QCs
+ * except the one that caused the NCQ error.
+ */
+ qc->result_tf.status &= ~ATA_ERR;
+ qc->result_tf.error = 0;
+
+ /*
+ * If we get a NCQ error, that means that a single command was
+ * aborted. All other failed commands for our link should be
+ * retried and has no business of going though further scrutiny
+ * by ata_eh_link_autopsy().
+ */
+ qc->flags |= ATA_QCFLAG_RETRY;
}
ehc->i.err_mask &= ~AC_ERR_DEV;
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index 06a3d95ed8f9..cbb3a7a50816 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -188,6 +188,22 @@ DEVICE_ATTR(unload_heads, S_IRUGO | S_IWUSR,
ata_scsi_park_show, ata_scsi_park_store);
EXPORT_SYMBOL_GPL(dev_attr_unload_heads);
+bool ata_scsi_sense_is_valid(u8 sk, u8 asc, u8 ascq)
+{
+ /*
+ * If sk == NO_SENSE, and asc + ascq == NO ADDITIONAL SENSE INFORMATION,
+ * then there is no sense data to add.
+ */
+ if (sk == 0 && asc == 0 && ascq == 0)
+ return false;
+
+ /* If sk > COMPLETED, sense data is bogus. */
+ if (sk > COMPLETED)
+ return false;
+
+ return true;
+}
+
void ata_scsi_set_sense(struct ata_device *dev, struct scsi_cmnd *cmd,
u8 sk, u8 asc, u8 ascq)
{
@@ -642,7 +658,7 @@ static struct ata_queued_cmd *ata_scsi_qc_new(struct ata_device *dev,
struct ata_queued_cmd *qc;
int tag;
- if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
+ if (unlikely(ata_port_is_frozen(ap)))
goto fail;
if (ap->flags & ATA_FLAG_SAS_HOST) {
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 7916e369e15e..153f49e00713 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -184,62 +184,6 @@ void ata_sff_dma_pause(struct ata_port *ap)
}
EXPORT_SYMBOL_GPL(ata_sff_dma_pause);
-/**
- * ata_sff_busy_sleep - sleep until BSY clears, or timeout
- * @ap: port containing status register to be polled
- * @tmout_pat: impatience timeout in msecs
- * @tmout: overall timeout in msecs
- *
- * Sleep until ATA Status register bit BSY clears,
- * or a timeout occurs.
- *
- * LOCKING:
- * Kernel thread context (may sleep).
- *
- * RETURNS:
- * 0 on success, -errno otherwise.
- */
-int ata_sff_busy_sleep(struct ata_port *ap,
- unsigned long tmout_pat, unsigned long tmout)
-{
- unsigned long timer_start, timeout;
- u8 status;
-
- status = ata_sff_busy_wait(ap, ATA_BUSY, 300);
- timer_start = jiffies;
- timeout = ata_deadline(timer_start, tmout_pat);
- while (status != 0xff && (status & ATA_BUSY) &&
- time_before(jiffies, timeout)) {
- ata_msleep(ap, 50);
- status = ata_sff_busy_wait(ap, ATA_BUSY, 3);
- }
-
- if (status != 0xff && (status & ATA_BUSY))
- ata_port_warn(ap,
- "port is slow to respond, please be patient (Status 0x%x)\n",
- status);
-
- timeout = ata_deadline(timer_start, tmout);
- while (status != 0xff && (status & ATA_BUSY) &&
- time_before(jiffies, timeout)) {
- ata_msleep(ap, 50);
- status = ap->ops->sff_check_status(ap);
- }
-
- if (status == 0xff)
- return -ENODEV;
-
- if (status & ATA_BUSY) {
- ata_port_err(ap,
- "port failed to respond (%lu secs, Status 0x%x)\n",
- DIV_ROUND_UP(tmout, 1000), status);
- return -EBUSY;
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(ata_sff_busy_sleep);
-
static int ata_sff_check_ready(struct ata_link *link)
{
u8 status = link->ap->ops->sff_check_status(link->ap);
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h
index 2c5c8273af01..2cd6124a01e8 100644
--- a/drivers/ata/libata.h
+++ b/drivers/ata/libata.h
@@ -114,6 +114,7 @@ extern int ata_scsi_add_hosts(struct ata_host *host,
struct scsi_host_template *sht);
extern void ata_scsi_scan_host(struct ata_port *ap, int sync);
extern int ata_scsi_offline_dev(struct ata_device *dev);
+extern bool ata_scsi_sense_is_valid(u8 sk, u8 asc, u8 ascq);
extern void ata_scsi_set_sense(struct ata_device *dev,
struct scsi_cmnd *cmd, u8 sk, u8 asc, u8 ascq);
extern void ata_scsi_set_sense_information(struct ata_device *dev,
diff --git a/drivers/ata/pata_bk3710.c b/drivers/ata/pata_bk3710.c
deleted file mode 100644
index fad95cfecced..000000000000
--- a/drivers/ata/pata_bk3710.c
+++ /dev/null
@@ -1,380 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-/*
- * Palmchip BK3710 PATA controller driver
- *
- * Copyright (c) 2017 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Based on palm_bk3710.c:
- *
- * Copyright (C) 2006 Texas Instruments.
- * Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com>
- */
-
-#include <linux/ata.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/libata.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/types.h>
-
-#define DRV_NAME "pata_bk3710"
-
-#define BK3710_TF_OFFSET 0x1F0
-#define BK3710_CTL_OFFSET 0x3F6
-
-#define BK3710_BMISP 0x02
-#define BK3710_IDETIMP 0x40
-#define BK3710_UDMACTL 0x48
-#define BK3710_MISCCTL 0x50
-#define BK3710_REGSTB 0x54
-#define BK3710_REGRCVR 0x58
-#define BK3710_DATSTB 0x5C
-#define BK3710_DATRCVR 0x60
-#define BK3710_DMASTB 0x64
-#define BK3710_DMARCVR 0x68
-#define BK3710_UDMASTB 0x6C
-#define BK3710_UDMATRP 0x70
-#define BK3710_UDMAENV 0x74
-#define BK3710_IORDYTMP 0x78
-
-static struct scsi_host_template pata_bk3710_sht = {
- ATA_BMDMA_SHT(DRV_NAME),
-};
-
-static unsigned int ideclk_period; /* in nanoseconds */
-
-struct pata_bk3710_udmatiming {
- unsigned int rptime; /* tRP -- Ready to pause time (nsec) */
- unsigned int cycletime; /* tCYCTYP2/2 -- avg Cycle Time (nsec) */
- /* tENV is always a minimum of 20 nsec */
-};
-
-static const struct pata_bk3710_udmatiming pata_bk3710_udmatimings[6] = {
- { 160, 240 / 2 }, /* UDMA Mode 0 */
- { 125, 160 / 2 }, /* UDMA Mode 1 */
- { 100, 120 / 2 }, /* UDMA Mode 2 */
- { 100, 90 / 2 }, /* UDMA Mode 3 */
- { 100, 60 / 2 }, /* UDMA Mode 4 */
- { 85, 40 / 2 }, /* UDMA Mode 5 */
-};
-
-static void pata_bk3710_setudmamode(void __iomem *base, unsigned int dev,
- unsigned int mode)
-{
- u32 val32;
- u16 val16;
- u8 tenv, trp, t0;
-
- /* DMA Data Setup */
- t0 = DIV_ROUND_UP(pata_bk3710_udmatimings[mode].cycletime,
- ideclk_period) - 1;
- tenv = DIV_ROUND_UP(20, ideclk_period) - 1;
- trp = DIV_ROUND_UP(pata_bk3710_udmatimings[mode].rptime,
- ideclk_period) - 1;
-
- /* udmastb Ultra DMA Access Strobe Width */
- val32 = ioread32(base + BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8));
- val32 |= t0 << (dev ? 8 : 0);
- iowrite32(val32, base + BK3710_UDMASTB);
-
- /* udmatrp Ultra DMA Ready to Pause Time */
- val32 = ioread32(base + BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8));
- val32 |= trp << (dev ? 8 : 0);
- iowrite32(val32, base + BK3710_UDMATRP);
-
- /* udmaenv Ultra DMA envelop Time */
- val32 = ioread32(base + BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8));
- val32 |= tenv << (dev ? 8 : 0);
- iowrite32(val32, base + BK3710_UDMAENV);
-
- /* Enable UDMA for Device */
- val16 = ioread16(base + BK3710_UDMACTL) | (1 << dev);
- iowrite16(val16, base + BK3710_UDMACTL);
-}
-
-static void pata_bk3710_setmwdmamode(void __iomem *base, unsigned int dev,
- unsigned short min_cycle,
- unsigned int mode)
-{
- const struct ata_timing *t;
- int cycletime;
- u32 val32;
- u16 val16;
- u8 td, tkw, t0;
-
- t = ata_timing_find_mode(mode);
- cycletime = max_t(int, t->cycle, min_cycle);
-
- /* DMA Data Setup */
- t0 = DIV_ROUND_UP(cycletime, ideclk_period);
- td = DIV_ROUND_UP(t->active, ideclk_period);
- tkw = t0 - td - 1;
- td--;
-
- val32 = ioread32(base + BK3710_DMASTB) & (0xFF << (dev ? 0 : 8));
- val32 |= td << (dev ? 8 : 0);
- iowrite32(val32, base + BK3710_DMASTB);
-
- val32 = ioread32(base + BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8));
- val32 |= tkw << (dev ? 8 : 0);
- iowrite32(val32, base + BK3710_DMARCVR);
-
- /* Disable UDMA for Device */
- val16 = ioread16(base + BK3710_UDMACTL) & ~(1 << dev);
- iowrite16(val16, base + BK3710_UDMACTL);
-}
-
-static void pata_bk3710_set_dmamode(struct ata_port *ap,
- struct ata_device *adev)
-{
- void __iomem *base = (void __iomem *)ap->ioaddr.bmdma_addr;
- int is_slave = adev->devno;
- const u8 xferspeed = adev->dma_mode;
-
- if (xferspeed >= XFER_UDMA_0)
- pata_bk3710_setudmamode(base, is_slave,
- xferspeed - XFER_UDMA_0);
- else
- pata_bk3710_setmwdmamode(base, is_slave,
- adev->id[ATA_ID_EIDE_DMA_MIN],
- xferspeed);
-}
-
-static void pata_bk3710_setpiomode(void __iomem *base, struct ata_device *pair,
- unsigned int dev, unsigned int cycletime,
- unsigned int mode)
-{
- const struct ata_timing *t;
- u32 val32;
- u8 t2, t2i, t0;
-
- t = ata_timing_find_mode(XFER_PIO_0 + mode);
-
- /* PIO Data Setup */
- t0 = DIV_ROUND_UP(cycletime, ideclk_period);
- t2 = DIV_ROUND_UP(t->active, ideclk_period);
-
- t2i = t0 - t2 - 1;
- t2--;
-
- val32 = ioread32(base + BK3710_DATSTB) & (0xFF << (dev ? 0 : 8));
- val32 |= t2 << (dev ? 8 : 0);
- iowrite32(val32, base + BK3710_DATSTB);
-
- val32 = ioread32(base + BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8));
- val32 |= t2i << (dev ? 8 : 0);
- iowrite32(val32, base + BK3710_DATRCVR);
-
- /* FIXME: this is broken also in the old driver */
- if (pair) {
- u8 mode2 = pair->pio_mode - XFER_PIO_0;
-
- if (mode2 < mode)
- mode = mode2;
- }
-
- /* TASKFILE Setup */
- t0 = DIV_ROUND_UP(t->cyc8b, ideclk_period);
- t2 = DIV_ROUND_UP(t->act8b, ideclk_period);
-
- t2i = t0 - t2 - 1;
- t2--;
-
- val32 = ioread32(base + BK3710_REGSTB) & (0xFF << (dev ? 0 : 8));
- val32 |= t2 << (dev ? 8 : 0);
- iowrite32(val32, base + BK3710_REGSTB);
-
- val32 = ioread32(base + BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8));
- val32 |= t2i << (dev ? 8 : 0);
- iowrite32(val32, base + BK3710_REGRCVR);
-}
-
-static void pata_bk3710_set_piomode(struct ata_port *ap,
- struct ata_device *adev)
-{
- void __iomem *base = (void __iomem *)ap->ioaddr.bmdma_addr;
- struct ata_device *pair = ata_dev_pair(adev);
- const struct ata_timing *t = ata_timing_find_mode(adev->pio_mode);
- const u16 *id = adev->id;
- unsigned int cycle_time = 0;
- int is_slave = adev->devno;
- const u8 pio = adev->pio_mode - XFER_PIO_0;
-
- if (id[ATA_ID_FIELD_VALID] & 2) {
- if (ata_id_has_iordy(id))
- cycle_time = id[ATA_ID_EIDE_PIO_IORDY];
- else
- cycle_time = id[ATA_ID_EIDE_PIO];
-
- /* conservative "downgrade" for all pre-ATA2 drives */
- if (pio < 3 && cycle_time < t->cycle)
- cycle_time = 0; /* use standard timing */
- }
-
- if (!cycle_time)
- cycle_time = t->cycle;
-
- pata_bk3710_setpiomode(base, pair, is_slave, cycle_time, pio);
-}
-
-static void pata_bk3710_chipinit(void __iomem *base)
-{
- /*
- * REVISIT: the ATA reset signal needs to be managed through a
- * GPIO, which means it should come from platform_data. Until
- * we get and use such information, we have to trust that things
- * have been reset before we get here.
- */
-
- /*
- * Program the IDETIMP Register Value based on the following assumptions
- *
- * (ATA_IDETIMP_IDEEN , ENABLE ) |
- * (ATA_IDETIMP_PREPOST1 , DISABLE) |
- * (ATA_IDETIMP_PREPOST0 , DISABLE) |
- *
- * DM6446 silicon rev 2.1 and earlier have no observed net benefit
- * from enabling prefetch/postwrite.
- */
- iowrite16(BIT(15), base + BK3710_IDETIMP);
-
- /*
- * UDMACTL Ultra-ATA DMA Control
- * (ATA_UDMACTL_UDMAP1 , 0 ) |
- * (ATA_UDMACTL_UDMAP0 , 0 )
- *
- */
- iowrite16(0, base + BK3710_UDMACTL);
-
- /*
- * MISCCTL Miscellaneous Conrol Register
- * (ATA_MISCCTL_HWNHLD1P , 1 cycle)
- * (ATA_MISCCTL_HWNHLD0P , 1 cycle)
- * (ATA_MISCCTL_TIMORIDE , 1)
- */
- iowrite32(0x001, base + BK3710_MISCCTL);
-
- /*
- * IORDYTMP IORDY Timer for Primary Register
- * (ATA_IORDYTMP_IORDYTMP , DISABLE)
- */
- iowrite32(0, base + BK3710_IORDYTMP);
-
- /*
- * Configure BMISP Register
- * (ATA_BMISP_DMAEN1 , DISABLE ) |
- * (ATA_BMISP_DMAEN0 , DISABLE ) |
- * (ATA_BMISP_IORDYINT , CLEAR) |
- * (ATA_BMISP_INTRSTAT , CLEAR) |
- * (ATA_BMISP_DMAERROR , CLEAR)
- */
- iowrite16(0xE, base + BK3710_BMISP);
-
- pata_bk3710_setpiomode(base, NULL, 0, 600, 0);
- pata_bk3710_setpiomode(base, NULL, 1, 600, 0);
-}
-
-static struct ata_port_operations pata_bk3710_ports_ops = {
- .inherits = &ata_bmdma_port_ops,
- .cable_detect = ata_cable_80wire,
-
- .set_piomode = pata_bk3710_set_piomode,
- .set_dmamode = pata_bk3710_set_dmamode,
-};
-
-static int __init pata_bk3710_probe(struct platform_device *pdev)
-{
- struct clk *clk;
- struct resource *mem;
- struct ata_host *host;
- struct ata_port *ap;
- void __iomem *base;
- unsigned long rate;
- int irq;
-
- clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(clk))
- return -ENODEV;
-
- clk_enable(clk);
- rate = clk_get_rate(clk);
- if (!rate)
- return -EINVAL;
-
- /* NOTE: round *down* to meet minimum timings; we count in clocks */
- ideclk_period = 1000000000UL / rate;
-
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- pr_err(DRV_NAME ": failed to get IRQ resource\n");
- return irq;
- }
-
- base = devm_ioremap_resource(&pdev->dev, mem);
- if (IS_ERR(base))
- return PTR_ERR(base);
-
- /* configure the Palmchip controller */
- pata_bk3710_chipinit(base);
-
- /* allocate host */
- host = ata_host_alloc(&pdev->dev, 1);
- if (!host)
- return -ENOMEM;
- ap = host->ports[0];
-
- ap->ops = &pata_bk3710_ports_ops;
- ap->pio_mask = ATA_PIO4;
- ap->mwdma_mask = ATA_MWDMA2;
- ap->udma_mask = rate < 100000000 ? ATA_UDMA4 : ATA_UDMA5;
- ap->flags |= ATA_FLAG_SLAVE_POSS;
-
- ap->ioaddr.data_addr = base + BK3710_TF_OFFSET;
- ap->ioaddr.error_addr = base + BK3710_TF_OFFSET + 1;
- ap->ioaddr.feature_addr = base + BK3710_TF_OFFSET + 1;
- ap->ioaddr.nsect_addr = base + BK3710_TF_OFFSET + 2;
- ap->ioaddr.lbal_addr = base + BK3710_TF_OFFSET + 3;
- ap->ioaddr.lbam_addr = base + BK3710_TF_OFFSET + 4;
- ap->ioaddr.lbah_addr = base + BK3710_TF_OFFSET + 5;
- ap->ioaddr.device_addr = base + BK3710_TF_OFFSET + 6;
- ap->ioaddr.status_addr = base + BK3710_TF_OFFSET + 7;
- ap->ioaddr.command_addr = base + BK3710_TF_OFFSET + 7;
-
- ap->ioaddr.altstatus_addr = base + BK3710_CTL_OFFSET;
- ap->ioaddr.ctl_addr = base + BK3710_CTL_OFFSET;
-
- ap->ioaddr.bmdma_addr = base;
-
- ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx",
- (unsigned long)base + BK3710_TF_OFFSET,
- (unsigned long)base + BK3710_CTL_OFFSET);
-
- /* activate */
- return ata_host_activate(host, irq, ata_sff_interrupt, 0,
- &pata_bk3710_sht);
-}
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:palm_bk3710");
-
-static struct platform_driver pata_bk3710_driver = {
- .driver = {
- .name = "palm_bk3710",
- },
-};
-
-static int __init pata_bk3710_init(void)
-{
- return platform_driver_probe(&pata_bk3710_driver, pata_bk3710_probe);
-}
-
-module_init(pata_bk3710_init);
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/ata/pata_ep93xx.c b/drivers/ata/pata_ep93xx.c
index 6c75a22db12b..47845d920075 100644
--- a/drivers/ata/pata_ep93xx.c
+++ b/drivers/ata/pata_ep93xx.c
@@ -931,8 +931,7 @@ static int ep93xx_pata_probe(struct platform_device *pdev)
goto err_rel_gpio;
}
- mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- ide_base = devm_ioremap_resource(&pdev->dev, mem_res);
+ ide_base = devm_platform_get_and_ioremap_resource(pdev, 0, &mem_res);
if (IS_ERR(ide_base)) {
err = PTR_ERR(ide_base);
goto err_rel_gpio;
diff --git a/drivers/ata/pata_ftide010.c b/drivers/ata/pata_ftide010.c
index 0117df0fe3c5..88924b5daa1a 100644
--- a/drivers/ata/pata_ftide010.c
+++ b/drivers/ata/pata_ftide010.c
@@ -560,7 +560,7 @@ static const struct of_device_id pata_ftide010_of_match[] = {
static struct platform_driver pata_ftide010_driver = {
.driver = {
.name = DRV_NAME,
- .of_match_table = of_match_ptr(pata_ftide010_of_match),
+ .of_match_table = pata_ftide010_of_match,
},
.probe = pata_ftide010_probe,
.remove = pata_ftide010_remove,
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index 6559b606736d..3ebd6522a1fd 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -731,7 +731,7 @@ static int mpc52xx_ata_probe(struct platform_device *op)
udma_mask = ATA_UDMA2 & ((1 << (*prop + 1)) - 1);
ata_irq = irq_of_parse_and_map(op->dev.of_node, 0);
- if (ata_irq == NO_IRQ) {
+ if (!ata_irq) {
dev_err(&op->dev, "error mapping irq\n");
return -EINVAL;
}
diff --git a/drivers/ata/sata_dwc_460ex.c b/drivers/ata/sata_dwc_460ex.c
index e3263e961045..21d77633a98f 100644
--- a/drivers/ata/sata_dwc_460ex.c
+++ b/drivers/ata/sata_dwc_460ex.c
@@ -42,10 +42,6 @@
#define sata_dwc_writel(a, v) writel_relaxed(v, a)
#define sata_dwc_readl(a) readl_relaxed(a)
-#ifndef NO_IRQ
-#define NO_IRQ 0
-#endif
-
#define AHB_DMA_BRST_DFLT 64 /* 16 data items burst length */
enum {
@@ -242,7 +238,7 @@ static int sata_dwc_dma_init_old(struct platform_device *pdev,
/* Get SATA DMA interrupt number */
hsdev->dma->irq = irq_of_parse_and_map(np, 1);
- if (hsdev->dma->irq == NO_IRQ) {
+ if (!hsdev->dma->irq) {
dev_err(dev, "no SATA DMA irq\n");
return -ENODEV;
}
@@ -472,7 +468,7 @@ static irqreturn_t sata_dwc_isr(int irq, void *dev_instance)
struct ata_queued_cmd *qc;
unsigned long flags;
u8 status, tag;
- int handled, num_processed, port = 0;
+ int handled, port = 0;
uint intpr, sactive, sactive2, tag_mask;
struct sata_dwc_device_port *hsdevp;
hsdev->sactive_issued = 0;
@@ -618,9 +614,7 @@ DRVSTILLBUSY:
dev_dbg(ap->dev, "%s ATA status register=0x%x\n", __func__, status);
tag = 0;
- num_processed = 0;
while (tag_mask) {
- num_processed++;
while (!(tag_mask & 0x00000001)) {
tag++;
tag_mask <<= 1;
@@ -1180,7 +1174,7 @@ static int sata_dwc_probe(struct platform_device *ofdev)
/* Get SATA interrupt number */
irq = irq_of_parse_and_map(np, 0);
- if (irq == NO_IRQ) {
+ if (!irq) {
dev_err(dev, "no SATA DMA irq\n");
return -ENODEV;
}
diff --git a/drivers/ata/sata_gemini.c b/drivers/ata/sata_gemini.c
index b729e9919bb0..c42cc9bbbc4e 100644
--- a/drivers/ata/sata_gemini.c
+++ b/drivers/ata/sata_gemini.c
@@ -421,7 +421,7 @@ static const struct of_device_id gemini_sata_of_match[] = {
static struct platform_driver gemini_sata_driver = {
.driver = {
.name = DRV_NAME,
- .of_match_table = of_match_ptr(gemini_sata_of_match),
+ .of_match_table = gemini_sata_of_match,
},
.probe = gemini_sata_probe,
.remove = gemini_sata_remove,
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 7f14d0d31057..9b2d289e89e1 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -2185,7 +2185,7 @@ static void nv_swncq_host_interrupt(struct ata_port *ap, u16 fis)
if (!fis)
return;
- if (ap->pflags & ATA_PFLAG_FROZEN)
+ if (ata_port_is_frozen(ap))
return;
if (fis & NV_SWNCQ_IRQ_HOTPLUG) {
diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c
index b8465fef2ed2..9cd7d8b71361 100644
--- a/drivers/ata/sata_promise.c
+++ b/drivers/ata/sata_promise.c
@@ -817,7 +817,7 @@ static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class,
static void pdc_error_handler(struct ata_port *ap)
{
- if (!(ap->pflags & ATA_PFLAG_FROZEN))
+ if (!ata_port_is_frozen(ap))
pdc_reset_port(ap);
ata_sff_error_handler(ap);
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c
index 6ceec59cb291..ab70cbc78f96 100644
--- a/drivers/ata/sata_sx4.c
+++ b/drivers/ata/sata_sx4.c
@@ -855,7 +855,7 @@ static int pdc_softreset(struct ata_link *link, unsigned int *class,
static void pdc_error_handler(struct ata_port *ap)
{
- if (!(ap->pflags & ATA_PFLAG_FROZEN))
+ if (!ata_port_is_frozen(ap))
pdc_reset_port(ap);
ata_sff_error_handler(ap);
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 83217d243c25..3079bfe53d04 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -22,7 +22,7 @@ obj-$(CONFIG_REGMAP) += regmap/
obj-$(CONFIG_SOC_BUS) += soc.o
obj-$(CONFIG_PINCTRL) += pinctrl.o
obj-$(CONFIG_DEV_COREDUMP) += devcoredump.o
-obj-$(CONFIG_GENERIC_MSI_IRQ_DOMAIN) += platform-msi.o
+obj-$(CONFIG_GENERIC_MSI_IRQ) += platform-msi.o
obj-$(CONFIG_GENERIC_ARCH_TOPOLOGY) += arch_topology.o
obj-$(CONFIG_GENERIC_ARCH_NUMA) += arch_numa.o
obj-$(CONFIG_ACPI) += physical_location.o
diff --git a/drivers/base/platform-msi.c b/drivers/base/platform-msi.c
index 12b044151298..5883e7634a2b 100644
--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -213,7 +213,7 @@ int platform_msi_domain_alloc_irqs(struct device *dev, unsigned int nvec,
if (err)
return err;
- err = msi_domain_alloc_irqs(dev->msi.domain, dev, nvec);
+ err = msi_domain_alloc_irqs_range(dev, MSI_DEFAULT_DOMAIN, 0, nvec - 1);
if (err)
platform_msi_free_priv_data(dev);
@@ -227,7 +227,7 @@ EXPORT_SYMBOL_GPL(platform_msi_domain_alloc_irqs);
*/
void platform_msi_domain_free_irqs(struct device *dev)
{
- msi_domain_free_irqs(dev->msi.domain, dev);
+ msi_domain_free_irqs_all(dev, MSI_DEFAULT_DOMAIN);
platform_msi_free_priv_data(dev);
}
EXPORT_SYMBOL_GPL(platform_msi_domain_free_irqs);
@@ -325,7 +325,7 @@ void platform_msi_device_domain_free(struct irq_domain *domain, unsigned int vir
msi_lock_descs(data->dev);
irq_domain_free_irqs_common(domain, virq, nr_irqs);
- msi_free_msi_descs_range(data->dev, MSI_DESC_ALL, virq, virq + nr_irqs - 1);
+ msi_free_msi_descs_range(data->dev, virq, virq + nr_irqs - 1);
msi_unlock_descs(data->dev);
}
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index 6471b559230e..967bcf9d415e 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -494,6 +494,31 @@ void dev_pm_genpd_set_next_wakeup(struct device *dev, ktime_t next)
}
EXPORT_SYMBOL_GPL(dev_pm_genpd_set_next_wakeup);
+/**
+ * dev_pm_genpd_get_next_hrtimer - Return the next_hrtimer for the genpd
+ * @dev: A device that is attached to the genpd.
+ *
+ * This routine should typically be called for a device, at the point of when a
+ * GENPD_NOTIFY_PRE_OFF notification has been sent for it.
+ *
+ * Returns the aggregated value of the genpd's next hrtimer or KTIME_MAX if no
+ * valid value have been set.
+ */
+ktime_t dev_pm_genpd_get_next_hrtimer(struct device *dev)
+{
+ struct generic_pm_domain *genpd;
+
+ genpd = dev_to_genpd_safe(dev);
+ if (!genpd)
+ return KTIME_MAX;
+
+ if (genpd->gd)
+ return genpd->gd->next_hrtimer;
+
+ return KTIME_MAX;
+}
+EXPORT_SYMBOL_GPL(dev_pm_genpd_get_next_hrtimer);
+
static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed)
{
unsigned int state_idx = genpd->state_idx;
@@ -939,8 +964,8 @@ static int genpd_runtime_suspend(struct device *dev)
return 0;
genpd_lock(genpd);
- gpd_data->rpm_pstate = genpd_drop_performance_state(dev);
genpd_power_off(genpd, true, 0);
+ gpd_data->rpm_pstate = genpd_drop_performance_state(dev);
genpd_unlock(genpd);
return 0;
@@ -978,9 +1003,8 @@ static int genpd_runtime_resume(struct device *dev)
goto out;
genpd_lock(genpd);
+ genpd_restore_performance_state(dev, gpd_data->rpm_pstate);
ret = genpd_power_on(genpd, 0);
- if (!ret)
- genpd_restore_performance_state(dev, gpd_data->rpm_pstate);
genpd_unlock(genpd);
if (ret)
@@ -1018,8 +1042,8 @@ err_stop:
err_poweroff:
if (!pm_runtime_is_irq_safe(dev) || genpd_is_irq_safe(genpd)) {
genpd_lock(genpd);
- gpd_data->rpm_pstate = genpd_drop_performance_state(dev);
genpd_power_off(genpd, true, 0);
+ gpd_data->rpm_pstate = genpd_drop_performance_state(dev);
genpd_unlock(genpd);
}
@@ -1189,12 +1213,15 @@ static int genpd_prepare(struct device *dev)
* genpd_finish_suspend - Completion of suspend or hibernation of device in an
* I/O pm domain.
* @dev: Device to suspend.
- * @poweroff: Specifies if this is a poweroff_noirq or suspend_noirq callback.
+ * @suspend_noirq: Generic suspend_noirq callback.
+ * @resume_noirq: Generic resume_noirq callback.
*
* Stop the device and remove power from the domain if all devices in it have
* been stopped.
*/
-static int genpd_finish_suspend(struct device *dev, bool poweroff)
+static int genpd_finish_suspend(struct device *dev,
+ int (*suspend_noirq)(struct device *dev),
+ int (*resume_noirq)(struct device *dev))
{
struct generic_pm_domain *genpd;
int ret = 0;
@@ -1203,10 +1230,7 @@ static int genpd_finish_suspend(struct device *dev, bool poweroff)
if (IS_ERR(genpd))
return -EINVAL;
- if (poweroff)
- ret = pm_generic_poweroff_noirq(dev);
- else
- ret = pm_generic_suspend_noirq(dev);
+ ret = suspend_noirq(dev);
if (ret)
return ret;
@@ -1217,10 +1241,7 @@ static int genpd_finish_suspend(struct device *dev, bool poweroff)
!pm_runtime_status_suspended(dev)) {
ret = genpd_stop_dev(genpd, dev);
if (ret) {
- if (poweroff)
- pm_generic_restore_noirq(dev);
- else
- pm_generic_resume_noirq(dev);
+ resume_noirq(dev);
return ret;
}
}
@@ -1244,16 +1265,20 @@ static int genpd_suspend_noirq(struct device *dev)
{
dev_dbg(dev, "%s()\n", __func__);
- return genpd_finish_suspend(dev, false);
+ return genpd_finish_suspend(dev,
+ pm_generic_suspend_noirq,
+ pm_generic_resume_noirq);
}
/**
- * genpd_resume_noirq - Start of resume of device in an I/O PM domain.
+ * genpd_finish_resume - Completion of resume of device in an I/O PM domain.
* @dev: Device to resume.
+ * @resume_noirq: Generic resume_noirq callback.
*
* Restore power to the device's PM domain, if necessary, and start the device.
*/
-static int genpd_resume_noirq(struct device *dev)
+static int genpd_finish_resume(struct device *dev,
+ int (*resume_noirq)(struct device *dev))
{
struct generic_pm_domain *genpd;
int ret;
@@ -1265,7 +1290,7 @@ static int genpd_resume_noirq(struct device *dev)
return -EINVAL;
if (device_wakeup_path(dev) && genpd_is_active_wakeup(genpd))
- return pm_generic_resume_noirq(dev);
+ return resume_noirq(dev);
genpd_lock(genpd);
genpd_sync_power_on(genpd, true, 0);
@@ -1283,6 +1308,19 @@ static int genpd_resume_noirq(struct device *dev)
}
/**
+ * genpd_resume_noirq - Start of resume of device in an I/O PM domain.
+ * @dev: Device to resume.
+ *
+ * Restore power to the device's PM domain, if necessary, and start the device.
+ */
+static int genpd_resume_noirq(struct device *dev)
+{
+ dev_dbg(dev, "%s()\n", __func__);
+
+ return genpd_finish_resume(dev, pm_generic_resume_noirq);
+}
+
+/**
* genpd_freeze_noirq - Completion of freezing a device in an I/O PM domain.
* @dev: Device to freeze.
*
@@ -1293,24 +1331,11 @@ static int genpd_resume_noirq(struct device *dev)
*/
static int genpd_freeze_noirq(struct device *dev)
{
- const struct generic_pm_domain *genpd;
- int ret = 0;
-
dev_dbg(dev, "%s()\n", __func__);
- genpd = dev_to_genpd(dev);
- if (IS_ERR(genpd))
- return -EINVAL;
-
- ret = pm_generic_freeze_noirq(dev);
- if (ret)
- return ret;
-
- if (genpd->dev_ops.stop && genpd->dev_ops.start &&
- !pm_runtime_status_suspended(dev))
- ret = genpd_stop_dev(genpd, dev);
-
- return ret;
+ return genpd_finish_suspend(dev,
+ pm_generic_freeze_noirq,
+ pm_generic_thaw_noirq);
}
/**
@@ -1322,23 +1347,9 @@ static int genpd_freeze_noirq(struct device *dev)
*/
static int genpd_thaw_noirq(struct device *dev)
{
- const struct generic_pm_domain *genpd;
- int ret = 0;
-
dev_dbg(dev, "%s()\n", __func__);
- genpd = dev_to_genpd(dev);
- if (IS_ERR(genpd))
- return -EINVAL;
-
- if (genpd->dev_ops.stop && genpd->dev_ops.start &&
- !pm_runtime_status_suspended(dev)) {
- ret = genpd_start_dev(genpd, dev);
- if (ret)
- return ret;
- }
-
- return pm_generic_thaw_noirq(dev);
+ return genpd_finish_resume(dev, pm_generic_thaw_noirq);
}
/**
@@ -1353,7 +1364,9 @@ static int genpd_poweroff_noirq(struct device *dev)
{
dev_dbg(dev, "%s()\n", __func__);
- return genpd_finish_suspend(dev, true);
+ return genpd_finish_suspend(dev,
+ pm_generic_poweroff_noirq,
+ pm_generic_restore_noirq);
}
/**
@@ -1365,40 +1378,9 @@ static int genpd_poweroff_noirq(struct device *dev)
*/
static int genpd_restore_noirq(struct device *dev)
{
- struct generic_pm_domain *genpd;
- int ret = 0;
-
dev_dbg(dev, "%s()\n", __func__);
- genpd = dev_to_genpd(dev);
- if (IS_ERR(genpd))
- return -EINVAL;
-
- /*
- * At this point suspended_count == 0 means we are being run for the
- * first time for the given domain in the present cycle.
- */
- genpd_lock(genpd);
- if (genpd->suspended_count++ == 0) {
- /*
- * The boot kernel might put the domain into arbitrary state,
- * so make it appear as powered off to genpd_sync_power_on(),
- * so that it tries to power it on in case it was really off.
- */
- genpd->status = GENPD_STATE_OFF;
- }
-
- genpd_sync_power_on(genpd, true, 0);
- genpd_unlock(genpd);
-
- if (genpd->dev_ops.stop && genpd->dev_ops.start &&
- !pm_runtime_status_suspended(dev)) {
- ret = genpd_start_dev(genpd, dev);
- if (ret)
- return ret;
- }
-
- return pm_generic_restore_noirq(dev);
+ return genpd_finish_resume(dev, pm_generic_restore_noirq);
}
/**
@@ -1994,6 +1976,7 @@ static int genpd_alloc_data(struct generic_pm_domain *genpd)
gd->max_off_time_ns = -1;
gd->max_off_time_changed = true;
gd->next_wakeup = KTIME_MAX;
+ gd->next_hrtimer = KTIME_MAX;
}
/* Use only one "off" state if there were no states declared */
@@ -2749,17 +2732,6 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev,
dev->pm_domain->detach = genpd_dev_pm_detach;
dev->pm_domain->sync = genpd_dev_pm_sync;
- if (power_on) {
- genpd_lock(pd);
- ret = genpd_power_on(pd, 0);
- genpd_unlock(pd);
- }
-
- if (ret) {
- genpd_remove_device(pd, dev);
- return -EPROBE_DEFER;
- }
-
/* Set the default performance state */
pstate = of_get_required_opp_performance_state(dev->of_node, index);
if (pstate < 0 && pstate != -ENODEV && pstate != -EOPNOTSUPP) {
@@ -2771,6 +2743,24 @@ static int __genpd_dev_pm_attach(struct device *dev, struct device *base_dev,
goto err;
dev_gpd_data(dev)->default_pstate = pstate;
}
+
+ if (power_on) {
+ genpd_lock(pd);
+ ret = genpd_power_on(pd, 0);
+ genpd_unlock(pd);
+ }
+
+ if (ret) {
+ /* Drop the default performance state */
+ if (dev_gpd_data(dev)->default_pstate) {
+ dev_pm_genpd_set_performance_state(dev, 0);
+ dev_gpd_data(dev)->default_pstate = 0;
+ }
+
+ genpd_remove_device(pd, dev);
+ return -EPROBE_DEFER;
+ }
+
return 1;
err:
diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c
index 282a3a135827..cc2c3a5a6d35 100644
--- a/drivers/base/power/domain_governor.c
+++ b/drivers/base/power/domain_governor.c
@@ -375,6 +375,9 @@ static bool cpu_power_down_ok(struct dev_pm_domain *pd)
if (idle_duration_ns <= 0)
return false;
+ /* Store the next domain_wakeup to allow consumers to use it. */
+ genpd->gd->next_hrtimer = domain_wakeup;
+
/*
* Find the deepest idle state that has its residency value satisfied
* and by also taking into account the power off latency for the state.
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index b52049098d4e..50e726b6c2cf 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -243,8 +243,7 @@ void pm_runtime_set_memalloc_noio(struct device *dev, bool enable)
* flag was set by any one of the descendants.
*/
if (!dev || (!enable &&
- device_for_each_child(dev, NULL,
- dev_memalloc_noio)))
+ device_for_each_child(dev, NULL, dev_memalloc_noio)))
break;
}
mutex_unlock(&dev_hotplug_mutex);
@@ -265,15 +264,13 @@ static int rpm_check_suspend_allowed(struct device *dev)
retval = -EACCES;
else if (atomic_read(&dev->power.usage_count))
retval = -EAGAIN;
- else if (!dev->power.ignore_children &&
- atomic_read(&dev->power.child_count))
+ else if (!dev->power.ignore_children && atomic_read(&dev->power.child_count))
retval = -EBUSY;
/* Pending resume requests take precedence over suspends. */
- else if ((dev->power.deferred_resume
- && dev->power.runtime_status == RPM_SUSPENDING)
- || (dev->power.request_pending
- && dev->power.request == RPM_REQ_RESUME))
+ else if ((dev->power.deferred_resume &&
+ dev->power.runtime_status == RPM_SUSPENDING) ||
+ (dev->power.request_pending && dev->power.request == RPM_REQ_RESUME))
retval = -EAGAIN;
else if (__dev_pm_qos_resume_latency(dev) == 0)
retval = -EPERM;
@@ -404,9 +401,9 @@ static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
*
* Do that if resume fails too.
*/
- if (use_links
- && ((dev->power.runtime_status == RPM_SUSPENDING && !retval)
- || (dev->power.runtime_status == RPM_RESUMING && retval))) {
+ if (use_links &&
+ ((dev->power.runtime_status == RPM_SUSPENDING && !retval) ||
+ (dev->power.runtime_status == RPM_RESUMING && retval))) {
idx = device_links_read_lock();
__rpm_put_suppliers(dev, false);
@@ -422,6 +419,38 @@ fail:
}
/**
+ * rpm_callback - Run a given runtime PM callback for a given device.
+ * @cb: Runtime PM callback to run.
+ * @dev: Device to run the callback for.
+ */
+static int rpm_callback(int (*cb)(struct device *), struct device *dev)
+{
+ int retval;
+
+ if (dev->power.memalloc_noio) {
+ unsigned int noio_flag;
+
+ /*
+ * Deadlock might be caused if memory allocation with
+ * GFP_KERNEL happens inside runtime_suspend and
+ * runtime_resume callbacks of one block device's
+ * ancestor or the block device itself. Network
+ * device might be thought as part of iSCSI block
+ * device, so network device and its ancestor should
+ * be marked as memalloc_noio too.
+ */
+ noio_flag = memalloc_noio_save();
+ retval = __rpm_callback(cb, dev);
+ memalloc_noio_restore(noio_flag);
+ } else {
+ retval = __rpm_callback(cb, dev);
+ }
+
+ dev->power.runtime_error = retval;
+ return retval != -EACCES ? retval : -EIO;
+}
+
+/**
* rpm_idle - Notify device bus type if the device can be suspended.
* @dev: Device to notify the bus type about.
* @rpmflags: Flag bits.
@@ -459,6 +488,7 @@ static int rpm_idle(struct device *dev, int rpmflags)
/* Act as though RPM_NOWAIT is always set. */
else if (dev->power.idle_notification)
retval = -EINPROGRESS;
+
if (retval)
goto out;
@@ -484,7 +514,17 @@ static int rpm_idle(struct device *dev, int rpmflags)
dev->power.idle_notification = true;
- retval = __rpm_callback(callback, dev);
+ if (dev->power.irq_safe)
+ spin_unlock(&dev->power.lock);
+ else
+ spin_unlock_irq(&dev->power.lock);
+
+ retval = callback(dev);
+
+ if (dev->power.irq_safe)
+ spin_lock(&dev->power.lock);
+ else
+ spin_lock_irq(&dev->power.lock);
dev->power.idle_notification = false;
wake_up_all(&dev->power.wait_queue);
@@ -495,38 +535,6 @@ static int rpm_idle(struct device *dev, int rpmflags)
}
/**
- * rpm_callback - Run a given runtime PM callback for a given device.
- * @cb: Runtime PM callback to run.
- * @dev: Device to run the callback for.
- */
-static int rpm_callback(int (*cb)(struct device *), struct device *dev)
-{
- int retval;
-
- if (dev->power.memalloc_noio) {
- unsigned int noio_flag;
-
- /*
- * Deadlock might be caused if memory allocation with
- * GFP_KERNEL happens inside runtime_suspend and
- * runtime_resume callbacks of one block device's
- * ancestor or the block device itself. Network
- * device might be thought as part of iSCSI block
- * device, so network device and its ancestor should
- * be marked as memalloc_noio too.
- */
- noio_flag = memalloc_noio_save();
- retval = __rpm_callback(cb, dev);
- memalloc_noio_restore(noio_flag);
- } else {
- retval = __rpm_callback(cb, dev);
- }
-
- dev->power.runtime_error = retval;
- return retval != -EACCES ? retval : -EIO;
-}
-
-/**
* rpm_suspend - Carry out runtime suspend of given device.
* @dev: Device to suspend.
* @rpmflags: Flag bits.
@@ -564,12 +572,12 @@ static int rpm_suspend(struct device *dev, int rpmflags)
/* Synchronous suspends are not allowed in the RPM_RESUMING state. */
if (dev->power.runtime_status == RPM_RESUMING && !(rpmflags & RPM_ASYNC))
retval = -EAGAIN;
+
if (retval)
goto out;
/* If the autosuspend_delay time hasn't expired yet, reschedule. */
- if ((rpmflags & RPM_AUTO)
- && dev->power.runtime_status != RPM_SUSPENDING) {
+ if ((rpmflags & RPM_AUTO) && dev->power.runtime_status != RPM_SUSPENDING) {
u64 expires = pm_runtime_autosuspend_expiration(dev);
if (expires != 0) {
@@ -584,7 +592,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
* rest.
*/
if (!(dev->power.timer_expires &&
- dev->power.timer_expires <= expires)) {
+ dev->power.timer_expires <= expires)) {
/*
* We add a slack of 25% to gather wakeups
* without sacrificing the granularity.
@@ -594,9 +602,9 @@ static int rpm_suspend(struct device *dev, int rpmflags)
dev->power.timer_expires = expires;
hrtimer_start_range_ns(&dev->power.suspend_timer,
- ns_to_ktime(expires),
- slack,
- HRTIMER_MODE_ABS);
+ ns_to_ktime(expires),
+ slack,
+ HRTIMER_MODE_ABS);
}
dev->power.timer_autosuspends = 1;
goto out;
@@ -787,8 +795,8 @@ static int rpm_resume(struct device *dev, int rpmflags)
goto out;
}
- if (dev->power.runtime_status == RPM_RESUMING
- || dev->power.runtime_status == RPM_SUSPENDING) {
+ if (dev->power.runtime_status == RPM_RESUMING ||
+ dev->power.runtime_status == RPM_SUSPENDING) {
DEFINE_WAIT(wait);
if (rpmflags & (RPM_ASYNC | RPM_NOWAIT)) {
@@ -815,8 +823,8 @@ static int rpm_resume(struct device *dev, int rpmflags)
for (;;) {
prepare_to_wait(&dev->power.wait_queue, &wait,
TASK_UNINTERRUPTIBLE);
- if (dev->power.runtime_status != RPM_RESUMING
- && dev->power.runtime_status != RPM_SUSPENDING)
+ if (dev->power.runtime_status != RPM_RESUMING &&
+ dev->power.runtime_status != RPM_SUSPENDING)
break;
spin_unlock_irq(&dev->power.lock);
@@ -836,9 +844,9 @@ static int rpm_resume(struct device *dev, int rpmflags)
*/
if (dev->power.no_callbacks && !parent && dev->parent) {
spin_lock_nested(&dev->parent->power.lock, SINGLE_DEPTH_NESTING);
- if (dev->parent->power.disable_depth > 0
- || dev->parent->power.ignore_children
- || dev->parent->power.runtime_status == RPM_ACTIVE) {
+ if (dev->parent->power.disable_depth > 0 ||
+ dev->parent->power.ignore_children ||
+ dev->parent->power.runtime_status == RPM_ACTIVE) {
atomic_inc(&dev->parent->power.child_count);
spin_unlock(&dev->parent->power.lock);
retval = 1;
@@ -867,6 +875,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
parent = dev->parent;
if (dev->power.irq_safe)
goto skip_parent;
+
spin_unlock(&dev->power.lock);
pm_runtime_get_noresume(parent);
@@ -876,8 +885,8 @@ static int rpm_resume(struct device *dev, int rpmflags)
* Resume the parent if it has runtime PM enabled and not been
* set to ignore its children.
*/
- if (!parent->power.disable_depth
- && !parent->power.ignore_children) {
+ if (!parent->power.disable_depth &&
+ !parent->power.ignore_children) {
rpm_resume(parent, 0);
if (parent->power.runtime_status != RPM_ACTIVE)
retval = -EBUSY;
@@ -887,6 +896,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
spin_lock(&dev->power.lock);
if (retval)
goto out;
+
goto repeat;
}
skip_parent:
@@ -1291,9 +1301,9 @@ int __pm_runtime_set_status(struct device *dev, unsigned int status)
* not active, has runtime PM enabled and the
* 'power.ignore_children' flag unset.
*/
- if (!parent->power.disable_depth
- && !parent->power.ignore_children
- && parent->power.runtime_status != RPM_ACTIVE) {
+ if (!parent->power.disable_depth &&
+ !parent->power.ignore_children &&
+ parent->power.runtime_status != RPM_ACTIVE) {
dev_err(dev, "runtime PM trying to activate child device %s but parent (%s) is not active\n",
dev_name(dev),
dev_name(parent));
@@ -1358,9 +1368,9 @@ static void __pm_runtime_barrier(struct device *dev)
dev->power.request_pending = false;
}
- if (dev->power.runtime_status == RPM_SUSPENDING
- || dev->power.runtime_status == RPM_RESUMING
- || dev->power.idle_notification) {
+ if (dev->power.runtime_status == RPM_SUSPENDING ||
+ dev->power.runtime_status == RPM_RESUMING ||
+ dev->power.idle_notification) {
DEFINE_WAIT(wait);
/* Suspend, wake-up or idle notification in progress. */
@@ -1445,8 +1455,8 @@ void __pm_runtime_disable(struct device *dev, bool check_resume)
* means there probably is some I/O to process and disabling runtime PM
* shouldn't prevent the device from processing the I/O.
*/
- if (check_resume && dev->power.request_pending
- && dev->power.request == RPM_REQ_RESUME) {
+ if (check_resume && dev->power.request_pending &&
+ dev->power.request == RPM_REQ_RESUME) {
/*
* Prevent suspends and idle notifications from being carried
* out after we have woken up the device.
@@ -1606,6 +1616,7 @@ void pm_runtime_irq_safe(struct device *dev)
{
if (dev->parent)
pm_runtime_get_sync(dev->parent);
+
spin_lock_irq(&dev->power.lock);
dev->power.irq_safe = 1;
spin_unlock_irq(&dev->power.lock);
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig
index 159bac6c5046..cd4bb642b9de 100644
--- a/drivers/base/regmap/Kconfig
+++ b/drivers/base/regmap/Kconfig
@@ -4,7 +4,7 @@
# subsystems should select the appropriate symbols.
config REGMAP
- default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SOUNDWIRE_MBQ || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM || REGMAP_MDIO)
+ default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SOUNDWIRE_MBQ || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM || REGMAP_MDIO || REGMAP_FSI)
select IRQ_DOMAIN if REGMAP_IRQ
select MDIO_BUS if REGMAP_MDIO
bool
@@ -65,3 +65,7 @@ config REGMAP_I3C
config REGMAP_SPI_AVMM
tristate
depends on SPI
+
+config REGMAP_FSI
+ tristate
+ depends on FSI
diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile
index 11facb32a027..6990de7ca9a9 100644
--- a/drivers/base/regmap/Makefile
+++ b/drivers/base/regmap/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_REGMAP_SCCB) += regmap-sccb.o
obj-$(CONFIG_REGMAP_I3C) += regmap-i3c.o
obj-$(CONFIG_REGMAP_SPI_AVMM) += regmap-spi-avmm.o
obj-$(CONFIG_REGMAP_MDIO) += regmap-mdio.o
+obj-$(CONFIG_REGMAP_FSI) += regmap-fsi.o
diff --git a/drivers/base/regmap/regmap-fsi.c b/drivers/base/regmap/regmap-fsi.c
new file mode 100644
index 000000000000..3d2f3cb31d5e
--- /dev/null
+++ b/drivers/base/regmap/regmap-fsi.c
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Register map access API - FSI support
+//
+// Copyright 2022 IBM Corp
+//
+// Author: Eddie James <eajames@linux.ibm.com>
+
+#include <linux/fsi.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include "internal.h"
+
+static int regmap_fsi32_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+ u32 v;
+ int ret;
+
+ ret = fsi_slave_read(context, reg, &v, sizeof(v));
+ if (ret)
+ return ret;
+
+ *val = v;
+ return 0;
+}
+
+static int regmap_fsi32_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+ u32 v = val;
+
+ return fsi_slave_write(context, reg, &v, sizeof(v));
+}
+
+static const struct regmap_bus regmap_fsi32 = {
+ .reg_write = regmap_fsi32_reg_write,
+ .reg_read = regmap_fsi32_reg_read,
+};
+
+static int regmap_fsi32le_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+ __be32 v;
+ int ret;
+
+ ret = fsi_slave_read(context, reg, &v, sizeof(v));
+ if (ret)
+ return ret;
+
+ *val = be32_to_cpu(v);
+ return 0;
+}
+
+static int regmap_fsi32le_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+ __be32 v = cpu_to_be32(val);
+
+ return fsi_slave_write(context, reg, &v, sizeof(v));
+}
+
+static const struct regmap_bus regmap_fsi32le = {
+ .reg_write = regmap_fsi32le_reg_write,
+ .reg_read = regmap_fsi32le_reg_read,
+};
+
+static int regmap_fsi16_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+ u16 v;
+ int ret;
+
+ ret = fsi_slave_read(context, reg, &v, sizeof(v));
+ if (ret)
+ return ret;
+
+ *val = v;
+ return 0;
+}
+
+static int regmap_fsi16_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+ u16 v;
+
+ if (val > 0xffff)
+ return -EINVAL;
+
+ v = val;
+ return fsi_slave_write(context, reg, &v, sizeof(v));
+}
+
+static const struct regmap_bus regmap_fsi16 = {
+ .reg_write = regmap_fsi16_reg_write,
+ .reg_read = regmap_fsi16_reg_read,
+};
+
+static int regmap_fsi16le_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+ __be16 v;
+ int ret;
+
+ ret = fsi_slave_read(context, reg, &v, sizeof(v));
+ if (ret)
+ return ret;
+
+ *val = be16_to_cpu(v);
+ return 0;
+}
+
+static int regmap_fsi16le_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+ __be16 v;
+
+ if (val > 0xffff)
+ return -EINVAL;
+
+ v = cpu_to_be16(val);
+ return fsi_slave_write(context, reg, &v, sizeof(v));
+}
+
+static const struct regmap_bus regmap_fsi16le = {
+ .reg_write = regmap_fsi16le_reg_write,
+ .reg_read = regmap_fsi16le_reg_read,
+};
+
+static int regmap_fsi8_reg_read(void *context, unsigned int reg, unsigned int *val)
+{
+ u8 v;
+ int ret;
+
+ ret = fsi_slave_read(context, reg, &v, sizeof(v));
+ if (ret)
+ return ret;
+
+ *val = v;
+ return 0;
+}
+
+static int regmap_fsi8_reg_write(void *context, unsigned int reg, unsigned int val)
+{
+ u8 v;
+
+ if (val > 0xff)
+ return -EINVAL;
+
+ v = val;
+ return fsi_slave_write(context, reg, &v, sizeof(v));
+}
+
+static const struct regmap_bus regmap_fsi8 = {
+ .reg_write = regmap_fsi8_reg_write,
+ .reg_read = regmap_fsi8_reg_read,
+};
+
+static const struct regmap_bus *regmap_get_fsi_bus(struct fsi_device *fsi_dev,
+ const struct regmap_config *config)
+{
+ const struct regmap_bus *bus = NULL;
+
+ if (config->reg_bits == 8 || config->reg_bits == 16 || config->reg_bits == 32) {
+ switch (config->val_bits) {
+ case 8:
+ bus = &regmap_fsi8;
+ break;
+ case 16:
+ switch (regmap_get_val_endian(&fsi_dev->dev, NULL, config)) {
+ case REGMAP_ENDIAN_LITTLE:
+#ifdef __LITTLE_ENDIAN
+ case REGMAP_ENDIAN_NATIVE:
+#endif
+ bus = &regmap_fsi16le;
+ break;
+ case REGMAP_ENDIAN_DEFAULT:
+ case REGMAP_ENDIAN_BIG:
+#ifdef __BIG_ENDIAN
+ case REGMAP_ENDIAN_NATIVE:
+#endif
+ bus = &regmap_fsi16;
+ break;
+ default:
+ break;
+ }
+ break;
+ case 32:
+ switch (regmap_get_val_endian(&fsi_dev->dev, NULL, config)) {
+ case REGMAP_ENDIAN_LITTLE:
+#ifdef __LITTLE_ENDIAN
+ case REGMAP_ENDIAN_NATIVE:
+#endif
+ bus = &regmap_fsi32le;
+ break;
+ case REGMAP_ENDIAN_DEFAULT:
+ case REGMAP_ENDIAN_BIG:
+#ifdef __BIG_ENDIAN
+ case REGMAP_ENDIAN_NATIVE:
+#endif
+ bus = &regmap_fsi32;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ }
+
+ return bus ?: ERR_PTR(-EOPNOTSUPP);
+}
+
+struct regmap *__regmap_init_fsi(struct fsi_device *fsi_dev, const struct regmap_config *config,
+ struct lock_class_key *lock_key, const char *lock_name)
+{
+ const struct regmap_bus *bus = regmap_get_fsi_bus(fsi_dev, config);
+
+ if (IS_ERR(bus))
+ return ERR_CAST(bus);
+
+ return __regmap_init(&fsi_dev->dev, bus, fsi_dev->slave, config, lock_key, lock_name);
+}
+EXPORT_SYMBOL_GPL(__regmap_init_fsi);
+
+struct regmap *__devm_regmap_init_fsi(struct fsi_device *fsi_dev,
+ const struct regmap_config *config,
+ struct lock_class_key *lock_key, const char *lock_name)
+{
+ const struct regmap_bus *bus = regmap_get_fsi_bus(fsi_dev, config);
+
+ if (IS_ERR(bus))
+ return ERR_CAST(bus);
+
+ return __devm_regmap_init(&fsi_dev->dev, bus, fsi_dev->slave, config, lock_key, lock_name);
+}
+EXPORT_SYMBOL_GPL(__devm_regmap_init_fsi);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 4ef9488d05cd..a8f185430a07 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -115,12 +115,20 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
*/
for (i = 0; i < d->chip->num_regs; i++) {
if (d->mask_base) {
- 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(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->unmask_base) {
@@ -722,6 +730,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
int i;
int ret = -ENOMEM;
int num_type_reg;
+ int num_regs;
u32 reg;
if (chip->num_regs <= 0)
@@ -796,14 +805,20 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
goto err_alloc;
}
- num_type_reg = chip->type_in_mask ? chip->num_regs : chip->num_type_reg;
- if (num_type_reg) {
- d->type_buf_def = kcalloc(num_type_reg,
+ /*
+ * 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,
sizeof(*d->type_buf_def), GFP_KERNEL);
if (!d->type_buf_def)
goto err_alloc;
- d->type_buf = kcalloc(num_type_reg, sizeof(*d->type_buf),
+ d->type_buf = kcalloc(num_regs, sizeof(*d->type_buf),
GFP_KERNEL);
if (!d->type_buf)
goto err_alloc;
@@ -917,13 +932,23 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
d->mask_buf[i] = d->mask_buf_def[i];
if (d->mask_base) {
- 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(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;
+ }
}
}
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index c6d6d53e8cd3..d12d669157f2 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -3486,6 +3486,19 @@ int regmap_get_reg_stride(struct regmap *map)
}
EXPORT_SYMBOL_GPL(regmap_get_reg_stride);
+/**
+ * regmap_might_sleep() - Returns whether a regmap access might sleep.
+ *
+ * @map: Register map to operate on.
+ *
+ * Returns true if an access to the register might sleep, else false.
+ */
+bool regmap_might_sleep(struct regmap *map)
+{
+ return map->can_sleep;
+}
+EXPORT_SYMBOL_GPL(regmap_might_sleep);
+
int regmap_parse_val(struct regmap *map, const void *buf,
unsigned int *val)
{
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig
index a41145d52de9..a2184b428493 100644
--- a/drivers/block/Kconfig
+++ b/drivers/block/Kconfig
@@ -285,49 +285,6 @@ config BLK_DEV_RAM_SIZE
The default value is 4096 kilobytes. Only change this if you know
what you are doing.
-config CDROM_PKTCDVD
- tristate "Packet writing on CD/DVD media (DEPRECATED)"
- depends on !UML
- depends on SCSI
- select CDROM
- help
- Note: This driver is deprecated and will be removed from the
- kernel in the near future!
-
- If you have a CDROM/DVD drive that supports packet writing, say
- Y to include support. It should work with any MMC/Mt Fuji
- compliant ATAPI or SCSI drive, which is just about any newer
- DVD/CD writer.
-
- Currently only writing to CD-RW, DVD-RW, DVD+RW and DVDRAM discs
- is possible.
- DVD-RW disks must be in restricted overwrite mode.
-
- See the file <file:Documentation/cdrom/packet-writing.rst>
- for further information on the use of this driver.
-
- To compile this driver as a module, choose M here: the
- module will be called pktcdvd.
-
-config CDROM_PKTCDVD_BUFFERS
- int "Free buffers for data gathering"
- depends on CDROM_PKTCDVD
- default "8"
- help
- This controls the maximum number of active concurrent packets. More
- concurrent packets can increase write performance, but also require
- more memory. Each concurrent packet will require approximately 64Kb
- of non-swappable kernel memory, memory which will be allocated when
- a disc is opened for writing.
-
-config CDROM_PKTCDVD_WCACHE
- bool "Enable write caching"
- depends on CDROM_PKTCDVD
- help
- If enabled, write caching will be set for the CD-R/W device. For now
- this option is dangerous unless the CD-RW media is known good, as we
- don't do deferred write error handling yet.
-
config ATA_OVER_ETH
tristate "ATA over Ethernet support"
depends on NET
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 101612cba303..962ee65d8ca3 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -20,7 +20,6 @@ obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o
obj-$(CONFIG_N64CART) += n64cart.o
obj-$(CONFIG_BLK_DEV_RAM) += brd.o
obj-$(CONFIG_BLK_DEV_LOOP) += loop.o
-obj-$(CONFIG_CDROM_PKTCDVD) += pktcdvd.o
obj-$(CONFIG_SUNVDC) += sunvdc.o
obj-$(CONFIG_BLK_DEV_NBD) += nbd.o
diff --git a/drivers/block/drbd/Kconfig b/drivers/block/drbd/Kconfig
index cbacddc55a1d..6fb4e38fca88 100644
--- a/drivers/block/drbd/Kconfig
+++ b/drivers/block/drbd/Kconfig
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0
+# SPDX-License-Identifier: GPL-2.0-only
#
# DRBD device driver configuration
#
diff --git a/drivers/block/drbd/Makefile b/drivers/block/drbd/Makefile
index 8bd534697d1b..c93e462130ff 100644
--- a/drivers/block/drbd/Makefile
+++ b/drivers/block/drbd/Makefile
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0
+# SPDX-License-Identifier: GPL-2.0-only
drbd-y := drbd_bitmap.o drbd_proc.o
drbd-y += drbd_worker.o drbd_receiver.o drbd_req.o drbd_actlog.o
drbd-y += drbd_main.o drbd_strings.o drbd_nl.o
diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c
index e27478ae579c..429255876800 100644
--- a/drivers/block/drbd/drbd_actlog.c
+++ b/drivers/block/drbd/drbd_actlog.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-License-Identifier: GPL-2.0-only
/*
drbd_actlog.c
@@ -868,9 +868,9 @@ int __drbd_change_sync(struct drbd_device *device, sector_t sector, int size,
nr_sectors = get_capacity(device->vdisk);
esector = sector + (size >> 9) - 1;
- if (!expect(sector < nr_sectors))
+ if (!expect(device, sector < nr_sectors))
goto out;
- if (!expect(esector < nr_sectors))
+ if (!expect(device, esector < nr_sectors))
esector = nr_sectors - 1;
lbnr = BM_SECT_TO_BIT(nr_sectors-1);
@@ -1143,7 +1143,7 @@ void drbd_rs_complete_io(struct drbd_device *device, sector_t sector)
bm_ext = e ? lc_entry(e, struct bm_extent, lce) : NULL;
if (!bm_ext) {
spin_unlock_irqrestore(&device->al_lock, flags);
- if (__ratelimit(&drbd_ratelimit_state))
+ if (drbd_ratelimit())
drbd_err(device, "drbd_rs_complete_io() called, but extent not found\n");
return;
}
diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index 7d9db33363de..289876ffbc31 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-License-Identifier: GPL-2.0-only
/*
drbd_bitmap.c
@@ -113,7 +113,7 @@ struct drbd_bitmap {
static void __bm_print_lock_info(struct drbd_device *device, const char *func)
{
struct drbd_bitmap *b = device->bitmap;
- if (!__ratelimit(&drbd_ratelimit_state))
+ if (!drbd_ratelimit())
return;
drbd_err(device, "FIXME %s[%d] in %s, bitmap locked for '%s' by %s[%d]\n",
current->comm, task_pid_nr(current),
@@ -448,7 +448,7 @@ int drbd_bm_init(struct drbd_device *device)
sector_t drbd_bm_capacity(struct drbd_device *device)
{
- if (!expect(device->bitmap))
+ if (!expect(device, device->bitmap))
return 0;
return device->bitmap->bm_dev_capacity;
}
@@ -457,7 +457,7 @@ sector_t drbd_bm_capacity(struct drbd_device *device)
*/
void drbd_bm_cleanup(struct drbd_device *device)
{
- if (!expect(device->bitmap))
+ if (!expect(device, device->bitmap))
return;
bm_free_pages(device->bitmap->bm_pages, device->bitmap->bm_number_of_pages);
bm_vk_free(device->bitmap->bm_pages);
@@ -636,7 +636,7 @@ int drbd_bm_resize(struct drbd_device *device, sector_t capacity, int set_new_bi
int err = 0;
bool growing;
- if (!expect(b))
+ if (!expect(device, b))
return -ENOMEM;
drbd_bm_lock(device, "resize", BM_LOCKED_MASK);
@@ -757,9 +757,9 @@ unsigned long _drbd_bm_total_weight(struct drbd_device *device)
unsigned long s;
unsigned long flags;
- if (!expect(b))
+ if (!expect(device, b))
return 0;
- if (!expect(b->bm_pages))
+ if (!expect(device, b->bm_pages))
return 0;
spin_lock_irqsave(&b->bm_lock, flags);
@@ -783,9 +783,9 @@ unsigned long drbd_bm_total_weight(struct drbd_device *device)
size_t drbd_bm_words(struct drbd_device *device)
{
struct drbd_bitmap *b = device->bitmap;
- if (!expect(b))
+ if (!expect(device, b))
return 0;
- if (!expect(b->bm_pages))
+ if (!expect(device, b->bm_pages))
return 0;
return b->bm_words;
@@ -794,7 +794,7 @@ size_t drbd_bm_words(struct drbd_device *device)
unsigned long drbd_bm_bits(struct drbd_device *device)
{
struct drbd_bitmap *b = device->bitmap;
- if (!expect(b))
+ if (!expect(device, b))
return 0;
return b->bm_bits;
@@ -816,9 +816,9 @@ void drbd_bm_merge_lel(struct drbd_device *device, size_t offset, size_t number,
end = offset + number;
- if (!expect(b))
+ if (!expect(device, b))
return;
- if (!expect(b->bm_pages))
+ if (!expect(device, b->bm_pages))
return;
if (number == 0)
return;
@@ -863,9 +863,9 @@ void drbd_bm_get_lel(struct drbd_device *device, size_t offset, size_t number,
end = offset + number;
- if (!expect(b))
+ if (!expect(device, b))
return;
- if (!expect(b->bm_pages))
+ if (!expect(device, b->bm_pages))
return;
spin_lock_irq(&b->bm_lock);
@@ -894,9 +894,9 @@ void drbd_bm_get_lel(struct drbd_device *device, size_t offset, size_t number,
void drbd_bm_set_all(struct drbd_device *device)
{
struct drbd_bitmap *b = device->bitmap;
- if (!expect(b))
+ if (!expect(device, b))
return;
- if (!expect(b->bm_pages))
+ if (!expect(device, b->bm_pages))
return;
spin_lock_irq(&b->bm_lock);
@@ -910,9 +910,9 @@ void drbd_bm_set_all(struct drbd_device *device)
void drbd_bm_clear_all(struct drbd_device *device)
{
struct drbd_bitmap *b = device->bitmap;
- if (!expect(b))
+ if (!expect(device, b))
return;
- if (!expect(b->bm_pages))
+ if (!expect(device, b->bm_pages))
return;
spin_lock_irq(&b->bm_lock);
@@ -952,7 +952,7 @@ static void drbd_bm_endio(struct bio *bio)
bm_set_page_io_err(b->bm_pages[idx]);
/* Not identical to on disk version of it.
* Is BM_PAGE_IO_ERROR enough? */
- if (__ratelimit(&drbd_ratelimit_state))
+ if (drbd_ratelimit())
drbd_err(device, "IO ERROR %d on bitmap page idx %u\n",
bio->bi_status, idx);
} else {
@@ -1013,7 +1013,7 @@ static void bm_page_io_async(struct drbd_bm_aio_ctx *ctx, int page_nr) __must_ho
else
len = PAGE_SIZE;
} else {
- if (__ratelimit(&drbd_ratelimit_state)) {
+ if (drbd_ratelimit()) {
drbd_err(device, "Invalid offset during on-disk bitmap access: "
"page idx %u, sector %llu\n", page_nr, on_disk_sector);
}
@@ -1332,9 +1332,9 @@ static unsigned long bm_find_next(struct drbd_device *device,
struct drbd_bitmap *b = device->bitmap;
unsigned long i = DRBD_END_OF_BITMAP;
- if (!expect(b))
+ if (!expect(device, b))
return i;
- if (!expect(b->bm_pages))
+ if (!expect(device, b->bm_pages))
return i;
spin_lock_irq(&b->bm_lock);
@@ -1436,9 +1436,9 @@ static int bm_change_bits_to(struct drbd_device *device, const unsigned long s,
struct drbd_bitmap *b = device->bitmap;
int c = 0;
- if (!expect(b))
+ if (!expect(device, b))
return 1;
- if (!expect(b->bm_pages))
+ if (!expect(device, b->bm_pages))
return 0;
spin_lock_irqsave(&b->bm_lock, flags);
@@ -1582,9 +1582,9 @@ int drbd_bm_test_bit(struct drbd_device *device, const unsigned long bitnr)
unsigned long *p_addr;
int i;
- if (!expect(b))
+ if (!expect(device, b))
return 0;
- if (!expect(b->bm_pages))
+ if (!expect(device, b->bm_pages))
return 0;
spin_lock_irqsave(&b->bm_lock, flags);
@@ -1619,9 +1619,9 @@ int drbd_bm_count_bits(struct drbd_device *device, const unsigned long s, const
* robust in case we screwed up elsewhere, in that case pretend there
* was one dirty bit in the requested area, so we won't try to do a
* local read there (no bitmap probably implies no disk) */
- if (!expect(b))
+ if (!expect(device, b))
return 1;
- if (!expect(b->bm_pages))
+ if (!expect(device, b->bm_pages))
return 1;
spin_lock_irqsave(&b->bm_lock, flags);
@@ -1635,7 +1635,7 @@ int drbd_bm_count_bits(struct drbd_device *device, const unsigned long s, const
bm_unmap(p_addr);
p_addr = bm_map_pidx(b, idx);
}
- if (expect(bitnr < b->bm_bits))
+ if (expect(device, bitnr < b->bm_bits))
c += (0 != test_bit_le(bitnr - (page_nr << (PAGE_SHIFT+3)), p_addr));
else
drbd_err(device, "bitnr=%lu bm_bits=%lu\n", bitnr, b->bm_bits);
@@ -1668,9 +1668,9 @@ int drbd_bm_e_weight(struct drbd_device *device, unsigned long enr)
unsigned long flags;
unsigned long *p_addr, *bm;
- if (!expect(b))
+ if (!expect(device, b))
return 0;
- if (!expect(b->bm_pages))
+ if (!expect(device, b->bm_pages))
return 0;
spin_lock_irqsave(&b->bm_lock, flags);
diff --git a/drivers/block/drbd/drbd_debugfs.c b/drivers/block/drbd/drbd_debugfs.c
index b3b9cd5628fd..a72c096aa5b1 100644
--- a/drivers/block/drbd/drbd_debugfs.c
+++ b/drivers/block/drbd/drbd_debugfs.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
#define pr_fmt(fmt) "drbd debugfs: " fmt
#include <linux/kernel.h>
#include <linux/module.h>
diff --git a/drivers/block/drbd/drbd_debugfs.h b/drivers/block/drbd/drbd_debugfs.h
index 58e31cef0844..ee3d66eb40c6 100644
--- a/drivers/block/drbd/drbd_debugfs.h
+++ b/drivers/block/drbd/drbd_debugfs.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0-only */
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/debugfs.h>
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h
index 4d661282ff41..ae713338aa46 100644
--- a/drivers/block/drbd/drbd_int.h
+++ b/drivers/block/drbd/drbd_int.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
drbd_int.h
@@ -37,6 +37,7 @@
#include "drbd_strings.h"
#include "drbd_state.h"
#include "drbd_protocol.h"
+#include "drbd_polymorph_printk.h"
#ifdef __CHECKER__
# define __protected_by(x) __attribute__((require_context(x,1,999,"rdwr")))
@@ -75,71 +76,6 @@ extern int drbd_proc_details;
struct drbd_device;
struct drbd_connection;
-#define __drbd_printk_device(level, device, fmt, args...) \
- dev_printk(level, disk_to_dev((device)->vdisk), fmt, ## args)
-#define __drbd_printk_peer_device(level, peer_device, fmt, args...) \
- dev_printk(level, disk_to_dev((peer_device)->device->vdisk), fmt, ## args)
-#define __drbd_printk_resource(level, resource, fmt, args...) \
- printk(level "drbd %s: " fmt, (resource)->name, ## args)
-#define __drbd_printk_connection(level, connection, fmt, args...) \
- printk(level "drbd %s: " fmt, (connection)->resource->name, ## args)
-
-void drbd_printk_with_wrong_object_type(void);
-
-#define __drbd_printk_if_same_type(obj, type, func, level, fmt, args...) \
- (__builtin_types_compatible_p(typeof(obj), type) || \
- __builtin_types_compatible_p(typeof(obj), const type)), \
- func(level, (const type)(obj), fmt, ## args)
-
-#define drbd_printk(level, obj, fmt, args...) \
- __builtin_choose_expr( \
- __drbd_printk_if_same_type(obj, struct drbd_device *, \
- __drbd_printk_device, level, fmt, ## args), \
- __builtin_choose_expr( \
- __drbd_printk_if_same_type(obj, struct drbd_resource *, \
- __drbd_printk_resource, level, fmt, ## args), \
- __builtin_choose_expr( \
- __drbd_printk_if_same_type(obj, struct drbd_connection *, \
- __drbd_printk_connection, level, fmt, ## args), \
- __builtin_choose_expr( \
- __drbd_printk_if_same_type(obj, struct drbd_peer_device *, \
- __drbd_printk_peer_device, level, fmt, ## args), \
- drbd_printk_with_wrong_object_type()))))
-
-#define drbd_dbg(obj, fmt, args...) \
- drbd_printk(KERN_DEBUG, obj, fmt, ## args)
-#define drbd_alert(obj, fmt, args...) \
- drbd_printk(KERN_ALERT, obj, fmt, ## args)
-#define drbd_err(obj, fmt, args...) \
- drbd_printk(KERN_ERR, obj, fmt, ## args)
-#define drbd_warn(obj, fmt, args...) \
- drbd_printk(KERN_WARNING, obj, fmt, ## args)
-#define drbd_info(obj, fmt, args...) \
- drbd_printk(KERN_INFO, obj, fmt, ## args)
-#define drbd_emerg(obj, fmt, args...) \
- drbd_printk(KERN_EMERG, obj, fmt, ## args)
-
-#define dynamic_drbd_dbg(device, fmt, args...) \
- dynamic_dev_dbg(disk_to_dev(device->vdisk), fmt, ## args)
-
-#define D_ASSERT(device, exp) do { \
- if (!(exp)) \
- drbd_err(device, "ASSERT( " #exp " ) in %s:%d\n", __FILE__, __LINE__); \
- } while (0)
-
-/**
- * expect - Make an assertion
- *
- * Unlike the assert macro, this macro returns a boolean result.
- */
-#define expect(exp) ({ \
- bool _bool = (exp); \
- if (!_bool) \
- drbd_err(device, "ASSERTION %s FAILED in %s\n", \
- #exp, __func__); \
- _bool; \
- })
-
/* Defines to control fault insertion */
enum {
DRBD_FAULT_MD_WR = 0, /* meta data write */
@@ -395,6 +331,7 @@ struct drbd_peer_request {
struct drbd_peer_device *peer_device;
struct drbd_epoch *epoch; /* for writes */
struct page *pages;
+ blk_opf_t opf;
atomic_t pending_bios;
struct drbd_interval i;
/* see comments on ee flag bits below */
@@ -406,6 +343,10 @@ struct drbd_peer_request {
};
};
+/* Equivalent to bio_op and req_op. */
+#define peer_req_op(peer_req) \
+ ((peer_req)->opf & REQ_OP_MASK)
+
/* ee flag bits.
* While corresponding bios are in flight, the only modification will be
* set_bit WAS_ERROR, which has to be atomic.
@@ -1545,8 +1486,7 @@ extern void drbd_send_acks_wf(struct work_struct *ws);
extern bool drbd_rs_c_min_rate_throttle(struct drbd_device *device);
extern bool drbd_rs_should_slow_down(struct drbd_device *device, sector_t sector,
bool throttle_if_app_is_waiting);
-extern int drbd_submit_peer_request(struct drbd_device *,
- struct drbd_peer_request *, blk_opf_t, int);
+extern int drbd_submit_peer_request(struct drbd_peer_request *peer_req);
extern int drbd_free_peer_reqs(struct drbd_device *, struct list_head *);
extern struct drbd_peer_request *drbd_alloc_peer_req(struct drbd_peer_device *, u64,
sector_t, unsigned int,
@@ -1718,7 +1658,7 @@ static inline void __drbd_chk_io_error_(struct drbd_device *device,
switch (ep) {
case EP_PASS_ON: /* FIXME would this be better named "Ignore"? */
if (df == DRBD_READ_ERROR || df == DRBD_WRITE_ERROR) {
- if (__ratelimit(&drbd_ratelimit_state))
+ if (drbd_ratelimit())
drbd_err(device, "Local IO failed in %s.\n", where);
if (device->state.disk > D_INCONSISTENT)
_drbd_set_state(_NS(device, disk, D_INCONSISTENT), CS_HARD, NULL);
diff --git a/drivers/block/drbd/drbd_interval.c b/drivers/block/drbd/drbd_interval.c
index f07b4378388b..5024ffd6143d 100644
--- a/drivers/block/drbd/drbd_interval.c
+++ b/drivers/block/drbd/drbd_interval.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
#include <asm/bug.h>
#include <linux/rbtree_augmented.h>
#include "drbd_interval.h"
diff --git a/drivers/block/drbd/drbd_interval.h b/drivers/block/drbd/drbd_interval.h
index b8c2dee5edc8..366489b72fe9 100644
--- a/drivers/block/drbd/drbd_interval.h
+++ b/drivers/block/drbd/drbd_interval.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __DRBD_INTERVAL_H
#define __DRBD_INTERVAL_H
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 8532b839a343..2f16e1bfb6e7 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-License-Identifier: GPL-2.0-only
/*
drbd.c
@@ -1259,7 +1259,7 @@ static int _drbd_send_bitmap(struct drbd_device *device)
struct bm_xfer_ctx c;
int err;
- if (!expect(device->bitmap))
+ if (!expect(device, device->bitmap))
return false;
if (get_ldev(device)) {
@@ -1816,7 +1816,7 @@ int drbd_send(struct drbd_connection *connection, struct socket *sock,
/* THINK if (signal_pending) return ... ? */
- iov_iter_kvec(&msg.msg_iter, WRITE, &iov, 1, size);
+ iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, &iov, 1, size);
if (sock == connection->data.socket) {
rcu_read_lock();
@@ -2217,7 +2217,8 @@ void drbd_destroy_device(struct kref *kref)
kref_put(&peer_device->connection->kref, drbd_destroy_connection);
kfree(peer_device);
}
- memset(device, 0xfd, sizeof(*device));
+ if (device->submit.wq)
+ destroy_workqueue(device->submit.wq);
kfree(device);
kref_put(&resource->kref, drbd_destroy_resource);
}
@@ -2249,9 +2250,9 @@ static void do_retry(struct work_struct *ws)
bool expected;
expected =
- expect(atomic_read(&req->completion_ref) == 0) &&
- expect(req->rq_state & RQ_POSTPONED) &&
- expect((req->rq_state & RQ_LOCAL_PENDING) == 0 ||
+ expect(device, atomic_read(&req->completion_ref) == 0) &&
+ expect(device, req->rq_state & RQ_POSTPONED) &&
+ expect(device, (req->rq_state & RQ_LOCAL_PENDING) == 0 ||
(req->rq_state & RQ_LOCAL_ABORTED) != 0);
if (!expected)
@@ -2309,7 +2310,6 @@ void drbd_destroy_resource(struct kref *kref)
idr_destroy(&resource->devices);
free_cpumask_var(resource->cpu_mask);
kfree(resource->name);
- memset(resource, 0xf2, sizeof(*resource));
kfree(resource);
}
@@ -2650,7 +2650,6 @@ void drbd_destroy_connection(struct kref *kref)
drbd_free_socket(&connection->data);
kfree(connection->int_dig_in);
kfree(connection->int_dig_vv);
- memset(connection, 0xfc, sizeof(*connection));
kfree(connection);
kref_put(&resource->kref, drbd_destroy_resource);
}
@@ -2774,7 +2773,7 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
err = add_disk(disk);
if (err)
- goto out_idr_remove_from_resource;
+ goto out_destroy_workqueue;
/* inherit the connection state */
device->state.conn = first_connection(resource)->cstate;
@@ -2788,6 +2787,8 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
drbd_debugfs_device_add(device);
return NO_ERROR;
+out_destroy_workqueue:
+ destroy_workqueue(device->submit.wq);
out_idr_remove_from_resource:
for_each_connection_safe(connection, n, resource) {
peer_device = idr_remove(&connection->peer_devices, vnr);
@@ -3766,7 +3767,7 @@ _drbd_insert_fault(struct drbd_device *device, unsigned int type)
if (ret) {
drbd_fault_count++;
- if (__ratelimit(&drbd_ratelimit_state))
+ if (drbd_ratelimit())
drbd_warn(device, "***Simulating %s failure\n",
_drbd_fault_str(type));
}
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 864c98e74875..60757ac31701 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-License-Identifier: GPL-2.0-only
/*
drbd_nl.c
@@ -1210,6 +1210,7 @@ static void decide_on_discard_support(struct drbd_device *device,
struct drbd_connection *connection =
first_peer_device(device)->connection;
struct request_queue *q = device->rq_queue;
+ unsigned int max_discard_sectors;
if (bdev && !bdev_max_discard_sectors(bdev->backing_bdev))
goto not_supported;
@@ -1230,15 +1231,14 @@ static void decide_on_discard_support(struct drbd_device *device,
* topology on all peers.
*/
blk_queue_discard_granularity(q, 512);
- q->limits.max_discard_sectors = drbd_max_discard_sectors(connection);
- q->limits.max_write_zeroes_sectors =
- drbd_max_discard_sectors(connection);
+ max_discard_sectors = drbd_max_discard_sectors(connection);
+ blk_queue_max_discard_sectors(q, max_discard_sectors);
+ blk_queue_max_write_zeroes_sectors(q, max_discard_sectors);
return;
not_supported:
blk_queue_discard_granularity(q, 0);
- q->limits.max_discard_sectors = 0;
- q->limits.max_write_zeroes_sectors = 0;
+ blk_queue_max_discard_sectors(q, 0);
}
static void fixup_write_zeroes(struct drbd_device *device, struct request_queue *q)
@@ -1256,6 +1256,18 @@ static void fixup_write_zeroes(struct drbd_device *device, struct request_queue
q->limits.max_write_zeroes_sectors = 0;
}
+static void fixup_discard_support(struct drbd_device *device, struct request_queue *q)
+{
+ unsigned int max_discard = device->rq_queue->limits.max_discard_sectors;
+ unsigned int discard_granularity =
+ device->rq_queue->limits.discard_granularity >> SECTOR_SHIFT;
+
+ if (discard_granularity > max_discard) {
+ blk_queue_discard_granularity(q, 0);
+ blk_queue_max_discard_sectors(q, 0);
+ }
+}
+
static void drbd_setup_queue_param(struct drbd_device *device, struct drbd_backing_dev *bdev,
unsigned int max_bio_size, struct o_qlim *o)
{
@@ -1288,6 +1300,7 @@ static void drbd_setup_queue_param(struct drbd_device *device, struct drbd_backi
disk_update_readahead(device->vdisk);
}
fixup_write_zeroes(device, q);
+ fixup_discard_support(device, q);
}
void drbd_reconsider_queue_parameters(struct drbd_device *device, struct drbd_backing_dev *bdev, struct o_qlim *o)
@@ -1530,7 +1543,7 @@ int drbd_adm_disk_opts(struct sk_buff *skb, struct genl_info *info)
goto fail_unlock;
}
- if (!expect(new_disk_conf->resync_rate >= 1))
+ if (!expect(device, new_disk_conf->resync_rate >= 1))
new_disk_conf->resync_rate = 1;
sanitize_disk_conf(device, new_disk_conf, device->ldev);
diff --git a/drivers/block/drbd/drbd_nla.c b/drivers/block/drbd/drbd_nla.c
index 6a09b0b98018..df0d241d3f6a 100644
--- a/drivers/block/drbd/drbd_nla.c
+++ b/drivers/block/drbd/drbd_nla.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0-only
#include <linux/kernel.h>
#include <net/netlink.h>
#include <linux/drbd_genl_api.h>
diff --git a/drivers/block/drbd/drbd_nla.h b/drivers/block/drbd/drbd_nla.h
index f5eaffb6474e..d3555df0d353 100644
--- a/drivers/block/drbd/drbd_nla.h
+++ b/drivers/block/drbd/drbd_nla.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __DRBD_NLA_H
#define __DRBD_NLA_H
diff --git a/drivers/block/drbd/drbd_polymorph_printk.h b/drivers/block/drbd/drbd_polymorph_printk.h
new file mode 100644
index 000000000000..8e0082d139ba
--- /dev/null
+++ b/drivers/block/drbd/drbd_polymorph_printk.h
@@ -0,0 +1,141 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef DRBD_POLYMORPH_PRINTK_H
+#define DRBD_POLYMORPH_PRINTK_H
+
+#if !defined(CONFIG_DYNAMIC_DEBUG)
+#undef DEFINE_DYNAMIC_DEBUG_METADATA
+#undef __dynamic_pr_debug
+#undef DYNAMIC_DEBUG_BRANCH
+#define DEFINE_DYNAMIC_DEBUG_METADATA(D, F) const char *D = F; ((void)D)
+#define __dynamic_pr_debug(D, F, args...) do { (void)(D); if (0) printk(F, ## args); } while (0)
+#define DYNAMIC_DEBUG_BRANCH(D) false
+#endif
+
+
+#define __drbd_printk_drbd_device_prep(device) \
+ const struct drbd_device *__d = (device); \
+ const struct drbd_resource *__r = __d->resource
+#define __drbd_printk_drbd_device_fmt(fmt) "drbd %s/%u drbd%u: " fmt
+#define __drbd_printk_drbd_device_args() __r->name, __d->vnr, __d->minor
+#define __drbd_printk_drbd_device_unprep()
+
+#define __drbd_printk_drbd_peer_device_prep(peer_device) \
+ const struct drbd_device *__d; \
+ const struct drbd_resource *__r; \
+ __d = (peer_device)->device; \
+ __r = __d->resource
+#define __drbd_printk_drbd_peer_device_fmt(fmt) \
+ "drbd %s/%u drbd%u: " fmt
+#define __drbd_printk_drbd_peer_device_args() \
+ __r->name, __d->vnr, __d->minor
+#define __drbd_printk_drbd_peer_device_unprep()
+
+#define __drbd_printk_drbd_resource_prep(resource) \
+ const struct drbd_resource *__r = resource
+#define __drbd_printk_drbd_resource_fmt(fmt) "drbd %s: " fmt
+#define __drbd_printk_drbd_resource_args() __r->name
+#define __drbd_printk_drbd_resource_unprep(resource)
+
+#define __drbd_printk_drbd_connection_prep(connection) \
+ const struct drbd_connection *__c = (connection); \
+ const struct drbd_resource *__r = __c->resource
+#define __drbd_printk_drbd_connection_fmt(fmt) \
+ "drbd %s: " fmt
+#define __drbd_printk_drbd_connection_args() \
+ __r->name
+#define __drbd_printk_drbd_connection_unprep()
+
+void drbd_printk_with_wrong_object_type(void);
+void drbd_dyn_dbg_with_wrong_object_type(void);
+
+#define __drbd_printk_choose_cond(obj, struct_name) \
+ (__builtin_types_compatible_p(typeof(obj), struct struct_name *) || \
+ __builtin_types_compatible_p(typeof(obj), const struct struct_name *))
+#define __drbd_printk_if_same_type(obj, struct_name, level, fmt, args...) \
+ __drbd_printk_choose_cond(obj, struct_name), \
+({ \
+ __drbd_printk_ ## struct_name ## _prep((const struct struct_name *)(obj)); \
+ printk(level __drbd_printk_ ## struct_name ## _fmt(fmt), \
+ __drbd_printk_ ## struct_name ## _args(), ## args); \
+ __drbd_printk_ ## struct_name ## _unprep(); \
+})
+
+#define drbd_printk(level, obj, fmt, args...) \
+ __builtin_choose_expr( \
+ __drbd_printk_if_same_type(obj, drbd_device, level, fmt, ## args), \
+ __builtin_choose_expr( \
+ __drbd_printk_if_same_type(obj, drbd_resource, level, fmt, ## args), \
+ __builtin_choose_expr( \
+ __drbd_printk_if_same_type(obj, drbd_connection, level, fmt, ## args), \
+ __builtin_choose_expr( \
+ __drbd_printk_if_same_type(obj, drbd_peer_device, level, fmt, ## args), \
+ drbd_printk_with_wrong_object_type()))))
+
+#define __drbd_dyn_dbg_if_same_type(obj, struct_name, fmt, args...) \
+ __drbd_printk_choose_cond(obj, struct_name), \
+({ \
+ DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
+ if (DYNAMIC_DEBUG_BRANCH(descriptor)) { \
+ __drbd_printk_ ## struct_name ## _prep((const struct struct_name *)(obj)); \
+ __dynamic_pr_debug(&descriptor, __drbd_printk_ ## struct_name ## _fmt(fmt), \
+ __drbd_printk_ ## struct_name ## _args(), ## args); \
+ __drbd_printk_ ## struct_name ## _unprep(); \
+ } \
+})
+
+#define dynamic_drbd_dbg(obj, fmt, args...) \
+ __builtin_choose_expr( \
+ __drbd_dyn_dbg_if_same_type(obj, drbd_device, fmt, ## args), \
+ __builtin_choose_expr( \
+ __drbd_dyn_dbg_if_same_type(obj, drbd_resource, fmt, ## args), \
+ __builtin_choose_expr( \
+ __drbd_dyn_dbg_if_same_type(obj, drbd_connection, fmt, ## args), \
+ __builtin_choose_expr( \
+ __drbd_dyn_dbg_if_same_type(obj, drbd_peer_device, fmt, ## args), \
+ drbd_dyn_dbg_with_wrong_object_type()))))
+
+#define drbd_emerg(device, fmt, args...) \
+ drbd_printk(KERN_EMERG, device, fmt, ## args)
+#define drbd_alert(device, fmt, args...) \
+ drbd_printk(KERN_ALERT, device, fmt, ## args)
+#define drbd_crit(device, fmt, args...) \
+ drbd_printk(KERN_CRIT, device, fmt, ## args)
+#define drbd_err(device, fmt, args...) \
+ drbd_printk(KERN_ERR, device, fmt, ## args)
+#define drbd_warn(device, fmt, args...) \
+ drbd_printk(KERN_WARNING, device, fmt, ## args)
+#define drbd_notice(device, fmt, args...) \
+ drbd_printk(KERN_NOTICE, device, fmt, ## args)
+#define drbd_info(device, fmt, args...) \
+ drbd_printk(KERN_INFO, device, fmt, ## args)
+
+
+#define drbd_ratelimit() \
+({ \
+ static DEFINE_RATELIMIT_STATE(_rs, \
+ DEFAULT_RATELIMIT_INTERVAL, \
+ DEFAULT_RATELIMIT_BURST); \
+ __ratelimit(&_rs); \
+})
+
+#define D_ASSERT(x, exp) \
+ do { \
+ if (!(exp)) \
+ drbd_err(x, "ASSERTION %s FAILED in %s\n", \
+ #exp, __func__); \
+ } while (0)
+
+/**
+ * expect - Make an assertion
+ *
+ * Unlike the assert macro, this macro returns a boolean result.
+ */
+#define expect(x, exp) ({ \
+ bool _bool = (exp); \
+ if (!_bool && drbd_ratelimit()) \
+ drbd_err(x, "ASSERTION %s FAILED in %s\n", \
+ #exp, __func__); \
+ _bool; \
+ })
+
+#endif
diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c
index 3c0193de2498..2227fb0db1ce 100644
--- a/drivers/block/drbd/drbd_proc.c
+++ b/drivers/block/drbd/drbd_proc.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-License-Identifier: GPL-2.0-only
/*
drbd_proc.c
diff --git a/drivers/block/drbd/drbd_protocol.h b/drivers/block/drbd/drbd_protocol.h
index a882b65ab5d2..56bbca9d7700 100644
--- a/drivers/block/drbd/drbd_protocol.h
+++ b/drivers/block/drbd/drbd_protocol.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __DRBD_PROTOCOL_H
#define __DRBD_PROTOCOL_H
diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c
index ee69d50ba4fd..0e58a3187345 100644
--- a/drivers/block/drbd/drbd_receiver.c
+++ b/drivers/block/drbd/drbd_receiver.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-License-Identifier: GPL-2.0-only
/*
drbd_receiver.c
@@ -413,7 +413,7 @@ void __drbd_free_peer_req(struct drbd_device *device, struct drbd_peer_request *
drbd_free_pages(device, peer_req->pages, is_net);
D_ASSERT(device, atomic_read(&peer_req->pending_bios) == 0);
D_ASSERT(device, drbd_interval_empty(&peer_req->i));
- if (!expect(!(peer_req->flags & EE_CALL_AL_COMPLETE_IO))) {
+ if (!expect(device, !(peer_req->flags & EE_CALL_AL_COMPLETE_IO))) {
peer_req->flags &= ~EE_CALL_AL_COMPLETE_IO;
drbd_al_complete_io(device, &peer_req->i);
}
@@ -507,7 +507,7 @@ static int drbd_recv_short(struct socket *sock, void *buf, size_t size, int flag
struct msghdr msg = {
.msg_flags = (flags ? flags : MSG_WAITALL | MSG_NOSIGNAL)
};
- iov_iter_kvec(&msg.msg_iter, READ, &iov, 1, size);
+ iov_iter_kvec(&msg.msg_iter, ITER_DEST, &iov, 1, size);
return sock_recvmsg(sock, &msg, msg.msg_flags);
}
@@ -781,7 +781,7 @@ static struct socket *drbd_wait_for_connect(struct drbd_connection *connection,
timeo = connect_int * HZ;
/* 28.5% random jitter */
- timeo += prandom_u32_max(2) ? timeo / 7 : -timeo / 7;
+ timeo += get_random_u32_below(2) ? timeo / 7 : -timeo / 7;
err = wait_for_completion_interruptible_timeout(&ad->door_bell, timeo);
if (err <= 0)
@@ -1004,7 +1004,7 @@ retry:
drbd_warn(connection, "Error receiving initial packet\n");
sock_release(s);
randomize:
- if (prandom_u32_max(2))
+ if (get_random_u32_below(2))
goto retry;
}
}
@@ -1603,9 +1603,19 @@ static void drbd_issue_peer_discard_or_zero_out(struct drbd_device *device, stru
drbd_endio_write_sec_final(peer_req);
}
+static int peer_request_fault_type(struct drbd_peer_request *peer_req)
+{
+ if (peer_req_op(peer_req) == REQ_OP_READ) {
+ return peer_req->flags & EE_APPLICATION ?
+ DRBD_FAULT_DT_RD : DRBD_FAULT_RS_RD;
+ } else {
+ return peer_req->flags & EE_APPLICATION ?
+ DRBD_FAULT_DT_WR : DRBD_FAULT_RS_WR;
+ }
+}
+
/**
* drbd_submit_peer_request()
- * @device: DRBD device.
* @peer_req: peer request
*
* May spread the pages to multiple bios,
@@ -1619,10 +1629,9 @@ static void drbd_issue_peer_discard_or_zero_out(struct drbd_device *device, stru
* on certain Xen deployments.
*/
/* TODO allocate from our own bio_set. */
-int drbd_submit_peer_request(struct drbd_device *device,
- struct drbd_peer_request *peer_req,
- const blk_opf_t opf, const int fault_type)
+int drbd_submit_peer_request(struct drbd_peer_request *peer_req)
{
+ struct drbd_device *device = peer_req->peer_device->device;
struct bio *bios = NULL;
struct bio *bio;
struct page *page = peer_req->pages;
@@ -1667,7 +1676,18 @@ int drbd_submit_peer_request(struct drbd_device *device,
* generated bio, but a bio allocated on behalf of the peer.
*/
next_bio:
- bio = bio_alloc(device->ldev->backing_bdev, nr_pages, opf, GFP_NOIO);
+ /* _DISCARD, _WRITE_ZEROES handled above.
+ * REQ_OP_FLUSH (empty flush) not expected,
+ * should have been mapped to a "drbd protocol barrier".
+ * REQ_OP_SECURE_ERASE: I don't see how we could ever support that.
+ */
+ if (!(peer_req_op(peer_req) == REQ_OP_WRITE ||
+ peer_req_op(peer_req) == REQ_OP_READ)) {
+ drbd_err(device, "Invalid bio op received: 0x%x\n", peer_req->opf);
+ return -EINVAL;
+ }
+
+ bio = bio_alloc(device->ldev->backing_bdev, nr_pages, peer_req->opf, GFP_NOIO);
/* > peer_req->i.sector, unless this is the first bio */
bio->bi_iter.bi_sector = sector;
bio->bi_private = peer_req;
@@ -1697,7 +1717,7 @@ next_bio:
bios = bios->bi_next;
bio->bi_next = NULL;
- drbd_submit_bio_noacct(device, fault_type, bio);
+ drbd_submit_bio_noacct(device, peer_request_fault_type(peer_req), bio);
} while (bios);
return 0;
}
@@ -1853,21 +1873,21 @@ read_in_block(struct drbd_peer_device *peer_device, u64 id, sector_t sector,
/* assume request_size == data_size, but special case trim. */
ds = data_size;
if (trim) {
- if (!expect(data_size == 0))
+ if (!expect(peer_device, data_size == 0))
return NULL;
ds = be32_to_cpu(trim->size);
} else if (zeroes) {
- if (!expect(data_size == 0))
+ if (!expect(peer_device, data_size == 0))
return NULL;
ds = be32_to_cpu(zeroes->size);
}
- if (!expect(IS_ALIGNED(ds, 512)))
+ if (!expect(peer_device, IS_ALIGNED(ds, 512)))
return NULL;
if (trim || zeroes) {
- if (!expect(ds <= (DRBD_MAX_BBIO_SECTORS << 9)))
+ if (!expect(peer_device, ds <= (DRBD_MAX_BBIO_SECTORS << 9)))
return NULL;
- } else if (!expect(ds <= DRBD_MAX_BIO_SIZE))
+ } else if (!expect(peer_device, ds <= DRBD_MAX_BIO_SIZE))
return NULL;
/* even though we trust out peer,
@@ -2051,6 +2071,7 @@ static int recv_resync_read(struct drbd_peer_device *peer_device, sector_t secto
* respective _drbd_clear_done_ee */
peer_req->w.cb = e_end_resync_block;
+ peer_req->opf = REQ_OP_WRITE;
peer_req->submit_jif = jiffies;
spin_lock_irq(&device->resource->req_lock);
@@ -2058,8 +2079,7 @@ static int recv_resync_read(struct drbd_peer_device *peer_device, sector_t secto
spin_unlock_irq(&device->resource->req_lock);
atomic_add(pi->size >> 9, &device->rs_sect_ev);
- if (drbd_submit_peer_request(device, peer_req, REQ_OP_WRITE,
- DRBD_FAULT_RS_WR) == 0)
+ if (drbd_submit_peer_request(peer_req) == 0)
return 0;
/* don't care for the reason here */
@@ -2145,7 +2165,7 @@ static int receive_RSDataReply(struct drbd_connection *connection, struct packet
* or in drbd_peer_request_endio. */
err = recv_resync_read(peer_device, sector, pi);
} else {
- if (__ratelimit(&drbd_ratelimit_state))
+ if (drbd_ratelimit())
drbd_err(device, "Can not write resync data to local disk.\n");
err = drbd_drain_block(peer_device, pi->size);
@@ -2375,16 +2395,6 @@ static int wait_for_and_update_peer_seq(struct drbd_peer_device *peer_device, co
return ret;
}
-/* see also bio_flags_to_wire()
- * DRBD_REQ_*, because we need to semantically map the flags to data packet
- * flags and back. We may replicate to other kernel versions. */
-static blk_opf_t wire_flags_to_bio_flags(u32 dpf)
-{
- return (dpf & DP_RW_SYNC ? REQ_SYNC : 0) |
- (dpf & DP_FUA ? REQ_FUA : 0) |
- (dpf & DP_FLUSH ? REQ_PREFLUSH : 0);
-}
-
static enum req_op wire_flags_to_bio_op(u32 dpf)
{
if (dpf & DP_ZEROES)
@@ -2395,6 +2405,15 @@ static enum req_op wire_flags_to_bio_op(u32 dpf)
return REQ_OP_WRITE;
}
+/* see also bio_flags_to_wire() */
+static blk_opf_t wire_flags_to_bio(struct drbd_connection *connection, u32 dpf)
+{
+ return wire_flags_to_bio_op(dpf) |
+ (dpf & DP_RW_SYNC ? REQ_SYNC : 0) |
+ (dpf & DP_FUA ? REQ_FUA : 0) |
+ (dpf & DP_FLUSH ? REQ_PREFLUSH : 0);
+}
+
static void fail_postponed_requests(struct drbd_device *device, sector_t sector,
unsigned int size)
{
@@ -2538,8 +2557,6 @@ static int receive_Data(struct drbd_connection *connection, struct packet_info *
struct drbd_peer_request *peer_req;
struct p_data *p = pi->data;
u32 peer_seq = be32_to_cpu(p->seq_num);
- enum req_op op;
- blk_opf_t op_flags;
u32 dp_flags;
int err, tp;
@@ -2578,11 +2595,10 @@ static int receive_Data(struct drbd_connection *connection, struct packet_info *
peer_req->flags |= EE_APPLICATION;
dp_flags = be32_to_cpu(p->dp_flags);
- op = wire_flags_to_bio_op(dp_flags);
- op_flags = wire_flags_to_bio_flags(dp_flags);
+ peer_req->opf = wire_flags_to_bio(connection, dp_flags);
if (pi->cmd == P_TRIM) {
D_ASSERT(peer_device, peer_req->i.size > 0);
- D_ASSERT(peer_device, op == REQ_OP_DISCARD);
+ D_ASSERT(peer_device, peer_req_op(peer_req) == REQ_OP_DISCARD);
D_ASSERT(peer_device, peer_req->pages == NULL);
/* need to play safe: an older DRBD sender
* may mean zero-out while sending P_TRIM. */
@@ -2590,7 +2606,7 @@ static int receive_Data(struct drbd_connection *connection, struct packet_info *
peer_req->flags |= EE_ZEROOUT;
} else if (pi->cmd == P_ZEROES) {
D_ASSERT(peer_device, peer_req->i.size > 0);
- D_ASSERT(peer_device, op == REQ_OP_WRITE_ZEROES);
+ D_ASSERT(peer_device, peer_req_op(peer_req) == REQ_OP_WRITE_ZEROES);
D_ASSERT(peer_device, peer_req->pages == NULL);
/* Do (not) pass down BLKDEV_ZERO_NOUNMAP? */
if (dp_flags & DP_DISCARD)
@@ -2677,8 +2693,7 @@ static int receive_Data(struct drbd_connection *connection, struct packet_info *
peer_req->flags |= EE_CALL_AL_COMPLETE_IO;
}
- err = drbd_submit_peer_request(device, peer_req, op | op_flags,
- DRBD_FAULT_DT_WR);
+ err = drbd_submit_peer_request(peer_req);
if (!err)
return 0;
@@ -2789,7 +2804,6 @@ static int receive_DataRequest(struct drbd_connection *connection, struct packet
struct drbd_peer_request *peer_req;
struct digest_info *di = NULL;
int size, verb;
- unsigned int fault_type;
struct p_block_req *p = pi->data;
peer_device = conn_peer_device(connection, pi->vnr);
@@ -2832,7 +2846,7 @@ static int receive_DataRequest(struct drbd_connection *connection, struct packet
default:
BUG();
}
- if (verb && __ratelimit(&drbd_ratelimit_state))
+ if (verb && drbd_ratelimit())
drbd_err(device, "Can not satisfy peer's read request, "
"no local data.\n");
@@ -2849,11 +2863,11 @@ static int receive_DataRequest(struct drbd_connection *connection, struct packet
put_ldev(device);
return -ENOMEM;
}
+ peer_req->opf = REQ_OP_READ;
switch (pi->cmd) {
case P_DATA_REQUEST:
peer_req->w.cb = w_e_end_data_req;
- fault_type = DRBD_FAULT_DT_RD;
/* application IO, don't drbd_rs_begin_io */
peer_req->flags |= EE_APPLICATION;
goto submit;
@@ -2867,14 +2881,12 @@ static int receive_DataRequest(struct drbd_connection *connection, struct packet
fallthrough;
case P_RS_DATA_REQUEST:
peer_req->w.cb = w_e_end_rsdata_req;
- fault_type = DRBD_FAULT_RS_RD;
/* used in the sector offset progress display */
device->bm_resync_fo = BM_SECT_TO_BIT(sector);
break;
case P_OV_REPLY:
case P_CSUM_RS_REQUEST:
- fault_type = DRBD_FAULT_RS_RD;
di = kmalloc(sizeof(*di) + pi->size, GFP_NOIO);
if (!di)
goto out_free_e;
@@ -2923,7 +2935,6 @@ static int receive_DataRequest(struct drbd_connection *connection, struct packet
(unsigned long long)sector);
}
peer_req->w.cb = w_e_end_ov_req;
- fault_type = DRBD_FAULT_RS_RD;
break;
default:
@@ -2975,8 +2986,7 @@ submit_for_resync:
submit:
update_receiver_timing_details(connection, drbd_submit_peer_request);
inc_unacked(device);
- if (drbd_submit_peer_request(device, peer_req, REQ_OP_READ,
- fault_type) == 0)
+ if (drbd_submit_peer_request(peer_req) == 0)
return 0;
/* don't care for the reason here */
@@ -4947,7 +4957,6 @@ static int receive_rs_deallocated(struct drbd_connection *connection, struct pac
if (get_ldev(device)) {
struct drbd_peer_request *peer_req;
- const enum req_op op = REQ_OP_WRITE_ZEROES;
peer_req = drbd_alloc_peer_req(peer_device, ID_SYNCER, sector,
size, 0, GFP_NOIO);
@@ -4957,6 +4966,7 @@ static int receive_rs_deallocated(struct drbd_connection *connection, struct pac
}
peer_req->w.cb = e_end_resync_block;
+ peer_req->opf = REQ_OP_DISCARD;
peer_req->submit_jif = jiffies;
peer_req->flags |= EE_TRIM;
@@ -4965,8 +4975,7 @@ static int receive_rs_deallocated(struct drbd_connection *connection, struct pac
spin_unlock_irq(&device->resource->req_lock);
atomic_add(pi->size >> 9, &device->rs_sect_ev);
- err = drbd_submit_peer_request(device, peer_req, op,
- DRBD_FAULT_RS_WR);
+ err = drbd_submit_peer_request(peer_req);
if (err) {
spin_lock_irq(&device->resource->req_lock);
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index 7f9bcc82fc9c..eb14ec8ec04c 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-License-Identifier: GPL-2.0-only
/*
drbd_req.c
@@ -144,7 +144,7 @@ void drbd_req_destroy(struct kref *kref)
if (get_ldev_if_state(device, D_FAILED)) {
drbd_al_complete_io(device, &req->i);
put_ldev(device);
- } else if (__ratelimit(&drbd_ratelimit_state)) {
+ } else if (drbd_ratelimit()) {
drbd_warn(device, "Should have called drbd_al_complete_io(, %llu, %u), "
"but my Disk seems to have failed :(\n",
(unsigned long long) req->i.sector, req->i.size);
@@ -518,7 +518,7 @@ static void mod_rq_state(struct drbd_request *req, struct bio_and_error *m,
static void drbd_report_io_error(struct drbd_device *device, struct drbd_request *req)
{
- if (!__ratelimit(&drbd_ratelimit_state))
+ if (!drbd_ratelimit())
return;
drbd_warn(device, "local %s IO error sector %llu+%u on %pg\n",
@@ -1402,7 +1402,7 @@ static void drbd_send_and_submit(struct drbd_device *device, struct drbd_request
submit_private_bio = true;
} else if (no_remote) {
nodata:
- if (__ratelimit(&drbd_ratelimit_state))
+ if (drbd_ratelimit())
drbd_err(device, "IO ERROR: neither local nor remote data, sector %llu+%u\n",
(unsigned long long)req->i.sector, req->i.size >> 9);
/* A write may have been queued for send_oos, however.
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h
index 6237fa1dcb0e..b4017b5c3fbc 100644
--- a/drivers/block/drbd/drbd_req.h
+++ b/drivers/block/drbd/drbd_req.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
drbd_req.h
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c
index 3f7bf9f2d874..75d13ea0024f 100644
--- a/drivers/block/drbd/drbd_state.c
+++ b/drivers/block/drbd/drbd_state.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-License-Identifier: GPL-2.0-only
/*
drbd_state.c
diff --git a/drivers/block/drbd/drbd_state.h b/drivers/block/drbd/drbd_state.h
index f87371e55e68..cbaeb8018dbf 100644
--- a/drivers/block/drbd/drbd_state.h
+++ b/drivers/block/drbd/drbd_state.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef DRBD_STATE_H
#define DRBD_STATE_H
diff --git a/drivers/block/drbd/drbd_state_change.h b/drivers/block/drbd/drbd_state_change.h
index d5b0479bc9a6..9d78d8e3912e 100644
--- a/drivers/block/drbd/drbd_state_change.h
+++ b/drivers/block/drbd/drbd_state_change.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef DRBD_STATE_CHANGE_H
#define DRBD_STATE_CHANGE_H
diff --git a/drivers/block/drbd/drbd_strings.c b/drivers/block/drbd/drbd_strings.c
index fc01307607ea..0a06f744b096 100644
--- a/drivers/block/drbd/drbd_strings.c
+++ b/drivers/block/drbd/drbd_strings.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-License-Identifier: GPL-2.0-only
/*
drbd.h
diff --git a/drivers/block/drbd/drbd_strings.h b/drivers/block/drbd/drbd_strings.h
index 87b94a27358a..0201f6590f6a 100644
--- a/drivers/block/drbd/drbd_strings.h
+++ b/drivers/block/drbd/drbd_strings.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __DRBD_STRINGS_H
#define __DRBD_STRINGS_H
diff --git a/drivers/block/drbd/drbd_vli.h b/drivers/block/drbd/drbd_vli.h
index 01e3babc5277..1ee81e3c2152 100644
--- a/drivers/block/drbd/drbd_vli.h
+++ b/drivers/block/drbd/drbd_vli.h
@@ -1,4 +1,4 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
-*- linux-c -*-
drbd_receiver.c
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c
index 0bb1a900c2d5..f46738040d6b 100644
--- a/drivers/block/drbd/drbd_worker.c
+++ b/drivers/block/drbd/drbd_worker.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
+// SPDX-License-Identifier: GPL-2.0-only
/*
drbd_worker.c
@@ -176,7 +176,7 @@ void drbd_peer_request_endio(struct bio *bio)
bool is_discard = bio_op(bio) == REQ_OP_WRITE_ZEROES ||
bio_op(bio) == REQ_OP_DISCARD;
- if (bio->bi_status && __ratelimit(&drbd_ratelimit_state))
+ if (bio->bi_status && drbd_ratelimit())
drbd_warn(device, "%s: error=%d s=%llus\n",
is_write ? (is_discard ? "discard" : "write")
: "read", bio->bi_status,
@@ -240,7 +240,7 @@ void drbd_request_endio(struct bio *bio)
* though we still will complain noisily about it.
*/
if (unlikely(req->rq_state & RQ_LOCAL_ABORTED)) {
- if (__ratelimit(&drbd_ratelimit_state))
+ if (drbd_ratelimit())
drbd_emerg(device, "delayed completion of aborted local request; disk-timeout may be too aggressive\n");
if (!bio->bi_status)
@@ -400,13 +400,13 @@ static int read_for_csum(struct drbd_peer_device *peer_device, sector_t sector,
goto defer;
peer_req->w.cb = w_e_send_csum;
+ peer_req->opf = REQ_OP_READ;
spin_lock_irq(&device->resource->req_lock);
list_add_tail(&peer_req->w.list, &device->read_ee);
spin_unlock_irq(&device->resource->req_lock);
atomic_add(size >> 9, &device->rs_sect_ev);
- if (drbd_submit_peer_request(device, peer_req, REQ_OP_READ,
- DRBD_FAULT_RS_RD) == 0)
+ if (drbd_submit_peer_request(peer_req) == 0)
return 0;
/* If it failed because of ENOMEM, retry should help. If it failed
@@ -1062,7 +1062,7 @@ int w_e_end_data_req(struct drbd_work *w, int cancel)
if (likely((peer_req->flags & EE_WAS_ERROR) == 0)) {
err = drbd_send_block(peer_device, P_DATA_REPLY, peer_req);
} else {
- if (__ratelimit(&drbd_ratelimit_state))
+ if (drbd_ratelimit())
drbd_err(device, "Sending NegDReply. sector=%llus.\n",
(unsigned long long)peer_req->i.sector);
@@ -1135,13 +1135,13 @@ int w_e_end_rsdata_req(struct drbd_work *w, int cancel)
else
err = drbd_send_block(peer_device, P_RS_DATA_REPLY, peer_req);
} else {
- if (__ratelimit(&drbd_ratelimit_state))
+ if (drbd_ratelimit())
drbd_err(device, "Not sending RSDataReply, "
"partner DISKLESS!\n");
err = 0;
}
} else {
- if (__ratelimit(&drbd_ratelimit_state))
+ if (drbd_ratelimit())
drbd_err(device, "Sending NegRSDReply. sector %llus.\n",
(unsigned long long)peer_req->i.sector);
@@ -1212,7 +1212,7 @@ int w_e_end_csum_rs_req(struct drbd_work *w, int cancel)
}
} else {
err = drbd_send_ack(peer_device, P_NEG_RS_DREPLY, peer_req);
- if (__ratelimit(&drbd_ratelimit_state))
+ if (drbd_ratelimit())
drbd_err(device, "Sending NegDReply. I guess it gets messy.\n");
}
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index ccad3d7b3ddd..487840e3564d 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4593,8 +4593,10 @@ static int __init do_floppy_init(void)
goto out_put_disk;
err = floppy_alloc_disk(drive, 0);
- if (err)
+ if (err) {
+ blk_mq_free_tag_set(&tag_sets[drive]);
goto out_put_disk;
+ }
timer_setup(&motor_off_timer[drive], motor_off_callback, 0);
}
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index ad92192c7d61..1f8f3b87bdfa 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -243,7 +243,7 @@ static int lo_write_bvec(struct file *file, struct bio_vec *bvec, loff_t *ppos)
struct iov_iter i;
ssize_t bw;
- iov_iter_bvec(&i, WRITE, bvec, 1, bvec->bv_len);
+ iov_iter_bvec(&i, ITER_SOURCE, bvec, 1, bvec->bv_len);
file_start_write(file);
bw = vfs_iter_write(file, &i, ppos, 0);
@@ -286,7 +286,7 @@ static int lo_read_simple(struct loop_device *lo, struct request *rq,
ssize_t len;
rq_for_each_segment(bvec, rq, iter) {
- iov_iter_bvec(&i, READ, &bvec, 1, bvec.bv_len);
+ iov_iter_bvec(&i, ITER_DEST, &bvec, 1, bvec.bv_len);
len = vfs_iter_read(lo->lo_backing_file, &i, &pos, 0);
if (len < 0)
return len;
@@ -392,7 +392,7 @@ static void lo_rw_aio_complete(struct kiocb *iocb, long ret)
}
static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
- loff_t pos, bool rw)
+ loff_t pos, int rw)
{
struct iov_iter iter;
struct req_iterator rq_iter;
@@ -448,7 +448,7 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd,
cmd->iocb.ki_flags = IOCB_DIRECT;
cmd->iocb.ki_ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_NONE, 0);
- if (rw == WRITE)
+ if (rw == ITER_SOURCE)
ret = call_write_iter(file, &cmd->iocb, &iter);
else
ret = call_read_iter(file, &cmd->iocb, &iter);
@@ -490,12 +490,12 @@ static int do_req_filebacked(struct loop_device *lo, struct request *rq)
return lo_fallocate(lo, rq, pos, FALLOC_FL_PUNCH_HOLE);
case REQ_OP_WRITE:
if (cmd->use_aio)
- return lo_rw_aio(lo, cmd, pos, WRITE);
+ return lo_rw_aio(lo, cmd, pos, ITER_SOURCE);
else
return lo_write_simple(lo, rq, pos);
case REQ_OP_READ:
if (cmd->use_aio)
- return lo_rw_aio(lo, cmd, pos, READ);
+ return lo_rw_aio(lo, cmd, pos, ITER_DEST);
else
return lo_read_simple(lo, rq, pos);
default:
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c
index 5cffd96ef2d7..e379ccc63c52 100644
--- a/drivers/block/nbd.c
+++ b/drivers/block/nbd.c
@@ -563,7 +563,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
u32 nbd_cmd_flags = 0;
int sent = nsock->sent, skip = 0;
- iov_iter_kvec(&from, WRITE, &iov, 1, sizeof(request));
+ iov_iter_kvec(&from, ITER_SOURCE, &iov, 1, sizeof(request));
type = req_to_nbd_cmd_type(req);
if (type == U32_MAX)
@@ -649,7 +649,7 @@ send_pages:
dev_dbg(nbd_to_dev(nbd), "request %p: sending %d bytes data\n",
req, bvec.bv_len);
- iov_iter_bvec(&from, WRITE, &bvec, 1, bvec.bv_len);
+ iov_iter_bvec(&from, ITER_SOURCE, &bvec, 1, bvec.bv_len);
if (skip) {
if (skip >= iov_iter_count(&from)) {
skip -= iov_iter_count(&from);
@@ -701,7 +701,7 @@ static int nbd_read_reply(struct nbd_device *nbd, int index,
int result;
reply->magic = 0;
- iov_iter_kvec(&to, READ, &iov, 1, sizeof(*reply));
+ iov_iter_kvec(&to, ITER_DEST, &iov, 1, sizeof(*reply));
result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL, NULL);
if (result < 0) {
if (!nbd_disconnected(nbd->config))
@@ -790,7 +790,7 @@ static struct nbd_cmd *nbd_handle_reply(struct nbd_device *nbd, int index,
struct iov_iter to;
rq_for_each_segment(bvec, req, iter) {
- iov_iter_bvec(&to, READ, &bvec, 1, bvec.bv_len);
+ iov_iter_bvec(&to, ITER_DEST, &bvec, 1, bvec.bv_len);
result = sock_xmit(nbd, index, 0, &to, MSG_WAITALL, NULL);
if (result < 0) {
dev_err(disk_to_dev(nbd->disk), "Receive data failed (result %d)\n",
@@ -1267,7 +1267,7 @@ static void send_disconnects(struct nbd_device *nbd)
for (i = 0; i < config->num_connections; i++) {
struct nbd_sock *nsock = config->socks[i];
- iov_iter_kvec(&from, WRITE, &iov, 1, sizeof(request));
+ iov_iter_kvec(&from, ITER_SOURCE, &iov, 1, sizeof(request));
mutex_lock(&nsock->tx_lock);
ret = sock_xmit(nbd, i, 1, &from, 0, NULL);
if (ret < 0)
diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c
index 1f154f92f4c2..7d28e3aa406c 100644
--- a/drivers/block/null_blk/main.c
+++ b/drivers/block/null_blk/main.c
@@ -523,6 +523,24 @@ out:
}
CONFIGFS_ATTR(nullb_device_, badblocks);
+static ssize_t nullb_device_zone_readonly_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct nullb_device *dev = to_nullb_device(item);
+
+ return zone_cond_store(dev, page, count, BLK_ZONE_COND_READONLY);
+}
+CONFIGFS_ATTR_WO(nullb_device_, zone_readonly);
+
+static ssize_t nullb_device_zone_offline_store(struct config_item *item,
+ const char *page, size_t count)
+{
+ struct nullb_device *dev = to_nullb_device(item);
+
+ return zone_cond_store(dev, page, count, BLK_ZONE_COND_OFFLINE);
+}
+CONFIGFS_ATTR_WO(nullb_device_, zone_offline);
+
static struct configfs_attribute *nullb_device_attrs[] = {
&nullb_device_attr_size,
&nullb_device_attr_completion_nsec,
@@ -549,6 +567,8 @@ static struct configfs_attribute *nullb_device_attrs[] = {
&nullb_device_attr_zone_nr_conv,
&nullb_device_attr_zone_max_open,
&nullb_device_attr_zone_max_active,
+ &nullb_device_attr_zone_readonly,
+ &nullb_device_attr_zone_offline,
&nullb_device_attr_virt_boundary,
&nullb_device_attr_no_sched,
&nullb_device_attr_shared_tag_bitmap,
@@ -614,7 +634,7 @@ static ssize_t memb_group_features_show(struct config_item *item, char *page)
"poll_queues,power,queue_mode,shared_tag_bitmap,size,"
"submit_queues,use_per_node_hctx,virt_boundary,zoned,"
"zone_capacity,zone_max_active,zone_max_open,"
- "zone_nr_conv,zone_size\n");
+ "zone_nr_conv,zone_offline,zone_readonly,zone_size\n");
}
CONFIGFS_ATTR_RO(memb_group_, features);
diff --git a/drivers/block/null_blk/null_blk.h b/drivers/block/null_blk/null_blk.h
index 94ff68052b1e..eb5972c50be8 100644
--- a/drivers/block/null_blk/null_blk.h
+++ b/drivers/block/null_blk/null_blk.h
@@ -151,6 +151,8 @@ blk_status_t null_process_zoned_cmd(struct nullb_cmd *cmd, enum req_op op,
sector_t sector, sector_t nr_sectors);
size_t null_zone_valid_read_len(struct nullb *nullb,
sector_t sector, unsigned int len);
+ssize_t zone_cond_store(struct nullb_device *dev, const char *page,
+ size_t count, enum blk_zone_cond cond);
#else
static inline int null_init_zoned_dev(struct nullb_device *dev,
struct request_queue *q)
@@ -174,6 +176,12 @@ static inline size_t null_zone_valid_read_len(struct nullb *nullb,
{
return len;
}
+static inline ssize_t zone_cond_store(struct nullb_device *dev,
+ const char *page, size_t count,
+ enum blk_zone_cond cond)
+{
+ return -EOPNOTSUPP;
+}
#define null_report_zones NULL
#endif /* CONFIG_BLK_DEV_ZONED */
#endif /* __NULL_BLK_H */
diff --git a/drivers/block/null_blk/zoned.c b/drivers/block/null_blk/zoned.c
index 55a69e48ef8b..635ce0648133 100644
--- a/drivers/block/null_blk/zoned.c
+++ b/drivers/block/null_blk/zoned.c
@@ -384,8 +384,10 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
null_lock_zone(dev, zone);
- if (zone->cond == BLK_ZONE_COND_FULL) {
- /* Cannot write to a full zone */
+ if (zone->cond == BLK_ZONE_COND_FULL ||
+ zone->cond == BLK_ZONE_COND_READONLY ||
+ zone->cond == BLK_ZONE_COND_OFFLINE) {
+ /* Cannot write to the zone */
ret = BLK_STS_IOERR;
goto unlock;
}
@@ -613,7 +615,9 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_op op,
for (i = dev->zone_nr_conv; i < dev->nr_zones; i++) {
zone = &dev->zones[i];
null_lock_zone(dev, zone);
- if (zone->cond != BLK_ZONE_COND_EMPTY) {
+ if (zone->cond != BLK_ZONE_COND_EMPTY &&
+ zone->cond != BLK_ZONE_COND_READONLY &&
+ zone->cond != BLK_ZONE_COND_OFFLINE) {
null_reset_zone(dev, zone);
trace_nullb_zone_op(cmd, i, zone->cond);
}
@@ -627,6 +631,12 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_op op,
null_lock_zone(dev, zone);
+ if (zone->cond == BLK_ZONE_COND_READONLY ||
+ zone->cond == BLK_ZONE_COND_OFFLINE) {
+ ret = BLK_STS_IOERR;
+ goto unlock;
+ }
+
switch (op) {
case REQ_OP_ZONE_RESET:
ret = null_reset_zone(dev, zone);
@@ -648,6 +658,7 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_op op,
if (ret == BLK_STS_OK)
trace_nullb_zone_op(cmd, zone_no, zone->cond);
+unlock:
null_unlock_zone(dev, zone);
return ret;
@@ -674,6 +685,8 @@ blk_status_t null_process_zoned_cmd(struct nullb_cmd *cmd, enum req_op op,
default:
dev = cmd->nq->dev;
zone = &dev->zones[null_zone_no(dev, sector)];
+ if (zone->cond == BLK_ZONE_COND_OFFLINE)
+ return BLK_STS_IOERR;
null_lock_zone(dev, zone);
sts = null_process_cmd(cmd, op, sector, nr_sectors);
@@ -681,3 +694,79 @@ blk_status_t null_process_zoned_cmd(struct nullb_cmd *cmd, enum req_op op,
return sts;
}
}
+
+/*
+ * Set a zone in the read-only or offline condition.
+ */
+static void null_set_zone_cond(struct nullb_device *dev,
+ struct nullb_zone *zone, enum blk_zone_cond cond)
+{
+ if (WARN_ON_ONCE(cond != BLK_ZONE_COND_READONLY &&
+ cond != BLK_ZONE_COND_OFFLINE))
+ return;
+
+ null_lock_zone(dev, zone);
+
+ /*
+ * If the read-only condition is requested again to zones already in
+ * read-only condition, restore back normal empty condition. Do the same
+ * if the offline condition is requested for offline zones. Otherwise,
+ * set the specified zone condition to the zones. Finish the zones
+ * beforehand to free up zone resources.
+ */
+ if (zone->cond == cond) {
+ zone->cond = BLK_ZONE_COND_EMPTY;
+ zone->wp = zone->start;
+ if (dev->memory_backed)
+ null_handle_discard(dev, zone->start, zone->len);
+ } else {
+ if (zone->cond != BLK_ZONE_COND_READONLY &&
+ zone->cond != BLK_ZONE_COND_OFFLINE)
+ null_finish_zone(dev, zone);
+ zone->cond = cond;
+ zone->wp = (sector_t)-1;
+ }
+
+ null_unlock_zone(dev, zone);
+}
+
+/*
+ * Identify a zone from the sector written to configfs file. Then set zone
+ * condition to the zone.
+ */
+ssize_t zone_cond_store(struct nullb_device *dev, const char *page,
+ size_t count, enum blk_zone_cond cond)
+{
+ unsigned long long sector;
+ unsigned int zone_no;
+ int ret;
+
+ if (!dev->zoned) {
+ pr_err("null_blk device is not zoned\n");
+ return -EINVAL;
+ }
+
+ if (!dev->zones) {
+ pr_err("null_blk device is not yet powered\n");
+ return -EINVAL;
+ }
+
+ ret = kstrtoull(page, 0, &sector);
+ if (ret < 0)
+ return ret;
+
+ zone_no = null_zone_no(dev, sector);
+ if (zone_no >= dev->nr_zones) {
+ pr_err("Sector out of range\n");
+ return -EINVAL;
+ }
+
+ if (dev->zones[zone_no].type == BLK_ZONE_TYPE_CONVENTIONAL) {
+ pr_err("Can not change condition of conventional zones\n");
+ return -EINVAL;
+ }
+
+ null_set_zone_cond(dev, &dev->zones[zone_no], cond);
+
+ return count;
+}
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
deleted file mode 100644
index 4cea3b08087e..000000000000
--- a/drivers/block/pktcdvd.c
+++ /dev/null
@@ -1,2944 +0,0 @@
-/*
- * Copyright (C) 2000 Jens Axboe <axboe@suse.de>
- * Copyright (C) 2001-2004 Peter Osterlund <petero2@telia.com>
- * Copyright (C) 2006 Thomas Maier <balagi@justmail.de>
- *
- * May be copied or modified under the terms of the GNU General Public
- * License. See linux/COPYING for more information.
- *
- * Packet writing layer for ATAPI and SCSI CD-RW, DVD+RW, DVD-RW and
- * DVD-RAM devices.
- *
- * Theory of operation:
- *
- * At the lowest level, there is the standard driver for the CD/DVD device,
- * such as drivers/scsi/sr.c. This driver can handle read and write requests,
- * but it doesn't know anything about the special restrictions that apply to
- * packet writing. One restriction is that write requests must be aligned to
- * packet boundaries on the physical media, and the size of a write request
- * must be equal to the packet size. Another restriction is that a
- * GPCMD_FLUSH_CACHE command has to be issued to the drive before a read
- * command, if the previous command was a write.
- *
- * The purpose of the packet writing driver is to hide these restrictions from
- * higher layers, such as file systems, and present a block device that can be
- * randomly read and written using 2kB-sized blocks.
- *
- * The lowest layer in the packet writing driver is the packet I/O scheduler.
- * Its data is defined by the struct packet_iosched and includes two bio
- * queues with pending read and write requests. These queues are processed
- * by the pkt_iosched_process_queue() function. The write requests in this
- * queue are already properly aligned and sized. This layer is responsible for
- * issuing the flush cache commands and scheduling the I/O in a good order.
- *
- * The next layer transforms unaligned write requests to aligned writes. This
- * transformation requires reading missing pieces of data from the underlying
- * block device, assembling the pieces to full packets and queuing them to the
- * packet I/O scheduler.
- *
- * At the top layer there is a custom ->submit_bio function that forwards
- * read requests directly to the iosched queue and puts write requests in the
- * unaligned write queue. A kernel thread performs the necessary read
- * gathering to convert the unaligned writes to aligned writes and then feeds
- * them to the packet I/O scheduler.
- *
- *************************************************************************/
-
-#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/compat.h>
-#include <linux/kthread.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/mutex.h>
-#include <linux/slab.h>
-#include <linux/backing-dev.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"
-
-#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 MAX_SPEED 0xffff
-
-static DEFINE_MUTEX(pktcdvd_mutex);
-static struct pktcdvd_device *pkt_devs[MAX_WRITERS];
-static struct proc_dir_entry *pkt_proc;
-static int pktdev_major;
-static int write_congestion_on = PKT_WRITE_CONGESTION_ON;
-static int write_congestion_off = PKT_WRITE_CONGESTION_OFF;
-static struct mutex ctl_mutex; /* Serialize open/close/setup/teardown */
-static mempool_t psd_pool;
-static struct bio_set pkt_bio_set;
-
-static struct class *class_pktcdvd = NULL; /* /sys/class/pktcdvd */
-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)
-{
- return (sector + pd->offset) & ~(sector_t)(pd->settings.size - 1);
-}
-
-/**********************************************************
- * sysfs interface for pktcdvd
- * by (C) 2006 Thomas Maier <balagi@justmail.de>
-
- /sys/class/pktcdvd/pktcdvd[0-7]/
- stat/reset
- stat/packets_started
- stat/packets_finished
- stat/kb_written
- stat/kb_read
- stat/kb_read_gather
- write_queue/size
- write_queue/congestion_off
- write_queue/congestion_on
- **********************************************************/
-
-static ssize_t packets_started_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct pktcdvd_device *pd = dev_get_drvdata(dev);
-
- return sysfs_emit(buf, "%lu\n", pd->stats.pkt_started);
-}
-static DEVICE_ATTR_RO(packets_started);
-
-static ssize_t packets_finished_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct pktcdvd_device *pd = dev_get_drvdata(dev);
-
- return sysfs_emit(buf, "%lu\n", pd->stats.pkt_ended);
-}
-static DEVICE_ATTR_RO(packets_finished);
-
-static ssize_t kb_written_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct pktcdvd_device *pd = dev_get_drvdata(dev);
-
- return sysfs_emit(buf, "%lu\n", pd->stats.secs_w >> 1);
-}
-static DEVICE_ATTR_RO(kb_written);
-
-static ssize_t kb_read_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct pktcdvd_device *pd = dev_get_drvdata(dev);
-
- return sysfs_emit(buf, "%lu\n", pd->stats.secs_r >> 1);
-}
-static DEVICE_ATTR_RO(kb_read);
-
-static ssize_t kb_read_gather_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct pktcdvd_device *pd = dev_get_drvdata(dev);
-
- return sysfs_emit(buf, "%lu\n", pd->stats.secs_rg >> 1);
-}
-static DEVICE_ATTR_RO(kb_read_gather);
-
-static ssize_t reset_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t len)
-{
- struct pktcdvd_device *pd = dev_get_drvdata(dev);
-
- if (len > 0) {
- pd->stats.pkt_started = 0;
- pd->stats.pkt_ended = 0;
- pd->stats.secs_w = 0;
- pd->stats.secs_rg = 0;
- pd->stats.secs_r = 0;
- }
- return len;
-}
-static DEVICE_ATTR_WO(reset);
-
-static struct attribute *pkt_stat_attrs[] = {
- &dev_attr_packets_finished.attr,
- &dev_attr_packets_started.attr,
- &dev_attr_kb_read.attr,
- &dev_attr_kb_written.attr,
- &dev_attr_kb_read_gather.attr,
- &dev_attr_reset.attr,
- NULL,
-};
-
-static const struct attribute_group pkt_stat_group = {
- .name = "stat",
- .attrs = pkt_stat_attrs,
-};
-
-static ssize_t size_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct pktcdvd_device *pd = dev_get_drvdata(dev);
- int n;
-
- spin_lock(&pd->lock);
- n = sysfs_emit(buf, "%d\n", pd->bio_queue_size);
- spin_unlock(&pd->lock);
- return n;
-}
-static DEVICE_ATTR_RO(size);
-
-static void init_write_congestion_marks(int* lo, int* hi)
-{
- if (*hi > 0) {
- *hi = max(*hi, 500);
- *hi = min(*hi, 1000000);
- if (*lo <= 0)
- *lo = *hi - 100;
- else {
- *lo = min(*lo, *hi - 100);
- *lo = max(*lo, 100);
- }
- } else {
- *hi = -1;
- *lo = -1;
- }
-}
-
-static ssize_t congestion_off_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct pktcdvd_device *pd = dev_get_drvdata(dev);
- int n;
-
- spin_lock(&pd->lock);
- n = sysfs_emit(buf, "%d\n", pd->write_congestion_off);
- spin_unlock(&pd->lock);
- return n;
-}
-
-static ssize_t congestion_off_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
-{
- struct pktcdvd_device *pd = dev_get_drvdata(dev);
- int val;
-
- 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);
- }
- return len;
-}
-static DEVICE_ATTR_RW(congestion_off);
-
-static ssize_t congestion_on_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct pktcdvd_device *pd = dev_get_drvdata(dev);
- int n;
-
- spin_lock(&pd->lock);
- n = sysfs_emit(buf, "%d\n", pd->write_congestion_on);
- spin_unlock(&pd->lock);
- return n;
-}
-
-static ssize_t congestion_on_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t len)
-{
- struct pktcdvd_device *pd = dev_get_drvdata(dev);
- int val;
-
- 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);
- }
- return len;
-}
-static DEVICE_ATTR_RW(congestion_on);
-
-static struct attribute *pkt_wq_attrs[] = {
- &dev_attr_congestion_on.attr,
- &dev_attr_congestion_off.attr,
- &dev_attr_size.attr,
- NULL,
-};
-
-static const struct attribute_group pkt_wq_group = {
- .name = "write_queue",
- .attrs = pkt_wq_attrs,
-};
-
-static const struct attribute_group *pkt_groups[] = {
- &pkt_stat_group,
- &pkt_wq_group,
- NULL,
-};
-
-static void pkt_sysfs_dev_new(struct pktcdvd_device *pd)
-{
- if (class_pktcdvd) {
- pd->dev = device_create_with_groups(class_pktcdvd, NULL,
- MKDEV(0, 0), pd, pkt_groups,
- "%s", pd->name);
- if (IS_ERR(pd->dev))
- pd->dev = NULL;
- }
-}
-
-static void pkt_sysfs_dev_remove(struct pktcdvd_device *pd)
-{
- if (class_pktcdvd)
- device_unregister(pd->dev);
-}
-
-
-/********************************************************************
- /sys/class/pktcdvd/
- add map block device
- remove unmap packet dev
- device_map show mappings
- *******************************************************************/
-
-static void class_pktcdvd_release(struct class *cls)
-{
- kfree(cls);
-}
-
-static ssize_t device_map_show(struct class *c, struct class_attribute *attr,
- char *data)
-{
- int n = 0;
- int idx;
- mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
- for (idx = 0; idx < MAX_WRITERS; idx++) {
- struct pktcdvd_device *pd = pkt_devs[idx];
- if (!pd)
- continue;
- n += sprintf(data+n, "%s %u:%u %u:%u\n",
- pd->name,
- MAJOR(pd->pkt_dev), MINOR(pd->pkt_dev),
- MAJOR(pd->bdev->bd_dev),
- MINOR(pd->bdev->bd_dev));
- }
- mutex_unlock(&ctl_mutex);
- return n;
-}
-static CLASS_ATTR_RO(device_map);
-
-static ssize_t add_store(struct class *c, struct class_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned int major, minor;
-
- if (sscanf(buf, "%u:%u", &major, &minor) == 2) {
- /* pkt_setup_dev() expects caller to hold reference to self */
- if (!try_module_get(THIS_MODULE))
- return -ENODEV;
-
- pkt_setup_dev(MKDEV(major, minor), NULL);
-
- module_put(THIS_MODULE);
-
- return count;
- }
-
- return -EINVAL;
-}
-static CLASS_ATTR_WO(add);
-
-static ssize_t remove_store(struct class *c, struct class_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned int major, minor;
- if (sscanf(buf, "%u:%u", &major, &minor) == 2) {
- pkt_remove_dev(MKDEV(major, minor));
- return count;
- }
- return -EINVAL;
-}
-static CLASS_ATTR_WO(remove);
-
-static struct attribute *class_pktcdvd_attrs[] = {
- &class_attr_add.attr,
- &class_attr_remove.attr,
- &class_attr_device_map.attr,
- NULL,
-};
-ATTRIBUTE_GROUPS(class_pktcdvd);
-
-static int pkt_sysfs_init(void)
-{
- int ret = 0;
-
- /*
- * create control files in sysfs
- * /sys/class/pktcdvd/...
- */
- class_pktcdvd = kzalloc(sizeof(*class_pktcdvd), GFP_KERNEL);
- if (!class_pktcdvd)
- return -ENOMEM;
- class_pktcdvd->name = DRIVER_NAME;
- class_pktcdvd->owner = THIS_MODULE;
- class_pktcdvd->class_release = class_pktcdvd_release;
- class_pktcdvd->class_groups = class_pktcdvd_groups;
- ret = class_register(class_pktcdvd);
- if (ret) {
- kfree(class_pktcdvd);
- class_pktcdvd = NULL;
- pr_err("failed to create class pktcdvd\n");
- return ret;
- }
- return 0;
-}
-
-static void pkt_sysfs_cleanup(void)
-{
- if (class_pktcdvd)
- class_destroy(class_pktcdvd);
- class_pktcdvd = NULL;
-}
-
-/********************************************************************
- entries in debugfs
-
- /sys/kernel/debug/pktcdvd[0-7]/
- info
-
- *******************************************************************/
-
-static int pkt_debugfs_seq_show(struct seq_file *m, void *p)
-{
- return pkt_seq_show(m, p);
-}
-
-static int pkt_debugfs_fops_open(struct inode *inode, struct file *file)
-{
- return single_open(file, pkt_debugfs_seq_show, inode->i_private);
-}
-
-static const struct file_operations debug_fops = {
- .open = pkt_debugfs_fops_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .owner = THIS_MODULE,
-};
-
-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);
- if (!pd->dfs_d_root)
- return;
-
- pd->dfs_f_info = debugfs_create_file("info", 0444,
- pd->dfs_d_root, pd, &debug_fops);
-}
-
-static void pkt_debugfs_dev_remove(struct pktcdvd_device *pd)
-{
- if (!pkt_debugfs_root)
- return;
- debugfs_remove(pd->dfs_f_info);
- debugfs_remove(pd->dfs_d_root);
- pd->dfs_f_info = NULL;
- pd->dfs_d_root = NULL;
-}
-
-static void pkt_debugfs_init(void)
-{
- pkt_debugfs_root = debugfs_create_dir(DRIVER_NAME, NULL);
-}
-
-static void pkt_debugfs_cleanup(void)
-{
- debugfs_remove(pkt_debugfs_root);
- pkt_debugfs_root = NULL;
-}
-
-/* ----------------------------------------------------------*/
-
-
-static void pkt_bio_finished(struct pktcdvd_device *pd)
-{
- 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");
- atomic_set(&pd->iosched.attention, 1);
- wake_up(&pd->wqueue);
- }
-}
-
-/*
- * Allocate a packet_data struct
- */
-static struct packet_data *pkt_alloc_packet_data(int frames)
-{
- int i;
- struct packet_data *pkt;
-
- pkt = kzalloc(sizeof(struct packet_data), GFP_KERNEL);
- if (!pkt)
- goto no_pkt;
-
- pkt->frames = frames;
- pkt->w_bio = bio_kmalloc(frames, GFP_KERNEL);
- if (!pkt->w_bio)
- goto no_bio;
-
- for (i = 0; i < frames / FRAMES_PER_PAGE; i++) {
- pkt->pages[i] = alloc_page(GFP_KERNEL|__GFP_ZERO);
- if (!pkt->pages[i])
- goto no_page;
- }
-
- spin_lock_init(&pkt->lock);
- bio_list_init(&pkt->orig_bios);
-
- for (i = 0; i < frames; i++) {
- pkt->r_bios[i] = bio_kmalloc(1, GFP_KERNEL);
- if (!pkt->r_bios[i])
- goto no_rd_bio;
- }
-
- return pkt;
-
-no_rd_bio:
- for (i = 0; i < frames; i++)
- kfree(pkt->r_bios[i]);
-no_page:
- for (i = 0; i < frames / FRAMES_PER_PAGE; i++)
- if (pkt->pages[i])
- __free_page(pkt->pages[i]);
- kfree(pkt->w_bio);
-no_bio:
- kfree(pkt);
-no_pkt:
- return NULL;
-}
-
-/*
- * Free a packet_data struct
- */
-static void pkt_free_packet_data(struct packet_data *pkt)
-{
- int i;
-
- for (i = 0; i < pkt->frames; i++)
- kfree(pkt->r_bios[i]);
- for (i = 0; i < pkt->frames / FRAMES_PER_PAGE; i++)
- __free_page(pkt->pages[i]);
- kfree(pkt->w_bio);
- kfree(pkt);
-}
-
-static void pkt_shrink_pktlist(struct pktcdvd_device *pd)
-{
- struct packet_data *pkt, *next;
-
- BUG_ON(!list_empty(&pd->cdrw.pkt_active_list));
-
- list_for_each_entry_safe(pkt, next, &pd->cdrw.pkt_free_list, list) {
- pkt_free_packet_data(pkt);
- }
- INIT_LIST_HEAD(&pd->cdrw.pkt_free_list);
-}
-
-static int pkt_grow_pktlist(struct pktcdvd_device *pd, int nr_packets)
-{
- struct packet_data *pkt;
-
- BUG_ON(!list_empty(&pd->cdrw.pkt_free_list));
-
- while (nr_packets > 0) {
- pkt = pkt_alloc_packet_data(pd->settings.size >> 2);
- if (!pkt) {
- pkt_shrink_pktlist(pd);
- return 0;
- }
- pkt->id = nr_packets;
- pkt->pd = pd;
- list_add(&pkt->list, &pd->cdrw.pkt_free_list);
- nr_packets--;
- }
- return 1;
-}
-
-static inline struct pkt_rb_node *pkt_rbtree_next(struct pkt_rb_node *node)
-{
- struct rb_node *n = rb_next(&node->rb_node);
- if (!n)
- return NULL;
- return rb_entry(n, struct pkt_rb_node, rb_node);
-}
-
-static void pkt_rbtree_erase(struct pktcdvd_device *pd, struct pkt_rb_node *node)
-{
- rb_erase(&node->rb_node, &pd->bio_queue);
- mempool_free(node, &pd->rb_pool);
- pd->bio_queue_size--;
- BUG_ON(pd->bio_queue_size < 0);
-}
-
-/*
- * Find the first node in the pd->bio_queue rb tree with a starting sector >= s.
- */
-static struct pkt_rb_node *pkt_rbtree_find(struct pktcdvd_device *pd, sector_t s)
-{
- struct rb_node *n = pd->bio_queue.rb_node;
- struct rb_node *next;
- struct pkt_rb_node *tmp;
-
- if (!n) {
- BUG_ON(pd->bio_queue_size > 0);
- return NULL;
- }
-
- for (;;) {
- tmp = rb_entry(n, struct pkt_rb_node, rb_node);
- if (s <= tmp->bio->bi_iter.bi_sector)
- next = n->rb_left;
- else
- next = n->rb_right;
- if (!next)
- break;
- n = next;
- }
-
- if (s > tmp->bio->bi_iter.bi_sector) {
- tmp = pkt_rbtree_next(tmp);
- if (!tmp)
- return NULL;
- }
- BUG_ON(s > tmp->bio->bi_iter.bi_sector);
- return tmp;
-}
-
-/*
- * Insert a node into the pd->bio_queue rb tree.
- */
-static void pkt_rbtree_insert(struct pktcdvd_device *pd, struct pkt_rb_node *node)
-{
- struct rb_node **p = &pd->bio_queue.rb_node;
- struct rb_node *parent = NULL;
- sector_t s = node->bio->bi_iter.bi_sector;
- struct pkt_rb_node *tmp;
-
- while (*p) {
- parent = *p;
- tmp = rb_entry(parent, struct pkt_rb_node, rb_node);
- if (s < tmp->bio->bi_iter.bi_sector)
- p = &(*p)->rb_left;
- else
- p = &(*p)->rb_right;
- }
- rb_link_node(&node->rb_node, parent, p);
- rb_insert_color(&node->rb_node, &pd->bio_queue);
- pd->bio_queue_size++;
-}
-
-/*
- * Send a packet_command to the underlying block device and
- * wait for completion.
- */
-static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *cgc)
-{
- struct request_queue *q = bdev_get_queue(pd->bdev);
- struct scsi_cmnd *scmd;
- struct request *rq;
- int ret = 0;
-
- rq = scsi_alloc_request(q, (cgc->data_direction == CGC_DATA_WRITE) ?
- REQ_OP_DRV_OUT : REQ_OP_DRV_IN, 0);
- if (IS_ERR(rq))
- return PTR_ERR(rq);
- scmd = blk_mq_rq_to_pdu(rq);
-
- if (cgc->buflen) {
- ret = blk_rq_map_kern(q, rq, cgc->buffer, cgc->buflen,
- GFP_NOIO);
- if (ret)
- goto out;
- }
-
- scmd->cmd_len = COMMAND_SIZE(cgc->cmd[0]);
- memcpy(scmd->cmnd, cgc->cmd, CDROM_PACKET_SIZE);
-
- rq->timeout = 60*HZ;
- if (cgc->quiet)
- rq->rq_flags |= RQF_QUIET;
-
- blk_execute_rq(rq, false);
- if (scmd->result)
- ret = -EIO;
-out:
- blk_mq_free_request(rq);
- return ret;
-}
-
-static const char *sense_key_string(__u8 index)
-{
- static const char * const info[] = {
- "No sense", "Recovered error", "Not ready",
- "Medium error", "Hardware error", "Illegal request",
- "Unit attention", "Data protect", "Blank check",
- };
-
- return index < ARRAY_SIZE(info) ? info[index] : "INVALID";
-}
-
-/*
- * A generic sense dump / resolve mechanism should be implemented across
- * all ATAPI + SCSI devices.
- */
-static void pkt_dump_sense(struct pktcdvd_device *pd,
- struct packet_command *cgc)
-{
- struct scsi_sense_hdr *sshdr = cgc->sshdr;
-
- if (sshdr)
- pkt_err(pd, "%*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);
-}
-
-/*
- * flush the drive cache to media
- */
-static int pkt_flush_cache(struct pktcdvd_device *pd)
-{
- struct packet_command cgc;
-
- init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
- cgc.cmd[0] = GPCMD_FLUSH_CACHE;
- cgc.quiet = 1;
-
- /*
- * the IMMED bit -- we default to not setting it, although that
- * would allow a much faster close, this is safer
- */
-#if 0
- cgc.cmd[1] = 1 << 1;
-#endif
- return pkt_generic_packet(pd, &cgc);
-}
-
-/*
- * speed is given as the normal factor, e.g. 4 for 4x
- */
-static noinline_for_stack int pkt_set_speed(struct pktcdvd_device *pd,
- unsigned write_speed, unsigned read_speed)
-{
- struct packet_command cgc;
- struct scsi_sense_hdr sshdr;
- int ret;
-
- 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;
-
- ret = pkt_generic_packet(pd, &cgc);
- if (ret)
- pkt_dump_sense(pd, &cgc);
-
- return ret;
-}
-
-/*
- * Queue a bio for processing by the low-level CD device. Must be called
- * from process context.
- */
-static void pkt_queue_bio(struct pktcdvd_device *pd, struct bio *bio)
-{
- spin_lock(&pd->iosched.lock);
- if (bio_data_dir(bio) == READ)
- bio_list_add(&pd->iosched.read_queue, bio);
- else
- bio_list_add(&pd->iosched.write_queue, bio);
- spin_unlock(&pd->iosched.lock);
-
- atomic_set(&pd->iosched.attention, 1);
- wake_up(&pd->wqueue);
-}
-
-/*
- * Process the queued read/write requests. This function handles special
- * requirements for CDRW drives:
- * - A cache flush command must be inserted before a read request if the
- * previous request was a write.
- * - Switching between reading and writing is slow, so don't do it more often
- * than necessary.
- * - Optimize for throughput at the expense of latency. This means that streaming
- * writes will never be interrupted by a read, but if the drive has to seek
- * before the next write, switch to reading instead if there are any pending
- * read requests.
- * - Set the read speed according to current usage pattern. When only reading
- * from the device, it's best to use the highest possible read speed, but
- * when switching often between reading and writing, it's better to have the
- * same read and write speeds.
- */
-static void pkt_iosched_process_queue(struct pktcdvd_device *pd)
-{
-
- if (atomic_read(&pd->iosched.attention) == 0)
- return;
- atomic_set(&pd->iosched.attention, 0);
-
- for (;;) {
- struct bio *bio;
- int reads_queued, writes_queued;
-
- spin_lock(&pd->iosched.lock);
- reads_queued = !bio_list_empty(&pd->iosched.read_queue);
- writes_queued = !bio_list_empty(&pd->iosched.write_queue);
- spin_unlock(&pd->iosched.lock);
-
- if (!reads_queued && !writes_queued)
- break;
-
- if (pd->iosched.writing) {
- int need_write_seek = 1;
- spin_lock(&pd->iosched.lock);
- bio = bio_list_peek(&pd->iosched.write_queue);
- spin_unlock(&pd->iosched.lock);
- if (bio && (bio->bi_iter.bi_sector ==
- pd->iosched.last_write))
- 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");
- break;
- }
- pkt_flush_cache(pd);
- pd->iosched.writing = 0;
- }
- } else {
- if (!reads_queued && writes_queued) {
- if (atomic_read(&pd->cdrw.pending_bios) > 0) {
- pkt_dbg(2, pd, "read, waiting\n");
- break;
- }
- pd->iosched.writing = 1;
- }
- }
-
- spin_lock(&pd->iosched.lock);
- if (pd->iosched.writing)
- bio = bio_list_pop(&pd->iosched.write_queue);
- else
- bio = bio_list_pop(&pd->iosched.read_queue);
- spin_unlock(&pd->iosched.lock);
-
- if (!bio)
- continue;
-
- if (bio_data_dir(bio) == READ)
- pd->iosched.successive_reads +=
- bio->bi_iter.bi_size >> 10;
- else {
- pd->iosched.successive_reads = 0;
- pd->iosched.last_write = bio_end_sector(bio);
- }
- if (pd->iosched.successive_reads >= HI_SPEED_SWITCH) {
- if (pd->read_speed == pd->write_speed) {
- pd->read_speed = MAX_SPEED;
- pkt_set_speed(pd, pd->write_speed, pd->read_speed);
- }
- } else {
- if (pd->read_speed != pd->write_speed) {
- pd->read_speed = pd->write_speed;
- pkt_set_speed(pd, pd->write_speed, pd->read_speed);
- }
- }
-
- atomic_inc(&pd->cdrw.pending_bios);
- submit_bio_noacct(bio);
- }
-}
-
-/*
- * Special care is needed if the underlying block device has a small
- * max_phys_segments value.
- */
-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)) {
- /*
- * 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)) {
- /*
- * 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;
- }
-}
-
-static void pkt_end_io_read(struct bio *bio)
-{
- struct packet_data *pkt = bio->bi_private;
- 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);
-
- if (bio->bi_status)
- atomic_inc(&pkt->io_errors);
- bio_uninit(bio);
- if (atomic_dec_and_test(&pkt->io_wait)) {
- atomic_inc(&pkt->run_sm);
- wake_up(&pd->wqueue);
- }
- pkt_bio_finished(pd);
-}
-
-static void pkt_end_io_packet_write(struct bio *bio)
-{
- struct packet_data *pkt = bio->bi_private;
- struct pktcdvd_device *pd = pkt->pd;
- BUG_ON(!pd);
-
- pkt_dbg(2, pd, "id=%d, err=%d\n", pkt->id, bio->bi_status);
-
- pd->stats.pkt_ended++;
-
- bio_uninit(bio);
- pkt_bio_finished(pd);
- atomic_dec(&pkt->io_wait);
- atomic_inc(&pkt->run_sm);
- wake_up(&pd->wqueue);
-}
-
-/*
- * Schedule reads for the holes in a packet
- */
-static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt)
-{
- int frames_read = 0;
- struct bio *bio;
- int f;
- char written[PACKET_MAX_SIZE];
-
- BUG_ON(bio_list_empty(&pkt->orig_bios));
-
- atomic_set(&pkt->io_wait, 0);
- atomic_set(&pkt->io_errors, 0);
-
- /*
- * Figure out which frames we need to read before we can write.
- */
- memset(written, 0, sizeof(written));
- spin_lock(&pkt->lock);
- bio_list_for_each(bio, &pkt->orig_bios) {
- int first_frame = (bio->bi_iter.bi_sector - pkt->sector) /
- (CD_FRAMESIZE >> 9);
- int num_frames = bio->bi_iter.bi_size / CD_FRAMESIZE;
- pd->stats.secs_w += num_frames * (CD_FRAMESIZE >> 9);
- BUG_ON(first_frame < 0);
- BUG_ON(first_frame + num_frames > pkt->frames);
- for (f = first_frame; f < first_frame + num_frames; f++)
- written[f] = 1;
- }
- spin_unlock(&pkt->lock);
-
- if (pkt->cache_valid) {
- pkt_dbg(2, pd, "zone %llx cached\n",
- (unsigned long long)pkt->sector);
- goto out_account;
- }
-
- /*
- * Schedule reads for missing parts of the packet.
- */
- for (f = 0; f < pkt->frames; f++) {
- int p, offset;
-
- if (written[f])
- continue;
-
- bio = pkt->r_bios[f];
- bio_init(bio, pd->bdev, bio->bi_inline_vecs, 1, REQ_OP_READ);
- bio->bi_iter.bi_sector = pkt->sector + f * (CD_FRAMESIZE >> 9);
- bio->bi_end_io = pkt_end_io_read;
- bio->bi_private = 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);
- if (!bio_add_page(bio, pkt->pages[p], CD_FRAMESIZE, offset))
- BUG();
-
- atomic_inc(&pkt->io_wait);
- pkt_queue_bio(pd, bio);
- frames_read++;
- }
-
-out_account:
- pkt_dbg(2, pd, "need %d frames for zone %llx\n",
- frames_read, (unsigned long long)pkt->sector);
- pd->stats.pkt_started++;
- pd->stats.secs_rg += frames_read * (CD_FRAMESIZE >> 9);
-}
-
-/*
- * Find a packet matching zone, or the least recently used packet if
- * there is no match.
- */
-static struct packet_data *pkt_get_packet_data(struct pktcdvd_device *pd, int zone)
-{
- struct packet_data *pkt;
-
- list_for_each_entry(pkt, &pd->cdrw.pkt_free_list, list) {
- if (pkt->sector == zone || pkt->list.next == &pd->cdrw.pkt_free_list) {
- list_del_init(&pkt->list);
- if (pkt->sector != zone)
- pkt->cache_valid = 0;
- return pkt;
- }
- }
- BUG();
- return NULL;
-}
-
-static void pkt_put_packet_data(struct pktcdvd_device *pd, struct packet_data *pkt)
-{
- if (pkt->cache_valid) {
- list_add(&pkt->list, &pd->cdrw.pkt_free_list);
- } else {
- list_add_tail(&pkt->list, &pd->cdrw.pkt_free_list);
- }
-}
-
-static inline void pkt_set_state(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
- pkt->state = state;
-}
-
-/*
- * Scan the work queue to see if we can start a new packet.
- * returns non-zero if any work was done.
- */
-static int pkt_handle_queue(struct pktcdvd_device *pd)
-{
- struct packet_data *pkt, *p;
- struct bio *bio = NULL;
- sector_t zone = 0; /* Suppress gcc warning */
- struct pkt_rb_node *node, *first_node;
- struct rb_node *n;
-
- atomic_set(&pd->scan_queue, 0);
-
- if (list_empty(&pd->cdrw.pkt_free_list)) {
- pkt_dbg(2, pd, "no pkt\n");
- return 0;
- }
-
- /*
- * Try to find a zone we are not already working on.
- */
- spin_lock(&pd->lock);
- first_node = pkt_rbtree_find(pd, pd->current_sector);
- if (!first_node) {
- n = rb_first(&pd->bio_queue);
- if (n)
- first_node = rb_entry(n, struct pkt_rb_node, rb_node);
- }
- node = first_node;
- while (node) {
- bio = node->bio;
- zone = get_zone(bio->bi_iter.bi_sector, pd);
- list_for_each_entry(p, &pd->cdrw.pkt_active_list, list) {
- if (p->sector == zone) {
- bio = NULL;
- goto try_next_bio;
- }
- }
- break;
-try_next_bio:
- node = pkt_rbtree_next(node);
- if (!node) {
- n = rb_first(&pd->bio_queue);
- if (n)
- node = rb_entry(n, struct pkt_rb_node, rb_node);
- }
- if (node == first_node)
- node = NULL;
- }
- spin_unlock(&pd->lock);
- if (!bio) {
- pkt_dbg(2, pd, "no bio\n");
- return 0;
- }
-
- pkt = pkt_get_packet_data(pd, zone);
-
- pd->current_sector = zone + pd->settings.size;
- pkt->sector = zone;
- BUG_ON(pkt->frames != pd->settings.size >> 2);
- pkt->write_size = 0;
-
- /*
- * Scan work queue for bios in the same zone and link them
- * to this packet.
- */
- spin_lock(&pd->lock);
- pkt_dbg(2, pd, "looking for zone %llx\n", (unsigned long long)zone);
- while ((node = pkt_rbtree_find(pd, zone)) != NULL) {
- 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)
- break;
- pkt_rbtree_erase(pd, node);
- spin_lock(&pkt->lock);
- bio_list_add(&pkt->orig_bios, bio);
- pkt->write_size += bio->bi_iter.bi_size / CD_FRAMESIZE;
- spin_unlock(&pkt->lock);
- }
- /* check write congestion marks, and if bio_queue_size is
- * below, wake up any waiters
- */
- if (pd->congested &&
- pd->bio_queue_size <= pd->write_congestion_off) {
- pd->congested = false;
- wake_up_var(&pd->congested);
- }
- spin_unlock(&pd->lock);
-
- pkt->sleep_time = max(PACKET_WAIT_TIME, 1);
- pkt_set_state(pkt, PACKET_WAITING_STATE);
- atomic_set(&pkt->run_sm, 1);
-
- spin_lock(&pd->cdrw.active_list_lock);
- list_add(&pkt->list, &pd->cdrw.pkt_active_list);
- spin_unlock(&pd->cdrw.active_list_lock);
-
- return 1;
-}
-
-/**
- * bio_list_copy_data - copy contents of data buffers from one chain of bios to
- * another
- * @src: source bio list
- * @dst: destination bio list
- *
- * Stops when it reaches the end of either the @src list or @dst list - that is,
- * copies min(src->bi_size, dst->bi_size) bytes (or the equivalent for lists of
- * bios).
- */
-static void bio_list_copy_data(struct bio *dst, struct bio *src)
-{
- struct bvec_iter src_iter = src->bi_iter;
- struct bvec_iter dst_iter = dst->bi_iter;
-
- while (1) {
- if (!src_iter.bi_size) {
- src = src->bi_next;
- if (!src)
- break;
-
- src_iter = src->bi_iter;
- }
-
- if (!dst_iter.bi_size) {
- dst = dst->bi_next;
- if (!dst)
- break;
-
- dst_iter = dst->bi_iter;
- }
-
- bio_copy_data_iter(dst, &dst_iter, src, &src_iter);
- }
-}
-
-/*
- * Assemble a bio to write one packet and queue the bio for processing
- * by the underlying block device.
- */
-static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt)
-{
- int f;
-
- bio_init(pkt->w_bio, pd->bdev, pkt->w_bio->bi_inline_vecs, pkt->frames,
- REQ_OP_WRITE);
- pkt->w_bio->bi_iter.bi_sector = pkt->sector;
- pkt->w_bio->bi_end_io = pkt_end_io_packet_write;
- pkt->w_bio->bi_private = pkt;
-
- /* XXX: locking? */
- for (f = 0; f < pkt->frames; f++) {
- struct page *page = pkt->pages[(f * CD_FRAMESIZE) / PAGE_SIZE];
- unsigned offset = (f * CD_FRAMESIZE) % PAGE_SIZE;
-
- if (!bio_add_page(pkt->w_bio, page, CD_FRAMESIZE, offset))
- BUG();
- }
- pkt_dbg(2, pd, "vcnt=%d\n", pkt->w_bio->bi_vcnt);
-
- /*
- * Fill-in bvec with data from orig_bios.
- */
- spin_lock(&pkt->lock);
- bio_list_copy_data(pkt->w_bio, pkt->orig_bios.head);
-
- pkt_set_state(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);
-
- if (test_bit(PACKET_MERGE_SEGS, &pd->flags) || (pkt->write_size < pkt->frames))
- pkt->cache_valid = 1;
- else
- pkt->cache_valid = 0;
-
- /* Start the write request */
- atomic_set(&pkt->io_wait, 1);
- pkt_queue_bio(pd, pkt->w_bio);
-}
-
-static void pkt_finish_packet(struct packet_data *pkt, blk_status_t status)
-{
- struct bio *bio;
-
- if (status)
- pkt->cache_valid = 0;
-
- /* Finish all bios corresponding to this packet */
- while ((bio = bio_list_pop(&pkt->orig_bios))) {
- bio->bi_status = status;
- bio_endio(bio);
- }
-}
-
-static void pkt_run_state_machine(struct pktcdvd_device *pd, struct packet_data *pkt)
-{
- pkt_dbg(2, pd, "pkt %d\n", pkt->id);
-
- for (;;) {
- switch (pkt->state) {
- case PACKET_WAITING_STATE:
- if ((pkt->write_size < pkt->frames) && (pkt->sleep_time > 0))
- return;
-
- pkt->sleep_time = 0;
- pkt_gather_data(pd, pkt);
- pkt_set_state(pkt, PACKET_READ_WAIT_STATE);
- break;
-
- case PACKET_READ_WAIT_STATE:
- if (atomic_read(&pkt->io_wait) > 0)
- return;
-
- if (atomic_read(&pkt->io_errors) > 0) {
- pkt_set_state(pkt, PACKET_RECOVERY_STATE);
- } else {
- pkt_start_write(pd, pkt);
- }
- break;
-
- case PACKET_WRITE_WAIT_STATE:
- if (atomic_read(&pkt->io_wait) > 0)
- return;
-
- if (!pkt->w_bio->bi_status) {
- pkt_set_state(pkt, PACKET_FINISHED_STATE);
- } else {
- pkt_set_state(pkt, PACKET_RECOVERY_STATE);
- }
- break;
-
- case PACKET_RECOVERY_STATE:
- pkt_dbg(2, pd, "No recovery possible\n");
- pkt_set_state(pkt, PACKET_FINISHED_STATE);
- break;
-
- case PACKET_FINISHED_STATE:
- pkt_finish_packet(pkt, pkt->w_bio->bi_status);
- return;
-
- default:
- BUG();
- break;
- }
- }
-}
-
-static void pkt_handle_packets(struct pktcdvd_device *pd)
-{
- struct packet_data *pkt, *next;
-
- /*
- * Run state machine for active packets
- */
- list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) {
- if (atomic_read(&pkt->run_sm) > 0) {
- atomic_set(&pkt->run_sm, 0);
- pkt_run_state_machine(pd, pkt);
- }
- }
-
- /*
- * Move no longer active packets to the free list
- */
- spin_lock(&pd->cdrw.active_list_lock);
- list_for_each_entry_safe(pkt, next, &pd->cdrw.pkt_active_list, list) {
- if (pkt->state == PACKET_FINISHED_STATE) {
- list_del(&pkt->list);
- pkt_put_packet_data(pd, pkt);
- pkt_set_state(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
- */
-static int kcdrwd(void *foobar)
-{
- struct pktcdvd_device *pd = foobar;
- struct packet_data *pkt;
- long min_sleep_time, residue;
-
- set_user_nice(current, MIN_NICE);
- set_freezable();
-
- for (;;) {
- DECLARE_WAITQUEUE(wait, current);
-
- /*
- * Wait until there is something to do
- */
- add_wait_queue(&pd->wqueue, &wait);
- for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
-
- /* Check if we need to run pkt_handle_queue */
- if (atomic_read(&pd->scan_queue) > 0)
- goto work_to_do;
-
- /* Check if we need to run the state machine for some packet */
- list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) {
- if (atomic_read(&pkt->run_sm) > 0)
- goto work_to_do;
- }
-
- /* Check if we need to process the iosched queues */
- if (atomic_read(&pd->iosched.attention) != 0)
- 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]);
- }
-
- min_sleep_time = MAX_SCHEDULE_TIMEOUT;
- list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) {
- if (pkt->sleep_time && pkt->sleep_time < min_sleep_time)
- min_sleep_time = pkt->sleep_time;
- }
-
- pkt_dbg(2, pd, "sleeping\n");
- residue = schedule_timeout(min_sleep_time);
- pkt_dbg(2, pd, "wake up\n");
-
- /* make swsusp happy with our thread */
- try_to_freeze();
-
- list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) {
- if (!pkt->sleep_time)
- continue;
- pkt->sleep_time -= min_sleep_time - residue;
- if (pkt->sleep_time <= 0) {
- pkt->sleep_time = 0;
- atomic_inc(&pkt->run_sm);
- }
- }
-
- if (kthread_should_stop())
- break;
- }
-work_to_do:
- set_current_state(TASK_RUNNING);
- remove_wait_queue(&pd->wqueue, &wait);
-
- if (kthread_should_stop())
- break;
-
- /*
- * if pkt_handle_queue returns true, we can queue
- * another request.
- */
- while (pkt_handle_queue(pd))
- ;
-
- /*
- * Handle packet state machine
- */
- pkt_handle_packets(pd);
-
- /*
- * Handle iosched queues
- */
- pkt_iosched_process_queue(pd);
- }
-
- return 0;
-}
-
-static void pkt_print_settings(struct pktcdvd_device *pd)
-{
- pkt_info(pd, "%s packets, %u blocks, Mode-%c disc\n",
- pd->settings.fp ? "Fixed" : "Variable",
- pd->settings.size >> 2,
- pd->settings.block_mode == 8 ? '1' : '2');
-}
-
-static int pkt_mode_sense(struct pktcdvd_device *pd, struct packet_command *cgc, int page_code, int page_control)
-{
- memset(cgc->cmd, 0, sizeof(cgc->cmd));
-
- 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;
- cgc->data_direction = CGC_DATA_READ;
- return pkt_generic_packet(pd, cgc);
-}
-
-static int pkt_mode_select(struct pktcdvd_device *pd, struct packet_command *cgc)
-{
- memset(cgc->cmd, 0, sizeof(cgc->cmd));
- 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;
- cgc->data_direction = CGC_DATA_WRITE;
- return pkt_generic_packet(pd, cgc);
-}
-
-static int pkt_get_disc_info(struct pktcdvd_device *pd, disc_information *di)
-{
- struct packet_command cgc;
- int ret;
-
- /* set up command and get the disc info */
- init_cdrom_command(&cgc, di, sizeof(*di), CGC_DATA_READ);
- cgc.cmd[0] = GPCMD_READ_DISC_INFO;
- cgc.cmd[8] = cgc.buflen = 2;
- cgc.quiet = 1;
-
- ret = pkt_generic_packet(pd, &cgc);
- if (ret)
- return ret;
-
- /* not all drives have the same disc_info length, so requeue
- * packet with the length the drive tells us it can supply
- */
- cgc.buflen = be16_to_cpu(di->disc_information_length) +
- sizeof(di->disc_information_length);
-
- if (cgc.buflen > sizeof(disc_information))
- cgc.buflen = sizeof(disc_information);
-
- cgc.cmd[8] = cgc.buflen;
- return pkt_generic_packet(pd, &cgc);
-}
-
-static int pkt_get_track_info(struct pktcdvd_device *pd, __u16 track, __u8 type, track_information *ti)
-{
- struct packet_command cgc;
- int ret;
-
- 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;
- cgc.cmd[8] = 8;
- cgc.quiet = 1;
-
- ret = pkt_generic_packet(pd, &cgc);
- if (ret)
- return ret;
-
- cgc.buflen = be16_to_cpu(ti->track_information_length) +
- sizeof(ti->track_information_length);
-
- if (cgc.buflen > sizeof(track_information))
- cgc.buflen = sizeof(track_information);
-
- cgc.cmd[8] = cgc.buflen;
- return pkt_generic_packet(pd, &cgc);
-}
-
-static noinline_for_stack int pkt_get_last_written(struct pktcdvd_device *pd,
- long *last_written)
-{
- disc_information di;
- track_information ti;
- __u32 last_track;
- int ret;
-
- ret = pkt_get_disc_info(pd, &di);
- if (ret)
- return ret;
-
- last_track = (di.last_track_msb << 8) | di.last_track_lsb;
- ret = pkt_get_track_info(pd, last_track, 1, &ti);
- if (ret)
- return ret;
-
- /* if this track is blank, try the previous. */
- if (ti.blank) {
- last_track--;
- ret = pkt_get_track_info(pd, last_track, 1, &ti);
- if (ret)
- return ret;
- }
-
- /* if last recorded field is valid, return it. */
- if (ti.lra_v) {
- *last_written = be32_to_cpu(ti.last_rec_address);
- } else {
- /* make it up instead */
- *last_written = be32_to_cpu(ti.track_start) +
- be32_to_cpu(ti.track_size);
- if (ti.free_blocks)
- *last_written -= (be32_to_cpu(ti.free_blocks) + 7);
- }
- return 0;
-}
-
-/*
- * write mode select package based on pd->settings
- */
-static noinline_for_stack int pkt_set_write_settings(struct pktcdvd_device *pd)
-{
- struct packet_command cgc;
- struct scsi_sense_hdr sshdr;
- write_param_page *wp;
- char buffer[128];
- int ret, size;
-
- /* doesn't apply to DVD+RW or DVD-RAM */
- if ((pd->mmc3_profile == 0x1a) || (pd->mmc3_profile == 0x12))
- return 0;
-
- memset(buffer, 0, sizeof(buffer));
- init_cdrom_command(&cgc, buffer, sizeof(*wp), CGC_DATA_READ);
- cgc.sshdr = &sshdr;
- ret = pkt_mode_sense(pd, &cgc, GPMODE_WRITE_PARMS_PAGE, 0);
- if (ret) {
- pkt_dump_sense(pd, &cgc);
- return ret;
- }
-
- size = 2 + ((buffer[0] << 8) | (buffer[1] & 0xff));
- pd->mode_offset = (buffer[6] << 8) | (buffer[7] & 0xff);
- if (size > sizeof(buffer))
- size = sizeof(buffer);
-
- /*
- * now get it all
- */
- init_cdrom_command(&cgc, buffer, size, CGC_DATA_READ);
- cgc.sshdr = &sshdr;
- ret = pkt_mode_sense(pd, &cgc, GPMODE_WRITE_PARMS_PAGE, 0);
- if (ret) {
- pkt_dump_sense(pd, &cgc);
- return ret;
- }
-
- /*
- * write page is offset header + block descriptor length
- */
- wp = (write_param_page *) &buffer[sizeof(struct mode_page_header) + pd->mode_offset];
-
- wp->fp = pd->settings.fp;
- wp->track_mode = pd->settings.track_mode;
- wp->write_type = pd->settings.write_type;
- wp->data_block_type = pd->settings.block_mode;
-
- wp->multi_session = 0;
-
-#ifdef PACKET_USE_LS
- wp->link_size = 7;
- wp->ls_v = 1;
-#endif
-
- if (wp->data_block_type == PACKET_BLOCK_MODE1) {
- wp->session_format = 0;
- wp->subhdr2 = 0x20;
- } else if (wp->data_block_type == PACKET_BLOCK_MODE2) {
- wp->session_format = 0x20;
- wp->subhdr2 = 8;
-#if 0
- wp->mcn[0] = 0x80;
- memcpy(&wp->mcn[1], PACKET_MCN, sizeof(wp->mcn) - 1);
-#endif
- } else {
- /*
- * paranoia
- */
- pkt_err(pd, "write mode wrong %d\n", wp->data_block_type);
- return 1;
- }
- wp->packet_size = cpu_to_be32(pd->settings.size >> 2);
-
- cgc.buflen = cgc.cmd[8] = size;
- ret = pkt_mode_select(pd, &cgc);
- if (ret) {
- pkt_dump_sense(pd, &cgc);
- return ret;
- }
-
- pkt_print_settings(pd);
- return 0;
-}
-
-/*
- * 1 -- we can write to this track, 0 -- we can't
- */
-static int pkt_writable_track(struct pktcdvd_device *pd, track_information *ti)
-{
- switch (pd->mmc3_profile) {
- case 0x1a: /* DVD+RW */
- case 0x12: /* DVD-RAM */
- /* The track is always writable on DVD+RW/DVD-RAM */
- return 1;
- default:
- break;
- }
-
- if (!ti->packet || !ti->fp)
- return 0;
-
- /*
- * "good" settings as per Mt Fuji.
- */
- if (ti->rt == 0 && ti->blank == 0)
- return 1;
-
- if (ti->rt == 0 && ti->blank == 1)
- return 1;
-
- if (ti->rt == 1 && ti->blank == 0)
- return 1;
-
- pkt_err(pd, "bad state %d-%d-%d\n", ti->rt, ti->blank, ti->packet);
- return 0;
-}
-
-/*
- * 1 -- we can write to this disc, 0 -- we can't
- */
-static int pkt_writable_disc(struct pktcdvd_device *pd, disc_information *di)
-{
- switch (pd->mmc3_profile) {
- case 0x0a: /* CD-RW */
- case 0xffff: /* MMC3 not supported */
- break;
- case 0x1a: /* DVD+RW */
- case 0x13: /* DVD-RW */
- case 0x12: /* DVD-RAM */
- return 1;
- default:
- pkt_dbg(2, pd, "Wrong disc profile (%x)\n",
- pd->mmc3_profile);
- return 0;
- }
-
- /*
- * for disc type 0xff we should probably reserve a new track.
- * 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");
- return 0;
- }
-
- if (di->disc_type != 0x20 && di->disc_type != 0) {
- pkt_err(pd, "wrong disc type (%x)\n", di->disc_type);
- return 0;
- }
-
- if (di->erasable == 0) {
- pkt_notice(pd, "disc not erasable\n");
- return 0;
- }
-
- if (di->border_status == PACKET_SESSION_RESERVED) {
- pkt_err(pd, "can't write to last track (reserved)\n");
- return 0;
- }
-
- return 1;
-}
-
-static noinline_for_stack int pkt_probe_settings(struct pktcdvd_device *pd)
-{
- struct packet_command cgc;
- unsigned char buf[12];
- disc_information di;
- track_information ti;
- int ret, track;
-
- init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
- 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];
-
- 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");
- return ret;
- }
-
- if (!pkt_writable_disc(pd, &di))
- return -EROFS;
-
- pd->type = di.erasable ? PACKET_CDRW : PACKET_CDR;
-
- 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");
- return ret;
- }
-
- if (!pkt_writable_track(pd, &ti)) {
- pkt_err(pd, "can't write to this track\n");
- return -EROFS;
- }
-
- /*
- * we keep packet size in 512 byte units, makes it easier to
- * deal with request calculations.
- */
- pd->settings.size = be32_to_cpu(ti.fixed_packet_size) << 2;
- if (pd->settings.size == 0) {
- pkt_notice(pd, "detected zero packet size!\n");
- return -ENXIO;
- }
- if (pd->settings.size > PACKET_MAX_SECTORS) {
- pkt_err(pd, "packet size is too big\n");
- return -EROFS;
- }
- pd->settings.fp = ti.fp;
- pd->offset = (be32_to_cpu(ti.track_start) << 2) & (pd->settings.size - 1);
-
- if (ti.nwa_v) {
- pd->nwa = be32_to_cpu(ti.next_writable);
- set_bit(PACKET_NWA_VALID, &pd->flags);
- }
-
- /*
- * in theory we could use lra on -RW media as well and just zero
- * blocks that haven't been written yet, but in practice that
- * is just a no-go. we'll use that for -R, naturally.
- */
- if (ti.lra_v) {
- pd->lra = be32_to_cpu(ti.last_rec_address);
- set_bit(PACKET_LRA_VALID, &pd->flags);
- } else {
- pd->lra = 0xffffffff;
- set_bit(PACKET_LRA_VALID, &pd->flags);
- }
-
- /*
- * fine for now
- */
- pd->settings.link_loss = 7;
- pd->settings.write_type = 0; /* packet */
- pd->settings.track_mode = ti.track_mode;
-
- /*
- * mode1 or mode2 disc
- */
- switch (ti.data_mode) {
- case PACKET_MODE1:
- pd->settings.block_mode = PACKET_BLOCK_MODE1;
- break;
- case PACKET_MODE2:
- pd->settings.block_mode = PACKET_BLOCK_MODE2;
- break;
- default:
- pkt_err(pd, "unknown data mode\n");
- return -EROFS;
- }
- return 0;
-}
-
-/*
- * enable/disable write caching on drive
- */
-static noinline_for_stack int pkt_write_caching(struct pktcdvd_device *pd,
- int set)
-{
- struct packet_command cgc;
- struct scsi_sense_hdr sshdr;
- unsigned char buf[64];
- int ret;
-
- init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_READ);
- cgc.sshdr = &sshdr;
- cgc.buflen = pd->mode_offset + 12;
-
- /*
- * caching mode page might not be there, so quiet this command
- */
- cgc.quiet = 1;
-
- ret = pkt_mode_sense(pd, &cgc, GPMODE_WCACHING_PAGE, 0);
- if (ret)
- return ret;
-
- buf[pd->mode_offset + 10] |= (!!set << 2);
-
- cgc.buflen = cgc.cmd[8] = 2 + ((buf[0] << 8) | (buf[1] & 0xff));
- ret = pkt_mode_select(pd, &cgc);
- if (ret) {
- pkt_err(pd, "write caching control failed\n");
- pkt_dump_sense(pd, &cgc);
- } else if (!ret && set)
- pkt_notice(pd, "enabled write caching\n");
- return ret;
-}
-
-static int pkt_lock_door(struct pktcdvd_device *pd, int lockflag)
-{
- struct packet_command cgc;
-
- init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
- cgc.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL;
- cgc.cmd[4] = lockflag ? 1 : 0;
- return pkt_generic_packet(pd, &cgc);
-}
-
-/*
- * Returns drive maximum write speed
- */
-static noinline_for_stack int pkt_get_max_speed(struct pktcdvd_device *pd,
- unsigned *write_speed)
-{
- struct packet_command cgc;
- struct scsi_sense_hdr sshdr;
- unsigned char buf[256+18];
- unsigned char *cap_buf;
- int ret, offset;
-
- cap_buf = &buf[sizeof(struct mode_page_header) + pd->mode_offset];
- init_cdrom_command(&cgc, buf, sizeof(buf), CGC_DATA_UNKNOWN);
- cgc.sshdr = &sshdr;
-
- ret = pkt_mode_sense(pd, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
- if (ret) {
- cgc.buflen = pd->mode_offset + cap_buf[1] + 2 +
- sizeof(struct mode_page_header);
- ret = pkt_mode_sense(pd, &cgc, GPMODE_CAPABILITIES_PAGE, 0);
- if (ret) {
- pkt_dump_sense(pd, &cgc);
- return ret;
- }
- }
-
- offset = 20; /* Obsoleted field, used by older drives */
- if (cap_buf[1] >= 28)
- offset = 28; /* Current write speed selected */
- if (cap_buf[1] >= 30) {
- /* If the drive reports at least one "Logical Unit Write
- * 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];
- if (num_spdb > 0)
- offset = 34;
- }
-
- *write_speed = (cap_buf[offset] << 8) | cap_buf[offset + 1];
- return 0;
-}
-
-/* These tables from cdrecord - I don't have orange book */
-/* standard speed CD-RW (1-4x) */
-static char clv_to_speed[16] = {
- /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
- 0, 2, 4, 6, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-/* high speed CD-RW (-10x) */
-static char hs_clv_to_speed[16] = {
- /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
- 0, 2, 4, 6, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-/* ultra high speed CD-RW */
-static char us_clv_to_speed[16] = {
- /* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
- 0, 2, 4, 8, 0, 0,16, 0,24,32,40,48, 0, 0, 0, 0
-};
-
-/*
- * reads the maximum media speed from ATIP
- */
-static noinline_for_stack int pkt_media_speed(struct pktcdvd_device *pd,
- unsigned *speed)
-{
- struct packet_command cgc;
- struct scsi_sense_hdr sshdr;
- unsigned char buf[64];
- unsigned int size, st, sp;
- int ret;
-
- init_cdrom_command(&cgc, buf, 2, CGC_DATA_READ);
- cgc.sshdr = &sshdr;
- cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
- cgc.cmd[1] = 2;
- cgc.cmd[2] = 4; /* READ ATIP */
- cgc.cmd[8] = 2;
- ret = pkt_generic_packet(pd, &cgc);
- if (ret) {
- pkt_dump_sense(pd, &cgc);
- return ret;
- }
- size = ((unsigned int) buf[0]<<8) + buf[1] + 2;
- if (size > sizeof(buf))
- size = sizeof(buf);
-
- init_cdrom_command(&cgc, buf, size, CGC_DATA_READ);
- cgc.sshdr = &sshdr;
- cgc.cmd[0] = GPCMD_READ_TOC_PMA_ATIP;
- cgc.cmd[1] = 2;
- cgc.cmd[2] = 4;
- cgc.cmd[8] = size;
- ret = pkt_generic_packet(pd, &cgc);
- if (ret) {
- pkt_dump_sense(pd, &cgc);
- return ret;
- }
-
- if (!(buf[6] & 0x40)) {
- pkt_notice(pd, "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");
- return 1;
- }
-
- st = (buf[6] >> 3) & 0x7; /* disc sub-type */
-
- sp = buf[16] & 0xf; /* max speed from ATIP A1 field */
-
- /* Info from cdrecord */
- switch (st) {
- case 0: /* standard speed */
- *speed = clv_to_speed[sp];
- break;
- case 1: /* high speed */
- *speed = hs_clv_to_speed[sp];
- break;
- case 2: /* ultra high speed */
- *speed = us_clv_to_speed[sp];
- break;
- default:
- pkt_notice(pd, "unknown disc sub-type %d\n", st);
- return 1;
- }
- if (*speed) {
- pkt_info(pd, "maximum media speed: %d\n", *speed);
- return 0;
- } else {
- pkt_notice(pd, "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 packet_command cgc;
- struct scsi_sense_hdr sshdr;
- int ret;
-
- pkt_dbg(2, pd, "Performing OPC\n");
-
- init_cdrom_command(&cgc, NULL, 0, CGC_DATA_NONE);
- cgc.sshdr = &sshdr;
- cgc.timeout = 60*HZ;
- cgc.cmd[0] = GPCMD_SEND_OPC;
- cgc.cmd[1] = 1;
- ret = pkt_generic_packet(pd, &cgc);
- if (ret)
- pkt_dump_sense(pd, &cgc);
- return ret;
-}
-
-static int pkt_open_write(struct pktcdvd_device *pd)
-{
- 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");
- return ret;
- }
-
- ret = pkt_set_write_settings(pd);
- if (ret) {
- pkt_dbg(1, pd, "failed saving write settings\n");
- return -EIO;
- }
-
- pkt_write_caching(pd, USE_WCACHING);
-
- ret = pkt_get_max_speed(pd, &write_speed);
- if (ret)
- write_speed = 16 * 177;
- switch (pd->mmc3_profile) {
- case 0x13: /* DVD-RW */
- case 0x1a: /* DVD+RW */
- case 0x12: /* DVD-RAM */
- pkt_dbg(1, pd, "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);
- 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");
- 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");
- }
-
- return 0;
-}
-
-/*
- * called at open time.
- */
-static int pkt_open_dev(struct pktcdvd_device *pd, fmode_t write)
-{
- int ret;
- long lba;
- struct request_queue *q;
- struct block_device *bdev;
-
- /*
- * We need to re-open the cdrom device without O_NONBLOCK to be able
- * 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);
- if (IS_ERR(bdev)) {
- ret = PTR_ERR(bdev);
- goto out;
- }
-
- ret = pkt_get_last_written(pd, &lba);
- if (ret) {
- pkt_err(pd, "pkt_get_last_written failed\n");
- goto out_putdev;
- }
-
- set_capacity(pd->disk, lba << 2);
- set_capacity_and_notify(pd->bdev->bd_disk, lba << 2);
-
- q = bdev_get_queue(pd->bdev);
- if (write) {
- ret = pkt_open_write(pd);
- if (ret)
- goto out_putdev;
- /*
- * Some CDRW drives can not handle writes larger than one packet,
- * even if the size is a multiple of the packet size.
- */
- blk_queue_max_hw_sectors(q, pd->settings.size);
- set_bit(PACKET_WRITABLE, &pd->flags);
- } else {
- pkt_set_speed(pd, MAX_SPEED, MAX_SPEED);
- clear_bit(PACKET_WRITABLE, &pd->flags);
- }
-
- ret = pkt_set_segment_merging(pd, q);
- if (ret)
- goto out_putdev;
-
- if (write) {
- if (!pkt_grow_pktlist(pd, CONFIG_CDROM_PKTCDVD_BUFFERS)) {
- pkt_err(pd, "not enough memory for buffers\n");
- ret = -ENOMEM;
- goto out_putdev;
- }
- pkt_info(pd, "%lukB available on disc\n", lba << 1);
- }
-
- return 0;
-
-out_putdev:
- blkdev_put(bdev, FMODE_READ | FMODE_EXCL);
-out:
- return ret;
-}
-
-/*
- * called when the device is closed. makes sure that the device flushes
- * the internal cache before we close.
- */
-static void pkt_release_dev(struct pktcdvd_device *pd, int flush)
-{
- if (flush && pkt_flush_cache(pd))
- pkt_dbg(1, pd, "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);
-
- pkt_shrink_pktlist(pd);
-}
-
-static struct pktcdvd_device *pkt_find_dev_from_minor(unsigned int dev_minor)
-{
- if (dev_minor >= MAX_WRITERS)
- return NULL;
-
- dev_minor = array_index_nospec(dev_minor, MAX_WRITERS);
- return pkt_devs[dev_minor];
-}
-
-static int pkt_open(struct block_device *bdev, fmode_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));
- if (!pd) {
- ret = -ENODEV;
- goto out;
- }
- BUG_ON(pd->refcnt < 0);
-
- pd->refcnt++;
- if (pd->refcnt > 1) {
- if ((mode & FMODE_WRITE) &&
- !test_bit(PACKET_WRITABLE, &pd->flags)) {
- ret = -EBUSY;
- goto out_dec;
- }
- } else {
- ret = pkt_open_dev(pd, mode & FMODE_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);
- }
-
- mutex_unlock(&ctl_mutex);
- mutex_unlock(&pktcdvd_mutex);
- return 0;
-
-out_dec:
- pd->refcnt--;
-out:
- mutex_unlock(&ctl_mutex);
- mutex_unlock(&pktcdvd_mutex);
- return ret;
-}
-
-static void pkt_close(struct gendisk *disk, fmode_t mode)
-{
- struct pktcdvd_device *pd = disk->private_data;
-
- mutex_lock(&pktcdvd_mutex);
- mutex_lock(&ctl_mutex);
- pd->refcnt--;
- BUG_ON(pd->refcnt < 0);
- if (pd->refcnt == 0) {
- int flush = test_bit(PACKET_WRITABLE, &pd->flags);
- pkt_release_dev(pd, flush);
- }
- mutex_unlock(&ctl_mutex);
- mutex_unlock(&pktcdvd_mutex);
-}
-
-
-static void pkt_end_io_read_cloned(struct bio *bio)
-{
- struct packet_stacked_data *psd = bio->bi_private;
- struct pktcdvd_device *pd = psd->pd;
-
- psd->bio->bi_status = bio->bi_status;
- bio_put(bio);
- bio_endio(psd->bio);
- mempool_free(psd, &psd_pool);
- pkt_bio_finished(pd);
-}
-
-static void pkt_make_request_read(struct pktcdvd_device *pd, struct bio *bio)
-{
- struct bio *cloned_bio =
- bio_alloc_clone(pd->bdev, bio, GFP_NOIO, &pkt_bio_set);
- struct packet_stacked_data *psd = mempool_alloc(&psd_pool, GFP_NOIO);
-
- psd->pd = pd;
- psd->bio = bio;
- cloned_bio->bi_private = psd;
- cloned_bio->bi_end_io = pkt_end_io_read_cloned;
- pd->stats.secs_r += bio_sectors(bio);
- pkt_queue_bio(pd, cloned_bio);
-}
-
-static void pkt_make_request_write(struct request_queue *q, struct bio *bio)
-{
- struct pktcdvd_device *pd = q->queuedata;
- sector_t zone;
- struct packet_data *pkt;
- int was_empty, blocked_bio;
- struct pkt_rb_node *node;
-
- zone = get_zone(bio->bi_iter.bi_sector, pd);
-
- /*
- * If we find a matching packet in state WAITING or READ_WAIT, we can
- * just append this bio to that packet.
- */
- spin_lock(&pd->cdrw.active_list_lock);
- blocked_bio = 0;
- list_for_each_entry(pkt, &pd->cdrw.pkt_active_list, list) {
- if (pkt->sector == zone) {
- spin_lock(&pkt->lock);
- if ((pkt->state == PACKET_WAITING_STATE) ||
- (pkt->state == PACKET_READ_WAIT_STATE)) {
- bio_list_add(&pkt->orig_bios, bio);
- pkt->write_size +=
- bio->bi_iter.bi_size / CD_FRAMESIZE;
- if ((pkt->write_size >= pkt->frames) &&
- (pkt->state == PACKET_WAITING_STATE)) {
- atomic_inc(&pkt->run_sm);
- wake_up(&pd->wqueue);
- }
- spin_unlock(&pkt->lock);
- spin_unlock(&pd->cdrw.active_list_lock);
- return;
- } else {
- blocked_bio = 1;
- }
- spin_unlock(&pkt->lock);
- }
- }
- spin_unlock(&pd->cdrw.active_list_lock);
-
- /*
- * Test if there is enough room left in the bio work queue
- * (queue size >= congestion on mark).
- * If not, wait till the work queue size is below the congestion off mark.
- */
- spin_lock(&pd->lock);
- if (pd->write_congestion_on > 0
- && pd->bio_queue_size >= pd->write_congestion_on) {
- struct wait_bit_queue_entry wqe;
-
- init_wait_var_entry(&wqe, &pd->congested, 0);
- for (;;) {
- prepare_to_wait_event(__var_waitqueue(&pd->congested),
- &wqe.wq_entry,
- TASK_UNINTERRUPTIBLE);
- if (pd->bio_queue_size <= pd->write_congestion_off)
- break;
- pd->congested = true;
- spin_unlock(&pd->lock);
- schedule();
- spin_lock(&pd->lock);
- }
- }
- spin_unlock(&pd->lock);
-
- /*
- * No matching packet found. Store the bio in the work queue.
- */
- node = mempool_alloc(&pd->rb_pool, GFP_NOIO);
- node->bio = bio;
- spin_lock(&pd->lock);
- BUG_ON(pd->bio_queue_size < 0);
- was_empty = (pd->bio_queue_size == 0);
- pkt_rbtree_insert(pd, node);
- spin_unlock(&pd->lock);
-
- /*
- * Wake up the worker thread.
- */
- atomic_set(&pd->scan_queue, 1);
- if (was_empty) {
- /* This wake_up is required for correct operation */
- wake_up(&pd->wqueue);
- } else if (!list_empty(&pd->cdrw.pkt_free_list) && !blocked_bio) {
- /*
- * This wake up is not required for correct operation,
- * but improves performance in some cases.
- */
- wake_up(&pd->wqueue);
- }
-}
-
-static void pkt_submit_bio(struct bio *bio)
-{
- struct pktcdvd_device *pd = bio->bi_bdev->bd_disk->queue->queuedata;
- struct bio *split;
-
- bio = bio_split_to_limits(bio);
-
- pkt_dbg(2, pd, "start = %6llx stop = %6llx\n",
- (unsigned long long)bio->bi_iter.bi_sector,
- (unsigned long long)bio_end_sector(bio));
-
- /*
- * Clone READ bios so we can have our own bi_end_io callback.
- */
- if (bio_data_dir(bio) == READ) {
- pkt_make_request_read(pd, bio);
- return;
- }
-
- if (!test_bit(PACKET_WRITABLE, &pd->flags)) {
- pkt_notice(pd, "WRITE for ro device (%llu)\n",
- (unsigned long long)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");
- goto end_io;
- }
-
- do {
- sector_t zone = get_zone(bio->bi_iter.bi_sector, pd);
- sector_t last_zone = get_zone(bio_end_sector(bio) - 1, pd);
-
- if (last_zone != zone) {
- BUG_ON(last_zone != zone + pd->settings.size);
-
- split = bio_split(bio, last_zone -
- bio->bi_iter.bi_sector,
- GFP_NOIO, &pkt_bio_set);
- bio_chain(split, bio);
- } else {
- split = bio;
- }
-
- pkt_make_request_write(bio->bi_bdev->bd_disk->queue, split);
- } while (split != bio);
-
- return;
-end_io:
- bio_io_error(bio);
-}
-
-static void pkt_init_queue(struct pktcdvd_device *pd)
-{
- struct request_queue *q = pd->disk->queue;
-
- blk_queue_logical_block_size(q, CD_FRAMESIZE);
- blk_queue_max_hw_sectors(q, PACKET_MAX_SECTORS);
- 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)
-{
- int i;
- struct block_device *bdev;
- struct scsi_device *sdev;
-
- if (pd->pkt_dev == dev) {
- pkt_err(pd, "recursive setup not allowed\n");
- return -EBUSY;
- }
- for (i = 0; i < MAX_WRITERS; i++) {
- struct pktcdvd_device *pd2 = pkt_devs[i];
- if (!pd2)
- continue;
- if (pd2->bdev->bd_dev == dev) {
- pkt_err(pd, "%pg already setup\n", pd2->bdev);
- return -EBUSY;
- }
- if (pd2->pkt_dev == dev) {
- pkt_err(pd, "can't chain pktcdvd devices\n");
- return -EBUSY;
- }
- }
-
- bdev = blkdev_get_by_dev(dev, FMODE_READ | FMODE_NDELAY, 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);
- return -EINVAL;
- }
- put_device(&sdev->sdev_gendev);
-
- /* This is safe, since we have a reference from open(). */
- __module_get(THIS_MODULE);
-
- pd->bdev = bdev;
- set_blocksize(bdev, CD_FRAMESIZE);
-
- pkt_init_queue(pd);
-
- atomic_set(&pd->cdrw.pending_bios, 0);
- pd->cdrw.thread = kthread_run(kcdrwd, pd, "%s", pd->name);
- if (IS_ERR(pd->cdrw.thread)) {
- pkt_err(pd, "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);
- return 0;
-
-out_mem:
- blkdev_put(bdev, FMODE_READ | FMODE_NDELAY);
- /* 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)
-{
- struct pktcdvd_device *pd = bdev->bd_disk->private_data;
- int ret;
-
- pkt_dbg(2, pd, "cmd %x, dev %d:%d\n",
- cmd, MAJOR(bdev->bd_dev), MINOR(bdev->bd_dev));
-
- mutex_lock(&pktcdvd_mutex);
- switch (cmd) {
- case CDROMEJECT:
- /*
- * The door gets locked when the device is opened, so we
- * have to unlock it or else the eject command fails.
- */
- if (pd->refcnt == 1)
- pkt_lock_door(pd, 0);
- fallthrough;
- /*
- * forward selected CDROM ioctls to CD-ROM, for UDF
- */
- case CDROMMULTISESSION:
- case CDROMREADTOCENTRY:
- case CDROM_LAST_WRITTEN:
- case CDROM_SEND_PACKET:
- case SCSI_IOCTL_SEND_COMMAND:
- if (!bdev->bd_disk->fops->ioctl)
- ret = -ENOTTY;
- else
- ret = bdev->bd_disk->fops->ioctl(bdev, mode, cmd, arg);
- break;
- default:
- pkt_dbg(2, pd, "Unknown ioctl (%x)\n", cmd);
- ret = -ENOTTY;
- }
- mutex_unlock(&pktcdvd_mutex);
-
- return ret;
-}
-
-static unsigned int pkt_check_events(struct gendisk *disk,
- unsigned int clearing)
-{
- struct pktcdvd_device *pd = disk->private_data;
- struct gendisk *attached_disk;
-
- if (!pd)
- return 0;
- if (!pd->bdev)
- return 0;
- attached_disk = pd->bdev->bd_disk;
- if (!attached_disk || !attached_disk->fops->check_events)
- return 0;
- return attached_disk->fops->check_events(attached_disk, clearing);
-}
-
-static char *pkt_devnode(struct gendisk *disk, umode_t *mode)
-{
- return kasprintf(GFP_KERNEL, "pktcdvd/%s", disk->disk_name);
-}
-
-static const struct block_device_operations pktcdvd_ops = {
- .owner = THIS_MODULE,
- .submit_bio = pkt_submit_bio,
- .open = pkt_open,
- .release = pkt_close,
- .ioctl = pkt_ioctl,
- .compat_ioctl = blkdev_compat_ptr_ioctl,
- .check_events = pkt_check_events,
- .devnode = pkt_devnode,
-};
-
-/*
- * Set up mapping from pktcdvd device to CD-ROM device.
- */
-static int pkt_setup_dev(dev_t dev, dev_t* pkt_dev)
-{
- int idx;
- int ret = -ENOMEM;
- struct pktcdvd_device *pd;
- struct gendisk *disk;
-
- mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
-
- for (idx = 0; idx < MAX_WRITERS; idx++)
- if (!pkt_devs[idx])
- break;
- if (idx == MAX_WRITERS) {
- pr_err("max %d writers supported\n", MAX_WRITERS);
- ret = -EBUSY;
- goto out_mutex;
- }
-
- pd = kzalloc(sizeof(struct pktcdvd_device), GFP_KERNEL);
- if (!pd)
- goto out_mutex;
-
- ret = mempool_init_kmalloc_pool(&pd->rb_pool, PKT_RB_POOL_SIZE,
- sizeof(struct pkt_rb_node));
- if (ret)
- goto out_mem;
-
- INIT_LIST_HEAD(&pd->cdrw.pkt_free_list);
- INIT_LIST_HEAD(&pd->cdrw.pkt_active_list);
- spin_lock_init(&pd->cdrw.active_list_lock);
-
- spin_lock_init(&pd->lock);
- 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;
-
- pd->write_congestion_on = write_congestion_on;
- pd->write_congestion_off = write_congestion_off;
-
- ret = -ENOMEM;
- disk = blk_alloc_disk(NUMA_NO_NODE);
- if (!disk)
- goto out_mem;
- pd->disk = disk;
- disk->major = pktdev_major;
- disk->first_minor = idx;
- disk->minors = 1;
- disk->fops = &pktcdvd_ops;
- disk->flags = GENHD_FL_REMOVABLE | GENHD_FL_NO_PART;
- strcpy(disk->disk_name, pd->name);
- disk->private_data = pd;
-
- pd->pkt_dev = MKDEV(pktdev_major, idx);
- ret = pkt_new_dev(pd, dev);
- if (ret)
- goto out_mem2;
-
- /* inherit events of the host device */
- disk->events = pd->bdev->bd_disk->events;
-
- ret = add_disk(disk);
- if (ret)
- goto out_mem2;
-
- pkt_sysfs_dev_new(pd);
- pkt_debugfs_dev_new(pd);
-
- pkt_devs[idx] = pd;
- if (pkt_dev)
- *pkt_dev = pd->pkt_dev;
-
- mutex_unlock(&ctl_mutex);
- return 0;
-
-out_mem2:
- put_disk(disk);
-out_mem:
- mempool_exit(&pd->rb_pool);
- kfree(pd);
-out_mutex:
- mutex_unlock(&ctl_mutex);
- pr_err("setup of pktcdvd device failed\n");
- return ret;
-}
-
-/*
- * Tear down mapping from pktcdvd device to CD-ROM device.
- */
-static int pkt_remove_dev(dev_t pkt_dev)
-{
- struct pktcdvd_device *pd;
- int idx;
- int ret = 0;
-
- mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
-
- for (idx = 0; idx < MAX_WRITERS; idx++) {
- pd = pkt_devs[idx];
- if (pd && (pd->pkt_dev == pkt_dev))
- break;
- }
- if (idx == MAX_WRITERS) {
- pr_debug("dev not setup\n");
- ret = -ENXIO;
- goto out;
- }
-
- if (pd->refcnt > 0) {
- ret = -EBUSY;
- goto out;
- }
- if (!IS_ERR(pd->cdrw.thread))
- kthread_stop(pd->cdrw.thread);
-
- pkt_devs[idx] = NULL;
-
- pkt_debugfs_dev_remove(pd);
- pkt_sysfs_dev_remove(pd);
-
- blkdev_put(pd->bdev, FMODE_READ | FMODE_NDELAY);
-
- remove_proc_entry(pd->name, pkt_proc);
- pkt_dbg(1, pd, "writer unmapped\n");
-
- del_gendisk(pd->disk);
- put_disk(pd->disk);
-
- mempool_exit(&pd->rb_pool);
- kfree(pd);
-
- /* This is safe: open() is still holding a reference. */
- module_put(THIS_MODULE);
-
-out:
- mutex_unlock(&ctl_mutex);
- return ret;
-}
-
-static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd)
-{
- struct pktcdvd_device *pd;
-
- mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
-
- pd = pkt_find_dev_from_minor(ctrl_cmd->dev_index);
- if (pd) {
- ctrl_cmd->dev = new_encode_dev(pd->bdev->bd_dev);
- ctrl_cmd->pkt_dev = new_encode_dev(pd->pkt_dev);
- } else {
- ctrl_cmd->dev = 0;
- ctrl_cmd->pkt_dev = 0;
- }
- ctrl_cmd->num_devices = MAX_WRITERS;
-
- mutex_unlock(&ctl_mutex);
-}
-
-static long pkt_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- void __user *argp = (void __user *)arg;
- struct pkt_ctrl_command ctrl_cmd;
- int ret = 0;
- dev_t pkt_dev = 0;
-
- if (cmd != PACKET_CTRL_CMD)
- return -ENOTTY;
-
- if (copy_from_user(&ctrl_cmd, argp, sizeof(struct pkt_ctrl_command)))
- return -EFAULT;
-
- switch (ctrl_cmd.command) {
- case PKT_CTRL_CMD_SETUP:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- ret = pkt_setup_dev(new_decode_dev(ctrl_cmd.dev), &pkt_dev);
- ctrl_cmd.pkt_dev = new_encode_dev(pkt_dev);
- break;
- case PKT_CTRL_CMD_TEARDOWN:
- if (!capable(CAP_SYS_ADMIN))
- return -EPERM;
- ret = pkt_remove_dev(new_decode_dev(ctrl_cmd.pkt_dev));
- break;
- case PKT_CTRL_CMD_STATUS:
- pkt_get_status(&ctrl_cmd);
- break;
- default:
- return -ENOTTY;
- }
-
- if (copy_to_user(argp, &ctrl_cmd, sizeof(struct pkt_ctrl_command)))
- return -EFAULT;
- return ret;
-}
-
-#ifdef CONFIG_COMPAT
-static long pkt_ctl_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- return pkt_ctl_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
-}
-#endif
-
-static const struct file_operations pkt_ctl_fops = {
- .open = nonseekable_open,
- .unlocked_ioctl = pkt_ctl_ioctl,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = pkt_ctl_compat_ioctl,
-#endif
- .owner = THIS_MODULE,
- .llseek = no_llseek,
-};
-
-static struct miscdevice pkt_misc = {
- .minor = MISC_DYNAMIC_MINOR,
- .name = DRIVER_NAME,
- .nodename = "pktcdvd/control",
- .fops = &pkt_ctl_fops
-};
-
-static int __init pkt_init(void)
-{
- int ret;
-
- mutex_init(&ctl_mutex);
-
- ret = mempool_init_kmalloc_pool(&psd_pool, PSD_POOL_SIZE,
- sizeof(struct packet_stacked_data));
- if (ret)
- return ret;
- ret = bioset_init(&pkt_bio_set, BIO_POOL_SIZE, 0, 0);
- if (ret) {
- mempool_exit(&psd_pool);
- return ret;
- }
-
- ret = register_blkdev(pktdev_major, DRIVER_NAME);
- if (ret < 0) {
- pr_err("unable to register block device\n");
- goto out2;
- }
- if (!pktdev_major)
- pktdev_major = ret;
-
- ret = pkt_sysfs_init();
- if (ret)
- goto out;
-
- pkt_debugfs_init();
-
- ret = misc_register(&pkt_misc);
- if (ret) {
- pr_err("unable to register misc device\n");
- goto out_misc;
- }
-
- pkt_proc = proc_mkdir("driver/"DRIVER_NAME, NULL);
-
- return 0;
-
-out_misc:
- pkt_debugfs_cleanup();
- pkt_sysfs_cleanup();
-out:
- unregister_blkdev(pktdev_major, DRIVER_NAME);
-out2:
- mempool_exit(&psd_pool);
- bioset_exit(&pkt_bio_set);
- return ret;
-}
-
-static void __exit pkt_exit(void)
-{
- remove_proc_entry("driver/"DRIVER_NAME, NULL);
- misc_deregister(&pkt_misc);
-
- pkt_debugfs_cleanup();
- pkt_sysfs_cleanup();
-
- unregister_blkdev(pktdev_major, DRIVER_NAME);
- mempool_exit(&psd_pool);
- bioset_exit(&pkt_bio_set);
-}
-
-MODULE_DESCRIPTION("Packet writing layer for CD/DVD drives");
-MODULE_AUTHOR("Jens Axboe <axboe@suse.de>");
-MODULE_LICENSE("GPL");
-
-module_init(pkt_init);
-module_exit(pkt_exit);
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 19da5defd734..68bd2f7961b3 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -512,7 +512,7 @@ static void virtblk_free_disk(struct gendisk *disk)
{
struct virtio_blk *vblk = disk->private_data;
- ida_simple_remove(&vd_index_ida, vblk->index);
+ ida_free(&vd_index_ida, vblk->index);
mutex_destroy(&vblk->vdev_mutex);
kfree(vblk);
}
@@ -902,8 +902,8 @@ static int virtblk_probe(struct virtio_device *vdev)
return -EINVAL;
}
- err = ida_simple_get(&vd_index_ida, 0, minor_to_index(1 << MINORBITS),
- GFP_KERNEL);
+ err = ida_alloc_range(&vd_index_ida, 0,
+ minor_to_index(1 << MINORBITS) - 1, GFP_KERNEL);
if (err < 0)
goto out;
index = err;
@@ -1163,7 +1163,7 @@ out_free_vq:
out_free_vblk:
kfree(vblk);
out_free_index:
- ida_simple_remove(&vd_index_ida, index);
+ ida_free(&vd_index_ida, index);
out:
return err;
}
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c
index 35b9bcad9db9..b28489290323 100644
--- a/drivers/block/xen-blkfront.c
+++ b/drivers/block/xen-blkfront.c
@@ -2129,7 +2129,6 @@ static void blkfront_closing(struct blkfront_info *info)
if (info->rq && info->gd) {
blk_mq_stop_hw_queues(info->rq);
blk_mark_disk_dead(info->gd);
- set_capacity(info->gd, 0);
}
for_each_rinfo(info, rinfo, i) {
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index 3df9e692756a..6eddc23e49d9 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -696,9 +696,15 @@ static int qca_close(struct hci_uart *hu)
skb_queue_purge(&qca->tx_wait_q);
skb_queue_purge(&qca->txq);
skb_queue_purge(&qca->rx_memdump_q);
+ /*
+ * Shut the timers down so they can't be rearmed when
+ * destroy_workqueue() drains pending work which in turn might try
+ * to arm a timer. After shutdown rearm attempts are silently
+ * ignored by the timer core code.
+ */
+ timer_shutdown_sync(&qca->tx_idle_timer);
+ timer_shutdown_sync(&qca->wake_retrans_timer);
destroy_workqueue(qca->workqueue);
- del_timer_sync(&qca->tx_idle_timer);
- del_timer_sync(&qca->wake_retrans_timer);
qca->hu = NULL;
kfree_skb(qca->rx_skb);
diff --git a/drivers/bus/fsl-mc/Kconfig b/drivers/bus/fsl-mc/Kconfig
index b1fd55901c50..9492342e7d13 100644
--- a/drivers/bus/fsl-mc/Kconfig
+++ b/drivers/bus/fsl-mc/Kconfig
@@ -8,7 +8,7 @@
config FSL_MC_BUS
bool "QorIQ DPAA2 fsl-mc bus driver"
depends on OF && (ARCH_LAYERSCAPE || (COMPILE_TEST && (ARM || ARM64 || X86_LOCAL_APIC || PPC)))
- select GENERIC_MSI_IRQ_DOMAIN
+ select GENERIC_MSI_IRQ
help
Driver to enable the bus infrastructure for the QorIQ DPAA2
architecture. The fsl-mc bus driver handles discovery of
diff --git a/drivers/bus/fsl-mc/dprc-driver.c b/drivers/bus/fsl-mc/dprc-driver.c
index 5e70f9775a0e..4c84be378bf2 100644
--- a/drivers/bus/fsl-mc/dprc-driver.c
+++ b/drivers/bus/fsl-mc/dprc-driver.c
@@ -11,7 +11,6 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
-#include <linux/msi.h>
#include <linux/fsl/mc.h>
#include "fsl-mc-private.h"
diff --git a/drivers/bus/fsl-mc/fsl-mc-bus.c b/drivers/bus/fsl-mc/fsl-mc-bus.c
index 6143dbf31f31..774f307844b4 100644
--- a/drivers/bus/fsl-mc/fsl-mc-bus.c
+++ b/drivers/bus/fsl-mc/fsl-mc-bus.c
@@ -17,7 +17,6 @@
#include <linux/slab.h>
#include <linux/limits.h>
#include <linux/bitops.h>
-#include <linux/msi.h>
#include <linux/dma-mapping.h>
#include <linux/acpi.h>
#include <linux/iommu.h>
diff --git a/drivers/bus/fsl-mc/fsl-mc-msi.c b/drivers/bus/fsl-mc/fsl-mc-msi.c
index 0cfe859a4ac4..f3f8af9426c9 100644
--- a/drivers/bus/fsl-mc/fsl-mc-msi.c
+++ b/drivers/bus/fsl-mc/fsl-mc-msi.c
@@ -213,21 +213,8 @@ struct irq_domain *fsl_mc_find_msi_domain(struct device *dev)
int fsl_mc_msi_domain_alloc_irqs(struct device *dev, unsigned int irq_count)
{
- struct irq_domain *msi_domain;
- int error;
-
- msi_domain = dev_get_msi_domain(dev);
- if (!msi_domain)
- return -EINVAL;
-
- error = msi_setup_device_data(dev);
- if (error)
- return error;
+ int error = msi_setup_device_data(dev);
- msi_lock_descs(dev);
- if (msi_first_desc(dev, MSI_DESC_ALL))
- error = -EINVAL;
- msi_unlock_descs(dev);
if (error)
return error;
@@ -235,7 +222,7 @@ int fsl_mc_msi_domain_alloc_irqs(struct device *dev, unsigned int irq_count)
* NOTE: Calling this function will trigger the invocation of the
* its_fsl_mc_msi_prepare() callback
*/
- error = msi_domain_alloc_irqs(msi_domain, dev, irq_count);
+ error = msi_domain_alloc_irqs_range(dev, MSI_DEFAULT_DOMAIN, 0, irq_count - 1);
if (error)
dev_err(dev, "Failed to allocate IRQs\n");
@@ -244,11 +231,5 @@ int fsl_mc_msi_domain_alloc_irqs(struct device *dev, unsigned int irq_count)
void fsl_mc_msi_domain_free_irqs(struct device *dev)
{
- struct irq_domain *msi_domain;
-
- msi_domain = dev_get_msi_domain(dev);
- if (!msi_domain)
- return;
-
- msi_domain_free_irqs(msi_domain, dev);
+ msi_domain_free_irqs_all(dev, MSI_DEFAULT_DOMAIN);
}
diff --git a/drivers/bus/mhi/host/internal.h b/drivers/bus/mhi/host/internal.h
index 01fd10a399b6..2e139e76de4c 100644
--- a/drivers/bus/mhi/host/internal.h
+++ b/drivers/bus/mhi/host/internal.h
@@ -129,7 +129,7 @@ enum mhi_pm_state {
#define PRIMARY_CMD_RING 0
#define MHI_DEV_WAKE_DB 127
#define MHI_MAX_MTU 0xffff
-#define MHI_RANDOM_U32_NONZERO(bmsk) (prandom_u32_max(bmsk) + 1)
+#define MHI_RANDOM_U32_NONZERO(bmsk) (get_random_u32_inclusive(1, bmsk))
enum mhi_er_type {
MHI_ER_TYPE_INVALID = 0x0,
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
index 9a7d12332fad..6afae9897843 100644
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -1610,6 +1610,12 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),
SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, -ENODEV, 0x50700101, 0xffffffff,
SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),
+ SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000033,
+ 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY |
+ SYSC_MODULE_QUIRK_OTG),
+ SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000040,
+ 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY |
+ SYSC_MODULE_QUIRK_OTG),
SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050,
0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY |
SYSC_MODULE_QUIRK_OTG),
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 0f378d29dab0..30fe9848dac1 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -423,40 +423,4 @@ config ADI
and SSM (Silicon Secured Memory). Intended consumers of this
driver include crash and makedumpfile.
-config RANDOM_TRUST_CPU
- bool "Initialize RNG using CPU RNG instructions"
- default y
- help
- Initialize the RNG using random numbers supplied by the CPU's
- RNG instructions (e.g. RDRAND), if supported and available. These
- random numbers are never used directly, but are rather hashed into
- the main input pool, and this happens regardless of whether or not
- this option is enabled. Instead, this option controls whether the
- they are credited and hence can initialize the RNG. Additionally,
- other sources of randomness are always used, regardless of this
- setting. Enabling this implies trusting that the CPU can supply high
- quality and non-backdoored random numbers.
-
- Say Y here unless you have reason to mistrust your CPU or believe
- its RNG facilities may be faulty. This may also be configured at
- boot time with "random.trust_cpu=on/off".
-
-config RANDOM_TRUST_BOOTLOADER
- bool "Initialize RNG using bootloader-supplied seed"
- default y
- help
- Initialize the RNG using a seed supplied by the bootloader or boot
- environment (e.g. EFI or a bootloader-generated device tree). This
- seed is not used directly, but is rather hashed into the main input
- pool, and this happens regardless of whether or not this option is
- enabled. Instead, this option controls whether the seed is credited
- and hence can initialize the RNG. Additionally, other sources of
- randomness are always used, regardless of this setting. Enabling
- this implies trusting that the bootloader can supply high quality and
- non-backdoored seeds.
-
- Say Y here unless you have reason to mistrust your bootloader or
- believe its RNG facilities may be faulty. This may also be configured
- at boot time with "random.trust_bootloader=on/off".
-
endmenu
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index cc002b0c2f0c..63a0a8e4505d 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -69,8 +69,10 @@ static void add_early_randomness(struct hwrng *rng)
mutex_lock(&reading_mutex);
bytes_read = rng_get_data(rng, rng_fillbuf, 32, 0);
mutex_unlock(&reading_mutex);
- if (bytes_read > 0)
- add_device_randomness(rng_fillbuf, bytes_read);
+ if (bytes_read > 0) {
+ size_t entropy = bytes_read * 8 * rng->quality / 1024;
+ add_hwgenerator_randomness(rng_fillbuf, bytes_read, entropy, false);
+ }
}
static inline void cleanup_rng(struct kref *kref)
@@ -528,7 +530,7 @@ static int hwrng_fillfn(void *unused)
/* Outside lock, sure, but y'know: randomness. */
add_hwgenerator_randomness((void *)rng_fillbuf, rc,
- entropy >> 10);
+ entropy >> 10, true);
}
hwrng_fill = NULL;
return 0;
diff --git a/drivers/char/ipmi/Kconfig b/drivers/char/ipmi/Kconfig
index 39565cf74b2c..b6c0d35fc1a5 100644
--- a/drivers/char/ipmi/Kconfig
+++ b/drivers/char/ipmi/Kconfig
@@ -169,6 +169,16 @@ config ASPEED_BT_IPMI_BMC
found on Aspeed SOCs (AST2400 and AST2500). The driver
implements the BMC side of the BT interface.
+config SSIF_IPMI_BMC
+ tristate "SSIF IPMI BMC driver"
+ depends on I2C && I2C_SLAVE
+ help
+ This enables the IPMI SMBus system interface (SSIF) at the
+ management (BMC) side.
+
+ The driver implements the BMC side of the SMBus system
+ interface (SSIF).
+
config IPMB_DEVICE_INTERFACE
tristate 'IPMB Interface handler'
depends on I2C
diff --git a/drivers/char/ipmi/Makefile b/drivers/char/ipmi/Makefile
index 7ce790efad92..cb6138b8ded9 100644
--- a/drivers/char/ipmi/Makefile
+++ b/drivers/char/ipmi/Makefile
@@ -30,3 +30,4 @@ obj-$(CONFIG_ASPEED_BT_IPMI_BMC) += bt-bmc.o
obj-$(CONFIG_ASPEED_KCS_IPMI_BMC) += kcs_bmc_aspeed.o
obj-$(CONFIG_NPCM7XX_KCS_IPMI_BMC) += kcs_bmc_npcm7xx.o
obj-$(CONFIG_IPMB_DEVICE_INTERFACE) += ipmb_dev_int.o
+obj-$(CONFIG_SSIF_IPMI_BMC) += ssif_bmc.o
diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c
index efda90dcf5b3..ecfcb50302f6 100644
--- a/drivers/char/ipmi/ipmi_kcs_sm.c
+++ b/drivers/char/ipmi/ipmi_kcs_sm.c
@@ -122,10 +122,10 @@ struct si_sm_data {
unsigned long error0_timeout;
};
-static unsigned int init_kcs_data(struct si_sm_data *kcs,
- struct si_sm_io *io)
+static unsigned int init_kcs_data_with_state(struct si_sm_data *kcs,
+ struct si_sm_io *io, enum kcs_states state)
{
- kcs->state = KCS_IDLE;
+ kcs->state = state;
kcs->io = io;
kcs->write_pos = 0;
kcs->write_count = 0;
@@ -140,6 +140,12 @@ static unsigned int init_kcs_data(struct si_sm_data *kcs,
return 2;
}
+static unsigned int init_kcs_data(struct si_sm_data *kcs,
+ struct si_sm_io *io)
+{
+ return init_kcs_data_with_state(kcs, io, KCS_IDLE);
+}
+
static inline unsigned char read_status(struct si_sm_data *kcs)
{
return kcs->io->inputb(kcs->io, 1);
@@ -270,7 +276,7 @@ static int start_kcs_transaction(struct si_sm_data *kcs, unsigned char *data,
if (size > MAX_KCS_WRITE_SIZE)
return IPMI_REQ_LEN_EXCEEDED_ERR;
- if ((kcs->state != KCS_IDLE) && (kcs->state != KCS_HOSED)) {
+ if (kcs->state != KCS_IDLE) {
dev_warn(kcs->io->dev, "KCS in invalid state %d\n", kcs->state);
return IPMI_NOT_IN_MY_STATE_ERR;
}
@@ -495,7 +501,7 @@ static enum si_sm_result kcs_event(struct si_sm_data *kcs, long time)
}
if (kcs->state == KCS_HOSED) {
- init_kcs_data(kcs, kcs->io);
+ init_kcs_data_with_state(kcs, kcs->io, KCS_ERROR0);
return SI_SM_HOSED;
}
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 49a1707693c9..186f1fee7534 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -614,7 +614,7 @@ static int __ipmi_bmc_register(struct ipmi_smi *intf,
static int __scan_channels(struct ipmi_smi *intf, struct ipmi_device_id *id);
-/**
+/*
* The driver model view of the IPMI messaging driver.
*/
static struct platform_driver ipmidriver = {
@@ -1330,6 +1330,7 @@ static void _ipmi_destroy_user(struct ipmi_user *user)
unsigned long flags;
struct cmd_rcvr *rcvr;
struct cmd_rcvr *rcvrs = NULL;
+ struct module *owner;
if (!acquire_ipmi_user(user, &i)) {
/*
@@ -1392,8 +1393,9 @@ static void _ipmi_destroy_user(struct ipmi_user *user)
kfree(rcvr);
}
+ owner = intf->owner;
kref_put(&intf->refcount, intf_free);
- module_put(intf->owner);
+ module_put(owner);
}
int ipmi_destroy_user(struct ipmi_user *user)
@@ -3704,12 +3706,16 @@ static void deliver_smi_err_response(struct ipmi_smi *intf,
struct ipmi_smi_msg *msg,
unsigned char err)
{
+ int rv;
msg->rsp[0] = msg->data[0] | 4;
msg->rsp[1] = msg->data[1];
msg->rsp[2] = err;
msg->rsp_size = 3;
- /* It's an error, so it will never requeue, no need to check return. */
- handle_one_recv_msg(intf, msg);
+
+ /* This will never requeue, but it may ask us to free the message. */
+ rv = handle_one_recv_msg(intf, msg);
+ if (rv == 0)
+ ipmi_free_smi_msg(msg);
}
static void cleanup_smi_msgs(struct ipmi_smi *intf)
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 6e357ad76f2e..abddd7e43a9a 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -2153,6 +2153,20 @@ skip_fallback_noirq:
}
module_init(init_ipmi_si);
+static void wait_msg_processed(struct smi_info *smi_info)
+{
+ unsigned long jiffies_now;
+ long time_diff;
+
+ while (smi_info->curr_msg || (smi_info->si_state != SI_NORMAL)) {
+ jiffies_now = jiffies;
+ time_diff = (((long)jiffies_now - (long)smi_info->last_timeout_jiffies)
+ * SI_USEC_PER_JIFFY);
+ smi_event_handler(smi_info, time_diff);
+ schedule_timeout_uninterruptible(1);
+ }
+}
+
static void shutdown_smi(void *send_info)
{
struct smi_info *smi_info = send_info;
@@ -2187,16 +2201,13 @@ static void shutdown_smi(void *send_info)
* in the BMC. Note that timers and CPU interrupts are off,
* so no need for locks.
*/
- while (smi_info->curr_msg || (smi_info->si_state != SI_NORMAL)) {
- poll(smi_info);
- schedule_timeout_uninterruptible(1);
- }
+ wait_msg_processed(smi_info);
+
if (smi_info->handlers)
disable_si_irq(smi_info);
- while (smi_info->curr_msg || (smi_info->si_state != SI_NORMAL)) {
- poll(smi_info);
- schedule_timeout_uninterruptible(1);
- }
+
+ wait_msg_processed(smi_info);
+
if (smi_info->handlers)
smi_info->handlers->cleanup(smi_info->si_sm);
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
index e1072809fe31..4bfd1e306616 100644
--- a/drivers/char/ipmi/ipmi_ssif.c
+++ b/drivers/char/ipmi/ipmi_ssif.c
@@ -74,7 +74,7 @@
/*
* Timer values
*/
-#define SSIF_MSG_USEC 20000 /* 20ms between message tries. */
+#define SSIF_MSG_USEC 60000 /* 60ms between message tries. */
#define SSIF_MSG_PART_USEC 5000 /* 5ms for a message part */
/* How many times to we retry sending/receiving the message. */
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 5b4e677929ca..0d4a8dcacfd4 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -23,6 +23,7 @@
#include <linux/init.h>
#include <linux/completion.h>
#include <linux/kdebug.h>
+#include <linux/kstrtox.h>
#include <linux/rwsem.h>
#include <linux/errno.h>
#include <linux/uaccess.h>
@@ -212,8 +213,7 @@ static int set_param_str(const char *val, const struct kernel_param *kp)
char valcp[16];
char *s;
- strncpy(valcp, val, 15);
- valcp[15] = '\0';
+ strscpy(valcp, val, 16);
s = strstrip(valcp);
diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c
index 19c32bf50e0e..2dea8cd5a09a 100644
--- a/drivers/char/ipmi/kcs_bmc_aspeed.c
+++ b/drivers/char/ipmi/kcs_bmc_aspeed.c
@@ -406,13 +406,31 @@ static void aspeed_kcs_check_obe(struct timer_list *timer)
static void aspeed_kcs_irq_mask_update(struct kcs_bmc_device *kcs_bmc, u8 mask, u8 state)
{
struct aspeed_kcs_bmc *priv = to_aspeed_kcs_bmc(kcs_bmc);
+ int rc;
+ u8 str;
/* We don't have an OBE IRQ, emulate it */
if (mask & KCS_BMC_EVENT_TYPE_OBE) {
- if (KCS_BMC_EVENT_TYPE_OBE & state)
- mod_timer(&priv->obe.timer, jiffies + OBE_POLL_PERIOD);
- else
+ if (KCS_BMC_EVENT_TYPE_OBE & state) {
+ /*
+ * Given we don't have an OBE IRQ, delay by polling briefly to see if we can
+ * observe such an event before returning to the caller. This is not
+ * incorrect because OBF may have already become clear before enabling the
+ * IRQ if we had one, under which circumstance no event will be propagated
+ * anyway.
+ *
+ * The onus is on the client to perform a race-free check that it hasn't
+ * missed the event.
+ */
+ rc = read_poll_timeout_atomic(aspeed_kcs_inb, str,
+ !(str & KCS_BMC_STR_OBF), 1, 100, false,
+ &priv->kcs_bmc, priv->kcs_bmc.ioreg.str);
+ /* Time for the slow path? */
+ if (rc == -ETIMEDOUT)
+ mod_timer(&priv->obe.timer, jiffies + OBE_POLL_PERIOD);
+ } else {
del_timer(&priv->obe.timer);
+ }
}
if (mask & KCS_BMC_EVENT_TYPE_IBF) {
diff --git a/drivers/char/ipmi/ssif_bmc.c b/drivers/char/ipmi/ssif_bmc.c
new file mode 100644
index 000000000000..caee848261e9
--- /dev/null
+++ b/drivers/char/ipmi/ssif_bmc.c
@@ -0,0 +1,873 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * The driver for BMC side of SSIF interface
+ *
+ * Copyright (c) 2022, Ampere Computing LLC
+ *
+ */
+
+#include <linux/i2c.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+#include <linux/ipmi_ssif_bmc.h>
+
+#define DEVICE_NAME "ipmi-ssif-host"
+
+#define GET_8BIT_ADDR(addr_7bit) (((addr_7bit) << 1) & 0xff)
+
+/* A standard SMBus Transaction is limited to 32 data bytes */
+#define MAX_PAYLOAD_PER_TRANSACTION 32
+/* Transaction includes the address, the command, the length and the PEC byte */
+#define MAX_TRANSACTION (MAX_PAYLOAD_PER_TRANSACTION + 4)
+
+#define MAX_IPMI_DATA_PER_START_TRANSACTION 30
+#define MAX_IPMI_DATA_PER_MIDDLE_TRANSACTION 31
+
+#define SSIF_IPMI_SINGLEPART_WRITE 0x2
+#define SSIF_IPMI_SINGLEPART_READ 0x3
+#define SSIF_IPMI_MULTIPART_WRITE_START 0x6
+#define SSIF_IPMI_MULTIPART_WRITE_MIDDLE 0x7
+#define SSIF_IPMI_MULTIPART_WRITE_END 0x8
+#define SSIF_IPMI_MULTIPART_READ_START 0x3
+#define SSIF_IPMI_MULTIPART_READ_MIDDLE 0x9
+
+/*
+ * IPMI 2.0 Spec, section 12.7 SSIF Timing,
+ * Request-to-Response Time is T6max(250ms) - T1max(20ms) - 3ms = 227ms
+ * Recover ssif_bmc from busy state if it takes up to 500ms
+ */
+#define RESPONSE_TIMEOUT 500 /* ms */
+
+struct ssif_part_buffer {
+ u8 address;
+ u8 smbus_cmd;
+ u8 length;
+ u8 payload[MAX_PAYLOAD_PER_TRANSACTION];
+ u8 pec;
+ u8 index;
+};
+
+/*
+ * SSIF internal states:
+ * SSIF_READY 0x00 : Ready state
+ * SSIF_START 0x01 : Start smbus transaction
+ * SSIF_SMBUS_CMD 0x02 : Received SMBus command
+ * SSIF_REQ_RECVING 0x03 : Receiving request
+ * SSIF_RES_SENDING 0x04 : Sending response
+ * SSIF_ABORTING 0x05 : Aborting state
+ */
+enum ssif_state {
+ SSIF_READY,
+ SSIF_START,
+ SSIF_SMBUS_CMD,
+ SSIF_REQ_RECVING,
+ SSIF_RES_SENDING,
+ SSIF_ABORTING,
+ SSIF_STATE_MAX
+};
+
+struct ssif_bmc_ctx {
+ struct i2c_client *client;
+ struct miscdevice miscdev;
+ int msg_idx;
+ bool pec_support;
+ /* ssif bmc spinlock */
+ spinlock_t lock;
+ wait_queue_head_t wait_queue;
+ u8 running;
+ enum ssif_state state;
+ /* Timeout waiting for response */
+ struct timer_list response_timer;
+ bool response_timer_inited;
+ /* Flag to identify a Multi-part Read Transaction */
+ bool is_singlepart_read;
+ u8 nbytes_processed;
+ u8 remain_len;
+ u8 recv_len;
+ /* Block Number of a Multi-part Read Transaction */
+ u8 block_num;
+ bool request_available;
+ bool response_in_progress;
+ bool busy;
+ bool aborting;
+ /* Buffer for SSIF Transaction part*/
+ struct ssif_part_buffer part_buf;
+ struct ipmi_ssif_msg response;
+ struct ipmi_ssif_msg request;
+};
+
+static inline struct ssif_bmc_ctx *to_ssif_bmc(struct file *file)
+{
+ return container_of(file->private_data, struct ssif_bmc_ctx, miscdev);
+}
+
+static const char *state_to_string(enum ssif_state state)
+{
+ switch (state) {
+ case SSIF_READY:
+ return "SSIF_READY";
+ case SSIF_START:
+ return "SSIF_START";
+ case SSIF_SMBUS_CMD:
+ return "SSIF_SMBUS_CMD";
+ case SSIF_REQ_RECVING:
+ return "SSIF_REQ_RECVING";
+ case SSIF_RES_SENDING:
+ return "SSIF_RES_SENDING";
+ case SSIF_ABORTING:
+ return "SSIF_ABORTING";
+ default:
+ return "SSIF_STATE_UNKNOWN";
+ }
+}
+
+/* Handle SSIF message that will be sent to user */
+static ssize_t ssif_bmc_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+ struct ssif_bmc_ctx *ssif_bmc = to_ssif_bmc(file);
+ struct ipmi_ssif_msg msg;
+ unsigned long flags;
+ ssize_t ret;
+
+ spin_lock_irqsave(&ssif_bmc->lock, flags);
+ while (!ssif_bmc->request_available) {
+ spin_unlock_irqrestore(&ssif_bmc->lock, flags);
+ if (file->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+ ret = wait_event_interruptible(ssif_bmc->wait_queue,
+ ssif_bmc->request_available);
+ if (ret)
+ return ret;
+ spin_lock_irqsave(&ssif_bmc->lock, flags);
+ }
+
+ if (count < min_t(ssize_t,
+ sizeof_field(struct ipmi_ssif_msg, len) + ssif_bmc->request.len,
+ sizeof(struct ipmi_ssif_msg))) {
+ spin_unlock_irqrestore(&ssif_bmc->lock, flags);
+ ret = -EINVAL;
+ } else {
+ count = min_t(ssize_t,
+ sizeof_field(struct ipmi_ssif_msg, len) + ssif_bmc->request.len,
+ sizeof(struct ipmi_ssif_msg));
+ memcpy(&msg, &ssif_bmc->request, count);
+ ssif_bmc->request_available = false;
+ spin_unlock_irqrestore(&ssif_bmc->lock, flags);
+
+ ret = copy_to_user(buf, &msg, count);
+ }
+
+ return (ret < 0) ? ret : count;
+}
+
+/* Handle SSIF message that is written by user */
+static ssize_t ssif_bmc_write(struct file *file, const char __user *buf, size_t count,
+ loff_t *ppos)
+{
+ struct ssif_bmc_ctx *ssif_bmc = to_ssif_bmc(file);
+ struct ipmi_ssif_msg msg;
+ unsigned long flags;
+ ssize_t ret;
+
+ if (count > sizeof(struct ipmi_ssif_msg))
+ return -EINVAL;
+
+ if (copy_from_user(&msg, buf, count))
+ return -EFAULT;
+
+ if (!msg.len || count < sizeof_field(struct ipmi_ssif_msg, len) + msg.len)
+ return -EINVAL;
+
+ spin_lock_irqsave(&ssif_bmc->lock, flags);
+ while (ssif_bmc->response_in_progress) {
+ spin_unlock_irqrestore(&ssif_bmc->lock, flags);
+ if (file->f_flags & O_NONBLOCK)
+ return -EAGAIN;
+ ret = wait_event_interruptible(ssif_bmc->wait_queue,
+ !ssif_bmc->response_in_progress);
+ if (ret)
+ return ret;
+ spin_lock_irqsave(&ssif_bmc->lock, flags);
+ }
+
+ /*
+ * The write must complete before the response timeout fired, otherwise
+ * the response is aborted and wait for next request
+ * Return -EINVAL if the response is aborted
+ */
+ ret = (ssif_bmc->response_timer_inited) ? 0 : -EINVAL;
+ if (ret)
+ goto exit;
+
+ del_timer(&ssif_bmc->response_timer);
+ ssif_bmc->response_timer_inited = false;
+
+ memcpy(&ssif_bmc->response, &msg, count);
+ ssif_bmc->is_singlepart_read = (msg.len <= MAX_PAYLOAD_PER_TRANSACTION);
+
+ ssif_bmc->response_in_progress = true;
+
+ /* ssif_bmc not busy */
+ ssif_bmc->busy = false;
+
+ /* Clean old request buffer */
+ memset(&ssif_bmc->request, 0, sizeof(struct ipmi_ssif_msg));
+exit:
+ spin_unlock_irqrestore(&ssif_bmc->lock, flags);
+
+ return (ret < 0) ? ret : count;
+}
+
+static int ssif_bmc_open(struct inode *inode, struct file *file)
+{
+ struct ssif_bmc_ctx *ssif_bmc = to_ssif_bmc(file);
+ int ret = 0;
+
+ spin_lock_irq(&ssif_bmc->lock);
+ if (!ssif_bmc->running)
+ ssif_bmc->running = 1;
+ else
+ ret = -EBUSY;
+ spin_unlock_irq(&ssif_bmc->lock);
+
+ return ret;
+}
+
+static __poll_t ssif_bmc_poll(struct file *file, poll_table *wait)
+{
+ struct ssif_bmc_ctx *ssif_bmc = to_ssif_bmc(file);
+ __poll_t mask = 0;
+
+ poll_wait(file, &ssif_bmc->wait_queue, wait);
+
+ spin_lock_irq(&ssif_bmc->lock);
+ /* The request is available, userspace application can get the request */
+ if (ssif_bmc->request_available)
+ mask |= EPOLLIN;
+
+ spin_unlock_irq(&ssif_bmc->lock);
+
+ return mask;
+}
+
+static int ssif_bmc_release(struct inode *inode, struct file *file)
+{
+ struct ssif_bmc_ctx *ssif_bmc = to_ssif_bmc(file);
+
+ spin_lock_irq(&ssif_bmc->lock);
+ ssif_bmc->running = 0;
+ spin_unlock_irq(&ssif_bmc->lock);
+
+ return 0;
+}
+
+/*
+ * System calls to device interface for user apps
+ */
+static const struct file_operations ssif_bmc_fops = {
+ .owner = THIS_MODULE,
+ .open = ssif_bmc_open,
+ .read = ssif_bmc_read,
+ .write = ssif_bmc_write,
+ .release = ssif_bmc_release,
+ .poll = ssif_bmc_poll,
+};
+
+/* Called with ssif_bmc->lock held. */
+static void complete_response(struct ssif_bmc_ctx *ssif_bmc)
+{
+ /* Invalidate response in buffer to denote it having been sent. */
+ ssif_bmc->response.len = 0;
+ ssif_bmc->response_in_progress = false;
+ ssif_bmc->nbytes_processed = 0;
+ ssif_bmc->remain_len = 0;
+ ssif_bmc->busy = false;
+ memset(&ssif_bmc->part_buf, 0, sizeof(struct ssif_part_buffer));
+ wake_up_all(&ssif_bmc->wait_queue);
+}
+
+static void response_timeout(struct timer_list *t)
+{
+ struct ssif_bmc_ctx *ssif_bmc = from_timer(ssif_bmc, t, response_timer);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ssif_bmc->lock, flags);
+
+ /* Do nothing if the response is in progress */
+ if (!ssif_bmc->response_in_progress) {
+ /* Recover ssif_bmc from busy */
+ ssif_bmc->busy = false;
+ ssif_bmc->response_timer_inited = false;
+ /* Set aborting flag */
+ ssif_bmc->aborting = true;
+ }
+
+ spin_unlock_irqrestore(&ssif_bmc->lock, flags);
+}
+
+/* Called with ssif_bmc->lock held. */
+static void handle_request(struct ssif_bmc_ctx *ssif_bmc)
+{
+ /* set ssif_bmc to busy waiting for response */
+ ssif_bmc->busy = true;
+ /* Request message is available to process */
+ ssif_bmc->request_available = true;
+ /* Clean old response buffer */
+ memset(&ssif_bmc->response, 0, sizeof(struct ipmi_ssif_msg));
+ /* This is the new READ request.*/
+ wake_up_all(&ssif_bmc->wait_queue);
+
+ /* Armed timer to recover slave from busy state in case of no response */
+ if (!ssif_bmc->response_timer_inited) {
+ timer_setup(&ssif_bmc->response_timer, response_timeout, 0);
+ ssif_bmc->response_timer_inited = true;
+ }
+ mod_timer(&ssif_bmc->response_timer, jiffies + msecs_to_jiffies(RESPONSE_TIMEOUT));
+}
+
+static void calculate_response_part_pec(struct ssif_part_buffer *part)
+{
+ u8 addr = part->address;
+
+ /* PEC - Start Read Address */
+ part->pec = i2c_smbus_pec(0, &addr, 1);
+ /* PEC - SSIF Command */
+ part->pec = i2c_smbus_pec(part->pec, &part->smbus_cmd, 1);
+ /* PEC - Restart Write Address */
+ addr = addr | 0x01;
+ part->pec = i2c_smbus_pec(part->pec, &addr, 1);
+ part->pec = i2c_smbus_pec(part->pec, &part->length, 1);
+ if (part->length)
+ part->pec = i2c_smbus_pec(part->pec, part->payload, part->length);
+}
+
+static void set_singlepart_response_buffer(struct ssif_bmc_ctx *ssif_bmc)
+{
+ struct ssif_part_buffer *part = &ssif_bmc->part_buf;
+
+ part->address = GET_8BIT_ADDR(ssif_bmc->client->addr);
+ part->length = (u8)ssif_bmc->response.len;
+
+ /* Clear the rest to 0 */
+ memset(part->payload + part->length, 0, MAX_PAYLOAD_PER_TRANSACTION - part->length);
+ memcpy(&part->payload[0], &ssif_bmc->response.payload[0], part->length);
+}
+
+static void set_multipart_response_buffer(struct ssif_bmc_ctx *ssif_bmc)
+{
+ struct ssif_part_buffer *part = &ssif_bmc->part_buf;
+ u8 part_len = 0;
+
+ part->address = GET_8BIT_ADDR(ssif_bmc->client->addr);
+ switch (part->smbus_cmd) {
+ case SSIF_IPMI_MULTIPART_READ_START:
+ /*
+ * Read Start length is 32 bytes.
+ * Read Start transfer first 30 bytes of IPMI response
+ * and 2 special code 0x00, 0x01.
+ */
+ ssif_bmc->nbytes_processed = 0;
+ ssif_bmc->block_num = 0;
+ part->length = MAX_PAYLOAD_PER_TRANSACTION;
+ part_len = MAX_IPMI_DATA_PER_START_TRANSACTION;
+ ssif_bmc->remain_len = ssif_bmc->response.len - part_len;
+
+ part->payload[0] = 0x00; /* Start Flag */
+ part->payload[1] = 0x01; /* Start Flag */
+
+ memcpy(&part->payload[2], &ssif_bmc->response.payload[0], part_len);
+ break;
+
+ case SSIF_IPMI_MULTIPART_READ_MIDDLE:
+ /*
+ * IPMI READ Middle or READ End messages can carry up to 31 bytes
+ * IPMI data plus block number byte.
+ */
+ if (ssif_bmc->remain_len <= MAX_IPMI_DATA_PER_MIDDLE_TRANSACTION) {
+ /*
+ * This is READ End message
+ * Return length is the remaining response data length
+ * plus block number
+ * Block number 0xFF is to indicate this is last message
+ *
+ */
+ /* Clean the buffer */
+ memset(&part->payload[0], 0, MAX_PAYLOAD_PER_TRANSACTION);
+ part->length = ssif_bmc->remain_len + 1;
+ part_len = ssif_bmc->remain_len;
+ ssif_bmc->block_num = 0xFF;
+ part->payload[0] = ssif_bmc->block_num;
+ } else {
+ /*
+ * This is READ Middle message
+ * Response length is the maximum SMBUS transfer length
+ * Block number byte is incremented
+ * Return length is maximum SMBUS transfer length
+ */
+ part->length = MAX_PAYLOAD_PER_TRANSACTION;
+ part_len = MAX_IPMI_DATA_PER_MIDDLE_TRANSACTION;
+ part->payload[0] = ssif_bmc->block_num;
+ ssif_bmc->block_num++;
+ }
+
+ ssif_bmc->remain_len -= part_len;
+ memcpy(&part->payload[1], ssif_bmc->response.payload + ssif_bmc->nbytes_processed,
+ part_len);
+ break;
+
+ default:
+ /* Do not expect to go to this case */
+ dev_err(&ssif_bmc->client->dev, "%s: Unexpected SMBus command 0x%x\n",
+ __func__, part->smbus_cmd);
+ break;
+ }
+
+ ssif_bmc->nbytes_processed += part_len;
+}
+
+static bool supported_read_cmd(u8 cmd)
+{
+ if (cmd == SSIF_IPMI_SINGLEPART_READ ||
+ cmd == SSIF_IPMI_MULTIPART_READ_START ||
+ cmd == SSIF_IPMI_MULTIPART_READ_MIDDLE)
+ return true;
+
+ return false;
+}
+
+static bool supported_write_cmd(u8 cmd)
+{
+ if (cmd == SSIF_IPMI_SINGLEPART_WRITE ||
+ cmd == SSIF_IPMI_MULTIPART_WRITE_START ||
+ cmd == SSIF_IPMI_MULTIPART_WRITE_MIDDLE ||
+ cmd == SSIF_IPMI_MULTIPART_WRITE_END)
+ return true;
+
+ return false;
+}
+
+/* Process the IPMI response that will be read by master */
+static void handle_read_processed(struct ssif_bmc_ctx *ssif_bmc, u8 *val)
+{
+ struct ssif_part_buffer *part = &ssif_bmc->part_buf;
+
+ /* msg_idx start from 0 */
+ if (part->index < part->length)
+ *val = part->payload[part->index];
+ else if (part->index == part->length && ssif_bmc->pec_support)
+ *val = part->pec;
+ else
+ *val = 0;
+
+ part->index++;
+}
+
+static void handle_write_received(struct ssif_bmc_ctx *ssif_bmc, u8 *val)
+{
+ /*
+ * The msg_idx must be 1 when first enter SSIF_REQ_RECVING state
+ * And it would never exceeded 36 bytes included the 32 bytes max payload +
+ * the address + the command + the len and the PEC.
+ */
+ if (ssif_bmc->msg_idx < 1 || ssif_bmc->msg_idx > MAX_TRANSACTION)
+ return;
+
+ if (ssif_bmc->msg_idx == 1) {
+ ssif_bmc->part_buf.length = *val;
+ ssif_bmc->part_buf.index = 0;
+ } else {
+ ssif_bmc->part_buf.payload[ssif_bmc->part_buf.index++] = *val;
+ }
+
+ ssif_bmc->msg_idx++;
+}
+
+static bool validate_request_part(struct ssif_bmc_ctx *ssif_bmc)
+{
+ struct ssif_part_buffer *part = &ssif_bmc->part_buf;
+ bool ret = true;
+ u8 cpec;
+ u8 addr;
+
+ if (part->index == part->length) {
+ /* PEC is not included */
+ ssif_bmc->pec_support = false;
+ ret = true;
+ goto exit;
+ }
+
+ if (part->index != part->length + 1) {
+ ret = false;
+ goto exit;
+ }
+
+ /* PEC is included */
+ ssif_bmc->pec_support = true;
+ part->pec = part->payload[part->length];
+ addr = GET_8BIT_ADDR(ssif_bmc->client->addr);
+ cpec = i2c_smbus_pec(0, &addr, 1);
+ cpec = i2c_smbus_pec(cpec, &part->smbus_cmd, 1);
+ cpec = i2c_smbus_pec(cpec, &part->length, 1);
+ /*
+ * As SMBus specification does not allow the length
+ * (byte count) in the Write-Block protocol to be zero.
+ * Therefore, it is illegal to have the last Middle
+ * transaction in the sequence carry 32-byte and have
+ * a length of ‘0’ in the End transaction.
+ * But some users may try to use this way and we should
+ * prevent ssif_bmc driver broken in this case.
+ */
+ if (part->length)
+ cpec = i2c_smbus_pec(cpec, part->payload, part->length);
+
+ if (cpec != part->pec)
+ ret = false;
+
+exit:
+ return ret;
+}
+
+static void process_request_part(struct ssif_bmc_ctx *ssif_bmc)
+{
+ struct ssif_part_buffer *part = &ssif_bmc->part_buf;
+ unsigned int len;
+
+ switch (part->smbus_cmd) {
+ case SSIF_IPMI_SINGLEPART_WRITE:
+ /* save the whole part to request*/
+ ssif_bmc->request.len = part->length;
+ memcpy(ssif_bmc->request.payload, part->payload, part->length);
+
+ break;
+ case SSIF_IPMI_MULTIPART_WRITE_START:
+ ssif_bmc->request.len = 0;
+
+ fallthrough;
+ case SSIF_IPMI_MULTIPART_WRITE_MIDDLE:
+ case SSIF_IPMI_MULTIPART_WRITE_END:
+ len = ssif_bmc->request.len + part->length;
+ /* Do the bound check here, not allow the request len exceed 254 bytes */
+ if (len > IPMI_SSIF_PAYLOAD_MAX) {
+ dev_warn(&ssif_bmc->client->dev,
+ "Warn: Request exceeded 254 bytes, aborting");
+ /* Request too long, aborting */
+ ssif_bmc->aborting = true;
+ } else {
+ memcpy(ssif_bmc->request.payload + ssif_bmc->request.len,
+ part->payload, part->length);
+ ssif_bmc->request.len += part->length;
+ }
+ break;
+ default:
+ /* Do not expect to go to this case */
+ dev_err(&ssif_bmc->client->dev, "%s: Unexpected SMBus command 0x%x\n",
+ __func__, part->smbus_cmd);
+ break;
+ }
+}
+
+static void process_smbus_cmd(struct ssif_bmc_ctx *ssif_bmc, u8 *val)
+{
+ /* SMBUS command can vary (single or multi-part) */
+ ssif_bmc->part_buf.smbus_cmd = *val;
+ ssif_bmc->msg_idx = 1;
+ memset(&ssif_bmc->part_buf.payload[0], 0, MAX_PAYLOAD_PER_TRANSACTION);
+
+ if (*val == SSIF_IPMI_SINGLEPART_WRITE || *val == SSIF_IPMI_MULTIPART_WRITE_START) {
+ /*
+ * The response maybe not come in-time, causing host SSIF driver
+ * to timeout and resend a new request. In such case check for
+ * pending response and clear it
+ */
+ if (ssif_bmc->response_in_progress)
+ complete_response(ssif_bmc);
+
+ /* This is new request, flip aborting flag if set */
+ if (ssif_bmc->aborting)
+ ssif_bmc->aborting = false;
+ }
+}
+
+static void on_read_requested_event(struct ssif_bmc_ctx *ssif_bmc, u8 *val)
+{
+ if (ssif_bmc->state == SSIF_READY ||
+ ssif_bmc->state == SSIF_START ||
+ ssif_bmc->state == SSIF_REQ_RECVING ||
+ ssif_bmc->state == SSIF_RES_SENDING) {
+ dev_warn(&ssif_bmc->client->dev,
+ "Warn: %s unexpected READ REQUESTED in state=%s\n",
+ __func__, state_to_string(ssif_bmc->state));
+ ssif_bmc->state = SSIF_ABORTING;
+ *val = 0;
+ return;
+
+ } else if (ssif_bmc->state == SSIF_SMBUS_CMD) {
+ if (!supported_read_cmd(ssif_bmc->part_buf.smbus_cmd)) {
+ dev_warn(&ssif_bmc->client->dev, "Warn: Unknown SMBus read command=0x%x",
+ ssif_bmc->part_buf.smbus_cmd);
+ ssif_bmc->aborting = true;
+ }
+
+ if (ssif_bmc->aborting)
+ ssif_bmc->state = SSIF_ABORTING;
+ else
+ ssif_bmc->state = SSIF_RES_SENDING;
+ }
+
+ ssif_bmc->msg_idx = 0;
+
+ /* Send 0 if there is nothing to send */
+ if (!ssif_bmc->response_in_progress || ssif_bmc->state == SSIF_ABORTING) {
+ *val = 0;
+ return;
+ }
+
+ if (ssif_bmc->is_singlepart_read)
+ set_singlepart_response_buffer(ssif_bmc);
+ else
+ set_multipart_response_buffer(ssif_bmc);
+
+ calculate_response_part_pec(&ssif_bmc->part_buf);
+ ssif_bmc->part_buf.index = 0;
+ *val = ssif_bmc->part_buf.length;
+}
+
+static void on_read_processed_event(struct ssif_bmc_ctx *ssif_bmc, u8 *val)
+{
+ if (ssif_bmc->state == SSIF_READY ||
+ ssif_bmc->state == SSIF_START ||
+ ssif_bmc->state == SSIF_REQ_RECVING ||
+ ssif_bmc->state == SSIF_SMBUS_CMD) {
+ dev_warn(&ssif_bmc->client->dev,
+ "Warn: %s unexpected READ PROCESSED in state=%s\n",
+ __func__, state_to_string(ssif_bmc->state));
+ ssif_bmc->state = SSIF_ABORTING;
+ *val = 0;
+ return;
+ }
+
+ /* Send 0 if there is nothing to send */
+ if (!ssif_bmc->response_in_progress || ssif_bmc->state == SSIF_ABORTING) {
+ *val = 0;
+ return;
+ }
+
+ handle_read_processed(ssif_bmc, val);
+}
+
+static void on_write_requested_event(struct ssif_bmc_ctx *ssif_bmc, u8 *val)
+{
+ if (ssif_bmc->state == SSIF_READY || ssif_bmc->state == SSIF_SMBUS_CMD) {
+ ssif_bmc->state = SSIF_START;
+
+ } else if (ssif_bmc->state == SSIF_START ||
+ ssif_bmc->state == SSIF_REQ_RECVING ||
+ ssif_bmc->state == SSIF_RES_SENDING) {
+ dev_warn(&ssif_bmc->client->dev,
+ "Warn: %s unexpected WRITE REQUEST in state=%s\n",
+ __func__, state_to_string(ssif_bmc->state));
+ ssif_bmc->state = SSIF_ABORTING;
+ return;
+ }
+
+ ssif_bmc->msg_idx = 0;
+ ssif_bmc->part_buf.address = *val;
+}
+
+static void on_write_received_event(struct ssif_bmc_ctx *ssif_bmc, u8 *val)
+{
+ if (ssif_bmc->state == SSIF_READY ||
+ ssif_bmc->state == SSIF_RES_SENDING) {
+ dev_warn(&ssif_bmc->client->dev,
+ "Warn: %s unexpected WRITE RECEIVED in state=%s\n",
+ __func__, state_to_string(ssif_bmc->state));
+ ssif_bmc->state = SSIF_ABORTING;
+
+ } else if (ssif_bmc->state == SSIF_START) {
+ ssif_bmc->state = SSIF_SMBUS_CMD;
+
+ } else if (ssif_bmc->state == SSIF_SMBUS_CMD) {
+ if (!supported_write_cmd(ssif_bmc->part_buf.smbus_cmd)) {
+ dev_warn(&ssif_bmc->client->dev, "Warn: Unknown SMBus write command=0x%x",
+ ssif_bmc->part_buf.smbus_cmd);
+ ssif_bmc->aborting = true;
+ }
+
+ if (ssif_bmc->aborting)
+ ssif_bmc->state = SSIF_ABORTING;
+ else
+ ssif_bmc->state = SSIF_REQ_RECVING;
+ }
+
+ /* This is response sending state */
+ if (ssif_bmc->state == SSIF_REQ_RECVING)
+ handle_write_received(ssif_bmc, val);
+ else if (ssif_bmc->state == SSIF_SMBUS_CMD)
+ process_smbus_cmd(ssif_bmc, val);
+}
+
+static void on_stop_event(struct ssif_bmc_ctx *ssif_bmc, u8 *val)
+{
+ if (ssif_bmc->state == SSIF_READY ||
+ ssif_bmc->state == SSIF_START ||
+ ssif_bmc->state == SSIF_SMBUS_CMD ||
+ ssif_bmc->state == SSIF_ABORTING) {
+ dev_warn(&ssif_bmc->client->dev,
+ "Warn: %s unexpected SLAVE STOP in state=%s\n",
+ __func__, state_to_string(ssif_bmc->state));
+ ssif_bmc->state = SSIF_READY;
+
+ } else if (ssif_bmc->state == SSIF_REQ_RECVING) {
+ if (validate_request_part(ssif_bmc)) {
+ process_request_part(ssif_bmc);
+ if (ssif_bmc->part_buf.smbus_cmd == SSIF_IPMI_SINGLEPART_WRITE ||
+ ssif_bmc->part_buf.smbus_cmd == SSIF_IPMI_MULTIPART_WRITE_END)
+ handle_request(ssif_bmc);
+ ssif_bmc->state = SSIF_READY;
+ } else {
+ /*
+ * A BMC that receives an invalid request drop the data for the write
+ * transaction and any further transactions (read or write) until
+ * the next valid read or write Start transaction is received
+ */
+ dev_err(&ssif_bmc->client->dev, "Error: invalid pec\n");
+ ssif_bmc->aborting = true;
+ }
+ } else if (ssif_bmc->state == SSIF_RES_SENDING) {
+ if (ssif_bmc->is_singlepart_read || ssif_bmc->block_num == 0xFF)
+ /* Invalidate response buffer to denote it is sent */
+ complete_response(ssif_bmc);
+ ssif_bmc->state = SSIF_READY;
+ }
+
+ /* Reset message index */
+ ssif_bmc->msg_idx = 0;
+}
+
+/*
+ * Callback function to handle I2C slave events
+ */
+static int ssif_bmc_cb(struct i2c_client *client, enum i2c_slave_event event, u8 *val)
+{
+ unsigned long flags;
+ struct ssif_bmc_ctx *ssif_bmc = i2c_get_clientdata(client);
+ int ret = 0;
+
+ spin_lock_irqsave(&ssif_bmc->lock, flags);
+
+ switch (event) {
+ case I2C_SLAVE_READ_REQUESTED:
+ on_read_requested_event(ssif_bmc, val);
+ break;
+
+ case I2C_SLAVE_WRITE_REQUESTED:
+ on_write_requested_event(ssif_bmc, val);
+ break;
+
+ case I2C_SLAVE_READ_PROCESSED:
+ on_read_processed_event(ssif_bmc, val);
+ break;
+
+ case I2C_SLAVE_WRITE_RECEIVED:
+ on_write_received_event(ssif_bmc, val);
+ break;
+
+ case I2C_SLAVE_STOP:
+ on_stop_event(ssif_bmc, val);
+ break;
+
+ default:
+ dev_warn(&ssif_bmc->client->dev, "Warn: Unknown i2c slave event\n");
+ break;
+ }
+
+ if (!ssif_bmc->aborting && ssif_bmc->busy)
+ ret = -EBUSY;
+
+ spin_unlock_irqrestore(&ssif_bmc->lock, flags);
+
+ return ret;
+}
+
+static int ssif_bmc_probe(struct i2c_client *client)
+{
+ struct ssif_bmc_ctx *ssif_bmc;
+ int ret;
+
+ ssif_bmc = devm_kzalloc(&client->dev, sizeof(*ssif_bmc), GFP_KERNEL);
+ if (!ssif_bmc)
+ return -ENOMEM;
+
+ spin_lock_init(&ssif_bmc->lock);
+
+ init_waitqueue_head(&ssif_bmc->wait_queue);
+ ssif_bmc->request_available = false;
+ ssif_bmc->response_in_progress = false;
+ ssif_bmc->busy = false;
+ ssif_bmc->response_timer_inited = false;
+
+ /* Register misc device interface */
+ ssif_bmc->miscdev.minor = MISC_DYNAMIC_MINOR;
+ ssif_bmc->miscdev.name = DEVICE_NAME;
+ ssif_bmc->miscdev.fops = &ssif_bmc_fops;
+ ssif_bmc->miscdev.parent = &client->dev;
+ ret = misc_register(&ssif_bmc->miscdev);
+ if (ret)
+ return ret;
+
+ ssif_bmc->client = client;
+ ssif_bmc->client->flags |= I2C_CLIENT_SLAVE;
+
+ /* Register I2C slave */
+ i2c_set_clientdata(client, ssif_bmc);
+ ret = i2c_slave_register(client, ssif_bmc_cb);
+ if (ret)
+ misc_deregister(&ssif_bmc->miscdev);
+
+ return ret;
+}
+
+static void ssif_bmc_remove(struct i2c_client *client)
+{
+ struct ssif_bmc_ctx *ssif_bmc = i2c_get_clientdata(client);
+
+ i2c_slave_unregister(client);
+ misc_deregister(&ssif_bmc->miscdev);
+}
+
+static const struct of_device_id ssif_bmc_match[] = {
+ { .compatible = "ssif-bmc" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ssif_bmc_match);
+
+static const struct i2c_device_id ssif_bmc_id[] = {
+ { DEVICE_NAME, 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(i2c, ssif_bmc_id);
+
+static struct i2c_driver ssif_bmc_driver = {
+ .driver = {
+ .name = DEVICE_NAME,
+ .of_match_table = ssif_bmc_match,
+ },
+ .probe_new = ssif_bmc_probe,
+ .remove = ssif_bmc_remove,
+ .id_table = ssif_bmc_id,
+};
+
+module_i2c_driver(ssif_bmc_driver);
+
+MODULE_AUTHOR("Quan Nguyen <quan@os.amperecomputing.com>");
+MODULE_AUTHOR("Chuong Tran <chuong@os.amperecomputing.com>");
+MODULE_DESCRIPTION("Linux device driver of the BMC IPMI SSIF interface.");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 69754155300e..5885ed574c6a 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -53,6 +53,7 @@
#include <linux/uaccess.h>
#include <linux/suspend.h>
#include <linux/siphash.h>
+#include <linux/sched/isolation.h>
#include <crypto/chacha.h>
#include <crypto/blake2s.h>
#include <asm/processor.h>
@@ -84,6 +85,7 @@ static DEFINE_STATIC_KEY_FALSE(crng_is_ready);
/* Various types of waiters for crng_init->CRNG_READY transition. */
static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait);
static struct fasync_struct *fasync;
+static ATOMIC_NOTIFIER_HEAD(random_ready_notifier);
/* Control how we warn userspace. */
static struct ratelimit_state urandom_warning =
@@ -120,7 +122,7 @@ static void try_to_generate_entropy(void);
* Wait for the input pool to be seeded and thus guaranteed to supply
* cryptographically secure random numbers. This applies to: the /dev/urandom
* device, the get_random_bytes function, and the get_random_{u8,u16,u32,u64,
- * int,long} family of functions. Using any of these functions without first
+ * long} family of functions. Using any of these functions without first
* calling this function forfeits the guarantee of security.
*
* Returns: 0 if the input pool has been seeded.
@@ -140,6 +142,26 @@ int wait_for_random_bytes(void)
}
EXPORT_SYMBOL(wait_for_random_bytes);
+/*
+ * Add a callback function that will be invoked when the crng is initialised,
+ * or immediately if it already has been. Only use this is you are absolutely
+ * sure it is required. Most users should instead be able to test
+ * `rng_is_initialized()` on demand, or make use of `get_random_bytes_wait()`.
+ */
+int __cold execute_with_initialized_rng(struct notifier_block *nb)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&random_ready_notifier.lock, flags);
+ if (crng_ready())
+ nb->notifier_call(nb, 0, NULL);
+ else
+ ret = raw_notifier_chain_register((struct raw_notifier_head *)&random_ready_notifier.head, nb);
+ spin_unlock_irqrestore(&random_ready_notifier.lock, flags);
+ return ret;
+}
+
#define warn_unseeded_randomness() \
if (IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM) && !crng_ready()) \
printk_deferred(KERN_NOTICE "random: %s called from %pS with crng_init=%d\n", \
@@ -160,6 +182,9 @@ EXPORT_SYMBOL(wait_for_random_bytes);
* u8 get_random_u8()
* u16 get_random_u16()
* u32 get_random_u32()
+ * u32 get_random_u32_below(u32 ceil)
+ * u32 get_random_u32_above(u32 floor)
+ * u32 get_random_u32_inclusive(u32 floor, u32 ceil)
* u64 get_random_u64()
* unsigned long get_random_long()
*
@@ -179,7 +204,6 @@ enum {
static struct {
u8 key[CHACHA_KEY_SIZE] __aligned(__alignof__(long));
- unsigned long birth;
unsigned long generation;
spinlock_t lock;
} base_crng = {
@@ -197,16 +221,41 @@ static DEFINE_PER_CPU(struct crng, crngs) = {
.lock = INIT_LOCAL_LOCK(crngs.lock),
};
+/*
+ * Return the interval until the next reseeding, which is normally
+ * CRNG_RESEED_INTERVAL, but during early boot, it is at an interval
+ * proportional to the uptime.
+ */
+static unsigned int crng_reseed_interval(void)
+{
+ static bool early_boot = true;
+
+ if (unlikely(READ_ONCE(early_boot))) {
+ time64_t uptime = ktime_get_seconds();
+ if (uptime >= CRNG_RESEED_INTERVAL / HZ * 2)
+ WRITE_ONCE(early_boot, false);
+ else
+ return max_t(unsigned int, CRNG_RESEED_START_INTERVAL,
+ (unsigned int)uptime / 2 * HZ);
+ }
+ return CRNG_RESEED_INTERVAL;
+}
+
/* Used by crng_reseed() and crng_make_state() to extract a new seed from the input pool. */
static void extract_entropy(void *buf, size_t len);
/* This extracts a new crng key from the input pool. */
-static void crng_reseed(void)
+static void crng_reseed(struct work_struct *work)
{
+ static DECLARE_DELAYED_WORK(next_reseed, crng_reseed);
unsigned long flags;
unsigned long next_gen;
u8 key[CHACHA_KEY_SIZE];
+ /* Immediately schedule the next reseeding, so that it fires sooner rather than later. */
+ if (likely(system_unbound_wq))
+ queue_delayed_work(system_unbound_wq, &next_reseed, crng_reseed_interval());
+
extract_entropy(key, sizeof(key));
/*
@@ -221,7 +270,6 @@ static void crng_reseed(void)
if (next_gen == ULONG_MAX)
++next_gen;
WRITE_ONCE(base_crng.generation, next_gen);
- WRITE_ONCE(base_crng.birth, jiffies);
if (!static_branch_likely(&crng_is_ready))
crng_init = CRNG_READY;
spin_unlock_irqrestore(&base_crng.lock, flags);
@@ -261,26 +309,6 @@ static void crng_fast_key_erasure(u8 key[CHACHA_KEY_SIZE],
}
/*
- * Return the interval until the next reseeding, which is normally
- * CRNG_RESEED_INTERVAL, but during early boot, it is at an interval
- * proportional to the uptime.
- */
-static unsigned int crng_reseed_interval(void)
-{
- static bool early_boot = true;
-
- if (unlikely(READ_ONCE(early_boot))) {
- time64_t uptime = ktime_get_seconds();
- if (uptime >= CRNG_RESEED_INTERVAL / HZ * 2)
- WRITE_ONCE(early_boot, false);
- else
- return max_t(unsigned int, CRNG_RESEED_START_INTERVAL,
- (unsigned int)uptime / 2 * HZ);
- }
- return CRNG_RESEED_INTERVAL;
-}
-
-/*
* This function returns a ChaCha state that you may use for generating
* random data. It also returns up to 32 bytes on its own of random data
* that may be used; random_data_len may not be greater than 32.
@@ -315,13 +343,6 @@ static void crng_make_state(u32 chacha_state[CHACHA_STATE_WORDS],
return;
}
- /*
- * If the base_crng is old enough, we reseed, which in turn bumps the
- * generation counter that we check below.
- */
- if (unlikely(time_is_before_jiffies(READ_ONCE(base_crng.birth) + crng_reseed_interval())))
- crng_reseed();
-
local_lock_irqsave(&crngs.lock, flags);
crng = raw_cpu_ptr(&crngs);
@@ -383,11 +404,11 @@ static void _get_random_bytes(void *buf, size_t len)
}
/*
- * This function is the exported kernel interface. It returns some number of
- * good random numbers, suitable for key generation, seeding TCP sequence
- * numbers, etc. In order to ensure that the randomness returned by this
- * function is okay, the function wait_for_random_bytes() should be called and
- * return 0 at least once at any point prior.
+ * This returns random bytes in arbitrary quantities. The quality of the
+ * random bytes is good as /dev/urandom. In order to ensure that the
+ * randomness provided by this function is okay, the function
+ * wait_for_random_bytes() should be called and return 0 at least once
+ * at any point prior.
*/
void get_random_bytes(void *buf, size_t len)
{
@@ -510,6 +531,41 @@ DEFINE_BATCHED_ENTROPY(u16)
DEFINE_BATCHED_ENTROPY(u32)
DEFINE_BATCHED_ENTROPY(u64)
+u32 __get_random_u32_below(u32 ceil)
+{
+ /*
+ * This is the slow path for variable ceil. It is still fast, most of
+ * the time, by doing traditional reciprocal multiplication and
+ * opportunistically comparing the lower half to ceil itself, before
+ * falling back to computing a larger bound, and then rejecting samples
+ * whose lower half would indicate a range indivisible by ceil. The use
+ * of `-ceil % ceil` is analogous to `2^32 % ceil`, but is computable
+ * in 32-bits.
+ */
+ u32 rand = get_random_u32();
+ u64 mult;
+
+ /*
+ * This function is technically undefined for ceil == 0, and in fact
+ * for the non-underscored constant version in the header, we build bug
+ * on that. But for the non-constant case, it's convenient to have that
+ * evaluate to being a straight call to get_random_u32(), so that
+ * get_random_u32_inclusive() can work over its whole range without
+ * undefined behavior.
+ */
+ if (unlikely(!ceil))
+ return rand;
+
+ mult = (u64)ceil * rand;
+ if (unlikely((u32)mult < ceil)) {
+ u32 bound = -ceil % ceil;
+ while (unlikely((u32)mult < bound))
+ mult = (u64)ceil * get_random_u32();
+ }
+ return mult >> 32;
+}
+EXPORT_SYMBOL(__get_random_u32_below);
+
#ifdef CONFIG_SMP
/*
* This function is called when the CPU is coming up, with entry
@@ -660,9 +716,10 @@ static void __cold _credit_init_bits(size_t bits)
} while (!try_cmpxchg(&input_pool.init_bits, &orig, new));
if (orig < POOL_READY_BITS && new >= POOL_READY_BITS) {
- crng_reseed(); /* Sets crng_init to CRNG_READY under base_crng.lock. */
+ crng_reseed(NULL); /* Sets crng_init to CRNG_READY under base_crng.lock. */
if (static_key_initialized)
execute_in_process_context(crng_set_ready, &set_ready);
+ atomic_notifier_call_chain(&random_ready_notifier, 0, NULL);
wake_up_interruptible(&crng_init_wait);
kill_fasync(&fasync, SIGIO, POLL_IN);
pr_notice("crng init done\n");
@@ -689,7 +746,7 @@ static void __cold _credit_init_bits(size_t bits)
* the above entropy accumulation routines:
*
* void add_device_randomness(const void *buf, size_t len);
- * void add_hwgenerator_randomness(const void *buf, size_t len, size_t entropy);
+ * void add_hwgenerator_randomness(const void *buf, size_t len, size_t entropy, bool sleep_after);
* void add_bootloader_randomness(const void *buf, size_t len);
* void add_vmfork_randomness(const void *unique_vm_id, size_t len);
* void add_interrupt_randomness(int irq);
@@ -710,7 +767,7 @@ static void __cold _credit_init_bits(size_t bits)
*
* add_bootloader_randomness() is called by bootloader drivers, such as EFI
* and device tree, and credits its input depending on whether or not the
- * configuration option CONFIG_RANDOM_TRUST_BOOTLOADER is set.
+ * command line option 'random.trust_bootloader'.
*
* add_vmfork_randomness() adds a unique (but not necessarily secret) ID
* representing the current instance of a VM to the pool, without crediting,
@@ -736,8 +793,8 @@ static void __cold _credit_init_bits(size_t bits)
*
**********************************************************************/
-static bool trust_cpu __initdata = IS_ENABLED(CONFIG_RANDOM_TRUST_CPU);
-static bool trust_bootloader __initdata = IS_ENABLED(CONFIG_RANDOM_TRUST_BOOTLOADER);
+static bool trust_cpu __initdata = true;
+static bool trust_bootloader __initdata = true;
static int __init parse_trust_cpu(char *arg)
{
return kstrtobool(arg, &trust_cpu);
@@ -768,7 +825,7 @@ static int random_pm_notification(struct notifier_block *nb, unsigned long actio
if (crng_ready() && (action == PM_RESTORE_PREPARE ||
(action == PM_POST_SUSPEND && !IS_ENABLED(CONFIG_PM_AUTOSLEEP) &&
!IS_ENABLED(CONFIG_PM_USERSPACE_AUTOSLEEP)))) {
- crng_reseed();
+ crng_reseed(NULL);
pr_notice("crng reseeded on system resumption\n");
}
return 0;
@@ -791,13 +848,13 @@ void __init random_init_early(const char *command_line)
#endif
for (i = 0, arch_bits = sizeof(entropy) * 8; i < ARRAY_SIZE(entropy);) {
- longs = arch_get_random_seed_longs_early(entropy, ARRAY_SIZE(entropy) - i);
+ longs = arch_get_random_seed_longs(entropy, ARRAY_SIZE(entropy) - i);
if (longs) {
_mix_pool_bytes(entropy, sizeof(*entropy) * longs);
i += longs;
continue;
}
- longs = arch_get_random_longs_early(entropy, ARRAY_SIZE(entropy) - i);
+ longs = arch_get_random_longs(entropy, ARRAY_SIZE(entropy) - i);
if (longs) {
_mix_pool_bytes(entropy, sizeof(*entropy) * longs);
i += longs;
@@ -812,7 +869,7 @@ void __init random_init_early(const char *command_line)
/* Reseed if already seeded by earlier phases. */
if (crng_ready())
- crng_reseed();
+ crng_reseed(NULL);
else if (trust_cpu)
_credit_init_bits(arch_bits);
}
@@ -840,7 +897,7 @@ void __init random_init(void)
/* Reseed if already seeded by earlier phases. */
if (crng_ready())
- crng_reseed();
+ crng_reseed(NULL);
WARN_ON(register_pm_notifier(&pm_notifier));
@@ -869,11 +926,11 @@ void add_device_randomness(const void *buf, size_t len)
EXPORT_SYMBOL(add_device_randomness);
/*
- * Interface for in-kernel drivers of true hardware RNGs.
- * Those devices may produce endless random bits and will be throttled
- * when our pool is full.
+ * Interface for in-kernel drivers of true hardware RNGs. Those devices
+ * may produce endless random bits, so this function will sleep for
+ * some amount of time after, if the sleep_after parameter is true.
*/
-void add_hwgenerator_randomness(const void *buf, size_t len, size_t entropy)
+void add_hwgenerator_randomness(const void *buf, size_t len, size_t entropy, bool sleep_after)
{
mix_pool_bytes(buf, len);
credit_init_bits(entropy);
@@ -882,14 +939,14 @@ void add_hwgenerator_randomness(const void *buf, size_t len, size_t entropy)
* Throttle writing to once every reseed interval, unless we're not yet
* initialized or no entropy is credited.
*/
- if (!kthread_should_stop() && (crng_ready() || !entropy))
+ if (sleep_after && !kthread_should_stop() && (crng_ready() || !entropy))
schedule_timeout_interruptible(crng_reseed_interval());
}
EXPORT_SYMBOL_GPL(add_hwgenerator_randomness);
/*
- * Handle random seed passed by bootloader, and credit it if
- * CONFIG_RANDOM_TRUST_BOOTLOADER is set.
+ * Handle random seed passed by bootloader, and credit it depending
+ * on the command line option 'random.trust_bootloader'.
*/
void __init add_bootloader_randomness(const void *buf, size_t len)
{
@@ -910,7 +967,7 @@ void __cold add_vmfork_randomness(const void *unique_vm_id, size_t len)
{
add_device_randomness(unique_vm_id, len);
if (crng_ready()) {
- crng_reseed();
+ crng_reseed(NULL);
pr_notice("crng reseeded due to virtual machine fork\n");
}
blocking_notifier_call_chain(&vmfork_chain, 0, NULL);
@@ -1176,66 +1233,102 @@ void __cold rand_initialize_disk(struct gendisk *disk)
struct entropy_timer_state {
unsigned long entropy;
struct timer_list timer;
- unsigned int samples, samples_per_bit;
+ atomic_t samples;
+ unsigned int samples_per_bit;
};
/*
- * Each time the timer fires, we expect that we got an unpredictable
- * jump in the cycle counter. Even if the timer is running on another
- * CPU, the timer activity will be touching the stack of the CPU that is
- * generating entropy..
+ * Each time the timer fires, we expect that we got an unpredictable jump in
+ * the cycle counter. Even if the timer is running on another CPU, the timer
+ * activity will be touching the stack of the CPU that is generating entropy.
*
- * Note that we don't re-arm the timer in the timer itself - we are
- * happy to be scheduled away, since that just makes the load more
- * complex, but we do not want the timer to keep ticking unless the
- * entropy loop is running.
+ * Note that we don't re-arm the timer in the timer itself - we are happy to be
+ * scheduled away, since that just makes the load more complex, but we do not
+ * want the timer to keep ticking unless the entropy loop is running.
*
* So the re-arming always happens in the entropy loop itself.
*/
static void __cold entropy_timer(struct timer_list *timer)
{
struct entropy_timer_state *state = container_of(timer, struct entropy_timer_state, timer);
+ unsigned long entropy = random_get_entropy();
- if (++state->samples == state->samples_per_bit) {
+ mix_pool_bytes(&entropy, sizeof(entropy));
+ if (atomic_inc_return(&state->samples) % state->samples_per_bit == 0)
credit_init_bits(1);
- state->samples = 0;
- }
}
/*
- * If we have an actual cycle counter, see if we can
- * generate enough entropy with timing noise
+ * If we have an actual cycle counter, see if we can generate enough entropy
+ * with timing noise.
*/
static void __cold try_to_generate_entropy(void)
{
enum { NUM_TRIAL_SAMPLES = 8192, MAX_SAMPLES_PER_BIT = HZ / 15 };
- struct entropy_timer_state stack;
+ u8 stack_bytes[sizeof(struct entropy_timer_state) + SMP_CACHE_BYTES - 1];
+ struct entropy_timer_state *stack = PTR_ALIGN((void *)stack_bytes, SMP_CACHE_BYTES);
unsigned int i, num_different = 0;
unsigned long last = random_get_entropy();
+ int cpu = -1;
for (i = 0; i < NUM_TRIAL_SAMPLES - 1; ++i) {
- stack.entropy = random_get_entropy();
- if (stack.entropy != last)
+ stack->entropy = random_get_entropy();
+ if (stack->entropy != last)
++num_different;
- last = stack.entropy;
+ last = stack->entropy;
}
- stack.samples_per_bit = DIV_ROUND_UP(NUM_TRIAL_SAMPLES, num_different + 1);
- if (stack.samples_per_bit > MAX_SAMPLES_PER_BIT)
+ stack->samples_per_bit = DIV_ROUND_UP(NUM_TRIAL_SAMPLES, num_different + 1);
+ if (stack->samples_per_bit > MAX_SAMPLES_PER_BIT)
return;
- stack.samples = 0;
- timer_setup_on_stack(&stack.timer, entropy_timer, 0);
+ atomic_set(&stack->samples, 0);
+ timer_setup_on_stack(&stack->timer, entropy_timer, 0);
while (!crng_ready() && !signal_pending(current)) {
- if (!timer_pending(&stack.timer))
- mod_timer(&stack.timer, jiffies);
- mix_pool_bytes(&stack.entropy, sizeof(stack.entropy));
+ /*
+ * Check !timer_pending() and then ensure that any previous callback has finished
+ * executing by checking try_to_del_timer_sync(), before queueing the next one.
+ */
+ if (!timer_pending(&stack->timer) && try_to_del_timer_sync(&stack->timer) >= 0) {
+ struct cpumask timer_cpus;
+ unsigned int num_cpus;
+
+ /*
+ * Preemption must be disabled here, both to read the current CPU number
+ * and to avoid scheduling a timer on a dead CPU.
+ */
+ preempt_disable();
+
+ /* Only schedule callbacks on timer CPUs that are online. */
+ cpumask_and(&timer_cpus, housekeeping_cpumask(HK_TYPE_TIMER), cpu_online_mask);
+ num_cpus = cpumask_weight(&timer_cpus);
+ /* In very bizarre case of misconfiguration, fallback to all online. */
+ if (unlikely(num_cpus == 0)) {
+ timer_cpus = *cpu_online_mask;
+ num_cpus = cpumask_weight(&timer_cpus);
+ }
+
+ /* Basic CPU round-robin, which avoids the current CPU. */
+ do {
+ cpu = cpumask_next(cpu, &timer_cpus);
+ if (cpu == nr_cpumask_bits)
+ cpu = cpumask_first(&timer_cpus);
+ } while (cpu == smp_processor_id() && num_cpus > 1);
+
+ /* Expiring the timer at `jiffies` means it's the next tick. */
+ stack->timer.expires = jiffies;
+
+ add_timer_on(&stack->timer, cpu);
+
+ preempt_enable();
+ }
+ mix_pool_bytes(&stack->entropy, sizeof(stack->entropy));
schedule();
- stack.entropy = random_get_entropy();
+ stack->entropy = random_get_entropy();
}
+ mix_pool_bytes(&stack->entropy, sizeof(stack->entropy));
- del_timer_sync(&stack.timer);
- destroy_timer_on_stack(&stack.timer);
- mix_pool_bytes(&stack.entropy, sizeof(stack.entropy));
+ del_timer_sync(&stack->timer);
+ destroy_timer_on_stack(&stack->timer);
}
@@ -1291,7 +1384,7 @@ SYSCALL_DEFINE3(getrandom, char __user *, ubuf, size_t, len, unsigned int, flags
return ret;
}
- ret = import_single_range(READ, ubuf, len, &iov, &iter);
+ ret = import_single_range(ITER_DEST, ubuf, len, &iov, &iter);
if (unlikely(ret))
return ret;
return get_random_bytes_user(&iter);
@@ -1409,7 +1502,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
return -EINVAL;
if (get_user(len, p++))
return -EFAULT;
- ret = import_single_range(WRITE, p, len, &iov, &iter);
+ ret = import_single_range(ITER_SOURCE, p, len, &iov, &iter);
if (unlikely(ret))
return ret;
ret = write_pool_user(&iter);
@@ -1432,7 +1525,7 @@ static long random_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
return -EPERM;
if (!crng_ready())
return -ENODATA;
- crng_reseed();
+ crng_reseed(NULL);
return 0;
default:
return -EINVAL;
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 27e301a6bb7a..9211531689b2 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -1123,10 +1123,9 @@ static int sonypi_acpi_add(struct acpi_device *device)
return 0;
}
-static int sonypi_acpi_remove(struct acpi_device *device)
+static void sonypi_acpi_remove(struct acpi_device *device)
{
sonypi_acpi_device = NULL;
- return 0;
}
static const struct acpi_device_id sonypi_device_ids[] = {
diff --git a/drivers/char/tpm/eventlog/acpi.c b/drivers/char/tpm/eventlog/acpi.c
index 1b18ce5ebab1..0913d3eb8d51 100644
--- a/drivers/char/tpm/eventlog/acpi.c
+++ b/drivers/char/tpm/eventlog/acpi.c
@@ -90,16 +90,21 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
return -ENODEV;
if (tbl->header.length <
- sizeof(*tbl) + sizeof(struct acpi_tpm2_phy))
+ sizeof(*tbl) + sizeof(struct acpi_tpm2_phy)) {
+ acpi_put_table((struct acpi_table_header *)tbl);
return -ENODEV;
+ }
tpm2_phy = (void *)tbl + sizeof(*tbl);
len = tpm2_phy->log_area_minimum_length;
start = tpm2_phy->log_area_start_address;
- if (!start || !len)
+ if (!start || !len) {
+ acpi_put_table((struct acpi_table_header *)tbl);
return -ENODEV;
+ }
+ acpi_put_table((struct acpi_table_header *)tbl);
format = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
} else {
/* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
@@ -120,8 +125,10 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
break;
}
+ acpi_put_table((struct acpi_table_header *)buff);
format = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
}
+
if (!len) {
dev_warn(&chip->dev, "%s: TCPA log area empty\n", __func__);
return -EIO;
@@ -156,5 +163,4 @@ err:
kfree(log->bios_event_log);
log->bios_event_log = NULL;
return ret;
-
}
diff --git a/drivers/char/tpm/st33zp24/i2c.c b/drivers/char/tpm/st33zp24/i2c.c
index a3aa411389e7..8156bb2af78c 100644
--- a/drivers/char/tpm/st33zp24/i2c.c
+++ b/drivers/char/tpm/st33zp24/i2c.c
@@ -6,13 +6,9 @@
#include <linux/module.h>
#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/gpio/consumer.h>
-#include <linux/of_irq.h>
-#include <linux/of_gpio.h>
+#include <linux/of.h>
#include <linux/acpi.h>
#include <linux/tpm.h>
-#include <linux/platform_data/st33zp24.h>
#include "../tpm.h"
#include "st33zp24.h"
@@ -22,7 +18,6 @@
struct st33zp24_i2c_phy {
struct i2c_client *client;
u8 buf[ST33ZP24_BUFSIZE + 1];
- int io_lpcpd;
};
/*
@@ -99,115 +94,6 @@ static const struct st33zp24_phy_ops i2c_phy_ops = {
.recv = st33zp24_i2c_recv,
};
-static const struct acpi_gpio_params lpcpd_gpios = { 1, 0, false };
-
-static const struct acpi_gpio_mapping acpi_st33zp24_gpios[] = {
- { "lpcpd-gpios", &lpcpd_gpios, 1 },
- {},
-};
-
-static int st33zp24_i2c_acpi_request_resources(struct i2c_client *client)
-{
- struct tpm_chip *chip = i2c_get_clientdata(client);
- struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
- struct st33zp24_i2c_phy *phy = tpm_dev->phy_id;
- struct gpio_desc *gpiod_lpcpd;
- struct device *dev = &client->dev;
- int ret;
-
- ret = devm_acpi_dev_add_driver_gpios(dev, acpi_st33zp24_gpios);
- if (ret)
- return ret;
-
- /* Get LPCPD GPIO from ACPI */
- gpiod_lpcpd = devm_gpiod_get(dev, "lpcpd", GPIOD_OUT_HIGH);
- if (IS_ERR(gpiod_lpcpd)) {
- dev_err(&client->dev,
- "Failed to retrieve lpcpd-gpios from acpi.\n");
- phy->io_lpcpd = -1;
- /*
- * lpcpd pin is not specified. This is not an issue as
- * power management can be also managed by TPM specific
- * commands. So leave with a success status code.
- */
- return 0;
- }
-
- phy->io_lpcpd = desc_to_gpio(gpiod_lpcpd);
-
- return 0;
-}
-
-static int st33zp24_i2c_of_request_resources(struct i2c_client *client)
-{
- struct tpm_chip *chip = i2c_get_clientdata(client);
- struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
- struct st33zp24_i2c_phy *phy = tpm_dev->phy_id;
- struct device_node *pp;
- int gpio;
- int ret;
-
- pp = client->dev.of_node;
- if (!pp) {
- dev_err(&client->dev, "No platform data\n");
- return -ENODEV;
- }
-
- /* Get GPIO from device tree */
- gpio = of_get_named_gpio(pp, "lpcpd-gpios", 0);
- if (gpio < 0) {
- dev_err(&client->dev,
- "Failed to retrieve lpcpd-gpios from dts.\n");
- phy->io_lpcpd = -1;
- /*
- * lpcpd pin is not specified. This is not an issue as
- * power management can be also managed by TPM specific
- * commands. So leave with a success status code.
- */
- return 0;
- }
- /* GPIO request and configuration */
- ret = devm_gpio_request_one(&client->dev, gpio,
- GPIOF_OUT_INIT_HIGH, "TPM IO LPCPD");
- if (ret) {
- dev_err(&client->dev, "Failed to request lpcpd pin\n");
- return -ENODEV;
- }
- phy->io_lpcpd = gpio;
-
- return 0;
-}
-
-static int st33zp24_i2c_request_resources(struct i2c_client *client)
-{
- struct tpm_chip *chip = i2c_get_clientdata(client);
- struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
- struct st33zp24_i2c_phy *phy = tpm_dev->phy_id;
- struct st33zp24_platform_data *pdata;
- int ret;
-
- pdata = client->dev.platform_data;
- if (!pdata) {
- dev_err(&client->dev, "No platform data\n");
- return -ENODEV;
- }
-
- /* store for late use */
- phy->io_lpcpd = pdata->io_lpcpd;
-
- if (gpio_is_valid(pdata->io_lpcpd)) {
- ret = devm_gpio_request_one(&client->dev,
- pdata->io_lpcpd, GPIOF_OUT_INIT_HIGH,
- "TPM IO_LPCPD");
- if (ret) {
- dev_err(&client->dev, "Failed to request lpcpd pin\n");
- return ret;
- }
- }
-
- return 0;
-}
-
/*
* st33zp24_i2c_probe initialize the TPM device
* @param: client, the i2c_client description (TPM I2C description).
@@ -218,16 +104,8 @@ static int st33zp24_i2c_request_resources(struct i2c_client *client)
static int st33zp24_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- int ret;
- struct st33zp24_platform_data *pdata;
struct st33zp24_i2c_phy *phy;
- if (!client) {
- pr_info("%s: i2c client is NULL. Device not accessible.\n",
- __func__);
- return -ENODEV;
- }
-
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
dev_info(&client->dev, "client not i2c capable\n");
return -ENODEV;
@@ -240,23 +118,7 @@ static int st33zp24_i2c_probe(struct i2c_client *client,
phy->client = client;
- pdata = client->dev.platform_data;
- if (!pdata && client->dev.of_node) {
- ret = st33zp24_i2c_of_request_resources(client);
- if (ret)
- return ret;
- } else if (pdata) {
- ret = st33zp24_i2c_request_resources(client);
- if (ret)
- return ret;
- } else if (ACPI_HANDLE(&client->dev)) {
- ret = st33zp24_i2c_acpi_request_resources(client);
- if (ret)
- return ret;
- }
-
- return st33zp24_probe(phy, &i2c_phy_ops, &client->dev, client->irq,
- phy->io_lpcpd);
+ return st33zp24_probe(phy, &i2c_phy_ops, &client->dev, client->irq);
}
/*
diff --git a/drivers/char/tpm/st33zp24/spi.c b/drivers/char/tpm/st33zp24/spi.c
index 22d184884694..2154059f0235 100644
--- a/drivers/char/tpm/st33zp24/spi.c
+++ b/drivers/char/tpm/st33zp24/spi.c
@@ -6,13 +6,9 @@
#include <linux/module.h>
#include <linux/spi/spi.h>
-#include <linux/gpio.h>
-#include <linux/gpio/consumer.h>
-#include <linux/of_irq.h>
-#include <linux/of_gpio.h>
+#include <linux/of.h>
#include <linux/acpi.h>
#include <linux/tpm.h>
-#include <linux/platform_data/st33zp24.h>
#include "../tpm.h"
#include "st33zp24.h"
@@ -61,7 +57,6 @@ struct st33zp24_spi_phy {
u8 tx_buf[ST33ZP24_SPI_BUFFER_SIZE];
u8 rx_buf[ST33ZP24_SPI_BUFFER_SIZE];
- int io_lpcpd;
int latency;
};
@@ -218,115 +213,6 @@ static const struct st33zp24_phy_ops spi_phy_ops = {
.recv = st33zp24_spi_recv,
};
-static const struct acpi_gpio_params lpcpd_gpios = { 1, 0, false };
-
-static const struct acpi_gpio_mapping acpi_st33zp24_gpios[] = {
- { "lpcpd-gpios", &lpcpd_gpios, 1 },
- {},
-};
-
-static int st33zp24_spi_acpi_request_resources(struct spi_device *spi_dev)
-{
- struct tpm_chip *chip = spi_get_drvdata(spi_dev);
- struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
- struct st33zp24_spi_phy *phy = tpm_dev->phy_id;
- struct gpio_desc *gpiod_lpcpd;
- struct device *dev = &spi_dev->dev;
- int ret;
-
- ret = devm_acpi_dev_add_driver_gpios(dev, acpi_st33zp24_gpios);
- if (ret)
- return ret;
-
- /* Get LPCPD GPIO from ACPI */
- gpiod_lpcpd = devm_gpiod_get(dev, "lpcpd", GPIOD_OUT_HIGH);
- if (IS_ERR(gpiod_lpcpd)) {
- dev_err(dev, "Failed to retrieve lpcpd-gpios from acpi.\n");
- phy->io_lpcpd = -1;
- /*
- * lpcpd pin is not specified. This is not an issue as
- * power management can be also managed by TPM specific
- * commands. So leave with a success status code.
- */
- return 0;
- }
-
- phy->io_lpcpd = desc_to_gpio(gpiod_lpcpd);
-
- return 0;
-}
-
-static int st33zp24_spi_of_request_resources(struct spi_device *spi_dev)
-{
- struct tpm_chip *chip = spi_get_drvdata(spi_dev);
- struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
- struct st33zp24_spi_phy *phy = tpm_dev->phy_id;
- struct device_node *pp;
- int gpio;
- int ret;
-
- pp = spi_dev->dev.of_node;
- if (!pp) {
- dev_err(&spi_dev->dev, "No platform data\n");
- return -ENODEV;
- }
-
- /* Get GPIO from device tree */
- gpio = of_get_named_gpio(pp, "lpcpd-gpios", 0);
- if (gpio < 0) {
- dev_err(&spi_dev->dev,
- "Failed to retrieve lpcpd-gpios from dts.\n");
- phy->io_lpcpd = -1;
- /*
- * lpcpd pin is not specified. This is not an issue as
- * power management can be also managed by TPM specific
- * commands. So leave with a success status code.
- */
- return 0;
- }
- /* GPIO request and configuration */
- ret = devm_gpio_request_one(&spi_dev->dev, gpio,
- GPIOF_OUT_INIT_HIGH, "TPM IO LPCPD");
- if (ret) {
- dev_err(&spi_dev->dev, "Failed to request lpcpd pin\n");
- return -ENODEV;
- }
- phy->io_lpcpd = gpio;
-
- return 0;
-}
-
-static int st33zp24_spi_request_resources(struct spi_device *dev)
-{
- struct tpm_chip *chip = spi_get_drvdata(dev);
- struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
- struct st33zp24_spi_phy *phy = tpm_dev->phy_id;
- struct st33zp24_platform_data *pdata;
- int ret;
-
- pdata = dev->dev.platform_data;
- if (!pdata) {
- dev_err(&dev->dev, "No platform data\n");
- return -ENODEV;
- }
-
- /* store for late use */
- phy->io_lpcpd = pdata->io_lpcpd;
-
- if (gpio_is_valid(pdata->io_lpcpd)) {
- ret = devm_gpio_request_one(&dev->dev,
- pdata->io_lpcpd, GPIOF_OUT_INIT_HIGH,
- "TPM IO_LPCPD");
- if (ret) {
- dev_err(&dev->dev, "%s : reset gpio_request failed\n",
- __FILE__);
- return ret;
- }
- }
-
- return 0;
-}
-
/*
* st33zp24_spi_probe initialize the TPM device
* @param: dev, the spi_device description (TPM SPI description).
@@ -335,17 +221,8 @@ static int st33zp24_spi_request_resources(struct spi_device *dev)
*/
static int st33zp24_spi_probe(struct spi_device *dev)
{
- int ret;
- struct st33zp24_platform_data *pdata;
struct st33zp24_spi_phy *phy;
- /* Check SPI platform functionnalities */
- if (!dev) {
- pr_info("%s: dev is NULL. Device is not accessible.\n",
- __func__);
- return -ENODEV;
- }
-
phy = devm_kzalloc(&dev->dev, sizeof(struct st33zp24_spi_phy),
GFP_KERNEL);
if (!phy)
@@ -353,27 +230,11 @@ static int st33zp24_spi_probe(struct spi_device *dev)
phy->spi_device = dev;
- pdata = dev->dev.platform_data;
- if (!pdata && dev->dev.of_node) {
- ret = st33zp24_spi_of_request_resources(dev);
- if (ret)
- return ret;
- } else if (pdata) {
- ret = st33zp24_spi_request_resources(dev);
- if (ret)
- return ret;
- } else if (ACPI_HANDLE(&dev->dev)) {
- ret = st33zp24_spi_acpi_request_resources(dev);
- if (ret)
- return ret;
- }
-
phy->latency = st33zp24_spi_evaluate_latency(phy);
if (phy->latency <= 0)
return -ENODEV;
- return st33zp24_probe(phy, &spi_phy_ops, &dev->dev, dev->irq,
- phy->io_lpcpd);
+ return st33zp24_probe(phy, &spi_phy_ops, &dev->dev, dev->irq);
}
/*
@@ -411,7 +272,7 @@ static SIMPLE_DEV_PM_OPS(st33zp24_spi_ops, st33zp24_pm_suspend,
static struct spi_driver st33zp24_spi_driver = {
.driver = {
- .name = TPM_ST33_SPI,
+ .name = "st33zp24-spi",
.pm = &st33zp24_spi_ops,
.of_match_table = of_match_ptr(of_st33zp24_spi_match),
.acpi_match_table = ACPI_PTR(st33zp24_spi_acpi_match),
diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c
index 15b393e92c8e..a5b554cd4778 100644
--- a/drivers/char/tpm/st33zp24/st33zp24.c
+++ b/drivers/char/tpm/st33zp24/st33zp24.c
@@ -4,6 +4,7 @@
* Copyright (C) 2009 - 2016 STMicroelectronics
*/
+#include <linux/acpi.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/kernel.h>
@@ -12,7 +13,7 @@
#include <linux/freezer.h>
#include <linux/string.h>
#include <linux/interrupt.h>
-#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/io.h>
@@ -432,11 +433,18 @@ static const struct tpm_class_ops st33zp24_tpm = {
.req_canceled = st33zp24_req_canceled,
};
+static const struct acpi_gpio_params lpcpd_gpios = { 1, 0, false };
+
+static const struct acpi_gpio_mapping acpi_st33zp24_gpios[] = {
+ { "lpcpd-gpios", &lpcpd_gpios, 1 },
+ { },
+};
+
/*
* initialize the TPM device
*/
int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops,
- struct device *dev, int irq, int io_lpcpd)
+ struct device *dev, int irq)
{
int ret;
u8 intmask = 0;
@@ -463,6 +471,25 @@ int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops,
tpm_dev->locality = LOCALITY0;
+ if (ACPI_COMPANION(dev)) {
+ ret = devm_acpi_dev_add_driver_gpios(dev, acpi_st33zp24_gpios);
+ if (ret)
+ return ret;
+ }
+
+ /*
+ * Get LPCPD GPIO. If lpcpd pin is not specified. This is not an
+ * issue as power management can be also managed by TPM specific
+ * commands.
+ */
+ tpm_dev->io_lpcpd = devm_gpiod_get_optional(dev, "lpcpd",
+ GPIOD_OUT_HIGH);
+ ret = PTR_ERR_OR_ZERO(tpm_dev->io_lpcpd);
+ if (ret) {
+ dev_err(dev, "failed to request lpcpd gpio: %d\n", ret);
+ return ret;
+ }
+
if (irq) {
/* INTERRUPT Setup */
init_waitqueue_head(&tpm_dev->read_queue);
@@ -525,8 +552,8 @@ int st33zp24_pm_suspend(struct device *dev)
int ret = 0;
- if (gpio_is_valid(tpm_dev->io_lpcpd))
- gpio_set_value(tpm_dev->io_lpcpd, 0);
+ if (tpm_dev->io_lpcpd)
+ gpiod_set_value_cansleep(tpm_dev->io_lpcpd, 0);
else
ret = tpm_pm_suspend(dev);
@@ -540,8 +567,8 @@ int st33zp24_pm_resume(struct device *dev)
struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev);
int ret = 0;
- if (gpio_is_valid(tpm_dev->io_lpcpd)) {
- gpio_set_value(tpm_dev->io_lpcpd, 1);
+ if (tpm_dev->io_lpcpd) {
+ gpiod_set_value_cansleep(tpm_dev->io_lpcpd, 1);
ret = wait_for_stat(chip,
TPM_STS_VALID, chip->timeout_b,
&tpm_dev->read_queue, false);
diff --git a/drivers/char/tpm/st33zp24/st33zp24.h b/drivers/char/tpm/st33zp24/st33zp24.h
index b387a476c555..5acc85f711e6 100644
--- a/drivers/char/tpm/st33zp24/st33zp24.h
+++ b/drivers/char/tpm/st33zp24/st33zp24.h
@@ -7,6 +7,9 @@
#ifndef __LOCAL_ST33ZP24_H__
#define __LOCAL_ST33ZP24_H__
+#define TPM_ST33_I2C "st33zp24-i2c"
+#define TPM_ST33_SPI "st33zp24-spi"
+
#define TPM_WRITE_DIRECTION 0x80
#define ST33ZP24_BUFSIZE 2048
@@ -17,7 +20,7 @@ struct st33zp24_dev {
int locality;
int irq;
u32 intrs;
- int io_lpcpd;
+ struct gpio_desc *io_lpcpd;
wait_queue_head_t read_queue;
};
@@ -33,6 +36,6 @@ int st33zp24_pm_resume(struct device *dev);
#endif
int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops,
- struct device *dev, int irq, int io_lpcpd);
+ struct device *dev, int irq);
void st33zp24_remove(struct tpm_chip *chip);
#endif /* __LOCAL_ST33ZP24_H__ */
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 783d65fc71f0..741d8f3e8fb3 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -373,6 +373,11 @@ out:
}
EXPORT_SYMBOL_GPL(tpm_chip_alloc);
+static void tpm_put_device(void *dev)
+{
+ put_device(dev);
+}
+
/**
* tpmm_chip_alloc() - allocate a new struct tpm_chip instance
* @pdev: parent device to which the chip is associated
@@ -391,7 +396,7 @@ struct tpm_chip *tpmm_chip_alloc(struct device *pdev,
return chip;
rc = devm_add_action_or_reset(pdev,
- (void (*)(void *)) put_device,
+ tpm_put_device,
&chip->dev);
if (rc)
return ERR_PTR(rc);
diff --git a/drivers/char/tpm/tpm-dev-common.c b/drivers/char/tpm/tpm-dev-common.c
index dc4c0a0a5129..30b4c288c1bb 100644
--- a/drivers/char/tpm/tpm-dev-common.c
+++ b/drivers/char/tpm/tpm-dev-common.c
@@ -155,7 +155,7 @@ ssize_t tpm_common_read(struct file *file, char __user *buf,
out:
if (!priv->response_length) {
*off = 0;
- del_singleshot_timer_sync(&priv->user_read_timer);
+ del_timer_sync(&priv->user_read_timer);
flush_work(&priv->timeout_work);
}
mutex_unlock(&priv->buffer_mutex);
@@ -262,7 +262,7 @@ __poll_t tpm_common_poll(struct file *file, poll_table *wait)
void tpm_common_release(struct file *file, struct file_priv *priv)
{
flush_work(&priv->async_work);
- del_singleshot_timer_sync(&priv->user_read_timer);
+ del_timer_sync(&priv->user_read_timer);
flush_work(&priv->timeout_work);
file->private_data = NULL;
priv->response_length = 0;
diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c
index 18606651d1aa..7e9da671a0e8 100644
--- a/drivers/char/tpm/tpm_crb.c
+++ b/drivers/char/tpm/tpm_crb.c
@@ -252,7 +252,7 @@ static int __crb_relinquish_locality(struct device *dev,
iowrite32(CRB_LOC_CTRL_RELINQUISH, &priv->regs_h->loc_ctrl);
if (!crb_wait_for_reg_32(&priv->regs_h->loc_state, mask, value,
TPM2_TIMEOUT_C)) {
- dev_warn(dev, "TPM_LOC_STATE_x.requestAccess timed out\n");
+ dev_warn(dev, "TPM_LOC_STATE_x.Relinquish timed out\n");
return -ETIME;
}
@@ -676,12 +676,16 @@ static int crb_acpi_add(struct acpi_device *device)
/* Should the FIFO driver handle this? */
sm = buf->start_method;
- if (sm == ACPI_TPM2_MEMORY_MAPPED)
- return -ENODEV;
+ if (sm == ACPI_TPM2_MEMORY_MAPPED) {
+ rc = -ENODEV;
+ goto out;
+ }
priv = devm_kzalloc(dev, sizeof(struct crb_priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
+ if (!priv) {
+ rc = -ENOMEM;
+ goto out;
+ }
if (sm == ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC) {
if (buf->header.length < (sizeof(*buf) + sizeof(*crb_smc))) {
@@ -689,7 +693,8 @@ static int crb_acpi_add(struct acpi_device *device)
FW_BUG "TPM2 ACPI table has wrong size %u for start method type %d\n",
buf->header.length,
ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC);
- return -EINVAL;
+ rc = -EINVAL;
+ goto out;
}
crb_smc = ACPI_ADD_PTR(struct tpm2_crb_smc, buf, sizeof(*buf));
priv->smc_func_id = crb_smc->smc_func_id;
@@ -700,27 +705,31 @@ static int crb_acpi_add(struct acpi_device *device)
rc = crb_map_io(device, priv, buf);
if (rc)
- return rc;
+ goto out;
chip = tpmm_chip_alloc(dev, &tpm_crb);
- if (IS_ERR(chip))
- return PTR_ERR(chip);
+ if (IS_ERR(chip)) {
+ rc = PTR_ERR(chip);
+ goto out;
+ }
dev_set_drvdata(&chip->dev, priv);
chip->acpi_dev_handle = device->handle;
chip->flags = TPM_CHIP_FLAG_TPM2;
- return tpm_chip_register(chip);
+ rc = tpm_chip_register(chip);
+
+out:
+ acpi_put_table((struct acpi_table_header *)buf);
+ return rc;
}
-static int crb_acpi_remove(struct acpi_device *device)
+static void crb_acpi_remove(struct acpi_device *device)
{
struct device *dev = &device->dev;
struct tpm_chip *chip = dev_get_drvdata(dev);
tpm_chip_unregister(chip);
-
- return 0;
}
static const struct dev_pm_ops crb_pm = {
diff --git a/drivers/char/tpm/tpm_ftpm_tee.c b/drivers/char/tpm/tpm_ftpm_tee.c
index 5c233423c56f..deff23bb54bf 100644
--- a/drivers/char/tpm/tpm_ftpm_tee.c
+++ b/drivers/char/tpm/tpm_ftpm_tee.c
@@ -397,7 +397,13 @@ static int __init ftpm_mod_init(void)
if (rc)
return rc;
- return driver_register(&ftpm_tee_driver.driver);
+ rc = driver_register(&ftpm_tee_driver.driver);
+ if (rc) {
+ platform_driver_unregister(&ftpm_tee_plat_driver);
+ return rc;
+ }
+
+ return 0;
}
static void __exit ftpm_mod_exit(void)
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index bcff6429e0b4..ed5dabd3c72d 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -125,6 +125,7 @@ static int check_acpi_tpm2(struct device *dev)
const struct acpi_device_id *aid = acpi_match_device(tpm_acpi_tbl, dev);
struct acpi_table_tpm2 *tbl;
acpi_status st;
+ int ret = 0;
if (!aid || aid->driver_data != DEVICE_IS_TPM2)
return 0;
@@ -132,8 +133,7 @@ static int check_acpi_tpm2(struct device *dev)
/* If the ACPI TPM2 signature is matched then a global ACPI_SIG_TPM2
* table is mandatory
*/
- st =
- acpi_get_table(ACPI_SIG_TPM2, 1, (struct acpi_table_header **)&tbl);
+ st = acpi_get_table(ACPI_SIG_TPM2, 1, (struct acpi_table_header **)&tbl);
if (ACPI_FAILURE(st) || tbl->header.length < sizeof(*tbl)) {
dev_err(dev, FW_BUG "failed to get TPM2 ACPI table\n");
return -EINVAL;
@@ -141,9 +141,10 @@ static int check_acpi_tpm2(struct device *dev)
/* The tpm2_crb driver handles this device */
if (tbl->start_method != ACPI_TPM2_MEMORY_MAPPED)
- return -ENODEV;
+ ret = -ENODEV;
- return 0;
+ acpi_put_table((struct acpi_table_header *)tbl);
+ return ret;
}
#else
static int check_acpi_tpm2(struct device *dev)
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index 757623bacfd5..3f98e587b3e8 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -682,15 +682,19 @@ static bool tpm_tis_req_canceled(struct tpm_chip *chip, u8 status)
{
struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
- switch (priv->manufacturer_id) {
- case TPM_VID_WINBOND:
- return ((status == TPM_STS_VALID) ||
- (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY)));
- case TPM_VID_STM:
- return (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY));
- default:
- return (status == TPM_STS_COMMAND_READY);
+ if (!test_bit(TPM_TIS_DEFAULT_CANCELLATION, &priv->flags)) {
+ switch (priv->manufacturer_id) {
+ case TPM_VID_WINBOND:
+ return ((status == TPM_STS_VALID) ||
+ (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY)));
+ case TPM_VID_STM:
+ return (status == (TPM_STS_VALID | TPM_STS_COMMAND_READY));
+ default:
+ break;
+ }
}
+
+ return status == TPM_STS_COMMAND_READY;
}
static irqreturn_t tis_int_handler(int dummy, void *dev_id)
diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h
index 66a5a13cd1df..b68479e0de10 100644
--- a/drivers/char/tpm/tpm_tis_core.h
+++ b/drivers/char/tpm/tpm_tis_core.h
@@ -86,6 +86,7 @@ enum tis_defaults {
enum tpm_tis_flags {
TPM_TIS_ITPM_WORKAROUND = BIT(0),
TPM_TIS_INVALID_STATUS = BIT(1),
+ TPM_TIS_DEFAULT_CANCELLATION = BIT(2),
};
struct tpm_tis_data {
diff --git a/drivers/char/tpm/tpm_tis_i2c.c b/drivers/char/tpm/tpm_tis_i2c.c
index 0692510dfcab..f3a7251c8e38 100644
--- a/drivers/char/tpm/tpm_tis_i2c.c
+++ b/drivers/char/tpm/tpm_tis_i2c.c
@@ -49,7 +49,7 @@
/* Masks with bits that must be read zero */
#define TPM_ACCESS_READ_ZERO 0x48
-#define TPM_INT_ENABLE_ZERO 0x7FFFFF6
+#define TPM_INT_ENABLE_ZERO 0x7FFFFF60
#define TPM_STS_READ_ZERO 0x23
#define TPM_INTF_CAPABILITY_ZERO 0x0FFFF000
#define TPM_I2C_INTERFACE_CAPABILITY_ZERO 0x80000000
@@ -329,6 +329,7 @@ static int tpm_tis_i2c_probe(struct i2c_client *dev,
if (!phy->io_buf)
return -ENOMEM;
+ set_bit(TPM_TIS_DEFAULT_CANCELLATION, &phy->priv.flags);
phy->i2c_client = dev;
/* must precede all communication with the tpm */
diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c
index 679f4649a7ef..ce2f93479736 100644
--- a/drivers/clk/bcm/clk-raspberrypi.c
+++ b/drivers/clk/bcm/clk-raspberrypi.c
@@ -18,25 +18,6 @@
#include <soc/bcm2835/raspberrypi-firmware.h>
-enum rpi_firmware_clk_id {
- RPI_FIRMWARE_EMMC_CLK_ID = 1,
- RPI_FIRMWARE_UART_CLK_ID,
- RPI_FIRMWARE_ARM_CLK_ID,
- RPI_FIRMWARE_CORE_CLK_ID,
- RPI_FIRMWARE_V3D_CLK_ID,
- RPI_FIRMWARE_H264_CLK_ID,
- RPI_FIRMWARE_ISP_CLK_ID,
- RPI_FIRMWARE_SDRAM_CLK_ID,
- RPI_FIRMWARE_PIXEL_CLK_ID,
- RPI_FIRMWARE_PWM_CLK_ID,
- RPI_FIRMWARE_HEVC_CLK_ID,
- RPI_FIRMWARE_EMMC2_CLK_ID,
- RPI_FIRMWARE_M2MC_CLK_ID,
- RPI_FIRMWARE_PIXEL_BVB_CLK_ID,
- RPI_FIRMWARE_VEC_CLK_ID,
- RPI_FIRMWARE_NUM_CLK_ID,
-};
-
static char *rpi_firmware_clk_names[] = {
[RPI_FIRMWARE_EMMC_CLK_ID] = "emmc",
[RPI_FIRMWARE_UART_CLK_ID] = "uart",
diff --git a/drivers/clk/clk-bulk.c b/drivers/clk/clk-bulk.c
index e9e16425c739..826b3ff99433 100644
--- a/drivers/clk/clk-bulk.c
+++ b/drivers/clk/clk-bulk.c
@@ -96,9 +96,9 @@ static int __clk_bulk_get(struct device *dev, int num_clks,
if (ret == -ENOENT && optional)
continue;
- if (ret != -EPROBE_DEFER)
- dev_err(dev, "Failed to get clk '%s': %d\n",
- clks[i].id, ret);
+ dev_err_probe(dev, ret,
+ "Failed to get clk '%s'\n",
+ clks[i].id);
goto err;
}
}
diff --git a/drivers/clk/clk-cdce925.c b/drivers/clk/clk-cdce925.c
index ef9a2d44e40c..6350682f7e6d 100644
--- a/drivers/clk/clk-cdce925.c
+++ b/drivers/clk/clk-cdce925.c
@@ -603,28 +603,15 @@ of_clk_cdce925_get(struct of_phandle_args *clkspec, void *_data)
return &data->clk[idx].hw;
}
-static void cdce925_regulator_disable(void *regulator)
-{
- regulator_disable(regulator);
-}
-
static int cdce925_regulator_enable(struct device *dev, const char *name)
{
- struct regulator *regulator;
int err;
- regulator = devm_regulator_get(dev, name);
- if (IS_ERR(regulator))
- return PTR_ERR(regulator);
-
- err = regulator_enable(regulator);
- if (err) {
- dev_err(dev, "Failed to enable %s: %d\n", name, err);
- return err;
- }
+ err = devm_regulator_get_enable(dev, name);
+ if (err)
+ dev_err_probe(dev, err, "Failed to enable %s:\n", name);
- return devm_add_action_or_reset(dev, cdce925_regulator_disable,
- regulator);
+ return err;
}
/* The CDCE925 uses a funky way to read/write registers. Bulk mode is
diff --git a/drivers/clk/clk-fractional-divider.c b/drivers/clk/clk-fractional-divider.c
index 8efa5142ff8c..6affe3565025 100644
--- a/drivers/clk/clk-fractional-divider.c
+++ b/drivers/clk/clk-fractional-divider.c
@@ -38,12 +38,15 @@
* saturated values.
*/
-#include <linux/clk-provider.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
#include <linux/io.h>
+#include <linux/math.h>
#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/slab.h>
#include <linux/rational.h>
+#include <linux/slab.h>
+
+#include <linux/clk-provider.h>
#include "clk-fractional-divider.h"
@@ -63,14 +66,12 @@ static inline void clk_fd_writel(struct clk_fractional_divider *fd, u32 val)
writel(val, fd->reg);
}
-static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
+static void clk_fd_get_div(struct clk_hw *hw, struct u32_fract *fract)
{
struct clk_fractional_divider *fd = to_clk_fd(hw);
unsigned long flags = 0;
unsigned long m, n;
u32 val;
- u64 ret;
if (fd->lock)
spin_lock_irqsave(fd->lock, flags);
@@ -92,11 +93,22 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
n++;
}
- if (!n || !m)
+ fract->numerator = m;
+ fract->denominator = n;
+}
+
+static unsigned long clk_fd_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+ struct u32_fract fract;
+ u64 ret;
+
+ clk_fd_get_div(hw, &fract);
+
+ if (!fract.numerator || !fract.denominator)
return parent_rate;
- ret = (u64)parent_rate * m;
- do_div(ret, n);
+ ret = (u64)parent_rate * fract.numerator;
+ do_div(ret, fract.denominator);
return ret;
}
@@ -183,10 +195,45 @@ static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}
+#ifdef CONFIG_DEBUG_FS
+static int clk_fd_numerator_get(void *hw, u64 *val)
+{
+ struct u32_fract fract;
+
+ clk_fd_get_div(hw, &fract);
+
+ *val = fract.numerator;
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(clk_fd_numerator_fops, clk_fd_numerator_get, NULL, "%llu\n");
+
+static int clk_fd_denominator_get(void *hw, u64 *val)
+{
+ struct u32_fract fract;
+
+ clk_fd_get_div(hw, &fract);
+
+ *val = fract.denominator;
+
+ return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(clk_fd_denominator_fops, clk_fd_denominator_get, NULL, "%llu\n");
+
+static void clk_fd_debug_init(struct clk_hw *hw, struct dentry *dentry)
+{
+ debugfs_create_file("numerator", 0444, dentry, hw, &clk_fd_numerator_fops);
+ debugfs_create_file("denominator", 0444, dentry, hw, &clk_fd_denominator_fops);
+}
+#endif
+
const struct clk_ops clk_fractional_divider_ops = {
.recalc_rate = clk_fd_recalc_rate,
.round_rate = clk_fd_round_rate,
.set_rate = clk_fd_set_rate,
+#ifdef CONFIG_DEBUG_FS
+ .debug_init = clk_fd_debug_init,
+#endif
};
EXPORT_SYMBOL_GPL(clk_fractional_divider_ops);
diff --git a/drivers/clk/clk-lmk04832.c b/drivers/clk/clk-lmk04832.c
index f416f8bc2898..57485356de4c 100644
--- a/drivers/clk/clk-lmk04832.c
+++ b/drivers/clk/clk-lmk04832.c
@@ -12,12 +12,10 @@
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
-#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/gcd.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
-#include <linux/uaccess.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
@@ -177,14 +175,14 @@ enum lmk04832_device_types {
};
/**
- * lmk04832_device_info - Holds static device information that is specific to
- * the chip revision
+ * struct lmk04832_device_info - Holds static device information that is
+ * specific to the chip revision
*
- * pid: Product Identifier
- * maskrev: IC version identifier
- * num_channels: Number of available output channels (clkout count)
- * vco0_range: {min, max} of the VCO0 operating range (in MHz)
- * vco1_range: {min, max} of the VCO1 operating range (in MHz)
+ * @pid: Product Identifier
+ * @maskrev: IC version identifier
+ * @num_channels: Number of available output channels (clkout count)
+ * @vco0_range: {min, max} of the VCO0 operating range (in MHz)
+ * @vco1_range: {min, max} of the VCO1 operating range (in MHz)
*/
struct lmk04832_device_info {
u16 pid;
@@ -282,7 +280,7 @@ static bool lmk04832_regmap_rd_regs(struct device *dev, unsigned int reg)
default:
return false;
};
-};
+}
static bool lmk04832_regmap_wr_regs(struct device *dev, unsigned int reg)
{
@@ -305,7 +303,7 @@ static bool lmk04832_regmap_wr_regs(struct device *dev, unsigned int reg)
default:
return false;
};
-};
+}
static const struct regmap_config regmap_config = {
.name = "lmk04832",
@@ -371,7 +369,7 @@ static unsigned long lmk04832_vco_recalc_rate(struct clk_hw *hw,
unsigned long prate)
{
struct lmk04832 *lmk = container_of(hw, struct lmk04832, vco);
- unsigned int pll2_p[] = {8, 2, 2, 3, 4, 5, 6, 7};
+ const unsigned int pll2_p[] = {8, 2, 2, 3, 4, 5, 6, 7};
unsigned int pll2_n, p, pll2_r;
unsigned int pll2_misc;
unsigned long vco_rate;
@@ -403,7 +401,7 @@ static unsigned long lmk04832_vco_recalc_rate(struct clk_hw *hw,
pll2_misc)) * pll2_n * pll2_p[p] / pll2_r;
return vco_rate;
-};
+}
/**
* lmk04832_check_vco_ranges - Check requested VCO frequency against VCO ranges
@@ -414,7 +412,7 @@ static unsigned long lmk04832_vco_recalc_rate(struct clk_hw *hw,
* The LMK04832 has 2 internal VCO, each with independent operating ranges.
* Use the device_info structure to determine which VCO to use based on rate.
*
- * Returns VCO_MUX value or negative errno.
+ * Returns: VCO_MUX value or negative errno.
*/
static int lmk04832_check_vco_ranges(struct lmk04832 *lmk, unsigned long rate)
{
@@ -451,7 +449,7 @@ static int lmk04832_check_vco_ranges(struct lmk04832 *lmk, unsigned long rate)
*
* VCO = OSCin * 2 * PLL2_N * PLL2_P / PLL2_R
*
- * Returns vco rate or negative errno.
+ * Returns: vco rate or negative errno.
*/
static long lmk04832_calc_pll2_params(unsigned long prate, unsigned long rate,
unsigned int *n, unsigned int *p,
@@ -509,7 +507,7 @@ static long lmk04832_vco_round_rate(struct clk_hw *hw, unsigned long rate,
return -EINVAL;
return vco_rate;
-};
+}
static int lmk04832_vco_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long prate)
@@ -568,7 +566,7 @@ static int lmk04832_vco_set_rate(struct clk_hw *hw, unsigned long rate,
return regmap_write(lmk->regmap, LMK04832_REG_PLL2_N_2,
FIELD_GET(0x0000ff, n));
-};
+}
static const struct clk_ops lmk04832_vco_ops = {
.is_enabled = lmk04832_vco_is_enabled,
@@ -633,7 +631,7 @@ static int lmk04832_register_vco(struct lmk04832 *lmk)
static int lmk04832_clkout_set_ddly(struct lmk04832 *lmk, int id)
{
- int dclk_div_adj[] = {0, 0, -2, -2, 0, 3, -1, 0};
+ const int dclk_div_adj[] = {0, 0, -2, -2, 0, 3, -1, 0};
unsigned int sclkx_y_ddly = 10;
unsigned int dclkx_y_ddly;
unsigned int dclkx_y_div;
@@ -1063,7 +1061,7 @@ static unsigned long lmk04832_dclk_recalc_rate(struct clk_hw *hw,
rate = DIV_ROUND_CLOSEST(prate, dclk_div);
return rate;
-};
+}
static long lmk04832_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
@@ -1085,7 +1083,7 @@ static long lmk04832_dclk_round_rate(struct clk_hw *hw, unsigned long rate,
return -EINVAL;
return dclk_rate;
-};
+}
static int lmk04832_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long prate)
@@ -1147,7 +1145,7 @@ static int lmk04832_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
dev_err(lmk->dev, "SYNC sequence failed\n");
return ret;
-};
+}
static const struct clk_ops lmk04832_dclk_ops = {
.is_enabled = lmk04832_dclk_is_enabled,
@@ -1551,6 +1549,7 @@ static void lmk04832_remove(struct spi_device *spi)
clk_disable_unprepare(lmk->oscin);
of_clk_del_provider(spi->dev.of_node);
}
+
static const struct spi_device_id lmk04832_id[] = {
{ "lmk04832", LMK04832 },
{}
diff --git a/drivers/clk/clk-nomadik.c b/drivers/clk/clk-nomadik.c
index 71fbe687fa7b..06245681dac7 100644
--- a/drivers/clk/clk-nomadik.c
+++ b/drivers/clk/clk-nomadik.c
@@ -138,7 +138,7 @@ out_put:
}
/**
- * struct clk_pll1 - Nomadik PLL1 clock
+ * struct clk_pll - Nomadik PLL clock
* @hw: corresponding clock hardware entry
* @id: PLL instance: 1 or 2
*/
diff --git a/drivers/clk/clk-stm32mp1.c b/drivers/clk/clk-stm32mp1.c
index 7ad2e6203bae..01e5a466897f 100644
--- a/drivers/clk/clk-stm32mp1.c
+++ b/drivers/clk/clk-stm32mp1.c
@@ -155,7 +155,7 @@ static const char * const eth_src[] = {
"pll4_p", "pll3_q"
};
-const struct clk_parent_data ethrx_src[] = {
+static const struct clk_parent_data ethrx_src[] = {
{ .name = "ethck_k", .fw_name = "ETH_RX_CLK/ETH_REF_CLK" },
};
diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c
index 88689415aff9..e9737969170e 100644
--- a/drivers/clk/clk-versaclock5.c
+++ b/drivers/clk/clk-versaclock5.c
@@ -20,7 +20,6 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
-#include <linux/rational.h>
#include <linux/regmap.h>
#include <linux/slab.h>
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 57b83665e5c3..e62552a75f08 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -603,10 +603,15 @@ int clk_mux_determine_rate_flags(struct clk_hw *hw,
}
clk_core_forward_rate_req(core, req, parent, &parent_req, req->rate);
+
+ trace_clk_rate_request_start(&parent_req);
+
ret = clk_core_round_rate_nolock(parent, &parent_req);
if (ret)
return ret;
+ trace_clk_rate_request_done(&parent_req);
+
best = parent_req.rate;
} else if (parent) {
best = clk_core_get_rate_nolock(parent);
@@ -630,10 +635,15 @@ int clk_mux_determine_rate_flags(struct clk_hw *hw,
struct clk_rate_request parent_req;
clk_core_forward_rate_req(core, req, parent, &parent_req, req->rate);
+
+ trace_clk_rate_request_start(&parent_req);
+
ret = clk_core_round_rate_nolock(parent, &parent_req);
if (ret)
continue;
+ trace_clk_rate_request_done(&parent_req);
+
parent_rate = parent_req.rate;
} else {
parent_rate = clk_core_get_rate_nolock(parent);
@@ -1468,6 +1478,7 @@ static void clk_core_init_rate_req(struct clk_core * const core,
if (!core)
return;
+ req->core = core;
req->rate = rate;
clk_core_get_boundaries(core, &req->min_rate, &req->max_rate);
@@ -1550,10 +1561,15 @@ static int clk_core_round_rate_nolock(struct clk_core *core,
struct clk_rate_request parent_req;
clk_core_forward_rate_req(core, req, core->parent, &parent_req, req->rate);
+
+ trace_clk_rate_request_start(&parent_req);
+
ret = clk_core_round_rate_nolock(core->parent, &parent_req);
if (ret)
return ret;
+ trace_clk_rate_request_done(&parent_req);
+
req->best_parent_rate = parent_req.rate;
req->rate = parent_req.rate;
@@ -1604,10 +1620,14 @@ unsigned long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate)
clk_core_init_rate_req(hw->core, &req, rate);
+ trace_clk_rate_request_start(&req);
+
ret = clk_core_round_rate_nolock(hw->core, &req);
if (ret)
return 0;
+ trace_clk_rate_request_done(&req);
+
return req.rate;
}
EXPORT_SYMBOL_GPL(clk_hw_round_rate);
@@ -1636,8 +1656,12 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
clk_core_init_rate_req(clk->core, &req, rate);
+ trace_clk_rate_request_start(&req);
+
ret = clk_core_round_rate_nolock(clk->core, &req);
+ trace_clk_rate_request_done(&req);
+
if (clk->exclusive_count)
clk_core_rate_protect(clk->core);
@@ -2129,10 +2153,14 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
clk_core_init_rate_req(core, &req, rate);
+ trace_clk_rate_request_start(&req);
+
ret = clk_core_determine_round_nolock(core, &req);
if (ret < 0)
return NULL;
+ trace_clk_rate_request_done(&req);
+
best_parent_rate = req.best_parent_rate;
new_rate = req.rate;
parent = req.best_parent_hw ? req.best_parent_hw->core : NULL;
@@ -2328,8 +2356,12 @@ static unsigned long clk_core_req_round_rate_nolock(struct clk_core *core,
clk_core_init_rate_req(core, &req, req_rate);
+ trace_clk_rate_request_start(&req);
+
ret = clk_core_round_rate_nolock(core, &req);
+ trace_clk_rate_request_done(&req);
+
/* restore the protection */
clk_core_rate_restore_protect(core, cnt);
diff --git a/drivers/clk/imx/clk-imx6sll.c b/drivers/clk/imx/clk-imx6sll.c
index 31d777f30039..1c9351649eab 100644
--- a/drivers/clk/imx/clk-imx6sll.c
+++ b/drivers/clk/imx/clk-imx6sll.c
@@ -91,12 +91,12 @@ static void __init imx6sll_clocks_init(struct device_node *ccm_node)
hws[IMX6SLL_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
- hws[IMX6SLL_CLK_CKIL] = imx_obtain_fixed_clk_hw(ccm_node, "ckil");
- hws[IMX6SLL_CLK_OSC] = imx_obtain_fixed_clk_hw(ccm_node, "osc");
+ hws[IMX6SLL_CLK_CKIL] = imx_get_clk_hw_by_name(ccm_node, "ckil");
+ hws[IMX6SLL_CLK_OSC] = imx_get_clk_hw_by_name(ccm_node, "osc");
/* ipp_di clock is external input */
- hws[IMX6SLL_CLK_IPP_DI0] = imx_obtain_fixed_clk_hw(ccm_node, "ipp_di0");
- hws[IMX6SLL_CLK_IPP_DI1] = imx_obtain_fixed_clk_hw(ccm_node, "ipp_di1");
+ hws[IMX6SLL_CLK_IPP_DI0] = imx_get_clk_hw_by_name(ccm_node, "ipp_di0");
+ hws[IMX6SLL_CLK_IPP_DI1] = imx_get_clk_hw_by_name(ccm_node, "ipp_di1");
np = of_find_compatible_node(NULL, NULL, "fsl,imx6sll-anatop");
base = of_iomap(np, 0);
diff --git a/drivers/clk/imx/clk-imx6sx.c b/drivers/clk/imx/clk-imx6sx.c
index 598f3cf4eba4..b378531240e6 100644
--- a/drivers/clk/imx/clk-imx6sx.c
+++ b/drivers/clk/imx/clk-imx6sx.c
@@ -132,16 +132,16 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
hws[IMX6SX_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
- hws[IMX6SX_CLK_CKIL] = imx_obtain_fixed_clk_hw(ccm_node, "ckil");
- hws[IMX6SX_CLK_OSC] = imx_obtain_fixed_clk_hw(ccm_node, "osc");
+ hws[IMX6SX_CLK_CKIL] = imx_get_clk_hw_by_name(ccm_node, "ckil");
+ hws[IMX6SX_CLK_OSC] = imx_get_clk_hw_by_name(ccm_node, "osc");
/* ipp_di clock is external input */
- hws[IMX6SX_CLK_IPP_DI0] = imx_obtain_fixed_clk_hw(ccm_node, "ipp_di0");
- hws[IMX6SX_CLK_IPP_DI1] = imx_obtain_fixed_clk_hw(ccm_node, "ipp_di1");
+ hws[IMX6SX_CLK_IPP_DI0] = imx_get_clk_hw_by_name(ccm_node, "ipp_di0");
+ hws[IMX6SX_CLK_IPP_DI1] = imx_get_clk_hw_by_name(ccm_node, "ipp_di1");
/* Clock source from external clock via CLK1/2 PAD */
- hws[IMX6SX_CLK_ANACLK1] = imx_obtain_fixed_clk_hw(ccm_node, "anaclk1");
- hws[IMX6SX_CLK_ANACLK2] = imx_obtain_fixed_clk_hw(ccm_node, "anaclk2");
+ hws[IMX6SX_CLK_ANACLK1] = imx_get_clk_hw_by_name(ccm_node, "anaclk1");
+ hws[IMX6SX_CLK_ANACLK2] = imx_get_clk_hw_by_name(ccm_node, "anaclk2");
np = of_find_compatible_node(NULL, NULL, "fsl,imx6sx-anatop");
base = of_iomap(np, 0);
diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c
index 520b100bff4b..67a7a77ca540 100644
--- a/drivers/clk/imx/clk-imx6ul.c
+++ b/drivers/clk/imx/clk-imx6ul.c
@@ -126,12 +126,12 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
hws[IMX6UL_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
- hws[IMX6UL_CLK_CKIL] = imx_obtain_fixed_clk_hw(ccm_node, "ckil");
- hws[IMX6UL_CLK_OSC] = imx_obtain_fixed_clk_hw(ccm_node, "osc");
+ hws[IMX6UL_CLK_CKIL] = imx_get_clk_hw_by_name(ccm_node, "ckil");
+ hws[IMX6UL_CLK_OSC] = imx_get_clk_hw_by_name(ccm_node, "osc");
/* ipp_di clock is external input */
- hws[IMX6UL_CLK_IPP_DI0] = imx_obtain_fixed_clk_hw(ccm_node, "ipp_di0");
- hws[IMX6UL_CLK_IPP_DI1] = imx_obtain_fixed_clk_hw(ccm_node, "ipp_di1");
+ hws[IMX6UL_CLK_IPP_DI0] = imx_get_clk_hw_by_name(ccm_node, "ipp_di0");
+ hws[IMX6UL_CLK_IPP_DI1] = imx_get_clk_hw_by_name(ccm_node, "ipp_di1");
np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-anatop");
base = of_iomap(np, 0);
diff --git a/drivers/clk/imx/clk-imx7d.c b/drivers/clk/imx/clk-imx7d.c
index cbf8131c63f7..d681b6c4b29a 100644
--- a/drivers/clk/imx/clk-imx7d.c
+++ b/drivers/clk/imx/clk-imx7d.c
@@ -391,8 +391,8 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
hws = clk_hw_data->hws;
hws[IMX7D_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
- hws[IMX7D_OSC_24M_CLK] = imx_obtain_fixed_clk_hw(ccm_node, "osc");
- hws[IMX7D_CKIL] = imx_obtain_fixed_clk_hw(ccm_node, "ckil");
+ hws[IMX7D_OSC_24M_CLK] = imx_get_clk_hw_by_name(ccm_node, "osc");
+ hws[IMX7D_CKIL] = imx_get_clk_hw_by_name(ccm_node, "ckil");
np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-anatop");
base = of_iomap(np, 0);
diff --git a/drivers/clk/imx/clk-imx7ulp.c b/drivers/clk/imx/clk-imx7ulp.c
index b6e45e77ee39..208a0ab80d5e 100644
--- a/drivers/clk/imx/clk-imx7ulp.c
+++ b/drivers/clk/imx/clk-imx7ulp.c
@@ -59,11 +59,11 @@ static void __init imx7ulp_clk_scg1_init(struct device_node *np)
hws[IMX7ULP_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
- hws[IMX7ULP_CLK_ROSC] = imx_obtain_fixed_clk_hw(np, "rosc");
- hws[IMX7ULP_CLK_SOSC] = imx_obtain_fixed_clk_hw(np, "sosc");
- hws[IMX7ULP_CLK_SIRC] = imx_obtain_fixed_clk_hw(np, "sirc");
- hws[IMX7ULP_CLK_FIRC] = imx_obtain_fixed_clk_hw(np, "firc");
- hws[IMX7ULP_CLK_UPLL] = imx_obtain_fixed_clk_hw(np, "upll");
+ hws[IMX7ULP_CLK_ROSC] = imx_get_clk_hw_by_name(np, "rosc");
+ hws[IMX7ULP_CLK_SOSC] = imx_get_clk_hw_by_name(np, "sosc");
+ hws[IMX7ULP_CLK_SIRC] = imx_get_clk_hw_by_name(np, "sirc");
+ hws[IMX7ULP_CLK_FIRC] = imx_get_clk_hw_by_name(np, "firc");
+ hws[IMX7ULP_CLK_UPLL] = imx_get_clk_hw_by_name(np, "upll");
/* SCG1 */
base = of_iomap(np, 0);
diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
index b6d275855b36..cb44e8148e53 100644
--- a/drivers/clk/imx/clk-imx8mm.c
+++ b/drivers/clk/imx/clk-imx8mm.c
@@ -312,12 +312,12 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
hws = clk_hw_data->hws;
hws[IMX8MM_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
- hws[IMX8MM_CLK_24M] = imx_obtain_fixed_clk_hw(np, "osc_24m");
- hws[IMX8MM_CLK_32K] = imx_obtain_fixed_clk_hw(np, "osc_32k");
- hws[IMX8MM_CLK_EXT1] = imx_obtain_fixed_clk_hw(np, "clk_ext1");
- hws[IMX8MM_CLK_EXT2] = imx_obtain_fixed_clk_hw(np, "clk_ext2");
- hws[IMX8MM_CLK_EXT3] = imx_obtain_fixed_clk_hw(np, "clk_ext3");
- hws[IMX8MM_CLK_EXT4] = imx_obtain_fixed_clk_hw(np, "clk_ext4");
+ hws[IMX8MM_CLK_24M] = imx_get_clk_hw_by_name(np, "osc_24m");
+ hws[IMX8MM_CLK_32K] = imx_get_clk_hw_by_name(np, "osc_32k");
+ hws[IMX8MM_CLK_EXT1] = imx_get_clk_hw_by_name(np, "clk_ext1");
+ hws[IMX8MM_CLK_EXT2] = imx_get_clk_hw_by_name(np, "clk_ext2");
+ hws[IMX8MM_CLK_EXT3] = imx_get_clk_hw_by_name(np, "clk_ext3");
+ hws[IMX8MM_CLK_EXT4] = imx_get_clk_hw_by_name(np, "clk_ext4");
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
base = of_iomap(np, 0);
diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c
index d37c45b676ab..af256ade554f 100644
--- a/drivers/clk/imx/clk-imx8mn.c
+++ b/drivers/clk/imx/clk-imx8mn.c
@@ -27,10 +27,10 @@ static u32 share_count_nand;
static const char * const pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
static const char * const audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
static const char * const audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", };
-static const char * const video_pll1_bypass_sels[] = {"video_pll1", "video_pll1_ref_sel", };
+static const char * const video_pll_bypass_sels[] = {"video_pll", "video_pll_ref_sel", };
static const char * const dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
static const char * const gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
-static const char * const vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
+static const char * const m7_alt_pll_bypass_sels[] = {"m7_alt_pll", "m7_alt_pll_ref_sel", };
static const char * const arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
static const char * const sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
@@ -40,24 +40,24 @@ static const char * const imx8mn_a53_sels[] = {"osc_24m", "arm_pll_out", "sys_pl
static const char * const imx8mn_a53_core_sels[] = {"arm_a53_div", "arm_pll_out", };
-static const char * const imx8mn_m7_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_250m", "vpu_pll_out",
- "sys_pll1_800m", "audio_pll1_out", "video_pll1_out", "sys_pll3_out", };
+static const char * const imx8mn_m7_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_250m", "m7_alt_pll_out",
+ "sys_pll1_800m", "audio_pll1_out", "video_pll_out", "sys_pll3_out", };
static const char * const imx8mn_gpu_core_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m",
"sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
- "video_pll1_out", "audio_pll2_out", };
+ "video_pll_out", "audio_pll2_out", };
static const char * const imx8mn_gpu_shader_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m",
"sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
- "video_pll1_out", "audio_pll2_out", };
+ "video_pll_out", "audio_pll2_out", };
static const char * const imx8mn_main_axi_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll1_800m",
"sys_pll2_250m", "sys_pll2_1000m", "audio_pll1_out",
- "video_pll1_out", "sys_pll1_100m",};
+ "video_pll_out", "sys_pll1_100m",};
static const char * const imx8mn_enet_axi_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m",
"sys_pll2_250m", "sys_pll2_200m", "audio_pll1_out",
- "video_pll1_out", "sys_pll3_out", };
+ "video_pll_out", "sys_pll3_out", };
static const char * const imx8mn_nand_usdhc_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m",
"sys_pll2_200m", "sys_pll1_133m", "sys_pll3_out",
@@ -77,23 +77,23 @@ static const char * const imx8mn_usb_bus_sels[] = {"osc_24m", "sys_pll2_500m", "
static const char * const imx8mn_gpu_axi_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out",
"sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
- "video_pll1_out", "audio_pll2_out", };
+ "video_pll_out", "audio_pll2_out", };
static const char * const imx8mn_gpu_ahb_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out",
"sys_pll3_out", "sys_pll2_1000m", "audio_pll1_out",
- "video_pll1_out", "audio_pll2_out", };
+ "video_pll_out", "audio_pll2_out", };
static const char * const imx8mn_noc_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll3_out",
"sys_pll2_1000m", "sys_pll2_500m", "audio_pll1_out",
- "video_pll1_out", "audio_pll2_out", };
+ "video_pll_out", "audio_pll2_out", };
static const char * const imx8mn_ahb_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_800m",
"sys_pll1_400m", "sys_pll2_125m", "sys_pll3_out",
- "audio_pll1_out", "video_pll1_out", };
+ "audio_pll1_out", "video_pll_out", };
static const char * const imx8mn_audio_ahb_sels[] = {"osc_24m", "sys_pll2_500m", "sys_pll1_800m",
"sys_pll2_1000m", "sys_pll2_166m", "sys_pll3_out",
- "audio_pll1_out", "video_pll1_out", };
+ "audio_pll1_out", "video_pll_out", };
static const char * const imx8mn_dram_alt_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll1_100m",
"sys_pll2_500m", "sys_pll2_1000m", "sys_pll3_out",
@@ -103,49 +103,49 @@ static const char * const imx8mn_dram_apb_sels[] = {"osc_24m", "sys_pll2_200m",
"sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
"sys_pll2_250m", "audio_pll2_out", };
-static const char * const imx8mn_disp_pixel_sels[] = {"osc_24m", "video_pll1_out", "audio_pll2_out",
+static const char * const imx8mn_disp_pixel_sels[] = {"osc_24m", "video_pll_out", "audio_pll2_out",
"audio_pll1_out", "sys_pll1_800m", "sys_pll2_1000m",
"sys_pll3_out", "clk_ext4", };
static const char * const imx8mn_sai2_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
- "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
- "clk_ext3", "clk_ext4", };
+ "video_pll_out", "sys_pll1_133m", "dummy",
+ "clk_ext2", "clk_ext3", };
static const char * const imx8mn_sai3_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
- "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "video_pll_out", "sys_pll1_133m", "dummy",
"clk_ext3", "clk_ext4", };
static const char * const imx8mn_sai5_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
- "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "video_pll_out", "sys_pll1_133m", "dummy",
"clk_ext2", "clk_ext3", };
static const char * const imx8mn_sai6_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
- "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "video_pll_out", "sys_pll1_133m", "dummy",
"clk_ext3", "clk_ext4", };
static const char * const imx8mn_sai7_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
- "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "video_pll_out", "sys_pll1_133m", "dummy",
"clk_ext3", "clk_ext4", };
static const char * const imx8mn_spdif1_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out",
- "video_pll1_out", "sys_pll1_133m", "osc_hdmi",
+ "video_pll_out", "sys_pll1_133m", "dummy",
"clk_ext2", "clk_ext3", };
static const char * const imx8mn_enet_ref_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_50m",
"sys_pll2_100m", "sys_pll1_160m", "audio_pll1_out",
- "video_pll1_out", "clk_ext4", };
+ "video_pll_out", "clk_ext4", };
static const char * const imx8mn_enet_timer_sels[] = {"osc_24m", "sys_pll2_100m", "audio_pll1_out",
"clk_ext1", "clk_ext2", "clk_ext3",
- "clk_ext4", "video_pll1_out", };
+ "clk_ext4", "video_pll_out", };
static const char * const imx8mn_enet_phy_sels[] = {"osc_24m", "sys_pll2_50m", "sys_pll2_125m",
- "sys_pll2_200m", "sys_pll2_500m", "video_pll1_out",
- "audio_pll2_out", };
+ "sys_pll2_200m", "sys_pll2_500m", "audio_pll1_out",
+ "video_pll_out", "audio_pll2_out", };
static const char * const imx8mn_nand_sels[] = {"osc_24m", "sys_pll2_500m", "audio_pll1_out",
"sys_pll1_400m", "audio_pll2_out", "sys_pll3_out",
- "sys_pll2_250m", "video_pll1_out", };
+ "sys_pll2_250m", "video_pll_out", };
static const char * const imx8mn_qspi_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll2_333m",
"sys_pll2_500m", "audio_pll2_out", "sys_pll1_266m",
@@ -160,19 +160,19 @@ static const char * const imx8mn_usdhc2_sels[] = {"osc_24m", "sys_pll1_400m", "s
"audio_pll2_out", "sys_pll1_100m", };
static const char * const imx8mn_i2c1_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
- "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "sys_pll3_out", "audio_pll1_out", "video_pll_out",
"audio_pll2_out", "sys_pll1_133m", };
static const char * const imx8mn_i2c2_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
- "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "sys_pll3_out", "audio_pll1_out", "video_pll_out",
"audio_pll2_out", "sys_pll1_133m", };
static const char * const imx8mn_i2c3_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
- "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "sys_pll3_out", "audio_pll1_out", "video_pll_out",
"audio_pll2_out", "sys_pll1_133m", };
static const char * const imx8mn_i2c4_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m",
- "sys_pll3_out", "audio_pll1_out", "video_pll1_out",
+ "sys_pll3_out", "audio_pll1_out", "video_pll_out",
"audio_pll2_out", "sys_pll1_133m", };
static const char * const imx8mn_uart1_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m",
@@ -213,63 +213,63 @@ static const char * const imx8mn_ecspi2_sels[] = {"osc_24m", "sys_pll2_200m", "s
static const char * const imx8mn_pwm1_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
"sys_pll1_40m", "sys_pll3_out", "clk_ext1",
- "sys_pll1_80m", "video_pll1_out", };
+ "sys_pll1_80m", "video_pll_out", };
static const char * const imx8mn_pwm2_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
"sys_pll1_40m", "sys_pll3_out", "clk_ext1",
- "sys_pll1_80m", "video_pll1_out", };
+ "sys_pll1_80m", "video_pll_out", };
static const char * const imx8mn_pwm3_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
"sys_pll1_40m", "sys_pll3_out", "clk_ext2",
- "sys_pll1_80m", "video_pll1_out", };
+ "sys_pll1_80m", "video_pll_out", };
static const char * const imx8mn_pwm4_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
"sys_pll1_40m", "sys_pll3_out", "clk_ext2",
- "sys_pll1_80m", "video_pll1_out", };
+ "sys_pll1_80m", "video_pll_out", };
static const char * const imx8mn_gpt1_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m",
- "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m",
+ "sys_pll1_40m", "video_pll_out", "sys_pll1_80m",
"audio_pll1_out", "clk_ext1", };
static const char * const imx8mn_gpt2_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m",
- "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m",
+ "sys_pll1_40m", "video_pll_out", "sys_pll1_80m",
"audio_pll1_out", "clk_ext1", };
static const char * const imx8mn_gpt3_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m",
- "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m",
+ "sys_pll1_40m", "video_pll_out", "sys_pll1_80m",
"audio_pll1_out", "clk_ext1", };
static const char * const imx8mn_gpt4_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m",
- "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m",
+ "sys_pll1_40m", "video_pll_out", "sys_pll1_80m",
"audio_pll1_out", "clk_ext1", };
static const char * const imx8mn_gpt5_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m",
- "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m",
+ "sys_pll1_40m", "video_pll_out", "sys_pll1_80m",
"audio_pll1_out", "clk_ext1", };
static const char * const imx8mn_gpt6_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m",
- "sys_pll1_40m", "video_pll1_out", "sys_pll1_80m",
+ "sys_pll1_40m", "video_pll_out", "sys_pll1_80m",
"audio_pll1_out", "clk_ext1", };
static const char * const imx8mn_wdog_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_160m",
- "vpu_pll_out", "sys_pll2_125m", "sys_pll3_out",
+ "m7_alt_pll_out", "sys_pll2_125m", "sys_pll3_out",
"sys_pll1_80m", "sys_pll2_166m", };
-static const char * const imx8mn_wrclk_sels[] = {"osc_24m", "sys_pll1_40m", "vpu_pll_out",
+static const char * const imx8mn_wrclk_sels[] = {"osc_24m", "sys_pll1_40m", "m7_alt_pll_out",
"sys_pll3_out", "sys_pll2_200m", "sys_pll1_266m",
"sys_pll2_500m", "sys_pll1_100m", };
static const char * const imx8mn_dsi_core_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m",
"sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
- "audio_pll2_out", "video_pll1_out", };
+ "audio_pll2_out", "video_pll_out", };
static const char * const imx8mn_dsi_phy_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_100m",
"sys_pll1_800m", "sys_pll2_1000m", "clk_ext2",
- "audio_pll2_out", "video_pll1_out", };
+ "audio_pll2_out", "video_pll_out", };
static const char * const imx8mn_dsi_dbi_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_100m",
"sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
- "audio_pll2_out", "video_pll1_out", };
+ "audio_pll2_out", "video_pll_out", };
static const char * const imx8mn_usdhc3_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m",
"sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
@@ -277,15 +277,15 @@ static const char * const imx8mn_usdhc3_sels[] = {"osc_24m", "sys_pll1_400m", "s
static const char * const imx8mn_camera_pixel_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m",
"sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
- "audio_pll2_out", "video_pll1_out", };
+ "audio_pll2_out", "video_pll_out", };
static const char * const imx8mn_csi1_phy_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m",
"sys_pll1_800m", "sys_pll2_1000m", "clk_ext2",
- "audio_pll2_out", "video_pll1_out", };
+ "audio_pll2_out", "video_pll_out", };
static const char * const imx8mn_csi2_phy_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m",
"sys_pll1_800m", "sys_pll2_1000m", "clk_ext2",
- "audio_pll2_out", "video_pll1_out", };
+ "audio_pll2_out", "video_pll_out", };
static const char * const imx8mn_csi2_esc_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_80m",
"sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
@@ -306,9 +306,9 @@ static const char * const imx8mn_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "du
"dummy", "sys_pll1_80m", };
static const char * const imx8mn_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_400m",
"sys_pll2_166m", "sys_pll3_out", "audio_pll1_out",
- "video_pll1_out", "osc_32k", };
+ "video_pll_out", "osc_32k", };
-static const char * const clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+static const char * const clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll_out",
"dummy", "dummy", "gpu_pll_out", "dummy",
"arm_pll_out", "sys_pll1", "sys_pll2", "sys_pll3",
"dummy", "dummy", "osc_24m", "dummy", "osc_32k"};
@@ -332,12 +332,12 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
hws = clk_hw_data->hws;
hws[IMX8MN_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
- hws[IMX8MN_CLK_24M] = imx_obtain_fixed_clk_hw(np, "osc_24m");
- hws[IMX8MN_CLK_32K] = imx_obtain_fixed_clk_hw(np, "osc_32k");
- hws[IMX8MN_CLK_EXT1] = imx_obtain_fixed_clk_hw(np, "clk_ext1");
- hws[IMX8MN_CLK_EXT2] = imx_obtain_fixed_clk_hw(np, "clk_ext2");
- hws[IMX8MN_CLK_EXT3] = imx_obtain_fixed_clk_hw(np, "clk_ext3");
- hws[IMX8MN_CLK_EXT4] = imx_obtain_fixed_clk_hw(np, "clk_ext4");
+ hws[IMX8MN_CLK_24M] = imx_get_clk_hw_by_name(np, "osc_24m");
+ hws[IMX8MN_CLK_32K] = imx_get_clk_hw_by_name(np, "osc_32k");
+ hws[IMX8MN_CLK_EXT1] = imx_get_clk_hw_by_name(np, "clk_ext1");
+ hws[IMX8MN_CLK_EXT2] = imx_get_clk_hw_by_name(np, "clk_ext2");
+ hws[IMX8MN_CLK_EXT3] = imx_get_clk_hw_by_name(np, "clk_ext3");
+ 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);
@@ -349,19 +349,19 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
hws[IMX8MN_AUDIO_PLL1_REF_SEL] = imx_clk_hw_mux("audio_pll1_ref_sel", base + 0x0, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
hws[IMX8MN_AUDIO_PLL2_REF_SEL] = imx_clk_hw_mux("audio_pll2_ref_sel", base + 0x14, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
- hws[IMX8MN_VIDEO_PLL1_REF_SEL] = imx_clk_hw_mux("video_pll1_ref_sel", base + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ hws[IMX8MN_VIDEO_PLL_REF_SEL] = imx_clk_hw_mux("video_pll_ref_sel", base + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
hws[IMX8MN_DRAM_PLL_REF_SEL] = imx_clk_hw_mux("dram_pll_ref_sel", base + 0x50, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
hws[IMX8MN_GPU_PLL_REF_SEL] = imx_clk_hw_mux("gpu_pll_ref_sel", base + 0x64, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
- hws[IMX8MN_VPU_PLL_REF_SEL] = imx_clk_hw_mux("vpu_pll_ref_sel", base + 0x74, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+ hws[IMX8MN_M7_ALT_PLL_REF_SEL] = imx_clk_hw_mux("m7_alt_pll_ref_sel", base + 0x74, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
hws[IMX8MN_ARM_PLL_REF_SEL] = imx_clk_hw_mux("arm_pll_ref_sel", base + 0x84, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
hws[IMX8MN_SYS_PLL3_REF_SEL] = imx_clk_hw_mux("sys_pll3_ref_sel", base + 0x114, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
hws[IMX8MN_AUDIO_PLL1] = imx_clk_hw_pll14xx("audio_pll1", "audio_pll1_ref_sel", base, &imx_1443x_pll);
hws[IMX8MN_AUDIO_PLL2] = imx_clk_hw_pll14xx("audio_pll2", "audio_pll2_ref_sel", base + 0x14, &imx_1443x_pll);
- hws[IMX8MN_VIDEO_PLL1] = imx_clk_hw_pll14xx("video_pll1", "video_pll1_ref_sel", base + 0x28, &imx_1443x_pll);
+ hws[IMX8MN_VIDEO_PLL] = imx_clk_hw_pll14xx("video_pll", "video_pll_ref_sel", base + 0x28, &imx_1443x_pll);
hws[IMX8MN_DRAM_PLL] = imx_clk_hw_pll14xx("dram_pll", "dram_pll_ref_sel", base + 0x50, &imx_1443x_dram_pll);
hws[IMX8MN_GPU_PLL] = imx_clk_hw_pll14xx("gpu_pll", "gpu_pll_ref_sel", base + 0x64, &imx_1416x_pll);
- hws[IMX8MN_VPU_PLL] = imx_clk_hw_pll14xx("vpu_pll", "vpu_pll_ref_sel", base + 0x74, &imx_1416x_pll);
+ hws[IMX8MN_M7_ALT_PLL] = imx_clk_hw_pll14xx("m7_alt_pll", "m7_alt_pll_ref_sel", base + 0x74, &imx_1416x_pll);
hws[IMX8MN_ARM_PLL] = imx_clk_hw_pll14xx("arm_pll", "arm_pll_ref_sel", base + 0x84, &imx_1416x_pll);
hws[IMX8MN_SYS_PLL1] = imx_clk_hw_fixed("sys_pll1", 800000000);
hws[IMX8MN_SYS_PLL2] = imx_clk_hw_fixed("sys_pll2", 1000000000);
@@ -370,20 +370,20 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
/* PLL bypass out */
hws[IMX8MN_AUDIO_PLL1_BYPASS] = imx_clk_hw_mux_flags("audio_pll1_bypass", base, 16, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT);
hws[IMX8MN_AUDIO_PLL2_BYPASS] = imx_clk_hw_mux_flags("audio_pll2_bypass", base + 0x14, 16, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels), CLK_SET_RATE_PARENT);
- hws[IMX8MN_VIDEO_PLL1_BYPASS] = imx_clk_hw_mux_flags("video_pll1_bypass", base + 0x28, 16, 1, video_pll1_bypass_sels, ARRAY_SIZE(video_pll1_bypass_sels), CLK_SET_RATE_PARENT);
+ hws[IMX8MN_VIDEO_PLL_BYPASS] = imx_clk_hw_mux_flags("video_pll_bypass", base + 0x28, 16, 1, video_pll_bypass_sels, ARRAY_SIZE(video_pll_bypass_sels), CLK_SET_RATE_PARENT);
hws[IMX8MN_DRAM_PLL_BYPASS] = imx_clk_hw_mux_flags("dram_pll_bypass", base + 0x50, 16, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT);
hws[IMX8MN_GPU_PLL_BYPASS] = imx_clk_hw_mux_flags("gpu_pll_bypass", base + 0x64, 28, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
- hws[IMX8MN_VPU_PLL_BYPASS] = imx_clk_hw_mux_flags("vpu_pll_bypass", base + 0x74, 28, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
+ hws[IMX8MN_M7_ALT_PLL_BYPASS] = imx_clk_hw_mux_flags("m7_alt_pll_bypass", base + 0x74, 28, 1, m7_alt_pll_bypass_sels, ARRAY_SIZE(m7_alt_pll_bypass_sels), CLK_SET_RATE_PARENT);
hws[IMX8MN_ARM_PLL_BYPASS] = imx_clk_hw_mux_flags("arm_pll_bypass", base + 0x84, 28, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT);
hws[IMX8MN_SYS_PLL3_BYPASS] = imx_clk_hw_mux_flags("sys_pll3_bypass", base + 0x114, 28, 1, sys_pll3_bypass_sels, ARRAY_SIZE(sys_pll3_bypass_sels), CLK_SET_RATE_PARENT);
/* PLL out gate */
hws[IMX8MN_AUDIO_PLL1_OUT] = imx_clk_hw_gate("audio_pll1_out", "audio_pll1_bypass", base, 13);
hws[IMX8MN_AUDIO_PLL2_OUT] = imx_clk_hw_gate("audio_pll2_out", "audio_pll2_bypass", base + 0x14, 13);
- hws[IMX8MN_VIDEO_PLL1_OUT] = imx_clk_hw_gate("video_pll1_out", "video_pll1_bypass", base + 0x28, 13);
+ hws[IMX8MN_VIDEO_PLL_OUT] = imx_clk_hw_gate("video_pll_out", "video_pll_bypass", base + 0x28, 13);
hws[IMX8MN_DRAM_PLL_OUT] = imx_clk_hw_gate("dram_pll_out", "dram_pll_bypass", base + 0x50, 13);
hws[IMX8MN_GPU_PLL_OUT] = imx_clk_hw_gate("gpu_pll_out", "gpu_pll_bypass", base + 0x64, 11);
- hws[IMX8MN_VPU_PLL_OUT] = imx_clk_hw_gate("vpu_pll_out", "vpu_pll_bypass", base + 0x74, 11);
+ hws[IMX8MN_M7_ALT_PLL_OUT] = imx_clk_hw_gate("m7_alt_pll_out", "m7_alt_pll_bypass", base + 0x74, 11);
hws[IMX8MN_ARM_PLL_OUT] = imx_clk_hw_gate("arm_pll_out", "arm_pll_bypass", base + 0x84, 11);
hws[IMX8MN_SYS_PLL3_OUT] = imx_clk_hw_gate("sys_pll3_out", "sys_pll3_bypass", base + 0x114, 11);
diff --git a/drivers/clk/imx/clk-imx8mp.c b/drivers/clk/imx/clk-imx8mp.c
index 652ae58c2735..a57d877d393d 100644
--- a/drivers/clk/imx/clk-imx8mp.c
+++ b/drivers/clk/imx/clk-imx8mp.c
@@ -17,6 +17,8 @@
static u32 share_count_nand;
static u32 share_count_media;
+static u32 share_count_usb;
+static u32 share_count_audio;
static const char * const pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
static const char * const audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
@@ -436,12 +438,12 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
hws = clk_hw_data->hws;
hws[IMX8MP_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
- hws[IMX8MP_CLK_24M] = imx_obtain_fixed_clk_hw(np, "osc_24m");
- hws[IMX8MP_CLK_32K] = imx_obtain_fixed_clk_hw(np, "osc_32k");
- hws[IMX8MP_CLK_EXT1] = imx_obtain_fixed_clk_hw(np, "clk_ext1");
- hws[IMX8MP_CLK_EXT2] = imx_obtain_fixed_clk_hw(np, "clk_ext2");
- hws[IMX8MP_CLK_EXT3] = imx_obtain_fixed_clk_hw(np, "clk_ext3");
- hws[IMX8MP_CLK_EXT4] = imx_obtain_fixed_clk_hw(np, "clk_ext4");
+ hws[IMX8MP_CLK_24M] = imx_get_clk_hw_by_name(np, "osc_24m");
+ hws[IMX8MP_CLK_32K] = imx_get_clk_hw_by_name(np, "osc_32k");
+ hws[IMX8MP_CLK_EXT1] = imx_get_clk_hw_by_name(np, "clk_ext1");
+ hws[IMX8MP_CLK_EXT2] = imx_get_clk_hw_by_name(np, "clk_ext2");
+ hws[IMX8MP_CLK_EXT3] = imx_get_clk_hw_by_name(np, "clk_ext3");
+ hws[IMX8MP_CLK_EXT4] = imx_get_clk_hw_by_name(np, "clk_ext4");
hws[IMX8MP_AUDIO_PLL1_REF_SEL] = imx_clk_hw_mux("audio_pll1_ref_sel", anatop_base + 0x0, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
hws[IMX8MP_AUDIO_PLL2_REF_SEL] = imx_clk_hw_mux("audio_pll2_ref_sel", anatop_base + 0x14, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
@@ -673,7 +675,8 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
hws[IMX8MP_CLK_UART2_ROOT] = imx_clk_hw_gate4("uart2_root_clk", "uart2", ccm_base + 0x44a0, 0);
hws[IMX8MP_CLK_UART3_ROOT] = imx_clk_hw_gate4("uart3_root_clk", "uart3", ccm_base + 0x44b0, 0);
hws[IMX8MP_CLK_UART4_ROOT] = imx_clk_hw_gate4("uart4_root_clk", "uart4", ccm_base + 0x44c0, 0);
- hws[IMX8MP_CLK_USB_ROOT] = imx_clk_hw_gate4("usb_root_clk", "hsio_axi", ccm_base + 0x44d0, 0);
+ hws[IMX8MP_CLK_USB_ROOT] = imx_clk_hw_gate2_shared2("usb_root_clk", "hsio_axi", ccm_base + 0x44d0, 0, &share_count_usb);
+ hws[IMX8MP_CLK_USB_SUSP] = imx_clk_hw_gate2_shared2("usb_suspend_clk", "osc_32k", ccm_base + 0x44d0, 0, &share_count_usb);
hws[IMX8MP_CLK_USB_PHY_ROOT] = imx_clk_hw_gate4("usb_phy_root_clk", "usb_phy_ref", ccm_base + 0x44f0, 0);
hws[IMX8MP_CLK_USDHC1_ROOT] = imx_clk_hw_gate4("usdhc1_root_clk", "usdhc1", ccm_base + 0x4510, 0);
hws[IMX8MP_CLK_USDHC2_ROOT] = imx_clk_hw_gate4("usdhc2_root_clk", "usdhc2", ccm_base + 0x4520, 0);
@@ -699,7 +702,16 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
hws[IMX8MP_CLK_HDMI_ROOT] = imx_clk_hw_gate4("hdmi_root_clk", "hdmi_axi", ccm_base + 0x45f0, 0);
hws[IMX8MP_CLK_TSENSOR_ROOT] = imx_clk_hw_gate4("tsensor_root_clk", "ipg_root", ccm_base + 0x4620, 0);
hws[IMX8MP_CLK_VPU_ROOT] = imx_clk_hw_gate4("vpu_root_clk", "vpu_bus", ccm_base + 0x4630, 0);
- hws[IMX8MP_CLK_AUDIO_ROOT] = imx_clk_hw_gate4("audio_root_clk", "audio_ahb", ccm_base + 0x4650, 0);
+
+ hws[IMX8MP_CLK_AUDIO_AHB_ROOT] = imx_clk_hw_gate2_shared2("audio_ahb_root", "audio_ahb", ccm_base + 0x4650, 0, &share_count_audio);
+ hws[IMX8MP_CLK_AUDIO_AXI_ROOT] = imx_clk_hw_gate2_shared2("audio_axi_root", "audio_axi", ccm_base + 0x4650, 0, &share_count_audio);
+ hws[IMX8MP_CLK_SAI1_ROOT] = imx_clk_hw_gate2_shared2("sai1_root", "sai1", ccm_base + 0x4650, 0, &share_count_audio);
+ hws[IMX8MP_CLK_SAI2_ROOT] = imx_clk_hw_gate2_shared2("sai2_root", "sai2", ccm_base + 0x4650, 0, &share_count_audio);
+ hws[IMX8MP_CLK_SAI3_ROOT] = imx_clk_hw_gate2_shared2("sai3_root", "sai3", ccm_base + 0x4650, 0, &share_count_audio);
+ hws[IMX8MP_CLK_SAI5_ROOT] = imx_clk_hw_gate2_shared2("sai5_root", "sai5", ccm_base + 0x4650, 0, &share_count_audio);
+ hws[IMX8MP_CLK_SAI6_ROOT] = imx_clk_hw_gate2_shared2("sai6_root", "sai6", ccm_base + 0x4650, 0, &share_count_audio);
+ hws[IMX8MP_CLK_SAI7_ROOT] = imx_clk_hw_gate2_shared2("sai7_root", "sai7", ccm_base + 0x4650, 0, &share_count_audio);
+ hws[IMX8MP_CLK_PDM_ROOT] = imx_clk_hw_gate2_shared2("pdm_root", "pdm", ccm_base + 0x4650, 0, &share_count_audio);
hws[IMX8MP_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_core",
hws[IMX8MP_CLK_A53_CORE]->clk,
diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c
index 882dcad4817d..2bcaec19a999 100644
--- a/drivers/clk/imx/clk-imx8mq.c
+++ b/drivers/clk/imx/clk-imx8mq.c
@@ -297,13 +297,13 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
hws = clk_hw_data->hws;
hws[IMX8MQ_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
- hws[IMX8MQ_CLK_32K] = imx_obtain_fixed_clk_hw(np, "ckil");
- hws[IMX8MQ_CLK_25M] = imx_obtain_fixed_clk_hw(np, "osc_25m");
- hws[IMX8MQ_CLK_27M] = imx_obtain_fixed_clk_hw(np, "osc_27m");
- hws[IMX8MQ_CLK_EXT1] = imx_obtain_fixed_clk_hw(np, "clk_ext1");
- hws[IMX8MQ_CLK_EXT2] = imx_obtain_fixed_clk_hw(np, "clk_ext2");
- hws[IMX8MQ_CLK_EXT3] = imx_obtain_fixed_clk_hw(np, "clk_ext3");
- hws[IMX8MQ_CLK_EXT4] = imx_obtain_fixed_clk_hw(np, "clk_ext4");
+ hws[IMX8MQ_CLK_32K] = imx_get_clk_hw_by_name(np, "ckil");
+ hws[IMX8MQ_CLK_25M] = imx_get_clk_hw_by_name(np, "osc_25m");
+ hws[IMX8MQ_CLK_27M] = imx_get_clk_hw_by_name(np, "osc_27m");
+ hws[IMX8MQ_CLK_EXT1] = imx_get_clk_hw_by_name(np, "clk_ext1");
+ hws[IMX8MQ_CLK_EXT2] = imx_get_clk_hw_by_name(np, "clk_ext2");
+ hws[IMX8MQ_CLK_EXT3] = imx_get_clk_hw_by_name(np, "clk_ext3");
+ hws[IMX8MQ_CLK_EXT4] = imx_get_clk_hw_by_name(np, "clk_ext4");
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-anatop");
base = of_iomap(np, 0);
diff --git a/drivers/clk/imx/clk-imx93.c b/drivers/clk/imx/clk-imx93.c
index 99cff1fd108b..e464d9e71fbc 100644
--- a/drivers/clk/imx/clk-imx93.c
+++ b/drivers/clk/imx/clk-imx93.c
@@ -64,13 +64,9 @@ static const struct imx93_clk_root {
{ IMX93_CLK_M33_SYSTICK, "m33_systick_root", 0x0480, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_FLEXIO1, "flexio1_root", 0x0500, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_FLEXIO2, "flexio2_root", 0x0580, LOW_SPEED_IO_SEL, },
- { IMX93_CLK_LPIT1, "lpit1_root", 0x0600, LOW_SPEED_IO_SEL, },
- { IMX93_CLK_LPIT2, "lpit2_root", 0x0680, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_LPTMR1, "lptmr1_root", 0x0700, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_LPTMR2, "lptmr2_root", 0x0780, LOW_SPEED_IO_SEL, },
- { IMX93_CLK_TPM1, "tpm1_root", 0x0800, TPM_SEL, },
{ IMX93_CLK_TPM2, "tpm2_root", 0x0880, TPM_SEL, },
- { IMX93_CLK_TPM3, "tpm3_root", 0x0900, TPM_SEL, },
{ IMX93_CLK_TPM4, "tpm4_root", 0x0980, TPM_SEL, },
{ IMX93_CLK_TPM5, "tpm5_root", 0x0a00, TPM_SEL, },
{ IMX93_CLK_TPM6, "tpm6_root", 0x0a80, TPM_SEL, },
@@ -113,7 +109,11 @@ static const struct imx93_clk_root {
{ IMX93_CLK_CCM_CKO2, "ccm_cko2_root", 0x1d00, CKO2_SEL, },
{ IMX93_CLK_CCM_CKO3, "ccm_cko3_root", 0x1d80, CKO1_SEL, },
{ IMX93_CLK_CCM_CKO4, "ccm_cko4_root", 0x1e00, CKO2_SEL, },
- { IMX93_CLK_HSIO, "hsio_root", 0x1e80, LOW_SPEED_IO_SEL, },
+ /*
+ * Critical because clk is used for handshake between HSIOMIX and NICMIX when
+ * NICMIX power down/on during system suspend/resume
+ */
+ { IMX93_CLK_HSIO, "hsio_root", 0x1e80, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL},
{ IMX93_CLK_HSIO_USB_TEST_60M, "hsio_usb_test_60m_root", 0x1f00, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_HSIO_ACSCAN_80M, "hsio_acscan_80m_root", 0x1f80, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_HSIO_ACSCAN_480M, "hsio_acscan_480m_root", 0x2000, MISC_SEL, },
@@ -170,20 +170,20 @@ static const struct imx93_clk_ccgr {
{ IMX93_CLK_MU2_B_GATE, "mu2_b", "bus_wakeup_root", 0x8500, 0, &share_count_mub },
{ IMX93_CLK_EDMA1_GATE, "edma1", "m33_root", 0x8540, },
{ IMX93_CLK_EDMA2_GATE, "edma2", "wakeup_axi_root", 0x8580, },
- { IMX93_CLK_FLEXSPI1_GATE, "flexspi", "flexspi_root", 0x8640, },
+ { IMX93_CLK_FLEXSPI1_GATE, "flexspi1", "flexspi1_root", 0x8640, },
{ IMX93_CLK_GPIO1_GATE, "gpio1", "m33_root", 0x8880, },
{ IMX93_CLK_GPIO2_GATE, "gpio2", "bus_wakeup_root", 0x88c0, },
{ IMX93_CLK_GPIO3_GATE, "gpio3", "bus_wakeup_root", 0x8900, },
{ IMX93_CLK_GPIO4_GATE, "gpio4", "bus_wakeup_root", 0x8940, },
{ IMX93_CLK_FLEXIO1_GATE, "flexio1", "flexio1_root", 0x8980, },
{ IMX93_CLK_FLEXIO2_GATE, "flexio2", "flexio2_root", 0x89c0, },
- { IMX93_CLK_LPIT1_GATE, "lpit1", "lpit1_root", 0x8a00, },
- { IMX93_CLK_LPIT2_GATE, "lpit2", "lpit2_root", 0x8a40, },
+ { IMX93_CLK_LPIT1_GATE, "lpit1", "bus_aon_root", 0x8a00, },
+ { IMX93_CLK_LPIT2_GATE, "lpit2", "bus_wakeup_root", 0x8a40, },
{ IMX93_CLK_LPTMR1_GATE, "lptmr1", "lptmr1_root", 0x8a80, },
{ IMX93_CLK_LPTMR2_GATE, "lptmr2", "lptmr2_root", 0x8ac0, },
- { IMX93_CLK_TPM1_GATE, "tpm1", "tpm1_root", 0x8b00, },
+ { IMX93_CLK_TPM1_GATE, "tpm1", "bus_aon_root", 0x8b00, },
{ IMX93_CLK_TPM2_GATE, "tpm2", "tpm2_root", 0x8b40, },
- { IMX93_CLK_TPM3_GATE, "tpm3", "tpm3_root", 0x8b80, },
+ { IMX93_CLK_TPM3_GATE, "tpm3", "bus_wakeup_root", 0x8b80, },
{ IMX93_CLK_TPM4_GATE, "tpm4", "tpm4_root", 0x8bc0, },
{ IMX93_CLK_TPM5_GATE, "tpm5", "tpm5_root", 0x8c00, },
{ IMX93_CLK_TPM6_GATE, "tpm6", "tpm6_root", 0x8c40, },
@@ -240,9 +240,10 @@ static const struct imx93_clk_ccgr {
{ IMX93_CLK_AUD_XCVR_GATE, "aud_xcvr", "audio_xcvr_root", 0x9b80, },
{ IMX93_CLK_SPDIF_GATE, "spdif", "spdif_root", 0x9c00, },
{ IMX93_CLK_HSIO_32K_GATE, "hsio_32k", "osc_32k", 0x9dc0, },
- { IMX93_CLK_ENET1_GATE, "enet1", "enet_root", 0x9e00, },
+ { IMX93_CLK_ENET1_GATE, "enet1", "wakeup_axi_root", 0x9e00, },
{ IMX93_CLK_ENET_QOS_GATE, "enet_qos", "wakeup_axi_root", 0x9e40, },
- { IMX93_CLK_SYS_CNT_GATE, "sys_cnt", "osc_24m", 0x9e80, },
+ /* Critical because clk accessed during CPU idle */
+ { IMX93_CLK_SYS_CNT_GATE, "sys_cnt", "osc_24m", 0x9e80, CLK_IS_CRITICAL},
{ IMX93_CLK_TSTMR1_GATE, "tstmr1", "bus_aon_root", 0x9ec0, },
{ IMX93_CLK_TSTMR2_GATE, "tstmr2", "bus_wakeup_root", 0x9f00, },
{ IMX93_CLK_TMC_GATE, "tmc", "osc_24m", 0x9f40, },
@@ -258,7 +259,7 @@ static int imx93_clocks_probe(struct platform_device *pdev)
struct device_node *np = dev->of_node;
const struct imx93_clk_root *root;
const struct imx93_clk_ccgr *ccgr;
- void __iomem *base = NULL;
+ void __iomem *base, *anatop_base;
int i, ret;
clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
@@ -270,9 +271,9 @@ static int imx93_clocks_probe(struct platform_device *pdev)
clks = clk_hw_data->hws;
clks[IMX93_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
- clks[IMX93_CLK_24M] = imx_obtain_fixed_clk_hw(np, "osc_24m");
- clks[IMX93_CLK_32K] = imx_obtain_fixed_clk_hw(np, "osc_32k");
- clks[IMX93_CLK_EXT1] = imx_obtain_fixed_clk_hw(np, "clk_ext1");
+ clks[IMX93_CLK_24M] = imx_get_clk_hw_by_name(np, "osc_24m");
+ clks[IMX93_CLK_32K] = imx_get_clk_hw_by_name(np, "osc_32k");
+ clks[IMX93_CLK_EXT1] = imx_get_clk_hw_by_name(np, "clk_ext1");
clks[IMX93_CLK_SYS_PLL_PFD0] = imx_clk_hw_fixed("sys_pll_pfd0", 1000000000);
clks[IMX93_CLK_SYS_PLL_PFD0_DIV2] = imx_clk_hw_fixed_factor("sys_pll_pfd0_div2",
@@ -285,20 +286,22 @@ static int imx93_clocks_probe(struct platform_device *pdev)
"sys_pll_pfd2", 1, 2);
np = of_find_compatible_node(NULL, NULL, "fsl,imx93-anatop");
- base = of_iomap(np, 0);
+ anatop_base = of_iomap(np, 0);
of_node_put(np);
- if (WARN_ON(!base))
+ if (WARN_ON(!anatop_base))
return -ENOMEM;
- clks[IMX93_CLK_AUDIO_PLL] = imx_clk_fracn_gppll("audio_pll", "osc_24m", base + 0x1200,
+ clks[IMX93_CLK_AUDIO_PLL] = imx_clk_fracn_gppll("audio_pll", "osc_24m", anatop_base + 0x1200,
&imx_fracn_gppll);
- clks[IMX93_CLK_VIDEO_PLL] = imx_clk_fracn_gppll("video_pll", "osc_24m", base + 0x1400,
+ clks[IMX93_CLK_VIDEO_PLL] = imx_clk_fracn_gppll("video_pll", "osc_24m", anatop_base + 0x1400,
&imx_fracn_gppll);
np = dev->of_node;
base = devm_platform_ioremap_resource(pdev, 0);
- if (WARN_ON(IS_ERR(base)))
+ if (WARN_ON(IS_ERR(base))) {
+ iounmap(anatop_base);
return PTR_ERR(base);
+ }
for (i = 0; i < ARRAY_SIZE(root_array); i++) {
root = &root_array[i];
@@ -327,6 +330,7 @@ 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 9539d35588ee..e972abd299a8 100644
--- a/drivers/clk/imx/clk-imxrt1050.c
+++ b/drivers/clk/imx/clk-imxrt1050.c
@@ -50,7 +50,7 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev)
clk_hw_data->num = IMXRT1050_CLK_END;
hws = clk_hw_data->hws;
- hws[IMXRT1050_CLK_OSC] = imx_obtain_fixed_clk_hw(np, "osc");
+ 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);
@@ -140,7 +140,8 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev)
hws[IMXRT1050_CLK_USDHC1] = imx_clk_hw_gate2("usdhc1", "usdhc1_podf", ccm_base + 0x80, 2);
hws[IMXRT1050_CLK_USDHC2] = imx_clk_hw_gate2("usdhc2", "usdhc2_podf", ccm_base + 0x80, 4);
hws[IMXRT1050_CLK_LPUART1] = imx_clk_hw_gate2("lpuart1", "lpuart_podf", ccm_base + 0x7c, 24);
- hws[IMXRT1050_CLK_LCDIF_APB] = imx_clk_hw_gate2("lcdif", "lcdif_podf", ccm_base + 0x74, 10);
+ hws[IMXRT1050_CLK_LCDIF_APB] = imx_clk_hw_gate2("lcdif", "lcdif_podf", ccm_base + 0x70, 28);
+ hws[IMXRT1050_CLK_LCDIF_PIX] = imx_clk_hw_gate2("lcdif_pix", "lcdif", ccm_base + 0x74, 10);
hws[IMXRT1050_CLK_DMA] = imx_clk_hw_gate("dma", "ipg", ccm_base + 0x7C, 6);
hws[IMXRT1050_CLK_DMA_MUX] = imx_clk_hw_gate("dmamux0", "ipg", ccm_base + 0x7C, 7);
imx_check_clk_hws(hws, IMXRT1050_CLK_END);
diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c
index 1d0f79e9c346..828336873a98 100644
--- a/drivers/clk/imx/clk-pll14xx.c
+++ b/drivers/clk/imx/clk-pll14xx.c
@@ -54,7 +54,9 @@ static const struct imx_pll14xx_rate_table imx_pll1416x_tbl[] = {
PLL_1416X_RATE(800000000U, 200, 3, 1),
PLL_1416X_RATE(750000000U, 250, 2, 2),
PLL_1416X_RATE(700000000U, 350, 3, 2),
+ PLL_1416X_RATE(640000000U, 320, 3, 2),
PLL_1416X_RATE(600000000U, 300, 3, 2),
+ PLL_1416X_RATE(320000000U, 160, 3, 2),
};
static const struct imx_pll14xx_rate_table imx_pll1443x_tbl[] = {
diff --git a/drivers/clk/imx/clk.c b/drivers/clk/imx/clk.c
index 5582f18dd632..b636cc099d96 100644
--- a/drivers/clk/imx/clk.c
+++ b/drivers/clk/imx/clk.c
@@ -110,8 +110,7 @@ struct clk_hw *imx_obtain_fixed_clock_hw(
return __clk_get_hw(clk);
}
-struct clk_hw * imx_obtain_fixed_clk_hw(struct device_node *np,
- const char *name)
+struct clk_hw *imx_get_clk_hw_by_name(struct device_node *np, const char *name)
{
struct clk *clk;
@@ -121,7 +120,7 @@ struct clk_hw * imx_obtain_fixed_clk_hw(struct device_node *np,
return __clk_get_hw(clk);
}
-EXPORT_SYMBOL_GPL(imx_obtain_fixed_clk_hw);
+EXPORT_SYMBOL_GPL(imx_get_clk_hw_by_name);
/*
* This fixups the register CCM_CSCMR1 write value.
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index dd49f90110e8..689b3ad927c0 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -288,8 +288,7 @@ struct clk * imx_obtain_fixed_clock(
struct clk_hw *imx_obtain_fixed_clock_hw(
const char *name, unsigned long rate);
-struct clk_hw *imx_obtain_fixed_clk_hw(struct device_node *np,
- const char *name);
+struct clk_hw *imx_get_clk_hw_by_name(struct device_node *np, const char *name);
struct clk_hw *imx_clk_hw_gate_exclusive(const char *name, const char *parent,
void __iomem *reg, u8 shift, u32 exclusive_mask);
diff --git a/drivers/clk/ingenic/Kconfig b/drivers/clk/ingenic/Kconfig
index 898f1bc478c9..f80ac4f2992b 100644
--- a/drivers/clk/ingenic/Kconfig
+++ b/drivers/clk/ingenic/Kconfig
@@ -15,6 +15,16 @@ config INGENIC_CGU_JZ4740
If building for a JZ4740 SoC, you want to say Y here.
+config INGENIC_CGU_JZ4755
+ bool "Ingenic JZ4755 CGU driver"
+ default MACH_JZ4755
+ select INGENIC_CGU_COMMON
+ help
+ Support the clocks provided by the CGU hardware on Ingenic JZ4755
+ and compatible SoCs.
+
+ If building for a JZ4755 SoC, you want to say Y here.
+
config INGENIC_CGU_JZ4725B
bool "Ingenic JZ4725B CGU driver"
default MACH_JZ4725B
diff --git a/drivers/clk/ingenic/Makefile b/drivers/clk/ingenic/Makefile
index 9edfaf4610b9..81d8e23c2636 100644
--- a/drivers/clk/ingenic/Makefile
+++ b/drivers/clk/ingenic/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_INGENIC_CGU_COMMON) += cgu.o pm.o
obj-$(CONFIG_INGENIC_CGU_JZ4740) += jz4740-cgu.o
+obj-$(CONFIG_INGENIC_CGU_JZ4755) += jz4755-cgu.o
obj-$(CONFIG_INGENIC_CGU_JZ4725B) += jz4725b-cgu.o
obj-$(CONFIG_INGENIC_CGU_JZ4760) += jz4760-cgu.o
obj-$(CONFIG_INGENIC_CGU_JZ4770) += jz4770-cgu.o
diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c
index 861c50d6cb24..1f7ba30f5a1b 100644
--- a/drivers/clk/ingenic/cgu.c
+++ b/drivers/clk/ingenic/cgu.c
@@ -83,7 +83,7 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk);
struct ingenic_cgu *cgu = ingenic_clk->cgu;
const struct ingenic_cgu_pll_info *pll_info;
- unsigned m, n, od_enc, od;
+ unsigned m, n, od, od_enc = 0;
bool bypass;
u32 ctl;
@@ -96,8 +96,11 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
m += pll_info->m_offset;
n = (ctl >> pll_info->n_shift) & GENMASK(pll_info->n_bits - 1, 0);
n += pll_info->n_offset;
- od_enc = ctl >> pll_info->od_shift;
- od_enc &= GENMASK(pll_info->od_bits - 1, 0);
+
+ if (pll_info->od_bits > 0) {
+ od_enc = ctl >> pll_info->od_shift;
+ od_enc &= GENMASK(pll_info->od_bits - 1, 0);
+ }
if (pll_info->bypass_bit >= 0) {
ctl = readl(cgu->base + pll_info->bypass_reg);
@@ -108,11 +111,15 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
return parent_rate;
}
- for (od = 0; od < pll_info->od_max; od++) {
+ for (od = 0; od < pll_info->od_max; od++)
if (pll_info->od_encoding[od] == od_enc)
break;
- }
- BUG_ON(od == pll_info->od_max);
+
+ /* if od_max = 0, od_bits should be 0 and od is fixed to 1. */
+ if (pll_info->od_max == 0)
+ BUG_ON(pll_info->od_bits != 0);
+ else
+ BUG_ON(od == pll_info->od_max);
od++;
return div_u64((u64)parent_rate * m * pll_info->rate_multiplier,
@@ -182,6 +189,9 @@ static inline int ingenic_pll_check_stable(struct ingenic_cgu *cgu,
{
u32 ctl;
+ if (pll_info->stable_bit < 0)
+ return 0;
+
return readl_poll_timeout(cgu->base + pll_info->reg, ctl,
ctl & BIT(pll_info->stable_bit),
0, 100 * USEC_PER_MSEC);
@@ -215,13 +225,18 @@ ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate,
ctl &= ~(GENMASK(pll_info->n_bits - 1, 0) << pll_info->n_shift);
ctl |= (n - pll_info->n_offset) << pll_info->n_shift;
- ctl &= ~(GENMASK(pll_info->od_bits - 1, 0) << pll_info->od_shift);
- ctl |= pll_info->od_encoding[od - 1] << pll_info->od_shift;
+ if (pll_info->od_bits > 0) {
+ ctl &= ~(GENMASK(pll_info->od_bits - 1, 0) << pll_info->od_shift);
+ ctl |= pll_info->od_encoding[od - 1] << pll_info->od_shift;
+ }
writel(ctl, cgu->base + pll_info->reg);
+ if (pll_info->set_rate_hook)
+ pll_info->set_rate_hook(pll_info, rate, parent_rate);
+
/* If the PLL is enabled, verify that it's stable */
- if (ctl & BIT(pll_info->enable_bit))
+ if (pll_info->enable_bit >= 0 && (ctl & BIT(pll_info->enable_bit)))
ret = ingenic_pll_check_stable(cgu, pll_info);
spin_unlock_irqrestore(&cgu->lock, flags);
@@ -239,6 +254,9 @@ static int ingenic_pll_enable(struct clk_hw *hw)
int ret;
u32 ctl;
+ if (pll_info->enable_bit < 0)
+ return 0;
+
spin_lock_irqsave(&cgu->lock, flags);
if (pll_info->bypass_bit >= 0) {
ctl = readl(cgu->base + pll_info->bypass_reg);
@@ -269,6 +287,9 @@ static void ingenic_pll_disable(struct clk_hw *hw)
unsigned long flags;
u32 ctl;
+ if (pll_info->enable_bit < 0)
+ return;
+
spin_lock_irqsave(&cgu->lock, flags);
ctl = readl(cgu->base + pll_info->reg);
@@ -286,6 +307,9 @@ static int ingenic_pll_is_enabled(struct clk_hw *hw)
const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll;
u32 ctl;
+ if (pll_info->enable_bit < 0)
+ return true;
+
ctl = readl(cgu->base + pll_info->reg);
return !!(ctl & BIT(pll_info->enable_bit));
diff --git a/drivers/clk/ingenic/cgu.h b/drivers/clk/ingenic/cgu.h
index 147b7df0d657..99da9bd86e63 100644
--- a/drivers/clk/ingenic/cgu.h
+++ b/drivers/clk/ingenic/cgu.h
@@ -33,7 +33,8 @@
* @od_shift: the number of bits to shift the post-VCO divider value by (ie.
* the index of the lowest bit of the post-VCO divider value in
* the PLL's control register)
- * @od_bits: the size of the post-VCO divider field in bits
+ * @od_bits: the size of the post-VCO divider field in bits, or 0 if no
+ * OD field exists (then the OD is fixed to 1)
* @od_max: the maximum post-VCO divider value
* @od_encoding: a pointer to an array mapping post-VCO divider values to
* their encoded values in the PLL control register, or -1 for
@@ -41,8 +42,12 @@
* @bypass_reg: the offset of the bypass control register within the CGU
* @bypass_bit: the index of the bypass bit in the PLL control register, or
* -1 if there is no bypass bit
- * @enable_bit: the index of the enable bit in the PLL control register
- * @stable_bit: the index of the stable bit in the PLL control register
+ * @enable_bit: the index of the enable bit in the PLL control register, or
+ * -1 if there is no enable bit (ie, the PLL is always on)
+ * @stable_bit: the index of the stable bit in the PLL control register, or
+ * -1 if there is no stable bit
+ * @set_rate_hook: hook called immediately after updating the CGU register,
+ * before releasing the spinlock
*/
struct ingenic_cgu_pll_info {
unsigned reg;
@@ -53,11 +58,13 @@ struct ingenic_cgu_pll_info {
u8 od_shift, od_bits, od_max;
unsigned bypass_reg;
s8 bypass_bit;
- u8 enable_bit;
- u8 stable_bit;
+ s8 enable_bit;
+ s8 stable_bit;
void (*calc_m_n_od)(const struct ingenic_cgu_pll_info *pll_info,
unsigned long rate, unsigned long parent_rate,
unsigned int *m, unsigned int *n, unsigned int *od);
+ void (*set_rate_hook)(const struct ingenic_cgu_pll_info *pll_info,
+ unsigned long rate, unsigned long parent_rate);
};
/**
diff --git a/drivers/clk/ingenic/jz4755-cgu.c b/drivers/clk/ingenic/jz4755-cgu.c
new file mode 100644
index 000000000000..f2c2d848dab7
--- /dev/null
+++ b/drivers/clk/ingenic/jz4755-cgu.c
@@ -0,0 +1,346 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Ingenic JZ4755 SoC CGU driver
+ * Heavily based on JZ4725b CGU driver
+ *
+ * Copyright (C) 2022 Siarhei Volkau
+ * Author: Siarhei Volkau <lis8215@gmail.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+
+#include <dt-bindings/clock/ingenic,jz4755-cgu.h>
+
+#include "cgu.h"
+#include "pm.h"
+
+/* CGU register offsets */
+#define CGU_REG_CPCCR 0x00
+#define CGU_REG_CPPCR 0x10
+#define CGU_REG_CLKGR 0x20
+#define CGU_REG_OPCR 0x24
+#define CGU_REG_I2SCDR 0x60
+#define CGU_REG_LPCDR 0x64
+#define CGU_REG_MSCCDR 0x68
+#define CGU_REG_SSICDR 0x74
+#define CGU_REG_CIMCDR 0x7C
+
+static struct ingenic_cgu *cgu;
+
+static const s8 pll_od_encoding[4] = {
+ 0x0, 0x1, -1, 0x3,
+};
+
+static const u8 jz4755_cgu_cpccr_div_table[] = {
+ 1, 2, 3, 4, 6, 8,
+};
+
+static const u8 jz4755_cgu_pll_half_div_table[] = {
+ 2, 1,
+};
+
+static const struct ingenic_cgu_clk_info jz4755_cgu_clocks[] = {
+
+ /* External clocks */
+
+ [JZ4755_CLK_EXT] = { "ext", CGU_CLK_EXT },
+ [JZ4755_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT },
+
+ [JZ4755_CLK_PLL] = {
+ "pll", CGU_CLK_PLL,
+ .parents = { JZ4755_CLK_EXT, },
+ .pll = {
+ .reg = CGU_REG_CPPCR,
+ .rate_multiplier = 1,
+ .m_shift = 23,
+ .m_bits = 9,
+ .m_offset = 2,
+ .n_shift = 18,
+ .n_bits = 5,
+ .n_offset = 2,
+ .od_shift = 16,
+ .od_bits = 2,
+ .od_max = 4,
+ .od_encoding = pll_od_encoding,
+ .stable_bit = 10,
+ .bypass_reg = CGU_REG_CPPCR,
+ .bypass_bit = 9,
+ .enable_bit = 8,
+ },
+ },
+
+ /* Muxes & dividers */
+
+ [JZ4755_CLK_PLL_HALF] = {
+ "pll half", CGU_CLK_DIV,
+ .parents = { JZ4755_CLK_PLL, },
+ .div = {
+ CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, 0,
+ jz4755_cgu_pll_half_div_table,
+ },
+ },
+
+ [JZ4755_CLK_EXT_HALF] = {
+ "ext half", CGU_CLK_DIV,
+ .parents = { JZ4755_CLK_EXT, },
+ .div = {
+ CGU_REG_CPCCR, 30, 1, 1, -1, -1, -1, 0,
+ NULL,
+ },
+ },
+
+ [JZ4755_CLK_CCLK] = {
+ "cclk", CGU_CLK_DIV,
+ .parents = { JZ4755_CLK_PLL, },
+ .div = {
+ CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0,
+ jz4755_cgu_cpccr_div_table,
+ },
+ },
+
+ [JZ4755_CLK_H0CLK] = {
+ "hclk", CGU_CLK_DIV,
+ .parents = { JZ4755_CLK_PLL, },
+ .div = {
+ CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0,
+ jz4755_cgu_cpccr_div_table,
+ },
+ },
+
+ [JZ4755_CLK_PCLK] = {
+ "pclk", CGU_CLK_DIV,
+ .parents = { JZ4755_CLK_PLL, },
+ .div = {
+ CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0,
+ jz4755_cgu_cpccr_div_table,
+ },
+ },
+
+ [JZ4755_CLK_MCLK] = {
+ "mclk", CGU_CLK_DIV,
+ .parents = { JZ4755_CLK_PLL, },
+ .div = {
+ CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0,
+ jz4755_cgu_cpccr_div_table,
+ },
+ },
+
+ [JZ4755_CLK_H1CLK] = {
+ "h1clk", CGU_CLK_DIV,
+ .parents = { JZ4755_CLK_PLL, },
+ .div = {
+ CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0,
+ jz4755_cgu_cpccr_div_table,
+ },
+ },
+
+ [JZ4755_CLK_UDC] = {
+ "udc", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_EXT_HALF, JZ4755_CLK_PLL_HALF, },
+ .mux = { CGU_REG_CPCCR, 29, 1 },
+ .div = { CGU_REG_CPCCR, 23, 1, 6, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR, 10 },
+ },
+
+ [JZ4755_CLK_LCD] = {
+ "lcd", CGU_CLK_DIV | CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_PLL_HALF, },
+ .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR, 9 },
+ },
+
+ [JZ4755_CLK_MMC] = {
+ "mmc", CGU_CLK_DIV,
+ .parents = { JZ4755_CLK_PLL_HALF, },
+ .div = { CGU_REG_MSCCDR, 0, 1, 5, -1, -1, -1 },
+ },
+
+ [JZ4755_CLK_I2S] = {
+ "i2s", CGU_CLK_MUX | CGU_CLK_DIV,
+ .parents = { JZ4755_CLK_EXT_HALF, JZ4755_CLK_PLL_HALF, },
+ .mux = { CGU_REG_CPCCR, 31, 1 },
+ .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 },
+ },
+
+ [JZ4755_CLK_SPI] = {
+ "spi", CGU_CLK_DIV | CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_PLL_HALF, },
+ .div = { CGU_REG_SSICDR, 0, 1, 4, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR, 4 },
+ },
+
+ [JZ4755_CLK_TVE] = {
+ "tve", CGU_CLK_MUX | CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_LCD, JZ4755_CLK_EXT, },
+ .mux = { CGU_REG_LPCDR, 31, 1 },
+ .gate = { CGU_REG_CLKGR, 18 },
+ },
+
+ [JZ4755_CLK_RTC] = {
+ "rtc", CGU_CLK_MUX | CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_EXT512, JZ4755_CLK_OSC32K, },
+ .mux = { CGU_REG_OPCR, 2, 1},
+ .gate = { CGU_REG_CLKGR, 2 },
+ },
+
+ [JZ4755_CLK_CIM] = {
+ "cim", CGU_CLK_DIV | CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_PLL_HALF, },
+ .div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 },
+ .gate = { CGU_REG_CLKGR, 8 },
+ },
+
+ /* Gate-only clocks */
+
+ [JZ4755_CLK_UART0] = {
+ "uart0", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_EXT_HALF, },
+ .gate = { CGU_REG_CLKGR, 0 },
+ },
+
+ [JZ4755_CLK_UART1] = {
+ "uart1", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_EXT_HALF, },
+ .gate = { CGU_REG_CLKGR, 14 },
+ },
+
+ [JZ4755_CLK_UART2] = {
+ "uart2", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_EXT_HALF, },
+ .gate = { CGU_REG_CLKGR, 15 },
+ },
+
+ [JZ4755_CLK_ADC] = {
+ "adc", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_EXT_HALF, },
+ .gate = { CGU_REG_CLKGR, 7 },
+ },
+
+ [JZ4755_CLK_AIC] = {
+ "aic", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_EXT_HALF, },
+ .gate = { CGU_REG_CLKGR, 5 },
+ },
+
+ [JZ4755_CLK_I2C] = {
+ "i2c", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_EXT_HALF, },
+ .gate = { CGU_REG_CLKGR, 3 },
+ },
+
+ [JZ4755_CLK_BCH] = {
+ "bch", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_H1CLK, },
+ .gate = { CGU_REG_CLKGR, 11 },
+ },
+
+ [JZ4755_CLK_TCU] = {
+ "tcu", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_EXT, },
+ .gate = { CGU_REG_CLKGR, 1 },
+ },
+
+ [JZ4755_CLK_DMA] = {
+ "dma", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_PCLK, },
+ .gate = { CGU_REG_CLKGR, 12 },
+ },
+
+ [JZ4755_CLK_MMC0] = {
+ "mmc0", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_MMC, },
+ .gate = { CGU_REG_CLKGR, 6 },
+ },
+
+ [JZ4755_CLK_MMC1] = {
+ "mmc1", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_MMC, },
+ .gate = { CGU_REG_CLKGR, 16 },
+ },
+
+ [JZ4755_CLK_AUX_CPU] = {
+ "aux_cpu", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_H1CLK, },
+ .gate = { CGU_REG_CLKGR, 24 },
+ },
+
+ [JZ4755_CLK_AHB1] = {
+ "ahb1", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_H1CLK, },
+ .gate = { CGU_REG_CLKGR, 23 },
+ },
+
+ [JZ4755_CLK_IDCT] = {
+ "idct", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_H1CLK, },
+ .gate = { CGU_REG_CLKGR, 22 },
+ },
+
+ [JZ4755_CLK_DB] = {
+ "db", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_H1CLK, },
+ .gate = { CGU_REG_CLKGR, 21 },
+ },
+
+ [JZ4755_CLK_ME] = {
+ "me", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_H1CLK, },
+ .gate = { CGU_REG_CLKGR, 20 },
+ },
+
+ [JZ4755_CLK_MC] = {
+ "mc", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_H1CLK, },
+ .gate = { CGU_REG_CLKGR, 19 },
+ },
+
+ [JZ4755_CLK_TSSI] = {
+ "tssi", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_EXT_HALF/* not sure */, },
+ .gate = { CGU_REG_CLKGR, 17 },
+ },
+
+ [JZ4755_CLK_IPU] = {
+ "ipu", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_PLL_HALF/* not sure */, },
+ .gate = { CGU_REG_CLKGR, 13 },
+ },
+
+ [JZ4755_CLK_EXT512] = {
+ "ext/512", CGU_CLK_FIXDIV,
+ .parents = { JZ4755_CLK_EXT, },
+
+ .fixdiv = { 512 },
+ },
+
+ [JZ4755_CLK_UDC_PHY] = {
+ "udc_phy", CGU_CLK_GATE,
+ .parents = { JZ4755_CLK_EXT_HALF, },
+ .gate = { CGU_REG_OPCR, 6, true },
+ },
+};
+
+static void __init jz4755_cgu_init(struct device_node *np)
+{
+ int retval;
+
+ cgu = ingenic_cgu_new(jz4755_cgu_clocks,
+ ARRAY_SIZE(jz4755_cgu_clocks), np);
+ if (!cgu) {
+ pr_err("%s: failed to initialise CGU\n", __func__);
+ return;
+ }
+
+ retval = ingenic_cgu_register_clocks(cgu);
+ if (retval)
+ pr_err("%s: failed to register CGU Clocks\n", __func__);
+
+ ingenic_cgu_register_syscore_ops(cgu);
+}
+/*
+ * CGU has some children devices, this is useful for probing children devices
+ * in the case where the device node is compatible with "simple-mfd".
+ */
+CLK_OF_DECLARE_DRIVER(jz4755_cgu, "ingenic,jz4755-cgu", jz4755_cgu_init);
diff --git a/drivers/clk/ingenic/x1000-cgu.c b/drivers/clk/ingenic/x1000-cgu.c
index b2ce3fb83f54..feb03eed4fe8 100644
--- a/drivers/clk/ingenic/x1000-cgu.c
+++ b/drivers/clk/ingenic/x1000-cgu.c
@@ -8,6 +8,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/of.h>
+#include <linux/rational.h>
#include <dt-bindings/clock/ingenic,x1000-cgu.h>
@@ -168,6 +169,38 @@ static const struct clk_ops x1000_otg_phy_ops = {
.is_enabled = x1000_usb_phy_is_enabled,
};
+static void
+x1000_i2spll_calc_m_n_od(const struct ingenic_cgu_pll_info *pll_info,
+ unsigned long rate, unsigned long parent_rate,
+ unsigned int *pm, unsigned int *pn, unsigned int *pod)
+{
+ const unsigned long m_max = GENMASK(pll_info->m_bits - 1, 0);
+ const unsigned long n_max = GENMASK(pll_info->n_bits - 1, 0);
+ unsigned long m, n;
+
+ rational_best_approximation(rate, parent_rate, m_max, n_max, &m, &n);
+
+ /* n should not be less than 2*m */
+ if (n < 2 * m)
+ n = 2 * m;
+
+ *pm = m;
+ *pn = n;
+ *pod = 1;
+}
+
+static void
+x1000_i2spll_set_rate_hook(const struct ingenic_cgu_pll_info *pll_info,
+ unsigned long rate, unsigned long parent_rate)
+{
+ /*
+ * Writing 0 causes I2SCDR1.I2SDIV_D to be automatically recalculated
+ * based on the current value of I2SCDR.I2SDIV_N, which is needed for
+ * the divider to function correctly.
+ */
+ writel(0, cgu->base + CGU_REG_I2SCDR1);
+}
+
static const s8 pll_od_encoding[8] = {
0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
};
@@ -183,7 +216,7 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
[X1000_CLK_APLL] = {
"apll", CGU_CLK_PLL,
- .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
+ .parents = { X1000_CLK_EXCLK },
.pll = {
.reg = CGU_REG_APLL,
.rate_multiplier = 1,
@@ -206,7 +239,7 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
[X1000_CLK_MPLL] = {
"mpll", CGU_CLK_PLL,
- .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
+ .parents = { X1000_CLK_EXCLK },
.pll = {
.reg = CGU_REG_MPLL,
.rate_multiplier = 1,
@@ -256,7 +289,7 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
* system; mark it critical.
*/
.flags = CLK_IS_CRITICAL,
- .parents = { X1000_CLK_CPUMUX, -1, -1, -1 },
+ .parents = { X1000_CLK_CPUMUX },
.div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
.gate = { CGU_REG_CLKGR, 30 },
},
@@ -268,7 +301,7 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
* disabling it or any parent clocks will hang the system.
*/
.flags = CLK_IS_CRITICAL,
- .parents = { X1000_CLK_CPUMUX, -1, -1, -1 },
+ .parents = { X1000_CLK_CPUMUX },
.div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 },
},
@@ -287,13 +320,13 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
[X1000_CLK_AHB2] = {
"ahb2", CGU_CLK_DIV,
- .parents = { X1000_CLK_AHB2PMUX, -1, -1, -1 },
+ .parents = { X1000_CLK_AHB2PMUX },
.div = { CGU_REG_CPCCR, 12, 1, 4, 20, -1, -1 },
},
[X1000_CLK_PCLK] = {
"pclk", CGU_CLK_DIV | CGU_CLK_GATE,
- .parents = { X1000_CLK_AHB2PMUX, -1, -1, -1 },
+ .parents = { X1000_CLK_AHB2PMUX },
.div = { CGU_REG_CPCCR, 16, 1, 4, 20, -1, -1 },
.gate = { CGU_REG_CLKGR, 28 },
},
@@ -319,6 +352,37 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
.gate = { CGU_REG_CLKGR, 25 },
},
+ [X1000_CLK_I2SPLLMUX] = {
+ "i2s_pll_mux", CGU_CLK_MUX,
+ .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
+ .mux = { CGU_REG_I2SCDR, 31, 1 },
+ },
+
+ [X1000_CLK_I2SPLL] = {
+ "i2s_pll", CGU_CLK_PLL,
+ .parents = { X1000_CLK_I2SPLLMUX },
+ .pll = {
+ .reg = CGU_REG_I2SCDR,
+ .rate_multiplier = 1,
+ .m_shift = 13,
+ .m_bits = 9,
+ .n_shift = 0,
+ .n_bits = 13,
+ .calc_m_n_od = x1000_i2spll_calc_m_n_od,
+ .set_rate_hook = x1000_i2spll_set_rate_hook,
+ },
+ },
+
+ [X1000_CLK_I2S] = {
+ "i2s", CGU_CLK_MUX,
+ .parents = { X1000_CLK_EXCLK, -1, -1, X1000_CLK_I2SPLL },
+ /*
+ * NOTE: the mux is at bit 30; bit 29 enables the M/N divider.
+ * Therefore, the divider is disabled when EXCLK is selected.
+ */
+ .mux = { CGU_REG_I2SCDR, 29, 2 },
+ },
+
[X1000_CLK_LCD] = {
"lcd", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
@@ -329,13 +393,13 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
[X1000_CLK_MSCMUX] = {
"msc_mux", CGU_CLK_MUX,
- .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL},
+ .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
.mux = { CGU_REG_MSC0CDR, 31, 1 },
},
[X1000_CLK_MSC0] = {
"msc0", CGU_CLK_DIV | CGU_CLK_GATE,
- .parents = { X1000_CLK_MSCMUX, -1, -1, -1 },
+ .parents = { X1000_CLK_MSCMUX },
.div = { CGU_REG_MSC0CDR, 0, 2, 8, 29, 28, 27 },
.gate = { CGU_REG_CLKGR, 4 },
},
@@ -349,8 +413,7 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
[X1000_CLK_OTG] = {
"otg", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
- .parents = { X1000_CLK_EXCLK, -1,
- X1000_CLK_APLL, X1000_CLK_MPLL },
+ .parents = { X1000_CLK_EXCLK, -1, X1000_CLK_APLL, X1000_CLK_MPLL },
.mux = { CGU_REG_USBCDR, 30, 2 },
.div = { CGU_REG_USBCDR, 0, 1, 8, 29, 28, 27 },
.gate = { CGU_REG_CLKGR, 3 },
@@ -358,7 +421,7 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
[X1000_CLK_SSIPLL] = {
"ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV,
- .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL, -1, -1 },
+ .parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
.mux = { CGU_REG_SSICDR, 31, 1 },
.div = { CGU_REG_SSICDR, 0, 1, 8, 29, 28, 27 },
},
@@ -371,7 +434,7 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
[X1000_CLK_SSIMUX] = {
"ssi_mux", CGU_CLK_MUX,
- .parents = { X1000_CLK_EXCLK, X1000_CLK_SSIPLL_DIV2, -1, -1 },
+ .parents = { X1000_CLK_EXCLK, X1000_CLK_SSIPLL_DIV2 },
.mux = { CGU_REG_SSICDR, 30, 1 },
},
@@ -392,79 +455,85 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
[X1000_CLK_EMC] = {
"emc", CGU_CLK_GATE,
- .parents = { X1000_CLK_AHB2, -1, -1, -1 },
+ .parents = { X1000_CLK_AHB2 },
.gate = { CGU_REG_CLKGR, 0 },
},
[X1000_CLK_EFUSE] = {
"efuse", CGU_CLK_GATE,
- .parents = { X1000_CLK_AHB2, -1, -1, -1 },
+ .parents = { X1000_CLK_AHB2 },
.gate = { CGU_REG_CLKGR, 1 },
},
[X1000_CLK_SFC] = {
"sfc", CGU_CLK_GATE,
- .parents = { X1000_CLK_SSIPLL, -1, -1, -1 },
+ .parents = { X1000_CLK_SSIPLL },
.gate = { CGU_REG_CLKGR, 2 },
},
[X1000_CLK_I2C0] = {
"i2c0", CGU_CLK_GATE,
- .parents = { X1000_CLK_PCLK, -1, -1, -1 },
+ .parents = { X1000_CLK_PCLK },
.gate = { CGU_REG_CLKGR, 7 },
},
[X1000_CLK_I2C1] = {
"i2c1", CGU_CLK_GATE,
- .parents = { X1000_CLK_PCLK, -1, -1, -1 },
+ .parents = { X1000_CLK_PCLK },
.gate = { CGU_REG_CLKGR, 8 },
},
[X1000_CLK_I2C2] = {
"i2c2", CGU_CLK_GATE,
- .parents = { X1000_CLK_PCLK, -1, -1, -1 },
+ .parents = { X1000_CLK_PCLK },
.gate = { CGU_REG_CLKGR, 9 },
},
+ [X1000_CLK_AIC] = {
+ "aic", CGU_CLK_GATE,
+ .parents = { X1000_CLK_EXCLK },
+ .gate = { CGU_REG_CLKGR, 11 },
+ },
+
[X1000_CLK_UART0] = {
"uart0", CGU_CLK_GATE,
- .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
+ .parents = { X1000_CLK_EXCLK },
.gate = { CGU_REG_CLKGR, 14 },
},
[X1000_CLK_UART1] = {
"uart1", CGU_CLK_GATE,
- .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
+ .parents = { X1000_CLK_EXCLK},
.gate = { CGU_REG_CLKGR, 15 },
},
[X1000_CLK_UART2] = {
"uart2", CGU_CLK_GATE,
- .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
+ .parents = { X1000_CLK_EXCLK },
.gate = { CGU_REG_CLKGR, 16 },
},
[X1000_CLK_TCU] = {
"tcu", CGU_CLK_GATE,
- .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
+ .parents = { X1000_CLK_EXCLK },
.gate = { CGU_REG_CLKGR, 18 },
},
[X1000_CLK_SSI] = {
"ssi", CGU_CLK_GATE,
- .parents = { X1000_CLK_SSIMUX, -1, -1, -1 },
+ .parents = { X1000_CLK_SSIMUX },
.gate = { CGU_REG_CLKGR, 19 },
},
[X1000_CLK_OST] = {
"ost", CGU_CLK_GATE,
- .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
+ .parents = { X1000_CLK_EXCLK },
.gate = { CGU_REG_CLKGR, 20 },
},
[X1000_CLK_PDMA] = {
"pdma", CGU_CLK_GATE,
- .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
+ .parents = { X1000_CLK_EXCLK },
.gate = { CGU_REG_CLKGR, 21 },
},
};
diff --git a/drivers/clk/keystone/syscon-clk.c b/drivers/clk/keystone/syscon-clk.c
index 19198325b909..5d7cc83682da 100644
--- a/drivers/clk/keystone/syscon-clk.c
+++ b/drivers/clk/keystone/syscon-clk.c
@@ -102,12 +102,9 @@ static int ti_syscon_gate_clk_probe(struct platform_device *pdev)
return -EINVAL;
regmap = syscon_node_to_regmap(dev->of_node);
- if (IS_ERR(regmap)) {
- if (PTR_ERR(regmap) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
- dev_err(dev, "failed to find parent regmap\n");
- return PTR_ERR(regmap);
- }
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "failed to find parent regmap\n");
num_clks = 0;
for (p = data; p->name; p++)
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig
index 843cea0c7a44..22e8e79475ee 100644
--- a/drivers/clk/mediatek/Kconfig
+++ b/drivers/clk/mediatek/Kconfig
@@ -11,6 +11,13 @@ config COMMON_CLK_MEDIATEK
help
MediaTek SoCs' clock support.
+config COMMON_CLK_MEDIATEK_FHCTL
+ bool "clock driver for MediaTek FHCTL hardware control"
+ select COMMON_CLK_MEDIATEK
+ help
+ This driver supports MediaTek frequency hopping and
+ spread spectrum clocking features.
+
config COMMON_CLK_MT2701
bool "Clock driver for MediaTek MT2701"
depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
@@ -553,6 +560,7 @@ config COMMON_CLK_MT8186
bool "Clock driver for MediaTek MT8186"
depends on ARM64 || COMPILE_TEST
select COMMON_CLK_MEDIATEK
+ select COMMON_CLK_MEDIATEK_FHCTL
default ARCH_MEDIATEK
help
This driver supports MediaTek MT8186 clocks.
diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile
index ea3b73240303..e24080fd6e7f 100644
--- a/drivers/clk/mediatek/Makefile
+++ b/drivers/clk/mediatek/Makefile
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o reset.o clk-mux.o
+obj-$(CONFIG_COMMON_CLK_MEDIATEK_FHCTL) += clk-fhctl.o clk-pllfh.o
obj-$(CONFIG_COMMON_CLK_MT6765) += clk-mt6765.o
obj-$(CONFIG_COMMON_CLK_MT6765_AUDIOSYS) += clk-mt6765-audio.o
diff --git a/drivers/clk/mediatek/clk-fhctl.c b/drivers/clk/mediatek/clk-fhctl.c
new file mode 100644
index 000000000000..4f271acef5fe
--- /dev/null
+++ b/drivers/clk/mediatek/clk-fhctl.c
@@ -0,0 +1,244 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Edward-JW Yang <edward-jw.yang@mediatek.com>
+ */
+
+#include <linux/io.h>
+#include <linux/iopoll.h>
+
+#include "clk-mtk.h"
+#include "clk-pllfh.h"
+#include "clk-fhctl.h"
+
+#define PERCENT_TO_DDSLMT(dds, percent_m10) \
+ ((((dds) * (percent_m10)) >> 5) / 100)
+
+static const struct fhctl_offset fhctl_offset = {
+ .offset_hp_en = 0x0,
+ .offset_clk_con = 0x8,
+ .offset_rst_con = 0xc,
+ .offset_slope0 = 0x10,
+ .offset_slope1 = 0x14,
+ .offset_cfg = 0x0,
+ .offset_updnlmt = 0x4,
+ .offset_dds = 0x8,
+ .offset_dvfs = 0xc,
+ .offset_mon = 0x10,
+};
+
+const struct fhctl_offset *fhctl_get_offset_table(void)
+{
+ return &fhctl_offset;
+}
+
+static void dump_hw(struct mtk_clk_pll *pll, struct fh_pll_regs *regs,
+ const struct fh_pll_data *data)
+{
+ pr_info("hp_en<%x>,clk_con<%x>,slope0<%x>,slope1<%x>\n",
+ readl(regs->reg_hp_en), readl(regs->reg_clk_con),
+ readl(regs->reg_slope0), readl(regs->reg_slope1));
+ pr_info("cfg<%x>,lmt<%x>,dds<%x>,dvfs<%x>,mon<%x>\n",
+ readl(regs->reg_cfg), readl(regs->reg_updnlmt),
+ readl(regs->reg_dds), readl(regs->reg_dvfs),
+ readl(regs->reg_mon));
+ pr_info("pcw<%x>\n", readl(pll->pcw_addr));
+}
+
+static int fhctl_set_ssc_regs(struct mtk_clk_pll *pll, struct fh_pll_regs *regs,
+ const struct fh_pll_data *data, u32 rate)
+{
+ u32 updnlmt_val, r;
+
+ writel((readl(regs->reg_cfg) & ~(data->frddsx_en)), regs->reg_cfg);
+ writel((readl(regs->reg_cfg) & ~(data->sfstrx_en)), regs->reg_cfg);
+ writel((readl(regs->reg_cfg) & ~(data->fhctlx_en)), regs->reg_cfg);
+
+ if (rate > 0) {
+ /* Set the relative parameter registers (dt/df/upbnd/downbnd) */
+ r = readl(regs->reg_cfg);
+ r &= ~(data->msk_frddsx_dys);
+ r |= (data->df_val << (ffs(data->msk_frddsx_dys) - 1));
+ writel(r, regs->reg_cfg);
+
+ r = readl(regs->reg_cfg);
+ r &= ~(data->msk_frddsx_dts);
+ r |= (data->dt_val << (ffs(data->msk_frddsx_dts) - 1));
+ writel(r, regs->reg_cfg);
+
+ writel((readl(pll->pcw_addr) & data->dds_mask) | data->tgl_org,
+ regs->reg_dds);
+
+ /* Calculate UPDNLMT */
+ updnlmt_val = PERCENT_TO_DDSLMT((readl(regs->reg_dds) &
+ data->dds_mask), rate) <<
+ data->updnlmt_shft;
+
+ writel(updnlmt_val, regs->reg_updnlmt);
+ writel(readl(regs->reg_hp_en) | BIT(data->fh_id),
+ regs->reg_hp_en);
+ /* Enable SSC */
+ writel(readl(regs->reg_cfg) | data->frddsx_en, regs->reg_cfg);
+ /* Enable Hopping control */
+ writel(readl(regs->reg_cfg) | data->fhctlx_en, regs->reg_cfg);
+
+ } else {
+ /* Switch to APMIXEDSYS control */
+ writel(readl(regs->reg_hp_en) & ~BIT(data->fh_id),
+ regs->reg_hp_en);
+ /* Wait for DDS to be stable */
+ udelay(30);
+ }
+
+ return 0;
+}
+
+static int hopping_hw_flow(struct mtk_clk_pll *pll, struct fh_pll_regs *regs,
+ const struct fh_pll_data *data,
+ struct fh_pll_state *state, unsigned int new_dds)
+{
+ u32 dds_mask = data->dds_mask;
+ u32 mon_dds = 0;
+ u32 con_pcw_tmp;
+ int ret;
+
+ if (state->ssc_rate)
+ fhctl_set_ssc_regs(pll, regs, data, 0);
+
+ writel((readl(pll->pcw_addr) & dds_mask) | data->tgl_org,
+ regs->reg_dds);
+
+ writel(readl(regs->reg_cfg) | data->sfstrx_en, regs->reg_cfg);
+ writel(readl(regs->reg_cfg) | data->fhctlx_en, regs->reg_cfg);
+ writel(data->slope0_value, regs->reg_slope0);
+ writel(data->slope1_value, regs->reg_slope1);
+
+ writel(readl(regs->reg_hp_en) | BIT(data->fh_id), regs->reg_hp_en);
+ writel((new_dds) | (data->dvfs_tri), regs->reg_dvfs);
+
+ /* Wait 1000 us until DDS stable */
+ ret = readl_poll_timeout_atomic(regs->reg_mon, mon_dds,
+ (mon_dds & dds_mask) == new_dds,
+ 10, 1000);
+ if (ret) {
+ pr_warn("%s: FHCTL hopping timeout\n", pll->data->name);
+ dump_hw(pll, regs, data);
+ }
+
+ con_pcw_tmp = readl(pll->pcw_addr) & (~dds_mask);
+ con_pcw_tmp = (con_pcw_tmp | (readl(regs->reg_mon) & dds_mask) |
+ data->pcwchg);
+
+ writel(con_pcw_tmp, pll->pcw_addr);
+ writel(readl(regs->reg_hp_en) & ~BIT(data->fh_id), regs->reg_hp_en);
+
+ if (state->ssc_rate)
+ fhctl_set_ssc_regs(pll, regs, data, state->ssc_rate);
+
+ return ret;
+}
+
+static unsigned int __get_postdiv(struct mtk_clk_pll *pll)
+{
+ unsigned int regval;
+
+ regval = readl(pll->pd_addr) >> pll->data->pd_shift;
+ regval &= POSTDIV_MASK;
+
+ return BIT(regval);
+}
+
+static void __set_postdiv(struct mtk_clk_pll *pll, unsigned int postdiv)
+{
+ unsigned int regval;
+
+ regval = readl(pll->pd_addr);
+ regval &= ~(POSTDIV_MASK << pll->data->pd_shift);
+ regval |= (ffs(postdiv) - 1) << pll->data->pd_shift;
+ writel(regval, pll->pd_addr);
+}
+
+static int fhctl_hopping(struct mtk_fh *fh, unsigned int new_dds,
+ unsigned int postdiv)
+{
+ const struct fh_pll_data *data = &fh->pllfh_data->data;
+ struct fh_pll_state *state = &fh->pllfh_data->state;
+ struct fh_pll_regs *regs = &fh->regs;
+ struct mtk_clk_pll *pll = &fh->clk_pll;
+ spinlock_t *lock = fh->lock;
+ unsigned int pll_postdiv;
+ unsigned long flags = 0;
+ int ret;
+
+ if (postdiv) {
+ pll_postdiv = __get_postdiv(pll);
+
+ if (postdiv > pll_postdiv)
+ __set_postdiv(pll, postdiv);
+ }
+
+ spin_lock_irqsave(lock, flags);
+
+ ret = hopping_hw_flow(pll, regs, data, state, new_dds);
+
+ spin_unlock_irqrestore(lock, flags);
+
+ if (postdiv && postdiv < pll_postdiv)
+ __set_postdiv(pll, postdiv);
+
+ return ret;
+}
+
+static int fhctl_ssc_enable(struct mtk_fh *fh, u32 rate)
+{
+ const struct fh_pll_data *data = &fh->pllfh_data->data;
+ struct fh_pll_state *state = &fh->pllfh_data->state;
+ struct fh_pll_regs *regs = &fh->regs;
+ struct mtk_clk_pll *pll = &fh->clk_pll;
+ spinlock_t *lock = fh->lock;
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(lock, flags);
+
+ fhctl_set_ssc_regs(pll, regs, data, rate);
+ state->ssc_rate = rate;
+
+ spin_unlock_irqrestore(lock, flags);
+
+ return 0;
+}
+
+static const struct fh_operation fhctl_ops = {
+ .hopping = fhctl_hopping,
+ .ssc_enable = fhctl_ssc_enable,
+};
+
+const struct fh_operation *fhctl_get_ops(void)
+{
+ return &fhctl_ops;
+}
+
+void fhctl_hw_init(struct mtk_fh *fh)
+{
+ const struct fh_pll_data data = fh->pllfh_data->data;
+ struct fh_pll_state state = fh->pllfh_data->state;
+ struct fh_pll_regs regs = fh->regs;
+ u32 val;
+
+ /* initial hw register */
+ val = readl(regs.reg_clk_con) | BIT(data.fh_id);
+ writel(val, regs.reg_clk_con);
+
+ val = readl(regs.reg_rst_con) & ~BIT(data.fh_id);
+ writel(val, regs.reg_rst_con);
+ val = readl(regs.reg_rst_con) | BIT(data.fh_id);
+ writel(val, regs.reg_rst_con);
+
+ writel(0x0, regs.reg_cfg);
+ writel(0x0, regs.reg_updnlmt);
+ writel(0x0, regs.reg_dds);
+
+ /* enable ssc if needed */
+ if (state.ssc_rate)
+ fh->ops->ssc_enable(fh, state.ssc_rate);
+}
diff --git a/drivers/clk/mediatek/clk-fhctl.h b/drivers/clk/mediatek/clk-fhctl.h
new file mode 100644
index 000000000000..51275febf086
--- /dev/null
+++ b/drivers/clk/mediatek/clk-fhctl.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Edward-JW Yang <edward-jw.yang@mediatek.com>
+ */
+
+#ifndef __CLK_FHCTL_H
+#define __CLK_FHCTL_H
+
+struct fhctl_offset {
+ u32 offset_hp_en;
+ u32 offset_clk_con;
+ u32 offset_rst_con;
+ u32 offset_slope0;
+ u32 offset_slope1;
+ u32 offset_cfg;
+ u32 offset_updnlmt;
+ u32 offset_dds;
+ u32 offset_dvfs;
+ u32 offset_mon;
+};
+const struct fhctl_offset *fhctl_get_offset_table(void);
+const struct fh_operation *fhctl_get_ops(void);
+void fhctl_hw_init(struct mtk_fh *fh);
+
+#endif
diff --git a/drivers/clk/mediatek/clk-mt6795-topckgen.c b/drivers/clk/mediatek/clk-mt6795-topckgen.c
index 2948dd1aee8f..8b8307635a35 100644
--- a/drivers/clk/mediatek/clk-mt6795-topckgen.c
+++ b/drivers/clk/mediatek/clk-mt6795-topckgen.c
@@ -359,19 +359,19 @@ static const struct mtk_fixed_factor top_divs[] = {
FACTOR(CLK_TOP_ARMCA53PLL_754M, "armca53pll_754m", "clk26m", 1, 2),
FACTOR(CLK_TOP_ARMCA53PLL_502M, "armca53pll_502m", "clk26m", 1, 3),
- FACTOR(CLK_TOP_MAIN_H546M, "main_h546m", "mainpll", 1, 2),
- FACTOR(CLK_TOP_MAIN_H364M, "main_h364m", "mainpll", 1, 3),
- FACTOR(CLK_TOP_MAIN_H218P4M, "main_h218p4m", "mainpll", 1, 5),
- FACTOR(CLK_TOP_MAIN_H156M, "main_h156m", "mainpll", 1, 7),
+ FACTOR_FLAGS(CLK_TOP_MAIN_H546M, "main_h546m", "mainpll", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_MAIN_H364M, "main_h364m", "mainpll", 1, 3, 0),
+ FACTOR_FLAGS(CLK_TOP_MAIN_H218P4M, "main_h218p4m", "mainpll", 1, 5, 0),
+ FACTOR_FLAGS(CLK_TOP_MAIN_H156M, "main_h156m", "mainpll", 1, 7, 0),
FACTOR(CLK_TOP_TVDPLL_445P5M, "tvdpll_445p5m", "tvdpll", 1, 4),
FACTOR(CLK_TOP_TVDPLL_594M, "tvdpll_594m", "tvdpll", 1, 3),
- FACTOR(CLK_TOP_UNIV_624M, "univ_624m", "univpll", 1, 2),
- FACTOR(CLK_TOP_UNIV_416M, "univ_416m", "univpll", 1, 3),
- FACTOR(CLK_TOP_UNIV_249P6M, "univ_249p6m", "univpll", 1, 5),
- FACTOR(CLK_TOP_UNIV_178P3M, "univ_178p3m", "univpll", 1, 7),
- FACTOR(CLK_TOP_UNIV_48M, "univ_48m", "univpll", 1, 26),
+ FACTOR_FLAGS(CLK_TOP_UNIV_624M, "univ_624m", "univpll", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIV_416M, "univ_416m", "univpll", 1, 3, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIV_249P6M, "univ_249p6m", "univpll", 1, 5, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIV_178P3M, "univ_178p3m", "univpll", 1, 7, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIV_48M, "univ_48m", "univpll", 1, 26, 0),
FACTOR(CLK_TOP_CLKRTC_EXT, "clkrtc_ext", "clk32k", 1, 1),
FACTOR(CLK_TOP_CLKRTC_INT, "clkrtc_int", "clk26m", 1, 793),
@@ -402,20 +402,20 @@ static const struct mtk_fixed_factor top_divs[] = {
FACTOR(CLK_TOP_MSDCPLL2_D2, "msdcpll2_d2", "msdcpll2", 1, 2),
FACTOR(CLK_TOP_MSDCPLL2_D4, "msdcpll2_d4", "msdcpll2", 1, 4),
- FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "main_h546m", 1, 1),
- FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "main_h546m", 1, 2),
- FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "main_h546m", 1, 4),
- FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "main_h546m", 1, 8),
- FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "main_h546m", 1, 16),
- FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "main_h364m", 1, 1),
- FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "main_h364m", 1, 2),
- FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "main_h364m", 1, 4),
- FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "main_h218p4m", 1, 1),
- FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "main_h218p4m", 1, 2),
- FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "main_h218p4m", 1, 4),
- FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "main_h156m", 1, 1),
- FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "main_h156m", 1, 2),
- FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "main_h156m", 1, 4),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D2, "syspll_d2", "main_h546m", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "main_h546m", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "main_h546m", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "main_h546m", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "main_h546m", 1, 16, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D3, "syspll_d3", "main_h364m", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "main_h364m", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "main_h364m", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D5, "syspll_d5", "main_h218p4m", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "main_h218p4m", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "main_h218p4m", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D7, "syspll_d7", "main_h156m", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "main_h156m", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "main_h156m", 1, 4, 0),
FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll_594m", 1, 1),
FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_594m", 1, 2),
@@ -423,21 +423,21 @@ static const struct mtk_fixed_factor top_divs[] = {
FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_594m", 1, 8),
FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_594m", 1, 16),
- FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univ_624m", 1, 1),
- FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univ_624m", 1, 2),
- FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univ_624m", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univ_624m", 1, 8),
- FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univ_416m", 1, 1),
- FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univ_416m", 1, 2),
- FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univ_416m", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univ_416m", 1, 8),
- FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univ_249p6m", 1, 1),
- FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univ_249p6m", 1, 2),
- FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univ_249p6m", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univ_249p6m", 1, 8),
- FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univ_178p3m", 1, 1),
- FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univ_48m", 1, 1),
- FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univ_48m", 1, 2),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univ_624m", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univ_624m", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univ_624m", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univ_624m", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univ_416m", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univ_416m", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univ_416m", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univ_416m", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univ_249p6m", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univ_249p6m", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univ_249p6m", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univ_249p6m", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univ_178p3m", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univ_48m", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univ_48m", 1, 2, 0),
FACTOR(CLK_TOP_VCODECPLL, "vcodecpll_ck", "vcodecpll", 1, 3),
FACTOR(CLK_TOP_VCODECPLL_370P5, "vcodecpll_370p5", "vcodecpll", 1, 4),
diff --git a/drivers/clk/mediatek/clk-mt7986-infracfg.c b/drivers/clk/mediatek/clk-mt7986-infracfg.c
index d90727a53283..49666047bf0e 100644
--- a/drivers/clk/mediatek/clk-mt7986-infracfg.c
+++ b/drivers/clk/mediatek/clk-mt7986-infracfg.c
@@ -153,7 +153,7 @@ static const struct mtk_gate infra_clks[] = {
18),
GATE_INFRA1(CLK_INFRA_MSDC_66M_CK, "infra_msdc_66m", "infra_sysaxi_d2",
19),
- GATE_INFRA1(CLK_INFRA_ADC_26M_CK, "infra_adc_26m", "csw_f26m_sel", 20),
+ GATE_INFRA1(CLK_INFRA_ADC_26M_CK, "infra_adc_26m", "infra_adc_frc", 20),
GATE_INFRA1(CLK_INFRA_ADC_FRC_CK, "infra_adc_frc", "csw_f26m_sel", 21),
GATE_INFRA1(CLK_INFRA_FBIST2FPC_CK, "infra_fbist2fpc", "nfi1x_sel", 23),
/* INFRA2 */
diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c
index b8529ee7199d..b57e33cda7a5 100644
--- a/drivers/clk/mediatek/clk-mt8173.c
+++ b/drivers/clk/mediatek/clk-mt8173.c
@@ -37,19 +37,19 @@ static const struct mtk_fixed_factor top_divs[] __initconst = {
FACTOR(CLK_TOP_ARMCA7PLL_754M, "armca7pll_754m", "armca7pll", 1, 2),
FACTOR(CLK_TOP_ARMCA7PLL_502M, "armca7pll_502m", "armca7pll", 1, 3),
- FACTOR(CLK_TOP_MAIN_H546M, "main_h546m", "mainpll", 1, 2),
- FACTOR(CLK_TOP_MAIN_H364M, "main_h364m", "mainpll", 1, 3),
- FACTOR(CLK_TOP_MAIN_H218P4M, "main_h218p4m", "mainpll", 1, 5),
- FACTOR(CLK_TOP_MAIN_H156M, "main_h156m", "mainpll", 1, 7),
+ FACTOR_FLAGS(CLK_TOP_MAIN_H546M, "main_h546m", "mainpll", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_MAIN_H364M, "main_h364m", "mainpll", 1, 3, 0),
+ FACTOR_FLAGS(CLK_TOP_MAIN_H218P4M, "main_h218p4m", "mainpll", 1, 5, 0),
+ FACTOR_FLAGS(CLK_TOP_MAIN_H156M, "main_h156m", "mainpll", 1, 7, 0),
FACTOR(CLK_TOP_TVDPLL_445P5M, "tvdpll_445p5m", "tvdpll", 1, 4),
FACTOR(CLK_TOP_TVDPLL_594M, "tvdpll_594m", "tvdpll", 1, 3),
- FACTOR(CLK_TOP_UNIV_624M, "univ_624m", "univpll", 1, 2),
- FACTOR(CLK_TOP_UNIV_416M, "univ_416m", "univpll", 1, 3),
- FACTOR(CLK_TOP_UNIV_249P6M, "univ_249p6m", "univpll", 1, 5),
- FACTOR(CLK_TOP_UNIV_178P3M, "univ_178p3m", "univpll", 1, 7),
- FACTOR(CLK_TOP_UNIV_48M, "univ_48m", "univpll", 1, 26),
+ FACTOR_FLAGS(CLK_TOP_UNIV_624M, "univ_624m", "univpll", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIV_416M, "univ_416m", "univpll", 1, 3, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIV_249P6M, "univ_249p6m", "univpll", 1, 5, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIV_178P3M, "univ_178p3m", "univpll", 1, 7, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIV_48M, "univ_48m", "univpll", 1, 26, 0),
FACTOR(CLK_TOP_CLKRTC_EXT, "clkrtc_ext", "clk32k", 1, 1),
FACTOR(CLK_TOP_CLKRTC_INT, "clkrtc_int", "clk26m", 1, 793),
@@ -84,20 +84,20 @@ static const struct mtk_fixed_factor top_divs[] __initconst = {
FACTOR(CLK_TOP_MSDCPLL2_D2, "msdcpll2_d2", "msdcpll2", 1, 2),
FACTOR(CLK_TOP_MSDCPLL2_D4, "msdcpll2_d4", "msdcpll2", 1, 4),
- FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "main_h546m", 1, 1),
- FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "main_h546m", 1, 2),
- FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "main_h546m", 1, 4),
- FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "main_h546m", 1, 8),
- FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "main_h546m", 1, 16),
- FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "main_h364m", 1, 1),
- FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "main_h364m", 1, 2),
- FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "main_h364m", 1, 4),
- FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "main_h218p4m", 1, 1),
- FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "main_h218p4m", 1, 2),
- FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "main_h218p4m", 1, 4),
- FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "main_h156m", 1, 1),
- FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "main_h156m", 1, 2),
- FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "main_h156m", 1, 4),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D2, "syspll_d2", "main_h546m", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "main_h546m", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "main_h546m", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "main_h546m", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "main_h546m", 1, 16, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D3, "syspll_d3", "main_h364m", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "main_h364m", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "main_h364m", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D5, "syspll_d5", "main_h218p4m", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "main_h218p4m", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "main_h218p4m", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D7, "syspll_d7", "main_h156m", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "main_h156m", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "main_h156m", 1, 4, 0),
FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll_594m", 1, 1),
FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_594m", 1, 2),
@@ -105,21 +105,21 @@ static const struct mtk_fixed_factor top_divs[] __initconst = {
FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_594m", 1, 8),
FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_594m", 1, 16),
- FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univ_624m", 1, 1),
- FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univ_624m", 1, 2),
- FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univ_624m", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univ_624m", 1, 8),
- FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univ_416m", 1, 1),
- FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univ_416m", 1, 2),
- FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univ_416m", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univ_416m", 1, 8),
- FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univ_249p6m", 1, 1),
- FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univ_249p6m", 1, 2),
- FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univ_249p6m", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univ_249p6m", 1, 8),
- FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univ_178p3m", 1, 1),
- FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univ_48m", 1, 1),
- FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univ_48m", 1, 2),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univ_624m", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univ_624m", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univ_624m", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univ_624m", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univ_416m", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univ_416m", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univ_416m", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univ_416m", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univ_249p6m", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univ_249p6m", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univ_249p6m", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univ_249p6m", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univ_178p3m", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univ_48m", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univ_48m", 1, 2, 0),
FACTOR(CLK_TOP_VCODECPLL, "vcodecpll_ck", "vcodecpll", 1, 3),
FACTOR(CLK_TOP_VCODECPLL_370P5, "vcodecpll_370p5", "vcodecpll", 1, 4),
diff --git a/drivers/clk/mediatek/clk-mt8183.c b/drivers/clk/mediatek/clk-mt8183.c
index 1860a35a723a..23afc9584638 100644
--- a/drivers/clk/mediatek/clk-mt8183.c
+++ b/drivers/clk/mediatek/clk-mt8183.c
@@ -31,150 +31,78 @@ static const struct mtk_fixed_factor top_early_divs[] = {
};
static const struct mtk_fixed_factor top_divs[] = {
- FACTOR(CLK_TOP_F26M_CK_D2, "csw_f26m_ck_d2", "clk26m", 1,
- 2),
- FACTOR(CLK_TOP_SYSPLL_CK, "syspll_ck", "mainpll", 1,
- 1),
- FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "syspll_ck", 1,
- 2),
- FACTOR(CLK_TOP_SYSPLL_D2_D2, "syspll_d2_d2", "syspll_d2", 1,
- 2),
- FACTOR(CLK_TOP_SYSPLL_D2_D4, "syspll_d2_d4", "syspll_d2", 1,
- 4),
- FACTOR(CLK_TOP_SYSPLL_D2_D8, "syspll_d2_d8", "syspll_d2", 1,
- 8),
- FACTOR(CLK_TOP_SYSPLL_D2_D16, "syspll_d2_d16", "syspll_d2", 1,
- 16),
- FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1,
- 3),
- FACTOR(CLK_TOP_SYSPLL_D3_D2, "syspll_d3_d2", "syspll_d3", 1,
- 2),
- FACTOR(CLK_TOP_SYSPLL_D3_D4, "syspll_d3_d4", "syspll_d3", 1,
- 4),
- FACTOR(CLK_TOP_SYSPLL_D3_D8, "syspll_d3_d8", "syspll_d3", 1,
- 8),
- FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1,
- 5),
- FACTOR(CLK_TOP_SYSPLL_D5_D2, "syspll_d5_d2", "syspll_d5", 1,
- 2),
- FACTOR(CLK_TOP_SYSPLL_D5_D4, "syspll_d5_d4", "syspll_d5", 1,
- 4),
- FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1,
- 7),
- FACTOR(CLK_TOP_SYSPLL_D7_D2, "syspll_d7_d2", "syspll_d7", 1,
- 2),
- FACTOR(CLK_TOP_SYSPLL_D7_D4, "syspll_d7_d4", "syspll_d7", 1,
- 4),
- FACTOR(CLK_TOP_UNIVPLL_CK, "univpll_ck", "univpll", 1,
- 1),
- FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll_ck", 1,
- 2),
- FACTOR(CLK_TOP_UNIVPLL_D2_D2, "univpll_d2_d2", "univpll_d2", 1,
- 2),
- FACTOR(CLK_TOP_UNIVPLL_D2_D4, "univpll_d2_d4", "univpll_d2", 1,
- 4),
- FACTOR(CLK_TOP_UNIVPLL_D2_D8, "univpll_d2_d8", "univpll_d2", 1,
- 8),
- FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1,
- 3),
- FACTOR(CLK_TOP_UNIVPLL_D3_D2, "univpll_d3_d2", "univpll_d3", 1,
- 2),
- FACTOR(CLK_TOP_UNIVPLL_D3_D4, "univpll_d3_d4", "univpll_d3", 1,
- 4),
- FACTOR(CLK_TOP_UNIVPLL_D3_D8, "univpll_d3_d8", "univpll_d3", 1,
- 8),
- FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1,
- 5),
- FACTOR(CLK_TOP_UNIVPLL_D5_D2, "univpll_d5_d2", "univpll_d5", 1,
- 2),
- FACTOR(CLK_TOP_UNIVPLL_D5_D4, "univpll_d5_d4", "univpll_d5", 1,
- 4),
- FACTOR(CLK_TOP_UNIVPLL_D5_D8, "univpll_d5_d8", "univpll_d5", 1,
- 8),
- FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1,
- 7),
- FACTOR(CLK_TOP_UNIVP_192M_CK, "univ_192m_ck", "univpll_192m", 1,
- 1),
- FACTOR(CLK_TOP_UNIVP_192M_D2, "univ_192m_d2", "univ_192m_ck", 1,
- 2),
- FACTOR(CLK_TOP_UNIVP_192M_D4, "univ_192m_d4", "univ_192m_ck", 1,
- 4),
- FACTOR(CLK_TOP_UNIVP_192M_D8, "univ_192m_d8", "univ_192m_ck", 1,
- 8),
- FACTOR(CLK_TOP_UNIVP_192M_D16, "univ_192m_d16", "univ_192m_ck", 1,
- 16),
- FACTOR(CLK_TOP_UNIVP_192M_D32, "univ_192m_d32", "univ_192m_ck", 1,
- 32),
- FACTOR(CLK_TOP_APLL1_CK, "apll1_ck", "apll1", 1,
- 1),
- FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1", 1,
- 2),
- FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1", 1,
- 4),
- FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1", 1,
- 8),
- FACTOR(CLK_TOP_APLL2_CK, "apll2_ck", "apll2", 1,
- 1),
- FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2", 1,
- 2),
- FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1,
- 4),
- FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "apll2", 1,
- 8),
- FACTOR(CLK_TOP_TVDPLL_CK, "tvdpll_ck", "tvdpll", 1,
- 1),
- FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_ck", 1,
- 2),
- FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1,
- 4),
- FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll", 1,
- 8),
- FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll", 1,
- 16),
- FACTOR(CLK_TOP_MMPLL_CK, "mmpll_ck", "mmpll", 1,
- 1),
- FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll", 1,
- 4),
- FACTOR(CLK_TOP_MMPLL_D4_D2, "mmpll_d4_d2", "mmpll_d4", 1,
- 2),
- FACTOR(CLK_TOP_MMPLL_D4_D4, "mmpll_d4_d4", "mmpll_d4", 1,
- 4),
- FACTOR(CLK_TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1,
- 5),
- FACTOR(CLK_TOP_MMPLL_D5_D2, "mmpll_d5_d2", "mmpll_d5", 1,
- 2),
- FACTOR(CLK_TOP_MMPLL_D5_D4, "mmpll_d5_d4", "mmpll_d5", 1,
- 4),
- FACTOR(CLK_TOP_MMPLL_D6, "mmpll_d6", "mmpll", 1,
- 6),
- FACTOR(CLK_TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1,
- 7),
- FACTOR(CLK_TOP_MFGPLL_CK, "mfgpll_ck", "mfgpll", 1,
- 1),
- FACTOR(CLK_TOP_MSDCPLL_CK, "msdcpll_ck", "msdcpll", 1,
- 1),
- FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1,
- 2),
- FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1,
- 4),
- FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8", "msdcpll", 1,
- 8),
- FACTOR(CLK_TOP_MSDCPLL_D16, "msdcpll_d16", "msdcpll", 1,
- 16),
- FACTOR(CLK_TOP_AD_OSC_CK, "ad_osc_ck", "osc", 1,
- 1),
- FACTOR(CLK_TOP_OSC_D2, "osc_d2", "osc", 1,
- 2),
- FACTOR(CLK_TOP_OSC_D4, "osc_d4", "osc", 1,
- 4),
- FACTOR(CLK_TOP_OSC_D8, "osc_d8", "osc", 1,
- 8),
- FACTOR(CLK_TOP_OSC_D16, "osc_d16", "osc", 1,
- 16),
- FACTOR(CLK_TOP_UNIVPLL, "univpll", "univ2pll", 1,
- 2),
- FACTOR(CLK_TOP_UNIVPLL_D3_D16, "univpll_d3_d16", "univpll_d3", 1,
- 16),
+ FACTOR(CLK_TOP_F26M_CK_D2, "csw_f26m_ck_d2", "clk26m", 1, 2),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_CK, "syspll_ck", "mainpll", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D2, "syspll_d2", "syspll_ck", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D2_D2, "syspll_d2_d2", "syspll_d2", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D2_D4, "syspll_d2_d4", "syspll_d2", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D2_D8, "syspll_d2_d8", "syspll_d2", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D2_D16, "syspll_d2_d16", "syspll_d2", 1, 16, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, 3, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D3_D2, "syspll_d3_d2", "syspll_d3", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D3_D4, "syspll_d3_d4", "syspll_d3", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D3_D8, "syspll_d3_d8", "syspll_d3", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D5_D2, "syspll_d5_d2", "syspll_d5", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D5_D4, "syspll_d5_d4", "syspll_d5", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1, 7, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D7_D2, "syspll_d7_d2", "syspll_d7", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_SYSPLL_D7_D4, "syspll_d7_d4", "syspll_d7", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_CK, "univpll_ck", "univpll", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll_ck", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D2_D2, "univpll_d2_d2", "univpll_d2", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D2_D4, "univpll_d2_d4", "univpll_d2", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D2_D8, "univpll_d2_d8", "univpll_d2", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D3_D2, "univpll_d3_d2", "univpll_d3", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D3_D4, "univpll_d3_d4", "univpll_d3", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D3_D8, "univpll_d3_d8", "univpll_d3", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D5_D2, "univpll_d5_d2", "univpll_d5", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D5_D4, "univpll_d5_d4", "univpll_d5", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D5_D8, "univpll_d5_d8", "univpll_d5", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVP_192M_CK, "univ_192m_ck", "univpll_192m", 1, 1, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVP_192M_D2, "univ_192m_d2", "univ_192m_ck", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVP_192M_D4, "univ_192m_d4", "univ_192m_ck", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVP_192M_D8, "univ_192m_d8", "univ_192m_ck", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVP_192M_D16, "univ_192m_d16", "univ_192m_ck", 1, 16, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVP_192M_D32, "univ_192m_d32", "univ_192m_ck", 1, 32, 0),
+ FACTOR(CLK_TOP_APLL1_CK, "apll1_ck", "apll1", 1, 1),
+ FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1", 1, 2),
+ FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1", 1, 4),
+ FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1", 1, 8),
+ FACTOR(CLK_TOP_APLL2_CK, "apll2_ck", "apll2", 1, 1),
+ FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2", 1, 2),
+ FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1, 4),
+ FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "apll2", 1, 8),
+ FACTOR(CLK_TOP_TVDPLL_CK, "tvdpll_ck", "tvdpll", 1, 1),
+ FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_ck", 1, 2),
+ FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4),
+ FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll", 1, 8),
+ FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll", 1, 16),
+ FACTOR(CLK_TOP_MMPLL_CK, "mmpll_ck", "mmpll", 1, 1),
+ FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll", 1, 4),
+ FACTOR(CLK_TOP_MMPLL_D4_D2, "mmpll_d4_d2", "mmpll_d4", 1, 2),
+ FACTOR(CLK_TOP_MMPLL_D4_D4, "mmpll_d4_d4", "mmpll_d4", 1, 4),
+ FACTOR(CLK_TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5),
+ FACTOR(CLK_TOP_MMPLL_D5_D2, "mmpll_d5_d2", "mmpll_d5", 1, 2),
+ FACTOR(CLK_TOP_MMPLL_D5_D4, "mmpll_d5_d4", "mmpll_d5", 1, 4),
+ FACTOR(CLK_TOP_MMPLL_D6, "mmpll_d6", "mmpll", 1, 6),
+ FACTOR(CLK_TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7),
+ FACTOR(CLK_TOP_MFGPLL_CK, "mfgpll_ck", "mfgpll", 1, 1),
+ FACTOR(CLK_TOP_MSDCPLL_CK, "msdcpll_ck", "msdcpll", 1, 1),
+ FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
+ FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4),
+ FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8", "msdcpll", 1, 8),
+ FACTOR(CLK_TOP_MSDCPLL_D16, "msdcpll_d16", "msdcpll", 1, 16),
+ FACTOR(CLK_TOP_AD_OSC_CK, "ad_osc_ck", "osc", 1, 1),
+ FACTOR(CLK_TOP_OSC_D2, "osc_d2", "osc", 1, 2),
+ FACTOR(CLK_TOP_OSC_D4, "osc_d4", "osc", 1, 4),
+ FACTOR(CLK_TOP_OSC_D8, "osc_d8", "osc", 1, 8),
+ FACTOR(CLK_TOP_OSC_D16, "osc_d16", "osc", 1, 16),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL, "univpll", "univ2pll", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D3_D16, "univpll_d3_d16", "univpll_d3", 1, 16, 0),
};
static const char * const axi_parents[] = {
diff --git a/drivers/clk/mediatek/clk-mt8186-apmixedsys.c b/drivers/clk/mediatek/clk-mt8186-apmixedsys.c
index e692a2a67ce1..1d673c6278a9 100644
--- a/drivers/clk/mediatek/clk-mt8186-apmixedsys.c
+++ b/drivers/clk/mediatek/clk-mt8186-apmixedsys.c
@@ -9,6 +9,7 @@
#include "clk-mtk.h"
#include "clk-pll.h"
+#include "clk-pllfh.h"
#define MT8186_PLL_FMAX (3800UL * MHZ)
#define MT8186_PLL_FMIN (1500UL * MHZ)
@@ -76,6 +77,59 @@ static const struct mtk_pll_data plls[] = {
0, 0, 32, 0x034C, 24, 0x0044, 0x000C, 5, 0x0350),
};
+enum fh_pll_id {
+ FH_ARMPLL_LL,
+ FH_ARMPLL_BL,
+ FH_CCIPLL,
+ FH_MAINPLL,
+ FH_MMPLL,
+ FH_TVDPLL,
+ FH_RESERVE6,
+ FH_ADSPPLL,
+ FH_MFGPLL,
+ FH_NNAPLL,
+ FH_NNA2PLL,
+ FH_MSDCPLL,
+ FH_RESERVE12,
+ FH_NR_FH,
+};
+
+#define FH(_pllid, _fhid, _offset) { \
+ .data = { \
+ .pll_id = _pllid, \
+ .fh_id = _fhid, \
+ .fhx_offset = _offset, \
+ .dds_mask = GENMASK(21, 0), \
+ .slope0_value = 0x6003c97, \
+ .slope1_value = 0x6003c97, \
+ .sfstrx_en = BIT(2), \
+ .frddsx_en = BIT(1), \
+ .fhctlx_en = BIT(0), \
+ .tgl_org = BIT(31), \
+ .dvfs_tri = BIT(31), \
+ .pcwchg = BIT(31), \
+ .dt_val = 0x0, \
+ .df_val = 0x9, \
+ .updnlmt_shft = 16, \
+ .msk_frddsx_dys = GENMASK(23, 20), \
+ .msk_frddsx_dts = GENMASK(19, 16), \
+ }, \
+ }
+
+static struct mtk_pllfh_data pllfhs[] = {
+ FH(CLK_APMIXED_ARMPLL_LL, FH_ARMPLL_LL, 0x003C),
+ FH(CLK_APMIXED_ARMPLL_BL, FH_ARMPLL_BL, 0x0050),
+ FH(CLK_APMIXED_CCIPLL, FH_CCIPLL, 0x0064),
+ FH(CLK_APMIXED_MAINPLL, FH_MAINPLL, 0x0078),
+ FH(CLK_APMIXED_MMPLL, FH_MMPLL, 0x008C),
+ FH(CLK_APMIXED_TVDPLL, FH_TVDPLL, 0x00A0),
+ FH(CLK_APMIXED_ADSPPLL, FH_ADSPPLL, 0x00C8),
+ FH(CLK_APMIXED_MFGPLL, FH_MFGPLL, 0x00DC),
+ FH(CLK_APMIXED_NNAPLL, FH_NNAPLL, 0x00F0),
+ FH(CLK_APMIXED_NNA2PLL, FH_NNA2PLL, 0x0104),
+ FH(CLK_APMIXED_MSDCPLL, FH_MSDCPLL, 0x0118),
+};
+
static const struct of_device_id of_match_clk_mt8186_apmixed[] = {
{ .compatible = "mediatek,mt8186-apmixedsys", },
{}
@@ -85,13 +139,17 @@ static int clk_mt8186_apmixed_probe(struct platform_device *pdev)
{
struct clk_hw_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
+ const u8 *fhctl_node = "mediatek,mt8186-fhctl";
int r;
clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
if (!clk_data)
return -ENOMEM;
- r = mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+ fhctl_parse_dt(fhctl_node, pllfhs, ARRAY_SIZE(pllfhs));
+
+ r = mtk_clk_register_pllfhs(node, plls, ARRAY_SIZE(plls),
+ pllfhs, ARRAY_SIZE(pllfhs), clk_data);
if (r)
goto free_apmixed_data;
@@ -104,7 +162,8 @@ static int clk_mt8186_apmixed_probe(struct platform_device *pdev)
return r;
unregister_plls:
- mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data);
+ mtk_clk_unregister_pllfhs(plls, ARRAY_SIZE(plls), pllfhs,
+ ARRAY_SIZE(pllfhs), clk_data);
free_apmixed_data:
mtk_free_clk_data(clk_data);
return r;
@@ -116,7 +175,8 @@ static int clk_mt8186_apmixed_remove(struct platform_device *pdev)
struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev);
of_clk_del_provider(node);
- mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data);
+ mtk_clk_unregister_pllfhs(plls, ARRAY_SIZE(plls), pllfhs,
+ ARRAY_SIZE(pllfhs), clk_data);
mtk_free_clk_data(clk_data);
return 0;
diff --git a/drivers/clk/mediatek/clk-mt8186-mfg.c b/drivers/clk/mediatek/clk-mt8186-mfg.c
index f1f92216f894..0142d741053a 100644
--- a/drivers/clk/mediatek/clk-mt8186-mfg.c
+++ b/drivers/clk/mediatek/clk-mt8186-mfg.c
@@ -16,8 +16,9 @@ static const struct mtk_gate_regs mfg_cg_regs = {
.sta_ofs = 0x0,
};
-#define GATE_MFG(_id, _name, _parent, _shift) \
- GATE_MTK(_id, _name, _parent, &mfg_cg_regs, _shift, &mtk_clk_gate_ops_setclr)
+#define GATE_MFG(_id, _name, _parent, _shift) \
+ GATE_MTK_FLAGS(_id, _name, _parent, &mfg_cg_regs, _shift, \
+ &mtk_clk_gate_ops_setclr, CLK_SET_RATE_PARENT)
static const struct mtk_gate mfg_clks[] = {
GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "top_mfg", 0),
diff --git a/drivers/clk/mediatek/clk-mt8186-topckgen.c b/drivers/clk/mediatek/clk-mt8186-topckgen.c
index d7f2c4663c85..c2beda7ef976 100644
--- a/drivers/clk/mediatek/clk-mt8186-topckgen.c
+++ b/drivers/clk/mediatek/clk-mt8186-topckgen.c
@@ -19,37 +19,37 @@ static const struct mtk_fixed_clk top_fixed_clks[] = {
};
static const struct mtk_fixed_factor top_divs[] = {
- FACTOR(CLK_TOP_MAINPLL_D2, "mainpll_d2", "mainpll", 1, 2),
- FACTOR(CLK_TOP_MAINPLL_D2_D2, "mainpll_d2_d2", "mainpll_d2", 1, 2),
- FACTOR(CLK_TOP_MAINPLL_D2_D4, "mainpll_d2_d4", "mainpll_d2", 1, 4),
- FACTOR(CLK_TOP_MAINPLL_D2_D16, "mainpll_d2_d16", "mainpll_d2", 1, 16),
- FACTOR(CLK_TOP_MAINPLL_D3, "mainpll_d3", "mainpll", 1, 3),
- FACTOR(CLK_TOP_MAINPLL_D3_D2, "mainpll_d3_d2", "mainpll_d3", 1, 2),
- FACTOR(CLK_TOP_MAINPLL_D3_D4, "mainpll_d3_d4", "mainpll_d3", 1, 4),
- FACTOR(CLK_TOP_MAINPLL_D5, "mainpll_d5", "mainpll", 1, 5),
- FACTOR(CLK_TOP_MAINPLL_D5_D2, "mainpll_d5_d2", "mainpll_d5", 1, 2),
- FACTOR(CLK_TOP_MAINPLL_D5_D4, "mainpll_d5_d4", "mainpll_d5", 1, 4),
- FACTOR(CLK_TOP_MAINPLL_D7, "mainpll_d7", "mainpll", 1, 7),
- FACTOR(CLK_TOP_MAINPLL_D7_D2, "mainpll_d7_d2", "mainpll_d7", 1, 2),
- FACTOR(CLK_TOP_MAINPLL_D7_D4, "mainpll_d7_d4", "mainpll_d7", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL, "univpll", "univ2pll", 1, 2),
- FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
- FACTOR(CLK_TOP_UNIVPLL_D2_D2, "univpll_d2_d2", "univpll_d2", 1, 2),
- FACTOR(CLK_TOP_UNIVPLL_D2_D4, "univpll_d2_d4", "univpll_d2", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
- FACTOR(CLK_TOP_UNIVPLL_D3_D2, "univpll_d3_d2", "univpll_d3", 1, 2),
- FACTOR(CLK_TOP_UNIVPLL_D3_D4, "univpll_d3_d4", "univpll_d3", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL_D3_D8, "univpll_d3_d8", "univpll_d3", 1, 8),
- FACTOR(CLK_TOP_UNIVPLL_D3_D32, "univpll_d3_d32", "univpll_d3", 1, 32),
- FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
- FACTOR(CLK_TOP_UNIVPLL_D5_D2, "univpll_d5_d2", "univpll_d5", 1, 2),
- FACTOR(CLK_TOP_UNIVPLL_D5_D4, "univpll_d5_d4", "univpll_d5", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
- FACTOR(CLK_TOP_UNIVPLL_192M, "univpll_192m", "univ2pll", 1, 13),
- FACTOR(CLK_TOP_UNIVPLL_192M_D4, "univpll_192m_d4", "univpll_192m", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL_192M_D8, "univpll_192m_d8", "univpll_192m", 1, 8),
- FACTOR(CLK_TOP_UNIVPLL_192M_D16, "univpll_192m_d16", "univpll_192m", 1, 16),
- FACTOR(CLK_TOP_UNIVPLL_192M_D32, "univpll_192m_d32", "univpll_192m", 1, 32),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D2, "mainpll_d2", "mainpll", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D2_D2, "mainpll_d2_d2", "mainpll_d2", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D2_D4, "mainpll_d2_d4", "mainpll_d2", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D2_D16, "mainpll_d2_d16", "mainpll_d2", 1, 16, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D3, "mainpll_d3", "mainpll", 1, 3, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D3_D2, "mainpll_d3_d2", "mainpll_d3", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D3_D4, "mainpll_d3_d4", "mainpll_d3", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D5, "mainpll_d5", "mainpll", 1, 5, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D5_D2, "mainpll_d5_d2", "mainpll_d5", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D5_D4, "mainpll_d5_d4", "mainpll_d5", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D7, "mainpll_d7", "mainpll", 1, 7, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D7_D2, "mainpll_d7_d2", "mainpll_d7", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D7_D4, "mainpll_d7_d4", "mainpll_d7", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL, "univpll", "univ2pll", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D2_D2, "univpll_d2_d2", "univpll_d2", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D2_D4, "univpll_d2_d4", "univpll_d2", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D3_D2, "univpll_d3_d2", "univpll_d3", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D3_D4, "univpll_d3_d4", "univpll_d3", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D3_D8, "univpll_d3_d8", "univpll_d3", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D3_D32, "univpll_d3_d32", "univpll_d3", 1, 32, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D5_D2, "univpll_d5_d2", "univpll_d5", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D5_D4, "univpll_d5_d4", "univpll_d5", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_192M, "univpll_192m", "univ2pll", 1, 13, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_192M_D4, "univpll_192m_d4", "univpll_192m", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_192M_D8, "univpll_192m_d8", "univpll_192m", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_192M_D16, "univpll_192m_d16", "univpll_192m", 1, 16, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_192M_D32, "univpll_192m_d32", "univpll_192m", 1, 32, 0),
FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1", 1, 2),
FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1", 1, 4),
FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1", 1, 8),
@@ -689,6 +689,28 @@ static const struct of_device_id of_match_clk_mt8186_topck[] = {
{}
};
+/* Register mux notifier for MFG mux */
+static int clk_mt8186_reg_mfg_mux_notifier(struct device *dev, struct clk *clk)
+{
+ struct mtk_mux_nb *mfg_mux_nb;
+ int i;
+
+ mfg_mux_nb = devm_kzalloc(dev, sizeof(*mfg_mux_nb), GFP_KERNEL);
+ if (!mfg_mux_nb)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(top_mtk_muxes); i++)
+ if (top_mtk_muxes[i].id == CLK_TOP_MFG)
+ break;
+ if (i == ARRAY_SIZE(top_mtk_muxes))
+ return -EINVAL;
+
+ mfg_mux_nb->ops = top_mtk_muxes[i].ops;
+ mfg_mux_nb->bypass_index = 0; /* Bypass to 26M crystal */
+
+ return devm_mtk_clk_mux_notifier_register(dev, clk, mfg_mux_nb);
+}
+
static int clk_mt8186_topck_probe(struct platform_device *pdev)
{
struct clk_hw_onecell_data *clk_data;
@@ -730,6 +752,11 @@ static int clk_mt8186_topck_probe(struct platform_device *pdev)
if (r)
goto unregister_composite_muxes;
+ r = clk_mt8186_reg_mfg_mux_notifier(&pdev->dev,
+ clk_data->hws[CLK_TOP_MFG]->clk);
+ if (r)
+ goto unregister_composite_divs;
+
r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
if (r)
goto unregister_composite_divs;
diff --git a/drivers/clk/mediatek/clk-mt8192.c b/drivers/clk/mediatek/clk-mt8192.c
index d0f226931070..0e88588b2c49 100644
--- a/drivers/clk/mediatek/clk-mt8192.c
+++ b/drivers/clk/mediatek/clk-mt8192.c
@@ -31,38 +31,38 @@ static const struct mtk_fixed_factor top_early_divs[] = {
};
static const struct mtk_fixed_factor top_divs[] = {
- FACTOR(CLK_TOP_MAINPLL_D3, "mainpll_d3", "mainpll", 1, 3),
- FACTOR(CLK_TOP_MAINPLL_D4, "mainpll_d4", "mainpll", 1, 4),
- FACTOR(CLK_TOP_MAINPLL_D4_D2, "mainpll_d4_d2", "mainpll_d4", 1, 2),
- FACTOR(CLK_TOP_MAINPLL_D4_D4, "mainpll_d4_d4", "mainpll_d4", 1, 4),
- FACTOR(CLK_TOP_MAINPLL_D4_D8, "mainpll_d4_d8", "mainpll_d4", 1, 8),
- FACTOR(CLK_TOP_MAINPLL_D4_D16, "mainpll_d4_d16", "mainpll_d4", 1, 16),
- FACTOR(CLK_TOP_MAINPLL_D5, "mainpll_d5", "mainpll", 1, 5),
- FACTOR(CLK_TOP_MAINPLL_D5_D2, "mainpll_d5_d2", "mainpll_d5", 1, 2),
- FACTOR(CLK_TOP_MAINPLL_D5_D4, "mainpll_d5_d4", "mainpll_d5", 1, 4),
- FACTOR(CLK_TOP_MAINPLL_D5_D8, "mainpll_d5_d8", "mainpll_d5", 1, 8),
- FACTOR(CLK_TOP_MAINPLL_D6, "mainpll_d6", "mainpll", 1, 6),
- FACTOR(CLK_TOP_MAINPLL_D6_D2, "mainpll_d6_d2", "mainpll_d6", 1, 2),
- FACTOR(CLK_TOP_MAINPLL_D6_D4, "mainpll_d6_d4", "mainpll_d6", 1, 4),
- FACTOR(CLK_TOP_MAINPLL_D7, "mainpll_d7", "mainpll", 1, 7),
- FACTOR(CLK_TOP_MAINPLL_D7_D2, "mainpll_d7_d2", "mainpll_d7", 1, 2),
- FACTOR(CLK_TOP_MAINPLL_D7_D4, "mainpll_d7_d4", "mainpll_d7", 1, 4),
- FACTOR(CLK_TOP_MAINPLL_D7_D8, "mainpll_d7_d8", "mainpll_d7", 1, 8),
- FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
- FACTOR(CLK_TOP_UNIVPLL_D4, "univpll_d4", "univpll", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL_D4_D2, "univpll_d4_d2", "univpll_d4", 1, 2),
- FACTOR(CLK_TOP_UNIVPLL_D4_D4, "univpll_d4_d4", "univpll_d4", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL_D4_D8, "univpll_d4_d8", "univpll_d4", 1, 8),
- FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
- FACTOR(CLK_TOP_UNIVPLL_D5_D2, "univpll_d5_d2", "univpll_d5", 1, 2),
- FACTOR(CLK_TOP_UNIVPLL_D5_D4, "univpll_d5_d4", "univpll_d5", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL_D5_D8, "univpll_d5_d8", "univpll_d5", 1, 8),
- FACTOR(CLK_TOP_UNIVPLL_D6, "univpll_d6", "univpll", 1, 6),
- FACTOR(CLK_TOP_UNIVPLL_D6_D2, "univpll_d6_d2", "univpll_d6", 1, 2),
- FACTOR(CLK_TOP_UNIVPLL_D6_D4, "univpll_d6_d4", "univpll_d6", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL_D6_D8, "univpll_d6_d8", "univpll_d6", 1, 8),
- FACTOR(CLK_TOP_UNIVPLL_D6_D16, "univpll_d6_d16", "univpll_d6", 1, 16),
- FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D3, "mainpll_d3", "mainpll", 1, 3, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D4, "mainpll_d4", "mainpll", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D4_D2, "mainpll_d4_d2", "mainpll_d4", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D4_D4, "mainpll_d4_d4", "mainpll_d4", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D4_D8, "mainpll_d4_d8", "mainpll_d4", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D4_D16, "mainpll_d4_d16", "mainpll_d4", 1, 16, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D5, "mainpll_d5", "mainpll", 1, 5, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D5_D2, "mainpll_d5_d2", "mainpll_d5", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D5_D4, "mainpll_d5_d4", "mainpll_d5", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D5_D8, "mainpll_d5_d8", "mainpll_d5", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D6, "mainpll_d6", "mainpll", 1, 6, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D6_D2, "mainpll_d6_d2", "mainpll_d6", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D6_D4, "mainpll_d6_d4", "mainpll_d6", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D7, "mainpll_d7", "mainpll", 1, 7, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D7_D2, "mainpll_d7_d2", "mainpll_d7", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D7_D4, "mainpll_d7_d4", "mainpll_d7", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D7_D8, "mainpll_d7_d8", "mainpll_d7", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D4, "univpll_d4", "univpll", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D4_D2, "univpll_d4_d2", "univpll_d4", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D4_D4, "univpll_d4_d4", "univpll_d4", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D4_D8, "univpll_d4_d8", "univpll_d4", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D5_D2, "univpll_d5_d2", "univpll_d5", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D5_D4, "univpll_d5_d4", "univpll_d5", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D5_D8, "univpll_d5_d8", "univpll_d5", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D6, "univpll_d6", "univpll", 1, 6, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D6_D2, "univpll_d6_d2", "univpll_d6", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D6_D4, "univpll_d6_d4", "univpll_d6", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D6_D8, "univpll_d6_d8", "univpll_d6", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D6_D16, "univpll_d6_d16", "univpll_d6", 1, 16, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7, 0),
FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, 1),
FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1", 1, 2),
FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1", 1, 4),
@@ -96,12 +96,12 @@ static const struct mtk_fixed_factor top_divs[] = {
FACTOR(CLK_TOP_OSC_D16, "osc_d16", "ulposc", 1, 16),
FACTOR(CLK_TOP_OSC_D20, "osc_d20", "ulposc", 1, 20),
FACTOR(CLK_TOP_ADSPPLL, "adsppll_ck", "adsppll", 1, 1),
- FACTOR(CLK_TOP_UNIVPLL_192M, "univpll_192m", "univpll", 1, 13),
- FACTOR(CLK_TOP_UNIVPLL_192M_D2, "univpll_192m_d2", "univpll_192m", 1, 2),
- FACTOR(CLK_TOP_UNIVPLL_192M_D4, "univpll_192m_d4", "univpll_192m", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL_192M_D8, "univpll_192m_d8", "univpll_192m", 1, 8),
- FACTOR(CLK_TOP_UNIVPLL_192M_D16, "univpll_192m_d16", "univpll_192m", 1, 16),
- FACTOR(CLK_TOP_UNIVPLL_192M_D32, "univpll_192m_d32", "univpll_192m", 1, 32),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_192M, "univpll_192m", "univpll", 1, 13, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_192M_D2, "univpll_192m_d2", "univpll_192m", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_192M_D4, "univpll_192m_d4", "univpll_192m", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_192M_D8, "univpll_192m_d8", "univpll_192m", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_192M_D16, "univpll_192m_d16", "univpll_192m", 1, 16, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_192M_D32, "univpll_192m_d32", "univpll_192m", 1, 32, 0),
};
static const char * const axi_parents[] = {
diff --git a/drivers/clk/mediatek/clk-mt8195-topckgen.c b/drivers/clk/mediatek/clk-mt8195-topckgen.c
index 1e016329c1d2..93e96419da66 100644
--- a/drivers/clk/mediatek/clk-mt8195-topckgen.c
+++ b/drivers/clk/mediatek/clk-mt8195-topckgen.c
@@ -35,45 +35,45 @@ static const struct mtk_fixed_factor top_divs[] = {
FACTOR(CLK_TOP_IN_DGI_D4, "in_dgi_d4", "in_dgi", 1, 4),
FACTOR(CLK_TOP_IN_DGI_D6, "in_dgi_d6", "in_dgi", 1, 6),
FACTOR(CLK_TOP_IN_DGI_D8, "in_dgi_d8", "in_dgi", 1, 8),
- FACTOR(CLK_TOP_MAINPLL_D3, "mainpll_d3", "mainpll", 1, 3),
- FACTOR(CLK_TOP_MAINPLL_D4, "mainpll_d4", "mainpll", 1, 4),
- FACTOR(CLK_TOP_MAINPLL_D4_D2, "mainpll_d4_d2", "mainpll_d4", 1, 2),
- FACTOR(CLK_TOP_MAINPLL_D4_D4, "mainpll_d4_d4", "mainpll_d4", 1, 4),
- FACTOR(CLK_TOP_MAINPLL_D4_D8, "mainpll_d4_d8", "mainpll_d4", 1, 8),
- FACTOR(CLK_TOP_MAINPLL_D5, "mainpll_d5", "mainpll", 1, 5),
- FACTOR(CLK_TOP_MAINPLL_D5_D2, "mainpll_d5_d2", "mainpll_d5", 1, 2),
- FACTOR(CLK_TOP_MAINPLL_D5_D4, "mainpll_d5_d4", "mainpll_d5", 1, 4),
- FACTOR(CLK_TOP_MAINPLL_D5_D8, "mainpll_d5_d8", "mainpll_d5", 1, 8),
- FACTOR(CLK_TOP_MAINPLL_D6, "mainpll_d6", "mainpll", 1, 6),
- FACTOR(CLK_TOP_MAINPLL_D6_D2, "mainpll_d6_d2", "mainpll_d6", 1, 2),
- FACTOR(CLK_TOP_MAINPLL_D6_D4, "mainpll_d6_d4", "mainpll_d6", 1, 4),
- FACTOR(CLK_TOP_MAINPLL_D6_D8, "mainpll_d6_d8", "mainpll_d6", 1, 8),
- FACTOR(CLK_TOP_MAINPLL_D7, "mainpll_d7", "mainpll", 1, 7),
- FACTOR(CLK_TOP_MAINPLL_D7_D2, "mainpll_d7_d2", "mainpll_d7", 1, 2),
- FACTOR(CLK_TOP_MAINPLL_D7_D4, "mainpll_d7_d4", "mainpll_d7", 1, 4),
- FACTOR(CLK_TOP_MAINPLL_D7_D8, "mainpll_d7_d8", "mainpll_d7", 1, 8),
- FACTOR(CLK_TOP_MAINPLL_D9, "mainpll_d9", "mainpll", 1, 9),
- FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
- FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
- FACTOR(CLK_TOP_UNIVPLL_D4, "univpll_d4", "univpll", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL_D4_D2, "univpll_d4_d2", "univpll_d4", 1, 2),
- FACTOR(CLK_TOP_UNIVPLL_D4_D4, "univpll_d4_d4", "univpll_d4", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL_D4_D8, "univpll_d4_d8", "univpll_d4", 1, 8),
- FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
- FACTOR(CLK_TOP_UNIVPLL_D5_D2, "univpll_d5_d2", "univpll_d5", 1, 2),
- FACTOR(CLK_TOP_UNIVPLL_D5_D4, "univpll_d5_d4", "univpll_d5", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL_D5_D8, "univpll_d5_d8", "univpll_d5", 1, 8),
- FACTOR(CLK_TOP_UNIVPLL_D6, "univpll_d6", "univpll", 1, 6),
- FACTOR(CLK_TOP_UNIVPLL_D6_D2, "univpll_d6_d2", "univpll_d6", 1, 2),
- FACTOR(CLK_TOP_UNIVPLL_D6_D4, "univpll_d6_d4", "univpll_d6", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL_D6_D8, "univpll_d6_d8", "univpll_d6", 1, 8),
- FACTOR(CLK_TOP_UNIVPLL_D6_D16, "univpll_d6_d16", "univpll_d6", 1, 16),
- FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
- FACTOR(CLK_TOP_UNIVPLL_192M, "univpll_192m", "univpll", 1, 13),
- FACTOR(CLK_TOP_UNIVPLL_192M_D4, "univpll_192m_d4", "univpll_192m", 1, 4),
- FACTOR(CLK_TOP_UNIVPLL_192M_D8, "univpll_192m_d8", "univpll_192m", 1, 8),
- FACTOR(CLK_TOP_UNIVPLL_192M_D16, "univpll_192m_d16", "univpll_192m", 1, 16),
- FACTOR(CLK_TOP_UNIVPLL_192M_D32, "univpll_192m_d32", "univpll_192m", 1, 32),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D3, "mainpll_d3", "mainpll", 1, 3, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D4, "mainpll_d4", "mainpll", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D4_D2, "mainpll_d4_d2", "mainpll_d4", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D4_D4, "mainpll_d4_d4", "mainpll_d4", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D4_D8, "mainpll_d4_d8", "mainpll_d4", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D5, "mainpll_d5", "mainpll", 1, 5, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D5_D2, "mainpll_d5_d2", "mainpll_d5", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D5_D4, "mainpll_d5_d4", "mainpll_d5", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D5_D8, "mainpll_d5_d8", "mainpll_d5", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D6, "mainpll_d6", "mainpll", 1, 6, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D6_D2, "mainpll_d6_d2", "mainpll_d6", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D6_D4, "mainpll_d6_d4", "mainpll_d6", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D6_D8, "mainpll_d6_d8", "mainpll_d6", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D7, "mainpll_d7", "mainpll", 1, 7, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D7_D2, "mainpll_d7_d2", "mainpll_d7", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D7_D4, "mainpll_d7_d4", "mainpll_d7", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D7_D8, "mainpll_d7_d8", "mainpll_d7", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_MAINPLL_D9, "mainpll_d9", "mainpll", 1, 9, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D4, "univpll_d4", "univpll", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D4_D2, "univpll_d4_d2", "univpll_d4", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D4_D4, "univpll_d4_d4", "univpll_d4", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D4_D8, "univpll_d4_d8", "univpll_d4", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D5_D2, "univpll_d5_d2", "univpll_d5", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D5_D4, "univpll_d5_d4", "univpll_d5", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D5_D8, "univpll_d5_d8", "univpll_d5", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D6, "univpll_d6", "univpll", 1, 6, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D6_D2, "univpll_d6_d2", "univpll_d6", 1, 2, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D6_D4, "univpll_d6_d4", "univpll_d6", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D6_D8, "univpll_d6_d8", "univpll_d6", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D6_D16, "univpll_d6_d16", "univpll_d6", 1, 16, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_192M, "univpll_192m", "univpll", 1, 13, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_192M_D4, "univpll_192m_d4", "univpll_192m", 1, 4, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_192M_D8, "univpll_192m_d8", "univpll_192m", 1, 8, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_192M_D16, "univpll_192m_d16", "univpll_192m", 1, 16, 0),
+ FACTOR_FLAGS(CLK_TOP_UNIVPLL_192M_D32, "univpll_192m_d32", "univpll_192m", 1, 32, 0),
FACTOR(CLK_TOP_APLL1_D3, "apll1_d3", "apll1", 1, 3),
FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1", 1, 4),
FACTOR(CLK_TOP_APLL2_D3, "apll2_d3", "apll2", 1, 3),
diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c
index d31f01d0ba1c..3c1ac8d3010f 100644
--- a/drivers/clk/mediatek/clk-mtk.c
+++ b/drivers/clk/mediatek/clk-mtk.c
@@ -149,7 +149,7 @@ int mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num,
}
hw = clk_hw_register_fixed_factor(NULL, ff->name, ff->parent_name,
- CLK_SET_RATE_PARENT, ff->mult, ff->div);
+ ff->flags, ff->mult, ff->div);
if (IS_ERR(hw)) {
pr_err("Failed to register clk %s: %pe\n", ff->name,
diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h
index 63ae7941aa92..f2db6b57d5b5 100644
--- a/drivers/clk/mediatek/clk-mtk.h
+++ b/drivers/clk/mediatek/clk-mtk.h
@@ -47,16 +47,21 @@ struct mtk_fixed_factor {
const char *parent_name;
int mult;
int div;
+ unsigned long flags;
};
-#define FACTOR(_id, _name, _parent, _mult, _div) { \
+#define FACTOR_FLAGS(_id, _name, _parent, _mult, _div, _fl) { \
.id = _id, \
.name = _name, \
.parent_name = _parent, \
.mult = _mult, \
.div = _div, \
+ .flags = _fl, \
}
+#define FACTOR(_id, _name, _parent, _mult, _div) \
+ FACTOR_FLAGS(_id, _name, _parent, _mult, _div, CLK_SET_RATE_PARENT)
+
int mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num,
struct clk_hw_onecell_data *clk_data);
void mtk_clk_unregister_factors(const struct mtk_fixed_factor *clks, int num,
diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c
index 54e6cfd29dfc..a4eca5fd539c 100644
--- a/drivers/clk/mediatek/clk-pll.c
+++ b/drivers/clk/mediatek/clk-pll.c
@@ -27,37 +27,10 @@
#define AUDPLL_TUNER_EN BIT(31)
-#define POSTDIV_MASK 0x7
-
/* default 7 bits integer, can be overridden with pcwibits. */
#define INTEGER_BITS 7
-/*
- * MediaTek PLLs are configured through their pcw value. The pcw value describes
- * a divider in the PLL feedback loop which consists of 7 bits for the integer
- * part and the remaining bits (if present) for the fractional part. Also they
- * have a 3 bit power-of-two post divider.
- */
-
-struct mtk_clk_pll {
- struct clk_hw hw;
- void __iomem *base_addr;
- void __iomem *pd_addr;
- void __iomem *pwr_addr;
- void __iomem *tuner_addr;
- void __iomem *tuner_en_addr;
- void __iomem *pcw_addr;
- void __iomem *pcw_chg_addr;
- void __iomem *en_addr;
- const struct mtk_pll_data *data;
-};
-
-static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw)
-{
- return container_of(hw, struct mtk_clk_pll, hw);
-}
-
-static int mtk_pll_is_prepared(struct clk_hw *hw)
+int mtk_pll_is_prepared(struct clk_hw *hw)
{
struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
@@ -161,8 +134,8 @@ static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw,
* @fin: The input frequency
*
*/
-static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
- u32 freq, u32 fin)
+void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
+ u32 freq, u32 fin)
{
unsigned long fmin = pll->data->fmin ? pll->data->fmin : (1000 * MHZ);
const struct mtk_pll_div_table *div_table = pll->data->div_table;
@@ -198,8 +171,8 @@ static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
*pcw = (u32)_pcw;
}
-static int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
+int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
{
struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
u32 pcw = 0;
@@ -211,8 +184,7 @@ static int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}
-static unsigned long mtk_pll_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
+unsigned long mtk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
u32 postdiv;
@@ -227,8 +199,8 @@ static unsigned long mtk_pll_recalc_rate(struct clk_hw *hw,
return __mtk_pll_recalc_rate(pll, parent_rate, pcw, postdiv);
}
-static long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *prate)
+long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
{
struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
u32 pcw = 0;
@@ -239,7 +211,7 @@ static long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
return __mtk_pll_recalc_rate(pll, *prate, pcw, postdiv);
}
-static int mtk_pll_prepare(struct clk_hw *hw)
+int mtk_pll_prepare(struct clk_hw *hw)
{
struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
u32 r;
@@ -273,7 +245,7 @@ static int mtk_pll_prepare(struct clk_hw *hw)
return 0;
}
-static void mtk_pll_unprepare(struct clk_hw *hw)
+void mtk_pll_unprepare(struct clk_hw *hw)
{
struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
u32 r;
@@ -301,7 +273,7 @@ static void mtk_pll_unprepare(struct clk_hw *hw)
writel(r, pll->pwr_addr);
}
-static const struct clk_ops mtk_pll_ops = {
+const struct clk_ops mtk_pll_ops = {
.is_prepared = mtk_pll_is_prepared,
.prepare = mtk_pll_prepare,
.unprepare = mtk_pll_unprepare,
@@ -310,18 +282,15 @@ static const struct clk_ops mtk_pll_ops = {
.set_rate = mtk_pll_set_rate,
};
-static struct clk_hw *mtk_clk_register_pll(const struct mtk_pll_data *data,
- void __iomem *base)
+struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll,
+ const struct mtk_pll_data *data,
+ void __iomem *base,
+ const struct clk_ops *pll_ops)
{
- struct mtk_clk_pll *pll;
struct clk_init_data init = {};
int ret;
const char *parent_name = "clk26m";
- pll = kzalloc(sizeof(*pll), GFP_KERNEL);
- if (!pll)
- return ERR_PTR(-ENOMEM);
-
pll->base_addr = base + data->reg;
pll->pwr_addr = base + data->pwr_reg;
pll->pd_addr = base + data->pd_reg;
@@ -343,7 +312,7 @@ static struct clk_hw *mtk_clk_register_pll(const struct mtk_pll_data *data,
init.name = data->name;
init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0;
- init.ops = &mtk_pll_ops;
+ init.ops = pll_ops;
if (data->parent_name)
init.parent_names = &data->parent_name;
else
@@ -360,7 +329,22 @@ static struct clk_hw *mtk_clk_register_pll(const struct mtk_pll_data *data,
return &pll->hw;
}
-static void mtk_clk_unregister_pll(struct clk_hw *hw)
+struct clk_hw *mtk_clk_register_pll(const struct mtk_pll_data *data,
+ void __iomem *base)
+{
+ struct mtk_clk_pll *pll;
+ struct clk_hw *hw;
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll)
+ return ERR_PTR(-ENOMEM);
+
+ hw = mtk_clk_register_pll_ops(pll, data, base, &mtk_pll_ops);
+
+ return hw;
+}
+
+void mtk_clk_unregister_pll(struct clk_hw *hw)
{
struct mtk_clk_pll *pll;
@@ -423,8 +407,8 @@ err:
}
EXPORT_SYMBOL_GPL(mtk_clk_register_plls);
-static __iomem void *mtk_clk_pll_get_base(struct clk_hw *hw,
- const struct mtk_pll_data *data)
+__iomem void *mtk_clk_pll_get_base(struct clk_hw *hw,
+ const struct mtk_pll_data *data)
{
struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
diff --git a/drivers/clk/mediatek/clk-pll.h b/drivers/clk/mediatek/clk-pll.h
index fe3199715688..f17278ff15d7 100644
--- a/drivers/clk/mediatek/clk-pll.h
+++ b/drivers/clk/mediatek/clk-pll.h
@@ -7,6 +7,7 @@
#ifndef __DRV_CLK_MTK_PLL_H
#define __DRV_CLK_MTK_PLL_H
+#include <linux/clk-provider.h>
#include <linux/types.h>
struct clk_ops;
@@ -20,6 +21,7 @@ struct mtk_pll_div_table {
#define HAVE_RST_BAR BIT(0)
#define PLL_AO BIT(1)
+#define POSTDIV_MASK GENMASK(2, 0)
struct mtk_pll_data {
int id;
@@ -48,10 +50,63 @@ struct mtk_pll_data {
u8 pll_en_bit; /* Assume 0, indicates BIT(0) by default */
};
+/*
+ * MediaTek PLLs are configured through their pcw value. The pcw value describes
+ * a divider in the PLL feedback loop which consists of 7 bits for the integer
+ * part and the remaining bits (if present) for the fractional part. Also they
+ * have a 3 bit power-of-two post divider.
+ */
+
+struct mtk_clk_pll {
+ struct clk_hw hw;
+ void __iomem *base_addr;
+ void __iomem *pd_addr;
+ void __iomem *pwr_addr;
+ void __iomem *tuner_addr;
+ void __iomem *tuner_en_addr;
+ void __iomem *pcw_addr;
+ void __iomem *pcw_chg_addr;
+ void __iomem *en_addr;
+ const struct mtk_pll_data *data;
+};
+
int mtk_clk_register_plls(struct device_node *node,
const struct mtk_pll_data *plls, int num_plls,
struct clk_hw_onecell_data *clk_data);
void mtk_clk_unregister_plls(const struct mtk_pll_data *plls, int num_plls,
struct clk_hw_onecell_data *clk_data);
+extern const struct clk_ops mtk_pll_ops;
+
+static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw)
+{
+ return container_of(hw, struct mtk_clk_pll, hw);
+}
+
+int mtk_pll_is_prepared(struct clk_hw *hw);
+
+int mtk_pll_prepare(struct clk_hw *hw);
+
+void mtk_pll_unprepare(struct clk_hw *hw);
+
+unsigned long mtk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate);
+
+void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv,
+ u32 freq, u32 fin);
+int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate);
+long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate);
+
+struct clk_hw *mtk_clk_register_pll_ops(struct mtk_clk_pll *pll,
+ const struct mtk_pll_data *data,
+ void __iomem *base,
+ const struct clk_ops *pll_ops);
+struct clk_hw *mtk_clk_register_pll(const struct mtk_pll_data *data,
+ void __iomem *base);
+void mtk_clk_unregister_pll(struct clk_hw *hw);
+
+__iomem void *mtk_clk_pll_get_base(struct clk_hw *hw,
+ const struct mtk_pll_data *data);
+
#endif /* __DRV_CLK_MTK_PLL_H */
diff --git a/drivers/clk/mediatek/clk-pllfh.c b/drivers/clk/mediatek/clk-pllfh.c
new file mode 100644
index 000000000000..f48780bec507
--- /dev/null
+++ b/drivers/clk/mediatek/clk-pllfh.c
@@ -0,0 +1,275 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Edward-JW Yang <edward-jw.yang@mediatek.com>
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/clkdev.h>
+#include <linux/delay.h>
+
+#include "clk-mtk.h"
+#include "clk-pllfh.h"
+#include "clk-fhctl.h"
+
+static DEFINE_SPINLOCK(pllfh_lock);
+
+inline struct mtk_fh *to_mtk_fh(struct clk_hw *hw)
+{
+ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+
+ return container_of(pll, struct mtk_fh, clk_pll);
+}
+
+static int mtk_fhctl_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct mtk_clk_pll *pll = to_mtk_clk_pll(hw);
+ struct mtk_fh *fh = to_mtk_fh(hw);
+ u32 pcw = 0;
+ u32 postdiv;
+
+ mtk_pll_calc_values(pll, &pcw, &postdiv, rate, parent_rate);
+
+ return fh->ops->hopping(fh, pcw, postdiv);
+}
+
+static const struct clk_ops mtk_pllfh_ops = {
+ .is_prepared = mtk_pll_is_prepared,
+ .prepare = mtk_pll_prepare,
+ .unprepare = mtk_pll_unprepare,
+ .recalc_rate = mtk_pll_recalc_rate,
+ .round_rate = mtk_pll_round_rate,
+ .set_rate = mtk_fhctl_set_rate,
+};
+
+static struct mtk_pllfh_data *get_pllfh_by_id(struct mtk_pllfh_data *pllfhs,
+ int num_fhs, int pll_id)
+{
+ int i;
+
+ for (i = 0; i < num_fhs; i++)
+ if (pllfhs[i].data.pll_id == pll_id)
+ return &pllfhs[i];
+
+ return NULL;
+}
+
+void fhctl_parse_dt(const u8 *compatible_node, struct mtk_pllfh_data *pllfhs,
+ int num_fhs)
+{
+ void __iomem *base;
+ struct device_node *node;
+ u32 num_clocks, pll_id, ssc_rate;
+ int offset, i;
+
+ node = of_find_compatible_node(NULL, NULL, compatible_node);
+ if (!node) {
+ pr_err("cannot find \"%s\"\n", compatible_node);
+ return;
+ }
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s(): ioremap failed\n", __func__);
+ return;
+ }
+
+ num_clocks = of_clk_get_parent_count(node);
+ if (!num_clocks) {
+ pr_err("%s(): failed to get clocks property\n", __func__);
+ return;
+ }
+
+ for (i = 0; i < num_clocks; i++) {
+ struct mtk_pllfh_data *pllfh;
+
+ offset = i * 2;
+
+ of_property_read_u32_index(node, "clocks", offset + 1, &pll_id);
+ of_property_read_u32_index(node,
+ "mediatek,hopping-ssc-percent",
+ i, &ssc_rate);
+
+ pllfh = get_pllfh_by_id(pllfhs, num_fhs, pll_id);
+ if (!pllfh)
+ continue;
+
+ pllfh->state.fh_enable = 1;
+ pllfh->state.ssc_rate = ssc_rate;
+ pllfh->state.base = base;
+ }
+}
+
+static void pllfh_init(struct mtk_fh *fh, struct mtk_pllfh_data *pllfh_data)
+{
+ struct fh_pll_regs *regs = &fh->regs;
+ const struct fhctl_offset *offset;
+ void __iomem *base = pllfh_data->state.base;
+ void __iomem *fhx_base = base + pllfh_data->data.fhx_offset;
+
+ offset = fhctl_get_offset_table();
+
+ regs->reg_hp_en = base + offset->offset_hp_en;
+ regs->reg_clk_con = base + offset->offset_clk_con;
+ regs->reg_rst_con = base + offset->offset_rst_con;
+ regs->reg_slope0 = base + offset->offset_slope0;
+ regs->reg_slope1 = base + offset->offset_slope1;
+
+ regs->reg_cfg = fhx_base + offset->offset_cfg;
+ regs->reg_updnlmt = fhx_base + offset->offset_updnlmt;
+ regs->reg_dds = fhx_base + offset->offset_dds;
+ regs->reg_dvfs = fhx_base + offset->offset_dvfs;
+ regs->reg_mon = fhx_base + offset->offset_mon;
+
+ fh->pllfh_data = pllfh_data;
+ fh->lock = &pllfh_lock;
+
+ fh->ops = fhctl_get_ops();
+}
+
+static bool fhctl_is_supported_and_enabled(const struct mtk_pllfh_data *pllfh)
+{
+ return pllfh && (pllfh->state.fh_enable == 1);
+}
+
+static struct clk_hw *
+mtk_clk_register_pllfh(const struct mtk_pll_data *pll_data,
+ struct mtk_pllfh_data *pllfh_data, void __iomem *base)
+{
+ struct clk_hw *hw;
+ struct mtk_fh *fh;
+
+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+ if (!fh)
+ return ERR_PTR(-ENOMEM);
+
+ pllfh_init(fh, pllfh_data);
+
+ hw = mtk_clk_register_pll_ops(&fh->clk_pll, pll_data, base,
+ &mtk_pllfh_ops);
+
+ if (IS_ERR(hw))
+ kfree(fh);
+ else
+ fhctl_hw_init(fh);
+
+ return hw;
+}
+
+static void mtk_clk_unregister_pllfh(struct clk_hw *hw)
+{
+ struct mtk_fh *fh;
+
+ if (!hw)
+ return;
+
+ fh = to_mtk_fh(hw);
+
+ clk_hw_unregister(hw);
+ kfree(fh);
+}
+
+int mtk_clk_register_pllfhs(struct device_node *node,
+ const struct mtk_pll_data *plls, int num_plls,
+ struct mtk_pllfh_data *pllfhs, int num_fhs,
+ struct clk_hw_onecell_data *clk_data)
+{
+ void __iomem *base;
+ int i;
+ struct clk_hw *hw;
+
+ base = of_iomap(node, 0);
+ if (!base) {
+ pr_err("%s(): ioremap failed\n", __func__);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < num_plls; i++) {
+ const struct mtk_pll_data *pll = &plls[i];
+ struct mtk_pllfh_data *pllfh;
+ bool use_fhctl;
+
+ pllfh = get_pllfh_by_id(pllfhs, num_fhs, pll->id);
+ use_fhctl = fhctl_is_supported_and_enabled(pllfh);
+
+ if (use_fhctl)
+ hw = mtk_clk_register_pllfh(pll, pllfh, base);
+ else
+ hw = mtk_clk_register_pll(pll, base);
+
+ if (IS_ERR(hw)) {
+ pr_err("Failed to register %s clk %s: %ld\n",
+ use_fhctl ? "fhpll" : "pll", pll->name,
+ PTR_ERR(hw));
+ goto err;
+ }
+
+ clk_data->hws[pll->id] = hw;
+ }
+
+ return 0;
+
+err:
+ while (--i >= 0) {
+ const struct mtk_pll_data *pll = &plls[i];
+ struct mtk_pllfh_data *pllfh;
+ bool use_fhctl;
+
+ pllfh = get_pllfh_by_id(pllfhs, num_fhs, pll->id);
+ use_fhctl = fhctl_is_supported_and_enabled(pllfh);
+
+ if (use_fhctl)
+ mtk_clk_unregister_pllfh(clk_data->hws[pll->id]);
+ else
+ mtk_clk_unregister_pll(clk_data->hws[pll->id]);
+
+ clk_data->hws[pll->id] = ERR_PTR(-ENOENT);
+ }
+
+ iounmap(base);
+
+ return PTR_ERR(hw);
+}
+
+void mtk_clk_unregister_pllfhs(const struct mtk_pll_data *plls, int num_plls,
+ struct mtk_pllfh_data *pllfhs, int num_fhs,
+ struct clk_hw_onecell_data *clk_data)
+{
+ void __iomem *base = NULL, *fhctl_base = NULL;
+ int i;
+
+ if (!clk_data)
+ return;
+
+ for (i = num_plls; i > 0; i--) {
+ const struct mtk_pll_data *pll = &plls[i - 1];
+ struct mtk_pllfh_data *pllfh;
+ bool use_fhctl;
+
+ if (IS_ERR_OR_NULL(clk_data->hws[pll->id]))
+ continue;
+
+ pllfh = get_pllfh_by_id(pllfhs, num_fhs, pll->id);
+ use_fhctl = fhctl_is_supported_and_enabled(pllfh);
+
+ if (use_fhctl) {
+ fhctl_base = pllfh->state.base;
+ mtk_clk_unregister_pllfh(clk_data->hws[pll->id]);
+ } else {
+ base = mtk_clk_pll_get_base(clk_data->hws[pll->id],
+ pll);
+ mtk_clk_unregister_pll(clk_data->hws[pll->id]);
+ }
+
+ clk_data->hws[pll->id] = ERR_PTR(-ENOENT);
+ }
+
+ if (fhctl_base)
+ iounmap(fhctl_base);
+
+ iounmap(base);
+}
diff --git a/drivers/clk/mediatek/clk-pllfh.h b/drivers/clk/mediatek/clk-pllfh.h
new file mode 100644
index 000000000000..c0a6e1537034
--- /dev/null
+++ b/drivers/clk/mediatek/clk-pllfh.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ * Author: Edward-JW Yang <edward-jw.yang@mediatek.com>
+ */
+
+#ifndef __CLK_PLLFH_H
+#define __CLK_PLLFH_H
+
+#include "clk-pll.h"
+
+struct fh_pll_state {
+ void __iomem *base;
+ u32 fh_enable;
+ u32 ssc_rate;
+};
+
+struct fh_pll_data {
+ int pll_id;
+ int fh_id;
+ u32 fhx_offset;
+ u32 dds_mask;
+ u32 slope0_value;
+ u32 slope1_value;
+ u32 sfstrx_en;
+ u32 frddsx_en;
+ u32 fhctlx_en;
+ u32 tgl_org;
+ u32 dvfs_tri;
+ u32 pcwchg;
+ u32 dt_val;
+ u32 df_val;
+ u32 updnlmt_shft;
+ u32 msk_frddsx_dys;
+ u32 msk_frddsx_dts;
+};
+
+struct mtk_pllfh_data {
+ struct fh_pll_state state;
+ const struct fh_pll_data data;
+};
+
+struct fh_pll_regs {
+ void __iomem *reg_hp_en;
+ void __iomem *reg_clk_con;
+ void __iomem *reg_rst_con;
+ void __iomem *reg_slope0;
+ void __iomem *reg_slope1;
+ void __iomem *reg_cfg;
+ void __iomem *reg_updnlmt;
+ void __iomem *reg_dds;
+ void __iomem *reg_dvfs;
+ void __iomem *reg_mon;
+};
+
+struct mtk_fh {
+ struct mtk_clk_pll clk_pll;
+ struct fh_pll_regs regs;
+ struct mtk_pllfh_data *pllfh_data;
+ const struct fh_operation *ops;
+ spinlock_t *lock;
+};
+
+struct fh_operation {
+ int (*hopping)(struct mtk_fh *fh, unsigned int new_dds,
+ unsigned int postdiv);
+ int (*ssc_enable)(struct mtk_fh *fh, u32 rate);
+};
+
+int mtk_clk_register_pllfhs(struct device_node *node,
+ const struct mtk_pll_data *plls, int num_plls,
+ struct mtk_pllfh_data *pllfhs, int num_pllfhs,
+ struct clk_hw_onecell_data *clk_data);
+
+void mtk_clk_unregister_pllfhs(const struct mtk_pll_data *plls, int num_plls,
+ struct mtk_pllfh_data *pllfhs, int num_fhs,
+ struct clk_hw_onecell_data *clk_data);
+
+void fhctl_parse_dt(const u8 *compatible_node, struct mtk_pllfh_data *pllfhs,
+ int num_pllfhs);
+
+#endif /* __CLK_PLLFH_H */
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index 9e55617bc3b4..afefeba6e458 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -32,7 +32,6 @@
#include <linux/io.h>
#include <linux/math64.h>
#include <linux/module.h>
-#include <linux/rational.h>
#include "clk-regmap.h"
#include "clk-pll.h"
@@ -277,15 +276,15 @@ static int meson_clk_pll_wait_lock(struct clk_hw *hw)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
- int delay = 24000000;
+ int delay = 5000;
do {
- /* Is the clock locked now ? */
+ /* Is the clock locked now ? Time out after 100ms. */
if (meson_parm_read(clk->map, &pll->l))
return 0;
- delay--;
- } while (delay > 0);
+ udelay(20);
+ } while (--delay);
return -ETIMEDOUT;
}
@@ -320,12 +319,16 @@ static int meson_clk_pll_is_enabled(struct clk_hw *hw)
static int meson_clk_pcie_pll_enable(struct clk_hw *hw)
{
- meson_clk_pll_init(hw);
+ int retries = 10;
- if (meson_clk_pll_wait_lock(hw))
- return -EIO;
+ do {
+ meson_clk_pll_init(hw);
+ if (!meson_clk_pll_wait_lock(hw))
+ return 0;
+ pr_info("Retry enabling PCIe PLL clock\n");
+ } while (--retries);
- return 0;
+ return -EIO;
}
static int meson_clk_pll_enable(struct clk_hw *hw)
diff --git a/drivers/clk/microchip/Kconfig b/drivers/clk/microchip/Kconfig
index b46e864b3bd8..e33e51978938 100644
--- a/drivers/clk/microchip/Kconfig
+++ b/drivers/clk/microchip/Kconfig
@@ -5,7 +5,8 @@ config COMMON_CLK_PIC32
config MCHP_CLK_MPFS
bool "Clk driver for PolarFire SoC"
- depends on (RISCV && SOC_MICROCHIP_POLARFIRE) || COMPILE_TEST
+ depends on SOC_MICROCHIP_POLARFIRE || COMPILE_TEST
+ default SOC_MICROCHIP_POLARFIRE
select AUXILIARY_BUS
help
Supports Clock Configuration for PolarFire SoC
diff --git a/drivers/clk/microchip/clk-mpfs-ccc.c b/drivers/clk/microchip/clk-mpfs-ccc.c
index 7be028dced63..32aae880a14f 100644
--- a/drivers/clk/microchip/clk-mpfs-ccc.c
+++ b/drivers/clk/microchip/clk-mpfs-ccc.c
@@ -166,6 +166,9 @@ static int mpfs_ccc_register_outputs(struct device *dev, struct mpfs_ccc_out_hw_
struct mpfs_ccc_out_hw_clock *out_hw = &out_hws[i];
char *name = devm_kzalloc(dev, 23, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+
snprintf(name, 23, "%s_out%u", parent->name, i);
out_hw->divider.hw.init = CLK_HW_INIT_HW(name, &parent->hw, &clk_divider_ops, 0);
out_hw->divider.reg = data->pll_base[i / MPFS_CCC_OUTPUTS_PER_PLL] +
@@ -200,6 +203,9 @@ static int mpfs_ccc_register_plls(struct device *dev, struct mpfs_ccc_pll_hw_clo
struct mpfs_ccc_pll_hw_clock *pll_hw = &pll_hws[i];
char *name = devm_kzalloc(dev, 18, GFP_KERNEL);
+ if (!name)
+ return -ENOMEM;
+
pll_hw->base = data->pll_base[i];
snprintf(name, 18, "ccc%s_pll%u", strchrnul(dev->of_node->full_name, '@'), i);
pll_hw->name = (const char *)name;
diff --git a/drivers/clk/mstar/Kconfig b/drivers/clk/mstar/Kconfig
index de37e1bce2d2..b9bcb5e02814 100644
--- a/drivers/clk/mstar/Kconfig
+++ b/drivers/clk/mstar/Kconfig
@@ -1,4 +1,11 @@
# SPDX-License-Identifier: GPL-2.0-only
+config MSTAR_MSC313_CPUPLL
+ bool "MStar CPUPLL driver"
+ depends on ARCH_MSTARV7 || COMPILE_TEST
+ default ARCH_MSTARV7
+ help
+ Support for the CPU PLL present on MStar/Sigmastar SoCs.
+
config MSTAR_MSC313_MPLL
bool "MStar MPLL driver"
depends on ARCH_MSTARV7 || COMPILE_TEST
diff --git a/drivers/clk/mstar/Makefile b/drivers/clk/mstar/Makefile
index f8dcd25ede1d..17d97eedcd36 100644
--- a/drivers/clk/mstar/Makefile
+++ b/drivers/clk/mstar/Makefile
@@ -3,4 +3,5 @@
# Makefile for mstar specific clk
#
+obj-$(CONFIG_MSTAR_MSC313_CPUPLL) += clk-msc313-cpupll.o
obj-$(CONFIG_MSTAR_MSC313_MPLL) += clk-msc313-mpll.o
diff --git a/drivers/clk/mstar/clk-msc313-cpupll.c b/drivers/clk/mstar/clk-msc313-cpupll.c
new file mode 100644
index 000000000000..a93e2dba09d3
--- /dev/null
+++ b/drivers/clk/mstar/clk-msc313-cpupll.c
@@ -0,0 +1,220 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 Daniel Palmer <daniel@thingy.jp>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+/*
+ * This IP is not documented outside of the messy vendor driver.
+ * Below is what we think the registers look like based on looking at
+ * the vendor code and poking at the hardware:
+ *
+ * 0x140 -- LPF low. Seems to store one half of the clock transition
+ * 0x144 /
+ * 0x148 -- LPF high. Seems to store one half of the clock transition
+ * 0x14c /
+ * 0x150 -- vendor code says "toggle lpf enable"
+ * 0x154 -- mu?
+ * 0x15c -- lpf_update_count?
+ * 0x160 -- vendor code says "switch to LPF". Clock source config? Register bank?
+ * 0x164 -- vendor code says "from low to high" which seems to mean transition from LPF low to
+ * LPF high.
+ * 0x174 -- Seems to be the PLL lock status bit
+ * 0x180 -- Seems to be the current frequency, this might need to be populated by software?
+ * 0x184 / The vendor driver uses these to set the initial value of LPF low
+ *
+ * Frequency seems to be calculated like this:
+ * (parent clock (432mhz) / register_magic_value) * 16 * 524288
+ * Only the lower 24 bits of the resulting value will be used. In addition, the
+ * PLL doesn't seem to be able to lock on frequencies lower than 220 MHz, as
+ * divisor 0xfb586f (220 MHz) works but 0xfb7fff locks up.
+ *
+ * Vendor values:
+ * frequency - register value
+ *
+ * 400000000 - 0x0067AE14
+ * 600000000 - 0x00451EB8,
+ * 800000000 - 0x0033D70A,
+ * 1000000000 - 0x002978d4,
+ */
+
+#define REG_LPF_LOW_L 0x140
+#define REG_LPF_LOW_H 0x144
+#define REG_LPF_HIGH_BOTTOM 0x148
+#define REG_LPF_HIGH_TOP 0x14c
+#define REG_LPF_TOGGLE 0x150
+#define REG_LPF_MYSTERYTWO 0x154
+#define REG_LPF_UPDATE_COUNT 0x15c
+#define REG_LPF_MYSTERYONE 0x160
+#define REG_LPF_TRANSITIONCTRL 0x164
+#define REG_LPF_LOCK 0x174
+#define REG_CURRENT 0x180
+
+#define LPF_LOCK_TIMEOUT 100000000
+
+#define MULTIPLIER_1 16
+#define MULTIPLIER_2 524288
+#define MULTIPLIER (MULTIPLIER_1 * MULTIPLIER_2)
+
+struct msc313_cpupll {
+ void __iomem *base;
+ struct clk_hw clk_hw;
+};
+
+#define to_cpupll(_hw) container_of(_hw, struct msc313_cpupll, clk_hw)
+
+static u32 msc313_cpupll_reg_read32(struct msc313_cpupll *cpupll, unsigned int reg)
+{
+ u32 value;
+
+ value = ioread16(cpupll->base + reg + 4) << 16;
+ value |= ioread16(cpupll->base + reg);
+
+ return value;
+}
+
+static void msc313_cpupll_reg_write32(struct msc313_cpupll *cpupll, unsigned int reg, u32 value)
+{
+ u16 l = value & 0xffff, h = (value >> 16) & 0xffff;
+
+ iowrite16(l, cpupll->base + reg);
+ iowrite16(h, cpupll->base + reg + 4);
+}
+
+static void msc313_cpupll_setfreq(struct msc313_cpupll *cpupll, u32 regvalue)
+{
+ ktime_t timeout;
+
+ msc313_cpupll_reg_write32(cpupll, REG_LPF_HIGH_BOTTOM, regvalue);
+
+ iowrite16(0x1, cpupll->base + REG_LPF_MYSTERYONE);
+ iowrite16(0x6, cpupll->base + REG_LPF_MYSTERYTWO);
+ iowrite16(0x8, cpupll->base + REG_LPF_UPDATE_COUNT);
+ iowrite16(BIT(12), cpupll->base + REG_LPF_TRANSITIONCTRL);
+
+ iowrite16(0, cpupll->base + REG_LPF_TOGGLE);
+ iowrite16(1, cpupll->base + REG_LPF_TOGGLE);
+
+ timeout = ktime_add_ns(ktime_get(), LPF_LOCK_TIMEOUT);
+ while (!(ioread16(cpupll->base + REG_LPF_LOCK))) {
+ if (ktime_after(ktime_get(), timeout)) {
+ pr_err("timeout waiting for LPF_LOCK\n");
+ return;
+ }
+ cpu_relax();
+ }
+
+ iowrite16(0, cpupll->base + REG_LPF_TOGGLE);
+
+ msc313_cpupll_reg_write32(cpupll, REG_LPF_LOW_L, regvalue);
+}
+
+static unsigned long msc313_cpupll_frequencyforreg(u32 reg, unsigned long parent_rate)
+{
+ unsigned long long prescaled = ((unsigned long long)parent_rate) * MULTIPLIER;
+
+ if (prescaled == 0 || reg == 0)
+ return 0;
+ return DIV_ROUND_DOWN_ULL(prescaled, reg);
+}
+
+static u32 msc313_cpupll_regforfrequecy(unsigned long rate, unsigned long parent_rate)
+{
+ unsigned long long prescaled = ((unsigned long long)parent_rate) * MULTIPLIER;
+
+ if (prescaled == 0 || rate == 0)
+ return 0;
+ return DIV_ROUND_UP_ULL(prescaled, rate);
+}
+
+static unsigned long msc313_cpupll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+ struct msc313_cpupll *cpupll = to_cpupll(hw);
+
+ return msc313_cpupll_frequencyforreg(msc313_cpupll_reg_read32(cpupll, REG_LPF_LOW_L),
+ parent_rate);
+}
+
+static long msc313_cpupll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *parent_rate)
+{
+ u32 reg = msc313_cpupll_regforfrequecy(rate, *parent_rate);
+ long rounded = msc313_cpupll_frequencyforreg(reg, *parent_rate);
+
+ /*
+ * This is my poor attempt at making sure the resulting
+ * rate doesn't overshoot the requested rate.
+ */
+ for (; rounded >= rate && reg > 0; reg--)
+ rounded = msc313_cpupll_frequencyforreg(reg, *parent_rate);
+
+ return rounded;
+}
+
+static int msc313_cpupll_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate)
+{
+ struct msc313_cpupll *cpupll = to_cpupll(hw);
+ u32 reg = msc313_cpupll_regforfrequecy(rate, parent_rate);
+
+ msc313_cpupll_setfreq(cpupll, reg);
+
+ return 0;
+}
+
+static const struct clk_ops msc313_cpupll_ops = {
+ .recalc_rate = msc313_cpupll_recalc_rate,
+ .round_rate = msc313_cpupll_round_rate,
+ .set_rate = msc313_cpupll_set_rate,
+};
+
+static const struct of_device_id msc313_cpupll_of_match[] = {
+ { .compatible = "mstar,msc313-cpupll" },
+ {}
+};
+
+static int msc313_cpupll_probe(struct platform_device *pdev)
+{
+ struct clk_init_data clk_init = {};
+ struct clk_parent_data cpupll_parent = { .index = 0 };
+ struct device *dev = &pdev->dev;
+ struct msc313_cpupll *cpupll;
+ int ret;
+
+ cpupll = devm_kzalloc(&pdev->dev, sizeof(*cpupll), GFP_KERNEL);
+ if (!cpupll)
+ return -ENOMEM;
+
+ cpupll->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(cpupll->base))
+ return PTR_ERR(cpupll->base);
+
+ /* LPF might not contain the current frequency so fix that up */
+ msc313_cpupll_reg_write32(cpupll, REG_LPF_LOW_L,
+ msc313_cpupll_reg_read32(cpupll, REG_CURRENT));
+
+ clk_init.name = dev_name(dev);
+ clk_init.ops = &msc313_cpupll_ops;
+ clk_init.parent_data = &cpupll_parent;
+ clk_init.num_parents = 1;
+ cpupll->clk_hw.init = &clk_init;
+
+ ret = devm_clk_hw_register(dev, &cpupll->clk_hw);
+ if (ret)
+ return ret;
+
+ return devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_simple_get, &cpupll->clk_hw);
+}
+
+static struct platform_driver msc313_cpupll_driver = {
+ .driver = {
+ .name = "mstar-msc313-cpupll",
+ .of_match_table = msc313_cpupll_of_match,
+ },
+ .probe = msc313_cpupll_probe,
+};
+builtin_platform_driver(msc313_cpupll_driver);
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 76e6dee450d5..70d43f0a8919 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -401,6 +401,15 @@ config SC_DISPCC_7280
Say Y if you want to support display devices and functionality such as
splash screen.
+config SC_DISPCC_8280XP
+ tristate "SC8280XP Display Clock Controller"
+ select SC_GCC_8280XP
+ help
+ Support for the two display clock controllers on Qualcomm
+ Technologies, Inc. SC8280XP devices.
+ Say Y if you want to support display devices and functionality such as
+ splash screen.
+
config SC_GCC_7180
tristate "SC7180 Global Clock Controller"
select QCOM_GDSC
@@ -668,6 +677,15 @@ config SM_DISPCC_6350
Say Y if you want to support display devices and functionality such as
splash screen.
+config SM_DISPCC_6375
+ tristate "SM6375 Display Clock Controller"
+ depends on SM_GCC_6375
+ help
+ Support for the display clock controller on Qualcomm Technologies, Inc
+ SM6375 devices.
+ Say Y if you want to support display devices and functionality such as
+ splash screen.
+
config SM_DISPCC_8450
tristate "SM8450 Display Clock Controller"
depends on SM_GCC_8450
@@ -739,6 +757,14 @@ config SM_GCC_8450
Say Y if you want to use peripheral devices such as UART,
SPI, I2C, USB, SD/UFS, PCIe etc.
+config SM_GCC_8550
+ tristate "SM8550 Global Clock Controller"
+ select QCOM_GDSC
+ help
+ Support for the global clock controller on SM8550 devices.
+ Say Y if you want to use peripheral devices such as UART,
+ SPI, I2C, USB, SD/UFS, PCIe etc.
+
config SM_GPUCC_6350
tristate "SM6350 Graphics Clock Controller"
select SM_GCC_6350
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index e6cecf9e0436..f18c446a97ea 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_SC_CAMCC_7180) += camcc-sc7180.o
obj-$(CONFIG_SC_CAMCC_7280) += camcc-sc7280.o
obj-$(CONFIG_SC_DISPCC_7180) += dispcc-sc7180.o
obj-$(CONFIG_SC_DISPCC_7280) += dispcc-sc7280.o
+obj-$(CONFIG_SC_DISPCC_8280XP) += dispcc-sc8280xp.o
obj-$(CONFIG_SC_GCC_7180) += gcc-sc7180.o
obj-$(CONFIG_SC_GCC_7280) += gcc-sc7280.o
obj-$(CONFIG_SC_GCC_8180X) += gcc-sc8180x.o
@@ -95,6 +96,7 @@ obj-$(CONFIG_SM_CAMCC_8450) += camcc-sm8450.o
obj-$(CONFIG_SM_DISPCC_6115) += dispcc-sm6115.o
obj-$(CONFIG_SM_DISPCC_6125) += dispcc-sm6125.o
obj-$(CONFIG_SM_DISPCC_6350) += dispcc-sm6350.o
+obj-$(CONFIG_SM_DISPCC_6375) += dispcc-sm6375.o
obj-$(CONFIG_SM_DISPCC_8250) += dispcc-sm8250.o
obj-$(CONFIG_SM_DISPCC_8450) += dispcc-sm8450.o
obj-$(CONFIG_SM_GCC_6115) += gcc-sm6115.o
@@ -105,6 +107,7 @@ obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o
obj-$(CONFIG_SM_GCC_8250) += gcc-sm8250.o
obj-$(CONFIG_SM_GCC_8350) += gcc-sm8350.o
obj-$(CONFIG_SM_GCC_8450) += gcc-sm8450.o
+obj-$(CONFIG_SM_GCC_8550) += gcc-sm8550.o
obj-$(CONFIG_SM_GPUCC_6350) += gpucc-sm6350.o
obj-$(CONFIG_SM_GPUCC_8150) += gpucc-sm8150.o
obj-$(CONFIG_SM_GPUCC_8250) += gpucc-sm8250.o
diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c
index 1973d79c9465..f9e4cfd7261c 100644
--- a/drivers/clk/qcom/clk-alpha-pll.c
+++ b/drivers/clk/qcom/clk-alpha-pll.c
@@ -155,6 +155,22 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {
[PLL_OFF_TEST_CTL_U] = 0x30,
[PLL_OFF_TEST_CTL_U1] = 0x34,
},
+ [CLK_ALPHA_PLL_TYPE_LUCID_OLE] = {
+ [PLL_OFF_OPMODE] = 0x04,
+ [PLL_OFF_STATE] = 0x08,
+ [PLL_OFF_STATUS] = 0x0c,
+ [PLL_OFF_L_VAL] = 0x10,
+ [PLL_OFF_ALPHA_VAL] = 0x14,
+ [PLL_OFF_USER_CTL] = 0x18,
+ [PLL_OFF_USER_CTL_U] = 0x1c,
+ [PLL_OFF_CONFIG_CTL] = 0x20,
+ [PLL_OFF_CONFIG_CTL_U] = 0x24,
+ [PLL_OFF_CONFIG_CTL_U1] = 0x28,
+ [PLL_OFF_TEST_CTL] = 0x2c,
+ [PLL_OFF_TEST_CTL_U] = 0x30,
+ [PLL_OFF_TEST_CTL_U1] = 0x34,
+ [PLL_OFF_TEST_CTL_U2] = 0x38,
+ },
[CLK_ALPHA_PLL_TYPE_RIVIAN_EVO] = {
[PLL_OFF_OPMODE] = 0x04,
[PLL_OFF_STATUS] = 0x0c,
diff --git a/drivers/clk/qcom/clk-alpha-pll.h b/drivers/clk/qcom/clk-alpha-pll.h
index f9524b3fce6b..2bdae362c827 100644
--- a/drivers/clk/qcom/clk-alpha-pll.h
+++ b/drivers/clk/qcom/clk-alpha-pll.h
@@ -18,6 +18,7 @@ enum {
CLK_ALPHA_PLL_TYPE_AGERA,
CLK_ALPHA_PLL_TYPE_ZONDA,
CLK_ALPHA_PLL_TYPE_LUCID_EVO,
+ CLK_ALPHA_PLL_TYPE_LUCID_OLE,
CLK_ALPHA_PLL_TYPE_RIVIAN_EVO,
CLK_ALPHA_PLL_TYPE_DEFAULT_EVO,
CLK_ALPHA_PLL_TYPE_BRAMMO_EVO,
@@ -38,6 +39,8 @@ enum {
PLL_OFF_TEST_CTL,
PLL_OFF_TEST_CTL_U,
PLL_OFF_TEST_CTL_U1,
+ PLL_OFF_TEST_CTL_U2,
+ PLL_OFF_STATE,
PLL_OFF_STATUS,
PLL_OFF_OPMODE,
PLL_OFF_FRAC,
@@ -160,7 +163,9 @@ extern const struct clk_ops clk_alpha_pll_zonda_ops;
extern const struct clk_ops clk_alpha_pll_lucid_evo_ops;
extern const struct clk_ops clk_alpha_pll_reset_lucid_evo_ops;
extern const struct clk_ops clk_alpha_pll_fixed_lucid_evo_ops;
+#define clk_alpha_pll_fixed_lucid_ole_ops clk_alpha_pll_fixed_lucid_evo_ops
extern const struct clk_ops clk_alpha_pll_postdiv_lucid_evo_ops;
+#define clk_alpha_pll_postdiv_lucid_ole_ops clk_alpha_pll_postdiv_lucid_evo_ops
extern const struct clk_ops clk_alpha_pll_rivian_evo_ops;
#define clk_alpha_pll_postdiv_rivian_evo_ops clk_alpha_pll_postdiv_fabia_ops
diff --git a/drivers/clk/qcom/clk-krait.c b/drivers/clk/qcom/clk-krait.c
index 45da736bd5f4..293a9dfa7151 100644
--- a/drivers/clk/qcom/clk-krait.c
+++ b/drivers/clk/qcom/clk-krait.c
@@ -114,6 +114,8 @@ static int krait_div2_set_rate(struct clk_hw *hw, unsigned long rate,
if (d->lpl)
mask = mask << (d->shift + LPL_SHIFT) | mask << d->shift;
+ else
+ mask <<= d->shift;
spin_lock_irqsave(&krait_clock_reg_lock, flags);
val = krait_get_l2_indirect_reg(d->offset);
diff --git a/drivers/clk/qcom/clk-rpm.c b/drivers/clk/qcom/clk-rpm.c
index 747c473b0b5e..b1be5b664bf3 100644
--- a/drivers/clk/qcom/clk-rpm.c
+++ b/drivers/clk/qcom/clk-rpm.c
@@ -31,51 +31,51 @@ static const struct clk_parent_data gcc_cxo[] = {
{ .fw_name = "cxo", .name = "cxo_board" },
};
-#define DEFINE_CLK_RPM(_platform, _name, _active, r_id) \
- static struct clk_rpm _platform##_##_active; \
- static struct clk_rpm _platform##_##_name = { \
+#define DEFINE_CLK_RPM(_name, r_id) \
+ static struct clk_rpm clk_rpm_##_name##_a_clk; \
+ static struct clk_rpm clk_rpm_##_name##_clk = { \
.rpm_clk_id = (r_id), \
- .peer = &_platform##_##_active, \
+ .peer = &clk_rpm_##_name##_a_clk, \
.rate = INT_MAX, \
.hw.init = &(struct clk_init_data){ \
.ops = &clk_rpm_ops, \
- .name = #_name, \
+ .name = #_name "_clk", \
.parent_data = gcc_pxo, \
.num_parents = ARRAY_SIZE(gcc_pxo), \
}, \
}; \
- static struct clk_rpm _platform##_##_active = { \
+ static struct clk_rpm clk_rpm_##_name##_a_clk = { \
.rpm_clk_id = (r_id), \
- .peer = &_platform##_##_name, \
+ .peer = &clk_rpm_##_name##_clk, \
.active_only = true, \
.rate = INT_MAX, \
.hw.init = &(struct clk_init_data){ \
.ops = &clk_rpm_ops, \
- .name = #_active, \
+ .name = #_name "_a_clk", \
.parent_data = gcc_pxo, \
.num_parents = ARRAY_SIZE(gcc_pxo), \
}, \
}
-#define DEFINE_CLK_RPM_XO_BUFFER(_platform, _name, _active, offset) \
- static struct clk_rpm _platform##_##_name = { \
+#define DEFINE_CLK_RPM_XO_BUFFER(_name, offset) \
+ static struct clk_rpm clk_rpm_##_name##_clk = { \
.rpm_clk_id = QCOM_RPM_CXO_BUFFERS, \
.xo_offset = (offset), \
.hw.init = &(struct clk_init_data){ \
- .ops = &clk_rpm_xo_ops, \
- .name = #_name, \
+ .ops = &clk_rpm_xo_ops, \
+ .name = #_name "_clk", \
.parent_data = gcc_cxo, \
.num_parents = ARRAY_SIZE(gcc_cxo), \
}, \
}
-#define DEFINE_CLK_RPM_FIXED(_platform, _name, _active, r_id, r) \
- static struct clk_rpm _platform##_##_name = { \
+#define DEFINE_CLK_RPM_FIXED(_name, r_id, r) \
+ static struct clk_rpm clk_rpm_##_name##_clk = { \
.rpm_clk_id = (r_id), \
.rate = (r), \
.hw.init = &(struct clk_init_data){ \
.ops = &clk_rpm_fixed_ops, \
- .name = #_name, \
+ .name = #_name "_clk", \
.parent_data = gcc_pxo, \
.num_parents = ARRAY_SIZE(gcc_pxo), \
}, \
@@ -402,38 +402,48 @@ static const struct clk_ops clk_rpm_ops = {
.recalc_rate = clk_rpm_recalc_rate,
};
-/* MSM8660/APQ8060 */
-DEFINE_CLK_RPM(msm8660, afab_clk, afab_a_clk, QCOM_RPM_APPS_FABRIC_CLK);
-DEFINE_CLK_RPM(msm8660, sfab_clk, sfab_a_clk, QCOM_RPM_SYS_FABRIC_CLK);
-DEFINE_CLK_RPM(msm8660, mmfab_clk, mmfab_a_clk, QCOM_RPM_MM_FABRIC_CLK);
-DEFINE_CLK_RPM(msm8660, daytona_clk, daytona_a_clk, QCOM_RPM_DAYTONA_FABRIC_CLK);
-DEFINE_CLK_RPM(msm8660, sfpb_clk, sfpb_a_clk, QCOM_RPM_SFPB_CLK);
-DEFINE_CLK_RPM(msm8660, cfpb_clk, cfpb_a_clk, QCOM_RPM_CFPB_CLK);
-DEFINE_CLK_RPM(msm8660, mmfpb_clk, mmfpb_a_clk, QCOM_RPM_MMFPB_CLK);
-DEFINE_CLK_RPM(msm8660, smi_clk, smi_a_clk, QCOM_RPM_SMI_CLK);
-DEFINE_CLK_RPM(msm8660, ebi1_clk, ebi1_a_clk, QCOM_RPM_EBI1_CLK);
-DEFINE_CLK_RPM_FIXED(msm8660, pll4_clk, pll4_a_clk, QCOM_RPM_PLL_4, 540672000);
+DEFINE_CLK_RPM(afab, QCOM_RPM_APPS_FABRIC_CLK);
+DEFINE_CLK_RPM(sfab, QCOM_RPM_SYS_FABRIC_CLK);
+DEFINE_CLK_RPM(mmfab, QCOM_RPM_MM_FABRIC_CLK);
+DEFINE_CLK_RPM(daytona, QCOM_RPM_DAYTONA_FABRIC_CLK);
+DEFINE_CLK_RPM(sfpb, QCOM_RPM_SFPB_CLK);
+DEFINE_CLK_RPM(cfpb, QCOM_RPM_CFPB_CLK);
+DEFINE_CLK_RPM(mmfpb, QCOM_RPM_MMFPB_CLK);
+DEFINE_CLK_RPM(smi, QCOM_RPM_SMI_CLK);
+DEFINE_CLK_RPM(ebi1, QCOM_RPM_EBI1_CLK);
+
+DEFINE_CLK_RPM(qdss, QCOM_RPM_QDSS_CLK);
+DEFINE_CLK_RPM(nss_fabric_0, QCOM_RPM_NSS_FABRIC_0_CLK);
+DEFINE_CLK_RPM(nss_fabric_1, QCOM_RPM_NSS_FABRIC_1_CLK);
+
+DEFINE_CLK_RPM_FIXED(pll4, QCOM_RPM_PLL_4, 540672000);
+
+DEFINE_CLK_RPM_XO_BUFFER(xo_d0, 0);
+DEFINE_CLK_RPM_XO_BUFFER(xo_d1, 8);
+DEFINE_CLK_RPM_XO_BUFFER(xo_a0, 16);
+DEFINE_CLK_RPM_XO_BUFFER(xo_a1, 24);
+DEFINE_CLK_RPM_XO_BUFFER(xo_a2, 28);
static struct clk_rpm *msm8660_clks[] = {
- [RPM_APPS_FABRIC_CLK] = &msm8660_afab_clk,
- [RPM_APPS_FABRIC_A_CLK] = &msm8660_afab_a_clk,
- [RPM_SYS_FABRIC_CLK] = &msm8660_sfab_clk,
- [RPM_SYS_FABRIC_A_CLK] = &msm8660_sfab_a_clk,
- [RPM_MM_FABRIC_CLK] = &msm8660_mmfab_clk,
- [RPM_MM_FABRIC_A_CLK] = &msm8660_mmfab_a_clk,
- [RPM_DAYTONA_FABRIC_CLK] = &msm8660_daytona_clk,
- [RPM_DAYTONA_FABRIC_A_CLK] = &msm8660_daytona_a_clk,
- [RPM_SFPB_CLK] = &msm8660_sfpb_clk,
- [RPM_SFPB_A_CLK] = &msm8660_sfpb_a_clk,
- [RPM_CFPB_CLK] = &msm8660_cfpb_clk,
- [RPM_CFPB_A_CLK] = &msm8660_cfpb_a_clk,
- [RPM_MMFPB_CLK] = &msm8660_mmfpb_clk,
- [RPM_MMFPB_A_CLK] = &msm8660_mmfpb_a_clk,
- [RPM_SMI_CLK] = &msm8660_smi_clk,
- [RPM_SMI_A_CLK] = &msm8660_smi_a_clk,
- [RPM_EBI1_CLK] = &msm8660_ebi1_clk,
- [RPM_EBI1_A_CLK] = &msm8660_ebi1_a_clk,
- [RPM_PLL4_CLK] = &msm8660_pll4_clk,
+ [RPM_APPS_FABRIC_CLK] = &clk_rpm_afab_clk,
+ [RPM_APPS_FABRIC_A_CLK] = &clk_rpm_afab_a_clk,
+ [RPM_SYS_FABRIC_CLK] = &clk_rpm_sfab_clk,
+ [RPM_SYS_FABRIC_A_CLK] = &clk_rpm_sfab_a_clk,
+ [RPM_MM_FABRIC_CLK] = &clk_rpm_mmfab_clk,
+ [RPM_MM_FABRIC_A_CLK] = &clk_rpm_mmfab_a_clk,
+ [RPM_DAYTONA_FABRIC_CLK] = &clk_rpm_daytona_clk,
+ [RPM_DAYTONA_FABRIC_A_CLK] = &clk_rpm_daytona_a_clk,
+ [RPM_SFPB_CLK] = &clk_rpm_sfpb_clk,
+ [RPM_SFPB_A_CLK] = &clk_rpm_sfpb_a_clk,
+ [RPM_CFPB_CLK] = &clk_rpm_cfpb_clk,
+ [RPM_CFPB_A_CLK] = &clk_rpm_cfpb_a_clk,
+ [RPM_MMFPB_CLK] = &clk_rpm_mmfpb_clk,
+ [RPM_MMFPB_A_CLK] = &clk_rpm_mmfpb_a_clk,
+ [RPM_SMI_CLK] = &clk_rpm_smi_clk,
+ [RPM_SMI_A_CLK] = &clk_rpm_smi_a_clk,
+ [RPM_EBI1_CLK] = &clk_rpm_ebi1_clk,
+ [RPM_EBI1_A_CLK] = &clk_rpm_ebi1_a_clk,
+ [RPM_PLL4_CLK] = &clk_rpm_pll4_clk,
};
static const struct rpm_clk_desc rpm_clk_msm8660 = {
@@ -441,46 +451,30 @@ static const struct rpm_clk_desc rpm_clk_msm8660 = {
.num_clks = ARRAY_SIZE(msm8660_clks),
};
-/* apq8064 */
-DEFINE_CLK_RPM(apq8064, afab_clk, afab_a_clk, QCOM_RPM_APPS_FABRIC_CLK);
-DEFINE_CLK_RPM(apq8064, cfpb_clk, cfpb_a_clk, QCOM_RPM_CFPB_CLK);
-DEFINE_CLK_RPM(apq8064, daytona_clk, daytona_a_clk, QCOM_RPM_DAYTONA_FABRIC_CLK);
-DEFINE_CLK_RPM(apq8064, ebi1_clk, ebi1_a_clk, QCOM_RPM_EBI1_CLK);
-DEFINE_CLK_RPM(apq8064, mmfab_clk, mmfab_a_clk, QCOM_RPM_MM_FABRIC_CLK);
-DEFINE_CLK_RPM(apq8064, mmfpb_clk, mmfpb_a_clk, QCOM_RPM_MMFPB_CLK);
-DEFINE_CLK_RPM(apq8064, sfab_clk, sfab_a_clk, QCOM_RPM_SYS_FABRIC_CLK);
-DEFINE_CLK_RPM(apq8064, sfpb_clk, sfpb_a_clk, QCOM_RPM_SFPB_CLK);
-DEFINE_CLK_RPM(apq8064, qdss_clk, qdss_a_clk, QCOM_RPM_QDSS_CLK);
-DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_d0_clk, xo_d0_a_clk, 0);
-DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_d1_clk, xo_d1_a_clk, 8);
-DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_a0_clk, xo_a0_a_clk, 16);
-DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_a1_clk, xo_a1_a_clk, 24);
-DEFINE_CLK_RPM_XO_BUFFER(apq8064, xo_a2_clk, xo_a2_a_clk, 28);
-
static struct clk_rpm *apq8064_clks[] = {
- [RPM_APPS_FABRIC_CLK] = &apq8064_afab_clk,
- [RPM_APPS_FABRIC_A_CLK] = &apq8064_afab_a_clk,
- [RPM_CFPB_CLK] = &apq8064_cfpb_clk,
- [RPM_CFPB_A_CLK] = &apq8064_cfpb_a_clk,
- [RPM_DAYTONA_FABRIC_CLK] = &apq8064_daytona_clk,
- [RPM_DAYTONA_FABRIC_A_CLK] = &apq8064_daytona_a_clk,
- [RPM_EBI1_CLK] = &apq8064_ebi1_clk,
- [RPM_EBI1_A_CLK] = &apq8064_ebi1_a_clk,
- [RPM_MM_FABRIC_CLK] = &apq8064_mmfab_clk,
- [RPM_MM_FABRIC_A_CLK] = &apq8064_mmfab_a_clk,
- [RPM_MMFPB_CLK] = &apq8064_mmfpb_clk,
- [RPM_MMFPB_A_CLK] = &apq8064_mmfpb_a_clk,
- [RPM_SYS_FABRIC_CLK] = &apq8064_sfab_clk,
- [RPM_SYS_FABRIC_A_CLK] = &apq8064_sfab_a_clk,
- [RPM_SFPB_CLK] = &apq8064_sfpb_clk,
- [RPM_SFPB_A_CLK] = &apq8064_sfpb_a_clk,
- [RPM_QDSS_CLK] = &apq8064_qdss_clk,
- [RPM_QDSS_A_CLK] = &apq8064_qdss_a_clk,
- [RPM_XO_D0] = &apq8064_xo_d0_clk,
- [RPM_XO_D1] = &apq8064_xo_d1_clk,
- [RPM_XO_A0] = &apq8064_xo_a0_clk,
- [RPM_XO_A1] = &apq8064_xo_a1_clk,
- [RPM_XO_A2] = &apq8064_xo_a2_clk,
+ [RPM_APPS_FABRIC_CLK] = &clk_rpm_afab_clk,
+ [RPM_APPS_FABRIC_A_CLK] = &clk_rpm_afab_a_clk,
+ [RPM_CFPB_CLK] = &clk_rpm_cfpb_clk,
+ [RPM_CFPB_A_CLK] = &clk_rpm_cfpb_a_clk,
+ [RPM_DAYTONA_FABRIC_CLK] = &clk_rpm_daytona_clk,
+ [RPM_DAYTONA_FABRIC_A_CLK] = &clk_rpm_daytona_a_clk,
+ [RPM_EBI1_CLK] = &clk_rpm_ebi1_clk,
+ [RPM_EBI1_A_CLK] = &clk_rpm_ebi1_a_clk,
+ [RPM_MM_FABRIC_CLK] = &clk_rpm_mmfab_clk,
+ [RPM_MM_FABRIC_A_CLK] = &clk_rpm_mmfab_a_clk,
+ [RPM_MMFPB_CLK] = &clk_rpm_mmfpb_clk,
+ [RPM_MMFPB_A_CLK] = &clk_rpm_mmfpb_a_clk,
+ [RPM_SYS_FABRIC_CLK] = &clk_rpm_sfab_clk,
+ [RPM_SYS_FABRIC_A_CLK] = &clk_rpm_sfab_a_clk,
+ [RPM_SFPB_CLK] = &clk_rpm_sfpb_clk,
+ [RPM_SFPB_A_CLK] = &clk_rpm_sfpb_a_clk,
+ [RPM_QDSS_CLK] = &clk_rpm_qdss_clk,
+ [RPM_QDSS_A_CLK] = &clk_rpm_qdss_a_clk,
+ [RPM_XO_D0] = &clk_rpm_xo_d0_clk,
+ [RPM_XO_D1] = &clk_rpm_xo_d1_clk,
+ [RPM_XO_A0] = &clk_rpm_xo_a0_clk,
+ [RPM_XO_A1] = &clk_rpm_xo_a1_clk,
+ [RPM_XO_A2] = &clk_rpm_xo_a2_clk,
};
static const struct rpm_clk_desc rpm_clk_apq8064 = {
@@ -488,33 +482,23 @@ static const struct rpm_clk_desc rpm_clk_apq8064 = {
.num_clks = ARRAY_SIZE(apq8064_clks),
};
-/* ipq806x */
-DEFINE_CLK_RPM(ipq806x, afab_clk, afab_a_clk, QCOM_RPM_APPS_FABRIC_CLK);
-DEFINE_CLK_RPM(ipq806x, cfpb_clk, cfpb_a_clk, QCOM_RPM_CFPB_CLK);
-DEFINE_CLK_RPM(ipq806x, daytona_clk, daytona_a_clk, QCOM_RPM_DAYTONA_FABRIC_CLK);
-DEFINE_CLK_RPM(ipq806x, ebi1_clk, ebi1_a_clk, QCOM_RPM_EBI1_CLK);
-DEFINE_CLK_RPM(ipq806x, sfab_clk, sfab_a_clk, QCOM_RPM_SYS_FABRIC_CLK);
-DEFINE_CLK_RPM(ipq806x, sfpb_clk, sfpb_a_clk, QCOM_RPM_SFPB_CLK);
-DEFINE_CLK_RPM(ipq806x, nss_fabric_0_clk, nss_fabric_0_a_clk, QCOM_RPM_NSS_FABRIC_0_CLK);
-DEFINE_CLK_RPM(ipq806x, nss_fabric_1_clk, nss_fabric_1_a_clk, QCOM_RPM_NSS_FABRIC_1_CLK);
-
static struct clk_rpm *ipq806x_clks[] = {
- [RPM_APPS_FABRIC_CLK] = &ipq806x_afab_clk,
- [RPM_APPS_FABRIC_A_CLK] = &ipq806x_afab_a_clk,
- [RPM_CFPB_CLK] = &ipq806x_cfpb_clk,
- [RPM_CFPB_A_CLK] = &ipq806x_cfpb_a_clk,
- [RPM_DAYTONA_FABRIC_CLK] = &ipq806x_daytona_clk,
- [RPM_DAYTONA_FABRIC_A_CLK] = &ipq806x_daytona_a_clk,
- [RPM_EBI1_CLK] = &ipq806x_ebi1_clk,
- [RPM_EBI1_A_CLK] = &ipq806x_ebi1_a_clk,
- [RPM_SYS_FABRIC_CLK] = &ipq806x_sfab_clk,
- [RPM_SYS_FABRIC_A_CLK] = &ipq806x_sfab_a_clk,
- [RPM_SFPB_CLK] = &ipq806x_sfpb_clk,
- [RPM_SFPB_A_CLK] = &ipq806x_sfpb_a_clk,
- [RPM_NSS_FABRIC_0_CLK] = &ipq806x_nss_fabric_0_clk,
- [RPM_NSS_FABRIC_0_A_CLK] = &ipq806x_nss_fabric_0_a_clk,
- [RPM_NSS_FABRIC_1_CLK] = &ipq806x_nss_fabric_1_clk,
- [RPM_NSS_FABRIC_1_A_CLK] = &ipq806x_nss_fabric_1_a_clk,
+ [RPM_APPS_FABRIC_CLK] = &clk_rpm_afab_clk,
+ [RPM_APPS_FABRIC_A_CLK] = &clk_rpm_afab_a_clk,
+ [RPM_CFPB_CLK] = &clk_rpm_cfpb_clk,
+ [RPM_CFPB_A_CLK] = &clk_rpm_cfpb_a_clk,
+ [RPM_DAYTONA_FABRIC_CLK] = &clk_rpm_daytona_clk,
+ [RPM_DAYTONA_FABRIC_A_CLK] = &clk_rpm_daytona_a_clk,
+ [RPM_EBI1_CLK] = &clk_rpm_ebi1_clk,
+ [RPM_EBI1_A_CLK] = &clk_rpm_ebi1_a_clk,
+ [RPM_SYS_FABRIC_CLK] = &clk_rpm_sfab_clk,
+ [RPM_SYS_FABRIC_A_CLK] = &clk_rpm_sfab_a_clk,
+ [RPM_SFPB_CLK] = &clk_rpm_sfpb_clk,
+ [RPM_SFPB_A_CLK] = &clk_rpm_sfpb_a_clk,
+ [RPM_NSS_FABRIC_0_CLK] = &clk_rpm_nss_fabric_0_clk,
+ [RPM_NSS_FABRIC_0_A_CLK] = &clk_rpm_nss_fabric_0_a_clk,
+ [RPM_NSS_FABRIC_1_CLK] = &clk_rpm_nss_fabric_1_clk,
+ [RPM_NSS_FABRIC_1_A_CLK] = &clk_rpm_nss_fabric_1_a_clk,
};
static const struct rpm_clk_desc rpm_clk_ipq806x = {
diff --git a/drivers/clk/qcom/clk-rpmh.c b/drivers/clk/qcom/clk-rpmh.c
index 0471bab82464..586a810c682c 100644
--- a/drivers/clk/qcom/clk-rpmh.c
+++ b/drivers/clk/qcom/clk-rpmh.c
@@ -70,15 +70,15 @@ struct clk_rpmh_desc {
static DEFINE_MUTEX(rpmh_clk_lock);
-#define __DEFINE_CLK_RPMH(_platform, _name, _name_active, _res_name, \
+#define __DEFINE_CLK_RPMH(_name, _clk_name, _res_name, \
_res_en_offset, _res_on, _div) \
- static struct clk_rpmh _platform##_##_name_active; \
- static struct clk_rpmh _platform##_##_name = { \
+ static struct clk_rpmh clk_rpmh_##_clk_name##_ao; \
+ static struct clk_rpmh clk_rpmh_##_clk_name = { \
.res_name = _res_name, \
.res_addr = _res_en_offset, \
.res_on_val = _res_on, \
.div = _div, \
- .peer = &_platform##_##_name_active, \
+ .peer = &clk_rpmh_##_clk_name##_ao, \
.valid_state_mask = (BIT(RPMH_WAKE_ONLY_STATE) | \
BIT(RPMH_ACTIVE_ONLY_STATE) | \
BIT(RPMH_SLEEP_STATE)), \
@@ -92,17 +92,17 @@ static DEFINE_MUTEX(rpmh_clk_lock);
.num_parents = 1, \
}, \
}; \
- static struct clk_rpmh _platform##_##_name_active = { \
+ static struct clk_rpmh clk_rpmh_##_clk_name##_ao= { \
.res_name = _res_name, \
.res_addr = _res_en_offset, \
.res_on_val = _res_on, \
.div = _div, \
- .peer = &_platform##_##_name, \
+ .peer = &clk_rpmh_##_clk_name, \
.valid_state_mask = (BIT(RPMH_WAKE_ONLY_STATE) | \
BIT(RPMH_ACTIVE_ONLY_STATE)), \
.hw.init = &(struct clk_init_data){ \
.ops = &clk_rpmh_ops, \
- .name = #_name_active, \
+ .name = #_name "_ao", \
.parent_data = &(const struct clk_parent_data){ \
.fw_name = "xo", \
.name = "xo_board", \
@@ -111,18 +111,16 @@ static DEFINE_MUTEX(rpmh_clk_lock);
}, \
}
-#define DEFINE_CLK_RPMH_ARC(_platform, _name, _name_active, _res_name, \
- _res_on, _div) \
- __DEFINE_CLK_RPMH(_platform, _name, _name_active, _res_name, \
+#define DEFINE_CLK_RPMH_ARC(_name, _res_name, _res_on, _div) \
+ __DEFINE_CLK_RPMH(_name, _name##_##div##_div, _res_name, \
CLK_RPMH_ARC_EN_OFFSET, _res_on, _div)
-#define DEFINE_CLK_RPMH_VRM(_platform, _name, _name_active, _res_name, \
- _div) \
- __DEFINE_CLK_RPMH(_platform, _name, _name_active, _res_name, \
+#define DEFINE_CLK_RPMH_VRM(_name, _suffix, _res_name, _div) \
+ __DEFINE_CLK_RPMH(_name, _name##_suffix, _res_name, \
CLK_RPMH_VRM_EN_OFFSET, 1, _div)
-#define DEFINE_CLK_RPMH_BCM(_platform, _name, _res_name) \
- static struct clk_rpmh _platform##_##_name = { \
+#define DEFINE_CLK_RPMH_BCM(_name, _res_name) \
+ static struct clk_rpmh clk_rpmh_##_name = { \
.res_name = _res_name, \
.valid_state_mask = BIT(RPMH_ACTIVE_ONLY_STATE), \
.div = 1, \
@@ -342,35 +340,55 @@ static const struct clk_ops clk_rpmh_bcm_ops = {
};
/* Resource name must match resource id present in cmd-db */
-DEFINE_CLK_RPMH_ARC(sdm845, bi_tcxo, bi_tcxo_ao, "xo.lvl", 0x3, 2);
-DEFINE_CLK_RPMH_VRM(sdm845, ln_bb_clk2, ln_bb_clk2_ao, "lnbclka2", 2);
-DEFINE_CLK_RPMH_VRM(sdm845, ln_bb_clk3, ln_bb_clk3_ao, "lnbclka3", 2);
-DEFINE_CLK_RPMH_VRM(sdm845, rf_clk1, rf_clk1_ao, "rfclka1", 1);
-DEFINE_CLK_RPMH_VRM(sdm845, rf_clk2, rf_clk2_ao, "rfclka2", 1);
-DEFINE_CLK_RPMH_VRM(sdm845, rf_clk3, rf_clk3_ao, "rfclka3", 1);
-DEFINE_CLK_RPMH_VRM(sm8150, rf_clk3, rf_clk3_ao, "rfclka3", 1);
-DEFINE_CLK_RPMH_VRM(sc8180x, rf_clk1, rf_clk1_ao, "rfclkd1", 1);
-DEFINE_CLK_RPMH_VRM(sc8180x, rf_clk2, rf_clk2_ao, "rfclkd2", 1);
-DEFINE_CLK_RPMH_VRM(sc8180x, rf_clk3, rf_clk3_ao, "rfclkd3", 1);
-DEFINE_CLK_RPMH_VRM(sc8180x, rf_clk4, rf_clk4_ao, "rfclkd4", 1);
-DEFINE_CLK_RPMH_BCM(sdm845, ipa, "IP0");
-DEFINE_CLK_RPMH_BCM(sdm845, ce, "CE0");
+DEFINE_CLK_RPMH_ARC(bi_tcxo, "xo.lvl", 0x3, 1);
+DEFINE_CLK_RPMH_ARC(bi_tcxo, "xo.lvl", 0x3, 2);
+DEFINE_CLK_RPMH_ARC(bi_tcxo, "xo.lvl", 0x3, 4);
+DEFINE_CLK_RPMH_ARC(qlink, "qphy.lvl", 0x1, 4);
+
+DEFINE_CLK_RPMH_VRM(ln_bb_clk1, _a2, "lnbclka1", 2);
+DEFINE_CLK_RPMH_VRM(ln_bb_clk2, _a2, "lnbclka2", 2);
+DEFINE_CLK_RPMH_VRM(ln_bb_clk3, _a2, "lnbclka3", 2);
+
+DEFINE_CLK_RPMH_VRM(ln_bb_clk1, _a4, "lnbclka1", 4);
+DEFINE_CLK_RPMH_VRM(ln_bb_clk2, _a4, "lnbclka2", 4);
+
+DEFINE_CLK_RPMH_VRM(ln_bb_clk2, _g4, "lnbclkg2", 4);
+DEFINE_CLK_RPMH_VRM(ln_bb_clk3, _g4, "lnbclkg3", 4);
+
+DEFINE_CLK_RPMH_VRM(rf_clk1, _a, "rfclka1", 1);
+DEFINE_CLK_RPMH_VRM(rf_clk2, _a, "rfclka2", 1);
+DEFINE_CLK_RPMH_VRM(rf_clk3, _a, "rfclka3", 1);
+DEFINE_CLK_RPMH_VRM(rf_clk4, _a, "rfclka4", 1);
+DEFINE_CLK_RPMH_VRM(rf_clk5, _a, "rfclka5", 1);
+
+DEFINE_CLK_RPMH_VRM(rf_clk1, _d, "rfclkd1", 1);
+DEFINE_CLK_RPMH_VRM(rf_clk2, _d, "rfclkd2", 1);
+DEFINE_CLK_RPMH_VRM(rf_clk3, _d, "rfclkd3", 1);
+DEFINE_CLK_RPMH_VRM(rf_clk4, _d, "rfclkd4", 1);
+
+DEFINE_CLK_RPMH_VRM(div_clk1, _div2, "divclka1", 2);
+
+DEFINE_CLK_RPMH_BCM(ce, "CE0");
+DEFINE_CLK_RPMH_BCM(hwkm, "HK0");
+DEFINE_CLK_RPMH_BCM(ipa, "IP0");
+DEFINE_CLK_RPMH_BCM(pka, "PKA0");
+DEFINE_CLK_RPMH_BCM(qpic_clk, "QP0");
static struct clk_hw *sdm845_rpmh_clocks[] = {
- [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
- [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
- [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw,
- [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw,
- [RPMH_LN_BB_CLK3] = &sdm845_ln_bb_clk3.hw,
- [RPMH_LN_BB_CLK3_A] = &sdm845_ln_bb_clk3_ao.hw,
- [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
- [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
- [RPMH_RF_CLK2] = &sdm845_rf_clk2.hw,
- [RPMH_RF_CLK2_A] = &sdm845_rf_clk2_ao.hw,
- [RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
- [RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
- [RPMH_IPA_CLK] = &sdm845_ipa.hw,
- [RPMH_CE_CLK] = &sdm845_ce.hw,
+ [RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div2.hw,
+ [RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div2_ao.hw,
+ [RPMH_LN_BB_CLK2] = &clk_rpmh_ln_bb_clk2_a2.hw,
+ [RPMH_LN_BB_CLK2_A] = &clk_rpmh_ln_bb_clk2_a2_ao.hw,
+ [RPMH_LN_BB_CLK3] = &clk_rpmh_ln_bb_clk3_a2.hw,
+ [RPMH_LN_BB_CLK3_A] = &clk_rpmh_ln_bb_clk3_a2_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_IPA_CLK] = &clk_rpmh_ipa.hw,
+ [RPMH_CE_CLK] = &clk_rpmh_ce.hw,
};
static const struct clk_rpmh_desc clk_rpmh_sdm845 = {
@@ -379,18 +397,18 @@ static const struct clk_rpmh_desc clk_rpmh_sdm845 = {
};
static struct clk_hw *sdm670_rpmh_clocks[] = {
- [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
- [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
- [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw,
- [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw,
- [RPMH_LN_BB_CLK3] = &sdm845_ln_bb_clk3.hw,
- [RPMH_LN_BB_CLK3_A] = &sdm845_ln_bb_clk3_ao.hw,
- [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
- [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
- [RPMH_RF_CLK2] = &sdm845_rf_clk2.hw,
- [RPMH_RF_CLK2_A] = &sdm845_rf_clk2_ao.hw,
- [RPMH_IPA_CLK] = &sdm845_ipa.hw,
- [RPMH_CE_CLK] = &sdm845_ce.hw,
+ [RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div2.hw,
+ [RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div2_ao.hw,
+ [RPMH_LN_BB_CLK2] = &clk_rpmh_ln_bb_clk2_a2.hw,
+ [RPMH_LN_BB_CLK2_A] = &clk_rpmh_ln_bb_clk2_a2_ao.hw,
+ [RPMH_LN_BB_CLK3] = &clk_rpmh_ln_bb_clk3_a2.hw,
+ [RPMH_LN_BB_CLK3_A] = &clk_rpmh_ln_bb_clk3_a2_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_IPA_CLK] = &clk_rpmh_ipa.hw,
+ [RPMH_CE_CLK] = &clk_rpmh_ce.hw,
};
static const struct clk_rpmh_desc clk_rpmh_sdm670 = {
@@ -398,20 +416,15 @@ static const struct clk_rpmh_desc clk_rpmh_sdm670 = {
.num_clks = ARRAY_SIZE(sdm670_rpmh_clocks),
};
-DEFINE_CLK_RPMH_VRM(sdx55, rf_clk1, rf_clk1_ao, "rfclkd1", 1);
-DEFINE_CLK_RPMH_VRM(sdx55, rf_clk2, rf_clk2_ao, "rfclkd2", 1);
-DEFINE_CLK_RPMH_BCM(sdx55, qpic_clk, "QP0");
-DEFINE_CLK_RPMH_BCM(sdx55, ipa, "IP0");
-
static struct clk_hw *sdx55_rpmh_clocks[] = {
- [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
- [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
- [RPMH_RF_CLK1] = &sdx55_rf_clk1.hw,
- [RPMH_RF_CLK1_A] = &sdx55_rf_clk1_ao.hw,
- [RPMH_RF_CLK2] = &sdx55_rf_clk2.hw,
- [RPMH_RF_CLK2_A] = &sdx55_rf_clk2_ao.hw,
- [RPMH_QPIC_CLK] = &sdx55_qpic_clk.hw,
- [RPMH_IPA_CLK] = &sdx55_ipa.hw,
+ [RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div2.hw,
+ [RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div2_ao.hw,
+ [RPMH_RF_CLK1] = &clk_rpmh_rf_clk1_d.hw,
+ [RPMH_RF_CLK1_A] = &clk_rpmh_rf_clk1_d_ao.hw,
+ [RPMH_RF_CLK2] = &clk_rpmh_rf_clk2_d.hw,
+ [RPMH_RF_CLK2_A] = &clk_rpmh_rf_clk2_d_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_sdx55 = {
@@ -420,18 +433,18 @@ static const struct clk_rpmh_desc clk_rpmh_sdx55 = {
};
static struct clk_hw *sm8150_rpmh_clocks[] = {
- [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
- [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
- [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw,
- [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw,
- [RPMH_LN_BB_CLK3] = &sdm845_ln_bb_clk3.hw,
- [RPMH_LN_BB_CLK3_A] = &sdm845_ln_bb_clk3_ao.hw,
- [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
- [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
- [RPMH_RF_CLK2] = &sdm845_rf_clk2.hw,
- [RPMH_RF_CLK2_A] = &sdm845_rf_clk2_ao.hw,
- [RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
- [RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
+ [RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div2.hw,
+ [RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div2_ao.hw,
+ [RPMH_LN_BB_CLK2] = &clk_rpmh_ln_bb_clk2_a2.hw,
+ [RPMH_LN_BB_CLK2_A] = &clk_rpmh_ln_bb_clk2_a2_ao.hw,
+ [RPMH_LN_BB_CLK3] = &clk_rpmh_ln_bb_clk3_a2.hw,
+ [RPMH_LN_BB_CLK3_A] = &clk_rpmh_ln_bb_clk3_a2_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,
};
static const struct clk_rpmh_desc clk_rpmh_sm8150 = {
@@ -440,17 +453,17 @@ static const struct clk_rpmh_desc clk_rpmh_sm8150 = {
};
static struct clk_hw *sc7180_rpmh_clocks[] = {
- [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
- [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
- [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw,
- [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw,
- [RPMH_LN_BB_CLK3] = &sdm845_ln_bb_clk3.hw,
- [RPMH_LN_BB_CLK3_A] = &sdm845_ln_bb_clk3_ao.hw,
- [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
- [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
- [RPMH_RF_CLK2] = &sdm845_rf_clk2.hw,
- [RPMH_RF_CLK2_A] = &sdm845_rf_clk2_ao.hw,
- [RPMH_IPA_CLK] = &sdm845_ipa.hw,
+ [RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div2.hw,
+ [RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div2_ao.hw,
+ [RPMH_LN_BB_CLK2] = &clk_rpmh_ln_bb_clk2_a2.hw,
+ [RPMH_LN_BB_CLK2_A] = &clk_rpmh_ln_bb_clk2_a2_ao.hw,
+ [RPMH_LN_BB_CLK3] = &clk_rpmh_ln_bb_clk3_a2.hw,
+ [RPMH_LN_BB_CLK3_A] = &clk_rpmh_ln_bb_clk3_a2_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_IPA_CLK] = &clk_rpmh_ipa.hw,
};
static const struct clk_rpmh_desc clk_rpmh_sc7180 = {
@@ -459,18 +472,18 @@ static const struct clk_rpmh_desc clk_rpmh_sc7180 = {
};
static struct clk_hw *sc8180x_rpmh_clocks[] = {
- [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
- [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
- [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw,
- [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw,
- [RPMH_LN_BB_CLK3] = &sdm845_ln_bb_clk3.hw,
- [RPMH_LN_BB_CLK3_A] = &sdm845_ln_bb_clk3_ao.hw,
- [RPMH_RF_CLK1] = &sc8180x_rf_clk1.hw,
- [RPMH_RF_CLK1_A] = &sc8180x_rf_clk1_ao.hw,
- [RPMH_RF_CLK2] = &sc8180x_rf_clk2.hw,
- [RPMH_RF_CLK2_A] = &sc8180x_rf_clk2_ao.hw,
- [RPMH_RF_CLK3] = &sc8180x_rf_clk3.hw,
- [RPMH_RF_CLK3_A] = &sc8180x_rf_clk3_ao.hw,
+ [RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div2.hw,
+ [RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div2_ao.hw,
+ [RPMH_LN_BB_CLK2] = &clk_rpmh_ln_bb_clk2_a2.hw,
+ [RPMH_LN_BB_CLK2_A] = &clk_rpmh_ln_bb_clk2_a2_ao.hw,
+ [RPMH_LN_BB_CLK3] = &clk_rpmh_ln_bb_clk3_a2.hw,
+ [RPMH_LN_BB_CLK3_A] = &clk_rpmh_ln_bb_clk3_a2_ao.hw,
+ [RPMH_RF_CLK1] = &clk_rpmh_rf_clk1_d.hw,
+ [RPMH_RF_CLK1_A] = &clk_rpmh_rf_clk1_d_ao.hw,
+ [RPMH_RF_CLK2] = &clk_rpmh_rf_clk2_d.hw,
+ [RPMH_RF_CLK2_A] = &clk_rpmh_rf_clk2_d_ao.hw,
+ [RPMH_RF_CLK3] = &clk_rpmh_rf_clk3_d.hw,
+ [RPMH_RF_CLK3_A] = &clk_rpmh_rf_clk3_d_ao.hw,
};
static const struct clk_rpmh_desc clk_rpmh_sc8180x = {
@@ -478,21 +491,19 @@ static const struct clk_rpmh_desc clk_rpmh_sc8180x = {
.num_clks = ARRAY_SIZE(sc8180x_rpmh_clocks),
};
-DEFINE_CLK_RPMH_VRM(sm8250, ln_bb_clk1, ln_bb_clk1_ao, "lnbclka1", 2);
-
static struct clk_hw *sm8250_rpmh_clocks[] = {
- [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
- [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
- [RPMH_LN_BB_CLK1] = &sm8250_ln_bb_clk1.hw,
- [RPMH_LN_BB_CLK1_A] = &sm8250_ln_bb_clk1_ao.hw,
- [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw,
- [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw,
- [RPMH_LN_BB_CLK3] = &sdm845_ln_bb_clk3.hw,
- [RPMH_LN_BB_CLK3_A] = &sdm845_ln_bb_clk3_ao.hw,
- [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
- [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
- [RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
- [RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
+ [RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div2.hw,
+ [RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div2_ao.hw,
+ [RPMH_LN_BB_CLK1] = &clk_rpmh_ln_bb_clk1_a2.hw,
+ [RPMH_LN_BB_CLK1_A] = &clk_rpmh_ln_bb_clk1_a2_ao.hw,
+ [RPMH_LN_BB_CLK2] = &clk_rpmh_ln_bb_clk2_a2.hw,
+ [RPMH_LN_BB_CLK2_A] = &clk_rpmh_ln_bb_clk2_a2_ao.hw,
+ [RPMH_LN_BB_CLK3] = &clk_rpmh_ln_bb_clk3_a2.hw,
+ [RPMH_LN_BB_CLK3_A] = &clk_rpmh_ln_bb_clk3_a2_ao.hw,
+ [RPMH_RF_CLK1] = &clk_rpmh_rf_clk1_a.hw,
+ [RPMH_RF_CLK1_A] = &clk_rpmh_rf_clk1_a_ao.hw,
+ [RPMH_RF_CLK3] = &clk_rpmh_rf_clk3_a.hw,
+ [RPMH_RF_CLK3_A] = &clk_rpmh_rf_clk3_a_ao.hw,
};
static const struct clk_rpmh_desc clk_rpmh_sm8250 = {
@@ -500,32 +511,26 @@ static const struct clk_rpmh_desc clk_rpmh_sm8250 = {
.num_clks = ARRAY_SIZE(sm8250_rpmh_clocks),
};
-DEFINE_CLK_RPMH_VRM(sm8350, div_clk1, div_clk1_ao, "divclka1", 2);
-DEFINE_CLK_RPMH_VRM(sm8350, rf_clk4, rf_clk4_ao, "rfclka4", 1);
-DEFINE_CLK_RPMH_VRM(sm8350, rf_clk5, rf_clk5_ao, "rfclka5", 1);
-DEFINE_CLK_RPMH_BCM(sm8350, pka, "PKA0");
-DEFINE_CLK_RPMH_BCM(sm8350, hwkm, "HK0");
-
static struct clk_hw *sm8350_rpmh_clocks[] = {
- [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
- [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
- [RPMH_DIV_CLK1] = &sm8350_div_clk1.hw,
- [RPMH_DIV_CLK1_A] = &sm8350_div_clk1_ao.hw,
- [RPMH_LN_BB_CLK1] = &sm8250_ln_bb_clk1.hw,
- [RPMH_LN_BB_CLK1_A] = &sm8250_ln_bb_clk1_ao.hw,
- [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw,
- [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw,
- [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
- [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
- [RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
- [RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
- [RPMH_RF_CLK4] = &sm8350_rf_clk4.hw,
- [RPMH_RF_CLK4_A] = &sm8350_rf_clk4_ao.hw,
- [RPMH_RF_CLK5] = &sm8350_rf_clk5.hw,
- [RPMH_RF_CLK5_A] = &sm8350_rf_clk5_ao.hw,
- [RPMH_IPA_CLK] = &sdm845_ipa.hw,
- [RPMH_PKA_CLK] = &sm8350_pka.hw,
- [RPMH_HWKM_CLK] = &sm8350_hwkm.hw,
+ [RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div2.hw,
+ [RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div2_ao.hw,
+ [RPMH_DIV_CLK1] = &clk_rpmh_div_clk1_div2.hw,
+ [RPMH_DIV_CLK1_A] = &clk_rpmh_div_clk1_div2_ao.hw,
+ [RPMH_LN_BB_CLK1] = &clk_rpmh_ln_bb_clk1_a2.hw,
+ [RPMH_LN_BB_CLK1_A] = &clk_rpmh_ln_bb_clk1_a2_ao.hw,
+ [RPMH_LN_BB_CLK2] = &clk_rpmh_ln_bb_clk2_a2.hw,
+ [RPMH_LN_BB_CLK2_A] = &clk_rpmh_ln_bb_clk2_a2_ao.hw,
+ [RPMH_RF_CLK1] = &clk_rpmh_rf_clk1_a.hw,
+ [RPMH_RF_CLK1_A] = &clk_rpmh_rf_clk1_a_ao.hw,
+ [RPMH_RF_CLK3] = &clk_rpmh_rf_clk3_a.hw,
+ [RPMH_RF_CLK3_A] = &clk_rpmh_rf_clk3_a_ao.hw,
+ [RPMH_RF_CLK4] = &clk_rpmh_rf_clk4_a.hw,
+ [RPMH_RF_CLK4_A] = &clk_rpmh_rf_clk4_a_ao.hw,
+ [RPMH_RF_CLK5] = &clk_rpmh_rf_clk5_a.hw,
+ [RPMH_RF_CLK5_A] = &clk_rpmh_rf_clk5_a_ao.hw,
+ [RPMH_IPA_CLK] = &clk_rpmh_ipa.hw,
+ [RPMH_PKA_CLK] = &clk_rpmh_pka.hw,
+ [RPMH_HWKM_CLK] = &clk_rpmh_hwkm.hw,
};
static const struct clk_rpmh_desc clk_rpmh_sm8350 = {
@@ -533,16 +538,14 @@ static const struct clk_rpmh_desc clk_rpmh_sm8350 = {
.num_clks = ARRAY_SIZE(sm8350_rpmh_clocks),
};
-DEFINE_CLK_RPMH_VRM(sc8280xp, ln_bb_clk3, ln_bb_clk3_ao, "lnbclka3", 2);
-
static struct clk_hw *sc8280xp_rpmh_clocks[] = {
- [RPMH_CXO_CLK] = &sdm845_bi_tcxo.hw,
- [RPMH_CXO_CLK_A] = &sdm845_bi_tcxo_ao.hw,
- [RPMH_LN_BB_CLK3] = &sc8280xp_ln_bb_clk3.hw,
- [RPMH_LN_BB_CLK3_A] = &sc8280xp_ln_bb_clk3_ao.hw,
- [RPMH_IPA_CLK] = &sdm845_ipa.hw,
- [RPMH_PKA_CLK] = &sm8350_pka.hw,
- [RPMH_HWKM_CLK] = &sm8350_hwkm.hw,
+ [RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div2.hw,
+ [RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div2_ao.hw,
+ [RPMH_LN_BB_CLK3] = &clk_rpmh_ln_bb_clk3_a2.hw,
+ [RPMH_LN_BB_CLK3_A] = &clk_rpmh_ln_bb_clk3_a2_ao.hw,
+ [RPMH_IPA_CLK] = &clk_rpmh_ipa.hw,
+ [RPMH_PKA_CLK] = &clk_rpmh_pka.hw,
+ [RPMH_HWKM_CLK] = &clk_rpmh_hwkm.hw,
};
static const struct clk_rpmh_desc clk_rpmh_sc8280xp = {
@@ -550,28 +553,22 @@ static const struct clk_rpmh_desc clk_rpmh_sc8280xp = {
.num_clks = ARRAY_SIZE(sc8280xp_rpmh_clocks),
};
-/* Resource name must match resource id present in cmd-db */
-DEFINE_CLK_RPMH_ARC(sc7280, bi_tcxo, bi_tcxo_ao, "xo.lvl", 0x3, 4);
-
-DEFINE_CLK_RPMH_VRM(sm8450, ln_bb_clk1, ln_bb_clk1_ao, "lnbclka1", 4);
-DEFINE_CLK_RPMH_VRM(sm8450, ln_bb_clk2, ln_bb_clk2_ao, "lnbclka2", 4);
-
static struct clk_hw *sm8450_rpmh_clocks[] = {
- [RPMH_CXO_CLK] = &sc7280_bi_tcxo.hw,
- [RPMH_CXO_CLK_A] = &sc7280_bi_tcxo_ao.hw,
- [RPMH_LN_BB_CLK1] = &sm8450_ln_bb_clk1.hw,
- [RPMH_LN_BB_CLK1_A] = &sm8450_ln_bb_clk1_ao.hw,
- [RPMH_LN_BB_CLK2] = &sm8450_ln_bb_clk2.hw,
- [RPMH_LN_BB_CLK2_A] = &sm8450_ln_bb_clk2_ao.hw,
- [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
- [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
- [RPMH_RF_CLK2] = &sdm845_rf_clk2.hw,
- [RPMH_RF_CLK2_A] = &sdm845_rf_clk2_ao.hw,
- [RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
- [RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
- [RPMH_RF_CLK4] = &sm8350_rf_clk4.hw,
- [RPMH_RF_CLK4_A] = &sm8350_rf_clk4_ao.hw,
- [RPMH_IPA_CLK] = &sdm845_ipa.hw,
+ [RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div4.hw,
+ [RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div4_ao.hw,
+ [RPMH_LN_BB_CLK1] = &clk_rpmh_ln_bb_clk1_a4.hw,
+ [RPMH_LN_BB_CLK1_A] = &clk_rpmh_ln_bb_clk1_a4_ao.hw,
+ [RPMH_LN_BB_CLK2] = &clk_rpmh_ln_bb_clk2_a4.hw,
+ [RPMH_LN_BB_CLK2_A] = &clk_rpmh_ln_bb_clk2_a4_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_RF_CLK4] = &clk_rpmh_rf_clk4_a.hw,
+ [RPMH_RF_CLK4_A] = &clk_rpmh_rf_clk4_a_ao.hw,
+ [RPMH_IPA_CLK] = &clk_rpmh_ipa.hw,
};
static const struct clk_rpmh_desc clk_rpmh_sm8450 = {
@@ -580,19 +577,19 @@ static const struct clk_rpmh_desc clk_rpmh_sm8450 = {
};
static struct clk_hw *sc7280_rpmh_clocks[] = {
- [RPMH_CXO_CLK] = &sc7280_bi_tcxo.hw,
- [RPMH_CXO_CLK_A] = &sc7280_bi_tcxo_ao.hw,
- [RPMH_LN_BB_CLK2] = &sdm845_ln_bb_clk2.hw,
- [RPMH_LN_BB_CLK2_A] = &sdm845_ln_bb_clk2_ao.hw,
- [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
- [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
- [RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
- [RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
- [RPMH_RF_CLK4] = &sm8350_rf_clk4.hw,
- [RPMH_RF_CLK4_A] = &sm8350_rf_clk4_ao.hw,
- [RPMH_IPA_CLK] = &sdm845_ipa.hw,
- [RPMH_PKA_CLK] = &sm8350_pka.hw,
- [RPMH_HWKM_CLK] = &sm8350_hwkm.hw,
+ [RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div4.hw,
+ [RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div4_ao.hw,
+ [RPMH_LN_BB_CLK2] = &clk_rpmh_ln_bb_clk2_a2.hw,
+ [RPMH_LN_BB_CLK2_A] = &clk_rpmh_ln_bb_clk2_a2_ao.hw,
+ [RPMH_RF_CLK1] = &clk_rpmh_rf_clk1_a.hw,
+ [RPMH_RF_CLK1_A] = &clk_rpmh_rf_clk1_a_ao.hw,
+ [RPMH_RF_CLK3] = &clk_rpmh_rf_clk3_a.hw,
+ [RPMH_RF_CLK3_A] = &clk_rpmh_rf_clk3_a_ao.hw,
+ [RPMH_RF_CLK4] = &clk_rpmh_rf_clk4_a.hw,
+ [RPMH_RF_CLK4_A] = &clk_rpmh_rf_clk4_a_ao.hw,
+ [RPMH_IPA_CLK] = &clk_rpmh_ipa.hw,
+ [RPMH_PKA_CLK] = &clk_rpmh_pka.hw,
+ [RPMH_HWKM_CLK] = &clk_rpmh_hwkm.hw,
};
static const struct clk_rpmh_desc clk_rpmh_sc7280 = {
@@ -600,19 +597,16 @@ static const struct clk_rpmh_desc clk_rpmh_sc7280 = {
.num_clks = ARRAY_SIZE(sc7280_rpmh_clocks),
};
-DEFINE_CLK_RPMH_VRM(sm6350, ln_bb_clk2, ln_bb_clk2_ao, "lnbclkg2", 4);
-DEFINE_CLK_RPMH_VRM(sm6350, ln_bb_clk3, ln_bb_clk3_ao, "lnbclkg3", 4);
-DEFINE_CLK_RPMH_ARC(sm6350, qlink, qlink_ao, "qphy.lvl", 0x1, 4);
-
static struct clk_hw *sm6350_rpmh_clocks[] = {
- [RPMH_CXO_CLK] = &sc7280_bi_tcxo.hw,
- [RPMH_CXO_CLK_A] = &sc7280_bi_tcxo_ao.hw,
- [RPMH_LN_BB_CLK2] = &sm6350_ln_bb_clk2.hw,
- [RPMH_LN_BB_CLK2_A] = &sm6350_ln_bb_clk2_ao.hw,
- [RPMH_LN_BB_CLK3] = &sm6350_ln_bb_clk3.hw,
- [RPMH_LN_BB_CLK3_A] = &sm6350_ln_bb_clk3_ao.hw,
- [RPMH_QLINK_CLK] = &sm6350_qlink.hw,
- [RPMH_QLINK_CLK_A] = &sm6350_qlink_ao.hw,
+ [RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div4.hw,
+ [RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div4_ao.hw,
+ [RPMH_LN_BB_CLK2] = &clk_rpmh_ln_bb_clk2_g4.hw,
+ [RPMH_LN_BB_CLK2_A] = &clk_rpmh_ln_bb_clk2_g4_ao.hw,
+ [RPMH_LN_BB_CLK3] = &clk_rpmh_ln_bb_clk3_g4.hw,
+ [RPMH_LN_BB_CLK3_A] = &clk_rpmh_ln_bb_clk3_g4_ao.hw,
+ [RPMH_QLINK_CLK] = &clk_rpmh_qlink_div4.hw,
+ [RPMH_QLINK_CLK_A] = &clk_rpmh_qlink_div4_ao.hw,
+ [RPMH_IPA_CLK] = &clk_rpmh_ipa.hw,
};
static const struct clk_rpmh_desc clk_rpmh_sm6350 = {
@@ -620,23 +614,21 @@ static const struct clk_rpmh_desc clk_rpmh_sm6350 = {
.num_clks = ARRAY_SIZE(sm6350_rpmh_clocks),
};
-DEFINE_CLK_RPMH_VRM(sdx65, ln_bb_clk1, ln_bb_clk1_ao, "lnbclka1", 4);
-
static struct clk_hw *sdx65_rpmh_clocks[] = {
- [RPMH_CXO_CLK] = &sc7280_bi_tcxo.hw,
- [RPMH_CXO_CLK_A] = &sc7280_bi_tcxo_ao.hw,
- [RPMH_LN_BB_CLK1] = &sdx65_ln_bb_clk1.hw,
- [RPMH_LN_BB_CLK1_A] = &sdx65_ln_bb_clk1_ao.hw,
- [RPMH_RF_CLK1] = &sdm845_rf_clk1.hw,
- [RPMH_RF_CLK1_A] = &sdm845_rf_clk1_ao.hw,
- [RPMH_RF_CLK2] = &sdm845_rf_clk2.hw,
- [RPMH_RF_CLK2_A] = &sdm845_rf_clk2_ao.hw,
- [RPMH_RF_CLK3] = &sdm845_rf_clk3.hw,
- [RPMH_RF_CLK3_A] = &sdm845_rf_clk3_ao.hw,
- [RPMH_RF_CLK4] = &sm8350_rf_clk4.hw,
- [RPMH_RF_CLK4_A] = &sm8350_rf_clk4_ao.hw,
- [RPMH_IPA_CLK] = &sdm845_ipa.hw,
- [RPMH_QPIC_CLK] = &sdx55_qpic_clk.hw,
+ [RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div4.hw,
+ [RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div4_ao.hw,
+ [RPMH_LN_BB_CLK1] = &clk_rpmh_ln_bb_clk1_a4.hw,
+ [RPMH_LN_BB_CLK1_A] = &clk_rpmh_ln_bb_clk1_a4_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_RF_CLK4] = &clk_rpmh_rf_clk4_a.hw,
+ [RPMH_RF_CLK4_A] = &clk_rpmh_rf_clk4_a_ao.hw,
+ [RPMH_IPA_CLK] = &clk_rpmh_ipa.hw,
+ [RPMH_QPIC_CLK] = &clk_rpmh_qpic_clk.hw,
};
static const struct clk_rpmh_desc clk_rpmh_sdx65 = {
@@ -644,6 +636,16 @@ static const struct clk_rpmh_desc clk_rpmh_sdx65 = {
.num_clks = ARRAY_SIZE(sdx65_rpmh_clocks),
};
+static struct clk_hw *qdu1000_rpmh_clocks[] = {
+ [RPMH_CXO_CLK] = &clk_rpmh_bi_tcxo_div1.hw,
+ [RPMH_CXO_CLK_A] = &clk_rpmh_bi_tcxo_div1_ao.hw,
+};
+
+static const struct clk_rpmh_desc clk_rpmh_qdu1000 = {
+ .clks = qdu1000_rpmh_clocks,
+ .num_clks = ARRAY_SIZE(qdu1000_rpmh_clocks),
+};
+
static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec,
void *data)
{
@@ -727,6 +729,7 @@ static int clk_rpmh_probe(struct platform_device *pdev)
}
static const struct of_device_id clk_rpmh_match_table[] = {
+ { .compatible = "qcom,qdu1000-rpmh-clk", .data = &clk_rpmh_qdu1000},
{ .compatible = "qcom,sc7180-rpmh-clk", .data = &clk_rpmh_sc7180},
{ .compatible = "qcom,sc8180x-rpmh-clk", .data = &clk_rpmh_sc8180x},
{ .compatible = "qcom,sc8280xp-rpmh-clk", .data = &clk_rpmh_sc8280xp},
diff --git a/drivers/clk/qcom/dispcc-sc8280xp.c b/drivers/clk/qcom/dispcc-sc8280xp.c
new file mode 100644
index 000000000000..167470beb369
--- /dev/null
+++ b/drivers/clk/qcom/dispcc-sc8280xp.c
@@ -0,0 +1,3218 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022, Linaro Ltd.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/clock/qcom,dispcc-sc8280xp.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "clk-regmap-divider.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+/* Need to match the order of clocks in DT binding */
+enum {
+ DT_IFACE,
+ DT_BI_TCXO,
+ DT_SLEEP_CLK,
+ DT_DP0_PHY_PLL_LINK_CLK,
+ DT_DP0_PHY_PLL_VCO_DIV_CLK,
+ DT_DP1_PHY_PLL_LINK_CLK,
+ DT_DP1_PHY_PLL_VCO_DIV_CLK,
+ DT_DP2_PHY_PLL_LINK_CLK,
+ DT_DP2_PHY_PLL_VCO_DIV_CLK,
+ DT_DP3_PHY_PLL_LINK_CLK,
+ DT_DP3_PHY_PLL_VCO_DIV_CLK,
+ DT_DSI0_PHY_PLL_OUT_BYTECLK,
+ DT_DSI0_PHY_PLL_OUT_DSICLK,
+ DT_DSI1_PHY_PLL_OUT_BYTECLK,
+ DT_DSI1_PHY_PLL_OUT_DSICLK,
+};
+
+enum {
+ P_BI_TCXO,
+ P_DP0_PHY_PLL_LINK_CLK,
+ P_DP0_PHY_PLL_VCO_DIV_CLK,
+ P_DP1_PHY_PLL_LINK_CLK,
+ P_DP1_PHY_PLL_VCO_DIV_CLK,
+ P_DP2_PHY_PLL_LINK_CLK,
+ P_DP2_PHY_PLL_VCO_DIV_CLK,
+ P_DP3_PHY_PLL_LINK_CLK,
+ P_DP3_PHY_PLL_VCO_DIV_CLK,
+ P_DSI0_PHY_PLL_OUT_BYTECLK,
+ P_DSI0_PHY_PLL_OUT_DSICLK,
+ P_DSI1_PHY_PLL_OUT_BYTECLK,
+ P_DSI1_PHY_PLL_OUT_DSICLK,
+ P_DISPn_CC_PLL0_OUT_MAIN,
+ P_DISPn_CC_PLL1_OUT_EVEN,
+ P_DISPn_CC_PLL1_OUT_MAIN,
+ P_DISPn_CC_PLL2_OUT_MAIN,
+ P_SLEEP_CLK,
+};
+
+static const struct clk_parent_data parent_data_tcxo = { .index = DT_BI_TCXO };
+
+static const struct pll_vco lucid_5lpe_vco[] = {
+ { 249600000, 1800000000, 0 },
+};
+
+static const struct alpha_pll_config disp_cc_pll0_config = {
+ .l = 0x4e,
+ .alpha = 0x2000,
+ .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 disp0_cc_pll0 = {
+ .offset = 0x0,
+ .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 = "disp0_cc_pll0",
+ .parent_data = &parent_data_tcxo,
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_5lpe_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll disp1_cc_pll0 = {
+ .offset = 0x0,
+ .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 = "disp1_cc_pll0",
+ .parent_data = &parent_data_tcxo,
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_5lpe_ops,
+ },
+ },
+};
+
+static const struct alpha_pll_config disp_cc_pll1_config = {
+ .l = 0x1f,
+ .alpha = 0x4000,
+ .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 = 0x00000100,
+ .user_ctl_hi_val = 0x00000805,
+ .user_ctl_hi1_val = 0x00000000,
+};
+
+static struct clk_alpha_pll disp0_cc_pll1 = {
+ .offset = 0x1000,
+ .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 = "disp0_cc_pll1",
+ .parent_data = &parent_data_tcxo,
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_5lpe_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll disp1_cc_pll1 = {
+ .offset = 0x1000,
+ .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 = "disp1_cc_pll1",
+ .parent_data = &parent_data_tcxo,
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_5lpe_ops,
+ },
+ },
+};
+
+static const struct clk_div_table post_div_table_disp_cc_pll1_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv disp0_cc_pll1_out_even = {
+ .offset = 0x1000,
+ .post_div_shift = 8,
+ .post_div_table = post_div_table_disp_cc_pll1_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_disp_cc_pll1_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_pll1_out_even",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_pll1.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_lucid_5lpe_ops,
+ },
+};
+
+static struct clk_alpha_pll_postdiv disp1_cc_pll1_out_even = {
+ .offset = 0x1000,
+ .post_div_shift = 8,
+ .post_div_table = post_div_table_disp_cc_pll1_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_disp_cc_pll1_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_pll1_out_even",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_pll1.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_lucid_5lpe_ops,
+ },
+};
+
+static const struct alpha_pll_config disp_cc_pll2_config = {
+ .l = 0x46,
+ .alpha = 0x5000,
+ .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 disp0_cc_pll2 = {
+ .offset = 0x9000,
+ .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 = "disp0_cc_pll2",
+ .parent_data = &parent_data_tcxo,
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_5lpe_ops,
+ },
+ },
+};
+
+static struct clk_alpha_pll disp1_cc_pll2 = {
+ .offset = 0x9000,
+ .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 = "disp1_cc_pll2",
+ .parent_data = &parent_data_tcxo,
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_5lpe_ops,
+ },
+ },
+};
+
+static const struct parent_map disp_cc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_DP0_PHY_PLL_LINK_CLK, 1 },
+ { P_DP1_PHY_PLL_LINK_CLK, 2 },
+ { P_DP2_PHY_PLL_LINK_CLK, 3 },
+ { P_DP3_PHY_PLL_LINK_CLK, 4 },
+ { P_DISPn_CC_PLL2_OUT_MAIN, 5 },
+};
+
+static const struct clk_parent_data disp0_cc_parent_data_0[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_DP0_PHY_PLL_LINK_CLK },
+ { .index = DT_DP1_PHY_PLL_LINK_CLK },
+ { .index = DT_DP2_PHY_PLL_LINK_CLK },
+ { .index = DT_DP3_PHY_PLL_LINK_CLK },
+ { .hw = &disp0_cc_pll2.clkr.hw },
+};
+
+static const struct clk_parent_data disp1_cc_parent_data_0[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_DP0_PHY_PLL_LINK_CLK },
+ { .index = DT_DP1_PHY_PLL_LINK_CLK },
+ { .index = DT_DP2_PHY_PLL_LINK_CLK },
+ { .index = DT_DP3_PHY_PLL_LINK_CLK },
+ { .hw = &disp1_cc_pll2.clkr.hw },
+};
+
+static const struct parent_map disp_cc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_DP0_PHY_PLL_LINK_CLK, 1 },
+ { P_DP0_PHY_PLL_VCO_DIV_CLK, 2 },
+ { P_DP3_PHY_PLL_VCO_DIV_CLK, 3 },
+ { P_DP1_PHY_PLL_VCO_DIV_CLK, 4 },
+ { P_DISPn_CC_PLL2_OUT_MAIN, 5 },
+ { P_DP2_PHY_PLL_VCO_DIV_CLK, 6 },
+};
+
+static const struct clk_parent_data disp0_cc_parent_data_1[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_DP0_PHY_PLL_LINK_CLK },
+ { .index = DT_DP0_PHY_PLL_VCO_DIV_CLK },
+ { .index = DT_DP3_PHY_PLL_VCO_DIV_CLK },
+ { .index = DT_DP1_PHY_PLL_VCO_DIV_CLK },
+ { .hw = &disp0_cc_pll2.clkr.hw },
+ { .index = DT_DP2_PHY_PLL_VCO_DIV_CLK },
+};
+
+static const struct clk_parent_data disp1_cc_parent_data_1[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_DP0_PHY_PLL_LINK_CLK },
+ { .index = DT_DP0_PHY_PLL_VCO_DIV_CLK },
+ { .index = DT_DP3_PHY_PLL_VCO_DIV_CLK },
+ { .index = DT_DP1_PHY_PLL_VCO_DIV_CLK },
+ { .hw = &disp1_cc_pll2.clkr.hw },
+ { .index = DT_DP2_PHY_PLL_VCO_DIV_CLK },
+};
+
+static const struct parent_map disp_cc_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_2[] = {
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map disp_cc_parent_map_3[] = {
+ { P_BI_TCXO, 0 },
+ { P_DSI0_PHY_PLL_OUT_DSICLK, 1 },
+ { P_DSI0_PHY_PLL_OUT_BYTECLK, 2 },
+ { P_DSI1_PHY_PLL_OUT_DSICLK, 3 },
+ { P_DSI1_PHY_PLL_OUT_BYTECLK, 4 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_3[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_DSI0_PHY_PLL_OUT_DSICLK },
+ { .index = DT_DSI0_PHY_PLL_OUT_BYTECLK },
+ { .index = DT_DSI1_PHY_PLL_OUT_DSICLK },
+ { .index = DT_DSI1_PHY_PLL_OUT_BYTECLK },
+};
+
+static const struct parent_map disp_cc_parent_map_4[] = {
+ { P_BI_TCXO, 0 },
+ { P_DSI0_PHY_PLL_OUT_BYTECLK, 2 },
+ { P_DSI1_PHY_PLL_OUT_BYTECLK, 4 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_4[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_DSI0_PHY_PLL_OUT_BYTECLK },
+ { .index = DT_DSI1_PHY_PLL_OUT_BYTECLK },
+};
+
+static const struct parent_map disp_cc_parent_map_5[] = {
+ { P_BI_TCXO, 0 },
+ { P_DISPn_CC_PLL0_OUT_MAIN, 1 },
+ { P_DISPn_CC_PLL1_OUT_MAIN, 4 },
+ { P_DISPn_CC_PLL2_OUT_MAIN, 5 },
+ { P_DISPn_CC_PLL1_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data disp0_cc_parent_data_5[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &disp0_cc_pll0.clkr.hw },
+ { .hw = &disp0_cc_pll1.clkr.hw },
+ { .hw = &disp0_cc_pll2.clkr.hw },
+ { .hw = &disp0_cc_pll1_out_even.clkr.hw },
+};
+
+static const struct clk_parent_data disp1_cc_parent_data_5[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &disp1_cc_pll0.clkr.hw },
+ { .hw = &disp1_cc_pll1.clkr.hw },
+ { .hw = &disp1_cc_pll2.clkr.hw },
+ { .hw = &disp1_cc_pll1_out_even.clkr.hw },
+};
+
+static const struct parent_map disp_cc_parent_map_6[] = {
+ { P_BI_TCXO, 0 },
+ { P_DISPn_CC_PLL1_OUT_MAIN, 4 },
+ { P_DISPn_CC_PLL1_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data disp0_cc_parent_data_6[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &disp0_cc_pll1.clkr.hw },
+ { .hw = &disp0_cc_pll1_out_even.clkr.hw },
+};
+
+static const struct clk_parent_data disp1_cc_parent_data_6[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &disp1_cc_pll1.clkr.hw },
+ { .hw = &disp1_cc_pll1_out_even.clkr.hw },
+};
+
+static const struct parent_map disp_cc_parent_map_7[] = {
+ { P_SLEEP_CLK, 0 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_7[] = {
+ { .index = DT_SLEEP_CLK },
+};
+
+static const struct freq_tbl ftbl_disp_cc_mdss_ahb_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(37500000, P_DISPn_CC_PLL1_OUT_EVEN, 8, 0, 0),
+ F(75000000, P_DISPn_CC_PLL1_OUT_MAIN, 8, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 disp0_cc_mdss_ahb_clk_src = {
+ .cmd_rcgr = 0x2364,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_6,
+ .freq_tbl = ftbl_disp_cc_mdss_ahb_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_ahb_clk_src",
+ .parent_data = disp0_cc_parent_data_6,
+ .num_parents = ARRAY_SIZE(disp0_cc_parent_data_6),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_ahb_clk_src = {
+ .cmd_rcgr = 0x2364,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_6,
+ .freq_tbl = ftbl_disp_cc_mdss_ahb_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_ahb_clk_src",
+ .parent_data = disp1_cc_parent_data_6,
+ .num_parents = ARRAY_SIZE(disp1_cc_parent_data_6),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_disp_cc_mdss_byte0_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 disp0_cc_mdss_byte0_clk_src = {
+ .cmd_rcgr = 0x213c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_byte0_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_byte0_clk_src = {
+ .cmd_rcgr = 0x213c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_byte0_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_byte1_clk_src = {
+ .cmd_rcgr = 0x2158,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_byte1_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_byte1_clk_src = {
+ .cmd_rcgr = 0x2158,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_byte1_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_dptx0_aux_clk_src = {
+ .cmd_rcgr = 0x2238,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_2,
+ .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx0_aux_clk_src",
+ .parent_data = disp_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_dptx0_aux_clk_src = {
+ .cmd_rcgr = 0x2238,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_2,
+ .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx0_aux_clk_src",
+ .parent_data = disp_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_dptx0_link_clk_src = {
+ .cmd_rcgr = 0x21a4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_0,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx0_link_clk_src",
+ .parent_data = disp0_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp0_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_dptx0_link_clk_src = {
+ .cmd_rcgr = 0x21a4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_0,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx0_link_clk_src",
+ .parent_data = disp1_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp1_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_dptx0_pixel0_clk_src = {
+ .cmd_rcgr = 0x21d8,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_1,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx0_pixel0_clk_src",
+ .parent_data = disp0_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp0_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_dptx0_pixel0_clk_src = {
+ .cmd_rcgr = 0x21d8,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_1,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx0_pixel0_clk_src",
+ .parent_data = disp1_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp1_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_dptx0_pixel1_clk_src = {
+ .cmd_rcgr = 0x21f0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_1,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx0_pixel1_clk_src",
+ .parent_data = disp0_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp0_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_dptx0_pixel1_clk_src = {
+ .cmd_rcgr = 0x21f0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_1,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx0_pixel1_clk_src",
+ .parent_data = disp1_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp1_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_dptx1_aux_clk_src = {
+ .cmd_rcgr = 0x22d0,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_2,
+ .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx1_aux_clk_src",
+ .parent_data = disp_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_dptx1_aux_clk_src = {
+ .cmd_rcgr = 0x22d0,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_2,
+ .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx1_aux_clk_src",
+ .parent_data = disp_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_dptx1_link_clk_src = {
+ .cmd_rcgr = 0x2268,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_0,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx1_link_clk_src",
+ .parent_data = disp0_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp0_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_dptx1_link_clk_src = {
+ .cmd_rcgr = 0x2268,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_0,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx1_link_clk_src",
+ .parent_data = disp1_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp1_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_dptx1_pixel0_clk_src = {
+ .cmd_rcgr = 0x2250,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_1,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx1_pixel0_clk_src",
+ .parent_data = disp0_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp0_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_dptx1_pixel0_clk_src = {
+ .cmd_rcgr = 0x2250,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_1,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx1_pixel0_clk_src",
+ .parent_data = disp1_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp1_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_dptx1_pixel1_clk_src = {
+ .cmd_rcgr = 0x2370,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_1,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx1_pixel1_clk_src",
+ .parent_data = disp0_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp0_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_dptx1_pixel1_clk_src = {
+ .cmd_rcgr = 0x2370,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_1,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx1_pixel1_clk_src",
+ .parent_data = disp1_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp1_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_dptx2_aux_clk_src = {
+ .cmd_rcgr = 0x22e8,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_2,
+ .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx2_aux_clk_src",
+ .parent_data = disp_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_dptx2_aux_clk_src = {
+ .cmd_rcgr = 0x22e8,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_2,
+ .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx2_aux_clk_src",
+ .parent_data = disp_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_dptx2_link_clk_src = {
+ .cmd_rcgr = 0x2284,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_0,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx2_link_clk_src",
+ .parent_data = disp0_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp0_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_dptx2_link_clk_src = {
+ .cmd_rcgr = 0x2284,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_0,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx2_link_clk_src",
+ .parent_data = disp1_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp1_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_dptx2_pixel0_clk_src = {
+ .cmd_rcgr = 0x2208,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_1,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx2_pixel0_clk_src",
+ .parent_data = disp0_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp0_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_dptx2_pixel0_clk_src = {
+ .cmd_rcgr = 0x2208,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_1,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx2_pixel0_clk_src",
+ .parent_data = disp1_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp1_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_dptx2_pixel1_clk_src = {
+ .cmd_rcgr = 0x2220,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_1,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx2_pixel1_clk_src",
+ .parent_data = disp0_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp0_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_dptx2_pixel1_clk_src = {
+ .cmd_rcgr = 0x2220,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_1,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx2_pixel1_clk_src",
+ .parent_data = disp1_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp1_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_dptx3_aux_clk_src = {
+ .cmd_rcgr = 0x234c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_2,
+ .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx3_aux_clk_src",
+ .parent_data = disp_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_dptx3_aux_clk_src = {
+ .cmd_rcgr = 0x234c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_2,
+ .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx3_aux_clk_src",
+ .parent_data = disp_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_dptx3_link_clk_src = {
+ .cmd_rcgr = 0x2318,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_0,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx3_link_clk_src",
+ .parent_data = disp0_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp0_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_dptx3_link_clk_src = {
+ .cmd_rcgr = 0x2318,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_0,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx3_link_clk_src",
+ .parent_data = disp1_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp1_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_dptx3_pixel0_clk_src = {
+ .cmd_rcgr = 0x2300,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_1,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx3_pixel0_clk_src",
+ .parent_data = disp0_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp0_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_dptx3_pixel0_clk_src = {
+ .cmd_rcgr = 0x2300,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_1,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx3_pixel0_clk_src",
+ .parent_data = disp1_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp1_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_dp_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_esc0_clk_src = {
+ .cmd_rcgr = 0x2174,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_4,
+ .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_esc0_clk_src",
+ .parent_data = disp_cc_parent_data_4,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_4),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_esc0_clk_src = {
+ .cmd_rcgr = 0x2174,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_4,
+ .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_esc0_clk_src",
+ .parent_data = disp_cc_parent_data_4,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_4),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_esc1_clk_src = {
+ .cmd_rcgr = 0x218c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_4,
+ .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_esc1_clk_src",
+ .parent_data = disp_cc_parent_data_4,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_4),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_esc1_clk_src = {
+ .cmd_rcgr = 0x218c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_4,
+ .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_esc1_clk_src",
+ .parent_data = disp_cc_parent_data_4,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_4),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(85714286, P_DISPn_CC_PLL1_OUT_MAIN, 7, 0, 0),
+ F(100000000, P_DISPn_CC_PLL1_OUT_MAIN, 6, 0, 0),
+ F(150000000, P_DISPn_CC_PLL1_OUT_MAIN, 4, 0, 0),
+ F(200000000, P_DISPn_CC_PLL1_OUT_MAIN, 3, 0, 0),
+ F(300000000, P_DISPn_CC_PLL1_OUT_MAIN, 2, 0, 0),
+ F(375000000, P_DISPn_CC_PLL0_OUT_MAIN, 4, 0, 0),
+ F(500000000, P_DISPn_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ F(600000000, P_DISPn_CC_PLL1_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 disp0_cc_mdss_mdp_clk_src = {
+ .cmd_rcgr = 0x20f4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_5,
+ .freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_mdp_clk_src",
+ .parent_data = disp0_cc_parent_data_5,
+ .num_parents = ARRAY_SIZE(disp0_cc_parent_data_5),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_mdp_clk_src = {
+ .cmd_rcgr = 0x20f4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_5,
+ .freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_mdp_clk_src",
+ .parent_data = disp1_cc_parent_data_5,
+ .num_parents = ARRAY_SIZE(disp1_cc_parent_data_5),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_pclk0_clk_src = {
+ .cmd_rcgr = 0x20c4,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_pclk0_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_pixel_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_pclk0_clk_src = {
+ .cmd_rcgr = 0x20c4,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_pclk0_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_pixel_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_pclk1_clk_src = {
+ .cmd_rcgr = 0x20dc,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_pclk1_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_pixel_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_pclk1_clk_src = {
+ .cmd_rcgr = 0x20dc,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_pclk1_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_pixel_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_disp_cc_mdss_rot_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(200000000, P_DISPn_CC_PLL1_OUT_MAIN, 3, 0, 0),
+ F(300000000, P_DISPn_CC_PLL1_OUT_MAIN, 2, 0, 0),
+ F(375000000, P_DISPn_CC_PLL0_OUT_MAIN, 4, 0, 0),
+ F(500000000, P_DISPn_CC_PLL0_OUT_MAIN, 3, 0, 0),
+ F(600000000, P_DISPn_CC_PLL1_OUT_MAIN, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 disp0_cc_mdss_rot_clk_src = {
+ .cmd_rcgr = 0x210c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_5,
+ .freq_tbl = ftbl_disp_cc_mdss_rot_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_rot_clk_src",
+ .parent_data = disp0_cc_parent_data_5,
+ .num_parents = ARRAY_SIZE(disp0_cc_parent_data_5),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_rot_clk_src = {
+ .cmd_rcgr = 0x210c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_5,
+ .freq_tbl = ftbl_disp_cc_mdss_rot_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_rot_clk_src",
+ .parent_data = disp1_cc_parent_data_5,
+ .num_parents = ARRAY_SIZE(disp1_cc_parent_data_5),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 disp0_cc_mdss_vsync_clk_src = {
+ .cmd_rcgr = 0x2124,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_2,
+ .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_vsync_clk_src",
+ .parent_data = disp_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_mdss_vsync_clk_src = {
+ .cmd_rcgr = 0x2124,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_2,
+ .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_vsync_clk_src",
+ .parent_data = disp_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_2),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_disp_cc_sleep_clk_src[] = {
+ F(32000, P_SLEEP_CLK, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 disp0_cc_sleep_clk_src = {
+ .cmd_rcgr = 0x6060,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_7,
+ .freq_tbl = ftbl_disp_cc_sleep_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_sleep_clk_src",
+ .parent_data = disp_cc_parent_data_7,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_7),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 disp1_cc_sleep_clk_src = {
+ .cmd_rcgr = 0x6060,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_7,
+ .freq_tbl = ftbl_disp_cc_sleep_clk_src,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_sleep_clk_src",
+ .parent_data = disp_cc_parent_data_7,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_7),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_regmap_div disp0_cc_mdss_byte0_div_clk_src = {
+ .reg = 0x2154,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_byte0_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_byte0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ops,
+ },
+};
+
+static struct clk_regmap_div disp1_cc_mdss_byte0_div_clk_src = {
+ .reg = 0x2154,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_byte0_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_byte0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ops,
+ },
+};
+
+static struct clk_regmap_div disp0_cc_mdss_byte1_div_clk_src = {
+ .reg = 0x2170,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_byte1_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_byte1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ops,
+ },
+};
+
+static struct clk_regmap_div disp1_cc_mdss_byte1_div_clk_src = {
+ .reg = 0x2170,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_byte1_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_byte1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ops,
+ },
+};
+
+static struct clk_regmap_div disp0_cc_mdss_dptx0_link_div_clk_src = {
+ .reg = 0x21bc,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx0_link_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx0_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div disp1_cc_mdss_dptx0_link_div_clk_src = {
+ .reg = 0x21bc,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx0_link_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx0_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div disp0_cc_mdss_dptx1_link_div_clk_src = {
+ .reg = 0x2280,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx1_link_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx1_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div disp1_cc_mdss_dptx1_link_div_clk_src = {
+ .reg = 0x2280,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx1_link_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx1_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div disp0_cc_mdss_dptx2_link_div_clk_src = {
+ .reg = 0x229c,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx2_link_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx2_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div disp1_cc_mdss_dptx2_link_div_clk_src = {
+ .reg = 0x229c,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx2_link_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx2_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div disp0_cc_mdss_dptx3_link_div_clk_src = {
+ .reg = 0x2330,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx3_link_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx3_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_regmap_div disp1_cc_mdss_dptx3_link_div_clk_src = {
+ .reg = 0x2330,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx3_link_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx3_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_ahb1_clk = {
+ .halt_reg = 0x20c0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20c0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_ahb1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_ahb1_clk = {
+ .halt_reg = 0x20c0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20c0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_ahb1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_ahb_clk = {
+ .halt_reg = 0x20bc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20bc,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_ahb_clk = {
+ .halt_reg = 0x20bc,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20bc,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_byte0_clk = {
+ .halt_reg = 0x2044,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2044,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_byte0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_byte0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_byte0_clk = {
+ .halt_reg = 0x2044,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2044,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_byte0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_byte0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_byte0_intf_clk = {
+ .halt_reg = 0x2048,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2048,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_byte0_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_byte0_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_byte0_intf_clk = {
+ .halt_reg = 0x2048,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2048,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_byte0_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_byte0_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_byte1_clk = {
+ .halt_reg = 0x204c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x204c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_byte1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_byte1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_byte1_clk = {
+ .halt_reg = 0x204c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x204c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_byte1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_byte1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_byte1_intf_clk = {
+ .halt_reg = 0x2050,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2050,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_byte1_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_byte1_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_byte1_intf_clk = {
+ .halt_reg = 0x2050,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2050,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_byte1_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_byte1_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx0_aux_clk = {
+ .halt_reg = 0x206c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x206c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx0_aux_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx0_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx0_aux_clk = {
+ .halt_reg = 0x206c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x206c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx0_aux_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx0_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx0_link_clk = {
+ .halt_reg = 0x205c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x205c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx0_link_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx0_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx0_link_clk = {
+ .halt_reg = 0x205c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x205c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx0_link_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx0_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx0_link_intf_clk = {
+ .halt_reg = 0x2060,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2060,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx0_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx0_link_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx0_link_intf_clk = {
+ .halt_reg = 0x2060,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2060,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx0_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx0_link_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx0_pixel0_clk = {
+ .halt_reg = 0x2070,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2070,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx0_pixel0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx0_pixel0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx0_pixel0_clk = {
+ .halt_reg = 0x2070,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2070,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx0_pixel0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx0_pixel0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx0_pixel1_clk = {
+ .halt_reg = 0x2074,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2074,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx0_pixel1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx0_pixel1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx0_pixel1_clk = {
+ .halt_reg = 0x2074,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2074,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx0_pixel1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx0_pixel1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx0_usb_router_link_intf_clk = {
+ .halt_reg = 0x2064,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2064,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx0_usb_router_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx0_link_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx0_usb_router_link_intf_clk = {
+ .halt_reg = 0x2064,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2064,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx0_usb_router_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx0_link_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx1_aux_clk = {
+ .halt_reg = 0x20a0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20a0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx1_aux_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx1_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx1_aux_clk = {
+ .halt_reg = 0x20a0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20a0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx1_aux_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx1_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx1_link_clk = {
+ .halt_reg = 0x2084,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2084,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx1_link_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx1_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx1_link_clk = {
+ .halt_reg = 0x2084,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2084,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx1_link_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx1_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx1_link_intf_clk = {
+ .halt_reg = 0x2088,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2088,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx1_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx1_link_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx1_link_intf_clk = {
+ .halt_reg = 0x2088,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2088,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx1_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx1_link_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx1_pixel0_clk = {
+ .halt_reg = 0x2078,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2078,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx1_pixel0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx1_pixel0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx1_pixel0_clk = {
+ .halt_reg = 0x2078,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2078,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx1_pixel0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx1_pixel0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx1_pixel1_clk = {
+ .halt_reg = 0x236c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x236c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx1_pixel1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx1_pixel1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx1_pixel1_clk = {
+ .halt_reg = 0x236c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x236c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx1_pixel1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx1_pixel1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx1_usb_router_link_intf_clk = {
+ .halt_reg = 0x208c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x208c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx1_usb_router_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx1_link_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx1_usb_router_link_intf_clk = {
+ .halt_reg = 0x208c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x208c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx1_usb_router_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx1_link_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx2_aux_clk = {
+ .halt_reg = 0x20a4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20a4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx2_aux_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx2_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx2_aux_clk = {
+ .halt_reg = 0x20a4,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20a4,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx2_aux_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx2_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx2_link_clk = {
+ .halt_reg = 0x2090,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2090,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx2_link_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx2_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx2_link_clk = {
+ .halt_reg = 0x2090,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2090,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx2_link_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx2_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx2_link_intf_clk = {
+ .halt_reg = 0x2094,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2094,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx2_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx2_link_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx2_link_intf_clk = {
+ .halt_reg = 0x2094,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2094,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx2_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx2_link_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx2_pixel0_clk = {
+ .halt_reg = 0x207c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x207c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx2_pixel0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx2_pixel0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx2_pixel0_clk = {
+ .halt_reg = 0x207c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x207c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx2_pixel0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx2_pixel0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx2_pixel1_clk = {
+ .halt_reg = 0x2080,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2080,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx2_pixel1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx2_pixel1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx2_pixel1_clk = {
+ .halt_reg = 0x2080,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2080,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx2_pixel1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx2_pixel1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx3_aux_clk = {
+ .halt_reg = 0x20b8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20b8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx3_aux_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx3_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx3_aux_clk = {
+ .halt_reg = 0x20b8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20b8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx3_aux_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx3_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx3_link_clk = {
+ .halt_reg = 0x20ac,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20ac,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx3_link_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx3_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx3_link_clk = {
+ .halt_reg = 0x20ac,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20ac,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx3_link_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx3_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx3_link_intf_clk = {
+ .halt_reg = 0x20b0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20b0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx3_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx3_link_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx3_link_intf_clk = {
+ .halt_reg = 0x20b0,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20b0,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx3_link_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx3_link_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_dptx3_pixel0_clk = {
+ .halt_reg = 0x20a8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20a8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_dptx3_pixel0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_dptx3_pixel0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_dptx3_pixel0_clk = {
+ .halt_reg = 0x20a8,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x20a8,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_dptx3_pixel0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_dptx3_pixel0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_esc0_clk = {
+ .halt_reg = 0x2054,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2054,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_esc0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_esc0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_esc0_clk = {
+ .halt_reg = 0x2054,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2054,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_esc0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_esc0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_esc1_clk = {
+ .halt_reg = 0x2058,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2058,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_esc1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_esc1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_esc1_clk = {
+ .halt_reg = 0x2058,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2058,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_esc1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_esc1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_mdp1_clk = {
+ .halt_reg = 0x2014,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2014,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_mdp1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_mdp1_clk = {
+ .halt_reg = 0x2014,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2014,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_mdp1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_mdp_clk = {
+ .halt_reg = 0x200c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x200c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_mdp_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_mdp_clk = {
+ .halt_reg = 0x200c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x200c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_mdp_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_mdp_lut1_clk = {
+ .halt_reg = 0x2034,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2034,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_mdp_lut1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_mdp_lut1_clk = {
+ .halt_reg = 0x2034,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2034,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_mdp_lut1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_mdp_lut_clk = {
+ .halt_reg = 0x202c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x202c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_mdp_lut_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_mdp_lut_clk = {
+ .halt_reg = 0x202c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x202c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_mdp_lut_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_non_gdsc_ahb_clk = {
+ .halt_reg = 0x4004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_non_gdsc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_non_gdsc_ahb_clk = {
+ .halt_reg = 0x4004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x4004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_non_gdsc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_pclk0_clk = {
+ .halt_reg = 0x2004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_pclk0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_pclk0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_pclk0_clk = {
+ .halt_reg = 0x2004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2004,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_pclk0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_pclk0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_pclk1_clk = {
+ .halt_reg = 0x2008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_pclk1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_pclk1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_pclk1_clk = {
+ .halt_reg = 0x2008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_pclk1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_pclk1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_rot1_clk = {
+ .halt_reg = 0x2024,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_rot1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_rot_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_rot1_clk = {
+ .halt_reg = 0x2024,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2024,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_rot1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_rot_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_rot_clk = {
+ .halt_reg = 0x201c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x201c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_rot_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_rot_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_rot_clk = {
+ .halt_reg = 0x201c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x201c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_rot_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_rot_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_rscc_ahb_clk = {
+ .halt_reg = 0x400c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x400c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_rscc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_rscc_ahb_clk = {
+ .halt_reg = 0x400c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x400c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_rscc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_rscc_vsync_clk = {
+ .halt_reg = 0x4008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_rscc_vsync_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_vsync_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_rscc_vsync_clk = {
+ .halt_reg = 0x4008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x4008,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_rscc_vsync_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_vsync_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_vsync1_clk = {
+ .halt_reg = 0x2040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2040,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_vsync1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_vsync_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_vsync1_clk = {
+ .halt_reg = 0x2040,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2040,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_vsync1_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_vsync_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_mdss_vsync_clk = {
+ .halt_reg = 0x203c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x203c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_mdss_vsync_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_mdss_vsync_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_mdss_vsync_clk = {
+ .halt_reg = 0x203c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x203c,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_mdss_vsync_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_mdss_vsync_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp0_cc_sleep_clk = {
+ .halt_reg = 0x6078,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x6078,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp0_cc_sleep_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp0_cc_sleep_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp1_cc_sleep_clk = {
+ .halt_reg = 0x6078,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x6078,
+ .enable_mask = BIT(0),
+ .hw.init = &(const struct clk_init_data) {
+ .name = "disp1_cc_sleep_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp1_cc_sleep_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_regmap *disp0_cc_sc8280xp_clocks[] = {
+ [DISP_CC_MDSS_AHB1_CLK] = &disp0_cc_mdss_ahb1_clk.clkr,
+ [DISP_CC_MDSS_AHB_CLK] = &disp0_cc_mdss_ahb_clk.clkr,
+ [DISP_CC_MDSS_AHB_CLK_SRC] = &disp0_cc_mdss_ahb_clk_src.clkr,
+ [DISP_CC_MDSS_BYTE0_CLK] = &disp0_cc_mdss_byte0_clk.clkr,
+ [DISP_CC_MDSS_BYTE0_CLK_SRC] = &disp0_cc_mdss_byte0_clk_src.clkr,
+ [DISP_CC_MDSS_BYTE0_DIV_CLK_SRC] = &disp0_cc_mdss_byte0_div_clk_src.clkr,
+ [DISP_CC_MDSS_BYTE0_INTF_CLK] = &disp0_cc_mdss_byte0_intf_clk.clkr,
+ [DISP_CC_MDSS_BYTE1_CLK] = &disp0_cc_mdss_byte1_clk.clkr,
+ [DISP_CC_MDSS_BYTE1_CLK_SRC] = &disp0_cc_mdss_byte1_clk_src.clkr,
+ [DISP_CC_MDSS_BYTE1_DIV_CLK_SRC] = &disp0_cc_mdss_byte1_div_clk_src.clkr,
+ [DISP_CC_MDSS_BYTE1_INTF_CLK] = &disp0_cc_mdss_byte1_intf_clk.clkr,
+ [DISP_CC_MDSS_DPTX0_AUX_CLK] = &disp0_cc_mdss_dptx0_aux_clk.clkr,
+ [DISP_CC_MDSS_DPTX0_AUX_CLK_SRC] = &disp0_cc_mdss_dptx0_aux_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX0_LINK_CLK] = &disp0_cc_mdss_dptx0_link_clk.clkr,
+ [DISP_CC_MDSS_DPTX0_LINK_CLK_SRC] = &disp0_cc_mdss_dptx0_link_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX0_LINK_DIV_CLK_SRC] = &disp0_cc_mdss_dptx0_link_div_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX0_LINK_INTF_CLK] = &disp0_cc_mdss_dptx0_link_intf_clk.clkr,
+ [DISP_CC_MDSS_DPTX0_PIXEL0_CLK] = &disp0_cc_mdss_dptx0_pixel0_clk.clkr,
+ [DISP_CC_MDSS_DPTX0_PIXEL0_CLK_SRC] = &disp0_cc_mdss_dptx0_pixel0_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX0_PIXEL1_CLK] = &disp0_cc_mdss_dptx0_pixel1_clk.clkr,
+ [DISP_CC_MDSS_DPTX0_PIXEL1_CLK_SRC] = &disp0_cc_mdss_dptx0_pixel1_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX0_USB_ROUTER_LINK_INTF_CLK] = &disp0_cc_mdss_dptx0_usb_router_link_intf_clk.clkr,
+ [DISP_CC_MDSS_DPTX1_AUX_CLK] = &disp0_cc_mdss_dptx1_aux_clk.clkr,
+ [DISP_CC_MDSS_DPTX1_AUX_CLK_SRC] = &disp0_cc_mdss_dptx1_aux_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX1_LINK_CLK] = &disp0_cc_mdss_dptx1_link_clk.clkr,
+ [DISP_CC_MDSS_DPTX1_LINK_CLK_SRC] = &disp0_cc_mdss_dptx1_link_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX1_LINK_DIV_CLK_SRC] = &disp0_cc_mdss_dptx1_link_div_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX1_LINK_INTF_CLK] = &disp0_cc_mdss_dptx1_link_intf_clk.clkr,
+ [DISP_CC_MDSS_DPTX1_PIXEL0_CLK] = &disp0_cc_mdss_dptx1_pixel0_clk.clkr,
+ [DISP_CC_MDSS_DPTX1_PIXEL0_CLK_SRC] = &disp0_cc_mdss_dptx1_pixel0_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX1_PIXEL1_CLK] = &disp0_cc_mdss_dptx1_pixel1_clk.clkr,
+ [DISP_CC_MDSS_DPTX1_PIXEL1_CLK_SRC] = &disp0_cc_mdss_dptx1_pixel1_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX1_USB_ROUTER_LINK_INTF_CLK] = &disp0_cc_mdss_dptx1_usb_router_link_intf_clk.clkr,
+ [DISP_CC_MDSS_DPTX2_AUX_CLK] = &disp0_cc_mdss_dptx2_aux_clk.clkr,
+ [DISP_CC_MDSS_DPTX2_AUX_CLK_SRC] = &disp0_cc_mdss_dptx2_aux_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX2_LINK_CLK] = &disp0_cc_mdss_dptx2_link_clk.clkr,
+ [DISP_CC_MDSS_DPTX2_LINK_CLK_SRC] = &disp0_cc_mdss_dptx2_link_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX2_LINK_DIV_CLK_SRC] = &disp0_cc_mdss_dptx2_link_div_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX2_LINK_INTF_CLK] = &disp0_cc_mdss_dptx2_link_intf_clk.clkr,
+ [DISP_CC_MDSS_DPTX2_PIXEL0_CLK] = &disp0_cc_mdss_dptx2_pixel0_clk.clkr,
+ [DISP_CC_MDSS_DPTX2_PIXEL0_CLK_SRC] = &disp0_cc_mdss_dptx2_pixel0_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX2_PIXEL1_CLK] = &disp0_cc_mdss_dptx2_pixel1_clk.clkr,
+ [DISP_CC_MDSS_DPTX2_PIXEL1_CLK_SRC] = &disp0_cc_mdss_dptx2_pixel1_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX3_AUX_CLK] = &disp0_cc_mdss_dptx3_aux_clk.clkr,
+ [DISP_CC_MDSS_DPTX3_AUX_CLK_SRC] = &disp0_cc_mdss_dptx3_aux_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX3_LINK_CLK] = &disp0_cc_mdss_dptx3_link_clk.clkr,
+ [DISP_CC_MDSS_DPTX3_LINK_CLK_SRC] = &disp0_cc_mdss_dptx3_link_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX3_LINK_DIV_CLK_SRC] = &disp0_cc_mdss_dptx3_link_div_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX3_LINK_INTF_CLK] = &disp0_cc_mdss_dptx3_link_intf_clk.clkr,
+ [DISP_CC_MDSS_DPTX3_PIXEL0_CLK] = &disp0_cc_mdss_dptx3_pixel0_clk.clkr,
+ [DISP_CC_MDSS_DPTX3_PIXEL0_CLK_SRC] = &disp0_cc_mdss_dptx3_pixel0_clk_src.clkr,
+ [DISP_CC_MDSS_ESC0_CLK] = &disp0_cc_mdss_esc0_clk.clkr,
+ [DISP_CC_MDSS_ESC0_CLK_SRC] = &disp0_cc_mdss_esc0_clk_src.clkr,
+ [DISP_CC_MDSS_ESC1_CLK] = &disp0_cc_mdss_esc1_clk.clkr,
+ [DISP_CC_MDSS_ESC1_CLK_SRC] = &disp0_cc_mdss_esc1_clk_src.clkr,
+ [DISP_CC_MDSS_MDP1_CLK] = &disp0_cc_mdss_mdp1_clk.clkr,
+ [DISP_CC_MDSS_MDP_CLK] = &disp0_cc_mdss_mdp_clk.clkr,
+ [DISP_CC_MDSS_MDP_CLK_SRC] = &disp0_cc_mdss_mdp_clk_src.clkr,
+ [DISP_CC_MDSS_MDP_LUT1_CLK] = &disp0_cc_mdss_mdp_lut1_clk.clkr,
+ [DISP_CC_MDSS_MDP_LUT_CLK] = &disp0_cc_mdss_mdp_lut_clk.clkr,
+ [DISP_CC_MDSS_NON_GDSC_AHB_CLK] = &disp0_cc_mdss_non_gdsc_ahb_clk.clkr,
+ [DISP_CC_MDSS_PCLK0_CLK] = &disp0_cc_mdss_pclk0_clk.clkr,
+ [DISP_CC_MDSS_PCLK0_CLK_SRC] = &disp0_cc_mdss_pclk0_clk_src.clkr,
+ [DISP_CC_MDSS_PCLK1_CLK] = &disp0_cc_mdss_pclk1_clk.clkr,
+ [DISP_CC_MDSS_PCLK1_CLK_SRC] = &disp0_cc_mdss_pclk1_clk_src.clkr,
+ [DISP_CC_MDSS_ROT1_CLK] = &disp0_cc_mdss_rot1_clk.clkr,
+ [DISP_CC_MDSS_ROT_CLK] = &disp0_cc_mdss_rot_clk.clkr,
+ [DISP_CC_MDSS_ROT_CLK_SRC] = &disp0_cc_mdss_rot_clk_src.clkr,
+ [DISP_CC_MDSS_RSCC_AHB_CLK] = &disp0_cc_mdss_rscc_ahb_clk.clkr,
+ [DISP_CC_MDSS_RSCC_VSYNC_CLK] = &disp0_cc_mdss_rscc_vsync_clk.clkr,
+ [DISP_CC_MDSS_VSYNC1_CLK] = &disp0_cc_mdss_vsync1_clk.clkr,
+ [DISP_CC_MDSS_VSYNC_CLK] = &disp0_cc_mdss_vsync_clk.clkr,
+ [DISP_CC_MDSS_VSYNC_CLK_SRC] = &disp0_cc_mdss_vsync_clk_src.clkr,
+ [DISP_CC_PLL0] = &disp0_cc_pll0.clkr,
+ [DISP_CC_PLL1] = &disp0_cc_pll1.clkr,
+ [DISP_CC_PLL1_OUT_EVEN] = &disp0_cc_pll1_out_even.clkr,
+ [DISP_CC_PLL2] = &disp0_cc_pll2.clkr,
+ [DISP_CC_SLEEP_CLK] = &disp0_cc_sleep_clk.clkr,
+ [DISP_CC_SLEEP_CLK_SRC] = &disp0_cc_sleep_clk_src.clkr,
+};
+
+static struct clk_regmap *disp1_cc_sc8280xp_clocks[] = {
+ [DISP_CC_MDSS_AHB1_CLK] = &disp1_cc_mdss_ahb1_clk.clkr,
+ [DISP_CC_MDSS_AHB_CLK] = &disp1_cc_mdss_ahb_clk.clkr,
+ [DISP_CC_MDSS_AHB_CLK_SRC] = &disp1_cc_mdss_ahb_clk_src.clkr,
+ [DISP_CC_MDSS_BYTE0_CLK] = &disp1_cc_mdss_byte0_clk.clkr,
+ [DISP_CC_MDSS_BYTE0_CLK_SRC] = &disp1_cc_mdss_byte0_clk_src.clkr,
+ [DISP_CC_MDSS_BYTE0_DIV_CLK_SRC] = &disp1_cc_mdss_byte0_div_clk_src.clkr,
+ [DISP_CC_MDSS_BYTE0_INTF_CLK] = &disp1_cc_mdss_byte0_intf_clk.clkr,
+ [DISP_CC_MDSS_BYTE1_CLK] = &disp1_cc_mdss_byte1_clk.clkr,
+ [DISP_CC_MDSS_BYTE1_CLK_SRC] = &disp1_cc_mdss_byte1_clk_src.clkr,
+ [DISP_CC_MDSS_BYTE1_DIV_CLK_SRC] = &disp1_cc_mdss_byte1_div_clk_src.clkr,
+ [DISP_CC_MDSS_BYTE1_INTF_CLK] = &disp1_cc_mdss_byte1_intf_clk.clkr,
+ [DISP_CC_MDSS_DPTX0_AUX_CLK] = &disp1_cc_mdss_dptx0_aux_clk.clkr,
+ [DISP_CC_MDSS_DPTX0_AUX_CLK_SRC] = &disp1_cc_mdss_dptx0_aux_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX0_LINK_CLK] = &disp1_cc_mdss_dptx0_link_clk.clkr,
+ [DISP_CC_MDSS_DPTX0_LINK_CLK_SRC] = &disp1_cc_mdss_dptx0_link_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX0_LINK_DIV_CLK_SRC] = &disp1_cc_mdss_dptx0_link_div_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX0_LINK_INTF_CLK] = &disp1_cc_mdss_dptx0_link_intf_clk.clkr,
+ [DISP_CC_MDSS_DPTX0_PIXEL0_CLK] = &disp1_cc_mdss_dptx0_pixel0_clk.clkr,
+ [DISP_CC_MDSS_DPTX0_PIXEL0_CLK_SRC] = &disp1_cc_mdss_dptx0_pixel0_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX0_PIXEL1_CLK] = &disp1_cc_mdss_dptx0_pixel1_clk.clkr,
+ [DISP_CC_MDSS_DPTX0_PIXEL1_CLK_SRC] = &disp1_cc_mdss_dptx0_pixel1_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX0_USB_ROUTER_LINK_INTF_CLK] = &disp1_cc_mdss_dptx0_usb_router_link_intf_clk.clkr,
+ [DISP_CC_MDSS_DPTX1_AUX_CLK] = &disp1_cc_mdss_dptx1_aux_clk.clkr,
+ [DISP_CC_MDSS_DPTX1_AUX_CLK_SRC] = &disp1_cc_mdss_dptx1_aux_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX1_LINK_CLK] = &disp1_cc_mdss_dptx1_link_clk.clkr,
+ [DISP_CC_MDSS_DPTX1_LINK_CLK_SRC] = &disp1_cc_mdss_dptx1_link_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX1_LINK_DIV_CLK_SRC] = &disp1_cc_mdss_dptx1_link_div_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX1_LINK_INTF_CLK] = &disp1_cc_mdss_dptx1_link_intf_clk.clkr,
+ [DISP_CC_MDSS_DPTX1_PIXEL0_CLK] = &disp1_cc_mdss_dptx1_pixel0_clk.clkr,
+ [DISP_CC_MDSS_DPTX1_PIXEL0_CLK_SRC] = &disp1_cc_mdss_dptx1_pixel0_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX1_PIXEL1_CLK] = &disp1_cc_mdss_dptx1_pixel1_clk.clkr,
+ [DISP_CC_MDSS_DPTX1_PIXEL1_CLK_SRC] = &disp1_cc_mdss_dptx1_pixel1_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX1_USB_ROUTER_LINK_INTF_CLK] = &disp1_cc_mdss_dptx1_usb_router_link_intf_clk.clkr,
+ [DISP_CC_MDSS_DPTX2_AUX_CLK] = &disp1_cc_mdss_dptx2_aux_clk.clkr,
+ [DISP_CC_MDSS_DPTX2_AUX_CLK_SRC] = &disp1_cc_mdss_dptx2_aux_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX2_LINK_CLK] = &disp1_cc_mdss_dptx2_link_clk.clkr,
+ [DISP_CC_MDSS_DPTX2_LINK_CLK_SRC] = &disp1_cc_mdss_dptx2_link_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX2_LINK_DIV_CLK_SRC] = &disp1_cc_mdss_dptx2_link_div_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX2_LINK_INTF_CLK] = &disp1_cc_mdss_dptx2_link_intf_clk.clkr,
+ [DISP_CC_MDSS_DPTX2_PIXEL0_CLK] = &disp1_cc_mdss_dptx2_pixel0_clk.clkr,
+ [DISP_CC_MDSS_DPTX2_PIXEL0_CLK_SRC] = &disp1_cc_mdss_dptx2_pixel0_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX2_PIXEL1_CLK] = &disp1_cc_mdss_dptx2_pixel1_clk.clkr,
+ [DISP_CC_MDSS_DPTX2_PIXEL1_CLK_SRC] = &disp1_cc_mdss_dptx2_pixel1_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX3_AUX_CLK] = &disp1_cc_mdss_dptx3_aux_clk.clkr,
+ [DISP_CC_MDSS_DPTX3_AUX_CLK_SRC] = &disp1_cc_mdss_dptx3_aux_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX3_LINK_CLK] = &disp1_cc_mdss_dptx3_link_clk.clkr,
+ [DISP_CC_MDSS_DPTX3_LINK_CLK_SRC] = &disp1_cc_mdss_dptx3_link_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX3_LINK_DIV_CLK_SRC] = &disp1_cc_mdss_dptx3_link_div_clk_src.clkr,
+ [DISP_CC_MDSS_DPTX3_LINK_INTF_CLK] = &disp1_cc_mdss_dptx3_link_intf_clk.clkr,
+ [DISP_CC_MDSS_DPTX3_PIXEL0_CLK] = &disp1_cc_mdss_dptx3_pixel0_clk.clkr,
+ [DISP_CC_MDSS_DPTX3_PIXEL0_CLK_SRC] = &disp1_cc_mdss_dptx3_pixel0_clk_src.clkr,
+ [DISP_CC_MDSS_ESC0_CLK] = &disp1_cc_mdss_esc0_clk.clkr,
+ [DISP_CC_MDSS_ESC0_CLK_SRC] = &disp1_cc_mdss_esc0_clk_src.clkr,
+ [DISP_CC_MDSS_ESC1_CLK] = &disp1_cc_mdss_esc1_clk.clkr,
+ [DISP_CC_MDSS_ESC1_CLK_SRC] = &disp1_cc_mdss_esc1_clk_src.clkr,
+ [DISP_CC_MDSS_MDP1_CLK] = &disp1_cc_mdss_mdp1_clk.clkr,
+ [DISP_CC_MDSS_MDP_CLK] = &disp1_cc_mdss_mdp_clk.clkr,
+ [DISP_CC_MDSS_MDP_CLK_SRC] = &disp1_cc_mdss_mdp_clk_src.clkr,
+ [DISP_CC_MDSS_MDP_LUT1_CLK] = &disp1_cc_mdss_mdp_lut1_clk.clkr,
+ [DISP_CC_MDSS_MDP_LUT_CLK] = &disp1_cc_mdss_mdp_lut_clk.clkr,
+ [DISP_CC_MDSS_NON_GDSC_AHB_CLK] = &disp1_cc_mdss_non_gdsc_ahb_clk.clkr,
+ [DISP_CC_MDSS_PCLK0_CLK] = &disp1_cc_mdss_pclk0_clk.clkr,
+ [DISP_CC_MDSS_PCLK0_CLK_SRC] = &disp1_cc_mdss_pclk0_clk_src.clkr,
+ [DISP_CC_MDSS_PCLK1_CLK] = &disp1_cc_mdss_pclk1_clk.clkr,
+ [DISP_CC_MDSS_PCLK1_CLK_SRC] = &disp1_cc_mdss_pclk1_clk_src.clkr,
+ [DISP_CC_MDSS_ROT1_CLK] = &disp1_cc_mdss_rot1_clk.clkr,
+ [DISP_CC_MDSS_ROT_CLK] = &disp1_cc_mdss_rot_clk.clkr,
+ [DISP_CC_MDSS_ROT_CLK_SRC] = &disp1_cc_mdss_rot_clk_src.clkr,
+ [DISP_CC_MDSS_RSCC_AHB_CLK] = &disp1_cc_mdss_rscc_ahb_clk.clkr,
+ [DISP_CC_MDSS_RSCC_VSYNC_CLK] = &disp1_cc_mdss_rscc_vsync_clk.clkr,
+ [DISP_CC_MDSS_VSYNC1_CLK] = &disp1_cc_mdss_vsync1_clk.clkr,
+ [DISP_CC_MDSS_VSYNC_CLK] = &disp1_cc_mdss_vsync_clk.clkr,
+ [DISP_CC_MDSS_VSYNC_CLK_SRC] = &disp1_cc_mdss_vsync_clk_src.clkr,
+ [DISP_CC_PLL0] = &disp1_cc_pll0.clkr,
+ [DISP_CC_PLL1] = &disp1_cc_pll1.clkr,
+ [DISP_CC_PLL1_OUT_EVEN] = &disp1_cc_pll1_out_even.clkr,
+ [DISP_CC_PLL2] = &disp1_cc_pll2.clkr,
+ [DISP_CC_SLEEP_CLK] = &disp1_cc_sleep_clk.clkr,
+ [DISP_CC_SLEEP_CLK_SRC] = &disp1_cc_sleep_clk_src.clkr,
+};
+
+static const struct qcom_reset_map disp_cc_sc8280xp_resets[] = {
+ [DISP_CC_MDSS_CORE_BCR] = { 0x2000 },
+ [DISP_CC_MDSS_RSCC_BCR] = { 0x4000 },
+};
+
+static struct gdsc disp0_mdss_gdsc = {
+ .gdscr = 0x3000,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "disp0_mdss_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = HW_CTRL,
+};
+
+static struct gdsc disp1_mdss_gdsc = {
+ .gdscr = 0x3000,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "disp1_mdss_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = HW_CTRL,
+};
+
+static struct gdsc disp0_mdss_int2_gdsc = {
+ .gdscr = 0xa000,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "disp0_mdss_int2_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = HW_CTRL,
+};
+
+static struct gdsc disp1_mdss_int2_gdsc = {
+ .gdscr = 0xa000,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "disp1_mdss_int2_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = HW_CTRL,
+};
+
+static struct gdsc *disp0_cc_sc8280xp_gdscs[] = {
+ [MDSS_GDSC] = &disp0_mdss_gdsc,
+ [MDSS_INT2_GDSC] = &disp0_mdss_int2_gdsc,
+};
+
+static struct gdsc *disp1_cc_sc8280xp_gdscs[] = {
+ [MDSS_GDSC] = &disp1_mdss_gdsc,
+ [MDSS_INT2_GDSC] = &disp1_mdss_int2_gdsc,
+};
+
+static const struct regmap_config disp_cc_sc8280xp_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x10000,
+ .fast_io = true,
+};
+
+static struct qcom_cc_desc disp0_cc_sc8280xp_desc = {
+ .config = &disp_cc_sc8280xp_regmap_config,
+ .clks = disp0_cc_sc8280xp_clocks,
+ .num_clks = ARRAY_SIZE(disp0_cc_sc8280xp_clocks),
+ .resets = disp_cc_sc8280xp_resets,
+ .num_resets = ARRAY_SIZE(disp_cc_sc8280xp_resets),
+ .gdscs = disp0_cc_sc8280xp_gdscs,
+ .num_gdscs = ARRAY_SIZE(disp0_cc_sc8280xp_gdscs),
+};
+
+static struct qcom_cc_desc disp1_cc_sc8280xp_desc = {
+ .config = &disp_cc_sc8280xp_regmap_config,
+ .clks = disp1_cc_sc8280xp_clocks,
+ .num_clks = ARRAY_SIZE(disp1_cc_sc8280xp_clocks),
+ .resets = disp_cc_sc8280xp_resets,
+ .num_resets = ARRAY_SIZE(disp_cc_sc8280xp_resets),
+ .gdscs = disp1_cc_sc8280xp_gdscs,
+ .num_gdscs = ARRAY_SIZE(disp1_cc_sc8280xp_gdscs),
+};
+
+#define clkr_to_alpha_clk_pll(_clkr) container_of(_clkr, struct clk_alpha_pll, clkr)
+
+static int disp_cc_sc8280xp_probe(struct platform_device *pdev)
+{
+ const struct qcom_cc_desc *desc;
+ struct regmap *regmap;
+ int ret;
+
+ desc = device_get_match_data(&pdev->dev);
+
+ ret = devm_pm_runtime_enable(&pdev->dev);
+ if (ret)
+ return ret;
+
+ ret = devm_pm_clk_create(&pdev->dev);
+ if (ret)
+ return ret;
+
+ ret = pm_clk_add(&pdev->dev, NULL);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to acquire ahb clock\n");
+ return ret;
+ }
+
+ ret = pm_runtime_resume_and_get(&pdev->dev);
+ if (ret)
+ return ret;
+
+ regmap = qcom_cc_map(pdev, desc);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ goto out_pm_runtime_put;
+ }
+
+ clk_lucid_pll_configure(clkr_to_alpha_clk_pll(desc->clks[DISP_CC_PLL0]), regmap, &disp_cc_pll0_config);
+ clk_lucid_pll_configure(clkr_to_alpha_clk_pll(desc->clks[DISP_CC_PLL1]), regmap, &disp_cc_pll1_config);
+ clk_lucid_pll_configure(clkr_to_alpha_clk_pll(desc->clks[DISP_CC_PLL2]), regmap, &disp_cc_pll2_config);
+
+ ret = qcom_cc_really_probe(pdev, desc, regmap);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to register display clock controller\n");
+ goto out_pm_runtime_put;
+ }
+
+ /* DISP_CC_XO_CLK always-on */
+ regmap_update_bits(regmap, 0x605c, BIT(0), BIT(0));
+
+out_pm_runtime_put:
+ pm_runtime_put_sync(&pdev->dev);
+
+ return ret;
+}
+
+static const struct of_device_id disp_cc_sc8280xp_match_table[] = {
+ { .compatible = "qcom,sc8280xp-dispcc0", .data = &disp0_cc_sc8280xp_desc },
+ { .compatible = "qcom,sc8280xp-dispcc1", .data = &disp1_cc_sc8280xp_desc },
+ { }
+};
+MODULE_DEVICE_TABLE(of, disp_cc_sc8280xp_match_table);
+
+static struct platform_driver disp_cc_sc8280xp_driver = {
+ .probe = disp_cc_sc8280xp_probe,
+ .driver = {
+ .name = "disp_cc-sc8280xp",
+ .of_match_table = disp_cc_sc8280xp_match_table,
+ },
+};
+
+static int __init disp_cc_sc8280xp_init(void)
+{
+ return platform_driver_register(&disp_cc_sc8280xp_driver);
+}
+subsys_initcall(disp_cc_sc8280xp_init);
+
+static void __exit disp_cc_sc8280xp_exit(void)
+{
+ platform_driver_unregister(&disp_cc_sc8280xp_driver);
+}
+module_exit(disp_cc_sc8280xp_exit);
+
+MODULE_DESCRIPTION("Qualcomm SC8280XP dispcc driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/dispcc-sm6350.c b/drivers/clk/qcom/dispcc-sm6350.c
index 0c3c2e26ede9..ea6f54ed846e 100644
--- a/drivers/clk/qcom/dispcc-sm6350.c
+++ b/drivers/clk/qcom/dispcc-sm6350.c
@@ -306,7 +306,7 @@ static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src = {
.name = "disp_cc_mdss_pclk0_clk_src",
.parent_data = disp_cc_parent_data_5,
.num_parents = ARRAY_SIZE(disp_cc_parent_data_5),
- .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
+ .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE | CLK_OPS_PARENT_ENABLE,
.ops = &clk_pixel_ops,
},
};
@@ -385,7 +385,7 @@ static struct clk_branch disp_cc_mdss_byte0_clk = {
&disp_cc_mdss_byte0_clk_src.clkr.hw,
},
.num_parents = 1,
- .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
+ .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE | CLK_OPS_PARENT_ENABLE,
.ops = &clk_branch2_ops,
},
},
diff --git a/drivers/clk/qcom/dispcc-sm6375.c b/drivers/clk/qcom/dispcc-sm6375.c
new file mode 100644
index 000000000000..5ce9198ad611
--- /dev/null
+++ b/drivers/clk/qcom/dispcc-sm6375.c
@@ -0,0 +1,610 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,sm6375-dispcc.h>
+
+#include "clk-alpha-pll.h"
+#include "clk-branch.h"
+#include "clk-rcg.h"
+#include "clk-regmap-divider.h"
+#include "common.h"
+#include "gdsc.h"
+#include "reset.h"
+
+enum {
+ DT_BI_TCXO,
+ DT_GCC_DISP_GPLL0_CLK,
+ DT_DSI0_PHY_PLL_OUT_BYTECLK,
+ DT_DSI0_PHY_PLL_OUT_DSICLK,
+};
+
+enum {
+ P_BI_TCXO,
+ P_DISP_CC_PLL0_OUT_EVEN,
+ P_DISP_CC_PLL0_OUT_MAIN,
+ P_DSI0_PHY_PLL_OUT_BYTECLK,
+ P_DSI0_PHY_PLL_OUT_DSICLK,
+ P_GCC_DISP_GPLL0_CLK,
+};
+
+static struct pll_vco lucid_vco[] = {
+ { 249600000, 2000000000, 0 },
+};
+
+/* 615MHz */
+static const struct alpha_pll_config disp_cc_pll0_config = {
+ .l = 0x20,
+ .alpha = 0x800,
+ .config_ctl_val = 0x20485699,
+ .config_ctl_hi_val = 0x00002261,
+ .config_ctl_hi1_val = 0x329a299c,
+ .user_ctl_val = 0x00000001,
+ .user_ctl_hi_val = 0x00000805,
+ .user_ctl_hi1_val = 0x00000000,
+};
+
+static struct clk_alpha_pll disp_cc_pll0 = {
+ .offset = 0x0,
+ .vco_table = lucid_vco,
+ .num_vco = ARRAY_SIZE(lucid_vco),
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_pll0",
+ .parent_data = &(const struct clk_parent_data){
+ .index = DT_BI_TCXO,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_lucid_ops,
+ },
+ },
+};
+
+static const struct parent_map disp_cc_parent_map_0[] = {
+ { P_BI_TCXO, 0 },
+ { P_DSI0_PHY_PLL_OUT_BYTECLK, 1 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_0[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_DSI0_PHY_PLL_OUT_BYTECLK },
+};
+
+static const struct parent_map disp_cc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_DISP_CC_PLL0_OUT_MAIN, 1 },
+ { P_GCC_DISP_GPLL0_CLK, 4 },
+ { P_DISP_CC_PLL0_OUT_EVEN, 5 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_1[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &disp_cc_pll0.clkr.hw },
+ { .index = DT_GCC_DISP_GPLL0_CLK },
+ { .hw = &disp_cc_pll0.clkr.hw },
+};
+
+static const struct parent_map disp_cc_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+ { P_GCC_DISP_GPLL0_CLK, 4 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_2[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_GCC_DISP_GPLL0_CLK },
+};
+
+static const struct parent_map disp_cc_parent_map_3[] = {
+ { P_BI_TCXO, 0 },
+ { P_DSI0_PHY_PLL_OUT_DSICLK, 1 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_3[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_DSI0_PHY_PLL_OUT_DSICLK },
+};
+
+static const struct parent_map disp_cc_parent_map_4[] = {
+ { P_BI_TCXO, 0 },
+};
+
+static const struct clk_parent_data disp_cc_parent_data_4[] = {
+ { .index = DT_BI_TCXO },
+};
+
+static const struct freq_tbl ftbl_disp_cc_mdss_ahb_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(37500000, P_GCC_DISP_GPLL0_CLK, 8, 0, 0),
+ F(75000000, P_GCC_DISP_GPLL0_CLK, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 disp_cc_mdss_ahb_clk_src = {
+ .cmd_rcgr = 0x115c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_2,
+ .freq_tbl = ftbl_disp_cc_mdss_ahb_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_ahb_clk_src",
+ .parent_data = disp_cc_parent_data_2,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_2),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 disp_cc_mdss_byte0_clk_src = {
+ .cmd_rcgr = 0x10c4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_0,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_byte0_clk_src",
+ .parent_data = disp_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+ .ops = &clk_byte2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_disp_cc_mdss_esc0_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 disp_cc_mdss_esc0_clk_src = {
+ .cmd_rcgr = 0x10e0,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_0,
+ .freq_tbl = ftbl_disp_cc_mdss_esc0_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_esc0_clk_src",
+ .parent_data = disp_cc_parent_data_0,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_0),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src[] = {
+ F(200000000, P_GCC_DISP_GPLL0_CLK, 1.5, 0, 0),
+ F(300000000, P_GCC_DISP_GPLL0_CLK, 1, 0, 0),
+ F(373500000, P_DISP_CC_PLL0_OUT_MAIN, 2, 0, 0),
+ F(470000000, P_DISP_CC_PLL0_OUT_MAIN, 2, 0, 0),
+ F(560000000, P_DISP_CC_PLL0_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = {
+ .cmd_rcgr = 0x107c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_1,
+ .freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_mdp_clk_src",
+ .parent_data = disp_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src = {
+ .cmd_rcgr = 0x1064,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_3,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_pclk0_clk_src",
+ .parent_data = disp_cc_parent_data_3,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,
+ .ops = &clk_pixel_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_disp_cc_mdss_rot_clk_src[] = {
+ F(200000000, P_GCC_DISP_GPLL0_CLK, 1.5, 0, 0),
+ F(300000000, P_GCC_DISP_GPLL0_CLK, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 disp_cc_mdss_rot_clk_src = {
+ .cmd_rcgr = 0x1094,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_1,
+ .freq_tbl = ftbl_disp_cc_mdss_rot_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_rot_clk_src",
+ .parent_data = disp_cc_parent_data_1,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_1),
+ .ops = &clk_rcg2_shared_ops,
+ },
+};
+
+static struct clk_rcg2 disp_cc_mdss_vsync_clk_src = {
+ .cmd_rcgr = 0x10ac,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = disp_cc_parent_map_4,
+ .freq_tbl = ftbl_disp_cc_mdss_esc0_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_vsync_clk_src",
+ .parent_data = disp_cc_parent_data_4,
+ .num_parents = ARRAY_SIZE(disp_cc_parent_data_4),
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_regmap_div disp_cc_mdss_byte0_div_clk_src = {
+ .reg = 0x10dc,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "disp_cc_mdss_byte0_div_clk_src",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &disp_cc_mdss_byte0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_div_ops,
+ },
+};
+
+static struct clk_branch disp_cc_mdss_ahb_clk = {
+ .halt_reg = 0x104c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x104c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_byte0_clk = {
+ .halt_reg = 0x102c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x102c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_byte0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_byte0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_byte0_intf_clk = {
+ .halt_reg = 0x1030,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1030,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_byte0_intf_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_byte0_div_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_esc0_clk = {
+ .halt_reg = 0x1034,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1034,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_esc0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_esc0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_mdp_clk = {
+ .halt_reg = 0x1010,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_mdp_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_mdp_lut_clk = {
+ .halt_reg = 0x1020,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x1020,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_mdp_lut_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_mdp_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_non_gdsc_ahb_clk = {
+ .halt_reg = 0x2004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x2004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_non_gdsc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_pclk0_clk = {
+ .halt_reg = 0x1168,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1168,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_pclk0_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_pclk0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_rot_clk = {
+ .halt_reg = 0x1018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_rot_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_rot_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_rscc_ahb_clk = {
+ .halt_reg = 0x200c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x200c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_rscc_ahb_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_ahb_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_rscc_vsync_clk = {
+ .halt_reg = 0x2008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x2008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_rscc_vsync_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_vsync_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_mdss_vsync_clk = {
+ .halt_reg = 0x1028,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x1028,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_mdss_vsync_clk",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_vsync_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_sleep_clk = {
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_sleep_clk",
+ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch disp_cc_xo_clk = {
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x5008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "disp_cc_xo_clk",
+ .flags = CLK_IS_CRITICAL,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc mdss_gdsc = {
+ .gdscr = 0x1004,
+ .en_rest_wait_val = 0x2,
+ .en_few_wait_val = 0x2,
+ .clk_dis_wait_val = 0xf,
+ .pd = {
+ .name = "mdss_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = HW_CTRL,
+};
+
+static struct clk_regmap *disp_cc_sm6375_clocks[] = {
+ [DISP_CC_MDSS_AHB_CLK] = &disp_cc_mdss_ahb_clk.clkr,
+ [DISP_CC_MDSS_AHB_CLK_SRC] = &disp_cc_mdss_ahb_clk_src.clkr,
+ [DISP_CC_MDSS_BYTE0_CLK] = &disp_cc_mdss_byte0_clk.clkr,
+ [DISP_CC_MDSS_BYTE0_CLK_SRC] = &disp_cc_mdss_byte0_clk_src.clkr,
+ [DISP_CC_MDSS_BYTE0_DIV_CLK_SRC] = &disp_cc_mdss_byte0_div_clk_src.clkr,
+ [DISP_CC_MDSS_BYTE0_INTF_CLK] = &disp_cc_mdss_byte0_intf_clk.clkr,
+ [DISP_CC_MDSS_ESC0_CLK] = &disp_cc_mdss_esc0_clk.clkr,
+ [DISP_CC_MDSS_ESC0_CLK_SRC] = &disp_cc_mdss_esc0_clk_src.clkr,
+ [DISP_CC_MDSS_MDP_CLK] = &disp_cc_mdss_mdp_clk.clkr,
+ [DISP_CC_MDSS_MDP_CLK_SRC] = &disp_cc_mdss_mdp_clk_src.clkr,
+ [DISP_CC_MDSS_MDP_LUT_CLK] = &disp_cc_mdss_mdp_lut_clk.clkr,
+ [DISP_CC_MDSS_NON_GDSC_AHB_CLK] = &disp_cc_mdss_non_gdsc_ahb_clk.clkr,
+ [DISP_CC_MDSS_PCLK0_CLK] = &disp_cc_mdss_pclk0_clk.clkr,
+ [DISP_CC_MDSS_PCLK0_CLK_SRC] = &disp_cc_mdss_pclk0_clk_src.clkr,
+ [DISP_CC_MDSS_ROT_CLK] = &disp_cc_mdss_rot_clk.clkr,
+ [DISP_CC_MDSS_ROT_CLK_SRC] = &disp_cc_mdss_rot_clk_src.clkr,
+ [DISP_CC_MDSS_RSCC_AHB_CLK] = &disp_cc_mdss_rscc_ahb_clk.clkr,
+ [DISP_CC_MDSS_RSCC_VSYNC_CLK] = &disp_cc_mdss_rscc_vsync_clk.clkr,
+ [DISP_CC_MDSS_VSYNC_CLK] = &disp_cc_mdss_vsync_clk.clkr,
+ [DISP_CC_MDSS_VSYNC_CLK_SRC] = &disp_cc_mdss_vsync_clk_src.clkr,
+ [DISP_CC_PLL0] = &disp_cc_pll0.clkr,
+ [DISP_CC_SLEEP_CLK] = &disp_cc_sleep_clk.clkr,
+ [DISP_CC_XO_CLK] = &disp_cc_xo_clk.clkr,
+};
+
+static const struct qcom_reset_map disp_cc_sm6375_resets[] = {
+ [DISP_CC_MDSS_CORE_BCR] = { 0x1000 },
+ [DISP_CC_MDSS_RSCC_BCR] = { 0x2000 },
+};
+
+static struct gdsc *disp_cc_sm6375_gdscs[] = {
+ [MDSS_GDSC] = &mdss_gdsc,
+};
+
+static const struct regmap_config disp_cc_sm6375_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x10000,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc disp_cc_sm6375_desc = {
+ .config = &disp_cc_sm6375_regmap_config,
+ .clks = disp_cc_sm6375_clocks,
+ .num_clks = ARRAY_SIZE(disp_cc_sm6375_clocks),
+ .resets = disp_cc_sm6375_resets,
+ .num_resets = ARRAY_SIZE(disp_cc_sm6375_resets),
+ .gdscs = disp_cc_sm6375_gdscs,
+ .num_gdscs = ARRAY_SIZE(disp_cc_sm6375_gdscs),
+};
+
+static const struct of_device_id disp_cc_sm6375_match_table[] = {
+ { .compatible = "qcom,sm6375-dispcc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, disp_cc_sm6375_match_table);
+
+static int disp_cc_sm6375_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+
+ regmap = qcom_cc_map(pdev, &disp_cc_sm6375_desc);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ clk_lucid_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config);
+
+ return qcom_cc_really_probe(pdev, &disp_cc_sm6375_desc, regmap);
+}
+
+static struct platform_driver disp_cc_sm6375_driver = {
+ .probe = disp_cc_sm6375_probe,
+ .driver = {
+ .name = "disp_cc-sm6375",
+ .of_match_table = disp_cc_sm6375_match_table,
+ },
+};
+
+static int __init disp_cc_sm6375_init(void)
+{
+ return platform_driver_register(&disp_cc_sm6375_driver);
+}
+subsys_initcall(disp_cc_sm6375_init);
+
+static void __exit disp_cc_sm6375_exit(void)
+{
+ platform_driver_unregister(&disp_cc_sm6375_driver);
+}
+module_exit(disp_cc_sm6375_exit);
+
+MODULE_DESCRIPTION("QTI DISPCC SM6375 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/dispcc-sm8250.c b/drivers/clk/qcom/dispcc-sm8250.c
index 709076f0f9d7..382dbd8ba250 100644
--- a/drivers/clk/qcom/dispcc-sm8250.c
+++ b/drivers/clk/qcom/dispcc-sm8250.c
@@ -462,6 +462,20 @@ static struct clk_branch disp_cc_mdss_edp_link_clk = {
},
};
+static struct clk_regmap_div disp_cc_mdss_edp_link_div_clk_src = {
+ .reg = 0x2288,
+ .shift = 0,
+ .width = 2,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "disp_cc_mdss_edp_link_div_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &disp_cc_mdss_edp_link_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_div_ro_ops,
+ },
+};
+
static struct clk_branch disp_cc_mdss_edp_link_intf_clk = {
.halt_reg = 0x2074,
.halt_check = BRANCH_HALT,
@@ -471,7 +485,7 @@ static struct clk_branch disp_cc_mdss_edp_link_intf_clk = {
.hw.init = &(struct clk_init_data){
.name = "disp_cc_mdss_edp_link_intf_clk",
.parent_hws = (const struct clk_hw*[]){
- &disp_cc_mdss_edp_link_clk_src.clkr.hw,
+ &disp_cc_mdss_edp_link_div_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_GET_RATE_NOCACHE,
@@ -1137,7 +1151,7 @@ static struct gdsc mdss_gdsc = {
.name = "mdss_gdsc",
},
.pwrsts = PWRSTS_OFF_ON,
- .flags = HW_CTRL,
+ .flags = HW_CTRL | RETAIN_FF_ENABLE,
};
static struct clk_regmap *disp_cc_sm8250_clocks[] = {
@@ -1175,6 +1189,7 @@ static struct clk_regmap *disp_cc_sm8250_clocks[] = {
[DISP_CC_MDSS_EDP_GTC_CLK_SRC] = &disp_cc_mdss_edp_gtc_clk_src.clkr,
[DISP_CC_MDSS_EDP_LINK_CLK] = &disp_cc_mdss_edp_link_clk.clkr,
[DISP_CC_MDSS_EDP_LINK_CLK_SRC] = &disp_cc_mdss_edp_link_clk_src.clkr,
+ [DISP_CC_MDSS_EDP_LINK_DIV_CLK_SRC] = &disp_cc_mdss_edp_link_div_clk_src.clkr,
[DISP_CC_MDSS_EDP_LINK_INTF_CLK] = &disp_cc_mdss_edp_link_intf_clk.clkr,
[DISP_CC_MDSS_EDP_PIXEL_CLK] = &disp_cc_mdss_edp_pixel_clk.clkr,
[DISP_CC_MDSS_EDP_PIXEL_CLK_SRC] = &disp_cc_mdss_edp_pixel_clk_src.clkr,
@@ -1274,6 +1289,17 @@ static int disp_cc_sm8250_probe(struct platform_device *pdev)
disp_cc_pll1_config.config_ctl_hi1_val = 0x00000024;
disp_cc_pll1_config.user_ctl_hi1_val = 0x000000D0;
disp_cc_pll1_init.ops = &clk_alpha_pll_trion_ops;
+
+ disp_cc_mdss_dp_link_intf_clk.clkr.hw.init->parent_hws[0] =
+ &disp_cc_mdss_dp_link_clk_src.clkr.hw;
+ disp_cc_mdss_dp_link1_intf_clk.clkr.hw.init->parent_hws[0] =
+ &disp_cc_mdss_dp_link1_clk_src.clkr.hw;
+ disp_cc_mdss_edp_link_intf_clk.clkr.hw.init->parent_hws[0] =
+ &disp_cc_mdss_edp_link_clk_src.clkr.hw;
+
+ disp_cc_sm8250_clocks[DISP_CC_MDSS_DP_LINK1_DIV_CLK_SRC] = NULL;
+ disp_cc_sm8250_clocks[DISP_CC_MDSS_DP_LINK_DIV_CLK_SRC] = NULL;
+ disp_cc_sm8250_clocks[DISP_CC_MDSS_EDP_LINK_DIV_CLK_SRC] = NULL;
} else if (of_device_is_compatible(pdev->dev.of_node, "qcom,sm8350-dispcc")) {
static struct clk_rcg2 * const rcgs[] = {
&disp_cc_mdss_byte0_clk_src,
@@ -1285,7 +1311,11 @@ static int disp_cc_sm8250_probe(struct platform_device *pdev)
&disp_cc_mdss_dp_pixel1_clk_src,
&disp_cc_mdss_dp_pixel2_clk_src,
&disp_cc_mdss_dp_pixel_clk_src,
+ &disp_cc_mdss_edp_aux_clk_src,
+ &disp_cc_mdss_edp_link_clk_src,
+ &disp_cc_mdss_edp_pixel_clk_src,
&disp_cc_mdss_esc0_clk_src,
+ &disp_cc_mdss_esc1_clk_src,
&disp_cc_mdss_mdp_clk_src,
&disp_cc_mdss_pclk0_clk_src,
&disp_cc_mdss_pclk1_clk_src,
@@ -1297,6 +1327,7 @@ static int disp_cc_sm8250_probe(struct platform_device *pdev)
&disp_cc_mdss_byte1_div_clk_src,
&disp_cc_mdss_dp_link1_div_clk_src,
&disp_cc_mdss_dp_link_div_clk_src,
+ &disp_cc_mdss_edp_link_div_clk_src,
};
unsigned int i;
static bool offset_applied;
@@ -1330,6 +1361,9 @@ static int disp_cc_sm8250_probe(struct platform_device *pdev)
disp_cc_pll1_config.test_ctl_hi1_val = 0x01800000;
disp_cc_pll1_init.ops = &clk_alpha_pll_lucid_5lpe_ops;
disp_cc_pll1.vco_table = lucid_5lpe_vco;
+
+ disp_cc_sm8250_clocks[DISP_CC_MDSS_EDP_GTC_CLK] = NULL;
+ disp_cc_sm8250_clocks[DISP_CC_MDSS_EDP_GTC_CLK_SRC] = NULL;
}
clk_lucid_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config);
diff --git a/drivers/clk/qcom/gcc-ipq4019.c b/drivers/clk/qcom/gcc-ipq4019.c
index 8abad4032de7..5675c60525a7 100644
--- a/drivers/clk/qcom/gcc-ipq4019.c
+++ b/drivers/clk/qcom/gcc-ipq4019.c
@@ -1756,19 +1756,12 @@ static int gcc_ipq4019_probe(struct platform_device *pdev)
if (err)
return err;
- return clk_notifier_register(apps_clk_src.clkr.hw.clk,
- &gcc_ipq4019_cpu_clk_notifier);
-}
-
-static int gcc_ipq4019_remove(struct platform_device *pdev)
-{
- return clk_notifier_unregister(apps_clk_src.clkr.hw.clk,
- &gcc_ipq4019_cpu_clk_notifier);
+ return devm_clk_notifier_register(&pdev->dev, apps_clk_src.clkr.hw.clk,
+ &gcc_ipq4019_cpu_clk_notifier);
}
static struct platform_driver gcc_ipq4019_driver = {
.probe = gcc_ipq4019_probe,
- .remove = gcc_ipq4019_remove,
.driver = {
.name = "qcom,gcc-ipq4019",
.of_match_table = gcc_ipq4019_match_table,
diff --git a/drivers/clk/qcom/gcc-ipq806x.c b/drivers/clk/qcom/gcc-ipq806x.c
index 718de17a1e60..6447f3e81b55 100644
--- a/drivers/clk/qcom/gcc-ipq806x.c
+++ b/drivers/clk/qcom/gcc-ipq806x.c
@@ -79,7 +79,9 @@ static struct clk_regmap pll4_vote = {
.enable_mask = BIT(4),
.hw.init = &(struct clk_init_data){
.name = "pll4_vote",
- .parent_names = (const char *[]){ "pll4" },
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "pll4", .name = "pll4",
+ },
.num_parents = 1,
.ops = &clk_pll_vote_ops,
},
diff --git a/drivers/clk/qcom/gcc-ipq8074.c b/drivers/clk/qcom/gcc-ipq8074.c
index 42d185fe19c8..14cc4ad02221 100644
--- a/drivers/clk/qcom/gcc-ipq8074.c
+++ b/drivers/clk/qcom/gcc-ipq8074.c
@@ -49,349 +49,6 @@ enum {
P_UNIPHY2_TX,
};
-static const char * const gcc_xo_gpll0_gpll0_out_main_div2[] = {
- "xo",
- "gpll0",
- "gpll0_out_main_div2",
-};
-
-static const struct parent_map gcc_xo_gpll0_gpll0_out_main_div2_map[] = {
- { P_XO, 0 },
- { P_GPLL0, 1 },
- { P_GPLL0_DIV2, 4 },
-};
-
-static const struct parent_map gcc_xo_gpll0_map[] = {
- { P_XO, 0 },
- { P_GPLL0, 1 },
-};
-
-static const char * const gcc_xo_gpll0_gpll2_gpll0_out_main_div2[] = {
- "xo",
- "gpll0",
- "gpll2",
- "gpll0_out_main_div2",
-};
-
-static const struct parent_map gcc_xo_gpll0_gpll2_gpll0_out_main_div2_map[] = {
- { P_XO, 0 },
- { P_GPLL0, 1 },
- { P_GPLL2, 2 },
- { P_GPLL0_DIV2, 4 },
-};
-
-static const char * const gcc_xo_gpll0_sleep_clk[] = {
- "xo",
- "gpll0",
- "sleep_clk",
-};
-
-static const struct parent_map gcc_xo_gpll0_sleep_clk_map[] = {
- { P_XO, 0 },
- { P_GPLL0, 2 },
- { P_SLEEP_CLK, 6 },
-};
-
-static const char * const gcc_xo_gpll6_gpll0_gpll0_out_main_div2[] = {
- "xo",
- "gpll6",
- "gpll0",
- "gpll0_out_main_div2",
-};
-
-static const struct parent_map gcc_xo_gpll6_gpll0_gpll0_out_main_div2_map[] = {
- { P_XO, 0 },
- { P_GPLL6, 1 },
- { P_GPLL0, 3 },
- { P_GPLL0_DIV2, 4 },
-};
-
-static const char * const gcc_xo_gpll0_out_main_div2_gpll0[] = {
- "xo",
- "gpll0_out_main_div2",
- "gpll0",
-};
-
-static const struct parent_map gcc_xo_gpll0_out_main_div2_gpll0_map[] = {
- { P_XO, 0 },
- { P_GPLL0_DIV2, 2 },
- { P_GPLL0, 1 },
-};
-
-static const char * const gcc_usb3phy_0_cc_pipe_clk_xo[] = {
- "usb3phy_0_cc_pipe_clk",
- "xo",
-};
-
-static const struct parent_map gcc_usb3phy_0_cc_pipe_clk_xo_map[] = {
- { P_USB3PHY_0_PIPE, 0 },
- { P_XO, 2 },
-};
-
-static const char * const gcc_usb3phy_1_cc_pipe_clk_xo[] = {
- "usb3phy_1_cc_pipe_clk",
- "xo",
-};
-
-static const struct parent_map gcc_usb3phy_1_cc_pipe_clk_xo_map[] = {
- { P_USB3PHY_1_PIPE, 0 },
- { P_XO, 2 },
-};
-
-static const char * const gcc_pcie20_phy0_pipe_clk_xo[] = {
- "pcie20_phy0_pipe_clk",
- "xo",
-};
-
-static const struct parent_map gcc_pcie20_phy0_pipe_clk_xo_map[] = {
- { P_PCIE20_PHY0_PIPE, 0 },
- { P_XO, 2 },
-};
-
-static const char * const gcc_pcie20_phy1_pipe_clk_xo[] = {
- "pcie20_phy1_pipe_clk",
- "xo",
-};
-
-static const struct parent_map gcc_pcie20_phy1_pipe_clk_xo_map[] = {
- { P_PCIE20_PHY1_PIPE, 0 },
- { P_XO, 2 },
-};
-
-static const char * const gcc_xo_gpll0_gpll6_gpll0_div2[] = {
- "xo",
- "gpll0",
- "gpll6",
- "gpll0_out_main_div2",
-};
-
-static const struct parent_map gcc_xo_gpll0_gpll6_gpll0_div2_map[] = {
- { P_XO, 0 },
- { P_GPLL0, 1 },
- { P_GPLL6, 2 },
- { P_GPLL0_DIV2, 4 },
-};
-
-static const char * const gcc_xo_gpll0_gpll6_gpll0_out_main_div2[] = {
- "xo",
- "gpll0",
- "gpll6",
- "gpll0_out_main_div2",
-};
-
-static const struct parent_map gcc_xo_gpll0_gpll6_gpll0_out_main_div2_map[] = {
- { P_XO, 0 },
- { P_GPLL0, 1 },
- { P_GPLL6, 2 },
- { P_GPLL0_DIV2, 3 },
-};
-
-static const char * const gcc_xo_bias_pll_nss_noc_clk_gpll0_gpll2[] = {
- "xo",
- "bias_pll_nss_noc_clk",
- "gpll0",
- "gpll2",
-};
-
-static const struct parent_map gcc_xo_bias_pll_nss_noc_clk_gpll0_gpll2_map[] = {
- { P_XO, 0 },
- { P_BIAS_PLL_NSS_NOC, 1 },
- { P_GPLL0, 2 },
- { P_GPLL2, 3 },
-};
-
-static const char * const gcc_xo_nss_crypto_pll_gpll0[] = {
- "xo",
- "nss_crypto_pll",
- "gpll0",
-};
-
-static const struct parent_map gcc_xo_nss_crypto_pll_gpll0_map[] = {
- { P_XO, 0 },
- { P_NSS_CRYPTO_PLL, 1 },
- { P_GPLL0, 2 },
-};
-
-static const char * const gcc_xo_ubi32_pll_gpll0_gpll2_gpll4_gpll6[] = {
- "xo",
- "ubi32_pll",
- "gpll0",
- "gpll2",
- "gpll4",
- "gpll6",
-};
-
-static const struct parent_map gcc_xo_ubi32_gpll0_gpll2_gpll4_gpll6_map[] = {
- { P_XO, 0 },
- { P_UBI32_PLL, 1 },
- { P_GPLL0, 2 },
- { P_GPLL2, 3 },
- { P_GPLL4, 4 },
- { P_GPLL6, 5 },
-};
-
-static const char * const gcc_xo_gpll0_out_main_div2[] = {
- "xo",
- "gpll0_out_main_div2",
-};
-
-static const struct parent_map gcc_xo_gpll0_out_main_div2_map[] = {
- { P_XO, 0 },
- { P_GPLL0_DIV2, 1 },
-};
-
-static const char * const gcc_xo_bias_gpll0_gpll4_nss_ubi32[] = {
- "xo",
- "bias_pll_cc_clk",
- "gpll0",
- "gpll4",
- "nss_crypto_pll",
- "ubi32_pll",
-};
-
-static const struct parent_map gcc_xo_bias_gpll0_gpll4_nss_ubi32_map[] = {
- { P_XO, 0 },
- { P_BIAS_PLL, 1 },
- { P_GPLL0, 2 },
- { P_GPLL4, 3 },
- { P_NSS_CRYPTO_PLL, 4 },
- { P_UBI32_PLL, 5 },
-};
-
-static const char * const gcc_xo_gpll0_gpll4[] = {
- "xo",
- "gpll0",
- "gpll4",
-};
-
-static const struct parent_map gcc_xo_gpll0_gpll4_map[] = {
- { P_XO, 0 },
- { P_GPLL0, 1 },
- { P_GPLL4, 2 },
-};
-
-static const char * const gcc_xo_uniphy0_rx_tx_ubi32_bias[] = {
- "xo",
- "uniphy0_gcc_rx_clk",
- "uniphy0_gcc_tx_clk",
- "ubi32_pll",
- "bias_pll_cc_clk",
-};
-
-static const struct parent_map gcc_xo_uniphy0_rx_tx_ubi32_bias_map[] = {
- { P_XO, 0 },
- { P_UNIPHY0_RX, 1 },
- { P_UNIPHY0_TX, 2 },
- { P_UBI32_PLL, 5 },
- { P_BIAS_PLL, 6 },
-};
-
-static const char * const gcc_xo_uniphy0_tx_rx_ubi32_bias[] = {
- "xo",
- "uniphy0_gcc_tx_clk",
- "uniphy0_gcc_rx_clk",
- "ubi32_pll",
- "bias_pll_cc_clk",
-};
-
-static const struct parent_map gcc_xo_uniphy0_tx_rx_ubi32_bias_map[] = {
- { P_XO, 0 },
- { P_UNIPHY0_TX, 1 },
- { P_UNIPHY0_RX, 2 },
- { P_UBI32_PLL, 5 },
- { P_BIAS_PLL, 6 },
-};
-
-static const char * const gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias[] = {
- "xo",
- "uniphy0_gcc_rx_clk",
- "uniphy0_gcc_tx_clk",
- "uniphy1_gcc_rx_clk",
- "uniphy1_gcc_tx_clk",
- "ubi32_pll",
- "bias_pll_cc_clk",
-};
-
-static const struct parent_map
-gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias_map[] = {
- { P_XO, 0 },
- { P_UNIPHY0_RX, 1 },
- { P_UNIPHY0_TX, 2 },
- { P_UNIPHY1_RX, 3 },
- { P_UNIPHY1_TX, 4 },
- { P_UBI32_PLL, 5 },
- { P_BIAS_PLL, 6 },
-};
-
-static const char * const gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias[] = {
- "xo",
- "uniphy0_gcc_tx_clk",
- "uniphy0_gcc_rx_clk",
- "uniphy1_gcc_tx_clk",
- "uniphy1_gcc_rx_clk",
- "ubi32_pll",
- "bias_pll_cc_clk",
-};
-
-static const struct parent_map
-gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias_map[] = {
- { P_XO, 0 },
- { P_UNIPHY0_TX, 1 },
- { P_UNIPHY0_RX, 2 },
- { P_UNIPHY1_TX, 3 },
- { P_UNIPHY1_RX, 4 },
- { P_UBI32_PLL, 5 },
- { P_BIAS_PLL, 6 },
-};
-
-static const char * const gcc_xo_uniphy2_rx_tx_ubi32_bias[] = {
- "xo",
- "uniphy2_gcc_rx_clk",
- "uniphy2_gcc_tx_clk",
- "ubi32_pll",
- "bias_pll_cc_clk",
-};
-
-static const struct parent_map gcc_xo_uniphy2_rx_tx_ubi32_bias_map[] = {
- { P_XO, 0 },
- { P_UNIPHY2_RX, 1 },
- { P_UNIPHY2_TX, 2 },
- { P_UBI32_PLL, 5 },
- { P_BIAS_PLL, 6 },
-};
-
-static const char * const gcc_xo_uniphy2_tx_rx_ubi32_bias[] = {
- "xo",
- "uniphy2_gcc_tx_clk",
- "uniphy2_gcc_rx_clk",
- "ubi32_pll",
- "bias_pll_cc_clk",
-};
-
-static const struct parent_map gcc_xo_uniphy2_tx_rx_ubi32_bias_map[] = {
- { P_XO, 0 },
- { P_UNIPHY2_TX, 1 },
- { P_UNIPHY2_RX, 2 },
- { P_UBI32_PLL, 5 },
- { P_BIAS_PLL, 6 },
-};
-
-static const char * const gcc_xo_gpll0_gpll6_gpll0_sleep_clk[] = {
- "xo",
- "gpll0",
- "gpll6",
- "gpll0_out_main_div2",
- "sleep_clk",
-};
-
-static const struct parent_map gcc_xo_gpll0_gpll6_gpll0_sleep_clk_map[] = {
- { P_XO, 0 },
- { P_GPLL0, 1 },
- { P_GPLL6, 2 },
- { P_GPLL0_DIV2, 4 },
- { P_SLEEP_CLK, 6 },
-};
-
static struct clk_alpha_pll gpll0_main = {
.offset = 0x21000,
.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],
@@ -400,8 +57,9 @@ static struct clk_alpha_pll gpll0_main = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpll0_main",
- .parent_names = (const char *[]){
- "xo"
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo",
+ .name = "xo",
},
.num_parents = 1,
.ops = &clk_alpha_pll_ops,
@@ -414,9 +72,8 @@ static struct clk_fixed_factor gpll0_out_main_div2 = {
.div = 2,
.hw.init = &(struct clk_init_data){
.name = "gpll0_out_main_div2",
- .parent_names = (const char *[]){
- "gpll0_main"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &gpll0_main.clkr.hw },
.num_parents = 1,
.ops = &clk_fixed_factor_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -429,9 +86,8 @@ static struct clk_alpha_pll_postdiv gpll0 = {
.width = 4,
.clkr.hw.init = &(struct clk_init_data){
.name = "gpll0",
- .parent_names = (const char *[]){
- "gpll0_main"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &gpll0_main.clkr.hw },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
},
@@ -445,8 +101,9 @@ static struct clk_alpha_pll gpll2_main = {
.enable_mask = BIT(2),
.hw.init = &(struct clk_init_data){
.name = "gpll2_main",
- .parent_names = (const char *[]){
- "xo"
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo",
+ .name = "xo",
},
.num_parents = 1,
.ops = &clk_alpha_pll_ops,
@@ -461,9 +118,8 @@ static struct clk_alpha_pll_postdiv gpll2 = {
.width = 4,
.clkr.hw.init = &(struct clk_init_data){
.name = "gpll2",
- .parent_names = (const char *[]){
- "gpll2_main"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &gpll2_main.clkr.hw },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -478,8 +134,9 @@ static struct clk_alpha_pll gpll4_main = {
.enable_mask = BIT(5),
.hw.init = &(struct clk_init_data){
.name = "gpll4_main",
- .parent_names = (const char *[]){
- "xo"
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo",
+ .name = "xo",
},
.num_parents = 1,
.ops = &clk_alpha_pll_ops,
@@ -494,9 +151,8 @@ static struct clk_alpha_pll_postdiv gpll4 = {
.width = 4,
.clkr.hw.init = &(struct clk_init_data){
.name = "gpll4",
- .parent_names = (const char *[]){
- "gpll4_main"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &gpll4_main.clkr.hw },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -512,8 +168,9 @@ static struct clk_alpha_pll gpll6_main = {
.enable_mask = BIT(7),
.hw.init = &(struct clk_init_data){
.name = "gpll6_main",
- .parent_names = (const char *[]){
- "xo"
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo",
+ .name = "xo",
},
.num_parents = 1,
.ops = &clk_alpha_pll_ops,
@@ -528,9 +185,8 @@ static struct clk_alpha_pll_postdiv gpll6 = {
.width = 2,
.clkr.hw.init = &(struct clk_init_data){
.name = "gpll6",
- .parent_names = (const char *[]){
- "gpll6_main"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &gpll6_main.clkr.hw },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -542,9 +198,8 @@ static struct clk_fixed_factor gpll6_out_main_div2 = {
.div = 2,
.hw.init = &(struct clk_init_data){
.name = "gpll6_out_main_div2",
- .parent_names = (const char *[]){
- "gpll6_main"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &gpll6_main.clkr.hw },
.num_parents = 1,
.ops = &clk_fixed_factor_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -560,8 +215,9 @@ static struct clk_alpha_pll ubi32_pll_main = {
.enable_mask = BIT(6),
.hw.init = &(struct clk_init_data){
.name = "ubi32_pll_main",
- .parent_names = (const char *[]){
- "xo"
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo",
+ .name = "xo",
},
.num_parents = 1,
.ops = &clk_alpha_pll_huayra_ops,
@@ -575,9 +231,8 @@ static struct clk_alpha_pll_postdiv ubi32_pll = {
.width = 2,
.clkr.hw.init = &(struct clk_init_data){
.name = "ubi32_pll",
- .parent_names = (const char *[]){
- "ubi32_pll_main"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &ubi32_pll_main.clkr.hw },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -592,8 +247,9 @@ static struct clk_alpha_pll nss_crypto_pll_main = {
.enable_mask = BIT(4),
.hw.init = &(struct clk_init_data){
.name = "nss_crypto_pll_main",
- .parent_names = (const char *[]){
- "xo"
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo",
+ .name = "xo",
},
.num_parents = 1,
.ops = &clk_alpha_pll_ops,
@@ -607,9 +263,8 @@ static struct clk_alpha_pll_postdiv nss_crypto_pll = {
.width = 4,
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_crypto_pll",
- .parent_names = (const char *[]){
- "nss_crypto_pll_main"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_crypto_pll_main.clkr.hw },
.num_parents = 1,
.ops = &clk_alpha_pll_postdiv_ro_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -623,6 +278,18 @@ static const struct freq_tbl ftbl_pcnoc_bfdcd_clk_src[] = {
{ }
};
+static const struct clk_parent_data gcc_xo_gpll0_gpll0_out_main_div2[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .hw = &gpll0.clkr.hw},
+ { .hw = &gpll0_out_main_div2.hw},
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll0_out_main_div2_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL0_DIV2, 4 },
+};
+
static struct clk_rcg2 pcnoc_bfdcd_clk_src = {
.cmd_rcgr = 0x27000,
.freq_tbl = ftbl_pcnoc_bfdcd_clk_src,
@@ -630,8 +297,8 @@ static struct clk_rcg2 pcnoc_bfdcd_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "pcnoc_bfdcd_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
.flags = CLK_IS_CRITICAL,
},
@@ -642,9 +309,8 @@ static struct clk_fixed_factor pcnoc_clk_src = {
.div = 1,
.hw.init = &(struct clk_init_data){
.name = "pcnoc_clk_src",
- .parent_names = (const char *[]){
- "pcnoc_bfdcd_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcnoc_bfdcd_clk_src.clkr.hw },
.num_parents = 1,
.ops = &clk_fixed_factor_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -658,8 +324,9 @@ static struct clk_branch gcc_sleep_clk_src = {
.enable_mask = BIT(1),
.hw.init = &(struct clk_init_data){
.name = "gcc_sleep_clk_src",
- .parent_names = (const char *[]){
- "sleep_clk"
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "sleep_clk",
+ .name = "sleep_clk",
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -682,8 +349,8 @@ static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup1_i2c_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -708,8 +375,8 @@ static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup1_spi_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -721,8 +388,8 @@ static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup2_i2c_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -735,8 +402,8 @@ static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup2_spi_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -748,8 +415,8 @@ static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup3_i2c_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -762,8 +429,8 @@ static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup3_spi_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -775,8 +442,8 @@ static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup4_i2c_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -789,8 +456,8 @@ static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup4_spi_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -802,8 +469,8 @@ static struct clk_rcg2 blsp1_qup5_i2c_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup5_i2c_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -816,8 +483,8 @@ static struct clk_rcg2 blsp1_qup5_spi_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup5_spi_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -829,8 +496,8 @@ static struct clk_rcg2 blsp1_qup6_i2c_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup6_i2c_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -843,8 +510,8 @@ static struct clk_rcg2 blsp1_qup6_spi_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup6_spi_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -877,8 +544,8 @@ static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_uart1_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -891,8 +558,8 @@ static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_uart2_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -905,8 +572,8 @@ static struct clk_rcg2 blsp1_uart3_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_uart3_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -919,8 +586,8 @@ static struct clk_rcg2 blsp1_uart4_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_uart4_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -933,8 +600,8 @@ static struct clk_rcg2 blsp1_uart5_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_uart5_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -947,8 +614,8 @@ static struct clk_rcg2 blsp1_uart6_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_uart6_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -958,6 +625,11 @@ static const struct clk_parent_data gcc_xo_gpll0[] = {
{ .hw = &gpll0.clkr.hw },
};
+static const struct parent_map gcc_xo_gpll0_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+};
+
static const struct freq_tbl ftbl_pcie_axi_clk_src[] = {
F(19200000, P_XO, 1, 0, 0),
F(200000000, P_GPLL0, 4, 0, 0),
@@ -972,7 +644,7 @@ static struct clk_rcg2 pcie0_axi_clk_src = {
.clkr.hw.init = &(struct clk_init_data){
.name = "pcie0_axi_clk_src",
.parent_data = gcc_xo_gpll0,
- .num_parents = 2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -981,6 +653,18 @@ static const struct freq_tbl ftbl_pcie_aux_clk_src[] = {
F(19200000, P_XO, 1, 0, 0),
};
+static const struct clk_parent_data gcc_xo_gpll0_sleep_clk[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .fw_name = "sleep_clk", .name = "sleep_clk" },
+};
+
+static const struct parent_map gcc_xo_gpll0_sleep_clk_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 2 },
+ { P_SLEEP_CLK, 6 },
+};
+
static struct clk_rcg2 pcie0_aux_clk_src = {
.cmd_rcgr = 0x75024,
.freq_tbl = ftbl_pcie_aux_clk_src,
@@ -989,12 +673,22 @@ static struct clk_rcg2 pcie0_aux_clk_src = {
.parent_map = gcc_xo_gpll0_sleep_clk_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "pcie0_aux_clk_src",
- .parent_names = gcc_xo_gpll0_sleep_clk,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_sleep_clk,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_sleep_clk),
.ops = &clk_rcg2_ops,
},
};
+static const struct clk_parent_data gcc_pcie20_phy0_pipe_clk_xo[] = {
+ { .fw_name = "pcie0_pipe", .name = "pcie20_phy0_pipe_clk" },
+ { .fw_name = "xo", .name = "xo" },
+};
+
+static const struct parent_map gcc_pcie20_phy0_pipe_clk_xo_map[] = {
+ { P_PCIE20_PHY0_PIPE, 0 },
+ { P_XO, 2 },
+};
+
static struct clk_regmap_mux pcie0_pipe_clk_src = {
.reg = 0x7501c,
.shift = 8,
@@ -1003,8 +697,8 @@ static struct clk_regmap_mux pcie0_pipe_clk_src = {
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "pcie0_pipe_clk_src",
- .parent_names = gcc_pcie20_phy0_pipe_clk_xo,
- .num_parents = 2,
+ .parent_data = gcc_pcie20_phy0_pipe_clk_xo,
+ .num_parents = ARRAY_SIZE(gcc_pcie20_phy0_pipe_clk_xo),
.ops = &clk_regmap_mux_closest_ops,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1019,7 +713,7 @@ static struct clk_rcg2 pcie1_axi_clk_src = {
.clkr.hw.init = &(struct clk_init_data){
.name = "pcie1_axi_clk_src",
.parent_data = gcc_xo_gpll0,
- .num_parents = 2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -1032,12 +726,22 @@ static struct clk_rcg2 pcie1_aux_clk_src = {
.parent_map = gcc_xo_gpll0_sleep_clk_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "pcie1_aux_clk_src",
- .parent_names = gcc_xo_gpll0_sleep_clk,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_sleep_clk,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_sleep_clk),
.ops = &clk_rcg2_ops,
},
};
+static const struct clk_parent_data gcc_pcie20_phy1_pipe_clk_xo[] = {
+ { .fw_name = "pcie1_pipe", .name = "pcie20_phy1_pipe_clk" },
+ { .fw_name = "xo", .name = "xo" },
+};
+
+static const struct parent_map gcc_pcie20_phy1_pipe_clk_xo_map[] = {
+ { P_PCIE20_PHY1_PIPE, 0 },
+ { P_XO, 2 },
+};
+
static struct clk_regmap_mux pcie1_pipe_clk_src = {
.reg = 0x7601c,
.shift = 8,
@@ -1046,8 +750,8 @@ static struct clk_regmap_mux pcie1_pipe_clk_src = {
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "pcie1_pipe_clk_src",
- .parent_names = gcc_pcie20_phy1_pipe_clk_xo,
- .num_parents = 2,
+ .parent_data = gcc_pcie20_phy1_pipe_clk_xo,
+ .num_parents = ARRAY_SIZE(gcc_pcie20_phy1_pipe_clk_xo),
.ops = &clk_regmap_mux_closest_ops,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1066,6 +770,20 @@ static const struct freq_tbl ftbl_sdcc_apps_clk_src[] = {
{ }
};
+static const struct clk_parent_data gcc_xo_gpll0_gpll2_gpll0_out_main_div2[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll2.clkr.hw },
+ { .hw = &gpll0_out_main_div2.hw },
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll2_gpll0_out_main_div2_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL2, 2 },
+ { P_GPLL0_DIV2, 4 },
+};
+
static struct clk_rcg2 sdcc1_apps_clk_src = {
.cmd_rcgr = 0x42004,
.freq_tbl = ftbl_sdcc_apps_clk_src,
@@ -1074,8 +792,8 @@ static struct clk_rcg2 sdcc1_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll2_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "sdcc1_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll2_gpll0_out_main_div2,
- .num_parents = 4,
+ .parent_data = gcc_xo_gpll0_gpll2_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll2_gpll0_out_main_div2),
.ops = &clk_rcg2_floor_ops,
},
};
@@ -1086,6 +804,20 @@ static const struct freq_tbl ftbl_sdcc_ice_core_clk_src[] = {
F(308570000, P_GPLL6, 3.5, 0, 0),
};
+static const struct clk_parent_data gcc_xo_gpll0_gpll6_gpll0_div2[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll6.clkr.hw },
+ { .hw = &gpll0_out_main_div2.hw },
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll6_gpll0_div2_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL6, 2 },
+ { P_GPLL0_DIV2, 4 },
+};
+
static struct clk_rcg2 sdcc1_ice_core_clk_src = {
.cmd_rcgr = 0x5d000,
.freq_tbl = ftbl_sdcc_ice_core_clk_src,
@@ -1094,8 +826,8 @@ static struct clk_rcg2 sdcc1_ice_core_clk_src = {
.parent_map = gcc_xo_gpll0_gpll6_gpll0_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "sdcc1_ice_core_clk_src",
- .parent_names = gcc_xo_gpll0_gpll6_gpll0_div2,
- .num_parents = 4,
+ .parent_data = gcc_xo_gpll0_gpll6_gpll0_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll6_gpll0_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -1108,8 +840,8 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
.parent_map = gcc_xo_gpll0_gpll2_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "sdcc2_apps_clk_src",
- .parent_names = gcc_xo_gpll0_gpll2_gpll0_out_main_div2,
- .num_parents = 4,
+ .parent_data = gcc_xo_gpll0_gpll2_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll2_gpll0_out_main_div2),
.ops = &clk_rcg2_floor_ops,
},
};
@@ -1121,6 +853,18 @@ static const struct freq_tbl ftbl_usb_master_clk_src[] = {
{ }
};
+static const struct clk_parent_data gcc_xo_gpll0_out_main_div2_gpll0[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .hw = &gpll0_out_main_div2.hw },
+ { .hw = &gpll0.clkr.hw },
+};
+
+static const struct parent_map gcc_xo_gpll0_out_main_div2_gpll0_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0_DIV2, 2 },
+ { P_GPLL0, 1 },
+};
+
static struct clk_rcg2 usb0_master_clk_src = {
.cmd_rcgr = 0x3e00c,
.freq_tbl = ftbl_usb_master_clk_src,
@@ -1129,8 +873,8 @@ static struct clk_rcg2 usb0_master_clk_src = {
.parent_map = gcc_xo_gpll0_out_main_div2_gpll0_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "usb0_master_clk_src",
- .parent_names = gcc_xo_gpll0_out_main_div2_gpll0,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_out_main_div2_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_out_main_div2_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -1148,8 +892,8 @@ static struct clk_rcg2 usb0_aux_clk_src = {
.parent_map = gcc_xo_gpll0_sleep_clk_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "usb0_aux_clk_src",
- .parent_names = gcc_xo_gpll0_sleep_clk,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_sleep_clk,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_sleep_clk),
.ops = &clk_rcg2_ops,
},
};
@@ -1161,6 +905,20 @@ static const struct freq_tbl ftbl_usb_mock_utmi_clk_src[] = {
{ }
};
+static const struct clk_parent_data gcc_xo_gpll6_gpll0_gpll0_out_main_div2[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .hw = &gpll6.clkr.hw },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll0_out_main_div2.hw },
+};
+
+static const struct parent_map gcc_xo_gpll6_gpll0_gpll0_out_main_div2_map[] = {
+ { P_XO, 0 },
+ { P_GPLL6, 1 },
+ { P_GPLL0, 3 },
+ { P_GPLL0_DIV2, 4 },
+};
+
static struct clk_rcg2 usb0_mock_utmi_clk_src = {
.cmd_rcgr = 0x3e020,
.freq_tbl = ftbl_usb_mock_utmi_clk_src,
@@ -1169,12 +927,22 @@ static struct clk_rcg2 usb0_mock_utmi_clk_src = {
.parent_map = gcc_xo_gpll6_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "usb0_mock_utmi_clk_src",
- .parent_names = gcc_xo_gpll6_gpll0_gpll0_out_main_div2,
- .num_parents = 4,
+ .parent_data = gcc_xo_gpll6_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll6_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
+static const struct clk_parent_data gcc_usb3phy_0_cc_pipe_clk_xo[] = {
+ { .name = "usb3phy_0_cc_pipe_clk" },
+ { .fw_name = "xo", .name = "xo" },
+};
+
+static const struct parent_map gcc_usb3phy_0_cc_pipe_clk_xo_map[] = {
+ { P_USB3PHY_0_PIPE, 0 },
+ { P_XO, 2 },
+};
+
static struct clk_regmap_mux usb0_pipe_clk_src = {
.reg = 0x3e048,
.shift = 8,
@@ -1183,8 +951,8 @@ static struct clk_regmap_mux usb0_pipe_clk_src = {
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "usb0_pipe_clk_src",
- .parent_names = gcc_usb3phy_0_cc_pipe_clk_xo,
- .num_parents = 2,
+ .parent_data = gcc_usb3phy_0_cc_pipe_clk_xo,
+ .num_parents = ARRAY_SIZE(gcc_usb3phy_0_cc_pipe_clk_xo),
.ops = &clk_regmap_mux_closest_ops,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1199,8 +967,8 @@ static struct clk_rcg2 usb1_master_clk_src = {
.parent_map = gcc_xo_gpll0_out_main_div2_gpll0_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "usb1_master_clk_src",
- .parent_names = gcc_xo_gpll0_out_main_div2_gpll0,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_out_main_div2_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_out_main_div2_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -1213,8 +981,8 @@ static struct clk_rcg2 usb1_aux_clk_src = {
.parent_map = gcc_xo_gpll0_sleep_clk_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "usb1_aux_clk_src",
- .parent_names = gcc_xo_gpll0_sleep_clk,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_sleep_clk,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_sleep_clk),
.ops = &clk_rcg2_ops,
},
};
@@ -1227,12 +995,22 @@ static struct clk_rcg2 usb1_mock_utmi_clk_src = {
.parent_map = gcc_xo_gpll6_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "usb1_mock_utmi_clk_src",
- .parent_names = gcc_xo_gpll6_gpll0_gpll0_out_main_div2,
- .num_parents = 4,
+ .parent_data = gcc_xo_gpll6_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll6_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
+static const struct clk_parent_data gcc_usb3phy_1_cc_pipe_clk_xo[] = {
+ { .name = "usb3phy_1_cc_pipe_clk" },
+ { .fw_name = "xo", .name = "xo" },
+};
+
+static const struct parent_map gcc_usb3phy_1_cc_pipe_clk_xo_map[] = {
+ { P_USB3PHY_1_PIPE, 0 },
+ { P_XO, 2 },
+};
+
static struct clk_regmap_mux usb1_pipe_clk_src = {
.reg = 0x3f048,
.shift = 8,
@@ -1241,8 +1019,8 @@ static struct clk_regmap_mux usb1_pipe_clk_src = {
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "usb1_pipe_clk_src",
- .parent_names = gcc_usb3phy_1_cc_pipe_clk_xo,
- .num_parents = 2,
+ .parent_data = gcc_usb3phy_1_cc_pipe_clk_xo,
+ .num_parents = ARRAY_SIZE(gcc_usb3phy_1_cc_pipe_clk_xo),
.ops = &clk_regmap_mux_closest_ops,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1256,8 +1034,9 @@ static struct clk_branch gcc_xo_clk_src = {
.enable_mask = BIT(1),
.hw.init = &(struct clk_init_data){
.name = "gcc_xo_clk_src",
- .parent_names = (const char *[]){
- "xo"
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo",
+ .name = "xo",
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
@@ -1271,9 +1050,8 @@ static struct clk_fixed_factor gcc_xo_div4_clk_src = {
.div = 4,
.hw.init = &(struct clk_init_data){
.name = "gcc_xo_div4_clk_src",
- .parent_names = (const char *[]){
- "gcc_xo_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_xo_clk_src.clkr.hw },
.num_parents = 1,
.ops = &clk_fixed_factor_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -1291,6 +1069,20 @@ static const struct freq_tbl ftbl_system_noc_bfdcd_clk_src[] = {
{ }
};
+static const struct clk_parent_data gcc_xo_gpll0_gpll6_gpll0_out_main_div2[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll6.clkr.hw },
+ { .hw = &gpll0_out_main_div2.hw },
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll6_gpll0_out_main_div2_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL6, 2 },
+ { P_GPLL0_DIV2, 3 },
+};
+
static struct clk_rcg2 system_noc_bfdcd_clk_src = {
.cmd_rcgr = 0x26004,
.freq_tbl = ftbl_system_noc_bfdcd_clk_src,
@@ -1298,8 +1090,8 @@ static struct clk_rcg2 system_noc_bfdcd_clk_src = {
.parent_map = gcc_xo_gpll0_gpll6_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "system_noc_bfdcd_clk_src",
- .parent_names = gcc_xo_gpll0_gpll6_gpll0_out_main_div2,
- .num_parents = 4,
+ .parent_data = gcc_xo_gpll0_gpll6_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll6_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
.flags = CLK_IS_CRITICAL,
},
@@ -1310,9 +1102,8 @@ static struct clk_fixed_factor system_noc_clk_src = {
.div = 1,
.hw.init = &(struct clk_init_data){
.name = "system_noc_clk_src",
- .parent_names = (const char *[]){
- "system_noc_bfdcd_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &system_noc_bfdcd_clk_src.clkr.hw },
.num_parents = 1,
.ops = &clk_fixed_factor_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -1333,7 +1124,7 @@ static struct clk_rcg2 nss_ce_clk_src = {
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_ce_clk_src",
.parent_data = gcc_xo_gpll0,
- .num_parents = 2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -1344,6 +1135,20 @@ static const struct freq_tbl ftbl_nss_noc_bfdcd_clk_src[] = {
{ }
};
+static const struct clk_parent_data gcc_xo_bias_pll_nss_noc_clk_gpll0_gpll2[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .fw_name = "bias_pll_nss_noc_clk", .name = "bias_pll_nss_noc_clk" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll2.clkr.hw },
+};
+
+static const struct parent_map gcc_xo_bias_pll_nss_noc_clk_gpll0_gpll2_map[] = {
+ { P_XO, 0 },
+ { P_BIAS_PLL_NSS_NOC, 1 },
+ { P_GPLL0, 2 },
+ { P_GPLL2, 3 },
+};
+
static struct clk_rcg2 nss_noc_bfdcd_clk_src = {
.cmd_rcgr = 0x68088,
.freq_tbl = ftbl_nss_noc_bfdcd_clk_src,
@@ -1351,8 +1156,8 @@ static struct clk_rcg2 nss_noc_bfdcd_clk_src = {
.parent_map = gcc_xo_bias_pll_nss_noc_clk_gpll0_gpll2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_noc_bfdcd_clk_src",
- .parent_names = gcc_xo_bias_pll_nss_noc_clk_gpll0_gpll2,
- .num_parents = 4,
+ .parent_data = gcc_xo_bias_pll_nss_noc_clk_gpll0_gpll2,
+ .num_parents = ARRAY_SIZE(gcc_xo_bias_pll_nss_noc_clk_gpll0_gpll2),
.ops = &clk_rcg2_ops,
},
};
@@ -1362,9 +1167,8 @@ static struct clk_fixed_factor nss_noc_clk_src = {
.div = 1,
.hw.init = &(struct clk_init_data){
.name = "nss_noc_clk_src",
- .parent_names = (const char *[]){
- "nss_noc_bfdcd_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_noc_bfdcd_clk_src.clkr.hw },
.num_parents = 1,
.ops = &clk_fixed_factor_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -1377,6 +1181,18 @@ static const struct freq_tbl ftbl_nss_crypto_clk_src[] = {
{ }
};
+static const struct clk_parent_data gcc_xo_nss_crypto_pll_gpll0[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .hw = &nss_crypto_pll.clkr.hw },
+ { .hw = &gpll0.clkr.hw },
+};
+
+static const struct parent_map gcc_xo_nss_crypto_pll_gpll0_map[] = {
+ { P_XO, 0 },
+ { P_NSS_CRYPTO_PLL, 1 },
+ { P_GPLL0, 2 },
+};
+
static struct clk_rcg2 nss_crypto_clk_src = {
.cmd_rcgr = 0x68144,
.freq_tbl = ftbl_nss_crypto_clk_src,
@@ -1385,8 +1201,8 @@ static struct clk_rcg2 nss_crypto_clk_src = {
.parent_map = gcc_xo_nss_crypto_pll_gpll0_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_crypto_clk_src",
- .parent_names = gcc_xo_nss_crypto_pll_gpll0,
- .num_parents = 3,
+ .parent_data = gcc_xo_nss_crypto_pll_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_nss_crypto_pll_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -1400,6 +1216,24 @@ static const struct freq_tbl ftbl_nss_ubi_clk_src[] = {
{ }
};
+static const struct clk_parent_data gcc_xo_ubi32_pll_gpll0_gpll2_gpll4_gpll6[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .hw = &ubi32_pll.clkr.hw },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll2.clkr.hw },
+ { .hw = &gpll4.clkr.hw },
+ { .hw = &gpll6.clkr.hw },
+};
+
+static const struct parent_map gcc_xo_ubi32_gpll0_gpll2_gpll4_gpll6_map[] = {
+ { P_XO, 0 },
+ { P_UBI32_PLL, 1 },
+ { P_GPLL0, 2 },
+ { P_GPLL2, 3 },
+ { P_GPLL4, 4 },
+ { P_GPLL6, 5 },
+};
+
static struct clk_rcg2 nss_ubi0_clk_src = {
.cmd_rcgr = 0x68104,
.freq_tbl = ftbl_nss_ubi_clk_src,
@@ -1407,8 +1241,8 @@ static struct clk_rcg2 nss_ubi0_clk_src = {
.parent_map = gcc_xo_ubi32_gpll0_gpll2_gpll4_gpll6_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_ubi0_clk_src",
- .parent_names = gcc_xo_ubi32_pll_gpll0_gpll2_gpll4_gpll6,
- .num_parents = 6,
+ .parent_data = gcc_xo_ubi32_pll_gpll0_gpll2_gpll4_gpll6,
+ .num_parents = ARRAY_SIZE(gcc_xo_ubi32_pll_gpll0_gpll2_gpll4_gpll6),
.ops = &clk_rcg2_ops,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1421,9 +1255,8 @@ static struct clk_regmap_div nss_ubi0_div_clk_src = {
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "nss_ubi0_div_clk_src",
- .parent_names = (const char *[]){
- "nss_ubi0_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ubi0_clk_src.clkr.hw },
.num_parents = 1,
.ops = &clk_regmap_div_ro_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -1438,8 +1271,8 @@ static struct clk_rcg2 nss_ubi1_clk_src = {
.parent_map = gcc_xo_ubi32_gpll0_gpll2_gpll4_gpll6_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_ubi1_clk_src",
- .parent_names = gcc_xo_ubi32_pll_gpll0_gpll2_gpll4_gpll6,
- .num_parents = 6,
+ .parent_data = gcc_xo_ubi32_pll_gpll0_gpll2_gpll4_gpll6,
+ .num_parents = ARRAY_SIZE(gcc_xo_ubi32_pll_gpll0_gpll2_gpll4_gpll6),
.ops = &clk_rcg2_ops,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1452,9 +1285,8 @@ static struct clk_regmap_div nss_ubi1_div_clk_src = {
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "nss_ubi1_div_clk_src",
- .parent_names = (const char *[]){
- "nss_ubi1_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ubi1_clk_src.clkr.hw },
.num_parents = 1,
.ops = &clk_regmap_div_ro_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -1468,6 +1300,16 @@ static const struct freq_tbl ftbl_ubi_mpt_clk_src[] = {
{ }
};
+static const struct clk_parent_data gcc_xo_gpll0_out_main_div2[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .hw = &gpll0_out_main_div2.hw },
+};
+
+static const struct parent_map gcc_xo_gpll0_out_main_div2_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0_DIV2, 1 },
+};
+
static struct clk_rcg2 ubi_mpt_clk_src = {
.cmd_rcgr = 0x68090,
.freq_tbl = ftbl_ubi_mpt_clk_src,
@@ -1475,8 +1317,8 @@ static struct clk_rcg2 ubi_mpt_clk_src = {
.parent_map = gcc_xo_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "ubi_mpt_clk_src",
- .parent_names = gcc_xo_gpll0_out_main_div2,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -1487,6 +1329,18 @@ static const struct freq_tbl ftbl_nss_imem_clk_src[] = {
{ }
};
+static const struct clk_parent_data gcc_xo_gpll0_gpll4[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll4.clkr.hw },
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll4_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL4, 2 },
+};
+
static struct clk_rcg2 nss_imem_clk_src = {
.cmd_rcgr = 0x68158,
.freq_tbl = ftbl_nss_imem_clk_src,
@@ -1494,8 +1348,8 @@ static struct clk_rcg2 nss_imem_clk_src = {
.parent_map = gcc_xo_gpll0_gpll4_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_imem_clk_src",
- .parent_names = gcc_xo_gpll0_gpll4,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll4,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll4),
.ops = &clk_rcg2_ops,
},
};
@@ -1506,6 +1360,24 @@ static const struct freq_tbl ftbl_nss_ppe_clk_src[] = {
{ }
};
+static const struct clk_parent_data gcc_xo_bias_gpll0_gpll4_nss_ubi32[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .fw_name = "bias_pll_cc_clk", .name = "bias_pll_cc_clk" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll4.clkr.hw },
+ { .hw = &nss_crypto_pll.clkr.hw },
+ { .hw = &ubi32_pll.clkr.hw },
+};
+
+static const struct parent_map gcc_xo_bias_gpll0_gpll4_nss_ubi32_map[] = {
+ { P_XO, 0 },
+ { P_BIAS_PLL, 1 },
+ { P_GPLL0, 2 },
+ { P_GPLL4, 3 },
+ { P_NSS_CRYPTO_PLL, 4 },
+ { P_UBI32_PLL, 5 },
+};
+
static struct clk_rcg2 nss_ppe_clk_src = {
.cmd_rcgr = 0x68080,
.freq_tbl = ftbl_nss_ppe_clk_src,
@@ -1513,8 +1385,8 @@ static struct clk_rcg2 nss_ppe_clk_src = {
.parent_map = gcc_xo_bias_gpll0_gpll4_nss_ubi32_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_ppe_clk_src",
- .parent_names = gcc_xo_bias_gpll0_gpll4_nss_ubi32,
- .num_parents = 6,
+ .parent_data = gcc_xo_bias_gpll0_gpll4_nss_ubi32,
+ .num_parents = ARRAY_SIZE(gcc_xo_bias_gpll0_gpll4_nss_ubi32),
.ops = &clk_rcg2_ops,
},
};
@@ -1524,9 +1396,8 @@ static struct clk_fixed_factor nss_ppe_cdiv_clk_src = {
.div = 4,
.hw.init = &(struct clk_init_data){
.name = "nss_ppe_cdiv_clk_src",
- .parent_names = (const char *[]){
- "nss_ppe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ppe_clk_src.clkr.hw },
.num_parents = 1,
.ops = &clk_fixed_factor_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -1540,6 +1411,22 @@ static const struct freq_tbl ftbl_nss_port1_rx_clk_src[] = {
{ }
};
+static const struct clk_parent_data gcc_xo_uniphy0_rx_tx_ubi32_bias[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .fw_name = "uniphy0_gcc_rx_clk", .name = "uniphy0_gcc_rx_clk" },
+ { .fw_name = "uniphy0_gcc_tx_clk", .name = "uniphy0_gcc_tx_clk" },
+ { .hw = &ubi32_pll.clkr.hw },
+ { .fw_name = "bias_pll_cc_clk", .name = "bias_pll_cc_clk" },
+};
+
+static const struct parent_map gcc_xo_uniphy0_rx_tx_ubi32_bias_map[] = {
+ { P_XO, 0 },
+ { P_UNIPHY0_RX, 1 },
+ { P_UNIPHY0_TX, 2 },
+ { P_UBI32_PLL, 5 },
+ { P_BIAS_PLL, 6 },
+};
+
static struct clk_rcg2 nss_port1_rx_clk_src = {
.cmd_rcgr = 0x68020,
.freq_tbl = ftbl_nss_port1_rx_clk_src,
@@ -1547,8 +1434,8 @@ static struct clk_rcg2 nss_port1_rx_clk_src = {
.parent_map = gcc_xo_uniphy0_rx_tx_ubi32_bias_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_port1_rx_clk_src",
- .parent_names = gcc_xo_uniphy0_rx_tx_ubi32_bias,
- .num_parents = 5,
+ .parent_data = gcc_xo_uniphy0_rx_tx_ubi32_bias,
+ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_rx_tx_ubi32_bias),
.ops = &clk_rcg2_ops,
},
};
@@ -1560,9 +1447,8 @@ static struct clk_regmap_div nss_port1_rx_div_clk_src = {
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "nss_port1_rx_div_clk_src",
- .parent_names = (const char *[]){
- "nss_port1_rx_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port1_rx_clk_src.clkr.hw },
.num_parents = 1,
.ops = &clk_regmap_div_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -1577,6 +1463,22 @@ static const struct freq_tbl ftbl_nss_port1_tx_clk_src[] = {
{ }
};
+static const struct clk_parent_data gcc_xo_uniphy0_tx_rx_ubi32_bias[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .fw_name = "uniphy0_gcc_tx_clk", .name = "uniphy0_gcc_tx_clk" },
+ { .fw_name = "uniphy0_gcc_rx_clk", .name = "uniphy0_gcc_rx_clk" },
+ { .hw = &ubi32_pll.clkr.hw },
+ { .fw_name = "bias_pll_cc_clk", .name = "bias_pll_cc_clk" },
+};
+
+static const struct parent_map gcc_xo_uniphy0_tx_rx_ubi32_bias_map[] = {
+ { P_XO, 0 },
+ { P_UNIPHY0_TX, 1 },
+ { P_UNIPHY0_RX, 2 },
+ { P_UBI32_PLL, 5 },
+ { P_BIAS_PLL, 6 },
+};
+
static struct clk_rcg2 nss_port1_tx_clk_src = {
.cmd_rcgr = 0x68028,
.freq_tbl = ftbl_nss_port1_tx_clk_src,
@@ -1584,8 +1486,8 @@ static struct clk_rcg2 nss_port1_tx_clk_src = {
.parent_map = gcc_xo_uniphy0_tx_rx_ubi32_bias_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_port1_tx_clk_src",
- .parent_names = gcc_xo_uniphy0_tx_rx_ubi32_bias,
- .num_parents = 5,
+ .parent_data = gcc_xo_uniphy0_tx_rx_ubi32_bias,
+ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_tx_rx_ubi32_bias),
.ops = &clk_rcg2_ops,
},
};
@@ -1597,9 +1499,8 @@ static struct clk_regmap_div nss_port1_tx_div_clk_src = {
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "nss_port1_tx_div_clk_src",
- .parent_names = (const char *[]){
- "nss_port1_tx_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port1_tx_clk_src.clkr.hw },
.num_parents = 1,
.ops = &clk_regmap_div_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -1614,8 +1515,8 @@ static struct clk_rcg2 nss_port2_rx_clk_src = {
.parent_map = gcc_xo_uniphy0_rx_tx_ubi32_bias_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_port2_rx_clk_src",
- .parent_names = gcc_xo_uniphy0_rx_tx_ubi32_bias,
- .num_parents = 5,
+ .parent_data = gcc_xo_uniphy0_rx_tx_ubi32_bias,
+ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_rx_tx_ubi32_bias),
.ops = &clk_rcg2_ops,
},
};
@@ -1627,9 +1528,8 @@ static struct clk_regmap_div nss_port2_rx_div_clk_src = {
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "nss_port2_rx_div_clk_src",
- .parent_names = (const char *[]){
- "nss_port2_rx_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port2_rx_clk_src.clkr.hw },
.num_parents = 1,
.ops = &clk_regmap_div_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -1644,8 +1544,8 @@ static struct clk_rcg2 nss_port2_tx_clk_src = {
.parent_map = gcc_xo_uniphy0_tx_rx_ubi32_bias_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_port2_tx_clk_src",
- .parent_names = gcc_xo_uniphy0_tx_rx_ubi32_bias,
- .num_parents = 5,
+ .parent_data = gcc_xo_uniphy0_tx_rx_ubi32_bias,
+ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_tx_rx_ubi32_bias),
.ops = &clk_rcg2_ops,
},
};
@@ -1657,9 +1557,8 @@ static struct clk_regmap_div nss_port2_tx_div_clk_src = {
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "nss_port2_tx_div_clk_src",
- .parent_names = (const char *[]){
- "nss_port2_tx_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port2_tx_clk_src.clkr.hw },
.num_parents = 1,
.ops = &clk_regmap_div_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -1674,8 +1573,8 @@ static struct clk_rcg2 nss_port3_rx_clk_src = {
.parent_map = gcc_xo_uniphy0_rx_tx_ubi32_bias_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_port3_rx_clk_src",
- .parent_names = gcc_xo_uniphy0_rx_tx_ubi32_bias,
- .num_parents = 5,
+ .parent_data = gcc_xo_uniphy0_rx_tx_ubi32_bias,
+ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_rx_tx_ubi32_bias),
.ops = &clk_rcg2_ops,
},
};
@@ -1687,9 +1586,8 @@ static struct clk_regmap_div nss_port3_rx_div_clk_src = {
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "nss_port3_rx_div_clk_src",
- .parent_names = (const char *[]){
- "nss_port3_rx_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port3_rx_clk_src.clkr.hw },
.num_parents = 1,
.ops = &clk_regmap_div_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -1704,8 +1602,8 @@ static struct clk_rcg2 nss_port3_tx_clk_src = {
.parent_map = gcc_xo_uniphy0_tx_rx_ubi32_bias_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_port3_tx_clk_src",
- .parent_names = gcc_xo_uniphy0_tx_rx_ubi32_bias,
- .num_parents = 5,
+ .parent_data = gcc_xo_uniphy0_tx_rx_ubi32_bias,
+ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_tx_rx_ubi32_bias),
.ops = &clk_rcg2_ops,
},
};
@@ -1717,9 +1615,8 @@ static struct clk_regmap_div nss_port3_tx_div_clk_src = {
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "nss_port3_tx_div_clk_src",
- .parent_names = (const char *[]){
- "nss_port3_tx_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port3_tx_clk_src.clkr.hw },
.num_parents = 1,
.ops = &clk_regmap_div_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -1734,8 +1631,8 @@ static struct clk_rcg2 nss_port4_rx_clk_src = {
.parent_map = gcc_xo_uniphy0_rx_tx_ubi32_bias_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_port4_rx_clk_src",
- .parent_names = gcc_xo_uniphy0_rx_tx_ubi32_bias,
- .num_parents = 5,
+ .parent_data = gcc_xo_uniphy0_rx_tx_ubi32_bias,
+ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_rx_tx_ubi32_bias),
.ops = &clk_rcg2_ops,
},
};
@@ -1747,9 +1644,8 @@ static struct clk_regmap_div nss_port4_rx_div_clk_src = {
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "nss_port4_rx_div_clk_src",
- .parent_names = (const char *[]){
- "nss_port4_rx_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port4_rx_clk_src.clkr.hw },
.num_parents = 1,
.ops = &clk_regmap_div_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -1764,8 +1660,8 @@ static struct clk_rcg2 nss_port4_tx_clk_src = {
.parent_map = gcc_xo_uniphy0_tx_rx_ubi32_bias_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_port4_tx_clk_src",
- .parent_names = gcc_xo_uniphy0_tx_rx_ubi32_bias,
- .num_parents = 5,
+ .parent_data = gcc_xo_uniphy0_tx_rx_ubi32_bias,
+ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_tx_rx_ubi32_bias),
.ops = &clk_rcg2_ops,
},
};
@@ -1777,9 +1673,8 @@ static struct clk_regmap_div nss_port4_tx_div_clk_src = {
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "nss_port4_tx_div_clk_src",
- .parent_names = (const char *[]){
- "nss_port4_tx_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port4_tx_clk_src.clkr.hw },
.num_parents = 1,
.ops = &clk_regmap_div_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -1799,6 +1694,27 @@ static const struct freq_tbl ftbl_nss_port5_rx_clk_src[] = {
{ }
};
+static const struct clk_parent_data gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .fw_name = "uniphy0_gcc_rx_clk", .name = "uniphy0_gcc_rx_clk" },
+ { .fw_name = "uniphy0_gcc_tx_clk", .name = "uniphy0_gcc_tx_clk" },
+ { .fw_name = "uniphy1_gcc_rx_clk", .name = "uniphy1_gcc_rx_clk" },
+ { .fw_name = "uniphy1_gcc_tx_clk", .name = "uniphy1_gcc_tx_clk" },
+ { .hw = &ubi32_pll.clkr.hw },
+ { .fw_name = "bias_pll_cc_clk", .name = "bias_pll_cc_clk" },
+};
+
+static const struct parent_map
+gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias_map[] = {
+ { P_XO, 0 },
+ { P_UNIPHY0_RX, 1 },
+ { P_UNIPHY0_TX, 2 },
+ { P_UNIPHY1_RX, 3 },
+ { P_UNIPHY1_TX, 4 },
+ { P_UBI32_PLL, 5 },
+ { P_BIAS_PLL, 6 },
+};
+
static struct clk_rcg2 nss_port5_rx_clk_src = {
.cmd_rcgr = 0x68060,
.freq_tbl = ftbl_nss_port5_rx_clk_src,
@@ -1806,8 +1722,8 @@ static struct clk_rcg2 nss_port5_rx_clk_src = {
.parent_map = gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_port5_rx_clk_src",
- .parent_names = gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias,
- .num_parents = 7,
+ .parent_data = gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias,
+ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias),
.ops = &clk_rcg2_ops,
},
};
@@ -1819,9 +1735,8 @@ static struct clk_regmap_div nss_port5_rx_div_clk_src = {
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "nss_port5_rx_div_clk_src",
- .parent_names = (const char *[]){
- "nss_port5_rx_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port5_rx_clk_src.clkr.hw },
.num_parents = 1,
.ops = &clk_regmap_div_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -1841,6 +1756,27 @@ static const struct freq_tbl ftbl_nss_port5_tx_clk_src[] = {
{ }
};
+static const struct clk_parent_data gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .fw_name = "uniphy0_gcc_tx_clk", .name = "uniphy0_gcc_tx_clk" },
+ { .fw_name = "uniphy0_gcc_rx_clk", .name = "uniphy0_gcc_rx_clk" },
+ { .fw_name = "uniphy1_gcc_tx_clk", .name = "uniphy1_gcc_tx_clk" },
+ { .fw_name = "uniphy1_gcc_rx_clk", .name = "uniphy1_gcc_rx_clk" },
+ { .hw = &ubi32_pll.clkr.hw },
+ { .fw_name = "bias_pll_cc_clk", .name = "bias_pll_cc_clk" },
+};
+
+static const struct parent_map
+gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias_map[] = {
+ { P_XO, 0 },
+ { P_UNIPHY0_TX, 1 },
+ { P_UNIPHY0_RX, 2 },
+ { P_UNIPHY1_TX, 3 },
+ { P_UNIPHY1_RX, 4 },
+ { P_UBI32_PLL, 5 },
+ { P_BIAS_PLL, 6 },
+};
+
static struct clk_rcg2 nss_port5_tx_clk_src = {
.cmd_rcgr = 0x68068,
.freq_tbl = ftbl_nss_port5_tx_clk_src,
@@ -1848,8 +1784,8 @@ static struct clk_rcg2 nss_port5_tx_clk_src = {
.parent_map = gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_port5_tx_clk_src",
- .parent_names = gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias,
- .num_parents = 7,
+ .parent_data = gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias,
+ .num_parents = ARRAY_SIZE(gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias),
.ops = &clk_rcg2_ops,
},
};
@@ -1861,9 +1797,8 @@ static struct clk_regmap_div nss_port5_tx_div_clk_src = {
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "nss_port5_tx_div_clk_src",
- .parent_names = (const char *[]){
- "nss_port5_tx_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port5_tx_clk_src.clkr.hw },
.num_parents = 1,
.ops = &clk_regmap_div_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -1883,6 +1818,22 @@ static const struct freq_tbl ftbl_nss_port6_rx_clk_src[] = {
{ }
};
+static const struct clk_parent_data gcc_xo_uniphy2_rx_tx_ubi32_bias[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .fw_name = "uniphy2_gcc_rx_clk", .name = "uniphy2_gcc_rx_clk" },
+ { .fw_name = "uniphy2_gcc_tx_clk", .name = "uniphy2_gcc_tx_clk" },
+ { .hw = &ubi32_pll.clkr.hw },
+ { .fw_name = "bias_pll_cc_clk", .name = "bias_pll_cc_clk" },
+};
+
+static const struct parent_map gcc_xo_uniphy2_rx_tx_ubi32_bias_map[] = {
+ { P_XO, 0 },
+ { P_UNIPHY2_RX, 1 },
+ { P_UNIPHY2_TX, 2 },
+ { P_UBI32_PLL, 5 },
+ { P_BIAS_PLL, 6 },
+};
+
static struct clk_rcg2 nss_port6_rx_clk_src = {
.cmd_rcgr = 0x68070,
.freq_tbl = ftbl_nss_port6_rx_clk_src,
@@ -1890,8 +1841,8 @@ static struct clk_rcg2 nss_port6_rx_clk_src = {
.parent_map = gcc_xo_uniphy2_rx_tx_ubi32_bias_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_port6_rx_clk_src",
- .parent_names = gcc_xo_uniphy2_rx_tx_ubi32_bias,
- .num_parents = 5,
+ .parent_data = gcc_xo_uniphy2_rx_tx_ubi32_bias,
+ .num_parents = ARRAY_SIZE(gcc_xo_uniphy2_rx_tx_ubi32_bias),
.ops = &clk_rcg2_ops,
},
};
@@ -1903,9 +1854,8 @@ static struct clk_regmap_div nss_port6_rx_div_clk_src = {
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "nss_port6_rx_div_clk_src",
- .parent_names = (const char *[]){
- "nss_port6_rx_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port6_rx_clk_src.clkr.hw },
.num_parents = 1,
.ops = &clk_regmap_div_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -1925,6 +1875,22 @@ static const struct freq_tbl ftbl_nss_port6_tx_clk_src[] = {
{ }
};
+static const struct clk_parent_data gcc_xo_uniphy2_tx_rx_ubi32_bias[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .fw_name = "uniphy2_gcc_tx_clk", .name = "uniphy2_gcc_tx_clk" },
+ { .fw_name = "uniphy2_gcc_rx_clk", .name = "uniphy2_gcc_rx_clk" },
+ { .hw = &ubi32_pll.clkr.hw },
+ { .fw_name = "bias_pll_cc_clk", .name = "bias_pll_cc_clk" },
+};
+
+static const struct parent_map gcc_xo_uniphy2_tx_rx_ubi32_bias_map[] = {
+ { P_XO, 0 },
+ { P_UNIPHY2_TX, 1 },
+ { P_UNIPHY2_RX, 2 },
+ { P_UBI32_PLL, 5 },
+ { P_BIAS_PLL, 6 },
+};
+
static struct clk_rcg2 nss_port6_tx_clk_src = {
.cmd_rcgr = 0x68078,
.freq_tbl = ftbl_nss_port6_tx_clk_src,
@@ -1932,8 +1898,8 @@ static struct clk_rcg2 nss_port6_tx_clk_src = {
.parent_map = gcc_xo_uniphy2_tx_rx_ubi32_bias_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "nss_port6_tx_clk_src",
- .parent_names = gcc_xo_uniphy2_tx_rx_ubi32_bias,
- .num_parents = 5,
+ .parent_data = gcc_xo_uniphy2_tx_rx_ubi32_bias,
+ .num_parents = ARRAY_SIZE(gcc_xo_uniphy2_tx_rx_ubi32_bias),
.ops = &clk_rcg2_ops,
},
};
@@ -1945,9 +1911,8 @@ static struct clk_regmap_div nss_port6_tx_div_clk_src = {
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "nss_port6_tx_div_clk_src",
- .parent_names = (const char *[]){
- "nss_port6_tx_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port6_tx_clk_src.clkr.hw },
.num_parents = 1,
.ops = &clk_regmap_div_ops,
.flags = CLK_SET_RATE_PARENT,
@@ -1970,8 +1935,8 @@ static struct clk_rcg2 crypto_clk_src = {
.parent_map = gcc_xo_gpll0_gpll0_out_main_div2_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "crypto_clk_src",
- .parent_names = gcc_xo_gpll0_gpll0_out_main_div2,
- .num_parents = 3,
+ .parent_data = gcc_xo_gpll0_gpll0_out_main_div2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll0_out_main_div2),
.ops = &clk_rcg2_ops,
},
};
@@ -1981,6 +1946,22 @@ static struct freq_tbl ftbl_gp_clk_src[] = {
{ }
};
+static const struct clk_parent_data gcc_xo_gpll0_gpll6_gpll0_sleep_clk[] = {
+ { .fw_name = "xo", .name = "xo" },
+ { .hw = &gpll0.clkr.hw },
+ { .hw = &gpll6.clkr.hw },
+ { .hw = &gpll0_out_main_div2.hw },
+ { .fw_name = "sleep_clk", .name = "sleep_clk" },
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll6_gpll0_sleep_clk_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL6, 2 },
+ { P_GPLL0_DIV2, 4 },
+ { P_SLEEP_CLK, 6 },
+};
+
static struct clk_rcg2 gp1_clk_src = {
.cmd_rcgr = 0x08004,
.freq_tbl = ftbl_gp_clk_src,
@@ -1989,8 +1970,8 @@ static struct clk_rcg2 gp1_clk_src = {
.parent_map = gcc_xo_gpll0_gpll6_gpll0_sleep_clk_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "gp1_clk_src",
- .parent_names = gcc_xo_gpll0_gpll6_gpll0_sleep_clk,
- .num_parents = 5,
+ .parent_data = gcc_xo_gpll0_gpll6_gpll0_sleep_clk,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll6_gpll0_sleep_clk),
.ops = &clk_rcg2_ops,
},
};
@@ -2003,8 +1984,8 @@ static struct clk_rcg2 gp2_clk_src = {
.parent_map = gcc_xo_gpll0_gpll6_gpll0_sleep_clk_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "gp2_clk_src",
- .parent_names = gcc_xo_gpll0_gpll6_gpll0_sleep_clk,
- .num_parents = 5,
+ .parent_data = gcc_xo_gpll0_gpll6_gpll0_sleep_clk,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll6_gpll0_sleep_clk),
.ops = &clk_rcg2_ops,
},
};
@@ -2017,8 +1998,8 @@ static struct clk_rcg2 gp3_clk_src = {
.parent_map = gcc_xo_gpll0_gpll6_gpll0_sleep_clk_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "gp3_clk_src",
- .parent_names = gcc_xo_gpll0_gpll6_gpll0_sleep_clk,
- .num_parents = 5,
+ .parent_data = gcc_xo_gpll0_gpll6_gpll0_sleep_clk,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0_gpll6_gpll0_sleep_clk),
.ops = &clk_rcg2_ops,
},
};
@@ -2030,9 +2011,8 @@ static struct clk_branch gcc_blsp1_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_ahb_clk",
- .parent_names = (const char *[]){
- "pcnoc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcnoc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2047,9 +2027,8 @@ static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup1_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup1_i2c_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &blsp1_qup1_i2c_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2064,9 +2043,8 @@ static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup1_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup1_spi_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &blsp1_qup1_spi_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2081,9 +2059,8 @@ static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup2_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup2_i2c_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &blsp1_qup2_i2c_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2098,9 +2075,8 @@ static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup2_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup2_spi_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &blsp1_qup2_spi_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2115,9 +2091,8 @@ static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup3_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup3_i2c_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &blsp1_qup3_i2c_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2132,9 +2107,8 @@ static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup3_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup3_spi_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &blsp1_qup3_spi_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2149,9 +2123,8 @@ static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup4_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup4_i2c_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &blsp1_qup4_i2c_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2166,9 +2139,8 @@ static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup4_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup4_spi_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &blsp1_qup4_spi_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2183,9 +2155,8 @@ static struct clk_branch gcc_blsp1_qup5_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup5_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup5_i2c_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &blsp1_qup5_i2c_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2200,9 +2171,8 @@ static struct clk_branch gcc_blsp1_qup5_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup5_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup5_spi_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &blsp1_qup5_spi_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2217,9 +2187,8 @@ static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup6_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup6_i2c_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &blsp1_qup6_i2c_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2234,9 +2203,8 @@ static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup6_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup6_spi_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &blsp1_qup6_spi_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2251,9 +2219,8 @@ static struct clk_branch gcc_blsp1_uart1_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_uart1_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_uart1_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &blsp1_uart1_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2268,9 +2235,8 @@ static struct clk_branch gcc_blsp1_uart2_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_uart2_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_uart2_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &blsp1_uart2_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2285,9 +2251,8 @@ static struct clk_branch gcc_blsp1_uart3_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_uart3_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_uart3_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &blsp1_uart3_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2302,9 +2267,8 @@ static struct clk_branch gcc_blsp1_uart4_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_uart4_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_uart4_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &blsp1_uart4_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2319,9 +2283,8 @@ static struct clk_branch gcc_blsp1_uart5_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_uart5_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_uart5_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &blsp1_uart5_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2336,9 +2299,8 @@ static struct clk_branch gcc_blsp1_uart6_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_uart6_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_uart6_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &blsp1_uart6_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2354,9 +2316,8 @@ static struct clk_branch gcc_prng_ahb_clk = {
.enable_mask = BIT(8),
.hw.init = &(struct clk_init_data){
.name = "gcc_prng_ahb_clk",
- .parent_names = (const char *[]){
- "pcnoc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcnoc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2371,9 +2332,8 @@ static struct clk_branch gcc_qpic_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_qpic_ahb_clk",
- .parent_names = (const char *[]){
- "pcnoc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcnoc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2388,9 +2348,8 @@ static struct clk_branch gcc_qpic_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_qpic_clk",
- .parent_names = (const char *[]){
- "pcnoc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcnoc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2405,9 +2364,8 @@ static struct clk_branch gcc_pcie0_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie0_ahb_clk",
- .parent_names = (const char *[]){
- "pcnoc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcnoc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2422,9 +2380,8 @@ static struct clk_branch gcc_pcie0_aux_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie0_aux_clk",
- .parent_names = (const char *[]){
- "pcie0_aux_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcie0_aux_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2439,9 +2396,8 @@ static struct clk_branch gcc_pcie0_axi_m_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie0_axi_m_clk",
- .parent_names = (const char *[]){
- "pcie0_axi_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcie0_axi_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2456,9 +2412,8 @@ static struct clk_branch gcc_pcie0_axi_s_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie0_axi_s_clk",
- .parent_names = (const char *[]){
- "pcie0_axi_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcie0_axi_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2474,9 +2429,8 @@ static struct clk_branch gcc_pcie0_pipe_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie0_pipe_clk",
- .parent_names = (const char *[]){
- "pcie0_pipe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcie0_pipe_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2491,9 +2445,8 @@ static struct clk_branch gcc_sys_noc_pcie0_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sys_noc_pcie0_axi_clk",
- .parent_names = (const char *[]){
- "pcie0_axi_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcie0_axi_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2508,9 +2461,8 @@ static struct clk_branch gcc_pcie1_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie1_ahb_clk",
- .parent_names = (const char *[]){
- "pcnoc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcnoc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2525,9 +2477,8 @@ static struct clk_branch gcc_pcie1_aux_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie1_aux_clk",
- .parent_names = (const char *[]){
- "pcie1_aux_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcie1_aux_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2542,9 +2493,8 @@ static struct clk_branch gcc_pcie1_axi_m_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie1_axi_m_clk",
- .parent_names = (const char *[]){
- "pcie1_axi_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcie1_axi_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2559,9 +2509,8 @@ static struct clk_branch gcc_pcie1_axi_s_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie1_axi_s_clk",
- .parent_names = (const char *[]){
- "pcie1_axi_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcie1_axi_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2577,9 +2526,8 @@ static struct clk_branch gcc_pcie1_pipe_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pcie1_pipe_clk",
- .parent_names = (const char *[]){
- "pcie1_pipe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcie1_pipe_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2594,9 +2542,8 @@ static struct clk_branch gcc_sys_noc_pcie1_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sys_noc_pcie1_axi_clk",
- .parent_names = (const char *[]){
- "pcie1_axi_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcie1_axi_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2611,9 +2558,8 @@ static struct clk_branch gcc_usb0_aux_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb0_aux_clk",
- .parent_names = (const char *[]){
- "usb0_aux_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &usb0_aux_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2628,9 +2574,8 @@ static struct clk_branch gcc_sys_noc_usb0_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sys_noc_usb0_axi_clk",
- .parent_names = (const char *[]){
- "usb0_master_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &usb0_master_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2645,9 +2590,8 @@ static struct clk_branch gcc_usb0_master_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb0_master_clk",
- .parent_names = (const char *[]){
- "usb0_master_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &usb0_master_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2662,9 +2606,8 @@ static struct clk_branch gcc_usb0_mock_utmi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb0_mock_utmi_clk",
- .parent_names = (const char *[]){
- "usb0_mock_utmi_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &usb0_mock_utmi_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2679,9 +2622,8 @@ static struct clk_branch gcc_usb0_phy_cfg_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb0_phy_cfg_ahb_clk",
- .parent_names = (const char *[]){
- "pcnoc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcnoc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2697,9 +2639,8 @@ static struct clk_branch gcc_usb0_pipe_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb0_pipe_clk",
- .parent_names = (const char *[]){
- "usb0_pipe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &usb0_pipe_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2714,9 +2655,8 @@ static struct clk_branch gcc_usb0_sleep_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb0_sleep_clk",
- .parent_names = (const char *[]){
- "gcc_sleep_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_sleep_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2731,9 +2671,8 @@ static struct clk_branch gcc_usb1_aux_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb1_aux_clk",
- .parent_names = (const char *[]){
- "usb1_aux_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &usb1_aux_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2748,9 +2687,8 @@ static struct clk_branch gcc_sys_noc_usb1_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sys_noc_usb1_axi_clk",
- .parent_names = (const char *[]){
- "usb1_master_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &usb1_master_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2765,9 +2703,8 @@ static struct clk_branch gcc_usb1_master_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb1_master_clk",
- .parent_names = (const char *[]){
- "usb1_master_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &usb1_master_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2782,9 +2719,8 @@ static struct clk_branch gcc_usb1_mock_utmi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb1_mock_utmi_clk",
- .parent_names = (const char *[]){
- "usb1_mock_utmi_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &usb1_mock_utmi_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2799,9 +2735,8 @@ static struct clk_branch gcc_usb1_phy_cfg_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb1_phy_cfg_ahb_clk",
- .parent_names = (const char *[]){
- "pcnoc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcnoc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2817,9 +2752,8 @@ static struct clk_branch gcc_usb1_pipe_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb1_pipe_clk",
- .parent_names = (const char *[]){
- "usb1_pipe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &usb1_pipe_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2834,9 +2768,8 @@ static struct clk_branch gcc_usb1_sleep_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb1_sleep_clk",
- .parent_names = (const char *[]){
- "gcc_sleep_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_sleep_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2851,9 +2784,8 @@ static struct clk_branch gcc_sdcc1_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc1_ahb_clk",
- .parent_names = (const char *[]){
- "pcnoc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcnoc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2868,9 +2800,8 @@ static struct clk_branch gcc_sdcc1_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc1_apps_clk",
- .parent_names = (const char *[]){
- "sdcc1_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &sdcc1_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2885,9 +2816,8 @@ static struct clk_branch gcc_sdcc1_ice_core_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc1_ice_core_clk",
- .parent_names = (const char *[]){
- "sdcc1_ice_core_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &sdcc1_ice_core_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2902,9 +2832,8 @@ static struct clk_branch gcc_sdcc2_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc2_ahb_clk",
- .parent_names = (const char *[]){
- "pcnoc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcnoc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2919,9 +2848,8 @@ static struct clk_branch gcc_sdcc2_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc2_apps_clk",
- .parent_names = (const char *[]){
- "sdcc2_apps_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &sdcc2_apps_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2936,9 +2864,8 @@ static struct clk_branch gcc_mem_noc_nss_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_mem_noc_nss_axi_clk",
- .parent_names = (const char *[]){
- "nss_noc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_noc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2953,9 +2880,8 @@ static struct clk_branch gcc_nss_ce_apb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_ce_apb_clk",
- .parent_names = (const char *[]){
- "nss_ce_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ce_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2970,9 +2896,8 @@ static struct clk_branch gcc_nss_ce_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_ce_axi_clk",
- .parent_names = (const char *[]){
- "nss_ce_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ce_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -2987,9 +2912,8 @@ static struct clk_branch gcc_nss_cfg_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_cfg_clk",
- .parent_names = (const char *[]){
- "pcnoc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcnoc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3004,9 +2928,8 @@ static struct clk_branch gcc_nss_crypto_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_crypto_clk",
- .parent_names = (const char *[]){
- "nss_crypto_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_crypto_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3021,9 +2944,8 @@ static struct clk_branch gcc_nss_csr_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_csr_clk",
- .parent_names = (const char *[]){
- "nss_ce_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ce_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3038,9 +2960,8 @@ static struct clk_branch gcc_nss_edma_cfg_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_edma_cfg_clk",
- .parent_names = (const char *[]){
- "nss_ppe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ppe_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3055,9 +2976,8 @@ static struct clk_branch gcc_nss_edma_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_edma_clk",
- .parent_names = (const char *[]){
- "nss_ppe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ppe_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3072,9 +2992,8 @@ static struct clk_branch gcc_nss_imem_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_imem_clk",
- .parent_names = (const char *[]){
- "nss_imem_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_imem_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3089,9 +3008,8 @@ static struct clk_branch gcc_nss_noc_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_noc_clk",
- .parent_names = (const char *[]){
- "nss_noc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_noc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3106,9 +3024,8 @@ static struct clk_branch gcc_nss_ppe_btq_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_ppe_btq_clk",
- .parent_names = (const char *[]){
- "nss_ppe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ppe_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3123,9 +3040,8 @@ static struct clk_branch gcc_nss_ppe_cfg_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_ppe_cfg_clk",
- .parent_names = (const char *[]){
- "nss_ppe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ppe_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3140,9 +3056,8 @@ static struct clk_branch gcc_nss_ppe_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_ppe_clk",
- .parent_names = (const char *[]){
- "nss_ppe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ppe_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3157,9 +3072,8 @@ static struct clk_branch gcc_nss_ppe_ipe_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_ppe_ipe_clk",
- .parent_names = (const char *[]){
- "nss_ppe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ppe_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3174,9 +3088,8 @@ static struct clk_branch gcc_nss_ptp_ref_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_ptp_ref_clk",
- .parent_names = (const char *[]){
- "nss_ppe_cdiv_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ppe_cdiv_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3192,9 +3105,8 @@ static struct clk_branch gcc_crypto_ppe_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_crypto_ppe_clk",
- .parent_names = (const char *[]){
- "nss_ppe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ppe_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3209,9 +3121,8 @@ static struct clk_branch gcc_nssnoc_ce_apb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nssnoc_ce_apb_clk",
- .parent_names = (const char *[]){
- "nss_ce_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ce_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3226,9 +3137,8 @@ static struct clk_branch gcc_nssnoc_ce_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nssnoc_ce_axi_clk",
- .parent_names = (const char *[]){
- "nss_ce_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ce_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3243,9 +3153,8 @@ static struct clk_branch gcc_nssnoc_crypto_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nssnoc_crypto_clk",
- .parent_names = (const char *[]){
- "nss_crypto_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_crypto_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3260,9 +3169,8 @@ static struct clk_branch gcc_nssnoc_ppe_cfg_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nssnoc_ppe_cfg_clk",
- .parent_names = (const char *[]){
- "nss_ppe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ppe_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3277,9 +3185,8 @@ static struct clk_branch gcc_nssnoc_ppe_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nssnoc_ppe_clk",
- .parent_names = (const char *[]){
- "nss_ppe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ppe_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3294,9 +3201,8 @@ static struct clk_branch gcc_nssnoc_qosgen_ref_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nssnoc_qosgen_ref_clk",
- .parent_names = (const char *[]){
- "gcc_xo_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_xo_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3311,9 +3217,8 @@ static struct clk_branch gcc_nssnoc_snoc_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nssnoc_snoc_clk",
- .parent_names = (const char *[]){
- "system_noc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &system_noc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3328,9 +3233,8 @@ static struct clk_branch gcc_nssnoc_timeout_ref_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nssnoc_timeout_ref_clk",
- .parent_names = (const char *[]){
- "gcc_xo_div4_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_xo_div4_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3345,9 +3249,8 @@ static struct clk_branch gcc_nssnoc_ubi0_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nssnoc_ubi0_ahb_clk",
- .parent_names = (const char *[]){
- "nss_ce_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ce_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3362,9 +3265,8 @@ static struct clk_branch gcc_nssnoc_ubi1_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nssnoc_ubi1_ahb_clk",
- .parent_names = (const char *[]){
- "nss_ce_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ce_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3380,9 +3282,8 @@ static struct clk_branch gcc_ubi0_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ubi0_ahb_clk",
- .parent_names = (const char *[]){
- "nss_ce_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ce_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3398,9 +3299,8 @@ static struct clk_branch gcc_ubi0_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ubi0_axi_clk",
- .parent_names = (const char *[]){
- "nss_noc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_noc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3416,9 +3316,8 @@ static struct clk_branch gcc_ubi0_nc_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ubi0_nc_axi_clk",
- .parent_names = (const char *[]){
- "nss_noc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_noc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3434,9 +3333,8 @@ static struct clk_branch gcc_ubi0_core_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ubi0_core_clk",
- .parent_names = (const char *[]){
- "nss_ubi0_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ubi0_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3452,9 +3350,8 @@ static struct clk_branch gcc_ubi0_mpt_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ubi0_mpt_clk",
- .parent_names = (const char *[]){
- "ubi_mpt_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &ubi_mpt_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3470,9 +3367,8 @@ static struct clk_branch gcc_ubi1_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ubi1_ahb_clk",
- .parent_names = (const char *[]){
- "nss_ce_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ce_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3488,9 +3384,8 @@ static struct clk_branch gcc_ubi1_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ubi1_axi_clk",
- .parent_names = (const char *[]){
- "nss_noc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_noc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3506,9 +3401,8 @@ static struct clk_branch gcc_ubi1_nc_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ubi1_nc_axi_clk",
- .parent_names = (const char *[]){
- "nss_noc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_noc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3524,9 +3418,8 @@ static struct clk_branch gcc_ubi1_core_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ubi1_core_clk",
- .parent_names = (const char *[]){
- "nss_ubi1_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ubi1_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3542,9 +3435,8 @@ static struct clk_branch gcc_ubi1_mpt_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ubi1_mpt_clk",
- .parent_names = (const char *[]){
- "ubi_mpt_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &ubi_mpt_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3559,9 +3451,8 @@ static struct clk_branch gcc_cmn_12gpll_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_cmn_12gpll_ahb_clk",
- .parent_names = (const char *[]){
- "pcnoc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcnoc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3576,9 +3467,8 @@ static struct clk_branch gcc_cmn_12gpll_sys_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_cmn_12gpll_sys_clk",
- .parent_names = (const char *[]){
- "gcc_xo_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_xo_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3593,9 +3483,8 @@ static struct clk_branch gcc_mdio_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_mdio_ahb_clk",
- .parent_names = (const char *[]){
- "pcnoc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcnoc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3610,9 +3499,8 @@ static struct clk_branch gcc_uniphy0_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy0_ahb_clk",
- .parent_names = (const char *[]){
- "pcnoc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcnoc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3627,9 +3515,8 @@ static struct clk_branch gcc_uniphy0_sys_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy0_sys_clk",
- .parent_names = (const char *[]){
- "gcc_xo_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_xo_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3644,9 +3531,8 @@ static struct clk_branch gcc_uniphy1_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy1_ahb_clk",
- .parent_names = (const char *[]){
- "pcnoc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcnoc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3661,9 +3547,8 @@ static struct clk_branch gcc_uniphy1_sys_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy1_sys_clk",
- .parent_names = (const char *[]){
- "gcc_xo_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_xo_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3678,9 +3563,8 @@ static struct clk_branch gcc_uniphy2_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy2_ahb_clk",
- .parent_names = (const char *[]){
- "pcnoc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcnoc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3695,9 +3579,8 @@ static struct clk_branch gcc_uniphy2_sys_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy2_sys_clk",
- .parent_names = (const char *[]){
- "gcc_xo_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &gcc_xo_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3712,9 +3595,8 @@ static struct clk_branch gcc_nss_port1_rx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_port1_rx_clk",
- .parent_names = (const char *[]){
- "nss_port1_rx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port1_rx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3729,9 +3611,8 @@ static struct clk_branch gcc_nss_port1_tx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_port1_tx_clk",
- .parent_names = (const char *[]){
- "nss_port1_tx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port1_tx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3746,9 +3627,8 @@ static struct clk_branch gcc_nss_port2_rx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_port2_rx_clk",
- .parent_names = (const char *[]){
- "nss_port2_rx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port2_rx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3763,9 +3643,8 @@ static struct clk_branch gcc_nss_port2_tx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_port2_tx_clk",
- .parent_names = (const char *[]){
- "nss_port2_tx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port2_tx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3780,9 +3659,8 @@ static struct clk_branch gcc_nss_port3_rx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_port3_rx_clk",
- .parent_names = (const char *[]){
- "nss_port3_rx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port3_rx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3797,9 +3675,8 @@ static struct clk_branch gcc_nss_port3_tx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_port3_tx_clk",
- .parent_names = (const char *[]){
- "nss_port3_tx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port3_tx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3814,9 +3691,8 @@ static struct clk_branch gcc_nss_port4_rx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_port4_rx_clk",
- .parent_names = (const char *[]){
- "nss_port4_rx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port4_rx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3831,9 +3707,8 @@ static struct clk_branch gcc_nss_port4_tx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_port4_tx_clk",
- .parent_names = (const char *[]){
- "nss_port4_tx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port4_tx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3848,9 +3723,8 @@ static struct clk_branch gcc_nss_port5_rx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_port5_rx_clk",
- .parent_names = (const char *[]){
- "nss_port5_rx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port5_rx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3865,9 +3739,8 @@ static struct clk_branch gcc_nss_port5_tx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_port5_tx_clk",
- .parent_names = (const char *[]){
- "nss_port5_tx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port5_tx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3882,9 +3755,8 @@ static struct clk_branch gcc_nss_port6_rx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_port6_rx_clk",
- .parent_names = (const char *[]){
- "nss_port6_rx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port6_rx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3899,9 +3771,8 @@ static struct clk_branch gcc_nss_port6_tx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_nss_port6_tx_clk",
- .parent_names = (const char *[]){
- "nss_port6_tx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port6_tx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3916,9 +3787,8 @@ static struct clk_branch gcc_port1_mac_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_port1_mac_clk",
- .parent_names = (const char *[]){
- "nss_ppe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ppe_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3933,9 +3803,8 @@ static struct clk_branch gcc_port2_mac_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_port2_mac_clk",
- .parent_names = (const char *[]){
- "nss_ppe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ppe_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3950,9 +3819,8 @@ static struct clk_branch gcc_port3_mac_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_port3_mac_clk",
- .parent_names = (const char *[]){
- "nss_ppe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ppe_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3967,9 +3835,8 @@ static struct clk_branch gcc_port4_mac_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_port4_mac_clk",
- .parent_names = (const char *[]){
- "nss_ppe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ppe_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -3984,9 +3851,8 @@ static struct clk_branch gcc_port5_mac_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_port5_mac_clk",
- .parent_names = (const char *[]){
- "nss_ppe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ppe_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4001,9 +3867,8 @@ static struct clk_branch gcc_port6_mac_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_port6_mac_clk",
- .parent_names = (const char *[]){
- "nss_ppe_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_ppe_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4018,9 +3883,8 @@ static struct clk_branch gcc_uniphy0_port1_rx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy0_port1_rx_clk",
- .parent_names = (const char *[]){
- "nss_port1_rx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port1_rx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4035,9 +3899,8 @@ static struct clk_branch gcc_uniphy0_port1_tx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy0_port1_tx_clk",
- .parent_names = (const char *[]){
- "nss_port1_tx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port1_tx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4052,9 +3915,8 @@ static struct clk_branch gcc_uniphy0_port2_rx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy0_port2_rx_clk",
- .parent_names = (const char *[]){
- "nss_port2_rx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port2_rx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4069,9 +3931,8 @@ static struct clk_branch gcc_uniphy0_port2_tx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy0_port2_tx_clk",
- .parent_names = (const char *[]){
- "nss_port2_tx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port2_tx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4086,9 +3947,8 @@ static struct clk_branch gcc_uniphy0_port3_rx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy0_port3_rx_clk",
- .parent_names = (const char *[]){
- "nss_port3_rx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port3_rx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4103,9 +3963,8 @@ static struct clk_branch gcc_uniphy0_port3_tx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy0_port3_tx_clk",
- .parent_names = (const char *[]){
- "nss_port3_tx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port3_tx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4120,9 +3979,8 @@ static struct clk_branch gcc_uniphy0_port4_rx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy0_port4_rx_clk",
- .parent_names = (const char *[]){
- "nss_port4_rx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port4_rx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4137,9 +3995,8 @@ static struct clk_branch gcc_uniphy0_port4_tx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy0_port4_tx_clk",
- .parent_names = (const char *[]){
- "nss_port4_tx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port4_tx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4154,9 +4011,8 @@ static struct clk_branch gcc_uniphy0_port5_rx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy0_port5_rx_clk",
- .parent_names = (const char *[]){
- "nss_port5_rx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port5_rx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4171,9 +4027,8 @@ static struct clk_branch gcc_uniphy0_port5_tx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy0_port5_tx_clk",
- .parent_names = (const char *[]){
- "nss_port5_tx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port5_tx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4188,9 +4043,8 @@ static struct clk_branch gcc_uniphy1_port5_rx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy1_port5_rx_clk",
- .parent_names = (const char *[]){
- "nss_port5_rx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port5_rx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4205,9 +4059,8 @@ static struct clk_branch gcc_uniphy1_port5_tx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy1_port5_tx_clk",
- .parent_names = (const char *[]){
- "nss_port5_tx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port5_tx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4222,9 +4075,8 @@ static struct clk_branch gcc_uniphy2_port6_rx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy2_port6_rx_clk",
- .parent_names = (const char *[]){
- "nss_port6_rx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port6_rx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4239,9 +4091,8 @@ static struct clk_branch gcc_uniphy2_port6_tx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_uniphy2_port6_tx_clk",
- .parent_names = (const char *[]){
- "nss_port6_tx_div_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &nss_port6_tx_div_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4257,9 +4108,8 @@ static struct clk_branch gcc_crypto_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_crypto_ahb_clk",
- .parent_names = (const char *[]){
- "pcnoc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcnoc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4275,9 +4125,8 @@ static struct clk_branch gcc_crypto_axi_clk = {
.enable_mask = BIT(1),
.hw.init = &(struct clk_init_data){
.name = "gcc_crypto_axi_clk",
- .parent_names = (const char *[]){
- "pcnoc_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &pcnoc_clk_src.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4293,9 +4142,8 @@ static struct clk_branch gcc_crypto_clk = {
.enable_mask = BIT(2),
.hw.init = &(struct clk_init_data){
.name = "gcc_crypto_clk",
- .parent_names = (const char *[]){
- "crypto_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &crypto_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4310,9 +4158,8 @@ static struct clk_branch gcc_gp1_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_gp1_clk",
- .parent_names = (const char *[]){
- "gp1_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &gp1_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4327,9 +4174,8 @@ static struct clk_branch gcc_gp2_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_gp2_clk",
- .parent_names = (const char *[]){
- "gp2_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &gp2_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4344,9 +4190,8 @@ static struct clk_branch gcc_gp3_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_gp3_clk",
- .parent_names = (const char *[]){
- "gp3_clk_src"
- },
+ .parent_hws = (const struct clk_hw *[]){
+ &gp3_clk_src.clkr.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
.ops = &clk_branch2_ops,
@@ -4368,7 +4213,7 @@ static struct clk_rcg2 pcie0_rchng_clk_src = {
.clkr.hw.init = &(struct clk_init_data){
.name = "pcie0_rchng_clk_src",
.parent_data = gcc_xo_gpll0,
- .num_parents = 2,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -4826,6 +4671,20 @@ static const struct qcom_reset_map gcc_ipq8074_resets[] = {
[GCC_PCIE1_AXI_SLAVE_ARES] = { 0x76040, 4 },
[GCC_PCIE1_AHB_ARES] = { 0x76040, 5 },
[GCC_PCIE1_AXI_MASTER_STICKY_ARES] = { 0x76040, 6 },
+ [GCC_PPE_FULL_RESET] = { .reg = 0x68014, .bitmask = GENMASK(19, 16) },
+ [GCC_UNIPHY0_SOFT_RESET] = { .reg = 0x56004, .bitmask = GENMASK(13, 4) | BIT(1) },
+ [GCC_UNIPHY0_XPCS_RESET] = { 0x56004, 2 },
+ [GCC_UNIPHY1_SOFT_RESET] = { .reg = 0x56104, .bitmask = GENMASK(5, 4) | BIT(1) },
+ [GCC_UNIPHY1_XPCS_RESET] = { 0x56104, 2 },
+ [GCC_UNIPHY2_SOFT_RESET] = { .reg = 0x56204, .bitmask = GENMASK(5, 4) | BIT(1) },
+ [GCC_UNIPHY2_XPCS_RESET] = { 0x56204, 2 },
+ [GCC_EDMA_HW_RESET] = { .reg = 0x68014, .bitmask = GENMASK(21, 20) },
+ [GCC_NSSPORT1_RESET] = { .reg = 0x68014, .bitmask = BIT(24) | GENMASK(1, 0) },
+ [GCC_NSSPORT2_RESET] = { .reg = 0x68014, .bitmask = BIT(25) | GENMASK(3, 2) },
+ [GCC_NSSPORT3_RESET] = { .reg = 0x68014, .bitmask = BIT(26) | GENMASK(5, 4) },
+ [GCC_NSSPORT4_RESET] = { .reg = 0x68014, .bitmask = BIT(27) | GENMASK(9, 8) },
+ [GCC_NSSPORT5_RESET] = { .reg = 0x68014, .bitmask = BIT(28) | GENMASK(11, 10) },
+ [GCC_NSSPORT6_RESET] = { .reg = 0x68014, .bitmask = BIT(29) | GENMASK(13, 12) },
};
static struct gdsc *gcc_ipq8074_gdscs[] = {
diff --git a/drivers/clk/qcom/gcc-msm8939.c b/drivers/clk/qcom/gcc-msm8939.c
index af608f165896..712073f9dc69 100644
--- a/drivers/clk/qcom/gcc-msm8939.c
+++ b/drivers/clk/qcom/gcc-msm8939.c
@@ -1033,7 +1033,20 @@ static struct clk_rcg2 cci_clk_src = {
},
};
+/*
+ * This is a frequency table for "General Purpose" clocks.
+ * These clocks can be muxed to the SoC pins and may be used by
+ * external devices. They're often used as PWM source.
+ *
+ * See comment at ftbl_gcc_gp1_3_clk.
+ */
static const struct freq_tbl ftbl_gcc_camss_gp0_1_clk[] = {
+ F(10000, P_XO, 16, 1, 120),
+ F(100000, P_XO, 16, 1, 12),
+ F(500000, P_GPLL0, 16, 1, 100),
+ F(1000000, P_GPLL0, 16, 1, 50),
+ F(2500000, P_GPLL0, 16, 1, 20),
+ F(5000000, P_GPLL0, 16, 1, 10),
F(100000000, P_GPLL0, 8, 0, 0),
F(200000000, P_GPLL0, 4, 0, 0),
{ }
@@ -1198,7 +1211,29 @@ static struct clk_rcg2 crypto_clk_src = {
},
};
+/*
+ * This is a frequency table for "General Purpose" clocks.
+ * These clocks can be muxed to the SoC pins and may be used by
+ * external devices. They're often used as PWM source.
+ *
+ * Please note that MND divider must be enabled for duty-cycle
+ * control to be possible. (M != N) Also since D register is configured
+ * with a value multiplied by 2, and duty cycle is calculated as
+ * (2 * D) % 2^W
+ * DutyCycle = ----------------
+ * 2 * (N % 2^W)
+ * (where W = .mnd_width)
+ * N must be half or less than maximum value for the register.
+ * Otherwise duty-cycle control would be limited.
+ * (e.g. for 8-bit NMD N should be less than 128)
+ */
static const struct freq_tbl ftbl_gcc_gp1_3_clk[] = {
+ F(10000, P_XO, 16, 1, 120),
+ F(100000, P_XO, 16, 1, 12),
+ F(500000, P_GPLL0, 16, 1, 100),
+ F(1000000, P_GPLL0, 16, 1, 50),
+ F(2500000, P_GPLL0, 16, 1, 20),
+ F(5000000, P_GPLL0, 16, 1, 10),
F(19200000, P_XO, 1, 0, 0),
{ }
};
diff --git a/drivers/clk/qcom/gcc-msm8974.c b/drivers/clk/qcom/gcc-msm8974.c
index bf305fa9e522..025cc9a20dbb 100644
--- a/drivers/clk/qcom/gcc-msm8974.c
+++ b/drivers/clk/qcom/gcc-msm8974.c
@@ -32,28 +32,6 @@ enum {
P_GPLL4,
};
-static const struct parent_map gcc_xo_gpll0_map[] = {
- { P_XO, 0 },
- { P_GPLL0, 1 }
-};
-
-static const char * const gcc_xo_gpll0[] = {
- "xo",
- "gpll0_vote",
-};
-
-static const struct parent_map gcc_xo_gpll0_gpll4_map[] = {
- { P_XO, 0 },
- { P_GPLL0, 1 },
- { P_GPLL4, 5 }
-};
-
-static const char * const gcc_xo_gpll0_gpll4[] = {
- "xo",
- "gpll0_vote",
- "gpll4_vote",
-};
-
static struct clk_pll gpll0 = {
.l_reg = 0x0004,
.m_reg = 0x0008,
@@ -64,7 +42,9 @@ static struct clk_pll gpll0 = {
.status_bit = 17,
.clkr.hw.init = &(struct clk_init_data){
.name = "gpll0",
- .parent_names = (const char *[]){ "xo" },
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo", .name = "xo_board",
+ },
.num_parents = 1,
.ops = &clk_pll_ops,
},
@@ -75,20 +55,75 @@ static struct clk_regmap gpll0_vote = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gpll0_vote",
- .parent_names = (const char *[]){ "gpll0" },
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll0.clkr.hw,
+ },
.num_parents = 1,
.ops = &clk_pll_vote_ops,
},
};
+static struct clk_pll gpll4 = {
+ .l_reg = 0x1dc4,
+ .m_reg = 0x1dc8,
+ .n_reg = 0x1dcc,
+ .config_reg = 0x1dd4,
+ .mode_reg = 0x1dc0,
+ .status_reg = 0x1ddc,
+ .status_bit = 17,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gpll4",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo", .name = "xo_board",
+ },
+ .num_parents = 1,
+ .ops = &clk_pll_ops,
+ },
+};
+
+static struct clk_regmap gpll4_vote = {
+ .enable_reg = 0x1480,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gpll4_vote",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll4.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_pll_vote_ops,
+ },
+};
+
+static const struct parent_map gcc_xo_gpll0_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 }
+};
+
+static const struct clk_parent_data gcc_xo_gpll0[] = {
+ { .fw_name = "xo", .name = "xo_board" },
+ { .hw = &gpll0_vote.hw },
+};
+
+static const struct parent_map gcc_xo_gpll0_gpll4_map[] = {
+ { P_XO, 0 },
+ { P_GPLL0, 1 },
+ { P_GPLL4, 5 }
+};
+
+static const struct clk_parent_data gcc_xo_gpll0_gpll4[] = {
+ { .fw_name = "xo", .name = "xo_board" },
+ { .hw = &gpll0_vote.hw },
+ { .hw = &gpll4_vote.hw },
+};
+
static struct clk_rcg2 config_noc_clk_src = {
.cmd_rcgr = 0x0150,
.hid_width = 5,
.parent_map = gcc_xo_gpll0_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "config_noc_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -99,8 +134,8 @@ static struct clk_rcg2 periph_noc_clk_src = {
.parent_map = gcc_xo_gpll0_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "periph_noc_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -111,8 +146,8 @@ static struct clk_rcg2 system_noc_clk_src = {
.parent_map = gcc_xo_gpll0_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "system_noc_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -127,7 +162,9 @@ static struct clk_pll gpll1 = {
.status_bit = 17,
.clkr.hw.init = &(struct clk_init_data){
.name = "gpll1",
- .parent_names = (const char *[]){ "xo" },
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo", .name = "xo_board",
+ },
.num_parents = 1,
.ops = &clk_pll_ops,
},
@@ -138,34 +175,9 @@ static struct clk_regmap gpll1_vote = {
.enable_mask = BIT(1),
.hw.init = &(struct clk_init_data){
.name = "gpll1_vote",
- .parent_names = (const char *[]){ "gpll1" },
- .num_parents = 1,
- .ops = &clk_pll_vote_ops,
- },
-};
-
-static struct clk_pll gpll4 = {
- .l_reg = 0x1dc4,
- .m_reg = 0x1dc8,
- .n_reg = 0x1dcc,
- .config_reg = 0x1dd4,
- .mode_reg = 0x1dc0,
- .status_reg = 0x1ddc,
- .status_bit = 17,
- .clkr.hw.init = &(struct clk_init_data){
- .name = "gpll4",
- .parent_names = (const char *[]){ "xo" },
- .num_parents = 1,
- .ops = &clk_pll_ops,
- },
-};
-
-static struct clk_regmap gpll4_vote = {
- .enable_reg = 0x1480,
- .enable_mask = BIT(4),
- .hw.init = &(struct clk_init_data){
- .name = "gpll4_vote",
- .parent_names = (const char *[]){ "gpll4" },
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll1.clkr.hw,
+ },
.num_parents = 1,
.ops = &clk_pll_vote_ops,
},
@@ -184,8 +196,8 @@ static struct clk_rcg2 usb30_master_clk_src = {
.freq_tbl = ftbl_gcc_usb30_master_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "usb30_master_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -204,8 +216,8 @@ static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup1_i2c_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -229,8 +241,8 @@ static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup1_spi_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -242,8 +254,8 @@ static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup2_i2c_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -256,8 +268,8 @@ static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup2_spi_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -269,8 +281,8 @@ static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup3_i2c_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -283,8 +295,8 @@ static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup3_spi_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -296,8 +308,8 @@ static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup4_i2c_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -310,8 +322,8 @@ static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup4_spi_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -323,8 +335,8 @@ static struct clk_rcg2 blsp1_qup5_i2c_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup5_i2c_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -337,8 +349,8 @@ static struct clk_rcg2 blsp1_qup5_spi_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup5_spi_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -350,8 +362,8 @@ static struct clk_rcg2 blsp1_qup6_i2c_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup6_i2c_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -364,8 +376,8 @@ static struct clk_rcg2 blsp1_qup6_spi_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_qup6_spi_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -397,8 +409,8 @@ static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_uart1_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -411,8 +423,8 @@ static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_uart2_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -425,8 +437,8 @@ static struct clk_rcg2 blsp1_uart3_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_uart3_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -439,8 +451,8 @@ static struct clk_rcg2 blsp1_uart4_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_uart4_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -453,8 +465,8 @@ static struct clk_rcg2 blsp1_uart5_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_uart5_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -467,8 +479,8 @@ static struct clk_rcg2 blsp1_uart6_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp1_uart6_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -480,8 +492,8 @@ static struct clk_rcg2 blsp2_qup1_i2c_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup1_i2c_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -494,8 +506,8 @@ static struct clk_rcg2 blsp2_qup1_spi_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup1_spi_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -507,8 +519,8 @@ static struct clk_rcg2 blsp2_qup2_i2c_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup2_i2c_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -521,8 +533,8 @@ static struct clk_rcg2 blsp2_qup2_spi_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup2_spi_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -534,8 +546,8 @@ static struct clk_rcg2 blsp2_qup3_i2c_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup3_i2c_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -548,8 +560,8 @@ static struct clk_rcg2 blsp2_qup3_spi_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup3_spi_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -561,8 +573,8 @@ static struct clk_rcg2 blsp2_qup4_i2c_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup4_i2c_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -575,8 +587,8 @@ static struct clk_rcg2 blsp2_qup4_spi_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup4_spi_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -588,8 +600,8 @@ static struct clk_rcg2 blsp2_qup5_i2c_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup5_i2c_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -602,8 +614,8 @@ static struct clk_rcg2 blsp2_qup5_spi_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup5_spi_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -615,8 +627,8 @@ static struct clk_rcg2 blsp2_qup6_i2c_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup6_i2c_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -629,8 +641,8 @@ static struct clk_rcg2 blsp2_qup6_spi_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_qup6_spi_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -643,8 +655,8 @@ static struct clk_rcg2 blsp2_uart1_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_uart1_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -657,8 +669,8 @@ static struct clk_rcg2 blsp2_uart2_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_uart2_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -671,8 +683,8 @@ static struct clk_rcg2 blsp2_uart3_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_uart3_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -685,8 +697,8 @@ static struct clk_rcg2 blsp2_uart4_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_uart4_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -699,8 +711,8 @@ static struct clk_rcg2 blsp2_uart5_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_uart5_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -713,8 +725,8 @@ static struct clk_rcg2 blsp2_uart6_apps_clk_src = {
.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "blsp2_uart6_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -740,8 +752,8 @@ static struct clk_rcg2 ce1_clk_src = {
.freq_tbl = ftbl_gcc_ce1_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "ce1_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -761,8 +773,8 @@ static struct clk_rcg2 ce2_clk_src = {
.freq_tbl = ftbl_gcc_ce2_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "ce2_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -793,8 +805,8 @@ static struct clk_rcg2 gp1_clk_src = {
.freq_tbl = ftbl_gcc_gp_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "gp1_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -807,8 +819,8 @@ static struct clk_rcg2 gp2_clk_src = {
.freq_tbl = ftbl_gcc_gp_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "gp2_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -821,8 +833,8 @@ static struct clk_rcg2 gp3_clk_src = {
.freq_tbl = ftbl_gcc_gp_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "gp3_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -839,8 +851,8 @@ static struct clk_rcg2 pdm2_clk_src = {
.freq_tbl = ftbl_gcc_pdm2_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "pdm2_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -871,8 +883,8 @@ static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk_pro[] = {
static struct clk_init_data sdcc1_apps_clk_src_init = {
.name = "sdcc1_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_floor_ops,
};
@@ -893,8 +905,8 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
.freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "sdcc2_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_floor_ops,
},
};
@@ -907,8 +919,8 @@ static struct clk_rcg2 sdcc3_apps_clk_src = {
.freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "sdcc3_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_floor_ops,
},
};
@@ -921,8 +933,8 @@ static struct clk_rcg2 sdcc4_apps_clk_src = {
.freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "sdcc4_apps_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_floor_ops,
},
};
@@ -940,8 +952,8 @@ static struct clk_rcg2 tsif_ref_clk_src = {
.freq_tbl = ftbl_gcc_tsif_ref_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "tsif_ref_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -958,8 +970,8 @@ static struct clk_rcg2 usb30_mock_utmi_clk_src = {
.freq_tbl = ftbl_gcc_usb30_mock_utmi_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "usb30_mock_utmi_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -977,8 +989,8 @@ static struct clk_rcg2 usb_hs_system_clk_src = {
.freq_tbl = ftbl_gcc_usb_hs_system_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "usb_hs_system_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -1000,9 +1012,9 @@ static struct clk_rcg2 usb_hsic_clk_src = {
.freq_tbl = ftbl_gcc_usb_hsic_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "usb_hsic_clk_src",
- .parent_names = (const char *[]){
- "xo",
- "gpll1_vote",
+ .parent_data = (const struct clk_parent_data[]){
+ { .fw_name = "xo", .name = "xo_board" },
+ { .hw = &gpll1_vote.hw },
},
.num_parents = 2,
.ops = &clk_rcg2_ops,
@@ -1021,8 +1033,8 @@ static struct clk_rcg2 usb_hsic_io_cal_clk_src = {
.freq_tbl = ftbl_gcc_usb_hsic_io_cal_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "usb_hsic_io_cal_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 1,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -1040,8 +1052,8 @@ static struct clk_rcg2 usb_hsic_system_clk_src = {
.freq_tbl = ftbl_gcc_usb_hsic_system_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "usb_hsic_system_clk_src",
- .parent_names = gcc_xo_gpll0,
- .num_parents = 2,
+ .parent_data = gcc_xo_gpll0,
+ .num_parents = ARRAY_SIZE(gcc_xo_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -1051,8 +1063,8 @@ static struct clk_regmap gcc_mmss_gpll0_clk_src = {
.enable_mask = BIT(26),
.hw.init = &(struct clk_init_data){
.name = "mmss_gpll0_vote",
- .parent_names = (const char *[]){
- "gpll0_vote",
+ .parent_hws = (const struct clk_hw*[]){
+ &gpll0_vote.hw,
},
.num_parents = 1,
.ops = &clk_branch_simple_ops,
@@ -1067,8 +1079,8 @@ static struct clk_branch gcc_bam_dma_ahb_clk = {
.enable_mask = BIT(12),
.hw.init = &(struct clk_init_data){
.name = "gcc_bam_dma_ahb_clk",
- .parent_names = (const char *[]){
- "periph_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &periph_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1084,8 +1096,8 @@ static struct clk_branch gcc_blsp1_ahb_clk = {
.enable_mask = BIT(17),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_ahb_clk",
- .parent_names = (const char *[]){
- "periph_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &periph_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1100,8 +1112,8 @@ static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup1_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup1_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup1_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1117,8 +1129,8 @@ static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup1_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup1_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup1_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1134,8 +1146,8 @@ static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup2_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup2_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup2_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1151,8 +1163,8 @@ static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup2_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup2_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup2_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1168,8 +1180,8 @@ static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup3_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup3_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup3_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1185,8 +1197,8 @@ static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup3_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup3_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup3_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1202,8 +1214,8 @@ static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup4_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup4_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup4_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1219,8 +1231,8 @@ static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup4_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup4_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup4_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1236,8 +1248,8 @@ static struct clk_branch gcc_blsp1_qup5_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup5_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup5_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup5_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1253,8 +1265,8 @@ static struct clk_branch gcc_blsp1_qup5_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup5_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup5_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup5_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1270,8 +1282,8 @@ static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup6_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup6_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup6_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1287,8 +1299,8 @@ static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_qup6_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_qup6_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_qup6_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1304,8 +1316,8 @@ static struct clk_branch gcc_blsp1_uart1_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_uart1_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_uart1_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_uart1_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1321,8 +1333,8 @@ static struct clk_branch gcc_blsp1_uart2_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_uart2_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_uart2_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_uart2_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1338,8 +1350,8 @@ static struct clk_branch gcc_blsp1_uart3_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_uart3_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_uart3_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_uart3_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1355,8 +1367,8 @@ static struct clk_branch gcc_blsp1_uart4_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_uart4_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_uart4_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_uart4_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1372,8 +1384,8 @@ static struct clk_branch gcc_blsp1_uart5_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_uart5_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_uart5_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_uart5_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1389,8 +1401,8 @@ static struct clk_branch gcc_blsp1_uart6_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp1_uart6_apps_clk",
- .parent_names = (const char *[]){
- "blsp1_uart6_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp1_uart6_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1407,8 +1419,8 @@ static struct clk_branch gcc_blsp2_ahb_clk = {
.enable_mask = BIT(15),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_ahb_clk",
- .parent_names = (const char *[]){
- "periph_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &periph_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1423,8 +1435,8 @@ static struct clk_branch gcc_blsp2_qup1_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup1_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup1_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup1_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1440,8 +1452,8 @@ static struct clk_branch gcc_blsp2_qup1_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup1_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup1_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup1_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1457,8 +1469,8 @@ static struct clk_branch gcc_blsp2_qup2_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup2_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup2_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup2_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1474,8 +1486,8 @@ static struct clk_branch gcc_blsp2_qup2_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup2_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup2_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup2_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1491,8 +1503,8 @@ static struct clk_branch gcc_blsp2_qup3_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup3_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup3_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup3_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1508,8 +1520,8 @@ static struct clk_branch gcc_blsp2_qup3_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup3_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup3_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup3_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1525,8 +1537,8 @@ static struct clk_branch gcc_blsp2_qup4_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup4_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup4_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup4_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1542,8 +1554,8 @@ static struct clk_branch gcc_blsp2_qup4_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup4_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup4_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup4_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1559,8 +1571,8 @@ static struct clk_branch gcc_blsp2_qup5_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup5_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup5_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup5_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1576,8 +1588,8 @@ static struct clk_branch gcc_blsp2_qup5_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup5_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup5_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup5_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1593,8 +1605,8 @@ static struct clk_branch gcc_blsp2_qup6_i2c_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup6_i2c_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup6_i2c_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup6_i2c_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1610,8 +1622,8 @@ static struct clk_branch gcc_blsp2_qup6_spi_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_qup6_spi_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_qup6_spi_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_qup6_spi_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1627,8 +1639,8 @@ static struct clk_branch gcc_blsp2_uart1_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_uart1_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_uart1_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_uart1_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1644,8 +1656,8 @@ static struct clk_branch gcc_blsp2_uart2_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_uart2_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_uart2_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_uart2_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1661,8 +1673,8 @@ static struct clk_branch gcc_blsp2_uart3_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_uart3_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_uart3_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_uart3_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1678,8 +1690,8 @@ static struct clk_branch gcc_blsp2_uart4_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_uart4_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_uart4_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_uart4_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1695,8 +1707,8 @@ static struct clk_branch gcc_blsp2_uart5_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_uart5_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_uart5_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_uart5_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1712,8 +1724,8 @@ static struct clk_branch gcc_blsp2_uart6_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_blsp2_uart6_apps_clk",
- .parent_names = (const char *[]){
- "blsp2_uart6_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &blsp2_uart6_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1730,8 +1742,8 @@ static struct clk_branch gcc_boot_rom_ahb_clk = {
.enable_mask = BIT(10),
.hw.init = &(struct clk_init_data){
.name = "gcc_boot_rom_ahb_clk",
- .parent_names = (const char *[]){
- "config_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &config_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1747,8 +1759,8 @@ static struct clk_branch gcc_ce1_ahb_clk = {
.enable_mask = BIT(3),
.hw.init = &(struct clk_init_data){
.name = "gcc_ce1_ahb_clk",
- .parent_names = (const char *[]){
- "config_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &config_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1764,8 +1776,8 @@ static struct clk_branch gcc_ce1_axi_clk = {
.enable_mask = BIT(4),
.hw.init = &(struct clk_init_data){
.name = "gcc_ce1_axi_clk",
- .parent_names = (const char *[]){
- "system_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &system_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1781,8 +1793,8 @@ static struct clk_branch gcc_ce1_clk = {
.enable_mask = BIT(5),
.hw.init = &(struct clk_init_data){
.name = "gcc_ce1_clk",
- .parent_names = (const char *[]){
- "ce1_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &ce1_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1799,8 +1811,8 @@ static struct clk_branch gcc_ce2_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ce2_ahb_clk",
- .parent_names = (const char *[]){
- "config_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &config_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1816,8 +1828,8 @@ static struct clk_branch gcc_ce2_axi_clk = {
.enable_mask = BIT(1),
.hw.init = &(struct clk_init_data){
.name = "gcc_ce2_axi_clk",
- .parent_names = (const char *[]){
- "system_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &system_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1833,8 +1845,8 @@ static struct clk_branch gcc_ce2_clk = {
.enable_mask = BIT(2),
.hw.init = &(struct clk_init_data){
.name = "gcc_ce2_clk",
- .parent_names = (const char *[]){
- "ce2_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &ce2_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1850,8 +1862,8 @@ static struct clk_branch gcc_gp1_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_gp1_clk",
- .parent_names = (const char *[]){
- "gp1_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &gp1_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1867,8 +1879,8 @@ static struct clk_branch gcc_gp2_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_gp2_clk",
- .parent_names = (const char *[]){
- "gp2_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &gp2_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1884,8 +1896,8 @@ static struct clk_branch gcc_gp3_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_gp3_clk",
- .parent_names = (const char *[]){
- "gp3_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &gp3_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1901,8 +1913,8 @@ static struct clk_branch gcc_lpass_q6_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_lpass_q6_axi_clk",
- .parent_names = (const char *[]){
- "system_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &system_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1917,8 +1929,8 @@ static struct clk_branch gcc_mmss_noc_cfg_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_mmss_noc_cfg_ahb_clk",
- .parent_names = (const char *[]){
- "config_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &config_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1934,8 +1946,8 @@ static struct clk_branch gcc_ocmem_noc_cfg_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_ocmem_noc_cfg_ahb_clk",
- .parent_names = (const char *[]){
- "config_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &config_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1950,8 +1962,8 @@ static struct clk_branch gcc_mss_cfg_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_mss_cfg_ahb_clk",
- .parent_names = (const char *[]){
- "config_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &config_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1966,8 +1978,8 @@ static struct clk_branch gcc_mss_q6_bimc_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_mss_q6_bimc_axi_clk",
- .parent_names = (const char *[]){
- "system_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &system_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1982,8 +1994,8 @@ static struct clk_branch gcc_pdm2_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pdm2_clk",
- .parent_names = (const char *[]){
- "pdm2_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &pdm2_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1999,8 +2011,8 @@ static struct clk_branch gcc_pdm_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pdm_ahb_clk",
- .parent_names = (const char *[]){
- "periph_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &periph_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2015,7 +2027,9 @@ static struct clk_branch gcc_pdm_xo4_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_pdm_xo4_clk",
- .parent_names = (const char *[]){ "xo" },
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "xo", .name = "xo_board",
+ },
.num_parents = 1,
.ops = &clk_branch2_ops,
},
@@ -2030,8 +2044,8 @@ static struct clk_branch gcc_prng_ahb_clk = {
.enable_mask = BIT(13),
.hw.init = &(struct clk_init_data){
.name = "gcc_prng_ahb_clk",
- .parent_names = (const char *[]){
- "periph_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &periph_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2046,8 +2060,8 @@ static struct clk_branch gcc_sdcc1_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc1_ahb_clk",
- .parent_names = (const char *[]){
- "periph_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &periph_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2062,8 +2076,8 @@ static struct clk_branch gcc_sdcc1_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc1_apps_clk",
- .parent_names = (const char *[]){
- "sdcc1_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &sdcc1_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2079,8 +2093,8 @@ static struct clk_branch gcc_sdcc1_cdccal_ff_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc1_cdccal_ff_clk",
- .parent_names = (const char *[]){
- "xo"
+ .parent_data = (const struct clk_parent_data[]){
+ { .fw_name = "xo", .name = "xo_board" }
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2095,8 +2109,8 @@ static struct clk_branch gcc_sdcc1_cdccal_sleep_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc1_cdccal_sleep_clk",
- .parent_names = (const char *[]){
- "sleep_clk_src"
+ .parent_data = (const struct clk_parent_data[]){
+ { .fw_name = "sleep_clk", .name = "sleep_clk_src" }
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2111,8 +2125,8 @@ static struct clk_branch gcc_sdcc2_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc2_ahb_clk",
- .parent_names = (const char *[]){
- "periph_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &periph_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2127,8 +2141,8 @@ static struct clk_branch gcc_sdcc2_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc2_apps_clk",
- .parent_names = (const char *[]){
- "sdcc2_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &sdcc2_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2144,8 +2158,8 @@ static struct clk_branch gcc_sdcc3_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc3_ahb_clk",
- .parent_names = (const char *[]){
- "periph_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &periph_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2160,8 +2174,8 @@ static struct clk_branch gcc_sdcc3_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc3_apps_clk",
- .parent_names = (const char *[]){
- "sdcc3_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &sdcc3_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2177,8 +2191,8 @@ static struct clk_branch gcc_sdcc4_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc4_ahb_clk",
- .parent_names = (const char *[]){
- "periph_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &periph_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2193,8 +2207,8 @@ static struct clk_branch gcc_sdcc4_apps_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sdcc4_apps_clk",
- .parent_names = (const char *[]){
- "sdcc4_apps_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &sdcc4_apps_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2210,8 +2224,8 @@ static struct clk_branch gcc_sys_noc_usb3_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_sys_noc_usb3_axi_clk",
- .parent_names = (const char *[]){
- "usb30_master_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &usb30_master_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2227,8 +2241,8 @@ static struct clk_branch gcc_tsif_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_tsif_ahb_clk",
- .parent_names = (const char *[]){
- "periph_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &periph_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2243,8 +2257,8 @@ static struct clk_branch gcc_tsif_ref_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_tsif_ref_clk",
- .parent_names = (const char *[]){
- "tsif_ref_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &tsif_ref_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2260,8 +2274,8 @@ static struct clk_branch gcc_usb2a_phy_sleep_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb2a_phy_sleep_clk",
- .parent_names = (const char *[]){
- "sleep_clk_src",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "sleep_clk", .name = "sleep_clk_src",
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2276,8 +2290,8 @@ static struct clk_branch gcc_usb2b_phy_sleep_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb2b_phy_sleep_clk",
- .parent_names = (const char *[]){
- "sleep_clk_src",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "sleep_clk", .name = "sleep_clk_src",
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2292,8 +2306,8 @@ static struct clk_branch gcc_usb30_master_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb30_master_clk",
- .parent_names = (const char *[]){
- "usb30_master_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &usb30_master_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2309,8 +2323,8 @@ static struct clk_branch gcc_usb30_mock_utmi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb30_mock_utmi_clk",
- .parent_names = (const char *[]){
- "usb30_mock_utmi_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &usb30_mock_utmi_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2326,8 +2340,8 @@ static struct clk_branch gcc_usb30_sleep_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb30_sleep_clk",
- .parent_names = (const char *[]){
- "sleep_clk_src",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "sleep_clk", .name = "sleep_clk_src",
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2342,8 +2356,8 @@ static struct clk_branch gcc_usb_hs_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb_hs_ahb_clk",
- .parent_names = (const char *[]){
- "periph_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &periph_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2358,8 +2372,8 @@ static struct clk_branch gcc_usb_hs_system_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb_hs_system_clk",
- .parent_names = (const char *[]){
- "usb_hs_system_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &usb_hs_system_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2375,8 +2389,8 @@ static struct clk_branch gcc_usb_hsic_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb_hsic_ahb_clk",
- .parent_names = (const char *[]){
- "periph_noc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &periph_noc_clk_src.clkr.hw,
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2391,8 +2405,8 @@ static struct clk_branch gcc_usb_hsic_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb_hsic_clk",
- .parent_names = (const char *[]){
- "usb_hsic_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &usb_hsic_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2408,8 +2422,8 @@ static struct clk_branch gcc_usb_hsic_io_cal_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb_hsic_io_cal_clk",
- .parent_names = (const char *[]){
- "usb_hsic_io_cal_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &usb_hsic_io_cal_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2425,8 +2439,8 @@ static struct clk_branch gcc_usb_hsic_io_cal_sleep_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb_hsic_io_cal_sleep_clk",
- .parent_names = (const char *[]){
- "sleep_clk_src",
+ .parent_data = &(const struct clk_parent_data){
+ .fw_name = "sleep_clk", .name = "sleep_clk_src",
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2441,8 +2455,8 @@ static struct clk_branch gcc_usb_hsic_system_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_usb_hsic_system_clk",
- .parent_names = (const char *[]){
- "usb_hsic_system_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &usb_hsic_system_clk_src.clkr.hw,
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2844,7 +2858,7 @@ static void msm8226_clock_override(void)
static void msm8974_pro_clock_override(void)
{
- sdcc1_apps_clk_src_init.parent_names = gcc_xo_gpll0_gpll4;
+ sdcc1_apps_clk_src_init.parent_data = gcc_xo_gpll0_gpll4;
sdcc1_apps_clk_src_init.num_parents = 3;
sdcc1_apps_clk_src.freq_tbl = ftbl_gcc_sdcc1_apps_clk_pro;
sdcc1_apps_clk_src.parent_map = gcc_xo_gpll0_gpll4_map;
diff --git a/drivers/clk/qcom/gcc-sm6125.c b/drivers/clk/qcom/gcc-sm6125.c
index cf3af88d4021..40ad062d1bf7 100644
--- a/drivers/clk/qcom/gcc-sm6125.c
+++ b/drivers/clk/qcom/gcc-sm6125.c
@@ -1153,7 +1153,6 @@ static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = {
F(25000000, P_GPLL0_OUT_AUX2, 12, 0, 0),
F(50000000, P_GPLL0_OUT_AUX2, 6, 0, 0),
F(100000000, P_GPLL0_OUT_AUX2, 3, 0, 0),
- F(202000000, P_GPLL7_OUT_MAIN, 2, 0, 0),
{ }
};
diff --git a/drivers/clk/qcom/gcc-sm8250.c b/drivers/clk/qcom/gcc-sm8250.c
index 9755ef4888c1..a0ba37656b07 100644
--- a/drivers/clk/qcom/gcc-sm8250.c
+++ b/drivers/clk/qcom/gcc-sm8250.c
@@ -3267,7 +3267,7 @@ static struct gdsc usb30_prim_gdsc = {
.pd = {
.name = "usb30_prim_gdsc",
},
- .pwrsts = PWRSTS_OFF_ON,
+ .pwrsts = PWRSTS_RET_ON,
};
static struct gdsc usb30_sec_gdsc = {
@@ -3275,7 +3275,7 @@ static struct gdsc usb30_sec_gdsc = {
.pd = {
.name = "usb30_sec_gdsc",
},
- .pwrsts = PWRSTS_OFF_ON,
+ .pwrsts = PWRSTS_RET_ON,
};
static struct gdsc hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc = {
diff --git a/drivers/clk/qcom/gcc-sm8550.c b/drivers/clk/qcom/gcc-sm8550.c
new file mode 100644
index 000000000000..81d630c666d1
--- /dev/null
+++ b/drivers/clk/qcom/gcc-sm8550.c
@@ -0,0 +1,3387 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022, Linaro Limited
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,sm8550-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_PCIE_0_PIPE,
+ DT_PCIE_1_PIPE,
+ DT_PCIE_1_PHY_AUX,
+ DT_UFS_PHY_RX_SYMBOL_0,
+ DT_UFS_PHY_RX_SYMBOL_1,
+ DT_UFS_PHY_TX_SYMBOL_0,
+ DT_USB3_PHY_WRAPPER_GCC_USB30_PIPE,
+};
+
+enum {
+ P_BI_TCXO,
+ P_GCC_GPLL0_OUT_EVEN,
+ P_GCC_GPLL0_OUT_MAIN,
+ P_GCC_GPLL4_OUT_MAIN,
+ P_GCC_GPLL7_OUT_MAIN,
+ P_GCC_GPLL9_OUT_MAIN,
+ P_PCIE_0_PIPE_CLK,
+ P_PCIE_1_PHY_AUX_CLK,
+ P_PCIE_1_PIPE_CLK,
+ P_SLEEP_CLK,
+ P_UFS_PHY_RX_SYMBOL_0_CLK,
+ P_UFS_PHY_RX_SYMBOL_1_CLK,
+ P_UFS_PHY_TX_SYMBOL_0_CLK,
+ P_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK,
+};
+
+static struct clk_alpha_pll gcc_gpll0 = {
+ .offset = 0x0,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .enable_reg = 0x52018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_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_gcc_gpll0_out_even[] = {
+ { 0x1, 2 },
+ { }
+};
+
+static struct clk_alpha_pll_postdiv gcc_gpll0_out_even = {
+ .offset = 0x0,
+ .post_div_shift = 10,
+ .post_div_table = post_div_table_gcc_gpll0_out_even,
+ .num_post_div = ARRAY_SIZE(post_div_table_gcc_gpll0_out_even),
+ .width = 4,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_gpll0_out_even",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .ops = &clk_alpha_pll_postdiv_lucid_ole_ops,
+ },
+};
+
+static struct clk_alpha_pll gcc_gpll4 = {
+ .offset = 0x4000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .enable_reg = 0x52018,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_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 gcc_gpll7 = {
+ .offset = 0x7000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .enable_reg = 0x52018,
+ .enable_mask = BIT(7),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpll7",
+ .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 gcc_gpll9 = {
+ .offset = 0x9000,
+ .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID_OLE],
+ .clkr = {
+ .enable_reg = 0x52018,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpll9",
+ .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_GCC_GPLL0_OUT_MAIN, 1 },
+ { P_GCC_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_0[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gcc_gpll0.clkr.hw },
+ { .hw = &gcc_gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_1[] = {
+ { P_BI_TCXO, 0 },
+ { P_GCC_GPLL0_OUT_MAIN, 1 },
+ { P_SLEEP_CLK, 5 },
+ { P_GCC_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_1[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gcc_gpll0.clkr.hw },
+ { .index = DT_SLEEP_CLK },
+ { .hw = &gcc_gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_2[] = {
+ { P_BI_TCXO, 0 },
+ { P_SLEEP_CLK, 5 },
+};
+
+static const struct clk_parent_data gcc_parent_data_2[] = {
+ { .index = DT_BI_TCXO },
+ { .index = DT_SLEEP_CLK },
+};
+
+static const struct parent_map gcc_parent_map_3[] = {
+ { P_BI_TCXO, 0 },
+ { P_GCC_GPLL0_OUT_MAIN, 1 },
+ { P_GCC_GPLL4_OUT_MAIN, 5 },
+ { P_GCC_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_3[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gcc_gpll0.clkr.hw },
+ { .hw = &gcc_gpll4.clkr.hw },
+ { .hw = &gcc_gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_4[] = {
+ { P_BI_TCXO, 0 },
+};
+
+static const struct clk_parent_data gcc_parent_data_4[] = {
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_6[] = {
+ { P_PCIE_1_PHY_AUX_CLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_6[] = {
+ { .index = DT_PCIE_1_PHY_AUX },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_8[] = {
+ { P_BI_TCXO, 0 },
+ { P_GCC_GPLL0_OUT_MAIN, 1 },
+ { P_GCC_GPLL7_OUT_MAIN, 2 },
+ { P_GCC_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_8[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gcc_gpll0.clkr.hw },
+ { .hw = &gcc_gpll7.clkr.hw },
+ { .hw = &gcc_gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_9[] = {
+ { P_BI_TCXO, 0 },
+ { P_GCC_GPLL0_OUT_MAIN, 1 },
+ { P_GCC_GPLL9_OUT_MAIN, 2 },
+ { P_GCC_GPLL4_OUT_MAIN, 5 },
+ { P_GCC_GPLL0_OUT_EVEN, 6 },
+};
+
+static const struct clk_parent_data gcc_parent_data_9[] = {
+ { .index = DT_BI_TCXO },
+ { .hw = &gcc_gpll0.clkr.hw },
+ { .hw = &gcc_gpll9.clkr.hw },
+ { .hw = &gcc_gpll4.clkr.hw },
+ { .hw = &gcc_gpll0_out_even.clkr.hw },
+};
+
+static const struct parent_map gcc_parent_map_10[] = {
+ { P_UFS_PHY_RX_SYMBOL_0_CLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_10[] = {
+ { .index = DT_UFS_PHY_RX_SYMBOL_0 },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_11[] = {
+ { P_UFS_PHY_RX_SYMBOL_1_CLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_11[] = {
+ { .index = DT_UFS_PHY_RX_SYMBOL_1 },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_12[] = {
+ { P_UFS_PHY_TX_SYMBOL_0_CLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_12[] = {
+ { .index = DT_UFS_PHY_TX_SYMBOL_0 },
+ { .index = DT_BI_TCXO },
+};
+
+static const struct parent_map gcc_parent_map_13[] = {
+ { P_USB3_PHY_WRAPPER_GCC_USB30_PIPE_CLK, 0 },
+ { P_BI_TCXO, 2 },
+};
+
+static const struct clk_parent_data gcc_parent_data_13[] = {
+ { .index = DT_USB3_PHY_WRAPPER_GCC_USB30_PIPE },
+ { .index = DT_BI_TCXO },
+};
+
+static struct clk_regmap_phy_mux gcc_pcie_0_pipe_clk_src = {
+ .reg = 0x6b070,
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_pipe_clk_src",
+ .parent_data = &(const struct clk_parent_data){
+ .index = DT_PCIE_0_PIPE,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_phy_mux_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_pcie_1_phy_aux_clk_src = {
+ .reg = 0x8d094,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_6,
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_phy_aux_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_phy_mux gcc_pcie_1_pipe_clk_src = {
+ .reg = 0x8d078,
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_pipe_clk_src",
+ .parent_data = &(const struct clk_parent_data){
+ .index = DT_PCIE_1_PIPE,
+ },
+ .num_parents = 1,
+ .ops = &clk_regmap_phy_mux_ops,
+ },
+ },
+};
+
+static struct clk_regmap_mux gcc_ufs_phy_rx_symbol_0_clk_src = {
+ .reg = 0x77064,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_10,
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_rx_symbol_0_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_ufs_phy_rx_symbol_1_clk_src = {
+ .reg = 0x770e0,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_11,
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_rx_symbol_1_clk_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_ufs_phy_tx_symbol_0_clk_src = {
+ .reg = 0x77054,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_12,
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_tx_symbol_0_clk_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_mux gcc_usb3_prim_phy_pipe_clk_src = {
+ .reg = 0x3906c,
+ .shift = 0,
+ .width = 2,
+ .parent_map = gcc_parent_map_13,
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_prim_phy_pipe_clk_src",
+ .parent_data = gcc_parent_data_13,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_13),
+ .ops = &clk_regmap_mux_closest_ops,
+ },
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_gp1_clk_src[] = {
+ F(50000000, P_GCC_GPLL0_OUT_EVEN, 6, 0, 0),
+ F(100000000, P_GCC_GPLL0_OUT_MAIN, 6, 0, 0),
+ F(200000000, P_GCC_GPLL0_OUT_MAIN, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_gp1_clk_src = {
+ .cmd_rcgr = 0x64004,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_gp1_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_gp2_clk_src = {
+ .cmd_rcgr = 0x65004,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_gp2_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_gp3_clk_src = {
+ .cmd_rcgr = 0x66004,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_1,
+ .freq_tbl = ftbl_gcc_gp1_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_gp3_clk_src",
+ .parent_data = gcc_parent_data_1,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_1),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_pcie_0_aux_clk_src[] = {
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_pcie_0_aux_clk_src = {
+ .cmd_rcgr = 0x6b074,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_aux_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_pcie_0_phy_rchng_clk_src[] = {
+ F(100000000, P_GCC_GPLL0_OUT_EVEN, 3, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_pcie_0_phy_rchng_clk_src = {
+ .cmd_rcgr = 0x6b058,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pcie_0_phy_rchng_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_phy_rchng_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie_1_aux_clk_src = {
+ .cmd_rcgr = 0x8d07c,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_aux_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_pcie_1_phy_rchng_clk_src = {
+ .cmd_rcgr = 0x8d060,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pcie_0_phy_rchng_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_phy_rchng_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_pdm2_clk_src[] = {
+ F(60000000, P_GCC_GPLL0_OUT_MAIN, 10, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_pdm2_clk_src = {
+ .cmd_rcgr = 0x33010,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pdm2_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm2_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_qupv3_i2c_s0_clk_src = {
+ .cmd_rcgr = 0x17008,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s0_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_qupv3_i2c_s1_clk_src = {
+ .cmd_rcgr = 0x17024,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s1_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_qupv3_i2c_s2_clk_src = {
+ .cmd_rcgr = 0x17040,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s2_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_qupv3_i2c_s3_clk_src = {
+ .cmd_rcgr = 0x1705c,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s3_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_qupv3_i2c_s4_clk_src = {
+ .cmd_rcgr = 0x17078,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s4_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_qupv3_i2c_s5_clk_src = {
+ .cmd_rcgr = 0x17094,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s5_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_qupv3_i2c_s6_clk_src = {
+ .cmd_rcgr = 0x170b0,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s6_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_qupv3_i2c_s7_clk_src = {
+ .cmd_rcgr = 0x170cc,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s7_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_qupv3_i2c_s8_clk_src = {
+ .cmd_rcgr = 0x170e8,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s8_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_qupv3_i2c_s9_clk_src = {
+ .cmd_rcgr = 0x17104,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s9_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_qupv3_wrap1_s0_clk_src[] = {
+ F(7372800, P_GCC_GPLL0_OUT_EVEN, 1, 384, 15625),
+ F(14745600, P_GCC_GPLL0_OUT_EVEN, 1, 768, 15625),
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(29491200, P_GCC_GPLL0_OUT_EVEN, 1, 1536, 15625),
+ F(32000000, P_GCC_GPLL0_OUT_EVEN, 1, 8, 75),
+ F(48000000, P_GCC_GPLL0_OUT_EVEN, 1, 4, 25),
+ F(51200000, P_GCC_GPLL0_OUT_EVEN, 1, 64, 375),
+ F(64000000, P_GCC_GPLL0_OUT_EVEN, 1, 16, 75),
+ F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0),
+ F(80000000, P_GCC_GPLL0_OUT_EVEN, 1, 4, 15),
+ F(96000000, P_GCC_GPLL0_OUT_EVEN, 1, 8, 25),
+ F(100000000, P_GCC_GPLL0_OUT_MAIN, 6, 0, 0),
+ F(102400000, P_GCC_GPLL0_OUT_EVEN, 1, 128, 375),
+ F(112000000, P_GCC_GPLL0_OUT_EVEN, 1, 28, 75),
+ F(117964800, P_GCC_GPLL0_OUT_EVEN, 1, 6144, 15625),
+ F(120000000, P_GCC_GPLL0_OUT_MAIN, 5, 0, 0),
+ { }
+};
+
+static struct clk_init_data gcc_qupv3_wrap1_s0_clk_src_init = {
+ .name = "gcc_qupv3_wrap1_s0_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s0_clk_src = {
+ .cmd_rcgr = 0x18010,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap1_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s0_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap1_s1_clk_src_init = {
+ .name = "gcc_qupv3_wrap1_s1_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s1_clk_src = {
+ .cmd_rcgr = 0x18148,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap1_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s1_clk_src_init,
+};
+
+static const struct freq_tbl ftbl_gcc_qupv3_wrap1_s2_clk_src[] = {
+ F(7372800, P_GCC_GPLL0_OUT_EVEN, 1, 384, 15625),
+ F(14745600, P_GCC_GPLL0_OUT_EVEN, 1, 768, 15625),
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(29491200, P_GCC_GPLL0_OUT_EVEN, 1, 1536, 15625),
+ F(32000000, P_GCC_GPLL0_OUT_EVEN, 1, 8, 75),
+ F(48000000, P_GCC_GPLL0_OUT_EVEN, 1, 4, 25),
+ F(51200000, P_GCC_GPLL0_OUT_EVEN, 1, 64, 375),
+ F(64000000, P_GCC_GPLL0_OUT_EVEN, 1, 16, 75),
+ F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0),
+ F(80000000, P_GCC_GPLL0_OUT_EVEN, 1, 4, 15),
+ F(96000000, P_GCC_GPLL0_OUT_EVEN, 1, 8, 25),
+ F(100000000, P_GCC_GPLL0_OUT_MAIN, 6, 0, 0),
+ { }
+};
+
+static struct clk_init_data gcc_qupv3_wrap1_s2_clk_src_init = {
+ .name = "gcc_qupv3_wrap1_s2_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s2_clk_src = {
+ .cmd_rcgr = 0x18280,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap1_s2_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s2_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap1_s3_clk_src_init = {
+ .name = "gcc_qupv3_wrap1_s3_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s3_clk_src = {
+ .cmd_rcgr = 0x183b8,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap1_s2_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s3_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap1_s4_clk_src_init = {
+ .name = "gcc_qupv3_wrap1_s4_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s4_clk_src = {
+ .cmd_rcgr = 0x184f0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap1_s2_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s4_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap1_s5_clk_src_init = {
+ .name = "gcc_qupv3_wrap1_s5_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s5_clk_src = {
+ .cmd_rcgr = 0x18628,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap1_s2_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s5_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap1_s6_clk_src_init = {
+ .name = "gcc_qupv3_wrap1_s6_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s6_clk_src = {
+ .cmd_rcgr = 0x18760,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap1_s2_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s6_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap1_s7_clk_src_init = {
+ .name = "gcc_qupv3_wrap1_s7_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap1_s7_clk_src = {
+ .cmd_rcgr = 0x18898,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap1_s2_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap1_s7_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap2_s0_clk_src_init = {
+ .name = "gcc_qupv3_wrap2_s0_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap2_s0_clk_src = {
+ .cmd_rcgr = 0x1e010,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap1_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap2_s0_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap2_s1_clk_src_init = {
+ .name = "gcc_qupv3_wrap2_s1_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap2_s1_clk_src = {
+ .cmd_rcgr = 0x1e148,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap1_s0_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap2_s1_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap2_s2_clk_src_init = {
+ .name = "gcc_qupv3_wrap2_s2_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap2_s2_clk_src = {
+ .cmd_rcgr = 0x1e280,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap1_s2_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap2_s2_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap2_s3_clk_src_init = {
+ .name = "gcc_qupv3_wrap2_s3_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap2_s3_clk_src = {
+ .cmd_rcgr = 0x1e3b8,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap1_s2_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap2_s3_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap2_s4_clk_src_init = {
+ .name = "gcc_qupv3_wrap2_s4_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap2_s4_clk_src = {
+ .cmd_rcgr = 0x1e4f0,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap1_s2_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap2_s4_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap2_s5_clk_src_init = {
+ .name = "gcc_qupv3_wrap2_s5_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap2_s5_clk_src = {
+ .cmd_rcgr = 0x1e628,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap1_s2_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap2_s5_clk_src_init,
+};
+
+static const struct freq_tbl ftbl_gcc_qupv3_wrap2_s6_clk_src[] = {
+ F(7372800, P_GCC_GPLL0_OUT_EVEN, 1, 384, 15625),
+ F(14745600, P_GCC_GPLL0_OUT_EVEN, 1, 768, 15625),
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ F(29491200, P_GCC_GPLL0_OUT_EVEN, 1, 1536, 15625),
+ F(32000000, P_GCC_GPLL0_OUT_EVEN, 1, 8, 75),
+ F(48000000, P_GCC_GPLL0_OUT_EVEN, 1, 4, 25),
+ F(51200000, P_GCC_GPLL0_OUT_EVEN, 1, 64, 375),
+ F(64000000, P_GCC_GPLL0_OUT_EVEN, 1, 16, 75),
+ F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0),
+ F(80000000, P_GCC_GPLL0_OUT_EVEN, 1, 4, 15),
+ F(96000000, P_GCC_GPLL0_OUT_EVEN, 1, 8, 25),
+ F(100000000, P_GCC_GPLL0_OUT_MAIN, 6, 0, 0),
+ F(102400000, P_GCC_GPLL0_OUT_EVEN, 1, 128, 375),
+ F(112000000, P_GCC_GPLL0_OUT_EVEN, 1, 28, 75),
+ F(117964800, P_GCC_GPLL0_OUT_EVEN, 1, 6144, 15625),
+ F(120000000, P_GCC_GPLL0_OUT_MAIN, 5, 0, 0),
+ F(125000000, P_GCC_GPLL0_OUT_MAIN, 1, 5, 24),
+ { }
+};
+
+static struct clk_init_data gcc_qupv3_wrap2_s6_clk_src_init = {
+ .name = "gcc_qupv3_wrap2_s6_clk_src",
+ .parent_data = gcc_parent_data_8,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_8),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap2_s6_clk_src = {
+ .cmd_rcgr = 0x1e760,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_8,
+ .freq_tbl = ftbl_gcc_qupv3_wrap2_s6_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap2_s6_clk_src_init,
+};
+
+static struct clk_init_data gcc_qupv3_wrap2_s7_clk_src_init = {
+ .name = "gcc_qupv3_wrap2_s7_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+};
+
+static struct clk_rcg2 gcc_qupv3_wrap2_s7_clk_src = {
+ .cmd_rcgr = 0x1e898,
+ .mnd_width = 16,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_qupv3_wrap1_s2_clk_src,
+ .clkr.hw.init = &gcc_qupv3_wrap2_s7_clk_src_init,
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc2_apps_clk_src[] = {
+ F(400000, P_BI_TCXO, 12, 1, 4),
+ F(25000000, P_GCC_GPLL0_OUT_EVEN, 12, 0, 0),
+ F(37500000, P_GCC_GPLL0_OUT_EVEN, 8, 0, 0),
+ F(50000000, P_GCC_GPLL0_OUT_EVEN, 6, 0, 0),
+ F(100000000, P_GCC_GPLL0_OUT_EVEN, 3, 0, 0),
+ F(202000000, P_GCC_GPLL9_OUT_MAIN, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_sdcc2_apps_clk_src = {
+ .cmd_rcgr = 0x14018,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_9,
+ .freq_tbl = ftbl_gcc_sdcc2_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_apps_clk_src",
+ .parent_data = gcc_parent_data_9,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_9),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc4_apps_clk_src[] = {
+ F(400000, P_BI_TCXO, 12, 1, 4),
+ F(25000000, P_GCC_GPLL0_OUT_EVEN, 12, 0, 0),
+ F(37500000, P_GCC_GPLL0_OUT_EVEN, 8, 0, 0),
+ F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_sdcc4_apps_clk_src = {
+ .cmd_rcgr = 0x16018,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_sdcc4_apps_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc4_apps_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ufs_phy_axi_clk_src[] = {
+ F(25000000, P_GCC_GPLL0_OUT_EVEN, 12, 0, 0),
+ F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0),
+ F(150000000, P_GCC_GPLL0_OUT_MAIN, 4, 0, 0),
+ F(300000000, P_GCC_GPLL0_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_ufs_phy_axi_clk_src = {
+ .cmd_rcgr = 0x77030,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_ufs_phy_axi_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_axi_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ufs_phy_ice_core_clk_src[] = {
+ F(100000000, P_GCC_GPLL0_OUT_EVEN, 3, 0, 0),
+ F(201500000, P_GCC_GPLL4_OUT_MAIN, 4, 0, 0),
+ F(403000000, P_GCC_GPLL4_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_ufs_phy_ice_core_clk_src = {
+ .cmd_rcgr = 0x77080,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_3,
+ .freq_tbl = ftbl_gcc_ufs_phy_ice_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_ice_core_clk_src",
+ .parent_data = gcc_parent_data_3,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_3),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ufs_phy_phy_aux_clk_src[] = {
+ F(9600000, P_BI_TCXO, 2, 0, 0),
+ F(19200000, P_BI_TCXO, 1, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_ufs_phy_phy_aux_clk_src = {
+ .cmd_rcgr = 0x770b4,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_4,
+ .freq_tbl = ftbl_gcc_ufs_phy_phy_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_phy_aux_clk_src",
+ .parent_data = gcc_parent_data_4,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_4),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_ufs_phy_unipro_core_clk_src[] = {
+ F(75000000, P_GCC_GPLL0_OUT_EVEN, 4, 0, 0),
+ F(150000000, P_GCC_GPLL0_OUT_MAIN, 4, 0, 0),
+ F(300000000, P_GCC_GPLL0_OUT_MAIN, 2, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_ufs_phy_unipro_core_clk_src = {
+ .cmd_rcgr = 0x77098,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_ufs_phy_unipro_core_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_unipro_core_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static const struct freq_tbl ftbl_gcc_usb30_prim_master_clk_src[] = {
+ F(66666667, P_GCC_GPLL0_OUT_EVEN, 4.5, 0, 0),
+ F(133333333, P_GCC_GPLL0_OUT_MAIN, 4.5, 0, 0),
+ F(200000000, P_GCC_GPLL0_OUT_MAIN, 3, 0, 0),
+ F(240000000, P_GCC_GPLL0_OUT_MAIN, 2.5, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 gcc_usb30_prim_master_clk_src = {
+ .cmd_rcgr = 0x3902c,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_usb30_prim_master_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_prim_master_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_usb30_prim_mock_utmi_clk_src = {
+ .cmd_rcgr = 0x39044,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_0,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_prim_mock_utmi_clk_src",
+ .parent_data = gcc_parent_data_0,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_0),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gcc_usb3_prim_phy_aux_clk_src = {
+ .cmd_rcgr = 0x39070,
+ .mnd_width = 0,
+ .hid_width = 5,
+ .parent_map = gcc_parent_map_2,
+ .freq_tbl = ftbl_gcc_pcie_0_aux_clk_src,
+ .clkr.hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_prim_phy_aux_clk_src",
+ .parent_data = gcc_parent_data_2,
+ .num_parents = ARRAY_SIZE(gcc_parent_data_2),
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_regmap_div gcc_usb30_prim_mock_utmi_postdiv_clk_src = {
+ .reg = 0x3905c,
+ .shift = 0,
+ .width = 4,
+ .clkr.hw.init = &(struct clk_init_data) {
+ .name = "gcc_usb30_prim_mock_utmi_postdiv_clk_src",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_usb30_prim_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_aggre_noc_pcie_axi_clk = {
+ .halt_reg = 0x1003c,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x1003c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(12),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre_noc_pcie_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_aggre_ufs_phy_axi_clk = {
+ .halt_reg = 0x770e4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x770e4,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x770e4,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre_ufs_phy_axi_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_ufs_phy_axi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_aggre_ufs_phy_axi_hw_ctl_clk = {
+ .halt_reg = 0x770e4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x770e4,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x770e4,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre_ufs_phy_axi_hw_ctl_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_ufs_phy_axi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_aggre_usb3_prim_axi_clk = {
+ .halt_reg = 0x3908c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x3908c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3908c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_aggre_usb3_prim_axi_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_usb30_prim_master_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_boot_rom_ahb_clk = {
+ .halt_reg = 0x38004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x38004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(10),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_boot_rom_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camera_hf_axi_clk = {
+ .halt_reg = 0x26010,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x26010,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x26010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camera_hf_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_camera_sf_axi_clk = {
+ .halt_reg = 0x2601c,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x2601c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x2601c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_camera_sf_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cfg_noc_pcie_anoc_ahb_clk = {
+ .halt_reg = 0x10028,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x10028,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(20),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_cfg_noc_pcie_anoc_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cfg_noc_usb3_prim_axi_clk = {
+ .halt_reg = 0x39088,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x39088,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x39088,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_cfg_noc_usb3_prim_axi_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_usb30_prim_master_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_cnoc_pcie_sf_axi_clk = {
+ .halt_reg = 0x10030,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x10030,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(6),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_cnoc_pcie_sf_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ddrss_gpu_axi_clk = {
+ .halt_reg = 0x71154,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x71154,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x71154,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ddrss_gpu_axi_clk",
+ .ops = &clk_branch2_aon_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ddrss_pcie_sf_qtb_clk = {
+ .halt_reg = 0x1004c,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x1004c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(19),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ddrss_pcie_sf_qtb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_disp_hf_axi_clk = {
+ .halt_reg = 0x2700c,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x2700c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x2700c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_disp_hf_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gp1_clk = {
+ .halt_reg = 0x64000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x64000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp1_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .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 = 0x65000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x65000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp2_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .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 = 0x66000,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x66000,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gp3_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_gp3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_gpll0_clk_src = {
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(15),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_gpll0_clk_src",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_gpll0.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_gpll0_div_clk_src = {
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(16),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_gpll0_div_clk_src",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_gpll0_out_even.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_memnoc_gfx_clk = {
+ .halt_reg = 0x71010,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x71010,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x71010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_memnoc_gfx_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_gpu_snoc_dvm_gfx_clk = {
+ .halt_reg = 0x71018,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x71018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_gpu_snoc_dvm_gfx_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_aux_clk = {
+ .halt_reg = 0x6b03c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(3),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_aux_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_pcie_0_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_cfg_ahb_clk = {
+ .halt_reg = 0x6b038,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x6b038,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_mstr_axi_clk = {
+ .halt_reg = 0x6b02c,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x6b02c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_mstr_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_phy_rchng_clk = {
+ .halt_reg = 0x6b054,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(22),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_phy_rchng_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_pcie_0_phy_rchng_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_pipe_clk = {
+ .halt_reg = 0x6b048,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_pipe_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_pcie_0_pipe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_slv_axi_clk = {
+ .halt_reg = 0x6b020,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x6b020,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_slv_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_0_slv_q2a_axi_clk = {
+ .halt_reg = 0x6b01c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(5),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_0_slv_q2a_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_aux_clk = {
+ .halt_reg = 0x8d038,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(29),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_aux_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_pcie_1_aux_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 = 0x8d034,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x8d034,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(28),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_cfg_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_mstr_axi_clk = {
+ .halt_reg = 0x8d028,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x8d028,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(27),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_mstr_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_phy_aux_clk = {
+ .halt_reg = 0x8d044,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(24),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_phy_aux_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_pcie_1_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pcie_1_phy_rchng_clk = {
+ .halt_reg = 0x8d05c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(23),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_phy_rchng_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .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 = 0x8d050,
+ .halt_check = BRANCH_HALT_SKIP,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(30),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_pipe_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .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_slv_axi_clk = {
+ .halt_reg = 0x8d01c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x8d01c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(26),
+ .hw.init = &(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 = 0x8d018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(25),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pcie_1_slv_q2a_axi_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm2_clk = {
+ .halt_reg = 0x3300c,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x3300c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm2_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .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 = 0x33004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x33004,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x33004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_pdm_xo4_clk = {
+ .halt_reg = 0x33008,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x33008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_pdm_xo4_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_camera_nrt_ahb_clk = {
+ .halt_reg = 0x26008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x26008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x26008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qmip_camera_nrt_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_camera_rt_ahb_clk = {
+ .halt_reg = 0x2600c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x2600c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x2600c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qmip_camera_rt_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_disp_ahb_clk = {
+ .halt_reg = 0x27008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x27008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x27008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qmip_disp_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_gpu_ahb_clk = {
+ .halt_reg = 0x71008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x71008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x71008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qmip_gpu_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_pcie_ahb_clk = {
+ .halt_reg = 0x6b018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x6b018,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52000,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qmip_pcie_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_video_cv_cpu_ahb_clk = {
+ .halt_reg = 0x32014,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x32014,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x32014,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qmip_video_cv_cpu_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_video_cvp_ahb_clk = {
+ .halt_reg = 0x32008,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x32008,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x32008,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qmip_video_cvp_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_video_v_cpu_ahb_clk = {
+ .halt_reg = 0x32010,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x32010,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x32010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qmip_video_v_cpu_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qmip_video_vcodec_ahb_clk = {
+ .halt_reg = 0x3200c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x3200c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x3200c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qmip_video_vcodec_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_i2c_core_clk = {
+ .halt_reg = 0x23144,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(8),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_core_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_i2c_s0_clk = {
+ .halt_reg = 0x17004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(10),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s0_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_i2c_s0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_i2c_s1_clk = {
+ .halt_reg = 0x17020,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(11),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s1_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_i2c_s1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_i2c_s2_clk = {
+ .halt_reg = 0x1703c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(12),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s2_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_i2c_s2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_i2c_s3_clk = {
+ .halt_reg = 0x17058,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(13),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s3_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_i2c_s3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_i2c_s4_clk = {
+ .halt_reg = 0x17074,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(14),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s4_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_i2c_s4_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_i2c_s5_clk = {
+ .halt_reg = 0x17090,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(15),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s5_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_i2c_s5_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_i2c_s6_clk = {
+ .halt_reg = 0x170ac,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(16),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s6_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_i2c_s6_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_i2c_s7_clk = {
+ .halt_reg = 0x170c8,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(17),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s7_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_i2c_s7_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_i2c_s8_clk = {
+ .halt_reg = 0x170e4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52010,
+ .enable_mask = BIT(14),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s8_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_i2c_s8_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_i2c_s9_clk = {
+ .halt_reg = 0x17100,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52010,
+ .enable_mask = BIT(15),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s9_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_i2c_s9_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_i2c_s_ahb_clk = {
+ .halt_reg = 0x23140,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x23140,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(7),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_i2c_s_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_core_2x_clk = {
+ .halt_reg = 0x23294,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(18),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap1_core_2x_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_core_clk = {
+ .halt_reg = 0x23284,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(19),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap1_core_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_s0_clk = {
+ .halt_reg = 0x18004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(22),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap1_s0_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_wrap1_s0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_s1_clk = {
+ .halt_reg = 0x1813c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(23),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap1_s1_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_wrap1_s1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_s2_clk = {
+ .halt_reg = 0x18274,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(24),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap1_s2_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_wrap1_s2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_s3_clk = {
+ .halt_reg = 0x183ac,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(25),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap1_s3_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_wrap1_s3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_s4_clk = {
+ .halt_reg = 0x184e4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(26),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap1_s4_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_wrap1_s4_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_s5_clk = {
+ .halt_reg = 0x1861c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(27),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap1_s5_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_wrap1_s5_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_s6_clk = {
+ .halt_reg = 0x18754,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(28),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap1_s6_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_wrap1_s6_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap1_s7_clk = {
+ .halt_reg = 0x1888c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52010,
+ .enable_mask = BIT(16),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap1_s7_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_wrap1_s7_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap2_core_2x_clk = {
+ .halt_reg = 0x23004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52010,
+ .enable_mask = BIT(3),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap2_core_2x_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap2_core_clk = {
+ .halt_reg = 0x233d4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap2_core_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap2_s0_clk = {
+ .halt_reg = 0x1e004,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52010,
+ .enable_mask = BIT(4),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap2_s0_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_wrap2_s0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap2_s1_clk = {
+ .halt_reg = 0x1e13c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52010,
+ .enable_mask = BIT(5),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap2_s1_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_wrap2_s1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap2_s2_clk = {
+ .halt_reg = 0x1e274,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52010,
+ .enable_mask = BIT(6),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap2_s2_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_wrap2_s2_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap2_s3_clk = {
+ .halt_reg = 0x1e3ac,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52010,
+ .enable_mask = BIT(7),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap2_s3_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_wrap2_s3_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap2_s4_clk = {
+ .halt_reg = 0x1e4e4,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52010,
+ .enable_mask = BIT(8),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap2_s4_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_wrap2_s4_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap2_s5_clk = {
+ .halt_reg = 0x1e61c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52010,
+ .enable_mask = BIT(9),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap2_s5_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_wrap2_s5_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap2_s6_clk = {
+ .halt_reg = 0x1e754,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52010,
+ .enable_mask = BIT(10),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap2_s6_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_wrap2_s6_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap2_s7_clk = {
+ .halt_reg = 0x1e88c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .clkr = {
+ .enable_reg = 0x52010,
+ .enable_mask = BIT(17),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap2_s7_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_qupv3_wrap2_s7_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_1_m_ahb_clk = {
+ .halt_reg = 0x2327c,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x2327c,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(20),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap_1_m_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_1_s_ahb_clk = {
+ .halt_reg = 0x23280,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x23280,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52008,
+ .enable_mask = BIT(21),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap_1_s_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_2_m_ahb_clk = {
+ .halt_reg = 0x233cc,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x233cc,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52010,
+ .enable_mask = BIT(2),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap_2_m_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_qupv3_wrap_2_s_ahb_clk = {
+ .halt_reg = 0x233d0,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x233d0,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x52010,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_qupv3_wrap_2_s_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc2_ahb_clk = {
+ .halt_reg = 0x14010,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x14010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc2_apps_clk = {
+ .halt_reg = 0x14004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x14004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc2_apps_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .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_sdcc4_ahb_clk = {
+ .halt_reg = 0x16010,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x16010,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc4_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_sdcc4_apps_clk = {
+ .halt_reg = 0x16004,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x16004,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_sdcc4_apps_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_sdcc4_apps_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_ahb_clk = {
+ .halt_reg = 0x77024,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x77024,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x77024,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_ahb_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_axi_clk = {
+ .halt_reg = 0x77018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x77018,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x77018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_axi_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_ufs_phy_axi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_axi_hw_ctl_clk = {
+ .halt_reg = 0x77018,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x77018,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x77018,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_axi_hw_ctl_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_ufs_phy_axi_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_ice_core_clk = {
+ .halt_reg = 0x77074,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x77074,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x77074,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_ice_core_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_ufs_phy_ice_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_ice_core_hw_ctl_clk = {
+ .halt_reg = 0x77074,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x77074,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x77074,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_ice_core_hw_ctl_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_ufs_phy_ice_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_phy_aux_clk = {
+ .halt_reg = 0x770b0,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x770b0,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x770b0,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_phy_aux_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_ufs_phy_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_phy_aux_hw_ctl_clk = {
+ .halt_reg = 0x770b0,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x770b0,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x770b0,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_phy_aux_hw_ctl_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_ufs_phy_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_rx_symbol_0_clk = {
+ .halt_reg = 0x7702c,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x7702c,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_rx_symbol_0_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_ufs_phy_rx_symbol_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_rx_symbol_1_clk = {
+ .halt_reg = 0x770cc,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x770cc,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_rx_symbol_1_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_ufs_phy_rx_symbol_1_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_tx_symbol_0_clk = {
+ .halt_reg = 0x77028,
+ .halt_check = BRANCH_HALT_DELAY,
+ .clkr = {
+ .enable_reg = 0x77028,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_tx_symbol_0_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_ufs_phy_tx_symbol_0_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_unipro_core_clk = {
+ .halt_reg = 0x77068,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x77068,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x77068,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_unipro_core_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_ufs_phy_unipro_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_ufs_phy_unipro_core_hw_ctl_clk = {
+ .halt_reg = 0x77068,
+ .halt_check = BRANCH_HALT_VOTED,
+ .hwcg_reg = 0x77068,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x77068,
+ .enable_mask = BIT(1),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_ufs_phy_unipro_core_hw_ctl_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_ufs_phy_unipro_core_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_prim_master_clk = {
+ .halt_reg = 0x39018,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x39018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_prim_master_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_usb30_prim_master_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb30_prim_mock_utmi_clk = {
+ .halt_reg = 0x39028,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x39028,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_prim_mock_utmi_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_usb30_prim_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_prim_sleep_clk = {
+ .halt_reg = 0x39024,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x39024,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb30_prim_sleep_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_prim_phy_aux_clk = {
+ .halt_reg = 0x39060,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x39060,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_prim_phy_aux_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_usb3_prim_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_prim_phy_com_aux_clk = {
+ .halt_reg = 0x39064,
+ .halt_check = BRANCH_HALT,
+ .clkr = {
+ .enable_reg = 0x39064,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_prim_phy_com_aux_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_usb3_prim_phy_aux_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_usb3_prim_phy_pipe_clk = {
+ .halt_reg = 0x39068,
+ .halt_check = BRANCH_HALT_DELAY,
+ .hwcg_reg = 0x39068,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x39068,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_usb3_prim_phy_pipe_clk",
+ .parent_data = &(const struct clk_parent_data){
+ .hw = &gcc_usb3_prim_phy_pipe_clk_src.clkr.hw,
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_video_axi0_clk = {
+ .halt_reg = 0x32018,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x32018,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x32018,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_video_axi0_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct clk_branch gcc_video_axi1_clk = {
+ .halt_reg = 0x32024,
+ .halt_check = BRANCH_HALT_SKIP,
+ .hwcg_reg = 0x32024,
+ .hwcg_bit = 1,
+ .clkr = {
+ .enable_reg = 0x32024,
+ .enable_mask = BIT(0),
+ .hw.init = &(struct clk_init_data){
+ .name = "gcc_video_axi1_clk",
+ .ops = &clk_branch2_ops,
+ },
+ },
+};
+
+static struct gdsc pcie_0_gdsc = {
+ .gdscr = 0x6b004,
+ .pd = {
+ .name = "pcie_0_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR,
+};
+
+static struct gdsc pcie_0_phy_gdsc = {
+ .gdscr = 0x6c000,
+ .pd = {
+ .name = "pcie_0_phy_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR,
+};
+
+static struct gdsc pcie_1_gdsc = {
+ .gdscr = 0x8d004,
+ .pd = {
+ .name = "pcie_1_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR,
+};
+
+static struct gdsc pcie_1_phy_gdsc = {
+ .gdscr = 0x8e000,
+ .pd = {
+ .name = "pcie_1_phy_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR,
+};
+
+static struct gdsc ufs_phy_gdsc = {
+ .gdscr = 0x77004,
+ .pd = {
+ .name = "ufs_phy_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR,
+};
+
+static struct gdsc ufs_mem_phy_gdsc = {
+ .gdscr = 0x9e000,
+ .pd = {
+ .name = "ufs_mem_phy_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR,
+};
+
+static struct gdsc usb30_prim_gdsc = {
+ .gdscr = 0x39004,
+ .pd = {
+ .name = "usb30_prim_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR,
+};
+
+static struct gdsc usb3_phy_gdsc = {
+ .gdscr = 0x50018,
+ .pd = {
+ .name = "usb3_phy_gdsc",
+ },
+ .pwrsts = PWRSTS_OFF_ON,
+ .flags = POLL_CFG_GDSCR,
+};
+
+static struct clk_regmap *gcc_sm8550_clocks[] = {
+ [GCC_AGGRE_NOC_PCIE_AXI_CLK] = &gcc_aggre_noc_pcie_axi_clk.clkr,
+ [GCC_AGGRE_UFS_PHY_AXI_CLK] = &gcc_aggre_ufs_phy_axi_clk.clkr,
+ [GCC_AGGRE_UFS_PHY_AXI_HW_CTL_CLK] = &gcc_aggre_ufs_phy_axi_hw_ctl_clk.clkr,
+ [GCC_AGGRE_USB3_PRIM_AXI_CLK] = &gcc_aggre_usb3_prim_axi_clk.clkr,
+ [GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.clkr,
+ [GCC_CAMERA_HF_AXI_CLK] = &gcc_camera_hf_axi_clk.clkr,
+ [GCC_CAMERA_SF_AXI_CLK] = &gcc_camera_sf_axi_clk.clkr,
+ [GCC_CFG_NOC_PCIE_ANOC_AHB_CLK] = &gcc_cfg_noc_pcie_anoc_ahb_clk.clkr,
+ [GCC_CFG_NOC_USB3_PRIM_AXI_CLK] = &gcc_cfg_noc_usb3_prim_axi_clk.clkr,
+ [GCC_CNOC_PCIE_SF_AXI_CLK] = &gcc_cnoc_pcie_sf_axi_clk.clkr,
+ [GCC_DDRSS_GPU_AXI_CLK] = &gcc_ddrss_gpu_axi_clk.clkr,
+ [GCC_DDRSS_PCIE_SF_QTB_CLK] = &gcc_ddrss_pcie_sf_qtb_clk.clkr,
+ [GCC_DISP_HF_AXI_CLK] = &gcc_disp_hf_axi_clk.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_GPLL0] = &gcc_gpll0.clkr,
+ [GCC_GPLL0_OUT_EVEN] = &gcc_gpll0_out_even.clkr,
+ [GCC_GPLL4] = &gcc_gpll4.clkr,
+ [GCC_GPLL7] = &gcc_gpll7.clkr,
+ [GCC_GPLL9] = &gcc_gpll9.clkr,
+ [GCC_GPU_GPLL0_CLK_SRC] = &gcc_gpu_gpll0_clk_src.clkr,
+ [GCC_GPU_GPLL0_DIV_CLK_SRC] = &gcc_gpu_gpll0_div_clk_src.clkr,
+ [GCC_GPU_MEMNOC_GFX_CLK] = &gcc_gpu_memnoc_gfx_clk.clkr,
+ [GCC_GPU_SNOC_DVM_GFX_CLK] = &gcc_gpu_snoc_dvm_gfx_clk.clkr,
+ [GCC_PCIE_0_AUX_CLK] = &gcc_pcie_0_aux_clk.clkr,
+ [GCC_PCIE_0_AUX_CLK_SRC] = &gcc_pcie_0_aux_clk_src.clkr,
+ [GCC_PCIE_0_CFG_AHB_CLK] = &gcc_pcie_0_cfg_ahb_clk.clkr,
+ [GCC_PCIE_0_MSTR_AXI_CLK] = &gcc_pcie_0_mstr_axi_clk.clkr,
+ [GCC_PCIE_0_PHY_RCHNG_CLK] = &gcc_pcie_0_phy_rchng_clk.clkr,
+ [GCC_PCIE_0_PHY_RCHNG_CLK_SRC] = &gcc_pcie_0_phy_rchng_clk_src.clkr,
+ [GCC_PCIE_0_PIPE_CLK] = &gcc_pcie_0_pipe_clk.clkr,
+ [GCC_PCIE_0_PIPE_CLK_SRC] = &gcc_pcie_0_pipe_clk_src.clkr,
+ [GCC_PCIE_0_SLV_AXI_CLK] = &gcc_pcie_0_slv_axi_clk.clkr,
+ [GCC_PCIE_0_SLV_Q2A_AXI_CLK] = &gcc_pcie_0_slv_q2a_axi_clk.clkr,
+ [GCC_PCIE_1_AUX_CLK] = &gcc_pcie_1_aux_clk.clkr,
+ [GCC_PCIE_1_AUX_CLK_SRC] = &gcc_pcie_1_aux_clk_src.clkr,
+ [GCC_PCIE_1_CFG_AHB_CLK] = &gcc_pcie_1_cfg_ahb_clk.clkr,
+ [GCC_PCIE_1_MSTR_AXI_CLK] = &gcc_pcie_1_mstr_axi_clk.clkr,
+ [GCC_PCIE_1_PHY_AUX_CLK] = &gcc_pcie_1_phy_aux_clk.clkr,
+ [GCC_PCIE_1_PHY_AUX_CLK_SRC] = &gcc_pcie_1_phy_aux_clk_src.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_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_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_QMIP_CAMERA_NRT_AHB_CLK] = &gcc_qmip_camera_nrt_ahb_clk.clkr,
+ [GCC_QMIP_CAMERA_RT_AHB_CLK] = &gcc_qmip_camera_rt_ahb_clk.clkr,
+ [GCC_QMIP_DISP_AHB_CLK] = &gcc_qmip_disp_ahb_clk.clkr,
+ [GCC_QMIP_GPU_AHB_CLK] = &gcc_qmip_gpu_ahb_clk.clkr,
+ [GCC_QMIP_PCIE_AHB_CLK] = &gcc_qmip_pcie_ahb_clk.clkr,
+ [GCC_QMIP_VIDEO_CV_CPU_AHB_CLK] = &gcc_qmip_video_cv_cpu_ahb_clk.clkr,
+ [GCC_QMIP_VIDEO_CVP_AHB_CLK] = &gcc_qmip_video_cvp_ahb_clk.clkr,
+ [GCC_QMIP_VIDEO_V_CPU_AHB_CLK] = &gcc_qmip_video_v_cpu_ahb_clk.clkr,
+ [GCC_QMIP_VIDEO_VCODEC_AHB_CLK] = &gcc_qmip_video_vcodec_ahb_clk.clkr,
+ [GCC_QUPV3_I2C_CORE_CLK] = &gcc_qupv3_i2c_core_clk.clkr,
+ [GCC_QUPV3_I2C_S0_CLK] = &gcc_qupv3_i2c_s0_clk.clkr,
+ [GCC_QUPV3_I2C_S0_CLK_SRC] = &gcc_qupv3_i2c_s0_clk_src.clkr,
+ [GCC_QUPV3_I2C_S1_CLK] = &gcc_qupv3_i2c_s1_clk.clkr,
+ [GCC_QUPV3_I2C_S1_CLK_SRC] = &gcc_qupv3_i2c_s1_clk_src.clkr,
+ [GCC_QUPV3_I2C_S2_CLK] = &gcc_qupv3_i2c_s2_clk.clkr,
+ [GCC_QUPV3_I2C_S2_CLK_SRC] = &gcc_qupv3_i2c_s2_clk_src.clkr,
+ [GCC_QUPV3_I2C_S3_CLK] = &gcc_qupv3_i2c_s3_clk.clkr,
+ [GCC_QUPV3_I2C_S3_CLK_SRC] = &gcc_qupv3_i2c_s3_clk_src.clkr,
+ [GCC_QUPV3_I2C_S4_CLK] = &gcc_qupv3_i2c_s4_clk.clkr,
+ [GCC_QUPV3_I2C_S4_CLK_SRC] = &gcc_qupv3_i2c_s4_clk_src.clkr,
+ [GCC_QUPV3_I2C_S5_CLK] = &gcc_qupv3_i2c_s5_clk.clkr,
+ [GCC_QUPV3_I2C_S5_CLK_SRC] = &gcc_qupv3_i2c_s5_clk_src.clkr,
+ [GCC_QUPV3_I2C_S6_CLK] = &gcc_qupv3_i2c_s6_clk.clkr,
+ [GCC_QUPV3_I2C_S6_CLK_SRC] = &gcc_qupv3_i2c_s6_clk_src.clkr,
+ [GCC_QUPV3_I2C_S7_CLK] = &gcc_qupv3_i2c_s7_clk.clkr,
+ [GCC_QUPV3_I2C_S7_CLK_SRC] = &gcc_qupv3_i2c_s7_clk_src.clkr,
+ [GCC_QUPV3_I2C_S8_CLK] = &gcc_qupv3_i2c_s8_clk.clkr,
+ [GCC_QUPV3_I2C_S8_CLK_SRC] = &gcc_qupv3_i2c_s8_clk_src.clkr,
+ [GCC_QUPV3_I2C_S9_CLK] = &gcc_qupv3_i2c_s9_clk.clkr,
+ [GCC_QUPV3_I2C_S9_CLK_SRC] = &gcc_qupv3_i2c_s9_clk_src.clkr,
+ [GCC_QUPV3_I2C_S_AHB_CLK] = &gcc_qupv3_i2c_s_ahb_clk.clkr,
+ [GCC_QUPV3_WRAP1_CORE_2X_CLK] = &gcc_qupv3_wrap1_core_2x_clk.clkr,
+ [GCC_QUPV3_WRAP1_CORE_CLK] = &gcc_qupv3_wrap1_core_clk.clkr,
+ [GCC_QUPV3_WRAP1_S0_CLK] = &gcc_qupv3_wrap1_s0_clk.clkr,
+ [GCC_QUPV3_WRAP1_S0_CLK_SRC] = &gcc_qupv3_wrap1_s0_clk_src.clkr,
+ [GCC_QUPV3_WRAP1_S1_CLK] = &gcc_qupv3_wrap1_s1_clk.clkr,
+ [GCC_QUPV3_WRAP1_S1_CLK_SRC] = &gcc_qupv3_wrap1_s1_clk_src.clkr,
+ [GCC_QUPV3_WRAP1_S2_CLK] = &gcc_qupv3_wrap1_s2_clk.clkr,
+ [GCC_QUPV3_WRAP1_S2_CLK_SRC] = &gcc_qupv3_wrap1_s2_clk_src.clkr,
+ [GCC_QUPV3_WRAP1_S3_CLK] = &gcc_qupv3_wrap1_s3_clk.clkr,
+ [GCC_QUPV3_WRAP1_S3_CLK_SRC] = &gcc_qupv3_wrap1_s3_clk_src.clkr,
+ [GCC_QUPV3_WRAP1_S4_CLK] = &gcc_qupv3_wrap1_s4_clk.clkr,
+ [GCC_QUPV3_WRAP1_S4_CLK_SRC] = &gcc_qupv3_wrap1_s4_clk_src.clkr,
+ [GCC_QUPV3_WRAP1_S5_CLK] = &gcc_qupv3_wrap1_s5_clk.clkr,
+ [GCC_QUPV3_WRAP1_S5_CLK_SRC] = &gcc_qupv3_wrap1_s5_clk_src.clkr,
+ [GCC_QUPV3_WRAP1_S6_CLK] = &gcc_qupv3_wrap1_s6_clk.clkr,
+ [GCC_QUPV3_WRAP1_S6_CLK_SRC] = &gcc_qupv3_wrap1_s6_clk_src.clkr,
+ [GCC_QUPV3_WRAP1_S7_CLK] = &gcc_qupv3_wrap1_s7_clk.clkr,
+ [GCC_QUPV3_WRAP1_S7_CLK_SRC] = &gcc_qupv3_wrap1_s7_clk_src.clkr,
+ [GCC_QUPV3_WRAP2_CORE_2X_CLK] = &gcc_qupv3_wrap2_core_2x_clk.clkr,
+ [GCC_QUPV3_WRAP2_CORE_CLK] = &gcc_qupv3_wrap2_core_clk.clkr,
+ [GCC_QUPV3_WRAP2_S0_CLK] = &gcc_qupv3_wrap2_s0_clk.clkr,
+ [GCC_QUPV3_WRAP2_S0_CLK_SRC] = &gcc_qupv3_wrap2_s0_clk_src.clkr,
+ [GCC_QUPV3_WRAP2_S1_CLK] = &gcc_qupv3_wrap2_s1_clk.clkr,
+ [GCC_QUPV3_WRAP2_S1_CLK_SRC] = &gcc_qupv3_wrap2_s1_clk_src.clkr,
+ [GCC_QUPV3_WRAP2_S2_CLK] = &gcc_qupv3_wrap2_s2_clk.clkr,
+ [GCC_QUPV3_WRAP2_S2_CLK_SRC] = &gcc_qupv3_wrap2_s2_clk_src.clkr,
+ [GCC_QUPV3_WRAP2_S3_CLK] = &gcc_qupv3_wrap2_s3_clk.clkr,
+ [GCC_QUPV3_WRAP2_S3_CLK_SRC] = &gcc_qupv3_wrap2_s3_clk_src.clkr,
+ [GCC_QUPV3_WRAP2_S4_CLK] = &gcc_qupv3_wrap2_s4_clk.clkr,
+ [GCC_QUPV3_WRAP2_S4_CLK_SRC] = &gcc_qupv3_wrap2_s4_clk_src.clkr,
+ [GCC_QUPV3_WRAP2_S5_CLK] = &gcc_qupv3_wrap2_s5_clk.clkr,
+ [GCC_QUPV3_WRAP2_S5_CLK_SRC] = &gcc_qupv3_wrap2_s5_clk_src.clkr,
+ [GCC_QUPV3_WRAP2_S6_CLK] = &gcc_qupv3_wrap2_s6_clk.clkr,
+ [GCC_QUPV3_WRAP2_S6_CLK_SRC] = &gcc_qupv3_wrap2_s6_clk_src.clkr,
+ [GCC_QUPV3_WRAP2_S7_CLK] = &gcc_qupv3_wrap2_s7_clk.clkr,
+ [GCC_QUPV3_WRAP2_S7_CLK_SRC] = &gcc_qupv3_wrap2_s7_clk_src.clkr,
+ [GCC_QUPV3_WRAP_1_M_AHB_CLK] = &gcc_qupv3_wrap_1_m_ahb_clk.clkr,
+ [GCC_QUPV3_WRAP_1_S_AHB_CLK] = &gcc_qupv3_wrap_1_s_ahb_clk.clkr,
+ [GCC_QUPV3_WRAP_2_M_AHB_CLK] = &gcc_qupv3_wrap_2_m_ahb_clk.clkr,
+ [GCC_QUPV3_WRAP_2_S_AHB_CLK] = &gcc_qupv3_wrap_2_s_ahb_clk.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_SDCC4_AHB_CLK] = &gcc_sdcc4_ahb_clk.clkr,
+ [GCC_SDCC4_APPS_CLK] = &gcc_sdcc4_apps_clk.clkr,
+ [GCC_SDCC4_APPS_CLK_SRC] = &gcc_sdcc4_apps_clk_src.clkr,
+ [GCC_UFS_PHY_AHB_CLK] = &gcc_ufs_phy_ahb_clk.clkr,
+ [GCC_UFS_PHY_AXI_CLK] = &gcc_ufs_phy_axi_clk.clkr,
+ [GCC_UFS_PHY_AXI_CLK_SRC] = &gcc_ufs_phy_axi_clk_src.clkr,
+ [GCC_UFS_PHY_AXI_HW_CTL_CLK] = &gcc_ufs_phy_axi_hw_ctl_clk.clkr,
+ [GCC_UFS_PHY_ICE_CORE_CLK] = &gcc_ufs_phy_ice_core_clk.clkr,
+ [GCC_UFS_PHY_ICE_CORE_CLK_SRC] = &gcc_ufs_phy_ice_core_clk_src.clkr,
+ [GCC_UFS_PHY_ICE_CORE_HW_CTL_CLK] = &gcc_ufs_phy_ice_core_hw_ctl_clk.clkr,
+ [GCC_UFS_PHY_PHY_AUX_CLK] = &gcc_ufs_phy_phy_aux_clk.clkr,
+ [GCC_UFS_PHY_PHY_AUX_CLK_SRC] = &gcc_ufs_phy_phy_aux_clk_src.clkr,
+ [GCC_UFS_PHY_PHY_AUX_HW_CTL_CLK] = &gcc_ufs_phy_phy_aux_hw_ctl_clk.clkr,
+ [GCC_UFS_PHY_RX_SYMBOL_0_CLK] = &gcc_ufs_phy_rx_symbol_0_clk.clkr,
+ [GCC_UFS_PHY_RX_SYMBOL_0_CLK_SRC] = &gcc_ufs_phy_rx_symbol_0_clk_src.clkr,
+ [GCC_UFS_PHY_RX_SYMBOL_1_CLK] = &gcc_ufs_phy_rx_symbol_1_clk.clkr,
+ [GCC_UFS_PHY_RX_SYMBOL_1_CLK_SRC] = &gcc_ufs_phy_rx_symbol_1_clk_src.clkr,
+ [GCC_UFS_PHY_TX_SYMBOL_0_CLK] = &gcc_ufs_phy_tx_symbol_0_clk.clkr,
+ [GCC_UFS_PHY_TX_SYMBOL_0_CLK_SRC] = &gcc_ufs_phy_tx_symbol_0_clk_src.clkr,
+ [GCC_UFS_PHY_UNIPRO_CORE_CLK] = &gcc_ufs_phy_unipro_core_clk.clkr,
+ [GCC_UFS_PHY_UNIPRO_CORE_CLK_SRC] = &gcc_ufs_phy_unipro_core_clk_src.clkr,
+ [GCC_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK] = &gcc_ufs_phy_unipro_core_hw_ctl_clk.clkr,
+ [GCC_USB30_PRIM_MASTER_CLK] = &gcc_usb30_prim_master_clk.clkr,
+ [GCC_USB30_PRIM_MASTER_CLK_SRC] = &gcc_usb30_prim_master_clk_src.clkr,
+ [GCC_USB30_PRIM_MOCK_UTMI_CLK] = &gcc_usb30_prim_mock_utmi_clk.clkr,
+ [GCC_USB30_PRIM_MOCK_UTMI_CLK_SRC] = &gcc_usb30_prim_mock_utmi_clk_src.clkr,
+ [GCC_USB30_PRIM_MOCK_UTMI_POSTDIV_CLK_SRC] = &gcc_usb30_prim_mock_utmi_postdiv_clk_src.clkr,
+ [GCC_USB30_PRIM_SLEEP_CLK] = &gcc_usb30_prim_sleep_clk.clkr,
+ [GCC_USB3_PRIM_PHY_AUX_CLK] = &gcc_usb3_prim_phy_aux_clk.clkr,
+ [GCC_USB3_PRIM_PHY_AUX_CLK_SRC] = &gcc_usb3_prim_phy_aux_clk_src.clkr,
+ [GCC_USB3_PRIM_PHY_COM_AUX_CLK] = &gcc_usb3_prim_phy_com_aux_clk.clkr,
+ [GCC_USB3_PRIM_PHY_PIPE_CLK] = &gcc_usb3_prim_phy_pipe_clk.clkr,
+ [GCC_USB3_PRIM_PHY_PIPE_CLK_SRC] = &gcc_usb3_prim_phy_pipe_clk_src.clkr,
+ [GCC_VIDEO_AXI0_CLK] = &gcc_video_axi0_clk.clkr,
+ [GCC_VIDEO_AXI1_CLK] = &gcc_video_axi1_clk.clkr,
+};
+
+static const struct qcom_reset_map gcc_sm8550_resets[] = {
+ [GCC_CAMERA_BCR] = { 0x26000 },
+ [GCC_DISPLAY_BCR] = { 0x27000 },
+ [GCC_GPU_BCR] = { 0x71000 },
+ [GCC_PCIE_0_BCR] = { 0x6b000 },
+ [GCC_PCIE_0_LINK_DOWN_BCR] = { 0x6c014 },
+ [GCC_PCIE_0_NOCSR_COM_PHY_BCR] = { 0x6c020 },
+ [GCC_PCIE_0_PHY_BCR] = { 0x6c01c },
+ [GCC_PCIE_0_PHY_NOCSR_COM_PHY_BCR] = { 0x6c028 },
+ [GCC_PCIE_1_BCR] = { 0x8d000 },
+ [GCC_PCIE_1_LINK_DOWN_BCR] = { 0x8e014 },
+ [GCC_PCIE_1_NOCSR_COM_PHY_BCR] = { 0x8e020 },
+ [GCC_PCIE_1_PHY_BCR] = { 0x8e01c },
+ [GCC_PCIE_1_PHY_NOCSR_COM_PHY_BCR] = { 0x8e024 },
+ [GCC_PCIE_PHY_BCR] = { 0x6f000 },
+ [GCC_PCIE_PHY_CFG_AHB_BCR] = { 0x6f00c },
+ [GCC_PCIE_PHY_COM_BCR] = { 0x6f010 },
+ [GCC_PDM_BCR] = { 0x33000 },
+ [GCC_QUPV3_WRAPPER_1_BCR] = { 0x18000 },
+ [GCC_QUPV3_WRAPPER_2_BCR] = { 0x1e000 },
+ [GCC_QUPV3_WRAPPER_I2C_BCR] = { 0x17000 },
+ [GCC_QUSB2PHY_PRIM_BCR] = { 0x12000 },
+ [GCC_QUSB2PHY_SEC_BCR] = { 0x12004 },
+ [GCC_SDCC2_BCR] = { 0x14000 },
+ [GCC_SDCC4_BCR] = { 0x16000 },
+ [GCC_UFS_PHY_BCR] = { 0x77000 },
+ [GCC_USB30_PRIM_BCR] = { 0x39000 },
+ [GCC_USB3_DP_PHY_PRIM_BCR] = { 0x50008 },
+ [GCC_USB3_DP_PHY_SEC_BCR] = { 0x50014 },
+ [GCC_USB3_PHY_PRIM_BCR] = { 0x50000 },
+ [GCC_USB3_PHY_SEC_BCR] = { 0x5000c },
+ [GCC_USB3PHY_PHY_PRIM_BCR] = { 0x50004 },
+ [GCC_USB3PHY_PHY_SEC_BCR] = { 0x50010 },
+ [GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 },
+ [GCC_VIDEO_AXI0_CLK_ARES] = { 0x32018, 2 },
+ [GCC_VIDEO_AXI1_CLK_ARES] = { 0x32024, 2 },
+ [GCC_VIDEO_BCR] = { 0x32000 },
+};
+
+static const struct clk_rcg_dfs_data gcc_dfs_clocks[] = {
+ DEFINE_RCG_DFS(gcc_qupv3_wrap1_s0_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap1_s1_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap1_s2_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap1_s3_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap1_s4_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap1_s5_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap1_s6_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap1_s7_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap2_s0_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap2_s1_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap2_s2_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap2_s3_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap2_s4_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap2_s5_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap2_s6_clk_src),
+ DEFINE_RCG_DFS(gcc_qupv3_wrap2_s7_clk_src),
+};
+
+static struct gdsc *gcc_sm8550_gdscs[] = {
+ [PCIE_0_GDSC] = &pcie_0_gdsc,
+ [PCIE_0_PHY_GDSC] = &pcie_0_phy_gdsc,
+ [PCIE_1_GDSC] = &pcie_1_gdsc,
+ [PCIE_1_PHY_GDSC] = &pcie_1_phy_gdsc,
+ [UFS_PHY_GDSC] = &ufs_phy_gdsc,
+ [UFS_MEM_PHY_GDSC] = &ufs_mem_phy_gdsc,
+ [USB30_PRIM_GDSC] = &usb30_prim_gdsc,
+ [USB3_PHY_GDSC] = &usb3_phy_gdsc,
+};
+
+static const struct regmap_config gcc_sm8550_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x1f41f0,
+ .fast_io = true,
+};
+
+static const struct qcom_cc_desc gcc_sm8550_desc = {
+ .config = &gcc_sm8550_regmap_config,
+ .clks = gcc_sm8550_clocks,
+ .num_clks = ARRAY_SIZE(gcc_sm8550_clocks),
+ .resets = gcc_sm8550_resets,
+ .num_resets = ARRAY_SIZE(gcc_sm8550_resets),
+ .gdscs = gcc_sm8550_gdscs,
+ .num_gdscs = ARRAY_SIZE(gcc_sm8550_gdscs),
+};
+
+static const struct of_device_id gcc_sm8550_match_table[] = {
+ { .compatible = "qcom,sm8550-gcc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, gcc_sm8550_match_table);
+
+static int gcc_sm8550_probe(struct platform_device *pdev)
+{
+ struct regmap *regmap;
+ int ret;
+
+ regmap = qcom_cc_map(pdev, &gcc_sm8550_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;
+
+ /* FORCE_MEM_CORE_ON for ufs phy ice core clocks */
+ regmap_update_bits(regmap, gcc_ufs_phy_ice_core_clk.halt_reg, BIT(14), BIT(14));
+
+ /*
+ * Keep the critical clock always-On
+ * gcc_camera_ahb_clk, gcc_camera_xo_clk, gcc_disp_ahb_clk,
+ * gcc_disp_xo_clk, gcc_gpu_cfg_ahb_clk, gcc_video_ahb_clk,
+ * gcc_video_xo_clk
+ */
+ regmap_update_bits(regmap, 0x26004, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x26028, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x27004, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x27018, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x71004, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x32004, BIT(0), BIT(0));
+ regmap_update_bits(regmap, 0x32030, BIT(0), BIT(0));
+
+ /* Clear GDSC_SLEEP_ENA_VOTE to stop votes being auto-removed in sleep. */
+ regmap_write(regmap, 0x52024, 0x0);
+
+ return qcom_cc_really_probe(pdev, &gcc_sm8550_desc, regmap);
+}
+
+static struct platform_driver gcc_sm8550_driver = {
+ .probe = gcc_sm8550_probe,
+ .driver = {
+ .name = "gcc-sm8550",
+ .of_match_table = gcc_sm8550_match_table,
+ },
+};
+
+static int __init gcc_sm8550_init(void)
+{
+ return platform_driver_register(&gcc_sm8550_driver);
+}
+subsys_initcall(gcc_sm8550_init);
+
+static void __exit gcc_sm8550_exit(void)
+{
+ platform_driver_unregister(&gcc_sm8550_driver);
+}
+module_exit(gcc_sm8550_exit);
+
+MODULE_DESCRIPTION("QTI GCC SM8550 Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c
index 0f21a8a767ac..9e4d6ce891aa 100644
--- a/drivers/clk/qcom/gdsc.c
+++ b/drivers/clk/qcom/gdsc.c
@@ -46,6 +46,7 @@
#define RETAIN_MEM BIT(14)
#define RETAIN_PERIPH BIT(13)
+#define STATUS_POLL_TIMEOUT_US 1500
#define TIMEOUT_US 500
#define domain_to_gdsc(domain) container_of(domain, struct gdsc, pd)
@@ -107,7 +108,7 @@ static int gdsc_poll_status(struct gdsc *sc, enum gdsc_status status)
do {
if (gdsc_check_status(sc, status))
return 0;
- } while (ktime_us_delta(ktime_get(), start) < TIMEOUT_US);
+ } while (ktime_us_delta(ktime_get(), start) < STATUS_POLL_TIMEOUT_US);
if (gdsc_check_status(sc, status))
return 0;
diff --git a/drivers/clk/qcom/hfpll.c b/drivers/clk/qcom/hfpll.c
index 5ff7f5a60620..f4d78003d189 100644
--- a/drivers/clk/qcom/hfpll.c
+++ b/drivers/clk/qcom/hfpll.c
@@ -47,7 +47,6 @@ static const struct regmap_config hfpll_regmap_config = {
static int qcom_hfpll_probe(struct platform_device *pdev)
{
- struct resource *res;
struct device *dev = &pdev->dev;
void __iomem *base;
struct regmap *regmap;
@@ -70,8 +69,7 @@ static int qcom_hfpll_probe(struct platform_device *pdev)
if (!h)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(dev, res);
+ base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(base))
return PTR_ERR(base);
diff --git a/drivers/clk/qcom/kpss-xcc.c b/drivers/clk/qcom/kpss-xcc.c
index b1b370274ec4..97358c98c6c9 100644
--- a/drivers/clk/qcom/kpss-xcc.c
+++ b/drivers/clk/qcom/kpss-xcc.c
@@ -31,12 +31,13 @@ MODULE_DEVICE_TABLE(of, kpss_xcc_match_table);
static int kpss_xcc_driver_probe(struct platform_device *pdev)
{
+ struct device *dev = &pdev->dev;
const struct of_device_id *id;
void __iomem *base;
struct clk_hw *hw;
const char *name;
- id = of_match_device(kpss_xcc_match_table, &pdev->dev);
+ id = of_match_device(kpss_xcc_match_table, dev);
if (!id)
return -ENODEV;
@@ -45,7 +46,7 @@ static int kpss_xcc_driver_probe(struct platform_device *pdev)
return PTR_ERR(base);
if (id->data) {
- if (of_property_read_string_index(pdev->dev.of_node,
+ if (of_property_read_string_index(dev->of_node,
"clock-output-names",
0, &name))
return -ENODEV;
@@ -55,12 +56,16 @@ static int kpss_xcc_driver_probe(struct platform_device *pdev)
base += 0x28;
}
- hw = devm_clk_hw_register_mux_parent_data_table(&pdev->dev, name, aux_parents,
+ hw = devm_clk_hw_register_mux_parent_data_table(dev, name, aux_parents,
ARRAY_SIZE(aux_parents), 0,
base, 0, 0x3,
0, aux_parent_map, NULL);
+ if (IS_ERR(hw))
+ return PTR_ERR(hw);
- return PTR_ERR_OR_ZERO(hw);
+ of_clk_add_hw_provider(dev->of_node, of_clk_hw_simple_get, hw);
+
+ return 0;
}
static struct platform_driver kpss_xcc_driver = {
diff --git a/drivers/clk/qcom/krait-cc.c b/drivers/clk/qcom/krait-cc.c
index cfd961d5cc45..2f9287c263ec 100644
--- a/drivers/clk/qcom/krait-cc.c
+++ b/drivers/clk/qcom/krait-cc.c
@@ -15,6 +15,16 @@
#include "clk-krait.h"
+enum {
+ cpu0_mux = 0,
+ cpu1_mux,
+ cpu2_mux,
+ cpu3_mux,
+ l2_mux,
+
+ clks_max,
+};
+
static unsigned int sec_mux_map[] = {
2,
0,
@@ -62,28 +72,30 @@ static int krait_notifier_register(struct device *dev, struct clk *clk,
int ret = 0;
mux->clk_nb.notifier_call = krait_notifier_cb;
- ret = clk_notifier_register(clk, &mux->clk_nb);
+ ret = devm_clk_notifier_register(dev, clk, &mux->clk_nb);
if (ret)
dev_err(dev, "failed to register clock notifier: %d\n", ret);
return ret;
}
-static int
+static struct clk_hw *
krait_add_div(struct device *dev, int id, const char *s, unsigned int offset)
{
struct krait_div2_clk *div;
+ static struct clk_parent_data p_data[1];
struct clk_init_data init = {
- .num_parents = 1,
+ .num_parents = ARRAY_SIZE(p_data),
.ops = &krait_div2_clk_ops,
.flags = CLK_SET_RATE_PARENT,
};
- const char *p_names[1];
- struct clk *clk;
+ struct clk_hw *clk;
+ char *parent_name;
+ int cpu, ret;
div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
if (!div)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
div->width = 2;
div->shift = 6;
@@ -93,43 +105,63 @@ krait_add_div(struct device *dev, int id, const char *s, unsigned int offset)
init.name = kasprintf(GFP_KERNEL, "hfpll%s_div", s);
if (!init.name)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
- init.parent_names = p_names;
- p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s);
- if (!p_names[0]) {
- kfree(init.name);
- return -ENOMEM;
+ init.parent_data = p_data;
+ parent_name = kasprintf(GFP_KERNEL, "hfpll%s", s);
+ if (!parent_name) {
+ clk = ERR_PTR(-ENOMEM);
+ goto err_parent_name;
+ }
+
+ p_data[0].fw_name = parent_name;
+ p_data[0].name = parent_name;
+
+ ret = devm_clk_hw_register(dev, &div->hw);
+ if (ret) {
+ clk = ERR_PTR(ret);
+ goto err_clk;
}
- clk = devm_clk_register(dev, &div->hw);
- kfree(p_names[0]);
+ clk = &div->hw;
+
+ /* clk-krait ignore any rate change if mux is not flagged as enabled */
+ if (id < 0)
+ for_each_online_cpu(cpu)
+ clk_prepare_enable(div->hw.clk);
+ else
+ clk_prepare_enable(div->hw.clk);
+
+err_clk:
+ kfree(parent_name);
+err_parent_name:
kfree(init.name);
- return PTR_ERR_OR_ZERO(clk);
+ return clk;
}
-static int
+static struct clk_hw *
krait_add_sec_mux(struct device *dev, int id, const char *s,
unsigned int offset, bool unique_aux)
{
- int ret;
+ int cpu, ret;
struct krait_mux_clk *mux;
- static const char *sec_mux_list[] = {
- "acpu_aux",
- "qsb",
+ static struct clk_parent_data sec_mux_list[2] = {
+ { .name = "qsb", .fw_name = "qsb" },
+ {},
};
struct clk_init_data init = {
- .parent_names = sec_mux_list,
+ .parent_data = sec_mux_list,
.num_parents = ARRAY_SIZE(sec_mux_list),
.ops = &krait_mux_clk_ops,
.flags = CLK_SET_RATE_PARENT,
};
- struct clk *clk;
+ struct clk_hw *clk;
+ char *parent_name;
mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
if (!mux)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
mux->offset = offset;
mux->lpl = id >= 0;
@@ -149,44 +181,64 @@ krait_add_sec_mux(struct device *dev, int id, const char *s,
init.name = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s);
if (!init.name)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
if (unique_aux) {
- sec_mux_list[0] = kasprintf(GFP_KERNEL, "acpu%s_aux", s);
- if (!sec_mux_list[0]) {
+ parent_name = kasprintf(GFP_KERNEL, "acpu%s_aux", s);
+ if (!parent_name) {
clk = ERR_PTR(-ENOMEM);
goto err_aux;
}
+ sec_mux_list[1].fw_name = parent_name;
+ sec_mux_list[1].name = parent_name;
+ } else {
+ sec_mux_list[1].name = "apu_aux";
}
- clk = devm_clk_register(dev, &mux->hw);
+ ret = devm_clk_hw_register(dev, &mux->hw);
+ if (ret) {
+ clk = ERR_PTR(ret);
+ goto err_clk;
+ }
- ret = krait_notifier_register(dev, clk, mux);
- if (ret)
- goto unique_aux;
+ clk = &mux->hw;
+
+ ret = krait_notifier_register(dev, mux->hw.clk, mux);
+ if (ret) {
+ clk = ERR_PTR(ret);
+ goto err_clk;
+ }
-unique_aux:
+ /* clk-krait ignore any rate change if mux is not flagged as enabled */
+ if (id < 0)
+ for_each_online_cpu(cpu)
+ clk_prepare_enable(mux->hw.clk);
+ else
+ clk_prepare_enable(mux->hw.clk);
+
+err_clk:
if (unique_aux)
- kfree(sec_mux_list[0]);
+ kfree(parent_name);
err_aux:
kfree(init.name);
- return PTR_ERR_OR_ZERO(clk);
+ return clk;
}
-static struct clk *
-krait_add_pri_mux(struct device *dev, int id, const char *s,
- unsigned int offset)
+static struct clk_hw *
+krait_add_pri_mux(struct device *dev, struct clk_hw *hfpll_div, struct clk_hw *sec_mux,
+ int id, const char *s, unsigned int offset)
{
int ret;
struct krait_mux_clk *mux;
- const char *p_names[3];
+ static struct clk_parent_data p_data[3];
struct clk_init_data init = {
- .parent_names = p_names,
- .num_parents = ARRAY_SIZE(p_names),
+ .parent_data = p_data,
+ .num_parents = ARRAY_SIZE(p_data),
.ops = &krait_mux_clk_ops,
.flags = CLK_SET_RATE_PARENT,
};
- struct clk *clk;
+ struct clk_hw *clk;
+ char *hfpll_name;
mux = devm_kzalloc(dev, sizeof(*mux), GFP_KERNEL);
if (!mux)
@@ -204,48 +256,44 @@ krait_add_pri_mux(struct device *dev, int id, const char *s,
if (!init.name)
return ERR_PTR(-ENOMEM);
- p_names[0] = kasprintf(GFP_KERNEL, "hfpll%s", s);
- if (!p_names[0]) {
+ hfpll_name = kasprintf(GFP_KERNEL, "hfpll%s", s);
+ if (!hfpll_name) {
clk = ERR_PTR(-ENOMEM);
- goto err_p0;
+ goto err_hfpll;
}
- p_names[1] = kasprintf(GFP_KERNEL, "hfpll%s_div", s);
- if (!p_names[1]) {
- clk = ERR_PTR(-ENOMEM);
- goto err_p1;
- }
+ p_data[0].fw_name = hfpll_name;
+ p_data[0].name = hfpll_name;
- p_names[2] = kasprintf(GFP_KERNEL, "krait%s_sec_mux", s);
- if (!p_names[2]) {
- clk = ERR_PTR(-ENOMEM);
- goto err_p2;
+ p_data[1].hw = hfpll_div;
+ p_data[2].hw = sec_mux;
+
+ ret = devm_clk_hw_register(dev, &mux->hw);
+ if (ret) {
+ clk = ERR_PTR(ret);
+ goto err_clk;
}
- clk = devm_clk_register(dev, &mux->hw);
+ clk = &mux->hw;
- ret = krait_notifier_register(dev, clk, mux);
+ ret = krait_notifier_register(dev, mux->hw.clk, mux);
if (ret)
- goto err_p3;
-err_p3:
- kfree(p_names[2]);
-err_p2:
- kfree(p_names[1]);
-err_p1:
- kfree(p_names[0]);
-err_p0:
+ clk = ERR_PTR(ret);
+
+err_clk:
+ kfree(hfpll_name);
+err_hfpll:
kfree(init.name);
return clk;
}
/* id < 0 for L2, otherwise id == physical CPU number */
-static struct clk *krait_add_clks(struct device *dev, int id, bool unique_aux)
+static struct clk_hw *krait_add_clks(struct device *dev, int id, bool unique_aux)
{
- int ret;
+ struct clk_hw *hfpll_div, *sec_mux, *pri_mux;
unsigned int offset;
void *p = NULL;
const char *s;
- struct clk *clk;
if (id >= 0) {
offset = 0x4501 + (0x1000 * id);
@@ -257,22 +305,23 @@ static struct clk *krait_add_clks(struct device *dev, int id, bool unique_aux)
s = "_l2";
}
- ret = krait_add_div(dev, id, s, offset);
- if (ret) {
- clk = ERR_PTR(ret);
+ hfpll_div = krait_add_div(dev, id, s, offset);
+ if (IS_ERR(hfpll_div)) {
+ pri_mux = hfpll_div;
goto err;
}
- ret = krait_add_sec_mux(dev, id, s, offset, unique_aux);
- if (ret) {
- clk = ERR_PTR(ret);
+ sec_mux = krait_add_sec_mux(dev, id, s, offset, unique_aux);
+ if (IS_ERR(sec_mux)) {
+ pri_mux = sec_mux;
goto err;
}
- clk = krait_add_pri_mux(dev, id, s, offset);
+ pri_mux = krait_add_pri_mux(dev, hfpll_div, sec_mux, id, s, offset);
+
err:
kfree(p);
- return clk;
+ return pri_mux;
}
static struct clk *krait_of_get(struct of_phandle_args *clkspec, void *data)
@@ -280,7 +329,7 @@ static struct clk *krait_of_get(struct of_phandle_args *clkspec, void *data)
unsigned int idx = clkspec->args[0];
struct clk **clks = data;
- if (idx >= 5) {
+ if (idx >= clks_max) {
pr_err("%s: invalid clock index %d\n", __func__, idx);
return ERR_PTR(-EINVAL);
}
@@ -301,9 +350,8 @@ static int krait_cc_probe(struct platform_device *pdev)
const struct of_device_id *id;
unsigned long cur_rate, aux_rate;
int cpu;
- struct clk *clk;
- struct clk **clks;
- struct clk *l2_pri_mux_clk;
+ struct clk_hw *mux, *l2_pri_mux;
+ struct clk *clk, **clks;
id = of_match_device(krait_cc_match_table, dev);
if (!id)
@@ -322,21 +370,21 @@ static int krait_cc_probe(struct platform_device *pdev)
}
/* Krait configurations have at most 4 CPUs and one L2 */
- clks = devm_kcalloc(dev, 5, sizeof(*clks), GFP_KERNEL);
+ clks = devm_kcalloc(dev, clks_max, sizeof(*clks), GFP_KERNEL);
if (!clks)
return -ENOMEM;
for_each_possible_cpu(cpu) {
- clk = krait_add_clks(dev, cpu, id->data);
+ mux = krait_add_clks(dev, cpu, id->data);
if (IS_ERR(clk))
return PTR_ERR(clk);
- clks[cpu] = clk;
+ clks[cpu] = mux->clk;
}
- l2_pri_mux_clk = krait_add_clks(dev, -1, id->data);
- if (IS_ERR(l2_pri_mux_clk))
- return PTR_ERR(l2_pri_mux_clk);
- clks[4] = l2_pri_mux_clk;
+ l2_pri_mux = krait_add_clks(dev, -1, id->data);
+ if (IS_ERR(l2_pri_mux))
+ return PTR_ERR(l2_pri_mux);
+ clks[l2_mux] = l2_pri_mux->clk;
/*
* We don't want the CPU or L2 clocks to be turned off at late init
@@ -346,7 +394,7 @@ static int krait_cc_probe(struct platform_device *pdev)
* they take over.
*/
for_each_online_cpu(cpu) {
- clk_prepare_enable(l2_pri_mux_clk);
+ clk_prepare_enable(clks[l2_mux]);
WARN(clk_prepare_enable(clks[cpu]),
"Unable to turn on CPU%d clock", cpu);
}
@@ -362,21 +410,21 @@ static int krait_cc_probe(struct platform_device *pdev)
* two different rates to force a HFPLL reinit under all
* circumstances.
*/
- cur_rate = clk_get_rate(l2_pri_mux_clk);
+ cur_rate = clk_get_rate(clks[l2_mux]);
aux_rate = 384000000;
- if (cur_rate == 1) {
- pr_info("L2 @ QSB rate. Forcing new rate.\n");
+ if (cur_rate < aux_rate) {
+ pr_info("L2 @ Undefined rate. Forcing new rate.\n");
cur_rate = aux_rate;
}
- clk_set_rate(l2_pri_mux_clk, aux_rate);
- clk_set_rate(l2_pri_mux_clk, 2);
- clk_set_rate(l2_pri_mux_clk, cur_rate);
- pr_info("L2 @ %lu KHz\n", clk_get_rate(l2_pri_mux_clk) / 1000);
+ clk_set_rate(clks[l2_mux], aux_rate);
+ clk_set_rate(clks[l2_mux], 2);
+ clk_set_rate(clks[l2_mux], cur_rate);
+ pr_info("L2 @ %lu KHz\n", clk_get_rate(clks[l2_mux]) / 1000);
for_each_possible_cpu(cpu) {
clk = clks[cpu];
cur_rate = clk_get_rate(clk);
- if (cur_rate == 1) {
- pr_info("CPU%d @ QSB rate. Forcing new rate.\n", cpu);
+ if (cur_rate < aux_rate) {
+ pr_info("CPU%d @ Undefined rate. Forcing new rate.\n", cpu);
cur_rate = aux_rate;
}
diff --git a/drivers/clk/qcom/lpassaudiocc-sc7280.c b/drivers/clk/qcom/lpassaudiocc-sc7280.c
index 063e0365f311..1339f9211a14 100644
--- a/drivers/clk/qcom/lpassaudiocc-sc7280.c
+++ b/drivers/clk/qcom/lpassaudiocc-sc7280.c
@@ -722,33 +722,17 @@ static const struct of_device_id lpass_audio_cc_sc7280_match_table[] = {
};
MODULE_DEVICE_TABLE(of, lpass_audio_cc_sc7280_match_table);
-static void lpassaudio_pm_runtime_disable(void *data)
-{
- pm_runtime_disable(data);
-}
-
-static void lpassaudio_pm_clk_destroy(void *data)
-{
- pm_clk_destroy(data);
-}
-
-static int lpassaudio_create_pm_clks(struct platform_device *pdev)
+static int lpass_audio_setup_runtime_pm(struct platform_device *pdev)
{
int ret;
pm_runtime_use_autosuspend(&pdev->dev);
pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
- pm_runtime_enable(&pdev->dev);
-
- ret = devm_add_action_or_reset(&pdev->dev, lpassaudio_pm_runtime_disable, &pdev->dev);
- if (ret)
- return ret;
-
- ret = pm_clk_create(&pdev->dev);
+ ret = devm_pm_runtime_enable(&pdev->dev);
if (ret)
return ret;
- ret = devm_add_action_or_reset(&pdev->dev, lpassaudio_pm_clk_destroy, &pdev->dev);
+ ret = devm_pm_clk_create(&pdev->dev);
if (ret)
return ret;
@@ -756,7 +740,7 @@ static int lpassaudio_create_pm_clks(struct platform_device *pdev)
if (ret < 0)
dev_err(&pdev->dev, "failed to acquire iface clock\n");
- return ret;
+ return pm_runtime_resume_and_get(&pdev->dev);
}
static int lpass_audio_cc_sc7280_probe(struct platform_device *pdev)
@@ -765,7 +749,7 @@ static int lpass_audio_cc_sc7280_probe(struct platform_device *pdev)
struct regmap *regmap;
int ret;
- ret = lpassaudio_create_pm_clks(pdev);
+ ret = lpass_audio_setup_runtime_pm(pdev);
if (ret)
return ret;
@@ -775,8 +759,8 @@ static int lpass_audio_cc_sc7280_probe(struct platform_device *pdev)
regmap = qcom_cc_map(pdev, desc);
if (IS_ERR(regmap)) {
- pm_runtime_disable(&pdev->dev);
- return PTR_ERR(regmap);
+ ret = PTR_ERR(regmap);
+ goto exit;
}
clk_zonda_pll_configure(&lpass_audio_cc_pll, regmap, &lpass_audio_cc_pll_config);
@@ -788,20 +772,18 @@ static int lpass_audio_cc_sc7280_probe(struct platform_device *pdev)
ret = qcom_cc_really_probe(pdev, &lpass_audio_cc_sc7280_desc, regmap);
if (ret) {
dev_err(&pdev->dev, "Failed to register LPASS AUDIO CC clocks\n");
- pm_runtime_disable(&pdev->dev);
- return ret;
+ goto exit;
}
ret = qcom_cc_probe_by_index(pdev, 1, &lpass_audio_cc_reset_sc7280_desc);
if (ret) {
dev_err(&pdev->dev, "Failed to register LPASS AUDIO CC Resets\n");
- pm_runtime_disable(&pdev->dev);
- return ret;
+ goto exit;
}
pm_runtime_mark_last_busy(&pdev->dev);
+exit:
pm_runtime_put_autosuspend(&pdev->dev);
- pm_runtime_put_sync(&pdev->dev);
return ret;
}
@@ -839,14 +821,15 @@ static int lpass_aon_cc_sc7280_probe(struct platform_device *pdev)
struct regmap *regmap;
int ret;
- ret = lpassaudio_create_pm_clks(pdev);
+ ret = lpass_audio_setup_runtime_pm(pdev);
if (ret)
return ret;
if (of_property_read_bool(pdev->dev.of_node, "qcom,adsp-pil-mode")) {
lpass_audio_cc_sc7280_regmap_config.name = "cc";
desc = &lpass_cc_sc7280_desc;
- return qcom_cc_probe(pdev, desc);
+ ret = qcom_cc_probe(pdev, desc);
+ goto exit;
}
lpass_audio_cc_sc7280_regmap_config.name = "lpasscc_aon";
@@ -854,18 +837,22 @@ static int lpass_aon_cc_sc7280_probe(struct platform_device *pdev)
desc = &lpass_aon_cc_sc7280_desc;
regmap = qcom_cc_map(pdev, desc);
- if (IS_ERR(regmap))
- return PTR_ERR(regmap);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ goto exit;
+ }
clk_lucid_pll_configure(&lpass_aon_cc_pll, regmap, &lpass_aon_cc_pll_config);
ret = qcom_cc_really_probe(pdev, &lpass_aon_cc_sc7280_desc, regmap);
- if (ret)
+ if (ret) {
dev_err(&pdev->dev, "Failed to register LPASS AON CC clocks\n");
+ goto exit;
+ }
pm_runtime_mark_last_busy(&pdev->dev);
+exit:
pm_runtime_put_autosuspend(&pdev->dev);
- pm_runtime_put_sync(&pdev->dev);
return ret;
}
diff --git a/drivers/clk/qcom/lpasscorecc-sc7180.c b/drivers/clk/qcom/lpasscorecc-sc7180.c
index ac09b7b840ab..33ed91c67e1c 100644
--- a/drivers/clk/qcom/lpasscorecc-sc7180.c
+++ b/drivers/clk/qcom/lpasscorecc-sc7180.c
@@ -356,7 +356,7 @@ static const struct qcom_cc_desc lpass_audio_hm_sc7180_desc = {
.num_gdscs = ARRAY_SIZE(lpass_audio_hm_sc7180_gdscs),
};
-static int lpass_create_pm_clks(struct platform_device *pdev)
+static int lpass_setup_runtime_pm(struct platform_device *pdev)
{
int ret;
@@ -375,7 +375,7 @@ static int lpass_create_pm_clks(struct platform_device *pdev)
if (ret < 0)
dev_err(&pdev->dev, "failed to acquire iface clock\n");
- return ret;
+ return pm_runtime_resume_and_get(&pdev->dev);
}
static int lpass_core_cc_sc7180_probe(struct platform_device *pdev)
@@ -384,7 +384,7 @@ static int lpass_core_cc_sc7180_probe(struct platform_device *pdev)
struct regmap *regmap;
int ret;
- ret = lpass_create_pm_clks(pdev);
+ ret = lpass_setup_runtime_pm(pdev);
if (ret)
return ret;
@@ -392,12 +392,14 @@ static int lpass_core_cc_sc7180_probe(struct platform_device *pdev)
desc = &lpass_audio_hm_sc7180_desc;
ret = qcom_cc_probe_by_index(pdev, 1, desc);
if (ret)
- return ret;
+ goto exit;
lpass_core_cc_sc7180_regmap_config.name = "lpass_core_cc";
regmap = qcom_cc_map(pdev, &lpass_core_cc_sc7180_desc);
- if (IS_ERR(regmap))
- return PTR_ERR(regmap);
+ if (IS_ERR(regmap)) {
+ ret = PTR_ERR(regmap);
+ goto exit;
+ }
/*
* Keep the CLK always-ON
@@ -415,6 +417,7 @@ static int lpass_core_cc_sc7180_probe(struct platform_device *pdev)
ret = qcom_cc_really_probe(pdev, &lpass_core_cc_sc7180_desc, regmap);
pm_runtime_mark_last_busy(&pdev->dev);
+exit:
pm_runtime_put_autosuspend(&pdev->dev);
return ret;
@@ -425,14 +428,19 @@ static int lpass_hm_core_probe(struct platform_device *pdev)
const struct qcom_cc_desc *desc;
int ret;
- ret = lpass_create_pm_clks(pdev);
+ ret = lpass_setup_runtime_pm(pdev);
if (ret)
return ret;
lpass_core_cc_sc7180_regmap_config.name = "lpass_hm_core";
desc = &lpass_core_hm_sc7180_desc;
- return qcom_cc_probe_by_index(pdev, 0, desc);
+ ret = qcom_cc_probe_by_index(pdev, 0, desc);
+
+ pm_runtime_mark_last_busy(&pdev->dev);
+ pm_runtime_put_autosuspend(&pdev->dev);
+
+ return ret;
}
static const struct of_device_id lpass_hm_sc7180_match_table[] = {
@@ -451,7 +459,7 @@ static const struct of_device_id lpass_core_cc_sc7180_match_table[] = {
};
MODULE_DEVICE_TABLE(of, lpass_core_cc_sc7180_match_table);
-static const struct dev_pm_ops lpass_core_cc_pm_ops = {
+static const struct dev_pm_ops lpass_pm_ops = {
SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
};
@@ -460,20 +468,16 @@ static struct platform_driver lpass_core_cc_sc7180_driver = {
.driver = {
.name = "lpass_core_cc-sc7180",
.of_match_table = lpass_core_cc_sc7180_match_table,
- .pm = &lpass_core_cc_pm_ops,
+ .pm = &lpass_pm_ops,
},
};
-static const struct dev_pm_ops lpass_hm_pm_ops = {
- SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
-};
-
static struct platform_driver lpass_hm_sc7180_driver = {
.probe = lpass_hm_core_probe,
.driver = {
.name = "lpass_hm-sc7180",
.of_match_table = lpass_hm_sc7180_match_table,
- .pm = &lpass_hm_pm_ops,
+ .pm = &lpass_pm_ops,
},
};
diff --git a/drivers/clk/qcom/mmcc-msm8974.c b/drivers/clk/qcom/mmcc-msm8974.c
index f74662925a58..4273fce9a4a4 100644
--- a/drivers/clk/qcom/mmcc-msm8974.c
+++ b/drivers/clk/qcom/mmcc-msm8974.c
@@ -42,124 +42,6 @@ enum {
P_DSI1PLL_BYTE,
};
-static const struct parent_map mmcc_xo_mmpll0_mmpll1_gpll0_map[] = {
- { P_XO, 0 },
- { P_MMPLL0, 1 },
- { P_MMPLL1, 2 },
- { P_GPLL0, 5 }
-};
-
-static const char * const mmcc_xo_mmpll0_mmpll1_gpll0[] = {
- "xo",
- "mmpll0_vote",
- "mmpll1_vote",
- "mmss_gpll0_vote",
-};
-
-static const struct parent_map mmcc_xo_mmpll0_dsi_hdmi_gpll0_map[] = {
- { P_XO, 0 },
- { P_MMPLL0, 1 },
- { P_HDMIPLL, 4 },
- { P_GPLL0, 5 },
- { P_DSI0PLL, 2 },
- { P_DSI1PLL, 3 }
-};
-
-static const char * const mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = {
- "xo",
- "mmpll0_vote",
- "hdmipll",
- "mmss_gpll0_vote",
- "dsi0pll",
- "dsi1pll",
-};
-
-static const struct parent_map mmcc_xo_mmpll0_1_3_gpll0_map[] = {
- { P_XO, 0 },
- { P_MMPLL0, 1 },
- { P_MMPLL1, 2 },
- { P_GPLL0, 5 },
- { P_MMPLL3, 3 }
-};
-
-static const char * const mmcc_xo_mmpll0_1_3_gpll0[] = {
- "xo",
- "mmpll0_vote",
- "mmpll1_vote",
- "mmss_gpll0_vote",
- "mmpll3",
-};
-
-static const struct parent_map mmcc_xo_mmpll0_1_gpll1_0_map[] = {
- { P_XO, 0 },
- { P_MMPLL0, 1 },
- { P_MMPLL1, 2 },
- { P_GPLL0, 5 },
- { P_GPLL1, 4 }
-};
-
-static const char * const mmcc_xo_mmpll0_1_gpll1_0[] = {
- "xo",
- "mmpll0_vote",
- "mmpll1_vote",
- "mmss_gpll0_vote",
- "gpll1_vote",
-};
-
-static const struct parent_map mmcc_xo_dsi_hdmi_edp_map[] = {
- { P_XO, 0 },
- { P_EDPLINK, 4 },
- { P_HDMIPLL, 3 },
- { P_EDPVCO, 5 },
- { P_DSI0PLL, 1 },
- { P_DSI1PLL, 2 }
-};
-
-static const char * const mmcc_xo_dsi_hdmi_edp[] = {
- "xo",
- "edp_link_clk",
- "hdmipll",
- "edp_vco_div",
- "dsi0pll",
- "dsi1pll",
-};
-
-static const struct parent_map mmcc_xo_dsi_hdmi_edp_gpll0_map[] = {
- { P_XO, 0 },
- { P_EDPLINK, 4 },
- { P_HDMIPLL, 3 },
- { P_GPLL0, 5 },
- { P_DSI0PLL, 1 },
- { P_DSI1PLL, 2 }
-};
-
-static const char * const mmcc_xo_dsi_hdmi_edp_gpll0[] = {
- "xo",
- "edp_link_clk",
- "hdmipll",
- "gpll0_vote",
- "dsi0pll",
- "dsi1pll",
-};
-
-static const struct parent_map mmcc_xo_dsibyte_hdmi_edp_gpll0_map[] = {
- { P_XO, 0 },
- { P_EDPLINK, 4 },
- { P_HDMIPLL, 3 },
- { P_GPLL0, 5 },
- { P_DSI0PLL_BYTE, 1 },
- { P_DSI1PLL_BYTE, 2 }
-};
-
-static const char * const mmcc_xo_dsibyte_hdmi_edp_gpll0[] = {
- "xo",
- "edp_link_clk",
- "hdmipll",
- "gpll0_vote",
- "dsi0pllbyte",
- "dsi1pllbyte",
-};
-
static struct clk_pll mmpll0 = {
.l_reg = 0x0004,
.m_reg = 0x0008,
@@ -170,7 +52,9 @@ static struct clk_pll mmpll0 = {
.status_bit = 17,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll0",
- .parent_names = (const char *[]){ "xo" },
+ .parent_data = (const struct clk_parent_data[]){
+ { .fw_name = "xo", .name = "xo_board" },
+ },
.num_parents = 1,
.ops = &clk_pll_ops,
},
@@ -181,7 +65,9 @@ static struct clk_regmap mmpll0_vote = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mmpll0_vote",
- .parent_names = (const char *[]){ "mmpll0" },
+ .parent_hws = (const struct clk_hw*[]){
+ &mmpll0.clkr.hw
+ },
.num_parents = 1,
.ops = &clk_pll_vote_ops,
},
@@ -197,7 +83,9 @@ static struct clk_pll mmpll1 = {
.status_bit = 17,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll1",
- .parent_names = (const char *[]){ "xo" },
+ .parent_data = (const struct clk_parent_data[]){
+ { .fw_name = "xo", .name = "xo_board" },
+ },
.num_parents = 1,
.ops = &clk_pll_ops,
},
@@ -208,7 +96,9 @@ static struct clk_regmap mmpll1_vote = {
.enable_mask = BIT(1),
.hw.init = &(struct clk_init_data){
.name = "mmpll1_vote",
- .parent_names = (const char *[]){ "mmpll1" },
+ .parent_hws = (const struct clk_hw*[]){
+ &mmpll1.clkr.hw
+ },
.num_parents = 1,
.ops = &clk_pll_vote_ops,
},
@@ -223,7 +113,9 @@ static struct clk_pll mmpll2 = {
.status_reg = 0x411c,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll2",
- .parent_names = (const char *[]){ "xo" },
+ .parent_data = (const struct clk_parent_data[]){
+ { .fw_name = "xo", .name = "xo_board" },
+ },
.num_parents = 1,
.ops = &clk_pll_ops,
},
@@ -239,20 +131,140 @@ static struct clk_pll mmpll3 = {
.status_bit = 17,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmpll3",
- .parent_names = (const char *[]){ "xo" },
+ .parent_data = (const struct clk_parent_data[]){
+ { .fw_name = "xo", .name = "xo_board" },
+ },
.num_parents = 1,
.ops = &clk_pll_ops,
},
};
+static const struct parent_map mmcc_xo_mmpll0_mmpll1_gpll0_map[] = {
+ { P_XO, 0 },
+ { P_MMPLL0, 1 },
+ { P_MMPLL1, 2 },
+ { P_GPLL0, 5 }
+};
+
+static const struct clk_parent_data mmcc_xo_mmpll0_mmpll1_gpll0[] = {
+ { .fw_name = "xo", .name = "xo_board" },
+ { .hw = &mmpll0_vote.hw },
+ { .hw = &mmpll1_vote.hw },
+ { .fw_name = "mmss_gpll0_vote", .name = "mmss_gpll0_vote" },
+};
+
+static const struct parent_map mmcc_xo_mmpll0_dsi_hdmi_gpll0_map[] = {
+ { P_XO, 0 },
+ { P_MMPLL0, 1 },
+ { P_HDMIPLL, 4 },
+ { P_GPLL0, 5 },
+ { P_DSI0PLL, 2 },
+ { P_DSI1PLL, 3 }
+};
+
+static const struct clk_parent_data mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = {
+ { .fw_name = "xo", .name = "xo_board" },
+ { .hw = &mmpll0_vote.hw },
+ { .fw_name = "hdmipll", .name = "hdmipll" },
+ { .fw_name = "mmss_gpll0_vote", .name = "mmss_gpll0_vote" },
+ { .fw_name = "dsi0pll", .name = "dsi0pll" },
+ { .fw_name = "dsi1pll", .name = "dsi1pll" },
+};
+
+static const struct parent_map mmcc_xo_mmpll0_1_3_gpll0_map[] = {
+ { P_XO, 0 },
+ { P_MMPLL0, 1 },
+ { P_MMPLL1, 2 },
+ { P_GPLL0, 5 },
+ { P_MMPLL3, 3 }
+};
+
+static const struct clk_parent_data mmcc_xo_mmpll0_1_3_gpll0[] = {
+ { .fw_name = "xo", .name = "xo_board" },
+ { .hw = &mmpll0_vote.hw },
+ { .hw = &mmpll1_vote.hw },
+ { .fw_name = "mmss_gpll0_vote", .name = "mmss_gpll0_vote" },
+ { .hw = &mmpll3.clkr.hw },
+};
+
+static const struct parent_map mmcc_xo_mmpll0_1_gpll1_0_map[] = {
+ { P_XO, 0 },
+ { P_MMPLL0, 1 },
+ { P_MMPLL1, 2 },
+ { P_GPLL0, 5 },
+ { P_GPLL1, 4 }
+};
+
+static const struct clk_parent_data mmcc_xo_mmpll0_1_gpll1_0[] = {
+ { .fw_name = "xo", .name = "xo_board" },
+ { .hw = &mmpll0_vote.hw },
+ { .hw = &mmpll1_vote.hw },
+ { .fw_name = "mmss_gpll0_vote", .name = "mmss_gpll0_vote" },
+ { .fw_name = "gpll1_vote", .name = "gpll1_vote" },
+};
+
+static const struct parent_map mmcc_xo_dsi_hdmi_edp_map[] = {
+ { P_XO, 0 },
+ { P_EDPLINK, 4 },
+ { P_HDMIPLL, 3 },
+ { P_EDPVCO, 5 },
+ { P_DSI0PLL, 1 },
+ { P_DSI1PLL, 2 }
+};
+
+static const struct clk_parent_data mmcc_xo_dsi_hdmi_edp[] = {
+ { .fw_name = "xo", .name = "xo_board" },
+ { .fw_name = "edp_link_clk", .name = "edp_link_clk" },
+ { .fw_name = "hdmipll", .name = "hdmipll" },
+ { .fw_name = "edp_vco_div", .name = "edp_vco_div" },
+ { .fw_name = "dsi0pll", .name = "dsi0pll" },
+ { .fw_name = "dsi1pll", .name = "dsi1pll" },
+};
+
+static const struct parent_map mmcc_xo_dsi_hdmi_edp_gpll0_map[] = {
+ { P_XO, 0 },
+ { P_EDPLINK, 4 },
+ { P_HDMIPLL, 3 },
+ { P_GPLL0, 5 },
+ { P_DSI0PLL, 1 },
+ { P_DSI1PLL, 2 }
+};
+
+static const struct clk_parent_data mmcc_xo_dsi_hdmi_edp_gpll0[] = {
+ { .fw_name = "xo", .name = "xo_board" },
+ { .fw_name = "edp_link_clk", .name = "edp_link_clk" },
+ { .fw_name = "hdmipll", .name = "hdmipll" },
+ { .fw_name = "gpll0_vote", .name = "gpll0_vote" },
+ { .fw_name = "dsi0pll", .name = "dsi0pll" },
+ { .fw_name = "dsi1pll", .name = "dsi1pll" },
+};
+
+static const struct parent_map mmcc_xo_dsibyte_hdmi_edp_gpll0_map[] = {
+ { P_XO, 0 },
+ { P_EDPLINK, 4 },
+ { P_HDMIPLL, 3 },
+ { P_GPLL0, 5 },
+ { P_DSI0PLL_BYTE, 1 },
+ { P_DSI1PLL_BYTE, 2 }
+};
+
+static const struct clk_parent_data mmcc_xo_dsibyte_hdmi_edp_gpll0[] = {
+ { .fw_name = "xo", .name = "xo_board" },
+ { .fw_name = "edp_link_clk", .name = "edp_link_clk" },
+ { .fw_name = "hdmipll", .name = "hdmipll" },
+ { .fw_name = "gpll0_vote", .name = "gpll0_vote" },
+ { .fw_name = "dsi0pllbyte", .name = "dsi0pllbyte" },
+ { .fw_name = "dsi1pllbyte", .name = "dsi1pllbyte" },
+};
+
static struct clk_rcg2 mmss_ahb_clk_src = {
.cmd_rcgr = 0x5000,
.hid_width = 5,
.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmss_ahb_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -288,8 +300,8 @@ static struct clk_rcg2 mmss_axi_clk_src = {
.freq_tbl = ftbl_mmss_axi_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "mmss_axi_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -312,8 +324,8 @@ static struct clk_rcg2 ocmemnoc_clk_src = {
.freq_tbl = ftbl_ocmemnoc_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "ocmemnoc_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -331,8 +343,8 @@ static struct clk_rcg2 csi0_clk_src = {
.freq_tbl = ftbl_camss_csi0_3_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "csi0_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -344,8 +356,8 @@ static struct clk_rcg2 csi1_clk_src = {
.freq_tbl = ftbl_camss_csi0_3_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "csi1_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -357,8 +369,8 @@ static struct clk_rcg2 csi2_clk_src = {
.freq_tbl = ftbl_camss_csi0_3_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "csi2_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -370,8 +382,8 @@ static struct clk_rcg2 csi3_clk_src = {
.freq_tbl = ftbl_camss_csi0_3_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "csi3_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -417,8 +429,8 @@ static struct clk_rcg2 vfe0_clk_src = {
.freq_tbl = ftbl_camss_vfe_vfe0_1_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "vfe0_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -430,8 +442,8 @@ static struct clk_rcg2 vfe1_clk_src = {
.freq_tbl = ftbl_camss_vfe_vfe0_1_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "vfe1_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -471,8 +483,8 @@ static struct clk_rcg2 mdp_clk_src = {
.freq_tbl = ftbl_mdss_mdp_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "mdp_clk_src",
- .parent_names = mmcc_xo_mmpll0_dsi_hdmi_gpll0,
- .num_parents = 6,
+ .parent_data = mmcc_xo_mmpll0_dsi_hdmi_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_dsi_hdmi_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -494,8 +506,8 @@ static struct clk_rcg2 jpeg0_clk_src = {
.freq_tbl = ftbl_camss_jpeg_jpeg0_2_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "jpeg0_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -507,8 +519,8 @@ static struct clk_rcg2 jpeg1_clk_src = {
.freq_tbl = ftbl_camss_jpeg_jpeg0_2_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "jpeg1_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -520,8 +532,8 @@ static struct clk_rcg2 jpeg2_clk_src = {
.freq_tbl = ftbl_camss_jpeg_jpeg0_2_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "jpeg2_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -533,8 +545,8 @@ static struct clk_rcg2 pclk0_clk_src = {
.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "pclk0_clk_src",
- .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
- .num_parents = 6,
+ .parent_data = mmcc_xo_dsi_hdmi_edp_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_dsi_hdmi_edp_gpll0),
.ops = &clk_pixel_ops,
.flags = CLK_SET_RATE_PARENT,
},
@@ -547,8 +559,8 @@ static struct clk_rcg2 pclk1_clk_src = {
.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
.clkr.hw.init = &(struct clk_init_data){
.name = "pclk1_clk_src",
- .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
- .num_parents = 6,
+ .parent_data = mmcc_xo_dsi_hdmi_edp_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_dsi_hdmi_edp_gpll0),
.ops = &clk_pixel_ops,
.flags = CLK_SET_RATE_PARENT,
},
@@ -580,8 +592,8 @@ static struct clk_rcg2 vcodec0_clk_src = {
.freq_tbl = ftbl_venus0_vcodec0_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "vcodec0_clk_src",
- .parent_names = mmcc_xo_mmpll0_1_3_gpll0,
- .num_parents = 5,
+ .parent_data = mmcc_xo_mmpll0_1_3_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_1_3_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -598,8 +610,8 @@ static struct clk_rcg2 cci_clk_src = {
.freq_tbl = ftbl_camss_cci_cci_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "cci_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -622,8 +634,8 @@ static struct clk_rcg2 camss_gp0_clk_src = {
.freq_tbl = ftbl_camss_gp0_1_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "camss_gp0_clk_src",
- .parent_names = mmcc_xo_mmpll0_1_gpll1_0,
- .num_parents = 5,
+ .parent_data = mmcc_xo_mmpll0_1_gpll1_0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_1_gpll1_0),
.ops = &clk_rcg2_ops,
},
};
@@ -636,8 +648,8 @@ static struct clk_rcg2 camss_gp1_clk_src = {
.freq_tbl = ftbl_camss_gp0_1_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "camss_gp1_clk_src",
- .parent_names = mmcc_xo_mmpll0_1_gpll1_0,
- .num_parents = 5,
+ .parent_data = mmcc_xo_mmpll0_1_gpll1_0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_1_gpll1_0),
.ops = &clk_rcg2_ops,
},
};
@@ -671,8 +683,8 @@ static struct clk_rcg2 mclk0_clk_src = {
.freq_tbl = ftbl_camss_mclk0_3_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "mclk0_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -684,8 +696,8 @@ static struct clk_rcg2 mclk1_clk_src = {
.freq_tbl = ftbl_camss_mclk0_3_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "mclk1_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -697,8 +709,8 @@ static struct clk_rcg2 mclk2_clk_src = {
.freq_tbl = ftbl_camss_mclk0_3_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "mclk2_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -710,8 +722,8 @@ static struct clk_rcg2 mclk3_clk_src = {
.freq_tbl = ftbl_camss_mclk0_3_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "mclk3_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -729,8 +741,8 @@ static struct clk_rcg2 csi0phytimer_clk_src = {
.freq_tbl = ftbl_camss_phy0_2_csi0_2phytimer_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "csi0phytimer_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -742,8 +754,8 @@ static struct clk_rcg2 csi1phytimer_clk_src = {
.freq_tbl = ftbl_camss_phy0_2_csi0_2phytimer_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "csi1phytimer_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -755,8 +767,8 @@ static struct clk_rcg2 csi2phytimer_clk_src = {
.freq_tbl = ftbl_camss_phy0_2_csi0_2phytimer_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "csi2phytimer_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -786,8 +798,8 @@ static struct clk_rcg2 cpp_clk_src = {
.freq_tbl = ftbl_camss_vfe_cpp_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "cpp_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -804,8 +816,8 @@ static struct clk_rcg2 byte0_clk_src = {
.freq_tbl = byte_freq_tbl,
.clkr.hw.init = &(struct clk_init_data){
.name = "byte0_clk_src",
- .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
- .num_parents = 6,
+ .parent_data = mmcc_xo_dsibyte_hdmi_edp_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_dsibyte_hdmi_edp_gpll0),
.ops = &clk_byte2_ops,
.flags = CLK_SET_RATE_PARENT,
},
@@ -818,8 +830,8 @@ static struct clk_rcg2 byte1_clk_src = {
.freq_tbl = byte_freq_tbl,
.clkr.hw.init = &(struct clk_init_data){
.name = "byte1_clk_src",
- .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
- .num_parents = 6,
+ .parent_data = mmcc_xo_dsibyte_hdmi_edp_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_dsibyte_hdmi_edp_gpll0),
.ops = &clk_byte2_ops,
.flags = CLK_SET_RATE_PARENT,
},
@@ -837,8 +849,8 @@ static struct clk_rcg2 edpaux_clk_src = {
.freq_tbl = ftbl_mdss_edpaux_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "edpaux_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -856,8 +868,8 @@ static struct clk_rcg2 edplink_clk_src = {
.freq_tbl = ftbl_mdss_edplink_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "edplink_clk_src",
- .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
- .num_parents = 6,
+ .parent_data = mmcc_xo_dsi_hdmi_edp_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_dsi_hdmi_edp_gpll0),
.ops = &clk_rcg2_ops,
.flags = CLK_SET_RATE_PARENT,
},
@@ -876,8 +888,8 @@ static struct clk_rcg2 edppixel_clk_src = {
.freq_tbl = edp_pixel_freq_tbl,
.clkr.hw.init = &(struct clk_init_data){
.name = "edppixel_clk_src",
- .parent_names = mmcc_xo_dsi_hdmi_edp,
- .num_parents = 6,
+ .parent_data = mmcc_xo_dsi_hdmi_edp,
+ .num_parents = ARRAY_SIZE(mmcc_xo_dsi_hdmi_edp),
.ops = &clk_edp_pixel_ops,
},
};
@@ -894,8 +906,8 @@ static struct clk_rcg2 esc0_clk_src = {
.freq_tbl = ftbl_mdss_esc0_1_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "esc0_clk_src",
- .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
- .num_parents = 6,
+ .parent_data = mmcc_xo_dsibyte_hdmi_edp_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_dsibyte_hdmi_edp_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -907,8 +919,8 @@ static struct clk_rcg2 esc1_clk_src = {
.freq_tbl = ftbl_mdss_esc0_1_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "esc1_clk_src",
- .parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
- .num_parents = 6,
+ .parent_data = mmcc_xo_dsibyte_hdmi_edp_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_dsibyte_hdmi_edp_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -925,8 +937,8 @@ static struct clk_rcg2 extpclk_clk_src = {
.freq_tbl = extpclk_freq_tbl,
.clkr.hw.init = &(struct clk_init_data){
.name = "extpclk_clk_src",
- .parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
- .num_parents = 6,
+ .parent_data = mmcc_xo_dsi_hdmi_edp_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_dsi_hdmi_edp_gpll0),
.ops = &clk_byte_ops,
.flags = CLK_SET_RATE_PARENT,
},
@@ -944,8 +956,8 @@ static struct clk_rcg2 hdmi_clk_src = {
.freq_tbl = ftbl_mdss_hdmi_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "hdmi_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -962,8 +974,8 @@ static struct clk_rcg2 vsync_clk_src = {
.freq_tbl = ftbl_mdss_vsync_clk,
.clkr.hw.init = &(struct clk_init_data){
.name = "vsync_clk_src",
- .parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
- .num_parents = 4,
+ .parent_data = mmcc_xo_mmpll0_mmpll1_gpll0,
+ .num_parents = ARRAY_SIZE(mmcc_xo_mmpll0_mmpll1_gpll0),
.ops = &clk_rcg2_ops,
},
};
@@ -975,8 +987,8 @@ static struct clk_branch camss_cci_cci_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_cci_cci_ahb_clk",
- .parent_names = (const char *[]){
- "mmss_ahb_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_ahb_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -991,8 +1003,8 @@ static struct clk_branch camss_cci_cci_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_cci_cci_clk",
- .parent_names = (const char *[]){
- "cci_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &cci_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1008,8 +1020,8 @@ static struct clk_branch camss_csi0_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi0_ahb_clk",
- .parent_names = (const char *[]){
- "mmss_ahb_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_ahb_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1024,8 +1036,8 @@ static struct clk_branch camss_csi0_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi0_clk",
- .parent_names = (const char *[]){
- "csi0_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi0_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1041,8 +1053,8 @@ static struct clk_branch camss_csi0phy_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi0phy_clk",
- .parent_names = (const char *[]){
- "csi0_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi0_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1058,8 +1070,8 @@ static struct clk_branch camss_csi0pix_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi0pix_clk",
- .parent_names = (const char *[]){
- "csi0_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi0_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1075,8 +1087,8 @@ static struct clk_branch camss_csi0rdi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi0rdi_clk",
- .parent_names = (const char *[]){
- "csi0_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi0_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1092,8 +1104,8 @@ static struct clk_branch camss_csi1_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi1_ahb_clk",
- .parent_names = (const char *[]){
- "mmss_ahb_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_ahb_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1108,8 +1120,8 @@ static struct clk_branch camss_csi1_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi1_clk",
- .parent_names = (const char *[]){
- "csi1_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi1_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1125,8 +1137,8 @@ static struct clk_branch camss_csi1phy_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi1phy_clk",
- .parent_names = (const char *[]){
- "csi1_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi1_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1142,8 +1154,8 @@ static struct clk_branch camss_csi1pix_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi1pix_clk",
- .parent_names = (const char *[]){
- "csi1_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi1_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1159,8 +1171,8 @@ static struct clk_branch camss_csi1rdi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi1rdi_clk",
- .parent_names = (const char *[]){
- "csi1_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi1_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1176,8 +1188,8 @@ static struct clk_branch camss_csi2_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi2_ahb_clk",
- .parent_names = (const char *[]){
- "mmss_ahb_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_ahb_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1192,8 +1204,8 @@ static struct clk_branch camss_csi2_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi2_clk",
- .parent_names = (const char *[]){
- "csi2_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi2_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1209,8 +1221,8 @@ static struct clk_branch camss_csi2phy_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi2phy_clk",
- .parent_names = (const char *[]){
- "csi2_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi2_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1226,8 +1238,8 @@ static struct clk_branch camss_csi2pix_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi2pix_clk",
- .parent_names = (const char *[]){
- "csi2_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi2_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1243,8 +1255,8 @@ static struct clk_branch camss_csi2rdi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi2rdi_clk",
- .parent_names = (const char *[]){
- "csi2_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi2_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1260,8 +1272,8 @@ static struct clk_branch camss_csi3_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi3_ahb_clk",
- .parent_names = (const char *[]){
- "mmss_ahb_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_ahb_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1276,8 +1288,8 @@ static struct clk_branch camss_csi3_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi3_clk",
- .parent_names = (const char *[]){
- "csi3_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi3_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1293,8 +1305,8 @@ static struct clk_branch camss_csi3phy_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi3phy_clk",
- .parent_names = (const char *[]){
- "csi3_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi3_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1310,8 +1322,8 @@ static struct clk_branch camss_csi3pix_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi3pix_clk",
- .parent_names = (const char *[]){
- "csi3_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi3_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1327,8 +1339,8 @@ static struct clk_branch camss_csi3rdi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi3rdi_clk",
- .parent_names = (const char *[]){
- "csi3_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi3_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1344,8 +1356,8 @@ static struct clk_branch camss_csi_vfe0_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi_vfe0_clk",
- .parent_names = (const char *[]){
- "vfe0_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &vfe0_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1361,8 +1373,8 @@ static struct clk_branch camss_csi_vfe1_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_csi_vfe1_clk",
- .parent_names = (const char *[]){
- "vfe1_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &vfe1_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1378,8 +1390,8 @@ static struct clk_branch camss_gp0_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_gp0_clk",
- .parent_names = (const char *[]){
- "camss_gp0_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &camss_gp0_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1395,8 +1407,8 @@ static struct clk_branch camss_gp1_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_gp1_clk",
- .parent_names = (const char *[]){
- "camss_gp1_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &camss_gp1_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1412,8 +1424,8 @@ static struct clk_branch camss_ispif_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_ispif_ahb_clk",
- .parent_names = (const char *[]){
- "mmss_ahb_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_ahb_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1428,8 +1440,8 @@ static struct clk_branch camss_jpeg_jpeg0_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_jpeg_jpeg0_clk",
- .parent_names = (const char *[]){
- "jpeg0_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &jpeg0_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1445,8 +1457,8 @@ static struct clk_branch camss_jpeg_jpeg1_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_jpeg_jpeg1_clk",
- .parent_names = (const char *[]){
- "jpeg1_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &jpeg1_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1462,8 +1474,8 @@ static struct clk_branch camss_jpeg_jpeg2_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_jpeg_jpeg2_clk",
- .parent_names = (const char *[]){
- "jpeg2_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &jpeg2_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1479,8 +1491,8 @@ static struct clk_branch camss_jpeg_jpeg_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_jpeg_jpeg_ahb_clk",
- .parent_names = (const char *[]){
- "mmss_ahb_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_ahb_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1495,8 +1507,8 @@ static struct clk_branch camss_jpeg_jpeg_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_jpeg_jpeg_axi_clk",
- .parent_names = (const char *[]){
- "mmss_axi_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_axi_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1511,8 +1523,8 @@ static struct clk_branch camss_jpeg_jpeg_ocmemnoc_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_jpeg_jpeg_ocmemnoc_clk",
- .parent_names = (const char *[]){
- "ocmemnoc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &ocmemnoc_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1528,8 +1540,8 @@ static struct clk_branch camss_mclk0_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_mclk0_clk",
- .parent_names = (const char *[]){
- "mclk0_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mclk0_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1545,8 +1557,8 @@ static struct clk_branch camss_mclk1_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_mclk1_clk",
- .parent_names = (const char *[]){
- "mclk1_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mclk1_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1562,8 +1574,8 @@ static struct clk_branch camss_mclk2_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_mclk2_clk",
- .parent_names = (const char *[]){
- "mclk2_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mclk2_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1579,8 +1591,8 @@ static struct clk_branch camss_mclk3_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_mclk3_clk",
- .parent_names = (const char *[]){
- "mclk3_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mclk3_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1596,8 +1608,8 @@ static struct clk_branch camss_micro_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_micro_ahb_clk",
- .parent_names = (const char *[]){
- "mmss_ahb_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_ahb_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1612,8 +1624,8 @@ static struct clk_branch camss_phy0_csi0phytimer_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_phy0_csi0phytimer_clk",
- .parent_names = (const char *[]){
- "csi0phytimer_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi0phytimer_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1629,8 +1641,8 @@ static struct clk_branch camss_phy1_csi1phytimer_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_phy1_csi1phytimer_clk",
- .parent_names = (const char *[]){
- "csi1phytimer_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi1phytimer_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1646,8 +1658,8 @@ static struct clk_branch camss_phy2_csi2phytimer_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_phy2_csi2phytimer_clk",
- .parent_names = (const char *[]){
- "csi2phytimer_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &csi2phytimer_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1663,8 +1675,8 @@ static struct clk_branch camss_top_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_top_ahb_clk",
- .parent_names = (const char *[]){
- "mmss_ahb_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_ahb_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1679,8 +1691,8 @@ static struct clk_branch camss_vfe_cpp_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_vfe_cpp_ahb_clk",
- .parent_names = (const char *[]){
- "mmss_ahb_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_ahb_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1695,8 +1707,8 @@ static struct clk_branch camss_vfe_cpp_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_vfe_cpp_clk",
- .parent_names = (const char *[]){
- "cpp_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &cpp_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1712,8 +1724,8 @@ static struct clk_branch camss_vfe_vfe0_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_vfe_vfe0_clk",
- .parent_names = (const char *[]){
- "vfe0_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &vfe0_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1729,8 +1741,8 @@ static struct clk_branch camss_vfe_vfe1_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_vfe_vfe1_clk",
- .parent_names = (const char *[]){
- "vfe1_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &vfe1_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1746,8 +1758,8 @@ static struct clk_branch camss_vfe_vfe_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_vfe_vfe_ahb_clk",
- .parent_names = (const char *[]){
- "mmss_ahb_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_ahb_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1762,8 +1774,8 @@ static struct clk_branch camss_vfe_vfe_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_vfe_vfe_axi_clk",
- .parent_names = (const char *[]){
- "mmss_axi_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_axi_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1778,8 +1790,8 @@ static struct clk_branch camss_vfe_vfe_ocmemnoc_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "camss_vfe_vfe_ocmemnoc_clk",
- .parent_names = (const char *[]){
- "ocmemnoc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &ocmemnoc_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1795,8 +1807,8 @@ static struct clk_branch mdss_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mdss_ahb_clk",
- .parent_names = (const char *[]){
- "mmss_ahb_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_ahb_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1811,8 +1823,8 @@ static struct clk_branch mdss_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mdss_axi_clk",
- .parent_names = (const char *[]){
- "mmss_axi_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_axi_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1828,8 +1840,8 @@ static struct clk_branch mdss_byte0_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mdss_byte0_clk",
- .parent_names = (const char *[]){
- "byte0_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &byte0_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1845,8 +1857,8 @@ static struct clk_branch mdss_byte1_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mdss_byte1_clk",
- .parent_names = (const char *[]){
- "byte1_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &byte1_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1862,8 +1874,8 @@ static struct clk_branch mdss_edpaux_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mdss_edpaux_clk",
- .parent_names = (const char *[]){
- "edpaux_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &edpaux_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1879,8 +1891,8 @@ static struct clk_branch mdss_edplink_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mdss_edplink_clk",
- .parent_names = (const char *[]){
- "edplink_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &edplink_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1896,8 +1908,8 @@ static struct clk_branch mdss_edppixel_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mdss_edppixel_clk",
- .parent_names = (const char *[]){
- "edppixel_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &edppixel_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1913,8 +1925,8 @@ static struct clk_branch mdss_esc0_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mdss_esc0_clk",
- .parent_names = (const char *[]){
- "esc0_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &esc0_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1930,8 +1942,8 @@ static struct clk_branch mdss_esc1_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mdss_esc1_clk",
- .parent_names = (const char *[]){
- "esc1_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &esc1_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1947,8 +1959,8 @@ static struct clk_branch mdss_extpclk_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mdss_extpclk_clk",
- .parent_names = (const char *[]){
- "extpclk_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &extpclk_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1964,8 +1976,8 @@ static struct clk_branch mdss_hdmi_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mdss_hdmi_ahb_clk",
- .parent_names = (const char *[]){
- "mmss_ahb_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_ahb_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -1980,8 +1992,8 @@ static struct clk_branch mdss_hdmi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mdss_hdmi_clk",
- .parent_names = (const char *[]){
- "hdmi_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &hdmi_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -1997,8 +2009,8 @@ static struct clk_branch mdss_mdp_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mdss_mdp_clk",
- .parent_names = (const char *[]){
- "mdp_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mdp_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2014,8 +2026,8 @@ static struct clk_branch mdss_mdp_lut_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mdss_mdp_lut_clk",
- .parent_names = (const char *[]){
- "mdp_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mdp_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2031,8 +2043,8 @@ static struct clk_branch mdss_pclk0_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mdss_pclk0_clk",
- .parent_names = (const char *[]){
- "pclk0_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &pclk0_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2048,8 +2060,8 @@ static struct clk_branch mdss_pclk1_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mdss_pclk1_clk",
- .parent_names = (const char *[]){
- "pclk1_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &pclk1_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2065,8 +2077,8 @@ static struct clk_branch mdss_vsync_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mdss_vsync_clk",
- .parent_names = (const char *[]){
- "vsync_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &vsync_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2082,8 +2094,8 @@ static struct clk_branch mmss_misc_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mmss_misc_ahb_clk",
- .parent_names = (const char *[]){
- "mmss_ahb_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_ahb_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2098,8 +2110,8 @@ static struct clk_branch mmss_mmssnoc_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mmss_mmssnoc_ahb_clk",
- .parent_names = (const char *[]){
- "mmss_ahb_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_ahb_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2115,8 +2127,8 @@ static struct clk_branch mmss_mmssnoc_bto_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mmss_mmssnoc_bto_ahb_clk",
- .parent_names = (const char *[]){
- "mmss_ahb_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_ahb_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2132,8 +2144,8 @@ static struct clk_branch mmss_mmssnoc_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mmss_mmssnoc_axi_clk",
- .parent_names = (const char *[]){
- "mmss_axi_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_axi_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
@@ -2149,8 +2161,8 @@ static struct clk_branch mmss_s0_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "mmss_s0_axi_clk",
- .parent_names = (const char *[]){
- "mmss_axi_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_axi_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2166,8 +2178,8 @@ static struct clk_branch ocmemcx_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "ocmemcx_ahb_clk",
- .parent_names = (const char *[]){
- "mmss_ahb_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_ahb_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2182,8 +2194,8 @@ static struct clk_branch ocmemcx_ocmemnoc_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "ocmemcx_ocmemnoc_clk",
- .parent_names = (const char *[]){
- "ocmemnoc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &ocmemnoc_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2199,8 +2211,8 @@ static struct clk_branch oxili_ocmemgx_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "oxili_ocmemgx_clk",
- .parent_names = (const char *[]){
- "gfx3d_clk_src",
+ .parent_data = (const struct clk_parent_data[]){
+ { .fw_name = "gfx3d_clk_src", .name = "gfx3d_clk_src" },
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2216,8 +2228,8 @@ static struct clk_branch ocmemnoc_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "ocmemnoc_clk",
- .parent_names = (const char *[]){
- "ocmemnoc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &ocmemnoc_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2233,8 +2245,8 @@ static struct clk_branch oxili_gfx3d_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "oxili_gfx3d_clk",
- .parent_names = (const char *[]){
- "gfx3d_clk_src",
+ .parent_data = (const struct clk_parent_data[]){
+ { .fw_name = "gfx3d_clk_src", .name = "gfx3d_clk_src" },
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2250,8 +2262,8 @@ static struct clk_branch oxilicx_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "oxilicx_ahb_clk",
- .parent_names = (const char *[]){
- "mmss_ahb_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_ahb_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2266,8 +2278,8 @@ static struct clk_branch oxilicx_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "oxilicx_axi_clk",
- .parent_names = (const char *[]){
- "mmss_axi_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_axi_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2282,8 +2294,8 @@ static struct clk_branch venus0_ahb_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "venus0_ahb_clk",
- .parent_names = (const char *[]){
- "mmss_ahb_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_ahb_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2298,8 +2310,8 @@ static struct clk_branch venus0_axi_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "venus0_axi_clk",
- .parent_names = (const char *[]){
- "mmss_axi_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &mmss_axi_clk_src.clkr.hw
},
.num_parents = 1,
.ops = &clk_branch2_ops,
@@ -2314,8 +2326,8 @@ static struct clk_branch venus0_ocmemnoc_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "venus0_ocmemnoc_clk",
- .parent_names = (const char *[]){
- "ocmemnoc_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &ocmemnoc_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -2331,8 +2343,8 @@ static struct clk_branch venus0_vcodec0_clk = {
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "venus0_vcodec0_clk",
- .parent_names = (const char *[]){
- "vcodec0_clk_src",
+ .parent_hws = (const struct clk_hw*[]){
+ &vcodec0_clk_src.clkr.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
diff --git a/drivers/clk/qcom/reset.c b/drivers/clk/qcom/reset.c
index 2a16adb572d2..0e914ec7aeae 100644
--- a/drivers/clk/qcom/reset.c
+++ b/drivers/clk/qcom/reset.c
@@ -30,7 +30,7 @@ qcom_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
rst = to_qcom_reset_controller(rcdev);
map = &rst->reset_map[id];
- mask = BIT(map->bit);
+ mask = map->bitmask ? map->bitmask : BIT(map->bit);
return regmap_update_bits(rst->regmap, map->reg, mask, mask);
}
@@ -44,7 +44,7 @@ qcom_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
rst = to_qcom_reset_controller(rcdev);
map = &rst->reset_map[id];
- mask = BIT(map->bit);
+ mask = map->bitmask ? map->bitmask : BIT(map->bit);
return regmap_update_bits(rst->regmap, map->reg, mask, 0);
}
diff --git a/drivers/clk/qcom/reset.h b/drivers/clk/qcom/reset.h
index b8c113582072..9a47c838d9b1 100644
--- a/drivers/clk/qcom/reset.h
+++ b/drivers/clk/qcom/reset.h
@@ -12,6 +12,7 @@ struct qcom_reset_map {
unsigned int reg;
u8 bit;
u8 udelay;
+ u32 bitmask;
};
struct regmap;
diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c
index d74d46833012..e02542ca24a0 100644
--- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c
@@ -116,7 +116,7 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = {
DEF_FIXED("cp", R8A779A0_CLK_CP, CLK_EXTAL, 2, 1),
DEF_FIXED("cl16mck", R8A779A0_CLK_CL16MCK, CLK_PLL1_DIV2, 64, 1),
- DEF_GEN4_SDH("sdh0", R8A779A0_CLK_SD0H, CLK_SDSRC, 0x870),
+ DEF_GEN4_SDH("sd0h", R8A779A0_CLK_SD0H, CLK_SDSRC, 0x870),
DEF_GEN4_SD("sd0", R8A779A0_CLK_SD0, R8A779A0_CLK_SD0H, 0x870),
DEF_BASE("rpc", R8A779A0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC),
diff --git a/drivers/clk/renesas/r8a779f0-cpg-mssr.c b/drivers/clk/renesas/r8a779f0-cpg-mssr.c
index 4baf355e26d8..f721835c7e21 100644
--- a/drivers/clk/renesas/r8a779f0-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a779f0-cpg-mssr.c
@@ -42,6 +42,7 @@ enum clk_ids {
CLK_PLL5_DIV4,
CLK_PLL6_DIV2,
CLK_S0,
+ CLK_SASYNCPER,
CLK_SDSRC,
CLK_RPCSRC,
CLK_OCO,
@@ -71,6 +72,7 @@ static const struct cpg_core_clk r8a779f0_core_clks[] __initconst = {
DEF_FIXED(".pll6_div2", CLK_PLL6_DIV2, CLK_PLL6, 2, 1),
DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1),
+ DEF_FIXED(".sasyncper", CLK_SASYNCPER, CLK_PLL5_DIV4, 3, 1),
DEF_BASE(".sdsrc", CLK_SDSRC, CLK_TYPE_GEN4_SDSRC, CLK_PLL5),
DEF_RATE(".oco", CLK_OCO, 32768),
@@ -109,11 +111,11 @@ static const struct cpg_core_clk r8a779f0_core_clks[] __initconst = {
DEF_FIXED("cpex", R8A779F0_CLK_CPEX, CLK_EXTAL, 2, 1),
DEF_FIXED("sasyncrt", R8A779F0_CLK_SASYNCRT, CLK_PLL5_DIV4, 48, 1),
- DEF_FIXED("sasyncperd1", R8A779F0_CLK_SASYNCPERD1, CLK_PLL5_DIV4, 3, 1),
- DEF_FIXED("sasyncperd2", R8A779F0_CLK_SASYNCPERD2, R8A779F0_CLK_SASYNCPERD1, 2, 1),
- DEF_FIXED("sasyncperd4", R8A779F0_CLK_SASYNCPERD4, R8A779F0_CLK_SASYNCPERD1, 4, 1),
+ DEF_FIXED("sasyncperd1",R8A779F0_CLK_SASYNCPERD1, CLK_SASYNCPER,1, 1),
+ DEF_FIXED("sasyncperd2",R8A779F0_CLK_SASYNCPERD2, CLK_SASYNCPER,2, 1),
+ DEF_FIXED("sasyncperd4",R8A779F0_CLK_SASYNCPERD4, CLK_SASYNCPER,4, 1),
- DEF_GEN4_SDH("sdh0", R8A779F0_CLK_SD0H, CLK_SDSRC, 0x870),
+ DEF_GEN4_SDH("sd0h", R8A779F0_CLK_SD0H, CLK_SDSRC, 0x870),
DEF_GEN4_SD("sd0", R8A779F0_CLK_SD0, R8A779F0_CLK_SD0H, 0x870),
DEF_BASE("rpc", R8A779F0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC),
@@ -126,10 +128,10 @@ static const struct cpg_core_clk r8a779f0_core_clks[] __initconst = {
};
static const struct mssr_mod_clk r8a779f0_mod_clks[] __initconst = {
- DEF_MOD("hscif0", 514, R8A779F0_CLK_S0D3),
- DEF_MOD("hscif1", 515, R8A779F0_CLK_S0D3),
- DEF_MOD("hscif2", 516, R8A779F0_CLK_S0D3),
- DEF_MOD("hscif3", 517, R8A779F0_CLK_S0D3),
+ DEF_MOD("hscif0", 514, R8A779F0_CLK_SASYNCPERD1),
+ DEF_MOD("hscif1", 515, R8A779F0_CLK_SASYNCPERD1),
+ DEF_MOD("hscif2", 516, R8A779F0_CLK_SASYNCPERD1),
+ DEF_MOD("hscif3", 517, R8A779F0_CLK_SASYNCPERD1),
DEF_MOD("i2c0", 518, R8A779F0_CLK_S0D6_PER),
DEF_MOD("i2c1", 519, R8A779F0_CLK_S0D6_PER),
DEF_MOD("i2c2", 520, R8A779F0_CLK_S0D6_PER),
@@ -142,10 +144,10 @@ static const struct mssr_mod_clk r8a779f0_mod_clks[] __initconst = {
DEF_MOD("msiof3", 621, R8A779F0_CLK_MSO),
DEF_MOD("pcie0", 624, R8A779F0_CLK_S0D2),
DEF_MOD("pcie1", 625, R8A779F0_CLK_S0D2),
- DEF_MOD("scif0", 702, R8A779F0_CLK_S0D12_PER),
- DEF_MOD("scif1", 703, R8A779F0_CLK_S0D12_PER),
- DEF_MOD("scif3", 704, R8A779F0_CLK_S0D12_PER),
- DEF_MOD("scif4", 705, R8A779F0_CLK_S0D12_PER),
+ DEF_MOD("scif0", 702, R8A779F0_CLK_SASYNCPERD4),
+ DEF_MOD("scif1", 703, R8A779F0_CLK_SASYNCPERD4),
+ DEF_MOD("scif3", 704, R8A779F0_CLK_SASYNCPERD4),
+ DEF_MOD("scif4", 705, R8A779F0_CLK_SASYNCPERD4),
DEF_MOD("sdhi0", 706, R8A779F0_CLK_SD0),
DEF_MOD("sys-dmac0", 709, R8A779F0_CLK_S0D3_PER),
DEF_MOD("sys-dmac1", 710, R8A779F0_CLK_S0D3_PER),
@@ -161,6 +163,8 @@ static const struct mssr_mod_clk r8a779f0_mod_clks[] __initconst = {
DEF_MOD("cmt3", 913, R8A779F0_CLK_R),
DEF_MOD("pfc0", 915, R8A779F0_CLK_CL16M),
DEF_MOD("tsc", 919, R8A779F0_CLK_CL16M),
+ DEF_MOD("rswitch2", 1505, R8A779F0_CLK_RSW2),
+ DEF_MOD("ether-serdes", 1506, R8A779F0_CLK_S0D2_HSC),
DEF_MOD("ufs", 1514, R8A779F0_CLK_S0D4_HSC),
};
diff --git a/drivers/clk/renesas/r8a779g0-cpg-mssr.c b/drivers/clk/renesas/r8a779g0-cpg-mssr.c
index d5b325e3c539..c6337a408e5e 100644
--- a/drivers/clk/renesas/r8a779g0-cpg-mssr.c
+++ b/drivers/clk/renesas/r8a779g0-cpg-mssr.c
@@ -91,11 +91,12 @@ static const struct cpg_core_clk r8a779g0_core_clks[] __initconst = {
DEF_BASE(".sdsrc", CLK_SDSRC, CLK_TYPE_GEN4_SDSRC, CLK_PLL5),
DEF_RATE(".oco", CLK_OCO, 32768),
- DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN4_RPCSRC, CLK_PLL5),
+ DEF_BASE(".rpcsrc", CLK_RPCSRC, CLK_TYPE_GEN4_RPCSRC, CLK_PLL5),
DEF_FIXED(".vio", CLK_VIO, CLK_PLL5_DIV2, 3, 1),
DEF_FIXED(".vc", CLK_VC, CLK_PLL5_DIV2, 3, 1),
/* Core Clock Outputs */
+ DEF_GEN4_Z("z0", R8A779G0_CLK_Z0, CLK_TYPE_GEN4_Z, CLK_PLL2, 2, 0),
DEF_FIXED("s0d2", R8A779G0_CLK_S0D2, CLK_S0, 2, 1),
DEF_FIXED("s0d3", R8A779G0_CLK_S0D3, CLK_S0, 3, 1),
DEF_FIXED("s0d4", R8A779G0_CLK_S0D4, CLK_S0, 4, 1),
@@ -130,6 +131,7 @@ static const struct cpg_core_clk r8a779g0_core_clks[] __initconst = {
DEF_FIXED("s0d4_hsc", R8A779G0_CLK_S0D4_HSC, CLK_S0_HSC, 4, 1),
DEF_FIXED("cl16m_hsc", R8A779G0_CLK_CL16M_HSC, CLK_S0_HSC, 48, 1),
DEF_FIXED("s0d2_cc", R8A779G0_CLK_S0D2_CC, CLK_S0, 2, 1),
+ DEF_FIXED("sasyncrt", R8A779G0_CLK_SASYNCRT, CLK_PLL5_DIV4, 48, 1),
DEF_FIXED("sasyncperd1",R8A779G0_CLK_SASYNCPERD1, CLK_SASYNCPER,1, 1),
DEF_FIXED("sasyncperd2",R8A779G0_CLK_SASYNCPERD2, CLK_SASYNCPER,2, 1),
DEF_FIXED("sasyncperd4",R8A779G0_CLK_SASYNCPERD4, CLK_SASYNCPER,4, 1),
@@ -144,7 +146,8 @@ static const struct cpg_core_clk r8a779g0_core_clks[] __initconst = {
DEF_FIXED("vcbus", R8A779G0_CLK_VCBUS, CLK_VC, 1, 1),
DEF_FIXED("vcbusd2", R8A779G0_CLK_VCBUSD2, CLK_VC, 2, 1),
- DEF_GEN4_SD("sd0", R8A779G0_CLK_SD0, CLK_SDSRC, 0x870),
+ DEF_GEN4_SDH("sd0h", R8A779G0_CLK_SD0H, CLK_SDSRC, 0x870),
+ DEF_GEN4_SD("sd0", R8A779G0_CLK_SD0, R8A779G0_CLK_SD0H, 0x870),
DEF_DIV6P1("mso", R8A779G0_CLK_MSO, CLK_PLL5_DIV4, 0x87c),
DEF_BASE("rpc", R8A779G0_CLK_RPC, CLK_TYPE_GEN4_RPC, CLK_RPCSRC),
@@ -168,7 +171,33 @@ static const struct mssr_mod_clk r8a779g0_mod_clks[] __initconst = {
DEF_MOD("i2c3", 521, R8A779G0_CLK_S0D6_PER),
DEF_MOD("i2c4", 522, R8A779G0_CLK_S0D6_PER),
DEF_MOD("i2c5", 523, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("irqc", 611, R8A779G0_CLK_CL16M),
+ DEF_MOD("msi0", 618, R8A779G0_CLK_MSO),
+ DEF_MOD("msi1", 619, R8A779G0_CLK_MSO),
+ DEF_MOD("msi2", 620, R8A779G0_CLK_MSO),
+ DEF_MOD("msi3", 621, R8A779G0_CLK_MSO),
+ DEF_MOD("msi4", 622, R8A779G0_CLK_MSO),
+ DEF_MOD("msi5", 623, R8A779G0_CLK_MSO),
+ DEF_MOD("pwm", 628, R8A779G0_CLK_SASYNCPERD4),
+ DEF_MOD("rpc-if", 629, R8A779G0_CLK_RPCD2),
+ DEF_MOD("scif0", 702, R8A779G0_CLK_SASYNCPERD4),
+ DEF_MOD("scif1", 703, R8A779G0_CLK_SASYNCPERD4),
+ DEF_MOD("scif3", 704, R8A779G0_CLK_SASYNCPERD4),
+ DEF_MOD("scif4", 705, R8A779G0_CLK_SASYNCPERD4),
+ DEF_MOD("sdhi", 706, R8A779G0_CLK_SD0),
+ DEF_MOD("sydm0", 709, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("sydm1", 710, R8A779G0_CLK_S0D6_PER),
+ DEF_MOD("tmu0", 713, R8A779G0_CLK_SASYNCRT),
+ DEF_MOD("tmu1", 714, R8A779G0_CLK_SASYNCPERD2),
+ DEF_MOD("tmu2", 715, R8A779G0_CLK_SASYNCPERD2),
+ DEF_MOD("tmu3", 716, R8A779G0_CLK_SASYNCPERD2),
+ DEF_MOD("tmu4", 717, R8A779G0_CLK_SASYNCPERD2),
+ DEF_MOD("tpu0", 718, R8A779G0_CLK_SASYNCPERD4),
DEF_MOD("wdt1:wdt0", 907, R8A779G0_CLK_R),
+ DEF_MOD("cmt0", 910, R8A779G0_CLK_R),
+ DEF_MOD("cmt1", 911, R8A779G0_CLK_R),
+ DEF_MOD("cmt2", 912, R8A779G0_CLK_R),
+ DEF_MOD("cmt3", 913, R8A779G0_CLK_R),
DEF_MOD("pfc0", 915, R8A779G0_CLK_CL16M),
DEF_MOD("pfc1", 916, R8A779G0_CLK_CL16M),
DEF_MOD("pfc2", 917, R8A779G0_CLK_CL16M),
diff --git a/drivers/clk/renesas/r9a06g032-clocks.c b/drivers/clk/renesas/r9a06g032-clocks.c
index 1488c9d6e639..983faa5707b9 100644
--- a/drivers/clk/renesas/r9a06g032-clocks.c
+++ b/drivers/clk/renesas/r9a06g032-clocks.c
@@ -412,7 +412,7 @@ static int r9a06g032_attach_dev(struct generic_pm_domain *pd,
int error;
int index;
- while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
+ while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i++,
&clkspec)) {
if (clkspec.np != pd->dev.of_node)
continue;
@@ -425,7 +425,6 @@ static int r9a06g032_attach_dev(struct generic_pm_domain *pd,
if (error)
return error;
}
- i++;
}
return 0;
diff --git a/drivers/clk/renesas/r9a07g043-cpg.c b/drivers/clk/renesas/r9a07g043-cpg.c
index 37475465100d..99f72bf590fa 100644
--- a/drivers/clk/renesas/r9a07g043-cpg.c
+++ b/drivers/clk/renesas/r9a07g043-cpg.c
@@ -158,10 +158,6 @@ static struct rzg2l_mod_clk r9a07g043_mod_clks[] = {
0x548, 0),
DEF_MOD("wdt0_clk", R9A07G043_WDT0_CLK, R9A07G043_OSCCLK,
0x548, 1),
- DEF_MOD("wdt2_pclk", R9A07G043_WDT2_PCLK, R9A07G043_CLK_P0,
- 0x548, 4),
- DEF_MOD("wdt2_clk", R9A07G043_WDT2_CLK, R9A07G043_OSCCLK,
- 0x548, 5),
DEF_MOD("spi_clk2", R9A07G043_SPI_CLK2, R9A07G043_CLK_SPI1,
0x550, 0),
DEF_MOD("spi_clk", R9A07G043_SPI_CLK, R9A07G043_CLK_SPI0,
@@ -269,7 +265,6 @@ static struct rzg2l_reset r9a07g043_resets[] = {
DEF_RST(R9A07G043_OSTM1_PRESETZ, 0x834, 1),
DEF_RST(R9A07G043_OSTM2_PRESETZ, 0x834, 2),
DEF_RST(R9A07G043_WDT0_PRESETN, 0x848, 0),
- DEF_RST(R9A07G043_WDT2_PRESETN, 0x848, 2),
DEF_RST(R9A07G043_SPI_RST, 0x850, 0),
DEF_RST(R9A07G043_SDHI0_IXRST, 0x854, 0),
DEF_RST(R9A07G043_SDHI1_IXRST, 0x854, 1),
diff --git a/drivers/clk/renesas/r9a07g044-cpg.c b/drivers/clk/renesas/r9a07g044-cpg.c
index 02a4fc41bb6e..f5550fccb029 100644
--- a/drivers/clk/renesas/r9a07g044-cpg.c
+++ b/drivers/clk/renesas/r9a07g044-cpg.c
@@ -182,7 +182,7 @@ static const struct {
};
static const struct {
- struct rzg2l_mod_clk common[76];
+ struct rzg2l_mod_clk common[75];
#ifdef CONFIG_CLK_R9A07G054
struct rzg2l_mod_clk drp[0];
#endif
@@ -204,6 +204,8 @@ static const struct {
0x534, 1),
DEF_MOD("ostm2_pclk", R9A07G044_OSTM2_PCLK, R9A07G044_CLK_P0,
0x534, 2),
+ DEF_MOD("mtu_x_mck", R9A07G044_MTU_X_MCK_MTU3, R9A07G044_CLK_P0,
+ 0x538, 0),
DEF_MOD("gpt_pclk", R9A07G044_GPT_PCLK, R9A07G044_CLK_P0,
0x540, 0),
DEF_MOD("poeg_a_clkp", R9A07G044_POEG_A_CLKP, R9A07G044_CLK_P0,
@@ -222,10 +224,6 @@ static const struct {
0x548, 2),
DEF_MOD("wdt1_clk", R9A07G044_WDT1_CLK, R9A07G044_OSCCLK,
0x548, 3),
- DEF_MOD("wdt2_pclk", R9A07G044_WDT2_PCLK, R9A07G044_CLK_P0,
- 0x548, 4),
- DEF_MOD("wdt2_clk", R9A07G044_WDT2_CLK, R9A07G044_OSCCLK,
- 0x548, 5),
DEF_MOD("spi_clk2", R9A07G044_SPI_CLK2, R9A07G044_CLK_SPI1,
0x550, 0),
DEF_MOD("spi_clk", R9A07G044_SPI_CLK, R9A07G044_CLK_SPI0,
@@ -356,6 +354,7 @@ static struct rzg2l_reset r9a07g044_resets[] = {
DEF_RST(R9A07G044_OSTM0_PRESETZ, 0x834, 0),
DEF_RST(R9A07G044_OSTM1_PRESETZ, 0x834, 1),
DEF_RST(R9A07G044_OSTM2_PRESETZ, 0x834, 2),
+ DEF_RST(R9A07G044_MTU_X_PRESET_MTU3, 0x838, 0),
DEF_RST(R9A07G044_GPT_RST_C, 0x840, 0),
DEF_RST(R9A07G044_POEG_A_RST, 0x844, 0),
DEF_RST(R9A07G044_POEG_B_RST, 0x844, 1),
@@ -363,7 +362,6 @@ static struct rzg2l_reset r9a07g044_resets[] = {
DEF_RST(R9A07G044_POEG_D_RST, 0x844, 3),
DEF_RST(R9A07G044_WDT0_PRESETN, 0x848, 0),
DEF_RST(R9A07G044_WDT1_PRESETN, 0x848, 1),
- DEF_RST(R9A07G044_WDT2_PRESETN, 0x848, 2),
DEF_RST(R9A07G044_SPI_RST, 0x850, 0),
DEF_RST(R9A07G044_SDHI0_IXRST, 0x854, 0),
DEF_RST(R9A07G044_SDHI1_IXRST, 0x854, 1),
diff --git a/drivers/clk/renesas/rzg2l-cpg.c b/drivers/clk/renesas/rzg2l-cpg.c
index 3ff6ecd61756..4bf40f6ccd1d 100644
--- a/drivers/clk/renesas/rzg2l-cpg.c
+++ b/drivers/clk/renesas/rzg2l-cpg.c
@@ -95,7 +95,8 @@ struct rzg2l_pll5_mux_dsi_div_param {
* @num_resets: Number of Module Resets in info->resets[]
* @last_dt_core_clk: ID of the last Core Clock exported to DT
* @info: Pointer to platform data
- * @pll5_mux_dsi_div_params: pll5 mux and dsi div parameters
+ * @genpd: PM domain
+ * @mux_dsi_div_params: pll5 mux and dsi div parameters
*/
struct rzg2l_cpg_priv {
struct reset_controller_dev rcdev;
@@ -111,6 +112,8 @@ struct rzg2l_cpg_priv {
const struct rzg2l_cpg_info *info;
+ struct generic_pm_domain genpd;
+
struct rzg2l_pll5_mux_dsi_div_param mux_dsi_div_params;
};
@@ -182,7 +185,7 @@ rzg2l_cpg_mux_clk_register(const struct cpg_core_clk *core,
static int rzg2l_cpg_sd_clk_mux_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
- return clk_mux_determine_rate_flags(hw, req, 0);
+ return clk_mux_determine_rate_flags(hw, req, CLK_MUX_ROUND_CLOSEST);
}
static int rzg2l_cpg_sd_clk_mux_set_parent(struct clk_hw *hw, u8 index)
@@ -1014,8 +1017,8 @@ static const struct clk_ops rzg2l_mod_clock_ops = {
};
static struct mstp_clock
-*rzg2l_mod_clock__get_sibling(struct mstp_clock *clock,
- struct rzg2l_cpg_priv *priv)
+*rzg2l_mod_clock_get_sibling(struct mstp_clock *clock,
+ struct rzg2l_cpg_priv *priv)
{
struct clk_hw *hw;
unsigned int i;
@@ -1101,7 +1104,7 @@ rzg2l_cpg_register_mod_clk(const struct rzg2l_mod_clk *mod,
struct mstp_clock *sibling;
clock->enabled = rzg2l_mod_clock_is_enabled(&clock->hw);
- sibling = rzg2l_mod_clock__get_sibling(clock, priv);
+ sibling = rzg2l_mod_clock_get_sibling(clock, priv);
if (sibling) {
clock->sibling = sibling;
sibling->sibling = clock;
@@ -1223,22 +1226,31 @@ static int rzg2l_cpg_reset_controller_register(struct rzg2l_cpg_priv *priv)
return devm_reset_controller_register(priv->dev, &priv->rcdev);
}
-static bool rzg2l_cpg_is_pm_clk(const struct of_phandle_args *clkspec)
+static bool rzg2l_cpg_is_pm_clk(struct rzg2l_cpg_priv *priv,
+ const struct of_phandle_args *clkspec)
{
+ const struct rzg2l_cpg_info *info = priv->info;
+ unsigned int id;
+ unsigned int i;
+
if (clkspec->args_count != 2)
return false;
- switch (clkspec->args[0]) {
- case CPG_MOD:
- return true;
-
- default:
+ if (clkspec->args[0] != CPG_MOD)
return false;
+
+ id = clkspec->args[1] + info->num_total_core_clks;
+ for (i = 0; i < info->num_no_pm_mod_clks; i++) {
+ if (info->no_pm_mod_clks[i] == id)
+ return false;
}
+
+ return true;
}
-static int rzg2l_cpg_attach_dev(struct generic_pm_domain *unused, struct device *dev)
+static int rzg2l_cpg_attach_dev(struct generic_pm_domain *domain, struct device *dev)
{
+ struct rzg2l_cpg_priv *priv = container_of(domain, struct rzg2l_cpg_priv, genpd);
struct device_node *np = dev->of_node;
struct of_phandle_args clkspec;
bool once = true;
@@ -1248,7 +1260,7 @@ static int rzg2l_cpg_attach_dev(struct generic_pm_domain *unused, struct device
while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
&clkspec)) {
- if (rzg2l_cpg_is_pm_clk(&clkspec)) {
+ if (rzg2l_cpg_is_pm_clk(priv, &clkspec)) {
if (once) {
once = false;
error = pm_clk_create(dev);
@@ -1298,16 +1310,13 @@ static void rzg2l_cpg_genpd_remove(void *data)
pm_genpd_remove(data);
}
-static int __init rzg2l_cpg_add_clk_domain(struct device *dev)
+static int __init rzg2l_cpg_add_clk_domain(struct rzg2l_cpg_priv *priv)
{
+ struct device *dev = priv->dev;
struct device_node *np = dev->of_node;
- struct generic_pm_domain *genpd;
+ struct generic_pm_domain *genpd = &priv->genpd;
int ret;
- genpd = devm_kzalloc(dev, sizeof(*genpd), GFP_KERNEL);
- if (!genpd)
- return -ENOMEM;
-
genpd->name = np->name;
genpd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ALWAYS_ON |
GENPD_FLAG_ACTIVE_WAKEUP;
@@ -1377,7 +1386,7 @@ static int __init rzg2l_cpg_probe(struct platform_device *pdev)
if (error)
return error;
- error = rzg2l_cpg_add_clk_domain(dev);
+ error = rzg2l_cpg_add_clk_domain(priv);
if (error)
return error;
diff --git a/drivers/clk/renesas/rzg2l-cpg.h b/drivers/clk/renesas/rzg2l-cpg.h
index cecbdf5e4f93..eee780276a9e 100644
--- a/drivers/clk/renesas/rzg2l-cpg.h
+++ b/drivers/clk/renesas/rzg2l-cpg.h
@@ -256,6 +256,10 @@ struct rzg2l_cpg_info {
unsigned int num_mod_clks;
unsigned int num_hw_mod_clks;
+ /* No PM Module Clocks */
+ const unsigned int *no_pm_mod_clks;
+ unsigned int num_no_pm_mod_clks;
+
/* Resets */
const struct rzg2l_reset *resets;
unsigned int num_resets;
diff --git a/drivers/clk/rockchip/Kconfig b/drivers/clk/rockchip/Kconfig
index 345a5d2a457c..9aad86925cd2 100644
--- a/drivers/clk/rockchip/Kconfig
+++ b/drivers/clk/rockchip/Kconfig
@@ -99,4 +99,12 @@ config CLK_RK3568
default y
help
Build the driver for RK3568 Clock Driver.
+
+config CLK_RK3588
+ bool "Rockchip RK3588 clock controller support"
+ depends on ARM64 || COMPILE_TEST
+ default y
+ help
+ Build the driver for RK3588 Clock Driver.
+
endif
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile
index e8543876c056..36894f6a7022 100644
--- a/drivers/clk/rockchip/Makefile
+++ b/drivers/clk/rockchip/Makefile
@@ -28,3 +28,4 @@ obj-$(CONFIG_CLK_RK3328) += clk-rk3328.o
obj-$(CONFIG_CLK_RK3368) += clk-rk3368.o
obj-$(CONFIG_CLK_RK3399) += clk-rk3399.o
obj-$(CONFIG_CLK_RK3568) += clk-rk3568.o
+obj-$(CONFIG_CLK_RK3588) += clk-rk3588.o rst-rk3588.o
diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c
index 47288197c9d7..6ea7fba9f9e5 100644
--- a/drivers/clk/rockchip/clk-cpu.c
+++ b/drivers/clk/rockchip/clk-cpu.c
@@ -113,6 +113,42 @@ static void rockchip_cpuclk_set_dividers(struct rockchip_cpuclk *cpuclk,
}
}
+static void rockchip_cpuclk_set_pre_muxs(struct rockchip_cpuclk *cpuclk,
+ const struct rockchip_cpuclk_rate_table *rate)
+{
+ int i;
+
+ /* alternate parent is active now. set the pre_muxs */
+ for (i = 0; i < ARRAY_SIZE(rate->pre_muxs); i++) {
+ const struct rockchip_cpuclk_clksel *clksel = &rate->pre_muxs[i];
+
+ if (!clksel->reg)
+ break;
+
+ pr_debug("%s: setting reg 0x%x to 0x%x\n",
+ __func__, clksel->reg, clksel->val);
+ writel(clksel->val, cpuclk->reg_base + clksel->reg);
+ }
+}
+
+static void rockchip_cpuclk_set_post_muxs(struct rockchip_cpuclk *cpuclk,
+ const struct rockchip_cpuclk_rate_table *rate)
+{
+ int i;
+
+ /* alternate parent is active now. set the muxs */
+ for (i = 0; i < ARRAY_SIZE(rate->post_muxs); i++) {
+ const struct rockchip_cpuclk_clksel *clksel = &rate->post_muxs[i];
+
+ if (!clksel->reg)
+ break;
+
+ pr_debug("%s: setting reg 0x%x to 0x%x\n",
+ __func__, clksel->reg, clksel->val);
+ writel(clksel->val, cpuclk->reg_base + clksel->reg);
+ }
+}
+
static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk,
struct clk_notifier_data *ndata)
{
@@ -165,11 +201,20 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk,
cpuclk->reg_base + reg_data->core_reg[i]);
}
}
+
+ rockchip_cpuclk_set_pre_muxs(cpuclk, rate);
+
/* select alternate parent */
- writel(HIWORD_UPDATE(reg_data->mux_core_alt,
- reg_data->mux_core_mask,
- reg_data->mux_core_shift),
- cpuclk->reg_base + reg_data->core_reg[0]);
+ if (reg_data->mux_core_reg)
+ writel(HIWORD_UPDATE(reg_data->mux_core_alt,
+ reg_data->mux_core_mask,
+ reg_data->mux_core_shift),
+ cpuclk->reg_base + reg_data->mux_core_reg);
+ else
+ writel(HIWORD_UPDATE(reg_data->mux_core_alt,
+ reg_data->mux_core_mask,
+ reg_data->mux_core_shift),
+ cpuclk->reg_base + reg_data->core_reg[0]);
spin_unlock_irqrestore(cpuclk->lock, flags);
return 0;
@@ -202,10 +247,18 @@ static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk,
* primary parent by the extra dividers that were needed for the alt.
*/
- writel(HIWORD_UPDATE(reg_data->mux_core_main,
- reg_data->mux_core_mask,
- reg_data->mux_core_shift),
- cpuclk->reg_base + reg_data->core_reg[0]);
+ if (reg_data->mux_core_reg)
+ writel(HIWORD_UPDATE(reg_data->mux_core_main,
+ reg_data->mux_core_mask,
+ reg_data->mux_core_shift),
+ cpuclk->reg_base + reg_data->mux_core_reg);
+ else
+ writel(HIWORD_UPDATE(reg_data->mux_core_main,
+ reg_data->mux_core_mask,
+ reg_data->mux_core_shift),
+ cpuclk->reg_base + reg_data->core_reg[0]);
+
+ rockchip_cpuclk_set_post_muxs(cpuclk, rate);
/* remove dividers */
for (i = 0; i < reg_data->num_cores; i++) {
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index f7827b3b7fc1..2d42eb628926 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -843,6 +843,213 @@ static const struct clk_ops rockchip_rk3399_pll_clk_ops = {
};
/*
+ * PLL used in RK3588
+ */
+
+#define RK3588_PLLCON(i) (i * 0x4)
+#define RK3588_PLLCON0_M_MASK 0x3ff
+#define RK3588_PLLCON0_M_SHIFT 0
+#define RK3588_PLLCON1_P_MASK 0x3f
+#define RK3588_PLLCON1_P_SHIFT 0
+#define RK3588_PLLCON1_S_MASK 0x7
+#define RK3588_PLLCON1_S_SHIFT 6
+#define RK3588_PLLCON2_K_MASK 0xffff
+#define RK3588_PLLCON2_K_SHIFT 0
+#define RK3588_PLLCON1_PWRDOWN BIT(13)
+#define RK3588_PLLCON6_LOCK_STATUS BIT(15)
+
+static int rockchip_rk3588_pll_wait_lock(struct rockchip_clk_pll *pll)
+{
+ u32 pllcon;
+ int ret;
+
+ /*
+ * Lock time typical 250, max 500 input clock cycles @24MHz
+ * So define a very safe maximum of 1000us, meaning 24000 cycles.
+ */
+ ret = readl_relaxed_poll_timeout(pll->reg_base + RK3588_PLLCON(6),
+ pllcon,
+ pllcon & RK3588_PLLCON6_LOCK_STATUS,
+ 0, 1000);
+ if (ret)
+ pr_err("%s: timeout waiting for pll to lock\n", __func__);
+
+ return ret;
+}
+
+static void rockchip_rk3588_pll_get_params(struct rockchip_clk_pll *pll,
+ struct rockchip_pll_rate_table *rate)
+{
+ u32 pllcon;
+
+ pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(0));
+ rate->m = ((pllcon >> RK3588_PLLCON0_M_SHIFT) & RK3588_PLLCON0_M_MASK);
+
+ pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(1));
+ rate->p = ((pllcon >> RK3588_PLLCON1_P_SHIFT) & RK3588_PLLCON1_P_MASK);
+ rate->s = ((pllcon >> RK3588_PLLCON1_S_SHIFT) & RK3588_PLLCON1_S_MASK);
+
+ pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(2));
+ rate->k = ((pllcon >> RK3588_PLLCON2_K_SHIFT) & RK3588_PLLCON2_K_MASK);
+}
+
+static unsigned long rockchip_rk3588_pll_recalc_rate(struct clk_hw *hw, unsigned long prate)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ struct rockchip_pll_rate_table cur;
+ u64 rate64 = prate, postdiv;
+
+ rockchip_rk3588_pll_get_params(pll, &cur);
+
+ rate64 *= cur.m;
+ do_div(rate64, cur.p);
+
+ if (cur.k) {
+ /* fractional mode */
+ u64 frac_rate64 = prate * cur.k;
+
+ postdiv = cur.p * 65535;
+ do_div(frac_rate64, postdiv);
+ rate64 += frac_rate64;
+ }
+ rate64 = rate64 >> cur.s;
+
+ return (unsigned long)rate64;
+}
+
+static int rockchip_rk3588_pll_set_params(struct rockchip_clk_pll *pll,
+ const struct rockchip_pll_rate_table *rate)
+{
+ const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
+ struct clk_mux *pll_mux = &pll->pll_mux;
+ struct rockchip_pll_rate_table cur;
+ int rate_change_remuxed = 0;
+ int cur_parent;
+ int ret;
+
+ pr_debug("%s: rate settings for %lu p: %d, m: %d, s: %d, k: %d\n",
+ __func__, rate->rate, rate->p, rate->m, rate->s, rate->k);
+
+ rockchip_rk3588_pll_get_params(pll, &cur);
+ cur.rate = 0;
+
+ if (pll->type == pll_rk3588) {
+ cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
+ if (cur_parent == PLL_MODE_NORM) {
+ pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
+ rate_change_remuxed = 1;
+ }
+ }
+
+ /* set pll power down */
+ writel(HIWORD_UPDATE(RK3588_PLLCON1_PWRDOWN,
+ RK3588_PLLCON1_PWRDOWN, 0),
+ pll->reg_base + RK3399_PLLCON(1));
+
+ /* update pll values */
+ writel_relaxed(HIWORD_UPDATE(rate->m, RK3588_PLLCON0_M_MASK, RK3588_PLLCON0_M_SHIFT),
+ pll->reg_base + RK3399_PLLCON(0));
+
+ writel_relaxed(HIWORD_UPDATE(rate->p, RK3588_PLLCON1_P_MASK, RK3588_PLLCON1_P_SHIFT) |
+ HIWORD_UPDATE(rate->s, RK3588_PLLCON1_S_MASK, RK3588_PLLCON1_S_SHIFT),
+ pll->reg_base + RK3399_PLLCON(1));
+
+ writel_relaxed(HIWORD_UPDATE(rate->k, RK3588_PLLCON2_K_MASK, RK3588_PLLCON2_K_SHIFT),
+ pll->reg_base + RK3399_PLLCON(2));
+
+ /* set pll power up */
+ writel(HIWORD_UPDATE(0, RK3588_PLLCON1_PWRDOWN, 0),
+ pll->reg_base + RK3588_PLLCON(1));
+
+ /* wait for the pll to lock */
+ ret = rockchip_rk3588_pll_wait_lock(pll);
+ if (ret) {
+ pr_warn("%s: pll update unsuccessful, trying to restore old params\n",
+ __func__);
+ rockchip_rk3588_pll_set_params(pll, &cur);
+ }
+
+ if ((pll->type == pll_rk3588) && rate_change_remuxed)
+ pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
+
+ return ret;
+}
+
+static int rockchip_rk3588_pll_set_rate(struct clk_hw *hw, unsigned long drate,
+ unsigned long prate)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ const struct rockchip_pll_rate_table *rate;
+
+ pr_debug("%s: changing %s to %lu with a parent rate of %lu\n",
+ __func__, __clk_get_name(hw->clk), drate, prate);
+
+ /* Get required rate settings from table */
+ rate = rockchip_get_pll_settings(pll, drate);
+ if (!rate) {
+ pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+ drate, __clk_get_name(hw->clk));
+ return -EINVAL;
+ }
+
+ return rockchip_rk3588_pll_set_params(pll, rate);
+}
+
+static int rockchip_rk3588_pll_enable(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+ writel(HIWORD_UPDATE(0, RK3588_PLLCON1_PWRDOWN, 0),
+ pll->reg_base + RK3588_PLLCON(1));
+ rockchip_rk3588_pll_wait_lock(pll);
+
+ return 0;
+}
+
+static void rockchip_rk3588_pll_disable(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+ writel(HIWORD_UPDATE(RK3588_PLLCON1_PWRDOWN, RK3588_PLLCON1_PWRDOWN, 0),
+ pll->reg_base + RK3588_PLLCON(1));
+}
+
+static int rockchip_rk3588_pll_is_enabled(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+ u32 pllcon = readl(pll->reg_base + RK3588_PLLCON(1));
+
+ return !(pllcon & RK3588_PLLCON1_PWRDOWN);
+}
+
+static int rockchip_rk3588_pll_init(struct clk_hw *hw)
+{
+ struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
+
+ if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
+ return 0;
+
+ return 0;
+}
+
+static const struct clk_ops rockchip_rk3588_pll_clk_norate_ops = {
+ .recalc_rate = rockchip_rk3588_pll_recalc_rate,
+ .enable = rockchip_rk3588_pll_enable,
+ .disable = rockchip_rk3588_pll_disable,
+ .is_enabled = rockchip_rk3588_pll_is_enabled,
+};
+
+static const struct clk_ops rockchip_rk3588_pll_clk_ops = {
+ .recalc_rate = rockchip_rk3588_pll_recalc_rate,
+ .round_rate = rockchip_pll_round_rate,
+ .set_rate = rockchip_rk3588_pll_set_rate,
+ .enable = rockchip_rk3588_pll_enable,
+ .disable = rockchip_rk3588_pll_disable,
+ .is_enabled = rockchip_rk3588_pll_is_enabled,
+ .init = rockchip_rk3588_pll_init,
+};
+
+/*
* Common registering of pll clocks
*/
@@ -890,7 +1097,8 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
if (pll_type == pll_rk3036 ||
pll_type == pll_rk3066 ||
pll_type == pll_rk3328 ||
- pll_type == pll_rk3399)
+ pll_type == pll_rk3399 ||
+ pll_type == pll_rk3588)
pll_mux->flags |= CLK_MUX_HIWORD_MASK;
/* the actual muxing is xin24m, pll-output, xin32k */
@@ -957,6 +1165,14 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
else
init.ops = &rockchip_rk3399_pll_clk_ops;
break;
+ case pll_rk3588:
+ case pll_rk3588_core:
+ if (!pll->rate_table)
+ init.ops = &rockchip_rk3588_pll_clk_norate_ops;
+ else
+ init.ops = &rockchip_rk3588_pll_clk_ops;
+ init.flags = flags;
+ break;
default:
pr_warn("%s: Unknown pll type for pll clk %s\n",
__func__, name);
@@ -981,6 +1197,7 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
return mux_clk;
err_pll:
+ kfree(pll->rate_table);
clk_unregister(mux_clk);
mux_clk = pll_clk;
err_mux:
diff --git a/drivers/clk/rockchip/clk-rk3588.c b/drivers/clk/rockchip/clk-rk3588.c
new file mode 100644
index 000000000000..b7ce3fbd6fa6
--- /dev/null
+++ b/drivers/clk/rockchip/clk-rk3588.c
@@ -0,0 +1,2533 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2021 Rockchip Electronics Co. Ltd.
+ * Author: Elaine Zhang <zhangqing@rock-chips.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/syscore_ops.h>
+#include <dt-bindings/clock/rockchip,rk3588-cru.h>
+#include "clk.h"
+
+/*
+ * GATE with additional linked clock. Downstream enables the linked clock
+ * (via runtime PM) whenever the gate is enabled. The downstream implementation
+ * does this via separate clock nodes for each of the linked gate clocks,
+ * which leaks parts of the clock tree into DT. It is unclear why this is
+ * actually needed and things work without it for simple use cases. Thus
+ * the linked clock is ignored for now.
+ */
+#define GATE_LINK(_id, cname, pname, linkname, f, o, b, gf) \
+ GATE(_id, cname, pname, f, o, b, gf)
+
+
+#define RK3588_GRF_SOC_STATUS0 0x600
+#define RK3588_PHYREF_ALT_GATE 0xc38
+
+enum rk3588_plls {
+ b0pll, b1pll, lpll, v0pll, aupll, cpll, gpll, npll, ppll,
+};
+
+static struct rockchip_pll_rate_table rk3588_pll_rates[] = {
+ /* _mhz, _p, _m, _s, _k */
+ RK3588_PLL_RATE(2520000000, 2, 210, 0, 0),
+ RK3588_PLL_RATE(2496000000, 2, 208, 0, 0),
+ RK3588_PLL_RATE(2472000000, 2, 206, 0, 0),
+ RK3588_PLL_RATE(2448000000, 2, 204, 0, 0),
+ RK3588_PLL_RATE(2424000000, 2, 202, 0, 0),
+ RK3588_PLL_RATE(2400000000, 2, 200, 0, 0),
+ RK3588_PLL_RATE(2376000000, 2, 198, 0, 0),
+ RK3588_PLL_RATE(2352000000, 2, 196, 0, 0),
+ RK3588_PLL_RATE(2328000000, 2, 194, 0, 0),
+ RK3588_PLL_RATE(2304000000, 2, 192, 0, 0),
+ RK3588_PLL_RATE(2280000000, 2, 190, 0, 0),
+ RK3588_PLL_RATE(2256000000, 2, 376, 1, 0),
+ RK3588_PLL_RATE(2232000000, 2, 372, 1, 0),
+ RK3588_PLL_RATE(2208000000, 2, 368, 1, 0),
+ RK3588_PLL_RATE(2184000000, 2, 364, 1, 0),
+ RK3588_PLL_RATE(2160000000, 2, 360, 1, 0),
+ RK3588_PLL_RATE(2136000000, 2, 356, 1, 0),
+ RK3588_PLL_RATE(2112000000, 2, 352, 1, 0),
+ RK3588_PLL_RATE(2088000000, 2, 348, 1, 0),
+ RK3588_PLL_RATE(2064000000, 2, 344, 1, 0),
+ RK3588_PLL_RATE(2040000000, 2, 340, 1, 0),
+ RK3588_PLL_RATE(2016000000, 2, 336, 1, 0),
+ RK3588_PLL_RATE(1992000000, 2, 332, 1, 0),
+ RK3588_PLL_RATE(1968000000, 2, 328, 1, 0),
+ RK3588_PLL_RATE(1944000000, 2, 324, 1, 0),
+ RK3588_PLL_RATE(1920000000, 2, 320, 1, 0),
+ RK3588_PLL_RATE(1896000000, 2, 316, 1, 0),
+ RK3588_PLL_RATE(1872000000, 2, 312, 1, 0),
+ RK3588_PLL_RATE(1848000000, 2, 308, 1, 0),
+ RK3588_PLL_RATE(1824000000, 2, 304, 1, 0),
+ RK3588_PLL_RATE(1800000000, 2, 300, 1, 0),
+ RK3588_PLL_RATE(1776000000, 2, 296, 1, 0),
+ RK3588_PLL_RATE(1752000000, 2, 292, 1, 0),
+ RK3588_PLL_RATE(1728000000, 2, 288, 1, 0),
+ RK3588_PLL_RATE(1704000000, 2, 284, 1, 0),
+ RK3588_PLL_RATE(1680000000, 2, 280, 1, 0),
+ RK3588_PLL_RATE(1656000000, 2, 276, 1, 0),
+ RK3588_PLL_RATE(1632000000, 2, 272, 1, 0),
+ RK3588_PLL_RATE(1608000000, 2, 268, 1, 0),
+ RK3588_PLL_RATE(1584000000, 2, 264, 1, 0),
+ RK3588_PLL_RATE(1560000000, 2, 260, 1, 0),
+ RK3588_PLL_RATE(1536000000, 2, 256, 1, 0),
+ RK3588_PLL_RATE(1512000000, 2, 252, 1, 0),
+ RK3588_PLL_RATE(1488000000, 2, 248, 1, 0),
+ RK3588_PLL_RATE(1464000000, 2, 244, 1, 0),
+ RK3588_PLL_RATE(1440000000, 2, 240, 1, 0),
+ RK3588_PLL_RATE(1416000000, 2, 236, 1, 0),
+ RK3588_PLL_RATE(1392000000, 2, 232, 1, 0),
+ RK3588_PLL_RATE(1320000000, 2, 220, 1, 0),
+ RK3588_PLL_RATE(1200000000, 2, 200, 1, 0),
+ RK3588_PLL_RATE(1188000000, 2, 198, 1, 0),
+ RK3588_PLL_RATE(1100000000, 3, 550, 2, 0),
+ RK3588_PLL_RATE(1008000000, 2, 336, 2, 0),
+ RK3588_PLL_RATE(1000000000, 3, 500, 2, 0),
+ RK3588_PLL_RATE(983040000, 4, 655, 2, 23592),
+ RK3588_PLL_RATE(955520000, 3, 477, 2, 49806),
+ RK3588_PLL_RATE(903168000, 6, 903, 2, 11009),
+ RK3588_PLL_RATE(900000000, 2, 300, 2, 0),
+ RK3588_PLL_RATE(850000000, 3, 425, 2, 0),
+ RK3588_PLL_RATE(816000000, 2, 272, 2, 0),
+ RK3588_PLL_RATE(786432000, 2, 262, 2, 9437),
+ RK3588_PLL_RATE(786000000, 1, 131, 2, 0),
+ RK3588_PLL_RATE(785560000, 3, 392, 2, 51117),
+ RK3588_PLL_RATE(722534400, 8, 963, 2, 24850),
+ RK3588_PLL_RATE(600000000, 2, 200, 2, 0),
+ RK3588_PLL_RATE(594000000, 2, 198, 2, 0),
+ RK3588_PLL_RATE(408000000, 2, 272, 3, 0),
+ RK3588_PLL_RATE(312000000, 2, 208, 3, 0),
+ RK3588_PLL_RATE(216000000, 2, 288, 4, 0),
+ RK3588_PLL_RATE(100000000, 3, 400, 5, 0),
+ RK3588_PLL_RATE(96000000, 2, 256, 5, 0),
+ { /* sentinel */ },
+};
+
+#define RK3588_CLK_CORE_B0_SEL_CLEAN_MASK 0x3
+#define RK3588_CLK_CORE_B0_SEL_CLEAN_SHIFT 13
+#define RK3588_CLK_CORE_B1_SEL_CLEAN_MASK 0x3
+#define RK3588_CLK_CORE_B1_SEL_CLEAN_SHIFT 5
+#define RK3588_CLK_CORE_B0_GPLL_DIV_MASK 0x1f
+#define RK3588_CLK_CORE_B0_GPLL_DIV_SHIFT 1
+#define RK3588_CLK_CORE_L_SEL_CLEAN_MASK 0x3
+#define RK3588_CLK_CORE_L1_SEL_CLEAN_SHIFT 12
+#define RK3588_CLK_CORE_L0_SEL_CLEAN_SHIFT 5
+#define RK3588_CLK_DSU_SEL_DF_MASK 0x1
+#define RK3588_CLK_DSU_SEL_DF_SHIFT 15
+#define RK3588_CLK_DSU_DF_SRC_MASK 0x3
+#define RK3588_CLK_DSU_DF_SRC_SHIFT 12
+#define RK3588_CLK_DSU_DF_DIV_MASK 0x1f
+#define RK3588_CLK_DSU_DF_DIV_SHIFT 7
+#define RK3588_ACLKM_DSU_DIV_MASK 0x1f
+#define RK3588_ACLKM_DSU_DIV_SHIFT 1
+#define RK3588_ACLKS_DSU_DIV_MASK 0x1f
+#define RK3588_ACLKS_DSU_DIV_SHIFT 6
+#define RK3588_ACLKMP_DSU_DIV_MASK 0x1f
+#define RK3588_ACLKMP_DSU_DIV_SHIFT 11
+#define RK3588_PERIPH_DSU_DIV_MASK 0x1f
+#define RK3588_PERIPH_DSU_DIV_SHIFT 0
+#define RK3588_ATCLK_DSU_DIV_MASK 0x1f
+#define RK3588_ATCLK_DSU_DIV_SHIFT 0
+#define RK3588_GICCLK_DSU_DIV_MASK 0x1f
+#define RK3588_GICCLK_DSU_DIV_SHIFT 5
+
+#define RK3588_CORE_B0_SEL(_apllcore) \
+{ \
+ .reg = RK3588_BIGCORE0_CLKSEL_CON(0), \
+ .val = HIWORD_UPDATE(_apllcore, RK3588_CLK_CORE_B0_SEL_CLEAN_MASK, \
+ RK3588_CLK_CORE_B0_SEL_CLEAN_SHIFT) | \
+ HIWORD_UPDATE(0, RK3588_CLK_CORE_B0_GPLL_DIV_MASK, \
+ RK3588_CLK_CORE_B0_GPLL_DIV_SHIFT), \
+}
+
+#define RK3588_CORE_B1_SEL(_apllcore) \
+{ \
+ .reg = RK3588_BIGCORE0_CLKSEL_CON(1), \
+ .val = HIWORD_UPDATE(_apllcore, RK3588_CLK_CORE_B1_SEL_CLEAN_MASK, \
+ RK3588_CLK_CORE_B1_SEL_CLEAN_SHIFT), \
+}
+
+#define RK3588_CORE_B2_SEL(_apllcore) \
+{ \
+ .reg = RK3588_BIGCORE1_CLKSEL_CON(0), \
+ .val = HIWORD_UPDATE(_apllcore, RK3588_CLK_CORE_B0_SEL_CLEAN_MASK, \
+ RK3588_CLK_CORE_B0_SEL_CLEAN_SHIFT) | \
+ HIWORD_UPDATE(0, RK3588_CLK_CORE_B0_GPLL_DIV_MASK, \
+ RK3588_CLK_CORE_B0_GPLL_DIV_SHIFT), \
+}
+
+#define RK3588_CORE_B3_SEL(_apllcore) \
+{ \
+ .reg = RK3588_BIGCORE1_CLKSEL_CON(1), \
+ .val = HIWORD_UPDATE(_apllcore, RK3588_CLK_CORE_B1_SEL_CLEAN_MASK, \
+ RK3588_CLK_CORE_B1_SEL_CLEAN_SHIFT), \
+}
+
+#define RK3588_CORE_L_SEL0(_offs, _apllcore) \
+{ \
+ .reg = RK3588_DSU_CLKSEL_CON(6 + _offs), \
+ .val = HIWORD_UPDATE(_apllcore, RK3588_CLK_CORE_L_SEL_CLEAN_MASK, \
+ RK3588_CLK_CORE_L0_SEL_CLEAN_SHIFT) | \
+ HIWORD_UPDATE(_apllcore, RK3588_CLK_CORE_L_SEL_CLEAN_MASK, \
+ RK3588_CLK_CORE_L1_SEL_CLEAN_SHIFT), \
+}
+
+#define RK3588_CORE_L_SEL1(_seldsu, _divdsu) \
+{ \
+ .reg = RK3588_DSU_CLKSEL_CON(0), \
+ .val = HIWORD_UPDATE(_seldsu, RK3588_CLK_DSU_DF_SRC_MASK, \
+ RK3588_CLK_DSU_DF_SRC_SHIFT) | \
+ HIWORD_UPDATE(_divdsu - 1, RK3588_CLK_DSU_DF_DIV_MASK, \
+ RK3588_CLK_DSU_DF_DIV_SHIFT), \
+}
+
+#define RK3588_CORE_L_SEL2(_aclkm, _aclkmp, _aclks) \
+{ \
+ .reg = RK3588_DSU_CLKSEL_CON(1), \
+ .val = HIWORD_UPDATE(_aclkm - 1, RK3588_ACLKM_DSU_DIV_MASK, \
+ RK3588_ACLKM_DSU_DIV_SHIFT) | \
+ HIWORD_UPDATE(_aclkmp - 1, RK3588_ACLKMP_DSU_DIV_MASK, \
+ RK3588_ACLKMP_DSU_DIV_SHIFT) | \
+ HIWORD_UPDATE(_aclks - 1, RK3588_ACLKS_DSU_DIV_MASK, \
+ RK3588_ACLKS_DSU_DIV_SHIFT), \
+}
+
+#define RK3588_CORE_L_SEL3(_periph) \
+{ \
+ .reg = RK3588_DSU_CLKSEL_CON(2), \
+ .val = HIWORD_UPDATE(_periph - 1, RK3588_PERIPH_DSU_DIV_MASK, \
+ RK3588_PERIPH_DSU_DIV_SHIFT), \
+}
+
+#define RK3588_CORE_L_SEL4(_gicclk, _atclk) \
+{ \
+ .reg = RK3588_DSU_CLKSEL_CON(3), \
+ .val = HIWORD_UPDATE(_gicclk - 1, RK3588_GICCLK_DSU_DIV_MASK, \
+ RK3588_GICCLK_DSU_DIV_SHIFT) | \
+ HIWORD_UPDATE(_atclk - 1, RK3588_ATCLK_DSU_DIV_MASK, \
+ RK3588_ATCLK_DSU_DIV_SHIFT), \
+}
+
+#define RK3588_CPUB01CLK_RATE(_prate, _apllcore) \
+{ \
+ .prate = _prate##U, \
+ .pre_muxs = { \
+ RK3588_CORE_B0_SEL(0), \
+ RK3588_CORE_B1_SEL(0), \
+ }, \
+ .post_muxs = { \
+ RK3588_CORE_B0_SEL(_apllcore), \
+ RK3588_CORE_B1_SEL(_apllcore), \
+ }, \
+}
+
+#define RK3588_CPUB23CLK_RATE(_prate, _apllcore) \
+{ \
+ .prate = _prate##U, \
+ .pre_muxs = { \
+ RK3588_CORE_B2_SEL(0), \
+ RK3588_CORE_B3_SEL(0), \
+ }, \
+ .post_muxs = { \
+ RK3588_CORE_B2_SEL(_apllcore), \
+ RK3588_CORE_B3_SEL(_apllcore), \
+ }, \
+}
+
+#define RK3588_CPULCLK_RATE(_prate, _apllcore, _seldsu, _divdsu) \
+{ \
+ .prate = _prate##U, \
+ .pre_muxs = { \
+ RK3588_CORE_L_SEL0(0, 0), \
+ RK3588_CORE_L_SEL0(1, 0), \
+ RK3588_CORE_L_SEL1(3, 2), \
+ RK3588_CORE_L_SEL2(2, 3, 3), \
+ RK3588_CORE_L_SEL3(4), \
+ RK3588_CORE_L_SEL4(4, 4), \
+ }, \
+ .post_muxs = { \
+ RK3588_CORE_L_SEL0(0, _apllcore), \
+ RK3588_CORE_L_SEL0(1, _apllcore), \
+ RK3588_CORE_L_SEL1(_seldsu, _divdsu), \
+ }, \
+}
+
+static struct rockchip_cpuclk_rate_table rk3588_cpub0clk_rates[] __initdata = {
+ RK3588_CPUB01CLK_RATE(2496000000, 1),
+ RK3588_CPUB01CLK_RATE(2400000000, 1),
+ RK3588_CPUB01CLK_RATE(2304000000, 1),
+ RK3588_CPUB01CLK_RATE(2208000000, 1),
+ RK3588_CPUB01CLK_RATE(2184000000, 1),
+ RK3588_CPUB01CLK_RATE(2088000000, 1),
+ RK3588_CPUB01CLK_RATE(2040000000, 1),
+ RK3588_CPUB01CLK_RATE(2016000000, 1),
+ RK3588_CPUB01CLK_RATE(1992000000, 1),
+ RK3588_CPUB01CLK_RATE(1896000000, 1),
+ RK3588_CPUB01CLK_RATE(1800000000, 1),
+ RK3588_CPUB01CLK_RATE(1704000000, 0),
+ RK3588_CPUB01CLK_RATE(1608000000, 0),
+ RK3588_CPUB01CLK_RATE(1584000000, 0),
+ RK3588_CPUB01CLK_RATE(1560000000, 0),
+ RK3588_CPUB01CLK_RATE(1536000000, 0),
+ RK3588_CPUB01CLK_RATE(1512000000, 0),
+ RK3588_CPUB01CLK_RATE(1488000000, 0),
+ RK3588_CPUB01CLK_RATE(1464000000, 0),
+ RK3588_CPUB01CLK_RATE(1440000000, 0),
+ RK3588_CPUB01CLK_RATE(1416000000, 0),
+ RK3588_CPUB01CLK_RATE(1392000000, 0),
+ RK3588_CPUB01CLK_RATE(1368000000, 0),
+ RK3588_CPUB01CLK_RATE(1344000000, 0),
+ RK3588_CPUB01CLK_RATE(1320000000, 0),
+ RK3588_CPUB01CLK_RATE(1296000000, 0),
+ RK3588_CPUB01CLK_RATE(1272000000, 0),
+ RK3588_CPUB01CLK_RATE(1248000000, 0),
+ RK3588_CPUB01CLK_RATE(1224000000, 0),
+ RK3588_CPUB01CLK_RATE(1200000000, 0),
+ RK3588_CPUB01CLK_RATE(1104000000, 0),
+ RK3588_CPUB01CLK_RATE(1008000000, 0),
+ RK3588_CPUB01CLK_RATE(912000000, 0),
+ RK3588_CPUB01CLK_RATE(816000000, 0),
+ RK3588_CPUB01CLK_RATE(696000000, 0),
+ RK3588_CPUB01CLK_RATE(600000000, 0),
+ RK3588_CPUB01CLK_RATE(408000000, 0),
+ RK3588_CPUB01CLK_RATE(312000000, 0),
+ RK3588_CPUB01CLK_RATE(216000000, 0),
+ RK3588_CPUB01CLK_RATE(96000000, 0),
+};
+
+static const struct rockchip_cpuclk_reg_data rk3588_cpub0clk_data = {
+ .core_reg[0] = RK3588_BIGCORE0_CLKSEL_CON(0),
+ .div_core_shift[0] = 8,
+ .div_core_mask[0] = 0x1f,
+ .core_reg[1] = RK3588_BIGCORE0_CLKSEL_CON(1),
+ .div_core_shift[1] = 0,
+ .div_core_mask[1] = 0x1f,
+ .num_cores = 2,
+ .mux_core_alt = 1,
+ .mux_core_main = 2,
+ .mux_core_shift = 6,
+ .mux_core_mask = 0x3,
+};
+
+static struct rockchip_cpuclk_rate_table rk3588_cpub1clk_rates[] __initdata = {
+ RK3588_CPUB23CLK_RATE(2496000000, 1),
+ RK3588_CPUB23CLK_RATE(2400000000, 1),
+ RK3588_CPUB23CLK_RATE(2304000000, 1),
+ RK3588_CPUB23CLK_RATE(2208000000, 1),
+ RK3588_CPUB23CLK_RATE(2184000000, 1),
+ RK3588_CPUB23CLK_RATE(2088000000, 1),
+ RK3588_CPUB23CLK_RATE(2040000000, 1),
+ RK3588_CPUB23CLK_RATE(2016000000, 1),
+ RK3588_CPUB23CLK_RATE(1992000000, 1),
+ RK3588_CPUB23CLK_RATE(1896000000, 1),
+ RK3588_CPUB23CLK_RATE(1800000000, 1),
+ RK3588_CPUB23CLK_RATE(1704000000, 0),
+ RK3588_CPUB23CLK_RATE(1608000000, 0),
+ RK3588_CPUB23CLK_RATE(1584000000, 0),
+ RK3588_CPUB23CLK_RATE(1560000000, 0),
+ RK3588_CPUB23CLK_RATE(1536000000, 0),
+ RK3588_CPUB23CLK_RATE(1512000000, 0),
+ RK3588_CPUB23CLK_RATE(1488000000, 0),
+ RK3588_CPUB23CLK_RATE(1464000000, 0),
+ RK3588_CPUB23CLK_RATE(1440000000, 0),
+ RK3588_CPUB23CLK_RATE(1416000000, 0),
+ RK3588_CPUB23CLK_RATE(1392000000, 0),
+ RK3588_CPUB23CLK_RATE(1368000000, 0),
+ RK3588_CPUB23CLK_RATE(1344000000, 0),
+ RK3588_CPUB23CLK_RATE(1320000000, 0),
+ RK3588_CPUB23CLK_RATE(1296000000, 0),
+ RK3588_CPUB23CLK_RATE(1272000000, 0),
+ RK3588_CPUB23CLK_RATE(1248000000, 0),
+ RK3588_CPUB23CLK_RATE(1224000000, 0),
+ RK3588_CPUB23CLK_RATE(1200000000, 0),
+ RK3588_CPUB23CLK_RATE(1104000000, 0),
+ RK3588_CPUB23CLK_RATE(1008000000, 0),
+ RK3588_CPUB23CLK_RATE(912000000, 0),
+ RK3588_CPUB23CLK_RATE(816000000, 0),
+ RK3588_CPUB23CLK_RATE(696000000, 0),
+ RK3588_CPUB23CLK_RATE(600000000, 0),
+ RK3588_CPUB23CLK_RATE(408000000, 0),
+ RK3588_CPUB23CLK_RATE(312000000, 0),
+ RK3588_CPUB23CLK_RATE(216000000, 0),
+ RK3588_CPUB23CLK_RATE(96000000, 0),
+};
+
+static const struct rockchip_cpuclk_reg_data rk3588_cpub1clk_data = {
+ .core_reg[0] = RK3588_BIGCORE1_CLKSEL_CON(0),
+ .div_core_shift[0] = 8,
+ .div_core_mask[0] = 0x1f,
+ .core_reg[1] = RK3588_BIGCORE1_CLKSEL_CON(1),
+ .div_core_shift[1] = 0,
+ .div_core_mask[1] = 0x1f,
+ .num_cores = 2,
+ .mux_core_alt = 1,
+ .mux_core_main = 2,
+ .mux_core_shift = 6,
+ .mux_core_mask = 0x3,
+};
+
+static struct rockchip_cpuclk_rate_table rk3588_cpulclk_rates[] __initdata = {
+ RK3588_CPULCLK_RATE(2208000000, 1, 3, 1),
+ RK3588_CPULCLK_RATE(2184000000, 1, 3, 1),
+ RK3588_CPULCLK_RATE(2088000000, 1, 3, 1),
+ RK3588_CPULCLK_RATE(2040000000, 1, 3, 1),
+ RK3588_CPULCLK_RATE(2016000000, 1, 3, 1),
+ RK3588_CPULCLK_RATE(1992000000, 1, 3, 1),
+ RK3588_CPULCLK_RATE(1896000000, 1, 3, 1),
+ RK3588_CPULCLK_RATE(1800000000, 1, 3, 1),
+ RK3588_CPULCLK_RATE(1704000000, 0, 3, 1),
+ RK3588_CPULCLK_RATE(1608000000, 0, 3, 1),
+ RK3588_CPULCLK_RATE(1584000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1560000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1536000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1512000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1488000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1464000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1440000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1416000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1392000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1368000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1344000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1320000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1296000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1272000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1248000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1224000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1200000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1104000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(1008000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(912000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(816000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(696000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(600000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(408000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(312000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(216000000, 0, 2, 1),
+ RK3588_CPULCLK_RATE(96000000, 0, 2, 1),
+};
+
+static const struct rockchip_cpuclk_reg_data rk3588_cpulclk_data = {
+ .core_reg[0] = RK3588_DSU_CLKSEL_CON(6),
+ .div_core_shift[0] = 0,
+ .div_core_mask[0] = 0x1f,
+ .core_reg[1] = RK3588_DSU_CLKSEL_CON(6),
+ .div_core_shift[1] = 7,
+ .div_core_mask[1] = 0x1f,
+ .core_reg[2] = RK3588_DSU_CLKSEL_CON(7),
+ .div_core_shift[2] = 0,
+ .div_core_mask[2] = 0x1f,
+ .core_reg[3] = RK3588_DSU_CLKSEL_CON(7),
+ .div_core_shift[3] = 7,
+ .div_core_mask[3] = 0x1f,
+ .num_cores = 4,
+ .mux_core_reg = RK3588_DSU_CLKSEL_CON(5),
+ .mux_core_alt = 1,
+ .mux_core_main = 2,
+ .mux_core_shift = 14,
+ .mux_core_mask = 0x3,
+};
+
+PNAME(mux_pll_p) = { "xin24m", "xin32k" };
+PNAME(mux_armclkl_p) = { "xin24m", "gpll", "lpll" };
+PNAME(mux_armclkb01_p) = { "xin24m", "gpll", "b0pll",};
+PNAME(mux_armclkb23_p) = { "xin24m", "gpll", "b1pll",};
+PNAME(b0pll_b1pll_lpll_gpll_p) = { "b0pll", "b1pll", "lpll", "gpll" };
+PNAME(gpll_24m_p) = { "gpll", "xin24m" };
+PNAME(gpll_aupll_p) = { "gpll", "aupll" };
+PNAME(gpll_lpll_p) = { "gpll", "lpll" };
+PNAME(gpll_cpll_p) = { "gpll", "cpll" };
+PNAME(gpll_spll_p) = { "gpll", "spll" };
+PNAME(gpll_cpll_24m_p) = { "gpll", "cpll", "xin24m"};
+PNAME(gpll_cpll_aupll_p) = { "gpll", "cpll", "aupll"};
+PNAME(gpll_cpll_npll_p) = { "gpll", "cpll", "npll"};
+PNAME(gpll_cpll_npll_v0pll_p) = { "gpll", "cpll", "npll", "v0pll"};
+PNAME(gpll_cpll_24m_spll_p) = { "gpll", "cpll", "xin24m", "spll" };
+PNAME(gpll_cpll_aupll_spll_p) = { "gpll", "cpll", "aupll", "spll" };
+PNAME(gpll_cpll_aupll_npll_p) = { "gpll", "cpll", "aupll", "npll" };
+PNAME(gpll_cpll_v0pll_aupll_p) = { "gpll", "cpll", "v0pll", "aupll" };
+PNAME(gpll_cpll_v0pll_spll_p) = { "gpll", "cpll", "v0pll", "spll" };
+PNAME(gpll_cpll_aupll_npll_spll_p) = { "gpll", "cpll", "aupll", "npll", "spll" };
+PNAME(gpll_cpll_dmyaupll_npll_spll_p) = { "gpll", "cpll", "dummy_aupll", "npll", "spll" };
+PNAME(gpll_cpll_npll_aupll_spll_p) = { "gpll", "cpll", "npll", "aupll", "spll" };
+PNAME(gpll_cpll_npll_1000m_p) = { "gpll", "cpll", "npll", "clk_1000m_src" };
+PNAME(mux_24m_spll_gpll_cpll_p) = { "xin24m", "spll", "gpll", "cpll" };
+PNAME(mux_24m_32k_p) = { "xin24m", "xin32k" };
+PNAME(mux_24m_100m_p) = { "xin24m", "clk_100m_src" };
+PNAME(mux_200m_100m_p) = { "clk_200m_src", "clk_100m_src" };
+PNAME(mux_100m_50m_24m_p) = { "clk_100m_src", "clk_50m_src", "xin24m" };
+PNAME(mux_150m_50m_24m_p) = { "clk_150m_src", "clk_50m_src", "xin24m" };
+PNAME(mux_150m_100m_24m_p) = { "clk_150m_src", "clk_100m_src", "xin24m" };
+PNAME(mux_200m_150m_24m_p) = { "clk_200m_src", "clk_150m_src", "xin24m" };
+PNAME(mux_150m_100m_50m_24m_p) = { "clk_150m_src", "clk_100m_src", "clk_50m_src", "xin24m" };
+PNAME(mux_200m_100m_50m_24m_p) = { "clk_200m_src", "clk_100m_src", "clk_50m_src", "xin24m" };
+PNAME(mux_300m_200m_100m_24m_p) = { "clk_300m_src", "clk_200m_src", "clk_100m_src", "xin24m" };
+PNAME(mux_700m_400m_200m_24m_p) = { "clk_700m_src", "clk_400m_src", "clk_200m_src", "xin24m" };
+PNAME(mux_500m_250m_100m_24m_p) = { "clk_500m_src", "clk_250m_src", "clk_100m_src", "xin24m" };
+PNAME(mux_500m_300m_100m_24m_p) = { "clk_500m_src", "clk_300m_src", "clk_100m_src", "xin24m" };
+PNAME(mux_400m_200m_100m_24m_p) = { "clk_400m_src", "clk_200m_src", "clk_100m_src", "xin24m" };
+PNAME(clk_i2s2_2ch_p) = { "clk_i2s2_2ch_src", "clk_i2s2_2ch_frac", "i2s2_mclkin", "xin12m" };
+PNAME(i2s2_2ch_mclkout_p) = { "mclk_i2s2_2ch", "xin12m" };
+PNAME(clk_i2s3_2ch_p) = { "clk_i2s3_2ch_src", "clk_i2s3_2ch_frac", "i2s3_mclkin", "xin12m" };
+PNAME(i2s3_2ch_mclkout_p) = { "mclk_i2s3_2ch", "xin12m" };
+PNAME(clk_i2s0_8ch_tx_p) = { "clk_i2s0_8ch_tx_src", "clk_i2s0_8ch_tx_frac", "i2s0_mclkin", "xin12m" };
+PNAME(clk_i2s0_8ch_rx_p) = { "clk_i2s0_8ch_rx_src", "clk_i2s0_8ch_rx_frac", "i2s0_mclkin", "xin12m" };
+PNAME(i2s0_8ch_mclkout_p) = { "mclk_i2s0_8ch_tx", "mclk_i2s0_8ch_rx", "xin12m" };
+PNAME(clk_i2s1_8ch_tx_p) = { "clk_i2s1_8ch_tx_src", "clk_i2s1_8ch_tx_frac", "i2s1_mclkin", "xin12m" };
+PNAME(clk_i2s1_8ch_rx_p) = { "clk_i2s1_8ch_rx_src", "clk_i2s1_8ch_rx_frac", "i2s1_mclkin", "xin12m" };
+PNAME(i2s1_8ch_mclkout_p) = { "mclk_i2s1_8ch_tx", "mclk_i2s1_8ch_rx", "xin12m" };
+PNAME(clk_i2s4_8ch_tx_p) = { "clk_i2s4_8ch_tx_src", "clk_i2s4_8ch_tx_frac", "i2s4_mclkin", "xin12m" };
+PNAME(clk_i2s5_8ch_tx_p) = { "clk_i2s5_8ch_tx_src", "clk_i2s5_8ch_tx_frac", "i2s5_mclkin", "xin12m" };
+PNAME(clk_i2s6_8ch_tx_p) = { "clk_i2s6_8ch_tx_src", "clk_i2s6_8ch_tx_frac", "i2s6_mclkin", "xin12m" };
+PNAME(clk_i2s6_8ch_rx_p) = { "clk_i2s6_8ch_rx_src", "clk_i2s6_8ch_rx_frac", "i2s6_mclkin", "xin12m" };
+PNAME(i2s6_8ch_mclkout_p) = { "mclk_i2s6_8ch_tx", "mclk_i2s6_8ch_rx", "xin12m" };
+PNAME(clk_i2s7_8ch_rx_p) = { "clk_i2s7_8ch_rx_src", "clk_i2s7_8ch_rx_frac", "i2s7_mclkin", "xin12m" };
+PNAME(clk_i2s8_8ch_tx_p) = { "clk_i2s8_8ch_tx_src", "clk_i2s8_8ch_tx_frac", "i2s8_mclkin", "xin12m" };
+PNAME(clk_i2s9_8ch_rx_p) = { "clk_i2s9_8ch_rx_src", "clk_i2s9_8ch_rx_frac", "i2s9_mclkin", "xin12m" };
+PNAME(clk_i2s10_8ch_rx_p) = { "clk_i2s10_8ch_rx_src", "clk_i2s10_8ch_rx_frac", "i2s10_mclkin", "xin12m" };
+PNAME(clk_spdif0_p) = { "clk_spdif0_src", "clk_spdif0_frac", "xin12m" };
+PNAME(clk_spdif1_p) = { "clk_spdif1_src", "clk_spdif1_frac", "xin12m" };
+PNAME(clk_spdif2_dp0_p) = { "clk_spdif2_dp0_src", "clk_spdif2_dp0_frac", "xin12m" };
+PNAME(clk_spdif3_p) = { "clk_spdif3_src", "clk_spdif3_frac", "xin12m" };
+PNAME(clk_spdif4_p) = { "clk_spdif4_src", "clk_spdif4_frac", "xin12m" };
+PNAME(clk_spdif5_dp1_p) = { "clk_spdif5_dp1_src", "clk_spdif5_dp1_frac", "xin12m" };
+PNAME(clk_uart0_p) = { "clk_uart0_src", "clk_uart0_frac", "xin24m" };
+PNAME(clk_uart1_p) = { "clk_uart1_src", "clk_uart1_frac", "xin24m" };
+PNAME(clk_uart2_p) = { "clk_uart2_src", "clk_uart2_frac", "xin24m" };
+PNAME(clk_uart3_p) = { "clk_uart3_src", "clk_uart3_frac", "xin24m" };
+PNAME(clk_uart4_p) = { "clk_uart4_src", "clk_uart4_frac", "xin24m" };
+PNAME(clk_uart5_p) = { "clk_uart5_src", "clk_uart5_frac", "xin24m" };
+PNAME(clk_uart6_p) = { "clk_uart6_src", "clk_uart6_frac", "xin24m" };
+PNAME(clk_uart7_p) = { "clk_uart7_src", "clk_uart7_frac", "xin24m" };
+PNAME(clk_uart8_p) = { "clk_uart8_src", "clk_uart8_frac", "xin24m" };
+PNAME(clk_uart9_p) = { "clk_uart9_src", "clk_uart9_frac", "xin24m" };
+PNAME(clk_gmac0_ptp_ref_p) = { "cpll", "clk_gmac0_ptpref_io" };
+PNAME(clk_gmac1_ptp_ref_p) = { "cpll", "clk_gmac1_ptpref_io" };
+PNAME(clk_hdmirx_aud_p) = { "clk_hdmirx_aud_src", "clk_hdmirx_aud_frac" };
+PNAME(aclk_hdcp1_root_p) = { "gpll", "cpll", "clk_hdmitrx_refsrc" };
+PNAME(aclk_vop_sub_src_p) = { "aclk_vop_root", "aclk_vop_div2_src" };
+PNAME(dclk_vop0_p) = { "dclk_vop0_src", "clk_hdmiphy_pixel0", "clk_hdmiphy_pixel1" };
+PNAME(dclk_vop1_p) = { "dclk_vop1_src", "clk_hdmiphy_pixel0", "clk_hdmiphy_pixel1" };
+PNAME(dclk_vop2_p) = { "dclk_vop2_src", "clk_hdmiphy_pixel0", "clk_hdmiphy_pixel1" };
+PNAME(pmu_200m_100m_p) = { "clk_pmu1_200m_src", "clk_pmu1_100m_src" };
+PNAME(pmu_300m_24m_p) = { "clk_300m_src", "xin24m" };
+PNAME(pmu_400m_24m_p) = { "clk_400m_src", "xin24m" };
+PNAME(pmu_100m_50m_24m_src_p) = { "clk_pmu1_100m_src", "clk_pmu1_50m_src", "xin24m" };
+PNAME(pmu_24m_32k_100m_src_p) = { "xin24m", "32k", "clk_pmu1_100m_src" };
+PNAME(hclk_pmu1_root_p) = { "clk_pmu1_200m_src", "clk_pmu1_100m_src", "clk_pmu1_50m_src", "xin24m" };
+PNAME(hclk_pmu_cm0_root_p) = { "clk_pmu1_400m_src", "clk_pmu1_200m_src", "clk_pmu1_100m_src", "xin24m" };
+PNAME(mclk_pdm0_p) = { "clk_pmu1_300m_src", "clk_pmu1_200m_src" };
+PNAME(mux_24m_ppll_spll_p) = { "xin24m", "ppll", "spll" };
+PNAME(mux_24m_ppll_p) = { "xin24m", "ppll" };
+PNAME(clk_ref_pipe_phy0_p) = { "clk_ref_pipe_phy0_osc_src", "clk_ref_pipe_phy0_pll_src" };
+PNAME(clk_ref_pipe_phy1_p) = { "clk_ref_pipe_phy1_osc_src", "clk_ref_pipe_phy1_pll_src" };
+PNAME(clk_ref_pipe_phy2_p) = { "clk_ref_pipe_phy2_osc_src", "clk_ref_pipe_phy2_pll_src" };
+
+#define MFLAGS CLK_MUX_HIWORD_MASK
+#define DFLAGS CLK_DIVIDER_HIWORD_MASK
+#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
+
+static struct rockchip_clk_branch rk3588_i2s0_8ch_tx_fracmux __initdata =
+ MUX(CLK_I2S0_8CH_TX, "clk_i2s0_8ch_tx", clk_i2s0_8ch_tx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(26), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s0_8ch_rx_fracmux __initdata =
+ MUX(CLK_I2S0_8CH_RX, "clk_i2s0_8ch_rx", clk_i2s0_8ch_rx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(28), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s1_8ch_tx_fracmux __initdata =
+ MUX(CLK_I2S1_8CH_TX, "clk_i2s1_8ch_tx", clk_i2s1_8ch_tx_p, CLK_SET_RATE_PARENT,
+ RK3588_PMU_CLKSEL_CON(7), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s1_8ch_rx_fracmux __initdata =
+ MUX(CLK_I2S1_8CH_RX, "clk_i2s1_8ch_rx", clk_i2s1_8ch_rx_p, CLK_SET_RATE_PARENT,
+ RK3588_PMU_CLKSEL_CON(9), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s2_2ch_fracmux __initdata =
+ MUX(CLK_I2S2_2CH, "clk_i2s2_2ch", clk_i2s2_2ch_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(30), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s3_2ch_fracmux __initdata =
+ MUX(CLK_I2S3_2CH, "clk_i2s3_2ch", clk_i2s3_2ch_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(32), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s4_8ch_tx_fracmux __initdata =
+ MUX(CLK_I2S4_8CH_TX, "clk_i2s4_8ch_tx", clk_i2s4_8ch_tx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(120), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s5_8ch_tx_fracmux __initdata =
+ MUX(CLK_I2S5_8CH_TX, "clk_i2s5_8ch_tx", clk_i2s5_8ch_tx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(142), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s6_8ch_tx_fracmux __initdata =
+ MUX(CLK_I2S6_8CH_TX, "clk_i2s6_8ch_tx", clk_i2s6_8ch_tx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(146), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s6_8ch_rx_fracmux __initdata =
+ MUX(CLK_I2S6_8CH_RX, "clk_i2s6_8ch_rx", clk_i2s6_8ch_rx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(148), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s7_8ch_rx_fracmux __initdata =
+ MUX(CLK_I2S7_8CH_RX, "clk_i2s7_8ch_rx", clk_i2s7_8ch_rx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(131), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s8_8ch_tx_fracmux __initdata =
+ MUX(CLK_I2S8_8CH_TX, "clk_i2s8_8ch_tx", clk_i2s8_8ch_tx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(122), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s9_8ch_rx_fracmux __initdata =
+ MUX(CLK_I2S9_8CH_RX, "clk_i2s9_8ch_rx", clk_i2s9_8ch_rx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(155), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_i2s10_8ch_rx_fracmux __initdata =
+ MUX(CLK_I2S10_8CH_RX, "clk_i2s10_8ch_rx", clk_i2s10_8ch_rx_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(157), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_spdif0_fracmux __initdata =
+ MUX(CLK_SPDIF0, "clk_spdif0", clk_spdif0_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(34), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_spdif1_fracmux __initdata =
+ MUX(CLK_SPDIF1, "clk_spdif1", clk_spdif1_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(36), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_spdif2_dp0_fracmux __initdata =
+ MUX(CLK_SPDIF2_DP0, "clk_spdif2_dp0", clk_spdif2_dp0_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(124), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_spdif3_fracmux __initdata =
+ MUX(CLK_SPDIF3, "clk_spdif3", clk_spdif3_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(150), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_spdif4_fracmux __initdata =
+ MUX(CLK_SPDIF4, "clk_spdif4", clk_spdif4_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(152), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_spdif5_dp1_fracmux __initdata =
+ MUX(CLK_SPDIF5_DP1, "clk_spdif5_dp1", clk_spdif5_dp1_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(126), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart0_fracmux __initdata =
+ MUX(CLK_UART0, "clk_uart0", clk_uart0_p, CLK_SET_RATE_PARENT,
+ RK3588_PMU_CLKSEL_CON(5), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart1_fracmux __initdata =
+ MUX(CLK_UART1, "clk_uart1", clk_uart1_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(43), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart2_fracmux __initdata =
+ MUX(CLK_UART2, "clk_uart2", clk_uart2_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(45), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart3_fracmux __initdata =
+ MUX(CLK_UART3, "clk_uart3", clk_uart3_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(47), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart4_fracmux __initdata =
+ MUX(CLK_UART4, "clk_uart4", clk_uart4_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(49), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart5_fracmux __initdata =
+ MUX(CLK_UART5, "clk_uart5", clk_uart5_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(51), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart6_fracmux __initdata =
+ MUX(CLK_UART6, "clk_uart6", clk_uart6_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(53), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart7_fracmux __initdata =
+ MUX(CLK_UART7, "clk_uart7", clk_uart7_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(55), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart8_fracmux __initdata =
+ MUX(CLK_UART8, "clk_uart8", clk_uart8_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(57), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_uart9_fracmux __initdata =
+ MUX(CLK_UART9, "clk_uart9", clk_uart9_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(59), 0, 2, MFLAGS);
+
+static struct rockchip_clk_branch rk3588_hdmirx_aud_fracmux __initdata =
+ MUX(CLK_HDMIRX_AUD_P_MUX, "clk_hdmirx_aud_mux", clk_hdmirx_aud_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(140), 0, 1, MFLAGS);
+
+static struct rockchip_pll_clock rk3588_pll_clks[] __initdata = {
+ [b0pll] = PLL(pll_rk3588_core, PLL_B0PLL, "b0pll", mux_pll_p,
+ CLK_IGNORE_UNUSED, RK3588_B0_PLL_CON(0),
+ RK3588_B0_PLL_MODE_CON0, 0, 15, 0, rk3588_pll_rates),
+ [b1pll] = PLL(pll_rk3588_core, PLL_B1PLL, "b1pll", mux_pll_p,
+ CLK_IGNORE_UNUSED, RK3588_B1_PLL_CON(8),
+ RK3588_B1_PLL_MODE_CON0, 0, 15, 0, rk3588_pll_rates),
+ [lpll] = PLL(pll_rk3588_core, PLL_LPLL, "lpll", mux_pll_p,
+ CLK_IGNORE_UNUSED, RK3588_LPLL_CON(16),
+ RK3588_LPLL_MODE_CON0, 0, 15, 0, rk3588_pll_rates),
+ [v0pll] = PLL(pll_rk3588, PLL_V0PLL, "v0pll", mux_pll_p,
+ 0, RK3588_PLL_CON(88),
+ RK3588_MODE_CON0, 4, 15, 0, rk3588_pll_rates),
+ [aupll] = PLL(pll_rk3588, PLL_AUPLL, "aupll", mux_pll_p,
+ 0, RK3588_PLL_CON(96),
+ RK3588_MODE_CON0, 6, 15, 0, rk3588_pll_rates),
+ [cpll] = PLL(pll_rk3588, PLL_CPLL, "cpll", mux_pll_p,
+ CLK_IGNORE_UNUSED, RK3588_PLL_CON(104),
+ RK3588_MODE_CON0, 8, 15, 0, rk3588_pll_rates),
+ [gpll] = PLL(pll_rk3588, PLL_GPLL, "gpll", mux_pll_p,
+ CLK_IGNORE_UNUSED, RK3588_PLL_CON(112),
+ RK3588_MODE_CON0, 2, 15, 0, rk3588_pll_rates),
+ [npll] = PLL(pll_rk3588, PLL_NPLL, "npll", mux_pll_p,
+ 0, RK3588_PLL_CON(120),
+ RK3588_MODE_CON0, 0, 15, 0, rk3588_pll_rates),
+ [ppll] = PLL(pll_rk3588_core, PLL_PPLL, "ppll", mux_pll_p,
+ CLK_IGNORE_UNUSED, RK3588_PMU_PLL_CON(128),
+ RK3588_MODE_CON0, 10, 15, 0, rk3588_pll_rates),
+};
+
+static struct rockchip_clk_branch rk3588_clk_branches[] __initdata = {
+ /*
+ * CRU Clock-Architecture
+ */
+ /* fixed */
+ FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
+
+ /* top */
+ COMPOSITE(CLK_50M_SRC, "clk_50m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(0), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 0, GFLAGS),
+ COMPOSITE(CLK_100M_SRC, "clk_100m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(0), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 1, GFLAGS),
+ COMPOSITE(CLK_150M_SRC, "clk_150m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(1), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 2, GFLAGS),
+ COMPOSITE(CLK_200M_SRC, "clk_200m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(1), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 3, GFLAGS),
+ COMPOSITE(CLK_250M_SRC, "clk_250m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(2), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 4, GFLAGS),
+ COMPOSITE(CLK_300M_SRC, "clk_300m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(2), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 5, GFLAGS),
+ COMPOSITE(CLK_350M_SRC, "clk_350m_src", gpll_spll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(3), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 6, GFLAGS),
+ COMPOSITE(CLK_400M_SRC, "clk_400m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(3), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 7, GFLAGS),
+ COMPOSITE_HALFDIV(CLK_450M_SRC, "clk_450m_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(4), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 8, GFLAGS),
+ COMPOSITE(CLK_500M_SRC, "clk_500m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(4), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 9, GFLAGS),
+ COMPOSITE(CLK_600M_SRC, "clk_600m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(5), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 10, GFLAGS),
+ COMPOSITE(CLK_650M_SRC, "clk_650m_src", gpll_lpll_p, 0,
+ RK3588_CLKSEL_CON(5), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 11, GFLAGS),
+ COMPOSITE(CLK_700M_SRC, "clk_700m_src", gpll_spll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(6), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 12, GFLAGS),
+ COMPOSITE(CLK_800M_SRC, "clk_800m_src", gpll_aupll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(6), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 13, GFLAGS),
+ COMPOSITE_HALFDIV(CLK_1000M_SRC, "clk_1000m_src", gpll_cpll_npll_v0pll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(7), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 14, GFLAGS),
+ COMPOSITE(CLK_1200M_SRC, "clk_1200m_src", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(7), 12, 1, MFLAGS, 7, 5, DFLAGS,
+ RK3588_CLKGATE_CON(0), 15, GFLAGS),
+ COMPOSITE_NODIV(ACLK_TOP_M300_ROOT, "aclk_top_m300_root", mux_300m_200m_100m_24m_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(9), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(1), 10, GFLAGS),
+ COMPOSITE_NODIV(ACLK_TOP_M500_ROOT, "aclk_top_m500_root", mux_500m_300m_100m_24m_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(9), 2, 2, MFLAGS,
+ RK3588_CLKGATE_CON(1), 11, GFLAGS),
+ COMPOSITE_NODIV(ACLK_TOP_M400_ROOT, "aclk_top_m400_root", mux_400m_200m_100m_24m_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(9), 4, 2, MFLAGS,
+ RK3588_CLKGATE_CON(1), 12, GFLAGS),
+ COMPOSITE_NODIV(ACLK_TOP_S200_ROOT, "aclk_top_s200_root", mux_200m_100m_50m_24m_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(9), 6, 2, MFLAGS,
+ RK3588_CLKGATE_CON(1), 13, GFLAGS),
+ COMPOSITE_NODIV(ACLK_TOP_S400_ROOT, "aclk_top_s400_root", mux_400m_200m_100m_24m_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(9), 8, 2, MFLAGS,
+ RK3588_CLKGATE_CON(1), 14, GFLAGS),
+ COMPOSITE(ACLK_TOP_ROOT, "aclk_top_root", gpll_cpll_aupll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(8), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(1), 0, GFLAGS),
+ COMPOSITE_NODIV(PCLK_TOP_ROOT, "pclk_top_root", mux_100m_50m_24m_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(8), 7, 2, MFLAGS,
+ RK3588_CLKGATE_CON(1), 1, GFLAGS),
+ COMPOSITE(ACLK_LOW_TOP_ROOT, "aclk_low_top_root", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(8), 14, 1, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(1), 2, GFLAGS),
+ COMPOSITE(CLK_MIPI_CAMARAOUT_M0, "clk_mipi_camaraout_m0", mux_24m_spll_gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(18), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3588_CLKGATE_CON(5), 9, GFLAGS),
+ COMPOSITE(CLK_MIPI_CAMARAOUT_M1, "clk_mipi_camaraout_m1", mux_24m_spll_gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(19), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3588_CLKGATE_CON(5), 10, GFLAGS),
+ COMPOSITE(CLK_MIPI_CAMARAOUT_M2, "clk_mipi_camaraout_m2", mux_24m_spll_gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(20), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3588_CLKGATE_CON(5), 11, GFLAGS),
+ COMPOSITE(CLK_MIPI_CAMARAOUT_M3, "clk_mipi_camaraout_m3", mux_24m_spll_gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(21), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3588_CLKGATE_CON(5), 12, GFLAGS),
+ COMPOSITE(CLK_MIPI_CAMARAOUT_M4, "clk_mipi_camaraout_m4", mux_24m_spll_gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(22), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3588_CLKGATE_CON(5), 13, GFLAGS),
+ COMPOSITE(MCLK_GMAC0_OUT, "mclk_gmac0_out", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(15), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3588_CLKGATE_CON(5), 3, GFLAGS),
+ COMPOSITE(REFCLKO25M_ETH0_OUT, "refclko25m_eth0_out", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(15), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ RK3588_CLKGATE_CON(5), 4, GFLAGS),
+ COMPOSITE(REFCLKO25M_ETH1_OUT, "refclko25m_eth1_out", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(16), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3588_CLKGATE_CON(5), 5, GFLAGS),
+ COMPOSITE(CLK_CIFOUT_OUT, "clk_cifout_out", gpll_cpll_24m_spll_p, 0,
+ RK3588_CLKSEL_CON(17), 8, 2, MFLAGS, 0, 8, DFLAGS,
+ RK3588_CLKGATE_CON(5), 6, GFLAGS),
+ GATE(PCLK_MIPI_DCPHY0, "pclk_mipi_dcphy0", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(3), 14, GFLAGS),
+ GATE(PCLK_MIPI_DCPHY1, "pclk_mipi_dcphy1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(4), 3, GFLAGS),
+ GATE(PCLK_CSIPHY0, "pclk_csiphy0", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(1), 6, GFLAGS),
+ GATE(PCLK_CSIPHY1, "pclk_csiphy1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(1), 8, GFLAGS),
+ GATE(PCLK_CRU, "pclk_cru", "pclk_top_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(5), 0, GFLAGS),
+
+ /* bigcore0 */
+ COMPOSITE_NODIV(PCLK_BIGCORE0_ROOT, "pclk_bigcore0_root", mux_100m_50m_24m_p,
+ CLK_IS_CRITICAL,
+ RK3588_BIGCORE0_CLKSEL_CON(2), 0, 2, MFLAGS,
+ RK3588_BIGCORE0_CLKGATE_CON(0), 14, GFLAGS),
+ GATE(PCLK_BIGCORE0_PVTM, "pclk_bigcore0_pvtm", "pclk_bigcore0_root", 0,
+ RK3588_BIGCORE0_CLKGATE_CON(1), 0, GFLAGS),
+ GATE(CLK_BIGCORE0_PVTM, "clk_bigcore0_pvtm", "xin24m", 0,
+ RK3588_BIGCORE0_CLKGATE_CON(0), 12, GFLAGS),
+ GATE(CLK_CORE_BIGCORE0_PVTM, "clk_core_bigcore0_pvtm", "armclk_b01", 0,
+ RK3588_BIGCORE0_CLKGATE_CON(0), 13, GFLAGS),
+
+ /* bigcore1 */
+ COMPOSITE_NODIV(PCLK_BIGCORE1_ROOT, "pclk_bigcore1_root", mux_100m_50m_24m_p,
+ CLK_IS_CRITICAL,
+ RK3588_BIGCORE1_CLKSEL_CON(2), 0, 2, MFLAGS,
+ RK3588_BIGCORE1_CLKGATE_CON(0), 14, GFLAGS),
+ GATE(PCLK_BIGCORE1_PVTM, "pclk_bigcore1_pvtm", "pclk_bigcore1_root", 0,
+ RK3588_BIGCORE1_CLKGATE_CON(1), 0, GFLAGS),
+ GATE(CLK_BIGCORE1_PVTM, "clk_bigcore1_pvtm", "xin24m", 0,
+ RK3588_BIGCORE1_CLKGATE_CON(0), 12, GFLAGS),
+ GATE(CLK_CORE_BIGCORE1_PVTM, "clk_core_bigcore1_pvtm", "armclk_b23", 0,
+ RK3588_BIGCORE1_CLKGATE_CON(0), 13, GFLAGS),
+
+ /* dsu */
+ COMPOSITE(0, "sclk_dsu", b0pll_b1pll_lpll_gpll_p, CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(0), 12, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_DSU_CLKGATE_CON(0), 4, GFLAGS),
+ COMPOSITE_NOMUX(0, "atclk_dsu", "sclk_dsu", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(3), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3588_DSU_CLKGATE_CON(1), 0, GFLAGS),
+ COMPOSITE_NOMUX(0, "gicclk_dsu", "sclk_dsu", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(3), 5, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3588_DSU_CLKGATE_CON(1), 1, GFLAGS),
+ COMPOSITE_NOMUX(0, "aclkmp_dsu", "sclk_dsu", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(1), 11, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3588_DSU_CLKGATE_CON(0), 12, GFLAGS),
+ COMPOSITE_NOMUX(0, "aclkm_dsu", "sclk_dsu", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(1), 1, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3588_DSU_CLKGATE_CON(0), 8, GFLAGS),
+ COMPOSITE_NOMUX(0, "aclks_dsu", "sclk_dsu", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(1), 6, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3588_DSU_CLKGATE_CON(0), 9, GFLAGS),
+ COMPOSITE_NOMUX(0, "periph_dsu", "sclk_dsu", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(2), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3588_DSU_CLKGATE_CON(0), 13, GFLAGS),
+ COMPOSITE_NOMUX(0, "cntclk_dsu", "periph_dsu", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(2), 5, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3588_DSU_CLKGATE_CON(0), 14, GFLAGS),
+ COMPOSITE_NOMUX(0, "tsclk_dsu", "periph_dsu", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(2), 10, 5, DFLAGS | CLK_DIVIDER_READ_ONLY,
+ RK3588_DSU_CLKGATE_CON(0), 15, GFLAGS),
+ COMPOSITE_NODIV(PCLK_DSU_S_ROOT, "pclk_dsu_s_root", mux_100m_50m_24m_p, CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(4), 11, 2, MFLAGS,
+ RK3588_DSU_CLKGATE_CON(2), 2, GFLAGS),
+ COMPOSITE(PCLK_DSU_ROOT, "pclk_dsu_root", b0pll_b1pll_lpll_gpll_p, CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(4), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_DSU_CLKGATE_CON(1), 3, GFLAGS),
+ COMPOSITE_NODIV(PCLK_DSU_NS_ROOT, "pclk_dsu_ns_root", mux_100m_50m_24m_p, CLK_IS_CRITICAL,
+ RK3588_DSU_CLKSEL_CON(4), 7, 2, MFLAGS,
+ RK3588_DSU_CLKGATE_CON(1), 4, GFLAGS),
+ GATE(PCLK_LITCORE_PVTM, "pclk_litcore_pvtm", "pclk_dsu_ns_root", 0,
+ RK3588_DSU_CLKGATE_CON(2), 6, GFLAGS),
+ GATE(PCLK_DBG, "pclk_dbg", "pclk_dsu_root", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKGATE_CON(1), 7, GFLAGS),
+ GATE(PCLK_DSU, "pclk_dsu", "pclk_dsu_root", CLK_IS_CRITICAL,
+ RK3588_DSU_CLKGATE_CON(1), 6, GFLAGS),
+ GATE(PCLK_S_DAPLITE, "pclk_s_daplite", "pclk_dsu_ns_root", CLK_IGNORE_UNUSED,
+ RK3588_DSU_CLKGATE_CON(1), 8, GFLAGS),
+ GATE(PCLK_M_DAPLITE, "pclk_m_daplite", "pclk_dsu_root", CLK_IGNORE_UNUSED,
+ RK3588_DSU_CLKGATE_CON(1), 9, GFLAGS),
+ GATE(CLK_LITCORE_PVTM, "clk_litcore_pvtm", "xin24m", 0,
+ RK3588_DSU_CLKGATE_CON(2), 0, GFLAGS),
+ GATE(CLK_CORE_LITCORE_PVTM, "clk_core_litcore_pvtm", "armclk_l", 0,
+ RK3588_DSU_CLKGATE_CON(2), 1, GFLAGS),
+
+ /* audio */
+ COMPOSITE_NODIV(HCLK_AUDIO_ROOT, "hclk_audio_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(24), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(7), 0, GFLAGS),
+ COMPOSITE_NODIV(PCLK_AUDIO_ROOT, "pclk_audio_root", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(24), 2, 2, MFLAGS,
+ RK3588_CLKGATE_CON(7), 1, GFLAGS),
+ GATE(HCLK_I2S2_2CH, "hclk_i2s2_2ch", "hclk_audio_root", 0,
+ RK3588_CLKGATE_CON(7), 12, GFLAGS),
+ GATE(HCLK_I2S3_2CH, "hclk_i2s3_2ch", "hclk_audio_root", 0,
+ RK3588_CLKGATE_CON(7), 13, GFLAGS),
+ COMPOSITE(CLK_I2S2_2CH_SRC, "clk_i2s2_2ch_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(28), 9, 1, MFLAGS, 4, 5, DFLAGS,
+ RK3588_CLKGATE_CON(7), 14, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S2_2CH_FRAC, "clk_i2s2_2ch_frac", "clk_i2s2_2ch_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(29), 0,
+ RK3588_CLKGATE_CON(7), 15, GFLAGS,
+ &rk3588_i2s2_2ch_fracmux),
+ GATE(MCLK_I2S2_2CH, "mclk_i2s2_2ch", "clk_i2s2_2ch", 0,
+ RK3588_CLKGATE_CON(8), 0, GFLAGS),
+ MUX(I2S2_2CH_MCLKOUT, "i2s2_2ch_mclkout", i2s2_2ch_mclkout_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(30), 2, 1, MFLAGS),
+
+ COMPOSITE(CLK_I2S3_2CH_SRC, "clk_i2s3_2ch_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(30), 8, 1, MFLAGS, 3, 5, DFLAGS,
+ RK3588_CLKGATE_CON(8), 1, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S3_2CH_FRAC, "clk_i2s3_2ch_frac", "clk_i2s3_2ch_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(31), 0,
+ RK3588_CLKGATE_CON(8), 2, GFLAGS,
+ &rk3588_i2s3_2ch_fracmux),
+ GATE(MCLK_I2S3_2CH, "mclk_i2s3_2ch", "clk_i2s3_2ch", 0,
+ RK3588_CLKGATE_CON(8), 3, GFLAGS),
+ GATE(CLK_DAC_ACDCDIG, "clk_dac_acdcdig", "mclk_i2s3_2ch", 0,
+ RK3588_CLKGATE_CON(8), 4, GFLAGS),
+ MUX(I2S3_2CH_MCLKOUT, "i2s3_2ch_mclkout", i2s3_2ch_mclkout_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(32), 2, 1, MFLAGS),
+ GATE(PCLK_ACDCDIG, "pclk_acdcdig", "pclk_audio_root", 0,
+ RK3588_CLKGATE_CON(7), 11, GFLAGS),
+ GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_audio_root", 0,
+ RK3588_CLKGATE_CON(7), 4, GFLAGS),
+
+ COMPOSITE(CLK_I2S0_8CH_TX_SRC, "clk_i2s0_8ch_tx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(24), 9, 1, MFLAGS, 4, 5, DFLAGS,
+ RK3588_CLKGATE_CON(7), 5, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S0_8CH_TX_FRAC, "clk_i2s0_8ch_tx_frac", "clk_i2s0_8ch_tx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(25), 0,
+ RK3588_CLKGATE_CON(7), 6, GFLAGS,
+ &rk3588_i2s0_8ch_tx_fracmux),
+ GATE(MCLK_I2S0_8CH_TX, "mclk_i2s0_8ch_tx", "clk_i2s0_8ch_tx", 0,
+ RK3588_CLKGATE_CON(7), 7, GFLAGS),
+
+ COMPOSITE(CLK_I2S0_8CH_RX_SRC, "clk_i2s0_8ch_rx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(26), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(7), 8, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S0_8CH_RX_FRAC, "clk_i2s0_8ch_rx_frac", "clk_i2s0_8ch_rx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(27), 0,
+ RK3588_CLKGATE_CON(7), 9, GFLAGS,
+ &rk3588_i2s0_8ch_rx_fracmux),
+ GATE(MCLK_I2S0_8CH_RX, "mclk_i2s0_8ch_rx", "clk_i2s0_8ch_rx", 0,
+ RK3588_CLKGATE_CON(7), 10, GFLAGS),
+ MUX(I2S0_8CH_MCLKOUT, "i2s0_8ch_mclkout", i2s0_8ch_mclkout_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(28), 2, 2, MFLAGS),
+
+ GATE(HCLK_PDM1, "hclk_pdm1", "hclk_audio_root", 0,
+ RK3588_CLKGATE_CON(9), 6, GFLAGS),
+ COMPOSITE(MCLK_PDM1, "mclk_pdm1", gpll_cpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(36), 7, 2, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(9), 7, GFLAGS),
+
+ GATE(HCLK_SPDIF0, "hclk_spdif0", "hclk_audio_root", 0,
+ RK3588_CLKGATE_CON(8), 14, GFLAGS),
+ COMPOSITE(CLK_SPDIF0_SRC, "clk_spdif0_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(32), 8, 1, MFLAGS, 3, 5, DFLAGS,
+ RK3588_CLKGATE_CON(8), 15, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_SPDIF0_FRAC, "clk_spdif0_frac", "clk_spdif0_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(33), 0,
+ RK3588_CLKGATE_CON(9), 0, GFLAGS,
+ &rk3588_spdif0_fracmux),
+ GATE(MCLK_SPDIF0, "mclk_spdif0", "clk_spdif0", 0,
+ RK3588_CLKGATE_CON(9), 1, GFLAGS),
+
+ GATE(HCLK_SPDIF1, "hclk_spdif1", "hclk_audio_root", 0,
+ RK3588_CLKGATE_CON(9), 2, GFLAGS),
+ COMPOSITE(CLK_SPDIF1_SRC, "clk_spdif1_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(34), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(9), 3, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_SPDIF1_FRAC, "clk_spdif1_frac", "clk_spdif1_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(35), 0,
+ RK3588_CLKGATE_CON(9), 4, GFLAGS,
+ &rk3588_spdif1_fracmux),
+ GATE(MCLK_SPDIF1, "mclk_spdif1", "clk_spdif1", 0,
+ RK3588_CLKGATE_CON(9), 5, GFLAGS),
+
+ COMPOSITE(ACLK_AV1_ROOT, "aclk_av1_root", gpll_cpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(163), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(68), 0, GFLAGS),
+ COMPOSITE_NODIV(PCLK_AV1_ROOT, "pclk_av1_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(163), 7, 2, MFLAGS,
+ RK3588_CLKGATE_CON(68), 3, GFLAGS),
+
+ /* bus */
+ COMPOSITE(ACLK_BUS_ROOT, "aclk_bus_root", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(38), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(10), 0, GFLAGS),
+
+ GATE(PCLK_MAILBOX0, "pclk_mailbox0", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(16), 11, GFLAGS),
+ GATE(PCLK_MAILBOX1, "pclk_mailbox1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(16), 12, GFLAGS),
+ GATE(PCLK_MAILBOX2, "pclk_mailbox2", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(16), 13, GFLAGS),
+ GATE(PCLK_PMU2, "pclk_pmu2", "pclk_top_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(19), 3, GFLAGS),
+ GATE(PCLK_PMUCM0_INTMUX, "pclk_pmucm0_intmux", "pclk_top_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(19), 4, GFLAGS),
+ GATE(PCLK_DDRCM0_INTMUX, "pclk_ddrcm0_intmux", "pclk_top_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(19), 5, GFLAGS),
+
+ GATE(PCLK_PWM1, "pclk_pwm1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(15), 3, GFLAGS),
+ COMPOSITE_NODIV(CLK_PWM1, "clk_pwm1", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(59), 12, 2, MFLAGS,
+ RK3588_CLKGATE_CON(15), 4, GFLAGS),
+ GATE(CLK_PWM1_CAPTURE, "clk_pwm1_capture", "xin24m", 0,
+ RK3588_CLKGATE_CON(15), 5, GFLAGS),
+ GATE(PCLK_PWM2, "pclk_pwm2", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(15), 6, GFLAGS),
+ COMPOSITE_NODIV(CLK_PWM2, "clk_pwm2", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(59), 14, 2, MFLAGS,
+ RK3588_CLKGATE_CON(15), 7, GFLAGS),
+ GATE(CLK_PWM2_CAPTURE, "clk_pwm2_capture", "xin24m", 0,
+ RK3588_CLKGATE_CON(15), 8, GFLAGS),
+ GATE(PCLK_PWM3, "pclk_pwm3", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(15), 9, GFLAGS),
+ COMPOSITE_NODIV(CLK_PWM3, "clk_pwm3", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(60), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(15), 10, GFLAGS),
+ GATE(CLK_PWM3_CAPTURE, "clk_pwm3_capture", "xin24m", 0,
+ RK3588_CLKGATE_CON(15), 11, GFLAGS),
+
+ GATE(PCLK_BUSTIMER0, "pclk_bustimer0", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(15), 12, GFLAGS),
+ GATE(PCLK_BUSTIMER1, "pclk_bustimer1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(15), 13, GFLAGS),
+ COMPOSITE_NODIV(CLK_BUS_TIMER_ROOT, "clk_bus_timer_root", mux_24m_100m_p, 0,
+ RK3588_CLKSEL_CON(60), 2, 1, MFLAGS,
+ RK3588_CLKGATE_CON(15), 14, GFLAGS),
+ GATE(CLK_BUSTIMER0, "clk_bustimer0", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(15), 15, GFLAGS),
+ GATE(CLK_BUSTIMER1, "clk_bustimer1", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 0, GFLAGS),
+ GATE(CLK_BUSTIMER2, "clk_bustimer2", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 1, GFLAGS),
+ GATE(CLK_BUSTIMER3, "clk_bustimer3", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 2, GFLAGS),
+ GATE(CLK_BUSTIMER4, "clk_bustimer4", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 3, GFLAGS),
+ GATE(CLK_BUSTIMER5, "clk_bustimer5", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 4, GFLAGS),
+ GATE(CLK_BUSTIMER6, "clk_bustimer6", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 5, GFLAGS),
+ GATE(CLK_BUSTIMER7, "clk_bustimer7", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 6, GFLAGS),
+ GATE(CLK_BUSTIMER8, "clk_bustimer8", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 7, GFLAGS),
+ GATE(CLK_BUSTIMER9, "clk_bustimer9", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 8, GFLAGS),
+ GATE(CLK_BUSTIMER10, "clk_bustimer10", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 9, GFLAGS),
+ GATE(CLK_BUSTIMER11, "clk_bustimer11", "clk_bus_timer_root", 0,
+ RK3588_CLKGATE_CON(16), 10, GFLAGS),
+
+ GATE(PCLK_WDT0, "pclk_wdt0", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(15), 0, GFLAGS),
+ GATE(TCLK_WDT0, "tclk_wdt0", "xin24m", 0,
+ RK3588_CLKGATE_CON(15), 1, GFLAGS),
+
+ GATE(PCLK_CAN0, "pclk_can0", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(11), 8, GFLAGS),
+ COMPOSITE(CLK_CAN0, "clk_can0", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(39), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(11), 9, GFLAGS),
+ GATE(PCLK_CAN1, "pclk_can1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(11), 10, GFLAGS),
+ COMPOSITE(CLK_CAN1, "clk_can1", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(39), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(11), 11, GFLAGS),
+ GATE(PCLK_CAN2, "pclk_can2", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(11), 12, GFLAGS),
+ COMPOSITE(CLK_CAN2, "clk_can2", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(40), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(11), 13, GFLAGS),
+
+ GATE(ACLK_DECOM, "aclk_decom", "aclk_bus_root", 0,
+ RK3588_CLKGATE_CON(17), 6, GFLAGS),
+ GATE(PCLK_DECOM, "pclk_decom", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(17), 7, GFLAGS),
+ COMPOSITE(DCLK_DECOM, "dclk_decom", gpll_spll_p, 0,
+ RK3588_CLKSEL_CON(62), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(17), 8, GFLAGS),
+ GATE(ACLK_DMAC0, "aclk_dmac0", "aclk_bus_root", 0,
+ RK3588_CLKGATE_CON(10), 5, GFLAGS),
+ GATE(ACLK_DMAC1, "aclk_dmac1", "aclk_bus_root", 0,
+ RK3588_CLKGATE_CON(10), 6, GFLAGS),
+ GATE(ACLK_DMAC2, "aclk_dmac2", "aclk_bus_root", 0,
+ RK3588_CLKGATE_CON(10), 7, GFLAGS),
+ GATE(ACLK_GIC, "aclk_gic", "aclk_bus_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(10), 3, GFLAGS),
+
+ GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(16), 14, GFLAGS),
+ COMPOSITE(DBCLK_GPIO1, "dbclk_gpio1", mux_24m_32k_p, 0,
+ RK3588_CLKSEL_CON(60), 8, 1, MFLAGS, 3, 5, DFLAGS,
+ RK3588_CLKGATE_CON(16), 15, GFLAGS),
+ GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(17), 0, GFLAGS),
+ COMPOSITE(DBCLK_GPIO2, "dbclk_gpio2", mux_24m_32k_p, 0,
+ RK3588_CLKSEL_CON(60), 14, 1, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(17), 1, GFLAGS),
+ GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(17), 2, GFLAGS),
+ COMPOSITE(DBCLK_GPIO3, "dbclk_gpio3", mux_24m_32k_p, 0,
+ RK3588_CLKSEL_CON(61), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(17), 3, GFLAGS),
+ GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(17), 4, GFLAGS),
+ COMPOSITE(DBCLK_GPIO4, "dbclk_gpio4", mux_24m_32k_p, 0,
+ RK3588_CLKSEL_CON(61), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(17), 5, GFLAGS),
+
+ GATE(PCLK_I2C1, "pclk_i2c1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(10), 8, GFLAGS),
+ GATE(PCLK_I2C2, "pclk_i2c2", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(10), 9, GFLAGS),
+ GATE(PCLK_I2C3, "pclk_i2c3", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(10), 10, GFLAGS),
+ GATE(PCLK_I2C4, "pclk_i2c4", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(10), 11, GFLAGS),
+ GATE(PCLK_I2C5, "pclk_i2c5", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(10), 12, GFLAGS),
+ GATE(PCLK_I2C6, "pclk_i2c6", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(10), 13, GFLAGS),
+ GATE(PCLK_I2C7, "pclk_i2c7", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(10), 14, GFLAGS),
+ GATE(PCLK_I2C8, "pclk_i2c8", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(10), 15, GFLAGS),
+ COMPOSITE_NODIV(CLK_I2C1, "clk_i2c1", mux_200m_100m_p, 0,
+ RK3588_CLKSEL_CON(38), 6, 1, MFLAGS,
+ RK3588_CLKGATE_CON(11), 0, GFLAGS),
+ COMPOSITE_NODIV(CLK_I2C2, "clk_i2c2", mux_200m_100m_p, 0,
+ RK3588_CLKSEL_CON(38), 7, 1, MFLAGS,
+ RK3588_CLKGATE_CON(11), 1, GFLAGS),
+ COMPOSITE_NODIV(CLK_I2C3, "clk_i2c3", mux_200m_100m_p, 0,
+ RK3588_CLKSEL_CON(38), 8, 1, MFLAGS,
+ RK3588_CLKGATE_CON(11), 2, GFLAGS),
+ COMPOSITE_NODIV(CLK_I2C4, "clk_i2c4", mux_200m_100m_p, 0,
+ RK3588_CLKSEL_CON(38), 9, 1, MFLAGS,
+ RK3588_CLKGATE_CON(11), 3, GFLAGS),
+ COMPOSITE_NODIV(CLK_I2C5, "clk_i2c5", mux_200m_100m_p, 0,
+ RK3588_CLKSEL_CON(38), 10, 1, MFLAGS,
+ RK3588_CLKGATE_CON(11), 4, GFLAGS),
+ COMPOSITE_NODIV(CLK_I2C6, "clk_i2c6", mux_200m_100m_p, 0,
+ RK3588_CLKSEL_CON(38), 11, 1, MFLAGS,
+ RK3588_CLKGATE_CON(11), 5, GFLAGS),
+ COMPOSITE_NODIV(CLK_I2C7, "clk_i2c7", mux_200m_100m_p, 0,
+ RK3588_CLKSEL_CON(38), 12, 1, MFLAGS,
+ RK3588_CLKGATE_CON(11), 6, GFLAGS),
+ COMPOSITE_NODIV(CLK_I2C8, "clk_i2c8", mux_200m_100m_p, 0,
+ RK3588_CLKSEL_CON(38), 13, 1, MFLAGS,
+ RK3588_CLKGATE_CON(11), 7, GFLAGS),
+
+ GATE(PCLK_OTPC_NS, "pclk_otpc_ns", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(18), 9, GFLAGS),
+ GATE(CLK_OTPC_NS, "clk_otpc_ns", "xin24m", 0,
+ RK3588_CLKGATE_CON(18), 10, GFLAGS),
+ GATE(CLK_OTPC_ARB, "clk_otpc_arb", "xin24m", 0,
+ RK3588_CLKGATE_CON(18), 11, GFLAGS),
+ GATE(CLK_OTP_PHY_G, "clk_otp_phy_g", "xin24m", 0,
+ RK3588_CLKGATE_CON(18), 13, GFLAGS),
+ GATE(CLK_OTPC_AUTO_RD_G, "clk_otpc_auto_rd_g", "xin24m", 0,
+ RK3588_CLKGATE_CON(18), 12, GFLAGS),
+
+ GATE(PCLK_SARADC, "pclk_saradc", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(11), 14, GFLAGS),
+ COMPOSITE(CLK_SARADC, "clk_saradc", gpll_24m_p, 0,
+ RK3588_CLKSEL_CON(40), 14, 1, MFLAGS, 6, 8, DFLAGS,
+ RK3588_CLKGATE_CON(11), 15, GFLAGS),
+
+ GATE(PCLK_SPI0, "pclk_spi0", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(14), 6, GFLAGS),
+ GATE(PCLK_SPI1, "pclk_spi1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(14), 7, GFLAGS),
+ GATE(PCLK_SPI2, "pclk_spi2", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(14), 8, GFLAGS),
+ GATE(PCLK_SPI3, "pclk_spi3", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(14), 9, GFLAGS),
+ GATE(PCLK_SPI4, "pclk_spi4", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(14), 10, GFLAGS),
+ COMPOSITE_NODIV(CLK_SPI0, "clk_spi0", mux_200m_150m_24m_p, 0,
+ RK3588_CLKSEL_CON(59), 2, 2, MFLAGS,
+ RK3588_CLKGATE_CON(14), 11, GFLAGS),
+ COMPOSITE_NODIV(CLK_SPI1, "clk_spi1", mux_200m_150m_24m_p, 0,
+ RK3588_CLKSEL_CON(59), 4, 2, MFLAGS,
+ RK3588_CLKGATE_CON(14), 12, GFLAGS),
+ COMPOSITE_NODIV(CLK_SPI2, "clk_spi2", mux_200m_150m_24m_p, 0,
+ RK3588_CLKSEL_CON(59), 6, 2, MFLAGS,
+ RK3588_CLKGATE_CON(14), 13, GFLAGS),
+ COMPOSITE_NODIV(CLK_SPI3, "clk_spi3", mux_200m_150m_24m_p, 0,
+ RK3588_CLKSEL_CON(59), 8, 2, MFLAGS,
+ RK3588_CLKGATE_CON(14), 14, GFLAGS),
+ COMPOSITE_NODIV(CLK_SPI4, "clk_spi4", mux_200m_150m_24m_p, 0,
+ RK3588_CLKSEL_CON(59), 10, 2, MFLAGS,
+ RK3588_CLKGATE_CON(14), 15, GFLAGS),
+
+ GATE(ACLK_SPINLOCK, "aclk_spinlock", "aclk_bus_root", CLK_IGNORE_UNUSED,
+ RK3588_CLKGATE_CON(18), 6, GFLAGS),
+ GATE(PCLK_TSADC, "pclk_tsadc", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 0, GFLAGS),
+ COMPOSITE(CLK_TSADC, "clk_tsadc", gpll_24m_p, 0,
+ RK3588_CLKSEL_CON(41), 8, 1, MFLAGS, 0, 8, DFLAGS,
+ RK3588_CLKGATE_CON(12), 1, GFLAGS),
+
+ GATE(PCLK_UART1, "pclk_uart1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 2, GFLAGS),
+ GATE(PCLK_UART2, "pclk_uart2", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 3, GFLAGS),
+ GATE(PCLK_UART3, "pclk_uart3", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 4, GFLAGS),
+ GATE(PCLK_UART4, "pclk_uart4", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 5, GFLAGS),
+ GATE(PCLK_UART5, "pclk_uart5", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 6, GFLAGS),
+ GATE(PCLK_UART6, "pclk_uart6", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 7, GFLAGS),
+ GATE(PCLK_UART7, "pclk_uart7", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 8, GFLAGS),
+ GATE(PCLK_UART8, "pclk_uart8", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 9, GFLAGS),
+ GATE(PCLK_UART9, "pclk_uart9", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(12), 10, GFLAGS),
+
+ COMPOSITE(CLK_UART1_SRC, "clk_uart1_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(41), 14, 1, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(12), 11, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART1_FRAC, "clk_uart1_frac", "clk_uart1_src", CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(42), 0,
+ RK3588_CLKGATE_CON(12), 12, GFLAGS,
+ &rk3588_uart1_fracmux),
+ GATE(SCLK_UART1, "sclk_uart1", "clk_uart1", 0,
+ RK3588_CLKGATE_CON(12), 13, GFLAGS),
+ COMPOSITE(CLK_UART2_SRC, "clk_uart2_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(43), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(12), 14, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART2_FRAC, "clk_uart2_frac", "clk_uart2_src", CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(44), 0,
+ RK3588_CLKGATE_CON(12), 15, GFLAGS,
+ &rk3588_uart2_fracmux),
+ GATE(SCLK_UART2, "sclk_uart2", "clk_uart2", 0,
+ RK3588_CLKGATE_CON(13), 0, GFLAGS),
+ COMPOSITE(CLK_UART3_SRC, "clk_uart3_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(45), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(13), 1, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART3_FRAC, "clk_uart3_frac", "clk_uart3_src", CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(46), 0,
+ RK3588_CLKGATE_CON(13), 2, GFLAGS,
+ &rk3588_uart3_fracmux),
+ GATE(SCLK_UART3, "sclk_uart3", "clk_uart3", 0,
+ RK3588_CLKGATE_CON(13), 3, GFLAGS),
+ COMPOSITE(CLK_UART4_SRC, "clk_uart4_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(47), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(13), 4, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART4_FRAC, "clk_uart4_frac", "clk_uart4_src", CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(48), 0,
+ RK3588_CLKGATE_CON(13), 5, GFLAGS,
+ &rk3588_uart4_fracmux),
+ GATE(SCLK_UART4, "sclk_uart4", "clk_uart4", 0,
+ RK3588_CLKGATE_CON(13), 6, GFLAGS),
+ COMPOSITE(CLK_UART5_SRC, "clk_uart5_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(49), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(13), 7, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART5_FRAC, "clk_uart5_frac", "clk_uart5_src", CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(50), 0,
+ RK3588_CLKGATE_CON(13), 8, GFLAGS,
+ &rk3588_uart5_fracmux),
+ GATE(SCLK_UART5, "sclk_uart5", "clk_uart5", 0,
+ RK3588_CLKGATE_CON(13), 9, GFLAGS),
+ COMPOSITE(CLK_UART6_SRC, "clk_uart6_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(51), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(13), 10, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART6_FRAC, "clk_uart6_frac", "clk_uart6_src", CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(52), 0,
+ RK3588_CLKGATE_CON(13), 11, GFLAGS,
+ &rk3588_uart6_fracmux),
+ GATE(SCLK_UART6, "sclk_uart6", "clk_uart6", 0,
+ RK3588_CLKGATE_CON(13), 12, GFLAGS),
+ COMPOSITE(CLK_UART7_SRC, "clk_uart7_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(53), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(13), 13, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART7_FRAC, "clk_uart7_frac", "clk_uart7_src", CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(54), 0,
+ RK3588_CLKGATE_CON(13), 14, GFLAGS,
+ &rk3588_uart7_fracmux),
+ GATE(SCLK_UART7, "sclk_uart7", "clk_uart7", 0,
+ RK3588_CLKGATE_CON(13), 15, GFLAGS),
+ COMPOSITE(CLK_UART8_SRC, "clk_uart8_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(55), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(14), 0, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART8_FRAC, "clk_uart8_frac", "clk_uart8_src", CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(56), 0,
+ RK3588_CLKGATE_CON(14), 1, GFLAGS,
+ &rk3588_uart8_fracmux),
+ GATE(SCLK_UART8, "sclk_uart8", "clk_uart8", 0,
+ RK3588_CLKGATE_CON(14), 2, GFLAGS),
+ COMPOSITE(CLK_UART9_SRC, "clk_uart9_src", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(57), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(14), 3, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART9_FRAC, "clk_uart9_frac", "clk_uart9_src", CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(58), 0,
+ RK3588_CLKGATE_CON(14), 4, GFLAGS,
+ &rk3588_uart9_fracmux),
+ GATE(SCLK_UART9, "sclk_uart9", "clk_uart9", 0,
+ RK3588_CLKGATE_CON(14), 5, GFLAGS),
+
+ /* center */
+ COMPOSITE_NODIV(ACLK_CENTER_ROOT, "aclk_center_root", mux_700m_400m_200m_24m_p,
+ CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(165), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(69), 0, GFLAGS),
+ COMPOSITE_NODIV(ACLK_CENTER_LOW_ROOT, "aclk_center_low_root", mux_500m_250m_100m_24m_p,
+ CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(165), 2, 2, MFLAGS,
+ RK3588_CLKGATE_CON(69), 1, GFLAGS),
+ COMPOSITE_NODIV(HCLK_CENTER_ROOT, "hclk_center_root", mux_400m_200m_100m_24m_p,
+ CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(165), 4, 2, MFLAGS,
+ RK3588_CLKGATE_CON(69), 2, GFLAGS),
+ COMPOSITE_NODIV(PCLK_CENTER_ROOT, "pclk_center_root", mux_200m_100m_50m_24m_p,
+ CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(165), 6, 2, MFLAGS | CLK_MUX_READ_ONLY,
+ RK3588_CLKGATE_CON(69), 3, GFLAGS),
+ GATE(ACLK_DMA2DDR, "aclk_dma2ddr", "aclk_center_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(69), 5, GFLAGS),
+ GATE(ACLK_DDR_SHAREMEM, "aclk_ddr_sharemem", "aclk_center_low_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(69), 6, GFLAGS),
+ COMPOSITE_NODIV(ACLK_CENTER_S200_ROOT, "aclk_center_s200_root", mux_200m_100m_50m_24m_p,
+ CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(165), 8, 2, MFLAGS,
+ RK3588_CLKGATE_CON(69), 8, GFLAGS),
+ COMPOSITE_NODIV(ACLK_CENTER_S400_ROOT, "aclk_center_s400_root", mux_400m_200m_100m_24m_p,
+ CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(165), 10, 2, MFLAGS,
+ RK3588_CLKGATE_CON(69), 9, GFLAGS),
+ GATE(FCLK_DDR_CM0_CORE, "fclk_ddr_cm0_core", "hclk_center_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(69), 14, GFLAGS),
+ COMPOSITE_NODIV(CLK_DDR_TIMER_ROOT, "clk_ddr_timer_root", mux_24m_100m_p, CLK_IGNORE_UNUSED,
+ RK3588_CLKSEL_CON(165), 12, 1, MFLAGS,
+ RK3588_CLKGATE_CON(69), 15, GFLAGS),
+ GATE(CLK_DDR_TIMER0, "clk_ddr_timer0", "clk_ddr_timer_root", 0,
+ RK3588_CLKGATE_CON(70), 0, GFLAGS),
+ GATE(CLK_DDR_TIMER1, "clk_ddr_timer1", "clk_ddr_timer_root", 0,
+ RK3588_CLKGATE_CON(70), 1, GFLAGS),
+ GATE(TCLK_WDT_DDR, "tclk_wdt_ddr", "xin24m", 0,
+ RK3588_CLKGATE_CON(70), 2, GFLAGS),
+ COMPOSITE(CLK_DDR_CM0_RTC, "clk_ddr_cm0_rtc", mux_24m_32k_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(166), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(70), 4, GFLAGS),
+ GATE(PCLK_WDT, "pclk_wdt", "pclk_center_root", 0,
+ RK3588_CLKGATE_CON(70), 7, GFLAGS),
+ GATE(PCLK_TIMER, "pclk_timer", "pclk_center_root", 0,
+ RK3588_CLKGATE_CON(70), 8, GFLAGS),
+ GATE(PCLK_DMA2DDR, "pclk_dma2ddr", "pclk_center_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(70), 9, GFLAGS),
+ GATE(PCLK_SHAREMEM, "pclk_sharemem", "pclk_center_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(70), 10, GFLAGS),
+
+ /* gpu */
+ COMPOSITE(CLK_GPU_SRC, "clk_gpu_src", gpll_cpll_aupll_npll_spll_p, 0,
+ RK3588_CLKSEL_CON(158), 5, 3, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(66), 1, GFLAGS),
+ GATE(CLK_GPU, "clk_gpu", "clk_gpu_src", 0,
+ RK3588_CLKGATE_CON(66), 4, GFLAGS),
+ GATE(CLK_GPU_COREGROUP, "clk_gpu_coregroup", "clk_gpu_src", 0,
+ RK3588_CLKGATE_CON(66), 6, GFLAGS),
+ COMPOSITE_NOMUX(CLK_GPU_STACKS, "clk_gpu_stacks", "clk_gpu_src", 0,
+ RK3588_CLKSEL_CON(159), 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(66), 7, GFLAGS),
+ GATE(CLK_GPU_PVTM, "clk_gpu_pvtm", "xin24m", 0,
+ RK3588_CLKGATE_CON(67), 0, GFLAGS),
+ GATE(CLK_CORE_GPU_PVTM, "clk_core_gpu_pvtm", "clk_gpu_src", 0,
+ RK3588_CLKGATE_CON(67), 1, GFLAGS),
+
+ /* isp1 */
+ COMPOSITE(ACLK_ISP1_ROOT, "aclk_isp1_root", gpll_cpll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(67), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(26), 0, GFLAGS),
+ COMPOSITE_NODIV(HCLK_ISP1_ROOT, "hclk_isp1_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(67), 7, 2, MFLAGS,
+ RK3588_CLKGATE_CON(26), 1, GFLAGS),
+ COMPOSITE(CLK_ISP1_CORE, "clk_isp1_core", gpll_cpll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(67), 14, 2, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(26), 2, GFLAGS),
+ GATE(CLK_ISP1_CORE_MARVIN, "clk_isp1_core_marvin", "clk_isp1_core", 0,
+ RK3588_CLKGATE_CON(26), 3, GFLAGS),
+ GATE(CLK_ISP1_CORE_VICAP, "clk_isp1_core_vicap", "clk_isp1_core", 0,
+ RK3588_CLKGATE_CON(26), 4, GFLAGS),
+
+ /* npu */
+ COMPOSITE_NODIV(HCLK_NPU_ROOT, "hclk_npu_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(73), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(29), 0, GFLAGS),
+ COMPOSITE(CLK_NPU_DSU0, "clk_npu_dsu0", gpll_cpll_aupll_npll_spll_p, 0,
+ RK3588_CLKSEL_CON(73), 7, 3, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(29), 1, GFLAGS),
+ COMPOSITE_NODIV(PCLK_NPU_ROOT, "pclk_npu_root", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(74), 1, 2, MFLAGS,
+ RK3588_CLKGATE_CON(29), 4, GFLAGS),
+ GATE(ACLK_NPU1, "aclk_npu1", "clk_npu_dsu0", 0,
+ RK3588_CLKGATE_CON(27), 0, GFLAGS),
+ GATE(HCLK_NPU1, "hclk_npu1", "hclk_npu_root", 0,
+ RK3588_CLKGATE_CON(27), 2, GFLAGS),
+ GATE(ACLK_NPU2, "aclk_npu2", "clk_npu_dsu0", 0,
+ RK3588_CLKGATE_CON(28), 0, GFLAGS),
+ GATE(HCLK_NPU2, "hclk_npu2", "hclk_npu_root", 0,
+ RK3588_CLKGATE_CON(28), 2, GFLAGS),
+ COMPOSITE_NODIV(HCLK_NPU_CM0_ROOT, "hclk_npu_cm0_root", mux_400m_200m_100m_24m_p, 0,
+ RK3588_CLKSEL_CON(74), 5, 2, MFLAGS,
+ RK3588_CLKGATE_CON(30), 1, GFLAGS),
+ GATE(FCLK_NPU_CM0_CORE, "fclk_npu_cm0_core", "hclk_npu_cm0_root", 0,
+ RK3588_CLKGATE_CON(30), 3, GFLAGS),
+ COMPOSITE(CLK_NPU_CM0_RTC, "clk_npu_cm0_rtc", mux_24m_32k_p, 0,
+ RK3588_CLKSEL_CON(74), 12, 1, MFLAGS, 7, 5, DFLAGS,
+ RK3588_CLKGATE_CON(30), 5, GFLAGS),
+ GATE(PCLK_NPU_PVTM, "pclk_npu_pvtm", "pclk_npu_root", 0,
+ RK3588_CLKGATE_CON(29), 12, GFLAGS),
+ GATE(PCLK_NPU_GRF, "pclk_npu_grf", "pclk_npu_root", CLK_IGNORE_UNUSED,
+ RK3588_CLKGATE_CON(29), 13, GFLAGS),
+ GATE(CLK_NPU_PVTM, "clk_npu_pvtm", "xin24m", 0,
+ RK3588_CLKGATE_CON(29), 14, GFLAGS),
+ GATE(CLK_CORE_NPU_PVTM, "clk_core_npu_pvtm", "clk_npu_dsu0", 0,
+ RK3588_CLKGATE_CON(29), 15, GFLAGS),
+ GATE(ACLK_NPU0, "aclk_npu0", "clk_npu_dsu0", 0,
+ RK3588_CLKGATE_CON(30), 6, GFLAGS),
+ GATE(HCLK_NPU0, "hclk_npu0", "hclk_npu_root", 0,
+ RK3588_CLKGATE_CON(30), 8, GFLAGS),
+ GATE(PCLK_NPU_TIMER, "pclk_npu_timer", "pclk_npu_root", 0,
+ RK3588_CLKGATE_CON(29), 6, GFLAGS),
+ COMPOSITE_NODIV(CLK_NPUTIMER_ROOT, "clk_nputimer_root", mux_24m_100m_p, 0,
+ RK3588_CLKSEL_CON(74), 3, 1, MFLAGS,
+ RK3588_CLKGATE_CON(29), 7, GFLAGS),
+ GATE(CLK_NPUTIMER0, "clk_nputimer0", "clk_nputimer_root", 0,
+ RK3588_CLKGATE_CON(29), 8, GFLAGS),
+ GATE(CLK_NPUTIMER1, "clk_nputimer1", "clk_nputimer_root", 0,
+ RK3588_CLKGATE_CON(29), 9, GFLAGS),
+ GATE(PCLK_NPU_WDT, "pclk_npu_wdt", "pclk_npu_root", 0,
+ RK3588_CLKGATE_CON(29), 10, GFLAGS),
+ GATE(TCLK_NPU_WDT, "tclk_npu_wdt", "xin24m", 0,
+ RK3588_CLKGATE_CON(29), 11, GFLAGS),
+
+ /* nvm */
+ COMPOSITE_NODIV(HCLK_NVM_ROOT, "hclk_nvm_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(77), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(31), 0, GFLAGS),
+ COMPOSITE(ACLK_NVM_ROOT, "aclk_nvm_root", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(77), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(31), 1, GFLAGS),
+ GATE(ACLK_EMMC, "aclk_emmc", "aclk_nvm_root", 0,
+ RK3588_CLKGATE_CON(31), 5, GFLAGS),
+ COMPOSITE(CCLK_EMMC, "cclk_emmc", gpll_cpll_24m_p, 0,
+ RK3588_CLKSEL_CON(77), 14, 2, MFLAGS, 8, 6, DFLAGS,
+ RK3588_CLKGATE_CON(31), 6, GFLAGS),
+ COMPOSITE(BCLK_EMMC, "bclk_emmc", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(78), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(31), 7, GFLAGS),
+ GATE(TMCLK_EMMC, "tmclk_emmc", "xin24m", 0,
+ RK3588_CLKGATE_CON(31), 8, GFLAGS),
+
+ COMPOSITE(SCLK_SFC, "sclk_sfc", gpll_cpll_24m_p, 0,
+ RK3588_CLKSEL_CON(78), 12, 2, MFLAGS, 6, 6, DFLAGS,
+ RK3588_CLKGATE_CON(31), 9, GFLAGS),
+
+ /* php */
+ COMPOSITE(CLK_GMAC0_PTP_REF, "clk_gmac0_ptp_ref", clk_gmac0_ptp_ref_p, 0,
+ RK3588_CLKSEL_CON(81), 6, 1, MFLAGS, 0, 6, DFLAGS,
+ RK3588_CLKGATE_CON(34), 10, GFLAGS),
+ COMPOSITE(CLK_GMAC1_PTP_REF, "clk_gmac1_ptp_ref", clk_gmac1_ptp_ref_p, 0,
+ RK3588_CLKSEL_CON(81), 13, 1, MFLAGS, 7, 6, DFLAGS,
+ RK3588_CLKGATE_CON(34), 11, GFLAGS),
+ COMPOSITE(CLK_GMAC_125M, "clk_gmac_125m", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(83), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ RK3588_CLKGATE_CON(35), 5, GFLAGS),
+ COMPOSITE(CLK_GMAC_50M, "clk_gmac_50m", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(84), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3588_CLKGATE_CON(35), 6, GFLAGS),
+
+ COMPOSITE(ACLK_PCIE_ROOT, "aclk_pcie_root", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(80), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(32), 6, GFLAGS),
+ COMPOSITE(ACLK_PHP_ROOT, "aclk_php_root", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(80), 13, 1, MFLAGS, 8, 5, DFLAGS,
+ RK3588_CLKGATE_CON(32), 7, GFLAGS),
+ COMPOSITE_NODIV(PCLK_PHP_ROOT, "pclk_php_root", mux_150m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(80), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(32), 0, GFLAGS),
+ GATE(ACLK_PHP_GIC_ITS, "aclk_php_gic_its", "aclk_pcie_root", CLK_IS_CRITICAL,
+ RK3588_CLKGATE_CON(34), 6, GFLAGS),
+ GATE(ACLK_PCIE_BRIDGE, "aclk_pcie_bridge", "aclk_pcie_root", 0,
+ RK3588_CLKGATE_CON(32), 8, GFLAGS),
+ GATE(ACLK_MMU_PCIE, "aclk_mmu_pcie", "aclk_pcie_bridge", 0,
+ RK3588_CLKGATE_CON(34), 7, GFLAGS),
+ GATE(ACLK_MMU_PHP, "aclk_mmu_php", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(34), 8, GFLAGS),
+ GATE(ACLK_PCIE_4L_DBI, "aclk_pcie_4l_dbi", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(32), 13, GFLAGS),
+ GATE(ACLK_PCIE_2L_DBI, "aclk_pcie_2l_dbi", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(32), 14, GFLAGS),
+ GATE(ACLK_PCIE_1L0_DBI, "aclk_pcie_1l0_dbi", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(32), 15, GFLAGS),
+ GATE(ACLK_PCIE_1L1_DBI, "aclk_pcie_1l1_dbi", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 0, GFLAGS),
+ GATE(ACLK_PCIE_1L2_DBI, "aclk_pcie_1l2_dbi", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 1, GFLAGS),
+ GATE(ACLK_PCIE_4L_MSTR, "aclk_pcie_4l_mstr", "aclk_mmu_pcie", 0,
+ RK3588_CLKGATE_CON(33), 2, GFLAGS),
+ GATE(ACLK_PCIE_2L_MSTR, "aclk_pcie_2l_mstr", "aclk_mmu_pcie", 0,
+ RK3588_CLKGATE_CON(33), 3, GFLAGS),
+ GATE(ACLK_PCIE_1L0_MSTR, "aclk_pcie_1l0_mstr", "aclk_mmu_pcie", 0,
+ RK3588_CLKGATE_CON(33), 4, GFLAGS),
+ GATE(ACLK_PCIE_1L1_MSTR, "aclk_pcie_1l1_mstr", "aclk_mmu_pcie", 0,
+ RK3588_CLKGATE_CON(33), 5, GFLAGS),
+ GATE(ACLK_PCIE_1L2_MSTR, "aclk_pcie_1l2_mstr", "aclk_mmu_pcie", 0,
+ RK3588_CLKGATE_CON(33), 6, GFLAGS),
+ GATE(ACLK_PCIE_4L_SLV, "aclk_pcie_4l_slv", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 7, GFLAGS),
+ GATE(ACLK_PCIE_2L_SLV, "aclk_pcie_2l_slv", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 8, GFLAGS),
+ GATE(ACLK_PCIE_1L0_SLV, "aclk_pcie_1l0_slv", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 9, GFLAGS),
+ GATE(ACLK_PCIE_1L1_SLV, "aclk_pcie_1l1_slv", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 10, GFLAGS),
+ GATE(ACLK_PCIE_1L2_SLV, "aclk_pcie_1l2_slv", "aclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 11, GFLAGS),
+ GATE(PCLK_PCIE_4L, "pclk_pcie_4l", "pclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 12, GFLAGS),
+ GATE(PCLK_PCIE_2L, "pclk_pcie_2l", "pclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 13, GFLAGS),
+ GATE(PCLK_PCIE_1L0, "pclk_pcie_1l0", "pclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 14, GFLAGS),
+ GATE(PCLK_PCIE_1L1, "pclk_pcie_1l1", "pclk_php_root", 0,
+ RK3588_CLKGATE_CON(33), 15, GFLAGS),
+ GATE(PCLK_PCIE_1L2, "pclk_pcie_1l2", "pclk_php_root", 0,
+ RK3588_CLKGATE_CON(34), 0, GFLAGS),
+ GATE(CLK_PCIE_AUX0, "clk_pcie_aux0", "xin24m", 0,
+ RK3588_CLKGATE_CON(34), 1, GFLAGS),
+ GATE(CLK_PCIE_AUX1, "clk_pcie_aux1", "xin24m", 0,
+ RK3588_CLKGATE_CON(34), 2, GFLAGS),
+ GATE(CLK_PCIE_AUX2, "clk_pcie_aux2", "xin24m", 0,
+ RK3588_CLKGATE_CON(34), 3, GFLAGS),
+ GATE(CLK_PCIE_AUX3, "clk_pcie_aux3", "xin24m", 0,
+ RK3588_CLKGATE_CON(34), 4, GFLAGS),
+ GATE(CLK_PCIE_AUX4, "clk_pcie_aux4", "xin24m", 0,
+ RK3588_CLKGATE_CON(34), 5, GFLAGS),
+ GATE(CLK_PIPEPHY0_REF, "clk_pipephy0_ref", "xin24m", 0,
+ RK3588_CLKGATE_CON(37), 0, GFLAGS),
+ GATE(CLK_PIPEPHY1_REF, "clk_pipephy1_ref", "xin24m", 0,
+ RK3588_CLKGATE_CON(37), 1, GFLAGS),
+ GATE(CLK_PIPEPHY2_REF, "clk_pipephy2_ref", "xin24m", 0,
+ RK3588_CLKGATE_CON(37), 2, GFLAGS),
+ GATE(PCLK_GMAC0, "pclk_gmac0", "pclk_php_root", 0,
+ RK3588_CLKGATE_CON(32), 3, GFLAGS),
+ GATE(PCLK_GMAC1, "pclk_gmac1", "pclk_php_root", 0,
+ RK3588_CLKGATE_CON(32), 4, GFLAGS),
+ GATE(ACLK_GMAC0, "aclk_gmac0", "aclk_mmu_php", 0,
+ RK3588_CLKGATE_CON(32), 10, GFLAGS),
+ GATE(ACLK_GMAC1, "aclk_gmac1", "aclk_mmu_php", 0,
+ RK3588_CLKGATE_CON(32), 11, GFLAGS),
+ GATE(CLK_PMALIVE0, "clk_pmalive0", "xin24m", 0,
+ RK3588_CLKGATE_CON(37), 4, GFLAGS),
+ GATE(CLK_PMALIVE1, "clk_pmalive1", "xin24m", 0,
+ RK3588_CLKGATE_CON(37), 5, GFLAGS),
+ GATE(CLK_PMALIVE2, "clk_pmalive2", "xin24m", 0,
+ RK3588_CLKGATE_CON(37), 6, GFLAGS),
+ GATE(ACLK_SATA0, "aclk_sata0", "aclk_mmu_php", 0,
+ RK3588_CLKGATE_CON(37), 7, GFLAGS),
+ GATE(ACLK_SATA1, "aclk_sata1", "aclk_mmu_php", 0,
+ RK3588_CLKGATE_CON(37), 8, GFLAGS),
+ GATE(ACLK_SATA2, "aclk_sata2", "aclk_mmu_php", 0,
+ RK3588_CLKGATE_CON(37), 9, GFLAGS),
+ COMPOSITE(CLK_RXOOB0, "clk_rxoob0", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(82), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3588_CLKGATE_CON(37), 10, GFLAGS),
+ COMPOSITE(CLK_RXOOB1, "clk_rxoob1", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(82), 15, 1, MFLAGS, 8, 7, DFLAGS,
+ RK3588_CLKGATE_CON(37), 11, GFLAGS),
+ COMPOSITE(CLK_RXOOB2, "clk_rxoob2", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(83), 7, 1, MFLAGS, 0, 7, DFLAGS,
+ RK3588_CLKGATE_CON(37), 12, GFLAGS),
+ GATE(ACLK_USB3OTG2, "aclk_usb3otg2", "aclk_mmu_php", 0,
+ RK3588_CLKGATE_CON(35), 7, GFLAGS),
+ GATE(SUSPEND_CLK_USB3OTG2, "suspend_clk_usb3otg2", "xin24m", 0,
+ RK3588_CLKGATE_CON(35), 8, GFLAGS),
+ GATE(REF_CLK_USB3OTG2, "ref_clk_usb3otg2", "xin24m", 0,
+ RK3588_CLKGATE_CON(35), 9, GFLAGS),
+ COMPOSITE(CLK_UTMI_OTG2, "clk_utmi_otg2", mux_150m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(84), 12, 2, MFLAGS, 8, 4, DFLAGS,
+ RK3588_CLKGATE_CON(35), 10, GFLAGS),
+ GATE(PCLK_PCIE_COMBO_PIPE_PHY0, "pclk_pcie_combo_pipe_phy0", "pclk_top_root", 0,
+ RK3588_PHP_CLKGATE_CON(0), 5, GFLAGS),
+ GATE(PCLK_PCIE_COMBO_PIPE_PHY1, "pclk_pcie_combo_pipe_phy1", "pclk_top_root", 0,
+ RK3588_PHP_CLKGATE_CON(0), 6, GFLAGS),
+ GATE(PCLK_PCIE_COMBO_PIPE_PHY2, "pclk_pcie_combo_pipe_phy2", "pclk_top_root", 0,
+ RK3588_PHP_CLKGATE_CON(0), 7, GFLAGS),
+ GATE(PCLK_PCIE_COMBO_PIPE_PHY, "pclk_pcie_combo_pipe_phy", "pclk_top_root", 0,
+ RK3588_PHP_CLKGATE_CON(0), 8, GFLAGS),
+
+ /* rga */
+ COMPOSITE(CLK_RGA3_1_CORE, "clk_rga3_1_core", gpll_cpll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(174), 14, 2, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(76), 6, GFLAGS),
+ COMPOSITE(ACLK_RGA3_ROOT, "aclk_rga3_root", gpll_cpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(174), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(76), 0, GFLAGS),
+ COMPOSITE_NODIV(HCLK_RGA3_ROOT, "hclk_rga3_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(174), 7, 2, MFLAGS,
+ RK3588_CLKGATE_CON(76), 1, GFLAGS),
+ GATE(HCLK_RGA3_1, "hclk_rga3_1", "hclk_rga3_root", 0,
+ RK3588_CLKGATE_CON(76), 4, GFLAGS),
+ GATE(ACLK_RGA3_1, "aclk_rga3_1", "aclk_rga3_root", 0,
+ RK3588_CLKGATE_CON(76), 5, GFLAGS),
+
+ /* vdec */
+ COMPOSITE_NODIV(0, "hclk_rkvdec0_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(89), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(40), 0, GFLAGS),
+ COMPOSITE(0, "aclk_rkvdec0_root", gpll_cpll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(89), 7, 2, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(40), 1, GFLAGS),
+ COMPOSITE(ACLK_RKVDEC_CCU, "aclk_rkvdec_ccu", gpll_cpll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(89), 14, 2, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(40), 2, GFLAGS),
+ COMPOSITE(CLK_RKVDEC0_CA, "clk_rkvdec0_ca", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(90), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(40), 7, GFLAGS),
+ COMPOSITE(CLK_RKVDEC0_HEVC_CA, "clk_rkvdec0_hevc_ca", gpll_cpll_npll_1000m_p, 0,
+ RK3588_CLKSEL_CON(90), 11, 2, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(40), 8, GFLAGS),
+ COMPOSITE(CLK_RKVDEC0_CORE, "clk_rkvdec0_core", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(91), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(40), 9, GFLAGS),
+ COMPOSITE_NODIV(0, "hclk_rkvdec1_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(93), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(41), 0, GFLAGS),
+ COMPOSITE(0, "aclk_rkvdec1_root", gpll_cpll_aupll_npll_p, 0,
+ RK3588_CLKSEL_CON(93), 7, 2, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(41), 1, GFLAGS),
+ COMPOSITE(CLK_RKVDEC1_CA, "clk_rkvdec1_ca", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(93), 14, 1, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(41), 6, GFLAGS),
+ COMPOSITE(CLK_RKVDEC1_HEVC_CA, "clk_rkvdec1_hevc_ca", gpll_cpll_npll_1000m_p, 0,
+ RK3588_CLKSEL_CON(94), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(41), 7, GFLAGS),
+ COMPOSITE(CLK_RKVDEC1_CORE, "clk_rkvdec1_core", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(94), 12, 1, MFLAGS, 7, 5, DFLAGS,
+ RK3588_CLKGATE_CON(41), 8, GFLAGS),
+
+ /* sdio */
+ COMPOSITE_NODIV(0, "hclk_sdio_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(172), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(75), 0, GFLAGS),
+ COMPOSITE(CCLK_SRC_SDIO, "cclk_src_sdio", gpll_cpll_24m_p, 0,
+ RK3588_CLKSEL_CON(172), 8, 2, MFLAGS, 2, 6, DFLAGS,
+ RK3588_CLKGATE_CON(75), 3, GFLAGS),
+ MMC(SCLK_SDIO_DRV, "sdio_drv", "cclk_src_sdio", RK3588_SDIO_CON0, 1),
+ MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "cclk_src_sdio", RK3588_SDIO_CON1, 1),
+
+ /* usb */
+ COMPOSITE(ACLK_USB_ROOT, "aclk_usb_root", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(96), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(42), 0, GFLAGS),
+ COMPOSITE_NODIV(HCLK_USB_ROOT, "hclk_usb_root", mux_150m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(96), 6, 2, MFLAGS,
+ RK3588_CLKGATE_CON(42), 1, GFLAGS),
+ GATE(SUSPEND_CLK_USB3OTG0, "suspend_clk_usb3otg0", "xin24m", 0,
+ RK3588_CLKGATE_CON(42), 5, GFLAGS),
+ GATE(REF_CLK_USB3OTG0, "ref_clk_usb3otg0", "xin24m", 0,
+ RK3588_CLKGATE_CON(42), 6, GFLAGS),
+ GATE(SUSPEND_CLK_USB3OTG1, "suspend_clk_usb3otg1", "xin24m", 0,
+ RK3588_CLKGATE_CON(42), 8, GFLAGS),
+ GATE(REF_CLK_USB3OTG1, "ref_clk_usb3otg1", "xin24m", 0,
+ RK3588_CLKGATE_CON(42), 9, GFLAGS),
+
+ /* vdpu */
+ COMPOSITE(ACLK_VDPU_ROOT, "aclk_vdpu_root", gpll_cpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(98), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(44), 0, GFLAGS),
+ COMPOSITE_NODIV(ACLK_VDPU_LOW_ROOT, "aclk_vdpu_low_root", mux_400m_200m_100m_24m_p, 0,
+ RK3588_CLKSEL_CON(98), 7, 2, MFLAGS,
+ RK3588_CLKGATE_CON(44), 1, GFLAGS),
+ COMPOSITE_NODIV(HCLK_VDPU_ROOT, "hclk_vdpu_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(98), 9, 2, MFLAGS,
+ RK3588_CLKGATE_CON(44), 2, GFLAGS),
+ COMPOSITE(ACLK_JPEG_DECODER_ROOT, "aclk_jpeg_decoder_root", gpll_cpll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(99), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(44), 3, GFLAGS),
+ GATE(HCLK_IEP2P0, "hclk_iep2p0", "hclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(45), 4, GFLAGS),
+ COMPOSITE(CLK_IEP2P0_CORE, "clk_iep2p0_core", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(99), 12, 1, MFLAGS, 7, 5, DFLAGS,
+ RK3588_CLKGATE_CON(45), 6, GFLAGS),
+ GATE(HCLK_JPEG_ENCODER0, "hclk_jpeg_encoder0", "hclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(44), 11, GFLAGS),
+ GATE(HCLK_JPEG_ENCODER1, "hclk_jpeg_encoder1", "hclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(44), 13, GFLAGS),
+ GATE(HCLK_JPEG_ENCODER2, "hclk_jpeg_encoder2", "hclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(44), 15, GFLAGS),
+ GATE(HCLK_JPEG_ENCODER3, "hclk_jpeg_encoder3", "hclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(45), 1, GFLAGS),
+ GATE(HCLK_JPEG_DECODER, "hclk_jpeg_decoder", "hclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(45), 3, GFLAGS),
+ GATE(HCLK_RGA2, "hclk_rga2", "hclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(45), 7, GFLAGS),
+ GATE(ACLK_RGA2, "aclk_rga2", "aclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(45), 8, GFLAGS),
+ COMPOSITE(CLK_RGA2_CORE, "clk_rga2_core", gpll_cpll_npll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(100), 5, 3, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(45), 9, GFLAGS),
+ GATE(HCLK_RGA3_0, "hclk_rga3_0", "hclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(45), 10, GFLAGS),
+ GATE(ACLK_RGA3_0, "aclk_rga3_0", "aclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(45), 11, GFLAGS),
+ COMPOSITE(CLK_RGA3_0_CORE, "clk_rga3_0_core", gpll_cpll_npll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(100), 13, 3, MFLAGS, 8, 5, DFLAGS,
+ RK3588_CLKGATE_CON(45), 12, GFLAGS),
+ GATE(HCLK_VPU, "hclk_vpu", "hclk_vdpu_root", 0,
+ RK3588_CLKGATE_CON(44), 9, GFLAGS),
+
+ /* venc */
+ COMPOSITE_NODIV(HCLK_RKVENC1_ROOT, "hclk_rkvenc1_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(104), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(48), 0, GFLAGS),
+ COMPOSITE(ACLK_RKVENC1_ROOT, "aclk_rkvenc1_root", gpll_cpll_npll_p, 0,
+ RK3588_CLKSEL_CON(104), 7, 2, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(48), 1, GFLAGS),
+ COMPOSITE_NODIV(HCLK_RKVENC0_ROOT, "hclk_rkvenc0_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(102), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(47), 0, GFLAGS),
+ COMPOSITE(ACLK_RKVENC0_ROOT, "aclk_rkvenc0_root", gpll_cpll_npll_p, 0,
+ RK3588_CLKSEL_CON(102), 7, 2, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(47), 1, GFLAGS),
+ GATE(HCLK_RKVENC0, "hclk_rkvenc0", "hclk_rkvenc0_root", 0,
+ RK3588_CLKGATE_CON(47), 4, GFLAGS),
+ GATE(ACLK_RKVENC0, "aclk_rkvenc0", "aclk_rkvenc0_root", 0,
+ RK3588_CLKGATE_CON(47), 5, GFLAGS),
+ COMPOSITE(CLK_RKVENC0_CORE, "clk_rkvenc0_core", gpll_cpll_aupll_npll_p, 0,
+ RK3588_CLKSEL_CON(102), 14, 2, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(47), 6, GFLAGS),
+ COMPOSITE(CLK_RKVENC1_CORE, "clk_rkvenc1_core", gpll_cpll_aupll_npll_p, 0,
+ RK3588_CLKSEL_CON(104), 14, 2, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(48), 6, GFLAGS),
+
+ /* vi */
+ COMPOSITE(ACLK_VI_ROOT, "aclk_vi_root", gpll_cpll_npll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(106), 5, 3, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(49), 0, GFLAGS),
+ COMPOSITE_NODIV(HCLK_VI_ROOT, "hclk_vi_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(106), 8, 2, MFLAGS,
+ RK3588_CLKGATE_CON(49), 1, GFLAGS),
+ COMPOSITE_NODIV(PCLK_VI_ROOT, "pclk_vi_root", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(106), 10, 2, MFLAGS,
+ RK3588_CLKGATE_CON(49), 2, GFLAGS),
+ COMPOSITE_NODIV(ICLK_CSIHOST01, "iclk_csihost01", mux_400m_200m_100m_24m_p, 0,
+ RK3588_CLKSEL_CON(108), 14, 2, MFLAGS,
+ RK3588_CLKGATE_CON(51), 10, GFLAGS),
+ GATE(ICLK_CSIHOST0, "iclk_csihost0", "iclk_csihost01", 0,
+ RK3588_CLKGATE_CON(51), 11, GFLAGS),
+ GATE(ICLK_CSIHOST1, "iclk_csihost1", "iclk_csihost01", 0,
+ RK3588_CLKGATE_CON(51), 12, GFLAGS),
+ GATE(PCLK_CSI_HOST_0, "pclk_csi_host_0", "pclk_vi_root", 0,
+ RK3588_CLKGATE_CON(50), 4, GFLAGS),
+ GATE(PCLK_CSI_HOST_1, "pclk_csi_host_1", "pclk_vi_root", 0,
+ RK3588_CLKGATE_CON(50), 5, GFLAGS),
+ GATE(PCLK_CSI_HOST_2, "pclk_csi_host_2", "pclk_vi_root", 0,
+ RK3588_CLKGATE_CON(50), 6, GFLAGS),
+ GATE(PCLK_CSI_HOST_3, "pclk_csi_host_3", "pclk_vi_root", 0,
+ RK3588_CLKGATE_CON(50), 7, GFLAGS),
+ GATE(PCLK_CSI_HOST_4, "pclk_csi_host_4", "pclk_vi_root", 0,
+ RK3588_CLKGATE_CON(50), 8, GFLAGS),
+ GATE(PCLK_CSI_HOST_5, "pclk_csi_host_5", "pclk_vi_root", 0,
+ RK3588_CLKGATE_CON(50), 9, GFLAGS),
+ GATE(ACLK_FISHEYE0, "aclk_fisheye0", "aclk_vi_root", 0,
+ RK3588_CLKGATE_CON(49), 14, GFLAGS),
+ GATE(HCLK_FISHEYE0, "hclk_fisheye0", "hclk_vi_root", 0,
+ RK3588_CLKGATE_CON(49), 15, GFLAGS),
+ COMPOSITE(CLK_FISHEYE0_CORE, "clk_fisheye0_core", gpll_cpll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(108), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(50), 0, GFLAGS),
+ GATE(ACLK_FISHEYE1, "aclk_fisheye1", "aclk_vi_root", 0,
+ RK3588_CLKGATE_CON(50), 1, GFLAGS),
+ GATE(HCLK_FISHEYE1, "hclk_fisheye1", "hclk_vi_root", 0,
+ RK3588_CLKGATE_CON(50), 2, GFLAGS),
+ COMPOSITE(CLK_FISHEYE1_CORE, "clk_fisheye1_core", gpll_cpll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(108), 12, 2, MFLAGS, 7, 5, DFLAGS,
+ RK3588_CLKGATE_CON(50), 3, GFLAGS),
+ COMPOSITE(CLK_ISP0_CORE, "clk_isp0_core", gpll_cpll_aupll_spll_p, 0,
+ RK3588_CLKSEL_CON(107), 11, 2, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(49), 9, GFLAGS),
+ GATE(CLK_ISP0_CORE_MARVIN, "clk_isp0_core_marvin", "clk_isp0_core", 0,
+ RK3588_CLKGATE_CON(49), 10, GFLAGS),
+ GATE(CLK_ISP0_CORE_VICAP, "clk_isp0_core_vicap", "clk_isp0_core", 0,
+ RK3588_CLKGATE_CON(49), 11, GFLAGS),
+ GATE(ACLK_ISP0, "aclk_isp0", "aclk_vi_root", 0,
+ RK3588_CLKGATE_CON(49), 12, GFLAGS),
+ GATE(HCLK_ISP0, "hclk_isp0", "hclk_vi_root", 0,
+ RK3588_CLKGATE_CON(49), 13, GFLAGS),
+ COMPOSITE(DCLK_VICAP, "dclk_vicap", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(107), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(49), 6, GFLAGS),
+ GATE(ACLK_VICAP, "aclk_vicap", "aclk_vi_root", 0,
+ RK3588_CLKGATE_CON(49), 7, GFLAGS),
+ GATE(HCLK_VICAP, "hclk_vicap", "hclk_vi_root", 0,
+ RK3588_CLKGATE_CON(49), 8, GFLAGS),
+
+ /* vo0 */
+ COMPOSITE(ACLK_VO0_ROOT, "aclk_vo0_root", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(116), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(55), 0, GFLAGS),
+ COMPOSITE_NODIV(HCLK_VO0_ROOT, "hclk_vo0_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(116), 6, 2, MFLAGS,
+ RK3588_CLKGATE_CON(55), 1, GFLAGS),
+ COMPOSITE_NODIV(HCLK_VO0_S_ROOT, "hclk_vo0_s_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(116), 8, 2, MFLAGS,
+ RK3588_CLKGATE_CON(55), 2, GFLAGS),
+ COMPOSITE_NODIV(PCLK_VO0_ROOT, "pclk_vo0_root", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(116), 10, 2, MFLAGS,
+ RK3588_CLKGATE_CON(55), 3, GFLAGS),
+ COMPOSITE_NODIV(PCLK_VO0_S_ROOT, "pclk_vo0_s_root", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(116), 12, 2, MFLAGS,
+ RK3588_CLKGATE_CON(55), 4, GFLAGS),
+ GATE(PCLK_DP0, "pclk_dp0", "pclk_vo0_root", 0,
+ RK3588_CLKGATE_CON(56), 4, GFLAGS),
+ GATE(PCLK_DP1, "pclk_dp1", "pclk_vo0_root", 0,
+ RK3588_CLKGATE_CON(56), 5, GFLAGS),
+ GATE(PCLK_S_DP0, "pclk_s_dp0", "pclk_vo0_s_root", 0,
+ RK3588_CLKGATE_CON(56), 6, GFLAGS),
+ GATE(PCLK_S_DP1, "pclk_s_dp1", "pclk_vo0_s_root", 0,
+ RK3588_CLKGATE_CON(56), 7, GFLAGS),
+ GATE(CLK_DP0, "clk_dp0", "aclk_vo0_root", 0,
+ RK3588_CLKGATE_CON(56), 8, GFLAGS),
+ GATE(CLK_DP1, "clk_dp1", "aclk_vo0_root", 0,
+ RK3588_CLKGATE_CON(56), 9, GFLAGS),
+ GATE(HCLK_HDCP_KEY0, "hclk_hdcp_key0", "hclk_vo0_s_root", 0,
+ RK3588_CLKGATE_CON(55), 11, GFLAGS),
+ GATE(PCLK_HDCP0, "pclk_hdcp0", "pclk_vo0_root", 0,
+ RK3588_CLKGATE_CON(55), 14, GFLAGS),
+ GATE(ACLK_TRNG0, "aclk_trng0", "aclk_vo0_root", 0,
+ RK3588_CLKGATE_CON(56), 0, GFLAGS),
+ GATE(PCLK_TRNG0, "pclk_trng0", "pclk_vo0_root", 0,
+ RK3588_CLKGATE_CON(56), 1, GFLAGS),
+ GATE(PCLK_VO0GRF, "pclk_vo0grf", "pclk_vo0_root", CLK_IGNORE_UNUSED,
+ RK3588_CLKGATE_CON(55), 10, GFLAGS),
+ COMPOSITE(CLK_I2S4_8CH_TX_SRC, "clk_i2s4_8ch_tx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(118), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(56), 11, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S4_8CH_TX_FRAC, "clk_i2s4_8ch_tx_frac", "clk_i2s4_8ch_tx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(119), 0,
+ RK3588_CLKGATE_CON(56), 12, GFLAGS,
+ &rk3588_i2s4_8ch_tx_fracmux),
+ GATE(MCLK_I2S4_8CH_TX, "mclk_i2s4_8ch_tx", "clk_i2s4_8ch_tx", 0,
+ RK3588_CLKGATE_CON(56), 13, GFLAGS),
+ COMPOSITE(CLK_I2S8_8CH_TX_SRC, "clk_i2s8_8ch_tx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(120), 8, 1, MFLAGS, 3, 5, DFLAGS,
+ RK3588_CLKGATE_CON(56), 15, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S8_8CH_TX_FRAC, "clk_i2s8_8ch_tx_frac", "clk_i2s8_8ch_tx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(121), 0,
+ RK3588_CLKGATE_CON(57), 0, GFLAGS,
+ &rk3588_i2s8_8ch_tx_fracmux),
+ GATE(MCLK_I2S8_8CH_TX, "mclk_i2s8_8ch_tx", "clk_i2s8_8ch_tx", 0,
+ RK3588_CLKGATE_CON(57), 1, GFLAGS),
+ COMPOSITE(CLK_SPDIF2_DP0_SRC, "clk_spdif2_dp0_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(122), 8, 1, MFLAGS, 3, 5, DFLAGS,
+ RK3588_CLKGATE_CON(57), 3, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_SPDIF2_DP0_FRAC, "clk_spdif2_dp0_frac", "clk_spdif2_dp0_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(123), 0,
+ RK3588_CLKGATE_CON(57), 4, GFLAGS,
+ &rk3588_spdif2_dp0_fracmux),
+ GATE(MCLK_SPDIF2_DP0, "mclk_spdif2_dp0", "clk_spdif2_dp0", 0,
+ RK3588_CLKGATE_CON(57), 5, GFLAGS),
+ GATE(MCLK_SPDIF2, "mclk_spdif2", "clk_spdif2_dp0", 0,
+ RK3588_CLKGATE_CON(57), 6, GFLAGS),
+ COMPOSITE(CLK_SPDIF5_DP1_SRC, "clk_spdif5_dp1_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(124), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(57), 8, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_SPDIF5_DP1_FRAC, "clk_spdif5_dp1_frac", "clk_spdif5_dp1_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(125), 0,
+ RK3588_CLKGATE_CON(57), 9, GFLAGS,
+ &rk3588_spdif5_dp1_fracmux),
+ GATE(MCLK_SPDIF5_DP1, "mclk_spdif5_dp1", "clk_spdif5_dp1", 0,
+ RK3588_CLKGATE_CON(57), 10, GFLAGS),
+ GATE(MCLK_SPDIF5, "mclk_spdif5", "clk_spdif5_dp1", 0,
+ RK3588_CLKGATE_CON(57), 11, GFLAGS),
+ COMPOSITE_NOMUX(CLK_AUX16M_0, "clk_aux16m_0", "gpll", 0,
+ RK3588_CLKSEL_CON(117), 0, 8, DFLAGS,
+ RK3588_CLKGATE_CON(56), 2, GFLAGS),
+ COMPOSITE_NOMUX(CLK_AUX16M_1, "clk_aux16m_1", "gpll", 0,
+ RK3588_CLKSEL_CON(117), 8, 8, DFLAGS,
+ RK3588_CLKGATE_CON(56), 3, GFLAGS),
+
+ /* vo1 */
+ COMPOSITE_HALFDIV(CLK_HDMITRX_REFSRC, "clk_hdmitrx_refsrc", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(157), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(65), 9, GFLAGS),
+ COMPOSITE(ACLK_HDCP1_ROOT, "aclk_hdcp1_root", aclk_hdcp1_root_p, 0,
+ RK3588_CLKSEL_CON(128), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(59), 0, GFLAGS),
+ COMPOSITE(ACLK_HDMIRX_ROOT, "aclk_hdmirx_root", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(128), 12, 1, MFLAGS, 7, 5, DFLAGS,
+ RK3588_CLKGATE_CON(59), 1, GFLAGS),
+ COMPOSITE_NODIV(HCLK_VO1_ROOT, "hclk_vo1_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(128), 13, 2, MFLAGS,
+ RK3588_CLKGATE_CON(59), 2, GFLAGS),
+ COMPOSITE_NODIV(HCLK_VO1_S_ROOT, "hclk_vo1_s_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(129), 0, 2, MFLAGS,
+ RK3588_CLKGATE_CON(59), 3, GFLAGS),
+ COMPOSITE_NODIV(PCLK_VO1_ROOT, "pclk_vo1_root", mux_150m_100m_24m_p, 0,
+ RK3588_CLKSEL_CON(129), 2, 2, MFLAGS,
+ RK3588_CLKGATE_CON(59), 4, GFLAGS),
+ COMPOSITE_NODIV(PCLK_VO1_S_ROOT, "pclk_vo1_s_root", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(129), 4, 2, MFLAGS,
+ RK3588_CLKGATE_CON(59), 5, GFLAGS),
+ COMPOSITE(ACLK_VOP_ROOT, "aclk_vop_root", gpll_cpll_dmyaupll_npll_spll_p, 0,
+ RK3588_CLKSEL_CON(110), 5, 3, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(52), 0, GFLAGS),
+ COMPOSITE_NODIV(ACLK_VOP_LOW_ROOT, "aclk_vop_low_root", mux_400m_200m_100m_24m_p, 0,
+ RK3588_CLKSEL_CON(110), 8, 2, MFLAGS,
+ RK3588_CLKGATE_CON(52), 1, GFLAGS),
+ COMPOSITE_NODIV(HCLK_VOP_ROOT, "hclk_vop_root", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(110), 10, 2, MFLAGS,
+ RK3588_CLKGATE_CON(52), 2, GFLAGS),
+ COMPOSITE_NODIV(PCLK_VOP_ROOT, "pclk_vop_root", mux_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(110), 12, 2, MFLAGS,
+ RK3588_CLKGATE_CON(52), 3, GFLAGS),
+ COMPOSITE(ACLK_VO1USB_TOP_ROOT, "aclk_vo1usb_top_root", gpll_cpll_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(170), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(74), 0, GFLAGS),
+ COMPOSITE_NODIV(HCLK_VO1USB_TOP_ROOT, "hclk_vo1usb_top_root", mux_200m_100m_50m_24m_p, CLK_IS_CRITICAL,
+ RK3588_CLKSEL_CON(170), 6, 2, MFLAGS,
+ RK3588_CLKGATE_CON(74), 2, GFLAGS),
+ MUX(ACLK_VOP_SUB_SRC, "aclk_vop_sub_src", aclk_vop_sub_src_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(115), 9, 1, MFLAGS),
+ GATE(PCLK_EDP0, "pclk_edp0", "pclk_vo1_root", 0,
+ RK3588_CLKGATE_CON(62), 0, GFLAGS),
+ GATE(CLK_EDP0_24M, "clk_edp0_24m", "xin24m", 0,
+ RK3588_CLKGATE_CON(62), 1, GFLAGS),
+ COMPOSITE_NODIV(CLK_EDP0_200M, "clk_edp0_200m", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(140), 1, 2, MFLAGS,
+ RK3588_CLKGATE_CON(62), 2, GFLAGS),
+ GATE(PCLK_EDP1, "pclk_edp1", "pclk_vo1_root", 0,
+ RK3588_CLKGATE_CON(62), 3, GFLAGS),
+ GATE(CLK_EDP1_24M, "clk_edp1_24m", "xin24m", 0,
+ RK3588_CLKGATE_CON(62), 4, GFLAGS),
+ COMPOSITE_NODIV(CLK_EDP1_200M, "clk_edp1_200m", mux_200m_100m_50m_24m_p, 0,
+ RK3588_CLKSEL_CON(140), 3, 2, MFLAGS,
+ RK3588_CLKGATE_CON(62), 5, GFLAGS),
+ GATE(HCLK_HDCP_KEY1, "hclk_hdcp_key1", "hclk_vo1_s_root", 0,
+ RK3588_CLKGATE_CON(60), 4, GFLAGS),
+ GATE(PCLK_HDCP1, "pclk_hdcp1", "pclk_vo1_root", 0,
+ RK3588_CLKGATE_CON(60), 7, GFLAGS),
+ GATE(ACLK_HDMIRX, "aclk_hdmirx", "aclk_hdmirx_root", 0,
+ RK3588_CLKGATE_CON(61), 9, GFLAGS),
+ GATE(PCLK_HDMIRX, "pclk_hdmirx", "pclk_vo1_root", 0,
+ RK3588_CLKGATE_CON(61), 10, GFLAGS),
+ GATE(CLK_HDMIRX_REF, "clk_hdmirx_ref", "aclk_hdcp1_root", 0,
+ RK3588_CLKGATE_CON(61), 11, GFLAGS),
+ COMPOSITE(CLK_HDMIRX_AUD_SRC, "clk_hdmirx_aud_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(138), 8, 1, MFLAGS, 0, 8, DFLAGS,
+ RK3588_CLKGATE_CON(61), 12, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_HDMIRX_AUD_FRAC, "clk_hdmirx_aud_frac", "clk_hdmirx_aud_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(139), 0,
+ RK3588_CLKGATE_CON(61), 13, GFLAGS,
+ &rk3588_hdmirx_aud_fracmux),
+ GATE(CLK_HDMIRX_AUD, "clk_hdmirx_aud", "clk_hdmirx_aud_mux", 0,
+ RK3588_CLKGATE_CON(61), 14, GFLAGS),
+ GATE(PCLK_HDMITX0, "pclk_hdmitx0", "pclk_vo1_root", 0,
+ RK3588_CLKGATE_CON(60), 11, GFLAGS),
+ COMPOSITE(CLK_HDMITX0_EARC, "clk_hdmitx0_earc", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(133), 6, 1, MFLAGS, 1, 5, DFLAGS,
+ RK3588_CLKGATE_CON(60), 15, GFLAGS),
+ GATE(CLK_HDMITX0_REF, "clk_hdmitx0_ref", "aclk_hdcp1_root", 0,
+ RK3588_CLKGATE_CON(61), 0, GFLAGS),
+ GATE(PCLK_HDMITX1, "pclk_hdmitx1", "pclk_vo1_root", 0,
+ RK3588_CLKGATE_CON(61), 2, GFLAGS),
+ COMPOSITE(CLK_HDMITX1_EARC, "clk_hdmitx1_earc", gpll_cpll_p, 0,
+ RK3588_CLKSEL_CON(136), 6, 1, MFLAGS, 1, 5, DFLAGS,
+ RK3588_CLKGATE_CON(61), 6, GFLAGS),
+ GATE(CLK_HDMITX1_REF, "clk_hdmitx1_ref", "aclk_hdcp1_root", 0,
+ RK3588_CLKGATE_CON(61), 7, GFLAGS),
+ GATE(ACLK_TRNG1, "aclk_trng1", "aclk_hdcp1_root", 0,
+ RK3588_CLKGATE_CON(60), 9, GFLAGS),
+ GATE(PCLK_TRNG1, "pclk_trng1", "pclk_vo1_root", 0,
+ RK3588_CLKGATE_CON(60), 10, GFLAGS),
+ GATE(0, "pclk_vo1grf", "pclk_vo1_root", CLK_IGNORE_UNUSED,
+ RK3588_CLKGATE_CON(59), 12, GFLAGS),
+ GATE(PCLK_S_EDP0, "pclk_s_edp0", "pclk_vo1_s_root", 0,
+ RK3588_CLKGATE_CON(59), 14, GFLAGS),
+ GATE(PCLK_S_EDP1, "pclk_s_edp1", "pclk_vo1_s_root", 0,
+ RK3588_CLKGATE_CON(59), 15, GFLAGS),
+ GATE(PCLK_S_HDMIRX, "pclk_s_hdmirx", "pclk_vo1_s_root", 0,
+ RK3588_CLKGATE_CON(65), 8, GFLAGS),
+ COMPOSITE(CLK_I2S10_8CH_RX_SRC, "clk_i2s10_8ch_rx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(155), 8, 1, MFLAGS, 3, 5, DFLAGS,
+ RK3588_CLKGATE_CON(65), 5, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S10_8CH_RX_FRAC, "clk_i2s10_8ch_rx_frac", "clk_i2s10_8ch_rx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(156), 0,
+ RK3588_CLKGATE_CON(65), 6, GFLAGS,
+ &rk3588_i2s10_8ch_rx_fracmux),
+ GATE(MCLK_I2S10_8CH_RX, "mclk_i2s10_8ch_rx", "clk_i2s10_8ch_rx", 0,
+ RK3588_CLKGATE_CON(65), 7, GFLAGS),
+ COMPOSITE(CLK_I2S7_8CH_RX_SRC, "clk_i2s7_8ch_rx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(129), 11, 1, MFLAGS, 6, 5, DFLAGS,
+ RK3588_CLKGATE_CON(60), 1, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S7_8CH_RX_FRAC, "clk_i2s7_8ch_rx_frac", "clk_i2s7_8ch_rx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(130), 0,
+ RK3588_CLKGATE_CON(60), 2, GFLAGS,
+ &rk3588_i2s7_8ch_rx_fracmux),
+ GATE(MCLK_I2S7_8CH_RX, "mclk_i2s7_8ch_rx", "clk_i2s7_8ch_rx", 0,
+ RK3588_CLKGATE_CON(60), 3, GFLAGS),
+ COMPOSITE(CLK_I2S9_8CH_RX_SRC, "clk_i2s9_8ch_rx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(153), 12, 1, MFLAGS, 7, 5, DFLAGS,
+ RK3588_CLKGATE_CON(65), 1, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S9_8CH_RX_FRAC, "clk_i2s9_8ch_rx_frac", "clk_i2s9_8ch_rx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(154), 0,
+ RK3588_CLKGATE_CON(65), 2, GFLAGS,
+ &rk3588_i2s9_8ch_rx_fracmux),
+ GATE(MCLK_I2S9_8CH_RX, "mclk_i2s9_8ch_rx", "clk_i2s9_8ch_rx", 0,
+ RK3588_CLKGATE_CON(65), 3, GFLAGS),
+ COMPOSITE(CLK_I2S5_8CH_TX_SRC, "clk_i2s5_8ch_tx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(140), 10, 1, MFLAGS, 5, 5, DFLAGS,
+ RK3588_CLKGATE_CON(62), 6, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S5_8CH_TX_FRAC, "clk_i2s5_8ch_tx_frac", "clk_i2s5_8ch_tx_src", 0,
+ RK3588_CLKSEL_CON(141), 0,
+ RK3588_CLKGATE_CON(62), 7, GFLAGS,
+ &rk3588_i2s5_8ch_tx_fracmux),
+ GATE(MCLK_I2S5_8CH_TX, "mclk_i2s5_8ch_tx", "clk_i2s5_8ch_tx", 0,
+ RK3588_CLKGATE_CON(62), 8, GFLAGS),
+ COMPOSITE(CLK_I2S6_8CH_TX_SRC, "clk_i2s6_8ch_tx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(144), 8, 1, MFLAGS, 3, 5, DFLAGS,
+ RK3588_CLKGATE_CON(62), 13, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S6_8CH_TX_FRAC, "clk_i2s6_8ch_tx_frac", "clk_i2s6_8ch_tx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(145), 0,
+ RK3588_CLKGATE_CON(62), 14, GFLAGS,
+ &rk3588_i2s6_8ch_tx_fracmux),
+ GATE(MCLK_I2S6_8CH_TX, "mclk_i2s6_8ch_tx", "clk_i2s6_8ch_tx", 0,
+ RK3588_CLKGATE_CON(62), 15, GFLAGS),
+ COMPOSITE(CLK_I2S6_8CH_RX_SRC, "clk_i2s6_8ch_rx_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(146), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(63), 0, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S6_8CH_RX_FRAC, "clk_i2s6_8ch_rx_frac", "clk_i2s6_8ch_rx_src", 0,
+ RK3588_CLKSEL_CON(147), 0,
+ RK3588_CLKGATE_CON(63), 1, GFLAGS,
+ &rk3588_i2s6_8ch_rx_fracmux),
+ GATE(MCLK_I2S6_8CH_RX, "mclk_i2s6_8ch_rx", "clk_i2s6_8ch_rx", 0,
+ RK3588_CLKGATE_CON(63), 2, GFLAGS),
+ MUX(I2S6_8CH_MCLKOUT, "i2s6_8ch_mclkout", i2s6_8ch_mclkout_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(148), 2, 2, MFLAGS),
+ COMPOSITE(CLK_SPDIF3_SRC, "clk_spdif3_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(148), 9, 1, MFLAGS, 4, 5, DFLAGS,
+ RK3588_CLKGATE_CON(63), 5, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_SPDIF3_FRAC, "clk_spdif3_frac", "clk_spdif3_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(149), 0,
+ RK3588_CLKGATE_CON(63), 6, GFLAGS,
+ &rk3588_spdif3_fracmux),
+ GATE(MCLK_SPDIF3, "mclk_spdif3", "clk_spdif3", 0,
+ RK3588_CLKGATE_CON(63), 7, GFLAGS),
+ COMPOSITE(CLK_SPDIF4_SRC, "clk_spdif4_src", gpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(150), 7, 1, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(63), 9, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_SPDIF4_FRAC, "clk_spdif4_frac", "clk_spdif4_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(151), 0,
+ RK3588_CLKGATE_CON(63), 10, GFLAGS,
+ &rk3588_spdif4_fracmux),
+ GATE(MCLK_SPDIF4, "mclk_spdif4", "clk_spdif4", 0,
+ RK3588_CLKGATE_CON(63), 11, GFLAGS),
+ COMPOSITE(MCLK_SPDIFRX0, "mclk_spdifrx0", gpll_cpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(152), 7, 2, MFLAGS, 2, 5, DFLAGS,
+ RK3588_CLKGATE_CON(63), 13, GFLAGS),
+ COMPOSITE(MCLK_SPDIFRX1, "mclk_spdifrx1", gpll_cpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(152), 14, 2, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(63), 15, GFLAGS),
+ COMPOSITE(MCLK_SPDIFRX2, "mclk_spdifrx2", gpll_cpll_aupll_p, 0,
+ RK3588_CLKSEL_CON(153), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(64), 1, GFLAGS),
+ GATE(CLK_HDMIHDP0, "clk_hdmihdp0", "xin24m", 0,
+ RK3588_CLKGATE_CON(73), 12, GFLAGS),
+ GATE(CLK_HDMIHDP1, "clk_hdmihdp1", "xin24m", 0,
+ RK3588_CLKGATE_CON(73), 13, GFLAGS),
+ GATE(PCLK_HDPTX0, "pclk_hdptx0", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(72), 5, GFLAGS),
+ GATE(PCLK_HDPTX1, "pclk_hdptx1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(72), 6, GFLAGS),
+ GATE(PCLK_USBDPPHY0, "pclk_usbdpphy0", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(72), 2, GFLAGS),
+ GATE(PCLK_USBDPPHY1, "pclk_usbdpphy1", "pclk_top_root", 0,
+ RK3588_CLKGATE_CON(72), 4, GFLAGS),
+ GATE(HCLK_VOP, "hclk_vop", "hclk_vop_root", 0,
+ RK3588_CLKGATE_CON(52), 8, GFLAGS),
+ GATE(ACLK_VOP, "aclk_vop", "aclk_vop_sub_src", 0,
+ RK3588_CLKGATE_CON(52), 9, GFLAGS),
+ COMPOSITE(DCLK_VOP0_SRC, "dclk_vop0_src", gpll_cpll_v0pll_aupll_p, 0,
+ RK3588_CLKSEL_CON(111), 7, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3588_CLKGATE_CON(52), 10, GFLAGS),
+ COMPOSITE(DCLK_VOP1_SRC, "dclk_vop1_src", gpll_cpll_v0pll_aupll_p, 0,
+ RK3588_CLKSEL_CON(111), 14, 2, MFLAGS, 9, 5, DFLAGS,
+ RK3588_CLKGATE_CON(52), 11, GFLAGS),
+ COMPOSITE(DCLK_VOP2_SRC, "dclk_vop2_src", gpll_cpll_v0pll_aupll_p, CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+ RK3588_CLKSEL_CON(112), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_CLKGATE_CON(52), 12, GFLAGS),
+ COMPOSITE_NODIV(DCLK_VOP0, "dclk_vop0", dclk_vop0_p,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+ RK3588_CLKSEL_CON(112), 7, 2, MFLAGS,
+ RK3588_CLKGATE_CON(52), 13, GFLAGS),
+ COMPOSITE_NODIV(DCLK_VOP1, "dclk_vop1", dclk_vop1_p,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+ RK3588_CLKSEL_CON(112), 9, 2, MFLAGS,
+ RK3588_CLKGATE_CON(53), 0, GFLAGS),
+ COMPOSITE_NODIV(DCLK_VOP2, "dclk_vop2", dclk_vop2_p,
+ CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+ RK3588_CLKSEL_CON(112), 11, 2, MFLAGS,
+ RK3588_CLKGATE_CON(53), 1, GFLAGS),
+ COMPOSITE(DCLK_VOP3, "dclk_vop3", gpll_cpll_v0pll_aupll_p, 0,
+ RK3588_CLKSEL_CON(113), 7, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3588_CLKGATE_CON(53), 2, GFLAGS),
+ GATE(PCLK_DSIHOST0, "pclk_dsihost0", "pclk_vop_root", 0,
+ RK3588_CLKGATE_CON(53), 4, GFLAGS),
+ GATE(PCLK_DSIHOST1, "pclk_dsihost1", "pclk_vop_root", 0,
+ RK3588_CLKGATE_CON(53), 5, GFLAGS),
+ COMPOSITE(CLK_DSIHOST0, "clk_dsihost0", gpll_cpll_v0pll_spll_p, 0,
+ RK3588_CLKSEL_CON(114), 7, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3588_CLKGATE_CON(53), 6, GFLAGS),
+ COMPOSITE(CLK_DSIHOST1, "clk_dsihost1", gpll_cpll_v0pll_spll_p, 0,
+ RK3588_CLKSEL_CON(115), 7, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3588_CLKGATE_CON(53), 7, GFLAGS),
+ GATE(CLK_VOP_PMU, "clk_vop_pmu", "xin24m", CLK_IGNORE_UNUSED,
+ RK3588_CLKGATE_CON(53), 8, GFLAGS),
+ GATE(ACLK_VOP_DOBY, "aclk_vop_doby", "aclk_vop_root", 0,
+ RK3588_CLKGATE_CON(53), 10, GFLAGS),
+ GATE(CLK_USBDP_PHY0_IMMORTAL, "clk_usbdp_phy0_immortal", "xin24m", CLK_IGNORE_UNUSED,
+ RK3588_CLKGATE_CON(2), 8, GFLAGS),
+ GATE(CLK_USBDP_PHY1_IMMORTAL, "clk_usbdp_phy1_immortal", "xin24m", CLK_IGNORE_UNUSED,
+ RK3588_CLKGATE_CON(2), 15, GFLAGS),
+
+ GATE(CLK_REF_PIPE_PHY0_OSC_SRC, "clk_ref_pipe_phy0_osc_src", "xin24m", 0,
+ RK3588_CLKGATE_CON(77), 0, GFLAGS),
+ GATE(CLK_REF_PIPE_PHY1_OSC_SRC, "clk_ref_pipe_phy1_osc_src", "xin24m", 0,
+ RK3588_CLKGATE_CON(77), 1, GFLAGS),
+ GATE(CLK_REF_PIPE_PHY2_OSC_SRC, "clk_ref_pipe_phy2_osc_src", "xin24m", 0,
+ RK3588_CLKGATE_CON(77), 2, GFLAGS),
+ COMPOSITE_NOMUX(CLK_REF_PIPE_PHY0_PLL_SRC, "clk_ref_pipe_phy0_pll_src", "ppll", 0,
+ RK3588_CLKSEL_CON(176), 0, 6, DFLAGS,
+ RK3588_CLKGATE_CON(77), 3, GFLAGS),
+ COMPOSITE_NOMUX(CLK_REF_PIPE_PHY1_PLL_SRC, "clk_ref_pipe_phy1_pll_src", "ppll", 0,
+ RK3588_CLKSEL_CON(176), 6, 6, DFLAGS,
+ RK3588_CLKGATE_CON(77), 4, GFLAGS),
+ COMPOSITE_NOMUX(CLK_REF_PIPE_PHY2_PLL_SRC, "clk_ref_pipe_phy2_pll_src", "ppll", 0,
+ RK3588_CLKSEL_CON(177), 0, 6, DFLAGS,
+ RK3588_CLKGATE_CON(77), 5, GFLAGS),
+ MUX(CLK_REF_PIPE_PHY0, "clk_ref_pipe_phy0", clk_ref_pipe_phy0_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(177), 6, 1, MFLAGS),
+ MUX(CLK_REF_PIPE_PHY1, "clk_ref_pipe_phy1", clk_ref_pipe_phy1_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(177), 7, 1, MFLAGS),
+ MUX(CLK_REF_PIPE_PHY2, "clk_ref_pipe_phy2", clk_ref_pipe_phy2_p, CLK_SET_RATE_PARENT,
+ RK3588_CLKSEL_CON(177), 8, 1, MFLAGS),
+
+ /* pmu */
+ COMPOSITE(CLK_PMU1_300M_SRC, "clk_pmu1_300m_src", pmu_300m_24m_p, 0,
+ RK3588_PMU_CLKSEL_CON(0), 15, 1, MFLAGS, 10, 5, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(0), 3, GFLAGS),
+ COMPOSITE(CLK_PMU1_400M_SRC, "clk_pmu1_400m_src", pmu_400m_24m_p, 0,
+ RK3588_PMU_CLKSEL_CON(1), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(0), 4, GFLAGS),
+ COMPOSITE_NOMUX(CLK_PMU1_50M_SRC, "clk_pmu1_50m_src", "clk_pmu1_400m_src", 0,
+ RK3588_PMU_CLKSEL_CON(0), 0, 4, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(0), 0, GFLAGS),
+ COMPOSITE_NOMUX(CLK_PMU1_100M_SRC, "clk_pmu1_100m_src", "clk_pmu1_400m_src", 0,
+ RK3588_PMU_CLKSEL_CON(0), 4, 3, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(0), 1, GFLAGS),
+ COMPOSITE_NOMUX(CLK_PMU1_200M_SRC, "clk_pmu1_200m_src", "clk_pmu1_400m_src", 0,
+ RK3588_PMU_CLKSEL_CON(0), 7, 3, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(0), 2, GFLAGS),
+ COMPOSITE_NODIV(HCLK_PMU1_ROOT, "hclk_pmu1_root", hclk_pmu1_root_p, CLK_IS_CRITICAL,
+ RK3588_PMU_CLKSEL_CON(1), 6, 2, MFLAGS,
+ RK3588_PMU_CLKGATE_CON(0), 5, GFLAGS),
+ COMPOSITE_NODIV(PCLK_PMU1_ROOT, "pclk_pmu1_root", pmu_100m_50m_24m_src_p, CLK_IS_CRITICAL,
+ RK3588_PMU_CLKSEL_CON(1), 8, 2, MFLAGS,
+ RK3588_PMU_CLKGATE_CON(0), 7, GFLAGS),
+ GATE(PCLK_PMU0_ROOT, "pclk_pmu0_root", "pclk_pmu1_root", CLK_IS_CRITICAL,
+ RK3588_PMU_CLKGATE_CON(5), 0, GFLAGS),
+ COMPOSITE_NODIV(HCLK_PMU_CM0_ROOT, "hclk_pmu_cm0_root", hclk_pmu_cm0_root_p, CLK_IS_CRITICAL,
+ RK3588_PMU_CLKSEL_CON(1), 10, 2, MFLAGS,
+ RK3588_PMU_CLKGATE_CON(0), 8, GFLAGS),
+ GATE(CLK_PMU0, "clk_pmu0", "xin24m", CLK_IS_CRITICAL,
+ RK3588_PMU_CLKGATE_CON(5), 1, GFLAGS),
+ GATE(PCLK_PMU0, "pclk_pmu0", "pclk_pmu0_root", CLK_IS_CRITICAL,
+ RK3588_PMU_CLKGATE_CON(5), 2, GFLAGS),
+ GATE(PCLK_PMU0IOC, "pclk_pmu0ioc", "pclk_pmu0_root", CLK_IS_CRITICAL,
+ RK3588_PMU_CLKGATE_CON(5), 4, GFLAGS),
+ GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pmu0_root", 0,
+ RK3588_PMU_CLKGATE_CON(5), 5, GFLAGS),
+ COMPOSITE_NODIV(DBCLK_GPIO0, "dbclk_gpio0", mux_24m_32k_p, 0,
+ RK3588_PMU_CLKSEL_CON(17), 0, 1, MFLAGS,
+ RK3588_PMU_CLKGATE_CON(5), 6, GFLAGS),
+ GATE(PCLK_I2C0, "pclk_i2c0", "pclk_pmu0_root", 0,
+ RK3588_PMU_CLKGATE_CON(2), 1, GFLAGS),
+ COMPOSITE_NODIV(CLK_I2C0, "clk_i2c0", pmu_200m_100m_p, 0,
+ RK3588_PMU_CLKSEL_CON(3), 6, 1, MFLAGS,
+ RK3588_PMU_CLKGATE_CON(2), 2, GFLAGS),
+ GATE(HCLK_I2S1_8CH, "hclk_i2s1_8ch", "hclk_pmu1_root", 0,
+ RK3588_PMU_CLKGATE_CON(2), 7, GFLAGS),
+ COMPOSITE_NOMUX(CLK_I2S1_8CH_TX_SRC, "clk_i2s1_8ch_tx_src", "cpll", 0,
+ RK3588_PMU_CLKSEL_CON(5), 2, 5, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(2), 8, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S1_8CH_TX_FRAC, "clk_i2s1_8ch_tx_frac", "clk_i2s1_8ch_tx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_PMU_CLKSEL_CON(6), 0,
+ RK3588_PMU_CLKGATE_CON(2), 9, GFLAGS,
+ &rk3588_i2s1_8ch_tx_fracmux),
+ GATE(MCLK_I2S1_8CH_TX, "mclk_i2s1_8ch_tx", "clk_i2s1_8ch_tx", 0,
+ RK3588_PMU_CLKGATE_CON(2), 10, GFLAGS),
+ COMPOSITE_NOMUX(CLK_I2S1_8CH_RX_SRC, "clk_i2s1_8ch_rx_src", "cpll", 0,
+ RK3588_PMU_CLKSEL_CON(7), 2, 5, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(2), 11, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_I2S1_8CH_RX_FRAC, "clk_i2s1_8ch_rx_frac", "clk_i2s1_8ch_rx_src",
+ CLK_SET_RATE_PARENT,
+ RK3588_PMU_CLKSEL_CON(8), 0,
+ RK3588_PMU_CLKGATE_CON(2), 12, GFLAGS,
+ &rk3588_i2s1_8ch_rx_fracmux),
+ GATE(MCLK_I2S1_8CH_RX, "mclk_i2s1_8ch_rx", "clk_i2s1_8ch_rx", 0,
+ RK3588_PMU_CLKGATE_CON(2), 13, GFLAGS),
+ MUX(I2S1_8CH_MCLKOUT, "i2s1_8ch_mclkout", i2s1_8ch_mclkout_p, CLK_SET_RATE_PARENT,
+ RK3588_PMU_CLKSEL_CON(9), 2, 2, MFLAGS),
+ GATE(PCLK_PMU1, "pclk_pmu1", "pclk_pmu0_root", CLK_IS_CRITICAL,
+ RK3588_PMU_CLKGATE_CON(1), 0, GFLAGS),
+ GATE(CLK_DDR_FAIL_SAFE, "clk_ddr_fail_safe", "clk_pmu0", CLK_IGNORE_UNUSED,
+ RK3588_PMU_CLKGATE_CON(1), 1, GFLAGS),
+ GATE(CLK_PMU1, "clk_pmu1", "clk_pmu0", CLK_IS_CRITICAL,
+ RK3588_PMU_CLKGATE_CON(1), 3, GFLAGS),
+ GATE(HCLK_PDM0, "hclk_pdm0", "hclk_pmu1_root", 0,
+ RK3588_PMU_CLKGATE_CON(2), 14, GFLAGS),
+ COMPOSITE_NODIV(MCLK_PDM0, "mclk_pdm0", mclk_pdm0_p, 0,
+ RK3588_PMU_CLKSEL_CON(9), 4, 1, MFLAGS,
+ RK3588_PMU_CLKGATE_CON(2), 15, GFLAGS),
+ GATE(HCLK_VAD, "hclk_vad", "hclk_pmu1_root", 0,
+ RK3588_PMU_CLKGATE_CON(3), 0, GFLAGS),
+ GATE(FCLK_PMU_CM0_CORE, "fclk_pmu_cm0_core", "hclk_pmu_cm0_root", CLK_IS_CRITICAL,
+ RK3588_PMU_CLKGATE_CON(0), 13, GFLAGS),
+ COMPOSITE(CLK_PMU_CM0_RTC, "clk_pmu_cm0_rtc", mux_24m_32k_p, CLK_IS_CRITICAL,
+ RK3588_PMU_CLKSEL_CON(2), 5, 1, MFLAGS, 0, 5, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(0), 15, GFLAGS),
+ GATE(PCLK_PMU1_IOC, "pclk_pmu1_ioc", "pclk_pmu0_root", CLK_IGNORE_UNUSED,
+ RK3588_PMU_CLKGATE_CON(1), 5, GFLAGS),
+ GATE(PCLK_PMU1PWM, "pclk_pmu1pwm", "pclk_pmu0_root", 0,
+ RK3588_PMU_CLKGATE_CON(1), 12, GFLAGS),
+ COMPOSITE_NODIV(CLK_PMU1PWM, "clk_pmu1pwm", pmu_100m_50m_24m_src_p, 0,
+ RK3588_PMU_CLKSEL_CON(2), 9, 2, MFLAGS,
+ RK3588_PMU_CLKGATE_CON(1), 13, GFLAGS),
+ GATE(CLK_PMU1PWM_CAPTURE, "clk_pmu1pwm_capture", "xin24m", 0,
+ RK3588_PMU_CLKGATE_CON(1), 14, GFLAGS),
+ GATE(PCLK_PMU1TIMER, "pclk_pmu1timer", "pclk_pmu0_root", 0,
+ RK3588_PMU_CLKGATE_CON(1), 8, GFLAGS),
+ COMPOSITE_NODIV(CLK_PMU1TIMER_ROOT, "clk_pmu1timer_root", pmu_24m_32k_100m_src_p, 0,
+ RK3588_PMU_CLKSEL_CON(2), 7, 2, MFLAGS,
+ RK3588_PMU_CLKGATE_CON(1), 9, GFLAGS),
+ GATE(CLK_PMU1TIMER0, "clk_pmu1timer0", "clk_pmu1timer_root", 0,
+ RK3588_PMU_CLKGATE_CON(1), 10, GFLAGS),
+ GATE(CLK_PMU1TIMER1, "clk_pmu1timer1", "clk_pmu1timer_root", 0,
+ RK3588_PMU_CLKGATE_CON(1), 11, GFLAGS),
+ COMPOSITE_NOMUX(CLK_UART0_SRC, "clk_uart0_src", "cpll", 0,
+ RK3588_PMU_CLKSEL_CON(3), 7, 5, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(2), 3, GFLAGS),
+ COMPOSITE_FRACMUX(CLK_UART0_FRAC, "clk_uart0_frac", "clk_uart0_src", CLK_SET_RATE_PARENT,
+ RK3588_PMU_CLKSEL_CON(4), 0,
+ RK3588_PMU_CLKGATE_CON(2), 4, GFLAGS,
+ &rk3588_uart0_fracmux),
+ GATE(SCLK_UART0, "sclk_uart0", "clk_uart0", 0,
+ RK3588_PMU_CLKGATE_CON(2), 5, GFLAGS),
+ GATE(PCLK_UART0, "pclk_uart0", "pclk_pmu0_root", 0,
+ RK3588_PMU_CLKGATE_CON(2), 6, GFLAGS),
+ GATE(PCLK_PMU1WDT, "pclk_pmu1wdt", "pclk_pmu0_root", 0,
+ RK3588_PMU_CLKGATE_CON(1), 6, GFLAGS),
+ COMPOSITE_NODIV(TCLK_PMU1WDT, "tclk_pmu1wdt", mux_24m_32k_p, 0,
+ RK3588_PMU_CLKSEL_CON(2), 6, 1, MFLAGS,
+ RK3588_PMU_CLKGATE_CON(1), 7, GFLAGS),
+ COMPOSITE(CLK_CR_PARA, "clk_cr_para", mux_24m_ppll_spll_p, 0,
+ RK3588_PMU_CLKSEL_CON(15), 5, 2, MFLAGS, 0, 5, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(4), 11, GFLAGS),
+ COMPOSITE(CLK_USB2PHY_HDPTXRXPHY_REF, "clk_usb2phy_hdptxrxphy_ref", mux_24m_ppll_p,
+ CLK_IS_CRITICAL,
+ RK3588_PMU_CLKSEL_CON(14), 14, 1, MFLAGS, 9, 5, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(4), 7, GFLAGS),
+ COMPOSITE(CLK_USBDPPHY_MIPIDCPPHY_REF, "clk_usbdpphy_mipidcpphy_ref", mux_24m_ppll_spll_p,
+ CLK_IS_CRITICAL,
+ RK3588_PMU_CLKSEL_CON(14), 7, 2, MFLAGS, 0, 7, DFLAGS,
+ RK3588_PMU_CLKGATE_CON(4), 3, GFLAGS),
+
+ GATE(CLK_PHY0_REF_ALT_P, "clk_phy0_ref_alt_p", "ppll", 0,
+ RK3588_PHYREF_ALT_GATE, 0, GFLAGS),
+ GATE(CLK_PHY0_REF_ALT_M, "clk_phy0_ref_alt_m", "ppll", 0,
+ RK3588_PHYREF_ALT_GATE, 1, GFLAGS),
+ GATE(CLK_PHY1_REF_ALT_P, "clk_phy1_ref_alt_p", "ppll", 0,
+ RK3588_PHYREF_ALT_GATE, 2, GFLAGS),
+ GATE(CLK_PHY1_REF_ALT_M, "clk_phy1_ref_alt_m", "ppll", 0,
+ RK3588_PHYREF_ALT_GATE, 3, GFLAGS),
+
+ GATE(HCLK_SPDIFRX0, "hclk_spdifrx0", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(63), 12, GFLAGS),
+ GATE(HCLK_SPDIFRX1, "hclk_spdifrx1", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(63), 14, GFLAGS),
+ GATE(HCLK_SPDIFRX2, "hclk_spdifrx2", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(64), 0, GFLAGS),
+ GATE(HCLK_SPDIF4, "hclk_spdif4", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(63), 8, GFLAGS),
+ GATE(HCLK_SPDIF3, "hclk_spdif3", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(63), 4, GFLAGS),
+ GATE(HCLK_I2S6_8CH, "hclk_i2s6_8ch", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(63), 3, GFLAGS),
+ GATE(HCLK_I2S5_8CH, "hclk_i2s5_8ch", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(62), 12, GFLAGS),
+ GATE(HCLK_I2S9_8CH, "hclk_i2s9_8ch", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(65), 0, GFLAGS),
+ GATE(HCLK_I2S7_8CH, "hclk_i2s7_8ch", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(60), 0, GFLAGS),
+ GATE(HCLK_I2S10_8CH, "hclk_i2s10_8ch", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(65), 4, GFLAGS),
+ GATE(ACLK_HDCP1, "aclk_hdcp1", "aclk_hdcp1_pre", 0,
+ RK3588_CLKGATE_CON(60), 5, GFLAGS),
+ GATE(HCLK_HDCP1, "hclk_hdcp1", "hclk_vo1", 0,
+ RK3588_CLKGATE_CON(60), 6, GFLAGS),
+ GATE(HCLK_SPDIF5_DP1, "hclk_spdif5_dp1", "hclk_vo0", 0,
+ RK3588_CLKGATE_CON(57), 7, GFLAGS),
+ GATE(HCLK_SPDIF2_DP0, "hclk_spdif2_dp0", "hclk_vo0", 0,
+ RK3588_CLKGATE_CON(57), 2, GFLAGS),
+ GATE(HCLK_I2S8_8CH, "hclk_i2s8_8ch", "hclk_vo0", 0,
+ RK3588_CLKGATE_CON(56), 14, GFLAGS),
+ GATE(HCLK_I2S4_8CH, "hclk_i2s4_8ch", "hclk_vo0", 0,
+ RK3588_CLKGATE_CON(56), 10, GFLAGS),
+ GATE(ACLK_HDCP0, "aclk_hdcp0", "aclk_hdcp0_pre", 0,
+ RK3588_CLKGATE_CON(55), 12, GFLAGS),
+ GATE(HCLK_HDCP0, "hclk_hdcp0", "hclk_vo0", 0,
+ RK3588_CLKGATE_CON(55), 13, GFLAGS),
+ GATE(HCLK_RKVENC1, "hclk_rkvenc1", "hclk_rkvenc1_pre", 0,
+ RK3588_CLKGATE_CON(48), 4, GFLAGS),
+ GATE(ACLK_RKVENC1, "aclk_rkvenc1", "aclk_rkvenc1_pre", 0,
+ RK3588_CLKGATE_CON(48), 5, GFLAGS),
+ GATE(ACLK_VPU, "aclk_vpu", "aclk_vdpu_low_pre", 0,
+ RK3588_CLKGATE_CON(44), 8, GFLAGS),
+ GATE(ACLK_IEP2P0, "aclk_iep2p0", "aclk_vdpu_low_pre", 0,
+ RK3588_CLKGATE_CON(45), 5, GFLAGS),
+ GATE(ACLK_JPEG_ENCODER0, "aclk_jpeg_encoder0", "aclk_vdpu_low_pre", 0,
+ RK3588_CLKGATE_CON(44), 10, GFLAGS),
+ GATE(ACLK_JPEG_ENCODER1, "aclk_jpeg_encoder1", "aclk_vdpu_low_pre", 0,
+ RK3588_CLKGATE_CON(44), 12, GFLAGS),
+ GATE(ACLK_JPEG_ENCODER2, "aclk_jpeg_encoder2", "aclk_vdpu_low_pre", 0,
+ RK3588_CLKGATE_CON(44), 14, GFLAGS),
+ GATE(ACLK_JPEG_ENCODER3, "aclk_jpeg_encoder3", "aclk_vdpu_low_pre", 0,
+ RK3588_CLKGATE_CON(45), 0, GFLAGS),
+ GATE(ACLK_JPEG_DECODER, "aclk_jpeg_decoder", "aclk_jpeg_decoder_pre", 0,
+ RK3588_CLKGATE_CON(45), 2, GFLAGS),
+ GATE(ACLK_USB3OTG1, "aclk_usb3otg1", "aclk_usb", 0,
+ RK3588_CLKGATE_CON(42), 7, GFLAGS),
+ GATE(HCLK_HOST0, "hclk_host0", "hclk_usb", 0,
+ RK3588_CLKGATE_CON(42), 10, GFLAGS),
+ GATE(HCLK_HOST_ARB0, "hclk_host_arb0", "hclk_usb", 0,
+ RK3588_CLKGATE_CON(42), 11, GFLAGS),
+ GATE(HCLK_HOST1, "hclk_host1", "hclk_usb", 0,
+ RK3588_CLKGATE_CON(42), 12, GFLAGS),
+ GATE(HCLK_HOST_ARB1, "hclk_host_arb1", "hclk_usb", 0,
+ RK3588_CLKGATE_CON(42), 13, GFLAGS),
+ GATE(ACLK_USB3OTG0, "aclk_usb3otg0", "aclk_usb", 0,
+ RK3588_CLKGATE_CON(42), 4, GFLAGS),
+ MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "scmi_cclk_sd", RK3588_SDMMC_CON0, 1),
+ MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "scmi_cclk_sd", RK3588_SDMMC_CON1, 1),
+ GATE(HCLK_SDIO, "hclk_sdio", "hclk_sdio_pre", 0,
+ RK3588_CLKGATE_CON(75), 2, GFLAGS),
+ GATE(HCLK_RKVDEC1, "hclk_rkvdec1", "hclk_rkvdec1_pre", 0,
+ RK3588_CLKGATE_CON(41), 2, GFLAGS),
+ GATE(ACLK_RKVDEC1, "aclk_rkvdec1", "aclk_rkvdec1_pre", 0,
+ RK3588_CLKGATE_CON(41), 3, GFLAGS),
+ GATE(HCLK_RKVDEC0, "hclk_rkvdec0", "hclk_rkvdec0_pre", 0,
+ RK3588_CLKGATE_CON(40), 3, GFLAGS),
+ GATE(ACLK_RKVDEC0, "aclk_rkvdec0", "aclk_rkvdec0_pre", 0,
+ RK3588_CLKGATE_CON(40), 4, GFLAGS),
+ GATE(CLK_PCIE4L_PIPE, "clk_pcie4l_pipe", "clk_pipe30phy_pipe0_i", 0,
+ RK3588_CLKGATE_CON(39), 0, GFLAGS),
+ GATE(CLK_PCIE2L_PIPE, "clk_pcie2l_pipe", "clk_pipe30phy_pipe2_i", 0,
+ RK3588_CLKGATE_CON(39), 1, GFLAGS),
+ GATE(CLK_PIPEPHY0_PIPE_G, "clk_pipephy0_pipe_g", "clk_pipephy0_pipe_i", 0,
+ RK3588_CLKGATE_CON(38), 3, GFLAGS),
+ GATE(CLK_PIPEPHY1_PIPE_G, "clk_pipephy1_pipe_g", "clk_pipephy1_pipe_i", 0,
+ RK3588_CLKGATE_CON(38), 4, GFLAGS),
+ GATE(CLK_PIPEPHY2_PIPE_G, "clk_pipephy2_pipe_g", "clk_pipephy2_pipe_i", 0,
+ RK3588_CLKGATE_CON(38), 5, GFLAGS),
+ GATE(CLK_PIPEPHY0_PIPE_ASIC_G, "clk_pipephy0_pipe_asic_g", "clk_pipephy0_pipe_i", 0,
+ RK3588_CLKGATE_CON(38), 6, GFLAGS),
+ GATE(CLK_PIPEPHY1_PIPE_ASIC_G, "clk_pipephy1_pipe_asic_g", "clk_pipephy1_pipe_i", 0,
+ RK3588_CLKGATE_CON(38), 7, GFLAGS),
+ GATE(CLK_PIPEPHY2_PIPE_ASIC_G, "clk_pipephy2_pipe_asic_g", "clk_pipephy2_pipe_i", 0,
+ RK3588_CLKGATE_CON(38), 8, GFLAGS),
+ GATE(CLK_PIPEPHY2_PIPE_U3_G, "clk_pipephy2_pipe_u3_g", "clk_pipephy2_pipe_i", 0,
+ RK3588_CLKGATE_CON(38), 9, GFLAGS),
+ GATE(CLK_PCIE1L2_PIPE, "clk_pcie1l2_pipe", "clk_pipephy0_pipe_g", 0,
+ RK3588_CLKGATE_CON(38), 13, GFLAGS),
+ GATE(CLK_PCIE1L0_PIPE, "clk_pcie1l0_pipe", "clk_pipephy1_pipe_g", 0,
+ RK3588_CLKGATE_CON(38), 14, GFLAGS),
+ GATE(CLK_PCIE1L1_PIPE, "clk_pcie1l1_pipe", "clk_pipephy2_pipe_g", 0,
+ RK3588_CLKGATE_CON(38), 15, GFLAGS),
+ GATE(HCLK_SFC, "hclk_sfc", "hclk_nvm", 0,
+ RK3588_CLKGATE_CON(31), 10, GFLAGS),
+ GATE(HCLK_SFC_XIP, "hclk_sfc_xip", "hclk_nvm", 0,
+ RK3588_CLKGATE_CON(31), 11, GFLAGS),
+ GATE(HCLK_EMMC, "hclk_emmc", "hclk_nvm", 0,
+ RK3588_CLKGATE_CON(31), 4, GFLAGS),
+ GATE(ACLK_ISP1, "aclk_isp1", "aclk_isp1_pre", 0,
+ RK3588_CLKGATE_CON(26), 5, GFLAGS),
+ GATE(HCLK_ISP1, "hclk_isp1", "hclk_isp1_pre", 0,
+ RK3588_CLKGATE_CON(26), 7, GFLAGS),
+ GATE(PCLK_AV1, "pclk_av1", "pclk_av1_pre", 0,
+ RK3588_CLKGATE_CON(68), 5, GFLAGS),
+ GATE(ACLK_AV1, "aclk_av1", "aclk_av1_pre", 0,
+ RK3588_CLKGATE_CON(68), 2, GFLAGS),
+
+ GATE_LINK(ACLK_ISP1_PRE, "aclk_isp1_pre", "aclk_isp1_root", "aclk_vi_root", 0, RK3588_CLKGATE_CON(26), 6, GFLAGS),
+ GATE_LINK(HCLK_ISP1_PRE, "hclk_isp1_pre", "hclk_isp1_root", "hclk_vi_root", 0, RK3588_CLKGATE_CON(26), 8, GFLAGS),
+ GATE_LINK(HCLK_NVM, "hclk_nvm", "hclk_nvm_root", "aclk_nvm_root", 0, RK3588_CLKGATE_CON(31), 2, GFLAGS),
+ GATE_LINK(ACLK_USB, "aclk_usb", "aclk_usb_root", "aclk_vo1usb_top_root", 0, RK3588_CLKGATE_CON(42), 2, GFLAGS),
+ GATE_LINK(HCLK_USB, "hclk_usb", "hclk_usb_root", "hclk_vo1usb_top_root", 0, RK3588_CLKGATE_CON(42), 3, GFLAGS),
+ GATE_LINK(ACLK_JPEG_DECODER_PRE, "aclk_jpeg_decoder_pre", "aclk_jpeg_decoder_root", "aclk_vdpu_root", 0, RK3588_CLKGATE_CON(44), 7, GFLAGS),
+ GATE_LINK(ACLK_VDPU_LOW_PRE, "aclk_vdpu_low_pre", "aclk_vdpu_low_root", "aclk_vdpu_root", 0, RK3588_CLKGATE_CON(44), 5, GFLAGS),
+ GATE_LINK(ACLK_RKVENC1_PRE, "aclk_rkvenc1_pre", "aclk_rkvenc1_root", "aclk_rkvenc0", 0, RK3588_CLKGATE_CON(48), 3, GFLAGS),
+ GATE_LINK(HCLK_RKVENC1_PRE, "hclk_rkvenc1_pre", "hclk_rkvenc1_root", "hclk_rkvenc0", 0, RK3588_CLKGATE_CON(48), 2, GFLAGS),
+ GATE_LINK(HCLK_RKVDEC0_PRE, "hclk_rkvdec0_pre", "hclk_rkvdec0_root", "hclk_vdpu_root", 0, RK3588_CLKGATE_CON(40), 5, GFLAGS),
+ GATE_LINK(ACLK_RKVDEC0_PRE, "aclk_rkvdec0_pre", "aclk_rkvdec0_root", "aclk_vdpu_root", 0, RK3588_CLKGATE_CON(40), 6, GFLAGS),
+ GATE_LINK(HCLK_RKVDEC1_PRE, "hclk_rkvdec1_pre", "hclk_rkvdec1_root", "hclk_vdpu_root", 0, RK3588_CLKGATE_CON(41), 4, GFLAGS),
+ GATE_LINK(ACLK_RKVDEC1_PRE, "aclk_rkvdec1_pre", "aclk_rkvdec1_root", "aclk_vdpu_root", 0, RK3588_CLKGATE_CON(41), 5, GFLAGS),
+ GATE_LINK(ACLK_HDCP0_PRE, "aclk_hdcp0_pre", "aclk_vo0_root", "aclk_vop_low_root", 0, RK3588_CLKGATE_CON(55), 9, GFLAGS),
+ GATE_LINK(HCLK_VO0, "hclk_vo0", "hclk_vo0_root", "hclk_vop_root", 0, RK3588_CLKGATE_CON(55), 5, GFLAGS),
+ GATE_LINK(ACLK_HDCP1_PRE, "aclk_hdcp1_pre", "aclk_hdcp1_root", "aclk_vo1usb_top_root", 0, RK3588_CLKGATE_CON(59), 6, GFLAGS),
+ GATE_LINK(HCLK_VO1, "hclk_vo1", "hclk_vo1_root", "hclk_vo1usb_top_root", 0, RK3588_CLKGATE_CON(59), 9, GFLAGS),
+ GATE_LINK(ACLK_AV1_PRE, "aclk_av1_pre", "aclk_av1_root", "aclk_vdpu_root", 0, RK3588_CLKGATE_CON(68), 1, GFLAGS),
+ GATE_LINK(PCLK_AV1_PRE, "pclk_av1_pre", "pclk_av1_root", "hclk_vdpu_root", 0, RK3588_CLKGATE_CON(68), 4, GFLAGS),
+ GATE_LINK(HCLK_SDIO_PRE, "hclk_sdio_pre", "hclk_sdio_root", "hclk_nvm", 0, RK3588_CLKGATE_CON(75), 1, GFLAGS),
+};
+
+static void __init rk3588_clk_init(struct device_node *np)
+{
+ struct rockchip_clk_provider *ctx;
+ void __iomem *reg_base;
+
+ reg_base = of_iomap(np, 0);
+ if (!reg_base) {
+ pr_err("%s: could not map cru region\n", __func__);
+ return;
+ }
+
+ ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
+ if (IS_ERR(ctx)) {
+ pr_err("%s: rockchip clk init failed\n", __func__);
+ iounmap(reg_base);
+ return;
+ }
+
+ rockchip_clk_register_plls(ctx, rk3588_pll_clks,
+ ARRAY_SIZE(rk3588_pll_clks),
+ RK3588_GRF_SOC_STATUS0);
+
+ rockchip_clk_register_armclk(ctx, ARMCLK_L, "armclk_l",
+ mux_armclkl_p, ARRAY_SIZE(mux_armclkl_p),
+ &rk3588_cpulclk_data, rk3588_cpulclk_rates,
+ ARRAY_SIZE(rk3588_cpulclk_rates));
+ rockchip_clk_register_armclk(ctx, ARMCLK_B01, "armclk_b01",
+ mux_armclkb01_p, ARRAY_SIZE(mux_armclkb01_p),
+ &rk3588_cpub0clk_data, rk3588_cpub0clk_rates,
+ ARRAY_SIZE(rk3588_cpub0clk_rates));
+ rockchip_clk_register_armclk(ctx, ARMCLK_B23, "armclk_b23",
+ mux_armclkb23_p, ARRAY_SIZE(mux_armclkb23_p),
+ &rk3588_cpub1clk_data, rk3588_cpub1clk_rates,
+ ARRAY_SIZE(rk3588_cpub1clk_rates));
+
+ rockchip_clk_register_branches(ctx, rk3588_clk_branches,
+ ARRAY_SIZE(rk3588_clk_branches));
+
+ rk3588_rst_init(np, reg_base);
+
+ rockchip_register_restart_notifier(ctx, RK3588_GLB_SRST_FST, NULL);
+
+ rockchip_clk_of_add_provider(np, ctx);
+}
+
+CLK_OF_DECLARE(rk3588_cru, "rockchip,rk3588-cru", rk3588_clk_init);
+
+struct clk_rk3588_inits {
+ void (*inits)(struct device_node *np);
+};
+
+static const struct clk_rk3588_inits clk_3588_cru_init = {
+ .inits = rk3588_clk_init,
+};
+
+static const struct of_device_id clk_rk3588_match_table[] = {
+ {
+ .compatible = "rockchip,rk3588-cru",
+ .data = &clk_3588_cru_init,
+ },
+ { }
+};
+
+static int __init clk_rk3588_probe(struct platform_device *pdev)
+{
+ const struct clk_rk3588_inits *init_data;
+ struct device *dev = &pdev->dev;
+
+ init_data = device_get_match_data(dev);
+ if (!init_data)
+ return -EINVAL;
+
+ if (init_data->inits)
+ init_data->inits(dev->of_node);
+
+ return 0;
+}
+
+static struct platform_driver clk_rk3588_driver = {
+ .driver = {
+ .name = "clk-rk3588",
+ .of_match_table = clk_rk3588_match_table,
+ .suppress_bind_attrs = true,
+ },
+};
+builtin_platform_driver_probe(clk_rk3588_driver, clk_rk3588_probe);
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c
index e63d4f20b479..a8646794575a 100644
--- a/drivers/clk/rockchip/clk.c
+++ b/drivers/clk/rockchip/clk.c
@@ -21,7 +21,6 @@
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/reboot.h>
-#include <linux/rational.h>
#include "../clk-fractional-divider.h"
#include "clk.h"
@@ -198,6 +197,12 @@ static void rockchip_fractional_approximation(struct clk_hw *hw,
clk_fractional_divider_general_approximation(hw, rate, parent_rate, m, n);
}
+static void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx,
+ struct clk *clk, unsigned int id)
+{
+ ctx->clk_data.clks[id] = clk;
+}
+
static struct clk *rockchip_clk_register_frac_branch(
struct rockchip_clk_provider *ctx, const char *name,
const char *const *parent_names, u8 num_parents,
@@ -401,14 +406,6 @@ void rockchip_clk_of_add_provider(struct device_node *np,
}
EXPORT_SYMBOL_GPL(rockchip_clk_of_add_provider);
-void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx,
- struct clk *clk, unsigned int id)
-{
- if (ctx->clk_data.clks && id)
- ctx->clk_data.clks[id] = clk;
-}
-EXPORT_SYMBOL_GPL(rockchip_clk_add_lookup);
-
void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx,
struct rockchip_pll_clock *list,
unsigned int nr_pll, int grf_lock_offset)
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h
index ee01739e4a7c..758ebaf2236b 100644
--- a/drivers/clk/rockchip/clk.h
+++ b/drivers/clk/rockchip/clk.h
@@ -235,11 +235,58 @@ struct clk;
#define RK3568_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x180)
#define RK3568_PMU_SOFTRST_CON(x) ((x) * 0x4 + 0x200)
+#define RK3588_PHP_CRU_BASE 0x8000
+#define RK3588_PMU_CRU_BASE 0x30000
+#define RK3588_BIGCORE0_CRU_BASE 0x50000
+#define RK3588_BIGCORE1_CRU_BASE 0x52000
+#define RK3588_DSU_CRU_BASE 0x58000
+
+#define RK3588_PLL_CON(x) RK2928_PLL_CON(x)
+#define RK3588_MODE_CON0 0x280
+#define RK3588_B0_PLL_MODE_CON0 (RK3588_BIGCORE0_CRU_BASE + 0x280)
+#define RK3588_B1_PLL_MODE_CON0 (RK3588_BIGCORE1_CRU_BASE + 0x280)
+#define RK3588_LPLL_MODE_CON0 (RK3588_DSU_CRU_BASE + 0x280)
+#define RK3588_CLKSEL_CON(x) ((x) * 0x4 + 0x300)
+#define RK3588_CLKGATE_CON(x) ((x) * 0x4 + 0x800)
+#define RK3588_SOFTRST_CON(x) ((x) * 0x4 + 0xa00)
+#define RK3588_GLB_CNT_TH 0xc00
+#define RK3588_GLB_SRST_FST 0xc08
+#define RK3588_GLB_SRST_SND 0xc0c
+#define RK3588_GLB_RST_CON 0xc10
+#define RK3588_GLB_RST_ST 0xc04
+#define RK3588_SDIO_CON0 0xC24
+#define RK3588_SDIO_CON1 0xC28
+#define RK3588_SDMMC_CON0 0xC30
+#define RK3588_SDMMC_CON1 0xC34
+
+#define RK3588_PHP_CLKGATE_CON(x) ((x) * 0x4 + RK3588_PHP_CRU_BASE + 0x800)
+#define RK3588_PHP_SOFTRST_CON(x) ((x) * 0x4 + RK3588_PHP_CRU_BASE + 0xa00)
+
+#define RK3588_PMU_PLL_CON(x) ((x) * 0x4 + RK3588_PHP_CRU_BASE)
+#define RK3588_PMU_CLKSEL_CON(x) ((x) * 0x4 + RK3588_PMU_CRU_BASE + 0x300)
+#define RK3588_PMU_CLKGATE_CON(x) ((x) * 0x4 + RK3588_PMU_CRU_BASE + 0x800)
+#define RK3588_PMU_SOFTRST_CON(x) ((x) * 0x4 + RK3588_PMU_CRU_BASE + 0xa00)
+
+#define RK3588_B0_PLL_CON(x) ((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE)
+#define RK3588_BIGCORE0_CLKSEL_CON(x) ((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE + 0x300)
+#define RK3588_BIGCORE0_CLKGATE_CON(x) ((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE + 0x800)
+#define RK3588_BIGCORE0_SOFTRST_CON(x) ((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE + 0xa00)
+#define RK3588_B1_PLL_CON(x) ((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE)
+#define RK3588_BIGCORE1_CLKSEL_CON(x) ((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE + 0x300)
+#define RK3588_BIGCORE1_CLKGATE_CON(x) ((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE + 0x800)
+#define RK3588_BIGCORE1_SOFTRST_CON(x) ((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE + 0xa00)
+#define RK3588_LPLL_CON(x) ((x) * 0x4 + RK3588_DSU_CRU_BASE)
+#define RK3588_DSU_CLKSEL_CON(x) ((x) * 0x4 + RK3588_DSU_CRU_BASE + 0x300)
+#define RK3588_DSU_CLKGATE_CON(x) ((x) * 0x4 + RK3588_DSU_CRU_BASE + 0x800)
+#define RK3588_DSU_SOFTRST_CON(x) ((x) * 0x4 + RK3588_DSU_CRU_BASE + 0xa00)
+
enum rockchip_pll_type {
pll_rk3036,
pll_rk3066,
pll_rk3328,
pll_rk3399,
+ pll_rk3588,
+ pll_rk3588_core,
};
#define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \
@@ -272,6 +319,15 @@ enum rockchip_pll_type {
.nb = _nb, \
}
+#define RK3588_PLL_RATE(_rate, _p, _m, _s, _k) \
+{ \
+ .rate = _rate##U, \
+ .p = _p, \
+ .m = _m, \
+ .s = _s, \
+ .k = _k, \
+}
+
/**
* struct rockchip_clk_provider - information about clock provider
* @reg_base: virtual address for the register base.
@@ -307,6 +363,13 @@ struct rockchip_pll_rate_table {
unsigned int dsmpd;
unsigned int frac;
};
+ struct {
+ /* for RK3588 */
+ unsigned int m;
+ unsigned int p;
+ unsigned int s;
+ unsigned int k;
+ };
};
};
@@ -376,11 +439,13 @@ struct rockchip_cpuclk_clksel {
u32 val;
};
-#define ROCKCHIP_CPUCLK_NUM_DIVIDERS 5
+#define ROCKCHIP_CPUCLK_NUM_DIVIDERS 6
#define ROCKCHIP_CPUCLK_MAX_CORES 4
struct rockchip_cpuclk_rate_table {
unsigned long prate;
struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
+ struct rockchip_cpuclk_clksel pre_muxs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
+ struct rockchip_cpuclk_clksel post_muxs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
};
/**
@@ -389,6 +454,8 @@ struct rockchip_cpuclk_rate_table {
* @div_core_shift[]: cores divider offset used to divide the pll value
* @div_core_mask[]: cores divider mask
* @num_cores: number of cpu cores
+ * @mux_core_reg: register offset of the cores select parent
+ * @mux_core_alt: mux value to select alternate parent
* @mux_core_main: mux value to select main parent of core
* @mux_core_shift: offset of the core multiplexer
* @mux_core_mask: core multiplexer mask
@@ -398,6 +465,7 @@ struct rockchip_cpuclk_reg_data {
u8 div_core_shift[ROCKCHIP_CPUCLK_MAX_CORES];
u32 div_core_mask[ROCKCHIP_CPUCLK_MAX_CORES];
int num_cores;
+ int mux_core_reg;
u8 mux_core_alt;
u8 mux_core_main;
u8 mux_core_shift;
@@ -905,8 +973,6 @@ struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,
void __iomem *base, unsigned long nr_clks);
void rockchip_clk_of_add_provider(struct device_node *np,
struct rockchip_clk_provider *ctx);
-void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx,
- struct clk *clk, unsigned int id);
void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
struct rockchip_clk_branch *list,
unsigned int nr_clk);
@@ -937,15 +1003,26 @@ struct clk *rockchip_clk_register_halfdiv(const char *name,
spinlock_t *lock);
#ifdef CONFIG_RESET_CONTROLLER
-void rockchip_register_softrst(struct device_node *np,
- unsigned int num_regs,
- void __iomem *base, u8 flags);
+void rockchip_register_softrst_lut(struct device_node *np,
+ const int *lookup_table,
+ unsigned int num_regs,
+ void __iomem *base, u8 flags);
#else
-static inline void rockchip_register_softrst(struct device_node *np,
- unsigned int num_regs,
- void __iomem *base, u8 flags)
+static inline void rockchip_register_softrst_lut(struct device_node *np,
+ const int *lookup_table,
+ unsigned int num_regs,
+ void __iomem *base, u8 flags)
{
}
#endif
+static inline void rockchip_register_softrst(struct device_node *np,
+ unsigned int num_regs,
+ void __iomem *base, u8 flags)
+{
+ return rockchip_register_softrst_lut(np, NULL, num_regs, base, flags);
+}
+
+void rk3588_rst_init(struct device_node *np, void __iomem *reg_base);
+
#endif
diff --git a/drivers/clk/rockchip/rst-rk3588.c b/drivers/clk/rockchip/rst-rk3588.c
new file mode 100644
index 000000000000..e855bb8d5413
--- /dev/null
+++ b/drivers/clk/rockchip/rst-rk3588.c
@@ -0,0 +1,857 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Copyright (c) 2021 Rockchip Electronics Co., Ltd.
+ * Copyright (c) 2022 Collabora Ltd.
+ * Author: Sebastian Reichel <sebastian.reichel@collabora.com>
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <dt-bindings/reset/rockchip,rk3588-cru.h>
+#include "clk.h"
+
+/* 0xFD7C0000 + 0x0A00 */
+#define RK3588_CRU_RESET_OFFSET(id, reg, bit) [id] = (0 + reg * 16 + bit)
+
+/* 0xFD7C8000 + 0x0A00 */
+#define RK3588_PHPTOPCRU_RESET_OFFSET(id, reg, bit) [id] = (0x8000*4 + reg * 16 + bit)
+
+/* 0xFD7D0000 + 0x0A00 */
+#define RK3588_SECURECRU_RESET_OFFSET(id, reg, bit) [id] = (0x10000*4 + reg * 16 + bit)
+
+/* 0xFD7F0000 + 0x0A00 */
+#define RK3588_PMU1CRU_RESET_OFFSET(id, reg, bit) [id] = (0x30000*4 + reg * 16 + bit)
+
+/* mapping table for reset ID to register offset */
+static const int rk3588_register_offset[] = {
+ /* SOFTRST_CON01 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_TOP_BIU, 1, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_TOP_BIU, 1, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CSIPHY0, 1, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_CSIPHY0, 1, 7), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_P_CSIPHY1, 1, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_CSIPHY1, 1, 9), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_A_TOP_M500_BIU, 1, 15),
+
+ /* SOFTRST_CON02 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_TOP_M400_BIU, 2, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_A_TOP_S200_BIU, 2, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_A_TOP_S400_BIU, 2, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_A_TOP_M300_BIU, 2, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_INIT, 2, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_CMN, 2, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_LANE, 2, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_PCS, 2, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_INIT, 2, 15),
+
+ /* SOFTRST_CON03 */
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_CMN, 3, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_LANE, 3, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_PCS, 3, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_DCPHY0, 3, 11), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_P_MIPI_DCPHY0, 3, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_P_MIPI_DCPHY0_GRF, 3, 15),
+
+ /* SOFTRST_CON04 */
+ RK3588_CRU_RESET_OFFSET(SRST_DCPHY1, 4, 0), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_P_MIPI_DCPHY1, 4, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_MIPI_DCPHY1_GRF, 4, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_CDPHY, 4, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_CSIPHY, 4, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_VCCIO3_5, 4, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_VCCIO6, 4, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_EMMCIO, 4, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_IOC_TOP, 4, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_IOC_RIGHT, 4, 11),
+
+ /* SOFTRST_CON05 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_CRU, 5, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_A_CHANNEL_SECURE2VO1USB, 5, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_A_CHANNEL_SECURE2CENTER, 5, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_H_CHANNEL_SECURE2VO1USB, 5, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_H_CHANNEL_SECURE2CENTER, 5, 15),
+
+ /* SOFTRST_CON06 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_CHANNEL_SECURE2VO1USB, 6, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CHANNEL_SECURE2CENTER, 6, 1),
+
+ /* SOFTRST_CON07 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_AUDIO_BIU, 7, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_AUDIO_BIU, 7, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S0_8CH, 7, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S0_8CH_TX, 7, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S0_8CH_RX, 7, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_P_ACDCDIG, 7, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S2_2CH, 7, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S3_2CH, 7, 13),
+
+ /* SOFTRST_CON08 */
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S2_2CH, 8, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S3_2CH, 8, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_DAC_ACDCDIG, 8, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SPDIF0, 8, 14),
+
+ /* SOFTRST_CON09 */
+ RK3588_CRU_RESET_OFFSET(SRST_M_SPDIF0, 9, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SPDIF1, 9, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_M_SPDIF1, 9, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_H_PDM1, 9, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_PDM1, 9, 7),
+
+ /* SOFTRST_CON10 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_BUS_BIU, 10, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_BUS_BIU, 10, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_A_GIC, 10, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_A_GIC_DBG, 10, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DMAC0, 10, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DMAC1, 10, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DMAC2, 10, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_I2C1, 10, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_I2C2, 10, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_I2C3, 10, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_P_I2C4, 10, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_P_I2C5, 10, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_I2C6, 10, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_P_I2C7, 10, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_P_I2C8, 10, 15),
+
+ /* SOFTRST_CON11 */
+ RK3588_CRU_RESET_OFFSET(SRST_I2C1, 11, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_I2C2, 11, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_I2C3, 11, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_I2C4, 11, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_I2C5, 11, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_I2C6, 11, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_I2C7, 11, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_I2C8, 11, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CAN0, 11, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_CAN0, 11, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CAN1, 11, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_CAN1, 11, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CAN2, 11, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_CAN2, 11, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_P_SARADC, 11, 14),
+
+ /* SOFTRST_CON12 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_TSADC, 12, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_TSADC, 12, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_UART1, 12, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_UART2, 12, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_UART3, 12, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_UART4, 12, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_P_UART5, 12, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_UART6, 12, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_UART7, 12, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_UART8, 12, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_UART9, 12, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_S_UART1, 12, 13),
+
+ /* SOFTRST_CON13 */
+ RK3588_CRU_RESET_OFFSET(SRST_S_UART2, 13, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_S_UART3, 13, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_S_UART4, 13, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_S_UART5, 13, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_S_UART6, 13, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_S_UART7, 13, 15),
+
+ /* SOFTRST_CON14 */
+ RK3588_CRU_RESET_OFFSET(SRST_S_UART8, 14, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_S_UART9, 14, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_P_SPI0, 14, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_SPI1, 14, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_SPI2, 14, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_SPI3, 14, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_SPI4, 14, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_SPI0, 14, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_SPI1, 14, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_SPI2, 14, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_SPI3, 14, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_SPI4, 14, 15),
+
+ /* SOFTRST_CON15 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_WDT0, 15, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_T_WDT0, 15, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_SYS_GRF, 15, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_PWM1, 15, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_PWM1, 15, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_PWM2, 15, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_PWM2, 15, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_PWM3, 15, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_PWM3, 15, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_P_BUSTIMER0, 15, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_BUSTIMER1, 15, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER0, 15, 15),
+
+ /* SOFTRST_CON16 */
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER1, 16, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER2, 16, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER3, 16, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER4, 16, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER5, 16, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER6, 16, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER7, 16, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER8, 16, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER9, 16, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER10, 16, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_BUSTIMER11, 16, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_P_MAILBOX0, 16, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_P_MAILBOX1, 16, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_MAILBOX2, 16, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_P_GPIO1, 16, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_GPIO1, 16, 15),
+
+ /* SOFTRST_CON17 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_GPIO2, 17, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_GPIO2, 17, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_GPIO3, 17, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_GPIO3, 17, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_GPIO4, 17, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_GPIO4, 17, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DECOM, 17, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DECOM, 17, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_D_DECOM, 17, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_TOP, 17, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_A_GICADB_GIC2CORE_BUS, 17, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DFT2APB, 17, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_TOP, 17, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_CDPHY, 17, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_BOT_RIGHT, 17, 15),
+
+ /* SOFTRST_CON18 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_IOC_TOP, 18, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_IOC_RIGHT, 18, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_CSIPHY, 18, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_VCCIO3_5, 18, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_VCCIO6, 18, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_MST_EMMCIO, 18, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_A_SPINLOCK, 18, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_OTPC_NS, 18, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_OTPC_NS, 18, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_OTPC_ARB, 18, 11),
+
+ /* SOFTRST_CON19 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_BUSIOC, 19, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_P_PMUCM0_INTMUX, 19, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDRCM0_INTMUX, 19, 5),
+
+ /* SOFTRST_CON20 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_DFICTL_CH0, 20, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_MON_CH0, 20, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_STANDBY_CH0, 20, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_UPCTL_CH0, 20, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_TM_DDR_MON_CH0, 20, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_GRF_CH01, 20, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_DFI_CH0, 20, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_SBR_CH0, 20, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_UPCTL_CH0, 20, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_DFICTL_CH0, 20, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_MON_CH0, 20, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_STANDBY_CH0, 20, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_CH0, 20, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_DFICTL_CH1, 20, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_MON_CH1, 20, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_STANDBY_CH1, 20, 15),
+
+ /* SOFTRST_CON21 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_UPCTL_CH1, 21, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_TM_DDR_MON_CH1, 21, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_DFI_CH1, 21, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_SBR_CH1, 21, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_UPCTL_CH1, 21, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_DFICTL_CH1, 21, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_MON_CH1, 21, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_STANDBY_CH1, 21, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_CH1, 21, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_MSCH0, 21, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_RS_MSCH0, 21, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_FRS_MSCH0, 21, 15),
+
+ /* SOFTRST_CON22 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_SCRAMBLE0, 22, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_FRS_SCRAMBLE0, 22, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_MSCH1, 22, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_RS_MSCH1, 22, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_FRS_MSCH1, 22, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_SCRAMBLE1, 22, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR01_FRS_SCRAMBLE1, 22, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR01_MSCH0, 22, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR01_MSCH1, 22, 8),
+
+ /* SOFTRST_CON23 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_DFICTL_CH2, 23, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_MON_CH2, 23, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_STANDBY_CH2, 23, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_UPCTL_CH2, 23, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_TM_DDR_MON_CH2, 23, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_GRF_CH23, 23, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_DFI_CH2, 23, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_SBR_CH2, 23, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_UPCTL_CH2, 23, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_DFICTL_CH2, 23, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_MON_CH2, 23, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_STANDBY_CH2, 23, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_CH2, 23, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_DFICTL_CH3, 23, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_MON_CH3, 23, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_STANDBY_CH3, 23, 15),
+
+ /* SOFTRST_CON24 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR_UPCTL_CH3, 24, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_TM_DDR_MON_CH3, 24, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_DFI_CH3, 24, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_SBR_CH3, 24, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_UPCTL_CH3, 24, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_DFICTL_CH3, 24, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_MON_CH3, 24, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_STANDBY_CH3, 24, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR_UPCTL_CH3, 24, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_MSCH2, 24, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_RS_MSCH2, 24, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_FRS_MSCH2, 24, 15),
+
+ /* SOFTRST_CON25 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_SCRAMBLE2, 25, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_FRS_SCRAMBLE2, 25, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_MSCH3, 25, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_RS_MSCH3, 25, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_FRS_MSCH3, 25, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_SCRAMBLE3, 25, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR23_FRS_SCRAMBLE3, 25, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR23_MSCH2, 25, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DDR23_MSCH3, 25, 8),
+
+ /* SOFTRST_CON26 */
+ RK3588_CRU_RESET_OFFSET(SRST_ISP1, 26, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_ISP1_VICAP, 26, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_ISP1_BIU, 26, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_H_ISP1_BIU, 26, 8),
+
+ /* SOFTRST_CON27 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKNN1, 27, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKNN1_BIU, 27, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKNN1, 27, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKNN1_BIU, 27, 3),
+
+ /* SOFTRST_CON28 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKNN2, 28, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKNN2_BIU, 28, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKNN2, 28, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKNN2_BIU, 28, 3),
+
+ /* SOFTRST_CON29 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKNN_DSU0, 29, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_NPUTOP_BIU, 29, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_P_NPU_TIMER, 29, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_NPUTIMER0, 29, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_NPUTIMER1, 29, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_NPU_WDT, 29, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_T_NPU_WDT, 29, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_P_NPU_PVTM, 29, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_NPU_GRF, 29, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_NPU_PVTM, 29, 14),
+
+ /* SOFTRST_CON30 */
+ RK3588_CRU_RESET_OFFSET(SRST_NPU_PVTPLL, 30, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_H_NPU_CM0_BIU, 30, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_F_NPU_CM0_CORE, 30, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_T_NPU_CM0_JTAG, 30, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKNN0, 30, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKNN0_BIU, 30, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKNN0, 30, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKNN0_BIU, 30, 9),
+
+ /* SOFTRST_CON31 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_NVM_BIU, 31, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_A_NVM_BIU, 31, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_EMMC, 31, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_EMMC, 31, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_C_EMMC, 31, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_B_EMMC, 31, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_T_EMMC, 31, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_S_SFC, 31, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SFC, 31, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SFC_XIP, 31, 11),
+
+ /* SOFTRST_CON32 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_GRF, 32, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DEC_BIU, 32, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_PHP_BIU, 32, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_A_PCIE_GRIDGE, 32, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_A_PHP_BIU, 32, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_A_GMAC0, 32, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_A_GMAC1, 32, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_A_PCIE_BIU, 32, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_PCIE0_POWER_UP, 32, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_PCIE1_POWER_UP, 32, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_PCIE2_POWER_UP, 32, 15),
+
+ /* SOFTRST_CON33 */
+ RK3588_CRU_RESET_OFFSET(SRST_PCIE3_POWER_UP, 33, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_PCIE4_POWER_UP, 33, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_PCIE0, 33, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_PCIE1, 33, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_P_PCIE2, 33, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_P_PCIE3, 33, 15),
+
+ /* SOFTRST_CON34 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_PCIE4, 34, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_A_PHP_GIC_ITS, 34, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_A_MMU_PCIE, 34, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_A_MMU_PHP, 34, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_A_MMU_BIU, 34, 9),
+
+ /* SOFTRST_CON35 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_USB3OTG2, 35, 7),
+
+ /* SOFTRST_CON37 */
+ RK3588_CRU_RESET_OFFSET(SRST_PMALIVE0, 37, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_PMALIVE1, 37, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_PMALIVE2, 37, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_A_SATA0, 37, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_A_SATA1, 37, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_A_SATA2, 37, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_RXOOB0, 37, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_RXOOB1, 37, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_RXOOB2, 37, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_ASIC0, 37, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_ASIC1, 37, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_ASIC2, 37, 15),
+
+ /* SOFTRST_CON40 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKVDEC_CCU, 40, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKVDEC0, 40, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKVDEC0, 40, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKVDEC0_BIU, 40, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKVDEC0_BIU, 40, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_RKVDEC0_CA, 40, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_RKVDEC0_HEVC_CA, 40, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_RKVDEC0_CORE, 40, 9),
+
+ /* SOFTRST_CON41 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKVDEC1, 41, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKVDEC1, 41, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKVDEC1_BIU, 41, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKVDEC1_BIU, 41, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_RKVDEC1_CA, 41, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_RKVDEC1_HEVC_CA, 41, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_RKVDEC1_CORE, 41, 8),
+
+ /* SOFTRST_CON42 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_USB_BIU, 42, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_H_USB_BIU, 42, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_A_USB3OTG0, 42, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_USB3OTG1, 42, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_H_HOST0, 42, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_H_HOST_ARB0, 42, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_H_HOST1, 42, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_H_HOST_ARB1, 42, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_A_USB_GRF, 42, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_C_USB2P0_HOST0, 42, 15),
+
+ /* SOFTRST_CON43 */
+ RK3588_CRU_RESET_OFFSET(SRST_C_USB2P0_HOST1, 43, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_HOST_UTMI0, 43, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_HOST_UTMI1, 43, 2),
+
+ /* SOFTRST_CON44 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_VDPU_BIU, 44, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_VDPU_LOW_BIU, 44, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VDPU_BIU, 44, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_A_JPEG_DECODER_BIU, 44, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_A_VPU, 44, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VPU, 44, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_A_JPEG_ENCODER0, 44, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_H_JPEG_ENCODER0, 44, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_A_JPEG_ENCODER1, 44, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_H_JPEG_ENCODER1, 44, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_A_JPEG_ENCODER2, 44, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_H_JPEG_ENCODER2, 44, 15),
+
+ /* SOFTRST_CON45 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_JPEG_ENCODER3, 45, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_H_JPEG_ENCODER3, 45, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_A_JPEG_DECODER, 45, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_H_JPEG_DECODER, 45, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_IEP2P0, 45, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_IEP2P0, 45, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_IEP2P0_CORE, 45, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RGA2, 45, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RGA2, 45, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_RGA2_CORE, 45, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RGA3_0, 45, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RGA3_0, 45, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_RGA3_0_CORE, 45, 12),
+
+ /* SOFTRST_CON47 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKVENC0_BIU, 47, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKVENC0_BIU, 47, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKVENC0, 47, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKVENC0, 47, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_RKVENC0_CORE, 47, 6),
+
+ /* SOFTRST_CON48 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKVENC1_BIU, 48, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKVENC1_BIU, 48, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RKVENC1, 48, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RKVENC1, 48, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_RKVENC1_CORE, 48, 6),
+
+ /* SOFTRST_CON49 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_VI_BIU, 49, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VI_BIU, 49, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VI_BIU, 49, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_D_VICAP, 49, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_A_VICAP, 49, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VICAP, 49, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_ISP0, 49, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_ISP0_VICAP, 49, 11),
+
+ /* SOFTRST_CON50 */
+ RK3588_CRU_RESET_OFFSET(SRST_FISHEYE0, 50, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_FISHEYE1, 50, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CSI_HOST_0, 50, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CSI_HOST_1, 50, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CSI_HOST_2, 50, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CSI_HOST_3, 50, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CSI_HOST_4, 50, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CSI_HOST_5, 50, 9),
+
+ /* SOFTRST_CON51 */
+ RK3588_CRU_RESET_OFFSET(SRST_CSIHOST0_VICAP, 51, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_CSIHOST1_VICAP, 51, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_CSIHOST2_VICAP, 51, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_CSIHOST3_VICAP, 51, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_CSIHOST4_VICAP, 51, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_CSIHOST5_VICAP, 51, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_CIFIN, 51, 13),
+
+ /* SOFTRST_CON52 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_VOP_BIU, 52, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_VOP_LOW_BIU, 52, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VOP_BIU, 52, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VOP_BIU, 52, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VOP, 52, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_A_VOP, 52, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_D_VOP0, 52, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_D_VOP2HDMI_BRIDGE0, 52, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_D_VOP2HDMI_BRIDGE1, 52, 15),
+
+ /* SOFTRST_CON53 */
+ RK3588_CRU_RESET_OFFSET(SRST_D_VOP1, 53, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_D_VOP2, 53, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_D_VOP3, 53, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VOPGRF, 53, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DSIHOST0, 53, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DSIHOST1, 53, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_DSIHOST0, 53, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_DSIHOST1, 53, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_VOP_PMU, 53, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VOP_CHANNEL_BIU, 53, 9),
+
+ /* SOFTRST_CON55 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_VO0_BIU, 55, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VO0_S_BIU, 55, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VO0_BIU, 55, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VO0_S_BIU, 55, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_A_HDCP0_BIU, 55, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VO0GRF, 55, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_H_HDCP_KEY0, 55, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_A_HDCP0, 55, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_H_HDCP0, 55, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_HDCP0, 55, 15),
+
+ /* SOFTRST_CON56 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_TRNG0, 56, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_DP0, 56, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_DP1, 56, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S4_8CH, 56, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S4_8CH_TX, 56, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S8_8CH, 56, 14),
+
+ /* SOFTRST_CON57 */
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S8_8CH_TX, 57, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SPDIF2_DP0, 57, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_M_SPDIF2_DP0, 57, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SPDIF5_DP1, 57, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_M_SPDIF5_DP1, 57, 11),
+
+ /* SOFTRST_CON59 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_HDCP1_BIU, 59, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_A_VO1_BIU, 59, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VOP1_BIU, 59, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VOP1_S_BIU, 59, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VOP1_BIU, 59, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VO1GRF, 59, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_VO1_S_BIU, 59, 13),
+
+ /* SOFTRST_CON60 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S7_8CH, 60, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S7_8CH_RX, 60, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_HDCP_KEY1, 60, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_HDCP1, 60, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_H_HDCP1, 60, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_HDCP1, 60, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_TRNG1, 60, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_P_HDMITX0, 60, 11),
+
+ /* SOFTRST_CON61 */
+ RK3588_CRU_RESET_OFFSET(SRST_HDMITX0_REF, 61, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_P_HDMITX1, 61, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_HDMITX1_REF, 61, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_A_HDMIRX, 61, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_HDMIRX, 61, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_HDMIRX_REF, 61, 11),
+
+ /* SOFTRST_CON62 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_EDP0, 62, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_EDP0_24M, 62, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_EDP1, 62, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_EDP1_24M, 62, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S5_8CH_TX, 62, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S5_8CH, 62, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S6_8CH_TX, 62, 15),
+
+ /* SOFTRST_CON63 */
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S6_8CH_RX, 63, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S6_8CH, 63, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SPDIF3, 63, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_M_SPDIF3, 63, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SPDIF4, 63, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_M_SPDIF4, 63, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SPDIFRX0, 63, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_M_SPDIFRX0, 63, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SPDIFRX1, 63, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_M_SPDIFRX1, 63, 15),
+
+ /* SOFTRST_CON64 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_SPDIFRX2, 64, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_M_SPDIFRX2, 64, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_LINKSYM_HDMITXPHY0, 64, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_LINKSYM_HDMITXPHY1, 64, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_VO1_BRIDGE0, 64, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_VO1_BRIDGE1, 64, 15),
+
+ /* SOFTRST_CON65 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S9_8CH, 65, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S9_8CH_RX, 65, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_I2S10_8CH, 65, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_M_I2S10_8CH_RX, 65, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_S_HDMIRX, 65, 8),
+
+ /* SOFTRST_CON66 */
+ RK3588_CRU_RESET_OFFSET(SRST_GPU, 66, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_SYS_GPU, 66, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_A_S_GPU_BIU, 66, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_A_M0_GPU_BIU, 66, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_A_M1_GPU_BIU, 66, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_A_M2_GPU_BIU, 66, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_A_M3_GPU_BIU, 66, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_P_GPU_BIU, 66, 14),
+ RK3588_CRU_RESET_OFFSET(SRST_P_GPU_PVTM, 66, 15),
+
+ /* SOFTRST_CON67 */
+ RK3588_CRU_RESET_OFFSET(SRST_GPU_PVTM, 67, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_P_GPU_GRF, 67, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_GPU_PVTPLL, 67, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_GPU_JTAG, 67, 4),
+
+ /* SOFTRST_CON68 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_AV1_BIU, 68, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_A_AV1, 68, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_AV1_BIU, 68, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_AV1, 68, 5),
+
+ /* SOFTRST_CON69 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR_BIU, 69, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DMA2DDR, 69, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR_SHAREMEM, 69, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_A_DDR_SHAREMEM_BIU, 69, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_A_CENTER_S200_BIU, 69, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_A_CENTER_S400_BIU, 69, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_H_AHB2APB, 69, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_H_CENTER_BIU, 69, 13),
+ RK3588_CRU_RESET_OFFSET(SRST_F_DDR_CM0_CORE, 69, 14),
+
+ /* SOFTRST_CON70 */
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_TIMER0, 70, 0),
+ RK3588_CRU_RESET_OFFSET(SRST_DDR_TIMER1, 70, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_T_WDT_DDR, 70, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_T_DDR_CM0_JTAG, 70, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CENTER_GRF, 70, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_P_AHB2APB, 70, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_WDT, 70, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_TIMER, 70, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_DMA2DDR, 70, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_SHAREMEM, 70, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CENTER_BIU, 70, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_P_CENTER_CHANNEL_BIU, 70, 12),
+
+ /* SOFTRST_CON72 */
+ RK3588_CRU_RESET_OFFSET(SRST_P_USBDPGRF0, 72, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_P_USBDPPHY0, 72, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_P_USBDPGRF1, 72, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_P_USBDPPHY1, 72, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_P_HDPTX0, 72, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_P_HDPTX1, 72, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_BOT_RIGHT, 72, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_P_USB2PHY_U3_0_GRF0, 72, 8),
+ RK3588_CRU_RESET_OFFSET(SRST_P_USB2PHY_U3_1_GRF0, 72, 9),
+ RK3588_CRU_RESET_OFFSET(SRST_P_USB2PHY_U2_0_GRF0, 72, 10),
+ RK3588_CRU_RESET_OFFSET(SRST_P_USB2PHY_U2_1_GRF0, 72, 11),
+ RK3588_CRU_RESET_OFFSET(SRST_HDPTX0_ROPLL, 72, 12), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_HDPTX0_LCPLL, 72, 13), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_HDPTX0, 72, 14), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_HDPTX1_ROPLL, 72, 15), // missing in TRM
+
+ /* SOFTRST_CON73 */
+ RK3588_CRU_RESET_OFFSET(SRST_HDPTX1_LCPLL, 73, 0), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_HDPTX1, 73, 1), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_HDPTX0_HDMIRXPHY_SET, 73, 2), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0, 73, 3), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_LCPLL, 73, 4), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_ROPLL, 73, 5), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY0_PCS_HS, 73, 6), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1, 73, 7), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_LCPLL, 73, 8), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_ROPLL, 73, 9), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_USBDP_COMBO_PHY1_PCS_HS, 73, 10), // missing in TRM
+ RK3588_CRU_RESET_OFFSET(SRST_HDMIHDP0, 73, 12),
+ RK3588_CRU_RESET_OFFSET(SRST_HDMIHDP1, 73, 13),
+
+ /* SOFTRST_CON74 */
+ RK3588_CRU_RESET_OFFSET(SRST_A_VO1USB_TOP_BIU, 74, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_H_VO1USB_TOP_BIU, 74, 3),
+
+ /* SOFTRST_CON75 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_SDIO_BIU, 75, 1),
+ RK3588_CRU_RESET_OFFSET(SRST_H_SDIO, 75, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_SDIO, 75, 3),
+
+ /* SOFTRST_CON76 */
+ RK3588_CRU_RESET_OFFSET(SRST_H_RGA3_BIU, 76, 2),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RGA3_BIU, 76, 3),
+ RK3588_CRU_RESET_OFFSET(SRST_H_RGA3_1, 76, 4),
+ RK3588_CRU_RESET_OFFSET(SRST_A_RGA3_1, 76, 5),
+ RK3588_CRU_RESET_OFFSET(SRST_RGA3_1_CORE, 76, 6),
+
+ /* SOFTRST_CON77 */
+ RK3588_CRU_RESET_OFFSET(SRST_REF_PIPE_PHY0, 77, 6),
+ RK3588_CRU_RESET_OFFSET(SRST_REF_PIPE_PHY1, 77, 7),
+ RK3588_CRU_RESET_OFFSET(SRST_REF_PIPE_PHY2, 77, 8),
+
+ /* PHPTOPCRU_SOFTRST_CON00 */
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PHPTOP_CRU, 0, 1),
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE2_GRF0, 0, 2),
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE2_GRF1, 0, 3),
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE2_GRF2, 0, 4),
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE2_PHY0, 0, 5),
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE2_PHY1, 0, 6),
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE2_PHY2, 0, 7),
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_PCIE3_PHY, 0, 8),
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_P_APB2ASB_SLV_CHIP_TOP, 0, 9),
+ RK3588_PHPTOPCRU_RESET_OFFSET(SRST_PCIE30_PHY, 0, 10),
+
+ /* PMU1CRU_SOFTRST_CON00 */
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_H_PMU1_BIU, 0, 10),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU1_BIU, 0, 11),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_H_PMU_CM0_BIU, 0, 12),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_F_PMU_CM0_CORE, 0, 13),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_T_PMU1_CM0_JTAG, 0, 14),
+
+ /* PMU1CRU_SOFTRST_CON01 */
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_DDR_FAIL_SAFE, 1, 1),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_CRU_PMU1, 1, 2),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU1_GRF, 1, 4),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU1_IOC, 1, 5),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU1WDT, 1, 6),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_T_PMU1WDT, 1, 7),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU1TIMER, 1, 8),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_PMU1TIMER0, 1, 10),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_PMU1TIMER1, 1, 11),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU1PWM, 1, 12),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_PMU1PWM, 1, 13),
+
+ /* PMU1CRU_SOFTRST_CON02 */
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_I2C0, 2, 1),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_I2C0, 2, 2),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_S_UART0, 2, 5),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_UART0, 2, 6),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_H_I2S1_8CH, 2, 7),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_M_I2S1_8CH_TX, 2, 10),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_M_I2S1_8CH_RX, 2, 13),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_H_PDM0, 2, 14),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_PDM0, 2, 15),
+
+ /* PMU1CRU_SOFTRST_CON03 */
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_H_VAD, 3, 0),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_HDPTX0_INIT, 3, 11),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_HDPTX0_CMN, 3, 12),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_HDPTX0_LANE, 3, 13),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_HDPTX1_INIT, 3, 15),
+
+ /* PMU1CRU_SOFTRST_CON04 */
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_HDPTX1_CMN, 4, 0),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_HDPTX1_LANE, 4, 1),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_M_MIPI_DCPHY0, 4, 3),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_S_MIPI_DCPHY0, 4, 4),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_M_MIPI_DCPHY1, 4, 5),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_S_MIPI_DCPHY1, 4, 6),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_OTGPHY_U3_0, 4, 7),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_OTGPHY_U3_1, 4, 8),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_OTGPHY_U2_0, 4, 9),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_OTGPHY_U2_1, 4, 10),
+
+ /* PMU1CRU_SOFTRST_CON05 */
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU0GRF, 5, 3),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_PMU0IOC, 5, 4),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_P_GPIO0, 5, 5),
+ RK3588_PMU1CRU_RESET_OFFSET(SRST_GPIO0, 5, 6),
+
+ /* SECURECRU_SOFTRST_CON00 */
+ RK3588_SECURECRU_RESET_OFFSET(SRST_A_SECURE_NS_BIU, 0, 10),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_SECURE_NS_BIU, 0, 11),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_A_SECURE_S_BIU, 0, 12),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_SECURE_S_BIU, 0, 13),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_P_SECURE_S_BIU, 0, 14),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_CRYPTO_CORE, 0, 15),
+
+ /* SECURECRU_SOFTRST_CON01 */
+ RK3588_SECURECRU_RESET_OFFSET(SRST_CRYPTO_PKA, 1, 0),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_CRYPTO_RNG, 1, 1),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_A_CRYPTO, 1, 2),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_CRYPTO, 1, 3),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_KEYLADDER_CORE, 1, 9),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_KEYLADDER_RNG, 1, 10),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_A_KEYLADDER, 1, 11),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_KEYLADDER, 1, 12),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_P_OTPC_S, 1, 13),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_OTPC_S, 1, 14),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_WDT_S, 1, 15),
+
+ /* SECURECRU_SOFTRST_CON02 */
+ RK3588_SECURECRU_RESET_OFFSET(SRST_T_WDT_S, 2, 0),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_BOOTROM, 2, 1),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_A_DCF, 2, 2),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_P_DCF, 2, 3),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_BOOTROM_NS, 2, 5),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_P_KEYLADDER, 2, 14),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_TRNG_S, 2, 15),
+
+ /* SECURECRU_SOFTRST_CON03 */
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_TRNG_NS, 3, 0),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_D_SDMMC_BUFFER, 3, 1),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_SDMMC, 3, 2),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_H_SDMMC_BUFFER, 3, 3),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_SDMMC, 3, 4),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_P_TRNG_CHK, 3, 5),
+ RK3588_SECURECRU_RESET_OFFSET(SRST_TRNG_S, 3, 6),
+};
+
+void rk3588_rst_init(struct device_node *np, void __iomem *reg_base)
+{
+ rockchip_register_softrst_lut(np,
+ rk3588_register_offset,
+ ARRAY_SIZE(rk3588_register_offset),
+ reg_base + RK3588_SOFTRST_CON(0),
+ ROCKCHIP_SOFTRST_HIWORD_MASK);
+}
diff --git a/drivers/clk/rockchip/softrst.c b/drivers/clk/rockchip/softrst.c
index 5d07266745b8..fd56aaefe6d1 100644
--- a/drivers/clk/rockchip/softrst.c
+++ b/drivers/clk/rockchip/softrst.c
@@ -12,6 +12,7 @@
struct rockchip_softrst {
struct reset_controller_dev rcdev;
+ const int *lut;
void __iomem *reg_base;
int num_regs;
int num_per_reg;
@@ -25,8 +26,13 @@ static int rockchip_softrst_assert(struct reset_controller_dev *rcdev,
struct rockchip_softrst *softrst = container_of(rcdev,
struct rockchip_softrst,
rcdev);
- int bank = id / softrst->num_per_reg;
- int offset = id % softrst->num_per_reg;
+ int bank, offset;
+
+ if (softrst->lut)
+ id = softrst->lut[id];
+
+ bank = id / softrst->num_per_reg;
+ offset = id % softrst->num_per_reg;
if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {
writel(BIT(offset) | (BIT(offset) << 16),
@@ -52,8 +58,13 @@ static int rockchip_softrst_deassert(struct reset_controller_dev *rcdev,
struct rockchip_softrst *softrst = container_of(rcdev,
struct rockchip_softrst,
rcdev);
- int bank = id / softrst->num_per_reg;
- int offset = id % softrst->num_per_reg;
+ int bank, offset;
+
+ if (softrst->lut)
+ id = softrst->lut[id];
+
+ bank = id / softrst->num_per_reg;
+ offset = id % softrst->num_per_reg;
if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {
writel((BIT(offset) << 16), softrst->reg_base + (bank * 4));
@@ -77,9 +88,10 @@ static const struct reset_control_ops rockchip_softrst_ops = {
.deassert = rockchip_softrst_deassert,
};
-void rockchip_register_softrst(struct device_node *np,
- unsigned int num_regs,
- void __iomem *base, u8 flags)
+void rockchip_register_softrst_lut(struct device_node *np,
+ const int *lookup_table,
+ unsigned int num_regs,
+ void __iomem *base, u8 flags)
{
struct rockchip_softrst *softrst;
int ret;
@@ -91,13 +103,17 @@ void rockchip_register_softrst(struct device_node *np,
spin_lock_init(&softrst->lock);
softrst->reg_base = base;
+ softrst->lut = lookup_table;
softrst->flags = flags;
softrst->num_regs = num_regs;
softrst->num_per_reg = (flags & ROCKCHIP_SOFTRST_HIWORD_MASK) ? 16
: 32;
softrst->rcdev.owner = THIS_MODULE;
- softrst->rcdev.nr_resets = num_regs * softrst->num_per_reg;
+ if (lookup_table)
+ softrst->rcdev.nr_resets = num_regs;
+ else
+ softrst->rcdev.nr_resets = num_regs * softrst->num_per_reg;
softrst->rcdev.ops = &rockchip_softrst_ops;
softrst->rcdev.of_node = np;
ret = reset_controller_register(&softrst->rcdev);
@@ -107,4 +123,4 @@ void rockchip_register_softrst(struct device_node *np,
kfree(softrst);
}
};
-EXPORT_SYMBOL_GPL(rockchip_register_softrst);
+EXPORT_SYMBOL_GPL(rockchip_register_softrst_lut);
diff --git a/drivers/clk/samsung/clk-exynos5-subcmu.c b/drivers/clk/samsung/clk-exynos5-subcmu.c
index 65c82d922b05..96d74bc250e5 100644
--- a/drivers/clk/samsung/clk-exynos5-subcmu.c
+++ b/drivers/clk/samsung/clk-exynos5-subcmu.c
@@ -47,10 +47,10 @@ static void exynos5_subcmu_defer_gate(struct samsung_clk_provider *ctx,
/*
* Pass the needed clock provider context and register sub-CMU clocks
*
- * NOTE: This function has to be called from the main, OF_CLK_DECLARE-
+ * NOTE: This function has to be called from the main, CLK_OF_DECLARE-
* initialized clock provider driver. This happens very early during boot
* process. Then this driver, during core_initcall registers two platform
- * drivers: one which binds to the same device-tree node as OF_CLK_DECLARE
+ * drivers: one which binds to the same device-tree node as CLK_OF_DECLARE
* driver and second, for handling its per-domain child-devices. Those
* platform drivers are bound to their devices a bit later in arch_initcall,
* when OF-core populates all device-tree nodes.
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index fe383471c5f0..0ff28938943f 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -1583,6 +1583,7 @@ static void __init _samsung_clk_register_pll(struct samsung_clk_provider *ctx,
if (ret) {
pr_err("%s: failed to register pll clock %s : %d\n",
__func__, pll_clk->name, ret);
+ kfree(pll->rate_table);
kfree(pll);
return;
}
diff --git a/drivers/clk/socfpga/clk-gate-a10.c b/drivers/clk/socfpga/clk-gate-a10.c
index 738c53391e39..7cdf2f07c79b 100644
--- a/drivers/clk/socfpga/clk-gate-a10.c
+++ b/drivers/clk/socfpga/clk-gate-a10.c
@@ -35,59 +35,7 @@ static unsigned long socfpga_gate_clk_recalc_rate(struct clk_hw *hwclk,
return parent_rate / div;
}
-static int socfpga_clk_prepare(struct clk_hw *hwclk)
-{
- struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
- int i;
- u32 hs_timing;
- u32 clk_phase[2];
-
- if (socfpgaclk->clk_phase[0] || socfpgaclk->clk_phase[1]) {
- for (i = 0; i < ARRAY_SIZE(clk_phase); i++) {
- switch (socfpgaclk->clk_phase[i]) {
- case 0:
- clk_phase[i] = 0;
- break;
- case 45:
- clk_phase[i] = 1;
- break;
- case 90:
- clk_phase[i] = 2;
- break;
- case 135:
- clk_phase[i] = 3;
- break;
- case 180:
- clk_phase[i] = 4;
- break;
- case 225:
- clk_phase[i] = 5;
- break;
- case 270:
- clk_phase[i] = 6;
- break;
- case 315:
- clk_phase[i] = 7;
- break;
- default:
- clk_phase[i] = 0;
- break;
- }
- }
-
- hs_timing = SYSMGR_SDMMC_CTRL_SET_AS10(clk_phase[0], clk_phase[1]);
- if (!IS_ERR(socfpgaclk->sys_mgr_base_addr))
- regmap_write(socfpgaclk->sys_mgr_base_addr,
- SYSMGR_SDMMCGRP_CTRL_OFFSET, hs_timing);
- else
- pr_err("%s: cannot set clk_phase because sys_mgr_base_addr is not available!\n",
- __func__);
- }
- return 0;
-}
-
static struct clk_ops gateclk_ops = {
- .prepare = socfpga_clk_prepare,
.recalc_rate = socfpga_gate_clk_recalc_rate,
};
@@ -96,7 +44,6 @@ static void __init __socfpga_gate_init(struct device_node *node,
{
u32 clk_gate[2];
u32 div_reg[3];
- u32 clk_phase[2];
u32 fixed_div;
struct clk_hw *hw_clk;
struct socfpga_gate_clk *socfpga_clk;
@@ -136,21 +83,6 @@ static void __init __socfpga_gate_init(struct device_node *node,
socfpga_clk->div_reg = NULL;
}
- rc = of_property_read_u32_array(node, "clk-phase", clk_phase, 2);
- if (!rc) {
- socfpga_clk->clk_phase[0] = clk_phase[0];
- socfpga_clk->clk_phase[1] = clk_phase[1];
-
- socfpga_clk->sys_mgr_base_addr =
- syscon_regmap_lookup_by_compatible("altr,sys-mgr");
- if (IS_ERR(socfpga_clk->sys_mgr_base_addr)) {
- pr_err("%s: failed to find altr,sys-mgr regmap!\n",
- __func__);
- kfree(socfpga_clk);
- return;
- }
- }
-
of_property_read_string(node, "clock-output-names", &clk_name);
init.name = clk_name;
diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c
index 53d6e3ec4309..0c18c55edf8c 100644
--- a/drivers/clk/socfpga/clk-gate.c
+++ b/drivers/clk/socfpga/clk-gate.c
@@ -108,61 +108,7 @@ static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk,
return parent_rate / div;
}
-static int socfpga_clk_prepare(struct clk_hw *hwclk)
-{
- struct socfpga_gate_clk *socfpgaclk = to_socfpga_gate_clk(hwclk);
- struct regmap *sys_mgr_base_addr;
- int i;
- u32 hs_timing;
- u32 clk_phase[2];
-
- if (socfpgaclk->clk_phase[0] || socfpgaclk->clk_phase[1]) {
- sys_mgr_base_addr = syscon_regmap_lookup_by_compatible("altr,sys-mgr");
- if (IS_ERR(sys_mgr_base_addr)) {
- pr_err("%s: failed to find altr,sys-mgr regmap!\n", __func__);
- return -EINVAL;
- }
-
- for (i = 0; i < 2; i++) {
- switch (socfpgaclk->clk_phase[i]) {
- case 0:
- clk_phase[i] = 0;
- break;
- case 45:
- clk_phase[i] = 1;
- break;
- case 90:
- clk_phase[i] = 2;
- break;
- case 135:
- clk_phase[i] = 3;
- break;
- case 180:
- clk_phase[i] = 4;
- break;
- case 225:
- clk_phase[i] = 5;
- break;
- case 270:
- clk_phase[i] = 6;
- break;
- case 315:
- clk_phase[i] = 7;
- break;
- default:
- clk_phase[i] = 0;
- break;
- }
- }
- hs_timing = SYSMGR_SDMMC_CTRL_SET(clk_phase[0], clk_phase[1]);
- regmap_write(sys_mgr_base_addr, SYSMGR_SDMMCGRP_CTRL_OFFSET,
- hs_timing);
- }
- return 0;
-}
-
static struct clk_ops gateclk_ops = {
- .prepare = socfpga_clk_prepare,
.recalc_rate = socfpga_clk_recalc_rate,
.get_parent = socfpga_clk_get_parent,
.set_parent = socfpga_clk_set_parent,
@@ -172,7 +118,6 @@ void __init socfpga_gate_init(struct device_node *node)
{
u32 clk_gate[2];
u32 div_reg[3];
- u32 clk_phase[2];
u32 fixed_div;
struct clk_hw *hw_clk;
struct socfpga_gate_clk *socfpga_clk;
@@ -188,8 +133,10 @@ void __init socfpga_gate_init(struct device_node *node)
return;
ops = kmemdup(&gateclk_ops, sizeof(gateclk_ops), GFP_KERNEL);
- if (WARN_ON(!ops))
+ if (WARN_ON(!ops)) {
+ kfree(socfpga_clk);
return;
+ }
rc = of_property_read_u32_array(node, "clk-gate", clk_gate, 2);
if (rc)
@@ -218,12 +165,6 @@ void __init socfpga_gate_init(struct device_node *node)
socfpga_clk->div_reg = NULL;
}
- rc = of_property_read_u32_array(node, "clk-phase", clk_phase, 2);
- if (!rc) {
- socfpga_clk->clk_phase[0] = clk_phase[0];
- socfpga_clk->clk_phase[1] = clk_phase[1];
- }
-
of_property_read_string(node, "clock-output-names", &clk_name);
init.name = clk_name;
@@ -243,6 +184,7 @@ void __init socfpga_gate_init(struct device_node *node)
err = clk_hw_register(NULL, hw_clk);
if (err) {
+ kfree(ops);
kfree(socfpga_clk);
return;
}
diff --git a/drivers/clk/socfpga/clk.h b/drivers/clk/socfpga/clk.h
index d80115fbdd6a..9a2fb2dde5b8 100644
--- a/drivers/clk/socfpga/clk.h
+++ b/drivers/clk/socfpga/clk.h
@@ -50,7 +50,6 @@ struct socfpga_gate_clk {
u32 width; /* only valid if div_reg != 0 */
u32 shift; /* only valid if div_reg != 0 */
u32 bypass_shift; /* only valid if bypass_reg != 0 */
- u32 clk_phase[2];
};
struct socfpga_periph_clk {
diff --git a/drivers/clk/spear/spear6xx_clock.c b/drivers/clk/spear/spear6xx_clock.c
index c192a9141b86..adfa118520c3 100644
--- a/drivers/clk/spear/spear6xx_clock.c
+++ b/drivers/clk/spear/spear6xx_clock.c
@@ -207,7 +207,7 @@ void __init spear6xx_clk_init(void __iomem *misc_base)
clk = clk_register_gate(NULL, "clcd_clk", "clcd_mclk", 0,
PERIP1_CLK_ENB, CLCD_CLK_ENB, 0, &_lock);
- clk_register_clkdev(clk, NULL, "clcd");
+ clk_register_clkdev(clk, NULL, "fc200000.clcd");
/* gpt clocks */
clk = clk_register_gpt("gpt0_1_syn_clk", "pll1_clk", 0, PRSC0_CLK_CFG,
@@ -326,13 +326,13 @@ void __init spear6xx_clk_init(void __iomem *misc_base)
clk = clk_register_gate(NULL, "ssp0_clk", "apb_clk", 0, PERIP1_CLK_ENB,
SSP0_CLK_ENB, 0, &_lock);
- clk_register_clkdev(clk, NULL, "ssp-pl022.0");
+ clk_register_clkdev(clk, NULL, "d0100000.spi");
clk = clk_register_gate(NULL, "ssp1_clk", "apb_clk", 0, PERIP1_CLK_ENB,
SSP1_CLK_ENB, 0, &_lock);
- clk_register_clkdev(clk, NULL, "ssp-pl022.1");
+ clk_register_clkdev(clk, NULL, "d0180000.spi");
clk = clk_register_gate(NULL, "ssp2_clk", "apb_clk", 0, PERIP1_CLK_ENB,
SSP2_CLK_ENB, 0, &_lock);
- clk_register_clkdev(clk, NULL, "ssp-pl022.2");
+ clk_register_clkdev(clk, NULL, "d8180000.spi");
}
diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c
index d820292a381d..40df1db102a7 100644
--- a/drivers/clk/st/clkgen-fsyn.c
+++ b/drivers/clk/st/clkgen-fsyn.c
@@ -1020,9 +1020,10 @@ static void __init st_of_quadfs_setup(struct device_node *np,
clk = st_clk_register_quadfs_pll(pll_name, clk_parent_name, datac->data,
reg, lock);
- if (IS_ERR(clk))
+ if (IS_ERR(clk)) {
+ kfree(lock);
goto err_exit;
- else
+ } else
pr_debug("%s: parent %s rate %u\n",
__clk_get_name(clk),
__clk_get_name(clk_get_parent(clk)),
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.h b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.h
index 108eeeedcbf7..345cdbbab362 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.h
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.h
@@ -6,8 +6,8 @@
* Copyright (c) 2016 Maxime Ripard <maxime.ripard@free-electrons.com>
*/
-#ifndef _CCU_SUN8I_H3_H_
-#define _CCU_SUN8I_H3_H_
+#ifndef _CCU_SUN8I_V3S_H_
+#define _CCU_SUN8I_V3S_H_
#include <dt-bindings/clock/sun8i-v3s-ccu.h>
#include <dt-bindings/reset/sun8i-v3s-ccu.h>
@@ -51,4 +51,4 @@
#define CLK_PLL_DDR1 74
-#endif /* _CCU_SUN8I_H3_H_ */
+#endif /* _CCU_SUN8I_V3S_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c
index ed097c4f780f..0d5b60b123b7 100644
--- a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c
+++ b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c
@@ -239,7 +239,14 @@ static SUNXI_CCU_MUX_WITH_GATE(i2s_clk, "i2s", i2s_spdif_parents,
static SUNXI_CCU_MUX_WITH_GATE(spdif_clk, "spdif", i2s_spdif_parents,
0x0b4, 16, 2, BIT(31), 0);
-/* The BSP header file has a CIR_CFG, but no mod clock uses this definition */
+static const char * const ir_parents[] = { "osc32k", "osc24M" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ir_clk, "ir",
+ ir_parents, 0x0b8,
+ 0, 4, /* M */
+ 16, 2, /* P */
+ 24, 2, /* mux */
+ BIT(31), /* gate */
+ 0);
static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M",
0x0cc, BIT(1), 0);
@@ -355,6 +362,7 @@ static struct ccu_common *suniv_ccu_clks[] = {
&mmc1_output_clk.common,
&i2s_clk.common,
&spdif_clk.common,
+ &ir_clk.common,
&usb_phy0_clk.common,
&dram_ve_clk.common,
&dram_csi_clk.common,
@@ -446,6 +454,7 @@ static struct clk_hw_onecell_data suniv_hw_clks = {
[CLK_MMC1_OUTPUT] = &mmc1_output_clk.common.hw,
[CLK_I2S] = &i2s_clk.common.hw,
[CLK_SPDIF] = &spdif_clk.common.hw,
+ [CLK_IR] = &ir_clk.common.hw,
[CLK_USB_PHY0] = &usb_phy0_clk.common.hw,
[CLK_DRAM_VE] = &dram_ve_clk.common.hw,
[CLK_DRAM_CSI] = &dram_csi_clk.common.hw,
diff --git a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.h b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.h
index b22484f1bb9a..d56a4316289d 100644
--- a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.h
+++ b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.h
@@ -29,6 +29,6 @@
/* All bus gates, DRAM gates and mod clocks are exported */
-#define CLK_NUMBER (CLK_AVS + 1)
+#define CLK_NUMBER (CLK_IR + 1)
#endif /* _CCU_SUNIV_F1C100S_H_ */
diff --git a/drivers/clk/tegra/clk-bpmp.c b/drivers/clk/tegra/clk-bpmp.c
index d82a71f10c2c..0ecdffaa6b16 100644
--- a/drivers/clk/tegra/clk-bpmp.c
+++ b/drivers/clk/tegra/clk-bpmp.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (C) 2016-2020 NVIDIA Corporation
+ * Copyright (C) 2016-2022 NVIDIA Corporation
*/
#include <linux/clk-provider.h>
@@ -310,6 +310,23 @@ static const struct clk_ops tegra_bpmp_clk_mux_rate_ops = {
.set_rate = tegra_bpmp_clk_set_rate,
};
+static const struct clk_ops tegra_bpmp_clk_mux_read_only_ops = {
+ .get_parent = tegra_bpmp_clk_get_parent,
+ .recalc_rate = tegra_bpmp_clk_recalc_rate,
+};
+
+static const struct clk_ops tegra_bpmp_clk_read_only_ops = {
+ .recalc_rate = tegra_bpmp_clk_recalc_rate,
+};
+
+static const struct clk_ops tegra_bpmp_clk_gate_mux_read_only_ops = {
+ .prepare = tegra_bpmp_clk_prepare,
+ .unprepare = tegra_bpmp_clk_unprepare,
+ .is_prepared = tegra_bpmp_clk_is_prepared,
+ .recalc_rate = tegra_bpmp_clk_recalc_rate,
+ .get_parent = tegra_bpmp_clk_get_parent,
+};
+
static int tegra_bpmp_clk_get_max_id(struct tegra_bpmp *bpmp)
{
struct cmd_clk_get_max_clk_id_response response;
@@ -510,8 +527,22 @@ tegra_bpmp_clk_register(struct tegra_bpmp *bpmp,
memset(&init, 0, sizeof(init));
init.name = info->name;
clk->hw.init = &init;
-
- if (info->flags & TEGRA_BPMP_CLK_HAS_MUX) {
+ if (info->flags & BPMP_CLK_STATE_CHANGE_DENIED) {
+ if ((info->flags & BPMP_CLK_RATE_PARENT_CHANGE_DENIED) == 0) {
+ dev_WARN(bpmp->dev,
+ "Firmware bug! Inconsistent permission bits for clock %s. State and parent/rate changes disabled.",
+ init.name);
+ }
+ if (info->flags & TEGRA_BPMP_CLK_HAS_MUX)
+ init.ops = &tegra_bpmp_clk_mux_read_only_ops;
+ else
+ init.ops = &tegra_bpmp_clk_read_only_ops;
+ } else if (info->flags & BPMP_CLK_RATE_PARENT_CHANGE_DENIED) {
+ if (info->flags & TEGRA_BPMP_CLK_HAS_MUX)
+ init.ops = &tegra_bpmp_clk_gate_mux_read_only_ops;
+ else
+ init.ops = &tegra_bpmp_clk_gate_ops;
+ } else if (info->flags & TEGRA_BPMP_CLK_HAS_MUX) {
if (info->flags & TEGRA_BPMP_CLK_HAS_SET_RATE)
init.ops = &tegra_bpmp_clk_mux_rate_ops;
else
diff --git a/drivers/clk/ti/apll.c b/drivers/clk/ti/apll.c
index dd0709c9c249..93183287c58d 100644
--- a/drivers/clk/ti/apll.c
+++ b/drivers/clk/ti/apll.c
@@ -160,7 +160,7 @@ static void __init omap_clk_register_apll(void *user,
ad->clk_bypass = __clk_get_hw(clk);
name = ti_dt_clk_name(node);
- clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
+ clk = of_ti_clk_register_omap_hw(node, &clk_hw->hw, name);
if (!IS_ERR(clk)) {
of_clk_add_provider(node, of_clk_src_simple_get, clk);
kfree(init->parent_names);
@@ -400,7 +400,7 @@ static void __init of_omap2_apll_setup(struct device_node *node)
goto cleanup;
name = ti_dt_clk_name(node);
- clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
+ clk = of_ti_clk_register_omap_hw(node, &clk_hw->hw, name);
if (!IS_ERR(clk)) {
of_clk_add_provider(node, of_clk_src_simple_get, clk);
kfree(init);
diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c
index ff4d6a951681..d964e3affd42 100644
--- a/drivers/clk/ti/clk-dra7-atl.c
+++ b/drivers/clk/ti/clk-dra7-atl.c
@@ -163,8 +163,8 @@ static const struct clk_ops atl_clk_ops = {
static void __init of_dra7_atl_clock_setup(struct device_node *node)
{
struct dra7_atl_desc *clk_hw = NULL;
+ struct clk_parent_data pdata = { .index = 0 };
struct clk_init_data init = { NULL };
- const char **parent_names = NULL;
const char *name;
struct clk *clk;
@@ -188,24 +188,14 @@ static void __init of_dra7_atl_clock_setup(struct device_node *node)
goto cleanup;
}
- parent_names = kzalloc(sizeof(char *), GFP_KERNEL);
-
- if (!parent_names)
- goto cleanup;
-
- parent_names[0] = of_clk_get_parent_name(node, 0);
-
- init.parent_names = parent_names;
-
- clk = ti_clk_register(NULL, &clk_hw->hw, name);
+ init.parent_data = &pdata;
+ clk = of_ti_clk_register(node, &clk_hw->hw, name);
if (!IS_ERR(clk)) {
of_clk_add_provider(node, of_clk_src_simple_get, clk);
- kfree(parent_names);
return;
}
cleanup:
- kfree(parent_names);
kfree(clk_hw);
}
CLK_OF_DECLARE(dra7_atl_clock, "ti,dra7-atl-clock", of_dra7_atl_clock_setup);
diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c
index 1dc2f15fb75b..3d636938a739 100644
--- a/drivers/clk/ti/clk.c
+++ b/drivers/clk/ti/clk.c
@@ -263,7 +263,7 @@ static LIST_HEAD(retry_list);
/**
* ti_clk_retry_init - retries a failed clock init at later phase
- * @node: device not for the clock
+ * @node: device node for the clock
* @user: user data pointer
* @func: init function to be called for the clock
*
@@ -475,7 +475,7 @@ void __init ti_clk_add_aliases(void)
clkspec.np = np;
clk = of_clk_get_from_provider(&clkspec);
- ti_clk_add_alias(NULL, clk, ti_dt_clk_name(np));
+ ti_clk_add_alias(clk, ti_dt_clk_name(np));
}
}
@@ -528,7 +528,6 @@ void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks)
/**
* ti_clk_add_alias - add a clock alias for a TI clock
- * @dev: device alias for this clock
* @clk: clock handle to create alias for
* @con: connection ID for this clock
*
@@ -536,7 +535,7 @@ void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks)
* and assigns the data to it. Returns 0 if successful, negative error
* value otherwise.
*/
-int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con)
+int ti_clk_add_alias(struct clk *clk, const char *con)
{
struct clk_lookup *cl;
@@ -550,8 +549,6 @@ int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con)
if (!cl)
return -ENOMEM;
- if (dev)
- cl->dev_id = dev_name(dev);
cl->con_id = con;
cl->clk = clk;
@@ -561,8 +558,8 @@ int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con)
}
/**
- * ti_clk_register - register a TI clock to the common clock framework
- * @dev: device for this clock
+ * of_ti_clk_register - register a TI clock to the common clock framework
+ * @node: device node for this clock
* @hw: hardware clock handle
* @con: connection ID for this clock
*
@@ -570,17 +567,18 @@ int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con)
* alias for it. Returns a handle to the registered clock if successful,
* ERR_PTR value in failure.
*/
-struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
- const char *con)
+struct clk *of_ti_clk_register(struct device_node *node, struct clk_hw *hw,
+ const char *con)
{
struct clk *clk;
int ret;
- clk = clk_register(dev, hw);
- if (IS_ERR(clk))
- return clk;
+ ret = of_clk_hw_register(node, hw);
+ if (ret)
+ return ERR_PTR(ret);
- ret = ti_clk_add_alias(dev, clk, con);
+ clk = hw->clk;
+ ret = ti_clk_add_alias(clk, con);
if (ret) {
clk_unregister(clk);
return ERR_PTR(ret);
@@ -590,8 +588,8 @@ struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
}
/**
- * ti_clk_register_omap_hw - register a clk_hw_omap to the clock framework
- * @dev: device for this clock
+ * of_ti_clk_register_omap_hw - register a clk_hw_omap to the clock framework
+ * @node: device node for this clock
* @hw: hardware clock handle
* @con: connection ID for this clock
*
@@ -600,13 +598,13 @@ struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
* Returns a handle to the registered clock if successful, ERR_PTR value
* in failure.
*/
-struct clk *ti_clk_register_omap_hw(struct device *dev, struct clk_hw *hw,
- const char *con)
+struct clk *of_ti_clk_register_omap_hw(struct device_node *node,
+ struct clk_hw *hw, const char *con)
{
struct clk *clk;
struct clk_hw_omap *oclk;
- clk = ti_clk_register(dev, hw, con);
+ clk = of_ti_clk_register(node, hw, con);
if (IS_ERR(clk))
return clk;
diff --git a/drivers/clk/ti/clkctrl.c b/drivers/clk/ti/clkctrl.c
index ae5862879417..f73f402ff7de 100644
--- a/drivers/clk/ti/clkctrl.c
+++ b/drivers/clk/ti/clkctrl.c
@@ -305,7 +305,7 @@ _ti_clkctrl_clk_register(struct omap_clkctrl_provider *provider,
init.ops = ops;
init.flags = 0;
- clk = ti_clk_register(NULL, clk_hw, init.name);
+ clk = of_ti_clk_register(node, clk_hw, init.name);
if (IS_ERR_OR_NULL(clk)) {
ret = -EINVAL;
goto cleanup;
@@ -682,7 +682,7 @@ clkdm_found:
init.ops = &omap4_clkctrl_clk_ops;
hw->hw.init = &init;
- clk = ti_clk_register_omap_hw(NULL, &hw->hw, init.name);
+ clk = of_ti_clk_register_omap_hw(node, &hw->hw, init.name);
if (IS_ERR_OR_NULL(clk))
goto cleanup;
diff --git a/drivers/clk/ti/clock.h b/drivers/clk/ti/clock.h
index 37ab53339a9b..16a9f7c2280a 100644
--- a/drivers/clk/ti/clock.h
+++ b/drivers/clk/ti/clock.h
@@ -199,12 +199,12 @@ extern const struct omap_clkctrl_data dm816_clkctrl_data[];
typedef void (*ti_of_clk_init_cb_t)(void *, struct device_node *);
-struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
- const char *con);
-struct clk *ti_clk_register_omap_hw(struct device *dev, struct clk_hw *hw,
- const char *con);
+struct clk *of_ti_clk_register(struct device_node *node, struct clk_hw *hw,
+ const char *con);
+struct clk *of_ti_clk_register_omap_hw(struct device_node *node,
+ struct clk_hw *hw, const char *con);
const char *ti_dt_clk_name(struct device_node *np);
-int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con);
+int ti_clk_add_alias(struct clk *clk, const char *con);
void ti_clk_add_aliases(void);
void ti_clk_latch(struct clk_omap_reg *reg, s8 shift);
diff --git a/drivers/clk/ti/composite.c b/drivers/clk/ti/composite.c
index 77b771dd050a..b85382c370f7 100644
--- a/drivers/clk/ti/composite.c
+++ b/drivers/clk/ti/composite.c
@@ -176,7 +176,7 @@ static void __init _register_composite(void *user,
&ti_composite_gate_ops, 0);
if (!IS_ERR(clk)) {
- ret = ti_clk_add_alias(NULL, clk, name);
+ ret = ti_clk_add_alias(clk, name);
if (ret) {
clk_unregister(clk);
goto cleanup;
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
index 488d3da60c31..768a1f3398b4 100644
--- a/drivers/clk/ti/divider.c
+++ b/drivers/clk/ti/divider.c
@@ -326,7 +326,7 @@ static struct clk *_register_divider(struct device_node *node,
div->hw.init = &init;
/* register the clock */
- clk = ti_clk_register(NULL, &div->hw, name);
+ clk = of_ti_clk_register(node, &div->hw, name);
if (IS_ERR(clk))
kfree(div);
diff --git a/drivers/clk/ti/dpll.c b/drivers/clk/ti/dpll.c
index 8ed43bc6b7cc..403ec81f561b 100644
--- a/drivers/clk/ti/dpll.c
+++ b/drivers/clk/ti/dpll.c
@@ -187,7 +187,7 @@ static void __init _register_dpll(void *user,
/* register the clock */
name = ti_dt_clk_name(node);
- clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
+ clk = of_ti_clk_register_omap_hw(node, &clk_hw->hw, name);
if (!IS_ERR(clk)) {
of_clk_add_provider(node, of_clk_src_simple_get, clk);
@@ -259,7 +259,7 @@ static void _register_dpll_x2(struct device_node *node,
#endif
/* register the clock */
- clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
+ clk = of_ti_clk_register_omap_hw(node, &clk_hw->hw, name);
if (IS_ERR(clk))
kfree(clk_hw);
diff --git a/drivers/clk/ti/fixed-factor.c b/drivers/clk/ti/fixed-factor.c
index c80cee0f5d3d..c102c5320168 100644
--- a/drivers/clk/ti/fixed-factor.c
+++ b/drivers/clk/ti/fixed-factor.c
@@ -54,7 +54,7 @@ static void __init of_ti_fixed_factor_clk_setup(struct device_node *node)
if (!IS_ERR(clk)) {
of_clk_add_provider(node, of_clk_src_simple_get, clk);
of_ti_clk_autoidle_setup(node);
- ti_clk_add_alias(NULL, clk, clk_name);
+ ti_clk_add_alias(clk, clk_name);
}
}
CLK_OF_DECLARE(ti_fixed_factor_clk, "ti,fixed-factor-clock",
diff --git a/drivers/clk/ti/gate.c b/drivers/clk/ti/gate.c
index 307702921431..8e477d50d0fd 100644
--- a/drivers/clk/ti/gate.c
+++ b/drivers/clk/ti/gate.c
@@ -85,7 +85,7 @@ static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *hw)
return ret;
}
-static struct clk *_register_gate(struct device *dev, const char *name,
+static struct clk *_register_gate(struct device_node *node, const char *name,
const char *parent_name, unsigned long flags,
struct clk_omap_reg *reg, u8 bit_idx,
u8 clk_gate_flags, const struct clk_ops *ops,
@@ -115,7 +115,7 @@ static struct clk *_register_gate(struct device *dev, const char *name,
init.flags = flags;
- clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
+ clk = of_ti_clk_register_omap_hw(node, &clk_hw->hw, name);
if (IS_ERR(clk))
kfree(clk_hw);
@@ -158,7 +158,7 @@ static void __init _of_ti_gate_clk_setup(struct device_node *node,
clk_gate_flags |= INVERT_ENABLE;
name = ti_dt_clk_name(node);
- clk = _register_gate(NULL, name, parent_name, flags, &reg,
+ clk = _register_gate(node, name, parent_name, flags, &reg,
enable_bit, clk_gate_flags, ops, hw_ops);
if (!IS_ERR(clk))
diff --git a/drivers/clk/ti/interface.c b/drivers/clk/ti/interface.c
index f47beeea211e..172301c646f8 100644
--- a/drivers/clk/ti/interface.c
+++ b/drivers/clk/ti/interface.c
@@ -24,7 +24,8 @@ static const struct clk_ops ti_interface_clk_ops = {
.is_enabled = &omap2_dflt_clk_is_enabled,
};
-static struct clk *_register_interface(struct device *dev, const char *name,
+static struct clk *_register_interface(struct device_node *node,
+ const char *name,
const char *parent_name,
struct clk_omap_reg *reg, u8 bit_idx,
const struct clk_hw_omap_ops *ops)
@@ -49,7 +50,7 @@ static struct clk *_register_interface(struct device *dev, const char *name,
init.num_parents = 1;
init.parent_names = &parent_name;
- clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
+ clk = of_ti_clk_register_omap_hw(node, &clk_hw->hw, name);
if (IS_ERR(clk))
kfree(clk_hw);
@@ -80,7 +81,7 @@ static void __init _of_ti_interface_clk_setup(struct device_node *node,
}
name = ti_dt_clk_name(node);
- clk = _register_interface(NULL, name, parent_name, &reg,
+ clk = _register_interface(node, name, parent_name, &reg,
enable_bit, ops);
if (!IS_ERR(clk))
diff --git a/drivers/clk/ti/mux.c b/drivers/clk/ti/mux.c
index 46b45b3e8319..1ebafa386be6 100644
--- a/drivers/clk/ti/mux.c
+++ b/drivers/clk/ti/mux.c
@@ -118,7 +118,7 @@ const struct clk_ops ti_clk_mux_ops = {
.restore_context = clk_mux_restore_context,
};
-static struct clk *_register_mux(struct device *dev, const char *name,
+static struct clk *_register_mux(struct device_node *node, const char *name,
const char * const *parent_names,
u8 num_parents, unsigned long flags,
struct clk_omap_reg *reg, u8 shift, u32 mask,
@@ -148,7 +148,7 @@ static struct clk *_register_mux(struct device *dev, const char *name,
mux->table = table;
mux->hw.init = &init;
- clk = ti_clk_register(dev, &mux->hw, name);
+ clk = of_ti_clk_register(node, &mux->hw, name);
if (IS_ERR(clk))
kfree(mux);
@@ -207,7 +207,7 @@ static void of_mux_clk_setup(struct device_node *node)
mask = (1 << fls(mask)) - 1;
name = ti_dt_clk_name(node);
- clk = _register_mux(NULL, name, parent_names, num_parents,
+ clk = _register_mux(node, name, parent_names, num_parents,
flags, &reg, shift, mask, latch, clk_mux_flags,
NULL);
diff --git a/drivers/clk/visconti/pll.c b/drivers/clk/visconti/pll.c
index a484cb945d67..1f3234f22667 100644
--- a/drivers/clk/visconti/pll.c
+++ b/drivers/clk/visconti/pll.c
@@ -277,6 +277,7 @@ static struct clk_hw *visconti_register_pll(struct visconti_pll_provider *ctx,
ret = clk_hw_register(NULL, &pll->hw);
if (ret) {
pr_err("failed to register pll clock %s : %d\n", name, ret);
+ kfree(pll->rate_table);
kfree(pll);
pll_hw_clk = ERR_PTR(ret);
}
diff --git a/drivers/clk/x86/Kconfig b/drivers/clk/x86/Kconfig
index 69642e15fcc1..ced99e082e3d 100644
--- a/drivers/clk/x86/Kconfig
+++ b/drivers/clk/x86/Kconfig
@@ -1,8 +1,9 @@
# SPDX-License-Identifier: GPL-2.0-only
config CLK_LGM_CGU
depends on OF && HAS_IOMEM && (X86 || COMPILE_TEST)
+ select MFD_SYSCON
select OF_EARLY_FLATTREE
bool "Clock driver for Lightning Mountain(LGM) platform"
help
- Clock Generation Unit(CGU) driver for Intel Lightning Mountain(LGM)
- network processor SoC.
+ Clock Generation Unit(CGU) driver for MaxLinear's x86 based
+ Lightning Mountain(LGM) network processor SoC.
diff --git a/drivers/clk/x86/clk-cgu-pll.c b/drivers/clk/x86/clk-cgu-pll.c
index 3179557b5f78..409dbf55f4ca 100644
--- a/drivers/clk/x86/clk-cgu-pll.c
+++ b/drivers/clk/x86/clk-cgu-pll.c
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
/*
+ * Copyright (C) 2020-2022 MaxLinear, Inc.
* Copyright (C) 2020 Intel Corporation.
- * Zhu YiXin <yixin.zhu@intel.com>
- * Rahul Tanwar <rahul.tanwar@intel.com>
+ * Zhu Yixin <yzhu@maxlinear.com>
+ * Rahul Tanwar <rtanwar@maxlinear.com>
*/
#include <linux/clk-provider.h>
@@ -40,13 +41,10 @@ static unsigned long lgm_pll_recalc_rate(struct clk_hw *hw, unsigned long prate)
{
struct lgm_clk_pll *pll = to_lgm_clk_pll(hw);
unsigned int div, mult, frac;
- unsigned long flags;
- spin_lock_irqsave(&pll->lock, flags);
mult = lgm_get_clk_val(pll->membase, PLL_REF_DIV(pll->reg), 0, 12);
div = lgm_get_clk_val(pll->membase, PLL_REF_DIV(pll->reg), 18, 6);
frac = lgm_get_clk_val(pll->membase, pll->reg, 2, 24);
- spin_unlock_irqrestore(&pll->lock, flags);
if (pll->type == TYPE_LJPLL)
div *= 4;
@@ -57,12 +55,9 @@ static unsigned long lgm_pll_recalc_rate(struct clk_hw *hw, unsigned long prate)
static int lgm_pll_is_enabled(struct clk_hw *hw)
{
struct lgm_clk_pll *pll = to_lgm_clk_pll(hw);
- unsigned long flags;
unsigned int ret;
- spin_lock_irqsave(&pll->lock, flags);
ret = lgm_get_clk_val(pll->membase, pll->reg, 0, 1);
- spin_unlock_irqrestore(&pll->lock, flags);
return ret;
}
@@ -70,15 +65,13 @@ static int lgm_pll_is_enabled(struct clk_hw *hw)
static int lgm_pll_enable(struct clk_hw *hw)
{
struct lgm_clk_pll *pll = to_lgm_clk_pll(hw);
- unsigned long flags;
u32 val;
int ret;
- spin_lock_irqsave(&pll->lock, flags);
lgm_set_clk_val(pll->membase, pll->reg, 0, 1, 1);
- ret = readl_poll_timeout_atomic(pll->membase + pll->reg,
- val, (val & 0x1), 1, 100);
- spin_unlock_irqrestore(&pll->lock, flags);
+ ret = regmap_read_poll_timeout_atomic(pll->membase, pll->reg,
+ val, (val & 0x1), 1, 100);
+
return ret;
}
@@ -86,11 +79,8 @@ static int lgm_pll_enable(struct clk_hw *hw)
static void lgm_pll_disable(struct clk_hw *hw)
{
struct lgm_clk_pll *pll = to_lgm_clk_pll(hw);
- unsigned long flags;
- spin_lock_irqsave(&pll->lock, flags);
lgm_set_clk_val(pll->membase, pll->reg, 0, 1, 0);
- spin_unlock_irqrestore(&pll->lock, flags);
}
static const struct clk_ops lgm_pll_ops = {
@@ -121,7 +111,6 @@ lgm_clk_register_pll(struct lgm_clk_provider *ctx,
return ERR_PTR(-ENOMEM);
pll->membase = ctx->membase;
- pll->lock = ctx->lock;
pll->reg = list->reg;
pll->flags = list->flags;
pll->type = list->type;
diff --git a/drivers/clk/x86/clk-cgu.c b/drivers/clk/x86/clk-cgu.c
index 33de600e0c38..89b53f280aee 100644
--- a/drivers/clk/x86/clk-cgu.c
+++ b/drivers/clk/x86/clk-cgu.c
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
/*
+ * Copyright (C) 2020-2022 MaxLinear, Inc.
* Copyright (C) 2020 Intel Corporation.
- * Zhu YiXin <yixin.zhu@intel.com>
- * Rahul Tanwar <rahul.tanwar@intel.com>
+ * Zhu Yixin <yzhu@maxlinear.com>
+ * Rahul Tanwar <rtanwar@maxlinear.com>
*/
#include <linux/clk-provider.h>
#include <linux/device.h>
@@ -24,14 +25,10 @@
static struct clk_hw *lgm_clk_register_fixed(struct lgm_clk_provider *ctx,
const struct lgm_clk_branch *list)
{
- unsigned long flags;
- if (list->div_flags & CLOCK_FLAG_VAL_INIT) {
- spin_lock_irqsave(&ctx->lock, flags);
+ if (list->div_flags & CLOCK_FLAG_VAL_INIT)
lgm_set_clk_val(ctx->membase, list->div_off, list->div_shift,
list->div_width, list->div_val);
- spin_unlock_irqrestore(&ctx->lock, flags);
- }
return clk_hw_register_fixed_rate(NULL, list->name,
list->parent_data[0].name,
@@ -41,33 +38,27 @@ static struct clk_hw *lgm_clk_register_fixed(struct lgm_clk_provider *ctx,
static u8 lgm_clk_mux_get_parent(struct clk_hw *hw)
{
struct lgm_clk_mux *mux = to_lgm_clk_mux(hw);
- unsigned long flags;
u32 val;
- spin_lock_irqsave(&mux->lock, flags);
if (mux->flags & MUX_CLK_SW)
val = mux->reg;
else
val = lgm_get_clk_val(mux->membase, mux->reg, mux->shift,
mux->width);
- spin_unlock_irqrestore(&mux->lock, flags);
return clk_mux_val_to_index(hw, NULL, mux->flags, val);
}
static int lgm_clk_mux_set_parent(struct clk_hw *hw, u8 index)
{
struct lgm_clk_mux *mux = to_lgm_clk_mux(hw);
- unsigned long flags;
u32 val;
val = clk_mux_index_to_val(NULL, mux->flags, index);
- spin_lock_irqsave(&mux->lock, flags);
if (mux->flags & MUX_CLK_SW)
mux->reg = val;
else
lgm_set_clk_val(mux->membase, mux->reg, mux->shift,
mux->width, val);
- spin_unlock_irqrestore(&mux->lock, flags);
return 0;
}
@@ -90,7 +81,7 @@ static struct clk_hw *
lgm_clk_register_mux(struct lgm_clk_provider *ctx,
const struct lgm_clk_branch *list)
{
- unsigned long flags, cflags = list->mux_flags;
+ unsigned long cflags = list->mux_flags;
struct device *dev = ctx->dev;
u8 shift = list->mux_shift;
u8 width = list->mux_width;
@@ -111,7 +102,6 @@ lgm_clk_register_mux(struct lgm_clk_provider *ctx,
init.num_parents = list->num_parents;
mux->membase = ctx->membase;
- mux->lock = ctx->lock;
mux->reg = reg;
mux->shift = shift;
mux->width = width;
@@ -123,11 +113,8 @@ lgm_clk_register_mux(struct lgm_clk_provider *ctx,
if (ret)
return ERR_PTR(ret);
- if (cflags & CLOCK_FLAG_VAL_INIT) {
- spin_lock_irqsave(&mux->lock, flags);
+ if (cflags & CLOCK_FLAG_VAL_INIT)
lgm_set_clk_val(mux->membase, reg, shift, width, list->mux_val);
- spin_unlock_irqrestore(&mux->lock, flags);
- }
return hw;
}
@@ -136,13 +123,10 @@ static unsigned long
lgm_clk_divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
struct lgm_clk_divider *divider = to_lgm_clk_divider(hw);
- unsigned long flags;
unsigned int val;
- spin_lock_irqsave(&divider->lock, flags);
val = lgm_get_clk_val(divider->membase, divider->reg,
divider->shift, divider->width);
- spin_unlock_irqrestore(&divider->lock, flags);
return divider_recalc_rate(hw, parent_rate, val, divider->table,
divider->flags, divider->width);
@@ -163,7 +147,6 @@ lgm_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long prate)
{
struct lgm_clk_divider *divider = to_lgm_clk_divider(hw);
- unsigned long flags;
int value;
value = divider_get_val(rate, prate, divider->table,
@@ -171,10 +154,8 @@ lgm_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
if (value < 0)
return value;
- spin_lock_irqsave(&divider->lock, flags);
lgm_set_clk_val(divider->membase, divider->reg,
divider->shift, divider->width, value);
- spin_unlock_irqrestore(&divider->lock, flags);
return 0;
}
@@ -182,12 +163,10 @@ lgm_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
static int lgm_clk_divider_enable_disable(struct clk_hw *hw, int enable)
{
struct lgm_clk_divider *div = to_lgm_clk_divider(hw);
- unsigned long flags;
- spin_lock_irqsave(&div->lock, flags);
- lgm_set_clk_val(div->membase, div->reg, div->shift_gate,
- div->width_gate, enable);
- spin_unlock_irqrestore(&div->lock, flags);
+ if (div->flags != DIV_CLK_NO_MASK)
+ lgm_set_clk_val(div->membase, div->reg, div->shift_gate,
+ div->width_gate, enable);
return 0;
}
@@ -213,7 +192,7 @@ static struct clk_hw *
lgm_clk_register_divider(struct lgm_clk_provider *ctx,
const struct lgm_clk_branch *list)
{
- unsigned long flags, cflags = list->div_flags;
+ unsigned long cflags = list->div_flags;
struct device *dev = ctx->dev;
struct lgm_clk_divider *div;
struct clk_init_data init = {};
@@ -236,7 +215,6 @@ lgm_clk_register_divider(struct lgm_clk_provider *ctx,
init.num_parents = 1;
div->membase = ctx->membase;
- div->lock = ctx->lock;
div->reg = reg;
div->shift = shift;
div->width = width;
@@ -251,11 +229,8 @@ lgm_clk_register_divider(struct lgm_clk_provider *ctx,
if (ret)
return ERR_PTR(ret);
- if (cflags & CLOCK_FLAG_VAL_INIT) {
- spin_lock_irqsave(&div->lock, flags);
+ if (cflags & CLOCK_FLAG_VAL_INIT)
lgm_set_clk_val(div->membase, reg, shift, width, list->div_val);
- spin_unlock_irqrestore(&div->lock, flags);
- }
return hw;
}
@@ -264,7 +239,6 @@ static struct clk_hw *
lgm_clk_register_fixed_factor(struct lgm_clk_provider *ctx,
const struct lgm_clk_branch *list)
{
- unsigned long flags;
struct clk_hw *hw;
hw = clk_hw_register_fixed_factor(ctx->dev, list->name,
@@ -273,12 +247,9 @@ lgm_clk_register_fixed_factor(struct lgm_clk_provider *ctx,
if (IS_ERR(hw))
return ERR_CAST(hw);
- if (list->div_flags & CLOCK_FLAG_VAL_INIT) {
- spin_lock_irqsave(&ctx->lock, flags);
+ if (list->div_flags & CLOCK_FLAG_VAL_INIT)
lgm_set_clk_val(ctx->membase, list->div_off, list->div_shift,
list->div_width, list->div_val);
- spin_unlock_irqrestore(&ctx->lock, flags);
- }
return hw;
}
@@ -286,13 +257,10 @@ lgm_clk_register_fixed_factor(struct lgm_clk_provider *ctx,
static int lgm_clk_gate_enable(struct clk_hw *hw)
{
struct lgm_clk_gate *gate = to_lgm_clk_gate(hw);
- unsigned long flags;
unsigned int reg;
- spin_lock_irqsave(&gate->lock, flags);
reg = GATE_HW_REG_EN(gate->reg);
lgm_set_clk_val(gate->membase, reg, gate->shift, 1, 1);
- spin_unlock_irqrestore(&gate->lock, flags);
return 0;
}
@@ -300,25 +268,19 @@ static int lgm_clk_gate_enable(struct clk_hw *hw)
static void lgm_clk_gate_disable(struct clk_hw *hw)
{
struct lgm_clk_gate *gate = to_lgm_clk_gate(hw);
- unsigned long flags;
unsigned int reg;
- spin_lock_irqsave(&gate->lock, flags);
reg = GATE_HW_REG_DIS(gate->reg);
lgm_set_clk_val(gate->membase, reg, gate->shift, 1, 1);
- spin_unlock_irqrestore(&gate->lock, flags);
}
static int lgm_clk_gate_is_enabled(struct clk_hw *hw)
{
struct lgm_clk_gate *gate = to_lgm_clk_gate(hw);
unsigned int reg, ret;
- unsigned long flags;
- spin_lock_irqsave(&gate->lock, flags);
reg = GATE_HW_REG_STAT(gate->reg);
ret = lgm_get_clk_val(gate->membase, reg, gate->shift, 1);
- spin_unlock_irqrestore(&gate->lock, flags);
return ret;
}
@@ -333,7 +295,7 @@ static struct clk_hw *
lgm_clk_register_gate(struct lgm_clk_provider *ctx,
const struct lgm_clk_branch *list)
{
- unsigned long flags, cflags = list->gate_flags;
+ unsigned long cflags = list->gate_flags;
const char *pname = list->parent_data[0].name;
struct device *dev = ctx->dev;
u8 shift = list->gate_shift;
@@ -354,7 +316,6 @@ lgm_clk_register_gate(struct lgm_clk_provider *ctx,
init.num_parents = pname ? 1 : 0;
gate->membase = ctx->membase;
- gate->lock = ctx->lock;
gate->reg = reg;
gate->shift = shift;
gate->flags = cflags;
@@ -366,9 +327,7 @@ lgm_clk_register_gate(struct lgm_clk_provider *ctx,
return ERR_PTR(ret);
if (cflags & CLOCK_FLAG_VAL_INIT) {
- spin_lock_irqsave(&gate->lock, flags);
lgm_set_clk_val(gate->membase, reg, shift, 1, list->gate_val);
- spin_unlock_irqrestore(&gate->lock, flags);
}
return hw;
@@ -396,8 +355,22 @@ int lgm_clk_register_branches(struct lgm_clk_provider *ctx,
hw = lgm_clk_register_fixed_factor(ctx, list);
break;
case CLK_TYPE_GATE:
- hw = lgm_clk_register_gate(ctx, list);
+ if (list->gate_flags & GATE_CLK_HW) {
+ hw = lgm_clk_register_gate(ctx, list);
+ } else {
+ /*
+ * GATE_CLKs can be controlled either from
+ * CGU clk driver i.e. this driver or directly
+ * from power management driver/daemon. It is
+ * dependent on the power policy/profile requirements
+ * of the end product. To override control of gate
+ * clks from this driver, provide NULL for this index
+ * of gate clk provider.
+ */
+ hw = NULL;
+ }
break;
+
default:
dev_err(ctx->dev, "invalid clk type\n");
return -EINVAL;
@@ -443,24 +416,18 @@ lgm_clk_ddiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
static int lgm_clk_ddiv_enable(struct clk_hw *hw)
{
struct lgm_clk_ddiv *ddiv = to_lgm_clk_ddiv(hw);
- unsigned long flags;
- spin_lock_irqsave(&ddiv->lock, flags);
lgm_set_clk_val(ddiv->membase, ddiv->reg, ddiv->shift_gate,
ddiv->width_gate, 1);
- spin_unlock_irqrestore(&ddiv->lock, flags);
return 0;
}
static void lgm_clk_ddiv_disable(struct clk_hw *hw)
{
struct lgm_clk_ddiv *ddiv = to_lgm_clk_ddiv(hw);
- unsigned long flags;
- spin_lock_irqsave(&ddiv->lock, flags);
lgm_set_clk_val(ddiv->membase, ddiv->reg, ddiv->shift_gate,
ddiv->width_gate, 0);
- spin_unlock_irqrestore(&ddiv->lock, flags);
}
static int
@@ -497,32 +464,25 @@ lgm_clk_ddiv_set_rate(struct clk_hw *hw, unsigned long rate,
{
struct lgm_clk_ddiv *ddiv = to_lgm_clk_ddiv(hw);
u32 div, ddiv1, ddiv2;
- unsigned long flags;
div = DIV_ROUND_CLOSEST_ULL((u64)prate, rate);
- spin_lock_irqsave(&ddiv->lock, flags);
if (lgm_get_clk_val(ddiv->membase, ddiv->reg, ddiv->shift2, 1)) {
div = DIV_ROUND_CLOSEST_ULL((u64)div, 5);
div = div * 2;
}
- if (div <= 0) {
- spin_unlock_irqrestore(&ddiv->lock, flags);
+ if (div <= 0)
return -EINVAL;
- }
- if (lgm_clk_get_ddiv_val(div, &ddiv1, &ddiv2)) {
- spin_unlock_irqrestore(&ddiv->lock, flags);
+ if (lgm_clk_get_ddiv_val(div, &ddiv1, &ddiv2))
return -EINVAL;
- }
lgm_set_clk_val(ddiv->membase, ddiv->reg, ddiv->shift0, ddiv->width0,
ddiv1 - 1);
lgm_set_clk_val(ddiv->membase, ddiv->reg, ddiv->shift1, ddiv->width1,
ddiv2 - 1);
- spin_unlock_irqrestore(&ddiv->lock, flags);
return 0;
}
@@ -533,18 +493,15 @@ lgm_clk_ddiv_round_rate(struct clk_hw *hw, unsigned long rate,
{
struct lgm_clk_ddiv *ddiv = to_lgm_clk_ddiv(hw);
u32 div, ddiv1, ddiv2;
- unsigned long flags;
u64 rate64;
div = DIV_ROUND_CLOSEST_ULL((u64)*prate, rate);
/* if predivide bit is enabled, modify div by factor of 2.5 */
- spin_lock_irqsave(&ddiv->lock, flags);
if (lgm_get_clk_val(ddiv->membase, ddiv->reg, ddiv->shift2, 1)) {
div = div * 2;
div = DIV_ROUND_CLOSEST_ULL((u64)div, 5);
}
- spin_unlock_irqrestore(&ddiv->lock, flags);
if (div <= 0)
return *prate;
@@ -558,12 +515,10 @@ lgm_clk_ddiv_round_rate(struct clk_hw *hw, unsigned long rate,
do_div(rate64, ddiv2);
/* if predivide bit is enabled, modify rounded rate by factor of 2.5 */
- spin_lock_irqsave(&ddiv->lock, flags);
if (lgm_get_clk_val(ddiv->membase, ddiv->reg, ddiv->shift2, 1)) {
rate64 = rate64 * 2;
rate64 = DIV_ROUND_CLOSEST_ULL(rate64, 5);
}
- spin_unlock_irqrestore(&ddiv->lock, flags);
return rate64;
}
@@ -600,7 +555,6 @@ int lgm_clk_register_ddiv(struct lgm_clk_provider *ctx,
init.num_parents = 1;
ddiv->membase = ctx->membase;
- ddiv->lock = ctx->lock;
ddiv->reg = list->reg;
ddiv->shift0 = list->shift0;
ddiv->width0 = list->width0;
diff --git a/drivers/clk/x86/clk-cgu.h b/drivers/clk/x86/clk-cgu.h
index 4e22bfb22312..bcaf8aec94e5 100644
--- a/drivers/clk/x86/clk-cgu.h
+++ b/drivers/clk/x86/clk-cgu.h
@@ -1,28 +1,28 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
- * Copyright(c) 2020 Intel Corporation.
- * Zhu YiXin <yixin.zhu@intel.com>
- * Rahul Tanwar <rahul.tanwar@intel.com>
+ * Copyright (C) 2020-2022 MaxLinear, Inc.
+ * Copyright (C) 2020 Intel Corporation.
+ * Zhu Yixin <yzhu@maxlinear.com>
+ * Rahul Tanwar <rtanwar@maxlinear.com>
*/
#ifndef __CLK_CGU_H
#define __CLK_CGU_H
-#include <linux/io.h>
+#include <linux/regmap.h>
struct lgm_clk_mux {
struct clk_hw hw;
- void __iomem *membase;
+ struct regmap *membase;
unsigned int reg;
u8 shift;
u8 width;
unsigned long flags;
- spinlock_t lock;
};
struct lgm_clk_divider {
struct clk_hw hw;
- void __iomem *membase;
+ struct regmap *membase;
unsigned int reg;
u8 shift;
u8 width;
@@ -30,12 +30,11 @@ struct lgm_clk_divider {
u8 width_gate;
unsigned long flags;
const struct clk_div_table *table;
- spinlock_t lock;
};
struct lgm_clk_ddiv {
struct clk_hw hw;
- void __iomem *membase;
+ struct regmap *membase;
unsigned int reg;
u8 shift0;
u8 width0;
@@ -48,16 +47,14 @@ struct lgm_clk_ddiv {
unsigned int mult;
unsigned int div;
unsigned long flags;
- spinlock_t lock;
};
struct lgm_clk_gate {
struct clk_hw hw;
- void __iomem *membase;
+ struct regmap *membase;
unsigned int reg;
u8 shift;
unsigned long flags;
- spinlock_t lock;
};
enum lgm_clk_type {
@@ -77,11 +74,10 @@ enum lgm_clk_type {
* @clk_data: array of hw clocks and clk number.
*/
struct lgm_clk_provider {
- void __iomem *membase;
+ struct regmap *membase;
struct device_node *np;
struct device *dev;
struct clk_hw_onecell_data clk_data;
- spinlock_t lock;
};
enum pll_type {
@@ -92,11 +88,10 @@ enum pll_type {
struct lgm_clk_pll {
struct clk_hw hw;
- void __iomem *membase;
+ struct regmap *membase;
unsigned int reg;
unsigned long flags;
enum pll_type type;
- spinlock_t lock;
};
/**
@@ -202,6 +197,8 @@ struct lgm_clk_branch {
/* clock flags definition */
#define CLOCK_FLAG_VAL_INIT BIT(16)
#define MUX_CLK_SW BIT(17)
+#define GATE_CLK_HW BIT(18)
+#define DIV_CLK_NO_MASK BIT(19)
#define LGM_MUX(_id, _name, _pdata, _f, _reg, \
_shift, _width, _cf, _v) \
@@ -300,29 +297,32 @@ struct lgm_clk_branch {
.div = _d, \
}
-static inline void lgm_set_clk_val(void __iomem *membase, u32 reg,
+static inline void lgm_set_clk_val(struct regmap *membase, u32 reg,
u8 shift, u8 width, u32 set_val)
{
u32 mask = (GENMASK(width - 1, 0) << shift);
- u32 regval;
- regval = readl(membase + reg);
- regval = (regval & ~mask) | ((set_val << shift) & mask);
- writel(regval, membase + reg);
+ regmap_update_bits(membase, reg, mask, set_val << shift);
}
-static inline u32 lgm_get_clk_val(void __iomem *membase, u32 reg,
+static inline u32 lgm_get_clk_val(struct regmap *membase, u32 reg,
u8 shift, u8 width)
{
u32 mask = (GENMASK(width - 1, 0) << shift);
u32 val;
- val = readl(membase + reg);
+ if (regmap_read(membase, reg, &val)) {
+ WARN_ONCE(1, "Failed to read clk reg: 0x%x\n", reg);
+ return 0;
+ }
+
val = (val & mask) >> shift;
return val;
}
+
+
int lgm_clk_register_branches(struct lgm_clk_provider *ctx,
const struct lgm_clk_branch *list,
unsigned int nr_clk);
diff --git a/drivers/clk/x86/clk-lgm.c b/drivers/clk/x86/clk-lgm.c
index 020f4e83a5cc..f69455dd1c98 100644
--- a/drivers/clk/x86/clk-lgm.c
+++ b/drivers/clk/x86/clk-lgm.c
@@ -1,10 +1,12 @@
// SPDX-License-Identifier: GPL-2.0
/*
+ * Copyright (C) 2020-2022 MaxLinear, Inc.
* Copyright (C) 2020 Intel Corporation.
- * Zhu YiXin <yixin.zhu@intel.com>
- * Rahul Tanwar <rahul.tanwar@intel.com>
+ * Zhu Yixin <yzhu@maxlinear.com>
+ * Rahul Tanwar <rtanwar@maxlinear.com>
*/
#include <linux/clk-provider.h>
+#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <dt-bindings/clock/intel,lgm-clk.h>
@@ -253,8 +255,8 @@ static const struct lgm_clk_branch lgm_branch_clks[] = {
LGM_FIXED(LGM_CLK_SLIC, "slic", NULL, 0, CGU_IF_CLK1,
8, 2, CLOCK_FLAG_VAL_INIT, 8192000, 2),
LGM_FIXED(LGM_CLK_DOCSIS, "v_docsis", NULL, 0, 0, 0, 0, 0, 16000000, 0),
- LGM_DIV(LGM_CLK_DCL, "dcl", "v_ifclk", 0, CGU_PCMCR,
- 25, 3, 0, 0, 0, 0, dcl_div),
+ LGM_DIV(LGM_CLK_DCL, "dcl", "v_ifclk", CLK_SET_RATE_PARENT, CGU_PCMCR,
+ 25, 3, 0, 0, DIV_CLK_NO_MASK, 0, dcl_div),
LGM_MUX(LGM_CLK_PCM, "pcm", pcm_p, 0, CGU_C55_PCMCR,
0, 1, CLK_MUX_ROUND_CLOSEST, 0),
LGM_FIXED_FACTOR(LGM_CLK_DDR_PHY, "ddr_phy", "ddr",
@@ -433,13 +435,15 @@ static int lgm_cgu_probe(struct platform_device *pdev)
ctx->clk_data.num = CLK_NR_CLKS;
- ctx->membase = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(ctx->membase))
+ ctx->membase = syscon_node_to_regmap(np);
+ if (IS_ERR(ctx->membase)) {
+ dev_err(dev, "Failed to get clk CGU iomem\n");
return PTR_ERR(ctx->membase);
+ }
+
ctx->np = np;
ctx->dev = dev;
- spin_lock_init(&ctx->lock);
ret = lgm_clk_register_plls(ctx, lgm_pll_clks,
ARRAY_SIZE(lgm_pll_clks));
diff --git a/drivers/clk/xilinx/Kconfig b/drivers/clk/xilinx/Kconfig
index f205522c40ff..051756953558 100644
--- a/drivers/clk/xilinx/Kconfig
+++ b/drivers/clk/xilinx/Kconfig
@@ -2,7 +2,7 @@
config XILINX_VCU
tristate "Xilinx VCU logicoreIP Init"
- depends on HAS_IOMEM && COMMON_CLK
+ depends on HAS_IOMEM
select REGMAP_MMIO
help
Provides the driver to enable and disable the isolation between the
@@ -19,7 +19,7 @@ config XILINX_VCU
config COMMON_CLK_XLNX_CLKWZRD
tristate "Xilinx Clocking Wizard"
- depends on COMMON_CLK && OF
+ depends on OF
depends on HAS_IOMEM
help
Support for the Xilinx Clocking Wizard IP core clock generator.
diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c
index 933bb960490d..e09d4427f604 100644
--- a/drivers/clocksource/arm_arch_timer.c
+++ b/drivers/clocksource/arm_arch_timer.c
@@ -18,6 +18,7 @@
#include <linux/clocksource.h>
#include <linux/clocksource_ids.h>
#include <linux/interrupt.h>
+#include <linux/kstrtox.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/io.h>
@@ -97,7 +98,7 @@ static bool evtstrm_enable __ro_after_init = IS_ENABLED(CONFIG_ARM_ARCH_TIMER_EV
static int __init early_evtstrm_cfg(char *buf)
{
- return strtobool(buf, &evtstrm_enable);
+ return kstrtobool(buf, &evtstrm_enable);
}
early_param("clocksource.arm_arch_timer.evtstrm", early_evtstrm_cfg);
@@ -687,8 +688,8 @@ static irqreturn_t arch_timer_handler_virt_mem(int irq, void *dev_id)
return timer_handler(ARCH_TIMER_MEM_VIRT_ACCESS, evt);
}
-static __always_inline int timer_shutdown(const int access,
- struct clock_event_device *clk)
+static __always_inline int arch_timer_shutdown(const int access,
+ struct clock_event_device *clk)
{
unsigned long ctrl;
@@ -701,22 +702,22 @@ static __always_inline int timer_shutdown(const int access,
static int arch_timer_shutdown_virt(struct clock_event_device *clk)
{
- return timer_shutdown(ARCH_TIMER_VIRT_ACCESS, clk);
+ return arch_timer_shutdown(ARCH_TIMER_VIRT_ACCESS, clk);
}
static int arch_timer_shutdown_phys(struct clock_event_device *clk)
{
- return timer_shutdown(ARCH_TIMER_PHYS_ACCESS, clk);
+ return arch_timer_shutdown(ARCH_TIMER_PHYS_ACCESS, clk);
}
static int arch_timer_shutdown_virt_mem(struct clock_event_device *clk)
{
- return timer_shutdown(ARCH_TIMER_MEM_VIRT_ACCESS, clk);
+ return arch_timer_shutdown(ARCH_TIMER_MEM_VIRT_ACCESS, clk);
}
static int arch_timer_shutdown_phys_mem(struct clock_event_device *clk)
{
- return timer_shutdown(ARCH_TIMER_MEM_PHYS_ACCESS, clk);
+ return arch_timer_shutdown(ARCH_TIMER_MEM_PHYS_ACCESS, clk);
}
static __always_inline void set_next_event(const int access, unsigned long evt,
diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c
index 18de1f439ffd..c0cef92b12b8 100644
--- a/drivers/clocksource/hyperv_timer.c
+++ b/drivers/clocksource/hyperv_timer.c
@@ -367,9 +367,18 @@ static union {
u8 reserved[PAGE_SIZE];
} tsc_pg __aligned(PAGE_SIZE);
+static struct ms_hyperv_tsc_page *tsc_page = &tsc_pg.page;
+static unsigned long tsc_pfn;
+
+unsigned long hv_get_tsc_pfn(void)
+{
+ return tsc_pfn;
+}
+EXPORT_SYMBOL_GPL(hv_get_tsc_pfn);
+
struct ms_hyperv_tsc_page *hv_get_tsc_page(void)
{
- return &tsc_pg.page;
+ return tsc_page;
}
EXPORT_SYMBOL_GPL(hv_get_tsc_page);
@@ -407,13 +416,12 @@ static void suspend_hv_clock_tsc(struct clocksource *arg)
static void resume_hv_clock_tsc(struct clocksource *arg)
{
- phys_addr_t phys_addr = virt_to_phys(&tsc_pg);
union hv_reference_tsc_msr tsc_msr;
/* Re-enable the TSC page */
tsc_msr.as_uint64 = hv_get_register(HV_REGISTER_REFERENCE_TSC);
tsc_msr.enable = 1;
- tsc_msr.pfn = HVPFN_DOWN(phys_addr);
+ tsc_msr.pfn = tsc_pfn;
hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr.as_uint64);
}
@@ -497,14 +505,10 @@ static __always_inline void hv_setup_sched_clock(void *sched_clock) {}
static bool __init hv_init_tsc_clocksource(void)
{
union hv_reference_tsc_msr tsc_msr;
- phys_addr_t phys_addr;
if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE))
return false;
- if (hv_root_partition)
- return false;
-
/*
* If Hyper-V offers TSC_INVARIANT, then the virtualized TSC correctly
* handles frequency and offset changes due to live migration,
@@ -522,18 +526,30 @@ static bool __init hv_init_tsc_clocksource(void)
}
hv_read_reference_counter = read_hv_clock_tsc;
- phys_addr = virt_to_phys(hv_get_tsc_page());
/*
- * The Hyper-V TLFS specifies to preserve the value of reserved
- * bits in registers. So read the existing value, preserve the
- * low order 12 bits, and add in the guest physical address
- * (which already has at least the low 12 bits set to zero since
- * it is page aligned). Also set the "enable" bit, which is bit 0.
+ * TSC page mapping works differently in root compared to guest.
+ * - In guest partition the guest PFN has to be passed to the
+ * hypervisor.
+ * - In root partition it's other way around: it has to map the PFN
+ * provided by the hypervisor.
+ * But it can't be mapped right here as it's too early and MMU isn't
+ * ready yet. So, we only set the enable bit here and will remap the
+ * page later in hv_remap_tsc_clocksource().
+ *
+ * It worth mentioning, that TSC clocksource read function
+ * (read_hv_clock_tsc) has a MSR-based fallback mechanism, used when
+ * TSC page is zeroed (which is the case until the PFN is remapped) and
+ * thus TSC clocksource will work even without the real TSC page
+ * mapped.
*/
tsc_msr.as_uint64 = hv_get_register(HV_REGISTER_REFERENCE_TSC);
+ if (hv_root_partition)
+ tsc_pfn = tsc_msr.pfn;
+ else
+ tsc_pfn = HVPFN_DOWN(virt_to_phys(tsc_page));
tsc_msr.enable = 1;
- tsc_msr.pfn = HVPFN_DOWN(phys_addr);
+ tsc_msr.pfn = tsc_pfn;
hv_set_register(HV_REGISTER_REFERENCE_TSC, tsc_msr.as_uint64);
clocksource_register_hz(&hyperv_cs_tsc, NSEC_PER_SEC/100);
@@ -566,3 +582,20 @@ void __init hv_init_clocksource(void)
hv_sched_clock_offset = hv_read_reference_counter();
hv_setup_sched_clock(read_hv_sched_clock_msr);
}
+
+void __init hv_remap_tsc_clocksource(void)
+{
+ if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE))
+ return;
+
+ if (!hv_root_partition) {
+ WARN(1, "%s: attempt to remap TSC page in guest partition\n",
+ __func__);
+ return;
+ }
+
+ tsc_page = memremap(tsc_pfn << HV_HYP_PAGE_SHIFT, sizeof(tsc_pg),
+ MEMREMAP_WB);
+ if (!tsc_page)
+ pr_err("Failed to remap Hyper-V TSC page.\n");
+}
diff --git a/drivers/clocksource/ingenic-ost.c b/drivers/clocksource/ingenic-ost.c
index 06d25754e606..9f7c280a1336 100644
--- a/drivers/clocksource/ingenic-ost.c
+++ b/drivers/clocksource/ingenic-ost.c
@@ -141,7 +141,7 @@ static int __init ingenic_ost_probe(struct platform_device *pdev)
return 0;
}
-static int __maybe_unused ingenic_ost_suspend(struct device *dev)
+static int ingenic_ost_suspend(struct device *dev)
{
struct ingenic_ost *ost = dev_get_drvdata(dev);
@@ -150,14 +150,14 @@ static int __maybe_unused ingenic_ost_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused ingenic_ost_resume(struct device *dev)
+static int ingenic_ost_resume(struct device *dev)
{
struct ingenic_ost *ost = dev_get_drvdata(dev);
return clk_enable(ost->clk);
}
-static const struct dev_pm_ops __maybe_unused ingenic_ost_pm_ops = {
+static const struct dev_pm_ops ingenic_ost_pm_ops = {
/* _noirq: We want the OST clock to be gated last / ungated first */
.suspend_noirq = ingenic_ost_suspend,
.resume_noirq = ingenic_ost_resume,
@@ -181,9 +181,7 @@ static const struct of_device_id ingenic_ost_of_match[] = {
static struct platform_driver ingenic_ost_driver = {
.driver = {
.name = "ingenic-ost",
-#ifdef CONFIG_PM_SUSPEND
- .pm = &ingenic_ost_pm_ops,
-#endif
+ .pm = pm_sleep_ptr(&ingenic_ost_pm_ops),
.of_match_table = ingenic_ost_of_match,
},
};
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c
index 64dcb082d4cf..7b952aa52c0b 100644
--- a/drivers/clocksource/sh_cmt.c
+++ b/drivers/clocksource/sh_cmt.c
@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/module.h>
@@ -116,6 +117,7 @@ struct sh_cmt_device {
void __iomem *mapbase;
struct clk *clk;
unsigned long rate;
+ unsigned int reg_delay;
raw_spinlock_t lock; /* Protect the shared start/stop register */
@@ -247,10 +249,17 @@ static inline u32 sh_cmt_read_cmstr(struct sh_cmt_channel *ch)
static inline void sh_cmt_write_cmstr(struct sh_cmt_channel *ch, u32 value)
{
- if (ch->iostart)
- ch->cmt->info->write_control(ch->iostart, 0, value);
- else
- ch->cmt->info->write_control(ch->cmt->mapbase, 0, value);
+ u32 old_value = sh_cmt_read_cmstr(ch);
+
+ if (value != old_value) {
+ if (ch->iostart) {
+ ch->cmt->info->write_control(ch->iostart, 0, value);
+ udelay(ch->cmt->reg_delay);
+ } else {
+ ch->cmt->info->write_control(ch->cmt->mapbase, 0, value);
+ udelay(ch->cmt->reg_delay);
+ }
+ }
}
static inline u32 sh_cmt_read_cmcsr(struct sh_cmt_channel *ch)
@@ -260,7 +269,12 @@ static inline u32 sh_cmt_read_cmcsr(struct sh_cmt_channel *ch)
static inline void sh_cmt_write_cmcsr(struct sh_cmt_channel *ch, u32 value)
{
- ch->cmt->info->write_control(ch->ioctrl, CMCSR, value);
+ u32 old_value = sh_cmt_read_cmcsr(ch);
+
+ if (value != old_value) {
+ ch->cmt->info->write_control(ch->ioctrl, CMCSR, value);
+ udelay(ch->cmt->reg_delay);
+ }
}
static inline u32 sh_cmt_read_cmcnt(struct sh_cmt_channel *ch)
@@ -268,14 +282,33 @@ static inline u32 sh_cmt_read_cmcnt(struct sh_cmt_channel *ch)
return ch->cmt->info->read_count(ch->ioctrl, CMCNT);
}
-static inline void sh_cmt_write_cmcnt(struct sh_cmt_channel *ch, u32 value)
+static inline int sh_cmt_write_cmcnt(struct sh_cmt_channel *ch, u32 value)
{
+ /* Tests showed that we need to wait 3 clocks here */
+ unsigned int cmcnt_delay = DIV_ROUND_UP(3 * ch->cmt->reg_delay, 2);
+ u32 reg;
+
+ if (ch->cmt->info->model > SH_CMT_16BIT) {
+ int ret = read_poll_timeout_atomic(sh_cmt_read_cmcsr, reg,
+ !(reg & SH_CMT32_CMCSR_WRFLG),
+ 1, cmcnt_delay, false, ch);
+ if (ret < 0)
+ return ret;
+ }
+
ch->cmt->info->write_count(ch->ioctrl, CMCNT, value);
+ udelay(cmcnt_delay);
+ return 0;
}
static inline void sh_cmt_write_cmcor(struct sh_cmt_channel *ch, u32 value)
{
- ch->cmt->info->write_count(ch->ioctrl, CMCOR, value);
+ u32 old_value = ch->cmt->info->read_count(ch->ioctrl, CMCOR);
+
+ if (value != old_value) {
+ ch->cmt->info->write_count(ch->ioctrl, CMCOR, value);
+ udelay(ch->cmt->reg_delay);
+ }
}
static u32 sh_cmt_get_counter(struct sh_cmt_channel *ch, u32 *has_wrapped)
@@ -319,7 +352,7 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_channel *ch, int start)
static int sh_cmt_enable(struct sh_cmt_channel *ch)
{
- int k, ret;
+ int ret;
dev_pm_syscore_device(&ch->cmt->pdev->dev, true);
@@ -347,26 +380,9 @@ static int sh_cmt_enable(struct sh_cmt_channel *ch)
}
sh_cmt_write_cmcor(ch, 0xffffffff);
- sh_cmt_write_cmcnt(ch, 0);
-
- /*
- * According to the sh73a0 user's manual, as CMCNT can be operated
- * only by the RCLK (Pseudo 32 kHz), there's one restriction on
- * modifying CMCNT register; two RCLK cycles are necessary before
- * this register is either read or any modification of the value
- * it holds is reflected in the LSI's actual operation.
- *
- * While at it, we're supposed to clear out the CMCNT as of this
- * moment, so make sure it's processed properly here. This will
- * take RCLKx2 at maximum.
- */
- for (k = 0; k < 100; k++) {
- if (!sh_cmt_read_cmcnt(ch))
- break;
- udelay(1);
- }
+ ret = sh_cmt_write_cmcnt(ch, 0);
- if (sh_cmt_read_cmcnt(ch)) {
+ if (ret || sh_cmt_read_cmcnt(ch)) {
dev_err(&ch->cmt->pdev->dev, "ch%u: cannot clear CMCNT\n",
ch->index);
ret = -ETIMEDOUT;
@@ -995,8 +1011,8 @@ MODULE_DEVICE_TABLE(of, sh_cmt_of_table);
static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
{
- unsigned int mask;
- unsigned int i;
+ unsigned int mask, i;
+ unsigned long rate;
int ret;
cmt->pdev = pdev;
@@ -1032,10 +1048,16 @@ static int sh_cmt_setup(struct sh_cmt_device *cmt, struct platform_device *pdev)
if (ret < 0)
goto err_clk_unprepare;
- if (cmt->info->width == 16)
- cmt->rate = clk_get_rate(cmt->clk) / 512;
- else
- cmt->rate = clk_get_rate(cmt->clk) / 8;
+ rate = clk_get_rate(cmt->clk);
+ if (!rate) {
+ ret = -EINVAL;
+ goto err_clk_disable;
+ }
+
+ /* We shall wait 2 input clks after register writes */
+ if (cmt->info->model >= SH_CMT_48BIT)
+ cmt->reg_delay = DIV_ROUND_UP(2UL * USEC_PER_SEC, rate);
+ cmt->rate = rate / (cmt->info->width == 16 ? 512 : 8);
/* Map the memory resource(s). */
ret = sh_cmt_map_memory(cmt);
diff --git a/drivers/clocksource/timer-npcm7xx.c b/drivers/clocksource/timer-npcm7xx.c
index a00520cbb660..9af30af5f989 100644
--- a/drivers/clocksource/timer-npcm7xx.c
+++ b/drivers/clocksource/timer-npcm7xx.c
@@ -188,6 +188,7 @@ static void __init npcm7xx_clocksource_init(void)
static int __init npcm7xx_timer_init(struct device_node *np)
{
+ struct clk *clk;
int ret;
ret = timer_of_init(np, &npcm7xx_to);
@@ -199,6 +200,15 @@ static int __init npcm7xx_timer_init(struct device_node *np)
npcm7xx_to.of_clk.rate = npcm7xx_to.of_clk.rate /
(NPCM7XX_Tx_MIN_PRESCALE + 1);
+ /* Enable the clock for timer1, if it exists */
+ clk = of_clk_get(np, 1);
+ if (clk) {
+ if (!IS_ERR(clk))
+ clk_prepare_enable(clk);
+ else
+ pr_warn("%pOF: Failed to get clock for timer1: %pe", np, clk);
+ }
+
npcm7xx_clocksource_init();
npcm7xx_clockevents_init();
diff --git a/drivers/clocksource/timer-sp804.c b/drivers/clocksource/timer-sp804.c
index e6a87f4af2b5..cd1916c05325 100644
--- a/drivers/clocksource/timer-sp804.c
+++ b/drivers/clocksource/timer-sp804.c
@@ -155,14 +155,14 @@ static irqreturn_t sp804_timer_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static inline void timer_shutdown(struct clock_event_device *evt)
+static inline void evt_timer_shutdown(struct clock_event_device *evt)
{
writel(0, common_clkevt->ctrl);
}
static int sp804_shutdown(struct clock_event_device *evt)
{
- timer_shutdown(evt);
+ evt_timer_shutdown(evt);
return 0;
}
@@ -171,7 +171,7 @@ static int sp804_set_periodic(struct clock_event_device *evt)
unsigned long ctrl = TIMER_CTRL_32BIT | TIMER_CTRL_IE |
TIMER_CTRL_PERIODIC | TIMER_CTRL_ENABLE;
- timer_shutdown(evt);
+ evt_timer_shutdown(evt);
writel(common_clkevt->reload, common_clkevt->load);
writel(ctrl, common_clkevt->ctrl);
return 0;
diff --git a/drivers/clocksource/timer-ti-dm-systimer.c b/drivers/clocksource/timer-ti-dm-systimer.c
index 2737407ff069..632523c1232f 100644
--- a/drivers/clocksource/timer-ti-dm-systimer.c
+++ b/drivers/clocksource/timer-ti-dm-systimer.c
@@ -345,8 +345,10 @@ static int __init dmtimer_systimer_init_clock(struct dmtimer_systimer *t,
return error;
r = clk_get_rate(clock);
- if (!r)
+ if (!r) {
+ clk_disable_unprepare(clock);
return -ENODEV;
+ }
if (is_ick)
t->ick = clock;
diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c
index cad29ded3a48..b24b903a8822 100644
--- a/drivers/clocksource/timer-ti-dm.c
+++ b/drivers/clocksource/timer-ti-dm.c
@@ -633,6 +633,8 @@ static struct omap_dm_timer *omap_dm_timer_request_by_node(struct device_node *n
static int omap_dm_timer_free(struct omap_dm_timer *cookie)
{
struct dmtimer *timer;
+ struct device *dev;
+ int rc;
timer = to_dmtimer(cookie);
if (unlikely(!timer))
@@ -640,10 +642,21 @@ static int omap_dm_timer_free(struct omap_dm_timer *cookie)
WARN_ON(!timer->reserved);
timer->reserved = 0;
+
+ dev = &timer->pdev->dev;
+ rc = pm_runtime_resume_and_get(dev);
+ if (rc)
+ return rc;
+
+ /* Clear timer configuration */
+ dmtimer_write(timer, OMAP_TIMER_CTRL_REG, 0);
+
+ pm_runtime_put_sync(dev);
+
return 0;
}
-int omap_dm_timer_get_irq(struct omap_dm_timer *cookie)
+static int omap_dm_timer_get_irq(struct omap_dm_timer *cookie)
{
struct dmtimer *timer = to_dmtimer(cookie);
if (timer)
@@ -1135,6 +1148,10 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
goto err_disable;
}
__omap_dm_timer_init_regs(timer);
+
+ /* Clear timer configuration */
+ dmtimer_write(timer, OMAP_TIMER_CTRL_REG, 0);
+
pm_runtime_put(dev);
}
@@ -1258,7 +1275,7 @@ static struct platform_driver omap_dm_timer_driver = {
.remove = omap_dm_timer_remove,
.driver = {
.name = "omap_timer",
- .of_match_table = of_match_ptr(omap_timer_match),
+ .of_match_table = omap_timer_match,
.pm = &omap_dm_timer_pm_ops,
},
};
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 82e5de1f6f8c..0a0352d8fa45 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -41,6 +41,15 @@ config ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM
To compile this driver as a module, choose M here: the
module will be called sun50i-cpufreq-nvmem.
+config ARM_APPLE_SOC_CPUFREQ
+ tristate "Apple Silicon SoC CPUFreq support"
+ depends on ARCH_APPLE || (COMPILE_TEST && 64BIT)
+ select PM_OPP
+ default ARCH_APPLE
+ help
+ This adds the CPUFreq driver for Apple Silicon machines
+ (e.g. Apple M1).
+
config ARM_ARMADA_37XX_CPUFREQ
tristate "Armada 37xx CPUFreq support"
depends on ARCH_MVEBU && CPUFREQ_DT
@@ -340,8 +349,8 @@ config ARM_TEGRA194_CPUFREQ
config ARM_TI_CPUFREQ
bool "Texas Instruments CPUFreq support"
- depends on ARCH_OMAP2PLUS
- default ARCH_OMAP2PLUS
+ depends on ARCH_OMAP2PLUS || ARCH_K3
+ default y
help
This driver enables valid OPPs on the running platform based on
values contained within the SoC in use. Enable this in order to
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index 49b98c62c5af..32a7029e25ed 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_X86_AMD_FREQ_SENSITIVITY) += amd_freq_sensitivity.o
##################################################################################
# ARM SoC drivers
+obj-$(CONFIG_ARM_APPLE_SOC_CPUFREQ) += apple-soc-cpufreq.o
obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o
obj-$(CONFIG_ARM_ARMADA_8K_CPUFREQ) += armada-8k-cpufreq.o
obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 1bb2b90ebb21..78adfb2ffff6 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -19,6 +19,7 @@
#include <linux/compiler.h>
#include <linux/dmi.h>
#include <linux/slab.h>
+#include <linux/string_helpers.h>
#include <linux/acpi.h>
#include <linux/io.h>
@@ -135,8 +136,8 @@ static int set_boost(struct cpufreq_policy *policy, int val)
{
on_each_cpu_mask(policy->cpus, boost_set_msr_each,
(void *)(long)val, 1);
- pr_debug("CPU %*pbl: Core Boosting %sabled.\n",
- cpumask_pr_args(policy->cpus), val ? "en" : "dis");
+ pr_debug("CPU %*pbl: Core Boosting %s.\n",
+ cpumask_pr_args(policy->cpus), str_enabled_disabled(val));
return 0;
}
@@ -535,15 +536,6 @@ static void free_acpi_perf_data(void)
free_percpu(acpi_perf_data);
}
-static int cpufreq_boost_online(unsigned int cpu)
-{
- /*
- * On the CPU_UP path we simply keep the boost-disable flag
- * in sync with the current global state.
- */
- return boost_set_msr(acpi_cpufreq_driver.boost_enabled);
-}
-
static int cpufreq_boost_down_prep(unsigned int cpu)
{
/*
@@ -897,6 +889,9 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
if (perf->states[0].core_frequency * 1000 != freq_table[0].frequency)
pr_warn(FW_WARN "P-state 0 is not max freq\n");
+ if (acpi_cpufreq_driver.set_boost)
+ set_boost(policy, acpi_cpufreq_driver.boost_enabled);
+
return result;
err_unreg:
@@ -916,6 +911,7 @@ static int acpi_cpufreq_cpu_exit(struct cpufreq_policy *policy)
pr_debug("%s\n", __func__);
+ cpufreq_boost_down_prep(policy->cpu);
policy->fast_switch_possible = false;
policy->driver_data = NULL;
acpi_processor_unregister_performance(data->acpi_perf_cpu);
@@ -958,12 +954,8 @@ static struct cpufreq_driver acpi_cpufreq_driver = {
.attr = acpi_cpufreq_attr,
};
-static enum cpuhp_state acpi_cpufreq_online;
-
static void __init acpi_cpufreq_boost_init(void)
{
- int ret;
-
if (!(boot_cpu_has(X86_FEATURE_CPB) || boot_cpu_has(X86_FEATURE_IDA))) {
pr_debug("Boost capabilities not present in the processor\n");
return;
@@ -971,24 +963,6 @@ static void __init acpi_cpufreq_boost_init(void)
acpi_cpufreq_driver.set_boost = set_boost;
acpi_cpufreq_driver.boost_enabled = boost_state(0);
-
- /*
- * This calls the online callback on all online cpu and forces all
- * MSRs to the same value.
- */
- ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "cpufreq/acpi:online",
- cpufreq_boost_online, cpufreq_boost_down_prep);
- if (ret < 0) {
- pr_err("acpi_cpufreq: failed to register hotplug callbacks\n");
- return;
- }
- acpi_cpufreq_online = ret;
-}
-
-static void acpi_cpufreq_boost_exit(void)
-{
- if (acpi_cpufreq_online > 0)
- cpuhp_remove_state_nocalls(acpi_cpufreq_online);
}
static int __init acpi_cpufreq_init(void)
@@ -1032,7 +1006,6 @@ static int __init acpi_cpufreq_init(void)
ret = cpufreq_register_driver(&acpi_cpufreq_driver);
if (ret) {
free_acpi_perf_data();
- acpi_cpufreq_boost_exit();
}
return ret;
}
@@ -1041,8 +1014,6 @@ static void __exit acpi_cpufreq_exit(void)
{
pr_debug("%s\n", __func__);
- acpi_cpufreq_boost_exit();
-
cpufreq_unregister_driver(&acpi_cpufreq_driver);
free_acpi_perf_data();
diff --git a/drivers/cpufreq/amd-pstate-ut.c b/drivers/cpufreq/amd-pstate-ut.c
index e4a5b4d90f83..7f3fe2048981 100644
--- a/drivers/cpufreq/amd-pstate-ut.c
+++ b/drivers/cpufreq/amd-pstate-ut.c
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-1.0-or-later
+// SPDX-License-Identifier: GPL-2.0-or-later
/*
* AMD Processor P-state Frequency Driver Unit Test
*
diff --git a/drivers/cpufreq/amd_freq_sensitivity.c b/drivers/cpufreq/amd_freq_sensitivity.c
index 6448e03bcf48..59b19b9975e8 100644
--- a/drivers/cpufreq/amd_freq_sensitivity.c
+++ b/drivers/cpufreq/amd_freq_sensitivity.c
@@ -125,6 +125,8 @@ static int __init amd_freq_sensitivity_init(void)
if (!pcidev) {
if (!boot_cpu_has(X86_FEATURE_PROC_FEEDBACK))
return -ENODEV;
+ } else {
+ pci_dev_put(pcidev);
}
if (rdmsrl_safe(MSR_AMD64_FREQ_SENSITIVITY_ACTUAL, &val))
diff --git a/drivers/cpufreq/apple-soc-cpufreq.c b/drivers/cpufreq/apple-soc-cpufreq.c
new file mode 100644
index 000000000000..d1801281cdd9
--- /dev/null
+++ b/drivers/cpufreq/apple-soc-cpufreq.c
@@ -0,0 +1,352 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Apple SoC CPU cluster performance state driver
+ *
+ * Copyright The Asahi Linux Contributors
+ *
+ * Based on scpi-cpufreq.c
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/cpu.h>
+#include <linux/cpufreq.h>
+#include <linux/cpumask.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/pm_opp.h>
+#include <linux/slab.h>
+
+#define APPLE_DVFS_CMD 0x20
+#define APPLE_DVFS_CMD_BUSY BIT(31)
+#define APPLE_DVFS_CMD_SET BIT(25)
+#define APPLE_DVFS_CMD_PS2 GENMASK(16, 12)
+#define APPLE_DVFS_CMD_PS1 GENMASK(4, 0)
+
+/* Same timebase as CPU counter (24MHz) */
+#define APPLE_DVFS_LAST_CHG_TIME 0x38
+
+/*
+ * Apple ran out of bits and had to shift this in T8112...
+ */
+#define APPLE_DVFS_STATUS 0x50
+#define APPLE_DVFS_STATUS_CUR_PS_T8103 GENMASK(7, 4)
+#define APPLE_DVFS_STATUS_CUR_PS_SHIFT_T8103 4
+#define APPLE_DVFS_STATUS_TGT_PS_T8103 GENMASK(3, 0)
+#define APPLE_DVFS_STATUS_CUR_PS_T8112 GENMASK(9, 5)
+#define APPLE_DVFS_STATUS_CUR_PS_SHIFT_T8112 5
+#define APPLE_DVFS_STATUS_TGT_PS_T8112 GENMASK(4, 0)
+
+/*
+ * Div is +1, base clock is 12MHz on existing SoCs.
+ * For documentation purposes. We use the OPP table to
+ * get the frequency.
+ */
+#define APPLE_DVFS_PLL_STATUS 0xc0
+#define APPLE_DVFS_PLL_FACTOR 0xc8
+#define APPLE_DVFS_PLL_FACTOR_MULT GENMASK(31, 16)
+#define APPLE_DVFS_PLL_FACTOR_DIV GENMASK(15, 0)
+
+#define APPLE_DVFS_TRANSITION_TIMEOUT 100
+
+struct apple_soc_cpufreq_info {
+ u64 max_pstate;
+ u64 cur_pstate_mask;
+ u64 cur_pstate_shift;
+};
+
+struct apple_cpu_priv {
+ struct device *cpu_dev;
+ void __iomem *reg_base;
+ const struct apple_soc_cpufreq_info *info;
+};
+
+static struct cpufreq_driver apple_soc_cpufreq_driver;
+
+static const struct apple_soc_cpufreq_info soc_t8103_info = {
+ .max_pstate = 15,
+ .cur_pstate_mask = APPLE_DVFS_STATUS_CUR_PS_T8103,
+ .cur_pstate_shift = APPLE_DVFS_STATUS_CUR_PS_SHIFT_T8103,
+};
+
+static const struct apple_soc_cpufreq_info soc_t8112_info = {
+ .max_pstate = 31,
+ .cur_pstate_mask = APPLE_DVFS_STATUS_CUR_PS_T8112,
+ .cur_pstate_shift = APPLE_DVFS_STATUS_CUR_PS_SHIFT_T8112,
+};
+
+static const struct apple_soc_cpufreq_info soc_default_info = {
+ .max_pstate = 15,
+ .cur_pstate_mask = 0, /* fallback */
+};
+
+static const struct of_device_id apple_soc_cpufreq_of_match[] = {
+ {
+ .compatible = "apple,t8103-cluster-cpufreq",
+ .data = &soc_t8103_info,
+ },
+ {
+ .compatible = "apple,t8112-cluster-cpufreq",
+ .data = &soc_t8112_info,
+ },
+ {
+ .compatible = "apple,cluster-cpufreq",
+ .data = &soc_default_info,
+ },
+ {}
+};
+
+static unsigned int apple_soc_cpufreq_get_rate(unsigned int cpu)
+{
+ struct cpufreq_policy *policy = cpufreq_cpu_get_raw(cpu);
+ struct apple_cpu_priv *priv = policy->driver_data;
+ struct cpufreq_frequency_table *p;
+ unsigned int pstate;
+
+ if (priv->info->cur_pstate_mask) {
+ u64 reg = readq_relaxed(priv->reg_base + APPLE_DVFS_STATUS);
+
+ pstate = (reg & priv->info->cur_pstate_mask) >> priv->info->cur_pstate_shift;
+ } else {
+ /*
+ * For the fallback case we might not know the layout of DVFS_STATUS,
+ * so just use the command register value (which ignores boost limitations).
+ */
+ u64 reg = readq_relaxed(priv->reg_base + APPLE_DVFS_CMD);
+
+ pstate = FIELD_GET(APPLE_DVFS_CMD_PS1, reg);
+ }
+
+ cpufreq_for_each_valid_entry(p, policy->freq_table)
+ if (p->driver_data == pstate)
+ return p->frequency;
+
+ dev_err(priv->cpu_dev, "could not find frequency for pstate %d\n",
+ pstate);
+ return 0;
+}
+
+static int apple_soc_cpufreq_set_target(struct cpufreq_policy *policy,
+ unsigned int index)
+{
+ struct apple_cpu_priv *priv = policy->driver_data;
+ unsigned int pstate = policy->freq_table[index].driver_data;
+ u64 reg;
+
+ /* Fallback for newer SoCs */
+ if (index > priv->info->max_pstate)
+ index = priv->info->max_pstate;
+
+ if (readq_poll_timeout_atomic(priv->reg_base + APPLE_DVFS_CMD, reg,
+ !(reg & APPLE_DVFS_CMD_BUSY), 2,
+ APPLE_DVFS_TRANSITION_TIMEOUT)) {
+ return -EIO;
+ }
+
+ reg &= ~(APPLE_DVFS_CMD_PS1 | APPLE_DVFS_CMD_PS2);
+ reg |= FIELD_PREP(APPLE_DVFS_CMD_PS1, pstate);
+ reg |= FIELD_PREP(APPLE_DVFS_CMD_PS2, pstate);
+ reg |= APPLE_DVFS_CMD_SET;
+
+ writeq_relaxed(reg, priv->reg_base + APPLE_DVFS_CMD);
+
+ return 0;
+}
+
+static unsigned int apple_soc_cpufreq_fast_switch(struct cpufreq_policy *policy,
+ unsigned int target_freq)
+{
+ if (apple_soc_cpufreq_set_target(policy, policy->cached_resolved_idx) < 0)
+ return 0;
+
+ return policy->freq_table[policy->cached_resolved_idx].frequency;
+}
+
+static int apple_soc_cpufreq_find_cluster(struct cpufreq_policy *policy,
+ void __iomem **reg_base,
+ const struct apple_soc_cpufreq_info **info)
+{
+ struct of_phandle_args args;
+ const struct of_device_id *match;
+ int ret = 0;
+
+ ret = of_perf_domain_get_sharing_cpumask(policy->cpu, "performance-domains",
+ "#performance-domain-cells",
+ policy->cpus, &args);
+ if (ret < 0)
+ return ret;
+
+ match = of_match_node(apple_soc_cpufreq_of_match, args.np);
+ of_node_put(args.np);
+ if (!match)
+ return -ENODEV;
+
+ *info = match->data;
+
+ *reg_base = of_iomap(args.np, 0);
+ if (IS_ERR(*reg_base))
+ return PTR_ERR(*reg_base);
+
+ return 0;
+}
+
+static struct freq_attr *apple_soc_cpufreq_hw_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL, /* Filled in below if boost is enabled */
+ NULL,
+};
+
+static int apple_soc_cpufreq_init(struct cpufreq_policy *policy)
+{
+ int ret, i;
+ unsigned int transition_latency;
+ void __iomem *reg_base;
+ struct device *cpu_dev;
+ struct apple_cpu_priv *priv;
+ const struct apple_soc_cpufreq_info *info;
+ struct cpufreq_frequency_table *freq_table;
+
+ cpu_dev = get_cpu_device(policy->cpu);
+ if (!cpu_dev) {
+ pr_err("failed to get cpu%d device\n", policy->cpu);
+ return -ENODEV;
+ }
+
+ ret = dev_pm_opp_of_add_table(cpu_dev);
+ if (ret < 0) {
+ dev_err(cpu_dev, "%s: failed to add OPP table: %d\n", __func__, ret);
+ return ret;
+ }
+
+ ret = apple_soc_cpufreq_find_cluster(policy, &reg_base, &info);
+ if (ret) {
+ dev_err(cpu_dev, "%s: failed to get cluster info: %d\n", __func__, ret);
+ return ret;
+ }
+
+ ret = dev_pm_opp_set_sharing_cpus(cpu_dev, policy->cpus);
+ if (ret) {
+ dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n", __func__, ret);
+ goto out_iounmap;
+ }
+
+ ret = dev_pm_opp_get_opp_count(cpu_dev);
+ if (ret <= 0) {
+ dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n");
+ ret = -EPROBE_DEFER;
+ goto out_free_opp;
+ }
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ ret = -ENOMEM;
+ goto out_free_opp;
+ }
+
+ ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
+ if (ret) {
+ dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
+ goto out_free_priv;
+ }
+
+ /* Get OPP levels (p-state indexes) and stash them in driver_data */
+ for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) {
+ unsigned long rate = freq_table[i].frequency * 1000 + 999;
+ struct dev_pm_opp *opp = dev_pm_opp_find_freq_floor(cpu_dev, &rate);
+
+ if (IS_ERR(opp)) {
+ ret = PTR_ERR(opp);
+ goto out_free_cpufreq_table;
+ }
+ freq_table[i].driver_data = dev_pm_opp_get_level(opp);
+ dev_pm_opp_put(opp);
+ }
+
+ priv->cpu_dev = cpu_dev;
+ priv->reg_base = reg_base;
+ priv->info = info;
+ policy->driver_data = priv;
+ policy->freq_table = freq_table;
+
+ transition_latency = dev_pm_opp_get_max_transition_latency(cpu_dev);
+ if (!transition_latency)
+ transition_latency = CPUFREQ_ETERNAL;
+
+ policy->cpuinfo.transition_latency = transition_latency;
+ policy->dvfs_possible_from_any_cpu = true;
+ policy->fast_switch_possible = true;
+
+ if (policy_has_boost_freq(policy)) {
+ ret = cpufreq_enable_boost_support();
+ if (ret) {
+ dev_warn(cpu_dev, "failed to enable boost: %d\n", ret);
+ } else {
+ apple_soc_cpufreq_hw_attr[1] = &cpufreq_freq_attr_scaling_boost_freqs;
+ apple_soc_cpufreq_driver.boost_enabled = true;
+ }
+ }
+
+ return 0;
+
+out_free_cpufreq_table:
+ dev_pm_opp_free_cpufreq_table(cpu_dev, &freq_table);
+out_free_priv:
+ kfree(priv);
+out_free_opp:
+ dev_pm_opp_remove_all_dynamic(cpu_dev);
+out_iounmap:
+ iounmap(reg_base);
+ return ret;
+}
+
+static int apple_soc_cpufreq_exit(struct cpufreq_policy *policy)
+{
+ struct apple_cpu_priv *priv = policy->driver_data;
+
+ dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
+ dev_pm_opp_remove_all_dynamic(priv->cpu_dev);
+ iounmap(priv->reg_base);
+ kfree(priv);
+
+ return 0;
+}
+
+static struct cpufreq_driver apple_soc_cpufreq_driver = {
+ .name = "apple-cpufreq",
+ .flags = CPUFREQ_HAVE_GOVERNOR_PER_POLICY |
+ CPUFREQ_NEED_INITIAL_FREQ_CHECK | CPUFREQ_IS_COOLING_DEV,
+ .verify = cpufreq_generic_frequency_table_verify,
+ .attr = cpufreq_generic_attr,
+ .get = apple_soc_cpufreq_get_rate,
+ .init = apple_soc_cpufreq_init,
+ .exit = apple_soc_cpufreq_exit,
+ .target_index = apple_soc_cpufreq_set_target,
+ .fast_switch = apple_soc_cpufreq_fast_switch,
+ .register_em = cpufreq_register_em_with_opp,
+ .attr = apple_soc_cpufreq_hw_attr,
+};
+
+static int __init apple_soc_cpufreq_module_init(void)
+{
+ if (!of_machine_is_compatible("apple,arm-platform"))
+ return -ENODEV;
+
+ return cpufreq_register_driver(&apple_soc_cpufreq_driver);
+}
+module_init(apple_soc_cpufreq_module_init);
+
+static void __exit apple_soc_cpufreq_module_exit(void)
+{
+ cpufreq_unregister_driver(&apple_soc_cpufreq_driver);
+}
+module_exit(apple_soc_cpufreq_module_exit);
+
+MODULE_DEVICE_TABLE(of, apple_soc_cpufreq_of_match);
+MODULE_AUTHOR("Hector Martin <marcan@marcan.st>");
+MODULE_DESCRIPTION("Apple SoC CPU cluster DVFS driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c
index 6ac3800db450..8ab672883043 100644
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
@@ -103,6 +103,8 @@ static const struct of_device_id allowlist[] __initconst = {
static const struct of_device_id blocklist[] __initconst = {
{ .compatible = "allwinner,sun50i-h6", },
+ { .compatible = "apple,arm-platform", },
+
{ .compatible = "arm,vexpress", },
{ .compatible = "calxeda,highbank", },
@@ -160,6 +162,7 @@ static const struct of_device_id blocklist[] __initconst = {
{ .compatible = "ti,am43", },
{ .compatible = "ti,dra7", },
{ .compatible = "ti,omap3", },
+ { .compatible = "ti,am625", },
{ .compatible = "qcom,ipq8064", },
{ .compatible = "qcom,apq8064", },
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 69b3d61852ac..7e56a42750ea 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1207,6 +1207,7 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
if (!zalloc_cpumask_var(&policy->real_cpus, GFP_KERNEL))
goto err_free_rcpumask;
+ init_completion(&policy->kobj_unregister);
ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq,
cpufreq_global_kobject, "policy%u", cpu);
if (ret) {
@@ -1245,7 +1246,6 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu)
init_rwsem(&policy->rwsem);
spin_lock_init(&policy->transition_lock);
init_waitqueue_head(&policy->transition_wait);
- init_completion(&policy->kobj_unregister);
INIT_WORK(&policy->update, handle_update);
policy->cpu = cpu;
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index 1570d6f3e75d..55c7ffd37d1c 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -128,25 +128,23 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
ssize_t len = 0;
int i, j, count;
- len += scnprintf(buf + len, PAGE_SIZE - len, " From : To\n");
- len += scnprintf(buf + len, PAGE_SIZE - len, " : ");
+ len += sysfs_emit_at(buf, len, " From : To\n");
+ len += sysfs_emit_at(buf, len, " : ");
for (i = 0; i < stats->state_num; i++) {
if (len >= PAGE_SIZE)
break;
- len += scnprintf(buf + len, PAGE_SIZE - len, "%9u ",
- stats->freq_table[i]);
+ len += sysfs_emit_at(buf, len, "%9u ", stats->freq_table[i]);
}
if (len >= PAGE_SIZE)
return PAGE_SIZE;
- len += scnprintf(buf + len, PAGE_SIZE - len, "\n");
+ len += sysfs_emit_at(buf, len, "\n");
for (i = 0; i < stats->state_num; i++) {
if (len >= PAGE_SIZE)
break;
- len += scnprintf(buf + len, PAGE_SIZE - len, "%9u: ",
- stats->freq_table[i]);
+ len += sysfs_emit_at(buf, len, "%9u: ", stats->freq_table[i]);
for (j = 0; j < stats->state_num; j++) {
if (len >= PAGE_SIZE)
@@ -157,11 +155,11 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf)
else
count = stats->trans_table[i * stats->max_state + j];
- len += scnprintf(buf + len, PAGE_SIZE - len, "%9u ", count);
+ len += sysfs_emit_at(buf, len, "%9u ", count);
}
if (len >= PAGE_SIZE)
break;
- len += scnprintf(buf + len, PAGE_SIZE - len, "\n");
+ len += sysfs_emit_at(buf, len, "\n");
}
if (len >= PAGE_SIZE) {
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 6ff73c30769f..fd73d6d2b808 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -298,6 +298,7 @@ static int hwp_active __read_mostly;
static int hwp_mode_bdw __read_mostly;
static bool per_cpu_limits __read_mostly;
static bool hwp_boost __read_mostly;
+static bool hwp_forced __read_mostly;
static struct cpufreq_driver *intel_pstate_driver __read_mostly;
@@ -1679,12 +1680,12 @@ static void intel_pstate_update_epp_defaults(struct cpudata *cpudata)
return;
/*
- * If powerup EPP is something other than chipset default 0x80 and
- * - is more performance oriented than 0x80 (default balance_perf EPP)
+ * If the EPP is set by firmware, which means that firmware enabled HWP
+ * - Is equal or less than 0x80 (default balance_perf EPP)
* - But less performance oriented than performance EPP
* then use this as new balance_perf EPP.
*/
- if (cpudata->epp_default < HWP_EPP_BALANCE_PERFORMANCE &&
+ if (hwp_forced && cpudata->epp_default <= HWP_EPP_BALANCE_PERFORMANCE &&
cpudata->epp_default > HWP_EPP_PERFORMANCE) {
epp_values[EPP_INDEX_BALANCE_PERFORMANCE] = cpudata->epp_default;
return;
@@ -2378,6 +2379,7 @@ static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
X86_MATCH(COMETLAKE, core_funcs),
X86_MATCH(ICELAKE_X, core_funcs),
X86_MATCH(TIGERLAKE, core_funcs),
+ X86_MATCH(SAPPHIRERAPIDS_X, core_funcs),
{}
};
MODULE_DEVICE_TABLE(x86cpu, intel_pstate_cpu_ids);
@@ -3384,7 +3386,7 @@ static int __init intel_pstate_init(void)
id = x86_match_cpu(hwp_support_ids);
if (id) {
- bool hwp_forced = intel_pstate_hwp_is_enabled();
+ hwp_forced = intel_pstate_hwp_is_enabled();
if (hwp_forced)
pr_info("HWP enabled by BIOS\n");
diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c
index 3e000e1a75c6..4c57c6725c13 100644
--- a/drivers/cpufreq/longhaul.c
+++ b/drivers/cpufreq/longhaul.c
@@ -407,10 +407,10 @@ static int guess_fsb(int mult)
{
int speed = cpu_khz / 1000;
int i;
- int speeds[] = { 666, 1000, 1333, 2000 };
+ static const int speeds[] = { 666, 1000, 1333, 2000 };
int f_max, f_min;
- for (i = 0; i < 4; i++) {
+ for (i = 0; i < ARRAY_SIZE(speeds); i++) {
f_max = ((speeds[i] * mult) + 50) / 100;
f_max += (ROUNDING / 2);
f_min = f_max - ROUNDING;
diff --git a/drivers/cpufreq/mediatek-cpufreq-hw.c b/drivers/cpufreq/mediatek-cpufreq-hw.c
index f0e0a35c7f21..f80339779084 100644
--- a/drivers/cpufreq/mediatek-cpufreq-hw.c
+++ b/drivers/cpufreq/mediatek-cpufreq-hw.c
@@ -160,6 +160,7 @@ static int mtk_cpu_resources_init(struct platform_device *pdev,
struct mtk_cpufreq_data *data;
struct device *dev = &pdev->dev;
struct resource *res;
+ struct of_phandle_args args;
void __iomem *base;
int ret, i;
int index;
@@ -168,11 +169,14 @@ static int mtk_cpu_resources_init(struct platform_device *pdev,
if (!data)
return -ENOMEM;
- index = of_perf_domain_get_sharing_cpumask(policy->cpu, "performance-domains",
- "#performance-domain-cells",
- policy->cpus);
- if (index < 0)
- return index;
+ ret = of_perf_domain_get_sharing_cpumask(policy->cpu, "performance-domains",
+ "#performance-domain-cells",
+ policy->cpus, &args);
+ if (ret < 0)
+ return ret;
+
+ index = args.args[0];
+ of_node_put(args.np);
res = platform_get_resource(pdev, IORESOURCE_MEM, index);
if (!res) {
diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c
index 833589bc95e4..340fed35e45d 100644
--- a/drivers/cpufreq/qcom-cpufreq-hw.c
+++ b/drivers/cpufreq/qcom-cpufreq-hw.c
@@ -4,6 +4,7 @@
*/
#include <linux/bitfield.h>
+#include <linux/clk-provider.h>
#include <linux/cpufreq.h>
#include <linux/init.h>
#include <linux/interconnect.h>
@@ -43,7 +44,6 @@ struct qcom_cpufreq_soc_data {
struct qcom_cpufreq_data {
void __iomem *base;
struct resource *res;
- const struct qcom_cpufreq_soc_data *soc_data;
/*
* Mutex to synchronize between de-init sequence and re-starting LMh
@@ -55,12 +55,18 @@ struct qcom_cpufreq_data {
bool cancel_throttle;
struct delayed_work throttle_work;
struct cpufreq_policy *policy;
+ struct clk_hw cpu_clk;
bool per_core_dcvs;
struct freq_qos_request throttle_freq_req;
};
+static struct {
+ struct qcom_cpufreq_data *data;
+ const struct qcom_cpufreq_soc_data *soc_data;
+} qcom_cpufreq;
+
static unsigned long cpu_hw_rate, xo_rate;
static bool icc_scaling_enabled;
@@ -109,7 +115,7 @@ static int qcom_cpufreq_hw_target_index(struct cpufreq_policy *policy,
unsigned int index)
{
struct qcom_cpufreq_data *data = policy->driver_data;
- const struct qcom_cpufreq_soc_data *soc_data = data->soc_data;
+ const struct qcom_cpufreq_soc_data *soc_data = qcom_cpufreq.soc_data;
unsigned long freq = policy->freq_table[index].frequency;
unsigned int i;
@@ -125,9 +131,37 @@ static int qcom_cpufreq_hw_target_index(struct cpufreq_policy *policy,
return 0;
}
+static unsigned long qcom_lmh_get_throttle_freq(struct qcom_cpufreq_data *data)
+{
+ unsigned int lval;
+
+ if (qcom_cpufreq.soc_data->reg_current_vote)
+ lval = readl_relaxed(data->base + qcom_cpufreq.soc_data->reg_current_vote) & 0x3ff;
+ else
+ lval = readl_relaxed(data->base + qcom_cpufreq.soc_data->reg_domain_state) & 0xff;
+
+ return lval * xo_rate;
+}
+
+/* Get the current frequency of the CPU (after throttling) */
static unsigned int qcom_cpufreq_hw_get(unsigned int cpu)
{
struct qcom_cpufreq_data *data;
+ struct cpufreq_policy *policy;
+
+ policy = cpufreq_cpu_get_raw(cpu);
+ if (!policy)
+ return 0;
+
+ data = policy->driver_data;
+
+ return qcom_lmh_get_throttle_freq(data) / HZ_PER_KHZ;
+}
+
+/* Get the frequency requested by the cpufreq core for the CPU */
+static unsigned int qcom_cpufreq_get_freq(unsigned int cpu)
+{
+ struct qcom_cpufreq_data *data;
const struct qcom_cpufreq_soc_data *soc_data;
struct cpufreq_policy *policy;
unsigned int index;
@@ -137,7 +171,7 @@ static unsigned int qcom_cpufreq_hw_get(unsigned int cpu)
return 0;
data = policy->driver_data;
- soc_data = data->soc_data;
+ soc_data = qcom_cpufreq.soc_data;
index = readl_relaxed(data->base + soc_data->reg_perf_state);
index = min(index, LUT_MAX_ENTRIES - 1);
@@ -149,7 +183,7 @@ static unsigned int qcom_cpufreq_hw_fast_switch(struct cpufreq_policy *policy,
unsigned int target_freq)
{
struct qcom_cpufreq_data *data = policy->driver_data;
- const struct qcom_cpufreq_soc_data *soc_data = data->soc_data;
+ const struct qcom_cpufreq_soc_data *soc_data = qcom_cpufreq.soc_data;
unsigned int index;
unsigned int i;
@@ -173,7 +207,7 @@ static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev,
unsigned long rate;
int ret;
struct qcom_cpufreq_data *drv_data = policy->driver_data;
- const struct qcom_cpufreq_soc_data *soc_data = drv_data->soc_data;
+ const struct qcom_cpufreq_soc_data *soc_data = qcom_cpufreq.soc_data;
table = kcalloc(LUT_MAX_ENTRIES + 1, sizeof(*table), GFP_KERNEL);
if (!table)
@@ -193,6 +227,7 @@ static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev,
}
} else if (ret != -ENODEV) {
dev_err(cpu_dev, "Invalid opp table in device tree\n");
+ kfree(table);
return ret;
} else {
policy->fast_switch_possible = true;
@@ -286,18 +321,6 @@ static void qcom_get_related_cpus(int index, struct cpumask *m)
}
}
-static unsigned long qcom_lmh_get_throttle_freq(struct qcom_cpufreq_data *data)
-{
- unsigned int lval;
-
- if (data->soc_data->reg_current_vote)
- lval = readl_relaxed(data->base + data->soc_data->reg_current_vote) & 0x3ff;
- else
- lval = readl_relaxed(data->base + data->soc_data->reg_domain_state) & 0xff;
-
- return lval * xo_rate;
-}
-
static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data)
{
struct cpufreq_policy *policy = data->policy;
@@ -341,7 +364,7 @@ static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data)
* If h/w throttled frequency is higher than what cpufreq has requested
* for, then stop polling and switch back to interrupt mechanism.
*/
- if (throttled_freq >= qcom_cpufreq_hw_get(cpu))
+ if (throttled_freq >= qcom_cpufreq_get_freq(cpu))
enable_irq(data->throttle_irq);
else
mod_delayed_work(system_highpri_wq, &data->throttle_work,
@@ -367,9 +390,9 @@ static irqreturn_t qcom_lmh_dcvs_handle_irq(int irq, void *data)
disable_irq_nosync(c_data->throttle_irq);
schedule_delayed_work(&c_data->throttle_work, 0);
- if (c_data->soc_data->reg_intr_clr)
+ if (qcom_cpufreq.soc_data->reg_intr_clr)
writel_relaxed(GT_IRQ_STATUS,
- c_data->base + c_data->soc_data->reg_intr_clr);
+ c_data->base + qcom_cpufreq.soc_data->reg_intr_clr);
return IRQ_HANDLED;
}
@@ -503,8 +526,6 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy)
struct of_phandle_args args;
struct device_node *cpu_np;
struct device *cpu_dev;
- struct resource *res;
- void __iomem *base;
struct qcom_cpufreq_data *data;
int ret, index;
@@ -526,51 +547,18 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy)
return ret;
index = args.args[0];
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, index);
- if (!res) {
- dev_err(dev, "failed to get mem resource %d\n", index);
- return -ENODEV;
- }
-
- if (!request_mem_region(res->start, resource_size(res), res->name)) {
- dev_err(dev, "failed to request resource %pR\n", res);
- return -EBUSY;
- }
-
- base = ioremap(res->start, resource_size(res));
- if (!base) {
- dev_err(dev, "failed to map resource %pR\n", res);
- ret = -ENOMEM;
- goto release_region;
- }
-
- data = kzalloc(sizeof(*data), GFP_KERNEL);
- if (!data) {
- ret = -ENOMEM;
- goto unmap_base;
- }
-
- data->soc_data = of_device_get_match_data(&pdev->dev);
- data->base = base;
- data->res = res;
+ data = &qcom_cpufreq.data[index];
/* HW should be in enabled state to proceed */
- if (!(readl_relaxed(base + data->soc_data->reg_enable) & 0x1)) {
+ if (!(readl_relaxed(data->base + qcom_cpufreq.soc_data->reg_enable) & 0x1)) {
dev_err(dev, "Domain-%d cpufreq hardware not enabled\n", index);
- ret = -ENODEV;
- goto error;
+ return -ENODEV;
}
- if (readl_relaxed(base + data->soc_data->reg_dcvs_ctrl) & 0x1)
+ if (readl_relaxed(data->base + qcom_cpufreq.soc_data->reg_dcvs_ctrl) & 0x1)
data->per_core_dcvs = true;
qcom_get_related_cpus(index, policy->cpus);
- if (cpumask_empty(policy->cpus)) {
- dev_err(dev, "Domain-%d failed to get related CPUs\n", index);
- ret = -ENOENT;
- goto error;
- }
policy->driver_data = data;
policy->dvfs_possible_from_any_cpu = true;
@@ -578,14 +566,13 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy)
ret = qcom_cpufreq_hw_read_lut(cpu_dev, policy);
if (ret) {
dev_err(dev, "Domain-%d failed to read LUT\n", index);
- goto error;
+ return ret;
}
ret = dev_pm_opp_get_opp_count(cpu_dev);
if (ret <= 0) {
dev_err(cpu_dev, "Failed to add OPPs\n");
- ret = -ENODEV;
- goto error;
+ return -ENODEV;
}
if (policy_has_boost_freq(policy)) {
@@ -594,18 +581,7 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy)
dev_warn(cpu_dev, "failed to enable boost: %d\n", ret);
}
- ret = qcom_cpufreq_hw_lmh_init(policy, index);
- if (ret)
- goto error;
-
- return 0;
-error:
- kfree(data);
-unmap_base:
- iounmap(base);
-release_region:
- release_mem_region(res->start, resource_size(res));
- return ret;
+ return qcom_cpufreq_hw_lmh_init(policy, index);
}
static int qcom_cpufreq_hw_cpu_exit(struct cpufreq_policy *policy)
@@ -658,20 +634,33 @@ static struct cpufreq_driver cpufreq_qcom_hw_driver = {
.ready = qcom_cpufreq_ready,
};
+static unsigned long qcom_cpufreq_hw_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+ struct qcom_cpufreq_data *data = container_of(hw, struct qcom_cpufreq_data, cpu_clk);
+
+ return qcom_lmh_get_throttle_freq(data);
+}
+
+static const struct clk_ops qcom_cpufreq_hw_clk_ops = {
+ .recalc_rate = qcom_cpufreq_hw_recalc_rate,
+};
+
static int qcom_cpufreq_hw_driver_probe(struct platform_device *pdev)
{
+ struct clk_hw_onecell_data *clk_data;
+ struct device *dev = &pdev->dev;
struct device *cpu_dev;
struct clk *clk;
- int ret;
+ int ret, i, num_domains;
- clk = clk_get(&pdev->dev, "xo");
+ clk = clk_get(dev, "xo");
if (IS_ERR(clk))
return PTR_ERR(clk);
xo_rate = clk_get_rate(clk);
clk_put(clk);
- clk = clk_get(&pdev->dev, "alternate");
+ clk = clk_get(dev, "alternate");
if (IS_ERR(clk))
return PTR_ERR(clk);
@@ -689,11 +678,70 @@ static int qcom_cpufreq_hw_driver_probe(struct platform_device *pdev)
if (ret)
return ret;
+ /* Allocate qcom_cpufreq_data based on the available frequency domains in DT */
+ num_domains = of_property_count_elems_of_size(dev->of_node, "reg", sizeof(u32) * 4);
+ if (num_domains <= 0)
+ return num_domains;
+
+ qcom_cpufreq.data = devm_kzalloc(dev, sizeof(struct qcom_cpufreq_data) * num_domains,
+ GFP_KERNEL);
+ if (!qcom_cpufreq.data)
+ return -ENOMEM;
+
+ qcom_cpufreq.soc_data = of_device_get_match_data(dev);
+
+ clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, num_domains), GFP_KERNEL);
+ if (!clk_data)
+ return -ENOMEM;
+
+ clk_data->num = num_domains;
+
+ for (i = 0; i < num_domains; i++) {
+ struct qcom_cpufreq_data *data = &qcom_cpufreq.data[i];
+ struct clk_init_data clk_init = {};
+ struct resource *res;
+ void __iomem *base;
+
+ base = devm_platform_get_and_ioremap_resource(pdev, i, &res);
+ if (IS_ERR(base)) {
+ dev_err(dev, "Failed to map resource %pR\n", res);
+ return PTR_ERR(base);
+ }
+
+ data->base = base;
+ data->res = res;
+
+ /* Register CPU clock for each frequency domain */
+ clk_init.name = kasprintf(GFP_KERNEL, "qcom_cpufreq%d", i);
+ if (!clk_init.name)
+ return -ENOMEM;
+
+ clk_init.flags = CLK_GET_RATE_NOCACHE;
+ clk_init.ops = &qcom_cpufreq_hw_clk_ops;
+ data->cpu_clk.init = &clk_init;
+
+ ret = devm_clk_hw_register(dev, &data->cpu_clk);
+ if (ret < 0) {
+ dev_err(dev, "Failed to register clock %d: %d\n", i, ret);
+ kfree(clk_init.name);
+ return ret;
+ }
+
+ clk_data->hws[i] = &data->cpu_clk;
+ kfree(clk_init.name);
+ }
+
+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data);
+ if (ret < 0) {
+ dev_err(dev, "Failed to add clock provider\n");
+ return ret;
+ }
+
ret = cpufreq_register_driver(&cpufreq_qcom_hw_driver);
if (ret)
- dev_err(&pdev->dev, "CPUFreq HW driver failed to register\n");
+ dev_err(dev, "CPUFreq HW driver failed to register\n");
else
- dev_dbg(&pdev->dev, "QCOM CPUFreq HW driver initialized\n");
+ dev_dbg(dev, "QCOM CPUFreq HW driver initialized\n");
return ret;
}
diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c
index 7d0d62a06bf3..c6fdf019dbde 100644
--- a/drivers/cpufreq/spear-cpufreq.c
+++ b/drivers/cpufreq/spear-cpufreq.c
@@ -39,7 +39,7 @@ static struct clk *spear1340_cpu_get_possible_parent(unsigned long newfreq)
* In SPEAr1340, cpu clk's parent sys clk can take input from
* following sources
*/
- const char *sys_clk_src[] = {
+ static const char * const sys_clk_src[] = {
"sys_syn_clk",
"pll1_clk",
"pll2_clk",
diff --git a/drivers/cpufreq/tegra186-cpufreq.c b/drivers/cpufreq/tegra186-cpufreq.c
index 6c88827f4e62..f98f53bf1011 100644
--- a/drivers/cpufreq/tegra186-cpufreq.c
+++ b/drivers/cpufreq/tegra186-cpufreq.c
@@ -65,8 +65,8 @@ struct tegra186_cpufreq_cluster {
struct tegra186_cpufreq_data {
void __iomem *regs;
- struct tegra186_cpufreq_cluster *clusters;
const struct tegra186_cpufreq_cpu *cpus;
+ struct tegra186_cpufreq_cluster clusters[];
};
static int tegra186_cpufreq_init(struct cpufreq_policy *policy)
@@ -221,15 +221,12 @@ static int tegra186_cpufreq_probe(struct platform_device *pdev)
struct tegra_bpmp *bpmp;
unsigned int i = 0, err;
- data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+ data = devm_kzalloc(&pdev->dev,
+ struct_size(data, clusters, TEGRA186_NUM_CLUSTERS),
+ GFP_KERNEL);
if (!data)
return -ENOMEM;
- data->clusters = devm_kcalloc(&pdev->dev, TEGRA186_NUM_CLUSTERS,
- sizeof(*data->clusters), GFP_KERNEL);
- if (!data->clusters)
- return -ENOMEM;
-
data->cpus = tegra186_cpus;
bpmp = tegra_bpmp_get(&pdev->dev);
diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c
index f64180dd2005..be4209d97cb3 100644
--- a/drivers/cpufreq/ti-cpufreq.c
+++ b/drivers/cpufreq/ti-cpufreq.c
@@ -39,6 +39,14 @@
#define OMAP34xx_ProdID_SKUID 0x4830A20C
#define OMAP3_SYSCON_BASE (0x48000000 + 0x2000 + 0x270)
+#define AM625_EFUSE_K_MPU_OPP 11
+#define AM625_EFUSE_S_MPU_OPP 19
+#define AM625_EFUSE_T_MPU_OPP 20
+
+#define AM625_SUPPORT_K_MPU_OPP BIT(0)
+#define AM625_SUPPORT_S_MPU_OPP BIT(1)
+#define AM625_SUPPORT_T_MPU_OPP BIT(2)
+
#define VERSION_COUNT 2
struct ti_cpufreq_data;
@@ -104,6 +112,25 @@ static unsigned long omap3_efuse_xlate(struct ti_cpufreq_data *opp_data,
return BIT(efuse);
}
+static unsigned long am625_efuse_xlate(struct ti_cpufreq_data *opp_data,
+ unsigned long efuse)
+{
+ unsigned long calculated_efuse = AM625_SUPPORT_K_MPU_OPP;
+
+ switch (efuse) {
+ case AM625_EFUSE_T_MPU_OPP:
+ calculated_efuse |= AM625_SUPPORT_T_MPU_OPP;
+ fallthrough;
+ case AM625_EFUSE_S_MPU_OPP:
+ calculated_efuse |= AM625_SUPPORT_S_MPU_OPP;
+ fallthrough;
+ case AM625_EFUSE_K_MPU_OPP:
+ calculated_efuse |= AM625_SUPPORT_K_MPU_OPP;
+ }
+
+ return calculated_efuse;
+}
+
static struct ti_cpufreq_soc_data am3x_soc_data = {
.efuse_xlate = amx3_efuse_xlate,
.efuse_fallback = AM33XX_800M_ARM_MPU_MAX_FREQ,
@@ -198,6 +225,14 @@ static struct ti_cpufreq_soc_data am3517_soc_data = {
.multi_regulator = false,
};
+static struct ti_cpufreq_soc_data am625_soc_data = {
+ .efuse_xlate = am625_efuse_xlate,
+ .efuse_offset = 0x0018,
+ .efuse_mask = 0x07c0,
+ .efuse_shift = 0x6,
+ .rev_offset = 0x0014,
+ .multi_regulator = false,
+};
/**
* ti_cpufreq_get_efuse() - Parse and return efuse value present on SoC
@@ -301,6 +336,7 @@ static const struct of_device_id ti_cpufreq_of_match[] = {
{ .compatible = "ti,dra7", .data = &dra7_soc_data },
{ .compatible = "ti,omap34xx", .data = &omap34xx_soc_data, },
{ .compatible = "ti,omap36xx", .data = &omap36xx_soc_data, },
+ { .compatible = "ti,am625", .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 821984947ed9..c80cf9ddabd8 100644
--- a/drivers/cpuidle/cpuidle-psci-domain.c
+++ b/drivers/cpuidle/cpuidle-psci-domain.c
@@ -181,7 +181,8 @@ static int psci_cpuidle_domain_probe(struct platform_device *pdev)
if (ret)
goto remove_pd;
- pr_info("Initialized CPU PM domain topology\n");
+ pr_info("Initialized CPU PM domain topology using %s mode\n",
+ use_osi ? "OSI" : "PC");
return 0;
put_node:
diff --git a/drivers/cpuidle/dt_idle_states.c b/drivers/cpuidle/dt_idle_states.c
index 252f2a9686a6..7ca3d7d9b5ea 100644
--- a/drivers/cpuidle/dt_idle_states.c
+++ b/drivers/cpuidle/dt_idle_states.c
@@ -211,18 +211,15 @@ int dt_init_idle_driver(struct cpuidle_driver *drv,
of_node_put(cpu_node);
if (err)
return err;
- /*
- * Update the driver state count only if some valid DT idle states
- * were detected
- */
- if (i)
- drv->state_count = state_idx;
+
+ /* Set the number of total supported idle states. */
+ drv->state_count = state_idx;
/*
* Return the number of present and valid DT idle states, which can
* also be 0 on platforms with missing DT idle states or legacy DT
* configuration predating the DT idle states bindings.
*/
- return i;
+ return state_idx - start_idx;
}
EXPORT_SYMBOL_GPL(dt_init_idle_driver);
diff --git a/drivers/cxl/Kconfig b/drivers/cxl/Kconfig
index 768ced3d6fe8..0ac53c422c31 100644
--- a/drivers/cxl/Kconfig
+++ b/drivers/cxl/Kconfig
@@ -111,4 +111,22 @@ config CXL_REGION
select MEMREGION
select GET_FREE_REGION
+config CXL_REGION_INVALIDATION_TEST
+ bool "CXL: Region Cache Management Bypass (TEST)"
+ depends on CXL_REGION
+ help
+ CXL Region management and security operations potentially invalidate
+ the content of CPU caches without notifiying those caches to
+ invalidate the affected cachelines. The CXL Region driver attempts
+ to invalidate caches when those events occur. If that invalidation
+ fails the region will fail to enable. Reasons for cache
+ invalidation failure are due to the CPU not providing a cache
+ invalidation mechanism. For example usage of wbinvd is restricted to
+ bare metal x86. However, for testing purposes toggling this option
+ can disable that data integrity safety and proceed with enabling
+ regions when there might be conflicting contents in the CPU cache.
+
+ If unsure, or if this kernel is meant for production environments,
+ say N.
+
endif
diff --git a/drivers/cxl/Makefile b/drivers/cxl/Makefile
index a78270794150..db321f48ba52 100644
--- a/drivers/cxl/Makefile
+++ b/drivers/cxl/Makefile
@@ -9,5 +9,5 @@ obj-$(CONFIG_CXL_PORT) += cxl_port.o
cxl_mem-y := mem.o
cxl_pci-y := pci.o
cxl_acpi-y := acpi.o
-cxl_pmem-y := pmem.o
+cxl_pmem-y := pmem.o security.o
cxl_port-y := port.o
diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
index fb649683dd3a..ad0849af42d7 100644
--- a/drivers/cxl/acpi.c
+++ b/drivers/cxl/acpi.c
@@ -6,9 +6,120 @@
#include <linux/kernel.h>
#include <linux/acpi.h>
#include <linux/pci.h>
+#include <asm/div64.h>
#include "cxlpci.h"
#include "cxl.h"
+#define CXL_RCRB_SIZE SZ_8K
+
+struct cxl_cxims_data {
+ int nr_maps;
+ u64 xormaps[];
+};
+
+/*
+ * Find a targets entry (n) in the host bridge interleave list.
+ * CXL Specfication 3.0 Table 9-22
+ */
+static int cxl_xor_calc_n(u64 hpa, struct cxl_cxims_data *cximsd, int iw,
+ int ig)
+{
+ int i = 0, n = 0;
+ u8 eiw;
+
+ /* IW: 2,4,6,8,12,16 begin building 'n' using xormaps */
+ if (iw != 3) {
+ for (i = 0; i < cximsd->nr_maps; i++)
+ n |= (hweight64(hpa & cximsd->xormaps[i]) & 1) << i;
+ }
+ /* IW: 3,6,12 add a modulo calculation to 'n' */
+ if (!is_power_of_2(iw)) {
+ if (ways_to_eiw(iw, &eiw))
+ return -1;
+ hpa &= GENMASK_ULL(51, eiw + ig);
+ n |= do_div(hpa, 3) << i;
+ }
+ return n;
+}
+
+static struct cxl_dport *cxl_hb_xor(struct cxl_root_decoder *cxlrd, int pos)
+{
+ struct cxl_cxims_data *cximsd = cxlrd->platform_data;
+ struct cxl_switch_decoder *cxlsd = &cxlrd->cxlsd;
+ struct cxl_decoder *cxld = &cxlsd->cxld;
+ int ig = cxld->interleave_granularity;
+ int iw = cxld->interleave_ways;
+ int n = 0;
+ u64 hpa;
+
+ if (dev_WARN_ONCE(&cxld->dev,
+ cxld->interleave_ways != cxlsd->nr_targets,
+ "misconfigured root decoder\n"))
+ return NULL;
+
+ hpa = cxlrd->res->start + pos * ig;
+
+ /* Entry (n) is 0 for no interleave (iw == 1) */
+ if (iw != 1)
+ n = cxl_xor_calc_n(hpa, cximsd, iw, ig);
+
+ if (n < 0)
+ return NULL;
+
+ return cxlrd->cxlsd.target[n];
+}
+
+struct cxl_cxims_context {
+ struct device *dev;
+ struct cxl_root_decoder *cxlrd;
+};
+
+static int cxl_parse_cxims(union acpi_subtable_headers *header, void *arg,
+ const unsigned long end)
+{
+ struct acpi_cedt_cxims *cxims = (struct acpi_cedt_cxims *)header;
+ struct cxl_cxims_context *ctx = arg;
+ struct cxl_root_decoder *cxlrd = ctx->cxlrd;
+ struct cxl_decoder *cxld = &cxlrd->cxlsd.cxld;
+ struct device *dev = ctx->dev;
+ struct cxl_cxims_data *cximsd;
+ unsigned int hbig, nr_maps;
+ int rc;
+
+ rc = eig_to_granularity(cxims->hbig, &hbig);
+ if (rc)
+ return rc;
+
+ /* Does this CXIMS entry apply to the given CXL Window? */
+ if (hbig != cxld->interleave_granularity)
+ return 0;
+
+ /* IW 1,3 do not use xormaps and skip this parsing entirely */
+ if (is_power_of_2(cxld->interleave_ways))
+ /* 2, 4, 8, 16 way */
+ nr_maps = ilog2(cxld->interleave_ways);
+ else
+ /* 6, 12 way */
+ nr_maps = ilog2(cxld->interleave_ways / 3);
+
+ if (cxims->nr_xormaps < nr_maps) {
+ dev_dbg(dev, "CXIMS nr_xormaps[%d] expected[%d]\n",
+ cxims->nr_xormaps, nr_maps);
+ return -ENXIO;
+ }
+
+ cximsd = devm_kzalloc(dev, struct_size(cximsd, xormaps, nr_maps),
+ GFP_KERNEL);
+ if (!cximsd)
+ return -ENOMEM;
+ memcpy(cximsd->xormaps, cxims->xormap_list,
+ nr_maps * sizeof(*cximsd->xormaps));
+ cximsd->nr_maps = nr_maps;
+ cxlrd->platform_data = cximsd;
+
+ return 0;
+}
+
static unsigned long cfmws_to_decoder_flags(int restrictions)
{
unsigned long flags = CXL_DECODER_F_ENABLE;
@@ -33,8 +144,10 @@ static int cxl_acpi_cfmws_verify(struct device *dev,
int rc, expected_len;
unsigned int ways;
- if (cfmws->interleave_arithmetic != ACPI_CEDT_CFMWS_ARITHMETIC_MODULO) {
- dev_err(dev, "CFMWS Unsupported Interleave Arithmetic\n");
+ if (cfmws->interleave_arithmetic != ACPI_CEDT_CFMWS_ARITHMETIC_MODULO &&
+ cfmws->interleave_arithmetic != ACPI_CEDT_CFMWS_ARITHMETIC_XOR) {
+ dev_err(dev, "CFMWS Unknown Interleave Arithmetic: %d\n",
+ cfmws->interleave_arithmetic);
return -EINVAL;
}
@@ -48,7 +161,7 @@ static int cxl_acpi_cfmws_verify(struct device *dev,
return -EINVAL;
}
- rc = cxl_to_ways(cfmws->interleave_ways, &ways);
+ rc = eiw_to_ways(cfmws->interleave_ways, &ways);
if (rc) {
dev_err(dev, "CFMWS Interleave Ways (%d) invalid\n",
cfmws->interleave_ways);
@@ -70,6 +183,10 @@ static int cxl_acpi_cfmws_verify(struct device *dev,
return 0;
}
+/*
+ * Note, @dev must be the first member, see 'struct cxl_chbs_context'
+ * and mock_acpi_table_parse_cedt()
+ */
struct cxl_cfmws_context {
struct device *dev;
struct cxl_port *root_port;
@@ -84,9 +201,11 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg,
struct cxl_cfmws_context *ctx = arg;
struct cxl_port *root_port = ctx->root_port;
struct resource *cxl_res = ctx->cxl_res;
+ struct cxl_cxims_context cxims_ctx;
struct cxl_root_decoder *cxlrd;
struct device *dev = ctx->dev;
struct acpi_cedt_cfmws *cfmws;
+ cxl_calc_hb_fn cxl_calc_hb;
struct cxl_decoder *cxld;
unsigned int ways, i, ig;
struct resource *res;
@@ -102,10 +221,10 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg,
return 0;
}
- rc = cxl_to_ways(cfmws->interleave_ways, &ways);
+ rc = eiw_to_ways(cfmws->interleave_ways, &ways);
if (rc)
return rc;
- rc = cxl_to_granularity(cfmws->granularity, &ig);
+ rc = eig_to_granularity(cfmws->granularity, &ig);
if (rc)
return rc;
for (i = 0; i < ways; i++)
@@ -128,7 +247,12 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg,
if (rc)
goto err_insert;
- cxlrd = cxl_root_decoder_alloc(root_port, ways);
+ if (cfmws->interleave_arithmetic == ACPI_CEDT_CFMWS_ARITHMETIC_MODULO)
+ cxl_calc_hb = cxl_hb_modulo;
+ else
+ cxl_calc_hb = cxl_hb_xor;
+
+ cxlrd = cxl_root_decoder_alloc(root_port, ways, cxl_calc_hb);
if (IS_ERR(cxlrd))
return 0;
@@ -148,7 +272,25 @@ static int cxl_parse_cfmws(union acpi_subtable_headers *header, void *arg,
ig = CXL_DECODER_MIN_GRANULARITY;
cxld->interleave_granularity = ig;
+ if (cfmws->interleave_arithmetic == ACPI_CEDT_CFMWS_ARITHMETIC_XOR) {
+ if (ways != 1 && ways != 3) {
+ cxims_ctx = (struct cxl_cxims_context) {
+ .dev = dev,
+ .cxlrd = cxlrd,
+ };
+ rc = acpi_table_parse_cedt(ACPI_CEDT_TYPE_CXIMS,
+ cxl_parse_cxims, &cxims_ctx);
+ if (rc < 0)
+ goto err_xormap;
+ if (!cxlrd->platform_data) {
+ dev_err(dev, "No CXIMS for HBIG %u\n", ig);
+ rc = -EINVAL;
+ goto err_xormap;
+ }
+ }
+ }
rc = cxl_decoder_add(cxld, target_map);
+err_xormap:
if (rc)
put_device(&cxld->dev);
else
@@ -193,34 +335,39 @@ 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 *bridge = to_cxl_host_bridge(host, match);
+ 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 (!bridge)
+ if (!hb)
return 0;
- dport = cxl_find_dport_by_dev(root_port, match);
+ 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;
}
- /*
- * Note that this lookup already succeeded in
- * to_cxl_host_bridge(), so no need to check for failure here
- */
- pci_root = acpi_pci_find_root(bridge->handle);
- rc = devm_cxl_register_pci_bus(host, match, pci_root->bus);
+ 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, match, dport->component_reg_phys, dport);
+ port = devm_cxl_add_port(host, bridge, dport->component_reg_phys,
+ dport);
if (IS_ERR(port))
return PTR_ERR(port);
- dev_dbg(host, "%s: add: %s\n", dev_name(match), dev_name(&port->dev));
+
+ dev_info(bridge, "host supports CXL\n");
return 0;
}
@@ -228,7 +375,9 @@ static int add_host_bridge_uport(struct device *match, void *arg)
struct cxl_chbs_context {
struct device *dev;
unsigned long long uid;
+ resource_size_t rcrb;
resource_size_t chbcr;
+ u32 cxl_version;
};
static int cxl_get_chbcr(union acpi_subtable_headers *header, void *arg,
@@ -244,51 +393,86 @@ static int cxl_get_chbcr(union acpi_subtable_headers *header, void *arg,
if (ctx->uid != chbs->uid)
return 0;
- ctx->chbcr = chbs->base;
+
+ 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;
+ return 0;
+ }
+
+ if (chbs->length != CXL_RCRB_SIZE)
+ return 0;
+
+ ctx->rcrb = chbs->base;
+ ctx->chbcr = cxl_rcrb_to_component(ctx->dev, chbs->base,
+ CXL_RCRB_DOWNSTREAM);
return 0;
}
static int add_host_bridge_dport(struct device *match, void *arg)
{
- acpi_status status;
+ 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;
struct cxl_port *root_port = arg;
struct device *host = root_port->dev.parent;
- struct acpi_device *bridge = to_cxl_host_bridge(host, match);
+ struct acpi_device *hb = to_cxl_host_bridge(host, match);
- if (!bridge)
+ if (!hb)
return 0;
- status = acpi_evaluate_integer(bridge->handle, METHOD_NAME__UID, NULL,
- &uid);
- if (status != AE_OK) {
- dev_err(host, "unable to retrieve _UID of %s\n",
- dev_name(match));
+ 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 = host,
+ .dev = match,
.uid = uid,
};
acpi_table_parse_cedt(ACPI_CEDT_TYPE_CHBS, cxl_get_chbcr, &ctx);
- if (ctx.chbcr == 0) {
- dev_warn(host, "No CHBS found for Host Bridge: %s\n",
- dev_name(match));
+ if (!ctx.chbcr) {
+ dev_warn(match, "No CHBS found for Host Bridge (UID %lld)\n",
+ uid);
return 0;
}
- dport = devm_cxl_add_dport(root_port, match, uid, ctx.chbcr);
- if (IS_ERR(dport)) {
- dev_err(host, "failed to add downstream port: %s\n",
- dev_name(match));
- return PTR_ERR(dport);
+ 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);
+ return 0;
}
- dev_dbg(host, "add dport%llu: %s\n", uid, dev_name(match));
+
+ 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);
+ if (IS_ERR(dport))
+ return PTR_ERR(dport);
+
return 0;
}
@@ -466,7 +650,6 @@ static int cxl_acpi_probe(struct platform_device *pdev)
root_port = devm_cxl_add_port(host, host, CXL_RESOURCE_NONE, NULL);
if (IS_ERR(root_port))
return PTR_ERR(root_port);
- dev_dbg(host, "add: %s\n", dev_name(&root_port->dev));
rc = bus_for_each_dev(adev->dev.bus, NULL, root_port,
add_host_bridge_dport);
@@ -512,7 +695,8 @@ static int cxl_acpi_probe(struct platform_device *pdev)
return rc;
/* In case PCI is scanned before ACPI re-trigger memdev attach */
- return cxl_bus_rescan();
+ cxl_bus_rescan();
+ return 0;
}
static const struct acpi_device_id cxl_acpi_ids[] = {
@@ -536,7 +720,20 @@ static struct platform_driver cxl_acpi_driver = {
.id_table = cxl_test_ids,
};
-module_platform_driver(cxl_acpi_driver);
+static int __init cxl_acpi_init(void)
+{
+ return platform_driver_register(&cxl_acpi_driver);
+}
+
+static void __exit cxl_acpi_exit(void)
+{
+ platform_driver_unregister(&cxl_acpi_driver);
+ cxl_bus_drain();
+}
+
+module_init(cxl_acpi_init);
+module_exit(cxl_acpi_exit);
MODULE_LICENSE("GPL v2");
MODULE_IMPORT_NS(CXL);
MODULE_IMPORT_NS(ACPI);
+MODULE_SOFTDEP("pre: cxl_pmem");
diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
index 1d8f87be283f..8c04672dca56 100644
--- a/drivers/cxl/core/core.h
+++ b/drivers/cxl/core/core.h
@@ -58,14 +58,6 @@ extern struct rw_semaphore cxl_dpa_rwsem;
bool is_switch_decoder(struct device *dev);
struct cxl_switch_decoder *to_cxl_switch_decoder(struct device *dev);
-static inline struct cxl_ep *cxl_ep_load(struct cxl_port *port,
- struct cxl_memdev *cxlmd)
-{
- if (!port)
- return NULL;
-
- return xa_load(&port->endpoints, (unsigned long)&cxlmd->dev);
-}
int cxl_memdev_init(void);
void cxl_memdev_exit(void);
diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
index d1d2caea5c62..dcc16d7cb8f3 100644
--- a/drivers/cxl/core/hdm.c
+++ b/drivers/cxl/core/hdm.c
@@ -82,18 +82,23 @@ static void parse_hdm_decoder_caps(struct cxl_hdm *cxlhdm)
cxlhdm->interleave_mask |= GENMASK(14, 12);
}
-static void __iomem *map_hdm_decoder_regs(struct cxl_port *port,
- void __iomem *crb)
+static int map_hdm_decoder_regs(struct cxl_port *port, void __iomem *crb,
+ struct cxl_component_regs *regs)
{
- struct cxl_component_reg_map map;
+ struct cxl_register_map map = {
+ .resource = port->component_reg_phys,
+ .base = crb,
+ .max_size = CXL_COMPONENT_REG_BLOCK_SIZE,
+ };
- cxl_probe_component_regs(&port->dev, crb, &map);
- if (!map.hdm_decoder.valid) {
+ cxl_probe_component_regs(&port->dev, crb, &map.component_map);
+ if (!map.component_map.hdm_decoder.valid) {
dev_err(&port->dev, "HDM decoder registers invalid\n");
- return IOMEM_ERR_PTR(-ENXIO);
+ return -ENXIO;
}
- return crb + map.hdm_decoder.offset;
+ return cxl_map_component_regs(&port->dev, regs, &map,
+ BIT(CXL_CM_CAP_CAP_ID_HDM));
}
/**
@@ -103,25 +108,25 @@ static void __iomem *map_hdm_decoder_regs(struct cxl_port *port,
struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port)
{
struct device *dev = &port->dev;
- void __iomem *crb, *hdm;
struct cxl_hdm *cxlhdm;
+ void __iomem *crb;
+ int rc;
cxlhdm = devm_kzalloc(dev, sizeof(*cxlhdm), GFP_KERNEL);
if (!cxlhdm)
return ERR_PTR(-ENOMEM);
cxlhdm->port = port;
- crb = devm_cxl_iomap_block(dev, port->component_reg_phys,
- CXL_COMPONENT_REG_BLOCK_SIZE);
+ crb = ioremap(port->component_reg_phys, CXL_COMPONENT_REG_BLOCK_SIZE);
if (!crb) {
dev_err(dev, "No component registers mapped\n");
return ERR_PTR(-ENXIO);
}
- hdm = map_hdm_decoder_regs(port, crb);
- if (IS_ERR(hdm))
- return ERR_CAST(hdm);
- cxlhdm->regs.hdm_decoder = hdm;
+ rc = map_hdm_decoder_regs(port, crb, &cxlhdm->regs);
+ iounmap(crb);
+ if (rc)
+ return ERR_PTR(rc);
parse_hdm_decoder_caps(cxlhdm);
if (cxlhdm->decoder_count == 0) {
@@ -489,10 +494,10 @@ static void cxld_set_interleave(struct cxl_decoder *cxld, u32 *ctrl)
* Input validation ensures these warns never fire, but otherwise
* suppress unititalized variable usage warnings.
*/
- if (WARN_ONCE(ways_to_cxl(cxld->interleave_ways, &eiw),
+ if (WARN_ONCE(ways_to_eiw(cxld->interleave_ways, &eiw),
"invalid interleave_ways: %d\n", cxld->interleave_ways))
return;
- if (WARN_ONCE(granularity_to_cxl(cxld->interleave_granularity, &eig),
+ if (WARN_ONCE(granularity_to_eig(cxld->interleave_granularity, &eig),
"invalid interleave_granularity: %d\n",
cxld->interleave_granularity))
return;
@@ -736,16 +741,16 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
}
cxld->target_type = CXL_DECODER_EXPANDER;
}
- rc = cxl_to_ways(FIELD_GET(CXL_HDM_DECODER0_CTRL_IW_MASK, ctrl),
- &cxld->interleave_ways);
+ rc = eiw_to_ways(FIELD_GET(CXL_HDM_DECODER0_CTRL_IW_MASK, ctrl),
+ &cxld->interleave_ways);
if (rc) {
dev_warn(&port->dev,
"decoder%d.%d: Invalid interleave ways (ctrl: %#x)\n",
port->id, cxld->id, ctrl);
return rc;
}
- rc = cxl_to_granularity(FIELD_GET(CXL_HDM_DECODER0_CTRL_IG_MASK, ctrl),
- &cxld->interleave_granularity);
+ rc = eig_to_granularity(FIELD_GET(CXL_HDM_DECODER0_CTRL_IG_MASK, ctrl),
+ &cxld->interleave_granularity);
if (rc)
return rc;
diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
index 0c90f13870a4..b03fba212799 100644
--- a/drivers/cxl/core/mbox.c
+++ b/drivers/cxl/core/mbox.c
@@ -140,13 +140,9 @@ static const char *cxl_mem_opcode_to_name(u16 opcode)
}
/**
- * cxl_mbox_send_cmd() - Send a mailbox command to a device.
+ * cxl_internal_send_cmd() - Kernel internal interface to send a mailbox command
* @cxlds: The device data for the operation
- * @opcode: Opcode for the mailbox command.
- * @in: The input payload for the mailbox command.
- * @in_size: The length of the input payload
- * @out: Caller allocated buffer for the output.
- * @out_size: Expected size of output.
+ * @mbox_cmd: initialized command to execute
*
* Context: Any context.
* Return:
@@ -161,40 +157,40 @@ 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_mbox_send_cmd(struct cxl_dev_state *cxlds, u16 opcode, void *in,
- size_t in_size, void *out, size_t out_size)
+int cxl_internal_send_cmd(struct cxl_dev_state *cxlds,
+ struct cxl_mbox_cmd *mbox_cmd)
{
- const struct cxl_mem_command *cmd = cxl_mem_find_command(opcode);
- struct cxl_mbox_cmd mbox_cmd = {
- .opcode = opcode,
- .payload_in = in,
- .size_in = in_size,
- .size_out = out_size,
- .payload_out = out,
- };
+ size_t out_size, min_out;
int rc;
- if (in_size > cxlds->payload_size || out_size > cxlds->payload_size)
+ if (mbox_cmd->size_in > cxlds->payload_size ||
+ mbox_cmd->size_out > cxlds->payload_size)
return -E2BIG;
- rc = cxlds->mbox_send(cxlds, &mbox_cmd);
+ out_size = mbox_cmd->size_out;
+ min_out = mbox_cmd->min_out;
+ rc = cxlds->mbox_send(cxlds, mbox_cmd);
if (rc)
return rc;
- if (mbox_cmd.return_code != CXL_MBOX_CMD_RC_SUCCESS)
- return cxl_mbox_cmd_rc2errno(&mbox_cmd);
+ if (mbox_cmd->return_code != CXL_MBOX_CMD_RC_SUCCESS)
+ return cxl_mbox_cmd_rc2errno(mbox_cmd);
+
+ if (!out_size)
+ return 0;
/*
- * Variable sized commands can't be validated and so it's up to the
- * caller to do that if they wish.
+ * Variable sized output needs to at least satisfy the caller's
+ * minimum if not the fully requested size.
*/
- if (cmd->info.size_out != CXL_VARIABLE_PAYLOAD) {
- if (mbox_cmd.size_out != out_size)
- return -EIO;
- }
+ if (min_out == 0)
+ min_out = out_size;
+
+ if (mbox_cmd->size_out < min_out)
+ return -EIO;
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cxl_mbox_send_cmd, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_internal_send_cmd, CXL);
static bool cxl_mem_raw_command_allowed(u16 opcode)
{
@@ -561,15 +557,25 @@ static int cxl_xfer_log(struct cxl_dev_state *cxlds, uuid_t *uuid, u32 size, u8
while (remaining) {
u32 xfer_size = min_t(u32, remaining, cxlds->payload_size);
- struct cxl_mbox_get_log log = {
+ struct cxl_mbox_cmd mbox_cmd;
+ struct cxl_mbox_get_log log;
+ int rc;
+
+ log = (struct cxl_mbox_get_log) {
.uuid = *uuid,
.offset = cpu_to_le32(offset),
- .length = cpu_to_le32(xfer_size)
+ .length = cpu_to_le32(xfer_size),
};
- int rc;
- rc = cxl_mbox_send_cmd(cxlds, CXL_MBOX_OP_GET_LOG, &log, sizeof(log),
- out, xfer_size);
+ mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_GET_LOG,
+ .size_in = sizeof(log),
+ .payload_in = &log,
+ .size_out = xfer_size,
+ .payload_out = out,
+ };
+
+ rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
if (rc < 0)
return rc;
@@ -615,19 +621,27 @@ static void cxl_walk_cel(struct cxl_dev_state *cxlds, size_t size, u8 *cel)
static struct cxl_mbox_get_supported_logs *cxl_get_gsl(struct cxl_dev_state *cxlds)
{
struct cxl_mbox_get_supported_logs *ret;
+ struct cxl_mbox_cmd mbox_cmd;
int rc;
ret = kvmalloc(cxlds->payload_size, GFP_KERNEL);
if (!ret)
return ERR_PTR(-ENOMEM);
- rc = cxl_mbox_send_cmd(cxlds, CXL_MBOX_OP_GET_SUPPORTED_LOGS, NULL, 0, ret,
- cxlds->payload_size);
+ mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_GET_SUPPORTED_LOGS,
+ .size_out = cxlds->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);
if (rc < 0) {
kvfree(ret);
return ERR_PTR(rc);
}
+
return ret;
}
@@ -697,7 +711,6 @@ int cxl_enumerate_cmds(struct cxl_dev_state *cxlds)
/* Found the required CEL */
rc = 0;
}
-
out:
kvfree(gsl);
return rc;
@@ -719,11 +732,15 @@ EXPORT_SYMBOL_NS_GPL(cxl_enumerate_cmds, CXL);
static int cxl_mem_get_partition_info(struct cxl_dev_state *cxlds)
{
struct cxl_mbox_get_partition_info pi;
+ struct cxl_mbox_cmd mbox_cmd;
int rc;
- rc = cxl_mbox_send_cmd(cxlds, CXL_MBOX_OP_GET_PARTITION_INFO, NULL, 0,
- &pi, sizeof(pi));
-
+ mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_GET_PARTITION_INFO,
+ .size_out = sizeof(pi),
+ .payload_out = &pi,
+ };
+ rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
if (rc)
return rc;
@@ -752,10 +769,15 @@ int cxl_dev_state_identify(struct cxl_dev_state *cxlds)
{
/* See CXL 2.0 Table 175 Identify Memory Device Output Payload */
struct cxl_mbox_identify id;
+ struct cxl_mbox_cmd mbox_cmd;
int rc;
- rc = cxl_mbox_send_cmd(cxlds, CXL_MBOX_OP_IDENTIFY, NULL, 0, &id,
- sizeof(id));
+ mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_IDENTIFY,
+ .size_out = sizeof(id),
+ .payload_out = &id,
+ };
+ rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
if (rc < 0)
return rc;
diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
index 20ce488a7754..a74a93310d26 100644
--- a/drivers/cxl/core/memdev.c
+++ b/drivers/cxl/core/memdev.c
@@ -344,6 +344,7 @@ struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds)
* needed as this is ordered with cdev_add() publishing the device.
*/
cxlmd->cxlds = cxlds;
+ cxlds->cxlmd = cxlmd;
cdev = &cxlmd->cdev;
rc = cdev_device_add(cdev, dev);
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 9240df53ed87..57764e9cd19d 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -54,16 +54,13 @@ static int match_add_dports(struct pci_dev *pdev, void *data)
dev_dbg(&port->dev, "failed to find component registers\n");
port_num = FIELD_GET(PCI_EXP_LNKCAP_PN, lnkcap);
- dport = devm_cxl_add_dport(port, &pdev->dev, port_num,
- cxl_regmap_to_base(pdev, &map));
+ dport = devm_cxl_add_dport(port, &pdev->dev, port_num, map.resource);
if (IS_ERR(dport)) {
ctx->error = PTR_ERR(dport);
return PTR_ERR(dport);
}
ctx->count++;
- dev_dbg(&port->dev, "add dport%d: %s\n", port_num, dev_name(&pdev->dev));
-
return 0;
}
diff --git a/drivers/cxl/core/pmem.c b/drivers/cxl/core/pmem.c
index 36aa5070d902..f3d2169b6731 100644
--- a/drivers/cxl/core/pmem.c
+++ b/drivers/cxl/core/pmem.c
@@ -99,7 +99,6 @@ static struct cxl_nvdimm_bridge *cxl_nvdimm_bridge_alloc(struct cxl_port *port)
dev = &cxl_nvb->dev;
cxl_nvb->port = port;
- cxl_nvb->state = CXL_NVB_NEW;
device_initialize(dev);
lockdep_set_class(&dev->mutex, &cxl_nvdimm_bridge_key);
device_set_pm_not_required(dev);
@@ -117,28 +116,7 @@ err:
static void unregister_nvb(void *_cxl_nvb)
{
struct cxl_nvdimm_bridge *cxl_nvb = _cxl_nvb;
- bool flush;
- /*
- * If the bridge was ever activated then there might be in-flight state
- * work to flush. Once the state has been changed to 'dead' then no new
- * work can be queued by user-triggered bind.
- */
- device_lock(&cxl_nvb->dev);
- flush = cxl_nvb->state != CXL_NVB_NEW;
- cxl_nvb->state = CXL_NVB_DEAD;
- device_unlock(&cxl_nvb->dev);
-
- /*
- * Even though the device core will trigger device_release_driver()
- * before the unregister, it does not know about the fact that
- * cxl_nvdimm_bridge_driver defers ->remove() work. So, do the driver
- * release not and flush it before tearing down the nvdimm device
- * hierarchy.
- */
- device_release_driver(&cxl_nvb->dev);
- if (flush)
- flush_work(&cxl_nvb->state_work);
device_unregister(&cxl_nvb->dev);
}
@@ -188,7 +166,6 @@ static void cxl_nvdimm_release(struct device *dev)
{
struct cxl_nvdimm *cxl_nvd = to_cxl_nvdimm(dev);
- xa_destroy(&cxl_nvd->pmem_regions);
kfree(cxl_nvd);
}
@@ -220,7 +197,8 @@ EXPORT_SYMBOL_NS_GPL(to_cxl_nvdimm, CXL);
static struct lock_class_key cxl_nvdimm_key;
-static struct cxl_nvdimm *cxl_nvdimm_alloc(struct cxl_memdev *cxlmd)
+static struct cxl_nvdimm *cxl_nvdimm_alloc(struct cxl_nvdimm_bridge *cxl_nvb,
+ struct cxl_memdev *cxlmd)
{
struct cxl_nvdimm *cxl_nvd;
struct device *dev;
@@ -231,38 +209,78 @@ static struct cxl_nvdimm *cxl_nvdimm_alloc(struct cxl_memdev *cxlmd)
dev = &cxl_nvd->dev;
cxl_nvd->cxlmd = cxlmd;
- xa_init(&cxl_nvd->pmem_regions);
+ cxlmd->cxl_nvd = cxl_nvd;
device_initialize(dev);
lockdep_set_class(&dev->mutex, &cxl_nvdimm_key);
device_set_pm_not_required(dev);
dev->parent = &cxlmd->dev;
dev->bus = &cxl_bus_type;
dev->type = &cxl_nvdimm_type;
+ /*
+ * A "%llx" string is 17-bytes vs dimm_id that is max
+ * NVDIMM_KEY_DESC_LEN
+ */
+ BUILD_BUG_ON(sizeof(cxl_nvd->dev_id) < 17 ||
+ sizeof(cxl_nvd->dev_id) > NVDIMM_KEY_DESC_LEN);
+ sprintf(cxl_nvd->dev_id, "%llx", cxlmd->cxlds->serial);
return cxl_nvd;
}
-static void cxl_nvd_unregister(void *dev)
+static void cxl_nvd_unregister(void *_cxl_nvd)
{
- device_unregister(dev);
+ struct cxl_nvdimm *cxl_nvd = _cxl_nvd;
+ struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
+ struct cxl_nvdimm_bridge *cxl_nvb = cxlmd->cxl_nvb;
+
+ /*
+ * Either the bridge is in ->remove() context under the device_lock(),
+ * or cxlmd_release_nvdimm() is cancelling the bridge's release action
+ * for @cxl_nvd and doing it itself (while manually holding the bridge
+ * lock).
+ */
+ device_lock_assert(&cxl_nvb->dev);
+ cxl_nvd->cxlmd = NULL;
+ cxlmd->cxl_nvd = NULL;
+ device_unregister(&cxl_nvd->dev);
+}
+
+static void cxlmd_release_nvdimm(void *_cxlmd)
+{
+ struct cxl_memdev *cxlmd = _cxlmd;
+ struct cxl_nvdimm_bridge *cxl_nvb = cxlmd->cxl_nvb;
+
+ device_lock(&cxl_nvb->dev);
+ if (cxlmd->cxl_nvd)
+ devm_release_action(&cxl_nvb->dev, cxl_nvd_unregister,
+ cxlmd->cxl_nvd);
+ device_unlock(&cxl_nvb->dev);
+ put_device(&cxl_nvb->dev);
}
/**
* devm_cxl_add_nvdimm() - add a bridge between a cxl_memdev and an nvdimm
- * @host: same host as @cxlmd
* @cxlmd: cxl_memdev instance that will perform LIBNVDIMM operations
*
* Return: 0 on success negative error code on failure.
*/
-int devm_cxl_add_nvdimm(struct device *host, struct cxl_memdev *cxlmd)
+int devm_cxl_add_nvdimm(struct cxl_memdev *cxlmd)
{
+ struct cxl_nvdimm_bridge *cxl_nvb;
struct cxl_nvdimm *cxl_nvd;
struct device *dev;
int rc;
- cxl_nvd = cxl_nvdimm_alloc(cxlmd);
- if (IS_ERR(cxl_nvd))
- return PTR_ERR(cxl_nvd);
+ cxl_nvb = cxl_find_nvdimm_bridge(&cxlmd->dev);
+ if (!cxl_nvb)
+ return -ENODEV;
+
+ cxl_nvd = cxl_nvdimm_alloc(cxl_nvb, cxlmd);
+ if (IS_ERR(cxl_nvd)) {
+ rc = PTR_ERR(cxl_nvd);
+ goto err_alloc;
+ }
+ cxlmd->cxl_nvb = cxl_nvb;
dev = &cxl_nvd->dev;
rc = dev_set_name(dev, "pmem%d", cxlmd->id);
@@ -273,13 +291,34 @@ int devm_cxl_add_nvdimm(struct device *host, struct cxl_memdev *cxlmd)
if (rc)
goto err;
- dev_dbg(host, "%s: register %s\n", dev_name(dev->parent),
- dev_name(dev));
+ dev_dbg(&cxlmd->dev, "register %s\n", dev_name(dev));
+
+ /*
+ * The two actions below arrange for @cxl_nvd to be deleted when either
+ * the top-level PMEM bridge goes down, or the endpoint device goes
+ * through ->remove().
+ */
+ device_lock(&cxl_nvb->dev);
+ if (cxl_nvb->dev.driver)
+ rc = devm_add_action_or_reset(&cxl_nvb->dev, cxl_nvd_unregister,
+ cxl_nvd);
+ else
+ rc = -ENXIO;
+ device_unlock(&cxl_nvb->dev);
- return devm_add_action_or_reset(host, cxl_nvd_unregister, dev);
+ if (rc)
+ goto err_alloc;
+
+ /* @cxlmd carries a reference on @cxl_nvb until cxlmd_release_nvdimm */
+ return devm_add_action_or_reset(&cxlmd->dev, cxlmd_release_nvdimm, cxlmd);
err:
put_device(dev);
+err_alloc:
+ cxlmd->cxl_nvb = NULL;
+ cxlmd->cxl_nvd = NULL;
+ put_device(&cxl_nvb->dev);
+
return rc;
}
EXPORT_SYMBOL_NS_GPL(devm_cxl_add_nvdimm, CXL);
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index e7556864ea80..b631a0520456 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -628,6 +628,8 @@ static struct cxl_port *cxl_port_alloc(struct device *uport,
iter = to_cxl_port(iter->dev.parent);
if (iter->host_bridge)
port->host_bridge = iter->host_bridge;
+ else if (parent_dport->rch)
+ port->host_bridge = parent_dport->dport;
else
port->host_bridge = iter->uport;
dev_dbg(uport, "host-bridge: %s\n", dev_name(port->host_bridge));
@@ -655,16 +657,10 @@ err:
return ERR_PTR(rc);
}
-/**
- * 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
- * @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,
- resource_size_t component_reg_phys,
- struct cxl_dport *parent_dport)
+static struct cxl_port *__devm_cxl_add_port(struct device *host,
+ struct device *uport,
+ resource_size_t component_reg_phys,
+ struct cxl_dport *parent_dport)
{
struct cxl_port *port;
struct device *dev;
@@ -702,6 +698,41 @@ err:
put_device(dev);
return ERR_PTR(rc);
}
+
+/**
+ * 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
+ * @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,
+ 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,
+ parent_dport);
+
+ parent_port = parent_dport ? parent_dport->port : NULL;
+ if (IS_ERR(port)) {
+ dev_dbg(uport, "Failed to add %s%s%s%s: %ld\n",
+ dev_name(&port->dev),
+ parent_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_name(&port->dev),
+ parent_port ? " to " : "",
+ parent_port ? dev_name(&parent_port->dev) : "",
+ parent_port ? "" : " (root port)");
+ }
+
+ return port;
+}
EXPORT_SYMBOL_NS_GPL(devm_cxl_add_port, CXL);
struct pci_bus *cxl_port_to_pci_bus(struct cxl_port *port)
@@ -870,20 +901,10 @@ static void cxl_dport_unlink(void *data)
sysfs_remove_link(&port->dev.kobj, link_name);
}
-/**
- * devm_cxl_add_dport - append downstream port data to a cxl_port
- * @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
- *
- * Note that dports are appended to the devm release action's of the
- * either the port's host (for root ports), or the port itself (for
- * switch ports)
- */
-struct cxl_dport *devm_cxl_add_dport(struct cxl_port *port,
- struct device *dport_dev, int port_id,
- resource_size_t component_reg_phys)
+static struct cxl_dport *
+__devm_cxl_add_dport(struct cxl_port *port, struct device *dport_dev,
+ int port_id, resource_size_t component_reg_phys,
+ resource_size_t rcrb)
{
char link_name[CXL_TARGET_STRLEN];
struct cxl_dport *dport;
@@ -913,6 +934,9 @@ struct cxl_dport *devm_cxl_add_dport(struct cxl_port *port,
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;
cond_cxl_root_lock(port);
rc = add_dport(port, dport);
@@ -935,8 +959,74 @@ struct cxl_dport *devm_cxl_add_dport(struct cxl_port *port,
return dport;
}
+
+/**
+ * devm_cxl_add_dport - append VH downstream port data to a cxl_port
+ * @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
+ *
+ * Note that dports are appended to the devm release action's of the
+ * either the port's host (for root ports), or the port itself (for
+ * switch ports)
+ */
+struct cxl_dport *devm_cxl_add_dport(struct cxl_port *port,
+ struct device *dport_dev, int port_id,
+ resource_size_t component_reg_phys)
+{
+ struct cxl_dport *dport;
+
+ dport = __devm_cxl_add_dport(port, dport_dev, port_id,
+ component_reg_phys, CXL_RESOURCE_NONE);
+ if (IS_ERR(dport)) {
+ dev_dbg(dport_dev, "failed to add dport to %s: %ld\n",
+ dev_name(&port->dev), PTR_ERR(dport));
+ } else {
+ dev_dbg(dport_dev, "dport added to %s\n",
+ dev_name(&port->dev));
+ }
+
+ return dport;
+}
EXPORT_SYMBOL_NS_GPL(devm_cxl_add_dport, CXL);
+/**
+ * devm_cxl_add_rch_dport - append RCH downstream port data to a cxl_port
+ * @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;
+
+ if (rcrb == CXL_RESOURCE_NONE) {
+ dev_dbg(&port->dev, "failed to add RCH dport, missing RCRB\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ dport = __devm_cxl_add_dport(port, dport_dev, port_id,
+ component_reg_phys, 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));
+ } else {
+ dev_dbg(dport_dev, "RCH dport added to %s\n",
+ dev_name(&port->dev));
+ }
+
+ return dport;
+}
+EXPORT_SYMBOL_NS_GPL(devm_cxl_add_rch_dport, CXL);
+
static int add_ep(struct cxl_ep *new)
{
struct cxl_port *port = new->dport->port;
@@ -1122,47 +1212,6 @@ static void reap_dports(struct cxl_port *port)
}
}
-int devm_cxl_add_endpoint(struct cxl_memdev *cxlmd,
- struct cxl_dport *parent_dport)
-{
- struct cxl_port *parent_port = parent_dport->port;
- struct cxl_dev_state *cxlds = cxlmd->cxlds;
- struct cxl_port *endpoint, *iter, *down;
- int rc;
-
- /*
- * Now that the path to the root is established record all the
- * intervening ports in the chain.
- */
- for (iter = parent_port, down = NULL; !is_cxl_root(iter);
- down = iter, iter = to_cxl_port(iter->dev.parent)) {
- struct cxl_ep *ep;
-
- ep = cxl_ep_load(iter, cxlmd);
- ep->next = down;
- }
-
- endpoint = devm_cxl_add_port(&parent_port->dev, &cxlmd->dev,
- cxlds->component_reg_phys, parent_dport);
- if (IS_ERR(endpoint))
- return PTR_ERR(endpoint);
-
- dev_dbg(&cxlmd->dev, "add: %s\n", dev_name(&endpoint->dev));
-
- rc = cxl_endpoint_autoremove(cxlmd, endpoint);
- if (rc)
- return rc;
-
- if (!endpoint->dev.driver) {
- dev_err(&cxlmd->dev, "%s failed probe\n",
- dev_name(&endpoint->dev));
- return -ENXIO;
- }
-
- return 0;
-}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_add_endpoint, CXL);
-
static void cxl_detach_ep(void *data)
{
struct cxl_memdev *cxlmd = data;
@@ -1243,7 +1292,7 @@ static resource_size_t find_component_registers(struct device *dev)
pdev = to_pci_dev(dev);
cxl_find_regblock(pdev, CXL_REGLOC_RBI_COMPONENT, &map);
- return cxl_regmap_to_base(pdev, &map);
+ return map.resource;
}
static int add_port_attach_ep(struct cxl_memdev *cxlmd,
@@ -1320,6 +1369,13 @@ int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd)
struct device *iter;
int rc;
+ /*
+ * Skip intermediate port enumeration in the RCH case, there
+ * are no ports in between a host bridge and an endpoint.
+ */
+ if (cxlmd->cxlds->rcd)
+ return 0;
+
rc = devm_add_action_or_reset(&cxlmd->dev, cxl_detach_ep, cxlmd);
if (rc)
return rc;
@@ -1428,7 +1484,7 @@ static int decoder_populate_targets(struct cxl_switch_decoder *cxlsd,
return rc;
}
-static struct cxl_dport *cxl_hb_modulo(struct cxl_root_decoder *cxlrd, int pos)
+struct cxl_dport *cxl_hb_modulo(struct cxl_root_decoder *cxlrd, int pos)
{
struct cxl_switch_decoder *cxlsd = &cxlrd->cxlsd;
struct cxl_decoder *cxld = &cxlsd->cxld;
@@ -1441,6 +1497,7 @@ static struct cxl_dport *cxl_hb_modulo(struct cxl_root_decoder *cxlrd, int pos)
return cxlrd->cxlsd.target[pos % iw];
}
+EXPORT_SYMBOL_NS_GPL(cxl_hb_modulo, CXL);
static struct lock_class_key cxl_decoder_key;
@@ -1502,6 +1559,7 @@ static int cxl_switch_decoder_init(struct cxl_port *port,
* cxl_root_decoder_alloc - Allocate a root level decoder
* @port: owning CXL root of this decoder
* @nr_targets: static number of downstream targets
+ * @calc_hb: which host bridge covers the n'th position by granularity
*
* Return: A new cxl decoder to be registered by cxl_decoder_add(). A
* 'CXL root' decoder is one that decodes from a top-level / static platform
@@ -1509,7 +1567,8 @@ static int cxl_switch_decoder_init(struct cxl_port *port,
* topology.
*/
struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
- unsigned int nr_targets)
+ unsigned int nr_targets,
+ cxl_calc_hb_fn calc_hb)
{
struct cxl_root_decoder *cxlrd;
struct cxl_switch_decoder *cxlsd;
@@ -1531,7 +1590,7 @@ struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
return ERR_PTR(rc);
}
- cxlrd->calc_hb = cxl_hb_modulo;
+ cxlrd->calc_hb = calc_hb;
cxld = &cxlsd->cxld;
cxld->dev.type = &cxl_decoder_root_type;
@@ -1797,12 +1856,27 @@ static void cxl_bus_remove(struct device *dev)
static struct workqueue_struct *cxl_bus_wq;
-int cxl_bus_rescan(void)
+static void cxl_bus_rescan_queue(struct work_struct *w)
{
- return bus_rescan_devices(&cxl_bus_type);
+ int rc = bus_rescan_devices(&cxl_bus_type);
+
+ pr_debug("CXL bus rescan result: %d\n", rc);
+}
+
+void cxl_bus_rescan(void)
+{
+ static DECLARE_WORK(rescan_work, cxl_bus_rescan_queue);
+
+ queue_work(cxl_bus_wq, &rescan_work);
}
EXPORT_SYMBOL_NS_GPL(cxl_bus_rescan, CXL);
+void cxl_bus_drain(void)
+{
+ drain_workqueue(cxl_bus_wq);
+}
+EXPORT_SYMBOL_NS_GPL(cxl_bus_drain, CXL);
+
bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd)
{
return queue_work(cxl_bus_wq, &cxlmd->detach_work);
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index f9ae5ad284ff..02f28da519e3 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -324,7 +324,7 @@ static ssize_t interleave_ways_store(struct device *dev,
if (rc)
return rc;
- rc = ways_to_cxl(val, &iw);
+ rc = ways_to_eiw(val, &iw);
if (rc)
return rc;
@@ -391,7 +391,7 @@ static ssize_t interleave_granularity_store(struct device *dev,
if (rc)
return rc;
- rc = granularity_to_cxl(val, &ig);
+ rc = granularity_to_eig(val, &ig);
if (rc)
return rc;
@@ -1028,7 +1028,7 @@ static int cxl_port_setup_targets(struct cxl_port *port,
parent_iw = parent_cxld->interleave_ways;
}
- rc = granularity_to_cxl(parent_ig, &peig);
+ 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),
@@ -1036,7 +1036,7 @@ static int cxl_port_setup_targets(struct cxl_port *port,
return rc;
}
- rc = ways_to_cxl(parent_iw, &peiw);
+ 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),
@@ -1045,7 +1045,7 @@ static int cxl_port_setup_targets(struct cxl_port *port,
}
iw = cxl_rr->nr_targets;
- rc = ways_to_cxl(iw, &eiw);
+ 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);
@@ -1065,7 +1065,7 @@ static int cxl_port_setup_targets(struct cxl_port *port,
eig = peig;
}
- rc = cxl_to_granularity(eig, &ig);
+ 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),
@@ -1226,7 +1226,7 @@ static int cxl_region_attach(struct cxl_region *cxlr,
struct cxl_endpoint_decoder *cxled_target;
struct cxl_memdev *cxlmd_target;
- cxled_target = p->targets[pos];
+ cxled_target = p->targets[i];
if (!cxled_target)
continue;
@@ -1403,6 +1403,8 @@ static int attach_target(struct cxl_region *cxlr, const char *decoder, int pos)
goto out;
down_read(&cxl_dpa_rwsem);
rc = cxl_region_attach(cxlr, to_cxl_endpoint_decoder(dev), pos);
+ if (rc == 0)
+ set_bit(CXL_REGION_F_INCOHERENT, &cxlr->flags);
up_read(&cxl_dpa_rwsem);
up_write(&cxl_region_rwsem);
out:
@@ -1812,6 +1814,7 @@ static struct lock_class_key cxl_pmem_region_key;
static struct cxl_pmem_region *cxl_pmem_region_alloc(struct cxl_region *cxlr)
{
struct cxl_region_params *p = &cxlr->params;
+ struct cxl_nvdimm_bridge *cxl_nvb;
struct cxl_pmem_region *cxlr_pmem;
struct device *dev;
int i;
@@ -1839,6 +1842,18 @@ static struct cxl_pmem_region *cxl_pmem_region_alloc(struct cxl_region *cxlr)
struct cxl_memdev *cxlmd = cxled_to_memdev(cxled);
struct cxl_pmem_region_mapping *m = &cxlr_pmem->mapping[i];
+ /*
+ * Regions never span CXL root devices, so by definition the
+ * bridge for one device is the same for all.
+ */
+ if (i == 0) {
+ cxl_nvb = cxl_find_nvdimm_bridge(&cxlmd->dev);
+ if (!cxl_nvb) {
+ cxlr_pmem = ERR_PTR(-ENODEV);
+ goto out;
+ }
+ cxlr->cxl_nvb = cxl_nvb;
+ }
m->cxlmd = cxlmd;
get_device(&cxlmd->dev);
m->start = cxled->dpa_res->start;
@@ -1848,6 +1863,7 @@ static struct cxl_pmem_region *cxl_pmem_region_alloc(struct cxl_region *cxlr)
dev = &cxlr_pmem->dev;
cxlr_pmem->cxlr = cxlr;
+ cxlr->cxlr_pmem = cxlr_pmem;
device_initialize(dev);
lockdep_set_class(&dev->mutex, &cxl_pmem_region_key);
device_set_pm_not_required(dev);
@@ -1860,9 +1876,36 @@ out:
return cxlr_pmem;
}
-static void cxlr_pmem_unregister(void *dev)
+static void cxlr_pmem_unregister(void *_cxlr_pmem)
{
- device_unregister(dev);
+ struct cxl_pmem_region *cxlr_pmem = _cxlr_pmem;
+ struct cxl_region *cxlr = cxlr_pmem->cxlr;
+ struct cxl_nvdimm_bridge *cxl_nvb = cxlr->cxl_nvb;
+
+ /*
+ * Either the bridge is in ->remove() context under the device_lock(),
+ * or cxlr_release_nvdimm() is cancelling the bridge's release action
+ * for @cxlr_pmem and doing it itself (while manually holding the bridge
+ * lock).
+ */
+ device_lock_assert(&cxl_nvb->dev);
+ cxlr->cxlr_pmem = NULL;
+ cxlr_pmem->cxlr = NULL;
+ device_unregister(&cxlr_pmem->dev);
+}
+
+static void cxlr_release_nvdimm(void *_cxlr)
+{
+ struct cxl_region *cxlr = _cxlr;
+ struct cxl_nvdimm_bridge *cxl_nvb = cxlr->cxl_nvb;
+
+ device_lock(&cxl_nvb->dev);
+ if (cxlr->cxlr_pmem)
+ devm_release_action(&cxl_nvb->dev, cxlr_pmem_unregister,
+ cxlr->cxlr_pmem);
+ device_unlock(&cxl_nvb->dev);
+ cxlr->cxl_nvb = NULL;
+ put_device(&cxl_nvb->dev);
}
/**
@@ -1874,12 +1917,14 @@ static void cxlr_pmem_unregister(void *dev)
static int devm_cxl_add_pmem_region(struct cxl_region *cxlr)
{
struct cxl_pmem_region *cxlr_pmem;
+ struct cxl_nvdimm_bridge *cxl_nvb;
struct device *dev;
int rc;
cxlr_pmem = cxl_pmem_region_alloc(cxlr);
if (IS_ERR(cxlr_pmem))
return PTR_ERR(cxlr_pmem);
+ cxl_nvb = cxlr->cxl_nvb;
dev = &cxlr_pmem->dev;
rc = dev_set_name(dev, "pmem_region%d", cxlr->id);
@@ -1893,13 +1938,52 @@ static int devm_cxl_add_pmem_region(struct cxl_region *cxlr)
dev_dbg(&cxlr->dev, "%s: register %s\n", dev_name(dev->parent),
dev_name(dev));
- return devm_add_action_or_reset(&cxlr->dev, cxlr_pmem_unregister, dev);
+ device_lock(&cxl_nvb->dev);
+ if (cxl_nvb->dev.driver)
+ rc = devm_add_action_or_reset(&cxl_nvb->dev,
+ cxlr_pmem_unregister, cxlr_pmem);
+ else
+ rc = -ENXIO;
+ device_unlock(&cxl_nvb->dev);
+
+ if (rc)
+ goto err_bridge;
+
+ /* @cxlr carries a reference on @cxl_nvb until cxlr_release_nvdimm */
+ return devm_add_action_or_reset(&cxlr->dev, cxlr_release_nvdimm, cxlr);
err:
put_device(dev);
+err_bridge:
+ put_device(&cxl_nvb->dev);
+ cxlr->cxl_nvb = NULL;
return rc;
}
+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(
+ &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 cxl_region_probe(struct device *dev)
{
struct cxl_region *cxlr = to_cxl_region(dev);
@@ -1915,14 +1999,21 @@ static int cxl_region_probe(struct device *dev)
if (p->state < CXL_CONFIG_COMMIT) {
dev_dbg(&cxlr->dev, "config state: %d\n", p->state);
rc = -ENXIO;
+ goto out;
}
+ rc = cxl_region_invalidate_memregion(cxlr);
+
/*
* From this point on any path that changes the region's state away from
* CXL_CONFIG_COMMIT is also responsible for releasing the driver.
*/
+out:
up_read(&cxl_region_rwsem);
+ if (rc)
+ return rc;
+
switch (cxlr->mode) {
case CXL_DECODER_PMEM:
return devm_cxl_add_pmem_region(cxlr);
@@ -1950,4 +2041,5 @@ void cxl_region_exit(void)
}
MODULE_IMPORT_NS(CXL);
+MODULE_IMPORT_NS(DEVMEM);
MODULE_ALIAS_CXL(CXL_DEVICE_REGION);
diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c
index 39a129c57d40..1476a0299c9b 100644
--- a/drivers/cxl/core/regs.c
+++ b/drivers/cxl/core/regs.c
@@ -7,6 +7,8 @@
#include <cxlmem.h>
#include <cxlpci.h>
+#include "core.h"
+
/**
* DOC: cxl registers
*
@@ -59,36 +61,48 @@ void cxl_probe_component_regs(struct device *dev, void __iomem *base,
for (cap = 1; cap <= cap_count; cap++) {
void __iomem *register_block;
- u32 hdr;
- int decoder_cnt;
+ struct cxl_reg_map *rmap;
u16 cap_id, offset;
- u32 length;
+ u32 length, hdr;
hdr = readl(base + cap * 0x4);
cap_id = FIELD_GET(CXL_CM_CAP_HDR_ID_MASK, hdr);
offset = FIELD_GET(CXL_CM_CAP_PTR_MASK, hdr);
register_block = base + offset;
+ hdr = readl(register_block);
+ rmap = NULL;
switch (cap_id) {
- case CXL_CM_CAP_CAP_ID_HDM:
+ case CXL_CM_CAP_CAP_ID_HDM: {
+ int decoder_cnt;
+
dev_dbg(dev, "found HDM decoder capability (0x%x)\n",
offset);
- hdr = readl(register_block);
-
decoder_cnt = cxl_hdm_decoder_count(hdr);
length = 0x20 * decoder_cnt + 0x10;
-
- map->hdm_decoder.valid = true;
- map->hdm_decoder.offset = CXL_CM_OFFSET + offset;
- map->hdm_decoder.size = length;
+ rmap = &map->hdm_decoder;
+ break;
+ }
+ case CXL_CM_CAP_CAP_ID_RAS:
+ dev_dbg(dev, "found RAS capability (0x%x)\n",
+ offset);
+ length = CXL_RAS_CAPABILITY_LENGTH;
+ rmap = &map->ras;
break;
default:
dev_dbg(dev, "Unknown CM cap ID: %d (0x%x)\n", cap_id,
offset);
break;
}
+
+ if (!rmap)
+ continue;
+ rmap->valid = true;
+ rmap->id = cap_id;
+ rmap->offset = CXL_CM_OFFSET + offset;
+ rmap->size = length;
}
}
EXPORT_SYMBOL_NS_GPL(cxl_probe_component_regs, CXL);
@@ -117,6 +131,7 @@ void cxl_probe_device_regs(struct device *dev, void __iomem *base,
cap_count = FIELD_GET(CXLDEV_CAP_ARRAY_COUNT_MASK, cap_array);
for (cap = 1; cap <= cap_count; cap++) {
+ struct cxl_reg_map *rmap;
u32 offset, length;
u16 cap_id;
@@ -125,28 +140,22 @@ void cxl_probe_device_regs(struct device *dev, void __iomem *base,
offset = readl(base + cap * 0x10 + 0x4);
length = readl(base + cap * 0x10 + 0x8);
+ rmap = NULL;
switch (cap_id) {
case CXLDEV_CAP_CAP_ID_DEVICE_STATUS:
dev_dbg(dev, "found Status capability (0x%x)\n", offset);
-
- map->status.valid = true;
- map->status.offset = offset;
- map->status.size = length;
+ rmap = &map->status;
break;
case CXLDEV_CAP_CAP_ID_PRIMARY_MAILBOX:
dev_dbg(dev, "found Mailbox capability (0x%x)\n", offset);
- map->mbox.valid = true;
- map->mbox.offset = offset;
- map->mbox.size = length;
+ rmap = &map->mbox;
break;
case CXLDEV_CAP_CAP_ID_SECONDARY_MAILBOX:
dev_dbg(dev, "found Secondary Mailbox capability (0x%x)\n", offset);
break;
case CXLDEV_CAP_CAP_ID_MEMDEV:
dev_dbg(dev, "found Memory Device capability (0x%x)\n", offset);
- map->memdev.valid = true;
- map->memdev.offset = offset;
- map->memdev.size = length;
+ rmap = &map->memdev;
break;
default:
if (cap_id >= 0x8000)
@@ -155,6 +164,13 @@ void cxl_probe_device_regs(struct device *dev, void __iomem *base,
dev_dbg(dev, "Unknown cap ID: %#x offset: %#x\n", cap_id, offset);
break;
}
+
+ if (!rmap)
+ continue;
+ rmap->valid = true;
+ rmap->id = cap_id;
+ rmap->offset = offset;
+ rmap->size = length;
}
}
EXPORT_SYMBOL_NS_GPL(cxl_probe_device_regs, CXL);
@@ -165,6 +181,9 @@ void __iomem *devm_cxl_iomap_block(struct device *dev, resource_size_t addr,
void __iomem *ret_val;
struct resource *res;
+ if (WARN_ON_ONCE(addr == CXL_RESOURCE_NONE))
+ return NULL;
+
res = devm_request_mem_region(dev, addr, length, dev_name(dev));
if (!res) {
resource_size_t end = addr + length - 1;
@@ -180,67 +199,65 @@ void __iomem *devm_cxl_iomap_block(struct device *dev, resource_size_t addr,
return ret_val;
}
-int cxl_map_component_regs(struct pci_dev *pdev,
- struct cxl_component_regs *regs,
- struct cxl_register_map *map)
+int cxl_map_component_regs(struct device *dev, struct cxl_component_regs *regs,
+ struct cxl_register_map *map, unsigned long map_mask)
{
- struct device *dev = &pdev->dev;
- resource_size_t phys_addr;
- resource_size_t length;
-
- phys_addr = pci_resource_start(pdev, map->barno);
- phys_addr += map->block_offset;
+ struct mapinfo {
+ struct cxl_reg_map *rmap;
+ void __iomem **addr;
+ } mapinfo[] = {
+ { &map->component_map.hdm_decoder, &regs->hdm_decoder },
+ { &map->component_map.ras, &regs->ras },
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mapinfo); i++) {
+ struct mapinfo *mi = &mapinfo[i];
+ resource_size_t phys_addr;
+ resource_size_t length;
- phys_addr += map->component_map.hdm_decoder.offset;
- length = map->component_map.hdm_decoder.size;
- regs->hdm_decoder = devm_cxl_iomap_block(dev, phys_addr, length);
- if (!regs->hdm_decoder)
- return -ENOMEM;
+ if (!mi->rmap->valid)
+ continue;
+ if (!test_bit(mi->rmap->id, &map_mask))
+ continue;
+ phys_addr = map->resource + mi->rmap->offset;
+ length = mi->rmap->size;
+ *(mi->addr) = devm_cxl_iomap_block(dev, phys_addr, length);
+ if (!*(mi->addr))
+ return -ENOMEM;
+ }
return 0;
}
EXPORT_SYMBOL_NS_GPL(cxl_map_component_regs, CXL);
-int cxl_map_device_regs(struct pci_dev *pdev,
+int cxl_map_device_regs(struct device *dev,
struct cxl_device_regs *regs,
struct cxl_register_map *map)
{
- struct device *dev = &pdev->dev;
- resource_size_t phys_addr;
-
- phys_addr = pci_resource_start(pdev, map->barno);
- phys_addr += map->block_offset;
-
- if (map->device_map.status.valid) {
- resource_size_t addr;
+ resource_size_t phys_addr = map->resource;
+ struct mapinfo {
+ struct cxl_reg_map *rmap;
+ void __iomem **addr;
+ } mapinfo[] = {
+ { &map->device_map.status, &regs->status, },
+ { &map->device_map.mbox, &regs->mbox, },
+ { &map->device_map.memdev, &regs->memdev, },
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(mapinfo); i++) {
+ struct mapinfo *mi = &mapinfo[i];
resource_size_t length;
-
- addr = phys_addr + map->device_map.status.offset;
- length = map->device_map.status.size;
- regs->status = devm_cxl_iomap_block(dev, addr, length);
- if (!regs->status)
- return -ENOMEM;
- }
-
- if (map->device_map.mbox.valid) {
resource_size_t addr;
- resource_size_t length;
- addr = phys_addr + map->device_map.mbox.offset;
- length = map->device_map.mbox.size;
- regs->mbox = devm_cxl_iomap_block(dev, addr, length);
- if (!regs->mbox)
- return -ENOMEM;
- }
-
- if (map->device_map.memdev.valid) {
- resource_size_t addr;
- resource_size_t length;
+ if (!mi->rmap->valid)
+ continue;
- addr = phys_addr + map->device_map.memdev.offset;
- length = map->device_map.memdev.size;
- regs->memdev = devm_cxl_iomap_block(dev, addr, length);
- if (!regs->memdev)
+ addr = phys_addr + mi->rmap->offset;
+ length = mi->rmap->size;
+ *(mi->addr) = devm_cxl_iomap_block(dev, addr, length);
+ if (!*(mi->addr))
return -ENOMEM;
}
@@ -248,13 +265,24 @@ int cxl_map_device_regs(struct pci_dev *pdev,
}
EXPORT_SYMBOL_NS_GPL(cxl_map_device_regs, CXL);
-static void cxl_decode_regblock(u32 reg_lo, u32 reg_hi,
+static bool cxl_decode_regblock(struct pci_dev *pdev, u32 reg_lo, u32 reg_hi,
struct cxl_register_map *map)
{
- map->block_offset = ((u64)reg_hi << 32) |
- (reg_lo & CXL_DVSEC_REG_LOCATOR_BLOCK_OFF_LOW_MASK);
- map->barno = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BIR_MASK, reg_lo);
+ int bar = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BIR_MASK, reg_lo);
+ u64 offset = ((u64)reg_hi << 32) |
+ (reg_lo & CXL_DVSEC_REG_LOCATOR_BLOCK_OFF_LOW_MASK);
+
+ if (offset > pci_resource_len(pdev, bar)) {
+ dev_warn(&pdev->dev,
+ "BAR%d: %pr: too small (offset: %pa, type: %d)\n", bar,
+ &pdev->resource[bar], &offset, map->reg_type);
+ return false;
+ }
+
map->reg_type = FIELD_GET(CXL_DVSEC_REG_LOCATOR_BLOCK_ID_MASK, reg_lo);
+ map->resource = pci_resource_start(pdev, bar) + offset;
+ map->max_size = pci_resource_len(pdev, bar) - offset;
+ return true;
}
/**
@@ -274,7 +302,7 @@ int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
u32 regloc_size, regblocks;
int regloc, i;
- map->block_offset = U64_MAX;
+ map->resource = CXL_RESOURCE_NONE;
regloc = pci_find_dvsec_capability(pdev, PCI_DVSEC_VENDOR_ID_CXL,
CXL_DVSEC_REG_LOCATOR);
if (!regloc)
@@ -292,13 +320,79 @@ int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
pci_read_config_dword(pdev, regloc, &reg_lo);
pci_read_config_dword(pdev, regloc + 4, &reg_hi);
- cxl_decode_regblock(reg_lo, reg_hi, map);
+ if (!cxl_decode_regblock(pdev, reg_lo, reg_hi, map))
+ continue;
if (map->reg_type == type)
return 0;
}
- map->block_offset = U64_MAX;
+ map->resource = CXL_RESOURCE_NONE;
return -ENODEV;
}
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)
+{
+ resource_size_t component_reg_phys;
+ void __iomem *addr;
+ u32 bar0, bar1;
+ u16 cmd;
+ u32 id;
+
+ if (which == CXL_RCRB_UPSTREAM)
+ rcrb += SZ_4K;
+
+ /*
+ * RCRB's BAR[0..1] point to component block containing CXL
+ * subsystem component registers. MEMBAR extraction follows
+ * the PCI Base spec here, esp. 64 bit extraction and memory
+ * ranges alignment (6.0, 7.5.1.2.1).
+ */
+ if (!request_mem_region(rcrb, SZ_4K, "CXL RCRB"))
+ return CXL_RESOURCE_NONE;
+ addr = ioremap(rcrb, SZ_4K);
+ if (!addr) {
+ dev_err(dev, "Failed to map region %pr\n", addr);
+ release_mem_region(rcrb, SZ_4K);
+ return CXL_RESOURCE_NONE;
+ }
+
+ id = readl(addr + PCI_VENDOR_ID);
+ cmd = readw(addr + PCI_COMMAND);
+ bar0 = readl(addr + PCI_BASE_ADDRESS_0);
+ bar1 = readl(addr + PCI_BASE_ADDRESS_1);
+ iounmap(addr);
+ release_mem_region(rcrb, SZ_4K);
+
+ /*
+ * Sanity check, see CXL 3.0 Figure 9-8 CXL Device that Does Not
+ * Remap Upstream Port and Component Registers
+ */
+ if (id == U32_MAX) {
+ if (which == CXL_RCRB_DOWNSTREAM)
+ dev_err(dev, "Failed to access Downstream Port RCRB\n");
+ return CXL_RESOURCE_NONE;
+ }
+ if (!(cmd & PCI_COMMAND_MEMORY))
+ return CXL_RESOURCE_NONE;
+ /* The RCRB is a Memory Window, and the MEM_TYPE_1M bit is obsolete */
+ if (bar0 & (PCI_BASE_ADDRESS_MEM_TYPE_1M | PCI_BASE_ADDRESS_SPACE_IO))
+ return CXL_RESOURCE_NONE;
+
+ component_reg_phys = bar0 & PCI_BASE_ADDRESS_MEM_MASK;
+ if (bar0 & PCI_BASE_ADDRESS_MEM_TYPE_64)
+ component_reg_phys |= ((u64)bar1) << 32;
+
+ if (!component_reg_phys)
+ return CXL_RESOURCE_NONE;
+
+ /* MEMBAR is block size (64k) aligned. */
+ if (!IS_ALIGNED(component_reg_phys, CXL_COMPONENT_REG_BLOCK_SIZE))
+ return CXL_RESOURCE_NONE;
+
+ return component_reg_phys;
+}
+EXPORT_SYMBOL_NS_GPL(cxl_rcrb_to_component, CXL);
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index ac75554b5d76..1b1cf459ac77 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -33,6 +33,7 @@
#define CXL_CM_CAP_HDR_ARRAY_SIZE_MASK GENMASK(31, 24)
#define CXL_CM_CAP_PTR_MASK GENMASK(31, 20)
+#define CXL_CM_CAP_CAP_ID_RAS 0x2
#define CXL_CM_CAP_CAP_ID_HDM 0x5
#define CXL_CM_CAP_CAP_HDM_VERSION 1
@@ -61,6 +62,10 @@
#define CXL_HDM_DECODER0_SKIP_LOW(i) CXL_HDM_DECODER0_TL_LOW(i)
#define CXL_HDM_DECODER0_SKIP_HIGH(i) CXL_HDM_DECODER0_TL_HIGH(i)
+/* HDM decoder control register constants CXL 3.0 8.2.5.19.7 */
+#define CXL_DECODER_MIN_GRANULARITY 256
+#define CXL_DECODER_MAX_ENCODED_IG 6
+
static inline int cxl_hdm_decoder_count(u32 cap_hdr)
{
int val = FIELD_GET(CXL_HDM_DECODER_COUNT_MASK, cap_hdr);
@@ -69,23 +74,23 @@ static inline int cxl_hdm_decoder_count(u32 cap_hdr)
}
/* Encode defined in CXL 2.0 8.2.5.12.7 HDM Decoder Control Register */
-static inline int cxl_to_granularity(u16 ig, unsigned int *val)
+static inline int eig_to_granularity(u16 eig, unsigned int *granularity)
{
- if (ig > 6)
+ if (eig > CXL_DECODER_MAX_ENCODED_IG)
return -EINVAL;
- *val = 256 << ig;
+ *granularity = CXL_DECODER_MIN_GRANULARITY << eig;
return 0;
}
/* Encode defined in CXL ECN "3, 6, 12 and 16-way memory Interleaving" */
-static inline int cxl_to_ways(u8 eniw, unsigned int *val)
+static inline int eiw_to_ways(u8 eiw, unsigned int *ways)
{
- switch (eniw) {
+ switch (eiw) {
case 0 ... 4:
- *val = 1 << eniw;
+ *ways = 1 << eiw;
break;
case 8 ... 10:
- *val = 3 << (eniw - 8);
+ *ways = 3 << (eiw - 8);
break;
default:
return -EINVAL;
@@ -94,20 +99,21 @@ static inline int cxl_to_ways(u8 eniw, unsigned int *val)
return 0;
}
-static inline int granularity_to_cxl(int g, u16 *ig)
+static inline int granularity_to_eig(int granularity, u16 *eig)
{
- if (g > SZ_16K || g < 256 || !is_power_of_2(g))
+ if (granularity > SZ_16K || granularity < CXL_DECODER_MIN_GRANULARITY ||
+ !is_power_of_2(granularity))
return -EINVAL;
- *ig = ilog2(g) - 8;
+ *eig = ilog2(granularity) - 8;
return 0;
}
-static inline int ways_to_cxl(unsigned int ways, u8 *iw)
+static inline int ways_to_eiw(unsigned int ways, u8 *eiw)
{
if (ways > 16)
return -EINVAL;
if (is_power_of_2(ways)) {
- *iw = ilog2(ways);
+ *eiw = ilog2(ways);
return 0;
}
if (ways % 3)
@@ -115,10 +121,26 @@ static inline int ways_to_cxl(unsigned int ways, u8 *iw)
ways /= 3;
if (!is_power_of_2(ways))
return -EINVAL;
- *iw = ilog2(ways) + 8;
+ *eiw = ilog2(ways) + 8;
return 0;
}
+/* RAS Registers CXL 2.0 8.2.5.9 CXL RAS Capability Structure */
+#define CXL_RAS_UNCORRECTABLE_STATUS_OFFSET 0x0
+#define CXL_RAS_UNCORRECTABLE_STATUS_MASK (GENMASK(16, 14) | GENMASK(11, 0))
+#define CXL_RAS_UNCORRECTABLE_MASK_OFFSET 0x4
+#define CXL_RAS_UNCORRECTABLE_MASK_MASK (GENMASK(16, 14) | GENMASK(11, 0))
+#define CXL_RAS_UNCORRECTABLE_SEVERITY_OFFSET 0x8
+#define CXL_RAS_UNCORRECTABLE_SEVERITY_MASK (GENMASK(16, 14) | GENMASK(11, 0))
+#define CXL_RAS_CORRECTABLE_STATUS_OFFSET 0xC
+#define CXL_RAS_CORRECTABLE_STATUS_MASK GENMASK(6, 0)
+#define CXL_RAS_CORRECTABLE_MASK_OFFSET 0x10
+#define CXL_RAS_CORRECTABLE_MASK_MASK GENMASK(6, 0)
+#define CXL_RAS_CAP_CONTROL_OFFSET 0x14
+#define CXL_RAS_CAP_CONTROL_FE_MASK GENMASK(5, 0)
+#define CXL_RAS_HEADER_LOG_OFFSET 0x18
+#define CXL_RAS_CAPABILITY_LENGTH 0x58
+
/* CXL 2.0 8.2.8.1 Device Capabilities Array Register */
#define CXLDEV_CAP_ARRAY_OFFSET 0x0
#define CXLDEV_CAP_ARRAY_CAP_ID 0
@@ -153,9 +175,11 @@ struct cxl_regs {
/*
* Common set of CXL Component register block base pointers
* @hdm_decoder: CXL 2.0 8.2.5.12 CXL HDM Decoder Capability Structure
+ * @ras: CXL 2.0 8.2.5.9 CXL RAS Capability Structure
*/
struct_group_tagged(cxl_component_regs, component,
void __iomem *hdm_decoder;
+ void __iomem *ras;
);
/*
* Common set of CXL Device register block base pointers
@@ -170,12 +194,14 @@ struct cxl_regs {
struct cxl_reg_map {
bool valid;
+ int id;
unsigned long offset;
unsigned long size;
};
struct cxl_component_reg_map {
struct cxl_reg_map hdm_decoder;
+ struct cxl_reg_map ras;
};
struct cxl_device_reg_map {
@@ -187,17 +213,17 @@ struct cxl_device_reg_map {
/**
* struct cxl_register_map - DVSEC harvested register block mapping parameters
* @base: virtual base of the register-block-BAR + @block_offset
- * @block_offset: offset to start of register block in @barno
+ * @resource: physical resource base of the register block
+ * @max_size: maximum mapping size to perform register search
* @reg_type: see enum cxl_regloc_type
- * @barno: PCI BAR number containing the register block
* @component_map: cxl_reg_map for component registers
* @device_map: cxl_reg_maps for device registers
*/
struct cxl_register_map {
void __iomem *base;
- u64 block_offset;
+ resource_size_t resource;
+ resource_size_t max_size;
u8 reg_type;
- u8 barno;
union {
struct cxl_component_reg_map component_map;
struct cxl_device_reg_map device_map;
@@ -208,18 +234,23 @@ 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 pci_dev *pdev,
- struct cxl_component_regs *regs,
- struct cxl_register_map *map);
-int cxl_map_device_regs(struct pci_dev *pdev,
- struct cxl_device_regs *regs,
+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_device_regs(struct device *dev, struct cxl_device_regs *regs,
struct cxl_register_map *map);
enum cxl_regloc_type;
int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
struct cxl_register_map *map);
-void __iomem *devm_cxl_iomap_block(struct device *dev, resource_size_t addr,
- resource_size_t length);
+
+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);
#define CXL_RESOURCE_NONE ((resource_size_t) -1)
#define CXL_TARGET_STRLEN 20
@@ -248,7 +279,6 @@ enum cxl_decoder_type {
*/
#define CXL_DECODER_MAX_INTERLEAVE 16
-#define CXL_DECODER_MIN_GRANULARITY 256
/**
* struct cxl_decoder - Common CXL HDM Decoder Attributes
@@ -324,18 +354,23 @@ struct cxl_switch_decoder {
struct cxl_dport *target[];
};
+struct cxl_root_decoder;
+typedef struct cxl_dport *(*cxl_calc_hb_fn)(struct cxl_root_decoder *cxlrd,
+ int pos);
/**
* struct cxl_root_decoder - Static platform CXL address decoder
* @res: host / parent resource for region allocations
* @region_id: region id for next region provisioning event
* @calc_hb: which host bridge covers the n'th position by granularity
+ * @platform_data: platform specific configuration data
* @cxlsd: base cxl switch decoder
*/
struct cxl_root_decoder {
struct resource *res;
atomic_t region_id;
- struct cxl_dport *(*calc_hb)(struct cxl_root_decoder *cxlrd, int pos);
+ cxl_calc_hb_fn calc_hb;
+ void *platform_data;
struct cxl_switch_decoder cxlsd;
};
@@ -379,12 +414,21 @@ struct cxl_region_params {
int nr_targets;
};
+/*
+ * 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
+
/**
* struct cxl_region - CXL region
* @dev: This region's device
* @id: This region's id. Id is globally unique across all regions
* @mode: Endpoint decoder allocation / access mode
* @type: Endpoint decoder target type
+ * @cxl_nvb: nvdimm bridge for coordinating @cxlr_pmem setup / shutdown
+ * @cxlr_pmem: (for pmem regions) cached copy of the nvdimm bridge
+ * @flags: Region state flags
* @params: active + config params for the region
*/
struct cxl_region {
@@ -392,38 +436,26 @@ struct cxl_region {
int id;
enum cxl_decoder_mode mode;
enum cxl_decoder_type type;
+ struct cxl_nvdimm_bridge *cxl_nvb;
+ struct cxl_pmem_region *cxlr_pmem;
+ unsigned long flags;
struct cxl_region_params params;
};
-/**
- * enum cxl_nvdimm_brige_state - state machine for managing bus rescans
- * @CXL_NVB_NEW: Set at bridge create and after cxl_pmem_wq is destroyed
- * @CXL_NVB_DEAD: Set at brige unregistration to preclude async probing
- * @CXL_NVB_ONLINE: Target state after successful ->probe()
- * @CXL_NVB_OFFLINE: Target state after ->remove() or failed ->probe()
- */
-enum cxl_nvdimm_brige_state {
- CXL_NVB_NEW,
- CXL_NVB_DEAD,
- CXL_NVB_ONLINE,
- CXL_NVB_OFFLINE,
-};
-
struct cxl_nvdimm_bridge {
int id;
struct device dev;
struct cxl_port *port;
struct nvdimm_bus *nvdimm_bus;
struct nvdimm_bus_descriptor nd_desc;
- struct work_struct state_work;
- enum cxl_nvdimm_brige_state state;
};
+#define CXL_DEV_ID_LEN 19
+
struct cxl_nvdimm {
struct device dev;
struct cxl_memdev *cxlmd;
- struct cxl_nvdimm_bridge *bridge;
- struct xarray pmem_regions;
+ u8 dev_id[CXL_DEV_ID_LEN]; /* for nvdimm, string of 'serial' */
};
struct cxl_pmem_region_mapping {
@@ -438,7 +470,6 @@ struct cxl_pmem_region {
struct device dev;
struct cxl_region *cxlr;
struct nd_region *nd_region;
- struct cxl_nvdimm_bridge *bridge;
struct range hpa_range;
int nr_mappings;
struct cxl_pmem_region_mapping mapping[];
@@ -500,12 +531,16 @@ cxl_find_dport_by_dev(struct cxl_port *port, const struct device *dport_dev)
* @dport: PCI bridge or firmware device representing the downstream link
* @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
+ * @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;
int port_id;
resource_size_t component_reg_phys;
+ resource_size_t rcrb;
+ bool rch;
struct cxl_port *port;
};
@@ -562,11 +597,10 @@ 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,
resource_size_t component_reg_phys,
struct cxl_dport *parent_dport);
-int devm_cxl_add_endpoint(struct cxl_memdev *cxlmd,
- struct cxl_dport *parent_dport);
struct cxl_port *find_cxl_root(struct device *dev);
int devm_cxl_enumerate_ports(struct cxl_memdev *cxlmd);
-int cxl_bus_rescan(void);
+void cxl_bus_rescan(void);
+void cxl_bus_drain(void);
struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd,
struct cxl_dport **dport);
bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd);
@@ -574,6 +608,10 @@ bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd);
struct cxl_dport *devm_cxl_add_dport(struct cxl_port *port,
struct device *dport, int port_id,
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);
struct cxl_root_decoder *to_cxl_root_decoder(struct device *dev);
@@ -581,7 +619,9 @@ struct cxl_endpoint_decoder *to_cxl_endpoint_decoder(struct device *dev);
bool is_root_decoder(struct device *dev);
bool is_endpoint_decoder(struct device *dev);
struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
- unsigned int nr_targets);
+ unsigned int nr_targets,
+ cxl_calc_hb_fn calc_hb);
+struct cxl_dport *cxl_hb_modulo(struct cxl_root_decoder *cxlrd, int pos);
struct cxl_switch_decoder *cxl_switch_decoder_alloc(struct cxl_port *port,
unsigned int nr_targets);
int cxl_decoder_add(struct cxl_decoder *cxld, int *target_map);
@@ -637,7 +677,7 @@ struct cxl_nvdimm_bridge *devm_cxl_add_nvdimm_bridge(struct device *host,
struct cxl_nvdimm *to_cxl_nvdimm(struct device *dev);
bool is_cxl_nvdimm(struct device *dev);
bool is_cxl_nvdimm_bridge(struct device *dev);
-int devm_cxl_add_nvdimm(struct device *host, struct cxl_memdev *cxlmd);
+int devm_cxl_add_nvdimm(struct cxl_memdev *cxlmd);
struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct device *dev);
#ifdef CONFIG_CXL_REGION
diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h
index 88e3a8e54b6a..ab138004f644 100644
--- a/drivers/cxl/cxlmem.h
+++ b/drivers/cxl/cxlmem.h
@@ -35,6 +35,8 @@
* @cdev: char dev core object for ioctl operations
* @cxlds: The device state backing this device
* @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
* @id: id number of this memdev instance.
*/
struct cxl_memdev {
@@ -42,6 +44,8 @@ struct cxl_memdev {
struct cdev cdev;
struct cxl_dev_state *cxlds;
struct work_struct detach_work;
+ struct cxl_nvdimm_bridge *cxl_nvb;
+ struct cxl_nvdimm *cxl_nvd;
int id;
};
@@ -76,6 +80,15 @@ static inline bool is_cxl_endpoint(struct cxl_port *port)
struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds);
+static inline struct cxl_ep *cxl_ep_load(struct cxl_port *port,
+ struct cxl_memdev *cxlmd)
+{
+ if (!port)
+ return NULL;
+
+ return xa_load(&port->endpoints, (unsigned long)&cxlmd->dev);
+}
+
/**
* struct cxl_mbox_cmd - A command to be submitted to hardware.
* @opcode: (input) The command set and command submitted to hardware.
@@ -88,6 +101,7 @@ struct cxl_memdev *devm_cxl_add_memdev(struct cxl_dev_state *cxlds);
* outputs commands this is always expected to be deterministic. For
* variable sized output commands, it tells the exact number of bytes
* written.
+ * @min_out: (input) internal command output payload size validation
* @return_code: (output) Error code returned from hardware.
*
* This is the primary mechanism used to send commands to the hardware.
@@ -102,6 +116,7 @@ struct cxl_mbox_cmd {
void *payload_out;
size_t size_in;
size_t size_out;
+ size_t min_out;
u16 return_code;
};
@@ -186,8 +201,10 @@ struct cxl_endpoint_dvsec_info {
* Currently only memory devices are represented.
*
* @dev: The device associated with this CXL state
+ * @cxlmd: The device representing the CXL.mem capabilities of @dev
* @regs: Parsed register blocks
* @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)
* @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
@@ -218,10 +235,12 @@ struct cxl_endpoint_dvsec_info {
*/
struct cxl_dev_state {
struct device *dev;
+ struct cxl_memdev *cxlmd;
struct cxl_regs regs;
int cxl_dvsec;
+ bool rcd;
size_t payload_size;
size_t lsa_size;
struct mutex mbox_mutex; /* Protects device mailbox and firmware */
@@ -273,6 +292,12 @@ 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_GET_SECURITY_STATE = 0x4500,
+ CXL_MBOX_OP_SET_PASSPHRASE = 0x4501,
+ CXL_MBOX_OP_DISABLE_PASSPHRASE = 0x4502,
+ CXL_MBOX_OP_UNLOCK = 0x4503,
+ CXL_MBOX_OP_FREEZE_SECURITY = 0x4504,
+ CXL_MBOX_OP_PASSPHRASE_SECURE_ERASE = 0x4505,
CXL_MBOX_OP_MAX = 0x10000
};
@@ -372,8 +397,43 @@ struct cxl_mem_command {
#define CXL_CMD_FLAG_FORCE_ENABLE BIT(0)
};
-int cxl_mbox_send_cmd(struct cxl_dev_state *cxlds, u16 opcode, void *in,
- size_t in_size, void *out, size_t out_size);
+#define CXL_PMEM_SEC_STATE_USER_PASS_SET 0x01
+#define CXL_PMEM_SEC_STATE_MASTER_PASS_SET 0x02
+#define CXL_PMEM_SEC_STATE_LOCKED 0x04
+#define CXL_PMEM_SEC_STATE_FROZEN 0x08
+#define CXL_PMEM_SEC_STATE_USER_PLIMIT 0x10
+#define CXL_PMEM_SEC_STATE_MASTER_PLIMIT 0x20
+
+/* set passphrase input payload */
+struct cxl_set_pass {
+ u8 type;
+ u8 reserved[31];
+ /* CXL field using NVDIMM define, same length */
+ u8 old_pass[NVDIMM_PASSPHRASE_LEN];
+ u8 new_pass[NVDIMM_PASSPHRASE_LEN];
+} __packed;
+
+/* disable passphrase input payload */
+struct cxl_disable_pass {
+ u8 type;
+ u8 reserved[31];
+ u8 pass[NVDIMM_PASSPHRASE_LEN];
+} __packed;
+
+/* passphrase secure erase payload */
+struct cxl_pass_erase {
+ u8 type;
+ u8 reserved[31];
+ u8 pass[NVDIMM_PASSPHRASE_LEN];
+} __packed;
+
+enum {
+ CXL_PMEM_SEC_PASS_MASTER = 0,
+ CXL_PMEM_SEC_PASS_USER,
+};
+
+int cxl_internal_send_cmd(struct cxl_dev_state *cxlds,
+ struct cxl_mbox_cmd *cmd);
int cxl_dev_state_identify(struct cxl_dev_state *cxlds);
int cxl_await_media_ready(struct cxl_dev_state *cxlds);
int cxl_enumerate_cmds(struct cxl_dev_state *cxlds);
diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h
index eec597dbe763..920909791bb9 100644
--- a/drivers/cxl/cxlpci.h
+++ b/drivers/cxl/cxlpci.h
@@ -62,15 +62,6 @@ enum cxl_regloc_type {
CXL_REGLOC_RBI_TYPES
};
-static inline resource_size_t cxl_regmap_to_base(struct pci_dev *pdev,
- struct cxl_register_map *map)
-{
- if (map->block_offset == U64_MAX)
- return CXL_RESOURCE_NONE;
-
- return pci_resource_start(pdev, map->barno) + map->block_offset;
-}
-
int devm_cxl_port_enumerate_dports(struct cxl_port *port);
struct cxl_dev_state;
int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm);
diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index 64ccf053d32c..39c4b54f0715 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -45,9 +45,60 @@ static int cxl_mem_dpa_show(struct seq_file *file, void *data)
return 0;
}
+static int devm_cxl_add_endpoint(struct device *host, struct cxl_memdev *cxlmd,
+ struct cxl_dport *parent_dport)
+{
+ 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;
+
+ /*
+ * Now that the path to the root is established record all the
+ * intervening ports in the chain.
+ */
+ for (iter = parent_port, down = NULL; !is_cxl_root(iter);
+ down = iter, iter = to_cxl_port(iter->dev.parent)) {
+ struct cxl_ep *ep;
+
+ ep = cxl_ep_load(iter, 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,
+ parent_dport);
+ if (IS_ERR(endpoint))
+ return PTR_ERR(endpoint);
+
+ rc = cxl_endpoint_autoremove(cxlmd, endpoint);
+ if (rc)
+ return rc;
+
+ if (!endpoint->dev.driver) {
+ dev_err(&cxlmd->dev, "%s failed probe\n",
+ dev_name(&endpoint->dev));
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
static int cxl_mem_probe(struct device *dev)
{
struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
+ struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ struct device *endpoint_parent;
struct cxl_port *parent_port;
struct cxl_dport *dport;
struct dentry *dentry;
@@ -80,21 +131,34 @@ static int cxl_mem_probe(struct device *dev)
return -ENXIO;
}
- device_lock(&parent_port->dev);
- if (!parent_port->dev.driver) {
+ if (dport->rch)
+ endpoint_parent = parent_port->uport;
+ else
+ endpoint_parent = &parent_port->dev;
+
+ device_lock(endpoint_parent);
+ if (!endpoint_parent->driver) {
dev_err(dev, "CXL port topology %s not enabled\n",
- dev_name(&parent_port->dev));
+ dev_name(endpoint_parent));
rc = -ENXIO;
goto unlock;
}
- rc = devm_cxl_add_endpoint(cxlmd, dport);
+ rc = devm_cxl_add_endpoint(endpoint_parent, cxlmd, dport);
unlock:
- device_unlock(&parent_port->dev);
+ device_unlock(endpoint_parent);
put_device(&parent_port->dev);
if (rc)
return rc;
+ if (resource_size(&cxlds->pmem_res) && IS_ENABLED(CONFIG_CXL_PMEM)) {
+ rc = devm_cxl_add_nvdimm(cxlmd);
+ if (rc == -ENODEV)
+ dev_info(dev, "PMEM disabled by platform\n");
+ else
+ return rc;
+ }
+
/*
* The kernel may be operating out of CXL memory on this device,
* there is no spec defined way to determine whether this device
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
index faeb5d9d7a7a..33083a522fd1 100644
--- a/drivers/cxl/pci.c
+++ b/drivers/cxl/pci.c
@@ -9,10 +9,13 @@
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/pci-doe.h>
+#include <linux/aer.h>
#include <linux/io.h>
#include "cxlmem.h"
#include "cxlpci.h"
#include "cxl.h"
+#define CREATE_TRACE_POINTS
+#include <trace/events/cxl.h>
/**
* DOC: cxl pci
@@ -276,35 +279,22 @@ static int cxl_pci_setup_mailbox(struct cxl_dev_state *cxlds)
static int cxl_map_regblock(struct pci_dev *pdev, struct cxl_register_map *map)
{
- void __iomem *addr;
- int bar = map->barno;
struct device *dev = &pdev->dev;
- resource_size_t offset = map->block_offset;
-
- /* Basic sanity check that BAR is big enough */
- if (pci_resource_len(pdev, bar) < offset) {
- dev_err(dev, "BAR%d: %pr: too small (offset: %pa)\n", bar,
- &pdev->resource[bar], &offset);
- return -ENXIO;
- }
- addr = pci_iomap(pdev, bar, 0);
- if (!addr) {
+ 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 bar %u @ %pa\n",
- bar, &offset);
-
- map->base = addr + map->block_offset;
+ dev_dbg(dev, "Mapped CXL Memory Device resource %pa\n", &map->resource);
return 0;
}
static void cxl_unmap_regblock(struct pci_dev *pdev,
struct cxl_register_map *map)
{
- pci_iounmap(pdev, map->base - map->block_offset);
+ iounmap(map->base);
map->base = NULL;
}
@@ -324,6 +314,9 @@ static int cxl_probe_regs(struct pci_dev *pdev, struct cxl_register_map *map)
return -ENXIO;
}
+ 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:
@@ -347,27 +340,6 @@ static int cxl_probe_regs(struct pci_dev *pdev, struct cxl_register_map *map)
return 0;
}
-static int cxl_map_regs(struct cxl_dev_state *cxlds, struct cxl_register_map *map)
-{
- struct device *dev = cxlds->dev;
- struct pci_dev *pdev = to_pci_dev(dev);
-
- switch (map->reg_type) {
- case CXL_REGLOC_RBI_COMPONENT:
- cxl_map_component_regs(pdev, &cxlds->regs.component, map);
- dev_dbg(dev, "Mapping component registers...\n");
- break;
- case CXL_REGLOC_RBI_MEMDEV:
- cxl_map_device_regs(pdev, &cxlds->regs.device_regs, map);
- dev_dbg(dev, "Probing device registers...\n");
- break;
- default:
- break;
- }
-
- return 0;
-}
-
static int cxl_setup_regs(struct pci_dev *pdev, enum cxl_regloc_type type,
struct cxl_register_map *map)
{
@@ -418,6 +390,11 @@ static void devm_cxl_pci_create_doe(struct cxl_dev_state *cxlds)
continue;
}
+ if (!pci_request_config_region_exclusive(pdev, off,
+ PCI_DOE_CAP_SIZEOF,
+ dev_name(dev)))
+ pci_err(pdev, "Failed to exclude DOE registers\n");
+
if (xa_insert(&cxlds->doe_mbs, off, doe_mb, GFP_KERNEL)) {
dev_err(dev, "xa_insert failed to insert MB @ %x\n",
off);
@@ -428,6 +405,20 @@ static void devm_cxl_pci_create_doe(struct cxl_dev_state *cxlds)
}
}
+/*
+ * 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;
+}
+
+static void disable_aer(void *pdev)
+{
+ pci_disable_pcie_error_reporting(pdev);
+}
+
static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct cxl_register_map map;
@@ -449,7 +440,9 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
cxlds = cxl_dev_state_create(&pdev->dev);
if (IS_ERR(cxlds))
return PTR_ERR(cxlds);
+ pci_set_drvdata(pdev, cxlds);
+ cxlds->rcd = is_cxl_restricted(pdev);
cxlds->serial = pci_get_dsn(pdev);
cxlds->cxl_dvsec = pci_find_dvsec_capability(
pdev, PCI_DVSEC_VENDOR_ID_CXL, CXL_DVSEC_PCIE_DEVICE);
@@ -461,7 +454,7 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (rc)
return rc;
- rc = cxl_map_regs(cxlds, &map);
+ rc = cxl_map_device_regs(&pdev->dev, &cxlds->regs.device_regs, &map);
if (rc)
return rc;
@@ -474,10 +467,15 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (rc)
dev_warn(&pdev->dev, "No component registers (%d)\n", rc);
- cxlds->component_reg_phys = cxl_regmap_to_base(pdev, &map);
+ cxlds->component_reg_phys = map.resource;
devm_cxl_pci_create_doe(cxlds);
+ rc = cxl_map_component_regs(&pdev->dev, &cxlds->regs.component,
+ &map, BIT(CXL_CM_CAP_CAP_ID_RAS));
+ if (rc)
+ dev_dbg(&pdev->dev, "Failed to map RAS capability.\n");
+
rc = cxl_pci_setup_mailbox(cxlds);
if (rc)
return rc;
@@ -498,8 +496,13 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (IS_ERR(cxlmd))
return PTR_ERR(cxlmd);
- if (resource_size(&cxlds->pmem_res) && IS_ENABLED(CONFIG_CXL_PMEM))
- rc = devm_cxl_add_nvdimm(&pdev->dev, cxlmd);
+ if (cxlds->regs.ras) {
+ pci_enable_pcie_error_reporting(pdev);
+ rc = devm_add_action_or_reset(&pdev->dev, disable_aer, pdev);
+ if (rc)
+ return rc;
+ }
+ pci_save_state(pdev);
return rc;
}
@@ -511,10 +514,151 @@ static const struct pci_device_id cxl_mem_pci_tbl[] = {
};
MODULE_DEVICE_TABLE(pci, cxl_mem_pci_tbl);
+/* CXL spec rev3.0 8.2.4.16.1 */
+static void header_log_copy(struct cxl_dev_state *cxlds, u32 *log)
+{
+ void __iomem *addr;
+ u32 *log_addr;
+ int i, log_u32_size = CXL_HEADERLOG_SIZE / sizeof(u32);
+
+ addr = cxlds->regs.ras + CXL_RAS_HEADER_LOG_OFFSET;
+ log_addr = log;
+
+ for (i = 0; i < log_u32_size; i++) {
+ *log_addr = readl(addr);
+ log_addr++;
+ addr += sizeof(u32);
+ }
+}
+
+/*
+ * Log the state of the RAS status registers and prepare them to log the
+ * next error status. Return 1 if reset needed.
+ */
+static bool cxl_report_and_clear(struct cxl_dev_state *cxlds)
+{
+ struct cxl_memdev *cxlmd = cxlds->cxlmd;
+ struct device *dev = &cxlmd->dev;
+ u32 hl[CXL_HEADERLOG_SIZE_U32];
+ void __iomem *addr;
+ u32 status;
+ u32 fe;
+
+ if (!cxlds->regs.ras)
+ return false;
+
+ addr = cxlds->regs.ras + CXL_RAS_UNCORRECTABLE_STATUS_OFFSET;
+ status = readl(addr);
+ if (!(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK))
+ return false;
+
+ /* If multiple errors, log header points to first error from ctrl reg */
+ if (hweight32(status) > 1) {
+ addr = cxlds->regs.ras + CXL_RAS_CAP_CONTROL_OFFSET;
+ fe = BIT(FIELD_GET(CXL_RAS_CAP_CONTROL_FE_MASK, readl(addr)));
+ } else {
+ fe = status;
+ }
+
+ header_log_copy(cxlds, hl);
+ trace_cxl_aer_uncorrectable_error(dev, status, fe, hl);
+ writel(status & CXL_RAS_UNCORRECTABLE_STATUS_MASK, addr);
+
+ return true;
+}
+
+static pci_ers_result_t cxl_error_detected(struct pci_dev *pdev,
+ pci_channel_state_t state)
+{
+ struct cxl_dev_state *cxlds = pci_get_drvdata(pdev);
+ struct cxl_memdev *cxlmd = cxlds->cxlmd;
+ struct device *dev = &cxlmd->dev;
+ bool ue;
+
+ /*
+ * A frozen channel indicates an impending reset which is fatal to
+ * CXL.mem operation, and will likely crash the system. On the off
+ * chance the situation is recoverable dump the status of the RAS
+ * capability registers and bounce the active state of the memdev.
+ */
+ ue = cxl_report_and_clear(cxlds);
+
+ switch (state) {
+ case pci_channel_io_normal:
+ if (ue) {
+ device_release_driver(dev);
+ return PCI_ERS_RESULT_NEED_RESET;
+ }
+ return PCI_ERS_RESULT_CAN_RECOVER;
+ case pci_channel_io_frozen:
+ dev_warn(&pdev->dev,
+ "%s: frozen state error detected, disable CXL.mem\n",
+ dev_name(dev));
+ device_release_driver(dev);
+ return PCI_ERS_RESULT_NEED_RESET;
+ case pci_channel_io_perm_failure:
+ dev_warn(&pdev->dev,
+ "failure state error detected, request disconnect\n");
+ return PCI_ERS_RESULT_DISCONNECT;
+ }
+ return PCI_ERS_RESULT_NEED_RESET;
+}
+
+static pci_ers_result_t cxl_slot_reset(struct pci_dev *pdev)
+{
+ struct cxl_dev_state *cxlds = pci_get_drvdata(pdev);
+ struct cxl_memdev *cxlmd = cxlds->cxlmd;
+ struct device *dev = &cxlmd->dev;
+
+ dev_info(&pdev->dev, "%s: restart CXL.mem after slot reset\n",
+ dev_name(dev));
+ pci_restore_state(pdev);
+ if (device_attach(dev) <= 0)
+ return PCI_ERS_RESULT_DISCONNECT;
+ return PCI_ERS_RESULT_RECOVERED;
+}
+
+static void cxl_error_resume(struct pci_dev *pdev)
+{
+ struct cxl_dev_state *cxlds = pci_get_drvdata(pdev);
+ struct cxl_memdev *cxlmd = cxlds->cxlmd;
+ struct device *dev = &cxlmd->dev;
+
+ dev_info(&pdev->dev, "%s: error resume %s\n", dev_name(dev),
+ dev->driver ? "successful" : "failed");
+}
+
+static void cxl_cor_error_detected(struct pci_dev *pdev)
+{
+ struct cxl_dev_state *cxlds = pci_get_drvdata(pdev);
+ struct cxl_memdev *cxlmd = cxlds->cxlmd;
+ struct device *dev = &cxlmd->dev;
+ void __iomem *addr;
+ u32 status;
+
+ if (!cxlds->regs.ras)
+ return;
+
+ addr = cxlds->regs.ras + CXL_RAS_CORRECTABLE_STATUS_OFFSET;
+ status = readl(addr);
+ if (status & CXL_RAS_CORRECTABLE_STATUS_MASK) {
+ writel(status & CXL_RAS_CORRECTABLE_STATUS_MASK, addr);
+ trace_cxl_aer_correctable_error(dev, status);
+ }
+}
+
+static const struct pci_error_handlers cxl_error_handlers = {
+ .error_detected = cxl_error_detected,
+ .slot_reset = cxl_slot_reset,
+ .resume = cxl_error_resume,
+ .cor_error_detected = cxl_cor_error_detected,
+};
+
static struct pci_driver cxl_pci_driver = {
.name = KBUILD_MODNAME,
.id_table = cxl_mem_pci_tbl,
.probe = cxl_pci_probe,
+ .err_handler = &cxl_error_handlers,
.driver = {
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
},
diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c
index 4c627d67281a..eedefebc4283 100644
--- a/drivers/cxl/pmem.c
+++ b/drivers/cxl/pmem.c
@@ -11,12 +11,7 @@
#include "cxlmem.h"
#include "cxl.h"
-/*
- * Ordered workqueue for cxl nvdimm device arrival and departure
- * to coordinate bus rescans when a bridge arrives and trigger remove
- * operations when the bridge is removed.
- */
-static struct workqueue_struct *cxl_pmem_wq;
+extern const struct nvdimm_security_ops *cxl_security_ops;
static __read_mostly DECLARE_BITMAP(exclusive_cmds, CXL_MEM_COMMAND_ID_MAX);
@@ -27,78 +22,81 @@ static void clear_exclusive(void *cxlds)
static void unregister_nvdimm(void *nvdimm)
{
- struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
- struct cxl_nvdimm_bridge *cxl_nvb = cxl_nvd->bridge;
- struct cxl_pmem_region *cxlr_pmem;
- unsigned long index;
+ nvdimm_delete(nvdimm);
+}
- device_lock(&cxl_nvb->dev);
- dev_set_drvdata(&cxl_nvd->dev, NULL);
- xa_for_each(&cxl_nvd->pmem_regions, index, cxlr_pmem) {
- get_device(&cxlr_pmem->dev);
- device_unlock(&cxl_nvb->dev);
+static ssize_t provider_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct nvdimm *nvdimm = to_nvdimm(dev);
+ struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
- device_release_driver(&cxlr_pmem->dev);
- put_device(&cxlr_pmem->dev);
+ return sysfs_emit(buf, "%s\n", dev_name(&cxl_nvd->dev));
+}
+static DEVICE_ATTR_RO(provider);
- device_lock(&cxl_nvb->dev);
- }
- device_unlock(&cxl_nvb->dev);
+static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct nvdimm *nvdimm = to_nvdimm(dev);
+ struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
+ struct cxl_dev_state *cxlds = cxl_nvd->cxlmd->cxlds;
- nvdimm_delete(nvdimm);
- cxl_nvd->bridge = NULL;
+ return sysfs_emit(buf, "%lld\n", cxlds->serial);
}
+static DEVICE_ATTR_RO(id);
+
+static struct attribute *cxl_dimm_attributes[] = {
+ &dev_attr_id.attr,
+ &dev_attr_provider.attr,
+ NULL
+};
+
+static const struct attribute_group cxl_dimm_attribute_group = {
+ .name = "cxl",
+ .attrs = cxl_dimm_attributes,
+};
+
+static const struct attribute_group *cxl_dimm_attribute_groups[] = {
+ &cxl_dimm_attribute_group,
+ NULL
+};
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;
unsigned long flags = 0, cmd_mask = 0;
struct cxl_dev_state *cxlds = cxlmd->cxlds;
- struct cxl_nvdimm_bridge *cxl_nvb;
struct nvdimm *nvdimm;
int rc;
- cxl_nvb = cxl_find_nvdimm_bridge(dev);
- if (!cxl_nvb)
- return -ENXIO;
-
- device_lock(&cxl_nvb->dev);
- if (!cxl_nvb->nvdimm_bus) {
- rc = -ENXIO;
- goto out;
- }
-
set_exclusive_cxl_commands(cxlds, exclusive_cmds);
rc = devm_add_action_or_reset(dev, clear_exclusive, cxlds);
if (rc)
- goto out;
+ return rc;
set_bit(NDD_LABELING, &flags);
set_bit(ND_CMD_GET_CONFIG_SIZE, &cmd_mask);
set_bit(ND_CMD_GET_CONFIG_DATA, &cmd_mask);
set_bit(ND_CMD_SET_CONFIG_DATA, &cmd_mask);
- nvdimm = nvdimm_create(cxl_nvb->nvdimm_bus, cxl_nvd, NULL, flags,
- cmd_mask, 0, NULL);
- if (!nvdimm) {
- rc = -ENOMEM;
- goto out;
- }
+ nvdimm = __nvdimm_create(cxl_nvb->nvdimm_bus, cxl_nvd,
+ cxl_dimm_attribute_groups, flags,
+ cmd_mask, 0, NULL, cxl_nvd->dev_id,
+ cxl_security_ops, NULL);
+ if (!nvdimm)
+ return -ENOMEM;
dev_set_drvdata(dev, nvdimm);
- cxl_nvd->bridge = cxl_nvb;
- rc = devm_add_action_or_reset(dev, unregister_nvdimm, nvdimm);
-out:
- device_unlock(&cxl_nvb->dev);
- put_device(&cxl_nvb->dev);
-
- return rc;
+ return devm_add_action_or_reset(dev, unregister_nvdimm, nvdimm);
}
static struct cxl_driver cxl_nvdimm_driver = {
.name = "cxl_nvdimm",
.probe = cxl_nvdimm_probe,
.id = CXL_DEVICE_NVDIMM,
+ .drv = {
+ .suppress_bind_attrs = true,
+ },
};
static int cxl_pmem_get_config_size(struct cxl_dev_state *cxlds,
@@ -121,6 +119,7 @@ static int cxl_pmem_get_config_data(struct cxl_dev_state *cxlds,
unsigned int buf_len)
{
struct cxl_mbox_get_lsa get_lsa;
+ struct cxl_mbox_cmd mbox_cmd;
int rc;
if (sizeof(*cmd) > buf_len)
@@ -132,9 +131,15 @@ static int cxl_pmem_get_config_data(struct cxl_dev_state *cxlds,
.offset = cpu_to_le32(cmd->in_offset),
.length = cpu_to_le32(cmd->in_length),
};
+ mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_GET_LSA,
+ .payload_in = &get_lsa,
+ .size_in = sizeof(get_lsa),
+ .size_out = cmd->in_length,
+ .payload_out = cmd->out_buf,
+ };
- rc = cxl_mbox_send_cmd(cxlds, CXL_MBOX_OP_GET_LSA, &get_lsa,
- sizeof(get_lsa), cmd->out_buf, cmd->in_length);
+ rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
cmd->status = 0;
return rc;
@@ -145,6 +150,7 @@ static int cxl_pmem_set_config_data(struct cxl_dev_state *cxlds,
unsigned int buf_len)
{
struct cxl_mbox_set_lsa *set_lsa;
+ struct cxl_mbox_cmd mbox_cmd;
int rc;
if (sizeof(*cmd) > buf_len)
@@ -163,10 +169,13 @@ static int cxl_pmem_set_config_data(struct cxl_dev_state *cxlds,
.offset = cpu_to_le32(cmd->in_offset),
};
memcpy(set_lsa->data, cmd->in_buf, cmd->in_length);
+ mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_SET_LSA,
+ .payload_in = set_lsa,
+ .size_in = struct_size(set_lsa, data, cmd->in_length),
+ };
- rc = cxl_mbox_send_cmd(cxlds, CXL_MBOX_OP_SET_LSA, set_lsa,
- struct_size(set_lsa, data, cmd->in_length),
- NULL, 0);
+ rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
/*
* Set "firmware" status (4-packed bytes at the end of the input
@@ -216,204 +225,48 @@ static int cxl_pmem_ctl(struct nvdimm_bus_descriptor *nd_desc,
return cxl_pmem_nvdimm_ctl(nvdimm, cmd, buf, buf_len);
}
-static bool online_nvdimm_bus(struct cxl_nvdimm_bridge *cxl_nvb)
-{
- if (cxl_nvb->nvdimm_bus)
- return true;
- cxl_nvb->nvdimm_bus =
- nvdimm_bus_register(&cxl_nvb->dev, &cxl_nvb->nd_desc);
- return cxl_nvb->nvdimm_bus != NULL;
-}
-
-static int cxl_nvdimm_release_driver(struct device *dev, void *cxl_nvb)
-{
- struct cxl_nvdimm *cxl_nvd;
-
- if (!is_cxl_nvdimm(dev))
- return 0;
-
- cxl_nvd = to_cxl_nvdimm(dev);
- if (cxl_nvd->bridge != cxl_nvb)
- return 0;
-
- device_release_driver(dev);
- return 0;
-}
-
-static int cxl_pmem_region_release_driver(struct device *dev, void *cxl_nvb)
-{
- struct cxl_pmem_region *cxlr_pmem;
-
- if (!is_cxl_pmem_region(dev))
- return 0;
-
- cxlr_pmem = to_cxl_pmem_region(dev);
- if (cxlr_pmem->bridge != cxl_nvb)
- return 0;
-
- device_release_driver(dev);
- return 0;
-}
-
-static void offline_nvdimm_bus(struct cxl_nvdimm_bridge *cxl_nvb,
- struct nvdimm_bus *nvdimm_bus)
+static void unregister_nvdimm_bus(void *_cxl_nvb)
{
- if (!nvdimm_bus)
- return;
+ struct cxl_nvdimm_bridge *cxl_nvb = _cxl_nvb;
+ struct nvdimm_bus *nvdimm_bus = cxl_nvb->nvdimm_bus;
- /*
- * Set the state of cxl_nvdimm devices to unbound / idle before
- * nvdimm_bus_unregister() rips the nvdimm objects out from
- * underneath them.
- */
- bus_for_each_dev(&cxl_bus_type, NULL, cxl_nvb,
- cxl_pmem_region_release_driver);
- bus_for_each_dev(&cxl_bus_type, NULL, cxl_nvb,
- cxl_nvdimm_release_driver);
+ cxl_nvb->nvdimm_bus = NULL;
nvdimm_bus_unregister(nvdimm_bus);
}
-static void cxl_nvb_update_state(struct work_struct *work)
-{
- struct cxl_nvdimm_bridge *cxl_nvb =
- container_of(work, typeof(*cxl_nvb), state_work);
- struct nvdimm_bus *victim_bus = NULL;
- bool release = false, rescan = false;
-
- device_lock(&cxl_nvb->dev);
- switch (cxl_nvb->state) {
- case CXL_NVB_ONLINE:
- if (!online_nvdimm_bus(cxl_nvb)) {
- dev_err(&cxl_nvb->dev,
- "failed to establish nvdimm bus\n");
- release = true;
- } else
- rescan = true;
- break;
- case CXL_NVB_OFFLINE:
- case CXL_NVB_DEAD:
- victim_bus = cxl_nvb->nvdimm_bus;
- cxl_nvb->nvdimm_bus = NULL;
- break;
- default:
- break;
- }
- device_unlock(&cxl_nvb->dev);
-
- if (release)
- device_release_driver(&cxl_nvb->dev);
- if (rescan) {
- int rc = bus_rescan_devices(&cxl_bus_type);
-
- dev_dbg(&cxl_nvb->dev, "rescan: %d\n", rc);
- }
- offline_nvdimm_bus(cxl_nvb, victim_bus);
-
- put_device(&cxl_nvb->dev);
-}
-
-static void cxl_nvdimm_bridge_state_work(struct cxl_nvdimm_bridge *cxl_nvb)
-{
- /*
- * Take a reference that the workqueue will drop if new work
- * gets queued.
- */
- get_device(&cxl_nvb->dev);
- if (!queue_work(cxl_pmem_wq, &cxl_nvb->state_work))
- put_device(&cxl_nvb->dev);
-}
-
-static void cxl_nvdimm_bridge_remove(struct device *dev)
-{
- struct cxl_nvdimm_bridge *cxl_nvb = to_cxl_nvdimm_bridge(dev);
-
- if (cxl_nvb->state == CXL_NVB_ONLINE)
- cxl_nvb->state = CXL_NVB_OFFLINE;
- cxl_nvdimm_bridge_state_work(cxl_nvb);
-}
-
static int cxl_nvdimm_bridge_probe(struct device *dev)
{
struct cxl_nvdimm_bridge *cxl_nvb = to_cxl_nvdimm_bridge(dev);
- if (cxl_nvb->state == CXL_NVB_DEAD)
- return -ENXIO;
-
- if (cxl_nvb->state == CXL_NVB_NEW) {
- cxl_nvb->nd_desc = (struct nvdimm_bus_descriptor) {
- .provider_name = "CXL",
- .module = THIS_MODULE,
- .ndctl = cxl_pmem_ctl,
- };
+ cxl_nvb->nd_desc = (struct nvdimm_bus_descriptor) {
+ .provider_name = "CXL",
+ .module = THIS_MODULE,
+ .ndctl = cxl_pmem_ctl,
+ };
- INIT_WORK(&cxl_nvb->state_work, cxl_nvb_update_state);
- }
+ cxl_nvb->nvdimm_bus =
+ nvdimm_bus_register(&cxl_nvb->dev, &cxl_nvb->nd_desc);
- cxl_nvb->state = CXL_NVB_ONLINE;
- cxl_nvdimm_bridge_state_work(cxl_nvb);
+ if (!cxl_nvb->nvdimm_bus)
+ return -ENOMEM;
- return 0;
+ return devm_add_action_or_reset(dev, unregister_nvdimm_bus, cxl_nvb);
}
static struct cxl_driver cxl_nvdimm_bridge_driver = {
.name = "cxl_nvdimm_bridge",
.probe = cxl_nvdimm_bridge_probe,
- .remove = cxl_nvdimm_bridge_remove,
.id = CXL_DEVICE_NVDIMM_BRIDGE,
+ .drv = {
+ .suppress_bind_attrs = true,
+ },
};
-static int match_cxl_nvdimm(struct device *dev, void *data)
-{
- return is_cxl_nvdimm(dev);
-}
-
static void unregister_nvdimm_region(void *nd_region)
{
nvdimm_region_delete(nd_region);
}
-static int cxl_nvdimm_add_region(struct cxl_nvdimm *cxl_nvd,
- struct cxl_pmem_region *cxlr_pmem)
-{
- int rc;
-
- rc = xa_insert(&cxl_nvd->pmem_regions, (unsigned long)cxlr_pmem,
- cxlr_pmem, GFP_KERNEL);
- if (rc)
- return rc;
-
- get_device(&cxlr_pmem->dev);
- return 0;
-}
-
-static void cxl_nvdimm_del_region(struct cxl_nvdimm *cxl_nvd,
- struct cxl_pmem_region *cxlr_pmem)
-{
- /*
- * It is possible this is called without a corresponding
- * cxl_nvdimm_add_region for @cxlr_pmem
- */
- cxlr_pmem = xa_erase(&cxl_nvd->pmem_regions, (unsigned long)cxlr_pmem);
- if (cxlr_pmem)
- put_device(&cxlr_pmem->dev);
-}
-
-static void release_mappings(void *data)
-{
- int i;
- struct cxl_pmem_region *cxlr_pmem = data;
- struct cxl_nvdimm_bridge *cxl_nvb = cxlr_pmem->bridge;
-
- device_lock(&cxl_nvb->dev);
- for (i = 0; i < cxlr_pmem->nr_mappings; i++) {
- struct cxl_pmem_region_mapping *m = &cxlr_pmem->mapping[i];
- struct cxl_nvdimm *cxl_nvd = m->cxl_nvd;
-
- cxl_nvdimm_del_region(cxl_nvd, cxlr_pmem);
- }
- device_unlock(&cxl_nvb->dev);
-}
-
static void cxlr_pmem_remove_resource(void *res)
{
remove_resource(res);
@@ -429,8 +282,8 @@ static int cxl_pmem_region_probe(struct device *dev)
struct nd_mapping_desc mappings[CXL_DECODER_MAX_INTERLEAVE];
struct cxl_pmem_region *cxlr_pmem = to_cxl_pmem_region(dev);
struct cxl_region *cxlr = cxlr_pmem->cxlr;
+ struct cxl_nvdimm_bridge *cxl_nvb = cxlr->cxl_nvb;
struct cxl_pmem_region_info *info = NULL;
- struct cxl_nvdimm_bridge *cxl_nvb;
struct nd_interleave_set *nd_set;
struct nd_region_desc ndr_desc;
struct cxl_nvdimm *cxl_nvd;
@@ -438,28 +291,12 @@ static int cxl_pmem_region_probe(struct device *dev)
struct resource *res;
int rc, i = 0;
- cxl_nvb = cxl_find_nvdimm_bridge(&cxlr_pmem->mapping[0].cxlmd->dev);
- if (!cxl_nvb) {
- dev_dbg(dev, "bridge not found\n");
- return -ENXIO;
- }
- cxlr_pmem->bridge = cxl_nvb;
-
- device_lock(&cxl_nvb->dev);
- if (!cxl_nvb->nvdimm_bus) {
- dev_dbg(dev, "nvdimm bus not found\n");
- rc = -ENXIO;
- goto out_nvb;
- }
-
memset(&mappings, 0, sizeof(mappings));
memset(&ndr_desc, 0, sizeof(ndr_desc));
res = devm_kzalloc(dev, sizeof(*res), GFP_KERNEL);
- if (!res) {
- rc = -ENOMEM;
- goto out_nvb;
- }
+ if (!res)
+ return -ENOMEM;
res->name = "Persistent Memory";
res->start = cxlr_pmem->hpa_range.start;
@@ -469,11 +306,11 @@ static int cxl_pmem_region_probe(struct device *dev)
rc = insert_resource(&iomem_resource, res);
if (rc)
- goto out_nvb;
+ return rc;
rc = devm_add_action_or_reset(dev, cxlr_pmem_remove_resource, res);
if (rc)
- goto out_nvb;
+ return rc;
ndr_desc.res = res;
ndr_desc.provider_data = cxlr_pmem;
@@ -487,43 +324,23 @@ static int cxl_pmem_region_probe(struct device *dev)
}
nd_set = devm_kzalloc(dev, sizeof(*nd_set), GFP_KERNEL);
- if (!nd_set) {
- rc = -ENOMEM;
- goto out_nvb;
- }
+ if (!nd_set)
+ return -ENOMEM;
ndr_desc.memregion = cxlr->id;
set_bit(ND_REGION_CXL, &ndr_desc.flags);
set_bit(ND_REGION_PERSIST_MEMCTRL, &ndr_desc.flags);
info = kmalloc_array(cxlr_pmem->nr_mappings, sizeof(*info), GFP_KERNEL);
- if (!info) {
- rc = -ENOMEM;
- goto out_nvb;
- }
-
- rc = devm_add_action_or_reset(dev, release_mappings, cxlr_pmem);
- if (rc)
- goto out_nvd;
+ if (!info)
+ return -ENOMEM;
for (i = 0; i < cxlr_pmem->nr_mappings; i++) {
struct cxl_pmem_region_mapping *m = &cxlr_pmem->mapping[i];
struct cxl_memdev *cxlmd = m->cxlmd;
struct cxl_dev_state *cxlds = cxlmd->cxlds;
- struct device *d;
-
- d = device_find_child(&cxlmd->dev, NULL, match_cxl_nvdimm);
- if (!d) {
- dev_dbg(dev, "[%d]: %s: no cxl_nvdimm found\n", i,
- dev_name(&cxlmd->dev));
- rc = -ENODEV;
- goto out_nvd;
- }
- /* safe to drop ref now with bridge lock held */
- put_device(d);
-
- cxl_nvd = to_cxl_nvdimm(d);
+ cxl_nvd = cxlmd->cxl_nvd;
nvdimm = dev_get_drvdata(&cxl_nvd->dev);
if (!nvdimm) {
dev_dbg(dev, "[%d]: %s: no nvdimm found\n", i,
@@ -532,14 +349,6 @@ static int cxl_pmem_region_probe(struct device *dev)
goto out_nvd;
}
- /*
- * Pin the region per nvdimm device as those may be released
- * out-of-order with respect to the region, and a single nvdimm
- * maybe associated with multiple regions
- */
- rc = cxl_nvdimm_add_region(cxl_nvd, cxlr_pmem);
- if (rc)
- goto out_nvd;
m->cxl_nvd = cxl_nvd;
mappings[i] = (struct nd_mapping_desc) {
.nvdimm = nvdimm,
@@ -572,9 +381,6 @@ static int cxl_pmem_region_probe(struct device *dev)
cxlr_pmem->nd_region);
out_nvd:
kfree(info);
-out_nvb:
- device_unlock(&cxl_nvb->dev);
- put_device(&cxl_nvb->dev);
return rc;
}
@@ -583,33 +389,11 @@ static struct cxl_driver cxl_pmem_region_driver = {
.name = "cxl_pmem_region",
.probe = cxl_pmem_region_probe,
.id = CXL_DEVICE_PMEM_REGION,
+ .drv = {
+ .suppress_bind_attrs = true,
+ },
};
-/*
- * Return all bridges to the CXL_NVB_NEW state to invalidate any
- * ->state_work referring to the now destroyed cxl_pmem_wq.
- */
-static int cxl_nvdimm_bridge_reset(struct device *dev, void *data)
-{
- struct cxl_nvdimm_bridge *cxl_nvb;
-
- if (!is_cxl_nvdimm_bridge(dev))
- return 0;
-
- cxl_nvb = to_cxl_nvdimm_bridge(dev);
- device_lock(dev);
- cxl_nvb->state = CXL_NVB_NEW;
- device_unlock(dev);
-
- return 0;
-}
-
-static void destroy_cxl_pmem_wq(void)
-{
- destroy_workqueue(cxl_pmem_wq);
- bus_for_each_dev(&cxl_bus_type, NULL, NULL, cxl_nvdimm_bridge_reset);
-}
-
static __init int cxl_pmem_init(void)
{
int rc;
@@ -617,13 +401,9 @@ static __init int cxl_pmem_init(void)
set_bit(CXL_MEM_COMMAND_ID_SET_SHUTDOWN_STATE, exclusive_cmds);
set_bit(CXL_MEM_COMMAND_ID_SET_LSA, exclusive_cmds);
- cxl_pmem_wq = alloc_ordered_workqueue("cxl_pmem", 0);
- if (!cxl_pmem_wq)
- return -ENXIO;
-
rc = cxl_driver_register(&cxl_nvdimm_bridge_driver);
if (rc)
- goto err_bridge;
+ return rc;
rc = cxl_driver_register(&cxl_nvdimm_driver);
if (rc)
@@ -639,8 +419,6 @@ err_region:
cxl_driver_unregister(&cxl_nvdimm_driver);
err_nvdimm:
cxl_driver_unregister(&cxl_nvdimm_bridge_driver);
-err_bridge:
- destroy_cxl_pmem_wq();
return rc;
}
@@ -649,7 +427,6 @@ static __exit void cxl_pmem_exit(void)
cxl_driver_unregister(&cxl_pmem_region_driver);
cxl_driver_unregister(&cxl_nvdimm_driver);
cxl_driver_unregister(&cxl_nvdimm_bridge_driver);
- destroy_cxl_pmem_wq();
}
MODULE_LICENSE("GPL v2");
diff --git a/drivers/cxl/security.c b/drivers/cxl/security.c
new file mode 100644
index 000000000000..4ad4bda2d18e
--- /dev/null
+++ b/drivers/cxl/security.c
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright(c) 2022 Intel Corporation. All rights reserved. */
+#include <linux/libnvdimm.h>
+#include <asm/unaligned.h>
+#include <linux/module.h>
+#include <linux/async.h>
+#include <linux/slab.h>
+#include <linux/memregion.h>
+#include "cxlmem.h"
+#include "cxl.h"
+
+static unsigned long cxl_pmem_get_security_flags(struct nvdimm *nvdimm,
+ enum nvdimm_passphrase_type ptype)
+{
+ struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
+ struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
+ struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ unsigned long security_flags = 0;
+ struct cxl_get_security_output {
+ __le32 flags;
+ } out;
+ struct cxl_mbox_cmd mbox_cmd;
+ u32 sec_out;
+ int rc;
+
+ mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_GET_SECURITY_STATE,
+ .size_out = sizeof(out),
+ .payload_out = &out,
+ };
+
+ rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ if (rc < 0)
+ return 0;
+
+ sec_out = le32_to_cpu(out.flags);
+ if (ptype == NVDIMM_MASTER) {
+ if (sec_out & CXL_PMEM_SEC_STATE_MASTER_PASS_SET)
+ set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
+ else
+ set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
+ if (sec_out & CXL_PMEM_SEC_STATE_MASTER_PLIMIT)
+ set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);
+ return security_flags;
+ }
+
+ if (sec_out & CXL_PMEM_SEC_STATE_USER_PASS_SET) {
+ if (sec_out & CXL_PMEM_SEC_STATE_FROZEN ||
+ sec_out & CXL_PMEM_SEC_STATE_USER_PLIMIT)
+ set_bit(NVDIMM_SECURITY_FROZEN, &security_flags);
+
+ if (sec_out & CXL_PMEM_SEC_STATE_LOCKED)
+ set_bit(NVDIMM_SECURITY_LOCKED, &security_flags);
+ else
+ set_bit(NVDIMM_SECURITY_UNLOCKED, &security_flags);
+ } else {
+ set_bit(NVDIMM_SECURITY_DISABLED, &security_flags);
+ }
+
+ return security_flags;
+}
+
+static int cxl_pmem_security_change_key(struct nvdimm *nvdimm,
+ const struct nvdimm_key_data *old_data,
+ const struct nvdimm_key_data *new_data,
+ enum nvdimm_passphrase_type ptype)
+{
+ 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_mbox_cmd mbox_cmd;
+ struct cxl_set_pass set_pass;
+
+ set_pass = (struct cxl_set_pass) {
+ .type = ptype == NVDIMM_MASTER ? CXL_PMEM_SEC_PASS_MASTER :
+ CXL_PMEM_SEC_PASS_USER,
+ };
+ memcpy(set_pass.old_pass, old_data->data, NVDIMM_PASSPHRASE_LEN);
+ memcpy(set_pass.new_pass, new_data->data, NVDIMM_PASSPHRASE_LEN);
+
+ mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_SET_PASSPHRASE,
+ .size_in = sizeof(set_pass),
+ .payload_in = &set_pass,
+ };
+
+ return cxl_internal_send_cmd(cxlds, &mbox_cmd);
+}
+
+static int __cxl_pmem_security_disable(struct nvdimm *nvdimm,
+ const struct nvdimm_key_data *key_data,
+ enum nvdimm_passphrase_type ptype)
+{
+ 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_disable_pass dis_pass;
+ struct cxl_mbox_cmd mbox_cmd;
+
+ dis_pass = (struct cxl_disable_pass) {
+ .type = ptype == NVDIMM_MASTER ? CXL_PMEM_SEC_PASS_MASTER :
+ CXL_PMEM_SEC_PASS_USER,
+ };
+ memcpy(dis_pass.pass, key_data->data, NVDIMM_PASSPHRASE_LEN);
+
+ mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_DISABLE_PASSPHRASE,
+ .size_in = sizeof(dis_pass),
+ .payload_in = &dis_pass,
+ };
+
+ return cxl_internal_send_cmd(cxlds, &mbox_cmd);
+}
+
+static int cxl_pmem_security_disable(struct nvdimm *nvdimm,
+ const struct nvdimm_key_data *key_data)
+{
+ return __cxl_pmem_security_disable(nvdimm, key_data, NVDIMM_USER);
+}
+
+static int cxl_pmem_security_disable_master(struct nvdimm *nvdimm,
+ const struct nvdimm_key_data *key_data)
+{
+ return __cxl_pmem_security_disable(nvdimm, key_data, NVDIMM_MASTER);
+}
+
+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_mbox_cmd mbox_cmd = {
+ .opcode = CXL_MBOX_OP_FREEZE_SECURITY,
+ };
+
+ return cxl_internal_send_cmd(cxlds, &mbox_cmd);
+}
+
+static int cxl_pmem_security_unlock(struct nvdimm *nvdimm,
+ const struct nvdimm_key_data *key_data)
+{
+ struct cxl_nvdimm *cxl_nvd = nvdimm_provider_data(nvdimm);
+ struct cxl_memdev *cxlmd = cxl_nvd->cxlmd;
+ struct cxl_dev_state *cxlds = cxlmd->cxlds;
+ u8 pass[NVDIMM_PASSPHRASE_LEN];
+ struct cxl_mbox_cmd mbox_cmd;
+ int rc;
+
+ memcpy(pass, key_data->data, NVDIMM_PASSPHRASE_LEN);
+ mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_UNLOCK,
+ .size_in = NVDIMM_PASSPHRASE_LEN,
+ .payload_in = pass,
+ };
+
+ rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
+static int cxl_pmem_security_passphrase_erase(struct nvdimm *nvdimm,
+ const struct nvdimm_key_data *key,
+ enum nvdimm_passphrase_type ptype)
+{
+ 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_mbox_cmd mbox_cmd;
+ struct cxl_pass_erase erase;
+ int rc;
+
+ erase = (struct cxl_pass_erase) {
+ .type = ptype == NVDIMM_MASTER ? CXL_PMEM_SEC_PASS_MASTER :
+ CXL_PMEM_SEC_PASS_USER,
+ };
+ memcpy(erase.pass, key->data, NVDIMM_PASSPHRASE_LEN);
+ mbox_cmd = (struct cxl_mbox_cmd) {
+ .opcode = CXL_MBOX_OP_PASSPHRASE_SECURE_ERASE,
+ .size_in = sizeof(erase),
+ .payload_in = &erase,
+ };
+
+ rc = cxl_internal_send_cmd(cxlds, &mbox_cmd);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
+static const struct nvdimm_security_ops __cxl_security_ops = {
+ .get_flags = cxl_pmem_get_security_flags,
+ .change_key = cxl_pmem_security_change_key,
+ .disable = cxl_pmem_security_disable,
+ .freeze = cxl_pmem_security_freeze,
+ .unlock = cxl_pmem_security_unlock,
+ .erase = cxl_pmem_security_passphrase_erase,
+ .disable_master = cxl_pmem_security_disable_master,
+};
+
+const struct nvdimm_security_ops *cxl_security_ops = &__cxl_security_ops;
diff --git a/drivers/devfreq/devfreq-event.c b/drivers/devfreq/devfreq-event.c
index 6765c03334bc..f041edccd107 100644
--- a/drivers/devfreq/devfreq-event.c
+++ b/drivers/devfreq/devfreq-event.c
@@ -233,7 +233,7 @@ struct devfreq_event_dev *devfreq_event_get_edev_by_phandle(struct device *dev,
mutex_lock(&devfreq_event_list_lock);
list_for_each_entry(edev, &devfreq_event_list, node) {
- if (edev->dev.parent && edev->dev.parent->of_node == node)
+ if (edev->dev.parent && device_match_of_node(edev->dev.parent, node))
goto out;
}
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 63347a5ae599..817c71da391a 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -776,8 +776,7 @@ static void remove_sysfs_files(struct devfreq *devfreq,
* @dev: the device to add devfreq feature.
* @profile: device-specific profile to run devfreq.
* @governor_name: name of the policy to choose frequency.
- * @data: private data for the governor. The devfreq framework does not
- * touch this value.
+ * @data: devfreq driver pass to governors, governor should not change it.
*/
struct devfreq *devfreq_add_device(struct device *dev,
struct devfreq_dev_profile *profile,
@@ -1011,8 +1010,7 @@ static void devm_devfreq_dev_release(struct device *dev, void *res)
* @dev: the device to add devfreq feature.
* @profile: device-specific profile to run devfreq.
* @governor_name: name of the policy to choose frequency.
- * @data: private data for the governor. The devfreq framework does not
- * touch this value.
+ * @data: devfreq driver pass to governors, governor should not change it.
*
* This function manages automatically the memory of devfreq device using device
* resource management and simplify the free operation for memory of devfreq
@@ -1059,7 +1057,7 @@ struct devfreq *devfreq_get_devfreq_by_node(struct device_node *node)
mutex_lock(&devfreq_list_lock);
list_for_each_entry(devfreq, &devfreq_list, node) {
if (devfreq->dev.parent
- && devfreq->dev.parent->of_node == node) {
+ && device_match_of_node(devfreq->dev.parent, node)) {
mutex_unlock(&devfreq_list_lock);
return devfreq;
}
diff --git a/drivers/devfreq/event/exynos-nocp.c b/drivers/devfreq/event/exynos-nocp.c
index ccc531ee6938..c1cc23bcb995 100644
--- a/drivers/devfreq/event/exynos-nocp.c
+++ b/drivers/devfreq/event/exynos-nocp.c
@@ -214,8 +214,7 @@ static int exynos_nocp_parse_dt(struct platform_device *pdev,
nocp->clk = NULL;
/* Maps the memory mapped IO to control nocp register */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(dev, res);
+ base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(base))
return PTR_ERR(base);
diff --git a/drivers/devfreq/governor_userspace.c b/drivers/devfreq/governor_userspace.c
index ab9db7adb3ad..d69672ccacc4 100644
--- a/drivers/devfreq/governor_userspace.c
+++ b/drivers/devfreq/governor_userspace.c
@@ -21,7 +21,7 @@ struct userspace_data {
static int devfreq_userspace_func(struct devfreq *df, unsigned long *freq)
{
- struct userspace_data *data = df->data;
+ struct userspace_data *data = df->governor_data;
if (data->valid)
*freq = data->user_frequency;
@@ -40,7 +40,7 @@ static ssize_t set_freq_store(struct device *dev, struct device_attribute *attr,
int err = 0;
mutex_lock(&devfreq->lock);
- data = devfreq->data;
+ data = devfreq->governor_data;
sscanf(buf, "%lu", &wanted);
data->user_frequency = wanted;
@@ -60,7 +60,7 @@ static ssize_t set_freq_show(struct device *dev,
int err = 0;
mutex_lock(&devfreq->lock);
- data = devfreq->data;
+ data = devfreq->governor_data;
if (data->valid)
err = sprintf(buf, "%lu\n", data->user_frequency);
@@ -91,7 +91,7 @@ static int userspace_init(struct devfreq *devfreq)
goto out;
}
data->valid = false;
- devfreq->data = data;
+ devfreq->governor_data = data;
err = sysfs_create_group(&devfreq->dev.kobj, &dev_attr_group);
out:
@@ -107,8 +107,8 @@ static void userspace_exit(struct devfreq *devfreq)
if (devfreq->dev.kobj.sd)
sysfs_remove_group(&devfreq->dev.kobj, &dev_attr_group);
- kfree(devfreq->data);
- devfreq->data = NULL;
+ kfree(devfreq->governor_data);
+ devfreq->governor_data = NULL;
}
static int devfreq_userspace_handler(struct devfreq *devfreq,
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index e6f36c014c4c..b6c36914e7c6 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -130,6 +130,7 @@ static struct file_system_type dma_buf_fs_type = {
static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct *vma)
{
struct dma_buf *dmabuf;
+ int ret;
if (!is_dma_buf_file(file))
return -EINVAL;
@@ -145,7 +146,11 @@ static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct *vma)
dmabuf->size >> PAGE_SHIFT)
return -EINVAL;
- return dmabuf->ops->mmap(dmabuf, vma);
+ dma_resv_lock(dmabuf->resv, NULL);
+ ret = dmabuf->ops->mmap(dmabuf, vma);
+ dma_resv_unlock(dmabuf->resv);
+
+ return ret;
}
static loff_t dma_buf_llseek(struct file *file, loff_t offset, int whence)
@@ -668,7 +673,6 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
dmabuf->file = file;
- mutex_init(&dmabuf->lock);
INIT_LIST_HEAD(&dmabuf->attachments);
mutex_lock(&db_list.lock);
@@ -807,6 +811,70 @@ static struct sg_table * __map_dma_buf(struct dma_buf_attachment *attach,
}
/**
+ * DOC: locking convention
+ *
+ * In order to avoid deadlock situations between dma-buf exports and importers,
+ * all dma-buf API users must follow the common dma-buf locking convention.
+ *
+ * Convention for importers
+ *
+ * 1. Importers must hold the dma-buf reservation lock when calling these
+ * functions:
+ *
+ * - dma_buf_pin()
+ * - dma_buf_unpin()
+ * - dma_buf_map_attachment()
+ * - dma_buf_unmap_attachment()
+ * - dma_buf_vmap()
+ * - dma_buf_vunmap()
+ *
+ * 2. Importers must not hold the dma-buf reservation lock when calling these
+ * functions:
+ *
+ * - dma_buf_attach()
+ * - dma_buf_dynamic_attach()
+ * - dma_buf_detach()
+ * - dma_buf_export(
+ * - dma_buf_fd()
+ * - dma_buf_get()
+ * - dma_buf_put()
+ * - dma_buf_mmap()
+ * - dma_buf_begin_cpu_access()
+ * - dma_buf_end_cpu_access()
+ * - dma_buf_map_attachment_unlocked()
+ * - dma_buf_unmap_attachment_unlocked()
+ * - dma_buf_vmap_unlocked()
+ * - dma_buf_vunmap_unlocked()
+ *
+ * Convention for exporters
+ *
+ * 1. These &dma_buf_ops callbacks are invoked with unlocked dma-buf
+ * reservation and exporter can take the lock:
+ *
+ * - &dma_buf_ops.attach()
+ * - &dma_buf_ops.detach()
+ * - &dma_buf_ops.release()
+ * - &dma_buf_ops.begin_cpu_access()
+ * - &dma_buf_ops.end_cpu_access()
+ *
+ * 2. These &dma_buf_ops callbacks are invoked with locked dma-buf
+ * reservation and exporter can't take the lock:
+ *
+ * - &dma_buf_ops.pin()
+ * - &dma_buf_ops.unpin()
+ * - &dma_buf_ops.map_dma_buf()
+ * - &dma_buf_ops.unmap_dma_buf()
+ * - &dma_buf_ops.mmap()
+ * - &dma_buf_ops.vmap()
+ * - &dma_buf_ops.vunmap()
+ *
+ * 3. Exporters must hold the dma-buf reservation lock when calling these
+ * functions:
+ *
+ * - dma_buf_move_notify()
+ */
+
+/**
* dma_buf_dynamic_attach - Add the device to dma_buf's attachments list
* @dmabuf: [in] buffer to attach device to.
* @dev: [in] device to be attached.
@@ -870,8 +938,8 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
dma_buf_is_dynamic(dmabuf)) {
struct sg_table *sgt;
+ dma_resv_lock(attach->dmabuf->resv, NULL);
if (dma_buf_is_dynamic(attach->dmabuf)) {
- dma_resv_lock(attach->dmabuf->resv, NULL);
ret = dmabuf->ops->pin(attach);
if (ret)
goto err_unlock;
@@ -884,8 +952,7 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
ret = PTR_ERR(sgt);
goto err_unpin;
}
- if (dma_buf_is_dynamic(attach->dmabuf))
- dma_resv_unlock(attach->dmabuf->resv);
+ dma_resv_unlock(attach->dmabuf->resv);
attach->sgt = sgt;
attach->dir = DMA_BIDIRECTIONAL;
}
@@ -901,8 +968,7 @@ err_unpin:
dmabuf->ops->unpin(attach);
err_unlock:
- if (dma_buf_is_dynamic(attach->dmabuf))
- dma_resv_unlock(attach->dmabuf->resv);
+ dma_resv_unlock(attach->dmabuf->resv);
dma_buf_detach(dmabuf, attach);
return ERR_PTR(ret);
@@ -945,24 +1011,22 @@ static void __unmap_dma_buf(struct dma_buf_attachment *attach,
*/
void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
{
- if (WARN_ON(!dmabuf || !attach))
+ if (WARN_ON(!dmabuf || !attach || dmabuf != attach->dmabuf))
return;
+ dma_resv_lock(dmabuf->resv, NULL);
+
if (attach->sgt) {
- if (dma_buf_is_dynamic(attach->dmabuf))
- dma_resv_lock(attach->dmabuf->resv, NULL);
__unmap_dma_buf(attach, attach->sgt, attach->dir);
- if (dma_buf_is_dynamic(attach->dmabuf)) {
+ if (dma_buf_is_dynamic(attach->dmabuf))
dmabuf->ops->unpin(attach);
- dma_resv_unlock(attach->dmabuf->resv);
- }
}
-
- dma_resv_lock(dmabuf->resv, NULL);
list_del(&attach->node);
+
dma_resv_unlock(dmabuf->resv);
+
if (dmabuf->ops->detach)
dmabuf->ops->detach(dmabuf, attach);
@@ -1053,8 +1117,7 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
if (WARN_ON(!attach || !attach->dmabuf))
return ERR_PTR(-EINVAL);
- if (dma_buf_attachment_is_dynamic(attach))
- dma_resv_assert_held(attach->dmabuf->resv);
+ dma_resv_assert_held(attach->dmabuf->resv);
if (attach->sgt) {
/*
@@ -1069,7 +1132,6 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
}
if (dma_buf_is_dynamic(attach->dmabuf)) {
- dma_resv_assert_held(attach->dmabuf->resv);
if (!IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY)) {
r = attach->dmabuf->ops->pin(attach);
if (r)
@@ -1112,6 +1174,34 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
EXPORT_SYMBOL_NS_GPL(dma_buf_map_attachment, DMA_BUF);
/**
+ * dma_buf_map_attachment_unlocked - Returns the scatterlist table of the attachment;
+ * mapped into _device_ address space. Is a wrapper for map_dma_buf() of the
+ * dma_buf_ops.
+ * @attach: [in] attachment whose scatterlist is to be returned
+ * @direction: [in] direction of DMA transfer
+ *
+ * Unlocked variant of dma_buf_map_attachment().
+ */
+struct sg_table *
+dma_buf_map_attachment_unlocked(struct dma_buf_attachment *attach,
+ enum dma_data_direction direction)
+{
+ struct sg_table *sg_table;
+
+ might_sleep();
+
+ if (WARN_ON(!attach || !attach->dmabuf))
+ return ERR_PTR(-EINVAL);
+
+ dma_resv_lock(attach->dmabuf->resv, NULL);
+ sg_table = dma_buf_map_attachment(attach, direction);
+ dma_resv_unlock(attach->dmabuf->resv);
+
+ return sg_table;
+}
+EXPORT_SYMBOL_NS_GPL(dma_buf_map_attachment_unlocked, DMA_BUF);
+
+/**
* dma_buf_unmap_attachment - unmaps and decreases usecount of the buffer;might
* deallocate the scatterlist associated. Is a wrapper for unmap_dma_buf() of
* dma_buf_ops.
@@ -1130,15 +1220,11 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
return;
- if (dma_buf_attachment_is_dynamic(attach))
- dma_resv_assert_held(attach->dmabuf->resv);
+ dma_resv_assert_held(attach->dmabuf->resv);
if (attach->sgt == sg_table)
return;
- if (dma_buf_is_dynamic(attach->dmabuf))
- dma_resv_assert_held(attach->dmabuf->resv);
-
__unmap_dma_buf(attach, sg_table, direction);
if (dma_buf_is_dynamic(attach->dmabuf) &&
@@ -1148,6 +1234,31 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment, DMA_BUF);
/**
+ * dma_buf_unmap_attachment_unlocked - unmaps and decreases usecount of the buffer;might
+ * deallocate the scatterlist associated. Is a wrapper for unmap_dma_buf() of
+ * dma_buf_ops.
+ * @attach: [in] attachment to unmap buffer from
+ * @sg_table: [in] scatterlist info of the buffer to unmap
+ * @direction: [in] direction of DMA transfer
+ *
+ * Unlocked variant of dma_buf_unmap_attachment().
+ */
+void dma_buf_unmap_attachment_unlocked(struct dma_buf_attachment *attach,
+ struct sg_table *sg_table,
+ enum dma_data_direction direction)
+{
+ might_sleep();
+
+ if (WARN_ON(!attach || !attach->dmabuf || !sg_table))
+ return;
+
+ dma_resv_lock(attach->dmabuf->resv, NULL);
+ dma_buf_unmap_attachment(attach, sg_table, direction);
+ dma_resv_unlock(attach->dmabuf->resv);
+}
+EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment_unlocked, DMA_BUF);
+
+/**
* dma_buf_move_notify - notify attachments that DMA-buf is moving
*
* @dmabuf: [in] buffer which is moving
@@ -1358,6 +1469,8 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_end_cpu_access, DMA_BUF);
int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
unsigned long pgoff)
{
+ int ret;
+
if (WARN_ON(!dmabuf || !vma))
return -EINVAL;
@@ -1378,7 +1491,11 @@ int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
vma_set_file(vma, dmabuf->file);
vma->vm_pgoff = pgoff;
- return dmabuf->ops->mmap(dmabuf, vma);
+ dma_resv_lock(dmabuf->resv, NULL);
+ ret = dmabuf->ops->mmap(dmabuf, vma);
+ dma_resv_unlock(dmabuf->resv);
+
+ return ret;
}
EXPORT_SYMBOL_NS_GPL(dma_buf_mmap, DMA_BUF);
@@ -1401,42 +1518,68 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_mmap, DMA_BUF);
int dma_buf_vmap(struct dma_buf *dmabuf, struct iosys_map *map)
{
struct iosys_map ptr;
- int ret = 0;
+ int ret;
iosys_map_clear(map);
if (WARN_ON(!dmabuf))
return -EINVAL;
+ dma_resv_assert_held(dmabuf->resv);
+
if (!dmabuf->ops->vmap)
return -EINVAL;
- mutex_lock(&dmabuf->lock);
if (dmabuf->vmapping_counter) {
dmabuf->vmapping_counter++;
BUG_ON(iosys_map_is_null(&dmabuf->vmap_ptr));
*map = dmabuf->vmap_ptr;
- goto out_unlock;
+ return 0;
}
BUG_ON(iosys_map_is_set(&dmabuf->vmap_ptr));
ret = dmabuf->ops->vmap(dmabuf, &ptr);
if (WARN_ON_ONCE(ret))
- goto out_unlock;
+ return ret;
dmabuf->vmap_ptr = ptr;
dmabuf->vmapping_counter = 1;
*map = dmabuf->vmap_ptr;
-out_unlock:
- mutex_unlock(&dmabuf->lock);
- return ret;
+ return 0;
}
EXPORT_SYMBOL_NS_GPL(dma_buf_vmap, DMA_BUF);
/**
+ * dma_buf_vmap_unlocked - Create virtual mapping for the buffer object into kernel
+ * address space. Same restrictions as for vmap and friends apply.
+ * @dmabuf: [in] buffer to vmap
+ * @map: [out] returns the vmap pointer
+ *
+ * Unlocked version of dma_buf_vmap()
+ *
+ * Returns 0 on success, or a negative errno code otherwise.
+ */
+int dma_buf_vmap_unlocked(struct dma_buf *dmabuf, struct iosys_map *map)
+{
+ int ret;
+
+ iosys_map_clear(map);
+
+ if (WARN_ON(!dmabuf))
+ return -EINVAL;
+
+ dma_resv_lock(dmabuf->resv, NULL);
+ ret = dma_buf_vmap(dmabuf, map);
+ dma_resv_unlock(dmabuf->resv);
+
+ return ret;
+}
+EXPORT_SYMBOL_NS_GPL(dma_buf_vmap_unlocked, DMA_BUF);
+
+/**
* dma_buf_vunmap - Unmap a vmap obtained by dma_buf_vmap.
* @dmabuf: [in] buffer to vunmap
* @map: [in] vmap pointer to vunmap
@@ -1446,20 +1589,36 @@ void dma_buf_vunmap(struct dma_buf *dmabuf, struct iosys_map *map)
if (WARN_ON(!dmabuf))
return;
+ dma_resv_assert_held(dmabuf->resv);
+
BUG_ON(iosys_map_is_null(&dmabuf->vmap_ptr));
BUG_ON(dmabuf->vmapping_counter == 0);
BUG_ON(!iosys_map_is_equal(&dmabuf->vmap_ptr, map));
- mutex_lock(&dmabuf->lock);
if (--dmabuf->vmapping_counter == 0) {
if (dmabuf->ops->vunmap)
dmabuf->ops->vunmap(dmabuf, map);
iosys_map_clear(&dmabuf->vmap_ptr);
}
- mutex_unlock(&dmabuf->lock);
}
EXPORT_SYMBOL_NS_GPL(dma_buf_vunmap, DMA_BUF);
+/**
+ * dma_buf_vunmap_unlocked - Unmap a vmap obtained by dma_buf_vmap.
+ * @dmabuf: [in] buffer to vunmap
+ * @map: [in] vmap pointer to vunmap
+ */
+void dma_buf_vunmap_unlocked(struct dma_buf *dmabuf, struct iosys_map *map)
+{
+ if (WARN_ON(!dmabuf))
+ return;
+
+ dma_resv_lock(dmabuf->resv, NULL);
+ dma_buf_vunmap(dmabuf, map);
+ dma_resv_unlock(dmabuf->resv);
+}
+EXPORT_SYMBOL_NS_GPL(dma_buf_vunmap_unlocked, DMA_BUF);
+
#ifdef CONFIG_DEBUG_FS
static int dma_buf_debug_show(struct seq_file *s, void *unused)
{
diff --git a/drivers/dma-buf/heaps/cma_heap.c b/drivers/dma-buf/heaps/cma_heap.c
index 28fb04eccdd0..1131fb943992 100644
--- a/drivers/dma-buf/heaps/cma_heap.c
+++ b/drivers/dma-buf/heaps/cma_heap.c
@@ -13,6 +13,7 @@
#include <linux/dma-buf.h>
#include <linux/dma-heap.h>
#include <linux/dma-map-ops.h>
+#include <linux/dma-resv.h>
#include <linux/err.h>
#include <linux/highmem.h>
#include <linux/io.h>
@@ -182,6 +183,8 @@ static int cma_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
{
struct cma_heap_buffer *buffer = dmabuf->priv;
+ dma_resv_assert_held(dmabuf->resv);
+
if ((vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) == 0)
return -EINVAL;
diff --git a/drivers/dma-buf/heaps/system_heap.c b/drivers/dma-buf/heaps/system_heap.c
index fcf836ba9c1f..e8bd10e60998 100644
--- a/drivers/dma-buf/heaps/system_heap.c
+++ b/drivers/dma-buf/heaps/system_heap.c
@@ -13,6 +13,7 @@
#include <linux/dma-buf.h>
#include <linux/dma-mapping.h>
#include <linux/dma-heap.h>
+#include <linux/dma-resv.h>
#include <linux/err.h>
#include <linux/highmem.h>
#include <linux/mm.h>
@@ -201,6 +202,8 @@ static int system_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
struct sg_page_iter piter;
int ret;
+ dma_resv_assert_held(dmabuf->resv);
+
for_each_sgtable_page(table, &piter, vma->vm_pgoff) {
struct page *page = sg_page_iter_page(&piter);
diff --git a/drivers/dma-buf/st-dma-fence-chain.c b/drivers/dma-buf/st-dma-fence-chain.c
index 0a9b099d0518..c0979c8049b5 100644
--- a/drivers/dma-buf/st-dma-fence-chain.c
+++ b/drivers/dma-buf/st-dma-fence-chain.c
@@ -400,7 +400,7 @@ static int __find_race(void *arg)
struct dma_fence *fence = dma_fence_get(data->fc.tail);
int seqno;
- seqno = prandom_u32_max(data->fc.chain_length) + 1;
+ seqno = get_random_u32_inclusive(1, data->fc.chain_length);
err = dma_fence_chain_find_seqno(&fence, seqno);
if (err) {
@@ -429,7 +429,7 @@ static int __find_race(void *arg)
dma_fence_put(fence);
signal:
- seqno = prandom_u32_max(data->fc.chain_length - 1);
+ seqno = get_random_u32_below(data->fc.chain_length - 1);
dma_fence_signal(data->fc.fences[seqno]);
cond_resched();
}
@@ -637,7 +637,7 @@ static void randomise_fences(struct fence_chains *fc)
while (--count) {
unsigned int swp;
- swp = prandom_u32_max(count + 1);
+ swp = get_random_u32_below(count + 1);
if (swp == count)
continue;
diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
index 2bcdb935a3ac..283816fbd72f 100644
--- a/drivers/dma-buf/udmabuf.c
+++ b/drivers/dma-buf/udmabuf.c
@@ -2,6 +2,7 @@
#include <linux/cred.h>
#include <linux/device.h>
#include <linux/dma-buf.h>
+#include <linux/dma-resv.h>
#include <linux/highmem.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -49,6 +50,8 @@ static int mmap_udmabuf(struct dma_buf *buf, struct vm_area_struct *vma)
{
struct udmabuf *ubuf = buf->priv;
+ dma_resv_assert_held(buf->resv);
+
if ((vma->vm_flags & (VM_SHARED | VM_MAYSHARE)) == 0)
return -EINVAL;
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 7524b62a8870..25e111ab21f8 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -462,7 +462,7 @@ config MV_XOR_V2
select DMA_ENGINE
select DMA_ENGINE_RAID
select ASYNC_TX_ENABLE_CHANNEL_SWITCH
- select GENERIC_MSI_IRQ_DOMAIN
+ select GENERIC_MSI_IRQ
help
Enable support for the Marvell version 2 XOR engine.
diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c
index 210f1a9eb441..04d1c33afc12 100644
--- a/drivers/dma/qcom/hidma.c
+++ b/drivers/dma/qcom/hidma.c
@@ -610,7 +610,7 @@ static irqreturn_t hidma_chirq_handler(int chirq, void *arg)
return hidma_ll_inthandler(chirq, lldev);
}
-#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+#ifdef CONFIG_GENERIC_MSI_IRQ
static irqreturn_t hidma_chirq_handler_msi(int chirq, void *arg)
{
struct hidma_lldev **lldevp = arg;
@@ -671,7 +671,7 @@ static int hidma_sysfs_init(struct hidma_dev *dev)
return device_create_file(dev->ddev.dev, dev->chid_attrs);
}
-#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+#ifdef CONFIG_GENERIC_MSI_IRQ
static void hidma_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg)
{
struct device *dev = msi_desc_to_dev(desc);
@@ -687,7 +687,7 @@ static void hidma_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg)
static void hidma_free_msis(struct hidma_dev *dmadev)
{
-#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+#ifdef CONFIG_GENERIC_MSI_IRQ
struct device *dev = dmadev->ddev.dev;
int i, virq;
@@ -704,7 +704,7 @@ static void hidma_free_msis(struct hidma_dev *dmadev)
static int hidma_request_msi(struct hidma_dev *dmadev,
struct platform_device *pdev)
{
-#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
+#ifdef CONFIG_GENERIC_MSI_IRQ
int rc, i, virq;
rc = platform_msi_domain_alloc_irqs(&pdev->dev, HIDMA_MSI_INTS,
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index 456602d373b7..4cfdefbd744d 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -53,8 +53,8 @@ config EDAC_DECODE_MCE
has been initialized.
config EDAC_GHES
- bool "Output ACPI APEI/GHES BIOS detected errors via EDAC"
- depends on ACPI_APEI_GHES && (EDAC=y)
+ tristate "Output ACPI APEI/GHES BIOS detected errors via EDAC"
+ depends on ACPI_APEI_GHES
select UEFI_CPER
help
Not all machines support hardware-driven error report. Some of those
@@ -211,6 +211,7 @@ config EDAC_R82600
config EDAC_I5000
tristate "Intel Greencreek/Blackford chipset"
depends on X86 && PCI
+ depends on BROKEN
help
Support for error detection and correction the Intel
Greekcreek/Blackford chipsets.
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 2f854feeeb23..e3318e5575a3 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -4329,6 +4329,9 @@ static int __init amd64_edac_init(void)
int err = -ENODEV;
int i;
+ if (ghes_get_devices())
+ return -EBUSY;
+
owner = edac_get_owner();
if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR)))
return -EBUSY;
diff --git a/drivers/edac/armada_xp_edac.c b/drivers/edac/armada_xp_edac.c
index 038abbb83f4b..c4bd2fb9c46b 100644
--- a/drivers/edac/armada_xp_edac.c
+++ b/drivers/edac/armada_xp_edac.c
@@ -599,6 +599,9 @@ static int __init armada_xp_edac_init(void)
{
int res;
+ if (ghes_get_devices())
+ return -EBUSY;
+
/* only polling is supported */
edac_op_state = EDAC_OPSTATE_POLL;
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c
index 0a638c97702a..15f63452a9be 100644
--- a/drivers/edac/edac_mc_sysfs.c
+++ b/drivers/edac/edac_mc_sysfs.c
@@ -298,6 +298,14 @@ DEVICE_CHANNEL(ch6_dimm_label, S_IRUGO | S_IWUSR,
channel_dimm_label_show, channel_dimm_label_store, 6);
DEVICE_CHANNEL(ch7_dimm_label, S_IRUGO | S_IWUSR,
channel_dimm_label_show, channel_dimm_label_store, 7);
+DEVICE_CHANNEL(ch8_dimm_label, S_IRUGO | S_IWUSR,
+ channel_dimm_label_show, channel_dimm_label_store, 8);
+DEVICE_CHANNEL(ch9_dimm_label, S_IRUGO | S_IWUSR,
+ channel_dimm_label_show, channel_dimm_label_store, 9);
+DEVICE_CHANNEL(ch10_dimm_label, S_IRUGO | S_IWUSR,
+ channel_dimm_label_show, channel_dimm_label_store, 10);
+DEVICE_CHANNEL(ch11_dimm_label, S_IRUGO | S_IWUSR,
+ channel_dimm_label_show, channel_dimm_label_store, 11);
/* Total possible dynamic DIMM Label attribute file table */
static struct attribute *dynamic_csrow_dimm_attr[] = {
@@ -309,6 +317,10 @@ static struct attribute *dynamic_csrow_dimm_attr[] = {
&dev_attr_legacy_ch5_dimm_label.attr.attr,
&dev_attr_legacy_ch6_dimm_label.attr.attr,
&dev_attr_legacy_ch7_dimm_label.attr.attr,
+ &dev_attr_legacy_ch8_dimm_label.attr.attr,
+ &dev_attr_legacy_ch9_dimm_label.attr.attr,
+ &dev_attr_legacy_ch10_dimm_label.attr.attr,
+ &dev_attr_legacy_ch11_dimm_label.attr.attr,
NULL
};
@@ -329,6 +341,14 @@ DEVICE_CHANNEL(ch6_ce_count, S_IRUGO,
channel_ce_count_show, NULL, 6);
DEVICE_CHANNEL(ch7_ce_count, S_IRUGO,
channel_ce_count_show, NULL, 7);
+DEVICE_CHANNEL(ch8_ce_count, S_IRUGO,
+ channel_ce_count_show, NULL, 8);
+DEVICE_CHANNEL(ch9_ce_count, S_IRUGO,
+ channel_ce_count_show, NULL, 9);
+DEVICE_CHANNEL(ch10_ce_count, S_IRUGO,
+ channel_ce_count_show, NULL, 10);
+DEVICE_CHANNEL(ch11_ce_count, S_IRUGO,
+ channel_ce_count_show, NULL, 11);
/* Total possible dynamic ce_count attribute file table */
static struct attribute *dynamic_csrow_ce_count_attr[] = {
@@ -340,6 +360,10 @@ static struct attribute *dynamic_csrow_ce_count_attr[] = {
&dev_attr_legacy_ch5_ce_count.attr.attr,
&dev_attr_legacy_ch6_ce_count.attr.attr,
&dev_attr_legacy_ch7_ce_count.attr.attr,
+ &dev_attr_legacy_ch8_ce_count.attr.attr,
+ &dev_attr_legacy_ch9_ce_count.attr.attr,
+ &dev_attr_legacy_ch10_ce_count.attr.attr,
+ &dev_attr_legacy_ch11_ce_count.attr.attr,
NULL
};
diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h
index 50ed9f2425bb..763c076d96f2 100644
--- a/drivers/edac/edac_module.h
+++ b/drivers/edac/edac_module.h
@@ -11,6 +11,7 @@
#ifndef __EDAC_MODULE_H__
#define __EDAC_MODULE_H__
+#include <acpi/ghes.h>
#include "edac_mc.h"
#include "edac_pci.h"
#include "edac_device.h"
diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c
index c8fa7dcfdbd0..cf2b618c1ada 100644
--- a/drivers/edac/ghes_edac.c
+++ b/drivers/edac/ghes_edac.c
@@ -14,6 +14,7 @@
#include <linux/dmi.h>
#include "edac_module.h"
#include <ras/ras_event.h>
+#include <linux/notifier.h>
#define OTHER_DETAIL_LEN 400
@@ -53,12 +54,10 @@ static DEFINE_MUTEX(ghes_reg_mutex);
*/
static DEFINE_SPINLOCK(ghes_lock);
-/* "ghes_edac.force_load=1" skips the platform check */
-static bool __read_mostly force_load;
-module_param(force_load, bool, 0);
-
static bool system_scanned;
+static struct list_head *ghes_devs;
+
/* Memory Device - Type 17 of SMBIOS spec */
struct memdev_dmi_entry {
u8 type;
@@ -267,11 +266,14 @@ out:
return n;
}
-void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err)
+static int ghes_edac_report_mem_error(struct notifier_block *nb,
+ unsigned long val, void *data)
{
+ struct cper_sec_mem_err *mem_err = (struct cper_sec_mem_err *)data;
struct cper_mem_err_compact cmem;
struct edac_raw_error_desc *e;
struct mem_ctl_info *mci;
+ unsigned long sev = val;
struct ghes_pvt *pvt;
unsigned long flags;
char *p;
@@ -282,7 +284,7 @@ void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err)
* know.
*/
if (WARN_ON_ONCE(in_nmi()))
- return;
+ return NOTIFY_OK;
spin_lock_irqsave(&ghes_lock, flags);
@@ -374,36 +376,24 @@ void ghes_edac_report_mem_error(int sev, struct cper_sec_mem_err *mem_err)
unlock:
spin_unlock_irqrestore(&ghes_lock, flags);
+
+ return NOTIFY_OK;
}
-/*
- * Known systems that are safe to enable this module.
- */
-static struct acpi_platform_list plat_list[] = {
- {"HPE ", "Server ", 0, ACPI_SIG_FADT, all_versions},
- { } /* End */
+static struct notifier_block ghes_edac_mem_err_nb = {
+ .notifier_call = ghes_edac_report_mem_error,
+ .priority = 0,
};
-int ghes_edac_register(struct ghes *ghes, struct device *dev)
+static int ghes_edac_register(struct device *dev)
{
bool fake = false;
struct mem_ctl_info *mci;
struct ghes_pvt *pvt;
struct edac_mc_layer layers[1];
unsigned long flags;
- int idx = -1;
int rc = 0;
- if (IS_ENABLED(CONFIG_X86)) {
- /* Check if safe to enable on this system */
- idx = acpi_match_platform_list(plat_list);
- if (!force_load && idx < 0)
- return -ENODEV;
- } else {
- force_load = true;
- idx = 0;
- }
-
/* finish another registration/unregistration instance first */
mutex_lock(&ghes_reg_mutex);
@@ -447,15 +437,10 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev)
pr_info("This system has a very crappy BIOS: It doesn't even list the DIMMS.\n");
pr_info("Its SMBIOS info is wrong. It is doubtful that the error report would\n");
pr_info("work on such system. Use this driver with caution\n");
- } else if (idx < 0) {
- pr_info("This EDAC driver relies on BIOS to enumerate memory and get error reports.\n");
- pr_info("Unfortunately, not all BIOSes reflect the memory layout correctly.\n");
- pr_info("So, the end result of using this driver varies from vendor to vendor.\n");
- pr_info("If you find incorrect reports, please contact your hardware vendor\n");
- pr_info("to correct its BIOS.\n");
- pr_info("This system has %d DIMM sockets.\n", ghes_hw.num_dimms);
}
+ pr_info("This system has %d DIMM sockets.\n", ghes_hw.num_dimms);
+
if (!fake) {
struct dimm_info *src, *dst;
int i = 0;
@@ -503,6 +488,8 @@ int ghes_edac_register(struct ghes *ghes, struct device *dev)
ghes_pvt = pvt;
spin_unlock_irqrestore(&ghes_lock, flags);
+ ghes_register_report_chain(&ghes_edac_mem_err_nb);
+
/* only set on success */
refcount_set(&ghes_refcount, 1);
@@ -517,14 +504,11 @@ unlock:
return rc;
}
-void ghes_edac_unregister(struct ghes *ghes)
+static void ghes_edac_unregister(struct ghes *ghes)
{
struct mem_ctl_info *mci;
unsigned long flags;
- if (!force_load)
- return;
-
mutex_lock(&ghes_reg_mutex);
system_scanned = false;
@@ -548,6 +532,42 @@ void ghes_edac_unregister(struct ghes *ghes)
if (mci)
edac_mc_free(mci);
+ ghes_unregister_report_chain(&ghes_edac_mem_err_nb);
+
unlock:
mutex_unlock(&ghes_reg_mutex);
}
+
+static int __init ghes_edac_init(void)
+{
+ struct ghes *g, *g_tmp;
+
+ ghes_devs = ghes_get_devices();
+ if (!ghes_devs)
+ return -ENODEV;
+
+ if (list_empty(ghes_devs)) {
+ pr_info("GHES probing device list is empty");
+ return -ENODEV;
+ }
+
+ list_for_each_entry_safe(g, g_tmp, ghes_devs, elist) {
+ ghes_edac_register(g->dev);
+ }
+
+ return 0;
+}
+module_init(ghes_edac_init);
+
+static void __exit ghes_edac_exit(void)
+{
+ struct ghes *g, *g_tmp;
+
+ list_for_each_entry_safe(g, g_tmp, ghes_devs, elist) {
+ ghes_edac_unregister(g);
+ }
+}
+module_exit(ghes_edac_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Output ACPI APEI/GHES BIOS detected errors via EDAC");
diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c
index a22ea053f8e1..65aeea53e2df 100644
--- a/drivers/edac/i10nm_base.c
+++ b/drivers/edac/i10nm_base.c
@@ -304,11 +304,10 @@ static struct pci_dev *pci_get_dev_wrapper(int dom, unsigned int bus,
if (unlikely(pci_enable_device(pdev) < 0)) {
edac_dbg(2, "Failed to enable device %02x:%02x.%x\n",
bus, dev, fun);
+ pci_dev_put(pdev);
return NULL;
}
- pci_dev_get(pdev);
-
return pdev;
}
@@ -756,6 +755,9 @@ static int __init i10nm_init(void)
edac_dbg(2, "\n");
+ if (ghes_get_devices())
+ return -EBUSY;
+
owner = edac_get_owner();
if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR)))
return -EBUSY;
diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c
index f76624ee82ef..49b4499269fb 100644
--- a/drivers/edac/i5400_edac.c
+++ b/drivers/edac/i5400_edac.c
@@ -279,7 +279,8 @@ static inline int from_nf_ferr(unsigned int mask)
#define FERR_NF_RECOVERABLE to_nf_mask(ERROR_NF_RECOVERABLE)
#define FERR_NF_UNCORRECTABLE to_nf_mask(ERROR_NF_UNCORRECTABLE)
-/* Defines to extract the vaious fields from the
+/*
+ * Defines to extract the various fields from the
* MTRx - Memory Technology Registers
*/
#define MTR_DIMMS_PRESENT(mtr) ((mtr) & (1 << 10))
diff --git a/drivers/edac/igen6_edac.c b/drivers/edac/igen6_edac.c
index a07bbfd075d0..544dd19072ea 100644
--- a/drivers/edac/igen6_edac.c
+++ b/drivers/edac/igen6_edac.c
@@ -1271,9 +1271,12 @@ static int __init igen6_init(void)
edac_dbg(2, "\n");
+ if (ghes_get_devices())
+ return -EBUSY;
+
owner = edac_get_owner();
if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR)))
- return -ENODEV;
+ return -EBUSY;
edac_op_state = EDAC_OPSTATE_NMI;
diff --git a/drivers/edac/layerscape_edac.c b/drivers/edac/layerscape_edac.c
index 94cac7686a56..35ceaca578e1 100644
--- a/drivers/edac/layerscape_edac.c
+++ b/drivers/edac/layerscape_edac.c
@@ -38,6 +38,9 @@ static int __init fsl_ddr_mc_init(void)
{
int res;
+ if (ghes_get_devices())
+ return -EBUSY;
+
/* make sure error reporting method is sane */
switch (edac_op_state) {
case EDAC_OPSTATE_POLL:
diff --git a/drivers/edac/pnd2_edac.c b/drivers/edac/pnd2_edac.c
index a20b299f1202..2b306f2cc605 100644
--- a/drivers/edac/pnd2_edac.c
+++ b/drivers/edac/pnd2_edac.c
@@ -1528,6 +1528,9 @@ static int __init pnd2_init(void)
edac_dbg(2, "\n");
+ if (ghes_get_devices())
+ return -EBUSY;
+
owner = edac_get_owner();
if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR)))
return -EBUSY;
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index 8e39370fdb5c..0c779a0326b6 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -3634,6 +3634,9 @@ static int __init sbridge_init(void)
edac_dbg(2, "\n");
+ if (ghes_get_devices())
+ return -EBUSY;
+
owner = edac_get_owner();
if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR)))
return -EBUSY;
diff --git a/drivers/edac/skx_base.c b/drivers/edac/skx_base.c
index 7e2762f62eec..9397abb42c49 100644
--- a/drivers/edac/skx_base.c
+++ b/drivers/edac/skx_base.c
@@ -653,6 +653,9 @@ static int __init skx_init(void)
edac_dbg(2, "\n");
+ if (ghes_get_devices())
+ return -EBUSY;
+
owner = edac_get_owner();
if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR)))
return -EBUSY;
diff --git a/drivers/edac/thunderx_edac.c b/drivers/edac/thunderx_edac.c
index f13674081cb6..0bcd9f02c84a 100644
--- a/drivers/edac/thunderx_edac.c
+++ b/drivers/edac/thunderx_edac.c
@@ -2114,6 +2114,9 @@ static int __init thunderx_edac_init(void)
{
int rc = 0;
+ if (ghes_get_devices())
+ return -EBUSY;
+
rc = pci_register_driver(&thunderx_lmc_driver);
if (rc)
return rc;
diff --git a/drivers/edac/xgene_edac.c b/drivers/edac/xgene_edac.c
index 54081403db4f..c52b9dd9154c 100644
--- a/drivers/edac/xgene_edac.c
+++ b/drivers/edac/xgene_edac.c
@@ -2004,6 +2004,9 @@ static int __init xgene_edac_init(void)
{
int rc;
+ if (ghes_get_devices())
+ return -EBUSY;
+
/* Make sure error reporting method is sane */
switch (edac_op_state) {
case EDAC_OPSTATE_POLL:
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index d5e86ef40b89..fa85c64d3ded 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -36,81 +36,6 @@
#include "common.h"
#define FFA_DRIVER_VERSION FFA_VERSION_1_0
-
-#define FFA_SMC(calling_convention, func_num) \
- ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, (calling_convention), \
- ARM_SMCCC_OWNER_STANDARD, (func_num))
-
-#define FFA_SMC_32(func_num) FFA_SMC(ARM_SMCCC_SMC_32, (func_num))
-#define FFA_SMC_64(func_num) FFA_SMC(ARM_SMCCC_SMC_64, (func_num))
-
-#define FFA_ERROR FFA_SMC_32(0x60)
-#define FFA_SUCCESS FFA_SMC_32(0x61)
-#define FFA_INTERRUPT FFA_SMC_32(0x62)
-#define FFA_VERSION FFA_SMC_32(0x63)
-#define FFA_FEATURES FFA_SMC_32(0x64)
-#define FFA_RX_RELEASE FFA_SMC_32(0x65)
-#define FFA_RXTX_MAP FFA_SMC_32(0x66)
-#define FFA_FN64_RXTX_MAP FFA_SMC_64(0x66)
-#define FFA_RXTX_UNMAP FFA_SMC_32(0x67)
-#define FFA_PARTITION_INFO_GET FFA_SMC_32(0x68)
-#define FFA_ID_GET FFA_SMC_32(0x69)
-#define FFA_MSG_POLL FFA_SMC_32(0x6A)
-#define FFA_MSG_WAIT FFA_SMC_32(0x6B)
-#define FFA_YIELD FFA_SMC_32(0x6C)
-#define FFA_RUN FFA_SMC_32(0x6D)
-#define FFA_MSG_SEND FFA_SMC_32(0x6E)
-#define FFA_MSG_SEND_DIRECT_REQ FFA_SMC_32(0x6F)
-#define FFA_FN64_MSG_SEND_DIRECT_REQ FFA_SMC_64(0x6F)
-#define FFA_MSG_SEND_DIRECT_RESP FFA_SMC_32(0x70)
-#define FFA_FN64_MSG_SEND_DIRECT_RESP FFA_SMC_64(0x70)
-#define FFA_MEM_DONATE FFA_SMC_32(0x71)
-#define FFA_FN64_MEM_DONATE FFA_SMC_64(0x71)
-#define FFA_MEM_LEND FFA_SMC_32(0x72)
-#define FFA_FN64_MEM_LEND FFA_SMC_64(0x72)
-#define FFA_MEM_SHARE FFA_SMC_32(0x73)
-#define FFA_FN64_MEM_SHARE FFA_SMC_64(0x73)
-#define FFA_MEM_RETRIEVE_REQ FFA_SMC_32(0x74)
-#define FFA_FN64_MEM_RETRIEVE_REQ FFA_SMC_64(0x74)
-#define FFA_MEM_RETRIEVE_RESP FFA_SMC_32(0x75)
-#define FFA_MEM_RELINQUISH FFA_SMC_32(0x76)
-#define FFA_MEM_RECLAIM FFA_SMC_32(0x77)
-#define FFA_MEM_OP_PAUSE FFA_SMC_32(0x78)
-#define FFA_MEM_OP_RESUME FFA_SMC_32(0x79)
-#define FFA_MEM_FRAG_RX FFA_SMC_32(0x7A)
-#define FFA_MEM_FRAG_TX FFA_SMC_32(0x7B)
-#define FFA_NORMAL_WORLD_RESUME FFA_SMC_32(0x7C)
-
-/*
- * For some calls it is necessary to use SMC64 to pass or return 64-bit values.
- * For such calls FFA_FN_NATIVE(name) will choose the appropriate
- * (native-width) function ID.
- */
-#ifdef CONFIG_64BIT
-#define FFA_FN_NATIVE(name) FFA_FN64_##name
-#else
-#define FFA_FN_NATIVE(name) FFA_##name
-#endif
-
-/* FFA error codes. */
-#define FFA_RET_SUCCESS (0)
-#define FFA_RET_NOT_SUPPORTED (-1)
-#define FFA_RET_INVALID_PARAMETERS (-2)
-#define FFA_RET_NO_MEMORY (-3)
-#define FFA_RET_BUSY (-4)
-#define FFA_RET_INTERRUPTED (-5)
-#define FFA_RET_DENIED (-6)
-#define FFA_RET_RETRY (-7)
-#define FFA_RET_ABORTED (-8)
-
-#define MAJOR_VERSION_MASK GENMASK(30, 16)
-#define MINOR_VERSION_MASK GENMASK(15, 0)
-#define MAJOR_VERSION(x) ((u16)(FIELD_GET(MAJOR_VERSION_MASK, (x))))
-#define MINOR_VERSION(x) ((u16)(FIELD_GET(MINOR_VERSION_MASK, (x))))
-#define PACK_VERSION_INFO(major, minor) \
- (FIELD_PREP(MAJOR_VERSION_MASK, (major)) | \
- FIELD_PREP(MINOR_VERSION_MASK, (minor)))
-#define FFA_VERSION_1_0 PACK_VERSION_INFO(1, 0)
#define FFA_MIN_VERSION FFA_VERSION_1_0
#define SENDER_ID_MASK GENMASK(31, 16)
@@ -121,12 +46,6 @@
(FIELD_PREP(SENDER_ID_MASK, (s)) | FIELD_PREP(RECEIVER_ID_MASK, (r)))
/*
- * FF-A specification mentions explicitly about '4K pages'. This should
- * not be confused with the kernel PAGE_SIZE, which is the translation
- * granule kernel is configured and may be one among 4K, 16K and 64K.
- */
-#define FFA_PAGE_SIZE SZ_4K
-/*
* Keeping RX TX buffer size as 4K for now
* 64K may be preferred to keep it min a page in 64K PAGE_SIZE config
*/
@@ -178,9 +97,9 @@ static struct ffa_drv_info *drv_info;
*/
static u32 ffa_compatible_version_find(u32 version)
{
- u16 major = MAJOR_VERSION(version), minor = MINOR_VERSION(version);
- u16 drv_major = MAJOR_VERSION(FFA_DRIVER_VERSION);
- u16 drv_minor = MINOR_VERSION(FFA_DRIVER_VERSION);
+ u16 major = FFA_MAJOR_VERSION(version), minor = FFA_MINOR_VERSION(version);
+ u16 drv_major = FFA_MAJOR_VERSION(FFA_DRIVER_VERSION);
+ u16 drv_minor = FFA_MINOR_VERSION(FFA_DRIVER_VERSION);
if ((major < drv_major) || (major == drv_major && minor <= drv_minor))
return version;
@@ -204,16 +123,16 @@ static int ffa_version_check(u32 *version)
if (ver.a0 < FFA_MIN_VERSION) {
pr_err("Incompatible v%d.%d! Earliest supported v%d.%d\n",
- MAJOR_VERSION(ver.a0), MINOR_VERSION(ver.a0),
- MAJOR_VERSION(FFA_MIN_VERSION),
- MINOR_VERSION(FFA_MIN_VERSION));
+ FFA_MAJOR_VERSION(ver.a0), FFA_MINOR_VERSION(ver.a0),
+ FFA_MAJOR_VERSION(FFA_MIN_VERSION),
+ FFA_MINOR_VERSION(FFA_MIN_VERSION));
return -EINVAL;
}
- pr_info("Driver version %d.%d\n", MAJOR_VERSION(FFA_DRIVER_VERSION),
- MINOR_VERSION(FFA_DRIVER_VERSION));
- pr_info("Firmware version %d.%d found\n", MAJOR_VERSION(ver.a0),
- MINOR_VERSION(ver.a0));
+ pr_info("Driver version %d.%d\n", FFA_MAJOR_VERSION(FFA_DRIVER_VERSION),
+ FFA_MINOR_VERSION(FFA_DRIVER_VERSION));
+ pr_info("Firmware version %d.%d found\n", FFA_MAJOR_VERSION(ver.a0),
+ FFA_MINOR_VERSION(ver.a0));
*version = ffa_compatible_version_find(ver.a0);
return 0;
diff --git a/drivers/firmware/broadcom/bcm47xx_nvram.c b/drivers/firmware/broadcom/bcm47xx_nvram.c
index bd235833b687..5f47dbf4889a 100644
--- a/drivers/firmware/broadcom/bcm47xx_nvram.c
+++ b/drivers/firmware/broadcom/bcm47xx_nvram.c
@@ -110,6 +110,24 @@ found:
return 0;
}
+int bcm47xx_nvram_init_from_iomem(void __iomem *nvram_start, size_t res_size)
+{
+ if (nvram_len) {
+ pr_warn("nvram already initialized\n");
+ return -EEXIST;
+ }
+
+ if (!bcm47xx_nvram_is_valid(nvram_start)) {
+ pr_err("No valid NVRAM found\n");
+ return -ENOENT;
+ }
+
+ bcm47xx_nvram_copy(nvram_start, res_size);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(bcm47xx_nvram_init_from_iomem);
+
/*
* On bcm47xx we need access to the NVRAM very early, so we can't use mtd
* subsystem to access flash. We can't even use platform device / driver to
diff --git a/drivers/firmware/cirrus/Kconfig b/drivers/firmware/cirrus/Kconfig
index f9503cb481d2..3ccbe14e4b0c 100644
--- a/drivers/firmware/cirrus/Kconfig
+++ b/drivers/firmware/cirrus/Kconfig
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
-config CS_DSP
+config FW_CS_DSP
tristate
default n
diff --git a/drivers/firmware/cirrus/Makefile b/drivers/firmware/cirrus/Makefile
index f074e2638c9c..b91318ca0ff4 100644
--- a/drivers/firmware/cirrus/Makefile
+++ b/drivers/firmware/cirrus/Makefile
@@ -1,3 +1,3 @@
# SPDX-License-Identifier: GPL-2.0
#
-obj-$(CONFIG_CS_DSP) += cs_dsp.o
+obj-$(CONFIG_FW_CS_DSP) += cs_dsp.o
diff --git a/drivers/firmware/cirrus/cs_dsp.c b/drivers/firmware/cirrus/cs_dsp.c
index 81cc3d0f6eec..f558b390fbfe 100644
--- a/drivers/firmware/cirrus/cs_dsp.c
+++ b/drivers/firmware/cirrus/cs_dsp.c
@@ -369,7 +369,7 @@ const char *cs_dsp_mem_region_name(unsigned int type)
return NULL;
}
}
-EXPORT_SYMBOL_GPL(cs_dsp_mem_region_name);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_mem_region_name, FW_CS_DSP);
#ifdef CONFIG_DEBUG_FS
static void cs_dsp_debugfs_save_wmfwname(struct cs_dsp *dsp, const char *s)
@@ -480,7 +480,7 @@ void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root)
dsp->debugfs_root = root;
}
-EXPORT_SYMBOL_GPL(cs_dsp_init_debugfs);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_init_debugfs, FW_CS_DSP);
/**
* cs_dsp_cleanup_debugfs() - Removes DSP representation from debugfs
@@ -492,17 +492,17 @@ void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp)
debugfs_remove_recursive(dsp->debugfs_root);
dsp->debugfs_root = NULL;
}
-EXPORT_SYMBOL_GPL(cs_dsp_cleanup_debugfs);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_cleanup_debugfs, FW_CS_DSP);
#else
void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root)
{
}
-EXPORT_SYMBOL_GPL(cs_dsp_init_debugfs);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_init_debugfs, FW_CS_DSP);
void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp)
{
}
-EXPORT_SYMBOL_GPL(cs_dsp_cleanup_debugfs);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_cleanup_debugfs, FW_CS_DSP);
static inline void cs_dsp_debugfs_save_wmfwname(struct cs_dsp *dsp,
const char *s)
@@ -710,7 +710,7 @@ int cs_dsp_coeff_write_acked_control(struct cs_dsp_coeff_ctl *ctl, unsigned int
return -ETIMEDOUT;
}
-EXPORT_SYMBOL_GPL(cs_dsp_coeff_write_acked_control);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_coeff_write_acked_control, FW_CS_DSP);
static int cs_dsp_coeff_write_ctrl_raw(struct cs_dsp_coeff_ctl *ctl,
unsigned int off, const void *buf, size_t len)
@@ -752,7 +752,7 @@ static int cs_dsp_coeff_write_ctrl_raw(struct cs_dsp_coeff_ctl *ctl,
*
* Must be called with pwr_lock held.
*
- * Return: Zero for success, a negative number on error.
+ * Return: < 0 on error, 1 when the control value changed and 0 when it has not.
*/
int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl,
unsigned int off, const void *buf, size_t len)
@@ -767,18 +767,25 @@ int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl,
if (len + off * sizeof(u32) > ctl->len)
return -EINVAL;
- if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
+ if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
ret = -EPERM;
- else if (buf != ctl->cache)
- memcpy(ctl->cache + off * sizeof(u32), buf, len);
+ } else if (buf != ctl->cache) {
+ if (memcmp(ctl->cache + off * sizeof(u32), buf, len))
+ memcpy(ctl->cache + off * sizeof(u32), buf, len);
+ else
+ return 0;
+ }
ctl->set = 1;
if (ctl->enabled && ctl->dsp->running)
ret = cs_dsp_coeff_write_ctrl_raw(ctl, off, buf, len);
- return ret;
+ if (ret < 0)
+ return ret;
+
+ return 1;
}
-EXPORT_SYMBOL_GPL(cs_dsp_coeff_write_ctrl);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_coeff_write_ctrl, FW_CS_DSP);
static int cs_dsp_coeff_read_ctrl_raw(struct cs_dsp_coeff_ctl *ctl,
unsigned int off, void *buf, size_t len)
@@ -850,7 +857,7 @@ int cs_dsp_coeff_read_ctrl(struct cs_dsp_coeff_ctl *ctl,
return ret;
}
-EXPORT_SYMBOL_GPL(cs_dsp_coeff_read_ctrl);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_coeff_read_ctrl, FW_CS_DSP);
static int cs_dsp_coeff_init_control_caches(struct cs_dsp *dsp)
{
@@ -1493,7 +1500,7 @@ struct cs_dsp_coeff_ctl *cs_dsp_get_ctl(struct cs_dsp *dsp, const char *name, in
return rslt;
}
-EXPORT_SYMBOL_GPL(cs_dsp_get_ctl);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_get_ctl, FW_CS_DSP);
static void cs_dsp_ctl_fixup_base(struct cs_dsp *dsp,
const struct cs_dsp_alg_region *alg_region)
@@ -1583,7 +1590,7 @@ struct cs_dsp_alg_region *cs_dsp_find_alg_region(struct cs_dsp *dsp,
return NULL;
}
-EXPORT_SYMBOL_GPL(cs_dsp_find_alg_region);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_find_alg_region, FW_CS_DSP);
static struct cs_dsp_alg_region *cs_dsp_create_region(struct cs_dsp *dsp,
int type, __be32 id,
@@ -2217,7 +2224,7 @@ int cs_dsp_adsp1_init(struct cs_dsp *dsp)
return cs_dsp_common_init(dsp);
}
-EXPORT_SYMBOL_GPL(cs_dsp_adsp1_init);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp1_init, FW_CS_DSP);
/**
* cs_dsp_adsp1_power_up() - Load and start the named firmware
@@ -2309,7 +2316,7 @@ err_mutex:
mutex_unlock(&dsp->pwr_lock);
return ret;
}
-EXPORT_SYMBOL_GPL(cs_dsp_adsp1_power_up);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp1_power_up, FW_CS_DSP);
/**
* cs_dsp_adsp1_power_down() - Halts the DSP
@@ -2341,7 +2348,7 @@ void cs_dsp_adsp1_power_down(struct cs_dsp *dsp)
mutex_unlock(&dsp->pwr_lock);
}
-EXPORT_SYMBOL_GPL(cs_dsp_adsp1_power_down);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp1_power_down, FW_CS_DSP);
static int cs_dsp_adsp2v2_enable_core(struct cs_dsp *dsp)
{
@@ -2493,7 +2500,7 @@ int cs_dsp_set_dspclk(struct cs_dsp *dsp, unsigned int freq)
return ret;
}
-EXPORT_SYMBOL_GPL(cs_dsp_set_dspclk);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_set_dspclk, FW_CS_DSP);
static void cs_dsp_stop_watchdog(struct cs_dsp *dsp)
{
@@ -2583,7 +2590,7 @@ err_mutex:
return ret;
}
-EXPORT_SYMBOL_GPL(cs_dsp_power_up);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_power_up, FW_CS_DSP);
/**
* cs_dsp_power_down() - Powers-down the DSP
@@ -2617,7 +2624,7 @@ void cs_dsp_power_down(struct cs_dsp *dsp)
cs_dsp_dbg(dsp, "Shutdown complete\n");
}
-EXPORT_SYMBOL_GPL(cs_dsp_power_down);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_power_down, FW_CS_DSP);
static int cs_dsp_adsp2_start_core(struct cs_dsp *dsp)
{
@@ -2703,7 +2710,7 @@ err:
return ret;
}
-EXPORT_SYMBOL_GPL(cs_dsp_run);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_run, FW_CS_DSP);
/**
* cs_dsp_stop() - Stops the firmware
@@ -2742,7 +2749,7 @@ void cs_dsp_stop(struct cs_dsp *dsp)
cs_dsp_dbg(dsp, "Execution stopped\n");
}
-EXPORT_SYMBOL_GPL(cs_dsp_stop);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_stop, FW_CS_DSP);
static int cs_dsp_halo_start_core(struct cs_dsp *dsp)
{
@@ -2804,7 +2811,7 @@ int cs_dsp_adsp2_init(struct cs_dsp *dsp)
return cs_dsp_common_init(dsp);
}
-EXPORT_SYMBOL_GPL(cs_dsp_adsp2_init);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp2_init, FW_CS_DSP);
/**
* cs_dsp_halo_init() - Initialise a cs_dsp structure representing a HALO Core DSP
@@ -2818,7 +2825,7 @@ int cs_dsp_halo_init(struct cs_dsp *dsp)
return cs_dsp_common_init(dsp);
}
-EXPORT_SYMBOL_GPL(cs_dsp_halo_init);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_halo_init, FW_CS_DSP);
/**
* cs_dsp_remove() - Clean a cs_dsp before deletion
@@ -2838,7 +2845,7 @@ void cs_dsp_remove(struct cs_dsp *dsp)
cs_dsp_free_ctl_blk(ctl);
}
}
-EXPORT_SYMBOL_GPL(cs_dsp_remove);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_remove, FW_CS_DSP);
/**
* cs_dsp_read_raw_data_block() - Reads a block of data from DSP memory
@@ -2875,7 +2882,7 @@ int cs_dsp_read_raw_data_block(struct cs_dsp *dsp, int mem_type, unsigned int me
return 0;
}
-EXPORT_SYMBOL_GPL(cs_dsp_read_raw_data_block);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_read_raw_data_block, FW_CS_DSP);
/**
* cs_dsp_read_data_word() - Reads a word from DSP memory
@@ -2899,7 +2906,7 @@ int cs_dsp_read_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_add
return 0;
}
-EXPORT_SYMBOL_GPL(cs_dsp_read_data_word);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_read_data_word, FW_CS_DSP);
/**
* cs_dsp_write_data_word() - Writes a word to DSP memory
@@ -2925,7 +2932,7 @@ int cs_dsp_write_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_ad
return regmap_raw_write(dsp->regmap, reg, &val, sizeof(val));
}
-EXPORT_SYMBOL_GPL(cs_dsp_write_data_word);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_write_data_word, FW_CS_DSP);
/**
* cs_dsp_remove_padding() - Convert unpacked words to packed bytes
@@ -2949,7 +2956,7 @@ void cs_dsp_remove_padding(u32 *buf, int nwords)
*pack_out++ = (u8)(word >> 16);
}
}
-EXPORT_SYMBOL_GPL(cs_dsp_remove_padding);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_remove_padding, FW_CS_DSP);
/**
* cs_dsp_adsp2_bus_error() - Handle a DSP bus error interrupt
@@ -3019,7 +3026,7 @@ void cs_dsp_adsp2_bus_error(struct cs_dsp *dsp)
error:
mutex_unlock(&dsp->pwr_lock);
}
-EXPORT_SYMBOL_GPL(cs_dsp_adsp2_bus_error);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp2_bus_error, FW_CS_DSP);
/**
* cs_dsp_halo_bus_error() - Handle a DSP bus error interrupt
@@ -3079,7 +3086,7 @@ void cs_dsp_halo_bus_error(struct cs_dsp *dsp)
exit_unlock:
mutex_unlock(&dsp->pwr_lock);
}
-EXPORT_SYMBOL_GPL(cs_dsp_halo_bus_error);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_halo_bus_error, FW_CS_DSP);
/**
* cs_dsp_halo_wdt_expire() - Handle DSP watchdog expiry
@@ -3099,7 +3106,7 @@ void cs_dsp_halo_wdt_expire(struct cs_dsp *dsp)
mutex_unlock(&dsp->pwr_lock);
}
-EXPORT_SYMBOL_GPL(cs_dsp_halo_wdt_expire);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_halo_wdt_expire, FW_CS_DSP);
static const struct cs_dsp_ops cs_dsp_adsp1_ops = {
.validate_version = cs_dsp_validate_version,
@@ -3221,7 +3228,7 @@ int cs_dsp_chunk_write(struct cs_dsp_chunk *ch, int nbits, u32 val)
return 0;
}
-EXPORT_SYMBOL_GPL(cs_dsp_chunk_write);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_chunk_write, FW_CS_DSP);
/**
* cs_dsp_chunk_flush() - Pad remaining data with zero and commit to chunk
@@ -3240,7 +3247,7 @@ int cs_dsp_chunk_flush(struct cs_dsp_chunk *ch)
return cs_dsp_chunk_write(ch, CS_DSP_DATA_WORD_BITS - ch->cachebits, 0);
}
-EXPORT_SYMBOL_GPL(cs_dsp_chunk_flush);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_chunk_flush, FW_CS_DSP);
/**
* cs_dsp_chunk_read() - Parse data from a DSP memory chunk
@@ -3282,7 +3289,7 @@ int cs_dsp_chunk_read(struct cs_dsp_chunk *ch, int nbits)
return result;
}
-EXPORT_SYMBOL_GPL(cs_dsp_chunk_read);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_chunk_read, FW_CS_DSP);
MODULE_DESCRIPTION("Cirrus Logic DSP Support");
MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 6787ed8dfacf..043ca31c114e 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -26,39 +26,6 @@ config EFI_VARS_PSTORE_DEFAULT_DISABLE
backend for pstore by default. This setting can be overridden
using the efivars module's pstore_disable parameter.
-config EFI_RUNTIME_MAP
- bool "Export efi runtime maps to sysfs"
- depends on X86 && EFI && KEXEC_CORE
- default y
- help
- Export efi runtime memory maps to /sys/firmware/efi/runtime-map.
- That memory map is used for example by kexec to set up efi virtual
- mapping the 2nd kernel, but can also be used for debugging purposes.
-
- See also Documentation/ABI/testing/sysfs-firmware-efi-runtime-map.
-
-config EFI_FAKE_MEMMAP
- bool "Enable EFI fake memory map"
- depends on EFI && X86
- default n
- help
- Saying Y here will enable "efi_fake_mem" boot option.
- By specifying this parameter, you can add arbitrary attribute
- to specific memory range by updating original (firmware provided)
- EFI memmap.
- This is useful for debugging of EFI memmap related feature.
- e.g. Address Range Mirroring feature.
-
-config EFI_MAX_FAKE_MEM
- int "maximum allowable number of ranges in efi_fake_mem boot option"
- depends on EFI_FAKE_MEMMAP
- range 1 128
- default 8
- help
- Maximum allowable number of ranges in efi_fake_mem boot option.
- Ranges can be set up to this value using comma-separated list.
- The default value is 8.
-
config EFI_SOFT_RESERVE
bool "Reserve EFI Specific Purpose Memory"
depends on EFI && EFI_STUB && ACPI_HMAT
@@ -139,18 +106,6 @@ config EFI_ARMSTUB_DTB_LOADER
functionality for bootloaders that do not have such support
this option is necessary.
-config EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER
- bool "Enable the command line initrd loader" if !X86
- depends on EFI_STUB && (EFI_GENERIC_STUB || X86)
- default y if X86
- depends on !RISCV && !LOONGARCH
- help
- Select this config option to add support for the initrd= command
- line parameter, allowing an initrd that resides on the same volume
- as the kernel image to be loaded into memory.
-
- This method is deprecated.
-
config EFI_BOOTLOADER_CONTROL
tristate "EFI Bootloader Control"
select UCS2_STRING
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index 8d151e332584..b51f2a4c821e 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -19,11 +19,9 @@ endif
obj-$(CONFIG_EFI_PARAMS_FROM_FDT) += fdtparams.o
obj-$(CONFIG_EFI_ESRT) += esrt.o
obj-$(CONFIG_EFI_VARS_PSTORE) += efi-pstore.o
-obj-$(CONFIG_UEFI_CPER) += cper.o
-obj-$(CONFIG_EFI_RUNTIME_MAP) += runtime-map.o
+obj-$(CONFIG_UEFI_CPER) += cper.o cper_cxl.o
obj-$(CONFIG_EFI_RUNTIME_WRAPPERS) += runtime-wrappers.o
subdir-$(CONFIG_EFI_STUB) += libstub
-obj-$(CONFIG_EFI_FAKE_MEMMAP) += fake_map.o
obj-$(CONFIG_EFI_BOOTLOADER_CONTROL) += efibc.o
obj-$(CONFIG_EFI_TEST) += test/
obj-$(CONFIG_EFI_DEV_PATH_PARSER) += dev-path-parser.o
@@ -32,9 +30,6 @@ obj-$(CONFIG_EFI_RCI2_TABLE) += rci2-table.o
obj-$(CONFIG_EFI_EMBEDDED_FIRMWARE) += embedded-firmware.o
obj-$(CONFIG_LOAD_UEFI_KEYS) += mokvar-table.o
-fake_map-y += fake_mem.o
-fake_map-$(CONFIG_X86) += x86_fake_mem.o
-
obj-$(CONFIG_SYSFB) += sysfb_efi.o
arm-obj-$(CONFIG_EFI) := efi-init.o arm-runtime.o
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
index 7c48c380d722..83f5bb57fa4c 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -25,14 +25,14 @@
#include <asm/mmu.h>
#include <asm/pgalloc.h>
-#if defined(CONFIG_PTDUMP_DEBUGFS) && defined(CONFIG_ARM64)
+#if defined(CONFIG_PTDUMP_DEBUGFS) || defined(CONFIG_ARM_PTDUMP_DEBUGFS)
#include <asm/ptdump.h>
static struct ptdump_info efi_ptdump_info = {
.mm = &efi_mm,
.markers = (struct addr_marker[]){
{ 0, "UEFI runtime start" },
- { DEFAULT_MAP_WINDOW_64, "UEFI runtime end" },
+ { EFI_RUNTIME_MAP_END, "UEFI runtime end" },
{ -1, NULL }
},
.base_addr = 0,
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index e4e5ea7ce910..35c37f667781 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -24,6 +24,7 @@
#include <linux/bcd.h>
#include <acpi/ghes.h>
#include <ras/ras_event.h>
+#include "cper_cxl.h"
/*
* CPER record ID need to be unique even after reboot, because record
@@ -290,6 +291,7 @@ int cper_mem_err_location(struct cper_mem_err_compact *mem, char *msg)
return n;
}
+EXPORT_SYMBOL_GPL(cper_mem_err_location);
int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg)
{
@@ -310,6 +312,7 @@ int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg)
return n;
}
+EXPORT_SYMBOL_GPL(cper_dimm_err_location);
void cper_mem_err_pack(const struct cper_sec_mem_err *mem,
struct cper_mem_err_compact *cmem)
@@ -331,6 +334,7 @@ void cper_mem_err_pack(const struct cper_sec_mem_err *mem,
cmem->mem_array_handle = mem->mem_array_handle;
cmem->mem_dev_handle = mem->mem_dev_handle;
}
+EXPORT_SYMBOL_GPL(cper_mem_err_pack);
const char *cper_mem_err_unpack(struct trace_seq *p,
struct cper_mem_err_compact *cmem)
@@ -595,6 +599,14 @@ cper_estatus_print_section(const char *pfx, struct acpi_hest_generic_data *gdata
cper_print_fw_err(newpfx, gdata, fw_err);
else
goto err_section_too_small;
+ } else if (guid_equal(sec_type, &CPER_SEC_CXL_PROT_ERR)) {
+ struct cper_sec_prot_err *prot_err = acpi_hest_get_payload(gdata);
+
+ printk("%ssection_type: CXL Protocol Error\n", newpfx);
+ if (gdata->error_data_length >= sizeof(*prot_err))
+ cper_print_prot_err(newpfx, prot_err);
+ else
+ goto err_section_too_small;
} else {
const void *err = acpi_hest_get_payload(gdata);
diff --git a/drivers/firmware/efi/cper_cxl.c b/drivers/firmware/efi/cper_cxl.c
new file mode 100644
index 000000000000..53e435c4f310
--- /dev/null
+++ b/drivers/firmware/efi/cper_cxl.c
@@ -0,0 +1,179 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * UEFI Common Platform Error Record (CPER) support for CXL Section.
+ *
+ * Copyright (C) 2022 Advanced Micro Devices, Inc.
+ *
+ * Author: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com>
+ */
+
+#include <linux/cper.h>
+#include "cper_cxl.h"
+#include <linux/cxl_err.h>
+
+#define PROT_ERR_VALID_AGENT_TYPE BIT_ULL(0)
+#define PROT_ERR_VALID_AGENT_ADDRESS BIT_ULL(1)
+#define PROT_ERR_VALID_DEVICE_ID BIT_ULL(2)
+#define PROT_ERR_VALID_SERIAL_NUMBER BIT_ULL(3)
+#define PROT_ERR_VALID_CAPABILITY BIT_ULL(4)
+#define PROT_ERR_VALID_DVSEC BIT_ULL(5)
+#define PROT_ERR_VALID_ERROR_LOG BIT_ULL(6)
+
+static const char * const prot_err_agent_type_strs[] = {
+ "Restricted CXL Device",
+ "Restricted CXL Host Downstream Port",
+ "CXL Device",
+ "CXL Logical Device",
+ "CXL Fabric Manager managed Logical Device",
+ "CXL Root Port",
+ "CXL Downstream Switch Port",
+ "CXL Upstream Switch Port",
+};
+
+/*
+ * The layout of the enumeration and the values matches CXL Agent Type
+ * field in the UEFI 2.10 Section N.2.13,
+ */
+enum {
+ RCD, /* Restricted CXL Device */
+ RCH_DP, /* Restricted CXL Host Downstream Port */
+ DEVICE, /* CXL Device */
+ LD, /* CXL Logical Device */
+ FMLD, /* CXL Fabric Manager managed Logical Device */
+ RP, /* CXL Root Port */
+ DSP, /* CXL Downstream Switch Port */
+ USP, /* CXL Upstream Switch Port */
+};
+
+void cper_print_prot_err(const char *pfx, const struct cper_sec_prot_err *prot_err)
+{
+ if (prot_err->valid_bits & PROT_ERR_VALID_AGENT_TYPE)
+ pr_info("%s agent_type: %d, %s\n", pfx, prot_err->agent_type,
+ prot_err->agent_type < ARRAY_SIZE(prot_err_agent_type_strs)
+ ? prot_err_agent_type_strs[prot_err->agent_type]
+ : "unknown");
+
+ if (prot_err->valid_bits & PROT_ERR_VALID_AGENT_ADDRESS) {
+ switch (prot_err->agent_type) {
+ /*
+ * According to UEFI 2.10 Section N.2.13, the term CXL Device
+ * is used to refer to Restricted CXL Device, CXL Device, CXL
+ * Logical Device or a CXL Fabric Manager Managed Logical
+ * Device.
+ */
+ case RCD:
+ case DEVICE:
+ case LD:
+ case FMLD:
+ case RP:
+ case DSP:
+ case USP:
+ pr_info("%s agent_address: %04x:%02x:%02x.%x\n",
+ pfx, prot_err->agent_addr.segment,
+ prot_err->agent_addr.bus,
+ prot_err->agent_addr.device,
+ prot_err->agent_addr.function);
+ break;
+ case RCH_DP:
+ pr_info("%s rcrb_base_address: 0x%016llx\n", pfx,
+ prot_err->agent_addr.rcrb_base_addr);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (prot_err->valid_bits & PROT_ERR_VALID_DEVICE_ID) {
+ const __u8 *class_code;
+
+ switch (prot_err->agent_type) {
+ case RCD:
+ case DEVICE:
+ case LD:
+ case FMLD:
+ case RP:
+ case DSP:
+ case USP:
+ pr_info("%s slot: %d\n", pfx,
+ prot_err->device_id.slot >> CPER_PCIE_SLOT_SHIFT);
+ pr_info("%s vendor_id: 0x%04x, device_id: 0x%04x\n",
+ pfx, prot_err->device_id.vendor_id,
+ prot_err->device_id.device_id);
+ pr_info("%s sub_vendor_id: 0x%04x, sub_device_id: 0x%04x\n",
+ pfx, prot_err->device_id.subsystem_vendor_id,
+ prot_err->device_id.subsystem_id);
+ class_code = prot_err->device_id.class_code;
+ pr_info("%s class_code: %02x%02x\n", pfx,
+ class_code[1], class_code[0]);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (prot_err->valid_bits & PROT_ERR_VALID_SERIAL_NUMBER) {
+ switch (prot_err->agent_type) {
+ case RCD:
+ case DEVICE:
+ case LD:
+ case FMLD:
+ pr_info("%s lower_dw: 0x%08x, upper_dw: 0x%08x\n", pfx,
+ prot_err->dev_serial_num.lower_dw,
+ prot_err->dev_serial_num.upper_dw);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (prot_err->valid_bits & PROT_ERR_VALID_CAPABILITY) {
+ switch (prot_err->agent_type) {
+ case RCD:
+ case DEVICE:
+ case LD:
+ case FMLD:
+ case RP:
+ case DSP:
+ case USP:
+ print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4,
+ prot_err->capability,
+ sizeof(prot_err->capability), 0);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (prot_err->valid_bits & PROT_ERR_VALID_DVSEC) {
+ pr_info("%s DVSEC length: 0x%04x\n", pfx, prot_err->dvsec_len);
+
+ pr_info("%s CXL DVSEC:\n", pfx);
+ print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, (prot_err + 1),
+ prot_err->dvsec_len, 0);
+ }
+
+ if (prot_err->valid_bits & PROT_ERR_VALID_ERROR_LOG) {
+ size_t size = sizeof(*prot_err) + prot_err->dvsec_len;
+ struct cxl_ras_capability_regs *cxl_ras;
+
+ pr_info("%s Error log length: 0x%04x\n", pfx, prot_err->err_len);
+
+ pr_info("%s CXL Error Log:\n", pfx);
+ cxl_ras = (struct cxl_ras_capability_regs *)((long)prot_err + size);
+ pr_info("%s cxl_ras_uncor_status: 0x%08x", pfx,
+ cxl_ras->uncor_status);
+ pr_info("%s cxl_ras_uncor_mask: 0x%08x\n", pfx,
+ cxl_ras->uncor_mask);
+ pr_info("%s cxl_ras_uncor_severity: 0x%08x\n", pfx,
+ cxl_ras->uncor_severity);
+ pr_info("%s cxl_ras_cor_status: 0x%08x", pfx,
+ cxl_ras->cor_status);
+ pr_info("%s cxl_ras_cor_mask: 0x%08x\n", pfx,
+ cxl_ras->cor_mask);
+ pr_info("%s cap_control: 0x%08x\n", pfx,
+ cxl_ras->cap_control);
+ pr_info("%s Header Log Registers:\n", pfx);
+ print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, cxl_ras->header_log,
+ sizeof(cxl_ras->header_log), 0);
+ }
+}
diff --git a/drivers/firmware/efi/cper_cxl.h b/drivers/firmware/efi/cper_cxl.h
new file mode 100644
index 000000000000..86bfcf7909ec
--- /dev/null
+++ b/drivers/firmware/efi/cper_cxl.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * UEFI Common Platform Error Record (CPER) support for CXL Section.
+ *
+ * Copyright (C) 2022 Advanced Micro Devices, Inc.
+ *
+ * Author: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com>
+ */
+
+#ifndef LINUX_CPER_CXL_H
+#define LINUX_CPER_CXL_H
+
+/* CXL Protocol Error Section */
+#define CPER_SEC_CXL_PROT_ERR \
+ GUID_INIT(0x80B9EFB4, 0x52B5, 0x4DE3, 0xA7, 0x77, 0x68, 0x78, \
+ 0x4B, 0x77, 0x10, 0x48)
+
+#pragma pack(1)
+
+/* Compute Express Link Protocol Error Section, UEFI v2.10 sec N.2.13 */
+struct cper_sec_prot_err {
+ u64 valid_bits;
+ u8 agent_type;
+ u8 reserved[7];
+
+ /*
+ * Except for RCH Downstream Port, all the remaining CXL Agent
+ * types are uniquely identified by the PCIe compatible SBDF number.
+ */
+ union {
+ u64 rcrb_base_addr;
+ struct {
+ u8 function;
+ u8 device;
+ u8 bus;
+ u16 segment;
+ u8 reserved_1[3];
+ };
+ } agent_addr;
+
+ struct {
+ u16 vendor_id;
+ u16 device_id;
+ u16 subsystem_vendor_id;
+ u16 subsystem_id;
+ u8 class_code[2];
+ u16 slot;
+ u8 reserved_1[4];
+ } device_id;
+
+ struct {
+ u32 lower_dw;
+ u32 upper_dw;
+ } dev_serial_num;
+
+ u8 capability[60];
+ u16 dvsec_len;
+ u16 err_len;
+ u8 reserved_2[4];
+};
+
+#pragma pack()
+
+void cper_print_prot_err(const char *pfx, const struct cper_sec_prot_err *prot_err);
+
+#endif //__CPER_CXL_
diff --git a/drivers/firmware/efi/earlycon.c b/drivers/firmware/efi/earlycon.c
index a52236e11e5f..4d6c5327471a 100644
--- a/drivers/firmware/efi/earlycon.c
+++ b/drivers/firmware/efi/earlycon.c
@@ -29,8 +29,8 @@ static void *efi_fb;
*/
static int __init efi_earlycon_remap_fb(void)
{
- /* bail if there is no bootconsole or it has been disabled already */
- if (!earlycon_console || !(earlycon_console->flags & CON_ENABLED))
+ /* bail if there is no bootconsole or it was unregistered already */
+ if (!earlycon_console || !console_is_registered(earlycon_console))
return 0;
efi_fb = memremap(fb_base, screen_info.lfb_size,
@@ -42,8 +42,8 @@ early_initcall(efi_earlycon_remap_fb);
static int __init efi_earlycon_unmap_fb(void)
{
- /* unmap the bootconsole fb unless keep_bootcon has left it enabled */
- if (efi_fb && !(earlycon_console->flags & CON_ENABLED))
+ /* unmap the bootconsole fb unless keep_bootcon left it registered */
+ if (efi_fb && !console_is_registered(earlycon_console))
memunmap(efi_fb);
return 0;
}
diff --git a/drivers/firmware/efi/efi-init.c b/drivers/firmware/efi/efi-init.c
index 2fd770b499a3..1639159493e3 100644
--- a/drivers/firmware/efi/efi-init.c
+++ b/drivers/firmware/efi/efi-init.c
@@ -22,6 +22,8 @@
#include <asm/efi.h>
+unsigned long __initdata screen_info_table = EFI_INVALID_TABLE_ADDR;
+
static int __init is_memory(efi_memory_desc_t *md)
{
if (md->attribute & (EFI_MEMORY_WB|EFI_MEMORY_WT|EFI_MEMORY_WC))
@@ -55,9 +57,22 @@ extern __weak const efi_config_table_type_t efi_arch_tables[];
static void __init init_screen_info(void)
{
- if (screen_info.orig_video_isVGA == VIDEO_TYPE_EFI &&
- memblock_is_map_memory(screen_info.lfb_base))
- memblock_mark_nomap(screen_info.lfb_base, screen_info.lfb_size);
+ struct screen_info *si;
+
+ if (screen_info_table != EFI_INVALID_TABLE_ADDR) {
+ si = early_memremap(screen_info_table, sizeof(*si));
+ if (!si) {
+ pr_err("Could not map screen_info config table\n");
+ return;
+ }
+ screen_info = *si;
+ memset(si, 0, sizeof(*si));
+ early_memunmap(si, sizeof(*si));
+
+ if (memblock_is_map_memory(screen_info.lfb_base))
+ memblock_mark_nomap(screen_info.lfb_base,
+ screen_info.lfb_size);
+ }
}
static int __init uefi_init(u64 efi_system_table)
diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c
index 3bddc152fcd4..e7b9ec6f8a86 100644
--- a/drivers/firmware/efi/efi-pstore.c
+++ b/drivers/firmware/efi/efi-pstore.c
@@ -10,7 +10,9 @@ MODULE_IMPORT_NS(EFIVAR);
#define DUMP_NAME_LEN 66
-#define EFIVARS_DATA_SIZE_MAX 1024
+static unsigned int record_size = 1024;
+module_param(record_size, uint, 0444);
+MODULE_PARM_DESC(record_size, "size of each pstore UEFI var (in bytes, min/default=1024)");
static bool efivars_pstore_disable =
IS_ENABLED(CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE);
@@ -30,7 +32,7 @@ static int efi_pstore_open(struct pstore_info *psi)
if (err)
return err;
- psi->data = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL);
+ psi->data = kzalloc(record_size, GFP_KERNEL);
if (!psi->data)
return -ENOMEM;
@@ -52,7 +54,7 @@ static inline u64 generic_id(u64 timestamp, unsigned int part, int count)
static int efi_pstore_read_func(struct pstore_record *record,
efi_char16_t *varname)
{
- unsigned long wlen, size = EFIVARS_DATA_SIZE_MAX;
+ unsigned long wlen, size = record_size;
char name[DUMP_NAME_LEN], data_type;
efi_status_t status;
int cnt;
@@ -133,7 +135,7 @@ static ssize_t efi_pstore_read(struct pstore_record *record)
efi_status_t status;
for (;;) {
- varname_size = EFIVARS_DATA_SIZE_MAX;
+ varname_size = 1024;
/*
* If this is the first read() call in the pstore enumeration,
@@ -207,7 +209,7 @@ static int efi_pstore_erase(struct pstore_record *record)
static struct pstore_info efi_pstore_info = {
.owner = THIS_MODULE,
- .name = "efi",
+ .name = KBUILD_MODNAME,
.flags = PSTORE_FLAGS_DMESG,
.open = efi_pstore_open,
.close = efi_pstore_close,
@@ -224,11 +226,20 @@ static __init int efivars_pstore_init(void)
if (efivars_pstore_disable)
return 0;
- efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL);
+ /*
+ * Notice that 1024 is the minimum here to prevent issues with
+ * decompression algorithms that were spotted during tests;
+ * even in the case of not using compression, smaller values would
+ * just pollute more the pstore FS with many small collected files.
+ */
+ if (record_size < 1024)
+ record_size = 1024;
+
+ efi_pstore_info.buf = kmalloc(record_size, GFP_KERNEL);
if (!efi_pstore_info.buf)
return -ENOMEM;
- efi_pstore_info.bufsize = 1024;
+ efi_pstore_info.bufsize = record_size;
if (pstore_register(&efi_pstore_info)) {
kfree(efi_pstore_info.buf);
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index a46df5d1d094..31a4090c66b3 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -58,6 +58,8 @@ static unsigned long __initdata mem_reserve = EFI_INVALID_TABLE_ADDR;
static unsigned long __initdata rt_prop = EFI_INVALID_TABLE_ADDR;
static unsigned long __initdata initrd = EFI_INVALID_TABLE_ADDR;
+extern unsigned long screen_info_table;
+
struct mm_struct efi_mm = {
.mm_mt = MTREE_INIT_EXT(mm_mt, MM_MT_FLAGS, efi_mm.mmap_lock),
.mm_users = ATOMIC_INIT(2),
@@ -337,6 +339,24 @@ static void __init efi_debugfs_init(void)
static inline void efi_debugfs_init(void) {}
#endif
+static void refresh_nv_rng_seed(struct work_struct *work)
+{
+ u8 seed[EFI_RANDOM_SEED_SIZE];
+
+ get_random_bytes(seed, sizeof(seed));
+ efi.set_variable(L"RandomSeed", &LINUX_EFI_RANDOM_SEED_TABLE_GUID,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS |
+ EFI_VARIABLE_RUNTIME_ACCESS, sizeof(seed), seed);
+ memzero_explicit(seed, sizeof(seed));
+}
+static int refresh_nv_rng_seed_notification(struct notifier_block *nb, unsigned long action, void *data)
+{
+ static DECLARE_WORK(work, refresh_nv_rng_seed);
+ schedule_work(&work);
+ return NOTIFY_DONE;
+}
+static struct notifier_block refresh_nv_rng_seed_nb = { .notifier_call = refresh_nv_rng_seed_notification };
+
/*
* We register the efi subsystem with the firmware subsystem and the
* efivars subsystem with the efi subsystem, if the system was booted with
@@ -394,10 +414,6 @@ static int __init efisubsys_init(void)
goto err_unregister;
}
- error = efi_runtime_map_init(efi_kobj);
- if (error)
- goto err_remove_group;
-
/* and the standard mountpoint for efivarfs */
error = sysfs_create_mount_point(efi_kobj, "efivars");
if (error) {
@@ -413,6 +429,7 @@ static int __init efisubsys_init(void)
platform_device_register_simple("efi_secret", 0, NULL, 0);
#endif
+ execute_with_initialized_rng(&refresh_nv_rng_seed_nb);
return 0;
err_remove_group:
@@ -423,6 +440,7 @@ err_unregister:
generic_ops_unregister();
err_put:
kobject_put(efi_kobj);
+ efi_kobj = NULL;
destroy_workqueue(efi_rts_wq);
return error;
}
@@ -547,6 +565,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_EFI_GENERIC_STUB
+ {LINUX_EFI_SCREEN_INFO_TABLE_GUID, &screen_info_table },
+#endif
{},
};
@@ -611,7 +632,7 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
seed = early_memremap(efi_rng_seed, sizeof(*seed));
if (seed != NULL) {
- size = min(seed->size, EFI_RANDOM_SEED_SIZE);
+ size = min_t(u32, seed->size, SZ_1K); // sanity check
early_memunmap(seed, sizeof(*seed));
} else {
pr_err("Could not map UEFI random seed!\n");
@@ -620,8 +641,8 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
seed = early_memremap(efi_rng_seed,
sizeof(*seed) + size);
if (seed != NULL) {
- pr_notice("seeding entropy pool\n");
add_bootloader_randomness(seed->bits, size);
+ memzero_explicit(seed->bits, size);
early_memunmap(seed, sizeof(*seed) + size);
} else {
pr_err("Could not map UEFI random seed!\n");
diff --git a/drivers/firmware/efi/fake_mem.h b/drivers/firmware/efi/fake_mem.h
deleted file mode 100644
index d52791af4b18..000000000000
--- a/drivers/firmware/efi/fake_mem.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __EFI_FAKE_MEM_H__
-#define __EFI_FAKE_MEM_H__
-#include <asm/efi.h>
-
-#define EFI_MAX_FAKEMEM CONFIG_EFI_MAX_FAKE_MEM
-
-extern struct efi_mem_range efi_fake_mems[EFI_MAX_FAKEMEM];
-extern int nr_fake_mem;
-#endif /* __EFI_FAKE_MEM_H__ */
diff --git a/drivers/firmware/efi/fdtparams.c b/drivers/firmware/efi/fdtparams.c
index e901f8564ca0..0ec83ba58097 100644
--- a/drivers/firmware/efi/fdtparams.c
+++ b/drivers/firmware/efi/fdtparams.c
@@ -30,11 +30,13 @@ static __initconst const char name[][22] = {
static __initconst const struct {
const char path[17];
+ u8 paravirt;
const char params[PARAMCOUNT][26];
} dt_params[] = {
{
#ifdef CONFIG_XEN // <-------17------>
.path = "/hypervisor/uefi",
+ .paravirt = 1,
.params = {
[SYSTAB] = "xen,uefi-system-table",
[MMBASE] = "xen,uefi-mmap-start",
@@ -121,6 +123,8 @@ u64 __init efi_get_fdt_params(struct efi_memory_map_data *mm)
pr_err("Can't find property '%s' in DT!\n", pname);
return 0;
}
+ if (dt_params[i].paravirt)
+ set_bit(EFI_PARAVIRT, &efi.flags);
return systab;
}
notfound:
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile
index ef5045a53ce0..be8b8c6e8b40 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -5,6 +5,10 @@
# things like ftrace and stack-protector are likely to cause trouble if left
# enabled, even if doing so doesn't break the build.
#
+
+# non-x86 reuses KBUILD_CFLAGS, x86 does not
+cflags-y := $(KBUILD_CFLAGS)
+
cflags-$(CONFIG_X86_32) := -march=i386
cflags-$(CONFIG_X86_64) := -mcmodel=small
cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ \
@@ -18,20 +22,20 @@ cflags-$(CONFIG_X86) += -m$(BITS) -D__KERNEL__ \
# arm64 uses the full KBUILD_CFLAGS so it's necessary to explicitly
# disable the stackleak plugin
-cflags-$(CONFIG_ARM64) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
- -fpie $(DISABLE_STACKLEAK_PLUGIN) \
+cflags-$(CONFIG_ARM64) += -fpie $(DISABLE_STACKLEAK_PLUGIN) \
+ -fno-unwind-tables -fno-asynchronous-unwind-tables \
$(call cc-option,-mbranch-protection=none)
-cflags-$(CONFIG_ARM) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
- -fno-builtin -fpic \
+cflags-$(CONFIG_ARM) += -DEFI_HAVE_STRLEN -DEFI_HAVE_STRNLEN \
+ -DEFI_HAVE_MEMCHR -DEFI_HAVE_STRRCHR \
+ -DEFI_HAVE_STRCMP -fno-builtin -fpic \
$(call cc-option,-mno-single-pic-base)
-cflags-$(CONFIG_RISCV) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
- -fpic
-cflags-$(CONFIG_LOONGARCH) := $(subst $(CC_FLAGS_FTRACE),,$(KBUILD_CFLAGS)) \
- -fpie
+cflags-$(CONFIG_RISCV) += -fpic
+cflags-$(CONFIG_LOONGARCH) += -fpie
cflags-$(CONFIG_EFI_PARAMS_FROM_FDT) += -I$(srctree)/scripts/dtc/libfdt
-KBUILD_CFLAGS := $(cflags-y) -Os -DDISABLE_BRANCH_PROFILING \
+KBUILD_CFLAGS := $(subst $(CC_FLAGS_FTRACE),,$(cflags-y)) \
+ -Os -DDISABLE_BRANCH_PROFILING \
-include $(srctree)/include/linux/hidden.h \
-D__NO_FORTIFY \
-ffreestanding \
@@ -67,7 +71,7 @@ KCOV_INSTRUMENT := n
lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o \
file.o mem.o random.o randomalloc.o pci.o \
skip_spaces.o lib-cmdline.o lib-ctype.o \
- alignedmem.o relocate.o vsprintf.o
+ alignedmem.o relocate.o printk.o vsprintf.o
# include the stub's libfdt dependencies from lib/ when needed
libfdt-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c \
@@ -79,13 +83,14 @@ lib-$(CONFIG_EFI_PARAMS_FROM_FDT) += fdt.o \
$(obj)/lib-%.o: $(srctree)/lib/%.c FORCE
$(call if_changed_rule,cc_o_c)
-lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o
+lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o \
+ screen_info.o efi-stub-entry.o
lib-$(CONFIG_ARM) += arm32-stub.o
-lib-$(CONFIG_ARM64) += arm64-stub.o smbios.o
+lib-$(CONFIG_ARM64) += arm64.o arm64-stub.o arm64-entry.o smbios.o
lib-$(CONFIG_X86) += x86-stub.o
-lib-$(CONFIG_RISCV) += riscv-stub.o
-lib-$(CONFIG_LOONGARCH) += loongarch-stub.o
+lib-$(CONFIG_RISCV) += riscv.o riscv-stub.o
+lib-$(CONFIG_LOONGARCH) += loongarch.o loongarch-stub.o
CFLAGS_arm32-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)
@@ -136,7 +141,7 @@ STUBCOPY_RELOC-$(CONFIG_ARM) := R_ARM_ABS
#
STUBCOPY_FLAGS-$(CONFIG_ARM64) += --prefix-alloc-sections=.init \
--prefix-symbols=__efistub_
-STUBCOPY_RELOC-$(CONFIG_ARM64) := R_AARCH64_ABS
+STUBCOPY_RELOC-$(CONFIG_ARM64) := R_AARCH64_ABS64
# For RISC-V, we don't need anything special other than arm64. Keep all the
# symbols in .init section and make sure that no absolute symbols references
diff --git a/drivers/firmware/efi/libstub/Makefile.zboot b/drivers/firmware/efi/libstub/Makefile.zboot
index 3340b385a05b..43e9a4cab9f5 100644
--- a/drivers/firmware/efi/libstub/Makefile.zboot
+++ b/drivers/firmware/efi/libstub/Makefile.zboot
@@ -10,18 +10,17 @@ comp-type-$(CONFIG_KERNEL_LZO) := lzo
comp-type-$(CONFIG_KERNEL_XZ) := xzkern
comp-type-$(CONFIG_KERNEL_ZSTD) := zstd22
-# in GZIP, the appended le32 carrying the uncompressed size is part of the
-# format, but in other cases, we just append it at the end for convenience,
-# causing the original tools to complain when checking image integrity.
-# So disregard it when calculating the payload size in the zimage header.
-zboot-method-y := $(comp-type-y)_with_size
-zboot-size-len-y := 4
-
-zboot-method-$(CONFIG_KERNEL_GZIP) := gzip
-zboot-size-len-$(CONFIG_KERNEL_GZIP) := 0
+# Copy the SizeOfHeaders, SizeOfCode and SizeOfImage fields from the payload to
+# the end of the compressed image. Note that this presupposes a PE header
+# offset of 64 bytes, which is what arm64, RISC-V and LoongArch use.
+quiet_cmd_compwithsize = $(quiet_cmd_$(comp-type-y))
+ cmd_compwithsize = $(cmd_$(comp-type-y)) && ( \
+ dd status=none if=$< bs=4 count=1 skip=37 ; \
+ dd status=none if=$< bs=4 count=1 skip=23 ; \
+ dd status=none if=$< bs=4 count=1 skip=36 ) >> $@
$(obj)/vmlinuz: $(obj)/$(EFI_ZBOOT_PAYLOAD) FORCE
- $(call if_changed,$(zboot-method-y))
+ $(call if_changed,compwithsize)
OBJCOPYFLAGS_vmlinuz.o := -I binary -O $(EFI_ZBOOT_BFD_TARGET) \
--rename-section .data=.gzdata,load,alloc,readonly,contents
@@ -30,7 +29,6 @@ $(obj)/vmlinuz.o: $(obj)/vmlinuz FORCE
AFLAGS_zboot-header.o += -DMACHINE_TYPE=IMAGE_FILE_MACHINE_$(EFI_ZBOOT_MACH_TYPE) \
-DZBOOT_EFI_PATH="\"$(realpath $(obj)/vmlinuz.efi.elf)\"" \
- -DZBOOT_SIZE_LEN=$(zboot-size-len-y) \
-DCOMP_TYPE="\"$(comp-type-y)\""
$(obj)/zboot-header.o: $(srctree)/drivers/firmware/efi/libstub/zboot-header.S FORCE
@@ -46,4 +44,4 @@ OBJCOPYFLAGS_vmlinuz.efi := -O binary
$(obj)/vmlinuz.efi: $(obj)/vmlinuz.efi.elf FORCE
$(call if_changed,objcopy)
-targets += zboot-header.o vmlinuz vmlinuz.o vmlinuz.efi.elf vmlinuz.efi
+targets += zboot-header.o vmlinuz.o vmlinuz.efi.elf vmlinuz.efi
diff --git a/drivers/firmware/efi/libstub/alignedmem.c b/drivers/firmware/efi/libstub/alignedmem.c
index 1de9878ddd3a..6b83c492c3b8 100644
--- a/drivers/firmware/efi/libstub/alignedmem.c
+++ b/drivers/firmware/efi/libstub/alignedmem.c
@@ -22,12 +22,15 @@
* Return: status code
*/
efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr,
- unsigned long max, unsigned long align)
+ unsigned long max, unsigned long align,
+ int memory_type)
{
efi_physical_addr_t alloc_addr;
efi_status_t status;
int slack;
+ max = min(max, EFI_ALLOC_LIMIT);
+
if (align < EFI_ALLOC_ALIGN)
align = EFI_ALLOC_ALIGN;
@@ -36,7 +39,7 @@ efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr,
slack = align / EFI_PAGE_SIZE - 1;
status = efi_bs_call(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,
- EFI_LOADER_DATA, size / EFI_PAGE_SIZE + slack,
+ memory_type, size / EFI_PAGE_SIZE + slack,
&alloc_addr);
if (status != EFI_SUCCESS)
return status;
diff --git a/drivers/firmware/efi/libstub/arm32-stub.c b/drivers/firmware/efi/libstub/arm32-stub.c
index 0131e3aaa605..1073dd947516 100644
--- a/drivers/firmware/efi/libstub/arm32-stub.c
+++ b/drivers/firmware/efi/libstub/arm32-stub.c
@@ -76,43 +76,6 @@ void efi_handle_post_ebs_state(void)
&efi_entry_state->sctlr_after_ebs);
}
-static efi_guid_t screen_info_guid = LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID;
-
-struct screen_info *alloc_screen_info(void)
-{
- struct screen_info *si;
- efi_status_t status;
-
- /*
- * Unlike on arm64, where we can directly fill out the screen_info
- * structure from the stub, we need to allocate a buffer to hold
- * its contents while we hand over to the kernel proper from the
- * decompressor.
- */
- status = efi_bs_call(allocate_pool, EFI_RUNTIME_SERVICES_DATA,
- sizeof(*si), (void **)&si);
-
- if (status != EFI_SUCCESS)
- return NULL;
-
- status = efi_bs_call(install_configuration_table,
- &screen_info_guid, si);
- if (status == EFI_SUCCESS)
- return si;
-
- efi_bs_call(free_pool, si);
- return NULL;
-}
-
-void free_screen_info(struct screen_info *si)
-{
- if (!si)
- return;
-
- efi_bs_call(install_configuration_table, &screen_info_guid, NULL);
- efi_bs_call(free_pool, si);
-}
-
efi_status_t handle_kernel_image(unsigned long *image_addr,
unsigned long *image_size,
unsigned long *reserve_addr,
diff --git a/drivers/firmware/efi/libstub/arm64-entry.S b/drivers/firmware/efi/libstub/arm64-entry.S
new file mode 100644
index 000000000000..b5c17e89a4fc
--- /dev/null
+++ b/drivers/firmware/efi/libstub/arm64-entry.S
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * EFI entry point.
+ *
+ * Copyright (C) 2013, 2014 Red Hat, Inc.
+ * Author: Mark Salter <msalter@redhat.com>
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+ /*
+ * The entrypoint of a arm64 bare metal image is at offset #0 of the
+ * image, so this is a reasonable default for primary_entry_offset.
+ * Only when the EFI stub is integrated into the core kernel, it is not
+ * guaranteed that the PE/COFF header has been copied to memory too, so
+ * in this case, primary_entry_offset should be overridden by the
+ * linker and point to primary_entry() directly.
+ */
+ .weak primary_entry_offset
+
+SYM_CODE_START(efi_enter_kernel)
+ /*
+ * efi_pe_entry() will have copied the kernel image if necessary and we
+ * end up here with device tree address in x1 and the kernel entry
+ * point stored in x0. Save those values in registers which are
+ * callee preserved.
+ */
+ ldr w2, =primary_entry_offset
+ add x19, x0, x2 // relocated Image entrypoint
+
+ mov x0, x1 // DTB address
+ mov x1, xzr
+ mov x2, xzr
+ mov x3, xzr
+
+ /*
+ * Clean the remainder of this routine to the PoC
+ * so that we can safely disable the MMU and caches.
+ */
+ adr x4, 1f
+ dc civac, x4
+ dsb sy
+
+ /* Turn off Dcache and MMU */
+ mrs x4, CurrentEL
+ cmp x4, #CurrentEL_EL2
+ mrs x4, sctlr_el1
+ b.ne 0f
+ mrs x4, sctlr_el2
+0: bic x4, x4, #SCTLR_ELx_M
+ bic x4, x4, #SCTLR_ELx_C
+ b.eq 1f
+ b 2f
+
+ .balign 32
+1: pre_disable_mmu_workaround
+ msr sctlr_el2, x4
+ isb
+ br x19 // jump to kernel entrypoint
+
+2: pre_disable_mmu_workaround
+ msr sctlr_el1, x4
+ isb
+ br x19 // jump to kernel entrypoint
+
+ .org 1b + 32
+SYM_CODE_END(efi_enter_kernel)
diff --git a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c
index f9de5217ea65..7327b98d8e3f 100644
--- a/drivers/firmware/efi/libstub/arm64-stub.c
+++ b/drivers/firmware/efi/libstub/arm64-stub.c
@@ -11,52 +11,9 @@
#include <asm/efi.h>
#include <asm/memory.h>
#include <asm/sections.h>
-#include <asm/sysreg.h>
#include "efistub.h"
-static bool system_needs_vamap(void)
-{
- const u8 *type1_family = efi_get_smbios_string(1, family);
-
- /*
- * Ampere Altra machines crash in SetTime() if SetVirtualAddressMap()
- * has not been called prior.
- */
- if (!type1_family || strcmp(type1_family, "Altra"))
- return false;
-
- efi_warn("Working around broken SetVirtualAddressMap()\n");
- return true;
-}
-
-efi_status_t check_platform_features(void)
-{
- u64 tg;
-
- /*
- * If we have 48 bits of VA space for TTBR0 mappings, we can map the
- * UEFI runtime regions 1:1 and so calling SetVirtualAddressMap() is
- * unnecessary.
- */
- if (VA_BITS_MIN >= 48 && !system_needs_vamap())
- efi_novamap = true;
-
- /* UEFI mandates support for 4 KB granularity, no need to check */
- if (IS_ENABLED(CONFIG_ARM64_4K_PAGES))
- return EFI_SUCCESS;
-
- tg = (read_cpuid(ID_AA64MMFR0_EL1) >> ID_AA64MMFR0_EL1_TGRAN_SHIFT) & 0xf;
- if (tg < ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MIN || tg > ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MAX) {
- if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
- efi_err("This 64 KB granular kernel is not supported by your CPU\n");
- else
- efi_err("This 16 KB granular kernel is not supported by your CPU\n");
- return EFI_UNSUPPORTED;
- }
- return EFI_SUCCESS;
-}
-
/*
* Distro versions of GRUB may ignore the BSS allocation entirely (i.e., fail
* to provide space, and fail to zero it). Check for this condition by double
@@ -103,16 +60,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
efi_status_t status;
unsigned long kernel_size, kernel_memsize = 0;
u32 phys_seed = 0;
-
- /*
- * Although relocatable kernels can fix up the misalignment with
- * respect to MIN_KIMG_ALIGN, the resulting virtual text addresses are
- * subtly out of sync with those recorded in the vmlinux when kaslr is
- * disabled but the image required relocation anyway. Therefore retain
- * 2M alignment if KASLR was explicitly disabled, even if it was not
- * going to be activated to begin with.
- */
- u64 min_kimg_align = efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN;
+ u64 min_kimg_align = efi_get_kimg_min_align();
if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
efi_guid_t li_fixed_proto = LINUX_EFI_LOADED_IMAGE_FIXED_GUID;
@@ -154,7 +102,8 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
* locate the kernel at a randomized offset in physical memory.
*/
status = efi_random_alloc(*reserve_size, min_kimg_align,
- reserve_addr, phys_seed);
+ reserve_addr, phys_seed,
+ EFI_LOADER_CODE);
if (status != EFI_SUCCESS)
efi_warn("efi_random_alloc() failed: 0x%lx\n", status);
} else {
@@ -164,18 +113,20 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
if (status != EFI_SUCCESS) {
if (!check_image_region((u64)_text, kernel_memsize)) {
efi_err("FIRMWARE BUG: Image BSS overlaps adjacent EFI memory region\n");
- } else if (IS_ALIGNED((u64)_text, min_kimg_align)) {
+ } else if (IS_ALIGNED((u64)_text, min_kimg_align) &&
+ (u64)_end < EFI_ALLOC_LIMIT) {
/*
* Just execute from wherever we were loaded by the
- * UEFI PE/COFF loader if the alignment is suitable.
+ * UEFI PE/COFF loader if the placement is suitable.
*/
*image_addr = (u64)_text;
*reserve_size = 0;
- return EFI_SUCCESS;
+ goto clean_image_to_poc;
}
status = efi_allocate_pages_aligned(*reserve_size, reserve_addr,
- ULONG_MAX, min_kimg_align);
+ ULONG_MAX, min_kimg_align,
+ EFI_LOADER_CODE);
if (status != EFI_SUCCESS) {
efi_err("Failed to relocate kernel\n");
@@ -187,5 +138,13 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
*image_addr = *reserve_addr;
memcpy((void *)*image_addr, _text, kernel_size);
+clean_image_to_poc:
+ /*
+ * Clean the copied Image to the PoC, and ensure it is not shadowed by
+ * stale icache entries from before relocation.
+ */
+ dcache_clean_poc(*image_addr, *image_addr + kernel_size);
+ asm("ic ialluis");
+
return EFI_SUCCESS;
}
diff --git a/drivers/firmware/efi/libstub/arm64.c b/drivers/firmware/efi/libstub/arm64.c
new file mode 100644
index 000000000000..ff2d18c42ee7
--- /dev/null
+++ b/drivers/firmware/efi/libstub/arm64.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2013, 2014 Linaro Ltd; <roy.franz@linaro.org>
+ *
+ * This file implements the EFI boot stub for the arm64 kernel.
+ * Adapted from ARM version by Mark Salter <msalter@redhat.com>
+ */
+
+
+#include <linux/efi.h>
+#include <asm/efi.h>
+#include <asm/memory.h>
+#include <asm/sysreg.h>
+
+#include "efistub.h"
+
+static bool system_needs_vamap(void)
+{
+ const u8 *type1_family = efi_get_smbios_string(1, family);
+
+ /*
+ * Ampere Altra machines crash in SetTime() if SetVirtualAddressMap()
+ * has not been called prior.
+ */
+ if (!type1_family || strcmp(type1_family, "Altra"))
+ return false;
+
+ efi_warn("Working around broken SetVirtualAddressMap()\n");
+ return true;
+}
+
+efi_status_t check_platform_features(void)
+{
+ u64 tg;
+
+ /*
+ * If we have 48 bits of VA space for TTBR0 mappings, we can map the
+ * UEFI runtime regions 1:1 and so calling SetVirtualAddressMap() is
+ * unnecessary.
+ */
+ if (VA_BITS_MIN >= 48 && !system_needs_vamap())
+ efi_novamap = true;
+
+ /* UEFI mandates support for 4 KB granularity, no need to check */
+ if (IS_ENABLED(CONFIG_ARM64_4K_PAGES))
+ return EFI_SUCCESS;
+
+ tg = (read_cpuid(ID_AA64MMFR0_EL1) >> ID_AA64MMFR0_EL1_TGRAN_SHIFT) & 0xf;
+ if (tg < ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MIN || tg > ID_AA64MMFR0_EL1_TGRAN_SUPPORTED_MAX) {
+ if (IS_ENABLED(CONFIG_ARM64_64K_PAGES))
+ efi_err("This 64 KB granular kernel is not supported by your CPU\n");
+ else
+ efi_err("This 16 KB granular kernel is not supported by your CPU\n");
+ return EFI_UNSUPPORTED;
+ }
+ return EFI_SUCCESS;
+}
+
+void efi_cache_sync_image(unsigned long image_base,
+ unsigned long alloc_size,
+ unsigned long code_size)
+{
+ u32 ctr = read_cpuid_effective_cachetype();
+ u64 lsize = 4 << cpuid_feature_extract_unsigned_field(ctr,
+ CTR_EL0_DminLine_SHIFT);
+
+ do {
+ asm("dc civac, %0" :: "r"(image_base));
+ image_base += lsize;
+ alloc_size -= lsize;
+ } while (alloc_size >= lsize);
+
+ asm("ic ialluis");
+ dsb(ish);
+ isb();
+}
diff --git a/drivers/firmware/efi/libstub/efi-stub-entry.c b/drivers/firmware/efi/libstub/efi-stub-entry.c
new file mode 100644
index 000000000000..5245c4f031c0
--- /dev/null
+++ b/drivers/firmware/efi/libstub/efi-stub-entry.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/efi.h>
+#include <asm/efi.h>
+
+#include "efistub.h"
+
+/*
+ * EFI entry point for the generic EFI stub used by ARM, arm64, RISC-V and
+ * LoongArch. This is the entrypoint that is described in the PE/COFF header
+ * of the core kernel.
+ */
+efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
+ efi_system_table_t *systab)
+{
+ efi_loaded_image_t *image;
+ efi_status_t status;
+ unsigned long image_addr;
+ unsigned long image_size = 0;
+ /* addr/point and size pairs for memory management*/
+ char *cmdline_ptr = NULL;
+ efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID;
+ unsigned long reserve_addr = 0;
+ unsigned long reserve_size = 0;
+
+ WRITE_ONCE(efi_system_table, systab);
+
+ /* Check if we were booted by the EFI firmware */
+ if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)
+ return EFI_INVALID_PARAMETER;
+
+ /*
+ * Get a handle to the loaded image protocol. This is used to get
+ * information about the running image, such as size and the command
+ * line.
+ */
+ status = efi_bs_call(handle_protocol, handle, &loaded_image_proto,
+ (void *)&image);
+ if (status != EFI_SUCCESS) {
+ efi_err("Failed to get loaded image protocol\n");
+ return status;
+ }
+
+ status = efi_handle_cmdline(image, &cmdline_ptr);
+ if (status != EFI_SUCCESS)
+ return status;
+
+ efi_info("Booting Linux Kernel...\n");
+
+ status = handle_kernel_image(&image_addr, &image_size,
+ &reserve_addr,
+ &reserve_size,
+ image, handle);
+ if (status != EFI_SUCCESS) {
+ efi_err("Failed to relocate kernel\n");
+ return status;
+ }
+
+ status = efi_stub_common(handle, image, image_addr, cmdline_ptr);
+
+ efi_free(image_size, image_addr);
+ efi_free(reserve_size, reserve_addr);
+
+ return status;
+}
diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c
index 0c493521b25b..f5a4bdacac64 100644
--- a/drivers/firmware/efi/libstub/efi-stub-helper.c
+++ b/drivers/firmware/efi/libstub/efi-stub-helper.c
@@ -9,10 +9,8 @@
#include <linux/stdarg.h>
-#include <linux/ctype.h>
#include <linux/efi.h>
#include <linux/kernel.h>
-#include <linux/printk.h> /* For CONSOLE_LOGLEVEL_* */
#include <asm/efi.h>
#include <asm/setup.h>
@@ -20,7 +18,6 @@
bool efi_nochunk;
bool efi_nokaslr = !IS_ENABLED(CONFIG_RANDOMIZE_BASE);
-int efi_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
bool efi_novamap;
static bool efi_noinitrd;
@@ -33,146 +30,6 @@ bool __pure __efi_soft_reserve_enabled(void)
}
/**
- * efi_char16_puts() - Write a UCS-2 encoded string to the console
- * @str: UCS-2 encoded string
- */
-void efi_char16_puts(efi_char16_t *str)
-{
- efi_call_proto(efi_table_attr(efi_system_table, con_out),
- output_string, str);
-}
-
-static
-u32 utf8_to_utf32(const u8 **s8)
-{
- u32 c32;
- u8 c0, cx;
- size_t clen, i;
-
- c0 = cx = *(*s8)++;
- /*
- * The position of the most-significant 0 bit gives us the length of
- * a multi-octet encoding.
- */
- for (clen = 0; cx & 0x80; ++clen)
- cx <<= 1;
- /*
- * If the 0 bit is in position 8, this is a valid single-octet
- * encoding. If the 0 bit is in position 7 or positions 1-3, the
- * encoding is invalid.
- * In either case, we just return the first octet.
- */
- if (clen < 2 || clen > 4)
- return c0;
- /* Get the bits from the first octet. */
- c32 = cx >> clen--;
- for (i = 0; i < clen; ++i) {
- /* Trailing octets must have 10 in most significant bits. */
- cx = (*s8)[i] ^ 0x80;
- if (cx & 0xc0)
- return c0;
- c32 = (c32 << 6) | cx;
- }
- /*
- * Check for validity:
- * - The character must be in the Unicode range.
- * - It must not be a surrogate.
- * - It must be encoded using the correct number of octets.
- */
- if (c32 > 0x10ffff ||
- (c32 & 0xf800) == 0xd800 ||
- clen != (c32 >= 0x80) + (c32 >= 0x800) + (c32 >= 0x10000))
- return c0;
- *s8 += clen;
- return c32;
-}
-
-/**
- * efi_puts() - Write a UTF-8 encoded string to the console
- * @str: UTF-8 encoded string
- */
-void efi_puts(const char *str)
-{
- efi_char16_t buf[128];
- size_t pos = 0, lim = ARRAY_SIZE(buf);
- const u8 *s8 = (const u8 *)str;
- u32 c32;
-
- while (*s8) {
- if (*s8 == '\n')
- buf[pos++] = L'\r';
- c32 = utf8_to_utf32(&s8);
- if (c32 < 0x10000) {
- /* Characters in plane 0 use a single word. */
- buf[pos++] = c32;
- } else {
- /*
- * Characters in other planes encode into a surrogate
- * pair.
- */
- buf[pos++] = (0xd800 - (0x10000 >> 10)) + (c32 >> 10);
- buf[pos++] = 0xdc00 + (c32 & 0x3ff);
- }
- if (*s8 == '\0' || pos >= lim - 2) {
- buf[pos] = L'\0';
- efi_char16_puts(buf);
- pos = 0;
- }
- }
-}
-
-/**
- * efi_printk() - Print a kernel message
- * @fmt: format string
- *
- * The first letter of the format string is used to determine the logging level
- * of the message. If the level is less then the current EFI logging level, the
- * message is suppressed. The message will be truncated to 255 bytes.
- *
- * Return: number of printed characters
- */
-int efi_printk(const char *fmt, ...)
-{
- char printf_buf[256];
- va_list args;
- int printed;
- int loglevel = printk_get_level(fmt);
-
- switch (loglevel) {
- case '0' ... '9':
- loglevel -= '0';
- break;
- default:
- /*
- * Use loglevel -1 for cases where we just want to print to
- * the screen.
- */
- loglevel = -1;
- break;
- }
-
- if (loglevel >= efi_loglevel)
- return 0;
-
- if (loglevel >= 0)
- efi_puts("EFI stub: ");
-
- fmt = printk_skip_level(fmt);
-
- va_start(args, fmt);
- printed = vsnprintf(printf_buf, sizeof(printf_buf), fmt, args);
- va_end(args);
-
- efi_puts(printf_buf);
- if (printed >= sizeof(printf_buf)) {
- efi_puts("[Message truncated]\n");
- return -1;
- }
-
- return printed;
-}
-
-/**
* efi_parse_options() - Parse EFI command line options
* @cmdline: kernel command line
*
@@ -626,8 +483,8 @@ static const struct {
/**
* efi_load_initrd_dev_path() - load the initrd from the Linux initrd device path
- * @load_addr: pointer to store the address where the initrd was loaded
- * @load_size: pointer to store the size of the loaded initrd
+ * @initrd: pointer of struct to store the address where the initrd was loaded
+ * and the size of the loaded initrd
* @max: upper limit for the initrd memory allocation
*
* Return:
@@ -681,8 +538,7 @@ efi_status_t efi_load_initrd_cmdline(efi_loaded_image_t *image,
unsigned long soft_limit,
unsigned long hard_limit)
{
- if (!IS_ENABLED(CONFIG_EFI_GENERIC_STUB_INITRD_CMDLINE_LOADER) ||
- (IS_ENABLED(CONFIG_X86) && (!efi_is_native() || image == NULL)))
+ if (image == NULL)
return EFI_UNSUPPORTED;
return handle_cmdline_files(image, L"initrd=", sizeof(L"initrd=") - 2,
diff --git a/drivers/firmware/efi/libstub/efi-stub.c b/drivers/firmware/efi/libstub/efi-stub.c
index cf474f0dd261..2955c1ac6a36 100644
--- a/drivers/firmware/efi/libstub/efi-stub.c
+++ b/drivers/firmware/efi/libstub/efi-stub.c
@@ -35,15 +35,6 @@
* as well to minimize the code churn.
*/
#define EFI_RT_VIRTUAL_BASE SZ_512M
-#define EFI_RT_VIRTUAL_SIZE SZ_512M
-
-#ifdef CONFIG_ARM64
-# define EFI_RT_VIRTUAL_LIMIT DEFAULT_MAP_WINDOW_64
-#elif defined(CONFIG_RISCV) || defined(CONFIG_LOONGARCH)
-# define EFI_RT_VIRTUAL_LIMIT TASK_SIZE_MIN
-#else /* Only if TASK_SIZE is a constant */
-# define EFI_RT_VIRTUAL_LIMIT TASK_SIZE
-#endif
/*
* Some architectures map the EFI regions into the kernel's linear map using a
@@ -56,6 +47,15 @@
static u64 virtmap_base = EFI_RT_VIRTUAL_BASE;
static bool flat_va_mapping = (EFI_RT_VIRTUAL_OFFSET != 0);
+struct screen_info * __weak alloc_screen_info(void)
+{
+ return &screen_info;
+}
+
+void __weak free_screen_info(struct screen_info *si)
+{
+}
+
static struct screen_info *setup_graphics(void)
{
efi_guid_t gop_proto = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
@@ -115,62 +115,21 @@ static u32 get_supported_rt_services(void)
return supported;
}
-/*
- * EFI entry point for the arm/arm64 EFI stubs. This is the entrypoint
- * that is described in the PE/COFF header. Most of the code is the same
- * for both archictectures, with the arch-specific code provided in the
- * handle_kernel_image() function.
- */
-efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
- efi_system_table_t *sys_table_arg)
+efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr)
{
- efi_loaded_image_t *image;
- efi_status_t status;
- unsigned long image_addr;
- unsigned long image_size = 0;
- /* addr/point and size pairs for memory management*/
- char *cmdline_ptr = NULL;
int cmdline_size = 0;
- efi_guid_t loaded_image_proto = LOADED_IMAGE_PROTOCOL_GUID;
- unsigned long reserve_addr = 0;
- unsigned long reserve_size = 0;
- struct screen_info *si;
- efi_properties_table_t *prop_tbl;
-
- efi_system_table = sys_table_arg;
-
- /* Check if we were booted by the EFI firmware */
- if (efi_system_table->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE) {
- status = EFI_INVALID_PARAMETER;
- goto fail;
- }
-
- status = check_platform_features();
- if (status != EFI_SUCCESS)
- goto fail;
-
- /*
- * Get a handle to the loaded image protocol. This is used to get
- * information about the running image, such as size and the command
- * line.
- */
- status = efi_bs_call(handle_protocol, handle, &loaded_image_proto,
- (void *)&image);
- if (status != EFI_SUCCESS) {
- efi_err("Failed to get loaded image protocol\n");
- goto fail;
- }
+ efi_status_t status;
+ char *cmdline;
/*
* Get the command line from EFI, using the LOADED_IMAGE
* protocol. We are going to copy the command line into the
* device tree, so this can be allocated anywhere.
*/
- cmdline_ptr = efi_convert_cmdline(image, &cmdline_size);
- if (!cmdline_ptr) {
+ cmdline = efi_convert_cmdline(image, &cmdline_size);
+ if (!cmdline) {
efi_err("getting command line via LOADED_IMAGE_PROTOCOL\n");
- status = EFI_OUT_OF_RESOURCES;
- goto fail;
+ return EFI_OUT_OF_RESOURCES;
}
if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) ||
@@ -184,25 +143,34 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
}
if (!IS_ENABLED(CONFIG_CMDLINE_FORCE) && cmdline_size > 0) {
- status = efi_parse_options(cmdline_ptr);
+ status = efi_parse_options(cmdline);
if (status != EFI_SUCCESS) {
efi_err("Failed to parse options\n");
goto fail_free_cmdline;
}
}
- efi_info("Booting Linux Kernel...\n");
+ *cmdline_ptr = cmdline;
+ return EFI_SUCCESS;
- si = setup_graphics();
+fail_free_cmdline:
+ efi_bs_call(free_pool, cmdline_ptr);
+ return status;
+}
- status = handle_kernel_image(&image_addr, &image_size,
- &reserve_addr,
- &reserve_size,
- image, handle);
- if (status != EFI_SUCCESS) {
- efi_err("Failed to relocate kernel\n");
- goto fail_free_screeninfo;
- }
+efi_status_t efi_stub_common(efi_handle_t handle,
+ efi_loaded_image_t *image,
+ unsigned long image_addr,
+ char *cmdline_ptr)
+{
+ struct screen_info *si;
+ efi_status_t status;
+
+ status = check_platform_features();
+ if (status != EFI_SUCCESS)
+ return status;
+
+ si = setup_graphics();
efi_retrieve_tpm2_eventlog();
@@ -214,53 +182,15 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
efi_random_get_seed();
- /*
- * If the NX PE data feature is enabled in the properties table, we
- * should take care not to create a virtual mapping that changes the
- * relative placement of runtime services code and data regions, as
- * they may belong to the same PE/COFF executable image in memory.
- * The easiest way to achieve that is to simply use a 1:1 mapping.
- */
- prop_tbl = get_efi_config_table(EFI_PROPERTIES_TABLE_GUID);
- flat_va_mapping |= prop_tbl &&
- (prop_tbl->memory_protection_attribute &
- EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA);
-
/* force efi_novamap if SetVirtualAddressMap() is unsupported */
efi_novamap |= !(get_supported_rt_services() &
EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP);
- /* hibernation expects the runtime regions to stay in the same place */
- if (!IS_ENABLED(CONFIG_HIBERNATION) && !efi_nokaslr && !flat_va_mapping) {
- /*
- * Randomize the base of the UEFI runtime services region.
- * Preserve the 2 MB alignment of the region by taking a
- * shift of 21 bit positions into account when scaling
- * the headroom value using a 32-bit random value.
- */
- static const u64 headroom = EFI_RT_VIRTUAL_LIMIT -
- EFI_RT_VIRTUAL_BASE -
- EFI_RT_VIRTUAL_SIZE;
- u32 rnd;
-
- status = efi_get_random_bytes(sizeof(rnd), (u8 *)&rnd);
- if (status == EFI_SUCCESS) {
- virtmap_base = EFI_RT_VIRTUAL_BASE +
- (((headroom >> 21) * rnd) >> (32 - 21));
- }
- }
-
install_memreserve_table();
status = efi_boot_kernel(handle, image, image_addr, cmdline_ptr);
- efi_free(image_size, image_addr);
- efi_free(reserve_size, reserve_addr);
-fail_free_screeninfo:
free_screen_info(si);
-fail_free_cmdline:
- efi_bs_call(free_pool, cmdline_ptr);
-fail:
return status;
}
diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h
index eb03d5a9aac8..5b8f2c411ed8 100644
--- a/drivers/firmware/efi/libstub/efistub.h
+++ b/drivers/firmware/efi/libstub/efistub.h
@@ -29,6 +29,10 @@
#define EFI_ALLOC_ALIGN EFI_PAGE_SIZE
#endif
+#ifndef EFI_ALLOC_LIMIT
+#define EFI_ALLOC_LIMIT ULONG_MAX
+#endif
+
extern bool efi_nochunk;
extern bool efi_nokaslr;
extern int efi_loglevel;
@@ -44,15 +48,23 @@ efi_status_t __efiapi efi_pe_entry(efi_handle_t handle,
#ifndef ARCH_HAS_EFISTUB_WRAPPERS
-#define efi_is_native() (true)
-#define efi_bs_call(func, ...) efi_system_table->boottime->func(__VA_ARGS__)
-#define efi_rt_call(func, ...) efi_system_table->runtime->func(__VA_ARGS__)
-#define efi_dxe_call(func, ...) efi_dxe_table->func(__VA_ARGS__)
-#define efi_table_attr(inst, attr) (inst->attr)
-#define efi_call_proto(inst, func, ...) inst->func(inst, ##__VA_ARGS__)
+#define efi_is_native() (true)
+#define efi_table_attr(inst, attr) (inst)->attr
+#define efi_fn_call(inst, func, ...) (inst)->func(__VA_ARGS__)
#endif
+#define efi_call_proto(inst, func, ...) ({ \
+ __typeof__(inst) __inst = (inst); \
+ efi_fn_call(__inst, func, __inst, ##__VA_ARGS__); \
+})
+#define efi_bs_call(func, ...) \
+ efi_fn_call(efi_table_attr(efi_system_table, boottime), func, ##__VA_ARGS__)
+#define efi_rt_call(func, ...) \
+ efi_fn_call(efi_table_attr(efi_system_table, runtime), func, ##__VA_ARGS__)
+#define efi_dxe_call(func, ...) \
+ efi_fn_call(efi_dxe_table, func, ##__VA_ARGS__)
+
#define efi_info(fmt, ...) \
efi_printk(KERN_INFO fmt, ##__VA_ARGS__)
#define efi_warn(fmt, ...) \
@@ -179,6 +191,21 @@ union efi_device_path_to_text_protocol {
typedef union efi_device_path_to_text_protocol efi_device_path_to_text_protocol_t;
+union efi_device_path_from_text_protocol {
+ struct {
+ efi_device_path_protocol_t *
+ (__efiapi *convert_text_to_device_node)(const efi_char16_t *);
+ efi_device_path_protocol_t *
+ (__efiapi *convert_text_to_device_path)(const efi_char16_t *);
+ };
+ struct {
+ u32 convert_text_to_device_node;
+ u32 convert_text_to_device_path;
+ } mixed_mode;
+};
+
+typedef union efi_device_path_from_text_protocol efi_device_path_from_text_protocol_t;
+
typedef void *efi_event_t;
/* Note that notifications won't work in mixed mode */
typedef void (__efiapi *efi_event_notify_t)(efi_event_t, void *);
@@ -572,36 +599,63 @@ typedef struct {
efi_char16_t filename[];
} efi_file_info_t;
-typedef struct efi_file_protocol efi_file_protocol_t;
-
-struct efi_file_protocol {
- u64 revision;
- efi_status_t (__efiapi *open) (efi_file_protocol_t *,
- efi_file_protocol_t **,
- efi_char16_t *, u64, u64);
- efi_status_t (__efiapi *close) (efi_file_protocol_t *);
- efi_status_t (__efiapi *delete) (efi_file_protocol_t *);
- efi_status_t (__efiapi *read) (efi_file_protocol_t *,
- unsigned long *, void *);
- efi_status_t (__efiapi *write) (efi_file_protocol_t *,
- unsigned long, void *);
- efi_status_t (__efiapi *get_position)(efi_file_protocol_t *, u64 *);
- efi_status_t (__efiapi *set_position)(efi_file_protocol_t *, u64);
- efi_status_t (__efiapi *get_info) (efi_file_protocol_t *,
- efi_guid_t *, unsigned long *,
- void *);
- efi_status_t (__efiapi *set_info) (efi_file_protocol_t *,
- efi_guid_t *, unsigned long,
- void *);
- efi_status_t (__efiapi *flush) (efi_file_protocol_t *);
+typedef union efi_file_protocol efi_file_protocol_t;
+
+union efi_file_protocol {
+ struct {
+ u64 revision;
+ efi_status_t (__efiapi *open) (efi_file_protocol_t *,
+ efi_file_protocol_t **,
+ efi_char16_t *, u64,
+ u64);
+ efi_status_t (__efiapi *close) (efi_file_protocol_t *);
+ efi_status_t (__efiapi *delete) (efi_file_protocol_t *);
+ efi_status_t (__efiapi *read) (efi_file_protocol_t *,
+ unsigned long *,
+ void *);
+ efi_status_t (__efiapi *write) (efi_file_protocol_t *,
+ unsigned long, void *);
+ efi_status_t (__efiapi *get_position)(efi_file_protocol_t *,
+ u64 *);
+ efi_status_t (__efiapi *set_position)(efi_file_protocol_t *,
+ u64);
+ efi_status_t (__efiapi *get_info) (efi_file_protocol_t *,
+ efi_guid_t *,
+ unsigned long *,
+ void *);
+ efi_status_t (__efiapi *set_info) (efi_file_protocol_t *,
+ efi_guid_t *,
+ unsigned long,
+ void *);
+ efi_status_t (__efiapi *flush) (efi_file_protocol_t *);
+ };
+ struct {
+ u64 revision;
+ u32 open;
+ u32 close;
+ u32 delete;
+ u32 read;
+ u32 write;
+ u32 get_position;
+ u32 set_position;
+ u32 get_info;
+ u32 set_info;
+ u32 flush;
+ } mixed_mode;
};
-typedef struct efi_simple_file_system_protocol efi_simple_file_system_protocol_t;
+typedef union efi_simple_file_system_protocol efi_simple_file_system_protocol_t;
-struct efi_simple_file_system_protocol {
- u64 revision;
- int (__efiapi *open_volume)(efi_simple_file_system_protocol_t *,
- efi_file_protocol_t **);
+union efi_simple_file_system_protocol {
+ struct {
+ u64 revision;
+ efi_status_t (__efiapi *open_volume)(efi_simple_file_system_protocol_t *,
+ efi_file_protocol_t **);
+ };
+ struct {
+ u64 revision;
+ u32 open_volume;
+ } mixed_mode;
};
#define EFI_FILE_MODE_READ 0x0000000000000001
@@ -880,7 +934,10 @@ void efi_get_virtmap(efi_memory_desc_t *memory_map, unsigned long map_size,
efi_status_t efi_get_random_bytes(unsigned long size, u8 *out);
efi_status_t efi_random_alloc(unsigned long size, unsigned long align,
- unsigned long *addr, unsigned long random_seed);
+ unsigned long *addr, unsigned long random_seed,
+ int memory_type);
+
+efi_status_t efi_random_get_seed(void);
efi_status_t check_platform_features(void);
@@ -905,7 +962,8 @@ efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr,
unsigned long max);
efi_status_t efi_allocate_pages_aligned(unsigned long size, unsigned long *addr,
- unsigned long max, unsigned long align);
+ unsigned long max, unsigned long align,
+ int memory_type);
efi_status_t efi_low_alloc_above(unsigned long size, unsigned long align,
unsigned long *addr, unsigned long min);
@@ -958,6 +1016,14 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
efi_loaded_image_t *image,
efi_handle_t image_handle);
+/* shared entrypoint between the normal stub and the zboot stub */
+efi_status_t efi_stub_common(efi_handle_t handle,
+ efi_loaded_image_t *image,
+ unsigned long image_addr,
+ char *cmdline_ptr);
+
+efi_status_t efi_handle_cmdline(efi_loaded_image_t *image, char **cmdline_ptr);
+
asmlinkage void __noreturn efi_enter_kernel(unsigned long entrypoint,
unsigned long fdt_addr,
unsigned long fdt_size);
@@ -975,6 +1041,13 @@ efi_enable_reset_attack_mitigation(void) { }
void efi_retrieve_tpm2_eventlog(void);
+struct screen_info *alloc_screen_info(void);
+void free_screen_info(struct screen_info *si);
+
+void efi_cache_sync_image(unsigned long image_base,
+ unsigned long alloc_size,
+ unsigned long code_size);
+
struct efi_smbios_record {
u8 type;
u8 length;
diff --git a/drivers/firmware/efi/libstub/file.c b/drivers/firmware/efi/libstub/file.c
index f756c61396e9..d6a025df07dc 100644
--- a/drivers/firmware/efi/libstub/file.c
+++ b/drivers/firmware/efi/libstub/file.c
@@ -43,18 +43,26 @@ static efi_status_t efi_open_file(efi_file_protocol_t *volume,
efi_file_protocol_t *fh;
unsigned long info_sz;
efi_status_t status;
+ efi_char16_t *c;
- status = volume->open(volume, &fh, fi->filename, EFI_FILE_MODE_READ, 0);
+ /* Replace UNIX dir separators with EFI standard ones */
+ for (c = fi->filename; *c != L'\0'; c++) {
+ if (*c == L'/')
+ *c = L'\\';
+ }
+
+ status = efi_call_proto(volume, open, &fh, fi->filename,
+ EFI_FILE_MODE_READ, 0);
if (status != EFI_SUCCESS) {
efi_err("Failed to open file: %ls\n", fi->filename);
return status;
}
info_sz = sizeof(struct finfo);
- status = fh->get_info(fh, &info_guid, &info_sz, fi);
+ status = efi_call_proto(fh, get_info, &info_guid, &info_sz, fi);
if (status != EFI_SUCCESS) {
efi_err("Failed to get file info\n");
- fh->close(fh);
+ efi_call_proto(fh, close);
return status;
}
@@ -66,36 +74,18 @@ static efi_status_t efi_open_file(efi_file_protocol_t *volume,
static efi_status_t efi_open_volume(efi_loaded_image_t *image,
efi_file_protocol_t **fh)
{
- struct efi_vendor_dev_path *dp = image->file_path;
- efi_guid_t li_proto = LOADED_IMAGE_PROTOCOL_GUID;
efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
efi_simple_file_system_protocol_t *io;
efi_status_t status;
- // If we are using EFI zboot, we should look for the file system
- // protocol on the parent image's handle instead
- if (IS_ENABLED(CONFIG_EFI_ZBOOT) &&
- image->parent_handle != NULL &&
- dp != NULL &&
- dp->header.type == EFI_DEV_MEDIA &&
- dp->header.sub_type == EFI_DEV_MEDIA_VENDOR &&
- !efi_guidcmp(dp->vendorguid, LINUX_EFI_ZBOOT_MEDIA_GUID)) {
- status = efi_bs_call(handle_protocol, image->parent_handle,
- &li_proto, (void *)&image);
- if (status != EFI_SUCCESS) {
- efi_err("Failed to locate parent image handle\n");
- return status;
- }
- }
-
- status = efi_bs_call(handle_protocol, image->device_handle, &fs_proto,
- (void **)&io);
+ status = efi_bs_call(handle_protocol, efi_table_attr(image, device_handle),
+ &fs_proto, (void **)&io);
if (status != EFI_SUCCESS) {
efi_err("Failed to handle fs_proto\n");
return status;
}
- status = io->open_volume(io, fh);
+ status = efi_call_proto(io, open_volume, fh);
if (status != EFI_SUCCESS)
efi_err("Failed to open volume\n");
@@ -129,16 +119,62 @@ static int find_file_option(const efi_char16_t *cmdline, int cmdline_len,
if (c == L'\0' || c == L'\n' || c == L' ')
break;
- else if (c == L'/')
- /* Replace UNIX dir separators with EFI standard ones */
- *result++ = L'\\';
- else
- *result++ = c;
+ *result++ = c;
}
*result = L'\0';
return i;
}
+static efi_status_t efi_open_device_path(efi_file_protocol_t **volume,
+ struct finfo *fi)
+{
+ efi_guid_t text_to_dp_guid = EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID;
+ static efi_device_path_from_text_protocol_t *text_to_dp = NULL;
+ efi_guid_t fs_proto = EFI_FILE_SYSTEM_GUID;
+ efi_device_path_protocol_t *initrd_dp;
+ efi_simple_file_system_protocol_t *io;
+ struct efi_file_path_dev_path *fpath;
+ efi_handle_t handle;
+ efi_status_t status;
+
+ /* See if the text to device path protocol exists */
+ if (!text_to_dp &&
+ efi_bs_call(locate_protocol, &text_to_dp_guid, NULL,
+ (void **)&text_to_dp) != EFI_SUCCESS)
+ return EFI_UNSUPPORTED;
+
+
+ /* Convert the filename wide string into a device path */
+ initrd_dp = efi_fn_call(text_to_dp, convert_text_to_device_path,
+ fi->filename);
+
+ /* Check whether the device path in question implements simple FS */
+ if ((efi_bs_call(locate_device_path, &fs_proto, &initrd_dp, &handle) ?:
+ efi_bs_call(handle_protocol, handle, &fs_proto, (void **)&io))
+ != EFI_SUCCESS)
+ return EFI_NOT_FOUND;
+
+ /* Check whether the remaining device path is a file device path */
+ if (initrd_dp->type != EFI_DEV_MEDIA ||
+ initrd_dp->sub_type != EFI_DEV_MEDIA_FILE) {
+ efi_warn("Unexpected device path node type: (%x, %x)\n",
+ initrd_dp->type, initrd_dp->sub_type);
+ return EFI_LOAD_ERROR;
+ }
+
+ /* Copy the remaining file path into the fi structure */
+ fpath = (struct efi_file_path_dev_path *)initrd_dp;
+ memcpy(fi->filename, fpath->filename,
+ min(sizeof(fi->filename),
+ fpath->header.length - sizeof(fpath->header)));
+
+ status = efi_call_proto(io, open_volume, volume);
+ if (status != EFI_SUCCESS)
+ efi_err("Failed to open volume\n");
+
+ return status;
+}
+
/*
* Check the cmdline for a LILO-style file= arguments.
*
@@ -153,8 +189,8 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
unsigned long *load_addr,
unsigned long *load_size)
{
- const efi_char16_t *cmdline = image->load_options;
- u32 cmdline_len = image->load_options_size;
+ const efi_char16_t *cmdline = efi_table_attr(image, load_options);
+ u32 cmdline_len = efi_table_attr(image, load_options_size);
unsigned long efi_chunk_size = ULONG_MAX;
efi_file_protocol_t *volume = NULL;
efi_file_protocol_t *file;
@@ -188,11 +224,13 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
cmdline += offset;
cmdline_len -= offset;
- if (!volume) {
+ status = efi_open_device_path(&volume, &fi);
+ if (status == EFI_UNSUPPORTED || status == EFI_NOT_FOUND)
+ /* try the volume that holds the kernel itself */
status = efi_open_volume(image, &volume);
- if (status != EFI_SUCCESS)
- return status;
- }
+
+ if (status != EFI_SUCCESS)
+ goto err_free_alloc;
status = efi_open_file(volume, &fi, &file, &size);
if (status != EFI_SUCCESS)
@@ -240,7 +278,7 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
while (size) {
unsigned long chunksize = min(size, efi_chunk_size);
- status = file->read(file, &chunksize, addr);
+ status = efi_call_proto(file, read, &chunksize, addr);
if (status != EFI_SUCCESS) {
efi_err("Failed to read file\n");
goto err_close_file;
@@ -248,24 +286,24 @@ efi_status_t handle_cmdline_files(efi_loaded_image_t *image,
addr += chunksize;
size -= chunksize;
}
- file->close(file);
+ efi_call_proto(file, close);
+ efi_call_proto(volume, close);
} while (offset > 0);
*load_addr = alloc_addr;
*load_size = alloc_size;
- if (volume)
- volume->close(volume);
-
if (*load_size == 0)
return EFI_NOT_READY;
return EFI_SUCCESS;
err_close_file:
- file->close(file);
+ efi_call_proto(file, close);
err_close_volume:
- volume->close(volume);
+ efi_call_proto(volume, close);
+
+err_free_alloc:
efi_free(alloc_size, alloc_addr);
return status;
}
diff --git a/drivers/firmware/efi/libstub/intrinsics.c b/drivers/firmware/efi/libstub/intrinsics.c
index a04ab39292b6..965e734f6f98 100644
--- a/drivers/firmware/efi/libstub/intrinsics.c
+++ b/drivers/firmware/efi/libstub/intrinsics.c
@@ -28,3 +28,21 @@ void *memset(void *dst, int c, size_t len)
efi_bs_call(set_mem, dst, len, c & U8_MAX);
return dst;
}
+
+/**
+ * memcmp - Compare two areas of memory
+ * @cs: One area of memory
+ * @ct: Another area of memory
+ * @count: The size of the area.
+ */
+#undef memcmp
+int memcmp(const void *cs, const void *ct, size_t count)
+{
+ const unsigned char *su1, *su2;
+ int res = 0;
+
+ for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
+ if ((res = *su1 - *su2) != 0)
+ break;
+ return res;
+}
diff --git a/drivers/firmware/efi/libstub/loongarch-stub.c b/drivers/firmware/efi/libstub/loongarch-stub.c
index 32329f2a92f9..eee7ed43cdfb 100644
--- a/drivers/firmware/efi/libstub/loongarch-stub.c
+++ b/drivers/firmware/efi/libstub/loongarch-stub.c
@@ -9,18 +9,10 @@
#include <asm/addrspace.h>
#include "efistub.h"
-typedef void __noreturn (*kernel_entry_t)(bool efi, unsigned long cmdline,
- unsigned long systab);
-
extern int kernel_asize;
extern int kernel_fsize;
extern int kernel_offset;
-extern kernel_entry_t kernel_entry;
-
-efi_status_t check_platform_features(void)
-{
- return EFI_SUCCESS;
-}
+extern int kernel_entry;
efi_status_t handle_kernel_image(unsigned long *image_addr,
unsigned long *image_size,
@@ -29,74 +21,33 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
efi_loaded_image_t *image,
efi_handle_t image_handle)
{
+ int nr_pages = round_up(kernel_asize, EFI_ALLOC_ALIGN) / EFI_PAGE_SIZE;
+ efi_physical_addr_t kernel_addr = EFI_KIMG_PREFERRED_ADDRESS;
efi_status_t status;
- unsigned long kernel_addr = 0;
-
- kernel_addr = (unsigned long)&kernel_offset - kernel_offset;
-
- status = efi_relocate_kernel(&kernel_addr, kernel_fsize, kernel_asize,
- PHYSADDR(VMLINUX_LOAD_ADDRESS), SZ_2M, 0x0);
-
- *image_addr = kernel_addr;
- *image_size = kernel_asize;
-
- return status;
-}
-
-struct exit_boot_struct {
- efi_memory_desc_t *runtime_map;
- int runtime_entry_count;
-};
-
-static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv)
-{
- struct exit_boot_struct *p = priv;
/*
- * Update the memory map with virtual addresses. The function will also
- * populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME
- * entries so that we can pass it straight to SetVirtualAddressMap()
+ * Allocate space for the kernel image at the preferred offset. This is
+ * the only location in memory from where we can execute the image, so
+ * no point in falling back to another allocation.
*/
- efi_get_virtmap(map->map, map->map_size, map->desc_size,
- p->runtime_map, &p->runtime_entry_count);
-
- return EFI_SUCCESS;
-}
-
-efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
- unsigned long kernel_addr, char *cmdline_ptr)
-{
- kernel_entry_t real_kernel_entry;
- struct exit_boot_struct priv;
- unsigned long desc_size;
- efi_status_t status;
- u32 desc_ver;
-
- status = efi_alloc_virtmap(&priv.runtime_map, &desc_size, &desc_ver);
- if (status != EFI_SUCCESS) {
- efi_err("Unable to retrieve UEFI memory map.\n");
- return status;
- }
-
- efi_info("Exiting boot services\n");
-
- efi_novamap = false;
- status = efi_exit_boot_services(handle, &priv, exit_boot_func);
+ status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS,
+ EFI_LOADER_DATA, nr_pages, &kernel_addr);
if (status != EFI_SUCCESS)
return status;
- /* Install the new virtual address map */
- efi_rt_call(set_virtual_address_map,
- priv.runtime_entry_count * desc_size, desc_size,
- desc_ver, priv.runtime_map);
+ *image_addr = EFI_KIMG_PREFERRED_ADDRESS;
+ *image_size = kernel_asize;
- /* Config Direct Mapping */
- csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0);
- csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1);
+ memcpy((void *)EFI_KIMG_PREFERRED_ADDRESS,
+ (void *)&kernel_offset - kernel_offset,
+ kernel_fsize);
- real_kernel_entry = (kernel_entry_t)
- ((unsigned long)&kernel_entry - kernel_addr + VMLINUX_LOAD_ADDRESS);
+ return status;
+}
+
+unsigned long kernel_entry_address(void)
+{
+ unsigned long base = (unsigned long)&kernel_offset - kernel_offset;
- real_kernel_entry(true, (unsigned long)cmdline_ptr,
- (unsigned long)efi_system_table);
+ return (unsigned long)&kernel_entry - base + VMLINUX_LOAD_ADDRESS;
}
diff --git a/drivers/firmware/efi/libstub/loongarch.c b/drivers/firmware/efi/libstub/loongarch.c
new file mode 100644
index 000000000000..807cba2693fc
--- /dev/null
+++ b/drivers/firmware/efi/libstub/loongarch.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Author: Yun Liu <liuyun@loongson.cn>
+ * Huacai Chen <chenhuacai@loongson.cn>
+ * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
+ */
+
+#include <asm/efi.h>
+#include <asm/addrspace.h>
+#include "efistub.h"
+
+typedef void __noreturn (*kernel_entry_t)(bool efi, unsigned long cmdline,
+ unsigned long systab);
+
+efi_status_t check_platform_features(void)
+{
+ return EFI_SUCCESS;
+}
+
+struct exit_boot_struct {
+ efi_memory_desc_t *runtime_map;
+ int runtime_entry_count;
+};
+
+static efi_status_t exit_boot_func(struct efi_boot_memmap *map, void *priv)
+{
+ struct exit_boot_struct *p = priv;
+
+ /*
+ * Update the memory map with virtual addresses. The function will also
+ * populate @runtime_map with copies of just the EFI_MEMORY_RUNTIME
+ * entries so that we can pass it straight to SetVirtualAddressMap()
+ */
+ efi_get_virtmap(map->map, map->map_size, map->desc_size,
+ p->runtime_map, &p->runtime_entry_count);
+
+ return EFI_SUCCESS;
+}
+
+unsigned long __weak kernel_entry_address(void)
+{
+ return *(unsigned long *)(PHYSADDR(VMLINUX_LOAD_ADDRESS) + 8);
+}
+
+efi_status_t efi_boot_kernel(void *handle, efi_loaded_image_t *image,
+ unsigned long kernel_addr, char *cmdline_ptr)
+{
+ kernel_entry_t real_kernel_entry;
+ struct exit_boot_struct priv;
+ unsigned long desc_size;
+ efi_status_t status;
+ u32 desc_ver;
+
+ status = efi_alloc_virtmap(&priv.runtime_map, &desc_size, &desc_ver);
+ if (status != EFI_SUCCESS) {
+ efi_err("Unable to retrieve UEFI memory map.\n");
+ return status;
+ }
+
+ efi_info("Exiting boot services\n");
+
+ efi_novamap = false;
+ status = efi_exit_boot_services(handle, &priv, exit_boot_func);
+ if (status != EFI_SUCCESS)
+ return status;
+
+ /* Install the new virtual address map */
+ efi_rt_call(set_virtual_address_map,
+ priv.runtime_entry_count * desc_size, desc_size,
+ desc_ver, priv.runtime_map);
+
+ /* Config Direct Mapping */
+ csr_write64(CSR_DMW0_INIT, LOONGARCH_CSR_DMWIN0);
+ csr_write64(CSR_DMW1_INIT, LOONGARCH_CSR_DMWIN1);
+
+ real_kernel_entry = (void *)kernel_entry_address();
+
+ real_kernel_entry(true, (unsigned long)cmdline_ptr,
+ (unsigned long)efi_system_table);
+}
diff --git a/drivers/firmware/efi/libstub/mem.c b/drivers/firmware/efi/libstub/mem.c
index 45841ef55a9f..4f1fa302234d 100644
--- a/drivers/firmware/efi/libstub/mem.c
+++ b/drivers/firmware/efi/libstub/mem.c
@@ -89,9 +89,12 @@ efi_status_t efi_allocate_pages(unsigned long size, unsigned long *addr,
efi_physical_addr_t alloc_addr;
efi_status_t status;
+ max = min(max, EFI_ALLOC_LIMIT);
+
if (EFI_ALLOC_ALIGN > EFI_PAGE_SIZE)
return efi_allocate_pages_aligned(size, addr, max,
- EFI_ALLOC_ALIGN);
+ EFI_ALLOC_ALIGN,
+ EFI_LOADER_DATA);
alloc_addr = ALIGN_DOWN(max + 1, EFI_ALLOC_ALIGN) - 1;
status = efi_bs_call(allocate_pages, EFI_ALLOCATE_MAX_ADDRESS,
diff --git a/drivers/firmware/efi/libstub/printk.c b/drivers/firmware/efi/libstub/printk.c
new file mode 100644
index 000000000000..3a67a2cea7bd
--- /dev/null
+++ b/drivers/firmware/efi/libstub/printk.c
@@ -0,0 +1,154 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/stdarg.h>
+
+#include <linux/ctype.h>
+#include <linux/efi.h>
+#include <linux/kernel.h>
+#include <linux/printk.h> /* For CONSOLE_LOGLEVEL_* */
+#include <asm/efi.h>
+#include <asm/setup.h>
+
+#include "efistub.h"
+
+int efi_loglevel = CONSOLE_LOGLEVEL_DEFAULT;
+
+/**
+ * efi_char16_puts() - Write a UCS-2 encoded string to the console
+ * @str: UCS-2 encoded string
+ */
+void efi_char16_puts(efi_char16_t *str)
+{
+ efi_call_proto(efi_table_attr(efi_system_table, con_out),
+ output_string, str);
+}
+
+static
+u32 utf8_to_utf32(const u8 **s8)
+{
+ u32 c32;
+ u8 c0, cx;
+ size_t clen, i;
+
+ c0 = cx = *(*s8)++;
+ /*
+ * The position of the most-significant 0 bit gives us the length of
+ * a multi-octet encoding.
+ */
+ for (clen = 0; cx & 0x80; ++clen)
+ cx <<= 1;
+ /*
+ * If the 0 bit is in position 8, this is a valid single-octet
+ * encoding. If the 0 bit is in position 7 or positions 1-3, the
+ * encoding is invalid.
+ * In either case, we just return the first octet.
+ */
+ if (clen < 2 || clen > 4)
+ return c0;
+ /* Get the bits from the first octet. */
+ c32 = cx >> clen--;
+ for (i = 0; i < clen; ++i) {
+ /* Trailing octets must have 10 in most significant bits. */
+ cx = (*s8)[i] ^ 0x80;
+ if (cx & 0xc0)
+ return c0;
+ c32 = (c32 << 6) | cx;
+ }
+ /*
+ * Check for validity:
+ * - The character must be in the Unicode range.
+ * - It must not be a surrogate.
+ * - It must be encoded using the correct number of octets.
+ */
+ if (c32 > 0x10ffff ||
+ (c32 & 0xf800) == 0xd800 ||
+ clen != (c32 >= 0x80) + (c32 >= 0x800) + (c32 >= 0x10000))
+ return c0;
+ *s8 += clen;
+ return c32;
+}
+
+/**
+ * efi_puts() - Write a UTF-8 encoded string to the console
+ * @str: UTF-8 encoded string
+ */
+void efi_puts(const char *str)
+{
+ efi_char16_t buf[128];
+ size_t pos = 0, lim = ARRAY_SIZE(buf);
+ const u8 *s8 = (const u8 *)str;
+ u32 c32;
+
+ while (*s8) {
+ if (*s8 == '\n')
+ buf[pos++] = L'\r';
+ c32 = utf8_to_utf32(&s8);
+ if (c32 < 0x10000) {
+ /* Characters in plane 0 use a single word. */
+ buf[pos++] = c32;
+ } else {
+ /*
+ * Characters in other planes encode into a surrogate
+ * pair.
+ */
+ buf[pos++] = (0xd800 - (0x10000 >> 10)) + (c32 >> 10);
+ buf[pos++] = 0xdc00 + (c32 & 0x3ff);
+ }
+ if (*s8 == '\0' || pos >= lim - 2) {
+ buf[pos] = L'\0';
+ efi_char16_puts(buf);
+ pos = 0;
+ }
+ }
+}
+
+/**
+ * efi_printk() - Print a kernel message
+ * @fmt: format string
+ *
+ * The first letter of the format string is used to determine the logging level
+ * of the message. If the level is less then the current EFI logging level, the
+ * message is suppressed. The message will be truncated to 255 bytes.
+ *
+ * Return: number of printed characters
+ */
+int efi_printk(const char *fmt, ...)
+{
+ char printf_buf[256];
+ va_list args;
+ int printed;
+ int loglevel = printk_get_level(fmt);
+
+ switch (loglevel) {
+ case '0' ... '9':
+ loglevel -= '0';
+ break;
+ default:
+ /*
+ * Use loglevel -1 for cases where we just want to print to
+ * the screen.
+ */
+ loglevel = -1;
+ break;
+ }
+
+ if (loglevel >= efi_loglevel)
+ return 0;
+
+ if (loglevel >= 0)
+ efi_puts("EFI stub: ");
+
+ fmt = printk_skip_level(fmt);
+
+ va_start(args, fmt);
+ printed = vsnprintf(printf_buf, sizeof(printf_buf), fmt, args);
+ va_end(args);
+
+ efi_puts(printf_buf);
+ if (printed >= sizeof(printf_buf)) {
+ efi_puts("[Message truncated]\n");
+ return -1;
+ }
+
+ return printed;
+}
diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c
index 33ab56769595..7109b8a2dcba 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -67,47 +67,113 @@ efi_status_t efi_random_get_seed(void)
efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
efi_guid_t rng_algo_raw = EFI_RNG_ALGORITHM_RAW;
efi_guid_t rng_table_guid = LINUX_EFI_RANDOM_SEED_TABLE_GUID;
+ struct linux_efi_random_seed *prev_seed, *seed = NULL;
+ int prev_seed_size = 0, seed_size = EFI_RANDOM_SEED_SIZE;
+ unsigned long nv_seed_size = 0, offset = 0;
efi_rng_protocol_t *rng = NULL;
- struct linux_efi_random_seed *seed = NULL;
efi_status_t status;
status = efi_bs_call(locate_protocol, &rng_proto, NULL, (void **)&rng);
if (status != EFI_SUCCESS)
+ seed_size = 0;
+
+ // Call GetVariable() with a zero length buffer to obtain the size
+ get_efi_var(L"RandomSeed", &rng_table_guid, NULL, &nv_seed_size, NULL);
+ if (!seed_size && !nv_seed_size)
return status;
+ seed_size += nv_seed_size;
+
+ /*
+ * Check whether a seed was provided by a prior boot stage. In that
+ * case, instead of overwriting it, let's create a new buffer that can
+ * hold both, and concatenate the existing and the new seeds.
+ * Note that we should read the seed size with caution, in case the
+ * table got corrupted in memory somehow.
+ */
+ prev_seed = get_efi_config_table(rng_table_guid);
+ if (prev_seed && prev_seed->size <= 512U) {
+ prev_seed_size = prev_seed->size;
+ seed_size += prev_seed_size;
+ }
+
/*
* Use EFI_ACPI_RECLAIM_MEMORY here so that it is guaranteed that the
* allocation will survive a kexec reboot (although we refresh the seed
* beforehand)
*/
status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
- sizeof(*seed) + EFI_RANDOM_SEED_SIZE,
+ struct_size(seed, bits, seed_size),
(void **)&seed);
- if (status != EFI_SUCCESS)
- return status;
-
- status = efi_call_proto(rng, get_rng, &rng_algo_raw,
- EFI_RANDOM_SEED_SIZE, seed->bits);
+ if (status != EFI_SUCCESS) {
+ efi_warn("Failed to allocate memory for RNG seed.\n");
+ goto err_warn;
+ }
- if (status == EFI_UNSUPPORTED)
- /*
- * Use whatever algorithm we have available if the raw algorithm
- * is not implemented.
- */
- status = efi_call_proto(rng, get_rng, NULL,
+ if (rng) {
+ status = efi_call_proto(rng, get_rng, &rng_algo_raw,
EFI_RANDOM_SEED_SIZE, seed->bits);
- if (status != EFI_SUCCESS)
+ if (status == EFI_UNSUPPORTED)
+ /*
+ * Use whatever algorithm we have available if the raw algorithm
+ * is not implemented.
+ */
+ status = efi_call_proto(rng, get_rng, NULL,
+ EFI_RANDOM_SEED_SIZE, seed->bits);
+
+ if (status == EFI_SUCCESS)
+ offset = EFI_RANDOM_SEED_SIZE;
+ }
+
+ if (nv_seed_size) {
+ status = get_efi_var(L"RandomSeed", &rng_table_guid, NULL,
+ &nv_seed_size, seed->bits + offset);
+
+ if (status == EFI_SUCCESS)
+ /*
+ * We delete the seed here, and /hope/ that this causes
+ * EFI to also zero out its representation on disk.
+ * This is somewhat idealistic, but overwriting the
+ * variable with zeros is likely just as fraught too.
+ * TODO: in the future, maybe we can hash it forward
+ * instead, and write a new seed.
+ */
+ status = set_efi_var(L"RandomSeed", &rng_table_guid, 0,
+ 0, NULL);
+
+ if (status == EFI_SUCCESS)
+ offset += nv_seed_size;
+ else
+ memzero_explicit(seed->bits + offset, nv_seed_size);
+ }
+
+ if (!offset)
goto err_freepool;
- seed->size = EFI_RANDOM_SEED_SIZE;
+ if (prev_seed_size) {
+ memcpy(seed->bits + offset, prev_seed->bits, prev_seed_size);
+ offset += prev_seed_size;
+ }
+
+ seed->size = offset;
status = efi_bs_call(install_configuration_table, &rng_table_guid, seed);
if (status != EFI_SUCCESS)
goto err_freepool;
+ if (prev_seed_size) {
+ /* wipe and free the old seed if we managed to install the new one */
+ memzero_explicit(prev_seed->bits, prev_seed_size);
+ efi_bs_call(free_pool, prev_seed);
+ }
return EFI_SUCCESS;
err_freepool:
+ memzero_explicit(seed, struct_size(seed, bits, seed_size));
efi_bs_call(free_pool, seed);
+ efi_warn("Failed to obtain seed from EFI_RNG_PROTOCOL or EFI variable\n");
+err_warn:
+ if (prev_seed)
+ efi_warn("Retaining bootloader-supplied seed only");
return status;
}
diff --git a/drivers/firmware/efi/libstub/randomalloc.c b/drivers/firmware/efi/libstub/randomalloc.c
index 9fb5869896be..1692d19ae80f 100644
--- a/drivers/firmware/efi/libstub/randomalloc.c
+++ b/drivers/firmware/efi/libstub/randomalloc.c
@@ -29,7 +29,7 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
return 0;
region_end = min(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - 1,
- (u64)ULONG_MAX);
+ (u64)EFI_ALLOC_LIMIT);
if (region_end < size)
return 0;
@@ -53,7 +53,8 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
efi_status_t efi_random_alloc(unsigned long size,
unsigned long align,
unsigned long *addr,
- unsigned long random_seed)
+ unsigned long random_seed,
+ int memory_type)
{
unsigned long total_slots = 0, target_slot;
unsigned long total_mirrored_slots = 0;
@@ -118,7 +119,7 @@ efi_status_t efi_random_alloc(unsigned long size,
pages = size / EFI_PAGE_SIZE;
status = efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS,
- EFI_LOADER_DATA, pages, &target);
+ memory_type, pages, &target);
if (status == EFI_SUCCESS)
*addr = target;
break;
diff --git a/drivers/firmware/efi/libstub/riscv-stub.c b/drivers/firmware/efi/libstub/riscv-stub.c
index b450ebf95977..145c9f0ba217 100644
--- a/drivers/firmware/efi/libstub/riscv-stub.c
+++ b/drivers/firmware/efi/libstub/riscv-stub.c
@@ -4,7 +4,6 @@
*/
#include <linux/efi.h>
-#include <linux/libfdt.h>
#include <asm/efi.h>
#include <asm/sections.h>
@@ -12,92 +11,16 @@
#include "efistub.h"
-/*
- * RISC-V requires the kernel image to placed 2 MB aligned base for 64 bit and
- * 4MB for 32 bit.
- */
-#ifdef CONFIG_64BIT
-#define MIN_KIMG_ALIGN SZ_2M
-#else
-#define MIN_KIMG_ALIGN SZ_4M
-#endif
-
-typedef void __noreturn (*jump_kernel_func)(unsigned long, unsigned long);
-
-static unsigned long hartid;
-
-static int get_boot_hartid_from_fdt(void)
-{
- const void *fdt;
- int chosen_node, len;
- const void *prop;
-
- fdt = get_efi_config_table(DEVICE_TREE_GUID);
- if (!fdt)
- return -EINVAL;
-
- chosen_node = fdt_path_offset(fdt, "/chosen");
- if (chosen_node < 0)
- return -EINVAL;
-
- prop = fdt_getprop((void *)fdt, chosen_node, "boot-hartid", &len);
- if (!prop)
- return -EINVAL;
-
- if (len == sizeof(u32))
- hartid = (unsigned long) fdt32_to_cpu(*(fdt32_t *)prop);
- else if (len == sizeof(u64))
- hartid = (unsigned long) fdt64_to_cpu(__get_unaligned_t(fdt64_t, prop));
- else
- return -EINVAL;
-
- return 0;
-}
-
-static efi_status_t get_boot_hartid_from_efi(void)
+unsigned long stext_offset(void)
{
- efi_guid_t boot_protocol_guid = RISCV_EFI_BOOT_PROTOCOL_GUID;
- struct riscv_efi_boot_protocol *boot_protocol;
- efi_status_t status;
-
- status = efi_bs_call(locate_protocol, &boot_protocol_guid, NULL,
- (void **)&boot_protocol);
- if (status != EFI_SUCCESS)
- return status;
- return efi_call_proto(boot_protocol, get_boot_hartid, &hartid);
-}
-
-efi_status_t check_platform_features(void)
-{
- efi_status_t status;
- int ret;
-
- status = get_boot_hartid_from_efi();
- if (status != EFI_SUCCESS) {
- ret = get_boot_hartid_from_fdt();
- if (ret) {
- efi_err("Failed to get boot hartid!\n");
- return EFI_UNSUPPORTED;
- }
- }
- return EFI_SUCCESS;
-}
-
-void __noreturn efi_enter_kernel(unsigned long entrypoint, unsigned long fdt,
- unsigned long fdt_size)
-{
- unsigned long stext_offset = _start_kernel - _start;
- unsigned long kernel_entry = entrypoint + stext_offset;
- jump_kernel_func jump_kernel = (jump_kernel_func)kernel_entry;
-
/*
- * Jump to real kernel here with following constraints.
- * 1. MMU should be disabled.
- * 2. a0 should contain hartid
- * 3. a1 should DT address
+ * When built as part of the kernel, the EFI stub cannot branch to the
+ * kernel proper via the image header, as the PE/COFF header is
+ * strictly not part of the in-memory presentation of the image, only
+ * of the file representation. So instead, we need to jump to the
+ * actual entrypoint in the .text region of the image.
*/
- csr_write(CSR_SATP, 0);
- jump_kernel(hartid, fdt);
+ return _start_kernel - _start;
}
efi_status_t handle_kernel_image(unsigned long *image_addr,
@@ -125,9 +48,10 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
* lowest possible memory region as long as the address and size meets
* the alignment constraints.
*/
- preferred_addr = MIN_KIMG_ALIGN;
+ preferred_addr = EFI_KIMG_PREFERRED_ADDRESS;
status = efi_relocate_kernel(image_addr, kernel_size, *image_size,
- preferred_addr, MIN_KIMG_ALIGN, 0x0);
+ preferred_addr, efi_get_kimg_min_align(),
+ 0x0);
if (status != EFI_SUCCESS) {
efi_err("Failed to relocate kernel\n");
diff --git a/drivers/firmware/efi/libstub/riscv.c b/drivers/firmware/efi/libstub/riscv.c
new file mode 100644
index 000000000000..8022b104c3e6
--- /dev/null
+++ b/drivers/firmware/efi/libstub/riscv.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020 Western Digital Corporation or its affiliates.
+ */
+
+#include <linux/efi.h>
+#include <linux/libfdt.h>
+
+#include <asm/efi.h>
+#include <asm/unaligned.h>
+
+#include "efistub.h"
+
+typedef void __noreturn (*jump_kernel_func)(unsigned long, unsigned long);
+
+static unsigned long hartid;
+
+static int get_boot_hartid_from_fdt(void)
+{
+ const void *fdt;
+ int chosen_node, len;
+ const void *prop;
+
+ fdt = get_efi_config_table(DEVICE_TREE_GUID);
+ if (!fdt)
+ return -EINVAL;
+
+ chosen_node = fdt_path_offset(fdt, "/chosen");
+ if (chosen_node < 0)
+ return -EINVAL;
+
+ prop = fdt_getprop((void *)fdt, chosen_node, "boot-hartid", &len);
+ if (!prop)
+ return -EINVAL;
+
+ if (len == sizeof(u32))
+ hartid = (unsigned long) fdt32_to_cpu(*(fdt32_t *)prop);
+ else if (len == sizeof(u64))
+ hartid = (unsigned long) fdt64_to_cpu(__get_unaligned_t(fdt64_t, prop));
+ else
+ return -EINVAL;
+
+ return 0;
+}
+
+static efi_status_t get_boot_hartid_from_efi(void)
+{
+ efi_guid_t boot_protocol_guid = RISCV_EFI_BOOT_PROTOCOL_GUID;
+ struct riscv_efi_boot_protocol *boot_protocol;
+ efi_status_t status;
+
+ status = efi_bs_call(locate_protocol, &boot_protocol_guid, NULL,
+ (void **)&boot_protocol);
+ if (status != EFI_SUCCESS)
+ return status;
+ return efi_call_proto(boot_protocol, get_boot_hartid, &hartid);
+}
+
+efi_status_t check_platform_features(void)
+{
+ efi_status_t status;
+ int ret;
+
+ status = get_boot_hartid_from_efi();
+ if (status != EFI_SUCCESS) {
+ ret = get_boot_hartid_from_fdt();
+ if (ret) {
+ efi_err("Failed to get boot hartid!\n");
+ return EFI_UNSUPPORTED;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+unsigned long __weak stext_offset(void)
+{
+ /*
+ * This fallback definition is used by the EFI zboot stub, which loads
+ * the entire image so it can branch via the image header at offset #0.
+ */
+ return 0;
+}
+
+void __noreturn efi_enter_kernel(unsigned long entrypoint, unsigned long fdt,
+ unsigned long fdt_size)
+{
+ unsigned long kernel_entry = entrypoint + stext_offset();
+ jump_kernel_func jump_kernel = (jump_kernel_func)kernel_entry;
+
+ /*
+ * Jump to real kernel here with following constraints.
+ * 1. MMU should be disabled.
+ * 2. a0 should contain hartid
+ * 3. a1 should DT address
+ */
+ csr_write(CSR_SATP, 0);
+ jump_kernel(hartid, fdt);
+}
diff --git a/drivers/firmware/efi/libstub/screen_info.c b/drivers/firmware/efi/libstub/screen_info.c
new file mode 100644
index 000000000000..8e76a8b384ba
--- /dev/null
+++ b/drivers/firmware/efi/libstub/screen_info.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/efi.h>
+#include <asm/efi.h>
+
+#include "efistub.h"
+
+/*
+ * There are two ways of populating the core kernel's struct screen_info via the stub:
+ * - using a configuration table, like below, which relies on the EFI init code
+ * to locate the table and copy the contents;
+ * - by linking directly to the core kernel's copy of the global symbol.
+ *
+ * The latter is preferred because it makes the EFIFB earlycon available very
+ * early, but it only works if the EFI stub is part of the core kernel image
+ * itself. The zboot decompressor can only use the configuration table
+ * approach.
+ *
+ * In order to support both methods from the same build of the EFI stub
+ * library, provide this dummy global definition of struct screen_info. If it
+ * is required to satisfy a link dependency, it means we need to override the
+ * __weak alloc and free methods with the ones below, and those will be pulled
+ * in as well.
+ */
+struct screen_info screen_info;
+
+static efi_guid_t screen_info_guid = LINUX_EFI_SCREEN_INFO_TABLE_GUID;
+
+struct screen_info *alloc_screen_info(void)
+{
+ struct screen_info *si;
+ efi_status_t status;
+
+ status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY,
+ sizeof(*si), (void **)&si);
+
+ if (status != EFI_SUCCESS)
+ return NULL;
+
+ status = efi_bs_call(install_configuration_table,
+ &screen_info_guid, si);
+ if (status == EFI_SUCCESS)
+ return si;
+
+ efi_bs_call(free_pool, si);
+ return NULL;
+}
+
+void free_screen_info(struct screen_info *si)
+{
+ if (!si)
+ return;
+
+ efi_bs_call(install_configuration_table, &screen_info_guid, NULL);
+ efi_bs_call(free_pool, si);
+}
diff --git a/drivers/firmware/efi/libstub/string.c b/drivers/firmware/efi/libstub/string.c
index 5d13e43869ee..168fe8e79abc 100644
--- a/drivers/firmware/efi/libstub/string.c
+++ b/drivers/firmware/efi/libstub/string.c
@@ -11,7 +11,37 @@
#include <linux/types.h>
#include <linux/string.h>
-#ifndef __HAVE_ARCH_STRSTR
+#ifndef EFI_HAVE_STRLEN
+/**
+ * strlen - Find the length of a string
+ * @s: The string to be sized
+ */
+size_t strlen(const char *s)
+{
+ const char *sc;
+
+ for (sc = s; *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+#endif
+
+#ifndef EFI_HAVE_STRNLEN
+/**
+ * strnlen - Find the length of a length-limited string
+ * @s: The string to be sized
+ * @count: The maximum number of bytes to search
+ */
+size_t strnlen(const char *s, size_t count)
+{
+ const char *sc;
+
+ for (sc = s; count-- && *sc != '\0'; ++sc)
+ /* nothing */;
+ return sc - s;
+}
+#endif
+
/**
* strstr - Find the first substring in a %NUL terminated string
* @s1: The string to be searched
@@ -33,9 +63,29 @@ char *strstr(const char *s1, const char *s2)
}
return NULL;
}
+
+#ifndef EFI_HAVE_STRCMP
+/**
+ * strcmp - Compare two strings
+ * @cs: One string
+ * @ct: Another string
+ */
+int strcmp(const char *cs, const char *ct)
+{
+ unsigned char c1, c2;
+
+ while (1) {
+ c1 = *cs++;
+ c2 = *ct++;
+ if (c1 != c2)
+ return c1 < c2 ? -1 : 1;
+ if (!c1)
+ break;
+ }
+ return 0;
+}
#endif
-#ifndef __HAVE_ARCH_STRNCMP
/**
* strncmp - Compare two length-limited strings
* @cs: One string
@@ -57,7 +107,6 @@ int strncmp(const char *cs, const char *ct, size_t count)
}
return 0;
}
-#endif
/* Works only for digits and letters, but small and fast */
#define TOLOWER(x) ((x) | 0x20)
@@ -113,3 +162,43 @@ long simple_strtol(const char *cp, char **endp, unsigned int base)
return simple_strtoull(cp, endp, base);
}
+
+#ifdef CONFIG_EFI_PARAMS_FROM_FDT
+#ifndef EFI_HAVE_STRRCHR
+/**
+ * strrchr - Find the last occurrence of a character in a string
+ * @s: The string to be searched
+ * @c: The character to search for
+ */
+char *strrchr(const char *s, int c)
+{
+ const char *last = NULL;
+ do {
+ if (*s == (char)c)
+ last = s;
+ } while (*s++);
+ return (char *)last;
+}
+#endif
+#ifndef EFI_HAVE_MEMCHR
+/**
+ * memchr - Find a character in an area of memory.
+ * @s: The memory area
+ * @c: The byte to search for
+ * @n: The size of the area.
+ *
+ * returns the address of the first occurrence of @c, or %NULL
+ * if @c is not found
+ */
+void *memchr(const void *s, int c, size_t n)
+{
+ const unsigned char *p = s;
+ while (n-- != 0) {
+ if ((unsigned char)c == *p++) {
+ return (void *)(p - 1);
+ }
+ }
+ return NULL;
+}
+#endif
+#endif
diff --git a/drivers/firmware/efi/libstub/x86-stub.c b/drivers/firmware/efi/libstub/x86-stub.c
index 33a7811e12c6..a0bfd31358ba 100644
--- a/drivers/firmware/efi/libstub/x86-stub.c
+++ b/drivers/firmware/efi/libstub/x86-stub.c
@@ -23,7 +23,7 @@
const efi_system_table_t *efi_system_table;
const efi_dxe_services_table_t *efi_dxe_table;
-extern u32 image_offset;
+u32 image_offset __section(".data");
static efi_loaded_image_t *image = NULL;
static efi_status_t
diff --git a/drivers/firmware/efi/libstub/zboot-header.S b/drivers/firmware/efi/libstub/zboot-header.S
index 9e6fe061ab07..ec4525d40e0c 100644
--- a/drivers/firmware/efi/libstub/zboot-header.S
+++ b/drivers/firmware/efi/libstub/zboot-header.S
@@ -17,10 +17,11 @@ __efistub_efi_zboot_header:
.long MZ_MAGIC
.ascii "zimg" // image type
.long __efistub__gzdata_start - .Ldoshdr // payload offset
- .long __efistub__gzdata_size - ZBOOT_SIZE_LEN // payload size
+ .long __efistub__gzdata_size - 12 // payload size
.long 0, 0 // reserved
.asciz COMP_TYPE // compression type
- .org .Ldoshdr + 0x3c
+ .org .Ldoshdr + 0x38
+ .long LINUX_PE_MAGIC
.long .Lpehdr - .Ldoshdr // PE header offset
.Lpehdr:
diff --git a/drivers/firmware/efi/libstub/zboot.c b/drivers/firmware/efi/libstub/zboot.c
index ea72c8f27da6..66be5fdc6b58 100644
--- a/drivers/firmware/efi/libstub/zboot.c
+++ b/drivers/firmware/efi/libstub/zboot.c
@@ -32,271 +32,116 @@ static unsigned long free_mem_ptr, free_mem_end_ptr;
extern char efi_zboot_header[];
extern char _gzdata_start[], _gzdata_end[];
-static void log(efi_char16_t str[])
-{
- efi_call_proto(efi_table_attr(efi_system_table, con_out),
- output_string, L"EFI decompressor: ");
- efi_call_proto(efi_table_attr(efi_system_table, con_out),
- output_string, str);
- efi_call_proto(efi_table_attr(efi_system_table, con_out),
- output_string, L"\n");
-}
-
static void error(char *x)
{
- log(L"error() called from decompressor library\n");
-}
-
-// Local version to avoid pulling in memcmp()
-static bool guids_eq(const efi_guid_t *a, const efi_guid_t *b)
-{
- const u32 *l = (u32 *)a;
- const u32 *r = (u32 *)b;
-
- return l[0] == r[0] && l[1] == r[1] && l[2] == r[2] && l[3] == r[3];
-}
-
-static efi_status_t __efiapi
-load_file(efi_load_file_protocol_t *this, efi_device_path_protocol_t *rem,
- bool boot_policy, unsigned long *bufsize, void *buffer)
-{
- unsigned long compressed_size = _gzdata_end - _gzdata_start;
- struct efi_vendor_dev_path *vendor_dp;
- bool decompress = false;
- unsigned long size;
- int ret;
-
- if (rem == NULL || bufsize == NULL)
- return EFI_INVALID_PARAMETER;
-
- if (boot_policy)
- return EFI_UNSUPPORTED;
-
- // Look for our vendor media device node in the remaining file path
- if (rem->type == EFI_DEV_MEDIA &&
- rem->sub_type == EFI_DEV_MEDIA_VENDOR) {
- vendor_dp = container_of(rem, struct efi_vendor_dev_path, header);
- if (!guids_eq(&vendor_dp->vendorguid, &LINUX_EFI_ZBOOT_MEDIA_GUID))
- return EFI_NOT_FOUND;
-
- decompress = true;
- rem = (void *)(vendor_dp + 1);
- }
-
- if (rem->type != EFI_DEV_END_PATH ||
- rem->sub_type != EFI_DEV_END_ENTIRE)
- return EFI_NOT_FOUND;
-
- // The uncompressed size of the payload is appended to the raw bit
- // stream, and may therefore appear misaligned in memory
- size = decompress ? get_unaligned_le32(_gzdata_end - 4)
- : compressed_size;
- if (buffer == NULL || *bufsize < size) {
- *bufsize = size;
- return EFI_BUFFER_TOO_SMALL;
- }
-
- if (decompress) {
- ret = __decompress(_gzdata_start, compressed_size, NULL, NULL,
- buffer, size, NULL, error);
- if (ret < 0) {
- log(L"Decompression failed");
- return EFI_DEVICE_ERROR;
- }
- } else {
- memcpy(buffer, _gzdata_start, compressed_size);
- }
-
- return EFI_SUCCESS;
-}
-
-// Return the length in bytes of the device path up to the first end node.
-static int device_path_length(const efi_device_path_protocol_t *dp)
-{
- int len = 0;
-
- while (dp->type != EFI_DEV_END_PATH) {
- len += dp->length;
- dp = (void *)((u8 *)dp + dp->length);
- }
- return len;
+ efi_err("EFI decompressor: %s\n", x);
}
-static void append_rel_offset_node(efi_device_path_protocol_t **dp,
- unsigned long start, unsigned long end)
+static unsigned long alloc_preferred_address(unsigned long alloc_size)
{
- struct efi_rel_offset_dev_path *rodp = (void *)*dp;
-
- rodp->header.type = EFI_DEV_MEDIA;
- rodp->header.sub_type = EFI_DEV_MEDIA_REL_OFFSET;
- rodp->header.length = sizeof(struct efi_rel_offset_dev_path);
- rodp->reserved = 0;
- rodp->starting_offset = start;
- rodp->ending_offset = end;
+#ifdef EFI_KIMG_PREFERRED_ADDRESS
+ efi_physical_addr_t efi_addr = EFI_KIMG_PREFERRED_ADDRESS;
- *dp = (void *)(rodp + 1);
-}
-
-static void append_ven_media_node(efi_device_path_protocol_t **dp,
- efi_guid_t *guid)
-{
- struct efi_vendor_dev_path *vmdp = (void *)*dp;
-
- vmdp->header.type = EFI_DEV_MEDIA;
- vmdp->header.sub_type = EFI_DEV_MEDIA_VENDOR;
- vmdp->header.length = sizeof(struct efi_vendor_dev_path);
- vmdp->vendorguid = *guid;
-
- *dp = (void *)(vmdp + 1);
+ if (efi_bs_call(allocate_pages, EFI_ALLOCATE_ADDRESS, EFI_LOADER_DATA,
+ alloc_size / EFI_PAGE_SIZE, &efi_addr) == EFI_SUCCESS)
+ return efi_addr;
+#endif
+ return ULONG_MAX;
}
-static void append_end_node(efi_device_path_protocol_t **dp)
+void __weak efi_cache_sync_image(unsigned long image_base,
+ unsigned long alloc_size,
+ unsigned long code_size)
{
- (*dp)->type = EFI_DEV_END_PATH;
- (*dp)->sub_type = EFI_DEV_END_ENTIRE;
- (*dp)->length = sizeof(struct efi_generic_dev_path);
-
- ++*dp;
+ // Provided by the arch to perform the cache maintenance necessary for
+ // executable code loaded into memory to be safe for execution.
}
asmlinkage efi_status_t __efiapi
efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
{
- struct efi_mem_mapped_dev_path mmdp = {
- .header.type = EFI_DEV_HW,
- .header.sub_type = EFI_DEV_MEM_MAPPED,
- .header.length = sizeof(struct efi_mem_mapped_dev_path)
- };
- efi_device_path_protocol_t *parent_dp, *dpp, *lf2_dp, *li_dp;
- efi_load_file2_protocol_t zboot_load_file2;
- efi_loaded_image_t *parent, *child;
- unsigned long exit_data_size;
- efi_handle_t child_handle;
- efi_handle_t zboot_handle;
- efi_char16_t *exit_data;
+ unsigned long compressed_size = _gzdata_end - _gzdata_start;
+ unsigned long image_base, alloc_size, code_size;
+ efi_loaded_image_t *image;
efi_status_t status;
- void *dp_alloc;
- int dp_len;
+ char *cmdline_ptr;
+ int ret;
WRITE_ONCE(efi_system_table, systab);
free_mem_ptr = (unsigned long)&zboot_heap;
free_mem_end_ptr = free_mem_ptr + sizeof(zboot_heap);
- exit_data = NULL;
- exit_data_size = 0;
-
status = efi_bs_call(handle_protocol, handle,
- &LOADED_IMAGE_PROTOCOL_GUID, (void **)&parent);
+ &LOADED_IMAGE_PROTOCOL_GUID, (void **)&image);
if (status != EFI_SUCCESS) {
- log(L"Failed to locate parent's loaded image protocol");
+ error("Failed to locate parent's loaded image protocol");
return status;
}
- status = efi_bs_call(handle_protocol, handle,
- &LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID,
- (void **)&parent_dp);
- if (status != EFI_SUCCESS || parent_dp == NULL) {
- // Create a MemoryMapped() device path node to describe
- // the parent image if no device path was provided.
- mmdp.memory_type = parent->image_code_type;
- mmdp.starting_addr = (unsigned long)parent->image_base;
- mmdp.ending_addr = (unsigned long)parent->image_base +
- parent->image_size - 1;
- parent_dp = &mmdp.header;
- dp_len = sizeof(mmdp);
- } else {
- dp_len = device_path_length(parent_dp);
- }
-
- // Allocate some pool memory for device path protocol data
- status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
- 2 * (dp_len + sizeof(struct efi_rel_offset_dev_path) +
- sizeof(struct efi_generic_dev_path)) +
- sizeof(struct efi_vendor_dev_path),
- (void **)&dp_alloc);
- if (status != EFI_SUCCESS) {
- log(L"Failed to allocate device path pool memory");
+ status = efi_handle_cmdline(image, &cmdline_ptr);
+ if (status != EFI_SUCCESS)
return status;
- }
- // Create a device path describing the compressed payload in this image
- // <...parent_dp...>/Offset(<start>, <end>)
- lf2_dp = memcpy(dp_alloc, parent_dp, dp_len);
- dpp = (void *)((u8 *)lf2_dp + dp_len);
- append_rel_offset_node(&dpp,
- (unsigned long)(_gzdata_start - efi_zboot_header),
- (unsigned long)(_gzdata_end - efi_zboot_header - 1));
- append_end_node(&dpp);
-
- // Create a device path describing the decompressed payload in this image
- // <...parent_dp...>/Offset(<start>, <end>)/VenMedia(ZBOOT_MEDIA_GUID)
- dp_len += sizeof(struct efi_rel_offset_dev_path);
- li_dp = memcpy(dpp, lf2_dp, dp_len);
- dpp = (void *)((u8 *)li_dp + dp_len);
- append_ven_media_node(&dpp, &LINUX_EFI_ZBOOT_MEDIA_GUID);
- append_end_node(&dpp);
-
- zboot_handle = NULL;
- zboot_load_file2.load_file = load_file;
- status = efi_bs_call(install_multiple_protocol_interfaces,
- &zboot_handle,
- &EFI_DEVICE_PATH_PROTOCOL_GUID, lf2_dp,
- &EFI_LOAD_FILE2_PROTOCOL_GUID, &zboot_load_file2,
- NULL);
- if (status != EFI_SUCCESS) {
- log(L"Failed to install LoadFile2 protocol and device path");
- goto free_dpalloc;
- }
-
- status = efi_bs_call(load_image, false, handle, li_dp, NULL, 0,
- &child_handle);
- if (status != EFI_SUCCESS) {
- log(L"Failed to load image");
- goto uninstall_lf2;
- }
+ efi_info("Decompressing Linux Kernel...\n");
+
+ // SizeOfImage from the compressee's PE/COFF header
+ alloc_size = round_up(get_unaligned_le32(_gzdata_end - 4),
+ EFI_ALLOC_ALIGN);
+
+ // SizeOfHeaders and SizeOfCode from the compressee's PE/COFF header
+ code_size = get_unaligned_le32(_gzdata_end - 8) +
+ get_unaligned_le32(_gzdata_end - 12);
+
+ // If the architecture has a preferred address for the image,
+ // try that first.
+ image_base = alloc_preferred_address(alloc_size);
+ if (image_base == ULONG_MAX) {
+ unsigned long min_kimg_align = efi_get_kimg_min_align();
+ u32 seed = U32_MAX;
+
+ if (!IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
+ // Setting the random seed to 0x0 is the same as
+ // allocating as low as possible
+ seed = 0;
+ } else if (efi_nokaslr) {
+ efi_info("KASLR disabled on kernel command line\n");
+ } else {
+ status = efi_get_random_bytes(sizeof(seed), (u8 *)&seed);
+ if (status == EFI_NOT_FOUND) {
+ efi_info("EFI_RNG_PROTOCOL unavailable\n");
+ efi_nokaslr = true;
+ } else if (status != EFI_SUCCESS) {
+ efi_err("efi_get_random_bytes() failed (0x%lx)\n",
+ status);
+ efi_nokaslr = true;
+ }
+ }
- status = efi_bs_call(handle_protocol, child_handle,
- &LOADED_IMAGE_PROTOCOL_GUID, (void **)&child);
- if (status != EFI_SUCCESS) {
- log(L"Failed to locate child's loaded image protocol");
- goto unload_image;
+ status = efi_random_alloc(alloc_size, min_kimg_align, &image_base,
+ seed, EFI_LOADER_CODE);
+ if (status != EFI_SUCCESS) {
+ efi_err("Failed to allocate memory\n");
+ goto free_cmdline;
+ }
}
- // Copy the kernel command line
- child->load_options = parent->load_options;
- child->load_options_size = parent->load_options_size;
-
- status = efi_bs_call(start_image, child_handle, &exit_data_size,
- &exit_data);
- if (status != EFI_SUCCESS) {
- log(L"StartImage() returned with error");
- if (exit_data_size > 0)
- log(exit_data);
-
- // If StartImage() returns EFI_SECURITY_VIOLATION, the image is
- // not unloaded so we need to do it by hand.
- if (status == EFI_SECURITY_VIOLATION)
-unload_image:
- efi_bs_call(unload_image, child_handle);
+ // Decompress the payload into the newly allocated buffer.
+ ret = __decompress(_gzdata_start, compressed_size, NULL, NULL,
+ (void *)image_base, alloc_size, NULL, error);
+ if (ret < 0) {
+ error("Decompression failed");
+ status = EFI_DEVICE_ERROR;
+ goto free_image;
}
-uninstall_lf2:
- efi_bs_call(uninstall_multiple_protocol_interfaces,
- zboot_handle,
- &EFI_DEVICE_PATH_PROTOCOL_GUID, lf2_dp,
- &EFI_LOAD_FILE2_PROTOCOL_GUID, &zboot_load_file2,
- NULL);
-
-free_dpalloc:
- efi_bs_call(free_pool, dp_alloc);
+ efi_cache_sync_image(image_base, alloc_size, code_size);
- efi_bs_call(exit, handle, status, exit_data_size, exit_data);
+ status = efi_stub_common(handle, image, image_base, cmdline_ptr);
- // Free ExitData in case Exit() returned with a failure code,
- // but return the original status code.
- log(L"Exit() returned with failure code");
- if (exit_data != NULL)
- efi_bs_call(free_pool, exit_data);
+free_image:
+ efi_free(alloc_size, image_base);
+free_cmdline:
+ efi_bs_call(free_pool, cmdline_ptr);
return status;
}
diff --git a/drivers/firmware/efi/memmap.c b/drivers/firmware/efi/memmap.c
index 6ec7970dbd40..a1180461a445 100644
--- a/drivers/firmware/efi/memmap.c
+++ b/drivers/firmware/efi/memmap.c
@@ -9,82 +9,15 @@
#include <linux/kernel.h>
#include <linux/efi.h>
#include <linux/io.h>
-#include <asm/early_ioremap.h>
#include <linux/memblock.h>
#include <linux/slab.h>
-static phys_addr_t __init __efi_memmap_alloc_early(unsigned long size)
-{
- return memblock_phys_alloc(size, SMP_CACHE_BYTES);
-}
-
-static phys_addr_t __init __efi_memmap_alloc_late(unsigned long size)
-{
- unsigned int order = get_order(size);
- struct page *p = alloc_pages(GFP_KERNEL, order);
-
- if (!p)
- return 0;
-
- return PFN_PHYS(page_to_pfn(p));
-}
-
-void __init __efi_memmap_free(u64 phys, unsigned long size, unsigned long flags)
-{
- if (flags & EFI_MEMMAP_MEMBLOCK) {
- if (slab_is_available())
- memblock_free_late(phys, size);
- else
- memblock_phys_free(phys, size);
- } else if (flags & EFI_MEMMAP_SLAB) {
- struct page *p = pfn_to_page(PHYS_PFN(phys));
- unsigned int order = get_order(size);
-
- free_pages((unsigned long) page_address(p), order);
- }
-}
-
-static void __init efi_memmap_free(void)
-{
- __efi_memmap_free(efi.memmap.phys_map,
- efi.memmap.desc_size * efi.memmap.nr_map,
- efi.memmap.flags);
-}
-
-/**
- * efi_memmap_alloc - Allocate memory for the EFI memory map
- * @num_entries: Number of entries in the allocated map.
- * @data: efi memmap installation parameters
- *
- * Depending on whether mm_init() has already been invoked or not,
- * either memblock or "normal" page allocation is used.
- *
- * Returns zero on success, a negative error code on failure.
- */
-int __init efi_memmap_alloc(unsigned int num_entries,
- struct efi_memory_map_data *data)
-{
- /* Expect allocation parameters are zero initialized */
- WARN_ON(data->phys_map || data->size);
-
- data->size = num_entries * efi.memmap.desc_size;
- data->desc_version = efi.memmap.desc_version;
- data->desc_size = efi.memmap.desc_size;
- data->flags &= ~(EFI_MEMMAP_SLAB | EFI_MEMMAP_MEMBLOCK);
- data->flags |= efi.memmap.flags & EFI_MEMMAP_LATE;
-
- if (slab_is_available()) {
- data->flags |= EFI_MEMMAP_SLAB;
- data->phys_map = __efi_memmap_alloc_late(data->size);
- } else {
- data->flags |= EFI_MEMMAP_MEMBLOCK;
- data->phys_map = __efi_memmap_alloc_early(data->size);
- }
+#include <asm/early_ioremap.h>
+#include <asm/efi.h>
- if (!data->phys_map)
- return -ENOMEM;
- return 0;
-}
+#ifndef __efi_memmap_free
+#define __efi_memmap_free(phys, size, flags) do { } while (0)
+#endif
/**
* __efi_memmap_init - Common code for mapping the EFI memory map
@@ -101,14 +34,11 @@ int __init efi_memmap_alloc(unsigned int num_entries,
*
* Returns zero on success, a negative error code on failure.
*/
-static int __init __efi_memmap_init(struct efi_memory_map_data *data)
+int __init __efi_memmap_init(struct efi_memory_map_data *data)
{
struct efi_memory_map map;
phys_addr_t phys_map;
- if (efi_enabled(EFI_PARAVIRT))
- return 0;
-
phys_map = data->phys_map;
if (data->flags & EFI_MEMMAP_LATE)
@@ -121,8 +51,10 @@ static int __init __efi_memmap_init(struct efi_memory_map_data *data)
return -ENOMEM;
}
- /* NOP if data->flags & (EFI_MEMMAP_MEMBLOCK | EFI_MEMMAP_SLAB) == 0 */
- efi_memmap_free();
+ if (efi.memmap.flags & (EFI_MEMMAP_MEMBLOCK | EFI_MEMMAP_SLAB))
+ __efi_memmap_free(efi.memmap.phys_map,
+ efi.memmap.desc_size * efi.memmap.nr_map,
+ efi.memmap.flags);
map.phys_map = data->phys_map;
map.nr_map = data->size / data->desc_size;
@@ -220,158 +152,3 @@ int __init efi_memmap_init_late(phys_addr_t addr, unsigned long size)
return __efi_memmap_init(&data);
}
-
-/**
- * efi_memmap_install - Install a new EFI memory map in efi.memmap
- * @ctx: map allocation parameters (address, size, flags)
- *
- * Unlike efi_memmap_init_*(), this function does not allow the caller
- * to switch from early to late mappings. It simply uses the existing
- * mapping function and installs the new memmap.
- *
- * Returns zero on success, a negative error code on failure.
- */
-int __init efi_memmap_install(struct efi_memory_map_data *data)
-{
- efi_memmap_unmap();
-
- return __efi_memmap_init(data);
-}
-
-/**
- * efi_memmap_split_count - Count number of additional EFI memmap entries
- * @md: EFI memory descriptor to split
- * @range: Address range (start, end) to split around
- *
- * Returns the number of additional EFI memmap entries required to
- * accommodate @range.
- */
-int __init efi_memmap_split_count(efi_memory_desc_t *md, struct range *range)
-{
- u64 m_start, m_end;
- u64 start, end;
- int count = 0;
-
- start = md->phys_addr;
- end = start + (md->num_pages << EFI_PAGE_SHIFT) - 1;
-
- /* modifying range */
- m_start = range->start;
- m_end = range->end;
-
- if (m_start <= start) {
- /* split into 2 parts */
- if (start < m_end && m_end < end)
- count++;
- }
-
- if (start < m_start && m_start < end) {
- /* split into 3 parts */
- if (m_end < end)
- count += 2;
- /* split into 2 parts */
- if (end <= m_end)
- count++;
- }
-
- return count;
-}
-
-/**
- * efi_memmap_insert - Insert a memory region in an EFI memmap
- * @old_memmap: The existing EFI memory map structure
- * @buf: Address of buffer to store new map
- * @mem: Memory map entry to insert
- *
- * It is suggested that you call efi_memmap_split_count() first
- * to see how large @buf needs to be.
- */
-void __init efi_memmap_insert(struct efi_memory_map *old_memmap, void *buf,
- struct efi_mem_range *mem)
-{
- u64 m_start, m_end, m_attr;
- efi_memory_desc_t *md;
- u64 start, end;
- void *old, *new;
-
- /* modifying range */
- m_start = mem->range.start;
- m_end = mem->range.end;
- m_attr = mem->attribute;
-
- /*
- * The EFI memory map deals with regions in EFI_PAGE_SIZE
- * units. Ensure that the region described by 'mem' is aligned
- * correctly.
- */
- if (!IS_ALIGNED(m_start, EFI_PAGE_SIZE) ||
- !IS_ALIGNED(m_end + 1, EFI_PAGE_SIZE)) {
- WARN_ON(1);
- return;
- }
-
- for (old = old_memmap->map, new = buf;
- old < old_memmap->map_end;
- old += old_memmap->desc_size, new += old_memmap->desc_size) {
-
- /* copy original EFI memory descriptor */
- memcpy(new, old, old_memmap->desc_size);
- md = new;
- start = md->phys_addr;
- end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
-
- if (m_start <= start && end <= m_end)
- md->attribute |= m_attr;
-
- if (m_start <= start &&
- (start < m_end && m_end < end)) {
- /* first part */
- md->attribute |= m_attr;
- md->num_pages = (m_end - md->phys_addr + 1) >>
- EFI_PAGE_SHIFT;
- /* latter part */
- new += old_memmap->desc_size;
- memcpy(new, old, old_memmap->desc_size);
- md = new;
- md->phys_addr = m_end + 1;
- md->num_pages = (end - md->phys_addr + 1) >>
- EFI_PAGE_SHIFT;
- }
-
- if ((start < m_start && m_start < end) && m_end < end) {
- /* first part */
- md->num_pages = (m_start - md->phys_addr) >>
- EFI_PAGE_SHIFT;
- /* middle part */
- new += old_memmap->desc_size;
- memcpy(new, old, old_memmap->desc_size);
- md = new;
- md->attribute |= m_attr;
- md->phys_addr = m_start;
- md->num_pages = (m_end - m_start + 1) >>
- EFI_PAGE_SHIFT;
- /* last part */
- new += old_memmap->desc_size;
- memcpy(new, old, old_memmap->desc_size);
- md = new;
- md->phys_addr = m_end + 1;
- md->num_pages = (end - m_end) >>
- EFI_PAGE_SHIFT;
- }
-
- if ((start < m_start && m_start < end) &&
- (end <= m_end)) {
- /* first part */
- md->num_pages = (m_start - md->phys_addr) >>
- EFI_PAGE_SHIFT;
- /* latter part */
- new += old_memmap->desc_size;
- memcpy(new, old, old_memmap->desc_size);
- md = new;
- md->phys_addr = m_start;
- md->num_pages = (end - md->phys_addr + 1) >>
- EFI_PAGE_SHIFT;
- md->attribute |= m_attr;
- }
- }
-}
diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c
index f3e54f6616f0..7feee3d9c2bf 100644
--- a/drivers/firmware/efi/runtime-wrappers.c
+++ b/drivers/firmware/efi/runtime-wrappers.c
@@ -83,6 +83,7 @@ struct efi_runtime_work efi_rts_work;
else \
pr_err("Failed to queue work to efi_rts_wq.\n"); \
\
+ WARN_ON_ONCE(efi_rts_work.status == EFI_ABORTED); \
exit: \
efi_rts_work.efi_rts_id = EFI_NONE; \
efi_rts_work.status; \
diff --git a/drivers/firmware/efi/x86_fake_mem.c b/drivers/firmware/efi/x86_fake_mem.c
deleted file mode 100644
index 0bafcc1bb0f6..000000000000
--- a/drivers/firmware/efi/x86_fake_mem.c
+++ /dev/null
@@ -1,75 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 2019 Intel Corporation. All rights reserved. */
-#include <linux/efi.h>
-#include <asm/e820/api.h>
-#include "fake_mem.h"
-
-void __init efi_fake_memmap_early(void)
-{
- int i;
-
- /*
- * The late efi_fake_mem() call can handle all requests if
- * EFI_MEMORY_SP support is disabled.
- */
- if (!efi_soft_reserve_enabled())
- return;
-
- if (!efi_enabled(EFI_MEMMAP) || !nr_fake_mem)
- return;
-
- /*
- * Given that efi_fake_memmap() needs to perform memblock
- * allocations it needs to run after e820__memblock_setup().
- * However, if efi_fake_mem specifies EFI_MEMORY_SP for a given
- * address range that potentially needs to mark the memory as
- * reserved prior to e820__memblock_setup(). Update e820
- * directly if EFI_MEMORY_SP is specified for an
- * EFI_CONVENTIONAL_MEMORY descriptor.
- */
- for (i = 0; i < nr_fake_mem; i++) {
- struct efi_mem_range *mem = &efi_fake_mems[i];
- efi_memory_desc_t *md;
- u64 m_start, m_end;
-
- if ((mem->attribute & EFI_MEMORY_SP) == 0)
- continue;
-
- m_start = mem->range.start;
- m_end = mem->range.end;
- for_each_efi_memory_desc(md) {
- u64 start, end, size;
-
- if (md->type != EFI_CONVENTIONAL_MEMORY)
- continue;
-
- start = md->phys_addr;
- end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1;
-
- if (m_start <= end && m_end >= start)
- /* fake range overlaps descriptor */;
- else
- continue;
-
- /*
- * Trim the boundary of the e820 update to the
- * descriptor in case the fake range overlaps
- * !EFI_CONVENTIONAL_MEMORY
- */
- start = max(start, m_start);
- end = min(end, m_end);
- size = end - start + 1;
-
- if (end <= start)
- continue;
-
- /*
- * Ensure each efi_fake_mem instance results in
- * a unique e820 resource
- */
- e820__range_remove(start, size, E820_TYPE_RAM, 1);
- e820__range_add(start, size, E820_TYPE_SOFT_RESERVED);
- e820__update_table(e820_table);
- }
- }
-}
diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c
index af3d057e6421..2a4f07423365 100644
--- a/drivers/firmware/imx/scu-pd.c
+++ b/drivers/firmware/imx/scu-pd.c
@@ -108,6 +108,7 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = {
/* CONN SS */
{ "usb", IMX_SC_R_USB_0, 2, true, 0 },
{ "usb0phy", IMX_SC_R_USB_0_PHY, 1, false, 0 },
+ { "usb1phy", IMX_SC_R_USB_1_PHY, 1, false, 0},
{ "usb2", IMX_SC_R_USB_2, 1, false, 0 },
{ "usb2phy", IMX_SC_R_USB_2_PHY, 1, false, 0 },
{ "sdhc", IMX_SC_R_SDHC_0, 3, true, 0 },
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index 4b8978b254f9..ec07bf26e5eb 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -228,6 +228,26 @@ static void rpi_register_clk_driver(struct device *dev)
-1, NULL, 0);
}
+unsigned int rpi_firmware_clk_get_max_rate(struct rpi_firmware *fw, unsigned int id)
+{
+ struct rpi_firmware_clk_rate_request msg =
+ RPI_FIRMWARE_CLK_RATE_REQUEST(id);
+ int ret;
+
+ ret = rpi_firmware_property(fw, RPI_FIRMWARE_GET_MAX_CLOCK_RATE,
+ &msg, sizeof(msg));
+ if (ret)
+ /*
+ * If our firmware doesn't support that operation, or fails, we
+ * assume the maximum clock rate is absolute maximum we can
+ * store over our type.
+ */
+ return UINT_MAX;
+
+ return le32_to_cpu(msg.rate);
+}
+EXPORT_SYMBOL_GPL(rpi_firmware_clk_get_max_rate);
+
static void rpi_firmware_delete(struct kref *kref)
{
struct rpi_firmware *fw = container_of(kref, struct rpi_firmware,
@@ -268,12 +288,9 @@ static int rpi_firmware_probe(struct platform_device *pdev)
fw->cl.tx_block = true;
fw->chan = mbox_request_channel(&fw->cl, 0);
- if (IS_ERR(fw->chan)) {
- int ret = PTR_ERR(fw->chan);
- if (ret != -EPROBE_DEFER)
- dev_err(dev, "Failed to get mbox channel: %d\n", ret);
- return ret;
- }
+ if (IS_ERR(fw->chan))
+ return dev_err_probe(dev, PTR_ERR(fw->chan),
+ "Failed to get mbox channel\n");
init_completion(&fw->c);
kref_init(&fw->consumers);
@@ -311,6 +328,18 @@ static int rpi_firmware_remove(struct platform_device *pdev)
return 0;
}
+static const struct of_device_id rpi_firmware_of_match[] = {
+ { .compatible = "raspberrypi,bcm2835-firmware", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, rpi_firmware_of_match);
+
+struct device_node *rpi_firmware_find_node(void)
+{
+ return of_find_matching_node(NULL, rpi_firmware_of_match);
+}
+EXPORT_SYMBOL_GPL(rpi_firmware_find_node);
+
/**
* rpi_firmware_get - Get pointer to rpi_firmware structure.
* @firmware_node: Pointer to the firmware Device Tree node.
@@ -366,12 +395,6 @@ struct rpi_firmware *devm_rpi_firmware_get(struct device *dev,
}
EXPORT_SYMBOL_GPL(devm_rpi_firmware_get);
-static const struct of_device_id rpi_firmware_of_match[] = {
- { .compatible = "raspberrypi,bcm2835-firmware", },
- {},
-};
-MODULE_DEVICE_TABLE(of, rpi_firmware_of_match);
-
static struct platform_driver rpi_firmware_driver = {
.driver = {
.name = "raspberrypi-firmware",
diff --git a/drivers/firmware/tegra/Kconfig b/drivers/firmware/tegra/Kconfig
index 1c8ba1f47c7c..cde1ab8bd9d1 100644
--- a/drivers/firmware/tegra/Kconfig
+++ b/drivers/firmware/tegra/Kconfig
@@ -14,6 +14,7 @@ config TEGRA_IVC
config TEGRA_BPMP
bool "Tegra BPMP driver"
depends on ARCH_TEGRA && TEGRA_HSP_MBOX && TEGRA_IVC
+ depends on !CPU_BIG_ENDIAN
help
BPMP (Boot and Power Management Processor) is designed to off-loading
the PM functions which include clock/DVFS/thermal/power from the CPU.
diff --git a/drivers/firmware/tegra/bpmp-debugfs.c b/drivers/firmware/tegra/bpmp-debugfs.c
index 9d3874cdaaee..3ca2b5d9e66f 100644
--- a/drivers/firmware/tegra/bpmp-debugfs.c
+++ b/drivers/firmware/tegra/bpmp-debugfs.c
@@ -48,13 +48,9 @@ static int seqbuf_read(struct seqbuf *seqbuf, void *buf, size_t nbyte)
return seqbuf_status(seqbuf);
}
-static int seqbuf_read_u32(struct seqbuf *seqbuf, uint32_t *v)
+static int seqbuf_read_u32(struct seqbuf *seqbuf, u32 *v)
{
- int err;
-
- err = seqbuf_read(seqbuf, v, 4);
- *v = le32_to_cpu(*v);
- return err;
+ return seqbuf_read(seqbuf, v, 4);
}
static int seqbuf_read_str(struct seqbuf *seqbuf, const char **str)
@@ -109,10 +105,10 @@ out:
}
static int mrq_debug_open(struct tegra_bpmp *bpmp, const char *name,
- uint32_t *fd, uint32_t *len, bool write)
+ u32 *fd, u32 *len, bool write)
{
struct mrq_debug_request req = {
- .cmd = cpu_to_le32(write ? CMD_DEBUG_OPEN_WO : CMD_DEBUG_OPEN_RO),
+ .cmd = write ? CMD_DEBUG_OPEN_WO : CMD_DEBUG_OPEN_RO,
};
struct mrq_debug_response resp;
struct tegra_bpmp_message msg = {
@@ -147,10 +143,10 @@ static int mrq_debug_open(struct tegra_bpmp *bpmp, const char *name,
return 0;
}
-static int mrq_debug_close(struct tegra_bpmp *bpmp, uint32_t fd)
+static int mrq_debug_close(struct tegra_bpmp *bpmp, u32 fd)
{
struct mrq_debug_request req = {
- .cmd = cpu_to_le32(CMD_DEBUG_CLOSE),
+ .cmd = CMD_DEBUG_CLOSE,
.frd = {
.fd = fd,
},
@@ -179,10 +175,10 @@ static int mrq_debug_close(struct tegra_bpmp *bpmp, uint32_t fd)
}
static int mrq_debug_read(struct tegra_bpmp *bpmp, const char *name,
- char *data, size_t sz_data, uint32_t *nbytes)
+ char *data, size_t sz_data, u32 *nbytes)
{
struct mrq_debug_request req = {
- .cmd = cpu_to_le32(CMD_DEBUG_READ),
+ .cmd = CMD_DEBUG_READ,
};
struct mrq_debug_response resp;
struct tegra_bpmp_message msg = {
@@ -196,7 +192,7 @@ static int mrq_debug_read(struct tegra_bpmp *bpmp, const char *name,
.size = sizeof(resp),
},
};
- uint32_t fd = 0, len = 0;
+ u32 fd = 0, len = 0;
int remaining, err;
mutex_lock(&bpmp_debug_lock);
@@ -245,7 +241,7 @@ static int mrq_debug_write(struct tegra_bpmp *bpmp, const char *name,
uint8_t *data, size_t sz_data)
{
struct mrq_debug_request req = {
- .cmd = cpu_to_le32(CMD_DEBUG_WRITE)
+ .cmd = CMD_DEBUG_WRITE
};
struct mrq_debug_response resp;
struct tegra_bpmp_message msg = {
@@ -259,7 +255,7 @@ static int mrq_debug_write(struct tegra_bpmp *bpmp, const char *name,
.size = sizeof(resp),
},
};
- uint32_t fd = 0, len = 0;
+ u32 fd = 0, len = 0;
size_t remaining;
int err;
@@ -308,7 +304,7 @@ static int bpmp_debug_show(struct seq_file *m, void *p)
char fnamebuf[256];
const char *filename;
struct mrq_debug_request req = {
- .cmd = cpu_to_le32(CMD_DEBUG_READ),
+ .cmd = CMD_DEBUG_READ,
};
struct mrq_debug_response resp;
struct tegra_bpmp_message msg = {
@@ -322,7 +318,7 @@ static int bpmp_debug_show(struct seq_file *m, void *p)
.size = sizeof(resp),
},
};
- uint32_t fd = 0, len = 0;
+ u32 fd = 0, len = 0;
int remaining, err;
filename = get_filename(bpmp, file, fnamebuf, sizeof(fnamebuf));
@@ -406,8 +402,8 @@ static int bpmp_populate_debugfs_inband(struct tegra_bpmp *bpmp,
{
const size_t pathlen = SZ_256;
const size_t bufsize = SZ_16K;
- uint32_t dsize, attrs = 0;
struct dentry *dentry;
+ u32 dsize, attrs = 0;
struct seqbuf seqbuf;
char *buf, *pathbuf;
const char *name;
@@ -487,12 +483,12 @@ static int mrq_debugfs_read(struct tegra_bpmp *bpmp,
size_t *nbytes)
{
struct mrq_debugfs_request req = {
- .cmd = cpu_to_le32(CMD_DEBUGFS_READ),
+ .cmd = CMD_DEBUGFS_READ,
.fop = {
- .fnameaddr = cpu_to_le32((uint32_t)name),
- .fnamelen = cpu_to_le32((uint32_t)sz_name),
- .dataaddr = cpu_to_le32((uint32_t)data),
- .datalen = cpu_to_le32((uint32_t)sz_data),
+ .fnameaddr = (u32)name,
+ .fnamelen = (u32)sz_name,
+ .dataaddr = (u32)data,
+ .datalen = (u32)sz_data,
},
};
struct mrq_debugfs_response resp;
@@ -525,12 +521,12 @@ static int mrq_debugfs_write(struct tegra_bpmp *bpmp,
dma_addr_t data, size_t sz_data)
{
const struct mrq_debugfs_request req = {
- .cmd = cpu_to_le32(CMD_DEBUGFS_WRITE),
+ .cmd = CMD_DEBUGFS_WRITE,
.fop = {
- .fnameaddr = cpu_to_le32((uint32_t)name),
- .fnamelen = cpu_to_le32((uint32_t)sz_name),
- .dataaddr = cpu_to_le32((uint32_t)data),
- .datalen = cpu_to_le32((uint32_t)sz_data),
+ .fnameaddr = (u32)name,
+ .fnamelen = (u32)sz_name,
+ .dataaddr = (u32)data,
+ .datalen = (u32)sz_data,
},
};
struct tegra_bpmp_message msg = {
@@ -548,10 +544,10 @@ static int mrq_debugfs_dumpdir(struct tegra_bpmp *bpmp, dma_addr_t addr,
size_t size, size_t *nbytes)
{
const struct mrq_debugfs_request req = {
- .cmd = cpu_to_le32(CMD_DEBUGFS_DUMPDIR),
+ .cmd = CMD_DEBUGFS_DUMPDIR,
.dumpdir = {
- .dataaddr = cpu_to_le32((uint32_t)addr),
- .datalen = cpu_to_le32((uint32_t)size),
+ .dataaddr = (u32)addr,
+ .datalen = (u32)size,
},
};
struct mrq_debugfs_response resp;
@@ -688,10 +684,10 @@ static const struct file_operations debugfs_fops = {
};
static int bpmp_populate_dir(struct tegra_bpmp *bpmp, struct seqbuf *seqbuf,
- struct dentry *parent, uint32_t depth)
+ struct dentry *parent, u32 depth)
{
int err;
- uint32_t d, t;
+ u32 d, t;
const char *name;
struct dentry *dentry;
diff --git a/drivers/firmware/tegra/bpmp-tegra186.c b/drivers/firmware/tegra/bpmp-tegra186.c
index 63ab21d89c2c..2e26199041cd 100644
--- a/drivers/firmware/tegra/bpmp-tegra186.c
+++ b/drivers/firmware/tegra/bpmp-tegra186.c
@@ -18,8 +18,8 @@ struct tegra186_bpmp {
struct {
struct gen_pool *pool;
+ void __iomem *virt;
dma_addr_t phys;
- void *virt;
} tx, rx;
struct {
@@ -40,31 +40,27 @@ mbox_client_to_bpmp(struct mbox_client *client)
static bool tegra186_bpmp_is_message_ready(struct tegra_bpmp_channel *channel)
{
- void *frame;
+ int err;
- frame = tegra_ivc_read_get_next_frame(channel->ivc);
- if (IS_ERR(frame)) {
- channel->ib = NULL;
+ err = tegra_ivc_read_get_next_frame(channel->ivc, &channel->ib);
+ if (err) {
+ iosys_map_clear(&channel->ib);
return false;
}
- channel->ib = frame;
-
return true;
}
static bool tegra186_bpmp_is_channel_free(struct tegra_bpmp_channel *channel)
{
- void *frame;
+ int err;
- frame = tegra_ivc_write_get_next_frame(channel->ivc);
- if (IS_ERR(frame)) {
- channel->ob = NULL;
+ err = tegra_ivc_write_get_next_frame(channel->ivc, &channel->ob);
+ if (err) {
+ iosys_map_clear(&channel->ob);
return false;
}
- channel->ob = frame;
-
return true;
}
@@ -109,6 +105,7 @@ static int tegra186_bpmp_channel_init(struct tegra_bpmp_channel *channel,
{
struct tegra186_bpmp *priv = bpmp->priv;
size_t message_size, queue_size;
+ struct iosys_map rx, tx;
unsigned int offset;
int err;
@@ -121,10 +118,11 @@ static int tegra186_bpmp_channel_init(struct tegra_bpmp_channel *channel,
queue_size = tegra_ivc_total_queue_size(message_size);
offset = queue_size * index;
- err = tegra_ivc_init(channel->ivc, NULL,
- priv->rx.virt + offset, priv->rx.phys + offset,
- priv->tx.virt + offset, priv->tx.phys + offset,
- 1, message_size, tegra186_bpmp_ivc_notify,
+ iosys_map_set_vaddr_iomem(&rx, priv->rx.virt + offset);
+ iosys_map_set_vaddr_iomem(&tx, priv->tx.virt + 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,
bpmp);
if (err < 0) {
dev_err(bpmp->dev, "failed to setup IVC for channel %u: %d\n",
@@ -179,7 +177,7 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
return -EPROBE_DEFER;
}
- priv->tx.virt = gen_pool_dma_alloc(priv->tx.pool, 4096, &priv->tx.phys);
+ priv->tx.virt = (void __iomem *)gen_pool_dma_alloc(priv->tx.pool, 4096, &priv->tx.phys);
if (!priv->tx.virt) {
dev_err(bpmp->dev, "failed to allocate from TX pool\n");
return -ENOMEM;
@@ -192,7 +190,7 @@ static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
goto free_tx;
}
- priv->rx.virt = gen_pool_dma_alloc(priv->rx.pool, 4096, &priv->rx.phys);
+ priv->rx.virt = (void __iomem *)gen_pool_dma_alloc(priv->rx.pool, 4096, &priv->rx.phys);
if (!priv->rx.virt) {
dev_err(bpmp->dev, "failed to allocate from RX pool\n");
err = -ENOMEM;
diff --git a/drivers/firmware/tegra/bpmp-tegra210.c b/drivers/firmware/tegra/bpmp-tegra210.c
index c9c830f658c3..6295f5640c15 100644
--- a/drivers/firmware/tegra/bpmp-tegra210.c
+++ b/drivers/firmware/tegra/bpmp-tegra210.c
@@ -137,8 +137,8 @@ static int tegra210_bpmp_channel_init(struct tegra_bpmp_channel *channel,
unsigned int index)
{
struct tegra210_bpmp *priv = bpmp->priv;
+ void __iomem *p;
u32 address;
- void *p;
/* Retrieve channel base address from BPMP */
writel(index << TRIGGER_ID_SHIFT | TRIGGER_CMD_GET,
@@ -149,8 +149,9 @@ static int tegra210_bpmp_channel_init(struct tegra_bpmp_channel *channel,
if (!p)
return -ENOMEM;
- channel->ib = p;
- channel->ob = p;
+ iosys_map_set_vaddr_iomem(&channel->ib, p);
+ iosys_map_set_vaddr_iomem(&channel->ob, p);
+
channel->index = index;
init_completion(&channel->completion);
channel->bpmp = bpmp;
@@ -199,10 +200,8 @@ static int tegra210_bpmp_init(struct tegra_bpmp *bpmp)
}
err = platform_get_irq_byname(pdev, "tx");
- if (err < 0) {
- dev_err(&pdev->dev, "failed to get TX IRQ: %d\n", err);
+ if (err < 0)
return err;
- }
priv->tx_irq_data = irq_get_irq_data(err);
if (!priv->tx_irq_data) {
@@ -211,10 +210,8 @@ static int tegra210_bpmp_init(struct tegra_bpmp *bpmp)
}
err = platform_get_irq_byname(pdev, "rx");
- if (err < 0) {
- dev_err(&pdev->dev, "failed to get rx IRQ: %d\n", err);
+ if (err < 0)
return err;
- }
err = devm_request_irq(&pdev->dev, err, rx_irq,
IRQF_NO_SUSPEND, dev_name(&pdev->dev), bpmp);
diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c
index 037db21de510..042c2043929d 100644
--- a/drivers/firmware/tegra/bpmp.c
+++ b/drivers/firmware/tegra/bpmp.c
@@ -201,13 +201,13 @@ static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel,
int err;
if (data && size > 0)
- memcpy_fromio(data, channel->ib->data, size);
+ tegra_bpmp_mb_read(data, &channel->ib, size);
err = tegra_bpmp_ack_response(channel);
if (err < 0)
return err;
- *ret = channel->ib->code;
+ *ret = tegra_bpmp_mb_read_field(&channel->ib, code);
return 0;
}
@@ -241,11 +241,11 @@ static ssize_t __tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel,
unsigned int mrq, unsigned long flags,
const void *data, size_t size)
{
- channel->ob->code = mrq;
- channel->ob->flags = flags;
+ tegra_bpmp_mb_write_field(&channel->ob, code, mrq);
+ tegra_bpmp_mb_write_field(&channel->ob, flags, flags);
if (data && size > 0)
- memcpy_toio(channel->ob->data, data, size);
+ tegra_bpmp_mb_write(&channel->ob, data, size);
return tegra_bpmp_post_request(channel);
}
@@ -400,7 +400,7 @@ static struct tegra_bpmp_mrq *tegra_bpmp_find_mrq(struct tegra_bpmp *bpmp,
void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, int code,
const void *data, size_t size)
{
- unsigned long flags = channel->ib->flags;
+ unsigned long flags = tegra_bpmp_mb_read_field(&channel->ib, flags);
struct tegra_bpmp *bpmp = channel->bpmp;
int err;
@@ -417,10 +417,10 @@ void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, int code,
if (WARN_ON(!tegra_bpmp_is_response_channel_free(channel)))
return;
- channel->ob->code = code;
+ tegra_bpmp_mb_write_field(&channel->ob, code, code);
if (data && size > 0)
- memcpy_toio(channel->ob->data, data, size);
+ tegra_bpmp_mb_write(&channel->ob, data, size);
err = tegra_bpmp_post_response(channel);
if (WARN_ON(err < 0))
@@ -502,7 +502,7 @@ EXPORT_SYMBOL_GPL(tegra_bpmp_free_mrq);
bool tegra_bpmp_mrq_is_supported(struct tegra_bpmp *bpmp, unsigned int mrq)
{
- struct mrq_query_abi_request req = { .mrq = cpu_to_le32(mrq) };
+ struct mrq_query_abi_request req = { .mrq = mrq };
struct mrq_query_abi_response resp;
struct tegra_bpmp_message msg = {
.mrq = MRQ_QUERY_ABI,
@@ -529,13 +529,13 @@ static void tegra_bpmp_mrq_handle_ping(unsigned int mrq,
struct tegra_bpmp_channel *channel,
void *data)
{
- struct mrq_ping_request *request;
+ struct mrq_ping_request request;
struct mrq_ping_response response;
- request = (struct mrq_ping_request *)channel->ib->data;
+ tegra_bpmp_mb_read(&request, &channel->ib, sizeof(request));
memset(&response, 0, sizeof(response));
- response.reply = request->challenge << 1;
+ response.reply = request.challenge << 1;
tegra_bpmp_mrq_return(channel, 0, &response, sizeof(response));
}
@@ -648,7 +648,7 @@ static int tegra_bpmp_get_firmware_tag(struct tegra_bpmp *bpmp, char *tag,
static void tegra_bpmp_channel_signal(struct tegra_bpmp_channel *channel)
{
- unsigned long flags = channel->ob->flags;
+ unsigned long flags = tegra_bpmp_mb_read_field(&channel->ob, flags);
if ((flags & MSG_RING) == 0)
return;
@@ -666,8 +666,11 @@ void tegra_bpmp_handle_rx(struct tegra_bpmp *bpmp)
count = bpmp->soc->channels.thread.count;
busy = bpmp->threaded.busy;
- if (tegra_bpmp_is_request_ready(channel))
- tegra_bpmp_handle_mrq(bpmp, channel->ib->code, channel);
+ if (tegra_bpmp_is_request_ready(channel)) {
+ unsigned int mrq = tegra_bpmp_mb_read_field(&channel->ib, code);
+
+ tegra_bpmp_handle_mrq(bpmp, mrq, channel);
+ }
spin_lock(&bpmp->lock);
diff --git a/drivers/firmware/tegra/ivc.c b/drivers/firmware/tegra/ivc.c
index e2398cd7ca98..8c9aff9804c0 100644
--- a/drivers/firmware/tegra/ivc.c
+++ b/drivers/firmware/tegra/ivc.c
@@ -68,6 +68,12 @@ struct tegra_ivc_header {
} rx;
};
+#define tegra_ivc_header_read_field(hdr, field) \
+ iosys_map_rd_field(hdr, 0, struct tegra_ivc_header, field)
+
+#define tegra_ivc_header_write_field(hdr, field, value) \
+ iosys_map_wr_field(hdr, 0, struct tegra_ivc_header, field, value)
+
static inline void tegra_ivc_invalidate(struct tegra_ivc *ivc, dma_addr_t phys)
{
if (!ivc->peer)
@@ -86,16 +92,15 @@ static inline void tegra_ivc_flush(struct tegra_ivc *ivc, dma_addr_t phys)
DMA_TO_DEVICE);
}
-static inline bool tegra_ivc_empty(struct tegra_ivc *ivc,
- struct tegra_ivc_header *header)
+static inline bool tegra_ivc_empty(struct tegra_ivc *ivc, struct iosys_map *map)
{
/*
* This function performs multiple checks on the same values with
* security implications, so create snapshots with READ_ONCE() to
* ensure that these checks use the same values.
*/
- u32 tx = READ_ONCE(header->tx.count);
- u32 rx = READ_ONCE(header->rx.count);
+ u32 tx = tegra_ivc_header_read_field(map, tx.count);
+ u32 rx = tegra_ivc_header_read_field(map, rx.count);
/*
* Perform an over-full check to prevent denial of service attacks
@@ -113,11 +118,10 @@ static inline bool tegra_ivc_empty(struct tegra_ivc *ivc,
return tx == rx;
}
-static inline bool tegra_ivc_full(struct tegra_ivc *ivc,
- struct tegra_ivc_header *header)
+static inline bool tegra_ivc_full(struct tegra_ivc *ivc, struct iosys_map *map)
{
- u32 tx = READ_ONCE(header->tx.count);
- u32 rx = READ_ONCE(header->rx.count);
+ u32 tx = tegra_ivc_header_read_field(map, tx.count);
+ u32 rx = tegra_ivc_header_read_field(map, rx.count);
/*
* Invalid cases where the counters indicate that the queue is over
@@ -126,11 +130,10 @@ static inline bool tegra_ivc_full(struct tegra_ivc *ivc,
return tx - rx >= ivc->num_frames;
}
-static inline u32 tegra_ivc_available(struct tegra_ivc *ivc,
- struct tegra_ivc_header *header)
+static inline u32 tegra_ivc_available(struct tegra_ivc *ivc, struct iosys_map *map)
{
- u32 tx = READ_ONCE(header->tx.count);
- u32 rx = READ_ONCE(header->rx.count);
+ u32 tx = tegra_ivc_header_read_field(map, tx.count);
+ u32 rx = tegra_ivc_header_read_field(map, rx.count);
/*
* This function isn't expected to be used in scenarios where an
@@ -143,8 +146,9 @@ static inline u32 tegra_ivc_available(struct tegra_ivc *ivc,
static inline void tegra_ivc_advance_tx(struct tegra_ivc *ivc)
{
- WRITE_ONCE(ivc->tx.channel->tx.count,
- READ_ONCE(ivc->tx.channel->tx.count) + 1);
+ unsigned int count = tegra_ivc_header_read_field(&ivc->tx.map, tx.count);
+
+ tegra_ivc_header_write_field(&ivc->tx.map, tx.count, count + 1);
if (ivc->tx.position == ivc->num_frames - 1)
ivc->tx.position = 0;
@@ -154,8 +158,9 @@ static inline void tegra_ivc_advance_tx(struct tegra_ivc *ivc)
static inline void tegra_ivc_advance_rx(struct tegra_ivc *ivc)
{
- WRITE_ONCE(ivc->rx.channel->rx.count,
- READ_ONCE(ivc->rx.channel->rx.count) + 1);
+ unsigned int count = tegra_ivc_header_read_field(&ivc->rx.map, rx.count);
+
+ tegra_ivc_header_write_field(&ivc->rx.map, rx.count, count + 1);
if (ivc->rx.position == ivc->num_frames - 1)
ivc->rx.position = 0;
@@ -166,6 +171,7 @@ static inline void tegra_ivc_advance_rx(struct tegra_ivc *ivc)
static inline int tegra_ivc_check_read(struct tegra_ivc *ivc)
{
unsigned int offset = offsetof(struct tegra_ivc_header, tx.count);
+ unsigned int state;
/*
* tx.channel->state is set locally, so it is not synchronized with
@@ -175,7 +181,8 @@ static inline int tegra_ivc_check_read(struct tegra_ivc *ivc)
* asynchronous transition of rx.channel->state to
* TEGRA_IVC_STATE_ACK is not allowed.
*/
- if (ivc->tx.channel->tx.state != TEGRA_IVC_STATE_ESTABLISHED)
+ state = tegra_ivc_header_read_field(&ivc->tx.map, tx.state);
+ if (state != TEGRA_IVC_STATE_ESTABLISHED)
return -ECONNRESET;
/*
@@ -185,12 +192,12 @@ static inline int tegra_ivc_check_read(struct tegra_ivc *ivc)
* Synchronization is only necessary when these pointers indicate
* empty or full.
*/
- if (!tegra_ivc_empty(ivc, ivc->rx.channel))
+ if (!tegra_ivc_empty(ivc, &ivc->rx.map))
return 0;
tegra_ivc_invalidate(ivc, ivc->rx.phys + offset);
- if (tegra_ivc_empty(ivc, ivc->rx.channel))
+ if (tegra_ivc_empty(ivc, &ivc->rx.map))
return -ENOSPC;
return 0;
@@ -199,29 +206,34 @@ static inline int tegra_ivc_check_read(struct tegra_ivc *ivc)
static inline int tegra_ivc_check_write(struct tegra_ivc *ivc)
{
unsigned int offset = offsetof(struct tegra_ivc_header, rx.count);
+ unsigned int state;
- if (ivc->tx.channel->tx.state != TEGRA_IVC_STATE_ESTABLISHED)
+ state = tegra_ivc_header_read_field(&ivc->tx.map, tx.state);
+ if (state != TEGRA_IVC_STATE_ESTABLISHED)
return -ECONNRESET;
- if (!tegra_ivc_full(ivc, ivc->tx.channel))
+ if (!tegra_ivc_full(ivc, &ivc->tx.map))
return 0;
tegra_ivc_invalidate(ivc, ivc->tx.phys + offset);
- if (tegra_ivc_full(ivc, ivc->tx.channel))
+ if (tegra_ivc_full(ivc, &ivc->tx.map))
return -ENOSPC;
return 0;
}
-static void *tegra_ivc_frame_virt(struct tegra_ivc *ivc,
- struct tegra_ivc_header *header,
- unsigned int frame)
+static int tegra_ivc_frame_virt(struct tegra_ivc *ivc, const struct iosys_map *header,
+ unsigned int frame, struct iosys_map *map)
{
+ size_t offset = sizeof(struct tegra_ivc_header) + ivc->frame_size * frame;
+
if (WARN_ON(frame >= ivc->num_frames))
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
- return (void *)(header + 1) + ivc->frame_size * frame;
+ *map = IOSYS_MAP_INIT_OFFSET(header, offset);
+
+ return 0;
}
static inline dma_addr_t tegra_ivc_frame_phys(struct tegra_ivc *ivc,
@@ -264,16 +276,16 @@ static inline void tegra_ivc_flush_frame(struct tegra_ivc *ivc,
}
/* directly peek at the next frame rx'ed */
-void *tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc)
+int tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc, struct iosys_map *map)
{
int err;
if (WARN_ON(ivc == NULL))
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
err = tegra_ivc_check_read(ivc);
if (err < 0)
- return ERR_PTR(err);
+ return err;
/*
* Order observation of ivc->rx.position potentially indicating new
@@ -284,7 +296,7 @@ void *tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc)
tegra_ivc_invalidate_frame(ivc, ivc->rx.phys, ivc->rx.position, 0,
ivc->frame_size);
- return tegra_ivc_frame_virt(ivc, ivc->rx.channel, ivc->rx.position);
+ return tegra_ivc_frame_virt(ivc, &ivc->rx.map, ivc->rx.position, map);
}
EXPORT_SYMBOL(tegra_ivc_read_get_next_frame);
@@ -320,7 +332,7 @@ int tegra_ivc_read_advance(struct tegra_ivc *ivc)
*/
tegra_ivc_invalidate(ivc, ivc->rx.phys + tx);
- if (tegra_ivc_available(ivc, ivc->rx.channel) == ivc->num_frames - 1)
+ if (tegra_ivc_available(ivc, &ivc->rx.map) == ivc->num_frames - 1)
ivc->notify(ivc, ivc->notify_data);
return 0;
@@ -328,15 +340,15 @@ int tegra_ivc_read_advance(struct tegra_ivc *ivc)
EXPORT_SYMBOL(tegra_ivc_read_advance);
/* directly poke at the next frame to be tx'ed */
-void *tegra_ivc_write_get_next_frame(struct tegra_ivc *ivc)
+int tegra_ivc_write_get_next_frame(struct tegra_ivc *ivc, struct iosys_map *map)
{
int err;
err = tegra_ivc_check_write(ivc);
if (err < 0)
- return ERR_PTR(err);
+ return err;
- return tegra_ivc_frame_virt(ivc, ivc->tx.channel, ivc->tx.position);
+ return tegra_ivc_frame_virt(ivc, &ivc->tx.map, ivc->tx.position, map);
}
EXPORT_SYMBOL(tegra_ivc_write_get_next_frame);
@@ -376,7 +388,7 @@ int tegra_ivc_write_advance(struct tegra_ivc *ivc)
*/
tegra_ivc_invalidate(ivc, ivc->tx.phys + rx);
- if (tegra_ivc_available(ivc, ivc->tx.channel) == 1)
+ if (tegra_ivc_available(ivc, &ivc->tx.map) == 1)
ivc->notify(ivc, ivc->notify_data);
return 0;
@@ -387,7 +399,7 @@ void tegra_ivc_reset(struct tegra_ivc *ivc)
{
unsigned int offset = offsetof(struct tegra_ivc_header, tx.count);
- ivc->tx.channel->tx.state = TEGRA_IVC_STATE_SYNC;
+ tegra_ivc_header_write_field(&ivc->tx.map, tx.state, TEGRA_IVC_STATE_SYNC);
tegra_ivc_flush(ivc, ivc->tx.phys + offset);
ivc->notify(ivc, ivc->notify_data);
}
@@ -416,13 +428,14 @@ EXPORT_SYMBOL(tegra_ivc_reset);
int tegra_ivc_notified(struct tegra_ivc *ivc)
{
unsigned int offset = offsetof(struct tegra_ivc_header, tx.count);
- enum tegra_ivc_state state;
+ enum tegra_ivc_state rx_state, tx_state;
/* Copy the receiver's state out of shared memory. */
tegra_ivc_invalidate(ivc, ivc->rx.phys + offset);
- state = READ_ONCE(ivc->rx.channel->tx.state);
+ rx_state = tegra_ivc_header_read_field(&ivc->rx.map, tx.state);
+ tx_state = tegra_ivc_header_read_field(&ivc->tx.map, tx.state);
- if (state == TEGRA_IVC_STATE_SYNC) {
+ if (rx_state == TEGRA_IVC_STATE_SYNC) {
offset = offsetof(struct tegra_ivc_header, tx.count);
/*
@@ -436,8 +449,8 @@ int tegra_ivc_notified(struct tegra_ivc *ivc)
* state and won't make progress until we change our state,
* so the counters are not in use at this time.
*/
- ivc->tx.channel->tx.count = 0;
- ivc->rx.channel->rx.count = 0;
+ tegra_ivc_header_write_field(&ivc->tx.map, tx.count, 0);
+ tegra_ivc_header_write_field(&ivc->rx.map, rx.count, 0);
ivc->tx.position = 0;
ivc->rx.position = 0;
@@ -452,7 +465,7 @@ int tegra_ivc_notified(struct tegra_ivc *ivc)
* Move to ACK state. We have just cleared our counters, so it
* is now safe for the remote end to start using these values.
*/
- ivc->tx.channel->tx.state = TEGRA_IVC_STATE_ACK;
+ tegra_ivc_header_write_field(&ivc->tx.map, tx.state, TEGRA_IVC_STATE_ACK);
tegra_ivc_flush(ivc, ivc->tx.phys + offset);
/*
@@ -460,8 +473,8 @@ int tegra_ivc_notified(struct tegra_ivc *ivc)
*/
ivc->notify(ivc, ivc->notify_data);
- } else if (ivc->tx.channel->tx.state == TEGRA_IVC_STATE_SYNC &&
- state == TEGRA_IVC_STATE_ACK) {
+ } else if (tx_state == TEGRA_IVC_STATE_SYNC &&
+ rx_state == TEGRA_IVC_STATE_ACK) {
offset = offsetof(struct tegra_ivc_header, tx.count);
/*
@@ -475,8 +488,8 @@ int tegra_ivc_notified(struct tegra_ivc *ivc)
* state and won't make progress until we change our state,
* so the counters are not in use at this time.
*/
- ivc->tx.channel->tx.count = 0;
- ivc->rx.channel->rx.count = 0;
+ tegra_ivc_header_write_field(&ivc->tx.map, tx.count, 0);
+ tegra_ivc_header_write_field(&ivc->rx.map, rx.count, 0);
ivc->tx.position = 0;
ivc->rx.position = 0;
@@ -492,7 +505,7 @@ int tegra_ivc_notified(struct tegra_ivc *ivc)
* already cleared its counters, so it is safe to start
* writing/reading on this channel.
*/
- ivc->tx.channel->tx.state = TEGRA_IVC_STATE_ESTABLISHED;
+ tegra_ivc_header_write_field(&ivc->tx.map, tx.state, TEGRA_IVC_STATE_ESTABLISHED);
tegra_ivc_flush(ivc, ivc->tx.phys + offset);
/*
@@ -500,7 +513,7 @@ int tegra_ivc_notified(struct tegra_ivc *ivc)
*/
ivc->notify(ivc, ivc->notify_data);
- } else if (ivc->tx.channel->tx.state == TEGRA_IVC_STATE_ACK) {
+ } else if (tx_state == TEGRA_IVC_STATE_ACK) {
offset = offsetof(struct tegra_ivc_header, tx.count);
/*
@@ -516,7 +529,7 @@ int tegra_ivc_notified(struct tegra_ivc *ivc)
* cleared its counters, so it is safe to start writing/reading
* on this channel.
*/
- ivc->tx.channel->tx.state = TEGRA_IVC_STATE_ESTABLISHED;
+ tegra_ivc_header_write_field(&ivc->tx.map, tx.state, TEGRA_IVC_STATE_ESTABLISHED);
tegra_ivc_flush(ivc, ivc->tx.phys + offset);
/*
@@ -533,7 +546,7 @@ int tegra_ivc_notified(struct tegra_ivc *ivc)
*/
}
- if (ivc->tx.channel->tx.state != TEGRA_IVC_STATE_ESTABLISHED)
+ if (tx_state != TEGRA_IVC_STATE_ESTABLISHED)
return -EAGAIN;
return 0;
@@ -609,8 +622,29 @@ static int tegra_ivc_check_params(unsigned long rx, unsigned long tx,
return 0;
}
-int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, void *rx,
- dma_addr_t rx_phys, void *tx, dma_addr_t tx_phys,
+static inline void iosys_map_copy(struct iosys_map *dst, const struct iosys_map *src)
+{
+ *dst = *src;
+}
+
+static inline unsigned long iosys_map_get_address(const struct iosys_map *map)
+{
+ if (map->is_iomem)
+ return (unsigned long)map->vaddr_iomem;
+
+ return (unsigned long)map->vaddr;
+}
+
+static inline void *iosys_map_get_vaddr(const struct iosys_map *map)
+{
+ if (WARN_ON(map->is_iomem))
+ return NULL;
+
+ return map->vaddr;
+}
+
+int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, const struct iosys_map *rx,
+ dma_addr_t rx_phys, const struct iosys_map *tx, dma_addr_t tx_phys,
unsigned int num_frames, size_t frame_size,
void (*notify)(struct tegra_ivc *ivc, void *data),
void *data)
@@ -628,7 +662,7 @@ int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, void *rx,
if (frame_size > INT_MAX)
return -E2BIG;
- err = tegra_ivc_check_params((unsigned long)rx, (unsigned long)tx,
+ err = tegra_ivc_check_params(iosys_map_get_address(rx), iosys_map_get_address(tx),
num_frames, frame_size);
if (err < 0)
return err;
@@ -636,12 +670,12 @@ int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, void *rx,
queue_size = tegra_ivc_total_queue_size(num_frames * frame_size);
if (peer) {
- ivc->rx.phys = dma_map_single(peer, rx, queue_size,
+ ivc->rx.phys = dma_map_single(peer, iosys_map_get_vaddr(rx), queue_size,
DMA_BIDIRECTIONAL);
if (dma_mapping_error(peer, ivc->rx.phys))
return -ENOMEM;
- ivc->tx.phys = dma_map_single(peer, tx, queue_size,
+ ivc->tx.phys = dma_map_single(peer, iosys_map_get_vaddr(tx), queue_size,
DMA_BIDIRECTIONAL);
if (dma_mapping_error(peer, ivc->tx.phys)) {
dma_unmap_single(peer, ivc->rx.phys, queue_size,
@@ -653,8 +687,8 @@ int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, void *rx,
ivc->tx.phys = tx_phys;
}
- ivc->rx.channel = rx;
- ivc->tx.channel = tx;
+ iosys_map_copy(&ivc->rx.map, rx);
+ iosys_map_copy(&ivc->tx.map, tx);
ivc->peer = peer;
ivc->notify = notify;
ivc->notify_data = data;
diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
index ebc32bbd9b83..039d92a595ec 100644
--- a/drivers/firmware/ti_sci.c
+++ b/drivers/firmware/ti_sci.c
@@ -429,15 +429,14 @@ static inline int ti_sci_do_xfer(struct ti_sci_info *info,
* during noirq phase, so we must manually poll the completion.
*/
ret = read_poll_timeout_atomic(try_wait_for_completion, done_state,
- true, 1,
+ done_state, 1,
info->desc->max_rx_timeout_ms * 1000,
false, &xfer->done);
}
- if (ret == -ETIMEDOUT || !done_state) {
+ if (ret == -ETIMEDOUT)
dev_err(dev, "Mbox timedout in resp(caller: %pS)\n",
(void *)_RET_IP_);
- }
/*
* NOTE: we might prefer not to need the mailbox ticker to manage the
@@ -3096,7 +3095,7 @@ u16 ti_sci_get_free_resource(struct ti_sci_resource *res)
free_bit = find_first_zero_bit(desc->res_map, res_count);
if (free_bit != res_count) {
- set_bit(free_bit, desc->res_map);
+ __set_bit(free_bit, desc->res_map);
raw_spin_unlock_irqrestore(&res->lock, flags);
if (desc->num && free_bit < desc->num)
@@ -3127,10 +3126,10 @@ void ti_sci_release_resource(struct ti_sci_resource *res, u16 id)
if (desc->num && desc->start <= id &&
(desc->start + desc->num) > id)
- clear_bit(id - desc->start, desc->res_map);
+ __clear_bit(id - desc->start, desc->res_map);
else if (desc->num_sec && desc->start_sec <= id &&
(desc->start_sec + desc->num_sec) > id)
- clear_bit(id - desc->start_sec, desc->res_map);
+ __clear_bit(id - desc->start_sec, desc->res_map);
}
raw_spin_unlock_irqrestore(&res->lock, flags);
}
@@ -3201,9 +3200,8 @@ devm_ti_sci_get_resource_sets(const struct ti_sci_handle *handle,
valid_set = true;
res_count = res->desc[i].num + res->desc[i].num_sec;
- res->desc[i].res_map =
- devm_kzalloc(dev, BITS_TO_LONGS(res_count) *
- sizeof(*res->desc[i].res_map), GFP_KERNEL);
+ res->desc[i].res_map = devm_bitmap_zalloc(dev, res_count,
+ GFP_KERNEL);
if (!res->desc[i].res_map)
return ERR_PTR(-ENOMEM);
}
@@ -3400,13 +3398,11 @@ static int ti_sci_probe(struct platform_device *pdev)
if (!minfo->xfer_block)
return -ENOMEM;
- minfo->xfer_alloc_table = devm_kcalloc(dev,
- BITS_TO_LONGS(desc->max_msgs),
- sizeof(unsigned long),
- GFP_KERNEL);
+ minfo->xfer_alloc_table = devm_bitmap_zalloc(dev,
+ desc->max_msgs,
+ GFP_KERNEL);
if (!minfo->xfer_alloc_table)
return -ENOMEM;
- bitmap_zero(minfo->xfer_alloc_table, desc->max_msgs);
/* Pre-initialize the buffer pointer to pre-allocated buffers */
for (i = 0, xfer = minfo->xfer_block; i < desc->max_msgs; i++, xfer++) {
diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
index ff5cabe70a2b..6bc6b6c84241 100644
--- a/drivers/firmware/xilinx/zynqmp.c
+++ b/drivers/firmware/xilinx/zynqmp.c
@@ -843,6 +843,13 @@ int zynqmp_pm_read_pggs(u32 index, u32 *value)
}
EXPORT_SYMBOL_GPL(zynqmp_pm_read_pggs);
+int zynqmp_pm_set_tapdelay_bypass(u32 index, u32 value)
+{
+ return zynqmp_pm_invoke_fn(PM_IOCTL, 0, IOCTL_SET_TAPDELAY_BYPASS,
+ index, value, NULL);
+}
+EXPORT_SYMBOL_GPL(zynqmp_pm_set_tapdelay_bypass);
+
/**
* zynqmp_pm_set_boot_health_status() - PM API for setting healthy boot status
* @value: Status value to be written
diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c
index 5f93a53846aa..9912b7a6a4b9 100644
--- a/drivers/fsi/fsi-sbefifo.c
+++ b/drivers/fsi/fsi-sbefifo.c
@@ -659,7 +659,7 @@ static void sbefifo_collect_async_ffdc(struct sbefifo *sbefifo)
}
ffdc_iov.iov_base = ffdc;
ffdc_iov.iov_len = SBEFIFO_MAX_FFDC_SIZE;
- iov_iter_kvec(&ffdc_iter, WRITE, &ffdc_iov, 1, SBEFIFO_MAX_FFDC_SIZE);
+ iov_iter_kvec(&ffdc_iter, ITER_DEST, &ffdc_iov, 1, SBEFIFO_MAX_FFDC_SIZE);
cmd[0] = cpu_to_be32(2);
cmd[1] = cpu_to_be32(SBEFIFO_CMD_GET_SBE_FFDC);
rc = sbefifo_do_command(sbefifo, cmd, 2, &ffdc_iter);
@@ -756,7 +756,7 @@ int sbefifo_submit(struct device *dev, const __be32 *command, size_t cmd_len,
rbytes = (*resp_len) * sizeof(__be32);
resp_iov.iov_base = response;
resp_iov.iov_len = rbytes;
- iov_iter_kvec(&resp_iter, WRITE, &resp_iov, 1, rbytes);
+ iov_iter_kvec(&resp_iter, ITER_DEST, &resp_iov, 1, rbytes);
/* Perform the command */
rc = mutex_lock_interruptible(&sbefifo->lock);
@@ -839,7 +839,7 @@ static ssize_t sbefifo_user_read(struct file *file, char __user *buf,
/* Prepare iov iterator */
resp_iov.iov_base = buf;
resp_iov.iov_len = len;
- iov_iter_init(&resp_iter, WRITE, &resp_iov, 1, len);
+ iov_iter_init(&resp_iter, ITER_DEST, &resp_iov, 1, len);
/* Perform the command */
rc = mutex_lock_interruptible(&sbefifo->lock);
diff --git a/drivers/gpio/gpio-arizona.c b/drivers/gpio/gpio-arizona.c
index 02f9ae19cd44..c15fda99120a 100644
--- a/drivers/gpio/gpio-arizona.c
+++ b/drivers/gpio/gpio-arizona.c
@@ -7,13 +7,12 @@
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
*/
+#include <linux/gpio/driver.h>
#include <linux/kernel.h>
-#include <linux/slab.h>
#include <linux/module.h>
-#include <linux/gpio/driver.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
-#include <linux/seq_file.h>
+#include <linux/slab.h>
#include <linux/mfd/arizona/core.h>
#include <linux/mfd/arizona/pdata.h>
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
index 318a7d95a1a8..a94da80d3a95 100644
--- a/drivers/gpio/gpio-aspeed.c
+++ b/drivers/gpio/gpio-aspeed.c
@@ -5,10 +5,9 @@
* Joel Stanley <joel@jms.id.au>
*/
-#include <asm/div64.h>
#include <linux/clk.h>
-#include <linux/gpio/driver.h>
#include <linux/gpio/aspeed.h>
+#include <linux/gpio/driver.h>
#include <linux/hashtable.h>
#include <linux/init.h>
#include <linux/io.h>
@@ -19,6 +18,8 @@
#include <linux/spinlock.h>
#include <linux/string.h>
+#include <asm/div64.h>
+
/*
* These two headers aren't meant to be used by GPIO drivers. We need
* them in order to access gpio_chip_hwgpio() which we need to implement
diff --git a/drivers/gpio/gpio-da9052.c b/drivers/gpio/gpio-da9052.c
index 559188d80c2b..6f3905f1b8f5 100644
--- a/drivers/gpio/gpio-da9052.c
+++ b/drivers/gpio/gpio-da9052.c
@@ -6,17 +6,16 @@
*
* Author: David Dajun Chen <dchen@diasemi.com>
*/
-#include <linux/module.h>
#include <linux/fs.h>
-#include <linux/uaccess.h>
-#include <linux/platform_device.h>
#include <linux/gpio/driver.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/syscalls.h>
-#include <linux/seq_file.h>
+#include <linux/uaccess.h>
#include <linux/mfd/da9052/da9052.h>
-#include <linux/mfd/da9052/reg.h>
#include <linux/mfd/da9052/pdata.h>
+#include <linux/mfd/da9052/reg.h>
#define DA9052_INPUT 1
#define DA9052_OUTPUT_OPENDRAIN 2
diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c
index 523dfd17dd92..e6a7049bef64 100644
--- a/drivers/gpio/gpio-mockup.c
+++ b/drivers/gpio/gpio-mockup.c
@@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/property.h>
+#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/string_helpers.h>
#include <linux/uaccess.h>
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index c871602fc5ba..d5626c572d24 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -24,6 +24,12 @@
#include <linux/of_device.h>
#include <linux/bug.h>
+#define IMX_SCU_WAKEUP_OFF 0
+#define IMX_SCU_WAKEUP_LOW_LVL 4
+#define IMX_SCU_WAKEUP_FALL_EDGE 5
+#define IMX_SCU_WAKEUP_RISE_EDGE 6
+#define IMX_SCU_WAKEUP_HIGH_LVL 7
+
/* device type dependent stuff */
struct mxc_gpio_hwdata {
unsigned dr_reg;
@@ -61,6 +67,9 @@ struct mxc_gpio_port {
u32 both_edges;
struct mxc_gpio_reg_saved gpio_saved_reg;
bool power_off;
+ u32 wakeup_pads;
+ bool is_pad_wakeup;
+ u32 pad_type[32];
const struct mxc_gpio_hwdata *hwdata;
};
@@ -130,6 +139,9 @@ static const struct of_device_id mxc_gpio_dt_ids[] = {
{ .compatible = "fsl,imx31-gpio", .data = &imx31_gpio_hwdata },
{ .compatible = "fsl,imx35-gpio", .data = &imx35_gpio_hwdata },
{ .compatible = "fsl,imx7d-gpio", .data = &imx35_gpio_hwdata },
+ { .compatible = "fsl,imx8dxl-gpio", .data = &imx35_gpio_hwdata },
+ { .compatible = "fsl,imx8qm-gpio", .data = &imx35_gpio_hwdata },
+ { .compatible = "fsl,imx8qxp-gpio", .data = &imx35_gpio_hwdata },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, mxc_gpio_dt_ids);
@@ -203,6 +215,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
}
writel(1 << gpio_idx, port->base + GPIO_ISR);
+ port->pad_type[gpio_idx] = type;
return 0;
}
@@ -254,6 +267,9 @@ static void mx3_gpio_irq_handler(struct irq_desc *desc)
struct mxc_gpio_port *port = irq_desc_get_handler_data(desc);
struct irq_chip *chip = irq_desc_get_chip(desc);
+ if (port->is_pad_wakeup)
+ return;
+
chained_irq_enter(chip, desc);
irq_stat = readl(port->base + GPIO_ISR) & readl(port->base + GPIO_IMR);
@@ -306,11 +322,13 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
ret = enable_irq_wake(port->irq_high);
else
ret = enable_irq_wake(port->irq);
+ port->wakeup_pads |= (1 << gpio_idx);
} else {
if (port->irq_high && (gpio_idx >= 16))
ret = disable_irq_wake(port->irq_high);
else
ret = disable_irq_wake(port->irq);
+ port->wakeup_pads &= ~(1 << gpio_idx);
}
return ret;
@@ -365,7 +383,6 @@ static int mxc_gpio_probe(struct platform_device *pdev)
return -ENOMEM;
port->dev = &pdev->dev;
-
port->hwdata = device_get_match_data(&pdev->dev);
port->base = devm_platform_ioremap_resource(pdev, 0);
@@ -498,6 +515,78 @@ static void mxc_gpio_restore_regs(struct mxc_gpio_port *port)
writel(port->gpio_saved_reg.dr, port->base + GPIO_DR);
}
+static bool mxc_gpio_generic_config(struct mxc_gpio_port *port,
+ unsigned int offset, unsigned long conf)
+{
+ struct device_node *np = port->dev->of_node;
+
+ if (of_device_is_compatible(np, "fsl,imx8dxl-gpio") ||
+ of_device_is_compatible(np, "fsl,imx8qxp-gpio") ||
+ of_device_is_compatible(np, "fsl,imx8qm-gpio"))
+ return (gpiochip_generic_config(&port->gc, offset, conf) == 0);
+
+ return false;
+}
+
+static bool mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable)
+{
+ unsigned long config;
+ bool ret = false;
+ int i, type;
+
+ static const u32 pad_type_map[] = {
+ IMX_SCU_WAKEUP_OFF, /* 0 */
+ IMX_SCU_WAKEUP_RISE_EDGE, /* IRQ_TYPE_EDGE_RISING */
+ IMX_SCU_WAKEUP_FALL_EDGE, /* IRQ_TYPE_EDGE_FALLING */
+ IMX_SCU_WAKEUP_FALL_EDGE, /* IRQ_TYPE_EDGE_BOTH */
+ IMX_SCU_WAKEUP_HIGH_LVL, /* IRQ_TYPE_LEVEL_HIGH */
+ IMX_SCU_WAKEUP_OFF, /* 5 */
+ IMX_SCU_WAKEUP_OFF, /* 6 */
+ IMX_SCU_WAKEUP_OFF, /* 7 */
+ IMX_SCU_WAKEUP_LOW_LVL, /* IRQ_TYPE_LEVEL_LOW */
+ };
+
+ for (i = 0; i < 32; i++) {
+ if ((port->wakeup_pads & (1 << i))) {
+ type = port->pad_type[i];
+ if (enable)
+ config = pad_type_map[type];
+ else
+ config = IMX_SCU_WAKEUP_OFF;
+ ret |= mxc_gpio_generic_config(port, i, config);
+ }
+ }
+
+ return ret;
+}
+
+static int __maybe_unused mxc_gpio_noirq_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct mxc_gpio_port *port = platform_get_drvdata(pdev);
+
+ if (port->wakeup_pads > 0)
+ port->is_pad_wakeup = mxc_gpio_set_pad_wakeup(port, true);
+
+ return 0;
+}
+
+static int __maybe_unused mxc_gpio_noirq_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct mxc_gpio_port *port = platform_get_drvdata(pdev);
+
+ if (port->wakeup_pads > 0)
+ mxc_gpio_set_pad_wakeup(port, false);
+ port->is_pad_wakeup = false;
+
+ return 0;
+}
+
+static const struct dev_pm_ops mxc_gpio_dev_pm_ops = {
+ SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(mxc_gpio_noirq_suspend, mxc_gpio_noirq_resume)
+};
+
static int mxc_gpio_syscore_suspend(void)
{
struct mxc_gpio_port *port;
@@ -537,6 +626,7 @@ static struct platform_driver mxc_gpio_driver = {
.name = "gpio-mxc",
.of_match_table = mxc_gpio_dt_ids,
.suppress_bind_attrs = true,
+ .pm = &mxc_gpio_dev_pm_ops,
},
.probe = mxc_gpio_probe,
};
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index ebe1943b85dd..6e67867e1dcd 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -10,8 +10,8 @@
#include <linux/acpi.h>
#include <linux/bitmap.h>
-#include <linux/gpio/driver.h>
#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
@@ -20,6 +20,7 @@
#include <linux/platform_data/pca953x.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
+#include <linux/seq_file.h>
#include <linux/slab.h>
#include <asm/unaligned.h>
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index 6464056cb6ae..9fc1f3dd4190 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -8,22 +8,23 @@
*
* Data sheet: ARM DDI 0190B, September 2000
*/
-#include <linux/spinlock.h>
+#include <linux/amba/bus.h>
+#include <linux/bitops.h>
+#include <linux/device.h>
#include <linux/errno.h>
+#include <linux/gpio/driver.h>
#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/ioport.h>
-#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/module.h>
-#include <linux/bitops.h>
-#include <linux/gpio/driver.h>
-#include <linux/device.h>
-#include <linux/amba/bus.h>
-#include <linux/slab.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pm.h>
+#include <linux/seq_file.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
#define GPIODIR 0x400
#define GPIOIS 0x404
diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c
index 54d9fa7da9c1..fdc5bdcd5638 100644
--- a/drivers/gpio/gpio-tegra186.c
+++ b/drivers/gpio/gpio-tegra186.c
@@ -7,12 +7,13 @@
*/
#include <linux/gpio/driver.h>
+#include <linux/hte.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
-#include <linux/hte.h>
+#include <linux/seq_file.h>
#include <dt-bindings/gpio/tegra186-gpio.h>
#include <dt-bindings/gpio/tegra194-gpio.h>
diff --git a/drivers/gpio/gpio-wm8350.c b/drivers/gpio/gpio-wm8350.c
index b1b131fb9804..2421cf606ed6 100644
--- a/drivers/gpio/gpio-wm8350.c
+++ b/drivers/gpio/gpio-wm8350.c
@@ -8,13 +8,12 @@
*
*/
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/module.h>
#include <linux/gpio/driver.h>
+#include <linux/kernel.h>
#include <linux/mfd/core.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/seq_file.h>
+#include <linux/slab.h>
#include <linux/mfd/wm8350/core.h>
#include <linux/mfd/wm8350/gpio.h>
diff --git a/drivers/gpio/gpiolib-acpi.h b/drivers/gpio/gpiolib-acpi.h
index 1ac6816839db..01e0cb480a00 100644
--- a/drivers/gpio/gpiolib-acpi.h
+++ b/drivers/gpio/gpiolib-acpi.h
@@ -8,7 +8,19 @@
#ifndef GPIOLIB_ACPI_H
#define GPIOLIB_ACPI_H
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+
+#include <linux/gpio/consumer.h>
+
struct acpi_device;
+struct device;
+struct fwnode_handle;
+
+struct gpio_chip;
+struct gpio_desc;
+struct gpio_device;
/**
* struct acpi_gpio_info - ACPI GPIO specific information
diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c
index 0cb6b468f364..65b2c09a4576 100644
--- a/drivers/gpio/gpiolib-cdev.c
+++ b/drivers/gpio/gpiolib-cdev.c
@@ -12,6 +12,7 @@
#include <linux/file.h>
#include <linux/gpio.h>
#include <linux/gpio/driver.h>
+#include <linux/hte.h>
#include <linux/interrupt.h>
#include <linux/irqreturn.h>
#include <linux/kernel.h>
@@ -20,11 +21,12 @@
#include <linux/mutex.h>
#include <linux/pinctrl/consumer.h>
#include <linux/poll.h>
+#include <linux/seq_file.h>
#include <linux/spinlock.h>
#include <linux/timekeeping.h>
#include <linux/uaccess.h>
#include <linux/workqueue.h>
-#include <linux/hte.h>
+
#include <uapi/linux/gpio.h>
#include "gpiolib.h"
diff --git a/drivers/gpio/gpiolib-of.h b/drivers/gpio/gpiolib-of.h
index 8af2bc899aab..1b5df39a952e 100644
--- a/drivers/gpio/gpiolib-of.h
+++ b/drivers/gpio/gpiolib-of.h
@@ -3,8 +3,17 @@
#ifndef GPIOLIB_OF_H
#define GPIOLIB_OF_H
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+
+#include <linux/notifier.h>
+
+struct device;
+
struct gpio_chip;
-enum of_gpio_flags;
+struct gpio_desc;
+struct gpio_device;
#ifdef CONFIG_OF_GPIO
struct gpio_desc *of_find_gpio(struct device *dev,
diff --git a/drivers/gpio/gpiolib-sysfs.h b/drivers/gpio/gpiolib-sysfs.h
index ddd0e503f8eb..0f213bdb4732 100644
--- a/drivers/gpio/gpiolib-sysfs.h
+++ b/drivers/gpio/gpiolib-sysfs.h
@@ -5,6 +5,8 @@
#ifdef CONFIG_GPIO_SYSFS
+struct gpio_device;
+
int gpiochip_sysfs_register(struct gpio_device *gdev);
void gpiochip_sysfs_unregister(struct gpio_device *gdev);
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 34f5a092c99e..315cbdf61979 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -8,7 +8,6 @@
menuconfig DRM
tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
depends on (AGP || AGP=n) && !EMULATED_CMPXCHG && HAS_DMA
- select DRM_NOMODESET
select DRM_PANEL_ORIENTATION_QUIRKS
select HDMI
select FB_CMDLINE
@@ -19,6 +18,7 @@ menuconfig DRM
# gallium uses SYS_kcmp for os_same_file_description() to de-duplicate
# device and dmabuf fd. Let's make sure that is available for our userspace.
select KCMP
+ select VIDEO_NOMODESET
help
Kernel-level support for the Direct Rendering Infrastructure (DRI)
introduced in XFree86 4.0. If you say Y here, you need to select
@@ -233,64 +233,8 @@ source "drivers/gpu/drm/i2c/Kconfig"
source "drivers/gpu/drm/arm/Kconfig"
-config DRM_RADEON
- tristate "ATI Radeon"
- depends on DRM && PCI && MMU
- depends on AGP || !AGP
- select FW_LOADER
- select DRM_DISPLAY_DP_HELPER
- select DRM_DISPLAY_HELPER
- select DRM_KMS_HELPER
- select DRM_TTM
- select DRM_TTM_HELPER
- select POWER_SUPPLY
- select HWMON
- select BACKLIGHT_CLASS_DEVICE
- select INTERVAL_TREE
- # radeon depends on ACPI_VIDEO when ACPI is enabled, for select to work
- # ACPI_VIDEO's dependencies must also be selected.
- select INPUT if ACPI
- select ACPI_VIDEO if ACPI
- # On x86 ACPI_VIDEO also needs ACPI_WMI
- select X86_PLATFORM_DEVICES if ACPI && X86
- select ACPI_WMI if ACPI && X86
- help
- Choose this option if you have an ATI Radeon graphics card. There
- are both PCI and AGP versions. You don't need to choose this to
- run the Radeon in plain VGA mode.
-
- If M is selected, the module will be called radeon.
-
source "drivers/gpu/drm/radeon/Kconfig"
-config DRM_AMDGPU
- tristate "AMD GPU"
- depends on DRM && PCI && MMU
- select FW_LOADER
- select DRM_DISPLAY_DP_HELPER
- select DRM_DISPLAY_HDMI_HELPER
- select DRM_DISPLAY_HELPER
- select DRM_KMS_HELPER
- select DRM_SCHED
- select DRM_TTM
- select DRM_TTM_HELPER
- select POWER_SUPPLY
- select HWMON
- select BACKLIGHT_CLASS_DEVICE
- select INTERVAL_TREE
- select DRM_BUDDY
- # amdgpu depends on ACPI_VIDEO when ACPI is enabled, for select to work
- # ACPI_VIDEO's dependencies must also be selected.
- select INPUT if ACPI
- select ACPI_VIDEO if ACPI
- # On x86 ACPI_VIDEO also needs ACPI_WMI
- select X86_PLATFORM_DEVICES if ACPI && X86
- select ACPI_WMI if ACPI && X86
- help
- Choose this option if you have a recent AMD Radeon graphics card.
-
- If M is selected, the module will be called amdgpu.
-
source "drivers/gpu/drm/amd/amdgpu/Kconfig"
source "drivers/gpu/drm/nouveau/Kconfig"
@@ -514,11 +458,6 @@ config DRM_EXPORT_FOR_TESTS
config DRM_PANEL_ORIENTATION_QUIRKS
tristate
-# Separate option because nomodeset parameter is global and expected built-in
-config DRM_NOMODESET
- bool
- default n
-
config DRM_LIB_RANDOM
bool
default n
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 0b283e46f28b..cc637343d87b 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -5,35 +5,74 @@
CFLAGS-$(CONFIG_DRM_USE_DYNAMIC_DEBUG) += -DDYNAMIC_DEBUG_MODULE
-drm-y := drm_aperture.o drm_auth.o drm_cache.o \
- drm_file.o drm_gem.o drm_ioctl.o \
- drm_drv.o \
- drm_sysfs.o drm_mm.o \
- drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o drm_displayid.o \
- drm_trace_points.o drm_prime.o \
- drm_vma_manager.o \
- drm_modeset_lock.o drm_atomic.o drm_bridge.o \
- drm_framebuffer.o drm_connector.o drm_blend.o \
- drm_encoder.o drm_mode_object.o drm_property.o \
- drm_plane.o drm_color_mgmt.o drm_print.o \
- drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
- drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
- drm_client_modeset.o drm_atomic_uapi.o \
- drm_managed.o drm_vblank_work.o
-drm-$(CONFIG_DRM_LEGACY) += drm_agpsupport.o drm_bufs.o drm_context.o drm_dma.o \
- drm_hashtab.o drm_irq.o drm_legacy_misc.o drm_lock.o \
- drm_memory.o drm_scatter.o drm_vm.o
+drm-y := \
+ drm_aperture.o \
+ drm_atomic.o \
+ drm_atomic_uapi.o \
+ drm_auth.o \
+ drm_blend.o \
+ drm_bridge.o \
+ drm_cache.o \
+ drm_client.o \
+ drm_client_modeset.o \
+ drm_color_mgmt.o \
+ drm_connector.o \
+ drm_crtc.o \
+ drm_displayid.o \
+ drm_drv.o \
+ drm_dumb_buffers.o \
+ drm_edid.o \
+ drm_encoder.o \
+ drm_file.o \
+ drm_fourcc.o \
+ drm_framebuffer.o \
+ drm_gem.o \
+ drm_ioctl.o \
+ drm_lease.o \
+ drm_managed.o \
+ drm_mm.o \
+ drm_mode_config.o \
+ drm_mode_object.o \
+ drm_modes.o \
+ drm_modeset_lock.o \
+ drm_plane.o \
+ drm_prime.o \
+ drm_print.o \
+ drm_property.o \
+ drm_syncobj.o \
+ drm_sysfs.o \
+ drm_trace_points.o \
+ drm_vblank.o \
+ drm_vblank_work.o \
+ drm_vma_manager.o \
+ drm_writeback.o
+drm-$(CONFIG_DRM_LEGACY) += \
+ drm_agpsupport.o \
+ drm_bufs.o \
+ drm_context.o \
+ drm_dma.o \
+ drm_hashtab.o \
+ drm_irq.o \
+ drm_legacy_misc.o \
+ drm_lock.o \
+ drm_memory.o \
+ drm_scatter.o \
+ drm_vm.o
drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
drm-$(CONFIG_COMPAT) += drm_ioc32.o
drm-$(CONFIG_DRM_PANEL) += drm_panel.o
drm-$(CONFIG_OF) += drm_of.o
drm-$(CONFIG_PCI) += drm_pci.o
-drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
+drm-$(CONFIG_DEBUG_FS) += \
+ drm_debugfs.o \
+ drm_debugfs_crc.o
drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
-drm-$(CONFIG_DRM_PRIVACY_SCREEN) += drm_privacy_screen.o drm_privacy_screen_x86.o
+drm-$(CONFIG_DRM_PRIVACY_SCREEN) += \
+ drm_privacy_screen.o \
+ drm_privacy_screen_x86.o
+drm-$(CONFIG_DRM_ACCEL) += ../../accel/drm_accel.o
obj-$(CONFIG_DRM) += drm.o
-obj-$(CONFIG_DRM_NOMODESET) += drm_nomodeset.o
obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o
#
@@ -59,18 +98,28 @@ obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o
# Modesetting helpers
#
-drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o \
- drm_encoder_slave.o drm_flip_work.o \
- drm_probe_helper.o \
- drm_plane_helper.o drm_atomic_helper.o \
- drm_kms_helper_common.o \
- drm_simple_kms_helper.o drm_modeset_helper.o \
- drm_gem_atomic_helper.o \
- drm_gem_framebuffer_helper.o \
- drm_atomic_state_helper.o drm_damage_helper.o \
- drm_format_helper.o drm_self_refresh_helper.o drm_rect.o
+drm_kms_helper-y := \
+ drm_atomic_helper.o \
+ drm_atomic_state_helper.o \
+ drm_bridge_connector.o \
+ drm_crtc_helper.o \
+ drm_damage_helper.o \
+ drm_encoder_slave.o \
+ drm_flip_work.o \
+ drm_format_helper.o \
+ drm_gem_atomic_helper.o \
+ drm_gem_framebuffer_helper.o \
+ drm_kms_helper_common.o \
+ drm_modeset_helper.o \
+ drm_plane_helper.o \
+ drm_probe_helper.o \
+ drm_rect.o \
+ drm_self_refresh_helper.o \
+ drm_simple_kms_helper.o
drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
-drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
+drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += \
+ drm_fbdev_generic.o \
+ drm_fb_helper.o
obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
#
diff --git a/drivers/gpu/drm/amd/amdgpu/Kconfig b/drivers/gpu/drm/amd/amdgpu/Kconfig
index 7777d55275de..5fcd510f1abb 100644
--- a/drivers/gpu/drm/amd/amdgpu/Kconfig
+++ b/drivers/gpu/drm/amd/amdgpu/Kconfig
@@ -1,4 +1,33 @@
# SPDX-License-Identifier: MIT
+
+config DRM_AMDGPU
+ tristate "AMD GPU"
+ depends on DRM && PCI && MMU
+ select FW_LOADER
+ select DRM_DISPLAY_DP_HELPER
+ select DRM_DISPLAY_HDMI_HELPER
+ select DRM_DISPLAY_HELPER
+ select DRM_KMS_HELPER
+ select DRM_SCHED
+ select DRM_TTM
+ select DRM_TTM_HELPER
+ select POWER_SUPPLY
+ select HWMON
+ select BACKLIGHT_CLASS_DEVICE
+ select INTERVAL_TREE
+ select DRM_BUDDY
+ # amdgpu depends on ACPI_VIDEO when ACPI is enabled, for select to work
+ # ACPI_VIDEO's dependencies must also be selected.
+ select INPUT if ACPI
+ select ACPI_VIDEO if ACPI
+ # On x86 ACPI_VIDEO also needs ACPI_WMI
+ select X86_PLATFORM_DEVICES if ACPI && X86
+ select ACPI_WMI if ACPI && X86
+ help
+ Choose this option if you have a recent AMD Radeon graphics card.
+
+ If M is selected, the module will be called amdgpu.
+
config DRM_AMDGPU_SI
bool "Enable amdgpu support for SI parts"
depends on DRM_AMDGPU
diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile
index 6ad39cf71bdd..798d0e9a60b7 100644
--- a/drivers/gpu/drm/amd/amdgpu/Makefile
+++ b/drivers/gpu/drm/amd/amdgpu/Makefile
@@ -58,7 +58,8 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \
amdgpu_vm_sdma.o amdgpu_discovery.o amdgpu_ras_eeprom.o amdgpu_nbio.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_eeprom.o amdgpu_mca.o amdgpu_psp_ta.o amdgpu_lsdma.o \
+ amdgpu_ring_mux.o
amdgpu-$(CONFIG_PROC_FS) += amdgpu_fdinfo.o
@@ -250,7 +251,7 @@ endif
amdgpu-$(CONFIG_COMPAT) += amdgpu_ioc32.o
amdgpu-$(CONFIG_VGA_SWITCHEROO) += amdgpu_atpx_handler.o
amdgpu-$(CONFIG_ACPI) += amdgpu_acpi.o
-amdgpu-$(CONFIG_HMM_MIRROR) += amdgpu_mn.o
+amdgpu-$(CONFIG_HMM_MIRROR) += amdgpu_hmm.o
include $(FULL_AMD_PATH)/pm/Makefile
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 2eca58220550..6b74df446694 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -82,7 +82,6 @@
#include "amdgpu_vce.h"
#include "amdgpu_vcn.h"
#include "amdgpu_jpeg.h"
-#include "amdgpu_mn.h"
#include "amdgpu_gmc.h"
#include "amdgpu_gfx.h"
#include "amdgpu_sdma.h"
@@ -219,10 +218,12 @@ extern int amdgpu_use_xgmi_p2p;
extern int sched_policy;
extern bool debug_evictions;
extern bool no_system_mem_limit;
+extern int halt_if_hws_hang;
#else
static const int __maybe_unused sched_policy = KFD_SCHED_POLICY_HWS;
static const bool __maybe_unused debug_evictions; /* = false */
static const bool __maybe_unused no_system_mem_limit;
+static const int __maybe_unused halt_if_hws_hang;
#endif
#ifdef CONFIG_HSA_AMD_P2P
extern bool pcie_p2p;
@@ -675,7 +676,7 @@ enum amd_hw_ip_block_type {
MAX_HWIP
};
-#define HWIP_MAX_INSTANCE 11
+#define HWIP_MAX_INSTANCE 28
#define HW_ID_MAX 300
#define IP_VERSION(mj, mn, rv) (((mj) << 16) | ((mn) << 8) | (rv))
@@ -1063,6 +1064,7 @@ struct amdgpu_device {
struct work_struct reset_work;
bool job_hang;
+ bool dc_enabled;
};
static inline struct amdgpu_device *drm_to_adev(struct drm_device *ddev)
@@ -1120,6 +1122,8 @@ void amdgpu_device_indirect_wreg64(struct amdgpu_device *adev,
bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type);
bool amdgpu_device_has_dc_support(struct amdgpu_device *adev);
+void amdgpu_device_set_sriov_virtual_display(struct amdgpu_device *adev);
+
int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
struct amdgpu_reset_context *reset_context);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
index b14800ac179e..57b5e11446c6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
@@ -847,7 +847,7 @@ int amdgpu_acpi_init(struct amdgpu_device *adev)
struct amdgpu_atif *atif = &amdgpu_acpi_priv.atif;
if (atif->notifications.brightness_change) {
- if (amdgpu_device_has_dc_support(adev)) {
+ if (adev->dc_enabled) {
#if defined(CONFIG_DRM_AMD_DC)
struct amdgpu_display_manager *dm = &adev->dm;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
index 5d9a34601a1a..f99d4873bf22 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
@@ -195,7 +195,7 @@ void amdgpu_amdkfd_device_init(struct amdgpu_device *adev)
}
adev->kfd.init_complete = kgd2kfd_device_init(adev->kfd.dev,
- adev_to_drm(adev), &gpu_resources);
+ &gpu_resources);
amdgpu_amdkfd_total_mem_size += adev->gmc.real_vram_size;
@@ -673,7 +673,7 @@ int amdgpu_amdkfd_submit_ib(struct amdgpu_device *adev,
goto err;
}
- ret = amdgpu_job_alloc(adev, 1, &job, NULL);
+ ret = amdgpu_job_alloc(adev, NULL, NULL, NULL, 1, &job);
if (ret)
goto err;
@@ -760,9 +760,7 @@ bool amdgpu_amdkfd_have_atomics_support(struct amdgpu_device *adev)
void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev, bool reset)
{
- struct ras_err_data err_data = {0, 0, 0, NULL};
-
- amdgpu_umc_poison_handler(adev, &err_data, reset);
+ amdgpu_umc_poison_handler(adev, reset);
}
bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
index 647220a8762d..f50e3ba4d7a5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
@@ -353,7 +353,6 @@ int kgd2kfd_init(void);
void kgd2kfd_exit(void);
struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf);
bool kgd2kfd_device_init(struct kfd_dev *kfd,
- struct drm_device *ddev,
const struct kgd2kfd_shared_resources *gpu_resources);
void kgd2kfd_device_exit(struct kfd_dev *kfd);
void kgd2kfd_suspend(struct kfd_dev *kfd, bool run_pm);
@@ -381,7 +380,7 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
}
static inline
-bool kgd2kfd_device_init(struct kfd_dev *kfd, struct drm_device *ddev,
+bool kgd2kfd_device_init(struct kfd_dev *kfd,
const struct kgd2kfd_shared_resources *gpu_resources)
{
return false;
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 81e3b528bbc9..e92b93557c13 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v9.c
@@ -787,7 +787,7 @@ 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++) {
- gfx_v9_0_select_se_sh(adev, se_idx, sh_idx, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, se_idx, sh_idx, 0xffffffff);
queue_map = RREG32_SOC15(GC, 0, mmSPI_CSQ_WF_ACTIVE_STATUS);
/*
@@ -820,7 +820,7 @@ void kgd_gfx_v9_get_cu_occupancy(struct amdgpu_device *adev, int pasid,
}
}
- gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
soc15_grbm_select(adev, 0, 0, 0, 0);
unlock_spi_csq_mutexes(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 1f76e27f1a35..8782916e64a0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -29,6 +29,7 @@
#include "amdgpu_object.h"
#include "amdgpu_gem.h"
#include "amdgpu_vm.h"
+#include "amdgpu_hmm.h"
#include "amdgpu_amdkfd.h"
#include "amdgpu_dma_buf.h"
#include <uapi/linux/kfd_ioctl.h>
@@ -403,63 +404,15 @@ static int vm_update_pds(struct amdgpu_vm *vm, struct amdgpu_sync *sync)
static uint64_t get_pte_flags(struct amdgpu_device *adev, struct kgd_mem *mem)
{
- struct amdgpu_device *bo_adev = amdgpu_ttm_adev(mem->bo->tbo.bdev);
- bool coherent = mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_COHERENT;
- bool uncached = mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_UNCACHED;
- uint32_t mapping_flags;
- uint64_t pte_flags;
- bool snoop = false;
+ uint32_t mapping_flags = AMDGPU_VM_PAGE_READABLE |
+ AMDGPU_VM_MTYPE_DEFAULT;
- mapping_flags = AMDGPU_VM_PAGE_READABLE;
if (mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_WRITABLE)
mapping_flags |= AMDGPU_VM_PAGE_WRITEABLE;
if (mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_EXECUTABLE)
mapping_flags |= AMDGPU_VM_PAGE_EXECUTABLE;
- switch (adev->asic_type) {
- case CHIP_ARCTURUS:
- case CHIP_ALDEBARAN:
- if (mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM) {
- if (bo_adev == adev) {
- if (uncached)
- mapping_flags |= AMDGPU_VM_MTYPE_UC;
- else if (coherent)
- mapping_flags |= AMDGPU_VM_MTYPE_CC;
- else
- mapping_flags |= AMDGPU_VM_MTYPE_RW;
- if (adev->asic_type == CHIP_ALDEBARAN &&
- adev->gmc.xgmi.connected_to_cpu)
- snoop = true;
- } else {
- if (uncached || coherent)
- mapping_flags |= AMDGPU_VM_MTYPE_UC;
- else
- mapping_flags |= AMDGPU_VM_MTYPE_NC;
- if (amdgpu_xgmi_same_hive(adev, bo_adev))
- snoop = true;
- }
- } else {
- if (uncached || coherent)
- mapping_flags |= AMDGPU_VM_MTYPE_UC;
- else
- mapping_flags |= AMDGPU_VM_MTYPE_NC;
- snoop = true;
- }
- break;
- default:
- if (uncached || coherent)
- mapping_flags |= AMDGPU_VM_MTYPE_UC;
- else
- mapping_flags |= AMDGPU_VM_MTYPE_NC;
-
- if (!(mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_VRAM))
- snoop = true;
- }
-
- pte_flags = amdgpu_gem_va_map_flags(adev, mapping_flags);
- pte_flags |= snoop ? AMDGPU_PTE_SNOOPED : 0;
-
- return pte_flags;
+ return amdgpu_gem_va_map_flags(adev, mapping_flags);
}
/**
@@ -997,7 +950,7 @@ static int init_user_pages(struct kgd_mem *mem, uint64_t user_addr,
goto out;
}
- ret = amdgpu_mn_register(bo, user_addr);
+ ret = amdgpu_hmm_register(bo, user_addr);
if (ret) {
pr_err("%s: Failed to register MMU notifier: %d\n",
__func__, ret);
@@ -1037,7 +990,7 @@ release_out:
amdgpu_ttm_tt_get_user_pages_done(bo->tbo.ttm, range);
unregister_out:
if (ret)
- amdgpu_mn_unregister(bo);
+ amdgpu_hmm_unregister(bo);
out:
mutex_unlock(&process_info->lock);
return ret;
@@ -1672,6 +1625,11 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
}
}
+ if (flags & KFD_IOC_ALLOC_MEM_FLAGS_COHERENT)
+ alloc_flags |= AMDGPU_GEM_CREATE_COHERENT;
+ if (flags & KFD_IOC_ALLOC_MEM_FLAGS_UNCACHED)
+ alloc_flags |= AMDGPU_GEM_CREATE_UNCACHED;
+
*mem = kzalloc(sizeof(struct kgd_mem), GFP_KERNEL);
if (!*mem) {
ret = -ENOMEM;
@@ -1816,7 +1774,7 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
mutex_unlock(&process_info->lock);
/* No more MMU notifiers */
- amdgpu_mn_unregister(mem->bo);
+ amdgpu_hmm_unregister(mem->bo);
ret = reserve_bo_and_cond_vms(mem, NULL, BO_VM_ALL, &ctx);
if (unlikely(ret))
@@ -1906,16 +1864,6 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
*/
mutex_lock(&mem->process_info->lock);
- /* Lock mmap-sem. If we find an invalid userptr BO, we can be
- * sure that the MMU notifier is no longer running
- * concurrently and the queues are actually stopped
- */
- if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm)) {
- mmap_write_lock(current->mm);
- is_invalid_userptr = atomic_read(&mem->invalid);
- mmap_write_unlock(current->mm);
- }
-
mutex_lock(&mem->lock);
domain = mem->domain;
@@ -2256,7 +2204,7 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf(struct amdgpu_device *adev,
ret = drm_vma_node_allow(&obj->vma_node, drm_priv);
if (ret) {
- kfree(mem);
+ kfree(*mem);
return ret;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
index b81b77a9efa6..ac6fe0ae4609 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
@@ -101,39 +101,101 @@ void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev)
}
}
+static int amdgpu_atomfirmware_allocate_fb_v2_1(struct amdgpu_device *adev,
+ struct vram_usagebyfirmware_v2_1 *fw_usage, int *usage_bytes)
+{
+ u32 start_addr, fw_size, drv_size;
+
+ start_addr = le32_to_cpu(fw_usage->start_address_in_kb);
+ fw_size = le16_to_cpu(fw_usage->used_by_firmware_in_kb);
+ drv_size = le16_to_cpu(fw_usage->used_by_driver_in_kb);
+
+ DRM_DEBUG("atom firmware v2_1 requested %08x %dkb fw %dkb drv\n",
+ start_addr,
+ fw_size,
+ drv_size);
+
+ if ((start_addr & ATOM_VRAM_OPERATION_FLAGS_MASK) ==
+ (u32)(ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION <<
+ ATOM_VRAM_OPERATION_FLAGS_SHIFT)) {
+ /* Firmware request VRAM reservation for SR-IOV */
+ adev->mman.fw_vram_usage_start_offset = (start_addr &
+ (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10;
+ adev->mman.fw_vram_usage_size = fw_size << 10;
+ /* Use the default scratch size */
+ *usage_bytes = 0;
+ } else {
+ *usage_bytes = drv_size << 10;
+ }
+ return 0;
+}
+
+static int amdgpu_atomfirmware_allocate_fb_v2_2(struct amdgpu_device *adev,
+ struct vram_usagebyfirmware_v2_2 *fw_usage, int *usage_bytes)
+{
+ u32 fw_start_addr, fw_size, drv_start_addr, drv_size;
+
+ fw_start_addr = le32_to_cpu(fw_usage->fw_region_start_address_in_kb);
+ fw_size = le16_to_cpu(fw_usage->used_by_firmware_in_kb);
+
+ drv_start_addr = le32_to_cpu(fw_usage->driver_region0_start_address_in_kb);
+ drv_size = le32_to_cpu(fw_usage->used_by_driver_region0_in_kb);
+
+ DRM_DEBUG("atom requested fw start at %08x %dkb and drv start at %08x %dkb\n",
+ fw_start_addr,
+ fw_size,
+ drv_start_addr,
+ drv_size);
+
+ if (amdgpu_sriov_vf(adev) &&
+ ((fw_start_addr & (ATOM_VRAM_BLOCK_NEEDS_NO_RESERVATION <<
+ ATOM_VRAM_OPERATION_FLAGS_SHIFT)) == 0)) {
+ /* Firmware request VRAM reservation for SR-IOV */
+ adev->mman.fw_vram_usage_start_offset = (fw_start_addr &
+ (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10;
+ adev->mman.fw_vram_usage_size = fw_size << 10;
+ }
+
+ if (amdgpu_sriov_vf(adev) &&
+ ((drv_start_addr & (ATOM_VRAM_BLOCK_NEEDS_NO_RESERVATION <<
+ ATOM_VRAM_OPERATION_FLAGS_SHIFT)) == 0)) {
+ /* driver request VRAM reservation for SR-IOV */
+ adev->mman.drv_vram_usage_start_offset = (drv_start_addr &
+ (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10;
+ adev->mman.drv_vram_usage_size = drv_size << 10;
+ }
+
+ *usage_bytes = 0;
+ return 0;
+}
+
int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev)
{
struct atom_context *ctx = adev->mode_info.atom_context;
int index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
vram_usagebyfirmware);
- struct vram_usagebyfirmware_v2_1 *firmware_usage;
- uint32_t start_addr, size;
- uint16_t data_offset;
+ struct vram_usagebyfirmware_v2_1 *fw_usage_v2_1;
+ struct vram_usagebyfirmware_v2_2 *fw_usage_v2_2;
+ u16 data_offset;
+ u8 frev, crev;
int usage_bytes = 0;
- if (amdgpu_atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) {
- firmware_usage = (struct vram_usagebyfirmware_v2_1 *)(ctx->bios + data_offset);
- DRM_DEBUG("atom firmware requested %08x %dkb fw %dkb drv\n",
- le32_to_cpu(firmware_usage->start_address_in_kb),
- le16_to_cpu(firmware_usage->used_by_firmware_in_kb),
- le16_to_cpu(firmware_usage->used_by_driver_in_kb));
-
- start_addr = le32_to_cpu(firmware_usage->start_address_in_kb);
- size = le16_to_cpu(firmware_usage->used_by_firmware_in_kb);
-
- if ((uint32_t)(start_addr & ATOM_VRAM_OPERATION_FLAGS_MASK) ==
- (uint32_t)(ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION <<
- ATOM_VRAM_OPERATION_FLAGS_SHIFT)) {
- /* Firmware request VRAM reservation for SR-IOV */
- adev->mman.fw_vram_usage_start_offset = (start_addr &
- (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10;
- adev->mman.fw_vram_usage_size = size << 10;
- /* Use the default scratch size */
- usage_bytes = 0;
- } else {
- usage_bytes = le16_to_cpu(firmware_usage->used_by_driver_in_kb) << 10;
+ if (amdgpu_atom_parse_data_header(ctx, index, NULL, &frev, &crev, &data_offset)) {
+ if (frev == 2 && crev == 1) {
+ fw_usage_v2_1 =
+ (struct vram_usagebyfirmware_v2_1 *)(ctx->bios + data_offset);
+ amdgpu_atomfirmware_allocate_fb_v2_1(adev,
+ fw_usage_v2_1,
+ &usage_bytes);
+ } else if (frev >= 2 && crev >= 2) {
+ fw_usage_v2_2 =
+ (struct vram_usagebyfirmware_v2_2 *)(ctx->bios + data_offset);
+ amdgpu_atomfirmware_allocate_fb_v2_2(adev,
+ fw_usage_v2_2,
+ &usage_bytes);
}
}
+
ctx->scratch_size_bytes = 0;
if (usage_bytes == 0)
usage_bytes = 20 * 1024;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
index e363f56c72af..30c28a69e847 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
@@ -317,6 +317,7 @@ static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
if (!found)
return false;
+ pci_dev_put(pdev);
adev->bios = kmalloc(size, GFP_KERNEL);
if (!adev->bios) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
index cfb262911bfc..2ebbc6382a06 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
@@ -26,7 +26,6 @@
#include <drm/display/drm_dp_helper.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_probe_helper.h>
#include <drm/amdgpu_drm.h>
#include "amdgpu.h"
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 365e3fb6a9e5..8516c814bc9b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -294,12 +294,8 @@ static int amdgpu_cs_pass1(struct amdgpu_cs_parser *p,
}
for (i = 0; i < p->gang_size; ++i) {
- ret = amdgpu_job_alloc(p->adev, num_ibs[i], &p->jobs[i], vm);
- if (ret)
- goto free_all_kdata;
-
- ret = drm_sched_job_init(&p->jobs[i]->base, p->entities[i],
- &fpriv->vm);
+ ret = amdgpu_job_alloc(p->adev, vm, p->entities[i], vm,
+ num_ibs[i], &p->jobs[i]);
if (ret)
goto free_all_kdata;
}
@@ -433,7 +429,7 @@ static int amdgpu_cs_p2_dependencies(struct amdgpu_cs_parser *p,
dma_fence_put(old);
}
- r = amdgpu_sync_fence(&p->gang_leader->sync, fence);
+ r = amdgpu_sync_fence(&p->sync, fence);
dma_fence_put(fence);
if (r)
return r;
@@ -455,9 +451,20 @@ static int amdgpu_syncobj_lookup_and_add(struct amdgpu_cs_parser *p,
return r;
}
- r = amdgpu_sync_fence(&p->gang_leader->sync, fence);
- dma_fence_put(fence);
+ r = amdgpu_sync_fence(&p->sync, fence);
+ if (r)
+ goto error;
+ /*
+ * When we have an explicit dependency it might be necessary to insert a
+ * pipeline sync to make sure that all caches etc are flushed and the
+ * next job actually sees the results from the previous one.
+ */
+ if (fence->context == p->gang_leader->base.entity->fence_context)
+ r = amdgpu_sync_fence(&p->gang_leader->explicit_sync, fence);
+
+error:
+ dma_fence_put(fence);
return r;
}
@@ -1106,7 +1113,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
if (r)
return r;
- r = amdgpu_sync_fence(&job->sync, fpriv->prt_va->last_pt_update);
+ r = amdgpu_sync_fence(&p->sync, fpriv->prt_va->last_pt_update);
if (r)
return r;
@@ -1117,7 +1124,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
if (r)
return r;
- r = amdgpu_sync_fence(&job->sync, bo_va->last_pt_update);
+ r = amdgpu_sync_fence(&p->sync, bo_va->last_pt_update);
if (r)
return r;
}
@@ -1136,7 +1143,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
if (r)
return r;
- r = amdgpu_sync_fence(&job->sync, bo_va->last_pt_update);
+ r = amdgpu_sync_fence(&p->sync, bo_va->last_pt_update);
if (r)
return r;
}
@@ -1149,7 +1156,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
if (r)
return r;
- r = amdgpu_sync_fence(&job->sync, vm->last_update);
+ r = amdgpu_sync_fence(&p->sync, vm->last_update);
if (r)
return r;
@@ -1181,7 +1188,6 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p)
static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
{
struct amdgpu_fpriv *fpriv = p->filp->driver_priv;
- struct amdgpu_job *leader = p->gang_leader;
struct amdgpu_bo_list_entry *e;
unsigned int i;
int r;
@@ -1193,17 +1199,14 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p)
sync_mode = amdgpu_bo_explicit_sync(bo) ?
AMDGPU_SYNC_EXPLICIT : AMDGPU_SYNC_NE_OWNER;
- r = amdgpu_sync_resv(p->adev, &leader->sync, resv, sync_mode,
+ r = amdgpu_sync_resv(p->adev, &p->sync, resv, sync_mode,
&fpriv->vm);
if (r)
return r;
}
for (i = 0; i < p->gang_size; ++i) {
- if (p->jobs[i] == leader)
- continue;
-
- r = amdgpu_sync_clone(&leader->sync, &p->jobs[i]->sync);
+ r = amdgpu_sync_push_to_job(&p->sync, p->jobs[i]);
if (r)
return r;
}
@@ -1251,7 +1254,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
continue;
fence = &p->jobs[i]->base.s_fence->scheduled;
- r = amdgpu_sync_fence(&leader->sync, fence);
+ r = drm_sched_job_add_dependency(&leader->base, fence);
if (r)
goto error_cleanup;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.h
index f80adf9069ec..113f39510a72 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.h
@@ -76,6 +76,8 @@ struct amdgpu_cs_parser {
unsigned num_post_deps;
struct amdgpu_cs_post_dep *post_deps;
+
+ struct amdgpu_sync sync;
};
int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
index de61a85c4b02..0f16d3c09309 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
@@ -1969,7 +1969,7 @@ int amdgpu_debugfs_init(struct amdgpu_device *adev)
amdgpu_ta_if_debugfs_init(adev);
#if defined(CONFIG_DRM_AMD_DC)
- if (amdgpu_device_has_dc_support(adev))
+ if (adev->dc_enabled)
dtn_debugfs_init(adev);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index f1e9663b4051..cfa411c12072 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -37,6 +37,7 @@
#include <linux/pci-p2pdma.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_fb_helper.h>
#include <drm/drm_probe_helper.h>
#include <drm/amdgpu_drm.h>
#include <linux/vgaarb.h>
@@ -1568,7 +1569,7 @@ static int amdgpu_device_check_arguments(struct amdgpu_device *adev)
* @pdev: pci dev pointer
* @state: vga_switcheroo state
*
- * Callback for the switcheroo driver. Suspends or resumes the
+ * Callback for the switcheroo driver. Suspends or resumes
* the asics before or after it is powered up using ACPI methods.
*/
static void amdgpu_switcheroo_set_state(struct pci_dev *pdev,
@@ -1915,6 +1916,16 @@ static void amdgpu_device_enable_virtual_display(struct amdgpu_device *adev)
}
}
+void amdgpu_device_set_sriov_virtual_display(struct amdgpu_device *adev)
+{
+ if (amdgpu_sriov_vf(adev) && !adev->enable_virtual_display) {
+ adev->mode_info.num_crtc = 1;
+ adev->enable_virtual_display = true;
+ DRM_INFO("virtual_display:%d, num_crtc:%d\n",
+ adev->enable_virtual_display, adev->mode_info.num_crtc);
+ }
+}
+
/**
* amdgpu_device_parse_gpu_info_fw - parse gpu info firmware
*
@@ -2397,7 +2408,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 || amdgpu_sriov_vf(adev)) {
+ if (amdgpu_mcbp) {
r = amdgpu_allocate_static_csa(adev, &adev->virt.csa_obj,
AMDGPU_GEM_DOMAIN_VRAM,
AMDGPU_CSA_SIZE);
@@ -2462,6 +2473,11 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
if (!amdgpu_sriov_vf(adev)) {
struct amdgpu_hive_info *hive = amdgpu_get_xgmi_hive(adev);
+ if (WARN_ON(!hive)) {
+ r = -ENOENT;
+ goto init_failed;
+ }
+
if (!hive->reset_domain ||
!amdgpu_reset_get_reset_domain(hive->reset_domain)) {
r = -ENOENT;
@@ -3347,8 +3363,7 @@ bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
*/
bool amdgpu_device_has_dc_support(struct amdgpu_device *adev)
{
- if (amdgpu_sriov_vf(adev) ||
- adev->enable_virtual_display ||
+ if (adev->enable_virtual_display ||
(adev->harvest_ip_mask & AMD_HARVEST_IP_DMU_MASK))
return false;
@@ -4171,21 +4186,15 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
r = amdgpu_device_ip_resume(adev);
- /* no matter what r is, always need to properly release full GPU */
- if (amdgpu_sriov_vf(adev)) {
- amdgpu_virt_init_data_exchange(adev);
- amdgpu_virt_release_full_gpu(adev, true);
- }
-
if (r) {
dev_err(adev->dev, "amdgpu_device_ip_resume failed (%d).\n", r);
- return r;
+ goto exit;
}
amdgpu_fence_driver_hw_init(adev);
r = amdgpu_device_ip_late_init(adev);
if (r)
- return r;
+ goto exit;
queue_delayed_work(system_wq, &adev->delayed_init_work,
msecs_to_jiffies(AMDGPU_RESUME_MS));
@@ -4193,9 +4202,18 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
if (!adev->in_s0ix) {
r = amdgpu_amdkfd_resume(adev, adev->in_runpm);
if (r)
- return r;
+ goto exit;
}
+exit:
+ if (amdgpu_sriov_vf(adev)) {
+ amdgpu_virt_init_data_exchange(adev);
+ amdgpu_virt_release_full_gpu(adev, true);
+ }
+
+ if (r)
+ return r;
+
/* Make sure IB tests flushed */
flush_delayed_work(&adev->delayed_init_work);
@@ -4213,25 +4231,27 @@ int amdgpu_device_resume(struct drm_device *dev, bool fbcon)
amdgpu_ras_resume(adev);
- /*
- * Most of the connector probing functions try to acquire runtime pm
- * refs to ensure that the GPU is powered on when connector polling is
- * performed. Since we're calling this from a runtime PM callback,
- * trying to acquire rpm refs will cause us to deadlock.
- *
- * Since we're guaranteed to be holding the rpm lock, it's safe to
- * temporarily disable the rpm helpers so this doesn't deadlock us.
- */
+ if (adev->mode_info.num_crtc) {
+ /*
+ * Most of the connector probing functions try to acquire runtime pm
+ * refs to ensure that the GPU is powered on when connector polling is
+ * performed. Since we're calling this from a runtime PM callback,
+ * trying to acquire rpm refs will cause us to deadlock.
+ *
+ * Since we're guaranteed to be holding the rpm lock, it's safe to
+ * temporarily disable the rpm helpers so this doesn't deadlock us.
+ */
#ifdef CONFIG_PM
- dev->dev->power.disable_depth++;
+ dev->dev->power.disable_depth++;
#endif
- if (!amdgpu_device_has_dc_support(adev))
- drm_helper_hpd_irq_event(dev);
- else
- drm_kms_helper_hotplug_event(dev);
+ if (!adev->dc_enabled)
+ drm_helper_hpd_irq_event(dev);
+ else
+ drm_kms_helper_hotplug_event(dev);
#ifdef CONFIG_PM
- dev->dev->power.disable_depth--;
+ dev->dev->power.disable_depth--;
#endif
+ }
adev->in_suspend = false;
if (amdgpu_acpi_smart_shift_update(dev, AMDGPU_SS_DEV_D0))
@@ -4580,6 +4600,10 @@ bool amdgpu_device_should_recover_gpu(struct amdgpu_device *adev)
if (amdgpu_gpu_recovery == 0)
goto disabled;
+ /* Skip soft reset check in fatal error mode */
+ if (!amdgpu_ras_is_poison_mode_supported(adev))
+ return true;
+
if (!amdgpu_device_ip_check_soft_reset(adev)) {
dev_info(adev->dev,"Timeout, but no hardware hang detected.\n");
return false;
@@ -5027,6 +5051,8 @@ static void amdgpu_device_resume_display_audio(struct amdgpu_device *adev)
pm_runtime_enable(&(p->dev));
pm_runtime_resume(&(p->dev));
}
+
+ pci_dev_put(p);
}
static int amdgpu_device_suspend_display_audio(struct amdgpu_device *adev)
@@ -5065,6 +5091,7 @@ static int amdgpu_device_suspend_display_audio(struct amdgpu_device *adev)
if (expires < ktime_get_mono_fast_ns()) {
dev_warn(adev->dev, "failed to suspend display audio\n");
+ pci_dev_put(p);
/* TODO: abort the succeeding gpu reset? */
return -ETIMEDOUT;
}
@@ -5072,97 +5099,10 @@ static int amdgpu_device_suspend_display_audio(struct amdgpu_device *adev)
pm_runtime_disable(&(p->dev));
+ pci_dev_put(p);
return 0;
}
-static void amdgpu_device_recheck_guilty_jobs(
- struct amdgpu_device *adev, struct list_head *device_list_handle,
- struct amdgpu_reset_context *reset_context)
-{
- int i, r = 0;
-
- for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
- struct amdgpu_ring *ring = adev->rings[i];
- int ret = 0;
- struct drm_sched_job *s_job;
-
- if (!ring || !ring->sched.thread)
- continue;
-
- s_job = list_first_entry_or_null(&ring->sched.pending_list,
- struct drm_sched_job, list);
- if (s_job == NULL)
- continue;
-
- /* clear job's guilty and depend the folowing step to decide the real one */
- drm_sched_reset_karma(s_job);
- drm_sched_resubmit_jobs_ext(&ring->sched, 1);
-
- if (!s_job->s_fence->parent) {
- DRM_WARN("Failed to get a HW fence for job!");
- continue;
- }
-
- ret = dma_fence_wait_timeout(s_job->s_fence->parent, false, ring->sched.timeout);
- if (ret == 0) { /* timeout */
- DRM_ERROR("Found the real bad job! ring:%s, job_id:%llx\n",
- ring->sched.name, s_job->id);
-
-
- amdgpu_fence_driver_isr_toggle(adev, true);
-
- /* Clear this failed job from fence array */
- amdgpu_fence_driver_clear_job_fences(ring);
-
- amdgpu_fence_driver_isr_toggle(adev, false);
-
- /* Since the job won't signal and we go for
- * another resubmit drop this parent pointer
- */
- dma_fence_put(s_job->s_fence->parent);
- s_job->s_fence->parent = NULL;
-
- /* set guilty */
- drm_sched_increase_karma(s_job);
- amdgpu_reset_prepare_hwcontext(adev, reset_context);
-retry:
- /* do hw reset */
- if (amdgpu_sriov_vf(adev)) {
- amdgpu_virt_fini_data_exchange(adev);
- r = amdgpu_device_reset_sriov(adev, false);
- if (r)
- adev->asic_reset_res = r;
- } else {
- clear_bit(AMDGPU_SKIP_HW_RESET,
- &reset_context->flags);
- r = amdgpu_do_asic_reset(device_list_handle,
- reset_context);
- if (r && r == -EAGAIN)
- goto retry;
- }
-
- /*
- * add reset counter so that the following
- * resubmitted job could flush vmid
- */
- atomic_inc(&adev->gpu_reset_counter);
- continue;
- }
-
- /* got the hw fence, signal finished fence */
- atomic_dec(ring->sched.score);
- dma_fence_get(&s_job->s_fence->finished);
- dma_fence_signal(&s_job->s_fence->finished);
- dma_fence_put(&s_job->s_fence->finished);
-
- /* remove node from list and free the job */
- spin_lock(&ring->sched.job_list_lock);
- list_del_init(&s_job->list);
- spin_unlock(&ring->sched.job_list_lock);
- ring->sched.ops->free_job(s_job);
- }
-}
-
static inline void amdgpu_device_stop_pending_resets(struct amdgpu_device *adev)
{
struct amdgpu_ras *con = amdgpu_ras_get_context(adev);
@@ -5183,7 +5123,6 @@ static inline void amdgpu_device_stop_pending_resets(struct amdgpu_device *adev)
}
-
/**
* amdgpu_device_gpu_recover - reset the asic and recover scheduler
*
@@ -5206,7 +5145,6 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
int i, r = 0;
bool need_emergency_restart = false;
bool audio_suspended = false;
- int tmp_vram_lost_counter;
bool gpu_reset_for_dev_remove = false;
gpu_reset_for_dev_remove =
@@ -5352,7 +5290,6 @@ retry: /* Rest of adevs pre asic reset from XGMI hive. */
amdgpu_device_stop_pending_resets(tmp_adev);
}
- tmp_vram_lost_counter = atomic_read(&((adev)->vram_lost_counter));
/* Actual ASIC resets if needed.*/
/* Host driver will handle XGMI hive reset for SRIOV */
if (amdgpu_sriov_vf(adev)) {
@@ -5377,29 +5314,13 @@ skip_hw_reset:
/* Post ASIC reset for all devs .*/
list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
- /*
- * Sometimes a later bad compute job can block a good gfx job as gfx
- * and compute ring share internal GC HW mutually. We add an additional
- * guilty jobs recheck step to find the real guilty job, it synchronously
- * submits and pends for the first job being signaled. If it gets timeout,
- * we identify it as a real guilty job.
- */
- if (amdgpu_gpu_recovery == 2 &&
- !(tmp_vram_lost_counter < atomic_read(&adev->vram_lost_counter)))
- amdgpu_device_recheck_guilty_jobs(
- tmp_adev, device_list_handle, reset_context);
-
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
struct amdgpu_ring *ring = tmp_adev->rings[i];
if (!ring || !ring->sched.thread)
continue;
- /* No point to resubmit jobs if we didn't HW reset*/
- if (!tmp_adev->asic_reset_res && !job_signaled)
- drm_sched_resubmit_jobs(&ring->sched);
-
- drm_sched_start(&ring->sched, !tmp_adev->asic_reset_res);
+ drm_sched_start(&ring->sched, true);
}
if (adev->enable_mes && adev->ip_versions[GC_HWIP][0] != IP_VERSION(11, 0, 3))
@@ -5441,6 +5362,8 @@ skip_sched_resume:
amdgpu_device_resume_display_audio(tmp_adev);
amdgpu_device_unset_mp1_state(tmp_adev);
+
+ amdgpu_ras_set_error_query_ready(tmp_adev, true);
}
recover_end:
@@ -5852,8 +5775,6 @@ void amdgpu_pci_resume(struct pci_dev *pdev)
if (!ring || !ring->sched.thread)
continue;
-
- drm_sched_resubmit_jobs(&ring->sched);
drm_sched_start(&ring->sched, true);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
index 3993e6134914..1bbd56029a4f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
@@ -305,8 +305,13 @@ static int amdgpu_discovery_init(struct amdgpu_device *adev)
goto out;
}
- if (!amdgpu_discovery_verify_binary_signature(adev->mman.discovery_bin)) {
- dev_warn(adev->dev, "get invalid ip discovery binary signature from vram\n");
+ 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 */
r = amdgpu_discovery_read_binary_from_file(adev, adev->mman.discovery_bin);
if (r) {
@@ -1507,6 +1512,7 @@ static int amdgpu_discovery_set_common_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 0, 1):
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
+ case IP_VERSION(11, 0, 4):
amdgpu_device_ip_block_add(adev, &soc21_common_ip_block);
break;
default:
@@ -1551,6 +1557,7 @@ static int amdgpu_discovery_set_gmc_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 0, 1):
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
+ case IP_VERSION(11, 0, 4):
amdgpu_device_ip_block_add(adev, &gmc_v11_0_ip_block);
break;
default:
@@ -1636,6 +1643,7 @@ static int amdgpu_discovery_set_psp_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(13, 0, 7):
case IP_VERSION(13, 0, 8):
case IP_VERSION(13, 0, 10):
+ case IP_VERSION(13, 0, 11):
amdgpu_device_ip_block_add(adev, &psp_v13_0_ip_block);
break;
case IP_VERSION(13, 0, 4):
@@ -1686,6 +1694,7 @@ static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(13, 0, 7):
case IP_VERSION(13, 0, 8):
case IP_VERSION(13, 0, 10):
+ case IP_VERSION(13, 0, 11):
amdgpu_device_ip_block_add(adev, &smu_v13_0_ip_block);
break;
default:
@@ -1697,9 +1706,17 @@ static int amdgpu_discovery_set_smu_ip_blocks(struct amdgpu_device *adev)
return 0;
}
+#if defined(CONFIG_DRM_AMD_DC)
+static void amdgpu_discovery_set_sriov_display(struct amdgpu_device *adev)
+{
+ amdgpu_device_set_sriov_virtual_display(adev);
+ amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
+}
+#endif
+
static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
{
- if (adev->enable_virtual_display || amdgpu_sriov_vf(adev)) {
+ if (adev->enable_virtual_display) {
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
return 0;
}
@@ -1727,7 +1744,10 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(3, 1, 6):
case IP_VERSION(3, 2, 0):
case IP_VERSION(3, 2, 1):
- amdgpu_device_ip_block_add(adev, &dm_ip_block);
+ if (amdgpu_sriov_vf(adev))
+ amdgpu_discovery_set_sriov_display(adev);
+ else
+ amdgpu_device_ip_block_add(adev, &dm_ip_block);
break;
default:
dev_err(adev->dev,
@@ -1740,7 +1760,10 @@ static int amdgpu_discovery_set_display_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(12, 0, 0):
case IP_VERSION(12, 0, 1):
case IP_VERSION(12, 1, 0):
- amdgpu_device_ip_block_add(adev, &dm_ip_block);
+ if (amdgpu_sriov_vf(adev))
+ amdgpu_discovery_set_sriov_display(adev);
+ else
+ amdgpu_device_ip_block_add(adev, &dm_ip_block);
break;
default:
dev_err(adev->dev,
@@ -1785,6 +1808,7 @@ static int amdgpu_discovery_set_gc_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 0, 1):
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
+ case IP_VERSION(11, 0, 4):
amdgpu_device_ip_block_add(adev, &gfx_v11_0_ip_block);
break;
default:
@@ -1948,6 +1972,7 @@ static int amdgpu_discovery_set_mes_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(11, 0, 1):
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
+ case IP_VERSION(11, 0, 4):
amdgpu_device_ip_block_add(adev, &mes_v11_0_ip_block);
adev->enable_mes = true;
adev->enable_mes_kiq = true;
@@ -2161,6 +2186,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
break;
case IP_VERSION(10, 3, 1):
adev->family = AMDGPU_FAMILY_VGH;
+ adev->apu_flags |= AMD_APU_IS_VANGOGH;
break;
case IP_VERSION(10, 3, 3):
adev->family = AMDGPU_FAMILY_YC;
@@ -2177,6 +2203,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
adev->family = AMDGPU_FAMILY_GC_11_0_0;
break;
case IP_VERSION(11, 0, 1):
+ case IP_VERSION(11, 0, 4):
adev->family = AMDGPU_FAMILY_GC_11_0_1;
break;
default:
@@ -2194,6 +2221,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
case IP_VERSION(10, 3, 6):
case IP_VERSION(10, 3, 7):
case IP_VERSION(11, 0, 1):
+ case IP_VERSION(11, 0, 4):
adev->flags |= AMD_IS_APU;
break;
default:
@@ -2250,6 +2278,7 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev)
adev->nbio.hdp_flush_reg = &nbio_v4_3_hdp_flush_reg;
break;
case IP_VERSION(7, 7, 0):
+ case IP_VERSION(7, 7, 1):
adev->nbio.funcs = &nbio_v7_7_funcs;
adev->nbio.hdp_flush_reg = &nbio_v7_7_hdp_flush_reg;
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
index 1a06b8d724f3..b22471b3bd63 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
@@ -39,11 +39,46 @@
#include <linux/pm_runtime.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_edid.h>
-#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_fb_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_vblank.h>
+/**
+ * amdgpu_display_hotplug_work_func - work handler for display hotplug event
+ *
+ * @work: work struct pointer
+ *
+ * This is the hotplug event work handler (all ASICs).
+ * The work gets scheduled from the IRQ handler if there
+ * was a hotplug interrupt. It walks through the connector table
+ * and calls hotplug handler for each connector. After this, it sends
+ * a DRM hotplug event to alert userspace.
+ *
+ * This design approach is required in order to defer hotplug event handling
+ * from the IRQ handler to a work handler because hotplug handler has to use
+ * mutexes which cannot be locked in an IRQ handler (since &mutex_lock may
+ * sleep).
+ */
+void amdgpu_display_hotplug_work_func(struct work_struct *work)
+{
+ struct amdgpu_device *adev = container_of(work, struct amdgpu_device,
+ hotplug_work);
+ struct drm_device *dev = adev_to_drm(adev);
+ struct drm_mode_config *mode_config = &dev->mode_config;
+ struct drm_connector *connector;
+ struct drm_connector_list_iter iter;
+
+ mutex_lock(&mode_config->mutex);
+ drm_connector_list_iter_begin(dev, &iter);
+ drm_for_each_connector_iter(connector, &iter)
+ amdgpu_connector_hotplug(connector);
+ drm_connector_list_iter_end(&iter);
+ mutex_unlock(&mode_config->mutex);
+ /* Just fire off a uevent and let userspace tell us what to do */
+ drm_helper_hpd_irq_event(dev);
+}
+
static int amdgpu_display_framebuffer_init(struct drm_device *dev,
struct amdgpu_framebuffer *rfb,
const struct drm_mode_fb_cmd2 *mode_cmd,
@@ -514,7 +549,7 @@ uint32_t amdgpu_display_supported_domains(struct amdgpu_device *adev,
*/
if ((bo_flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC) &&
amdgpu_bo_support_uswc(bo_flags) &&
- amdgpu_device_asic_has_dc_support(adev->asic_type) &&
+ adev->dc_enabled &&
adev->mode_info.gpu_vm_support)
domain |= AMDGPU_GEM_DOMAIN_GTT;
#endif
@@ -1214,7 +1249,6 @@ amdgpu_display_user_framebuffer_create(struct drm_device *dev,
const struct drm_mode_config_funcs amdgpu_mode_funcs = {
.fb_create = amdgpu_display_user_framebuffer_create,
- .output_poll_changed = drm_fb_helper_output_poll_changed,
};
static const struct drm_prop_enum_list amdgpu_underscan_enum_list[] =
@@ -1281,7 +1315,7 @@ int amdgpu_display_modeset_create_props(struct amdgpu_device *adev)
"dither",
amdgpu_dither_enum_list, sz);
- if (amdgpu_device_has_dc_support(adev)) {
+ if (adev->dc_enabled) {
adev->mode_info.abm_level_property =
drm_property_create_range(adev_to_drm(adev), 0,
"abm level", 0, 4);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h
index 560352f7c317..9d19940f73c8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.h
@@ -35,6 +35,7 @@
#define amdgpu_display_add_encoder(adev, e, s, c) (adev)->mode_info.funcs->add_encoder((adev), (e), (s), (c))
#define amdgpu_display_add_connector(adev, ci, sd, ct, ib, coi, h, r) (adev)->mode_info.funcs->add_connector((adev), (ci), (sd), (ct), (ib), (coi), (h), (r))
+void amdgpu_display_hotplug_work_func(struct work_struct *work);
void amdgpu_display_update_priority(struct amdgpu_device *adev);
uint32_t amdgpu_display_supported_domains(struct amdgpu_device *adev,
uint64_t bo_flags);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
index 7bd8e33b14be..271e30e34d93 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c
@@ -328,7 +328,9 @@ amdgpu_dma_buf_create_obj(struct drm_device *dev, struct dma_buf *dma_buf)
if (dma_buf->ops == &amdgpu_dmabuf_ops) {
struct amdgpu_bo *other = gem_to_amdgpu_bo(dma_buf->priv);
- flags |= other->flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC;
+ flags |= other->flags & (AMDGPU_GEM_CREATE_CPU_GTT_USWC |
+ AMDGPU_GEM_CREATE_COHERENT |
+ AMDGPU_GEM_CREATE_UNCACHED);
}
ret = amdgpu_gem_object_create(adev, dma_buf->size, PAGE_SIZE,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index bf2d50c8c92a..7383272c6a3a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -25,6 +25,7 @@
#include <drm/amdgpu_drm.h>
#include <drm/drm_aperture.h>
#include <drm/drm_drv.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem.h>
#include <drm/drm_vblank.h>
#include <drm/drm_managed.h>
@@ -230,17 +231,18 @@ module_param_named(vis_vramlimit, amdgpu_vis_vram_limit, int, 0444);
/**
* DOC: gartsize (uint)
- * Restrict the size of GART in Mib (32, 64, etc.) for testing. The default is -1 (The size depends on asic).
+ * Restrict the size of GART (for kernel use) in Mib (32, 64, etc.) for testing.
+ * The default is -1 (The size depends on asic).
*/
-MODULE_PARM_DESC(gartsize, "Size of GART to setup in megabytes (32, 64, etc., -1=auto)");
+MODULE_PARM_DESC(gartsize, "Size of kernel GART to setup in megabytes (32, 64, etc., -1=auto)");
module_param_named(gartsize, amdgpu_gart_size, uint, 0600);
/**
* DOC: gttsize (int)
- * Restrict the size of GTT domain in MiB for testing. The default is -1 (It's VRAM size if 3GB < VRAM < 3/4 RAM,
- * otherwise 3/4 RAM size).
+ * Restrict the size of GTT domain (for userspace use) in MiB for testing.
+ * The default is -1 (Use 1/2 RAM, minimum value is 3GB).
*/
-MODULE_PARM_DESC(gttsize, "Size of the GTT domain in megabytes (-1 = auto)");
+MODULE_PARM_DESC(gttsize, "Size of the GTT userspace domain in megabytes (-1 = auto)");
module_param_named(gttsize, amdgpu_gtt_size, int, 0600);
/**
@@ -533,7 +535,7 @@ module_param_named(compute_multipipe, amdgpu_compute_multipipe, int, 0444);
* DOC: gpu_recovery (int)
* Set to enable GPU recovery mechanism (1 = enable, 0 = disable). The default is -1 (auto, disabled except SRIOV).
*/
-MODULE_PARM_DESC(gpu_recovery, "Enable GPU recovery mechanism, (2 = advanced tdr mode, 1 = enable, 0 = disable, -1 = auto)");
+MODULE_PARM_DESC(gpu_recovery, "Enable GPU recovery mechanism, (1 = enable, 0 = disable, -1 = auto)");
module_param_named(gpu_recovery, amdgpu_gpu_recovery, int, 0444);
/**
@@ -1924,9 +1926,6 @@ static const struct pci_device_id pciidlist[] = {
{0x1002, 0x73AF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
{0x1002, 0x73BF, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SIENNA_CICHLID},
- /* Van Gogh */
- {0x1002, 0x163F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VANGOGH|AMD_IS_APU},
-
/* Yellow Carp */
{0x1002, 0x164D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_YELLOW_CARP|AMD_IS_APU},
{0x1002, 0x1681, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_YELLOW_CARP|AMD_IS_APU},
@@ -2471,7 +2470,7 @@ static int amdgpu_runtime_idle_check_display(struct device *dev)
if (ret)
return ret;
- if (amdgpu_device_has_dc_support(adev)) {
+ if (adev->dc_enabled) {
struct drm_crtc *crtc;
drm_for_each_crtc(crtc, drm_dev) {
@@ -2572,6 +2571,8 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
amdgpu_device_baco_enter(drm_dev);
}
+ dev_dbg(&pdev->dev, "asic/device is runtime suspended\n");
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
index 4d9eb0137f8c..7d2a908438e9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eeprom.c
@@ -79,13 +79,15 @@
* That is, for an I2C EEPROM driver everything is controlled by
* the "eeprom_addr".
*
+ * See also top of amdgpu_ras_eeprom.c.
+ *
* P.S. If you need to write, lock and read the Identification Page,
* (M24M02-DR device only, which we do not use), change the "7" to
* "0xF" in the macro below, and let the client set bit 20 to 1 in
* "eeprom_addr", and set A10 to 0 to write into it, and A10 and A1 to
* 1 to lock it permanently.
*/
-#define MAKE_I2C_ADDR(_aa) ((0xA << 3) | (((_aa) >> 16) & 7))
+#define MAKE_I2C_ADDR(_aa) ((0xA << 3) | (((_aa) >> 16) & 0xF))
static int __amdgpu_eeprom_xfer(struct i2c_adapter *i2c_adap, u32 eeprom_addr,
u8 *eeprom_buf, u16 buf_size, bool read)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
index d0d99ed607dd..00444203220d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
@@ -55,6 +55,7 @@ struct amdgpu_fence {
/* RB, DMA, etc. */
struct amdgpu_ring *ring;
+ ktime_t start_timestamp;
};
static struct kmem_cache *amdgpu_fence_slab;
@@ -199,6 +200,8 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f, struct amd
}
}
+ to_amdgpu_fence(fence)->start_timestamp = ktime_get();
+
/* This function can't be called concurrently anyway, otherwise
* emitting the fence would mess up the hardware ring buffer.
*/
@@ -407,6 +410,57 @@ unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring)
}
/**
+ * amdgpu_fence_last_unsignaled_time_us - the time fence emitted until now
+ * @ring: ring the fence is associated with
+ *
+ * Find the earliest fence unsignaled until now, calculate the time delta
+ * between the time fence emitted and now.
+ */
+u64 amdgpu_fence_last_unsignaled_time_us(struct amdgpu_ring *ring)
+{
+ struct amdgpu_fence_driver *drv = &ring->fence_drv;
+ struct dma_fence *fence;
+ uint32_t last_seq, sync_seq;
+
+ last_seq = atomic_read(&ring->fence_drv.last_seq);
+ sync_seq = READ_ONCE(ring->fence_drv.sync_seq);
+ if (last_seq == sync_seq)
+ return 0;
+
+ ++last_seq;
+ last_seq &= drv->num_fences_mask;
+ fence = drv->fences[last_seq];
+ if (!fence)
+ return 0;
+
+ return ktime_us_delta(ktime_get(),
+ to_amdgpu_fence(fence)->start_timestamp);
+}
+
+/**
+ * amdgpu_fence_update_start_timestamp - update the timestamp of the fence
+ * @ring: ring the fence is associated with
+ * @seq: the fence seq number to update.
+ * @timestamp: the start timestamp to update.
+ *
+ * The function called at the time the fence and related ib is about to
+ * resubmit to gpu in MCBP scenario. Thus we do not consider race condition
+ * with amdgpu_fence_process to modify the same fence.
+ */
+void amdgpu_fence_update_start_timestamp(struct amdgpu_ring *ring, uint32_t seq, ktime_t timestamp)
+{
+ struct amdgpu_fence_driver *drv = &ring->fence_drv;
+ struct dma_fence *fence;
+
+ seq &= drv->num_fences_mask;
+ fence = drv->fences[seq];
+ if (!fence)
+ return;
+
+ to_amdgpu_fence(fence)->start_timestamp = timestamp;
+}
+
+/**
* amdgpu_fence_driver_start_ring - make the fence driver
* ready for use on the requested ring.
*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
index e325150879df..2c38ac7bc643 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fru_eeprom.c
@@ -29,9 +29,10 @@
#include "amdgpu_fru_eeprom.h"
#include "amdgpu_eeprom.h"
-#define FRU_EEPROM_MADDR 0x60000
+#define FRU_EEPROM_MADDR_6 0x60000
+#define FRU_EEPROM_MADDR_8 0x80000
-static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
+static bool is_fru_eeprom_supported(struct amdgpu_device *adev, u32 *fru_addr)
{
/* Only server cards have the FRU EEPROM
* TODO: See if we can figure this out dynamically instead of
@@ -45,6 +46,11 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
if (amdgpu_sriov_vf(adev))
return false;
+ /* The default I2C EEPROM address of the FRU.
+ */
+ if (fru_addr)
+ *fru_addr = FRU_EEPROM_MADDR_8;
+
/* VBIOS is of the format ###-DXXXYYYY-##. For SKU identification,
* we can use just the "DXXX" portion. If there were more models, we
* could convert the 3 characters to a hex integer and use a switch
@@ -57,21 +63,29 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
if (strnstr(atom_ctx->vbios_version, "D161",
sizeof(atom_ctx->vbios_version)) ||
strnstr(atom_ctx->vbios_version, "D163",
- sizeof(atom_ctx->vbios_version)))
+ sizeof(atom_ctx->vbios_version))) {
+ *fru_addr = FRU_EEPROM_MADDR_6;
return true;
- else
+ } else {
return false;
+ }
case CHIP_ALDEBARAN:
- /* All Aldebaran SKUs have the FRU */
+ /* All Aldebaran SKUs have an FRU */
+ if (!strnstr(atom_ctx->vbios_version, "D673",
+ sizeof(atom_ctx->vbios_version)))
+ if (fru_addr)
+ *fru_addr = FRU_EEPROM_MADDR_6;
return true;
case CHIP_SIENNA_CICHLID:
if (strnstr(atom_ctx->vbios_version, "D603",
- sizeof(atom_ctx->vbios_version))) {
+ sizeof(atom_ctx->vbios_version))) {
if (strnstr(atom_ctx->vbios_version, "D603GLXE",
- sizeof(atom_ctx->vbios_version)))
+ sizeof(atom_ctx->vbios_version))) {
return false;
- else
+ } else {
+ *fru_addr = FRU_EEPROM_MADDR_6;
return true;
+ }
} else {
return false;
}
@@ -80,41 +94,14 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
}
}
-static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
- unsigned char *buf, size_t buf_size)
-{
- int ret;
- u8 size;
-
- ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr, buf, 1);
- if (ret < 1) {
- DRM_WARN("FRU: Failed to get size field");
- return ret;
- }
-
- /* The size returned by the i2c requires subtraction of 0xC0 since the
- * size apparently always reports as 0xC0+actual size.
- */
- size = buf[0] & 0x3F;
- size = min_t(size_t, size, buf_size);
-
- ret = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addrptr + 1,
- buf, size);
- if (ret < 1) {
- DRM_WARN("FRU: Failed to get data field");
- return ret;
- }
-
- return size;
-}
-
int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
{
- unsigned char buf[AMDGPU_PRODUCT_NAME_LEN];
- u32 addrptr;
+ unsigned char buf[8], *pia;
+ u32 addr, fru_addr;
int size, len;
+ u8 csum;
- if (!is_fru_eeprom_supported(adev))
+ if (!is_fru_eeprom_supported(adev, &fru_addr))
return 0;
/* If algo exists, it means that the i2c_adapter's initialized */
@@ -123,88 +110,102 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
return -ENODEV;
}
- /* There's a lot of repetition here. This is due to the FRU having
- * variable-length fields. To get the information, we have to find the
- * size of each field, and then keep reading along and reading along
- * until we get all of the data that we want. We use addrptr to track
- * the address as we go
- */
-
- /* The first fields are all of size 1-byte, from 0-7 are offsets that
- * contain information that isn't useful to us.
- * Bytes 8-a are all 1-byte and refer to the size of the entire struct,
- * and the language field, so just start from 0xb, manufacturer size
- */
- addrptr = FRU_EEPROM_MADDR + 0xb;
- size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf));
- if (size < 1) {
- DRM_ERROR("Failed to read FRU Manufacturer, ret:%d", size);
- return -EINVAL;
+ /* Read the IPMI Common header */
+ len = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, fru_addr, buf,
+ sizeof(buf));
+ if (len != 8) {
+ DRM_ERROR("Couldn't read the IPMI Common Header: %d", len);
+ return len < 0 ? len : -EIO;
}
- /* Increment the addrptr by the size of the field, and 1 due to the
- * size field being 1 byte. This pattern continues below.
- */
- addrptr += size + 1;
- size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf));
- if (size < 1) {
- DRM_ERROR("Failed to read FRU product name, ret:%d", size);
- return -EINVAL;
+ if (buf[0] != 1) {
+ DRM_ERROR("Bad IPMI Common Header version: 0x%02x", buf[0]);
+ return -EIO;
}
- len = size;
- if (len >= AMDGPU_PRODUCT_NAME_LEN) {
- DRM_WARN("FRU Product Name is larger than %d characters. This is likely a mistake",
- AMDGPU_PRODUCT_NAME_LEN);
- len = AMDGPU_PRODUCT_NAME_LEN - 1;
- }
- memcpy(adev->product_name, buf, len);
- adev->product_name[len] = '\0';
-
- addrptr += size + 1;
- size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf));
- if (size < 1) {
- DRM_ERROR("Failed to read FRU product number, ret:%d", size);
- return -EINVAL;
+ for (csum = 0; len > 0; len--)
+ csum += buf[len - 1];
+ if (csum) {
+ DRM_ERROR("Bad IPMI Common Header checksum: 0x%02x", csum);
+ return -EIO;
}
- len = size;
- /* Product number should only be 16 characters. Any more,
- * and something could be wrong. Cap it at 16 to be safe
- */
- if (len >= sizeof(adev->product_number)) {
- DRM_WARN("FRU Product Number is larger than 16 characters. This is likely a mistake");
- len = sizeof(adev->product_number) - 1;
- }
- memcpy(adev->product_number, buf, len);
- adev->product_number[len] = '\0';
+ /* Get the offset to the Product Info Area (PIA). */
+ addr = buf[4] * 8;
+ if (!addr)
+ return 0;
- addrptr += size + 1;
- size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf));
+ /* Get the absolute address to the PIA. */
+ addr += fru_addr;
- if (size < 1) {
- DRM_ERROR("Failed to read FRU product version, ret:%d", size);
- return -EINVAL;
+ /* Read the header of the PIA. */
+ len = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addr, buf, 3);
+ if (len != 3) {
+ DRM_ERROR("Couldn't read the Product Info Area header: %d", len);
+ return len < 0 ? len : -EIO;
}
- addrptr += size + 1;
- size = amdgpu_fru_read_eeprom(adev, addrptr, buf, sizeof(buf));
+ if (buf[0] != 1) {
+ DRM_ERROR("Bad IPMI Product Info Area version: 0x%02x", buf[0]);
+ return -EIO;
+ }
- if (size < 1) {
- DRM_ERROR("Failed to read FRU serial number, ret:%d", size);
- return -EINVAL;
+ size = buf[1] * 8;
+ pia = kzalloc(size, GFP_KERNEL);
+ if (!pia)
+ return -ENOMEM;
+
+ /* Read the whole PIA. */
+ len = amdgpu_eeprom_read(adev->pm.fru_eeprom_i2c_bus, addr, pia, size);
+ if (len != size) {
+ kfree(pia);
+ DRM_ERROR("Couldn't read the Product Info Area: %d", len);
+ return len < 0 ? len : -EIO;
}
- len = size;
- /* Serial number should only be 16 characters. Any more,
- * and something could be wrong. Cap it at 16 to be safe
- */
- if (len >= sizeof(adev->serial)) {
- DRM_WARN("FRU Serial Number is larger than 16 characters. This is likely a mistake");
- len = sizeof(adev->serial) - 1;
+ for (csum = 0; size > 0; size--)
+ csum += pia[size - 1];
+ if (csum) {
+ DRM_ERROR("Bad Product Info Area checksum: 0x%02x", csum);
+ return -EIO;
}
- memcpy(adev->serial, buf, len);
- adev->serial[len] = '\0';
+ /* Now extract useful information from the PIA.
+ *
+ * Skip the Manufacturer Name at [3] and go directly to
+ * the Product Name field.
+ */
+ addr = 3 + 1 + (pia[3] & 0x3F);
+ if (addr + 1 >= len)
+ goto Out;
+ memcpy(adev->product_name, pia + addr + 1,
+ min_t(size_t,
+ sizeof(adev->product_name),
+ pia[addr] & 0x3F));
+ adev->product_name[sizeof(adev->product_name) - 1] = '\0';
+
+ /* Go to the Product Part/Model Number field. */
+ addr += 1 + (pia[addr] & 0x3F);
+ if (addr + 1 >= len)
+ goto Out;
+ memcpy(adev->product_number, pia + addr + 1,
+ min_t(size_t,
+ sizeof(adev->product_number),
+ pia[addr] & 0x3F));
+ adev->product_number[sizeof(adev->product_number) - 1] = '\0';
+
+ /* Go to the Product Version field. */
+ addr += 1 + (pia[addr] & 0x3F);
+
+ /* Go to the Product Serial Number field. */
+ addr += 1 + (pia[addr] & 0x3F);
+ if (addr + 1 >= len)
+ goto Out;
+ memcpy(adev->serial, pia + addr + 1, min_t(size_t,
+ sizeof(adev->serial),
+ pia[addr] & 0x3F));
+ adev->serial[sizeof(adev->serial) - 1] = '\0';
+Out:
+ kfree(pia);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index 91571b1324f2..62e98f1ad770 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -38,6 +38,7 @@
#include "amdgpu.h"
#include "amdgpu_display.h"
#include "amdgpu_dma_buf.h"
+#include "amdgpu_hmm.h"
#include "amdgpu_xgmi.h"
static const struct drm_gem_object_funcs amdgpu_gem_object_funcs;
@@ -87,7 +88,7 @@ static void amdgpu_gem_object_free(struct drm_gem_object *gobj)
struct amdgpu_bo *robj = gem_to_amdgpu_bo(gobj);
if (robj) {
- amdgpu_mn_unregister(robj);
+ amdgpu_hmm_unregister(robj);
amdgpu_bo_unref(&robj);
}
}
@@ -112,7 +113,7 @@ int amdgpu_gem_object_create(struct amdgpu_device *adev, unsigned long size,
bp.resv = resv;
bp.preferred_domain = initial_domain;
bp.flags = flags;
- bp.domain = initial_domain;
+ bp.domain = initial_domain | AMDGPU_GEM_DOMAIN_CPU;
bp.bo_ptr_size = sizeof(struct amdgpu_bo);
r = amdgpu_bo_create_user(adev, &bp, &ubo);
@@ -331,20 +332,10 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data,
}
initial_domain = (u32)(0xffffffff & args->in.domains);
-retry:
r = amdgpu_gem_object_create(adev, size, args->in.alignment,
- initial_domain,
- flags, ttm_bo_type_device, resv, &gobj);
+ initial_domain, flags, ttm_bo_type_device,
+ resv, &gobj);
if (r && r != -ERESTARTSYS) {
- if (flags & AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED) {
- flags &= ~AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
- goto retry;
- }
-
- if (initial_domain == AMDGPU_GEM_DOMAIN_VRAM) {
- initial_domain |= AMDGPU_GEM_DOMAIN_GTT;
- goto retry;
- }
DRM_DEBUG("Failed to allocate GEM object (%llu, %d, %llu, %d)\n",
size, initial_domain, args->in.alignment, r);
}
@@ -414,7 +405,7 @@ int amdgpu_gem_userptr_ioctl(struct drm_device *dev, void *data,
if (r)
goto release_object;
- r = amdgpu_mn_register(bo, args->addr);
+ r = amdgpu_hmm_register(bo, args->addr);
if (r)
goto release_object;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
index 9546adc8a76f..23692e5d4d13 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -583,10 +583,14 @@ 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)
- delay = GFX_OFF_NO_DELAY;
- schedule_delayed_work(&adev->gfx.gfx_off_delay_work,
+ 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,
delay);
+ }
}
} else {
if (adev->gfx.gfx_off_req_count == 0) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
index 832b3807f1d6..b3df4787877e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h
@@ -33,6 +33,7 @@
#include "amdgpu_imu.h"
#include "soc15.h"
#include "amdgpu_ras.h"
+#include "amdgpu_ring_mux.h"
/* GFX current status */
#define AMDGPU_GFX_NORMAL_MODE 0x00000000L
@@ -352,6 +353,9 @@ struct amdgpu_gfx {
struct amdgpu_gfx_ras *ras;
bool is_poweron;
+
+ struct amdgpu_ring sw_gfx_ring[AMDGPU_MAX_SW_GFX_RINGS];
+ struct amdgpu_ring_mux muxer;
};
#define amdgpu_gfx_get_gpu_clock_counter(adev) (adev)->gfx.funcs->get_gpu_clock_counter((adev))
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
index 28612e56d0d4..02a4c93673ce 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
@@ -548,6 +548,8 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev)
case IP_VERSION(10, 3, 1):
/* YELLOW_CARP*/
case IP_VERSION(10, 3, 3):
+ case IP_VERSION(11, 0, 1):
+ case IP_VERSION(11, 0, 4):
/* Don't enable it by default yet.
*/
if (amdgpu_tmz < 1) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
index 1f3302aebeff..44367f03316f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
@@ -144,7 +144,7 @@ static int amdgpu_gtt_mgr_new(struct ttm_resource_manager *man,
node->base.start = node->mm_nodes[0].start;
} else {
node->mm_nodes[0].start = 0;
- node->mm_nodes[0].size = node->base.num_pages;
+ node->mm_nodes[0].size = PFN_UP(node->base.size);
node->base.start = AMDGPU_BO_INVALID_OFFSET;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c
index b86c0b8252a5..65715cb395d8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.c
@@ -49,9 +49,12 @@
#include "amdgpu.h"
#include "amdgpu_amdkfd.h"
+#include "amdgpu_hmm.h"
+
+#define MAX_WALK_BYTE (2UL << 30)
/**
- * amdgpu_mn_invalidate_gfx - callback to notify about mm change
+ * amdgpu_hmm_invalidate_gfx - callback to notify about mm change
*
* @mni: the range (mm) is about to update
* @range: details on the invalidation
@@ -60,9 +63,9 @@
* Block for operations on BOs to finish and mark pages as accessed and
* potentially dirty.
*/
-static bool amdgpu_mn_invalidate_gfx(struct mmu_interval_notifier *mni,
- const struct mmu_notifier_range *range,
- unsigned long cur_seq)
+static bool amdgpu_hmm_invalidate_gfx(struct mmu_interval_notifier *mni,
+ const struct mmu_notifier_range *range,
+ unsigned long cur_seq)
{
struct amdgpu_bo *bo = container_of(mni, struct amdgpu_bo, notifier);
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
@@ -83,12 +86,12 @@ static bool amdgpu_mn_invalidate_gfx(struct mmu_interval_notifier *mni,
return true;
}
-static const struct mmu_interval_notifier_ops amdgpu_mn_gfx_ops = {
- .invalidate = amdgpu_mn_invalidate_gfx,
+static const struct mmu_interval_notifier_ops amdgpu_hmm_gfx_ops = {
+ .invalidate = amdgpu_hmm_invalidate_gfx,
};
/**
- * amdgpu_mn_invalidate_hsa - callback to notify about mm change
+ * amdgpu_hmm_invalidate_hsa - callback to notify about mm change
*
* @mni: the range (mm) is about to update
* @range: details on the invalidation
@@ -97,9 +100,9 @@ static const struct mmu_interval_notifier_ops amdgpu_mn_gfx_ops = {
* We temporarily evict the BO attached to this range. This necessitates
* evicting all user-mode queues of the process.
*/
-static bool amdgpu_mn_invalidate_hsa(struct mmu_interval_notifier *mni,
- const struct mmu_notifier_range *range,
- unsigned long cur_seq)
+static bool amdgpu_hmm_invalidate_hsa(struct mmu_interval_notifier *mni,
+ const struct mmu_notifier_range *range,
+ unsigned long cur_seq)
{
struct amdgpu_bo *bo = container_of(mni, struct amdgpu_bo, notifier);
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
@@ -117,12 +120,12 @@ static bool amdgpu_mn_invalidate_hsa(struct mmu_interval_notifier *mni,
return true;
}
-static const struct mmu_interval_notifier_ops amdgpu_mn_hsa_ops = {
- .invalidate = amdgpu_mn_invalidate_hsa,
+static const struct mmu_interval_notifier_ops amdgpu_hmm_hsa_ops = {
+ .invalidate = amdgpu_hmm_invalidate_hsa,
};
/**
- * amdgpu_mn_register - register a BO for notifier updates
+ * amdgpu_hmm_register - register a BO for notifier updates
*
* @bo: amdgpu buffer object
* @addr: userptr addr we should monitor
@@ -130,25 +133,25 @@ static const struct mmu_interval_notifier_ops amdgpu_mn_hsa_ops = {
* Registers a mmu_notifier for the given BO at the specified address.
* Returns 0 on success, -ERRNO if anything goes wrong.
*/
-int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr)
+int amdgpu_hmm_register(struct amdgpu_bo *bo, unsigned long addr)
{
if (bo->kfd_bo)
return mmu_interval_notifier_insert(&bo->notifier, current->mm,
addr, amdgpu_bo_size(bo),
- &amdgpu_mn_hsa_ops);
+ &amdgpu_hmm_hsa_ops);
return mmu_interval_notifier_insert(&bo->notifier, current->mm, addr,
amdgpu_bo_size(bo),
- &amdgpu_mn_gfx_ops);
+ &amdgpu_hmm_gfx_ops);
}
/**
- * amdgpu_mn_unregister - unregister a BO for notifier updates
+ * amdgpu_hmm_unregister - unregister a BO for notifier updates
*
* @bo: amdgpu buffer object
*
* Remove any registration of mmu notifier updates from the buffer object.
*/
-void amdgpu_mn_unregister(struct amdgpu_bo *bo)
+void amdgpu_hmm_unregister(struct amdgpu_bo *bo)
{
if (!bo->notifier.mm)
return;
@@ -157,12 +160,12 @@ void amdgpu_mn_unregister(struct amdgpu_bo *bo)
}
int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
- struct mm_struct *mm, struct page **pages,
- uint64_t start, uint64_t npages,
- struct hmm_range **phmm_range, bool readonly,
- bool mmap_locked, void *owner)
+ uint64_t start, uint64_t npages, bool readonly,
+ void *owner, struct page **pages,
+ struct hmm_range **phmm_range)
{
struct hmm_range *hmm_range;
+ unsigned long end;
unsigned long timeout;
unsigned long i;
unsigned long *pfns;
@@ -184,32 +187,42 @@ int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
hmm_range->default_flags |= HMM_PFN_REQ_WRITE;
hmm_range->hmm_pfns = pfns;
hmm_range->start = start;
- hmm_range->end = start + npages * PAGE_SIZE;
+ end = start + npages * PAGE_SIZE;
hmm_range->dev_private_owner = owner;
- /* Assuming 512MB takes maxmium 1 second to fault page address */
- timeout = max(npages >> 17, 1ULL) * HMM_RANGE_DEFAULT_TIMEOUT;
- timeout = jiffies + msecs_to_jiffies(timeout);
+ do {
+ hmm_range->end = min(hmm_range->start + MAX_WALK_BYTE, end);
+
+ 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);
+ timeout *= HMM_RANGE_DEFAULT_TIMEOUT;
+ timeout = jiffies + msecs_to_jiffies(timeout);
retry:
- hmm_range->notifier_seq = mmu_interval_read_begin(notifier);
-
- if (likely(!mmap_locked))
- mmap_read_lock(mm);
-
- r = hmm_range_fault(hmm_range);
-
- if (likely(!mmap_locked))
- mmap_read_unlock(mm);
- if (unlikely(r)) {
- /*
- * FIXME: This timeout should encompass the retry from
- * mmu_interval_read_retry() as well.
- */
- if (r == -EBUSY && !time_after(jiffies, timeout))
- goto retry;
- goto out_free_pfns;
- }
+ hmm_range->notifier_seq = mmu_interval_read_begin(notifier);
+ r = hmm_range_fault(hmm_range);
+ if (unlikely(r)) {
+ /*
+ * FIXME: This timeout should encompass the retry from
+ * mmu_interval_read_retry() as well.
+ */
+ if (r == -EBUSY && !time_after(jiffies, timeout))
+ goto retry;
+ goto out_free_pfns;
+ }
+
+ if (hmm_range->end == end)
+ break;
+ hmm_range->hmm_pfns += MAX_WALK_BYTE >> PAGE_SHIFT;
+ hmm_range->start = hmm_range->end;
+ schedule();
+ } while (hmm_range->end < end);
+
+ hmm_range->start = start;
+ hmm_range->hmm_pfns = pfns;
/*
* Due to default_flags, all pages are HMM_PFN_VALID or
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.h
index 14a3c1864085..13ed94d3b01b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_hmm.h
@@ -31,23 +31,22 @@
#include <linux/interval_tree.h>
int amdgpu_hmm_range_get_pages(struct mmu_interval_notifier *notifier,
- struct mm_struct *mm, struct page **pages,
- uint64_t start, uint64_t npages,
- struct hmm_range **phmm_range, bool readonly,
- bool mmap_locked, void *owner);
+ uint64_t start, uint64_t npages, bool readonly,
+ void *owner, struct page **pages,
+ struct hmm_range **phmm_range);
int amdgpu_hmm_range_get_pages_done(struct hmm_range *hmm_range);
#if defined(CONFIG_HMM_MIRROR)
-int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr);
-void amdgpu_mn_unregister(struct amdgpu_bo *bo);
+int amdgpu_hmm_register(struct amdgpu_bo *bo, unsigned long addr);
+void amdgpu_hmm_unregister(struct amdgpu_bo *bo);
#else
-static inline int amdgpu_mn_register(struct amdgpu_bo *bo, unsigned long addr)
+static inline int amdgpu_hmm_register(struct amdgpu_bo *bo, unsigned long addr)
{
DRM_WARN_ONCE("HMM_MIRROR kernel config option is not enabled, "
"add CONFIG_ZONE_DEVICE=y in config file to fix this\n");
return -ENODEV;
}
-static inline void amdgpu_mn_unregister(struct amdgpu_bo *bo) {}
+static inline void amdgpu_hmm_unregister(struct amdgpu_bo *bo) {}
#endif
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index 258cffe3c06a..bcccc348dbe2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -182,7 +182,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
need_ctx_switch = ring->current_ctx != fence_ctx;
if (ring->funcs->emit_pipeline_sync && job &&
- ((tmp = amdgpu_sync_get_fence(&job->sched_sync)) ||
+ ((tmp = amdgpu_sync_get_fence(&job->explicit_sync)) ||
(amdgpu_sriov_vf(adev) && need_ctx_switch) ||
amdgpu_vm_need_pipeline_sync(ring, job))) {
need_pipe_sync = true;
@@ -211,6 +211,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
}
}
+ amdgpu_ring_ib_begin(ring);
if (job && ring->funcs->init_cond_exec)
patch_offset = amdgpu_ring_init_cond_exec(ring);
@@ -285,6 +286,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
ring->hw_prio == AMDGPU_GFX_PIPE_PRIO_HIGH)
ring->funcs->emit_wave_limit(ring, false);
+ amdgpu_ring_ib_end(ring);
amdgpu_ring_commit(ring);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
index 03d115d2b5ed..2a9a2593dc18 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c
@@ -170,26 +170,27 @@ bool amdgpu_vmid_had_gpu_reset(struct amdgpu_device *adev,
*
* @vm: vm to allocate id for
* @ring: ring we want to submit job to
- * @sync: sync object where we add dependencies
* @idle: resulting idle VMID
+ * @fence: fence to wait for if no id could be grabbed
*
* Try to find an idle VMID, if none is idle add a fence to wait to the sync
* object. Returns -ENOMEM when we are out of memory.
*/
static int amdgpu_vmid_grab_idle(struct amdgpu_vm *vm,
struct amdgpu_ring *ring,
- struct amdgpu_sync *sync,
- struct amdgpu_vmid **idle)
+ struct amdgpu_vmid **idle,
+ struct dma_fence **fence)
{
struct amdgpu_device *adev = ring->adev;
unsigned vmhub = ring->funcs->vmhub;
struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub];
struct dma_fence **fences;
unsigned i;
- int r;
- if (!dma_fence_is_signaled(ring->vmid_wait))
- return amdgpu_sync_fence(sync, ring->vmid_wait);
+ if (!dma_fence_is_signaled(ring->vmid_wait)) {
+ *fence = dma_fence_get(ring->vmid_wait);
+ return 0;
+ }
fences = kmalloc_array(id_mgr->num_ids, sizeof(void *), GFP_KERNEL);
if (!fences)
@@ -228,10 +229,10 @@ static int amdgpu_vmid_grab_idle(struct amdgpu_vm *vm,
return -ENOMEM;
}
- r = amdgpu_sync_fence(sync, &array->base);
+ *fence = dma_fence_get(&array->base);
dma_fence_put(ring->vmid_wait);
ring->vmid_wait = &array->base;
- return r;
+ return 0;
}
kfree(fences);
@@ -243,19 +244,17 @@ static int amdgpu_vmid_grab_idle(struct amdgpu_vm *vm,
*
* @vm: vm to allocate id for
* @ring: ring we want to submit job to
- * @sync: sync object where we add dependencies
- * @fence: fence protecting ID from reuse
* @job: job who wants to use the VMID
* @id: resulting VMID
+ * @fence: fence to wait for if no id could be grabbed
*
* Try to assign a reserved VMID.
*/
static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm,
struct amdgpu_ring *ring,
- struct amdgpu_sync *sync,
- struct dma_fence *fence,
struct amdgpu_job *job,
- struct amdgpu_vmid **id)
+ struct amdgpu_vmid **id,
+ struct dma_fence **fence)
{
struct amdgpu_device *adev = ring->adev;
unsigned vmhub = ring->funcs->vmhub;
@@ -282,7 +281,8 @@ static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm,
tmp = amdgpu_sync_peek_fence(&(*id)->active, ring);
if (tmp) {
*id = NULL;
- return amdgpu_sync_fence(sync, tmp);
+ *fence = dma_fence_get(tmp);
+ return 0;
}
needs_flush = true;
}
@@ -290,7 +290,7 @@ static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm,
/* Good we can use this VMID. Remember this submission as
* user of the VMID.
*/
- r = amdgpu_sync_fence(&(*id)->active, fence);
+ r = amdgpu_sync_fence(&(*id)->active, &job->base.s_fence->finished);
if (r)
return r;
@@ -304,19 +304,17 @@ static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm,
*
* @vm: vm to allocate id for
* @ring: ring we want to submit job to
- * @sync: sync object where we add dependencies
- * @fence: fence protecting ID from reuse
* @job: job who wants to use the VMID
* @id: resulting VMID
+ * @fence: fence to wait for if no id could be grabbed
*
* Try to reuse a VMID for this submission.
*/
static int amdgpu_vmid_grab_used(struct amdgpu_vm *vm,
struct amdgpu_ring *ring,
- struct amdgpu_sync *sync,
- struct dma_fence *fence,
struct amdgpu_job *job,
- struct amdgpu_vmid **id)
+ struct amdgpu_vmid **id,
+ struct dma_fence **fence)
{
struct amdgpu_device *adev = ring->adev;
unsigned vmhub = ring->funcs->vmhub;
@@ -352,7 +350,8 @@ static int amdgpu_vmid_grab_used(struct amdgpu_vm *vm,
/* Good, we can use this VMID. Remember this submission as
* user of the VMID.
*/
- r = amdgpu_sync_fence(&(*id)->active, fence);
+ r = amdgpu_sync_fence(&(*id)->active,
+ &job->base.s_fence->finished);
if (r)
return r;
@@ -370,15 +369,13 @@ static int amdgpu_vmid_grab_used(struct amdgpu_vm *vm,
*
* @vm: vm to allocate id for
* @ring: ring we want to submit job to
- * @sync: sync object where we add dependencies
- * @fence: fence protecting ID from reuse
* @job: job who wants to use the VMID
+ * @fence: fence to wait for if no id could be grabbed
*
* Allocate an id for the vm, adding fences to the sync obj as necessary.
*/
int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
- struct amdgpu_sync *sync, struct dma_fence *fence,
- struct amdgpu_job *job)
+ struct amdgpu_job *job, struct dma_fence **fence)
{
struct amdgpu_device *adev = ring->adev;
unsigned vmhub = ring->funcs->vmhub;
@@ -388,16 +385,16 @@ int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
int r = 0;
mutex_lock(&id_mgr->lock);
- r = amdgpu_vmid_grab_idle(vm, ring, sync, &idle);
+ r = amdgpu_vmid_grab_idle(vm, ring, &idle, fence);
if (r || !idle)
goto error;
if (vm->reserved_vmid[vmhub]) {
- r = amdgpu_vmid_grab_reserved(vm, ring, sync, fence, job, &id);
+ r = amdgpu_vmid_grab_reserved(vm, ring, job, &id, fence);
if (r || !id)
goto error;
} else {
- r = amdgpu_vmid_grab_used(vm, ring, sync, fence, job, &id);
+ r = amdgpu_vmid_grab_used(vm, ring, job, &id, fence);
if (r)
goto error;
@@ -406,7 +403,8 @@ int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
id = idle;
/* Remember this submission as user of the VMID */
- r = amdgpu_sync_fence(&id->active, fence);
+ r = amdgpu_sync_fence(&id->active,
+ &job->base.s_fence->finished);
if (r)
goto error;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
index 06c8a0034fa5..57efe61dceed 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h
@@ -84,8 +84,7 @@ void amdgpu_vmid_free_reserved(struct amdgpu_device *adev,
struct amdgpu_vm *vm,
unsigned vmhub);
int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
- struct amdgpu_sync *sync, struct dma_fence *fence,
- struct amdgpu_job *job);
+ struct amdgpu_job *job, struct dma_fence **fence);
void amdgpu_vmid_reset(struct amdgpu_device *adev, unsigned vmhub,
unsigned vmid);
void amdgpu_vmid_reset_all(struct amdgpu_device *adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
index 89011bae7588..a6aef488a822 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c
@@ -101,41 +101,6 @@ const char *soc15_ih_clientid_name[] = {
};
/**
- * amdgpu_hotplug_work_func - work handler for display hotplug event
- *
- * @work: work struct pointer
- *
- * This is the hotplug event work handler (all ASICs).
- * The work gets scheduled from the IRQ handler if there
- * was a hotplug interrupt. It walks through the connector table
- * and calls hotplug handler for each connector. After this, it sends
- * a DRM hotplug event to alert userspace.
- *
- * This design approach is required in order to defer hotplug event handling
- * from the IRQ handler to a work handler because hotplug handler has to use
- * mutexes which cannot be locked in an IRQ handler (since &mutex_lock may
- * sleep).
- */
-static void amdgpu_hotplug_work_func(struct work_struct *work)
-{
- struct amdgpu_device *adev = container_of(work, struct amdgpu_device,
- hotplug_work);
- struct drm_device *dev = adev_to_drm(adev);
- struct drm_mode_config *mode_config = &dev->mode_config;
- struct drm_connector *connector;
- struct drm_connector_list_iter iter;
-
- mutex_lock(&mode_config->mutex);
- drm_connector_list_iter_begin(dev, &iter);
- drm_for_each_connector_iter(connector, &iter)
- amdgpu_connector_hotplug(connector);
- drm_connector_list_iter_end(&iter);
- mutex_unlock(&mode_config->mutex);
- /* Just fire off a uevent and let userspace tell us what to do */
- drm_helper_hpd_irq_event(dev);
-}
-
-/**
* amdgpu_irq_disable_all - disable *all* interrupts
*
* @adev: amdgpu device pointer
@@ -317,21 +282,6 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
}
}
- if (!amdgpu_device_has_dc_support(adev)) {
- if (!adev->enable_virtual_display)
- /* Disable vblank IRQs aggressively for power-saving */
- /* XXX: can this be enabled for DC? */
- adev_to_drm(adev)->vblank_disable_immediate = true;
-
- r = drm_vblank_init(adev_to_drm(adev), adev->mode_info.num_crtc);
- if (r)
- return r;
-
- /* Pre-DCE11 */
- INIT_WORK(&adev->hotplug_work,
- amdgpu_hotplug_work_func);
- }
-
INIT_WORK(&adev->irq.ih1_work, amdgpu_irq_handle_ih1);
INIT_WORK(&adev->irq.ih2_work, amdgpu_irq_handle_ih2);
INIT_WORK(&adev->irq.ih_soft_work, amdgpu_irq_handle_ih_soft);
@@ -345,11 +295,8 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
/* PCI devices require shared interrupts. */
r = request_irq(irq, amdgpu_irq_handler, IRQF_SHARED, adev_to_drm(adev)->driver->name,
adev_to_drm(adev));
- if (r) {
- if (!amdgpu_device_has_dc_support(adev))
- flush_work(&adev->hotplug_work);
+ if (r)
return r;
- }
adev->irq.installed = true;
adev->irq.irq = irq;
adev_to_drm(adev)->max_vblank_count = 0x00ffffff;
@@ -366,9 +313,6 @@ void amdgpu_irq_fini_hw(struct amdgpu_device *adev)
adev->irq.installed = false;
if (adev->irq.msi_enabled)
pci_free_irq_vectors(adev->pdev);
-
- if (!amdgpu_device_has_dc_support(adev))
- flush_work(&adev->hotplug_work);
}
amdgpu_ih_ring_fini(adev, &adev->irq.ih_soft);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index adac650cf544..9e549923622b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -88,8 +88,9 @@ exit:
return DRM_GPU_SCHED_STAT_NOMINAL;
}
-int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs,
- struct amdgpu_job **job, struct amdgpu_vm *vm)
+int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+ struct drm_sched_entity *entity, void *owner,
+ unsigned int num_ibs, struct amdgpu_job **job)
{
if (num_ibs == 0)
return -EINVAL;
@@ -105,28 +106,34 @@ int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs,
(*job)->base.sched = &adev->rings[0]->sched;
(*job)->vm = vm;
- amdgpu_sync_create(&(*job)->sync);
- amdgpu_sync_create(&(*job)->sched_sync);
+ amdgpu_sync_create(&(*job)->explicit_sync);
(*job)->vram_lost_counter = atomic_read(&adev->vram_lost_counter);
(*job)->vm_pd_addr = AMDGPU_BO_INVALID_OFFSET;
- return 0;
+ if (!entity)
+ return 0;
+
+ return drm_sched_job_init(&(*job)->base, entity, owner);
}
-int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev, unsigned size,
- enum amdgpu_ib_pool_type pool_type,
- struct amdgpu_job **job)
+int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev,
+ struct drm_sched_entity *entity, void *owner,
+ size_t size, enum amdgpu_ib_pool_type pool_type,
+ struct amdgpu_job **job)
{
int r;
- r = amdgpu_job_alloc(adev, 1, job, NULL);
+ r = amdgpu_job_alloc(adev, NULL, entity, owner, 1, job);
if (r)
return r;
(*job)->num_ibs = 1;
r = amdgpu_ib_get(adev, NULL, size, pool_type, &(*job)->ibs[0]);
- if (r)
+ if (r) {
+ if (entity)
+ drm_sched_job_cleanup(&(*job)->base);
kfree(*job);
+ }
return r;
}
@@ -166,8 +173,7 @@ static void amdgpu_job_free_cb(struct drm_sched_job *s_job)
drm_sched_job_cleanup(s_job);
- amdgpu_sync_free(&job->sync);
- amdgpu_sync_free(&job->sched_sync);
+ amdgpu_sync_free(&job->explicit_sync);
/* only put the hw fence if has embedded fence */
if (!job->hw_fence.ops)
@@ -194,9 +200,11 @@ void amdgpu_job_set_gang_leader(struct amdgpu_job *job,
void amdgpu_job_free(struct amdgpu_job *job)
{
+ if (job->base.entity)
+ drm_sched_job_cleanup(&job->base);
+
amdgpu_job_free_resources(job);
- amdgpu_sync_free(&job->sync);
- amdgpu_sync_free(&job->sched_sync);
+ amdgpu_sync_free(&job->explicit_sync);
if (job->gang_submit != &job->base.s_fence->scheduled)
dma_fence_put(job->gang_submit);
@@ -206,25 +214,16 @@ void amdgpu_job_free(struct amdgpu_job *job)
dma_fence_put(&job->hw_fence);
}
-int amdgpu_job_submit(struct amdgpu_job *job, struct drm_sched_entity *entity,
- void *owner, struct dma_fence **f)
+struct dma_fence *amdgpu_job_submit(struct amdgpu_job *job)
{
- int r;
-
- if (!f)
- return -EINVAL;
-
- r = drm_sched_job_init(&job->base, entity, owner);
- if (r)
- return r;
+ struct dma_fence *f;
drm_sched_job_arm(&job->base);
-
- *f = dma_fence_get(&job->base.s_fence->finished);
+ f = dma_fence_get(&job->base.s_fence->finished);
amdgpu_job_free_resources(job);
drm_sched_entity_push_job(&job->base);
- return 0;
+ return f;
}
int amdgpu_job_submit_direct(struct amdgpu_job *job, struct amdgpu_ring *ring,
@@ -242,33 +241,22 @@ int amdgpu_job_submit_direct(struct amdgpu_job *job, struct amdgpu_ring *ring,
return 0;
}
-static struct dma_fence *amdgpu_job_dependency(struct drm_sched_job *sched_job,
- struct drm_sched_entity *s_entity)
+static struct dma_fence *
+amdgpu_job_prepare_job(struct drm_sched_job *sched_job,
+ struct drm_sched_entity *s_entity)
{
struct amdgpu_ring *ring = to_amdgpu_ring(s_entity->rq->sched);
struct amdgpu_job *job = to_amdgpu_job(sched_job);
- struct amdgpu_vm *vm = job->vm;
- struct dma_fence *fence;
+ struct dma_fence *fence = NULL;
int r;
- fence = amdgpu_sync_get_fence(&job->sync);
- if (fence && drm_sched_dependency_optimized(fence, s_entity)) {
- r = amdgpu_sync_fence(&job->sched_sync, fence);
- if (r)
- DRM_ERROR("Error adding fence (%d)\n", r);
- }
-
if (!fence && job->gang_submit)
fence = amdgpu_device_switch_gang(ring->adev, job->gang_submit);
- while (fence == NULL && vm && !job->vmid) {
- r = amdgpu_vmid_grab(vm, ring, &job->sync,
- &job->base.s_fence->finished,
- job);
+ while (!fence && job->vm && !job->vmid) {
+ r = amdgpu_vmid_grab(job->vm, ring, job, &fence);
if (r)
DRM_ERROR("Error getting VM ID (%d)\n", r);
-
- fence = amdgpu_sync_get_fence(&job->sync);
}
return fence;
@@ -285,8 +273,6 @@ static struct dma_fence *amdgpu_job_run(struct drm_sched_job *sched_job)
job = to_amdgpu_job(sched_job);
finished = &job->base.s_fence->finished;
- BUG_ON(amdgpu_sync_peek_fence(&job->sync, NULL));
-
trace_amdgpu_sched_run_job(job);
/* Skip job if VRAM is lost and never resubmit gangs */
@@ -345,7 +331,7 @@ void amdgpu_job_stop_all_jobs_on_sched(struct drm_gpu_scheduler *sched)
}
const struct drm_sched_backend_ops amdgpu_sched_ops = {
- .dependency = amdgpu_job_dependency,
+ .prepare_job = amdgpu_job_prepare_job,
.run_job = amdgpu_job_run,
.timedout_job = amdgpu_job_timedout,
.free_job = amdgpu_job_free_cb
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h
index ab7b150e5d50..a372802ea4e0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.h
@@ -47,8 +47,7 @@ enum amdgpu_ib_pool_type;
struct amdgpu_job {
struct drm_sched_job base;
struct amdgpu_vm *vm;
- struct amdgpu_sync sync;
- struct amdgpu_sync sched_sync;
+ struct amdgpu_sync explicit_sync;
struct dma_fence hw_fence;
struct dma_fence *gang_submit;
uint32_t preamble_status;
@@ -78,18 +77,20 @@ static inline struct amdgpu_ring *amdgpu_job_ring(struct amdgpu_job *job)
return to_amdgpu_ring(job->base.entity->rq->sched);
}
-int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs,
- struct amdgpu_job **job, struct amdgpu_vm *vm);
-int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev, unsigned size,
- enum amdgpu_ib_pool_type pool, struct amdgpu_job **job);
+int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm,
+ struct drm_sched_entity *entity, void *owner,
+ unsigned int num_ibs, struct amdgpu_job **job);
+int amdgpu_job_alloc_with_ib(struct amdgpu_device *adev,
+ struct drm_sched_entity *entity, void *owner,
+ size_t size, enum amdgpu_ib_pool_type pool_type,
+ struct amdgpu_job **job);
void amdgpu_job_set_resources(struct amdgpu_job *job, struct amdgpu_bo *gds,
struct amdgpu_bo *gws, struct amdgpu_bo *oa);
void amdgpu_job_free_resources(struct amdgpu_job *job);
void amdgpu_job_set_gang_leader(struct amdgpu_job *job,
struct amdgpu_job *leader);
void amdgpu_job_free(struct amdgpu_job *job);
-int amdgpu_job_submit(struct amdgpu_job *job, struct drm_sched_entity *entity,
- void *owner, struct dma_fence **f);
+struct dma_fence *amdgpu_job_submit(struct amdgpu_job *job);
int amdgpu_job_submit_direct(struct amdgpu_job *job, struct amdgpu_ring *ring,
struct dma_fence **fence);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
index 518eb0e40d32..6f81ed4fb0d9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
@@ -150,14 +150,15 @@ static int amdgpu_jpeg_dec_set_reg(struct amdgpu_ring *ring, uint32_t handle,
const unsigned ib_size_dw = 16;
int i, r;
- r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
- AMDGPU_IB_POOL_DIRECT, &job);
+ r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, ib_size_dw * 4,
+ AMDGPU_IB_POOL_DIRECT, &job);
if (r)
return r;
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, 0, 0,
+ PACKETJ_TYPE0);
ib->ptr[1] = 0xDEADBEEF;
for (i = 2; i < 16; i += 2) {
ib->ptr[i] = PACKETJ(0, 0, 0, PACKETJ_TYPE6);
@@ -234,3 +235,20 @@ int amdgpu_jpeg_process_poison_irq(struct amdgpu_device *adev,
return 0;
}
+
+void jpeg_set_ras_funcs(struct amdgpu_device *adev)
+{
+ if (!adev->jpeg.ras)
+ return;
+
+ amdgpu_ras_register_ras_block(adev, &adev->jpeg.ras->ras_block);
+
+ strcpy(adev->jpeg.ras->ras_block.ras_comm.name, "jpeg");
+ adev->jpeg.ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__JPEG;
+ adev->jpeg.ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__POISON;
+ adev->jpeg.ras_if = &adev->jpeg.ras->ras_block.ras_comm;
+
+ /* If don't define special ras_late_init function, use default ras_late_init */
+ if (!adev->jpeg.ras->ras_block.ras_late_init)
+ adev->jpeg.ras->ras_block.ras_late_init = amdgpu_ras_block_late_init;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h
index 635dca59a70a..e8ca3e32ad52 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h
@@ -72,5 +72,6 @@ int amdgpu_jpeg_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout);
int amdgpu_jpeg_process_poison_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry);
+void jpeg_set_ras_funcs(struct amdgpu_device *adev);
#endif /*__AMDGPU_JPEG_H__*/
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 4e42dcb1950f..7aa7e52ca784 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -29,6 +29,7 @@
#include "amdgpu.h"
#include <drm/amdgpu_drm.h>
#include <drm/drm_drv.h>
+#include <drm/drm_fb_helper.h>
#include "amdgpu_uvd.h"
#include "amdgpu_vce.h"
#include "atom.h"
@@ -430,7 +431,7 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
case AMDGPU_HW_IP_VCN_DEC:
type = AMD_IP_BLOCK_TYPE_VCN;
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
- if (adev->uvd.harvest_config & (1 << i))
+ if (adev->vcn.harvest_config & (1 << i))
continue;
if (adev->vcn.inst[i].ring_dec.sched.ready)
@@ -442,7 +443,7 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
case AMDGPU_HW_IP_VCN_ENC:
type = AMD_IP_BLOCK_TYPE_VCN;
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
- if (adev->uvd.harvest_config & (1 << i))
+ if (adev->vcn.harvest_config & (1 << i))
continue;
for (j = 0; j < adev->vcn.num_enc_rings; j++)
@@ -796,7 +797,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 || amdgpu_sriov_vf(adev))
+ if (amdgpu_mcbp)
dev_info->ids_flags |= AMDGPU_IDS_FLAGS_PREEMPTION;
if (amdgpu_is_tmz(adev))
dev_info->ids_flags |= AMDGPU_IDS_FLAGS_TMZ;
@@ -1172,7 +1173,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
goto error_vm;
}
- if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) {
+ if (amdgpu_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,
@@ -1236,7 +1237,7 @@ 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 || amdgpu_sriov_vf(adev)) {
+ 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);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
index ad980f4b66e1..97c05d08a551 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mes.h
@@ -91,14 +91,12 @@ struct amdgpu_mes {
struct amdgpu_bo *ucode_fw_obj[AMDGPU_MAX_MES_PIPES];
uint64_t ucode_fw_gpu_addr[AMDGPU_MAX_MES_PIPES];
uint32_t *ucode_fw_ptr[AMDGPU_MAX_MES_PIPES];
- uint32_t ucode_fw_version[AMDGPU_MAX_MES_PIPES];
uint64_t uc_start_addr[AMDGPU_MAX_MES_PIPES];
/* mes ucode data */
struct amdgpu_bo *data_fw_obj[AMDGPU_MAX_MES_PIPES];
uint64_t data_fw_gpu_addr[AMDGPU_MAX_MES_PIPES];
uint32_t *data_fw_ptr[AMDGPU_MAX_MES_PIPES];
- uint32_t data_fw_version[AMDGPU_MAX_MES_PIPES];
uint64_t data_start_addr[AMDGPU_MAX_MES_PIPES];
/* eop gpu obj */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index 37322550d750..8a39300b1a84 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -36,7 +36,6 @@
#include <drm/drm_encoder.h>
#include <drm/drm_fixed.h>
#include <drm/drm_crtc_helper.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_probe_helper.h>
#include <linux/i2c.h>
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
index 2e8f6cd7a729..919bbea2e3ac 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
@@ -542,6 +542,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
/* GWS and OA don't need any alignment. */
page_align = bp->byte_align;
size <<= PAGE_SHIFT;
+
} else if (bp->domain & AMDGPU_GEM_DOMAIN_GDS) {
/* Both size and alignment must be a multiple of 4. */
page_align = ALIGN(bp->byte_align, 4);
@@ -580,11 +581,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
bo->flags |= AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE;
bo->tbo.bdev = &adev->mman.bdev;
- if (bp->domain & (AMDGPU_GEM_DOMAIN_GWS | AMDGPU_GEM_DOMAIN_OA |
- AMDGPU_GEM_DOMAIN_GDS))
- amdgpu_bo_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_CPU);
- else
- amdgpu_bo_placement_from_domain(bo, bp->domain);
+ amdgpu_bo_placement_from_domain(bo, bp->domain);
if (bp->type == ttm_bo_type_kernel)
bo->tbo.priority = 1;
@@ -776,7 +773,7 @@ int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr)
return 0;
}
- r = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.resource->num_pages, &bo->kmap);
+ r = ttm_bo_kmap(&bo->tbo, 0, PFN_UP(bo->tbo.base.size), &bo->kmap);
if (r)
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index 7978307e1d6d..7a2fc920739b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -52,6 +52,32 @@ static int psp_load_smu_fw(struct psp_context *psp);
static int psp_rap_terminate(struct psp_context *psp);
static int psp_securedisplay_terminate(struct psp_context *psp);
+static int psp_ring_init(struct psp_context *psp,
+ enum psp_ring_type ring_type)
+{
+ int ret = 0;
+ struct psp_ring *ring;
+ struct amdgpu_device *adev = psp->adev;
+
+ ring = &psp->km_ring;
+
+ ring->ring_type = ring_type;
+
+ /* allocate 4k Page of Local Frame Buffer memory for ring */
+ ring->ring_size = 0x1000;
+ ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &adev->firmware.rbuf,
+ &ring->ring_mem_mc_addr,
+ (void **)&ring->ring_mem);
+ if (ret) {
+ ring->ring_size = 0;
+ return ret;
+ }
+
+ return 0;
+}
+
/*
* Due to DF Cstate management centralized to PMFW, the firmware
* loading sequence will be updated as below:
@@ -139,6 +165,7 @@ static int psp_early_init(void *handle)
case IP_VERSION(13, 0, 5):
case IP_VERSION(13, 0, 8):
case IP_VERSION(13, 0, 10):
+ case IP_VERSION(13, 0, 11):
psp_v13_0_set_psp_funcs(psp);
psp->autoload_supported = true;
break;
@@ -486,26 +513,22 @@ static int psp_sw_fini(void *handle)
struct psp_gfx_cmd_resp *cmd = psp->cmd;
psp_memory_training_fini(psp);
- if (psp->sos_fw) {
- release_firmware(psp->sos_fw);
- psp->sos_fw = NULL;
- }
- if (psp->asd_fw) {
- release_firmware(psp->asd_fw);
- psp->asd_fw = NULL;
- }
- if (psp->ta_fw) {
- release_firmware(psp->ta_fw);
- psp->ta_fw = NULL;
- }
- if (psp->cap_fw) {
- release_firmware(psp->cap_fw);
- psp->cap_fw = NULL;
- }
- if (psp->toc_fw) {
- release_firmware(psp->toc_fw);
- psp->toc_fw = NULL;
- }
+
+ release_firmware(psp->sos_fw);
+ psp->sos_fw = NULL;
+
+ release_firmware(psp->asd_fw);
+ psp->asd_fw = NULL;
+
+ release_firmware(psp->ta_fw);
+ psp->ta_fw = NULL;
+
+ release_firmware(psp->cap_fw);
+ psp->cap_fw = NULL;
+
+ release_firmware(psp->toc_fw);
+ psp->toc_fw = NULL;
+
if (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 0) ||
adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 7))
psp_sysfs_fini(adev);
@@ -835,7 +858,7 @@ static int psp_tmr_unload(struct psp_context *psp)
struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
psp_prep_tmr_unload_cmd_buf(psp, cmd);
- dev_info(psp->adev->dev, "free PSP TMR buffer\n");
+ dev_dbg(psp->adev->dev, "free PSP TMR buffer\n");
ret = psp_cmd_submit_buf(psp, NULL, cmd,
psp->fence_buf_mc_addr);
@@ -992,6 +1015,8 @@ int psp_ta_unload(struct psp_context *psp, struct ta_context *context)
ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
+ context->resp_status = cmd->resp.status;
+
release_psp_cmd_buf(psp);
return ret;
@@ -1073,42 +1098,6 @@ int psp_ta_init_shared_buf(struct psp_context *psp,
&mem_ctx->shared_buf);
}
-static void psp_prep_ta_invoke_indirect_cmd_buf(struct psp_gfx_cmd_resp *cmd,
- uint32_t ta_cmd_id,
- struct ta_context *context)
-{
- cmd->cmd_id = GFX_CMD_ID_INVOKE_CMD;
- cmd->cmd.cmd_invoke_cmd.session_id = context->session_id;
- cmd->cmd.cmd_invoke_cmd.ta_cmd_id = ta_cmd_id;
-
- cmd->cmd.cmd_invoke_cmd.buf.num_desc = 1;
- cmd->cmd.cmd_invoke_cmd.buf.total_size = context->mem_context.shared_mem_size;
- cmd->cmd.cmd_invoke_cmd.buf.buf_desc[0].buf_size = context->mem_context.shared_mem_size;
- cmd->cmd.cmd_invoke_cmd.buf.buf_desc[0].buf_phy_addr_lo =
- lower_32_bits(context->mem_context.shared_mc_addr);
- cmd->cmd.cmd_invoke_cmd.buf.buf_desc[0].buf_phy_addr_hi =
- upper_32_bits(context->mem_context.shared_mc_addr);
-}
-
-int psp_ta_invoke_indirect(struct psp_context *psp,
- uint32_t ta_cmd_id,
- struct ta_context *context)
-{
- int ret;
- struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
-
- psp_prep_ta_invoke_indirect_cmd_buf(cmd, ta_cmd_id, context);
-
- ret = psp_cmd_submit_buf(psp, NULL, cmd,
- psp->fence_buf_mc_addr);
-
- context->resp_status = cmd->resp.status;
-
- release_psp_cmd_buf(psp);
-
- return ret;
-}
-
static void psp_prep_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd,
uint32_t ta_cmd_id,
uint32_t session_id)
@@ -1551,7 +1540,7 @@ int psp_ras_terminate(struct psp_context *psp)
return ret;
}
-static int psp_ras_initialize(struct psp_context *psp)
+int psp_ras_initialize(struct psp_context *psp)
{
int ret;
uint32_t boot_cfg = 0xFF;
@@ -1614,7 +1603,7 @@ static int psp_ras_initialize(struct psp_context *psp)
psp->ras_context.context.mem_context.shared_mem_size = PSP_RAS_SHARED_MEM_SIZE;
psp->ras_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA;
- if (!psp->ras_context.context.initialized) {
+ if (!psp->ras_context.context.mem_context.shared_buf) {
ret = psp_ta_init_shared_buf(psp, &psp->ras_context.context.mem_context);
if (ret)
return ret;
@@ -1635,7 +1624,9 @@ static int psp_ras_initialize(struct psp_context *psp)
else {
if (ras_cmd->ras_status)
dev_warn(psp->adev->dev, "RAS Init Status: 0x%X\n", ras_cmd->ras_status);
- amdgpu_ras_fini(psp->adev);
+
+ /* fail to load RAS TA */
+ psp->ras_context.context.initialized = false;
}
return ret;
@@ -1942,10 +1933,15 @@ static int psp_securedisplay_initialize(struct psp_context *psp)
} else
return ret;
+ mutex_lock(&psp->securedisplay_context.mutex);
+
psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd,
TA_SECUREDISPLAY_COMMAND__QUERY_TA);
ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__QUERY_TA);
+
+ mutex_unlock(&psp->securedisplay_context.mutex);
+
if (ret) {
psp_securedisplay_terminate(psp);
/* free securedisplay shared memory */
@@ -1994,12 +1990,8 @@ int psp_securedisplay_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
ta_cmd_id != TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC)
return -EINVAL;
- mutex_lock(&psp->securedisplay_context.mutex);
-
ret = psp_ta_invoke(psp, ta_cmd_id, &psp->securedisplay_context.context);
- mutex_unlock(&psp->securedisplay_context.mutex);
-
return ret;
}
/* SECUREDISPLAY end */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
index 58ce3ebb446c..cf4f60c66122 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
@@ -118,7 +118,6 @@ struct psp_funcs
int (*bootloader_load_dbg_drv)(struct psp_context *psp);
int (*bootloader_load_ras_drv)(struct psp_context *psp);
int (*bootloader_load_sos)(struct psp_context *psp);
- int (*ring_init)(struct psp_context *psp, enum psp_ring_type ring_type);
int (*ring_create)(struct psp_context *psp,
enum psp_ring_type ring_type);
int (*ring_stop)(struct psp_context *psp,
@@ -136,6 +135,12 @@ struct psp_funcs
int (*vbflash_stat)(struct psp_context *psp);
};
+struct ta_funcs {
+ int (*fn_ta_initialize)(struct psp_context *psp);
+ int (*fn_ta_invoke)(struct psp_context *psp, uint32_t ta_cmd_id);
+ int (*fn_ta_terminate)(struct psp_context *psp);
+};
+
#define AMDGPU_XGMI_MAX_CONNECTED_NODES 64
struct psp_xgmi_node_info {
uint64_t node_id;
@@ -309,6 +314,7 @@ struct psp_context
struct psp_gfx_cmd_resp *cmd;
const struct psp_funcs *funcs;
+ const struct ta_funcs *ta_funcs;
/* firmware buffer */
struct amdgpu_bo *fw_pri_bo;
@@ -389,7 +395,6 @@ struct amdgpu_psp_funcs {
};
-#define psp_ring_init(psp, type) (psp)->funcs->ring_init((psp), (type))
#define psp_ring_create(psp, type) (psp)->funcs->ring_create((psp), (type))
#define psp_ring_stop(psp, type) (psp)->funcs->ring_stop((psp), (type))
#define psp_ring_destroy(psp, type) ((psp)->funcs->ring_destroy((psp), (type)))
@@ -463,9 +468,6 @@ int psp_ta_load(struct psp_context *psp, struct ta_context *context);
int psp_ta_invoke(struct psp_context *psp,
uint32_t ta_cmd_id,
struct ta_context *context);
-int psp_ta_invoke_indirect(struct psp_context *psp,
- uint32_t ta_cmd_id,
- struct ta_context *context);
int psp_xgmi_initialize(struct psp_context *psp, bool set_extended_data, bool load_ta);
int psp_xgmi_terminate(struct psp_context *psp);
@@ -479,7 +481,7 @@ int psp_xgmi_get_topology_info(struct psp_context *psp,
int psp_xgmi_set_topology_info(struct psp_context *psp,
int number_devices,
struct psp_xgmi_topology_info *topology);
-
+int psp_ras_initialize(struct psp_context *psp);
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);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c
index 0988e00612e5..468a67b302d4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c
@@ -41,30 +41,46 @@ static uint32_t get_bin_version(const uint8_t *bin)
return hdr->ucode_version;
}
-static void prep_ta_mem_context(struct psp_context *psp,
- struct ta_context *context,
+static int prep_ta_mem_context(struct ta_mem_context *mem_context,
uint8_t *shared_buf,
uint32_t shared_buf_len)
{
- context->mem_context.shared_mem_size = PAGE_ALIGN(shared_buf_len);
- psp_ta_init_shared_buf(psp, &context->mem_context);
+ if (mem_context->shared_mem_size < shared_buf_len)
+ return -EINVAL;
+ memset(mem_context->shared_buf, 0, mem_context->shared_mem_size);
+ memcpy((void *)mem_context->shared_buf, shared_buf, shared_buf_len);
- memcpy((void *)context->mem_context.shared_buf, shared_buf, shared_buf_len);
+ return 0;
}
static bool is_ta_type_valid(enum ta_type_id ta_type)
{
- bool ret = false;
+ switch (ta_type) {
+ case TA_TYPE_RAS:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct ta_funcs ras_ta_funcs = {
+ .fn_ta_initialize = psp_ras_initialize,
+ .fn_ta_invoke = psp_ras_invoke,
+ .fn_ta_terminate = psp_ras_terminate
+};
+static void set_ta_context_funcs(struct psp_context *psp,
+ enum ta_type_id ta_type,
+ struct ta_context **pcontext)
+{
switch (ta_type) {
case TA_TYPE_RAS:
- ret = true;
+ *pcontext = &psp->ras_context.context;
+ psp->ta_funcs = &ras_ta_funcs;
break;
default:
break;
}
-
- return ret;
}
static const struct file_operations ta_load_debugfs_fops = {
@@ -85,8 +101,7 @@ static const struct file_operations ta_invoke_debugfs_fops = {
.owner = THIS_MODULE
};
-
-/**
+/*
* DOC: AMDGPU TA debugfs interfaces
*
* Three debugfs interfaces can be opened by a program to
@@ -111,15 +126,18 @@ static const struct file_operations ta_invoke_debugfs_fops = {
*
* - For TA invoke debugfs interface:
* Transmit buffer:
+ * - TA type (4bytes)
* - TA ID (4bytes)
* - TA CMD ID (4bytes)
- * - TA shard buf length (4bytes)
+ * - TA shard buf length
+ * (4bytes, value not beyond TA shared memory size)
* - TA shared buf
* Receive buffer:
* - TA shared buf
*
* - For TA unload debugfs interface:
* Transmit buffer:
+ * - TA type (4bytes)
* - TA ID (4bytes)
*/
@@ -131,59 +149,92 @@ static ssize_t ta_if_load_debugfs_write(struct file *fp, const char *buf, size_t
uint32_t copy_pos = 0;
int ret = 0;
- struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private;
- struct psp_context *psp = &adev->psp;
- struct ta_context context = {0};
+ struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private;
+ struct psp_context *psp = &adev->psp;
+ struct ta_context *context = NULL;
if (!buf)
return -EINVAL;
ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t));
if (ret || (!is_ta_type_valid(ta_type)))
- return -EINVAL;
+ return -EFAULT;
copy_pos += sizeof(uint32_t);
ret = copy_from_user((void *)&ta_bin_len, &buf[copy_pos], sizeof(uint32_t));
if (ret)
- return -EINVAL;
+ return -EFAULT;
copy_pos += sizeof(uint32_t);
ta_bin = kzalloc(ta_bin_len, GFP_KERNEL);
if (!ta_bin)
- ret = -ENOMEM;
+ return -ENOMEM;
if (copy_from_user((void *)ta_bin, &buf[copy_pos], ta_bin_len)) {
ret = -EFAULT;
goto err_free_bin;
}
- ret = psp_ras_terminate(psp);
- if (ret) {
- dev_err(adev->dev, "Failed to unload embedded RAS TA\n");
+ /* Set TA context and functions */
+ set_ta_context_funcs(psp, ta_type, &context);
+
+ if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_terminate) {
+ dev_err(adev->dev, "Unsupported function to terminate TA\n");
+ ret = -EOPNOTSUPP;
goto err_free_bin;
}
- context.ta_type = ta_type;
- context.ta_load_type = GFX_CMD_ID_LOAD_TA;
- context.bin_desc.fw_version = get_bin_version(ta_bin);
- context.bin_desc.size_bytes = ta_bin_len;
- context.bin_desc.start_addr = ta_bin;
+ /*
+ * Allocate TA shared buf in case shared buf was freed
+ * due to loading TA failed before.
+ */
+ if (!context->mem_context.shared_buf) {
+ ret = psp_ta_init_shared_buf(psp, &context->mem_context);
+ if (ret) {
+ ret = -ENOMEM;
+ goto err_free_bin;
+ }
+ }
+
+ ret = psp_fn_ta_terminate(psp);
+ if (ret || context->resp_status) {
+ dev_err(adev->dev,
+ "Failed to unload embedded TA (%d) and status (0x%X)\n",
+ ret, context->resp_status);
+ if (!ret)
+ ret = -EINVAL;
+ goto err_free_ta_shared_buf;
+ }
+
+ /* Prepare TA context for TA initialization */
+ context->ta_type = ta_type;
+ context->bin_desc.fw_version = get_bin_version(ta_bin);
+ context->bin_desc.size_bytes = ta_bin_len;
+ context->bin_desc.start_addr = ta_bin;
- ret = psp_ta_load(psp, &context);
+ if (!psp->ta_funcs->fn_ta_initialize) {
+ dev_err(adev->dev, "Unsupported function to initialize TA\n");
+ ret = -EOPNOTSUPP;
+ goto err_free_ta_shared_buf;
+ }
- if (ret || context.resp_status) {
- dev_err(adev->dev, "TA load via debugfs failed (%d) status %d\n",
- ret, context.resp_status);
+ ret = psp_fn_ta_initialize(psp);
+ if (ret || context->resp_status) {
+ dev_err(adev->dev, "Failed to load TA via debugfs (%d) and status (0x%X)\n",
+ ret, context->resp_status);
if (!ret)
ret = -EINVAL;
- goto err_free_bin;
+ goto err_free_ta_shared_buf;
}
- context.initialized = true;
- if (copy_to_user((char *)buf, (void *)&context.session_id, sizeof(uint32_t)))
+ if (copy_to_user((char *)buf, (void *)&context->session_id, sizeof(uint32_t)))
ret = -EFAULT;
+err_free_ta_shared_buf:
+ /* Only free TA shared buf when returns error code */
+ if (ret && context->mem_context.shared_buf)
+ psp_ta_free_shared_buf(&context->mem_context);
err_free_bin:
kfree(ta_bin);
@@ -192,58 +243,85 @@ err_free_bin:
static ssize_t ta_if_unload_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
{
- uint32_t ta_id = 0;
- int ret = 0;
+ uint32_t ta_type = 0;
+ uint32_t ta_id = 0;
+ uint32_t copy_pos = 0;
+ int ret = 0;
- struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private;
- struct psp_context *psp = &adev->psp;
- struct ta_context context = {0};
+ struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private;
+ struct psp_context *psp = &adev->psp;
+ struct ta_context *context = NULL;
if (!buf)
return -EINVAL;
- ret = copy_from_user((void *)&ta_id, buf, sizeof(uint32_t));
+ ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t));
+ if (ret || (!is_ta_type_valid(ta_type)))
+ return -EFAULT;
+
+ copy_pos += sizeof(uint32_t);
+
+ ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t));
if (ret)
- return -EINVAL;
+ return -EFAULT;
- context.session_id = ta_id;
+ set_ta_context_funcs(psp, ta_type, &context);
+ context->session_id = ta_id;
- ret = psp_ta_unload(psp, &context);
- if (!ret)
- context.initialized = false;
+ if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_terminate) {
+ dev_err(adev->dev, "Unsupported function to terminate TA\n");
+ return -EOPNOTSUPP;
+ }
+
+ ret = psp_fn_ta_terminate(psp);
+ if (ret || context->resp_status) {
+ dev_err(adev->dev, "Failed to unload TA via debugfs (%d) and status (0x%X)\n",
+ ret, context->resp_status);
+ if (!ret)
+ ret = -EINVAL;
+ }
+
+ if (context->mem_context.shared_buf)
+ psp_ta_free_shared_buf(&context->mem_context);
return ret;
}
static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size_t len, loff_t *off)
{
+ uint32_t ta_type = 0;
uint32_t ta_id = 0;
uint32_t cmd_id = 0;
uint32_t shared_buf_len = 0;
- uint8_t *shared_buf = NULL;
+ uint8_t *shared_buf = NULL;
uint32_t copy_pos = 0;
int ret = 0;
- struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private;
- struct psp_context *psp = &adev->psp;
- struct ta_context context = {0};
+ struct amdgpu_device *adev = (struct amdgpu_device *)file_inode(fp)->i_private;
+ struct psp_context *psp = &adev->psp;
+ struct ta_context *context = NULL;
if (!buf)
return -EINVAL;
+ ret = copy_from_user((void *)&ta_type, &buf[copy_pos], sizeof(uint32_t));
+ if (ret)
+ return -EFAULT;
+ copy_pos += sizeof(uint32_t);
+
ret = copy_from_user((void *)&ta_id, &buf[copy_pos], sizeof(uint32_t));
if (ret)
- return -EINVAL;
+ return -EFAULT;
copy_pos += sizeof(uint32_t);
ret = copy_from_user((void *)&cmd_id, &buf[copy_pos], sizeof(uint32_t));
if (ret)
- return -EINVAL;
+ return -EFAULT;
copy_pos += sizeof(uint32_t);
ret = copy_from_user((void *)&shared_buf_len, &buf[copy_pos], sizeof(uint32_t));
if (ret)
- return -EINVAL;
+ return -EFAULT;
copy_pos += sizeof(uint32_t);
shared_buf = kzalloc(shared_buf_len, GFP_KERNEL);
@@ -254,26 +332,39 @@ static ssize_t ta_if_invoke_debugfs_write(struct file *fp, const char *buf, size
goto err_free_shared_buf;
}
- context.session_id = ta_id;
+ set_ta_context_funcs(psp, ta_type, &context);
+
+ if (!context->initialized) {
+ dev_err(adev->dev, "TA is not initialized\n");
+ ret = -EINVAL;
+ goto err_free_shared_buf;
+ }
+
+ if (!psp->ta_funcs || !psp->ta_funcs->fn_ta_invoke) {
+ dev_err(adev->dev, "Unsupported function to invoke TA\n");
+ ret = -EOPNOTSUPP;
+ goto err_free_shared_buf;
+ }
- prep_ta_mem_context(psp, &context, shared_buf, shared_buf_len);
+ context->session_id = ta_id;
- ret = psp_ta_invoke_indirect(psp, cmd_id, &context);
+ ret = prep_ta_mem_context(&context->mem_context, shared_buf, shared_buf_len);
+ if (ret)
+ goto err_free_shared_buf;
- if (ret || context.resp_status) {
- dev_err(adev->dev, "TA invoke via debugfs failed (%d) status %d\n",
- ret, context.resp_status);
- if (!ret)
+ ret = psp_fn_ta_invoke(psp, cmd_id);
+ if (ret || context->resp_status) {
+ dev_err(adev->dev, "Failed to invoke TA via debugfs (%d) and status (0x%X)\n",
+ ret, context->resp_status);
+ if (!ret) {
ret = -EINVAL;
- goto err_free_ta_shared_buf;
+ goto err_free_shared_buf;
+ }
}
- if (copy_to_user((char *)buf, context.mem_context.shared_buf, shared_buf_len))
+ if (copy_to_user((char *)buf, context->mem_context.shared_buf, shared_buf_len))
ret = -EFAULT;
-err_free_ta_shared_buf:
- psp_ta_free_shared_buf(&context.mem_context);
-
err_free_shared_buf:
kfree(shared_buf);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.h
index cfc1542f63ef..14cd1c81c3e6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.h
@@ -24,6 +24,11 @@
#ifndef __AMDGPU_PSP_TA_H__
#define __AMDGPU_PSP_TA_H__
+/* Calling set_ta_context_funcs is required before using the following macros */
+#define psp_fn_ta_initialize(psp) ((psp)->ta_funcs->fn_ta_initialize((psp)))
+#define psp_fn_ta_invoke(psp, ta_cmd_id) ((psp)->ta_funcs->fn_ta_invoke((psp), (ta_cmd_id)))
+#define psp_fn_ta_terminate(psp) ((psp)->ta_funcs->fn_ta_terminate((psp)))
+
void amdgpu_ta_if_debugfs_init(struct amdgpu_device *adev);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index a4b47e1bd111..ad490c1e2f57 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -1267,7 +1267,7 @@ static ssize_t amdgpu_ras_sysfs_features_read(struct device *dev,
struct amdgpu_ras *con =
container_of(attr, struct amdgpu_ras, features_attr);
- return scnprintf(buf, PAGE_SIZE, "feature mask: 0x%x\n", con->features);
+ return sysfs_emit(buf, "feature mask: 0x%x\n", con->features);
}
static void amdgpu_ras_sysfs_remove_bad_page_node(struct amdgpu_device *adev)
@@ -1561,7 +1561,6 @@ static void amdgpu_ras_interrupt_poison_consumption_handler(struct ras_manager *
{
bool poison_stat = false;
struct amdgpu_device *adev = obj->adev;
- struct ras_err_data err_data = {0, 0, 0, NULL};
struct amdgpu_ras_block_object *block_obj =
amdgpu_ras_get_ras_block(adev, obj->head.block, 0);
@@ -1584,7 +1583,7 @@ static void amdgpu_ras_interrupt_poison_consumption_handler(struct ras_manager *
}
if (!adev->gmc.xgmi.connected_to_cpu)
- amdgpu_umc_poison_handler(adev, &err_data, false);
+ amdgpu_umc_poison_handler(adev, false);
if (block_obj->hw_ops->handle_poison_consumption)
poison_stat = block_obj->hw_ops->handle_poison_consumption(adev);
@@ -1949,7 +1948,12 @@ static void amdgpu_ras_do_recovery(struct work_struct *work)
reset_context.method = AMD_RESET_METHOD_NONE;
reset_context.reset_req_dev = adev;
- clear_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
+
+ /* 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
+ clear_bit(AMDGPU_NEED_FULL_RESET, &reset_context.flags);
amdgpu_device_gpu_recover(ras->adev, NULL, &reset_context);
}
@@ -2344,7 +2348,8 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev)
adev->ras_hw_enabled |= ~(1 << AMDGPU_RAS_BLOCK__UMC |
1 << AMDGPU_RAS_BLOCK__DF);
- if (adev->ip_versions[VCN_HWIP][0] == IP_VERSION(2, 6, 0))
+ if (adev->ip_versions[VCN_HWIP][0] == IP_VERSION(2, 6, 0) ||
+ adev->ip_versions[VCN_HWIP][0] == IP_VERSION(4, 0, 0))
adev->ras_hw_enabled |= (1 << AMDGPU_RAS_BLOCK__VCN |
1 << AMDGPU_RAS_BLOCK__JPEG);
else
@@ -2848,7 +2853,6 @@ static int amdgpu_bad_page_notifier(struct notifier_block *nb,
struct amdgpu_device *adev = NULL;
uint32_t gpu_id = 0;
uint32_t umc_inst = 0, ch_inst = 0;
- struct ras_err_data err_data = {0, 0, 0, NULL};
/*
* If the error was generated in UMC_V2, which belongs to GPU UMCs,
@@ -2887,31 +2891,10 @@ static int amdgpu_bad_page_notifier(struct notifier_block *nb,
dev_info(adev->dev, "Uncorrectable error detected in UMC inst: %d, chan_idx: %d",
umc_inst, ch_inst);
- err_data.err_addr =
- kcalloc(adev->umc.max_ras_err_cnt_per_query,
- sizeof(struct eeprom_table_record), GFP_KERNEL);
- if (!err_data.err_addr) {
- dev_warn(adev->dev,
- "Failed to alloc memory for umc error record in mca notifier!\n");
+ if (!amdgpu_umc_page_retirement_mca(adev, m->addr, ch_inst, umc_inst))
+ return NOTIFY_OK;
+ else
return NOTIFY_DONE;
- }
-
- /*
- * Translate UMC channel address to Physical address
- */
- if (adev->umc.ras &&
- adev->umc.ras->convert_ras_error_address)
- adev->umc.ras->convert_ras_error_address(adev,
- &err_data, m->addr, ch_inst, umc_inst);
-
- if (amdgpu_bad_page_threshold != 0) {
- amdgpu_ras_add_bad_pages(adev, err_data.err_addr,
- err_data.err_addr_cnt);
- amdgpu_ras_save_bad_pages(adev);
- }
-
- kfree(err_data.err_addr);
- return NOTIFY_OK;
}
static struct notifier_block amdgpu_bad_page_nb = {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
index 84c241b9a2a1..2d9f3f4cd79e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
@@ -33,12 +33,29 @@
#include "amdgpu_reset.h"
-#define EEPROM_I2C_MADDR_VEGA20 0x0
-#define EEPROM_I2C_MADDR_ARCTURUS 0x40000
-#define EEPROM_I2C_MADDR_ARCTURUS_D342 0x0
-#define EEPROM_I2C_MADDR_SIENNA_CICHLID 0x0
-#define EEPROM_I2C_MADDR_ALDEBARAN 0x0
-#define EEPROM_I2C_MADDR_SMU_13_0_0 (0x54UL << 16)
+/* These are memory addresses as would be seen by one or more EEPROM
+ * chips strung on the I2C bus, usually by manipulating pins 1-3 of a
+ * set of EEPROM devices. They form a continuous memory space.
+ *
+ * The I2C device address includes the device type identifier, 1010b,
+ * which is a reserved value and indicates that this is an I2C EEPROM
+ * device. It also includes the top 3 bits of the 19 bit EEPROM memory
+ * address, namely bits 18, 17, and 16. This makes up the 7 bit
+ * address sent on the I2C bus with bit 0 being the direction bit,
+ * which is not represented here, and sent by the hardware directly.
+ *
+ * For instance,
+ * 50h = 1010000b => device type identifier 1010b, bits 18:16 = 000b, address 0.
+ * 54h = 1010100b => --"--, bits 18:16 = 100b, address 40000h.
+ * 56h = 1010110b => --"--, bits 18:16 = 110b, address 60000h.
+ * Depending on the size of the I2C EEPROM device(s), bits 18:16 may
+ * address memory in a device or a device on the I2C bus, depending on
+ * the status of pins 1-3. See top of amdgpu_eeprom.c.
+ *
+ * The RAS table lives either at address 0 or address 40000h of EEPROM.
+ */
+#define EEPROM_I2C_MADDR_0 0x0
+#define EEPROM_I2C_MADDR_4 0x40000
/*
* The 2 macros bellow represent the actual size in bytes that
@@ -90,6 +107,16 @@
static bool __is_ras_eeprom_supported(struct amdgpu_device *adev)
{
+ if (adev->asic_type == CHIP_IP_DISCOVERY) {
+ switch (adev->ip_versions[MP1_HWIP][0]) {
+ case IP_VERSION(13, 0, 0):
+ case IP_VERSION(13, 0, 10):
+ return true;
+ default:
+ return false;
+ }
+ }
+
return adev->asic_type == CHIP_VEGA20 ||
adev->asic_type == CHIP_ARCTURUS ||
adev->asic_type == CHIP_SIENNA_CICHLID ||
@@ -107,16 +134,30 @@ static bool __get_eeprom_i2c_addr_arct(struct amdgpu_device *adev,
if (strnstr(atom_ctx->vbios_version,
"D342",
sizeof(atom_ctx->vbios_version)))
- control->i2c_address = EEPROM_I2C_MADDR_ARCTURUS_D342;
+ control->i2c_address = EEPROM_I2C_MADDR_0;
else
- control->i2c_address = EEPROM_I2C_MADDR_ARCTURUS;
+ control->i2c_address = EEPROM_I2C_MADDR_4;
return true;
}
+static bool __get_eeprom_i2c_addr_ip_discovery(struct amdgpu_device *adev,
+ struct amdgpu_ras_eeprom_control *control)
+{
+ switch (adev->ip_versions[MP1_HWIP][0]) {
+ case IP_VERSION(13, 0, 0):
+ case IP_VERSION(13, 0, 10):
+ control->i2c_address = EEPROM_I2C_MADDR_4;
+ return true;
+ default:
+ return false;
+ }
+}
+
static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev,
struct amdgpu_ras_eeprom_control *control)
{
+ struct atom_context *atom_ctx = adev->mode_info.atom_context;
u8 i2c_addr;
if (!control)
@@ -139,27 +180,34 @@ static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev,
switch (adev->asic_type) {
case CHIP_VEGA20:
- control->i2c_address = EEPROM_I2C_MADDR_VEGA20;
+ control->i2c_address = EEPROM_I2C_MADDR_0;
break;
case CHIP_ARCTURUS:
return __get_eeprom_i2c_addr_arct(adev, control);
case CHIP_SIENNA_CICHLID:
- control->i2c_address = EEPROM_I2C_MADDR_SIENNA_CICHLID;
+ control->i2c_address = EEPROM_I2C_MADDR_0;
break;
case CHIP_ALDEBARAN:
- control->i2c_address = EEPROM_I2C_MADDR_ALDEBARAN;
+ if (strnstr(atom_ctx->vbios_version, "D673",
+ sizeof(atom_ctx->vbios_version)))
+ control->i2c_address = EEPROM_I2C_MADDR_4;
+ else
+ control->i2c_address = EEPROM_I2C_MADDR_0;
break;
+ case CHIP_IP_DISCOVERY:
+ return __get_eeprom_i2c_addr_ip_discovery(adev, control);
+
default:
return false;
}
switch (adev->ip_versions[MP1_HWIP][0]) {
case IP_VERSION(13, 0, 0):
- control->i2c_address = EEPROM_I2C_MADDR_SMU_13_0_0;
+ control->i2c_address = EEPROM_I2C_MADDR_4;
break;
default:
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
index 6546552e596c..5c4f93ee0c57 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
@@ -62,7 +62,7 @@ static inline void amdgpu_res_first(struct ttm_resource *res,
if (!res)
goto fallback;
- BUG_ON(start + size > res->num_pages << PAGE_SHIFT);
+ BUG_ON(start + size > res->size);
cur->mem_type = res->mem_type;
@@ -110,7 +110,7 @@ fallback:
cur->size = size;
cur->remaining = size;
cur->node = NULL;
- WARN_ON(res && start + size > res->num_pages << PAGE_SHIFT);
+ WARN_ON(res && start + size > res->size);
return;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
index d3558c34d406..dc474b809604 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
@@ -569,3 +569,15 @@ int amdgpu_ring_init_mqd(struct amdgpu_ring *ring)
return mqd_mgr->init_mqd(adev, ring->mqd_ptr, &prop);
}
+
+void amdgpu_ring_ib_begin(struct amdgpu_ring *ring)
+{
+ if (ring->is_sw_ring)
+ amdgpu_sw_ring_ib_begin(ring);
+}
+
+void amdgpu_ring_ib_end(struct amdgpu_ring *ring)
+{
+ if (ring->is_sw_ring)
+ amdgpu_sw_ring_ib_end(ring);
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
index 82c178a9033a..f752c7ae7f60 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
@@ -39,6 +39,7 @@ struct amdgpu_vm;
#define AMDGPU_MAX_RINGS 28
#define AMDGPU_MAX_HWIP_RINGS 8
#define AMDGPU_MAX_GFX_RINGS 2
+#define AMDGPU_MAX_SW_GFX_RINGS 2
#define AMDGPU_MAX_COMPUTE_RINGS 8
#define AMDGPU_MAX_VCE_RINGS 3
#define AMDGPU_MAX_UVD_ENC_RINGS 2
@@ -59,6 +60,7 @@ enum amdgpu_ring_priority_level {
#define AMDGPU_FENCE_FLAG_64BIT (1 << 0)
#define AMDGPU_FENCE_FLAG_INT (1 << 1)
#define AMDGPU_FENCE_FLAG_TC_WB_ONLY (1 << 2)
+#define AMDGPU_FENCE_FLAG_EXEC (1 << 3)
#define to_amdgpu_ring(s) container_of((s), struct amdgpu_ring, sched)
@@ -143,8 +145,13 @@ signed long amdgpu_fence_wait_polling(struct amdgpu_ring *ring,
uint32_t wait_seq,
signed long timeout);
unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring);
+
void amdgpu_fence_driver_isr_toggle(struct amdgpu_device *adev, bool stop);
+u64 amdgpu_fence_last_unsignaled_time_us(struct amdgpu_ring *ring);
+void amdgpu_fence_update_start_timestamp(struct amdgpu_ring *ring, uint32_t seq,
+ ktime_t timestamp);
+
/*
* Rings.
*/
@@ -279,6 +286,10 @@ struct amdgpu_ring {
bool is_mes_queue;
uint32_t hw_queue_id;
struct amdgpu_mes_ctx_data *mes_ctx;
+
+ bool is_sw_ring;
+ unsigned int entry_index;
+
};
#define amdgpu_ring_parse_cs(r, p, job, ib) ((r)->funcs->parse_cs((p), (job), (ib)))
@@ -307,6 +318,9 @@ struct amdgpu_ring {
#define amdgpu_ring_preempt_ib(r) (r)->funcs->preempt_ib(r)
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);
+
void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count);
void amdgpu_ring_generic_pad_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib);
void amdgpu_ring_commit(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
new file mode 100644
index 000000000000..62079f0e3ee8
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.c
@@ -0,0 +1,514 @@
+/*
+ * 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/slab.h>
+#include <drm/drm_print.h>
+
+#include "amdgpu_ring_mux.h"
+#include "amdgpu_ring.h"
+#include "amdgpu.h"
+
+#define AMDGPU_MUX_RESUBMIT_JIFFIES_TIMEOUT (HZ / 2)
+#define AMDGPU_MAX_LAST_UNSIGNALED_THRESHOLD_US 10000
+
+static const struct ring_info {
+ unsigned int hw_pio;
+ const char *ring_name;
+} sw_ring_info[] = {
+ { AMDGPU_RING_PRIO_DEFAULT, "gfx_low"},
+ { AMDGPU_RING_PRIO_2, "gfx_high"},
+};
+
+static struct kmem_cache *amdgpu_mux_chunk_slab;
+
+static inline struct amdgpu_mux_entry *amdgpu_ring_mux_sw_entry(struct amdgpu_ring_mux *mux,
+ struct amdgpu_ring *ring)
+{
+ return ring->entry_index < mux->ring_entry_size ?
+ &mux->ring_entry[ring->entry_index] : NULL;
+}
+
+/* copy packages on sw ring range[begin, end) */
+static void amdgpu_ring_mux_copy_pkt_from_sw_ring(struct amdgpu_ring_mux *mux,
+ struct amdgpu_ring *ring,
+ u64 s_start, u64 s_end)
+{
+ u64 start, end;
+ struct amdgpu_ring *real_ring = mux->real_ring;
+
+ start = s_start & ring->buf_mask;
+ end = s_end & ring->buf_mask;
+
+ if (start == end) {
+ DRM_ERROR("no more data copied from sw ring\n");
+ return;
+ }
+ if (start > end) {
+ amdgpu_ring_alloc(real_ring, (ring->ring_size >> 2) + end - start);
+ amdgpu_ring_write_multiple(real_ring, (void *)&ring->ring[start],
+ (ring->ring_size >> 2) - start);
+ amdgpu_ring_write_multiple(real_ring, (void *)&ring->ring[0], end);
+ } else {
+ amdgpu_ring_alloc(real_ring, end - start);
+ amdgpu_ring_write_multiple(real_ring, (void *)&ring->ring[start], end - start);
+ }
+}
+
+static void amdgpu_mux_resubmit_chunks(struct amdgpu_ring_mux *mux)
+{
+ struct amdgpu_mux_entry *e = NULL;
+ struct amdgpu_mux_chunk *chunk;
+ uint32_t seq, last_seq;
+ int i;
+
+ /*find low priority entries:*/
+ if (!mux->s_resubmit)
+ return;
+
+ for (i = 0; i < mux->num_ring_entries; i++) {
+ if (mux->ring_entry[i].ring->hw_prio <= AMDGPU_RING_PRIO_DEFAULT) {
+ e = &mux->ring_entry[i];
+ break;
+ }
+ }
+
+ if (!e) {
+ DRM_ERROR("%s no low priority ring found\n", __func__);
+ return;
+ }
+
+ last_seq = atomic_read(&e->ring->fence_drv.last_seq);
+ seq = mux->seqno_to_resubmit;
+ if (last_seq < seq) {
+ /*resubmit all the fences between (last_seq, seq]*/
+ list_for_each_entry(chunk, &e->list, entry) {
+ if (chunk->sync_seq > last_seq && chunk->sync_seq <= seq) {
+ amdgpu_fence_update_start_timestamp(e->ring,
+ chunk->sync_seq,
+ ktime_get());
+ amdgpu_ring_mux_copy_pkt_from_sw_ring(mux, e->ring,
+ chunk->start,
+ chunk->end);
+ mux->wptr_resubmit = chunk->end;
+ amdgpu_ring_commit(mux->real_ring);
+ }
+ }
+ }
+
+ del_timer(&mux->resubmit_timer);
+ mux->s_resubmit = false;
+}
+
+static void amdgpu_ring_mux_schedule_resubmit(struct amdgpu_ring_mux *mux)
+{
+ mod_timer(&mux->resubmit_timer, jiffies + AMDGPU_MUX_RESUBMIT_JIFFIES_TIMEOUT);
+}
+
+static void amdgpu_mux_resubmit_fallback(struct timer_list *t)
+{
+ struct amdgpu_ring_mux *mux = from_timer(mux, t, resubmit_timer);
+
+ if (!spin_trylock(&mux->lock)) {
+ amdgpu_ring_mux_schedule_resubmit(mux);
+ DRM_ERROR("reschedule resubmit\n");
+ return;
+ }
+ amdgpu_mux_resubmit_chunks(mux);
+ spin_unlock(&mux->lock);
+}
+
+int amdgpu_ring_mux_init(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring,
+ unsigned int entry_size)
+{
+ mux->real_ring = ring;
+ mux->num_ring_entries = 0;
+
+ mux->ring_entry = kcalloc(entry_size, sizeof(struct amdgpu_mux_entry), GFP_KERNEL);
+ if (!mux->ring_entry)
+ return -ENOMEM;
+
+ mux->ring_entry_size = entry_size;
+ mux->s_resubmit = false;
+
+ amdgpu_mux_chunk_slab = kmem_cache_create("amdgpu_mux_chunk",
+ sizeof(struct amdgpu_mux_chunk), 0,
+ SLAB_HWCACHE_ALIGN, NULL);
+ if (!amdgpu_mux_chunk_slab) {
+ DRM_ERROR("create amdgpu_mux_chunk cache failed\n");
+ return -ENOMEM;
+ }
+
+ spin_lock_init(&mux->lock);
+ timer_setup(&mux->resubmit_timer, amdgpu_mux_resubmit_fallback, 0);
+
+ return 0;
+}
+
+void amdgpu_ring_mux_fini(struct amdgpu_ring_mux *mux)
+{
+ struct amdgpu_mux_entry *e;
+ struct amdgpu_mux_chunk *chunk, *chunk2;
+ int i;
+
+ for (i = 0; i < mux->num_ring_entries; i++) {
+ e = &mux->ring_entry[i];
+ list_for_each_entry_safe(chunk, chunk2, &e->list, entry) {
+ list_del(&chunk->entry);
+ kmem_cache_free(amdgpu_mux_chunk_slab, chunk);
+ }
+ }
+ kmem_cache_destroy(amdgpu_mux_chunk_slab);
+ kfree(mux->ring_entry);
+ mux->ring_entry = NULL;
+ mux->num_ring_entries = 0;
+ mux->ring_entry_size = 0;
+}
+
+int amdgpu_ring_mux_add_sw_ring(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring)
+{
+ struct amdgpu_mux_entry *e;
+
+ if (mux->num_ring_entries >= mux->ring_entry_size) {
+ DRM_ERROR("add sw ring exceeding max entry size\n");
+ return -ENOENT;
+ }
+
+ e = &mux->ring_entry[mux->num_ring_entries];
+ ring->entry_index = mux->num_ring_entries;
+ e->ring = ring;
+
+ INIT_LIST_HEAD(&e->list);
+ mux->num_ring_entries += 1;
+ return 0;
+}
+
+void amdgpu_ring_mux_set_wptr(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring, u64 wptr)
+{
+ struct amdgpu_mux_entry *e;
+
+ spin_lock(&mux->lock);
+
+ if (ring->hw_prio <= AMDGPU_RING_PRIO_DEFAULT)
+ amdgpu_mux_resubmit_chunks(mux);
+
+ e = amdgpu_ring_mux_sw_entry(mux, ring);
+ if (!e) {
+ DRM_ERROR("cannot find entry for sw ring\n");
+ spin_unlock(&mux->lock);
+ return;
+ }
+
+ /* We could skip this set wptr as preemption in process. */
+ if (ring->hw_prio <= AMDGPU_RING_PRIO_DEFAULT && mux->pending_trailing_fence_signaled) {
+ spin_unlock(&mux->lock);
+ return;
+ }
+
+ e->sw_cptr = e->sw_wptr;
+ /* Update cptr if the package already copied in resubmit functions */
+ if (ring->hw_prio <= AMDGPU_RING_PRIO_DEFAULT && e->sw_cptr < mux->wptr_resubmit)
+ e->sw_cptr = mux->wptr_resubmit;
+ e->sw_wptr = wptr;
+ e->start_ptr_in_hw_ring = mux->real_ring->wptr;
+
+ /* Skip copying for the packages already resubmitted.*/
+ if (ring->hw_prio > AMDGPU_RING_PRIO_DEFAULT || mux->wptr_resubmit < wptr) {
+ amdgpu_ring_mux_copy_pkt_from_sw_ring(mux, ring, e->sw_cptr, wptr);
+ e->end_ptr_in_hw_ring = mux->real_ring->wptr;
+ amdgpu_ring_commit(mux->real_ring);
+ } else {
+ e->end_ptr_in_hw_ring = mux->real_ring->wptr;
+ }
+ spin_unlock(&mux->lock);
+}
+
+u64 amdgpu_ring_mux_get_wptr(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring)
+{
+ struct amdgpu_mux_entry *e;
+
+ e = amdgpu_ring_mux_sw_entry(mux, ring);
+ if (!e) {
+ DRM_ERROR("cannot find entry for sw ring\n");
+ return 0;
+ }
+
+ return e->sw_wptr;
+}
+
+/**
+ * amdgpu_ring_mux_get_rptr - get the readptr of the software ring
+ * @mux: the multiplexer the software rings attach to
+ * @ring: the software ring of which we calculate the readptr
+ *
+ * The return value of the readptr is not precise while the other rings could
+ * write data onto the real ring buffer.After overwriting on the real ring, we
+ * can not decide if our packages have been excuted or not read yet. However,
+ * this function is only called by the tools such as umr to collect the latest
+ * packages for the hang analysis. We assume the hang happens near our latest
+ * submit. Thus we could use the following logic to give the clue:
+ * If the readptr is between start and end, then we return the copy pointer
+ * plus the distance from start to readptr. If the readptr is before start, we
+ * return the copy pointer. Lastly, if the readptr is past end, we return the
+ * write pointer.
+ */
+u64 amdgpu_ring_mux_get_rptr(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring)
+{
+ struct amdgpu_mux_entry *e;
+ u64 readp, offset, start, end;
+
+ e = amdgpu_ring_mux_sw_entry(mux, ring);
+ if (!e) {
+ DRM_ERROR("no sw entry found!\n");
+ return 0;
+ }
+
+ readp = amdgpu_ring_get_rptr(mux->real_ring);
+
+ start = e->start_ptr_in_hw_ring & mux->real_ring->buf_mask;
+ end = e->end_ptr_in_hw_ring & mux->real_ring->buf_mask;
+ if (start > end) {
+ if (readp <= end)
+ readp += mux->real_ring->ring_size >> 2;
+ end += mux->real_ring->ring_size >> 2;
+ }
+
+ if (start <= readp && readp <= end) {
+ offset = readp - start;
+ e->sw_rptr = (e->sw_cptr + offset) & ring->buf_mask;
+ } else if (readp < start) {
+ e->sw_rptr = e->sw_cptr;
+ } else {
+ /* end < readptr */
+ e->sw_rptr = e->sw_wptr;
+ }
+
+ return e->sw_rptr;
+}
+
+u64 amdgpu_sw_ring_get_rptr_gfx(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+ struct amdgpu_ring_mux *mux = &adev->gfx.muxer;
+
+ WARN_ON(!ring->is_sw_ring);
+ return amdgpu_ring_mux_get_rptr(mux, ring);
+}
+
+u64 amdgpu_sw_ring_get_wptr_gfx(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+ struct amdgpu_ring_mux *mux = &adev->gfx.muxer;
+
+ WARN_ON(!ring->is_sw_ring);
+ return amdgpu_ring_mux_get_wptr(mux, ring);
+}
+
+void amdgpu_sw_ring_set_wptr_gfx(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+ struct amdgpu_ring_mux *mux = &adev->gfx.muxer;
+
+ WARN_ON(!ring->is_sw_ring);
+ amdgpu_ring_mux_set_wptr(mux, ring, ring->wptr);
+}
+
+/* Override insert_nop to prevent emitting nops to the software rings */
+void amdgpu_sw_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
+{
+ WARN_ON(!ring->is_sw_ring);
+}
+
+const char *amdgpu_sw_ring_name(int idx)
+{
+ return idx < ARRAY_SIZE(sw_ring_info) ?
+ sw_ring_info[idx].ring_name : NULL;
+}
+
+unsigned int amdgpu_sw_ring_priority(int idx)
+{
+ return idx < ARRAY_SIZE(sw_ring_info) ?
+ sw_ring_info[idx].hw_pio : AMDGPU_RING_PRIO_DEFAULT;
+}
+
+/*Scan on low prio rings to have unsignaled fence and high ring has no fence.*/
+static int amdgpu_mcbp_scan(struct amdgpu_ring_mux *mux)
+{
+ struct amdgpu_ring *ring;
+ int i, need_preempt;
+
+ need_preempt = 0;
+ for (i = 0; i < mux->num_ring_entries; i++) {
+ ring = mux->ring_entry[i].ring;
+ if (ring->hw_prio > AMDGPU_RING_PRIO_DEFAULT &&
+ amdgpu_fence_count_emitted(ring) > 0)
+ return 0;
+ if (ring->hw_prio <= AMDGPU_RING_PRIO_DEFAULT &&
+ amdgpu_fence_last_unsignaled_time_us(ring) >
+ AMDGPU_MAX_LAST_UNSIGNALED_THRESHOLD_US)
+ need_preempt = 1;
+ }
+ return need_preempt && !mux->s_resubmit;
+}
+
+/* Trigger Mid-Command Buffer Preemption (MCBP) and find if we need to resubmit. */
+static int amdgpu_mcbp_trigger_preempt(struct amdgpu_ring_mux *mux)
+{
+ int r;
+
+ spin_lock(&mux->lock);
+ mux->pending_trailing_fence_signaled = true;
+ r = amdgpu_ring_preempt_ib(mux->real_ring);
+ spin_unlock(&mux->lock);
+ return r;
+}
+
+void amdgpu_sw_ring_ib_begin(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+ struct amdgpu_ring_mux *mux = &adev->gfx.muxer;
+
+ WARN_ON(!ring->is_sw_ring);
+ if (ring->hw_prio > AMDGPU_RING_PRIO_DEFAULT) {
+ if (amdgpu_mcbp_scan(mux) > 0)
+ amdgpu_mcbp_trigger_preempt(mux);
+ return;
+ }
+
+ amdgpu_ring_mux_start_ib(mux, ring);
+}
+
+void amdgpu_sw_ring_ib_end(struct amdgpu_ring *ring)
+{
+ struct amdgpu_device *adev = ring->adev;
+ struct amdgpu_ring_mux *mux = &adev->gfx.muxer;
+
+ WARN_ON(!ring->is_sw_ring);
+ if (ring->hw_prio > AMDGPU_RING_PRIO_DEFAULT)
+ return;
+ amdgpu_ring_mux_end_ib(mux, ring);
+}
+
+void amdgpu_ring_mux_start_ib(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring)
+{
+ struct amdgpu_mux_entry *e;
+ struct amdgpu_mux_chunk *chunk;
+
+ spin_lock(&mux->lock);
+ amdgpu_mux_resubmit_chunks(mux);
+ spin_unlock(&mux->lock);
+
+ e = amdgpu_ring_mux_sw_entry(mux, ring);
+ if (!e) {
+ DRM_ERROR("cannot find entry!\n");
+ return;
+ }
+
+ chunk = kmem_cache_alloc(amdgpu_mux_chunk_slab, GFP_KERNEL);
+ if (!chunk) {
+ DRM_ERROR("alloc amdgpu_mux_chunk_slab failed\n");
+ return;
+ }
+
+ chunk->start = ring->wptr;
+ list_add_tail(&chunk->entry, &e->list);
+}
+
+static void scan_and_remove_signaled_chunk(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring)
+{
+ uint32_t last_seq = 0;
+ struct amdgpu_mux_entry *e;
+ struct amdgpu_mux_chunk *chunk, *tmp;
+
+ e = amdgpu_ring_mux_sw_entry(mux, ring);
+ if (!e) {
+ DRM_ERROR("cannot find entry!\n");
+ return;
+ }
+
+ last_seq = atomic_read(&ring->fence_drv.last_seq);
+
+ list_for_each_entry_safe(chunk, tmp, &e->list, entry) {
+ if (chunk->sync_seq <= last_seq) {
+ list_del(&chunk->entry);
+ kmem_cache_free(amdgpu_mux_chunk_slab, chunk);
+ }
+ }
+}
+
+void amdgpu_ring_mux_end_ib(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring)
+{
+ struct amdgpu_mux_entry *e;
+ struct amdgpu_mux_chunk *chunk;
+
+ e = amdgpu_ring_mux_sw_entry(mux, ring);
+ if (!e) {
+ DRM_ERROR("cannot find entry!\n");
+ return;
+ }
+
+ chunk = list_last_entry(&e->list, struct amdgpu_mux_chunk, entry);
+ if (!chunk) {
+ DRM_ERROR("cannot find chunk!\n");
+ return;
+ }
+
+ chunk->end = ring->wptr;
+ chunk->sync_seq = READ_ONCE(ring->fence_drv.sync_seq);
+
+ scan_and_remove_signaled_chunk(mux, ring);
+}
+
+bool amdgpu_mcbp_handle_trailing_fence_irq(struct amdgpu_ring_mux *mux)
+{
+ struct amdgpu_mux_entry *e;
+ struct amdgpu_ring *ring = NULL;
+ int i;
+
+ if (!mux->pending_trailing_fence_signaled)
+ return false;
+
+ if (mux->real_ring->trail_seq != le32_to_cpu(*mux->real_ring->trail_fence_cpu_addr))
+ return false;
+
+ for (i = 0; i < mux->num_ring_entries; i++) {
+ e = &mux->ring_entry[i];
+ if (e->ring->hw_prio <= AMDGPU_RING_PRIO_DEFAULT) {
+ ring = e->ring;
+ break;
+ }
+ }
+
+ if (!ring) {
+ DRM_ERROR("cannot find low priority ring\n");
+ return false;
+ }
+
+ amdgpu_fence_process(ring);
+ if (amdgpu_fence_count_emitted(ring) > 0) {
+ mux->s_resubmit = true;
+ mux->seqno_to_resubmit = ring->fence_drv.sync_seq;
+ amdgpu_ring_mux_schedule_resubmit(mux);
+ }
+
+ mux->pending_trailing_fence_signaled = false;
+ return true;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.h
new file mode 100644
index 000000000000..4be45fc14954
--- /dev/null
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring_mux.h
@@ -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.
+ *
+ */
+
+#ifndef __AMDGPU_RING_MUX__
+#define __AMDGPU_RING_MUX__
+
+#include <linux/timer.h>
+#include <linux/spinlock.h>
+#include "amdgpu_ring.h"
+
+struct amdgpu_ring;
+
+/**
+ * struct amdgpu_mux_entry - the entry recording software rings copying information.
+ * @ring: the pointer to the software ring.
+ * @start_ptr_in_hw_ring: last start location copied to in the hardware ring.
+ * @end_ptr_in_hw_ring: last end location copied to in the hardware ring.
+ * @sw_cptr: the position of the copy pointer in the sw ring.
+ * @sw_rptr: the read pointer in software ring.
+ * @sw_wptr: the write pointer in software ring.
+ * @list: list head for amdgpu_mux_chunk
+ */
+struct amdgpu_mux_entry {
+ struct amdgpu_ring *ring;
+ u64 start_ptr_in_hw_ring;
+ u64 end_ptr_in_hw_ring;
+ u64 sw_cptr;
+ u64 sw_rptr;
+ u64 sw_wptr;
+ struct list_head list;
+};
+
+struct amdgpu_ring_mux {
+ struct amdgpu_ring *real_ring;
+
+ struct amdgpu_mux_entry *ring_entry;
+ unsigned int num_ring_entries;
+ unsigned int ring_entry_size;
+ /*the lock for copy data from different software rings*/
+ spinlock_t lock;
+ bool s_resubmit;
+ uint32_t seqno_to_resubmit;
+ u64 wptr_resubmit;
+ struct timer_list resubmit_timer;
+
+ bool pending_trailing_fence_signaled;
+};
+
+/**
+ * struct amdgpu_mux_chunk - save the location of indirect buffer's package on softare rings.
+ * @entry: the list entry.
+ * @sync_seq: the fence seqno related with the saved IB.
+ * @start:- start location on the software ring.
+ * @end:- end location on the software ring.
+ */
+struct amdgpu_mux_chunk {
+ struct list_head entry;
+ uint32_t sync_seq;
+ u64 start;
+ u64 end;
+};
+
+int amdgpu_ring_mux_init(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring,
+ unsigned int entry_size);
+void amdgpu_ring_mux_fini(struct amdgpu_ring_mux *mux);
+int amdgpu_ring_mux_add_sw_ring(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring);
+void amdgpu_ring_mux_set_wptr(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring, u64 wptr);
+u64 amdgpu_ring_mux_get_wptr(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring);
+u64 amdgpu_ring_mux_get_rptr(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring);
+void amdgpu_ring_mux_start_ib(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring);
+void amdgpu_ring_mux_end_ib(struct amdgpu_ring_mux *mux, struct amdgpu_ring *ring);
+bool amdgpu_mcbp_handle_trailing_fence_irq(struct amdgpu_ring_mux *mux);
+
+u64 amdgpu_sw_ring_get_rptr_gfx(struct amdgpu_ring *ring);
+u64 amdgpu_sw_ring_get_wptr_gfx(struct amdgpu_ring *ring);
+void amdgpu_sw_ring_set_wptr_gfx(struct amdgpu_ring *ring);
+void amdgpu_sw_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count);
+void amdgpu_sw_ring_ib_begin(struct amdgpu_ring *ring);
+void amdgpu_sw_ring_ib_end(struct amdgpu_ring *ring);
+const char *amdgpu_sw_ring_name(int idx);
+unsigned int amdgpu_sw_ring_priority(int idx);
+
+#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_securedisplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_securedisplay.c
index cc7597a15fe9..2c1d82fc4c34 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_securedisplay.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_securedisplay.c
@@ -121,6 +121,7 @@ static ssize_t amdgpu_securedisplay_debugfs_write(struct file *f, const char __u
switch (op) {
case 1:
+ mutex_lock(&psp->securedisplay_context.mutex);
psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd,
TA_SECUREDISPLAY_COMMAND__QUERY_TA);
ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__QUERY_TA);
@@ -131,8 +132,10 @@ static ssize_t amdgpu_securedisplay_debugfs_write(struct file *f, const char __u
else
psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status);
}
+ mutex_unlock(&psp->securedisplay_context.mutex);
break;
case 2:
+ mutex_lock(&psp->securedisplay_context.mutex);
psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd,
TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC);
securedisplay_cmd->securedisplay_in_message.send_roi_crc.phy_id = phy_id;
@@ -146,6 +149,7 @@ static ssize_t amdgpu_securedisplay_debugfs_write(struct file *f, const char __u
psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status);
}
}
+ mutex_unlock(&psp->securedisplay_context.mutex);
break;
default:
dev_err(adev->dev, "Invalid input: %s\n", str);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
index 090e66a1b284..bac7976975bd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c
@@ -259,6 +259,14 @@ int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync,
return 0;
}
+/* Free the entry back to the slab */
+static void amdgpu_sync_entry_free(struct amdgpu_sync_entry *e)
+{
+ hash_del(&e->node);
+ dma_fence_put(e->fence);
+ kmem_cache_free(amdgpu_sync_slab, e);
+}
+
/**
* amdgpu_sync_peek_fence - get the next fence not signaled yet
*
@@ -280,9 +288,7 @@ struct dma_fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync,
struct drm_sched_fence *s_fence = to_drm_sched_fence(f);
if (dma_fence_is_signaled(f)) {
- hash_del(&e->node);
- dma_fence_put(f);
- kmem_cache_free(amdgpu_sync_slab, e);
+ amdgpu_sync_entry_free(e);
continue;
}
if (ring && s_fence) {
@@ -355,15 +361,42 @@ int amdgpu_sync_clone(struct amdgpu_sync *source, struct amdgpu_sync *clone)
if (r)
return r;
} else {
- hash_del(&e->node);
- dma_fence_put(f);
- kmem_cache_free(amdgpu_sync_slab, e);
+ amdgpu_sync_entry_free(e);
}
}
return 0;
}
+/**
+ * amdgpu_sync_push_to_job - push fences into job
+ * @sync: sync object to get the fences from
+ * @job: job to push the fences into
+ *
+ * Add all unsignaled fences from sync to job.
+ */
+int amdgpu_sync_push_to_job(struct amdgpu_sync *sync, struct amdgpu_job *job)
+{
+ struct amdgpu_sync_entry *e;
+ struct hlist_node *tmp;
+ struct dma_fence *f;
+ int i, r;
+
+ hash_for_each_safe(sync->fences, i, tmp, e, node) {
+ f = e->fence;
+ if (dma_fence_is_signaled(f)) {
+ amdgpu_sync_entry_free(e);
+ continue;
+ }
+
+ dma_fence_get(f);
+ r = drm_sched_job_add_dependency(&job->base, f);
+ if (r)
+ return r;
+ }
+ return 0;
+}
+
int amdgpu_sync_wait(struct amdgpu_sync *sync, bool intr)
{
struct amdgpu_sync_entry *e;
@@ -375,9 +408,7 @@ int amdgpu_sync_wait(struct amdgpu_sync *sync, bool intr)
if (r)
return r;
- hash_del(&e->node);
- dma_fence_put(e->fence);
- kmem_cache_free(amdgpu_sync_slab, e);
+ amdgpu_sync_entry_free(e);
}
return 0;
@@ -396,11 +427,8 @@ void amdgpu_sync_free(struct amdgpu_sync *sync)
struct hlist_node *tmp;
unsigned int i;
- hash_for_each_safe(sync->fences, i, tmp, e, node) {
- hash_del(&e->node);
- dma_fence_put(e->fence);
- kmem_cache_free(amdgpu_sync_slab, e);
- }
+ hash_for_each_safe(sync->fences, i, tmp, e, node)
+ amdgpu_sync_entry_free(e);
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h
index 2d5c613cda10..cf1e9e858efd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h
@@ -30,6 +30,7 @@ struct dma_fence;
struct dma_resv;
struct amdgpu_device;
struct amdgpu_ring;
+struct amdgpu_job;
enum amdgpu_sync_mode {
AMDGPU_SYNC_ALWAYS,
@@ -54,6 +55,7 @@ struct dma_fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync,
struct amdgpu_ring *ring);
struct dma_fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync);
int amdgpu_sync_clone(struct amdgpu_sync *source, struct amdgpu_sync *clone);
+int amdgpu_sync_push_to_job(struct amdgpu_sync *sync, struct amdgpu_job *job);
int amdgpu_sync_wait(struct amdgpu_sync *sync, bool intr);
void amdgpu_sync_free(struct amdgpu_sync *sync);
int amdgpu_sync_init(void);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
index 5e6ddc7e101c..677ad2016976 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
@@ -127,7 +127,7 @@ TRACE_EVENT(amdgpu_bo_create,
TP_fast_assign(
__entry->bo = bo;
- __entry->pages = bo->tbo.resource->num_pages;
+ __entry->pages = PFN_UP(bo->tbo.resource->size);
__entry->type = bo->tbo.resource->mem_type;
__entry->prefer = bo->preferred_domains;
__entry->allow = bo->allowed_domains;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index b64938ed8cb6..b4236572eae1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -58,6 +58,7 @@
#include "amdgpu_amdkfd.h"
#include "amdgpu_sdma.h"
#include "amdgpu_ras.h"
+#include "amdgpu_hmm.h"
#include "amdgpu_atomfirmware.h"
#include "amdgpu_res_cursor.h"
#include "bif/bif_4_1_d.h"
@@ -189,7 +190,6 @@ static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo,
struct amdgpu_device *adev = ring->adev;
unsigned offset, num_pages, num_dw, num_bytes;
uint64_t src_addr, dst_addr;
- struct dma_fence *fence;
struct amdgpu_job *job;
void *cpu_addr;
uint64_t flags;
@@ -229,7 +229,9 @@ 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, num_dw * 4 + num_bytes,
+ r = amdgpu_job_alloc_with_ib(adev, &adev->mman.entity,
+ AMDGPU_FENCE_OWNER_UNDEFINED,
+ num_dw * 4 + num_bytes,
AMDGPU_IB_POOL_DELAYED, &job);
if (r)
return r;
@@ -269,18 +271,8 @@ static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo,
}
}
- r = amdgpu_job_submit(job, &adev->mman.entity,
- AMDGPU_FENCE_OWNER_UNDEFINED, &fence);
- if (r)
- goto error_free;
-
- dma_fence_put(fence);
-
- return r;
-
-error_free:
- amdgpu_job_free(job);
- return r;
+ dma_fence_put(amdgpu_job_submit(job));
+ return 0;
}
/**
@@ -381,7 +373,7 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo,
dst.offset = 0;
r = amdgpu_ttm_copy_mem_to_mem(adev, &src, &dst,
- new_mem->num_pages << PAGE_SHIFT,
+ new_mem->size,
amdgpu_bo_encrypted(abo),
bo->base.resv, &fence);
if (r)
@@ -424,7 +416,7 @@ error:
static bool amdgpu_mem_visible(struct amdgpu_device *adev,
struct ttm_resource *mem)
{
- u64 mem_size = (u64)mem->num_pages << PAGE_SHIFT;
+ u64 mem_size = (u64)mem->size;
struct amdgpu_res_cursor cursor;
u64 end;
@@ -571,7 +563,7 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_device *bdev,
struct ttm_resource *mem)
{
struct amdgpu_device *adev = amdgpu_ttm_adev(bdev);
- size_t bus_size = (size_t)mem->num_pages << PAGE_SHIFT;
+ size_t bus_size = (size_t)mem->size;
switch (mem->mem_type) {
case TTM_PL_SYSTEM:
@@ -691,9 +683,8 @@ int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo, struct page **pages,
}
readonly = amdgpu_ttm_tt_is_readonly(ttm);
- r = amdgpu_hmm_range_get_pages(&bo->notifier, mm, pages, start,
- ttm->num_pages, range, readonly,
- true, NULL);
+ r = amdgpu_hmm_range_get_pages(&bo->notifier, start, ttm->num_pages,
+ readonly, NULL, pages, range);
out_unlock:
mmap_read_unlock(mm);
if (r)
@@ -1154,8 +1145,9 @@ int amdgpu_ttm_tt_get_userptr(const struct ttm_buffer_object *tbo,
* @addr: The address in the current tasks VM space to use
* @flags: Requirements of userptr object.
*
- * Called by amdgpu_gem_userptr_ioctl() to bind userptr pages
- * to current task
+ * Called by amdgpu_gem_userptr_ioctl() and kfd_ioctl_alloc_memory_of_gpu() to
+ * bind userptr pages to current task and by kfd_ioctl_acquire_vm() to
+ * initialize GPU VM for a KFD process.
*/
int amdgpu_ttm_tt_set_userptr(struct ttm_buffer_object *bo,
uint64_t addr, uint32_t flags)
@@ -1394,7 +1386,8 @@ static void amdgpu_ttm_vram_mm_access(struct amdgpu_device *adev, loff_t pos,
}
static int amdgpu_ttm_access_memory_sdma(struct ttm_buffer_object *bo,
- unsigned long offset, void *buf, int len, int write)
+ unsigned long offset, void *buf,
+ int len, int write)
{
struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo);
struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev);
@@ -1418,26 +1411,27 @@ 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, num_dw * 4, AMDGPU_IB_POOL_DELAYED, &job);
+ r = amdgpu_job_alloc_with_ib(adev, &adev->mman.entity,
+ AMDGPU_FENCE_OWNER_UNDEFINED,
+ num_dw * 4, AMDGPU_IB_POOL_DELAYED,
+ &job);
if (r)
goto out;
amdgpu_res_first(abo->tbo.resource, offset, len, &src_mm);
- src_addr = amdgpu_ttm_domain_start(adev, bo->resource->mem_type) + src_mm.start;
+ src_addr = amdgpu_ttm_domain_start(adev, bo->resource->mem_type) +
+ src_mm.start;
dst_addr = amdgpu_bo_gpu_offset(adev->mman.sdma_access_bo);
if (write)
swap(src_addr, dst_addr);
- amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, dst_addr, PAGE_SIZE, false);
+ amdgpu_emit_copy_buffer(adev, &job->ibs[0], src_addr, dst_addr,
+ PAGE_SIZE, false);
amdgpu_ring_pad_ib(adev->mman.buffer_funcs_ring, &job->ibs[0]);
WARN_ON(job->ibs[0].length_dw > num_dw);
- r = amdgpu_job_submit(job, &adev->mman.entity, AMDGPU_FENCE_OWNER_UNDEFINED, &fence);
- if (r) {
- amdgpu_job_free(job);
- goto out;
- }
+ fence = amdgpu_job_submit(job);
if (!dma_fence_wait_timeout(fence, false, adev->sdma_timeout))
r = -ETIMEDOUT;
@@ -1537,6 +1531,23 @@ static void amdgpu_ttm_fw_reserve_vram_fini(struct amdgpu_device *adev)
NULL, &adev->mman.fw_vram_usage_va);
}
+/*
+ * Driver Reservation functions
+ */
+/**
+ * amdgpu_ttm_drv_reserve_vram_fini - free drv reserved vram
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * free drv reserved vram if it has been reserved.
+ */
+static void amdgpu_ttm_drv_reserve_vram_fini(struct amdgpu_device *adev)
+{
+ amdgpu_bo_free_kernel(&adev->mman.drv_vram_usage_reserved_bo,
+ NULL,
+ &adev->mman.drv_vram_usage_va);
+}
+
/**
* amdgpu_ttm_fw_reserve_vram_init - create bo vram reservation from fw
*
@@ -1563,6 +1574,32 @@ static int amdgpu_ttm_fw_reserve_vram_init(struct amdgpu_device *adev)
&adev->mman.fw_vram_usage_va);
}
+/**
+ * amdgpu_ttm_drv_reserve_vram_init - create bo vram reservation from driver
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * create bo vram reservation from drv.
+ */
+static int amdgpu_ttm_drv_reserve_vram_init(struct amdgpu_device *adev)
+{
+ u64 vram_size = adev->gmc.visible_vram_size;
+
+ adev->mman.drv_vram_usage_va = NULL;
+ adev->mman.drv_vram_usage_reserved_bo = NULL;
+
+ if (adev->mman.drv_vram_usage_size == 0 ||
+ adev->mman.drv_vram_usage_size > vram_size)
+ return 0;
+
+ return amdgpu_bo_create_kernel_at(adev,
+ adev->mman.drv_vram_usage_start_offset,
+ adev->mman.drv_vram_usage_size,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &adev->mman.drv_vram_usage_reserved_bo,
+ &adev->mman.drv_vram_usage_va);
+}
+
/*
* Memoy training reservation functions
*/
@@ -1731,6 +1768,14 @@ int amdgpu_ttm_init(struct amdgpu_device *adev)
}
/*
+ *The reserved vram for driver must be pinned to the specified
+ *place on the VRAM, so reserve it early.
+ */
+ r = amdgpu_ttm_drv_reserve_vram_init(adev);
+ if (r)
+ return r;
+
+ /*
* only NAVI10 and onwards ASIC support for IP discovery.
* If IP discovery enabled, a block of memory should be
* reserved for IP discovey.
@@ -1855,6 +1900,7 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev)
amdgpu_bo_free_kernel(&adev->mman.sdma_access_bo, NULL,
&adev->mman.sdma_access_ptr);
amdgpu_ttm_fw_reserve_vram_fini(adev);
+ amdgpu_ttm_drv_reserve_vram_fini(adev);
if (drm_dev_enter(adev_to_drm(adev), &idx)) {
@@ -1936,7 +1982,9 @@ static int amdgpu_ttm_prepare_job(struct amdgpu_device *adev,
AMDGPU_IB_POOL_DELAYED;
int r;
- r = amdgpu_job_alloc_with_ib(adev, num_dw * 4, pool, job);
+ r = amdgpu_job_alloc_with_ib(adev, &adev->mman.entity,
+ AMDGPU_FENCE_OWNER_UNDEFINED,
+ num_dw * 4, pool, job);
if (r)
return r;
@@ -1946,17 +1994,11 @@ static int amdgpu_ttm_prepare_job(struct amdgpu_device *adev,
adev->gart.bo);
(*job)->vm_needs_flush = true;
}
- if (resv) {
- r = amdgpu_sync_resv(adev, &(*job)->sync, resv,
- AMDGPU_SYNC_ALWAYS,
- AMDGPU_FENCE_OWNER_UNDEFINED);
- if (r) {
- DRM_ERROR("sync failed (%d).\n", r);
- amdgpu_job_free(*job);
- return r;
- }
- }
- return 0;
+ if (!resv)
+ return 0;
+
+ return drm_sched_job_add_resv_dependencies(&(*job)->base, resv,
+ DMA_RESV_USAGE_BOOKKEEP);
}
int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset,
@@ -2001,8 +2043,7 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset,
if (direct_submit)
r = amdgpu_job_submit_direct(job, ring, fence);
else
- r = amdgpu_job_submit(job, &adev->mman.entity,
- AMDGPU_FENCE_OWNER_UNDEFINED, fence);
+ *fence = amdgpu_job_submit(job);
if (r)
goto error_free;
@@ -2047,16 +2088,8 @@ static int amdgpu_ttm_fill_mem(struct amdgpu_ring *ring, uint32_t src_data,
amdgpu_ring_pad_ib(ring, &job->ibs[0]);
WARN_ON(job->ibs[0].length_dw > num_dw);
- r = amdgpu_job_submit(job, &adev->mman.entity,
- AMDGPU_FENCE_OWNER_UNDEFINED, fence);
- if (r)
- goto error_free;
-
+ *fence = amdgpu_job_submit(job);
return 0;
-
-error_free:
- amdgpu_job_free(job);
- return r;
}
int amdgpu_fill_buffer(struct amdgpu_bo *bo,
@@ -2272,9 +2305,9 @@ static ssize_t amdgpu_iomem_read(struct file *f, char __user *buf,
if (p->mapping != adev->mman.bdev.dev_mapping)
return -EPERM;
- ptr = kmap(p);
+ ptr = kmap_local_page(p);
r = copy_to_user(buf, ptr + off, bytes);
- kunmap(p);
+ kunmap_local(ptr);
if (r)
return -EFAULT;
@@ -2323,9 +2356,9 @@ static ssize_t amdgpu_iomem_write(struct file *f, const char __user *buf,
if (p->mapping != adev->mman.bdev.dev_mapping)
return -EPERM;
- ptr = kmap(p);
+ ptr = kmap_local_page(p);
r = copy_from_user(ptr + off, buf, bytes);
- kunmap(p);
+ kunmap_local(ptr);
if (r)
return -EFAULT;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
index a37207011a69..b4d8ba2789f3 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h
@@ -86,6 +86,12 @@ struct amdgpu_mman {
struct amdgpu_bo *fw_vram_usage_reserved_bo;
void *fw_vram_usage_va;
+ /* driver VRAM reservation */
+ u64 drv_vram_usage_start_offset;
+ u64 drv_vram_usage_size;
+ struct amdgpu_bo *drv_vram_usage_reserved_bo;
+ void *drv_vram_usage_va;
+
/* PAGE_SIZE'd BO for process memory r/w over SDMA. */
struct amdgpu_bo *sdma_access_bo;
void *sdma_access_ptr;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
index 1c36235b4539..552e06929229 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
@@ -125,6 +125,7 @@ enum psp_fw_type {
PSP_FW_TYPE_PSP_INTF_DRV,
PSP_FW_TYPE_PSP_DBG_DRV,
PSP_FW_TYPE_PSP_RAS_DRV,
+ PSP_FW_TYPE_MAX_INDEX,
};
/* version_major=2, version_minor=0 */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
index aad3c8b4c810..f76c19fc0392 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.c
@@ -22,6 +22,59 @@
*/
#include "amdgpu.h"
+#include "umc_v6_7.h"
+
+static int amdgpu_umc_convert_error_address(struct amdgpu_device *adev,
+ struct ras_err_data *err_data, uint64_t err_addr,
+ uint32_t ch_inst, uint32_t umc_inst)
+{
+ switch (adev->ip_versions[UMC_HWIP][0]) {
+ case IP_VERSION(6, 7, 0):
+ umc_v6_7_convert_error_address(adev,
+ err_data, err_addr, ch_inst, umc_inst);
+ break;
+ default:
+ dev_warn(adev->dev,
+ "UMC address to Physical address translation is not supported\n");
+ return AMDGPU_RAS_FAIL;
+ }
+
+ return AMDGPU_RAS_SUCCESS;
+}
+
+int amdgpu_umc_page_retirement_mca(struct amdgpu_device *adev,
+ uint64_t err_addr, uint32_t ch_inst, uint32_t umc_inst)
+{
+ struct ras_err_data err_data = {0, 0, 0, NULL};
+ int ret = AMDGPU_RAS_FAIL;
+
+ err_data.err_addr =
+ kcalloc(adev->umc.max_ras_err_cnt_per_query,
+ sizeof(struct eeprom_table_record), GFP_KERNEL);
+ if (!err_data.err_addr) {
+ dev_warn(adev->dev,
+ "Failed to alloc memory for umc error record in MCA notifier!\n");
+ return AMDGPU_RAS_FAIL;
+ }
+
+ /*
+ * Translate UMC channel address to Physical address
+ */
+ ret = amdgpu_umc_convert_error_address(adev, &err_data, err_addr,
+ ch_inst, umc_inst);
+ if (ret)
+ goto out;
+
+ if (amdgpu_bad_page_threshold != 0) {
+ amdgpu_ras_add_bad_pages(adev, err_data.err_addr,
+ err_data.err_addr_cnt);
+ amdgpu_ras_save_bad_pages(adev);
+ }
+
+out:
+ kfree(err_data.err_addr);
+ return ret;
+}
static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev,
void *ras_error_status,
@@ -112,23 +165,29 @@ static int amdgpu_umc_do_page_retirement(struct amdgpu_device *adev,
return AMDGPU_RAS_SUCCESS;
}
-int amdgpu_umc_poison_handler(struct amdgpu_device *adev,
- void *ras_error_status,
- bool reset)
+int amdgpu_umc_poison_handler(struct amdgpu_device *adev, bool reset)
{
- int ret;
- struct ras_err_data *err_data = (struct ras_err_data *)ras_error_status;
- struct ras_common_if head = {
- .block = AMDGPU_RAS_BLOCK__UMC,
- };
- struct ras_manager *obj = amdgpu_ras_find_obj(adev, &head);
+ int ret = AMDGPU_RAS_SUCCESS;
- ret =
- amdgpu_umc_do_page_retirement(adev, ras_error_status, NULL, reset);
+ 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);
- if (ret == AMDGPU_RAS_SUCCESS && obj) {
- obj->err_data.ue_count += err_data->ue_count;
- obj->err_data.ce_count += err_data->ce_count;
+ 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) {
+ /* 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;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h
index e46439274f3a..a6951160f13a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h
@@ -51,9 +51,6 @@ struct amdgpu_umc_ras {
struct amdgpu_ras_block_object ras_block;
void (*err_cnt_init)(struct amdgpu_device *adev);
bool (*query_ras_poison_mode)(struct amdgpu_device *adev);
- void (*convert_ras_error_address)(struct amdgpu_device *adev,
- struct ras_err_data *err_data, uint64_t err_addr,
- uint32_t ch_inst, uint32_t umc_inst);
void (*ecc_info_query_ras_error_count)(struct amdgpu_device *adev,
void *ras_error_status);
void (*ecc_info_query_ras_error_address)(struct amdgpu_device *adev,
@@ -86,9 +83,7 @@ struct amdgpu_umc {
};
int amdgpu_umc_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block);
-int amdgpu_umc_poison_handler(struct amdgpu_device *adev,
- void *ras_error_status,
- bool reset);
+int amdgpu_umc_poison_handler(struct amdgpu_device *adev, bool reset);
int amdgpu_umc_process_ecc_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry);
@@ -101,4 +96,6 @@ void amdgpu_umc_fill_error_record(struct ras_err_data *err_data,
int amdgpu_umc_process_ras_data_cb(struct amdgpu_device *adev,
void *ras_error_status,
struct amdgpu_iv_entry *entry);
+int amdgpu_umc_page_retirement_mca(struct amdgpu_device *adev,
+ uint64_t err_addr, uint32_t ch_inst, uint32_t umc_inst);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index 6eac649499d3..e00bb654e24b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -1132,7 +1132,9 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,
unsigned offset_idx = 0;
unsigned offset[3] = { UVD_BASE_SI, 0, 0 };
- r = amdgpu_job_alloc_with_ib(adev, 64, direct ? AMDGPU_IB_POOL_DIRECT :
+ r = amdgpu_job_alloc_with_ib(ring->adev, &adev->uvd.entity,
+ AMDGPU_FENCE_OWNER_UNDEFINED,
+ 64, direct ? AMDGPU_IB_POOL_DIRECT :
AMDGPU_IB_POOL_DELAYED, &job);
if (r)
return r;
@@ -1175,16 +1177,13 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo,
if (r)
goto err_free;
} else {
- r = amdgpu_sync_resv(adev, &job->sync, bo->tbo.base.resv,
- AMDGPU_SYNC_ALWAYS,
- AMDGPU_FENCE_OWNER_UNDEFINED);
+ r = drm_sched_job_add_resv_dependencies(&job->base,
+ bo->tbo.base.resv,
+ DMA_RESV_USAGE_KERNEL);
if (r)
goto err_free;
- r = amdgpu_job_submit(job, &adev->uvd.entity,
- AMDGPU_FENCE_OWNER_UNDEFINED, &f);
- if (r)
- goto err_free;
+ f = amdgpu_job_submit(job);
}
amdgpu_bo_reserve(bo, true);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
index 02cb3a12dd76..b239e874f2d5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -450,8 +450,10 @@ static int amdgpu_vce_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
uint64_t addr;
int i, r;
- r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
- AMDGPU_IB_POOL_DIRECT, &job);
+ r = amdgpu_job_alloc_with_ib(ring->adev, &ring->adev->vce.entity,
+ AMDGPU_FENCE_OWNER_UNDEFINED,
+ ib_size_dw * 4, AMDGPU_IB_POOL_DIRECT,
+ &job);
if (r)
return r;
@@ -538,7 +540,9 @@ static int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
struct dma_fence *f = NULL;
int i, r;
- r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
+ r = amdgpu_job_alloc_with_ib(ring->adev, &ring->adev->vce.entity,
+ AMDGPU_FENCE_OWNER_UNDEFINED,
+ ib_size_dw * 4,
direct ? AMDGPU_IB_POOL_DIRECT :
AMDGPU_IB_POOL_DELAYED, &job);
if (r)
@@ -570,8 +574,7 @@ static int amdgpu_vce_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
if (direct)
r = amdgpu_job_submit_direct(job, ring, &f);
else
- r = amdgpu_job_submit(job, &ring->adev->vce.entity,
- AMDGPU_FENCE_OWNER_UNDEFINED, &f);
+ f = amdgpu_job_submit(job);
if (r)
goto err;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index ce64ca1c6e66..b1622ac9949f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -603,15 +603,16 @@ static int amdgpu_vcn_dec_send_msg(struct amdgpu_ring *ring,
struct amdgpu_ib *ib_msg,
struct dma_fence **fence)
{
+ u64 addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr);
struct amdgpu_device *adev = ring->adev;
struct dma_fence *f = NULL;
struct amdgpu_job *job;
struct amdgpu_ib *ib;
- uint64_t addr = AMDGPU_GPU_PAGE_ALIGN(ib_msg->gpu_addr);
int i, r;
- r = amdgpu_job_alloc_with_ib(adev, 64,
- AMDGPU_IB_POOL_DIRECT, &job);
+ r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
+ 64, AMDGPU_IB_POOL_DIRECT,
+ &job);
if (r)
goto err;
@@ -790,8 +791,9 @@ static int amdgpu_vcn_dec_sw_send_msg(struct amdgpu_ring *ring,
if (sq)
ib_size_dw += 8;
- r = amdgpu_job_alloc_with_ib(adev, ib_size_dw * 4,
- AMDGPU_IB_POOL_DIRECT, &job);
+ r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
+ ib_size_dw * 4, AMDGPU_IB_POOL_DIRECT,
+ &job);
if (r)
goto err;
@@ -919,8 +921,9 @@ static int amdgpu_vcn_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t hand
if (sq)
ib_size_dw += 8;
- r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
- AMDGPU_IB_POOL_DIRECT, &job);
+ r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
+ ib_size_dw * 4, AMDGPU_IB_POOL_DIRECT,
+ &job);
if (r)
return r;
@@ -985,8 +988,9 @@ static int amdgpu_vcn_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t han
if (sq)
ib_size_dw += 8;
- r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
- AMDGPU_IB_POOL_DIRECT, &job);
+ r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL,
+ ib_size_dw * 4, AMDGPU_IB_POOL_DIRECT,
+ &job);
if (r)
return r;
@@ -1251,3 +1255,20 @@ int amdgpu_vcn_process_poison_irq(struct amdgpu_device *adev,
return 0;
}
+
+void amdgpu_vcn_set_ras_funcs(struct amdgpu_device *adev)
+{
+ if (!adev->vcn.ras)
+ return;
+
+ amdgpu_ras_register_ras_block(adev, &adev->vcn.ras->ras_block);
+
+ strcpy(adev->vcn.ras->ras_block.ras_comm.name, "vcn");
+ adev->vcn.ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__VCN;
+ adev->vcn.ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__POISON;
+ adev->vcn.ras_if = &adev->vcn.ras->ras_block.ras_comm;
+
+ /* If don't define special ras_late_init function, use default ras_late_init */
+ if (!adev->vcn.ras->ras_block.ras_late_init)
+ adev->vcn.ras->ras_block.ras_late_init = amdgpu_ras_block_late_init;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index 253ea6b159df..dbb8d68a30c6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -399,5 +399,6 @@ void amdgpu_debugfs_vcn_fwlog_init(struct amdgpu_device *adev,
int amdgpu_vcn_process_poison_irq(struct amdgpu_device *adev,
struct amdgpu_irq_src *source,
struct amdgpu_iv_entry *entry);
+void amdgpu_vcn_set_ras_funcs(struct amdgpu_device *adev);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
index c73abe54d974..15544f262ec1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
@@ -64,6 +64,10 @@ void amdgpu_virt_init_setting(struct amdgpu_device *adev)
ddev->driver_features &= ~DRIVER_ATOMIC;
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;
+
}
void amdgpu_virt_kiq_reg_write_reg_wait(struct amdgpu_device *adev,
@@ -424,11 +428,17 @@ static void amdgpu_virt_add_bad_page(struct amdgpu_device *adev,
struct eeprom_table_record bp;
uint64_t retired_page;
uint32_t bp_idx, bp_cnt;
+ void *vram_usage_va = NULL;
+
+ if (adev->mman.fw_vram_usage_va)
+ vram_usage_va = adev->mman.fw_vram_usage_va;
+ else
+ vram_usage_va = adev->mman.drv_vram_usage_va;
if (bp_block_size) {
bp_cnt = bp_block_size / sizeof(uint64_t);
for (bp_idx = 0; bp_idx < bp_cnt; bp_idx++) {
- retired_page = *(uint64_t *)(adev->mman.fw_vram_usage_va +
+ retired_page = *(uint64_t *)(vram_usage_va +
bp_block_offset + bp_idx * sizeof(uint64_t));
bp.retired_page = retired_page;
@@ -639,7 +649,9 @@ void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev)
adev->virt.fw_reserve.p_vf2pf = NULL;
adev->virt.vf2pf_update_interval_ms = 0;
- if (adev->mman.fw_vram_usage_va != NULL) {
+ if (adev->mman.fw_vram_usage_va && adev->mman.drv_vram_usage_va) {
+ DRM_WARN("Currently fw_vram and drv_vram should not have values at the same time!");
+ } else if (adev->mman.fw_vram_usage_va || adev->mman.drv_vram_usage_va) {
/* go through this logic in ip_init and reset to init workqueue*/
amdgpu_virt_exchange_data(adev);
@@ -662,32 +674,40 @@ void amdgpu_virt_exchange_data(struct amdgpu_device *adev)
uint32_t bp_block_size = 0;
struct amd_sriov_msg_pf2vf_info *pf2vf_v2 = NULL;
- if (adev->mman.fw_vram_usage_va != NULL) {
-
- adev->virt.fw_reserve.p_pf2vf =
- (struct amd_sriov_msg_pf2vf_info_header *)
- (adev->mman.fw_vram_usage_va + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB << 10));
- adev->virt.fw_reserve.p_vf2pf =
- (struct amd_sriov_msg_vf2pf_info_header *)
- (adev->mman.fw_vram_usage_va + (AMD_SRIOV_MSG_VF2PF_OFFSET_KB << 10));
+ if (adev->mman.fw_vram_usage_va || adev->mman.drv_vram_usage_va) {
+ if (adev->mman.fw_vram_usage_va) {
+ adev->virt.fw_reserve.p_pf2vf =
+ (struct amd_sriov_msg_pf2vf_info_header *)
+ (adev->mman.fw_vram_usage_va + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB << 10));
+ adev->virt.fw_reserve.p_vf2pf =
+ (struct amd_sriov_msg_vf2pf_info_header *)
+ (adev->mman.fw_vram_usage_va + (AMD_SRIOV_MSG_VF2PF_OFFSET_KB << 10));
+ } else if (adev->mman.drv_vram_usage_va) {
+ adev->virt.fw_reserve.p_pf2vf =
+ (struct amd_sriov_msg_pf2vf_info_header *)
+ (adev->mman.drv_vram_usage_va + (AMD_SRIOV_MSG_PF2VF_OFFSET_KB << 10));
+ adev->virt.fw_reserve.p_vf2pf =
+ (struct amd_sriov_msg_vf2pf_info_header *)
+ (adev->mman.drv_vram_usage_va + (AMD_SRIOV_MSG_VF2PF_OFFSET_KB << 10));
+ }
amdgpu_virt_read_pf2vf_data(adev);
amdgpu_virt_write_vf2pf_data(adev);
/* bad page handling for version 2 */
if (adev->virt.fw_reserve.p_pf2vf->version == 2) {
- pf2vf_v2 = (struct amd_sriov_msg_pf2vf_info *)adev->virt.fw_reserve.p_pf2vf;
+ pf2vf_v2 = (struct amd_sriov_msg_pf2vf_info *)adev->virt.fw_reserve.p_pf2vf;
- bp_block_offset = ((uint64_t)pf2vf_v2->bp_block_offset_low & 0xFFFFFFFF) |
- ((((uint64_t)pf2vf_v2->bp_block_offset_high) << 32) & 0xFFFFFFFF00000000);
- bp_block_size = pf2vf_v2->bp_block_size;
+ bp_block_offset = ((uint64_t)pf2vf_v2->bp_block_offset_low & 0xFFFFFFFF) |
+ ((((uint64_t)pf2vf_v2->bp_block_offset_high) << 32) & 0xFFFFFFFF00000000);
+ bp_block_size = pf2vf_v2->bp_block_size;
- if (bp_block_size && !adev->virt.ras_init_done)
- amdgpu_virt_init_ras_err_handler_data(adev);
+ if (bp_block_size && !adev->virt.ras_init_done)
+ amdgpu_virt_init_ras_err_handler_data(adev);
- if (adev->virt.ras_init_done)
- amdgpu_virt_add_bad_page(adev, bp_block_offset, bp_block_size);
- }
+ if (adev->virt.ras_init_done)
+ amdgpu_virt_add_bad_page(adev, bp_block_offset, bp_block_size);
+ }
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
index 49c4347d154c..2b9d806e23af 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
@@ -75,6 +75,8 @@ struct amdgpu_vf_error_buffer {
uint64_t data[AMDGPU_VF_ERROR_ENTRY_SIZE];
};
+enum idh_request;
+
/**
* struct amdgpu_virt_ops - amdgpu device virt operations
*/
@@ -84,7 +86,8 @@ struct amdgpu_virt_ops {
int (*req_init_data)(struct amdgpu_device *adev);
int (*reset_gpu)(struct amdgpu_device *adev);
int (*wait_reset)(struct amdgpu_device *adev);
- void (*trans_msg)(struct amdgpu_device *adev, u32 req, u32 data1, u32 data2, u32 data3);
+ void (*trans_msg)(struct amdgpu_device *adev, enum idh_request req,
+ u32 data1, u32 data2, u32 data3);
};
/*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
index 500a1dc4fe02..53ff91fc6cf6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
@@ -498,7 +498,7 @@ static int amdgpu_vkms_sw_init(void *handle)
adev_to_drm(adev)->mode_config.preferred_depth = 24;
adev_to_drm(adev)->mode_config.prefer_shadow = 1;
- adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
+ adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;
adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;
@@ -513,6 +513,10 @@ static int amdgpu_vkms_sw_init(void *handle)
return r;
}
+ r = drm_vblank_init(adev_to_drm(adev), adev->mode_info.num_crtc);
+ if (r)
+ return r;
+
drm_kms_helper_poll_init(adev_to_drm(adev));
adev->mode_info.mode_config_initialized = true;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 003aa9e47085..c05cff979004 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -45,22 +45,43 @@
/**
* DOC: GPUVM
*
- * GPUVM is similar to the legacy gart on older asics, however
- * rather than there being a single global gart table
- * for the entire GPU, there are multiple VM page tables active
- * at any given time. The VM page tables can contain a mix
- * vram pages and system memory pages and system memory pages
+ * GPUVM is the MMU functionality provided on the GPU.
+ * GPUVM is similar to the legacy GART on older asics, however
+ * rather than there being a single global GART table
+ * for the entire GPU, there can be multiple GPUVM page tables active
+ * at any given time. The GPUVM page tables can contain a mix
+ * VRAM pages and system pages (both memory and MMIO) and system pages
* can be mapped as snooped (cached system pages) or unsnooped
* (uncached system pages).
- * Each VM has an ID associated with it and there is a page table
- * associated with each VMID. When executing a command buffer,
- * the kernel tells the ring what VMID to use for that command
+ *
+ * Each active GPUVM has an ID associated with it and there is a page table
+ * linked with each VMID. When executing a command buffer,
+ * the kernel tells the engine what VMID to use for that command
* buffer. VMIDs are allocated dynamically as commands are submitted.
* The userspace drivers maintain their own address space and the kernel
* sets up their pages tables accordingly when they submit their
* command buffers and a VMID is assigned.
- * Cayman/Trinity support up to 8 active VMs at any given time;
- * SI supports 16.
+ * The hardware supports up to 16 active GPUVMs at any given time.
+ *
+ * Each GPUVM is represented by a 1-2 or 1-5 level page table, depending
+ * on the ASIC family. GPUVM supports RWX attributes on each page as well
+ * as other features such as encryption and caching attributes.
+ *
+ * VMID 0 is special. It is the GPUVM used for the kernel driver. In
+ * addition to an aperture managed by a page table, VMID 0 also has
+ * several other apertures. There is an aperture for direct access to VRAM
+ * and there is a legacy AGP aperture which just forwards accesses directly
+ * to the matching system physical addresses (or IOVAs when an IOMMU is
+ * present). These apertures provide direct access to these memories without
+ * incurring the overhead of a page table. VMID 0 is used by the kernel
+ * driver for tasks like memory management.
+ *
+ * GPU clients (i.e., engines on the GPU) use GPUVM VMIDs to access memory.
+ * For user applications, each application can have their own unique GPUVM
+ * address space. The application manages the address space and the kernel
+ * driver manages the GPUVM page tables for each process. If an GPU client
+ * accesses an invalid page, it will generate a GPU page fault, similar to
+ * accessing an invalid page on a CPU.
*/
#define START(node) ((node)->start)
@@ -541,6 +562,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
if (!vm_flush_needed && !gds_switch_needed && !need_pipe_sync)
return 0;
+ amdgpu_ring_ib_begin(ring);
if (ring->funcs->init_cond_exec)
patch_offset = amdgpu_ring_init_cond_exec(ring);
@@ -601,6 +623,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
amdgpu_ring_emit_switch_buffer(ring);
amdgpu_ring_emit_switch_buffer(ring);
}
+ amdgpu_ring_ib_end(ring);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c
index 69e105fa41f6..59cf64216fbb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c
@@ -47,6 +47,32 @@ static int amdgpu_vm_sdma_map_table(struct amdgpu_bo_vm *table)
return r;
}
+/* Allocate a new job for @count PTE updates */
+static int amdgpu_vm_sdma_alloc_job(struct amdgpu_vm_update_params *p,
+ unsigned int count)
+{
+ enum amdgpu_ib_pool_type pool = p->immediate ? AMDGPU_IB_POOL_IMMEDIATE
+ : AMDGPU_IB_POOL_DELAYED;
+ struct drm_sched_entity *entity = p->immediate ? &p->vm->immediate
+ : &p->vm->delayed;
+ unsigned int ndw;
+ int r;
+
+ /* estimate how many dw we need */
+ ndw = AMDGPU_VM_SDMA_MIN_NUM_DW;
+ if (p->pages_addr)
+ ndw += count * 2;
+ ndw = min(ndw, AMDGPU_VM_SDMA_MAX_NUM_DW);
+
+ r = amdgpu_job_alloc_with_ib(p->adev, entity, AMDGPU_FENCE_OWNER_VM,
+ ndw * 4, pool, &p->job);
+ if (r)
+ return r;
+
+ p->num_dw_left = ndw;
+ return 0;
+}
+
/**
* amdgpu_vm_sdma_prepare - prepare SDMA command submission
*
@@ -61,21 +87,22 @@ static int amdgpu_vm_sdma_prepare(struct amdgpu_vm_update_params *p,
struct dma_resv *resv,
enum amdgpu_sync_mode sync_mode)
{
- enum amdgpu_ib_pool_type pool = p->immediate ? AMDGPU_IB_POOL_IMMEDIATE
- : AMDGPU_IB_POOL_DELAYED;
- unsigned int ndw = AMDGPU_VM_SDMA_MIN_NUM_DW;
+ struct amdgpu_sync sync;
int r;
- r = amdgpu_job_alloc_with_ib(p->adev, ndw * 4, pool, &p->job);
+ r = amdgpu_vm_sdma_alloc_job(p, 0);
if (r)
return r;
- p->num_dw_left = ndw;
-
if (!resv)
return 0;
- return amdgpu_sync_resv(p->adev, &p->job->sync, resv, sync_mode, p->vm);
+ amdgpu_sync_create(&sync);
+ r = amdgpu_sync_resv(p->adev, &sync, resv, sync_mode, p->vm);
+ if (!r)
+ r = amdgpu_sync_push_to_job(&sync, p->job);
+ amdgpu_sync_free(&sync);
+ return r;
}
/**
@@ -91,20 +118,16 @@ static int amdgpu_vm_sdma_commit(struct amdgpu_vm_update_params *p,
struct dma_fence **fence)
{
struct amdgpu_ib *ib = p->job->ibs;
- struct drm_sched_entity *entity;
struct amdgpu_ring *ring;
struct dma_fence *f;
- int r;
- entity = p->immediate ? &p->vm->immediate : &p->vm->delayed;
- ring = container_of(entity->rq->sched, struct amdgpu_ring, sched);
+ ring = container_of(p->vm->delayed.rq->sched, struct amdgpu_ring,
+ sched);
WARN_ON(ib->length_dw == 0);
amdgpu_ring_pad_ib(ring, ib);
WARN_ON(ib->length_dw > p->num_dw_left);
- r = amdgpu_job_submit(p->job, entity, AMDGPU_FENCE_OWNER_VM, &f);
- if (r)
- goto error;
+ f = amdgpu_job_submit(p->job);
if (p->unlocked) {
struct dma_fence *tmp = dma_fence_get(f);
@@ -127,10 +150,6 @@ static int amdgpu_vm_sdma_commit(struct amdgpu_vm_update_params *p,
}
dma_fence_put(f);
return 0;
-
-error:
- amdgpu_job_free(p->job);
- return r;
}
/**
@@ -210,8 +229,6 @@ static int amdgpu_vm_sdma_update(struct amdgpu_vm_update_params *p,
uint64_t flags)
{
struct amdgpu_bo *bo = &vmbo->bo;
- enum amdgpu_ib_pool_type pool = p->immediate ? AMDGPU_IB_POOL_IMMEDIATE
- : AMDGPU_IB_POOL_DELAYED;
struct dma_resv_iter cursor;
unsigned int i, ndw, nptes;
struct dma_fence *fence;
@@ -221,7 +238,7 @@ static int amdgpu_vm_sdma_update(struct amdgpu_vm_update_params *p,
/* Wait for PD/PT moves to be completed */
dma_resv_iter_begin(&cursor, bo->tbo.base.resv, DMA_RESV_USAGE_KERNEL);
dma_resv_for_each_fence_unlocked(&cursor, fence) {
- r = amdgpu_sync_fence(&p->job->sync, fence);
+ r = drm_sched_job_add_dependency(&p->job->base, fence);
if (r) {
dma_resv_iter_end(&cursor);
return r;
@@ -238,19 +255,9 @@ static int amdgpu_vm_sdma_update(struct amdgpu_vm_update_params *p,
if (r)
return r;
- /* estimate how many dw we need */
- ndw = 32;
- if (p->pages_addr)
- ndw += count * 2;
- ndw = max(ndw, AMDGPU_VM_SDMA_MIN_NUM_DW);
- ndw = min(ndw, AMDGPU_VM_SDMA_MAX_NUM_DW);
-
- r = amdgpu_job_alloc_with_ib(p->adev, ndw * 4, pool,
- &p->job);
+ r = amdgpu_vm_sdma_alloc_job(p, count);
if (r)
return r;
-
- p->num_dw_left = ndw;
}
if (!p->pages_addr) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
index 80dd1343594c..faa12146635c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c
@@ -439,7 +439,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
/* Allocate blocks in desired range */
vres->flags |= DRM_BUDDY_RANGE_ALLOCATION;
- remaining_size = (u64)vres->base.num_pages << PAGE_SHIFT;
+ remaining_size = (u64)vres->base.size;
mutex_lock(&mgr->lock);
while (remaining_size) {
@@ -498,7 +498,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
LIST_HEAD(temp);
trim_list = &vres->blocks;
- original_size = (u64)vres->base.num_pages << PAGE_SHIFT;
+ original_size = (u64)vres->base.size;
/*
* If size value is rounded up to min_block_size, trim the last
@@ -533,8 +533,8 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man,
amdgpu_vram_mgr_block_size(block);
start >>= PAGE_SHIFT;
- if (start > vres->base.num_pages)
- start -= vres->base.num_pages;
+ if (start > PFN_UP(vres->base.size))
+ start -= PFN_UP(vres->base.size);
else
start = 0;
vres->base.start = max(vres->base.start, start);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
index 47159e9a0884..4b9e7b050ccd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
@@ -386,7 +386,6 @@ struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev)
if (ret) {
dev_err(adev->dev, "XGMI: failed initializing kobject for xgmi hive\n");
kobject_put(&hive->kobj);
- kfree(hive);
hive = NULL;
goto pro_end;
}
@@ -410,7 +409,6 @@ struct amdgpu_hive_info *amdgpu_get_xgmi_hive(struct amdgpu_device *adev)
dev_err(adev->dev, "XGMI: failed initializing reset domain for xgmi hive\n");
ret = -ENOMEM;
kobject_put(&hive->kobj);
- kfree(hive);
hive = NULL;
goto pro_end;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
index 6be9ac2b9c5b..18ae9433e463 100644
--- a/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
+++ b/drivers/gpu/drm/amd/amdgpu/atombios_encoders.c
@@ -2081,8 +2081,11 @@ amdgpu_atombios_encoder_get_lcd_info(struct amdgpu_encoder *encoder)
}
}
record += fake_edid_record->ucFakeEDIDLength ?
- fake_edid_record->ucFakeEDIDLength + 2 :
- sizeof(ATOM_FAKE_EDID_PATCH_RECORD);
+ struct_size(fake_edid_record,
+ ucFakeEDIDString,
+ fake_edid_record->ucFakeEDIDLength) :
+ /* empty fake edid record must be 3 bytes long */
+ sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1;
break;
case LCD_PANEL_RESOLUTION_RECORD_TYPE:
panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record;
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
index 288fce7dc0ed..248f1a4e915f 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
@@ -21,6 +21,7 @@
*
*/
+#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_vblank.h>
@@ -2800,8 +2801,6 @@ static int dce_v10_0_sw_init(void *handle)
adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;
- adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
-
r = amdgpu_display_modeset_create_props(adev);
if (r)
return r;
@@ -2830,6 +2829,17 @@ static int dce_v10_0_sw_init(void *handle)
if (r)
return r;
+ /* Disable vblank IRQs aggressively for power-saving */
+ /* XXX: can this be enabled for DC? */
+ adev_to_drm(adev)->vblank_disable_immediate = true;
+
+ r = drm_vblank_init(adev_to_drm(adev), adev->mode_info.num_crtc);
+ if (r)
+ return r;
+
+ INIT_WORK(&adev->hotplug_work,
+ amdgpu_display_hotplug_work_func);
+
drm_kms_helper_poll_init(adev_to_drm(adev));
adev->mode_info.mode_config_initialized = true;
@@ -2892,6 +2902,8 @@ static int dce_v10_0_hw_fini(void *handle)
dce_v10_0_pageflip_interrupt_fini(adev);
+ flush_work(&adev->hotplug_work);
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
index cbe5250b31cb..cd9c19060d89 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
@@ -21,6 +21,7 @@
*
*/
+#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_vblank.h>
@@ -2918,8 +2919,6 @@ static int dce_v11_0_sw_init(void *handle)
adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;
- adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
-
r = amdgpu_display_modeset_create_props(adev);
if (r)
return r;
@@ -2949,6 +2948,17 @@ static int dce_v11_0_sw_init(void *handle)
if (r)
return r;
+ /* Disable vblank IRQs aggressively for power-saving */
+ /* XXX: can this be enabled for DC? */
+ adev_to_drm(adev)->vblank_disable_immediate = true;
+
+ r = drm_vblank_init(adev_to_drm(adev), adev->mode_info.num_crtc);
+ if (r)
+ return r;
+
+ INIT_WORK(&adev->hotplug_work,
+ amdgpu_display_hotplug_work_func);
+
drm_kms_helper_poll_init(adev_to_drm(adev));
adev->mode_info.mode_config_initialized = true;
@@ -3022,6 +3032,8 @@ static int dce_v11_0_hw_fini(void *handle)
dce_v11_0_pageflip_interrupt_fini(adev);
+ flush_work(&adev->hotplug_work);
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
index b1c44fab074f..76323deecc58 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
@@ -23,6 +23,7 @@
#include <linux/pci.h>
+#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_vblank.h>
@@ -2675,7 +2676,6 @@ static int dce_v6_0_sw_init(void *handle)
adev_to_drm(adev)->mode_config.preferred_depth = 24;
adev_to_drm(adev)->mode_config.prefer_shadow = 1;
adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;
- adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
r = amdgpu_display_modeset_create_props(adev);
if (r)
@@ -2706,6 +2706,18 @@ static int dce_v6_0_sw_init(void *handle)
if (r)
return r;
+ /* Disable vblank IRQs aggressively for power-saving */
+ /* XXX: can this be enabled for DC? */
+ adev_to_drm(adev)->vblank_disable_immediate = true;
+
+ r = drm_vblank_init(adev_to_drm(adev), adev->mode_info.num_crtc);
+ if (r)
+ return r;
+
+ /* Pre-DCE11 */
+ INIT_WORK(&adev->hotplug_work,
+ amdgpu_display_hotplug_work_func);
+
drm_kms_helper_poll_init(adev_to_drm(adev));
return r;
@@ -2764,6 +2776,8 @@ static int dce_v6_0_hw_fini(void *handle)
dce_v6_0_pageflip_interrupt_fini(adev);
+ flush_work(&adev->hotplug_work);
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
index a22b45c92792..01cf3ab111cb 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
@@ -21,6 +21,7 @@
*
*/
+#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_vblank.h>
@@ -2701,8 +2702,6 @@ static int dce_v8_0_sw_init(void *handle)
adev_to_drm(adev)->mode_config.fb_modifiers_not_supported = true;
- adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
-
r = amdgpu_display_modeset_create_props(adev);
if (r)
return r;
@@ -2731,6 +2730,18 @@ static int dce_v8_0_sw_init(void *handle)
if (r)
return r;
+ /* Disable vblank IRQs aggressively for power-saving */
+ /* XXX: can this be enabled for DC? */
+ adev_to_drm(adev)->vblank_disable_immediate = true;
+
+ r = drm_vblank_init(adev_to_drm(adev), adev->mode_info.num_crtc);
+ if (r)
+ return r;
+
+ /* Pre-DCE11 */
+ INIT_WORK(&adev->hotplug_work,
+ amdgpu_display_hotplug_work_func);
+
drm_kms_helper_poll_init(adev_to_drm(adev));
adev->mode_info.mode_config_initialized = true;
@@ -2791,6 +2802,8 @@ static int dce_v8_0_hw_fini(void *handle)
dce_v8_0_pageflip_interrupt_fini(adev);
+ flush_work(&adev->hotplug_work);
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index af94ac580d3e..49d34c7bbf20 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -4453,8 +4453,6 @@ static void gfx_v10_0_gpu_early_init(struct amdgpu_device *adev)
{
u32 gb_addr_config;
- adev->gfx.funcs = &gfx_v10_0_gfx_funcs;
-
switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 1):
@@ -6911,6 +6909,8 @@ static int gfx_v10_0_kiq_init_queue(struct amdgpu_ring *ring)
mutex_unlock(&adev->srbm_mutex);
} else {
memset((void *)mqd, 0, sizeof(*mqd));
+ if (amdgpu_sriov_vf(adev) && adev->in_suspend)
+ amdgpu_ring_clear_ring(ring);
mutex_lock(&adev->srbm_mutex);
nv_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
amdgpu_ring_init_mqd(ring);
@@ -7593,6 +7593,8 @@ static int gfx_v10_0_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ adev->gfx.funcs = &gfx_v10_0_gfx_funcs;
+
switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 1):
@@ -8489,7 +8491,7 @@ static void gfx_v10_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
control |= ib->length_dw | (vmid << 24);
- if ((amdgpu_sriov_vf(ring->adev) || amdgpu_mcbp) && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) {
+ if (amdgpu_mcbp && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) {
control |= INDIRECT_BUFFER_PRE_ENB(1);
if (flags & AMDGPU_IB_PREEMPTED)
@@ -8664,7 +8666,7 @@ static void gfx_v10_0_ring_emit_cntxcntl(struct amdgpu_ring *ring,
{
uint32_t dw2 = 0;
- if (amdgpu_mcbp || amdgpu_sriov_vf(ring->adev))
+ if (amdgpu_mcbp)
gfx_v10_0_ring_emit_ce_meta(ring,
(!amdgpu_sriov_vf(ring->adev) && flags & AMDGPU_IB_PREEMPTED) ? true : false);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index 0fecc5bf45bc..a56c6e106d00 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -77,6 +77,10 @@ MODULE_FIRMWARE("amdgpu/gc_11_0_3_pfp.bin");
MODULE_FIRMWARE("amdgpu/gc_11_0_3_me.bin");
MODULE_FIRMWARE("amdgpu/gc_11_0_3_mec.bin");
MODULE_FIRMWARE("amdgpu/gc_11_0_3_rlc.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_0_4_pfp.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_0_4_me.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_0_4_mec.bin");
+MODULE_FIRMWARE("amdgpu/gc_11_0_4_rlc.bin");
static const struct soc15_reg_golden golden_settings_gc_11_0_1[] =
{
@@ -262,6 +266,7 @@ static void gfx_v11_0_init_golden_registers(struct amdgpu_device *adev)
{
switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(11, 0, 1):
+ case IP_VERSION(11, 0, 4):
soc15_program_register_sequence(adev,
golden_settings_gc_11_0_1,
(const u32)ARRAY_SIZE(golden_settings_gc_11_0_1));
@@ -843,7 +848,6 @@ static const struct amdgpu_gfx_funcs gfx_v11_0_gfx_funcs = {
static int gfx_v11_0_gpu_early_init(struct amdgpu_device *adev)
{
- adev->gfx.funcs = &gfx_v11_0_gfx_funcs;
switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(11, 0, 0):
@@ -856,6 +860,7 @@ static int gfx_v11_0_gpu_early_init(struct amdgpu_device *adev)
adev->gfx.config.sc_earlyz_tile_fifo_size = 0x4C0;
break;
case IP_VERSION(11, 0, 1):
+ case IP_VERSION(11, 0, 4):
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;
@@ -1285,6 +1290,7 @@ static int gfx_v11_0_sw_init(void *handle)
case IP_VERSION(11, 0, 1):
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
+ case IP_VERSION(11, 0, 4):
adev->gfx.me.num_me = 1;
adev->gfx.me.num_pipe_per_me = 1;
adev->gfx.me.num_queue_per_pipe = 1;
@@ -1626,7 +1632,8 @@ static void gfx_v11_0_constants_init(struct amdgpu_device *adev)
u32 tmp;
int i;
- WREG32_FIELD15_PREREG(GC, 0, GRBM_CNTL, READ_TIMEOUT, 0xff);
+ if (!amdgpu_sriov_vf(adev))
+ WREG32_FIELD15_PREREG(GC, 0, GRBM_CNTL, READ_TIMEOUT, 0xff);
gfx_v11_0_setup_rb(adev);
gfx_v11_0_get_cu_info(adev, &adev->gfx.cu_info);
@@ -2486,7 +2493,8 @@ static int gfx_v11_0_wait_for_rlc_autoload_complete(struct amdgpu_device *adev)
for (i = 0; i < adev->usec_timeout; i++) {
cp_status = RREG32_SOC15(GC, 0, regCP_STAT);
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(11, 0, 1))
+ if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(11, 0, 1) ||
+ adev->ip_versions[GC_HWIP][0] == IP_VERSION(11, 0, 4))
bootload_status = RREG32_SOC15(GC, 0,
regRLC_RLCS_BOOTLOAD_STATUS_gc_11_0_1);
else
@@ -4004,6 +4012,8 @@ static int gfx_v11_0_kiq_init_queue(struct amdgpu_ring *ring)
mutex_unlock(&adev->srbm_mutex);
} else {
memset((void *)mqd, 0, sizeof(*mqd));
+ if (amdgpu_sriov_vf(adev) && adev->in_suspend)
+ amdgpu_ring_clear_ring(ring);
mutex_lock(&adev->srbm_mutex);
soc21_grbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
amdgpu_ring_init_mqd(ring);
@@ -4390,7 +4400,6 @@ static int gfx_v11_0_hw_fini(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int r;
- uint32_t tmp;
amdgpu_irq_put(adev, &adev->gfx.priv_reg_irq, 0);
amdgpu_irq_put(adev, &adev->gfx.priv_inst_irq, 0);
@@ -4409,15 +4418,14 @@ static int gfx_v11_0_hw_fini(void *handle)
amdgpu_mes_kiq_hw_fini(adev);
}
- if (amdgpu_sriov_vf(adev)) {
- gfx_v11_0_cp_gfx_enable(adev, false);
- /* Program KIQ position of RLC_CP_SCHEDULERS during destroy */
- tmp = RREG32_SOC15(GC, 0, regRLC_CP_SCHEDULERS);
- tmp &= 0xffffff00;
- WREG32_SOC15(GC, 0, regRLC_CP_SCHEDULERS, tmp);
-
+ if (amdgpu_sriov_vf(adev))
+ /* Remove the steps disabling CPG and clearing KIQ position,
+ * so that CP could perform IDLE-SAVE during switch. Those
+ * steps are necessary to avoid a DMAR error in gfx9 but it is
+ * not reproduced on gfx11.
+ */
return 0;
- }
+
gfx_v11_0_cp_enable(adev, false);
gfx_v11_0_enable_gui_idle_interrupt(adev, false);
@@ -4656,6 +4664,8 @@ static int gfx_v11_0_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ adev->gfx.funcs = &gfx_v11_0_gfx_funcs;
+
adev->gfx.num_gfx_rings = GFX11_NUM_GFX_RINGS;
adev->gfx.num_compute_rings = min(amdgpu_gfx_get_num_kcq(adev),
AMDGPU_MAX_COMPUTE_RINGS);
@@ -4673,6 +4683,26 @@ static int gfx_v11_0_early_init(void *handle)
return 0;
}
+static int gfx_v11_0_ras_late_init(void *handle)
+{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct ras_common_if *gfx_common_if;
+ int ret;
+
+ gfx_common_if = kzalloc(sizeof(struct ras_common_if), GFP_KERNEL);
+ if (!gfx_common_if)
+ return -ENOMEM;
+
+ gfx_common_if->block = AMDGPU_RAS_BLOCK__GFX;
+
+ ret = amdgpu_ras_feature_enable(adev, gfx_common_if, true);
+ if (ret)
+ dev_warn(adev->dev, "Failed to enable gfx11 ras feature\n");
+
+ kfree(gfx_common_if);
+ return 0;
+}
+
static int gfx_v11_0_late_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
@@ -4686,6 +4716,12 @@ static int gfx_v11_0_late_init(void *handle)
if (r)
return r;
+ if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(11, 0, 3)) {
+ r = gfx_v11_0_ras_late_init(handle);
+ if (r)
+ return r;
+ }
+
return 0;
}
@@ -5022,6 +5058,7 @@ static void gfx_v11_cntl_power_gating(struct amdgpu_device *adev, bool enable)
if (enable && (adev->pg_flags & AMD_PG_SUPPORT_GFX_PG)) {
switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(11, 0, 1):
+ case IP_VERSION(11, 0, 4):
WREG32_SOC15(GC, 0, regRLC_PG_DELAY_3, RLC_PG_DELAY_3_DEFAULT_GC_11_0_1);
break;
default:
@@ -5055,6 +5092,7 @@ static int gfx_v11_0_set_powergating_state(void *handle,
amdgpu_gfx_off_ctrl(adev, enable);
break;
case IP_VERSION(11, 0, 1):
+ case IP_VERSION(11, 0, 4):
gfx_v11_cntl_pg(adev, enable);
amdgpu_gfx_off_ctrl(adev, enable);
break;
@@ -5078,6 +5116,7 @@ static int gfx_v11_0_set_clockgating_state(void *handle,
case IP_VERSION(11, 0, 1):
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
+ case IP_VERSION(11, 0, 4):
gfx_v11_0_update_gfx_clock_gating(adev,
state == AMD_CG_STATE_GATE);
break;
@@ -5299,7 +5338,7 @@ static void gfx_v11_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
control |= ib->length_dw | (vmid << 24);
- if ((amdgpu_sriov_vf(ring->adev) || amdgpu_mcbp) && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) {
+ if (amdgpu_mcbp && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) {
control |= INDIRECT_BUFFER_PRE_ENB(1);
if (flags & AMDGPU_IB_PREEMPTED)
@@ -6060,6 +6099,7 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_gfx = {
.align_mask = 0xff,
.nop = PACKET3(PACKET3_NOP, 0x3FFF),
.support_64bit_ptrs = true,
+ .secure_submission_supported = true,
.vmhub = AMDGPU_GFXHUB_0,
.get_rptr = gfx_v11_0_ring_get_rptr_gfx,
.get_wptr = gfx_v11_0_ring_get_wptr_gfx,
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
index 7f0b18b0d4c4..d47135606e3e 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
@@ -4643,6 +4643,8 @@ static int gfx_v8_0_kiq_init_queue(struct amdgpu_ring *ring)
memset((void *)mqd, 0, sizeof(struct vi_mqd_allocation));
((struct vi_mqd_allocation *)mqd)->dynamic_cu_mask = 0xFFFFFFFF;
((struct vi_mqd_allocation *)mqd)->dynamic_rb_mask = 0xFFFFFFFF;
+ if (amdgpu_sriov_vf(adev) && adev->in_suspend)
+ amdgpu_ring_clear_ring(ring);
mutex_lock(&adev->srbm_mutex);
vi_srbm_select(adev, ring->me, ring->pipe, ring->queue, 0);
gfx_v8_0_mqd_init(ring);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
index 0320be4a5fc6..f202b45c413c 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -47,6 +47,7 @@
#include "amdgpu_ras.h"
+#include "amdgpu_ring_mux.h"
#include "gfx_v9_4.h"
#include "gfx_v9_0.h"
#include "gfx_v9_4_2.h"
@@ -56,6 +57,7 @@
#include "asic_reg/gc/gc_9_0_default.h"
#define GFX9_NUM_GFX_RINGS 1
+#define GFX9_NUM_SW_GFX_RINGS 2
#define GFX9_MEC_HPD_SIZE 4096
#define RLCG_UCODE_LOADING_START_ADDRESS 0x00002000L
#define RLC_SAVE_RESTORE_ADDR_STARTING_OFFSET 0x00000000L
@@ -753,7 +755,7 @@ static void gfx_v9_0_set_rlc_funcs(struct amdgpu_device *adev);
static int gfx_v9_0_get_cu_info(struct amdgpu_device *adev,
struct amdgpu_cu_info *cu_info);
static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev);
-static void gfx_v9_0_ring_emit_de_meta(struct amdgpu_ring *ring);
+static void gfx_v9_0_ring_emit_de_meta(struct amdgpu_ring *ring, bool resume);
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);
@@ -826,9 +828,10 @@ static void gfx_v9_0_kiq_unmap_queues(struct amdgpu_ring *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);
+ amdgpu_ring_write(kiq_ring, lower_32_bits(ring->wptr & ring->buf_mask));
+ amdgpu_ring_write(kiq_ring, 0);
+ amdgpu_ring_write(kiq_ring, 0);
+
} else {
amdgpu_ring_write(kiq_ring, 0);
amdgpu_ring_write(kiq_ring, 0);
@@ -1564,7 +1567,7 @@ static void gfx_v9_0_init_always_on_cu_mask(struct amdgpu_device *adev)
mask = 1;
cu_bitmap = 0;
counter = 0;
- gfx_v9_0_select_se_sh(adev, i, j, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff);
for (k = 0; k < adev->gfx.config.max_cu_per_sh; k ++) {
if (cu_info->bitmap[i][j] & mask) {
@@ -1583,7 +1586,7 @@ static void gfx_v9_0_init_always_on_cu_mask(struct amdgpu_device *adev)
cu_info->ao_cu_bitmap[i][j] = cu_bitmap;
}
}
- gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex);
}
@@ -1605,7 +1608,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*/
- gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
WREG32_SOC15(GC, 0, mmRLC_LB_INIT_CU_MASK, 0xffffffff);
/* set mmRLC_LB_PARAMS = 0x003F_1006 */
@@ -1654,7 +1657,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*/
- gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
WREG32_SOC15(GC, 0, mmRLC_LB_INIT_CU_MASK, 0xffffffff);
/* set mmRLC_LB_PARAMS = 0x003F_1006 */
@@ -1919,8 +1922,6 @@ static int gfx_v9_0_gpu_early_init(struct amdgpu_device *adev)
u32 gb_addr_config;
int err;
- adev->gfx.funcs = &gfx_v9_0_gfx_funcs;
-
switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(9, 0, 1):
adev->gfx.config.max_hw_contexts = 8;
@@ -2105,6 +2106,7 @@ static int gfx_v9_0_sw_init(void *handle)
struct amdgpu_ring *ring;
struct amdgpu_kiq *kiq;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ unsigned int hw_prio;
switch (adev->ip_versions[GC_HWIP][0]) {
case IP_VERSION(9, 0, 1):
@@ -2188,6 +2190,9 @@ static int gfx_v9_0_sw_init(void *handle)
sprintf(ring->name, "gfx_%d", i);
ring->use_doorbell = true;
ring->doorbell_index = adev->doorbell_index.gfx_ring0 << 1;
+
+ /* disable scheduler on the real ring */
+ ring->no_scheduler = true;
r = amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq,
AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP,
AMDGPU_RING_PRIO_DEFAULT, NULL);
@@ -2195,6 +2200,41 @@ static int gfx_v9_0_sw_init(void *handle)
return r;
}
+ /* set up the software rings */
+ if (adev->gfx.num_gfx_rings) {
+ for (i = 0; i < GFX9_NUM_SW_GFX_RINGS; i++) {
+ ring = &adev->gfx.sw_gfx_ring[i];
+ ring->ring_obj = NULL;
+ sprintf(ring->name, amdgpu_sw_ring_name(i));
+ ring->use_doorbell = true;
+ ring->doorbell_index = adev->doorbell_index.gfx_ring0 << 1;
+ ring->is_sw_ring = true;
+ hw_prio = amdgpu_sw_ring_priority(i);
+ r = amdgpu_ring_init(adev, ring, 1024, &adev->gfx.eop_irq,
+ AMDGPU_CP_IRQ_GFX_ME0_PIPE0_EOP, hw_prio,
+ NULL);
+ if (r)
+ return r;
+ ring->wptr = 0;
+ }
+
+ /* init the muxer and add software rings */
+ r = amdgpu_ring_mux_init(&adev->gfx.muxer, &adev->gfx.gfx_ring[0],
+ GFX9_NUM_SW_GFX_RINGS);
+ if (r) {
+ DRM_ERROR("amdgpu_ring_mux_init failed(%d)\n", r);
+ return r;
+ }
+ for (i = 0; i < GFX9_NUM_SW_GFX_RINGS; i++) {
+ r = amdgpu_ring_mux_add_sw_ring(&adev->gfx.muxer,
+ &adev->gfx.sw_gfx_ring[i]);
+ if (r) {
+ DRM_ERROR("amdgpu_ring_mux_add_sw_ring failed(%d)\n", r);
+ return r;
+ }
+ }
+ }
+
/* set up the compute queues - allocate horizontally across pipes */
ring_id = 0;
for (i = 0; i < adev->gfx.mec.num_mec; ++i) {
@@ -2245,6 +2285,12 @@ static int gfx_v9_0_sw_fini(void *handle)
int i;
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ if (adev->gfx.num_gfx_rings) {
+ for (i = 0; i < GFX9_NUM_SW_GFX_RINGS; i++)
+ amdgpu_ring_fini(&adev->gfx.sw_gfx_ring[i]);
+ amdgpu_ring_mux_fini(&adev->gfx.muxer);
+ }
+
for (i = 0; i < adev->gfx.num_gfx_rings; i++)
amdgpu_ring_fini(&adev->gfx.gfx_ring[i]);
for (i = 0; i < adev->gfx.num_compute_rings; i++)
@@ -2324,13 +2370,13 @@ 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++) {
- gfx_v9_0_select_se_sh(adev, i, j, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff);
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);
}
}
- gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex);
adev->gfx.config.backend_enable_mask = active_rbs;
@@ -2467,14 +2513,14 @@ 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++) {
- gfx_v9_0_select_se_sh(adev, i, j, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff);
for (k = 0; k < adev->usec_timeout; k++) {
if (RREG32_SOC15(GC, 0, mmRLC_SERDES_CU_MASTER_BUSY) == 0)
break;
udelay(1);
}
if (k == adev->usec_timeout) {
- gfx_v9_0_select_se_sh(adev, 0xffffffff,
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff,
0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex);
DRM_INFO("Timeout wait for RLC serdes %u,%u\n",
@@ -2483,7 +2529,7 @@ static void gfx_v9_0_wait_for_rlc_serdes(struct amdgpu_device *adev)
}
}
}
- gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex);
mask = RLC_SERDES_NONCU_MASTER_BUSY__SE_MASTER_BUSY_MASK |
@@ -3583,6 +3629,8 @@ static int gfx_v9_0_kiq_init_queue(struct amdgpu_ring *ring)
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;
+ 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);
gfx_v9_0_mqd_init(ring);
@@ -4539,6 +4587,8 @@ static int gfx_v9_0_early_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ adev->gfx.funcs = &gfx_v9_0_gfx_funcs;
+
if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 1) ||
adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2))
adev->gfx.num_gfx_rings = 0;
@@ -5155,11 +5205,17 @@ static void gfx_v9_0_ring_emit_ib_gfx(struct amdgpu_ring *ring,
control |= ib->length_dw | (vmid << 24);
- if (amdgpu_sriov_vf(ring->adev) && (ib->flags & AMDGPU_IB_FLAG_PREEMPT)) {
+ if (ib->flags & AMDGPU_IB_FLAG_PREEMPT) {
control |= INDIRECT_BUFFER_PRE_ENB(1);
+ if (flags & AMDGPU_IB_PREEMPTED)
+ control |= INDIRECT_BUFFER_PRE_RESUME(1);
+
if (!(ib->flags & AMDGPU_IB_FLAG_CE) && vmid)
- gfx_v9_0_ring_emit_de_meta(ring);
+ gfx_v9_0_ring_emit_de_meta(ring,
+ (!amdgpu_sriov_vf(ring->adev) &&
+ flags & AMDGPU_IB_PREEMPTED) ?
+ true : false);
}
amdgpu_ring_write(ring, header);
@@ -5214,17 +5270,24 @@ static void gfx_v9_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr,
bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT;
bool int_sel = flags & AMDGPU_FENCE_FLAG_INT;
bool writeback = flags & AMDGPU_FENCE_FLAG_TC_WB_ONLY;
+ bool exec = flags & AMDGPU_FENCE_FLAG_EXEC;
+ uint32_t dw2 = 0;
/* 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)));
+
+ if (writeback) {
+ dw2 = EOP_TC_NC_ACTION_EN;
+ } else {
+ dw2 = EOP_TCL1_ACTION_EN | EOP_TC_ACTION_EN |
+ EOP_TC_MD_ACTION_EN;
+ }
+ dw2 |= EOP_TC_WB_ACTION_EN | EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) |
+ EVENT_INDEX(5);
+ if (exec)
+ dw2 |= EOP_EXEC;
+
+ amdgpu_ring_write(ring, dw2);
amdgpu_ring_write(ring, DATA_SEL(write64bit ? 2 : 1) | INT_SEL(int_sel ? 2 : 0));
/*
@@ -5329,33 +5392,135 @@ static void gfx_v9_ring_emit_sb(struct amdgpu_ring *ring)
amdgpu_ring_write(ring, 0);
}
-static void gfx_v9_0_ring_emit_ce_meta(struct amdgpu_ring *ring)
+static void gfx_v9_0_ring_emit_ce_meta(struct amdgpu_ring *ring, bool resume)
{
+ struct amdgpu_device *adev = ring->adev;
struct v9_ce_ib_state ce_payload = {0};
- uint64_t csa_addr;
+ uint64_t offset, ce_payload_gpu_addr;
+ void *ce_payload_cpu_addr;
int cnt;
cnt = (sizeof(ce_payload) >> 2) + 4 - 2;
- csa_addr = amdgpu_csa_vaddr(ring->adev);
+
+ if (ring->is_mes_queue) {
+ offset = offsetof(struct amdgpu_mes_ctx_meta_data,
+ gfx[0].gfx_meta_data) +
+ offsetof(struct v9_gfx_meta_data, ce_payload);
+ ce_payload_gpu_addr =
+ amdgpu_mes_ctx_get_offs_gpu_addr(ring, offset);
+ ce_payload_cpu_addr =
+ amdgpu_mes_ctx_get_offs_cpu_addr(ring, offset);
+ } else {
+ offset = offsetof(struct v9_gfx_meta_data, ce_payload);
+ ce_payload_gpu_addr = amdgpu_csa_vaddr(ring->adev) + offset;
+ ce_payload_cpu_addr = adev->virt.csa_cpu_addr + offset;
+ }
amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, cnt));
amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(2) |
WRITE_DATA_DST_SEL(8) |
WR_CONFIRM) |
WRITE_DATA_CACHE_POLICY(0));
- amdgpu_ring_write(ring, lower_32_bits(csa_addr + offsetof(struct v9_gfx_meta_data, ce_payload)));
- amdgpu_ring_write(ring, upper_32_bits(csa_addr + offsetof(struct v9_gfx_meta_data, ce_payload)));
- amdgpu_ring_write_multiple(ring, (void *)&ce_payload, sizeof(ce_payload) >> 2);
+ amdgpu_ring_write(ring, lower_32_bits(ce_payload_gpu_addr));
+ amdgpu_ring_write(ring, upper_32_bits(ce_payload_gpu_addr));
+
+ if (resume)
+ amdgpu_ring_write_multiple(ring, ce_payload_cpu_addr,
+ sizeof(ce_payload) >> 2);
+ else
+ amdgpu_ring_write_multiple(ring, (void *)&ce_payload,
+ sizeof(ce_payload) >> 2);
+}
+
+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_ring *kiq_ring = &kiq->ring;
+ unsigned long flags;
+
+ if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
+ return -EINVAL;
+
+ spin_lock_irqsave(&kiq->ring_lock, flags);
+
+ if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size)) {
+ spin_unlock_irqrestore(&kiq->ring_lock, flags);
+ return -ENOMEM;
+ }
+
+ /* assert preemption condition */
+ amdgpu_ring_set_preempt_cond_exec(ring, false);
+
+ ring->trail_seq += 1;
+ amdgpu_ring_alloc(ring, 13);
+ gfx_v9_0_ring_emit_fence(ring, ring->trail_fence_gpu_addr,
+ ring->trail_seq, AMDGPU_FENCE_FLAG_EXEC | AMDGPU_FENCE_FLAG_INT);
+ /*reset the CP_VMID_PREEMPT after trailing fence*/
+ amdgpu_ring_emit_wreg(ring,
+ SOC15_REG_OFFSET(GC, 0, mmCP_VMID_PREEMPT),
+ 0x0);
+
+ /* assert IB preemption, emit the trailing fence */
+ kiq->pmf->kiq_unmap_queues(kiq_ring, ring, PREEMPT_QUEUES_NO_UNMAP,
+ ring->trail_fence_gpu_addr,
+ ring->trail_seq);
+
+ amdgpu_ring_commit(kiq_ring);
+ spin_unlock_irqrestore(&kiq->ring_lock, flags);
+
+ /* poll the trailing fence */
+ for (i = 0; i < adev->usec_timeout; i++) {
+ if (ring->trail_seq ==
+ le32_to_cpu(*ring->trail_fence_cpu_addr))
+ break;
+ udelay(1);
+ }
+
+ if (i >= adev->usec_timeout) {
+ r = -EINVAL;
+ DRM_WARN("ring %d timeout to preempt ib\n", ring->idx);
+ }
+
+ amdgpu_ring_commit(ring);
+
+ /* deassert preemption condition */
+ amdgpu_ring_set_preempt_cond_exec(ring, true);
+ return r;
}
-static void gfx_v9_0_ring_emit_de_meta(struct amdgpu_ring *ring)
+static void gfx_v9_0_ring_emit_de_meta(struct amdgpu_ring *ring, bool resume)
{
+ struct amdgpu_device *adev = ring->adev;
struct v9_de_ib_state de_payload = {0};
- uint64_t csa_addr, gds_addr;
+ uint64_t offset, gds_addr, de_payload_gpu_addr;
+ void *de_payload_cpu_addr;
int cnt;
- csa_addr = amdgpu_csa_vaddr(ring->adev);
- gds_addr = csa_addr + 4096;
+ if (ring->is_mes_queue) {
+ offset = offsetof(struct amdgpu_mes_ctx_meta_data,
+ gfx[0].gfx_meta_data) +
+ offsetof(struct v9_gfx_meta_data, de_payload);
+ de_payload_gpu_addr =
+ amdgpu_mes_ctx_get_offs_gpu_addr(ring, offset);
+ de_payload_cpu_addr =
+ amdgpu_mes_ctx_get_offs_cpu_addr(ring, offset);
+
+ offset = offsetof(struct amdgpu_mes_ctx_meta_data,
+ gfx[0].gds_backup) +
+ offsetof(struct v9_gfx_meta_data, de_payload);
+ gds_addr = amdgpu_mes_ctx_get_offs_gpu_addr(ring, offset);
+ } else {
+ offset = offsetof(struct v9_gfx_meta_data, de_payload);
+ de_payload_gpu_addr = amdgpu_csa_vaddr(ring->adev) + offset;
+ de_payload_cpu_addr = adev->virt.csa_cpu_addr + offset;
+
+ gds_addr = ALIGN(amdgpu_csa_vaddr(ring->adev) +
+ AMDGPU_CSA_SIZE - adev->gds.gds_size,
+ PAGE_SIZE);
+ }
+
de_payload.gds_backup_addrlo = lower_32_bits(gds_addr);
de_payload.gds_backup_addrhi = upper_32_bits(gds_addr);
@@ -5365,9 +5530,15 @@ static void gfx_v9_0_ring_emit_de_meta(struct amdgpu_ring *ring)
WRITE_DATA_DST_SEL(8) |
WR_CONFIRM) |
WRITE_DATA_CACHE_POLICY(0));
- amdgpu_ring_write(ring, lower_32_bits(csa_addr + offsetof(struct v9_gfx_meta_data, de_payload)));
- amdgpu_ring_write(ring, upper_32_bits(csa_addr + offsetof(struct v9_gfx_meta_data, de_payload)));
- amdgpu_ring_write_multiple(ring, (void *)&de_payload, sizeof(de_payload) >> 2);
+ amdgpu_ring_write(ring, lower_32_bits(de_payload_gpu_addr));
+ amdgpu_ring_write(ring, upper_32_bits(de_payload_gpu_addr));
+
+ if (resume)
+ amdgpu_ring_write_multiple(ring, de_payload_cpu_addr,
+ sizeof(de_payload) >> 2);
+ else
+ amdgpu_ring_write_multiple(ring, (void *)&de_payload,
+ sizeof(de_payload) >> 2);
}
static void gfx_v9_0_ring_emit_frame_cntl(struct amdgpu_ring *ring, bool start,
@@ -5383,8 +5554,9 @@ static void gfx_v9_ring_emit_cntxcntl(struct amdgpu_ring *ring, uint32_t flags)
{
uint32_t dw2 = 0;
- if (amdgpu_sriov_vf(ring->adev))
- gfx_v9_0_ring_emit_ce_meta(ring);
+ gfx_v9_0_ring_emit_ce_meta(ring,
+ (!amdgpu_sriov_vf(ring->adev) &&
+ flags & AMDGPU_IB_PREEMPTED) ? true : false);
dw2 |= 0x80000000; /* set load_enable otherwise this package is just NOPs */
if (flags & AMDGPU_HAVE_CTX_SWITCH) {
@@ -5710,7 +5882,12 @@ static int gfx_v9_0_eop_irq(struct amdgpu_device *adev,
switch (me_id) {
case 0:
- amdgpu_fence_process(&adev->gfx.gfx_ring[0]);
+ if (adev->gfx.num_gfx_rings &&
+ !amdgpu_mcbp_handle_trailing_fence_irq(&adev->gfx.muxer)) {
+ /* Fence signals are handled on the software rings*/
+ for (i = 0; i < GFX9_NUM_SW_GFX_RINGS; i++)
+ amdgpu_fence_process(&adev->gfx.sw_gfx_ring[i]);
+ }
break;
case 1:
case 2:
@@ -6482,7 +6659,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++) {
- gfx_v9_0_select_se_sh(adev, j, 0x0, k);
+ amdgpu_gfx_select_se_sh(adev, j, 0x0, k);
RREG32(SOC15_REG_ENTRY_OFFSET(gfx_v9_0_edc_counter_regs[i]));
}
}
@@ -6544,7 +6721,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++) {
- gfx_v9_0_select_se_sh(adev, j, 0, k);
+ amdgpu_gfx_select_se_sh(adev, j, 0, k);
reg_value =
RREG32(SOC15_REG_ENTRY_OFFSET(gfx_v9_0_edc_counter_regs[i]));
if (reg_value)
@@ -6559,7 +6736,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;
- gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex);
gfx_v9_0_query_utc_edc_status(adev, err_data);
@@ -6707,6 +6884,62 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_gfx = {
.emit_cntxcntl = gfx_v9_ring_emit_cntxcntl,
.init_cond_exec = gfx_v9_0_ring_emit_init_cond_exec,
.patch_cond_exec = gfx_v9_0_ring_emit_patch_cond_exec,
+ .preempt_ib = gfx_v9_0_ring_preempt_ib,
+ .emit_frame_cntl = gfx_v9_0_ring_emit_frame_cntl,
+ .emit_wreg = gfx_v9_0_ring_emit_wreg,
+ .emit_reg_wait = gfx_v9_0_ring_emit_reg_wait,
+ .emit_reg_write_reg_wait = gfx_v9_0_ring_emit_reg_write_reg_wait,
+ .soft_recovery = gfx_v9_0_ring_soft_recovery,
+ .emit_mem_sync = gfx_v9_0_emit_mem_sync,
+};
+
+static const struct amdgpu_ring_funcs gfx_v9_0_sw_ring_funcs_gfx = {
+ .type = AMDGPU_RING_TYPE_GFX,
+ .align_mask = 0xff,
+ .nop = PACKET3(PACKET3_NOP, 0x3FFF),
+ .support_64bit_ptrs = true,
+ .secure_submission_supported = true,
+ .vmhub = AMDGPU_GFXHUB_0,
+ .get_rptr = amdgpu_sw_ring_get_rptr_gfx,
+ .get_wptr = amdgpu_sw_ring_get_wptr_gfx,
+ .set_wptr = amdgpu_sw_ring_set_wptr_gfx,
+ .emit_frame_size = /* totally 242 maximum if 16 IBs */
+ 5 + /* COND_EXEC */
+ 7 + /* PIPELINE_SYNC */
+ SOC15_FLUSH_GPU_TLB_NUM_WREG * 5 +
+ SOC15_FLUSH_GPU_TLB_NUM_REG_WAIT * 7 +
+ 2 + /* VM_FLUSH */
+ 8 + /* FENCE for VM_FLUSH */
+ 20 + /* GDS switch */
+ 4 + /* double SWITCH_BUFFER,
+ * the first COND_EXEC jump to the place just
+ * prior to this double SWITCH_BUFFER
+ */
+ 5 + /* COND_EXEC */
+ 7 + /* HDP_flush */
+ 4 + /* VGT_flush */
+ 14 + /* CE_META */
+ 31 + /* DE_META */
+ 3 + /* CNTX_CTRL */
+ 5 + /* HDP_INVL */
+ 8 + 8 + /* FENCE x2 */
+ 2 + /* SWITCH_BUFFER */
+ 7, /* gfx_v9_0_emit_mem_sync */
+ .emit_ib_size = 4, /* gfx_v9_0_ring_emit_ib_gfx */
+ .emit_ib = gfx_v9_0_ring_emit_ib_gfx,
+ .emit_fence = gfx_v9_0_ring_emit_fence,
+ .emit_pipeline_sync = gfx_v9_0_ring_emit_pipeline_sync,
+ .emit_vm_flush = gfx_v9_0_ring_emit_vm_flush,
+ .emit_gds_switch = gfx_v9_0_ring_emit_gds_switch,
+ .emit_hdp_flush = gfx_v9_0_ring_emit_hdp_flush,
+ .test_ring = gfx_v9_0_ring_test_ring,
+ .test_ib = gfx_v9_0_ring_test_ib,
+ .insert_nop = amdgpu_sw_ring_insert_nop,
+ .pad_ib = amdgpu_ring_generic_pad_ib,
+ .emit_switch_buffer = gfx_v9_ring_emit_sb,
+ .emit_cntxcntl = gfx_v9_ring_emit_cntxcntl,
+ .init_cond_exec = gfx_v9_0_ring_emit_init_cond_exec,
+ .patch_cond_exec = gfx_v9_0_ring_emit_patch_cond_exec,
.emit_frame_cntl = gfx_v9_0_ring_emit_frame_cntl,
.emit_wreg = gfx_v9_0_ring_emit_wreg,
.emit_reg_wait = gfx_v9_0_ring_emit_reg_wait,
@@ -6792,6 +7025,11 @@ static void gfx_v9_0_set_ring_funcs(struct amdgpu_device *adev)
for (i = 0; i < adev->gfx.num_gfx_rings; i++)
adev->gfx.gfx_ring[i].funcs = &gfx_v9_0_ring_funcs_gfx;
+ if (adev->gfx.num_gfx_rings) {
+ for (i = 0; i < GFX9_NUM_SW_GFX_RINGS; i++)
+ adev->gfx.sw_gfx_ring[i].funcs = &gfx_v9_0_sw_ring_funcs_gfx;
+ }
+
for (i = 0; i < adev->gfx.num_compute_rings; i++)
adev->gfx.compute_ring[i].funcs = &gfx_v9_0_ring_funcs_compute;
}
@@ -6963,7 +7201,7 @@ static int gfx_v9_0_get_cu_info(struct amdgpu_device *adev,
mask = 1;
ao_bitmap = 0;
counter = 0;
- gfx_v9_0_select_se_sh(adev, i, j, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, i, j, 0xffffffff);
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);
@@ -6996,7 +7234,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;
}
}
- gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
+ amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex);
cu_info->number = active_cu_number;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c
index 8cf53e039c11..3f8676d23a5e 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v2_1.c
@@ -397,6 +397,9 @@ static void gfxhub_v2_1_gart_disable(struct amdgpu_device *adev)
ENABLE_ADVANCED_DRIVER_MODEL, 0);
WREG32_SOC15(GC, 0, mmGCMC_VM_MX_L1_TLB_CNTL, tmp);
+ if (amdgpu_sriov_vf(adev))
+ return;
+
/* Setup L2 cache */
WREG32_FIELD15(GC, 0, GCVM_L2_CNTL, ENABLE_L2_CACHE, 0);
WREG32_SOC15(GC, 0, mmGCVM_L2_CNTL3, 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 5d3fffd4929f..080ff11ca305 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v3_0_3.c
@@ -154,6 +154,9 @@ static void gfxhub_v3_0_3_init_system_aperture_regs(struct amdgpu_device *adev)
{
uint64_t value;
+ if (amdgpu_sriov_vf(adev))
+ return;
+
/* Disable AGP. */
WREG32_SOC15(GC, 0, regGCMC_VM_AGP_BASE, 0);
WREG32_SOC15(GC, 0, regGCMC_VM_AGP_TOP, 0);
@@ -354,18 +357,6 @@ static void gfxhub_v3_0_3_program_invalidation(struct amdgpu_device *adev)
static int gfxhub_v3_0_3_gart_enable(struct amdgpu_device *adev)
{
- if (amdgpu_sriov_vf(adev)) {
- /*
- * GCMC_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(GC, 0, regGCMC_VM_FB_LOCATION_BASE,
- adev->gmc.vram_start >> 24);
- WREG32_SOC15(GC, 0, regGCMC_VM_FB_LOCATION_TOP,
- adev->gmc.vram_end >> 24);
- }
-
/* GART Enable. */
gfxhub_v3_0_3_init_gart_aperture_regs(adev);
gfxhub_v3_0_3_init_system_aperture_regs(adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
index f513e2c2e964..21e46817d82d 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
@@ -371,7 +371,9 @@ 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(adev, 16 * 4, AMDGPU_IB_POOL_IMMEDIATE,
+ r = amdgpu_job_alloc_with_ib(ring->adev, &adev->mman.entity,
+ AMDGPU_FENCE_OWNER_UNDEFINED,
+ 16 * 4, AMDGPU_IB_POOL_IMMEDIATE,
&job);
if (r)
goto error_alloc;
@@ -380,10 +382,7 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
job->vm_needs_flush = true;
job->ibs->ptr[job->ibs->length_dw++] = ring->funcs->nop;
amdgpu_ring_pad_ib(ring, &job->ibs[0]);
- r = amdgpu_job_submit(job, &adev->mman.entity,
- AMDGPU_FENCE_OWNER_UNDEFINED, &fence);
- if (r)
- goto error_submit;
+ fence = amdgpu_job_submit(job);
mutex_unlock(&adev->mman.gtt_window_lock);
@@ -392,9 +391,6 @@ static void gmc_v10_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
return;
-error_submit:
- amdgpu_job_free(job);
-
error_alloc:
mutex_unlock(&adev->mman.gtt_window_lock);
DRM_ERROR("Error flushing GPU TLB using the SDMA (%d)!\n", r);
@@ -612,6 +608,8 @@ static void gmc_v10_0_get_vm_pte(struct amdgpu_device *adev,
struct amdgpu_bo_va_mapping *mapping,
uint64_t *flags)
{
+ struct amdgpu_bo *bo = mapping->bo_va->base.bo;
+
*flags &= ~AMDGPU_PTE_EXECUTABLE;
*flags |= mapping->flags & AMDGPU_PTE_EXECUTABLE;
@@ -628,6 +626,11 @@ static void gmc_v10_0_get_vm_pte(struct amdgpu_device *adev,
*flags |= AMDGPU_PTE_SYSTEM;
*flags &= ~AMDGPU_PTE_VALID;
}
+
+ if (bo && bo->flags & (AMDGPU_GEM_CREATE_COHERENT |
+ AMDGPU_GEM_CREATE_UNCACHED))
+ *flags = (*flags & ~AMDGPU_PTE_MTYPE_NV10_MASK) |
+ AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
}
static unsigned gmc_v10_0_get_vbios_fb_size(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
index 66dfb574cc7d..4326078689cd 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c
@@ -503,6 +503,8 @@ static void gmc_v11_0_get_vm_pte(struct amdgpu_device *adev,
struct amdgpu_bo_va_mapping *mapping,
uint64_t *flags)
{
+ struct amdgpu_bo *bo = mapping->bo_va->base.bo;
+
*flags &= ~AMDGPU_PTE_EXECUTABLE;
*flags |= mapping->flags & AMDGPU_PTE_EXECUTABLE;
@@ -519,6 +521,11 @@ static void gmc_v11_0_get_vm_pte(struct amdgpu_device *adev,
*flags |= AMDGPU_PTE_SYSTEM;
*flags &= ~AMDGPU_PTE_VALID;
}
+
+ if (bo && bo->flags & (AMDGPU_GEM_CREATE_COHERENT |
+ AMDGPU_GEM_CREATE_UNCACHED))
+ *flags = (*flags & ~AMDGPU_PTE_MTYPE_NV10_MASK) |
+ AMDGPU_PTE_MTYPE_NV10(MTYPE_UC);
}
static unsigned gmc_v11_0_get_vbios_fb_size(struct amdgpu_device *adev)
@@ -551,7 +558,10 @@ static void gmc_v11_0_set_umc_funcs(struct amdgpu_device *adev)
adev->umc.node_inst_num = adev->gmc.num_umc;
adev->umc.max_ras_err_cnt_per_query = UMC_V8_10_TOTAL_CHANNEL_NUM(adev);
adev->umc.channel_offs = UMC_V8_10_PER_CHANNEL_OFFSET;
- adev->umc.channel_idx_tbl = &umc_v8_10_channel_idx_tbl[0][0][0];
+ if (adev->umc.node_inst_num == 4)
+ adev->umc.channel_idx_tbl = &umc_v8_10_channel_idx_tbl_ext0[0][0][0];
+ else
+ adev->umc.channel_idx_tbl = &umc_v8_10_channel_idx_tbl[0][0][0];
adev->umc.ras = &umc_v8_10_ras;
break;
case IP_VERSION(8, 11, 0):
@@ -749,6 +759,7 @@ static int gmc_v11_0_sw_init(void *handle)
case IP_VERSION(11, 0, 1):
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
+ case IP_VERSION(11, 0, 4):
adev->num_vmhubs = 2;
/*
* To fulfill 4-level page support,
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
index 67ca16a8027c..50386eb2eec8 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
@@ -1113,6 +1113,74 @@ static void gmc_v9_0_get_vm_pde(struct amdgpu_device *adev, int level,
}
}
+static void gmc_v9_0_get_coherence_flags(struct amdgpu_device *adev,
+ struct amdgpu_bo *bo,
+ struct amdgpu_bo_va_mapping *mapping,
+ uint64_t *flags)
+{
+ struct amdgpu_device *bo_adev = amdgpu_ttm_adev(bo->tbo.bdev);
+ 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;
+ bool snoop = false;
+
+ switch (adev->ip_versions[GC_HWIP][0]) {
+ case IP_VERSION(9, 4, 1):
+ case IP_VERSION(9, 4, 2):
+ if (is_vram) {
+ if (bo_adev == adev) {
+ if (uncached)
+ mtype = MTYPE_UC;
+ else if (coherent)
+ mtype = MTYPE_CC;
+ else
+ mtype = MTYPE_RW;
+ /* FIXME: is this still needed? Or does
+ * amdgpu_ttm_tt_pde_flags already handle this?
+ */
+ if (adev->ip_versions[GC_HWIP][0] ==
+ IP_VERSION(9, 4, 2) &&
+ adev->gmc.xgmi.connected_to_cpu)
+ snoop = true;
+ } else {
+ if (uncached || coherent)
+ mtype = MTYPE_UC;
+ else
+ mtype = MTYPE_NC;
+ if (mapping->bo_va->is_xgmi)
+ snoop = true;
+ }
+ } else {
+ if (uncached || coherent)
+ mtype = MTYPE_UC;
+ else
+ mtype = MTYPE_NC;
+ /* FIXME: is this still needed? Or does
+ * amdgpu_ttm_tt_pde_flags already handle this?
+ */
+ snoop = true;
+ }
+ break;
+ default:
+ if (uncached || coherent)
+ mtype = MTYPE_UC;
+ else
+ mtype = MTYPE_NC;
+
+ /* FIXME: is this still needed? Or does
+ * amdgpu_ttm_tt_pde_flags already handle this?
+ */
+ if (!is_vram)
+ snoop = true;
+ }
+
+ if (mtype != MTYPE_NC)
+ *flags = (*flags & ~AMDGPU_PTE_MTYPE_VG10_MASK) |
+ AMDGPU_PTE_MTYPE_VG10(mtype);
+ *flags |= snoop ? AMDGPU_PTE_SNOOPED : 0;
+}
+
static void gmc_v9_0_get_vm_pte(struct amdgpu_device *adev,
struct amdgpu_bo_va_mapping *mapping,
uint64_t *flags)
@@ -1128,14 +1196,9 @@ static void gmc_v9_0_get_vm_pte(struct amdgpu_device *adev,
*flags &= ~AMDGPU_PTE_VALID;
}
- if ((adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 1) ||
- adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2)) &&
- !(*flags & AMDGPU_PTE_SYSTEM) &&
- mapping->bo_va->is_xgmi)
- *flags |= AMDGPU_PTE_SNOOPED;
-
- if (adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 4, 2))
- *flags |= mapping->flags & AMDGPU_PTE_SNOOPED;
+ if (mapping->bo_va->base.bo)
+ gmc_v9_0_get_coherence_flags(adev, mapping->bo_va->base.bo,
+ mapping, flags);
}
static unsigned gmc_v9_0_get_vbios_fb_size(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
index f87d0f6ffc93..f2b743a93915 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
@@ -807,16 +807,5 @@ static void jpeg_v2_5_set_ras_funcs(struct amdgpu_device *adev)
break;
}
- if (adev->jpeg.ras) {
- amdgpu_ras_register_ras_block(adev, &adev->jpeg.ras->ras_block);
-
- strcpy(adev->jpeg.ras->ras_block.ras_comm.name, "jpeg");
- adev->jpeg.ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__JPEG;
- adev->jpeg.ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__POISON;
- adev->jpeg.ras_if = &adev->jpeg.ras->ras_block.ras_comm;
-
- /* If don't define special ras_late_init function, use default ras_late_init */
- if (!adev->jpeg.ras->ras_block.ras_late_init)
- adev->jpeg.ras->ras_block.ras_late_init = amdgpu_ras_block_late_init;
- }
+ jpeg_set_ras_funcs(adev);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
index 63b0d0b810ec..3beb731b2ce5 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
@@ -27,6 +27,7 @@
#include "soc15.h"
#include "soc15d.h"
#include "jpeg_v2_0.h"
+#include "jpeg_v4_0.h"
#include "vcn/vcn_4_0_0_offset.h"
#include "vcn/vcn_4_0_0_sh_mask.h"
@@ -38,6 +39,7 @@ static void jpeg_v4_0_set_dec_ring_funcs(struct amdgpu_device *adev);
static void jpeg_v4_0_set_irq_funcs(struct amdgpu_device *adev);
static int jpeg_v4_0_set_powergating_state(void *handle,
enum amd_powergating_state state);
+static void jpeg_v4_0_set_ras_funcs(struct amdgpu_device *adev);
/**
* jpeg_v4_0_early_init - set function pointers
@@ -55,6 +57,7 @@ static int jpeg_v4_0_early_init(void *handle)
jpeg_v4_0_set_dec_ring_funcs(adev);
jpeg_v4_0_set_irq_funcs(adev);
+ jpeg_v4_0_set_ras_funcs(adev);
return 0;
}
@@ -78,6 +81,18 @@ static int jpeg_v4_0_sw_init(void *handle)
if (r)
return r;
+ /* JPEG DJPEG POISON EVENT */
+ r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
+ VCN_4_0__SRCID_DJPEG0_POISON, &adev->jpeg.inst->irq);
+ if (r)
+ return r;
+
+ /* JPEG EJPEG POISON EVENT */
+ r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN,
+ VCN_4_0__SRCID_EJPEG0_POISON, &adev->jpeg.inst->irq);
+ if (r)
+ return r;
+
r = amdgpu_jpeg_sw_init(adev);
if (r)
return r;
@@ -167,6 +182,8 @@ static int jpeg_v4_0_hw_fini(void *handle)
RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS))
jpeg_v4_0_set_powergating_state(adev, AMD_PG_STATE_GATE);
+ amdgpu_irq_put(adev, &adev->jpeg.inst->irq, 0);
+
return 0;
}
@@ -524,6 +541,10 @@ static int jpeg_v4_0_process_interrupt(struct amdgpu_device *adev,
case VCN_4_0__SRCID__JPEG_DECODE:
amdgpu_fence_process(&adev->jpeg.inst->ring_dec);
break;
+ case VCN_4_0__SRCID_DJPEG0_POISON:
+ case VCN_4_0__SRCID_EJPEG0_POISON:
+ amdgpu_jpeg_process_poison_irq(adev, source, entry);
+ break;
default:
DRM_DEV_ERROR(adev->dev, "Unhandled interrupt: %d %d\n",
entry->src_id, entry->src_data[0]);
@@ -607,3 +628,63 @@ const struct amdgpu_ip_block_version jpeg_v4_0_ip_block = {
.rev = 0,
.funcs = &jpeg_v4_0_ip_funcs,
};
+
+static uint32_t jpeg_v4_0_query_poison_by_instance(struct amdgpu_device *adev,
+ uint32_t instance, uint32_t sub_block)
+{
+ uint32_t poison_stat = 0, reg_value = 0;
+
+ switch (sub_block) {
+ case AMDGPU_JPEG_V4_0_JPEG0:
+ reg_value = RREG32_SOC15(JPEG, instance, regUVD_RAS_JPEG0_STATUS);
+ poison_stat = REG_GET_FIELD(reg_value, UVD_RAS_JPEG0_STATUS, POISONED_PF);
+ break;
+ case AMDGPU_JPEG_V4_0_JPEG1:
+ reg_value = RREG32_SOC15(JPEG, instance, regUVD_RAS_JPEG1_STATUS);
+ poison_stat = REG_GET_FIELD(reg_value, UVD_RAS_JPEG1_STATUS, POISONED_PF);
+ break;
+ default:
+ break;
+ }
+
+ if (poison_stat)
+ dev_info(adev->dev, "Poison detected in JPEG%d sub_block%d\n",
+ instance, sub_block);
+
+ return poison_stat;
+}
+
+static bool jpeg_v4_0_query_ras_poison_status(struct amdgpu_device *adev)
+{
+ uint32_t inst = 0, sub = 0, poison_stat = 0;
+
+ for (inst = 0; inst < adev->jpeg.num_jpeg_inst; inst++)
+ for (sub = 0; sub < AMDGPU_JPEG_V4_0_MAX_SUB_BLOCK; sub++)
+ poison_stat +=
+ jpeg_v4_0_query_poison_by_instance(adev, inst, sub);
+
+ return !!poison_stat;
+}
+
+const struct amdgpu_ras_block_hw_ops jpeg_v4_0_ras_hw_ops = {
+ .query_poison_status = jpeg_v4_0_query_ras_poison_status,
+};
+
+static struct amdgpu_jpeg_ras jpeg_v4_0_ras = {
+ .ras_block = {
+ .hw_ops = &jpeg_v4_0_ras_hw_ops,
+ },
+};
+
+static void jpeg_v4_0_set_ras_funcs(struct amdgpu_device *adev)
+{
+ switch (adev->ip_versions[JPEG_HWIP][0]) {
+ case IP_VERSION(4, 0, 0):
+ adev->jpeg.ras = &jpeg_v4_0_ras;
+ break;
+ default:
+ break;
+ }
+
+ jpeg_set_ras_funcs(adev);
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.h b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.h
index f1ed6ccfedca..07d36c2abd6b 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.h
@@ -24,6 +24,13 @@
#ifndef __JPEG_V4_0_H__
#define __JPEG_V4_0_H__
+enum amdgpu_jpeg_v4_0_sub_block {
+ AMDGPU_JPEG_V4_0_JPEG0 = 0,
+ AMDGPU_JPEG_V4_0_JPEG1,
+
+ AMDGPU_JPEG_V4_0_MAX_SUB_BLOCK,
+};
+
extern const struct amdgpu_ip_block_version jpeg_v4_0_ip_block;
#endif /* __JPEG_V4_0_H__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
index 067d10073a56..614394118a53 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v10_1.c
@@ -121,6 +121,10 @@ static int mes_v10_1_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
if (r < 1) {
DRM_ERROR("MES failed to response msg=%d\n",
x_pkt->header.opcode);
+
+ while (halt_if_hws_hang)
+ schedule();
+
return -ETIMEDOUT;
}
@@ -415,10 +419,6 @@ static int mes_v10_1_init_microcode(struct amdgpu_device *adev,
mes_hdr = (const struct mes_firmware_header_v1_0 *)
adev->mes.fw[pipe]->data;
- adev->mes.ucode_fw_version[pipe] =
- le32_to_cpu(mes_hdr->mes_ucode_version);
- adev->mes.ucode_fw_version[pipe] =
- le32_to_cpu(mes_hdr->mes_ucode_data_version);
adev->mes.uc_start_addr[pipe] =
le32_to_cpu(mes_hdr->mes_uc_start_addr_lo) |
((uint64_t)(le32_to_cpu(mes_hdr->mes_uc_start_addr_hi)) << 32);
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
index f141fadd2d86..5459366f49ff 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_v11_0.c
@@ -129,6 +129,10 @@ static int mes_v11_0_submit_pkt_and_poll_completion(struct amdgpu_mes *mes,
if (r < 1) {
DRM_ERROR("MES failed to response msg=%d\n",
x_pkt->header.opcode);
+
+ while (halt_if_hws_hang)
+ schedule();
+
return -ETIMEDOUT;
}
@@ -384,6 +388,7 @@ static int mes_v11_0_set_hw_resources(struct amdgpu_mes *mes)
mes_set_hw_res_pkt.disable_reset = 1;
mes_set_hw_res_pkt.disable_mes_log = 1;
mes_set_hw_res_pkt.use_different_vmid_compute = 1;
+ mes_set_hw_res_pkt.enable_reg_active_poll = 1;
mes_set_hw_res_pkt.oversubscription_timer = 50;
return mes_v11_0_submit_pkt_and_poll_completion(mes,
@@ -485,10 +490,6 @@ static int mes_v11_0_init_microcode(struct amdgpu_device *adev,
mes_hdr = (const struct mes_firmware_header_v1_0 *)
adev->mes.fw[pipe]->data;
- adev->mes.ucode_fw_version[pipe] =
- le32_to_cpu(mes_hdr->mes_ucode_version);
- adev->mes.ucode_fw_version[pipe] =
- le32_to_cpu(mes_hdr->mes_ucode_data_version);
adev->mes.uc_start_addr[pipe] =
le32_to_cpu(mes_hdr->mes_uc_start_addr_lo) |
((uint64_t)(le32_to_cpu(mes_hdr->mes_uc_start_addr_hi)) << 32);
@@ -1253,7 +1254,9 @@ static int mes_v11_0_kiq_hw_fini(struct amdgpu_device *adev)
if (adev->mes.ring.sched.ready)
mes_v11_0_kiq_dequeue_sched(adev);
- mes_v11_0_enable(adev, false);
+ if (!amdgpu_sriov_vf(adev))
+ mes_v11_0_enable(adev, false);
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c
index 998b5d17b271..0e664d0cc8d5 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_0.c
@@ -319,7 +319,7 @@ static void mmhub_v2_0_init_cache_regs(struct amdgpu_device *adev)
tmp = mmMMVM_L2_CNTL5_DEFAULT;
tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL5, L2_CACHE_SMALLK_FRAGMENT_SIZE, 0);
- WREG32_SOC15(GC, 0, mmMMVM_L2_CNTL5, tmp);
+ WREG32_SOC15(MMHUB, 0, mmMMVM_L2_CNTL5, tmp);
}
static void mmhub_v2_0_enable_system_domain(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c
index 1b027d069ab4..4638ea7c2eec 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v2_3.c
@@ -243,7 +243,7 @@ static void mmhub_v2_3_init_cache_regs(struct amdgpu_device *adev)
tmp = mmMMVM_L2_CNTL5_DEFAULT;
tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL5, L2_CACHE_SMALLK_FRAGMENT_SIZE, 0);
- WREG32_SOC15(GC, 0, mmMMVM_L2_CNTL5, tmp);
+ WREG32_SOC15(MMHUB, 0, mmMMVM_L2_CNTL5, tmp);
}
static void mmhub_v2_3_enable_system_domain(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c
index a1d26c4d80b8..16cc82215e2e 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0.c
@@ -275,7 +275,7 @@ static void mmhub_v3_0_init_cache_regs(struct amdgpu_device *adev)
tmp = regMMVM_L2_CNTL5_DEFAULT;
tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL5, L2_CACHE_SMALLK_FRAGMENT_SIZE, 0);
- WREG32_SOC15(GC, 0, regMMVM_L2_CNTL5, tmp);
+ WREG32_SOC15(MMHUB, 0, regMMVM_L2_CNTL5, tmp);
}
static void mmhub_v3_0_enable_system_domain(struct amdgpu_device *adev)
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 e8058edc1d10..6bdf2ef0298d 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_1.c
@@ -269,7 +269,7 @@ static void mmhub_v3_0_1_init_cache_regs(struct amdgpu_device *adev)
tmp = regMMVM_L2_CNTL5_DEFAULT;
tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL5, L2_CACHE_SMALLK_FRAGMENT_SIZE, 0);
- WREG32_SOC15(GC, 0, regMMVM_L2_CNTL5, tmp);
+ WREG32_SOC15(MMHUB, 0, regMMVM_L2_CNTL5, tmp);
}
static void mmhub_v3_0_1_enable_system_domain(struct amdgpu_device *adev)
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 770be0a8f7ce..45465acaa943 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v3_0_2.c
@@ -268,7 +268,7 @@ static void mmhub_v3_0_2_init_cache_regs(struct amdgpu_device *adev)
tmp = regMMVM_L2_CNTL5_DEFAULT;
tmp = REG_SET_FIELD(tmp, MMVM_L2_CNTL5, L2_CACHE_SMALLK_FRAGMENT_SIZE, 0);
- WREG32_SOC15(GC, 0, regMMVM_L2_CNTL5, tmp);
+ WREG32_SOC15(MMHUB, 0, regMMVM_L2_CNTL5, tmp);
}
static void mmhub_v3_0_2_enable_system_domain(struct amdgpu_device *adev)
diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c
index b3fba8dea63c..6853b93ac82e 100644
--- a/drivers/gpu/drm/amd/amdgpu/nv.c
+++ b/drivers/gpu/drm/amd/amdgpu/nv.c
@@ -82,10 +82,10 @@ static const struct amdgpu_video_codecs nv_video_codecs_encode =
/* Navi1x */
static const struct amdgpu_video_codec_info nv_video_codecs_decode_array[] =
{
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4906, 3)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4906, 5)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4906, 4)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)},
{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)},
@@ -100,10 +100,10 @@ static const struct amdgpu_video_codecs nv_video_codecs_decode =
/* Sienna Cichlid */
static const struct amdgpu_video_codec_info sc_video_codecs_decode_array[] =
{
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4906, 3)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4906, 5)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4906, 4)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)},
{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)},
@@ -125,10 +125,10 @@ static struct amdgpu_video_codec_info sriov_sc_video_codecs_encode_array[] =
static struct amdgpu_video_codec_info sriov_sc_video_codecs_decode_array[] =
{
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4906, 3)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4906, 5)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4906, 4)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)},
{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)},
@@ -149,7 +149,7 @@ static struct amdgpu_video_codecs sriov_sc_video_codecs_decode =
/* Beige Goby*/
static const struct amdgpu_video_codec_info bg_video_codecs_decode_array[] = {
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)},
+ {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_VP9, 8192, 4352, 0)},
};
@@ -166,7 +166,7 @@ static const struct amdgpu_video_codecs bg_video_codecs_encode = {
/* Yellow Carp*/
static const struct amdgpu_video_codec_info yc_video_codecs_decode_array[] = {
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)},
+ {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_VP9, 8192, 4352, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)},
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
index ed2293686f0d..9de46fa8f46c 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c
@@ -126,32 +126,6 @@ out:
return err;
}
-static int psp_v10_0_ring_init(struct psp_context *psp,
- enum psp_ring_type ring_type)
-{
- int ret = 0;
- struct psp_ring *ring;
- struct amdgpu_device *adev = psp->adev;
-
- ring = &psp->km_ring;
-
- ring->ring_type = ring_type;
-
- /* allocate 4k Page of Local Frame Buffer memory for ring */
- ring->ring_size = 0x1000;
- ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_VRAM,
- &adev->firmware.rbuf,
- &ring->ring_mem_mc_addr,
- (void **)&ring->ring_mem);
- if (ret) {
- ring->ring_size = 0;
- return ret;
- }
-
- return 0;
-}
-
static int psp_v10_0_ring_create(struct psp_context *psp,
enum psp_ring_type ring_type)
{
@@ -245,7 +219,6 @@ static void psp_v10_0_ring_set_wptr(struct psp_context *psp, uint32_t value)
static const struct psp_funcs psp_v10_0_funcs = {
.init_microcode = psp_v10_0_init_microcode,
- .ring_init = psp_v10_0_ring_init,
.ring_create = psp_v10_0_ring_create,
.ring_stop = psp_v10_0_ring_stop,
.ring_destroy = psp_v10_0_ring_destroy,
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
index 9518b4394a6e..bd3e3e23a939 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0.c
@@ -360,32 +360,6 @@ static int psp_v11_0_bootloader_load_sos(struct psp_context *psp)
return ret;
}
-static int psp_v11_0_ring_init(struct psp_context *psp,
- enum psp_ring_type ring_type)
-{
- int ret = 0;
- struct psp_ring *ring;
- struct amdgpu_device *adev = psp->adev;
-
- ring = &psp->km_ring;
-
- ring->ring_type = ring_type;
-
- /* allocate 4k Page of Local Frame Buffer memory for ring */
- ring->ring_size = 0x1000;
- ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_VRAM,
- &adev->firmware.rbuf,
- &ring->ring_mem_mc_addr,
- (void **)&ring->ring_mem);
- if (ret) {
- ring->ring_size = 0;
- return ret;
- }
-
- return 0;
-}
-
static int psp_v11_0_ring_stop(struct psp_context *psp,
enum psp_ring_type ring_type)
{
@@ -779,7 +753,6 @@ static const struct psp_funcs psp_v11_0_funcs = {
.bootloader_load_spl = psp_v11_0_bootloader_load_spl,
.bootloader_load_sysdrv = psp_v11_0_bootloader_load_sysdrv,
.bootloader_load_sos = psp_v11_0_bootloader_load_sos,
- .ring_init = psp_v11_0_ring_init,
.ring_create = psp_v11_0_ring_create,
.ring_stop = psp_v11_0_ring_stop,
.ring_destroy = psp_v11_0_ring_destroy,
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v11_0_8.c b/drivers/gpu/drm/amd/amdgpu/psp_v11_0_8.c
index ff13e1beb49b..5697760a819b 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v11_0_8.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v11_0_8.c
@@ -28,32 +28,6 @@
#include "mp/mp_11_0_8_offset.h"
-static int psp_v11_0_8_ring_init(struct psp_context *psp,
- enum psp_ring_type ring_type)
-{
- int ret = 0;
- struct psp_ring *ring;
- struct amdgpu_device *adev = psp->adev;
-
- ring = &psp->km_ring;
-
- ring->ring_type = ring_type;
-
- /* allocate 4k Page of Local Frame Buffer memory for ring */
- ring->ring_size = 0x1000;
- ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_VRAM,
- &adev->firmware.rbuf,
- &ring->ring_mem_mc_addr,
- (void **)&ring->ring_mem);
- if (ret) {
- ring->ring_size = 0;
- return ret;
- }
-
- return 0;
-}
-
static int psp_v11_0_8_ring_stop(struct psp_context *psp,
enum psp_ring_type ring_type)
{
@@ -194,7 +168,6 @@ static void psp_v11_0_8_ring_set_wptr(struct psp_context *psp, uint32_t value)
}
static const struct psp_funcs psp_v11_0_8_funcs = {
- .ring_init = psp_v11_0_8_ring_init,
.ring_create = psp_v11_0_8_ring_create,
.ring_stop = psp_v11_0_8_ring_stop,
.ring_destroy = psp_v11_0_8_ring_destroy,
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
index 0b2ac418e4ac..8ed2281b6557 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v12_0.c
@@ -236,34 +236,6 @@ static void psp_v12_0_reroute_ih(struct psp_context *psp)
0x80000000, 0x8000FFFF, false);
}
-static int psp_v12_0_ring_init(struct psp_context *psp,
- enum psp_ring_type ring_type)
-{
- int ret = 0;
- struct psp_ring *ring;
- struct amdgpu_device *adev = psp->adev;
-
- psp_v12_0_reroute_ih(psp);
-
- ring = &psp->km_ring;
-
- ring->ring_type = ring_type;
-
- /* allocate 4k Page of Local Frame Buffer memory for ring */
- ring->ring_size = 0x1000;
- ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_VRAM,
- &adev->firmware.rbuf,
- &ring->ring_mem_mc_addr,
- (void **)&ring->ring_mem);
- if (ret) {
- ring->ring_size = 0;
- return ret;
- }
-
- return 0;
-}
-
static int psp_v12_0_ring_create(struct psp_context *psp,
enum psp_ring_type ring_type)
{
@@ -272,6 +244,8 @@ static int psp_v12_0_ring_create(struct psp_context *psp,
struct psp_ring *ring = &psp->km_ring;
struct amdgpu_device *adev = psp->adev;
+ psp_v12_0_reroute_ih(psp);
+
if (amdgpu_sriov_vf(psp->adev)) {
/* Write low address of the ring to C2PMSG_102 */
psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr);
@@ -425,7 +399,6 @@ static const struct psp_funcs psp_v12_0_funcs = {
.init_microcode = psp_v12_0_init_microcode,
.bootloader_load_sysdrv = psp_v12_0_bootloader_load_sysdrv,
.bootloader_load_sos = psp_v12_0_bootloader_load_sos,
- .ring_init = psp_v12_0_ring_init,
.ring_create = psp_v12_0_ring_create,
.ring_stop = psp_v12_0_ring_stop,
.ring_destroy = psp_v12_0_ring_destroy,
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
index 88f9b327183a..e6a26a7e5e5e 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
@@ -46,6 +46,8 @@ MODULE_FIRMWARE("amdgpu/psp_13_0_7_sos.bin");
MODULE_FIRMWARE("amdgpu/psp_13_0_7_ta.bin");
MODULE_FIRMWARE("amdgpu/psp_13_0_10_sos.bin");
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");
/* For large FW files the time to complete can be very long */
#define USBC_PD_POLLING_LIMIT_S 240
@@ -102,6 +104,7 @@ static int psp_v13_0_init_microcode(struct psp_context *psp)
case IP_VERSION(13, 0, 3):
case IP_VERSION(13, 0, 5):
case IP_VERSION(13, 0, 8):
+ case IP_VERSION(13, 0, 11):
err = psp_init_toc_microcode(psp, chip_name);
if (err)
return err;
@@ -268,32 +271,6 @@ static int psp_v13_0_bootloader_load_sos(struct psp_context *psp)
return ret;
}
-static int psp_v13_0_ring_init(struct psp_context *psp,
- enum psp_ring_type ring_type)
-{
- int ret = 0;
- struct psp_ring *ring;
- struct amdgpu_device *adev = psp->adev;
-
- ring = &psp->km_ring;
-
- ring->ring_type = ring_type;
-
- /* allocate 4k Page of Local Frame Buffer memory for ring */
- ring->ring_size = 0x1000;
- ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_VRAM,
- &adev->firmware.rbuf,
- &ring->ring_mem_mc_addr,
- (void **)&ring->ring_mem);
- if (ret) {
- ring->ring_size = 0;
- return ret;
- }
-
- return 0;
-}
-
static int psp_v13_0_ring_stop(struct psp_context *psp,
enum psp_ring_type ring_type)
{
@@ -729,7 +706,6 @@ static const struct psp_funcs psp_v13_0_funcs = {
.bootloader_load_dbg_drv = psp_v13_0_bootloader_load_dbg_drv,
.bootloader_load_ras_drv = psp_v13_0_bootloader_load_ras_drv,
.bootloader_load_sos = psp_v13_0_bootloader_load_sos,
- .ring_init = psp_v13_0_ring_init,
.ring_create = psp_v13_0_ring_create,
.ring_stop = psp_v13_0_ring_stop,
.ring_destroy = psp_v13_0_ring_destroy,
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c b/drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c
index 321089dfa7db..9d4e24e518e8 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v13_0_4.c
@@ -199,32 +199,6 @@ static int psp_v13_0_4_bootloader_load_sos(struct psp_context *psp)
return ret;
}
-static int psp_v13_0_4_ring_init(struct psp_context *psp,
- enum psp_ring_type ring_type)
-{
- int ret = 0;
- struct psp_ring *ring;
- struct amdgpu_device *adev = psp->adev;
-
- ring = &psp->km_ring;
-
- ring->ring_type = ring_type;
-
- /* allocate 4k Page of Local Frame Buffer memory for ring */
- ring->ring_size = 0x1000;
- ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_VRAM,
- &adev->firmware.rbuf,
- &ring->ring_mem_mc_addr,
- (void **)&ring->ring_mem);
- if (ret) {
- ring->ring_size = 0;
- return ret;
- }
-
- return 0;
-}
-
static int psp_v13_0_4_ring_stop(struct psp_context *psp,
enum psp_ring_type ring_type)
{
@@ -373,7 +347,6 @@ static const struct psp_funcs psp_v13_0_4_funcs = {
.bootloader_load_intf_drv = psp_v13_0_4_bootloader_load_intf_drv,
.bootloader_load_dbg_drv = psp_v13_0_4_bootloader_load_dbg_drv,
.bootloader_load_sos = psp_v13_0_4_bootloader_load_sos,
- .ring_init = psp_v13_0_4_ring_init,
.ring_create = psp_v13_0_4_ring_create,
.ring_stop = psp_v13_0_4_ring_stop,
.ring_destroy = psp_v13_0_4_ring_destroy,
diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
index 01f3bcc62a6c..157147c6c94e 100644
--- a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
@@ -160,32 +160,6 @@ static int psp_v3_1_bootloader_load_sos(struct psp_context *psp)
return ret;
}
-static int psp_v3_1_ring_init(struct psp_context *psp,
- enum psp_ring_type ring_type)
-{
- int ret = 0;
- struct psp_ring *ring;
- struct amdgpu_device *adev = psp->adev;
-
- ring = &psp->km_ring;
-
- ring->ring_type = ring_type;
-
- /* allocate 4k Page of Local Frame Buffer memory for ring */
- ring->ring_size = 0x1000;
- ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_VRAM,
- &adev->firmware.rbuf,
- &ring->ring_mem_mc_addr,
- (void **)&ring->ring_mem);
- if (ret) {
- ring->ring_size = 0;
- return ret;
- }
-
- return 0;
-}
-
static void psp_v3_1_reroute_ih(struct psp_context *psp)
{
struct amdgpu_device *adev = psp->adev;
@@ -401,7 +375,6 @@ static const struct psp_funcs psp_v3_1_funcs = {
.init_microcode = psp_v3_1_init_microcode,
.bootloader_load_sysdrv = psp_v3_1_bootloader_load_sysdrv,
.bootloader_load_sos = psp_v3_1_bootloader_load_sos,
- .ring_init = psp_v3_1_ring_init,
.ring_create = psp_v3_1_ring_create,
.ring_stop = psp_v3_1_ring_stop,
.ring_destroy = psp_v3_1_ring_destroy,
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
index 1122bd4eae98..4d780e4430e7 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
@@ -907,13 +907,13 @@ static void sdma_v4_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
/**
- * sdma_v4_0_gfx_stop - stop the gfx async dma engines
+ * sdma_v4_0_gfx_enable - enable the gfx async dma engines
*
* @adev: amdgpu_device pointer
- *
- * Stop the gfx async dma ring buffers (VEGA10).
+ * @enable: enable SDMA RB/IB
+ * control the gfx async dma ring buffers (VEGA10).
*/
-static void sdma_v4_0_gfx_stop(struct amdgpu_device *adev)
+static void sdma_v4_0_gfx_enable(struct amdgpu_device *adev, bool enable)
{
u32 rb_cntl, ib_cntl;
int i;
@@ -922,10 +922,10 @@ static void sdma_v4_0_gfx_stop(struct amdgpu_device *adev)
for (i = 0; i < adev->sdma.num_instances; i++) {
rb_cntl = RREG32_SDMA(i, mmSDMA0_GFX_RB_CNTL);
- rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, 0);
+ rb_cntl = REG_SET_FIELD(rb_cntl, SDMA0_GFX_RB_CNTL, RB_ENABLE, enable ? 1 : 0);
WREG32_SDMA(i, mmSDMA0_GFX_RB_CNTL, rb_cntl);
ib_cntl = RREG32_SDMA(i, mmSDMA0_GFX_IB_CNTL);
- ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_ENABLE, 0);
+ ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_ENABLE, enable ? 1 : 0);
WREG32_SDMA(i, mmSDMA0_GFX_IB_CNTL, ib_cntl);
}
}
@@ -1044,7 +1044,7 @@ static void sdma_v4_0_enable(struct amdgpu_device *adev, bool enable)
int i;
if (!enable) {
- sdma_v4_0_gfx_stop(adev);
+ sdma_v4_0_gfx_enable(adev, enable);
sdma_v4_0_rlc_stop(adev);
if (adev->sdma.has_page_queue)
sdma_v4_0_page_stop(adev);
@@ -1960,8 +1960,10 @@ static int sdma_v4_0_suspend(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
/* SMU saves SDMA state for us */
- if (adev->in_s0ix)
+ if (adev->in_s0ix) {
+ sdma_v4_0_gfx_enable(adev, false);
return 0;
+ }
return sdma_v4_0_hw_fini(adev);
}
@@ -1971,8 +1973,12 @@ static int sdma_v4_0_resume(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
/* SMU restores SDMA state for us */
- if (adev->in_s0ix)
+ if (adev->in_s0ix) {
+ sdma_v4_0_enable(adev, true);
+ sdma_v4_0_gfx_enable(adev, true);
+ amdgpu_ttm_set_buffer_funcs_status(adev, true);
return 0;
+ }
return sdma_v4_0_hw_init(adev);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
index da3beb0bf2fa..049c26a45d85 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
@@ -455,6 +455,9 @@ static void sdma_v6_0_enable(struct amdgpu_device *adev, bool enable)
sdma_v6_0_rlc_stop(adev);
}
+ if (amdgpu_sriov_vf(adev))
+ return;
+
for (i = 0; i < adev->sdma.num_instances; i++) {
f32_cntl = RREG32_SOC15_IP(GC, sdma_v6_0_get_reg_offset(adev, i, regSDMA0_F32_CNTL));
f32_cntl = REG_SET_FIELD(f32_cntl, SDMA0_F32_CNTL, HALT, enable ? 0 : 1);
@@ -1523,6 +1526,7 @@ static const struct amdgpu_ring_funcs sdma_v6_0_ring_funcs = {
.align_mask = 0xf,
.nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP),
.support_64bit_ptrs = true,
+ .secure_submission_supported = true,
.vmhub = AMDGPU_GFXHUB_0,
.get_rptr = sdma_v6_0_ring_get_rptr,
.get_wptr = sdma_v6_0_ring_get_wptr,
diff --git a/drivers/gpu/drm/amd/amdgpu/si_dma.c b/drivers/gpu/drm/amd/amdgpu/si_dma.c
index 4d5e718540aa..abca8b529721 100644
--- a/drivers/gpu/drm/amd/amdgpu/si_dma.c
+++ b/drivers/gpu/drm/amd/amdgpu/si_dma.c
@@ -112,14 +112,12 @@ static void si_dma_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq,
static void si_dma_stop(struct amdgpu_device *adev)
{
- struct amdgpu_ring *ring;
u32 rb_cntl;
unsigned i;
amdgpu_sdma_unset_buffer_funcs_helper(adev);
for (i = 0; i < adev->sdma.num_instances; i++) {
- ring = &adev->sdma.instance[i].ring;
/* dma0 */
rb_cntl = RREG32(DMA_RB_CNTL + sdma_offsets[i]);
rb_cntl &= ~DMA_RB_ENABLE;
diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c
index e3b2b6b4f1a6..7cd17dda32ce 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc15.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc15.c
@@ -103,10 +103,10 @@ static const struct amdgpu_video_codecs vega_video_codecs_encode =
/* Vega */
static const struct amdgpu_video_codec_info vega_video_codecs_decode_array[] =
{
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4906, 3)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4906, 5)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4906, 4)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 4096, 186)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)},
};
@@ -120,10 +120,10 @@ static const struct amdgpu_video_codecs vega_video_codecs_decode =
/* Raven */
static const struct amdgpu_video_codec_info rv_video_codecs_decode_array[] =
{
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4906, 3)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4906, 5)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4906, 4)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_HEVC, 4096, 4096, 186)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_JPEG, 4096, 4096, 0)},
{codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VP9, 4096, 4096, 0)},
@@ -138,10 +138,10 @@ static const struct amdgpu_video_codecs rv_video_codecs_decode =
/* Renoir, Arcturus */
static const struct amdgpu_video_codec_info rn_video_codecs_decode_array[] =
{
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4906, 3)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4906, 5)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)},
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4906, 4)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG2, 4096, 4096, 3)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4, 4096, 4096, 5)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4096, 52)},
+ {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_VC1, 4096, 4096, 4)},
{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)},
diff --git a/drivers/gpu/drm/amd/amdgpu/soc15d.h b/drivers/gpu/drm/amd/amdgpu/soc15d.h
index 799925d22fc8..2357ff39323f 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc15d.h
+++ b/drivers/gpu/drm/amd/amdgpu/soc15d.h
@@ -162,6 +162,7 @@
* 2 - Bypass
*/
#define INDIRECT_BUFFER_PRE_ENB(x) ((x) << 21)
+#define INDIRECT_BUFFER_PRE_RESUME(x) ((x) << 30)
#define PACKET3_COPY_DATA 0x40
#define PACKET3_PFP_SYNC_ME 0x42
#define PACKET3_COND_WRITE 0x45
@@ -184,6 +185,7 @@
#define EOP_TC_ACTION_EN (1 << 17) /* L2 */
#define EOP_TC_NC_ACTION_EN (1 << 19)
#define EOP_TC_MD_ACTION_EN (1 << 21) /* L2 metadata */
+#define EOP_EXEC (1 << 28) /* For Trailing Fence */
#define DATA_SEL(x) ((x) << 29)
/* 0 - discard
diff --git a/drivers/gpu/drm/amd/amdgpu/soc21.c b/drivers/gpu/drm/amd/amdgpu/soc21.c
index e08044008186..7d5fdf450d0c 100644
--- a/drivers/gpu/drm/amd/amdgpu/soc21.c
+++ b/drivers/gpu/drm/amd/amdgpu/soc21.c
@@ -43,6 +43,7 @@
#include "soc15.h"
#include "soc15_common.h"
#include "soc21.h"
+#include "mxgpu_nv.h"
static const struct amd_ip_funcs soc21_common_ip_funcs;
@@ -61,7 +62,7 @@ static const struct amdgpu_video_codecs vcn_4_0_0_video_codecs_encode =
static const struct amdgpu_video_codec_info vcn_4_0_0_video_codecs_decode_array[] =
{
- {codec_info_build(AMDGPU_INFO_VIDEO_CAPS_CODEC_IDX_MPEG4_AVC, 4096, 4906, 52)},
+ {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)},
@@ -322,8 +323,10 @@ soc21_asic_reset_method(struct amdgpu_device *adev)
switch (adev->ip_versions[MP1_HWIP][0]) {
case IP_VERSION(13, 0, 0):
case IP_VERSION(13, 0, 7):
+ case IP_VERSION(13, 0, 10):
return AMD_RESET_METHOD_MODE1;
case IP_VERSION(13, 0, 4):
+ case IP_VERSION(13, 0, 11):
return AMD_RESET_METHOD_MODE2;
default:
if (amdgpu_dpm_is_baco_supported(adev))
@@ -584,10 +587,6 @@ static int soc21_common_early_init(void *handle)
AMD_PG_SUPPORT_JPEG |
AMD_PG_SUPPORT_ATHUB |
AMD_PG_SUPPORT_MMHUB;
- if (amdgpu_sriov_vf(adev)) {
- adev->cg_flags = 0;
- adev->pg_flags = 0;
- }
adev->external_rev_id = adev->rev_id + 0x1; // TODO: need update
break;
case IP_VERSION(11, 0, 2):
@@ -645,28 +644,63 @@ static int soc21_common_early_init(void *handle)
adev->pg_flags = AMD_PG_SUPPORT_VCN |
AMD_PG_SUPPORT_VCN_DPG |
AMD_PG_SUPPORT_JPEG;
- if (amdgpu_sriov_vf(adev)) {
- /* hypervisor control CG and PG enablement */
- adev->cg_flags = 0;
- adev->pg_flags = 0;
- }
adev->external_rev_id = adev->rev_id + 0x20;
break;
+ case IP_VERSION(11, 0, 4):
+ adev->cg_flags =
+ AMD_CG_SUPPORT_GFX_CGCG |
+ AMD_CG_SUPPORT_GFX_CGLS |
+ AMD_CG_SUPPORT_GFX_MGCG |
+ AMD_CG_SUPPORT_GFX_FGCG |
+ AMD_CG_SUPPORT_REPEATER_FGCG |
+ AMD_CG_SUPPORT_GFX_PERF_CLK |
+ AMD_CG_SUPPORT_MC_MGCG |
+ AMD_CG_SUPPORT_MC_LS |
+ AMD_CG_SUPPORT_HDP_MGCG |
+ AMD_CG_SUPPORT_HDP_LS |
+ AMD_CG_SUPPORT_ATHUB_MGCG |
+ AMD_CG_SUPPORT_ATHUB_LS |
+ AMD_CG_SUPPORT_IH_CG |
+ AMD_CG_SUPPORT_BIF_MGCG |
+ AMD_CG_SUPPORT_BIF_LS |
+ AMD_CG_SUPPORT_VCN_MGCG |
+ AMD_CG_SUPPORT_JPEG_MGCG;
+ adev->pg_flags = AMD_PG_SUPPORT_VCN |
+ AMD_PG_SUPPORT_GFX_PG |
+ AMD_PG_SUPPORT_JPEG;
+ adev->external_rev_id = adev->rev_id + 0x1;
+ break;
+
default:
/* FIXME: not supported yet */
return -EINVAL;
}
+ if (amdgpu_sriov_vf(adev)) {
+ amdgpu_virt_init_setting(adev);
+ xgpu_nv_mailbox_set_irq_funcs(adev);
+ }
+
return 0;
}
static int soc21_common_late_init(void *handle)
{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ if (amdgpu_sriov_vf(adev))
+ xgpu_nv_mailbox_get_irq(adev);
+
return 0;
}
static int soc21_common_sw_init(void *handle)
{
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
+ if (amdgpu_sriov_vf(adev))
+ xgpu_nv_mailbox_add_irq_id(adev);
+
return 0;
}
@@ -704,6 +738,9 @@ static int soc21_common_hw_fini(void *handle)
/* disable the doorbell aperture */
soc21_enable_doorbell_aperture(adev, false);
+ if (amdgpu_sriov_vf(adev))
+ xgpu_nv_mailbox_put_irq(adev);
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c
index 5d5d031c9e7d..72fd963f178b 100644
--- a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c
+++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.c
@@ -187,9 +187,9 @@ static void umc_v6_7_ecc_info_query_ras_error_count(struct amdgpu_device *adev,
}
}
-static void umc_v6_7_convert_error_address(struct amdgpu_device *adev,
- struct ras_err_data *err_data, uint64_t err_addr,
- uint32_t ch_inst, uint32_t umc_inst)
+void umc_v6_7_convert_error_address(struct amdgpu_device *adev,
+ struct ras_err_data *err_data, uint64_t err_addr,
+ uint32_t ch_inst, uint32_t umc_inst)
{
uint32_t channel_index;
uint64_t soc_pa, retired_page, column;
@@ -553,5 +553,4 @@ struct amdgpu_umc_ras umc_v6_7_ras = {
.query_ras_poison_mode = umc_v6_7_query_ras_poison_mode,
.ecc_info_query_ras_error_count = umc_v6_7_ecc_info_query_ras_error_count,
.ecc_info_query_ras_error_address = umc_v6_7_ecc_info_query_ras_error_address,
- .convert_ras_error_address = umc_v6_7_convert_error_address,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h
index fe41ed2f5945..105245d5b6e5 100644
--- a/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h
+++ b/drivers/gpu/drm/amd/amdgpu/umc_v6_7.h
@@ -71,5 +71,7 @@ extern const uint32_t
umc_v6_7_channel_idx_tbl_second[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM];
extern const uint32_t
umc_v6_7_channel_idx_tbl_first[UMC_V6_7_UMC_INSTANCE_NUM][UMC_V6_7_CHANNEL_INSTANCE_NUM];
-
+void umc_v6_7_convert_error_address(struct amdgpu_device *adev,
+ struct ras_err_data *err_data, uint64_t err_addr,
+ uint32_t ch_inst, uint32_t umc_inst);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_10.c b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.c
index 91235df54e22..b7da4528cf0a 100644
--- a/drivers/gpu/drm/amd/amdgpu/umc_v8_10.c
+++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.c
@@ -46,6 +46,16 @@ const struct channelnum_map_colbit umc_v8_10_channelnum_map_colbit_table[] = {
};
const uint32_t
+ umc_v8_10_channel_idx_tbl_ext0[]
+ [UMC_V8_10_UMC_INSTANCE_NUM]
+ [UMC_V8_10_CHANNEL_INSTANCE_NUM] = {
+ {{1, 5}, {7, 3}},
+ {{14, 15}, {13, 12}},
+ {{10, 11}, {9, 8}},
+ {{6, 2}, {0, 4}}
+ };
+
+const uint32_t
umc_v8_10_channel_idx_tbl[]
[UMC_V8_10_UMC_INSTANCE_NUM]
[UMC_V8_10_CHANNEL_INSTANCE_NUM] = {
diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_10.h b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.h
index 849ede88e111..25eaf4af5fcf 100644
--- a/drivers/gpu/drm/amd/amdgpu/umc_v8_10.h
+++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_10.h
@@ -66,5 +66,9 @@ extern const uint32_t
[UMC_V8_10_UMC_INSTANCE_NUM]
[UMC_V8_10_CHANNEL_INSTANCE_NUM];
+extern const uint32_t
+ umc_v8_10_channel_idx_tbl_ext0[]
+ [UMC_V8_10_UMC_INSTANCE_NUM]
+ [UMC_V8_10_CHANNEL_INSTANCE_NUM];
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
index 375c440957dc..5fe872f4bea7 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
@@ -216,8 +216,8 @@ static int uvd_v6_0_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle
uint64_t addr;
int i, r;
- r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
- AMDGPU_IB_POOL_DIRECT, &job);
+ r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, ib_size_dw * 4,
+ AMDGPU_IB_POOL_DIRECT, &job);
if (r)
return r;
@@ -280,8 +280,8 @@ static int uvd_v6_0_enc_get_destroy_msg(struct amdgpu_ring *ring,
uint64_t addr;
int i, r;
- r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
- AMDGPU_IB_POOL_DIRECT, &job);
+ r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, ib_size_dw * 4,
+ AMDGPU_IB_POOL_DIRECT, &job);
if (r)
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
index e668b3baa8c6..e407be6cb63c 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
@@ -213,7 +213,7 @@ static int uvd_v7_0_enc_ring_test_ring(struct amdgpu_ring *ring)
*
* Open up a stream for HW test
*/
-static int uvd_v7_0_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle,
+static int uvd_v7_0_enc_get_create_msg(struct amdgpu_ring *ring, u32 handle,
struct amdgpu_bo *bo,
struct dma_fence **fence)
{
@@ -224,8 +224,8 @@ static int uvd_v7_0_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle
uint64_t addr;
int i, r;
- r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
- AMDGPU_IB_POOL_DIRECT, &job);
+ r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, ib_size_dw * 4,
+ AMDGPU_IB_POOL_DIRECT, &job);
if (r)
return r;
@@ -276,7 +276,7 @@ err:
*
* Close up a stream for HW test or if userspace failed to do so
*/
-static int uvd_v7_0_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handle,
+static int uvd_v7_0_enc_get_destroy_msg(struct amdgpu_ring *ring, u32 handle,
struct amdgpu_bo *bo,
struct dma_fence **fence)
{
@@ -287,8 +287,8 @@ static int uvd_v7_0_enc_get_destroy_msg(struct amdgpu_ring *ring, uint32_t handl
uint64_t addr;
int i, r;
- r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4,
- AMDGPU_IB_POOL_DIRECT, &job);
+ r = amdgpu_job_alloc_with_ib(ring->adev, NULL, NULL, ib_size_dw * 4,
+ AMDGPU_IB_POOL_DIRECT, &job);
if (r)
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
index 8a7006d62a87..ec87b00f2e05 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
@@ -770,6 +770,33 @@ static void vcn_v2_5_enable_clock_gating(struct amdgpu_device *adev)
}
}
+static void vcn_v2_6_enable_ras(struct amdgpu_device *adev, int inst_idx,
+ bool indirect)
+{
+ uint32_t tmp;
+
+ if (adev->ip_versions[UVD_HWIP][0] != IP_VERSION(2, 6, 0))
+ 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, mmVCN_RAS_CNTL),
+ tmp, 0, indirect);
+
+ tmp = UVD_VCPU_INT_EN__RASCNTL_VCPU_VCODEC_EN_MASK;
+ WREG32_SOC15_DPG_MODE(inst_idx,
+ SOC15_DPG_MODE_OFFSET(VCN, 0, mmUVD_VCPU_INT_EN),
+ 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, mmUVD_SYS_INT_EN),
+ tmp, 0, indirect);
+}
+
static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, bool indirect)
{
volatile struct amdgpu_fw_shared *fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
@@ -849,6 +876,8 @@ static int vcn_v2_5_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
VCN, 0, mmUVD_LMI_CTRL2), 0, 0, indirect);
+ vcn_v2_6_enable_ras(adev, inst_idx, indirect);
+
/* unblock VCPU register access */
WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
VCN, 0, mmUVD_RB_ARB_CTRL), 0, 0, indirect);
@@ -2002,16 +2031,5 @@ static void vcn_v2_5_set_ras_funcs(struct amdgpu_device *adev)
break;
}
- if (adev->vcn.ras) {
- amdgpu_ras_register_ras_block(adev, &adev->vcn.ras->ras_block);
-
- strcpy(adev->vcn.ras->ras_block.ras_comm.name, "vcn");
- adev->vcn.ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__VCN;
- adev->vcn.ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__POISON;
- adev->vcn.ras_if = &adev->vcn.ras->ras_block.ras_comm;
-
- /* If don't define special ras_late_init function, use default ras_late_init */
- if (!adev->vcn.ras->ras_block.ras_late_init)
- adev->vcn.ras->ras_block.ras_late_init = amdgpu_ras_block_late_init;
- }
+ amdgpu_vcn_set_ras_funcs(adev);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index dcc49b01bd59..1e2b22299975 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -31,6 +31,7 @@
#include "soc15_hw_ip.h"
#include "vcn_v2_0.h"
#include "mmsch_v4_0.h"
+#include "vcn_v4_0.h"
#include "vcn/vcn_4_0_0_offset.h"
#include "vcn/vcn_4_0_0_sh_mask.h"
@@ -64,6 +65,7 @@ static int vcn_v4_0_set_powergating_state(void *handle,
static int vcn_v4_0_pause_dpg_mode(struct amdgpu_device *adev,
int inst_idx, struct dpg_pause_state *new_state);
static void vcn_v4_0_unified_ring_set_wptr(struct amdgpu_ring *ring);
+static void vcn_v4_0_set_ras_funcs(struct amdgpu_device *adev);
/**
* vcn_v4_0_early_init - set function pointers
@@ -84,6 +86,7 @@ static int vcn_v4_0_early_init(void *handle)
vcn_v4_0_set_unified_ring_funcs(adev);
vcn_v4_0_set_irq_funcs(adev);
+ vcn_v4_0_set_ras_funcs(adev);
return 0;
}
@@ -125,6 +128,12 @@ static int vcn_v4_0_sw_init(void *handle)
if (r)
return r;
+ /* VCN POISON TRAP */
+ r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[i],
+ VCN_4_0__SRCID_UVD_POISON, &adev->vcn.inst[i].irq);
+ if (r)
+ return r;
+
ring = &adev->vcn.inst[i].ring_enc[0];
ring->use_doorbell = true;
if (amdgpu_sriov_vf(adev))
@@ -289,6 +298,7 @@ static int vcn_v4_0_hw_fini(void *handle)
}
}
+ amdgpu_irq_put(adev, &adev->vcn.inst[i].irq, 0);
}
return 0;
@@ -852,6 +862,28 @@ static void vcn_v4_0_enable_clock_gating(struct amdgpu_device *adev, int inst)
return;
}
+static void vcn_v4_0_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);
+}
+
/**
* vcn_v4_0_start_dpg_mode - VCN start with dpg mode
*
@@ -940,6 +972,8 @@ static int vcn_v4_0_start_dpg_mode(struct amdgpu_device *adev, int inst_idx, boo
WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
VCN, inst_idx, regUVD_LMI_CTRL2), tmp, 0, indirect);
+ vcn_v4_0_enable_ras(adev, inst_idx, indirect);
+
/* enable master interrupt */
WREG32_SOC15_DPG_MODE(inst_idx, SOC15_DPG_MODE_OFFSET(
VCN, inst_idx, regUVD_MASTINT_EN),
@@ -1932,6 +1966,9 @@ static int vcn_v4_0_process_interrupt(struct amdgpu_device *adev, struct amdgpu_
case VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE:
amdgpu_fence_process(&adev->vcn.inst[ip_instance].ring_enc[0]);
break;
+ case VCN_4_0__SRCID_UVD_POISON:
+ amdgpu_vcn_process_poison_irq(adev, source, entry);
+ break;
default:
DRM_ERROR("Unhandled interrupt: %d %d\n",
entry->src_id, entry->src_data[0]);
@@ -1994,3 +2031,60 @@ const struct amdgpu_ip_block_version vcn_v4_0_ip_block =
.rev = 0,
.funcs = &vcn_v4_0_ip_funcs,
};
+
+static uint32_t vcn_v4_0_query_poison_by_instance(struct amdgpu_device *adev,
+ uint32_t instance, uint32_t sub_block)
+{
+ uint32_t poison_stat = 0, reg_value = 0;
+
+ switch (sub_block) {
+ case AMDGPU_VCN_V4_0_VCPU_VCODEC:
+ reg_value = RREG32_SOC15(VCN, instance, regUVD_RAS_VCPU_VCODEC_STATUS);
+ poison_stat = REG_GET_FIELD(reg_value, UVD_RAS_VCPU_VCODEC_STATUS, POISONED_PF);
+ break;
+ default:
+ break;
+ }
+
+ if (poison_stat)
+ dev_info(adev->dev, "Poison detected in VCN%d, sub_block%d\n",
+ instance, sub_block);
+
+ return poison_stat;
+}
+
+static bool vcn_v4_0_query_ras_poison_status(struct amdgpu_device *adev)
+{
+ uint32_t inst, sub;
+ uint32_t poison_stat = 0;
+
+ for (inst = 0; inst < adev->vcn.num_vcn_inst; inst++)
+ for (sub = 0; sub < AMDGPU_VCN_V4_0_MAX_SUB_BLOCK; sub++)
+ poison_stat +=
+ vcn_v4_0_query_poison_by_instance(adev, inst, sub);
+
+ return !!poison_stat;
+}
+
+const struct amdgpu_ras_block_hw_ops vcn_v4_0_ras_hw_ops = {
+ .query_poison_status = vcn_v4_0_query_ras_poison_status,
+};
+
+static struct amdgpu_vcn_ras vcn_v4_0_ras = {
+ .ras_block = {
+ .hw_ops = &vcn_v4_0_ras_hw_ops,
+ },
+};
+
+static void vcn_v4_0_set_ras_funcs(struct amdgpu_device *adev)
+{
+ switch (adev->ip_versions[VCN_HWIP][0]) {
+ case IP_VERSION(4, 0, 0):
+ adev->vcn.ras = &vcn_v4_0_ras;
+ break;
+ default:
+ break;
+ }
+
+ amdgpu_vcn_set_ras_funcs(adev);
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.h b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.h
index 7c5c9d91bb52..7d3d11f40f27 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.h
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.h
@@ -24,6 +24,12 @@
#ifndef __VCN_V4_0_H__
#define __VCN_V4_0_H__
+enum amdgpu_vcn_v4_0_sub_block {
+ AMDGPU_VCN_V4_0_VCPU_VCODEC = 0,
+
+ AMDGPU_VCN_V4_0_MAX_SUB_BLOCK,
+};
+
extern const struct amdgpu_ip_block_version vcn_v4_0_ip_block;
#endif /* __VCN_V4_0_H__ */
diff --git a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c
index 59dfca093155..1706081d054d 100644
--- a/drivers/gpu/drm/amd/amdgpu/vega20_ih.c
+++ b/drivers/gpu/drm/amd/amdgpu/vega20_ih.c
@@ -267,7 +267,7 @@ static void vega20_ih_reroute_ih(struct amdgpu_device *adev)
/* vega20 ih reroute will go through psp this
* function is used for newer asics starting arcturus
*/
- if (adev->asic_type >= CHIP_ARCTURUS) {
+ if (adev->ip_versions[OSSSYS_HWIP][0] >= IP_VERSION(4, 2, 1)) {
/* Reroute to IH ring 1 for VMC */
WREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_INDEX, 0x12);
tmp = RREG32_SOC15(OSSSYS, 0, mmIH_CLIENT_CFG_DATA);
@@ -308,7 +308,7 @@ static int vega20_ih_irq_init(struct amdgpu_device *adev)
adev->nbio.funcs->ih_control(adev);
- if (adev->asic_type == CHIP_ARCTURUS &&
+ if ((adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 2, 1)) &&
adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) {
ih_chicken = RREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN);
if (adev->irq.ih.use_bus_addr) {
@@ -321,7 +321,7 @@ static int vega20_ih_irq_init(struct amdgpu_device *adev)
/* psp firmware won't program IH_CHICKEN for aldebaran
* driver needs to program it properly according to
* MC_SPACE type in IH_RB_CNTL */
- if (adev->asic_type == CHIP_ALDEBARAN) {
+ if (adev->ip_versions[OSSSYS_HWIP][0] == IP_VERSION(4, 4, 0)) {
ih_chicken = RREG32_SOC15(OSSSYS, 0, mmIH_CHICKEN_ALDEBARAN);
if (adev->irq.ih.use_bus_addr) {
ih_chicken = REG_SET_FIELD(ih_chicken, IH_CHICKEN,
diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c
index f6ffd7c96ff9..12ef782eb478 100644
--- a/drivers/gpu/drm/amd/amdgpu/vi.c
+++ b/drivers/gpu/drm/amd/amdgpu/vi.c
@@ -2111,6 +2111,8 @@ void vi_set_virt_ops(struct amdgpu_device *adev)
int vi_set_ip_blocks(struct amdgpu_device *adev)
{
+ amdgpu_device_set_sriov_virtual_display(adev);
+
switch (adev->asic_type) {
case CHIP_TOPAZ:
/* topaz has no DCE, UVD, VCE */
@@ -2130,7 +2132,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &gfx_v8_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
- if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
+ if (adev->enable_virtual_display)
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
@@ -2150,7 +2152,7 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
amdgpu_device_ip_block_add(adev, &gfx_v8_0_ip_block);
amdgpu_device_ip_block_add(adev, &sdma_v3_0_ip_block);
amdgpu_device_ip_block_add(adev, &pp_smu_ip_block);
- if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
+ if (adev->enable_virtual_display)
amdgpu_device_ip_block_add(adev, &amdgpu_vkms_ip_block);
#if defined(CONFIG_DRM_AMD_DC)
else if (amdgpu_device_has_dc_support(adev))
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
index 8bfdfd062ff6..3251f4783ba1 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
@@ -50,16 +50,6 @@ static inline unsigned int get_and_inc_gpu_processor_id(
return current_id;
}
-/* Static table to describe GPU Cache information */
-struct kfd_gpu_cache_info {
- uint32_t cache_size;
- uint32_t cache_level;
- uint32_t flags;
- /* Indicates how many Compute Units share this cache
- * within a SA. Value = 1 indicates the cache is not shared
- */
- uint32_t num_cu_shared;
-};
static struct kfd_gpu_cache_info kaveri_cache_info[] = {
{
@@ -891,6 +881,54 @@ static struct kfd_gpu_cache_info gc_10_3_6_cache_info[] = {
},
};
+static struct kfd_gpu_cache_info dummy_cache_info[] = {
+ {
+ /* TCP L1 Cache per CU */
+ .cache_size = 16,
+ .cache_level = 1,
+ .flags = (CRAT_CACHE_FLAGS_ENABLED |
+ CRAT_CACHE_FLAGS_DATA_CACHE |
+ CRAT_CACHE_FLAGS_SIMD_CACHE),
+ .num_cu_shared = 1,
+ },
+ {
+ /* Scalar L1 Instruction Cache per SQC */
+ .cache_size = 32,
+ .cache_level = 1,
+ .flags = (CRAT_CACHE_FLAGS_ENABLED |
+ CRAT_CACHE_FLAGS_INST_CACHE |
+ CRAT_CACHE_FLAGS_SIMD_CACHE),
+ .num_cu_shared = 2,
+ },
+ {
+ /* Scalar L1 Data Cache per SQC */
+ .cache_size = 16,
+ .cache_level = 1,
+ .flags = (CRAT_CACHE_FLAGS_ENABLED |
+ CRAT_CACHE_FLAGS_DATA_CACHE |
+ CRAT_CACHE_FLAGS_SIMD_CACHE),
+ .num_cu_shared = 2,
+ },
+ {
+ /* GL1 Data Cache per SA */
+ .cache_size = 128,
+ .cache_level = 1,
+ .flags = (CRAT_CACHE_FLAGS_ENABLED |
+ CRAT_CACHE_FLAGS_DATA_CACHE |
+ CRAT_CACHE_FLAGS_SIMD_CACHE),
+ .num_cu_shared = 6,
+ },
+ {
+ /* L2 Data Cache per GPU (Total Tex Cache) */
+ .cache_size = 2048,
+ .cache_level = 2,
+ .flags = (CRAT_CACHE_FLAGS_ENABLED |
+ CRAT_CACHE_FLAGS_DATA_CACHE |
+ CRAT_CACHE_FLAGS_SIMD_CACHE),
+ .num_cu_shared = 6,
+ },
+};
+
static void kfd_populated_cu_info_cpu(struct kfd_topology_device *dev,
struct crat_subtype_computeunit *cu)
{
@@ -1071,8 +1109,12 @@ static int kfd_parse_subtype_cache(struct crat_subtype_cache *cache,
props->cachelines_per_tag = cache->lines_per_tag;
props->cache_assoc = cache->associativity;
props->cache_latency = cache->cache_latency;
+
memcpy(props->sibling_map, cache->sibling_map,
- sizeof(props->sibling_map));
+ CRAT_SIBLINGMAP_SIZE);
+
+ /* set the sibling_map_size as 32 for CRAT from ACPI */
+ props->sibling_map_size = CRAT_SIBLINGMAP_SIZE;
if (cache->flags & CRAT_CACHE_FLAGS_DATA_CACHE)
props->cache_type |= HSA_CACHE_TYPE_DATA;
@@ -1083,7 +1125,6 @@ static int kfd_parse_subtype_cache(struct crat_subtype_cache *cache,
if (cache->flags & CRAT_CACHE_FLAGS_SIMD_CACHE)
props->cache_type |= HSA_CACHE_TYPE_HSACU;
- dev->cache_count++;
dev->node_props.caches_count++;
list_add_tail(&props->list, &dev->cache_props);
@@ -1291,125 +1332,6 @@ err:
return ret;
}
-/* Helper function. See kfd_fill_gpu_cache_info for parameter description */
-static int fill_in_l1_pcache(struct crat_subtype_cache *pcache,
- struct kfd_gpu_cache_info *pcache_info,
- struct kfd_cu_info *cu_info,
- int mem_available,
- int cu_bitmask,
- int cache_type, unsigned int cu_processor_id,
- int cu_block)
-{
- unsigned int cu_sibling_map_mask;
- int first_active_cu;
-
- /* First check if enough memory is available */
- if (sizeof(struct crat_subtype_cache) > mem_available)
- return -ENOMEM;
-
- cu_sibling_map_mask = cu_bitmask;
- cu_sibling_map_mask >>= cu_block;
- cu_sibling_map_mask &=
- ((1 << pcache_info[cache_type].num_cu_shared) - 1);
- first_active_cu = ffs(cu_sibling_map_mask);
-
- /* CU could be inactive. In case of shared cache find the first active
- * CU. and incase of non-shared cache check if the CU is inactive. If
- * inactive active skip it
- */
- if (first_active_cu) {
- memset(pcache, 0, sizeof(struct crat_subtype_cache));
- pcache->type = CRAT_SUBTYPE_CACHE_AFFINITY;
- pcache->length = sizeof(struct crat_subtype_cache);
- pcache->flags = pcache_info[cache_type].flags;
- pcache->processor_id_low = cu_processor_id
- + (first_active_cu - 1);
- pcache->cache_level = pcache_info[cache_type].cache_level;
- pcache->cache_size = pcache_info[cache_type].cache_size;
-
- /* Sibling map is w.r.t processor_id_low, so shift out
- * inactive CU
- */
- cu_sibling_map_mask =
- cu_sibling_map_mask >> (first_active_cu - 1);
-
- pcache->sibling_map[0] = (uint8_t)(cu_sibling_map_mask & 0xFF);
- pcache->sibling_map[1] =
- (uint8_t)((cu_sibling_map_mask >> 8) & 0xFF);
- pcache->sibling_map[2] =
- (uint8_t)((cu_sibling_map_mask >> 16) & 0xFF);
- pcache->sibling_map[3] =
- (uint8_t)((cu_sibling_map_mask >> 24) & 0xFF);
- return 0;
- }
- return 1;
-}
-
-/* Helper function. See kfd_fill_gpu_cache_info for parameter description */
-static int fill_in_l2_l3_pcache(struct crat_subtype_cache *pcache,
- struct kfd_gpu_cache_info *pcache_info,
- struct kfd_cu_info *cu_info,
- int mem_available,
- int cache_type, unsigned int cu_processor_id)
-{
- unsigned int cu_sibling_map_mask;
- int first_active_cu;
- int i, j, k;
-
- /* First check if enough memory is available */
- if (sizeof(struct crat_subtype_cache) > mem_available)
- return -ENOMEM;
-
- cu_sibling_map_mask = cu_info->cu_bitmap[0][0];
- cu_sibling_map_mask &=
- ((1 << pcache_info[cache_type].num_cu_shared) - 1);
- first_active_cu = ffs(cu_sibling_map_mask);
-
- /* CU could be inactive. In case of shared cache find the first active
- * CU. and incase of non-shared cache check if the CU is inactive. If
- * inactive active skip it
- */
- if (first_active_cu) {
- memset(pcache, 0, sizeof(struct crat_subtype_cache));
- pcache->type = CRAT_SUBTYPE_CACHE_AFFINITY;
- pcache->length = sizeof(struct crat_subtype_cache);
- pcache->flags = pcache_info[cache_type].flags;
- pcache->processor_id_low = cu_processor_id
- + (first_active_cu - 1);
- pcache->cache_level = pcache_info[cache_type].cache_level;
- pcache->cache_size = pcache_info[cache_type].cache_size;
-
- /* Sibling map is w.r.t processor_id_low, so shift out
- * inactive CU
- */
- cu_sibling_map_mask =
- cu_sibling_map_mask >> (first_active_cu - 1);
- k = 0;
- for (i = 0; i < cu_info->num_shader_engines; i++) {
- for (j = 0; j < cu_info->num_shader_arrays_per_engine;
- j++) {
- pcache->sibling_map[k] =
- (uint8_t)(cu_sibling_map_mask & 0xFF);
- pcache->sibling_map[k+1] =
- (uint8_t)((cu_sibling_map_mask >> 8) & 0xFF);
- pcache->sibling_map[k+2] =
- (uint8_t)((cu_sibling_map_mask >> 16) & 0xFF);
- pcache->sibling_map[k+3] =
- (uint8_t)((cu_sibling_map_mask >> 24) & 0xFF);
- k += 4;
- cu_sibling_map_mask =
- cu_info->cu_bitmap[i % 4][j + i / 4];
- cu_sibling_map_mask &= (
- (1 << pcache_info[cache_type].num_cu_shared)
- - 1);
- }
- }
- return 0;
- }
- return 1;
-}
-
-#define KFD_MAX_CACHE_TYPES 6
static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
struct kfd_gpu_cache_info *pcache_info)
@@ -1483,228 +1405,134 @@ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
return i;
}
-/* kfd_fill_gpu_cache_info - Fill GPU cache info using kfd_gpu_cache_info
- * tables
- *
- * @kdev - [IN] GPU device
- * @gpu_processor_id - [IN] GPU processor ID to which these caches
- * associate
- * @available_size - [IN] Amount of memory available in pcache
- * @cu_info - [IN] Compute Unit info obtained from KGD
- * @pcache - [OUT] memory into which cache data is to be filled in.
- * @size_filled - [OUT] amount of data used up in pcache.
- * @num_of_entries - [OUT] number of caches added
- */
-static int kfd_fill_gpu_cache_info(struct kfd_dev *kdev,
- int gpu_processor_id,
- int available_size,
- struct kfd_cu_info *cu_info,
- struct crat_subtype_cache *pcache,
- int *size_filled,
- int *num_of_entries)
+int kfd_get_gpu_cache_info(struct kfd_dev *kdev, struct kfd_gpu_cache_info **pcache_info)
{
- struct kfd_gpu_cache_info *pcache_info;
- struct kfd_gpu_cache_info cache_info[KFD_MAX_CACHE_TYPES];
int num_of_cache_types = 0;
- int i, j, k;
- int ct = 0;
- int mem_available = available_size;
- unsigned int cu_processor_id;
- int ret;
- unsigned int num_cu_shared;
switch (kdev->adev->asic_type) {
case CHIP_KAVERI:
- pcache_info = kaveri_cache_info;
+ *pcache_info = kaveri_cache_info;
num_of_cache_types = ARRAY_SIZE(kaveri_cache_info);
break;
case CHIP_HAWAII:
- pcache_info = hawaii_cache_info;
+ *pcache_info = hawaii_cache_info;
num_of_cache_types = ARRAY_SIZE(hawaii_cache_info);
break;
case CHIP_CARRIZO:
- pcache_info = carrizo_cache_info;
+ *pcache_info = carrizo_cache_info;
num_of_cache_types = ARRAY_SIZE(carrizo_cache_info);
break;
case CHIP_TONGA:
- pcache_info = tonga_cache_info;
+ *pcache_info = tonga_cache_info;
num_of_cache_types = ARRAY_SIZE(tonga_cache_info);
break;
case CHIP_FIJI:
- pcache_info = fiji_cache_info;
+ *pcache_info = fiji_cache_info;
num_of_cache_types = ARRAY_SIZE(fiji_cache_info);
break;
case CHIP_POLARIS10:
- pcache_info = polaris10_cache_info;
+ *pcache_info = polaris10_cache_info;
num_of_cache_types = ARRAY_SIZE(polaris10_cache_info);
break;
case CHIP_POLARIS11:
- pcache_info = polaris11_cache_info;
+ *pcache_info = polaris11_cache_info;
num_of_cache_types = ARRAY_SIZE(polaris11_cache_info);
break;
case CHIP_POLARIS12:
- pcache_info = polaris12_cache_info;
+ *pcache_info = polaris12_cache_info;
num_of_cache_types = ARRAY_SIZE(polaris12_cache_info);
break;
case CHIP_VEGAM:
- pcache_info = vegam_cache_info;
+ *pcache_info = vegam_cache_info;
num_of_cache_types = ARRAY_SIZE(vegam_cache_info);
break;
default:
switch (KFD_GC_VERSION(kdev)) {
case IP_VERSION(9, 0, 1):
- pcache_info = vega10_cache_info;
+ *pcache_info = vega10_cache_info;
num_of_cache_types = ARRAY_SIZE(vega10_cache_info);
break;
case IP_VERSION(9, 2, 1):
- pcache_info = vega12_cache_info;
+ *pcache_info = vega12_cache_info;
num_of_cache_types = ARRAY_SIZE(vega12_cache_info);
break;
case IP_VERSION(9, 4, 0):
case IP_VERSION(9, 4, 1):
- pcache_info = vega20_cache_info;
+ *pcache_info = vega20_cache_info;
num_of_cache_types = ARRAY_SIZE(vega20_cache_info);
break;
case IP_VERSION(9, 4, 2):
- pcache_info = aldebaran_cache_info;
+ *pcache_info = aldebaran_cache_info;
num_of_cache_types = ARRAY_SIZE(aldebaran_cache_info);
break;
case IP_VERSION(9, 1, 0):
case IP_VERSION(9, 2, 2):
- pcache_info = raven_cache_info;
+ *pcache_info = raven_cache_info;
num_of_cache_types = ARRAY_SIZE(raven_cache_info);
break;
case IP_VERSION(9, 3, 0):
- pcache_info = renoir_cache_info;
+ *pcache_info = renoir_cache_info;
num_of_cache_types = ARRAY_SIZE(renoir_cache_info);
break;
case IP_VERSION(10, 1, 10):
case IP_VERSION(10, 1, 2):
case IP_VERSION(10, 1, 3):
case IP_VERSION(10, 1, 4):
- pcache_info = navi10_cache_info;
+ *pcache_info = navi10_cache_info;
num_of_cache_types = ARRAY_SIZE(navi10_cache_info);
break;
case IP_VERSION(10, 1, 1):
- pcache_info = navi14_cache_info;
+ *pcache_info = navi14_cache_info;
num_of_cache_types = ARRAY_SIZE(navi14_cache_info);
break;
case IP_VERSION(10, 3, 0):
- pcache_info = sienna_cichlid_cache_info;
+ *pcache_info = sienna_cichlid_cache_info;
num_of_cache_types = ARRAY_SIZE(sienna_cichlid_cache_info);
break;
case IP_VERSION(10, 3, 2):
- pcache_info = navy_flounder_cache_info;
+ *pcache_info = navy_flounder_cache_info;
num_of_cache_types = ARRAY_SIZE(navy_flounder_cache_info);
break;
case IP_VERSION(10, 3, 4):
- pcache_info = dimgrey_cavefish_cache_info;
+ *pcache_info = dimgrey_cavefish_cache_info;
num_of_cache_types = ARRAY_SIZE(dimgrey_cavefish_cache_info);
break;
case IP_VERSION(10, 3, 1):
- pcache_info = vangogh_cache_info;
+ *pcache_info = vangogh_cache_info;
num_of_cache_types = ARRAY_SIZE(vangogh_cache_info);
break;
case IP_VERSION(10, 3, 5):
- pcache_info = beige_goby_cache_info;
+ *pcache_info = beige_goby_cache_info;
num_of_cache_types = ARRAY_SIZE(beige_goby_cache_info);
break;
case IP_VERSION(10, 3, 3):
- pcache_info = yellow_carp_cache_info;
+ *pcache_info = yellow_carp_cache_info;
num_of_cache_types = ARRAY_SIZE(yellow_carp_cache_info);
break;
case IP_VERSION(10, 3, 6):
- pcache_info = gc_10_3_6_cache_info;
+ *pcache_info = gc_10_3_6_cache_info;
num_of_cache_types = ARRAY_SIZE(gc_10_3_6_cache_info);
break;
case IP_VERSION(10, 3, 7):
- pcache_info = gfx1037_cache_info;
+ *pcache_info = gfx1037_cache_info;
num_of_cache_types = ARRAY_SIZE(gfx1037_cache_info);
break;
case IP_VERSION(11, 0, 0):
case IP_VERSION(11, 0, 1):
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
- pcache_info = cache_info;
+ 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, *pcache_info);
break;
default:
- return -EINVAL;
- }
- }
-
- *size_filled = 0;
- *num_of_entries = 0;
-
- /* For each type of cache listed in the kfd_gpu_cache_info table,
- * go through all available Compute Units.
- * The [i,j,k] loop will
- * if kfd_gpu_cache_info.num_cu_shared = 1
- * will parse through all available CU
- * If (kfd_gpu_cache_info.num_cu_shared != 1)
- * then it will consider only one CU from
- * the shared unit
- */
-
- for (ct = 0; ct < num_of_cache_types; ct++) {
- cu_processor_id = gpu_processor_id;
- if (pcache_info[ct].cache_level == 1) {
- for (i = 0; i < cu_info->num_shader_engines; i++) {
- for (j = 0; j < cu_info->num_shader_arrays_per_engine; j++) {
- for (k = 0; k < cu_info->num_cu_per_sh;
- k += pcache_info[ct].num_cu_shared) {
- ret = fill_in_l1_pcache(pcache,
- pcache_info,
- cu_info,
- mem_available,
- cu_info->cu_bitmap[i % 4][j + i / 4],
- ct,
- cu_processor_id,
- k);
-
- if (ret < 0)
+ *pcache_info = dummy_cache_info;
+ num_of_cache_types = ARRAY_SIZE(dummy_cache_info);
+ pr_warn("dummy cache info is used temporarily and real cache info need update later.\n");
break;
-
- if (!ret) {
- pcache++;
- (*num_of_entries)++;
- mem_available -= sizeof(*pcache);
- (*size_filled) += sizeof(*pcache);
- }
-
- /* Move to next CU block */
- num_cu_shared = ((k + pcache_info[ct].num_cu_shared) <=
- cu_info->num_cu_per_sh) ?
- pcache_info[ct].num_cu_shared :
- (cu_info->num_cu_per_sh - k);
- cu_processor_id += num_cu_shared;
}
- }
- }
- } else {
- ret = fill_in_l2_l3_pcache(pcache,
- pcache_info,
- cu_info,
- mem_available,
- ct,
- cu_processor_id);
-
- if (ret < 0)
- break;
-
- if (!ret) {
- pcache++;
- (*num_of_entries)++;
- mem_available -= sizeof(*pcache);
- (*size_filled) += sizeof(*pcache);
- }
- }
}
-
- pr_debug("Added [%d] GPU cache entries\n", *num_of_entries);
-
- return 0;
+ return num_of_cache_types;
}
static bool kfd_ignore_crat(void)
@@ -2063,8 +1891,8 @@ static void kfd_find_numa_node_in_srat(struct kfd_dev *kdev)
struct acpi_table_header *table_header = NULL;
struct acpi_subtable_header *sub_header = NULL;
unsigned long table_end, subtable_len;
- u32 pci_id = pci_domain_nr(kdev->pdev->bus) << 16 |
- pci_dev_id(kdev->pdev);
+ u32 pci_id = pci_domain_nr(kdev->adev->pdev->bus) << 16 |
+ pci_dev_id(kdev->adev->pdev);
u32 bdf;
acpi_status status;
struct acpi_srat_cpu_affinity *cpu;
@@ -2139,7 +1967,7 @@ static void kfd_find_numa_node_in_srat(struct kfd_dev *kdev)
numa_node = 0;
if (numa_node != NUMA_NO_NODE)
- set_dev_node(&kdev->pdev->dev, numa_node);
+ set_dev_node(&kdev->adev->pdev->dev, numa_node);
}
#endif
@@ -2200,14 +2028,14 @@ 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->pdev->dev.numa_node == NUMA_NO_NODE)
+ if (kdev->adev->pdev->dev.numa_node == NUMA_NO_NODE)
kfd_find_numa_node_in_srat(kdev);
#endif
#ifdef CONFIG_NUMA
- if (kdev->pdev->dev.numa_node == NUMA_NO_NODE)
+ if (kdev->adev->pdev->dev.numa_node == NUMA_NO_NODE)
sub_type_hdr->proximity_domain_to = 0;
else
- sub_type_hdr->proximity_domain_to = kdev->pdev->dev.numa_node;
+ sub_type_hdr->proximity_domain_to = kdev->adev->pdev->dev.numa_node;
#else
sub_type_hdr->proximity_domain_to = 0;
#endif
@@ -2263,8 +2091,6 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
struct kfd_cu_info cu_info;
int avail_size = *size;
uint32_t total_num_of_cu;
- int num_of_cache_entries = 0;
- int cache_mem_filled = 0;
uint32_t nid = 0;
int ret = 0;
@@ -2365,31 +2191,12 @@ static int kfd_create_vcrat_image_gpu(void *pcrat_image,
crat_table->length += sizeof(struct crat_subtype_memory);
crat_table->total_entries++;
- /* TODO: Fill in cache information. This information is NOT readily
- * available in KGD
- */
- sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +
- sub_type_hdr->length);
- ret = kfd_fill_gpu_cache_info(kdev, cu->processor_id_low,
- avail_size,
- &cu_info,
- (struct crat_subtype_cache *)sub_type_hdr,
- &cache_mem_filled,
- &num_of_cache_entries);
-
- if (ret < 0)
- return ret;
-
- crat_table->length += cache_mem_filled;
- crat_table->total_entries += num_of_cache_entries;
- avail_size -= cache_mem_filled;
-
/* Fill in Subtype: IO_LINKS
* Only direct links are added here which is Link from GPU to
* its NUMA node. Indirect links are added by userspace.
*/
sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +
- cache_mem_filled);
+ sub_type_hdr->length);
ret = kfd_fill_gpu_direct_io_link_to_cpu(&avail_size, kdev,
(struct crat_subtype_iolink *)sub_type_hdr, proximity_domain);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
index 482ba84a728d..8d1e8ba58dee 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.h
@@ -29,11 +29,10 @@
#pragma pack(1)
/*
- * 4CC signature values for the CRAT and CDIT ACPI tables
+ * 4CC signature value for the CRAT ACPI table
*/
#define CRAT_SIGNATURE "CRAT"
-#define CDIT_SIGNATURE "CDIT"
/*
* Component Resource Association Table (CRAT)
@@ -292,31 +291,22 @@ struct crat_subtype_generic {
uint32_t flags;
};
-/*
- * Component Locality Distance Information Table (CDIT)
- */
-#define CDIT_OEMID_LENGTH 6
-#define CDIT_OEMTABLEID_LENGTH 8
-
-struct cdit_header {
- uint32_t signature;
- uint32_t length;
- uint8_t revision;
- uint8_t checksum;
- uint8_t oem_id[CDIT_OEMID_LENGTH];
- uint8_t oem_table_id[CDIT_OEMTABLEID_LENGTH];
- uint32_t oem_revision;
- uint32_t creator_id;
- uint32_t creator_revision;
- uint32_t total_entries;
- uint16_t num_domains;
- uint8_t entry[1];
-};
-
#pragma pack()
struct kfd_dev;
+/* Static table to describe GPU Cache information */
+struct kfd_gpu_cache_info {
+ uint32_t cache_size;
+ uint32_t cache_level;
+ uint32_t flags;
+ /* Indicates how many Compute Units share this cache
+ * within a SA. Value = 1 indicates the cache is not shared
+ */
+ uint32_t num_cu_shared;
+};
+int kfd_get_gpu_cache_info(struct kfd_dev *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,
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
index 65a1d4f9004b..b8936340742b 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
@@ -153,6 +153,7 @@ static void kfd_device_info_set_event_interrupt_class(struct kfd_dev *kfd)
case IP_VERSION(11, 0, 1):
case IP_VERSION(11, 0, 2):
case IP_VERSION(11, 0, 3):
+ case IP_VERSION(11, 0, 4):
kfd->device_info.event_interrupt_class = &event_interrupt_class_v11;
break;
default:
@@ -227,7 +228,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
{
struct kfd_dev *kfd = NULL;
const struct kfd2kgd_calls *f2g = NULL;
- struct pci_dev *pdev = adev->pdev;
uint32_t gfx_target_version = 0;
switch (adev->asic_type) {
@@ -395,6 +395,7 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
f2g = &gfx_v11_kfd2kgd;
break;
case IP_VERSION(11, 0, 1):
+ case IP_VERSION(11, 0, 4):
gfx_target_version = 110003;
f2g = &gfx_v11_kfd2kgd;
break;
@@ -429,7 +430,6 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
kfd->adev = adev;
kfd_device_info_init(kfd, vf, gfx_target_version);
- kfd->pdev = pdev;
kfd->init_complete = false;
kfd->kfd2kgd = f2g;
atomic_set(&kfd->compute_profile, 0);
@@ -497,7 +497,10 @@ static int kfd_gws_init(struct kfd_dev *kfd)
(KFD_GC_VERSION(kfd) == IP_VERSION(9, 4, 1)
&& kfd->mec2_fw_version >= 0x30) ||
(KFD_GC_VERSION(kfd) == IP_VERSION(9, 4, 2)
- && kfd->mec2_fw_version >= 0x28))))
+ && kfd->mec2_fw_version >= 0x28) ||
+ (KFD_GC_VERSION(kfd) >= IP_VERSION(10, 3, 0)
+ && KFD_GC_VERSION(kfd) < IP_VERSION(11, 0, 0)
+ && kfd->mec2_fw_version >= 0x6b))))
ret = amdgpu_amdkfd_alloc_gws(kfd->adev,
kfd->adev->gds.gws_size, &kfd->gws);
@@ -511,12 +514,10 @@ static void kfd_smi_init(struct kfd_dev *dev)
}
bool kgd2kfd_device_init(struct kfd_dev *kfd,
- struct drm_device *ddev,
const struct kgd2kfd_shared_resources *gpu_resources)
{
unsigned int size, map_process_packet_size;
- kfd->ddev = ddev;
kfd->mec_fw_version = amdgpu_amdkfd_get_fw_version(kfd->adev,
KGD_ENGINE_MEC1);
kfd->mec2_fw_version = amdgpu_amdkfd_get_fw_version(kfd->adev,
@@ -541,7 +542,7 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
kfd->mec_fw_version < kfd->device_info.no_atomic_fw_version)) {
dev_info(kfd_device,
"skipped device %x:%x, PCI rejects atomics %d<%d\n",
- kfd->pdev->vendor, kfd->pdev->device,
+ kfd->adev->pdev->vendor, kfd->adev->pdev->device,
kfd->mec_fw_version,
kfd->device_info.no_atomic_fw_version);
return false;
@@ -650,8 +651,8 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd,
kfd_smi_init(kfd);
kfd->init_complete = true;
- dev_info(kfd_device, "added device %x:%x\n", kfd->pdev->vendor,
- kfd->pdev->device);
+ 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);
@@ -676,7 +677,7 @@ alloc_gtt_mem_failure:
amdgpu_amdkfd_free_gws(kfd->adev, kfd->gws);
dev_err(kfd_device,
"device %x:%x NOT added due to errors\n",
- kfd->pdev->vendor, kfd->pdev->device);
+ kfd->adev->pdev->vendor, kfd->adev->pdev->device);
out:
return kfd->init_complete;
}
@@ -789,7 +790,7 @@ int kgd2kfd_resume_iommu(struct kfd_dev *kfd)
if (err)
dev_err(kfd_device,
"Failed to resume IOMMU for device %x:%x\n",
- kfd->pdev->vendor, kfd->pdev->device);
+ kfd->adev->pdev->vendor, kfd->adev->pdev->device);
return err;
}
@@ -801,7 +802,7 @@ static int kfd_resume(struct kfd_dev *kfd)
if (err)
dev_err(kfd_device,
"Error starting queue manager for device %x:%x\n",
- kfd->pdev->vendor, kfd->pdev->device);
+ kfd->adev->pdev->vendor, kfd->adev->pdev->device);
return err;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c b/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c
index fbd0afe4da42..ec1bf611624e 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_iommu.c
@@ -49,7 +49,7 @@ int kfd_iommu_check_device(struct kfd_dev *kfd)
return -ENODEV;
iommu_info.flags = 0;
- err = amd_iommu_device_info(kfd->pdev, &iommu_info);
+ err = amd_iommu_device_info(kfd->adev->pdev, &iommu_info);
if (err)
return err;
@@ -71,7 +71,7 @@ int kfd_iommu_device_init(struct kfd_dev *kfd)
return 0;
iommu_info.flags = 0;
- err = amd_iommu_device_info(kfd->pdev, &iommu_info);
+ err = amd_iommu_device_info(kfd->adev->pdev, &iommu_info);
if (err < 0) {
dev_err(kfd_device,
"error getting iommu info. is the iommu enabled?\n");
@@ -121,7 +121,7 @@ int kfd_iommu_bind_process_to_device(struct kfd_process_device *pdd)
return -EINVAL;
}
- err = amd_iommu_bind_pasid(dev->pdev, p->pasid, p->lead_thread);
+ err = amd_iommu_bind_pasid(dev->adev->pdev, p->pasid, p->lead_thread);
if (!err)
pdd->bound = PDD_BOUND;
@@ -139,7 +139,8 @@ void kfd_iommu_unbind_process(struct kfd_process *p)
for (i = 0; i < p->n_pdds; i++)
if (p->pdds[i]->bound == PDD_BOUND)
- amd_iommu_unbind_pasid(p->pdds[i]->dev->pdev, p->pasid);
+ amd_iommu_unbind_pasid(p->pdds[i]->dev->adev->pdev,
+ p->pasid);
}
/* Callback for process shutdown invoked by the IOMMU driver */
@@ -222,7 +223,7 @@ static int kfd_bind_processes_to_device(struct kfd_dev *kfd)
continue;
}
- err = amd_iommu_bind_pasid(kfd->pdev, p->pasid,
+ err = amd_iommu_bind_pasid(kfd->adev->pdev, p->pasid,
p->lead_thread);
if (err < 0) {
pr_err("Unexpected pasid 0x%x binding failure\n",
@@ -282,9 +283,9 @@ void kfd_iommu_suspend(struct kfd_dev *kfd)
kfd_unbind_processes_from_device(kfd);
- amd_iommu_set_invalidate_ctx_cb(kfd->pdev, NULL);
- amd_iommu_set_invalid_ppr_cb(kfd->pdev, NULL);
- amd_iommu_free_device(kfd->pdev);
+ amd_iommu_set_invalidate_ctx_cb(kfd->adev->pdev, NULL);
+ amd_iommu_set_invalid_ppr_cb(kfd->adev->pdev, NULL);
+ amd_iommu_free_device(kfd->adev->pdev);
}
/** kfd_iommu_resume - Restore IOMMU after resume
@@ -302,20 +303,20 @@ int kfd_iommu_resume(struct kfd_dev *kfd)
pasid_limit = kfd_get_pasid_limit();
- err = amd_iommu_init_device(kfd->pdev, pasid_limit);
+ err = amd_iommu_init_device(kfd->adev->pdev, pasid_limit);
if (err)
return -ENXIO;
- amd_iommu_set_invalidate_ctx_cb(kfd->pdev,
+ amd_iommu_set_invalidate_ctx_cb(kfd->adev->pdev,
iommu_pasid_shutdown_callback);
- amd_iommu_set_invalid_ppr_cb(kfd->pdev,
+ amd_iommu_set_invalid_ppr_cb(kfd->adev->pdev,
iommu_invalid_ppr_cb);
err = kfd_bind_processes_to_device(kfd);
if (err) {
- amd_iommu_set_invalidate_ctx_cb(kfd->pdev, NULL);
- amd_iommu_set_invalid_ppr_cb(kfd->pdev, NULL);
- amd_iommu_free_device(kfd->pdev);
+ amd_iommu_set_invalidate_ctx_cb(kfd->adev->pdev, NULL);
+ amd_iommu_set_invalid_ppr_cb(kfd->adev->pdev, NULL);
+ amd_iommu_free_device(kfd->adev->pdev);
return err;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index 22b077ac9a19..10048ce16aea 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -28,7 +28,6 @@
#include "amdgpu_sync.h"
#include "amdgpu_object.h"
#include "amdgpu_vm.h"
-#include "amdgpu_mn.h"
#include "amdgpu_res_cursor.h"
#include "kfd_priv.h"
#include "kfd_svm.h"
@@ -65,8 +64,11 @@ 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, num_dw * 4 + num_bytes,
- AMDGPU_IB_POOL_DELAYED, &job);
+ r = amdgpu_job_alloc_with_ib(adev, &adev->mman.entity,
+ AMDGPU_FENCE_OWNER_UNDEFINED,
+ num_dw * 4 + num_bytes,
+ AMDGPU_IB_POOL_DELAYED,
+ &job);
if (r)
return r;
@@ -89,18 +91,10 @@ svm_migrate_gart_map(struct amdgpu_ring *ring, uint64_t npages,
cpu_addr = &job->ibs[0].ptr[num_dw];
amdgpu_gart_map(adev, 0, npages, addr, pte_flags, cpu_addr);
- r = amdgpu_job_submit(job, &adev->mman.entity,
- AMDGPU_FENCE_OWNER_UNDEFINED, &fence);
- if (r)
- goto error_free;
-
+ fence = amdgpu_job_submit(job);
dma_fence_put(fence);
return r;
-
-error_free:
- amdgpu_job_free(job);
- return r;
}
/**
@@ -529,8 +523,8 @@ svm_migrate_ram_to_vram(struct svm_range *prange, uint32_t best_loc,
for (addr = start; addr < end;) {
unsigned long next;
- vma = find_vma(mm, addr);
- if (!vma || addr < vma->vm_start)
+ vma = vma_lookup(mm, addr);
+ if (!vma)
break;
next = min(vma->vm_end, end);
@@ -798,8 +792,8 @@ int svm_migrate_vram_to_ram(struct svm_range *prange, struct mm_struct *mm,
for (addr = start; addr < end;) {
unsigned long next;
- vma = find_vma(mm, addr);
- if (!vma || addr < vma->vm_start) {
+ vma = vma_lookup(mm, addr);
+ if (!vma) {
pr_debug("failed to find vma for prange %p\n", prange);
r = -EFAULT;
break;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_pm4_headers_diq.h b/drivers/gpu/drm/amd/amdkfd/kfd_pm4_headers_diq.h
deleted file mode 100644
index f9cd28690151..000000000000
--- a/drivers/gpu/drm/amd/amdkfd/kfd_pm4_headers_diq.h
+++ /dev/null
@@ -1,291 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 OR MIT */
-/*
- * Copyright 2014-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 KFD_PM4_HEADERS_DIQ_H_
-#define KFD_PM4_HEADERS_DIQ_H_
-
-/*--------------------_INDIRECT_BUFFER-------------------- */
-
-#ifndef _PM4__INDIRECT_BUFFER_DEFINED
-#define _PM4__INDIRECT_BUFFER_DEFINED
-enum _INDIRECT_BUFFER_cache_policy_enum {
- cache_policy___indirect_buffer__lru = 0,
- cache_policy___indirect_buffer__stream = 1,
- cache_policy___indirect_buffer__bypass = 2
-};
-
-enum {
- IT_INDIRECT_BUFFER_PASID = 0x5C
-};
-
-struct pm4__indirect_buffer_pasid {
- union {
- union PM4_MES_TYPE_3_HEADER header; /* header */
- unsigned int ordinal1;
- };
-
- union {
- struct {
- unsigned int reserved1:2;
- unsigned int ib_base_lo:30;
- } bitfields2;
- unsigned int ordinal2;
- };
-
- union {
- struct {
- unsigned int ib_base_hi:16;
- unsigned int reserved2:16;
- } bitfields3;
- unsigned int ordinal3;
- };
-
- union {
- unsigned int control;
- unsigned int ordinal4;
- };
-
- union {
- struct {
- unsigned int pasid:10;
- unsigned int reserved4:22;
- } bitfields5;
- unsigned int ordinal5;
- };
-
-};
-
-#endif
-
-/*--------------------_RELEASE_MEM-------------------- */
-
-#ifndef _PM4__RELEASE_MEM_DEFINED
-#define _PM4__RELEASE_MEM_DEFINED
-enum _RELEASE_MEM_event_index_enum {
- event_index___release_mem__end_of_pipe = 5,
- event_index___release_mem__shader_done = 6
-};
-
-enum _RELEASE_MEM_cache_policy_enum {
- cache_policy___release_mem__lru = 0,
- cache_policy___release_mem__stream = 1,
- cache_policy___release_mem__bypass = 2
-};
-
-enum _RELEASE_MEM_dst_sel_enum {
- dst_sel___release_mem__memory_controller = 0,
- dst_sel___release_mem__tc_l2 = 1,
- dst_sel___release_mem__queue_write_pointer_register = 2,
- dst_sel___release_mem__queue_write_pointer_poll_mask_bit = 3
-};
-
-enum _RELEASE_MEM_int_sel_enum {
- int_sel___release_mem__none = 0,
- int_sel___release_mem__send_interrupt_only = 1,
- int_sel___release_mem__send_interrupt_after_write_confirm = 2,
- int_sel___release_mem__send_data_after_write_confirm = 3
-};
-
-enum _RELEASE_MEM_data_sel_enum {
- data_sel___release_mem__none = 0,
- data_sel___release_mem__send_32_bit_low = 1,
- data_sel___release_mem__send_64_bit_data = 2,
- data_sel___release_mem__send_gpu_clock_counter = 3,
- data_sel___release_mem__send_cp_perfcounter_hi_lo = 4,
- data_sel___release_mem__store_gds_data_to_memory = 5
-};
-
-struct pm4__release_mem {
- union {
- union PM4_MES_TYPE_3_HEADER header; /*header */
- unsigned int ordinal1;
- };
-
- union {
- struct {
- unsigned int event_type:6;
- unsigned int reserved1:2;
- enum _RELEASE_MEM_event_index_enum event_index:4;
- unsigned int tcl1_vol_action_ena:1;
- unsigned int tc_vol_action_ena:1;
- unsigned int reserved2:1;
- unsigned int tc_wb_action_ena:1;
- unsigned int tcl1_action_ena:1;
- unsigned int tc_action_ena:1;
- unsigned int reserved3:6;
- unsigned int atc:1;
- enum _RELEASE_MEM_cache_policy_enum cache_policy:2;
- unsigned int reserved4:5;
- } bitfields2;
- unsigned int ordinal2;
- };
-
- union {
- struct {
- unsigned int reserved5:16;
- enum _RELEASE_MEM_dst_sel_enum dst_sel:2;
- unsigned int reserved6:6;
- enum _RELEASE_MEM_int_sel_enum int_sel:3;
- unsigned int reserved7:2;
- enum _RELEASE_MEM_data_sel_enum data_sel:3;
- } bitfields3;
- unsigned int ordinal3;
- };
-
- union {
- struct {
- unsigned int reserved8:2;
- unsigned int address_lo_32b:30;
- } bitfields4;
- struct {
- unsigned int reserved9:3;
- unsigned int address_lo_64b:29;
- } bitfields5;
- unsigned int ordinal4;
- };
-
- unsigned int address_hi;
-
- unsigned int data_lo;
-
- unsigned int data_hi;
-
-};
-#endif
-
-
-/*--------------------_SET_CONFIG_REG-------------------- */
-
-#ifndef _PM4__SET_CONFIG_REG_DEFINED
-#define _PM4__SET_CONFIG_REG_DEFINED
-
-struct pm4__set_config_reg {
- union {
- union PM4_MES_TYPE_3_HEADER header; /*header */
- unsigned int ordinal1;
- };
-
- union {
- struct {
- unsigned int reg_offset:16;
- unsigned int reserved1:7;
- unsigned int vmid_shift:5;
- unsigned int insert_vmid:1;
- unsigned int reserved2:3;
- } bitfields2;
- unsigned int ordinal2;
- };
-
- unsigned int reg_data[1]; /*1..N of these fields */
-
-};
-#endif
-
-/*--------------------_WAIT_REG_MEM-------------------- */
-
-#ifndef _PM4__WAIT_REG_MEM_DEFINED
-#define _PM4__WAIT_REG_MEM_DEFINED
-enum _WAIT_REG_MEM_function_enum {
- function___wait_reg_mem__always_pass = 0,
- function___wait_reg_mem__less_than_ref_value = 1,
- function___wait_reg_mem__less_than_equal_to_the_ref_value = 2,
- function___wait_reg_mem__equal_to_the_reference_value = 3,
- function___wait_reg_mem__not_equal_reference_value = 4,
- function___wait_reg_mem__greater_than_or_equal_reference_value = 5,
- function___wait_reg_mem__greater_than_reference_value = 6,
- function___wait_reg_mem__reserved = 7
-};
-
-enum _WAIT_REG_MEM_mem_space_enum {
- mem_space___wait_reg_mem__register_space = 0,
- mem_space___wait_reg_mem__memory_space = 1
-};
-
-enum _WAIT_REG_MEM_operation_enum {
- operation___wait_reg_mem__wait_reg_mem = 0,
- operation___wait_reg_mem__wr_wait_wr_reg = 1
-};
-
-struct pm4__wait_reg_mem {
- union {
- union PM4_MES_TYPE_3_HEADER header; /*header */
- unsigned int ordinal1;
- };
-
- union {
- struct {
- enum _WAIT_REG_MEM_function_enum function:3;
- unsigned int reserved1:1;
- enum _WAIT_REG_MEM_mem_space_enum mem_space:2;
- enum _WAIT_REG_MEM_operation_enum operation:2;
- unsigned int reserved2:24;
- } bitfields2;
- unsigned int ordinal2;
- };
-
- union {
- struct {
- unsigned int reserved3:2;
- unsigned int memory_poll_addr_lo:30;
- } bitfields3;
- struct {
- unsigned int register_poll_addr:16;
- unsigned int reserved4:16;
- } bitfields4;
- struct {
- unsigned int register_write_addr:16;
- unsigned int reserved5:16;
- } bitfields5;
- unsigned int ordinal3;
- };
-
- union {
- struct {
- unsigned int poll_address_hi:16;
- unsigned int reserved6:16;
- } bitfields6;
- struct {
- unsigned int register_write_addr:16;
- unsigned int reserved7:16;
- } bitfields7;
- unsigned int ordinal4;
- };
-
- unsigned int reference;
-
- unsigned int mask;
-
- union {
- struct {
- unsigned int poll_interval:16;
- unsigned int reserved8:16;
- } bitfields8;
- unsigned int ordinal7;
- };
-
-};
-#endif
-
-
-#endif /* KFD_PM4_HEADERS_DIQ_H_ */
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
index bf610e3b683b..552c3ac85a13 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
@@ -254,8 +254,6 @@ struct kfd_dev {
struct amdgpu_device *adev;
struct kfd_device_info device_info;
- struct pci_dev *pdev;
- struct drm_device *ddev;
unsigned int id; /* topology stub index */
@@ -1365,7 +1363,7 @@ void kfd_dec_compute_active(struct kfd_dev *dev);
static inline int kfd_devcgroup_check_permission(struct kfd_dev *kfd)
{
#if defined(CONFIG_CGROUP_DEVICE) || defined(CONFIG_CGROUP_BPF)
- struct drm_device *ddev = kfd->ddev;
+ struct drm_device *ddev = adev_to_drm(kfd->adev);
return devcgroup_check_permission(DEVCG_DEV_CHAR, DRM_MAJOR,
ddev->render->index,
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index 951b63677248..a26257171ab7 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -1050,8 +1050,8 @@ static void kfd_process_destroy_pdds(struct kfd_process *p)
* for auto suspend
*/
if (pdd->runtime_inuse) {
- pm_runtime_mark_last_busy(pdd->dev->ddev->dev);
- pm_runtime_put_autosuspend(pdd->dev->ddev->dev);
+ pm_runtime_mark_last_busy(adev_to_drm(pdd->dev->adev)->dev);
+ pm_runtime_put_autosuspend(adev_to_drm(pdd->dev->adev)->dev);
pdd->runtime_inuse = false;
}
@@ -1633,9 +1633,9 @@ struct kfd_process_device *kfd_bind_process_to_device(struct kfd_dev *dev,
* pdd is destroyed.
*/
if (!pdd->runtime_inuse) {
- err = pm_runtime_get_sync(dev->ddev->dev);
+ err = pm_runtime_get_sync(adev_to_drm(dev->adev)->dev);
if (err < 0) {
- pm_runtime_put_autosuspend(dev->ddev->dev);
+ pm_runtime_put_autosuspend(adev_to_drm(dev->adev)->dev);
return ERR_PTR(err);
}
}
@@ -1655,8 +1655,8 @@ struct kfd_process_device *kfd_bind_process_to_device(struct kfd_dev *dev,
out:
/* balance runpm reference count and exit with error */
if (!pdd->runtime_inuse) {
- pm_runtime_mark_last_busy(dev->ddev->dev);
- pm_runtime_put_autosuspend(dev->ddev->dev);
+ pm_runtime_mark_last_busy(adev_to_drm(dev->adev)->dev);
+ pm_runtime_put_autosuspend(adev_to_drm(dev->adev)->dev);
}
return ERR_PTR(err);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
index 64fdf63093a0..814f99888ab1 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c
@@ -26,7 +26,7 @@
#include "amdgpu_sync.h"
#include "amdgpu_object.h"
#include "amdgpu_vm.h"
-#include "amdgpu_mn.h"
+#include "amdgpu_hmm.h"
#include "amdgpu.h"
#include "amdgpu_xgmi.h"
#include "kfd_priv.h"
@@ -259,7 +259,7 @@ void svm_range_free_dma_mappings(struct svm_range *prange)
pr_debug("failed to find device idx %d\n", gpuidx);
continue;
}
- dev = &pdd->dev->pdev->dev;
+ dev = &pdd->dev->adev->pdev->dev;
svm_range_dma_unmap(dev, dma_addr, 0, prange->npages);
kvfree(dma_addr);
prange->dma_addr[gpuidx] = NULL;
@@ -1586,8 +1586,8 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
unsigned long npages;
bool readonly;
- vma = find_vma(mm, addr);
- if (!vma || addr < vma->vm_start) {
+ vma = vma_lookup(mm, addr);
+ if (!vma) {
r = -EFAULT;
goto unreserve_out;
}
@@ -1596,9 +1596,9 @@ static int svm_range_validate_and_map(struct mm_struct *mm,
next = min(vma->vm_end, end);
npages = (next - addr) >> PAGE_SHIFT;
WRITE_ONCE(p->svms.faulting_task, current);
- r = amdgpu_hmm_range_get_pages(&prange->notifier, mm, NULL,
- addr, npages, &hmm_range,
- readonly, true, owner);
+ r = amdgpu_hmm_range_get_pages(&prange->notifier, addr, npages,
+ readonly, owner, NULL,
+ &hmm_range);
WRITE_ONCE(p->svms.faulting_task, NULL);
if (r) {
pr_debug("failed %d to get svm range pages\n", r);
@@ -2542,8 +2542,8 @@ svm_range_get_range_boundaries(struct kfd_process *p, int64_t addr,
struct interval_tree_node *node;
unsigned long start_limit, end_limit;
- vma = find_vma(p->mm, addr << PAGE_SHIFT);
- if (!vma || (addr << PAGE_SHIFT) < vma->vm_start) {
+ vma = vma_lookup(p->mm, addr << PAGE_SHIFT);
+ if (!vma) {
pr_debug("VMA does not exist in address [0x%llx]\n", addr);
return -EFAULT;
}
@@ -2871,8 +2871,8 @@ retry_write_locked:
/* __do_munmap removed VMA, return success as we are handling stale
* retry fault.
*/
- vma = find_vma(mm, addr << PAGE_SHIFT);
- if (!vma || (addr << PAGE_SHIFT) < vma->vm_start) {
+ vma = vma_lookup(mm, addr << PAGE_SHIFT);
+ if (!vma) {
pr_debug("address 0x%llx VMA is removed\n", addr);
r = 0;
goto out_unlock_range;
@@ -3152,9 +3152,8 @@ svm_range_is_valid(struct kfd_process *p, uint64_t start, uint64_t size)
start <<= PAGE_SHIFT;
end = start + (size << PAGE_SHIFT);
do {
- vma = find_vma(p->mm, start);
- if (!vma || start < vma->vm_start ||
- (vma->vm_flags & device_vma))
+ vma = vma_lookup(p->mm, start);
+ if (!vma || (vma->vm_flags & device_vma))
return -EFAULT;
start = min(end, vma->vm_end);
} while (start < end);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
index 3f0a4a415907..bceb1a5b2518 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c
@@ -115,7 +115,7 @@ struct kfd_dev *kfd_device_by_pci_dev(const struct pci_dev *pdev)
down_read(&topology_lock);
list_for_each_entry(top_dev, &topology_device_list, list)
- if (top_dev->gpu && top_dev->gpu->pdev == pdev) {
+ if (top_dev->gpu && top_dev->gpu->adev->pdev == pdev) {
device = top_dev->gpu;
break;
}
@@ -364,7 +364,6 @@ static ssize_t kfd_cache_show(struct kobject *kobj, struct attribute *attr,
/* Making sure that the buffer is an empty string */
buffer[0] = 0;
-
cache = container_of(attr, struct kfd_cache_properties, attr);
if (cache->gpu && kfd_devcgroup_check_permission(cache->gpu))
return -EPERM;
@@ -379,12 +378,13 @@ static ssize_t kfd_cache_show(struct kobject *kobj, struct attribute *attr,
sysfs_show_32bit_prop(buffer, offs, "association", cache->cache_assoc);
sysfs_show_32bit_prop(buffer, offs, "latency", cache->cache_latency);
sysfs_show_32bit_prop(buffer, offs, "type", cache->cache_type);
+
offs += snprintf(buffer+offs, PAGE_SIZE-offs, "sibling_map ");
- for (i = 0; i < CRAT_SIBLINGMAP_SIZE; i++)
+ for (i = 0; i < cache->sibling_map_size; i++)
for (j = 0; j < sizeof(cache->sibling_map[0])*8; j++)
/* Check each bit */
offs += snprintf(buffer+offs, PAGE_SIZE-offs, "%d,",
- (cache->sibling_map[i] >> j) & 1);
+ (cache->sibling_map[i] >> j) & 1);
/* Replace the last "," with end of line */
buffer[offs-1] = '\n';
@@ -1169,13 +1169,12 @@ static uint32_t kfd_generate_gpu_id(struct kfd_dev *gpu)
local_mem_size = gpu->local_mem_info.local_mem_size_private +
gpu->local_mem_info.local_mem_size_public;
-
- buf[0] = gpu->pdev->devfn;
- buf[1] = gpu->pdev->subsystem_vendor |
- (gpu->pdev->subsystem_device << 16);
- buf[2] = pci_domain_nr(gpu->pdev->bus);
- buf[3] = gpu->pdev->device;
- buf[4] = gpu->pdev->bus->number;
+ buf[0] = gpu->adev->pdev->devfn;
+ buf[1] = gpu->adev->pdev->subsystem_vendor |
+ (gpu->adev->pdev->subsystem_device << 16);
+ buf[2] = pci_domain_nr(gpu->adev->pdev->bus);
+ buf[3] = gpu->adev->pdev->device;
+ buf[4] = gpu->adev->pdev->bus->number;
buf[5] = lower_32_bits(local_mem_size);
buf[6] = upper_32_bits(local_mem_size);
@@ -1198,7 +1197,6 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
struct kfd_iolink_properties *iolink;
struct kfd_iolink_properties *p2plink;
- down_write(&topology_lock);
list_for_each_entry(dev, &topology_device_list, list) {
/* Discrete GPUs need their own topology device list
* entries. Don't assign them to CPU/APU nodes.
@@ -1222,7 +1220,6 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
break;
}
}
- up_write(&topology_lock);
return out_dev;
}
@@ -1269,7 +1266,7 @@ static void kfd_set_iolink_no_atomics(struct kfd_topology_device *dev,
if (target_gpu_dev) {
uint32_t cap;
- pcie_capability_read_dword(target_gpu_dev->gpu->pdev,
+ pcie_capability_read_dword(target_gpu_dev->gpu->adev->pdev,
PCI_EXP_DEVCAP2, &cap);
if (!(cap & (PCI_EXP_DEVCAP2_ATOMIC_COMP32 |
@@ -1593,21 +1590,290 @@ 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,
+ struct kfd_cu_info *cu_info,
+ int cu_bitmask,
+ int cache_type, unsigned int cu_processor_id,
+ int cu_block)
+{
+ unsigned int cu_sibling_map_mask;
+ int first_active_cu;
+ struct kfd_cache_properties *pcache = NULL;
+
+ cu_sibling_map_mask = cu_bitmask;
+ cu_sibling_map_mask >>= cu_block;
+ cu_sibling_map_mask &= ((1 << pcache_info[cache_type].num_cu_shared) - 1);
+ first_active_cu = ffs(cu_sibling_map_mask);
+
+ /* CU could be inactive. In case of shared cache find the first active
+ * CU. and incase of non-shared cache check if the CU is inactive. If
+ * inactive active skip it
+ */
+ if (first_active_cu) {
+ pcache = kfd_alloc_struct(pcache);
+ if (!pcache)
+ return -ENOMEM;
+
+ memset(pcache, 0, sizeof(struct kfd_cache_properties));
+ pcache->processor_id_low = cu_processor_id + (first_active_cu - 1);
+ pcache->cache_level = pcache_info[cache_type].cache_level;
+ pcache->cache_size = pcache_info[cache_type].cache_size;
+
+ if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_DATA_CACHE)
+ pcache->cache_type |= HSA_CACHE_TYPE_DATA;
+ if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_INST_CACHE)
+ pcache->cache_type |= HSA_CACHE_TYPE_INSTRUCTION;
+ if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_CPU_CACHE)
+ pcache->cache_type |= HSA_CACHE_TYPE_CPU;
+ if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_SIMD_CACHE)
+ pcache->cache_type |= HSA_CACHE_TYPE_HSACU;
+
+ /* Sibling map is w.r.t processor_id_low, so shift out
+ * inactive CU
+ */
+ cu_sibling_map_mask =
+ cu_sibling_map_mask >> (first_active_cu - 1);
+
+ pcache->sibling_map[0] = (uint8_t)(cu_sibling_map_mask & 0xFF);
+ pcache->sibling_map[1] =
+ (uint8_t)((cu_sibling_map_mask >> 8) & 0xFF);
+ pcache->sibling_map[2] =
+ (uint8_t)((cu_sibling_map_mask >> 16) & 0xFF);
+ pcache->sibling_map[3] =
+ (uint8_t)((cu_sibling_map_mask >> 24) & 0xFF);
+
+ pcache->sibling_map_size = 4;
+ *props_ext = pcache;
+
+ return 0;
+ }
+ return 1;
+}
+
+/* Helper function. See kfd_fill_gpu_cache_info for parameter description */
+static int fill_in_l2_l3_pcache(struct kfd_cache_properties **props_ext,
+ struct kfd_gpu_cache_info *pcache_info,
+ struct kfd_cu_info *cu_info,
+ int cache_type, unsigned int cu_processor_id)
+{
+ unsigned int cu_sibling_map_mask;
+ int first_active_cu;
+ int i, j, k;
+ struct kfd_cache_properties *pcache = NULL;
+
+ cu_sibling_map_mask = cu_info->cu_bitmap[0][0];
+ cu_sibling_map_mask &=
+ ((1 << pcache_info[cache_type].num_cu_shared) - 1);
+ first_active_cu = ffs(cu_sibling_map_mask);
+
+ /* CU could be inactive. In case of shared cache find the first active
+ * CU. and incase of non-shared cache check if the CU is inactive. If
+ * inactive active skip it
+ */
+ if (first_active_cu) {
+ pcache = kfd_alloc_struct(pcache);
+ if (!pcache)
+ return -ENOMEM;
+
+ memset(pcache, 0, sizeof(struct kfd_cache_properties));
+ pcache->processor_id_low = cu_processor_id
+ + (first_active_cu - 1);
+ pcache->cache_level = pcache_info[cache_type].cache_level;
+ pcache->cache_size = pcache_info[cache_type].cache_size;
+
+ if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_DATA_CACHE)
+ pcache->cache_type |= HSA_CACHE_TYPE_DATA;
+ if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_INST_CACHE)
+ pcache->cache_type |= HSA_CACHE_TYPE_INSTRUCTION;
+ if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_CPU_CACHE)
+ pcache->cache_type |= HSA_CACHE_TYPE_CPU;
+ if (pcache_info[cache_type].flags & CRAT_CACHE_FLAGS_SIMD_CACHE)
+ pcache->cache_type |= HSA_CACHE_TYPE_HSACU;
+
+ /* Sibling map is w.r.t processor_id_low, so shift out
+ * inactive CU
+ */
+ cu_sibling_map_mask = cu_sibling_map_mask >> (first_active_cu - 1);
+ k = 0;
+
+ for (i = 0; i < cu_info->num_shader_engines; i++) {
+ for (j = 0; j < cu_info->num_shader_arrays_per_engine; j++) {
+ pcache->sibling_map[k] = (uint8_t)(cu_sibling_map_mask & 0xFF);
+ pcache->sibling_map[k+1] = (uint8_t)((cu_sibling_map_mask >> 8) & 0xFF);
+ pcache->sibling_map[k+2] = (uint8_t)((cu_sibling_map_mask >> 16) & 0xFF);
+ pcache->sibling_map[k+3] = (uint8_t)((cu_sibling_map_mask >> 24) & 0xFF);
+ k += 4;
+
+ cu_sibling_map_mask = cu_info->cu_bitmap[i % 4][j + i / 4];
+ cu_sibling_map_mask &= ((1 << pcache_info[cache_type].num_cu_shared) - 1);
+ }
+ }
+ pcache->sibling_map_size = k;
+ *props_ext = pcache;
+ return 0;
+ }
+ return 1;
+}
+
+#define KFD_MAX_CACHE_TYPES 6
+
+/* 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)
+{
+ struct kfd_gpu_cache_info *pcache_info = NULL;
+ int i, j, k;
+ int ct = 0;
+ unsigned int cu_processor_id;
+ int ret;
+ unsigned int num_cu_shared;
+ struct kfd_cu_info cu_info;
+ struct kfd_cu_info *pcu_info;
+ int gpu_processor_id;
+ struct kfd_cache_properties *props_ext;
+ int num_of_entries = 0;
+ int num_of_cache_types = 0;
+ struct kfd_gpu_cache_info cache_info[KFD_MAX_CACHE_TYPES];
+
+ amdgpu_amdkfd_get_cu_info(kdev->adev, &cu_info);
+ pcu_info = &cu_info;
+
+ gpu_processor_id = dev->node_props.simd_id_base;
+
+ pcache_info = cache_info;
+ num_of_cache_types = kfd_get_gpu_cache_info(kdev, &pcache_info);
+ if (!num_of_cache_types) {
+ pr_warn("no cache info found\n");
+ return;
+ }
+
+ /* For each type of cache listed in the kfd_gpu_cache_info table,
+ * go through all available Compute Units.
+ * The [i,j,k] loop will
+ * if kfd_gpu_cache_info.num_cu_shared = 1
+ * will parse through all available CU
+ * If (kfd_gpu_cache_info.num_cu_shared != 1)
+ * then it will consider only one CU from
+ * the shared unit
+ */
+ for (ct = 0; ct < num_of_cache_types; ct++) {
+ cu_processor_id = gpu_processor_id;
+ if (pcache_info[ct].cache_level == 1) {
+ for (i = 0; i < pcu_info->num_shader_engines; i++) {
+ for (j = 0; j < pcu_info->num_shader_arrays_per_engine; j++) {
+ for (k = 0; k < pcu_info->num_cu_per_sh; k += pcache_info[ct].num_cu_shared) {
+
+ ret = fill_in_l1_pcache(&props_ext, pcache_info, pcu_info,
+ pcu_info->cu_bitmap[i % 4][j + i / 4], ct,
+ cu_processor_id, k);
+
+ if (ret < 0)
+ break;
+
+ if (!ret) {
+ num_of_entries++;
+ list_add_tail(&props_ext->list, &dev->cache_props);
+ }
+
+ /* Move to next CU block */
+ num_cu_shared = ((k + pcache_info[ct].num_cu_shared) <=
+ pcu_info->num_cu_per_sh) ?
+ pcache_info[ct].num_cu_shared :
+ (pcu_info->num_cu_per_sh - k);
+ cu_processor_id += num_cu_shared;
+ }
+ }
+ }
+ } else {
+ ret = fill_in_l2_l3_pcache(&props_ext, pcache_info,
+ pcu_info, ct, cu_processor_id);
+
+ if (ret < 0)
+ break;
+
+ if (!ret) {
+ num_of_entries++;
+ list_add_tail(&props_ext->list, &dev->cache_props);
+ }
+ }
+ }
+ dev->node_props.caches_count += num_of_entries;
+ 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,
+ struct kfd_topology_device **dev)
+{
+ int proximity_domain = ++topology_crat_proximity_domain;
+ struct list_head temp_topology_device_list;
+ void *crat_image = NULL;
+ size_t image_size = 0;
+ int res;
+
+ res = kfd_create_crat_image_virtual(&crat_image, &image_size,
+ COMPUTE_UNIT_GPU, gpu,
+ proximity_domain);
+ if (res) {
+ pr_err("Error creating VCRAT for GPU (ID: 0x%x)\n",
+ gpu_id);
+ topology_crat_proximity_domain--;
+ goto err;
+ }
+
+ INIT_LIST_HEAD(&temp_topology_device_list);
+
+ res = kfd_parse_crat_table(crat_image,
+ &temp_topology_device_list,
+ proximity_domain);
+ if (res) {
+ pr_err("Error parsing VCRAT for GPU (ID: 0x%x)\n",
+ gpu_id);
+ topology_crat_proximity_domain--;
+ goto err;
+ }
+
+ kfd_topology_update_device_list(&temp_topology_device_list,
+ &topology_device_list);
+
+ *dev = kfd_assign_gpu(gpu);
+ if (WARN_ON(!*dev)) {
+ res = -ENODEV;
+ goto err;
+ }
+
+ /* Fill the cache affinity information here for the GPUs
+ * using VCRAT
+ */
+ kfd_fill_cache_non_crat_info(*dev, gpu);
+
+ /* Update the SYSFS tree, since we added another topology
+ * device
+ */
+ res = kfd_topology_update_sysfs();
+ if (!res)
+ sys_props.generation_count++;
+ else
+ pr_err("Failed to update GPU (ID: 0x%x) to sysfs topology. res=%d\n",
+ gpu_id, res);
+
+err:
+ kfd_destroy_crat_image(crat_image);
+ return res;
+}
+
int kfd_topology_add_device(struct kfd_dev *gpu)
{
uint32_t gpu_id;
struct kfd_topology_device *dev;
struct kfd_cu_info cu_info;
int res = 0;
- struct list_head temp_topology_device_list;
- void *crat_image = NULL;
- size_t image_size = 0;
- int proximity_domain;
int i;
const char *asic_name = amdgpu_asic_name[gpu->adev->asic_type];
- INIT_LIST_HEAD(&temp_topology_device_list);
-
gpu_id = kfd_generate_gpu_id(gpu);
pr_debug("Adding new GPU (ID: 0x%x) to topology\n", gpu_id);
@@ -1617,50 +1883,13 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
* CRAT to create a new topology device. Once created assign the gpu to
* that topology device
*/
+ down_write(&topology_lock);
dev = kfd_assign_gpu(gpu);
- if (!dev) {
- down_write(&topology_lock);
- proximity_domain = ++topology_crat_proximity_domain;
-
- res = kfd_create_crat_image_virtual(&crat_image, &image_size,
- COMPUTE_UNIT_GPU, gpu,
- proximity_domain);
- if (res) {
- pr_err("Error creating VCRAT for GPU (ID: 0x%x)\n",
- gpu_id);
- topology_crat_proximity_domain--;
- return res;
- }
- res = kfd_parse_crat_table(crat_image,
- &temp_topology_device_list,
- proximity_domain);
- if (res) {
- pr_err("Error parsing VCRAT for GPU (ID: 0x%x)\n",
- gpu_id);
- topology_crat_proximity_domain--;
- goto err;
- }
-
- kfd_topology_update_device_list(&temp_topology_device_list,
- &topology_device_list);
-
- /* Update the SYSFS tree, since we added another topology
- * device
- */
- res = kfd_topology_update_sysfs();
- up_write(&topology_lock);
-
- if (!res)
- sys_props.generation_count++;
- else
- pr_err("Failed to update GPU (ID: 0x%x) to sysfs topology. res=%d\n",
- gpu_id, res);
- dev = kfd_assign_gpu(gpu);
- if (WARN_ON(!dev)) {
- res = -ENODEV;
- goto err;
- }
- }
+ if (!dev)
+ res = kfd_topology_add_device_locked(gpu, gpu_id, &dev);
+ up_write(&topology_lock);
+ if (res)
+ return res;
dev->gpu_id = gpu_id;
gpu->id = gpu_id;
@@ -1688,13 +1917,13 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
cu_info.num_shader_arrays_per_engine;
dev->node_props.gfx_target_version = gpu->device_info.gfx_target_version;
- dev->node_props.vendor_id = gpu->pdev->vendor;
- dev->node_props.device_id = gpu->pdev->device;
+ 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->pdev);
- dev->node_props.domain = pci_domain_nr(gpu->pdev->bus);
+ dev->node_props.location_id = pci_dev_id(gpu->adev->pdev);
+ 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 =
@@ -1783,11 +2012,9 @@ int kfd_topology_add_device(struct kfd_dev *gpu)
kfd_debug_print_topology();
- if (!res)
- kfd_notify_gpu_change(gpu_id, 1);
-err:
- kfd_destroy_crat_image(crat_image);
- return res;
+ kfd_notify_gpu_change(gpu_id, 1);
+
+ return 0;
}
/**
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h
index 9f6c949186c1..fca30d00a9bb 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.h
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.h
@@ -80,6 +80,8 @@ struct kfd_mem_properties {
struct attribute attr;
};
+#define CACHE_SIBLINGMAP_SIZE 64
+
struct kfd_cache_properties {
struct list_head list;
uint32_t processor_id_low;
@@ -90,10 +92,11 @@ struct kfd_cache_properties {
uint32_t cache_assoc;
uint32_t cache_latency;
uint32_t cache_type;
- uint8_t sibling_map[CRAT_SIBLINGMAP_SIZE];
+ uint8_t sibling_map[CACHE_SIBLINGMAP_SIZE];
struct kfd_dev *gpu;
struct kobject *kobj;
struct attribute attr;
+ uint32_t sibling_map_size;
};
struct kfd_iolink_properties {
@@ -128,7 +131,6 @@ struct kfd_topology_device {
uint32_t proximity_domain;
struct kfd_node_properties node_props;
struct list_head mem_props;
- uint32_t cache_count;
struct list_head cache_props;
struct list_head io_link_props;
struct list_head p2p_link_props;
diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig
index f4f3d2665a6b..2efe93f74f84 100644
--- a/drivers/gpu/drm/amd/display/Kconfig
+++ b/drivers/gpu/drm/amd/display/Kconfig
@@ -7,7 +7,8 @@ config DRM_AMD_DC
default y
depends on BROKEN || !CC_IS_CLANG || X86_64 || SPARC64 || ARM64
select SND_HDA_COMPONENT if SND_HDA_CORE
- select DRM_AMD_DC_DCN if (X86 || PPC_LONG_DOUBLE_128)
+ # !CC_IS_CLANG: https://github.com/ClangBuiltLinux/linux/issues/1752
+ select DRM_AMD_DC_DCN if (X86 || PPC_LONG_DOUBLE_128 || (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
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 512c32327eb1..77277d90b6e2 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -82,7 +82,6 @@
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_blend.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_edid.h>
#include <drm/drm_vblank.h>
@@ -147,14 +146,6 @@ MODULE_FIRMWARE(FIRMWARE_NAVI12_DMCU);
/* Number of bytes in PSP footer for firmware. */
#define PSP_FOOTER_BYTES 0x100
-/*
- * DMUB Async to Sync Mechanism Status
- */
-#define DMUB_ASYNC_TO_SYNC_ACCESS_FAIL 1
-#define DMUB_ASYNC_TO_SYNC_ACCESS_TIMEOUT 2
-#define DMUB_ASYNC_TO_SYNC_ACCESS_SUCCESS 3
-#define DMUB_ASYNC_TO_SYNC_ACCESS_INVALID 4
-
/**
* DOC: overview
*
@@ -1105,7 +1096,7 @@ static int dm_dmub_hw_init(struct amdgpu_device *adev)
/* Initialize hardware. */
memset(&hw_params, 0, sizeof(hw_params));
hw_params.fb_base = adev->gmc.fb_start;
- hw_params.fb_offset = adev->gmc.aper_base;
+ hw_params.fb_offset = adev->vm_manager.vram_base_offset;
/* backdoor load firmware and trigger dmub running */
if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
@@ -1227,7 +1218,7 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
pa_config->system_aperture.agp_top = (uint64_t)agp_top << 24;
pa_config->system_aperture.fb_base = adev->gmc.fb_start;
- pa_config->system_aperture.fb_offset = adev->gmc.aper_base;
+ pa_config->system_aperture.fb_offset = adev->vm_manager.vram_base_offset;
pa_config->system_aperture.fb_top = adev->gmc.fb_end;
pa_config->gart_config.page_table_start_addr = page_table_start.quad_part << 12;
@@ -1442,9 +1433,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
memset(&init_params, 0, sizeof(init_params));
#endif
+ mutex_init(&adev->dm.dpia_aux_lock);
mutex_init(&adev->dm.dc_lock);
mutex_init(&adev->dm.audio_lock);
- spin_lock_init(&adev->dm.vblank_lock);
if(amdgpu_dm_irq_init(adev)) {
DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n");
@@ -1807,6 +1798,7 @@ 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;
}
@@ -2858,7 +2850,6 @@ const struct amdgpu_ip_block_version dm_ip_block =
static const struct drm_mode_config_funcs amdgpu_dm_mode_funcs = {
.fb_create = amdgpu_display_user_framebuffer_create,
.get_format_info = amd_get_format_info,
- .output_poll_changed = drm_fb_helper_output_poll_changed,
.atomic_check = amdgpu_dm_atomic_check,
.atomic_commit = drm_atomic_helper_commit,
};
@@ -3864,8 +3855,6 @@ static int amdgpu_dm_mode_config_init(struct amdgpu_device *adev)
/* indicates support for immediate flip */
adev_to_drm(adev)->mode_config.async_page_flip = true;
- adev_to_drm(adev)->mode_config.fb_base = adev->gmc.aper_base;
-
state = kzalloc(sizeof(*state), GFP_KERNEL);
if (!state)
return -ENOMEM;
@@ -4640,6 +4629,7 @@ static int dm_early_init(void *handle)
adev_to_drm(adev)->dev,
&dev_attr_s3_debug);
#endif
+ adev->dc_enabled = true;
return 0;
}
@@ -4879,6 +4869,35 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
return 0;
}
+static inline void fill_dc_dirty_rect(struct drm_plane *plane,
+ struct rect *dirty_rect, int32_t x,
+ int32_t y, int32_t width, int32_t height,
+ int *i, bool ffu)
+{
+ if (*i > DC_MAX_DIRTY_RECTS)
+ return;
+
+ if (*i == DC_MAX_DIRTY_RECTS)
+ goto out;
+
+ dirty_rect->x = x;
+ dirty_rect->y = y;
+ dirty_rect->width = width;
+ dirty_rect->height = height;
+
+ if (ffu)
+ drm_dbg(plane->dev,
+ "[PLANE:%d] PSR FFU dirty rect size (%d, %d)\n",
+ plane->base.id, width, height);
+ else
+ drm_dbg(plane->dev,
+ "[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)",
+ plane->base.id, x, y, width, height);
+
+out:
+ (*i)++;
+}
+
/**
* fill_dc_dirty_rects() - Fill DC dirty regions for PSR selective updates
*
@@ -4899,10 +4918,6 @@ static int fill_dc_plane_attributes(struct amdgpu_device *adev,
* addition, certain use cases - such as cursor and multi-plane overlay (MPO) -
* implicitly provide damage clips without any client support via the plane
* bounds.
- *
- * Today, amdgpu_dm only supports the MPO and cursor usecase.
- *
- * TODO: Also enable for FB_DAMAGE_CLIPS
*/
static void fill_dc_dirty_rects(struct drm_plane *plane,
struct drm_plane_state *old_plane_state,
@@ -4913,12 +4928,11 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
struct dm_crtc_state *dm_crtc_state = to_dm_crtc_state(crtc_state);
struct rect *dirty_rects = flip_addrs->dirty_rects;
uint32_t num_clips;
+ struct drm_mode_rect *clips;
bool bb_changed;
bool fb_changed;
uint32_t i = 0;
- flip_addrs->dirty_rect_count = 0;
-
/*
* Cursor plane has it's own dirty rect update interface. See
* dcn10_dmub_update_cursor_data and dmub_cmd_update_cursor_info_data
@@ -4926,20 +4940,20 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
if (plane->type == DRM_PLANE_TYPE_CURSOR)
return;
- /*
- * Today, we only consider MPO use-case for PSR SU. If MPO not
- * requested, and there is a plane update, do FFU.
- */
+ num_clips = drm_plane_get_damage_clips_count(new_plane_state);
+ clips = drm_plane_get_damage_clips(new_plane_state);
+
if (!dm_crtc_state->mpo_requested) {
- dirty_rects[0].x = 0;
- dirty_rects[0].y = 0;
- dirty_rects[0].width = dm_crtc_state->base.mode.crtc_hdisplay;
- dirty_rects[0].height = dm_crtc_state->base.mode.crtc_vdisplay;
- flip_addrs->dirty_rect_count = 1;
- DRM_DEBUG_DRIVER("[PLANE:%d] PSR FFU dirty rect size (%d, %d)\n",
- new_plane_state->plane->base.id,
- dm_crtc_state->base.mode.crtc_hdisplay,
- dm_crtc_state->base.mode.crtc_vdisplay);
+ if (!num_clips || num_clips > DC_MAX_DIRTY_RECTS)
+ goto ffu;
+
+ for (; flip_addrs->dirty_rect_count < num_clips; clips++)
+ fill_dc_dirty_rect(new_plane_state->plane,
+ &dirty_rects[i], clips->x1,
+ clips->y1, clips->x2 - clips->x1,
+ clips->y2 - clips->y1,
+ &flip_addrs->dirty_rect_count,
+ false);
return;
}
@@ -4950,7 +4964,6 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
* If plane is moved or resized, also add old bounding box to dirty
* rects.
*/
- num_clips = drm_plane_get_damage_clips_count(new_plane_state);
fb_changed = old_plane_state->fb->base.id !=
new_plane_state->fb->base.id;
bb_changed = (old_plane_state->crtc_x != new_plane_state->crtc_x ||
@@ -4958,36 +4971,51 @@ static void fill_dc_dirty_rects(struct drm_plane *plane,
old_plane_state->crtc_w != new_plane_state->crtc_w ||
old_plane_state->crtc_h != new_plane_state->crtc_h);
- DRM_DEBUG_DRIVER("[PLANE:%d] PSR bb_changed:%d fb_changed:%d num_clips:%d\n",
- new_plane_state->plane->base.id,
- bb_changed, fb_changed, num_clips);
+ drm_dbg(plane->dev,
+ "[PLANE:%d] PSR bb_changed:%d fb_changed:%d num_clips:%d\n",
+ new_plane_state->plane->base.id,
+ bb_changed, fb_changed, num_clips);
- if (num_clips || fb_changed || bb_changed) {
- dirty_rects[i].x = new_plane_state->crtc_x;
- dirty_rects[i].y = new_plane_state->crtc_y;
- dirty_rects[i].width = new_plane_state->crtc_w;
- dirty_rects[i].height = new_plane_state->crtc_h;
- DRM_DEBUG_DRIVER("[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)\n",
- new_plane_state->plane->base.id,
- dirty_rects[i].x, dirty_rects[i].y,
- dirty_rects[i].width, dirty_rects[i].height);
- i += 1;
- }
-
- /* Add old plane bounding-box if plane is moved or resized */
if (bb_changed) {
- dirty_rects[i].x = old_plane_state->crtc_x;
- dirty_rects[i].y = old_plane_state->crtc_y;
- dirty_rects[i].width = old_plane_state->crtc_w;
- dirty_rects[i].height = old_plane_state->crtc_h;
- DRM_DEBUG_DRIVER("[PLANE:%d] PSR SU dirty rect at (%d, %d) size (%d, %d)\n",
- old_plane_state->plane->base.id,
- dirty_rects[i].x, dirty_rects[i].y,
- dirty_rects[i].width, dirty_rects[i].height);
- i += 1;
- }
+ fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[i],
+ new_plane_state->crtc_x,
+ new_plane_state->crtc_y,
+ new_plane_state->crtc_w,
+ new_plane_state->crtc_h, &i, false);
+
+ /* Add old plane bounding-box if plane is moved or resized */
+ fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[i],
+ old_plane_state->crtc_x,
+ old_plane_state->crtc_y,
+ old_plane_state->crtc_w,
+ old_plane_state->crtc_h, &i, false);
+ }
+
+ if (num_clips) {
+ for (; i < num_clips; clips++)
+ fill_dc_dirty_rect(new_plane_state->plane,
+ &dirty_rects[i], clips->x1,
+ clips->y1, clips->x2 - clips->x1,
+ clips->y2 - clips->y1, &i, false);
+ } else if (fb_changed && !bb_changed) {
+ fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[i],
+ new_plane_state->crtc_x,
+ new_plane_state->crtc_y,
+ new_plane_state->crtc_w,
+ new_plane_state->crtc_h, &i, false);
+ }
+
+ if (i > DC_MAX_DIRTY_RECTS)
+ goto ffu;
flip_addrs->dirty_rect_count = i;
+ return;
+
+ffu:
+ fill_dc_dirty_rect(new_plane_state->plane, &dirty_rects[0], 0, 0,
+ dm_crtc_state->base.mode.crtc_hdisplay,
+ dm_crtc_state->base.mode.crtc_vdisplay,
+ &flip_addrs->dirty_rect_count, true);
}
static void update_stream_scaling_settings(const struct drm_display_mode *mode,
@@ -5652,16 +5680,14 @@ static void apply_dsc_policy_for_stream(struct amdgpu_dm_connector *aconnector,
{
struct drm_connector *drm_connector = &aconnector->base;
uint32_t link_bandwidth_kbps;
- uint32_t max_dsc_target_bpp_limit_override = 0;
struct dc *dc = sink->ctx->dc;
uint32_t max_supported_bw_in_kbps, timing_bw_in_kbps;
uint32_t dsc_max_supported_bw_in_kbps;
+ uint32_t max_dsc_target_bpp_limit_override =
+ drm_connector->display_info.max_dsc_bpp;
link_bandwidth_kbps = dc_link_bandwidth_kbps(aconnector->dc_link,
dc_link_get_link_cap(aconnector->dc_link));
- if (stream->link && stream->link->local_sink)
- max_dsc_target_bpp_limit_override =
- stream->link->local_sink->edid_caps.panel_patch.max_dsc_target_bpp_limit;
/* Set DSC policy according to dsc_clock_en */
dc_dsc_policy_set_enable_dsc_when_not_needed(
@@ -5734,7 +5760,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
const struct drm_connector_state *con_state =
dm_state ? &dm_state->base : NULL;
struct dc_stream_state *stream = NULL;
- struct drm_display_mode mode = *drm_mode;
+ struct drm_display_mode mode;
struct drm_display_mode saved_mode;
struct drm_display_mode *freesync_mode = NULL;
bool native_mode_found = false;
@@ -5742,12 +5768,14 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
bool scale = dm_state ? (dm_state->scaling != RMX_OFF) : false;
int mode_refresh;
int preferred_refresh = 0;
+ enum color_transfer_func tf = TRANSFER_FUNC_UNKNOWN;
#if defined(CONFIG_DRM_AMD_DC_DCN)
struct dsc_dec_dpcd_caps dsc_caps;
#endif
struct dc_sink *sink = NULL;
+ drm_mode_init(&mode, drm_mode);
memset(&saved_mode, 0, sizeof(saved_mode));
if (aconnector == NULL) {
@@ -5865,7 +5893,9 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
if (stream->link->dpcd_caps.dprx_feature.bits.VSC_SDP_COLORIMETRY_SUPPORTED)
stream->use_vsc_sdp_for_colorimetry = true;
}
- mod_build_vsc_infopacket(stream, &stream->vsc_infopacket, stream->output_color_space);
+ if (stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22)
+ tf = TRANSFER_FUNC_GAMMA_22;
+ mod_build_vsc_infopacket(stream, &stream->vsc_infopacket, stream->output_color_space, tf);
aconnector->psr_skip_count = AMDGPU_DM_PSR_ENTRY_DELAY;
}
@@ -6158,7 +6188,6 @@ static void create_eml_sink(struct amdgpu_dm_connector *aconnector)
aconnector->base.name);
aconnector->base.force = DRM_FORCE_OFF;
- aconnector->base.override_edid = false;
return;
}
@@ -6193,11 +6222,73 @@ static void handle_edid_mgmt(struct amdgpu_dm_connector *aconnector)
link->verified_link_cap.link_rate = LINK_RATE_HIGH2;
}
-
- aconnector->base.override_edid = true;
create_eml_sink(aconnector);
}
+static enum dc_status dm_validate_stream_and_context(struct dc *dc,
+ struct dc_stream_state *stream)
+{
+ enum dc_status dc_result = DC_ERROR_UNEXPECTED;
+ struct dc_plane_state *dc_plane_state = NULL;
+ struct dc_state *dc_state = NULL;
+
+ if (!stream)
+ goto cleanup;
+
+ dc_plane_state = dc_create_plane_state(dc);
+ if (!dc_plane_state)
+ goto cleanup;
+
+ dc_state = dc_create_state(dc);
+ if (!dc_state)
+ goto cleanup;
+
+ /* populate stream to plane */
+ dc_plane_state->src_rect.height = stream->src.height;
+ dc_plane_state->src_rect.width = stream->src.width;
+ dc_plane_state->dst_rect.height = stream->src.height;
+ dc_plane_state->dst_rect.width = stream->src.width;
+ dc_plane_state->clip_rect.height = stream->src.height;
+ dc_plane_state->clip_rect.width = stream->src.width;
+ dc_plane_state->plane_size.surface_pitch = ((stream->src.width + 255) / 256) * 256;
+ dc_plane_state->plane_size.surface_size.height = stream->src.height;
+ dc_plane_state->plane_size.surface_size.width = stream->src.width;
+ dc_plane_state->plane_size.chroma_size.height = stream->src.height;
+ dc_plane_state->plane_size.chroma_size.width = stream->src.width;
+ dc_plane_state->tiling_info.gfx9.swizzle = DC_SW_UNKNOWN;
+ dc_plane_state->format = SURFACE_PIXEL_FORMAT_GRPH_ARGB8888;
+ dc_plane_state->tiling_info.gfx9.swizzle = DC_SW_UNKNOWN;
+ dc_plane_state->rotation = ROTATION_ANGLE_0;
+ dc_plane_state->is_tiling_rotated = false;
+ dc_plane_state->tiling_info.gfx8.array_mode = DC_ARRAY_LINEAR_GENERAL;
+
+ dc_result = dc_validate_stream(dc, stream);
+ if (dc_result == DC_OK)
+ dc_result = dc_validate_plane(dc, dc_plane_state);
+
+ if (dc_result == DC_OK)
+ dc_result = dc_add_stream_to_ctx(dc, dc_state, stream);
+
+ if (dc_result == DC_OK && !dc_add_plane_to_context(
+ dc,
+ stream,
+ dc_plane_state,
+ dc_state))
+ dc_result = DC_FAIL_ATTACH_SURFACES;
+
+ if (dc_result == DC_OK)
+ dc_result = dc_validate_global_state(dc, dc_state, true);
+
+cleanup:
+ if (dc_state)
+ dc_release_state(dc_state);
+
+ if (dc_plane_state)
+ dc_plane_state_release(dc_plane_state);
+
+ return dc_result;
+}
+
struct dc_stream_state *
create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
const struct drm_display_mode *drm_mode,
@@ -6224,6 +6315,9 @@ create_validate_stream_for_sink(struct amdgpu_dm_connector *aconnector,
if (dc_result == DC_OK && stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST)
dc_result = dm_dp_mst_is_port_support_mode(aconnector, stream);
+ if (dc_result == DC_OK)
+ dc_result = dm_validate_stream_and_context(adev->dm.dc, stream);
+
if (dc_result != DC_OK) {
DRM_DEBUG_KMS("Mode %dx%d (clk %d) failed DC validation with error %d (%s)\n",
drm_mode->hdisplay,
@@ -7889,6 +7983,9 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
*/
if (acrtc_state->stream->link->psr_settings.psr_version >= DC_PSR_VERSION_SU_1 &&
acrtc_attach->dm_irq_params.allow_psr_entry &&
+#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
+ !amdgpu_dm_crc_window_is_activated(acrtc_state->base.crtc) &&
+#endif
!acrtc_state->stream->link->psr_settings.psr_allow_active)
amdgpu_dm_psr_enable(acrtc_state->stream);
} else {
@@ -8350,8 +8447,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
if (amdgpu_dm_crc_window_is_activated(crtc)) {
spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
- acrtc->dm_irq_params.crc_window.update_win = true;
- acrtc->dm_irq_params.crc_window.skip_frame_cnt = 2;
+ acrtc->dm_irq_params.window_param.update_win = true;
+ acrtc->dm_irq_params.window_param.skip_frame_cnt = 2;
spin_lock_irq(&crc_rd_wrk->crc_rd_work_lock);
crc_rd_wrk->crtc = crtc;
spin_unlock_irq(&crc_rd_wrk->crc_rd_work_lock);
@@ -10139,91 +10236,92 @@ uint32_t dm_read_reg_func(const struct dc_context *ctx, uint32_t address,
return value;
}
-static int amdgpu_dm_set_dmub_async_sync_status(bool is_cmd_aux,
- struct dc_context *ctx,
- uint8_t status_type,
- uint32_t *operation_result)
+int amdgpu_dm_process_dmub_aux_transfer_sync(
+ struct dc_context *ctx,
+ unsigned int link_index,
+ struct aux_payload *payload,
+ enum aux_return_code_type *operation_result)
{
struct amdgpu_device *adev = ctx->driver_context;
- int return_status = -1;
struct dmub_notification *p_notify = adev->dm.dmub_notify;
+ int ret = -1;
- if (is_cmd_aux) {
- if (status_type == DMUB_ASYNC_TO_SYNC_ACCESS_SUCCESS) {
- return_status = p_notify->aux_reply.length;
- *operation_result = p_notify->result;
- } else if (status_type == DMUB_ASYNC_TO_SYNC_ACCESS_TIMEOUT) {
- *operation_result = AUX_RET_ERROR_TIMEOUT;
- } else if (status_type == DMUB_ASYNC_TO_SYNC_ACCESS_FAIL) {
- *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE;
- } else if (status_type == DMUB_ASYNC_TO_SYNC_ACCESS_INVALID) {
- *operation_result = AUX_RET_ERROR_INVALID_REPLY;
- } else {
- *operation_result = AUX_RET_ERROR_UNKNOWN;
+ mutex_lock(&adev->dm.dpia_aux_lock);
+ if (!dc_process_dmub_aux_transfer_async(ctx->dc, link_index, payload)) {
+ *operation_result = AUX_RET_ERROR_ENGINE_ACQUIRE;
+ goto out;
+ }
+
+ if (!wait_for_completion_timeout(&adev->dm.dmub_aux_transfer_done, 10 * HZ)) {
+ DRM_ERROR("wait_for_completion_timeout timeout!");
+ *operation_result = AUX_RET_ERROR_TIMEOUT;
+ goto out;
+ }
+
+ if (p_notify->result != AUX_RET_SUCCESS) {
+ /*
+ * Transient states before tunneling is enabled could
+ * lead to this error. We can ignore this for now.
+ */
+ if (p_notify->result != AUX_RET_ERROR_PROTOCOL_ERROR) {
+ DRM_WARN("DPIA AUX failed on 0x%x(%d), error %d\n",
+ payload->address, payload->length,
+ p_notify->result);
}
- } else {
- if (status_type == DMUB_ASYNC_TO_SYNC_ACCESS_SUCCESS) {
- return_status = 0;
- *operation_result = p_notify->sc_status;
- } else {
- *operation_result = SET_CONFIG_UNKNOWN_ERROR;
+ *operation_result = AUX_RET_ERROR_INVALID_REPLY;
+ goto out;
+ }
+
+
+ payload->reply[0] = adev->dm.dmub_notify->aux_reply.command;
+ if (!payload->write && p_notify->aux_reply.length &&
+ (payload->reply[0] == AUX_TRANSACTION_REPLY_AUX_ACK)) {
+
+ if (payload->length != p_notify->aux_reply.length) {
+ DRM_WARN("invalid read length %d from DPIA AUX 0x%x(%d)!\n",
+ p_notify->aux_reply.length,
+ payload->address, payload->length);
+ *operation_result = AUX_RET_ERROR_INVALID_REPLY;
+ goto out;
}
+
+ memcpy(payload->data, p_notify->aux_reply.data,
+ p_notify->aux_reply.length);
}
- return return_status;
+ /* success */
+ ret = p_notify->aux_reply.length;
+ *operation_result = p_notify->result;
+out:
+ mutex_unlock(&adev->dm.dpia_aux_lock);
+ return ret;
}
-int amdgpu_dm_process_dmub_aux_transfer_sync(bool is_cmd_aux, struct dc_context *ctx,
- unsigned int link_index, void *cmd_payload, void *operation_result)
+int amdgpu_dm_process_dmub_set_config_sync(
+ struct dc_context *ctx,
+ unsigned int link_index,
+ struct set_config_cmd_payload *payload,
+ enum set_config_status *operation_result)
{
struct amdgpu_device *adev = ctx->driver_context;
- int ret = 0;
+ bool is_cmd_complete;
+ int ret;
- if (is_cmd_aux) {
- dc_process_dmub_aux_transfer_async(ctx->dc,
- link_index, (struct aux_payload *)cmd_payload);
- } else if (dc_process_dmub_set_config_async(ctx->dc, link_index,
- (struct set_config_cmd_payload *)cmd_payload,
- adev->dm.dmub_notify)) {
- return amdgpu_dm_set_dmub_async_sync_status(is_cmd_aux,
- ctx, DMUB_ASYNC_TO_SYNC_ACCESS_SUCCESS,
- (uint32_t *)operation_result);
- }
+ mutex_lock(&adev->dm.dpia_aux_lock);
+ is_cmd_complete = dc_process_dmub_set_config_async(ctx->dc,
+ link_index, payload, adev->dm.dmub_notify);
- ret = wait_for_completion_timeout(&adev->dm.dmub_aux_transfer_done, 10 * HZ);
- if (ret == 0) {
+ if (is_cmd_complete || wait_for_completion_timeout(&adev->dm.dmub_aux_transfer_done, 10 * HZ)) {
+ ret = 0;
+ *operation_result = adev->dm.dmub_notify->sc_status;
+ } else {
DRM_ERROR("wait_for_completion_timeout timeout!");
- return amdgpu_dm_set_dmub_async_sync_status(is_cmd_aux,
- ctx, DMUB_ASYNC_TO_SYNC_ACCESS_TIMEOUT,
- (uint32_t *)operation_result);
- }
-
- if (is_cmd_aux) {
- if (adev->dm.dmub_notify->result == AUX_RET_SUCCESS) {
- struct aux_payload *payload = (struct aux_payload *)cmd_payload;
-
- payload->reply[0] = adev->dm.dmub_notify->aux_reply.command;
- if (!payload->write && adev->dm.dmub_notify->aux_reply.length &&
- payload->reply[0] == AUX_TRANSACTION_REPLY_AUX_ACK) {
-
- if (payload->length != adev->dm.dmub_notify->aux_reply.length) {
- DRM_WARN("invalid read from DPIA AUX %x(%d) got length %d!\n",
- payload->address, payload->length,
- adev->dm.dmub_notify->aux_reply.length);
- return amdgpu_dm_set_dmub_async_sync_status(is_cmd_aux, ctx,
- DMUB_ASYNC_TO_SYNC_ACCESS_INVALID,
- (uint32_t *)operation_result);
- }
-
- memcpy(payload->data, adev->dm.dmub_notify->aux_reply.data,
- adev->dm.dmub_notify->aux_reply.length);
- }
- }
+ ret = -1;
+ *operation_result = SET_CONFIG_UNKNOWN_ERROR;
}
- return amdgpu_dm_set_dmub_async_sync_status(is_cmd_aux,
- ctx, DMUB_ASYNC_TO_SYNC_ACCESS_SUCCESS,
- (uint32_t *)operation_result);
+ mutex_unlock(&adev->dm.dpia_aux_lock);
+ return ret;
}
/*
@@ -10235,8 +10333,8 @@ int amdgpu_dm_process_dmub_aux_transfer_sync(bool is_cmd_aux, struct dc_context
*/
bool check_seamless_boot_capability(struct amdgpu_device *adev)
{
- switch (adev->asic_type) {
- case CHIP_VANGOGH:
+ switch (adev->ip_versions[DCE_HWIP][0]) {
+ case IP_VERSION(3, 0, 1):
if (!adev->mman.keep_stolen_vga_memory)
return true;
break;
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 635c398fcefe..df3c25e32c65 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
@@ -59,7 +59,9 @@
#include "signal_types.h"
#include "amdgpu_dm_crc.h"
struct aux_payload;
+struct set_config_cmd_payload;
enum aux_return_code_type;
+enum set_config_status;
/* Forward declarations */
struct amdgpu_device;
@@ -360,13 +362,6 @@ struct amdgpu_display_manager {
struct mutex audio_lock;
/**
- * @vblank_lock:
- *
- * Guards access to deferred vblank work state.
- */
- spinlock_t vblank_lock;
-
- /**
* @audio_component:
*
* Used to notify ELD changes to sound driver.
@@ -549,6 +544,13 @@ struct amdgpu_display_manager {
* occurred on certain intel platform
*/
bool aux_hpd_discon_quirk;
+
+ /**
+ * @dpia_aux_lock:
+ *
+ * Guards access to DPIA AUX
+ */
+ struct mutex dpia_aux_lock;
};
enum dsc_clock_force_state {
@@ -792,9 +794,11 @@ void amdgpu_dm_update_connector_after_detect(
extern const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs;
-int amdgpu_dm_process_dmub_aux_transfer_sync(bool is_cmd_aux,
- struct dc_context *ctx, unsigned int link_index,
- void *payload, void *operation_result);
+int amdgpu_dm_process_dmub_aux_transfer_sync(struct dc_context *ctx, unsigned int link_index,
+ struct aux_payload *payload, enum aux_return_code_type *operation_result);
+
+int amdgpu_dm_process_dmub_set_config_sync(struct dc_context *ctx, unsigned int link_index,
+ struct set_config_cmd_payload *payload, enum set_config_status *operation_result);
bool check_seamless_boot_capability(struct amdgpu_device *adev);
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 8a441a22c46e..66df2394d7e4 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
@@ -89,13 +89,13 @@ static void amdgpu_dm_set_crc_window_default(struct drm_crtc *crtc)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock);
- acrtc->dm_irq_params.crc_window.x_start = 0;
- acrtc->dm_irq_params.crc_window.y_start = 0;
- acrtc->dm_irq_params.crc_window.x_end = 0;
- acrtc->dm_irq_params.crc_window.y_end = 0;
- acrtc->dm_irq_params.crc_window.activated = false;
- acrtc->dm_irq_params.crc_window.update_win = false;
- acrtc->dm_irq_params.crc_window.skip_frame_cnt = 0;
+ 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;
+ acrtc->dm_irq_params.window_param.y_end = 0;
+ acrtc->dm_irq_params.window_param.activated = false;
+ 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);
}
@@ -123,6 +123,8 @@ static void amdgpu_dm_crtc_notify_ta_to_read(struct work_struct *work)
phy_id = crc_rd_wrk->phy_inst;
spin_unlock_irq(&crc_rd_wrk->crc_rd_work_lock);
+ mutex_lock(&psp->securedisplay_context.mutex);
+
psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd,
TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC);
securedisplay_cmd->securedisplay_in_message.send_roi_crc.phy_id =
@@ -133,6 +135,24 @@ static void amdgpu_dm_crtc_notify_ta_to_read(struct work_struct *work)
psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status);
}
}
+
+ mutex_unlock(&psp->securedisplay_context.mutex);
+}
+
+static void
+amdgpu_dm_forward_crc_window(struct work_struct *work)
+{
+ struct crc_fw_work *crc_fw_wrk;
+ struct amdgpu_display_manager *dm;
+
+ crc_fw_wrk = container_of(work, struct crc_fw_work, forward_roi_work);
+ dm = crc_fw_wrk->dm;
+
+ mutex_lock(&dm->dc_lock);
+ dc_stream_forward_crc_window(dm->dc, &crc_fw_wrk->rect, crc_fw_wrk->stream, crc_fw_wrk->is_stop_cmd);
+ mutex_unlock(&dm->dc_lock);
+
+ kfree(crc_fw_wrk);
}
bool amdgpu_dm_crc_window_is_activated(struct drm_crtc *crtc)
@@ -142,7 +162,7 @@ bool amdgpu_dm_crc_window_is_activated(struct drm_crtc *crtc)
bool ret = false;
spin_lock_irq(&drm_dev->event_lock);
- ret = acrtc->dm_irq_params.crc_window.activated;
+ ret = acrtc->dm_irq_params.window_param.activated;
spin_unlock_irq(&drm_dev->event_lock);
return ret;
@@ -187,9 +207,11 @@ int amdgpu_dm_crtc_configure_crc_source(struct drm_crtc *crtc,
if (adev->dm.crc_rd_wrk) {
flush_work(&adev->dm.crc_rd_wrk->notify_ta_work);
spin_lock_irq(&adev->dm.crc_rd_wrk->crc_rd_work_lock);
+
if (adev->dm.crc_rd_wrk->crtc == crtc) {
- dc_stream_stop_dmcu_crc_win_update(stream_state->ctx->dc,
- dm_crtc_state->stream);
+ /* stop ROI update on this crtc */
+ dc_stream_forward_crc_window(stream_state->ctx->dc,
+ NULL, stream_state, true);
adev->dm.crc_rd_wrk->crtc = NULL;
}
spin_unlock_irq(&adev->dm.crc_rd_wrk->crc_rd_work_lock);
@@ -439,14 +461,9 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc)
enum amdgpu_dm_pipe_crc_source cur_crc_src;
struct amdgpu_crtc *acrtc = NULL;
struct amdgpu_device *adev = NULL;
- struct crc_rd_work *crc_rd_wrk = NULL;
- struct crc_params *crc_window = NULL, tmp_window;
+ struct crc_rd_work *crc_rd_wrk;
+ struct crc_fw_work *crc_fw_wrk;
unsigned long flags1, flags2;
- struct crtc_position position;
- uint32_t v_blank;
- uint32_t v_back_porch;
- uint32_t crc_window_latch_up_line;
- struct dc_crtc_timing *timing_out;
if (crtc == NULL)
return;
@@ -458,74 +475,54 @@ void amdgpu_dm_crtc_handle_crc_window_irq(struct drm_crtc *crtc)
spin_lock_irqsave(&drm_dev->event_lock, flags1);
stream_state = acrtc->dm_irq_params.stream;
cur_crc_src = acrtc->dm_irq_params.crc_src;
- timing_out = &stream_state->timing;
/* Early return if CRC capture is not enabled. */
if (!amdgpu_dm_is_valid_crc_source(cur_crc_src))
goto cleanup;
- if (dm_is_crc_source_crtc(cur_crc_src)) {
- if (acrtc->dm_irq_params.crc_window.activated) {
- if (acrtc->dm_irq_params.crc_window.update_win) {
- if (acrtc->dm_irq_params.crc_window.skip_frame_cnt) {
- acrtc->dm_irq_params.crc_window.skip_frame_cnt -= 1;
- goto cleanup;
- }
- crc_window = &tmp_window;
-
- tmp_window.windowa_x_start =
- acrtc->dm_irq_params.crc_window.x_start;
- tmp_window.windowa_y_start =
- acrtc->dm_irq_params.crc_window.y_start;
- tmp_window.windowa_x_end =
- acrtc->dm_irq_params.crc_window.x_end;
- tmp_window.windowa_y_end =
- acrtc->dm_irq_params.crc_window.y_end;
- tmp_window.windowb_x_start =
- acrtc->dm_irq_params.crc_window.x_start;
- tmp_window.windowb_y_start =
- acrtc->dm_irq_params.crc_window.y_start;
- tmp_window.windowb_x_end =
- acrtc->dm_irq_params.crc_window.x_end;
- tmp_window.windowb_y_end =
- acrtc->dm_irq_params.crc_window.y_end;
-
- dc_stream_forward_dmcu_crc_window(stream_state->ctx->dc,
- stream_state, crc_window);
-
- acrtc->dm_irq_params.crc_window.update_win = false;
-
- dc_stream_get_crtc_position(stream_state->ctx->dc, &stream_state, 1,
- &position.vertical_count,
- &position.nominal_vcount);
-
- v_blank = timing_out->v_total - timing_out->v_border_top -
- timing_out->v_addressable - timing_out->v_border_bottom;
-
- v_back_porch = v_blank - timing_out->v_front_porch -
- timing_out->v_sync_width;
-
- crc_window_latch_up_line = v_back_porch + timing_out->v_sync_width;
-
- /* take 3 lines margin*/
- if ((position.vertical_count + 3) >= crc_window_latch_up_line)
- acrtc->dm_irq_params.crc_window.skip_frame_cnt = 1;
- else
- acrtc->dm_irq_params.crc_window.skip_frame_cnt = 0;
- } else {
- if (acrtc->dm_irq_params.crc_window.skip_frame_cnt == 0) {
- if (adev->dm.crc_rd_wrk) {
- crc_rd_wrk = adev->dm.crc_rd_wrk;
- spin_lock_irqsave(&crc_rd_wrk->crc_rd_work_lock, flags2);
- crc_rd_wrk->phy_inst =
- stream_state->link->link_enc_hw_inst;
- spin_unlock_irqrestore(&crc_rd_wrk->crc_rd_work_lock, flags2);
- schedule_work(&crc_rd_wrk->notify_ta_work);
- }
- } else {
- acrtc->dm_irq_params.crc_window.skip_frame_cnt -= 1;
- }
- }
+ if (!dm_is_crc_source_crtc(cur_crc_src))
+ goto cleanup;
+
+ if (!acrtc->dm_irq_params.window_param.activated)
+ goto cleanup;
+
+ if (acrtc->dm_irq_params.window_param.update_win) {
+ if (acrtc->dm_irq_params.window_param.skip_frame_cnt) {
+ acrtc->dm_irq_params.window_param.skip_frame_cnt -= 1;
+ goto cleanup;
+ }
+
+ /* prepare work for dmub to update ROI */
+ crc_fw_wrk = kzalloc(sizeof(*crc_fw_wrk), GFP_ATOMIC);
+ if (!crc_fw_wrk)
+ goto cleanup;
+
+ INIT_WORK(&crc_fw_wrk->forward_roi_work, amdgpu_dm_forward_crc_window);
+ crc_fw_wrk->dm = &adev->dm;
+ crc_fw_wrk->stream = stream_state;
+ crc_fw_wrk->rect.x = acrtc->dm_irq_params.window_param.x_start;
+ crc_fw_wrk->rect.y = acrtc->dm_irq_params.window_param.y_start;
+ crc_fw_wrk->rect.width = acrtc->dm_irq_params.window_param.x_end -
+ acrtc->dm_irq_params.window_param.x_start;
+ crc_fw_wrk->rect.height = acrtc->dm_irq_params.window_param.y_end -
+ acrtc->dm_irq_params.window_param.y_start;
+ schedule_work(&crc_fw_wrk->forward_roi_work);
+
+ acrtc->dm_irq_params.window_param.update_win = false;
+ acrtc->dm_irq_params.window_param.skip_frame_cnt = 1;
+
+ } else {
+ if (acrtc->dm_irq_params.window_param.skip_frame_cnt) {
+ acrtc->dm_irq_params.window_param.skip_frame_cnt -= 1;
+ goto cleanup;
+ }
+
+ if (adev->dm.crc_rd_wrk) {
+ crc_rd_wrk = adev->dm.crc_rd_wrk;
+ spin_lock_irqsave(&crc_rd_wrk->crc_rd_work_lock, flags2);
+ crc_rd_wrk->phy_inst = stream_state->link->link_enc_hw_inst;
+ spin_unlock_irqrestore(&crc_rd_wrk->crc_rd_work_lock, flags2);
+ schedule_work(&crc_rd_wrk->notify_ta_work);
}
}
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 f07850db60a6..71bce608d751 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
@@ -40,7 +40,7 @@ enum amdgpu_dm_pipe_crc_source {
};
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
-struct crc_window_parm {
+struct crc_window_param {
uint16_t x_start;
uint16_t y_start;
uint16_t x_end;
@@ -53,6 +53,7 @@ struct crc_window_parm {
int skip_frame_cnt;
};
+/* read_work for driver to call PSP to read */
struct crc_rd_work {
struct work_struct notify_ta_work;
/* To protect crc_rd_work carried fields*/
@@ -60,6 +61,15 @@ struct crc_rd_work {
struct drm_crtc *crtc;
uint8_t phy_inst;
};
+
+/* forward_work for driver to forward ROI to dmu */
+struct crc_fw_work {
+ struct work_struct forward_roi_work;
+ struct amdgpu_display_manager *dm;
+ struct dc_stream_state *stream;
+ struct rect rect;
+ bool is_stop_cmd;
+};
#endif
static inline bool amdgpu_dm_is_valid_crc_source(enum amdgpu_dm_pipe_crc_source source)
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 64dd02970292..22125daf9dcf 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
@@ -127,6 +127,9 @@ static void vblank_control_worker(struct work_struct *work)
amdgpu_dm_psr_disable(vblank_work->stream);
} else if (vblank_work->stream->link->psr_settings.psr_feature_enabled &&
!vblank_work->stream->link->psr_settings.psr_allow_active &&
+#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
+ !amdgpu_dm_crc_window_is_activated(&vblank_work->acrtc->base) &&
+#endif
vblank_work->acrtc->dm_irq_params.allow_psr_entry) {
amdgpu_dm_psr_enable(vblank_work->stream);
}
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 ee242d9d8b06..461037a3dd75 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
@@ -38,6 +38,10 @@
#include "link_hwss.h"
#include "dc/dc_dmub_srv.h"
+#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
+#include "amdgpu_dm_psr.h"
+#endif
+
struct dmub_debugfs_trace_header {
uint32_t entry_count;
uint32_t reserved[3];
@@ -299,6 +303,8 @@ static ssize_t dp_link_settings_write(struct file *f, const char __user *buf,
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;
@@ -2633,6 +2639,25 @@ static int dp_mst_progress_status_show(struct seq_file *m, void *unused)
return 0;
}
+/*
+ * Reports whether the connected display is a USB4 DPIA tunneled display
+ * Example usage: cat /sys/kernel/debug/dri/0/DP-8/is_dpia_link
+ */
+static int is_dpia_link_show(struct seq_file *m, void *data)
+{
+ struct drm_connector *connector = m->private;
+ struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
+ struct dc_link *link = aconnector->dc_link;
+
+ if (connector->status != connector_status_connected)
+ return -ENODEV;
+
+ seq_printf(m, "%s\n", (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA) ? "yes" :
+ (link->ep_type == DISPLAY_ENDPOINT_PHY) ? "no" : "unknown");
+
+ return 0;
+}
+
DEFINE_SHOW_ATTRIBUTE(dp_dsc_fec_support);
DEFINE_SHOW_ATTRIBUTE(dmub_fw_state);
DEFINE_SHOW_ATTRIBUTE(dmub_tracebuffer);
@@ -2644,6 +2669,7 @@ DEFINE_SHOW_ATTRIBUTE(internal_display);
DEFINE_SHOW_ATTRIBUTE(psr_capability);
DEFINE_SHOW_ATTRIBUTE(dp_is_mst_connector);
DEFINE_SHOW_ATTRIBUTE(dp_mst_progress_status);
+DEFINE_SHOW_ATTRIBUTE(is_dpia_link);
static const struct file_operations dp_dsc_clock_en_debugfs_fops = {
.owner = THIS_MODULE,
@@ -2788,7 +2814,8 @@ static const struct {
{"max_bpc", &dp_max_bpc_debugfs_fops},
{"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}
+ {"mst_progress_status", &dp_mst_progress_status_fops},
+ {"is_dpia_link", &is_dpia_link_fops}
};
#ifdef CONFIG_DRM_AMD_DC_HDCP
@@ -3079,8 +3106,8 @@ static int crc_win_x_start_set(void *data, u64 val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock);
- acrtc->dm_irq_params.crc_window.x_start = (uint16_t) val;
- acrtc->dm_irq_params.crc_window.update_win = false;
+ acrtc->dm_irq_params.window_param.x_start = (uint16_t) val;
+ acrtc->dm_irq_params.window_param.update_win = false;
spin_unlock_irq(&drm_dev->event_lock);
return 0;
@@ -3096,7 +3123,7 @@ static int crc_win_x_start_get(void *data, u64 *val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock);
- *val = acrtc->dm_irq_params.crc_window.x_start;
+ *val = acrtc->dm_irq_params.window_param.x_start;
spin_unlock_irq(&drm_dev->event_lock);
return 0;
@@ -3116,8 +3143,8 @@ static int crc_win_y_start_set(void *data, u64 val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock);
- acrtc->dm_irq_params.crc_window.y_start = (uint16_t) val;
- acrtc->dm_irq_params.crc_window.update_win = false;
+ acrtc->dm_irq_params.window_param.y_start = (uint16_t) val;
+ acrtc->dm_irq_params.window_param.update_win = false;
spin_unlock_irq(&drm_dev->event_lock);
return 0;
@@ -3133,7 +3160,7 @@ static int crc_win_y_start_get(void *data, u64 *val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock);
- *val = acrtc->dm_irq_params.crc_window.y_start;
+ *val = acrtc->dm_irq_params.window_param.y_start;
spin_unlock_irq(&drm_dev->event_lock);
return 0;
@@ -3152,8 +3179,8 @@ static int crc_win_x_end_set(void *data, u64 val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock);
- acrtc->dm_irq_params.crc_window.x_end = (uint16_t) val;
- acrtc->dm_irq_params.crc_window.update_win = false;
+ acrtc->dm_irq_params.window_param.x_end = (uint16_t) val;
+ acrtc->dm_irq_params.window_param.update_win = false;
spin_unlock_irq(&drm_dev->event_lock);
return 0;
@@ -3169,7 +3196,7 @@ static int crc_win_x_end_get(void *data, u64 *val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock);
- *val = acrtc->dm_irq_params.crc_window.x_end;
+ *val = acrtc->dm_irq_params.window_param.x_end;
spin_unlock_irq(&drm_dev->event_lock);
return 0;
@@ -3188,8 +3215,8 @@ static int crc_win_y_end_set(void *data, u64 val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock);
- acrtc->dm_irq_params.crc_window.y_end = (uint16_t) val;
- acrtc->dm_irq_params.crc_window.update_win = false;
+ acrtc->dm_irq_params.window_param.y_end = (uint16_t) val;
+ acrtc->dm_irq_params.window_param.update_win = false;
spin_unlock_irq(&drm_dev->event_lock);
return 0;
@@ -3205,7 +3232,7 @@ static int crc_win_y_end_get(void *data, u64 *val)
struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
spin_lock_irq(&drm_dev->event_lock);
- *val = acrtc->dm_irq_params.crc_window.y_end;
+ *val = acrtc->dm_irq_params.window_param.y_end;
spin_unlock_irq(&drm_dev->event_lock);
return 0;
@@ -3228,31 +3255,38 @@ static int crc_win_update_set(void *data, u64 val)
return 0;
if (val) {
+ new_acrtc = to_amdgpu_crtc(new_crtc);
+ mutex_lock(&adev->dm.dc_lock);
+ /* PSR may write to OTG CRC window control register,
+ * so close it before starting secure_display.
+ */
+ amdgpu_dm_psr_disable(new_acrtc->dm_irq_params.stream);
+
spin_lock_irq(&adev_to_drm(adev)->event_lock);
spin_lock_irq(&crc_rd_wrk->crc_rd_work_lock);
if (crc_rd_wrk->crtc) {
old_crtc = crc_rd_wrk->crtc;
old_acrtc = to_amdgpu_crtc(old_crtc);
}
- new_acrtc = to_amdgpu_crtc(new_crtc);
if (old_crtc && old_crtc != new_crtc) {
- old_acrtc->dm_irq_params.crc_window.activated = false;
- old_acrtc->dm_irq_params.crc_window.update_win = false;
- old_acrtc->dm_irq_params.crc_window.skip_frame_cnt = 0;
+ old_acrtc->dm_irq_params.window_param.activated = false;
+ old_acrtc->dm_irq_params.window_param.update_win = false;
+ old_acrtc->dm_irq_params.window_param.skip_frame_cnt = 0;
- new_acrtc->dm_irq_params.crc_window.activated = true;
- new_acrtc->dm_irq_params.crc_window.update_win = true;
- new_acrtc->dm_irq_params.crc_window.skip_frame_cnt = 0;
+ new_acrtc->dm_irq_params.window_param.activated = true;
+ new_acrtc->dm_irq_params.window_param.update_win = true;
+ new_acrtc->dm_irq_params.window_param.skip_frame_cnt = 0;
crc_rd_wrk->crtc = new_crtc;
} else {
- new_acrtc->dm_irq_params.crc_window.activated = true;
- new_acrtc->dm_irq_params.crc_window.update_win = true;
- new_acrtc->dm_irq_params.crc_window.skip_frame_cnt = 0;
+ new_acrtc->dm_irq_params.window_param.activated = true;
+ new_acrtc->dm_irq_params.window_param.update_win = true;
+ new_acrtc->dm_irq_params.window_param.skip_frame_cnt = 0;
crc_rd_wrk->crtc = new_crtc;
}
spin_unlock_irq(&crc_rd_wrk->crc_rd_work_lock);
spin_unlock_irq(&adev_to_drm(adev)->event_lock);
+ mutex_unlock(&adev->dm.dc_lock);
}
return 0;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
index 6202e31c7e3a..a7fd98f57f94 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_hdcp.c
@@ -495,7 +495,7 @@ static void update_config(void *handle, struct cp_psp_stream_config *config)
link->dp.mst_enabled = config->mst_enabled;
link->dp.usb4_enabled = config->usb4_enabled;
display->adjust.disable = MOD_HDCP_DISPLAY_DISABLE_AUTHENTICATION;
- link->adjust.auth_delay = 3;
+ link->adjust.auth_delay = 0;
link->adjust.hdcp1.disable = 0;
conn_state = aconnector->base.state;
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 f0b01c8dc4a6..6994c9a1ed85 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
@@ -42,39 +42,6 @@
#include "dm_helpers.h"
#include "ddc_service_types.h"
-struct monitor_patch_info {
- unsigned int manufacturer_id;
- unsigned int product_id;
- void (*patch_func)(struct dc_edid_caps *edid_caps, unsigned int param);
- unsigned int patch_param;
-};
-static void set_max_dsc_bpp_limit(struct dc_edid_caps *edid_caps, unsigned int param);
-
-static const struct monitor_patch_info monitor_patch_table[] = {
-{0x6D1E, 0x5BBF, set_max_dsc_bpp_limit, 15},
-{0x6D1E, 0x5B9A, set_max_dsc_bpp_limit, 15},
-};
-
-static void set_max_dsc_bpp_limit(struct dc_edid_caps *edid_caps, unsigned int param)
-{
- if (edid_caps)
- edid_caps->panel_patch.max_dsc_target_bpp_limit = param;
-}
-
-static int amdgpu_dm_patch_edid_caps(struct dc_edid_caps *edid_caps)
-{
- int i, ret = 0;
-
- for (i = 0; i < ARRAY_SIZE(monitor_patch_table); i++)
- if ((edid_caps->manufacturer_id == monitor_patch_table[i].manufacturer_id)
- && (edid_caps->product_id == monitor_patch_table[i].product_id)) {
- monitor_patch_table[i].patch_func(edid_caps, monitor_patch_table[i].patch_param);
- ret++;
- }
-
- return ret;
-}
-
/* dm_helpers_parse_edid_caps
*
* Parse edid caps
@@ -149,8 +116,6 @@ enum dc_edid_status dm_helpers_parse_edid_caps(
kfree(sads);
kfree(sadb);
- amdgpu_dm_patch_edid_caps(edid_caps);
-
return result;
}
@@ -852,9 +817,8 @@ int dm_helper_dmub_aux_transfer_sync(
struct aux_payload *payload,
enum aux_return_code_type *operation_result)
{
- return amdgpu_dm_process_dmub_aux_transfer_sync(true, ctx,
- link->link_index, (void *)payload,
- (void *)operation_result);
+ return amdgpu_dm_process_dmub_aux_transfer_sync(ctx, link->link_index, payload,
+ operation_result);
}
int dm_helpers_dmub_set_config_sync(struct dc_context *ctx,
@@ -862,9 +826,8 @@ int dm_helpers_dmub_set_config_sync(struct dc_context *ctx,
struct set_config_cmd_payload *payload,
enum set_config_status *operation_result)
{
- return amdgpu_dm_process_dmub_aux_transfer_sync(false, ctx,
- link->link_index, (void *)payload,
- (void *)operation_result);
+ return amdgpu_dm_process_dmub_set_config_sync(ctx, link->link_index, payload,
+ operation_result);
}
void dm_set_dcn_clocks(struct dc_context *ctx, struct dc_clocks *clks)
@@ -1006,3 +969,11 @@ void dm_helpers_enable_periodic_detection(struct dc_context *ctx, bool enable)
{
/* TODO: add periodic detection implementation */
}
+
+void dm_helpers_dp_mst_update_branch_bandwidth(
+ struct dc_context *ctx,
+ struct dc_link *link)
+{
+ // TODO
+}
+
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h
index 79b5f9999fec..5c9303241aeb 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq_params.h
@@ -39,7 +39,7 @@ struct dm_irq_params {
#ifdef CONFIG_DEBUG_FS
enum amdgpu_dm_pipe_crc_source crc_src;
#ifdef CONFIG_DRM_AMD_SECURE_DISPLAY
- struct crc_window_parm crc_window;
+ struct crc_window_param window_param;
#endif
#endif
};
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 6483ba266893..1edf7385f8d8 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
@@ -642,15 +642,18 @@ static void set_dsc_configs_from_fairness_vars(struct dsc_mst_fairness_params *p
int count,
int k)
{
+ struct drm_connector *drm_connector;
int i;
for (i = 0; i < count; i++) {
+ drm_connector = &params[i].aconnector->base;
+
memset(&params[i].timing->dsc_cfg, 0, sizeof(params[i].timing->dsc_cfg));
if (vars[i + k].dsc_enabled && dc_dsc_compute_config(
params[i].sink->ctx->dc->res_pool->dscs[0],
&params[i].sink->dsc_caps.dsc_dec_caps,
params[i].sink->ctx->dc->debug.dsc_min_slice_height_override,
- params[i].sink->edid_caps.panel_patch.max_dsc_target_bpp_limit,
+ drm_connector->display_info.max_dsc_bpp,
0,
params[i].timing,
&params[i].timing->dsc_cfg)) {
@@ -692,12 +695,16 @@ static int bpp_x16_from_pbn(struct dsc_mst_fairness_params param, int pbn)
struct dc_dsc_config dsc_config;
u64 kbps;
+ struct drm_connector *drm_connector = &param.aconnector->base;
+ uint32_t max_dsc_target_bpp_limit_override =
+ drm_connector->display_info.max_dsc_bpp;
+
kbps = div_u64((u64)pbn * 994 * 8 * 54, 64);
dc_dsc_compute_config(
param.sink->ctx->dc->res_pool->dscs[0],
&param.sink->dsc_caps.dsc_dec_caps,
param.sink->ctx->dc->debug.dsc_min_slice_height_override,
- param.sink->edid_caps.panel_patch.max_dsc_target_bpp_limit,
+ max_dsc_target_bpp_limit_override,
(int) kbps, param.timing, &dsc_config);
return dsc_config.bits_per_pixel;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
index e6854f7270a6..3c50b3ff7954 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
@@ -1600,6 +1600,10 @@ int amdgpu_dm_plane_init(struct amdgpu_display_manager *dm,
drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
supported_rotations);
+ if (dm->adev->ip_versions[DCE_HWIP][0] > IP_VERSION(3, 0, 1) &&
+ plane->type != DRM_PLANE_TYPE_CURSOR)
+ drm_plane_enable_fb_damage_clips(plane);
+
drm_plane_helper_add(plane, &dm_plane_helper_funcs);
#ifdef CONFIG_DRM_AMD_DC_HDR
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
index d3bc9dc21771..0f580ea37576 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_trace.h
@@ -37,6 +37,7 @@
#include <drm/drm_framebuffer.h>
#include <drm/drm_encoder.h>
#include <drm/drm_atomic.h>
+#include "dcn10/dcn10_optc.h"
#include "dc/inc/core_types.h"
@@ -662,6 +663,69 @@ TRACE_EVENT(dcn_fpu,
)
);
+TRACE_EVENT(dcn_optc_lock_unlock_state,
+ TP_PROTO(const struct optc *optc_state, int instance, bool lock, const char *function, const int line),
+ TP_ARGS(optc_state, instance, lock, function, line),
+
+ TP_STRUCT__entry(
+ __field(const char *, function)
+ __field(int, instance)
+ __field(bool, lock)
+ __field(int, line)
+ __field(int, opp_count)
+ __field(int, max_h_total)
+ __field(int, max_v_total)
+ __field(int, min_h_blank)
+ __field(int, min_h_sync_width)
+ __field(int, min_v_sync_width)
+ __field(int, min_v_blank)
+ __field(int, min_v_blank_interlace)
+ __field(int, vstartup_start)
+ __field(int, vupdate_offset)
+ __field(int, vupdate_width)
+ __field(int, vready_offset)
+ ),
+ TP_fast_assign(
+ __entry->function = function;
+ __entry->instance = instance;
+ __entry->lock = lock;
+ __entry->line = line;
+ __entry->opp_count = optc_state->opp_count;
+ __entry->max_h_total = optc_state->max_h_total;
+ __entry->max_v_total = optc_state->max_v_total;
+ __entry->min_h_blank = optc_state->min_h_blank;
+ __entry->min_h_sync_width = optc_state->min_h_sync_width;
+ __entry->min_v_sync_width = optc_state->min_v_sync_width;
+ __entry->min_v_blank = optc_state->min_v_blank;
+ __entry->min_v_blank_interlace = optc_state->min_v_blank_interlace;
+ __entry->vstartup_start = optc_state->vstartup_start;
+ __entry->vupdate_offset = optc_state->vupdate_offset;
+ __entry->vupdate_width = optc_state->vupdate_width;
+ __entry->vready_offset = optc_state->vupdate_offset;
+ ),
+ TP_printk("%s: %s()+%d: optc_instance=%d opp_count=%d max_h_total=%d max_v_total=%d "
+ "min_h_blank=%d min_h_sync_width=%d min_v_sync_width=%d min_v_blank=%d "
+ "min_v_blank_interlace=%d vstartup_start=%d vupdate_offset=%d vupdate_width=%d "
+ "vready_offset=%d",
+ __entry->lock ? "Lock" : "Unlock",
+ __entry->function,
+ __entry->line,
+ __entry->instance,
+ __entry->opp_count,
+ __entry->max_h_total,
+ __entry->max_v_total,
+ __entry->min_h_blank,
+ __entry->min_h_sync_width,
+ __entry->min_v_sync_width,
+ __entry->min_v_blank,
+ __entry->min_v_blank_interlace,
+ __entry->vstartup_start,
+ __entry->vupdate_offset,
+ __entry->vupdate_width,
+ __entry->vready_offset
+ )
+);
+
#endif /* _AMDGPU_DM_TRACE_H_ */
#undef TRACE_INCLUDE_PATH
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 ab0c6d191038..1743ca0a3641 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/dc_fpu.c
@@ -31,6 +31,8 @@
#elif defined(CONFIG_PPC64)
#include <asm/switch_to.h>
#include <asm/cputable.h>
+#elif defined(CONFIG_ARM64)
+#include <asm/neon.h>
#endif
/**
@@ -99,6 +101,8 @@ void dc_fpu_begin(const char *function_name, const int line)
preempt_disable();
enable_kernel_fp();
}
+#elif defined(CONFIG_ARM64)
+ kernel_neon_begin();
#endif
}
@@ -136,6 +140,8 @@ void dc_fpu_end(const char *function_name, const int line)
disable_kernel_fp();
preempt_enable();
}
+#elif defined(CONFIG_ARM64)
+ kernel_neon_end();
#endif
}
diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
index 9b8ea6e9a2b9..a1a00f432168 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser.c
@@ -138,7 +138,9 @@ static uint8_t get_number_of_objects(struct bios_parser *bp, uint32_t offset)
uint32_t object_table_offset = bp->object_info_tbl_offset + offset;
- table = GET_IMAGE(ATOM_OBJECT_TABLE, object_table_offset);
+ table = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base,
+ object_table_offset,
+ struct_size(table, asObjects, 1)));
if (!table)
return 0;
@@ -166,8 +168,9 @@ static struct graphics_object_id bios_parser_get_connector_id(
uint32_t connector_table_offset = bp->object_info_tbl_offset
+ le16_to_cpu(bp->object_info_tbl.v1_1->usConnectorObjectTableOffset);
- ATOM_OBJECT_TABLE *tbl =
- GET_IMAGE(ATOM_OBJECT_TABLE, connector_table_offset);
+ ATOM_OBJECT_TABLE *tbl = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base,
+ connector_table_offset,
+ struct_size(tbl, asObjects, 1)));
if (!tbl) {
dm_error("Can't get connector table from atom bios.\n");
@@ -662,8 +665,9 @@ static enum bp_result get_ss_info_v3_1(
if (!DATA_TABLES(ASIC_InternalSS_Info))
return BP_RESULT_UNSUPPORTED;
- ss_table_header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3,
- DATA_TABLES(ASIC_InternalSS_Info));
+ ss_table_header_include = ((ATOM_ASIC_INTERNAL_SS_INFO_V3 *) bios_get_image(&bp->base,
+ DATA_TABLES(ASIC_InternalSS_Info),
+ struct_size(ss_table_header_include, asSpreadSpectrum, 1)));
table_size =
(le16_to_cpu(ss_table_header_include->sHeader.usStructureSize)
- sizeof(ATOM_COMMON_TABLE_HEADER))
@@ -1029,8 +1033,10 @@ static enum bp_result get_ss_info_from_internal_ss_info_tbl_V2_1(
if (!DATA_TABLES(ASIC_InternalSS_Info))
return result;
- header = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2,
- DATA_TABLES(ASIC_InternalSS_Info));
+ header = ((ATOM_ASIC_INTERNAL_SS_INFO_V2 *) bios_get_image(
+ &bp->base,
+ DATA_TABLES(ASIC_InternalSS_Info),
+ struct_size(header, asSpreadSpectrum, 1)));
memset(info, 0, sizeof(struct spread_spectrum_info));
@@ -1709,8 +1715,10 @@ static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_v2_1(
if (!DATA_TABLES(ASIC_InternalSS_Info))
return 0;
- header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2,
- DATA_TABLES(ASIC_InternalSS_Info));
+ header_include = ((ATOM_ASIC_INTERNAL_SS_INFO_V2 *) bios_get_image(
+ &bp->base,
+ DATA_TABLES(ASIC_InternalSS_Info),
+ struct_size(header_include, asSpreadSpectrum, 1)));
size = (le16_to_cpu(header_include->sHeader.usStructureSize)
- sizeof(ATOM_COMMON_TABLE_HEADER))
@@ -1746,8 +1754,9 @@ static uint32_t get_ss_entry_number_from_internal_ss_info_tbl_V3_1(
if (!DATA_TABLES(ASIC_InternalSS_Info))
return number;
- header_include = GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V3,
- DATA_TABLES(ASIC_InternalSS_Info));
+ header_include = ((ATOM_ASIC_INTERNAL_SS_INFO_V3 *) bios_get_image(&bp->base,
+ DATA_TABLES(ASIC_InternalSS_Info),
+ struct_size(header_include, asSpreadSpectrum, 1)));
size = (le16_to_cpu(header_include->sHeader.usStructureSize) -
sizeof(ATOM_COMMON_TABLE_HEADER)) /
sizeof(ATOM_ASIC_SS_ASSIGNMENT_V3);
@@ -1789,11 +1798,13 @@ static enum bp_result bios_parser_get_gpio_pin_info(
if (!DATA_TABLES(GPIO_Pin_LUT))
return BP_RESULT_BADBIOSTABLE;
- header = GET_IMAGE(ATOM_GPIO_PIN_LUT, DATA_TABLES(GPIO_Pin_LUT));
+ header = ((ATOM_GPIO_PIN_LUT *) bios_get_image(&bp->base,
+ DATA_TABLES(GPIO_Pin_LUT),
+ struct_size(header, asGPIO_Pin, 1)));
if (!header)
return BP_RESULT_BADBIOSTABLE;
- if (sizeof(ATOM_COMMON_TABLE_HEADER) + sizeof(ATOM_GPIO_PIN_LUT)
+ if (sizeof(ATOM_COMMON_TABLE_HEADER) + struct_size(header, asGPIO_Pin, 1)
> le16_to_cpu(header->sHeader.usStructureSize))
return BP_RESULT_BADBIOSTABLE;
@@ -1978,7 +1989,8 @@ static ATOM_OBJECT *get_bios_object(struct bios_parser *bp,
offset += bp->object_info_tbl_offset;
- tbl = GET_IMAGE(ATOM_OBJECT_TABLE, offset);
+ tbl = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base, offset,
+ struct_size(tbl, asObjects, 1)));
if (!tbl)
return NULL;
@@ -2600,8 +2612,7 @@ static enum bp_result update_slot_layout_info(
for (;;) {
- record_header = (ATOM_COMMON_RECORD_HEADER *)
- GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset);
+ record_header = GET_IMAGE(ATOM_COMMON_RECORD_HEADER, record_offset);
if (record_header == NULL) {
result = BP_RESULT_BADBIOSTABLE;
break;
@@ -2615,7 +2626,7 @@ static enum bp_result update_slot_layout_info(
if (record_header->ucRecordType ==
ATOM_BRACKET_LAYOUT_RECORD_TYPE &&
- sizeof(ATOM_BRACKET_LAYOUT_RECORD)
+ struct_size(record, asConnInfo, 1)
<= record_header->ucRecordSize) {
record = (ATOM_BRACKET_LAYOUT_RECORD *)
(record_header);
@@ -2709,8 +2720,9 @@ static enum bp_result get_bracket_layout_record(
genericTableOffset = bp->object_info_tbl_offset +
bp->object_info_tbl.v1_3->usMiscObjectTableOffset;
- object_table = (ATOM_OBJECT_TABLE *)
- GET_IMAGE(ATOM_OBJECT_TABLE, genericTableOffset);
+ object_table = ((ATOM_OBJECT_TABLE *) bios_get_image(&bp->base,
+ genericTableOffset,
+ struct_size(object_table, asObjects, 1)));
if (!object_table)
return BP_RESULT_FAILURE;
diff --git a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
index e0c8d6f09bb4..074e70a5c458 100644
--- a/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
+++ b/drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
@@ -462,6 +462,7 @@ static enum bp_result get_gpio_i2c_info(
uint32_t count = 0;
unsigned int table_index = 0;
bool find_valid = false;
+ struct atom_gpio_pin_assignment *pin;
if (!info)
return BP_RESULT_BADINPUT;
@@ -489,20 +490,17 @@ static enum bp_result get_gpio_i2c_info(
- sizeof(struct atom_common_table_header))
/ sizeof(struct atom_gpio_pin_assignment);
+ pin = (struct atom_gpio_pin_assignment *) header->gpio_pin;
+
for (table_index = 0; table_index < count; table_index++) {
- if (((record->i2c_id & I2C_HW_CAP) == (
- header->gpio_pin[table_index].gpio_id &
- I2C_HW_CAP)) &&
- ((record->i2c_id & I2C_HW_ENGINE_ID_MASK) ==
- (header->gpio_pin[table_index].gpio_id &
- I2C_HW_ENGINE_ID_MASK)) &&
- ((record->i2c_id & I2C_HW_LANE_MUX) ==
- (header->gpio_pin[table_index].gpio_id &
- I2C_HW_LANE_MUX))) {
+ if (((record->i2c_id & I2C_HW_CAP) == (pin->gpio_id & I2C_HW_CAP)) &&
+ ((record->i2c_id & I2C_HW_ENGINE_ID_MASK) == (pin->gpio_id & I2C_HW_ENGINE_ID_MASK)) &&
+ ((record->i2c_id & I2C_HW_LANE_MUX) == (pin->gpio_id & I2C_HW_LANE_MUX))) {
/* still valid */
find_valid = true;
break;
}
+ pin = (struct atom_gpio_pin_assignment *)((uint8_t *)pin + sizeof(struct atom_gpio_pin_assignment));
}
/* If we don't find the entry that we are looking for then
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.h
index 3e5df27aa96f..1ce19d875358 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.h
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr_vbios_smu.h
@@ -26,6 +26,8 @@
#ifndef DAL_DC_RN_CLK_MGR_VBIOS_SMU_H_
#define DAL_DC_RN_CLK_MGR_VBIOS_SMU_H_
+enum dcn_pwr_state;
+
int rn_vbios_smu_get_smu_version(struct clk_mgr_internal *clk_mgr);
int rn_vbios_smu_set_dispclk(struct clk_mgr_internal *clk_mgr, int requested_dispclk_khz);
int rn_vbios_smu_set_dprefclk(struct clk_mgr_internal *clk_mgr);
@@ -33,7 +35,7 @@ int rn_vbios_smu_set_hard_min_dcfclk(struct clk_mgr_internal *clk_mgr, int reque
int rn_vbios_smu_set_min_deep_sleep_dcfclk(struct clk_mgr_internal *clk_mgr, int requested_min_ds_dcfclk_khz);
void rn_vbios_smu_set_phyclk(struct clk_mgr_internal *clk_mgr, int requested_phyclk_khz);
int rn_vbios_smu_set_dppclk(struct clk_mgr_internal *clk_mgr, int requested_dpp_khz);
-void rn_vbios_smu_set_dcn_low_power_state(struct clk_mgr_internal *clk_mgr, int display_count);
+void rn_vbios_smu_set_dcn_low_power_state(struct clk_mgr_internal *clk_mgr, enum dcn_pwr_state);
void rn_vbios_smu_enable_48mhz_tmdp_refclk_pwrdwn(struct clk_mgr_internal *clk_mgr, bool enable);
void rn_vbios_smu_enable_pme_wa(struct clk_mgr_internal *clk_mgr);
int rn_vbios_smu_is_periodic_retraining_disabled(struct clk_mgr_internal *clk_mgr);
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_smu11_driver_if.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_smu11_driver_if.h
index 8ea8ee57b39f..61bb1d86182e 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_smu11_driver_if.h
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn30/dcn30_smu11_driver_if.h
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: MIT
// This is a stripped-down version of the smu11_driver_if.h file for the relevant DAL interfaces.
#define SMU11_DRIVER_IF_VERSION 0x40
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 c1eaf571407a..1c0569b1dc8f 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
@@ -609,8 +609,10 @@ static void dcn31_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *clk
}
bw_params->vram_type = bios_info->memory_type;
- bw_params->num_channels = bios_info->ma_channel_number;
+ bw_params->dram_channel_width_bytes = bios_info->memory_type == 0x22 ? 8 : 4;
+ //bw_params->dram_channel_width_bytes = dc->ctx->asic_id.vram_width;
+ bw_params->num_channels = bios_info->ma_channel_number ? bios_info->ma_channel_number : 4;
for (i = 0; i < WM_SET_COUNT; i++) {
bw_params->wm_table.entries[i].wm_inst = i;
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 090b2c02aee1..0827c7df2855 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
@@ -333,8 +333,8 @@ void dcn31_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zst
(support == DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY))
support = DCN_ZSTATE_SUPPORT_DISALLOW;
-
- if (support == DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY)
+ if (support == DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY ||
+ support == DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY)
param = 1;
else
param = 0;
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 2db595672a46..f47cfe6b42bd 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
@@ -346,8 +346,6 @@ void dcn314_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zs
if (!clk_mgr->smu_present)
return;
- // Arg[15:0] = 8/9/0 for Z8/Z9/disallow -> existing bits
- // Arg[16] = Disallow Z9 -> new bit
switch (support) {
case DCN_ZSTATE_SUPPORT_ALLOW:
@@ -366,6 +364,16 @@ void dcn314_smu_set_zstate_support(struct clk_mgr_internal *clk_mgr, enum dcn_zs
param = (1 << 10);
break;
+ case DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY:
+ msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
+ param = (1 << 10) | (1 << 8);
+ break;
+
+ case DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY:
+ msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
+ param = (1 << 8);
+ break;
+
default: //DCN_ZSTATE_SUPPORT_UNKNOWN
msg_id = VBIOSSMC_MSG_AllowZstatesEntry;
param = 0;
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 893991a0eb97..07edd9777edf 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
@@ -458,19 +458,6 @@ static void dcn315_get_dpm_table_from_smu(struct clk_mgr_internal *clk_mgr,
dcn315_smu_transfer_dpm_table_smu_2_dram(clk_mgr);
}
-static uint32_t find_max_clk_value(const uint32_t clocks[], uint32_t num_clocks)
-{
- uint32_t max = 0;
- int i;
-
- for (i = 0; i < num_clocks; ++i) {
- if (clocks[i] > max)
- max = clocks[i];
- }
-
- return max;
-}
-
static void dcn315_clk_mgr_helper_populate_bw_params(
struct clk_mgr_internal *clk_mgr,
struct integrated_info *bios_info,
@@ -478,29 +465,21 @@ static void dcn315_clk_mgr_helper_populate_bw_params(
{
int i;
struct clk_bw_params *bw_params = clk_mgr->base.bw_params;
- uint32_t max_pstate = 0, max_fclk = 0, min_pstate = 0;
+ uint32_t max_pstate = clock_table->NumDfPstatesEnabled - 1;
struct clk_limit_table_entry def_max = bw_params->clk_table.entries[bw_params->clk_table.num_entries - 1];
- /* Find highest fclk pstate */
- for (i = 0; i < clock_table->NumDfPstatesEnabled; i++) {
- if (clock_table->DfPstateTable[i].FClk > max_fclk) {
- max_fclk = clock_table->DfPstateTable[i].FClk;
- max_pstate = i;
- }
- }
-
/* For 315 we want to base clock table on dcfclk, need at least one entry regardless of pmfw table */
for (i = 0; i < clock_table->NumDcfClkLevelsEnabled; i++) {
int j;
- uint32_t min_fclk = clock_table->DfPstateTable[0].FClk;
- for (j = 1; j < clock_table->NumDfPstatesEnabled; j++) {
- if (clock_table->DfPstateTable[j].Voltage <= clock_table->SocVoltage[i]
- && clock_table->DfPstateTable[j].FClk < min_fclk) {
- min_fclk = clock_table->DfPstateTable[j].FClk;
- min_pstate = j;
- }
+ /* DF table is sorted with clocks decreasing */
+ for (j = clock_table->NumDfPstatesEnabled - 2; j >= 0; j--) {
+ if (clock_table->DfPstateTable[j].Voltage <= clock_table->SocVoltage[i])
+ max_pstate = j;
}
+ /* Max DCFCLK should match up with max pstate */
+ if (i == clock_table->NumDcfClkLevelsEnabled - 1)
+ max_pstate = 0;
/* First search defaults for the clocks we don't read using closest lower or equal default dcfclk */
for (j = bw_params->clk_table.num_entries - 1; j > 0; j--)
@@ -511,9 +490,9 @@ static void dcn315_clk_mgr_helper_populate_bw_params(
bw_params->clk_table.entries[i].dtbclk_mhz = bw_params->clk_table.entries[j].dtbclk_mhz;
/* Now update clocks we do read */
- bw_params->clk_table.entries[i].fclk_mhz = min_fclk;
- bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[min_pstate].MemClk;
- bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[min_pstate].Voltage;
+ bw_params->clk_table.entries[i].fclk_mhz = clock_table->DfPstateTable[max_pstate].FClk;
+ bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[max_pstate].MemClk;
+ bw_params->clk_table.entries[i].voltage = clock_table->SocVoltage[i];
bw_params->clk_table.entries[i].dcfclk_mhz = clock_table->DcfClocks[i];
bw_params->clk_table.entries[i].socclk_mhz = clock_table->SocClocks[i];
bw_params->clk_table.entries[i].dispclk_mhz = clock_table->DispClocks[i];
@@ -521,25 +500,16 @@ static void dcn315_clk_mgr_helper_populate_bw_params(
bw_params->clk_table.entries[i].wck_ratio = 1;
}
- /* Make sure to include at least one entry and highest pstate */
- if (max_pstate != min_pstate || i == 0) {
- bw_params->clk_table.entries[i].fclk_mhz = max_fclk;
- bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[max_pstate].MemClk;
- bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[max_pstate].Voltage;
- bw_params->clk_table.entries[i].dcfclk_mhz = find_max_clk_value(clock_table->DcfClocks, NUM_DCFCLK_DPM_LEVELS);
+ /* Make sure to include at least one entry */
+ if (i == 0) {
+ bw_params->clk_table.entries[i].fclk_mhz = clock_table->DfPstateTable[0].FClk;
+ bw_params->clk_table.entries[i].memclk_mhz = clock_table->DfPstateTable[0].MemClk;
+ bw_params->clk_table.entries[i].voltage = clock_table->DfPstateTable[0].Voltage;
+ bw_params->clk_table.entries[i].dcfclk_mhz = clock_table->DcfClocks[0];
bw_params->clk_table.entries[i].wck_ratio = 1;
i++;
}
- bw_params->clk_table.num_entries = i--;
-
- /* Make sure all highest clocks are included*/
- bw_params->clk_table.entries[i].socclk_mhz = find_max_clk_value(clock_table->SocClocks, NUM_SOCCLK_DPM_LEVELS);
- bw_params->clk_table.entries[i].dispclk_mhz = find_max_clk_value(clock_table->DispClocks, NUM_DISPCLK_DPM_LEVELS);
- bw_params->clk_table.entries[i].dppclk_mhz = find_max_clk_value(clock_table->DppClocks, NUM_DPPCLK_DPM_LEVELS);
- ASSERT(clock_table->DcfClocks[i] == find_max_clk_value(clock_table->DcfClocks, NUM_DCFCLK_DPM_LEVELS));
- bw_params->clk_table.entries[i].phyclk_mhz = def_max.phyclk_mhz;
- bw_params->clk_table.entries[i].phyclk_d18_mhz = def_max.phyclk_d18_mhz;
- bw_params->clk_table.entries[i].dtbclk_mhz = def_max.dtbclk_mhz;
+ bw_params->clk_table.num_entries = i;
/* Set any 0 clocks to max default setting. Not an issue for
* power since we aren't doing switching in such case anyway
@@ -565,6 +535,11 @@ static void dcn315_clk_mgr_helper_populate_bw_params(
if (!bw_params->clk_table.entries[i].dtbclk_mhz)
bw_params->clk_table.entries[i].dtbclk_mhz = def_max.dtbclk_mhz;
}
+
+ /* Make sure all highest default clocks are included*/
+ ASSERT(bw_params->clk_table.entries[i-1].phyclk_mhz == def_max.phyclk_mhz);
+ ASSERT(bw_params->clk_table.entries[i-1].phyclk_d18_mhz == def_max.phyclk_d18_mhz);
+ ASSERT(bw_params->clk_table.entries[i-1].dtbclk_mhz == def_max.dtbclk_mhz);
ASSERT(bw_params->clk_table.entries[i-1].dcfclk_mhz);
bw_params->vram_type = bios_info->memory_type;
bw_params->num_channels = bios_info->ma_channel_number;
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 187f5b27fdc8..3edc81e2d417 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
@@ -553,6 +553,7 @@ static void dcn316_clk_mgr_helper_populate_bw_params(
bw_params->vram_type = bios_info->memory_type;
bw_params->num_channels = bios_info->ma_channel_number;
+ bw_params->dram_channel_width_bytes = bios_info->memory_type == 0x22 ? 8 : 4;
for (i = 0; i < WM_SET_COUNT; i++) {
bw_params->wm_table.entries[i].wm_inst = i;
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 6f77d8e538ab..200fcec19186 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
@@ -233,41 +233,6 @@ 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;
-
- if (is_dp_128b_132b_signal(pipe_ctx)) {
- dto_params.pixclk_khz = pipe_ctx->stream->phy_pix_clk;
-
- if (pipe_ctx->stream_res.audio != NULL)
- dto_params.req_audio_dtbclk_khz = 24000;
- }
- if (dc_is_hdmi_signal(pipe_ctx->stream->signal))
- dto_params.is_hdmi = true;
-
- 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
@@ -438,7 +403,7 @@ static void dcn32_update_clocks(struct clk_mgr *clk_mgr_base,
}
if (!new_clocks->dtbclk_en) {
- new_clocks->ref_dtbclk_khz = 0;
+ new_clocks->ref_dtbclk_khz = clk_mgr_base->bw_params->clk_table.entries[0].dtbclk_mhz * 1000;
}
/* clock limits are received with MHz precision, divide by 1000 to prevent setting clocks at every call */
@@ -447,8 +412,6 @@ 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)) {
diff --git a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_smu13_driver_if.h b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_smu13_driver_if.h
index d30fbbdd1792..d3d5a8caccf8 100644
--- a/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_smu13_driver_if.h
+++ b/drivers/gpu/drm/amd/display/dc/clk_mgr/dcn32/dcn32_smu13_driver_if.h
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: MIT
// This is a stripped-down version of the smu13_driver_if.h file for the relevant DAL interfaces.
#define SMU13_DRIVER_IF_VERSION 0x18
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 997ab031f816..0cb8d1f934d1 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -135,9 +135,7 @@ static const char DC_BUILD_ID[] = "production-build";
* one or two (in the pipe-split case).
*/
-/*******************************************************************************
- * Private functions
- ******************************************************************************/
+/* Private functions */
static inline void elevate_update_type(enum surface_update_type *original, enum surface_update_type new)
{
@@ -401,9 +399,6 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
{
int i;
- if (memcmp(adjust, &stream->adjust, sizeof(struct dc_crtc_timing_adjust)) == 0)
- return true;
-
stream->adjust.v_total_max = adjust->v_total_max;
stream->adjust.v_total_mid = adjust->v_total_mid;
stream->adjust.v_total_mid_frame_num = adjust->v_total_mid_frame_num;
@@ -424,18 +419,14 @@ bool dc_stream_adjust_vmin_vmax(struct dc *dc,
}
/**
- *****************************************************************************
- * Function: dc_stream_get_last_vrr_vtotal
+ * dc_stream_get_last_used_drr_vtotal - dc_stream_get_last_vrr_vtotal
*
- * @brief
- * Looks up the pipe context of dc_stream_state and gets the
- * last VTOTAL used by DRR (Dynamic Refresh Rate)
+ * @dc: [in] dc reference
+ * @stream: [in] Initial dc stream state
+ * @adjust: [in] Updated parameters for vertical_total_min and
*
- * @param [in] dc: dc reference
- * @param [in] stream: Initial dc stream state
- * @param [in] adjust: Updated parameters for vertical_total_min and
- * vertical_total_max
- *****************************************************************************
+ * Looks up the pipe context of dc_stream_state and gets the last VTOTAL used
+ * by DRR (Dynamic Refresh Rate)
*/
bool dc_stream_get_last_used_drr_vtotal(struct dc *dc,
struct dc_stream_state *stream,
@@ -491,86 +482,79 @@ bool dc_stream_get_crtc_position(struct dc *dc,
}
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
-bool dc_stream_forward_dmcu_crc_window(struct dc *dc, struct dc_stream_state *stream,
- struct crc_params *crc_window)
+static inline void
+dc_stream_forward_dmub_crc_window(struct dc_dmub_srv *dmub_srv,
+ struct rect *rect, struct otg_phy_mux *mux_mapping, bool is_stop)
{
- int i;
- struct dmcu *dmcu = dc->res_pool->dmcu;
- struct pipe_ctx *pipe;
- struct crc_region tmp_win, *crc_win;
- struct otg_phy_mux mapping_tmp, *mux_mapping;
-
- /*crc window can't be null*/
- if (!crc_window)
- return false;
-
- if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu))) {
- crc_win = &tmp_win;
- mux_mapping = &mapping_tmp;
- /*set crc window*/
- tmp_win.x_start = crc_window->windowa_x_start;
- tmp_win.y_start = crc_window->windowa_y_start;
- tmp_win.x_end = crc_window->windowa_x_end;
- tmp_win.y_end = crc_window->windowa_y_end;
-
- for (i = 0; i < MAX_PIPES; i++) {
- pipe = &dc->current_state->res_ctx.pipe_ctx[i];
- if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe)
- break;
- }
-
- /* Stream not found */
- if (i == MAX_PIPES)
- return false;
-
+ union dmub_rb_cmd cmd = {0};
- /*set mux routing info*/
- mapping_tmp.phy_output_num = stream->link->link_enc_hw_inst;
- mapping_tmp.otg_output_num = pipe->stream_res.tg->inst;
+ cmd.secure_display.roi_info.phy_id = mux_mapping->phy_output_num;
+ cmd.secure_display.roi_info.otg_id = mux_mapping->otg_output_num;
- dmcu->funcs->forward_crc_window(dmcu, crc_win, mux_mapping);
+ if (is_stop) {
+ cmd.secure_display.header.type = DMUB_CMD__SECURE_DISPLAY;
+ cmd.secure_display.header.sub_type = DMUB_CMD__SECURE_DISPLAY_CRC_STOP_UPDATE;
} else {
- DC_LOG_DC("dmcu is not initialized");
- return false;
+ cmd.secure_display.header.type = DMUB_CMD__SECURE_DISPLAY;
+ cmd.secure_display.header.sub_type = DMUB_CMD__SECURE_DISPLAY_CRC_WIN_NOTIFY;
+ cmd.secure_display.roi_info.x_start = rect->x;
+ cmd.secure_display.roi_info.y_start = rect->y;
+ cmd.secure_display.roi_info.x_end = rect->x + rect->width;
+ cmd.secure_display.roi_info.y_end = rect->y + rect->height;
}
- return true;
+ dc_dmub_srv_cmd_queue(dmub_srv, &cmd);
+ dc_dmub_srv_cmd_execute(dmub_srv);
}
-bool dc_stream_stop_dmcu_crc_win_update(struct dc *dc, struct dc_stream_state *stream)
+static inline void
+dc_stream_forward_dmcu_crc_window(struct dmcu *dmcu,
+ struct rect *rect, struct otg_phy_mux *mux_mapping, bool is_stop)
{
- int i;
- struct dmcu *dmcu = dc->res_pool->dmcu;
- struct pipe_ctx *pipe;
- struct otg_phy_mux mapping_tmp, *mux_mapping;
+ if (is_stop)
+ dmcu->funcs->stop_crc_win_update(dmcu, mux_mapping);
+ else
+ dmcu->funcs->forward_crc_window(dmcu, rect, mux_mapping);
+}
- if ((dmcu != NULL && dmcu->funcs->is_dmcu_initialized(dmcu))) {
- mux_mapping = &mapping_tmp;
+bool
+dc_stream_forward_crc_window(struct dc *dc,
+ struct rect *rect, struct dc_stream_state *stream, bool is_stop)
+{
+ struct dmcu *dmcu;
+ struct dc_dmub_srv *dmub_srv;
+ struct otg_phy_mux mux_mapping;
+ struct pipe_ctx *pipe;
+ int i;
- for (i = 0; i < MAX_PIPES; i++) {
- pipe = &dc->current_state->res_ctx.pipe_ctx[i];
- if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe)
- break;
- }
+ for (i = 0; i < MAX_PIPES; i++) {
+ pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+ if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe)
+ break;
+ }
- /* Stream not found */
- if (i == MAX_PIPES)
- return false;
+ /* Stream not found */
+ if (i == MAX_PIPES)
+ return false;
+ mux_mapping.phy_output_num = stream->link->link_enc_hw_inst;
+ mux_mapping.otg_output_num = pipe->stream_res.tg->inst;
- /*set mux routing info*/
- mapping_tmp.phy_output_num = stream->link->link_enc_hw_inst;
- mapping_tmp.otg_output_num = pipe->stream_res.tg->inst;
+ dmcu = dc->res_pool->dmcu;
+ dmub_srv = dc->ctx->dmub_srv;
- dmcu->funcs->stop_crc_win_update(dmcu, mux_mapping);
- } else {
- DC_LOG_DC("dmcu is not initialized");
+ /* forward to dmub */
+ if (dmub_srv)
+ dc_stream_forward_dmub_crc_window(dmub_srv, rect, &mux_mapping, is_stop);
+ /* forward to dmcu */
+ else if (dmcu && dmcu->funcs->is_dmcu_initialized(dmcu))
+ dc_stream_forward_dmcu_crc_window(dmcu, rect, &mux_mapping, is_stop);
+ else
return false;
- }
return true;
}
-#endif
+#endif /* CONFIG_DRM_AMD_SECURE_DISPLAY */
/**
* dc_stream_configure_crc() - Configure CRC capture for the given stream.
@@ -1070,6 +1054,8 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
int i, j;
struct dc_state *dangling_context = dc_create_state(dc);
struct dc_state *current_ctx;
+ struct pipe_ctx *pipe;
+ struct timing_generator *tg;
if (dangling_context == NULL)
return;
@@ -1112,6 +1098,18 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
}
if (should_disable && old_stream) {
+ pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+ tg = pipe->stream_res.tg;
+ /* When disabling plane for a phantom pipe, we must turn on the
+ * phantom OTG so the disable programming gets the double buffer
+ * update. Otherwise the pipe will be left in a partially disabled
+ * state that can result in underflow or hang when enabling it
+ * again for different use.
+ */
+ if (old_stream->mall_stream_config.type == SUBVP_PHANTOM) {
+ if (tg->funcs->enable_crtc)
+ tg->funcs->enable_crtc(tg);
+ }
dc_rem_all_planes_for_stream(dc, old_stream, dangling_context);
disable_all_writeback_pipes_for_stream(dc, old_stream, dangling_context);
@@ -1127,6 +1125,15 @@ static void disable_dangling_plane(struct dc *dc, struct dc_state *context)
dc->hwss.interdependent_update_lock(dc, dc->current_state, false);
dc->hwss.post_unlock_program_front_end(dc, dangling_context);
}
+ /* We need to put the phantom OTG back into it's default (disabled) state or we
+ * can get corruption when transition from one SubVP config to a different one.
+ * The OTG is set to disable on falling edge of VUPDATE so the plane disable
+ * will still get it's double buffer update.
+ */
+ if (old_stream->mall_stream_config.type == SUBVP_PHANTOM) {
+ if (tg->funcs->disable_phantom_crtc)
+ tg->funcs->disable_phantom_crtc(tg);
+ }
}
}
@@ -1219,9 +1226,7 @@ static void wait_for_no_pipes_pending(struct dc *dc, struct dc_state *context)
PERF_TRACE();
}
-/*******************************************************************************
- * Public functions
- ******************************************************************************/
+/* Public functions */
struct dc *dc_create(const struct dc_init_data *init_params)
{
@@ -1488,17 +1493,19 @@ static void program_timing_sync(
}
}
-static bool context_changed(
- struct dc *dc,
- struct dc_state *context)
+static bool streams_changed(struct dc *dc,
+ struct dc_stream_state *streams[],
+ uint8_t stream_count)
{
uint8_t i;
- if (context->stream_count != dc->current_state->stream_count)
+ if (stream_count != dc->current_state->stream_count)
return true;
for (i = 0; i < dc->current_state->stream_count; i++) {
- if (dc->current_state->streams[i] != context->streams[i])
+ if (dc->current_state->streams[i] != streams[i])
+ return true;
+ if (!streams[i]->link->link_state_valid)
return true;
}
@@ -1549,6 +1556,9 @@ bool dc_validate_boot_timing(const struct dc *dc,
if (tg_inst >= dc->res_pool->timing_generator_count)
return false;
+ if (tg_inst != link->link_enc->preferred_engine)
+ return false;
+
tg = dc->res_pool->timing_generators[tg_inst];
if (!tg->funcs->get_hw_timing)
@@ -1722,8 +1732,13 @@ void dc_z10_save_init(struct dc *dc)
dc->hwss.z10_save_init(dc);
}
-/*
- * Applies given context to HW and copy it into current context.
+/**
+ * dc_commit_state_no_check - Apply context to the hardware
+ *
+ * @dc: DC object with the current status to be updated
+ * @context: New state that will become the current status at the end of this function
+ *
+ * Applies given context to the hardware and copy it into current context.
* It's up to the user to release the src context afterwards.
*/
static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *context)
@@ -1760,6 +1775,12 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
context->stream_count == 0)
dc->hwss.prepare_bandwidth(dc, context);
+ /* When SubVP is active, all HW programming must be done while
+ * SubVP lock is acquired
+ */
+ if (dc->hwss.subvp_pipe_control_lock)
+ dc->hwss.subvp_pipe_control_lock(dc, context, true, true, NULL, subvp_prev_use);
+
if (dc->debug.enable_double_buffered_dsc_pg_support)
dc->hwss.update_dsc_pg(dc, context, false);
@@ -1787,9 +1808,6 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, pipe);
}
- if (dc->hwss.subvp_pipe_control_lock)
- dc->hwss.subvp_pipe_control_lock(dc, context, true, true, NULL, subvp_prev_use);
-
result = dc->hwss.apply_ctx_to_hw(dc, context);
if (result != DC_OK) {
@@ -1888,12 +1906,108 @@ static enum dc_status dc_commit_state_no_check(struct dc *dc, struct dc_state *c
return result;
}
+/**
+ * dc_commit_streams - Commit current stream state
+ *
+ * @dc: DC object with the commit state to be configured in the hardware
+ * @streams: Array with a list of stream state
+ * @stream_count: Total of streams
+ *
+ * Function responsible for commit streams change to the hardware.
+ *
+ * Return:
+ * Return DC_OK if everything work as expected, otherwise, return a dc_status
+ * code.
+ */
+enum dc_status dc_commit_streams(struct dc *dc,
+ struct dc_stream_state *streams[],
+ uint8_t stream_count)
+{
+ int i, j;
+ struct dc_state *context;
+ enum dc_status res = DC_OK;
+ struct dc_validation_set set[MAX_STREAMS] = {0};
+
+ if (dc->ctx->dce_environment == DCE_ENV_VIRTUAL_HW)
+ return res;
+
+ if (!streams_changed(dc, streams, stream_count))
+ return res;
+
+ DC_LOG_DC("%s: %d streams\n", __func__, stream_count);
+
+ for (i = 0; i < stream_count; i++) {
+ struct dc_stream_state *stream = streams[i];
+ struct dc_stream_status *status = dc_stream_get_status(stream);
+
+ dc_stream_log(dc, stream);
+
+ set[i].stream = stream;
+
+ if (status) {
+ set[i].plane_count = status->plane_count;
+ for (j = 0; j < status->plane_count; j++)
+ set[i].plane_states[j] = status->plane_states[j];
+ }
+ }
+
+ context = dc_create_state(dc);
+ if (!context)
+ goto context_alloc_fail;
+
+ dc_resource_state_copy_construct_current(dc, context);
+
+ res = dc_validate_with_context(dc, set, stream_count, context, false);
+ if (res != DC_OK) {
+ BREAK_TO_DEBUGGER();
+ goto fail;
+ }
+
+ res = dc_commit_state_no_check(dc, context);
+
+ for (i = 0; i < stream_count; i++) {
+ for (j = 0; j < context->stream_count; j++) {
+ if (streams[i]->stream_id == context->streams[j]->stream_id)
+ streams[i]->out.otg_offset = context->stream_status[j].primary_otg_inst;
+
+ if (dc_is_embedded_signal(streams[i]->signal)) {
+ struct dc_stream_status *status = dc_stream_get_status_from_state(context, streams[i]);
+
+ if (dc->hwss.is_abm_supported)
+ status->is_abm_supported = dc->hwss.is_abm_supported(dc, context, streams[i]);
+ else
+ status->is_abm_supported = true;
+ }
+ }
+ }
+
+fail:
+ dc_release_state(context);
+
+context_alloc_fail:
+
+ DC_LOG_DC("%s Finished.\n", __func__);
+
+ return res;
+}
+
+/* TODO: When the transition to the new commit sequence is done, remove this
+ * function in favor of dc_commit_streams. */
bool dc_commit_state(struct dc *dc, struct dc_state *context)
{
enum dc_status result = DC_ERROR_UNEXPECTED;
int i;
- if (!context_changed(dc, context))
+ /* TODO: Since change commit sequence can have a huge impact,
+ * we decided to only enable it for DCN3x. However, as soon as
+ * we get more confident about this change we'll need to enable
+ * the new sequence for all ASICs. */
+ if (dc->ctx->dce_version >= DCN_VERSION_3_2) {
+ result = dc_commit_streams(dc, context->streams, context->stream_count);
+ return result == DC_OK;
+ }
+
+ if (!streams_changed(dc, context->streams, context->stream_count))
return DC_OK;
DC_LOG_DC("%s: %d streams\n",
@@ -2950,7 +3064,7 @@ static bool update_planes_and_stream_state(struct dc *dc,
* Ensures that we have enough pipes for newly added MPO planes
*/
if (dc->res_pool->funcs->remove_phantom_pipes)
- dc->res_pool->funcs->remove_phantom_pipes(dc, context);
+ dc->res_pool->funcs->remove_phantom_pipes(dc, context, false);
/*remove old surfaces from context */
if (!dc_rem_all_planes_for_stream(dc, stream, context)) {
@@ -2987,6 +3101,19 @@ static bool update_planes_and_stream_state(struct dc *dc,
if (update_type == UPDATE_TYPE_FULL) {
if (!dc->res_pool->funcs->validate_bandwidth(dc, context, false)) {
+ /* For phantom pipes we remove and create a new set of phantom pipes
+ * for each full update (because we don't know if we'll need phantom
+ * pipes until after the first round of validation). However, if validation
+ * fails we need to keep the existing phantom pipes (because we don't update
+ * the dc->current_state).
+ *
+ * The phantom stream/plane refcount is decremented for validation because
+ * we assume it'll be removed (the free comes when the dc_state is freed),
+ * but if validation fails we have to increment back the refcount so it's
+ * consistent.
+ */
+ if (dc->res_pool->funcs->retain_phantom_pipes)
+ dc->res_pool->funcs->retain_phantom_pipes(dc, dc->current_state);
BREAK_TO_DEBUGGER();
goto fail;
}
@@ -3297,22 +3424,6 @@ static void commit_planes_for_stream(struct dc *dc,
dc->hwss.pipe_control_lock(dc, top_pipe_to_program, true);
}
- if (update_type != UPDATE_TYPE_FAST) {
- for (i = 0; i < dc->res_pool->pipe_count; i++) {
- struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i];
-
- if ((new_pipe->stream && new_pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) ||
- subvp_prev_use) {
- // If old context or new context has phantom pipes, apply
- // the phantom timings now. We can't change the phantom
- // pipe configuration safely without driver acquiring
- // the DMCUB lock first.
- dc->hwss.apply_ctx_to_hw(dc, context);
- break;
- }
- }
- }
-
dc_dmub_update_dirty_rect(dc, surface_count, stream, srf_updates, context);
if (update_type != UPDATE_TYPE_FAST) {
@@ -3370,6 +3481,24 @@ static void commit_planes_for_stream(struct dc *dc,
return;
}
+ if (update_type != UPDATE_TYPE_FAST) {
+ 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 &&
+ pipe_ctx->stream && pipe_ctx->plane_state) {
+ /* Only update visual confirm for SUBVP 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,
+ 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;
@@ -3487,7 +3616,6 @@ static void commit_planes_for_stream(struct dc *dc,
dc->hwss.update_plane_addr(dc, pipe_ctx);
}
}
-
}
if (should_lock_all_pipes && dc->hwss.interdependent_update_lock) {
@@ -3524,6 +3652,44 @@ static void commit_planes_for_stream(struct dc *dc,
top_pipe_to_program->stream_res.tg);
}
+ /* For phantom pipe OTG enable, it has to be done after any previous pipe
+ * that was in use has already been programmed at gotten its double buffer
+ * update for "disable".
+ */
+ if (update_type != UPDATE_TYPE_FAST) {
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+ struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+
+ /* If an active, non-phantom pipe is being transitioned into a phantom
+ * pipe, wait for the double buffer update to complete first before we do
+ * ANY phantom pipe programming.
+ */
+ if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM &&
+ old_pipe->stream && old_pipe->stream->mall_stream_config.type != SUBVP_PHANTOM) {
+ old_pipe->stream_res.tg->funcs->wait_for_state(
+ old_pipe->stream_res.tg,
+ CRTC_STATE_VBLANK);
+ old_pipe->stream_res.tg->funcs->wait_for_state(
+ old_pipe->stream_res.tg,
+ CRTC_STATE_VACTIVE);
+ }
+ }
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *new_pipe = &context->res_ctx.pipe_ctx[i];
+
+ if ((new_pipe->stream && new_pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) ||
+ subvp_prev_use) {
+ // If old context or new context has phantom pipes, apply
+ // the phantom timings now. We can't change the phantom
+ // pipe configuration safely without driver acquiring
+ // the DMCUB lock first.
+ dc->hwss.apply_ctx_to_hw(dc, context);
+ break;
+ }
+ }
+ }
+
if (update_type != UPDATE_TYPE_FAST)
dc->hwss.post_unlock_program_front_end(dc, context);
if (update_type != UPDATE_TYPE_FAST)
@@ -3563,10 +3729,24 @@ static void commit_planes_for_stream(struct dc *dc,
}
}
-/* Determines if the incoming context requires a applying transition state with unnecessary
- * pipe splitting and ODM disabled, due to hardware limitations. In a case where
- * the OPP associated with an MPCC might change due to plane additions, this function
+/**
+ * could_mpcc_tree_change_for_active_pipes - Check if an OPP associated with MPCC might change
+ *
+ * @dc: Used to get the current state status
+ * @stream: Target stream, which we want to remove the attached planes
+ * @surface_count: Number of surface update
+ * @is_plane_addition: [in] Fill out with true if it is a plane addition case
+ *
+ * DCN32x and newer support a feature named Dynamic ODM which can conflict with
+ * the MPO if used simultaneously in some specific configurations (e.g.,
+ * 4k@144). This function checks if the incoming context requires applying a
+ * transition state with unnecessary pipe splitting and ODM disabled to
+ * circumvent our hardware limitations to prevent this edge case. If the OPP
+ * associated with an MPCC might change due to plane additions, this function
* returns true.
+ *
+ * Return:
+ * Return true if OPP and MPCC might change, otherwise, return false.
*/
static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc,
struct dc_stream_state *stream,
@@ -3576,6 +3756,7 @@ static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc,
struct dc_stream_status *cur_stream_status = stream_get_status(dc->current_state, stream);
bool force_minimal_pipe_splitting = false;
+ bool subvp_active = false;
uint32_t i;
*is_plane_addition = false;
@@ -3608,39 +3789,55 @@ static bool could_mpcc_tree_change_for_active_pipes(struct dc *dc,
}
}
- /* For SubVP pipe split case when adding MPO video
- * we need to add a minimal transition. In this case
- * there will be 2 streams (1 main stream, 1 phantom
- * stream).
- */
- if (cur_stream_status &&
- dc->current_state->stream_count == 2 &&
- stream->mall_stream_config.type == SUBVP_MAIN) {
- bool is_pipe_split = false;
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
- for (i = 0; i < dc->res_pool->pipe_count; i++) {
- if (dc->current_state->res_ctx.pipe_ctx[i].stream == stream &&
- (dc->current_state->res_ctx.pipe_ctx[i].bottom_pipe ||
- dc->current_state->res_ctx.pipe_ctx[i].next_odm_pipe)) {
- is_pipe_split = true;
- break;
- }
+ if (pipe->stream && pipe->stream->mall_stream_config.type != SUBVP_NONE) {
+ subvp_active = true;
+ break;
}
+ }
+ /* For SubVP when adding or removing planes we need to add a minimal transition
+ * (even when disabling all planes). Whenever disabling a phantom pipe, we
+ * must use the minimal transition path to disable the pipe correctly.
+ *
+ * We want to use the minimal transition whenever subvp is active, not only if
+ * a plane is being added / removed from a subvp stream (MPO plane can be added
+ * to a DRR pipe of SubVP + DRR config, in which case we still want to run through
+ * a min transition to disable subvp.
+ */
+ if (cur_stream_status && subvp_active) {
/* determine if minimal transition is required due to SubVP*/
- if (surface_count > 0 && is_pipe_split) {
- if (cur_stream_status->plane_count > surface_count) {
- force_minimal_pipe_splitting = true;
- } else if (cur_stream_status->plane_count < surface_count) {
- force_minimal_pipe_splitting = true;
- *is_plane_addition = true;
- }
+ if (cur_stream_status->plane_count > surface_count) {
+ force_minimal_pipe_splitting = true;
+ } else if (cur_stream_status->plane_count < surface_count) {
+ force_minimal_pipe_splitting = true;
+ *is_plane_addition = true;
}
}
return force_minimal_pipe_splitting;
}
+/**
+ * commit_minimal_transition_state - Create a transition pipe split state
+ *
+ * @dc: Used to get the current state status
+ * @transition_base_context: New transition state
+ *
+ * In some specific configurations, such as pipe split on multi-display with
+ * MPO and/or Dynamic ODM, removing a plane may cause unsupported pipe
+ * programming when moving to new planes. To mitigate those types of problems,
+ * this function adds a transition state that minimizes pipe usage before
+ * programming the new configuration. When adding a new plane, the current
+ * state requires the least pipes, so it is applied without splitting. When
+ * removing a plane, the new state requires the least pipes, so it is applied
+ * without splitting.
+ *
+ * Return:
+ * Return false if something is wrong in the transition state.
+ */
static bool commit_minimal_transition_state(struct dc *dc,
struct dc_state *transition_base_context)
{
@@ -3650,9 +3847,48 @@ static bool commit_minimal_transition_state(struct dc *dc,
bool temp_subvp_policy;
enum dc_status ret = DC_ERROR_UNEXPECTED;
unsigned int i, j;
+ unsigned int pipe_in_use = 0;
+ bool subvp_in_use = false;
if (!transition_context)
return false;
+ /* Setup:
+ * Store the current ODM and MPC config in some temp variables to be
+ * restored after we commit the transition state.
+ */
+
+ /* check current pipes in use*/
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &transition_base_context->res_ctx.pipe_ctx[i];
+
+ if (pipe->plane_state)
+ pipe_in_use++;
+ }
+
+ /* If SubVP is enabled and we are adding or removing planes from any main subvp
+ * pipe, we must use the minimal transition.
+ */
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+
+ if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
+ subvp_in_use = true;
+ break;
+ }
+ }
+
+ /* When the OS add a new surface if we have been used all of pipes with odm combine
+ * and mpc split feature, it need use commit_minimal_transition_state to transition safely.
+ * After OS exit MPO, it will back to use odm and mpc split with all of pipes, we need
+ * call it again. Otherwise return true to skip.
+ *
+ * Reduce the scenarios to use dc_commit_state_no_check in the stage of flip. Especially
+ * enter/exit MPO when DCN still have enough resources.
+ */
+ if (pipe_in_use != dc->res_pool->pipe_count && !subvp_in_use) {
+ dc_release_state(transition_context);
+ return true;
+ }
if (!dc->config.is_vmin_only_asic) {
tmp_mpc_policy = dc->debug.pipe_split_policy;
@@ -3667,7 +3903,7 @@ static bool commit_minimal_transition_state(struct dc *dc,
dc_resource_state_copy_construct(transition_base_context, transition_context);
- //commit minimal state
+ /* commit minimal state */
if (dc->res_pool->funcs->validate_bandwidth(dc, transition_context, false)) {
for (i = 0; i < transition_context->stream_count; i++) {
struct dc_stream_status *stream_status = &transition_context->stream_status[i];
@@ -3685,10 +3921,12 @@ static bool commit_minimal_transition_state(struct dc *dc,
ret = dc_commit_state_no_check(dc, transition_context);
}
- /*always release as dc_commit_state_no_check retains in good case*/
+ /* always release as dc_commit_state_no_check retains in good case */
dc_release_state(transition_context);
- /*restore previous pipe split and odm policy*/
+ /* TearDown:
+ * Restore original configuration for ODM and MPO.
+ */
if (!dc->config.is_vmin_only_asic)
dc->debug.pipe_split_policy = tmp_mpc_policy;
@@ -3696,12 +3934,12 @@ static bool commit_minimal_transition_state(struct dc *dc,
dc->debug.force_disable_subvp = temp_subvp_policy;
if (ret != DC_OK) {
- /*this should never happen*/
+ /* this should never happen */
BREAK_TO_DEBUGGER();
return false;
}
- /*force full surface update*/
+ /* force full surface update */
for (i = 0; i < dc->current_state->stream_count; i++) {
for (j = 0; j < dc->current_state->stream_status[i].plane_count; j++) {
dc->current_state->stream_status[i].plane_states[j]->update_flags.raw = 0xFFFFFFFF;
@@ -3719,6 +3957,7 @@ bool dc_update_planes_and_stream(struct dc *dc,
struct dc_state *context;
enum surface_update_type update_type;
int i;
+ struct mall_temp_config mall_temp_config;
/* In cases where MPO and split or ODM are used transitions can
* cause underflow. Apply stream configuration with minimal pipe
@@ -3750,11 +3989,29 @@ bool dc_update_planes_and_stream(struct dc *dc,
/* on plane removal, minimal state is the new one */
if (force_minimal_pipe_splitting && !is_plane_addition) {
+ /* Since all phantom pipes are removed in full validation,
+ * we have to save and restore the subvp/mall config when
+ * we do a minimal transition since the flags marking the
+ * pipe as subvp/phantom will be cleared (dc copy constructor
+ * creates a shallow copy).
+ */
+ if (dc->res_pool->funcs->save_mall_state)
+ dc->res_pool->funcs->save_mall_state(dc, context, &mall_temp_config);
if (!commit_minimal_transition_state(dc, context)) {
dc_release_state(context);
return false;
}
-
+ if (dc->res_pool->funcs->restore_mall_state)
+ dc->res_pool->funcs->restore_mall_state(dc, context, &mall_temp_config);
+
+ /* If we do a minimal transition with plane removal and the context
+ * has subvp we also have to retain back the phantom stream / planes
+ * since the refcount is decremented as part of the min transition
+ * (we commit a state with no subvp, so the phantom streams / planes
+ * had to be removed).
+ */
+ if (dc->res_pool->funcs->retain_phantom_pipes)
+ dc->res_pool->funcs->retain_phantom_pipes(dc, context);
update_type = UPDATE_TYPE_FULL;
}
@@ -3806,6 +4063,18 @@ void dc_commit_updates_for_stream(struct dc *dc,
struct dc_context *dc_ctx = dc->ctx;
int i, j;
+ /* TODO: Since change commit sequence can have a huge impact,
+ * we decided to only enable it for DCN3x. However, as soon as
+ * we get more confident about this change we'll need to enable
+ * the new sequence for all ASICs.
+ */
+ if (dc->ctx->dce_version >= DCN_VERSION_3_2) {
+ dc_update_planes_and_stream(dc, srf_updates,
+ surface_count, stream,
+ stream_update);
+ return;
+ }
+
stream_status = dc_stream_get_status(stream);
context = dc->current_state;
@@ -4387,21 +4656,17 @@ void dc_mclk_switch_using_fw_based_vblank_stretch_shut_down(struct dc *dc)
dc->current_state->bw_ctx.bw.dcn.clk.fw_based_mclk_switching_shut_down = true;
}
-/*
- *****************************************************************************
- * Function: dc_is_dmub_outbox_supported -
+/**
+ * dc_is_dmub_outbox_supported - Check if DMUB firmware support outbox notification
*
- * @brief
- * Checks whether DMUB FW supports outbox notifications, if supported
- * DM should register outbox interrupt prior to actually enabling interrupts
- * via dc_enable_dmub_outbox
+ * @dc: [in] dc structure
*
- * @param
- * [in] dc: dc structure
+ * Checks whether DMUB FW supports outbox notifications, if supported DM
+ * should register outbox interrupt prior to actually enabling interrupts
+ * via dc_enable_dmub_outbox
*
- * @return
- * True if DMUB FW supports outbox notifications, False otherwise
- *****************************************************************************
+ * Return:
+ * True if DMUB FW supports outbox notifications, False otherwise
*/
bool dc_is_dmub_outbox_supported(struct dc *dc)
{
@@ -4419,21 +4684,17 @@ bool dc_is_dmub_outbox_supported(struct dc *dc)
return dc->debug.enable_dmub_aux_for_legacy_ddc;
}
-/*
- *****************************************************************************
- * Function: dc_enable_dmub_notifications
+/**
+ * dc_enable_dmub_notifications - Check if dmub fw supports outbox
*
- * @brief
- * Calls dc_is_dmub_outbox_supported to check if dmub fw supports outbox
- * notifications. All DMs shall switch to dc_is_dmub_outbox_supported.
- * This API shall be removed after switching.
+ * @dc: [in] dc structure
*
- * @param
- * [in] dc: dc structure
+ * Calls dc_is_dmub_outbox_supported to check if dmub fw supports outbox
+ * notifications. All DMs shall switch to dc_is_dmub_outbox_supported. This
+ * API shall be removed after switching.
*
- * @return
- * True if DMUB FW supports outbox notifications, False otherwise
- *****************************************************************************
+ * Return:
+ * True if DMUB FW supports outbox notifications, False otherwise
*/
bool dc_enable_dmub_notifications(struct dc *dc)
{
@@ -4441,18 +4702,11 @@ bool dc_enable_dmub_notifications(struct dc *dc)
}
/**
- *****************************************************************************
- * Function: dc_enable_dmub_outbox
+ * dc_enable_dmub_outbox - Enables DMUB unsolicited notification
*
- * @brief
- * Enables DMUB unsolicited notifications to x86 via outbox
+ * dc: [in] dc structure
*
- * @param
- * [in] dc: dc structure
- *
- * @return
- * None
- *****************************************************************************
+ * Enables DMUB unsolicited notifications to x86 via outbox.
*/
void dc_enable_dmub_outbox(struct dc *dc)
{
@@ -4553,21 +4807,17 @@ uint8_t get_link_index_from_dpia_port_index(const struct dc *dc,
}
/**
- *****************************************************************************
- * Function: dc_process_dmub_set_config_async
+ * dc_process_dmub_set_config_async - Submits set_config command
*
- * @brief
- * Submits set_config command to dmub via inbox message
+ * @dc: [in] dc structure
+ * @link_index: [in] link_index: link index
+ * @payload: [in] aux payload
+ * @notify: [out] set_config immediate reply
*
- * @param
- * [in] dc: dc structure
- * [in] link_index: link index
- * [in] payload: aux payload
- * [out] notify: set_config immediate reply
+ * Submits set_config command to dmub via inbox message.
*
- * @return
- * True if successful, False if failure
- *****************************************************************************
+ * Return:
+ * True if successful, False if failure
*/
bool dc_process_dmub_set_config_async(struct dc *dc,
uint32_t link_index,
@@ -4603,21 +4853,17 @@ bool dc_process_dmub_set_config_async(struct dc *dc,
}
/**
- *****************************************************************************
- * Function: dc_process_dmub_set_mst_slots
+ * dc_process_dmub_set_mst_slots - Submits MST solt allocation
*
- * @brief
- * Submits mst slot allocation command to dmub via inbox message
+ * @dc: [in] dc structure
+ * @link_index: [in] link index
+ * @mst_alloc_slots: [in] mst slots to be allotted
+ * @mst_slots_in_use: [out] mst slots in use returned in failure case
*
- * @param
- * [in] dc: dc structure
- * [in] link_index: link index
- * [in] mst_alloc_slots: mst slots to be allotted
- * [out] mst_slots_in_use: mst slots in use returned in failure case
+ * Submits mst slot allocation command to dmub via inbox message
*
- * @return
- * DC_OK if successful, DC_ERROR if failure
- *****************************************************************************
+ * Return:
+ * DC_OK if successful, DC_ERROR if failure
*/
enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
uint32_t link_index,
@@ -4657,19 +4903,12 @@ enum dc_status dc_process_dmub_set_mst_slots(const struct dc *dc,
}
/**
- *****************************************************************************
- * Function: dc_process_dmub_dpia_hpd_int_enable
+ * dc_process_dmub_dpia_hpd_int_enable - Submits DPIA DPD interruption
*
- * @brief
- * Submits dpia hpd int enable command to dmub via inbox message
+ * @dc [in]: dc structure
+ * @hpd_int_enable [in]: 1 for hpd int enable, 0 to disable
*
- * @param
- * [in] dc: dc structure
- * [in] hpd_int_enable: 1 for hpd int enable, 0 to disable
- *
- * @return
- * None
- *****************************************************************************
+ * Submits dpia hpd int enable command to dmub via inbox message
*/
void dc_process_dmub_dpia_hpd_int_enable(const struct dc *dc,
uint32_t hpd_int_enable)
@@ -4698,16 +4937,13 @@ void dc_disable_accelerated_mode(struct dc *dc)
/**
- *****************************************************************************
- * dc_notify_vsync_int_state() - notifies vsync enable/disable state
+ * dc_notify_vsync_int_state - notifies vsync enable/disable state
* @dc: dc structure
- * @stream: stream where vsync int state changed
- * @enable: whether vsync is enabled or disabled
- *
- * Called when vsync is enabled/disabled
- * Will notify DMUB to start/stop ABM interrupts after steady state is reached
+ * @stream: stream where vsync int state changed
+ * @enable: whether vsync is enabled or disabled
*
- *****************************************************************************
+ * Called when vsync is enabled/disabled Will notify DMUB to start/stop ABM
+ * interrupts after steady state is reached.
*/
void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bool enable)
{
@@ -4749,14 +4985,18 @@ 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_extended_blank_supported 0 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.
+ * 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.
*
- * @param [in] dc: Current DC state
- * @return: Indicate whether extended blank is supported (true or false)
+ * Return:
+ * Indicate whether extended blank is supported (true or false)
*/
bool dc_extended_blank_supported(struct dc *dc)
{
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 7c2e3b8dc26a..471078fc3900 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
@@ -366,6 +366,7 @@ void get_hdr_visual_confirm_color(
struct tg_color *color)
{
uint32_t color_value = MAX_TG_COLOR_VALUE;
+ bool is_sdr = false;
/* Determine the overscan color based on the top-most (desktop) plane's context */
struct pipe_ctx *top_pipe_ctx = pipe_ctx;
@@ -382,7 +383,8 @@ void get_hdr_visual_confirm_color(
/* FreeSync 2 ARGB2101010 - set border color to pink */
color->color_r_cr = color_value;
color->color_b_cb = color_value;
- }
+ } else
+ is_sdr = true;
break;
case PIXEL_FORMAT_FP16:
if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_PQ) {
@@ -391,14 +393,19 @@ void get_hdr_visual_confirm_color(
} else if (top_pipe_ctx->stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) {
/* FreeSync 2 HDR - set border color to green */
color->color_g_y = color_value;
- }
+ } else
+ is_sdr = true;
break;
default:
+ is_sdr = true;
+ break;
+ }
+
+ if (is_sdr) {
/* SDR - set border color to Gray */
color->color_r_cr = color_value/2;
color->color_b_cb = color_value/2;
color->color_g_y = color_value/2;
- break;
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
index d7b1ace6328a..342e906ae26e 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c
@@ -3378,7 +3378,7 @@ bool dc_link_setup_psr(struct dc_link *link,
case FAMILY_YELLOW_CARP:
case AMDGPU_FAMILY_GC_10_3_6:
case AMDGPU_FAMILY_GC_11_0_1:
- if (dc->debug.disable_z10)
+ if (dc->debug.disable_z10 || dc->debug.psr_skip_crtc_disable)
psr_context->psr_level.bits.SKIP_CRTC_DISABLE = true;
break;
default:
@@ -4229,6 +4229,7 @@ static void fpga_dp_hpo_enable_link_and_stream(struct dc_state *state, struct pi
link_hwss->ext.set_throttled_vcp_size(pipe_ctx, avg_time_slots_per_mtp);
dc->hwss.unblank_stream(pipe_ctx, &stream->link->cur_link_settings);
+ dc->hwss.enable_audio_stream(pipe_ctx);
}
void core_link_enable_stream(
@@ -4308,10 +4309,7 @@ void core_link_enable_stream(
/* 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);
- if (pipe_ctx->stream_res.audio != NULL) {
- pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
- dc->hwss.enable_audio_stream(pipe_ctx);
- }
+ dc->hwss.enable_audio_stream(pipe_ctx);
}
#if defined(CONFIG_DRM_AMD_DC_HDCP)
@@ -4665,6 +4663,10 @@ void dc_link_set_preferred_training_settings(struct dc *dc,
link->preferred_link_setting.link_rate = LINK_RATE_UNKNOWN;
}
+ if (link->connector_signal == SIGNAL_TYPE_DISPLAY_PORT &&
+ link->type == dc_connection_mst_branch)
+ dm_helpers_dp_mst_update_branch_bandwidth(dc->ctx, link);
+
/* Retrain now, or wait until next stream update to apply */
if (skip_immediate_retrain == false)
dc_link_set_preferred_link_settings(dc, &link->preferred_link_setting, link);
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
index 651231387043..ce8d6a54ca54 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
@@ -82,6 +82,7 @@ struct dp_hdmi_dongle_signature_data {
#define HDMI_SCDC_STATUS_FLAGS 0x40
#define HDMI_SCDC_ERR_DETECT 0x50
#define HDMI_SCDC_TEST_CONFIG 0xC0
+#define HDMI_SCDC_DEVICE_ID 0xD3
union hdmi_scdc_update_read_data {
uint8_t byte[2];
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
index 1254d38f1778..dedd1246ce58 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
@@ -1912,7 +1912,7 @@ enum dc_status dpcd_configure_lttpr_mode(struct dc_link *link, struct link_train
return status;
}
-static void dpcd_exit_training_mode(struct dc_link *link)
+static void dpcd_exit_training_mode(struct dc_link *link, enum dp_link_encoding encoding)
{
uint8_t sink_status = 0;
uint8_t i;
@@ -1920,12 +1920,14 @@ static void dpcd_exit_training_mode(struct dc_link *link)
/* clear training pattern set */
dpcd_set_training_pattern(link, DP_TRAINING_PATTERN_VIDEOIDLE);
- /* poll for intra-hop disable */
- for (i = 0; i < 10; i++) {
- if ((core_link_read_dpcd(link, DP_SINK_STATUS, &sink_status, 1) == DC_OK) &&
- (sink_status & DP_INTRA_HOP_AUX_REPLY_INDICATION) == 0)
- break;
- udelay(1000);
+ if (encoding == DP_128b_132b_ENCODING) {
+ /* poll for intra-hop disable */
+ for (i = 0; i < 10; i++) {
+ if ((core_link_read_dpcd(link, DP_SINK_STATUS, &sink_status, 1) == DC_OK) &&
+ (sink_status & DP_INTRA_HOP_AUX_REPLY_INDICATION) == 0)
+ break;
+ udelay(1000);
+ }
}
}
@@ -2649,7 +2651,7 @@ enum link_training_result dc_link_dp_perform_link_training(
&lt_settings);
/* reset previous training states */
- dpcd_exit_training_mode(link);
+ dpcd_exit_training_mode(link, encoding);
/* configure link prior to entering training mode */
dpcd_configure_lttpr_mode(link, &lt_settings);
@@ -2670,7 +2672,7 @@ enum link_training_result dc_link_dp_perform_link_training(
ASSERT(0);
/* exit training mode */
- dpcd_exit_training_mode(link);
+ dpcd_exit_training_mode(link, encoding);
/* switch to video idle */
if ((status == LINK_TRAINING_SUCCESS) || !skip_video_pattern)
@@ -2771,8 +2773,11 @@ bool perform_link_training_with_retries(
/* Update verified link settings to current one
* Because DPIA LT might fallback to lower link setting.
*/
- link->verified_link_cap.link_rate = link->cur_link_settings.link_rate;
- link->verified_link_cap.lane_count = link->cur_link_settings.lane_count;
+ if (stream->signal == SIGNAL_TYPE_DISPLAY_PORT_MST) {
+ link->verified_link_cap.link_rate = link->cur_link_settings.link_rate;
+ link->verified_link_cap.lane_count = link->cur_link_settings.lane_count;
+ dm_helpers_dp_mst_update_branch_bandwidth(link->ctx, link);
+ }
}
} else {
status = dc_link_dp_perform_link_training(link,
@@ -3020,7 +3025,7 @@ static enum dc_link_rate get_lttpr_max_link_rate(struct dc_link *link)
static enum dc_link_rate get_cable_max_link_rate(struct dc_link *link)
{
- enum dc_link_rate cable_max_link_rate = LINK_RATE_HIGH3;
+ enum dc_link_rate cable_max_link_rate = LINK_RATE_UNKNOWN;
if (link->dpcd_caps.cable_id.bits.UHBR10_20_CAPABILITY & DP_UHBR20)
cable_max_link_rate = LINK_RATE_UHBR20;
@@ -3083,15 +3088,29 @@ struct dc_link_settings dp_get_max_link_cap(struct dc_link *link)
max_link_cap.link_spread =
link->reported_link_cap.link_spread;
- /* Lower link settings based on cable attributes */
+ /* Lower link settings based on cable attributes
+ * Cable ID is a DP2 feature to identify max certified link rate that
+ * a cable can carry. The cable identification method requires both
+ * cable and display hardware support. Since the specs comes late, it is
+ * anticipated that the first round of DP2 cables and displays may not
+ * be fully compatible to reliably return cable ID data. Therefore the
+ * decision of our cable id policy is that if the cable can return non
+ * zero cable id data, we will take cable's link rate capability into
+ * account. However if we get zero data, the cable link rate capability
+ * is considered inconclusive. In this case, we will not take cable's
+ * capability into account to avoid of over limiting hardware capability
+ * from users. The max overall link rate capability is still determined
+ * after actual dp pre-training. Cable id is considered as an auxiliary
+ * method of determining max link bandwidth capability.
+ */
cable_max_link_rate = get_cable_max_link_rate(link);
if (!link->dc->debug.ignore_cable_id &&
+ cable_max_link_rate != LINK_RATE_UNKNOWN &&
cable_max_link_rate < max_link_cap.link_rate)
max_link_cap.link_rate = cable_max_link_rate;
- /*
- * account for lttpr repeaters cap
+ /* account for lttpr repeaters cap
* notes: repeaters do not snoop in the DPRX Capabilities addresses (3.6.3).
*/
if (dp_is_lttpr_present(link)) {
@@ -4540,9 +4559,19 @@ void dc_link_dp_handle_link_loss(struct dc_link *link)
for (i = 0; i < MAX_PIPES; i++) {
pipe_ctx = &link->dc->current_state->res_ctx.pipe_ctx[i];
- if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off &&
- pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe)
+ if (pipe_ctx && pipe_ctx->stream && !pipe_ctx->stream->dpms_off
+ && pipe_ctx->stream->link == link && !pipe_ctx->prev_odm_pipe) {
+ // Always use max settings here for DP 1.4a LL Compliance CTS
+ if (link->is_automated) {
+ pipe_ctx->link_config.dp_link_settings.lane_count =
+ link->verified_link_cap.lane_count;
+ pipe_ctx->link_config.dp_link_settings.link_rate =
+ link->verified_link_cap.link_rate;
+ pipe_ctx->link_config.dp_link_settings.link_spread =
+ link->verified_link_cap.link_spread;
+ }
core_link_enable_stream(link->dc->current_state, pipe_ctx);
+ }
}
}
@@ -4583,6 +4612,8 @@ bool dc_link_handle_hpd_rx_irq(struct dc_link *link, union hpd_irq_data *out_hpd
}
if (hpd_irq_dpcd_data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
+ // Workaround for DP 1.4a LL Compliance CTS as USB4 has to share encoders unlike DP and USBC
+ link->is_automated = true;
device_service_clear.bits.AUTOMATED_TEST = 1;
core_link_write_dpcd(
link,
@@ -5031,7 +5062,7 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link)
return true;
}
-bool dp_retrieve_lttpr_cap(struct dc_link *link)
+enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link)
{
uint8_t lttpr_dpcd_data[8];
enum dc_status status = DC_ERROR_UNEXPECTED;
@@ -5099,7 +5130,7 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link)
CONN_DATA_DETECT(link, lttpr_dpcd_data, sizeof(lttpr_dpcd_data), "LTTPR Caps: ");
DC_LOG_DC("is_lttpr_present = %d\n", is_lttpr_present);
- return is_lttpr_present;
+ return status;
}
bool dp_is_lttpr_present(struct dc_link *link)
@@ -5227,76 +5258,45 @@ static void retrieve_cable_id(struct dc_link *link)
&link->dpcd_caps.cable_id, &usbc_cable_id);
}
-/* DPRX may take some time to respond to AUX messages after HPD asserted.
- * If AUX read unsuccessful, try to wake unresponsive DPRX by toggling DPCD SET_POWER (0x600).
- */
-static enum dc_status wa_try_to_wake_dprx(struct dc_link *link, uint64_t timeout_ms)
+static enum dc_status wake_up_aux_channel(struct dc_link *link)
{
enum dc_status status = DC_ERROR_UNEXPECTED;
- uint8_t dpcd_data = 0;
- uint64_t start_ts = 0;
- uint64_t current_ts = 0;
- uint64_t time_taken_ms = 0;
- enum dc_connection_type type = dc_connection_none;
- bool lttpr_present;
- bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware;
+ uint32_t aux_channel_retry_cnt = 0;
+ uint8_t dpcd_power_state = '\0';
- lttpr_present = dp_is_lttpr_present(link) ||
- (!vbios_lttpr_interop || !link->dc->caps.extended_aux_timeout_support);
- DC_LOG_DC("lttpr_present = %d.\n", lttpr_present ? 1 : 0);
+ while (status != DC_OK && aux_channel_retry_cnt < 10) {
+ status = core_link_read_dpcd(link, DP_SET_POWER,
+ &dpcd_power_state, sizeof(dpcd_power_state));
- /* Issue an AUX read to test DPRX responsiveness. If LTTPR is supported the first read is expected to
- * be to determine LTTPR capabilities. Otherwise trying to read power state should be an innocuous AUX read.
- */
- if (lttpr_present)
- status = core_link_read_dpcd(
- link,
- DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV,
- &dpcd_data,
- sizeof(dpcd_data));
- else
- status = core_link_read_dpcd(
- link,
- DP_SET_POWER,
- &dpcd_data,
- sizeof(dpcd_data));
+ /* Delay 1 ms if AUX CH is in power down state. Based on spec
+ * section 2.3.1.2, if AUX CH may be powered down due to
+ * write to DPCD 600h = 2. Sink AUX CH is monitoring differential
+ * signal and may need up to 1 ms before being able to reply.
+ */
+ if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D3) {
+ udelay(1000);
+ aux_channel_retry_cnt++;
+ }
+ }
if (status != DC_OK) {
- DC_LOG_WARNING("%s: Read DPCD LTTPR_CAP failed - try to toggle DPCD SET_POWER for %lld ms.",
- __func__,
- timeout_ms);
- start_ts = dm_get_timestamp(link->ctx);
-
- do {
- if (!dc_link_detect_sink(link, &type) || type == dc_connection_none)
- break;
-
- dpcd_data = DP_SET_POWER_D3;
- status = core_link_write_dpcd(
- link,
- DP_SET_POWER,
- &dpcd_data,
- sizeof(dpcd_data));
-
- dpcd_data = DP_SET_POWER_D0;
- status = core_link_write_dpcd(
- link,
- DP_SET_POWER,
- &dpcd_data,
- sizeof(dpcd_data));
-
- current_ts = dm_get_timestamp(link->ctx);
- time_taken_ms = div_u64(dm_get_elapse_time_in_ns(link->ctx, current_ts, start_ts), 1000000);
- } while (status != DC_OK && time_taken_ms < timeout_ms);
+ dpcd_power_state = DP_SET_POWER_D0;
+ status = core_link_write_dpcd(
+ link,
+ DP_SET_POWER,
+ &dpcd_power_state,
+ sizeof(dpcd_power_state));
- DC_LOG_WARNING("%s: DPCD SET_POWER %s after %lld ms%s",
- __func__,
- (status == DC_OK) ? "succeeded" : "failed",
- time_taken_ms,
- (type == dc_connection_none) ? ". Unplugged." : ".");
+ dpcd_power_state = DP_SET_POWER_D3;
+ status = core_link_write_dpcd(
+ link,
+ DP_SET_POWER,
+ &dpcd_power_state,
+ sizeof(dpcd_power_state));
+ return DC_ERROR_UNEXPECTED;
}
- return status;
+ return DC_OK;
}
static bool retrieve_link_cap(struct dc_link *link)
@@ -5308,7 +5308,6 @@ static bool retrieve_link_cap(struct dc_link *link)
/*Only need to read 1 byte starting from DP_DPRX_FEATURE_ENUMERATION_LIST.
*/
uint8_t dpcd_dprx_data = '\0';
- uint8_t dpcd_power_state = '\0';
struct dp_device_vendor_id sink_id;
union down_stream_port_count down_strm_port_count;
@@ -5316,11 +5315,9 @@ static bool retrieve_link_cap(struct dc_link *link)
union dp_downstream_port_present ds_port = { 0 };
enum dc_status status = DC_ERROR_UNEXPECTED;
uint32_t read_dpcd_retry_cnt = 3;
- uint32_t aux_channel_retry_cnt = 0;
int i;
struct dp_sink_hw_fw_revision dp_hw_fw_revision;
const uint32_t post_oui_delay = 30; // 30ms
- bool is_lttpr_present = false;
memset(dpcd_data, '\0', sizeof(dpcd_data));
memset(&down_strm_port_count,
@@ -5335,51 +5332,17 @@ static bool retrieve_link_cap(struct dc_link *link)
dc_link_aux_try_to_configure_timeout(link->ddc,
LINK_AUX_DEFAULT_LTTPR_TIMEOUT_PERIOD);
- /* Try to ensure AUX channel active before proceeding. */
- if (link->dc->debug.aux_wake_wa.bits.enable_wa) {
- uint64_t timeout_ms = link->dc->debug.aux_wake_wa.bits.timeout_ms;
+ status = dp_retrieve_lttpr_cap(link);
- if (link->dc->debug.aux_wake_wa.bits.use_default_timeout)
- timeout_ms = LINK_AUX_WAKE_TIMEOUT_MS;
- status = wa_try_to_wake_dprx(link, timeout_ms);
- }
-
- while (status != DC_OK && aux_channel_retry_cnt < 10) {
- status = core_link_read_dpcd(link, DP_SET_POWER,
- &dpcd_power_state, sizeof(dpcd_power_state));
-
- /* Delay 1 ms if AUX CH is in power down state. Based on spec
- * section 2.3.1.2, if AUX CH may be powered down due to
- * write to DPCD 600h = 2. Sink AUX CH is monitoring differential
- * signal and may need up to 1 ms before being able to reply.
- */
- if (status != DC_OK || dpcd_power_state == DP_SET_POWER_D3) {
- udelay(1000);
- aux_channel_retry_cnt++;
- }
- }
-
- /* If aux channel is not active, return false and trigger another detect*/
if (status != DC_OK) {
- dpcd_power_state = DP_SET_POWER_D0;
- status = core_link_write_dpcd(
- link,
- DP_SET_POWER,
- &dpcd_power_state,
- sizeof(dpcd_power_state));
-
- dpcd_power_state = DP_SET_POWER_D3;
- status = core_link_write_dpcd(
- link,
- DP_SET_POWER,
- &dpcd_power_state,
- sizeof(dpcd_power_state));
- return false;
+ status = wake_up_aux_channel(link);
+ if (status == DC_OK)
+ dp_retrieve_lttpr_cap(link);
+ else
+ return false;
}
- is_lttpr_present = dp_retrieve_lttpr_cap(link);
-
- if (is_lttpr_present)
+ if (dp_is_lttpr_present(link))
configure_lttpr_mode_transparent(link);
/* Read DP tunneling information. */
@@ -5406,7 +5369,7 @@ static bool retrieve_link_cap(struct dc_link *link)
return false;
}
- if (!is_lttpr_present)
+ if (!dp_is_lttpr_present(link))
dc_link_aux_try_to_configure_timeout(link->ddc, LINK_AUX_DEFAULT_TIMEOUT_PERIOD);
{
@@ -7294,6 +7257,7 @@ void dp_retrain_link_dp_test(struct dc_link *link,
struct pipe_ctx *pipes =
&link->dc->current_state->res_ctx.pipe_ctx[0];
unsigned int i;
+ bool do_fallback = false;
for (i = 0; i < MAX_PIPES; i++) {
@@ -7326,32 +7290,23 @@ void dp_retrain_link_dp_test(struct dc_link *link,
memset(&link->cur_link_settings, 0,
sizeof(link->cur_link_settings));
+ if (link->ep_type == DISPLAY_ENDPOINT_USB4_DPIA)
+ do_fallback = true;
+
perform_link_training_with_retries(
link_setting,
skip_video_pattern,
LINK_TRAINING_ATTEMPTS,
&pipes[i],
SIGNAL_TYPE_DISPLAY_PORT,
- false);
+ do_fallback);
link->dc->hwss.enable_stream(&pipes[i]);
link->dc->hwss.unblank_stream(&pipes[i],
link_setting);
- if (pipes[i].stream_res.audio) {
- /* notify audio driver for
- * audio modes of monitor */
- pipes[i].stream_res.audio->funcs->az_enable(
- pipes[i].stream_res.audio);
-
- /* un-mute audio */
- /* TODO: audio should be per stream rather than
- * per link */
- pipes[i].stream_res.stream_enc->funcs->
- audio_mute_control(
- pipes[i].stream_res.stream_enc, false);
- }
+ link->dc->hwss.enable_audio_stream(&pipes[i]);
}
}
}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dpia.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dpia.c
index 74e36b34d3f7..d130d58ac08e 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dpia.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dpia.c
@@ -791,10 +791,14 @@ static enum link_training_result dpia_training_eq_transparent(
}
if (dp_is_ch_eq_done(lane_count, dpcd_lane_status) &&
- dp_is_symbol_locked(link->cur_link_settings.lane_count, dpcd_lane_status) &&
- dp_is_interlane_aligned(dpcd_lane_status_updated)) {
- result = LINK_TRAINING_SUCCESS;
- break;
+ dp_is_symbol_locked(link->cur_link_settings.lane_count, dpcd_lane_status)) {
+ /* Take into consideration corner case for DP 1.4a LL Compliance CTS as USB4
+ * has to share encoders unlike DP and USBC
+ */
+ if (dp_is_interlane_aligned(dpcd_lane_status_updated) || (link->is_automated && retries_eq)) {
+ result = LINK_TRAINING_SUCCESS;
+ break;
+ }
}
/* Update VS/PE. */
@@ -1008,7 +1012,8 @@ enum link_training_result dc_link_dpia_perform_link_training(
*/
if (result == LINK_TRAINING_SUCCESS) {
msleep(5);
- result = dp_check_link_loss_status(link, &lt_settings);
+ if (!link->is_automated)
+ result = dp_check_link_loss_status(link, &lt_settings);
} else if (result == LINK_TRAINING_ABORT) {
dpia_training_abort(link, &lt_settings, repeater_id);
} else {
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 fd8db482e56f..da164685547d 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -1768,6 +1768,17 @@ bool dc_remove_plane_from_context(
return true;
}
+/**
+ * dc_rem_all_planes_for_stream - Remove planes attached to the target stream.
+ *
+ * @dc: Current dc state.
+ * @stream: Target stream, which we want to remove the attached plans.
+ * @context: New context.
+ *
+ * Return:
+ * Return true if DC was able to remove all planes from the target
+ * stream, otherwise, return false.
+ */
bool dc_rem_all_planes_for_stream(
const struct dc *dc,
struct dc_stream_state *stream,
@@ -2562,9 +2573,12 @@ enum dc_status resource_map_pool_resources(
/**
* dc_resource_state_copy_construct_current() - Creates a new dc_state from existing state
- * Is a shallow copy. Increments refcounts on existing streams and planes.
+ *
* @dc: copy out of dc->current_state
* @dst_ctx: copy into this
+ *
+ * This function makes a shallow copy of the current DC state and increments
+ * refcounts on existing streams and planes.
*/
void dc_resource_state_copy_construct_current(
const struct dc *dc,
@@ -2593,15 +2607,241 @@ bool dc_resource_is_dsc_encoding_supported(const struct dc *dc)
return dc->res_pool->res_cap->num_dsc > 0;
}
+static bool planes_changed_for_existing_stream(struct dc_state *context,
+ struct dc_stream_state *stream,
+ const struct dc_validation_set set[],
+ int set_count)
+{
+ int i, j;
+ struct dc_stream_status *stream_status = NULL;
+
+ for (i = 0; i < context->stream_count; i++) {
+ if (context->streams[i] == stream) {
+ stream_status = &context->stream_status[i];
+ break;
+ }
+ }
+
+ if (!stream_status)
+ ASSERT(0);
+
+ for (i = 0; i < set_count; i++)
+ if (set[i].stream == stream)
+ break;
+
+ if (i == set_count)
+ ASSERT(0);
+
+ if (set[i].plane_count != stream_status->plane_count)
+ return true;
+
+ for (j = 0; j < set[i].plane_count; j++)
+ if (set[i].plane_states[j] != stream_status->plane_states[j])
+ return true;
+
+ return false;
+}
/**
- * dc_validate_global_state() - Determine if HW can support a given state
- * Checks HW resource availability and bandwidth requirement.
+ * dc_validate_with_context - Validate and update the potential new stream in the context object
+ *
+ * @dc: Used to get the current state status
+ * @set: An array of dc_validation_set with all the current streams reference
+ * @set_count: Total of streams
+ * @context: New context
+ * @fast_validate: Enable or disable fast validation
+ *
+ * This function updates the potential new stream in the context object. It
+ * creates multiple lists for the add, remove, and unchanged streams. In
+ * particular, if the unchanged streams have a plane that changed, it is
+ * necessary to remove all planes from the unchanged streams. In summary, this
+ * function is responsible for validating the new context.
+ *
+ * Return:
+ * In case of success, return DC_OK (1), otherwise, return a DC error.
+ */
+enum dc_status dc_validate_with_context(struct dc *dc,
+ const struct dc_validation_set set[],
+ int set_count,
+ struct dc_state *context,
+ bool fast_validate)
+{
+ struct dc_stream_state *unchanged_streams[MAX_PIPES] = { 0 };
+ struct dc_stream_state *del_streams[MAX_PIPES] = { 0 };
+ struct dc_stream_state *add_streams[MAX_PIPES] = { 0 };
+ int old_stream_count = context->stream_count;
+ enum dc_status res = DC_ERROR_UNEXPECTED;
+ int unchanged_streams_count = 0;
+ int del_streams_count = 0;
+ int add_streams_count = 0;
+ bool found = false;
+ int i, j, k;
+
+ DC_LOGGER_INIT(dc->ctx->logger);
+
+ /* First build a list of streams to be remove from current context */
+ for (i = 0; i < old_stream_count; i++) {
+ struct dc_stream_state *stream = context->streams[i];
+
+ for (j = 0; j < set_count; j++) {
+ if (stream == set[j].stream) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ del_streams[del_streams_count++] = stream;
+
+ found = false;
+ }
+
+ /* Second, build a list of new streams */
+ for (i = 0; i < set_count; i++) {
+ struct dc_stream_state *stream = set[i].stream;
+
+ for (j = 0; j < old_stream_count; j++) {
+ if (stream == context->streams[j]) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ add_streams[add_streams_count++] = stream;
+
+ found = false;
+ }
+
+ /* Build a list of unchanged streams which is necessary for handling
+ * planes change such as added, removed, and updated.
+ */
+ for (i = 0; i < set_count; i++) {
+ /* Check if stream is part of the delete list */
+ for (j = 0; j < del_streams_count; j++) {
+ if (set[i].stream == del_streams[j]) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ /* Check if stream is part of the add list */
+ for (j = 0; j < add_streams_count; j++) {
+ if (set[i].stream == add_streams[j]) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found)
+ unchanged_streams[unchanged_streams_count++] = set[i].stream;
+
+ found = false;
+ }
+
+ /* Remove all planes for unchanged streams if planes changed */
+ for (i = 0; i < unchanged_streams_count; i++) {
+ if (planes_changed_for_existing_stream(context,
+ unchanged_streams[i],
+ set,
+ set_count)) {
+ if (!dc_rem_all_planes_for_stream(dc,
+ unchanged_streams[i],
+ context)) {
+ res = DC_FAIL_DETACH_SURFACES;
+ goto fail;
+ }
+ }
+ }
+
+ /* Remove all planes for removed streams and then remove the streams */
+ for (i = 0; i < del_streams_count; i++) {
+ /* Need to cpy the dwb data from the old stream in order to efc to work */
+ if (del_streams[i]->num_wb_info > 0) {
+ for (j = 0; j < add_streams_count; j++) {
+ if (del_streams[i]->sink == add_streams[j]->sink) {
+ add_streams[j]->num_wb_info = del_streams[i]->num_wb_info;
+ for (k = 0; k < del_streams[i]->num_wb_info; k++)
+ add_streams[j]->writeback_info[k] = del_streams[i]->writeback_info[k];
+ }
+ }
+ }
+
+ if (!dc_rem_all_planes_for_stream(dc, del_streams[i], context)) {
+ res = DC_FAIL_DETACH_SURFACES;
+ goto fail;
+ }
+
+ res = dc_remove_stream_from_ctx(dc, context, del_streams[i]);
+ if (res != DC_OK)
+ goto fail;
+ }
+
+ /* Swap seamless boot stream to pipe 0 (if needed) to ensure pipe_ctx
+ * matches. This may change in the future if seamless_boot_stream can be
+ * multiple.
+ */
+ for (i = 0; i < add_streams_count; i++) {
+ mark_seamless_boot_stream(dc, add_streams[i]);
+ if (add_streams[i]->apply_seamless_boot_optimization && i != 0) {
+ struct dc_stream_state *temp = add_streams[0];
+
+ add_streams[0] = add_streams[i];
+ add_streams[i] = temp;
+ break;
+ }
+ }
+
+ /* Add new streams and then add all planes for the new stream */
+ for (i = 0; i < add_streams_count; i++) {
+ calculate_phy_pix_clks(add_streams[i]);
+ res = dc_add_stream_to_ctx(dc, context, add_streams[i]);
+ if (res != DC_OK)
+ goto fail;
+
+ if (!add_all_planes_for_stream(dc, add_streams[i], set, set_count, context)) {
+ res = DC_FAIL_ATTACH_SURFACES;
+ goto fail;
+ }
+ }
+
+ /* Add all planes for unchanged streams if planes changed */
+ for (i = 0; i < unchanged_streams_count; i++) {
+ if (planes_changed_for_existing_stream(context,
+ unchanged_streams[i],
+ set,
+ set_count)) {
+ if (!add_all_planes_for_stream(dc, unchanged_streams[i], set, set_count, context)) {
+ res = DC_FAIL_ATTACH_SURFACES;
+ goto fail;
+ }
+ }
+ }
+
+ res = dc_validate_global_state(dc, context, fast_validate);
+
+fail:
+ if (res != DC_OK)
+ DC_LOG_WARNING("%s:resource validation failed, dc_status:%d\n",
+ __func__,
+ res);
+
+ return res;
+}
+
+/**
+ * dc_validate_global_state() - Determine if hardware can support a given state
+ *
* @dc: dc struct for this driver
* @new_ctx: state to be validated
* @fast_validate: set to true if only yes/no to support matters
*
- * Return: DC_OK if the result can be programmed. Otherwise, an error code.
+ * Checks hardware resource availability and bandwidth requirement.
+ *
+ * Return:
+ * DC_OK if the result can be programmed. Otherwise, an error code.
*/
enum dc_status dc_validate_global_state(
struct dc *dc,
@@ -2789,6 +3029,12 @@ static void set_avi_info_frame(
hdmi_info.bits.C0_C1 = COLORIMETRY_EXTENDED;
}
+ if (pixel_encoding && color_space == COLOR_SPACE_2020_YCBCR &&
+ stream->out_transfer_func->tf == TRANSFER_FUNCTION_GAMMA22) {
+ hdmi_info.bits.EC0_EC2 = 0;
+ hdmi_info.bits.C0_C1 = COLORIMETRY_ITU709;
+ }
+
/* TODO: un-hardcode aspect ratio */
aspect = stream->timing.aspect_ratio;
@@ -3734,4 +3980,4 @@ bool dc_resource_acquire_secondary_pipe_for_mpc_odm(
}
return true;
-} \ No newline at end of file
+}
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 38d71b5c1f2d..20e534f73513 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_stream.c
@@ -332,9 +332,21 @@ bool dc_stream_set_cursor_attributes(
dc = stream->ctx->dc;
- if (dc->debug.allow_sw_cursor_fallback && attributes->height * attributes->width * 4 > 16384)
- if (stream->mall_stream_config.type == SUBVP_MAIN)
+ /* SubVP is not compatible with HW cursor larger than 64 x 64 x 4.
+ * Therefore, if cursor is greater than 64 x 64 x 4, fallback to SW cursor in the following case:
+ * 1. For single display cases, if resolution is >= 5K and refresh rate < 120hz
+ * 2. For multi display cases, if resolution is >= 4K and refresh rate < 120hz
+ *
+ * [< 120hz is a requirement for SubVP configs]
+ */
+ if (dc->debug.allow_sw_cursor_fallback && attributes->height * attributes->width * 4 > 16384) {
+ if (dc->current_state->stream_count == 1 && stream->timing.v_addressable >= 2880 &&
+ ((stream->timing.pix_clk_100hz * 100) / stream->timing.v_total / stream->timing.h_total) < 120)
return false;
+ else if (dc->current_state->stream_count > 1 && stream->timing.v_addressable >= 2160 &&
+ ((stream->timing.pix_clk_100hz * 100) / stream->timing.v_total / stream->timing.h_total) < 120)
+ return false;
+ }
stream->cursor_attributes = *attributes;
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index 0598465fd1a1..85ebeaa2de18 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -47,7 +47,7 @@ struct aux_payload;
struct set_config_cmd_payload;
struct dmub_notification;
-#define DC_VER "3.2.207"
+#define DC_VER "3.2.215"
#define MAX_SURFACES 3
#define MAX_PLANES 6
@@ -56,9 +56,7 @@ struct dmub_notification;
#define MIN_VIEWPORT_SIZE 12
#define MAX_NUM_EDP 2
-/*******************************************************************************
- * Display Core Interfaces
- ******************************************************************************/
+/* Display Core Interfaces */
struct dc_versions {
const char *dc_ver;
struct dmcu_version dmcu_version;
@@ -263,11 +261,13 @@ struct dc_caps {
uint32_t cache_line_size;
uint32_t cache_num_ways;
uint16_t subvp_fw_processing_delay_us;
+ uint8_t subvp_drr_max_vblank_margin_us;
uint16_t subvp_prefetch_end_to_mall_start_us;
uint8_t subvp_swath_height_margin_lines; // subvp start line must be aligned to 2 x swath height
uint16_t subvp_pstate_allow_width_us;
uint16_t subvp_vertical_int_margin_us;
bool seamless_odm;
+ uint8_t subvp_drr_vblank_start_margin_us;
};
struct dc_bug_wa {
@@ -395,6 +395,7 @@ struct dc_config {
bool disable_dmcu;
bool enable_4to1MPC;
bool enable_windowed_mpo_odm;
+ bool forceHBR2CP2520; // Used for switching between test patterns TPS4 and CP2520
uint32_t allow_edp_hotplug_detection;
bool clamp_min_dcfclk;
uint64_t vblank_alignment_dto_params;
@@ -408,6 +409,7 @@ struct dc_config {
bool use_default_clock_table;
bool force_bios_enable_lttpr;
uint8_t force_bios_fixed_vs;
+ int sdpif_request_limit_words_per_umc;
};
@@ -457,15 +459,15 @@ enum pipe_split_policy {
MPC_SPLIT_DYNAMIC = 0,
/**
- * @MPC_SPLIT_DYNAMIC: Avoid pipe split, which means that DC will not
+ * @MPC_SPLIT_AVOID: Avoid pipe split, which means that DC will not
* try any sort of split optimization.
*/
MPC_SPLIT_AVOID = 1,
/**
- * @MPC_SPLIT_DYNAMIC: With this option, DC will only try to optimize
- * the pipe utilization when using a single display; if the user
- * connects to a second display, DC will avoid pipe split.
+ * @MPC_SPLIT_AVOID_MULT_DISP: With this option, DC will only try to
+ * optimize the pipe utilization when using a single display; if the
+ * user connects to a second display, DC will avoid pipe split.
*/
MPC_SPLIT_AVOID_MULT_DISP = 2,
};
@@ -491,12 +493,17 @@ enum dcn_pwr_state {
enum dcn_zstate_support_state {
DCN_ZSTATE_SUPPORT_UNKNOWN,
DCN_ZSTATE_SUPPORT_ALLOW,
+ DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY,
+ DCN_ZSTATE_SUPPORT_ALLOW_Z8_Z10_ONLY,
DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY,
DCN_ZSTATE_SUPPORT_DISALLOW,
};
-/*
- * For any clocks that may differ per pipe
- * only the max is stored in this structure
+
+/**
+ * struct dc_clocks - DC pipe clocks
+ *
+ * For any clocks that may differ per pipe only the max is stored in this
+ * structure
*/
struct dc_clocks {
int dispclk_khz;
@@ -523,6 +530,16 @@ struct dc_clocks {
bool prev_p_state_change_support;
bool fclk_prev_p_state_change_support;
int num_ways;
+
+ /*
+ * @fw_based_mclk_switching
+ *
+ * DC has a mechanism that leverage the variable refresh rate to switch
+ * memory clock in cases that we have a large latency to achieve the
+ * memory clock change and a short vblank window. DC has some
+ * requirements to enable this feature, and this field describes if the
+ * system support or not such a feature.
+ */
bool fw_based_mclk_switching;
bool fw_based_mclk_switching_shut_down;
int prev_num_ways;
@@ -764,7 +781,6 @@ struct dc_debug_options {
bool disable_mem_low_power;
bool pstate_enabled;
bool disable_dmcu;
- bool disable_psr;
bool force_abm_enable;
bool disable_stereo_support;
bool vsr_support;
@@ -828,6 +844,7 @@ struct dc_debug_options {
int crb_alloc_policy_min_disp_count;
bool disable_z10;
bool enable_z9_disable_interface;
+ bool psr_skip_crtc_disable;
union dpia_debug_options dpia_debug;
bool disable_fixed_vs_aux_timeout_wa;
bool force_disable_subvp;
@@ -836,6 +853,7 @@ struct dc_debug_options {
unsigned int force_subvp_num_ways;
unsigned int force_mall_ss_num_ways;
bool alloc_extra_way_for_cursor;
+ uint32_t subvp_extra_lines;
bool force_usr_allow;
/* uses value at boot and disables switch */
bool disable_dtb_ref_clk_switch;
@@ -990,9 +1008,7 @@ void dc_init_callbacks(struct dc *dc,
void dc_deinit_callbacks(struct dc *dc);
void dc_destroy(struct dc **dc);
-/*******************************************************************************
- * Surface Interfaces
- ******************************************************************************/
+/* Surface Interfaces */
enum {
TRANSFER_FUNC_POINTS = 1025
@@ -1271,12 +1287,23 @@ void dc_post_update_surfaces_to_stream(
#include "dc_stream.h"
-/*
- * Structure to store surface/stream associations for validation
+/**
+ * struct dc_validation_set - Struct to store surface/stream associations for validation
*/
struct dc_validation_set {
+ /**
+ * @stream: Stream state properties
+ */
struct dc_stream_state *stream;
+
+ /**
+ * @plane_state: Surface state
+ */
struct dc_plane_state *plane_states[MAX_SURFACES];
+
+ /**
+ * @plane_count: Total of active planes
+ */
uint8_t plane_count;
};
@@ -1288,6 +1315,12 @@ enum dc_status dc_validate_plane(struct dc *dc, const struct dc_plane_state *pla
void get_clock_requirements_for_state(struct dc_state *state, struct AsicStateEx *info);
+enum dc_status dc_validate_with_context(struct dc *dc,
+ const struct dc_validation_set set[],
+ int set_count,
+ struct dc_state *context,
+ bool fast_validate);
+
bool dc_set_generic_gpio_for_stereo(bool enable,
struct gpio_service *gpio_service);
@@ -1323,15 +1356,12 @@ void dc_resource_state_destruct(struct dc_state *context);
bool dc_resource_is_dsc_encoding_supported(const struct dc *dc);
-/*
- * TODO update to make it about validation sets
- * Set up streams and links associated to drive sinks
- * The streams parameter is an absolute set of all active streams.
- *
- * After this call:
- * Phy, Encoder, Timing Generator are programmed and enabled.
- * New streams are enabled with blank stream; no memory read.
- */
+enum dc_status dc_commit_streams(struct dc *dc,
+ struct dc_stream_state *streams[],
+ uint8_t stream_count);
+
+/* TODO: When the transition to the new commit sequence is done, remove this
+ * function in favor of dc_commit_streams. */
bool dc_commit_state(struct dc *dc, struct dc_state *context);
struct dc_state *dc_create_state(struct dc *dc);
@@ -1339,9 +1369,7 @@ struct dc_state *dc_copy_state(struct dc_state *src_ctx);
void dc_retain_state(struct dc_state *context);
void dc_release_state(struct dc_state *context);
-/*******************************************************************************
- * Link Interfaces
- ******************************************************************************/
+/* Link Interfaces */
struct dpcd_caps {
union dpcd_rev dpcd_rev;
@@ -1443,9 +1471,7 @@ struct hdcp_caps {
uint32_t dc_get_opp_for_plane(struct dc *dc, struct dc_plane_state *plane);
-/*******************************************************************************
- * Sink Interfaces - A sink corresponds to a display output device
- ******************************************************************************/
+/* Sink Interfaces - A sink corresponds to a display output device */
struct dc_container_id {
// 128bit GUID in binary form
@@ -1528,9 +1554,7 @@ struct dc_cursor {
};
-/*******************************************************************************
- * Interrupt interfaces
- ******************************************************************************/
+/* Interrupt interfaces */
enum dc_irq_source dc_interrupt_to_irq_source(
struct dc *dc,
uint32_t src_id,
@@ -1542,9 +1566,7 @@ enum dc_irq_source dc_get_hpd_irq_source_at_index(
void dc_notify_vsync_int_state(struct dc *dc, struct dc_stream_state *stream, bool enable);
-/*******************************************************************************
- * Power Interfaces
- ******************************************************************************/
+/* Power Interfaces */
void dc_set_power_state(
struct dc *dc,
@@ -1617,14 +1639,10 @@ 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);
-/*******************************************************************************
- * DSC Interfaces
- ******************************************************************************/
+/* DSC Interfaces */
#include "dc_dsc.h"
-/*******************************************************************************
- * Disable acc mode Interfaces
- ******************************************************************************/
+/* Disable acc mode Interfaces */
void dc_disable_accelerated_mode(struct dc *dc);
#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 0541e87e4f38..6ccf477d1c4d 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_dmub_srv.c
@@ -423,25 +423,20 @@ void dc_dmub_srv_get_visual_confirm_color_cmd(struct dc *dc, struct pipe_ctx *pi
#ifdef CONFIG_DRM_AMD_DC_DCN
/**
- * ***********************************************************************************************
- * populate_subvp_cmd_drr_info: Helper to populate DRR pipe info for the DMCUB subvp command
+ * populate_subvp_cmd_drr_info - Helper to populate DRR pipe info for the DMCUB subvp command
*
- * Populate the DMCUB SubVP command with DRR pipe info. All the information required for calculating
- * the SubVP + DRR microschedule is populated here.
+ * @dc: [in] current dc state
+ * @subvp_pipe: [in] pipe_ctx for the SubVP pipe
+ * @vblank_pipe: [in] pipe_ctx for the DRR pipe
+ * @pipe_data: [in] Pipe data which stores the VBLANK/DRR info
+ *
+ * Populate the DMCUB SubVP command with DRR pipe info. All the information
+ * required for calculating the SubVP + DRR microschedule is populated here.
*
* High level algorithm:
* 1. Get timing for SubVP pipe, phantom pipe, and DRR pipe
* 2. Calculate the min and max vtotal which supports SubVP + DRR microschedule
* 3. Populate the drr_info with the min and max supported vtotal values
- *
- * @param [in] dc: current dc state
- * @param [in] subvp_pipe: pipe_ctx for the SubVP pipe
- * @param [in] vblank_pipe: pipe_ctx for the DRR pipe
- * @param [in] pipe_data: Pipe data which stores the VBLANK/DRR info
- *
- * @return: void
- *
- * ***********************************************************************************************
*/
static void populate_subvp_cmd_drr_info(struct dc *dc,
struct pipe_ctx *subvp_pipe,
@@ -482,33 +477,38 @@ static void populate_subvp_cmd_drr_info(struct dc *dc,
(((uint64_t)main_timing->pix_clk_100hz * 100)));
drr_active_us = div64_u64(((uint64_t)drr_timing->v_addressable * drr_timing->h_total * 1000000),
(((uint64_t)drr_timing->pix_clk_100hz * 100)));
- max_drr_vblank_us = div64_u64((subvp_active_us - prefetch_us - drr_active_us), 2) + drr_active_us;
- max_drr_mallregion_us = subvp_active_us - prefetch_us - mall_region_us;
+ max_drr_vblank_us = div64_u64((subvp_active_us - prefetch_us -
+ dc->caps.subvp_fw_processing_delay_us - drr_active_us), 2) + drr_active_us;
+ max_drr_mallregion_us = subvp_active_us - prefetch_us - mall_region_us - dc->caps.subvp_fw_processing_delay_us;
max_drr_supported_us = max_drr_vblank_us > max_drr_mallregion_us ? max_drr_vblank_us : max_drr_mallregion_us;
max_vtotal_supported = div64_u64(((uint64_t)drr_timing->pix_clk_100hz * 100 * max_drr_supported_us),
(((uint64_t)drr_timing->h_total * 1000000)));
+ /* When calculating the max vtotal supported for SubVP + DRR cases, add
+ * margin due to possible rounding errors (being off by 1 line in the
+ * FW calculation can incorrectly push the P-State switch to wait 1 frame
+ * longer).
+ */
+ max_vtotal_supported = max_vtotal_supported - dc->caps.subvp_drr_max_vblank_margin_us;
+
pipe_data->pipe_config.vblank_data.drr_info.min_vtotal_supported = min_vtotal_supported;
pipe_data->pipe_config.vblank_data.drr_info.max_vtotal_supported = max_vtotal_supported;
+ pipe_data->pipe_config.vblank_data.drr_info.drr_vblank_start_margin = dc->caps.subvp_drr_vblank_start_margin_us;
}
/**
- * ***********************************************************************************************
- * populate_subvp_cmd_vblank_pipe_info: Helper to populate VBLANK pipe info for the DMUB subvp command
- *
- * Populate the DMCUB SubVP command with VBLANK pipe info. All the information required to calculate
- * the microschedule for SubVP + VBLANK case is stored in the pipe_data (subvp_data and vblank_data).
- * Also check if the VBLANK pipe is a DRR display -- if it is make a call to populate drr_info.
- *
- * @param [in] dc: current dc state
- * @param [in] context: new dc state
- * @param [in] cmd: DMUB cmd to be populated with SubVP info
- * @param [in] vblank_pipe: pipe_ctx for the VBLANK pipe
- * @param [in] cmd_pipe_index: index for the pipe array in DMCUB SubVP cmd
+ * populate_subvp_cmd_vblank_pipe_info - Helper to populate VBLANK pipe info for the DMUB subvp command
*
- * @return: void
+ * @dc: [in] current dc state
+ * @context: [in] new dc state
+ * @cmd: [in] DMUB cmd to be populated with SubVP info
+ * @vblank_pipe: [in] pipe_ctx for the VBLANK pipe
+ * @cmd_pipe_index: [in] index for the pipe array in DMCUB SubVP cmd
*
- * ***********************************************************************************************
+ * Populate the DMCUB SubVP command with VBLANK pipe info. All the information
+ * required to calculate the microschedule for SubVP + VBLANK case is stored in
+ * the pipe_data (subvp_data and vblank_data). Also check if the VBLANK pipe
+ * is a DRR display -- if it is make a call to populate drr_info.
*/
static void populate_subvp_cmd_vblank_pipe_info(struct dc *dc,
struct dc_state *context,
@@ -551,22 +551,18 @@ static void populate_subvp_cmd_vblank_pipe_info(struct dc *dc,
}
/**
- * ***********************************************************************************************
- * update_subvp_prefetch_end_to_mall_start: Helper for SubVP + SubVP case
+ * update_subvp_prefetch_end_to_mall_start - Helper for SubVP + SubVP case
*
- * For SubVP + SubVP, we use a single vertical interrupt to start the microschedule for both
- * SubVP pipes. In order for this to work correctly, the MALL REGION of both SubVP pipes must
- * start at the same time. This function lengthens the prefetch end to mall start delay of the
- * SubVP pipe that has the shorter prefetch so that both MALL REGION's will start at the same time.
+ * @dc: [in] current dc state
+ * @context: [in] new dc state
+ * @cmd: [in] DMUB cmd to be populated with SubVP info
+ * @subvp_pipes: [in] Array of SubVP pipes (should always be length 2)
*
- * @param [in] dc: current dc state
- * @param [in] context: new dc state
- * @param [in] cmd: DMUB cmd to be populated with SubVP info
- * @param [in] subvp_pipes: Array of SubVP pipes (should always be length 2)
- *
- * @return: void
- *
- * ***********************************************************************************************
+ * For SubVP + SubVP, we use a single vertical interrupt to start the
+ * microschedule for both SubVP pipes. In order for this to work correctly, the
+ * MALL REGION of both SubVP pipes must start at the same time. This function
+ * lengthens the prefetch end to mall start delay of the SubVP pipe that has
+ * the shorter prefetch so that both MALL REGION's will start at the same time.
*/
static void update_subvp_prefetch_end_to_mall_start(struct dc *dc,
struct dc_state *context,
@@ -608,22 +604,17 @@ static void update_subvp_prefetch_end_to_mall_start(struct dc *dc,
}
/**
- * ***************************************************************************************
- * setup_subvp_dmub_command: Helper to populate the SubVP pipe info for the DMUB subvp command
- *
- * Populate the DMCUB SubVP command with SubVP pipe info. All the information required to
- * calculate the microschedule for the SubVP pipe is stored in the pipe_data of the DMCUB
- * SubVP command.
- *
- * @param [in] dc: current dc state
- * @param [in] context: new dc state
- * @param [in] cmd: DMUB cmd to be populated with SubVP info
- * @param [in] subvp_pipe: pipe_ctx for the SubVP pipe
- * @param [in] cmd_pipe_index: index for the pipe array in DMCUB SubVP cmd
+ * populate_subvp_cmd_pipe_info - Helper to populate the SubVP pipe info for the DMUB subvp command
*
- * @return: void
+ * @dc: [in] current dc state
+ * @context: [in] new dc state
+ * @cmd: [in] DMUB cmd to be populated with SubVP info
+ * @subvp_pipe: [in] pipe_ctx for the SubVP pipe
+ * @cmd_pipe_index: [in] index for the pipe array in DMCUB SubVP cmd
*
- * ***************************************************************************************
+ * Populate the DMCUB SubVP command with SubVP pipe info. All the information
+ * required to calculate the microschedule for the SubVP pipe is stored in the
+ * pipe_data of the DMCUB SubVP command.
*/
static void populate_subvp_cmd_pipe_info(struct dc *dc,
struct dc_state *context,
@@ -703,19 +694,14 @@ static void populate_subvp_cmd_pipe_info(struct dc *dc,
}
/**
- * ***************************************************************************************
- * dc_dmub_setup_subvp_dmub_command: Populate the DMCUB SubVP command
+ * dc_dmub_setup_subvp_dmub_command - Populate the DMCUB SubVP command
*
- * This function loops through each pipe and populates the DMUB
- * SubVP CMD info based on the pipe (e.g. SubVP, VBLANK).
+ * @dc: [in] current dc state
+ * @context: [in] new dc state
+ * @cmd: [in] DMUB cmd to be populated with SubVP info
*
- * @param [in] dc: current dc state
- * @param [in] context: new dc state
- * @param [in] cmd: DMUB cmd to be populated with SubVP info
- *
- * @return: void
- *
- * ***************************************************************************************
+ * This function loops through each pipe and populates the DMUB SubVP CMD info
+ * based on the pipe (e.g. SubVP, VBLANK).
*/
void dc_dmub_setup_subvp_dmub_command(struct dc *dc,
struct dc_state *context,
@@ -882,11 +868,59 @@ void dc_dmub_srv_log_diagnostic_data(struct dc_dmub_srv *dc_dmub_srv)
diag_data.is_cw6_enabled);
}
+static bool dc_can_pipe_disable_cursor(struct pipe_ctx *pipe_ctx)
+{
+ struct pipe_ctx *test_pipe, *split_pipe;
+ const struct scaler_data *scl_data = &pipe_ctx->plane_res.scl_data;
+ struct rect r1 = scl_data->recout, r2, r2_half;
+ int r1_r = r1.x + r1.width, r1_b = r1.y + r1.height, r2_r, r2_b;
+ int cur_layer = pipe_ctx->plane_state->layer_index;
+
+ /**
+ * Disable the cursor if there's another pipe above this with a
+ * plane that contains this pipe's viewport to prevent double cursor
+ * and incorrect scaling artifacts.
+ */
+ for (test_pipe = pipe_ctx->top_pipe; test_pipe;
+ test_pipe = test_pipe->top_pipe) {
+ // Skip invisible layer and pipe-split plane on same layer
+ if (!test_pipe->plane_state->visible || test_pipe->plane_state->layer_index == cur_layer)
+ continue;
+
+ r2 = test_pipe->plane_res.scl_data.recout;
+ r2_r = r2.x + r2.width;
+ r2_b = r2.y + r2.height;
+ split_pipe = test_pipe;
+
+ /**
+ * There is another half plane on same layer because of
+ * pipe-split, merge together per same height.
+ */
+ for (split_pipe = pipe_ctx->top_pipe; split_pipe;
+ split_pipe = split_pipe->top_pipe)
+ if (split_pipe->plane_state->layer_index == test_pipe->plane_state->layer_index) {
+ r2_half = split_pipe->plane_res.scl_data.recout;
+ r2.x = (r2_half.x < r2.x) ? r2_half.x : r2.x;
+ r2.width = r2.width + r2_half.width;
+ r2_r = r2.x + r2.width;
+ break;
+ }
+
+ if (r1.x >= r2.x && r1.y >= r2.y && r1_r <= r2_r && r1_b <= r2_b)
+ return true;
+ }
+
+ return false;
+}
+
static bool dc_dmub_should_update_cursor_data(struct pipe_ctx *pipe_ctx)
{
if (pipe_ctx->plane_state != NULL) {
if (pipe_ctx->plane_state->address.type == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
return false;
+
+ if (dc_can_pipe_disable_cursor(pipe_ctx))
+ return false;
}
if ((pipe_ctx->stream->link->psr_settings.psr_version == DC_PSR_VERSION_SU_1 ||
@@ -962,19 +996,14 @@ static void dc_build_cursor_attribute_update_payload1(
}
/**
- * ***************************************************************************************
- * dc_send_update_cursor_info_to_dmu: Populate the DMCUB Cursor update info command
- *
- * This function would store the cursor related information and pass it into dmub
+ * dc_send_update_cursor_info_to_dmu - Populate the DMCUB Cursor update info command
*
- * @param [in] pCtx: pipe context
- * @param [in] pipe_idx: pipe index
+ * @pCtx: [in] pipe context
+ * @pipe_idx: [in] pipe index
*
- * @return: void
- *
- * ***************************************************************************************
+ * This function would store the cursor related information and pass it into
+ * dmub
*/
-
void dc_send_update_cursor_info_to_dmu(
struct pipe_ctx *pCtx, uint8_t pipe_idx)
{
diff --git a/drivers/gpu/drm/amd/display/dc/dc_link.h b/drivers/gpu/drm/amd/display/dc/dc_link.h
index caf0c7af2d0b..2e18bcf6b11a 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_link.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_link.h
@@ -117,7 +117,7 @@ struct psr_settings {
* Add a struct dc_panel_config under dc_link
*/
struct dc_panel_config {
- // extra panel power sequence parameters
+ /* extra panel power sequence parameters */
struct pps {
unsigned int extra_t3_ms;
unsigned int extra_t7_ms;
@@ -127,13 +127,21 @@ struct dc_panel_config {
unsigned int extra_t12_ms;
unsigned int extra_post_OUI_ms;
} pps;
- // ABM
+ /* PSR */
+ struct psr {
+ bool disable_psr;
+ bool disallow_psrsu;
+ bool rc_disable;
+ bool rc_allow_static_screen;
+ bool rc_allow_fullscreen_VPB;
+ } psr;
+ /* ABM */
struct varib {
unsigned int varibright_feature_enable;
unsigned int def_varibright_level;
unsigned int abm_config_setting;
} varib;
- // edp DSC
+ /* edp DSC */
struct dsc {
bool disable_dsc_edp;
unsigned int force_dsc_edp_policy;
@@ -143,6 +151,20 @@ struct dc_panel_config {
bool optimize_edp_link_rate; /* eDP ILR */
} ilr;
};
+
+/*
+ * USB4 DPIA BW ALLOCATION STRUCTS
+ */
+struct dc_dpia_bw_alloc {
+ int sink_verified_bw; // The Verified BW that sink can allocated and use that has been verified already
+ int sink_allocated_bw; // The Actual Allocated BW that sink currently allocated
+ int padding_bw; // The Padding "Un-used" BW allocated by CM for padding reasons
+ int sink_max_bw; // The Max BW that sink can require/support
+ int estimated_bw; // The estimated available BW for this DPIA
+ int bw_granularity; // BW Granularity
+ bool bw_alloc_enabled; // The BW Alloc Mode Support is turned ON for all 3: DP-Tx & Dpia & CM
+};
+
/*
* A link contains one or more sinks and their connected status.
* The currently active signal type (HDMI, DP-SST, DP-MST) is also reported.
@@ -158,6 +180,14 @@ struct dc_link {
enum dc_irq_source irq_source_hpd_rx;/* aka DP Short Pulse */
bool is_hpd_filter_disabled;
bool dp_ss_off;
+
+ /**
+ * @link_state_valid:
+ *
+ * If there is no link and local sink, this variable should be set to
+ * false. Otherwise, it should be set to true; usually, the function
+ * core_link_enable_stream sets this field to true.
+ */
bool link_state_valid;
bool aux_access_disabled;
bool sync_lt_in_progress;
@@ -168,6 +198,7 @@ struct dc_link {
bool is_dig_mapping_flexible;
bool hpd_status; /* HPD status of link without physical HPD pin. */
bool is_hpd_pending; /* Indicates a new received hpd */
+ bool is_automated; /* Indicates automated testing */
bool edp_sink_present;
diff --git a/drivers/gpu/drm/amd/display/dc/dc_stream.h b/drivers/gpu/drm/amd/display/dc/dc_stream.h
index 9e6025c98db9..dfd3df1d2f7e 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_stream.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_stream.h
@@ -41,6 +41,10 @@ struct timing_sync_info {
struct dc_stream_status {
int primary_otg_inst;
int stream_enc_inst;
+
+ /**
+ * @plane_count: Total of planes attached to a single stream
+ */
int plane_count;
int audio_inst;
struct timing_sync_info timing_sync_info;
@@ -140,7 +144,7 @@ struct test_pattern {
unsigned int cust_pattern_size;
};
-#define SUBVP_DRR_MARGIN_US 500 // 500us for DRR margin (SubVP + DRR)
+#define SUBVP_DRR_MARGIN_US 600 // 600us for DRR margin (SubVP + DRR)
enum mall_stream_type {
SUBVP_NONE, // subvp not in use
@@ -156,6 +160,17 @@ struct mall_stream_config {
struct dc_stream_state *paired_stream; // master / slave stream
};
+/* Temp struct used to save and restore MALL config
+ * during validation.
+ *
+ * TODO: Move MALL config into dc_state instead of stream struct
+ * to avoid needing to save/restore.
+ */
+struct mall_temp_config {
+ struct mall_stream_config mall_stream_config[MAX_PIPES];
+ bool is_phantom_plane[MAX_PIPES];
+};
+
struct dc_stream_state {
// sink is deprecated, new code should not reference
// this pointer
@@ -197,7 +212,18 @@ struct dc_stream_state {
bool use_vsc_sdp_for_colorimetry;
bool ignore_msa_timing_param;
+ /**
+ * @allow_freesync:
+ *
+ * It say if Freesync is enabled or not.
+ */
bool allow_freesync;
+
+ /**
+ * @vrr_active_variable:
+ *
+ * It describes if VRR is in use.
+ */
bool vrr_active_variable;
bool freesync_on_desktop;
@@ -517,10 +543,10 @@ bool dc_stream_get_crtc_position(struct dc *dc,
unsigned int *nom_v_pos);
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
-bool dc_stream_forward_dmcu_crc_window(struct dc *dc, struct dc_stream_state *stream,
- struct crc_params *crc_window);
-bool dc_stream_stop_dmcu_crc_win_update(struct dc *dc,
- struct dc_stream_state *stream);
+bool dc_stream_forward_crc_window(struct dc *dc,
+ struct rect *rect,
+ struct dc_stream_state *stream,
+ bool is_stop);
#endif
bool dc_stream_configure_crc(struct dc *dc,
diff --git a/drivers/gpu/drm/amd/display/dc/dc_trace.h b/drivers/gpu/drm/amd/display/dc/dc_trace.h
index c711797e5c9e..bbec308a3a5e 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_trace.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_trace.h
@@ -40,3 +40,5 @@
#define TRACE_DCN_FPU(begin, function, line, ref_count) \
trace_dcn_fpu(begin, function, line, ref_count)
+#define TRACE_OPTC_LOCK_UNLOCK_STATE(optc, inst, lock) \
+ trace_dcn_optc_lock_unlock_state(optc, inst, lock, __func__, __LINE__)
diff --git a/drivers/gpu/drm/amd/display/dc/dc_types.h b/drivers/gpu/drm/amd/display/dc/dc_types.h
index ad9041472cca..dc78e2404b48 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_types.h
+++ b/drivers/gpu/drm/amd/display/dc/dc_types.h
@@ -993,4 +993,11 @@ struct display_endpoint_id {
enum display_endpoint_type ep_type;
};
+#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
+struct otg_phy_mux {
+ uint8_t phy_output_num;
+ uint8_t otg_output_num;
+};
+#endif
+
#endif /* DC_TYPES_H_ */
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 fbb19e253f50..d3cc5ec46956 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dce_dmcu.c
@@ -927,19 +927,20 @@ static bool dcn10_recv_edid_cea_ack(struct dmcu *dmcu, int *offset)
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
static void dcn10_forward_crc_window(struct dmcu *dmcu,
- struct crc_region *crc_win,
+ struct rect *rect,
struct otg_phy_mux *mux_mapping)
{
struct dce_dmcu *dmcu_dce = TO_DCE_DMCU(dmcu);
unsigned int dmcu_max_retry_on_wait_reg_ready = 801;
unsigned int dmcu_wait_reg_ready_interval = 100;
unsigned int crc_start = 0, crc_end = 0, otg_phy_mux = 0;
+ int x_start, y_start, x_end, y_end;
/* If microcontroller is not running, do nothing */
if (dmcu->dmcu_state != DMCU_RUNNING)
return;
- if (!crc_win)
+ if (!rect)
return;
/* waitDMCUReadyForCmd */
@@ -947,9 +948,14 @@ static void dcn10_forward_crc_window(struct dmcu *dmcu,
dmcu_wait_reg_ready_interval,
dmcu_max_retry_on_wait_reg_ready);
+ x_start = rect->x;
+ y_start = rect->y;
+ x_end = x_start + rect->width;
+ y_end = y_start + rect->height;
+
/* build up nitification data */
- crc_start = (((unsigned int) crc_win->x_start) << 16) | crc_win->y_start;
- crc_end = (((unsigned int) crc_win->x_end) << 16) | crc_win->y_end;
+ crc_start = (((unsigned int) x_start) << 16) | y_start;
+ crc_end = (((unsigned int) x_end) << 16) | y_end;
otg_phy_mux =
(((unsigned int) mux_mapping->otg_output_num) << 16) | mux_mapping->phy_output_num;
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 bec5e9f787fc..2d3201b77d6a 100644
--- a/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
+++ b/drivers/gpu/drm/amd/display/dc/dce/dmub_psr.c
@@ -399,7 +399,11 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
link->psr_settings.force_ffu_mode = 0;
copy_settings_data->force_ffu_mode = link->psr_settings.force_ffu_mode;
- if (link->fec_state == dc_link_fec_enabled &&
+ if (((link->dpcd_caps.fec_cap.bits.FEC_CAPABLE &&
+ !link->dc->debug.disable_fec) &&
+ (link->dpcd_caps.dsc_caps.dsc_basic_caps.fields.dsc_support.DSC_SUPPORT &&
+ !link->panel_config.dsc.disable_dsc_edp &&
+ link->dc->caps.edp_dsc_support)) &&
link->dpcd_caps.sink_dev_id == DP_DEVICE_ID_38EC11 &&
(!memcmp(link->dpcd_caps.sink_dev_id_str, DP_SINK_DEVICE_STR_ID_1,
sizeof(DP_SINK_DEVICE_STR_ID_1)) ||
@@ -409,6 +413,11 @@ static bool dmub_psr_copy_settings(struct dmub_psr *dmub,
else
copy_settings_data->debug.bitfields.force_wakeup_by_tps3 = 0;
+ //WA for PSR1 on specific TCON, require frame delay for frame re-lock
+ copy_settings_data->relock_delay_frame_cnt = 0;
+ if (link->dpcd_caps.sink_dev_id == DP_BRANCH_DEVICE_ID_001CF8)
+ copy_settings_data->relock_delay_frame_cnt = 2;
+
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);
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 d260eaa1509e..913a1fe6b3da 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
@@ -688,16 +688,6 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx)
early_control = lane_count;
tg->funcs->set_early_control(tg, early_control);
-
- /* enable audio only within mode set */
- if (pipe_ctx->stream_res.audio != NULL) {
- if (dc_is_dp_signal(pipe_ctx->stream->signal))
- pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
- }
-
-
-
-
}
static enum bp_result link_transmitter_control(
@@ -1081,12 +1071,14 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
struct dc *dc;
struct clk_mgr *clk_mgr;
unsigned int i, num_audio = 1;
+ const struct link_hwss *link_hwss;
if (!pipe_ctx->stream)
return;
dc = pipe_ctx->stream->ctx->dc;
clk_mgr = dc->clk_mgr;
+ link_hwss = get_link_hwss(pipe_ctx->stream->link, &pipe_ctx->link_res);
if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == true)
return;
@@ -1103,56 +1095,35 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
if (num_audio >= 1 && clk_mgr->funcs->enable_pme_wa)
/*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
clk_mgr->funcs->enable_pme_wa(clk_mgr);
- /* un-mute audio */
- /* TODO: audio should be per stream rather than per link */
- if (is_dp_128b_132b_signal(pipe_ctx))
- pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->audio_mute_control(
- pipe_ctx->stream_res.hpo_dp_stream_enc, false);
- else
- pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
- pipe_ctx->stream_res.stream_enc, false);
+
+ link_hwss->enable_audio_packet(pipe_ctx);
+
if (pipe_ctx->stream_res.audio)
pipe_ctx->stream_res.audio->enabled = true;
}
-
- if (dc_is_dp_signal(pipe_ctx->stream->signal))
- dp_source_sequence_trace(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_ENABLE_AUDIO_STREAM);
}
void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx)
{
struct dc *dc;
struct clk_mgr *clk_mgr;
+ const struct link_hwss *link_hwss;
if (!pipe_ctx || !pipe_ctx->stream)
return;
dc = pipe_ctx->stream->ctx->dc;
clk_mgr = dc->clk_mgr;
+ link_hwss = get_link_hwss(pipe_ctx->stream->link, &pipe_ctx->link_res);
if (pipe_ctx->stream_res.audio && pipe_ctx->stream_res.audio->enabled == false)
return;
- if (is_dp_128b_132b_signal(pipe_ctx))
- pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->audio_mute_control(
- pipe_ctx->stream_res.hpo_dp_stream_enc, true);
- else
- pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
- pipe_ctx->stream_res.stream_enc, true);
+ link_hwss->disable_audio_packet(pipe_ctx);
+
if (pipe_ctx->stream_res.audio) {
pipe_ctx->stream_res.audio->enabled = false;
- if (dc_is_dp_signal(pipe_ctx->stream->signal))
- if (is_dp_128b_132b_signal(pipe_ctx))
- pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_disable(
- pipe_ctx->stream_res.hpo_dp_stream_enc);
- else
- pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable(
- pipe_ctx->stream_res.stream_enc);
- else
- pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable(
- pipe_ctx->stream_res.stream_enc);
-
if (clk_mgr->funcs->enable_pme_wa)
/*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
clk_mgr->funcs->enable_pme_wa(clk_mgr);
@@ -1163,9 +1134,6 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx)
* stream->stream_engine_id);
*/
}
-
- if (dc_is_dp_signal(pipe_ctx->stream->signal))
- dp_source_sequence_trace(pipe_ctx->stream->link, DPCD_SOURCE_SEQ_AFTER_DISABLE_AUDIO_STREAM);
}
void dce110_disable_stream(struct pipe_ctx *pipe_ctx)
@@ -1487,6 +1455,9 @@ static enum dc_status apply_single_controller_ctx_to_hw(
unsigned int event_triggers = 0;
struct pipe_ctx *odm_pipe = pipe_ctx->next_odm_pipe;
struct dce_hwseq *hws = dc->hwseq;
+ const struct link_hwss *link_hwss = get_link_hwss(
+ link, &pipe_ctx->link_res);
+
if (hws->funcs.disable_stream_gating) {
hws->funcs.disable_stream_gating(dc, pipe_ctx);
@@ -1497,23 +1468,8 @@ static enum dc_status apply_single_controller_ctx_to_hw(
build_audio_output(context, pipe_ctx, &audio_output);
- if (dc_is_dp_signal(pipe_ctx->stream->signal))
- if (is_dp_128b_132b_signal(pipe_ctx))
- pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_setup(
- pipe_ctx->stream_res.hpo_dp_stream_enc,
- pipe_ctx->stream_res.audio->inst,
- &pipe_ctx->stream->audio_info);
- else
- pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup(
- pipe_ctx->stream_res.stream_enc,
- pipe_ctx->stream_res.audio->inst,
- &pipe_ctx->stream->audio_info);
- else
- pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup(
- pipe_ctx->stream_res.stream_enc,
- pipe_ctx->stream_res.audio->inst,
- &pipe_ctx->stream->audio_info,
- &audio_output.crtc_info);
+ link_hwss->setup_audio_output(pipe_ctx, &audio_output,
+ pipe_ctx->stream_res.audio->inst);
pipe_ctx->stream_res.audio->funcs->az_configure(
pipe_ctx->stream_res.audio,
@@ -1605,8 +1561,13 @@ static enum dc_status apply_single_controller_ctx_to_hw(
pipe_ctx->plane_res.scl_data.lb_params.alpha_en = pipe_ctx->bottom_pipe != NULL;
- pipe_ctx->stream->link->psr_settings.psr_feature_enabled = false;
-
+ /* Phantom and main stream share the same link (because the stream
+ * is constructed with the same sink). Make sure not to override
+ * and link programming on the main.
+ */
+ if (pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) {
+ pipe_ctx->stream->link->psr_settings.psr_feature_enabled = false;
+ }
return DC_OK;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c
index fc6aa098bda0..8db9f7514466 100644
--- a/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce60/dce60_resource.c
@@ -1128,6 +1128,7 @@ struct resource_pool *dce60_create_resource_pool(
if (dce60_construct(num_virtual_links, dc, pool))
return &pool->base;
+ kfree(pool);
BREAK_TO_DEBUGGER();
return NULL;
}
@@ -1325,6 +1326,7 @@ struct resource_pool *dce61_create_resource_pool(
if (dce61_construct(num_virtual_links, dc, pool))
return &pool->base;
+ kfree(pool);
BREAK_TO_DEBUGGER();
return NULL;
}
@@ -1518,6 +1520,7 @@ struct resource_pool *dce64_create_resource_pool(
if (dce64_construct(num_virtual_links, dc, pool))
return &pool->base;
+ kfree(pool);
BREAK_TO_DEBUGGER();
return NULL;
}
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 b28025960050..5825e6f412bd 100644
--- a/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dce80/dce80_resource.c
@@ -1137,6 +1137,7 @@ struct resource_pool *dce80_create_resource_pool(
if (dce80_construct(num_virtual_links, dc, pool))
return &pool->base;
+ kfree(pool);
BREAK_TO_DEBUGGER();
return NULL;
}
@@ -1336,6 +1337,7 @@ struct resource_pool *dce81_create_resource_pool(
if (dce81_construct(num_virtual_links, dc, pool))
return &pool->base;
+ kfree(pool);
BREAK_TO_DEBUGGER();
return NULL;
}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
index e48fd044f572..ba1c0621f0f8 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubbub.h
@@ -171,6 +171,7 @@ struct dcn_hubbub_registers {
uint32_t DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B;
uint32_t DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C;
uint32_t DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D;
+ uint32_t SDPIF_REQUEST_RATE_LIMIT;
};
#define HUBBUB_REG_FIELD_LIST_DCN32(type) \
@@ -360,7 +361,8 @@ struct dcn_hubbub_registers {
type DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_C;\
type DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_C;\
type DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_Z8_D;\
- type DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D
+ type DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_Z8_D;\
+ type SDPIF_REQUEST_RATE_LIMIT
struct dcn_hubbub_shift {
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 11e4c4e46947..c8ec11839b4d 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
@@ -97,10 +97,12 @@ void dcn10_lock_all_pipes(struct dc *dc,
bool lock)
{
struct pipe_ctx *pipe_ctx;
+ struct pipe_ctx *old_pipe_ctx;
struct timing_generator *tg;
int i;
for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ old_pipe_ctx = &dc->current_state->res_ctx.pipe_ctx[i];
pipe_ctx = &context->res_ctx.pipe_ctx[i];
tg = pipe_ctx->stream_res.tg;
@@ -110,7 +112,7 @@ void dcn10_lock_all_pipes(struct dc *dc,
*/
if (pipe_ctx->top_pipe ||
!pipe_ctx->stream ||
- !pipe_ctx->plane_state ||
+ (!pipe_ctx->plane_state && !old_pipe_ctx->plane_state) ||
!tg->funcs->is_tg_enabled(tg))
continue;
@@ -867,6 +869,32 @@ static void false_optc_underflow_wa(
tg->funcs->clear_optc_underflow(tg);
}
+static int calculate_vready_offset_for_group(struct pipe_ctx *pipe)
+{
+ struct pipe_ctx *other_pipe;
+ int vready_offset = pipe->pipe_dlg_param.vready_offset;
+
+ /* Always use the largest vready_offset of all connected pipes */
+ for (other_pipe = pipe->bottom_pipe; other_pipe != NULL; other_pipe = other_pipe->bottom_pipe) {
+ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset)
+ vready_offset = other_pipe->pipe_dlg_param.vready_offset;
+ }
+ for (other_pipe = pipe->top_pipe; other_pipe != NULL; other_pipe = other_pipe->top_pipe) {
+ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset)
+ vready_offset = other_pipe->pipe_dlg_param.vready_offset;
+ }
+ for (other_pipe = pipe->next_odm_pipe; other_pipe != NULL; other_pipe = other_pipe->next_odm_pipe) {
+ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset)
+ vready_offset = other_pipe->pipe_dlg_param.vready_offset;
+ }
+ for (other_pipe = pipe->prev_odm_pipe; other_pipe != NULL; other_pipe = other_pipe->prev_odm_pipe) {
+ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset)
+ vready_offset = other_pipe->pipe_dlg_param.vready_offset;
+ }
+
+ return vready_offset;
+}
+
enum dc_status dcn10_enable_stream_timing(
struct pipe_ctx *pipe_ctx,
struct dc_state *context,
@@ -910,7 +938,7 @@ enum dc_status dcn10_enable_stream_timing(
pipe_ctx->stream_res.tg->funcs->program_timing(
pipe_ctx->stream_res.tg,
&stream->timing,
- pipe_ctx->pipe_dlg_param.vready_offset,
+ calculate_vready_offset_for_group(pipe_ctx),
pipe_ctx->pipe_dlg_param.vstartup_start,
pipe_ctx->pipe_dlg_param.vupdate_offset,
pipe_ctx->pipe_dlg_param.vupdate_width,
@@ -2188,6 +2216,12 @@ void dcn10_enable_vblanks_synchronization(
opp = grouped_pipes[i]->stream_res.opp;
tg = grouped_pipes[i]->stream_res.tg;
tg->funcs->get_otg_active_size(tg, &width, &height);
+
+ if (!tg->funcs->is_tg_enabled(tg)) {
+ DC_SYNC_INFO("Skipping timing sync on disabled OTG\n");
+ return;
+ }
+
if (opp->funcs->opp_program_dpg_dimensions)
opp->funcs->opp_program_dpg_dimensions(opp, width, 2*(height) + 1);
}
@@ -2250,6 +2284,12 @@ void dcn10_enable_timing_synchronization(
opp = grouped_pipes[i]->stream_res.opp;
tg = grouped_pipes[i]->stream_res.tg;
tg->funcs->get_otg_active_size(tg, &width, &height);
+
+ if (!tg->funcs->is_tg_enabled(tg)) {
+ DC_SYNC_INFO("Skipping timing sync on disabled OTG\n");
+ return;
+ }
+
if (opp->funcs->opp_program_dpg_dimensions)
opp->funcs->opp_program_dpg_dimensions(opp, width, 2*(height) + 1);
}
@@ -2900,7 +2940,7 @@ void dcn10_program_pipe(
pipe_ctx->stream_res.tg->funcs->program_global_sync(
pipe_ctx->stream_res.tg,
- pipe_ctx->pipe_dlg_param.vready_offset,
+ calculate_vready_offset_for_group(pipe_ctx),
pipe_ctx->pipe_dlg_param.vstartup_start,
pipe_ctx->pipe_dlg_param.vupdate_offset,
pipe_ctx->pipe_dlg_param.vupdate_width);
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 33d780218790..c9e53dc49c92 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c
@@ -27,6 +27,7 @@
#include "reg_helper.h"
#include "dcn10_optc.h"
#include "dc.h"
+#include "dc_trace.h"
#define REG(reg)\
optc1->tg_regs->reg
@@ -657,6 +658,8 @@ void optc1_lock(struct timing_generator *optc)
REG_WAIT(OTG_MASTER_UPDATE_LOCK,
UPDATE_LOCK_STATUS, 1,
1, 10);
+
+ TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true);
}
void optc1_unlock(struct timing_generator *optc)
@@ -665,6 +668,8 @@ void optc1_unlock(struct timing_generator *optc)
REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
OTG_MASTER_UPDATE_LOCK, 0);
+
+ TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, false);
}
void optc1_get_position(struct timing_generator *optc,
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 56d30baf12df..6bfac8088ab0 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
@@ -1295,47 +1295,6 @@ static uint32_t read_pipe_fuses(struct dc_context *ctx)
return value;
}
-/*
- * Some architectures don't support soft-float (e.g. aarch64), on those
- * this function has to be called with hardfloat enabled, make sure not
- * to inline it so whatever fp stuff is done stays inside
- */
-static noinline void dcn10_resource_construct_fp(
- struct dc *dc)
-{
- if (dc->ctx->dce_version == DCN_VERSION_1_01) {
- struct dcn_soc_bounding_box *dcn_soc = dc->dcn_soc;
- struct dcn_ip_params *dcn_ip = dc->dcn_ip;
- struct display_mode_lib *dml = &dc->dml;
-
- dml->ip.max_num_dpp = 3;
- /* TODO how to handle 23.84? */
- dcn_soc->dram_clock_change_latency = 23;
- dcn_ip->max_num_dpp = 3;
- }
- if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) {
- dc->dcn_soc->urgent_latency = 3;
- dc->debug.disable_dmcu = true;
- dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 41.60f;
- }
-
-
- dc->dcn_soc->number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width;
- ASSERT(dc->dcn_soc->number_of_channels < 3);
- if (dc->dcn_soc->number_of_channels == 0)/*old sbios bug*/
- dc->dcn_soc->number_of_channels = 2;
-
- if (dc->dcn_soc->number_of_channels == 1) {
- dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 19.2f;
- dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 = 17.066f;
- dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = 14.933f;
- dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 = 12.8f;
- if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) {
- dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 20.80f;
- }
- }
-}
-
static bool verify_clock_values(struct dm_pp_clock_levels_with_voltage *clks)
{
int i;
@@ -1510,8 +1469,9 @@ static bool dcn10_resource_construct(
memcpy(dc->dcn_ip, &dcn10_ip_defaults, sizeof(dcn10_ip_defaults));
memcpy(dc->dcn_soc, &dcn10_soc_defaults, sizeof(dcn10_soc_defaults));
- /* Other architectures we build for build this with soft-float */
+ DC_FP_START();
dcn10_resource_construct_fp(dc);
+ DC_FP_END();
if (!dc->config.is_vmin_only_asic)
if (ASICREV_IS_RAVEN2(dc->ctx->asic_id.hw_internal_rev))
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb.h
index a85ed228dfc2..a9dd9ae23ec9 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dwb.h
@@ -27,204 +27,177 @@
#define TO_DCN20_DWBC(dwbc_base) \
container_of(dwbc_base, struct dcn20_dwbc, base)
-/* DCN */
-#define BASE_INNER(seg) \
- DCE_BASE__INST0_SEG ## seg
-
-#define BASE(seg) \
- BASE_INNER(seg)
-
-#define SR(reg_name)\
- .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \
- mm ## reg_name
-
-#define SRI(reg_name, block, id)\
- .reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
- mm ## block ## id ## _ ## reg_name
-
-#define SRI2(reg_name, block, id)\
- .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \
- mm ## reg_name
-
-#define SRII(reg_name, block, id)\
- .reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
- mm ## block ## id ## _ ## reg_name
-
-#define SF(reg_name, field_name, post_fix)\
- .field_name = reg_name ## __ ## field_name ## post_fix
-
-
#define DWBC_COMMON_REG_LIST_DCN2_0(inst) \
- SRI2(WB_ENABLE, CNV, inst),\
- SRI2(WB_EC_CONFIG, CNV, inst),\
- SRI2(CNV_MODE, CNV, inst),\
- SRI2(CNV_WINDOW_START, CNV, inst),\
- SRI2(CNV_WINDOW_SIZE, CNV, inst),\
- SRI2(CNV_UPDATE, CNV, inst),\
- SRI2(CNV_SOURCE_SIZE, CNV, inst),\
- SRI2(CNV_TEST_CNTL, CNV, inst),\
- SRI2(CNV_TEST_CRC_RED, CNV, inst),\
- SRI2(CNV_TEST_CRC_GREEN, CNV, inst),\
- SRI2(CNV_TEST_CRC_BLUE, CNV, inst),\
- SRI2(WBSCL_COEF_RAM_SELECT, WBSCL, inst),\
- SRI2(WBSCL_COEF_RAM_TAP_DATA, WBSCL, inst),\
- SRI2(WBSCL_MODE, WBSCL, inst),\
- SRI2(WBSCL_TAP_CONTROL, WBSCL, inst),\
- SRI2(WBSCL_DEST_SIZE, WBSCL, inst),\
- SRI2(WBSCL_HORZ_FILTER_SCALE_RATIO, WBSCL, inst),\
- SRI2(WBSCL_HORZ_FILTER_INIT_Y_RGB, WBSCL, inst),\
- SRI2(WBSCL_HORZ_FILTER_INIT_CBCR, WBSCL, inst),\
- SRI2(WBSCL_VERT_FILTER_SCALE_RATIO, WBSCL, inst),\
- SRI2(WBSCL_VERT_FILTER_INIT_Y_RGB, WBSCL, inst),\
- SRI2(WBSCL_VERT_FILTER_INIT_CBCR, WBSCL, inst),\
- SRI2(WBSCL_ROUND_OFFSET, WBSCL, inst),\
- SRI2(WBSCL_OVERFLOW_STATUS, WBSCL, inst),\
- SRI2(WBSCL_COEF_RAM_CONFLICT_STATUS, WBSCL, inst),\
- SRI2(WBSCL_TEST_CNTL, WBSCL, inst),\
- SRI2(WBSCL_TEST_CRC_RED, WBSCL, inst),\
- SRI2(WBSCL_TEST_CRC_GREEN, WBSCL, inst),\
- SRI2(WBSCL_TEST_CRC_BLUE, WBSCL, inst),\
- SRI2(WBSCL_BACKPRESSURE_CNT_EN, WBSCL, inst),\
- SRI2(WB_MCIF_BACKPRESSURE_CNT, WBSCL, inst),\
- SRI2(WBSCL_CLAMP_Y_RGB, WBSCL, inst),\
- SRI2(WBSCL_CLAMP_CBCR, WBSCL, inst),\
- SRI2(WBSCL_OUTSIDE_PIX_STRATEGY, WBSCL, inst),\
- SRI2(WBSCL_OUTSIDE_PIX_STRATEGY_CBCR, WBSCL, inst),\
- SRI2(WBSCL_DEBUG, WBSCL, inst),\
- SRI2(WBSCL_TEST_DEBUG_INDEX, WBSCL, inst),\
- SRI2(WBSCL_TEST_DEBUG_DATA, WBSCL, inst),\
- SRI2(WB_DEBUG_CTRL, CNV, inst),\
- SRI2(WB_DBG_MODE, CNV, inst),\
- SRI2(WB_HW_DEBUG, CNV, inst),\
- SRI2(CNV_TEST_DEBUG_INDEX, CNV, inst),\
- SRI2(CNV_TEST_DEBUG_DATA, CNV, inst),\
- SRI2(WB_SOFT_RESET, CNV, inst),\
- SRI2(WB_WARM_UP_MODE_CTL1, CNV, inst),\
- SRI2(WB_WARM_UP_MODE_CTL2, CNV, inst)
+ SRI2_DWB(WB_ENABLE, CNV, inst),\
+ SRI2_DWB(WB_EC_CONFIG, CNV, inst),\
+ SRI2_DWB(CNV_MODE, CNV, inst),\
+ SRI2_DWB(CNV_WINDOW_START, CNV, inst),\
+ SRI2_DWB(CNV_WINDOW_SIZE, CNV, inst),\
+ SRI2_DWB(CNV_UPDATE, CNV, inst),\
+ SRI2_DWB(CNV_SOURCE_SIZE, CNV, inst),\
+ SRI2_DWB(CNV_TEST_CNTL, CNV, inst),\
+ SRI2_DWB(CNV_TEST_CRC_RED, CNV, inst),\
+ SRI2_DWB(CNV_TEST_CRC_GREEN, CNV, inst),\
+ SRI2_DWB(CNV_TEST_CRC_BLUE, CNV, inst),\
+ SRI2_DWB(WBSCL_COEF_RAM_SELECT, WBSCL, inst),\
+ SRI2_DWB(WBSCL_COEF_RAM_TAP_DATA, WBSCL, inst),\
+ SRI2_DWB(WBSCL_MODE, WBSCL, inst),\
+ SRI2_DWB(WBSCL_TAP_CONTROL, WBSCL, inst),\
+ SRI2_DWB(WBSCL_DEST_SIZE, WBSCL, inst),\
+ SRI2_DWB(WBSCL_HORZ_FILTER_SCALE_RATIO, WBSCL, inst),\
+ SRI2_DWB(WBSCL_HORZ_FILTER_INIT_Y_RGB, WBSCL, inst),\
+ SRI2_DWB(WBSCL_HORZ_FILTER_INIT_CBCR, WBSCL, inst),\
+ SRI2_DWB(WBSCL_VERT_FILTER_SCALE_RATIO, WBSCL, inst),\
+ SRI2_DWB(WBSCL_VERT_FILTER_INIT_Y_RGB, WBSCL, inst),\
+ SRI2_DWB(WBSCL_VERT_FILTER_INIT_CBCR, WBSCL, inst),\
+ SRI2_DWB(WBSCL_ROUND_OFFSET, WBSCL, inst),\
+ SRI2_DWB(WBSCL_OVERFLOW_STATUS, WBSCL, inst),\
+ SRI2_DWB(WBSCL_COEF_RAM_CONFLICT_STATUS, WBSCL, inst),\
+ SRI2_DWB(WBSCL_TEST_CNTL, WBSCL, inst),\
+ SRI2_DWB(WBSCL_TEST_CRC_RED, WBSCL, inst),\
+ SRI2_DWB(WBSCL_TEST_CRC_GREEN, WBSCL, inst),\
+ SRI2_DWB(WBSCL_TEST_CRC_BLUE, WBSCL, inst),\
+ SRI2_DWB(WBSCL_BACKPRESSURE_CNT_EN, WBSCL, inst),\
+ SRI2_DWB(WB_MCIF_BACKPRESSURE_CNT, WBSCL, inst),\
+ SRI2_DWB(WBSCL_CLAMP_Y_RGB, WBSCL, inst),\
+ SRI2_DWB(WBSCL_CLAMP_CBCR, WBSCL, inst),\
+ SRI2_DWB(WBSCL_OUTSIDE_PIX_STRATEGY, WBSCL, inst),\
+ SRI2_DWB(WBSCL_OUTSIDE_PIX_STRATEGY_CBCR, WBSCL, inst),\
+ SRI2_DWB(WBSCL_DEBUG, WBSCL, inst),\
+ SRI2_DWB(WBSCL_TEST_DEBUG_INDEX, WBSCL, inst),\
+ SRI2_DWB(WBSCL_TEST_DEBUG_DATA, WBSCL, inst),\
+ SRI2_DWB(WB_DEBUG_CTRL, CNV, inst),\
+ SRI2_DWB(WB_DBG_MODE, CNV, inst),\
+ SRI2_DWB(WB_HW_DEBUG, CNV, inst),\
+ SRI2_DWB(CNV_TEST_DEBUG_INDEX, CNV, inst),\
+ SRI2_DWB(CNV_TEST_DEBUG_DATA, CNV, inst),\
+ SRI2_DWB(WB_SOFT_RESET, CNV, inst),\
+ SRI2_DWB(WB_WARM_UP_MODE_CTL1, CNV, inst),\
+ SRI2_DWB(WB_WARM_UP_MODE_CTL2, CNV, inst)
#define DWBC_COMMON_MASK_SH_LIST_DCN2_0(mask_sh) \
- SF(WB_ENABLE, WB_ENABLE, mask_sh),\
- SF(WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, mask_sh),\
- SF(WB_EC_CONFIG, DISPCLK_G_WB_GATE_DIS, mask_sh),\
- SF(WB_EC_CONFIG, DISPCLK_G_WBSCL_GATE_DIS, mask_sh),\
- SF(WB_EC_CONFIG, WB_TEST_CLK_SEL, mask_sh),\
- SF(WB_EC_CONFIG, WB_LB_LS_DIS, mask_sh),\
- SF(WB_EC_CONFIG, WB_LB_SD_DIS, mask_sh),\
- SF(WB_EC_CONFIG, WB_LUT_LS_DIS, mask_sh),\
- SF(WB_EC_CONFIG, WBSCL_LB_MEM_PWR_MODE_SEL, mask_sh),\
- SF(WB_EC_CONFIG, WBSCL_LB_MEM_PWR_DIS, mask_sh),\
- SF(WB_EC_CONFIG, WBSCL_LB_MEM_PWR_FORCE, mask_sh),\
- SF(WB_EC_CONFIG, WBSCL_LB_MEM_PWR_STATE, mask_sh),\
- SF(WB_EC_CONFIG, WB_RAM_PW_SAVE_MODE, mask_sh),\
- SF(WB_EC_CONFIG, WBSCL_LUT_MEM_PWR_STATE, mask_sh),\
- SF(CNV_MODE, CNV_OUT_BPC, mask_sh),\
- SF(CNV_MODE, CNV_FRAME_CAPTURE_RATE, mask_sh),\
- SF(CNV_MODE, CNV_WINDOW_CROP_EN, mask_sh),\
- SF(CNV_MODE, CNV_STEREO_TYPE, mask_sh),\
- SF(CNV_MODE, CNV_INTERLACED_MODE, mask_sh),\
- SF(CNV_MODE, CNV_EYE_SELECTION, mask_sh),\
- SF(CNV_MODE, CNV_STEREO_POLARITY, mask_sh),\
- SF(CNV_MODE, CNV_INTERLACED_FIELD_ORDER, mask_sh),\
- SF(CNV_MODE, CNV_STEREO_SPLIT, mask_sh),\
- SF(CNV_MODE, CNV_NEW_CONTENT, mask_sh),\
- SF(CNV_MODE, CNV_FRAME_CAPTURE_EN_CURRENT, mask_sh),\
- SF(CNV_MODE, CNV_FRAME_CAPTURE_EN, mask_sh),\
- SF(CNV_WINDOW_START, CNV_WINDOW_START_X, mask_sh),\
- SF(CNV_WINDOW_START, CNV_WINDOW_START_Y, mask_sh),\
- SF(CNV_WINDOW_SIZE, CNV_WINDOW_WIDTH, mask_sh),\
- SF(CNV_WINDOW_SIZE, CNV_WINDOW_HEIGHT, mask_sh),\
- SF(CNV_UPDATE, CNV_UPDATE_PENDING, mask_sh),\
- SF(CNV_UPDATE, CNV_UPDATE_TAKEN, mask_sh),\
- SF(CNV_UPDATE, CNV_UPDATE_LOCK, mask_sh),\
- SF(CNV_SOURCE_SIZE, CNV_SOURCE_WIDTH, mask_sh),\
- SF(CNV_SOURCE_SIZE, CNV_SOURCE_HEIGHT, mask_sh),\
- SF(CNV_TEST_CNTL, CNV_TEST_CRC_EN, mask_sh),\
- SF(CNV_TEST_CNTL, CNV_TEST_CRC_CONT_EN, mask_sh),\
- SF(CNV_TEST_CRC_RED, CNV_TEST_CRC_RED_MASK, mask_sh),\
- SF(CNV_TEST_CRC_RED, CNV_TEST_CRC_SIG_RED, mask_sh),\
- SF(CNV_TEST_CRC_GREEN, CNV_TEST_CRC_GREEN_MASK, mask_sh),\
- SF(CNV_TEST_CRC_GREEN, CNV_TEST_CRC_SIG_GREEN, mask_sh),\
- SF(CNV_TEST_CRC_BLUE, CNV_TEST_CRC_BLUE_MASK, mask_sh),\
- SF(CNV_TEST_CRC_BLUE, CNV_TEST_CRC_SIG_BLUE, mask_sh),\
- SF(WB_DEBUG_CTRL, WB_DEBUG_EN, mask_sh),\
- SF(WB_DEBUG_CTRL, WB_DEBUG_SEL, mask_sh),\
- SF(WB_DBG_MODE, WB_DBG_MODE_EN, mask_sh),\
- SF(WB_DBG_MODE, WB_DBG_DIN_FMT, mask_sh),\
- SF(WB_DBG_MODE, WB_DBG_36MODE, mask_sh),\
- SF(WB_DBG_MODE, WB_DBG_CMAP, mask_sh),\
- SF(WB_DBG_MODE, WB_DBG_PXLRATE_ERROR, mask_sh),\
- SF(WB_DBG_MODE, WB_DBG_SOURCE_WIDTH, mask_sh),\
- SF(WB_HW_DEBUG, WB_HW_DEBUG, mask_sh),\
- SF(WB_SOFT_RESET, WB_SOFT_RESET, mask_sh),\
- SF(CNV_TEST_DEBUG_INDEX, CNV_TEST_DEBUG_INDEX, mask_sh),\
- SF(CNV_TEST_DEBUG_INDEX, CNV_TEST_DEBUG_WRITE_EN, mask_sh),\
- SF(CNV_TEST_DEBUG_DATA, CNV_TEST_DEBUG_DATA, mask_sh),\
- SF(WBSCL_COEF_RAM_SELECT, WBSCL_COEF_RAM_TAP_PAIR_IDX, mask_sh),\
- SF(WBSCL_COEF_RAM_SELECT, WBSCL_COEF_RAM_PHASE, mask_sh),\
- SF(WBSCL_COEF_RAM_SELECT, WBSCL_COEF_RAM_FILTER_TYPE, mask_sh),\
- SF(WBSCL_COEF_RAM_TAP_DATA, WBSCL_COEF_RAM_EVEN_TAP_COEF, mask_sh),\
- SF(WBSCL_COEF_RAM_TAP_DATA, WBSCL_COEF_RAM_EVEN_TAP_COEF_EN, mask_sh),\
- SF(WBSCL_COEF_RAM_TAP_DATA, WBSCL_COEF_RAM_ODD_TAP_COEF, mask_sh),\
- SF(WBSCL_COEF_RAM_TAP_DATA, WBSCL_COEF_RAM_ODD_TAP_COEF_EN, mask_sh),\
- SF(WBSCL_MODE, WBSCL_MODE, mask_sh),\
- SF(WBSCL_MODE, WBSCL_OUT_BIT_DEPTH, mask_sh),\
- SF(WBSCL_TAP_CONTROL, WBSCL_V_NUM_OF_TAPS_Y_RGB, mask_sh),\
- SF(WBSCL_TAP_CONTROL, WBSCL_V_NUM_OF_TAPS_CBCR, mask_sh),\
- SF(WBSCL_TAP_CONTROL, WBSCL_H_NUM_OF_TAPS_Y_RGB, mask_sh),\
- SF(WBSCL_TAP_CONTROL, WBSCL_H_NUM_OF_TAPS_CBCR, mask_sh),\
- SF(WBSCL_DEST_SIZE, WBSCL_DEST_HEIGHT, mask_sh),\
- SF(WBSCL_DEST_SIZE, WBSCL_DEST_WIDTH, mask_sh),\
- SF(WBSCL_HORZ_FILTER_SCALE_RATIO, WBSCL_H_SCALE_RATIO, mask_sh),\
- SF(WBSCL_HORZ_FILTER_INIT_Y_RGB, WBSCL_H_INIT_FRAC_Y_RGB, mask_sh),\
- SF(WBSCL_HORZ_FILTER_INIT_Y_RGB, WBSCL_H_INIT_INT_Y_RGB, mask_sh),\
- SF(WBSCL_HORZ_FILTER_INIT_CBCR, WBSCL_H_INIT_FRAC_CBCR, mask_sh),\
- SF(WBSCL_HORZ_FILTER_INIT_CBCR, WBSCL_H_INIT_INT_CBCR, mask_sh),\
- SF(WBSCL_VERT_FILTER_SCALE_RATIO, WBSCL_V_SCALE_RATIO, mask_sh),\
- SF(WBSCL_VERT_FILTER_INIT_Y_RGB, WBSCL_V_INIT_FRAC_Y_RGB, mask_sh),\
- SF(WBSCL_VERT_FILTER_INIT_Y_RGB, WBSCL_V_INIT_INT_Y_RGB, mask_sh),\
- SF(WBSCL_VERT_FILTER_INIT_CBCR, WBSCL_V_INIT_FRAC_CBCR, mask_sh),\
- SF(WBSCL_VERT_FILTER_INIT_CBCR, WBSCL_V_INIT_INT_CBCR, mask_sh),\
- SF(WBSCL_ROUND_OFFSET, WBSCL_ROUND_OFFSET_Y_RGB, mask_sh),\
- SF(WBSCL_ROUND_OFFSET, WBSCL_ROUND_OFFSET_CBCR, mask_sh),\
- SF(WBSCL_OVERFLOW_STATUS, WBSCL_DATA_OVERFLOW_FLAG, mask_sh),\
- SF(WBSCL_OVERFLOW_STATUS, WBSCL_DATA_OVERFLOW_ACK, mask_sh),\
- SF(WBSCL_OVERFLOW_STATUS, WBSCL_DATA_OVERFLOW_MASK, mask_sh),\
- SF(WBSCL_OVERFLOW_STATUS, WBSCL_DATA_OVERFLOW_INT_STATUS, mask_sh),\
- SF(WBSCL_OVERFLOW_STATUS, WBSCL_DATA_OVERFLOW_INT_TYPE, mask_sh),\
- SF(WBSCL_COEF_RAM_CONFLICT_STATUS, WBSCL_HOST_CONFLICT_FLAG, mask_sh),\
- SF(WBSCL_COEF_RAM_CONFLICT_STATUS, WBSCL_HOST_CONFLICT_ACK, mask_sh),\
- SF(WBSCL_COEF_RAM_CONFLICT_STATUS, WBSCL_HOST_CONFLICT_MASK, mask_sh),\
- SF(WBSCL_COEF_RAM_CONFLICT_STATUS, WBSCL_HOST_CONFLICT_INT_STATUS, mask_sh),\
- SF(WBSCL_COEF_RAM_CONFLICT_STATUS, WBSCL_HOST_CONFLICT_INT_TYPE, mask_sh),\
- SF(WBSCL_TEST_CNTL, WBSCL_TEST_CRC_EN, mask_sh),\
- SF(WBSCL_TEST_CNTL, WBSCL_TEST_CRC_CONT_EN, mask_sh),\
- SF(WBSCL_TEST_CRC_RED, WBSCL_TEST_CRC_RED_MASK, mask_sh),\
- SF(WBSCL_TEST_CRC_RED, WBSCL_TEST_CRC_SIG_RED, mask_sh),\
- SF(WBSCL_TEST_CRC_GREEN, WBSCL_TEST_CRC_GREEN_MASK, mask_sh),\
- SF(WBSCL_TEST_CRC_GREEN, WBSCL_TEST_CRC_SIG_GREEN, mask_sh),\
- SF(WBSCL_TEST_CRC_BLUE, WBSCL_TEST_CRC_BLUE_MASK, mask_sh),\
- SF(WBSCL_TEST_CRC_BLUE, WBSCL_TEST_CRC_SIG_BLUE, mask_sh),\
- SF(WBSCL_BACKPRESSURE_CNT_EN, WBSCL_BACKPRESSURE_CNT_EN, mask_sh),\
- SF(WB_MCIF_BACKPRESSURE_CNT, WB_MCIF_Y_MAX_BACKPRESSURE, mask_sh),\
- SF(WB_MCIF_BACKPRESSURE_CNT, WB_MCIF_C_MAX_BACKPRESSURE, mask_sh),\
- SF(WBSCL_CLAMP_Y_RGB, WBSCL_CLAMP_UPPER_Y_RGB, mask_sh),\
- SF(WBSCL_CLAMP_Y_RGB, WBSCL_CLAMP_LOWER_Y_RGB, mask_sh),\
- SF(WBSCL_CLAMP_CBCR, WBSCL_CLAMP_UPPER_CBCR, mask_sh),\
- SF(WBSCL_CLAMP_CBCR, WBSCL_CLAMP_LOWER_CBCR, mask_sh),\
- SF(WBSCL_OUTSIDE_PIX_STRATEGY, WBSCL_OUTSIDE_PIX_STRATEGY, mask_sh),\
- SF(WBSCL_OUTSIDE_PIX_STRATEGY, WBSCL_BLACK_COLOR_G_Y, mask_sh),\
- SF(WBSCL_OUTSIDE_PIX_STRATEGY_CBCR, WBSCL_BLACK_COLOR_B_CB, mask_sh),\
- SF(WBSCL_OUTSIDE_PIX_STRATEGY_CBCR, WBSCL_BLACK_COLOR_R_CR, mask_sh),\
- SF(WBSCL_DEBUG, WBSCL_DEBUG, mask_sh),\
- SF(WBSCL_TEST_DEBUG_INDEX, WBSCL_TEST_DEBUG_INDEX, mask_sh),\
- SF(WBSCL_TEST_DEBUG_INDEX, WBSCL_TEST_DEBUG_WRITE_EN, mask_sh),\
- SF(WBSCL_TEST_DEBUG_DATA, WBSCL_TEST_DEBUG_DATA, mask_sh),\
- SF(WB_WARM_UP_MODE_CTL1, WIDTH_WARMUP, mask_sh),\
- SF(WB_WARM_UP_MODE_CTL1, HEIGHT_WARMUP, mask_sh),\
- SF(WB_WARM_UP_MODE_CTL1, GMC_WARM_UP_ENABLE, mask_sh),\
- SF(WB_WARM_UP_MODE_CTL2, DATA_VALUE_WARMUP, mask_sh),\
- SF(WB_WARM_UP_MODE_CTL2, MODE_WARMUP, mask_sh),\
- SF(WB_WARM_UP_MODE_CTL2, DATA_DEPTH_WARMUP, mask_sh)
+ SF_DWB(WB_ENABLE, WB_ENABLE, mask_sh),\
+ SF_DWB(WB_EC_CONFIG, DISPCLK_R_WB_GATE_DIS, mask_sh),\
+ SF_DWB(WB_EC_CONFIG, DISPCLK_G_WB_GATE_DIS, mask_sh),\
+ SF_DWB(WB_EC_CONFIG, DISPCLK_G_WBSCL_GATE_DIS, mask_sh),\
+ SF_DWB(WB_EC_CONFIG, WB_TEST_CLK_SEL, mask_sh),\
+ SF_DWB(WB_EC_CONFIG, WB_LB_LS_DIS, mask_sh),\
+ SF_DWB(WB_EC_CONFIG, WB_LB_SD_DIS, mask_sh),\
+ SF_DWB(WB_EC_CONFIG, WB_LUT_LS_DIS, mask_sh),\
+ SF_DWB(WB_EC_CONFIG, WBSCL_LB_MEM_PWR_MODE_SEL, mask_sh),\
+ SF_DWB(WB_EC_CONFIG, WBSCL_LB_MEM_PWR_DIS, mask_sh),\
+ SF_DWB(WB_EC_CONFIG, WBSCL_LB_MEM_PWR_FORCE, mask_sh),\
+ SF_DWB(WB_EC_CONFIG, WBSCL_LB_MEM_PWR_STATE, mask_sh),\
+ SF_DWB(WB_EC_CONFIG, WB_RAM_PW_SAVE_MODE, mask_sh),\
+ SF_DWB(WB_EC_CONFIG, WBSCL_LUT_MEM_PWR_STATE, mask_sh),\
+ SF_DWB(CNV_MODE, CNV_OUT_BPC, mask_sh),\
+ SF_DWB(CNV_MODE, CNV_FRAME_CAPTURE_RATE, mask_sh),\
+ SF_DWB(CNV_MODE, CNV_WINDOW_CROP_EN, mask_sh),\
+ SF_DWB(CNV_MODE, CNV_STEREO_TYPE, mask_sh),\
+ SF_DWB(CNV_MODE, CNV_INTERLACED_MODE, mask_sh),\
+ SF_DWB(CNV_MODE, CNV_EYE_SELECTION, mask_sh),\
+ SF_DWB(CNV_MODE, CNV_STEREO_POLARITY, mask_sh),\
+ SF_DWB(CNV_MODE, CNV_INTERLACED_FIELD_ORDER, mask_sh),\
+ SF_DWB(CNV_MODE, CNV_STEREO_SPLIT, mask_sh),\
+ SF_DWB(CNV_MODE, CNV_NEW_CONTENT, mask_sh),\
+ SF_DWB(CNV_MODE, CNV_FRAME_CAPTURE_EN_CURRENT, mask_sh),\
+ SF_DWB(CNV_MODE, CNV_FRAME_CAPTURE_EN, mask_sh),\
+ SF_DWB(CNV_WINDOW_START, CNV_WINDOW_START_X, mask_sh),\
+ SF_DWB(CNV_WINDOW_START, CNV_WINDOW_START_Y, mask_sh),\
+ SF_DWB(CNV_WINDOW_SIZE, CNV_WINDOW_WIDTH, mask_sh),\
+ SF_DWB(CNV_WINDOW_SIZE, CNV_WINDOW_HEIGHT, mask_sh),\
+ SF_DWB(CNV_UPDATE, CNV_UPDATE_PENDING, mask_sh),\
+ SF_DWB(CNV_UPDATE, CNV_UPDATE_TAKEN, mask_sh),\
+ SF_DWB(CNV_UPDATE, CNV_UPDATE_LOCK, mask_sh),\
+ SF_DWB(CNV_SOURCE_SIZE, CNV_SOURCE_WIDTH, mask_sh),\
+ SF_DWB(CNV_SOURCE_SIZE, CNV_SOURCE_HEIGHT, mask_sh),\
+ SF_DWB(CNV_TEST_CNTL, CNV_TEST_CRC_EN, mask_sh),\
+ SF_DWB(CNV_TEST_CNTL, CNV_TEST_CRC_CONT_EN, mask_sh),\
+ SF_DWB(CNV_TEST_CRC_RED, CNV_TEST_CRC_RED_MASK, mask_sh),\
+ SF_DWB(CNV_TEST_CRC_RED, CNV_TEST_CRC_SIG_RED, mask_sh),\
+ SF_DWB(CNV_TEST_CRC_GREEN, CNV_TEST_CRC_GREEN_MASK, mask_sh),\
+ SF_DWB(CNV_TEST_CRC_GREEN, CNV_TEST_CRC_SIG_GREEN, mask_sh),\
+ SF_DWB(CNV_TEST_CRC_BLUE, CNV_TEST_CRC_BLUE_MASK, mask_sh),\
+ SF_DWB(CNV_TEST_CRC_BLUE, CNV_TEST_CRC_SIG_BLUE, mask_sh),\
+ SF_DWB(WB_DEBUG_CTRL, WB_DEBUG_EN, mask_sh),\
+ SF_DWB(WB_DEBUG_CTRL, WB_DEBUG_SEL, mask_sh),\
+ SF_DWB(WB_DBG_MODE, WB_DBG_MODE_EN, mask_sh),\
+ SF_DWB(WB_DBG_MODE, WB_DBG_DIN_FMT, mask_sh),\
+ SF_DWB(WB_DBG_MODE, WB_DBG_36MODE, mask_sh),\
+ SF_DWB(WB_DBG_MODE, WB_DBG_CMAP, mask_sh),\
+ SF_DWB(WB_DBG_MODE, WB_DBG_PXLRATE_ERROR, mask_sh),\
+ SF_DWB(WB_DBG_MODE, WB_DBG_SOURCE_WIDTH, mask_sh),\
+ SF_DWB(WB_HW_DEBUG, WB_HW_DEBUG, mask_sh),\
+ SF_DWB(WB_SOFT_RESET, WB_SOFT_RESET, mask_sh),\
+ SF_DWB(CNV_TEST_DEBUG_INDEX, CNV_TEST_DEBUG_INDEX, mask_sh),\
+ SF_DWB(CNV_TEST_DEBUG_INDEX, CNV_TEST_DEBUG_WRITE_EN, mask_sh),\
+ SF_DWB(CNV_TEST_DEBUG_DATA, CNV_TEST_DEBUG_DATA, mask_sh),\
+ SF_DWB(WBSCL_COEF_RAM_SELECT, WBSCL_COEF_RAM_TAP_PAIR_IDX, mask_sh),\
+ SF_DWB(WBSCL_COEF_RAM_SELECT, WBSCL_COEF_RAM_PHASE, mask_sh),\
+ SF_DWB(WBSCL_COEF_RAM_SELECT, WBSCL_COEF_RAM_FILTER_TYPE, mask_sh),\
+ SF_DWB(WBSCL_COEF_RAM_TAP_DATA, WBSCL_COEF_RAM_EVEN_TAP_COEF, mask_sh),\
+ SF_DWB(WBSCL_COEF_RAM_TAP_DATA, WBSCL_COEF_RAM_EVEN_TAP_COEF_EN, mask_sh),\
+ SF_DWB(WBSCL_COEF_RAM_TAP_DATA, WBSCL_COEF_RAM_ODD_TAP_COEF, mask_sh),\
+ SF_DWB(WBSCL_COEF_RAM_TAP_DATA, WBSCL_COEF_RAM_ODD_TAP_COEF_EN, mask_sh),\
+ SF_DWB(WBSCL_MODE, WBSCL_MODE, mask_sh),\
+ SF_DWB(WBSCL_MODE, WBSCL_OUT_BIT_DEPTH, mask_sh),\
+ SF_DWB(WBSCL_TAP_CONTROL, WBSCL_V_NUM_OF_TAPS_Y_RGB, mask_sh),\
+ SF_DWB(WBSCL_TAP_CONTROL, WBSCL_V_NUM_OF_TAPS_CBCR, mask_sh),\
+ SF_DWB(WBSCL_TAP_CONTROL, WBSCL_H_NUM_OF_TAPS_Y_RGB, mask_sh),\
+ SF_DWB(WBSCL_TAP_CONTROL, WBSCL_H_NUM_OF_TAPS_CBCR, mask_sh),\
+ SF_DWB(WBSCL_DEST_SIZE, WBSCL_DEST_HEIGHT, mask_sh),\
+ SF_DWB(WBSCL_DEST_SIZE, WBSCL_DEST_WIDTH, mask_sh),\
+ SF_DWB(WBSCL_HORZ_FILTER_SCALE_RATIO, WBSCL_H_SCALE_RATIO, mask_sh),\
+ SF_DWB(WBSCL_HORZ_FILTER_INIT_Y_RGB, WBSCL_H_INIT_FRAC_Y_RGB, mask_sh),\
+ SF_DWB(WBSCL_HORZ_FILTER_INIT_Y_RGB, WBSCL_H_INIT_INT_Y_RGB, mask_sh),\
+ SF_DWB(WBSCL_HORZ_FILTER_INIT_CBCR, WBSCL_H_INIT_FRAC_CBCR, mask_sh),\
+ SF_DWB(WBSCL_HORZ_FILTER_INIT_CBCR, WBSCL_H_INIT_INT_CBCR, mask_sh),\
+ SF_DWB(WBSCL_VERT_FILTER_SCALE_RATIO, WBSCL_V_SCALE_RATIO, mask_sh),\
+ SF_DWB(WBSCL_VERT_FILTER_INIT_Y_RGB, WBSCL_V_INIT_FRAC_Y_RGB, mask_sh),\
+ SF_DWB(WBSCL_VERT_FILTER_INIT_Y_RGB, WBSCL_V_INIT_INT_Y_RGB, mask_sh),\
+ SF_DWB(WBSCL_VERT_FILTER_INIT_CBCR, WBSCL_V_INIT_FRAC_CBCR, mask_sh),\
+ SF_DWB(WBSCL_VERT_FILTER_INIT_CBCR, WBSCL_V_INIT_INT_CBCR, mask_sh),\
+ SF_DWB(WBSCL_ROUND_OFFSET, WBSCL_ROUND_OFFSET_Y_RGB, mask_sh),\
+ SF_DWB(WBSCL_ROUND_OFFSET, WBSCL_ROUND_OFFSET_CBCR, mask_sh),\
+ SF_DWB(WBSCL_OVERFLOW_STATUS, WBSCL_DATA_OVERFLOW_FLAG, mask_sh),\
+ SF_DWB(WBSCL_OVERFLOW_STATUS, WBSCL_DATA_OVERFLOW_ACK, mask_sh),\
+ SF_DWB(WBSCL_OVERFLOW_STATUS, WBSCL_DATA_OVERFLOW_MASK, mask_sh),\
+ SF_DWB(WBSCL_OVERFLOW_STATUS, WBSCL_DATA_OVERFLOW_INT_STATUS, mask_sh),\
+ SF_DWB(WBSCL_OVERFLOW_STATUS, WBSCL_DATA_OVERFLOW_INT_TYPE, mask_sh),\
+ SF_DWB(WBSCL_COEF_RAM_CONFLICT_STATUS, WBSCL_HOST_CONFLICT_FLAG, mask_sh),\
+ SF_DWB(WBSCL_COEF_RAM_CONFLICT_STATUS, WBSCL_HOST_CONFLICT_ACK, mask_sh),\
+ SF_DWB(WBSCL_COEF_RAM_CONFLICT_STATUS, WBSCL_HOST_CONFLICT_MASK, mask_sh),\
+ SF_DWB(WBSCL_COEF_RAM_CONFLICT_STATUS, WBSCL_HOST_CONFLICT_INT_STATUS, mask_sh),\
+ SF_DWB(WBSCL_COEF_RAM_CONFLICT_STATUS, WBSCL_HOST_CONFLICT_INT_TYPE, mask_sh),\
+ SF_DWB(WBSCL_TEST_CNTL, WBSCL_TEST_CRC_EN, mask_sh),\
+ SF_DWB(WBSCL_TEST_CNTL, WBSCL_TEST_CRC_CONT_EN, mask_sh),\
+ SF_DWB(WBSCL_TEST_CRC_RED, WBSCL_TEST_CRC_RED_MASK, mask_sh),\
+ SF_DWB(WBSCL_TEST_CRC_RED, WBSCL_TEST_CRC_SIG_RED, mask_sh),\
+ SF_DWB(WBSCL_TEST_CRC_GREEN, WBSCL_TEST_CRC_GREEN_MASK, mask_sh),\
+ SF_DWB(WBSCL_TEST_CRC_GREEN, WBSCL_TEST_CRC_SIG_GREEN, mask_sh),\
+ SF_DWB(WBSCL_TEST_CRC_BLUE, WBSCL_TEST_CRC_BLUE_MASK, mask_sh),\
+ SF_DWB(WBSCL_TEST_CRC_BLUE, WBSCL_TEST_CRC_SIG_BLUE, mask_sh),\
+ SF_DWB(WBSCL_BACKPRESSURE_CNT_EN, WBSCL_BACKPRESSURE_CNT_EN, mask_sh),\
+ SF_DWB(WB_MCIF_BACKPRESSURE_CNT, WB_MCIF_Y_MAX_BACKPRESSURE, mask_sh),\
+ SF_DWB(WB_MCIF_BACKPRESSURE_CNT, WB_MCIF_C_MAX_BACKPRESSURE, mask_sh),\
+ SF_DWB(WBSCL_CLAMP_Y_RGB, WBSCL_CLAMP_UPPER_Y_RGB, mask_sh),\
+ SF_DWB(WBSCL_CLAMP_Y_RGB, WBSCL_CLAMP_LOWER_Y_RGB, mask_sh),\
+ SF_DWB(WBSCL_CLAMP_CBCR, WBSCL_CLAMP_UPPER_CBCR, mask_sh),\
+ SF_DWB(WBSCL_CLAMP_CBCR, WBSCL_CLAMP_LOWER_CBCR, mask_sh),\
+ SF_DWB(WBSCL_OUTSIDE_PIX_STRATEGY, WBSCL_OUTSIDE_PIX_STRATEGY, mask_sh),\
+ SF_DWB(WBSCL_OUTSIDE_PIX_STRATEGY, WBSCL_BLACK_COLOR_G_Y, mask_sh),\
+ SF_DWB(WBSCL_OUTSIDE_PIX_STRATEGY_CBCR, WBSCL_BLACK_COLOR_B_CB, mask_sh),\
+ SF_DWB(WBSCL_OUTSIDE_PIX_STRATEGY_CBCR, WBSCL_BLACK_COLOR_R_CR, mask_sh),\
+ SF_DWB(WBSCL_DEBUG, WBSCL_DEBUG, mask_sh),\
+ SF_DWB(WBSCL_TEST_DEBUG_INDEX, WBSCL_TEST_DEBUG_INDEX, mask_sh),\
+ SF_DWB(WBSCL_TEST_DEBUG_INDEX, WBSCL_TEST_DEBUG_WRITE_EN, mask_sh),\
+ SF_DWB(WBSCL_TEST_DEBUG_DATA, WBSCL_TEST_DEBUG_DATA, mask_sh),\
+ SF_DWB(WB_WARM_UP_MODE_CTL1, WIDTH_WARMUP, mask_sh),\
+ SF_DWB(WB_WARM_UP_MODE_CTL1, HEIGHT_WARMUP, mask_sh),\
+ SF_DWB(WB_WARM_UP_MODE_CTL1, GMC_WARM_UP_ENABLE, mask_sh),\
+ SF_DWB(WB_WARM_UP_MODE_CTL2, DATA_VALUE_WARMUP, mask_sh),\
+ SF_DWB(WB_WARM_UP_MODE_CTL2, MODE_WARMUP, mask_sh),\
+ SF_DWB(WB_WARM_UP_MODE_CTL2, DATA_DEPTH_WARMUP, mask_sh)
#define DWBC_REG_FIELD_LIST_DCN2_0(type) \
type WB_ENABLE;\
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 a7e0001a8f46..6291a241158a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c
@@ -1079,6 +1079,29 @@ void dcn20_blank_pixel_data(
0);
}
+ if (!blank && dc->debug.enable_single_display_2to1_odm_policy) {
+ /* when exiting dynamic ODM need to reinit DPG state for unused pipes */
+ struct pipe_ctx *old_odm_pipe = dc->current_state->res_ctx.pipe_ctx[pipe_ctx->pipe_idx].next_odm_pipe;
+
+ odm_pipe = pipe_ctx->next_odm_pipe;
+
+ while (old_odm_pipe) {
+ if (!odm_pipe || old_odm_pipe->pipe_idx != odm_pipe->pipe_idx)
+ dc->hwss.set_disp_pattern_generator(dc,
+ old_odm_pipe,
+ CONTROLLER_DP_TEST_PATTERN_VIDEOMODE,
+ CONTROLLER_DP_COLOR_SPACE_UDEFINED,
+ COLOR_DEPTH_888,
+ NULL,
+ 0,
+ 0,
+ 0);
+ old_odm_pipe = old_odm_pipe->next_odm_pipe;
+ if (odm_pipe)
+ odm_pipe = odm_pipe->next_odm_pipe;
+ }
+ }
+
if (!blank)
if (stream_res->abm) {
dc->hwss.set_pipe(pipe_ctx);
@@ -1287,6 +1310,19 @@ static void dcn20_detect_pipe_changes(struct pipe_ctx *old_pipe, struct pipe_ctx
{
new_pipe->update_flags.raw = 0;
+ /* If non-phantom pipe is being transitioned to a phantom pipe,
+ * set disable and return immediately. This is because the pipe
+ * that was previously in use must be fully disabled before we
+ * can "enable" it as a phantom pipe (since the OTG will certainly
+ * be different). The post_unlock sequence will set the correct
+ * update flags to enable the phantom pipe.
+ */
+ if (old_pipe->plane_state && !old_pipe->plane_state->is_phantom &&
+ new_pipe->plane_state && new_pipe->plane_state->is_phantom) {
+ new_pipe->update_flags.bits.disable = 1;
+ return;
+ }
+
/* Exit on unchanged, unused pipe */
if (!old_pipe->plane_state && !new_pipe->plane_state)
return;
@@ -1616,6 +1652,31 @@ static void dcn20_update_dchubp_dpp(
hubp->funcs->phantom_hubp_post_enable(hubp);
}
+static int calculate_vready_offset_for_group(struct pipe_ctx *pipe)
+{
+ struct pipe_ctx *other_pipe;
+ int vready_offset = pipe->pipe_dlg_param.vready_offset;
+
+ /* Always use the largest vready_offset of all connected pipes */
+ for (other_pipe = pipe->bottom_pipe; other_pipe != NULL; other_pipe = other_pipe->bottom_pipe) {
+ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset)
+ vready_offset = other_pipe->pipe_dlg_param.vready_offset;
+ }
+ for (other_pipe = pipe->top_pipe; other_pipe != NULL; other_pipe = other_pipe->top_pipe) {
+ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset)
+ vready_offset = other_pipe->pipe_dlg_param.vready_offset;
+ }
+ for (other_pipe = pipe->next_odm_pipe; other_pipe != NULL; other_pipe = other_pipe->next_odm_pipe) {
+ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset)
+ vready_offset = other_pipe->pipe_dlg_param.vready_offset;
+ }
+ for (other_pipe = pipe->prev_odm_pipe; other_pipe != NULL; other_pipe = other_pipe->prev_odm_pipe) {
+ if (other_pipe->pipe_dlg_param.vready_offset > vready_offset)
+ vready_offset = other_pipe->pipe_dlg_param.vready_offset;
+ }
+
+ return vready_offset;
+}
static void dcn20_program_pipe(
struct dc *dc,
@@ -1634,16 +1695,14 @@ static void dcn20_program_pipe(
&& !pipe_ctx->prev_odm_pipe) {
pipe_ctx->stream_res.tg->funcs->program_global_sync(
pipe_ctx->stream_res.tg,
- pipe_ctx->pipe_dlg_param.vready_offset,
+ calculate_vready_offset_for_group(pipe_ctx),
pipe_ctx->pipe_dlg_param.vstartup_start,
pipe_ctx->pipe_dlg_param.vupdate_offset,
pipe_ctx->pipe_dlg_param.vupdate_width);
if (pipe_ctx->stream->mall_stream_config.type != SUBVP_PHANTOM) {
- pipe_ctx->stream_res.tg->funcs->wait_for_state(
- pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK);
- pipe_ctx->stream_res.tg->funcs->wait_for_state(
- pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
+ pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VBLANK);
+ pipe_ctx->stream_res.tg->funcs->wait_for_state(pipe_ctx->stream_res.tg, CRTC_STATE_VACTIVE);
}
pipe_ctx->stream_res.tg->funcs->set_vtg_params(
@@ -1682,7 +1741,10 @@ static void dcn20_program_pipe(
* only do gamma programming for powering on, internal memcmp to avoid
* updating on slave planes
*/
- if (pipe_ctx->update_flags.bits.enable || pipe_ctx->stream->update_flags.bits.out_tf)
+ if (pipe_ctx->update_flags.bits.enable ||
+ pipe_ctx->update_flags.bits.plane_changed ||
+ pipe_ctx->stream->update_flags.bits.out_tf ||
+ pipe_ctx->plane_state->update_flags.bits.output_tf_change)
hws->funcs.set_output_transfer_func(dc, pipe_ctx, pipe_ctx->stream);
/* If the pipe has been enabled or has a different opp, we
@@ -1813,6 +1875,17 @@ void dcn20_program_front_end_for_ctx(
context->stream_status[0].plane_count > 1) {
pipe->plane_res.hubp->funcs->hubp_wait_pipe_read_start(pipe->plane_res.hubp);
}
+
+ /* when dynamic ODM is active, pipes must be reconfigured when all planes are
+ * disabled, as some transitions will leave software and hardware state
+ * mismatched.
+ */
+ if (dc->debug.enable_single_display_2to1_odm_policy &&
+ pipe->stream &&
+ pipe->update_flags.bits.disable &&
+ !pipe->prev_odm_pipe &&
+ hws->funcs.update_odm)
+ hws->funcs.update_odm(dc, context, pipe);
}
}
@@ -1852,26 +1925,6 @@ void dcn20_post_unlock_program_front_end(
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
- struct pipe_ctx *old_pipe = &dc->current_state->res_ctx.pipe_ctx[i];
-
- /* If an active, non-phantom pipe is being transitioned into a phantom
- * pipe, wait for the double buffer update to complete first before we do
- * phantom pipe programming (HUBP_VTG_SEL updates right away so that can
- * cause issues).
- */
- if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM &&
- old_pipe->stream && old_pipe->stream->mall_stream_config.type != SUBVP_PHANTOM) {
- old_pipe->stream_res.tg->funcs->wait_for_state(
- old_pipe->stream_res.tg,
- CRTC_STATE_VBLANK);
- old_pipe->stream_res.tg->funcs->wait_for_state(
- old_pipe->stream_res.tg,
- CRTC_STATE_VACTIVE);
- }
- }
-
- for (i = 0; i < dc->res_pool->pipe_count; i++) {
- struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
if (pipe->plane_state && !pipe->top_pipe) {
/* Program phantom pipe here to prevent a frame of underflow in the MPO transition
@@ -1881,6 +1934,11 @@ void dcn20_post_unlock_program_front_end(
*/
while (pipe) {
if (pipe->stream && pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
+ /* When turning on the phantom pipe we want to run through the
+ * entire enable sequence, so apply all the "enable" flags.
+ */
+ if (dc->hwss.apply_update_flags_for_phantom)
+ dc->hwss.apply_update_flags_for_phantom(pipe);
if (dc->hwss.update_phantom_vp_position)
dc->hwss.update_phantom_vp_position(dc, context, pipe);
dcn20_program_pipe(dc, pipe, context);
@@ -1953,10 +2011,13 @@ void dcn20_prepare_bandwidth(
/* decrease compbuf size */
if (hubbub->funcs->program_compbuf_size) {
- if (context->bw_ctx.dml.ip.min_comp_buffer_size_kbytes)
+ if (context->bw_ctx.dml.ip.min_comp_buffer_size_kbytes) {
compbuf_size_kb = context->bw_ctx.dml.ip.min_comp_buffer_size_kbytes;
- else
+ dc->wm_optimized_required |= (compbuf_size_kb != dc->current_state->bw_ctx.dml.ip.min_comp_buffer_size_kbytes);
+ } else {
compbuf_size_kb = context->bw_ctx.bw.dcn.compbuf_size_kb;
+ dc->wm_optimized_required |= (compbuf_size_kb != dc->current_state->bw_ctx.bw.dcn.compbuf_size_kb);
+ }
hubbub->funcs->program_compbuf_size(hubbub, compbuf_size_kb, false);
}
@@ -2037,7 +2098,7 @@ bool dcn20_update_bandwidth(
pipe_ctx->stream_res.tg->funcs->program_global_sync(
pipe_ctx->stream_res.tg,
- pipe_ctx->pipe_dlg_param.vready_offset,
+ calculate_vready_offset_for_group(pipe_ctx),
pipe_ctx->pipe_dlg_param.vstartup_start,
pipe_ctx->pipe_dlg_param.vupdate_offset,
pipe_ctx->pipe_dlg_param.vupdate_width);
@@ -2601,14 +2662,6 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
if (dc->hwseq->funcs.set_pixels_per_cycle)
dc->hwseq->funcs.set_pixels_per_cycle(pipe_ctx);
-
- /* enable audio only within mode set */
- if (pipe_ctx->stream_res.audio != NULL) {
- if (is_dp_128b_132b_signal(pipe_ctx))
- pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.hpo_dp_stream_enc);
- else if (dc_is_dp_signal(pipe_ctx->stream->signal))
- pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(pipe_ctx->stream_res.stream_enc);
- }
}
void dcn20_program_dmdata_engine(struct pipe_ctx *pipe_ctx)
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mmhubbub.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mmhubbub.h
index 7bcee5894d2e..5ab32aa51e13 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mmhubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mmhubbub.h
@@ -29,13 +29,6 @@
#define TO_DCN20_MMHUBBUB(mcif_wb_base) \
container_of(mcif_wb_base, struct dcn20_mmhubbub, base)
-/* DCN */
-#define BASE_INNER(seg) \
- DCE_BASE__INST0_SEG ## seg
-
-#define BASE(seg) \
- BASE_INNER(seg)
-
#define MCIF_WB_COMMON_REG_LIST_DCN2_0(inst) \
SRI(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB, inst),\
SRI(MCIF_WB_BUFMGR_CUR_LINE_R, MCIF_WB, 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 8224b9bf01d1..8a0dd0d7134b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
@@ -124,8 +124,6 @@ enum dcn20_clk_src_array_id {
* macros to expend register list macro defined in HW object header file */
/* DCN */
-/* TODO awful hack. fixup dcn20_dwb.h */
-#undef BASE_INNER
#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
#define BASE(seg) BASE_INNER(seg)
@@ -138,6 +136,15 @@ enum dcn20_clk_src_array_id {
.reg_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
mm ## block ## id ## _ ## reg_name
+#define SRI2_DWB(reg_name, block, id)\
+ .reg_name = BASE(mm ## reg_name ## _BASE_IDX) + \
+ mm ## reg_name
+#define SF_DWB(reg_name, field_name, post_fix)\
+ .field_name = reg_name ## __ ## field_name ## post_fix
+
+#define SF_DWB2(reg_name, block, id, field_name, post_fix) \
+ .field_name = reg_name ## __ ## field_name ## post_fix
+
#define SRIR(var_name, reg_name, block, id)\
.var_name = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
mm ## block ## id ## _ ## reg_name
@@ -1454,6 +1461,22 @@ enum dc_status dcn20_remove_stream_from_ctx(struct dc *dc, struct dc_state *new_
return result;
}
+/**
+ * dcn20_split_stream_for_odm - Check if stream can be splited for ODM
+ *
+ * @dc: DC object with resource pool info required for pipe split
+ * @res_ctx: Persistent state of resources
+ * @prev_odm_pipe: Reference to the previous ODM pipe
+ * @next_odm_pipe: Reference to the next ODM pipe
+ *
+ * This function takes a logically active pipe and a logically free pipe and
+ * halves all the scaling parameters that need to be halved while populating
+ * the free pipe with the required resources and configuring the next/previous
+ * ODM pipe pointers.
+ *
+ * Return:
+ * Return true if split stream for ODM is possible, otherwise, return false.
+ */
bool dcn20_split_stream_for_odm(
const struct dc *dc,
struct resource_context *res_ctx,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.h
index f1ef46e8da5b..e7a1b7fa2cce 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_vmid.h
@@ -28,12 +28,6 @@
#include "vmid.h"
-#define BASE_INNER(seg) \
- DCE_BASE__INST0_SEG ## seg
-
-#define BASE(seg) \
- BASE_INNER(seg)
-
#define DCN20_VMID_REG_LIST(id)\
SRI(CNTL, DCN_VM_CONTEXT, id),\
SRI(PAGE_TABLE_BASE_ADDR_HI32, DCN_VM_CONTEXT, id),\
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 887081472c0d..fbcf0afeae0d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
@@ -94,8 +94,6 @@
* macros to expend register list macro defined in HW object header file */
/* DCN */
-/* TODO awful hack. fixup dcn20_dwb.h */
-#undef BASE_INNER
#define BASE_INNER(seg) DMU_BASE__INST0_SEG ## seg
#define BASE(seg) BASE_INNER(seg)
@@ -671,12 +669,15 @@ static const struct dc_debug_options debug_defaults_diags = {
.disable_pplib_wm_range = true,
.disable_stutter = true,
.disable_48mhz_pwrdwn = true,
- .disable_psr = true,
.enable_tri_buf = true,
.use_max_lb = true
};
static const struct dc_panel_config panel_config_defaults = {
+ .psr = {
+ .disable_psr = false,
+ .disallow_psrsu = false,
+ },
.ilr = {
.optimize_edp_link_rate = true,
},
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.h
index 1010930cf071..fc00ec0a0881 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_dwb.h
@@ -27,21 +27,6 @@
#define TO_DCN30_DWBC(dwbc_base) \
container_of(dwbc_base, struct dcn30_dwbc, base)
-/* DCN */
-#define BASE_INNER(seg) \
- DCE_BASE__INST0_SEG ## seg
-
-#define BASE(seg) \
- BASE_INNER(seg)
-
-#define SF_DWB(reg_name, block, id, field_name, post_fix)\
- .field_name = block ## id ## _ ## reg_name ## __ ## field_name ## post_fix
-
- /* set field name */
-#define SF_DWB2(reg_name, block, id, field_name, post_fix)\
- .field_name = reg_name ## __ ## field_name ## post_fix
-
-
#define DWBC_COMMON_REG_LIST_DCN30(inst) \
SR(DWB_ENABLE_CLK_CTRL),\
SR(DWB_MEM_PWR_CTRL),\
diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mmhubbub.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mmhubbub.h
index 7446e54bf5aa..376620a8f02f 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mmhubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_mmhubbub.h
@@ -31,13 +31,6 @@
#define TO_DCN30_MMHUBBUB(mcif_wb_base) \
container_of(mcif_wb_base, struct dcn30_mmhubbub, base)
-/* DCN */
-#define BASE_INNER(seg) \
- DCE_BASE__INST0_SEG ## seg
-
-#define BASE(seg) \
- BASE_INNER(seg)
-
#define MCIF_WB_COMMON_REG_LIST_DCN3_0(inst) \
SRI(MCIF_WB_BUFMGR_SW_CONTROL, MCIF_WB, inst),\
SRI(MCIF_WB_BUFMGR_STATUS, MCIF_WB, inst),\
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 892d3c4d01a1..867d60151aeb 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
@@ -30,6 +30,7 @@
#include "dc_dmub_srv.h"
#include "dml/dcn30/dcn30_fpu.h"
+#include "dc_trace.h"
#define REG(reg)\
optc1->tg_regs->reg
@@ -58,6 +59,8 @@ void optc3_triplebuffer_lock(struct timing_generator *optc)
REG_WAIT(OTG_MASTER_UPDATE_LOCK,
UPDATE_LOCK_STATUS, 1,
1, 10);
+
+ TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true);
}
void optc3_lock_doublebuffer_enable(struct timing_generator *optc)
@@ -93,6 +96,8 @@ void optc3_lock_doublebuffer_enable(struct timing_generator *optc)
MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_START_OFFSET, 0,
MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_END_OFFSET, 100,
OTG_MASTER_UPDATE_LOCK_VUPDATE_KEEPOUT_EN, 1);
+
+ TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true);
}
void optc3_lock_doublebuffer_disable(struct timing_generator *optc)
@@ -108,6 +113,8 @@ void optc3_lock_doublebuffer_disable(struct timing_generator *optc)
REG_UPDATE(OTG_GLOBAL_CONTROL2, GLOBAL_UPDATE_LOCK_EN, 0);
REG_UPDATE(OTG_GLOBAL_CONTROL0, MASTER_UPDATE_LOCK_DB_EN, 0);
+
+ TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true);
}
void optc3_lock(struct timing_generator *optc)
@@ -122,6 +129,8 @@ void optc3_lock(struct timing_generator *optc)
REG_WAIT(OTG_MASTER_UPDATE_LOCK,
UPDATE_LOCK_STATUS, 1,
1, 10);
+
+ TRACE_OPTC_LOCK_UNLOCK_STATE(optc1, optc->inst, true);
}
void optc3_set_out_mux(struct timing_generator *optc, enum otg_out_mux_dest dest)
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 020f512e9690..c18c52a60100 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
@@ -108,8 +108,6 @@ enum dcn30_clk_src_array_id {
*/
/* DCN */
-/* TODO awful hack. fixup dcn20_dwb.h */
-#undef BASE_INNER
#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
#define BASE(seg) BASE_INNER(seg)
@@ -142,6 +140,9 @@ enum dcn30_clk_src_array_id {
.reg_name[id] = BASE(mm ## block ## id ## _ ## temp_name ## _BASE_IDX) + \
mm ## block ## id ## _ ## temp_name
+#define SF_DWB2(reg_name, block, id, field_name, post_fix) \
+ .field_name = reg_name ## __ ## field_name ## post_fix
+
#define DCCG_SRII(reg_name, block, id)\
.block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
mm ## block ## id ## _ ## reg_name
@@ -723,7 +724,6 @@ static const struct dc_debug_options debug_defaults_drv = {
.underflow_assert_delay_us = 0xFFFFFFFF,
.dwb_fi_phase = -1, // -1 = disable,
.dmub_command_table = true,
- .disable_psr = false,
.use_max_lb = true,
.exit_idle_opt_for_cursor_updates = true
};
@@ -742,11 +742,17 @@ static const struct dc_debug_options debug_defaults_diags = {
.scl_reset_length10 = true,
.dwb_fi_phase = -1, // -1 = disable
.dmub_command_table = true,
- .disable_psr = true,
.enable_tri_buf = true,
.use_max_lb = true
};
+static const struct dc_panel_config panel_config_defaults = {
+ .psr = {
+ .disable_psr = false,
+ .disallow_psrsu = false,
+ },
+};
+
static void dcn30_dpp_destroy(struct dpp **dpp)
{
kfree(TO_DCN20_DPP(*dpp));
@@ -1323,6 +1329,7 @@ static struct clock_source *dcn30_clock_source_create(
return &clk_src->base;
}
+ kfree(clk_src);
BREAK_TO_DEBUGGER();
return NULL;
}
@@ -2212,6 +2219,11 @@ void dcn30_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params
}
}
+static void dcn30_get_panel_config_defaults(struct dc_panel_config *panel_config)
+{
+ *panel_config = panel_config_defaults;
+}
+
static const struct resource_funcs dcn30_res_pool_funcs = {
.destroy = dcn30_destroy_resource_pool,
.link_enc_create = dcn30_link_encoder_create,
@@ -2231,6 +2243,7 @@ static const struct resource_funcs dcn30_res_pool_funcs = {
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
.update_bw_bounding_box = dcn30_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
+ .get_panel_config_defaults = dcn30_get_panel_config_defaults,
};
#define CTX ctx
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 f04595b750ab..8cf10351f271 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
@@ -107,8 +107,6 @@ enum dcn301_clk_src_array_id {
*/
/* DCN */
-/* TODO awful hack. fixup dcn20_dwb.h */
-#undef BASE_INNER
#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
#define BASE(seg) BASE_INNER(seg)
@@ -146,6 +144,9 @@ enum dcn301_clk_src_array_id {
.reg_name[id] = BASE(mm ## block ## id ## _ ## temp_name ## _BASE_IDX) + \
mm ## block ## id ## _ ## temp_name
+#define SF_DWB2(reg_name, block, id, field_name, post_fix) \
+ .field_name = reg_name ## __ ## field_name ## post_fix
+
#define DCCG_SRII(reg_name, block, id)\
.block ## _ ## reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
mm ## block ## id ## _ ## reg_name
@@ -1288,6 +1289,7 @@ static struct clock_source *dcn301_clock_source_create(
return &clk_src->base;
}
+ kfree(clk_src);
BREAK_TO_DEBUGGER();
return NULL;
}
@@ -1491,6 +1493,8 @@ static bool dcn301_resource_construct(
dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
dc->caps.color.mpc.ocsc = 1;
+ dc->caps.dp_hdmi21_pcon_support = true;
+
/* read VBIOS LTTPR caps */
if (ctx->dc_bios->funcs->get_lttpr_caps) {
enum bp_result bp_query_result;
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 b925b6ddde5a..47cffd0e6830 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.c
@@ -112,10 +112,16 @@ static const struct dc_debug_options debug_defaults_diags = {
.dwb_fi_phase = -1, // -1 = disable
.dmub_command_table = true,
.enable_tri_buf = true,
- .disable_psr = true,
.use_max_lb = true
};
+static const struct dc_panel_config panel_config_defaults = {
+ .psr = {
+ .disable_psr = false,
+ .disallow_psrsu = false,
+ },
+};
+
enum dcn302_clk_src_array_id {
DCN302_CLK_SRC_PLL0,
DCN302_CLK_SRC_PLL1,
@@ -177,7 +183,6 @@ static const struct dc_plane_cap plane_cap = {
mm ## reg_name
/* DCN */
-#undef BASE_INNER
#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
#define BASE(seg) BASE_INNER(seg)
@@ -210,6 +215,9 @@ static const struct dc_plane_cap plane_cap = {
.reg_name[id] = BASE(mm ## block ## id ## _ ## temp_name ## _BASE_IDX) + \
mm ## block ## id ## _ ## temp_name
+#define SF_DWB2(reg_name, block, id, field_name, post_fix) \
+ .field_name = reg_name ## __ ## field_name ## post_fix
+
#define SRII_MPC_RMU(reg_name, block, id)\
.RMU##_##reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
mm ## block ## id ## _ ## reg_name
@@ -458,6 +466,7 @@ static struct clock_source *dcn302_clock_source_create(struct dc_context *ctx, s
return &clk_src->base;
}
+ kfree(clk_src);
BREAK_TO_DEBUGGER();
return NULL;
}
@@ -1132,6 +1141,11 @@ void dcn302_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
DC_FP_END();
}
+static void dcn302_get_panel_config_defaults(struct dc_panel_config *panel_config)
+{
+ *panel_config = panel_config_defaults;
+}
+
static struct resource_funcs dcn302_res_pool_funcs = {
.destroy = dcn302_destroy_resource_pool,
.link_enc_create = dcn302_link_encoder_create,
@@ -1151,6 +1165,7 @@ static struct resource_funcs dcn302_res_pool_funcs = {
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
.update_bw_bounding_box = dcn302_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
+ .get_panel_config_defaults = dcn302_get_panel_config_defaults,
};
static struct dc_cap_funcs cap_funcs = {
@@ -1266,6 +1281,8 @@ static bool dcn302_resource_construct(
dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
dc->caps.color.mpc.ocsc = 1;
+ dc->caps.dp_hdmi21_pcon_support = true;
+
/* read VBIOS LTTPR caps */
if (ctx->dc_bios->funcs->get_lttpr_caps) {
enum bp_result bp_query_result;
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 527d5c902878..c14d35894b2e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c
@@ -96,7 +96,13 @@ static const struct dc_debug_options debug_defaults_diags = {
.dwb_fi_phase = -1, // -1 = disable
.dmub_command_table = true,
.enable_tri_buf = true,
- .disable_psr = true,
+};
+
+static const struct dc_panel_config panel_config_defaults = {
+ .psr = {
+ .disable_psr = false,
+ .disallow_psrsu = false,
+ },
};
enum dcn303_clk_src_array_id {
@@ -156,7 +162,6 @@ static const struct dc_plane_cap plane_cap = {
mm ## reg_name
/* DCN */
-#undef BASE_INNER
#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
#define BASE(seg) BASE_INNER(seg)
@@ -189,6 +194,9 @@ static const struct dc_plane_cap plane_cap = {
.reg_name[id] = BASE(mm ## block ## id ## _ ## temp_name ## _BASE_IDX) + \
mm ## block ## id ## _ ## temp_name
+#define SF_DWB2(reg_name, block, id, field_name, post_fix) \
+ .field_name = reg_name ## __ ## field_name ## post_fix
+
#define SRII_MPC_RMU(reg_name, block, id)\
.RMU##_##reg_name[id] = BASE(mm ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
mm ## block ## id ## _ ## reg_name
@@ -425,6 +433,7 @@ static struct clock_source *dcn303_clock_source_create(struct dc_context *ctx, s
return &clk_src->base;
}
+ kfree(clk_src);
BREAK_TO_DEBUGGER();
return NULL;
}
@@ -1055,6 +1064,10 @@ static void dcn303_destroy_resource_pool(struct resource_pool **pool)
*pool = NULL;
}
+static void dcn303_get_panel_config_defaults(struct dc_panel_config *panel_config)
+{
+ *panel_config = panel_config_defaults;
+}
void dcn303_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
{
@@ -1082,6 +1095,7 @@ static struct resource_funcs dcn303_res_pool_funcs = {
.release_post_bldn_3dlut = dcn30_release_post_bldn_3dlut,
.update_bw_bounding_box = dcn303_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
+ .get_panel_config_defaults = dcn303_get_panel_config_defaults,
};
static struct dc_cap_funcs cap_funcs = {
@@ -1198,6 +1212,8 @@ static bool dcn303_resource_construct(
dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
dc->caps.color.mpc.ocsc = 1;
+ dc->caps.dp_hdmi21_pcon_support = true;
+
/* read VBIOS LTTPR caps */
if (ctx->dc_bios->funcs->get_lttpr_caps) {
enum bp_result bp_query_result;
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c
index de5e18c2a3ac..24e9ff65434d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.c
@@ -134,23 +134,10 @@ static void apg31_se_audio_setup(
/* Disable forced mem power off */
REG_UPDATE(APG_MEM_PWR, APG_MEM_PWR_FORCE, 0);
-
- apg31_enable(apg);
-}
-
-static void apg31_audio_mute_control(
- struct apg *apg,
- bool mute)
-{
- if (mute)
- apg31_disable(apg);
- else
- apg31_enable(apg);
}
static struct apg_funcs dcn31_apg_funcs = {
.se_audio_setup = apg31_se_audio_setup,
- .audio_mute_control = apg31_audio_mute_control,
.enable_apg = apg31_enable,
.disable_apg = apg31_disable,
};
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.h
index 24f568e120d8..1b81f6773c53 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_apg.h
@@ -84,10 +84,6 @@ struct apg_funcs {
unsigned int az_inst,
struct audio_info *audio_info);
- void (*audio_mute_control)(
- struct apg *apg,
- bool mute);
-
void (*enable_apg)(
struct apg *apg);
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c
index 814f401db3b3..16639bd03adf 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hpo_dp_stream_encoder.c
@@ -600,14 +600,6 @@ static void dcn31_hpo_dp_stream_enc_map_stream_to_link(
}
}
-static void dcn31_hpo_dp_stream_enc_mute_control(
- struct hpo_dp_stream_encoder *enc,
- bool mute)
-{
- ASSERT(enc->apg);
- enc->apg->funcs->audio_mute_control(enc->apg, mute);
-}
-
static void dcn31_hpo_dp_stream_enc_audio_setup(
struct hpo_dp_stream_encoder *enc,
unsigned int az_inst,
@@ -726,7 +718,6 @@ static const struct hpo_dp_stream_encoder_funcs dcn30_str_enc_funcs = {
.stop_dp_info_packets = dcn31_hpo_dp_stream_enc_stop_dp_info_packets,
.dp_set_dsc_pps_info_packet = dcn31_hpo_dp_stream_enc_set_dsc_pps_info_packet,
.map_stream_to_link = dcn31_hpo_dp_stream_enc_map_stream_to_link,
- .audio_mute_control = dcn31_hpo_dp_stream_enc_mute_control,
.dp_audio_setup = dcn31_hpo_dp_stream_enc_audio_setup,
.dp_audio_enable = dcn31_hpo_dp_stream_enc_audio_enable,
.dp_audio_disable = dcn31_hpo_dp_stream_enc_audio_disable,
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 bdf101547484..4226a051df41 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
@@ -89,7 +89,8 @@ static void enable_memory_low_power(struct dc *dc)
REG_UPDATE(MMHUBBUB_MEM_PWR_CNTL, VGA_MEM_PWR_FORCE, 1);
}
- if (dc->debug.enable_mem_low_power.bits.mpc)
+ if (dc->debug.enable_mem_low_power.bits.mpc &&
+ dc->res_pool->mpc->funcs->set_mpc_mem_lp_mode)
dc->res_pool->mpc->funcs->set_mpc_mem_lp_mode(dc->res_pool->mpc);
@@ -141,7 +142,8 @@ void dcn31_init_hw(struct dc *dc)
if (!dcb->funcs->is_accelerated_mode(dcb)) {
hws->funcs.bios_golden_init(dc);
- hws->funcs.disable_vga(dc->hwseq);
+ if (hws->funcs.disable_vga)
+ hws->funcs.disable_vga(dc->hwseq);
}
// Initialize the dccg
if (res_pool->dccg->funcs->dccg_init)
@@ -621,3 +623,43 @@ void dcn31_setup_hpo_hw_control(const struct dce_hwseq *hws, bool enable)
if (hws->ctx->dc->debug.hpo_optimization)
REG_UPDATE(HPO_TOP_HW_CONTROL, HPO_IO_EN, !!enable);
}
+void dcn31_set_drr(struct pipe_ctx **pipe_ctx,
+ int num_pipes, struct dc_crtc_timing_adjust adjust)
+{
+ int i = 0;
+ struct drr_params params = {0};
+ unsigned int event_triggers = 0x2;/*Bit[1]: OTG_TRIG_A*/
+ unsigned int num_frames = 2;
+ params.vertical_total_max = adjust.v_total_max;
+ params.vertical_total_min = adjust.v_total_min;
+ params.vertical_total_mid = adjust.v_total_mid;
+ params.vertical_total_mid_frame_num = adjust.v_total_mid_frame_num;
+ for (i = 0; i < num_pipes; i++) {
+ if ((pipe_ctx[i]->stream_res.tg != NULL) && pipe_ctx[i]->stream_res.tg->funcs) {
+ if (pipe_ctx[i]->stream_res.tg->funcs->set_drr)
+ pipe_ctx[i]->stream_res.tg->funcs->set_drr(
+ pipe_ctx[i]->stream_res.tg, &params);
+ if (adjust.v_total_max != 0 && adjust.v_total_min != 0)
+ if (pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control)
+ pipe_ctx[i]->stream_res.tg->funcs->set_static_screen_control(
+ pipe_ctx[i]->stream_res.tg,
+ event_triggers, num_frames);
+ }
+ }
+}
+void dcn31_set_static_screen_control(struct pipe_ctx **pipe_ctx,
+ int num_pipes, const struct dc_static_screen_params *params)
+{
+ unsigned int i;
+ unsigned int triggers = 0;
+ if (params->triggers.surface_update)
+ triggers |= 0x600;/*bit 9 and bit10 : 110 0000 0000*/
+ if (params->triggers.cursor_update)
+ triggers |= 0x10;/*bit4*/
+ if (params->triggers.force_trigger)
+ triggers |= 0x1;
+ for (i = 0; i < num_pipes; i++)
+ pipe_ctx[i]->stream_res.tg->funcs->
+ set_static_screen_control(pipe_ctx[i]->stream_res.tg,
+ triggers, params->num_frames);
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h
index edfc01d6ad73..e7e03a8722e0 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h
@@ -56,4 +56,8 @@ bool dcn31_is_abm_supported(struct dc *dc,
void dcn31_init_pipes(struct dc *dc, struct dc_state *context);
void dcn31_setup_hpo_hw_control(const struct dce_hwseq *hws, bool enable);
+void dcn31_set_static_screen_control(struct pipe_ctx **pipe_ctx,
+ int num_pipes, const struct dc_static_screen_params *params);
+void dcn31_set_drr(struct pipe_ctx **pipe_ctx,
+ int num_pipes, struct dc_crtc_timing_adjust adjust);
#endif /* __DC_HWSS_DCN31_H__ */
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..7c2da70ffe21 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c
@@ -64,9 +64,9 @@ static const struct hw_sequencer_funcs dcn31_funcs = {
.prepare_bandwidth = dcn20_prepare_bandwidth,
.optimize_bandwidth = dcn20_optimize_bandwidth,
.update_bandwidth = dcn20_update_bandwidth,
- .set_drr = dcn10_set_drr,
+ .set_drr = dcn31_set_drr,
.get_position = dcn10_get_position,
- .set_static_screen_control = dcn10_set_static_screen_control,
+ .set_static_screen_control = dcn31_set_static_screen_control,
.setup_stereo = dcn10_setup_stereo,
.set_avmute = dcn30_set_avmute,
.log_hw_state = dcn10_log_hw_state,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.c
index 63a677c8ee27..fe449f7aa771 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.c
@@ -40,6 +40,7 @@
#define FN(reg_name, field_name) \
optc1->tg_shift->field_name, optc1->tg_mask->field_name
+#define STATIC_SCREEN_EVENT_MASK_DRR_DOUBLE_BUFFER_UPDATE_EN 0x2000 /*bit 13*/
static void optc31_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
struct dc_crtc_timing *timing)
{
@@ -231,6 +232,32 @@ void optc3_init_odm(struct timing_generator *optc)
OPTC_MEM_SEL, 0);
optc1->opp_count = 1;
}
+void optc31_set_static_screen_control(
+ struct timing_generator *optc,
+ uint32_t event_triggers,
+ uint32_t num_frames)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(optc);
+ uint32_t framecount;
+ uint32_t events;
+
+ if (num_frames > 0xFF)
+ num_frames = 0xFF;
+ REG_GET_2(OTG_STATIC_SCREEN_CONTROL,
+ OTG_STATIC_SCREEN_EVENT_MASK, &events,
+ OTG_STATIC_SCREEN_FRAME_COUNT, &framecount);
+
+ if (events == event_triggers && num_frames == framecount)
+ return;
+ if ((event_triggers & STATIC_SCREEN_EVENT_MASK_DRR_DOUBLE_BUFFER_UPDATE_EN)
+ != 0)
+ event_triggers = event_triggers &
+ ~STATIC_SCREEN_EVENT_MASK_DRR_DOUBLE_BUFFER_UPDATE_EN;
+
+ REG_UPDATE_2(OTG_STATIC_SCREEN_CONTROL,
+ OTG_STATIC_SCREEN_EVENT_MASK, event_triggers,
+ OTG_STATIC_SCREEN_FRAME_COUNT, num_frames);
+}
static struct timing_generator_funcs dcn31_tg_funcs = {
.validate_timing = optc1_validate_timing,
@@ -266,7 +293,7 @@ static struct timing_generator_funcs dcn31_tg_funcs = {
.set_drr = optc31_set_drr,
.get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal,
.set_vtotal_min_max = optc1_set_vtotal_min_max,
- .set_static_screen_control = optc1_set_static_screen_control,
+ .set_static_screen_control = optc31_set_static_screen_control,
.program_stereo = optc1_program_stereo,
.is_stereo_left_eye = optc1_is_stereo_left_eye,
.tg_init = optc3_tg_init,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.h
index 30b81a448ce2..5fc6c63580d7 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_optc.h
@@ -263,5 +263,8 @@ bool optc31_immediate_disable_crtc(struct timing_generator *optc);
void optc31_set_drr(struct timing_generator *optc, const struct drr_params *params);
void optc3_init_odm(struct timing_generator *optc);
-
+void optc31_set_static_screen_control(
+ struct timing_generator *optc,
+ uint32_t event_triggers,
+ uint32_t num_frames);
#endif /* __DC_OPTC_DCN31_H__ */
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 fddc21a5a04c..3ca517dcc82d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
@@ -119,8 +119,6 @@ enum dcn31_clk_src_array_id {
*/
/* DCN */
-/* TODO awful hack. fixup dcn20_dwb.h */
-#undef BASE_INNER
#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
#define BASE(seg) BASE_INNER(seg)
@@ -153,6 +151,9 @@ enum dcn31_clk_src_array_id {
.reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \
reg ## block ## id ## _ ## temp_name
+#define SF_DWB2(reg_name, block, id, field_name, post_fix) \
+ .field_name = reg_name ## __ ## field_name ## post_fix
+
#define DCCG_SRII(reg_name, block, id)\
.block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
reg ## block ## id ## _ ## reg_name
@@ -911,6 +912,10 @@ static const struct dc_debug_options debug_defaults_diags = {
};
static const struct dc_panel_config panel_config_defaults = {
+ .psr = {
+ .disable_psr = false,
+ .disallow_psrsu = false,
+ },
.ilr = {
.optimize_edp_link_rate = true,
},
@@ -1625,6 +1630,7 @@ static struct clock_source *dcn31_clock_source_create(
return &clk_src->base;
}
+ kfree(clk_src);
BREAK_TO_DEBUGGER();
return NULL;
}
@@ -1634,6 +1640,31 @@ static bool is_dual_plane(enum surface_pixel_format format)
return format >= SURFACE_PIXEL_FORMAT_VIDEO_BEGIN || format == SURFACE_PIXEL_FORMAT_GRPH_RGBE_ALPHA;
}
+int dcn31x_populate_dml_pipes_from_context(struct dc *dc,
+ struct dc_state *context,
+ display_e2e_pipe_params_st *pipes,
+ bool fast_validate)
+{
+ uint32_t pipe_cnt;
+ int i;
+
+ dc_assert_fp_enabled();
+
+ pipe_cnt = dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate);
+
+ for (i = 0; i < pipe_cnt; i++) {
+ pipes[i].pipe.src.gpuvm = 1;
+ if (dc->debug.dml_hostvm_override == DML_HOSTVM_NO_OVERRIDE) {
+ //pipes[pipe_cnt].pipe.src.hostvm = dc->res_pool->hubbub->riommu_active;
+ pipes[i].pipe.src.hostvm = dc->vm_pa_config.is_hvm_enabled;
+ } else if (dc->debug.dml_hostvm_override == DML_HOSTVM_OVERRIDE_FALSE)
+ pipes[i].pipe.src.hostvm = false;
+ else if (dc->debug.dml_hostvm_override == DML_HOSTVM_OVERRIDE_TRUE)
+ pipes[i].pipe.src.hostvm = true;
+ }
+ return pipe_cnt;
+}
+
int dcn31_populate_dml_pipes_from_context(
struct dc *dc, struct dc_state *context,
display_e2e_pipe_params_st *pipes,
@@ -1645,7 +1676,7 @@ int dcn31_populate_dml_pipes_from_context(
bool upscaled = false;
DC_FP_START();
- dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate);
+ 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++) {
@@ -1675,12 +1706,6 @@ int dcn31_populate_dml_pipes_from_context(
dcn31_zero_pipe_dcc_fraction(pipes, pipe_cnt);
DC_FP_END();
- if (dc->debug.dml_hostvm_override == DML_HOSTVM_NO_OVERRIDE)
- pipes[pipe_cnt].pipe.src.hostvm = dc->res_pool->hubbub->riommu_active;
- else if (dc->debug.dml_hostvm_override == DML_HOSTVM_OVERRIDE_FALSE)
- pipes[pipe_cnt].pipe.src.hostvm = false;
- else if (dc->debug.dml_hostvm_override == DML_HOSTVM_OVERRIDE_TRUE)
- pipes[pipe_cnt].pipe.src.hostvm = true;
if (pipes[pipe_cnt].dout.dsc_enable) {
switch (timing->display_color_depth) {
@@ -1898,6 +1923,8 @@ static bool dcn31_resource_construct(
dc->caps.max_slave_rgb_planes = 2;
dc->caps.post_blend_color_processing = true;
dc->caps.force_dp_tps4_for_cp2520 = true;
+ if (dc->config.forceHBR2CP2520)
+ dc->caps.force_dp_tps4_for_cp2520 = false;
dc->caps.dp_hpo = true;
dc->caps.dp_hdmi21_pcon_support = true;
dc->caps.edp_dsc_support = true;
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 389a8938ee45..0b769ee71405 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_dccg.c
@@ -104,7 +104,7 @@ static void dccg314_set_pixel_rate_div(
}
dccg314_get_pixel_rate_div(dccg, otg_inst, &cur_k1, &cur_k2);
- if (k1 == PIXEL_RATE_DIV_NA || k2 == PIXEL_RATE_DIV_NA || (k1 == cur_k1 && k2 == cur_k2))
+ if (k1 == cur_k1 && k2 == cur_k2)
return;
switch (otg_inst) {
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 5b6c2d94ec71..31feb4b0edee 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_init.c
@@ -66,9 +66,9 @@ static const struct hw_sequencer_funcs dcn314_funcs = {
.prepare_bandwidth = dcn20_prepare_bandwidth,
.optimize_bandwidth = dcn20_optimize_bandwidth,
.update_bandwidth = dcn20_update_bandwidth,
- .set_drr = dcn10_set_drr,
+ .set_drr = dcn31_set_drr,
.get_position = dcn10_get_position,
- .set_static_screen_control = dcn10_set_static_screen_control,
+ .set_static_screen_control = dcn31_set_static_screen_control,
.setup_stereo = dcn10_setup_stereo,
.set_avmute = dcn30_set_avmute,
.log_hw_state = dcn10_log_hw_state,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.c b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.c
index 7dd36e402bac..41edbd64ea21 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_optc.c
@@ -228,7 +228,7 @@ static struct timing_generator_funcs dcn314_tg_funcs = {
.set_drr = optc31_set_drr,
.get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal,
.set_vtotal_min_max = optc1_set_vtotal_min_max,
- .set_static_screen_control = optc1_set_static_screen_control,
+ .set_static_screen_control = optc31_set_static_screen_control,
.program_stereo = optc1_program_stereo,
.is_stereo_left_eye = optc1_is_stereo_left_eye,
.tg_init = optc3_tg_init,
@@ -241,7 +241,6 @@ static struct timing_generator_funcs dcn314_tg_funcs = {
.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 = optc314_set_odm_combine,
.get_optc_source = optc2_get_optc_source,
.set_out_mux = optc3_set_out_mux,
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 9066c511a052..f9ea1e86707f 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
@@ -184,6 +184,9 @@ enum dcn31_clk_src_array_id {
.reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \
reg ## block ## id ## _ ## temp_name
+#define SF_DWB2(reg_name, block, id, field_name, post_fix) \
+ .field_name = reg_name ## __ ## field_name ## post_fix
+
#define DCCG_SRII(reg_name, block, id)\
.block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
reg ## block ## id ## _ ## reg_name
@@ -883,6 +886,7 @@ static const struct dc_plane_cap plane_cap = {
static const struct dc_debug_options debug_defaults_drv = {
.disable_z10 = false,
.enable_z9_disable_interface = true,
+ .psr_skip_crtc_disable = true,
.disable_dmcu = true,
.force_abm_enable = false,
.timing_trace = false,
@@ -937,6 +941,10 @@ static const struct dc_debug_options debug_defaults_diags = {
};
static const struct dc_panel_config panel_config_defaults = {
+ .psr = {
+ .disable_psr = false,
+ .disallow_psrsu = false,
+ },
.ilr = {
.optimize_edp_link_rate = true,
},
@@ -1766,6 +1774,8 @@ static bool dcn314_resource_construct(
dc->caps.max_slave_rgb_planes = 2;
dc->caps.post_blend_color_processing = true;
dc->caps.force_dp_tps4_for_cp2520 = true;
+ if (dc->config.forceHBR2CP2520)
+ dc->caps.force_dp_tps4_for_cp2520 = false;
dc->caps.dp_hpo = true;
dc->caps.dp_hdmi21_pcon_support = true;
dc->caps.edp_dsc_support = true;
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 58746c437554..7887078c5f64 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c
@@ -151,8 +151,6 @@ enum dcn31_clk_src_array_id {
*/
/* DCN */
-/* TODO awful hack. fixup dcn20_dwb.h */
-#undef BASE_INNER
#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
#define BASE(seg) BASE_INNER(seg)
@@ -185,6 +183,9 @@ enum dcn31_clk_src_array_id {
.reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \
reg ## block ## id ## _ ## temp_name
+#define SF_DWB2(reg_name, block, id, field_name, post_fix) \
+ .field_name = reg_name ## __ ## field_name ## post_fix
+
#define DCCG_SRII(reg_name, block, id)\
.block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
reg ## block ## id ## _ ## reg_name
@@ -907,6 +908,10 @@ static const struct dc_debug_options debug_defaults_diags = {
};
static const struct dc_panel_config panel_config_defaults = {
+ .psr = {
+ .disable_psr = false,
+ .disallow_psrsu = false,
+ },
.ilr = {
.optimize_edp_link_rate = true,
},
@@ -1623,6 +1628,7 @@ static struct clock_source *dcn31_clock_source_create(
return &clk_src->base;
}
+ kfree(clk_src);
BREAK_TO_DEBUGGER();
return NULL;
}
@@ -1643,7 +1649,7 @@ static int dcn315_populate_dml_pipes_from_context(
const int max_usable_det = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes - DCN3_15_MIN_COMPBUF_SIZE_KB;
DC_FP_START();
- dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate);
+ 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++) {
@@ -1662,7 +1668,6 @@ static int dcn315_populate_dml_pipes_from_context(
pipes[pipe_cnt].pipe.src.immediate_flip = true;
pipes[pipe_cnt].pipe.src.unbounded_req_mode = false;
- pipes[pipe_cnt].pipe.src.gpuvm = true;
pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch;
pipes[pipe_cnt].pipe.src.dcc_rate = 3;
pipes[pipe_cnt].dout.dsc_input_bpc = 0;
@@ -1703,7 +1708,9 @@ static int dcn315_populate_dml_pipes_from_context(
dc->config.enable_4to1MPC = true;
context->bw_ctx.dml.ip.det_buffer_size_kbytes =
(max_usable_det / DCN3_15_CRB_SEGMENT_SIZE_KB / 4) * DCN3_15_CRB_SEGMENT_SIZE_KB;
- } else if (!is_dual_plane(pipe->plane_state->format) && pipe->plane_state->src_rect.width <= 5120) {
+ } else if (!is_dual_plane(pipe->plane_state->format)
+ && pipe->plane_state->src_rect.width <= 5120
+ && pipe->stream->timing.pix_clk_100hz < dcn_get_max_non_odm_pix_rate_100hz(&dc->dml.soc)) {
/* Limit to 5k max to avoid forced pipe split when there is not enough detile for swath */
context->bw_ctx.dml.ip.det_buffer_size_kbytes = 192;
pipes[0].pipe.src.unbounded_req_mode = true;
@@ -1779,6 +1786,8 @@ static bool dcn315_resource_construct(
dc->caps.max_slave_rgb_planes = 2;
dc->caps.post_blend_color_processing = true;
dc->caps.force_dp_tps4_for_cp2520 = true;
+ if (dc->config.forceHBR2CP2520)
+ dc->caps.force_dp_tps4_for_cp2520 = false;
dc->caps.dp_hpo = true;
dc->caps.dp_hdmi21_pcon_support = true;
dc->caps.edp_dsc_support = true;
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 6b40a11ac83a..b4d5076e124c 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c
@@ -142,8 +142,6 @@ enum dcn31_clk_src_array_id {
*/
/* DCN */
-/* TODO awful hack. fixup dcn20_dwb.h */
-#undef BASE_INNER
#define BASE_INNER(seg) DCN_BASE__INST0_SEG ## seg
#define BASE(seg) BASE_INNER(seg)
@@ -176,6 +174,9 @@ enum dcn31_clk_src_array_id {
.reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \
reg ## block ## id ## _ ## temp_name
+#define SF_DWB2(reg_name, block, id, field_name, post_fix) \
+ .field_name = reg_name ## __ ## field_name ## post_fix
+
#define DCCG_SRII(reg_name, block, id)\
.block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
reg ## block ## id ## _ ## reg_name
@@ -906,6 +907,10 @@ static const struct dc_debug_options debug_defaults_diags = {
};
static const struct dc_panel_config panel_config_defaults = {
+ .psr = {
+ .disable_psr = false,
+ .disallow_psrsu = false,
+ },
.ilr = {
.optimize_edp_link_rate = true,
},
@@ -1646,7 +1651,7 @@ static int dcn316_populate_dml_pipes_from_context(
const int max_usable_det = context->bw_ctx.dml.ip.config_return_buffer_size_in_kbytes - DCN3_16_MIN_COMPBUF_SIZE_KB;
DC_FP_START();
- dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate);
+ 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++) {
@@ -1665,7 +1670,6 @@ static int dcn316_populate_dml_pipes_from_context(
pipes[pipe_cnt].pipe.src.immediate_flip = true;
pipes[pipe_cnt].pipe.src.unbounded_req_mode = false;
- pipes[pipe_cnt].pipe.src.gpuvm = true;
pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch;
pipes[pipe_cnt].pipe.src.dcc_rate = 3;
pipes[pipe_cnt].dout.dsc_input_bpc = 0;
@@ -1781,6 +1785,8 @@ static bool dcn316_resource_construct(
dc->caps.max_slave_rgb_planes = 2;
dc->caps.post_blend_color_processing = true;
dc->caps.force_dp_tps4_for_cp2520 = true;
+ if (dc->config.forceHBR2CP2520)
+ dc->caps.force_dp_tps4_for_cp2520 = false;
dc->caps.dp_hpo = true;
dc->caps.dp_hdmi21_pcon_support = true;
dc->caps.edp_dsc_support = true;
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 df4f25119142..e4472c6be6c3 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c
@@ -225,11 +225,7 @@ static void dccg32_set_dtbclk_dto(
} else {
REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst],
DTBCLK_DTO_ENABLE[params->otg_inst], 0,
- PIPE_DTO_SRC_SEL[params->otg_inst], 1);
- if (params->is_hdmi)
- REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
- PIPE_DTO_SRC_SEL[params->otg_inst], 0);
-
+ PIPE_DTO_SRC_SEL[params->otg_inst], params->is_hdmi ? 0 : 1);
REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0);
REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0);
}
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 9fbb72369c10..5947c2cb0f30 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.c
@@ -41,6 +41,10 @@
#define FN(reg_name, field_name) \
hubbub2->shifts->field_name, hubbub2->masks->field_name
+/**
+ * @DCN32_CRB_SEGMENT_SIZE_KB: Maximum Configurable Return Buffer size for
+ * DCN32
+ */
#define DCN32_CRB_SEGMENT_SIZE_KB 64
static void dcn32_init_crb(struct hubbub *hubbub)
@@ -68,6 +72,23 @@ static void dcn32_init_crb(struct hubbub *hubbub)
REG_UPDATE(DCHUBBUB_DEBUG_CTRL_0, DET_DEPTH, 0x47F);
}
+void hubbub32_set_request_limit(struct hubbub *hubbub, int memory_channel_count, int words_per_channel)
+{
+ struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+
+ uint32_t request_limit = 3 * memory_channel_count * words_per_channel / 4;
+
+ ASSERT((request_limit & (~0xFFF)) == 0); //field is only 24 bits long
+ ASSERT(request_limit > 0); //field is only 24 bits long
+
+ if (request_limit > 0xFFF)
+ request_limit = 0xFFF;
+
+ if (request_limit > 0)
+ REG_UPDATE(SDPIF_REQUEST_RATE_LIMIT, SDPIF_REQUEST_RATE_LIMIT, request_limit);
+}
+
+
void dcn32_program_det_size(struct hubbub *hubbub, int hubp_inst, unsigned int det_buffer_size_in_kbyte)
{
struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
@@ -945,6 +966,7 @@ static const struct hubbub_funcs hubbub32_funcs = {
.init_crb = dcn32_init_crb,
.hubbub_read_state = hubbub2_read_state,
.force_usr_retraining_allow = hubbub32_force_usr_retraining_allow,
+ .set_request_limit = hubbub32_set_request_limit
};
void hubbub32_construct(struct dcn20_hubbub *hubbub2,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h
index cda94e0e31bf..786f9ce07f92 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hubbub.h
@@ -82,7 +82,8 @@
SR(DCN_VM_FAULT_ADDR_MSB),\
SR(DCN_VM_FAULT_ADDR_LSB),\
SR(DCN_VM_FAULT_CNTL),\
- SR(DCN_VM_FAULT_STATUS)
+ SR(DCN_VM_FAULT_STATUS),\
+ SR(SDPIF_REQUEST_RATE_LIMIT)
#define HUBBUB_MASK_SH_LIST_DCN32(mask_sh)\
HUBBUB_SF(DCHUBBUB_GLOBAL_TIMER_CNTL, DCHUBBUB_GLOBAL_TIMER_ENABLE, mask_sh), \
@@ -159,7 +160,8 @@
HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_VMID, mask_sh), \
HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_TABLE_LEVEL, mask_sh), \
HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_PIPE, mask_sh), \
- HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_INTERRUPT_STATUS, mask_sh)
+ HUBBUB_SF(DCN_VM_FAULT_STATUS, DCN_VM_ERROR_INTERRUPT_STATUS, mask_sh),\
+ HUBBUB_SF(SDPIF_REQUEST_RATE_LIMIT, SDPIF_REQUEST_RATE_LIMIT, mask_sh)
bool hubbub32_program_urgent_watermarks(
struct hubbub *hubbub,
@@ -200,4 +202,6 @@ void hubbub32_construct(struct dcn20_hubbub *hubbub2,
int pixel_chunk_size_kb,
int config_return_buffer_size_kb);
+void hubbub32_set_request_limit(struct hubbub *hubbub, int umc_count, int words_per_umc);
+
#endif
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 d0b46a3e0155..b8767be1e4c5 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.c
@@ -227,8 +227,13 @@ static uint32_t dcn32_calculate_cab_allocation(struct dc *dc, struct dc_state *c
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &dc->current_state->res_ctx.pipe_ctx[i];
+ /* If PSR is supported on an eDP panel that's connected, but that panel is
+ * not in PSR at the time of trying to enter MALL SS, we have to include it
+ * in the static screen CAB calculation
+ */
if (!pipe->stream || !pipe->plane_state ||
- pipe->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED ||
+ (pipe->stream->link->psr_settings.psr_version != DC_PSR_VERSION_UNSUPPORTED &&
+ pipe->stream->link->psr_settings.psr_allow_active) ||
pipe->stream->mall_stream_config.type == SUBVP_PHANTOM)
continue;
@@ -257,11 +262,11 @@ static uint32_t dcn32_calculate_cab_allocation(struct dc *dc, struct dc_state *c
num_mblks = ((mall_alloc_width_blk_aligned + mblk_width - 1) / mblk_width) *
((mall_alloc_height_blk_aligned + mblk_height - 1) / mblk_height);
- /* For DCC:
- * meta_num_mblk = CEILING(full_mblk_width_ub_l*full_mblk_height_ub_l*Bpe/256/mblk_bytes, 1)
+ /*For DCC:
+ * meta_num_mblk = CEILING(meta_pitch*full_vp_height*Bpe/256/mblk_bytes, 1)
*/
if (pipe->plane_state->dcc.enable)
- num_mblks += (mall_alloc_width_blk_aligned * mall_alloc_width_blk_aligned * bytes_per_pixel +
+ num_mblks += (pipe->plane_state->dcc.meta_pitch * pipe->plane_res.scl_data.viewport.height * bytes_per_pixel +
(256 * DCN3_2_MALL_MBLK_SIZE_BYTES) - 1) / (256 * DCN3_2_MALL_MBLK_SIZE_BYTES);
bytes_in_mall = num_mblks * DCN3_2_MALL_MBLK_SIZE_BYTES;
@@ -311,8 +316,8 @@ static uint32_t dcn32_calculate_cab_allocation(struct dc *dc, struct dc_state *c
cache_lines_used += (((cursor_size + DCN3_2_MALL_MBLK_SIZE_BYTES - 1) /
DCN3_2_MALL_MBLK_SIZE_BYTES) * DCN3_2_MALL_MBLK_SIZE_BYTES) /
dc->caps.cache_line_size + 2;
+ break;
}
- break;
}
}
@@ -698,11 +703,7 @@ void dcn32_subvp_update_force_pstate(struct dc *dc, struct dc_state *context)
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
- // For SubVP + DRR, also force disallow on the DRR pipe
- // (We will force allow in the DMUB sequence -- some DRR timings by default won't allow P-State so we have
- // to force once the vblank is stretched).
- if (pipe->stream && pipe->plane_state && (pipe->stream->mall_stream_config.type == SUBVP_MAIN ||
- (pipe->stream->mall_stream_config.type == SUBVP_NONE && pipe->stream->ignore_msa_timing_param))) {
+ if (pipe->stream && pipe->plane_state && (pipe->stream->mall_stream_config.type == SUBVP_MAIN)) {
struct hubp *hubp = pipe->plane_res.hubp;
if (hubp && hubp->funcs->hubp_update_force_pstate_disallow)
@@ -780,6 +781,10 @@ void dcn32_program_mall_pipe_config(struct dc *dc, struct dc_state *context)
if (hws && hws->funcs.update_mall_sel)
hws->funcs.update_mall_sel(dc, context);
+ //update subvp force pstate
+ if (hws && hws->funcs.subvp_update_force_pstate)
+ dc->hwseq->funcs.subvp_update_force_pstate(dc, context);
+
// Program FORCE_ONE_ROW_FOR_FRAME and CURSOR_REQ_MODE for main subvp pipes
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
@@ -980,15 +985,14 @@ void dcn32_init_hw(struct dc *dc)
if (dc->res_pool->hubbub->funcs->init_crb)
dc->res_pool->hubbub->funcs->init_crb(dc->res_pool->hubbub);
+ if (dc->res_pool->hubbub->funcs->set_request_limit && dc->config.sdpif_request_limit_words_per_umc > 0)
+ dc->res_pool->hubbub->funcs->set_request_limit(dc->res_pool->hubbub, dc->ctx->dc_bios->vram_info.num_chans, dc->config.sdpif_request_limit_words_per_umc);
+
// Get DMCUB capabilities
if (dc->ctx->dmub_srv) {
dc_dmub_srv_query_caps_cmd(dc->ctx->dmub_srv->dmub);
dc->caps.dmub_caps.psr = dc->ctx->dmub_srv->dmub->feature_caps.psr;
}
-
- /* Enable support for ODM and windowed MPO if policy flag is set */
- if (dc->debug.enable_single_display_2to1_odm_policy)
- dc->config.enable_windowed_mpo_odm = true;
}
static int calc_mpc_flow_ctrl_cnt(const struct dc_stream_state *stream,
@@ -1180,7 +1184,7 @@ unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsign
*k2_div = PIXEL_RATE_DIV_BY_2;
else
*k2_div = PIXEL_RATE_DIV_BY_4;
- } else if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
+ } else if (dc_is_dp_signal(pipe_ctx->stream->signal) || dc_is_virtual_signal(pipe_ctx->stream->signal)) {
if (two_pix_per_container) {
*k1_div = PIXEL_RATE_DIV_BY_1;
*k2_div = PIXEL_RATE_DIV_BY_2;
@@ -1365,6 +1369,33 @@ void dcn32_update_phantom_vp_position(struct dc *dc,
}
}
+/* Treat the phantom pipe as if it needs to be fully enabled.
+ * If the pipe was previously in use but not phantom, it would
+ * have been disabled earlier in the sequence so we need to run
+ * the full enable sequence.
+ */
+void dcn32_apply_update_flags_for_phantom(struct pipe_ctx *phantom_pipe)
+{
+ phantom_pipe->update_flags.raw = 0;
+ if (phantom_pipe->stream && phantom_pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
+ if (phantom_pipe->stream && phantom_pipe->plane_state) {
+ phantom_pipe->update_flags.bits.enable = 1;
+ phantom_pipe->update_flags.bits.mpcc = 1;
+ phantom_pipe->update_flags.bits.dppclk = 1;
+ phantom_pipe->update_flags.bits.hubp_interdependent = 1;
+ phantom_pipe->update_flags.bits.hubp_rq_dlg_ttu = 1;
+ phantom_pipe->update_flags.bits.gamut_remap = 1;
+ phantom_pipe->update_flags.bits.scaler = 1;
+ phantom_pipe->update_flags.bits.viewport = 1;
+ phantom_pipe->update_flags.bits.det_size = 1;
+ if (!phantom_pipe->top_pipe && !phantom_pipe->prev_odm_pipe) {
+ phantom_pipe->update_flags.bits.odm = 1;
+ phantom_pipe->update_flags.bits.global_sync = 1;
+ }
+ }
+ }
+}
+
bool dcn32_dsc_pg_status(
struct dce_hwseq *hws,
unsigned int dsc_inst)
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 ac3657a5b9ea..7de36529cf99 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_hwseq.h
@@ -92,6 +92,8 @@ void dcn32_update_phantom_vp_position(struct dc *dc,
struct dc_state *context,
struct pipe_ctx *phantom_pipe);
+void dcn32_apply_update_flags_for_phantom(struct pipe_ctx *phantom_pipe);
+
bool dcn32_dsc_pg_status(
struct dce_hwseq *hws,
unsigned int dsc_inst);
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 45a949ba6f3f..dc4649458567 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_init.c
@@ -110,6 +110,7 @@ static const struct hw_sequencer_funcs dcn32_funcs = {
.update_visual_confirm_color = dcn20_update_visual_confirm_color,
.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,
};
static const struct hwseq_private_funcs dcn32_private_funcs = {
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.c
index 41b0baf8e183..c3b089ba511a 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mmhubbub.c
@@ -211,7 +211,7 @@ static void mmhubbub32_config_mcif_arb(struct mcif_wb *mcif_wb,
REG_UPDATE(MCIF_WB_ARBITRATION_CONTROL, MCIF_WB_CLIENT_ARBITRATION_SLICE, params->arbitration_slice);
}
-const struct mcif_wb_funcs dcn32_mmhubbub_funcs = {
+static const struct mcif_wb_funcs dcn32_mmhubbub_funcs = {
.warmup_mcif = mmhubbub32_warmup_mcif,
.enable_mcif = mmhubbub2_enable_mcif,
.disable_mcif = mmhubbub2_disable_mcif,
diff --git a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c
index 4edd0655965b..206a5ddbaf6d 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_mpc.c
@@ -982,7 +982,7 @@ static bool mpc32_program_3dlut(
return true;
}
-const struct mpc_funcs dcn32_mpc_funcs = {
+static const struct mpc_funcs dcn32_mpc_funcs = {
.read_mpcc_state = mpc1_read_mpcc_state,
.insert_plane = mpc1_insert_plane,
.remove_mpcc = mpc1_remove_mpcc,
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 2b33eeb213e2..2ee798965bc2 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_optc.c
@@ -167,6 +167,13 @@ static void optc32_phantom_crtc_post_enable(struct timing_generator *optc)
REG_WAIT(OTG_CLOCK_CONTROL, OTG_BUSY, 0, 1, 100000);
}
+static void optc32_disable_phantom_otg(struct timing_generator *optc)
+{
+ struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+ REG_UPDATE(OTG_CONTROL, OTG_MASTER_EN, 0);
+}
+
static void optc32_set_odm_bypass(struct timing_generator *optc,
const struct dc_crtc_timing *dc_crtc_timing)
{
@@ -260,6 +267,7 @@ static struct timing_generator_funcs dcn32_tg_funcs = {
.enable_crtc = optc32_enable_crtc,
.disable_crtc = optc32_disable_crtc,
.phantom_crtc_post_enable = optc32_phantom_crtc_post_enable,
+ .disable_phantom_crtc = optc32_disable_phantom_otg,
/* used by enable_timing_synchronization. Not need for FPGA */
.is_counter_moving = optc1_is_counter_moving,
.get_position = optc1_get_position,
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 d1598e3131f6..e4dbc8353ea3 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.c
@@ -106,8 +106,6 @@ enum dcn32_clk_src_array_id {
*/
/* DCN */
-/* TODO awful hack. fixup dcn20_dwb.h */
-#undef BASE_INNER
#define BASE_INNER(seg) ctx->dcn_reg_offsets[seg]
#define BASE(seg) BASE_INNER(seg)
@@ -167,6 +165,9 @@ enum dcn32_clk_src_array_id {
REG_STRUCT.reg_name[id] = BASE(reg ## block ## id ## _ ## temp_name ## _BASE_IDX) + \
reg ## block ## id ## _ ## temp_name
+#define SF_DWB2(reg_name, block, id, field_name, post_fix) \
+ .field_name = reg_name ## __ ## field_name ## post_fix
+
#define DCCG_SRII(reg_name, block, id)\
REG_STRUCT.block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
reg ## block ## id ## _ ## reg_name
@@ -722,7 +723,7 @@ static const struct dc_debug_options debug_defaults_drv = {
/* Must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions*/
.enable_double_buffered_dsc_pg_support = true,
.enable_dp_dig_pixel_rate_div_policy = 1,
- .allow_sw_cursor_fallback = false,
+ .allow_sw_cursor_fallback = false, // Linux can't do SW cursor "fallback"
.alloc_extra_way_for_cursor = true,
.min_prefetch_in_strobe_ns = 60000, // 60us
};
@@ -830,6 +831,7 @@ static struct clock_source *dcn32_clock_source_create(
return &clk_src->base;
}
+ kfree(clk_src);
BREAK_TO_DEBUGGER();
return NULL;
}
@@ -1679,7 +1681,7 @@ static void dcn32_enable_phantom_plane(struct dc *dc,
/* Shadow pipe has small viewport. */
phantom_plane->clip_rect.y = 0;
- phantom_plane->clip_rect.height = phantom_stream->timing.v_addressable;
+ phantom_plane->clip_rect.height = phantom_stream->src.height;
phantom_plane->is_phantom = true;
@@ -1719,8 +1721,29 @@ static struct dc_stream_state *dcn32_enable_phantom_stream(struct dc *dc,
return phantom_stream;
}
+void dcn32_retain_phantom_pipes(struct dc *dc, struct dc_state *context)
+{
+ int i;
+ struct dc_plane_state *phantom_plane = NULL;
+ struct dc_stream_state *phantom_stream = NULL;
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++) {
+ struct pipe_ctx *pipe = &context->res_ctx.pipe_ctx[i];
+
+ if (!pipe->top_pipe && !pipe->prev_odm_pipe &&
+ pipe->plane_state && pipe->stream &&
+ pipe->stream->mall_stream_config.type == SUBVP_PHANTOM) {
+ phantom_plane = pipe->plane_state;
+ phantom_stream = pipe->stream;
+
+ dc_plane_state_retain(phantom_plane);
+ dc_stream_retain(phantom_stream);
+ }
+ }
+}
+
// return true if removed piped from ctx, false otherwise
-bool dcn32_remove_phantom_pipes(struct dc *dc, struct dc_state *context)
+bool dcn32_remove_phantom_pipes(struct dc *dc, struct dc_state *context, bool fast_update)
{
int i;
bool removed_pipe = false;
@@ -1747,14 +1770,23 @@ bool dcn32_remove_phantom_pipes(struct dc *dc, struct dc_state *context)
removed_pipe = true;
}
- // Clear all phantom stream info
- if (pipe->stream) {
- pipe->stream->mall_stream_config.type = SUBVP_NONE;
- pipe->stream->mall_stream_config.paired_stream = NULL;
- }
+ /* For non-full updates, a shallow copy of the current state
+ * is created. In this case we don't want to erase the current
+ * state (there can be 2 HIRQL threads, one in flip, and one in
+ * checkMPO) that can cause a race condition.
+ *
+ * This is just a workaround, needs a proper fix.
+ */
+ if (!fast_update) {
+ // Clear all phantom stream info
+ if (pipe->stream) {
+ pipe->stream->mall_stream_config.type = SUBVP_NONE;
+ pipe->stream->mall_stream_config.paired_stream = NULL;
+ }
- if (pipe->plane_state) {
- pipe->plane_state->is_phantom = false;
+ if (pipe->plane_state) {
+ pipe->plane_state->is_phantom = false;
+ }
}
}
return removed_pipe;
@@ -1901,7 +1933,7 @@ int dcn32_populate_dml_pipes_from_context(
pipes[pipe_cnt].pipe.dest.odm_combine_policy = dm_odm_combine_policy_dal;
if (context->stream_count == 1 &&
- context->stream_status[0].plane_count <= 1 &&
+ context->stream_status[0].plane_count == 1 &&
!dc_is_hdmi_signal(res_ctx->pipe_ctx[i].stream->signal) &&
is_h_timing_divisible_by_2(res_ctx->pipe_ctx[i].stream) &&
pipe->stream->timing.pix_clk_100hz * 100 > DCN3_2_VMIN_DISPCLK_HZ &&
@@ -1919,30 +1951,36 @@ int dcn32_populate_dml_pipes_from_context(
timing = &pipe->stream->timing;
pipes[pipe_cnt].pipe.src.gpuvm = true;
- pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_luma = 0;
- pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_chroma = 0;
+ DC_FP_START();
+ dcn32_zero_pipe_dcc_fraction(pipes, pipe_cnt);
+ DC_FP_END();
pipes[pipe_cnt].pipe.dest.vfront_porch = timing->v_front_porch;
pipes[pipe_cnt].pipe.src.gpuvm_min_page_size_kbytes = 256; // according to spreadsheet
pipes[pipe_cnt].pipe.src.unbounded_req_mode = false;
pipes[pipe_cnt].pipe.scale_ratio_depth.lb_depth = dm_lb_19;
- switch (pipe->stream->mall_stream_config.type) {
- case SUBVP_MAIN:
- pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_sub_viewport;
- subvp_in_use = true;
- break;
- case SUBVP_PHANTOM:
- pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_phantom_pipe;
- pipes[pipe_cnt].pipe.src.use_mall_for_static_screen = dm_use_mall_static_screen_disable;
- // Disallow unbounded req for SubVP according to DCHUB programming guide
- pipes[pipe_cnt].pipe.src.unbounded_req_mode = false;
- break;
- case SUBVP_NONE:
- pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_disable;
- pipes[pipe_cnt].pipe.src.use_mall_for_static_screen = dm_use_mall_static_screen_disable;
- break;
- default:
- break;
+ /* Only populate DML input with subvp info for full updates.
+ * This is just a workaround -- needs a proper fix.
+ */
+ if (!fast_validate) {
+ switch (pipe->stream->mall_stream_config.type) {
+ case SUBVP_MAIN:
+ pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_sub_viewport;
+ subvp_in_use = true;
+ break;
+ case SUBVP_PHANTOM:
+ pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_phantom_pipe;
+ pipes[pipe_cnt].pipe.src.use_mall_for_static_screen = dm_use_mall_static_screen_disable;
+ // Disallow unbounded req for SubVP according to DCHUB programming guide
+ pipes[pipe_cnt].pipe.src.unbounded_req_mode = false;
+ break;
+ case SUBVP_NONE:
+ pipes[pipe_cnt].pipe.src.use_mall_for_pstate_change = dm_use_mall_pstate_change_disable;
+ pipes[pipe_cnt].pipe.src.use_mall_for_static_screen = dm_use_mall_static_screen_disable;
+ break;
+ default:
+ break;
+ }
}
pipes[pipe_cnt].dout.dsc_input_bpc = 0;
@@ -2030,6 +2068,9 @@ static struct resource_funcs dcn32_res_pool_funcs = {
.update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
.add_phantom_pipes = dcn32_add_phantom_pipes,
.remove_phantom_pipes = dcn32_remove_phantom_pipes,
+ .retain_phantom_pipes = dcn32_retain_phantom_pipes,
+ .save_mall_state = dcn32_save_mall_state,
+ .restore_mall_state = dcn32_restore_mall_state,
};
@@ -2116,16 +2157,20 @@ static bool dcn32_resource_construct(
dc->caps.cache_num_ways = 16;
dc->caps.max_cab_allocation_bytes = 67108864; // 64MB = 1024 * 1024 * 64
dc->caps.subvp_fw_processing_delay_us = 15;
+ dc->caps.subvp_drr_max_vblank_margin_us = 40;
dc->caps.subvp_prefetch_end_to_mall_start_us = 15;
dc->caps.subvp_swath_height_margin_lines = 16;
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 = 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;
+ if (dc->config.forceHBR2CP2520)
+ dc->caps.force_dp_tps4_for_cp2520 = false;
dc->caps.dp_hpo = true;
dc->caps.dp_hdmi21_pcon_support = true;
dc->caps.edp_dsc_support = true;
@@ -2409,6 +2454,9 @@ static bool dcn32_resource_construct(
pool->base.oem_device = NULL;
}
+ if (ASICREV_IS_GC_11_0_3(dc->ctx->asic_id.hw_internal_rev) && (dc->config.sdpif_request_limit_words_per_umc == 0))
+ dc->config.sdpif_request_limit_words_per_umc = 16;
+
DC_FP_END();
return true;
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 f76120e67c16..13fbc574910b 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/dcn32/dcn32_resource.h
@@ -45,17 +45,6 @@
extern struct _vcs_dpi_ip_params_st dcn3_2_ip;
extern struct _vcs_dpi_soc_bounding_box_st dcn3_2_soc;
-/* Temp struct used to save and restore MALL config
- * during validation.
- *
- * TODO: Move MALL config into dc_state instead of stream struct
- * to avoid needing to save/restore.
- */
-struct mall_temp_config {
- struct mall_stream_config mall_stream_config[MAX_PIPES];
- bool is_phantom_plane[MAX_PIPES];
-};
-
struct dcn32_resource_pool {
struct resource_pool base;
};
@@ -81,6 +70,9 @@ bool dcn32_release_post_bldn_3dlut(
struct dc_transfer_func **shaper);
bool dcn32_remove_phantom_pipes(struct dc *dc,
+ struct dc_state *context, bool fast_update);
+
+void dcn32_retain_phantom_pipes(struct dc *dc,
struct dc_state *context);
void dcn32_add_phantom_pipes(struct dc *dc,
@@ -1244,7 +1236,8 @@ void dcn32_restore_mall_state(struct dc *dc,
SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C), \
SR(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D), \
SR(DCN_VM_FAULT_ADDR_MSB), SR(DCN_VM_FAULT_ADDR_LSB), \
- SR(DCN_VM_FAULT_CNTL), SR(DCN_VM_FAULT_STATUS) \
+ SR(DCN_VM_FAULT_CNTL), SR(DCN_VM_FAULT_STATUS), \
+ SR(SDPIF_REQUEST_RATE_LIMIT) \
)
/* DCCG */
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 fa3778849db1..783935c4e664 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
@@ -97,14 +97,14 @@ uint32_t dcn32_helper_calculate_num_ways_for_subvp(struct dc *dc, struct dc_stat
* FLOOR(vp_x_start, blk_width)
*/
full_vp_width_blk_aligned = ((pipe->plane_res.scl_data.viewport.x +
- pipe->plane_res.scl_data.viewport.width + mblk_width - 1) / mblk_width * mblk_width) +
+ pipe->plane_res.scl_data.viewport.width + mblk_width - 1) / mblk_width * mblk_width) -
(pipe->plane_res.scl_data.viewport.x / mblk_width * mblk_width);
/* full_vp_height_blk_aligned = FLOOR(vp_y_start + full_vp_height + blk_height - 1, blk_height) -
* FLOOR(vp_y_start, blk_height)
*/
full_vp_height_blk_aligned = ((pipe->plane_res.scl_data.viewport.y +
- full_vp_height + mblk_height - 1) / mblk_height * mblk_height) +
+ full_vp_height + mblk_height - 1) / mblk_height * mblk_height) -
(pipe->plane_res.scl_data.viewport.y / mblk_height * mblk_height);
/* mall_alloc_width_blk_aligned_l/c = full_vp_width_blk_aligned_l/c */
@@ -121,14 +121,19 @@ uint32_t dcn32_helper_calculate_num_ways_for_subvp(struct dc *dc, struct dc_stat
*/
num_mblks = ((mall_alloc_width_blk_aligned + mblk_width - 1) / mblk_width) *
((mall_alloc_height_blk_aligned + mblk_height - 1) / mblk_height);
+
+ /*For DCC:
+ * meta_num_mblk = CEILING(meta_pitch*full_vp_height*Bpe/256/mblk_bytes, 1)
+ */
+ if (pipe->plane_state->dcc.enable)
+ num_mblks += (pipe->plane_state->dcc.meta_pitch * pipe->plane_res.scl_data.viewport.height * bytes_per_pixel +
+ (256 * DCN3_2_MALL_MBLK_SIZE_BYTES) - 1) / (256 * DCN3_2_MALL_MBLK_SIZE_BYTES);
+
bytes_in_mall = num_mblks * DCN3_2_MALL_MBLK_SIZE_BYTES;
// cache lines used is total bytes / cache_line size. Add +2 for worst case alignment
// (MALL is 64-byte aligned)
cache_lines_per_plane = bytes_in_mall / dc->caps.cache_line_size + 2;
- /* For DCC divide by 256 */
- if (pipe->plane_state->dcc.enable)
- cache_lines_per_plane = cache_lines_per_plane + (cache_lines_per_plane / 256) + 1;
cache_lines_used += cache_lines_per_plane;
}
}
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 6292ac515d1a..d1f36df03c2e 100644
--- a/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/dcn321/dcn321_resource.c
@@ -109,8 +109,6 @@ enum dcn321_clk_src_array_id {
*/
/* DCN */
-/* TODO awful hack. fixup dcn20_dwb.h */
-#undef BASE_INNER
#define BASE_INNER(seg) ctx->dcn_reg_offsets[seg]
#define BASE(seg) BASE_INNER(seg)
@@ -174,6 +172,9 @@ enum dcn321_clk_src_array_id {
REG_STRUCT.block ## _ ## reg_name[id] = BASE(reg ## block ## id ## _ ## reg_name ## _BASE_IDX) + \
reg ## block ## id ## _ ## reg_name
+#define SF_DWB2(reg_name, block, id, field_name, post_fix) \
+ .field_name = reg_name ## __ ## field_name ## post_fix
+
#define VUPDATE_SRII(reg_name, block, id)\
REG_STRUCT.reg_name[id] = BASE(reg ## reg_name ## _ ## block ## id ## _BASE_IDX) + \
reg ## reg_name ## _ ## block ## id
@@ -720,7 +721,7 @@ static const struct dc_debug_options debug_defaults_drv = {
/*must match enable_single_display_2to1_odm_policy to support dynamic ODM transitions*/
.enable_double_buffered_dsc_pg_support = true,
.enable_dp_dig_pixel_rate_div_policy = 1,
- .allow_sw_cursor_fallback = false,
+ .allow_sw_cursor_fallback = false, // Linux can't do SW cursor "fallback"
.alloc_extra_way_for_cursor = true,
.min_prefetch_in_strobe_ns = 60000, // 60us
};
@@ -742,7 +743,7 @@ static const struct dc_debug_options debug_defaults_diags = {
.dmub_command_table = true,
.enable_tri_buf = true,
.use_max_lb = true,
- .force_disable_subvp = true
+ .force_disable_subvp = true,
};
@@ -829,6 +830,7 @@ static struct clock_source *dcn321_clock_source_create(
return &clk_src->base;
}
+ kfree(clk_src);
BREAK_TO_DEBUGGER();
return NULL;
}
@@ -1619,6 +1621,9 @@ static struct resource_funcs dcn321_res_pool_funcs = {
.update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
.add_phantom_pipes = dcn32_add_phantom_pipes,
.remove_phantom_pipes = dcn32_remove_phantom_pipes,
+ .retain_phantom_pipes = dcn32_retain_phantom_pipes,
+ .save_mall_state = dcn32_save_mall_state,
+ .restore_mall_state = dcn32_restore_mall_state,
};
@@ -1704,10 +1709,12 @@ static bool dcn321_resource_construct(
dc->caps.cache_num_ways = 16;
dc->caps.max_cab_allocation_bytes = 33554432; // 32MB = 1024 * 1024 * 32
dc->caps.subvp_fw_processing_delay_us = 15;
+ dc->caps.subvp_drr_max_vblank_margin_us = 40;
dc->caps.subvp_prefetch_end_to_mall_start_us = 15;
dc->caps.subvp_swath_height_margin_lines = 16;
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;
diff --git a/drivers/gpu/drm/amd/display/dc/dm_helpers.h b/drivers/gpu/drm/amd/display/dc/dm_helpers.h
index e3e5c39895a3..af1c50ed905a 100644
--- a/drivers/gpu/drm/amd/display/dc/dm_helpers.h
+++ b/drivers/gpu/drm/amd/display/dc/dm_helpers.h
@@ -116,6 +116,11 @@ bool dm_helpers_dp_mst_start_top_mgr(
bool dm_helpers_dp_mst_stop_top_mgr(
struct dc_context *ctx,
struct dc_link *link);
+
+void dm_helpers_dp_mst_update_branch_bandwidth(
+ struct dc_context *ctx,
+ struct dc_link *link);
+
/**
* OS specific aux read callback.
*/
diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile
index ca7d24000621..0ecea87cf48f 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/Makefile
+++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile
@@ -33,6 +33,10 @@ ifdef CONFIG_PPC64
dml_ccflags := -mhard-float -maltivec
endif
+ifdef CONFIG_ARM64
+dml_rcflags := -mgeneral-regs-only
+endif
+
ifdef CONFIG_CC_IS_GCC
ifneq ($(call gcc-min-version, 70100),y)
IS_OLD_GCC = 1
@@ -55,8 +59,6 @@ frame_warn_flag := -Wframe-larger-than=2048
endif
CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags)
-
-ifdef CONFIG_DRM_AMD_DC_DCN
CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/dcn10/dcn10_fpu.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/dcn20/dcn20_fpu.o := $(dml_ccflags)
@@ -88,7 +90,6 @@ CFLAGS_$(AMDDALPATH)/dc/dml/calcs/dcn_calcs.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_auto.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_math.o := $(dml_ccflags) -Wno-tautological-compare
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_rcflags)
-CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn2x/dcn2x.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_rq_dlg_calc_20.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/display_mode_vba_20v2.o := $(dml_rcflags)
@@ -105,7 +106,18 @@ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn32/display_mode_vba_util_32.o := $(dml_rcf
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn301/dcn301_fpu.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_rcflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dsc/rc_calc_fpu.o := $(dml_rcflags)
-endif
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn10/dcn10_fpu.o := $(dml_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn20/dcn20_fpu.o := $(dml_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn314/display_mode_vba_314.o := $(dml_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn314/display_rq_dlg_calc_314.o := $(dml_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn314/dcn314_fpu.o := $(dml_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn30/dcn30_fpu.o := $(dml_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn32/dcn32_fpu.o := $(dml_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn321/dcn321_fpu.o := $(dml_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn31/dcn31_fpu.o := $(dml_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn302/dcn302_fpu.o := $(dml_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn303/dcn303_fpu.o := $(dml_rcflags)
+CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/calcs/dcn_calc_math.o := $(dml_rcflags)
CFLAGS_$(AMDDALPATH)/dc/dml/dml1_display_rq_dlg_calc.o := $(dml_ccflags)
CFLAGS_$(AMDDALPATH)/dc/dml/display_rq_dlg_helpers.o := $(dml_ccflags)
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dml1_display_rq_dlg_calc.o := $(dml_rcflags)
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dc_features.h b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h
index 74e86732e301..2cbdd75429ff 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dc_features.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/dc_features.h
@@ -29,6 +29,13 @@
#define DC__PRESENT 1
#define DC__PRESENT__1 1
#define DC__NUM_DPP 4
+
+/**
+ * @DC__VOLTAGE_STATES:
+ *
+ * Define the maximum amount of states supported by the ASIC. Every ASIC has a
+ * specific number of states; this macro defines the maximum number of states.
+ */
#define DC__VOLTAGE_STATES 20
#define DC__NUM_DPP__4 1
#define DC__NUM_DPP__0_PRESENT 1
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c
index 99644d896222..c5e84190c17a 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.c
@@ -27,6 +27,8 @@
#include "dcn10/dcn10_resource.h"
#include "dcn10_fpu.h"
+#include "resource.h"
+#include "amdgpu_dm/dc_fpu.h"
/**
* DOC: DCN10 FPU manipulation Overview
@@ -121,3 +123,37 @@ struct _vcs_dpi_soc_bounding_box_st dcn1_0_soc = {
.writeback_dram_clock_change_latency_us = 23.0,
.return_bus_width_bytes = 64,
};
+
+void dcn10_resource_construct_fp(struct dc *dc)
+{
+ dc_assert_fp_enabled();
+ if (dc->ctx->dce_version == DCN_VERSION_1_01) {
+ struct dcn_soc_bounding_box *dcn_soc = dc->dcn_soc;
+ struct dcn_ip_params *dcn_ip = dc->dcn_ip;
+ struct display_mode_lib *dml = &dc->dml;
+
+ dml->ip.max_num_dpp = 3;
+ /* TODO how to handle 23.84? */
+ dcn_soc->dram_clock_change_latency = 23;
+ dcn_ip->max_num_dpp = 3;
+ }
+ if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev)) {
+ dc->dcn_soc->urgent_latency = 3;
+ dc->debug.disable_dmcu = true;
+ dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 41.60f;
+ }
+
+ dc->dcn_soc->number_of_channels = dc->ctx->asic_id.vram_width / ddr4_dram_width;
+ ASSERT(dc->dcn_soc->number_of_channels < 3);
+ if (dc->dcn_soc->number_of_channels == 0)/*old sbios bug*/
+ dc->dcn_soc->number_of_channels = 2;
+
+ if (dc->dcn_soc->number_of_channels == 1) {
+ dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 19.2f;
+ dc->dcn_soc->fabric_and_dram_bandwidth_vnom0p8 = 17.066f;
+ dc->dcn_soc->fabric_and_dram_bandwidth_vmid0p72 = 14.933f;
+ dc->dcn_soc->fabric_and_dram_bandwidth_vmin0p65 = 12.8f;
+ if (ASICREV_IS_RV1_F0(dc->ctx->asic_id.hw_internal_rev))
+ dc->dcn_soc->fabric_and_dram_bandwidth_vmax0p9 = 20.80f;
+ }
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.h
index e74ed4b4ce5b..63219ecd8478 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn10/dcn10_fpu.h
@@ -27,4 +27,6 @@
#ifndef __DCN10_FPU_H__
#define __DCN10_FPU_H__
+void dcn10_resource_construct_fp(struct dc *dc);
+
#endif /* __DCN20_FPU_H__ */
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 45db40c41882..c26da3bb2892 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
@@ -565,7 +565,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = {
.dppclk_mhz = 847.06,
.phyclk_mhz = 810.0,
.socclk_mhz = 953.0,
- .dscclk_mhz = 489.0,
+ .dscclk_mhz = 300.0,
.dram_speed_mts = 2400.0,
},
{
@@ -576,7 +576,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = {
.dppclk_mhz = 960.00,
.phyclk_mhz = 810.0,
.socclk_mhz = 278.0,
- .dscclk_mhz = 287.67,
+ .dscclk_mhz = 342.86,
.dram_speed_mts = 2666.0,
},
{
@@ -587,7 +587,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = {
.dppclk_mhz = 1028.57,
.phyclk_mhz = 810.0,
.socclk_mhz = 715.0,
- .dscclk_mhz = 318.334,
+ .dscclk_mhz = 369.23,
.dram_speed_mts = 3200.0,
},
{
@@ -949,6 +949,7 @@ 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;
+ bool allow_z8 = context->bw_ctx.dml.vba.StutterPeriod > 1000.0;
plane_count = 0;
optimized_min_dst_y_next_start_us = 0;
@@ -963,6 +964,8 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc
* 2. single eDP, on link 0, 1 plane and stutter period > 5ms
* Z10 only cases:
* 1. single eDP, on link 0, 1 plane and stutter period >= 5ms
+ * Z8 cases:
+ * 1. stutter period sufficient
* Zstate not allowed cases:
* 1. Everything else
*/
@@ -989,12 +992,15 @@ static enum dcn_zstate_support_state decide_zstate_support(struct dc *dc, struc
if (context->bw_ctx.dml.vba.StutterPeriod > 5000.0 || optimized_min_dst_y_next_start_us > 5000)
return DCN_ZSTATE_SUPPORT_ALLOW;
- else if (link->psr_settings.psr_version == DC_PSR_VERSION_1 && !dc->debug.disable_psr)
- return DCN_ZSTATE_SUPPORT_ALLOW_Z10_ONLY;
+ else if (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;
else
- return DCN_ZSTATE_SUPPORT_DISALLOW;
- } else
+ return allow_z8 ? DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY : DCN_ZSTATE_SUPPORT_DISALLOW;
+ } else if (allow_z8) {
+ return DCN_ZSTATE_SUPPORT_ALLOW_Z8_ONLY;
+ } else {
return DCN_ZSTATE_SUPPORT_DISALLOW;
+ }
}
void dcn20_calculate_dlg_params(
@@ -1296,6 +1302,8 @@ int dcn20_populate_dml_pipes_from_context(
case SIGNAL_TYPE_DISPLAY_PORT_MST:
case SIGNAL_TYPE_DISPLAY_PORT:
pipes[pipe_cnt].dout.output_type = dm_dp;
+ if (is_dp_128b_132b_signal(&res_ctx->pipe_ctx[i]))
+ pipes[pipe_cnt].dout.output_type = dm_dp2p0;
break;
case SIGNAL_TYPE_EDP:
pipes[pipe_cnt].dout.output_type = dm_edp;
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 e1e92daba668..d4c0f9cdac8e 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
@@ -520,9 +520,7 @@ void dcn30_fpu_calculate_wm_and_dlg(
pipe_idx++;
}
- DC_FP_START();
dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
- DC_FP_END();
if (!pstate_en)
/* Restore full p-state latency */
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 479e2c1a1301..379729b02847 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
@@ -4851,7 +4851,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
v->SwathHeightYThisState[k],
v->SwathHeightCThisState[k],
v->HTotal[k] / v->PixelClock[k],
- v->UrgentLatency,
+ v->UrgLatency[i],
v->CursorBufferSize,
v->CursorWidth[k][0],
v->CursorBPP[k][0],
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 7dd0845d1bd9..b37d14369a62 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_dpp_count = 0;
+ int i, pipe_idx, active_hubp_count = 0;
double dcfclk = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb];
dc_assert_fp_enabled();
@@ -529,7 +529,7 @@ void dcn31_calculate_wm_and_dlg_fp(
continue;
if (context->res_ctx.pipe_ctx[i].plane_state)
- active_dpp_count++;
+ active_hubp_count++;
pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt);
pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
@@ -547,9 +547,22 @@ void dcn31_calculate_wm_and_dlg_fp(
}
dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
- /* For 31x apu pstate change is only supported if possible in vactive or if there are no active dpps */
+ /* For 31x apu pstate change is only supported if possible in vactive*/
context->bw_ctx.bw.dcn.clk.p_state_change_support =
- context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] == dm_dram_clock_change_vactive || !active_dpp_count;
+ context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] == dm_dram_clock_change_vactive;
+ /* If DCN isn't making memory requests we can allow pstate change and lower clocks */
+ if (!active_hubp_count) {
+ context->bw_ctx.bw.dcn.clk.socclk_khz = 0;
+ context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;
+ context->bw_ctx.bw.dcn.clk.dcfclk_khz = 0;
+ context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = 0;
+ 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;
+ for (i = 0; i < dc->res_pool->pipe_count; i++)
+ if (context->res_ctx.pipe_ctx[i].stream)
+ context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz = 0;
+ }
}
void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params)
@@ -797,3 +810,8 @@ void dcn316_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param
else
dml_init_instance(&dc->dml, &dcn3_16_soc, &dcn3_16_ip, DML_PROJECT_DCN31_FPGA);
}
+
+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);
+}
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 fd58b2561ec9..687d3522cc33 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
@@ -46,5 +46,10 @@ void dcn31_calculate_wm_and_dlg_fp(
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 dcn31x_populate_dml_pipes_from_context(struct dc *dc,
+ struct dc_state *context,
+ display_e2e_pipe_params_st *pipes,
+ bool fast_validate);
#endif /* __DCN31_FPU_H__*/
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 b612edb14417..ec351c8418cb 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
@@ -1052,17 +1052,16 @@ static bool CalculatePrefetchSchedule(
else
bytes_pp = myPipe->BytePerPixelY + myPipe->BytePerPixelC;
/*rev 99*/
- prefetch_bw_pr = dml_min(1, bytes_pp * myPipe->PixelClock / (double) myPipe->DPPPerPlane);
+ prefetch_bw_pr = bytes_pp * myPipe->PixelClock / (double) myPipe->DPPPerPlane;
+ prefetch_bw_pr = dml_min(1, myPipe->VRatio) * prefetch_bw_pr;
max_Tsw = dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime;
prefetch_sw_bytes = PrefetchSourceLinesY * swath_width_luma_ub * myPipe->BytePerPixelY + PrefetchSourceLinesC * swath_width_chroma_ub * myPipe->BytePerPixelC;
- prefetch_bw_oto = dml_max(bytes_pp * myPipe->PixelClock / myPipe->DPPPerPlane, prefetch_sw_bytes / (dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime));
prefetch_bw_oto = dml_max(prefetch_bw_pr, prefetch_sw_bytes / max_Tsw);
min_Lsw = dml_max(1, dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) / max_vratio_pre);
Lsw_oto = dml_ceil(4 * dml_max(prefetch_sw_bytes / prefetch_bw_oto / LineTime, min_Lsw), 1) / 4;
Tsw_oto = Lsw_oto * LineTime;
- prefetch_bw_oto = (PrefetchSourceLinesY * swath_width_luma_ub * myPipe->BytePerPixelY + PrefetchSourceLinesC * swath_width_chroma_ub * myPipe->BytePerPixelC) / Tsw_oto;
#ifdef __DML_VBA_DEBUG__
dml_print("DML: HTotal: %d\n", myPipe->HTotal);
@@ -5083,7 +5082,7 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
v->SwathHeightYThisState[k],
v->SwathHeightCThisState[k],
v->HTotal[k] / v->PixelClock[k],
- v->UrgentLatency,
+ v->UrgLatency[i],
v->CursorBufferSize,
v->CursorWidth[k][0],
v->CursorBPP[k][0],
@@ -5361,6 +5360,58 @@ void dml31_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
v->ModeSupport[i][j] = true;
} else {
v->ModeSupport[i][j] = false;
+#ifdef __DML_VBA_DEBUG__
+ if (v->ScaleRatioAndTapsSupport == false)
+ dml_print("DML SUPPORT: ScaleRatioAndTapsSupport failed");
+ if (v->SourceFormatPixelAndScanSupport == false)
+ dml_print("DML SUPPORT: SourceFormatPixelAndScanSupport failed");
+ if (v->ViewportSizeSupport[i][j] == false)
+ dml_print("DML SUPPORT: ViewportSizeSupport failed");
+ if (v->LinkCapacitySupport[i] == false)
+ dml_print("DML SUPPORT: LinkCapacitySupport failed");
+ if (v->ODMCombine4To1SupportCheckOK[i] == false)
+ dml_print("DML SUPPORT: DSC422NativeNotSupported failed");
+ if (v->NotEnoughDSCUnits[i] == true)
+ dml_print("DML SUPPORT: NotEnoughDSCUnits");
+ if (v->DTBCLKRequiredMoreThanSupported[i] == true)
+ dml_print("DML SUPPORT: DTBCLKRequiredMoreThanSupported");
+ if (v->ROBSupport[i][j] == false)
+ dml_print("DML SUPPORT: ROBSupport failed");
+ if (v->DISPCLK_DPPCLK_Support[i][j] == false)
+ dml_print("DML SUPPORT: DISPCLK_DPPCLK_Support failed");
+ if (v->TotalAvailablePipesSupport[i][j] == false)
+ dml_print("DML SUPPORT: DSC422NativeNotSupported failed");
+ if (EnoughWritebackUnits == false)
+ dml_print("DML SUPPORT: DSC422NativeNotSupported failed");
+ if (v->WritebackLatencySupport == false)
+ dml_print("DML SUPPORT: WritebackLatencySupport failed");
+ if (v->WritebackScaleRatioAndTapsSupport == false)
+ dml_print("DML SUPPORT: DSC422NativeNotSupported ");
+ if (v->CursorSupport == false)
+ dml_print("DML SUPPORT: DSC422NativeNotSupported failed");
+ if (v->PitchSupport == false)
+ dml_print("DML SUPPORT: PitchSupport failed");
+ if (ViewportExceedsSurface == true)
+ dml_print("DML SUPPORT: ViewportExceedsSurface failed");
+ if (v->PrefetchSupported[i][j] == false)
+ dml_print("DML SUPPORT: PrefetchSupported failed");
+ if (v->DynamicMetadataSupported[i][j] == false)
+ dml_print("DML SUPPORT: DSC422NativeNotSupported failed");
+ if (v->TotalVerticalActiveBandwidthSupport[i][j] == false)
+ dml_print("DML SUPPORT: TotalVerticalActiveBandwidthSupport failed");
+ if (v->VRatioInPrefetchSupported[i][j] == false)
+ dml_print("DML SUPPORT: VRatioInPrefetchSupported failed");
+ if (v->PTEBufferSizeNotExceeded[i][j] == false)
+ dml_print("DML SUPPORT: PTEBufferSizeNotExceeded failed");
+ if (v->NonsupportedDSCInputBPC == true)
+ dml_print("DML SUPPORT: NonsupportedDSCInputBPC failed");
+ if (!((v->HostVMEnable == false
+ && v->ImmediateFlipRequirement[0] != dm_immediate_flip_required)
+ || v->ImmediateFlipSupportedForState[i][j] == true))
+ dml_print("DML SUPPORT: ImmediateFlipRequirement failed");
+ if (FMTBufferExceeded == true)
+ dml_print("DML SUPPORT: FMTBufferExceeded failed");
+#endif
}
}
}
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 34b6c763a455..6a1cf6adea77 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
@@ -29,6 +29,7 @@
#include "dcn31/dcn31_hubbub.h"
#include "dcn314_fpu.h"
#include "dml/dcn20/dcn20_fpu.h"
+#include "dml/dcn31/dcn31_fpu.h"
#include "dml/display_mode_vba.h"
struct _vcs_dpi_ip_params_st dcn3_14_ip = {
@@ -148,8 +149,8 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_14_soc = {
.num_states = 5,
.sr_exit_time_us = 16.5,
.sr_enter_plus_exit_time_us = 18.5,
- .sr_exit_z8_time_us = 442.0,
- .sr_enter_plus_exit_z8_time_us = 560.0,
+ .sr_exit_z8_time_us = 280.0,
+ .sr_enter_plus_exit_z8_time_us = 350.0,
.writeback_latency_us = 12.0,
.dram_channel_width_bytes = 4,
.round_trip_ping_latency_dcfclk_cycles = 106,
@@ -264,11 +265,8 @@ void dcn314_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_p
dc->dml.soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2;
}
- if ((int)(dcn3_14_soc.dram_clock_change_latency_us * 1000)
- != dc->debug.dram_clock_change_latency_ns
- && dc->debug.dram_clock_change_latency_ns) {
- dcn3_14_soc.dram_clock_change_latency_us = dc->debug.dram_clock_change_latency_ns / 1000;
- }
+ 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
@@ -291,7 +289,7 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c
dc_assert_fp_enabled();
- dcn20_populate_dml_pipes_from_context(dc, context, pipes, fast_validate);
+ dcn31x_populate_dml_pipes_from_context(dc, context, pipes, fast_validate);
for (i = 0, pipe_cnt = 0; i < dc->res_pool->pipe_count; i++) {
struct dc_crtc_timing *timing;
@@ -318,8 +316,6 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c
pipes[pipe_cnt].pipe.src.immediate_flip = true;
pipes[pipe_cnt].pipe.src.unbounded_req_mode = false;
- pipes[pipe_cnt].pipe.src.hostvm = dc->res_pool->hubbub->riommu_active;
- pipes[pipe_cnt].pipe.src.gpuvm = true;
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;
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 0d12fd079cd6..950669f2c10d 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
@@ -1074,17 +1074,16 @@ static bool CalculatePrefetchSchedule(
else
bytes_pp = myPipe->BytePerPixelY + myPipe->BytePerPixelC;
/*rev 99*/
- prefetch_bw_pr = dml_min(1, bytes_pp * myPipe->PixelClock / (double) myPipe->DPPPerPlane);
+ prefetch_bw_pr = bytes_pp * myPipe->PixelClock / (double) myPipe->DPPPerPlane;
+ prefetch_bw_pr = dml_min(1, myPipe->VRatio) * prefetch_bw_pr;
max_Tsw = dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime;
prefetch_sw_bytes = PrefetchSourceLinesY * swath_width_luma_ub * myPipe->BytePerPixelY + PrefetchSourceLinesC * swath_width_chroma_ub * myPipe->BytePerPixelC;
- prefetch_bw_oto = dml_max(bytes_pp * myPipe->PixelClock / myPipe->DPPPerPlane, prefetch_sw_bytes / (dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) * LineTime));
prefetch_bw_oto = dml_max(prefetch_bw_pr, prefetch_sw_bytes / max_Tsw);
min_Lsw = dml_max(1, dml_max(PrefetchSourceLinesY, PrefetchSourceLinesC) / max_vratio_pre);
Lsw_oto = dml_ceil(4 * dml_max(prefetch_sw_bytes / prefetch_bw_oto / LineTime, min_Lsw), 1) / 4;
Tsw_oto = Lsw_oto * LineTime;
- prefetch_bw_oto = (PrefetchSourceLinesY * swath_width_luma_ub * myPipe->BytePerPixelY + PrefetchSourceLinesC * swath_width_chroma_ub * myPipe->BytePerPixelC) / Tsw_oto;
#ifdef __DML_VBA_DEBUG__
dml_print("DML: HTotal: %d\n", myPipe->HTotal);
@@ -5180,7 +5179,7 @@ void dml314_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_
v->SwathHeightYThisState[k],
v->SwathHeightCThisState[k],
v->HTotal[k] / v->PixelClock[k],
- v->UrgentLatency,
+ v->UrgLatency[i],
v->CursorBufferSize,
v->CursorWidth[k][0],
v->CursorBPP[k][0],
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 2abe3967f7fb..f94abd124021 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
@@ -256,16 +256,24 @@ int dcn32_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc,
int vlevel)
{
const int max_latency_table_entries = 4;
- const struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
+ struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
int dummy_latency_index = 0;
+ enum clock_change_support temp_clock_change_support = vba->DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb];
dc_assert_fp_enabled();
while (dummy_latency_index < max_latency_table_entries) {
+ if (temp_clock_change_support != dm_dram_clock_change_unsupported)
+ vba->DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] = temp_clock_change_support;
context->bw_ctx.dml.soc.dram_clock_change_latency_us =
dc->clk_mgr->bw_params->dummy_pstate_table[dummy_latency_index].dummy_pstate_latency_us;
dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, false);
+ /* for subvp + DRR case, if subvp pipes are still present we support pstate */
+ if (vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] == dm_dram_clock_change_unsupported &&
+ dcn32_subvp_in_use(dc, context))
+ vba->DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] = temp_clock_change_support;
+
if (vlevel < context->bw_ctx.dml.vba.soc.num_states &&
vba->DRAMClockChangeSupport[vlevel][vba->maxMpcComb] != dm_dram_clock_change_unsupported)
break;
@@ -531,9 +539,12 @@ void dcn32_set_phantom_stream_timing(struct dc *dc,
unsigned int i, pipe_idx;
struct pipe_ctx *pipe;
uint32_t phantom_vactive, phantom_bp, pstate_width_fw_delay_lines;
+ unsigned int num_dpp;
unsigned int vlevel = context->bw_ctx.dml.vba.VoltageLevel;
unsigned int dcfclk = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb];
unsigned int socclk = context->bw_ctx.dml.vba.SOCCLKPerState[vlevel];
+ struct vba_vars_st *vba = &context->bw_ctx.dml.vba;
+ struct dc_stream_state *main_stream = ref_pipe->stream;
dc_assert_fp_enabled();
@@ -569,13 +580,26 @@ void dcn32_set_phantom_stream_timing(struct dc *dc,
phantom_vactive = get_subviewport_lines_needed_in_mall(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx) +
pstate_width_fw_delay_lines + dc->caps.subvp_swath_height_margin_lines;
+ // W/A for DCC corruption with certain high resolution timings.
+ // Determing if pipesplit is used. If so, add meta_row_height to the phantom vactive.
+ num_dpp = vba->NoOfDPP[vba->VoltageLevel][vba->maxMpcComb][vba->pipe_plane[pipe_idx]];
+ phantom_vactive += num_dpp > 1 ? vba->meta_row_height[vba->pipe_plane[pipe_idx]] : 0;
+
+ /* dc->debug.subvp_extra_lines 0 by default*/
+ phantom_vactive += dc->debug.subvp_extra_lines;
+
// For backporch of phantom pipe, use vstartup of the main pipe
phantom_bp = get_vstartup(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
phantom_stream->dst.y = 0;
phantom_stream->dst.height = phantom_vactive;
+ /* When scaling, DML provides the end to end required number of lines for MALL.
+ * dst.height is always correct for this case, but src.height is not which causes a
+ * delta between main and phantom pipe scaling outputs. Need to adjust src.height on
+ * phantom for this case.
+ */
phantom_stream->src.y = 0;
- phantom_stream->src.height = phantom_vactive;
+ phantom_stream->src.height = (double)phantom_vactive * (double)main_stream->src.height / (double)main_stream->dst.height;
phantom_stream->timing.v_addressable = phantom_vactive;
phantom_stream->timing.v_front_porch = 1;
@@ -1128,7 +1152,7 @@ static void dcn32_full_validate_bw_helper(struct dc *dc,
context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final ==
dm_prefetch_support_uclk_fclk_and_stutter) {
context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final =
- dm_prefetch_support_stutter;
+ dm_prefetch_support_fclk_and_stutter;
/* There are params (such as FabricClock) that need to be recalculated
* after validation fails (otherwise it will be 0). Calculation for
* phantom vactive requires call into DML, so we must ensure all the
@@ -1179,7 +1203,7 @@ static void dcn32_full_validate_bw_helper(struct dc *dc,
// If SubVP pipe config is unsupported (or cannot be used for UCLK switching)
// remove phantom pipes and repopulate dml pipes
if (!found_supported_config) {
- dc->res_pool->funcs->remove_phantom_pipes(dc, context);
+ dc->res_pool->funcs->remove_phantom_pipes(dc, context, false);
vba->DRAMClockChangeSupport[*vlevel][vba->maxMpcComb] = dm_dram_clock_change_unsupported;
*pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, false);
@@ -1191,9 +1215,7 @@ static void dcn32_full_validate_bw_helper(struct dc *dc,
}
} else {
// Most populate phantom DLG params before programming hardware / timing for phantom pipe
- DC_FP_START();
dcn32_helper_populate_phantom_dlg_params(dc, context, pipes, *pipe_cnt);
- DC_FP_END();
/* Call validate_apply_pipe_split flags after calling DML getters for
* phantom dlg params, or some of the VBA params indicating pipe split
@@ -1230,7 +1252,7 @@ static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context,
display_e2e_pipe_params_st *pipes,
int pipe_cnt, int vlevel)
{
- int i, pipe_idx;
+ int i, pipe_idx, active_hubp_count = 0;
bool usr_retraining_support = false;
bool unbounded_req_enabled = false;
@@ -1275,6 +1297,8 @@ static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context,
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,
@@ -1296,10 +1320,23 @@ static void dcn32_calculate_dlg_params(struct dc *dc, struct dc_state *context,
if (context->bw_ctx.bw.dcn.clk.dppclk_khz < pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000)
context->bw_ctx.bw.dcn.clk.dppclk_khz = pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000;
- context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz = pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000;
+ if (context->res_ctx.pipe_ctx[i].plane_state)
+ context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz = pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000;
+ else
+ context->res_ctx.pipe_ctx[i].plane_res.bw.dppclk_khz = 0;
context->res_ctx.pipe_ctx[i].pipe_dlg_param = pipes[pipe_idx].pipe.dest;
pipe_idx++;
}
+ /* If DCN isn't making memory requests we can allow pstate change and lower clocks */
+ if (!active_hubp_count) {
+ context->bw_ctx.bw.dcn.clk.socclk_khz = 0;
+ context->bw_ctx.bw.dcn.clk.dppclk_khz = 0;
+ context->bw_ctx.bw.dcn.clk.dcfclk_khz = 0;
+ context->bw_ctx.bw.dcn.clk.dcfclk_deep_sleep_khz = 0;
+ 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;
+ }
/*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;
@@ -1481,7 +1518,7 @@ bool dcn32_internal_validate_bw(struct dc *dc,
return false;
// For each full update, remove all existing phantom pipes first
- dc->res_pool->funcs->remove_phantom_pipes(dc, context);
+ dc->res_pool->funcs->remove_phantom_pipes(dc, context, fast_validate);
dc->res_pool->funcs->update_soc_for_wm_a(dc, context);
@@ -1494,11 +1531,8 @@ bool dcn32_internal_validate_bw(struct dc *dc,
dml_log_pipe_params(&context->bw_ctx.dml, pipes, pipe_cnt);
- if (!fast_validate) {
- DC_FP_START();
+ if (!fast_validate)
dcn32_full_validate_bw_helper(dc, context, pipes, &vlevel, split, merge, &pipe_cnt);
- DC_FP_END();
- }
if (fast_validate ||
(dc->debug.dml_disallow_alternate_prefetch_modes &&
@@ -1734,6 +1768,10 @@ bool dcn32_internal_validate_bw(struct dc *dc,
}
if (repopulate_pipes) {
+ int flag_max_mpc_comb = vba->maxMpcComb;
+ int flag_vlevel = vlevel;
+ int i;
+
pipe_cnt = dc->res_pool->funcs->populate_dml_pipes(dc, context, pipes, fast_validate);
/* repopulate_pipes = 1 means the pipes were either split or merged. In this case
@@ -1741,10 +1779,28 @@ bool dcn32_internal_validate_bw(struct dc *dc,
* ensure all the params are calculated correctly. We do not need to run the
* pipe split check again after this call (pipes are already split / merged).
* */
- if (!fast_validate) {
- context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final =
- dm_prefetch_support_uclk_fclk_and_stutter_if_possible;
- vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
+ context->bw_ctx.dml.soc.allow_for_pstate_or_stutter_in_vblank_final =
+ dm_prefetch_support_uclk_fclk_and_stutter_if_possible;
+ vlevel = dml_get_voltage_level(&context->bw_ctx.dml, pipes, pipe_cnt);
+ if (vlevel == context->bw_ctx.dml.soc.num_states) {
+ /* failed after DET size changes */
+ goto validate_fail;
+ } else if (flag_max_mpc_comb == 0 &&
+ flag_max_mpc_comb != context->bw_ctx.dml.vba.maxMpcComb) {
+ /* check the context constructed with pipe split flags is still valid*/
+ bool flags_valid = false;
+ for (i = flag_vlevel; i < context->bw_ctx.dml.soc.num_states; i++) {
+ if (vba->ModeSupport[i][flag_max_mpc_comb]) {
+ vba->maxMpcComb = flag_max_mpc_comb;
+ vba->VoltageLevel = i;
+ vlevel = i;
+ flags_valid = true;
+ }
+ }
+
+ /* this should never happen */
+ if (!flags_valid)
+ goto validate_fail;
}
}
*vlevel_out = vlevel;
@@ -1775,14 +1831,38 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
unsigned int dummy_latency_index = 0;
int maxMpcComb = context->bw_ctx.dml.vba.maxMpcComb;
unsigned int min_dram_speed_mts = context->bw_ctx.dml.vba.DRAMSpeed;
+ bool subvp_in_use = dcn32_subvp_in_use(dc, context);
unsigned int min_dram_speed_mts_margin;
+ bool need_fclk_lat_as_dummy = false;
+ bool is_subvp_p_drr = true;
dc_assert_fp_enabled();
- // Override DRAMClockChangeSupport for SubVP + DRR case where the DRR cannot switch without stretching it's VBLANK
- if (!pstate_en && dcn32_subvp_in_use(dc, context)) {
- context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] = dm_dram_clock_change_vblank_w_mall_sub_vp;
- pstate_en = true;
+ /* need to find dummy latency index for subvp */
+ if (subvp_in_use) {
+ /* Override DRAMClockChangeSupport for SubVP + DRR case where the DRR cannot switch without stretching it's VBLANK */
+ if (!pstate_en) {
+ context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] = dm_dram_clock_change_vblank_w_mall_sub_vp;
+ pstate_en = true;
+ is_subvp_p_drr = true;
+ }
+ dummy_latency_index = dcn32_find_dummy_latency_index_for_fw_based_mclk_switch(dc,
+ context, pipes, pipe_cnt, vlevel);
+
+ /* For DCN32/321 need to validate with fclk pstate change latency equal to dummy so prefetch is
+ * scheduled correctly to account for dummy pstate.
+ */
+ if (context->bw_ctx.dml.soc.fclk_change_latency_us < dc->clk_mgr->bw_params->dummy_pstate_table[dummy_latency_index].dummy_pstate_latency_us) {
+ need_fclk_lat_as_dummy = true;
+ context->bw_ctx.dml.soc.fclk_change_latency_us =
+ dc->clk_mgr->bw_params->dummy_pstate_table[dummy_latency_index].dummy_pstate_latency_us;
+ }
+ context->bw_ctx.dml.soc.dram_clock_change_latency_us =
+ dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us;
+ dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, false);
+ if (is_subvp_p_drr) {
+ context->bw_ctx.dml.vba.DRAMClockChangeSupport[vlevel][context->bw_ctx.dml.vba.maxMpcComb] = dm_dram_clock_change_vblank_w_mall_sub_vp;
+ }
}
context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching = false;
@@ -1806,9 +1886,11 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
/* For DCN32/321 need to validate with fclk pstate change latency equal to dummy so
* prefetch is scheduled correctly to account for dummy pstate.
*/
- if (dummy_latency_index == 0)
+ if (context->bw_ctx.dml.soc.fclk_change_latency_us < dc->clk_mgr->bw_params->dummy_pstate_table[dummy_latency_index].dummy_pstate_latency_us) {
+ need_fclk_lat_as_dummy = true;
context->bw_ctx.dml.soc.fclk_change_latency_us =
dc->clk_mgr->bw_params->dummy_pstate_table[dummy_latency_index].dummy_pstate_latency_us;
+ }
dcn32_internal_validate_bw(dc, context, pipes, &pipe_cnt, &vlevel, false);
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];
@@ -1916,7 +1998,7 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
dc->clk_mgr->bw_params->clk_table.entries[min_dram_speed_mts_offset].memclk_mhz * 16;
}
- if (!context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) {
+ if (!context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching && !subvp_in_use) {
/* find largest table entry that is lower than dram speed,
* but lower than DPM0 still uses DPM0
*/
@@ -1996,7 +2078,8 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
context->perf_params.stutter_period_us = context->bw_ctx.dml.vba.StutterPeriod;
- if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching && dummy_latency_index == 0)
+ /* for proper prefetch calculations, if dummy lat > fclk lat, use fclk lat = dummy lat */
+ if (need_fclk_lat_as_dummy)
context->bw_ctx.dml.soc.fclk_change_latency_us =
dc->clk_mgr->bw_params->dummy_pstate_table[dummy_latency_index].dummy_pstate_latency_us;
@@ -2009,10 +2092,12 @@ void dcn32_calculate_wm_and_dlg_fpu(struct dc *dc, struct dc_state *context,
if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) {
dcn30_setup_mclk_switch_using_fw_based_vblank_stretch(dc, context);
- if (dummy_latency_index == 0)
- context->bw_ctx.dml.soc.fclk_change_latency_us =
- dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.fclk_change_latency_us;
}
+
+ /* revert fclk lat changes if required */
+ if (need_fclk_lat_as_dummy)
+ context->bw_ctx.dml.soc.fclk_change_latency_us =
+ dc->clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.fclk_change_latency_us;
}
static void dcn32_get_optimal_dcfclk_fclk_for_uclk(unsigned int uclk_mts,
@@ -2159,9 +2244,7 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
entry.fabricclk_mhz = 0;
entry.dram_speed_mts = 0;
- DC_FP_START();
insert_entry_into_table_sorted(table, num_entries, &entry);
- DC_FP_END();
}
// Insert the max DCFCLK
@@ -2169,9 +2252,7 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
entry.fabricclk_mhz = 0;
entry.dram_speed_mts = 0;
- DC_FP_START();
insert_entry_into_table_sorted(table, num_entries, &entry);
- DC_FP_END();
// Insert the UCLK DPMS
for (i = 0; i < num_uclk_dpms; i++) {
@@ -2179,9 +2260,7 @@ 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;
- DC_FP_START();
insert_entry_into_table_sorted(table, num_entries, &entry);
- DC_FP_END();
}
// If FCLK is coarse grained, insert individual DPMs.
@@ -2191,9 +2270,7 @@ 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;
- DC_FP_START();
insert_entry_into_table_sorted(table, num_entries, &entry);
- DC_FP_END();
}
}
// If FCLK fine grained, only insert max
@@ -2202,9 +2279,7 @@ static int build_synthetic_soc_states(struct clk_bw_params *bw_params,
entry.fabricclk_mhz = max_fclk_mhz;
entry.dram_speed_mts = 0;
- DC_FP_START();
insert_entry_into_table_sorted(table, num_entries, &entry);
- DC_FP_END();
}
// At this point, the table contains all "points of interest" based on
@@ -2539,3 +2614,11 @@ void dcn32_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_pa
}
}
+void dcn32_zero_pipe_dcc_fraction(display_e2e_pipe_params_st *pipes,
+ int pipe_cnt)
+{
+ dc_assert_fp_enabled();
+
+ pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_luma = 0;
+ pipes[pipe_cnt].pipe.src.dcc_fraction_of_zs_req_chroma = 0;
+}
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 3a3dc2ce4c73..ab010e7e840b 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
@@ -73,4 +73,7 @@ int dcn32_find_dummy_latency_index_for_fw_based_mclk_switch(struct dc *dc,
void dcn32_patch_dpm_table(struct clk_bw_params *bw_params);
+void dcn32_zero_pipe_dcc_fraction(display_e2e_pipe_params_st *pipes,
+ int pipe_cnt);
+
#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 9afd9ba23fb2..4b8f5fa0f0ad 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
@@ -670,6 +670,25 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman
v->cursor_bw[k] = mode_lib->vba.NumberOfCursors[k] * mode_lib->vba.CursorWidth[k][0] * mode_lib->vba.CursorBPP[k][0] / 8 / (mode_lib->vba.HTotal[k] / mode_lib->vba.PixelClock[k]) * mode_lib->vba.VRatio[k];
}
+ v->NotEnoughDETSwathFillLatencyHiding = dml32_CalculateDETSwathFillLatencyHiding(
+ mode_lib->vba.NumberOfActiveSurfaces,
+ mode_lib->vba.ReturnBW,
+ v->UrgentLatency,
+ mode_lib->vba.SwathHeightY,
+ mode_lib->vba.SwathHeightC,
+ v->swath_width_luma_ub,
+ v->swath_width_chroma_ub,
+ v->BytePerPixelDETY,
+ v->BytePerPixelDETC,
+ mode_lib->vba.DETBufferSizeY,
+ mode_lib->vba.DETBufferSizeC,
+ mode_lib->vba.DPPPerPlane,
+ mode_lib->vba.HTotal,
+ mode_lib->vba.PixelClock,
+ mode_lib->vba.VRatio,
+ mode_lib->vba.VRatioChroma,
+ mode_lib->vba.UsesMALLForPStateChange);
+
for (k = 0; k < mode_lib->vba.NumberOfActiveSurfaces; ++k) {
v->MaxVStartupLines[k] = ((mode_lib->vba.Interlace[k] &&
!mode_lib->vba.ProgressiveToInterlaceUnitInOPP) ?
@@ -1665,6 +1684,8 @@ static void mode_support_configuration(struct vba_vars_st *v,
&& mode_lib->vba.DCCMetaBufferSizeNotExceeded[i][j] == true
&& mode_lib->vba.NonsupportedDSCInputBPC == false
&& !mode_lib->vba.ExceededMALLSize
+ && (mode_lib->vba.NotEnoughDETSwathFillLatencyHidingPerState[i][j] == false
+ || i == v->soc.num_states - 1)
&& ((mode_lib->vba.HostVMEnable == false
&& !mode_lib->vba.ImmediateFlipRequiredFinal)
|| mode_lib->vba.ImmediateFlipSupportedForState[i][j])
@@ -3158,6 +3179,25 @@ void dml32_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l
mode_lib->vba.UrgentBurstFactorChroma,
mode_lib->vba.UrgentBurstFactorCursor);
+ mode_lib->vba.NotEnoughDETSwathFillLatencyHidingPerState[i][j] = dml32_CalculateDETSwathFillLatencyHiding(
+ mode_lib->vba.NumberOfActiveSurfaces,
+ mode_lib->vba.ReturnBWPerState[i][j],
+ mode_lib->vba.UrgLatency[i],
+ mode_lib->vba.SwathHeightYThisState,
+ mode_lib->vba.SwathHeightCThisState,
+ mode_lib->vba.swath_width_luma_ub_this_state,
+ mode_lib->vba.swath_width_chroma_ub_this_state,
+ mode_lib->vba.BytePerPixelInDETY,
+ mode_lib->vba.BytePerPixelInDETC,
+ mode_lib->vba.DETBufferSizeYThisState,
+ mode_lib->vba.DETBufferSizeCThisState,
+ mode_lib->vba.NoOfDPPThisState,
+ mode_lib->vba.HTotal,
+ mode_lib->vba.PixelClock,
+ mode_lib->vba.VRatio,
+ mode_lib->vba.VRatioChroma,
+ mode_lib->vba.UsesMALLForPStateChange);
+
v->dummy_vars.dml32_ModeSupportAndSystemConfigurationFull.VMDataOnlyReturnBWPerState = dml32_get_return_bw_mbps_vm_only(&mode_lib->vba.soc, i,
mode_lib->vba.DCFCLKState[i][j], mode_lib->vba.FabricClockPerState[i],
mode_lib->vba.DRAMSpeedPerState[i]);
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 debe46b24a3e..5af601cff1a0 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
@@ -6228,3 +6228,72 @@ void dml32_CalculateImmediateFlipBandwithSupport(unsigned int NumberOfActiveSurf
*ImmediateFlipBandwidthSupport = (*TotalBandwidth <= ReturnBW);
*FractionOfUrgentBandwidth = *TotalBandwidth / ReturnBW;
}
+
+bool dml32_CalculateDETSwathFillLatencyHiding(unsigned int NumberOfActiveSurfaces,
+ double ReturnBW,
+ double UrgentLatency,
+ unsigned int SwathHeightY[],
+ unsigned int SwathHeightC[],
+ unsigned int SwathWidthY[],
+ unsigned int SwathWidthC[],
+ double BytePerPixelInDETY[],
+ double BytePerPixelInDETC[],
+ unsigned int DETBufferSizeY[],
+ unsigned int DETBufferSizeC[],
+ unsigned int NumOfDPP[],
+ unsigned int HTotal[],
+ double PixelClock[],
+ double VRatioY[],
+ double VRatioC[],
+ enum dm_use_mall_for_pstate_change_mode UsesMALLForPStateChange[DC__NUM_DPP__MAX])
+{
+ int k;
+ double SwathSizeAllSurfaces = 0;
+ double SwathSizeAllSurfacesInFetchTimeUs;
+ double DETSwathLatencyHidingUs;
+ double DETSwathLatencyHidingYUs;
+ double DETSwathLatencyHidingCUs;
+ double SwathSizePerSurfaceY[DC__NUM_DPP__MAX];
+ double SwathSizePerSurfaceC[DC__NUM_DPP__MAX];
+ bool NotEnoughDETSwathFillLatencyHiding = false;
+
+ /* calculate sum of single swath size for all pipes in bytes*/
+ for (k = 0; k < NumberOfActiveSurfaces; k++) {
+ SwathSizePerSurfaceY[k] += SwathHeightY[k] * SwathWidthY[k] * BytePerPixelInDETY[k] * NumOfDPP[k];
+
+ if (SwathHeightC[k] != 0)
+ SwathSizePerSurfaceC[k] += SwathHeightC[k] * SwathWidthC[k] * BytePerPixelInDETC[k] * NumOfDPP[k];
+ else
+ SwathSizePerSurfaceC[k] = 0;
+
+ SwathSizeAllSurfaces += SwathSizePerSurfaceY[k] + SwathSizePerSurfaceC[k];
+ }
+
+ SwathSizeAllSurfacesInFetchTimeUs = SwathSizeAllSurfaces / ReturnBW + UrgentLatency;
+
+ /* ensure all DET - 1 swath can hide a fetch for all surfaces */
+ for (k = 0; k < NumberOfActiveSurfaces; k++) {
+ double LineTime = HTotal[k] / PixelClock[k];
+
+ /* only care if surface is not phantom */
+ if (UsesMALLForPStateChange[k] != dm_use_mall_pstate_change_phantom_pipe) {
+ DETSwathLatencyHidingYUs = (dml_floor(DETBufferSizeY[k] / BytePerPixelInDETY[k] / SwathWidthY[k], 1.0) - SwathHeightY[k]) / VRatioY[k] * LineTime;
+
+ if (SwathHeightC[k] != 0) {
+ DETSwathLatencyHidingCUs = (dml_floor(DETBufferSizeC[k] / BytePerPixelInDETC[k] / SwathWidthC[k], 1.0) - SwathHeightC[k]) / VRatioC[k] * LineTime;
+
+ DETSwathLatencyHidingUs = dml_min(DETSwathLatencyHidingYUs, DETSwathLatencyHidingCUs);
+ } else {
+ DETSwathLatencyHidingUs = DETSwathLatencyHidingYUs;
+ }
+
+ /* DET must be able to hide time to fetch 1 swath for each surface */
+ if (DETSwathLatencyHidingUs < SwathSizeAllSurfacesInFetchTimeUs) {
+ NotEnoughDETSwathFillLatencyHiding = true;
+ break;
+ }
+ }
+ }
+
+ return NotEnoughDETSwathFillLatencyHiding;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h
index 3989c2a28fae..779c6805f599 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/dcn32/display_mode_vba_util_32.h
@@ -1141,4 +1141,22 @@ void dml32_CalculateImmediateFlipBandwithSupport(unsigned int NumberOfActiveSurf
double *FractionOfUrgentBandwidth,
bool *ImmediateFlipBandwidthSupport);
+bool dml32_CalculateDETSwathFillLatencyHiding(unsigned int NumberOfActiveSurfaces,
+ double ReturnBW,
+ double UrgentLatency,
+ unsigned int SwathHeightY[],
+ unsigned int SwathHeightC[],
+ unsigned int SwathWidthY[],
+ unsigned int SwathWidthC[],
+ double BytePerPixelInDETY[],
+ double BytePerPixelInDETC[],
+ unsigned int DETBufferSizeY[],
+ unsigned int DETBufferSizeC[],
+ unsigned int NumOfDPP[],
+ unsigned int HTotal[],
+ double PixelClock[],
+ double VRatioY[],
+ double VRatioC[],
+ enum dm_use_mall_for_pstate_change_mode UsesMALLForPStateChange[DC__NUM_DPP__MAX]);
+
#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 f394b3f3922a..0bffae95f3a2 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
@@ -105,14 +105,39 @@ enum source_macro_tile_size {
enum cursor_bpp {
dm_cur_2bit = 0, dm_cur_32bit = 1, dm_cur_64bit = 2
};
+
+/**
+ * @enum clock_change_support - It represents possible reasons to change the DRAM clock.
+ *
+ * DC may change the DRAM clock during its execution, and this enum tracks all
+ * the available methods. Note that every ASIC has their specific way to deal
+ * with these clock switch.
+ */
enum clock_change_support {
+ /**
+ * @dm_dram_clock_change_uninitialized: If you see this, we might have
+ * a code initialization issue
+ */
dm_dram_clock_change_uninitialized = 0,
+
+ /**
+ * @dm_dram_clock_change_vactive: Support DRAM switch in VActive
+ */
dm_dram_clock_change_vactive,
+
+ /**
+ * @dm_dram_clock_change_vblank: Support DRAM switch in VBlank
+ */
dm_dram_clock_change_vblank,
+
dm_dram_clock_change_vactive_w_mall_full_frame,
dm_dram_clock_change_vactive_w_mall_sub_vp,
dm_dram_clock_change_vblank_w_mall_full_frame,
dm_dram_clock_change_vblank_w_mall_sub_vp,
+
+ /**
+ * @dm_dram_clock_change_unsupported: Do not support DRAM switch
+ */
dm_dram_clock_change_unsupported
};
diff --git a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h
index 630f3395e90a..81e53e67cd0b 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/display_mode_vba.h
@@ -419,6 +419,15 @@ struct vba_vars_st {
double MinPixelChunkSizeBytes;
unsigned int DCCMetaBufferSizeBytes;
// Pipe/Plane Parameters
+
+ /** @VoltageLevel:
+ * Every ASIC has a fixed number of DPM states, and some devices might
+ * have some particular voltage configuration that does not map
+ * directly to the DPM states. This field tells how many states the
+ * target device supports; even though this field combines the DPM and
+ * special SOC voltages, it mostly matches the total number of DPM
+ * states.
+ */
int VoltageLevel;
double FabricClock;
double DRAMSpeed;
@@ -1041,6 +1050,7 @@ struct vba_vars_st {
double MinFullDETBufferingTime;
double AverageReadBandwidthGBytePerSecond;
bool FirstMainPlane;
+ bool NotEnoughDETSwathFillLatencyHiding;
unsigned int ViewportWidthChroma[DC__NUM_DPP__MAX];
unsigned int ViewportHeightChroma[DC__NUM_DPP__MAX];
@@ -1153,7 +1163,7 @@ struct vba_vars_st {
double UrgBurstFactorLumaPre[DC__NUM_DPP__MAX];
double UrgBurstFactorChromaPre[DC__NUM_DPP__MAX];
bool NotUrgentLatencyHidingPre[DC__NUM_DPP__MAX];
- bool LinkCapacitySupport[DC__NUM_DPP__MAX];
+ bool LinkCapacitySupport[DC__VOLTAGE_STATES];
bool VREADY_AT_OR_AFTER_VSYNC[DC__NUM_DPP__MAX];
unsigned int MIN_DST_Y_NEXT_START[DC__NUM_DPP__MAX];
unsigned int VFrontPorch[DC__NUM_DPP__MAX];
@@ -1224,6 +1234,7 @@ struct vba_vars_st {
unsigned int BlockWidthC[DC__NUM_DPP__MAX];
unsigned int SubViewportLinesNeededInMALL[DC__NUM_DPP__MAX];
bool VActiveBandwithSupport[DC__VOLTAGE_STATES][2];
+ bool NotEnoughDETSwathFillLatencyHidingPerState[DC__VOLTAGE_STATES][2];
struct dummy_vars dummy_vars;
};
diff --git a/drivers/gpu/drm/amd/display/dc/dml/dsc/qp_tables.h b/drivers/gpu/drm/amd/display/dc/dml/dsc/qp_tables.h
index e5fac9f4181d..dcff0dd2b6a1 100644
--- a/drivers/gpu/drm/amd/display/dc/dml/dsc/qp_tables.h
+++ b/drivers/gpu/drm/amd/display/dc/dml/dsc/qp_tables.h
@@ -25,7 +25,7 @@
*/
-const qp_table qp_table_422_10bpc_min = {
+static const qp_table qp_table_422_10bpc_min = {
{ 6, { 0, 4, 5, 6, 6, 6, 6, 7, 7, 8, 9, 9, 9, 12, 16} },
{ 6.5, { 0, 4, 5, 6, 6, 6, 6, 7, 7, 8, 9, 9, 9, 12, 16} },
{ 7, { 0, 4, 5, 6, 6, 6, 6, 7, 7, 7, 9, 9, 9, 11, 15} },
@@ -58,7 +58,7 @@ const qp_table qp_table_422_10bpc_min = {
};
-const qp_table qp_table_444_8bpc_max = {
+static const qp_table qp_table_444_8bpc_max = {
{ 6, { 4, 6, 8, 8, 9, 9, 9, 10, 11, 12, 12, 12, 12, 13, 15} },
{ 6.5, { 4, 6, 7, 8, 8, 8, 9, 10, 11, 11, 12, 12, 12, 13, 15} },
{ 7, { 4, 5, 7, 7, 8, 8, 8, 9, 10, 11, 11, 12, 12, 13, 14} },
@@ -99,7 +99,7 @@ const qp_table qp_table_444_8bpc_max = {
};
-const qp_table qp_table_420_12bpc_max = {
+static const qp_table qp_table_420_12bpc_max = {
{ 4, {11, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 21, 22} },
{ 4.5, {10, 11, 12, 13, 14, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} },
{ 5, { 9, 11, 12, 13, 14, 15, 15, 16, 17, 17, 18, 18, 19, 20, 21} },
@@ -132,7 +132,7 @@ const qp_table qp_table_420_12bpc_max = {
};
-const qp_table qp_table_444_10bpc_min = {
+static const qp_table qp_table_444_10bpc_min = {
{ 6, { 0, 4, 7, 7, 9, 9, 9, 9, 9, 10, 10, 10, 10, 12, 18} },
{ 6.5, { 0, 4, 6, 7, 8, 8, 9, 9, 9, 9, 10, 10, 10, 12, 18} },
{ 7, { 0, 4, 6, 6, 8, 8, 8, 8, 8, 9, 9, 10, 10, 12, 17} },
@@ -185,7 +185,7 @@ const qp_table qp_table_444_10bpc_min = {
};
-const qp_table qp_table_420_8bpc_max = {
+static const qp_table qp_table_420_8bpc_max = {
{ 4, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 13, 14} },
{ 4.5, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} },
{ 5, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 12, 13} },
@@ -206,7 +206,7 @@ const qp_table qp_table_420_8bpc_max = {
};
-const qp_table qp_table_444_8bpc_min = {
+static const qp_table qp_table_444_8bpc_min = {
{ 6, { 0, 1, 3, 3, 5, 5, 5, 5, 5, 6, 6, 6, 6, 9, 14} },
{ 6.5, { 0, 1, 2, 3, 4, 4, 5, 5, 5, 5, 6, 6, 6, 9, 14} },
{ 7, { 0, 0, 2, 2, 4, 4, 4, 4, 4, 5, 5, 6, 6, 9, 13} },
@@ -247,7 +247,7 @@ const qp_table qp_table_444_8bpc_min = {
};
-const qp_table qp_table_444_12bpc_min = {
+static const qp_table qp_table_444_12bpc_min = {
{ 6, { 0, 5, 11, 11, 13, 13, 13, 13, 13, 14, 14, 14, 14, 17, 22} },
{ 6.5, { 0, 5, 10, 11, 12, 12, 13, 13, 13, 13, 14, 14, 14, 17, 22} },
{ 7, { 0, 5, 10, 10, 12, 12, 12, 12, 12, 13, 13, 14, 14, 17, 21} },
@@ -312,7 +312,7 @@ const qp_table qp_table_444_12bpc_min = {
};
-const qp_table qp_table_420_12bpc_min = {
+static const qp_table qp_table_420_12bpc_min = {
{ 4, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 21} },
{ 4.5, { 0, 4, 8, 9, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 20} },
{ 5, { 0, 4, 8, 9, 10, 11, 11, 11, 11, 11, 13, 13, 13, 15, 20} },
@@ -345,7 +345,7 @@ const qp_table qp_table_420_12bpc_min = {
};
-const qp_table qp_table_422_12bpc_min = {
+static const qp_table qp_table_422_12bpc_min = {
{ 6, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 16, 20} },
{ 6.5, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 16, 20} },
{ 7, { 0, 4, 9, 10, 11, 11, 11, 11, 11, 11, 13, 13, 13, 15, 19} },
@@ -386,7 +386,7 @@ const qp_table qp_table_422_12bpc_min = {
};
-const qp_table qp_table_422_12bpc_max = {
+static const qp_table qp_table_422_12bpc_max = {
{ 6, {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} },
{ 6.5, {12, 12, 13, 14, 15, 15, 15, 16, 17, 18, 18, 19, 19, 20, 21} },
{ 7, {11, 12, 13, 14, 15, 15, 15, 16, 17, 17, 18, 18, 19, 19, 20} },
@@ -427,7 +427,7 @@ const qp_table qp_table_422_12bpc_max = {
};
-const qp_table qp_table_444_12bpc_max = {
+static const qp_table qp_table_444_12bpc_max = {
{ 6, {12, 14, 16, 16, 17, 17, 17, 18, 19, 20, 20, 20, 20, 21, 23} },
{ 6.5, {12, 14, 15, 16, 16, 16, 17, 18, 19, 19, 20, 20, 20, 21, 23} },
{ 7, {12, 13, 15, 15, 16, 16, 16, 17, 18, 19, 19, 20, 20, 21, 22} },
@@ -492,7 +492,7 @@ const qp_table qp_table_444_12bpc_max = {
};
-const qp_table qp_table_420_8bpc_min = {
+static const qp_table qp_table_420_8bpc_min = {
{ 4, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 9, 13} },
{ 4.5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} },
{ 5, { 0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} },
@@ -513,7 +513,7 @@ const qp_table qp_table_420_8bpc_min = {
};
-const qp_table qp_table_422_8bpc_min = {
+static const qp_table qp_table_422_8bpc_min = {
{ 6, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} },
{ 6.5, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 12} },
{ 7, { 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 11} },
@@ -538,7 +538,7 @@ const qp_table qp_table_422_8bpc_min = {
};
-const qp_table qp_table_422_10bpc_max = {
+static const qp_table qp_table_422_10bpc_max = {
{ 6, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} },
{ 6.5, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} },
{ 7, { 7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 15, 16} },
@@ -571,7 +571,7 @@ const qp_table qp_table_422_10bpc_max = {
};
-const qp_table qp_table_420_10bpc_max = {
+static const qp_table qp_table_420_10bpc_max = {
{ 4, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 17, 18} },
{ 4.5, { 8, 8, 9, 10, 11, 11, 11, 12, 13, 14, 14, 15, 15, 16, 17} },
{ 5, { 7, 8, 9, 10, 11, 11, 11, 12, 13, 13, 14, 14, 15, 16, 17} },
@@ -598,7 +598,7 @@ const qp_table qp_table_420_10bpc_max = {
};
-const qp_table qp_table_420_10bpc_min = {
+static const qp_table qp_table_420_10bpc_min = {
{ 4, { 0, 4, 4, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 13, 17} },
{ 4.5, { 0, 4, 4, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 16} },
{ 5, { 0, 4, 4, 5, 7, 7, 7, 7, 7, 7, 9, 9, 9, 12, 16} },
@@ -625,7 +625,7 @@ const qp_table qp_table_420_10bpc_min = {
};
-const qp_table qp_table_444_10bpc_max = {
+static const qp_table qp_table_444_10bpc_max = {
{ 6, { 8, 10, 12, 12, 13, 13, 13, 14, 15, 16, 16, 16, 16, 17, 19} },
{ 6.5, { 8, 10, 11, 12, 12, 12, 13, 14, 15, 15, 16, 16, 16, 17, 19} },
{ 7, { 8, 9, 11, 11, 12, 12, 12, 13, 14, 15, 15, 16, 16, 17, 18} },
@@ -678,7 +678,7 @@ const qp_table qp_table_444_10bpc_max = {
};
-const qp_table qp_table_422_8bpc_max = {
+static const qp_table qp_table_422_8bpc_max = {
{ 6, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} },
{ 6.5, { 4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 10, 11, 11, 12, 13} },
{ 7, { 3, 4, 5, 6, 7, 7, 7, 8, 9, 9, 10, 10, 11, 11, 12} },
diff --git a/drivers/gpu/drm/amd/display/dc/gpio/dcn32/hw_factory_dcn32.c b/drivers/gpu/drm/amd/display/dc/gpio/dcn32/hw_factory_dcn32.c
index 0ea52ba5ac82..9fd8b269dd79 100644
--- a/drivers/gpu/drm/amd/display/dc/gpio/dcn32/hw_factory_dcn32.c
+++ b/drivers/gpu/drm/amd/display/dc/gpio/dcn32/hw_factory_dcn32.c
@@ -256,8 +256,8 @@ static const struct hw_factory_funcs funcs = {
*/
void dal_hw_factory_dcn32_init(struct hw_factory *factory)
{
- factory->number_of_pins[GPIO_ID_DDC_DATA] = 6;
- factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 6;
+ factory->number_of_pins[GPIO_ID_DDC_DATA] = 8;
+ factory->number_of_pins[GPIO_ID_DDC_CLOCK] = 8;
factory->number_of_pins[GPIO_ID_GENERIC] = 4;
factory->number_of_pins[GPIO_ID_HPD] = 5;
factory->number_of_pins[GPIO_ID_GPIO_PAD] = 28;
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 9498105c98ab..525f8f0b8732 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -115,6 +115,13 @@ struct resource_funcs {
int vlevel);
void (*update_soc_for_wm_a)(
struct dc *dc, struct dc_state *context);
+
+ /**
+ * @populate_dml_pipes - Populate pipe data struct
+ *
+ * Returns:
+ * Total of pipes available in the specific ASIC.
+ */
int (*populate_dml_pipes)(
struct dc *dc,
struct dc_state *context,
@@ -233,8 +240,11 @@ struct resource_funcs {
unsigned int pipe_cnt,
unsigned int index);
- bool (*remove_phantom_pipes)(struct dc *dc, struct dc_state *context);
+ bool (*remove_phantom_pipes)(struct dc *dc, struct dc_state *context, bool fast_update);
+ void (*retain_phantom_pipes)(struct dc *dc, struct dc_state *context);
void (*get_panel_config_defaults)(struct dc_panel_config *panel_config);
+ void (*save_mall_state)(struct dc *dc, struct dc_state *context, struct mall_temp_config *temp_config);
+ void (*restore_mall_state)(struct dc *dc, struct dc_state *context, struct mall_temp_config *temp_config);
};
struct audio_support{
@@ -413,7 +423,10 @@ struct pipe_ctx {
struct pll_settings pll_settings;
- /* link config records software decision for what link config should be
+ /**
+ * @link_config:
+ *
+ * link config records software decision for what link config should be
* enabled given current link capability and stream during hw resource
* mapping. This is to decouple the dependency on link capability during
* dc commit or update.
@@ -507,33 +520,62 @@ struct bw_context {
union bw_output bw;
struct display_mode_lib dml;
};
+
/**
- * struct dc_state - The full description of a state requested by a user
- *
- * @streams: Stream properties
- * @stream_status: The planes on a given stream
- * @res_ctx: Persistent state of resources
- * @bw_ctx: The output from bandwidth and watermark calculations and the DML
- * @pp_display_cfg: PowerPlay clocks and settings
- * @dcn_bw_vars: non-stack memory to support bandwidth calculations
- *
+ * struct dc_state - The full description of a state requested by users
*/
struct dc_state {
+ /**
+ * @streams: Stream state properties
+ */
struct dc_stream_state *streams[MAX_PIPES];
+
+ /**
+ * @stream_status: Planes status on a given stream
+ */
struct dc_stream_status stream_status[MAX_PIPES];
+
+ /**
+ * @stream_count: Total of streams in use
+ */
uint8_t stream_count;
uint8_t stream_mask;
+ /**
+ * @res_ctx: Persistent state of resources
+ */
struct resource_context res_ctx;
+ /**
+ * @bw_ctx: The output from bandwidth and watermark calculations and the DML
+ *
+ * Each context must have its own instance of VBA, and in order to
+ * initialize and obtain IP and SOC, the base DML instance from DC is
+ * initially copied into every context.
+ */
struct bw_context bw_ctx;
- /* Note: these are big structures, do *not* put on stack! */
+ /**
+ * @pp_display_cfg: PowerPlay clocks and settings
+ * Note: this is a big struct, do *not* put on stack!
+ */
struct dm_pp_display_configuration pp_display_cfg;
+
+ /**
+ * @dcn_bw_vars: non-stack memory to support bandwidth calculations
+ * Note: this is a big struct, do *not* put on stack!
+ */
struct dcn_bw_internal_vars dcn_bw_vars;
struct clk_mgr *clk_mgr;
+ /**
+ * @refcount: refcount reference
+ *
+ * Notice that dc_state is used around the code to capture the current
+ * context, so we need to pass it everywhere. That's why we want to use
+ * kref in this struct.
+ */
struct kref refcount;
struct {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h
index b304d450b038..e8d8c5cb1309 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/dc_link_dp.h
@@ -193,7 +193,7 @@ enum dc_status dpcd_configure_lttpr_mode(
struct link_training_settings *lt_settings);
enum dp_link_encoding dp_get_link_encoding_format(const struct dc_link_settings *link_settings);
-bool dp_retrieve_lttpr_cap(struct dc_link *link);
+enum dc_status dp_retrieve_lttpr_cap(struct dc_link *link);
bool dp_is_lttpr_present(struct dc_link *link);
enum lttpr_mode dp_decide_lttpr_mode(struct dc_link *link, struct dc_link_settings *link_setting);
void dp_get_lttpr_mode_override(struct dc_link *link, enum lttpr_mode *override);
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 e7571c6f5ead..f2e1fcb668fb 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
@@ -167,10 +167,26 @@ struct hubbub_funcs {
void (*force_pstate_change_control)(struct hubbub *hubbub, bool force, bool allow);
void (*init_watermarks)(struct hubbub *hubbub);
+
+ /**
+ * @program_det_size:
+ *
+ * DE-Tile buffers (DET) is a memory that is used to convert the tiled
+ * data into linear, which the rest of the display can use to generate
+ * the graphics output. One of the main features of this component is
+ * that each pipe has a configurable DET buffer which means that when a
+ * pipe is not enabled, the device can assign the memory to other
+ * enabled pipes to try to be more efficient.
+ *
+ * DET logic is handled by dchubbub. Some ASICs provide a feature named
+ * Configurable Return Buffer (CRB) segments which can be allocated to
+ * compressed or detiled buffers.
+ */
void (*program_det_size)(struct hubbub *hubbub, int hubp_inst, unsigned det_buffer_size_in_kbyte);
void (*program_compbuf_size)(struct hubbub *hubbub, unsigned compbuf_size_kb, bool safe_to_increase);
void (*init_crb)(struct hubbub *hubbub);
void (*force_usr_retraining_allow)(struct hubbub *hubbub, bool allow);
+ void (*set_request_limit)(struct hubbub *hubbub, int memory_channel_count, int words_per_channel);
};
struct hubbub {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
index 8df2765cce78..de3113ecbc77 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dmcu.h
@@ -56,20 +56,6 @@ struct dmcu {
bool auto_load_dmcu;
};
-#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
-struct crc_region {
- uint16_t x_start;
- uint16_t y_start;
- uint16_t x_end;
- uint16_t y_end;
-};
-
-struct otg_phy_mux {
- uint8_t phy_output_num;
- uint8_t otg_output_num;
-};
-#endif
-
struct dmcu_funcs {
bool (*dmcu_init)(struct dmcu *dmcu);
bool (*load_iram)(struct dmcu *dmcu,
@@ -100,7 +86,7 @@ struct dmcu_funcs {
bool (*recv_edid_cea_ack)(struct dmcu *dmcu, int *offset);
#if defined(CONFIG_DRM_AMD_SECURE_DISPLAY)
void (*forward_crc_window)(struct dmcu *dmcu,
- struct crc_region *crc_win,
+ struct rect *rect,
struct otg_phy_mux *mux_mapping);
void (*stop_crc_win_update)(struct dmcu *dmcu,
struct otg_phy_mux *mux_mapping);
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
index dcb80c4747b0..131fcfa28bca 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h
@@ -83,10 +83,15 @@ static const struct dpp_input_csc_matrix __maybe_unused dpp_input_csc_matrix[] =
{COLOR_SPACE_YCBCR709,
{0x3265, 0x2000, 0, 0xe6ce, 0xf105, 0x2000, 0xfa01, 0xa7d, 0,
0x2000, 0x3b61, 0xe24f} },
-
{COLOR_SPACE_YCBCR709_LIMITED,
{0x39a6, 0x2568, 0, 0xe0d6, 0xeedd, 0x2568, 0xf925, 0x9a8, 0,
- 0x2568, 0x43ee, 0xdbb2} }
+ 0x2568, 0x43ee, 0xdbb2} },
+ {COLOR_SPACE_2020_YCBCR,
+ {0x2F30, 0x2000, 0, 0xE869, 0xEDB7, 0x2000, 0xFABC, 0xBC6, 0,
+ 0x2000, 0x3C34, 0xE1E6} },
+ {COLOR_SPACE_2020_RGB_LIMITEDRANGE,
+ {0x35E0, 0x255F, 0, 0xE2B3, 0xEB20, 0x255F, 0xF9FD, 0xB1E, 0,
+ 0x255F, 0x44BD, 0xDB43} }
};
struct dpp_grph_csc_adjustment {
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
index cd2be729846b..a819f0f97c5f 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/hw_shared.h
@@ -35,6 +35,13 @@
******************************************************************************/
#define MAX_AUDIOS 7
+
+/**
+ * @MAX_PIPES:
+ *
+ * Every ASIC support a fixed number of pipes; MAX_PIPES defines a large number
+ * to be used inside loops and for determining array sizes.
+ */
#define MAX_PIPES 6
#define MAX_DIG_LINK_ENCODERS 7
#define MAX_DWB_PIPES 1
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
index 42afa1952890..42db4b7b79fd 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/stream_encoder.h
@@ -243,6 +243,9 @@ struct stream_encoder_funcs {
uint32_t hubp_requestor_id,
enum dynamic_metadata_mode dmdata_mode);
+ /**
+ * @dp_set_odm_combine: Sets up DP stream encoder for ODM.
+ */
void (*dp_set_odm_combine)(
struct stream_encoder *enc,
bool odm_combine);
@@ -317,9 +320,6 @@ struct hpo_dp_stream_encoder_funcs {
uint32_t stream_enc_inst,
uint32_t link_enc_inst);
- void (*audio_mute_control)(
- struct hpo_dp_stream_encoder *enc, bool mute);
-
void (*dp_audio_setup)(
struct hpo_dp_stream_encoder *enc,
unsigned int az_inst,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
index 25a1df45b264..0e42e721dd15 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h
@@ -185,6 +185,7 @@ struct timing_generator_funcs {
#ifdef CONFIG_DRM_AMD_DC_DCN
void (*phantom_crtc_post_enable)(struct timing_generator *tg);
#endif
+ void (*disable_phantom_crtc)(struct timing_generator *tg);
bool (*immediate_disable_crtc)(struct timing_generator *tg);
bool (*is_counter_moving)(struct timing_generator *tg);
void (*get_position)(struct timing_generator *tg,
@@ -301,6 +302,11 @@ struct timing_generator_funcs {
void (*get_dsc_status)(struct timing_generator *optc,
uint32_t *dsc_mode);
void (*set_odm_bypass)(struct timing_generator *optc, const struct dc_crtc_timing *dc_crtc_timing);
+
+ /**
+ * @set_odm_combine: Set up the ODM block to read from the correct
+ * OPP(s) and turn on/off ODM memory.
+ */
void (*set_odm_combine)(struct timing_generator *optc, int *opp_id, int opp_cnt,
struct dc_crtc_timing *timing);
void (*set_h_timing_div_manual_mode)(struct timing_generator *optc, bool manual_mode);
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 d04b68dad413..c43523f9ff6d 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
@@ -263,6 +263,7 @@ struct hw_sequencer_funcs {
void (*update_phantom_vp_position)(struct dc *dc,
struct dc_state *context,
struct pipe_ctx *phantom_pipe);
+ void (*apply_update_flags_for_phantom)(struct pipe_ctx *phantom_pipe);
void (*commit_subvp_config)(struct dc *dc, struct dc_state *context);
void (*subvp_pipe_control_lock)(struct dc *dc,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h
index 89964c980b87..0f69946cce9f 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/link_hwss.h
@@ -38,6 +38,7 @@ struct link_resource;
struct pipe_ctx;
struct encoder_set_dp_phy_pattern_param;
struct link_mst_stream_allocation_table;
+struct audio_output;
struct link_hwss_ext {
/* function pointers below may require to check for NULL if caller
@@ -79,6 +80,10 @@ struct link_hwss {
void (*disable_link_output)(struct dc_link *link,
const struct link_resource *link_res,
enum signal_type signal);
+ void (*setup_audio_output)(struct pipe_ctx *pipe_ctx,
+ struct audio_output *audio_output, uint32_t audio_inst);
+ void (*enable_audio_packet)(struct pipe_ctx *pipe_ctx);
+ void (*disable_audio_packet)(struct pipe_ctx *pipe_ctx);
};
#endif /* __DC_LINK_HWSS_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn201/irq_service_dcn201.c b/drivers/gpu/drm/amd/display/dc/irq/dcn201/irq_service_dcn201.c
index 45f99351a0ab..5f4f6dd79511 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn201/irq_service_dcn201.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn201/irq_service_dcn201.c
@@ -28,20 +28,19 @@
#include "include/logger_interface.h"
#include "../dce110/irq_service_dce110.h"
+#include "irq_service_dcn201.h"
#include "dcn/dcn_2_0_3_offset.h"
#include "dcn/dcn_2_0_3_sh_mask.h"
#include "cyan_skillfish_ip_offset.h"
#include "soc15_hw_ip.h"
-
-#include "irq_service_dcn201.h"
-
#include "ivsrcid/dcn/irqsrcs_dcn_1_0.h"
-static enum dc_irq_source to_dal_irq_source_dcn201(struct irq_service *irq_service,
- uint32_t src_id,
- uint32_t ext_id)
+enum dc_irq_source to_dal_irq_source_dcn201(
+ struct irq_service *irq_service,
+ uint32_t src_id,
+ uint32_t ext_id)
{
switch (src_id) {
case DCN_1_0__SRCID__DC_D1_OTG_VSTARTUP:
@@ -79,7 +78,6 @@ static enum dc_irq_source to_dal_irq_source_dcn201(struct irq_service *irq_servi
default:
return DC_IRQ_SOURCE_INVALID;
}
- return DC_IRQ_SOURCE_INVALID;
}
static bool hpd_ack(
@@ -138,6 +136,11 @@ static const struct irq_source_info_funcs vupdate_no_lock_irq_info_funcs = {
.ack = NULL
};
+static const struct irq_source_info_funcs dmub_outbox_irq_info_funcs = {
+ .set = NULL,
+ .ack = NULL
+};
+
#undef BASE_INNER
#define BASE_INNER(seg) DMU_BASE__INST0_SEG ## seg
diff --git a/drivers/gpu/drm/amd/display/dc/irq/dcn201/irq_service_dcn201.h b/drivers/gpu/drm/amd/display/dc/irq/dcn201/irq_service_dcn201.h
index 8e27c5e219a3..0cfd2f2d62e8 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/dcn201/irq_service_dcn201.h
+++ b/drivers/gpu/drm/amd/display/dc/irq/dcn201/irq_service_dcn201.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 Advanced Micro Devices, Inc.
+ * 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"),
diff --git a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c
index 7bad39bba86b..d100edaedbbb 100644
--- a/drivers/gpu/drm/amd/display/dc/irq/irq_service.c
+++ b/drivers/gpu/drm/amd/display/dc/irq/irq_service.c
@@ -112,8 +112,15 @@ bool dal_irq_service_set(
dal_irq_service_ack(irq_service, source);
- if (info->funcs && info->funcs->set)
+ if (info->funcs && info->funcs->set) {
+ if (info->funcs->set == dal_irq_service_dummy_set) {
+ DC_LOG_WARNING("%s: src: %d, st: %d\n", __func__,
+ source, enable);
+ ASSERT(0);
+ }
+
return info->funcs->set(irq_service, info, enable);
+ }
dal_irq_service_set_generic(irq_service, info, enable);
@@ -146,8 +153,14 @@ bool dal_irq_service_ack(
return false;
}
- if (info->funcs && info->funcs->ack)
+ if (info->funcs && info->funcs->ack) {
+ if (info->funcs->ack == dal_irq_service_dummy_ack) {
+ DC_LOG_WARNING("%s: src: %d\n", __func__, source);
+ ASSERT(0);
+ }
+
return info->funcs->ack(irq_service, info);
+ }
dal_irq_service_ack_generic(irq_service, info);
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_dpia_bw.c b/drivers/gpu/drm/amd/display/dc/link/link_dp_dpia_bw.c
new file mode 100644
index 000000000000..801a95b34e8c
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/link/link_dp_dpia_bw.c
@@ -0,0 +1,28 @@
+
+/*
+ * 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.
+ *
+ * Authors: AMD
+ *
+ */
+/*********************************************************************/
+// USB4 DPIA BANDWIDTH ALLOCATION LOGIC
+/*********************************************************************/
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dp_dpia_bw.h b/drivers/gpu/drm/amd/display/dc/link/link_dp_dpia_bw.h
new file mode 100644
index 000000000000..669e995f825f
--- /dev/null
+++ b/drivers/gpu/drm/amd/display/dc/link/link_dp_dpia_bw.h
@@ -0,0 +1,69 @@
+/*
+ * 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 DC_INC_LINK_DP_DPIA_BW_H_
+#define DC_INC_LINK_DP_DPIA_BW_H_
+
+// XXX: TODO: Re-add for Phase 2
+/* Number of Host Routers per motherboard is 2 and 2 DPIA per host router */
+#define MAX_HR_NUM 2
+
+struct dc_host_router_bw_alloc {
+ int max_bw[MAX_HR_NUM]; // The Max BW that each Host Router has available to be shared btw DPIAs
+ int total_estimated_bw[MAX_HR_NUM]; // The Total Verified and available BW that Host Router has
+};
+
+/*
+ * Enable BW Allocation Mode Support from the DP-Tx side
+ *
+ * @link: pointer to the dc_link struct instance
+ *
+ * return: SUCCESS or FAILURE
+ */
+bool set_dptx_usb4_bw_alloc_support(struct dc_link *link);
+
+/*
+ * Send a request from DP-Tx requesting to allocate BW remotely after
+ * allocating it locally. This will get processed by CM and a CB function
+ * will be called.
+ *
+ * @link: pointer to the dc_link struct instance
+ * @req_bw: The requested bw in Kbyte to allocated
+ *
+ * return: none
+ */
+void set_usb4_req_bw_req(struct dc_link *link, int req_bw);
+
+/*
+ * CB function for when the status of the Req above is complete. We will
+ * find out the result of allocating on CM and update structs accordingly
+ *
+ * @link: pointer to the dc_link struct instance
+ *
+ * return: none
+ */
+void get_usb4_req_bw_resp(struct dc_link *link);
+
+#endif /* DC_INC_LINK_DP_DPIA_BW_H_ */
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c
index 4227adbc646a..33148b753c03 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.c
@@ -170,11 +170,63 @@ static void update_dio_stream_allocation_table(struct dc_link *link,
link_enc->funcs->update_mst_stream_allocation_table(link_enc, table);
}
+void setup_dio_audio_output(struct pipe_ctx *pipe_ctx,
+ struct audio_output *audio_output, uint32_t audio_inst)
+{
+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
+ pipe_ctx->stream_res.stream_enc->funcs->dp_audio_setup(
+ pipe_ctx->stream_res.stream_enc,
+ audio_inst,
+ &pipe_ctx->stream->audio_info);
+ else
+ pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_setup(
+ pipe_ctx->stream_res.stream_enc,
+ audio_inst,
+ &pipe_ctx->stream->audio_info,
+ &audio_output->crtc_info);
+}
+
+void enable_dio_audio_packet(struct pipe_ctx *pipe_ctx)
+{
+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
+ pipe_ctx->stream_res.stream_enc->funcs->dp_audio_enable(
+ pipe_ctx->stream_res.stream_enc);
+
+ pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
+ pipe_ctx->stream_res.stream_enc, false);
+
+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
+ dp_source_sequence_trace(pipe_ctx->stream->link,
+ DPCD_SOURCE_SEQ_AFTER_ENABLE_AUDIO_STREAM);
+}
+
+void disable_dio_audio_packet(struct pipe_ctx *pipe_ctx)
+{
+ pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
+ pipe_ctx->stream_res.stream_enc, true);
+
+ if (pipe_ctx->stream_res.audio) {
+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
+ pipe_ctx->stream_res.stream_enc->funcs->dp_audio_disable(
+ pipe_ctx->stream_res.stream_enc);
+ else
+ pipe_ctx->stream_res.stream_enc->funcs->hdmi_audio_disable(
+ pipe_ctx->stream_res.stream_enc);
+ }
+
+ if (dc_is_dp_signal(pipe_ctx->stream->signal))
+ dp_source_sequence_trace(pipe_ctx->stream->link,
+ DPCD_SOURCE_SEQ_AFTER_DISABLE_AUDIO_STREAM);
+}
+
static const struct link_hwss dio_link_hwss = {
.setup_stream_encoder = setup_dio_stream_encoder,
.reset_stream_encoder = reset_dio_stream_encoder,
.setup_stream_attribute = setup_dio_stream_attribute,
.disable_link_output = disable_dio_link_output,
+ .setup_audio_output = setup_dio_audio_output,
+ .enable_audio_packet = enable_dio_audio_packet,
+ .disable_audio_packet = disable_dio_audio_packet,
.ext = {
.set_throttled_vcp_size = set_dio_throttled_vcp_size,
.enable_dp_link_output = enable_dio_dp_link_output,
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h
index 126d37f847a1..9a108c3d7831 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h
+++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dio.h
@@ -50,5 +50,9 @@ void set_dio_dp_lane_settings(struct dc_link *link,
const struct link_resource *link_res,
const struct dc_link_settings *link_settings,
const struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX]);
+void setup_dio_audio_output(struct pipe_ctx *pipe_ctx,
+ struct audio_output *audio_output, uint32_t audio_inst);
+void enable_dio_audio_packet(struct pipe_ctx *pipe_ctx);
+void disable_dio_audio_packet(struct pipe_ctx *pipe_ctx);
#endif /* __LINK_HWSS_DIO_H__ */
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c
index 64f7ea6a9aa3..861f3cd5b356 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_dpia.c
@@ -57,6 +57,9 @@ static const struct link_hwss dpia_link_hwss = {
.reset_stream_encoder = reset_dio_stream_encoder,
.setup_stream_attribute = setup_dio_stream_attribute,
.disable_link_output = disable_dio_link_output,
+ .setup_audio_output = setup_dio_audio_output,
+ .enable_audio_packet = enable_dio_audio_packet,
+ .disable_audio_packet = disable_dio_audio_packet,
.ext = {
.set_throttled_vcp_size = set_dio_throttled_vcp_size,
.enable_dp_link_output = enable_dio_dp_link_output,
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c b/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c
index 153a88381f2c..2f46e1ac4ce0 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_hwss_hpo_dp.c
@@ -262,11 +262,36 @@ static void update_hpo_dp_stream_allocation_table(struct dc_link *link,
table);
}
+static void setup_hpo_dp_audio_output(struct pipe_ctx *pipe_ctx,
+ struct audio_output *audio_output, uint32_t audio_inst)
+{
+ pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_setup(
+ pipe_ctx->stream_res.hpo_dp_stream_enc,
+ audio_inst,
+ &pipe_ctx->stream->audio_info);
+}
+
+static void enable_hpo_dp_audio_packet(struct pipe_ctx *pipe_ctx)
+{
+ pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_enable(
+ pipe_ctx->stream_res.hpo_dp_stream_enc);
+}
+
+static void disable_hpo_dp_audio_packet(struct pipe_ctx *pipe_ctx)
+{
+ if (pipe_ctx->stream_res.audio)
+ pipe_ctx->stream_res.hpo_dp_stream_enc->funcs->dp_audio_disable(
+ pipe_ctx->stream_res.hpo_dp_stream_enc);
+}
+
static const struct link_hwss hpo_dp_link_hwss = {
.setup_stream_encoder = setup_hpo_dp_stream_encoder,
.reset_stream_encoder = reset_hpo_dp_stream_encoder,
.setup_stream_attribute = setup_hpo_dp_stream_attribute,
.disable_link_output = disable_hpo_dp_link_output,
+ .setup_audio_output = setup_hpo_dp_audio_output,
+ .enable_audio_packet = enable_hpo_dp_audio_packet,
+ .disable_audio_packet = disable_hpo_dp_audio_packet,
.ext = {
.set_throttled_vcp_size = set_hpo_dp_throttled_vcp_size,
.set_hblank_min_symbol_width = set_hpo_dp_hblank_min_symbol_width,
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 7a8f61517424..33907feefebb 100644
--- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
+++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
@@ -225,6 +225,12 @@ union dmub_psr_debug_flags {
* Use TPS3 signal when restore main link.
*/
uint32_t force_wakeup_by_tps3 : 1;
+
+ /**
+ * Back to back flip, therefore cannot power down PHY
+ */
+ uint32_t back_to_back_flip : 1;
+
} bitfields;
/**
@@ -401,8 +407,9 @@ union dmub_fw_boot_options {
uint32_t gpint_scratch8: 1; /* 1 if GPINT is in scratch8*/
uint32_t usb4_cm_version: 1; /**< 1 CM support */
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 reserved : 16; /**< reserved */
+ uint32_t reserved : 15; /**< reserved */
} bits; /**< boot bits */
uint32_t all; /**< 32-bit access to bits */
};
@@ -731,6 +738,11 @@ enum dmub_cmd_type {
*/
/**
+ * Command type used for all SECURE_DISPLAY commands.
+ */
+ DMUB_CMD__SECURE_DISPLAY = 85,
+
+ /**
* Command type used to set DPIA HPD interrupt state
*/
DMUB_CMD__DPIA_HPD_INT_ENABLE = 86,
@@ -1017,13 +1029,14 @@ struct dmub_cmd_fw_assisted_mclk_switch_pipe_data_v2 {
uint16_t vtotal;
uint16_t htotal;
uint8_t vblank_pipe_index;
- uint8_t padding[2];
+ uint8_t padding[1];
struct {
uint8_t drr_in_use;
uint8_t drr_window_size_ms; // Indicates largest VMIN/VMAX adjustment per frame
uint16_t min_vtotal_supported; // Min VTOTAL that supports switching in VBLANK
uint16_t max_vtotal_supported; // Max VTOTAL that can support SubVP static scheduling
uint8_t use_ramping; // Use ramping or not
+ uint8_t drr_vblank_start_margin;
} drr_info; // DRR considered as part of SubVP + VBLANK case
} vblank_data;
} pipe_config;
@@ -1866,9 +1879,13 @@ struct dmub_cmd_psr_copy_settings_data {
*/
uint8_t use_phy_fsm;
/**
+ * frame delay for frame re-lock
+ */
+ uint8_t relock_delay_frame_cnt;
+ /**
* Explicit padding to 2 byte boundary.
*/
- uint8_t pad3[2];
+ uint8_t pad3;
};
/**
@@ -3144,6 +3161,33 @@ struct dmub_rb_cmd_get_usbc_cable_id {
};
/**
+ * Command type of a DMUB_CMD__SECURE_DISPLAY command
+ */
+enum dmub_cmd_secure_display_type {
+ DMUB_CMD__SECURE_DISPLAY_TEST_CMD = 0, /* test command to only check if inbox message works */
+ DMUB_CMD__SECURE_DISPLAY_CRC_STOP_UPDATE,
+ DMUB_CMD__SECURE_DISPLAY_CRC_WIN_NOTIFY
+};
+
+/**
+ * Definition of a DMUB_CMD__SECURE_DISPLAY command
+ */
+struct dmub_rb_cmd_secure_display {
+ struct dmub_cmd_header header;
+ /**
+ * Data passed from driver to dmub firmware.
+ */
+ struct dmub_cmd_roi_info {
+ uint16_t x_start;
+ uint16_t x_end;
+ uint16_t y_start;
+ uint16_t y_end;
+ uint8_t otg_id;
+ uint8_t phy_id;
+ } roi_info;
+};
+
+/**
* union dmub_rb_cmd - DMUB inbox command.
*/
union dmub_rb_cmd {
@@ -3348,6 +3392,11 @@ union dmub_rb_cmd {
*/
struct dmub_rb_cmd_query_hpd_state query_hpd;
/**
+ * Definition of a DMUB_CMD__SECURE_DISPLAY command.
+ */
+ struct dmub_rb_cmd_secure_display secure_display;
+
+ /**
* Definition of a DMUB_CMD__DPIA_HPD_INT_ENABLE command.
*/
struct dmub_rb_cmd_dpia_hpd_int_enable dpia_hpd_int_enable;
diff --git a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
index 447a0ec9cbe2..f6034213c700 100644
--- a/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
+++ b/drivers/gpu/drm/amd/display/modules/color/color_gamma.c
@@ -61,7 +61,7 @@ static const int32_t numerator01[] = { 31308, 180000, 0, 0, 0};
static const int32_t numerator02[] = { 12920, 4500, 0, 0, 0};
static const int32_t numerator03[] = { 55, 99, 0, 0, 0};
static const int32_t numerator04[] = { 55, 99, 0, 0, 0};
-static const int32_t numerator05[] = { 2400, 2200, 2200, 2400, 2600};
+static const int32_t numerator05[] = { 2400, 2222, 2200, 2400, 2600};
/* one-time setup of X points */
void setup_x_points_distribution(void)
diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
index 0f39ab9dc5b4..c2e00f7b8381 100644
--- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
+++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
@@ -688,10 +688,10 @@ static void build_vrr_infopacket_fs2_data(enum color_transfer_func app_tf,
if (app_tf != TRANSFER_FUNC_UNKNOWN) {
infopacket->valid = true;
- infopacket->sb[6] |= 0x08; // PB6 = [Bit 3 = Native Color Active]
-
- if (app_tf == TRANSFER_FUNC_GAMMA_22) {
- infopacket->sb[9] |= 0x04; // PB6 = [Bit 2 = Gamma 2.2 EOTF Active]
+ if (app_tf != TRANSFER_FUNC_PQ2084) {
+ infopacket->sb[6] |= 0x08; // PB6 = [Bit 3 = Native Color Active]
+ if (app_tf == TRANSFER_FUNC_GAMMA_22)
+ infopacket->sb[9] |= 0x04; // PB6 = [Bit 2 = Gamma 2.2 EOTF Active]
}
}
}
diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
index 1d8b746b02f2..edf5845f6a1f 100644
--- a/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
+++ b/drivers/gpu/drm/amd/display/modules/inc/mod_info_packet.h
@@ -35,7 +35,8 @@ struct mod_vrr_params;
void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
struct dc_info_packet *info_packet,
- enum dc_color_space cs);
+ enum dc_color_space cs,
+ enum color_transfer_func tf);
void mod_build_hf_vsif_infopacket(const struct dc_stream_state *stream,
struct dc_info_packet *info_packet);
diff --git a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
index 27ceba9d6d65..69691058ab89 100644
--- a/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
+++ b/drivers/gpu/drm/amd/display/modules/info_packet/info_packet.c
@@ -132,7 +132,8 @@ enum ColorimetryYCCDP {
void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
struct dc_info_packet *info_packet,
- enum dc_color_space cs)
+ enum dc_color_space cs,
+ enum color_transfer_func tf)
{
unsigned int vsc_packet_revision = vsc_packet_undefined;
unsigned int i;
@@ -382,6 +383,9 @@ void mod_build_vsc_infopacket(const struct dc_stream_state *stream,
colorimetryFormat = ColorimetryYCC_DP_AdobeYCC;
else if (cs == COLOR_SPACE_2020_YCBCR)
colorimetryFormat = ColorimetryYCC_DP_ITU2020YCbCr;
+
+ if (cs == COLOR_SPACE_2020_YCBCR && tf == TRANSFER_FUNC_GAMMA_22)
+ colorimetryFormat = ColorimetryYCC_DP_ITU709;
break;
default:
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 235259d6c5a1..9b5d9b2c9a6a 100644
--- a/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
+++ b/drivers/gpu/drm/amd/display/modules/power/power_helpers.c
@@ -102,9 +102,18 @@ static const struct abm_parameters abm_settings_config1[abm_defines_max_level] =
{0x82, 0x4d, 0x20, 0x00, 0x00, 0xff, 0xb3, 0x70, 0x70, 0xcccc, 0xcccc},
};
+static const struct abm_parameters abm_settings_config2[abm_defines_max_level] = {
+// min_red max_red bright_pos dark_pos bright_gain contrast dev min_knee max_knee blRed blStart
+ {0xf0, 0xbf, 0x20, 0x00, 0x88, 0x99, 0xb3, 0x40, 0xe0, 0x0000, 0xcccc},
+ {0xd8, 0x85, 0x20, 0x00, 0x70, 0x90, 0xa8, 0x40, 0xc8, 0x0700, 0xb333},
+ {0xb8, 0x58, 0x20, 0x00, 0x64, 0x88, 0x78, 0x70, 0xa0, 0x7000, 0x9999},
+ {0x82, 0x40, 0x20, 0x00, 0x00, 0xb8, 0xb3, 0x70, 0x70, 0xc333, 0xb333},
+};
+
static const struct abm_parameters * const abm_settings[] = {
abm_settings_config0,
abm_settings_config1,
+ abm_settings_config2,
};
#define NUM_AMBI_LEVEL 5
diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_offset.h
index 483769fb1736..537aee0536d3 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_offset.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_offset.h
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: MIT
#ifndef _dcn_3_0_0_OFFSET_HEADER
#define _dcn_3_0_0_OFFSET_HEADER
diff --git a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h
index b79be3a25a80..f9d90b098519 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/dcn/dcn_3_0_0_sh_mask.h
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: MIT
#ifndef _dcn_3_0_0_SH_MASK_HEADER
#define _dcn_3_0_0_SH_MASK_HEADER
diff --git a/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_2_5_offset.h b/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_2_5_offset.h
index 363d2139cea2..db7e22720d00 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_2_5_offset.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_2_5_offset.h
@@ -993,7 +993,8 @@
#define mmUVD_RAS_VCPU_VCODEC_STATUS_BASE_IDX 1
#define mmUVD_RAS_MMSCH_FATAL_ERROR 0x0058
#define mmUVD_RAS_MMSCH_FATAL_ERROR_BASE_IDX 1
-
+#define mmVCN_RAS_CNTL 0x04b9
+#define mmVCN_RAS_CNTL_BASE_IDX 1
/* JPEG 2_6_0 regs */
#define mmUVD_RAS_JPEG0_STATUS 0x0059
diff --git a/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_2_5_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_2_5_sh_mask.h
index 8de883b76d90..874a8b7e1feb 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_2_5_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_2_5_sh_mask.h
@@ -3618,6 +3618,33 @@
#define UVD_RAS_MMSCH_FATAL_ERROR__POISONED_VF_MASK 0x7FFFFFFFL
#define UVD_RAS_MMSCH_FATAL_ERROR__POISONED_PF_MASK 0x80000000L
+//VCN 2_6_0 VCN_RAS_CNTL
+#define VCN_RAS_CNTL__VCPU_VCODEC_IH_EN__SHIFT 0x0
+#define VCN_RAS_CNTL__MMSCH_FATAL_ERROR_EN__SHIFT 0x1
+#define VCN_RAS_CNTL__VCPU_VCODEC_PMI_EN__SHIFT 0x4
+#define VCN_RAS_CNTL__MMSCH_PMI_EN__SHIFT 0x5
+#define VCN_RAS_CNTL__VCPU_VCODEC_REARM__SHIFT 0x8
+#define VCN_RAS_CNTL__MMSCH_REARM__SHIFT 0x9
+#define VCN_RAS_CNTL__VCPU_VCODEC_STALL_EN__SHIFT 0xc
+#define VCN_RAS_CNTL__VCPU_VCODEC_READY__SHIFT 0x10
+#define VCN_RAS_CNTL__MMSCH_READY__SHIFT 0x11
+#define VCN_RAS_CNTL__VCPU_VCODEC_IH_EN_MASK 0x00000001L
+#define VCN_RAS_CNTL__MMSCH_FATAL_ERROR_EN_MASK 0x00000002L
+#define VCN_RAS_CNTL__VCPU_VCODEC_PMI_EN_MASK 0x00000010L
+#define VCN_RAS_CNTL__MMSCH_PMI_EN_MASK 0x00000020L
+#define VCN_RAS_CNTL__VCPU_VCODEC_REARM_MASK 0x00000100L
+#define VCN_RAS_CNTL__MMSCH_REARM_MASK 0x00000200L
+#define VCN_RAS_CNTL__VCPU_VCODEC_STALL_EN_MASK 0x00001000L
+#define VCN_RAS_CNTL__VCPU_VCODEC_READY_MASK 0x00010000L
+#define VCN_RAS_CNTL__MMSCH_READY_MASK 0x00020000L
+
+//VCN 2_6_0 UVD_VCPU_INT_EN
+#define UVD_VCPU_INT_EN__RASCNTL_VCPU_VCODEC_EN__SHIFT 0x16
+#define UVD_VCPU_INT_EN__RASCNTL_VCPU_VCODEC_EN_MASK 0x00400000L
+
+//VCN 2_6_0 UVD_SYS_INT_EN
+#define UVD_SYS_INT_EN__RASCNTL_VCPU_VCODEC_EN_MASK 0x04000000L
+
/* JPEG 2_6_0 UVD_RAS_JPEG0_STATUS */
#define UVD_RAS_JPEG0_STATUS__POISONED_VF__SHIFT 0x0
#define UVD_RAS_JPEG0_STATUS__POISONED_PF__SHIFT 0x1f
diff --git a/drivers/gpu/drm/amd/include/atombios.h b/drivers/gpu/drm/amd/include/atombios.h
index 15943bc21bc5..b78360a71bc9 100644
--- a/drivers/gpu/drm/amd/include/atombios.h
+++ b/drivers/gpu/drm/amd/include/atombios.h
@@ -4107,7 +4107,7 @@ typedef struct _ATOM_FAKE_EDID_PATCH_RECORD
{
UCHAR ucRecordType;
UCHAR ucFakeEDIDLength; // = 128 means EDID length is 128 bytes, otherwise the EDID length = ucFakeEDIDLength*128
- UCHAR ucFakeEDIDString[1]; // This actually has ucFakeEdidLength elements.
+ UCHAR ucFakeEDIDString[]; // This actually has ucFakeEdidLength elements.
} ATOM_FAKE_EDID_PATCH_RECORD;
typedef struct _ATOM_PANEL_RESOLUTION_PATCH_RECORD
@@ -4386,7 +4386,7 @@ typedef struct _ATOM_GPIO_PIN_ASSIGNMENT
typedef struct _ATOM_GPIO_PIN_LUT
{
ATOM_COMMON_TABLE_HEADER sHeader;
- ATOM_GPIO_PIN_ASSIGNMENT asGPIO_Pin[1];
+ ATOM_GPIO_PIN_ASSIGNMENT asGPIO_Pin[];
}ATOM_GPIO_PIN_LUT;
/****************************************************************************/
@@ -4513,7 +4513,7 @@ typedef struct _ATOM_DISPLAY_OBJECT_PATH
USHORT usSize; //the size of ATOM_DISPLAY_OBJECT_PATH
USHORT usConnObjectId; //Connector Object ID
USHORT usGPUObjectId; //GPU ID
- USHORT usGraphicObjIds[1]; //1st Encoder Obj source from GPU to last Graphic Obj destinate to connector.
+ USHORT usGraphicObjIds[]; //1st Encoder Obj source from GPU to last Graphic Obj destinate to connector.
}ATOM_DISPLAY_OBJECT_PATH;
typedef struct _ATOM_DISPLAY_EXTERNAL_OBJECT_PATH
@@ -4530,7 +4530,7 @@ typedef struct _ATOM_DISPLAY_OBJECT_PATH_TABLE
UCHAR ucNumOfDispPath;
UCHAR ucVersion;
UCHAR ucPadding[2];
- ATOM_DISPLAY_OBJECT_PATH asDispPath[1];
+ ATOM_DISPLAY_OBJECT_PATH asDispPath[];
}ATOM_DISPLAY_OBJECT_PATH_TABLE;
typedef struct _ATOM_OBJECT //each object has this structure
@@ -4545,7 +4545,7 @@ typedef struct _ATOM_OBJECT_TABLE //Above 4 object table
{
UCHAR ucNumberOfObjects;
UCHAR ucPadding[3];
- ATOM_OBJECT asObjects[1];
+ ATOM_OBJECT asObjects[];
}ATOM_OBJECT_TABLE;
typedef struct _ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT //usSrcDstTableOffset pointing to this structure
@@ -4733,7 +4733,7 @@ typedef struct _ATOM_CONNECTOR_DEVICE_TAG_RECORD
ATOM_COMMON_RECORD_HEADER sheader;
UCHAR ucNumberOfDevice;
UCHAR ucReserved;
- ATOM_CONNECTOR_DEVICE_TAG asDeviceTag[1]; //This Id is same as "ATOM_DEVICE_XXX_SUPPORT", 1 is only for allocation
+ ATOM_CONNECTOR_DEVICE_TAG asDeviceTag[]; //This Id is same as "ATOM_DEVICE_XXX_SUPPORT"
}ATOM_CONNECTOR_DEVICE_TAG_RECORD;
@@ -4793,7 +4793,7 @@ typedef struct _ATOM_OBJECT_GPIO_CNTL_RECORD
ATOM_COMMON_RECORD_HEADER sheader;
UCHAR ucFlags; // Future expnadibility
UCHAR ucNumberOfPins; // Number of GPIO pins used to control the object
- ATOM_GPIO_PIN_CONTROL_PAIR asGpio[1]; // the real gpio pin pair determined by number of pins ucNumberOfPins
+ ATOM_GPIO_PIN_CONTROL_PAIR asGpio[]; // the real gpio pin pair determined by number of pins ucNumberOfPins
}ATOM_OBJECT_GPIO_CNTL_RECORD;
//Definitions for GPIO pin state
@@ -4982,7 +4982,7 @@ typedef struct _ATOM_BRACKET_LAYOUT_RECORD
UCHAR ucWidth;
UCHAR ucConnNum;
UCHAR ucReserved;
- ATOM_CONNECTOR_LAYOUT_INFO asConnInfo[1];
+ ATOM_CONNECTOR_LAYOUT_INFO asConnInfo[];
}ATOM_BRACKET_LAYOUT_RECORD;
@@ -5146,7 +5146,7 @@ typedef struct _ATOM_I2C_VOLTAGE_OBJECT_V3
UCHAR ucVoltageControlOffset;
UCHAR ucVoltageControlFlag; // Bit0: 0 - One byte data; 1 - Two byte data
UCHAR ulReserved[3];
- VOLTAGE_LUT_ENTRY asVolI2cLut[1]; // end with 0xff
+ VOLTAGE_LUT_ENTRY asVolI2cLut[]; // end with 0xff
}ATOM_I2C_VOLTAGE_OBJECT_V3;
// ATOM_I2C_VOLTAGE_OBJECT_V3.ucVoltageControlFlag
@@ -5161,7 +5161,7 @@ typedef struct _ATOM_GPIO_VOLTAGE_OBJECT_V3
UCHAR ucPhaseDelay; // phase delay in unit of micro second
UCHAR ucReserved;
ULONG ulGpioMaskVal; // GPIO Mask value
- VOLTAGE_LUT_ENTRY_V2 asVolGpioLut[1];
+ VOLTAGE_LUT_ENTRY_V2 asVolGpioLut[];
}ATOM_GPIO_VOLTAGE_OBJECT_V3;
typedef struct _ATOM_LEAKAGE_VOLTAGE_OBJECT_V3
@@ -5171,7 +5171,7 @@ typedef struct _ATOM_LEAKAGE_VOLTAGE_OBJECT_V3
UCHAR ucLeakageEntryNum; // indicate the entry number of LeakageId/Voltage Lut table
UCHAR ucReserved[2];
ULONG ulMaxVoltageLevel;
- LEAKAGE_VOLTAGE_LUT_ENTRY_V2 asLeakageIdLut[1];
+ LEAKAGE_VOLTAGE_LUT_ENTRY_V2 asLeakageIdLut[];
}ATOM_LEAKAGE_VOLTAGE_OBJECT_V3;
@@ -6599,7 +6599,7 @@ typedef struct _ATOM_FUSION_SYSTEM_INFO_V3
typedef struct _ATOM_I2C_DATA_RECORD
{
UCHAR ucNunberOfBytes; //Indicates how many bytes SW needs to write to the external ASIC for one block, besides to "Start" and "Stop"
- UCHAR ucI2CData[1]; //I2C data in bytes, should be less than 16 bytes usually
+ UCHAR ucI2CData[]; //I2C data in bytes, should be less than 16 bytes usually
}ATOM_I2C_DATA_RECORD;
@@ -6610,14 +6610,14 @@ typedef struct _ATOM_I2C_DEVICE_SETUP_INFO
UCHAR ucSSChipID; //SS chip being used
UCHAR ucSSChipSlaveAddr; //Slave Address to set up this SS chip
UCHAR ucNumOfI2CDataRecords; //number of data block
- ATOM_I2C_DATA_RECORD asI2CData[1];
+ ATOM_I2C_DATA_RECORD asI2CData[];
}ATOM_I2C_DEVICE_SETUP_INFO;
//==========================================================================================
typedef struct _ATOM_ASIC_MVDD_INFO
{
ATOM_COMMON_TABLE_HEADER sHeader;
- ATOM_I2C_DEVICE_SETUP_INFO asI2CSetup[1];
+ ATOM_I2C_DEVICE_SETUP_INFO asI2CSetup[];
}ATOM_ASIC_MVDD_INFO;
//==========================================================================================
@@ -6679,7 +6679,7 @@ typedef struct _ATOM_ASIC_INTERNAL_SS_INFO
typedef struct _ATOM_ASIC_INTERNAL_SS_INFO_V2
{
ATOM_COMMON_TABLE_HEADER sHeader;
- ATOM_ASIC_SS_ASSIGNMENT_V2 asSpreadSpectrum[1]; //this is point only.
+ ATOM_ASIC_SS_ASSIGNMENT_V2 asSpreadSpectrum[]; //this is point only.
}ATOM_ASIC_INTERNAL_SS_INFO_V2;
typedef struct _ATOM_ASIC_SS_ASSIGNMENT_V3
@@ -6701,7 +6701,7 @@ typedef struct _ATOM_ASIC_SS_ASSIGNMENT_V3
typedef struct _ATOM_ASIC_INTERNAL_SS_INFO_V3
{
ATOM_COMMON_TABLE_HEADER sHeader;
- ATOM_ASIC_SS_ASSIGNMENT_V3 asSpreadSpectrum[1]; //this is pointer only.
+ ATOM_ASIC_SS_ASSIGNMENT_V3 asSpreadSpectrum[]; //this is pointer only.
}ATOM_ASIC_INTERNAL_SS_INFO_V3;
@@ -9292,7 +9292,7 @@ typedef struct {
typedef struct {
VFCT_IMAGE_HEADER VbiosHeader;
- UCHAR VbiosContent[1];
+ UCHAR VbiosContent[];
}GOP_VBIOS_CONTENT;
typedef struct {
diff --git a/drivers/gpu/drm/amd/include/atomfirmware.h b/drivers/gpu/drm/amd/include/atomfirmware.h
index ff855cb21d3f..bbe1337a8cee 100644
--- a/drivers/gpu/drm/amd/include/atomfirmware.h
+++ b/drivers/gpu/drm/amd/include/atomfirmware.h
@@ -705,20 +705,65 @@ struct atom_gpio_pin_lut_v2_1
};
-/*
- ***************************************************************************
- Data Table vram_usagebyfirmware structure
- ***************************************************************************
-*/
+/*
+ * VBIOS/PRE-OS always reserve a FB region at the top of frame buffer. driver should not write
+ * access that region. driver can allocate their own reservation region as long as it does not
+ * overlap firwmare's reservation region.
+ * if (pre-NV1X) atom data table firmwareInfoTable version < 3.3:
+ * in this case, atom data table vram_usagebyfirmwareTable version always <= 2.1
+ * if VBIOS/UEFI GOP is posted:
+ * VBIOS/UEFIGOP update used_by_firmware_in_kb = total reserved size by VBIOS
+ * update start_address_in_kb = total_mem_size_in_kb - used_by_firmware_in_kb;
+ * ( total_mem_size_in_kb = reg(CONFIG_MEMSIZE)<<10)
+ * driver can allocate driver reservation region under firmware reservation,
+ * used_by_driver_in_kb = driver reservation size
+ * driver reservation start address = (start_address_in_kb - used_by_driver_in_kb)
+ * Comment1[hchan]: There is only one reservation at the beginning of the FB reserved by
+ * host driver. Host driver would overwrite the table with the following
+ * used_by_firmware_in_kb = total reserved size for pf-vf info exchange and
+ * set SRIOV_MSG_SHARE_RESERVATION mask start_address_in_kb = 0
+ * else there is no VBIOS reservation region:
+ * driver must allocate driver reservation region at top of FB.
+ * driver set used_by_driver_in_kb = driver reservation size
+ * driver reservation start address = (total_mem_size_in_kb - used_by_driver_in_kb)
+ * same as Comment1
+ * else (NV1X and after):
+ * if VBIOS/UEFI GOP is posted:
+ * VBIOS/UEFIGOP update:
+ * used_by_firmware_in_kb = atom_firmware_Info_v3_3.fw_reserved_size_in_kb;
+ * start_address_in_kb = total_mem_size_in_kb - used_by_firmware_in_kb;
+ * (total_mem_size_in_kb = reg(CONFIG_MEMSIZE)<<10)
+ * if vram_usagebyfirmwareTable version <= 2.1:
+ * driver can allocate driver reservation region under firmware reservation,
+ * driver set used_by_driver_in_kb = driver reservation size
+ * driver reservation start address = start_address_in_kb - used_by_driver_in_kb
+ * same as Comment1
+ * else driver can:
+ * allocate it reservation any place as long as it does overlap pre-OS FW reservation area
+ * set used_by_driver_region0_in_kb = driver reservation size
+ * set driver_region0_start_address_in_kb = driver reservation region start address
+ * Comment2[hchan]: Host driver can set used_by_firmware_in_kb and start_address_in_kb to
+ * zero as the reservation for VF as it doesn’t exist. And Host driver should also
+ * update atom_firmware_Info table to remove the same VBIOS reservation as well.
+ */
struct vram_usagebyfirmware_v2_1
{
- struct atom_common_table_header table_header;
- uint32_t start_address_in_kb;
- uint16_t used_by_firmware_in_kb;
- uint16_t used_by_driver_in_kb;
+ struct atom_common_table_header table_header;
+ uint32_t start_address_in_kb;
+ uint16_t used_by_firmware_in_kb;
+ uint16_t used_by_driver_in_kb;
};
+struct vram_usagebyfirmware_v2_2 {
+ struct atom_common_table_header table_header;
+ uint32_t fw_region_start_address_in_kb;
+ uint16_t used_by_firmware_in_kb;
+ uint16_t reserved;
+ uint32_t driver_region0_start_address_in_kb;
+ uint32_t used_by_driver_region0_in_kb;
+ uint32_t reserved32[7];
+};
/*
***************************************************************************
diff --git a/drivers/gpu/drm/amd/include/ivsrcid/vcn/irqsrcs_vcn_4_0.h b/drivers/gpu/drm/amd/include/ivsrcid/vcn/irqsrcs_vcn_4_0.h
index a81138c9e491..03cfa0517df2 100644
--- a/drivers/gpu/drm/amd/include/ivsrcid/vcn/irqsrcs_vcn_4_0.h
+++ b/drivers/gpu/drm/amd/include/ivsrcid/vcn/irqsrcs_vcn_4_0.h
@@ -38,4 +38,7 @@
#define VCN_4_0__SRCID__JPEG6_DECODE 174 // 0xae JRBC6 Decode interrupt
#define VCN_4_0__SRCID__JPEG7_DECODE 175 // 0xaf JRBC7 Decode interrupt
+#define VCN_4_0__SRCID_UVD_POISON 160
+#define VCN_4_0__SRCID_DJPEG0_POISON 161
+#define VCN_4_0__SRCID_EJPEG0_POISON 162
#endif
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index a40ead44778a..d18162e9ed1d 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -354,7 +354,8 @@ struct amd_pm_funcs {
int (*get_power_profile_mode)(void *handle, char *buf);
int (*set_power_profile_mode)(void *handle, long *input, uint32_t size);
int (*set_fine_grain_clk_vol)(void *handle, uint32_t type, long *input, uint32_t size);
- int (*odn_edit_dpm_table)(void *handle, uint32_t type, long *input, uint32_t size);
+ int (*odn_edit_dpm_table)(void *handle, enum PP_OD_DPM_TABLE_COMMAND type,
+ long *input, uint32_t size);
int (*set_mp1_state)(void *handle, enum pp_mp1_state mp1_state);
int (*smu_i2c_bus_access)(void *handle, bool acquire);
int (*gfx_state_change_set)(void *handle, uint32_t state);
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 7e85cdc5bd34..dc694cb246d9 100644
--- a/drivers/gpu/drm/amd/include/mes_v11_api_def.h
+++ b/drivers/gpu/drm/amd/include/mes_v11_api_def.h
@@ -222,7 +222,11 @@ union MESAPI_SET_HW_RESOURCES {
uint32_t apply_grbm_remote_register_dummy_read_wa : 1;
uint32_t second_gfx_pipe_enabled : 1;
uint32_t enable_level_process_quantum_check : 1;
- uint32_t reserved : 25;
+ uint32_t legacy_sch_mode : 1;
+ uint32_t disable_add_queue_wptr_mc_addr : 1;
+ uint32_t enable_mes_event_int_logging : 1;
+ uint32_t enable_reg_active_poll : 1;
+ uint32_t reserved : 21;
};
uint32_t uint32_t_all;
};
diff --git a/drivers/gpu/drm/amd/include/yellow_carp_offset.h b/drivers/gpu/drm/amd/include/yellow_carp_offset.h
index 28a56b56bcaf..0fea6a746611 100644
--- a/drivers/gpu/drm/amd/include/yellow_carp_offset.h
+++ b/drivers/gpu/drm/amd/include/yellow_carp_offset.h
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: MIT
#ifndef YELLOW_CARP_OFFSET_H
#define YELLOW_CARP_OFFSET_H
diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
index ec055858eb95..304190d5c9d2 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c
@@ -838,7 +838,8 @@ static int pp_set_fine_grain_clk_vol(void *handle, uint32_t type, long *input, u
return hwmgr->hwmgr_func->set_fine_grain_clk_vol(hwmgr, type, input, size);
}
-static int pp_odn_edit_dpm_table(void *handle, uint32_t type, long *input, uint32_t size)
+static int pp_odn_edit_dpm_table(void *handle, enum PP_OD_DPM_TABLE_COMMAND type,
+ long *input, uint32_t size)
{
struct pp_hwmgr *hwmgr = handle;
@@ -1507,7 +1508,7 @@ static void pp_pm_compute_clocks(void *handle)
struct pp_hwmgr *hwmgr = handle;
struct amdgpu_device *adev = hwmgr->adev;
- if (!amdgpu_device_has_dc_support(adev)) {
+ if (!adev->dc_enabled) {
amdgpu_dpm_get_active_displays(adev);
adev->pm.pm_display_cfg.num_display = adev->pm.dpm.new_active_crtc_count;
adev->pm.pm_display_cfg.vrefresh = amdgpu_dpm_get_vrefresh(adev);
diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c
index 67d7da0b6fed..1d829402cd2e 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/pp_psm.c
@@ -75,8 +75,10 @@ int psm_init_power_state_table(struct pp_hwmgr *hwmgr)
for (i = 0; i < table_entries; i++) {
result = hwmgr->hwmgr_func->get_pp_table_entry(hwmgr, i, state);
if (result) {
+ kfree(hwmgr->current_ps);
kfree(hwmgr->request_ps);
kfree(hwmgr->ps);
+ hwmgr->current_ps = NULL;
hwmgr->request_ps = NULL;
hwmgr->ps = NULL;
return -EINVAL;
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 97b3ad369046..b30684c84e20 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega20_hwmgr.c
@@ -2961,7 +2961,8 @@ static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr,
data->od8_settings.od8_settings_array;
OverDriveTable_t *od_table =
&(data->smc_state_table.overdrive_table);
- int32_t input_index, input_clk, input_vol, i;
+ int32_t input_clk, input_vol, i;
+ uint32_t input_index;
int od8_id;
int ret;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index b880f4d7d67e..ca3beb5d8f27 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -161,7 +161,7 @@ int smu_get_dpm_freq_range(struct smu_context *smu,
int smu_set_gfx_power_up_by_imu(struct smu_context *smu)
{
- if (!smu->ppt_funcs && !smu->ppt_funcs->set_gfx_power_up_by_imu)
+ if (!smu->ppt_funcs || !smu->ppt_funcs->set_gfx_power_up_by_imu)
return -EOPNOTSUPP;
return smu->ppt_funcs->set_gfx_power_up_by_imu(smu);
@@ -585,6 +585,7 @@ static int smu_set_funcs(struct amdgpu_device *adev)
yellow_carp_set_ppt_funcs(smu);
break;
case IP_VERSION(13, 0, 4):
+ case IP_VERSION(13, 0, 11):
smu_v13_0_4_set_ppt_funcs(smu);
break;
case IP_VERSION(13, 0, 5):
@@ -1448,6 +1449,7 @@ static int smu_disable_dpms(struct smu_context *smu)
switch (adev->ip_versions[MP1_HWIP][0]) {
case IP_VERSION(13, 0, 0):
case IP_VERSION(13, 0, 7):
+ case IP_VERSION(13, 0, 10):
return 0;
default:
break;
@@ -1516,7 +1518,7 @@ static int smu_disable_dpms(struct smu_context *smu)
}
if (adev->ip_versions[GC_HWIP][0] >= IP_VERSION(9, 4, 2) &&
- adev->gfx.rlc.funcs->stop)
+ !amdgpu_sriov_vf(adev) && adev->gfx.rlc.funcs->stop)
adev->gfx.rlc.funcs->stop(adev);
return ret;
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 f816b1dd110e..3bc4128a22ac 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
@@ -168,6 +168,7 @@ struct smu_temperature_range {
int mem_crit_max;
int mem_emergency_max;
int software_shutdown_temp;
+ int software_shutdown_temp_offset;
};
struct smu_state_validation_block {
@@ -568,6 +569,10 @@ struct smu_context
u32 param_reg;
u32 msg_reg;
u32 resp_reg;
+
+ u32 debug_param_reg;
+ u32 debug_msg_reg;
+ u32 debug_resp_reg;
};
struct i2c_adapter;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_0_ppsmc.h b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_0_ppsmc.h
index 9ebb8f39732a..8b8266890a10 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_0_ppsmc.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu_v13_0_0_ppsmc.h
@@ -131,7 +131,13 @@
#define PPSMC_MSG_EnableAudioStutterWA 0x44
#define PPSMC_MSG_PowerUpUmsch 0x45
#define PPSMC_MSG_PowerDownUmsch 0x46
-#define PPSMC_Message_Count 0x47
+#define PPSMC_MSG_SetDcsArch 0x47
+#define PPSMC_MSG_TriggerVFFLR 0x48
+#define PPSMC_MSG_SetNumBadMemoryPagesRetired 0x49
+#define PPSMC_MSG_SetBadMemoryPagesRetiredFlagsPerChannel 0x4A
+#define PPSMC_MSG_SetPriorityDeltaGain 0x4B
+#define PPSMC_MSG_AllowIHHostInterrupt 0x4C
+#define PPSMC_Message_Count 0x4D
//Debug Dump Message
#define DEBUGSMC_MSG_TestMessage 0x1
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
index 58098b82df66..a4e3425b1027 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_types.h
@@ -239,7 +239,9 @@
__SMU_DUMMY_MAP(DriverMode2Reset), \
__SMU_DUMMY_MAP(GetGfxOffStatus), \
__SMU_DUMMY_MAP(GetGfxOffEntryCount), \
- __SMU_DUMMY_MAP(LogGfxOffResidency),
+ __SMU_DUMMY_MAP(LogGfxOffResidency), \
+ __SMU_DUMMY_MAP(SetNumBadMemoryPagesRetired), \
+ __SMU_DUMMY_MAP(SetBadMemoryPagesRetiredFlagsPerChannel),
#undef __SMU_DUMMY_MAP
#define __SMU_DUMMY_MAP(type) SMU_MSG_##type
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 70b560737687..ad66d57aa102 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
@@ -79,6 +79,17 @@ MODULE_FIRMWARE("amdgpu/beige_goby_smc.bin");
#define mmTHM_BACO_CNTL_ARCT 0xA7
#define mmTHM_BACO_CNTL_ARCT_BASE_IDX 0
+static void smu_v11_0_poll_baco_exit(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+ uint32_t data, loop = 0;
+
+ do {
+ usleep_range(1000, 1100);
+ data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL);
+ } while ((data & 0x100) && (++loop < 100));
+}
+
int smu_v11_0_init_microcode(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
@@ -1588,6 +1599,10 @@ bool smu_v11_0_baco_is_support(struct smu_context *smu)
if (amdgpu_sriov_vf(smu->adev) || !smu_baco->platform_support)
return false;
+ /* return true if ASIC is in BACO state already */
+ if (smu_v11_0_baco_get_state(smu) == SMU_BACO_STATE_ENTER)
+ return true;
+
/* Arcturus does not support this bit mask */
if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_BACO_BIT) &&
!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT))
@@ -1685,7 +1700,18 @@ int smu_v11_0_baco_enter(struct smu_context *smu)
int smu_v11_0_baco_exit(struct smu_context *smu)
{
- return smu_v11_0_baco_set_state(smu, SMU_BACO_STATE_EXIT);
+ int ret;
+
+ ret = smu_v11_0_baco_set_state(smu, SMU_BACO_STATE_EXIT);
+ if (!ret) {
+ /*
+ * Poll BACO exit status to ensure FW has completed
+ * BACO exit process to avoid timing issues.
+ */
+ smu_v11_0_poll_baco_exit(smu);
+ }
+
+ return ret;
}
int smu_v11_0_mode1_reset(struct smu_context *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 89f0f6eb19f3..f5e90e0a99df 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
@@ -250,6 +250,7 @@ int smu_v13_0_check_fw_status(struct smu_context *smu)
switch (adev->ip_versions[MP1_HWIP][0]) {
case IP_VERSION(13, 0, 4):
+ case IP_VERSION(13, 0, 11):
mp1_fw_flags = RREG32_PCIE(MP1_Public |
(smnMP1_V13_0_4_FIRMWARE_FLAGS & 0xffffffff));
break;
@@ -301,6 +302,7 @@ int smu_v13_0_check_fw_version(struct smu_context *smu)
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):
@@ -841,6 +843,7 @@ int smu_v13_0_gfx_off_control(struct smu_context *smu, bool enable)
case IP_VERSION(13, 0, 7):
case IP_VERSION(13, 0, 8):
case IP_VERSION(13, 0, 10):
+ case IP_VERSION(13, 0, 11):
if (!(adev->pm.pp_feature & PP_GFXOFF_MASK))
return 0;
if (enable)
@@ -1376,6 +1379,7 @@ static int smu_v13_0_irq_process(struct amdgpu_device *adev,
*/
uint32_t ctxid = entry->src_data[0];
uint32_t data;
+ uint32_t high;
if (client_id == SOC15_IH_CLIENTID_THM) {
switch (src_id) {
@@ -1432,6 +1436,36 @@ static int smu_v13_0_irq_process(struct amdgpu_device *adev,
schedule_work(&smu->throttling_logging_work);
break;
+ case 0x8:
+ high = smu->thermal_range.software_shutdown_temp +
+ smu->thermal_range.software_shutdown_temp_offset;
+ high = min_t(typeof(high),
+ SMU_THERMAL_MAXIMUM_ALERT_TEMP,
+ high);
+ dev_emerg(adev->dev, "Reduce soft CTF limit to %d (by an offset %d)\n",
+ high,
+ smu->thermal_range.software_shutdown_temp_offset);
+
+ data = RREG32_SOC15(THM, 0, regTHM_THERMAL_INT_CTRL);
+ data = REG_SET_FIELD(data, THM_THERMAL_INT_CTRL,
+ DIG_THERM_INTH,
+ (high & 0xff));
+ data = data & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
+ WREG32_SOC15(THM, 0, regTHM_THERMAL_INT_CTRL, data);
+ break;
+ case 0x9:
+ high = min_t(typeof(high),
+ SMU_THERMAL_MAXIMUM_ALERT_TEMP,
+ smu->thermal_range.software_shutdown_temp);
+ dev_emerg(adev->dev, "Recover soft CTF limit to %d\n", high);
+
+ data = RREG32_SOC15(THM, 0, regTHM_THERMAL_INT_CTRL);
+ data = REG_SET_FIELD(data, THM_THERMAL_INT_CTRL,
+ DIG_THERM_INTH,
+ (high & 0xff));
+ data = data & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
+ WREG32_SOC15(THM, 0, regTHM_THERMAL_INT_CTRL, data);
+ break;
}
}
}
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 f0121d171630..87d7c66e49ef 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
@@ -70,6 +70,26 @@
#define MP0_MP1_DATA_REGION_SIZE_COMBOPPTABLE 0x4000
+#define mmMP1_SMN_C2PMSG_66 0x0282
+#define mmMP1_SMN_C2PMSG_66_BASE_IDX 0
+
+#define mmMP1_SMN_C2PMSG_82 0x0292
+#define mmMP1_SMN_C2PMSG_82_BASE_IDX 0
+
+#define mmMP1_SMN_C2PMSG_90 0x029a
+#define mmMP1_SMN_C2PMSG_90_BASE_IDX 0
+
+#define mmMP1_SMN_C2PMSG_75 0x028b
+#define mmMP1_SMN_C2PMSG_75_BASE_IDX 0
+
+#define mmMP1_SMN_C2PMSG_53 0x0275
+#define mmMP1_SMN_C2PMSG_53_BASE_IDX 0
+
+#define mmMP1_SMN_C2PMSG_54 0x0276
+#define mmMP1_SMN_C2PMSG_54_BASE_IDX 0
+
+#define DEBUGSMC_MSG_Mode1Reset 2
+
static struct cmn2asic_msg_mapping smu_v13_0_0_message_map[SMU_MSG_MAX_COUNT] = {
MSG_MAP(TestMessage, PPSMC_MSG_TestMessage, 1),
MSG_MAP(GetSmuVersion, PPSMC_MSG_GetSmuVersion, 1),
@@ -121,6 +141,9 @@ static struct cmn2asic_msg_mapping smu_v13_0_0_message_map[SMU_MSG_MAX_COUNT] =
MSG_MAP(PrepareMp1ForUnload, PPSMC_MSG_PrepareMp1ForUnload, 0),
MSG_MAP(DFCstateControl, PPSMC_MSG_SetExternalClientDfCstateAllow, 0),
MSG_MAP(ArmD3, PPSMC_MSG_ArmD3, 0),
+ MSG_MAP(SetNumBadMemoryPagesRetired, PPSMC_MSG_SetNumBadMemoryPagesRetired, 0),
+ MSG_MAP(SetBadMemoryPagesRetiredFlagsPerChannel,
+ PPSMC_MSG_SetBadMemoryPagesRetiredFlagsPerChannel, 0),
};
static struct cmn2asic_mapping smu_v13_0_0_clk_map[SMU_CLK_COUNT] = {
@@ -1789,6 +1812,69 @@ static int smu_v13_0_0_set_df_cstate(struct smu_context *smu,
NULL);
}
+static int smu_v13_0_0_mode1_reset(struct smu_context *smu)
+{
+ int ret;
+ struct amdgpu_device *adev = smu->adev;
+
+ if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 10))
+ ret = smu_cmn_send_debug_smc_msg(smu, DEBUGSMC_MSG_Mode1Reset);
+ else
+ ret = smu_cmn_send_smc_msg(smu, SMU_MSG_Mode1Reset, NULL);
+
+ if (!ret)
+ msleep(SMU13_MODE1_RESET_WAIT_TIME_IN_MS);
+
+ return ret;
+}
+
+static void smu_v13_0_0_set_smu_mailbox_registers(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+
+ smu->param_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_82);
+ smu->msg_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_66);
+ smu->resp_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90);
+
+ smu->debug_param_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_53);
+ smu->debug_msg_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_75);
+ smu->debug_resp_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_54);
+}
+
+static int smu_v13_0_0_smu_send_bad_mem_page_num(struct smu_context *smu,
+ uint32_t size)
+{
+ int ret = 0;
+
+ /* message SMU to update the bad page number on SMUBUS */
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_SetNumBadMemoryPagesRetired,
+ size, NULL);
+ if (ret)
+ dev_err(smu->adev->dev,
+ "[%s] failed to message SMU to update bad memory pages number\n",
+ __func__);
+
+ return ret;
+}
+
+static int smu_v13_0_0_send_bad_mem_channel_flag(struct smu_context *smu,
+ uint32_t size)
+{
+ int ret = 0;
+
+ /* message SMU to update the bad channel info on SMUBUS */
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_SetBadMemoryPagesRetiredFlagsPerChannel,
+ size, NULL);
+ if (ret)
+ dev_err(smu->adev->dev,
+ "[%s] failed to message SMU to update bad memory pages channel info\n",
+ __func__);
+
+ return ret;
+}
+
static const struct pptable_funcs smu_v13_0_0_ppt_funcs = {
.get_allowed_feature_mask = smu_v13_0_0_get_allowed_feature_mask,
.set_default_dpm_table = smu_v13_0_0_set_default_dpm_table,
@@ -1856,9 +1942,11 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = {
.baco_enter = smu_v13_0_0_baco_enter,
.baco_exit = smu_v13_0_0_baco_exit,
.mode1_reset_is_support = smu_v13_0_0_is_mode1_reset_supported,
- .mode1_reset = smu_v13_0_mode1_reset,
+ .mode1_reset = smu_v13_0_0_mode1_reset,
.set_mp1_state = smu_v13_0_0_set_mp1_state,
.set_df_cstate = smu_v13_0_0_set_df_cstate,
+ .send_hbm_bad_pages_num = smu_v13_0_0_smu_send_bad_mem_page_num,
+ .send_hbm_bad_channel_flag = smu_v13_0_0_send_bad_mem_channel_flag,
};
void smu_v13_0_0_set_ppt_funcs(struct smu_context *smu)
@@ -1870,5 +1958,5 @@ 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_v13_0_set_smu_mailbox_registers(smu);
+ 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 97e1d55dcaad..8fa9a36c38b6 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
@@ -1026,6 +1026,15 @@ static const struct pptable_funcs smu_v13_0_4_ppt_funcs = {
.set_gfx_power_up_by_imu = smu_v13_0_set_gfx_power_up_by_imu,
};
+static void smu_v13_0_4_set_smu_mailbox_registers(struct smu_context *smu)
+{
+ struct amdgpu_device *adev = smu->adev;
+
+ smu->param_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_82);
+ smu->msg_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_66);
+ smu->resp_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90);
+}
+
void smu_v13_0_4_set_ppt_funcs(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
@@ -1035,7 +1044,9 @@ void smu_v13_0_4_set_ppt_funcs(struct smu_context *smu)
smu->feature_map = smu_v13_0_4_feature_mask_map;
smu->table_map = smu_v13_0_4_table_map;
smu->is_apu = true;
- smu->param_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_82);
- smu->msg_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_66);
- smu->resp_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90);
+
+ if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 4))
+ smu_v13_0_4_set_smu_mailbox_registers(smu);
+ else
+ 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 d74debc584f8..c3c9ef523e59 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
@@ -1223,6 +1223,7 @@ static int smu_v13_0_7_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;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
index e4f8f90ac5aa..768b6e7dbd77 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
@@ -233,6 +233,18 @@ static void __smu_cmn_send_msg(struct smu_context *smu,
WREG32(smu->msg_reg, msg);
}
+static int __smu_cmn_send_debug_msg(struct smu_context *smu,
+ u32 msg,
+ u32 param)
+{
+ struct amdgpu_device *adev = smu->adev;
+
+ WREG32(smu->debug_param_reg, param);
+ WREG32(smu->debug_msg_reg, msg);
+ WREG32(smu->debug_resp_reg, 0);
+
+ return 0;
+}
/**
* smu_cmn_send_msg_without_waiting -- send the message; don't wait for status
* @smu: pointer to an SMU context
@@ -386,6 +398,12 @@ int smu_cmn_send_smc_msg(struct smu_context *smu,
read_arg);
}
+int smu_cmn_send_debug_smc_msg(struct smu_context *smu,
+ uint32_t msg)
+{
+ return __smu_cmn_send_debug_msg(smu, msg, 0);
+}
+
int smu_cmn_to_asic_specific_index(struct smu_context *smu,
enum smu_cmn2asic_mapping_type type,
uint32_t index)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
index 1526ce09c399..f82cf76dd3a4 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
@@ -42,6 +42,9 @@ int smu_cmn_send_smc_msg(struct smu_context *smu,
enum smu_message_type msg,
uint32_t *read_arg);
+int smu_cmn_send_debug_smc_msg(struct smu_context *smu,
+ uint32_t msg);
+
int smu_cmn_wait_for_response(struct smu_context *smu);
int smu_cmn_to_asic_specific_index(struct smu_context *smu,
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
index 9fce4239d4ad..3f4e719eebd8 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
@@ -9,7 +9,7 @@
#include <linux/platform_device.h>
#include <linux/component.h>
#include <linux/pm_runtime.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_module.h>
#include <drm/drm_of.h>
#include "komeda_dev.h"
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
index 451746ebbe71..62dc64550793 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c
@@ -10,7 +10,6 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_managed.h>
@@ -59,7 +58,6 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
static const struct drm_driver komeda_kms_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
- .lastclose = drm_fb_helper_lastclose,
DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(komeda_gem_dma_dumb_create),
.fops = &komeda_cma_fops,
.name = "komeda",
diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c
index 7030339fa232..3cfefadc7c9d 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -19,7 +19,6 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_fb_dma_helper.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_of.h>
@@ -275,7 +274,7 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane,
dest_h = drm_rect_height(&new_plane_state->dst);
scanout_start = drm_fb_dma_get_gem_addr(fb, new_plane_state, 0);
- hdlcd = plane->dev->dev_private;
+ hdlcd = drm_to_hdlcd_priv(plane->dev);
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, fb->pitches[0]);
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_PITCH, fb->pitches[0]);
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_COUNT, dest_h - 1);
@@ -290,7 +289,6 @@ static const struct drm_plane_helper_funcs hdlcd_plane_helper_funcs = {
static const struct drm_plane_funcs hdlcd_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
- .destroy = drm_plane_cleanup,
.reset = drm_atomic_helper_plane_reset,
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
@@ -298,24 +296,19 @@ static const struct drm_plane_funcs hdlcd_plane_funcs = {
static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)
{
- struct hdlcd_drm_private *hdlcd = drm->dev_private;
+ struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
struct drm_plane *plane = NULL;
u32 formats[ARRAY_SIZE(supported_formats)], i;
- int ret;
-
- plane = devm_kzalloc(drm->dev, sizeof(*plane), GFP_KERNEL);
- if (!plane)
- return ERR_PTR(-ENOMEM);
for (i = 0; i < ARRAY_SIZE(supported_formats); i++)
formats[i] = supported_formats[i].fourcc;
- ret = drm_universal_plane_init(drm, plane, 0xff, &hdlcd_plane_funcs,
- formats, ARRAY_SIZE(formats),
- NULL,
- DRM_PLANE_TYPE_PRIMARY, NULL);
- if (ret)
- return ERR_PTR(ret);
+ plane = drmm_universal_plane_alloc(drm, struct drm_plane, dev, 0xff,
+ &hdlcd_plane_funcs,
+ formats, ARRAY_SIZE(formats),
+ NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
+ if (IS_ERR(plane))
+ return plane;
drm_plane_helper_add(plane, &hdlcd_plane_helper_funcs);
hdlcd->plane = plane;
@@ -325,7 +318,7 @@ static struct drm_plane *hdlcd_plane_init(struct drm_device *drm)
int hdlcd_setup_crtc(struct drm_device *drm)
{
- struct hdlcd_drm_private *hdlcd = drm->dev_private;
+ struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
struct drm_plane *primary;
int ret;
diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index a032003c340c..7043d1c9ed8f 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -26,7 +26,7 @@
#include <drm/drm_crtc.h>
#include <drm/drm_debugfs.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_modeset_helper.h>
@@ -98,7 +98,7 @@ static void hdlcd_irq_uninstall(struct hdlcd_drm_private *hdlcd)
static int hdlcd_load(struct drm_device *drm, unsigned long flags)
{
- struct hdlcd_drm_private *hdlcd = drm->dev_private;
+ struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
struct platform_device *pdev = to_platform_device(drm->dev);
struct resource *res;
u32 version;
@@ -175,14 +175,21 @@ static const struct drm_mode_config_funcs hdlcd_mode_config_funcs = {
.atomic_commit = drm_atomic_helper_commit,
};
-static void hdlcd_setup_mode_config(struct drm_device *drm)
+static int hdlcd_setup_mode_config(struct drm_device *drm)
{
- drm_mode_config_init(drm);
+ int ret;
+
+ ret = drmm_mode_config_init(drm);
+ if (ret)
+ return ret;
+
drm->mode_config.min_width = 0;
drm->mode_config.min_height = 0;
drm->mode_config.max_width = HDLCD_MAX_XRES;
drm->mode_config.max_height = HDLCD_MAX_YRES;
drm->mode_config.funcs = &hdlcd_mode_config_funcs;
+
+ return 0;
}
#ifdef CONFIG_DEBUG_FS
@@ -190,7 +197,7 @@ static int hdlcd_show_underrun_count(struct seq_file *m, void *arg)
{
struct drm_info_node *node = (struct drm_info_node *)m->private;
struct drm_device *drm = node->minor->dev;
- struct hdlcd_drm_private *hdlcd = drm->dev_private;
+ struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
seq_printf(m, "underrun : %d\n", atomic_read(&hdlcd->buffer_underrun_count));
seq_printf(m, "dma_end : %d\n", atomic_read(&hdlcd->dma_end_count));
@@ -203,7 +210,7 @@ static int hdlcd_show_pxlclock(struct seq_file *m, void *arg)
{
struct drm_info_node *node = (struct drm_info_node *)m->private;
struct drm_device *drm = node->minor->dev;
- struct hdlcd_drm_private *hdlcd = drm->dev_private;
+ struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
unsigned long clkrate = clk_get_rate(hdlcd->clk);
unsigned long mode_clock = hdlcd->crtc.mode.crtc_clock * 1000;
@@ -247,18 +254,18 @@ static int hdlcd_drm_bind(struct device *dev)
struct hdlcd_drm_private *hdlcd;
int ret;
- hdlcd = devm_kzalloc(dev, sizeof(*hdlcd), GFP_KERNEL);
- if (!hdlcd)
- return -ENOMEM;
+ hdlcd = devm_drm_dev_alloc(dev, &hdlcd_driver, typeof(*hdlcd), base);
+ if (IS_ERR(hdlcd))
+ return PTR_ERR(hdlcd);
- drm = drm_dev_alloc(&hdlcd_driver, dev);
- if (IS_ERR(drm))
- return PTR_ERR(drm);
+ drm = &hdlcd->base;
- drm->dev_private = hdlcd;
dev_set_drvdata(dev, drm);
- hdlcd_setup_mode_config(drm);
+ ret = hdlcd_setup_mode_config(drm);
+ if (ret)
+ goto err_free;
+
ret = hdlcd_load(drm, 0);
if (ret)
goto err_free;
@@ -317,17 +324,14 @@ err_unload:
hdlcd_irq_uninstall(hdlcd);
of_reserved_mem_device_release(drm->dev);
err_free:
- drm_mode_config_cleanup(drm);
dev_set_drvdata(dev, NULL);
- drm_dev_put(drm);
-
return ret;
}
static void hdlcd_drm_unbind(struct device *dev)
{
struct drm_device *drm = dev_get_drvdata(dev);
- struct hdlcd_drm_private *hdlcd = drm->dev_private;
+ struct hdlcd_drm_private *hdlcd = drm_to_hdlcd_priv(drm);
drm_dev_unregister(drm);
drm_kms_helper_poll_fini(drm);
@@ -341,10 +345,7 @@ static void hdlcd_drm_unbind(struct device *dev)
if (pm_runtime_enabled(dev))
pm_runtime_disable(dev);
of_reserved_mem_device_release(dev);
- drm_mode_config_cleanup(drm);
- drm->dev_private = NULL;
dev_set_drvdata(dev, NULL);
- drm_dev_put(drm);
}
static const struct component_master_ops hdlcd_master_ops = {
diff --git a/drivers/gpu/drm/arm/hdlcd_drv.h b/drivers/gpu/drm/arm/hdlcd_drv.h
index 909c39c28487..f1c1da2ac2db 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.h
+++ b/drivers/gpu/drm/arm/hdlcd_drv.h
@@ -7,6 +7,7 @@
#define __HDLCD_DRV_H__
struct hdlcd_drm_private {
+ struct drm_device base;
void __iomem *mmio;
struct clk *clk;
struct drm_crtc crtc;
@@ -20,6 +21,7 @@ struct hdlcd_drm_private {
#endif
};
+#define drm_to_hdlcd_priv(x) container_of(x, struct hdlcd_drm_private, base)
#define crtc_to_hdlcd_priv(x) container_of(x, struct hdlcd_drm_private, crtc)
static inline void hdlcd_write(struct hdlcd_drm_private *hdlcd,
diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c
index 962730772b2f..dc01c43f6193 100644
--- a/drivers/gpu/drm/arm/malidp_crtc.c
+++ b/drivers/gpu/drm/arm/malidp_crtc.c
@@ -514,7 +514,6 @@ static void malidp_crtc_disable_vblank(struct drm_crtc *crtc)
}
static const struct drm_crtc_funcs malidp_crtc_funcs = {
- .destroy = drm_crtc_cleanup,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
.reset = malidp_crtc_reset,
@@ -526,7 +525,7 @@ static const struct drm_crtc_funcs malidp_crtc_funcs = {
int malidp_crtc_init(struct drm_device *drm)
{
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
struct drm_plane *primary = NULL, *plane;
int ret;
@@ -548,8 +547,8 @@ int malidp_crtc_init(struct drm_device *drm)
return -EINVAL;
}
- ret = drm_crtc_init_with_planes(drm, &malidp->crtc, primary, NULL,
- &malidp_crtc_funcs, NULL);
+ ret = drmm_crtc_init_with_planes(drm, &malidp->crtc, primary, NULL,
+ &malidp_crtc_funcs, NULL);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index 1d0b0c54ccc7..589c1c66a6dc 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -19,10 +19,11 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_managed.h>
#include <drm/drm_modeset_helper.h>
#include <drm/drm_module.h>
#include <drm/drm_of.h>
@@ -168,7 +169,7 @@ static void malidp_atomic_commit_se_config(struct drm_crtc *crtc,
*/
static int malidp_set_and_wait_config_valid(struct drm_device *drm)
{
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
struct malidp_hw_device *hwdev = malidp->dev;
int ret;
@@ -189,7 +190,7 @@ static int malidp_set_and_wait_config_valid(struct drm_device *drm)
static void malidp_atomic_commit_hw_done(struct drm_atomic_state *state)
{
struct drm_device *drm = state->dev;
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
int loop = 5;
malidp->event = malidp->crtc.state->event;
@@ -230,7 +231,7 @@ static void malidp_atomic_commit_hw_done(struct drm_atomic_state *state)
static void malidp_atomic_commit_tail(struct drm_atomic_state *state)
{
struct drm_device *drm = state->dev;
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
struct drm_crtc *crtc;
struct drm_crtc_state *old_crtc_state;
int i;
@@ -392,10 +393,12 @@ static const struct drm_mode_config_funcs malidp_mode_config_funcs = {
static int malidp_init(struct drm_device *drm)
{
int ret;
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
struct malidp_hw_device *hwdev = malidp->dev;
- drm_mode_config_init(drm);
+ ret = drmm_mode_config_init(drm);
+ if (ret)
+ goto out;
drm->mode_config.min_width = hwdev->min_line_size;
drm->mode_config.min_height = hwdev->min_line_size;
@@ -406,29 +409,21 @@ static int malidp_init(struct drm_device *drm)
ret = malidp_crtc_init(drm);
if (ret)
- goto crtc_fail;
+ goto out;
ret = malidp_mw_connector_init(drm);
if (ret)
- goto crtc_fail;
-
- return 0;
+ goto out;
-crtc_fail:
- drm_mode_config_cleanup(drm);
+out:
return ret;
}
-static void malidp_fini(struct drm_device *drm)
-{
- drm_mode_config_cleanup(drm);
-}
-
static int malidp_irq_init(struct platform_device *pdev)
{
int irq_de, irq_se, ret = 0;
struct drm_device *drm = dev_get_drvdata(&pdev->dev);
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
struct malidp_hw_device *hwdev = malidp->dev;
/* fetch the interrupts from DT */
@@ -462,7 +457,7 @@ static int malidp_dumb_create(struct drm_file *file_priv,
struct drm_device *drm,
struct drm_mode_create_dumb *args)
{
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
/* allocate for the worst case scenario, i.e. rotated buffers */
u8 alignment = malidp_hw_get_pitch_align(malidp->dev, 1);
@@ -508,7 +503,7 @@ static void malidp_error_stats_dump(const char *prefix,
static int malidp_show_stats(struct seq_file *m, void *arg)
{
struct drm_device *drm = m->private;
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
unsigned long irqflags;
struct malidp_error_stats de_errors, se_errors;
@@ -531,7 +526,7 @@ static ssize_t malidp_debugfs_write(struct file *file, const char __user *ubuf,
{
struct seq_file *m = file->private_data;
struct drm_device *drm = m->private;
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
unsigned long irqflags;
spin_lock_irqsave(&malidp->errors_lock, irqflags);
@@ -552,7 +547,7 @@ static const struct file_operations malidp_debugfs_fops = {
static void malidp_debugfs_init(struct drm_minor *minor)
{
- struct malidp_drm *malidp = minor->dev->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(minor->dev);
malidp_error_stats_init(&malidp->de_errors);
malidp_error_stats_init(&malidp->se_errors);
@@ -652,7 +647,7 @@ static ssize_t core_id_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct drm_device *drm = dev_get_drvdata(dev);
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
return snprintf(buf, PAGE_SIZE, "%08x\n", malidp->core_id);
}
@@ -670,7 +665,7 @@ ATTRIBUTE_GROUPS(mali_dp);
static int malidp_runtime_pm_suspend(struct device *dev)
{
struct drm_device *drm = dev_get_drvdata(dev);
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
struct malidp_hw_device *hwdev = malidp->dev;
/* we can only suspend if the hardware is in config mode */
@@ -689,7 +684,7 @@ static int malidp_runtime_pm_suspend(struct device *dev)
static int malidp_runtime_pm_resume(struct device *dev)
{
struct drm_device *drm = dev_get_drvdata(dev);
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
struct malidp_hw_device *hwdev = malidp->dev;
clk_prepare_enable(hwdev->pclk);
@@ -716,11 +711,13 @@ static int malidp_bind(struct device *dev)
int ret = 0, i;
u32 version, out_depth = 0;
- malidp = devm_kzalloc(dev, sizeof(*malidp), GFP_KERNEL);
- if (!malidp)
- return -ENOMEM;
+ malidp = devm_drm_dev_alloc(dev, &malidp_driver, typeof(*malidp), base);
+ if (IS_ERR(malidp))
+ return PTR_ERR(malidp);
+
+ drm = &malidp->base;
- hwdev = devm_kzalloc(dev, sizeof(*hwdev), GFP_KERNEL);
+ hwdev = drmm_kzalloc(drm, sizeof(*hwdev), GFP_KERNEL);
if (!hwdev)
return -ENOMEM;
@@ -753,13 +750,6 @@ static int malidp_bind(struct device *dev)
if (ret && ret != -ENODEV)
return ret;
- drm = drm_dev_alloc(&malidp_driver, dev);
- if (IS_ERR(drm)) {
- ret = PTR_ERR(drm);
- goto alloc_fail;
- }
-
- drm->dev_private = malidp;
dev_set_drvdata(dev, drm);
/* Enable power management */
@@ -878,17 +868,13 @@ irq_init_fail:
bind_fail:
of_node_put(malidp->crtc.port);
malidp->crtc.port = NULL;
- malidp_fini(drm);
query_hw_fail:
pm_runtime_put(dev);
if (pm_runtime_enabled(dev))
pm_runtime_disable(dev);
else
malidp_runtime_pm_suspend(dev);
- drm->dev_private = NULL;
dev_set_drvdata(dev, NULL);
- drm_dev_put(drm);
-alloc_fail:
of_reserved_mem_device_release(dev);
return ret;
@@ -897,7 +883,7 @@ alloc_fail:
static void malidp_unbind(struct device *dev)
{
struct drm_device *drm = dev_get_drvdata(dev);
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
struct malidp_hw_device *hwdev = malidp->dev;
drm_dev_unregister(drm);
@@ -909,15 +895,12 @@ static void malidp_unbind(struct device *dev)
component_unbind_all(dev, drm);
of_node_put(malidp->crtc.port);
malidp->crtc.port = NULL;
- malidp_fini(drm);
pm_runtime_put(dev);
if (pm_runtime_enabled(dev))
pm_runtime_disable(dev);
else
malidp_runtime_pm_suspend(dev);
- drm->dev_private = NULL;
dev_set_drvdata(dev, NULL);
- drm_dev_put(drm);
of_reserved_mem_device_release(dev);
}
diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h
index cdfddfabf2d1..bc0387876dea 100644
--- a/drivers/gpu/drm/arm/malidp_drv.h
+++ b/drivers/gpu/drm/arm/malidp_drv.h
@@ -29,6 +29,7 @@ struct malidp_error_stats {
};
struct malidp_drm {
+ struct drm_device base;
struct malidp_hw_device *dev;
struct drm_crtc crtc;
struct drm_writeback_connector mw_connector;
@@ -44,6 +45,7 @@ struct malidp_drm {
#endif
};
+#define drm_to_malidp(x) container_of(x, struct malidp_drm, base)
#define crtc_to_malidp_device(x) container_of(x, struct malidp_drm, crtc)
struct malidp_plane {
diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c
index e9de542f9b7c..9b845d3f34e1 100644
--- a/drivers/gpu/drm/arm/malidp_hw.c
+++ b/drivers/gpu/drm/arm/malidp_hw.c
@@ -1168,7 +1168,7 @@ static void malidp_hw_clear_irq(struct malidp_hw_device *hwdev, u8 block, u32 ir
static irqreturn_t malidp_de_irq(int irq, void *arg)
{
struct drm_device *drm = arg;
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
struct malidp_hw_device *hwdev;
struct malidp_hw *hw;
const struct malidp_irq_map *de;
@@ -1226,7 +1226,7 @@ static irqreturn_t malidp_de_irq(int irq, void *arg)
static irqreturn_t malidp_de_irq_thread_handler(int irq, void *arg)
{
struct drm_device *drm = arg;
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
wake_up(&malidp->wq);
@@ -1252,7 +1252,7 @@ void malidp_de_irq_hw_init(struct malidp_hw_device *hwdev)
int malidp_de_irq_init(struct drm_device *drm, int irq)
{
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
struct malidp_hw_device *hwdev = malidp->dev;
int ret;
@@ -1286,7 +1286,7 @@ void malidp_de_irq_fini(struct malidp_hw_device *hwdev)
static irqreturn_t malidp_se_irq(int irq, void *arg)
{
struct drm_device *drm = arg;
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
struct malidp_hw_device *hwdev = malidp->dev;
struct malidp_hw *hw = hwdev->hw;
const struct malidp_irq_map *se = &hw->map.se_irq_map;
@@ -1363,7 +1363,7 @@ static irqreturn_t malidp_se_irq_thread_handler(int irq, void *arg)
int malidp_se_irq_init(struct drm_device *drm, int irq)
{
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
struct malidp_hw_device *hwdev = malidp->dev;
int ret;
diff --git a/drivers/gpu/drm/arm/malidp_mw.c b/drivers/gpu/drm/arm/malidp_mw.c
index ef76d0e6ee2f..626709bec6f5 100644
--- a/drivers/gpu/drm/arm/malidp_mw.c
+++ b/drivers/gpu/drm/arm/malidp_mw.c
@@ -129,7 +129,7 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder,
struct drm_connector_state *conn_state)
{
struct malidp_mw_connector_state *mw_state = to_mw_state(conn_state);
- struct malidp_drm *malidp = encoder->dev->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(encoder->dev);
struct drm_framebuffer *fb;
int i, n_planes;
@@ -207,7 +207,7 @@ static u32 *get_writeback_formats(struct malidp_drm *malidp, int *n_formats)
int malidp_mw_connector_init(struct drm_device *drm)
{
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
u32 *formats;
int ret, n_formats;
@@ -236,7 +236,7 @@ int malidp_mw_connector_init(struct drm_device *drm)
void malidp_mw_atomic_commit(struct drm_device *drm,
struct drm_atomic_state *old_state)
{
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
struct drm_writeback_connector *mw_conn = &malidp->mw_connector;
struct drm_connector_state *conn_state = mw_conn->base.state;
struct malidp_hw_device *hwdev = malidp->dev;
diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c
index 45f5e35e7f24..34547edf1ee3 100644
--- a/drivers/gpu/drm/arm/malidp_planes.c
+++ b/drivers/gpu/drm/arm/malidp_planes.c
@@ -68,14 +68,6 @@
/* readahead for partial-frame prefetch */
#define MALIDP_MMU_PREFETCH_READAHEAD 8
-static void malidp_de_plane_destroy(struct drm_plane *plane)
-{
- struct malidp_plane *mp = to_malidp_plane(plane);
-
- drm_plane_cleanup(plane);
- kfree(mp);
-}
-
/*
* Replicate what the default ->reset hook does: free the state pointer and
* allocate a new empty object. We just need enough space to store
@@ -151,7 +143,7 @@ bool malidp_format_mod_supported(struct drm_device *drm,
{
const struct drm_format_info *info;
const u64 *modifiers;
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
const struct malidp_hw_regmap *map = &malidp->dev->hw->map;
if (WARN_ON(modifier == DRM_FORMAT_MOD_INVALID))
@@ -260,7 +252,6 @@ static bool malidp_format_mod_supported_per_plane(struct drm_plane *plane,
static const struct drm_plane_funcs malidp_de_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
- .destroy = malidp_de_plane_destroy,
.reset = malidp_plane_reset,
.atomic_duplicate_state = malidp_duplicate_plane_state,
.atomic_destroy_state = malidp_destroy_plane_state,
@@ -931,7 +922,7 @@ static const uint64_t linear_only_modifiers[] = {
int malidp_de_planes_init(struct drm_device *drm)
{
- struct malidp_drm *malidp = drm->dev_private;
+ struct malidp_drm *malidp = drm_to_malidp(drm);
const struct malidp_hw_regmap *map = &malidp->dev->hw->map;
struct malidp_plane *plane = NULL;
enum drm_plane_type plane_type;
@@ -972,12 +963,6 @@ int malidp_de_planes_init(struct drm_device *drm)
for (i = 0; i < map->n_layers; i++) {
u8 id = map->layers[i].id;
- plane = kzalloc(sizeof(*plane), GFP_KERNEL);
- if (!plane) {
- ret = -ENOMEM;
- goto cleanup;
- }
-
/* build the list of DRM supported formats based on the map */
for (n = 0, j = 0; j < map->n_pixel_formats; j++) {
if ((map->pixel_formats[j].layer & id) == id)
@@ -990,13 +975,14 @@ int malidp_de_planes_init(struct drm_device *drm)
/*
* All the layers except smart layer supports AFBC modifiers.
*/
- ret = drm_universal_plane_init(drm, &plane->base, crtcs,
- &malidp_de_plane_funcs, formats, n,
- (id == DE_SMART) ? linear_only_modifiers : modifiers,
- plane_type, NULL);
-
- if (ret < 0)
+ plane = drmm_universal_plane_alloc(drm, struct malidp_plane, base,
+ crtcs, &malidp_de_plane_funcs, formats, n,
+ (id == DE_SMART) ? linear_only_modifiers :
+ modifiers, plane_type, NULL);
+ if (IS_ERR(plane)) {
+ ret = PTR_ERR(plane);
goto cleanup;
+ }
drm_plane_helper_add(&plane->base,
&malidp_de_plane_helper_funcs);
diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c
index 38f5170c0fea..584cee123bd8 100644
--- a/drivers/gpu/drm/armada/armada_fbdev.c
+++ b/drivers/gpu/drm/armada/armada_fbdev.c
@@ -19,6 +19,8 @@
static const struct fb_ops armada_fb_ops = {
.owner = THIS_MODULE,
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,
@@ -72,7 +74,7 @@ static int armada_fbdev_create(struct drm_fb_helper *fbh,
if (IS_ERR(dfb))
return PTR_ERR(dfb);
- info = drm_fb_helper_alloc_fbi(fbh);
+ info = drm_fb_helper_alloc_info(fbh);
if (IS_ERR(info)) {
ret = PTR_ERR(info);
goto err_fballoc;
@@ -155,7 +157,7 @@ void armada_fbdev_fini(struct drm_device *dev)
struct drm_fb_helper *fbh = priv->fbdev;
if (fbh) {
- drm_fb_helper_unregister_fbi(fbh);
+ drm_fb_helper_unregister_info(fbh);
drm_fb_helper_fini(fbh);
diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
index 5430265ad458..26d10065d534 100644
--- a/drivers/gpu/drm/armada/armada_gem.c
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -66,8 +66,8 @@ void armada_gem_free_object(struct drm_gem_object *obj)
if (dobj->obj.import_attach) {
/* We only ever display imported data */
if (dobj->sgt)
- dma_buf_unmap_attachment(dobj->obj.import_attach,
- dobj->sgt, DMA_TO_DEVICE);
+ dma_buf_unmap_attachment_unlocked(dobj->obj.import_attach,
+ dobj->sgt, DMA_TO_DEVICE);
drm_prime_gem_destroy(&dobj->obj, NULL);
}
@@ -539,8 +539,8 @@ int armada_gem_map_import(struct armada_gem_object *dobj)
{
int ret;
- dobj->sgt = dma_buf_map_attachment(dobj->obj.import_attach,
- DMA_TO_DEVICE);
+ dobj->sgt = dma_buf_map_attachment_unlocked(dobj->obj.import_attach,
+ DMA_TO_DEVICE);
if (IS_ERR(dobj->sgt)) {
ret = PTR_ERR(dobj->sgt);
dobj->sgt = NULL;
diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c
index a94f1a9e8f40..718119e168a6 100644
--- a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c
+++ b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c
@@ -16,7 +16,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_device.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_module.h>
diff --git a/drivers/gpu/drm/ast/Kconfig b/drivers/gpu/drm/ast/Kconfig
index fbcf2f45cef5..d367a90cd3de 100644
--- a/drivers/gpu/drm/ast/Kconfig
+++ b/drivers/gpu/drm/ast/Kconfig
@@ -2,10 +2,8 @@
config DRM_AST
tristate "AST server chips"
depends on DRM && PCI && MMU
+ select DRM_GEM_SHMEM_HELPER
select DRM_KMS_HELPER
- select DRM_VRAM_HELPER
- select DRM_TTM
- select DRM_TTM_HELPER
help
Say yes for experimental AST GPU driver. Do not enable
this driver without having a working -modesetting,
diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c
index b9392f31e629..420fc75c240e 100644
--- a/drivers/gpu/drm/ast/ast_drv.c
+++ b/drivers/gpu/drm/ast/ast_drv.c
@@ -33,7 +33,8 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_gem_vram_helper.h>
+#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_module.h>
#include <drm/drm_probe_helper.h>
@@ -63,7 +64,7 @@ static const struct drm_driver ast_driver = {
.minor = DRIVER_MINOR,
.patchlevel = DRIVER_PATCHLEVEL,
- DRM_GEM_VRAM_DRIVER
+ DRM_GEM_SHMEM_DRIVER_OPS
};
/*
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 2e44b971c3a6..d51b81fea9c8 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -38,7 +38,6 @@
#include <drm/drm_encoder.h>
#include <drm/drm_mode.h>
#include <drm/drm_framebuffer.h>
-#include <drm/drm_fb_helper.h>
#define DRIVER_AUTHOR "Dave Airlie"
@@ -87,7 +86,7 @@ enum ast_tx_chip {
#define AST_DRAM_8Gx16 8
/*
- * Cursor plane
+ * Hardware cursor
*/
#define AST_MAX_HWC_WIDTH 64
@@ -96,8 +95,6 @@ enum ast_tx_chip {
#define AST_HWC_SIZE (AST_MAX_HWC_WIDTH * AST_MAX_HWC_HEIGHT * 2)
#define AST_HWC_SIGNATURE_SIZE 32
-#define AST_DEFAULT_HWC_NUM 2
-
/* define for signature structure */
#define AST_HWC_SIGNATURE_CHECKSUM 0x00
#define AST_HWC_SIGNATURE_SizeX 0x04
@@ -107,22 +104,21 @@ enum ast_tx_chip {
#define AST_HWC_SIGNATURE_HOTSPOTX 0x14
#define AST_HWC_SIGNATURE_HOTSPOTY 0x18
-struct ast_cursor_plane {
- struct drm_plane base;
+/*
+ * Planes
+ */
- struct {
- struct drm_gem_vram_object *gbo;
- struct iosys_map map;
- u64 off;
- } hwc[AST_DEFAULT_HWC_NUM];
+struct ast_plane {
+ struct drm_plane base;
- unsigned int next_hwc_index;
+ void __iomem *vaddr;
+ u64 offset;
+ unsigned long size;
};
-static inline struct ast_cursor_plane *
-to_ast_cursor_plane(struct drm_plane *plane)
+static inline struct ast_plane *to_ast_plane(struct drm_plane *plane)
{
- return container_of(plane, struct ast_cursor_plane, base);
+ return container_of(plane, struct ast_plane, base);
}
/*
@@ -175,8 +171,13 @@ struct ast_private {
uint32_t dram_type;
uint32_t mclk;
- struct drm_plane primary_plane;
- struct ast_cursor_plane cursor_plane;
+ void __iomem *vram;
+ unsigned long vram_base;
+ unsigned long vram_size;
+ unsigned long vram_fb_available;
+
+ struct ast_plane primary_plane;
+ struct ast_plane cursor_plane;
struct drm_crtc crtc;
struct {
struct {
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 067453266897..bffa310a0431 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -32,7 +32,6 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_gem.h>
-#include <drm/drm_gem_vram_helper.h>
#include <drm/drm_managed.h>
#include "ast_drv.h"
@@ -461,8 +460,8 @@ struct ast_private *ast_device_create(const struct drm_driver *drv,
/* map reserved buffer */
ast->dp501_fw_buf = NULL;
- if (dev->vram_mm->vram_size < pci_resource_len(pdev, 0)) {
- ast->dp501_fw_buf = pci_iomap_range(pdev, 0, dev->vram_mm->vram_size, 0);
+ if (ast->vram_size < pci_resource_len(pdev, 0)) {
+ ast->dp501_fw_buf = pci_iomap_range(pdev, 0, ast->vram_size, 0);
if (!ast->dp501_fw_buf)
drm_info(dev, "failed to map reserved buffer!\n");
}
diff --git a/drivers/gpu/drm/ast/ast_mm.c b/drivers/gpu/drm/ast/ast_mm.c
index 6e999408dda9..248284a4b3ff 100644
--- a/drivers/gpu/drm/ast/ast_mm.c
+++ b/drivers/gpu/drm/ast/ast_mm.c
@@ -28,7 +28,6 @@
#include <linux/pci.h>
-#include <drm/drm_gem_vram_helper.h>
#include <drm/drm_managed.h>
#include <drm/drm_print.h>
@@ -80,7 +79,6 @@ int ast_mm_init(struct ast_private *ast)
struct pci_dev *pdev = to_pci_dev(dev->dev);
resource_size_t base, size;
u32 vram_size;
- int ret;
base = pci_resource_start(pdev, 0);
size = pci_resource_len(pdev, 0);
@@ -91,11 +89,13 @@ int ast_mm_init(struct ast_private *ast)
vram_size = ast_get_vram_size(ast);
- ret = drmm_vram_helper_init(dev, base, vram_size);
- if (ret) {
- drm_err(dev, "Error initializing VRAM MM; %d\n", ret);
- return ret;
- }
+ ast->vram = devm_ioremap_wc(dev->dev, base, vram_size);
+ if (!ast->vram)
+ return -ENOMEM;
+
+ ast->vram_base = base;
+ ast->vram_size = vram_size;
+ ast->vram_fb_available = vram_size;
return 0;
}
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 1bc0220e6783..c7443317c747 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -36,11 +36,13 @@
#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_damage_helper.h>
#include <drm/drm_edid.h>
+#include <drm/drm_format_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_gem_vram_helper.h>
+#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_managed.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
@@ -48,6 +50,8 @@
#include "ast_drv.h"
#include "ast_tables.h"
+#define AST_LUT_SIZE 256
+
static inline void ast_load_palette_index(struct ast_private *ast,
u8 index, u8 red, u8 green,
u8 blue)
@@ -62,20 +66,46 @@ static inline void ast_load_palette_index(struct ast_private *ast,
ast_io_read8(ast, AST_IO_SEQ_PORT);
}
-static void ast_crtc_load_lut(struct ast_private *ast, struct drm_crtc *crtc)
+static void ast_crtc_set_gamma_linear(struct ast_private *ast,
+ const struct drm_format_info *format)
{
- u16 *r, *g, *b;
int i;
- if (!crtc->enabled)
- return;
+ switch (format->format) {
+ case DRM_FORMAT_C8: /* In this case, gamma table is used as color palette */
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_XRGB8888:
+ for (i = 0; i < AST_LUT_SIZE; i++)
+ ast_load_palette_index(ast, i, i, i, i);
+ break;
+ default:
+ drm_warn_once(&ast->base, "Unsupported format %p4cc for gamma correction\n",
+ &format->format);
+ break;
+ }
+}
- r = crtc->gamma_store;
- g = r + crtc->gamma_size;
- b = g + crtc->gamma_size;
+static void ast_crtc_set_gamma(struct ast_private *ast,
+ const struct drm_format_info *format,
+ struct drm_color_lut *lut)
+{
+ int i;
- for (i = 0; i < 256; i++)
- ast_load_palette_index(ast, i, *r++ >> 8, *g++ >> 8, *b++ >> 8);
+ switch (format->format) {
+ case DRM_FORMAT_C8: /* In this case, gamma table is used as color palette */
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_XRGB8888:
+ for (i = 0; i < AST_LUT_SIZE; i++)
+ ast_load_palette_index(ast, i,
+ lut[i].red >> 8,
+ lut[i].green >> 8,
+ lut[i].blue >> 8);
+ break;
+ default:
+ drm_warn_once(&ast->base, "Unsupported format %p4cc for gamma correction\n",
+ &format->format);
+ break;
+ }
}
static bool ast_get_vbios_mode_info(const struct drm_format_info *format,
@@ -538,6 +568,29 @@ static void ast_wait_for_vretrace(struct ast_private *ast)
}
/*
+ * Planes
+ */
+
+static int ast_plane_init(struct drm_device *dev, struct ast_plane *ast_plane,
+ void __iomem *vaddr, u64 offset, unsigned long size,
+ uint32_t possible_crtcs,
+ const struct drm_plane_funcs *funcs,
+ const uint32_t *formats, unsigned int format_count,
+ const uint64_t *format_modifiers,
+ enum drm_plane_type type)
+{
+ struct drm_plane *plane = &ast_plane->base;
+
+ ast_plane->vaddr = vaddr;
+ ast_plane->offset = offset;
+ ast_plane->size = size;
+
+ return drm_universal_plane_init(dev, plane, possible_crtcs, funcs,
+ formats, format_count, format_modifiers,
+ type, NULL);
+}
+
+/*
* Primary plane
*/
@@ -550,52 +603,62 @@ static const uint32_t ast_primary_plane_formats[] = {
static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane,
struct drm_atomic_state *state)
{
- struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
- plane);
- struct drm_crtc_state *crtc_state;
- struct ast_crtc_state *ast_crtc_state;
+ struct drm_device *dev = plane->dev;
+ struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
+ struct drm_crtc_state *new_crtc_state = NULL;
+ struct ast_crtc_state *new_ast_crtc_state;
int ret;
- if (!new_plane_state->crtc)
- return 0;
-
- crtc_state = drm_atomic_get_new_crtc_state(state,
- new_plane_state->crtc);
+ if (new_plane_state->crtc)
+ new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
- ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
+ ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
DRM_PLANE_NO_SCALING,
DRM_PLANE_NO_SCALING,
false, true);
- if (ret)
+ if (ret) {
return ret;
+ } else if (!new_plane_state->visible) {
+ if (drm_WARN_ON(dev, new_plane_state->crtc)) /* cannot legally happen */
+ return -EINVAL;
+ else
+ return 0;
+ }
- if (!new_plane_state->visible)
- return 0;
-
- ast_crtc_state = to_ast_crtc_state(crtc_state);
+ new_ast_crtc_state = to_ast_crtc_state(new_crtc_state);
- ast_crtc_state->format = new_plane_state->fb->format;
+ new_ast_crtc_state->format = new_plane_state->fb->format;
return 0;
}
-static void
-ast_primary_plane_helper_atomic_update(struct drm_plane *plane,
- struct drm_atomic_state *state)
+static void ast_handle_damage(struct ast_plane *ast_plane, struct iosys_map *src,
+ struct drm_framebuffer *fb,
+ const struct drm_rect *clip)
+{
+ struct iosys_map dst = IOSYS_MAP_INIT_VADDR(ast_plane->vaddr);
+
+ iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, clip));
+ drm_fb_memcpy(&dst, fb->pitches, src, fb, clip);
+}
+
+static void ast_primary_plane_helper_atomic_update(struct drm_plane *plane,
+ struct drm_atomic_state *state)
{
- struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
- plane);
struct drm_device *dev = plane->dev;
struct ast_private *ast = to_ast_private(dev);
- struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
- plane);
- struct drm_gem_vram_object *gbo;
- s64 gpu_addr;
- struct drm_framebuffer *fb = new_state->fb;
- struct drm_framebuffer *old_fb = old_state->fb;
+ struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
+ struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
+ struct drm_framebuffer *fb = plane_state->fb;
+ struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
+ struct drm_framebuffer *old_fb = old_plane_state->fb;
+ struct ast_plane *ast_plane = to_ast_plane(plane);
+ struct drm_rect damage;
+ struct drm_atomic_helper_damage_iter iter;
if (!old_fb || (fb->format != old_fb->format)) {
- struct drm_crtc_state *crtc_state = new_state->crtc->state;
+ struct drm_crtc *crtc = plane_state->crtc;
+ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
@@ -603,20 +666,28 @@ ast_primary_plane_helper_atomic_update(struct drm_plane *plane,
ast_set_vbios_color_reg(ast, fb->format, vbios_mode_info);
}
- gbo = drm_gem_vram_of_gem(fb->obj[0]);
- gpu_addr = drm_gem_vram_offset(gbo);
- if (drm_WARN_ON_ONCE(dev, gpu_addr < 0))
- return; /* Bug: we didn't pin the BO to VRAM in prepare_fb. */
-
- ast_set_offset_reg(ast, fb);
- ast_set_start_address_crt1(ast, (u32)gpu_addr);
+ drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_for_each_plane_damage(&iter, &damage) {
+ ast_handle_damage(ast_plane, shadow_plane_state->data, fb, &damage);
+ }
- ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x00);
+ /*
+ * Some BMCs stop scanning out the video signal after the driver
+ * reprogrammed the offset or scanout address. This stalls display
+ * output for several seconds and makes the display unusable.
+ * Therefore only update the offset if it changes and reprogram the
+ * address after enabling the plane.
+ */
+ if (!old_fb || old_fb->pitches[0] != fb->pitches[0])
+ ast_set_offset_reg(ast, fb);
+ if (!old_fb) {
+ ast_set_start_address_crt1(ast, (u32)ast_plane->offset);
+ ast_set_index_reg_mask(ast, AST_IO_SEQ_PORT, 0x1, 0xdf, 0x00);
+ }
}
-static void
-ast_primary_plane_helper_atomic_disable(struct drm_plane *plane,
- struct drm_atomic_state *state)
+static void ast_primary_plane_helper_atomic_disable(struct drm_plane *plane,
+ struct drm_atomic_state *state)
{
struct ast_private *ast = to_ast_private(plane->dev);
@@ -624,7 +695,7 @@ ast_primary_plane_helper_atomic_disable(struct drm_plane *plane,
}
static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = {
- DRM_GEM_VRAM_PLANE_HELPER_FUNCS,
+ DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
.atomic_check = ast_primary_plane_helper_atomic_check,
.atomic_update = ast_primary_plane_helper_atomic_update,
.atomic_disable = ast_primary_plane_helper_atomic_disable,
@@ -634,27 +705,30 @@ static const struct drm_plane_funcs ast_primary_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = drm_plane_cleanup,
- .reset = drm_atomic_helper_plane_reset,
- .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+ DRM_GEM_SHADOW_PLANE_FUNCS,
};
static int ast_primary_plane_init(struct ast_private *ast)
{
struct drm_device *dev = &ast->base;
- struct drm_plane *primary_plane = &ast->primary_plane;
+ struct ast_plane *ast_primary_plane = &ast->primary_plane;
+ struct drm_plane *primary_plane = &ast_primary_plane->base;
+ void __iomem *vaddr = ast->vram;
+ u64 offset = ast->vram_base;
+ unsigned long cursor_size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE);
+ unsigned long size = ast->vram_fb_available - cursor_size;
int ret;
- ret = drm_universal_plane_init(dev, primary_plane, 0x01,
- &ast_primary_plane_funcs,
- ast_primary_plane_formats,
- ARRAY_SIZE(ast_primary_plane_formats),
- NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
+ ret = ast_plane_init(dev, ast_primary_plane, vaddr, offset, size,
+ 0x01, &ast_primary_plane_funcs,
+ ast_primary_plane_formats, ARRAY_SIZE(ast_primary_plane_formats),
+ NULL, DRM_PLANE_TYPE_PRIMARY);
if (ret) {
- drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
+ drm_err(dev, "ast_plane_init() failed: %d\n", ret);
return ret;
}
drm_plane_helper_add(primary_plane, &ast_primary_plane_helper_funcs);
+ drm_plane_enable_fb_damage_clips(primary_plane);
return 0;
}
@@ -774,99 +848,79 @@ static const uint32_t ast_cursor_plane_formats[] = {
static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane,
struct drm_atomic_state *state)
{
- struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
- plane);
- struct drm_framebuffer *fb = new_plane_state->fb;
- struct drm_crtc_state *crtc_state;
+ struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
+ struct drm_framebuffer *new_fb = new_plane_state->fb;
+ struct drm_crtc_state *new_crtc_state = NULL;
int ret;
- if (!new_plane_state->crtc)
- return 0;
-
- crtc_state = drm_atomic_get_new_crtc_state(state,
- new_plane_state->crtc);
+ if (new_plane_state->crtc)
+ new_crtc_state = drm_atomic_get_new_crtc_state(state, new_plane_state->crtc);
- ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
+ ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
DRM_PLANE_NO_SCALING,
DRM_PLANE_NO_SCALING,
true, true);
- if (ret)
+ if (ret || !new_plane_state->visible)
return ret;
- if (!new_plane_state->visible)
- return 0;
-
- if (fb->width > AST_MAX_HWC_WIDTH || fb->height > AST_MAX_HWC_HEIGHT)
+ if (new_fb->width > AST_MAX_HWC_WIDTH || new_fb->height > AST_MAX_HWC_HEIGHT)
return -EINVAL;
return 0;
}
-static void
-ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,
- struct drm_atomic_state *state)
+static void ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,
+ struct drm_atomic_state *state)
{
- struct ast_cursor_plane *ast_cursor_plane = to_ast_cursor_plane(plane);
- struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
- plane);
- struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
- plane);
- struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(new_state);
- struct drm_framebuffer *fb = new_state->fb;
+ struct ast_plane *ast_plane = to_ast_plane(plane);
+ struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
+ struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
+ struct drm_framebuffer *fb = plane_state->fb;
+ struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct ast_private *ast = to_ast_private(plane->dev);
- struct iosys_map dst_map =
- ast_cursor_plane->hwc[ast_cursor_plane->next_hwc_index].map;
- u64 dst_off =
- ast_cursor_plane->hwc[ast_cursor_plane->next_hwc_index].off;
struct iosys_map src_map = shadow_plane_state->data[0];
+ struct drm_rect damage;
+ const u8 *src = src_map.vaddr; /* TODO: Use mapping abstraction properly */
+ u64 dst_off = ast_plane->offset;
+ u8 __iomem *dst = ast_plane->vaddr; /* TODO: Use mapping abstraction properly */
+ u8 __iomem *sig = dst + AST_HWC_SIZE; /* TODO: Use mapping abstraction properly */
unsigned int offset_x, offset_y;
u16 x, y;
u8 x_offset, y_offset;
- u8 __iomem *dst;
- u8 __iomem *sig;
- const u8 *src;
-
- src = src_map.vaddr; /* TODO: Use mapping abstraction properly */
- dst = dst_map.vaddr_iomem; /* TODO: Use mapping abstraction properly */
- sig = dst + AST_HWC_SIZE; /* TODO: Use mapping abstraction properly */
/*
- * Do data transfer to HW cursor BO. If a new cursor image was installed,
- * point the scanout engine to dst_gbo's offset and page-flip the HWC buffers.
+ * Do data transfer to hardware buffer and point the scanout
+ * engine to the offset.
*/
- ast_update_cursor_image(dst, src, fb->width, fb->height);
-
- if (new_state->fb != old_state->fb) {
+ if (drm_atomic_helper_damage_merged(old_plane_state, plane_state, &damage)) {
+ ast_update_cursor_image(dst, src, fb->width, fb->height);
ast_set_cursor_base(ast, dst_off);
-
- ++ast_cursor_plane->next_hwc_index;
- ast_cursor_plane->next_hwc_index %= ARRAY_SIZE(ast_cursor_plane->hwc);
}
/*
* Update location in HWC signature and registers.
*/
- writel(new_state->crtc_x, sig + AST_HWC_SIGNATURE_X);
- writel(new_state->crtc_y, sig + AST_HWC_SIGNATURE_Y);
+ writel(plane_state->crtc_x, sig + AST_HWC_SIGNATURE_X);
+ writel(plane_state->crtc_y, sig + AST_HWC_SIGNATURE_Y);
offset_x = AST_MAX_HWC_WIDTH - fb->width;
offset_y = AST_MAX_HWC_HEIGHT - fb->height;
- if (new_state->crtc_x < 0) {
- x_offset = (-new_state->crtc_x) + offset_x;
+ if (plane_state->crtc_x < 0) {
+ x_offset = (-plane_state->crtc_x) + offset_x;
x = 0;
} else {
x_offset = offset_x;
- x = new_state->crtc_x;
+ x = plane_state->crtc_x;
}
- if (new_state->crtc_y < 0) {
- y_offset = (-new_state->crtc_y) + offset_y;
+ if (plane_state->crtc_y < 0) {
+ y_offset = (-plane_state->crtc_y) + offset_y;
y = 0;
} else {
y_offset = offset_y;
- y = new_state->crtc_y;
+ y = plane_state->crtc_y;
}
ast_set_cursor_location(ast, x, y, x_offset, y_offset);
@@ -875,9 +929,8 @@ ast_cursor_plane_helper_atomic_update(struct drm_plane *plane,
ast_set_cursor_enabled(ast, true);
}
-static void
-ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane,
- struct drm_atomic_state *state)
+static void ast_cursor_plane_helper_atomic_disable(struct drm_plane *plane,
+ struct drm_atomic_state *state)
{
struct ast_private *ast = to_ast_private(plane->dev);
@@ -891,41 +944,22 @@ static const struct drm_plane_helper_funcs ast_cursor_plane_helper_funcs = {
.atomic_disable = ast_cursor_plane_helper_atomic_disable,
};
-static void ast_cursor_plane_destroy(struct drm_plane *plane)
-{
- struct ast_cursor_plane *ast_cursor_plane = to_ast_cursor_plane(plane);
- size_t i;
- struct drm_gem_vram_object *gbo;
- struct iosys_map map;
-
- for (i = 0; i < ARRAY_SIZE(ast_cursor_plane->hwc); ++i) {
- gbo = ast_cursor_plane->hwc[i].gbo;
- map = ast_cursor_plane->hwc[i].map;
- drm_gem_vram_vunmap(gbo, &map);
- drm_gem_vram_unpin(gbo);
- drm_gem_vram_put(gbo);
- }
-
- drm_plane_cleanup(plane);
-}
-
static const struct drm_plane_funcs ast_cursor_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
- .destroy = ast_cursor_plane_destroy,
+ .destroy = drm_plane_cleanup,
DRM_GEM_SHADOW_PLANE_FUNCS,
};
static int ast_cursor_plane_init(struct ast_private *ast)
{
struct drm_device *dev = &ast->base;
- struct ast_cursor_plane *ast_cursor_plane = &ast->cursor_plane;
+ struct ast_plane *ast_cursor_plane = &ast->cursor_plane;
struct drm_plane *cursor_plane = &ast_cursor_plane->base;
- size_t size, i;
- struct drm_gem_vram_object *gbo;
- struct iosys_map map;
+ size_t size;
+ void __iomem *vaddr;
+ u64 offset;
int ret;
- s64 off;
/*
* Allocate backing storage for cursors. The BOs are permanently
@@ -934,60 +968,26 @@ static int ast_cursor_plane_init(struct ast_private *ast)
size = roundup(AST_HWC_SIZE + AST_HWC_SIGNATURE_SIZE, PAGE_SIZE);
- for (i = 0; i < ARRAY_SIZE(ast_cursor_plane->hwc); ++i) {
- gbo = drm_gem_vram_create(dev, size, 0);
- if (IS_ERR(gbo)) {
- ret = PTR_ERR(gbo);
- goto err_hwc;
- }
- ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM |
- DRM_GEM_VRAM_PL_FLAG_TOPDOWN);
- if (ret)
- goto err_drm_gem_vram_put;
- ret = drm_gem_vram_vmap(gbo, &map);
- if (ret)
- goto err_drm_gem_vram_unpin;
- off = drm_gem_vram_offset(gbo);
- if (off < 0) {
- ret = off;
- goto err_drm_gem_vram_vunmap;
- }
- ast_cursor_plane->hwc[i].gbo = gbo;
- ast_cursor_plane->hwc[i].map = map;
- ast_cursor_plane->hwc[i].off = off;
- }
+ if (ast->vram_fb_available < size)
+ return -ENOMEM;
- /*
- * Create the cursor plane. The plane's destroy callback will release
- * the backing storages' BO memory.
- */
+ vaddr = ast->vram + ast->vram_fb_available - size;
+ offset = ast->vram_base + ast->vram_fb_available - size;
- ret = drm_universal_plane_init(dev, cursor_plane, 0x01,
- &ast_cursor_plane_funcs,
- ast_cursor_plane_formats,
- ARRAY_SIZE(ast_cursor_plane_formats),
- NULL, DRM_PLANE_TYPE_CURSOR, NULL);
+ ret = ast_plane_init(dev, ast_cursor_plane, vaddr, offset, size,
+ 0x01, &ast_cursor_plane_funcs,
+ ast_cursor_plane_formats, ARRAY_SIZE(ast_cursor_plane_formats),
+ NULL, DRM_PLANE_TYPE_CURSOR);
if (ret) {
- drm_err(dev, "drm_universal_plane failed(): %d\n", ret);
- goto err_hwc;
+ drm_err(dev, "ast_plane_init() failed: %d\n", ret);
+ return ret;
}
drm_plane_helper_add(cursor_plane, &ast_cursor_plane_helper_funcs);
+ drm_plane_enable_fb_damage_clips(cursor_plane);
- return 0;
+ ast->vram_fb_available -= size;
-err_hwc:
- while (i) {
- --i;
- gbo = ast_cursor_plane->hwc[i].gbo;
- map = ast_cursor_plane->hwc[i].map;
-err_drm_gem_vram_vunmap:
- drm_gem_vram_vunmap(gbo, &map);
-err_drm_gem_vram_unpin:
- drm_gem_vram_unpin(gbo);
-err_drm_gem_vram_put:
- drm_gem_vram_put(gbo);
- }
- return ret;
+ return 0;
}
/*
@@ -1026,9 +1026,11 @@ static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
ast_set_color_reg(ast, format);
ast_set_vbios_color_reg(ast, format, vbios_mode_info);
+ if (crtc->state->gamma_lut)
+ ast_crtc_set_gamma(ast, format, crtc->state->gamma_lut->data);
+ else
+ ast_crtc_set_gamma_linear(ast, format);
}
-
- ast_crtc_load_lut(ast, crtc);
break;
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
@@ -1123,47 +1125,50 @@ static int ast_crtc_helper_atomic_check(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+ struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
+ struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
struct drm_device *dev = crtc->dev;
struct ast_crtc_state *ast_state;
const struct drm_format_info *format;
bool succ;
int ret;
- ret = drm_atomic_helper_check_crtc_state(crtc_state, false);
+ if (!crtc_state->enable)
+ return 0;
+
+ ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state);
if (ret)
return ret;
- if (!crtc_state->enable)
- goto out;
-
ast_state = to_ast_crtc_state(crtc_state);
format = ast_state->format;
if (drm_WARN_ON_ONCE(dev, !format))
return -EINVAL; /* BUG: We didn't set format in primary check(). */
+ /*
+ * The gamma LUT has to be reloaded after changing the primary
+ * plane's color format.
+ */
+ if (old_ast_crtc_state->format != format)
+ crtc_state->color_mgmt_changed = true;
+
+ if (crtc_state->color_mgmt_changed && crtc_state->gamma_lut) {
+ if (crtc_state->gamma_lut->length !=
+ AST_LUT_SIZE * sizeof(struct drm_color_lut)) {
+ drm_err(dev, "Wrong size for gamma_lut %zu\n",
+ crtc_state->gamma_lut->length);
+ return -EINVAL;
+ }
+ }
+
succ = ast_get_vbios_mode_info(format, &crtc_state->mode,
&crtc_state->adjusted_mode,
&ast_state->vbios_mode_info);
if (!succ)
return -EINVAL;
-out:
- return drm_atomic_add_affected_planes(state, crtc);
-}
-
-static void ast_crtc_helper_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state)
-{
- struct drm_device *dev = crtc->dev;
- struct ast_private *ast = to_ast_private(dev);
-
- /*
- * Concurrent operations could possibly trigger a call to
- * drm_connector_helper_funcs.get_modes by trying to read the
- * display modes. Protect access to I/O registers by acquiring
- * the I/O-register lock. Released in atomic_flush().
- */
- mutex_lock(&ast->ioregs_lock);
+ return 0;
}
static void
@@ -1172,35 +1177,34 @@ ast_crtc_helper_atomic_flush(struct drm_crtc *crtc,
{
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
crtc);
- struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state,
- crtc);
struct drm_device *dev = crtc->dev;
struct ast_private *ast = to_ast_private(dev);
struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
- struct ast_crtc_state *old_ast_crtc_state = to_ast_crtc_state(old_crtc_state);
struct ast_vbios_mode_info *vbios_mode_info = &ast_crtc_state->vbios_mode_info;
/*
* The gamma LUT has to be reloaded after changing the primary
* plane's color format.
*/
- if (old_ast_crtc_state->format != ast_crtc_state->format)
- ast_crtc_load_lut(ast, crtc);
+ if (crtc_state->enable && crtc_state->color_mgmt_changed) {
+ if (crtc_state->gamma_lut)
+ ast_crtc_set_gamma(ast,
+ ast_crtc_state->format,
+ crtc_state->gamma_lut->data);
+ else
+ ast_crtc_set_gamma_linear(ast, ast_crtc_state->format);
+ }
//Set Aspeed Display-Port
if (ast->tx_chip_types & AST_TX_ASTDP_BIT)
ast_dp_set_mode(crtc, vbios_mode_info);
-
- mutex_unlock(&ast->ioregs_lock);
}
-static void
-ast_crtc_helper_atomic_enable(struct drm_crtc *crtc,
- struct drm_atomic_state *state)
+static void ast_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state)
{
struct drm_device *dev = crtc->dev;
struct ast_private *ast = to_ast_private(dev);
- struct drm_crtc_state *crtc_state = crtc->state;
+ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
struct ast_crtc_state *ast_crtc_state = to_ast_crtc_state(crtc_state);
struct ast_vbios_mode_info *vbios_mode_info =
&ast_crtc_state->vbios_mode_info;
@@ -1217,12 +1221,9 @@ ast_crtc_helper_atomic_enable(struct drm_crtc *crtc,
ast_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
}
-static void
-ast_crtc_helper_atomic_disable(struct drm_crtc *crtc,
- struct drm_atomic_state *state)
+static void ast_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state)
{
- struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state,
- crtc);
+ struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc);
struct drm_device *dev = crtc->dev;
struct ast_private *ast = to_ast_private(dev);
@@ -1250,7 +1251,6 @@ ast_crtc_helper_atomic_disable(struct drm_crtc *crtc,
static const struct drm_crtc_helper_funcs ast_crtc_helper_funcs = {
.mode_valid = ast_crtc_helper_mode_valid,
.atomic_check = ast_crtc_helper_atomic_check,
- .atomic_begin = ast_crtc_helper_atomic_begin,
.atomic_flush = ast_crtc_helper_atomic_flush,
.atomic_enable = ast_crtc_helper_atomic_enable,
.atomic_disable = ast_crtc_helper_atomic_disable,
@@ -1317,13 +1317,15 @@ static int ast_crtc_init(struct drm_device *dev)
struct drm_crtc *crtc = &ast->crtc;
int ret;
- ret = drm_crtc_init_with_planes(dev, crtc, &ast->primary_plane,
+ ret = drm_crtc_init_with_planes(dev, crtc, &ast->primary_plane.base,
&ast->cursor_plane.base, &ast_crtc_funcs,
NULL);
if (ret)
return ret;
- drm_mode_crtc_set_gamma_size(crtc, 256);
+ drm_mode_crtc_set_gamma_size(crtc, AST_LUT_SIZE);
+ drm_crtc_enable_color_mgmt(crtc, 0, false, AST_LUT_SIZE);
+
drm_crtc_helper_add(crtc, &ast_crtc_helper_funcs);
return 0;
@@ -1718,13 +1720,46 @@ static int ast_astdp_output_init(struct ast_private *ast)
* Mode config
*/
+static void ast_mode_config_helper_atomic_commit_tail(struct drm_atomic_state *state)
+{
+ struct ast_private *ast = to_ast_private(state->dev);
+
+ /*
+ * Concurrent operations could possibly trigger a call to
+ * drm_connector_helper_funcs.get_modes by trying to read the
+ * display modes. Protect access to I/O registers by acquiring
+ * the I/O-register lock. Released in atomic_flush().
+ */
+ mutex_lock(&ast->ioregs_lock);
+ drm_atomic_helper_commit_tail_rpm(state);
+ mutex_unlock(&ast->ioregs_lock);
+}
+
static const struct drm_mode_config_helper_funcs ast_mode_config_helper_funcs = {
- .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
+ .atomic_commit_tail = ast_mode_config_helper_atomic_commit_tail,
};
+static enum drm_mode_status ast_mode_config_mode_valid(struct drm_device *dev,
+ const struct drm_display_mode *mode)
+{
+ static const unsigned long max_bpp = 4; /* DRM_FORMAT_XRGB8888 */
+ struct ast_private *ast = to_ast_private(dev);
+ unsigned long fbsize, fbpages, max_fbpages;
+
+ max_fbpages = (ast->vram_fb_available) >> PAGE_SHIFT;
+
+ fbsize = mode->hdisplay * mode->vdisplay * max_bpp;
+ fbpages = DIV_ROUND_UP(fbsize, PAGE_SIZE);
+
+ if (fbpages > max_fbpages)
+ return MODE_MEM;
+
+ return MODE_OK;
+}
+
static const struct drm_mode_config_funcs ast_mode_config_funcs = {
- .fb_create = drm_gem_fb_create,
- .mode_valid = drm_vram_helper_mode_valid,
+ .fb_create = drm_gem_fb_create_with_dirty,
+ .mode_valid = ast_mode_config_mode_valid,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit,
};
@@ -1732,7 +1767,6 @@ static const struct drm_mode_config_funcs ast_mode_config_funcs = {
int ast_mode_config_init(struct ast_private *ast)
{
struct drm_device *dev = &ast->base;
- struct pci_dev *pdev = to_pci_dev(dev->dev);
int ret;
ret = drmm_mode_config_init(dev);
@@ -1743,8 +1777,6 @@ int ast_mode_config_init(struct ast_private *ast)
dev->mode_config.min_width = 0;
dev->mode_config.min_height = 0;
dev->mode_config.preferred_depth = 24;
- dev->mode_config.prefer_shadow = 1;
- dev->mode_config.fb_base = pci_resource_start(pdev, 0);
if (ast->chip == AST2100 ||
ast->chip == AST2200 ||
@@ -1761,7 +1793,6 @@ int ast_mode_config_init(struct ast_private *ast)
dev->mode_config.helper_private = &ast_mode_config_helper_funcs;
-
ret = ast_primary_plane_init(ast);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index f7e7f4e919c7..a2bb5b916235 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -19,7 +19,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_module.h>
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h
index 94de73cbeb2d..17445800248d 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511.h
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h
@@ -402,7 +402,8 @@ static inline int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
void adv7533_dsi_power_on(struct adv7511 *adv);
void adv7533_dsi_power_off(struct adv7511 *adv);
-void adv7533_mode_set(struct adv7511 *adv, const struct drm_display_mode *mode);
+enum drm_mode_status adv7533_mode_valid(struct adv7511 *adv,
+ const struct drm_display_mode *mode);
int adv7533_patch_registers(struct adv7511 *adv);
int adv7533_patch_cec_registers(struct adv7511 *adv);
int adv7533_attach_dsi(struct adv7511 *adv);
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index f887200e8abc..e7a6e456ed0d 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -697,7 +697,7 @@ adv7511_detect(struct adv7511 *adv7511, struct drm_connector *connector)
}
static enum drm_mode_status adv7511_mode_valid(struct adv7511 *adv7511,
- struct drm_display_mode *mode)
+ const struct drm_display_mode *mode)
{
if (mode->clock > 165000)
return MODE_CLOCK_HIGH;
@@ -791,9 +791,6 @@ static void adv7511_mode_set(struct adv7511 *adv7511,
regmap_update_bits(adv7511->regmap, 0x17,
0x60, (vsync_polarity << 6) | (hsync_polarity << 5));
- if (adv7511->type == ADV7533 || adv7511->type == ADV7535)
- adv7533_mode_set(adv7511, adj_mode);
-
drm_mode_copy(&adv7511->curr_mode, adj_mode);
/*
@@ -913,6 +910,18 @@ static void adv7511_bridge_mode_set(struct drm_bridge *bridge,
adv7511_mode_set(adv, mode, adj_mode);
}
+static enum drm_mode_status adv7511_bridge_mode_valid(struct drm_bridge *bridge,
+ const struct drm_display_info *info,
+ const struct drm_display_mode *mode)
+{
+ struct adv7511 *adv = bridge_to_adv7511(bridge);
+
+ if (adv->type == ADV7533 || adv->type == ADV7535)
+ return adv7533_mode_valid(adv, mode);
+ else
+ return adv7511_mode_valid(adv, mode);
+}
+
static int adv7511_bridge_attach(struct drm_bridge *bridge,
enum drm_bridge_attach_flags flags)
{
@@ -960,6 +969,7 @@ static const struct drm_bridge_funcs adv7511_bridge_funcs = {
.enable = adv7511_bridge_enable,
.disable = adv7511_bridge_disable,
.mode_set = adv7511_bridge_mode_set,
+ .mode_valid = adv7511_bridge_mode_valid,
.attach = adv7511_bridge_attach,
.detect = adv7511_bridge_detect,
.get_edid = adv7511_bridge_get_edid,
@@ -1209,10 +1219,8 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
return ret;
ret = adv7511_init_regulators(adv7511);
- if (ret) {
- dev_err(dev, "failed to init regulators\n");
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to init regulators\n");
/*
* The power down GPIO is optional. If present, toggle it from active to
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7533.c b/drivers/gpu/drm/bridge/adv7511/adv7533.c
index ef6270806d1d..fdfeadcefe80 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7533.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7533.c
@@ -100,26 +100,27 @@ void adv7533_dsi_power_off(struct adv7511 *adv)
regmap_write(adv->regmap_cec, 0x27, 0x0b);
}
-void adv7533_mode_set(struct adv7511 *adv, const struct drm_display_mode *mode)
+enum drm_mode_status adv7533_mode_valid(struct adv7511 *adv,
+ const struct drm_display_mode *mode)
{
+ int lanes;
struct mipi_dsi_device *dsi = adv->dsi;
- int lanes, ret;
-
- if (adv->num_dsi_lanes != 4)
- return;
if (mode->clock > 80000)
lanes = 4;
else
lanes = 3;
- if (lanes != dsi->lanes) {
- mipi_dsi_detach(dsi);
- dsi->lanes = lanes;
- ret = mipi_dsi_attach(dsi);
- if (ret)
- dev_err(&dsi->dev, "failed to change host lanes\n");
- }
+ /*
+ * TODO: add support for dynamic switching of lanes
+ * by using the bridge pre_enable() op . Till then filter
+ * out the modes which shall need different number of lanes
+ * than what was configured in the device tree.
+ */
+ if (lanes != dsi->lanes)
+ return MODE_BAD;
+
+ return MODE_OK;
}
int adv7533_patch_registers(struct adv7511 *adv)
@@ -148,16 +149,14 @@ int adv7533_attach_dsi(struct adv7511 *adv)
};
host = of_find_mipi_dsi_host_by_node(adv->host_node);
- if (!host) {
- dev_err(dev, "failed to find dsi host\n");
- return -EPROBE_DEFER;
- }
+ if (!host)
+ return dev_err_probe(dev, -EPROBE_DEFER,
+ "failed to find dsi host\n");
dsi = devm_mipi_dsi_device_register_full(dev, host, &info);
- if (IS_ERR(dsi)) {
- dev_err(dev, "failed to create dsi device\n");
- return PTR_ERR(dsi);
- }
+ if (IS_ERR(dsi))
+ return dev_err_probe(dev, PTR_ERR(dsi),
+ "failed to create dsi device\n");
adv->dsi = dsi;
@@ -167,10 +166,8 @@ int adv7533_attach_dsi(struct adv7511 *adv)
MIPI_DSI_MODE_NO_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE;
ret = devm_mipi_dsi_attach(dev, dsi);
- if (ret < 0) {
- dev_err(dev, "failed to attach dsi to host\n");
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "failed to attach dsi to host\n");
return 0;
}
diff --git a/drivers/gpu/drm/bridge/ite-it6505.c b/drivers/gpu/drm/bridge/ite-it6505.c
index dfe4351c9bdd..21a9b8422bda 100644
--- a/drivers/gpu/drm/bridge/ite-it6505.c
+++ b/drivers/gpu/drm/bridge/ite-it6505.c
@@ -412,6 +412,7 @@ struct it6505 {
* Mutex protects extcon and interrupt functions from interfering
* each other.
*/
+ struct mutex irq_lock;
struct mutex extcon_lock;
struct mutex mode_lock; /* used to bridge_detect */
struct mutex aux_lock; /* used to aux data transfers */
@@ -421,6 +422,7 @@ struct it6505 {
struct notifier_block event_nb;
struct extcon_dev *extcon;
struct work_struct extcon_wq;
+ int extcon_state;
enum drm_connector_status connector_status;
enum link_train_status link_state;
struct work_struct link_works;
@@ -439,7 +441,7 @@ struct it6505 {
enum hdcp_state hdcp_status;
struct delayed_work hdcp_work;
struct work_struct hdcp_wait_ksv_list;
- struct completion wait_edid_complete;
+ struct completion extcon_completion;
u8 auto_train_retry;
bool hdcp_desired;
bool is_repeater;
@@ -724,28 +726,6 @@ static void it6505_calc_video_info(struct it6505 *it6505)
DRM_MODE_ARG(&it6505->video_info));
}
-static int it6505_drm_dp_link_probe(struct drm_dp_aux *aux,
- struct it6505_drm_dp_link *link)
-{
- u8 values[3];
- int err;
-
- memset(link, 0, sizeof(*link));
-
- err = drm_dp_dpcd_read(aux, DP_DPCD_REV, values, sizeof(values));
- if (err < 0)
- return err;
-
- link->revision = values[0];
- link->rate = drm_dp_bw_code_to_link_rate(values[1]);
- link->num_lanes = values[2] & DP_MAX_LANE_COUNT_MASK;
-
- if (values[2] & DP_ENHANCED_FRAME_CAP)
- link->capabilities = DP_ENHANCED_FRAME_CAP;
-
- return 0;
-}
-
static int it6505_drm_dp_link_set_power(struct drm_dp_aux *aux,
struct it6505_drm_dp_link *link,
u8 mode)
@@ -1455,11 +1435,19 @@ static void it6505_parse_link_capabilities(struct it6505 *it6505)
int bcaps;
if (it6505->dpcd[0] == 0) {
- it6505_aux_on(it6505);
- it6505_get_dpcd(it6505, DP_DPCD_REV, it6505->dpcd,
- ARRAY_SIZE(it6505->dpcd));
+ dev_err(dev, "DPCD is not initialized");
+ return;
}
+ memset(link, 0, sizeof(*link));
+
+ link->revision = it6505->dpcd[0];
+ link->rate = drm_dp_bw_code_to_link_rate(it6505->dpcd[1]);
+ link->num_lanes = it6505->dpcd[2] & DP_MAX_LANE_COUNT_MASK;
+
+ if (it6505->dpcd[2] & DP_ENHANCED_FRAME_CAP)
+ link->capabilities = DP_ENHANCED_FRAME_CAP;
+
DRM_DEV_DEBUG_DRIVER(dev, "DPCD Rev.: %d.%d",
link->revision >> 4, link->revision & 0x0F);
@@ -2322,19 +2310,32 @@ static int it6505_process_hpd_irq(struct it6505 *it6505)
static void it6505_irq_hpd(struct it6505 *it6505)
{
struct device *dev = &it6505->client->dev;
+ int dp_sink_count;
it6505->hpd_state = it6505_get_sink_hpd_status(it6505);
DRM_DEV_DEBUG_DRIVER(dev, "hpd change interrupt, change to %s",
it6505->hpd_state ? "high" : "low");
- if (it6505->bridge.dev)
- drm_helper_hpd_irq_event(it6505->bridge.dev);
- DRM_DEV_DEBUG_DRIVER(dev, "it6505->sink_count: %d",
- it6505->sink_count);
-
if (it6505->hpd_state) {
- wait_for_completion_timeout(&it6505->wait_edid_complete,
- msecs_to_jiffies(6000));
+ wait_for_completion_timeout(&it6505->extcon_completion,
+ msecs_to_jiffies(1000));
+ it6505_aux_on(it6505);
+ if (it6505->dpcd[0] == 0) {
+ it6505_get_dpcd(it6505, DP_DPCD_REV, it6505->dpcd,
+ ARRAY_SIZE(it6505->dpcd));
+ it6505_variable_config(it6505);
+ it6505_parse_link_capabilities(it6505);
+ }
+ it6505->auto_train_retry = AUTO_TRAIN_RETRY;
+
+ it6505_drm_dp_link_set_power(&it6505->aux, &it6505->link,
+ DP_SET_POWER_D0);
+ dp_sink_count = it6505_dpcd_read(it6505, DP_SINK_COUNT);
+ it6505->sink_count = DP_GET_SINK_COUNT(dp_sink_count);
+
+ DRM_DEV_DEBUG_DRIVER(dev, "it6505->sink_count: %d",
+ it6505->sink_count);
+
it6505_lane_termination_on(it6505);
it6505_lane_power_on(it6505);
@@ -2362,6 +2363,9 @@ static void it6505_irq_hpd(struct it6505 *it6505)
it6505_lane_off(it6505);
it6505_link_reset_step_train(it6505);
}
+
+ if (it6505->bridge.dev)
+ drm_helper_hpd_irq_event(it6505->bridge.dev);
}
static void it6505_irq_hpd_irq(struct it6505 *it6505)
@@ -2490,8 +2494,7 @@ static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
};
int int_status[3], i;
- msleep(100);
- mutex_lock(&it6505->extcon_lock);
+ mutex_lock(&it6505->irq_lock);
if (it6505->enable_drv_hold || !it6505->powered)
goto unlock;
@@ -2521,7 +2524,7 @@ static irqreturn_t it6505_int_threaded_handler(int unused, void *data)
}
unlock:
- mutex_unlock(&it6505->extcon_lock);
+ mutex_unlock(&it6505->irq_lock);
return IRQ_HANDLED;
}
@@ -2624,26 +2627,14 @@ static enum drm_connector_status it6505_detect(struct it6505 *it6505)
goto unlock;
if (it6505->enable_drv_hold) {
- status = it6505_get_sink_hpd_status(it6505) ?
- connector_status_connected :
- connector_status_disconnected;
+ status = it6505->hpd_state ? connector_status_connected :
+ connector_status_disconnected;
goto unlock;
}
- if (it6505_get_sink_hpd_status(it6505)) {
- it6505_aux_on(it6505);
- it6505_drm_dp_link_probe(&it6505->aux, &it6505->link);
+ if (it6505->hpd_state) {
it6505_drm_dp_link_set_power(&it6505->aux, &it6505->link,
DP_SET_POWER_D0);
- it6505->auto_train_retry = AUTO_TRAIN_RETRY;
-
- if (it6505->dpcd[0] == 0) {
- it6505_get_dpcd(it6505, DP_DPCD_REV, it6505->dpcd,
- ARRAY_SIZE(it6505->dpcd));
- it6505_variable_config(it6505);
- it6505_parse_link_capabilities(it6505);
- }
-
dp_sink_count = it6505_dpcd_read(it6505, DP_SINK_COUNT);
it6505->sink_count = DP_GET_SINK_COUNT(dp_sink_count);
DRM_DEV_DEBUG_DRIVER(dev, "it6505->sink_count:%d branch:%d",
@@ -2685,31 +2676,44 @@ static void it6505_extcon_work(struct work_struct *work)
{
struct it6505 *it6505 = container_of(work, struct it6505, extcon_wq);
struct device *dev = &it6505->client->dev;
- int state = extcon_get_state(it6505->extcon, EXTCON_DISP_DP);
- unsigned int pwroffretry = 0;
+ int state, ret;
if (it6505->enable_drv_hold)
return;
mutex_lock(&it6505->extcon_lock);
+ state = extcon_get_state(it6505->extcon, EXTCON_DISP_DP);
DRM_DEV_DEBUG_DRIVER(dev, "EXTCON_DISP_DP = 0x%02x", state);
- if (state > 0) {
+
+ if (state == it6505->extcon_state || unlikely(state < 0))
+ goto unlock;
+ it6505->extcon_state = state;
+ if (state) {
DRM_DEV_DEBUG_DRIVER(dev, "start to power on");
msleep(100);
- it6505_poweron(it6505);
+ ret = pm_runtime_get_sync(dev);
+
+ /*
+ * On system resume, extcon_work can be triggered before
+ * pm_runtime_force_resume re-enables runtime power management.
+ * Handling the error here to make sure the bridge is powered on.
+ */
+ if (ret < 0)
+ it6505_poweron(it6505);
+
+ complete_all(&it6505->extcon_completion);
} else {
DRM_DEV_DEBUG_DRIVER(dev, "start to power off");
- while (it6505_poweroff(it6505) && pwroffretry++ < 5) {
- DRM_DEV_DEBUG_DRIVER(dev, "power off fail %d times",
- pwroffretry);
- }
+ pm_runtime_put_sync(dev);
+ reinit_completion(&it6505->extcon_completion);
drm_helper_hpd_irq_event(it6505->bridge.dev);
memset(it6505->dpcd, 0, sizeof(it6505->dpcd));
DRM_DEV_DEBUG_DRIVER(dev, "power off it6505 success!");
}
+unlock:
mutex_unlock(&it6505->extcon_lock);
}
@@ -2860,10 +2864,7 @@ static int it6505_bridge_attach(struct drm_bridge *bridge,
}
/* Register aux channel */
- it6505->aux.name = "DP-AUX";
- it6505->aux.dev = dev;
it6505->aux.drm_dev = bridge->dev;
- it6505->aux.transfer = it6505_aux_transfer;
ret = drm_dp_aux_register(&it6505->aux);
@@ -2980,6 +2981,28 @@ static void it6505_bridge_atomic_disable(struct drm_bridge *bridge,
}
}
+static void it6505_bridge_atomic_pre_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_state)
+{
+ struct it6505 *it6505 = bridge_to_it6505(bridge);
+ struct device *dev = &it6505->client->dev;
+
+ DRM_DEV_DEBUG_DRIVER(dev, "start");
+
+ pm_runtime_get_sync(dev);
+}
+
+static void it6505_bridge_atomic_post_disable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_state)
+{
+ struct it6505 *it6505 = bridge_to_it6505(bridge);
+ struct device *dev = &it6505->client->dev;
+
+ DRM_DEV_DEBUG_DRIVER(dev, "start");
+
+ pm_runtime_put_sync(dev);
+}
+
static enum drm_connector_status
it6505_bridge_detect(struct drm_bridge *bridge)
{
@@ -3014,6 +3037,8 @@ static const struct drm_bridge_funcs it6505_bridge_funcs = {
.mode_valid = it6505_bridge_mode_valid,
.atomic_enable = it6505_bridge_atomic_enable,
.atomic_disable = it6505_bridge_atomic_disable,
+ .atomic_pre_enable = it6505_bridge_atomic_pre_enable,
+ .atomic_post_disable = it6505_bridge_atomic_post_disable,
.detect = it6505_bridge_detect,
.get_edid = it6505_bridge_get_edid,
};
@@ -3032,8 +3057,10 @@ static __maybe_unused int it6505_bridge_suspend(struct device *dev)
return it6505_poweroff(it6505);
}
-static SIMPLE_DEV_PM_OPS(it6505_bridge_pm_ops, it6505_bridge_suspend,
- it6505_bridge_resume);
+static const struct dev_pm_ops it6505_bridge_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
+ SET_RUNTIME_PM_OPS(it6505_bridge_suspend, it6505_bridge_resume, NULL)
+};
static int it6505_init_pdata(struct it6505 *it6505)
{
@@ -3250,6 +3277,7 @@ static int it6505_i2c_probe(struct i2c_client *client,
if (!it6505)
return -ENOMEM;
+ mutex_init(&it6505->irq_lock);
mutex_init(&it6505->extcon_lock);
mutex_init(&it6505->mode_lock);
mutex_init(&it6505->aux_lock);
@@ -3305,7 +3333,7 @@ static int it6505_i2c_probe(struct i2c_client *client,
INIT_WORK(&it6505->link_works, it6505_link_training_work);
INIT_WORK(&it6505->hdcp_wait_ksv_list, it6505_hdcp_wait_ksv_list);
INIT_DELAYED_WORK(&it6505->hdcp_work, it6505_hdcp_work);
- init_completion(&it6505->wait_edid_complete);
+ init_completion(&it6505->extcon_completion);
memset(it6505->dpcd, 0, sizeof(it6505->dpcd));
it6505->powered = false;
it6505->enable_drv_hold = DEFAULT_DRV_HOLD;
@@ -3315,6 +3343,12 @@ static int it6505_i2c_probe(struct i2c_client *client,
DRM_DEV_DEBUG_DRIVER(dev, "it6505 device name: %s", dev_name(dev));
debugfs_init(it6505);
+ pm_runtime_enable(dev);
+
+ it6505->aux.name = "DP-AUX";
+ it6505->aux.dev = dev;
+ it6505->aux.transfer = it6505_aux_transfer;
+ drm_dp_aux_init(&it6505->aux);
it6505->bridge.funcs = &it6505_bridge_funcs;
it6505->bridge.type = DRM_MODE_CONNECTOR_DisplayPort;
diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c
index 083337a27966..6a614e54b383 100644
--- a/drivers/gpu/drm/bridge/parade-ps8640.c
+++ b/drivers/gpu/drm/bridge/parade-ps8640.c
@@ -304,7 +304,6 @@ static ssize_t ps8640_aux_transfer_msg(struct drm_dp_aux *aux,
}
switch (data & SWAUX_STATUS_MASK) {
- /* Ignore the DEFER cases as they are already handled in hardware */
case SWAUX_STATUS_NACK:
case SWAUX_STATUS_I2C_NACK:
/*
@@ -321,6 +320,14 @@ static ssize_t ps8640_aux_transfer_msg(struct drm_dp_aux *aux,
case SWAUX_STATUS_ACKM:
len = data & SWAUX_M_MASK;
break;
+ case SWAUX_STATUS_DEFER:
+ case SWAUX_STATUS_I2C_DEFER:
+ if (is_native_aux)
+ msg->reply |= DP_AUX_NATIVE_REPLY_DEFER;
+ else
+ msg->reply |= DP_AUX_I2C_REPLY_DEFER;
+ len = data & SWAUX_M_MASK;
+ break;
case SWAUX_STATUS_INVALID:
return -EOPNOTSUPP;
case SWAUX_STATUS_TIMEOUT:
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
index 40d8ca37f5bc..aa51c61a78c7 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2720,6 +2720,9 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
* if supported. In any case the default RGB888 format is added
*/
+ /* Default 8bit RGB fallback */
+ output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24;
+
if (max_bpc >= 16 && info->bpc == 16) {
if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
output_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48;
@@ -2753,9 +2756,6 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
output_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24;
- /* Default 8bit RGB fallback */
- output_fmts[i++] = MEDIA_BUS_FMT_RGB888_1X24;
-
*num_output_fmts = i;
return output_fmts;
diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c
index 7f4fce1aa998..0b6a28436885 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/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of_graph.h>
#include <linux/regulator/consumer.h>
@@ -19,7 +20,6 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c
index 02dc12b8151e..3ceb0e9f9bdc 100644
--- a/drivers/gpu/drm/bridge/tc358775.c
+++ b/drivers/gpu/drm/bridge/tc358775.c
@@ -408,7 +408,7 @@ static void tc_bridge_enable(struct drm_bridge *bridge)
(val >> 8) & 0xFF, val & 0xFF);
d2l_write(tc->i2c, SYSRST, SYS_RST_REG | SYS_RST_DSIRX | SYS_RST_BM |
- SYS_RST_LCD | SYS_RST_I2CM | SYS_RST_I2CS);
+ SYS_RST_LCD | SYS_RST_I2CM);
usleep_range(30000, 40000);
d2l_write(tc->i2c, PPI_TX_RX_TA, TTA_GET | TTA_SURE);
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
index 3c3561942eb6..eb24322df721 100644
--- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c
+++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c
@@ -931,9 +931,9 @@ static void ti_sn_bridge_set_video_timings(struct ti_sn65dsi86 *pdata)
&pdata->bridge.encoder->crtc->state->adjusted_mode;
u8 hsync_polarity = 0, vsync_polarity = 0;
- if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+ if (mode->flags & DRM_MODE_FLAG_NHSYNC)
hsync_polarity = CHA_HSYNC_POLARITY;
- if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+ if (mode->flags & DRM_MODE_FLAG_NVSYNC)
vsync_polarity = CHA_VSYNC_POLARITY;
ti_sn65dsi86_write_u16(pdata, SN_CHA_ACTIVE_LINE_LENGTH_LOW_REG,
diff --git a/drivers/gpu/drm/display/Makefile b/drivers/gpu/drm/display/Makefile
index 52cdda1180d9..17ac4a1006a8 100644
--- a/drivers/gpu/drm/display/Makefile
+++ b/drivers/gpu/drm/display/Makefile
@@ -3,13 +3,15 @@
obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o
drm_display_helper-y := drm_display_helper_mod.o
-drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_HELPER) += drm_dp_dual_mode_helper.o \
- drm_dp_helper.o \
- drm_dp_mst_topology.o \
- drm_dsc_helper.o
+drm_display_helper-$(CONFIG_DRM_DISPLAY_DP_HELPER) += \
+ drm_dp_dual_mode_helper.o \
+ drm_dp_helper.o \
+ drm_dp_mst_topology.o \
+ drm_dsc_helper.o
drm_display_helper-$(CONFIG_DRM_DISPLAY_HDCP_HELPER) += drm_hdcp_helper.o
-drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_HELPER) += drm_hdmi_helper.o \
- drm_scdc_helper.o
+drm_display_helper-$(CONFIG_DRM_DISPLAY_HDMI_HELPER) += \
+ drm_hdmi_helper.o \
+ drm_scdc_helper.o
drm_display_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
drm_display_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 98cc3137c062..d579fd8f7cb8 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -924,59 +924,35 @@ int drm_atomic_helper_check_plane_state(struct drm_plane_state *plane_state,
EXPORT_SYMBOL(drm_atomic_helper_check_plane_state);
/**
- * drm_atomic_helper_check_crtc_state() - Check CRTC state for validity
+ * drm_atomic_helper_check_crtc_primary_plane() - Check CRTC state for primary plane
* @crtc_state: CRTC state to check
- * @can_disable_primary_planes: can the CRTC be enabled without a primary plane?
*
- * Checks that a desired CRTC update is valid. Drivers that provide
- * their own CRTC handling rather than helper-provided implementations may
- * still wish to call this function to avoid duplication of error checking
- * code.
- *
- * Note that @can_disable_primary_planes only tests if the CRTC can be
- * enabled without a primary plane. To test if a primary plane can be updated
- * without a CRTC, use drm_atomic_helper_check_plane_state() in the plane's
- * atomic check.
+ * Checks that a CRTC has at least one primary plane attached to it, which is
+ * a requirement on some hardware. Note that this only involves the CRTC side
+ * of the test. To test if the primary plane is visible or if it can be updated
+ * without the CRTC being enabled, use drm_atomic_helper_check_plane_state() in
+ * the plane's atomic check.
*
* RETURNS:
- * Zero if update appears valid, error code on failure
+ * 0 if a primary plane is attached to the CRTC, or an error code otherwise
*/
-int drm_atomic_helper_check_crtc_state(struct drm_crtc_state *crtc_state,
- bool can_disable_primary_planes)
+int drm_atomic_helper_check_crtc_primary_plane(struct drm_crtc_state *crtc_state)
{
- struct drm_device *dev = crtc_state->crtc->dev;
- struct drm_atomic_state *state = crtc_state->state;
-
- if (!crtc_state->enable)
- return 0;
+ struct drm_crtc *crtc = crtc_state->crtc;
+ struct drm_device *dev = crtc->dev;
+ struct drm_plane *plane;
/* needs at least one primary plane to be enabled */
- if (!can_disable_primary_planes) {
- bool has_primary_plane = false;
- struct drm_plane *plane;
-
- drm_for_each_plane_mask(plane, dev, crtc_state->plane_mask) {
- struct drm_plane_state *plane_state;
-
- if (plane->type != DRM_PLANE_TYPE_PRIMARY)
- continue;
- plane_state = drm_atomic_get_plane_state(state, plane);
- if (IS_ERR(plane_state))
- return PTR_ERR(plane_state);
- if (plane_state->fb && plane_state->crtc) {
- has_primary_plane = true;
- break;
- }
- }
- if (!has_primary_plane) {
- drm_dbg_kms(dev, "Cannot enable CRTC without a primary plane.\n");
- return -EINVAL;
- }
+ drm_for_each_plane_mask(plane, dev, crtc_state->plane_mask) {
+ if (plane->type == DRM_PLANE_TYPE_PRIMARY)
+ return 0;
}
- return 0;
+ drm_dbg_atomic(dev, "[CRTC:%d:%s] primary plane missing\n", crtc->base.id, crtc->name);
+
+ return -EINVAL;
}
-EXPORT_SYMBOL(drm_atomic_helper_check_crtc_state);
+EXPORT_SYMBOL(drm_atomic_helper_check_crtc_primary_plane);
/**
* drm_atomic_helper_check_planes - validate state object for planes changes
@@ -2560,7 +2536,7 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev,
if (funcs->prepare_fb) {
ret = funcs->prepare_fb(plane, new_plane_state);
if (ret)
- goto fail;
+ goto fail_prepare_fb;
} else {
WARN_ON_ONCE(funcs->cleanup_fb);
@@ -2569,13 +2545,34 @@ int drm_atomic_helper_prepare_planes(struct drm_device *dev,
ret = drm_gem_plane_helper_prepare_fb(plane, new_plane_state);
if (ret)
- goto fail;
+ goto fail_prepare_fb;
+ }
+ }
+
+ for_each_new_plane_in_state(state, plane, new_plane_state, i) {
+ const struct drm_plane_helper_funcs *funcs = plane->helper_private;
+
+ if (funcs->begin_fb_access) {
+ ret = funcs->begin_fb_access(plane, new_plane_state);
+ if (ret)
+ goto fail_begin_fb_access;
}
}
return 0;
-fail:
+fail_begin_fb_access:
+ for_each_new_plane_in_state(state, plane, new_plane_state, j) {
+ const struct drm_plane_helper_funcs *funcs = plane->helper_private;
+
+ if (j >= i)
+ continue;
+
+ if (funcs->end_fb_access)
+ funcs->end_fb_access(plane, new_plane_state);
+ }
+ i = j; /* set i to upper limit to cleanup all planes */
+fail_prepare_fb:
for_each_new_plane_in_state(state, plane, new_plane_state, j) {
const struct drm_plane_helper_funcs *funcs;
@@ -2852,6 +2849,13 @@ void drm_atomic_helper_cleanup_planes(struct drm_device *dev,
int i;
for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, new_plane_state, i) {
+ const struct drm_plane_helper_funcs *funcs = plane->helper_private;
+
+ if (funcs->end_fb_access)
+ funcs->end_fb_access(plane, new_plane_state);
+ }
+
+ for_each_oldnew_plane_in_state(old_state, plane, old_plane_state, new_plane_state, i) {
const struct drm_plane_helper_funcs *funcs;
struct drm_plane_state *plane_state;
diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c
index bf31b9d92094..dfb57217253b 100644
--- a/drivers/gpu/drm/drm_atomic_state_helper.c
+++ b/drivers/gpu/drm/drm_atomic_state_helper.c
@@ -464,12 +464,12 @@ void drm_atomic_helper_connector_reset(struct drm_connector *connector)
EXPORT_SYMBOL(drm_atomic_helper_connector_reset);
/**
- * drm_atomic_helper_connector_tv_reset - Resets TV connector properties
+ * drm_atomic_helper_connector_tv_margins_reset - Resets TV connector properties
* @connector: DRM connector
*
* Resets the TV-related properties attached to a connector.
*/
-void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector)
+void drm_atomic_helper_connector_tv_margins_reset(struct drm_connector *connector)
{
struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
struct drm_connector_state *state = connector->state;
@@ -479,7 +479,7 @@ void drm_atomic_helper_connector_tv_reset(struct drm_connector *connector)
state->tv.margins.top = cmdline->tv_margins.top;
state->tv.margins.bottom = cmdline->tv_margins.bottom;
}
-EXPORT_SYMBOL(drm_atomic_helper_connector_tv_reset);
+EXPORT_SYMBOL(drm_atomic_helper_connector_tv_margins_reset);
/**
* __drm_atomic_helper_connector_duplicate_state - copy atomic connector state
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c
index 79730fa1dd8e..c06d0639d552 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -687,6 +687,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
*/
return -EINVAL;
} else if (property == config->tv_select_subconnector_property) {
+ state->tv.select_subconnector = val;
+ } else if (property == config->tv_subconnector_property) {
state->tv.subconnector = val;
} else if (property == config->tv_left_margin_property) {
state->tv.margins.left = val;
@@ -795,6 +797,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
else
*val = connector->dpms;
} else if (property == config->tv_select_subconnector_property) {
+ *val = state->tv.select_subconnector;
+ } else if (property == config->tv_subconnector_property) {
*val = state->tv.subconnector;
} else if (property == config->tv_left_margin_property) {
*val = state->tv.margins.left;
diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c
index 2b230b4d6942..fd67efe37c63 100644
--- a/drivers/gpu/drm/drm_client.c
+++ b/drivers/gpu/drm/drm_client.c
@@ -235,10 +235,10 @@ static void drm_client_buffer_delete(struct drm_client_buffer *buffer)
{
struct drm_device *dev = buffer->client->dev;
- drm_gem_vunmap(buffer->gem, &buffer->map);
-
- if (buffer->gem)
+ if (buffer->gem) {
+ drm_gem_vunmap_unlocked(buffer->gem, &buffer->map);
drm_gem_object_put(buffer->gem);
+ }
if (buffer->handle)
drm_mode_destroy_dumb(dev, buffer->handle, buffer->client->file);
@@ -323,7 +323,7 @@ drm_client_buffer_vmap(struct drm_client_buffer *buffer,
* fd_install step out of the driver backend hooks, to make that
* final step optional for internal users.
*/
- ret = drm_gem_vmap(buffer->gem, map);
+ ret = drm_gem_vmap_unlocked(buffer->gem, map);
if (ret)
return ret;
@@ -345,7 +345,7 @@ void drm_client_buffer_vunmap(struct drm_client_buffer *buffer)
{
struct iosys_map *map = &buffer->map;
- drm_gem_vunmap(buffer->gem, map);
+ drm_gem_vunmap_unlocked(buffer->gem, map);
}
EXPORT_SYMBOL(drm_client_buffer_vunmap);
diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c
index bbc535cc50dd..d553e793e673 100644
--- a/drivers/gpu/drm/drm_client_modeset.c
+++ b/drivers/gpu/drm/drm_client_modeset.c
@@ -1237,3 +1237,7 @@ int drm_client_modeset_dpms(struct drm_client_dev *client, int mode)
return ret;
}
EXPORT_SYMBOL(drm_client_modeset_dpms);
+
+#ifdef CONFIG_DRM_KUNIT_TEST
+#include "tests/drm_client_modeset_test.c"
+#endif
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 61c29ce74b03..547356e00341 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -274,6 +274,7 @@ static int __drm_connector_init(struct drm_device *dev,
INIT_LIST_HEAD(&connector->probed_modes);
INIT_LIST_HEAD(&connector->modes);
mutex_init(&connector->mutex);
+ mutex_init(&connector->edid_override_mutex);
connector->edid_blob_ptr = NULL;
connector->epoch_counter = 0;
connector->tile_blob_ptr = NULL;
@@ -582,6 +583,9 @@ void drm_connector_cleanup(struct drm_connector *connector)
mutex_destroy(&connector->mutex);
memset(connector, 0, sizeof(*connector));
+
+ if (dev->registered)
+ drm_sysfs_hotplug_event(dev);
}
EXPORT_SYMBOL(drm_connector_cleanup);
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 7d86020b5244..a209659a996c 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -43,7 +43,6 @@
#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
#include <drm/drm_encoder.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_print.h>
@@ -434,6 +433,32 @@ done:
}
EXPORT_SYMBOL(drm_crtc_helper_set_mode);
+/**
+ * drm_crtc_helper_atomic_check() - Helper to check CRTC atomic-state
+ * @crtc: CRTC to check
+ * @state: atomic state object
+ *
+ * Provides a default CRTC-state check handler for CRTCs that only have
+ * one primary plane attached to it.
+ *
+ * This is often the case for the CRTC of simple framebuffers. See also
+ * drm_plane_helper_atomic_check() for the respective plane-state check
+ * helper function.
+ *
+ * RETURNS:
+ * Zero on success, or an errno code otherwise.
+ */
+int drm_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state)
+{
+ struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+
+ if (!new_crtc_state->enable)
+ return 0;
+
+ return drm_atomic_helper_check_crtc_primary_plane(new_crtc_state);
+}
+EXPORT_SYMBOL(drm_crtc_helper_atomic_check);
+
static void
drm_crtc_helper_disable(struct drm_crtc *crtc)
{
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index 56041b604881..501a10edd0e1 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -56,9 +56,10 @@ struct drm_plane;
struct drm_plane_state;
struct drm_property;
struct edid;
+struct fwnode_handle;
struct kref;
+struct seq_file;
struct work_struct;
-struct fwnode_handle;
/* drm_crtc.c */
int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
@@ -286,5 +287,17 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
/* drm_edid.c */
void drm_mode_fixup_1366x768(struct drm_display_mode *mode);
+int drm_edid_override_show(struct drm_connector *connector, struct seq_file *m);
int drm_edid_override_set(struct drm_connector *connector, const void *edid, size_t size);
int drm_edid_override_reset(struct drm_connector *connector);
+
+/* drm_edid_load.c */
+#ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE
+const struct drm_edid *drm_edid_load_firmware(struct drm_connector *connector);
+#else
+static inline const struct drm_edid *
+drm_edid_load_firmware(struct drm_connector *connector)
+{
+ return ERR_PTR(-ENOENT);
+}
+#endif
diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c
index 01ee3febb813..ee445f4605ba 100644
--- a/drivers/gpu/drm/drm_debugfs.c
+++ b/drivers/gpu/drm/drm_debugfs.c
@@ -328,13 +328,7 @@ static ssize_t connector_write(struct file *file, const char __user *ubuf,
static int edid_show(struct seq_file *m, void *data)
{
- struct drm_connector *connector = m->private;
- struct drm_property_blob *edid = connector->edid_blob_ptr;
-
- if (connector->override_edid && edid)
- seq_write(m, edid->data, edid->length);
-
- return 0;
+ return drm_edid_override_show(m->private, m);
}
static int edid_open(struct inode *inode, struct file *file)
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 203bf8d6c34c..73b845a75d52 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -35,6 +35,7 @@
#include <linux/slab.h>
#include <linux/srcu.h>
+#include <drm/drm_accel.h>
#include <drm/drm_cache.h>
#include <drm/drm_client.h>
#include <drm/drm_color_mgmt.h>
@@ -90,6 +91,8 @@ static struct drm_minor **drm_minor_get_slot(struct drm_device *dev,
return &dev->primary;
case DRM_MINOR_RENDER:
return &dev->render;
+ case DRM_MINOR_ACCEL:
+ return &dev->accel;
default:
BUG();
}
@@ -104,9 +107,13 @@ static void drm_minor_alloc_release(struct drm_device *dev, void *data)
put_device(minor->kdev);
- spin_lock_irqsave(&drm_minor_lock, flags);
- idr_remove(&drm_minors_idr, minor->index);
- spin_unlock_irqrestore(&drm_minor_lock, flags);
+ if (minor->type == DRM_MINOR_ACCEL) {
+ accel_minor_remove(minor->index);
+ } else {
+ spin_lock_irqsave(&drm_minor_lock, flags);
+ idr_remove(&drm_minors_idr, minor->index);
+ spin_unlock_irqrestore(&drm_minor_lock, flags);
+ }
}
static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
@@ -123,13 +130,17 @@ static int drm_minor_alloc(struct drm_device *dev, unsigned int type)
minor->dev = dev;
idr_preload(GFP_KERNEL);
- spin_lock_irqsave(&drm_minor_lock, flags);
- r = idr_alloc(&drm_minors_idr,
- NULL,
- 64 * type,
- 64 * (type + 1),
- GFP_NOWAIT);
- spin_unlock_irqrestore(&drm_minor_lock, flags);
+ if (type == DRM_MINOR_ACCEL) {
+ r = accel_minor_alloc();
+ } else {
+ spin_lock_irqsave(&drm_minor_lock, flags);
+ r = idr_alloc(&drm_minors_idr,
+ NULL,
+ 64 * type,
+ 64 * (type + 1),
+ GFP_NOWAIT);
+ spin_unlock_irqrestore(&drm_minor_lock, flags);
+ }
idr_preload_end();
if (r < 0)
@@ -161,10 +172,14 @@ static int drm_minor_register(struct drm_device *dev, unsigned int type)
if (!minor)
return 0;
- ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root);
- if (ret) {
- DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
- goto err_debugfs;
+ if (minor->type == DRM_MINOR_ACCEL) {
+ accel_debugfs_init(minor, minor->index);
+ } else {
+ ret = drm_debugfs_init(minor, minor->index, drm_debugfs_root);
+ if (ret) {
+ DRM_ERROR("DRM: Failed to initialize /sys/kernel/debug/dri.\n");
+ goto err_debugfs;
+ }
}
ret = device_add(minor->kdev);
@@ -172,9 +187,13 @@ static int drm_minor_register(struct drm_device *dev, unsigned int type)
goto err_debugfs;
/* replace NULL with @minor so lookups will succeed from now on */
- spin_lock_irqsave(&drm_minor_lock, flags);
- idr_replace(&drm_minors_idr, minor, minor->index);
- spin_unlock_irqrestore(&drm_minor_lock, flags);
+ if (minor->type == DRM_MINOR_ACCEL) {
+ accel_minor_replace(minor, minor->index);
+ } else {
+ spin_lock_irqsave(&drm_minor_lock, flags);
+ idr_replace(&drm_minors_idr, minor, minor->index);
+ spin_unlock_irqrestore(&drm_minor_lock, flags);
+ }
DRM_DEBUG("new minor registered %d\n", minor->index);
return 0;
@@ -194,9 +213,13 @@ static void drm_minor_unregister(struct drm_device *dev, unsigned int type)
return;
/* replace @minor with NULL so lookups will fail from now on */
- spin_lock_irqsave(&drm_minor_lock, flags);
- idr_replace(&drm_minors_idr, NULL, minor->index);
- spin_unlock_irqrestore(&drm_minor_lock, flags);
+ if (minor->type == DRM_MINOR_ACCEL) {
+ accel_minor_replace(NULL, minor->index);
+ } else {
+ spin_lock_irqsave(&drm_minor_lock, flags);
+ idr_replace(&drm_minors_idr, NULL, minor->index);
+ spin_unlock_irqrestore(&drm_minor_lock, flags);
+ }
device_del(minor->kdev);
dev_set_drvdata(minor->kdev, NULL); /* safety belt */
@@ -603,6 +626,13 @@ static int drm_dev_init(struct drm_device *dev,
/* no per-device feature limits by default */
dev->driver_features = ~0u;
+ if (drm_core_check_feature(dev, DRIVER_COMPUTE_ACCEL) &&
+ (drm_core_check_feature(dev, DRIVER_RENDER) ||
+ drm_core_check_feature(dev, DRIVER_MODESET))) {
+ DRM_ERROR("DRM driver can't be both a compute acceleration and graphics driver\n");
+ return -EINVAL;
+ }
+
drm_legacy_init_members(dev);
INIT_LIST_HEAD(&dev->filelist);
INIT_LIST_HEAD(&dev->filelist_internal);
@@ -628,15 +658,21 @@ static int drm_dev_init(struct drm_device *dev,
dev->anon_inode = inode;
- if (drm_core_check_feature(dev, DRIVER_RENDER)) {
- ret = drm_minor_alloc(dev, DRM_MINOR_RENDER);
+ if (drm_core_check_feature(dev, DRIVER_COMPUTE_ACCEL)) {
+ ret = drm_minor_alloc(dev, DRM_MINOR_ACCEL);
if (ret)
goto err;
- }
+ } else {
+ if (drm_core_check_feature(dev, DRIVER_RENDER)) {
+ ret = drm_minor_alloc(dev, DRM_MINOR_RENDER);
+ if (ret)
+ goto err;
+ }
- ret = drm_minor_alloc(dev, DRM_MINOR_PRIMARY);
- if (ret)
- goto err;
+ ret = drm_minor_alloc(dev, DRM_MINOR_PRIMARY);
+ if (ret)
+ goto err;
+ }
ret = drm_legacy_create_map_hash(dev);
if (ret)
@@ -883,6 +919,10 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
if (ret)
goto err_minors;
+ ret = drm_minor_register(dev, DRM_MINOR_ACCEL);
+ if (ret)
+ goto err_minors;
+
ret = create_compat_control_link(dev);
if (ret)
goto err_minors;
@@ -902,12 +942,13 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
driver->name, driver->major, driver->minor,
driver->patchlevel, driver->date,
dev->dev ? dev_name(dev->dev) : "virtual device",
- dev->primary->index);
+ dev->primary ? dev->primary->index : dev->accel->index);
goto out_unlock;
err_minors:
remove_compat_control_link(dev);
+ drm_minor_unregister(dev, DRM_MINOR_ACCEL);
drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
drm_minor_unregister(dev, DRM_MINOR_RENDER);
out_unlock:
@@ -950,6 +991,7 @@ void drm_dev_unregister(struct drm_device *dev)
drm_legacy_rmmaps(dev);
remove_compat_control_link(dev);
+ drm_minor_unregister(dev, DRM_MINOR_ACCEL);
drm_minor_unregister(dev, DRM_MINOR_PRIMARY);
drm_minor_unregister(dev, DRM_MINOR_RENDER);
}
@@ -1034,6 +1076,7 @@ static const struct file_operations drm_stub_fops = {
static void drm_core_exit(void)
{
drm_privacy_screen_lookup_exit();
+ accel_core_exit();
unregister_chrdev(DRM_MAJOR, "drm");
debugfs_remove(drm_debugfs_root);
drm_sysfs_destroy();
@@ -1061,6 +1104,10 @@ static int __init drm_core_init(void)
if (ret < 0)
goto error;
+ ret = accel_core_init();
+ if (ret < 0)
+ goto error;
+
drm_privacy_screen_lookup_init();
drm_core_init_complete = true;
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 4005dab6147d..3841aba17abd 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -87,6 +87,8 @@ static int oui(u8 first, u8 second, u8 third)
#define EDID_QUIRK_FORCE_10BPC (1 << 11)
/* Non desktop display (i.e. HMD) */
#define EDID_QUIRK_NON_DESKTOP (1 << 12)
+/* Cap the DSC target bitrate to 15bpp */
+#define EDID_QUIRK_CAP_DSC_15BPP (1 << 13)
#define MICROSOFT_IEEE_OUI 0xca125c
@@ -147,6 +149,12 @@ static const struct edid_quirk {
EDID_QUIRK('F', 'C', 'M', 13600, EDID_QUIRK_PREFER_LARGE_75 |
EDID_QUIRK_DETAILED_IN_CM),
+ /* LG 27GP950 */
+ EDID_QUIRK('G', 'S', 'M', 0x5bbf, EDID_QUIRK_CAP_DSC_15BPP),
+
+ /* LG 27GN950 */
+ EDID_QUIRK('G', 'S', 'M', 0x5b9a, EDID_QUIRK_CAP_DSC_15BPP),
+
/* LGD panel of HP zBook 17 G2, eDP 10 bpc, but reports unknown bpc */
EDID_QUIRK('L', 'G', 'D', 764, EDID_QUIRK_FORCE_10BPC),
@@ -1572,15 +1580,6 @@ struct drm_edid {
const struct edid *edid;
};
-static bool version_greater(const struct drm_edid *drm_edid,
- u8 version, u8 revision)
-{
- const struct edid *edid = drm_edid->edid;
-
- return edid->version > version ||
- (edid->version == version && edid->revision > revision);
-}
-
static int edid_hfeeodb_extension_block_count(const struct edid *edid);
static int edid_hfeeodb_block_count(const struct edid *edid)
@@ -1622,7 +1621,8 @@ static const void *edid_extension_block_data(const struct edid *edid, int index)
return edid_block_data(edid, index + 1);
}
-static int drm_edid_block_count(const struct drm_edid *drm_edid)
+/* EDID block count indicated in EDID, may exceed allocated size */
+static int __drm_edid_block_count(const struct drm_edid *drm_edid)
{
int num_blocks;
@@ -1642,12 +1642,18 @@ static int drm_edid_block_count(const struct drm_edid *drm_edid)
num_blocks = eeodb;
}
- /* Limit by allocated size */
- num_blocks = min(num_blocks, (int)drm_edid->size / EDID_LENGTH);
-
return num_blocks;
}
+/* EDID block count, limited by allocated size */
+static int drm_edid_block_count(const struct drm_edid *drm_edid)
+{
+ /* Limit by allocated size */
+ return min(__drm_edid_block_count(drm_edid),
+ (int)drm_edid->size / EDID_LENGTH);
+}
+
+/* EDID extension block count, limited by allocated size */
static int drm_edid_extension_block_count(const struct drm_edid *drm_edid)
{
return drm_edid_block_count(drm_edid) - 1;
@@ -1981,7 +1987,7 @@ bool drm_edid_block_valid(u8 *_block, int block_num, bool print_bad_edid,
status = edid_block_check(block, is_base_block);
if (status == EDID_BLOCK_HEADER_REPAIR) {
- DRM_DEBUG("Fixing EDID header, your hardware may be failing\n");
+ DRM_DEBUG_KMS("Fixing EDID header, your hardware may be failing\n");
edid_header_fix(block);
/* Retry with fixed header, update status if that worked. */
@@ -2042,6 +2048,36 @@ bool drm_edid_is_valid(struct edid *edid)
}
EXPORT_SYMBOL(drm_edid_is_valid);
+/**
+ * drm_edid_valid - sanity check EDID data
+ * @drm_edid: EDID data
+ *
+ * Sanity check an EDID. Cross check block count against allocated size and
+ * checksum the blocks.
+ *
+ * Return: True if the EDID data is valid, false otherwise.
+ */
+bool drm_edid_valid(const struct drm_edid *drm_edid)
+{
+ int i;
+
+ if (!drm_edid)
+ return false;
+
+ if (edid_size_by_blocks(__drm_edid_block_count(drm_edid)) != drm_edid->size)
+ return false;
+
+ for (i = 0; i < drm_edid_block_count(drm_edid); i++) {
+ const void *block = drm_edid_block_data(drm_edid, i);
+
+ if (!edid_block_valid(block, i == 0))
+ return false;
+ }
+
+ return true;
+}
+EXPORT_SYMBOL(drm_edid_valid);
+
static struct edid *edid_filter_invalid_blocks(struct edid *edid,
size_t *alloc_size)
{
@@ -2168,58 +2204,91 @@ static void connector_bad_edid(struct drm_connector *connector,
if (connector->bad_edid_counter++ && !drm_debug_enabled(DRM_UT_KMS))
return;
- drm_dbg_kms(connector->dev, "%s: EDID is invalid:\n", connector->name);
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] EDID is invalid:\n",
+ connector->base.id, connector->name);
for (i = 0; i < num_blocks; i++)
edid_block_dump(KERN_DEBUG, edid + i, i);
}
/* Get override or firmware EDID */
-static struct edid *drm_get_override_edid(struct drm_connector *connector,
- size_t *alloc_size)
+static const struct drm_edid *drm_edid_override_get(struct drm_connector *connector)
{
- struct edid *override = NULL;
+ const struct drm_edid *override = NULL;
- if (connector->override_edid)
- override = drm_edid_duplicate(connector->edid_blob_ptr->data);
+ mutex_lock(&connector->edid_override_mutex);
- if (!override)
- override = drm_load_edid_firmware(connector);
+ if (connector->edid_override)
+ override = drm_edid_dup(connector->edid_override);
- /* FIXME: Get alloc size from deeper down the stack */
- if (!IS_ERR_OR_NULL(override) && alloc_size)
- *alloc_size = edid_size(override);
+ mutex_unlock(&connector->edid_override_mutex);
+
+ if (!override)
+ override = drm_edid_load_firmware(connector);
return IS_ERR(override) ? NULL : override;
}
/* For debugfs edid_override implementation */
+int drm_edid_override_show(struct drm_connector *connector, struct seq_file *m)
+{
+ const struct drm_edid *drm_edid;
+
+ mutex_lock(&connector->edid_override_mutex);
+
+ drm_edid = connector->edid_override;
+ if (drm_edid)
+ seq_write(m, drm_edid->edid, drm_edid->size);
+
+ mutex_unlock(&connector->edid_override_mutex);
+
+ return 0;
+}
+
+/* For debugfs edid_override implementation */
int drm_edid_override_set(struct drm_connector *connector, const void *edid,
size_t size)
{
- int ret;
+ const struct drm_edid *drm_edid;
- if (size < EDID_LENGTH || edid_size(edid) > size)
+ drm_edid = drm_edid_alloc(edid, size);
+ if (!drm_edid_valid(drm_edid)) {
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] EDID override invalid\n",
+ connector->base.id, connector->name);
+ drm_edid_free(drm_edid);
return -EINVAL;
+ }
- connector->override_edid = false;
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] EDID override set\n",
+ connector->base.id, connector->name);
- ret = drm_connector_update_edid_property(connector, edid);
- if (!ret)
- connector->override_edid = true;
+ mutex_lock(&connector->edid_override_mutex);
- return ret;
+ drm_edid_free(connector->edid_override);
+ connector->edid_override = drm_edid;
+
+ mutex_unlock(&connector->edid_override_mutex);
+
+ return 0;
}
/* For debugfs edid_override implementation */
int drm_edid_override_reset(struct drm_connector *connector)
{
- connector->override_edid = false;
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] EDID override reset\n",
+ connector->base.id, connector->name);
+
+ mutex_lock(&connector->edid_override_mutex);
- return drm_connector_update_edid_property(connector, NULL);
+ drm_edid_free(connector->edid_override);
+ connector->edid_override = NULL;
+
+ mutex_unlock(&connector->edid_override_mutex);
+
+ return 0;
}
/**
- * drm_add_override_edid_modes - add modes from override/firmware EDID
+ * drm_edid_override_connector_update - add modes from override/firmware EDID
* @connector: connector we're probing
*
* Add modes from the override/firmware EDID, if available. Only to be used from
@@ -2229,24 +2298,25 @@ int drm_edid_override_reset(struct drm_connector *connector)
*
* Return: The number of modes added or 0 if we couldn't find any.
*/
-int drm_add_override_edid_modes(struct drm_connector *connector)
+int drm_edid_override_connector_update(struct drm_connector *connector)
{
- struct edid *override;
+ const struct drm_edid *override;
int num_modes = 0;
- override = drm_get_override_edid(connector, NULL);
+ override = drm_edid_override_get(connector);
if (override) {
- drm_connector_update_edid_property(connector, override);
- num_modes = drm_add_edid_modes(connector, override);
- kfree(override);
+ num_modes = drm_edid_connector_update(connector, override);
- DRM_DEBUG_KMS("[CONNECTOR:%d:%s] adding %d modes via fallback override/firmware EDID\n",
- connector->base.id, connector->name, num_modes);
+ drm_edid_free(override);
+
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] adding %d modes via fallback override/firmware EDID\n",
+ connector->base.id, connector->name, num_modes);
}
return num_modes;
}
-EXPORT_SYMBOL(drm_add_override_edid_modes);
+EXPORT_SYMBOL(drm_edid_override_connector_update);
typedef int read_block_fn(void *context, u8 *buf, unsigned int block, size_t len);
@@ -2289,12 +2359,19 @@ static struct edid *_drm_do_get_edid(struct drm_connector *connector,
{
enum edid_block_status status;
int i, num_blocks, invalid_blocks = 0;
+ const struct drm_edid *override;
struct edid *edid, *new;
size_t alloc_size = EDID_LENGTH;
- edid = drm_get_override_edid(connector, &alloc_size);
- if (edid)
+ override = drm_edid_override_get(connector);
+ if (override) {
+ alloc_size = override->size;
+ edid = kmemdup(override->edid, alloc_size, GFP_KERNEL);
+ drm_edid_free(override);
+ if (!edid)
+ return NULL;
goto ok;
+ }
edid = kmalloc(alloc_size, GFP_KERNEL);
if (!edid)
@@ -2397,7 +2474,7 @@ fail:
* adapter and use drm_get_edid() instead of abusing this function.
*
* The EDID may be overridden using debugfs override_edid or firmware EDID
- * (drm_load_edid_firmware() and drm.edid_firmware parameter), in this priority
+ * (drm_edid_load_firmware() and drm.edid_firmware parameter), in this priority
* order. Having either of them bypasses actual EDID reads.
*
* Return: Pointer to valid EDID or NULL if we couldn't find any.
@@ -2575,7 +2652,7 @@ EXPORT_SYMBOL(drm_get_edid);
* this function.
*
* The EDID may be overridden using debugfs override_edid or firmware EDID
- * (drm_load_edid_firmware() and drm.edid_firmware parameter), in this priority
+ * (drm_edid_load_firmware() and drm.edid_firmware parameter), in this priority
* order. Having either of them bypasses actual EDID reads.
*
* The returned pointer must be freed using drm_edid_free().
@@ -2613,7 +2690,7 @@ EXPORT_SYMBOL(drm_edid_read_custom);
* Read EDID using the given I2C adapter.
*
* The EDID may be overridden using debugfs override_edid or firmware EDID
- * (drm_load_edid_firmware() and drm.edid_firmware parameter), in this priority
+ * (drm_edid_load_firmware() and drm.edid_firmware parameter), in this priority
* order. Having either of them bypasses actual EDID reads.
*
* Prefer initializing connector->ddc with drm_connector_init_with_ddc() and
@@ -2649,7 +2726,7 @@ EXPORT_SYMBOL(drm_edid_read_ddc);
* Read EDID using the connector's I2C adapter.
*
* The EDID may be overridden using debugfs override_edid or firmware EDID
- * (drm_load_edid_firmware() and drm.edid_firmware parameter), in this priority
+ * (drm_edid_load_firmware() and drm.edid_firmware parameter), in this priority
* order. Having either of them bypasses actual EDID reads.
*
* The returned pointer must be freed using drm_edid_free().
@@ -2730,6 +2807,8 @@ u32 drm_edid_get_panel_id(struct i2c_adapter *adapter)
if (edid_block_status_valid(status, edid_block_tag(base_block)))
panel_id = edid_extract_panel_id(base_block);
+ else
+ edid_block_dump(KERN_NOTICE, base_block, 0);
kfree(base_block);
@@ -2984,7 +3063,7 @@ is_rb(const struct detailed_timing *descriptor, void *data)
BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.cvt.flags) != 15);
if (descriptor->data.other_data.data.range.flags == DRM_EDID_CVT_SUPPORT_FLAG &&
- descriptor->data.other_data.data.range.formula.cvt.flags & 0x10)
+ descriptor->data.other_data.data.range.formula.cvt.flags & DRM_EDID_CVT_FLAGS_REDUCED_BLANKING)
*res = true;
}
@@ -3012,7 +3091,7 @@ find_gtf2(const struct detailed_timing *descriptor, void *data)
BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.flags) != 10);
- if (descriptor->data.other_data.data.range.flags == 0x02)
+ if (descriptor->data.other_data.data.range.flags == DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG)
*res = descriptor;
}
@@ -3077,20 +3156,53 @@ drm_gtf2_2j(const struct drm_edid *drm_edid)
return descriptor ? descriptor->data.other_data.data.range.formula.gtf2.j : 0;
}
+static void
+get_timing_level(const struct detailed_timing *descriptor, void *data)
+{
+ int *res = data;
+
+ if (!is_display_descriptor(descriptor, EDID_DETAIL_MONITOR_RANGE))
+ return;
+
+ BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.flags) != 10);
+
+ switch (descriptor->data.other_data.data.range.flags) {
+ case DRM_EDID_DEFAULT_GTF_SUPPORT_FLAG:
+ *res = LEVEL_GTF;
+ break;
+ case DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG:
+ *res = LEVEL_GTF2;
+ break;
+ case DRM_EDID_CVT_SUPPORT_FLAG:
+ *res = LEVEL_CVT;
+ break;
+ default:
+ break;
+ }
+}
+
/* Get standard timing level (CVT/GTF/DMT). */
static int standard_timing_level(const struct drm_edid *drm_edid)
{
const struct edid *edid = drm_edid->edid;
- if (edid->revision >= 2) {
- if (edid->revision >= 4 && (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF))
- return LEVEL_CVT;
- if (drm_gtf2_hbreak(drm_edid))
- return LEVEL_GTF2;
- if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)
- return LEVEL_GTF;
+ if (edid->revision >= 4) {
+ /*
+ * If the range descriptor doesn't
+ * indicate otherwise default to CVT
+ */
+ int ret = LEVEL_CVT;
+
+ drm_for_each_detailed_block(drm_edid, get_timing_level, &ret);
+
+ return ret;
+ } else if (edid->revision >= 3 && drm_gtf2_hbreak(drm_edid)) {
+ return LEVEL_GTF2;
+ } else if (edid->revision >= 2) {
+ return LEVEL_GTF;
+ } else {
+ return LEVEL_DMT;
}
- return LEVEL_DMT;
}
/*
@@ -3113,6 +3225,35 @@ static int drm_mode_hsync(const struct drm_display_mode *mode)
return DIV_ROUND_CLOSEST(mode->clock, mode->htotal);
}
+static struct drm_display_mode *
+drm_gtf2_mode(struct drm_device *dev,
+ const struct drm_edid *drm_edid,
+ int hsize, int vsize, int vrefresh_rate)
+{
+ struct drm_display_mode *mode;
+
+ /*
+ * This is potentially wrong if there's ever a monitor with
+ * more than one ranges section, each claiming a different
+ * secondary GTF curve. Please don't do that.
+ */
+ mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
+ if (!mode)
+ return NULL;
+
+ if (drm_mode_hsync(mode) > drm_gtf2_hbreak(drm_edid)) {
+ drm_mode_destroy(dev, mode);
+ mode = drm_gtf_mode_complex(dev, hsize, vsize,
+ vrefresh_rate, 0, 0,
+ drm_gtf2_m(drm_edid),
+ drm_gtf2_2c(drm_edid),
+ drm_gtf2_k(drm_edid),
+ drm_gtf2_2j(drm_edid));
+ }
+
+ return mode;
+}
+
/*
* Take the standard timing params (in this case width, aspect, and refresh)
* and convert them into a real mode using CVT/GTF/DMT.
@@ -3201,23 +3342,7 @@ static struct drm_display_mode *drm_mode_std(struct drm_connector *connector,
mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
break;
case LEVEL_GTF2:
- /*
- * This is potentially wrong if there's ever a monitor with
- * more than one ranges section, each claiming a different
- * secondary GTF curve. Please don't do that.
- */
- mode = drm_gtf_mode(dev, hsize, vsize, vrefresh_rate, 0, 0);
- if (!mode)
- return NULL;
- if (drm_mode_hsync(mode) > drm_gtf2_hbreak(drm_edid)) {
- drm_mode_destroy(dev, mode);
- mode = drm_gtf_mode_complex(dev, hsize, vsize,
- vrefresh_rate, 0, 0,
- drm_gtf2_m(drm_edid),
- drm_gtf2_2c(drm_edid),
- drm_gtf2_k(drm_edid),
- drm_gtf2_2j(drm_edid));
- }
+ mode = drm_gtf2_mode(dev, drm_edid, hsize, vsize, vrefresh_rate);
break;
case LEVEL_CVT:
mode = drm_cvt_mode(dev, hsize, vsize, vrefresh_rate, 0, 0,
@@ -3274,11 +3399,12 @@ drm_mode_do_interlace_quirk(struct drm_display_mode *mode,
* timing block contains enough info for us to create and return a new struct
* drm_display_mode.
*/
-static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
+static struct drm_display_mode *drm_mode_detailed(struct drm_connector *connector,
const struct drm_edid *drm_edid,
const struct detailed_timing *timing,
u32 quirks)
{
+ struct drm_device *dev = connector->dev;
struct drm_display_mode *mode;
const struct detailed_pixel_timing *pt = &timing->data.pixel_data;
unsigned hactive = (pt->hactive_hblank_hi & 0xf0) << 4 | pt->hactive_lo;
@@ -3295,17 +3421,19 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
return NULL;
if (pt->misc & DRM_EDID_PT_STEREO) {
- DRM_DEBUG_KMS("stereo mode not supported\n");
+ drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Stereo mode not supported\n",
+ connector->base.id, connector->name);
return NULL;
}
if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
- DRM_DEBUG_KMS("composite sync not supported\n");
+ 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) {
- DRM_DEBUG_KMS("Incorrect Detailed timing. "
- "Wrong Hsync/Vsync pulse width\n");
+ drm_dbg_kms(dev, "[CONNECTOR:%d:%s] Incorrect Detailed timing. Wrong Hsync/Vsync pulse width\n",
+ connector->base.id, connector->name);
return NULL;
}
@@ -3415,7 +3543,7 @@ range_pixel_clock(const struct edid *edid, const u8 *t)
return 0;
/* 1.4 with CVT support gives us real precision, yay */
- if (edid->revision >= 4 && t[10] == 0x04)
+ if (edid->revision >= 4 && t[10] == DRM_EDID_CVT_SUPPORT_FLAG)
return (t[9] * 10000) - ((t[12] >> 2) * 250);
/* 1.3 is pathetic, so fuzz up a bit */
@@ -3441,7 +3569,7 @@ static bool mode_in_range(const struct drm_display_mode *mode,
return false;
/* 1.4 max horizontal check */
- if (edid->revision >= 4 && t[10] == 0x04)
+ if (edid->revision >= 4 && t[10] == DRM_EDID_CVT_SUPPORT_FLAG)
if (t[13] && mode->hdisplay > 8 * (t[13] + (256 * (t[12]&0x3))))
return false;
@@ -3533,6 +3661,35 @@ static int drm_gtf_modes_for_range(struct drm_connector *connector,
return modes;
}
+static int drm_gtf2_modes_for_range(struct drm_connector *connector,
+ const struct drm_edid *drm_edid,
+ const struct detailed_timing *timing)
+{
+ int i, modes = 0;
+ struct drm_display_mode *newmode;
+ struct drm_device *dev = connector->dev;
+
+ for (i = 0; i < ARRAY_SIZE(extra_modes); i++) {
+ const struct minimode *m = &extra_modes[i];
+
+ newmode = drm_gtf2_mode(dev, drm_edid, m->w, m->h, m->r);
+ if (!newmode)
+ return modes;
+
+ drm_mode_fixup_1366x768(newmode);
+ if (!mode_in_range(newmode, drm_edid, timing) ||
+ !valid_inferred_mode(connector, newmode)) {
+ drm_mode_destroy(dev, newmode);
+ continue;
+ }
+
+ drm_mode_probed_add(connector, newmode);
+ modes++;
+ }
+
+ return modes;
+}
+
static int drm_cvt_modes_for_range(struct drm_connector *connector,
const struct drm_edid *drm_edid,
const struct detailed_timing *timing)
@@ -3577,25 +3734,29 @@ do_inferred_modes(const struct detailed_timing *timing, void *c)
closure->drm_edid,
timing);
- if (!version_greater(closure->drm_edid, 1, 1))
+ if (closure->drm_edid->edid->revision < 2)
return; /* GTF not defined yet */
switch (range->flags) {
- case 0x02: /* secondary gtf, XXX could do more */
- case 0x00: /* default gtf */
+ case DRM_EDID_SECONDARY_GTF_SUPPORT_FLAG:
+ closure->modes += drm_gtf2_modes_for_range(closure->connector,
+ closure->drm_edid,
+ timing);
+ break;
+ case DRM_EDID_DEFAULT_GTF_SUPPORT_FLAG:
closure->modes += drm_gtf_modes_for_range(closure->connector,
closure->drm_edid,
timing);
break;
- case 0x04: /* cvt, only in 1.4+ */
- if (!version_greater(closure->drm_edid, 1, 3))
+ case DRM_EDID_CVT_SUPPORT_FLAG:
+ if (closure->drm_edid->edid->revision < 4)
break;
closure->modes += drm_cvt_modes_for_range(closure->connector,
closure->drm_edid,
timing);
break;
- case 0x01: /* just the ranges, no formula */
+ case DRM_EDID_RANGE_LIMITS_ONLY_FLAG:
default:
break;
}
@@ -3609,7 +3770,7 @@ static int add_inferred_modes(struct drm_connector *connector,
.drm_edid = drm_edid,
};
- if (version_greater(drm_edid, 1, 0))
+ if (drm_edid->edid->revision >= 1)
drm_for_each_detailed_block(drm_edid, do_inferred_modes, &closure);
return closure.modes;
@@ -3686,7 +3847,7 @@ static int add_established_modes(struct drm_connector *connector,
}
}
- if (version_greater(drm_edid, 1, 0))
+ if (edid->revision >= 1)
drm_for_each_detailed_block(drm_edid, do_established_modes,
&closure);
@@ -3741,7 +3902,7 @@ static int add_standard_modes(struct drm_connector *connector,
}
}
- if (version_greater(drm_edid, 1, 0))
+ if (drm_edid->edid->revision >= 1)
drm_for_each_detailed_block(drm_edid, do_standard_modes,
&closure);
@@ -3821,7 +3982,7 @@ add_cvt_modes(struct drm_connector *connector, const struct drm_edid *drm_edid)
.drm_edid = drm_edid,
};
- if (version_greater(drm_edid, 1, 2))
+ if (drm_edid->edid->revision >= 3)
drm_for_each_detailed_block(drm_edid, do_cvt_mode, &closure);
/* XXX should also look for CVT codes in VTB blocks */
@@ -3829,7 +3990,8 @@ add_cvt_modes(struct drm_connector *connector, const struct drm_edid *drm_edid)
return closure.modes;
}
-static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode);
+static void fixup_detailed_cea_mode_clock(struct drm_connector *connector,
+ struct drm_display_mode *mode);
static void
do_detailed_mode(const struct detailed_timing *timing, void *c)
@@ -3840,7 +4002,7 @@ do_detailed_mode(const struct detailed_timing *timing, void *c)
if (!is_detailed_timing_descriptor(timing))
return;
- newmode = drm_mode_detailed(closure->connector->dev,
+ newmode = drm_mode_detailed(closure->connector,
closure->drm_edid, timing,
closure->quirks);
if (!newmode)
@@ -3854,7 +4016,7 @@ do_detailed_mode(const struct detailed_timing *timing, void *c)
* so fix up anything that looks like CEA/HDMI mode, but the clock
* is just slightly off.
*/
- fixup_detailed_cea_mode_clock(newmode);
+ fixup_detailed_cea_mode_clock(closure->connector, newmode);
drm_mode_probed_add(closure->connector, newmode);
closure->modes++;
@@ -3873,13 +4035,14 @@ static int add_detailed_modes(struct drm_connector *connector,
struct detailed_mode_closure closure = {
.connector = connector,
.drm_edid = drm_edid,
- .preferred = true,
.quirks = quirks,
};
- if (closure.preferred && !version_greater(drm_edid, 1, 3))
+ if (drm_edid->edid->revision >= 4)
+ closure.preferred = true; /* first detailed timing is always preferred */
+ else
closure.preferred =
- (drm_edid->edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING);
+ drm_edid->edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING;
drm_for_each_detailed_block(drm_edid, do_detailed_mode, &closure);
@@ -4515,7 +4678,8 @@ static int add_hdmi_mode(struct drm_connector *connector, u8 vic)
struct drm_display_mode *newmode;
if (!drm_valid_hdmi_vic(vic)) {
- DRM_ERROR("Unknown HDMI VIC: %d\n", vic);
+ drm_err(connector->dev, "[CONNECTOR:%d:%s] Unknown HDMI VIC: %d\n",
+ connector->base.id, connector->name, vic);
return 0;
}
@@ -5122,7 +5286,8 @@ static int add_cea_modes(struct drm_connector *connector,
return modes;
}
-static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode)
+static void fixup_detailed_cea_mode_clock(struct drm_connector *connector,
+ struct drm_display_mode *mode)
{
const struct drm_display_mode *cea_mode;
int clock1, clock2, clock;
@@ -5160,8 +5325,10 @@ static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode)
if (mode->clock == clock)
return;
- DRM_DEBUG("detailed mode matches %s VIC %d, adjusting clock %d -> %d\n",
- type, vic, mode->clock, clock);
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] detailed mode matches %s VIC %d, adjusting clock %d -> %d\n",
+ connector->base.id, connector->name,
+ type, vic, mode->clock, clock);
mode->clock = clock;
}
@@ -5269,15 +5436,12 @@ drm_parse_hdmi_vsdb_audio(struct drm_connector *connector, const u8 *db)
if (len >= 12)
connector->audio_latency[1] = db[12];
- DRM_DEBUG_KMS("HDMI: latency present %d %d, "
- "video latency %d %d, "
- "audio latency %d %d\n",
- connector->latency_present[0],
- connector->latency_present[1],
- connector->video_latency[0],
- connector->video_latency[1],
- connector->audio_latency[0],
- connector->audio_latency[1]);
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] HDMI: latency present %d %d, video latency %d %d, audio latency %d %d\n",
+ connector->base.id, connector->name,
+ connector->latency_present[0], connector->latency_present[1],
+ connector->video_latency[0], connector->video_latency[1],
+ connector->audio_latency[0], connector->audio_latency[1]);
}
static void
@@ -5375,7 +5539,9 @@ static void drm_edid_to_eld(struct drm_connector *connector,
return;
mnl = get_monitor_name(drm_edid, &eld[DRM_ELD_MONITOR_NAME_STRING]);
- DRM_DEBUG_KMS("ELD monitor %s\n", &eld[DRM_ELD_MONITOR_NAME_STRING]);
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] ELD monitor %s\n",
+ connector->base.id, connector->name,
+ &eld[DRM_ELD_MONITOR_NAME_STRING]);
eld[DRM_ELD_CEA_EDID_VER_MNL] = info->cea_rev << DRM_ELD_CEA_EDID_VER_SHIFT;
eld[DRM_ELD_CEA_EDID_VER_MNL] |= mnl;
@@ -5429,8 +5595,9 @@ static void drm_edid_to_eld(struct drm_connector *connector,
eld[DRM_ELD_BASELINE_ELD_LEN] =
DIV_ROUND_UP(drm_eld_calc_baseline_block_size(eld), 4);
- DRM_DEBUG_KMS("ELD size %d, SAD count %d\n",
- drm_eld_size(eld), total_sad_count);
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] ELD size %d, SAD count %d\n",
+ connector->base.id, connector->name,
+ drm_eld_size(eld), total_sad_count);
}
static int _drm_edid_to_sad(const struct drm_edid *drm_edid,
@@ -5701,7 +5868,8 @@ static void drm_parse_vcdb(struct drm_connector *connector, const u8 *db)
{
struct drm_display_info *info = &connector->display_info;
- DRM_DEBUG_KMS("CEA VCDB 0x%02x\n", db[2]);
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] CEA VCDB 0x%02x\n",
+ connector->base.id, connector->name, db[2]);
if (db[2] & EDID_CEA_VCDB_QS)
info->rgb_quant_range_selectable = true;
@@ -5752,12 +5920,87 @@ static void drm_parse_ycbcr420_deep_color_info(struct drm_connector *connector,
hdmi->y420_dc_modes = dc_mask;
}
+static void drm_parse_dsc_info(struct drm_hdmi_dsc_cap *hdmi_dsc,
+ const u8 *hf_scds)
+{
+ hdmi_dsc->v_1p2 = hf_scds[11] & DRM_EDID_DSC_1P2;
+
+ if (!hdmi_dsc->v_1p2)
+ return;
+
+ hdmi_dsc->native_420 = hf_scds[11] & DRM_EDID_DSC_NATIVE_420;
+ hdmi_dsc->all_bpp = hf_scds[11] & DRM_EDID_DSC_ALL_BPP;
+
+ if (hf_scds[11] & DRM_EDID_DSC_16BPC)
+ hdmi_dsc->bpc_supported = 16;
+ else if (hf_scds[11] & DRM_EDID_DSC_12BPC)
+ hdmi_dsc->bpc_supported = 12;
+ else if (hf_scds[11] & DRM_EDID_DSC_10BPC)
+ hdmi_dsc->bpc_supported = 10;
+ else
+ /* Supports min 8 BPC if DSC 1.2 is supported*/
+ hdmi_dsc->bpc_supported = 8;
+
+ if (cea_db_payload_len(hf_scds) >= 12 && hf_scds[12]) {
+ u8 dsc_max_slices;
+ u8 dsc_max_frl_rate;
+
+ dsc_max_frl_rate = (hf_scds[12] & DRM_EDID_DSC_MAX_FRL_RATE_MASK) >> 4;
+ drm_get_max_frl_rate(dsc_max_frl_rate, &hdmi_dsc->max_lanes,
+ &hdmi_dsc->max_frl_rate_per_lane);
+
+ dsc_max_slices = hf_scds[12] & DRM_EDID_DSC_MAX_SLICES;
+
+ switch (dsc_max_slices) {
+ case 1:
+ hdmi_dsc->max_slices = 1;
+ hdmi_dsc->clk_per_slice = 340;
+ break;
+ case 2:
+ hdmi_dsc->max_slices = 2;
+ hdmi_dsc->clk_per_slice = 340;
+ break;
+ case 3:
+ hdmi_dsc->max_slices = 4;
+ hdmi_dsc->clk_per_slice = 340;
+ break;
+ case 4:
+ hdmi_dsc->max_slices = 8;
+ hdmi_dsc->clk_per_slice = 340;
+ break;
+ case 5:
+ hdmi_dsc->max_slices = 8;
+ hdmi_dsc->clk_per_slice = 400;
+ break;
+ case 6:
+ hdmi_dsc->max_slices = 12;
+ hdmi_dsc->clk_per_slice = 400;
+ break;
+ case 7:
+ hdmi_dsc->max_slices = 16;
+ hdmi_dsc->clk_per_slice = 400;
+ break;
+ case 0:
+ default:
+ hdmi_dsc->max_slices = 0;
+ hdmi_dsc->clk_per_slice = 0;
+ }
+ }
+
+ if (cea_db_payload_len(hf_scds) >= 13 && hf_scds[13])
+ hdmi_dsc->total_chunk_kbytes = hf_scds[13] & DRM_EDID_DSC_TOTAL_CHUNK_KBYTES;
+}
+
/* Sink Capability Data Structure */
static void drm_parse_hdmi_forum_scds(struct drm_connector *connector,
const u8 *hf_scds)
{
struct drm_display_info *display = &connector->display_info;
struct drm_hdmi_info *hdmi = &display->hdmi;
+ struct drm_hdmi_dsc_cap *hdmi_dsc = &hdmi->dsc_cap;
+ int max_tmds_clock = 0;
+ u8 max_frl_rate = 0;
+ bool dsc_support = false;
display->has_hdmi_infoframe = true;
@@ -5777,14 +6020,13 @@ static void drm_parse_hdmi_forum_scds(struct drm_connector *connector,
*/
if (hf_scds[5]) {
- /* max clock is 5000 KHz times block value */
- u32 max_tmds_clock = hf_scds[5] * 5000;
struct drm_scdc *scdc = &hdmi->scdc;
+ /* max clock is 5000 KHz times block value */
+ max_tmds_clock = hf_scds[5] * 5000;
+
if (max_tmds_clock > 340000) {
display->max_tmds_clock = max_tmds_clock;
- DRM_DEBUG_KMS("HF-VSDB: max TMDS clock %d kHz\n",
- display->max_tmds_clock);
}
if (scdc->supported) {
@@ -5797,74 +6039,22 @@ static void drm_parse_hdmi_forum_scds(struct drm_connector *connector,
}
if (hf_scds[7]) {
- u8 max_frl_rate;
- u8 dsc_max_frl_rate;
- u8 dsc_max_slices;
- struct drm_hdmi_dsc_cap *hdmi_dsc = &hdmi->dsc_cap;
-
- DRM_DEBUG_KMS("hdmi_21 sink detected. parsing edid\n");
max_frl_rate = (hf_scds[7] & DRM_EDID_MAX_FRL_RATE_MASK) >> 4;
drm_get_max_frl_rate(max_frl_rate, &hdmi->max_lanes,
&hdmi->max_frl_rate_per_lane);
- hdmi_dsc->v_1p2 = hf_scds[11] & DRM_EDID_DSC_1P2;
-
- if (hdmi_dsc->v_1p2) {
- hdmi_dsc->native_420 = hf_scds[11] & DRM_EDID_DSC_NATIVE_420;
- hdmi_dsc->all_bpp = hf_scds[11] & DRM_EDID_DSC_ALL_BPP;
-
- if (hf_scds[11] & DRM_EDID_DSC_16BPC)
- hdmi_dsc->bpc_supported = 16;
- else if (hf_scds[11] & DRM_EDID_DSC_12BPC)
- hdmi_dsc->bpc_supported = 12;
- else if (hf_scds[11] & DRM_EDID_DSC_10BPC)
- hdmi_dsc->bpc_supported = 10;
- else
- hdmi_dsc->bpc_supported = 0;
-
- dsc_max_frl_rate = (hf_scds[12] & DRM_EDID_DSC_MAX_FRL_RATE_MASK) >> 4;
- drm_get_max_frl_rate(dsc_max_frl_rate, &hdmi_dsc->max_lanes,
- &hdmi_dsc->max_frl_rate_per_lane);
- hdmi_dsc->total_chunk_kbytes = hf_scds[13] & DRM_EDID_DSC_TOTAL_CHUNK_KBYTES;
-
- dsc_max_slices = hf_scds[12] & DRM_EDID_DSC_MAX_SLICES;
- switch (dsc_max_slices) {
- case 1:
- hdmi_dsc->max_slices = 1;
- hdmi_dsc->clk_per_slice = 340;
- break;
- case 2:
- hdmi_dsc->max_slices = 2;
- hdmi_dsc->clk_per_slice = 340;
- break;
- case 3:
- hdmi_dsc->max_slices = 4;
- hdmi_dsc->clk_per_slice = 340;
- break;
- case 4:
- hdmi_dsc->max_slices = 8;
- hdmi_dsc->clk_per_slice = 340;
- break;
- case 5:
- hdmi_dsc->max_slices = 8;
- hdmi_dsc->clk_per_slice = 400;
- break;
- case 6:
- hdmi_dsc->max_slices = 12;
- hdmi_dsc->clk_per_slice = 400;
- break;
- case 7:
- hdmi_dsc->max_slices = 16;
- hdmi_dsc->clk_per_slice = 400;
- break;
- case 0:
- default:
- hdmi_dsc->max_slices = 0;
- hdmi_dsc->clk_per_slice = 0;
- }
- }
}
drm_parse_ycbcr420_deep_color_info(connector, hf_scds);
+
+ if (cea_db_payload_len(hf_scds) >= 11 && hf_scds[11]) {
+ drm_parse_dsc_info(hdmi_dsc, hf_scds);
+ dsc_support = true;
+ }
+
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] HF-VSDB: max TMDS clock: %d KHz, HDMI 2.1 support: %s, DSC 1.2 support: %s\n",
+ connector->base.id, connector->name,
+ max_tmds_clock, str_yes_no(max_frl_rate), str_yes_no(dsc_support));
}
static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
@@ -5882,39 +6072,39 @@ static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
if (hdmi[6] & DRM_EDID_HDMI_DC_30) {
dc_bpc = 10;
info->edid_hdmi_rgb444_dc_modes |= DRM_EDID_HDMI_DC_30;
- DRM_DEBUG("%s: HDMI sink does deep color 30.\n",
- connector->name);
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] HDMI sink does deep color 30.\n",
+ connector->base.id, connector->name);
}
if (hdmi[6] & DRM_EDID_HDMI_DC_36) {
dc_bpc = 12;
info->edid_hdmi_rgb444_dc_modes |= DRM_EDID_HDMI_DC_36;
- DRM_DEBUG("%s: HDMI sink does deep color 36.\n",
- connector->name);
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] HDMI sink does deep color 36.\n",
+ connector->base.id, connector->name);
}
if (hdmi[6] & DRM_EDID_HDMI_DC_48) {
dc_bpc = 16;
info->edid_hdmi_rgb444_dc_modes |= DRM_EDID_HDMI_DC_48;
- DRM_DEBUG("%s: HDMI sink does deep color 48.\n",
- connector->name);
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] HDMI sink does deep color 48.\n",
+ connector->base.id, connector->name);
}
if (dc_bpc == 0) {
- DRM_DEBUG("%s: No deep color support on this HDMI sink.\n",
- connector->name);
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] No deep color support on this HDMI sink.\n",
+ connector->base.id, connector->name);
return;
}
- DRM_DEBUG("%s: Assigning HDMI sink color depth as %d bpc.\n",
- connector->name, dc_bpc);
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] Assigning HDMI sink color depth as %d bpc.\n",
+ connector->base.id, connector->name, dc_bpc);
info->bpc = dc_bpc;
/* YCRCB444 is optional according to spec. */
if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) {
info->edid_hdmi_ycbcr444_dc_modes = info->edid_hdmi_rgb444_dc_modes;
- DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n",
- connector->name);
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] HDMI sink does YCRCB444 in deep color.\n",
+ connector->base.id, connector->name);
}
/*
@@ -5922,8 +6112,8 @@ static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
* then deep color 36 bit must be supported.
*/
if (!(hdmi[6] & DRM_EDID_HDMI_DC_36)) {
- DRM_DEBUG("%s: HDMI sink should do DC_36, but does not!\n",
- connector->name);
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] HDMI sink should do DC_36, but does not!\n",
+ connector->base.id, connector->name);
}
}
@@ -5940,10 +6130,9 @@ drm_parse_hdmi_vsdb_video(struct drm_connector *connector, const u8 *db)
if (len >= 7)
info->max_tmds_clock = db[7] * 5000;
- DRM_DEBUG_KMS("HDMI: DVI dual %d, "
- "max TMDS clock %d kHz\n",
- info->dvi_dual,
- info->max_tmds_clock);
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] HDMI: DVI dual %d, max TMDS clock %d kHz\n",
+ connector->base.id, connector->name,
+ info->dvi_dual, info->max_tmds_clock);
drm_parse_hdmi_deep_color_info(connector, db);
}
@@ -5963,8 +6152,9 @@ static void drm_parse_microsoft_vsdb(struct drm_connector *connector,
if (version == 1 || version == 2 || (version == 3 && !desktop_usage))
info->non_desktop = true;
- drm_dbg_kms(connector->dev, "HMD or specialized display VSDB version %u: 0x%02x\n",
- version, db[5]);
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] HMD or specialized display VSDB version %u: 0x%02x\n",
+ connector->base.id, connector->name, version, db[5]);
}
static void drm_parse_cea_ext(struct drm_connector *connector,
@@ -5985,8 +6175,10 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
info->cea_rev = edid_ext[1];
if (info->cea_rev != edid_ext[1])
- DRM_DEBUG_KMS("CEA extension version mismatch %u != %u\n",
- info->cea_rev, edid_ext[1]);
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] CEA extension version mismatch %u != %u\n",
+ connector->base.id, connector->name,
+ info->cea_rev, edid_ext[1]);
/* The existence of a CTA extension should imply RGB support */
info->color_formats = DRM_COLOR_FORMAT_RGB444;
@@ -6033,10 +6225,13 @@ void get_monitor_range(const struct detailed_timing *timing, void *c)
return;
/*
- * Check for flag range limits only. If flag == 1 then
- * no additional timing information provided.
- * Default GTF, GTF Secondary curve and CVT are not
- * supported
+ * These limits are used to determine the VRR refresh
+ * rate range. Only the "range limits only" variant
+ * of the range descriptor seems to guarantee that
+ * any and all timings are accepted by the sink, as
+ * opposed to just timings conforming to the indicated
+ * formula (GTF/GTF2/CVT). Thus other variants of the
+ * range descriptor are not accepted here.
*/
if (range->flags != DRM_EDID_RANGE_LIMITS_ONLY_FLAG)
return;
@@ -6061,14 +6256,18 @@ static void drm_get_monitor_range(struct drm_connector *connector,
.drm_edid = drm_edid,
};
- if (!version_greater(drm_edid, 1, 1))
+ if (drm_edid->edid->revision < 4)
+ return;
+
+ if (!(drm_edid->edid->features & DRM_EDID_FEATURE_CONTINUOUS_FREQ))
return;
drm_for_each_detailed_block(drm_edid, get_monitor_range, &closure);
- DRM_DEBUG_KMS("Supported Monitor Refresh rate range is %d Hz - %d Hz\n",
- info->monitor_range.min_vfreq,
- info->monitor_range.max_vfreq);
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] Supported Monitor Refresh rate range is %d Hz - %d Hz\n",
+ connector->base.id, connector->name,
+ info->monitor_range.min_vfreq, info->monitor_range.max_vfreq);
}
static void drm_parse_vesa_mso_data(struct drm_connector *connector,
@@ -6079,8 +6278,9 @@ static void drm_parse_vesa_mso_data(struct drm_connector *connector,
struct drm_display_info *info = &connector->display_info;
if (block->num_bytes < 3) {
- drm_dbg_kms(connector->dev, "Unexpected vendor block size %u\n",
- block->num_bytes);
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] Unexpected vendor block size %u\n",
+ connector->base.id, connector->name, block->num_bytes);
return;
}
@@ -6088,13 +6288,16 @@ static void drm_parse_vesa_mso_data(struct drm_connector *connector,
return;
if (sizeof(*vesa) != sizeof(*block) + block->num_bytes) {
- drm_dbg_kms(connector->dev, "Unexpected VESA vendor block size\n");
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] Unexpected VESA vendor block size\n",
+ connector->base.id, connector->name);
return;
}
switch (FIELD_GET(DISPLAYID_VESA_MSO_MODE, vesa->mso)) {
default:
- drm_dbg_kms(connector->dev, "Reserved MSO mode value\n");
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] Reserved MSO mode value\n",
+ connector->base.id, connector->name);
fallthrough;
case 0:
info->mso_stream_count = 0;
@@ -6114,12 +6317,16 @@ static void drm_parse_vesa_mso_data(struct drm_connector *connector,
info->mso_pixel_overlap = FIELD_GET(DISPLAYID_VESA_MSO_OVERLAP, vesa->mso);
if (info->mso_pixel_overlap > 8) {
- drm_dbg_kms(connector->dev, "Reserved MSO pixel overlap value %u\n",
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] Reserved MSO pixel overlap value %u\n",
+ connector->base.id, connector->name,
info->mso_pixel_overlap);
info->mso_pixel_overlap = 8;
}
- drm_dbg_kms(connector->dev, "MSO stream count %u, pixel overlap %u\n",
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] MSO stream count %u, pixel overlap %u\n",
+ connector->base.id, connector->name,
info->mso_stream_count, info->mso_pixel_overlap);
}
@@ -6166,6 +6373,7 @@ static void drm_reset_display_info(struct drm_connector *connector)
info->mso_stream_count = 0;
info->mso_pixel_overlap = 0;
+ info->max_dsc_bpp = 0;
}
static u32 update_display_info(struct drm_connector *connector,
@@ -6202,8 +6410,9 @@ static u32 update_display_info(struct drm_connector *connector,
if (info->bpc == 0 && edid->revision == 3 &&
edid->input & DRM_EDID_DIGITAL_DFP_1_X) {
info->bpc = 8;
- DRM_DEBUG("%s: Assigning DFP sink color depth as %d bpc.\n",
- connector->name, info->bpc);
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] Assigning DFP sink color depth as %d bpc.\n",
+ connector->base.id, connector->name, info->bpc);
}
/* Only defined for 1.4 with digital displays */
@@ -6235,8 +6444,9 @@ static u32 update_display_info(struct drm_connector *connector,
break;
}
- DRM_DEBUG("%s: Assigning EDID-1.4 digital sink color depth as %d bpc.\n",
- connector->name, info->bpc);
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] Assigning EDID-1.4 digital sink color depth as %d bpc.\n",
+ connector->base.id, connector->name, info->bpc);
if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444)
info->color_formats |= DRM_COLOR_FORMAT_YCBCR444;
@@ -6247,11 +6457,15 @@ static u32 update_display_info(struct drm_connector *connector,
out:
if (quirks & EDID_QUIRK_NON_DESKTOP) {
- drm_dbg_kms(connector->dev, "Non-desktop display%s\n",
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] Non-desktop display%s\n",
+ connector->base.id, connector->name,
info->non_desktop ? " (redundant quirk)" : "");
info->non_desktop = true;
}
+ if (quirks & EDID_QUIRK_CAP_DSC_15BPP)
+ info->max_dsc_bpp = 15;
+
return quirks;
}
@@ -6390,7 +6604,7 @@ static int _drm_edid_connector_update(struct drm_connector *connector,
num_modes += add_cea_modes(connector, drm_edid);
num_modes += add_alternate_cea_modes(connector, drm_edid);
num_modes += add_displayid_detailed_modes(connector, drm_edid);
- if (drm_edid->edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)
+ if (drm_edid->edid->features & DRM_EDID_FEATURE_CONTINUOUS_FREQ)
num_modes += add_inferred_modes(connector, drm_edid);
if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75))
@@ -6482,23 +6696,6 @@ int drm_edid_connector_update(struct drm_connector *connector,
{
int count;
- /*
- * FIXME: Reconcile the differences in override_edid handling between
- * this and drm_connector_update_edid_property().
- *
- * If override_edid is set, and the EDID passed in here originates from
- * drm_edid_read() and friends, it will be the override EDID, and there
- * are no issues. drm_connector_update_edid_property() ignoring requests
- * to set the EDID dates back to a time when override EDID was not
- * handled at the low level EDID read.
- *
- * The only way the EDID passed in here can be different from the
- * override EDID is when a driver passes in an EDID that does *not*
- * originate from drm_edid_read() and friends, or passes in a stale
- * cached version. This, in turn, is a question of when an override EDID
- * set via debugfs should take effect.
- */
-
count = _drm_edid_connector_update(connector, drm_edid);
_drm_update_tile_info(connector, drm_edid);
@@ -6513,10 +6710,6 @@ EXPORT_SYMBOL(drm_edid_connector_update);
static int _drm_connector_update_edid_property(struct drm_connector *connector,
const struct drm_edid *drm_edid)
{
- /* ignore requests to set edid when overridden */
- if (connector->override_edid)
- return 0;
-
/*
* Set the display info, using edid if available, otherwise resetting
* the values to defaults. This duplicates the work done in
@@ -6579,8 +6772,8 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
struct drm_edid drm_edid;
if (edid && !drm_edid_is_valid(edid)) {
- drm_warn(connector->dev, "%s: EDID invalid.\n",
- connector->name);
+ drm_warn(connector->dev, "[CONNECTOR:%d:%s] EDID invalid.\n",
+ connector->base.id, connector->name);
edid = NULL;
}
@@ -6837,7 +7030,7 @@ drm_hdmi_avi_infoframe_quant_range(struct hdmi_avi_infoframe *frame,
* by non-zero YQ when receiving RGB. There doesn't seem to be any
* good way to tell which version of CEA-861 the sink supports, so
* we limit non-zero YQ to HDMI 2.0 sinks only as HDMI 2.0 is based
- * on on CEA-861-F.
+ * on CEA-861-F.
*/
if (!is_hdmi2_sink(connector) ||
rgb_quant_range == HDMI_QUANTIZATION_RANGE_LIMITED)
@@ -6956,11 +7149,14 @@ static void drm_parse_tiled_block(struct drm_connector *connector,
connector->tile_h_size = w + 1;
connector->tile_v_size = h + 1;
- DRM_DEBUG_KMS("tile cap 0x%x\n", tile->tile_cap);
- DRM_DEBUG_KMS("tile_size %d x %d\n", w + 1, h + 1);
- DRM_DEBUG_KMS("topo num tiles %dx%d, location %dx%d\n",
- num_h_tile + 1, num_v_tile + 1, tile_h_loc, tile_v_loc);
- DRM_DEBUG_KMS("vend %c%c%c\n", tile->topology_id[0], tile->topology_id[1], tile->topology_id[2]);
+ drm_dbg_kms(connector->dev,
+ "[CONNECTOR:%d:%s] tile cap 0x%x, size %dx%d, num tiles %dx%d, location %dx%d, vend %c%c%c",
+ connector->base.id, connector->name,
+ tile->tile_cap,
+ connector->tile_h_size, connector->tile_v_size,
+ connector->num_h_tile, connector->num_v_tile,
+ connector->tile_h_loc, connector->tile_v_loc,
+ tile->topology_id[0], tile->topology_id[1], tile->topology_id[2]);
tg = drm_mode_get_tile_group(connector->dev, tile->topology_id);
if (!tg)
diff --git a/drivers/gpu/drm/drm_edid_load.c b/drivers/gpu/drm/drm_edid_load.c
index 37d8ba3ddb46..5d9ef267ebb3 100644
--- a/drivers/gpu/drm/drm_edid_load.c
+++ b/drivers/gpu/drm/drm_edid_load.c
@@ -11,12 +11,13 @@
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
+#include <drm/drm_connector.h>
#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
#include <drm/drm_print.h>
+#include "drm_crtc_internal.h"
+
static char edid_firmware[PATH_MAX];
module_param_string(edid_firmware, edid_firmware, sizeof(edid_firmware), 0644);
MODULE_PARM_DESC(edid_firmware, "Do not probe monitor, use specified EDID blob "
@@ -159,44 +160,26 @@ static const u8 generic_edid[GENERIC_EDIDS][128] = {
},
};
-static int edid_size(const u8 *edid, int data_size)
-{
- if (data_size < EDID_LENGTH)
- return 0;
-
- return (edid[0x7e] + 1) * EDID_LENGTH;
-}
-
-static void *edid_load(struct drm_connector *connector, const char *name,
- const char *connector_name)
+static const struct drm_edid *edid_load(struct drm_connector *connector, const char *name)
{
const struct firmware *fw = NULL;
const u8 *fwdata;
- u8 *edid;
+ const struct drm_edid *drm_edid;
int fwsize, builtin;
- int i, valid_extensions = 0;
- bool print_bad_edid = !connector->bad_edid_counter || drm_debug_enabled(DRM_UT_KMS);
builtin = match_string(generic_edid_name, GENERIC_EDIDS, name);
if (builtin >= 0) {
fwdata = generic_edid[builtin];
fwsize = sizeof(generic_edid[builtin]);
} else {
- struct platform_device *pdev;
int err;
- pdev = platform_device_register_simple(connector_name, -1, NULL, 0);
- if (IS_ERR(pdev)) {
- DRM_ERROR("Failed to register EDID firmware platform device "
- "for connector \"%s\"\n", connector_name);
- return ERR_CAST(pdev);
- }
-
- err = request_firmware(&fw, name, &pdev->dev);
- platform_device_unregister(pdev);
+ err = request_firmware(&fw, name, connector->dev->dev);
if (err) {
- DRM_ERROR("Requesting EDID firmware \"%s\" failed (err=%d)\n",
- name, err);
+ drm_err(connector->dev,
+ "[CONNECTOR:%d:%s] Requesting EDID firmware \"%s\" failed (err=%d)\n",
+ connector->base.id, connector->name,
+ name, err);
return ERR_PTR(err);
}
@@ -204,70 +187,26 @@ static void *edid_load(struct drm_connector *connector, const char *name,
fwsize = fw->size;
}
- if (edid_size(fwdata, fwsize) != fwsize) {
- DRM_ERROR("Size of EDID firmware \"%s\" is invalid "
- "(expected %d, got %d\n", name,
- edid_size(fwdata, fwsize), (int)fwsize);
- edid = ERR_PTR(-EINVAL);
- goto out;
- }
-
- edid = kmemdup(fwdata, fwsize, GFP_KERNEL);
- if (edid == NULL) {
- edid = ERR_PTR(-ENOMEM);
- goto out;
- }
+ drm_dbg_kms(connector->dev, "[CONNECTOR:%d:%s] Loaded %s firmware EDID \"%s\"\n",
+ connector->base.id, connector->name,
+ builtin >= 0 ? "built-in" : "external", name);
- if (!drm_edid_block_valid(edid, 0, print_bad_edid,
- &connector->edid_corrupt)) {
- connector->bad_edid_counter++;
- DRM_ERROR("Base block of EDID firmware \"%s\" is invalid ",
- name);
- kfree(edid);
- edid = ERR_PTR(-EINVAL);
- goto out;
+ drm_edid = drm_edid_alloc(fwdata, fwsize);
+ if (!drm_edid_valid(drm_edid)) {
+ drm_err(connector->dev, "Invalid firmware EDID \"%s\"\n", name);
+ drm_edid_free(drm_edid);
+ drm_edid = ERR_PTR(-EINVAL);
}
- for (i = 1; i <= edid[0x7e]; i++) {
- if (i != valid_extensions + 1)
- memcpy(edid + (valid_extensions + 1) * EDID_LENGTH,
- edid + i * EDID_LENGTH, EDID_LENGTH);
- if (drm_edid_block_valid(edid + i * EDID_LENGTH, i,
- print_bad_edid,
- NULL))
- valid_extensions++;
- }
-
- if (valid_extensions != edid[0x7e]) {
- u8 *new_edid;
-
- edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions;
- DRM_INFO("Found %d valid extensions instead of %d in EDID data "
- "\"%s\" for connector \"%s\"\n", valid_extensions,
- edid[0x7e], name, connector_name);
- edid[0x7e] = valid_extensions;
-
- new_edid = krealloc(edid, (valid_extensions + 1) * EDID_LENGTH,
- GFP_KERNEL);
- if (new_edid)
- edid = new_edid;
- }
-
- DRM_INFO("Got %s EDID base block and %d extension%s from "
- "\"%s\" for connector \"%s\"\n", (builtin >= 0) ? "built-in" :
- "external", valid_extensions, valid_extensions == 1 ? "" : "s",
- name, connector_name);
-
-out:
release_firmware(fw);
- return edid;
+
+ return drm_edid;
}
-struct edid *drm_load_edid_firmware(struct drm_connector *connector)
+const struct drm_edid *drm_edid_load_firmware(struct drm_connector *connector)
{
- const char *connector_name = connector->name;
char *edidname, *last, *colon, *fwstr, *edidstr, *fallback = NULL;
- struct edid *edid;
+ const struct drm_edid *drm_edid;
if (edid_firmware[0] == '\0')
return ERR_PTR(-ENOENT);
@@ -288,7 +227,7 @@ struct edid *drm_load_edid_firmware(struct drm_connector *connector)
while ((edidname = strsep(&edidstr, ","))) {
colon = strchr(edidname, ':');
if (colon != NULL) {
- if (strncmp(connector_name, edidname, colon - edidname))
+ if (strncmp(connector->name, edidname, colon - edidname))
continue;
edidname = colon + 1;
break;
@@ -310,8 +249,9 @@ struct edid *drm_load_edid_firmware(struct drm_connector *connector)
if (*last == '\n')
*last = '\0';
- edid = edid_load(connector, edidname, connector_name);
+ drm_edid = edid_load(connector, edidname);
+
kfree(fwstr);
- return edid;
+ return drm_edid;
}
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 71edb80fe0fb..b3a731b9170a 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -30,24 +30,17 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/console.h>
-#include <linux/dma-buf.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
#include <linux/sysrq.h>
-#include <linux/vmalloc.h>
#include <drm/drm_atomic.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_crtc_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
+#include <drm/drm_modeset_helper_vtables.h>
#include <drm/drm_print.h>
#include <drm/drm_vblank.h>
-#include "drm_crtc_helper_internal.h"
#include "drm_internal.h"
static bool drm_fbdev_emulation = true;
@@ -74,7 +67,7 @@ MODULE_PARM_DESC(drm_fbdev_overalloc,
* considered as a broken and legacy behaviour from a modern fbdev device.
*/
#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
-static bool drm_leak_fbdev_smem = false;
+static bool drm_leak_fbdev_smem;
module_param_unsafe(drm_leak_fbdev_smem, bool, 0600);
MODULE_PARM_DESC(drm_leak_fbdev_smem,
"Allow unsafe leaking fbdev physical smem address [default=false]");
@@ -96,11 +89,13 @@ static DEFINE_MUTEX(kernel_fb_helper_lock);
* It will automatically set up deferred I/O if the driver requires a shadow
* buffer.
*
- * At runtime drivers should restore the fbdev console by using
+ * Existing fbdev implementations should restore the fbdev console by using
* drm_fb_helper_lastclose() as their &drm_driver.lastclose callback.
* They should also notify the fb helper code from updates to the output
* configuration by using drm_fb_helper_output_poll_changed() as their
- * &drm_mode_config_funcs.output_poll_changed callback.
+ * &drm_mode_config_funcs.output_poll_changed callback. New implementations
+ * of fbdev should be build on top of struct &drm_client_funcs, which handles
+ * this automatically. Setting the old callbacks should be avoided.
*
* For suspend/resume consider using drm_mode_config_helper_suspend() and
* drm_mode_config_helper_resume() which takes care of fbdev as well.
@@ -368,115 +363,30 @@ static void drm_fb_helper_resume_worker(struct work_struct *work)
resume_work);
console_lock();
- fb_set_suspend(helper->fbdev, 0);
+ fb_set_suspend(helper->info, 0);
console_unlock();
}
-static void drm_fb_helper_damage_blit_real(struct drm_fb_helper *fb_helper,
- struct drm_clip_rect *clip,
- struct iosys_map *dst)
+static void drm_fb_helper_fb_dirty(struct drm_fb_helper *helper)
{
- struct drm_framebuffer *fb = fb_helper->fb;
- size_t offset = clip->y1 * fb->pitches[0];
- size_t len = clip->x2 - clip->x1;
- unsigned int y;
- void *src;
-
- switch (drm_format_info_bpp(fb->format, 0)) {
- case 1:
- offset += clip->x1 / 8;
- len = DIV_ROUND_UP(len + clip->x1 % 8, 8);
- break;
- case 2:
- offset += clip->x1 / 4;
- len = DIV_ROUND_UP(len + clip->x1 % 4, 4);
- break;
- case 4:
- offset += clip->x1 / 2;
- len = DIV_ROUND_UP(len + clip->x1 % 2, 2);
- break;
- default:
- offset += clip->x1 * fb->format->cpp[0];
- len *= fb->format->cpp[0];
- break;
- }
-
- src = fb_helper->fbdev->screen_buffer + offset;
- iosys_map_incr(dst, offset); /* go to first pixel within clip rect */
-
- for (y = clip->y1; y < clip->y2; y++) {
- iosys_map_memcpy_to(dst, 0, src, len);
- iosys_map_incr(dst, fb->pitches[0]);
- src += fb->pitches[0];
- }
-}
-
-static int drm_fb_helper_damage_blit(struct drm_fb_helper *fb_helper,
- struct drm_clip_rect *clip)
-{
- struct drm_client_buffer *buffer = fb_helper->buffer;
- struct iosys_map map, dst;
- int ret;
-
- /*
- * We have to pin the client buffer to its current location while
- * flushing the shadow buffer. In the general case, concurrent
- * modesetting operations could try to move the buffer and would
- * fail. The modeset has to be serialized by acquiring the reservation
- * object of the underlying BO here.
- *
- * For fbdev emulation, we only have to protect against fbdev modeset
- * operations. Nothing else will involve the client buffer's BO. So it
- * is sufficient to acquire struct drm_fb_helper.lock here.
- */
- mutex_lock(&fb_helper->lock);
-
- ret = drm_client_buffer_vmap(buffer, &map);
- if (ret)
- goto out;
-
- dst = map;
- drm_fb_helper_damage_blit_real(fb_helper, clip, &dst);
-
- drm_client_buffer_vunmap(buffer);
-
-out:
- mutex_unlock(&fb_helper->lock);
-
- return ret;
-}
-
-static void drm_fb_helper_damage_work(struct work_struct *work)
-{
- struct drm_fb_helper *helper = container_of(work, struct drm_fb_helper,
- damage_work);
struct drm_device *dev = helper->dev;
struct drm_clip_rect *clip = &helper->damage_clip;
struct drm_clip_rect clip_copy;
unsigned long flags;
int ret;
+ if (drm_WARN_ON_ONCE(dev, !helper->funcs->fb_dirty))
+ return;
+
spin_lock_irqsave(&helper->damage_lock, flags);
clip_copy = *clip;
clip->x1 = clip->y1 = ~0;
clip->x2 = clip->y2 = 0;
spin_unlock_irqrestore(&helper->damage_lock, flags);
- /* Call damage handlers only if necessary */
- if (!(clip_copy.x1 < clip_copy.x2 && clip_copy.y1 < clip_copy.y2))
- return;
-
- if (helper->buffer) {
- ret = drm_fb_helper_damage_blit(helper, &clip_copy);
- if (drm_WARN_ONCE(dev, ret, "Damage blitter failed: ret=%d\n", ret))
- goto err;
- }
-
- if (helper->fb->funcs->dirty) {
- ret = helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, &clip_copy, 1);
- if (drm_WARN_ONCE(dev, ret, "Dirty helper failed: ret=%d\n", ret))
- goto err;
- }
+ ret = helper->funcs->fb_dirty(helper, &clip_copy);
+ if (ret)
+ goto err;
return;
@@ -493,6 +403,13 @@ err:
spin_unlock_irqrestore(&helper->damage_lock, flags);
}
+static void drm_fb_helper_damage_work(struct work_struct *work)
+{
+ struct drm_fb_helper *helper = container_of(work, struct drm_fb_helper, damage_work);
+
+ drm_fb_helper_fb_dirty(helper);
+}
+
/**
* drm_fb_helper_prepare - setup a drm_fb_helper structure
* @dev: DRM device
@@ -536,11 +453,6 @@ int drm_fb_helper_init(struct drm_device *dev,
{
int ret;
- if (!drm_fbdev_emulation) {
- dev->fb_helper = fb_helper;
- return 0;
- }
-
/*
* If this is not the generic fbdev client, initialize a drm_client
* without callbacks so we can use the modesets.
@@ -558,7 +470,7 @@ int drm_fb_helper_init(struct drm_device *dev,
EXPORT_SYMBOL(drm_fb_helper_init);
/**
- * drm_fb_helper_alloc_fbi - allocate fb_info and some of its members
+ * drm_fb_helper_alloc_info - allocate fb_info and some of its members
* @fb_helper: driver-allocated fbdev helper
*
* A helper to alloc fb_info and the members cmap and apertures. Called
@@ -570,7 +482,7 @@ EXPORT_SYMBOL(drm_fb_helper_init);
* fb_info pointer if things went okay, pointer containing error code
* otherwise
*/
-struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper)
+struct fb_info *drm_fb_helper_alloc_info(struct drm_fb_helper *fb_helper)
{
struct device *dev = fb_helper->dev->dev;
struct fb_info *info;
@@ -598,7 +510,7 @@ struct fb_info *drm_fb_helper_alloc_fbi(struct drm_fb_helper *fb_helper)
goto err_free_cmap;
}
- fb_helper->fbdev = info;
+ fb_helper->info = info;
info->skip_vt_switch = true;
return info;
@@ -609,22 +521,22 @@ err_release:
framebuffer_release(info);
return ERR_PTR(ret);
}
-EXPORT_SYMBOL(drm_fb_helper_alloc_fbi);
+EXPORT_SYMBOL(drm_fb_helper_alloc_info);
/**
- * drm_fb_helper_unregister_fbi - unregister fb_info framebuffer device
+ * drm_fb_helper_unregister_info - unregister fb_info framebuffer device
* @fb_helper: driver-allocated fbdev helper, can be NULL
*
* A wrapper around unregister_framebuffer, to release the fb_info
* framebuffer device. This must be called before releasing all resources for
* @fb_helper by calling drm_fb_helper_fini().
*/
-void drm_fb_helper_unregister_fbi(struct drm_fb_helper *fb_helper)
+void drm_fb_helper_unregister_info(struct drm_fb_helper *fb_helper)
{
- if (fb_helper && fb_helper->fbdev)
- unregister_framebuffer(fb_helper->fbdev);
+ if (fb_helper && fb_helper->info)
+ unregister_framebuffer(fb_helper->info);
}
-EXPORT_SYMBOL(drm_fb_helper_unregister_fbi);
+EXPORT_SYMBOL(drm_fb_helper_unregister_info);
/**
* drm_fb_helper_fini - finialize a &struct drm_fb_helper
@@ -647,13 +559,13 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
cancel_work_sync(&fb_helper->resume_work);
cancel_work_sync(&fb_helper->damage_work);
- info = fb_helper->fbdev;
+ info = fb_helper->info;
if (info) {
if (info->cmap.len)
fb_dealloc_cmap(&info->cmap);
framebuffer_release(info);
}
- fb_helper->fbdev = NULL;
+ fb_helper->info = NULL;
mutex_lock(&kernel_fb_helper_lock);
if (!list_empty(&fb_helper->kernel_fb_list)) {
@@ -670,32 +582,24 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
}
EXPORT_SYMBOL(drm_fb_helper_fini);
-static bool drm_fbdev_use_shadow_fb(struct drm_fb_helper *fb_helper)
-{
- struct drm_device *dev = fb_helper->dev;
- struct drm_framebuffer *fb = fb_helper->fb;
-
- return dev->mode_config.prefer_shadow_fbdev ||
- dev->mode_config.prefer_shadow ||
- fb->funcs->dirty;
-}
-
-static void drm_fb_helper_damage(struct fb_info *info, u32 x, u32 y,
- u32 width, u32 height)
+static void drm_fb_helper_add_damage_clip(struct drm_fb_helper *helper, u32 x, u32 y,
+ u32 width, u32 height)
{
- struct drm_fb_helper *helper = info->par;
struct drm_clip_rect *clip = &helper->damage_clip;
unsigned long flags;
- if (!drm_fbdev_use_shadow_fb(helper))
- return;
-
spin_lock_irqsave(&helper->damage_lock, flags);
clip->x1 = min_t(u32, clip->x1, x);
clip->y1 = min_t(u32, clip->y1, y);
clip->x2 = max_t(u32, clip->x2, x + width);
clip->y2 = max_t(u32, clip->y2, y + height);
spin_unlock_irqrestore(&helper->damage_lock, flags);
+}
+
+static void drm_fb_helper_damage(struct drm_fb_helper *helper, u32 x, u32 y,
+ u32 width, u32 height)
+{
+ drm_fb_helper_add_damage_clip(helper, x, y, width, height);
schedule_work(&helper->damage_work);
}
@@ -739,6 +643,7 @@ static void drm_fb_helper_memory_range_to_clip(struct fb_info *info, off_t off,
*/
void drm_fb_helper_deferred_io(struct fb_info *info, struct list_head *pagereflist)
{
+ struct drm_fb_helper *helper = info->par;
unsigned long start, end, min_off, max_off;
struct fb_deferred_io_pageref *pageref;
struct drm_rect damage_area;
@@ -751,8 +656,6 @@ void drm_fb_helper_deferred_io(struct fb_info *info, struct list_head *pagerefli
min_off = min(min_off, start);
max_off = max(max_off, end);
}
- if (min_off >= max_off)
- return;
/*
* As we can only track pages, we might reach beyond the end
@@ -761,53 +664,160 @@ void drm_fb_helper_deferred_io(struct fb_info *info, struct list_head *pagerefli
*/
max_off = min(max_off, info->screen_size);
- drm_fb_helper_memory_range_to_clip(info, min_off, max_off - min_off, &damage_area);
- drm_fb_helper_damage(info, damage_area.x1, damage_area.y1,
- drm_rect_width(&damage_area),
- drm_rect_height(&damage_area));
+ if (min_off < max_off) {
+ drm_fb_helper_memory_range_to_clip(info, min_off, max_off - min_off, &damage_area);
+ drm_fb_helper_damage(helper, damage_area.x1, damage_area.y1,
+ drm_rect_width(&damage_area),
+ drm_rect_height(&damage_area));
+ }
}
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 - wrapper around fb_sys_read
+ * 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
*
- * A wrapper around fb_sys_read implemented by fbdev core
+ * 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 fb_sys_read(info, buf, count, 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 - wrapper around fb_sys_write
+ * 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
*
- * A wrapper around fb_sys_write implemented by fbdev core
+ * 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 = fb_sys_write(info, buf, count, ppos);
+ ret = __drm_fb_helper_write(info, buf, count, ppos, drm_fb_helper_write_screen_buffer);
if (ret <= 0)
return ret;
- drm_fb_helper_memory_range_to_clip(info, pos, ret, &damage_area);
- drm_fb_helper_damage(info, damage_area.x1, damage_area.y1,
- drm_rect_width(&damage_area),
- drm_rect_height(&damage_area));
+ 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;
}
@@ -823,8 +833,12 @@ EXPORT_SYMBOL(drm_fb_helper_sys_write);
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);
- drm_fb_helper_damage(info, rect->dx, rect->dy, rect->width, rect->height);
+
+ 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);
@@ -838,8 +852,12 @@ EXPORT_SYMBOL(drm_fb_helper_sys_fillrect);
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);
- drm_fb_helper_damage(info, area->dx, area->dy, area->width, area->height);
+
+ 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);
@@ -853,11 +871,131 @@ EXPORT_SYMBOL(drm_fb_helper_sys_copyarea);
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);
- drm_fb_helper_damage(info, image->dx, image->dy, image->width, image->height);
+
+ 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
@@ -868,8 +1006,12 @@ EXPORT_SYMBOL(drm_fb_helper_sys_imageblit);
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);
- drm_fb_helper_damage(info, rect->dx, rect->dy, rect->width, rect->height);
+
+ 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);
@@ -883,8 +1025,12 @@ EXPORT_SYMBOL(drm_fb_helper_cfb_fillrect);
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);
- drm_fb_helper_damage(info, area->dx, area->dy, area->width, area->height);
+
+ 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);
@@ -898,8 +1044,12 @@ EXPORT_SYMBOL(drm_fb_helper_cfb_copyarea);
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);
- drm_fb_helper_damage(info, image->dx, image->dy, image->width, image->height);
+
+ 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);
@@ -914,8 +1064,8 @@ EXPORT_SYMBOL(drm_fb_helper_cfb_imageblit);
*/
void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper, bool suspend)
{
- if (fb_helper && fb_helper->fbdev)
- fb_set_suspend(fb_helper->fbdev, suspend);
+ if (fb_helper && fb_helper->info)
+ fb_set_suspend(fb_helper->info, suspend);
}
EXPORT_SYMBOL(drm_fb_helper_set_suspend);
@@ -938,20 +1088,20 @@ EXPORT_SYMBOL(drm_fb_helper_set_suspend);
void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,
bool suspend)
{
- if (!fb_helper || !fb_helper->fbdev)
+ if (!fb_helper || !fb_helper->info)
return;
/* make sure there's no pending/ongoing resume */
flush_work(&fb_helper->resume_work);
if (suspend) {
- if (fb_helper->fbdev->state != FBINFO_STATE_RUNNING)
+ if (fb_helper->info->state != FBINFO_STATE_RUNNING)
return;
console_lock();
} else {
- if (fb_helper->fbdev->state == FBINFO_STATE_RUNNING)
+ if (fb_helper->info->state == FBINFO_STATE_RUNNING)
return;
if (!console_trylock()) {
@@ -960,7 +1110,7 @@ void drm_fb_helper_set_suspend_unlocked(struct drm_fb_helper *fb_helper,
}
}
- fb_set_suspend(fb_helper->fbdev, suspend);
+ fb_set_suspend(fb_helper->info, suspend);
console_unlock();
}
EXPORT_SYMBOL(drm_fb_helper_set_suspend_unlocked);
@@ -1749,6 +1899,10 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
sizes.surface_height = config->max_height;
}
+#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
+ fb_helper->hint_leak_smem_start = drm_leak_fbdev_smem;
+#endif
+
/* push down into drivers */
ret = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes);
if (ret < 0)
@@ -1850,7 +2004,7 @@ EXPORT_SYMBOL(drm_fb_helper_fill_info);
/*
* This is a continuation of drm_setup_crtcs() that sets up anything related
* to the framebuffer. During initialization, drm_setup_crtcs() is called before
- * the framebuffer has been allocated (fb_helper->fb and fb_helper->fbdev).
+ * the framebuffer has been allocated (fb_helper->fb and fb_helper->info).
* So, any setup that touches those fields needs to be done here instead of in
* drm_setup_crtcs().
*/
@@ -1858,7 +2012,7 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper)
{
struct drm_client_dev *client = &fb_helper->client;
struct drm_connector_list_iter conn_iter;
- struct fb_info *info = fb_helper->fbdev;
+ struct fb_info *info = fb_helper->info;
unsigned int rotation, sw_rotations = 0;
struct drm_connector *connector;
struct drm_mode_set *modeset;
@@ -1942,11 +2096,11 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper,
fb_helper->deferred_setup = false;
- info = fb_helper->fbdev;
+ info = fb_helper->info;
info->var.pixclock = 0;
/* Shamelessly allow physical address leaking to userspace */
#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
- if (!drm_leak_fbdev_smem)
+ if (!fb_helper->hint_leak_smem_start)
#endif
/* don't leak any physical addresses to userspace */
info->flags |= FBINFO_HIDE_SMEM_START;
@@ -2077,7 +2231,7 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
drm_setup_crtcs_fb(fb_helper);
mutex_unlock(&fb_helper->lock);
- drm_fb_helper_set_par(fb_helper->fbdev);
+ drm_fb_helper_set_par(fb_helper->info);
return 0;
}
@@ -2103,530 +2257,10 @@ EXPORT_SYMBOL(drm_fb_helper_lastclose);
*
* This function can be used as the
* &drm_mode_config_funcs.output_poll_changed callback for drivers that only
- * need to call drm_fb_helper_hotplug_event().
+ * need to call drm_fbdev.hotplug_event().
*/
void drm_fb_helper_output_poll_changed(struct drm_device *dev)
{
drm_fb_helper_hotplug_event(dev->fb_helper);
}
EXPORT_SYMBOL(drm_fb_helper_output_poll_changed);
-
-/* @user: 1=userspace, 0=fbcon */
-static int drm_fbdev_fb_open(struct fb_info *info, int user)
-{
- struct drm_fb_helper *fb_helper = info->par;
-
- /* No need to take a ref for fbcon because it unbinds on unregister */
- if (user && !try_module_get(fb_helper->dev->driver->fops->owner))
- return -ENODEV;
-
- return 0;
-}
-
-static int drm_fbdev_fb_release(struct fb_info *info, int user)
-{
- struct drm_fb_helper *fb_helper = info->par;
-
- if (user)
- module_put(fb_helper->dev->driver->fops->owner);
-
- return 0;
-}
-
-static void drm_fbdev_cleanup(struct drm_fb_helper *fb_helper)
-{
- struct fb_info *fbi = fb_helper->fbdev;
- void *shadow = NULL;
-
- if (!fb_helper->dev)
- return;
-
- if (fbi) {
- if (fbi->fbdefio)
- fb_deferred_io_cleanup(fbi);
- if (drm_fbdev_use_shadow_fb(fb_helper))
- shadow = fbi->screen_buffer;
- }
-
- drm_fb_helper_fini(fb_helper);
-
- if (shadow)
- vfree(shadow);
- else if (fb_helper->buffer)
- drm_client_buffer_vunmap(fb_helper->buffer);
-
- drm_client_framebuffer_delete(fb_helper->buffer);
-}
-
-static void drm_fbdev_release(struct drm_fb_helper *fb_helper)
-{
- drm_fbdev_cleanup(fb_helper);
- drm_client_release(&fb_helper->client);
- kfree(fb_helper);
-}
-
-/*
- * fb_ops.fb_destroy is called by the last put_fb_info() call at the end of
- * unregister_framebuffer() or fb_release().
- */
-static void drm_fbdev_fb_destroy(struct fb_info *info)
-{
- drm_fbdev_release(info->par);
-}
-
-static int drm_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
-{
- struct drm_fb_helper *fb_helper = info->par;
-
- if (drm_fbdev_use_shadow_fb(fb_helper))
- return fb_deferred_io_mmap(info, vma);
- else if (fb_helper->dev->driver->gem_prime_mmap)
- return fb_helper->dev->driver->gem_prime_mmap(fb_helper->buffer->gem, vma);
- else
- return -ENODEV;
-}
-
-static bool drm_fbdev_use_iomem(struct fb_info *info)
-{
- struct drm_fb_helper *fb_helper = info->par;
- struct drm_client_buffer *buffer = fb_helper->buffer;
-
- return !drm_fbdev_use_shadow_fb(fb_helper) && buffer->map.is_iomem;
-}
-
-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;
-}
-
-static ssize_t fb_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;
-}
-
-static ssize_t drm_fbdev_fb_read(struct fb_info *info, char __user *buf,
- size_t count, loff_t *ppos)
-{
- 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 (drm_fbdev_use_iomem(info))
- ret = fb_read_screen_base(info, buf, count, pos);
- else
- ret = fb_read_screen_buffer(info, buf, count, pos);
-
- if (ret > 0)
- *ppos += ret;
-
- return ret;
-}
-
-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;
-}
-
-static ssize_t fb_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;
-}
-
-static ssize_t drm_fbdev_fb_write(struct fb_info *info, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- loff_t pos = *ppos;
- size_t total_size;
- ssize_t ret;
- struct drm_rect damage_area;
- 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;
- }
-
- /*
- * Copy to framebuffer even if we already logged an error. Emulates
- * the behavior of the original fbdev implementation.
- */
- if (drm_fbdev_use_iomem(info))
- ret = fb_write_screen_base(info, buf, count, pos);
- else
- ret = fb_write_screen_buffer(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;
-
- drm_fb_helper_memory_range_to_clip(info, pos, ret, &damage_area);
- drm_fb_helper_damage(info, damage_area.x1, damage_area.y1,
- drm_rect_width(&damage_area),
- drm_rect_height(&damage_area));
-
- return ret;
-}
-
-static void drm_fbdev_fb_fillrect(struct fb_info *info,
- const struct fb_fillrect *rect)
-{
- if (drm_fbdev_use_iomem(info))
- drm_fb_helper_cfb_fillrect(info, rect);
- else
- drm_fb_helper_sys_fillrect(info, rect);
-}
-
-static void drm_fbdev_fb_copyarea(struct fb_info *info,
- const struct fb_copyarea *area)
-{
- if (drm_fbdev_use_iomem(info))
- drm_fb_helper_cfb_copyarea(info, area);
- else
- drm_fb_helper_sys_copyarea(info, area);
-}
-
-static void drm_fbdev_fb_imageblit(struct fb_info *info,
- const struct fb_image *image)
-{
- if (drm_fbdev_use_iomem(info))
- drm_fb_helper_cfb_imageblit(info, image);
- else
- drm_fb_helper_sys_imageblit(info, image);
-}
-
-static const struct fb_ops drm_fbdev_fb_ops = {
- .owner = THIS_MODULE,
- DRM_FB_HELPER_DEFAULT_OPS,
- .fb_open = drm_fbdev_fb_open,
- .fb_release = drm_fbdev_fb_release,
- .fb_destroy = drm_fbdev_fb_destroy,
- .fb_mmap = drm_fbdev_fb_mmap,
- .fb_read = drm_fbdev_fb_read,
- .fb_write = drm_fbdev_fb_write,
- .fb_fillrect = drm_fbdev_fb_fillrect,
- .fb_copyarea = drm_fbdev_fb_copyarea,
- .fb_imageblit = drm_fbdev_fb_imageblit,
-};
-
-static struct fb_deferred_io drm_fbdev_defio = {
- .delay = HZ / 20,
- .deferred_io = drm_fb_helper_deferred_io,
-};
-
-/*
- * This function uses the client API to create a framebuffer backed by a dumb buffer.
- *
- * The _sys_ versions are used for &fb_ops.fb_read, fb_write, fb_fillrect,
- * fb_copyarea, fb_imageblit.
- */
-static int drm_fb_helper_generic_probe(struct drm_fb_helper *fb_helper,
- struct drm_fb_helper_surface_size *sizes)
-{
- struct drm_client_dev *client = &fb_helper->client;
- struct drm_device *dev = fb_helper->dev;
- struct drm_client_buffer *buffer;
- struct drm_framebuffer *fb;
- struct fb_info *fbi;
- u32 format;
- struct iosys_map map;
- int ret;
-
- drm_dbg_kms(dev, "surface width(%d), height(%d) and bpp(%d)\n",
- sizes->surface_width, sizes->surface_height,
- sizes->surface_bpp);
-
- format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth);
- buffer = drm_client_framebuffer_create(client, sizes->surface_width,
- sizes->surface_height, format);
- if (IS_ERR(buffer))
- return PTR_ERR(buffer);
-
- fb_helper->buffer = buffer;
- fb_helper->fb = buffer->fb;
- fb = buffer->fb;
-
- fbi = drm_fb_helper_alloc_fbi(fb_helper);
- if (IS_ERR(fbi))
- return PTR_ERR(fbi);
-
- fbi->fbops = &drm_fbdev_fb_ops;
- fbi->screen_size = sizes->surface_height * fb->pitches[0];
- fbi->fix.smem_len = fbi->screen_size;
- fbi->flags = FBINFO_DEFAULT;
-
- drm_fb_helper_fill_info(fbi, fb_helper, sizes);
-
- if (drm_fbdev_use_shadow_fb(fb_helper)) {
- fbi->screen_buffer = vzalloc(fbi->screen_size);
- if (!fbi->screen_buffer)
- return -ENOMEM;
- fbi->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST;
-
- fbi->fbdefio = &drm_fbdev_defio;
- fb_deferred_io_init(fbi);
- } else {
- /* buffer is mapped for HW framebuffer */
- ret = drm_client_buffer_vmap(fb_helper->buffer, &map);
- if (ret)
- return ret;
- if (map.is_iomem) {
- fbi->screen_base = map.vaddr_iomem;
- } else {
- fbi->screen_buffer = map.vaddr;
- fbi->flags |= FBINFO_VIRTFB;
- }
-
- /*
- * Shamelessly leak the physical address to user-space. As
- * page_to_phys() is undefined for I/O memory, warn in this
- * case.
- */
-#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
- if (drm_leak_fbdev_smem && fbi->fix.smem_start == 0 &&
- !drm_WARN_ON_ONCE(dev, map.is_iomem))
- fbi->fix.smem_start =
- page_to_phys(virt_to_page(fbi->screen_buffer));
-#endif
- }
-
- return 0;
-}
-
-static const struct drm_fb_helper_funcs drm_fb_helper_generic_funcs = {
- .fb_probe = drm_fb_helper_generic_probe,
-};
-
-static void drm_fbdev_client_unregister(struct drm_client_dev *client)
-{
- struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
-
- if (fb_helper->fbdev)
- /* drm_fbdev_fb_destroy() takes care of cleanup */
- drm_fb_helper_unregister_fbi(fb_helper);
- else
- drm_fbdev_release(fb_helper);
-}
-
-static int drm_fbdev_client_restore(struct drm_client_dev *client)
-{
- drm_fb_helper_lastclose(client->dev);
-
- return 0;
-}
-
-static int drm_fbdev_client_hotplug(struct drm_client_dev *client)
-{
- struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
- struct drm_device *dev = client->dev;
- int ret;
-
- /* Setup is not retried if it has failed */
- if (!fb_helper->dev && fb_helper->funcs)
- return 0;
-
- if (dev->fb_helper)
- return drm_fb_helper_hotplug_event(dev->fb_helper);
-
- if (!dev->mode_config.num_connector) {
- drm_dbg_kms(dev, "No connectors found, will not create framebuffer!\n");
- return 0;
- }
-
- drm_fb_helper_prepare(dev, fb_helper, &drm_fb_helper_generic_funcs);
-
- ret = drm_fb_helper_init(dev, fb_helper);
- if (ret)
- goto err;
-
- if (!drm_drv_uses_atomic_modeset(dev))
- drm_helper_disable_unused_functions(dev);
-
- ret = drm_fb_helper_initial_config(fb_helper, fb_helper->preferred_bpp);
- if (ret)
- goto err_cleanup;
-
- return 0;
-
-err_cleanup:
- drm_fbdev_cleanup(fb_helper);
-err:
- fb_helper->dev = NULL;
- fb_helper->fbdev = NULL;
-
- drm_err(dev, "fbdev: Failed to setup generic emulation (ret=%d)\n", ret);
-
- return ret;
-}
-
-static const struct drm_client_funcs drm_fbdev_client_funcs = {
- .owner = THIS_MODULE,
- .unregister = drm_fbdev_client_unregister,
- .restore = drm_fbdev_client_restore,
- .hotplug = drm_fbdev_client_hotplug,
-};
-
-/**
- * drm_fbdev_generic_setup() - Setup generic fbdev emulation
- * @dev: DRM device
- * @preferred_bpp: Preferred bits per pixel for the device.
- * @dev->mode_config.preferred_depth is used if this is zero.
- *
- * This function sets up generic fbdev emulation for drivers that supports
- * dumb buffers with a virtual address and that can be mmap'ed.
- * drm_fbdev_generic_setup() shall be called after the DRM driver registered
- * the new DRM device with drm_dev_register().
- *
- * Restore, hotplug events and teardown are all taken care of. Drivers that do
- * suspend/resume need to call drm_fb_helper_set_suspend_unlocked() themselves.
- * Simple drivers might use drm_mode_config_helper_suspend().
- *
- * Drivers that set the dirty callback on their framebuffer will get a shadow
- * fbdev buffer that is blitted onto the real buffer. This is done in order to
- * make deferred I/O work with all kinds of buffers. A shadow buffer can be
- * requested explicitly by setting struct drm_mode_config.prefer_shadow or
- * struct drm_mode_config.prefer_shadow_fbdev to true beforehand. This is
- * required to use generic fbdev emulation with SHMEM helpers.
- *
- * This function is safe to call even when there are no connectors present.
- * Setup will be retried on the next hotplug event.
- *
- * The fbdev is destroyed by drm_dev_unregister().
- */
-void drm_fbdev_generic_setup(struct drm_device *dev,
- unsigned int preferred_bpp)
-{
- struct drm_fb_helper *fb_helper;
- int ret;
-
- drm_WARN(dev, !dev->registered, "Device has not been registered.\n");
- drm_WARN(dev, dev->fb_helper, "fb_helper is already set!\n");
-
- if (!drm_fbdev_emulation)
- return;
-
- fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
- if (!fb_helper) {
- drm_err(dev, "Failed to allocate fb_helper\n");
- return;
- }
-
- ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_client_funcs);
- if (ret) {
- kfree(fb_helper);
- drm_err(dev, "Failed to register client: %d\n", ret);
- return;
- }
-
- /*
- * FIXME: This mixes up depth with bpp, which results in a glorious
- * mess, resulting in some drivers picking wrong fbdev defaults and
- * others wrong preferred_depth defaults.
- */
- if (!preferred_bpp)
- preferred_bpp = dev->mode_config.preferred_depth;
- if (!preferred_bpp)
- preferred_bpp = 32;
- fb_helper->preferred_bpp = preferred_bpp;
-
- ret = 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);
-}
-EXPORT_SYMBOL(drm_fbdev_generic_setup);
diff --git a/drivers/gpu/drm/drm_fbdev_generic.c b/drivers/gpu/drm/drm_fbdev_generic.c
new file mode 100644
index 000000000000..ab8695669279
--- /dev/null
+++ b/drivers/gpu/drm/drm_fbdev_generic.c
@@ -0,0 +1,494 @@
+// SPDX-License-Identifier: MIT
+
+#include <linux/moduleparam.h>
+#include <linux/vmalloc.h>
+
+#include <drm/drm_crtc_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_print.h>
+
+#include <drm/drm_fbdev_generic.h>
+
+static bool drm_fbdev_use_shadow_fb(struct drm_fb_helper *fb_helper)
+{
+ struct drm_device *dev = fb_helper->dev;
+ struct drm_framebuffer *fb = fb_helper->fb;
+
+ return dev->mode_config.prefer_shadow_fbdev ||
+ dev->mode_config.prefer_shadow ||
+ fb->funcs->dirty;
+}
+
+/* @user: 1=userspace, 0=fbcon */
+static int drm_fbdev_fb_open(struct fb_info *info, int user)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+
+ /* No need to take a ref for fbcon because it unbinds on unregister */
+ if (user && !try_module_get(fb_helper->dev->driver->fops->owner))
+ return -ENODEV;
+
+ return 0;
+}
+
+static int drm_fbdev_fb_release(struct fb_info *info, int user)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+
+ if (user)
+ module_put(fb_helper->dev->driver->fops->owner);
+
+ return 0;
+}
+
+static void drm_fbdev_cleanup(struct drm_fb_helper *fb_helper)
+{
+ struct fb_info *fbi = fb_helper->info;
+ void *shadow = NULL;
+
+ if (!fb_helper->dev)
+ return;
+
+ if (fbi) {
+ if (fbi->fbdefio)
+ fb_deferred_io_cleanup(fbi);
+ if (drm_fbdev_use_shadow_fb(fb_helper))
+ shadow = fbi->screen_buffer;
+ }
+
+ drm_fb_helper_fini(fb_helper);
+
+ if (shadow)
+ vfree(shadow);
+ else if (fb_helper->buffer)
+ drm_client_buffer_vunmap(fb_helper->buffer);
+
+ drm_client_framebuffer_delete(fb_helper->buffer);
+}
+
+static void drm_fbdev_release(struct drm_fb_helper *fb_helper)
+{
+ drm_fbdev_cleanup(fb_helper);
+ drm_client_release(&fb_helper->client);
+ kfree(fb_helper);
+}
+
+/*
+ * fb_ops.fb_destroy is called by the last put_fb_info() call at the end of
+ * unregister_framebuffer() or fb_release().
+ */
+static void drm_fbdev_fb_destroy(struct fb_info *info)
+{
+ drm_fbdev_release(info->par);
+}
+
+static int drm_fbdev_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+
+ if (drm_fbdev_use_shadow_fb(fb_helper))
+ return fb_deferred_io_mmap(info, vma);
+ else if (fb_helper->dev->driver->gem_prime_mmap)
+ return fb_helper->dev->driver->gem_prime_mmap(fb_helper->buffer->gem, vma);
+ else
+ return -ENODEV;
+}
+
+static bool drm_fbdev_use_iomem(struct fb_info *info)
+{
+ struct drm_fb_helper *fb_helper = info->par;
+ struct drm_client_buffer *buffer = fb_helper->buffer;
+
+ return !drm_fbdev_use_shadow_fb(fb_helper) && buffer->map.is_iomem;
+}
+
+static ssize_t drm_fbdev_fb_read(struct fb_info *info, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ ssize_t ret;
+
+ if (drm_fbdev_use_iomem(info))
+ ret = drm_fb_helper_cfb_read(info, buf, count, ppos);
+ else
+ ret = drm_fb_helper_sys_read(info, buf, count, ppos);
+
+ return ret;
+}
+
+static ssize_t drm_fbdev_fb_write(struct fb_info *info, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ ssize_t ret;
+
+ if (drm_fbdev_use_iomem(info))
+ ret = drm_fb_helper_cfb_write(info, buf, count, ppos);
+ else
+ ret = drm_fb_helper_sys_write(info, buf, count, ppos);
+
+ return ret;
+}
+
+static void drm_fbdev_fb_fillrect(struct fb_info *info,
+ const struct fb_fillrect *rect)
+{
+ if (drm_fbdev_use_iomem(info))
+ drm_fb_helper_cfb_fillrect(info, rect);
+ else
+ drm_fb_helper_sys_fillrect(info, rect);
+}
+
+static void drm_fbdev_fb_copyarea(struct fb_info *info,
+ const struct fb_copyarea *area)
+{
+ if (drm_fbdev_use_iomem(info))
+ drm_fb_helper_cfb_copyarea(info, area);
+ else
+ drm_fb_helper_sys_copyarea(info, area);
+}
+
+static void drm_fbdev_fb_imageblit(struct fb_info *info,
+ const struct fb_image *image)
+{
+ if (drm_fbdev_use_iomem(info))
+ drm_fb_helper_cfb_imageblit(info, image);
+ else
+ drm_fb_helper_sys_imageblit(info, image);
+}
+
+static const struct fb_ops drm_fbdev_fb_ops = {
+ .owner = THIS_MODULE,
+ DRM_FB_HELPER_DEFAULT_OPS,
+ .fb_open = drm_fbdev_fb_open,
+ .fb_release = drm_fbdev_fb_release,
+ .fb_destroy = drm_fbdev_fb_destroy,
+ .fb_mmap = drm_fbdev_fb_mmap,
+ .fb_read = drm_fbdev_fb_read,
+ .fb_write = drm_fbdev_fb_write,
+ .fb_fillrect = drm_fbdev_fb_fillrect,
+ .fb_copyarea = drm_fbdev_fb_copyarea,
+ .fb_imageblit = drm_fbdev_fb_imageblit,
+};
+
+static struct fb_deferred_io drm_fbdev_defio = {
+ .delay = HZ / 20,
+ .deferred_io = drm_fb_helper_deferred_io,
+};
+
+/*
+ * This function uses the client API to create a framebuffer backed by a dumb buffer.
+ */
+static int drm_fbdev_fb_probe(struct drm_fb_helper *fb_helper,
+ struct drm_fb_helper_surface_size *sizes)
+{
+ struct drm_client_dev *client = &fb_helper->client;
+ struct drm_device *dev = fb_helper->dev;
+ struct drm_client_buffer *buffer;
+ struct drm_framebuffer *fb;
+ struct fb_info *fbi;
+ u32 format;
+ struct iosys_map map;
+ int ret;
+
+ drm_dbg_kms(dev, "surface width(%d), height(%d) and bpp(%d)\n",
+ sizes->surface_width, sizes->surface_height,
+ sizes->surface_bpp);
+
+ format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth);
+ buffer = drm_client_framebuffer_create(client, sizes->surface_width,
+ sizes->surface_height, format);
+ if (IS_ERR(buffer))
+ return PTR_ERR(buffer);
+
+ fb_helper->buffer = buffer;
+ fb_helper->fb = buffer->fb;
+ fb = buffer->fb;
+
+ fbi = drm_fb_helper_alloc_info(fb_helper);
+ if (IS_ERR(fbi))
+ return PTR_ERR(fbi);
+
+ fbi->fbops = &drm_fbdev_fb_ops;
+ fbi->screen_size = sizes->surface_height * fb->pitches[0];
+ fbi->fix.smem_len = fbi->screen_size;
+ fbi->flags = FBINFO_DEFAULT;
+
+ drm_fb_helper_fill_info(fbi, fb_helper, sizes);
+
+ if (drm_fbdev_use_shadow_fb(fb_helper)) {
+ fbi->screen_buffer = vzalloc(fbi->screen_size);
+ if (!fbi->screen_buffer)
+ return -ENOMEM;
+ fbi->flags |= FBINFO_VIRTFB | FBINFO_READS_FAST;
+
+ fbi->fbdefio = &drm_fbdev_defio;
+ fb_deferred_io_init(fbi);
+ } else {
+ /* buffer is mapped for HW framebuffer */
+ ret = drm_client_buffer_vmap(fb_helper->buffer, &map);
+ if (ret)
+ return ret;
+ if (map.is_iomem) {
+ fbi->screen_base = map.vaddr_iomem;
+ } else {
+ fbi->screen_buffer = map.vaddr;
+ fbi->flags |= FBINFO_VIRTFB;
+ }
+
+ /*
+ * Shamelessly leak the physical address to user-space. As
+ * page_to_phys() is undefined for I/O memory, warn in this
+ * case.
+ */
+#if IS_ENABLED(CONFIG_DRM_FBDEV_LEAK_PHYS_SMEM)
+ if (fb_helper->hint_leak_smem_start && fbi->fix.smem_start == 0 &&
+ !drm_WARN_ON_ONCE(dev, map.is_iomem))
+ fbi->fix.smem_start =
+ page_to_phys(virt_to_page(fbi->screen_buffer));
+#endif
+ }
+
+ return 0;
+}
+
+static void drm_fbdev_damage_blit_real(struct drm_fb_helper *fb_helper,
+ struct drm_clip_rect *clip,
+ struct iosys_map *dst)
+{
+ struct drm_framebuffer *fb = fb_helper->fb;
+ size_t offset = clip->y1 * fb->pitches[0];
+ size_t len = clip->x2 - clip->x1;
+ unsigned int y;
+ void *src;
+
+ switch (drm_format_info_bpp(fb->format, 0)) {
+ case 1:
+ offset += clip->x1 / 8;
+ len = DIV_ROUND_UP(len + clip->x1 % 8, 8);
+ break;
+ case 2:
+ offset += clip->x1 / 4;
+ len = DIV_ROUND_UP(len + clip->x1 % 4, 4);
+ break;
+ case 4:
+ offset += clip->x1 / 2;
+ len = DIV_ROUND_UP(len + clip->x1 % 2, 2);
+ break;
+ default:
+ offset += clip->x1 * fb->format->cpp[0];
+ len *= fb->format->cpp[0];
+ break;
+ }
+
+ src = fb_helper->info->screen_buffer + offset;
+ iosys_map_incr(dst, offset); /* go to first pixel within clip rect */
+
+ for (y = clip->y1; y < clip->y2; y++) {
+ iosys_map_memcpy_to(dst, 0, src, len);
+ iosys_map_incr(dst, fb->pitches[0]);
+ src += fb->pitches[0];
+ }
+}
+
+static int drm_fbdev_damage_blit(struct drm_fb_helper *fb_helper,
+ struct drm_clip_rect *clip)
+{
+ struct drm_client_buffer *buffer = fb_helper->buffer;
+ struct iosys_map map, dst;
+ int ret;
+
+ /*
+ * We have to pin the client buffer to its current location while
+ * flushing the shadow buffer. In the general case, concurrent
+ * modesetting operations could try to move the buffer and would
+ * fail. The modeset has to be serialized by acquiring the reservation
+ * object of the underlying BO here.
+ *
+ * For fbdev emulation, we only have to protect against fbdev modeset
+ * operations. Nothing else will involve the client buffer's BO. So it
+ * is sufficient to acquire struct drm_fb_helper.lock here.
+ */
+ mutex_lock(&fb_helper->lock);
+
+ ret = drm_client_buffer_vmap(buffer, &map);
+ if (ret)
+ goto out;
+
+ dst = map;
+ drm_fbdev_damage_blit_real(fb_helper, clip, &dst);
+
+ drm_client_buffer_vunmap(buffer);
+
+out:
+ mutex_unlock(&fb_helper->lock);
+
+ return ret;
+}
+
+static int drm_fbdev_fb_dirty(struct drm_fb_helper *helper, struct drm_clip_rect *clip)
+{
+ struct drm_device *dev = helper->dev;
+ int ret;
+
+ if (!drm_fbdev_use_shadow_fb(helper))
+ return 0;
+
+ /* Call damage handlers only if necessary */
+ if (!(clip->x1 < clip->x2 && clip->y1 < clip->y2))
+ return 0;
+
+ if (helper->buffer) {
+ ret = drm_fbdev_damage_blit(helper, clip);
+ if (drm_WARN_ONCE(dev, ret, "Damage blitter failed: ret=%d\n", ret))
+ return ret;
+ }
+
+ 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 drm_fb_helper_generic_funcs = {
+ .fb_probe = drm_fbdev_fb_probe,
+ .fb_dirty = drm_fbdev_fb_dirty,
+};
+
+static void drm_fbdev_client_unregister(struct drm_client_dev *client)
+{
+ struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
+
+ if (fb_helper->info)
+ /* drm_fbdev_fb_destroy() takes care of cleanup */
+ drm_fb_helper_unregister_info(fb_helper);
+ else
+ drm_fbdev_release(fb_helper);
+}
+
+static int drm_fbdev_client_restore(struct drm_client_dev *client)
+{
+ drm_fb_helper_lastclose(client->dev);
+
+ return 0;
+}
+
+static int drm_fbdev_client_hotplug(struct drm_client_dev *client)
+{
+ struct drm_fb_helper *fb_helper = drm_fb_helper_from_client(client);
+ struct drm_device *dev = client->dev;
+ int ret;
+
+ /* Setup is not retried if it has failed */
+ if (!fb_helper->dev && fb_helper->funcs)
+ return 0;
+
+ if (dev->fb_helper)
+ return drm_fb_helper_hotplug_event(dev->fb_helper);
+
+ if (!dev->mode_config.num_connector) {
+ drm_dbg_kms(dev, "No connectors found, will not create framebuffer!\n");
+ return 0;
+ }
+
+ drm_fb_helper_prepare(dev, fb_helper, &drm_fb_helper_generic_funcs);
+
+ ret = drm_fb_helper_init(dev, fb_helper);
+ if (ret)
+ goto err;
+
+ if (!drm_drv_uses_atomic_modeset(dev))
+ drm_helper_disable_unused_functions(dev);
+
+ ret = drm_fb_helper_initial_config(fb_helper, fb_helper->preferred_bpp);
+ if (ret)
+ goto err_cleanup;
+
+ return 0;
+
+err_cleanup:
+ drm_fbdev_cleanup(fb_helper);
+err:
+ fb_helper->dev = NULL;
+ fb_helper->info = NULL;
+
+ drm_err(dev, "fbdev: Failed to setup generic emulation (ret=%d)\n", ret);
+
+ return ret;
+}
+
+static const struct drm_client_funcs drm_fbdev_client_funcs = {
+ .owner = THIS_MODULE,
+ .unregister = drm_fbdev_client_unregister,
+ .restore = drm_fbdev_client_restore,
+ .hotplug = drm_fbdev_client_hotplug,
+};
+
+/**
+ * drm_fbdev_generic_setup() - Setup generic fbdev emulation
+ * @dev: DRM device
+ * @preferred_bpp: Preferred bits per pixel for the device.
+ * @dev->mode_config.preferred_depth is used if this is zero.
+ *
+ * This function sets up generic fbdev emulation for drivers that supports
+ * dumb buffers with a virtual address and that can be mmap'ed.
+ * drm_fbdev_generic_setup() shall be called after the DRM driver registered
+ * the new DRM device with drm_dev_register().
+ *
+ * Restore, hotplug events and teardown are all taken care of. Drivers that do
+ * suspend/resume need to call drm_fb_helper_set_suspend_unlocked() themselves.
+ * Simple drivers might use drm_mode_config_helper_suspend().
+ *
+ * Drivers that set the dirty callback on their framebuffer will get a shadow
+ * fbdev buffer that is blitted onto the real buffer. This is done in order to
+ * make deferred I/O work with all kinds of buffers. A shadow buffer can be
+ * requested explicitly by setting struct drm_mode_config.prefer_shadow or
+ * struct drm_mode_config.prefer_shadow_fbdev to true beforehand. This is
+ * required to use generic fbdev emulation with SHMEM helpers.
+ *
+ * This function is safe to call even when there are no connectors present.
+ * Setup will be retried on the next hotplug event.
+ *
+ * The fbdev is destroyed by drm_dev_unregister().
+ */
+void drm_fbdev_generic_setup(struct drm_device *dev,
+ unsigned int preferred_bpp)
+{
+ struct drm_fb_helper *fb_helper;
+ int ret;
+
+ drm_WARN(dev, !dev->registered, "Device has not been registered.\n");
+ drm_WARN(dev, dev->fb_helper, "fb_helper is already set!\n");
+
+ fb_helper = kzalloc(sizeof(*fb_helper), GFP_KERNEL);
+ if (!fb_helper)
+ return;
+
+ ret = drm_client_init(dev, &fb_helper->client, "fbdev", &drm_fbdev_client_funcs);
+ if (ret) {
+ kfree(fb_helper);
+ drm_err(dev, "Failed to register client: %d\n", ret);
+ return;
+ }
+
+ /*
+ * FIXME: This mixes up depth with bpp, which results in a glorious
+ * mess, resulting in some drivers picking wrong fbdev defaults and
+ * others wrong preferred_depth defaults.
+ */
+ if (!preferred_bpp)
+ preferred_bpp = dev->mode_config.preferred_depth;
+ if (!preferred_bpp)
+ preferred_bpp = 32;
+ fb_helper->preferred_bpp = preferred_bpp;
+
+ ret = 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);
+}
+EXPORT_SYMBOL(drm_fbdev_generic_setup);
diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c
index a8b4d918e9a3..64b4a3a87fbb 100644
--- a/drivers/gpu/drm/drm_file.c
+++ b/drivers/gpu/drm/drm_file.c
@@ -326,7 +326,7 @@ static int drm_cpu_valid(void)
* Creates and initializes a drm_file structure for the file private data in \p
* filp and add it into the double linked list in \p dev.
*/
-static int drm_open_helper(struct file *filp, struct drm_minor *minor)
+int drm_open_helper(struct file *filp, struct drm_minor *minor)
{
struct drm_device *dev = minor->dev;
struct drm_file *priv;
diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c
index 3ee59bae9d2f..74ff33c2ddaa 100644
--- a/drivers/gpu/drm/drm_format_helper.c
+++ b/drivers/gpu/drm/drm_format_helper.c
@@ -660,6 +660,11 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d
drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, false);
return 0;
}
+ } else if (dst_format == (DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN)) {
+ if (fb_format == DRM_FORMAT_RGB565) {
+ drm_fb_swab(dst, dst_pitch, src, fb, clip, false);
+ return 0;
+ }
} else if (dst_format == DRM_FORMAT_RGB888) {
if (fb_format == DRM_FORMAT_XRGB8888) {
drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip);
@@ -678,6 +683,11 @@ int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t d
drm_fb_xrgb8888_to_xrgb2101010(dst, dst_pitch, src, fb, clip);
return 0;
}
+ } else if (dst_format == DRM_FORMAT_BGRX8888) {
+ if (fb_format == DRM_FORMAT_XRGB8888) {
+ drm_fb_swab(dst, dst_pitch, src, fb, clip, false);
+ return 0;
+ }
}
drm_warn_once(fb->dev, "No conversion helper from %p4cc to %p4cc found.\n",
diff --git a/drivers/gpu/drm/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c
index e09331bb3bc7..6242dfbe9240 100644
--- a/drivers/gpu/drm/drm_fourcc.c
+++ b/drivers/gpu/drm/drm_fourcc.c
@@ -297,12 +297,12 @@ const struct drm_format_info *__drm_format_info(u32 format)
.vsub = 2, .is_yuv = true },
{ .format = DRM_FORMAT_Q410, .depth = 0,
.num_planes = 3, .char_per_block = { 2, 2, 2 },
- .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 0,
- .vsub = 0, .is_yuv = true },
+ .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 1,
+ .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_Q401, .depth = 0,
.num_planes = 3, .char_per_block = { 2, 2, 2 },
- .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 0,
- .vsub = 0, .is_yuv = true },
+ .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 }, .hsub = 1,
+ .vsub = 1, .is_yuv = true },
{ .format = DRM_FORMAT_P030, .depth = 0, .num_planes = 2,
.char_per_block = { 4, 8, 0 }, .block_w = { 3, 3, 0 }, .block_h = { 1, 1, 0 },
.hsub = 2, .vsub = 2, .is_yuv = true},
diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index 8b68a3c1e6ab..b8db675e7fb5 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -1158,6 +1158,8 @@ int drm_gem_vmap(struct drm_gem_object *obj, struct iosys_map *map)
{
int ret;
+ dma_resv_assert_held(obj->resv);
+
if (!obj->funcs->vmap)
return -EOPNOTSUPP;
@@ -1173,6 +1175,8 @@ EXPORT_SYMBOL(drm_gem_vmap);
void drm_gem_vunmap(struct drm_gem_object *obj, struct iosys_map *map)
{
+ dma_resv_assert_held(obj->resv);
+
if (iosys_map_is_null(map))
return;
@@ -1184,6 +1188,26 @@ void drm_gem_vunmap(struct drm_gem_object *obj, struct iosys_map *map)
}
EXPORT_SYMBOL(drm_gem_vunmap);
+int drm_gem_vmap_unlocked(struct drm_gem_object *obj, struct iosys_map *map)
+{
+ int ret;
+
+ dma_resv_lock(obj->resv, NULL);
+ ret = drm_gem_vmap(obj, map);
+ dma_resv_unlock(obj->resv);
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_gem_vmap_unlocked);
+
+void drm_gem_vunmap_unlocked(struct drm_gem_object *obj, struct iosys_map *map)
+{
+ dma_resv_lock(obj->resv, NULL);
+ drm_gem_vunmap(obj, map);
+ dma_resv_unlock(obj->resv);
+}
+EXPORT_SYMBOL(drm_gem_vunmap_unlocked);
+
/**
* drm_gem_lock_reservations - Sets up the ww context and acquires
* the lock on an array of GEM objects.
diff --git a/drivers/gpu/drm/drm_gem_atomic_helper.c b/drivers/gpu/drm/drm_gem_atomic_helper.c
index b6a0110eb64a..e42800718f51 100644
--- a/drivers/gpu/drm/drm_gem_atomic_helper.c
+++ b/drivers/gpu/drm/drm_gem_atomic_helper.c
@@ -360,48 +360,43 @@ void drm_gem_reset_shadow_plane(struct drm_plane *plane)
EXPORT_SYMBOL(drm_gem_reset_shadow_plane);
/**
- * drm_gem_prepare_shadow_fb - prepares shadow framebuffers
+ * drm_gem_begin_shadow_fb_access - prepares shadow framebuffers for CPU access
* @plane: the plane
* @plane_state: the plane state of type struct drm_shadow_plane_state
*
- * This function implements struct &drm_plane_helper_funcs.prepare_fb. It
+ * This function implements struct &drm_plane_helper_funcs.begin_fb_access. It
* maps all buffer objects of the plane's framebuffer into kernel address
- * space and stores them in &struct drm_shadow_plane_state.map. The
- * framebuffer will be synchronized as part of the atomic commit.
+ * space and stores them in struct &drm_shadow_plane_state.map. The first data
+ * bytes are available in struct &drm_shadow_plane_state.data.
*
- * See drm_gem_cleanup_shadow_fb() for cleanup.
+ * See drm_gem_end_shadow_fb_access() for cleanup.
*
* Returns:
* 0 on success, or a negative errno code otherwise.
*/
-int drm_gem_prepare_shadow_fb(struct drm_plane *plane, struct drm_plane_state *plane_state)
+int drm_gem_begin_shadow_fb_access(struct drm_plane *plane, struct drm_plane_state *plane_state)
{
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_framebuffer *fb = plane_state->fb;
- int ret;
if (!fb)
return 0;
- ret = drm_gem_plane_helper_prepare_fb(plane, plane_state);
- if (ret)
- return ret;
-
return drm_gem_fb_vmap(fb, shadow_plane_state->map, shadow_plane_state->data);
}
-EXPORT_SYMBOL(drm_gem_prepare_shadow_fb);
+EXPORT_SYMBOL(drm_gem_begin_shadow_fb_access);
/**
- * drm_gem_cleanup_shadow_fb - releases shadow framebuffers
+ * drm_gem_end_shadow_fb_access - releases shadow framebuffers from CPU access
* @plane: the plane
* @plane_state: the plane state of type struct drm_shadow_plane_state
*
- * This function implements struct &drm_plane_helper_funcs.cleanup_fb.
- * This function unmaps all buffer objects of the plane's framebuffer.
+ * This function implements struct &drm_plane_helper_funcs.end_fb_access. It
+ * undoes all effects of drm_gem_begin_shadow_fb_access() in reverse order.
*
- * See drm_gem_prepare_shadow_fb() for more information.
+ * See drm_gem_begin_shadow_fb_access() for more information.
*/
-void drm_gem_cleanup_shadow_fb(struct drm_plane *plane, struct drm_plane_state *plane_state)
+void drm_gem_end_shadow_fb_access(struct drm_plane *plane, struct drm_plane_state *plane_state)
{
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
struct drm_framebuffer *fb = plane_state->fb;
@@ -411,46 +406,45 @@ void drm_gem_cleanup_shadow_fb(struct drm_plane *plane, struct drm_plane_state *
drm_gem_fb_vunmap(fb, shadow_plane_state->map);
}
-EXPORT_SYMBOL(drm_gem_cleanup_shadow_fb);
+EXPORT_SYMBOL(drm_gem_end_shadow_fb_access);
/**
- * drm_gem_simple_kms_prepare_shadow_fb - prepares shadow framebuffers
+ * drm_gem_simple_kms_begin_shadow_fb_access - prepares shadow framebuffers for CPU access
* @pipe: the simple display pipe
* @plane_state: the plane state of type struct drm_shadow_plane_state
*
- * This function implements struct drm_simple_display_funcs.prepare_fb. It
- * maps all buffer objects of the plane's framebuffer into kernel address
- * space and stores them in struct drm_shadow_plane_state.map. The
- * framebuffer will be synchronized as part of the atomic commit.
+ * This function implements struct drm_simple_display_funcs.begin_fb_access.
*
- * See drm_gem_simple_kms_cleanup_shadow_fb() for cleanup.
+ * See drm_gem_begin_shadow_fb_access() for details and
+ * drm_gem_simple_kms_cleanup_shadow_fb() for cleanup.
*
* Returns:
* 0 on success, or a negative errno code otherwise.
*/
-int drm_gem_simple_kms_prepare_shadow_fb(struct drm_simple_display_pipe *pipe,
- struct drm_plane_state *plane_state)
+int drm_gem_simple_kms_begin_shadow_fb_access(struct drm_simple_display_pipe *pipe,
+ struct drm_plane_state *plane_state)
{
- return drm_gem_prepare_shadow_fb(&pipe->plane, plane_state);
+ return drm_gem_begin_shadow_fb_access(&pipe->plane, plane_state);
}
-EXPORT_SYMBOL(drm_gem_simple_kms_prepare_shadow_fb);
+EXPORT_SYMBOL(drm_gem_simple_kms_begin_shadow_fb_access);
/**
- * drm_gem_simple_kms_cleanup_shadow_fb - releases shadow framebuffers
+ * drm_gem_simple_kms_end_shadow_fb_access - releases shadow framebuffers from CPU access
* @pipe: the simple display pipe
* @plane_state: the plane state of type struct drm_shadow_plane_state
*
- * This function implements struct drm_simple_display_funcs.cleanup_fb.
- * This function unmaps all buffer objects of the plane's framebuffer.
+ * This function implements struct drm_simple_display_funcs.end_fb_access.
+ * It undoes all effects of drm_gem_simple_kms_begin_shadow_fb_access() in
+ * reverse order.
*
- * See drm_gem_simple_kms_prepare_shadow_fb().
+ * See drm_gem_simple_kms_begin_shadow_fb_access().
*/
-void drm_gem_simple_kms_cleanup_shadow_fb(struct drm_simple_display_pipe *pipe,
- struct drm_plane_state *plane_state)
+void drm_gem_simple_kms_end_shadow_fb_access(struct drm_simple_display_pipe *pipe,
+ struct drm_plane_state *plane_state)
{
- drm_gem_cleanup_shadow_fb(&pipe->plane, plane_state);
+ drm_gem_end_shadow_fb_access(&pipe->plane, plane_state);
}
-EXPORT_SYMBOL(drm_gem_simple_kms_cleanup_shadow_fb);
+EXPORT_SYMBOL(drm_gem_simple_kms_end_shadow_fb_access);
/**
* drm_gem_simple_kms_reset_shadow_plane - resets a shadow-buffered plane
diff --git a/drivers/gpu/drm/drm_gem_dma_helper.c b/drivers/gpu/drm/drm_gem_dma_helper.c
index f6901ff97bbb..1e658c448366 100644
--- a/drivers/gpu/drm/drm_gem_dma_helper.c
+++ b/drivers/gpu/drm/drm_gem_dma_helper.c
@@ -230,7 +230,7 @@ void drm_gem_dma_free(struct drm_gem_dma_object *dma_obj)
if (gem_obj->import_attach) {
if (dma_obj->vaddr)
- dma_buf_vunmap(gem_obj->import_attach->dmabuf, &map);
+ dma_buf_vunmap_unlocked(gem_obj->import_attach->dmabuf, &map);
drm_prime_gem_destroy(gem_obj, dma_obj->sgt);
} else if (dma_obj->vaddr) {
if (dma_obj->map_noncoherent)
@@ -581,7 +581,7 @@ drm_gem_dma_prime_import_sg_table_vmap(struct drm_device *dev,
struct iosys_map map;
int ret;
- ret = dma_buf_vmap(attach->dmabuf, &map);
+ ret = dma_buf_vmap_unlocked(attach->dmabuf, &map);
if (ret) {
DRM_ERROR("Failed to vmap PRIME buffer\n");
return ERR_PTR(ret);
@@ -589,7 +589,7 @@ drm_gem_dma_prime_import_sg_table_vmap(struct drm_device *dev,
obj = drm_gem_dma_prime_import_sg_table(dev, attach, sgt);
if (IS_ERR(obj)) {
- dma_buf_vunmap(attach->dmabuf, &map);
+ dma_buf_vunmap_unlocked(attach->dmabuf, &map);
return obj;
}
diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
index 880a4975507f..e93533b86037 100644
--- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
+++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
@@ -9,7 +9,6 @@
#include <linux/module.h>
#include <drm/drm_damage_helper.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem.h>
@@ -354,7 +353,7 @@ int drm_gem_fb_vmap(struct drm_framebuffer *fb, struct iosys_map *map,
ret = -EINVAL;
goto err_drm_gem_vunmap;
}
- ret = drm_gem_vmap(obj, &map[i]);
+ ret = drm_gem_vmap_unlocked(obj, &map[i]);
if (ret)
goto err_drm_gem_vunmap;
}
@@ -376,7 +375,7 @@ err_drm_gem_vunmap:
obj = drm_gem_fb_get_obj(fb, i);
if (!obj)
continue;
- drm_gem_vunmap(obj, &map[i]);
+ drm_gem_vunmap_unlocked(obj, &map[i]);
}
return ret;
}
@@ -403,7 +402,7 @@ void drm_gem_fb_vunmap(struct drm_framebuffer *fb, struct iosys_map *map)
continue;
if (iosys_map_is_null(&map[i]))
continue;
- drm_gem_vunmap(obj, &map[i]);
+ drm_gem_vunmap_unlocked(obj, &map[i]);
}
}
EXPORT_SYMBOL(drm_gem_fb_vunmap);
diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c
index 35138f8a375c..b602cd72a120 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -571,12 +571,20 @@ static void drm_gem_shmem_vm_open(struct vm_area_struct *vma)
{
struct drm_gem_object *obj = vma->vm_private_data;
struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(obj);
- int ret;
WARN_ON(shmem->base.import_attach);
- ret = drm_gem_shmem_get_pages(shmem);
- WARN_ON_ONCE(ret != 0);
+ mutex_lock(&shmem->pages_lock);
+
+ /*
+ * We should have already pinned the pages when the buffer was first
+ * mmap'd, vm_open() just grabs an additional reference for the new
+ * mm the vma is getting copied into (ie. on fork()).
+ */
+ if (!WARN_ON_ONCE(!shmem->pages_use_count))
+ shmem->pages_use_count++;
+
+ mutex_unlock(&shmem->pages_lock);
drm_gem_vm_open(vma);
}
@@ -622,10 +630,8 @@ int drm_gem_shmem_mmap(struct drm_gem_shmem_object *shmem, struct vm_area_struct
}
ret = drm_gem_shmem_get_pages(shmem);
- if (ret) {
- drm_gem_vm_close(vma);
+ if (ret)
return ret;
- }
vma->vm_flags |= VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
diff --git a/drivers/gpu/drm/drm_gem_ttm_helper.c b/drivers/gpu/drm/drm_gem_ttm_helper.c
index e5fc875990c4..d5962a34c01d 100644
--- a/drivers/gpu/drm/drm_gem_ttm_helper.c
+++ b/drivers/gpu/drm/drm_gem_ttm_helper.c
@@ -64,13 +64,8 @@ int drm_gem_ttm_vmap(struct drm_gem_object *gem,
struct iosys_map *map)
{
struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gem);
- int ret;
-
- dma_resv_lock(gem->resv, NULL);
- ret = ttm_bo_vmap(bo, map);
- dma_resv_unlock(gem->resv);
- return ret;
+ return ttm_bo_vmap(bo, map);
}
EXPORT_SYMBOL(drm_gem_ttm_vmap);
@@ -87,9 +82,7 @@ void drm_gem_ttm_vunmap(struct drm_gem_object *gem,
{
struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gem);
- dma_resv_lock(gem->resv, NULL);
ttm_bo_vunmap(bo, map);
- dma_resv_unlock(gem->resv);
}
EXPORT_SYMBOL(drm_gem_ttm_vunmap);
diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c
index 125160b534be..b6c7e3803bb3 100644
--- a/drivers/gpu/drm/drm_gem_vram_helper.c
+++ b/drivers/gpu/drm/drm_gem_vram_helper.c
@@ -433,25 +433,19 @@ int drm_gem_vram_vmap(struct drm_gem_vram_object *gbo, struct iosys_map *map)
{
int ret;
- ret = ttm_bo_reserve(&gbo->bo, true, false, NULL);
- if (ret)
- return ret;
+ dma_resv_assert_held(gbo->bo.base.resv);
ret = drm_gem_vram_pin_locked(gbo, 0);
if (ret)
- goto err_ttm_bo_unreserve;
+ return ret;
ret = drm_gem_vram_kmap_locked(gbo, map);
if (ret)
goto err_drm_gem_vram_unpin_locked;
- ttm_bo_unreserve(&gbo->bo);
-
return 0;
err_drm_gem_vram_unpin_locked:
drm_gem_vram_unpin_locked(gbo);
-err_ttm_bo_unreserve:
- ttm_bo_unreserve(&gbo->bo);
return ret;
}
EXPORT_SYMBOL(drm_gem_vram_vmap);
@@ -467,16 +461,10 @@ EXPORT_SYMBOL(drm_gem_vram_vmap);
void drm_gem_vram_vunmap(struct drm_gem_vram_object *gbo,
struct iosys_map *map)
{
- int ret;
-
- ret = ttm_bo_reserve(&gbo->bo, false, false, NULL);
- if (WARN_ONCE(ret, "ttm_bo_reserve_failed(): ret=%d\n", ret))
- return;
+ dma_resv_assert_held(gbo->bo.base.resv);
drm_gem_vram_kunmap_locked(gbo, map);
drm_gem_vram_unpin_locked(gbo);
-
- ttm_bo_unreserve(&gbo->bo);
}
EXPORT_SYMBOL(drm_gem_vram_vunmap);
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 3ec02748d56f..497ef4b6a90a 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -606,7 +606,7 @@ int mipi_dsi_turn_on_peripheral(struct mipi_dsi_device *dsi)
EXPORT_SYMBOL(mipi_dsi_turn_on_peripheral);
/*
- * mipi_dsi_set_maximum_return_packet_size() - specify the maximum size of the
+ * mipi_dsi_set_maximum_return_packet_size() - specify the maximum size of
* the payload in a long packet transmitted from the peripheral back to the
* host processor
* @dsi: DSI peripheral device
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 304004fb80aa..3c8034a8c27b 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1750,11 +1750,78 @@ static int drm_mode_parse_cmdline_options(const char *str,
return 0;
}
-static const char * const drm_named_modes_whitelist[] = {
- "NTSC",
- "PAL",
+struct drm_named_mode {
+ const char *name;
+ unsigned int pixel_clock_khz;
+ unsigned int xres;
+ unsigned int yres;
+ unsigned int flags;
+};
+
+#define NAMED_MODE(_name, _pclk, _x, _y, _flags) \
+ { \
+ .name = _name, \
+ .pixel_clock_khz = _pclk, \
+ .xres = _x, \
+ .yres = _y, \
+ .flags = _flags, \
+ }
+
+static const struct drm_named_mode drm_named_modes[] = {
+ NAMED_MODE("NTSC", 13500, 720, 480, DRM_MODE_FLAG_INTERLACE),
+ NAMED_MODE("PAL", 13500, 720, 576, DRM_MODE_FLAG_INTERLACE),
};
+static int drm_mode_parse_cmdline_named_mode(const char *name,
+ unsigned int name_end,
+ struct drm_cmdline_mode *cmdline_mode)
+{
+ unsigned int i;
+
+ if (!name_end)
+ return 0;
+
+ /* If the name starts with a digit, it's not a named mode */
+ if (isdigit(name[0]))
+ return 0;
+
+ /*
+ * If there's an equal sign in the name, the command-line
+ * contains only an option and no mode.
+ */
+ if (strnchr(name, name_end, '='))
+ return 0;
+
+ /* The connection status extras can be set without a mode. */
+ if (name_end == 1 &&
+ (name[0] == 'd' || name[0] == 'D' || name[0] == 'e'))
+ return 0;
+
+ /*
+ * We're sure we're a named mode at this point, iterate over the
+ * list of modes we're aware of.
+ */
+ for (i = 0; i < ARRAY_SIZE(drm_named_modes); i++) {
+ const struct drm_named_mode *mode = &drm_named_modes[i];
+ int ret;
+
+ ret = str_has_prefix(name, mode->name);
+ if (ret != name_end)
+ continue;
+
+ strcpy(cmdline_mode->name, mode->name);
+ cmdline_mode->pixel_clock = mode->pixel_clock_khz;
+ cmdline_mode->xres = mode->xres;
+ cmdline_mode->yres = mode->yres;
+ cmdline_mode->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
+ cmdline_mode->specified = true;
+
+ return 1;
+ }
+
+ return -EINVAL;
+}
+
/**
* drm_mode_parse_command_line_for_connector - parse command line modeline for connector
* @mode_option: optional per connector mode option
@@ -1791,7 +1858,7 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
const char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL;
const char *options_ptr = NULL;
char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL;
- int i, len, ret;
+ int len, ret;
memset(mode, 0, sizeof(*mode));
mode->panel_orientation = DRM_MODE_PANEL_ORIENTATION_UNKNOWN;
@@ -1801,20 +1868,24 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
name = mode_option;
+ /* Locate the start of named options */
+ options_ptr = strchr(name, ',');
+ if (options_ptr)
+ options_off = options_ptr - name;
+ else
+ options_off = strlen(name);
+
/* Try to locate the bpp and refresh specifiers, if any */
- bpp_ptr = strchr(name, '-');
+ bpp_ptr = strnchr(name, options_off, '-');
+ while (bpp_ptr && !isdigit(bpp_ptr[1]))
+ bpp_ptr = strnchr(bpp_ptr + 1, options_off, '-');
if (bpp_ptr)
bpp_off = bpp_ptr - name;
- refresh_ptr = strchr(name, '@');
+ refresh_ptr = strnchr(name, options_off, '@');
if (refresh_ptr)
refresh_off = refresh_ptr - name;
- /* Locate the start of named options */
- options_ptr = strchr(name, ',');
- if (options_ptr)
- options_off = options_ptr - name;
-
/* Locate the end of the name / resolution, and parse it */
if (bpp_ptr) {
mode_end = bpp_off;
@@ -1828,18 +1899,19 @@ bool drm_mode_parse_command_line_for_connector(const char *mode_option,
parse_extras = true;
}
- /* First check for a named mode */
- for (i = 0; i < ARRAY_SIZE(drm_named_modes_whitelist); i++) {
- ret = str_has_prefix(name, drm_named_modes_whitelist[i]);
- if (ret == mode_end) {
- if (refresh_ptr)
- return false; /* named + refresh is invalid */
+ if (!mode_end)
+ return false;
- strcpy(mode->name, drm_named_modes_whitelist[i]);
- mode->specified = true;
- break;
- }
- }
+ ret = drm_mode_parse_cmdline_named_mode(name, mode_end, mode);
+ if (ret < 0)
+ return false;
+
+ /*
+ * Having a mode that starts by a letter (and thus is named) and
+ * an at-sign (used to specify a refresh rate) is disallowed.
+ */
+ if (ret && refresh_ptr)
+ return false;
/* No named mode? Check for a normal mode argument, e.g. 1024x768 */
if (!mode->specified && isdigit(name[0])) {
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index 865bd999b187..ba6a9136a065 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -298,7 +298,9 @@ EXPORT_SYMBOL(drm_plane_helper_destroy);
* scale and positioning are not expected to change since the plane is always
* a fullscreen scanout buffer.
*
- * This is often the case for the primary plane of simple framebuffers.
+ * This is often the case for the primary plane of simple framebuffers. See
+ * also drm_crtc_helper_atomic_check() for the respective CRTC-state check
+ * helper function.
*
* RETURNS:
* Zero on success, or an errno code otherwise.
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index eb09e86044c6..f924b8b4ab6b 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -781,6 +781,8 @@ int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma)
struct drm_gem_object *obj = dma_buf->priv;
struct drm_device *dev = obj->dev;
+ dma_resv_assert_held(dma_buf->resv);
+
if (!dev->driver->gem_prime_mmap)
return -ENOSYS;
@@ -940,7 +942,7 @@ struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
get_dma_buf(dma_buf);
- sgt = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
+ sgt = dma_buf_map_attachment_unlocked(attach, DMA_BIDIRECTIONAL);
if (IS_ERR(sgt)) {
ret = PTR_ERR(sgt);
goto fail_detach;
@@ -958,7 +960,7 @@ struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev,
return obj;
fail_unmap:
- dma_buf_unmap_attachment(attach, sgt, DMA_BIDIRECTIONAL);
+ dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_BIDIRECTIONAL);
fail_detach:
dma_buf_detach(dma_buf, attach);
dma_buf_put(dma_buf);
@@ -1056,7 +1058,7 @@ void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg)
attach = obj->import_attach;
if (sg)
- dma_buf_unmap_attachment(attach, sg, DMA_BIDIRECTIONAL);
+ dma_buf_unmap_attachment_unlocked(attach, sg, DMA_BIDIRECTIONAL);
dma_buf = attach->dmabuf;
dma_buf_detach(attach->dmabuf, attach);
/* remove the reference */
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index 69b0b2b9cc1c..bcd9611dabfd 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -36,7 +36,6 @@
#include <drm/drm_client.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_modeset_helper_vtables.h>
#include <drm/drm_print.h>
@@ -367,7 +366,7 @@ static int drm_helper_probe_get_modes(struct drm_connector *connector)
* override/firmware EDID.
*/
if (count == 0 && connector->status == connector_status_connected)
- count = drm_add_override_edid_modes(connector);
+ count = drm_edid_override_connector_update(connector);
return count;
}
diff --git a/drivers/gpu/drm/drm_rect.c b/drivers/gpu/drm/drm_rect.c
index 0460e874896e..85c79a38c13a 100644
--- a/drivers/gpu/drm/drm_rect.c
+++ b/drivers/gpu/drm/drm_rect.c
@@ -80,7 +80,7 @@ static u32 clip_scaled(int src, int dst, int *clip)
* @dst: destination window rectangle
* @clip: clip rectangle
*
- * Clip rectangle @dst by rectangle @clip. Clip rectangle @src by the
+ * Clip rectangle @dst by rectangle @clip. Clip rectangle @src by
* the corresponding amounts, retaining the vertical and horizontal scaling
* factors from @src to @dst.
*
diff --git a/drivers/gpu/drm/drm_simple_kms_helper.c b/drivers/gpu/drm/drm_simple_kms_helper.c
index e9f782119d3d..3ef420ec4534 100644
--- a/drivers/gpu/drm/drm_simple_kms_helper.c
+++ b/drivers/gpu/drm/drm_simple_kms_helper.c
@@ -102,10 +102,14 @@ static int drm_simple_kms_crtc_check(struct drm_crtc *crtc,
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
int ret;
- ret = drm_atomic_helper_check_crtc_state(crtc_state, false);
+ if (!crtc_state->enable)
+ goto out;
+
+ ret = drm_atomic_helper_check_crtc_primary_plane(crtc_state);
if (ret)
return ret;
+out:
return drm_atomic_add_affected_planes(state, crtc);
}
@@ -281,6 +285,30 @@ static void drm_simple_kms_plane_cleanup_fb(struct drm_plane *plane,
pipe->funcs->cleanup_fb(pipe, state);
}
+static int drm_simple_kms_plane_begin_fb_access(struct drm_plane *plane,
+ struct drm_plane_state *new_plane_state)
+{
+ struct drm_simple_display_pipe *pipe;
+
+ pipe = container_of(plane, struct drm_simple_display_pipe, plane);
+ if (!pipe->funcs || !pipe->funcs->begin_fb_access)
+ return 0;
+
+ return pipe->funcs->begin_fb_access(pipe, new_plane_state);
+}
+
+static void drm_simple_kms_plane_end_fb_access(struct drm_plane *plane,
+ struct drm_plane_state *new_plane_state)
+{
+ struct drm_simple_display_pipe *pipe;
+
+ pipe = container_of(plane, struct drm_simple_display_pipe, plane);
+ if (!pipe->funcs || !pipe->funcs->end_fb_access)
+ return;
+
+ pipe->funcs->end_fb_access(pipe, new_plane_state);
+}
+
static bool drm_simple_kms_format_mod_supported(struct drm_plane *plane,
uint32_t format,
uint64_t modifier)
@@ -291,6 +319,8 @@ static bool drm_simple_kms_format_mod_supported(struct drm_plane *plane,
static const struct drm_plane_helper_funcs drm_simple_kms_plane_helper_funcs = {
.prepare_fb = drm_simple_kms_plane_prepare_fb,
.cleanup_fb = drm_simple_kms_plane_cleanup_fb,
+ .begin_fb_access = drm_simple_kms_plane_begin_fb_access,
+ .end_fb_access = drm_simple_kms_plane_end_fb_access,
.atomic_check = drm_simple_kms_plane_atomic_check,
.atomic_update = drm_simple_kms_plane_atomic_update,
};
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 430e00b16eec..b8da978d85bb 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -19,6 +19,7 @@
#include <linux/kdev_t.h>
#include <linux/slab.h>
+#include <drm/drm_accel.h>
#include <drm/drm_connector.h>
#include <drm/drm_device.h>
#include <drm/drm_file.h>
@@ -471,19 +472,26 @@ struct device *drm_sysfs_minor_alloc(struct drm_minor *minor)
struct device *kdev;
int r;
- if (minor->type == DRM_MINOR_RENDER)
- minor_str = "renderD%d";
- else
- minor_str = "card%d";
-
kdev = kzalloc(sizeof(*kdev), GFP_KERNEL);
if (!kdev)
return ERR_PTR(-ENOMEM);
device_initialize(kdev);
- kdev->devt = MKDEV(DRM_MAJOR, minor->index);
- kdev->class = drm_class;
- kdev->type = &drm_sysfs_device_minor;
+
+ if (minor->type == DRM_MINOR_ACCEL) {
+ minor_str = "accel%d";
+ accel_set_device_instance_params(kdev, minor->index);
+ } else {
+ if (minor->type == DRM_MINOR_RENDER)
+ minor_str = "renderD%d";
+ else
+ minor_str = "card%d";
+
+ kdev->devt = MKDEV(DRM_MAJOR, minor->index);
+ kdev->class = drm_class;
+ kdev->type = &drm_sysfs_device_minor;
+ }
+
kdev->parent = minor->dev->dev;
kdev->release = drm_sysfs_release;
dev_set_drvdata(kdev, minor);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
index f32f4771dada..2bb4c25565dc 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h
@@ -6,13 +6,14 @@
#ifndef __ETNAVIV_DRV_H__
#define __ETNAVIV_DRV_H__
+#include <linux/io.h>
#include <linux/list.h>
#include <linux/mm_types.h>
#include <linux/sizes.h>
#include <linux/time64.h>
#include <linux/types.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_drv.h>
#include <drm/drm_gem.h>
#include <drm/etnaviv_drm.h>
#include <drm/gpu_scheduler.h>
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_dump.c b/drivers/gpu/drm/etnaviv/etnaviv_dump.c
index f418e0b75772..44b5f3c35aab 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_dump.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_dump.c
@@ -83,10 +83,15 @@ static void etnaviv_core_dump_registers(struct core_dump_iterator *iter,
{
struct etnaviv_dump_registers *reg = iter->data;
unsigned int i;
+ u32 read_addr;
for (i = 0; i < ARRAY_SIZE(etnaviv_dump_registers); i++, reg++) {
+ read_addr = etnaviv_dump_registers[i];
+ if (read_addr >= VIVS_PM_POWER_CONTROLS &&
+ read_addr <= VIVS_PM_PULSE_EATER)
+ read_addr = gpu_fix_power_address(gpu, read_addr);
reg->reg = cpu_to_le32(etnaviv_dump_registers[i]);
- reg->value = cpu_to_le32(gpu_read(gpu, etnaviv_dump_registers[i]));
+ reg->value = cpu_to_le32(gpu_read(gpu, read_addr));
}
etnaviv_core_dump_header(iter, ETDUMP_BUF_REG, reg);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
index cc386f8a7116..68e4446a94ad 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c
@@ -130,7 +130,7 @@ static int etnaviv_gem_mmap_obj(struct etnaviv_gem_object *etnaviv_obj,
{
pgprot_t vm_page_prot;
- vma->vm_flags |= VM_IO | VM_MIXEDMAP | VM_DONTEXPAND | VM_DONTDUMP;
+ vma->vm_flags |= VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
vm_page_prot = vm_get_page_prot(vma->vm_flags);
@@ -165,7 +165,8 @@ static vm_fault_t etnaviv_gem_fault(struct vm_fault *vmf)
struct vm_area_struct *vma = vmf->vma;
struct drm_gem_object *obj = vma->vm_private_data;
struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj);
- struct page **pages, *page;
+ struct page **pages;
+ unsigned long pfn;
pgoff_t pgoff;
int err;
@@ -189,12 +190,12 @@ static vm_fault_t etnaviv_gem_fault(struct vm_fault *vmf)
/* We don't use vmf->pgoff since that has the fake offset: */
pgoff = (vmf->address - vma->vm_start) >> PAGE_SHIFT;
- page = pages[pgoff];
+ pfn = page_to_pfn(pages[pgoff]);
VERB("Inserting %p pfn %lx, pa %lx", (void *)vmf->address,
- page_to_pfn(page), page_to_pfn(page) << PAGE_SHIFT);
+ pfn, pfn << PAGE_SHIFT);
- return vmf_insert_page(vma, vmf->address, page);
+ return vmf_insert_pfn(vma, vmf->address, pfn);
}
int etnaviv_gem_mmap_offset(struct drm_gem_object *obj, u64 *offset)
@@ -258,7 +259,12 @@ struct etnaviv_vram_mapping *etnaviv_gem_mapping_get(
if (mapping->use == 0) {
mutex_lock(&mmu_context->lock);
if (mapping->context == mmu_context)
- mapping->use += 1;
+ if (va && mapping->iova != va) {
+ etnaviv_iommu_reap_mapping(mapping);
+ mapping = NULL;
+ } else {
+ mapping->use += 1;
+ }
else
mapping = NULL;
mutex_unlock(&mmu_context->lock);
@@ -504,7 +510,6 @@ void etnaviv_gem_free_object(struct drm_gem_object *obj)
kfree(mapping);
}
- drm_gem_free_mmap_offset(obj);
etnaviv_obj->ops->release(etnaviv_obj);
drm_gem_object_release(obj);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.h b/drivers/gpu/drm/etnaviv/etnaviv_gem.h
index 63688e6e4580..baa81cbf701a 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.h
@@ -96,6 +96,7 @@ struct etnaviv_gem_submit {
int out_fence_id;
struct list_head node; /* GPU active submit list */
struct etnaviv_cmdbuf cmdbuf;
+ struct pid *pid; /* submitting process */
bool runtime_resumed;
u32 exec_state;
u32 flags;
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
index 3fa2da149639..7031db145a77 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
@@ -65,7 +65,7 @@ static void etnaviv_gem_prime_release(struct etnaviv_gem_object *etnaviv_obj)
struct iosys_map map = IOSYS_MAP_INIT_VADDR(etnaviv_obj->vaddr);
if (etnaviv_obj->vaddr)
- dma_buf_vunmap(etnaviv_obj->base.import_attach->dmabuf, &map);
+ dma_buf_vunmap_unlocked(etnaviv_obj->base.import_attach->dmabuf, &map);
/* Don't drop the pages for imported dmabuf, as they are not
* ours, just free the array we allocated:
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
index 1ac916b24891..1491159d0d20 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c
@@ -399,6 +399,9 @@ static void submit_cleanup(struct kref *kref)
mutex_unlock(&submit->gpu->fence_lock);
dma_fence_put(submit->out_fence);
}
+
+ put_pid(submit->pid);
+
kfree(submit->pmrs);
kfree(submit);
}
@@ -422,6 +425,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
struct sync_file *sync_file = NULL;
struct ww_acquire_ctx ticket;
int out_fence_fd = -1;
+ struct pid *pid = get_pid(task_pid(current));
void *stream;
int ret;
@@ -519,6 +523,8 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
goto err_submit_ww_acquire;
}
+ submit->pid = pid;
+
ret = etnaviv_cmdbuf_init(priv->cmdbuf_suballoc, &submit->cmdbuf,
ALIGN(args->stream_size, 8) + 8);
if (ret)
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index 37018bc55810..51320eeebfcf 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -416,6 +416,12 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu)
if (gpu->identity.model == chipModel_GC700)
gpu->identity.features &= ~chipFeatures_FAST_CLEAR;
+ /* These models/revisions don't have the 2D pipe bit */
+ if ((gpu->identity.model == chipModel_GC500 &&
+ gpu->identity.revision <= 2) ||
+ gpu->identity.model == chipModel_GC300)
+ gpu->identity.features |= chipFeatures_PIPE_2D;
+
if ((gpu->identity.model == chipModel_GC500 &&
gpu->identity.revision < 2) ||
(gpu->identity.model == chipModel_GC300 &&
@@ -449,8 +455,9 @@ static void etnaviv_hw_identify(struct etnaviv_gpu *gpu)
gpu_read(gpu, VIVS_HI_CHIP_MINOR_FEATURE_5);
}
- /* GC600 idle register reports zero bits where modules aren't present */
- if (gpu->identity.model == chipModel_GC600)
+ /* GC600/300 idle register reports zero bits where modules aren't present */
+ if (gpu->identity.model == chipModel_GC600 ||
+ gpu->identity.model == chipModel_GC300)
gpu->idle_mask = VIVS_HI_IDLE_STATE_TX |
VIVS_HI_IDLE_STATE_RA |
VIVS_HI_IDLE_STATE_SE |
@@ -583,7 +590,7 @@ static void etnaviv_gpu_enable_mlcg(struct etnaviv_gpu *gpu)
u32 pmc, ppc;
/* enable clock gating */
- ppc = gpu_read(gpu, VIVS_PM_POWER_CONTROLS);
+ ppc = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS);
ppc |= VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;
/* Disable stall module clock gating for 4.3.0.1 and 4.3.0.2 revs */
@@ -591,9 +598,9 @@ static void etnaviv_gpu_enable_mlcg(struct etnaviv_gpu *gpu)
gpu->identity.revision == 0x4302)
ppc |= VIVS_PM_POWER_CONTROLS_DISABLE_STALL_MODULE_CLOCK_GATING;
- gpu_write(gpu, VIVS_PM_POWER_CONTROLS, ppc);
+ gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, ppc);
- pmc = gpu_read(gpu, VIVS_PM_MODULE_CONTROLS);
+ pmc = gpu_read_power(gpu, VIVS_PM_MODULE_CONTROLS);
/* Disable PA clock gating for GC400+ without bugfix except for GC420 */
if (gpu->identity.model >= chipModel_GC400 &&
@@ -616,19 +623,20 @@ static void etnaviv_gpu_enable_mlcg(struct etnaviv_gpu *gpu)
/* Disable TX clock gating on affected core revisions. */
if (etnaviv_is_model_rev(gpu, GC4000, 0x5222) ||
- etnaviv_is_model_rev(gpu, GC2000, 0x5108))
+ etnaviv_is_model_rev(gpu, GC2000, 0x5108) ||
+ etnaviv_is_model_rev(gpu, GC2000, 0x6202) ||
+ etnaviv_is_model_rev(gpu, GC2000, 0x6203))
pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_TX;
- /* Disable SE, RA and TX clock gating on affected core revisions. */
+ /* Disable SE and RA clock gating on affected core revisions. */
if (etnaviv_is_model_rev(gpu, GC7000, 0x6202))
pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_SE |
- VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA |
- VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_TX;
+ VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA;
pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_HZ;
pmc |= VIVS_PM_MODULE_CONTROLS_DISABLE_MODULE_CLOCK_GATING_RA_EZ;
- gpu_write(gpu, VIVS_PM_MODULE_CONTROLS, pmc);
+ gpu_write_power(gpu, VIVS_PM_MODULE_CONTROLS, pmc);
}
void etnaviv_gpu_start_fe(struct etnaviv_gpu *gpu, u32 address, u16 prefetch)
@@ -688,11 +696,11 @@ static void etnaviv_gpu_setup_pulse_eater(struct etnaviv_gpu *gpu)
(gpu->identity.features & chipFeatures_PIPE_3D))
{
/* Performance fix: disable internal DFS */
- pulse_eater = gpu_read(gpu, VIVS_PM_PULSE_EATER);
+ pulse_eater = gpu_read_power(gpu, VIVS_PM_PULSE_EATER);
pulse_eater |= BIT(18);
}
- gpu_write(gpu, VIVS_PM_PULSE_EATER, pulse_eater);
+ gpu_write_power(gpu, VIVS_PM_PULSE_EATER, pulse_eater);
}
static void etnaviv_gpu_hw_init(struct etnaviv_gpu *gpu)
@@ -1045,12 +1053,28 @@ pm_put:
}
#endif
-void etnaviv_gpu_recover_hang(struct etnaviv_gpu *gpu)
+void etnaviv_gpu_recover_hang(struct etnaviv_gem_submit *submit)
{
+ struct etnaviv_gpu *gpu = submit->gpu;
+ char *comm = NULL, *cmd = NULL;
+ struct task_struct *task;
unsigned int i;
dev_err(gpu->dev, "recover hung GPU!\n");
+ task = get_pid_task(submit->pid, PIDTYPE_PID);
+ if (task) {
+ comm = kstrdup(task->comm, GFP_KERNEL);
+ cmd = kstrdup_quotable_cmdline(task, GFP_KERNEL);
+ put_task_struct(task);
+ }
+
+ if (comm && cmd)
+ dev_err(gpu->dev, "offending task: %s (%s)\n", comm, cmd);
+
+ kfree(cmd);
+ kfree(comm);
+
if (pm_runtime_get_sync(gpu->dev) < 0)
goto pm_put;
@@ -1294,9 +1318,9 @@ static void sync_point_perfmon_sample_pre(struct etnaviv_gpu *gpu,
u32 val;
/* disable clock gating */
- val = gpu_read(gpu, VIVS_PM_POWER_CONTROLS);
+ val = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS);
val &= ~VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;
- gpu_write(gpu, VIVS_PM_POWER_CONTROLS, val);
+ gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, val);
/* enable debug register */
val = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL);
@@ -1327,9 +1351,9 @@ static void sync_point_perfmon_sample_post(struct etnaviv_gpu *gpu,
gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, val);
/* enable clock gating */
- val = gpu_read(gpu, VIVS_PM_POWER_CONTROLS);
+ val = gpu_read_power(gpu, VIVS_PM_POWER_CONTROLS);
val |= VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING;
- gpu_write(gpu, VIVS_PM_POWER_CONTROLS, val);
+ gpu_write_power(gpu, VIVS_PM_POWER_CONTROLS, val);
}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
index 85eddd492774..f1204b070fb8 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h
@@ -10,6 +10,7 @@
#include "etnaviv_gem.h"
#include "etnaviv_mmu.h"
#include "etnaviv_drv.h"
+#include "common.xml.h"
struct etnaviv_gem_submit;
struct etnaviv_vram_mapping;
@@ -159,6 +160,26 @@ static inline u32 gpu_read(struct etnaviv_gpu *gpu, u32 reg)
return readl(gpu->mmio + reg);
}
+static inline u32 gpu_fix_power_address(struct etnaviv_gpu *gpu, u32 reg)
+{
+ /* Power registers in GC300 < 2.0 are offset by 0x100 */
+ if (gpu->identity.model == chipModel_GC300 &&
+ gpu->identity.revision < 0x2000)
+ reg += 0x100;
+
+ return reg;
+}
+
+static inline void gpu_write_power(struct etnaviv_gpu *gpu, u32 reg, u32 data)
+{
+ writel(data, gpu->mmio + gpu_fix_power_address(gpu, reg));
+}
+
+static inline u32 gpu_read_power(struct etnaviv_gpu *gpu, u32 reg)
+{
+ return readl(gpu->mmio + gpu_fix_power_address(gpu, reg));
+}
+
int etnaviv_gpu_get_param(struct etnaviv_gpu *gpu, u32 param, u64 *value);
int etnaviv_gpu_init(struct etnaviv_gpu *gpu);
@@ -168,7 +189,7 @@ bool etnaviv_fill_identity_from_hwdb(struct etnaviv_gpu *gpu);
int etnaviv_gpu_debugfs(struct etnaviv_gpu *gpu, struct seq_file *m);
#endif
-void etnaviv_gpu_recover_hang(struct etnaviv_gpu *gpu);
+void etnaviv_gpu_recover_hang(struct etnaviv_gem_submit *submit);
void etnaviv_gpu_retire(struct etnaviv_gpu *gpu);
int etnaviv_gpu_wait_fence_interruptible(struct etnaviv_gpu *gpu,
u32 fence, struct drm_etnaviv_timespec *timeout);
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c
index f2fc645c7956..57f334e24189 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_hwdb.c
@@ -70,6 +70,37 @@ static const struct etnaviv_chip_identity etnaviv_chip_identities[] = {
},
{
.model = 0x7000,
+ .revision = 0x6203,
+ .product_id = 0x70003,
+ .customer_id = 0x4,
+ .eco_id = 0,
+ .stream_count = 16,
+ .register_max = 64,
+ .thread_count = 512,
+ .shader_core_count = 2,
+ .vertex_cache_size = 16,
+ .vertex_output_buffer_size = 1024,
+ .pixel_pipes = 1,
+ .instruction_count = 512,
+ .num_constants = 320,
+ .buffer_size = 0,
+ .varyings_count = 16,
+ .features = 0xe0287c8d,
+ .minor_features0 = 0xc1589eff,
+ .minor_features1 = 0xfefbfad9,
+ .minor_features2 = 0xeb9d4fbf,
+ .minor_features3 = 0xedfffced,
+ .minor_features4 = 0xdb0dafc7,
+ .minor_features5 = 0x3b5ac333,
+ .minor_features6 = 0xfcce6000,
+ .minor_features7 = 0xfffbfa6f,
+ .minor_features8 = 0x00e10ef3,
+ .minor_features9 = 0x00c8003c,
+ .minor_features10 = 0x00004040,
+ .minor_features11 = 0x00000024,
+ },
+ {
+ .model = 0x7000,
.revision = 0x6204,
.product_id = ~0U,
.customer_id = ~0U,
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
index dc1aa738c4f1..67bdce5326c6 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
@@ -80,10 +80,10 @@ static int etnaviv_iommu_map(struct etnaviv_iommu_context *context, u32 iova,
return -EINVAL;
for_each_sgtable_dma_sg(sgt, sg, i) {
- u32 pa = sg_dma_address(sg) - sg->offset;
+ phys_addr_t pa = sg_dma_address(sg) - sg->offset;
size_t bytes = sg_dma_len(sg) + sg->offset;
- VERB("map[%d]: %08x %08x(%zx)", i, iova, pa, bytes);
+ VERB("map[%d]: %08x %pap(%zx)", i, iova, &pa, bytes);
ret = etnaviv_context_map(context, da, pa, bytes, prot);
if (ret)
@@ -135,6 +135,19 @@ static void etnaviv_iommu_remove_mapping(struct etnaviv_iommu_context *context,
drm_mm_remove_node(&mapping->vram_node);
}
+void etnaviv_iommu_reap_mapping(struct etnaviv_vram_mapping *mapping)
+{
+ struct etnaviv_iommu_context *context = mapping->context;
+
+ lockdep_assert_held(&context->lock);
+ WARN_ON(mapping->use);
+
+ etnaviv_iommu_remove_mapping(context, mapping);
+ etnaviv_iommu_context_put(mapping->context);
+ mapping->context = NULL;
+ list_del_init(&mapping->mmu_node);
+}
+
static int etnaviv_iommu_find_iova(struct etnaviv_iommu_context *context,
struct drm_mm_node *node, size_t size)
{
@@ -202,10 +215,7 @@ static int etnaviv_iommu_find_iova(struct etnaviv_iommu_context *context,
* this mapping.
*/
list_for_each_entry_safe(m, n, &list, scan_node) {
- etnaviv_iommu_remove_mapping(context, m);
- etnaviv_iommu_context_put(m->context);
- m->context = NULL;
- list_del_init(&m->mmu_node);
+ etnaviv_iommu_reap_mapping(m);
list_del_init(&m->scan_node);
}
@@ -257,10 +267,7 @@ static int etnaviv_iommu_insert_exact(struct etnaviv_iommu_context *context,
}
list_for_each_entry_safe(m, n, &scan_list, scan_node) {
- etnaviv_iommu_remove_mapping(context, m);
- etnaviv_iommu_context_put(m->context);
- m->context = NULL;
- list_del_init(&m->mmu_node);
+ etnaviv_iommu_reap_mapping(m);
list_del_init(&m->scan_node);
}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
index e4a0b7d09c2e..c01a147f0dfd 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
+++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h
@@ -91,6 +91,7 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu_context *context,
struct etnaviv_vram_mapping *mapping, u64 va);
void etnaviv_iommu_unmap_gem(struct etnaviv_iommu_context *context,
struct etnaviv_vram_mapping *mapping);
+void etnaviv_iommu_reap_mapping(struct etnaviv_vram_mapping *mapping);
int etnaviv_iommu_get_suballoc_va(struct etnaviv_iommu_context *ctx,
struct etnaviv_vram_mapping *mapping,
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
index 72e2553fbc98..d29f467eee13 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
@@ -67,7 +67,7 @@ static enum drm_gpu_sched_stat etnaviv_sched_timedout_job(struct drm_sched_job
/* get the GPU back into the init state */
etnaviv_core_dump(submit);
- etnaviv_gpu_recover_hang(gpu);
+ etnaviv_gpu_recover_hang(submit);
drm_sched_resubmit_jobs(&gpu->sched);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index 767afd2bfa82..55c92372fca0 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -49,6 +49,8 @@ static const struct fb_ops exynos_drm_fb_ops = {
.owner = THIS_MODULE,
DRM_FB_HELPER_DEFAULT_OPS,
.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,
@@ -63,7 +65,7 @@ static int exynos_drm_fbdev_update(struct drm_fb_helper *helper,
unsigned int size = fb->width * fb->height * fb->format->cpp[0];
unsigned long offset;
- fbi = drm_fb_helper_alloc_fbi(helper);
+ fbi = drm_fb_helper_alloc_info(helper);
if (IS_ERR(fbi)) {
DRM_DEV_ERROR(to_dma_dev(helper->dev),
"failed to allocate fb info.\n");
@@ -201,7 +203,7 @@ static void exynos_drm_fbdev_destroy(struct drm_device *dev,
drm_framebuffer_remove(fb);
}
- drm_fb_helper_unregister_fbi(fb_helper);
+ drm_fb_helper_unregister_info(fb_helper);
drm_fb_helper_fini(fb_helper);
}
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
index b4acc3422ba4..8579c7629f5e 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
@@ -20,7 +20,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_modeset_helper.h>
#include <drm/drm_module.h>
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c
index aa3ecf771fd3..8d5a37b8f110 100644
--- a/drivers/gpu/drm/gma500/framebuffer.c
+++ b/drivers/gpu/drm/gma500/framebuffer.c
@@ -147,6 +147,8 @@ static const struct fb_ops psbfb_unaccel_ops = {
.owner = THIS_MODULE,
DRM_FB_HELPER_DEFAULT_OPS,
.fb_setcolreg = psbfb_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,
@@ -268,7 +270,7 @@ static int psbfb_create(struct drm_fb_helper *fb_helper,
memset(dev_priv->vram_addr + backing->offset, 0, size);
- info = drm_fb_helper_alloc_fbi(fb_helper);
+ info = drm_fb_helper_alloc_info(fb_helper);
if (IS_ERR(info)) {
ret = PTR_ERR(info);
goto err_drm_gem_object_put;
@@ -286,7 +288,7 @@ static int psbfb_create(struct drm_fb_helper *fb_helper,
info->fbops = &psbfb_unaccel_ops;
- info->fix.smem_start = dev->mode_config.fb_base;
+ info->fix.smem_start = dev_priv->fb_base;
info->fix.smem_len = size;
info->fix.ywrapstep = 0;
info->fix.ypanstep = 0;
@@ -296,7 +298,7 @@ static int psbfb_create(struct drm_fb_helper *fb_helper,
info->screen_size = size;
if (dev_priv->gtt.stolen_size) {
- info->apertures->ranges[0].base = dev->mode_config.fb_base;
+ info->apertures->ranges[0].base = dev_priv->fb_base;
info->apertures->ranges[0].size = dev_priv->gtt.stolen_size;
}
@@ -383,7 +385,7 @@ static int psb_fbdev_destroy(struct drm_device *dev,
{
struct drm_framebuffer *fb = fb_helper->fb;
- drm_fb_helper_unregister_fbi(fb_helper);
+ drm_fb_helper_unregister_info(fb_helper);
drm_fb_helper_fini(fb_helper);
drm_framebuffer_unregister_private(fb);
@@ -527,7 +529,7 @@ void psb_modeset_init(struct drm_device *dev)
/* set memory base */
/* Oaktrail and Poulsbo should use BAR 2*/
- pci_read_config_dword(pdev, PSB_BSM, (u32 *)&(dev->mode_config.fb_base));
+ pci_read_config_dword(pdev, PSB_BSM, (u32 *)&(dev_priv->fb_base));
/* num pipes is 2 for PSB but 1 for Mrst */
for (i = 0; i < dev_priv->num_pipe; i++)
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
index ae544b69fc47..a5df6d2f2cab 100644
--- a/drivers/gpu/drm/gma500/psb_drv.h
+++ b/drivers/gpu/drm/gma500/psb_drv.h
@@ -523,6 +523,7 @@ struct drm_psb_private {
uint32_t blc_adj2;
struct drm_fb_helper *fb_helper;
+ resource_size_t fb_base;
bool dsr_enable;
u32 dsr_fb_update;
diff --git a/drivers/gpu/drm/gud/gud_connector.c b/drivers/gpu/drm/gud/gud_connector.c
index d0addd478815..fa636206f232 100644
--- a/drivers/gpu/drm/gud/gud_connector.c
+++ b/drivers/gpu/drm/gud/gud_connector.c
@@ -355,7 +355,7 @@ static void gud_connector_reset(struct drm_connector *connector)
drm_atomic_helper_connector_reset(connector);
connector->state->tv = gconn->initial_tv_state;
/* Set margins from command line */
- drm_atomic_helper_connector_tv_reset(connector);
+ drm_atomic_helper_connector_tv_margins_reset(connector);
if (gconn->initial_brightness >= 0)
connector->state->tv.brightness = gconn->initial_brightness;
}
diff --git a/drivers/gpu/drm/gud/gud_drv.c b/drivers/gpu/drm/gud/gud_drv.c
index 8d1630b8edac..d57dab104358 100644
--- a/drivers/gpu/drm/gud/gud_drv.c
+++ b/drivers/gpu/drm/gud/gud_drv.c
@@ -18,7 +18,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_debugfs.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index fe4269c5aa0a..22053c613644 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -17,6 +17,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_gem_vram_helper.h>
#include <drm/drm_managed.h>
@@ -105,7 +106,6 @@ static int hibmc_kms_init(struct hibmc_drm_private *priv)
dev->mode_config.max_width = 1920;
dev->mode_config.max_height = 1200;
- dev->mode_config.fb_base = priv->fb_base;
dev->mode_config.preferred_depth = 32;
dev->mode_config.prefer_shadow = 1;
@@ -212,7 +212,7 @@ static int hibmc_hw_map(struct hibmc_drm_private *priv)
{
struct drm_device *dev = &priv->dev;
struct pci_dev *pdev = to_pci_dev(dev->dev);
- resource_size_t addr, size, ioaddr, iosize;
+ resource_size_t ioaddr, iosize;
ioaddr = pci_resource_start(pdev, 1);
iosize = pci_resource_len(pdev, 1);
@@ -222,16 +222,6 @@ static int hibmc_hw_map(struct hibmc_drm_private *priv)
return -ENOMEM;
}
- addr = pci_resource_start(pdev, 0);
- size = pci_resource_len(pdev, 0);
- priv->fb_map = devm_ioremap(dev->dev, addr, size);
- if (!priv->fb_map) {
- drm_err(dev, "Cannot map framebuffer\n");
- return -ENOMEM;
- }
- priv->fb_base = addr;
- priv->fb_size = size;
-
return 0;
}
@@ -271,7 +261,8 @@ static int hibmc_load(struct drm_device *dev)
if (ret)
goto err;
- ret = drmm_vram_helper_init(dev, pci_resource_start(pdev, 0), priv->fb_size);
+ ret = drmm_vram_helper_init(dev, pci_resource_start(pdev, 0),
+ pci_resource_len(pdev, 0));
if (ret) {
drm_err(dev, "Error initializing VRAM MM; %d\n", ret);
goto err;
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index 7d263f4d7078..f957552c6c50 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -19,7 +19,6 @@
#include <linux/i2c.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_framebuffer.h>
struct hibmc_connector {
@@ -32,9 +31,6 @@ struct hibmc_connector {
struct hibmc_drm_private {
/* hw */
void __iomem *mmio;
- void __iomem *fb_map;
- resource_size_t fb_base;
- resource_size_t fb_size;
/* drm */
struct drm_device dev;
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
index c228091fb0e6..8c6d2ea2a472 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
@@ -11,6 +11,8 @@
* Jianhua Li <lijianhua@huawei.com>
*/
+#include <linux/io.h>
+
#include <drm/drm_atomic_helper.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_print.h>
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index a0d5aa727d58..d9978b79828c 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
@@ -658,7 +658,7 @@ static enum drm_mode_status dsi_encoder_mode_valid(struct drm_encoder *encoder,
* reset adj_mode to the mode value each time,
* so we don't adjust the mode twice
*/
- drm_mode_copy(&adj_mode, mode);
+ drm_mode_init(&adj_mode, mode);
crtc_funcs = crtc->helper_private;
if (crtc_funcs && crtc_funcs->mode_fixup)
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
index 73ee7f25f734..9c5d49bf40c9 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
@@ -19,7 +19,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_module.h>
diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
index ca127ff797f7..427c20ba3404 100644
--- a/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
+++ b/drivers/gpu/drm/hyperv/hyperv_drm_drv.c
@@ -11,7 +11,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_simple_kms_helper.h>
diff --git a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
index 28e732f94bf2..6c6b57298797 100644
--- a/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
+++ b/drivers/gpu/drm/hyperv/hyperv_drm_modeset.c
@@ -8,7 +8,6 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c
index d444e7fffb54..a14d2896aebb 100644
--- a/drivers/gpu/drm/i2c/tda998x_drv.c
+++ b/drivers/gpu/drm/i2c/tda998x_drv.c
@@ -1174,6 +1174,8 @@ static int tda998x_audio_codec_init(struct tda998x_priv *priv,
struct hdmi_codec_pdata codec_data = {
.ops = &audio_codec_ops,
.max_i2s_channels = 2,
+ .no_i2s_capture = 1,
+ .no_spdif_capture = 1,
};
if (priv->audio_port_enable[AUDIO_ROUTE_I2S])
diff --git a/drivers/gpu/drm/i915/Kconfig.profile b/drivers/gpu/drm/i915/Kconfig.profile
index 39328567c200..7cc38d25ee5c 100644
--- a/drivers/gpu/drm/i915/Kconfig.profile
+++ b/drivers/gpu/drm/i915/Kconfig.profile
@@ -57,10 +57,28 @@ config DRM_I915_PREEMPT_TIMEOUT
default 640 # milliseconds
help
How long to wait (in milliseconds) for a preemption event to occur
- when submitting a new context via execlists. If the current context
- does not hit an arbitration point and yield to HW before the timer
- expires, the HW will be reset to allow the more important context
- to execute.
+ when submitting a new context. If the current context does not hit
+ an arbitration point and yield to HW before the timer expires, the
+ HW will be reset to allow the more important context to execute.
+
+ This is adjustable via
+ /sys/class/drm/card?/engine/*/preempt_timeout_ms
+
+ May be 0 to disable the timeout.
+
+ The compiled in default may get overridden at driver probe time on
+ certain platforms and certain engines which will be reflected in the
+ sysfs control.
+
+config DRM_I915_PREEMPT_TIMEOUT_COMPUTE
+ int "Preempt timeout for compute engines (ms, jiffy granularity)"
+ default 7500 # milliseconds
+ help
+ How long to wait (in milliseconds) for a preemption event to occur
+ when submitting a new context to a compute capable engine. If the
+ current context does not hit an arbitration point and yield to HW
+ before the timer expires, the HW will be reset to allow the more
+ important context to execute.
This is adjustable via
/sys/class/drm/card?/engine/*/preempt_timeout_ms
diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index cea00aaca04b..01974b82d205 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -127,9 +127,11 @@ gt-y += \
gt/intel_sseu.o \
gt/intel_sseu_debugfs.o \
gt/intel_timeline.o \
+ gt/intel_wopcm.o \
gt/intel_workarounds.o \
gt/shmem_utils.o \
gt/sysfs_engines.o
+
# x86 intel-gtt module support
gt-$(CONFIG_X86) += gt/intel_ggtt_gmch.o
# autogenerated null render state
@@ -183,8 +185,7 @@ i915-y += \
i915_trace_points.o \
i915_ttm_buddy_manager.o \
i915_vma.o \
- i915_vma_resource.o \
- intel_wopcm.o
+ i915_vma_resource.o
# general-purpose microcontroller (GuC) support
i915-y += gt/uc/intel_uc.o \
@@ -209,6 +210,9 @@ i915-y += gt/uc/intel_uc.o \
# graphics system controller (GSC) support
i915-y += gt/intel_gsc.o
+# graphics hardware monitoring (HWMON) support
+i915-$(CONFIG_HWMON) += i915_hwmon.o
+
# modesetting core code
i915-y += \
display/hsw_ips.o \
@@ -244,6 +248,7 @@ i915-y += \
display/intel_global_state.o \
display/intel_hdcp.o \
display/intel_hotplug.o \
+ display/intel_hti.o \
display/intel_lpe_audio.o \
display/intel_modeset_verify.o \
display/intel_modeset_setup.o \
@@ -310,15 +315,18 @@ i915-y += \
i915-y += i915_perf.o
-# Protected execution platform (PXP) support
-i915-$(CONFIG_DRM_I915_PXP) += \
+# Protected execution platform (PXP) support. Base support is required for HuC
+i915-y += \
pxp/intel_pxp.o \
+ pxp/intel_pxp_tee.o \
+ pxp/intel_pxp_huc.o
+
+i915-$(CONFIG_DRM_I915_PXP) += \
pxp/intel_pxp_cmd.o \
pxp/intel_pxp_debugfs.o \
pxp/intel_pxp_irq.o \
pxp/intel_pxp_pm.o \
- pxp/intel_pxp_session.o \
- pxp/intel_pxp_tee.o
+ pxp/intel_pxp_session.o
# Post-mortem debug and GPU hang state capture
i915-$(CONFIG_DRM_I915_CAPTURE_ERROR) += i915_gpu_error.o
diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c
index e3e3d27ffb53..3593938dcd87 100644
--- a/drivers/gpu/drm/i915/display/g4x_dp.c
+++ b/drivers/gpu/drm/i915/display/g4x_dp.c
@@ -8,6 +8,7 @@
#include <linux/string_helpers.h>
#include "g4x_dp.h"
+#include "i915_reg.h"
#include "intel_audio.h"
#include "intel_backlight.h"
#include "intel_connector.h"
diff --git a/drivers/gpu/drm/i915/display/g4x_dp.h b/drivers/gpu/drm/i915/display/g4x_dp.h
index e1f50263a725..a38b3e1e01d3 100644
--- a/drivers/gpu/drm/i915/display/g4x_dp.h
+++ b/drivers/gpu/drm/i915/display/g4x_dp.h
@@ -8,7 +8,7 @@
#include <linux/types.h>
-#include "i915_reg.h"
+#include "i915_reg_defs.h"
enum pipe;
enum port;
diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c
index 2b73f5ff0d02..121caeaa409b 100644
--- a/drivers/gpu/drm/i915/display/g4x_hdmi.c
+++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c
@@ -6,6 +6,7 @@
*/
#include "g4x_hdmi.h"
+#include "i915_reg.h"
#include "intel_audio.h"
#include "intel_connector.h"
#include "intel_crtc.h"
@@ -78,6 +79,18 @@ static bool intel_hdmi_get_hw_state(struct intel_encoder *encoder,
return ret;
}
+static int g4x_hdmi_compute_config(struct intel_encoder *encoder,
+ struct intel_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
+{
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+
+ if (HAS_PCH_SPLIT(i915))
+ crtc_state->has_pch_encoder = true;
+
+ return intel_hdmi_compute_config(encoder, crtc_state, conn_state);
+}
+
static void intel_hdmi_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
@@ -543,7 +556,7 @@ void g4x_hdmi_init(struct drm_i915_private *dev_priv,
"HDMI %c", port_name(port));
intel_encoder->hotplug = intel_hdmi_hotplug;
- intel_encoder->compute_config = intel_hdmi_compute_config;
+ intel_encoder->compute_config = g4x_hdmi_compute_config;
if (HAS_PCH_SPLIT(dev_priv)) {
intel_encoder->disable = pch_disable_hdmi;
intel_encoder->post_disable = pch_post_disable_hdmi;
@@ -585,7 +598,7 @@ void g4x_hdmi_init(struct drm_i915_private *dev_priv,
} else {
intel_encoder->pipe_mask = ~0;
}
- intel_encoder->cloneable = 1 << INTEL_OUTPUT_ANALOG;
+ intel_encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG);
intel_encoder->hpd_pin = intel_hpd_pin_default(dev_priv, port);
/*
* BSpec is unclear about HDMI+HDMI cloning on g4x, but it seems
@@ -593,7 +606,7 @@ void g4x_hdmi_init(struct drm_i915_private *dev_priv,
* only one port anyway, nothing is lost by allowing it.
*/
if (IS_G4X(dev_priv))
- intel_encoder->cloneable |= 1 << INTEL_OUTPUT_HDMI;
+ intel_encoder->cloneable |= BIT(INTEL_OUTPUT_HDMI);
dig_port->hdmi.hdmi_reg = hdmi_reg;
dig_port->dp.output_reg = INVALID_MMIO_REG;
diff --git a/drivers/gpu/drm/i915/display/hsw_ips.c b/drivers/gpu/drm/i915/display/hsw_ips.c
index a5be4af792cb..83aa3800245f 100644
--- a/drivers/gpu/drm/i915/display/hsw_ips.c
+++ b/drivers/gpu/drm/i915/display/hsw_ips.c
@@ -104,8 +104,7 @@ static bool hsw_ips_need_disable(struct intel_atomic_state *state,
* Disable IPS before we program the LUT.
*/
if (IS_HASWELL(i915) &&
- (new_crtc_state->uapi.color_mgmt_changed ||
- new_crtc_state->update_pipe) &&
+ intel_crtc_needs_color_update(new_crtc_state) &&
new_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)
return true;
@@ -146,8 +145,7 @@ static bool hsw_ips_need_enable(struct intel_atomic_state *state,
* Re-enable IPS after the LUT has been programmed.
*/
if (IS_HASWELL(i915) &&
- (new_crtc_state->uapi.color_mgmt_changed ||
- new_crtc_state->update_pipe) &&
+ intel_crtc_needs_color_update(new_crtc_state) &&
new_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT)
return true;
@@ -155,7 +153,7 @@ static bool hsw_ips_need_enable(struct intel_atomic_state *state,
* We can't read out IPS on broadwell, assume the worst and
* forcibly enable IPS on the first fastset.
*/
- if (new_crtc_state->update_pipe && old_crtc_state->inherited)
+ if (intel_crtc_needs_fastset(new_crtc_state) && old_crtc_state->inherited)
return true;
return !old_crtc_state->ips_enabled;
diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c
index 5afbe3e98ee8..ecaeb7dc196b 100644
--- a/drivers/gpu/drm/i915/display/i9xx_plane.c
+++ b/drivers/gpu/drm/i915/display/i9xx_plane.c
@@ -8,6 +8,9 @@
#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"
@@ -15,7 +18,6 @@
#include "intel_fb.h"
#include "intel_fbc.h"
#include "intel_sprite.h"
-#include "i9xx_plane.h"
/* Primary plane formats for gen <= 3 */
static const u32 i8xx_primary_formats[] = {
diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c
index ed4d93942dbd..d16b30a2dded 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi.c
+++ b/drivers/gpu/drm/i915/display/icl_dsi.c
@@ -29,6 +29,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_mipi_dsi.h>
+#include "i915_reg.h"
#include "icl_dsi.h"
#include "icl_dsi_regs.h"
#include "intel_atomic.h"
@@ -1974,16 +1975,8 @@ static void icl_dsi_add_properties(struct intel_connector *connector)
{
const struct drm_display_mode *fixed_mode =
intel_panel_preferred_fixed_mode(connector);
- u32 allowed_scalers;
- allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT) |
- BIT(DRM_MODE_SCALE_FULLSCREEN) |
- BIT(DRM_MODE_SCALE_CENTER);
-
- drm_connector_attach_scaling_mode_property(&connector->base,
- allowed_scalers);
-
- connector->base.state->scaling_mode = DRM_MODE_SCALE_ASPECT;
+ intel_attach_scaling_mode_property(&connector->base);
drm_connector_set_panel_orientation_with_quirk(&connector->base,
intel_dsi_get_panel_orientation(connector),
@@ -1993,7 +1986,6 @@ static void icl_dsi_add_properties(struct intel_connector *connector)
void icl_dsi_init(struct drm_i915_private *dev_priv)
{
- struct drm_device *dev = &dev_priv->drm;
struct intel_dsi *intel_dsi;
struct intel_encoder *encoder;
struct intel_connector *intel_connector;
@@ -2018,7 +2010,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
connector = &intel_connector->base;
/* register DSI encoder with DRM subsystem */
- drm_encoder_init(dev, &encoder->base, &gen11_dsi_encoder_funcs,
+ drm_encoder_init(&dev_priv->drm, &encoder->base, &gen11_dsi_encoder_funcs,
DRM_MODE_ENCODER_DSI, "DSI %c", port_name(port));
encoder->pre_pll_enable = gen11_dsi_pre_pll_enable;
@@ -2042,12 +2034,10 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
encoder->is_clock_enabled = gen11_dsi_is_clock_enabled;
/* register DSI connector with DRM subsystem */
- drm_connector_init(dev, connector, &gen11_dsi_connector_funcs,
+ drm_connector_init(&dev_priv->drm, connector, &gen11_dsi_connector_funcs,
DRM_MODE_CONNECTOR_DSI);
drm_connector_helper_add(connector, &gen11_dsi_connector_helper_funcs);
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
- connector->interlace_allowed = false;
- connector->doublescan_allowed = false;
intel_connector->get_hw_state = intel_connector_get_hw_state;
/* attach connector to encoder */
@@ -2055,9 +2045,9 @@ void icl_dsi_init(struct drm_i915_private *dev_priv)
intel_bios_init_panel(dev_priv, &intel_connector->panel, NULL, NULL);
- mutex_lock(&dev->mode_config.mutex);
+ mutex_lock(&dev_priv->drm.mode_config.mutex);
intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
- mutex_unlock(&dev->mode_config.mutex);
+ mutex_unlock(&dev_priv->drm.mode_config.mutex);
if (!intel_panel_preferred_fixed_mode(intel_connector)) {
drm_err(&dev_priv->drm, "DSI fixed mode info missing\n");
diff --git a/drivers/gpu/drm/i915/display/icl_dsi_regs.h b/drivers/gpu/drm/i915/display/icl_dsi_regs.h
index f78f28b8dd94..d4845ac65acc 100644
--- a/drivers/gpu/drm/i915/display/icl_dsi_regs.h
+++ b/drivers/gpu/drm/i915/display/icl_dsi_regs.h
@@ -6,7 +6,7 @@
#ifndef __ICL_DSI_REGS_H__
#define __ICL_DSI_REGS_H__
-#include "i915_reg_defs.h"
+#include "intel_display_reg_defs.h"
/* Gen11 DSI */
#define _MMIO_DSI(tc, dsi0, dsi1) _MMIO_TRANS((tc) - TRANSCODER_DSI_0, \
diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c
index 18f0a5ae3bac..6621aa245caf 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic.c
@@ -252,6 +252,11 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc)
if (crtc_state->hw.gamma_lut)
drm_property_blob_get(crtc_state->hw.gamma_lut);
+ if (crtc_state->pre_csc_lut)
+ drm_property_blob_get(crtc_state->pre_csc_lut);
+ if (crtc_state->post_csc_lut)
+ drm_property_blob_get(crtc_state->post_csc_lut);
+
crtc_state->update_pipe = false;
crtc_state->disable_lp_wm = false;
crtc_state->disable_cxsr = false;
@@ -274,6 +279,9 @@ static void intel_crtc_put_color_blobs(struct intel_crtc_state *crtc_state)
drm_property_blob_put(crtc_state->hw.degamma_lut);
drm_property_blob_put(crtc_state->hw.gamma_lut);
drm_property_blob_put(crtc_state->hw.ctm);
+
+ drm_property_blob_put(crtc_state->pre_csc_lut);
+ drm_property_blob_put(crtc_state->post_csc_lut);
}
void intel_crtc_free_hw_state(struct intel_crtc_state *crtc_state)
diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
index aaa6708256d5..10e1fc9d0698 100644
--- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c
+++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c
@@ -425,6 +425,47 @@ static bool intel_plane_do_async_flip(struct intel_plane *plane,
return DISPLAY_VER(i915) < 13 || old_crtc_state->uapi.async_flip;
}
+static bool i9xx_must_disable_cxsr(const struct intel_crtc_state *new_crtc_state,
+ const struct intel_plane_state *old_plane_state,
+ const struct intel_plane_state *new_plane_state)
+{
+ struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane);
+ bool old_visible = old_plane_state->uapi.visible;
+ bool new_visible = new_plane_state->uapi.visible;
+ u32 old_ctl = old_plane_state->ctl;
+ u32 new_ctl = new_plane_state->ctl;
+ bool modeset, turn_on, turn_off;
+
+ if (plane->id == PLANE_CURSOR)
+ return false;
+
+ modeset = intel_crtc_needs_modeset(new_crtc_state);
+ turn_off = old_visible && (!new_visible || modeset);
+ turn_on = new_visible && (!old_visible || modeset);
+
+ /* Must disable CxSR around plane enable/disable */
+ if (turn_on || turn_off)
+ return true;
+
+ if (!old_visible || !new_visible)
+ return false;
+
+ /*
+ * Most plane control register updates are blocked while in CxSR.
+ *
+ * Tiling mode is one exception where the primary plane can
+ * apparently handle it, whereas the sprites can not (the
+ * sprite issue being only relevant on VLV/CHV where CxSR
+ * is actually possible with a sprite enabled).
+ */
+ if (plane->id == PLANE_PRIMARY) {
+ old_ctl &= ~DISP_TILED;
+ new_ctl &= ~DISP_TILED;
+ }
+
+ return old_ctl != new_ctl;
+}
+
static int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_crtc_state,
struct intel_crtc_state *new_crtc_state,
const struct intel_plane_state *old_plane_state,
@@ -482,17 +523,9 @@ static int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_cr
if (turn_on) {
if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv))
new_crtc_state->update_wm_pre = true;
-
- /* must disable cxsr around plane enable/disable */
- if (plane->id != PLANE_CURSOR)
- new_crtc_state->disable_cxsr = true;
} else if (turn_off) {
if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv))
new_crtc_state->update_wm_post = true;
-
- /* must disable cxsr around plane enable/disable */
- if (plane->id != PLANE_CURSOR)
- new_crtc_state->disable_cxsr = true;
} else if (intel_wm_need_update(old_plane_state, new_plane_state)) {
if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv)) {
/* FIXME bollocks */
@@ -504,6 +537,10 @@ static int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_cr
if (visible || was_visible)
new_crtc_state->fb_bits |= plane->frontbuffer_bit;
+ if (HAS_GMCH(dev_priv) &&
+ i9xx_must_disable_cxsr(new_crtc_state, old_plane_state, new_plane_state))
+ new_crtc_state->disable_cxsr = true;
+
/*
* ILK/SNB DVSACNTR/Sprite Enable
* IVB SPR_CTL/Sprite Enable
@@ -720,7 +757,7 @@ void intel_plane_update_noarm(struct intel_plane *plane,
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- trace_intel_plane_update_noarm(&plane->base, crtc);
+ trace_intel_plane_update_noarm(plane, crtc);
if (plane->update_noarm)
plane->update_noarm(plane, crtc_state, plane_state);
@@ -732,7 +769,7 @@ void intel_plane_update_arm(struct intel_plane *plane,
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- trace_intel_plane_update_arm(&plane->base, crtc);
+ trace_intel_plane_update_arm(plane, crtc);
if (crtc_state->do_async_flip && plane->async_flip)
plane->async_flip(plane, crtc_state, plane_state, true);
@@ -745,7 +782,7 @@ void intel_plane_disable_arm(struct intel_plane *plane,
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- trace_intel_plane_disable_arm(&plane->base, crtc);
+ trace_intel_plane_disable_arm(plane, crtc);
plane->disable_arm(plane, crtc_state);
}
@@ -1005,7 +1042,7 @@ intel_prepare_plane_fb(struct drm_plane *_plane,
*/
if (intel_crtc_needs_modeset(crtc_state)) {
ret = i915_sw_fence_await_reservation(&state->commit_ready,
- old_obj->base.resv, NULL,
+ old_obj->base.resv,
false, 0,
GFP_KERNEL);
if (ret < 0)
@@ -1039,8 +1076,7 @@ intel_prepare_plane_fb(struct drm_plane *_plane,
struct dma_fence *fence;
ret = i915_sw_fence_await_reservation(&state->commit_ready,
- obj->base.resv, NULL,
- false,
+ obj->base.resv, false,
i915_fence_timeout(dev_priv),
GFP_KERNEL);
if (ret < 0)
diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c
index aacbc6da84ef..98c3322b4549 100644
--- a/drivers/gpu/drm/i915/display/intel_audio.c
+++ b/drivers/gpu/drm/i915/display/intel_audio.c
@@ -250,7 +250,7 @@ static const struct hdmi_aud_ncts hdmi_aud_ncts_36bpp[] = {
/* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */
static u32 audio_config_hdmi_pixel_clock(const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
const struct drm_display_mode *adjusted_mode =
&crtc_state->hw.adjusted_mode;
int i;
@@ -260,17 +260,17 @@ static u32 audio_config_hdmi_pixel_clock(const struct intel_crtc_state *crtc_sta
break;
}
- if (DISPLAY_VER(dev_priv) < 12 && adjusted_mode->crtc_clock > 148500)
+ if (DISPLAY_VER(i915) < 12 && adjusted_mode->crtc_clock > 148500)
i = ARRAY_SIZE(hdmi_audio_clock);
if (i == ARRAY_SIZE(hdmi_audio_clock)) {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"HDMI audio pixel clock setting for %d not found, falling back to defaults\n",
adjusted_mode->crtc_clock);
i = 1;
}
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"Configuring HDMI audio for pixel clock %d (0x%08x)\n",
hdmi_audio_clock[i].clock,
hdmi_audio_clock[i].config);
@@ -304,96 +304,67 @@ static int audio_config_hdmi_get_n(const struct intel_crtc_state *crtc_state,
return 0;
}
-static bool intel_eld_uptodate(struct drm_connector *connector,
- i915_reg_t reg_eldv, u32 bits_eldv,
- i915_reg_t reg_elda, u32 bits_elda,
- i915_reg_t reg_edid)
+/* ELD buffer size in dwords */
+static int g4x_eld_buffer_size(struct drm_i915_private *i915)
{
- struct drm_i915_private *dev_priv = to_i915(connector->dev);
- const u8 *eld = connector->eld;
u32 tmp;
- int i;
-
- tmp = intel_de_read(dev_priv, reg_eldv);
- tmp &= bits_eldv;
-
- if (!tmp)
- return false;
- tmp = intel_de_read(dev_priv, reg_elda);
- tmp &= ~bits_elda;
- intel_de_write(dev_priv, reg_elda, tmp);
+ tmp = intel_de_read(i915, G4X_AUD_CNTL_ST);
- for (i = 0; i < drm_eld_size(eld) / 4; i++)
- if (intel_de_read(dev_priv, reg_edid) != *((const u32 *)eld + i))
- return false;
-
- return true;
+ return REG_FIELD_GET(G4X_ELD_BUFFER_SIZE_MASK, tmp);
}
static void g4x_audio_codec_disable(struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- u32 eldv, tmp;
-
- tmp = intel_de_read(dev_priv, G4X_AUD_VID_DID);
- if (tmp == INTEL_AUDIO_DEVBLC || tmp == INTEL_AUDIO_DEVCL)
- eldv = G4X_ELDV_DEVCL_DEVBLC;
- else
- eldv = G4X_ELDV_DEVCTG;
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
/* Invalidate ELD */
- tmp = intel_de_read(dev_priv, G4X_AUD_CNTL_ST);
- tmp &= ~eldv;
- intel_de_write(dev_priv, G4X_AUD_CNTL_ST, tmp);
+ intel_de_rmw(i915, G4X_AUD_CNTL_ST,
+ G4X_ELD_VALID, 0);
+
+ intel_crtc_wait_for_next_vblank(crtc);
+ intel_crtc_wait_for_next_vblank(crtc);
}
static void g4x_audio_codec_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_connector *connector = conn_state->connector;
- const u8 *eld = connector->eld;
- u32 eldv;
- u32 tmp;
- int len, i;
+ const u32 *eld = (const u32 *)connector->eld;
+ int eld_buffer_size, len, i;
- tmp = intel_de_read(dev_priv, G4X_AUD_VID_DID);
- if (tmp == INTEL_AUDIO_DEVBLC || tmp == INTEL_AUDIO_DEVCL)
- eldv = G4X_ELDV_DEVCL_DEVBLC;
- else
- eldv = G4X_ELDV_DEVCTG;
+ intel_crtc_wait_for_next_vblank(crtc);
- if (intel_eld_uptodate(connector,
- G4X_AUD_CNTL_ST, eldv,
- G4X_AUD_CNTL_ST, G4X_ELD_ADDR_MASK,
- G4X_HDMIW_HDMIEDID))
- return;
+ intel_de_rmw(i915, G4X_AUD_CNTL_ST,
+ G4X_ELD_VALID | G4X_ELD_ADDRESS_MASK, 0);
- tmp = intel_de_read(dev_priv, G4X_AUD_CNTL_ST);
- tmp &= ~(eldv | G4X_ELD_ADDR_MASK);
- len = (tmp >> 9) & 0x1f; /* ELD buffer size */
- intel_de_write(dev_priv, G4X_AUD_CNTL_ST, tmp);
+ eld_buffer_size = g4x_eld_buffer_size(i915);
+ len = min(drm_eld_size(connector->eld) / 4, eld_buffer_size);
- len = min(drm_eld_size(eld) / 4, len);
for (i = 0; i < len; i++)
- intel_de_write(dev_priv, G4X_HDMIW_HDMIEDID,
- *((const u32 *)eld + i));
+ intel_de_write(i915, G4X_HDMIW_HDMIEDID, eld[i]);
+ for (; i < eld_buffer_size; i++)
+ intel_de_write(i915, G4X_HDMIW_HDMIEDID, 0);
- tmp = intel_de_read(dev_priv, G4X_AUD_CNTL_ST);
- tmp |= eldv;
- intel_de_write(dev_priv, G4X_AUD_CNTL_ST, tmp);
+ drm_WARN_ON(&i915->drm,
+ (intel_de_read(i915, G4X_AUD_CNTL_ST) & G4X_ELD_ADDRESS_MASK) != 0);
+
+ intel_de_rmw(i915, G4X_AUD_CNTL_ST,
+ 0, G4X_ELD_VALID);
}
static void
hsw_dp_audio_config_update(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct i915_audio_component *acomp = dev_priv->display.audio.component;
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct i915_audio_component *acomp = i915->display.audio.component;
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
enum port port = encoder->port;
const struct dp_aud_n_m *nm;
@@ -403,12 +374,12 @@ hsw_dp_audio_config_update(struct intel_encoder *encoder,
rate = acomp ? acomp->aud_sample_rate[port] : 0;
nm = audio_config_dp_get_n_m(crtc_state, rate);
if (nm)
- drm_dbg_kms(&dev_priv->drm, "using Maud %u, Naud %u\n", nm->m,
+ drm_dbg_kms(&i915->drm, "using Maud %u, Naud %u\n", nm->m,
nm->n);
else
- drm_dbg_kms(&dev_priv->drm, "using automatic Maud, Naud\n");
+ drm_dbg_kms(&i915->drm, "using automatic Maud, Naud\n");
- tmp = intel_de_read(dev_priv, HSW_AUD_CFG(cpu_transcoder));
+ tmp = intel_de_read(i915, HSW_AUD_CFG(cpu_transcoder));
tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
@@ -420,9 +391,9 @@ hsw_dp_audio_config_update(struct intel_encoder *encoder,
tmp |= AUD_CONFIG_N_PROG_ENABLE;
}
- intel_de_write(dev_priv, HSW_AUD_CFG(cpu_transcoder), tmp);
+ intel_de_write(i915, HSW_AUD_CFG(cpu_transcoder), tmp);
- tmp = intel_de_read(dev_priv, HSW_AUD_M_CTS_ENABLE(cpu_transcoder));
+ tmp = intel_de_read(i915, HSW_AUD_M_CTS_ENABLE(cpu_transcoder));
tmp &= ~AUD_CONFIG_M_MASK;
tmp &= ~AUD_M_CTS_M_VALUE_INDEX;
tmp &= ~AUD_M_CTS_M_PROG_ENABLE;
@@ -433,15 +404,15 @@ hsw_dp_audio_config_update(struct intel_encoder *encoder,
tmp |= AUD_M_CTS_M_PROG_ENABLE;
}
- intel_de_write(dev_priv, HSW_AUD_M_CTS_ENABLE(cpu_transcoder), tmp);
+ intel_de_write(i915, HSW_AUD_M_CTS_ENABLE(cpu_transcoder), tmp);
}
static void
hsw_hdmi_audio_config_update(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct i915_audio_component *acomp = dev_priv->display.audio.component;
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct i915_audio_component *acomp = i915->display.audio.component;
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
enum port port = encoder->port;
int n, rate;
@@ -449,7 +420,7 @@ hsw_hdmi_audio_config_update(struct intel_encoder *encoder,
rate = acomp ? acomp->aud_sample_rate[port] : 0;
- tmp = intel_de_read(dev_priv, HSW_AUD_CFG(cpu_transcoder));
+ tmp = intel_de_read(i915, HSW_AUD_CFG(cpu_transcoder));
tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
@@ -457,25 +428,25 @@ hsw_hdmi_audio_config_update(struct intel_encoder *encoder,
n = audio_config_hdmi_get_n(crtc_state, rate);
if (n != 0) {
- drm_dbg_kms(&dev_priv->drm, "using N %d\n", n);
+ drm_dbg_kms(&i915->drm, "using N %d\n", n);
tmp &= ~AUD_CONFIG_N_MASK;
tmp |= AUD_CONFIG_N(n);
tmp |= AUD_CONFIG_N_PROG_ENABLE;
} else {
- drm_dbg_kms(&dev_priv->drm, "using automatic N\n");
+ drm_dbg_kms(&i915->drm, "using automatic N\n");
}
- intel_de_write(dev_priv, HSW_AUD_CFG(cpu_transcoder), tmp);
+ intel_de_write(i915, HSW_AUD_CFG(cpu_transcoder), tmp);
/*
* Let's disable "Enable CTS or M Prog bit"
* and let HW calculate the value
*/
- tmp = intel_de_read(dev_priv, HSW_AUD_M_CTS_ENABLE(cpu_transcoder));
+ tmp = intel_de_read(i915, HSW_AUD_M_CTS_ENABLE(cpu_transcoder));
tmp &= ~AUD_M_CTS_M_PROG_ENABLE;
tmp &= ~AUD_M_CTS_M_VALUE_INDEX;
- intel_de_write(dev_priv, HSW_AUD_M_CTS_ENABLE(cpu_transcoder), tmp);
+ intel_de_write(i915, HSW_AUD_M_CTS_ENABLE(cpu_transcoder), tmp);
}
static void
@@ -488,33 +459,48 @@ hsw_audio_config_update(struct intel_encoder *encoder,
hsw_hdmi_audio_config_update(encoder, crtc_state);
}
+/* ELD buffer size in dwords */
+static int hsw_eld_buffer_size(struct drm_i915_private *i915,
+ enum transcoder cpu_transcoder)
+{
+ u32 tmp;
+
+ tmp = intel_de_read(i915, HSW_AUD_DIP_ELD_CTRL(cpu_transcoder));
+
+ return REG_FIELD_GET(IBX_ELD_BUFFER_SIZE_MASK, tmp);
+}
+
static void hsw_audio_codec_disable(struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder;
- u32 tmp;
- mutex_lock(&dev_priv->display.audio.mutex);
+ mutex_lock(&i915->display.audio.mutex);
/* Disable timestamps */
- tmp = intel_de_read(dev_priv, HSW_AUD_CFG(cpu_transcoder));
- tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
- tmp |= AUD_CONFIG_N_PROG_ENABLE;
- tmp &= ~AUD_CONFIG_UPPER_N_MASK;
- tmp &= ~AUD_CONFIG_LOWER_N_MASK;
- if (intel_crtc_has_dp_encoder(old_crtc_state))
- tmp |= AUD_CONFIG_N_VALUE_INDEX;
- intel_de_write(dev_priv, HSW_AUD_CFG(cpu_transcoder), tmp);
+ intel_de_rmw(i915, HSW_AUD_CFG(cpu_transcoder),
+ AUD_CONFIG_N_VALUE_INDEX |
+ AUD_CONFIG_UPPER_N_MASK |
+ AUD_CONFIG_LOWER_N_MASK,
+ AUD_CONFIG_N_PROG_ENABLE |
+ (intel_crtc_has_dp_encoder(old_crtc_state) ?
+ AUD_CONFIG_N_VALUE_INDEX : 0));
/* Invalidate ELD */
- tmp = intel_de_read(dev_priv, HSW_AUD_PIN_ELD_CP_VLD);
- tmp &= ~AUDIO_ELD_VALID(cpu_transcoder);
- tmp &= ~AUDIO_OUTPUT_ENABLE(cpu_transcoder);
- intel_de_write(dev_priv, HSW_AUD_PIN_ELD_CP_VLD, tmp);
+ intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD,
+ AUDIO_ELD_VALID(cpu_transcoder), 0);
+
+ intel_crtc_wait_for_next_vblank(crtc);
+ intel_crtc_wait_for_next_vblank(crtc);
- mutex_unlock(&dev_priv->display.audio.mutex);
+ /* Disable audio presence detect */
+ intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD,
+ AUDIO_OUTPUT_ENABLE(cpu_transcoder), 0);
+
+ mutex_unlock(&i915->display.audio.mutex);
}
static unsigned int calc_hblank_early_prog(struct intel_encoder *encoder,
@@ -626,178 +612,190 @@ static void enable_audio_dsc_wa(struct intel_encoder *encoder,
intel_de_write(i915, AUD_CONFIG_BE, val);
}
-#undef ROUNDING_FACTOR
-
static void hsw_audio_codec_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_connector *connector = conn_state->connector;
enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
- const u8 *eld = connector->eld;
- u32 tmp;
- int len, i;
+ const u32 *eld = (const u32 *)connector->eld;
+ int eld_buffer_size, len, i;
- mutex_lock(&dev_priv->display.audio.mutex);
+ mutex_lock(&i915->display.audio.mutex);
/* Enable Audio WA for 4k DSC usecases */
if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP))
enable_audio_dsc_wa(encoder, crtc_state);
- /* Enable audio presence detect, invalidate ELD */
- tmp = intel_de_read(dev_priv, HSW_AUD_PIN_ELD_CP_VLD);
- tmp |= AUDIO_OUTPUT_ENABLE(cpu_transcoder);
- tmp &= ~AUDIO_ELD_VALID(cpu_transcoder);
- intel_de_write(dev_priv, HSW_AUD_PIN_ELD_CP_VLD, tmp);
+ /* Enable audio presence detect */
+ intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD,
+ 0, AUDIO_OUTPUT_ENABLE(cpu_transcoder));
- /*
- * FIXME: We're supposed to wait for vblank here, but we have vblanks
- * disabled during the mode set. The proper fix would be to push the
- * rest of the setup into a vblank work item, queued here, but the
- * infrastructure is not there yet.
- */
+ intel_crtc_wait_for_next_vblank(crtc);
+
+ /* Invalidate ELD */
+ intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD,
+ AUDIO_ELD_VALID(cpu_transcoder), 0);
+
+ /* Reset ELD address */
+ intel_de_rmw(i915, HSW_AUD_DIP_ELD_CTRL(cpu_transcoder),
+ IBX_ELD_ADDRESS_MASK, 0);
- /* Reset ELD write address */
- tmp = intel_de_read(dev_priv, HSW_AUD_DIP_ELD_CTRL(cpu_transcoder));
- tmp &= ~IBX_ELD_ADDRESS_MASK;
- intel_de_write(dev_priv, HSW_AUD_DIP_ELD_CTRL(cpu_transcoder), tmp);
+ eld_buffer_size = hsw_eld_buffer_size(i915, cpu_transcoder);
+ len = min(drm_eld_size(connector->eld) / 4, eld_buffer_size);
- /* Up to 84 bytes of hw ELD buffer */
- len = min(drm_eld_size(eld), 84);
- for (i = 0; i < len / 4; i++)
- intel_de_write(dev_priv, HSW_AUD_EDID_DATA(cpu_transcoder),
- *((const u32 *)eld + i));
+ for (i = 0; i < len; i++)
+ intel_de_write(i915, HSW_AUD_EDID_DATA(cpu_transcoder), eld[i]);
+ for (; i < eld_buffer_size; i++)
+ intel_de_write(i915, HSW_AUD_EDID_DATA(cpu_transcoder), 0);
+
+ drm_WARN_ON(&i915->drm,
+ (intel_de_read(i915, HSW_AUD_DIP_ELD_CTRL(cpu_transcoder)) &
+ IBX_ELD_ADDRESS_MASK) != 0);
/* ELD valid */
- tmp = intel_de_read(dev_priv, HSW_AUD_PIN_ELD_CP_VLD);
- tmp |= AUDIO_ELD_VALID(cpu_transcoder);
- intel_de_write(dev_priv, HSW_AUD_PIN_ELD_CP_VLD, tmp);
+ intel_de_rmw(i915, HSW_AUD_PIN_ELD_CP_VLD,
+ 0, AUDIO_ELD_VALID(cpu_transcoder));
/* Enable timestamps */
hsw_audio_config_update(encoder, crtc_state);
- mutex_unlock(&dev_priv->display.audio.mutex);
+ mutex_unlock(&i915->display.audio.mutex);
+}
+
+struct ilk_audio_regs {
+ i915_reg_t hdmiw_hdmiedid, aud_config, aud_cntl_st, aud_cntrl_st2;
+};
+
+static void ilk_audio_regs_init(struct drm_i915_private *i915,
+ enum pipe pipe,
+ struct ilk_audio_regs *regs)
+{
+ if (HAS_PCH_IBX(i915)) {
+ regs->hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe);
+ regs->aud_config = IBX_AUD_CFG(pipe);
+ regs->aud_cntl_st = IBX_AUD_CNTL_ST(pipe);
+ regs->aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
+ } else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
+ regs->hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe);
+ regs->aud_config = VLV_AUD_CFG(pipe);
+ regs->aud_cntl_st = VLV_AUD_CNTL_ST(pipe);
+ regs->aud_cntrl_st2 = VLV_AUD_CNTL_ST2;
+ } else {
+ regs->hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID(pipe);
+ regs->aud_config = CPT_AUD_CFG(pipe);
+ regs->aud_cntl_st = CPT_AUD_CNTL_ST(pipe);
+ regs->aud_cntrl_st2 = CPT_AUD_CNTRL_ST2;
+ }
+}
+
+/* ELD buffer size in dwords */
+static int ilk_eld_buffer_size(struct drm_i915_private *i915,
+ enum pipe pipe)
+{
+ struct ilk_audio_regs regs;
+ u32 tmp;
+
+ ilk_audio_regs_init(i915, pipe, &regs);
+
+ tmp = intel_de_read(i915, regs.aud_cntl_st);
+
+ return REG_FIELD_GET(IBX_ELD_BUFFER_SIZE_MASK, tmp);
}
static void ilk_audio_codec_disable(struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
- enum pipe pipe = crtc->pipe;
enum port port = encoder->port;
- u32 tmp, eldv;
- i915_reg_t aud_config, aud_cntrl_st2;
+ enum pipe pipe = crtc->pipe;
+ struct ilk_audio_regs regs;
- if (drm_WARN_ON(&dev_priv->drm, port == PORT_A))
+ if (drm_WARN_ON(&i915->drm, port == PORT_A))
return;
- if (HAS_PCH_IBX(dev_priv)) {
- aud_config = IBX_AUD_CFG(pipe);
- aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
- } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
- aud_config = VLV_AUD_CFG(pipe);
- aud_cntrl_st2 = VLV_AUD_CNTL_ST2;
- } else {
- aud_config = CPT_AUD_CFG(pipe);
- aud_cntrl_st2 = CPT_AUD_CNTRL_ST2;
- }
+ ilk_audio_regs_init(i915, pipe, &regs);
- /* Disable timestamps */
- tmp = intel_de_read(dev_priv, aud_config);
- tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
- tmp |= AUD_CONFIG_N_PROG_ENABLE;
- tmp &= ~AUD_CONFIG_UPPER_N_MASK;
- tmp &= ~AUD_CONFIG_LOWER_N_MASK;
- if (intel_crtc_has_dp_encoder(old_crtc_state))
- tmp |= AUD_CONFIG_N_VALUE_INDEX;
- intel_de_write(dev_priv, aud_config, tmp);
+ mutex_lock(&i915->display.audio.mutex);
- eldv = IBX_ELD_VALID(port);
+ /* Disable timestamps */
+ intel_de_rmw(i915, regs.aud_config,
+ AUD_CONFIG_N_VALUE_INDEX |
+ AUD_CONFIG_UPPER_N_MASK |
+ AUD_CONFIG_LOWER_N_MASK,
+ AUD_CONFIG_N_PROG_ENABLE |
+ (intel_crtc_has_dp_encoder(old_crtc_state) ?
+ AUD_CONFIG_N_VALUE_INDEX : 0));
/* Invalidate ELD */
- tmp = intel_de_read(dev_priv, aud_cntrl_st2);
- tmp &= ~eldv;
- intel_de_write(dev_priv, aud_cntrl_st2, tmp);
+ intel_de_rmw(i915, regs.aud_cntrl_st2,
+ IBX_ELD_VALID(port), 0);
+
+ mutex_unlock(&i915->display.audio.mutex);
+
+ intel_crtc_wait_for_next_vblank(crtc);
+ intel_crtc_wait_for_next_vblank(crtc);
}
static void ilk_audio_codec_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_connector *connector = conn_state->connector;
- enum pipe pipe = crtc->pipe;
+ const u32 *eld = (const u32 *)connector->eld;
enum port port = encoder->port;
- const u8 *eld = connector->eld;
- u32 tmp, eldv;
- int len, i;
- i915_reg_t hdmiw_hdmiedid, aud_config, aud_cntl_st, aud_cntrl_st2;
+ enum pipe pipe = crtc->pipe;
+ int eld_buffer_size, len, i;
+ struct ilk_audio_regs regs;
- if (drm_WARN_ON(&dev_priv->drm, port == PORT_A))
+ if (drm_WARN_ON(&i915->drm, port == PORT_A))
return;
- /*
- * FIXME: We're supposed to wait for vblank here, but we have vblanks
- * disabled during the mode set. The proper fix would be to push the
- * rest of the setup into a vblank work item, queued here, but the
- * infrastructure is not there yet.
- */
+ intel_crtc_wait_for_next_vblank(crtc);
- if (HAS_PCH_IBX(dev_priv)) {
- hdmiw_hdmiedid = IBX_HDMIW_HDMIEDID(pipe);
- aud_config = IBX_AUD_CFG(pipe);
- aud_cntl_st = IBX_AUD_CNTL_ST(pipe);
- aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
- } else if (IS_VALLEYVIEW(dev_priv) ||
- IS_CHERRYVIEW(dev_priv)) {
- hdmiw_hdmiedid = VLV_HDMIW_HDMIEDID(pipe);
- aud_config = VLV_AUD_CFG(pipe);
- aud_cntl_st = VLV_AUD_CNTL_ST(pipe);
- aud_cntrl_st2 = VLV_AUD_CNTL_ST2;
- } else {
- hdmiw_hdmiedid = CPT_HDMIW_HDMIEDID(pipe);
- aud_config = CPT_AUD_CFG(pipe);
- aud_cntl_st = CPT_AUD_CNTL_ST(pipe);
- aud_cntrl_st2 = CPT_AUD_CNTRL_ST2;
- }
+ ilk_audio_regs_init(i915, pipe, &regs);
- eldv = IBX_ELD_VALID(port);
+ mutex_lock(&i915->display.audio.mutex);
/* Invalidate ELD */
- tmp = intel_de_read(dev_priv, aud_cntrl_st2);
- tmp &= ~eldv;
- intel_de_write(dev_priv, aud_cntrl_st2, tmp);
+ intel_de_rmw(i915, regs.aud_cntrl_st2,
+ IBX_ELD_VALID(port), 0);
+
+ /* Reset ELD address */
+ intel_de_rmw(i915, regs.aud_cntl_st,
+ IBX_ELD_ADDRESS_MASK, 0);
- /* Reset ELD write address */
- tmp = intel_de_read(dev_priv, aud_cntl_st);
- tmp &= ~IBX_ELD_ADDRESS_MASK;
- intel_de_write(dev_priv, aud_cntl_st, tmp);
+ eld_buffer_size = ilk_eld_buffer_size(i915, pipe);
+ len = min(drm_eld_size(connector->eld) / 4, eld_buffer_size);
- /* Up to 84 bytes of hw ELD buffer */
- len = min(drm_eld_size(eld), 84);
- for (i = 0; i < len / 4; i++)
- intel_de_write(dev_priv, hdmiw_hdmiedid,
- *((const u32 *)eld + i));
+ for (i = 0; i < len; i++)
+ intel_de_write(i915, regs.hdmiw_hdmiedid, eld[i]);
+ for (; i < eld_buffer_size; i++)
+ intel_de_write(i915, regs.hdmiw_hdmiedid, 0);
+
+ drm_WARN_ON(&i915->drm,
+ (intel_de_read(i915, regs.aud_cntl_st) & IBX_ELD_ADDRESS_MASK) != 0);
/* ELD valid */
- tmp = intel_de_read(dev_priv, aud_cntrl_st2);
- tmp |= eldv;
- intel_de_write(dev_priv, aud_cntrl_st2, tmp);
+ intel_de_rmw(i915, regs.aud_cntrl_st2,
+ 0, IBX_ELD_VALID(port));
/* Enable timestamps */
- tmp = intel_de_read(dev_priv, aud_config);
- tmp &= ~AUD_CONFIG_N_VALUE_INDEX;
- tmp &= ~AUD_CONFIG_N_PROG_ENABLE;
- tmp &= ~AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK;
- if (intel_crtc_has_dp_encoder(crtc_state))
- tmp |= AUD_CONFIG_N_VALUE_INDEX;
- else
- tmp |= audio_config_hdmi_pixel_clock(crtc_state);
- intel_de_write(dev_priv, aud_config, tmp);
+ intel_de_rmw(i915, regs.aud_config,
+ AUD_CONFIG_N_VALUE_INDEX |
+ AUD_CONFIG_N_PROG_ENABLE |
+ AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK,
+ (intel_crtc_has_dp_encoder(crtc_state) ?
+ AUD_CONFIG_N_VALUE_INDEX :
+ audio_config_hdmi_pixel_clock(crtc_state)));
+
+ mutex_unlock(&i915->display.audio.mutex);
}
/**
@@ -813,8 +811,8 @@ void intel_audio_codec_enable(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
const struct drm_connector_state *conn_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct i915_audio_component *acomp = dev_priv->display.audio.component;
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct i915_audio_component *acomp = i915->display.audio.component;
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct drm_connector *connector = conn_state->connector;
const struct drm_display_mode *adjusted_mode =
@@ -825,30 +823,30 @@ void intel_audio_codec_enable(struct intel_encoder *encoder,
if (!crtc_state->has_audio)
return;
- drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Enable audio codec on pipe %c, %u bytes ELD\n",
+ drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Enable audio codec on pipe %c, %u bytes ELD\n",
connector->base.id, connector->name,
encoder->base.base.id, encoder->base.name,
pipe_name(pipe), drm_eld_size(connector->eld));
/* FIXME precompute the ELD in .compute_config() */
if (!connector->eld[0])
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"Bogus ELD on [CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2;
- if (dev_priv->display.funcs.audio)
- dev_priv->display.funcs.audio->audio_codec_enable(encoder,
- crtc_state,
- conn_state);
+ if (i915->display.funcs.audio)
+ i915->display.funcs.audio->audio_codec_enable(encoder,
+ crtc_state,
+ conn_state);
- mutex_lock(&dev_priv->display.audio.mutex);
+ mutex_lock(&i915->display.audio.mutex);
encoder->audio_connector = connector;
/* referred in audio callbacks */
- dev_priv->display.audio.encoder_map[pipe] = encoder;
- mutex_unlock(&dev_priv->display.audio.mutex);
+ i915->display.audio.encoder_map[pipe] = encoder;
+ mutex_unlock(&i915->display.audio.mutex);
if (acomp && acomp->base.audio_ops &&
acomp->base.audio_ops->pin_eld_notify) {
@@ -856,10 +854,10 @@ void intel_audio_codec_enable(struct intel_encoder *encoder,
if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST))
pipe = -1;
acomp->base.audio_ops->pin_eld_notify(acomp->base.audio_ops->audio_ptr,
- (int) port, (int) pipe);
+ (int)port, (int)pipe);
}
- intel_lpe_audio_notify(dev_priv, pipe, port, connector->eld,
+ intel_lpe_audio_notify(i915, pipe, port, connector->eld,
crtc_state->port_clock,
intel_crtc_has_dp_encoder(crtc_state));
}
@@ -877,8 +875,8 @@ void intel_audio_codec_disable(struct intel_encoder *encoder,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
- struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct i915_audio_component *acomp = dev_priv->display.audio.component;
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct i915_audio_component *acomp = i915->display.audio.component;
struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc);
struct drm_connector *connector = old_conn_state->connector;
enum port port = encoder->port;
@@ -887,19 +885,19 @@ void intel_audio_codec_disable(struct intel_encoder *encoder,
if (!old_crtc_state->has_audio)
return;
- drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Disable audio codec on pipe %c\n",
+ drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Disable audio codec on pipe %c\n",
connector->base.id, connector->name,
encoder->base.base.id, encoder->base.name, pipe_name(pipe));
- if (dev_priv->display.funcs.audio)
- dev_priv->display.funcs.audio->audio_codec_disable(encoder,
- old_crtc_state,
- old_conn_state);
+ if (i915->display.funcs.audio)
+ i915->display.funcs.audio->audio_codec_disable(encoder,
+ old_crtc_state,
+ old_conn_state);
- mutex_lock(&dev_priv->display.audio.mutex);
+ mutex_lock(&i915->display.audio.mutex);
encoder->audio_connector = NULL;
- dev_priv->display.audio.encoder_map[pipe] = NULL;
- mutex_unlock(&dev_priv->display.audio.mutex);
+ i915->display.audio.encoder_map[pipe] = NULL;
+ mutex_unlock(&i915->display.audio.mutex);
if (acomp && acomp->base.audio_ops &&
acomp->base.audio_ops->pin_eld_notify) {
@@ -907,10 +905,10 @@ void intel_audio_codec_disable(struct intel_encoder *encoder,
if (!intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_DP_MST))
pipe = -1;
acomp->base.audio_ops->pin_eld_notify(acomp->base.audio_ops->audio_ptr,
- (int) port, (int) pipe);
+ (int)port, (int)pipe);
}
- intel_lpe_audio_notify(dev_priv, pipe, port, NULL, 0, false);
+ intel_lpe_audio_notify(i915, pipe, port, NULL, 0, false);
}
static const struct intel_audio_funcs g4x_audio_funcs = {
@@ -930,19 +928,18 @@ static const struct intel_audio_funcs hsw_audio_funcs = {
/**
* intel_audio_hooks_init - Set up chip specific audio hooks
- * @dev_priv: device private
+ * @i915: device private
*/
-void intel_audio_hooks_init(struct drm_i915_private *dev_priv)
+void intel_audio_hooks_init(struct drm_i915_private *i915)
{
- if (IS_G4X(dev_priv)) {
- dev_priv->display.funcs.audio = &g4x_audio_funcs;
- } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
- dev_priv->display.funcs.audio = &ilk_audio_funcs;
- } else if (IS_HASWELL(dev_priv) || DISPLAY_VER(dev_priv) >= 8) {
- dev_priv->display.funcs.audio = &hsw_audio_funcs;
- } else if (HAS_PCH_SPLIT(dev_priv)) {
- dev_priv->display.funcs.audio = &ilk_audio_funcs;
- }
+ if (IS_G4X(i915))
+ i915->display.funcs.audio = &g4x_audio_funcs;
+ else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
+ i915->display.funcs.audio = &ilk_audio_funcs;
+ else if (IS_HASWELL(i915) || DISPLAY_VER(i915) >= 8)
+ i915->display.funcs.audio = &hsw_audio_funcs;
+ else if (HAS_PCH_SPLIT(i915))
+ i915->display.funcs.audio = &ilk_audio_funcs;
}
struct aud_ts_cdclk_m_n {
@@ -1000,7 +997,7 @@ static int glk_force_audio_cdclk_commit(struct intel_atomic_state *state,
return drm_atomic_commit(&state->base);
}
-static void glk_force_audio_cdclk(struct drm_i915_private *dev_priv,
+static void glk_force_audio_cdclk(struct drm_i915_private *i915,
bool enable)
{
struct drm_modeset_acquire_ctx ctx;
@@ -1008,13 +1005,13 @@ static void glk_force_audio_cdclk(struct drm_i915_private *dev_priv,
struct intel_crtc *crtc;
int ret;
- crtc = intel_first_crtc(dev_priv);
+ crtc = intel_first_crtc(i915);
if (!crtc)
return;
drm_modeset_acquire_init(&ctx, 0);
- state = drm_atomic_state_alloc(&dev_priv->drm);
- if (drm_WARN_ON(&dev_priv->drm, !state))
+ state = drm_atomic_state_alloc(&i915->drm);
+ if (drm_WARN_ON(&i915->drm, !state))
return;
state->acquire_ctx = &ctx;
@@ -1028,7 +1025,7 @@ retry:
goto retry;
}
- drm_WARN_ON(&dev_priv->drm, ret);
+ drm_WARN_ON(&i915->drm, ret);
drm_atomic_state_put(state);
@@ -1038,30 +1035,30 @@ retry:
static unsigned long i915_audio_component_get_power(struct device *kdev)
{
- struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
+ struct drm_i915_private *i915 = kdev_to_i915(kdev);
intel_wakeref_t ret;
/* Catch potential impedance mismatches before they occur! */
BUILD_BUG_ON(sizeof(intel_wakeref_t) > sizeof(unsigned long));
- ret = intel_display_power_get(dev_priv, POWER_DOMAIN_AUDIO_PLAYBACK);
+ ret = intel_display_power_get(i915, POWER_DOMAIN_AUDIO_PLAYBACK);
- if (dev_priv->display.audio.power_refcount++ == 0) {
- if (DISPLAY_VER(dev_priv) >= 9) {
- intel_de_write(dev_priv, AUD_FREQ_CNTRL,
- dev_priv->display.audio.freq_cntrl);
- drm_dbg_kms(&dev_priv->drm,
+ if (i915->display.audio.power_refcount++ == 0) {
+ if (DISPLAY_VER(i915) >= 9) {
+ intel_de_write(i915, AUD_FREQ_CNTRL,
+ i915->display.audio.freq_cntrl);
+ drm_dbg_kms(&i915->drm,
"restored AUD_FREQ_CNTRL to 0x%x\n",
- dev_priv->display.audio.freq_cntrl);
+ i915->display.audio.freq_cntrl);
}
/* Force CDCLK to 2*BCLK as long as we need audio powered. */
- if (IS_GEMINILAKE(dev_priv))
- glk_force_audio_cdclk(dev_priv, true);
+ if (IS_GEMINILAKE(i915))
+ glk_force_audio_cdclk(i915, true);
- if (DISPLAY_VER(dev_priv) >= 10)
- intel_de_write(dev_priv, AUD_PIN_BUF_CTL,
- (intel_de_read(dev_priv, AUD_PIN_BUF_CTL) | AUD_PIN_BUF_ENABLE));
+ if (DISPLAY_VER(i915) >= 10)
+ intel_de_rmw(i915, AUD_PIN_BUF_CTL,
+ 0, AUD_PIN_BUF_ENABLE);
}
return ret;
@@ -1070,24 +1067,23 @@ static unsigned long i915_audio_component_get_power(struct device *kdev)
static void i915_audio_component_put_power(struct device *kdev,
unsigned long cookie)
{
- struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
+ struct drm_i915_private *i915 = kdev_to_i915(kdev);
/* Stop forcing CDCLK to 2*BCLK if no need for audio to be powered. */
- if (--dev_priv->display.audio.power_refcount == 0)
- if (IS_GEMINILAKE(dev_priv))
- glk_force_audio_cdclk(dev_priv, false);
+ if (--i915->display.audio.power_refcount == 0)
+ if (IS_GEMINILAKE(i915))
+ glk_force_audio_cdclk(i915, false);
- intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO_PLAYBACK, cookie);
+ intel_display_power_put(i915, POWER_DOMAIN_AUDIO_PLAYBACK, cookie);
}
static void i915_audio_component_codec_wake_override(struct device *kdev,
bool enable)
{
- struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
+ struct drm_i915_private *i915 = kdev_to_i915(kdev);
unsigned long cookie;
- u32 tmp;
- if (DISPLAY_VER(dev_priv) < 9)
+ if (DISPLAY_VER(i915) < 9)
return;
cookie = i915_audio_component_get_power(kdev);
@@ -1096,15 +1092,13 @@ static void i915_audio_component_codec_wake_override(struct device *kdev,
* Enable/disable generating the codec wake signal, overriding the
* internal logic to generate the codec wake to controller.
*/
- tmp = intel_de_read(dev_priv, HSW_AUD_CHICKENBIT);
- tmp &= ~SKL_AUD_CODEC_WAKE_SIGNAL;
- intel_de_write(dev_priv, HSW_AUD_CHICKENBIT, tmp);
+ intel_de_rmw(i915, HSW_AUD_CHICKENBIT,
+ SKL_AUD_CODEC_WAKE_SIGNAL, 0);
usleep_range(1000, 1500);
if (enable) {
- tmp = intel_de_read(dev_priv, HSW_AUD_CHICKENBIT);
- tmp |= SKL_AUD_CODEC_WAKE_SIGNAL;
- intel_de_write(dev_priv, HSW_AUD_CHICKENBIT, tmp);
+ intel_de_rmw(i915, HSW_AUD_CHICKENBIT,
+ 0, SKL_AUD_CODEC_WAKE_SIGNAL);
usleep_range(1000, 1500);
}
@@ -1114,12 +1108,12 @@ static void i915_audio_component_codec_wake_override(struct device *kdev,
/* Get CDCLK in kHz */
static int i915_audio_component_get_cdclk_freq(struct device *kdev)
{
- struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
+ struct drm_i915_private *i915 = kdev_to_i915(kdev);
- if (drm_WARN_ON_ONCE(&dev_priv->drm, !HAS_DDI(dev_priv)))
+ if (drm_WARN_ON_ONCE(&i915->drm, !HAS_DDI(i915)))
return -ENODEV;
- return dev_priv->display.cdclk.hw.cdclk;
+ return i915->display.cdclk.hw.cdclk;
}
/*
@@ -1132,24 +1126,24 @@ static int i915_audio_component_get_cdclk_freq(struct device *kdev)
* will get the right intel_encoder with port matched
* Non-MST & (pipe < 0): get the right intel_encoder with port matched
*/
-static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv,
- int port, int pipe)
+static struct intel_encoder *get_saved_enc(struct drm_i915_private *i915,
+ int port, int pipe)
{
- struct intel_encoder *encoder;
-
/* MST */
if (pipe >= 0) {
- if (drm_WARN_ON(&dev_priv->drm,
- pipe >= ARRAY_SIZE(dev_priv->display.audio.encoder_map)))
+ struct intel_encoder *encoder;
+
+ if (drm_WARN_ON(&i915->drm,
+ pipe >= ARRAY_SIZE(i915->display.audio.encoder_map)))
return NULL;
- encoder = dev_priv->display.audio.encoder_map[pipe];
+ encoder = i915->display.audio.encoder_map[pipe];
/*
* when bootup, audio driver may not know it is
* MST or not. So it will poll all the port & pipe
* combinations
*/
- if (encoder != NULL && encoder->port == port &&
+ if (encoder && encoder->port == port &&
encoder->type == INTEL_OUTPUT_DP_MST)
return encoder;
}
@@ -1158,15 +1152,13 @@ static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv,
if (pipe > 0)
return NULL;
- for_each_pipe(dev_priv, pipe) {
- encoder = dev_priv->display.audio.encoder_map[pipe];
- if (encoder == NULL)
- continue;
+ for_each_pipe(i915, pipe) {
+ struct intel_encoder *encoder;
- if (encoder->type == INTEL_OUTPUT_DP_MST)
- continue;
+ encoder = i915->display.audio.encoder_map[pipe];
- if (port == encoder->port)
+ if (encoder && encoder->port == port &&
+ encoder->type != INTEL_OUTPUT_DP_MST)
return encoder;
}
@@ -1176,23 +1168,23 @@ static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv,
static int i915_audio_component_sync_audio_rate(struct device *kdev, int port,
int pipe, int rate)
{
- struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
- struct i915_audio_component *acomp = dev_priv->display.audio.component;
+ struct drm_i915_private *i915 = kdev_to_i915(kdev);
+ struct i915_audio_component *acomp = i915->display.audio.component;
struct intel_encoder *encoder;
struct intel_crtc *crtc;
unsigned long cookie;
int err = 0;
- if (!HAS_DDI(dev_priv))
+ if (!HAS_DDI(i915))
return 0;
cookie = i915_audio_component_get_power(kdev);
- mutex_lock(&dev_priv->display.audio.mutex);
+ mutex_lock(&i915->display.audio.mutex);
/* 1. get the pipe */
- encoder = get_saved_enc(dev_priv, port, pipe);
+ encoder = get_saved_enc(i915, port, pipe);
if (!encoder || !encoder->base.crtc) {
- drm_dbg_kms(&dev_priv->drm, "Not valid for port %c\n",
+ drm_dbg_kms(&i915->drm, "Not valid for port %c\n",
port_name(port));
err = -ENODEV;
goto unlock;
@@ -1206,7 +1198,7 @@ static int i915_audio_component_sync_audio_rate(struct device *kdev, int port,
hsw_audio_config_update(encoder, crtc->config);
unlock:
- mutex_unlock(&dev_priv->display.audio.mutex);
+ mutex_unlock(&i915->display.audio.mutex);
i915_audio_component_put_power(kdev, cookie);
return err;
}
@@ -1215,18 +1207,18 @@ static int i915_audio_component_get_eld(struct device *kdev, int port,
int pipe, bool *enabled,
unsigned char *buf, int max_bytes)
{
- struct drm_i915_private *dev_priv = kdev_to_i915(kdev);
+ struct drm_i915_private *i915 = kdev_to_i915(kdev);
struct intel_encoder *intel_encoder;
const u8 *eld;
int ret = -EINVAL;
- mutex_lock(&dev_priv->display.audio.mutex);
+ mutex_lock(&i915->display.audio.mutex);
- intel_encoder = get_saved_enc(dev_priv, port, pipe);
+ intel_encoder = get_saved_enc(i915, port, pipe);
if (!intel_encoder) {
- drm_dbg_kms(&dev_priv->drm, "Not valid for port %c\n",
+ drm_dbg_kms(&i915->drm, "Not valid for port %c\n",
port_name(port));
- mutex_unlock(&dev_priv->display.audio.mutex);
+ mutex_unlock(&i915->display.audio.mutex);
return ret;
}
@@ -1238,7 +1230,7 @@ static int i915_audio_component_get_eld(struct device *kdev, int port,
memcpy(buf, eld, min(max_bytes, ret));
}
- mutex_unlock(&dev_priv->display.audio.mutex);
+ mutex_unlock(&i915->display.audio.mutex);
return ret;
}
@@ -1256,25 +1248,25 @@ static int i915_audio_component_bind(struct device *i915_kdev,
struct device *hda_kdev, void *data)
{
struct i915_audio_component *acomp = data;
- struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev);
+ struct drm_i915_private *i915 = kdev_to_i915(i915_kdev);
int i;
- if (drm_WARN_ON(&dev_priv->drm, acomp->base.ops || acomp->base.dev))
+ if (drm_WARN_ON(&i915->drm, acomp->base.ops || acomp->base.dev))
return -EEXIST;
- if (drm_WARN_ON(&dev_priv->drm,
+ if (drm_WARN_ON(&i915->drm,
!device_link_add(hda_kdev, i915_kdev,
DL_FLAG_STATELESS)))
return -ENOMEM;
- drm_modeset_lock_all(&dev_priv->drm);
+ drm_modeset_lock_all(&i915->drm);
acomp->base.ops = &i915_audio_component_ops;
acomp->base.dev = i915_kdev;
BUILD_BUG_ON(MAX_PORTS != I915_MAX_PORTS);
for (i = 0; i < ARRAY_SIZE(acomp->aud_sample_rate); i++)
acomp->aud_sample_rate[i] = 0;
- dev_priv->display.audio.component = acomp;
- drm_modeset_unlock_all(&dev_priv->drm);
+ i915->display.audio.component = acomp;
+ drm_modeset_unlock_all(&i915->drm);
return 0;
}
@@ -1283,19 +1275,19 @@ static void i915_audio_component_unbind(struct device *i915_kdev,
struct device *hda_kdev, void *data)
{
struct i915_audio_component *acomp = data;
- struct drm_i915_private *dev_priv = kdev_to_i915(i915_kdev);
+ struct drm_i915_private *i915 = kdev_to_i915(i915_kdev);
- drm_modeset_lock_all(&dev_priv->drm);
+ drm_modeset_lock_all(&i915->drm);
acomp->base.ops = NULL;
acomp->base.dev = NULL;
- dev_priv->display.audio.component = NULL;
- drm_modeset_unlock_all(&dev_priv->drm);
+ i915->display.audio.component = NULL;
+ drm_modeset_unlock_all(&i915->drm);
device_link_remove(hda_kdev, i915_kdev);
- if (dev_priv->display.audio.power_refcount)
- drm_err(&dev_priv->drm, "audio power refcount %d after unbind\n",
- dev_priv->display.audio.power_refcount);
+ if (i915->display.audio.power_refcount)
+ drm_err(&i915->drm, "audio power refcount %d after unbind\n",
+ i915->display.audio.power_refcount);
}
static const struct component_ops i915_audio_component_bind_ops = {
@@ -1314,7 +1306,7 @@ static const struct component_ops i915_audio_component_bind_ops = {
/**
* i915_audio_component_init - initialize and register the audio component
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
*
* This will register with the component framework a child component which
* will bind dynamically to the snd_hda_intel driver's corresponding master
@@ -1328,83 +1320,83 @@ static const struct component_ops i915_audio_component_bind_ops = {
* We ignore any error during registration and continue with reduced
* functionality (i.e. without HDMI audio).
*/
-static void i915_audio_component_init(struct drm_i915_private *dev_priv)
+static void i915_audio_component_init(struct drm_i915_private *i915)
{
u32 aud_freq, aud_freq_init;
int ret;
- ret = component_add_typed(dev_priv->drm.dev,
+ ret = component_add_typed(i915->drm.dev,
&i915_audio_component_bind_ops,
I915_COMPONENT_AUDIO);
if (ret < 0) {
- drm_err(&dev_priv->drm,
+ drm_err(&i915->drm,
"failed to add audio component (%d)\n", ret);
/* continue with reduced functionality */
return;
}
- if (DISPLAY_VER(dev_priv) >= 9) {
- aud_freq_init = intel_de_read(dev_priv, AUD_FREQ_CNTRL);
+ if (DISPLAY_VER(i915) >= 9) {
+ aud_freq_init = intel_de_read(i915, AUD_FREQ_CNTRL);
- if (DISPLAY_VER(dev_priv) >= 12)
+ if (DISPLAY_VER(i915) >= 12)
aud_freq = AUD_FREQ_GEN12;
else
aud_freq = aud_freq_init;
/* use BIOS provided value for TGL and RKL unless it is a known bad value */
- if ((IS_TIGERLAKE(dev_priv) || IS_ROCKETLAKE(dev_priv)) &&
+ if ((IS_TIGERLAKE(i915) || IS_ROCKETLAKE(i915)) &&
aud_freq_init != AUD_FREQ_TGL_BROKEN)
aud_freq = aud_freq_init;
- drm_dbg_kms(&dev_priv->drm, "use AUD_FREQ_CNTRL of 0x%x (init value 0x%x)\n",
+ drm_dbg_kms(&i915->drm, "use AUD_FREQ_CNTRL of 0x%x (init value 0x%x)\n",
aud_freq, aud_freq_init);
- dev_priv->display.audio.freq_cntrl = aud_freq;
+ i915->display.audio.freq_cntrl = aud_freq;
}
/* init with current cdclk */
- intel_audio_cdclk_change_post(dev_priv);
+ intel_audio_cdclk_change_post(i915);
- dev_priv->display.audio.component_registered = true;
+ i915->display.audio.component_registered = true;
}
/**
* i915_audio_component_cleanup - deregister the audio component
- * @dev_priv: i915 device instance
+ * @i915: i915 device instance
*
* Deregisters the audio component, breaking any existing binding to the
* corresponding snd_hda_intel driver's master component.
*/
-static void i915_audio_component_cleanup(struct drm_i915_private *dev_priv)
+static void i915_audio_component_cleanup(struct drm_i915_private *i915)
{
- if (!dev_priv->display.audio.component_registered)
+ if (!i915->display.audio.component_registered)
return;
- component_del(dev_priv->drm.dev, &i915_audio_component_bind_ops);
- dev_priv->display.audio.component_registered = false;
+ component_del(i915->drm.dev, &i915_audio_component_bind_ops);
+ i915->display.audio.component_registered = false;
}
/**
* intel_audio_init() - Initialize the audio driver either using
* component framework or using lpe audio bridge
- * @dev_priv: the i915 drm device private data
+ * @i915: the i915 drm device private data
*
*/
-void intel_audio_init(struct drm_i915_private *dev_priv)
+void intel_audio_init(struct drm_i915_private *i915)
{
- if (intel_lpe_audio_init(dev_priv) < 0)
- i915_audio_component_init(dev_priv);
+ if (intel_lpe_audio_init(i915) < 0)
+ i915_audio_component_init(i915);
}
/**
* intel_audio_deinit() - deinitialize the audio driver
- * @dev_priv: the i915 drm device private data
+ * @i915: the i915 drm device private data
*
*/
-void intel_audio_deinit(struct drm_i915_private *dev_priv)
+void intel_audio_deinit(struct drm_i915_private *i915)
{
- if (dev_priv->display.audio.lpe.platdev != NULL)
- intel_lpe_audio_teardown(dev_priv);
+ if (i915->display.audio.lpe.platdev != NULL)
+ intel_lpe_audio_teardown(i915);
else
- i915_audio_component_cleanup(dev_priv);
+ i915_audio_component_cleanup(i915);
}
diff --git a/drivers/gpu/drm/i915/display/intel_audio_regs.h b/drivers/gpu/drm/i915/display/intel_audio_regs.h
index d1e5844e3484..616e7b1275c4 100644
--- a/drivers/gpu/drm/i915/display/intel_audio_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_audio_regs.h
@@ -6,18 +6,13 @@
#ifndef __INTEL_AUDIO_REGS_H__
#define __INTEL_AUDIO_REGS_H__
-#include "i915_reg_defs.h"
-
-#define G4X_AUD_VID_DID _MMIO(DISPLAY_MMIO_BASE(dev_priv) + 0x62020)
-#define INTEL_AUDIO_DEVCL 0x808629FB
-#define INTEL_AUDIO_DEVBLC 0x80862801
-#define INTEL_AUDIO_DEVCTG 0x80862802
+#include "intel_display_reg_defs.h"
#define G4X_AUD_CNTL_ST _MMIO(0x620B4)
-#define G4X_ELDV_DEVCL_DEVBLC (1 << 13)
-#define G4X_ELDV_DEVCTG (1 << 14)
-#define G4X_ELD_ADDR_MASK (0xf << 5)
-#define G4X_ELD_ACK (1 << 4)
+#define G4X_ELD_VALID REG_BIT(14)
+#define G4X_ELD_BUFFER_SIZE_MASK REG_GENMASK(13, 9)
+#define G4X_ELD_ADDRESS_MASK REG_GENMASK(8, 5)
+#define G4X_ELD_ACK REG_BIT(4)
#define G4X_HDMIW_HDMIEDID _MMIO(0x6210C)
#define _IBX_HDMIW_HDMIEDID_A 0xE2050
@@ -28,12 +23,12 @@
#define _IBX_AUD_CNTL_ST_B 0xE21B4
#define IBX_AUD_CNTL_ST(pipe) _MMIO_PIPE(pipe, _IBX_AUD_CNTL_ST_A, \
_IBX_AUD_CNTL_ST_B)
-#define IBX_ELD_BUFFER_SIZE_MASK (0x1f << 10)
-#define IBX_ELD_ADDRESS_MASK (0x1f << 5)
-#define IBX_ELD_ACK (1 << 4)
+#define IBX_ELD_BUFFER_SIZE_MASK REG_GENMASK(14, 10)
+#define IBX_ELD_ADDRESS_MASK REG_GENMASK(9, 5)
+#define IBX_ELD_ACK REG_BIT(4)
#define IBX_AUD_CNTL_ST2 _MMIO(0xE20C0)
-#define IBX_CP_READY(port) ((1 << 1) << (((port) - 1) * 4))
-#define IBX_ELD_VALID(port) ((1 << 0) << (((port) - 1) * 4))
+#define IBX_CP_READY(port) REG_BIT(((port) - 1) * 4 + 1)
+#define IBX_ELD_VALID(port) REG_BIT(((port) - 1) * 4 + 0)
#define _CPT_HDMIW_HDMIEDID_A 0xE5050
#define _CPT_HDMIW_HDMIEDID_B 0xE5150
@@ -60,34 +55,30 @@
#define _VLV_AUD_CONFIG_A (VLV_DISPLAY_BASE + 0x62000)
#define _VLV_AUD_CONFIG_B (VLV_DISPLAY_BASE + 0x62100)
#define VLV_AUD_CFG(pipe) _MMIO_PIPE(pipe, _VLV_AUD_CONFIG_A, _VLV_AUD_CONFIG_B)
-
-#define AUD_CONFIG_N_VALUE_INDEX (1 << 29)
-#define AUD_CONFIG_N_PROG_ENABLE (1 << 28)
-#define AUD_CONFIG_UPPER_N_SHIFT 20
-#define AUD_CONFIG_UPPER_N_MASK (0xff << 20)
-#define AUD_CONFIG_LOWER_N_SHIFT 4
-#define AUD_CONFIG_LOWER_N_MASK (0xfff << 4)
-#define AUD_CONFIG_N_MASK (AUD_CONFIG_UPPER_N_MASK | AUD_CONFIG_LOWER_N_MASK)
-#define AUD_CONFIG_N(n) \
- (((((n) >> 12) & 0xff) << AUD_CONFIG_UPPER_N_SHIFT) | \
- (((n) & 0xfff) << AUD_CONFIG_LOWER_N_SHIFT))
-#define AUD_CONFIG_PIXEL_CLOCK_HDMI_SHIFT 16
-#define AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK (0xf << 16)
-#define AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 (0 << 16)
-#define AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 (1 << 16)
-#define AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 (2 << 16)
-#define AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 (3 << 16)
-#define AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 (4 << 16)
-#define AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 (5 << 16)
-#define AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 (6 << 16)
-#define AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 (7 << 16)
-#define AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 (8 << 16)
-#define AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 (9 << 16)
-#define AUD_CONFIG_PIXEL_CLOCK_HDMI_296703 (10 << 16)
-#define AUD_CONFIG_PIXEL_CLOCK_HDMI_297000 (11 << 16)
-#define AUD_CONFIG_PIXEL_CLOCK_HDMI_593407 (12 << 16)
-#define AUD_CONFIG_PIXEL_CLOCK_HDMI_594000 (13 << 16)
-#define AUD_CONFIG_DISABLE_NCTS (1 << 3)
+#define AUD_CONFIG_N_VALUE_INDEX REG_BIT(29)
+#define AUD_CONFIG_N_PROG_ENABLE REG_BIT(28)
+#define AUD_CONFIG_UPPER_N_MASK REG_GENMASK(27, 20)
+#define AUD_CONFIG_LOWER_N_MASK REG_GENMASK(15, 4)
+#define AUD_CONFIG_N_MASK (AUD_CONFIG_UPPER_N_MASK | \
+ AUD_CONFIG_LOWER_N_MASK)
+#define AUD_CONFIG_N(n) (REG_FIELD_PREP(AUD_CONFIG_UPPER_N_MASK, (n) >> 12) | \
+ REG_FIELD_PREP(AUD_CONFIG_LOWER_N_MASK, (n) & 0xfff))
+#define AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK REG_GENMASK(19, 16)
+#define AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 0)
+#define AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 1)
+#define AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 2)
+#define AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 3)
+#define AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 4)
+#define AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 5)
+#define AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 6)
+#define AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 7)
+#define AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 8)
+#define AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 9)
+#define AUD_CONFIG_PIXEL_CLOCK_HDMI_296703 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 10)
+#define AUD_CONFIG_PIXEL_CLOCK_HDMI_297000 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 11)
+#define AUD_CONFIG_PIXEL_CLOCK_HDMI_593407 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 12)
+#define AUD_CONFIG_PIXEL_CLOCK_HDMI_594000 REG_FIELD_PREP(AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK, 13)
+#define AUD_CONFIG_DISABLE_NCTS REG_BIT(3)
#define _HSW_AUD_CONFIG_A 0x65000
#define _HSW_AUD_CONFIG_B 0x65100
@@ -100,9 +91,9 @@
#define _HSW_AUD_M_CTS_ENABLE_A 0x65028
#define _HSW_AUD_M_CTS_ENABLE_B 0x65128
#define HSW_AUD_M_CTS_ENABLE(trans) _MMIO_TRANS(trans, _HSW_AUD_M_CTS_ENABLE_A, _HSW_AUD_M_CTS_ENABLE_B)
-#define AUD_M_CTS_M_VALUE_INDEX (1 << 21)
-#define AUD_M_CTS_M_PROG_ENABLE (1 << 20)
-#define AUD_CONFIG_M_MASK 0xfffff
+#define AUD_M_CTS_M_VALUE_INDEX REG_BIT(21)
+#define AUD_M_CTS_M_PROG_ENABLE REG_BIT(20)
+#define AUD_CONFIG_M_MASK REG_GENMASK(19, 0)
#define _HSW_AUD_DIP_ELD_CTRL_ST_A 0x650b4
#define _HSW_AUD_DIP_ELD_CTRL_ST_B 0x651b4
@@ -130,11 +121,11 @@
#define AUD_DP_2DOT0_CTRL(trans) _MMIO_TRANS(trans, _AUD_TCA_DP_2DOT0_CTRL, _AUD_TCB_DP_2DOT0_CTRL)
#define AUD_ENABLE_SDP_SPLIT REG_BIT(31)
-#define HSW_AUD_CHICKENBIT _MMIO(0x65f10)
-#define SKL_AUD_CODEC_WAKE_SIGNAL (1 << 15)
+#define HSW_AUD_CHICKENBIT _MMIO(0x65f10)
+#define SKL_AUD_CODEC_WAKE_SIGNAL REG_BIT(15)
#define AUD_FREQ_CNTRL _MMIO(0x65900)
-#define AUD_PIN_BUF_CTL _MMIO(0x48414)
+#define AUD_PIN_BUF_CTL _MMIO(0x48414)
#define AUD_PIN_BUF_ENABLE REG_BIT(31)
#define AUD_TS_CDCLK_M _MMIO(0x65ea0)
diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c
index beba39a38c87..71af88a70461 100644
--- a/drivers/gpu/drm/i915/display/intel_backlight.c
+++ b/drivers/gpu/drm/i915/display/intel_backlight.c
@@ -10,6 +10,7 @@
#include <acpi/video.h>
+#include "i915_reg.h"
#include "intel_backlight.h"
#include "intel_backlight_regs.h"
#include "intel_connector.h"
diff --git a/drivers/gpu/drm/i915/display/intel_backlight_regs.h b/drivers/gpu/drm/i915/display/intel_backlight_regs.h
index 50c1210f6d5d..344eb8096bd2 100644
--- a/drivers/gpu/drm/i915/display/intel_backlight_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_backlight_regs.h
@@ -6,7 +6,7 @@
#ifndef __INTEL_BACKLIGHT_REGS_H__
#define __INTEL_BACKLIGHT_REGS_H__
-#include "i915_reg_defs.h"
+#include "intel_display_reg_defs.h"
#define _VLV_BLC_PWM_CTL2_A (DISPLAY_MMIO_BASE(dev_priv) + 0x61250)
#define _VLV_BLC_PWM_CTL2_B (DISPLAY_MMIO_BASE(dev_priv) + 0x61350)
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 28bdb936cd1f..572a4e3769f3 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
+++ b/drivers/gpu/drm/i915/display/intel_bios.c
@@ -414,7 +414,7 @@ static void *generate_lfp_data_ptrs(struct drm_i915_private *i915,
ptrs->lvds_entries++;
if (size != 0 || ptrs->lvds_entries != 3) {
- kfree(ptrs);
+ kfree(ptrs_block);
return NULL;
}
@@ -2188,7 +2188,7 @@ static u8 map_ddc_pin(struct drm_i915_private *i915, u8 vbt_pin)
const u8 *ddc_pin_map;
int n_entries;
- if (IS_ALDERLAKE_P(i915)) {
+ if (HAS_PCH_MTP(i915) || IS_ALDERLAKE_P(i915)) {
ddc_pin_map = adlp_ddc_pin_map;
n_entries = ARRAY_SIZE(adlp_ddc_pin_map);
} else if (IS_ALDERLAKE_S(i915)) {
@@ -2676,6 +2676,14 @@ static void print_ddi_port(const struct intel_bios_encoder_data *devdata,
drm_dbg_kms(&i915->drm,
"Port %c VBT DP max link rate: %d\n",
port_name(port), dp_max_link_rate);
+
+ /*
+ * FIXME need to implement support for VBT
+ * vswing/preemph tables should this ever trigger.
+ */
+ drm_WARN(&i915->drm, child->use_vbt_vswing,
+ "Port %c asks to use VBT vswing/preemph tables\n",
+ port_name(port));
}
static void parse_ddi_port(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 4ace026b29bd..1c236f02b380 100644
--- a/drivers/gpu/drm/i915/display/intel_bw.c
+++ b/drivers/gpu/drm/i915/display/intel_bw.c
@@ -439,7 +439,8 @@ static int tgl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel
return ret;
}
- if (dram_info->type == INTEL_DRAM_LPDDR4 || dram_info->type == INTEL_DRAM_LPDDR5)
+ if (DISPLAY_VER(dev_priv) < 14 &&
+ (dram_info->type == INTEL_DRAM_LPDDR4 || dram_info->type == INTEL_DRAM_LPDDR5))
num_channels *= 2;
qi.deinterleave = qi.deinterleave ? : DIV_ROUND_UP(num_channels, is_y_tile ? 4 : 2);
diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c
index ed05070b7307..b74e36d76013 100644
--- a/drivers/gpu/drm/i915/display/intel_cdclk.c
+++ b/drivers/gpu/drm/i915/display/intel_cdclk.c
@@ -24,6 +24,7 @@
#include <linux/time.h>
#include "hsw_ips.h"
+#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_atomic_plane.h"
#include "intel_audio.h"
@@ -1220,11 +1221,6 @@ static void skl_cdclk_uninit_hw(struct drm_i915_private *dev_priv)
skl_set_cdclk(dev_priv, &cdclk_config, INVALID_PIPE);
}
-static bool has_cdclk_squasher(struct drm_i915_private *i915)
-{
- return IS_DG2(i915);
-}
-
struct intel_cdclk_vals {
u32 cdclk;
u16 refclk;
@@ -1520,7 +1516,7 @@ static void bxt_get_cdclk(struct drm_i915_private *dev_priv,
return;
}
- if (has_cdclk_squasher(dev_priv))
+ if (HAS_CDCLK_SQUASH(dev_priv))
squash_ctl = intel_de_read(dev_priv, CDCLK_SQUASH_CTL);
if (squash_ctl & CDCLK_SQUASH_ENABLE) {
@@ -1689,6 +1685,38 @@ static u32 cdclk_squash_waveform(struct drm_i915_private *dev_priv,
return 0xffff;
}
+static void icl_cdclk_pll_update(struct drm_i915_private *i915, int vco)
+{
+ if (i915->display.cdclk.hw.vco != 0 &&
+ i915->display.cdclk.hw.vco != vco)
+ icl_cdclk_pll_disable(i915);
+
+ if (i915->display.cdclk.hw.vco != vco)
+ icl_cdclk_pll_enable(i915, vco);
+}
+
+static void bxt_cdclk_pll_update(struct drm_i915_private *i915, int vco)
+{
+ if (i915->display.cdclk.hw.vco != 0 &&
+ i915->display.cdclk.hw.vco != vco)
+ bxt_de_pll_disable(i915);
+
+ if (i915->display.cdclk.hw.vco != vco)
+ bxt_de_pll_enable(i915, vco);
+}
+
+static void dg2_cdclk_squash_program(struct drm_i915_private *i915,
+ u16 waveform)
+{
+ u32 squash_ctl = 0;
+
+ if (waveform)
+ squash_ctl = CDCLK_SQUASH_ENABLE |
+ CDCLK_SQUASH_WINDOW_SIZE(0xf) | waveform;
+
+ intel_de_write(i915, CDCLK_SQUASH_CTL, squash_ctl);
+}
+
static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
const struct intel_cdclk_config *cdclk_config,
enum pipe pipe)
@@ -1724,21 +1752,10 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
if (HAS_CDCLK_CRAWL(dev_priv) && dev_priv->display.cdclk.hw.vco > 0 && vco > 0) {
if (dev_priv->display.cdclk.hw.vco != vco)
adlp_cdclk_pll_crawl(dev_priv, vco);
- } else if (DISPLAY_VER(dev_priv) >= 11) {
- if (dev_priv->display.cdclk.hw.vco != 0 &&
- dev_priv->display.cdclk.hw.vco != vco)
- icl_cdclk_pll_disable(dev_priv);
-
- if (dev_priv->display.cdclk.hw.vco != vco)
- icl_cdclk_pll_enable(dev_priv, vco);
- } else {
- if (dev_priv->display.cdclk.hw.vco != 0 &&
- dev_priv->display.cdclk.hw.vco != vco)
- bxt_de_pll_disable(dev_priv);
-
- if (dev_priv->display.cdclk.hw.vco != vco)
- bxt_de_pll_enable(dev_priv, vco);
- }
+ } else if (DISPLAY_VER(dev_priv) >= 11)
+ icl_cdclk_pll_update(dev_priv, vco);
+ else
+ bxt_cdclk_pll_update(dev_priv, vco);
waveform = cdclk_squash_waveform(dev_priv, cdclk);
@@ -1747,15 +1764,8 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv,
else
clock = cdclk;
- if (has_cdclk_squasher(dev_priv)) {
- u32 squash_ctl = 0;
-
- if (waveform)
- squash_ctl = CDCLK_SQUASH_ENABLE |
- CDCLK_SQUASH_WINDOW_SIZE(0xf) | waveform;
-
- intel_de_write(dev_priv, CDCLK_SQUASH_CTL, squash_ctl);
- }
+ if (HAS_CDCLK_SQUASH(dev_priv))
+ dg2_cdclk_squash_program(dev_priv, waveform);
val = bxt_cdclk_cd2x_div_sel(dev_priv, clock, vco) |
bxt_cdclk_cd2x_pipe(dev_priv, pipe) |
@@ -1845,7 +1855,7 @@ static void bxt_sanitize_cdclk(struct drm_i915_private *dev_priv)
expected = skl_cdclk_decimal(cdclk);
/* Figure out what CD2X divider we should be using for this cdclk */
- if (has_cdclk_squasher(dev_priv))
+ if (HAS_CDCLK_SQUASH(dev_priv))
clock = dev_priv->display.cdclk.hw.vco / 2;
else
clock = dev_priv->display.cdclk.hw.cdclk;
@@ -1976,7 +1986,7 @@ static bool intel_cdclk_can_squash(struct drm_i915_private *dev_priv,
* the moment all platforms with squasher use a fixed cd2x
* divider.
*/
- if (!has_cdclk_squasher(dev_priv))
+ if (!HAS_CDCLK_SQUASH(dev_priv))
return false;
return a->cdclk != b->cdclk &&
@@ -2028,7 +2038,7 @@ static bool intel_cdclk_can_cd2x_update(struct drm_i915_private *dev_priv,
* the moment all platforms with squasher use a fixed cd2x
* divider.
*/
- if (has_cdclk_squasher(dev_priv))
+ if (HAS_CDCLK_SQUASH(dev_priv))
return false;
return a->cdclk != b->cdclk &&
@@ -2464,10 +2474,6 @@ static int bdw_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state)
if (min_cdclk < 0)
return min_cdclk;
- /*
- * FIXME should also account for plane ratio
- * once 64bpp pixel formats are supported.
- */
cdclk = bdw_calc_cdclk(min_cdclk);
cdclk_state->logical.cdclk = cdclk;
@@ -2534,10 +2540,6 @@ static int skl_modeset_calc_cdclk(struct intel_cdclk_state *cdclk_state)
vco = skl_dpll0_vco(cdclk_state);
- /*
- * FIXME should also account for plane ratio
- * once 64bpp pixel formats are supported.
- */
cdclk = skl_calc_cdclk(min_cdclk, vco);
cdclk_state->logical.vco = vco;
@@ -2754,7 +2756,7 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
if (IS_ERR(crtc_state))
return PTR_ERR(crtc_state);
- if (drm_atomic_crtc_needs_modeset(&crtc_state->uapi))
+ if (intel_crtc_needs_modeset(crtc_state))
pipe = INVALID_PIPE;
}
@@ -2762,12 +2764,12 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
&old_cdclk_state->actual,
&new_cdclk_state->actual)) {
drm_dbg_kms(&dev_priv->drm,
- "Can change cdclk via squasher\n");
+ "Can change cdclk via squashing\n");
} else if (intel_cdclk_can_crawl(dev_priv,
&old_cdclk_state->actual,
&new_cdclk_state->actual)) {
drm_dbg_kms(&dev_priv->drm,
- "Can change cdclk via crawl\n");
+ "Can change cdclk via crawling\n");
} else if (pipe != INVALID_PIPE) {
new_cdclk_state->pipe = pipe;
@@ -2777,7 +2779,7 @@ int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
} else if (intel_cdclk_needs_modeset(&old_cdclk_state->actual,
&new_cdclk_state->actual)) {
/* All pipes must be switched off while we change the cdclk. */
- ret = intel_modeset_all_pipes(state);
+ ret = intel_modeset_all_pipes(state, "CDCLK change");
if (ret)
return ret;
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c
index 6bda4274eae9..250e83f1f5ac 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -22,12 +22,11 @@
*
*/
+#include "i915_reg.h"
#include "intel_color.h"
#include "intel_de.h"
#include "intel_display_types.h"
-#include "intel_dpll.h"
#include "intel_dsb.h"
-#include "vlv_dsi_pll.h"
struct intel_color_funcs {
int (*color_check)(struct intel_crtc_state *crtc_state);
@@ -186,31 +185,31 @@ static void ilk_update_pipe_csc(struct intel_crtc *crtc,
const u16 coeff[9],
const u16 postoff[3])
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
- intel_de_write_fw(dev_priv, PIPE_CSC_PREOFF_HI(pipe), preoff[0]);
- intel_de_write_fw(dev_priv, PIPE_CSC_PREOFF_ME(pipe), preoff[1]);
- intel_de_write_fw(dev_priv, PIPE_CSC_PREOFF_LO(pipe), preoff[2]);
+ 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(dev_priv, PIPE_CSC_COEFF_RY_GY(pipe),
+ intel_de_write_fw(i915, PIPE_CSC_COEFF_RY_GY(pipe),
coeff[0] << 16 | coeff[1]);
- intel_de_write_fw(dev_priv, PIPE_CSC_COEFF_BY(pipe), coeff[2] << 16);
+ intel_de_write_fw(i915, PIPE_CSC_COEFF_BY(pipe), coeff[2] << 16);
- intel_de_write_fw(dev_priv, PIPE_CSC_COEFF_RU_GU(pipe),
+ intel_de_write_fw(i915, PIPE_CSC_COEFF_RU_GU(pipe),
coeff[3] << 16 | coeff[4]);
- intel_de_write_fw(dev_priv, PIPE_CSC_COEFF_BU(pipe), coeff[5] << 16);
+ intel_de_write_fw(i915, PIPE_CSC_COEFF_BU(pipe), coeff[5] << 16);
- intel_de_write_fw(dev_priv, PIPE_CSC_COEFF_RV_GV(pipe),
+ intel_de_write_fw(i915, PIPE_CSC_COEFF_RV_GV(pipe),
coeff[6] << 16 | coeff[7]);
- intel_de_write_fw(dev_priv, PIPE_CSC_COEFF_BV(pipe), coeff[8] << 16);
+ intel_de_write_fw(i915, PIPE_CSC_COEFF_BV(pipe), coeff[8] << 16);
- if (DISPLAY_VER(dev_priv) >= 7) {
- intel_de_write_fw(dev_priv, PIPE_CSC_POSTOFF_HI(pipe),
+ if (DISPLAY_VER(i915) >= 7) {
+ intel_de_write_fw(i915, PIPE_CSC_POSTOFF_HI(pipe),
postoff[0]);
- intel_de_write_fw(dev_priv, PIPE_CSC_POSTOFF_ME(pipe),
+ intel_de_write_fw(i915, PIPE_CSC_POSTOFF_ME(pipe),
postoff[1]);
- intel_de_write_fw(dev_priv, PIPE_CSC_POSTOFF_LO(pipe),
+ intel_de_write_fw(i915, PIPE_CSC_POSTOFF_LO(pipe),
postoff[2]);
}
}
@@ -220,55 +219,55 @@ static void icl_update_output_csc(struct intel_crtc *crtc,
const u16 coeff[9],
const u16 postoff[3])
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
- intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_PREOFF_HI(pipe), preoff[0]);
- intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_PREOFF_ME(pipe), preoff[1]);
- intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_PREOFF_LO(pipe), preoff[2]);
+ 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(dev_priv, PIPE_CSC_OUTPUT_COEFF_RY_GY(pipe),
+ intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_RY_GY(pipe),
coeff[0] << 16 | coeff[1]);
- intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_COEFF_BY(pipe),
+ intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_BY(pipe),
coeff[2] << 16);
- intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_COEFF_RU_GU(pipe),
+ intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_RU_GU(pipe),
coeff[3] << 16 | coeff[4]);
- intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_COEFF_BU(pipe),
+ intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_BU(pipe),
coeff[5] << 16);
- intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_COEFF_RV_GV(pipe),
+ intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_RV_GV(pipe),
coeff[6] << 16 | coeff[7]);
- intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_COEFF_BV(pipe),
+ intel_de_write_fw(i915, PIPE_CSC_OUTPUT_COEFF_BV(pipe),
coeff[8] << 16);
- intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_POSTOFF_HI(pipe), postoff[0]);
- intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_POSTOFF_ME(pipe), postoff[1]);
- intel_de_write_fw(dev_priv, PIPE_CSC_OUTPUT_POSTOFF_LO(pipe), postoff[2]);
+ 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]);
}
static bool ilk_csc_limited_range(const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
/*
* FIXME if there's a gamma LUT after the CSC, we should
* do the range compression using the gamma LUT instead.
*/
return crtc_state->limited_color_range &&
- (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv) ||
- IS_DISPLAY_VER(dev_priv, 9, 10));
+ (IS_HASWELL(i915) || IS_BROADWELL(i915) ||
+ IS_DISPLAY_VER(i915, 9, 10));
}
static void ilk_csc_convert_ctm(const struct intel_crtc_state *crtc_state,
- u16 coeffs[9])
+ u16 coeffs[9], bool limited_color_range)
{
const struct drm_color_ctm *ctm = crtc_state->hw.ctm->data;
const u64 *input;
u64 temp[9];
int i;
- if (ilk_csc_limited_range(crtc_state))
+ if (limited_color_range)
input = ctm_mult_by_limited(temp, ctm->matrix);
else
input = ctm->matrix;
@@ -315,13 +314,13 @@ static void ilk_csc_convert_ctm(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);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
bool limited_color_range = ilk_csc_limited_range(crtc_state);
if (crtc_state->hw.ctm) {
u16 coeff[9];
- ilk_csc_convert_ctm(crtc_state, coeff);
+ 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 :
@@ -341,7 +340,7 @@ static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state)
* LUT is needed but CSC is not we need to load an
* identity matrix.
*/
- drm_WARN_ON(&dev_priv->drm, !IS_GEMINILAKE(dev_priv));
+ drm_WARN_ON(&i915->drm, !IS_GEMINILAKE(i915));
ilk_update_pipe_csc(crtc, ilk_csc_off_zero,
ilk_csc_coeff_identity,
@@ -356,7 +355,7 @@ static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state)
if (crtc_state->hw.ctm) {
u16 coeff[9];
- ilk_csc_convert_ctm(crtc_state, coeff);
+ ilk_csc_convert_ctm(crtc_state, coeff, false);
ilk_update_pipe_csc(crtc, ilk_csc_off_zero,
coeff, ilk_csc_off_zero);
}
@@ -375,7 +374,7 @@ static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state)
static void chv_load_cgm_csc(struct intel_crtc *crtc,
const struct drm_property_blob *blob)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ 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];
@@ -399,15 +398,15 @@ static void chv_load_cgm_csc(struct intel_crtc *crtc,
coeffs[i] |= (abs_coeff >> 20) & 0xfff;
}
- intel_de_write_fw(dev_priv, CGM_PIPE_CSC_COEFF01(pipe),
+ intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF01(pipe),
coeffs[1] << 16 | coeffs[0]);
- intel_de_write_fw(dev_priv, CGM_PIPE_CSC_COEFF23(pipe),
+ intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF23(pipe),
coeffs[3] << 16 | coeffs[2]);
- intel_de_write_fw(dev_priv, CGM_PIPE_CSC_COEFF45(pipe),
+ intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF45(pipe),
coeffs[5] << 16 | coeffs[4]);
- intel_de_write_fw(dev_priv, CGM_PIPE_CSC_COEFF67(pipe),
+ intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF67(pipe),
coeffs[7] << 16 | coeffs[6]);
- intel_de_write_fw(dev_priv, CGM_PIPE_CSC_COEFF8(pipe),
+ intel_de_write_fw(i915, CGM_PIPE_CSC_COEFF8(pipe),
coeffs[8]);
}
@@ -426,32 +425,32 @@ static u32 intel_color_lut_pack(u32 val, int bit_precision)
static u32 i9xx_lut_8(const struct drm_color_lut *color)
{
- return drm_color_lut_extract(color->red, 8) << 16 |
- drm_color_lut_extract(color->green, 8) << 8 |
- drm_color_lut_extract(color->blue, 8);
+ return REG_FIELD_PREP(PALETTE_RED_MASK, drm_color_lut_extract(color->red, 8)) |
+ REG_FIELD_PREP(PALETTE_GREEN_MASK, drm_color_lut_extract(color->green, 8)) |
+ REG_FIELD_PREP(PALETTE_BLUE_MASK, drm_color_lut_extract(color->blue, 8));
}
static void i9xx_lut_8_pack(struct drm_color_lut *entry, u32 val)
{
- entry->red = intel_color_lut_pack(REG_FIELD_GET(LGC_PALETTE_RED_MASK, val), 8);
- entry->green = intel_color_lut_pack(REG_FIELD_GET(LGC_PALETTE_GREEN_MASK, val), 8);
- entry->blue = intel_color_lut_pack(REG_FIELD_GET(LGC_PALETTE_BLUE_MASK, val), 8);
+ entry->red = intel_color_lut_pack(REG_FIELD_GET(PALETTE_RED_MASK, val), 8);
+ entry->green = intel_color_lut_pack(REG_FIELD_GET(PALETTE_GREEN_MASK, val), 8);
+ entry->blue = intel_color_lut_pack(REG_FIELD_GET(PALETTE_BLUE_MASK, val), 8);
}
/* i965+ "10.6" bit interpolated format "even DW" (low 8 bits) */
static u32 i965_lut_10p6_ldw(const struct drm_color_lut *color)
{
- return (color->red & 0xff) << 16 |
- (color->green & 0xff) << 8 |
- (color->blue & 0xff);
+ return REG_FIELD_PREP(PALETTE_RED_MASK, color->red & 0xff) |
+ REG_FIELD_PREP(PALETTE_GREEN_MASK, color->green & 0xff) |
+ REG_FIELD_PREP(PALETTE_BLUE_MASK, color->blue & 0xff);
}
/* i965+ "10.6" interpolated format "odd DW" (high 8 bits) */
static u32 i965_lut_10p6_udw(const struct drm_color_lut *color)
{
- return (color->red >> 8) << 16 |
- (color->green >> 8) << 8 |
- (color->blue >> 8);
+ return REG_FIELD_PREP(PALETTE_RED_MASK, color->red >> 8) |
+ REG_FIELD_PREP(PALETTE_GREEN_MASK, color->green >> 8) |
+ REG_FIELD_PREP(PALETTE_BLUE_MASK, color->blue >> 8);
}
static void i965_lut_10p6_pack(struct drm_color_lut *entry, u32 ldw, u32 udw)
@@ -472,26 +471,42 @@ static u16 i965_lut_11p6_max_pack(u32 val)
static u32 ilk_lut_10(const struct drm_color_lut *color)
{
- return drm_color_lut_extract(color->red, 10) << 20 |
- drm_color_lut_extract(color->green, 10) << 10 |
- drm_color_lut_extract(color->blue, 10);
+ return REG_FIELD_PREP(PREC_PALETTE_10_RED_MASK, drm_color_lut_extract(color->red, 10)) |
+ REG_FIELD_PREP(PREC_PALETTE_10_GREEN_MASK, drm_color_lut_extract(color->green, 10)) |
+ REG_FIELD_PREP(PREC_PALETTE_10_BLUE_MASK, drm_color_lut_extract(color->blue, 10));
}
static void ilk_lut_10_pack(struct drm_color_lut *entry, u32 val)
{
- entry->red = intel_color_lut_pack(REG_FIELD_GET(PREC_PALETTE_RED_MASK, val), 10);
- entry->green = intel_color_lut_pack(REG_FIELD_GET(PREC_PALETTE_GREEN_MASK, val), 10);
- entry->blue = intel_color_lut_pack(REG_FIELD_GET(PREC_PALETTE_BLUE_MASK, val), 10);
+ entry->red = intel_color_lut_pack(REG_FIELD_GET(PREC_PALETTE_10_RED_MASK, val), 10);
+ entry->green = intel_color_lut_pack(REG_FIELD_GET(PREC_PALETTE_10_GREEN_MASK, val), 10);
+ entry->blue = intel_color_lut_pack(REG_FIELD_GET(PREC_PALETTE_10_BLUE_MASK, val), 10);
+}
+
+/* ilk+ "12.4" interpolated format (low 6 bits) */
+static u32 ilk_lut_12p4_ldw(const struct drm_color_lut *color)
+{
+ return REG_FIELD_PREP(PREC_PALETTE_12P4_RED_LDW_MASK, color->red & 0x3f) |
+ REG_FIELD_PREP(PREC_PALETTE_12P4_GREEN_LDW_MASK, color->green & 0x3f) |
+ REG_FIELD_PREP(PREC_PALETTE_12P4_BLUE_LDW_MASK, color->blue & 0x3f);
+}
+
+/* ilk+ "12.4" interpolated format (high 10 bits) */
+static u32 ilk_lut_12p4_udw(const struct drm_color_lut *color)
+{
+ return REG_FIELD_PREP(PREC_PALETTE_12P4_RED_UDW_MASK, color->red >> 6) |
+ REG_FIELD_PREP(PREC_PALETTE_12P4_GREEN_UDW_MASK, color->green >> 6) |
+ REG_FIELD_PREP(PREC_PALETTE_12P4_BLUE_UDW_MASK, color->blue >> 6);
}
-static void icl_lut_multi_seg_pack(struct drm_color_lut *entry, u32 ldw, u32 udw)
+static void ilk_lut_12p4_pack(struct drm_color_lut *entry, u32 ldw, u32 udw)
{
- entry->red = REG_FIELD_GET(PAL_PREC_MULTI_SEG_RED_UDW_MASK, udw) << 6 |
- REG_FIELD_GET(PAL_PREC_MULTI_SEG_RED_LDW_MASK, ldw);
- entry->green = REG_FIELD_GET(PAL_PREC_MULTI_SEG_GREEN_UDW_MASK, udw) << 6 |
- REG_FIELD_GET(PAL_PREC_MULTI_SEG_GREEN_LDW_MASK, ldw);
- entry->blue = REG_FIELD_GET(PAL_PREC_MULTI_SEG_BLUE_UDW_MASK, udw) << 6 |
- REG_FIELD_GET(PAL_PREC_MULTI_SEG_BLUE_LDW_MASK, ldw);
+ entry->red = REG_FIELD_GET(PREC_PALETTE_12P4_RED_UDW_MASK, udw) << 6 |
+ REG_FIELD_GET(PREC_PALETTE_12P4_RED_LDW_MASK, ldw);
+ entry->green = REG_FIELD_GET(PREC_PALETTE_12P4_GREEN_UDW_MASK, udw) << 6 |
+ REG_FIELD_GET(PREC_PALETTE_12P4_GREEN_LDW_MASK, ldw);
+ entry->blue = REG_FIELD_GET(PREC_PALETTE_12P4_BLUE_UDW_MASK, udw) << 6 |
+ REG_FIELD_GET(PREC_PALETTE_12P4_BLUE_LDW_MASK, ldw);
}
static void icl_color_commit_noarm(const struct intel_crtc_state *crtc_state)
@@ -513,31 +528,31 @@ static void i9xx_color_commit_arm(const struct intel_crtc_state *crtc_state)
static void ilk_color_commit_arm(const 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 drm_i915_private *i915 = to_i915(crtc->base.dev);
/* update PIPECONF GAMMA_MODE */
ilk_set_pipeconf(crtc_state);
- intel_de_write_fw(dev_priv, PIPE_CSC_MODE(crtc->pipe),
+ intel_de_write_fw(i915, PIPE_CSC_MODE(crtc->pipe),
crtc_state->csc_mode);
}
static void hsw_color_commit_arm(const 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 drm_i915_private *i915 = to_i915(crtc->base.dev);
- intel_de_write(dev_priv, GAMMA_MODE(crtc->pipe),
+ intel_de_write(i915, GAMMA_MODE(crtc->pipe),
crtc_state->gamma_mode);
- intel_de_write_fw(dev_priv, PIPE_CSC_MODE(crtc->pipe),
+ intel_de_write_fw(i915, PIPE_CSC_MODE(crtc->pipe),
crtc_state->csc_mode);
}
static void skl_color_commit_arm(const 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 drm_i915_private *i915 = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
u32 val = 0;
@@ -550,15 +565,65 @@ static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state)
val |= SKL_BOTTOM_COLOR_GAMMA_ENABLE;
if (crtc_state->csc_enable)
val |= SKL_BOTTOM_COLOR_CSC_ENABLE;
- intel_de_write(dev_priv, SKL_BOTTOM_COLOR(pipe), val);
+ intel_de_write(i915, SKL_BOTTOM_COLOR(pipe), val);
- intel_de_write(dev_priv, GAMMA_MODE(crtc->pipe),
+ intel_de_write(i915, GAMMA_MODE(crtc->pipe),
crtc_state->gamma_mode);
- intel_de_write_fw(dev_priv, PIPE_CSC_MODE(crtc->pipe),
+ intel_de_write_fw(i915, PIPE_CSC_MODE(crtc->pipe),
crtc_state->csc_mode);
}
+static struct drm_property_blob *
+create_linear_lut(struct drm_i915_private *i915, int lut_size)
+{
+ struct drm_property_blob *blob;
+ struct drm_color_lut *lut;
+ int i;
+
+ blob = drm_property_create_blob(&i915->drm,
+ sizeof(lut[0]) * lut_size,
+ NULL);
+ if (IS_ERR(blob))
+ return blob;
+
+ lut = blob->data;
+
+ for (i = 0; i < lut_size; i++) {
+ u16 val = 0xffff * i / (lut_size - 1);
+
+ lut[i].red = val;
+ lut[i].green = val;
+ lut[i].blue = val;
+ }
+
+ return blob;
+}
+
+static struct drm_property_blob *
+create_resized_lut(struct drm_i915_private *i915,
+ const struct drm_property_blob *blob_in, int lut_out_size)
+{
+ int i, lut_in_size = drm_color_lut_size(blob_in);
+ struct drm_property_blob *blob_out;
+ const struct drm_color_lut *lut_in;
+ struct drm_color_lut *lut_out;
+
+ blob_out = drm_property_create_blob(&i915->drm,
+ sizeof(lut_out[0]) * lut_out_size,
+ NULL);
+ if (IS_ERR(blob_out))
+ return blob_out;
+
+ lut_in = blob_in->data;
+ lut_out = blob_out->data;
+
+ for (i = 0; i < lut_out_size; i++)
+ lut_out[i] = lut_in[i * (lut_in_size - 1) / (lut_out_size - 1)];
+
+ return blob_out;
+}
+
static void i9xx_load_lut_8(struct intel_crtc *crtc,
const struct drm_property_blob *blob)
{
@@ -580,12 +645,9 @@ static void i9xx_load_lut_8(struct intel_crtc *crtc,
static void i9xx_load_luts(const 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);
- const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
+ const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut;
- assert_pll_enabled(dev_priv, crtc->pipe);
-
- i9xx_load_lut_8(crtc, gamma_lut);
+ i9xx_load_lut_8(crtc, post_csc_lut);
}
static void i965_load_lut_10p6(struct intel_crtc *crtc,
@@ -611,24 +673,18 @@ static void i965_load_lut_10p6(struct intel_crtc *crtc,
static void i965_load_luts(const 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);
- const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
-
- if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DSI))
- assert_dsi_pll_enabled(dev_priv);
- else
- assert_pll_enabled(dev_priv, crtc->pipe);
+ const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut;
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT)
- i9xx_load_lut_8(crtc, gamma_lut);
+ i9xx_load_lut_8(crtc, post_csc_lut);
else
- i965_load_lut_10p6(crtc, gamma_lut);
+ i965_load_lut_10p6(crtc, post_csc_lut);
}
static void ilk_load_lut_8(struct intel_crtc *crtc,
const struct drm_property_blob *blob)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
const struct drm_color_lut *lut;
enum pipe pipe = crtc->pipe;
int i;
@@ -639,34 +695,36 @@ static void ilk_load_lut_8(struct intel_crtc *crtc,
lut = blob->data;
for (i = 0; i < 256; i++)
- intel_de_write_fw(dev_priv, LGC_PALETTE(pipe, i),
+ intel_de_write_fw(i915, LGC_PALETTE(pipe, i),
i9xx_lut_8(&lut[i]));
}
static void ilk_load_lut_10(struct intel_crtc *crtc,
const struct drm_property_blob *blob)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
const struct drm_color_lut *lut = blob->data;
int i, lut_size = drm_color_lut_size(blob);
enum pipe pipe = crtc->pipe;
for (i = 0; i < lut_size; i++)
- intel_de_write_fw(dev_priv, PREC_PALETTE(pipe, i),
+ intel_de_write_fw(i915, PREC_PALETTE(pipe, i),
ilk_lut_10(&lut[i]));
}
static void ilk_load_luts(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
+ const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut;
+ const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut;
+ const struct drm_property_blob *blob = post_csc_lut ?: pre_csc_lut;
switch (crtc_state->gamma_mode) {
case GAMMA_MODE_MODE_8BIT:
- ilk_load_lut_8(crtc, gamma_lut);
+ ilk_load_lut_8(crtc, blob);
break;
case GAMMA_MODE_MODE_10BIT:
- ilk_load_lut_10(crtc, gamma_lut);
+ ilk_load_lut_10(crtc, blob);
break;
default:
MISSING_CASE(crtc_state->gamma_mode);
@@ -691,27 +749,22 @@ static void ivb_load_lut_10(struct intel_crtc *crtc,
const struct drm_property_blob *blob,
u32 prec_index)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- int hw_lut_size = ivb_lut_10_size(prec_index);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
const struct drm_color_lut *lut = blob->data;
int i, lut_size = drm_color_lut_size(blob);
enum pipe pipe = crtc->pipe;
- for (i = 0; i < hw_lut_size; i++) {
- /* We discard half the user entries in split gamma mode */
- const struct drm_color_lut *entry =
- &lut[i * (lut_size - 1) / (hw_lut_size - 1)];
-
- intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), prec_index++);
- intel_de_write_fw(dev_priv, PREC_PAL_DATA(pipe),
- ilk_lut_10(entry));
+ for (i = 0; i < lut_size; i++) {
+ intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), prec_index++);
+ intel_de_write_fw(i915, PREC_PAL_DATA(pipe),
+ ilk_lut_10(&lut[i]));
}
/*
* Reset the index, otherwise it prevents the legacy palette to be
* written properly.
*/
- intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), 0);
+ intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), 0);
}
/* On BDW+ the index auto increment mode actually works */
@@ -719,73 +772,63 @@ static void bdw_load_lut_10(struct intel_crtc *crtc,
const struct drm_property_blob *blob,
u32 prec_index)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- int hw_lut_size = ivb_lut_10_size(prec_index);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
const struct drm_color_lut *lut = blob->data;
int i, lut_size = drm_color_lut_size(blob);
enum pipe pipe = crtc->pipe;
- intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe),
+ intel_de_write_fw(i915, PREC_PAL_INDEX(pipe),
prec_index | PAL_PREC_AUTO_INCREMENT);
- for (i = 0; i < hw_lut_size; i++) {
- /* We discard half the user entries in split gamma mode */
- const struct drm_color_lut *entry =
- &lut[i * (lut_size - 1) / (hw_lut_size - 1)];
-
- intel_de_write_fw(dev_priv, PREC_PAL_DATA(pipe),
- ilk_lut_10(entry));
- }
+ for (i = 0; i < lut_size; i++)
+ intel_de_write_fw(i915, PREC_PAL_DATA(pipe),
+ ilk_lut_10(&lut[i]));
/*
* Reset the index, otherwise it prevents the legacy palette to be
* written properly.
*/
- intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), 0);
+ intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), 0);
}
static void ivb_load_lut_ext_max(const 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 = crtc->pipe;
/* Program the max register to clamp values > 1.0. */
intel_dsb_reg_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 0), 1 << 16);
intel_dsb_reg_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 1), 1 << 16);
intel_dsb_reg_write(crtc_state, PREC_PAL_EXT_GC_MAX(pipe, 2), 1 << 16);
+}
- /*
- * Program the gc max 2 register to clamp values > 1.0.
- * ToDo: Extend the ABI to be able to program values
- * from 3.0 to 7.0
- */
- if (DISPLAY_VER(dev_priv) >= 10) {
- intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 0),
- 1 << 16);
- intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 1),
- 1 << 16);
- intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 2),
- 1 << 16);
- }
+static void glk_load_lut_ext2_max(const struct intel_crtc_state *crtc_state)
+{
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+ enum pipe pipe = crtc->pipe;
+
+ /* Program the max register to clamp values > 1.0. */
+ intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 0), 1 << 16);
+ intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 1), 1 << 16);
+ intel_dsb_reg_write(crtc_state, PREC_PAL_EXT2_GC_MAX(pipe, 2), 1 << 16);
}
static void ivb_load_luts(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
- const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut;
- const struct drm_property_blob *blob = gamma_lut ?: degamma_lut;
+ const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut;
+ const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut;
+ const struct drm_property_blob *blob = post_csc_lut ?: pre_csc_lut;
switch (crtc_state->gamma_mode) {
case GAMMA_MODE_MODE_8BIT:
ilk_load_lut_8(crtc, blob);
break;
case GAMMA_MODE_MODE_SPLIT:
- ivb_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE |
+ ivb_load_lut_10(crtc, pre_csc_lut, PAL_PREC_SPLIT_MODE |
PAL_PREC_INDEX_VALUE(0));
ivb_load_lut_ext_max(crtc_state);
- ivb_load_lut_10(crtc, gamma_lut, PAL_PREC_SPLIT_MODE |
+ ivb_load_lut_10(crtc, post_csc_lut, PAL_PREC_SPLIT_MODE |
PAL_PREC_INDEX_VALUE(512));
break;
case GAMMA_MODE_MODE_10BIT:
@@ -802,19 +845,19 @@ static void ivb_load_luts(const struct intel_crtc_state *crtc_state)
static void bdw_load_luts(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
- const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut;
- const struct drm_property_blob *blob = gamma_lut ?: degamma_lut;
+ const struct drm_property_blob *post_csc_lut = crtc_state->post_csc_lut;
+ const struct drm_property_blob *pre_csc_lut = crtc_state->pre_csc_lut;
+ const struct drm_property_blob *blob = post_csc_lut ?: pre_csc_lut;
switch (crtc_state->gamma_mode) {
case GAMMA_MODE_MODE_8BIT:
ilk_load_lut_8(crtc, blob);
break;
case GAMMA_MODE_MODE_SPLIT:
- bdw_load_lut_10(crtc, degamma_lut, PAL_PREC_SPLIT_MODE |
+ bdw_load_lut_10(crtc, pre_csc_lut, PAL_PREC_SPLIT_MODE |
PAL_PREC_INDEX_VALUE(0));
ivb_load_lut_ext_max(crtc_state);
- bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_SPLIT_MODE |
+ bdw_load_lut_10(crtc, post_csc_lut, PAL_PREC_SPLIT_MODE |
PAL_PREC_INDEX_VALUE(512));
break;
case GAMMA_MODE_MODE_10BIT:
@@ -837,21 +880,22 @@ static int glk_degamma_lut_size(struct drm_i915_private *i915)
return 35;
}
-static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state)
+static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state,
+ const struct drm_property_blob *blob)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ const struct drm_color_lut *lut = blob->data;
+ int i, lut_size = drm_color_lut_size(blob);
enum pipe pipe = crtc->pipe;
- int i, lut_size = INTEL_INFO(dev_priv)->display.color.degamma_lut_size;
- const struct drm_color_lut *lut = crtc_state->hw.degamma_lut->data;
/*
* When setting the auto-increment bit, the hardware seems to
* ignore the index bits, so we need to reset it to index 0
* separately.
*/
- intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0);
- intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe),
+ intel_de_write_fw(i915, PRE_CSC_GAMC_INDEX(pipe), 0);
+ intel_de_write_fw(i915, PRE_CSC_GAMC_INDEX(pipe),
PRE_CSC_GAMC_AUTO_INCREMENT);
for (i = 0; i < lut_size; i++) {
@@ -868,71 +912,34 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state)
* ToDo: Extend to max 7.0. Enable 32 bit input value
* as compared to just 16 to achieve this.
*/
- intel_de_write_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe),
+ intel_de_write_fw(i915, PRE_CSC_GAMC_DATA(pipe),
lut[i].green);
}
/* Clamp values > 1.0. */
- while (i++ < glk_degamma_lut_size(dev_priv))
- intel_de_write_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe), 1 << 16);
+ while (i++ < glk_degamma_lut_size(i915))
+ intel_de_write_fw(i915, PRE_CSC_GAMC_DATA(pipe), 1 << 16);
- intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0);
-}
-
-static void glk_load_degamma_lut_linear(const 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 = crtc->pipe;
- int i, lut_size = INTEL_INFO(dev_priv)->display.color.degamma_lut_size;
-
- /*
- * When setting the auto-increment bit, the hardware seems to
- * ignore the index bits, so we need to reset it to index 0
- * separately.
- */
- intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0);
- intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe),
- PRE_CSC_GAMC_AUTO_INCREMENT);
-
- for (i = 0; i < lut_size; i++) {
- u32 v = (i << 16) / (lut_size - 1);
-
- intel_de_write_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe), v);
- }
-
- /* Clamp values > 1.0. */
- while (i++ < 35)
- intel_de_write_fw(dev_priv, PRE_CSC_GAMC_DATA(pipe), 1 << 16);
-
- intel_de_write_fw(dev_priv, PRE_CSC_GAMC_INDEX(pipe), 0);
+ intel_de_write_fw(i915, PRE_CSC_GAMC_INDEX(pipe), 0);
}
static void glk_load_luts(const struct intel_crtc_state *crtc_state)
{
- const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
+ 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;
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- /*
- * On GLK+ both pipe CSC and degamma LUT are controlled
- * by csc_enable. Hence for the cases where the CSC is
- * needed but degamma LUT is not we need to load a
- * linear degamma LUT. In fact we'll just always load
- * the degama LUT so that we don't have to reload
- * it every time the pipe CSC is being enabled.
- */
- if (crtc_state->hw.degamma_lut)
- glk_load_degamma_lut(crtc_state);
- else
- glk_load_degamma_lut_linear(crtc_state);
+ if (pre_csc_lut)
+ glk_load_degamma_lut(crtc_state, pre_csc_lut);
switch (crtc_state->gamma_mode) {
case GAMMA_MODE_MODE_8BIT:
- ilk_load_lut_8(crtc, gamma_lut);
+ ilk_load_lut_8(crtc, post_csc_lut);
break;
case GAMMA_MODE_MODE_10BIT:
- bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_INDEX_VALUE(0));
+ bdw_load_lut_10(crtc, post_csc_lut, PAL_PREC_INDEX_VALUE(0));
ivb_load_lut_ext_max(crtc_state);
+ glk_load_lut_ext2_max(crtc_state);
break;
default:
MISSING_CASE(crtc_state->gamma_mode);
@@ -940,23 +947,9 @@ static void glk_load_luts(const struct intel_crtc_state *crtc_state)
}
}
-/* ilk+ "12.4" interpolated format (high 10 bits) */
-static u32 ilk_lut_12p4_udw(const struct drm_color_lut *color)
-{
- return (color->red >> 6) << 20 | (color->green >> 6) << 10 |
- (color->blue >> 6);
-}
-
-/* ilk+ "12.4" interpolated format (low 6 bits) */
-static u32 ilk_lut_12p4_ldw(const struct drm_color_lut *color)
-{
- return (color->red & 0x3f) << 24 | (color->green & 0x3f) << 14 |
- (color->blue & 0x3f) << 4;
-}
-
static void
-icl_load_gcmax(const struct intel_crtc_state *crtc_state,
- const struct drm_color_lut *color)
+ivb_load_lut_max(const struct intel_crtc_state *crtc_state,
+ const struct drm_color_lut *color)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
enum pipe pipe = crtc->pipe;
@@ -971,7 +964,7 @@ static void
icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- const struct drm_property_blob *blob = crtc_state->hw.gamma_lut;
+ const struct drm_property_blob *blob = crtc_state->post_csc_lut;
const struct drm_color_lut *lut = blob->data;
enum pipe pipe = crtc->pipe;
int i;
@@ -1000,7 +993,7 @@ static void
icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- const struct drm_property_blob *blob = crtc_state->hw.gamma_lut;
+ const struct drm_property_blob *blob = crtc_state->post_csc_lut;
const struct drm_color_lut *lut = blob->data;
const struct drm_color_lut *entry;
enum pipe pipe = crtc->pipe;
@@ -1048,29 +1041,32 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state)
/* The last entry in the LUT is to be programmed in GCMAX */
entry = &lut[256 * 8 * 128];
- icl_load_gcmax(crtc_state, entry);
- ivb_load_lut_ext_max(crtc_state);
+ ivb_load_lut_max(crtc_state, entry);
}
static void icl_load_luts(const struct intel_crtc_state *crtc_state)
{
- const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
+ 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;
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
- if (crtc_state->hw.degamma_lut)
- glk_load_degamma_lut(crtc_state);
+ if (pre_csc_lut)
+ glk_load_degamma_lut(crtc_state, pre_csc_lut);
switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) {
case GAMMA_MODE_MODE_8BIT:
- ilk_load_lut_8(crtc, gamma_lut);
+ ilk_load_lut_8(crtc, post_csc_lut);
break;
case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED:
icl_program_gamma_superfine_segment(crtc_state);
icl_program_gamma_multi_segment(crtc_state);
+ ivb_load_lut_ext_max(crtc_state);
+ glk_load_lut_ext2_max(crtc_state);
break;
case GAMMA_MODE_MODE_10BIT:
- bdw_load_lut_10(crtc, gamma_lut, PAL_PREC_INDEX_VALUE(0));
+ bdw_load_lut_10(crtc, post_csc_lut, PAL_PREC_INDEX_VALUE(0));
ivb_load_lut_ext_max(crtc_state);
+ glk_load_lut_ext2_max(crtc_state);
break;
default:
MISSING_CASE(crtc_state->gamma_mode);
@@ -1082,61 +1078,61 @@ static void icl_load_luts(const struct intel_crtc_state *crtc_state)
static u32 chv_cgm_degamma_ldw(const struct drm_color_lut *color)
{
- return drm_color_lut_extract(color->green, 14) << 16 |
- drm_color_lut_extract(color->blue, 14);
+ return REG_FIELD_PREP(CGM_PIPE_DEGAMMA_GREEN_LDW_MASK, drm_color_lut_extract(color->green, 14)) |
+ REG_FIELD_PREP(CGM_PIPE_DEGAMMA_BLUE_LDW_MASK, drm_color_lut_extract(color->blue, 14));
}
static u32 chv_cgm_degamma_udw(const struct drm_color_lut *color)
{
- return drm_color_lut_extract(color->red, 14);
+ return REG_FIELD_PREP(CGM_PIPE_DEGAMMA_RED_UDW_MASK, drm_color_lut_extract(color->red, 14));
}
static void chv_load_cgm_degamma(struct intel_crtc *crtc,
const struct drm_property_blob *blob)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
const struct drm_color_lut *lut = blob->data;
int i, lut_size = drm_color_lut_size(blob);
enum pipe pipe = crtc->pipe;
for (i = 0; i < lut_size; i++) {
- intel_de_write_fw(dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 0),
+ intel_de_write_fw(i915, CGM_PIPE_DEGAMMA(pipe, i, 0),
chv_cgm_degamma_ldw(&lut[i]));
- intel_de_write_fw(dev_priv, CGM_PIPE_DEGAMMA(pipe, i, 1),
+ intel_de_write_fw(i915, CGM_PIPE_DEGAMMA(pipe, i, 1),
chv_cgm_degamma_udw(&lut[i]));
}
}
static u32 chv_cgm_gamma_ldw(const struct drm_color_lut *color)
{
- return drm_color_lut_extract(color->green, 10) << 16 |
- drm_color_lut_extract(color->blue, 10);
+ return REG_FIELD_PREP(CGM_PIPE_GAMMA_GREEN_LDW_MASK, drm_color_lut_extract(color->green, 10)) |
+ REG_FIELD_PREP(CGM_PIPE_GAMMA_BLUE_LDW_MASK, drm_color_lut_extract(color->blue, 10));
}
static u32 chv_cgm_gamma_udw(const struct drm_color_lut *color)
{
- return drm_color_lut_extract(color->red, 10);
+ return REG_FIELD_PREP(CGM_PIPE_GAMMA_RED_UDW_MASK, drm_color_lut_extract(color->red, 10));
}
static void chv_cgm_gamma_pack(struct drm_color_lut *entry, u32 ldw, u32 udw)
{
- entry->green = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_GAMMA_GREEN_MASK, ldw), 10);
- entry->blue = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_GAMMA_BLUE_MASK, ldw), 10);
- entry->red = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_GAMMA_RED_MASK, udw), 10);
+ entry->green = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_GAMMA_GREEN_LDW_MASK, ldw), 10);
+ entry->blue = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_GAMMA_BLUE_LDW_MASK, ldw), 10);
+ entry->red = intel_color_lut_pack(REG_FIELD_GET(CGM_PIPE_GAMMA_RED_UDW_MASK, udw), 10);
}
static void chv_load_cgm_gamma(struct intel_crtc *crtc,
const struct drm_property_blob *blob)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
const struct drm_color_lut *lut = blob->data;
int i, lut_size = drm_color_lut_size(blob);
enum pipe pipe = crtc->pipe;
for (i = 0; i < lut_size; i++) {
- intel_de_write_fw(dev_priv, CGM_PIPE_GAMMA(pipe, i, 0),
+ intel_de_write_fw(i915, CGM_PIPE_GAMMA(pipe, i, 0),
chv_cgm_gamma_ldw(&lut[i]));
- intel_de_write_fw(dev_priv, CGM_PIPE_GAMMA(pipe, i, 1),
+ intel_de_write_fw(i915, CGM_PIPE_GAMMA(pipe, i, 1),
chv_cgm_gamma_udw(&lut[i]));
}
}
@@ -1144,46 +1140,46 @@ static void chv_load_cgm_gamma(struct intel_crtc *crtc,
static void chv_load_luts(const 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);
- const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut;
- const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
+ 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);
if (crtc_state->cgm_mode & CGM_PIPE_MODE_DEGAMMA)
- chv_load_cgm_degamma(crtc, degamma_lut);
+ chv_load_cgm_degamma(crtc, pre_csc_lut);
if (crtc_state->cgm_mode & CGM_PIPE_MODE_GAMMA)
- chv_load_cgm_gamma(crtc, gamma_lut);
+ chv_load_cgm_gamma(crtc, post_csc_lut);
else
i965_load_luts(crtc_state);
- intel_de_write_fw(dev_priv, CGM_PIPE_MODE(crtc->pipe),
+ intel_de_write_fw(i915, CGM_PIPE_MODE(crtc->pipe),
crtc_state->cgm_mode);
}
void intel_color_load_luts(const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
- dev_priv->display.funcs.color->load_luts(crtc_state);
+ i915->display.funcs.color->load_luts(crtc_state);
}
void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
- if (dev_priv->display.funcs.color->color_commit_noarm)
- dev_priv->display.funcs.color->color_commit_noarm(crtc_state);
+ if (i915->display.funcs.color->color_commit_noarm)
+ i915->display.funcs.color->color_commit_noarm(crtc_state);
}
void intel_color_commit_arm(const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
- dev_priv->display.funcs.color->color_commit_arm(crtc_state);
+ i915->display.funcs.color->color_commit_arm(crtc_state);
}
static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
@@ -1194,8 +1190,8 @@ static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state
const struct intel_crtc_state *old_crtc_state =
intel_atomic_get_old_crtc_state(state, crtc);
- return !old_crtc_state->hw.gamma_lut &&
- !old_crtc_state->hw.degamma_lut;
+ return !old_crtc_state->post_csc_lut &&
+ !old_crtc_state->pre_csc_lut;
}
static bool chv_can_preload_luts(const struct intel_crtc_state *new_crtc_state)
@@ -1214,46 +1210,28 @@ 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->hw.gamma_lut;
-}
-
-static bool glk_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);
-
- /*
- * The hardware degamma is active whenever the pipe
- * CSC is active. Thus even if the old state has no
- * software degamma we need to avoid clobbering the
- * linear hardware degamma mid scanout.
- */
- return !old_crtc_state->csc_enable &&
- !old_crtc_state->hw.gamma_lut;
+ return !old_crtc_state->post_csc_lut;
}
int intel_color_check(struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
- return dev_priv->display.funcs.color->color_check(crtc_state);
+ return i915->display.funcs.color->color_check(crtc_state);
}
void intel_color_get_config(struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
- if (dev_priv->display.funcs.color->read_luts)
- dev_priv->display.funcs.color->read_luts(crtc_state);
+ if (i915->display.funcs.color->read_luts)
+ i915->display.funcs.color->read_luts(crtc_state);
}
static bool need_plane_update(struct intel_plane *plane,
const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
+ struct drm_i915_private *i915 = to_i915(plane->base.dev);
/*
* On pre-SKL the pipe gamma enable and pipe csc enable for
@@ -1261,7 +1239,7 @@ static bool need_plane_update(struct intel_plane *plane,
* We have to reconfigure that even if the plane is inactive.
*/
return crtc_state->active_planes & BIT(plane->id) ||
- (DISPLAY_VER(dev_priv) < 9 &&
+ (DISPLAY_VER(i915) < 9 &&
plane->id == PLANE_PRIMARY);
}
@@ -1269,7 +1247,7 @@ static int
intel_color_add_affected_planes(struct intel_crtc_state *new_crtc_state)
{
struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc);
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
struct intel_atomic_state *state =
to_intel_atomic_state(new_crtc_state->uapi.state);
const struct intel_crtc_state *old_crtc_state =
@@ -1277,14 +1255,14 @@ intel_color_add_affected_planes(struct intel_crtc_state *new_crtc_state)
struct intel_plane *plane;
if (!new_crtc_state->hw.active ||
- drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi))
+ intel_crtc_needs_modeset(new_crtc_state))
return 0;
if (new_crtc_state->gamma_enable == old_crtc_state->gamma_enable &&
new_crtc_state->csc_enable == old_crtc_state->csc_enable)
return 0;
- for_each_intel_plane_on_crtc(&dev_priv->drm, crtc, plane) {
+ for_each_intel_plane_on_crtc(&i915->drm, crtc, plane) {
struct intel_plane_state *plane_state;
if (!need_plane_update(plane, new_crtc_state))
@@ -1295,6 +1273,10 @@ intel_color_add_affected_planes(struct intel_crtc_state *new_crtc_state)
return PTR_ERR(plane_state);
new_crtc_state->update_planes |= BIT(plane->id);
+
+ /* plane control register changes blocked by CxSR */
+ if (HAS_GMCH(i915))
+ new_crtc_state->disable_cxsr = true;
}
return 0;
@@ -1319,7 +1301,7 @@ static int check_lut_size(const struct drm_property_blob *lut, int expected)
static int check_luts(const struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
const struct drm_property_blob *gamma_lut = crtc_state->hw.gamma_lut;
const struct drm_property_blob *degamma_lut = crtc_state->hw.degamma_lut;
int gamma_length, degamma_length;
@@ -1331,15 +1313,15 @@ static int check_luts(const struct intel_crtc_state *crtc_state)
/* C8 relies on its palette being stored in the legacy LUT */
if (crtc_state->c8_planes) {
- drm_dbg_kms(&dev_priv->drm,
+ drm_dbg_kms(&i915->drm,
"C8 pixelformat requires the legacy LUT\n");
return -EINVAL;
}
- degamma_length = INTEL_INFO(dev_priv)->display.color.degamma_lut_size;
- gamma_length = INTEL_INFO(dev_priv)->display.color.gamma_lut_size;
- degamma_tests = INTEL_INFO(dev_priv)->display.color.degamma_lut_tests;
- gamma_tests = INTEL_INFO(dev_priv)->display.color.gamma_lut_tests;
+ degamma_length = INTEL_INFO(i915)->display.color.degamma_lut_size;
+ gamma_length = INTEL_INFO(i915)->display.color.gamma_lut_size;
+ degamma_tests = INTEL_INFO(i915)->display.color.degamma_lut_tests;
+ gamma_tests = INTEL_INFO(i915)->display.color.gamma_lut_tests;
if (check_lut_size(degamma_lut, degamma_length) ||
check_lut_size(gamma_lut, gamma_length))
@@ -1361,6 +1343,40 @@ static u32 i9xx_gamma_mode(struct intel_crtc_state *crtc_state)
return GAMMA_MODE_MODE_10BIT; /* i965+ only */
}
+void intel_color_assert_luts(const struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+
+ /* make sure {pre,post}_csc_lut were correctly assigned */
+ if (DISPLAY_VER(i915) >= 11 || HAS_GMCH(i915)) {
+ drm_WARN_ON(&i915->drm,
+ crtc_state->pre_csc_lut != crtc_state->hw.degamma_lut);
+ drm_WARN_ON(&i915->drm,
+ crtc_state->post_csc_lut != crtc_state->hw.gamma_lut);
+ } else if (DISPLAY_VER(i915) == 10) {
+ drm_WARN_ON(&i915->drm,
+ crtc_state->pre_csc_lut != crtc_state->hw.degamma_lut &&
+ crtc_state->pre_csc_lut != i915->display.color.glk_linear_degamma_lut);
+ drm_WARN_ON(&i915->drm,
+ crtc_state->post_csc_lut != crtc_state->hw.gamma_lut);
+ } else if (crtc_state->gamma_mode != GAMMA_MODE_MODE_SPLIT) {
+ drm_WARN_ON(&i915->drm,
+ crtc_state->pre_csc_lut != crtc_state->hw.degamma_lut &&
+ crtc_state->pre_csc_lut != crtc_state->hw.gamma_lut);
+ drm_WARN_ON(&i915->drm,
+ crtc_state->post_csc_lut != crtc_state->hw.degamma_lut &&
+ crtc_state->post_csc_lut != crtc_state->hw.gamma_lut);
+ }
+}
+
+static void intel_assign_luts(struct intel_crtc_state *crtc_state)
+{
+ drm_property_replace_blob(&crtc_state->pre_csc_lut,
+ crtc_state->hw.degamma_lut);
+ drm_property_replace_blob(&crtc_state->post_csc_lut,
+ crtc_state->hw.gamma_lut);
+}
+
static int i9xx_color_check(struct intel_crtc_state *crtc_state)
{
int ret;
@@ -1379,6 +1395,8 @@ static int i9xx_color_check(struct intel_crtc_state *crtc_state)
if (ret)
return ret;
+ intel_assign_luts(crtc_state);
+
crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
return 0;
@@ -1433,11 +1451,27 @@ static int chv_color_check(struct intel_crtc_state *crtc_state)
if (ret)
return ret;
+ intel_assign_luts(crtc_state);
+
crtc_state->preload_luts = chv_can_preload_luts(crtc_state);
return 0;
}
+static bool ilk_gamma_enable(const struct intel_crtc_state *crtc_state)
+{
+ return (crtc_state->hw.gamma_lut ||
+ crtc_state->hw.degamma_lut) &&
+ !crtc_state->c8_planes;
+}
+
+static bool ilk_csc_enable(const struct intel_crtc_state *crtc_state)
+{
+ return crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB ||
+ ilk_csc_limited_range(crtc_state) ||
+ crtc_state->hw.ctm;
+}
+
static u32 ilk_gamma_mode(const struct intel_crtc_state *crtc_state)
{
if (!crtc_state->gamma_enable ||
@@ -1458,28 +1492,54 @@ static u32 ilk_csc_mode(const struct intel_crtc_state *crtc_state)
if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB)
return CSC_BLACK_SCREEN_OFFSET;
+ if (crtc_state->hw.degamma_lut)
+ return CSC_MODE_YUV_TO_RGB;
+
return CSC_MODE_YUV_TO_RGB |
CSC_POSITION_BEFORE_GAMMA;
}
+static void ilk_assign_luts(struct intel_crtc_state *crtc_state)
+{
+ if (crtc_state->hw.degamma_lut ||
+ crtc_state->csc_mode & CSC_POSITION_BEFORE_GAMMA) {
+ drm_property_replace_blob(&crtc_state->pre_csc_lut,
+ crtc_state->hw.degamma_lut);
+ drm_property_replace_blob(&crtc_state->post_csc_lut,
+ crtc_state->hw.gamma_lut);
+ } else {
+ drm_property_replace_blob(&crtc_state->pre_csc_lut,
+ crtc_state->hw.gamma_lut);
+ drm_property_replace_blob(&crtc_state->post_csc_lut,
+ NULL);
+ }
+}
+
static int ilk_color_check(struct intel_crtc_state *crtc_state)
{
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
int ret;
ret = check_luts(crtc_state);
if (ret)
return ret;
- crtc_state->gamma_enable =
- crtc_state->hw.gamma_lut &&
- !crtc_state->c8_planes;
+ if (crtc_state->hw.degamma_lut && crtc_state->hw.gamma_lut) {
+ drm_dbg_kms(&i915->drm,
+ "Degamma and gamma together are not possible\n");
+ return -EINVAL;
+ }
- /*
- * We don't expose the ctm on ilk/snb currently, also RGB
- * limited range output is handled by the hw automagically.
- */
- crtc_state->csc_enable =
- crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB;
+ if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB &&
+ crtc_state->hw.ctm) {
+ drm_dbg_kms(&i915->drm,
+ "YCbCr and CTM together are not possible\n");
+ return -EINVAL;
+ }
+
+ crtc_state->gamma_enable = ilk_gamma_enable(crtc_state);
+
+ crtc_state->csc_enable = ilk_csc_enable(crtc_state);
crtc_state->gamma_mode = ilk_gamma_mode(crtc_state);
@@ -1489,6 +1549,8 @@ static int ilk_color_check(struct intel_crtc_state *crtc_state)
if (ret)
return ret;
+ ilk_assign_luts(crtc_state);
+
crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
return 0;
@@ -1496,14 +1558,10 @@ static int ilk_color_check(struct intel_crtc_state *crtc_state)
static u32 ivb_gamma_mode(const struct intel_crtc_state *crtc_state)
{
- if (!crtc_state->gamma_enable ||
- crtc_state_is_legacy_gamma(crtc_state))
- return GAMMA_MODE_MODE_8BIT;
- else if (crtc_state->hw.gamma_lut &&
- crtc_state->hw.degamma_lut)
+ if (crtc_state->hw.degamma_lut && crtc_state->hw.gamma_lut)
return GAMMA_MODE_MODE_SPLIT;
- else
- return GAMMA_MODE_MODE_10BIT;
+
+ return ilk_gamma_mode(crtc_state);
}
static u32 ivb_csc_mode(const struct intel_crtc_state *crtc_state)
@@ -1522,10 +1580,41 @@ static u32 ivb_csc_mode(const struct intel_crtc_state *crtc_state)
return CSC_POSITION_BEFORE_GAMMA;
}
+static int ivb_assign_luts(struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+ struct drm_property_blob *degamma_lut, *gamma_lut;
+
+ if (crtc_state->gamma_mode != GAMMA_MODE_MODE_SPLIT) {
+ ilk_assign_luts(crtc_state);
+ return 0;
+ }
+
+ drm_WARN_ON(&i915->drm, drm_color_lut_size(crtc_state->hw.degamma_lut) != 1024);
+ drm_WARN_ON(&i915->drm, drm_color_lut_size(crtc_state->hw.gamma_lut) != 1024);
+
+ degamma_lut = create_resized_lut(i915, crtc_state->hw.degamma_lut, 512);
+ if (IS_ERR(degamma_lut))
+ return PTR_ERR(degamma_lut);
+
+ gamma_lut = create_resized_lut(i915, crtc_state->hw.gamma_lut, 512);
+ if (IS_ERR(gamma_lut)) {
+ drm_property_blob_put(degamma_lut);
+ return PTR_ERR(gamma_lut);
+ }
+
+ drm_property_replace_blob(&crtc_state->pre_csc_lut, degamma_lut);
+ drm_property_replace_blob(&crtc_state->post_csc_lut, gamma_lut);
+
+ drm_property_blob_put(degamma_lut);
+ drm_property_blob_put(gamma_lut);
+
+ return 0;
+}
+
static int ivb_color_check(struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
- bool limited_color_range = ilk_csc_limited_range(crtc_state);
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
int ret;
ret = check_luts(crtc_state);
@@ -1534,19 +1623,21 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state)
if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB &&
crtc_state->hw.ctm) {
- drm_dbg_kms(&dev_priv->drm,
- "YCBCR and CTM together are not possible\n");
+ drm_dbg_kms(&i915->drm,
+ "YCbCr and CTM together are not possible\n");
return -EINVAL;
}
- crtc_state->gamma_enable =
- (crtc_state->hw.gamma_lut ||
- crtc_state->hw.degamma_lut) &&
- !crtc_state->c8_planes;
+ if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB &&
+ crtc_state->hw.degamma_lut && crtc_state->hw.gamma_lut) {
+ drm_dbg_kms(&i915->drm,
+ "YCbCr and degamma+gamma together are not possible\n");
+ return -EINVAL;
+ }
- crtc_state->csc_enable =
- crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB ||
- crtc_state->hw.ctm || limited_color_range;
+ crtc_state->gamma_enable = ilk_gamma_enable(crtc_state);
+
+ crtc_state->csc_enable = ilk_csc_enable(crtc_state);
crtc_state->gamma_mode = ivb_gamma_mode(crtc_state);
@@ -1556,6 +1647,10 @@ static int ivb_color_check(struct intel_crtc_state *crtc_state)
if (ret)
return ret;
+ ret = ivb_assign_luts(crtc_state);
+ if (ret)
+ return ret;
+
crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
return 0;
@@ -1570,9 +1665,26 @@ static u32 glk_gamma_mode(const struct intel_crtc_state *crtc_state)
return GAMMA_MODE_MODE_10BIT;
}
+static void glk_assign_luts(struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
+
+ intel_assign_luts(crtc_state);
+
+ /*
+ * On GLK+ both pipe CSC and degamma LUT are controlled
+ * by csc_enable. Hence for the cases where the CSC is
+ * needed but degamma LUT is not we need to load a
+ * linear degamma LUT.
+ */
+ if (crtc_state->csc_enable && !crtc_state->pre_csc_lut)
+ drm_property_replace_blob(&crtc_state->pre_csc_lut,
+ i915->display.color.glk_linear_degamma_lut);
+}
+
static int glk_color_check(struct intel_crtc_state *crtc_state)
{
- struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
+ struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev);
int ret;
ret = check_luts(crtc_state);
@@ -1581,8 +1693,15 @@ static int glk_color_check(struct intel_crtc_state *crtc_state)
if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB &&
crtc_state->hw.ctm) {
- drm_dbg_kms(&dev_priv->drm,
- "YCBCR and CTM together are not possible\n");
+ drm_dbg_kms(&i915->drm,
+ "YCbCr and CTM together are not possible\n");
+ return -EINVAL;
+ }
+
+ if (crtc_state->output_format != INTEL_OUTPUT_FORMAT_RGB &&
+ crtc_state->hw.degamma_lut && crtc_state->hw.gamma_lut) {
+ drm_dbg_kms(&i915->drm,
+ "YCbCr and degamma+gamma together are not possible\n");
return -EINVAL;
}
@@ -1604,7 +1723,9 @@ static int glk_color_check(struct intel_crtc_state *crtc_state)
if (ret)
return ret;
- crtc_state->preload_luts = glk_can_preload_luts(crtc_state);
+ glk_assign_luts(crtc_state);
+
+ crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
return 0;
}
@@ -1664,6 +1785,8 @@ static int icl_color_check(struct intel_crtc_state *crtc_state)
crtc_state->csc_mode = icl_csc_mode(crtc_state);
+ intel_assign_luts(crtc_state);
+
crtc_state->preload_luts = intel_can_preload_luts(crtc_state);
return 0;
@@ -1749,19 +1872,19 @@ static int icl_gamma_precision(const struct intel_crtc_state *crtc_state)
int intel_color_get_gamma_bit_precision(const 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 drm_i915_private *i915 = to_i915(crtc->base.dev);
- if (HAS_GMCH(dev_priv)) {
- if (IS_CHERRYVIEW(dev_priv))
+ if (HAS_GMCH(i915)) {
+ if (IS_CHERRYVIEW(i915))
return chv_gamma_precision(crtc_state);
else
return i9xx_gamma_precision(crtc_state);
} else {
- if (DISPLAY_VER(dev_priv) >= 11)
+ if (DISPLAY_VER(i915) >= 11)
return icl_gamma_precision(crtc_state);
- else if (DISPLAY_VER(dev_priv) == 10)
+ else if (DISPLAY_VER(i915) == 10)
return glk_gamma_precision(crtc_state);
- else if (IS_IRONLAKE(dev_priv))
+ else if (IS_IRONLAKE(i915))
return ilk_gamma_precision(crtc_state);
}
@@ -1846,7 +1969,7 @@ static struct drm_property_blob *i9xx_read_lut_8(struct intel_crtc *crtc)
int i;
blob = drm_property_create_blob(&dev_priv->drm,
- sizeof(struct drm_color_lut) * LEGACY_LUT_LENGTH,
+ sizeof(lut[0]) * LEGACY_LUT_LENGTH,
NULL);
if (IS_ERR(blob))
return NULL;
@@ -1869,7 +1992,7 @@ static void i9xx_read_luts(struct intel_crtc_state *crtc_state)
if (!crtc_state->gamma_enable)
return;
- crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc);
+ crtc_state->post_csc_lut = i9xx_read_lut_8(crtc);
}
static struct drm_property_blob *i965_read_lut_10p6(struct intel_crtc *crtc)
@@ -1881,7 +2004,7 @@ static struct drm_property_blob *i965_read_lut_10p6(struct intel_crtc *crtc)
struct drm_color_lut *lut;
blob = drm_property_create_blob(&dev_priv->drm,
- sizeof(struct drm_color_lut) * lut_size,
+ sizeof(lut[0]) * lut_size,
NULL);
if (IS_ERR(blob))
return NULL;
@@ -1910,21 +2033,21 @@ static void i965_read_luts(struct intel_crtc_state *crtc_state)
return;
if (crtc_state->gamma_mode == GAMMA_MODE_MODE_8BIT)
- crtc_state->hw.gamma_lut = i9xx_read_lut_8(crtc);
+ crtc_state->post_csc_lut = i9xx_read_lut_8(crtc);
else
- crtc_state->hw.gamma_lut = i965_read_lut_10p6(crtc);
+ crtc_state->post_csc_lut = i965_read_lut_10p6(crtc);
}
static struct drm_property_blob *chv_read_cgm_gamma(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;
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ int i, lut_size = INTEL_INFO(i915)->display.color.gamma_lut_size;
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *lut;
- blob = drm_property_create_blob(&dev_priv->drm,
- sizeof(struct drm_color_lut) * lut_size,
+ blob = drm_property_create_blob(&i915->drm,
+ sizeof(lut[0]) * lut_size,
NULL);
if (IS_ERR(blob))
return NULL;
@@ -1932,8 +2055,8 @@ static struct drm_property_blob *chv_read_cgm_gamma(struct intel_crtc *crtc)
lut = blob->data;
for (i = 0; i < lut_size; i++) {
- u32 ldw = intel_de_read_fw(dev_priv, CGM_PIPE_GAMMA(pipe, i, 0));
- u32 udw = intel_de_read_fw(dev_priv, CGM_PIPE_GAMMA(pipe, i, 1));
+ u32 ldw = intel_de_read_fw(i915, CGM_PIPE_GAMMA(pipe, i, 0));
+ u32 udw = intel_de_read_fw(i915, CGM_PIPE_GAMMA(pipe, i, 1));
chv_cgm_gamma_pack(&lut[i], ldw, udw);
}
@@ -1946,21 +2069,21 @@ static void chv_read_luts(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_GAMMA)
- crtc_state->hw.gamma_lut = chv_read_cgm_gamma(crtc);
+ crtc_state->post_csc_lut = chv_read_cgm_gamma(crtc);
else
i965_read_luts(crtc_state);
}
static struct drm_property_blob *ilk_read_lut_8(struct intel_crtc *crtc)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *lut;
int i;
- blob = drm_property_create_blob(&dev_priv->drm,
- sizeof(struct drm_color_lut) * LEGACY_LUT_LENGTH,
+ blob = drm_property_create_blob(&i915->drm,
+ sizeof(lut[0]) * LEGACY_LUT_LENGTH,
NULL);
if (IS_ERR(blob))
return NULL;
@@ -1968,7 +2091,7 @@ static struct drm_property_blob *ilk_read_lut_8(struct intel_crtc *crtc)
lut = blob->data;
for (i = 0; i < LEGACY_LUT_LENGTH; i++) {
- u32 val = intel_de_read_fw(dev_priv, LGC_PALETTE(pipe, i));
+ u32 val = intel_de_read_fw(i915, LGC_PALETTE(pipe, i));
i9xx_lut_8_pack(&lut[i], val);
}
@@ -1978,14 +2101,14 @@ 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 *dev_priv = to_i915(crtc->base.dev);
- int i, lut_size = INTEL_INFO(dev_priv)->display.color.gamma_lut_size;
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ int i, lut_size = INTEL_INFO(i915)->display.color.gamma_lut_size;
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *lut;
- blob = drm_property_create_blob(&dev_priv->drm,
- sizeof(struct drm_color_lut) * lut_size,
+ blob = drm_property_create_blob(&i915->drm,
+ sizeof(lut[0]) * lut_size,
NULL);
if (IS_ERR(blob))
return NULL;
@@ -1993,7 +2116,7 @@ static struct drm_property_blob *ilk_read_lut_10(struct intel_crtc *crtc)
lut = blob->data;
for (i = 0; i < lut_size; i++) {
- u32 val = intel_de_read_fw(dev_priv, PREC_PALETTE(pipe, i));
+ u32 val = intel_de_read_fw(i915, PREC_PALETTE(pipe, i));
ilk_lut_10_pack(&lut[i], val);
}
@@ -2013,10 +2136,10 @@ static void ilk_read_luts(struct intel_crtc_state *crtc_state)
switch (crtc_state->gamma_mode) {
case GAMMA_MODE_MODE_8BIT:
- crtc_state->hw.gamma_lut = ilk_read_lut_8(crtc);
+ crtc_state->post_csc_lut = ilk_read_lut_8(crtc);
break;
case GAMMA_MODE_MODE_10BIT:
- crtc_state->hw.gamma_lut = ilk_read_lut_10(crtc);
+ crtc_state->post_csc_lut = ilk_read_lut_10(crtc);
break;
default:
MISSING_CASE(crtc_state->gamma_mode);
@@ -2028,33 +2151,33 @@ static void ilk_read_luts(struct intel_crtc_state *crtc_state)
static struct drm_property_blob *bdw_read_lut_10(struct intel_crtc *crtc,
u32 prec_index)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
int i, hw_lut_size = ivb_lut_10_size(prec_index);
- int lut_size = INTEL_INFO(dev_priv)->display.color.gamma_lut_size;
+ int lut_size = INTEL_INFO(i915)->display.color.gamma_lut_size;
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *lut;
- drm_WARN_ON(&dev_priv->drm, lut_size != hw_lut_size);
+ drm_WARN_ON(&i915->drm, lut_size != hw_lut_size);
- blob = drm_property_create_blob(&dev_priv->drm,
- sizeof(struct drm_color_lut) * lut_size,
+ blob = drm_property_create_blob(&i915->drm,
+ sizeof(lut[0]) * lut_size,
NULL);
if (IS_ERR(blob))
return NULL;
lut = blob->data;
- intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe),
+ intel_de_write_fw(i915, PREC_PAL_INDEX(pipe),
prec_index | PAL_PREC_AUTO_INCREMENT);
for (i = 0; i < lut_size; i++) {
- u32 val = intel_de_read_fw(dev_priv, PREC_PAL_DATA(pipe));
+ u32 val = intel_de_read_fw(i915, PREC_PAL_DATA(pipe));
ilk_lut_10_pack(&lut[i], val);
}
- intel_de_write_fw(dev_priv, PREC_PAL_INDEX(pipe), 0);
+ intel_de_write_fw(i915, PREC_PAL_INDEX(pipe), 0);
return blob;
}
@@ -2068,10 +2191,10 @@ static void glk_read_luts(struct intel_crtc_state *crtc_state)
switch (crtc_state->gamma_mode) {
case GAMMA_MODE_MODE_8BIT:
- crtc_state->hw.gamma_lut = ilk_read_lut_8(crtc);
+ crtc_state->post_csc_lut = ilk_read_lut_8(crtc);
break;
case GAMMA_MODE_MODE_10BIT:
- crtc_state->hw.gamma_lut = bdw_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0));
+ crtc_state->post_csc_lut = bdw_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0));
break;
default:
MISSING_CASE(crtc_state->gamma_mode);
@@ -2082,31 +2205,31 @@ static void glk_read_luts(struct intel_crtc_state *crtc_state)
static struct drm_property_blob *
icl_read_lut_multi_segment(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;
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ int i, lut_size = INTEL_INFO(i915)->display.color.gamma_lut_size;
enum pipe pipe = crtc->pipe;
struct drm_property_blob *blob;
struct drm_color_lut *lut;
- blob = drm_property_create_blob(&dev_priv->drm,
- sizeof(struct drm_color_lut) * lut_size,
+ blob = drm_property_create_blob(&i915->drm,
+ sizeof(lut[0]) * lut_size,
NULL);
if (IS_ERR(blob))
return NULL;
lut = blob->data;
- intel_de_write_fw(dev_priv, PREC_PAL_MULTI_SEG_INDEX(pipe),
+ intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe),
PAL_PREC_AUTO_INCREMENT);
for (i = 0; i < 9; i++) {
- u32 ldw = intel_de_read_fw(dev_priv, PREC_PAL_MULTI_SEG_DATA(pipe));
- u32 udw = intel_de_read_fw(dev_priv, PREC_PAL_MULTI_SEG_DATA(pipe));
+ u32 ldw = intel_de_read_fw(i915, PREC_PAL_MULTI_SEG_DATA(pipe));
+ u32 udw = intel_de_read_fw(i915, PREC_PAL_MULTI_SEG_DATA(pipe));
- icl_lut_multi_seg_pack(&lut[i], ldw, udw);
+ ilk_lut_12p4_pack(&lut[i], ldw, udw);
}
- intel_de_write_fw(dev_priv, PREC_PAL_MULTI_SEG_INDEX(pipe), 0);
+ intel_de_write_fw(i915, PREC_PAL_MULTI_SEG_INDEX(pipe), 0);
/*
* FIXME readouts from PAL_PREC_DATA register aren't giving
@@ -2126,13 +2249,13 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state)
switch (crtc_state->gamma_mode & GAMMA_MODE_MODE_MASK) {
case GAMMA_MODE_MODE_8BIT:
- crtc_state->hw.gamma_lut = ilk_read_lut_8(crtc);
+ crtc_state->post_csc_lut = ilk_read_lut_8(crtc);
break;
case GAMMA_MODE_MODE_10BIT:
- crtc_state->hw.gamma_lut = bdw_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0));
+ crtc_state->post_csc_lut = bdw_read_lut_10(crtc, PAL_PREC_INDEX_VALUE(0));
break;
case GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED:
- crtc_state->hw.gamma_lut = icl_read_lut_multi_segment(crtc);
+ crtc_state->post_csc_lut = icl_read_lut_multi_segment(crtc);
break;
default:
MISSING_CASE(crtc_state->gamma_mode);
@@ -2217,41 +2340,58 @@ static const struct intel_color_funcs ilk_color_funcs = {
.read_luts = ilk_read_luts,
};
-void intel_color_init(struct intel_crtc *crtc)
+void intel_color_crtc_init(struct intel_crtc *crtc)
{
- struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- bool has_ctm = INTEL_INFO(dev_priv)->display.color.degamma_lut_size != 0;
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ bool has_ctm = INTEL_INFO(i915)->display.color.degamma_lut_size != 0;
drm_mode_crtc_set_gamma_size(&crtc->base, 256);
- if (HAS_GMCH(dev_priv)) {
- if (IS_CHERRYVIEW(dev_priv)) {
- dev_priv->display.funcs.color = &chv_color_funcs;
- } else if (DISPLAY_VER(dev_priv) >= 4) {
- dev_priv->display.funcs.color = &i965_color_funcs;
- } else {
- dev_priv->display.funcs.color = &i9xx_color_funcs;
- }
- } else {
- if (DISPLAY_VER(dev_priv) >= 11)
- dev_priv->display.funcs.color = &icl_color_funcs;
- else if (DISPLAY_VER(dev_priv) == 10)
- dev_priv->display.funcs.color = &glk_color_funcs;
- else if (DISPLAY_VER(dev_priv) == 9)
- dev_priv->display.funcs.color = &skl_color_funcs;
- else if (DISPLAY_VER(dev_priv) == 8)
- dev_priv->display.funcs.color = &bdw_color_funcs;
- else if (DISPLAY_VER(dev_priv) == 7) {
- if (IS_HASWELL(dev_priv))
- dev_priv->display.funcs.color = &hsw_color_funcs;
- else
- dev_priv->display.funcs.color = &ivb_color_funcs;
- } else
- dev_priv->display.funcs.color = &ilk_color_funcs;
- }
-
drm_crtc_enable_color_mgmt(&crtc->base,
- INTEL_INFO(dev_priv)->display.color.degamma_lut_size,
+ INTEL_INFO(i915)->display.color.degamma_lut_size,
has_ctm,
- INTEL_INFO(dev_priv)->display.color.gamma_lut_size);
+ INTEL_INFO(i915)->display.color.gamma_lut_size);
+}
+
+int intel_color_init(struct drm_i915_private *i915)
+{
+ struct drm_property_blob *blob;
+
+ if (DISPLAY_VER(i915) != 10)
+ return 0;
+
+ blob = create_linear_lut(i915, INTEL_INFO(i915)->display.color.degamma_lut_size);
+ if (IS_ERR(blob))
+ return PTR_ERR(blob);
+
+ i915->display.color.glk_linear_degamma_lut = blob;
+
+ return 0;
+}
+
+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 (DISPLAY_VER(i915) >= 4)
+ i915->display.funcs.color = &i965_color_funcs;
+ else
+ i915->display.funcs.color = &i9xx_color_funcs;
+ } else {
+ if (DISPLAY_VER(i915) >= 11)
+ i915->display.funcs.color = &icl_color_funcs;
+ else if (DISPLAY_VER(i915) == 10)
+ i915->display.funcs.color = &glk_color_funcs;
+ else if (DISPLAY_VER(i915) == 9)
+ i915->display.funcs.color = &skl_color_funcs;
+ else if (DISPLAY_VER(i915) == 8)
+ i915->display.funcs.color = &bdw_color_funcs;
+ else if (IS_HASWELL(i915))
+ i915->display.funcs.color = &hsw_color_funcs;
+ else if (DISPLAY_VER(i915) == 7)
+ i915->display.funcs.color = &ivb_color_funcs;
+ else
+ i915->display.funcs.color = &ilk_color_funcs;
+ }
}
diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h
index fd873425e082..2a5ada67774d 100644
--- a/drivers/gpu/drm/i915/display/intel_color.h
+++ b/drivers/gpu/drm/i915/display/intel_color.h
@@ -10,9 +10,12 @@
struct intel_crtc_state;
struct intel_crtc;
+struct drm_i915_private;
struct drm_property_blob;
-void intel_color_init(struct intel_crtc *crtc);
+void intel_color_init_hooks(struct drm_i915_private *i915);
+int intel_color_init(struct drm_i915_private *i915);
+void intel_color_crtc_init(struct intel_crtc *crtc);
int intel_color_check(struct intel_crtc_state *crtc_state);
void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state);
void intel_color_commit_arm(const struct intel_crtc_state *crtc_state);
@@ -22,5 +25,6 @@ int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_stat
bool intel_color_lut_equal(struct drm_property_blob *blob1,
struct drm_property_blob *blob2,
u32 gamma_mode, u32 bit_precision);
+void intel_color_assert_luts(const struct intel_crtc_state *crtc_state);
#endif /* __INTEL_COLOR_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c b/drivers/gpu/drm/i915/display/intel_combo_phy.c
index 64890f39c3cc..8b870b2dd4f9 100644
--- a/drivers/gpu/drm/i915/display/intel_combo_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c
@@ -3,6 +3,7 @@
* Copyright © 2018 Intel Corporation
*/
+#include "i915_reg.h"
#include "intel_combo_phy.h"
#include "intel_combo_phy_regs.h"
#include "intel_de.h"
@@ -53,7 +54,6 @@ static const struct icl_procmon {
static const struct icl_procmon *
icl_get_procmon_ref_values(struct drm_i915_private *dev_priv, enum phy phy)
{
- const struct icl_procmon *procmon;
u32 val;
val = intel_de_read(dev_priv, ICL_PORT_COMP_DW3(phy));
@@ -62,23 +62,16 @@ icl_get_procmon_ref_values(struct drm_i915_private *dev_priv, enum phy phy)
MISSING_CASE(val);
fallthrough;
case VOLTAGE_INFO_0_85V | PROCESS_INFO_DOT_0:
- procmon = &icl_procmon_values[PROCMON_0_85V_DOT_0];
- break;
+ return &icl_procmon_values[PROCMON_0_85V_DOT_0];
case VOLTAGE_INFO_0_95V | PROCESS_INFO_DOT_0:
- procmon = &icl_procmon_values[PROCMON_0_95V_DOT_0];
- break;
+ return &icl_procmon_values[PROCMON_0_95V_DOT_0];
case VOLTAGE_INFO_0_95V | PROCESS_INFO_DOT_1:
- procmon = &icl_procmon_values[PROCMON_0_95V_DOT_1];
- break;
+ return &icl_procmon_values[PROCMON_0_95V_DOT_1];
case VOLTAGE_INFO_1_05V | PROCESS_INFO_DOT_0:
- procmon = &icl_procmon_values[PROCMON_1_05V_DOT_0];
- break;
+ return &icl_procmon_values[PROCMON_1_05V_DOT_0];
case VOLTAGE_INFO_1_05V | PROCESS_INFO_DOT_1:
- procmon = &icl_procmon_values[PROCMON_1_05V_DOT_1];
- break;
+ return &icl_procmon_values[PROCMON_1_05V_DOT_1];
}
-
- return procmon;
}
static void icl_set_procmon_ref_values(struct drm_i915_private *dev_priv,
diff --git a/drivers/gpu/drm/i915/display/intel_connector.c b/drivers/gpu/drm/i915/display/intel_connector.c
index 6d5cbeb8df4d..6205ddd3ded0 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.c
+++ b/drivers/gpu/drm/i915/display/intel_connector.c
@@ -293,3 +293,21 @@ intel_attach_dp_colorspace_property(struct drm_connector *connector)
if (!drm_mode_create_dp_colorspace_property(connector))
drm_connector_attach_colorspace_property(connector);
}
+
+void
+intel_attach_scaling_mode_property(struct drm_connector *connector)
+{
+ struct drm_i915_private *i915 = to_i915(connector->dev);
+ u32 scaling_modes;
+
+ scaling_modes = BIT(DRM_MODE_SCALE_ASPECT) |
+ BIT(DRM_MODE_SCALE_FULLSCREEN);
+
+ /* On GMCH platforms borders are only possible on the LVDS port */
+ if (!HAS_GMCH(i915) || connector->connector_type == DRM_MODE_CONNECTOR_LVDS)
+ scaling_modes |= BIT(DRM_MODE_SCALE_CENTER);
+
+ drm_connector_attach_scaling_mode_property(connector, scaling_modes);
+
+ connector->state->scaling_mode = DRM_MODE_SCALE_ASPECT;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_connector.h b/drivers/gpu/drm/i915/display/intel_connector.h
index 661a37a3c6d8..9d2bc261b204 100644
--- a/drivers/gpu/drm/i915/display/intel_connector.h
+++ b/drivers/gpu/drm/i915/display/intel_connector.h
@@ -6,7 +6,7 @@
#ifndef __INTEL_CONNECTOR_H__
#define __INTEL_CONNECTOR_H__
-#include "intel_display.h"
+#include <linux/types.h>
struct drm_connector;
struct edid;
@@ -32,5 +32,6 @@ void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
void intel_attach_aspect_ratio_property(struct drm_connector *connector);
void intel_attach_hdmi_colorspace_property(struct drm_connector *connector);
void intel_attach_dp_colorspace_property(struct drm_connector *connector);
+void intel_attach_scaling_mode_property(struct drm_connector *connector);
#endif /* __INTEL_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_crt.c b/drivers/gpu/drm/i915/display/intel_crt.c
index 4a8ff2f97608..797ad9489f7e 100644
--- a/drivers/gpu/drm/i915/display/intel_crt.c
+++ b/drivers/gpu/drm/i915/display/intel_crt.c
@@ -34,6 +34,8 @@
#include <drm/drm_probe_helper.h>
#include "i915_drv.h"
+#include "i915_irq.h"
+#include "i915_reg.h"
#include "intel_connector.h"
#include "intel_crt.h"
#include "intel_crtc.h"
@@ -1044,17 +1046,14 @@ void intel_crt_init(struct drm_i915_private *dev_priv)
intel_connector_attach_encoder(intel_connector, &crt->base);
crt->base.type = INTEL_OUTPUT_ANALOG;
- crt->base.cloneable = (1 << INTEL_OUTPUT_DVO) | (1 << INTEL_OUTPUT_HDMI);
+ crt->base.cloneable = BIT(INTEL_OUTPUT_DVO) | BIT(INTEL_OUTPUT_HDMI);
if (IS_I830(dev_priv))
crt->base.pipe_mask = BIT(PIPE_A);
else
crt->base.pipe_mask = ~0;
- if (DISPLAY_VER(dev_priv) == 2)
- connector->interlace_allowed = 0;
- else
- connector->interlace_allowed = 1;
- connector->doublescan_allowed = 0;
+ if (DISPLAY_VER(dev_priv) != 2)
+ connector->interlace_allowed = true;
crt->adpa_reg = adpa_reg;
diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c
index 6792a9056f46..037fc140b585 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc.c
@@ -365,9 +365,8 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe)
BIT(DRM_SCALING_FILTER_DEFAULT) |
BIT(DRM_SCALING_FILTER_NEAREST_NEIGHBOR));
- intel_color_init(crtc);
-
- intel_crtc_drrs_init(crtc);
+ intel_color_crtc_init(crtc);
+ intel_drrs_crtc_init(crtc);
intel_crtc_crc_init(crtc);
cpu_latency_qos_add_request(&crtc->vblank_pm_qos, PM_QOS_DEFAULT_VALUE);
@@ -387,8 +386,7 @@ static bool intel_crtc_needs_vblank_work(const struct intel_crtc_state *crtc_sta
return crtc_state->hw.active &&
!intel_crtc_needs_modeset(crtc_state) &&
!crtc_state->preload_luts &&
- (crtc_state->uapi.color_mgmt_changed ||
- crtc_state->update_pipe);
+ intel_crtc_needs_color_update(crtc_state);
}
static void intel_crtc_vblank_work(struct kthread_work *base)
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 e9212f69c360..e3273fe8ddac 100644
--- a/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c
+++ b/drivers/gpu/drm/i915/display/intel_crtc_state_dump.c
@@ -298,11 +298,13 @@ void intel_crtc_state_dump(const struct intel_crtc_state *pipe_config,
pipe_config->csc_mode, pipe_config->gamma_mode,
pipe_config->gamma_enable, pipe_config->csc_enable);
- drm_dbg_kms(&i915->drm, "degamma lut: %d entries, gamma lut: %d entries\n",
- pipe_config->hw.degamma_lut ?
- drm_color_lut_size(pipe_config->hw.degamma_lut) : 0,
- pipe_config->hw.gamma_lut ?
- drm_color_lut_size(pipe_config->hw.gamma_lut) : 0);
+ drm_dbg_kms(&i915->drm, "pre csc lut: %s%d entries, post csc lut: %d entries\n",
+ pipe_config->pre_csc_lut && pipe_config->pre_csc_lut ==
+ i915->display.color.glk_linear_degamma_lut ? "(linear) " : "",
+ pipe_config->pre_csc_lut ?
+ drm_color_lut_size(pipe_config->pre_csc_lut) : 0,
+ pipe_config->post_csc_lut ?
+ drm_color_lut_size(pipe_config->post_csc_lut) : 0);
dump_planes:
if (!state)
diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c
index 87899e89b3a7..d190fa0d393b 100644
--- a/drivers/gpu/drm/i915/display/intel_cursor.c
+++ b/drivers/gpu/drm/i915/display/intel_cursor.c
@@ -10,12 +10,13 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_fourcc.h>
+#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_atomic_plane.h"
#include "intel_cursor.h"
#include "intel_de.h"
-#include "intel_display_types.h"
#include "intel_display.h"
+#include "intel_display_types.h"
#include "intel_fb.h"
#include "intel_fb_pin.h"
#include "intel_frontbuffer.h"
@@ -631,8 +632,10 @@ intel_legacy_cursor_update(struct drm_plane *_plane,
*
* FIXME bigjoiner fastpath would be good
*/
- if (!crtc_state->hw.active || intel_crtc_needs_modeset(crtc_state) ||
- crtc_state->update_pipe || crtc_state->bigjoiner_pipes)
+ if (!crtc_state->hw.active ||
+ intel_crtc_needs_modeset(crtc_state) ||
+ intel_crtc_needs_fastset(crtc_state) ||
+ crtc_state->bigjoiner_pipes)
goto slow;
/*
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 69ecf2a3d6c6..0f1ec2a98cc8 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -31,6 +31,7 @@
#include <drm/drm_privacy_screen_consumer.h>
#include "i915_drv.h"
+#include "i915_reg.h"
#include "intel_audio.h"
#include "intel_audio_regs.h"
#include "intel_backlight.h"
@@ -44,6 +45,7 @@
#include "intel_display_power.h"
#include "intel_display_types.h"
#include "intel_dkl_phy.h"
+#include "intel_dkl_phy_regs.h"
#include "intel_dp.h"
#include "intel_dp_link_training.h"
#include "intel_dp_mst.h"
@@ -55,14 +57,15 @@
#include "intel_hdcp.h"
#include "intel_hdmi.h"
#include "intel_hotplug.h"
+#include "intel_hti.h"
#include "intel_lspcon.h"
+#include "intel_mg_phy_regs.h"
#include "intel_pps.h"
#include "intel_psr.h"
#include "intel_quirks.h"
#include "intel_snps_phy.h"
#include "intel_sprite.h"
#include "intel_tc.h"
-#include "intel_tc_phy_regs.h"
#include "intel_vdsc.h"
#include "intel_vrr.h"
#include "skl_scaler.h"
@@ -845,22 +848,65 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder,
}
static enum intel_display_power_domain
-intel_ddi_main_link_aux_domain(struct intel_digital_port *dig_port)
+intel_ddi_main_link_aux_domain(struct intel_digital_port *dig_port,
+ const struct intel_crtc_state *crtc_state)
{
- /* ICL+ HW requires corresponding AUX IOs to be powered up for PSR with
+ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
+
+ /*
+ * ICL+ HW requires corresponding AUX IOs to be powered up for PSR with
* DC states enabled at the same time, while for driver initiated AUX
* transfers we need the same AUX IOs to be powered but with DC states
- * disabled. Accordingly use the AUX power domain here which leaves DC
- * states enabled.
- * However, for non-A AUX ports the corresponding non-EDP transcoders
- * would have already enabled power well 2 and DC_OFF. This means we can
- * acquire a wider POWER_DOMAIN_AUX_{B,C,D,F} reference instead of a
- * specific AUX_IO reference without powering up any extra wells.
- * Note that PSR is enabled only on Port A even though this function
- * returns the correct domain for other ports too.
+ * disabled. Accordingly use the AUX_IO_<port> power domain here which
+ * leaves DC states enabled.
+ *
+ * Before MTL TypeC PHYs (in all TypeC modes and both DP/HDMI) also require
+ * AUX IO to be enabled, but all these require DC_OFF to be enabled as
+ * well, so we can acquire a wider AUX_<port> power domain reference
+ * instead of a specific AUX_IO_<port> reference without powering up any
+ * extra wells.
*/
- return dig_port->aux_ch == AUX_CH_A ? POWER_DOMAIN_AUX_IO_A :
- intel_aux_power_domain(dig_port);
+ if (intel_encoder_can_psr(&dig_port->base))
+ return intel_display_power_aux_io_domain(i915, dig_port->aux_ch);
+ else if (DISPLAY_VER(i915) < 14 &&
+ (intel_crtc_has_dp_encoder(crtc_state) ||
+ intel_phy_is_tc(i915, phy)))
+ return intel_aux_power_domain(dig_port);
+ else
+ return POWER_DOMAIN_INVALID;
+}
+
+static void
+main_link_aux_power_domain_get(struct intel_digital_port *dig_port,
+ const struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ enum intel_display_power_domain domain =
+ intel_ddi_main_link_aux_domain(dig_port, crtc_state);
+
+ drm_WARN_ON(&i915->drm, dig_port->aux_wakeref);
+
+ if (domain == POWER_DOMAIN_INVALID)
+ return;
+
+ dig_port->aux_wakeref = intel_display_power_get(i915, domain);
+}
+
+static void
+main_link_aux_power_domain_put(struct intel_digital_port *dig_port,
+ const struct intel_crtc_state *crtc_state)
+{
+ struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ enum intel_display_power_domain domain =
+ intel_ddi_main_link_aux_domain(dig_port, crtc_state);
+ intel_wakeref_t wf;
+
+ wf = fetch_and_zero(&dig_port->aux_wakeref);
+ if (!wf)
+ return;
+
+ intel_display_power_put(i915, domain, wf);
}
static void intel_ddi_get_power_domains(struct intel_encoder *encoder,
@@ -868,7 +914,6 @@ static void intel_ddi_get_power_domains(struct intel_encoder *encoder,
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_digital_port *dig_port;
- enum phy phy = intel_port_to_phy(dev_priv, encoder->port);
/*
* TODO: Add support for MST encoders. Atm, the following should never
@@ -887,17 +932,7 @@ static void intel_ddi_get_power_domains(struct intel_encoder *encoder,
dig_port->ddi_io_power_domain);
}
- /*
- * AUX power is only needed for (e)DP mode, and for HDMI mode on TC
- * ports.
- */
- if (intel_crtc_has_dp_encoder(crtc_state) ||
- intel_phy_is_tc(dev_priv, phy)) {
- drm_WARN_ON(&dev_priv->drm, dig_port->aux_wakeref);
- dig_port->aux_wakeref =
- intel_display_power_get(dev_priv,
- intel_ddi_main_link_aux_domain(dig_port));
- }
+ main_link_aux_power_domain_get(dig_port, crtc_state);
}
void intel_ddi_enable_pipe_clock(struct intel_encoder *encoder,
@@ -1263,11 +1298,11 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder,
for (ln = 0; ln < 2; ln++) {
int level;
- intel_dkl_phy_write(dev_priv, DKL_TX_PMD_LANE_SUS(tc_port), ln, 0);
+ intel_dkl_phy_write(dev_priv, DKL_TX_PMD_LANE_SUS(tc_port, ln), 0);
level = intel_ddi_level(encoder, crtc_state, 2*ln+0);
- intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL0(tc_port), ln,
+ intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL0(tc_port, ln),
DKL_TX_PRESHOOT_COEFF_MASK |
DKL_TX_DE_EMPAHSIS_COEFF_MASK |
DKL_TX_VSWING_CONTROL_MASK,
@@ -1277,7 +1312,7 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder,
level = intel_ddi_level(encoder, crtc_state, 2*ln+1);
- intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL1(tc_port), ln,
+ intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL1(tc_port, ln),
DKL_TX_PRESHOOT_COEFF_MASK |
DKL_TX_DE_EMPAHSIS_COEFF_MASK |
DKL_TX_VSWING_CONTROL_MASK,
@@ -1285,7 +1320,7 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder,
DKL_TX_DE_EMPHASIS_COEFF(trans->entries[level].dkl.de_emphasis) |
DKL_TX_VSWING_CONTROL(trans->entries[level].dkl.vswing));
- intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port), ln,
+ intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port, ln),
DKL_TX_DP20BITMODE, 0);
if (IS_ALDERLAKE_P(dev_priv)) {
@@ -1304,7 +1339,7 @@ static void tgl_dkl_phy_set_signal_levels(struct intel_encoder *encoder,
val |= DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(0);
}
- intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port), ln,
+ intel_dkl_phy_rmw(dev_priv, DKL_TX_DPCNTL2(tc_port, ln),
DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK |
DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK,
val);
@@ -2017,8 +2052,8 @@ icl_program_mg_dp_mode(struct intel_digital_port *dig_port,
return;
if (DISPLAY_VER(dev_priv) >= 12) {
- ln0 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port), 0);
- ln1 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port), 1);
+ ln0 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port, 0));
+ ln1 = intel_dkl_phy_read(dev_priv, DKL_DP_MODE(tc_port, 1));
} else {
ln0 = intel_de_read(dev_priv, MG_DP_MODE(0, tc_port));
ln1 = intel_de_read(dev_priv, MG_DP_MODE(1, tc_port));
@@ -2079,8 +2114,8 @@ icl_program_mg_dp_mode(struct intel_digital_port *dig_port,
}
if (DISPLAY_VER(dev_priv) >= 12) {
- intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port), 0, ln0);
- intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port), 1, ln1);
+ intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 0), ln0);
+ intel_dkl_phy_write(dev_priv, DKL_DP_MODE(tc_port, 1), ln1);
} else {
intel_de_write(dev_priv, MG_DP_MODE(0, tc_port), ln0);
intel_de_write(dev_priv, MG_DP_MODE(1, tc_port), ln1);
@@ -2736,10 +2771,7 @@ static void intel_ddi_post_disable(struct intel_atomic_state *state,
intel_ddi_post_disable_dp(state, encoder, old_crtc_state,
old_conn_state);
- if (intel_crtc_has_dp_encoder(old_crtc_state) || is_tc_port)
- intel_display_power_put(dev_priv,
- intel_ddi_main_link_aux_domain(dig_port),
- fetch_and_zero(&dig_port->aux_wakeref));
+ main_link_aux_power_domain_put(dig_port, old_crtc_state);
if (is_tc_port)
intel_tc_port_put_link(dig_port);
@@ -3060,12 +3092,7 @@ intel_ddi_pre_pll_enable(struct intel_atomic_state *state,
if (is_tc_port)
intel_tc_port_get_link(dig_port, crtc_state->lane_count);
- if (intel_crtc_has_dp_encoder(crtc_state) || is_tc_port) {
- drm_WARN_ON(&dev_priv->drm, dig_port->aux_wakeref);
- dig_port->aux_wakeref =
- intel_display_power_get(dev_priv,
- intel_ddi_main_link_aux_domain(dig_port));
- }
+ main_link_aux_power_domain_get(dig_port, crtc_state);
if (is_tc_port && !intel_tc_port_in_tbt_alt_mode(dig_port))
/*
@@ -3085,7 +3112,7 @@ static void adlp_tbt_to_dp_alt_switch_wa(struct intel_encoder *encoder)
int ln;
for (ln = 0; ln < 2; ln++)
- intel_dkl_phy_rmw(i915, DKL_PCS_DW5(tc_port), ln, DKL_PCS_DW5_CORE_SOFTRESET, 0);
+ intel_dkl_phy_rmw(i915, DKL_PCS_DW5(tc_port, ln), DKL_PCS_DW5_CORE_SOFTRESET, 0);
}
static void intel_ddi_prepare_link_retrain(struct intel_dp *intel_dp,
@@ -3524,7 +3551,7 @@ static void icl_ddi_tc_get_clock(struct intel_encoder *encoder,
if (drm_WARN_ON(&i915->drm, !pll))
return;
- if (intel_get_shared_dpll_id(i915, pll) == DPLL_ID_ICL_TBTPLL)
+ if (pll->info->id == DPLL_ID_ICL_TBTPLL)
port_dpll_id = ICL_PORT_DPLL_DEFAULT;
else
port_dpll_id = ICL_PORT_DPLL_MG_PHY;
@@ -3537,7 +3564,7 @@ static void icl_ddi_tc_get_clock(struct intel_encoder *encoder,
icl_set_active_port_dpll(crtc_state, port_dpll_id);
- if (intel_get_shared_dpll_id(i915, crtc_state->shared_dpll) == DPLL_ID_ICL_TBTPLL)
+ if (crtc_state->shared_dpll->info->id == DPLL_ID_ICL_TBTPLL)
crtc_state->port_clock = icl_calc_tbt_pll_link(i915, encoder->port);
else
crtc_state->port_clock = intel_dpll_get_freq(i915, crtc_state->shared_dpll,
@@ -3579,7 +3606,7 @@ static void intel_ddi_sync_state(struct intel_encoder *encoder,
enum phy phy = intel_port_to_phy(i915, encoder->port);
if (intel_phy_is_tc(i915, phy))
- intel_tc_port_sanitize(enc_to_dig_port(encoder));
+ intel_tc_port_sanitize_mode(enc_to_dig_port(encoder));
if (crtc_state && intel_crtc_has_dp_encoder(crtc_state))
intel_dp_sync_state(encoder, crtc_state);
@@ -3789,11 +3816,17 @@ static void intel_ddi_encoder_destroy(struct drm_encoder *encoder)
static void intel_ddi_encoder_reset(struct drm_encoder *encoder)
{
+ struct drm_i915_private *i915 = to_i915(encoder->dev);
struct intel_dp *intel_dp = enc_to_intel_dp(to_intel_encoder(encoder));
+ struct intel_digital_port *dig_port = enc_to_dig_port(to_intel_encoder(encoder));
+ enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
intel_dp->reset_link_params = true;
intel_pps_encoder_reset(intel_dp);
+
+ if (intel_phy_is_tc(i915, phy))
+ intel_tc_port_init_mode(dig_port);
}
static const struct drm_encoder_funcs intel_ddi_funcs = {
@@ -4106,12 +4139,6 @@ intel_ddi_max_lanes(struct intel_digital_port *dig_port)
return max_lanes;
}
-static bool hti_uses_phy(struct drm_i915_private *i915, enum phy phy)
-{
- return i915->hti_state & HDPORT_ENABLED &&
- i915->hti_state & HDPORT_DDI_USED(phy);
-}
-
static enum hpd_pin xelpd_hpd_pin(struct drm_i915_private *dev_priv,
enum port port)
{
@@ -4240,7 +4267,7 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
* driver. In that case we should skip initializing the corresponding
* outputs.
*/
- if (hti_uses_phy(dev_priv, phy)) {
+ if (intel_hti_uses_phy(dev_priv, phy)) {
drm_dbg_kms(&dev_priv->drm, "PORT %c / PHY %c reserved by HTI\n",
port_name(port), phy_name(phy));
return;
diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index de77054195c6..6c2686ecb62a 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -76,6 +76,7 @@
#include "g4x_hdmi.h"
#include "hsw_ips.h"
#include "i915_drv.h"
+#include "i915_reg.h"
#include "i915_utils.h"
#include "icl_dsi.h"
#include "intel_acpi.h"
@@ -90,6 +91,7 @@
#include "intel_display_types.h"
#include "intel_dmc.h"
#include "intel_dp_link_training.h"
+#include "intel_dpio_phy.h"
#include "intel_dpt.h"
#include "intel_dsb.h"
#include "intel_fbc.h"
@@ -99,6 +101,7 @@
#include "intel_frontbuffer.h"
#include "intel_hdcp.h"
#include "intel_hotplug.h"
+#include "intel_hti.h"
#include "intel_modeset_verify.h"
#include "intel_modeset_setup.h"
#include "intel_overlay.h"
@@ -831,13 +834,27 @@ intel_plane_fence_y_offset(const struct intel_plane_state *plane_state)
}
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, ret;
+ int i;
intel_modeset_setup_hw_state(i915, ctx);
intel_vga_redisable(i915);
@@ -863,11 +880,7 @@ __intel_display_resume(struct drm_i915_private *i915,
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;
+ return intel_display_commit_duplicated_state(to_intel_atomic_state(state), ctx);
}
static bool gpu_reset_clobbers_display(struct drm_i915_private *dev_priv)
@@ -878,8 +891,7 @@ static bool gpu_reset_clobbers_display(struct drm_i915_private *dev_priv)
void intel_display_prepare_reset(struct drm_i915_private *dev_priv)
{
- struct drm_device *dev = &dev_priv->drm;
- struct drm_modeset_acquire_ctx *ctx = &dev_priv->reset_ctx;
+ struct drm_modeset_acquire_ctx *ctx = &dev_priv->display.restore.reset_ctx;
struct drm_atomic_state *state;
int ret;
@@ -906,10 +918,10 @@ void intel_display_prepare_reset(struct drm_i915_private *dev_priv)
* Need mode_config.mutex so that we don't
* trample ongoing ->detect() and whatnot.
*/
- mutex_lock(&dev->mode_config.mutex);
+ mutex_lock(&dev_priv->drm.mode_config.mutex);
drm_modeset_acquire_init(ctx, 0);
while (1) {
- ret = drm_modeset_lock_all_ctx(dev, ctx);
+ ret = drm_modeset_lock_all_ctx(&dev_priv->drm, ctx);
if (ret != -EDEADLK)
break;
@@ -919,7 +931,7 @@ void intel_display_prepare_reset(struct drm_i915_private *dev_priv)
* 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, ctx);
+ 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",
@@ -927,7 +939,7 @@ void intel_display_prepare_reset(struct drm_i915_private *dev_priv)
return;
}
- ret = drm_atomic_helper_disable_all(dev, ctx);
+ 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);
@@ -935,13 +947,13 @@ void intel_display_prepare_reset(struct drm_i915_private *dev_priv)
return;
}
- dev_priv->modeset_restore_state = state;
+ 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->reset_ctx;
+ struct drm_modeset_acquire_ctx *ctx = &i915->display.restore.reset_ctx;
struct drm_atomic_state *state;
int ret;
@@ -952,14 +964,14 @@ void intel_display_finish_reset(struct drm_i915_private *i915)
if (!test_bit(I915_RESET_MODESET, &to_gt(i915)->reset.flags))
return;
- state = fetch_and_zero(&i915->modeset_restore_state);
+ 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_resume(i915, state, ctx);
+ 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);
@@ -1252,8 +1264,6 @@ static void intel_post_plane_update(struct intel_atomic_state *state,
if (needs_cursorclk_wa(old_crtc_state) &&
!needs_cursorclk_wa(new_crtc_state))
icl_wa_cursorclkgating(dev_priv, pipe, false);
-
- intel_drrs_activate(new_crtc_state);
}
static void intel_crtc_enable_flip_done(struct intel_atomic_state *state,
@@ -2434,7 +2444,7 @@ int intel_display_suspend(struct drm_device *dev)
drm_err(&dev_priv->drm, "Suspending crtc's failed with %i\n",
ret);
else
- dev_priv->modeset_restore_state = state;
+ dev_priv->display.restore.modeset_state = state;
return ret;
}
@@ -4045,20 +4055,19 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
struct intel_crtc_state *pipe_config)
{
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
- struct intel_display_power_domain_set power_domain_set = { };
bool active;
u32 tmp;
- if (!intel_display_power_get_in_set_if_enabled(dev_priv, &power_domain_set,
+ if (!intel_display_power_get_in_set_if_enabled(dev_priv, &crtc->hw_readout_power_domains,
POWER_DOMAIN_PIPE(crtc->pipe)))
return false;
pipe_config->shared_dpll = NULL;
- active = hsw_get_transcoder_state(crtc, pipe_config, &power_domain_set);
+ active = hsw_get_transcoder_state(crtc, pipe_config, &crtc->hw_readout_power_domains);
if ((IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) &&
- bxt_get_dsi_transcoder_state(crtc, pipe_config, &power_domain_set)) {
+ bxt_get_dsi_transcoder_state(crtc, pipe_config, &crtc->hw_readout_power_domains)) {
drm_WARN_ON(&dev_priv->drm, active);
active = true;
}
@@ -4117,7 +4126,7 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
pipe_config->ips_linetime =
REG_FIELD_GET(HSW_IPS_LINETIME_MASK, tmp);
- if (intel_display_power_get_in_set_if_enabled(dev_priv, &power_domain_set,
+ 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);
@@ -4148,7 +4157,7 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc,
}
out:
- intel_display_power_put_all_in_set(dev_priv, &power_domain_set);
+ intel_display_power_put_all_in_set(dev_priv, &crtc->hw_readout_power_domains);
return active;
}
@@ -4576,8 +4585,8 @@ static bool encoders_cloneable(const struct intel_encoder *a,
const struct intel_encoder *b)
{
/* masks could be asymmetric, so check both ways */
- return a == b || (a->cloneable & (1 << b->type) &&
- b->cloneable & (1 << a->type));
+ return a == b || (a->cloneable & BIT(b->type) &&
+ b->cloneable & BIT(a->type));
}
static bool check_single_encoder_cloning(struct intel_atomic_state *state,
@@ -4828,14 +4837,14 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state,
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_crtc_state *crtc_state =
intel_atomic_get_new_crtc_state(state, crtc);
- bool mode_changed = intel_crtc_needs_modeset(crtc_state);
int ret;
if (DISPLAY_VER(dev_priv) < 5 && !IS_G4X(dev_priv) &&
- mode_changed && !crtc_state->hw.active)
+ intel_crtc_needs_modeset(crtc_state) &&
+ !crtc_state->hw.active)
crtc_state->update_wm_post = true;
- if (mode_changed) {
+ if (intel_crtc_needs_modeset(crtc_state)) {
ret = intel_dpll_crtc_get_shared_dpll(state, crtc);
if (ret)
return ret;
@@ -4848,8 +4857,7 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state,
if (c8_planes_changed(crtc_state))
crtc_state->uapi.color_mgmt_changed = true;
- if (mode_changed || crtc_state->update_pipe ||
- crtc_state->uapi.color_mgmt_changed) {
+ if (intel_crtc_needs_color_update(crtc_state)) {
ret = intel_color_check(crtc_state);
if (ret)
return ret;
@@ -4875,7 +4883,8 @@ static int intel_crtc_atomic_check(struct intel_atomic_state *state,
}
if (DISPLAY_VER(dev_priv) >= 9) {
- if (mode_changed || crtc_state->update_pipe) {
+ if (intel_crtc_needs_modeset(crtc_state) ||
+ intel_crtc_needs_fastset(crtc_state)) {
ret = skl_update_scaler_crtc(crtc_state);
if (ret)
return ret;
@@ -5641,39 +5650,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
PIPE_CONF_CHECK_I(name.y2); \
} while (0)
-/* This is required for BDW+ where there is only one set of registers for
- * switching between high and low RR.
- * This macro can be used whenever a comparison has to be made between one
- * hw state and multiple sw state variables.
- */
-#define PIPE_CONF_CHECK_M_N_ALT(name, alt_name) do { \
- if (!intel_compare_link_m_n(&current_config->name, \
- &pipe_config->name) && \
- !intel_compare_link_m_n(&current_config->alt_name, \
- &pipe_config->name)) { \
- pipe_config_mismatch(fastset, crtc, __stringify(name), \
- "(expected tu %i data %i/%i link %i/%i, " \
- "or tu %i data %i/%i link %i/%i, " \
- "found tu %i, data %i/%i link %i/%i)", \
- current_config->name.tu, \
- current_config->name.data_m, \
- current_config->name.data_n, \
- current_config->name.link_m, \
- current_config->name.link_n, \
- current_config->alt_name.tu, \
- current_config->alt_name.data_m, \
- current_config->alt_name.data_n, \
- current_config->alt_name.link_m, \
- current_config->alt_name.link_n, \
- pipe_config->name.tu, \
- pipe_config->name.data_m, \
- pipe_config->name.data_n, \
- pipe_config->name.link_m, \
- pipe_config->name.link_n); \
- ret = false; \
- } \
-} while (0)
-
#define PIPE_CONF_CHECK_FLAGS(name, mask) do { \
if ((current_config->name ^ pipe_config->name) & (mask)) { \
pipe_config_mismatch(fastset, crtc, __stringify(name), \
@@ -5742,7 +5718,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
if (HAS_DOUBLE_BUFFERED_M_N(dev_priv)) {
if (!fastset || !pipe_config->seamless_m_n)
- PIPE_CONF_CHECK_M_N_ALT(dp_m_n, dp_m2_n2);
+ PIPE_CONF_CHECK_M_N(dp_m_n);
} else {
PIPE_CONF_CHECK_M_N(dp_m_n);
PIPE_CONF_CHECK_M_N(dp_m2_n2);
@@ -5819,7 +5795,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config,
bp_gamma = intel_color_get_gamma_bit_precision(pipe_config);
if (bp_gamma)
- PIPE_CONF_CHECK_COLOR_LUT(gamma_mode, hw.gamma_lut, bp_gamma);
+ PIPE_CONF_CHECK_COLOR_LUT(gamma_mode, post_csc_lut, bp_gamma);
if (current_config->active_planes) {
PIPE_CONF_CHECK_BOOL(has_psr);
@@ -5941,7 +5917,8 @@ intel_verify_planes(struct intel_atomic_state *state)
plane_state->uapi.visible);
}
-int intel_modeset_all_pipes(struct intel_atomic_state *state)
+int intel_modeset_all_pipes(struct intel_atomic_state *state,
+ const char *reason)
{
struct drm_i915_private *dev_priv = to_i915(state->base.dev);
struct intel_crtc *crtc;
@@ -5959,10 +5936,14 @@ int intel_modeset_all_pipes(struct intel_atomic_state *state)
return PTR_ERR(crtc_state);
if (!crtc_state->hw.active ||
- drm_atomic_crtc_needs_modeset(&crtc_state->uapi))
+ intel_crtc_needs_modeset(crtc_state))
continue;
+ drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] Full modeset due to %s\n",
+ crtc->base.base.id, crtc->base.name, reason);
+
crtc_state->uapi.mode_changed = true;
+ crtc_state->update_pipe = false;
ret = drm_atomic_add_affected_connectors(&state->base,
&crtc->base);
@@ -6138,7 +6119,8 @@ static void intel_crtc_check_fastset(const struct intel_crtc_state *old_crtc_sta
return;
new_crtc_state->uapi.mode_changed = false;
- new_crtc_state->update_pipe = true;
+ if (!intel_crtc_needs_modeset(new_crtc_state))
+ new_crtc_state->update_pipe = true;
}
static int intel_crtc_add_planes_to_state(struct intel_atomic_state *state,
@@ -6910,12 +6892,19 @@ static int intel_atomic_check(struct drm_device *dev,
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
+ intel_color_assert_luts(new_crtc_state);
+
ret = intel_async_flip_check_hw(state, crtc);
if (ret)
goto fail;
+ /* Either full modeset or fastset (or neither), never both */
+ drm_WARN_ON(&dev_priv->drm,
+ intel_crtc_needs_modeset(new_crtc_state) &&
+ intel_crtc_needs_fastset(new_crtc_state));
+
if (!intel_crtc_needs_modeset(new_crtc_state) &&
- !new_crtc_state->update_pipe)
+ !intel_crtc_needs_fastset(new_crtc_state))
continue;
intel_crtc_state_dump(new_crtc_state, state,
@@ -6951,12 +6940,8 @@ static int intel_atomic_prepare_commit(struct intel_atomic_state *state)
return ret;
for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
- bool mode_changed = intel_crtc_needs_modeset(crtc_state);
-
- if (mode_changed || crtc_state->update_pipe ||
- crtc_state->uapi.color_mgmt_changed) {
+ if (intel_crtc_needs_color_update(crtc_state))
intel_dsb_prepare(crtc_state);
- }
}
return 0;
@@ -7037,14 +7022,13 @@ static void commit_pipe_pre_planes(struct intel_atomic_state *state,
* CRTC was enabled.
*/
if (!modeset) {
- if (new_crtc_state->uapi.color_mgmt_changed ||
- new_crtc_state->update_pipe)
+ if (intel_crtc_needs_color_update(new_crtc_state))
intel_color_commit_arm(new_crtc_state);
if (DISPLAY_VER(dev_priv) >= 9 || IS_BROADWELL(dev_priv))
bdw_set_pipemisc(new_crtc_state);
- if (new_crtc_state->update_pipe)
+ if (intel_crtc_needs_fastset(new_crtc_state))
intel_pipe_fastset(old_crtc_state, new_crtc_state);
}
@@ -7103,25 +7087,23 @@ static void intel_update_crtc(struct intel_atomic_state *state,
if (!modeset) {
if (new_crtc_state->preload_luts &&
- (new_crtc_state->uapi.color_mgmt_changed ||
- new_crtc_state->update_pipe))
+ intel_crtc_needs_color_update(new_crtc_state))
intel_color_load_luts(new_crtc_state);
intel_pre_plane_update(state, crtc);
- if (new_crtc_state->update_pipe)
+ if (intel_crtc_needs_fastset(new_crtc_state))
intel_encoders_update_pipe(state, crtc);
if (DISPLAY_VER(i915) >= 11 &&
- new_crtc_state->update_pipe)
+ intel_crtc_needs_fastset(new_crtc_state))
icl_set_pipe_chicken(new_crtc_state);
}
intel_fbc_update(state, crtc);
if (!modeset &&
- (new_crtc_state->uapi.color_mgmt_changed ||
- new_crtc_state->update_pipe))
+ intel_crtc_needs_color_update(new_crtc_state))
intel_color_commit_noarm(new_crtc_state);
intel_crtc_planes_update_noarm(state, crtc);
@@ -7143,7 +7125,7 @@ static void intel_update_crtc(struct intel_atomic_state *state,
* valid pipe configuration from the BIOS we need to take care
* of enabling them on the CRTC's first fastset.
*/
- if (new_crtc_state->update_pipe && !modeset &&
+ if (intel_crtc_needs_fastset(new_crtc_state) && !modeset &&
old_crtc_state->inherited)
intel_crtc_arm_fifo_underrun(crtc, new_crtc_state);
}
@@ -7166,9 +7148,7 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state,
intel_fbc_disable(crtc);
intel_disable_shared_dpll(old_crtc_state);
- /* FIXME unify this for all platforms */
- if (!new_crtc_state->hw.active &&
- !HAS_GMCH(dev_priv))
+ if (!new_crtc_state->hw.active)
intel_initial_watermarks(state, crtc);
}
@@ -7503,9 +7483,8 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state,
new_crtc_state, i) {
if (intel_crtc_needs_modeset(new_crtc_state) ||
- new_crtc_state->update_pipe) {
+ intel_crtc_needs_fastset(new_crtc_state))
intel_modeset_get_crtc_power_domains(new_crtc_state, &put_domains[crtc->pipe]);
- }
}
intel_commit_modeset_disables(state);
@@ -7609,6 +7588,12 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state)
intel_modeset_verify_crtc(crtc, state, old_crtc_state, new_crtc_state);
/*
+ * Activate DRRS after state readout to avoid
+ * dp_m_n vs. dp_m2_n2 confusion on BDW+.
+ */
+ intel_drrs_activate(new_crtc_state);
+
+ /*
* DSB cleanup is done in cleanup_work aligning with framebuffer
* cleanup. So copy and reset the dsb structure to sync with
* commit_done and later do dsb cleanup in cleanup_work.
@@ -8348,6 +8333,7 @@ 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);
@@ -8589,7 +8575,7 @@ 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->global_obj_list);
+ INIT_LIST_HEAD(&i915->display.global.obj_list);
mode_config->min_width = 0;
mode_config->min_height = 0;
@@ -8678,6 +8664,10 @@ int intel_modeset_init_noirq(struct drm_i915_private *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;
@@ -8750,12 +8740,7 @@ int intel_modeset_init_nogem(struct drm_i915_private *i915)
if (i915->display.cdclk.max_cdclk_freq == 0)
intel_update_max_cdclk(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)
- i915->hti_state = intel_de_read(i915, HDPORT_STATE);
+ intel_hti_init(i915);
/* Just disable it once at startup */
intel_vga_disable(i915);
@@ -8918,14 +8903,14 @@ void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe)
void intel_display_resume(struct drm_device *dev)
{
struct drm_i915_private *i915 = to_i915(dev);
- struct drm_atomic_state *state = i915->modeset_restore_state;
+ struct drm_atomic_state *state = i915->display.restore.modeset_state;
struct drm_modeset_acquire_ctx ctx;
int ret;
if (!HAS_DISPLAY(i915))
return;
- i915->modeset_restore_state = NULL;
+ i915->display.restore.modeset_state = NULL;
if (state)
state->acquire_ctx = &ctx;
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 884e8e67b17c..714030136b7f 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -53,6 +53,7 @@ struct intel_digital_port;
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;
@@ -61,24 +62,6 @@ struct intel_remapped_info;
struct intel_rotation_info;
struct pci_dev;
-enum i915_gpio {
- GPIOA,
- GPIOB,
- GPIOC,
- GPIOD,
- GPIOE,
- GPIOF,
- GPIOG,
- GPIOH,
- __GPIOI_UNUSED,
- GPIOJ,
- GPIOK,
- GPIOL,
- GPIOM,
- GPION,
- GPIOO,
-};
-
/*
* Keep the pipe enum values fixed: the code assumes that PIPE_A=0, the
* rest have consecutive values and match the enum values of transcoders
@@ -279,17 +262,6 @@ enum tc_port_mode {
TC_PORT_LEGACY,
};
-enum dpio_channel {
- DPIO_CH0,
- DPIO_CH1
-};
-
-enum dpio_phy {
- DPIO_PHY0,
- DPIO_PHY1,
- DPIO_PHY2,
-};
-
enum aux_ch {
AUX_CH_A,
AUX_CH_B,
@@ -316,15 +288,6 @@ enum aux_ch {
#define aux_ch_name(a) ((a) + 'A')
-/* Used by dp and fdi links */
-struct intel_link_m_n {
- u32 tu;
- u32 data_m;
- u32 data_n;
- u32 link_m;
- u32 link_n;
-};
-
enum phy {
PHY_NONE = -1,
@@ -469,10 +432,6 @@ enum hpd_pin {
list_for_each_entry((intel_encoder), &(dev)->mode_config.encoder_list, base.head) \
for_each_if((intel_encoder)->base.crtc == (__crtc))
-#define for_each_connector_on_encoder(dev, __encoder, intel_connector) \
- list_for_each_entry((intel_connector), &(dev)->mode_config.connector_list, base.head) \
- for_each_if((intel_connector)->base.encoder == (__encoder))
-
#define for_each_old_intel_plane_in_state(__state, plane, old_plane_state, __i) \
for ((__i) = 0; \
(__i) < (__state)->base.dev->mode_config.num_total_plane && \
@@ -683,7 +642,8 @@ 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);
+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,
struct intel_power_domain_mask *old_domains);
void intel_modeset_put_crtc_power_domains(struct intel_crtc *crtc,
diff --git a/drivers/gpu/drm/i915/display/intel_display_core.h b/drivers/gpu/drm/i915/display/intel_display_core.h
index 9b51148e8ba5..57ddce3ba02b 100644
--- a/drivers/gpu/drm/i915/display/intel_display_core.h
+++ b/drivers/gpu/drm/i915/display/intel_display_core.h
@@ -14,6 +14,7 @@
#include <linux/workqueue.h>
#include <drm/drm_connector.h>
+#include <drm/drm_modeset_lock.h>
#include "intel_cdclk.h"
#include "intel_display.h"
@@ -28,6 +29,7 @@
struct drm_i915_private;
struct drm_property;
+struct drm_property_blob;
struct i915_audio_component;
struct i915_hdcp_comp_master;
struct intel_atomic_state;
@@ -309,6 +311,10 @@ struct intel_display {
} cdclk;
struct {
+ struct drm_property_blob *glk_linear_degamma_lut;
+ } color;
+
+ struct {
/* The current hardware dbuf configuration */
u8 enabled_slices;
@@ -340,6 +346,10 @@ struct intel_display {
} fdi;
struct {
+ struct list_head obj_list;
+ } global;
+
+ struct {
/*
* Base address of where the gmbus and gpio blocks are located
* (either on PCH or on SoC for platforms without PCH).
@@ -366,6 +376,16 @@ struct intel_display {
} hdcp;
struct {
+ /*
+ * HTI (aka HDPORT) state read during initial hw readout. Most
+ * platforms don't have HTI, so this will just stay 0. Those
+ * that do will use this later to figure out which PLLs and PHYs
+ * are unavailable for driver usage.
+ */
+ u32 state;
+ } hti;
+
+ struct {
struct i915_power_domains domains;
/* Shadow for DISPLAY_PHY_CONTROL which can't be safely read */
@@ -392,6 +412,12 @@ struct intel_display {
} quirks;
struct {
+ /* restore state for suspend/resume and display reset */
+ struct drm_atomic_state *modeset_state;
+ struct drm_modeset_acquire_ctx reset_ctx;
+ } restore;
+
+ struct {
enum {
I915_SAGV_UNKNOWN = 0,
I915_SAGV_DISABLED,
diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index 7c7253a2541c..7bcd90384a46 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -9,6 +9,8 @@
#include <drm/drm_fourcc.h>
#include "i915_debugfs.h"
+#include "i915_irq.h"
+#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_debugfs.h"
#include "intel_display_power.h"
@@ -22,6 +24,7 @@
#include "intel_fbdev.h"
#include "intel_hdcp.h"
#include "intel_hdmi.h"
+#include "intel_hotplug.h"
#include "intel_panel.h"
#include "intel_pm.h"
#include "intel_psr.h"
@@ -127,7 +130,6 @@ static int i915_vbt(struct seq_file *m, void *unused)
static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
- struct drm_device *dev = &dev_priv->drm;
struct intel_framebuffer *fbdev_fb = NULL;
struct drm_framebuffer *drm_fb;
@@ -146,8 +148,8 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
}
#endif
- mutex_lock(&dev->mode_config.fb_lock);
- drm_for_each_fb(drm_fb, dev) {
+ mutex_lock(&dev_priv->drm.mode_config.fb_lock);
+ drm_for_each_fb(drm_fb, &dev_priv->drm) {
struct intel_framebuffer *fb = to_intel_framebuffer(drm_fb);
if (fb == fbdev_fb)
continue;
@@ -162,7 +164,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
i915_debugfs_describe_obj(m, intel_fb_obj(&fb->base));
seq_putc(m, '\n');
}
- mutex_unlock(&dev->mode_config.fb_lock);
+ mutex_unlock(&dev_priv->drm.mode_config.fb_lock);
return 0;
}
@@ -897,7 +899,6 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc)
static int i915_display_info(struct seq_file *m, void *unused)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
- struct drm_device *dev = &dev_priv->drm;
struct intel_crtc *crtc;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
@@ -905,22 +906,22 @@ static int i915_display_info(struct seq_file *m, void *unused)
wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm);
- drm_modeset_lock_all(dev);
+ drm_modeset_lock_all(&dev_priv->drm);
seq_printf(m, "CRTC info\n");
seq_printf(m, "---------\n");
- for_each_intel_crtc(dev, crtc)
+ for_each_intel_crtc(&dev_priv->drm, crtc)
intel_crtc_info(m, crtc);
seq_printf(m, "\n");
seq_printf(m, "Connector info\n");
seq_printf(m, "--------------\n");
- drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter)
intel_connector_info(m, connector);
drm_connector_list_iter_end(&conn_iter);
- drm_modeset_unlock_all(dev);
+ drm_modeset_unlock_all(&dev_priv->drm);
intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref);
@@ -930,10 +931,9 @@ static int i915_display_info(struct seq_file *m, void *unused)
static int i915_shared_dplls_info(struct seq_file *m, void *unused)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
- struct drm_device *dev = &dev_priv->drm;
int i;
- drm_modeset_lock_all(dev);
+ drm_modeset_lock_all(&dev_priv->drm);
seq_printf(m, "PLL refclks: non-SSC: %d kHz, SSC: %d kHz\n",
dev_priv->display.dpll.ref_clks.nssc,
@@ -978,7 +978,7 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
seq_printf(m, " mg_pll_tdc_coldst_bias: 0x%08x\n",
pll->state.hw_state.mg_pll_tdc_coldst_bias);
}
- drm_modeset_unlock_all(dev);
+ drm_modeset_unlock_all(&dev_priv->drm);
return 0;
}
@@ -986,14 +986,13 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused)
static int i915_ddb_info(struct seq_file *m, void *unused)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
- struct drm_device *dev = &dev_priv->drm;
struct skl_ddb_entry *entry;
struct intel_crtc *crtc;
if (DISPLAY_VER(dev_priv) < 9)
return -ENODEV;
- drm_modeset_lock_all(dev);
+ drm_modeset_lock_all(&dev_priv->drm);
seq_printf(m, "%-15s%8s%8s%8s\n", "", "Start", "End", "Size");
@@ -1017,53 +1016,7 @@ static int i915_ddb_info(struct seq_file *m, void *unused)
entry->end, skl_ddb_entry_size(entry));
}
- drm_modeset_unlock_all(dev);
-
- return 0;
-}
-
-static int i915_drrs_status(struct seq_file *m, void *unused)
-{
- struct drm_i915_private *dev_priv = node_to_i915(m->private);
- struct drm_connector_list_iter conn_iter;
- struct intel_connector *connector;
- struct intel_crtc *crtc;
-
- drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
- for_each_intel_connector_iter(connector, &conn_iter) {
- seq_printf(m, "[CONNECTOR:%d:%s] DRRS type: %s\n",
- connector->base.base.id, connector->base.name,
- intel_drrs_type_str(intel_panel_drrs_type(connector)));
- }
- drm_connector_list_iter_end(&conn_iter);
-
- seq_puts(m, "\n");
-
- for_each_intel_crtc(&dev_priv->drm, crtc) {
- const struct intel_crtc_state *crtc_state =
- to_intel_crtc_state(crtc->base.state);
-
- seq_printf(m, "[CRTC:%d:%s]:\n",
- crtc->base.base.id, crtc->base.name);
-
- mutex_lock(&crtc->drrs.mutex);
-
- /* DRRS Supported */
- seq_printf(m, "\tDRRS Enabled: %s\n",
- str_yes_no(crtc_state->has_drrs));
-
- seq_printf(m, "\tDRRS Active: %s\n",
- str_yes_no(intel_drrs_is_active(crtc)));
-
- seq_printf(m, "\tBusy_frontbuffer_bits: 0x%X\n",
- crtc->drrs.busy_frontbuffer_bits);
-
- seq_printf(m, "\tDRRS refresh rate: %s\n",
- crtc->drrs.refresh_rate == DRRS_REFRESH_RATE_LOW ?
- "low" : "high");
-
- mutex_unlock(&crtc->drrs.mutex);
- }
+ drm_modeset_unlock_all(&dev_priv->drm);
return 0;
}
@@ -1107,13 +1060,12 @@ static int i915_lpsp_status(struct seq_file *m, void *unused)
static int i915_dp_mst_info(struct seq_file *m, void *unused)
{
struct drm_i915_private *dev_priv = node_to_i915(m->private);
- struct drm_device *dev = &dev_priv->drm;
struct intel_encoder *intel_encoder;
struct intel_digital_port *dig_port;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
- drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
if (connector->connector_type != DRM_MODE_CONNECTOR_DisplayPort)
continue;
@@ -1200,12 +1152,11 @@ static ssize_t i915_displayport_test_active_write(struct file *file,
static int i915_displayport_test_active_show(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = m->private;
- struct drm_device *dev = &dev_priv->drm;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
struct intel_dp *intel_dp;
- drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
struct intel_encoder *encoder;
@@ -1250,12 +1201,11 @@ static const struct file_operations i915_displayport_test_active_fops = {
static int i915_displayport_test_data_show(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = m->private;
- struct drm_device *dev = &dev_priv->drm;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
struct intel_dp *intel_dp;
- drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
struct intel_encoder *encoder;
@@ -1304,12 +1254,11 @@ DEFINE_SHOW_ATTRIBUTE(i915_displayport_test_data);
static int i915_displayport_test_type_show(struct seq_file *m, void *data)
{
struct drm_i915_private *dev_priv = m->private;
- struct drm_device *dev = &dev_priv->drm;
struct drm_connector *connector;
struct drm_connector_list_iter conn_iter;
struct intel_dp *intel_dp;
- drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
struct intel_encoder *encoder;
@@ -1336,7 +1285,6 @@ DEFINE_SHOW_ATTRIBUTE(i915_displayport_test_type);
static void wm_latency_show(struct seq_file *m, const u16 wm[8])
{
struct drm_i915_private *dev_priv = m->private;
- struct drm_device *dev = &dev_priv->drm;
int level;
int num_levels;
@@ -1349,7 +1297,7 @@ static void wm_latency_show(struct seq_file *m, const u16 wm[8])
else
num_levels = ilk_wm_max_level(dev_priv) + 1;
- drm_modeset_lock_all(dev);
+ drm_modeset_lock_all(&dev_priv->drm);
for (level = 0; level < num_levels; level++) {
unsigned int latency = wm[level];
@@ -1370,7 +1318,7 @@ static void wm_latency_show(struct seq_file *m, const u16 wm[8])
level, wm[level], latency / 10, latency % 10);
}
- drm_modeset_unlock_all(dev);
+ drm_modeset_unlock_all(&dev_priv->drm);
}
static int pri_wm_latency_show(struct seq_file *m, void *data)
@@ -1453,7 +1401,6 @@ static ssize_t wm_latency_write(struct file *file, const char __user *ubuf,
{
struct seq_file *m = file->private_data;
struct drm_i915_private *dev_priv = m->private;
- struct drm_device *dev = &dev_priv->drm;
u16 new[8] = { 0 };
int num_levels;
int level;
@@ -1483,12 +1430,12 @@ static ssize_t wm_latency_write(struct file *file, const char __user *ubuf,
if (ret != num_levels)
return -EINVAL;
- drm_modeset_lock_all(dev);
+ drm_modeset_lock_all(&dev_priv->drm);
for (level = 0; level < num_levels; level++)
wm[level] = new[level];
- drm_modeset_unlock_all(dev);
+ drm_modeset_unlock_all(&dev_priv->drm);
return len;
}
@@ -1566,209 +1513,6 @@ static const struct file_operations i915_cur_wm_latency_fops = {
.write = cur_wm_latency_write
};
-static int i915_hpd_storm_ctl_show(struct seq_file *m, void *data)
-{
- struct drm_i915_private *dev_priv = m->private;
- struct intel_hotplug *hotplug = &dev_priv->display.hotplug;
-
- /* Synchronize with everything first in case there's been an HPD
- * storm, but we haven't finished handling it in the kernel yet
- */
- intel_synchronize_irq(dev_priv);
- flush_work(&dev_priv->display.hotplug.dig_port_work);
- flush_delayed_work(&dev_priv->display.hotplug.hotplug_work);
-
- seq_printf(m, "Threshold: %d\n", hotplug->hpd_storm_threshold);
- seq_printf(m, "Detected: %s\n",
- str_yes_no(delayed_work_pending(&hotplug->reenable_work)));
-
- return 0;
-}
-
-static ssize_t i915_hpd_storm_ctl_write(struct file *file,
- const char __user *ubuf, size_t len,
- loff_t *offp)
-{
- struct seq_file *m = file->private_data;
- struct drm_i915_private *dev_priv = m->private;
- struct intel_hotplug *hotplug = &dev_priv->display.hotplug;
- unsigned int new_threshold;
- int i;
- char *newline;
- char tmp[16];
-
- if (len >= sizeof(tmp))
- return -EINVAL;
-
- if (copy_from_user(tmp, ubuf, len))
- return -EFAULT;
-
- tmp[len] = '\0';
-
- /* Strip newline, if any */
- newline = strchr(tmp, '\n');
- if (newline)
- *newline = '\0';
-
- if (strcmp(tmp, "reset") == 0)
- new_threshold = HPD_STORM_DEFAULT_THRESHOLD;
- else if (kstrtouint(tmp, 10, &new_threshold) != 0)
- return -EINVAL;
-
- if (new_threshold > 0)
- drm_dbg_kms(&dev_priv->drm,
- "Setting HPD storm detection threshold to %d\n",
- new_threshold);
- else
- drm_dbg_kms(&dev_priv->drm, "Disabling HPD storm detection\n");
-
- spin_lock_irq(&dev_priv->irq_lock);
- hotplug->hpd_storm_threshold = new_threshold;
- /* Reset the HPD storm stats so we don't accidentally trigger a storm */
- for_each_hpd_pin(i)
- hotplug->stats[i].count = 0;
- spin_unlock_irq(&dev_priv->irq_lock);
-
- /* Re-enable hpd immediately if we were in an irq storm */
- flush_delayed_work(&dev_priv->display.hotplug.reenable_work);
-
- return len;
-}
-
-static int i915_hpd_storm_ctl_open(struct inode *inode, struct file *file)
-{
- return single_open(file, i915_hpd_storm_ctl_show, inode->i_private);
-}
-
-static const struct file_operations i915_hpd_storm_ctl_fops = {
- .owner = THIS_MODULE,
- .open = i915_hpd_storm_ctl_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .write = i915_hpd_storm_ctl_write
-};
-
-static int i915_hpd_short_storm_ctl_show(struct seq_file *m, void *data)
-{
- struct drm_i915_private *dev_priv = m->private;
-
- seq_printf(m, "Enabled: %s\n",
- str_yes_no(dev_priv->display.hotplug.hpd_short_storm_enabled));
-
- return 0;
-}
-
-static int
-i915_hpd_short_storm_ctl_open(struct inode *inode, struct file *file)
-{
- return single_open(file, i915_hpd_short_storm_ctl_show,
- inode->i_private);
-}
-
-static ssize_t i915_hpd_short_storm_ctl_write(struct file *file,
- const char __user *ubuf,
- size_t len, loff_t *offp)
-{
- struct seq_file *m = file->private_data;
- struct drm_i915_private *dev_priv = m->private;
- struct intel_hotplug *hotplug = &dev_priv->display.hotplug;
- char *newline;
- char tmp[16];
- int i;
- bool new_state;
-
- if (len >= sizeof(tmp))
- return -EINVAL;
-
- if (copy_from_user(tmp, ubuf, len))
- return -EFAULT;
-
- tmp[len] = '\0';
-
- /* Strip newline, if any */
- newline = strchr(tmp, '\n');
- if (newline)
- *newline = '\0';
-
- /* Reset to the "default" state for this system */
- if (strcmp(tmp, "reset") == 0)
- new_state = !HAS_DP_MST(dev_priv);
- else if (kstrtobool(tmp, &new_state) != 0)
- return -EINVAL;
-
- drm_dbg_kms(&dev_priv->drm, "%sabling HPD short storm detection\n",
- new_state ? "En" : "Dis");
-
- spin_lock_irq(&dev_priv->irq_lock);
- hotplug->hpd_short_storm_enabled = new_state;
- /* Reset the HPD storm stats so we don't accidentally trigger a storm */
- for_each_hpd_pin(i)
- hotplug->stats[i].count = 0;
- spin_unlock_irq(&dev_priv->irq_lock);
-
- /* Re-enable hpd immediately if we were in an irq storm */
- flush_delayed_work(&dev_priv->display.hotplug.reenable_work);
-
- return len;
-}
-
-static const struct file_operations i915_hpd_short_storm_ctl_fops = {
- .owner = THIS_MODULE,
- .open = i915_hpd_short_storm_ctl_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
- .write = i915_hpd_short_storm_ctl_write,
-};
-
-static int i915_drrs_ctl_set(void *data, u64 val)
-{
- struct drm_i915_private *dev_priv = data;
- struct drm_device *dev = &dev_priv->drm;
- struct intel_crtc *crtc;
-
- for_each_intel_crtc(dev, crtc) {
- struct intel_crtc_state *crtc_state;
- struct drm_crtc_commit *commit;
- int ret;
-
- ret = drm_modeset_lock_single_interruptible(&crtc->base.mutex);
- if (ret)
- return ret;
-
- crtc_state = to_intel_crtc_state(crtc->base.state);
-
- if (!crtc_state->hw.active ||
- !crtc_state->has_drrs)
- goto out;
-
- commit = crtc_state->uapi.commit;
- if (commit) {
- ret = wait_for_completion_interruptible(&commit->hw_done);
- if (ret)
- goto out;
- }
-
- drm_dbg(&dev_priv->drm,
- "Manually %sactivating DRRS\n", val ? "" : "de");
-
- if (val)
- intel_drrs_activate(crtc_state);
- else
- intel_drrs_deactivate(crtc_state);
-
-out:
- drm_modeset_unlock(&crtc->base.mutex);
- if (ret)
- return ret;
- }
-
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(i915_drrs_ctl_fops, NULL, i915_drrs_ctl_set, "%llu\n");
-
static ssize_t
i915_fifo_underrun_reset_write(struct file *filp,
const char __user *ubuf,
@@ -1776,7 +1520,6 @@ i915_fifo_underrun_reset_write(struct file *filp,
{
struct drm_i915_private *dev_priv = filp->private_data;
struct intel_crtc *crtc;
- struct drm_device *dev = &dev_priv->drm;
int ret;
bool reset;
@@ -1787,7 +1530,7 @@ i915_fifo_underrun_reset_write(struct file *filp,
if (!reset)
return cnt;
- for_each_intel_crtc(dev, crtc) {
+ for_each_intel_crtc(&dev_priv->drm, crtc) {
struct drm_crtc_commit *commit;
struct intel_crtc_state *crtc_state;
@@ -1842,7 +1585,6 @@ static const struct drm_info_list intel_display_debugfs_list[] = {
{"i915_shared_dplls_info", i915_shared_dplls_info, 0},
{"i915_dp_mst_info", i915_dp_mst_info, 0},
{"i915_ddb_info", i915_ddb_info, 0},
- {"i915_drrs_status", i915_drrs_status, 0},
{"i915_lpsp_status", i915_lpsp_status, 0},
};
@@ -1857,9 +1599,6 @@ static const struct {
{"i915_dp_test_data", &i915_displayport_test_data_fops},
{"i915_dp_test_type", &i915_displayport_test_type_fops},
{"i915_dp_test_active", &i915_displayport_test_active_fops},
- {"i915_hpd_storm_ctl", &i915_hpd_storm_ctl_fops},
- {"i915_hpd_short_storm_ctl", &i915_hpd_short_storm_ctl_fops},
- {"i915_drrs_ctl", &i915_drrs_ctl_fops},
{"i915_edp_psr_debug", &i915_edp_psr_debug_fops},
};
@@ -1882,6 +1621,7 @@ void intel_display_debugfs_register(struct drm_i915_private *i915)
intel_dmc_debugfs_register(i915);
intel_fbc_debugfs_register(i915);
+ intel_hpd_debugfs_register(i915);
skl_watermark_ipc_debugfs_register(i915);
}
@@ -2195,6 +1935,8 @@ void intel_connector_debugfs_add(struct intel_connector *intel_connector)
if (!root)
return;
+ intel_drrs_connector_debugfs_add(intel_connector);
+
if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
debugfs_create_file("i915_panel_timings", S_IRUGO, root,
connector, &i915_panel_fops);
@@ -2247,6 +1989,7 @@ void intel_crtc_debugfs_add(struct drm_crtc *crtc)
return;
crtc_updates_add(crtc);
+ intel_drrs_crtc_debugfs_add(to_intel_crtc(crtc));
intel_fbc_crtc_debugfs_add(to_intel_crtc(crtc));
debugfs_create_file("i915_current_bpc", 0444, crtc->debugfs_entry, crtc,
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
index 1a63da28f330..3adba64937de 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -129,6 +129,18 @@ intel_display_power_domain_str(enum intel_display_power_domain domain)
return "AUDIO_MMIO";
case POWER_DOMAIN_AUDIO_PLAYBACK:
return "AUDIO_PLAYBACK";
+ case POWER_DOMAIN_AUX_IO_A:
+ return "AUX_IO_A";
+ case POWER_DOMAIN_AUX_IO_B:
+ return "AUX_IO_B";
+ case POWER_DOMAIN_AUX_IO_C:
+ return "AUX_IO_C";
+ case POWER_DOMAIN_AUX_IO_D:
+ return "AUX_IO_D";
+ case POWER_DOMAIN_AUX_IO_E:
+ return "AUX_IO_E";
+ case POWER_DOMAIN_AUX_IO_F:
+ return "AUX_IO_F";
case POWER_DOMAIN_AUX_A:
return "AUX_A";
case POWER_DOMAIN_AUX_B:
@@ -153,8 +165,6 @@ intel_display_power_domain_str(enum intel_display_power_domain domain)
return "AUX_USBC5";
case POWER_DOMAIN_AUX_USBC6:
return "AUX_USBC6";
- case POWER_DOMAIN_AUX_IO_A:
- return "AUX_IO_A";
case POWER_DOMAIN_AUX_TBT1:
return "AUX_TBT1";
case POWER_DOMAIN_AUX_TBT2:
@@ -1148,10 +1158,9 @@ static void hsw_assert_cdclk(struct drm_i915_private *dev_priv)
static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
{
- struct drm_device *dev = &dev_priv->drm;
struct intel_crtc *crtc;
- for_each_intel_crtc(dev, crtc)
+ for_each_intel_crtc(&dev_priv->drm, crtc)
I915_STATE_WARN(crtc->active, "CRTC for pipe %c enabled\n",
pipe_name(crtc->pipe));
@@ -2290,6 +2299,7 @@ struct intel_ddi_port_domains {
enum intel_display_power_domain ddi_lanes;
enum intel_display_power_domain ddi_io;
+ enum intel_display_power_domain aux_io;
enum intel_display_power_domain aux_legacy_usbc;
enum intel_display_power_domain aux_tbt;
};
@@ -2304,6 +2314,7 @@ i9xx_port_domains[] = {
.ddi_lanes = POWER_DOMAIN_PORT_DDI_LANES_A,
.ddi_io = POWER_DOMAIN_PORT_DDI_IO_A,
+ .aux_io = POWER_DOMAIN_AUX_IO_A,
.aux_legacy_usbc = POWER_DOMAIN_AUX_A,
.aux_tbt = POWER_DOMAIN_INVALID,
},
@@ -2319,6 +2330,7 @@ d11_port_domains[] = {
.ddi_lanes = POWER_DOMAIN_PORT_DDI_LANES_A,
.ddi_io = POWER_DOMAIN_PORT_DDI_IO_A,
+ .aux_io = POWER_DOMAIN_AUX_IO_A,
.aux_legacy_usbc = POWER_DOMAIN_AUX_A,
.aux_tbt = POWER_DOMAIN_INVALID,
}, {
@@ -2329,6 +2341,7 @@ d11_port_domains[] = {
.ddi_lanes = POWER_DOMAIN_PORT_DDI_LANES_C,
.ddi_io = POWER_DOMAIN_PORT_DDI_IO_C,
+ .aux_io = POWER_DOMAIN_AUX_IO_C,
.aux_legacy_usbc = POWER_DOMAIN_AUX_C,
.aux_tbt = POWER_DOMAIN_AUX_TBT1,
},
@@ -2344,6 +2357,7 @@ d12_port_domains[] = {
.ddi_lanes = POWER_DOMAIN_PORT_DDI_LANES_A,
.ddi_io = POWER_DOMAIN_PORT_DDI_IO_A,
+ .aux_io = POWER_DOMAIN_AUX_IO_A,
.aux_legacy_usbc = POWER_DOMAIN_AUX_A,
.aux_tbt = POWER_DOMAIN_INVALID,
}, {
@@ -2354,6 +2368,7 @@ d12_port_domains[] = {
.ddi_lanes = POWER_DOMAIN_PORT_DDI_LANES_TC1,
.ddi_io = POWER_DOMAIN_PORT_DDI_IO_TC1,
+ .aux_io = POWER_DOMAIN_INVALID,
.aux_legacy_usbc = POWER_DOMAIN_AUX_USBC1,
.aux_tbt = POWER_DOMAIN_AUX_TBT1,
},
@@ -2369,6 +2384,7 @@ d13_port_domains[] = {
.ddi_lanes = POWER_DOMAIN_PORT_DDI_LANES_A,
.ddi_io = POWER_DOMAIN_PORT_DDI_IO_A,
+ .aux_io = POWER_DOMAIN_AUX_IO_A,
.aux_legacy_usbc = POWER_DOMAIN_AUX_A,
.aux_tbt = POWER_DOMAIN_INVALID,
}, {
@@ -2379,6 +2395,7 @@ d13_port_domains[] = {
.ddi_lanes = POWER_DOMAIN_PORT_DDI_LANES_TC1,
.ddi_io = POWER_DOMAIN_PORT_DDI_IO_TC1,
+ .aux_io = POWER_DOMAIN_INVALID,
.aux_legacy_usbc = POWER_DOMAIN_AUX_USBC1,
.aux_tbt = POWER_DOMAIN_AUX_TBT1,
}, {
@@ -2389,6 +2406,7 @@ d13_port_domains[] = {
.ddi_lanes = POWER_DOMAIN_PORT_DDI_LANES_D,
.ddi_io = POWER_DOMAIN_PORT_DDI_IO_D,
+ .aux_io = POWER_DOMAIN_AUX_IO_D,
.aux_legacy_usbc = POWER_DOMAIN_AUX_D,
.aux_tbt = POWER_DOMAIN_INVALID,
},
@@ -2467,6 +2485,17 @@ intel_port_domains_for_aux_ch(struct drm_i915_private *i915, enum aux_ch aux_ch)
}
enum intel_display_power_domain
+intel_display_power_aux_io_domain(struct drm_i915_private *i915, enum aux_ch aux_ch)
+{
+ const struct intel_ddi_port_domains *domains = intel_port_domains_for_aux_ch(i915, aux_ch);
+
+ if (drm_WARN_ON(&i915->drm, !domains || domains->aux_io == POWER_DOMAIN_INVALID))
+ return POWER_DOMAIN_AUX_IO_A;
+
+ return domains->aux_io + (int)(aux_ch - domains->aux_ch_start);
+}
+
+enum intel_display_power_domain
intel_display_power_legacy_aux_domain(struct drm_i915_private *i915, enum aux_ch aux_ch)
{
const struct intel_ddi_port_domains *domains = intel_port_domains_for_aux_ch(i915, aux_ch);
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h
index 7136ea3f233e..2154d900b1aa 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.h
+++ b/drivers/gpu/drm/i915/display/intel_display_power.h
@@ -6,11 +6,12 @@
#ifndef __INTEL_DISPLAY_POWER_H__
#define __INTEL_DISPLAY_POWER_H__
-#include "intel_runtime_pm.h"
+#include "intel_wakeref.h"
enum aux_ch;
enum dpio_channel;
enum dpio_phy;
+enum i915_drm_suspend_mode;
enum port;
struct drm_i915_private;
struct i915_power_well;
@@ -76,6 +77,14 @@ enum intel_display_power_domain {
POWER_DOMAIN_VGA,
POWER_DOMAIN_AUDIO_MMIO,
POWER_DOMAIN_AUDIO_PLAYBACK,
+
+ POWER_DOMAIN_AUX_IO_A,
+ POWER_DOMAIN_AUX_IO_B,
+ POWER_DOMAIN_AUX_IO_C,
+ POWER_DOMAIN_AUX_IO_D,
+ POWER_DOMAIN_AUX_IO_E,
+ POWER_DOMAIN_AUX_IO_F,
+
POWER_DOMAIN_AUX_A,
POWER_DOMAIN_AUX_B,
POWER_DOMAIN_AUX_C,
@@ -90,8 +99,6 @@ enum intel_display_power_domain {
POWER_DOMAIN_AUX_USBC5,
POWER_DOMAIN_AUX_USBC6,
- POWER_DOMAIN_AUX_IO_A,
-
POWER_DOMAIN_AUX_TBT1,
POWER_DOMAIN_AUX_TBT2,
POWER_DOMAIN_AUX_TBT3,
@@ -249,6 +256,8 @@ intel_display_power_ddi_lanes_domain(struct drm_i915_private *i915, enum port po
enum intel_display_power_domain
intel_display_power_ddi_io_domain(struct drm_i915_private *i915, enum port port);
enum intel_display_power_domain
+intel_display_power_aux_io_domain(struct drm_i915_private *i915, enum aux_ch aux_ch);
+enum intel_display_power_domain
intel_display_power_legacy_aux_domain(struct drm_i915_private *i915, enum aux_ch aux_ch);
enum intel_display_power_domain
intel_display_power_tbt_aux_domain(struct drm_i915_private *i915, enum aux_ch aux_ch);
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 dc04afc6cc8f..f5d66ca85b19 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_map.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power_map.c
@@ -170,6 +170,8 @@ I915_DECL_PW_DOMAINS(vlv_pwdoms_display,
POWER_DOMAIN_VGA,
POWER_DOMAIN_AUDIO_MMIO,
POWER_DOMAIN_AUDIO_PLAYBACK,
+ POWER_DOMAIN_AUX_IO_B,
+ POWER_DOMAIN_AUX_IO_C,
POWER_DOMAIN_AUX_B,
POWER_DOMAIN_AUX_C,
POWER_DOMAIN_GMBUS,
@@ -179,6 +181,8 @@ I915_DECL_PW_DOMAINS(vlv_pwdoms_dpio_cmn_bc,
POWER_DOMAIN_PORT_DDI_LANES_B,
POWER_DOMAIN_PORT_DDI_LANES_C,
POWER_DOMAIN_PORT_CRT,
+ POWER_DOMAIN_AUX_IO_B,
+ POWER_DOMAIN_AUX_IO_C,
POWER_DOMAIN_AUX_B,
POWER_DOMAIN_AUX_C,
POWER_DOMAIN_INIT);
@@ -186,6 +190,8 @@ I915_DECL_PW_DOMAINS(vlv_pwdoms_dpio_cmn_bc,
I915_DECL_PW_DOMAINS(vlv_pwdoms_dpio_tx_bc_lanes,
POWER_DOMAIN_PORT_DDI_LANES_B,
POWER_DOMAIN_PORT_DDI_LANES_C,
+ POWER_DOMAIN_AUX_IO_B,
+ POWER_DOMAIN_AUX_IO_C,
POWER_DOMAIN_AUX_B,
POWER_DOMAIN_AUX_C,
POWER_DOMAIN_INIT);
@@ -243,6 +249,9 @@ I915_DECL_PW_DOMAINS(chv_pwdoms_display,
POWER_DOMAIN_VGA,
POWER_DOMAIN_AUDIO_MMIO,
POWER_DOMAIN_AUDIO_PLAYBACK,
+ POWER_DOMAIN_AUX_IO_B,
+ POWER_DOMAIN_AUX_IO_C,
+ POWER_DOMAIN_AUX_IO_D,
POWER_DOMAIN_AUX_B,
POWER_DOMAIN_AUX_C,
POWER_DOMAIN_AUX_D,
@@ -252,12 +261,15 @@ I915_DECL_PW_DOMAINS(chv_pwdoms_display,
I915_DECL_PW_DOMAINS(chv_pwdoms_dpio_cmn_bc,
POWER_DOMAIN_PORT_DDI_LANES_B,
POWER_DOMAIN_PORT_DDI_LANES_C,
+ POWER_DOMAIN_AUX_IO_B,
+ POWER_DOMAIN_AUX_IO_C,
POWER_DOMAIN_AUX_B,
POWER_DOMAIN_AUX_C,
POWER_DOMAIN_INIT);
I915_DECL_PW_DOMAINS(chv_pwdoms_dpio_cmn_d,
POWER_DOMAIN_PORT_DDI_LANES_D,
+ POWER_DOMAIN_AUX_IO_D,
POWER_DOMAIN_AUX_D,
POWER_DOMAIN_INIT);
@@ -305,6 +317,9 @@ static const struct i915_power_well_desc_list chv_power_wells[] = {
POWER_DOMAIN_VGA, \
POWER_DOMAIN_AUDIO_MMIO, \
POWER_DOMAIN_AUDIO_PLAYBACK, \
+ POWER_DOMAIN_AUX_IO_B, \
+ POWER_DOMAIN_AUX_IO_C, \
+ POWER_DOMAIN_AUX_IO_D, \
POWER_DOMAIN_AUX_B, \
POWER_DOMAIN_AUX_C, \
POWER_DOMAIN_AUX_D
@@ -318,6 +333,7 @@ I915_DECL_PW_DOMAINS(skl_pwdoms_dc_off,
POWER_DOMAIN_AUX_A,
POWER_DOMAIN_MODESET,
POWER_DOMAIN_GT_IRQ,
+ POWER_DOMAIN_DC_OFF,
POWER_DOMAIN_INIT);
I915_DECL_PW_DOMAINS(skl_pwdoms_ddi_io_a_e,
@@ -407,6 +423,8 @@ static const struct i915_power_well_desc_list skl_power_wells[] = {
POWER_DOMAIN_VGA, \
POWER_DOMAIN_AUDIO_MMIO, \
POWER_DOMAIN_AUDIO_PLAYBACK, \
+ POWER_DOMAIN_AUX_IO_B, \
+ POWER_DOMAIN_AUX_IO_C, \
POWER_DOMAIN_AUX_B, \
POWER_DOMAIN_AUX_C
@@ -420,16 +438,20 @@ I915_DECL_PW_DOMAINS(bxt_pwdoms_dc_off,
POWER_DOMAIN_GMBUS,
POWER_DOMAIN_MODESET,
POWER_DOMAIN_GT_IRQ,
+ POWER_DOMAIN_DC_OFF,
POWER_DOMAIN_INIT);
I915_DECL_PW_DOMAINS(bxt_pwdoms_dpio_cmn_a,
POWER_DOMAIN_PORT_DDI_LANES_A,
+ POWER_DOMAIN_AUX_IO_A,
POWER_DOMAIN_AUX_A,
POWER_DOMAIN_INIT);
I915_DECL_PW_DOMAINS(bxt_pwdoms_dpio_cmn_bc,
POWER_DOMAIN_PORT_DDI_LANES_B,
POWER_DOMAIN_PORT_DDI_LANES_C,
+ POWER_DOMAIN_AUX_IO_B,
+ POWER_DOMAIN_AUX_IO_C,
POWER_DOMAIN_AUX_B,
POWER_DOMAIN_AUX_C,
POWER_DOMAIN_INIT);
@@ -483,6 +505,8 @@ static const struct i915_power_well_desc_list bxt_power_wells[] = {
POWER_DOMAIN_VGA, \
POWER_DOMAIN_AUDIO_MMIO, \
POWER_DOMAIN_AUDIO_PLAYBACK, \
+ POWER_DOMAIN_AUX_IO_B, \
+ POWER_DOMAIN_AUX_IO_C, \
POWER_DOMAIN_AUX_B, \
POWER_DOMAIN_AUX_C
@@ -496,6 +520,7 @@ I915_DECL_PW_DOMAINS(glk_pwdoms_dc_off,
POWER_DOMAIN_GMBUS,
POWER_DOMAIN_MODESET,
POWER_DOMAIN_GT_IRQ,
+ POWER_DOMAIN_DC_OFF,
POWER_DOMAIN_INIT);
I915_DECL_PW_DOMAINS(glk_pwdoms_ddi_io_a, POWER_DOMAIN_PORT_DDI_IO_A);
@@ -504,29 +529,34 @@ I915_DECL_PW_DOMAINS(glk_pwdoms_ddi_io_c, POWER_DOMAIN_PORT_DDI_IO_C);
I915_DECL_PW_DOMAINS(glk_pwdoms_dpio_cmn_a,
POWER_DOMAIN_PORT_DDI_LANES_A,
+ POWER_DOMAIN_AUX_IO_A,
POWER_DOMAIN_AUX_A,
POWER_DOMAIN_INIT);
I915_DECL_PW_DOMAINS(glk_pwdoms_dpio_cmn_b,
POWER_DOMAIN_PORT_DDI_LANES_B,
+ POWER_DOMAIN_AUX_IO_B,
POWER_DOMAIN_AUX_B,
POWER_DOMAIN_INIT);
I915_DECL_PW_DOMAINS(glk_pwdoms_dpio_cmn_c,
POWER_DOMAIN_PORT_DDI_LANES_C,
+ POWER_DOMAIN_AUX_IO_C,
POWER_DOMAIN_AUX_C,
POWER_DOMAIN_INIT);
I915_DECL_PW_DOMAINS(glk_pwdoms_aux_a,
- POWER_DOMAIN_AUX_A,
POWER_DOMAIN_AUX_IO_A,
+ POWER_DOMAIN_AUX_A,
POWER_DOMAIN_INIT);
I915_DECL_PW_DOMAINS(glk_pwdoms_aux_b,
+ POWER_DOMAIN_AUX_IO_B,
POWER_DOMAIN_AUX_B,
POWER_DOMAIN_INIT);
I915_DECL_PW_DOMAINS(glk_pwdoms_aux_c,
+ POWER_DOMAIN_AUX_IO_C,
POWER_DOMAIN_AUX_C,
POWER_DOMAIN_INIT);
@@ -617,6 +647,11 @@ I915_DECL_PW_DOMAINS(icl_pwdoms_pw_4,
POWER_DOMAIN_VGA, \
POWER_DOMAIN_AUDIO_MMIO, \
POWER_DOMAIN_AUDIO_PLAYBACK, \
+ POWER_DOMAIN_AUX_IO_B, \
+ POWER_DOMAIN_AUX_IO_C, \
+ POWER_DOMAIN_AUX_IO_D, \
+ POWER_DOMAIN_AUX_IO_E, \
+ POWER_DOMAIN_AUX_IO_F, \
POWER_DOMAIN_AUX_B, \
POWER_DOMAIN_AUX_C, \
POWER_DOMAIN_AUX_D, \
@@ -658,13 +693,23 @@ I915_DECL_PW_DOMAINS(icl_pwdoms_ddi_io_e, POWER_DOMAIN_PORT_DDI_IO_E);
I915_DECL_PW_DOMAINS(icl_pwdoms_ddi_io_f, POWER_DOMAIN_PORT_DDI_IO_F);
I915_DECL_PW_DOMAINS(icl_pwdoms_aux_a,
- POWER_DOMAIN_AUX_A,
- POWER_DOMAIN_AUX_IO_A);
-I915_DECL_PW_DOMAINS(icl_pwdoms_aux_b, POWER_DOMAIN_AUX_B);
-I915_DECL_PW_DOMAINS(icl_pwdoms_aux_c, POWER_DOMAIN_AUX_C);
-I915_DECL_PW_DOMAINS(icl_pwdoms_aux_d, POWER_DOMAIN_AUX_D);
-I915_DECL_PW_DOMAINS(icl_pwdoms_aux_e, POWER_DOMAIN_AUX_E);
-I915_DECL_PW_DOMAINS(icl_pwdoms_aux_f, POWER_DOMAIN_AUX_F);
+ POWER_DOMAIN_AUX_IO_A,
+ POWER_DOMAIN_AUX_A);
+I915_DECL_PW_DOMAINS(icl_pwdoms_aux_b,
+ POWER_DOMAIN_AUX_IO_B,
+ POWER_DOMAIN_AUX_B);
+I915_DECL_PW_DOMAINS(icl_pwdoms_aux_c,
+ POWER_DOMAIN_AUX_IO_C,
+ POWER_DOMAIN_AUX_C);
+I915_DECL_PW_DOMAINS(icl_pwdoms_aux_d,
+ POWER_DOMAIN_AUX_IO_D,
+ POWER_DOMAIN_AUX_D);
+I915_DECL_PW_DOMAINS(icl_pwdoms_aux_e,
+ POWER_DOMAIN_AUX_IO_E,
+ POWER_DOMAIN_AUX_E);
+I915_DECL_PW_DOMAINS(icl_pwdoms_aux_f,
+ POWER_DOMAIN_AUX_IO_F,
+ POWER_DOMAIN_AUX_F);
I915_DECL_PW_DOMAINS(icl_pwdoms_aux_tbt1, POWER_DOMAIN_AUX_TBT1);
I915_DECL_PW_DOMAINS(icl_pwdoms_aux_tbt2, POWER_DOMAIN_AUX_TBT2);
I915_DECL_PW_DOMAINS(icl_pwdoms_aux_tbt3, POWER_DOMAIN_AUX_TBT3);
@@ -816,6 +861,7 @@ I915_DECL_PW_DOMAINS(tgl_pwdoms_dc_off,
POWER_DOMAIN_AUX_B,
POWER_DOMAIN_AUX_C,
POWER_DOMAIN_MODESET,
+ POWER_DOMAIN_DC_OFF,
POWER_DOMAIN_INIT);
I915_DECL_PW_DOMAINS(tgl_pwdoms_ddi_io_tc1, POWER_DOMAIN_PORT_DDI_IO_TC1);
@@ -1012,6 +1058,7 @@ I915_DECL_PW_DOMAINS(rkl_pwdoms_dc_off,
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 rkl_power_wells_main[] = {
@@ -1094,6 +1141,7 @@ I915_DECL_PW_DOMAINS(dg1_pwdoms_dc_off,
POWER_DOMAIN_AUX_A,
POWER_DOMAIN_AUX_B,
POWER_DOMAIN_MODESET,
+ POWER_DOMAIN_DC_OFF,
POWER_DOMAIN_INIT);
I915_DECL_PW_DOMAINS(dg1_pwdoms_pw_2,
@@ -1215,6 +1263,9 @@ I915_DECL_PW_DOMAINS(xelpd_pwdoms_pw_a,
POWER_DOMAIN_PORT_DDI_LANES_TC4, \
POWER_DOMAIN_VGA, \
POWER_DOMAIN_AUDIO_PLAYBACK, \
+ POWER_DOMAIN_AUX_IO_C, \
+ POWER_DOMAIN_AUX_IO_D, \
+ POWER_DOMAIN_AUX_IO_E, \
POWER_DOMAIN_AUX_C, \
POWER_DOMAIN_AUX_D, \
POWER_DOMAIN_AUX_E, \
@@ -1255,6 +1306,7 @@ I915_DECL_PW_DOMAINS(xelpd_pwdoms_dc_off,
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 xelpd_power_wells_main[] = {
@@ -1376,6 +1428,7 @@ I915_DECL_PW_DOMAINS(xelpdp_pwdoms_dc_off,
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,
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 1d18eee56253..8710dd41ffd4 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_well.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c
@@ -13,6 +13,7 @@
#include "intel_display_power_well.h"
#include "intel_display_types.h"
#include "intel_dkl_phy.h"
+#include "intel_dkl_phy_regs.h"
#include "intel_dmc.h"
#include "intel_dpio_phy.h"
#include "intel_dpll.h"
@@ -531,7 +532,7 @@ icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv,
tc_port = TGL_AUX_PW_TO_TC_PORT(i915_power_well_instance(power_well)->hsw.idx);
- if (wait_for(intel_dkl_phy_read(dev_priv, DKL_CMN_UC_DW_27(tc_port), 2) &
+ if (wait_for(intel_dkl_phy_read(dev_priv, DKL_CMN_UC_DW_27(tc_port)) &
DKL_CMN_UC_DW27_UC_HEALTH, 1))
drm_warn(&dev_priv->drm,
"Timeout waiting TC uC health\n");
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 e13b521e322a..ba7cb977e7c7 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power_well.h
+++ b/drivers/gpu/drm/i915/display/intel_display_power_well.h
@@ -7,8 +7,8 @@
#include <linux/types.h>
-#include "intel_display.h"
#include "intel_display_power.h"
+#include "intel_dpio_phy.h"
struct drm_i915_private;
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
new file mode 100644
index 000000000000..02605418ff08
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_display_reg_defs.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+#ifndef __INTEL_DISPLAY_REG_DEFS_H__
+#define __INTEL_DISPLAY_REG_DEFS_H__
+
+#include "i915_reg_defs.h"
+
+#define DISPLAY_MMIO_BASE(dev_priv) (INTEL_INFO(dev_priv)->display.mmio_offset)
+
+#define VLV_DISPLAY_BASE 0x180000
+
+/*
+ * Named helper wrappers around _PICK_EVEN() and _PICK().
+ */
+#define _PIPE(pipe, a, b) _PICK_EVEN(pipe, a, b)
+#define _PLANE(plane, a, b) _PICK_EVEN(plane, a, b)
+#define _TRANS(tran, a, b) _PICK_EVEN(tran, a, b)
+#define _PORT(port, a, b) _PICK_EVEN(port, a, b)
+#define _PLL(pll, a, b) _PICK_EVEN(pll, a, b)
+#define _PHY(phy, a, b) _PICK_EVEN(phy, a, b)
+
+#define _MMIO_PIPE(pipe, a, b) _MMIO(_PIPE(pipe, a, b))
+#define _MMIO_PLANE(plane, a, b) _MMIO(_PLANE(plane, a, b))
+#define _MMIO_TRANS(tran, a, b) _MMIO(_TRANS(tran, a, b))
+#define _MMIO_PORT(port, a, b) _MMIO(_PORT(port, a, b))
+#define _MMIO_PLL(pll, a, b) _MMIO(_PLL(pll, a, b))
+#define _MMIO_PHY(phy, a, b) _MMIO(_PHY(phy, a, b))
+
+#define _PHY3(phy, ...) _PICK(phy, __VA_ARGS__)
+
+#define _MMIO_PIPE3(pipe, a, b, c) _MMIO(_PICK(pipe, a, b, c))
+#define _MMIO_PORT3(pipe, a, b, c) _MMIO(_PICK(pipe, a, b, c))
+#define _MMIO_PHY3(phy, a, b, c) _MMIO(_PHY3(phy, a, b, c))
+#define _MMIO_PLL3(pll, ...) _MMIO(_PICK(pll, __VA_ARGS__))
+
+/*
+ * 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] + \
+ 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] + \
+ 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] + \
+ DISPLAY_MMIO_BASE(dev_priv) + (reg))
+
+#endif /* __INTEL_DISPLAY_REG_DEFS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_display_trace.h b/drivers/gpu/drm/i915/display/intel_display_trace.h
index 2dd5a4b7f5d8..725aba3fa531 100644
--- a/drivers/gpu/drm/i915/display/intel_display_trace.h
+++ b/drivers/gpu/drm/i915/display/intel_display_trace.h
@@ -18,11 +18,15 @@
#include "intel_crtc.h"
#include "intel_display_types.h"
+#define __dev_name_i915(i915) dev_name((i915)->drm.dev)
+#define __dev_name_kms(obj) dev_name((obj)->base.dev->dev)
+
TRACE_EVENT(intel_pipe_enable,
TP_PROTO(struct intel_crtc *crtc),
TP_ARGS(crtc),
TP_STRUCT__entry(
+ __string(dev, __dev_name_kms(crtc))
__array(u32, frame, 3)
__array(u32, scanline, 3)
__field(enum pipe, pipe)
@@ -30,6 +34,7 @@ TRACE_EVENT(intel_pipe_enable,
TP_fast_assign(
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_crtc *it__;
+ __assign_str(dev, __dev_name_kms(crtc));
for_each_intel_crtc(&dev_priv->drm, it__) {
__entry->frame[it__->pipe] = intel_crtc_get_vblank_counter(it__);
__entry->scanline[it__->pipe] = intel_get_crtc_scanline(it__);
@@ -37,8 +42,8 @@ TRACE_EVENT(intel_pipe_enable,
__entry->pipe = crtc->pipe;
),
- TP_printk("pipe %c enable, pipe A: frame=%u, scanline=%u, pipe B: frame=%u, scanline=%u, pipe C: frame=%u, scanline=%u",
- pipe_name(__entry->pipe),
+ TP_printk("dev %s, pipe %c enable, pipe A: frame=%u, scanline=%u, pipe B: frame=%u, scanline=%u, pipe C: frame=%u, scanline=%u",
+ __get_str(dev), pipe_name(__entry->pipe),
__entry->frame[PIPE_A], __entry->scanline[PIPE_A],
__entry->frame[PIPE_B], __entry->scanline[PIPE_B],
__entry->frame[PIPE_C], __entry->scanline[PIPE_C])
@@ -49,6 +54,7 @@ TRACE_EVENT(intel_pipe_disable,
TP_ARGS(crtc),
TP_STRUCT__entry(
+ __string(dev, __dev_name_kms(crtc))
__array(u32, frame, 3)
__array(u32, scanline, 3)
__field(enum pipe, pipe)
@@ -57,6 +63,7 @@ TRACE_EVENT(intel_pipe_disable,
TP_fast_assign(
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
struct intel_crtc *it__;
+ __assign_str(dev, __dev_name_kms(crtc));
for_each_intel_crtc(&dev_priv->drm, it__) {
__entry->frame[it__->pipe] = intel_crtc_get_vblank_counter(it__);
__entry->scanline[it__->pipe] = intel_get_crtc_scanline(it__);
@@ -64,8 +71,8 @@ TRACE_EVENT(intel_pipe_disable,
__entry->pipe = crtc->pipe;
),
- TP_printk("pipe %c disable, pipe A: frame=%u, scanline=%u, pipe B: frame=%u, scanline=%u, pipe C: frame=%u, scanline=%u",
- pipe_name(__entry->pipe),
+ TP_printk("dev %s, pipe %c disable, pipe A: frame=%u, scanline=%u, pipe B: frame=%u, scanline=%u, pipe C: frame=%u, scanline=%u",
+ __get_str(dev), pipe_name(__entry->pipe),
__entry->frame[PIPE_A], __entry->scanline[PIPE_A],
__entry->frame[PIPE_B], __entry->scanline[PIPE_B],
__entry->frame[PIPE_C], __entry->scanline[PIPE_C])
@@ -76,6 +83,7 @@ TRACE_EVENT(intel_pipe_crc,
TP_ARGS(crtc, crcs),
TP_STRUCT__entry(
+ __string(dev, __dev_name_kms(crtc))
__field(enum pipe, pipe)
__field(u32, frame)
__field(u32, scanline)
@@ -83,16 +91,19 @@ TRACE_EVENT(intel_pipe_crc,
),
TP_fast_assign(
+ __assign_str(dev, __dev_name_kms(crtc));
__entry->pipe = crtc->pipe;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
memcpy(__entry->crcs, crcs, sizeof(__entry->crcs));
),
- TP_printk("pipe %c, frame=%u, scanline=%u crc=%08x %08x %08x %08x %08x",
- pipe_name(__entry->pipe), __entry->frame, __entry->scanline,
- __entry->crcs[0], __entry->crcs[1], __entry->crcs[2],
- __entry->crcs[3], __entry->crcs[4])
+ TP_printk("dev %s, pipe %c, frame=%u, scanline=%u crc=%08x %08x %08x %08x %08x",
+ __get_str(dev), pipe_name(__entry->pipe),
+ __entry->frame, __entry->scanline,
+ __entry->crcs[0], __entry->crcs[1],
+ __entry->crcs[2], __entry->crcs[3],
+ __entry->crcs[4])
);
TRACE_EVENT(intel_cpu_fifo_underrun,
@@ -100,6 +111,7 @@ TRACE_EVENT(intel_cpu_fifo_underrun,
TP_ARGS(dev_priv, pipe),
TP_STRUCT__entry(
+ __string(dev, __dev_name_i915(dev_priv))
__field(enum pipe, pipe)
__field(u32, frame)
__field(u32, scanline)
@@ -107,13 +119,14 @@ TRACE_EVENT(intel_cpu_fifo_underrun,
TP_fast_assign(
struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
+ __assign_str(dev, __dev_name_kms(crtc));
__entry->pipe = pipe;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
),
- TP_printk("pipe %c, frame=%u, scanline=%u",
- pipe_name(__entry->pipe),
+ TP_printk("dev %s, pipe %c, frame=%u, scanline=%u",
+ __get_str(dev), pipe_name(__entry->pipe),
__entry->frame, __entry->scanline)
);
@@ -122,6 +135,7 @@ TRACE_EVENT(intel_pch_fifo_underrun,
TP_ARGS(dev_priv, pch_transcoder),
TP_STRUCT__entry(
+ __string(dev, __dev_name_i915(dev_priv))
__field(enum pipe, pipe)
__field(u32, frame)
__field(u32, scanline)
@@ -130,13 +144,14 @@ TRACE_EVENT(intel_pch_fifo_underrun,
TP_fast_assign(
enum pipe pipe = pch_transcoder;
struct intel_crtc *crtc = intel_crtc_for_pipe(dev_priv, pipe);
+ __assign_str(dev, __dev_name_i915(dev_priv));
__entry->pipe = pipe;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
),
- TP_printk("pch transcoder %c, frame=%u, scanline=%u",
- pipe_name(__entry->pipe),
+ TP_printk("dev %s, pch transcoder %c, frame=%u, scanline=%u",
+ __get_str(dev), pipe_name(__entry->pipe),
__entry->frame, __entry->scanline)
);
@@ -145,6 +160,7 @@ TRACE_EVENT(intel_memory_cxsr,
TP_ARGS(dev_priv, old, new),
TP_STRUCT__entry(
+ __string(dev, __dev_name_i915(dev_priv))
__array(u32, frame, 3)
__array(u32, scanline, 3)
__field(bool, old)
@@ -153,6 +169,7 @@ TRACE_EVENT(intel_memory_cxsr,
TP_fast_assign(
struct intel_crtc *crtc;
+ __assign_str(dev, __dev_name_i915(dev_priv));
for_each_intel_crtc(&dev_priv->drm, crtc) {
__entry->frame[crtc->pipe] = intel_crtc_get_vblank_counter(crtc);
__entry->scanline[crtc->pipe] = intel_get_crtc_scanline(crtc);
@@ -161,8 +178,8 @@ TRACE_EVENT(intel_memory_cxsr,
__entry->new = new;
),
- TP_printk("%s->%s, pipe A: frame=%u, scanline=%u, pipe B: frame=%u, scanline=%u, pipe C: frame=%u, scanline=%u",
- str_on_off(__entry->old), str_on_off(__entry->new),
+ TP_printk("dev %s, cxsr %s->%s, pipe A: frame=%u, scanline=%u, pipe B: frame=%u, scanline=%u, pipe C: frame=%u, scanline=%u",
+ __get_str(dev), str_on_off(__entry->old), str_on_off(__entry->new),
__entry->frame[PIPE_A], __entry->scanline[PIPE_A],
__entry->frame[PIPE_B], __entry->scanline[PIPE_B],
__entry->frame[PIPE_C], __entry->scanline[PIPE_C])
@@ -173,6 +190,7 @@ TRACE_EVENT(g4x_wm,
TP_ARGS(crtc, wm),
TP_STRUCT__entry(
+ __string(dev, __dev_name_kms(crtc))
__field(enum pipe, pipe)
__field(u32, frame)
__field(u32, scanline)
@@ -191,6 +209,7 @@ TRACE_EVENT(g4x_wm,
),
TP_fast_assign(
+ __assign_str(dev, __dev_name_kms(crtc));
__entry->pipe = crtc->pipe;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
@@ -208,8 +227,9 @@ TRACE_EVENT(g4x_wm,
__entry->fbc = wm->fbc_en;
),
- TP_printk("pipe %c, frame=%u, scanline=%u, wm %d/%d/%d, sr %s/%d/%d/%d, hpll %s/%d/%d/%d, fbc %s",
- pipe_name(__entry->pipe), __entry->frame, __entry->scanline,
+ TP_printk("dev %s, pipe %c, frame=%u, scanline=%u, wm %d/%d/%d, sr %s/%d/%d/%d, hpll %s/%d/%d/%d, fbc %s",
+ __get_str(dev), pipe_name(__entry->pipe),
+ __entry->frame, __entry->scanline,
__entry->primary, __entry->sprite, __entry->cursor,
str_yes_no(__entry->cxsr), __entry->sr_plane, __entry->sr_cursor, __entry->sr_fbc,
str_yes_no(__entry->hpll), __entry->hpll_plane, __entry->hpll_cursor, __entry->hpll_fbc,
@@ -221,6 +241,7 @@ TRACE_EVENT(vlv_wm,
TP_ARGS(crtc, wm),
TP_STRUCT__entry(
+ __string(dev, __dev_name_kms(crtc))
__field(enum pipe, pipe)
__field(u32, frame)
__field(u32, scanline)
@@ -235,6 +256,7 @@ TRACE_EVENT(vlv_wm,
),
TP_fast_assign(
+ __assign_str(dev, __dev_name_kms(crtc));
__entry->pipe = crtc->pipe;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
@@ -248,9 +270,10 @@ TRACE_EVENT(vlv_wm,
__entry->sr_cursor = wm->sr.cursor;
),
- TP_printk("pipe %c, frame=%u, scanline=%u, level=%d, cxsr=%d, wm %d/%d/%d/%d, sr %d/%d",
- pipe_name(__entry->pipe), __entry->frame,
- __entry->scanline, __entry->level, __entry->cxsr,
+ TP_printk("dev %s, pipe %c, frame=%u, scanline=%u, level=%d, cxsr=%d, wm %d/%d/%d/%d, sr %d/%d",
+ __get_str(dev), pipe_name(__entry->pipe),
+ __entry->frame, __entry->scanline,
+ __entry->level, __entry->cxsr,
__entry->primary, __entry->sprite0, __entry->sprite1, __entry->cursor,
__entry->sr_plane, __entry->sr_cursor)
);
@@ -260,6 +283,7 @@ TRACE_EVENT(vlv_fifo_size,
TP_ARGS(crtc, sprite0_start, sprite1_start, fifo_size),
TP_STRUCT__entry(
+ __string(dev, __dev_name_kms(crtc))
__field(enum pipe, pipe)
__field(u32, frame)
__field(u32, scanline)
@@ -269,6 +293,7 @@ TRACE_EVENT(vlv_fifo_size,
),
TP_fast_assign(
+ __assign_str(dev, __dev_name_kms(crtc));
__entry->pipe = crtc->pipe;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
@@ -277,90 +302,96 @@ TRACE_EVENT(vlv_fifo_size,
__entry->fifo_size = fifo_size;
),
- TP_printk("pipe %c, frame=%u, scanline=%u, %d/%d/%d",
- pipe_name(__entry->pipe), __entry->frame,
- __entry->scanline, __entry->sprite0_start,
- __entry->sprite1_start, __entry->fifo_size)
+ TP_printk("dev %s, pipe %c, frame=%u, scanline=%u, %d/%d/%d",
+ __get_str(dev), pipe_name(__entry->pipe),
+ __entry->frame, __entry->scanline,
+ __entry->sprite0_start, __entry->sprite1_start, __entry->fifo_size)
);
TRACE_EVENT(intel_plane_update_noarm,
- TP_PROTO(struct drm_plane *plane, struct intel_crtc *crtc),
+ TP_PROTO(struct intel_plane *plane, struct intel_crtc *crtc),
TP_ARGS(plane, crtc),
TP_STRUCT__entry(
+ __string(dev, __dev_name_kms(plane))
__field(enum pipe, pipe)
__field(u32, frame)
__field(u32, scanline)
__array(int, src, 4)
__array(int, dst, 4)
- __string(name, plane->name)
+ __string(name, plane->base.name)
),
TP_fast_assign(
- __assign_str(name, plane->name);
+ __assign_str(dev, __dev_name_kms(plane));
+ __assign_str(name, plane->base.name);
__entry->pipe = crtc->pipe;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
- memcpy(__entry->src, &plane->state->src, sizeof(__entry->src));
- memcpy(__entry->dst, &plane->state->dst, sizeof(__entry->dst));
+ memcpy(__entry->src, &plane->base.state->src, sizeof(__entry->src));
+ memcpy(__entry->dst, &plane->base.state->dst, sizeof(__entry->dst));
),
- TP_printk("pipe %c, plane %s, frame=%u, scanline=%u, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT,
- pipe_name(__entry->pipe), __get_str(name),
+ TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT,
+ __get_str(dev), pipe_name(__entry->pipe), __get_str(name),
__entry->frame, __entry->scanline,
DRM_RECT_FP_ARG((const struct drm_rect *)__entry->src),
DRM_RECT_ARG((const struct drm_rect *)__entry->dst))
);
TRACE_EVENT(intel_plane_update_arm,
- TP_PROTO(struct drm_plane *plane, struct intel_crtc *crtc),
+ TP_PROTO(struct intel_plane *plane, struct intel_crtc *crtc),
TP_ARGS(plane, crtc),
TP_STRUCT__entry(
+ __string(dev, __dev_name_kms(plane))
__field(enum pipe, pipe)
__field(u32, frame)
__field(u32, scanline)
__array(int, src, 4)
__array(int, dst, 4)
- __string(name, plane->name)
+ __string(name, plane->base.name)
),
TP_fast_assign(
- __assign_str(name, plane->name);
+ __assign_str(dev, __dev_name_kms(plane));
+ __assign_str(name, plane->base.name);
__entry->pipe = crtc->pipe;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
- memcpy(__entry->src, &plane->state->src, sizeof(__entry->src));
- memcpy(__entry->dst, &plane->state->dst, sizeof(__entry->dst));
+ memcpy(__entry->src, &plane->base.state->src, sizeof(__entry->src));
+ memcpy(__entry->dst, &plane->base.state->dst, sizeof(__entry->dst));
),
- TP_printk("pipe %c, plane %s, frame=%u, scanline=%u, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT,
- pipe_name(__entry->pipe), __get_str(name),
+ TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u, " DRM_RECT_FP_FMT " -> " DRM_RECT_FMT,
+ __get_str(dev), pipe_name(__entry->pipe), __get_str(name),
__entry->frame, __entry->scanline,
DRM_RECT_FP_ARG((const struct drm_rect *)__entry->src),
DRM_RECT_ARG((const struct drm_rect *)__entry->dst))
);
TRACE_EVENT(intel_plane_disable_arm,
- TP_PROTO(struct drm_plane *plane, struct intel_crtc *crtc),
+ TP_PROTO(struct intel_plane *plane, struct intel_crtc *crtc),
TP_ARGS(plane, crtc),
TP_STRUCT__entry(
+ __string(dev, __dev_name_kms(plane))
__field(enum pipe, pipe)
__field(u32, frame)
__field(u32, scanline)
- __string(name, plane->name)
+ __string(name, plane->base.name)
),
TP_fast_assign(
- __assign_str(name, plane->name);
+ __assign_str(dev, __dev_name_kms(plane));
+ __assign_str(name, plane->base.name);
__entry->pipe = crtc->pipe;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
),
- TP_printk("pipe %c, plane %s, frame=%u, scanline=%u",
- pipe_name(__entry->pipe), __get_str(name),
+ TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u",
+ __get_str(dev), pipe_name(__entry->pipe), __get_str(name),
__entry->frame, __entry->scanline)
);
@@ -369,6 +400,8 @@ TRACE_EVENT(intel_fbc_activate,
TP_ARGS(plane),
TP_STRUCT__entry(
+ __string(dev, __dev_name_kms(plane))
+ __string(name, plane->base.name)
__field(enum pipe, pipe)
__field(u32, frame)
__field(u32, scanline)
@@ -377,13 +410,16 @@ TRACE_EVENT(intel_fbc_activate,
TP_fast_assign(
struct intel_crtc *crtc = intel_crtc_for_pipe(to_i915(plane->base.dev),
plane->pipe);
+ __assign_str(dev, __dev_name_kms(plane));
+ __assign_str(name, plane->base.name)
__entry->pipe = crtc->pipe;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
),
- TP_printk("pipe %c, frame=%u, scanline=%u",
- pipe_name(__entry->pipe), __entry->frame, __entry->scanline)
+ TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u",
+ __get_str(dev), pipe_name(__entry->pipe), __get_str(name),
+ __entry->frame, __entry->scanline)
);
TRACE_EVENT(intel_fbc_deactivate,
@@ -391,6 +427,8 @@ TRACE_EVENT(intel_fbc_deactivate,
TP_ARGS(plane),
TP_STRUCT__entry(
+ __string(dev, __dev_name_kms(plane))
+ __string(name, plane->base.name)
__field(enum pipe, pipe)
__field(u32, frame)
__field(u32, scanline)
@@ -399,13 +437,16 @@ TRACE_EVENT(intel_fbc_deactivate,
TP_fast_assign(
struct intel_crtc *crtc = intel_crtc_for_pipe(to_i915(plane->base.dev),
plane->pipe);
+ __assign_str(dev, __dev_name_kms(plane));
+ __assign_str(name, plane->base.name)
__entry->pipe = crtc->pipe;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
),
- TP_printk("pipe %c, frame=%u, scanline=%u",
- pipe_name(__entry->pipe), __entry->frame, __entry->scanline)
+ TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u",
+ __get_str(dev), pipe_name(__entry->pipe), __get_str(name),
+ __entry->frame, __entry->scanline)
);
TRACE_EVENT(intel_fbc_nuke,
@@ -413,6 +454,8 @@ TRACE_EVENT(intel_fbc_nuke,
TP_ARGS(plane),
TP_STRUCT__entry(
+ __string(dev, __dev_name_kms(plane))
+ __string(name, plane->base.name)
__field(enum pipe, pipe)
__field(u32, frame)
__field(u32, scanline)
@@ -421,13 +464,16 @@ TRACE_EVENT(intel_fbc_nuke,
TP_fast_assign(
struct intel_crtc *crtc = intel_crtc_for_pipe(to_i915(plane->base.dev),
plane->pipe);
+ __assign_str(dev, __dev_name_kms(plane));
+ __assign_str(name, plane->base.name)
__entry->pipe = crtc->pipe;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
),
- TP_printk("pipe %c, frame=%u, scanline=%u",
- pipe_name(__entry->pipe), __entry->frame, __entry->scanline)
+ TP_printk("dev %s, pipe %c, plane %s, frame=%u, scanline=%u",
+ __get_str(dev), pipe_name(__entry->pipe), __get_str(name),
+ __entry->frame, __entry->scanline)
);
TRACE_EVENT(intel_crtc_vblank_work_start,
@@ -435,20 +481,22 @@ TRACE_EVENT(intel_crtc_vblank_work_start,
TP_ARGS(crtc),
TP_STRUCT__entry(
+ __string(dev, __dev_name_kms(crtc))
__field(enum pipe, pipe)
__field(u32, frame)
__field(u32, scanline)
),
TP_fast_assign(
+ __assign_str(dev, __dev_name_kms(crtc));
__entry->pipe = crtc->pipe;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
),
- TP_printk("pipe %c, frame=%u, scanline=%u",
- pipe_name(__entry->pipe), __entry->frame,
- __entry->scanline)
+ TP_printk("dev %s, pipe %c, frame=%u, scanline=%u",
+ __get_str(dev), pipe_name(__entry->pipe),
+ __entry->frame, __entry->scanline)
);
TRACE_EVENT(intel_crtc_vblank_work_end,
@@ -456,20 +504,22 @@ TRACE_EVENT(intel_crtc_vblank_work_end,
TP_ARGS(crtc),
TP_STRUCT__entry(
+ __string(dev, __dev_name_kms(crtc))
__field(enum pipe, pipe)
__field(u32, frame)
__field(u32, scanline)
),
TP_fast_assign(
+ __assign_str(dev, __dev_name_kms(crtc));
__entry->pipe = crtc->pipe;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
),
- TP_printk("pipe %c, frame=%u, scanline=%u",
- pipe_name(__entry->pipe), __entry->frame,
- __entry->scanline)
+ TP_printk("dev %s, pipe %c, frame=%u, scanline=%u",
+ __get_str(dev), pipe_name(__entry->pipe),
+ __entry->frame, __entry->scanline)
);
TRACE_EVENT(intel_pipe_update_start,
@@ -477,6 +527,7 @@ TRACE_EVENT(intel_pipe_update_start,
TP_ARGS(crtc),
TP_STRUCT__entry(
+ __string(dev, __dev_name_kms(crtc))
__field(enum pipe, pipe)
__field(u32, frame)
__field(u32, scanline)
@@ -485,6 +536,7 @@ TRACE_EVENT(intel_pipe_update_start,
),
TP_fast_assign(
+ __assign_str(dev, __dev_name_kms(crtc));
__entry->pipe = crtc->pipe;
__entry->frame = intel_crtc_get_vblank_counter(crtc);
__entry->scanline = intel_get_crtc_scanline(crtc);
@@ -492,9 +544,10 @@ TRACE_EVENT(intel_pipe_update_start,
__entry->max = crtc->debug.max_vbl;
),
- TP_printk("pipe %c, frame=%u, scanline=%u, min=%u, max=%u",
- pipe_name(__entry->pipe), __entry->frame,
- __entry->scanline, __entry->min, __entry->max)
+ TP_printk("dev %s, pipe %c, frame=%u, scanline=%u, min=%u, max=%u",
+ __get_str(dev), pipe_name(__entry->pipe),
+ __entry->frame, __entry->scanline,
+ __entry->min, __entry->max)
);
TRACE_EVENT(intel_pipe_update_vblank_evaded,
@@ -502,6 +555,7 @@ TRACE_EVENT(intel_pipe_update_vblank_evaded,
TP_ARGS(crtc),
TP_STRUCT__entry(
+ __string(dev, __dev_name_kms(crtc))
__field(enum pipe, pipe)
__field(u32, frame)
__field(u32, scanline)
@@ -510,6 +564,7 @@ TRACE_EVENT(intel_pipe_update_vblank_evaded,
),
TP_fast_assign(
+ __assign_str(dev, __dev_name_kms(crtc));
__entry->pipe = crtc->pipe;
__entry->frame = crtc->debug.start_vbl_count;
__entry->scanline = crtc->debug.scanline_start;
@@ -517,9 +572,10 @@ TRACE_EVENT(intel_pipe_update_vblank_evaded,
__entry->max = crtc->debug.max_vbl;
),
- TP_printk("pipe %c, frame=%u, scanline=%u, min=%u, max=%u",
- pipe_name(__entry->pipe), __entry->frame,
- __entry->scanline, __entry->min, __entry->max)
+ TP_printk("dev %s, pipe %c, frame=%u, scanline=%u, min=%u, max=%u",
+ __get_str(dev), pipe_name(__entry->pipe),
+ __entry->frame, __entry->scanline,
+ __entry->min, __entry->max)
);
TRACE_EVENT(intel_pipe_update_end,
@@ -527,56 +583,64 @@ TRACE_EVENT(intel_pipe_update_end,
TP_ARGS(crtc, frame, scanline_end),
TP_STRUCT__entry(
+ __string(dev, __dev_name_kms(crtc))
__field(enum pipe, pipe)
__field(u32, frame)
__field(u32, scanline)
),
TP_fast_assign(
+ __assign_str(dev, __dev_name_kms(crtc));
__entry->pipe = crtc->pipe;
__entry->frame = frame;
__entry->scanline = scanline_end;
),
- TP_printk("pipe %c, frame=%u, scanline=%u",
- pipe_name(__entry->pipe), __entry->frame,
- __entry->scanline)
+ TP_printk("dev %s, pipe %c, frame=%u, scanline=%u",
+ __get_str(dev), pipe_name(__entry->pipe),
+ __entry->frame, __entry->scanline)
);
TRACE_EVENT(intel_frontbuffer_invalidate,
- TP_PROTO(unsigned int frontbuffer_bits, unsigned int origin),
- TP_ARGS(frontbuffer_bits, origin),
+ TP_PROTO(struct drm_i915_private *i915,
+ unsigned int frontbuffer_bits, unsigned int origin),
+ TP_ARGS(i915, frontbuffer_bits, origin),
TP_STRUCT__entry(
+ __string(dev, __dev_name_i915(i915))
__field(unsigned int, frontbuffer_bits)
__field(unsigned int, origin)
),
TP_fast_assign(
+ __assign_str(dev, __dev_name_i915(i915));
__entry->frontbuffer_bits = frontbuffer_bits;
__entry->origin = origin;
),
- TP_printk("frontbuffer_bits=0x%08x, origin=%u",
- __entry->frontbuffer_bits, __entry->origin)
+ TP_printk("dev %s, frontbuffer_bits=0x%08x, origin=%u",
+ __get_str(dev), __entry->frontbuffer_bits, __entry->origin)
);
TRACE_EVENT(intel_frontbuffer_flush,
- TP_PROTO(unsigned int frontbuffer_bits, unsigned int origin),
- TP_ARGS(frontbuffer_bits, origin),
+ TP_PROTO(struct drm_i915_private *i915,
+ unsigned int frontbuffer_bits, unsigned int origin),
+ TP_ARGS(i915, frontbuffer_bits, origin),
TP_STRUCT__entry(
+ __string(dev, __dev_name_i915(i915))
__field(unsigned int, frontbuffer_bits)
__field(unsigned int, origin)
),
TP_fast_assign(
+ __assign_str(dev, __dev_name_i915(i915));
__entry->frontbuffer_bits = frontbuffer_bits;
__entry->origin = origin;
),
- TP_printk("frontbuffer_bits=0x%08x, origin=%u",
- __entry->frontbuffer_bits, __entry->origin)
+ TP_printk("dev %s, frontbuffer_bits=0x%08x, origin=%u",
+ __get_str(dev), __entry->frontbuffer_bits, __entry->origin)
);
#endif /* __INTEL_DISPLAY_TRACE_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 298d00a11f47..f07395065a69 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -969,6 +969,15 @@ struct intel_mpllb_state {
u32 mpllb_sscstep;
};
+/* Used by dp and fdi links */
+struct intel_link_m_n {
+ u32 tu;
+ u32 data_m;
+ u32 data_n;
+ u32 link_m;
+ u32 link_n;
+};
+
struct intel_crtc_state {
/*
* uapi (drm) state. This is the software state shown to userspace.
@@ -1001,11 +1010,15 @@ struct intel_crtc_state {
*/
struct {
bool active, enable;
+ /* logical state of LUTs */
struct drm_property_blob *degamma_lut, *gamma_lut, *ctm;
struct drm_display_mode mode, pipe_mode, adjusted_mode;
enum drm_scaling_filter scaling_filter;
} hw;
+ /* actual state of LUTs */
+ struct drm_property_blob *pre_csc_lut, *post_csc_lut;
+
/**
* quirks - bitfield with hw state readout quirks
*
@@ -1362,6 +1375,7 @@ struct intel_crtc {
u16 vmax_vblank_start;
struct intel_display_power_domain_set enabled_power_domains;
+ struct intel_display_power_domain_set hw_readout_power_domains;
struct intel_overlay *overlay;
struct intel_crtc_state *config;
@@ -1799,51 +1813,6 @@ struct intel_dp_mst_encoder {
struct intel_connector *connector;
};
-static inline enum dpio_channel
-vlv_dig_port_to_channel(struct intel_digital_port *dig_port)
-{
- switch (dig_port->base.port) {
- default:
- MISSING_CASE(dig_port->base.port);
- fallthrough;
- case PORT_B:
- case PORT_D:
- return DPIO_CH0;
- case PORT_C:
- return DPIO_CH1;
- }
-}
-
-static inline enum dpio_phy
-vlv_dig_port_to_phy(struct intel_digital_port *dig_port)
-{
- switch (dig_port->base.port) {
- default:
- MISSING_CASE(dig_port->base.port);
- fallthrough;
- case PORT_B:
- case PORT_C:
- return DPIO_PHY0;
- case PORT_D:
- return DPIO_PHY1;
- }
-}
-
-static inline enum dpio_channel
-vlv_pipe_to_channel(enum pipe pipe)
-{
- switch (pipe) {
- default:
- MISSING_CASE(pipe);
- fallthrough;
- case PIPE_A:
- case PIPE_C:
- return DPIO_CH0;
- case PIPE_B:
- return DPIO_CH1;
- }
-}
-
struct intel_load_detect_pipe {
struct drm_atomic_state *restore_state;
};
@@ -2040,15 +2009,16 @@ static inline bool
intel_crtc_has_type(const struct intel_crtc_state *crtc_state,
enum intel_output_type type)
{
- return crtc_state->output_types & (1 << type);
+ return crtc_state->output_types & BIT(type);
}
+
static inline bool
intel_crtc_has_dp_encoder(const struct intel_crtc_state *crtc_state)
{
return crtc_state->output_types &
- ((1 << INTEL_OUTPUT_DP) |
- (1 << INTEL_OUTPUT_DP_MST) |
- (1 << INTEL_OUTPUT_EDP));
+ (BIT(INTEL_OUTPUT_DP) |
+ BIT(INTEL_OUTPUT_DP_MST) |
+ BIT(INTEL_OUTPUT_EDP));
}
static inline bool
@@ -2057,6 +2027,20 @@ intel_crtc_needs_modeset(const struct intel_crtc_state *crtc_state)
return drm_atomic_crtc_needs_modeset(&crtc_state->uapi);
}
+static inline bool
+intel_crtc_needs_fastset(const struct intel_crtc_state *crtc_state)
+{
+ return crtc_state->update_pipe;
+}
+
+static inline bool
+intel_crtc_needs_color_update(const struct intel_crtc_state *crtc_state)
+{
+ return crtc_state->uapi.color_mgmt_changed ||
+ intel_crtc_needs_fastset(crtc_state) ||
+ intel_crtc_needs_modeset(crtc_state);
+}
+
static inline u32 intel_plane_ggtt_offset(const struct intel_plane_state *plane_state)
{
return i915_ggtt_offset(plane_state->ggtt_vma);
diff --git a/drivers/gpu/drm/i915/display/intel_dkl_phy.c b/drivers/gpu/drm/i915/display/intel_dkl_phy.c
index 710b030c7ed5..57cc3edba016 100644
--- a/drivers/gpu/drm/i915/display/intel_dkl_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_dkl_phy.c
@@ -9,9 +9,10 @@
#include "intel_de.h"
#include "intel_display.h"
#include "intel_dkl_phy.h"
+#include "intel_dkl_phy_regs.h"
static void
-dkl_phy_set_hip_idx(struct drm_i915_private *i915, i915_reg_t reg, int idx)
+dkl_phy_set_hip_idx(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg)
{
enum tc_port tc_port = DKL_REG_TC_PORT(reg);
@@ -19,28 +20,27 @@ dkl_phy_set_hip_idx(struct drm_i915_private *i915, i915_reg_t reg, int idx)
intel_de_write(i915,
HIP_INDEX_REG(tc_port),
- HIP_INDEX_VAL(tc_port, idx));
+ HIP_INDEX_VAL(tc_port, reg.bank_idx));
}
/**
* intel_dkl_phy_read - read a Dekel PHY register
* @i915: i915 device instance
* @reg: Dekel PHY register
- * @ln: lane instance of @reg
*
* Read the @reg Dekel PHY register.
*
* Returns the read value.
*/
u32
-intel_dkl_phy_read(struct drm_i915_private *i915, i915_reg_t reg, int ln)
+intel_dkl_phy_read(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg)
{
u32 val;
spin_lock(&i915->display.dkl.phy_lock);
- dkl_phy_set_hip_idx(i915, reg, ln);
- val = intel_de_read(i915, reg);
+ dkl_phy_set_hip_idx(i915, reg);
+ val = intel_de_read(i915, DKL_REG_MMIO(reg));
spin_unlock(&i915->display.dkl.phy_lock);
@@ -51,18 +51,17 @@ intel_dkl_phy_read(struct drm_i915_private *i915, i915_reg_t reg, int ln)
* intel_dkl_phy_write - write a Dekel PHY register
* @i915: i915 device instance
* @reg: Dekel PHY register
- * @ln: lane instance of @reg
* @val: value to write
*
* Write @val to the @reg Dekel PHY register.
*/
void
-intel_dkl_phy_write(struct drm_i915_private *i915, i915_reg_t reg, int ln, u32 val)
+intel_dkl_phy_write(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg, u32 val)
{
spin_lock(&i915->display.dkl.phy_lock);
- dkl_phy_set_hip_idx(i915, reg, ln);
- intel_de_write(i915, reg, val);
+ dkl_phy_set_hip_idx(i915, reg);
+ intel_de_write(i915, DKL_REG_MMIO(reg), val);
spin_unlock(&i915->display.dkl.phy_lock);
}
@@ -71,7 +70,6 @@ intel_dkl_phy_write(struct drm_i915_private *i915, i915_reg_t reg, int ln, u32 v
* intel_dkl_phy_rmw - read-modify-write a Dekel PHY register
* @i915: i915 device instance
* @reg: Dekel PHY register
- * @ln: lane instance of @reg
* @clear: mask to clear
* @set: mask to set
*
@@ -79,12 +77,12 @@ intel_dkl_phy_write(struct drm_i915_private *i915, i915_reg_t reg, int ln, u32 v
* this value back to the register if the value differs from the read one.
*/
void
-intel_dkl_phy_rmw(struct drm_i915_private *i915, i915_reg_t reg, int ln, u32 clear, u32 set)
+intel_dkl_phy_rmw(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg, u32 clear, u32 set)
{
spin_lock(&i915->display.dkl.phy_lock);
- dkl_phy_set_hip_idx(i915, reg, ln);
- intel_de_rmw(i915, reg, clear, set);
+ dkl_phy_set_hip_idx(i915, reg);
+ intel_de_rmw(i915, DKL_REG_MMIO(reg), clear, set);
spin_unlock(&i915->display.dkl.phy_lock);
}
@@ -93,17 +91,16 @@ intel_dkl_phy_rmw(struct drm_i915_private *i915, i915_reg_t reg, int ln, u32 cle
* intel_dkl_phy_posting_read - do a posting read from a Dekel PHY register
* @i915: i915 device instance
* @reg: Dekel PHY register
- * @ln: lane instance of @reg
*
* Read the @reg Dekel PHY register without returning the read value.
*/
void
-intel_dkl_phy_posting_read(struct drm_i915_private *i915, i915_reg_t reg, int ln)
+intel_dkl_phy_posting_read(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg)
{
spin_lock(&i915->display.dkl.phy_lock);
- dkl_phy_set_hip_idx(i915, reg, ln);
- intel_de_posting_read(i915, reg);
+ dkl_phy_set_hip_idx(i915, reg);
+ intel_de_posting_read(i915, DKL_REG_MMIO(reg));
spin_unlock(&i915->display.dkl.phy_lock);
}
diff --git a/drivers/gpu/drm/i915/display/intel_dkl_phy.h b/drivers/gpu/drm/i915/display/intel_dkl_phy.h
index 260ad121a0b1..570ee36f9386 100644
--- a/drivers/gpu/drm/i915/display/intel_dkl_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_dkl_phy.h
@@ -8,17 +8,17 @@
#include <linux/types.h>
-#include "i915_reg_defs.h"
+#include "intel_dkl_phy_regs.h"
struct drm_i915_private;
u32
-intel_dkl_phy_read(struct drm_i915_private *i915, i915_reg_t reg, int ln);
+intel_dkl_phy_read(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg);
void
-intel_dkl_phy_write(struct drm_i915_private *i915, i915_reg_t reg, int ln, u32 val);
+intel_dkl_phy_write(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg, u32 val);
void
-intel_dkl_phy_rmw(struct drm_i915_private *i915, i915_reg_t reg, int ln, u32 clear, u32 set);
+intel_dkl_phy_rmw(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg, u32 clear, u32 set);
void
-intel_dkl_phy_posting_read(struct drm_i915_private *i915, i915_reg_t reg, int ln);
+intel_dkl_phy_posting_read(struct drm_i915_private *i915, struct intel_dkl_phy_reg reg);
#endif /* __INTEL_DKL_PHY_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dkl_phy_regs.h b/drivers/gpu/drm/i915/display/intel_dkl_phy_regs.h
new file mode 100644
index 000000000000..56085b32956d
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_dkl_phy_regs.h
@@ -0,0 +1,204 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+#ifndef __INTEL_DKL_PHY_REGS__
+#define __INTEL_DKL_PHY_REGS__
+
+#include <linux/types.h>
+
+struct intel_dkl_phy_reg {
+ u32 reg:24;
+ u32 bank_idx:4;
+};
+
+#define _DKL_PHY1_BASE 0x168000
+#define _DKL_PHY2_BASE 0x169000
+#define _DKL_PHY3_BASE 0x16A000
+#define _DKL_PHY4_BASE 0x16B000
+#define _DKL_PHY5_BASE 0x16C000
+#define _DKL_PHY6_BASE 0x16D000
+
+#define DKL_REG_TC_PORT(__reg) \
+ (TC_PORT_1 + ((__reg).reg - _DKL_PHY1_BASE) / (_DKL_PHY2_BASE - _DKL_PHY1_BASE))
+
+/* DEKEL PHY MMIO Address = Phy base + (internal address & ~index_mask) */
+#define DKL_REG_MMIO(__reg) _MMIO((__reg).reg)
+
+#define _DKL_REG_PHY_BASE(tc_port) _PORT(tc_port, \
+ _DKL_PHY1_BASE, \
+ _DKL_PHY2_BASE)
+
+#define _DKL_BANK_SHIFT 12
+#define _DKL_REG_BANK_OFFSET(phy_offset) \
+ ((phy_offset) & ((1 << _DKL_BANK_SHIFT) - 1))
+#define _DKL_REG_BANK_IDX(phy_offset) \
+ (((phy_offset) >> _DKL_BANK_SHIFT) & 0xf)
+
+#define _DKL_REG(tc_port, phy_offset) \
+ ((const struct intel_dkl_phy_reg) { \
+ .reg = _DKL_REG_PHY_BASE(tc_port) + \
+ _DKL_REG_BANK_OFFSET(phy_offset), \
+ .bank_idx = _DKL_REG_BANK_IDX(phy_offset), \
+ })
+
+#define _DKL_REG_LN(tc_port, ln_idx, ln0_offs, ln1_offs) \
+ _DKL_REG(tc_port, (ln0_offs) + (ln_idx) * ((ln1_offs) - (ln0_offs)))
+
+#define _DKL_PCS_DW5_LN0 0x0014
+#define _DKL_PCS_DW5_LN1 0x1014
+#define DKL_PCS_DW5(tc_port, ln) _DKL_REG_LN(tc_port, ln, \
+ _DKL_PCS_DW5_LN0, \
+ _DKL_PCS_DW5_LN1)
+#define DKL_PCS_DW5_CORE_SOFTRESET REG_BIT(11)
+
+#define _DKL_PLL_DIV0 0x2200
+#define DKL_PLL_DIV0(tc_port) _DKL_REG(tc_port, \
+ _DKL_PLL_DIV0)
+#define DKL_PLL_DIV0_AFC_STARTUP_MASK REG_GENMASK(27, 25)
+#define DKL_PLL_DIV0_AFC_STARTUP(val) REG_FIELD_PREP(DKL_PLL_DIV0_AFC_STARTUP_MASK, (val))
+#define DKL_PLL_DIV0_INTEG_COEFF(x) ((x) << 16)
+#define DKL_PLL_DIV0_INTEG_COEFF_MASK (0x1F << 16)
+#define DKL_PLL_DIV0_PROP_COEFF(x) ((x) << 12)
+#define DKL_PLL_DIV0_PROP_COEFF_MASK (0xF << 12)
+#define DKL_PLL_DIV0_FBPREDIV_SHIFT (8)
+#define DKL_PLL_DIV0_FBPREDIV(x) ((x) << DKL_PLL_DIV0_FBPREDIV_SHIFT)
+#define DKL_PLL_DIV0_FBPREDIV_MASK (0xF << DKL_PLL_DIV0_FBPREDIV_SHIFT)
+#define DKL_PLL_DIV0_FBDIV_INT(x) ((x) << 0)
+#define DKL_PLL_DIV0_FBDIV_INT_MASK (0xFF << 0)
+#define DKL_PLL_DIV0_MASK (DKL_PLL_DIV0_INTEG_COEFF_MASK | \
+ DKL_PLL_DIV0_PROP_COEFF_MASK | \
+ DKL_PLL_DIV0_FBPREDIV_MASK | \
+ DKL_PLL_DIV0_FBDIV_INT_MASK)
+
+#define _DKL_PLL_DIV1 0x2204
+#define DKL_PLL_DIV1(tc_port) _DKL_REG(tc_port, \
+ _DKL_PLL_DIV1)
+#define DKL_PLL_DIV1_IREF_TRIM(x) ((x) << 16)
+#define DKL_PLL_DIV1_IREF_TRIM_MASK (0x1F << 16)
+#define DKL_PLL_DIV1_TDC_TARGET_CNT(x) ((x) << 0)
+#define DKL_PLL_DIV1_TDC_TARGET_CNT_MASK (0xFF << 0)
+
+#define _DKL_PLL_SSC 0x2210
+#define DKL_PLL_SSC(tc_port) _DKL_REG(tc_port, \
+ _DKL_PLL_SSC)
+#define DKL_PLL_SSC_IREF_NDIV_RATIO(x) ((x) << 29)
+#define DKL_PLL_SSC_IREF_NDIV_RATIO_MASK (0x7 << 29)
+#define DKL_PLL_SSC_STEP_LEN(x) ((x) << 16)
+#define DKL_PLL_SSC_STEP_LEN_MASK (0xFF << 16)
+#define DKL_PLL_SSC_STEP_NUM(x) ((x) << 11)
+#define DKL_PLL_SSC_STEP_NUM_MASK (0x7 << 11)
+#define DKL_PLL_SSC_EN (1 << 9)
+
+#define _DKL_PLL_BIAS 0x2214
+#define DKL_PLL_BIAS(tc_port) _DKL_REG(tc_port, \
+ _DKL_PLL_BIAS)
+#define DKL_PLL_BIAS_FRAC_EN_H (1 << 30)
+#define DKL_PLL_BIAS_FBDIV_SHIFT (8)
+#define DKL_PLL_BIAS_FBDIV_FRAC(x) ((x) << DKL_PLL_BIAS_FBDIV_SHIFT)
+#define DKL_PLL_BIAS_FBDIV_FRAC_MASK (0x3FFFFF << DKL_PLL_BIAS_FBDIV_SHIFT)
+
+#define _DKL_PLL_TDC_COLDST_BIAS 0x2218
+#define DKL_PLL_TDC_COLDST_BIAS(tc_port) _DKL_REG(tc_port, \
+ _DKL_PLL_TDC_COLDST_BIAS)
+#define DKL_PLL_TDC_SSC_STEP_SIZE(x) ((x) << 8)
+#define DKL_PLL_TDC_SSC_STEP_SIZE_MASK (0xFF << 8)
+#define DKL_PLL_TDC_FEED_FWD_GAIN(x) ((x) << 0)
+#define DKL_PLL_TDC_FEED_FWD_GAIN_MASK (0xFF << 0)
+
+#define _DKL_REFCLKIN_CTL 0x212C
+#define DKL_REFCLKIN_CTL(tc_port) _DKL_REG(tc_port, \
+ _DKL_REFCLKIN_CTL)
+/* Bits are the same as MG_REFCLKIN_CTL */
+
+#define _DKL_CLKTOP2_HSCLKCTL 0x20D4
+#define DKL_CLKTOP2_HSCLKCTL(rc_port) _DKL_REG(tc_port, \
+ _DKL_CLKTOP2_HSCLKCTL)
+/* Bits are the same as MG_CLKTOP2_HSCLKCTL */
+
+#define _DKL_CLKTOP2_CORECLKCTL1 0x20D8
+#define DKL_CLKTOP2_CORECLKCTL1(tc_port) _DKL_REG(tc_port, \
+ _DKL_CLKTOP2_CORECLKCTL1)
+/* Bits are the same as MG_CLKTOP2_CORECLKCTL1 */
+
+#define _DKL_TX_DPCNTL0_LN0 0x02C0
+#define _DKL_TX_DPCNTL0_LN1 0x12C0
+#define DKL_TX_DPCNTL0(tc_port, ln) _DKL_REG_LN(tc_port, ln, \
+ _DKL_TX_DPCNTL0_LN0, \
+ _DKL_TX_DPCNTL0_LN1)
+#define DKL_TX_PRESHOOT_COEFF(x) ((x) << 13)
+#define DKL_TX_PRESHOOT_COEFF_MASK (0x1f << 13)
+#define DKL_TX_DE_EMPHASIS_COEFF(x) ((x) << 8)
+#define DKL_TX_DE_EMPAHSIS_COEFF_MASK (0x1f << 8)
+#define DKL_TX_VSWING_CONTROL(x) ((x) << 0)
+#define DKL_TX_VSWING_CONTROL_MASK (0x7 << 0)
+
+#define _DKL_TX_DPCNTL1_LN0 0x02C4
+#define _DKL_TX_DPCNTL1_LN1 0x12C4
+#define DKL_TX_DPCNTL1(tc_port, ln) _DKL_REG_LN(tc_port, ln, \
+ _DKL_TX_DPCNTL1_LN0, \
+ _DKL_TX_DPCNTL1_LN1)
+/* Bits are the same as DKL_TX_DPCNTRL0 */
+
+#define _DKL_TX_DPCNTL2_LN0 0x02C8
+#define _DKL_TX_DPCNTL2_LN1 0x12C8
+#define DKL_TX_DPCNTL2(tc_port, ln) _DKL_REG_LN(tc_port, ln, \
+ _DKL_TX_DPCNTL2_LN0, \
+ _DKL_TX_DPCNTL2_LN1)
+#define DKL_TX_DP20BITMODE REG_BIT(2)
+#define DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK REG_GENMASK(4, 3)
+#define DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1(val) REG_FIELD_PREP(DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK, (val))
+#define DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK REG_GENMASK(6, 5)
+#define DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(val) REG_FIELD_PREP(DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK, (val))
+
+#define _DKL_TX_FW_CALIB_LN0 0x02F8
+#define _DKL_TX_FW_CALIB_LN1 0x12F8
+#define DKL_TX_FW_CALIB(tc_port, ln) _DKL_REG_LN(tc_port, ln, \
+ _DKL_TX_FW_CALIB_LN0, \
+ _DKL_TX_FW_CALIB_LN1)
+#define DKL_TX_CFG_DISABLE_WAIT_INIT (1 << 7)
+
+#define _DKL_TX_PMD_LANE_SUS_LN0 0x0D00
+#define _DKL_TX_PMD_LANE_SUS_LN1 0x1D00
+#define DKL_TX_PMD_LANE_SUS(tc_port, ln) _DKL_REG_LN(tc_port, ln, \
+ _DKL_TX_PMD_LANE_SUS_LN0, \
+ _DKL_TX_PMD_LANE_SUS_LN1)
+
+#define _DKL_TX_DW17_LN0 0x0DC4
+#define _DKL_TX_DW17_LN1 0x1DC4
+#define DKL_TX_DW17(tc_port, ln) _DKL_REG_LN(tc_port, ln, \
+ _DKL_TX_DW17_LN0, \
+ _DKL_TX_DW17_LN1)
+
+#define _DKL_TX_DW18_LN0 0x0DC8
+#define _DKL_TX_DW18_LN1 0x1DC8
+#define DKL_TX_DW18(tc_port, ln) _DKL_REG_LN(tc_port, ln, \
+ _DKL_TX_DW18_LN0, \
+ _DKL_TX_DW18_LN1)
+
+#define _DKL_DP_MODE_LN0 0x00A0
+#define _DKL_DP_MODE_LN1 0x10A0
+#define DKL_DP_MODE(tc_port, ln) _DKL_REG_LN(tc_port, ln, \
+ _DKL_DP_MODE_LN0, \
+ _DKL_DP_MODE_LN1)
+
+#define _DKL_CMN_UC_DW27 0x236C
+#define DKL_CMN_UC_DW_27(tc_port) _DKL_REG(tc_port, \
+ _DKL_CMN_UC_DW27)
+#define DKL_CMN_UC_DW27_UC_HEALTH (0x1 << 15)
+
+/*
+ * Each Dekel PHY is addressed through a 4KB aperture. Each PHY has more than
+ * 4KB of register space, so a separate index is programmed in HIP_INDEX_REG0
+ * or HIP_INDEX_REG1, based on the port number, to set the upper 2 address
+ * bits that point the 4KB window into the full PHY register space.
+ */
+#define _HIP_INDEX_REG0 0x1010A0
+#define _HIP_INDEX_REG1 0x1010A4
+#define HIP_INDEX_REG(tc_port) _MMIO((tc_port) < 4 ? _HIP_INDEX_REG0 \
+ : _HIP_INDEX_REG1)
+#define _HIP_INDEX_SHIFT(tc_port) (8 * ((tc_port) % 4))
+#define HIP_INDEX_VAL(tc_port, val) ((val) << _HIP_INDEX_SHIFT(tc_port))
+
+#endif /* __INTEL_DKL_PHY_REGS__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c
index e52ecc0738a6..eff3add70611 100644
--- a/drivers/gpu/drm/i915/display/intel_dmc.c
+++ b/drivers/gpu/drm/i915/display/intel_dmc.c
@@ -52,8 +52,8 @@
#define DISPLAY_VER12_DMC_MAX_FW_SIZE ICL_DMC_MAX_FW_SIZE
-#define DG2_DMC_PATH DMC_PATH(dg2, 2, 07)
-#define DG2_DMC_VERSION_REQUIRED DMC_VERSION(2, 07)
+#define DG2_DMC_PATH DMC_PATH(dg2, 2, 08)
+#define DG2_DMC_VERSION_REQUIRED DMC_VERSION(2, 8)
MODULE_FIRMWARE(DG2_DMC_PATH);
#define ADLP_DMC_PATH DMC_PATH(adlp, 2, 16)
@@ -1065,12 +1065,13 @@ static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused)
seq_printf(m, "fw loaded: %s\n",
str_yes_no(intel_dmc_has_payload(i915)));
seq_printf(m, "path: %s\n", dmc->fw_path);
- seq_printf(m, "Pipe A fw support: %s\n",
+ seq_printf(m, "Pipe A fw needed: %s\n",
str_yes_no(GRAPHICS_VER(i915) >= 12));
seq_printf(m, "Pipe A fw loaded: %s\n",
str_yes_no(dmc->dmc_info[DMC_FW_PIPEA].payload));
- seq_printf(m, "Pipe B fw support: %s\n",
- str_yes_no(IS_ALDERLAKE_P(i915)));
+ seq_printf(m, "Pipe B fw needed: %s\n",
+ str_yes_no(IS_ALDERLAKE_P(i915) ||
+ DISPLAY_VER(i915) >= 14));
seq_printf(m, "Pipe B fw loaded: %s\n",
str_yes_no(dmc->dmc_info[DMC_FW_PIPEB].payload));
@@ -1081,22 +1082,19 @@ static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused)
DMC_VERSION_MINOR(dmc->version));
if (DISPLAY_VER(i915) >= 12) {
- if (IS_DGFX(i915)) {
+ i915_reg_t dc3co_reg;
+
+ if (IS_DGFX(i915) || DISPLAY_VER(i915) >= 14) {
+ dc3co_reg = DG1_DMC_DEBUG3;
dc5_reg = DG1_DMC_DEBUG_DC5_COUNT;
} else {
+ dc3co_reg = TGL_DMC_DEBUG3;
dc5_reg = TGL_DMC_DEBUG_DC5_COUNT;
dc6_reg = TGL_DMC_DEBUG_DC6_COUNT;
}
- /*
- * NOTE: DMC_DEBUG3 is a general purpose reg.
- * According to B.Specs:49196 DMC f/w reuses DC5/6 counter
- * reg for DC3CO debugging and validation,
- * but TGL DMC f/w is using DMC_DEBUG3 reg for DC3CO counter.
- */
seq_printf(m, "DC3CO count: %d\n",
- intel_de_read(i915, IS_DGFX(i915) ?
- DG1_DMC_DEBUG3 : TGL_DMC_DEBUG3));
+ intel_de_read(i915, dc3co_reg));
} else {
dc5_reg = IS_BROXTON(i915) ? BXT_DMC_DC3_DC5_COUNT :
SKL_DMC_DC3_DC5_COUNT;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 2b5bc95a8b0d..67089711d9e2 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -46,6 +46,7 @@
#include "g4x_dp.h"
#include "i915_debugfs.h"
#include "i915_drv.h"
+#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_audio.h"
#include "intel_backlight.h"
@@ -2306,6 +2307,7 @@ bool intel_dp_initial_fastset_check(struct intel_encoder *encoder,
{
struct drm_i915_private *i915 = to_i915(encoder->base.dev);
struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+ bool fastset = true;
/*
* If BIOS has set an unsupported or non-standard link rate for some
@@ -2313,9 +2315,10 @@ bool intel_dp_initial_fastset_check(struct intel_encoder *encoder,
*/
if (intel_dp_rate_index(intel_dp->source_rates, intel_dp->num_source_rates,
crtc_state->port_clock) < 0) {
- drm_dbg_kms(&i915->drm, "Forcing full modeset due to unsupported link rate\n");
+ drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] Forcing full modeset due to unsupported link rate\n",
+ encoder->base.base.id, encoder->base.name);
crtc_state->uapi.connectors_changed = true;
- return false;
+ fastset = false;
}
/*
@@ -2326,18 +2329,20 @@ bool intel_dp_initial_fastset_check(struct intel_encoder *encoder,
* Remove once we have readout for DSC.
*/
if (crtc_state->dsc.compression_enable) {
- drm_dbg_kms(&i915->drm, "Forcing full modeset due to DSC being enabled\n");
+ drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] Forcing full modeset due to DSC being enabled\n",
+ encoder->base.base.id, encoder->base.name);
crtc_state->uapi.mode_changed = true;
- return false;
+ fastset = false;
}
if (CAN_PSR(intel_dp)) {
- drm_dbg_kms(&i915->drm, "Forcing full modeset to compute PSR state\n");
+ drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] Forcing full modeset to compute PSR state\n",
+ encoder->base.base.id, encoder->base.name);
crtc_state->uapi.mode_changed = true;
- return false;
+ fastset = false;
}
- return true;
+ return fastset;
}
static void intel_dp_get_pcon_dsc_cap(struct intel_dp *intel_dp)
@@ -2686,7 +2691,6 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp,
str_enable_disable(tmp));
}
-
bool intel_dp_get_colorimetry_status(struct intel_dp *intel_dp)
{
u8 dprx = 0;
@@ -4873,6 +4877,12 @@ void intel_dp_encoder_flush_work(struct drm_encoder *encoder)
intel_pps_vdd_off_sync(intel_dp);
+ /*
+ * Ensure power off delay is respected on module remove, so that we can
+ * reduce delays at driver probe. See pps_init_timestamps().
+ */
+ intel_pps_wait_power_cycle(intel_dp);
+
intel_dp_aux_fini(intel_dp);
}
@@ -5174,19 +5184,6 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
if (has_gamut_metadata_dip(dev_priv, port))
drm_connector_attach_hdr_output_metadata_property(connector);
- if (intel_dp_is_edp(intel_dp)) {
- u32 allowed_scalers;
-
- allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT) | BIT(DRM_MODE_SCALE_FULLSCREEN);
- if (!HAS_GMCH(dev_priv))
- allowed_scalers |= BIT(DRM_MODE_SCALE_CENTER);
-
- drm_connector_attach_scaling_mode_property(connector, allowed_scalers);
-
- connector->state->scaling_mode = DRM_MODE_SCALE_ASPECT;
-
- }
-
if (HAS_VRR(dev_priv))
drm_connector_attach_vrr_capable_property(connector);
}
@@ -5199,8 +5196,7 @@ intel_edp_add_properties(struct intel_dp *intel_dp)
const struct drm_display_mode *fixed_mode =
intel_panel_preferred_fixed_mode(connector);
- if (!fixed_mode)
- return;
+ intel_attach_scaling_mode_property(&connector->base);
drm_connector_set_panel_orientation_with_quirk(&connector->base,
i915->display.vbt.orientation,
@@ -5208,16 +5204,43 @@ intel_edp_add_properties(struct intel_dp *intel_dp)
fixed_mode->vdisplay);
}
+static void intel_edp_backlight_setup(struct intel_dp *intel_dp,
+ struct intel_connector *connector)
+{
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+ enum pipe pipe = INVALID_PIPE;
+
+ if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
+ /*
+ * Figure out the current pipe for the initial backlight setup.
+ * If the current pipe isn't valid, try the PPS pipe, and if that
+ * fails just assume pipe A.
+ */
+ pipe = vlv_active_pipe(intel_dp);
+
+ if (pipe != PIPE_A && pipe != PIPE_B)
+ pipe = intel_dp->pps.pps_pipe;
+
+ if (pipe != PIPE_A && pipe != PIPE_B)
+ pipe = PIPE_A;
+
+ drm_dbg_kms(&i915->drm,
+ "[CONNECTOR:%d:%s] using pipe %c for initial backlight setup\n",
+ connector->base.base.id, connector->base.name,
+ pipe_name(pipe));
+ }
+
+ intel_backlight_setup(connector, pipe);
+}
+
static bool intel_edp_init_connector(struct intel_dp *intel_dp,
struct intel_connector *intel_connector)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
- struct drm_device *dev = &dev_priv->drm;
struct drm_connector *connector = &intel_connector->base;
struct drm_display_mode *fixed_mode;
struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base;
bool has_dpcd;
- enum pipe pipe = INVALID_PIPE;
struct edid *edid;
if (!intel_dp_is_edp(intel_dp))
@@ -5230,7 +5253,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
* with an already powered-on LVDS power sequencer.
*/
if (intel_get_lvds_encoder(dev_priv)) {
- drm_WARN_ON(dev,
+ drm_WARN_ON(&dev_priv->drm,
!(HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)));
drm_info(&dev_priv->drm,
"LVDS was detected, not registering eDP\n");
@@ -5246,11 +5269,12 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
if (!has_dpcd) {
/* if this fails, presume the device is a ghost */
drm_info(&dev_priv->drm,
- "failed to retrieve link info, disabling eDP\n");
+ "[ENCODER:%d:%s] failed to retrieve link info, disabling eDP\n",
+ encoder->base.base.id, encoder->base.name);
goto out_vdd_off;
}
- mutex_lock(&dev->mode_config.mutex);
+ mutex_lock(&dev_priv->drm.mode_config.mutex);
edid = drm_get_edid(connector, &intel_dp->aux.ddc);
if (!edid) {
/* Fallback to EDID from ACPI OpRegion, if any */
@@ -5275,9 +5299,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
intel_bios_init_panel(dev_priv, &intel_connector->panel,
encoder->devdata, IS_ERR(edid) ? NULL : edid);
- intel_panel_add_edid_fixed_modes(intel_connector,
- intel_connector->panel.vbt.drrs_type != DRRS_TYPE_NONE ||
- intel_vrr_is_capable(intel_connector));
+ intel_panel_add_edid_fixed_modes(intel_connector, true);
/* MSO requires information from the EDID */
intel_edp_mso_init(intel_dp);
@@ -5290,30 +5312,18 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
if (!intel_panel_preferred_fixed_mode(intel_connector))
intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
- mutex_unlock(&dev->mode_config.mutex);
+ mutex_unlock(&dev_priv->drm.mode_config.mutex);
- if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
- /*
- * Figure out the current pipe for the initial backlight setup.
- * If the current pipe isn't valid, try the PPS pipe, and if that
- * fails just assume pipe A.
- */
- pipe = vlv_active_pipe(intel_dp);
-
- if (pipe != PIPE_A && pipe != PIPE_B)
- pipe = intel_dp->pps.pps_pipe;
-
- if (pipe != PIPE_A && pipe != PIPE_B)
- pipe = PIPE_A;
-
- drm_dbg_kms(&dev_priv->drm,
- "using pipe %c for initial backlight setup\n",
- pipe_name(pipe));
+ if (!intel_panel_preferred_fixed_mode(intel_connector)) {
+ drm_info(&dev_priv->drm,
+ "[ENCODER:%d:%s] failed to find fixed mode for the panel, disabling eDP\n",
+ encoder->base.base.id, encoder->base.name);
+ goto out_vdd_off;
}
intel_panel_init(intel_connector);
- intel_backlight_setup(intel_connector, pipe);
+ intel_edp_backlight_setup(intel_dp, intel_connector);
intel_edp_add_properties(intel_dp);
@@ -5415,7 +5425,6 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
if (!HAS_GMCH(dev_priv))
connector->interlace_allowed = true;
- connector->doublescan_allowed = 0;
intel_connector->polled = DRM_CONNECTOR_POLL_HPD;
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c
index 48c375c65a41..664bebdecea7 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_aux.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c
@@ -4,6 +4,7 @@
*/
#include "i915_drv.h"
+#include "i915_reg.h"
#include "i915_trace.h"
#include "intel_display_types.h"
#include "intel_dp_aux.h"
diff --git a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
index 88689124c013..e0c177161407 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_hdcp.c
@@ -11,6 +11,7 @@
#include <drm/display/drm_hdcp_helper.h>
#include <drm/drm_print.h>
+#include "i915_reg.h"
#include "intel_ddi.h"
#include "intel_de.h"
#include "intel_display_types.h"
@@ -19,28 +20,20 @@
#include "intel_hdcp.h"
#include "intel_hdcp_regs.h"
-static unsigned int transcoder_to_stream_enc_status(enum transcoder cpu_transcoder)
+static u32 transcoder_to_stream_enc_status(enum transcoder cpu_transcoder)
{
- u32 stream_enc_mask;
-
switch (cpu_transcoder) {
case TRANSCODER_A:
- stream_enc_mask = HDCP_STATUS_STREAM_A_ENC;
- break;
+ return HDCP_STATUS_STREAM_A_ENC;
case TRANSCODER_B:
- stream_enc_mask = HDCP_STATUS_STREAM_B_ENC;
- break;
+ return HDCP_STATUS_STREAM_B_ENC;
case TRANSCODER_C:
- stream_enc_mask = HDCP_STATUS_STREAM_C_ENC;
- break;
+ return HDCP_STATUS_STREAM_C_ENC;
case TRANSCODER_D:
- stream_enc_mask = HDCP_STATUS_STREAM_D_ENC;
- break;
+ return HDCP_STATUS_STREAM_D_ENC;
default:
- stream_enc_mask = 0;
+ return 0;
}
-
- return stream_enc_mask;
}
static void intel_dp_hdcp_wait_for_cp_irq(struct intel_hdcp *hdcp, int timeout)
diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c
index 03604a37931c..4077a979a924 100644
--- a/drivers/gpu/drm/i915/display/intel_dp_mst.c
+++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c
@@ -29,6 +29,7 @@
#include <drm/drm_probe_helper.h>
#include "i915_drv.h"
+#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_audio.h"
#include "intel_connector.h"
@@ -793,7 +794,35 @@ static bool intel_dp_mst_get_hw_state(struct intel_connector *connector)
return false;
}
-static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, const char *pathprop)
+static int intel_dp_mst_add_properties(struct intel_dp *intel_dp,
+ struct drm_connector *connector,
+ const char *pathprop)
+{
+ struct drm_i915_private *i915 = to_i915(connector->dev);
+
+ drm_object_attach_property(&connector->base,
+ i915->drm.mode_config.path_property, 0);
+ drm_object_attach_property(&connector->base,
+ i915->drm.mode_config.tile_property, 0);
+
+ intel_attach_force_audio_property(connector);
+ intel_attach_broadcast_rgb_property(connector);
+
+ /*
+ * Reuse the prop from the SST connector because we're
+ * not allowed to create new props after device registration.
+ */
+ connector->max_bpc_property =
+ intel_dp->attached_connector->base.max_bpc_property;
+ if (connector->max_bpc_property)
+ drm_connector_attach_max_bpc_property(connector, 6, 12);
+
+ return drm_connector_set_path_property(connector, pathprop);
+}
+
+static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
+ struct drm_dp_mst_port *port,
+ const char *pathprop)
{
struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr);
struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
@@ -833,28 +862,14 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo
goto err;
}
- drm_object_attach_property(&connector->base, dev->mode_config.path_property, 0);
- drm_object_attach_property(&connector->base, dev->mode_config.tile_property, 0);
-
- ret = drm_connector_set_path_property(connector, pathprop);
+ ret = intel_dp_mst_add_properties(intel_dp, connector, pathprop);
if (ret)
goto err;
- intel_attach_force_audio_property(connector);
- intel_attach_broadcast_rgb_property(connector);
-
ret = intel_dp_hdcp_init(dig_port, intel_connector);
if (ret)
drm_dbg_kms(&dev_priv->drm, "[%s:%d] HDCP MST init failed, skipping.\n",
connector->name, connector->base.id);
- /*
- * Reuse the prop from the SST connector because we're
- * not allowed to create new props after device registration.
- */
- connector->max_bpc_property =
- intel_dp->attached_connector->base.max_bpc_property;
- if (connector->max_bpc_property)
- drm_connector_attach_max_bpc_property(connector, 6, 12);
return connector;
diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.c b/drivers/gpu/drm/i915/display/intel_dpio_phy.c
index 8732b8722ed7..7eb7440b3180 100644
--- a/drivers/gpu/drm/i915/display/intel_dpio_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.c
@@ -21,6 +21,7 @@
* DEALINGS IN THE SOFTWARE.
*/
+#include "i915_reg.h"
#include "intel_ddi.h"
#include "intel_ddi_buf_trans.h"
#include "intel_de.h"
@@ -655,6 +656,48 @@ bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder)
return mask;
}
+enum dpio_channel vlv_dig_port_to_channel(struct intel_digital_port *dig_port)
+{
+ switch (dig_port->base.port) {
+ default:
+ MISSING_CASE(dig_port->base.port);
+ fallthrough;
+ case PORT_B:
+ case PORT_D:
+ return DPIO_CH0;
+ case PORT_C:
+ return DPIO_CH1;
+ }
+}
+
+enum dpio_phy vlv_dig_port_to_phy(struct intel_digital_port *dig_port)
+{
+ switch (dig_port->base.port) {
+ default:
+ MISSING_CASE(dig_port->base.port);
+ fallthrough;
+ case PORT_B:
+ case PORT_C:
+ return DPIO_PHY0;
+ case PORT_D:
+ return DPIO_PHY1;
+ }
+}
+
+enum dpio_channel vlv_pipe_to_channel(enum pipe pipe)
+{
+ switch (pipe) {
+ default:
+ MISSING_CASE(pipe);
+ fallthrough;
+ case PIPE_A:
+ case PIPE_C:
+ return DPIO_CH0;
+ case PIPE_B:
+ return DPIO_CH1;
+ }
+}
+
void chv_set_phy_signal_level(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
u32 deemph_reg_value, u32 margin_reg_value,
diff --git a/drivers/gpu/drm/i915/display/intel_dpio_phy.h b/drivers/gpu/drm/i915/display/intel_dpio_phy.h
index 9c3d008e8e1a..9c7725dacb47 100644
--- a/drivers/gpu/drm/i915/display/intel_dpio_phy.h
+++ b/drivers/gpu/drm/i915/display/intel_dpio_phy.h
@@ -8,13 +8,24 @@
#include <linux/types.h>
-enum dpio_channel;
-enum dpio_phy;
+enum pipe;
enum port;
struct drm_i915_private;
struct intel_crtc_state;
+struct intel_digital_port;
struct intel_encoder;
+enum dpio_channel {
+ DPIO_CH0,
+ DPIO_CH1,
+};
+
+enum dpio_phy {
+ DPIO_PHY0,
+ DPIO_PHY1,
+ DPIO_PHY2,
+};
+
void bxt_port_to_phy_channel(struct drm_i915_private *dev_priv, enum port port,
enum dpio_phy *phy, enum dpio_channel *ch);
void bxt_ddi_phy_set_signal_levels(struct intel_encoder *encoder,
@@ -30,6 +41,10 @@ void bxt_ddi_phy_set_lane_optim_mask(struct intel_encoder *encoder,
u8 lane_lat_optim_mask);
u8 bxt_ddi_phy_get_lane_lat_optim_mask(struct intel_encoder *encoder);
+enum dpio_channel vlv_dig_port_to_channel(struct intel_digital_port *dig_port);
+enum dpio_phy vlv_dig_port_to_phy(struct intel_digital_port *dig_port);
+enum dpio_channel vlv_pipe_to_channel(enum pipe pipe);
+
void chv_set_phy_signal_level(struct intel_encoder *encoder,
const struct intel_crtc_state *crtc_state,
u32 deemph_reg_value, u32 margin_reg_value,
diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c
index b15ba78d64d6..c236aafe9be0 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll.c
@@ -6,10 +6,12 @@
#include <linux/kernel.h>
#include <linux/string_helpers.h>
+#include "i915_reg.h"
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display.h"
#include "intel_display_types.h"
+#include "intel_dpio_phy.h"
#include "intel_dpll.h"
#include "intel_lvds.h"
#include "intel_panel.h"
diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
index 64dd603dc69a..1974eb580ed1 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
+++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c
@@ -23,15 +23,18 @@
#include <linux/string_helpers.h>
+#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dkl_phy.h"
+#include "intel_dkl_phy_regs.h"
#include "intel_dpio_phy.h"
#include "intel_dpll.h"
#include "intel_dpll_mgr.h"
+#include "intel_hti.h"
+#include "intel_mg_phy_regs.h"
#include "intel_pch_refclk.h"
#include "intel_tc.h"
-#include "intel_tc_phy_regs.h"
/**
* DOC: Display PLLs
@@ -153,28 +156,6 @@ intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv,
return &dev_priv->display.dpll.shared_dplls[id];
}
-/**
- * intel_get_shared_dpll_id - get the id of a DPLL
- * @dev_priv: i915 device instance
- * @pll: the DPLL
- *
- * Returns:
- * The id of @pll
- */
-enum intel_dpll_id
-intel_get_shared_dpll_id(struct drm_i915_private *dev_priv,
- struct intel_shared_dpll *pll)
-{
- long pll_idx = pll - dev_priv->display.dpll.shared_dplls;
-
- if (drm_WARN_ON(&dev_priv->drm,
- pll_idx < 0 ||
- pll_idx >= dev_priv->display.dpll.num_shared_dpll))
- return -1;
-
- return pll_idx;
-}
-
/* For ILK+ */
void assert_shared_dpll(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll,
@@ -385,20 +366,30 @@ intel_reference_shared_dpll(struct intel_atomic_state *state,
if (shared_dpll[id].pipe_mask == 0)
shared_dpll[id].hw_state = *pll_state;
- drm_dbg(&i915->drm, "using %s for pipe %c\n", pll->info->name,
- pipe_name(crtc->pipe));
+ 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] reserving %s\n",
+ crtc->base.base.id, crtc->base.name, pll->info->name);
}
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);
- shared_dpll[pll->info->id].pipe_mask &= ~BIT(crtc->pipe);
+
+ 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);
}
static void intel_put_dpll(struct intel_atomic_state *state,
@@ -709,8 +700,6 @@ struct hsw_wrpll_rnp {
static unsigned hsw_wrpll_get_budget_for_freq(int clock)
{
- unsigned budget;
-
switch (clock) {
case 25175000:
case 25200000:
@@ -743,21 +732,18 @@ static unsigned hsw_wrpll_get_budget_for_freq(int clock)
case 222750000:
case 296703000:
case 297000000:
- budget = 0;
- break;
+ return 0;
case 233500000:
case 245250000:
case 247750000:
case 253250000:
case 298000000:
- budget = 1500;
- break;
+ return 1500;
case 169128000:
case 169500000:
case 179500000:
case 202000000:
- budget = 2000;
- break;
+ return 2000;
case 256250000:
case 262500000:
case 270000000:
@@ -767,18 +753,13 @@ static unsigned hsw_wrpll_get_budget_for_freq(int clock)
case 281250000:
case 286000000:
case 291750000:
- budget = 4000;
- break;
+ return 4000;
case 267250000:
case 268500000:
- budget = 5000;
- break;
+ return 5000;
default:
- budget = 1000;
- break;
+ return 1000;
}
-
- return budget;
}
static void hsw_wrpll_update_rnp(u64 freq2k, unsigned int budget,
@@ -3184,14 +3165,6 @@ static void icl_update_active_dpll(struct intel_atomic_state *state,
icl_set_active_port_dpll(crtc_state, port_dpll_id);
}
-static u32 intel_get_hti_plls(struct drm_i915_private *i915)
-{
- if (!(i915->hti_state & HDPORT_ENABLED))
- return 0;
-
- return REG_FIELD_GET(HDPORT_DPLL_USED_MASK, i915->hti_state);
-}
-
static int icl_compute_combo_phy_dpll(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
@@ -3266,7 +3239,7 @@ static int icl_get_combo_phy_dpll(struct intel_atomic_state *state,
}
/* Eliminate DPLLs from consideration if reserved by HTI */
- dpll_mask &= ~intel_get_hti_plls(dev_priv);
+ dpll_mask &= ~intel_hti_dpll_mask(dev_priv);
port_dpll->pll = intel_find_shared_dpll(state, crtc,
&port_dpll->hw_state,
@@ -3510,11 +3483,11 @@ static bool dkl_pll_get_hw_state(struct drm_i915_private *dev_priv,
* they are on different building blocks
*/
hw_state->mg_refclkin_ctl = intel_dkl_phy_read(dev_priv,
- DKL_REFCLKIN_CTL(tc_port), 2);
+ DKL_REFCLKIN_CTL(tc_port));
hw_state->mg_refclkin_ctl &= MG_REFCLKIN_CTL_OD_2_MUX_MASK;
hw_state->mg_clktop2_hsclkctl =
- intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port), 2);
+ intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port));
hw_state->mg_clktop2_hsclkctl &=
MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK |
MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK |
@@ -3522,32 +3495,32 @@ static bool dkl_pll_get_hw_state(struct drm_i915_private *dev_priv,
MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK;
hw_state->mg_clktop2_coreclkctl1 =
- intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port), 2);
+ intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port));
hw_state->mg_clktop2_coreclkctl1 &=
MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK;
- hw_state->mg_pll_div0 = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV0(tc_port), 2);
+ hw_state->mg_pll_div0 = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV0(tc_port));
val = DKL_PLL_DIV0_MASK;
if (dev_priv->display.vbt.override_afc_startup)
val |= DKL_PLL_DIV0_AFC_STARTUP_MASK;
hw_state->mg_pll_div0 &= val;
- hw_state->mg_pll_div1 = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV1(tc_port), 2);
+ hw_state->mg_pll_div1 = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV1(tc_port));
hw_state->mg_pll_div1 &= (DKL_PLL_DIV1_IREF_TRIM_MASK |
DKL_PLL_DIV1_TDC_TARGET_CNT_MASK);
- hw_state->mg_pll_ssc = intel_dkl_phy_read(dev_priv, DKL_PLL_SSC(tc_port), 2);
+ hw_state->mg_pll_ssc = intel_dkl_phy_read(dev_priv, DKL_PLL_SSC(tc_port));
hw_state->mg_pll_ssc &= (DKL_PLL_SSC_IREF_NDIV_RATIO_MASK |
DKL_PLL_SSC_STEP_LEN_MASK |
DKL_PLL_SSC_STEP_NUM_MASK |
DKL_PLL_SSC_EN);
- hw_state->mg_pll_bias = intel_dkl_phy_read(dev_priv, DKL_PLL_BIAS(tc_port), 2);
+ hw_state->mg_pll_bias = intel_dkl_phy_read(dev_priv, DKL_PLL_BIAS(tc_port));
hw_state->mg_pll_bias &= (DKL_PLL_BIAS_FRAC_EN_H |
DKL_PLL_BIAS_FBDIV_FRAC_MASK);
hw_state->mg_pll_tdc_coldst_bias =
- intel_dkl_phy_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port), 2);
+ intel_dkl_phy_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port));
hw_state->mg_pll_tdc_coldst_bias &= (DKL_PLL_TDC_SSC_STEP_SIZE_MASK |
DKL_PLL_TDC_FEED_FWD_GAIN_MASK);
@@ -3736,57 +3709,57 @@ static void dkl_pll_write(struct drm_i915_private *dev_priv,
* though on different building block
*/
/* All the registers are RMW */
- val = intel_dkl_phy_read(dev_priv, DKL_REFCLKIN_CTL(tc_port), 2);
+ val = intel_dkl_phy_read(dev_priv, DKL_REFCLKIN_CTL(tc_port));
val &= ~MG_REFCLKIN_CTL_OD_2_MUX_MASK;
val |= hw_state->mg_refclkin_ctl;
- intel_dkl_phy_write(dev_priv, DKL_REFCLKIN_CTL(tc_port), 2, val);
+ intel_dkl_phy_write(dev_priv, DKL_REFCLKIN_CTL(tc_port), val);
- val = intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port), 2);
+ val = intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port));
val &= ~MG_CLKTOP2_CORECLKCTL1_A_DIVRATIO_MASK;
val |= hw_state->mg_clktop2_coreclkctl1;
- intel_dkl_phy_write(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port), 2, val);
+ intel_dkl_phy_write(dev_priv, DKL_CLKTOP2_CORECLKCTL1(tc_port), val);
- val = intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port), 2);
+ val = intel_dkl_phy_read(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port));
val &= ~(MG_CLKTOP2_HSCLKCTL_TLINEDRV_CLKSEL_MASK |
MG_CLKTOP2_HSCLKCTL_CORE_INPUTSEL_MASK |
MG_CLKTOP2_HSCLKCTL_HSDIV_RATIO_MASK |
MG_CLKTOP2_HSCLKCTL_DSDIV_RATIO_MASK);
val |= hw_state->mg_clktop2_hsclkctl;
- intel_dkl_phy_write(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port), 2, val);
+ intel_dkl_phy_write(dev_priv, DKL_CLKTOP2_HSCLKCTL(tc_port), val);
val = DKL_PLL_DIV0_MASK;
if (dev_priv->display.vbt.override_afc_startup)
val |= DKL_PLL_DIV0_AFC_STARTUP_MASK;
- intel_dkl_phy_rmw(dev_priv, DKL_PLL_DIV0(tc_port), 2, val,
+ intel_dkl_phy_rmw(dev_priv, DKL_PLL_DIV0(tc_port), val,
hw_state->mg_pll_div0);
- val = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV1(tc_port), 2);
+ val = intel_dkl_phy_read(dev_priv, DKL_PLL_DIV1(tc_port));
val &= ~(DKL_PLL_DIV1_IREF_TRIM_MASK |
DKL_PLL_DIV1_TDC_TARGET_CNT_MASK);
val |= hw_state->mg_pll_div1;
- intel_dkl_phy_write(dev_priv, DKL_PLL_DIV1(tc_port), 2, val);
+ intel_dkl_phy_write(dev_priv, DKL_PLL_DIV1(tc_port), val);
- val = intel_dkl_phy_read(dev_priv, DKL_PLL_SSC(tc_port), 2);
+ val = intel_dkl_phy_read(dev_priv, DKL_PLL_SSC(tc_port));
val &= ~(DKL_PLL_SSC_IREF_NDIV_RATIO_MASK |
DKL_PLL_SSC_STEP_LEN_MASK |
DKL_PLL_SSC_STEP_NUM_MASK |
DKL_PLL_SSC_EN);
val |= hw_state->mg_pll_ssc;
- intel_dkl_phy_write(dev_priv, DKL_PLL_SSC(tc_port), 2, val);
+ intel_dkl_phy_write(dev_priv, DKL_PLL_SSC(tc_port), val);
- val = intel_dkl_phy_read(dev_priv, DKL_PLL_BIAS(tc_port), 2);
+ val = intel_dkl_phy_read(dev_priv, DKL_PLL_BIAS(tc_port));
val &= ~(DKL_PLL_BIAS_FRAC_EN_H |
DKL_PLL_BIAS_FBDIV_FRAC_MASK);
val |= hw_state->mg_pll_bias;
- intel_dkl_phy_write(dev_priv, DKL_PLL_BIAS(tc_port), 2, val);
+ intel_dkl_phy_write(dev_priv, DKL_PLL_BIAS(tc_port), val);
- val = intel_dkl_phy_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port), 2);
+ val = intel_dkl_phy_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port));
val &= ~(DKL_PLL_TDC_SSC_STEP_SIZE_MASK |
DKL_PLL_TDC_FEED_FWD_GAIN_MASK);
val |= hw_state->mg_pll_tdc_coldst_bias;
- intel_dkl_phy_write(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port), 2, val);
+ intel_dkl_phy_write(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port), val);
- intel_dkl_phy_posting_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port), 2);
+ intel_dkl_phy_posting_read(dev_priv, DKL_PLL_TDC_COLDST_BIAS(tc_port));
}
static void icl_pll_power_enable(struct drm_i915_private *dev_priv,
@@ -4188,6 +4161,8 @@ void intel_shared_dpll_init(struct drm_i915_private *dev_priv)
const struct dpll_info *dpll_info;
int i;
+ mutex_init(&dev_priv->display.dpll.lock);
+
if (IS_DG2(dev_priv))
/* No shared DPLLs on DG2; port PLLs are part of the PHY */
dpll_mgr = NULL;
@@ -4232,7 +4207,6 @@ void intel_shared_dpll_init(struct drm_i915_private *dev_priv)
dev_priv->display.dpll.mgr = dpll_mgr;
dev_priv->display.dpll.num_shared_dpll = i;
- mutex_init(&dev_priv->display.dpll.lock);
}
/**
diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
index 3247dc300ae4..3854f1b4299a 100644
--- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
+++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.h
@@ -328,9 +328,6 @@ struct intel_shared_dpll {
struct intel_shared_dpll *
intel_get_shared_dpll_by_id(struct drm_i915_private *dev_priv,
enum intel_dpll_id id);
-enum intel_dpll_id
-intel_get_shared_dpll_id(struct drm_i915_private *dev_priv,
- struct intel_shared_dpll *pll);
void assert_shared_dpll(struct drm_i915_private *dev_priv,
struct intel_shared_dpll *pll,
bool state);
diff --git a/drivers/gpu/drm/i915/display/intel_dpt.c b/drivers/gpu/drm/i915/display/intel_dpt.c
index ac587647e1f5..ad1a37b515fb 100644
--- a/drivers/gpu/drm/i915/display/intel_dpt.c
+++ b/drivers/gpu/drm/i915/display/intel_dpt.c
@@ -5,6 +5,7 @@
#include "gem/i915_gem_domain.h"
#include "gem/i915_gem_internal.h"
+#include "gem/i915_gem_lmem.h"
#include "gt/gen8_ppgtt.h"
#include "i915_drv.h"
diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c
index 7da4a9cbe4ba..5b9e44443814 100644
--- a/drivers/gpu/drm/i915/display/intel_drrs.c
+++ b/drivers/gpu/drm/i915/display/intel_drrs.c
@@ -4,6 +4,7 @@
*/
#include "i915_drv.h"
+#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_de.h"
#include "intel_display_types.h"
@@ -284,16 +285,124 @@ void intel_drrs_flush(struct drm_i915_private *dev_priv,
}
/**
- * intel_crtc_drrs_init - Init DRRS for CRTC
+ * intel_drrs_crtc_init - Init DRRS for CRTC
* @crtc: crtc
*
* This function is called only once at driver load to initialize basic
* DRRS stuff.
*
*/
-void intel_crtc_drrs_init(struct intel_crtc *crtc)
+void intel_drrs_crtc_init(struct intel_crtc *crtc)
{
INIT_DELAYED_WORK(&crtc->drrs.work, intel_drrs_downclock_work);
mutex_init(&crtc->drrs.mutex);
crtc->drrs.cpu_transcoder = INVALID_TRANSCODER;
}
+
+static int intel_drrs_debugfs_status_show(struct seq_file *m, void *unused)
+{
+ struct intel_crtc *crtc = m->private;
+ const struct intel_crtc_state *crtc_state;
+ int ret;
+
+ ret = drm_modeset_lock_single_interruptible(&crtc->base.mutex);
+ if (ret)
+ return ret;
+
+ crtc_state = to_intel_crtc_state(crtc->base.state);
+
+ mutex_lock(&crtc->drrs.mutex);
+
+ seq_printf(m, "DRRS enabled: %s\n",
+ str_yes_no(crtc_state->has_drrs));
+
+ seq_printf(m, "DRRS active: %s\n",
+ str_yes_no(intel_drrs_is_active(crtc)));
+
+ seq_printf(m, "DRRS refresh rate: %s\n",
+ crtc->drrs.refresh_rate == DRRS_REFRESH_RATE_LOW ?
+ "low" : "high");
+
+ seq_printf(m, "DRRS busy frontbuffer bits: 0x%x\n",
+ crtc->drrs.busy_frontbuffer_bits);
+
+ mutex_unlock(&crtc->drrs.mutex);
+
+ drm_modeset_unlock(&crtc->base.mutex);
+
+ return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(intel_drrs_debugfs_status);
+
+static int intel_drrs_debugfs_ctl_set(void *data, u64 val)
+{
+ struct intel_crtc *crtc = data;
+ struct drm_i915_private *i915 = to_i915(crtc->base.dev);
+ struct intel_crtc_state *crtc_state;
+ struct drm_crtc_commit *commit;
+ int ret;
+
+ ret = drm_modeset_lock_single_interruptible(&crtc->base.mutex);
+ if (ret)
+ return ret;
+
+ crtc_state = to_intel_crtc_state(crtc->base.state);
+
+ if (!crtc_state->hw.active ||
+ !crtc_state->has_drrs)
+ goto out;
+
+ commit = crtc_state->uapi.commit;
+ if (commit) {
+ ret = wait_for_completion_interruptible(&commit->hw_done);
+ if (ret)
+ goto out;
+ }
+
+ drm_dbg(&i915->drm,
+ "Manually %sactivating DRRS\n", val ? "" : "de");
+
+ if (val)
+ intel_drrs_activate(crtc_state);
+ else
+ intel_drrs_deactivate(crtc_state);
+
+out:
+ drm_modeset_unlock(&crtc->base.mutex);
+
+ return ret;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(intel_drrs_debugfs_ctl_fops,
+ NULL, intel_drrs_debugfs_ctl_set, "%llu\n");
+
+void intel_drrs_crtc_debugfs_add(struct intel_crtc *crtc)
+{
+ debugfs_create_file("i915_drrs_status", 0444, crtc->base.debugfs_entry,
+ crtc, &intel_drrs_debugfs_status_fops);
+
+ debugfs_create_file("i915_drrs_ctl", 0644, crtc->base.debugfs_entry,
+ crtc, &intel_drrs_debugfs_ctl_fops);
+}
+
+static int intel_drrs_debugfs_type_show(struct seq_file *m, void *unused)
+{
+ struct intel_connector *connector = m->private;
+
+ seq_printf(m, "DRRS type: %s\n",
+ intel_drrs_type_str(intel_panel_drrs_type(connector)));
+
+ return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(intel_drrs_debugfs_type);
+
+void intel_drrs_connector_debugfs_add(struct intel_connector *connector)
+{
+ if (intel_panel_drrs_type(connector) == DRRS_TYPE_NONE)
+ return;
+
+ debugfs_create_file("i915_drrs_type", 0444, connector->base.debugfs_entry,
+ connector, &intel_drrs_debugfs_type_fops);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_drrs.h b/drivers/gpu/drm/i915/display/intel_drrs.h
index 3ad1be1ad9c1..8ef5f93a80ff 100644
--- a/drivers/gpu/drm/i915/display/intel_drrs.h
+++ b/drivers/gpu/drm/i915/display/intel_drrs.h
@@ -23,6 +23,8 @@ void intel_drrs_invalidate(struct drm_i915_private *dev_priv,
unsigned int frontbuffer_bits);
void intel_drrs_flush(struct drm_i915_private *dev_priv,
unsigned int frontbuffer_bits);
-void intel_crtc_drrs_init(struct intel_crtc *crtc);
+void intel_drrs_crtc_init(struct intel_crtc *crtc);
+void intel_drrs_crtc_debugfs_add(struct intel_crtc *crtc);
+void intel_drrs_connector_debugfs_add(struct intel_connector *connector);
#endif /* __INTEL_DRRS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c
index fc9c3e41c333..1e1c6107d51b 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -7,6 +7,7 @@
#include "gem/i915_gem_internal.h"
#include "i915_drv.h"
+#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dsb.h"
diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
index 75e8cc4337c9..fce69fa446d5 100644
--- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
+++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c
@@ -137,9 +137,9 @@ static enum port intel_dsi_seq_port_to_port(struct intel_dsi *intel_dsi,
return ffs(intel_dsi->ports) - 1;
if (seq_port) {
- if (intel_dsi->ports & PORT_B)
+ if (intel_dsi->ports & BIT(PORT_B))
return PORT_B;
- else if (intel_dsi->ports & PORT_C)
+ else if (intel_dsi->ports & BIT(PORT_C))
return PORT_C;
}
diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c
index 5572e43026e4..c86f9890754d 100644
--- a/drivers/gpu/drm/i915/display/intel_dvo.c
+++ b/drivers/gpu/drm/i915/display/intel_dvo.c
@@ -32,6 +32,7 @@
#include <drm/drm_crtc.h>
#include "i915_drv.h"
+#include "i915_reg.h"
#include "intel_connector.h"
#include "intel_de.h"
#include "intel_display_types.h"
@@ -491,8 +492,8 @@ void intel_dvo_init(struct drm_i915_private *dev_priv)
intel_encoder->pipe_mask = ~0;
if (dvo->type != INTEL_DVO_CHIP_LVDS)
- intel_encoder->cloneable = (1 << INTEL_OUTPUT_ANALOG) |
- (1 << INTEL_OUTPUT_DVO);
+ intel_encoder->cloneable = BIT(INTEL_OUTPUT_ANALOG) |
+ BIT(INTEL_OUTPUT_DVO);
switch (dvo->type) {
case INTEL_DVO_CHIP_TMDS:
@@ -515,8 +516,6 @@ void intel_dvo_init(struct drm_i915_private *dev_priv)
drm_connector_helper_add(connector,
&intel_dvo_connector_helper_funcs);
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
- connector->interlace_allowed = false;
- connector->doublescan_allowed = false;
intel_connector_attach_encoder(intel_connector, intel_encoder);
if (dvo->type == INTEL_DVO_CHIP_LVDS) {
diff --git a/drivers/gpu/drm/i915/display/intel_dvo_dev.h b/drivers/gpu/drm/i915/display/intel_dvo_dev.h
index 50205f064d93..ecff7b190856 100644
--- a/drivers/gpu/drm/i915/display/intel_dvo_dev.h
+++ b/drivers/gpu/drm/i915/display/intel_dvo_dev.h
@@ -23,12 +23,12 @@
#ifndef __INTEL_DVO_DEV_H__
#define __INTEL_DVO_DEV_H__
-#include <linux/i2c.h>
-
-#include <drm/drm_crtc.h>
-
#include "i915_reg_defs.h"
+enum drm_connector_status;
+struct drm_display_mode;
+struct i2c_adapter;
+
struct intel_dvo_device {
const char *name;
int type;
diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c
index eefa33c555ac..63137ae5ab21 100644
--- a/drivers/gpu/drm/i915/display/intel_fb.c
+++ b/drivers/gpu/drm/i915/display/intel_fb.c
@@ -301,6 +301,19 @@ static bool plane_caps_contain_all(u8 caps, u8 mask)
}
/**
+ * intel_fb_is_tiled_modifier: Check if a modifier is a tiled modifier type
+ * @modifier: Modifier to check
+ *
+ * Returns:
+ * Returns %true if @modifier is a tiled modifier.
+ */
+bool intel_fb_is_tiled_modifier(u64 modifier)
+{
+ return plane_caps_contain_any(lookup_modifier(modifier)->plane_caps,
+ INTEL_PLANE_CAP_TILING_MASK);
+}
+
+/**
* intel_fb_is_ccs_modifier: Check if a modifier is a CCS modifier type
* @modifier: Modifier to check
*
diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h
index 12386f13a4e0..4662b812b934 100644
--- a/drivers/gpu/drm/i915/display/intel_fb.h
+++ b/drivers/gpu/drm/i915/display/intel_fb.h
@@ -29,6 +29,7 @@ struct intel_plane_state;
#define INTEL_PLANE_CAP_TILING_Yf BIT(5)
#define INTEL_PLANE_CAP_TILING_4 BIT(6)
+bool intel_fb_is_tiled_modifier(u64 modifier);
bool intel_fb_is_ccs_modifier(u64 modifier);
bool intel_fb_is_rc_ccs_cc_modifier(u64 modifier);
bool intel_fb_is_mc_ccs_modifier(u64 modifier);
diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.c b/drivers/gpu/drm/i915/display/intel_fb_pin.c
index 1dddd6abd77b..6900acbb1381 100644
--- a/drivers/gpu/drm/i915/display/intel_fb_pin.c
+++ b/drivers/gpu/drm/i915/display/intel_fb_pin.c
@@ -167,7 +167,6 @@ retry:
ret = i915_gem_object_attach_phys(obj, alignment);
else if (!ret && HAS_LMEM(dev_priv))
ret = i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM_0);
- /* TODO: Do we need to sync when migration becomes async? */
if (!ret)
ret = i915_gem_object_pin_pages(obj);
if (ret)
diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c
index f38175304928..b5ee5ea0d010 100644
--- a/drivers/gpu/drm/i915/display/intel_fbc.c
+++ b/drivers/gpu/drm/i915/display/intel_fbc.c
@@ -670,6 +670,7 @@ static void intel_fbc_nuke(struct intel_fbc *fbc)
{
struct drm_i915_private *i915 = fbc->i915;
+ lockdep_assert_held(&fbc->lock);
drm_WARN_ON(&i915->drm, fbc->flip_pending);
trace_intel_fbc_nuke(fbc->state.plane);
@@ -679,6 +680,8 @@ static void intel_fbc_nuke(struct intel_fbc *fbc)
static void intel_fbc_activate(struct intel_fbc *fbc)
{
+ lockdep_assert_held(&fbc->lock);
+
intel_fbc_hw_activate(fbc);
intel_fbc_nuke(fbc);
@@ -687,9 +690,7 @@ static void intel_fbc_activate(struct intel_fbc *fbc)
static void intel_fbc_deactivate(struct intel_fbc *fbc, const char *reason)
{
- struct drm_i915_private *i915 = fbc->i915;
-
- drm_WARN_ON(&i915->drm, !mutex_is_locked(&fbc->lock));
+ lockdep_assert_held(&fbc->lock);
if (fbc->active)
intel_fbc_hw_deactivate(fbc);
@@ -1009,7 +1010,8 @@ static bool intel_fbc_is_fence_ok(const struct intel_plane_state *plane_state)
{
struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev);
- /* The use of a CPU fence is one of two ways to detect writes by the
+ /*
+ * The use of a CPU fence is one of two ways to detect writes by the
* CPU to the scanout and trigger updates to the FBC.
*
* The other method is by software tracking (see
@@ -1019,12 +1021,6 @@ static bool intel_fbc_is_fence_ok(const struct intel_plane_state *plane_state)
* Note that is possible for a tiled surface to be unmappable (and
* so have no fence associated with it) due to aperture constraints
* at the time of pinning.
- *
- * FIXME with 90/270 degree rotation we should use the fence on
- * the normal GTT view (the rotated view doesn't even have a
- * fence). Would need changes to the FBC fence Y offset as well.
- * For now this will effectively disable FBC with 90/270 degree
- * rotation.
*/
return DISPLAY_VER(i915) >= 9 ||
(plane_state->flags & PLANE_HAS_FENCE &&
@@ -1187,7 +1183,7 @@ static bool intel_fbc_can_flip_nuke(struct intel_atomic_state *state,
const struct drm_framebuffer *old_fb = old_plane_state->hw.fb;
const struct drm_framebuffer *new_fb = new_plane_state->hw.fb;
- if (drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi))
+ if (intel_crtc_needs_modeset(new_crtc_state))
return false;
if (!intel_fbc_is_ok(old_plane_state) ||
@@ -1227,6 +1223,8 @@ static bool __intel_fbc_pre_update(struct intel_atomic_state *state,
struct intel_fbc *fbc = plane->fbc;
bool need_vblank_wait = false;
+ lockdep_assert_held(&fbc->lock);
+
fbc->flip_pending = true;
if (intel_fbc_can_flip_nuke(state, crtc, plane))
@@ -1284,7 +1282,7 @@ static void __intel_fbc_disable(struct intel_fbc *fbc)
struct drm_i915_private *i915 = fbc->i915;
struct intel_plane *plane = fbc->state.plane;
- drm_WARN_ON(&i915->drm, !mutex_is_locked(&fbc->lock));
+ lockdep_assert_held(&fbc->lock);
drm_WARN_ON(&i915->drm, fbc->active);
drm_dbg_kms(&i915->drm, "Disabling FBC on [PLANE:%d:%s]\n",
@@ -1299,9 +1297,9 @@ static void __intel_fbc_disable(struct intel_fbc *fbc)
static void __intel_fbc_post_update(struct intel_fbc *fbc)
{
- struct drm_i915_private *i915 = fbc->i915;
+ lockdep_assert_held(&fbc->lock);
- drm_WARN_ON(&i915->drm, !mutex_is_locked(&fbc->lock));
+ fbc->flip_pending = false;
if (!fbc->busy_bits)
intel_fbc_activate(fbc);
@@ -1324,10 +1322,8 @@ void intel_fbc_post_update(struct intel_atomic_state *state,
mutex_lock(&fbc->lock);
- if (fbc->state.plane == plane) {
- fbc->flip_pending = false;
+ if (fbc->state.plane == plane)
__intel_fbc_post_update(fbc);
- }
mutex_unlock(&fbc->lock);
}
@@ -1437,6 +1433,8 @@ static void __intel_fbc_enable(struct intel_atomic_state *state,
intel_atomic_get_new_plane_state(state, plane);
struct intel_fbc *fbc = plane->fbc;
+ lockdep_assert_held(&fbc->lock);
+
if (fbc->state.plane) {
if (fbc->state.plane != plane)
return;
@@ -1522,7 +1520,8 @@ void intel_fbc_update(struct intel_atomic_state *state,
mutex_lock(&fbc->lock);
- if (crtc_state->update_pipe && plane_state->no_fbc_reason) {
+ if (intel_crtc_needs_fastset(crtc_state) &&
+ plane_state->no_fbc_reason) {
if (fbc->state.plane == plane)
__intel_fbc_disable(fbc);
} else {
diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c
index 112aa0447a0d..5575d7abdc09 100644
--- a/drivers/gpu/drm/i915/display/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/display/intel_fbdev.c
@@ -124,6 +124,8 @@ static const struct fb_ops intelfb_ops = {
.owner = THIS_MODULE,
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,
@@ -175,7 +177,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
}
if (IS_ERR(obj)) {
- drm_err(&dev_priv->drm, "failed to allocate framebuffer\n");
+ drm_err(&dev_priv->drm, "failed to allocate framebuffer (%pe)\n", obj);
return PTR_ERR(obj);
}
@@ -254,9 +256,9 @@ static int intelfb_create(struct drm_fb_helper *helper,
goto out_unlock;
}
- info = drm_fb_helper_alloc_fbi(helper);
+ info = drm_fb_helper_alloc_info(helper);
if (IS_ERR(info)) {
- drm_err(&dev_priv->drm, "Failed to allocate fb_info\n");
+ drm_err(&dev_priv->drm, "Failed to allocate fb_info (%pe)\n", info);
ret = PTR_ERR(info);
goto out_unpin;
}
@@ -291,7 +293,7 @@ static int intelfb_create(struct drm_fb_helper *helper,
vaddr = i915_vma_pin_iomap(vma);
if (IS_ERR(vaddr)) {
drm_err(&dev_priv->drm,
- "Failed to remap framebuffer into virtual memory\n");
+ "Failed to remap framebuffer into virtual memory (%pe)\n", vaddr);
ret = PTR_ERR(vaddr);
goto out_unpin;
}
@@ -584,7 +586,7 @@ void intel_fbdev_unregister(struct drm_i915_private *dev_priv)
if (!current_is_async())
intel_fbdev_sync(ifbdev);
- drm_fb_helper_unregister_fbi(&ifbdev->helper);
+ drm_fb_helper_unregister_info(&ifbdev->helper);
}
void intel_fbdev_fini(struct drm_i915_private *dev_priv)
@@ -627,7 +629,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
if (!ifbdev || !ifbdev->vma)
goto set_suspend;
- info = ifbdev->helper.fbdev;
+ info = ifbdev->helper.info;
if (synchronous) {
/* Flush any pending work to turn the console on, and then
diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c
index 7f47e5c85c81..063f1da4f229 100644
--- a/drivers/gpu/drm/i915/display/intel_fdi.c
+++ b/drivers/gpu/drm/i915/display/intel_fdi.c
@@ -5,6 +5,7 @@
#include <linux/string_helpers.h>
+#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_crtc.h"
#include "intel_ddi.h"
diff --git a/drivers/gpu/drm/i915/display/intel_fifo_underrun.h b/drivers/gpu/drm/i915/display/intel_fifo_underrun.h
index e04f22ac1f49..2e47d7d3c101 100644
--- a/drivers/gpu/drm/i915/display/intel_fifo_underrun.h
+++ b/drivers/gpu/drm/i915/display/intel_fifo_underrun.h
@@ -8,9 +8,8 @@
#include <linux/types.h>
-#include "intel_display.h"
-
struct drm_i915_private;
+enum pipe;
bool intel_set_cpu_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
enum pipe pipe, bool enable);
diff --git a/drivers/gpu/drm/i915/display/intel_frontbuffer.c b/drivers/gpu/drm/i915/display/intel_frontbuffer.c
index d80e3e8a9b01..17a7aa8b28c2 100644
--- a/drivers/gpu/drm/i915/display/intel_frontbuffer.c
+++ b/drivers/gpu/drm/i915/display/intel_frontbuffer.c
@@ -88,7 +88,7 @@ static void frontbuffer_flush(struct drm_i915_private *i915,
if (!frontbuffer_bits)
return;
- trace_intel_frontbuffer_flush(frontbuffer_bits, origin);
+ trace_intel_frontbuffer_flush(i915, frontbuffer_bits, origin);
might_sleep();
intel_drrs_flush(i915, frontbuffer_bits);
@@ -176,7 +176,7 @@ void __intel_fb_invalidate(struct intel_frontbuffer *front,
spin_unlock(&i915->display.fb_tracking.lock);
}
- trace_intel_frontbuffer_invalidate(frontbuffer_bits, origin);
+ trace_intel_frontbuffer_invalidate(i915, frontbuffer_bits, origin);
might_sleep();
intel_psr_invalidate(i915, frontbuffer_bits, origin);
diff --git a/drivers/gpu/drm/i915/display/intel_global_state.c b/drivers/gpu/drm/i915/display/intel_global_state.c
index 7a19215ad844..02b593b1e2ea 100644
--- a/drivers/gpu/drm/i915/display/intel_global_state.c
+++ b/drivers/gpu/drm/i915/display/intel_global_state.c
@@ -45,14 +45,14 @@ void intel_atomic_global_obj_init(struct drm_i915_private *dev_priv,
obj->state = state;
obj->funcs = funcs;
- list_add_tail(&obj->head, &dev_priv->global_obj_list);
+ list_add_tail(&obj->head, &dev_priv->display.global.obj_list);
}
void intel_atomic_global_obj_cleanup(struct drm_i915_private *dev_priv)
{
struct intel_global_obj *obj, *next;
- list_for_each_entry_safe(obj, next, &dev_priv->global_obj_list, head) {
+ list_for_each_entry_safe(obj, next, &dev_priv->display.global.obj_list, head) {
list_del(&obj->head);
drm_WARN_ON(&dev_priv->drm, kref_read(&obj->state->ref) != 1);
diff --git a/drivers/gpu/drm/i915/display/intel_global_state.h b/drivers/gpu/drm/i915/display/intel_global_state.h
index 1f16fa3073c9..f01ee0bb3e5a 100644
--- a/drivers/gpu/drm/i915/display/intel_global_state.h
+++ b/drivers/gpu/drm/i915/display/intel_global_state.h
@@ -27,7 +27,7 @@ struct intel_global_obj {
};
#define intel_for_each_global_obj(obj, dev_priv) \
- list_for_each_entry(obj, &(dev_priv)->global_obj_list, head)
+ list_for_each_entry(obj, &(dev_priv)->display.global.obj_list, head)
#define for_each_new_global_obj_in_state(__state, obj, new_obj_state, __i) \
for ((__i) = 0; \
diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c
index 74443f57f62d..a5840a28a69d 100644
--- a/drivers/gpu/drm/i915/display/intel_gmbus.c
+++ b/drivers/gpu/drm/i915/display/intel_gmbus.c
@@ -34,6 +34,8 @@
#include <drm/display/drm_hdcp_helper.h>
#include "i915_drv.h"
+#include "i915_irq.h"
+#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_gmbus.h"
@@ -49,9 +51,27 @@ struct intel_gmbus {
struct drm_i915_private *i915;
};
+enum gmbus_gpio {
+ GPIOA,
+ GPIOB,
+ GPIOC,
+ GPIOD,
+ GPIOE,
+ GPIOF,
+ GPIOG,
+ GPIOH,
+ __GPIOI_UNUSED,
+ GPIOJ,
+ GPIOK,
+ GPIOL,
+ GPIOM,
+ GPION,
+ GPIOO,
+};
+
struct gmbus_pin {
const char *name;
- enum i915_gpio gpio;
+ enum gmbus_gpio gpio;
};
/* Map gmbus pin pairs to names and registers. */
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp_regs.h b/drivers/gpu/drm/i915/display/intel_hdcp_regs.h
index 2a3733e8966c..8023c85c7fa0 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_hdcp_regs.h
@@ -6,7 +6,7 @@
#ifndef __INTEL_HDCP_REGS_H__
#define __INTEL_HDCP_REGS_H__
-#include "i915_reg_defs.h"
+#include "intel_display_reg_defs.h"
/* HDCP Key Registers */
#define HDCP_KEY_CONF _MMIO(0x66c00)
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c
index 7816b2a33fee..bac85d88054f 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.c
@@ -42,6 +42,7 @@
#include "i915_debugfs.h"
#include "i915_drv.h"
+#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_connector.h"
#include "intel_ddi.h"
@@ -2057,13 +2058,6 @@ static bool hdmi_bpc_possible(const struct intel_crtc_state *crtc_state, int bpc
if (!intel_hdmi_source_bpc_possible(dev_priv, bpc))
return false;
- /*
- * HDMI deep color affects the clocks, so it's only possible
- * when not cloning with other encoder types.
- */
- if (bpc > 8 && crtc_state->output_types != BIT(INTEL_OUTPUT_HDMI))
- return false;
-
/* Display Wa_1405510057:icl,ehl */
if (intel_hdmi_is_ycbcr420(crtc_state) &&
bpc == 10 && DISPLAY_VER(dev_priv) == 11 &&
@@ -2190,9 +2184,13 @@ static bool intel_hdmi_has_audio(struct intel_encoder *encoder,
}
static enum intel_output_format
-intel_hdmi_output_format(struct intel_connector *connector,
+intel_hdmi_output_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;
+
if (connector->base.ycbcr_420_allowed && ycbcr_420_output)
return INTEL_OUTPUT_FORMAT_YCBCR420;
else
@@ -2211,7 +2209,8 @@ 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(connector, ycbcr_420_only);
+ crtc_state->output_format =
+ intel_hdmi_output_format(crtc_state, connector, ycbcr_420_only);
if (ycbcr_420_only && !intel_hdmi_is_ycbcr420(crtc_state)) {
drm_dbg_kms(&i915->drm,
@@ -2226,13 +2225,19 @@ static int intel_hdmi_compute_output_format(struct intel_encoder *encoder,
!drm_mode_is_420_also(info, adjusted_mode))
return ret;
- crtc_state->output_format = intel_hdmi_output_format(connector, true);
+ crtc_state->output_format = intel_hdmi_output_format(crtc_state, connector, true);
ret = intel_hdmi_compute_clock(encoder, crtc_state, respect_downstream_limits);
}
return ret;
}
+static bool intel_hdmi_is_cloned(const struct intel_crtc_state *crtc_state)
+{
+ return crtc_state->uapi.encoder_mask &&
+ !is_power_of_2(crtc_state->uapi.encoder_mask);
+}
+
int intel_hdmi_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state)
@@ -2248,8 +2253,9 @@ 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);
+ 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;
@@ -2257,9 +2263,6 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
pipe_config->pixel_multiplier = 2;
- if (HAS_PCH_SPLIT(dev_priv) && !HAS_DDI(dev_priv))
- pipe_config->has_pch_encoder = true;
-
pipe_config->has_audio =
intel_hdmi_has_audio(encoder, pipe_config, conn_state);
@@ -2355,7 +2358,7 @@ intel_hdmi_unset_edid(struct drm_connector *connector)
}
static void
-intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid)
+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));
@@ -2371,16 +2374,10 @@ intel_hdmi_dp_dual_mode_detect(struct drm_connector *connector, bool has_edid)
* CONFIG1 pin, but no such luck on our hardware.
*
* The only method left to us is to check the VBT to see
- * if the port is a dual mode capable DP port. But let's
- * only do that when we sucesfully read the EDID, to avoid
- * confusing log messages about DP dual mode adaptors when
- * there's nothing connected to the port.
+ * if the port is a dual mode capable DP port.
*/
if (type == DRM_DP_DUAL_MODE_UNKNOWN) {
- /* An overridden EDID imply that we want this port for testing.
- * Make sure not to set limits for that port.
- */
- if (has_edid && !connector->override_edid &&
+ if (!connector->force &&
intel_bios_is_port_dp_dual_mode(dev_priv, port)) {
drm_dbg_kms(&dev_priv->drm,
"Assuming DP dual mode adaptor presence based on VBT\n");
@@ -2435,18 +2432,18 @@ intel_hdmi_set_edid(struct drm_connector *connector)
intel_gmbus_force_bit(i2c, false);
}
- intel_hdmi_dp_dual_mode_detect(connector, edid != NULL);
-
- intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
-
to_intel_connector(connector)->detect_edid = 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;
}
+ intel_display_power_put(dev_priv, POWER_DOMAIN_GMBUS, wakeref);
+
cec_notifier_set_phys_addr_from_edid(intel_hdmi->cec_notifier, edid);
return connected;
@@ -2956,9 +2953,8 @@ void intel_hdmi_init_connector(struct intel_digital_port *dig_port,
ddc);
drm_connector_helper_add(connector, &intel_hdmi_connector_helper_funcs);
- connector->interlace_allowed = 1;
- connector->doublescan_allowed = 0;
- connector->stereo_allowed = 1;
+ connector->interlace_allowed = true;
+ connector->stereo_allowed = true;
if (DISPLAY_VER(dev_priv) >= 10)
connector->ycbcr_420_allowed = true;
diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.h b/drivers/gpu/drm/i915/display/intel_hdmi.h
index 93f65a917c36..774dda2376ed 100644
--- a/drivers/gpu/drm/i915/display/intel_hdmi.h
+++ b/drivers/gpu/drm/i915/display/intel_hdmi.h
@@ -6,20 +6,20 @@
#ifndef __INTEL_HDMI_H__
#define __INTEL_HDMI_H__
-#include <linux/hdmi.h>
#include <linux/types.h>
+enum hdmi_infoframe_type;
+enum port;
struct drm_connector;
+struct drm_connector_state;
struct drm_encoder;
struct drm_i915_private;
struct intel_connector;
+struct intel_crtc_state;
struct intel_digital_port;
struct intel_encoder;
-struct intel_crtc_state;
struct intel_hdmi;
-struct drm_connector_state;
union hdmi_infoframe;
-enum port;
void intel_hdmi_init_connector(struct intel_digital_port *dig_port,
struct intel_connector *intel_connector);
diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.c b/drivers/gpu/drm/i915/display/intel_hotplug.c
index f7a2f485b177..907ab7526cb4 100644
--- a/drivers/gpu/drm/i915/display/intel_hotplug.c
+++ b/drivers/gpu/drm/i915/display/intel_hotplug.c
@@ -90,6 +90,9 @@ enum hpd_pin intel_hpd_pin_default(struct drm_i915_private *dev_priv,
return HPD_PORT_A + port - PORT_A;
}
+/* Threshold == 5 for long IRQs, 50 for short */
+#define HPD_STORM_DEFAULT_THRESHOLD 50
+
#define HPD_STORM_DETECT_PERIOD 1000
#define HPD_STORM_REENABLE_DELAY (2 * 60 * 1000)
#define HPD_RETRY_DELAY 1000
@@ -175,14 +178,13 @@ static bool intel_hpd_irq_storm_detect(struct drm_i915_private *dev_priv,
static void
intel_hpd_irq_storm_switch_to_polling(struct drm_i915_private *dev_priv)
{
- struct drm_device *dev = &dev_priv->drm;
struct drm_connector_list_iter conn_iter;
struct intel_connector *connector;
bool hpd_disabled = false;
lockdep_assert_held(&dev_priv->irq_lock);
- drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
for_each_intel_connector_iter(connector, &conn_iter) {
enum hpd_pin pin;
@@ -208,7 +210,7 @@ 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);
+ drm_kms_helper_poll_enable(&dev_priv->drm);
mod_delayed_work(system_wq, &dev_priv->display.hotplug.reenable_work,
msecs_to_jiffies(HPD_STORM_REENABLE_DELAY));
}
@@ -219,7 +221,6 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
struct drm_i915_private *dev_priv =
container_of(work, typeof(*dev_priv),
display.hotplug.reenable_work.work);
- struct drm_device *dev = &dev_priv->drm;
struct drm_connector_list_iter conn_iter;
struct intel_connector *connector;
intel_wakeref_t wakeref;
@@ -229,7 +230,7 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)
spin_lock_irq(&dev_priv->irq_lock);
- drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
for_each_intel_connector_iter(connector, &conn_iter) {
pin = intel_connector_hpd_pin(connector);
if (pin == HPD_NONE ||
@@ -367,14 +368,13 @@ static void i915_hotplug_work_func(struct work_struct *work)
struct drm_i915_private *dev_priv =
container_of(work, struct drm_i915_private,
display.hotplug.hotplug_work.work);
- struct drm_device *dev = &dev_priv->drm;
struct drm_connector_list_iter conn_iter;
struct intel_connector *connector;
u32 changed = 0, retry = 0;
u32 hpd_event_bits;
u32 hpd_retry_bits;
- mutex_lock(&dev->mode_config.mutex);
+ mutex_lock(&dev_priv->drm.mode_config.mutex);
drm_dbg_kms(&dev_priv->drm, "running encoder hotplug functions\n");
spin_lock_irq(&dev_priv->irq_lock);
@@ -389,7 +389,7 @@ static void i915_hotplug_work_func(struct work_struct *work)
spin_unlock_irq(&dev_priv->irq_lock);
- drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
for_each_intel_connector_iter(connector, &conn_iter) {
enum hpd_pin pin;
u32 hpd_bit;
@@ -426,10 +426,10 @@ static void i915_hotplug_work_func(struct work_struct *work)
}
}
drm_connector_list_iter_end(&conn_iter);
- mutex_unlock(&dev->mode_config.mutex);
+ mutex_unlock(&dev_priv->drm.mode_config.mutex);
if (changed)
- drm_kms_helper_hotplug_event(dev);
+ drm_kms_helper_hotplug_event(&dev_priv->drm);
/* Remove shared HPD pins that have changed */
retry &= ~changed;
@@ -612,16 +612,15 @@ static void i915_hpd_poll_init_work(struct work_struct *work)
struct drm_i915_private *dev_priv =
container_of(work, struct drm_i915_private,
display.hotplug.poll_init_work);
- struct drm_device *dev = &dev_priv->drm;
struct drm_connector_list_iter conn_iter;
struct intel_connector *connector;
bool enabled;
- mutex_lock(&dev->mode_config.mutex);
+ mutex_lock(&dev_priv->drm.mode_config.mutex);
enabled = READ_ONCE(dev_priv->display.hotplug.poll_enabled);
- drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
for_each_intel_connector_iter(connector, &conn_iter) {
enum hpd_pin pin;
@@ -638,16 +637,16 @@ 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);
+ drm_kms_helper_poll_enable(&dev_priv->drm);
- mutex_unlock(&dev->mode_config.mutex);
+ mutex_unlock(&dev_priv->drm.mode_config.mutex);
/*
* We might have missed any hotplugs that happened while we were
* in the middle of disabling polling
*/
if (!enabled)
- drm_helper_hpd_irq_event(dev);
+ drm_helper_hpd_irq_event(&dev_priv->drm);
}
/**
@@ -711,14 +710,23 @@ void intel_hpd_poll_disable(struct drm_i915_private *dev_priv)
schedule_work(&dev_priv->display.hotplug.poll_init_work);
}
-void intel_hpd_init_work(struct drm_i915_private *dev_priv)
+void intel_hpd_init_early(struct drm_i915_private *i915)
{
- INIT_DELAYED_WORK(&dev_priv->display.hotplug.hotplug_work,
+ INIT_DELAYED_WORK(&i915->display.hotplug.hotplug_work,
i915_hotplug_work_func);
- INIT_WORK(&dev_priv->display.hotplug.dig_port_work, i915_digport_work_func);
- INIT_WORK(&dev_priv->display.hotplug.poll_init_work, i915_hpd_poll_init_work);
- INIT_DELAYED_WORK(&dev_priv->display.hotplug.reenable_work,
+ INIT_WORK(&i915->display.hotplug.dig_port_work, i915_digport_work_func);
+ INIT_WORK(&i915->display.hotplug.poll_init_work, i915_hpd_poll_init_work);
+ INIT_DELAYED_WORK(&i915->display.hotplug.reenable_work,
intel_hpd_irq_storm_reenable_work);
+
+ i915->display.hotplug.hpd_storm_threshold = HPD_STORM_DEFAULT_THRESHOLD;
+ /* If we have MST support, we want to avoid doing short HPD IRQ storm
+ * detection, as short HPD storms will occur as a natural part of
+ * sideband messaging with MST.
+ * On older platforms however, IRQ storms can occur with both long and
+ * short pulses, as seen on some G4x systems.
+ */
+ i915->display.hotplug.hpd_short_storm_enabled = !HAS_DP_MST(i915);
}
void intel_hpd_cancel_work(struct drm_i915_private *dev_priv)
@@ -767,3 +775,169 @@ void intel_hpd_enable(struct drm_i915_private *dev_priv, enum hpd_pin pin)
dev_priv->display.hotplug.stats[pin].state = HPD_ENABLED;
spin_unlock_irq(&dev_priv->irq_lock);
}
+
+static int i915_hpd_storm_ctl_show(struct seq_file *m, void *data)
+{
+ struct drm_i915_private *dev_priv = m->private;
+ struct intel_hotplug *hotplug = &dev_priv->display.hotplug;
+
+ /* Synchronize with everything first in case there's been an HPD
+ * storm, but we haven't finished handling it in the kernel yet
+ */
+ intel_synchronize_irq(dev_priv);
+ flush_work(&dev_priv->display.hotplug.dig_port_work);
+ flush_delayed_work(&dev_priv->display.hotplug.hotplug_work);
+
+ seq_printf(m, "Threshold: %d\n", hotplug->hpd_storm_threshold);
+ seq_printf(m, "Detected: %s\n",
+ str_yes_no(delayed_work_pending(&hotplug->reenable_work)));
+
+ return 0;
+}
+
+static ssize_t i915_hpd_storm_ctl_write(struct file *file,
+ const char __user *ubuf, size_t len,
+ loff_t *offp)
+{
+ struct seq_file *m = file->private_data;
+ struct drm_i915_private *dev_priv = m->private;
+ struct intel_hotplug *hotplug = &dev_priv->display.hotplug;
+ unsigned int new_threshold;
+ int i;
+ char *newline;
+ char tmp[16];
+
+ if (len >= sizeof(tmp))
+ return -EINVAL;
+
+ if (copy_from_user(tmp, ubuf, len))
+ return -EFAULT;
+
+ tmp[len] = '\0';
+
+ /* Strip newline, if any */
+ newline = strchr(tmp, '\n');
+ if (newline)
+ *newline = '\0';
+
+ if (strcmp(tmp, "reset") == 0)
+ new_threshold = HPD_STORM_DEFAULT_THRESHOLD;
+ else if (kstrtouint(tmp, 10, &new_threshold) != 0)
+ return -EINVAL;
+
+ if (new_threshold > 0)
+ drm_dbg_kms(&dev_priv->drm,
+ "Setting HPD storm detection threshold to %d\n",
+ new_threshold);
+ else
+ drm_dbg_kms(&dev_priv->drm, "Disabling HPD storm detection\n");
+
+ spin_lock_irq(&dev_priv->irq_lock);
+ hotplug->hpd_storm_threshold = new_threshold;
+ /* Reset the HPD storm stats so we don't accidentally trigger a storm */
+ for_each_hpd_pin(i)
+ hotplug->stats[i].count = 0;
+ spin_unlock_irq(&dev_priv->irq_lock);
+
+ /* Re-enable hpd immediately if we were in an irq storm */
+ flush_delayed_work(&dev_priv->display.hotplug.reenable_work);
+
+ return len;
+}
+
+static int i915_hpd_storm_ctl_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, i915_hpd_storm_ctl_show, inode->i_private);
+}
+
+static const struct file_operations i915_hpd_storm_ctl_fops = {
+ .owner = THIS_MODULE,
+ .open = i915_hpd_storm_ctl_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .write = i915_hpd_storm_ctl_write
+};
+
+static int i915_hpd_short_storm_ctl_show(struct seq_file *m, void *data)
+{
+ struct drm_i915_private *dev_priv = m->private;
+
+ seq_printf(m, "Enabled: %s\n",
+ str_yes_no(dev_priv->display.hotplug.hpd_short_storm_enabled));
+
+ return 0;
+}
+
+static int
+i915_hpd_short_storm_ctl_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, i915_hpd_short_storm_ctl_show,
+ inode->i_private);
+}
+
+static ssize_t i915_hpd_short_storm_ctl_write(struct file *file,
+ const char __user *ubuf,
+ size_t len, loff_t *offp)
+{
+ struct seq_file *m = file->private_data;
+ struct drm_i915_private *dev_priv = m->private;
+ struct intel_hotplug *hotplug = &dev_priv->display.hotplug;
+ char *newline;
+ char tmp[16];
+ int i;
+ bool new_state;
+
+ if (len >= sizeof(tmp))
+ return -EINVAL;
+
+ if (copy_from_user(tmp, ubuf, len))
+ return -EFAULT;
+
+ tmp[len] = '\0';
+
+ /* Strip newline, if any */
+ newline = strchr(tmp, '\n');
+ if (newline)
+ *newline = '\0';
+
+ /* Reset to the "default" state for this system */
+ if (strcmp(tmp, "reset") == 0)
+ new_state = !HAS_DP_MST(dev_priv);
+ else if (kstrtobool(tmp, &new_state) != 0)
+ return -EINVAL;
+
+ drm_dbg_kms(&dev_priv->drm, "%sabling HPD short storm detection\n",
+ new_state ? "En" : "Dis");
+
+ spin_lock_irq(&dev_priv->irq_lock);
+ hotplug->hpd_short_storm_enabled = new_state;
+ /* Reset the HPD storm stats so we don't accidentally trigger a storm */
+ for_each_hpd_pin(i)
+ hotplug->stats[i].count = 0;
+ spin_unlock_irq(&dev_priv->irq_lock);
+
+ /* Re-enable hpd immediately if we were in an irq storm */
+ flush_delayed_work(&dev_priv->display.hotplug.reenable_work);
+
+ return len;
+}
+
+static const struct file_operations i915_hpd_short_storm_ctl_fops = {
+ .owner = THIS_MODULE,
+ .open = i915_hpd_short_storm_ctl_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+ .write = i915_hpd_short_storm_ctl_write,
+};
+
+void intel_hpd_debugfs_register(struct drm_i915_private *i915)
+{
+ struct drm_minor *minor = i915->drm.primary;
+
+ debugfs_create_file("i915_hpd_storm_ctl", 0644, minor->debugfs_root,
+ i915, &i915_hpd_storm_ctl_fops);
+ debugfs_create_file("i915_hpd_short_storm_ctl", 0644, minor->debugfs_root,
+ i915, &i915_hpd_short_storm_ctl_fops);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_hotplug.h b/drivers/gpu/drm/i915/display/intel_hotplug.h
index b87e95d606e6..424ae5dbf5a0 100644
--- a/drivers/gpu/drm/i915/display/intel_hotplug.h
+++ b/drivers/gpu/drm/i915/display/intel_hotplug.h
@@ -22,11 +22,12 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,
u32 pin_mask, u32 long_mask);
void intel_hpd_trigger_irq(struct intel_digital_port *dig_port);
void intel_hpd_init(struct drm_i915_private *dev_priv);
-void intel_hpd_init_work(struct drm_i915_private *dev_priv);
+void intel_hpd_init_early(struct drm_i915_private *i915);
void intel_hpd_cancel_work(struct drm_i915_private *dev_priv);
enum hpd_pin intel_hpd_pin_default(struct drm_i915_private *dev_priv,
enum port port);
bool intel_hpd_disable(struct drm_i915_private *dev_priv, enum hpd_pin pin);
void intel_hpd_enable(struct drm_i915_private *dev_priv, enum hpd_pin pin);
+void intel_hpd_debugfs_register(struct drm_i915_private *i915);
#endif /* __INTEL_HOTPLUG_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_hti.c b/drivers/gpu/drm/i915/display/intel_hti.c
new file mode 100644
index 000000000000..12a1f4ce1a77
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_hti.c
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+#include "i915_drv.h"
+#include "intel_de.h"
+#include "intel_display.h"
+#include "intel_hti.h"
+#include "intel_hti_regs.h"
+
+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)
+ i915->display.hti.state = intel_de_read(i915, HDPORT_STATE);
+}
+
+bool intel_hti_uses_phy(struct drm_i915_private *i915, enum phy phy)
+{
+ return i915->display.hti.state & HDPORT_ENABLED &&
+ i915->display.hti.state & HDPORT_DDI_USED(phy);
+}
+
+u32 intel_hti_dpll_mask(struct drm_i915_private *i915)
+{
+ if (!(i915->display.hti.state & HDPORT_ENABLED))
+ return 0;
+
+ /*
+ * Note: This is subtle. The values must coincide with what's defined
+ * for the platform.
+ */
+ return REG_FIELD_GET(HDPORT_DPLL_USED_MASK, i915->display.hti.state);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_hti.h b/drivers/gpu/drm/i915/display/intel_hti.h
new file mode 100644
index 000000000000..2893d6668657
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_hti.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+#ifndef __INTEL_HTI_H__
+#define __INTEL_HTI_H__
+
+#include <linux/types.h>
+
+struct drm_i915_private;
+enum phy;
+
+void intel_hti_init(struct drm_i915_private *i915);
+bool intel_hti_uses_phy(struct drm_i915_private *i915, enum phy phy);
+u32 intel_hti_dpll_mask(struct drm_i915_private *i915);
+
+#endif /* __INTEL_HTI_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_hti_regs.h b/drivers/gpu/drm/i915/display/intel_hti_regs.h
new file mode 100644
index 000000000000..e206f2837fc8
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_hti_regs.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+#ifndef __INTEL_HTI_REGS_H__
+#define __INTEL_HTI_REGS_H__
+
+#include "i915_reg_defs.h"
+
+#define HDPORT_STATE _MMIO(0x45050)
+#define HDPORT_DPLL_USED_MASK REG_GENMASK(15, 12)
+#define HDPORT_DDI_USED(phy) REG_BIT(2 * (phy) + 1)
+#define HDPORT_ENABLED REG_BIT(0)
+
+#endif /* __INTEL_HTI_REGS_H__ */
diff --git a/drivers/gpu/drm/i915/display/intel_lpe_audio.c b/drivers/gpu/drm/i915/display/intel_lpe_audio.c
index dca6003ccac8..8aaaef4d7856 100644
--- a/drivers/gpu/drm/i915/display/intel_lpe_audio.c
+++ b/drivers/gpu/drm/i915/display/intel_lpe_audio.c
@@ -71,6 +71,8 @@
#include <drm/intel_lpe_audio.h>
#include "i915_drv.h"
+#include "i915_irq.h"
+#include "i915_reg.h"
#include "intel_de.h"
#include "intel_lpe_audio.h"
#include "intel_pci_config.h"
@@ -80,8 +82,7 @@
static struct platform_device *
lpe_audio_platdev_create(struct drm_i915_private *dev_priv)
{
- struct drm_device *dev = &dev_priv->drm;
- struct pci_dev *pdev = to_pci_dev(dev->dev);
+ struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev);
struct platform_device_info pinfo = {};
struct resource *rsc;
struct platform_device *platdev;
@@ -101,14 +102,14 @@ lpe_audio_platdev_create(struct drm_i915_private *dev_priv)
rsc[0].flags = IORESOURCE_IRQ;
rsc[0].name = "hdmi-lpe-audio-irq";
- rsc[1].start = pci_resource_start(pdev, GTTMMADR_BAR) +
+ rsc[1].start = pci_resource_start(pdev, GEN4_GTTMMADR_BAR) +
I915_HDMI_LPE_AUDIO_BASE;
- rsc[1].end = pci_resource_start(pdev, GTTMMADR_BAR) +
+ rsc[1].end = pci_resource_start(pdev, GEN4_GTTMMADR_BAR) +
I915_HDMI_LPE_AUDIO_BASE + I915_HDMI_LPE_AUDIO_SIZE - 1;
rsc[1].flags = IORESOURCE_MEM;
rsc[1].name = "hdmi-lpe-audio-mmio";
- pinfo.parent = dev->dev;
+ pinfo.parent = dev_priv->drm.dev;
pinfo.name = "hdmi-lpe-audio";
pinfo.id = -1;
pinfo.res = rsc;
diff --git a/drivers/gpu/drm/i915/display/intel_lspcon.c b/drivers/gpu/drm/i915/display/intel_lspcon.c
index 15d59de8810e..9ff1c0b223ad 100644
--- a/drivers/gpu/drm/i915/display/intel_lspcon.c
+++ b/drivers/gpu/drm/i915/display/intel_lspcon.c
@@ -28,6 +28,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
+#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_dp.h"
diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c
index e5352239b2a2..7bf1bdfd03ec 100644
--- a/drivers/gpu/drm/i915/display/intel_lvds.c
+++ b/drivers/gpu/drm/i915/display/intel_lvds.c
@@ -39,6 +39,7 @@
#include <drm/drm_edid.h>
#include "i915_drv.h"
+#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_backlight.h"
#include "intel_connector.h"
@@ -78,9 +79,9 @@ struct intel_lvds_encoder {
struct intel_connector *attached_connector;
};
-static struct intel_lvds_encoder *to_lvds_encoder(struct drm_encoder *encoder)
+static struct intel_lvds_encoder *to_lvds_encoder(struct intel_encoder *encoder)
{
- return container_of(encoder, struct intel_lvds_encoder, base.base);
+ return container_of(encoder, struct intel_lvds_encoder, base);
}
bool intel_lvds_port_enabled(struct drm_i915_private *dev_priv,
@@ -103,7 +104,7 @@ static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
enum pipe *pipe)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
+ struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);
intel_wakeref_t wakeref;
bool ret;
@@ -123,7 +124,7 @@ static void intel_lvds_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
- struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
+ struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);
u32 tmp, flags = 0;
pipe_config->output_types |= BIT(INTEL_OUTPUT_LVDS);
@@ -229,7 +230,7 @@ static void intel_pre_enable_lvds(struct intel_atomic_state *state,
const struct intel_crtc_state *pipe_config,
const struct drm_connector_state *conn_state)
{
- struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
+ struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
@@ -312,7 +313,7 @@ static void intel_enable_lvds(struct intel_atomic_state *state,
const struct drm_connector_state *conn_state)
{
struct drm_device *dev = encoder->base.dev;
- struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
+ struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);
struct drm_i915_private *dev_priv = to_i915(dev);
intel_de_write(dev_priv, lvds_encoder->reg,
@@ -334,7 +335,7 @@ static void intel_disable_lvds(struct intel_atomic_state *state,
const struct intel_crtc_state *old_crtc_state,
const struct drm_connector_state *old_conn_state)
{
- struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
+ struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);
struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
intel_de_write(dev_priv, PP_CONTROL(0),
@@ -413,7 +414,7 @@ static int intel_lvds_compute_config(struct intel_encoder *intel_encoder,
{
struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
struct intel_lvds_encoder *lvds_encoder =
- to_lvds_encoder(&intel_encoder->base);
+ to_lvds_encoder(intel_encoder);
struct intel_connector *intel_connector =
lvds_encoder->attached_connector;
struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
@@ -775,7 +776,7 @@ bool intel_is_dual_link_lvds(struct drm_i915_private *dev_priv)
{
struct intel_encoder *encoder = intel_get_lvds_encoder(dev_priv);
- return encoder && to_lvds_encoder(&encoder->base)->is_dual_link;
+ return encoder && to_lvds_encoder(encoder)->is_dual_link;
}
static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)
@@ -814,6 +815,11 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)
return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP;
}
+static void intel_lvds_add_properties(struct drm_connector *connector)
+{
+ intel_attach_scaling_mode_property(connector);
+}
+
/**
* intel_lvds_init - setup LVDS connectors on this device
* @dev_priv: i915 device
@@ -823,7 +829,6 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)
*/
void intel_lvds_init(struct drm_i915_private *dev_priv)
{
- struct drm_device *dev = &dev_priv->drm;
struct intel_lvds_encoder *lvds_encoder;
struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector;
@@ -833,11 +838,10 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
i915_reg_t lvds_reg;
u32 lvds;
u8 pin;
- u32 allowed_scalers;
/* Skip init on machines we know falsely report LVDS */
if (dmi_check_system(intel_no_lvds)) {
- drm_WARN(dev, !dev_priv->display.vbt.int_lvds_support,
+ drm_WARN(&dev_priv->drm, !dev_priv->display.vbt.int_lvds_support,
"Useless DMI match. Internal LVDS support disabled by VBT\n");
return;
}
@@ -886,10 +890,10 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
intel_encoder = &lvds_encoder->base;
encoder = &intel_encoder->base;
connector = &intel_connector->base;
- drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs,
+ drm_connector_init(&dev_priv->drm, &intel_connector->base, &intel_lvds_connector_funcs,
DRM_MODE_CONNECTOR_LVDS);
- drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs,
+ drm_encoder_init(&dev_priv->drm, &intel_encoder->base, &intel_lvds_enc_funcs,
DRM_MODE_ENCODER_LVDS, "LVDS");
intel_encoder->enable = intel_enable_lvds;
@@ -920,17 +924,10 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
connector->display_info.subpixel_order = SubPixelHorizontalRGB;
- connector->interlace_allowed = false;
- connector->doublescan_allowed = false;
lvds_encoder->reg = lvds_reg;
- /* create the scaling mode property */
- allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT);
- allowed_scalers |= BIT(DRM_MODE_SCALE_FULLSCREEN);
- allowed_scalers |= BIT(DRM_MODE_SCALE_CENTER);
- drm_connector_attach_scaling_mode_property(connector, allowed_scalers);
- connector->state->scaling_mode = DRM_MODE_SCALE_ASPECT;
+ intel_lvds_add_properties(connector);
intel_lvds_pps_get_hw_state(dev_priv, &lvds_encoder->init_pps);
lvds_encoder->init_lvds_val = lvds;
@@ -947,7 +944,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
* Attempt to get the fixed panel mode from DDC. Assume that the
* preferred mode is the right one.
*/
- mutex_lock(&dev->mode_config.mutex);
+ mutex_lock(&dev_priv->drm.mode_config.mutex);
if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC)
edid = drm_get_edid_switcheroo(connector,
intel_gmbus_get_adapter(dev_priv, pin));
@@ -971,8 +968,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
IS_ERR(edid) ? NULL : edid);
/* Try EDID first */
- intel_panel_add_edid_fixed_modes(intel_connector,
- intel_connector->panel.vbt.drrs_type != DRRS_TYPE_NONE);
+ intel_panel_add_edid_fixed_modes(intel_connector, true);
/* Failed to get EDID, what about VBT? */
if (!intel_panel_preferred_fixed_mode(intel_connector))
@@ -986,7 +982,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv)
if (!intel_panel_preferred_fixed_mode(intel_connector))
intel_panel_add_encoder_fixed_mode(intel_connector, intel_encoder);
- mutex_unlock(&dev->mode_config.mutex);
+ mutex_unlock(&dev_priv->drm.mode_config.mutex);
/* If we still don't have a mode after all that, give up. */
if (!intel_panel_preferred_fixed_mode(intel_connector))
diff --git a/drivers/gpu/drm/i915/display/intel_tc_phy_regs.h b/drivers/gpu/drm/i915/display/intel_mg_phy_regs.h
index 5a545086f959..0e8248bce52d 100644
--- a/drivers/gpu/drm/i915/display/intel_tc_phy_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_mg_phy_regs.h
@@ -3,10 +3,10 @@
* Copyright © 2022 Intel Corporation
*/
-#ifndef __INTEL_TC_PHY_REGS__
-#define __INTEL_TC_PHY_REGS__
+#ifndef __INTEL_MG_PHY_REGS__
+#define __INTEL_MG_PHY_REGS__
-#include "i915_reg_defs.h"
+#include "intel_display_reg_defs.h"
#define MG_PHY_PORT_LN(ln, tc_port, ln0p1, ln0p2, ln1p1) \
_MMIO(_PORT(tc_port, ln0p1, ln0p2) + (ln) * ((ln1p1) - (ln0p1)))
@@ -277,4 +277,4 @@
_MG_PLL_TDC_COLDST_BIAS_PORT1, \
_MG_PLL_TDC_COLDST_BIAS_PORT2)
-#endif /* __INTEL_TC_PHY_REGS__ */
+#endif /* __INTEL_MG_PHY_REGS__ */
diff --git a/drivers/gpu/drm/i915/display/intel_modeset_setup.c b/drivers/gpu/drm/i915/display/intel_modeset_setup.c
index cbfabd58b75a..96395bfbd41d 100644
--- a/drivers/gpu/drm/i915/display/intel_modeset_setup.c
+++ b/drivers/gpu/drm/i915/display/intel_modeset_setup.c
@@ -10,6 +10,7 @@
#include <drm/drm_atomic_state_helper.h>
#include "i915_drv.h"
+#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_bw.h"
#include "intel_color.h"
@@ -155,6 +156,12 @@ static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state
crtc_state->uapi.adjusted_mode = crtc_state->hw.adjusted_mode;
crtc_state->uapi.scaling_filter = crtc_state->hw.scaling_filter;
+ /* assume 1:1 mapping */
+ drm_property_replace_blob(&crtc_state->hw.degamma_lut,
+ crtc_state->pre_csc_lut);
+ drm_property_replace_blob(&crtc_state->hw.gamma_lut,
+ crtc_state->post_csc_lut);
+
drm_property_replace_blob(&crtc_state->uapi.degamma_lut,
crtc_state->hw.degamma_lut);
drm_property_replace_blob(&crtc_state->uapi.gamma_lut,
@@ -205,13 +212,21 @@ static bool intel_crtc_has_encoders(struct intel_crtc *crtc)
static struct intel_connector *intel_encoder_find_connector(struct intel_encoder *encoder)
{
- struct drm_device *dev = encoder->base.dev;
+ struct drm_i915_private *i915 = to_i915(encoder->base.dev);
+ struct drm_connector_list_iter conn_iter;
struct intel_connector *connector;
+ struct intel_connector *found_connector = NULL;
- for_each_connector_on_encoder(dev, &encoder->base, connector)
- return connector;
+ drm_connector_list_iter_begin(&i915->drm, &conn_iter);
+ for_each_intel_connector_iter(connector, &conn_iter) {
+ if (&encoder->base == connector->base.encoder) {
+ found_connector = connector;
+ break;
+ }
+ }
+ drm_connector_list_iter_end(&conn_iter);
- return NULL;
+ return found_connector;
}
static void intel_sanitize_fifo_underrun_reporting(const struct intel_crtc_state *crtc_state)
diff --git a/drivers/gpu/drm/i915/display/intel_modeset_verify.c b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
index 0fdcf2e6d57f..842d70f0dfd2 100644
--- a/drivers/gpu/drm/i915/display/intel_modeset_verify.c
+++ b/drivers/gpu/drm/i915/display/intel_modeset_verify.c
@@ -227,7 +227,8 @@ void intel_modeset_verify_crtc(struct intel_crtc *crtc,
struct intel_crtc_state *old_crtc_state,
struct intel_crtc_state *new_crtc_state)
{
- if (!intel_crtc_needs_modeset(new_crtc_state) && !new_crtc_state->update_pipe)
+ if (!intel_crtc_needs_modeset(new_crtc_state) &&
+ !intel_crtc_needs_fastset(new_crtc_state))
return;
intel_wm_state_verify(crtc, new_crtc_state);
diff --git a/drivers/gpu/drm/i915/display/intel_opregion.c b/drivers/gpu/drm/i915/display/intel_opregion.c
index caa07ef34f21..e0184745632c 100644
--- a/drivers/gpu/drm/i915/display/intel_opregion.c
+++ b/drivers/gpu/drm/i915/display/intel_opregion.c
@@ -463,7 +463,6 @@ static u32 asle_set_backlight(struct drm_i915_private *dev_priv, u32 bclp)
struct intel_connector *connector;
struct drm_connector_list_iter conn_iter;
struct opregion_asle *asle = dev_priv->display.opregion.asle;
- struct drm_device *dev = &dev_priv->drm;
drm_dbg(&dev_priv->drm, "bclp = 0x%08x\n", bclp);
@@ -480,7 +479,7 @@ static u32 asle_set_backlight(struct drm_i915_private *dev_priv, u32 bclp)
if (bclp > 255)
return ASLC_BACKLIGHT_FAILED;
- drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
+ drm_modeset_lock(&dev_priv->drm.mode_config.connection_mutex, NULL);
/*
* Update backlight on all connectors that support backlight (usually
@@ -488,13 +487,13 @@ static u32 asle_set_backlight(struct drm_i915_private *dev_priv, u32 bclp)
*/
drm_dbg_kms(&dev_priv->drm, "updating opregion backlight %d/255\n",
bclp);
- drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
for_each_intel_connector_iter(connector, &conn_iter)
intel_backlight_set_acpi(connector->base.state, bclp, 255);
drm_connector_list_iter_end(&conn_iter);
asle->cblv = DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID;
- drm_modeset_unlock(&dev->mode_config.connection_mutex);
+ drm_modeset_unlock(&dev_priv->drm.mode_config.connection_mutex);
return 0;
diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c
index 41cec9dc4223..1640726bfbf6 100644
--- a/drivers/gpu/drm/i915/display/intel_panel.c
+++ b/drivers/gpu/drm/i915/display/intel_panel.c
@@ -31,6 +31,7 @@
#include <linux/kernel.h>
#include <linux/pwm.h>
+#include "i915_reg.h"
#include "intel_backlight.h"
#include "intel_connector.h"
#include "intel_de.h"
@@ -85,9 +86,10 @@ static bool is_alt_drrs_mode(const struct drm_display_mode *mode,
static bool is_alt_fixed_mode(const struct drm_display_mode *mode,
const struct drm_display_mode *preferred_mode)
{
- return drm_mode_match(mode, preferred_mode,
- DRM_MODE_MATCH_FLAGS |
- DRM_MODE_MATCH_3D_FLAGS) &&
+ u32 sync_flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NHSYNC |
+ DRM_MODE_FLAG_PVSYNC | DRM_MODE_FLAG_NVSYNC;
+
+ return (mode->flags & ~sync_flags) == (preferred_mode->flags & ~sync_flags) &&
mode->hdisplay == preferred_mode->hdisplay &&
mode->vdisplay == preferred_mode->vdisplay;
}
@@ -147,12 +149,24 @@ int intel_panel_get_modes(struct intel_connector *connector)
return num_modes;
}
-enum drrs_type intel_panel_drrs_type(struct intel_connector *connector)
+static bool has_drrs_modes(struct intel_connector *connector)
{
- if (list_empty(&connector->panel.fixed_modes) ||
- list_is_singular(&connector->panel.fixed_modes))
- return DRRS_TYPE_NONE;
+ const struct drm_display_mode *mode1;
+
+ list_for_each_entry(mode1, &connector->panel.fixed_modes, head) {
+ const struct drm_display_mode *mode2 = mode1;
+
+ list_for_each_entry_continue(mode2, &connector->panel.fixed_modes, head) {
+ if (is_alt_drrs_mode(mode1, mode2))
+ return true;
+ }
+ }
+
+ return false;
+}
+enum drrs_type intel_panel_drrs_type(struct intel_connector *connector)
+{
return connector->panel.vbt.drrs_type;
}
@@ -653,6 +667,9 @@ int intel_panel_init(struct intel_connector *connector)
intel_backlight_init_funcs(panel);
+ if (!has_drrs_modes(connector))
+ connector->panel.vbt.drrs_type = DRRS_TYPE_NONE;
+
drm_dbg_kms(connector->base.dev,
"[CONNECTOR:%d:%s] DRRS type: %s\n",
connector->base.base.id, connector->base.name,
diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c
index 837152dca063..cecc0d007cf3 100644
--- a/drivers/gpu/drm/i915/display/intel_pch_display.c
+++ b/drivers/gpu/drm/i915/display/intel_pch_display.c
@@ -4,6 +4,7 @@
*/
#include "g4x_dp.h"
+#include "i915_reg.h"
#include "intel_crt.h"
#include "intel_de.h"
#include "intel_display_types.h"
diff --git a/drivers/gpu/drm/i915/display/intel_pch_refclk.c b/drivers/gpu/drm/i915/display/intel_pch_refclk.c
index a66097cdc1e0..08a94365b7d1 100644
--- a/drivers/gpu/drm/i915/display/intel_pch_refclk.c
+++ b/drivers/gpu/drm/i915/display/intel_pch_refclk.c
@@ -3,6 +3,7 @@
* Copyright © 2021 Intel Corporation
*/
+#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_panel.h"
diff --git a/drivers/gpu/drm/i915/display/intel_pipe_crc.c b/drivers/gpu/drm/i915/display/intel_pipe_crc.c
index 8ac263f471be..e9774670e3f6 100644
--- a/drivers/gpu/drm/i915/display/intel_pipe_crc.c
+++ b/drivers/gpu/drm/i915/display/intel_pipe_crc.c
@@ -24,11 +24,12 @@
*
*/
-#include <linux/circ_buf.h>
#include <linux/ctype.h>
#include <linux/debugfs.h>
#include <linux/seq_file.h>
+#include "i915_irq.h"
+#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_de.h"
#include "intel_display_types.h"
@@ -75,7 +76,6 @@ static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv,
enum pipe pipe,
enum intel_pipe_crc_source *source)
{
- struct drm_device *dev = &dev_priv->drm;
struct intel_encoder *encoder;
struct intel_crtc *crtc;
struct intel_digital_port *dig_port;
@@ -83,8 +83,8 @@ static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv,
*source = INTEL_PIPE_CRC_SOURCE_PIPE;
- drm_modeset_lock_all(dev);
- for_each_intel_encoder(dev, encoder) {
+ drm_modeset_lock_all(&dev_priv->drm);
+ for_each_intel_encoder(&dev_priv->drm, encoder) {
if (!encoder->base.crtc)
continue;
@@ -111,7 +111,7 @@ static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv,
*source = INTEL_PIPE_CRC_SOURCE_DP_D;
break;
default:
- drm_WARN(dev, 1, "nonexisting DP port %c\n",
+ drm_WARN(&dev_priv->drm, 1, "nonexisting DP port %c\n",
port_name(dig_port->base.port));
break;
}
@@ -120,7 +120,7 @@ static int i9xx_pipe_crc_auto_source(struct drm_i915_private *dev_priv,
break;
}
}
- drm_modeset_unlock_all(dev);
+ drm_modeset_unlock_all(&dev_priv->drm);
return ret;
}
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index 21944f5bf3a8..9bbf41a076f7 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -5,10 +5,12 @@
#include "g4x_dp.h"
#include "i915_drv.h"
+#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_power_well.h"
#include "intel_display_types.h"
#include "intel_dp.h"
+#include "intel_dpio_phy.h"
#include "intel_dpll.h"
#include "intel_lvds.h"
#include "intel_pps.h"
@@ -1098,7 +1100,13 @@ bool intel_pps_have_panel_power_or_vdd(struct intel_dp *intel_dp)
static void pps_init_timestamps(struct intel_dp *intel_dp)
{
- intel_dp->pps.panel_power_off_time = ktime_get_boottime();
+ /*
+ * Initialize panel power off time to 0, assuming panel power could have
+ * been toggled between kernel boot and now only by a previously loaded
+ * and removed i915, which has already ensured sufficient power off
+ * delay at module remove.
+ */
+ intel_dp->pps.panel_power_off_time = 0;
intel_dp->pps.last_power_on = jiffies;
intel_dp->pps.last_backlight_off = jiffies;
}
diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c
index 15c3e448aa0e..5b678916e6db 100644
--- a/drivers/gpu/drm/i915/display/intel_psr.c
+++ b/drivers/gpu/drm/i915/display/intel_psr.c
@@ -27,6 +27,7 @@
#include "display/intel_dp.h"
#include "i915_drv.h"
+#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_crtc.h"
#include "intel_de.h"
@@ -533,7 +534,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
val |= psr_compute_idle_frames(intel_dp) << EDP_PSR2_IDLE_FRAME_SHIFT;
- if (!IS_ALDERLAKE_P(dev_priv))
+ if (DISPLAY_VER(dev_priv) <= 13 && !IS_ALDERLAKE_P(dev_priv))
val |= EDP_SU_TRACK_ENABLE;
if (DISPLAY_VER(dev_priv) >= 10 && DISPLAY_VER(dev_priv) <= 12)
@@ -616,7 +617,7 @@ static void hsw_activate_psr2(struct intel_dp *intel_dp)
static bool
transcoder_has_psr2(struct drm_i915_private *dev_priv, enum transcoder trans)
{
- if (IS_ALDERLAKE_P(dev_priv))
+ if (IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14)
return trans == TRANSCODER_A || trans == TRANSCODER_B;
else if (DISPLAY_VER(dev_priv) >= 12)
return trans == TRANSCODER_A;
@@ -696,7 +697,7 @@ dc3co_is_pipe_port_compatible(struct intel_dp *intel_dp,
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
enum port port = dig_port->base.port;
- if (IS_ALDERLAKE_P(dev_priv))
+ if (IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14)
return pipe <= PIPE_B && port <= PORT_B;
else
return pipe == PIPE_A && port == PORT_A;
@@ -779,6 +780,7 @@ static bool psr2_granularity_check(struct intel_dp *intel_dp,
struct intel_crtc_state *crtc_state)
{
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+ const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
const int crtc_hdisplay = crtc_state->hw.adjusted_mode.crtc_hdisplay;
const int crtc_vdisplay = crtc_state->hw.adjusted_mode.crtc_vdisplay;
u16 y_granularity = 0;
@@ -795,11 +797,11 @@ static bool psr2_granularity_check(struct intel_dp *intel_dp,
return intel_dp->psr.su_y_granularity == 4;
/*
- * adl_p has 1 line granularity. For other platforms with SW tracking we
- * can adjust the y coordinates to match sink requirement if multiple of
- * 4.
+ * adl_p and display 14+ platforms has 1 line granularity.
+ * For other platforms with SW tracking we can adjust the y coordinates
+ * to match sink requirement if multiple of 4.
*/
- if (IS_ALDERLAKE_P(dev_priv))
+ if (IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14)
y_granularity = intel_dp->psr.su_y_granularity;
else if (intel_dp->psr.su_y_granularity <= 2)
y_granularity = 4;
@@ -809,6 +811,10 @@ static bool psr2_granularity_check(struct intel_dp *intel_dp,
if (y_granularity == 0 || crtc_vdisplay % y_granularity)
return false;
+ if (crtc_state->dsc.compression_enable &&
+ vdsc_cfg->slice_height % y_granularity)
+ return false;
+
crtc_state->su_y_granularity = y_granularity;
return true;
}
@@ -883,7 +889,8 @@ static bool intel_psr2_config_valid(struct intel_dp *intel_dp,
* resolution requires DSC to be enabled, priority is given to DSC
* over PSR2.
*/
- if (crtc_state->dsc.compression_enable) {
+ if (crtc_state->dsc.compression_enable &&
+ (DISPLAY_VER(dev_priv) <= 13 && !IS_ALDERLAKE_P(dev_priv))) {
drm_dbg_kms(&dev_priv->drm,
"PSR2 cannot be enabled since DSC is enabled\n");
return false;
@@ -1469,26 +1476,27 @@ unlock:
static u32 man_trk_ctl_enable_bit_get(struct drm_i915_private *dev_priv)
{
- return IS_ALDERLAKE_P(dev_priv) ? 0 : PSR2_MAN_TRK_CTL_ENABLE;
+ return IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14 ? 0 :
+ PSR2_MAN_TRK_CTL_ENABLE;
}
static u32 man_trk_ctl_single_full_frame_bit_get(struct drm_i915_private *dev_priv)
{
- return IS_ALDERLAKE_P(dev_priv) ?
+ return IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14 ?
ADLP_PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME :
PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME;
}
static u32 man_trk_ctl_partial_frame_bit_get(struct drm_i915_private *dev_priv)
{
- return IS_ALDERLAKE_P(dev_priv) ?
+ return IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14 ?
ADLP_PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE :
PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE;
}
static u32 man_trk_ctl_continuos_full_frame(struct drm_i915_private *dev_priv)
{
- return IS_ALDERLAKE_P(dev_priv) ?
+ return IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14 ?
ADLP_PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME :
PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME;
}
@@ -1627,7 +1635,7 @@ static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state,
if (clip->y1 == -1)
goto exit;
- if (IS_ALDERLAKE_P(dev_priv)) {
+ if (IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14) {
val |= ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(clip->y1);
val |= ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(clip->y2 - 1);
} else {
@@ -1664,14 +1672,19 @@ static void intel_psr2_sel_fetch_pipe_alignment(const struct intel_crtc_state *c
struct drm_rect *pipe_clip)
{
struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev);
- const u16 y_alignment = crtc_state->su_y_granularity;
+ const struct drm_dsc_config *vdsc_cfg = &crtc_state->dsc.config;
+ u16 y_alignment;
+
+ /* ADLP aligns the SU region to vdsc slice height in case dsc is enabled */
+ if (crtc_state->dsc.compression_enable &&
+ (IS_ALDERLAKE_P(dev_priv) || DISPLAY_VER(dev_priv) >= 14))
+ y_alignment = vdsc_cfg->slice_height;
+ else
+ y_alignment = crtc_state->su_y_granularity;
pipe_clip->y1 -= pipe_clip->y1 % y_alignment;
if (pipe_clip->y2 % y_alignment)
pipe_clip->y2 = ((pipe_clip->y2 / y_alignment) + 1) * y_alignment;
-
- if (IS_ALDERLAKE_P(dev_priv) && crtc_state->dsc.compression_enable)
- drm_warn(&dev_priv->drm, "Missing PSR2 sel fetch alignment with DSC\n");
}
/*
@@ -2054,13 +2067,12 @@ static bool __psr_wait_for_idle_locked(struct intel_dp *intel_dp)
static int intel_psr_fastset_force(struct drm_i915_private *dev_priv)
{
struct drm_connector_list_iter conn_iter;
- struct drm_device *dev = &dev_priv->drm;
struct drm_modeset_acquire_ctx ctx;
struct drm_atomic_state *state;
struct drm_connector *conn;
int err = 0;
- state = drm_atomic_state_alloc(dev);
+ state = drm_atomic_state_alloc(&dev_priv->drm);
if (!state)
return -ENOMEM;
@@ -2069,7 +2081,7 @@ static int intel_psr_fastset_force(struct drm_i915_private *dev_priv)
retry:
- drm_connector_list_iter_begin(dev, &conn_iter);
+ drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter);
drm_for_each_connector_iter(conn, &conn_iter) {
struct drm_connector_state *conn_state;
struct drm_crtc_state *crtc_state;
diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c
index 774c1dc31a52..329b9d9af667 100644
--- a/drivers/gpu/drm/i915/display/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/display/intel_sdvo.c
@@ -37,6 +37,7 @@
#include <drm/drm_edid.h>
#include "i915_drv.h"
+#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_connector.h"
#include "intel_crtc.h"
@@ -199,7 +200,7 @@ to_intel_sdvo_connector(struct drm_connector *connector)
container_of((conn_state), struct intel_sdvo_connector_state, base.base)
static bool
-intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, u16 flags);
+intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo);
static bool
intel_sdvo_tv_create_property(struct intel_sdvo *intel_sdvo,
struct intel_sdvo_connector *intel_sdvo_connector,
@@ -1297,13 +1298,28 @@ static bool intel_sdvo_limited_color_range(struct intel_encoder *encoder,
return intel_hdmi_limited_color_range(crtc_state, conn_state);
}
+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);
+ const struct intel_digital_connector_state *intel_conn_state =
+ to_intel_digital_connector_state(conn_state);
+
+ if (!crtc_state->has_hdmi_sink)
+ return false;
+
+ if (intel_conn_state->force_audio == HDMI_AUDIO_AUTO)
+ return intel_sdvo->has_hdmi_audio;
+ else
+ return intel_conn_state->force_audio == HDMI_AUDIO_ON;
+}
+
static int intel_sdvo_compute_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config,
struct drm_connector_state *conn_state)
{
struct intel_sdvo *intel_sdvo = to_sdvo(encoder);
- struct intel_sdvo_connector_state *intel_sdvo_state =
- to_intel_sdvo_connector_state(conn_state);
struct intel_sdvo_connector *intel_sdvo_connector =
to_intel_sdvo_connector(conn_state->connector);
struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
@@ -1362,13 +1378,7 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder,
pipe_config->has_hdmi_sink = intel_has_hdmi_sink(intel_sdvo, conn_state);
- if (pipe_config->has_hdmi_sink) {
- if (intel_sdvo_state->base.force_audio == HDMI_AUDIO_AUTO)
- pipe_config->has_audio = intel_sdvo->has_hdmi_audio;
- else
- pipe_config->has_audio =
- intel_sdvo_state->base.force_audio == HDMI_AUDIO_ON;
- }
+ pipe_config->has_audio = intel_sdvo_has_audio(encoder, pipe_config, conn_state);
pipe_config->limited_color_range =
intel_sdvo_limited_color_range(encoder, pipe_config,
@@ -2290,17 +2300,12 @@ static int intel_sdvo_get_tv_modes(struct drm_connector *connector)
static int intel_sdvo_get_lvds_modes(struct drm_connector *connector)
{
- struct intel_sdvo *intel_sdvo = intel_attached_sdvo(to_intel_connector(connector));
struct drm_i915_private *dev_priv = to_i915(connector->dev);
- int num_modes = 0;
drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
- num_modes += intel_panel_get_modes(to_intel_connector(connector));
- num_modes += intel_ddc_get_modes(connector, &intel_sdvo->ddc);
-
- return num_modes;
+ return intel_panel_get_modes(to_intel_connector(connector));
}
static int intel_sdvo_get_modes(struct drm_connector *connector)
@@ -2627,7 +2632,7 @@ intel_sdvo_unselect_i2c_bus(struct intel_sdvo *sdvo)
}
static bool
-intel_sdvo_is_hdmi_connector(struct intel_sdvo *intel_sdvo, int device)
+intel_sdvo_is_hdmi_connector(struct intel_sdvo *intel_sdvo)
{
return intel_sdvo_check_supp_encode(intel_sdvo);
}
@@ -2689,9 +2694,8 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
drm_connector_helper_add(drm_connector,
&intel_sdvo_connector_helper_funcs);
- connector->base.base.interlace_allowed = 1;
- connector->base.base.doublescan_allowed = 0;
connector->base.base.display_info.subpixel_order = SubPixelHorizontalRGB;
+ connector->base.base.interlace_allowed = true;
connector->base.get_hw_state = intel_sdvo_connector_get_hw_state;
intel_connector_attach_encoder(&connector->base, &encoder->base);
@@ -2733,7 +2737,7 @@ static struct intel_sdvo_connector *intel_sdvo_connector_alloc(void)
}
static bool
-intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
+intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, u16 type)
{
struct drm_encoder *encoder = &intel_sdvo->base.base;
struct drm_connector *connector;
@@ -2741,16 +2745,13 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
struct intel_connector *intel_connector;
struct intel_sdvo_connector *intel_sdvo_connector;
- DRM_DEBUG_KMS("initialising DVI device %d\n", device);
+ DRM_DEBUG_KMS("initialising DVI type 0x%x\n", type);
intel_sdvo_connector = intel_sdvo_connector_alloc();
if (!intel_sdvo_connector)
return false;
- if (device == 0)
- intel_sdvo_connector->output_flag = SDVO_OUTPUT_TMDS0;
- else if (device == 1)
- intel_sdvo_connector->output_flag = SDVO_OUTPUT_TMDS1;
+ intel_sdvo_connector->output_flag = type;
intel_connector = &intel_sdvo_connector->base;
connector = &intel_connector->base;
@@ -2770,7 +2771,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
encoder->encoder_type = DRM_MODE_ENCODER_TMDS;
connector->connector_type = DRM_MODE_CONNECTOR_DVID;
- if (intel_sdvo_is_hdmi_connector(intel_sdvo, device)) {
+ if (intel_sdvo_is_hdmi_connector(intel_sdvo)) {
connector->connector_type = DRM_MODE_CONNECTOR_HDMIA;
intel_sdvo_connector->is_hdmi = true;
}
@@ -2787,14 +2788,14 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
}
static bool
-intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, int type)
+intel_sdvo_tv_init(struct intel_sdvo *intel_sdvo, u16 type)
{
struct drm_encoder *encoder = &intel_sdvo->base.base;
struct drm_connector *connector;
struct intel_connector *intel_connector;
struct intel_sdvo_connector *intel_sdvo_connector;
- DRM_DEBUG_KMS("initialising TV type %d\n", type);
+ DRM_DEBUG_KMS("initialising TV type 0x%x\n", type);
intel_sdvo_connector = intel_sdvo_connector_alloc();
if (!intel_sdvo_connector)
@@ -2826,14 +2827,14 @@ err:
}
static bool
-intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
+intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, u16 type)
{
struct drm_encoder *encoder = &intel_sdvo->base.base;
struct drm_connector *connector;
struct intel_connector *intel_connector;
struct intel_sdvo_connector *intel_sdvo_connector;
- DRM_DEBUG_KMS("initialising analog device %d\n", device);
+ DRM_DEBUG_KMS("initialising analog type 0x%x\n", type);
intel_sdvo_connector = intel_sdvo_connector_alloc();
if (!intel_sdvo_connector)
@@ -2845,10 +2846,7 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
encoder->encoder_type = DRM_MODE_ENCODER_DAC;
connector->connector_type = DRM_MODE_CONNECTOR_VGA;
- if (device == 0)
- intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB0;
- else if (device == 1)
- intel_sdvo_connector->output_flag = SDVO_OUTPUT_RGB1;
+ intel_sdvo_connector->output_flag = type;
if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) {
kfree(intel_sdvo_connector);
@@ -2859,7 +2857,7 @@ intel_sdvo_analog_init(struct intel_sdvo *intel_sdvo, int device)
}
static bool
-intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
+intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, u16 type)
{
struct drm_encoder *encoder = &intel_sdvo->base.base;
struct drm_i915_private *i915 = to_i915(encoder->dev);
@@ -2867,7 +2865,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
struct intel_connector *intel_connector;
struct intel_sdvo_connector *intel_sdvo_connector;
- DRM_DEBUG_KMS("initialising LVDS device %d\n", device);
+ DRM_DEBUG_KMS("initialising LVDS type 0x%x\n", type);
intel_sdvo_connector = intel_sdvo_connector_alloc();
if (!intel_sdvo_connector)
@@ -2878,10 +2876,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device)
encoder->encoder_type = DRM_MODE_ENCODER_LVDS;
connector->connector_type = DRM_MODE_CONNECTOR_LVDS;
- if (device == 0)
- intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS0;
- else if (device == 1)
- intel_sdvo_connector->output_flag = SDVO_OUTPUT_LVDS1;
+ intel_sdvo_connector->output_flag = type;
if (intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo) < 0) {
kfree(intel_sdvo_connector);
@@ -2937,63 +2932,61 @@ static u16 intel_sdvo_filter_output_flags(u16 flags)
return flags;
}
-static bool
-intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo, u16 flags)
+static bool intel_sdvo_output_init(struct intel_sdvo *sdvo, u16 type)
{
+ if (type & SDVO_TMDS_MASK)
+ return intel_sdvo_dvi_init(sdvo, type);
+ else if (type & SDVO_TV_MASK)
+ return intel_sdvo_tv_init(sdvo, type);
+ else if (type & SDVO_RGB_MASK)
+ return intel_sdvo_analog_init(sdvo, type);
+ else if (type & SDVO_LVDS_MASK)
+ return intel_sdvo_lvds_init(sdvo, type);
+ else
+ return false;
+}
+
+static bool
+intel_sdvo_output_setup(struct intel_sdvo *intel_sdvo)
+{
+ static const u16 probe_order[] = {
+ SDVO_OUTPUT_TMDS0,
+ SDVO_OUTPUT_TMDS1,
+ /* TV has no XXX1 function block */
+ SDVO_OUTPUT_SVID0,
+ SDVO_OUTPUT_CVBS0,
+ SDVO_OUTPUT_YPRPB0,
+ SDVO_OUTPUT_RGB0,
+ SDVO_OUTPUT_RGB1,
+ SDVO_OUTPUT_LVDS0,
+ SDVO_OUTPUT_LVDS1,
+ };
struct drm_i915_private *i915 = to_i915(intel_sdvo->base.base.dev);
+ u16 flags;
+ int i;
- flags = intel_sdvo_filter_output_flags(flags);
+ flags = intel_sdvo_filter_output_flags(intel_sdvo->caps.output_flags);
+
+ if (flags == 0) {
+ DRM_DEBUG_KMS("%s: Unknown SDVO output type (0x%04x)\n",
+ SDVO_NAME(intel_sdvo), intel_sdvo->caps.output_flags);
+ return false;
+ }
intel_sdvo->controlled_output = flags;
intel_sdvo_select_ddc_bus(i915, intel_sdvo);
- if (flags & SDVO_OUTPUT_TMDS0)
- if (!intel_sdvo_dvi_init(intel_sdvo, 0))
- return false;
+ for (i = 0; i < ARRAY_SIZE(probe_order); i++) {
+ u16 type = flags & probe_order[i];
- if (flags & SDVO_OUTPUT_TMDS1)
- if (!intel_sdvo_dvi_init(intel_sdvo, 1))
- return false;
-
- /* TV has no XXX1 function block */
- if (flags & SDVO_OUTPUT_SVID0)
- if (!intel_sdvo_tv_init(intel_sdvo, SDVO_OUTPUT_SVID0))
- return false;
+ if (!type)
+ continue;
- if (flags & SDVO_OUTPUT_CVBS0)
- if (!intel_sdvo_tv_init(intel_sdvo, SDVO_OUTPUT_CVBS0))
+ if (!intel_sdvo_output_init(intel_sdvo, type))
return false;
-
- if (flags & SDVO_OUTPUT_YPRPB0)
- if (!intel_sdvo_tv_init(intel_sdvo, SDVO_OUTPUT_YPRPB0))
- return false;
-
- if (flags & SDVO_OUTPUT_RGB0)
- if (!intel_sdvo_analog_init(intel_sdvo, 0))
- return false;
-
- if (flags & SDVO_OUTPUT_RGB1)
- if (!intel_sdvo_analog_init(intel_sdvo, 1))
- return false;
-
- if (flags & SDVO_OUTPUT_LVDS0)
- if (!intel_sdvo_lvds_init(intel_sdvo, 0))
- return false;
-
- if (flags & SDVO_OUTPUT_LVDS1)
- if (!intel_sdvo_lvds_init(intel_sdvo, 1))
- return false;
-
- if (flags == 0) {
- unsigned char bytes[2];
-
- memcpy(bytes, &intel_sdvo->caps.output_flags, 2);
- DRM_DEBUG_KMS("%s: Unknown SDVO output type (0x%02x%02x)\n",
- SDVO_NAME(intel_sdvo),
- bytes[0], bytes[1]);
- return false;
}
+
intel_sdvo->base.pipe_mask = ~0;
return true;
@@ -3369,8 +3362,7 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv,
intel_sdvo->colorimetry_cap =
intel_sdvo_get_colorimetry_cap(intel_sdvo);
- if (intel_sdvo_output_setup(intel_sdvo,
- intel_sdvo->caps.output_flags) != true) {
+ if (!intel_sdvo_output_setup(intel_sdvo)) {
drm_dbg_kms(&dev_priv->drm,
"SDVO output failed to setup on %s\n",
SDVO_NAME(intel_sdvo));
@@ -3421,9 +3413,12 @@ bool intel_sdvo_init(struct drm_i915_private *dev_priv,
(intel_sdvo->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
/* check currently supported outputs */
intel_sdvo->caps.output_flags &
- (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0) ? 'Y' : 'N',
+ (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0 |
+ SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_SVID0 |
+ SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_YPRPB0) ? 'Y' : 'N',
intel_sdvo->caps.output_flags &
- (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N');
+ (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1 |
+ SDVO_OUTPUT_LVDS1) ? 'Y' : 'N');
return true;
err_output:
diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c
index 937cefd6f78f..c799e891f8b5 100644
--- a/drivers/gpu/drm/i915/display/intel_snps_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c
@@ -5,6 +5,7 @@
#include <linux/util_macros.h>
+#include "i915_reg.h"
#include "intel_ddi.h"
#include "intel_ddi_buf_trans.h"
#include "intel_de.h"
diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy_regs.h b/drivers/gpu/drm/i915/display/intel_snps_phy_regs.h
index 0543465aaf14..a04d692169d4 100644
--- a/drivers/gpu/drm/i915/display/intel_snps_phy_regs.h
+++ b/drivers/gpu/drm/i915/display/intel_snps_phy_regs.h
@@ -6,7 +6,7 @@
#ifndef __INTEL_SNPS_PHY_REGS__
#define __INTEL_SNPS_PHY_REGS__
-#include "i915_reg_defs.h"
+#include "intel_display_reg_defs.h"
#define _SNPS_PHY_A_BASE 0x168000
#define _SNPS_PHY_B_BASE 0x169000
diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c
index 7649c50b5445..e6b4d24b9cd0 100644
--- a/drivers/gpu/drm/i915/display/intel_sprite.c
+++ b/drivers/gpu/drm/i915/display/intel_sprite.c
@@ -42,6 +42,7 @@
#include <drm/drm_rect.h>
#include "i915_drv.h"
+#include "i915_reg.h"
#include "i915_vgpu.h"
#include "i9xx_plane.h"
#include "intel_atomic_plane.h"
diff --git a/drivers/gpu/drm/i915/display/intel_sprite.h b/drivers/gpu/drm/i915/display/intel_sprite.h
index 4f63e4967731..4635c7ad23f9 100644
--- a/drivers/gpu/drm/i915/display/intel_sprite.h
+++ b/drivers/gpu/drm/i915/display/intel_sprite.h
@@ -8,14 +8,13 @@
#include <linux/types.h>
-#include "intel_display.h"
-
struct drm_device;
struct drm_display_mode;
struct drm_file;
struct drm_i915_private;
struct intel_crtc_state;
struct intel_plane_state;
+enum pipe;
/*
* FIXME: We should instead only take spinlocks once for the entire update
@@ -34,12 +33,6 @@ int intel_sprite_set_colorkey_ioctl(struct drm_device *dev, void *data,
int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state);
int chv_plane_check_rotation(const struct intel_plane_state *plane_state);
-static inline u8 icl_hdr_plane_mask(void)
-{
- return BIT(PLANE_PRIMARY) |
- BIT(PLANE_SPRITE0) | BIT(PLANE_SPRITE1);
-}
-
int ivb_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
const struct intel_plane_state *plane_state);
int hsw_plane_min_cdclk(const struct intel_crtc_state *crtc_state,
diff --git a/drivers/gpu/drm/i915/display/intel_tc.c b/drivers/gpu/drm/i915/display/intel_tc.c
index e5af955b5600..70624b4b2d38 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.c
+++ b/drivers/gpu/drm/i915/display/intel_tc.c
@@ -8,9 +8,10 @@
#include "intel_display.h"
#include "intel_display_power_map.h"
#include "intel_display_types.h"
+#include "intel_dkl_phy_regs.h"
#include "intel_dp_mst.h"
+#include "intel_mg_phy_regs.h"
#include "intel_tc.h"
-#include "intel_tc_phy_regs.h"
static const char *tc_port_mode_name(enum tc_port_mode mode)
{
@@ -408,14 +409,9 @@ static bool adl_tc_phy_take_ownership(struct intel_digital_port *dig_port,
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_uncore *uncore = &i915->uncore;
enum port port = dig_port->base.port;
- u32 val;
- val = intel_uncore_read(uncore, DDI_BUF_CTL(port));
- if (take)
- val |= DDI_BUF_CTL_TC_PHY_OWNERSHIP;
- else
- val &= ~DDI_BUF_CTL_TC_PHY_OWNERSHIP;
- intel_uncore_write(uncore, DDI_BUF_CTL(port), val);
+ intel_uncore_rmw(uncore, DDI_BUF_CTL(port), DDI_BUF_CTL_TC_PHY_OWNERSHIP,
+ take ? DDI_BUF_CTL_TC_PHY_OWNERSHIP : 0);
return true;
}
@@ -687,18 +683,58 @@ static void
intel_tc_port_link_init_refcount(struct intel_digital_port *dig_port,
int refcount)
{
+ dig_port->tc_link_refcount = refcount;
+}
+
+/**
+ * intel_tc_port_init_mode: Read out HW state and init the given port's TypeC mode
+ * @dig_port: digital port
+ *
+ * Read out the HW state and initialize the TypeC mode of @dig_port. The mode
+ * will be locked until intel_tc_port_sanitize_mode() is called.
+ */
+void intel_tc_port_init_mode(struct intel_digital_port *dig_port)
+{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
+ intel_wakeref_t tc_cold_wref;
+ enum intel_display_power_domain domain;
+
+ mutex_lock(&dig_port->tc_lock);
+ drm_WARN_ON(&i915->drm, dig_port->tc_mode != TC_PORT_DISCONNECTED);
+ drm_WARN_ON(&i915->drm, dig_port->tc_lock_wakeref);
drm_WARN_ON(&i915->drm, dig_port->tc_link_refcount);
- dig_port->tc_link_refcount = refcount;
+
+ tc_cold_wref = tc_cold_block(dig_port, &domain);
+
+ dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port);
+ /* Prevent changing dig_port->tc_mode until intel_tc_port_sanitize_mode() is called. */
+ intel_tc_port_link_init_refcount(dig_port, 1);
+ dig_port->tc_lock_wakeref = tc_cold_block(dig_port, &dig_port->tc_lock_power_domain);
+
+ tc_cold_unblock(dig_port, domain, tc_cold_wref);
+
+ drm_dbg_kms(&i915->drm, "Port %s: init mode (%s)\n",
+ dig_port->tc_port_name,
+ tc_port_mode_name(dig_port->tc_mode));
+
+ mutex_unlock(&dig_port->tc_lock);
}
-void intel_tc_port_sanitize(struct intel_digital_port *dig_port)
+/**
+ * intel_tc_port_sanitize_mode: Sanitize the given port's TypeC mode
+ * @dig_port: digital port
+ *
+ * Sanitize @dig_port's TypeC mode wrt. the encoder's state right after driver
+ * loading and system resume:
+ * If the encoder is enabled keep the TypeC mode/PHY connected state locked until
+ * the encoder is disabled.
+ * If the encoder is disabled make sure the PHY is disconnected.
+ */
+void intel_tc_port_sanitize_mode(struct intel_digital_port *dig_port)
{
struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev);
struct intel_encoder *encoder = &dig_port->base;
- intel_wakeref_t tc_cold_wref;
- enum intel_display_power_domain domain;
int active_links = 0;
mutex_lock(&dig_port->tc_lock);
@@ -708,21 +744,14 @@ void intel_tc_port_sanitize(struct intel_digital_port *dig_port)
else if (encoder->base.crtc)
active_links = to_intel_crtc(encoder->base.crtc)->active;
- drm_WARN_ON(&i915->drm, dig_port->tc_mode != TC_PORT_DISCONNECTED);
- drm_WARN_ON(&i915->drm, dig_port->tc_lock_wakeref);
-
- tc_cold_wref = tc_cold_block(dig_port, &domain);
+ drm_WARN_ON(&i915->drm, dig_port->tc_link_refcount != 1);
+ intel_tc_port_link_init_refcount(dig_port, active_links);
- dig_port->tc_mode = intel_tc_port_get_current_mode(dig_port);
if (active_links) {
if (!icl_tc_phy_is_connected(dig_port))
drm_dbg_kms(&i915->drm,
"Port %s: PHY disconnected with %d active link(s)\n",
dig_port->tc_port_name, active_links);
- intel_tc_port_link_init_refcount(dig_port, active_links);
-
- dig_port->tc_lock_wakeref = tc_cold_block(dig_port,
- &dig_port->tc_lock_power_domain);
} else {
/*
* TBT-alt is the default mode in any case the PHY ownership is not
@@ -736,9 +765,10 @@ void intel_tc_port_sanitize(struct intel_digital_port *dig_port)
dig_port->tc_port_name,
tc_port_mode_name(dig_port->tc_mode));
icl_tc_phy_disconnect(dig_port);
- }
- tc_cold_unblock(dig_port, domain, tc_cold_wref);
+ tc_cold_unblock(dig_port, dig_port->tc_lock_power_domain,
+ fetch_and_zero(&dig_port->tc_lock_wakeref));
+ }
drm_dbg_kms(&i915->drm, "Port %s: sanitize mode (%s)\n",
dig_port->tc_port_name,
@@ -923,4 +953,6 @@ void intel_tc_port_init(struct intel_digital_port *dig_port, bool is_legacy)
dig_port->tc_mode = TC_PORT_DISCONNECTED;
dig_port->tc_link_refcount = 0;
tc_port_load_fia_params(i915, dig_port);
+
+ intel_tc_port_init_mode(dig_port);
}
diff --git a/drivers/gpu/drm/i915/display/intel_tc.h b/drivers/gpu/drm/i915/display/intel_tc.h
index 6b47b29f551c..d54082e2d5e8 100644
--- a/drivers/gpu/drm/i915/display/intel_tc.h
+++ b/drivers/gpu/drm/i915/display/intel_tc.h
@@ -24,7 +24,8 @@ int intel_tc_port_fia_max_lane_count(struct intel_digital_port *dig_port);
void intel_tc_port_set_fia_lane_count(struct intel_digital_port *dig_port,
int required_lanes);
-void intel_tc_port_sanitize(struct intel_digital_port *dig_port);
+void intel_tc_port_init_mode(struct intel_digital_port *dig_port);
+void intel_tc_port_sanitize_mode(struct intel_digital_port *dig_port);
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);
diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c
index dcf89d701f0f..4d2101ca1692 100644
--- a/drivers/gpu/drm/i915/display/intel_tv.c
+++ b/drivers/gpu/drm/i915/display/intel_tv.c
@@ -35,6 +35,8 @@
#include <drm/drm_edid.h>
#include "i915_drv.h"
+#include "i915_reg.h"
+#include "i915_irq.h"
#include "intel_connector.h"
#include "intel_crtc.h"
#include "intel_de.h"
@@ -1880,18 +1882,56 @@ static const struct drm_encoder_funcs intel_tv_enc_funcs = {
.destroy = intel_encoder_destroy,
};
+static void intel_tv_add_properties(struct drm_connector *connector)
+{
+ struct drm_i915_private *i915 = to_i915(connector->dev);
+ struct drm_connector_state *conn_state = connector->state;
+ const char *tv_format_names[ARRAY_SIZE(tv_modes)];
+ int i;
+
+ /* BIOS margin values */
+ conn_state->tv.margins.left = 54;
+ conn_state->tv.margins.top = 36;
+ conn_state->tv.margins.right = 46;
+ conn_state->tv.margins.bottom = 37;
+
+ conn_state->tv.mode = 0;
+
+ /* Create TV properties then attach current values */
+ for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
+ /* 1080p50/1080p60 not supported on gen3 */
+ if (DISPLAY_VER(i915) == 3 && tv_modes[i].oversample == 1)
+ break;
+
+ tv_format_names[i] = tv_modes[i].name;
+ }
+ drm_mode_create_tv_properties(&i915->drm, i, tv_format_names);
+
+ drm_object_attach_property(&connector->base,
+ i915->drm.mode_config.tv_mode_property,
+ conn_state->tv.mode);
+ drm_object_attach_property(&connector->base,
+ i915->drm.mode_config.tv_left_margin_property,
+ conn_state->tv.margins.left);
+ drm_object_attach_property(&connector->base,
+ i915->drm.mode_config.tv_top_margin_property,
+ conn_state->tv.margins.top);
+ drm_object_attach_property(&connector->base,
+ i915->drm.mode_config.tv_right_margin_property,
+ conn_state->tv.margins.right);
+ drm_object_attach_property(&connector->base,
+ i915->drm.mode_config.tv_bottom_margin_property,
+ conn_state->tv.margins.bottom);
+}
+
void
intel_tv_init(struct drm_i915_private *dev_priv)
{
- struct drm_device *dev = &dev_priv->drm;
struct drm_connector *connector;
struct intel_tv *intel_tv;
struct intel_encoder *intel_encoder;
struct intel_connector *intel_connector;
u32 tv_dac_on, tv_dac_off, save_tv_dac;
- const char *tv_format_names[ARRAY_SIZE(tv_modes)];
- int i, initial_mode = 0;
- struct drm_connector_state *state;
if ((intel_de_read(dev_priv, TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED)
return;
@@ -1937,7 +1977,6 @@ intel_tv_init(struct drm_i915_private *dev_priv)
intel_encoder = &intel_tv->base;
connector = &intel_connector->base;
- state = connector->state;
/*
* The documentation, for the older chipsets at least, recommend
@@ -1951,10 +1990,10 @@ intel_tv_init(struct drm_i915_private *dev_priv)
*/
intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
- drm_connector_init(dev, connector, &intel_tv_connector_funcs,
+ drm_connector_init(&dev_priv->drm, connector, &intel_tv_connector_funcs,
DRM_MODE_CONNECTOR_SVIDEO);
- drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs,
+ drm_encoder_init(&dev_priv->drm, &intel_encoder->base, &intel_tv_enc_funcs,
DRM_MODE_ENCODER_TVDAC, "TV");
intel_encoder->compute_config = intel_tv_compute_config;
@@ -1974,41 +2013,7 @@ intel_tv_init(struct drm_i915_private *dev_priv)
intel_encoder->cloneable = 0;
intel_tv->type = DRM_MODE_CONNECTOR_Unknown;
- /* BIOS margin values */
- state->tv.margins.left = 54;
- state->tv.margins.top = 36;
- state->tv.margins.right = 46;
- state->tv.margins.bottom = 37;
-
- state->tv.mode = initial_mode;
-
drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs);
- connector->interlace_allowed = false;
- connector->doublescan_allowed = false;
- /* Create TV properties then attach current values */
- for (i = 0; i < ARRAY_SIZE(tv_modes); i++) {
- /* 1080p50/1080p60 not supported on gen3 */
- if (DISPLAY_VER(dev_priv) == 3 &&
- tv_modes[i].oversample == 1)
- break;
-
- tv_format_names[i] = tv_modes[i].name;
- }
- drm_mode_create_tv_properties(dev, i, tv_format_names);
-
- drm_object_attach_property(&connector->base, dev->mode_config.tv_mode_property,
- state->tv.mode);
- drm_object_attach_property(&connector->base,
- dev->mode_config.tv_left_margin_property,
- state->tv.margins.left);
- drm_object_attach_property(&connector->base,
- dev->mode_config.tv_top_margin_property,
- state->tv.margins.top);
- drm_object_attach_property(&connector->base,
- dev->mode_config.tv_right_margin_property,
- state->tv.margins.right);
- drm_object_attach_property(&connector->base,
- dev->mode_config.tv_bottom_margin_property,
- state->tv.margins.bottom);
+ intel_tv_add_properties(connector);
}
diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c
index 269f9792390d..9d3b77b41b5c 100644
--- a/drivers/gpu/drm/i915/display/intel_vdsc.c
+++ b/drivers/gpu/drm/i915/display/intel_vdsc.c
@@ -10,6 +10,7 @@
#include <drm/display/drm_dsc_helper.h>
#include "i915_drv.h"
+#include "i915_reg.h"
#include "intel_crtc.h"
#include "intel_de.h"
#include "intel_display_types.h"
diff --git a/drivers/gpu/drm/i915/display/intel_vga.c b/drivers/gpu/drm/i915/display/intel_vga.c
index b5d058404c14..a69bfcac9a94 100644
--- a/drivers/gpu/drm/i915/display/intel_vga.c
+++ b/drivers/gpu/drm/i915/display/intel_vga.c
@@ -10,6 +10,7 @@
#include <video/vga.h>
#include "i915_drv.h"
+#include "i915_reg.h"
#include "intel_de.h"
#include "intel_vga.h"
diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c
index 5eac99021875..7b1357e82b69 100644
--- a/drivers/gpu/drm/i915/display/intel_vrr.c
+++ b/drivers/gpu/drm/i915/display/intel_vrr.c
@@ -5,6 +5,7 @@
*/
#include "i915_drv.h"
+#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_vrr.h"
diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c
index 4092679be21e..d7390067b7d4 100644
--- a/drivers/gpu/drm/i915/display/skl_scaler.c
+++ b/drivers/gpu/drm/i915/display/skl_scaler.c
@@ -2,6 +2,8 @@
/*
* Copyright © 2020 Intel Corporation
*/
+
+#include "i915_reg.h"
#include "intel_de.h"
#include "intel_display_types.h"
#include "intel_fb.h"
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c
index 7cb713043408..76490cc59d8f 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.c
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c
@@ -9,6 +9,8 @@
#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_types.h"
@@ -246,6 +248,11 @@ bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv,
icl_nv12_y_plane_mask(dev_priv) & BIT(plane_id);
}
+u8 icl_hdr_plane_mask(void)
+{
+ return BIT(PLANE_PRIMARY) | BIT(PLANE_SPRITE0) | BIT(PLANE_SPRITE1);
+}
+
bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id)
{
return DISPLAY_VER(dev_priv) >= 11 &&
diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.h b/drivers/gpu/drm/i915/display/skl_universal_plane.h
index 351040b64dc7..be64c201f9b3 100644
--- a/drivers/gpu/drm/i915/display/skl_universal_plane.h
+++ b/drivers/gpu/drm/i915/display/skl_universal_plane.h
@@ -30,6 +30,7 @@ int skl_calc_main_surface_offset(const struct intel_plane_state *plane_state,
bool icl_is_nv12_y_plane(struct drm_i915_private *dev_priv,
enum plane_id plane_id);
+u8 icl_hdr_plane_mask(void);
bool icl_is_hdr_plane(struct drm_i915_private *dev_priv, enum plane_id plane_id);
#endif
diff --git a/drivers/gpu/drm/i915/display/skl_watermark.c b/drivers/gpu/drm/i915/display/skl_watermark.c
index 18178b01375e..e0766d1be966 100644
--- a/drivers/gpu/drm/i915/display/skl_watermark.c
+++ b/drivers/gpu/drm/i915/display/skl_watermark.c
@@ -1706,26 +1706,10 @@ skl_compute_wm_params(const struct intel_crtc_state *crtc_state,
return -EINVAL;
}
- wp->y_tiled = modifier == I915_FORMAT_MOD_Y_TILED ||
- modifier == I915_FORMAT_MOD_4_TILED ||
- modifier == I915_FORMAT_MOD_Yf_TILED ||
- modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
- modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
- modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
- modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS ||
- modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC ||
- modifier == I915_FORMAT_MOD_4_TILED_DG2_RC_CCS ||
- modifier == I915_FORMAT_MOD_4_TILED_DG2_MC_CCS ||
- modifier == I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC;
wp->x_tiled = modifier == I915_FORMAT_MOD_X_TILED;
- wp->rc_surface = modifier == I915_FORMAT_MOD_Y_TILED_CCS ||
- modifier == I915_FORMAT_MOD_Yf_TILED_CCS ||
- modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS ||
- modifier == I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS ||
- modifier == I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC ||
- modifier == I915_FORMAT_MOD_4_TILED_DG2_RC_CCS ||
- modifier == I915_FORMAT_MOD_4_TILED_DG2_MC_CCS ||
- modifier == I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC;
+ wp->y_tiled = modifier != I915_FORMAT_MOD_X_TILED &&
+ intel_fb_is_tiled_modifier(modifier);
+ wp->rc_surface = intel_fb_is_ccs_modifier(modifier);
wp->is_planar = intel_format_info_is_yuv_semiplanar(format, modifier);
wp->width = width;
@@ -2498,7 +2482,7 @@ skl_compute_ddb(struct intel_atomic_state *state)
if (old_dbuf_state->joined_mbus != new_dbuf_state->joined_mbus) {
/* TODO: Implement vblank synchronized MBUS joining changes */
- ret = intel_modeset_all_pipes(state);
+ ret = intel_modeset_all_pipes(state, "MBUS joining change");
if (ret)
return ret;
}
@@ -2760,7 +2744,7 @@ static int skl_wm_add_affected_planes(struct intel_atomic_state *state,
* power well the hardware state will go out of sync
* with the software state.
*/
- if (!drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi) &&
+ if (!intel_crtc_needs_modeset(new_crtc_state) &&
skl_plane_selected_wm_equals(plane,
&old_crtc_state->wm.skl.optimal,
&new_crtc_state->wm.skl.optimal))
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c
index b3f5ca280ef2..84481030883a 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi.c
+++ b/drivers/gpu/drm/i915/display/vlv_dsi.c
@@ -31,6 +31,7 @@
#include <drm/drm_mipi_dsi.h>
#include "i915_drv.h"
+#include "i915_reg.h"
#include "intel_atomic.h"
#include "intel_backlight.h"
#include "intel_connector.h"
@@ -1659,19 +1660,10 @@ static const struct drm_connector_funcs intel_dsi_connector_funcs = {
static void vlv_dsi_add_properties(struct intel_connector *connector)
{
- struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
const struct drm_display_mode *fixed_mode =
intel_panel_preferred_fixed_mode(connector);
- u32 allowed_scalers;
- allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT) | BIT(DRM_MODE_SCALE_FULLSCREEN);
- if (!HAS_GMCH(dev_priv))
- allowed_scalers |= BIT(DRM_MODE_SCALE_CENTER);
-
- drm_connector_attach_scaling_mode_property(&connector->base,
- allowed_scalers);
-
- connector->base.state->scaling_mode = DRM_MODE_SCALE_ASPECT;
+ intel_attach_scaling_mode_property(&connector->base);
drm_connector_set_panel_orientation_with_quirk(&connector->base,
intel_dsi_get_panel_orientation(connector),
@@ -1854,7 +1846,6 @@ static void vlv_dphy_param_init(struct intel_dsi *intel_dsi)
void vlv_dsi_init(struct drm_i915_private *dev_priv)
{
- struct drm_device *dev = &dev_priv->drm;
struct intel_dsi *intel_dsi;
struct intel_encoder *intel_encoder;
struct drm_encoder *encoder;
@@ -1891,7 +1882,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
connector = &intel_connector->base;
- drm_encoder_init(dev, encoder, &intel_dsi_funcs, DRM_MODE_ENCODER_DSI,
+ drm_encoder_init(&dev_priv->drm, encoder, &intel_dsi_funcs, DRM_MODE_ENCODER_DSI,
"DSI %c", port_name(port));
intel_encoder->compute_config = intel_dsi_compute_config;
@@ -1974,20 +1965,18 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv)
intel_dsi_vbt_gpio_init(intel_dsi,
intel_dsi_get_hw_state(intel_encoder, &pipe));
- drm_connector_init(dev, connector, &intel_dsi_connector_funcs,
+ drm_connector_init(&dev_priv->drm, connector, &intel_dsi_connector_funcs,
DRM_MODE_CONNECTOR_DSI);
drm_connector_helper_add(connector, &intel_dsi_connector_helper_funcs);
connector->display_info.subpixel_order = SubPixelHorizontalRGB; /*XXX*/
- connector->interlace_allowed = false;
- connector->doublescan_allowed = false;
intel_connector_attach_encoder(intel_connector, intel_encoder);
- mutex_lock(&dev->mode_config.mutex);
+ mutex_lock(&dev_priv->drm.mode_config.mutex);
intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
- mutex_unlock(&dev->mode_config.mutex);
+ mutex_unlock(&dev_priv->drm.mode_config.mutex);
if (!intel_panel_preferred_fixed_mode(intel_connector)) {
drm_dbg_kms(&dev_priv->drm, "no fixed mode\n");
diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_regs.h b/drivers/gpu/drm/i915/display/vlv_dsi_regs.h
index e065b8f2ee08..abbe427e462e 100644
--- a/drivers/gpu/drm/i915/display/vlv_dsi_regs.h
+++ b/drivers/gpu/drm/i915/display/vlv_dsi_regs.h
@@ -6,7 +6,7 @@
#ifndef __VLV_DSI_REGS_H__
#define __VLV_DSI_REGS_H__
-#include "i915_reg_defs.h"
+#include "intel_display_reg_defs.h"
#define VLV_MIPI_BASE VLV_DISPLAY_BASE
#define BXT_MIPI_BASE 0x60000
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
index 0512afdd20d8..b3b398fe689c 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_clflush.c
@@ -113,7 +113,7 @@ bool i915_gem_clflush_object(struct drm_i915_gem_object *obj,
clflush = clflush_work_create(obj);
if (clflush) {
i915_sw_fence_await_reservation(&clflush->base.chain,
- obj->base.resv, NULL, true,
+ obj->base.resv, true,
i915_fence_timeout(i915),
I915_FENCE_GFP);
dma_resv_add_fence(obj->base.resv, &clflush->base.dma,
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index 1e29b1e6d186..7f2831efc798 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -546,7 +546,7 @@ set_proto_ctx_engines_bond(struct i915_user_extension __user *base, void *data)
}
if (intel_engine_uses_guc(master)) {
- DRM_DEBUG("bonding extension not supported with GuC submission");
+ drm_dbg(&i915->drm, "bonding extension not supported with GuC submission");
return -ENODEV;
}
@@ -1452,7 +1452,7 @@ static void engines_idle_release(struct i915_gem_context *ctx,
int err;
/* serialises with execbuf */
- set_bit(CONTEXT_CLOSED_BIT, &ce->flags);
+ intel_context_close(ce);
if (!intel_context_pin_if_active(ce))
continue;
@@ -2298,7 +2298,6 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
}
args->ctx_id = id;
- drm_dbg(&i915->drm, "HW context %d created\n", args->ctx_id);
return 0;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
index 824971a1ceec..fd556a076d05 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
@@ -25,43 +25,44 @@ static struct drm_i915_gem_object *dma_buf_to_obj(struct dma_buf *buf)
return to_intel_bo(buf->priv);
}
-static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attachment,
+static struct sg_table *i915_gem_map_dma_buf(struct dma_buf_attachment *attach,
enum dma_data_direction dir)
{
- struct drm_i915_gem_object *obj = dma_buf_to_obj(attachment->dmabuf);
- struct sg_table *st;
+ struct drm_i915_gem_object *obj = dma_buf_to_obj(attach->dmabuf);
+ struct sg_table *sgt;
struct scatterlist *src, *dst;
int ret, i;
- /* Copy sg so that we make an independent mapping */
- st = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
- if (st == NULL) {
+ /*
+ * Make a copy of the object's sgt, so that we can make an independent
+ * mapping
+ */
+ sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
+ if (!sgt) {
ret = -ENOMEM;
goto err;
}
- ret = sg_alloc_table(st, obj->mm.pages->orig_nents, GFP_KERNEL);
+ ret = sg_alloc_table(sgt, obj->mm.pages->orig_nents, GFP_KERNEL);
if (ret)
goto err_free;
- src = obj->mm.pages->sgl;
- dst = st->sgl;
- for (i = 0; i < obj->mm.pages->orig_nents; i++) {
+ dst = sgt->sgl;
+ for_each_sg(obj->mm.pages->sgl, src, obj->mm.pages->orig_nents, i) {
sg_set_page(dst, sg_page(src), src->length, 0);
dst = sg_next(dst);
- src = sg_next(src);
}
- ret = dma_map_sgtable(attachment->dev, st, dir, DMA_ATTR_SKIP_CPU_SYNC);
+ ret = dma_map_sgtable(attach->dev, sgt, dir, DMA_ATTR_SKIP_CPU_SYNC);
if (ret)
goto err_free_sg;
- return st;
+ return sgt;
err_free_sg:
- sg_free_table(st);
+ sg_free_table(sgt);
err_free:
- kfree(st);
+ kfree(sgt);
err:
return ERR_PTR(ret);
}
@@ -72,7 +73,7 @@ static int i915_gem_dmabuf_vmap(struct dma_buf *dma_buf,
struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
void *vaddr;
- vaddr = i915_gem_object_pin_map_unlocked(obj, I915_MAP_WB);
+ vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB);
if (IS_ERR(vaddr))
return PTR_ERR(vaddr);
@@ -96,6 +97,8 @@ static int i915_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *
struct drm_i915_private *i915 = to_i915(obj->base.dev);
int ret;
+ dma_resv_assert_held(dma_buf->resv);
+
if (obj->base.size < vma->vm_end - vma->vm_start)
return -EINVAL;
@@ -236,15 +239,14 @@ struct dma_buf *i915_gem_prime_export(struct drm_gem_object *gem_obj, int flags)
static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
{
struct drm_i915_private *i915 = to_i915(obj->base.dev);
- struct sg_table *pages;
- unsigned int sg_page_sizes;
+ struct sg_table *sgt;
assert_object_held(obj);
- pages = dma_buf_map_attachment(obj->base.import_attach,
- DMA_BIDIRECTIONAL);
- if (IS_ERR(pages))
- return PTR_ERR(pages);
+ sgt = dma_buf_map_attachment(obj->base.import_attach,
+ DMA_BIDIRECTIONAL);
+ if (IS_ERR(sgt))
+ return PTR_ERR(sgt);
/*
* DG1 is special here since it still snoops transactions even with
@@ -261,16 +263,15 @@ static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj)
(!HAS_LLC(i915) && !IS_DG1(i915)))
wbinvd_on_all_cpus();
- sg_page_sizes = i915_sg_dma_sizes(pages->sgl);
- __i915_gem_object_set_pages(obj, pages, sg_page_sizes);
+ __i915_gem_object_set_pages(obj, sgt);
return 0;
}
static void i915_gem_object_put_pages_dmabuf(struct drm_i915_gem_object *obj,
- struct sg_table *pages)
+ struct sg_table *sgt)
{
- dma_buf_unmap_attachment(obj->base.import_attach, pages,
+ dma_buf_unmap_attachment(obj->base.import_attach, sgt,
DMA_BIDIRECTIONAL);
}
@@ -313,7 +314,7 @@ struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev,
get_dma_buf(dma_buf);
obj = i915_gem_object_alloc();
- if (obj == NULL) {
+ if (!obj) {
ret = -ENOMEM;
goto fail_detach;
}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index 845023c14eb3..da09767fda07 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -30,6 +30,7 @@
#include "i915_gem_context.h"
#include "i915_gem_evict.h"
#include "i915_gem_ioctls.h"
+#include "i915_reg.h"
#include "i915_trace.h"
#include "i915_user_extensions.h"
@@ -53,13 +54,13 @@ enum {
#define DBG_FORCE_RELOC 0 /* choose one of the above! */
};
-/* __EXEC_OBJECT_NO_RESERVE is BIT(31), defined in i915_vma.h */
-#define __EXEC_OBJECT_HAS_PIN BIT(30)
-#define __EXEC_OBJECT_HAS_FENCE BIT(29)
-#define __EXEC_OBJECT_USERPTR_INIT BIT(28)
-#define __EXEC_OBJECT_NEEDS_MAP BIT(27)
-#define __EXEC_OBJECT_NEEDS_BIAS BIT(26)
-#define __EXEC_OBJECT_INTERNAL_FLAGS (~0u << 26) /* all of the above + */
+/* __EXEC_OBJECT_ flags > BIT(29) defined in i915_vma.h */
+#define __EXEC_OBJECT_HAS_PIN BIT(29)
+#define __EXEC_OBJECT_HAS_FENCE BIT(28)
+#define __EXEC_OBJECT_USERPTR_INIT BIT(27)
+#define __EXEC_OBJECT_NEEDS_MAP BIT(26)
+#define __EXEC_OBJECT_NEEDS_BIAS BIT(25)
+#define __EXEC_OBJECT_INTERNAL_FLAGS (~0u << 25) /* all of the above + */
#define __EXEC_OBJECT_RESERVED (__EXEC_OBJECT_HAS_PIN | __EXEC_OBJECT_HAS_FENCE)
#define __EXEC_HAS_RELOC BIT(31)
@@ -2101,7 +2102,8 @@ static int eb_move_to_gpu(struct i915_execbuffer *eb)
eb->composite_fence ?
eb->composite_fence :
&eb->requests[j]->fence,
- flags | __EXEC_OBJECT_NO_RESERVE);
+ flags | __EXEC_OBJECT_NO_RESERVE |
+ __EXEC_OBJECT_NO_REQUEST_AWAIT);
}
}
@@ -2148,7 +2150,8 @@ err_skip:
return err;
}
-static int i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec)
+static int i915_gem_check_execbuffer(struct drm_i915_private *i915,
+ struct drm_i915_gem_execbuffer2 *exec)
{
if (exec->flags & __I915_EXEC_ILLEGAL_FLAGS)
return -EINVAL;
@@ -2161,7 +2164,7 @@ static int i915_gem_check_execbuffer(struct drm_i915_gem_execbuffer2 *exec)
}
if (exec->DR4 == 0xffffffff) {
- DRM_DEBUG("UXA submitting garbage DR4, fixing up\n");
+ drm_dbg(&i915->drm, "UXA submitting garbage DR4, fixing up\n");
exec->DR4 = 0;
}
if (exec->DR1 || exec->DR4)
@@ -2424,7 +2427,7 @@ gen8_dispatch_bsd_engine(struct drm_i915_private *dev_priv,
/* Check whether the file_priv has already selected one ring. */
if ((int)file_priv->bsd_engine < 0)
file_priv->bsd_engine =
- prandom_u32_max(num_vcs_engines(dev_priv));
+ get_random_u32_below(num_vcs_engines(dev_priv));
return file_priv->bsd_engine;
}
@@ -2799,7 +2802,8 @@ add_timeline_fence_array(struct i915_execbuffer *eb,
syncobj = drm_syncobj_find(eb->file, user_fence.handle);
if (!syncobj) {
- DRM_DEBUG("Invalid syncobj handle provided\n");
+ drm_dbg(&eb->i915->drm,
+ "Invalid syncobj handle provided\n");
return -ENOENT;
}
@@ -2807,7 +2811,8 @@ add_timeline_fence_array(struct i915_execbuffer *eb,
if (!fence && user_fence.flags &&
!(user_fence.flags & I915_EXEC_FENCE_SIGNAL)) {
- DRM_DEBUG("Syncobj handle has no fence\n");
+ drm_dbg(&eb->i915->drm,
+ "Syncobj handle has no fence\n");
drm_syncobj_put(syncobj);
return -EINVAL;
}
@@ -2816,7 +2821,9 @@ add_timeline_fence_array(struct i915_execbuffer *eb,
err = dma_fence_chain_find_seqno(&fence, point);
if (err && !(user_fence.flags & I915_EXEC_FENCE_SIGNAL)) {
- DRM_DEBUG("Syncobj handle missing requested point %llu\n", point);
+ drm_dbg(&eb->i915->drm,
+ "Syncobj handle missing requested point %llu\n",
+ point);
dma_fence_put(fence);
drm_syncobj_put(syncobj);
return err;
@@ -2842,7 +2849,8 @@ add_timeline_fence_array(struct i915_execbuffer *eb,
* 0) would break the timeline.
*/
if (user_fence.flags & I915_EXEC_FENCE_WAIT) {
- DRM_DEBUG("Trying to wait & signal the same timeline point.\n");
+ drm_dbg(&eb->i915->drm,
+ "Trying to wait & signal the same timeline point.\n");
dma_fence_put(fence);
drm_syncobj_put(syncobj);
return -EINVAL;
@@ -2913,14 +2921,16 @@ static int add_fence_array(struct i915_execbuffer *eb)
syncobj = drm_syncobj_find(eb->file, user_fence.handle);
if (!syncobj) {
- DRM_DEBUG("Invalid syncobj handle provided\n");
+ drm_dbg(&eb->i915->drm,
+ "Invalid syncobj handle provided\n");
return -ENOENT;
}
if (user_fence.flags & I915_EXEC_FENCE_WAIT) {
fence = drm_syncobj_fence_get(syncobj);
if (!fence) {
- DRM_DEBUG("Syncobj handle has no fence\n");
+ drm_dbg(&eb->i915->drm,
+ "Syncobj handle has no fence\n");
drm_syncobj_put(syncobj);
return -EINVAL;
}
@@ -2954,11 +2964,6 @@ await_fence_array(struct i915_execbuffer *eb,
int err;
for (n = 0; n < eb->num_fences; n++) {
- struct drm_syncobj *syncobj;
- unsigned int flags;
-
- syncobj = ptr_unpack_bits(eb->fences[n].syncobj, &flags, 2);
-
if (!eb->fences[n].dma_fence)
continue;
@@ -3520,7 +3525,7 @@ i915_gem_execbuffer2_ioctl(struct drm_device *dev, void *data,
return -EINVAL;
}
- err = i915_gem_check_execbuffer(args);
+ err = i915_gem_check_execbuffer(i915, args);
if (err)
return err;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_internal.c b/drivers/gpu/drm/i915/gem/i915_gem_internal.c
index 629acb403a2c..f66bcefc09ec 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_internal.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_internal.c
@@ -35,7 +35,6 @@ static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj)
struct drm_i915_private *i915 = to_i915(obj->base.dev);
struct sg_table *st;
struct scatterlist *sg;
- unsigned int sg_page_sizes;
unsigned int npages;
int max_order = MAX_ORDER;
unsigned int max_segment;
@@ -64,7 +63,6 @@ create_st:
sg = st->sgl;
st->nents = 0;
- sg_page_sizes = 0;
do {
int order = min(fls(npages) - 1, max_order);
@@ -83,7 +81,6 @@ create_st:
} while (1);
sg_set_page(sg, page, PAGE_SIZE << order, 0);
- sg_page_sizes |= PAGE_SIZE << order;
st->nents++;
npages -= 1 << order;
@@ -105,7 +102,7 @@ create_st:
goto err;
}
- __i915_gem_object_set_pages(obj, st, sg_page_sizes);
+ __i915_gem_object_set_pages(obj, st);
return 0;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
index 73d9eda1d6b7..c29efdef8313 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c
@@ -330,7 +330,7 @@ retry:
if (ret)
goto err_rpm;
- ret = intel_gt_reset_trylock(ggtt->vm.gt, &srcu);
+ ret = intel_gt_reset_lock_interruptible(ggtt->vm.gt, &srcu);
if (ret)
goto err_pages;
@@ -413,7 +413,7 @@ retry:
vma->mmo = mmo;
if (CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND)
- intel_wakeref_auto(&to_gt(i915)->userfault_wakeref,
+ intel_wakeref_auto(&i915->runtime_pm.userfault_wakeref,
msecs_to_jiffies_timeout(CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND));
if (write) {
@@ -557,11 +557,13 @@ void i915_gem_object_runtime_pm_release_mmap_offset(struct drm_i915_gem_object *
drm_vma_node_unmap(&bo->base.vma_node, bdev->dev_mapping);
- if (obj->userfault_count) {
- /* rpm wakeref provide exclusive access */
- list_del(&obj->userfault_link);
- obj->userfault_count = 0;
- }
+ /*
+ * We have exclusive access here via runtime suspend. All other callers
+ * must first grab the rpm wakeref.
+ */
+ GEM_BUG_ON(!obj->userfault_count);
+ list_del(&obj->userfault_link);
+ obj->userfault_count = 0;
}
void i915_gem_object_release_mmap_offset(struct drm_i915_gem_object *obj)
@@ -587,13 +589,6 @@ void i915_gem_object_release_mmap_offset(struct drm_i915_gem_object *obj)
spin_lock(&obj->mmo.lock);
}
spin_unlock(&obj->mmo.lock);
-
- if (obj->userfault_count) {
- mutex_lock(&to_gt(to_i915(obj->base.dev))->lmem_userfault_lock);
- list_del(&obj->userfault_link);
- mutex_unlock(&to_gt(to_i915(obj->base.dev))->lmem_userfault_lock);
- obj->userfault_count = 0;
- }
}
static struct i915_mmap_offset *
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index 369006c5317f..733696057761 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -290,7 +290,21 @@ void __i915_gem_object_pages_fini(struct drm_i915_gem_object *obj)
__i915_gem_object_free_mmaps(obj);
atomic_set(&obj->mm.pages_pin_count, 0);
+
+ /*
+ * dma_buf_unmap_attachment() requires reservation to be
+ * locked. The imported GEM shouldn't share reservation lock
+ * and ttm_bo_cleanup_memtype_use() shouldn't be invoked for
+ * dma-buf, so it's safe to take the lock.
+ */
+ if (obj->base.import_attach)
+ i915_gem_object_lock(obj, NULL);
+
__i915_gem_object_put_pages(obj);
+
+ if (obj->base.import_attach)
+ i915_gem_object_unlock(obj);
+
GEM_BUG_ON(i915_gem_object_has_pages(obj));
}
@@ -444,6 +458,16 @@ i915_gem_object_read_from_page_iomap(struct drm_i915_gem_object *obj, u64 offset
io_mapping_unmap(src_map);
}
+static bool object_has_mappable_iomem(struct drm_i915_gem_object *obj)
+{
+ GEM_BUG_ON(!i915_gem_object_has_iomem(obj));
+
+ if (IS_DGFX(to_i915(obj->base.dev)))
+ return i915_ttm_resource_mappable(i915_gem_to_ttm(obj)->resource);
+
+ return true;
+}
+
/**
* i915_gem_object_read_from_page - read data from the page of a GEM object
* @obj: GEM object to read from
@@ -466,7 +490,7 @@ int i915_gem_object_read_from_page(struct drm_i915_gem_object *obj, u64 offset,
if (i915_gem_object_has_struct_page(obj))
i915_gem_object_read_from_page_kmap(obj, offset, dst, size);
- else if (i915_gem_object_has_iomem(obj))
+ else if (i915_gem_object_has_iomem(obj) && object_has_mappable_iomem(obj))
i915_gem_object_read_from_page_iomap(obj, offset, dst, size);
else
return -ENODEV;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index 1723af9b0f6a..3db53769864c 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -403,8 +403,7 @@ i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj,
unsigned long n);
void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
- struct sg_table *pages,
- unsigned int sg_page_sizes);
+ struct sg_table *pages);
int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj);
int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj);
@@ -482,6 +481,10 @@ void *__must_check i915_gem_object_pin_map(struct drm_i915_gem_object *obj,
void *__must_check i915_gem_object_pin_map_unlocked(struct drm_i915_gem_object *obj,
enum i915_map_type type);
+enum i915_map_type i915_coherent_map_type(struct drm_i915_private *i915,
+ struct drm_i915_gem_object *obj,
+ bool always_coherent);
+
void __i915_gem_object_flush_map(struct drm_i915_gem_object *obj,
unsigned long offset,
unsigned long size);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pages.c b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
index 4df50b049cea..05a27723ebb8 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_pages.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_pages.c
@@ -16,8 +16,7 @@
#include "i915_gem_mman.h"
void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
- struct sg_table *pages,
- unsigned int sg_page_sizes)
+ struct sg_table *pages)
{
struct drm_i915_private *i915 = to_i915(obj->base.dev);
unsigned long supported = RUNTIME_INFO(i915)->page_sizes;
@@ -45,8 +44,8 @@ void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
obj->mm.pages = pages;
- GEM_BUG_ON(!sg_page_sizes);
- obj->mm.page_sizes.phys = sg_page_sizes;
+ obj->mm.page_sizes.phys = i915_sg_dma_sizes(pages->sgl);
+ GEM_BUG_ON(!obj->mm.page_sizes.phys);
/*
* Calculate the supported page-sizes which fit into the given
@@ -466,6 +465,18 @@ void *i915_gem_object_pin_map_unlocked(struct drm_i915_gem_object *obj,
return ret;
}
+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))
+ return I915_MAP_WC;
+ if (HAS_LLC(i915) || always_coherent)
+ return I915_MAP_WB;
+ else
+ return I915_MAP_WC;
+}
+
void __i915_gem_object_flush_map(struct drm_i915_gem_object *obj,
unsigned long offset,
unsigned long size)
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
index 0d0e46dae559..68453572275b 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_phys.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_phys.c
@@ -79,7 +79,7 @@ static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj)
/* We're no longer struct page backed */
obj->mem_flags &= ~I915_BO_FLAG_STRUCT_PAGE;
- __i915_gem_object_set_pages(obj, st, sg->length);
+ __i915_gem_object_set_pages(obj, st);
return 0;
@@ -209,11 +209,8 @@ static int i915_gem_object_shmem_to_phys(struct drm_i915_gem_object *obj)
return 0;
err_xfer:
- if (!IS_ERR_OR_NULL(pages)) {
- unsigned int sg_page_sizes = i915_sg_dma_sizes(pages->sgl);
-
- __i915_gem_object_set_pages(obj, pages, sg_page_sizes);
- }
+ if (!IS_ERR_OR_NULL(pages))
+ __i915_gem_object_set_pages(obj, pages);
return err;
}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_pm.c b/drivers/gpu/drm/i915/gem/i915_gem_pm.c
index 3428f735e786..0d812f4d787d 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_pm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_pm.c
@@ -22,9 +22,12 @@
void i915_gem_suspend(struct drm_i915_private *i915)
{
+ struct intel_gt *gt;
+ unsigned int i;
+
GEM_TRACE("%s\n", dev_name(i915->drm.dev));
- intel_wakeref_auto(&to_gt(i915)->userfault_wakeref, 0);
+ intel_wakeref_auto(&i915->runtime_pm.userfault_wakeref, 0);
flush_workqueue(i915->wq);
/*
@@ -36,7 +39,8 @@ void i915_gem_suspend(struct drm_i915_private *i915)
* state. Fortunately, the kernel_context is disposable and we do
* not rely on its state.
*/
- intel_gt_suspend_prepare(to_gt(i915));
+ for_each_gt(gt, i915, i)
+ intel_gt_suspend_prepare(gt);
i915_gem_drain_freed_objects(i915);
}
@@ -131,7 +135,9 @@ void i915_gem_suspend_late(struct drm_i915_private *i915)
&i915->mm.purge_list,
NULL
}, **phase;
+ struct intel_gt *gt;
unsigned long flags;
+ unsigned int i;
bool flush = false;
/*
@@ -154,7 +160,8 @@ void i915_gem_suspend_late(struct drm_i915_private *i915)
* machine in an unusable condition.
*/
- intel_gt_suspend_late(to_gt(i915));
+ for_each_gt(gt, i915, i)
+ intel_gt_suspend_late(gt);
spin_lock_irqsave(&i915->mm.obj_lock, flags);
for (phase = phases; *phase; phase++) {
@@ -212,7 +219,8 @@ int i915_gem_freeze_late(struct drm_i915_private *i915)
void i915_gem_resume(struct drm_i915_private *i915)
{
- int ret;
+ struct intel_gt *gt;
+ int ret, i, j;
GEM_TRACE("%s\n", dev_name(i915->drm.dev));
@@ -224,8 +232,25 @@ void i915_gem_resume(struct drm_i915_private *i915)
* guarantee that the context image is complete. So let's just reset
* it and start again.
*/
- intel_gt_resume(to_gt(i915));
+ for_each_gt(gt, i915, i)
+ if (intel_gt_resume(gt))
+ goto err_wedged;
ret = lmem_restore(i915, I915_TTM_BACKUP_ALLOW_GPU);
GEM_WARN_ON(ret);
+
+ return;
+
+err_wedged:
+ for_each_gt(gt, i915, j) {
+ if (!intel_gt_is_wedged(gt)) {
+ dev_err(i915->drm.dev,
+ "Failed to re-initialize GPU[%u], declaring it wedged!\n",
+ j);
+ intel_gt_set_wedged(gt);
+ }
+
+ if (j == i)
+ break;
+ }
}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
index 2f7804492cd5..9c759df700ca 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c
@@ -247,7 +247,7 @@ rebuild_st:
if (i915_gem_object_can_bypass_llc(obj))
obj->cache_dirty = true;
- __i915_gem_object_set_pages(obj, st, i915_sg_dma_sizes(st->sgl));
+ __i915_gem_object_set_pages(obj, st);
return 0;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
index acc561c0f0aa..bc9521078807 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
@@ -77,22 +77,26 @@ void i915_gem_stolen_remove_node(struct drm_i915_private *i915,
mutex_unlock(&i915->mm.stolen_lock);
}
-static int i915_adjust_stolen(struct drm_i915_private *i915,
- struct resource *dsm)
+static bool valid_stolen_size(struct drm_i915_private *i915, struct resource *dsm)
+{
+ return (dsm->start != 0 || HAS_LMEMBAR_SMEM_STOLEN(i915)) && dsm->end > dsm->start;
+}
+
+static int adjust_stolen(struct drm_i915_private *i915,
+ struct resource *dsm)
{
struct i915_ggtt *ggtt = to_gt(i915)->ggtt;
struct intel_uncore *uncore = ggtt->vm.gt->uncore;
- struct resource *r;
- if (dsm->start == 0 || dsm->end <= dsm->start)
+ if (!valid_stolen_size(i915, dsm))
return -EINVAL;
/*
+ * Make sure we don't clobber the GTT if it's within stolen memory
+ *
* TODO: We have yet too encounter the case where the GTT wasn't at the
* end of stolen. With that assumption we could simplify this.
*/
-
- /* Make sure we don't clobber the GTT if it's within stolen memory */
if (GRAPHICS_VER(i915) <= 4 &&
!IS_G33(i915) && !IS_PINEVIEW(i915) && !IS_G4X(i915)) {
struct resource stolen[2] = {*dsm, *dsm};
@@ -131,12 +135,25 @@ static int i915_adjust_stolen(struct drm_i915_private *i915,
}
}
+ if (!valid_stolen_size(i915, dsm))
+ return -EINVAL;
+
+ return 0;
+}
+
+static int request_smem_stolen(struct drm_i915_private *i915,
+ struct resource *dsm)
+{
+ struct resource *r;
+
/*
- * With stolen lmem, we don't need to check if the address range
- * overlaps with the non-stolen system memory range, since lmem is local
- * to the gpu.
+ * With stolen lmem, we don't need to request system memory for the
+ * address range since it's local to the gpu.
+ *
+ * Starting MTL, in IGFX devices the stolen memory is exposed via
+ * LMEMBAR and shall be considered similar to stolen lmem.
*/
- if (HAS_LMEM(i915))
+ if (HAS_LMEM(i915) || HAS_LMEMBAR_SMEM_STOLEN(i915))
return 0;
/*
@@ -371,8 +388,6 @@ static void icl_get_stolen_reserved(struct drm_i915_private *i915,
drm_dbg(&i915->drm, "GEN6_STOLEN_RESERVED = 0x%016llx\n", reg_val);
- *base = reg_val & GEN11_STOLEN_RESERVED_ADDR_MASK;
-
switch (reg_val & GEN8_STOLEN_RESERVED_SIZE_MASK) {
case GEN8_STOLEN_RESERVED_1M:
*size = 1024 * 1024;
@@ -390,41 +405,30 @@ static void icl_get_stolen_reserved(struct drm_i915_private *i915,
*size = 8 * 1024 * 1024;
MISSING_CASE(reg_val & GEN8_STOLEN_RESERVED_SIZE_MASK);
}
+
+ if (HAS_LMEMBAR_SMEM_STOLEN(i915))
+ /* the base is initialized to stolen top so subtract size to get base */
+ *base -= *size;
+ else
+ *base = reg_val & GEN11_STOLEN_RESERVED_ADDR_MASK;
}
-static int i915_gem_init_stolen(struct intel_memory_region *mem)
+/*
+ * Initialize i915->dsm_reserved to contain the reserved space within the Data
+ * Stolen Memory. This is a range on the top of DSM that is reserved, not to
+ * be used by driver, so must be excluded from the region passed to the
+ * allocator later. In the spec this is also called as WOPCM.
+ *
+ * Our expectation is that the reserved space is at the top of the stolen
+ * region, as it has been the case for every platform, and *never* at the
+ * bottom, so the calculation here can be simplified.
+ */
+static int init_reserved_stolen(struct drm_i915_private *i915)
{
- struct drm_i915_private *i915 = mem->i915;
struct intel_uncore *uncore = &i915->uncore;
resource_size_t reserved_base, stolen_top;
- resource_size_t reserved_total, reserved_size;
-
- mutex_init(&i915->mm.stolen_lock);
-
- if (intel_vgpu_active(i915)) {
- drm_notice(&i915->drm,
- "%s, disabling use of stolen memory\n",
- "iGVT-g active");
- return 0;
- }
-
- if (i915_vtd_active(i915) && GRAPHICS_VER(i915) < 8) {
- drm_notice(&i915->drm,
- "%s, disabling use of stolen memory\n",
- "DMAR active");
- return 0;
- }
-
- if (resource_size(&mem->region) == 0)
- return 0;
-
- i915->dsm = mem->region;
-
- if (i915_adjust_stolen(i915, &i915->dsm))
- return 0;
-
- GEM_BUG_ON(i915->dsm.start == 0);
- GEM_BUG_ON(i915->dsm.end <= i915->dsm.start);
+ resource_size_t reserved_size;
+ int ret = 0;
stolen_top = i915->dsm.end + 1;
reserved_base = stolen_top;
@@ -455,17 +459,16 @@ static int i915_gem_init_stolen(struct intel_memory_region *mem)
&reserved_base, &reserved_size);
}
- /*
- * Our expectation is that the reserved space is at the top of the
- * stolen region and *never* at the bottom. If we see !reserved_base,
- * it likely means we failed to read the registers correctly.
- */
+ /* No reserved stolen */
+ if (reserved_base == stolen_top)
+ goto bail_out;
+
if (!reserved_base) {
drm_err(&i915->drm,
"inconsistent reservation %pa + %pa; ignoring\n",
&reserved_base, &reserved_size);
- reserved_base = stolen_top;
- reserved_size = 0;
+ ret = -EINVAL;
+ goto bail_out;
}
i915->dsm_reserved =
@@ -475,19 +478,55 @@ static int i915_gem_init_stolen(struct intel_memory_region *mem)
drm_err(&i915->drm,
"Stolen reserved area %pR outside stolen memory %pR\n",
&i915->dsm_reserved, &i915->dsm);
- return 0;
+ ret = -EINVAL;
+ goto bail_out;
}
+ return 0;
+
+bail_out:
+ i915->dsm_reserved =
+ (struct resource)DEFINE_RES_MEM(reserved_base, 0);
+
+ return ret;
+}
+
+static int i915_gem_init_stolen(struct intel_memory_region *mem)
+{
+ struct drm_i915_private *i915 = mem->i915;
+
+ mutex_init(&i915->mm.stolen_lock);
+
+ if (intel_vgpu_active(i915)) {
+ drm_notice(&i915->drm,
+ "%s, disabling use of stolen memory\n",
+ "iGVT-g active");
+ return -ENOSPC;
+ }
+
+ if (i915_vtd_active(i915) && GRAPHICS_VER(i915) < 8) {
+ drm_notice(&i915->drm,
+ "%s, disabling use of stolen memory\n",
+ "DMAR active");
+ return -ENOSPC;
+ }
+
+ if (adjust_stolen(i915, &mem->region))
+ return -ENOSPC;
+
+ if (request_smem_stolen(i915, &mem->region))
+ return -ENOSPC;
+
+ i915->dsm = mem->region;
+
+ if (init_reserved_stolen(i915))
+ return -ENOSPC;
+
/* Exclude the reserved region from driver use */
- mem->region.end = reserved_base - 1;
+ mem->region.end = i915->dsm_reserved.start - 1;
mem->io_size = min(mem->io_size, resource_size(&mem->region));
- /* It is possible for the reserved area to end before the end of stolen
- * memory, so just consider the start. */
- reserved_total = stolen_top - reserved_base;
-
- i915->stolen_usable_size =
- resource_size(&i915->dsm) - reserved_total;
+ i915->stolen_usable_size = resource_size(&mem->region);
drm_dbg(&i915->drm,
"Memory reserved for graphics device: %lluK, usable: %lluK\n",
@@ -495,7 +534,7 @@ static int i915_gem_init_stolen(struct intel_memory_region *mem)
(u64)i915->stolen_usable_size >> 10);
if (i915->stolen_usable_size == 0)
- return 0;
+ return -ENOSPC;
/* Basic memrange allocator for stolen space. */
drm_mm_init(&i915->mm.stolen, 0, i915->stolen_usable_size);
@@ -589,7 +628,7 @@ static int i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj)
sg_dma_len(pages->sgl),
POISON_INUSE);
- __i915_gem_object_set_pages(obj, pages, obj->stolen->size);
+ __i915_gem_object_set_pages(obj, pages);
return 0;
}
@@ -733,11 +772,17 @@ i915_gem_object_create_stolen(struct drm_i915_private *i915,
static int init_stolen_smem(struct intel_memory_region *mem)
{
+ int err;
+
/*
* Initialise stolen early so that we may reserve preallocated
* objects for the BIOS to KMS transition.
*/
- return i915_gem_init_stolen(mem);
+ err = i915_gem_init_stolen(mem);
+ if (err)
+ drm_dbg(&mem->i915->drm, "Skip stolen region: failed to setup\n");
+
+ return 0;
}
static int release_stolen_smem(struct intel_memory_region *mem)
@@ -754,26 +799,25 @@ static const struct intel_memory_region_ops i915_region_stolen_smem_ops = {
static int init_stolen_lmem(struct intel_memory_region *mem)
{
+ struct drm_i915_private *i915 = mem->i915;
int err;
if (GEM_WARN_ON(resource_size(&mem->region) == 0))
- return -ENODEV;
+ return 0;
- /*
- * TODO: For stolen lmem we mostly just care about populating the dsm
- * related bits and setting up the drm_mm allocator for the range.
- * Perhaps split up i915_gem_init_stolen() for this.
- */
err = i915_gem_init_stolen(mem);
- if (err)
- return err;
+ if (err) {
+ drm_dbg(&mem->i915->drm, "Skip stolen region: failed to setup\n");
+ return 0;
+ }
- if (mem->io_size && !io_mapping_init_wc(&mem->iomap,
- mem->io_start,
- mem->io_size)) {
- err = -EIO;
+ if (mem->io_size &&
+ !io_mapping_init_wc(&mem->iomap, mem->io_start, mem->io_size))
goto err_cleanup;
- }
+
+ drm_dbg(&i915->drm, "Stolen Local memory IO start: %pa\n",
+ &mem->io_start);
+ drm_dbg(&i915->drm, "Stolen Local DSM base: %pa\n", &mem->region.start);
return 0;
@@ -796,6 +840,29 @@ static const struct intel_memory_region_ops i915_region_stolen_lmem_ops = {
.init_object = _i915_gem_object_stolen_init,
};
+static int mtl_get_gms_size(struct intel_uncore *uncore)
+{
+ u16 ggc, gms;
+
+ ggc = intel_uncore_read16(uncore, GGC);
+
+ /* check GGMS, should be fixed 0x3 (8MB) */
+ if ((ggc & GGMS_MASK) != GGMS_MASK)
+ return -EIO;
+
+ /* return valid GMS value, -EIO if invalid */
+ gms = REG_FIELD_GET(GMS_MASK, ggc);
+ switch (gms) {
+ case 0x0 ... 0x04:
+ return gms * 32;
+ case 0xf0 ... 0xfe:
+ return (gms - 0xf0 + 1) * 4;
+ default:
+ MISSING_CASE(gms);
+ return -EIO;
+ }
+}
+
struct intel_memory_region *
i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type,
u16 instance)
@@ -806,6 +873,7 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type,
struct intel_memory_region *mem;
resource_size_t io_start, io_size;
resource_size_t min_page_size;
+ int ret;
if (WARN_ON_ONCE(instance))
return ERR_PTR(-ENODEV);
@@ -813,12 +881,8 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type,
if (!i915_pci_resource_valid(pdev, GEN12_LMEM_BAR))
return ERR_PTR(-ENXIO);
- /* Use DSM base address instead for stolen memory */
- dsm_base = intel_uncore_read64(uncore, GEN12_DSMBASE);
- if (IS_DG1(uncore->i915)) {
+ if (HAS_LMEMBAR_SMEM_STOLEN(i915) || IS_DG1(i915)) {
lmem_size = pci_resource_len(pdev, GEN12_LMEM_BAR);
- if (WARN_ON(lmem_size < dsm_base))
- return ERR_PTR(-ENODEV);
} else {
resource_size_t lmem_range;
@@ -827,13 +891,39 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type,
lmem_size *= SZ_1G;
}
- dsm_size = lmem_size - dsm_base;
- if (pci_resource_len(pdev, GEN12_LMEM_BAR) < lmem_size) {
+ if (HAS_LMEMBAR_SMEM_STOLEN(i915)) {
+ /*
+ * MTL dsm size is in GGC register.
+ * Also MTL uses offset to DSMBASE in ptes, so i915
+ * uses dsm_base = 0 to setup stolen region.
+ */
+ ret = mtl_get_gms_size(uncore);
+ if (ret < 0) {
+ drm_err(&i915->drm, "invalid MTL GGC register setting\n");
+ return ERR_PTR(ret);
+ }
+
+ dsm_base = 0;
+ dsm_size = (resource_size_t)(ret * SZ_1M);
+
+ GEM_BUG_ON(pci_resource_len(pdev, GEN12_LMEM_BAR) != SZ_256M);
+ GEM_BUG_ON((dsm_size + SZ_8M) > lmem_size);
+ } else {
+ /* Use DSM base address instead for stolen memory */
+ dsm_base = intel_uncore_read64(uncore, GEN12_DSMBASE) & GEN12_BDSM_MASK;
+ if (WARN_ON(lmem_size < dsm_base))
+ return ERR_PTR(-ENODEV);
+ dsm_size = lmem_size - dsm_base;
+ }
+
+ io_size = dsm_size;
+ if (HAS_LMEMBAR_SMEM_STOLEN(i915)) {
+ io_start = pci_resource_start(pdev, GEN12_LMEM_BAR) + SZ_8M;
+ } else if (pci_resource_len(pdev, GEN12_LMEM_BAR) < lmem_size) {
io_start = 0;
io_size = 0;
} else {
io_start = pci_resource_start(pdev, GEN12_LMEM_BAR) + dsm_base;
- io_size = dsm_size;
}
min_page_size = HAS_64K_PAGES(i915) ? I915_GTT_PAGE_SIZE_64K :
@@ -847,16 +937,6 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type,
if (IS_ERR(mem))
return mem;
- /*
- * TODO: consider creating common helper to just print all the
- * interesting stuff from intel_memory_region, which we can use for all
- * our probed regions.
- */
-
- drm_dbg(&i915->drm, "Stolen Local memory IO start: %pa\n",
- &mem->io_start);
- drm_dbg(&i915->drm, "Stolen Local DSM base: %pa\n", &dsm_base);
-
intel_memory_region_set_name(mem, "stolen-local");
mem->private = true;
@@ -881,6 +961,7 @@ i915_gem_stolen_smem_setup(struct drm_i915_private *i915, u16 type,
intel_memory_region_set_name(mem, "stolen-system");
mem->private = true;
+
return mem;
}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
index 0d6d640225fc..1e50fb0d6bfc 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c
@@ -279,7 +279,7 @@ static struct ttm_tt *i915_ttm_tt_create(struct ttm_buffer_object *bo,
struct i915_ttm_tt *i915_tt;
int ret;
- if (!obj)
+ if (i915_ttm_is_ghost_object(bo))
return NULL;
i915_tt = kzalloc(sizeof(*i915_tt), GFP_KERNEL);
@@ -362,7 +362,7 @@ static bool i915_ttm_eviction_valuable(struct ttm_buffer_object *bo,
{
struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
- if (!obj)
+ if (i915_ttm_is_ghost_object(bo))
return false;
/*
@@ -509,18 +509,9 @@ static int i915_ttm_shrink(struct drm_i915_gem_object *obj, unsigned int flags)
static void i915_ttm_delete_mem_notify(struct ttm_buffer_object *bo)
{
struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
- intel_wakeref_t wakeref = 0;
-
- if (bo->resource && likely(obj)) {
- /* ttm_bo_release() already has dma_resv_lock */
- if (i915_ttm_cpu_maps_iomem(bo->resource))
- wakeref = intel_runtime_pm_get(&to_i915(obj->base.dev)->runtime_pm);
+ if (bo->resource && !i915_ttm_is_ghost_object(bo)) {
__i915_gem_object_pages_fini(obj);
-
- if (wakeref)
- intel_runtime_pm_put(&to_i915(obj->base.dev)->runtime_pm, wakeref);
-
i915_ttm_free_cached_io_rsgt(obj);
}
}
@@ -628,7 +619,7 @@ static void i915_ttm_swap_notify(struct ttm_buffer_object *bo)
struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
int ret;
- if (!obj)
+ if (i915_ttm_is_ghost_object(bo))
return;
ret = i915_ttm_move_notify(bo);
@@ -653,7 +644,7 @@ bool i915_ttm_resource_mappable(struct ttm_resource *res)
if (!i915_ttm_cpu_maps_iomem(res))
return true;
- return bman_res->used_visible_size == bman_res->base.num_pages;
+ return bman_res->used_visible_size == PFN_UP(bman_res->base.size);
}
static int i915_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource *mem)
@@ -661,7 +652,7 @@ static int i915_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource
struct drm_i915_gem_object *obj = i915_ttm_to_gem(mem->bo);
bool unknown_state;
- if (!obj)
+ if (i915_ttm_is_ghost_object(mem->bo))
return -EINVAL;
if (!kref_get_unless_zero(&obj->base.refcount))
@@ -694,7 +685,7 @@ static unsigned long i915_ttm_io_mem_pfn(struct ttm_buffer_object *bo,
unsigned long base;
unsigned int ofs;
- GEM_BUG_ON(!obj);
+ GEM_BUG_ON(i915_ttm_is_ghost_object(bo));
GEM_WARN_ON(bo->ttm);
base = obj->mm.region->iomap.base - obj->mm.region->region.start;
@@ -703,6 +694,50 @@ static unsigned long i915_ttm_io_mem_pfn(struct ttm_buffer_object *bo,
return ((base + sg_dma_address(sg)) >> PAGE_SHIFT) + ofs;
}
+static int i915_ttm_access_memory(struct ttm_buffer_object *bo,
+ unsigned long offset, void *buf,
+ int len, int write)
+{
+ struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
+ resource_size_t iomap = obj->mm.region->iomap.base -
+ obj->mm.region->region.start;
+ unsigned long page = offset >> PAGE_SHIFT;
+ unsigned long bytes_left = len;
+
+ /*
+ * TODO: For now just let it fail if the resource is non-mappable,
+ * otherwise we need to perform the memcpy from the gpu here, without
+ * interfering with the object (like moving the entire thing).
+ */
+ if (!i915_ttm_resource_mappable(bo->resource))
+ return -EIO;
+
+ offset -= page << PAGE_SHIFT;
+ do {
+ unsigned long bytes = min(bytes_left, PAGE_SIZE - offset);
+ void __iomem *ptr;
+ dma_addr_t daddr;
+
+ daddr = i915_gem_object_get_dma_address(obj, page);
+ ptr = ioremap_wc(iomap + daddr + offset, bytes);
+ if (!ptr)
+ return -EIO;
+
+ if (write)
+ memcpy_toio(ptr, buf, bytes);
+ else
+ memcpy_fromio(buf, ptr, bytes);
+ iounmap(ptr);
+
+ page++;
+ buf += bytes;
+ bytes_left -= bytes;
+ offset = 0;
+ } while (bytes_left);
+
+ return len;
+}
+
/*
* All callbacks need to take care not to downcast a struct ttm_buffer_object
* without checking its subclass, since it might be a TTM ghost object.
@@ -719,6 +754,7 @@ static struct ttm_device_funcs i915_ttm_bo_driver = {
.delete_mem_notify = i915_ttm_delete_mem_notify,
.io_mem_reserve = i915_ttm_io_mem_reserve,
.io_mem_pfn = i915_ttm_io_mem_pfn,
+ .access_memory = i915_ttm_access_memory,
};
/**
@@ -783,8 +819,7 @@ static int __i915_ttm_get_pages(struct drm_i915_gem_object *obj,
GEM_BUG_ON(obj->mm.rsgt);
obj->mm.rsgt = rsgt;
- __i915_gem_object_set_pages(obj, &rsgt->table,
- i915_sg_dma_sizes(rsgt->table.sgl));
+ __i915_gem_object_set_pages(obj, &rsgt->table);
}
GEM_BUG_ON(bo->ttm && ((obj->base.size >> PAGE_SHIFT) < bo->ttm->num_pages));
@@ -994,15 +1029,11 @@ static vm_fault_t vm_fault_ttm(struct vm_fault *vmf)
struct vm_area_struct *area = vmf->vma;
struct ttm_buffer_object *bo = area->vm_private_data;
struct drm_device *dev = bo->base.dev;
- struct drm_i915_gem_object *obj;
+ struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo);
intel_wakeref_t wakeref = 0;
vm_fault_t ret;
int idx;
- obj = i915_ttm_to_gem(bo);
- if (!obj)
- return VM_FAULT_SIGBUS;
-
/* Sanity check that we allow writing into this object */
if (unlikely(i915_gem_object_is_readonly(obj) &&
area->vm_flags & VM_WRITE))
@@ -1036,7 +1067,8 @@ static vm_fault_t vm_fault_ttm(struct vm_fault *vmf)
}
if (err) {
- drm_dbg(dev, "Unable to make resource CPU accessible\n");
+ drm_dbg(dev, "Unable to make resource CPU accessible(err = %pe)\n",
+ ERR_PTR(err));
dma_resv_unlock(bo->base.resv);
ret = VM_FAULT_SIGBUS;
goto out_rpm;
@@ -1057,16 +1089,21 @@ static vm_fault_t vm_fault_ttm(struct vm_fault *vmf)
if (ret == VM_FAULT_RETRY && !(vmf->flags & FAULT_FLAG_RETRY_NOWAIT))
goto out_rpm;
- /* ttm_bo_vm_reserve() already has dma_resv_lock */
+ /*
+ * ttm_bo_vm_reserve() already has dma_resv_lock.
+ * userfault_count is protected by dma_resv lock and rpm wakeref.
+ */
if (ret == VM_FAULT_NOPAGE && wakeref && !obj->userfault_count) {
obj->userfault_count = 1;
- mutex_lock(&to_gt(to_i915(obj->base.dev))->lmem_userfault_lock);
- list_add(&obj->userfault_link, &to_gt(to_i915(obj->base.dev))->lmem_userfault_list);
- mutex_unlock(&to_gt(to_i915(obj->base.dev))->lmem_userfault_lock);
+ spin_lock(&to_i915(obj->base.dev)->runtime_pm.lmem_userfault_lock);
+ list_add(&obj->userfault_link, &to_i915(obj->base.dev)->runtime_pm.lmem_userfault_list);
+ spin_unlock(&to_i915(obj->base.dev)->runtime_pm.lmem_userfault_lock);
+
+ GEM_WARN_ON(!i915_ttm_cpu_maps_iomem(bo->resource));
}
if (wakeref & CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND)
- intel_wakeref_auto(&to_gt(to_i915(obj->base.dev))->userfault_wakeref,
+ intel_wakeref_auto(&to_i915(obj->base.dev)->runtime_pm.userfault_wakeref,
msecs_to_jiffies_timeout(CONFIG_DRM_I915_USERFAULT_AUTOSUSPEND));
i915_ttm_adjust_lru(obj);
@@ -1098,7 +1135,7 @@ static void ttm_vm_open(struct vm_area_struct *vma)
struct drm_i915_gem_object *obj =
i915_ttm_to_gem(vma->vm_private_data);
- GEM_BUG_ON(!obj);
+ GEM_BUG_ON(i915_ttm_is_ghost_object(vma->vm_private_data));
i915_gem_object_get(obj);
}
@@ -1107,7 +1144,7 @@ static void ttm_vm_close(struct vm_area_struct *vma)
struct drm_i915_gem_object *obj =
i915_ttm_to_gem(vma->vm_private_data);
- GEM_BUG_ON(!obj);
+ GEM_BUG_ON(i915_ttm_is_ghost_object(vma->vm_private_data));
i915_gem_object_put(obj);
}
@@ -1128,7 +1165,29 @@ static u64 i915_ttm_mmap_offset(struct drm_i915_gem_object *obj)
static void i915_ttm_unmap_virtual(struct drm_i915_gem_object *obj)
{
+ struct ttm_buffer_object *bo = i915_gem_to_ttm(obj);
+ intel_wakeref_t wakeref = 0;
+
+ assert_object_held_shared(obj);
+
+ if (i915_ttm_cpu_maps_iomem(bo->resource)) {
+ wakeref = intel_runtime_pm_get(&to_i915(obj->base.dev)->runtime_pm);
+
+ /* userfault_count is protected by obj lock and rpm wakeref. */
+ if (obj->userfault_count) {
+ spin_lock(&to_i915(obj->base.dev)->runtime_pm.lmem_userfault_lock);
+ list_del(&obj->userfault_link);
+ spin_unlock(&to_i915(obj->base.dev)->runtime_pm.lmem_userfault_lock);
+ obj->userfault_count = 0;
+ }
+ }
+
+ GEM_WARN_ON(obj->userfault_count);
+
ttm_bo_unmap_virtual(i915_gem_to_ttm(obj));
+
+ if (wakeref)
+ intel_runtime_pm_put(&to_i915(obj->base.dev)->runtime_pm, wakeref);
}
static const struct drm_i915_gem_object_ops i915_gem_ttm_obj_ops = {
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
index e4842b4296fc..2a94a99ef76b 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h
@@ -28,18 +28,26 @@ i915_gem_to_ttm(struct drm_i915_gem_object *obj)
void i915_ttm_bo_destroy(struct ttm_buffer_object *bo);
/**
+ * i915_ttm_is_ghost_object - Check if the ttm bo is a ghost object.
+ * @bo: Pointer to the ttm buffer object
+ *
+ * Return: True if the ttm bo is not a i915 object but a ghost ttm object,
+ * False otherwise.
+ */
+static inline bool i915_ttm_is_ghost_object(struct ttm_buffer_object *bo)
+{
+ return bo->destroy != i915_ttm_bo_destroy;
+}
+
+/**
* i915_ttm_to_gem - Convert a struct ttm_buffer_object to an embedding
* struct drm_i915_gem_object.
*
- * Return: Pointer to the embedding struct ttm_buffer_object, or NULL
- * if the object was not an i915 ttm object.
+ * Return: Pointer to the embedding struct ttm_buffer_object.
*/
static inline struct drm_i915_gem_object *
i915_ttm_to_gem(struct ttm_buffer_object *bo)
{
- if (bo->destroy != i915_ttm_bo_destroy)
- return NULL;
-
return container_of(bo, struct drm_i915_gem_object, __do_not_access);
}
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 9a7e50534b84..f59f812dc6d2 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c
@@ -560,7 +560,7 @@ int i915_ttm_move(struct ttm_buffer_object *bo, bool evict,
bool clear;
int ret;
- if (GEM_WARN_ON(!obj)) {
+ if (GEM_WARN_ON(i915_ttm_is_ghost_object(bo))) {
ttm_bo_move_null(bo, dst_mem);
return 0;
}
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
index ba14b18d65f3..9348b1804d53 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_userptr.c
@@ -131,7 +131,6 @@ static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
const unsigned long num_pages = obj->base.size >> PAGE_SHIFT;
unsigned int max_segment = i915_sg_segment_size(obj->base.dev->dev);
struct sg_table *st;
- unsigned int sg_page_sizes;
struct page **pvec;
int ret;
@@ -170,8 +169,7 @@ alloc_table:
if (i915_gem_object_can_bypass_llc(obj))
obj->cache_dirty = true;
- sg_page_sizes = i915_sg_dma_sizes(st->sgl);
- __i915_gem_object_set_pages(obj, st, sg_page_sizes);
+ __i915_gem_object_set_pages(obj, st);
return 0;
@@ -292,7 +290,7 @@ int i915_gem_object_userptr_submit_init(struct drm_i915_gem_object *obj)
if (!i915_gem_object_is_readonly(obj))
gup_flags |= FOLL_WRITE;
- pinned = ret = 0;
+ pinned = 0;
while (pinned < num_pages) {
ret = pin_user_pages_fast(obj->userptr.ptr + pinned * PAGE_SIZE,
num_pages - pinned, gup_flags,
@@ -302,7 +300,6 @@ int i915_gem_object_userptr_submit_init(struct drm_i915_gem_object *obj)
pinned += ret;
}
- ret = 0;
ret = i915_gem_object_lock_interruptible(obj, NULL);
if (ret)
diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c b/drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c
index f963b8e1e37b..cbd9b624a788 100644
--- a/drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/selftests/huge_gem_object.c
@@ -68,7 +68,7 @@ static int huge_get_pages(struct drm_i915_gem_object *obj)
if (i915_gem_gtt_prepare_pages(obj, pages))
goto err;
- __i915_gem_object_set_pages(obj, pages, PAGE_SIZE);
+ __i915_gem_object_set_pages(obj, pages);
return 0;
diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
index c570cf780079..beaf27e09e8a 100644
--- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
+++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c
@@ -136,7 +136,7 @@ static int get_huge_pages(struct drm_i915_gem_object *obj)
goto err;
GEM_BUG_ON(sg_page_sizes != obj->mm.page_mask);
- __i915_gem_object_set_pages(obj, st, sg_page_sizes);
+ __i915_gem_object_set_pages(obj, st);
return 0;
@@ -210,7 +210,6 @@ static int fake_get_huge_pages(struct drm_i915_gem_object *obj)
const u64 max_len = rounddown_pow_of_two(UINT_MAX);
struct sg_table *st;
struct scatterlist *sg;
- unsigned int sg_page_sizes;
u64 rem;
st = kmalloc(sizeof(*st), GFP);
@@ -226,7 +225,6 @@ static int fake_get_huge_pages(struct drm_i915_gem_object *obj)
rem = obj->base.size;
sg = st->sgl;
st->nents = 0;
- sg_page_sizes = 0;
do {
unsigned int page_size = get_largest_page_size(i915, rem);
unsigned int len = min(page_size * div_u64(rem, page_size),
@@ -239,8 +237,6 @@ static int fake_get_huge_pages(struct drm_i915_gem_object *obj)
sg_dma_len(sg) = len;
sg_dma_address(sg) = page_size;
- sg_page_sizes |= len;
-
st->nents++;
rem -= len;
@@ -254,7 +250,7 @@ static int fake_get_huge_pages(struct drm_i915_gem_object *obj)
i915_sg_trim(st);
- __i915_gem_object_set_pages(obj, st, sg_page_sizes);
+ __i915_gem_object_set_pages(obj, st);
return 0;
}
@@ -286,7 +282,7 @@ static int fake_get_huge_pages_single(struct drm_i915_gem_object *obj)
sg_dma_len(sg) = obj->base.size;
sg_dma_address(sg) = page_size;
- __i915_gem_object_set_pages(obj, st, sg->length);
+ __i915_gem_object_set_pages(obj, st);
return 0;
#undef GFP
@@ -1161,7 +1157,8 @@ static int igt_write_huge(struct drm_i915_private *i915,
GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
size = obj->base.size;
- if (obj->mm.page_sizes.sg & I915_GTT_PAGE_SIZE_64K)
+ if (obj->mm.page_sizes.sg & I915_GTT_PAGE_SIZE_64K &&
+ !HAS_64K_PAGES(i915))
size = round_up(size, I915_GTT_PAGE_SIZE_2M);
n = 0;
@@ -1214,6 +1211,10 @@ static int igt_write_huge(struct drm_i915_private *i915,
* size and ensure the vma offset is at the start of the pt
* boundary, however to improve coverage we opt for testing both
* aligned and unaligned offsets.
+ *
+ * With PS64 this is no longer the case, but to ensure we
+ * sometimes get the compact layout for smaller objects, apply
+ * the round_up anyway.
*/
if (obj->mm.page_sizes.sg & I915_GTT_PAGE_SIZE_64K)
offset_low = round_down(offset_low,
@@ -1411,6 +1412,7 @@ static int igt_ppgtt_sanity_check(void *arg)
{ SZ_2M + SZ_4K, SZ_64K | SZ_4K },
{ SZ_2M + SZ_4K, SZ_2M | SZ_4K },
{ SZ_2M + SZ_64K, SZ_2M | SZ_64K },
+ { SZ_2M + SZ_64K, SZ_64K },
};
int i, j;
int err;
@@ -1540,6 +1542,154 @@ out_put:
return err;
}
+static int igt_ppgtt_mixed(void *arg)
+{
+ struct drm_i915_private *i915 = arg;
+ const unsigned long flags = PIN_OFFSET_FIXED | PIN_USER;
+ struct drm_i915_gem_object *obj, *on;
+ struct i915_gem_engines *engines;
+ struct i915_gem_engines_iter it;
+ struct i915_address_space *vm;
+ struct i915_gem_context *ctx;
+ struct intel_context *ce;
+ struct file *file;
+ I915_RND_STATE(prng);
+ LIST_HEAD(objects);
+ struct intel_memory_region *mr;
+ struct i915_vma *vma;
+ unsigned int count;
+ u32 i, addr;
+ int *order;
+ int n, err;
+
+ /*
+ * Sanity check mixing 4K and 64K pages within the same page-table via
+ * the new PS64 TLB hint.
+ */
+
+ if (!HAS_64K_PAGES(i915)) {
+ pr_info("device lacks PS64, skipping\n");
+ 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);
+
+ i = 0;
+ addr = 0;
+ do {
+ u32 sz;
+
+ sz = i915_prandom_u32_max_state(SZ_4M, &prng);
+ sz = max_t(u32, sz, SZ_4K);
+
+ mr = i915->mm.regions[INTEL_REGION_LMEM_0];
+ if (i & 1)
+ mr = i915->mm.regions[INTEL_REGION_SMEM];
+
+ obj = i915_gem_object_create_region(mr, sz, 0, 0);
+ if (IS_ERR(obj)) {
+ err = PTR_ERR(obj);
+ goto out_vm;
+ }
+
+ list_add_tail(&obj->st_link, &objects);
+
+ vma = i915_vma_instance(obj, vm, NULL);
+ if (IS_ERR(vma)) {
+ err = PTR_ERR(vma);
+ goto err_put;
+ }
+
+ addr = round_up(addr, mr->min_page_size);
+ err = i915_vma_pin(vma, 0, 0, addr | flags);
+ if (err)
+ goto err_put;
+
+ if (mr->type == INTEL_MEMORY_LOCAL &&
+ (vma->resource->page_sizes_gtt & I915_GTT_PAGE_SIZE_4K)) {
+ err = -EINVAL;
+ goto err_put;
+ }
+
+ addr += obj->base.size;
+ i++;
+ } while (addr <= SZ_16M);
+
+ n = 0;
+ count = 0;
+ for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it) {
+ count++;
+ if (!intel_engine_can_store_dword(ce->engine))
+ continue;
+
+ n++;
+ }
+ i915_gem_context_unlock_engines(ctx);
+ if (!n)
+ goto err_put;
+
+ order = i915_random_order(count * count, &prng);
+ if (!order) {
+ err = -ENOMEM;
+ goto err_put;
+ }
+
+ i = 0;
+ addr = 0;
+ engines = i915_gem_context_lock_engines(ctx);
+ list_for_each_entry(obj, &objects, st_link) {
+ u32 rnd = i915_prandom_u32_max_state(UINT_MAX, &prng);
+
+ addr = round_up(addr, obj->mm.region->min_page_size);
+
+ ce = engines->engines[order[i] % engines->num_engines];
+ i = (i + 1) % (count * count);
+ if (!ce || !intel_engine_can_store_dword(ce->engine))
+ continue;
+
+ err = __igt_write_huge(ce, obj, obj->base.size, addr, 0, rnd);
+ if (err)
+ break;
+
+ err = __igt_write_huge(ce, obj, obj->base.size, addr,
+ offset_in_page(rnd) / sizeof(u32), rnd + 1);
+ if (err)
+ break;
+
+ err = __igt_write_huge(ce, obj, obj->base.size, addr,
+ (PAGE_SIZE / sizeof(u32)) - 1,
+ rnd + 2);
+ if (err)
+ break;
+
+ addr += obj->base.size;
+
+ cond_resched();
+ }
+
+ i915_gem_context_unlock_engines(ctx);
+ kfree(order);
+err_put:
+ list_for_each_entry_safe(obj, on, &objects, st_link) {
+ list_del(&obj->st_link);
+ i915_gem_object_put(obj);
+ }
+out_vm:
+ i915_vm_put(vm);
+out:
+ fput(file);
+ return err;
+}
+
static int igt_tmpfs_fallback(void *arg)
{
struct drm_i915_private *i915 = arg;
@@ -1803,6 +1953,7 @@ int i915_gem_huge_page_live_selftests(struct drm_i915_private *i915)
SUBTEST(igt_ppgtt_smoke_huge),
SUBTEST(igt_ppgtt_sanity_check),
SUBTEST(igt_ppgtt_compact),
+ SUBTEST(igt_ppgtt_mixed),
};
if (!HAS_PPGTT(i915)) {
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c
index 9a6a6b5b722b..692a16914ca0 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_client_blt.c
@@ -13,6 +13,7 @@
#include "gt/intel_gt_regs.h"
#include "gem/i915_gem_lmem.h"
+#include "gem/selftests/igt_gem_utils.h"
#include "selftests/igt_flush_test.h"
#include "selftests/mock_drm.h"
#include "selftests/i915_random.h"
@@ -457,21 +458,6 @@ static int verify_buffer(const struct tiled_blits *t,
return ret;
}
-static int move_to_active(struct i915_vma *vma,
- struct i915_request *rq,
- unsigned int flags)
-{
- int err;
-
- i915_vma_lock(vma);
- err = i915_request_await_object(rq, vma->obj, false);
- if (err == 0)
- err = i915_vma_move_to_active(vma, rq, flags);
- i915_vma_unlock(vma);
-
- return err;
-}
-
static int pin_buffer(struct i915_vma *vma, u64 addr)
{
int err;
@@ -525,11 +511,11 @@ tiled_blit(struct tiled_blits *t,
goto err_bb;
}
- err = move_to_active(t->batch, rq, 0);
+ err = igt_vma_move_to_active_unlocked(t->batch, rq, 0);
if (!err)
- err = move_to_active(src->vma, rq, 0);
+ err = igt_vma_move_to_active_unlocked(src->vma, rq, 0);
if (!err)
- err = move_to_active(dst->vma, rq, 0);
+ err = igt_vma_move_to_active_unlocked(dst->vma, rq, 0);
if (!err)
err = rq->engine->emit_bb_start(rq,
t->batch->node.start,
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c
index a666d7e610f5..c228fe4aba50 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_coherency.c
@@ -239,9 +239,7 @@ static int gpu_set(struct context *ctx, unsigned long offset, u32 v)
}
intel_ring_advance(rq, cs);
- err = i915_request_await_object(rq, vma->obj, true);
- if (err == 0)
- err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
+ err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
out_rq:
i915_request_add(rq);
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 c6ad67b90e8a..a0ff51d71d07 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c
@@ -179,97 +179,108 @@ out_file:
}
struct parallel_switch {
- struct task_struct *tsk;
+ struct kthread_worker *worker;
+ struct kthread_work work;
struct intel_context *ce[2];
+ int result;
};
-static int __live_parallel_switch1(void *data)
+static void __live_parallel_switch1(struct kthread_work *work)
{
- struct parallel_switch *arg = data;
+ struct parallel_switch *arg =
+ container_of(work, typeof(*arg), work);
IGT_TIMEOUT(end_time);
unsigned long count;
count = 0;
+ arg->result = 0;
do {
struct i915_request *rq = NULL;
- int err, n;
+ int n;
- err = 0;
- for (n = 0; !err && n < ARRAY_SIZE(arg->ce); n++) {
+ for (n = 0; !arg->result && n < ARRAY_SIZE(arg->ce); n++) {
struct i915_request *prev = rq;
rq = i915_request_create(arg->ce[n]);
if (IS_ERR(rq)) {
i915_request_put(prev);
- return PTR_ERR(rq);
+ arg->result = PTR_ERR(rq);
+ break;
}
i915_request_get(rq);
if (prev) {
- err = i915_request_await_dma_fence(rq, &prev->fence);
+ arg->result =
+ i915_request_await_dma_fence(rq,
+ &prev->fence);
i915_request_put(prev);
}
i915_request_add(rq);
}
+
+ if (IS_ERR_OR_NULL(rq))
+ break;
+
if (i915_request_wait(rq, 0, HZ) < 0)
- err = -ETIME;
+ arg->result = -ETIME;
+
i915_request_put(rq);
- if (err)
- return err;
count++;
- } while (!__igt_timeout(end_time, NULL));
+ } while (!arg->result && !__igt_timeout(end_time, NULL));
- pr_info("%s: %lu switches (sync)\n", arg->ce[0]->engine->name, count);
- return 0;
+ pr_info("%s: %lu switches (sync) <%d>\n",
+ arg->ce[0]->engine->name, count, arg->result);
}
-static int __live_parallel_switchN(void *data)
+static void __live_parallel_switchN(struct kthread_work *work)
{
- struct parallel_switch *arg = data;
+ struct parallel_switch *arg =
+ container_of(work, typeof(*arg), work);
struct i915_request *rq = NULL;
IGT_TIMEOUT(end_time);
unsigned long count;
int n;
count = 0;
+ arg->result = 0;
do {
- for (n = 0; n < ARRAY_SIZE(arg->ce); n++) {
+ for (n = 0; !arg->result && n < ARRAY_SIZE(arg->ce); n++) {
struct i915_request *prev = rq;
- int err = 0;
rq = i915_request_create(arg->ce[n]);
if (IS_ERR(rq)) {
i915_request_put(prev);
- return PTR_ERR(rq);
+ arg->result = PTR_ERR(rq);
+ break;
}
i915_request_get(rq);
if (prev) {
- err = i915_request_await_dma_fence(rq, &prev->fence);
+ arg->result =
+ i915_request_await_dma_fence(rq,
+ &prev->fence);
i915_request_put(prev);
}
i915_request_add(rq);
- if (err) {
- i915_request_put(rq);
- return err;
- }
}
count++;
- } while (!__igt_timeout(end_time, NULL));
- i915_request_put(rq);
+ } while (!arg->result && !__igt_timeout(end_time, NULL));
- pr_info("%s: %lu switches (many)\n", arg->ce[0]->engine->name, count);
- return 0;
+ if (!IS_ERR_OR_NULL(rq))
+ i915_request_put(rq);
+
+ pr_info("%s: %lu switches (many) <%d>\n",
+ arg->ce[0]->engine->name, count, arg->result);
}
static int live_parallel_switch(void *arg)
{
struct drm_i915_private *i915 = arg;
- static int (* const func[])(void *arg) = {
+ static void (* const func[])(struct kthread_work *) = {
__live_parallel_switch1,
__live_parallel_switchN,
NULL,
@@ -277,7 +288,7 @@ static int live_parallel_switch(void *arg)
struct parallel_switch *data = NULL;
struct i915_gem_engines *engines;
struct i915_gem_engines_iter it;
- int (* const *fn)(void *arg);
+ void (* const *fn)(struct kthread_work *);
struct i915_gem_context *ctx;
struct intel_context *ce;
struct file *file;
@@ -348,9 +359,22 @@ static int live_parallel_switch(void *arg)
}
}
+ for (n = 0; n < count; n++) {
+ struct kthread_worker *worker;
+
+ if (!data[n].ce[0])
+ continue;
+
+ worker = kthread_create_worker(0, "igt/parallel:%s",
+ data[n].ce[0]->engine->name);
+ if (IS_ERR(worker))
+ goto out;
+
+ data[n].worker = worker;
+ }
+
for (fn = func; !err && *fn; fn++) {
struct igt_live_test t;
- int n;
err = igt_live_test_begin(&t, i915, __func__, "");
if (err)
@@ -360,30 +384,17 @@ static int live_parallel_switch(void *arg)
if (!data[n].ce[0])
continue;
- data[n].tsk = kthread_run(*fn, &data[n],
- "igt/parallel:%s",
- data[n].ce[0]->engine->name);
- if (IS_ERR(data[n].tsk)) {
- err = PTR_ERR(data[n].tsk);
- break;
- }
- get_task_struct(data[n].tsk);
+ data[n].result = 0;
+ kthread_init_work(&data[n].work, *fn);
+ kthread_queue_work(data[n].worker, &data[n].work);
}
- yield(); /* start all threads before we kthread_stop() */
-
for (n = 0; n < count; n++) {
- int status;
-
- if (IS_ERR_OR_NULL(data[n].tsk))
- continue;
-
- status = kthread_stop(data[n].tsk);
- if (status && !err)
- err = status;
-
- put_task_struct(data[n].tsk);
- data[n].tsk = NULL;
+ if (data[n].ce[0]) {
+ kthread_flush_work(&data[n].work);
+ if (data[n].result && !err)
+ err = data[n].result;
+ }
}
if (igt_live_test_end(&t))
@@ -399,6 +410,9 @@ out:
intel_context_unpin(data[n].ce[m]);
intel_context_put(data[n].ce[m]);
}
+
+ if (data[n].worker)
+ kthread_destroy_worker(data[n].worker);
}
kfree(data);
out_file:
@@ -970,15 +984,11 @@ retry:
goto err_batch;
}
- err = i915_request_await_object(rq, batch->obj, false);
- if (err == 0)
- err = i915_vma_move_to_active(batch, rq, 0);
+ err = i915_vma_move_to_active(batch, rq, 0);
if (err)
goto skip_request;
- err = i915_request_await_object(rq, vma->obj, true);
- if (err == 0)
- err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
+ err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
if (err)
goto skip_request;
@@ -1539,9 +1549,7 @@ static int write_to_scratch(struct i915_gem_context *ctx,
}
i915_vma_lock(vma);
- err = i915_request_await_object(rq, vma->obj, false);
- if (err == 0)
- err = i915_vma_move_to_active(vma, rq, 0);
+ err = i915_vma_move_to_active(vma, rq, 0);
i915_vma_unlock(vma);
if (err)
goto skip_request;
@@ -1675,9 +1683,7 @@ static int read_from_scratch(struct i915_gem_context *ctx,
}
i915_vma_lock(vma);
- err = i915_request_await_object(rq, vma->obj, true);
- if (err == 0)
- err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
+ err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
i915_vma_unlock(vma);
if (err)
goto skip_request;
diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
index 51ed824b020c..e57f9390076c 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c
@@ -6,8 +6,12 @@
#include "i915_drv.h"
#include "i915_selftest.h"
+#include "gem/i915_gem_context.h"
+#include "mock_context.h"
#include "mock_dmabuf.h"
+#include "igt_gem_utils.h"
+#include "selftests/mock_drm.h"
#include "selftests/mock_gem_device.h"
static int igt_dmabuf_export(void *arg)
@@ -140,6 +144,75 @@ out_ret:
return err;
}
+static int verify_access(struct drm_i915_private *i915,
+ struct drm_i915_gem_object *native_obj,
+ struct drm_i915_gem_object *import_obj)
+{
+ struct i915_gem_engines_iter it;
+ struct i915_gem_context *ctx;
+ struct intel_context *ce;
+ struct i915_vma *vma;
+ struct file *file;
+ u32 *vaddr;
+ int err = 0, i;
+
+ file = mock_file(i915);
+ if (IS_ERR(file))
+ return PTR_ERR(file);
+
+ ctx = live_context(i915, file);
+ if (IS_ERR(ctx)) {
+ err = PTR_ERR(ctx);
+ goto out_file;
+ }
+
+ for_each_gem_engine(ce, i915_gem_context_lock_engines(ctx), it) {
+ if (intel_engine_can_store_dword(ce->engine))
+ break;
+ }
+ i915_gem_context_unlock_engines(ctx);
+ if (!ce)
+ goto out_file;
+
+ vma = i915_vma_instance(import_obj, ce->vm, NULL);
+ if (IS_ERR(vma)) {
+ err = PTR_ERR(vma);
+ goto out_file;
+ }
+
+ err = i915_vma_pin(vma, 0, 0, PIN_USER);
+ if (err)
+ goto out_file;
+
+ err = igt_gpu_fill_dw(ce, vma, 0,
+ vma->size >> PAGE_SHIFT, 0xdeadbeaf);
+ i915_vma_unpin(vma);
+ if (err)
+ goto out_file;
+
+ err = i915_gem_object_wait(import_obj, 0, MAX_SCHEDULE_TIMEOUT);
+ if (err)
+ goto out_file;
+
+ vaddr = i915_gem_object_pin_map_unlocked(native_obj, I915_MAP_WB);
+ if (IS_ERR(vaddr)) {
+ err = PTR_ERR(vaddr);
+ goto out_file;
+ }
+
+ for (i = 0; i < native_obj->base.size / sizeof(u32); i += PAGE_SIZE / sizeof(u32)) {
+ if (vaddr[i] != 0xdeadbeaf) {
+ pr_err("Data mismatch [%d]=%u\n", i, vaddr[i]);
+ err = -EINVAL;
+ goto out_file;
+ }
+ }
+
+out_file:
+ fput(file);
+ return err;
+}
+
static int igt_dmabuf_import_same_driver(struct drm_i915_private *i915,
struct intel_memory_region **regions,
unsigned int num_regions)
@@ -154,7 +227,7 @@ static int igt_dmabuf_import_same_driver(struct drm_i915_private *i915,
force_different_devices = true;
- obj = __i915_gem_object_create_user(i915, PAGE_SIZE,
+ obj = __i915_gem_object_create_user(i915, SZ_8M,
regions, num_regions);
if (IS_ERR(obj)) {
pr_err("__i915_gem_object_create_user failed with err=%ld\n",
@@ -206,6 +279,10 @@ static int igt_dmabuf_import_same_driver(struct drm_i915_private *i915,
i915_gem_object_unlock(import_obj);
+ err = verify_access(i915, obj, import_obj);
+ if (err)
+ goto out_import;
+
/* Now try a fake an importer */
import_attach = dma_buf_attach(dmabuf, obj->base.dev->dev);
if (IS_ERR(import_attach)) {
@@ -213,7 +290,7 @@ static int igt_dmabuf_import_same_driver(struct drm_i915_private *i915,
goto out_import;
}
- st = dma_buf_map_attachment(import_attach, DMA_BIDIRECTIONAL);
+ st = dma_buf_map_attachment_unlocked(import_attach, DMA_BIDIRECTIONAL);
if (IS_ERR(st)) {
err = PTR_ERR(st);
goto out_detach;
@@ -226,7 +303,7 @@ static int igt_dmabuf_import_same_driver(struct drm_i915_private *i915,
timeout = -ETIME;
}
err = timeout > 0 ? 0 : timeout;
- dma_buf_unmap_attachment(import_attach, st, DMA_BIDIRECTIONAL);
+ dma_buf_unmap_attachment_unlocked(import_attach, st, DMA_BIDIRECTIONAL);
out_detach:
dma_buf_detach(dmabuf, import_attach);
out_import:
@@ -296,7 +373,7 @@ static int igt_dmabuf_import(void *arg)
goto out_obj;
}
- err = dma_buf_vmap(dmabuf, &map);
+ err = dma_buf_vmap_unlocked(dmabuf, &map);
dma_map = err ? NULL : map.vaddr;
if (!dma_map) {
pr_err("dma_buf_vmap failed\n");
@@ -337,7 +414,7 @@ static int igt_dmabuf_import(void *arg)
err = 0;
out_dma_map:
- dma_buf_vunmap(dmabuf, &map);
+ dma_buf_vunmap_unlocked(dmabuf, &map);
out_obj:
i915_gem_object_put(obj);
out_dmabuf:
@@ -358,7 +435,7 @@ static int igt_dmabuf_import_ownership(void *arg)
if (IS_ERR(dmabuf))
return PTR_ERR(dmabuf);
- err = dma_buf_vmap(dmabuf, &map);
+ err = dma_buf_vmap_unlocked(dmabuf, &map);
ptr = err ? NULL : map.vaddr;
if (!ptr) {
pr_err("dma_buf_vmap failed\n");
@@ -367,7 +444,7 @@ static int igt_dmabuf_import_ownership(void *arg)
}
memset(ptr, 0xc5, PAGE_SIZE);
- dma_buf_vunmap(dmabuf, &map);
+ dma_buf_vunmap_unlocked(dmabuf, &map);
obj = to_intel_bo(i915_gem_prime_import(&i915->drm, dmabuf));
if (IS_ERR(obj)) {
@@ -418,7 +495,7 @@ static int igt_dmabuf_export_vmap(void *arg)
}
i915_gem_object_put(obj);
- err = dma_buf_vmap(dmabuf, &map);
+ err = dma_buf_vmap_unlocked(dmabuf, &map);
ptr = err ? NULL : map.vaddr;
if (!ptr) {
pr_err("dma_buf_vmap failed\n");
@@ -435,7 +512,7 @@ static int igt_dmabuf_export_vmap(void *arg)
memset(ptr, 0xc5, dmabuf->size);
err = 0;
- dma_buf_vunmap(dmabuf, &map);
+ dma_buf_vunmap_unlocked(dmabuf, &map);
out:
dma_buf_put(dmabuf);
return err;
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 b73c91aa5450..3f658d5717d8 100644
--- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
+++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c
@@ -8,6 +8,7 @@
#include <linux/prime_numbers.h>
#include "gem/i915_gem_internal.h"
+#include "gem/i915_gem_lmem.h"
#include "gem/i915_gem_region.h"
#include "gem/i915_gem_ttm.h"
#include "gem/i915_gem_ttm_move.h"
@@ -16,6 +17,7 @@
#include "gt/intel_gt.h"
#include "gt/intel_gt_pm.h"
#include "gt/intel_migrate.h"
+#include "i915_reg.h"
#include "i915_ttm_buddy_manager.h"
#include "huge_gem_object.h"
@@ -564,10 +566,8 @@ retry:
goto err_unpin;
}
- err = i915_request_await_object(rq, vma->obj, true);
- if (err == 0)
- err = i915_vma_move_to_active(vma, rq,
- EXEC_OBJECT_WRITE);
+ err = i915_vma_move_to_active(vma, rq,
+ EXEC_OBJECT_WRITE);
i915_request_add(rq);
err_unpin:
@@ -1607,9 +1607,7 @@ retry:
goto out_unpin;
}
- err = i915_request_await_object(rq, vma->obj, false);
- if (err == 0)
- err = i915_vma_move_to_active(vma, rq, 0);
+ err = i915_vma_move_to_active(vma, rq, 0);
err = engine->emit_bb_start(rq, vma->node.start, 0, 0);
i915_request_get(rq);
diff --git a/drivers/gpu/drm/i915/gem/selftests/igt_gem_utils.c b/drivers/gpu/drm/i915/gem/selftests/igt_gem_utils.c
index 3c55e77b0f1b..374b10ac430e 100644
--- a/drivers/gpu/drm/i915/gem/selftests/igt_gem_utils.c
+++ b/drivers/gpu/drm/i915/gem/selftests/igt_gem_utils.c
@@ -131,17 +131,13 @@ int igt_gpu_fill_dw(struct intel_context *ce,
}
i915_vma_lock(batch);
- err = i915_request_await_object(rq, batch->obj, false);
- if (err == 0)
- err = i915_vma_move_to_active(batch, rq, 0);
+ err = i915_vma_move_to_active(batch, rq, 0);
i915_vma_unlock(batch);
if (err)
goto skip_request;
i915_vma_lock(vma);
- err = i915_request_await_object(rq, vma->obj, true);
- if (err == 0)
- err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
+ err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
i915_vma_unlock(vma);
if (err)
goto skip_request;
diff --git a/drivers/gpu/drm/i915/gem/selftests/igt_gem_utils.h b/drivers/gpu/drm/i915/gem/selftests/igt_gem_utils.h
index 4221cf84d175..1379fbc14431 100644
--- a/drivers/gpu/drm/i915/gem/selftests/igt_gem_utils.h
+++ b/drivers/gpu/drm/i915/gem/selftests/igt_gem_utils.h
@@ -9,6 +9,8 @@
#include <linux/types.h>
+#include "i915_vma.h"
+
struct i915_request;
struct i915_gem_context;
struct i915_vma;
@@ -29,4 +31,16 @@ int igt_gpu_fill_dw(struct intel_context *ce,
struct i915_vma *vma, u64 offset,
unsigned long count, u32 val);
+static inline int __must_check
+igt_vma_move_to_active_unlocked(struct i915_vma *vma, struct i915_request *rq,
+ unsigned int flags)
+{
+ int err;
+
+ i915_vma_lock(vma);
+ err = _i915_vma_move_to_active(vma, rq, &rq->fence, flags);
+ i915_vma_unlock(vma);
+ return err;
+}
+
#endif /* __IGT_GEM_UTILS_H__ */
diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c
index e49fa6fa6aee..e1c76e5bfa82 100644
--- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c
@@ -396,15 +396,17 @@ int gen8_emit_init_breadcrumb(struct i915_request *rq)
return 0;
}
-static int __gen125_emit_bb_start(struct i915_request *rq,
- u64 offset, u32 len,
- const unsigned int flags,
- u32 arb)
+static int __xehp_emit_bb_start(struct i915_request *rq,
+ u64 offset, u32 len,
+ const unsigned int flags,
+ u32 arb)
{
struct intel_context *ce = rq->context;
u32 wa_offset = lrc_indirect_bb(ce);
u32 *cs;
+ GEM_BUG_ON(!ce->wa_bb_page);
+
cs = intel_ring_begin(rq, 12);
if (IS_ERR(cs))
return PTR_ERR(cs);
@@ -435,18 +437,18 @@ static int __gen125_emit_bb_start(struct i915_request *rq,
return 0;
}
-int gen125_emit_bb_start_noarb(struct i915_request *rq,
- u64 offset, u32 len,
- const unsigned int flags)
+int xehp_emit_bb_start_noarb(struct i915_request *rq,
+ u64 offset, u32 len,
+ const unsigned int flags)
{
- return __gen125_emit_bb_start(rq, offset, len, flags, MI_ARB_DISABLE);
+ return __xehp_emit_bb_start(rq, offset, len, flags, MI_ARB_DISABLE);
}
-int gen125_emit_bb_start(struct i915_request *rq,
- u64 offset, u32 len,
- const unsigned int flags)
+int xehp_emit_bb_start(struct i915_request *rq,
+ u64 offset, u32 len,
+ const unsigned int flags)
{
- return __gen125_emit_bb_start(rq, offset, len, flags, MI_ARB_ENABLE);
+ return __xehp_emit_bb_start(rq, offset, len, flags, MI_ARB_ENABLE);
}
int gen8_emit_bb_start_noarb(struct i915_request *rq,
@@ -583,6 +585,8 @@ u32 *gen8_emit_fini_breadcrumb_xcs(struct i915_request *rq, u32 *cs)
u32 *gen8_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs)
{
cs = gen8_emit_pipe_control(cs,
+ PIPE_CONTROL_CS_STALL |
+ PIPE_CONTROL_TLB_INVALIDATE |
PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH |
PIPE_CONTROL_DEPTH_CACHE_FLUSH |
PIPE_CONTROL_DC_FLUSH_ENABLE,
@@ -600,15 +604,21 @@ u32 *gen8_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs)
u32 *gen11_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs)
{
+ cs = gen8_emit_pipe_control(cs,
+ PIPE_CONTROL_CS_STALL |
+ PIPE_CONTROL_TLB_INVALIDATE |
+ PIPE_CONTROL_TILE_CACHE_FLUSH |
+ PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH |
+ PIPE_CONTROL_DEPTH_CACHE_FLUSH |
+ PIPE_CONTROL_DC_FLUSH_ENABLE,
+ 0);
+
+ /*XXX: Look at gen8_emit_fini_breadcrumb_rcs */
cs = gen8_emit_ggtt_write_rcs(cs,
rq->fence.seqno,
hwsp_offset(rq),
- PIPE_CONTROL_CS_STALL |
- PIPE_CONTROL_TILE_CACHE_FLUSH |
- PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH |
- PIPE_CONTROL_DEPTH_CACHE_FLUSH |
- PIPE_CONTROL_DC_FLUSH_ENABLE |
- PIPE_CONTROL_FLUSH_ENABLE);
+ PIPE_CONTROL_FLUSH_ENABLE |
+ PIPE_CONTROL_CS_STALL);
return gen8_emit_fini_breadcrumb_tail(rq, cs);
}
@@ -715,6 +725,7 @@ u32 *gen12_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs)
{
struct drm_i915_private *i915 = rq->engine->i915;
u32 flags = (PIPE_CONTROL_CS_STALL |
+ PIPE_CONTROL_TLB_INVALIDATE |
PIPE_CONTROL_TILE_CACHE_FLUSH |
PIPE_CONTROL_FLUSH_L3 |
PIPE_CONTROL_RENDER_TARGET_CACHE_FLUSH |
@@ -731,11 +742,15 @@ u32 *gen12_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs)
else if (rq->engine->class == COMPUTE_CLASS)
flags &= ~PIPE_CONTROL_3D_ENGINE_FLAGS;
+ cs = gen12_emit_pipe_control(cs, PIPE_CONTROL0_HDC_PIPELINE_FLUSH, flags, 0);
+
+ /*XXX: Look at gen8_emit_fini_breadcrumb_rcs */
cs = gen12_emit_ggtt_write_rcs(cs,
rq->fence.seqno,
hwsp_offset(rq),
- PIPE_CONTROL0_HDC_PIPELINE_FLUSH,
- flags);
+ 0,
+ PIPE_CONTROL_FLUSH_ENABLE |
+ PIPE_CONTROL_CS_STALL);
return gen12_emit_fini_breadcrumb_tail(rq, cs);
}
diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.h b/drivers/gpu/drm/i915/gt/gen8_engine_cs.h
index e4d24c811dd6..655e5c00ddc2 100644
--- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.h
+++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.h
@@ -32,12 +32,12 @@ int gen8_emit_bb_start(struct i915_request *rq,
u64 offset, u32 len,
const unsigned int flags);
-int gen125_emit_bb_start_noarb(struct i915_request *rq,
- u64 offset, u32 len,
- const unsigned int flags);
-int gen125_emit_bb_start(struct i915_request *rq,
- u64 offset, u32 len,
- const unsigned int flags);
+int xehp_emit_bb_start_noarb(struct i915_request *rq,
+ u64 offset, u32 len,
+ const unsigned int flags);
+int xehp_emit_bb_start(struct i915_request *rq,
+ u64 offset, u32 len,
+ const unsigned int flags);
u32 *gen8_emit_fini_breadcrumb_xcs(struct i915_request *rq, u32 *cs);
u32 *gen12_emit_fini_breadcrumb_xcs(struct i915_request *rq, u32 *cs);
diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
index 2128b7a72a25..4daaa6f55668 100644
--- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
+++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c
@@ -476,6 +476,7 @@ xehpsdv_ppgtt_insert_huge(struct i915_address_space *vm,
const gen8_pte_t pte_encode = vm->pte_encode(0, cache_level, flags);
unsigned int rem = sg_dma_len(iter->sg);
u64 start = vma_res->start;
+ u64 end = start + vma_res->vma_size;
GEM_BUG_ON(!i915_vm_is_4lvl(vm));
@@ -489,9 +490,10 @@ xehpsdv_ppgtt_insert_huge(struct i915_address_space *vm,
gen8_pte_t encode = pte_encode;
unsigned int page_size;
gen8_pte_t *vaddr;
- u16 index, max;
+ u16 index, max, nent, i;
max = I915_PDES;
+ nent = 1;
if (vma_res->bi.page_sizes.sg & I915_GTT_PAGE_SIZE_2M &&
IS_ALIGNED(iter->dma, I915_GTT_PAGE_SIZE_2M) &&
@@ -503,25 +505,37 @@ xehpsdv_ppgtt_insert_huge(struct i915_address_space *vm,
vaddr = px_vaddr(pd);
} else {
- if (encode & GEN12_PPGTT_PTE_LM) {
- GEM_BUG_ON(__gen8_pte_index(start, 0) % 16);
- GEM_BUG_ON(rem < I915_GTT_PAGE_SIZE_64K);
- GEM_BUG_ON(!IS_ALIGNED(iter->dma,
- I915_GTT_PAGE_SIZE_64K));
-
- index = __gen8_pte_index(start, 0) / 16;
- page_size = I915_GTT_PAGE_SIZE_64K;
-
- max /= 16;
-
- vaddr = px_vaddr(pd);
- vaddr[__gen8_pte_index(start, 1)] |= GEN12_PDE_64K;
+ index = __gen8_pte_index(start, 0);
+ page_size = I915_GTT_PAGE_SIZE;
- pt->is_compact = true;
- } else {
- GEM_BUG_ON(pt->is_compact);
- index = __gen8_pte_index(start, 0);
- page_size = I915_GTT_PAGE_SIZE;
+ if (vma_res->bi.page_sizes.sg & I915_GTT_PAGE_SIZE_64K) {
+ /*
+ * Device local-memory on these platforms should
+ * always use 64K pages or larger (including GTT
+ * alignment), therefore if we know the whole
+ * page-table needs to be filled we can always
+ * safely use the compact-layout. Otherwise fall
+ * back to the TLB hint with PS64. If this is
+ * system memory we only bother with PS64.
+ */
+ if ((encode & GEN12_PPGTT_PTE_LM) &&
+ end - start >= SZ_2M && !index) {
+ index = __gen8_pte_index(start, 0) / 16;
+ page_size = I915_GTT_PAGE_SIZE_64K;
+
+ max /= 16;
+
+ vaddr = px_vaddr(pd);
+ vaddr[__gen8_pte_index(start, 1)] |= GEN12_PDE_64K;
+
+ pt->is_compact = true;
+ } else if (IS_ALIGNED(iter->dma, I915_GTT_PAGE_SIZE_64K) &&
+ rem >= I915_GTT_PAGE_SIZE_64K &&
+ !(index % 16)) {
+ encode |= GEN12_PTE_PS64;
+ page_size = I915_GTT_PAGE_SIZE_64K;
+ nent = 16;
+ }
}
vaddr = px_vaddr(pt);
@@ -529,7 +543,12 @@ xehpsdv_ppgtt_insert_huge(struct i915_address_space *vm,
do {
GEM_BUG_ON(rem < page_size);
- vaddr[index++] = encode | iter->dma;
+
+ for (i = 0; i < nent; i++) {
+ vaddr[index++] =
+ encode | (iter->dma + i *
+ I915_GTT_PAGE_SIZE);
+ }
start += page_size;
iter->dma += page_size;
@@ -745,6 +764,8 @@ static void __xehpsdv_ppgtt_insert_entry_lm(struct i915_address_space *vm,
GEM_BUG_ON(!IS_ALIGNED(addr, SZ_64K));
GEM_BUG_ON(!IS_ALIGNED(offset, SZ_64K));
+ /* XXX: we don't strictly need to use this layout */
+
if (!pt->is_compact) {
vaddr = px_vaddr(pd);
vaddr[gen8_pd_index(idx, 1)] |= GEN12_PDE_64K;
@@ -929,29 +950,18 @@ struct i915_ppgtt *gen8_ppgtt_create(struct intel_gt *gt,
*/
ppgtt->vm.has_read_only = !IS_GRAPHICS_VER(gt->i915, 11, 12);
- if (HAS_LMEM(gt->i915)) {
+ if (HAS_LMEM(gt->i915))
ppgtt->vm.alloc_pt_dma = alloc_pt_lmem;
-
- /*
- * On some platforms the hw has dropped support for 4K GTT pages
- * when dealing with LMEM, and due to the design of 64K GTT
- * pages in the hw, we can only mark the *entire* page-table as
- * operating in 64K GTT mode, since the enable bit is still on
- * the pde, and not the pte. And since we still need to allow
- * 4K GTT pages for SMEM objects, we can't have a "normal" 4K
- * page-table with scratch pointing to LMEM, since that's
- * undefined from the hw pov. The simplest solution is to just
- * move the 64K scratch page to SMEM on such platforms and call
- * it a day, since that should work for all configurations.
- */
- if (HAS_64K_PAGES(gt->i915))
- ppgtt->vm.alloc_scratch_dma = alloc_pt_dma;
- else
- ppgtt->vm.alloc_scratch_dma = alloc_pt_lmem;
- } else {
+ else
ppgtt->vm.alloc_pt_dma = alloc_pt_dma;
- ppgtt->vm.alloc_scratch_dma = alloc_pt_dma;
- }
+
+ /*
+ * Using SMEM here instead of LMEM has the advantage of not reserving
+ * high performance memory for a "never" used filler page. It also
+ * removes the device access that would be required to initialise the
+ * scratch page, reducing pressure on an even scarcer resource.
+ */
+ ppgtt->vm.alloc_scratch_dma = alloc_pt_dma;
ppgtt->vm.pte_encode = gen8_pte_encode;
diff --git a/drivers/gpu/drm/i915/gt/intel_context.h b/drivers/gpu/drm/i915/gt/intel_context.h
index be09fb2e883a..fb62b7b8cbcd 100644
--- a/drivers/gpu/drm/i915/gt/intel_context.h
+++ b/drivers/gpu/drm/i915/gt/intel_context.h
@@ -276,6 +276,14 @@ static inline bool intel_context_is_barrier(const struct intel_context *ce)
return test_bit(CONTEXT_BARRIER_BIT, &ce->flags);
}
+static inline void intel_context_close(struct intel_context *ce)
+{
+ set_bit(CONTEXT_CLOSED_BIT, &ce->flags);
+
+ if (ce->ops->close)
+ ce->ops->close(ce);
+}
+
static inline bool intel_context_is_closed(const struct intel_context *ce)
{
return test_bit(CONTEXT_CLOSED_BIT, &ce->flags);
diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h
index 04eacae1aca5..e36670f2e626 100644
--- a/drivers/gpu/drm/i915/gt/intel_context_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_context_types.h
@@ -43,6 +43,8 @@ struct intel_context_ops {
void (*revoke)(struct intel_context *ce, struct i915_request *rq,
unsigned int preempt_timeout_ms);
+ void (*close)(struct intel_context *ce);
+
int (*pre_pin)(struct intel_context *ce, struct i915_gem_ww_ctx *ww, void **vaddr);
int (*pin)(struct intel_context *ce, void *vaddr);
void (*unpin)(struct intel_context *ce);
@@ -197,8 +199,6 @@ struct intel_context {
* context's submissions is complete.
*/
struct i915_sw_fence blocked;
- /** @number_committed_requests: number of committed requests */
- int number_committed_requests;
/** @requests: list of active requests on this context */
struct list_head requests;
/** @prio: the context's current guc priority */
@@ -208,6 +208,11 @@ struct intel_context {
* each priority bucket
*/
u32 prio_count[GUC_CLIENT_PRIORITY_NUM];
+ /**
+ * @sched_disable_delay_work: worker to disable scheduling on this
+ * context
+ */
+ struct delayed_work sched_disable_delay_work;
} guc_state;
struct {
diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h
index 04e435bce79b..cbc8b857d5f7 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine.h
@@ -348,4 +348,10 @@ intel_engine_get_hung_context(struct intel_engine_cs *engine)
return engine->hung_ce;
}
+u64 intel_clamp_heartbeat_interval_ms(struct intel_engine_cs *engine, u64 value);
+u64 intel_clamp_max_busywait_duration_ns(struct intel_engine_cs *engine, u64 value);
+u64 intel_clamp_preempt_timeout_ms(struct intel_engine_cs *engine, u64 value);
+u64 intel_clamp_stop_timeout_ms(struct intel_engine_cs *engine, u64 value);
+u64 intel_clamp_timeslice_duration_ms(struct intel_engine_cs *engine, u64 value);
+
#endif /* _INTEL_RINGBUFFER_H_ */
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index 1f7188129cd1..c33e0d72d670 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -13,6 +13,8 @@
#include "i915_cmd_parser.h"
#include "i915_drv.h"
+#include "i915_irq.h"
+#include "i915_reg.h"
#include "intel_breadcrumbs.h"
#include "intel_context.h"
#include "intel_engine.h"
@@ -244,6 +246,13 @@ static const struct engine_info intel_engines[] = {
{ .graphics_ver = 12, .base = GEN12_COMPUTE3_RING_BASE }
}
},
+ [GSC0] = {
+ .class = OTHER_CLASS,
+ .instance = OTHER_GSC_INSTANCE,
+ .mmio_bases = {
+ { .graphics_ver = 12, .base = MTL_GSC_RING_BASE }
+ }
+ },
};
/**
@@ -324,6 +333,7 @@ u32 intel_engine_context_size(struct intel_gt *gt, u8 class)
case VIDEO_DECODE_CLASS:
case VIDEO_ENHANCEMENT_CLASS:
case COPY_ENGINE_CLASS:
+ case OTHER_CLASS:
if (GRAPHICS_VER(gt->i915) < 8)
return 0;
return GEN8_LR_CONTEXT_OTHER_SIZE;
@@ -415,6 +425,7 @@ static u32 get_reset_domain(u8 ver, enum intel_engine_id id)
[CCS1] = GEN11_GRDOM_RENDER,
[CCS2] = GEN11_GRDOM_RENDER,
[CCS3] = GEN11_GRDOM_RENDER,
+ [GSC0] = GEN12_GRDOM_GSC,
};
GEM_BUG_ON(id >= ARRAY_SIZE(engine_reset_domains) ||
!engine_reset_domains[id]);
@@ -486,6 +497,17 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id,
engine->logical_mask = BIT(logical_instance);
__sprint_engine_name(engine);
+ if ((engine->class == COMPUTE_CLASS && !RCS_MASK(engine->gt) &&
+ __ffs(CCS_MASK(engine->gt)) == engine->instance) ||
+ engine->class == RENDER_CLASS)
+ engine->flags |= I915_ENGINE_FIRST_RENDER_COMPUTE;
+
+ /* features common between engines sharing EUs */
+ if (engine->class == RENDER_CLASS || engine->class == COMPUTE_CLASS) {
+ engine->flags |= I915_ENGINE_HAS_RCS_REG_STATE;
+ engine->flags |= I915_ENGINE_HAS_EU_PRIORITY;
+ }
+
engine->props.heartbeat_interval_ms =
CONFIG_DRM_I915_HEARTBEAT_INTERVAL;
engine->props.max_busywait_duration_ns =
@@ -497,20 +519,34 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id,
engine->props.timeslice_duration_ms =
CONFIG_DRM_I915_TIMESLICE_DURATION;
- /* Override to uninterruptible for OpenCL workloads. */
- if (GRAPHICS_VER(i915) == 12 && engine->class == RENDER_CLASS)
- engine->props.preempt_timeout_ms = 0;
-
- if ((engine->class == COMPUTE_CLASS && !RCS_MASK(engine->gt) &&
- __ffs(CCS_MASK(engine->gt)) == engine->instance) ||
- engine->class == RENDER_CLASS)
- engine->flags |= I915_ENGINE_FIRST_RENDER_COMPUTE;
-
- /* features common between engines sharing EUs */
- if (engine->class == RENDER_CLASS || engine->class == COMPUTE_CLASS) {
- engine->flags |= I915_ENGINE_HAS_RCS_REG_STATE;
- engine->flags |= I915_ENGINE_HAS_EU_PRIORITY;
- }
+ /*
+ * Mid-thread pre-emption is not available in Gen12. Unfortunately,
+ * some compute workloads run quite long threads. That means they get
+ * reset due to not pre-empting in a timely manner. So, bump the
+ * pre-emption timeout value to be much higher for compute engines.
+ */
+ if (GRAPHICS_VER(i915) == 12 && (engine->flags & I915_ENGINE_HAS_RCS_REG_STATE))
+ engine->props.preempt_timeout_ms = CONFIG_DRM_I915_PREEMPT_TIMEOUT_COMPUTE;
+
+ /* Cap properties according to any system limits */
+#define CLAMP_PROP(field) \
+ do { \
+ u64 clamp = intel_clamp_##field(engine, engine->props.field); \
+ if (clamp != engine->props.field) { \
+ drm_notice(&engine->i915->drm, \
+ "Warning, clamping %s to %lld to prevent overflow\n", \
+ #field, clamp); \
+ engine->props.field = clamp; \
+ } \
+ } while (0)
+
+ CLAMP_PROP(heartbeat_interval_ms);
+ CLAMP_PROP(max_busywait_duration_ns);
+ CLAMP_PROP(preempt_timeout_ms);
+ CLAMP_PROP(stop_timeout_ms);
+ CLAMP_PROP(timeslice_duration_ms);
+
+#undef CLAMP_PROP
engine->defaults = engine->props; /* never to change again */
@@ -534,6 +570,55 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id,
return 0;
}
+u64 intel_clamp_heartbeat_interval_ms(struct intel_engine_cs *engine, u64 value)
+{
+ value = min_t(u64, value, jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT));
+
+ return value;
+}
+
+u64 intel_clamp_max_busywait_duration_ns(struct intel_engine_cs *engine, u64 value)
+{
+ value = min(value, jiffies_to_nsecs(2));
+
+ return value;
+}
+
+u64 intel_clamp_preempt_timeout_ms(struct intel_engine_cs *engine, u64 value)
+{
+ /*
+ * NB: The GuC API only supports 32bit values. However, the limit is further
+ * reduced due to internal calculations which would otherwise overflow.
+ */
+ if (intel_guc_submission_is_wanted(&engine->gt->uc.guc))
+ value = min_t(u64, value, guc_policy_max_preempt_timeout_ms());
+
+ value = min_t(u64, value, jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT));
+
+ return value;
+}
+
+u64 intel_clamp_stop_timeout_ms(struct intel_engine_cs *engine, u64 value)
+{
+ value = min_t(u64, value, jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT));
+
+ return value;
+}
+
+u64 intel_clamp_timeslice_duration_ms(struct intel_engine_cs *engine, u64 value)
+{
+ /*
+ * NB: The GuC API only supports 32bit values. However, the limit is further
+ * reduced due to internal calculations which would otherwise overflow.
+ */
+ if (intel_guc_submission_is_wanted(&engine->gt->uc.guc))
+ value = min_t(u64, value, guc_policy_max_exec_quantum_ms());
+
+ value = min_t(u64, value, jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT));
+
+ return value;
+}
+
static void __setup_engine_capabilities(struct intel_engine_cs *engine)
{
struct drm_i915_private *i915 = engine->i915;
@@ -1274,8 +1359,13 @@ int intel_engines_init(struct intel_gt *gt)
return err;
err = setup(engine);
- if (err)
+ if (err) {
+ intel_engine_cleanup_common(engine);
return err;
+ }
+
+ /* The backend should now be responsible for cleanup */
+ GEM_BUG_ON(engine->release == NULL);
err = engine_init_common(engine);
if (err)
@@ -1554,11 +1644,11 @@ void intel_engine_get_instdone(const struct intel_engine_cs *engine,
for_each_ss_steering(iter, engine->gt, slice, subslice) {
instdone->sampler[slice][subslice] =
intel_gt_mcr_read(engine->gt,
- GEN7_SAMPLER_INSTDONE,
+ GEN8_SAMPLER_INSTDONE,
slice, subslice);
instdone->row[slice][subslice] =
intel_gt_mcr_read(engine->gt,
- GEN7_ROW_INSTDONE,
+ GEN8_ROW_INSTDONE,
slice, subslice);
}
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
index a3698f611f45..9a527e1f5be6 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_heartbeat.c
@@ -22,9 +22,37 @@
static bool next_heartbeat(struct intel_engine_cs *engine)
{
+ struct i915_request *rq;
long delay;
delay = READ_ONCE(engine->props.heartbeat_interval_ms);
+
+ rq = engine->heartbeat.systole;
+
+ /*
+ * FIXME: The final period extension is disabled if the period has been
+ * modified from the default. This is to prevent issues with certain
+ * selftests which override the value and expect specific behaviour.
+ * Once the selftests have been updated to either cope with variable
+ * heartbeat periods (or to override the pre-emption timeout as well,
+ * or just to add a selftest specific override of the extension), the
+ * generic override can be removed.
+ */
+ if (rq && rq->sched.attr.priority >= I915_PRIORITY_BARRIER &&
+ delay == engine->defaults.heartbeat_interval_ms) {
+ long longer;
+
+ /*
+ * The final try is at the highest priority possible. Up until now
+ * a pre-emption might not even have been attempted. So make sure
+ * this last attempt allows enough time for a pre-emption to occur.
+ */
+ longer = READ_ONCE(engine->props.preempt_timeout_ms) * 2;
+ longer = intel_clamp_heartbeat_interval_ms(engine, longer);
+ if (longer > delay)
+ delay = longer;
+ }
+
if (!delay)
return false;
@@ -288,6 +316,17 @@ int intel_engine_set_heartbeat(struct intel_engine_cs *engine,
if (!delay && !intel_engine_has_preempt_reset(engine))
return -ENODEV;
+ /* FIXME: Remove together with equally marked hack in next_heartbeat. */
+ if (delay != engine->defaults.heartbeat_interval_ms &&
+ delay < 2 * engine->props.preempt_timeout_ms) {
+ if (intel_engine_uses_guc(engine))
+ drm_notice(&engine->i915->drm, "%s heartbeat interval adjusted to a non-default value which may downgrade individual engine resets to full GPU resets!\n",
+ engine->name);
+ else
+ drm_notice(&engine->i915->drm, "%s heartbeat interval adjusted to a non-default value which may cause engine resets to target innocent contexts!\n",
+ engine->name);
+ }
+
intel_engine_pm_get(engine);
err = mutex_lock_interruptible(&ce->timeline->mutex);
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_regs.h b/drivers/gpu/drm/i915/gt/intel_engine_regs.h
index fe1a0d5fd4b1..ee3efd06ee54 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_regs.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine_regs.h
@@ -201,6 +201,7 @@
#define RING_CONTEXT_STATUS_PTR(base) _MMIO((base) + 0x3a0)
#define RING_CTX_TIMESTAMP(base) _MMIO((base) + 0x3a8) /* gen8+ */
#define RING_PREDICATE_RESULT(base) _MMIO((base) + 0x3b8)
+#define MI_PREDICATE_RESULT_2_ENGINE(base) _MMIO((base) + 0x3bc)
#define RING_FORCE_TO_NONPRIV(base, i) _MMIO(((base) + 0x4D0) + (i) * 4)
#define RING_FORCE_TO_NONPRIV_DENY REG_BIT(30)
#define RING_FORCE_TO_NONPRIV_ADDRESS_MASK REG_GENMASK(25, 2)
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h
index 6b5d4ea22b67..4fd54fb8810f 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h
@@ -136,6 +136,7 @@ enum intel_engine_id {
CCS2,
CCS3,
#define _CCS(n) (CCS0 + (n))
+ GSC0,
I915_NUM_ENGINES
#define INVALID_ENGINE ((enum intel_engine_id)-1)
};
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_user.c b/drivers/gpu/drm/i915/gt/intel_engine_user.c
index 46a174f8aa00..cd4f1b126f75 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_user.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_user.c
@@ -140,6 +140,7 @@ const char *intel_engine_class_repr(u8 class)
[COPY_ENGINE_CLASS] = "bcs",
[VIDEO_DECODE_CLASS] = "vcs",
[VIDEO_ENHANCEMENT_CLASS] = "vecs",
+ [OTHER_CLASS] = "other",
[COMPUTE_CLASS] = "ccs",
};
@@ -190,6 +191,15 @@ static void add_legacy_ring(struct legacy_ring *ring,
ring->instance++;
}
+static void engine_rename(struct intel_engine_cs *engine, const char *name, u16 instance)
+{
+ char old[sizeof(engine->name)];
+
+ memcpy(old, engine->name, sizeof(engine->name));
+ scnprintf(engine->name, sizeof(engine->name), "%s%u", name, instance);
+ drm_dbg(&engine->i915->drm, "renamed %s to %s\n", old, engine->name);
+}
+
void intel_engines_driver_register(struct drm_i915_private *i915)
{
struct legacy_ring ring = {};
@@ -205,11 +215,19 @@ void intel_engines_driver_register(struct drm_i915_private *i915)
struct intel_engine_cs *engine =
container_of((struct rb_node *)it, typeof(*engine),
uabi_node);
- char old[sizeof(engine->name)];
if (intel_gt_has_unrecoverable_error(engine->gt))
continue; /* ignore incomplete engines */
+ /*
+ * We don't want to expose the GSC engine to the users, but we
+ * still rename it so it is easier to identify in the debug logs
+ */
+ if (engine->id == GSC0) {
+ engine_rename(engine, "gsc", 0);
+ continue;
+ }
+
GEM_BUG_ON(engine->class >= ARRAY_SIZE(uabi_classes));
engine->uabi_class = uabi_classes[engine->class];
@@ -219,11 +237,9 @@ void intel_engines_driver_register(struct drm_i915_private *i915)
i915->engine_uabi_class_count[engine->uabi_class]++;
/* Replace the internal name with the final user facing name */
- memcpy(old, engine->name, sizeof(engine->name));
- scnprintf(engine->name, sizeof(engine->name), "%s%u",
- intel_engine_class_repr(engine->class),
- engine->uabi_instance);
- DRM_DEBUG_DRIVER("renamed %s to %s\n", old, engine->name);
+ engine_rename(engine,
+ intel_engine_class_repr(engine->class),
+ engine->uabi_instance);
rb_link_node(&engine->uabi_node, prev, p);
rb_insert_color(&engine->uabi_node, &i915->uabi_engines);
diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
index c718e6dc40b5..2daffa7c7dfd 100644
--- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
+++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c
@@ -110,6 +110,7 @@
#include <linux/string_helpers.h>
#include "i915_drv.h"
+#include "i915_reg.h"
#include "i915_trace.h"
#include "i915_vgpu.h"
#include "gen8_engine_cs.h"
@@ -3471,9 +3472,9 @@ logical_ring_default_vfuncs(struct intel_engine_cs *engine)
if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50)) {
if (intel_engine_has_preemption(engine))
- engine->emit_bb_start = gen125_emit_bb_start;
+ engine->emit_bb_start = xehp_emit_bb_start;
else
- engine->emit_bb_start = gen125_emit_bb_start_noarb;
+ engine->emit_bb_start = xehp_emit_bb_start_noarb;
} else {
if (intel_engine_has_preemption(engine))
engine->emit_bb_start = gen8_emit_bb_start;
@@ -3689,7 +3690,7 @@ static void virtual_engine_initial_hint(struct virtual_engine *ve)
* NB This does not force us to execute on this engine, it will just
* typically be the first we inspect for submission.
*/
- swp = prandom_u32_max(ve->num_siblings);
+ swp = get_random_u32_below(ve->num_siblings);
if (swp)
swap(ve->siblings[swp], ve->siblings[0]);
}
@@ -3921,6 +3922,7 @@ static struct intel_context *
execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count,
unsigned long flags)
{
+ struct drm_i915_private *i915 = siblings[0]->i915;
struct virtual_engine *ve;
unsigned int n;
int err;
@@ -3929,7 +3931,7 @@ execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count,
if (!ve)
return ERR_PTR(-ENOMEM);
- ve->base.i915 = siblings[0]->i915;
+ ve->base.i915 = i915;
ve->base.gt = siblings[0]->gt;
ve->base.uncore = siblings[0]->uncore;
ve->base.id = -1;
@@ -3988,8 +3990,9 @@ execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count,
GEM_BUG_ON(!is_power_of_2(sibling->mask));
if (sibling->mask & ve->base.mask) {
- DRM_DEBUG("duplicate %s entry in load balancer\n",
- sibling->name);
+ drm_dbg(&i915->drm,
+ "duplicate %s entry in load balancer\n",
+ sibling->name);
err = -EINVAL;
goto err_put;
}
@@ -4023,8 +4026,9 @@ execlists_create_virtual(struct intel_engine_cs **siblings, unsigned int count,
*/
if (ve->base.class != OTHER_CLASS) {
if (ve->base.class != sibling->class) {
- DRM_DEBUG("invalid mixing of engine class, sibling %d, already %d\n",
- sibling->class, ve->base.class);
+ drm_dbg(&i915->drm,
+ "invalid mixing of engine class, sibling %d, already %d\n",
+ sibling->class, ve->base.class);
err = -EINVAL;
goto err_put;
}
diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c
index 2049a00417af..8145851ad23d 100644
--- a/drivers/gpu/drm/i915/gt/intel_ggtt.c
+++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c
@@ -560,7 +560,7 @@ static int init_ggtt(struct i915_ggtt *ggtt)
* why.
*/
ggtt->pin_bias = max_t(u32, I915_GTT_PAGE_SIZE,
- intel_wopcm_guc_size(&ggtt->vm.i915->wopcm));
+ intel_wopcm_guc_size(&ggtt->vm.gt->wopcm));
ret = intel_vgt_balloon(ggtt);
if (ret)
@@ -871,8 +871,8 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size)
u32 pte_flags;
int ret;
- GEM_WARN_ON(pci_resource_len(pdev, GTTMMADR_BAR) != gen6_gttmmadr_size(i915));
- phys_addr = pci_resource_start(pdev, GTTMMADR_BAR) + gen6_gttadr_offset(i915);
+ GEM_WARN_ON(pci_resource_len(pdev, GEN4_GTTMMADR_BAR) != gen6_gttmmadr_size(i915));
+ phys_addr = pci_resource_start(pdev, GEN4_GTTMMADR_BAR) + gen6_gttadr_offset(i915);
/*
* On BXT+/ICL+ writes larger than 64 bit to the GTT pagetable range
@@ -931,11 +931,11 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
unsigned int size;
u16 snb_gmch_ctl;
- if (!HAS_LMEM(i915)) {
- if (!i915_pci_resource_valid(pdev, GTT_APERTURE_BAR))
+ if (!HAS_LMEM(i915) && !HAS_LMEMBAR_SMEM_STOLEN(i915)) {
+ if (!i915_pci_resource_valid(pdev, GEN4_GMADR_BAR))
return -ENXIO;
- ggtt->gmadr = pci_resource(pdev, GTT_APERTURE_BAR);
+ ggtt->gmadr = pci_resource(pdev, GEN4_GMADR_BAR);
ggtt->mappable_end = resource_size(&ggtt->gmadr);
}
@@ -986,7 +986,7 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
ggtt->vm.pte_encode = gen8_ggtt_pte_encode;
- setup_private_pat(ggtt->vm.gt->uncore);
+ setup_private_pat(ggtt->vm.gt);
return ggtt_probe_common(ggtt, size);
}
@@ -1089,10 +1089,10 @@ static int gen6_gmch_probe(struct i915_ggtt *ggtt)
unsigned int size;
u16 snb_gmch_ctl;
- if (!i915_pci_resource_valid(pdev, GTT_APERTURE_BAR))
+ if (!i915_pci_resource_valid(pdev, GEN4_GMADR_BAR))
return -ENXIO;
- ggtt->gmadr = pci_resource(pdev, GTT_APERTURE_BAR);
+ ggtt->gmadr = pci_resource(pdev, GEN4_GMADR_BAR);
ggtt->mappable_end = resource_size(&ggtt->gmadr);
/*
@@ -1308,7 +1308,7 @@ void i915_ggtt_resume(struct i915_ggtt *ggtt)
wbinvd_on_all_cpus();
if (GRAPHICS_VER(ggtt->vm.i915) >= 8)
- setup_private_pat(ggtt->vm.gt->uncore);
+ setup_private_pat(ggtt->vm.gt);
intel_ggtt_restore_fences(ggtt);
}
diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c
index ea775e601686..995082d45cb2 100644
--- a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c
+++ b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c
@@ -816,8 +816,8 @@ i915_gem_object_save_bit_17_swizzle(struct drm_i915_gem_object *obj,
if (obj->bit_17 == NULL) {
obj->bit_17 = bitmap_zalloc(page_count, GFP_KERNEL);
if (obj->bit_17 == NULL) {
- DRM_ERROR("Failed to allocate memory for bit 17 "
- "record\n");
+ drm_err(&to_i915(obj->base.dev)->drm,
+ "Failed to allocate memory for bit 17 record\n");
return;
}
}
diff --git a/drivers/gpu/drm/i915/gt/intel_gpu_commands.h b/drivers/gpu/drm/i915/gt/intel_gpu_commands.h
index d4e9702d3c8e..f50ea92910d9 100644
--- a/drivers/gpu/drm/i915/gt/intel_gpu_commands.h
+++ b/drivers/gpu/drm/i915/gt/intel_gpu_commands.h
@@ -187,6 +187,10 @@
#define MI_BATCH_RESOURCE_STREAMER REG_BIT(10)
#define MI_BATCH_PREDICATE REG_BIT(15) /* HSW+ on RCS only*/
+#define MI_OPCODE(x) (((x) >> 23) & 0x3f)
+#define IS_MI_LRI_CMD(x) (MI_OPCODE(x) == MI_OPCODE(MI_INSTR(0x22, 0)))
+#define MI_LRI_LEN(x) (((x) & 0xff) + 1)
+
/*
* 3D instructions used by the kernel
*/
diff --git a/drivers/gpu/drm/i915/gt/intel_gsc.c b/drivers/gpu/drm/i915/gt/intel_gsc.c
index 7af6db3194dd..976fdf27e790 100644
--- a/drivers/gpu/drm/i915/gt/intel_gsc.c
+++ b/drivers/gpu/drm/i915/gt/intel_gsc.c
@@ -7,6 +7,7 @@
#include <linux/mei_aux.h>
#include "i915_drv.h"
#include "i915_reg.h"
+#include "gem/i915_gem_lmem.h"
#include "gem/i915_gem_region.h"
#include "gt/intel_gsc.h"
#include "gt/intel_gt.h"
@@ -142,8 +143,14 @@ static void gsc_destroy_one(struct drm_i915_private *i915,
struct intel_gsc_intf *intf = &gsc->intf[intf_id];
if (intf->adev) {
- auxiliary_device_delete(&intf->adev->aux_dev);
- auxiliary_device_uninit(&intf->adev->aux_dev);
+ struct auxiliary_device *aux_dev = &intf->adev->aux_dev;
+
+ if (intf_id == 0)
+ intel_huc_unregister_gsc_notifier(&gsc_to_gt(gsc)->uc.huc,
+ aux_dev->dev.bus);
+
+ auxiliary_device_delete(aux_dev);
+ auxiliary_device_uninit(aux_dev);
intf->adev = NULL;
}
@@ -242,14 +249,24 @@ add_device:
goto fail;
}
+ intf->adev = adev; /* needed by the notifier */
+
+ if (intf_id == 0)
+ intel_huc_register_gsc_notifier(&gsc_to_gt(gsc)->uc.huc,
+ aux_dev->dev.bus);
+
ret = auxiliary_device_add(aux_dev);
if (ret < 0) {
drm_err(&i915->drm, "gsc aux add failed %d\n", ret);
+ if (intf_id == 0)
+ intel_huc_unregister_gsc_notifier(&gsc_to_gt(gsc)->uc.huc,
+ aux_dev->dev.bus);
+ intf->adev = NULL;
+
/* adev will be freed with the put_device() and .release sequence */
auxiliary_device_uninit(aux_dev);
goto fail;
}
- intf->adev = adev;
return;
fail:
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c
index 7caa3412a244..767e329e1cc5 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -12,6 +12,7 @@
#include "i915_drv.h"
#include "i915_perf_oa_regs.h"
+#include "i915_reg.h"
#include "intel_context.h"
#include "intel_engine_pm.h"
#include "intel_engine_regs.h"
@@ -40,8 +41,6 @@ void intel_gt_common_init_early(struct intel_gt *gt)
{
spin_lock_init(gt->irq_lock);
- INIT_LIST_HEAD(&gt->lmem_userfault_list);
- mutex_init(&gt->lmem_userfault_lock);
INIT_LIST_HEAD(&gt->closed_vma);
spin_lock_init(&gt->closed_lock);
@@ -56,6 +55,7 @@ void intel_gt_common_init_early(struct intel_gt *gt)
seqcount_mutex_init(&gt->tlb.seqno, &gt->tlb.invalidate_lock);
intel_gt_pm_init_early(gt);
+ intel_wopcm_init_early(&gt->wopcm);
intel_uc_init_early(&gt->uc);
intel_rps_init_early(&gt->rps);
}
@@ -192,7 +192,7 @@ int intel_gt_init_hw(struct intel_gt *gt)
ret = i915_ppgtt_init_hw(gt);
if (ret) {
- DRM_ERROR("Enabling PPGTT failed (%d)\n", ret);
+ drm_err(&i915->drm, "Enabling PPGTT failed (%d)\n", ret);
goto out;
}
@@ -231,6 +231,16 @@ static void gen6_clear_engine_error_register(struct intel_engine_cs *engine)
GEN6_RING_FAULT_REG_POSTING_READ(engine);
}
+i915_reg_t intel_gt_perf_limit_reasons_reg(struct intel_gt *gt)
+{
+ /* GT0_PERF_LIMIT_REASONS is available only for Gen11+ */
+ if (GRAPHICS_VER(gt->i915) < 11)
+ return INVALID_MMIO_REG;
+
+ return gt->type == GT_MEDIA ?
+ MTL_MEDIA_PERF_LIMIT_REASONS : GT0_PERF_LIMIT_REASONS;
+}
+
void
intel_gt_clear_error_registers(struct intel_gt *gt,
intel_engine_mask_t engine_mask)
@@ -254,13 +264,17 @@ intel_gt_clear_error_registers(struct intel_gt *gt,
* some errors might have become stuck,
* mask them.
*/
- DRM_DEBUG_DRIVER("EIR stuck: 0x%08x, masking\n", eir);
+ drm_dbg(&gt->i915->drm, "EIR stuck: 0x%08x, masking\n", eir);
rmw_set(uncore, EMR, eir);
intel_uncore_write(uncore, GEN2_IIR,
I915_MASTER_ERROR_INTERRUPT);
}
- if (GRAPHICS_VER(i915) >= 12) {
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) {
+ intel_gt_mcr_multicast_rmw(gt, XEHP_RING_FAULT_REG,
+ RING_FAULT_VALID, 0);
+ intel_gt_mcr_read_any(gt, XEHP_RING_FAULT_REG);
+ } else if (GRAPHICS_VER(i915) >= 12) {
rmw_clear(uncore, GEN12_RING_FAULT_REG, RING_FAULT_VALID);
intel_uncore_posting_read(uncore, GEN12_RING_FAULT_REG);
} else if (GRAPHICS_VER(i915) >= 8) {
@@ -298,6 +312,42 @@ static void gen6_check_faults(struct intel_gt *gt)
}
}
+static void xehp_check_faults(struct intel_gt *gt)
+{
+ u32 fault;
+
+ /*
+ * Although the fault register now lives in an MCR register range,
+ * the GAM registers are special and we only truly need to read
+ * the "primary" GAM instance rather than handling each instance
+ * individually. intel_gt_mcr_read_any() will automatically steer
+ * toward the primary instance.
+ */
+ fault = intel_gt_mcr_read_any(gt, XEHP_RING_FAULT_REG);
+ if (fault & RING_FAULT_VALID) {
+ u32 fault_data0, fault_data1;
+ u64 fault_addr;
+
+ fault_data0 = intel_gt_mcr_read_any(gt, XEHP_FAULT_TLB_DATA0);
+ fault_data1 = intel_gt_mcr_read_any(gt, XEHP_FAULT_TLB_DATA1);
+
+ fault_addr = ((u64)(fault_data1 & FAULT_VA_HIGH_BITS) << 44) |
+ ((u64)fault_data0 << 12);
+
+ drm_dbg(&gt->i915->drm, "Unexpected fault\n"
+ "\tAddr: 0x%08x_%08x\n"
+ "\tAddress space: %s\n"
+ "\tEngine ID: %d\n"
+ "\tSource ID: %d\n"
+ "\tType: %d\n",
+ upper_32_bits(fault_addr), lower_32_bits(fault_addr),
+ fault_data1 & FAULT_GTT_SEL ? "GGTT" : "PPGTT",
+ GEN8_RING_FAULT_ENGINE_ID(fault),
+ RING_FAULT_SRCID(fault),
+ RING_FAULT_FAULT_TYPE(fault));
+ }
+}
+
static void gen8_check_faults(struct intel_gt *gt)
{
struct intel_uncore *uncore = gt->uncore;
@@ -344,7 +394,9 @@ void intel_gt_check_and_clear_faults(struct intel_gt *gt)
struct drm_i915_private *i915 = gt->i915;
/* From GEN8 onwards we only have one 'All Engine Fault Register' */
- if (GRAPHICS_VER(i915) >= 8)
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50))
+ xehp_check_faults(gt);
+ else if (GRAPHICS_VER(i915) >= 8)
gen8_check_faults(gt);
else if (GRAPHICS_VER(i915) >= 6)
gen6_check_faults(gt);
@@ -812,7 +864,6 @@ static int intel_gt_tile_setup(struct intel_gt *gt, phys_addr_t phys_addr)
}
intel_uncore_init_early(gt->uncore, gt);
- intel_wakeref_auto_init(&gt->userfault_wakeref, gt->uncore->rpm);
ret = intel_uncore_setup_mmio(gt->uncore, phys_addr);
if (ret)
@@ -833,7 +884,7 @@ int intel_gt_probe_all(struct drm_i915_private *i915)
unsigned int i;
int ret;
- mmio_bar = GRAPHICS_VER(i915) == 2 ? GEN2_GTTMMADR_BAR : GTTMMADR_BAR;
+ mmio_bar = intel_mmio_bar(GRAPHICS_VER(i915));
phys_addr = pci_resource_start(pdev, mmio_bar);
/*
@@ -944,7 +995,10 @@ void intel_gt_info_print(const struct intel_gt_info *info,
}
struct reg_and_bit {
- i915_reg_t reg;
+ union {
+ i915_reg_t reg;
+ i915_mcr_reg_t mcr_reg;
+ };
u32 bit;
};
@@ -970,6 +1024,32 @@ get_reg_and_bit(const struct intel_engine_cs *engine, const bool gen8,
return rb;
}
+/*
+ * HW architecture suggest typical invalidation time at 40us,
+ * with pessimistic cases up to 100us and a recommendation to
+ * cap at 1ms. We go a bit higher just in case.
+ */
+#define TLB_INVAL_TIMEOUT_US 100
+#define TLB_INVAL_TIMEOUT_MS 4
+
+/*
+ * On Xe_HP the TLB invalidation registers are located at the same MMIO offsets
+ * but are now considered MCR registers. Since they exist within a GAM range,
+ * the primary instance of the register rolls up the status from each unit.
+ */
+static int wait_for_invalidate(struct intel_gt *gt, struct reg_and_bit rb)
+{
+ if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 50))
+ return intel_gt_mcr_wait_for_reg(gt, rb.mcr_reg, rb.bit, 0,
+ TLB_INVAL_TIMEOUT_US,
+ TLB_INVAL_TIMEOUT_MS);
+ else
+ return __intel_wait_for_register_fw(gt->uncore, rb.reg, rb.bit, 0,
+ TLB_INVAL_TIMEOUT_US,
+ TLB_INVAL_TIMEOUT_MS,
+ NULL);
+}
+
static void mmio_invalidate_full(struct intel_gt *gt)
{
static const i915_reg_t gen8_regs[] = {
@@ -985,6 +1065,13 @@ static void mmio_invalidate_full(struct intel_gt *gt)
[COPY_ENGINE_CLASS] = GEN12_BLT_TLB_INV_CR,
[COMPUTE_CLASS] = GEN12_COMPCTX_TLB_INV_CR,
};
+ static const i915_mcr_reg_t xehp_regs[] = {
+ [RENDER_CLASS] = XEHP_GFX_TLB_INV_CR,
+ [VIDEO_DECODE_CLASS] = XEHP_VD_TLB_INV_CR,
+ [VIDEO_ENHANCEMENT_CLASS] = XEHP_VE_TLB_INV_CR,
+ [COPY_ENGINE_CLASS] = XEHP_BLT_TLB_INV_CR,
+ [COMPUTE_CLASS] = XEHP_COMPCTX_TLB_INV_CR,
+ };
struct drm_i915_private *i915 = gt->i915;
struct intel_uncore *uncore = gt->uncore;
struct intel_engine_cs *engine;
@@ -993,7 +1080,10 @@ static void mmio_invalidate_full(struct intel_gt *gt)
const i915_reg_t *regs;
unsigned int num = 0;
- if (GRAPHICS_VER(i915) == 12) {
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) {
+ regs = NULL;
+ num = ARRAY_SIZE(xehp_regs);
+ } else if (GRAPHICS_VER(i915) == 12) {
regs = gen12_regs;
num = ARRAY_SIZE(gen12_regs);
} else if (GRAPHICS_VER(i915) >= 8 && GRAPHICS_VER(i915) <= 11) {
@@ -1018,16 +1108,22 @@ static void mmio_invalidate_full(struct intel_gt *gt)
if (!intel_engine_pm_is_awake(engine))
continue;
- rb = get_reg_and_bit(engine, regs == gen8_regs, regs, num);
- if (!i915_mmio_reg_offset(rb.reg))
- continue;
-
- if (GRAPHICS_VER(i915) == 12 && (engine->class == VIDEO_DECODE_CLASS ||
- engine->class == VIDEO_ENHANCEMENT_CLASS ||
- engine->class == COMPUTE_CLASS))
- rb.bit = _MASKED_BIT_ENABLE(rb.bit);
-
- intel_uncore_write_fw(uncore, rb.reg, rb.bit);
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) {
+ intel_gt_mcr_multicast_write_fw(gt,
+ xehp_regs[engine->class],
+ BIT(engine->instance));
+ } else {
+ rb = get_reg_and_bit(engine, regs == gen8_regs, regs, num);
+ if (!i915_mmio_reg_offset(rb.reg))
+ continue;
+
+ if (GRAPHICS_VER(i915) == 12 && (engine->class == VIDEO_DECODE_CLASS ||
+ engine->class == VIDEO_ENHANCEMENT_CLASS ||
+ engine->class == COMPUTE_CLASS))
+ rb.bit = _MASKED_BIT_ENABLE(rb.bit);
+
+ intel_uncore_write_fw(uncore, rb.reg, rb.bit);
+ }
awake |= engine->mask;
}
@@ -1047,22 +1143,17 @@ static void mmio_invalidate_full(struct intel_gt *gt)
for_each_engine_masked(engine, gt, awake, tmp) {
struct reg_and_bit rb;
- /*
- * HW architecture suggest typical invalidation time at 40us,
- * with pessimistic cases up to 100us and a recommendation to
- * cap at 1ms. We go a bit higher just in case.
- */
- const unsigned int timeout_us = 100;
- const unsigned int timeout_ms = 4;
-
- rb = get_reg_and_bit(engine, regs == gen8_regs, regs, num);
- if (__intel_wait_for_register_fw(uncore,
- rb.reg, rb.bit, 0,
- timeout_us, timeout_ms,
- NULL))
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) {
+ rb.mcr_reg = xehp_regs[engine->class];
+ rb.bit = BIT(engine->instance);
+ } else {
+ rb = get_reg_and_bit(engine, regs == gen8_regs, regs, num);
+ }
+
+ if (wait_for_invalidate(gt, rb))
drm_err_ratelimited(&gt->i915->drm,
"%s TLB invalidation did not complete in %ums!\n",
- engine->name, timeout_ms);
+ engine->name, TLB_INVAL_TIMEOUT_MS);
}
/*
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h
index 2ee582e287c8..e0365d556248 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt.h
@@ -60,6 +60,7 @@ void intel_gt_driver_late_release_all(struct drm_i915_private *i915);
int intel_gt_wait_for_idle(struct intel_gt *gt, long timeout);
void intel_gt_check_and_clear_faults(struct intel_gt *gt);
+i915_reg_t intel_gt_perf_limit_reasons_reg(struct intel_gt *gt);
void intel_gt_clear_error_registers(struct intel_gt *gt,
intel_engine_mask_t engine_mask);
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c b/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c
index 3f656d3dba9a..2a6a4ca7fdad 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_clock_utils.c
@@ -107,7 +107,7 @@ static u32 gen9_read_clock_frequency(struct intel_uncore *uncore)
return freq;
}
-static u32 gen5_read_clock_frequency(struct intel_uncore *uncore)
+static u32 gen6_read_clock_frequency(struct intel_uncore *uncore)
{
/*
* PRMs say:
@@ -119,7 +119,27 @@ static u32 gen5_read_clock_frequency(struct intel_uncore *uncore)
return 12500000;
}
-static u32 gen2_read_clock_frequency(struct intel_uncore *uncore)
+static u32 gen5_read_clock_frequency(struct intel_uncore *uncore)
+{
+ /*
+ * 63:32 increments every 1000 ns
+ * 31:0 mbz
+ */
+ return 1000000000 / 1000;
+}
+
+static u32 g4x_read_clock_frequency(struct intel_uncore *uncore)
+{
+ /*
+ * 63:20 increments every 1/4 ns
+ * 19:0 mbz
+ *
+ * -> 63:32 increments every 1024 ns
+ */
+ return 1000000000 / 1024;
+}
+
+static u32 gen4_read_clock_frequency(struct intel_uncore *uncore)
{
/*
* PRMs say:
@@ -127,8 +147,10 @@ static u32 gen2_read_clock_frequency(struct intel_uncore *uncore)
* "The value in this register increments once every 16
* hclks." (through the “Clocking Configurationâ€
* (“CLKCFGâ€) MCHBAR register)
+ *
+ * Testing on actual hardware has shown there is no /16.
*/
- return RUNTIME_INFO(uncore->i915)->rawclk_freq * 1000 / 16;
+ return RUNTIME_INFO(uncore->i915)->rawclk_freq * 1000;
}
static u32 read_clock_frequency(struct intel_uncore *uncore)
@@ -137,10 +159,16 @@ static u32 read_clock_frequency(struct intel_uncore *uncore)
return gen11_read_clock_frequency(uncore);
else if (GRAPHICS_VER(uncore->i915) >= 9)
return gen9_read_clock_frequency(uncore);
- else if (GRAPHICS_VER(uncore->i915) >= 5)
+ else if (GRAPHICS_VER(uncore->i915) >= 6)
+ return gen6_read_clock_frequency(uncore);
+ else if (GRAPHICS_VER(uncore->i915) == 5)
return gen5_read_clock_frequency(uncore);
+ else if (IS_G4X(uncore->i915))
+ return g4x_read_clock_frequency(uncore);
+ else if (GRAPHICS_VER(uncore->i915) == 4)
+ return gen4_read_clock_frequency(uncore);
else
- return gen2_read_clock_frequency(uncore);
+ return 0;
}
void intel_gt_init_clock_frequency(struct intel_gt *gt)
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_irq.c b/drivers/gpu/drm/i915/gt/intel_gt_irq.c
index f26882fdc24c..6f6b9e04d916 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_irq.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_irq.c
@@ -17,6 +17,9 @@
static void guc_irq_handler(struct intel_guc *guc, u16 iir)
{
+ if (unlikely(!guc->interrupts.enabled))
+ return;
+
if (iir & GUC_INTR_GUC2HOST)
intel_guc_to_host_event_handler(guc);
}
@@ -44,8 +47,9 @@ gen11_gt_engine_identity(struct intel_gt *gt,
!time_after32(local_clock() >> 10, timeout_ts));
if (unlikely(!(ident & GEN11_INTR_DATA_VALID))) {
- DRM_ERROR("INTR_IDENTITY_REG%u:%u 0x%08x not valid!\n",
- bank, bit, ident);
+ drm_err(&gt->i915->drm,
+ "INTR_IDENTITY_REG%u:%u 0x%08x not valid!\n",
+ bank, bit, ident);
return 0;
}
@@ -81,35 +85,27 @@ gen11_other_irq_handler(struct intel_gt *gt, const u8 instance,
instance, iir);
}
-static void
-gen11_engine_irq_handler(struct intel_gt *gt, const u8 class,
- const u8 instance, const u16 iir)
+static struct intel_gt *pick_gt(struct intel_gt *gt, u8 class, u8 instance)
{
- struct intel_engine_cs *engine;
-
- /*
- * Platforms with standalone media have their media engines in another
- * GT.
- */
- if (MEDIA_VER(gt->i915) >= 13 &&
- (class == VIDEO_DECODE_CLASS || class == VIDEO_ENHANCEMENT_CLASS)) {
- if (!gt->i915->media_gt)
- goto err;
+ struct intel_gt *media_gt = gt->i915->media_gt;
- gt = gt->i915->media_gt;
+ /* we expect the non-media gt to be passed in */
+ GEM_BUG_ON(gt == media_gt);
+
+ if (!media_gt)
+ return gt;
+
+ switch (class) {
+ case VIDEO_DECODE_CLASS:
+ case VIDEO_ENHANCEMENT_CLASS:
+ return media_gt;
+ case OTHER_CLASS:
+ if (instance == OTHER_GSC_INSTANCE && HAS_ENGINE(media_gt, GSC0))
+ return media_gt;
+ fallthrough;
+ default:
+ return gt;
}
-
- if (instance <= MAX_ENGINE_INSTANCE)
- engine = gt->engine_class[class][instance];
- else
- engine = NULL;
-
- if (likely(engine))
- return intel_engine_cs_irq(engine, iir);
-
-err:
- WARN_ONCE(1, "unhandled engine interrupt class=0x%x, instance=0x%x\n",
- class, instance);
}
static void
@@ -122,8 +118,17 @@ gen11_gt_identity_handler(struct intel_gt *gt, const u32 identity)
if (unlikely(!intr))
return;
- if (class <= COPY_ENGINE_CLASS || class == COMPUTE_CLASS)
- return gen11_engine_irq_handler(gt, class, instance, intr);
+ /*
+ * Platforms with standalone media have the media and GSC engines in
+ * another GT.
+ */
+ gt = pick_gt(gt, class, instance);
+
+ if (class <= MAX_ENGINE_CLASS && instance <= MAX_ENGINE_INSTANCE) {
+ struct intel_engine_cs *engine = gt->engine_class[class][instance];
+ if (engine)
+ return intel_engine_cs_irq(engine, intr);
+ }
if (class == OTHER_CLASS)
return gen11_other_irq_handler(gt, instance, intr);
@@ -206,7 +211,7 @@ void gen11_gt_irq_reset(struct intel_gt *gt)
intel_uncore_write(uncore, GEN11_VCS_VECS_INTR_ENABLE, 0);
if (CCS_MASK(gt))
intel_uncore_write(uncore, GEN12_CCS_RSVD_INTR_ENABLE, 0);
- if (HAS_HECI_GSC(gt->i915))
+ if (HAS_HECI_GSC(gt->i915) || HAS_ENGINE(gt, GSC0))
intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_ENABLE, 0);
/* Restore masks irqs on RCS, BCS, VCS and VECS engines. */
@@ -233,7 +238,7 @@ void gen11_gt_irq_reset(struct intel_gt *gt)
intel_uncore_write(uncore, GEN12_CCS0_CCS1_INTR_MASK, ~0);
if (HAS_ENGINE(gt, CCS2) || HAS_ENGINE(gt, CCS3))
intel_uncore_write(uncore, GEN12_CCS2_CCS3_INTR_MASK, ~0);
- if (HAS_HECI_GSC(gt->i915))
+ if (HAS_HECI_GSC(gt->i915) || HAS_ENGINE(gt, GSC0))
intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_MASK, ~0);
intel_uncore_write(uncore, GEN11_GPM_WGBOXPERF_INTR_ENABLE, 0);
@@ -249,7 +254,8 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
{
struct intel_uncore *uncore = gt->uncore;
u32 irqs = GT_RENDER_USER_INTERRUPT;
- const u32 gsc_mask = GSC_IRQ_INTF(0) | GSC_IRQ_INTF(1);
+ u32 guc_mask = intel_uc_wants_guc(&gt->uc) ? GUC_INTR_GUC2HOST : 0;
+ u32 gsc_mask = 0;
u32 dmask;
u32 smask;
@@ -261,6 +267,11 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
dmask = irqs << 16 | irqs;
smask = irqs << 16;
+ if (HAS_ENGINE(gt, GSC0))
+ gsc_mask = irqs;
+ else if (HAS_HECI_GSC(gt->i915))
+ gsc_mask = GSC_IRQ_INTF(0) | GSC_IRQ_INTF(1);
+
BUILD_BUG_ON(irqs & 0xffff0000);
/* Enable RCS, BCS, VCS and VECS class interrupts. */
@@ -268,9 +279,8 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
intel_uncore_write(uncore, GEN11_VCS_VECS_INTR_ENABLE, dmask);
if (CCS_MASK(gt))
intel_uncore_write(uncore, GEN12_CCS_RSVD_INTR_ENABLE, smask);
- if (HAS_HECI_GSC(gt->i915))
- intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_ENABLE,
- gsc_mask);
+ if (gsc_mask)
+ intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_ENABLE, gsc_mask);
/* Unmask irqs on RCS, BCS, VCS and VECS engines. */
intel_uncore_write(uncore, GEN11_RCS0_RSVD_INTR_MASK, ~smask);
@@ -296,9 +306,22 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
intel_uncore_write(uncore, GEN12_CCS0_CCS1_INTR_MASK, ~dmask);
if (HAS_ENGINE(gt, CCS2) || HAS_ENGINE(gt, CCS3))
intel_uncore_write(uncore, GEN12_CCS2_CCS3_INTR_MASK, ~dmask);
- if (HAS_HECI_GSC(gt->i915))
+ if (gsc_mask)
intel_uncore_write(uncore, GEN11_GUNIT_CSME_INTR_MASK, ~gsc_mask);
+ if (guc_mask) {
+ /* the enable bit is common for both GTs but the masks are separate */
+ u32 mask = gt->type == GT_MEDIA ?
+ REG_FIELD_PREP(ENGINE0_MASK, guc_mask) :
+ REG_FIELD_PREP(ENGINE1_MASK, guc_mask);
+
+ intel_uncore_write(uncore, GEN11_GUC_SG_INTR_ENABLE,
+ REG_FIELD_PREP(ENGINE1_MASK, guc_mask));
+
+ /* we might not be the first GT to write this reg */
+ intel_uncore_rmw(uncore, MTL_GUC_MGUC_INTR_MASK, mask, 0);
+ }
+
/*
* RPS interrupts will get enabled/disabled on demand when RPS itself
* is enabled/disabled.
@@ -307,10 +330,6 @@ void gen11_gt_irq_postinstall(struct intel_gt *gt)
gt->pm_imr = ~gt->pm_ier;
intel_uncore_write(uncore, GEN11_GPM_WGBOXPERF_INTR_ENABLE, 0);
intel_uncore_write(uncore, GEN11_GPM_WGBOXPERF_INTR_MASK, ~0);
-
- /* Same thing for GuC interrupts */
- intel_uncore_write(uncore, GEN11_GUC_SG_INTR_ENABLE, 0);
- intel_uncore_write(uncore, GEN11_GUC_SG_INTR_MASK, ~0);
}
void gen5_gt_irq_handler(struct intel_gt *gt, u32 gt_iir)
@@ -359,7 +378,8 @@ void gen6_gt_irq_handler(struct intel_gt *gt, u32 gt_iir)
if (gt_iir & (GT_BLT_CS_ERROR_INTERRUPT |
GT_BSD_CS_ERROR_INTERRUPT |
GT_CS_MASTER_ERROR_INTERRUPT))
- DRM_DEBUG("Command parser error, gt_iir 0x%08x\n", gt_iir);
+ drm_dbg(&gt->i915->drm, "Command parser error, gt_iir 0x%08x\n",
+ gt_iir);
if (gt_iir & GT_PARITY_ERROR(gt->i915))
gen7_parity_error_irq_handler(gt, gt_iir);
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_mcr.c b/drivers/gpu/drm/i915/gt/intel_gt_mcr.c
index e79405a45312..d9a8ff9e5e57 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_mcr.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_mcr.c
@@ -40,6 +40,9 @@ static const char * const intel_steering_types[] = {
"L3BANK",
"MSLICE",
"LNCF",
+ "GAM",
+ "DSS",
+ "OADDRM",
"INSTANCE 0",
};
@@ -48,14 +51,23 @@ static const struct intel_mmio_range icl_l3bank_steering_table[] = {
{},
};
+/*
+ * Although the bspec lists more "MSLICE" ranges than shown here, some of those
+ * are of a "GAM" subclass that has special rules. Thus we use a separate
+ * GAM table farther down for those.
+ */
static const struct intel_mmio_range xehpsdv_mslice_steering_table[] = {
- { 0x004000, 0x004AFF },
- { 0x00C800, 0x00CFFF },
{ 0x00DD00, 0x00DDFF },
{ 0x00E900, 0x00FFFF }, /* 0xEA00 - OxEFFF is unused */
{},
};
+static const struct intel_mmio_range xehpsdv_gam_steering_table[] = {
+ { 0x004000, 0x004AFF },
+ { 0x00C800, 0x00CFFF },
+ {},
+};
+
static const struct intel_mmio_range xehpsdv_lncf_steering_table[] = {
{ 0x00B000, 0x00B0FF },
{ 0x00D800, 0x00D8FF },
@@ -89,9 +101,47 @@ static const struct intel_mmio_range pvc_instance0_steering_table[] = {
{},
};
+static const struct intel_mmio_range xelpg_instance0_steering_table[] = {
+ { 0x000B00, 0x000BFF }, /* SQIDI */
+ { 0x001000, 0x001FFF }, /* SQIDI */
+ { 0x004000, 0x0048FF }, /* GAM */
+ { 0x008700, 0x0087FF }, /* SQIDI */
+ { 0x00B000, 0x00B0FF }, /* NODE */
+ { 0x00C800, 0x00CFFF }, /* GAM */
+ { 0x00D880, 0x00D8FF }, /* NODE */
+ { 0x00DD00, 0x00DDFF }, /* OAAL2 */
+ {},
+};
+
+static const struct intel_mmio_range xelpg_l3bank_steering_table[] = {
+ { 0x00B100, 0x00B3FF },
+ {},
+};
+
+/* DSS steering is used for SLICE ranges as well */
+static const struct intel_mmio_range xelpg_dss_steering_table[] = {
+ { 0x005200, 0x0052FF }, /* SLICE */
+ { 0x005500, 0x007FFF }, /* SLICE */
+ { 0x008140, 0x00815F }, /* SLICE (0x8140-0x814F), DSS (0x8150-0x815F) */
+ { 0x0094D0, 0x00955F }, /* SLICE (0x94D0-0x951F), DSS (0x9520-0x955F) */
+ { 0x009680, 0x0096FF }, /* DSS */
+ { 0x00D800, 0x00D87F }, /* SLICE */
+ { 0x00DC00, 0x00DCFF }, /* SLICE */
+ { 0x00DE80, 0x00E8FF }, /* DSS (0xE000-0xE0FF reserved) */
+ {},
+};
+
+static const struct intel_mmio_range xelpmp_oaddrm_steering_table[] = {
+ { 0x393200, 0x39323F },
+ { 0x393400, 0x3934FF },
+ {},
+};
+
void intel_gt_mcr_init(struct intel_gt *gt)
{
struct drm_i915_private *i915 = gt->i915;
+ unsigned long fuse;
+ int i;
/*
* An mslice is unavailable only if both the meml3 for the slice is
@@ -109,14 +159,36 @@ void intel_gt_mcr_init(struct intel_gt *gt)
drm_warn(&i915->drm, "mslice mask all zero!\n");
}
- if (IS_PONTEVECCHIO(i915)) {
+ if (MEDIA_VER(i915) >= 13 && gt->type == GT_MEDIA) {
+ gt->steering_table[OADDRM] = xelpmp_oaddrm_steering_table;
+ } else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70)) {
+ fuse = REG_FIELD_GET(GT_L3_EXC_MASK,
+ intel_uncore_read(gt->uncore, XEHP_FUSE4));
+
+ /*
+ * Despite the register field being named "exclude mask" the
+ * bits actually represent enabled banks (two banks per bit).
+ */
+ for_each_set_bit(i, &fuse, 3)
+ gt->info.l3bank_mask |= 0x3 << 2 * i;
+
+ gt->steering_table[INSTANCE0] = xelpg_instance0_steering_table;
+ gt->steering_table[L3BANK] = xelpg_l3bank_steering_table;
+ gt->steering_table[DSS] = xelpg_dss_steering_table;
+ } else if (IS_PONTEVECCHIO(i915)) {
gt->steering_table[INSTANCE0] = pvc_instance0_steering_table;
} else if (IS_DG2(i915)) {
gt->steering_table[MSLICE] = xehpsdv_mslice_steering_table;
gt->steering_table[LNCF] = dg2_lncf_steering_table;
+ /*
+ * No need to hook up the GAM table since it has a dedicated
+ * steering control register on DG2 and can use implicit
+ * steering.
+ */
} else if (IS_XEHPSDV(i915)) {
gt->steering_table[MSLICE] = xehpsdv_mslice_steering_table;
gt->steering_table[LNCF] = xehpsdv_lncf_steering_table;
+ gt->steering_table[GAM] = xehpsdv_gam_steering_table;
} else if (GRAPHICS_VER(i915) >= 11 &&
GRAPHICS_VER_FULL(i915) < IP_VER(12, 50)) {
gt->steering_table[L3BANK] = icl_l3bank_steering_table;
@@ -135,6 +207,19 @@ void intel_gt_mcr_init(struct intel_gt *gt)
}
/*
+ * Although the rest of the driver should use MCR-specific functions to
+ * read/write MCR registers, we still use the regular intel_uncore_* functions
+ * internally to implement those, so we need a way for the functions in this
+ * file to "cast" an i915_mcr_reg_t into an i915_reg_t.
+ */
+static i915_reg_t mcr_reg_cast(const i915_mcr_reg_t mcr)
+{
+ i915_reg_t r = { .reg = mcr.reg };
+
+ return r;
+}
+
+/*
* rw_with_mcr_steering_fw - Access a register with specific MCR steering
* @uncore: pointer to struct intel_uncore
* @reg: register being accessed
@@ -148,14 +233,26 @@ void intel_gt_mcr_init(struct intel_gt *gt)
* Caller needs to make sure the relevant forcewake wells are up.
*/
static u32 rw_with_mcr_steering_fw(struct intel_uncore *uncore,
- i915_reg_t reg, u8 rw_flag,
+ i915_mcr_reg_t reg, u8 rw_flag,
int group, int instance, u32 value)
{
u32 mcr_mask, mcr_ss, mcr, old_mcr, val = 0;
lockdep_assert_held(&uncore->lock);
- if (GRAPHICS_VER(uncore->i915) >= 11) {
+ if (GRAPHICS_VER_FULL(uncore->i915) >= IP_VER(12, 70)) {
+ /*
+ * Always leave the hardware in multicast mode when doing reads
+ * (see comment about Wa_22013088509 below) and only change it
+ * to unicast mode when doing writes of a specific instance.
+ *
+ * No need to save old steering reg value.
+ */
+ intel_uncore_write_fw(uncore, MTL_MCR_SELECTOR,
+ REG_FIELD_PREP(MTL_MCR_GROUPID, group) |
+ REG_FIELD_PREP(MTL_MCR_INSTANCEID, instance) |
+ (rw_flag == FW_REG_READ ? GEN11_MCR_MULTICAST : 0));
+ } else if (GRAPHICS_VER(uncore->i915) >= 11) {
mcr_mask = GEN11_MCR_SLICE_MASK | GEN11_MCR_SUBSLICE_MASK;
mcr_ss = GEN11_MCR_SLICE(group) | GEN11_MCR_SUBSLICE(instance);
@@ -173,39 +270,53 @@ static u32 rw_with_mcr_steering_fw(struct intel_uncore *uncore,
*/
if (rw_flag == FW_REG_WRITE)
mcr_mask |= GEN11_MCR_MULTICAST;
+
+ mcr = intel_uncore_read_fw(uncore, GEN8_MCR_SELECTOR);
+ old_mcr = mcr;
+
+ mcr &= ~mcr_mask;
+ mcr |= mcr_ss;
+ intel_uncore_write_fw(uncore, GEN8_MCR_SELECTOR, mcr);
} else {
mcr_mask = GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK;
mcr_ss = GEN8_MCR_SLICE(group) | GEN8_MCR_SUBSLICE(instance);
- }
- old_mcr = mcr = intel_uncore_read_fw(uncore, GEN8_MCR_SELECTOR);
+ mcr = intel_uncore_read_fw(uncore, GEN8_MCR_SELECTOR);
+ old_mcr = mcr;
- mcr &= ~mcr_mask;
- mcr |= mcr_ss;
- intel_uncore_write_fw(uncore, GEN8_MCR_SELECTOR, mcr);
+ mcr &= ~mcr_mask;
+ mcr |= mcr_ss;
+ intel_uncore_write_fw(uncore, GEN8_MCR_SELECTOR, mcr);
+ }
if (rw_flag == FW_REG_READ)
- val = intel_uncore_read_fw(uncore, reg);
+ val = intel_uncore_read_fw(uncore, mcr_reg_cast(reg));
else
- intel_uncore_write_fw(uncore, reg, value);
-
- mcr &= ~mcr_mask;
- mcr |= old_mcr & mcr_mask;
+ intel_uncore_write_fw(uncore, mcr_reg_cast(reg), value);
- intel_uncore_write_fw(uncore, GEN8_MCR_SELECTOR, mcr);
+ /*
+ * For pre-MTL platforms, we need to restore the old value of the
+ * steering control register to ensure that implicit steering continues
+ * to behave as expected. For MTL and beyond, we need only reinstate
+ * the 'multicast' bit (and only if we did a write that cleared it).
+ */
+ if (GRAPHICS_VER_FULL(uncore->i915) >= IP_VER(12, 70) && rw_flag == FW_REG_WRITE)
+ intel_uncore_write_fw(uncore, MTL_MCR_SELECTOR, GEN11_MCR_MULTICAST);
+ else if (GRAPHICS_VER_FULL(uncore->i915) < IP_VER(12, 70))
+ intel_uncore_write_fw(uncore, GEN8_MCR_SELECTOR, old_mcr);
return val;
}
static u32 rw_with_mcr_steering(struct intel_uncore *uncore,
- i915_reg_t reg, u8 rw_flag,
+ i915_mcr_reg_t reg, u8 rw_flag,
int group, int instance,
u32 value)
{
enum forcewake_domains fw_domains;
u32 val;
- fw_domains = intel_uncore_forcewake_for_reg(uncore, reg,
+ fw_domains = intel_uncore_forcewake_for_reg(uncore, mcr_reg_cast(reg),
rw_flag);
fw_domains |= intel_uncore_forcewake_for_reg(uncore,
GEN8_MCR_SELECTOR,
@@ -233,7 +344,7 @@ static u32 rw_with_mcr_steering(struct intel_uncore *uncore,
* group/instance.
*/
u32 intel_gt_mcr_read(struct intel_gt *gt,
- i915_reg_t reg,
+ i915_mcr_reg_t reg,
int group, int instance)
{
return rw_with_mcr_steering(gt->uncore, reg, FW_REG_READ, group, instance, 0);
@@ -250,7 +361,7 @@ u32 intel_gt_mcr_read(struct intel_gt *gt,
* Write an MCR register in unicast mode after steering toward a specific
* group/instance.
*/
-void intel_gt_mcr_unicast_write(struct intel_gt *gt, i915_reg_t reg, u32 value,
+void intel_gt_mcr_unicast_write(struct intel_gt *gt, i915_mcr_reg_t reg, u32 value,
int group, int instance)
{
rw_with_mcr_steering(gt->uncore, reg, FW_REG_WRITE, group, instance, value);
@@ -265,9 +376,16 @@ void intel_gt_mcr_unicast_write(struct intel_gt *gt, i915_reg_t reg, u32 value,
* Write an MCR register in multicast mode to update all instances.
*/
void intel_gt_mcr_multicast_write(struct intel_gt *gt,
- i915_reg_t reg, u32 value)
+ i915_mcr_reg_t reg, u32 value)
{
- intel_uncore_write(gt->uncore, reg, value);
+ /*
+ * Ensure we have multicast behavior, just in case some non-i915 agent
+ * left the hardware in unicast mode.
+ */
+ if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 70))
+ intel_uncore_write_fw(gt->uncore, MTL_MCR_SELECTOR, GEN11_MCR_MULTICAST);
+
+ intel_uncore_write(gt->uncore, mcr_reg_cast(reg), value);
}
/**
@@ -281,9 +399,44 @@ void intel_gt_mcr_multicast_write(struct intel_gt *gt,
* domains; use intel_gt_mcr_multicast_write() in cases where forcewake should
* be obtained automatically.
*/
-void intel_gt_mcr_multicast_write_fw(struct intel_gt *gt, i915_reg_t reg, u32 value)
+void intel_gt_mcr_multicast_write_fw(struct intel_gt *gt, i915_mcr_reg_t reg, u32 value)
{
- intel_uncore_write_fw(gt->uncore, reg, value);
+ /*
+ * Ensure we have multicast behavior, just in case some non-i915 agent
+ * left the hardware in unicast mode.
+ */
+ if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 70))
+ intel_uncore_write_fw(gt->uncore, MTL_MCR_SELECTOR, GEN11_MCR_MULTICAST);
+
+ intel_uncore_write_fw(gt->uncore, mcr_reg_cast(reg), value);
+}
+
+/**
+ * intel_gt_mcr_multicast_rmw - Performs a multicast RMW operations
+ * @gt: GT structure
+ * @reg: the MCR register to read and write
+ * @clear: bits to clear during RMW
+ * @set: bits to set during RMW
+ *
+ * Performs a read-modify-write on an MCR register in a multicast manner.
+ * This operation only makes sense on MCR registers where all instances are
+ * expected to have the same value. The read will target any non-terminated
+ * instance and the write will be applied to all instances.
+ *
+ * This function assumes the caller is already holding any necessary forcewake
+ * domains; use intel_gt_mcr_multicast_rmw() in cases where forcewake should
+ * be obtained automatically.
+ *
+ * Returns the old (unmodified) value read.
+ */
+u32 intel_gt_mcr_multicast_rmw(struct intel_gt *gt, i915_mcr_reg_t reg,
+ u32 clear, u32 set)
+{
+ u32 val = intel_gt_mcr_read_any(gt, reg);
+
+ intel_gt_mcr_multicast_write(gt, reg, (val & ~clear) | set);
+
+ return val;
}
/*
@@ -301,7 +454,7 @@ void intel_gt_mcr_multicast_write_fw(struct intel_gt *gt, i915_reg_t reg, u32 va
* for @type steering too.
*/
static bool reg_needs_read_steering(struct intel_gt *gt,
- i915_reg_t reg,
+ i915_mcr_reg_t reg,
enum intel_steering_type type)
{
const u32 offset = i915_mmio_reg_offset(reg);
@@ -332,6 +485,8 @@ static void get_nonterminated_steering(struct intel_gt *gt,
enum intel_steering_type type,
u8 *group, u8 *instance)
{
+ u32 dss;
+
switch (type) {
case L3BANK:
*group = 0; /* unused */
@@ -351,6 +506,15 @@ static void get_nonterminated_steering(struct intel_gt *gt,
*group = __ffs(gt->info.mslice_mask) << 1;
*instance = 0; /* unused */
break;
+ case GAM:
+ *group = IS_DG2(gt->i915) ? 1 : 0;
+ *instance = 0;
+ break;
+ case DSS:
+ dss = intel_sseu_find_first_xehp_dss(&gt->info.sseu, 0, 0);
+ *group = dss / GEN_DSS_PER_GSLICE;
+ *instance = dss % GEN_DSS_PER_GSLICE;
+ break;
case INSTANCE0:
/*
* There are a lot of MCR types for which instance (0, 0)
@@ -359,6 +523,13 @@ static void get_nonterminated_steering(struct intel_gt *gt,
*group = 0;
*instance = 0;
break;
+ case OADDRM:
+ if ((VDBOX_MASK(gt) | VEBOX_MASK(gt) | gt->info.sfc_mask) & BIT(0))
+ *group = 0;
+ else
+ *group = 1;
+ *instance = 0;
+ break;
default:
MISSING_CASE(type);
*group = 0;
@@ -380,7 +551,7 @@ static void get_nonterminated_steering(struct intel_gt *gt,
* steering.
*/
void intel_gt_mcr_get_nonterminated_steering(struct intel_gt *gt,
- i915_reg_t reg,
+ i915_mcr_reg_t reg,
u8 *group, u8 *instance)
{
int type;
@@ -409,7 +580,7 @@ void intel_gt_mcr_get_nonterminated_steering(struct intel_gt *gt,
*
* Returns the value from a non-terminated instance of @reg.
*/
-u32 intel_gt_mcr_read_any_fw(struct intel_gt *gt, i915_reg_t reg)
+u32 intel_gt_mcr_read_any_fw(struct intel_gt *gt, i915_mcr_reg_t reg)
{
int type;
u8 group, instance;
@@ -423,7 +594,7 @@ u32 intel_gt_mcr_read_any_fw(struct intel_gt *gt, i915_reg_t reg)
}
}
- return intel_uncore_read_fw(gt->uncore, reg);
+ return intel_uncore_read_fw(gt->uncore, mcr_reg_cast(reg));
}
/**
@@ -436,7 +607,7 @@ u32 intel_gt_mcr_read_any_fw(struct intel_gt *gt, i915_reg_t reg)
*
* Returns the value from a non-terminated instance of @reg.
*/
-u32 intel_gt_mcr_read_any(struct intel_gt *gt, i915_reg_t reg)
+u32 intel_gt_mcr_read_any(struct intel_gt *gt, i915_mcr_reg_t reg)
{
int type;
u8 group, instance;
@@ -450,7 +621,7 @@ u32 intel_gt_mcr_read_any(struct intel_gt *gt, i915_reg_t reg)
}
}
- return intel_uncore_read(gt->uncore, reg);
+ return intel_uncore_read(gt->uncore, mcr_reg_cast(reg));
}
static void report_steering_type(struct drm_printer *p,
@@ -483,11 +654,20 @@ static void report_steering_type(struct drm_printer *p,
void intel_gt_mcr_report_steering(struct drm_printer *p, struct intel_gt *gt,
bool dump_table)
{
- drm_printf(p, "Default steering: group=0x%x, instance=0x%x\n",
- gt->default_steering.groupid,
- gt->default_steering.instanceid);
-
- if (IS_PONTEVECCHIO(gt->i915)) {
+ /*
+ * Starting with MTL we no longer have default steering;
+ * all ranges are explicitly steered.
+ */
+ if (GRAPHICS_VER_FULL(gt->i915) < IP_VER(12, 70))
+ drm_printf(p, "Default steering: group=0x%x, instance=0x%x\n",
+ gt->default_steering.groupid,
+ gt->default_steering.instanceid);
+
+ if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 70)) {
+ for (int i = 0; i < NUM_STEERING_TYPES; i++)
+ if (gt->steering_table[i])
+ report_steering_type(p, gt, i, dump_table);
+ } else if (IS_PONTEVECCHIO(gt->i915)) {
report_steering_type(p, gt, INSTANCE0, dump_table);
} else if (HAS_MSLICE_STEERING(gt->i915)) {
report_steering_type(p, gt, MSLICE, dump_table);
@@ -520,3 +700,60 @@ void intel_gt_mcr_get_ss_steering(struct intel_gt *gt, unsigned int dss,
return;
}
}
+
+/**
+ * intel_gt_mcr_wait_for_reg_fw - wait until MCR register matches expected state
+ * @gt: GT structure
+ * @reg: the register to read
+ * @mask: mask to apply to register value
+ * @value: value to wait for
+ * @fast_timeout_us: fast timeout in microsecond for atomic/tight wait
+ * @slow_timeout_ms: slow timeout in millisecond
+ *
+ * This routine waits until the target register @reg contains the expected
+ * @value after applying the @mask, i.e. it waits until ::
+ *
+ * (intel_gt_mcr_read_any_fw(gt, reg) & mask) == value
+ *
+ * Otherwise, the wait will timeout after @slow_timeout_ms milliseconds.
+ * For atomic context @slow_timeout_ms must be zero and @fast_timeout_us
+ * must be not larger than 20,0000 microseconds.
+ *
+ * This function is basically an MCR-friendly version of
+ * __intel_wait_for_register_fw(). Generally this function will only be used
+ * on GAM registers which are a bit special --- although they're MCR registers,
+ * reads (e.g., waiting for status updates) are always directed to the primary
+ * instance.
+ *
+ * Note that this routine assumes the caller holds forcewake asserted, it is
+ * not suitable for very long waits.
+ *
+ * Return: 0 if the register matches the desired condition, or -ETIMEDOUT.
+ */
+int intel_gt_mcr_wait_for_reg(struct intel_gt *gt,
+ i915_mcr_reg_t reg,
+ u32 mask,
+ u32 value,
+ unsigned int fast_timeout_us,
+ unsigned int slow_timeout_ms)
+{
+ int ret;
+
+ lockdep_assert_not_held(&gt->uncore->lock);
+
+#define done ((intel_gt_mcr_read_any(gt, reg) & mask) == value)
+
+ /* Catch any overuse of this function */
+ might_sleep_if(slow_timeout_ms);
+ GEM_BUG_ON(fast_timeout_us > 20000);
+ GEM_BUG_ON(!fast_timeout_us && !slow_timeout_ms);
+
+ ret = -ETIMEDOUT;
+ if (fast_timeout_us && fast_timeout_us <= 20000)
+ ret = _wait_for_atomic(done, fast_timeout_us, 0);
+ if (ret && slow_timeout_ms)
+ ret = wait_for(done, slow_timeout_ms);
+
+ return ret;
+#undef done
+}
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_mcr.h b/drivers/gpu/drm/i915/gt/intel_gt_mcr.h
index 77a8b11c287d..ae93b20e1c17 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_mcr.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_mcr.h
@@ -11,21 +11,24 @@
void intel_gt_mcr_init(struct intel_gt *gt);
u32 intel_gt_mcr_read(struct intel_gt *gt,
- i915_reg_t reg,
+ i915_mcr_reg_t reg,
int group, int instance);
-u32 intel_gt_mcr_read_any_fw(struct intel_gt *gt, i915_reg_t reg);
-u32 intel_gt_mcr_read_any(struct intel_gt *gt, i915_reg_t reg);
+u32 intel_gt_mcr_read_any_fw(struct intel_gt *gt, i915_mcr_reg_t reg);
+u32 intel_gt_mcr_read_any(struct intel_gt *gt, i915_mcr_reg_t reg);
void intel_gt_mcr_unicast_write(struct intel_gt *gt,
- i915_reg_t reg, u32 value,
+ i915_mcr_reg_t reg, u32 value,
int group, int instance);
void intel_gt_mcr_multicast_write(struct intel_gt *gt,
- i915_reg_t reg, u32 value);
+ i915_mcr_reg_t reg, u32 value);
void intel_gt_mcr_multicast_write_fw(struct intel_gt *gt,
- i915_reg_t reg, u32 value);
+ i915_mcr_reg_t reg, u32 value);
+
+u32 intel_gt_mcr_multicast_rmw(struct intel_gt *gt, i915_mcr_reg_t reg,
+ u32 clear, u32 set);
void intel_gt_mcr_get_nonterminated_steering(struct intel_gt *gt,
- i915_reg_t reg,
+ i915_mcr_reg_t reg,
u8 *group, u8 *instance);
void intel_gt_mcr_report_steering(struct drm_printer *p, struct intel_gt *gt,
@@ -34,6 +37,13 @@ void intel_gt_mcr_report_steering(struct drm_printer *p, struct intel_gt *gt,
void intel_gt_mcr_get_ss_steering(struct intel_gt *gt, unsigned int dss,
unsigned int *group, unsigned int *instance);
+int intel_gt_mcr_wait_for_reg(struct intel_gt *gt,
+ i915_mcr_reg_t reg,
+ u32 mask,
+ u32 value,
+ unsigned int fast_timeout_us,
+ unsigned int slow_timeout_ms);
+
/*
* Helper for for_each_ss_steering loop. On pre-Xe_HP platforms, subslice
* presence is determined by using the group/instance as direct lookups in the
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
index f553e2173bda..16db85fab0b1 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c
@@ -7,6 +7,7 @@
#include <linux/suspend.h>
#include "i915_drv.h"
+#include "i915_irq.h"
#include "i915_params.h"
#include "intel_context.h"
#include "intel_engine_pm.h"
@@ -19,10 +20,31 @@
#include "intel_rc6.h"
#include "intel_rps.h"
#include "intel_wakeref.h"
+#include "intel_pcode.h"
#include "pxp/intel_pxp_pm.h"
#define I915_GT_SUSPEND_IDLE_TIMEOUT (HZ / 2)
+static void mtl_media_busy(struct intel_gt *gt)
+{
+ /* Wa_14017073508: mtl */
+ if (IS_MTL_GRAPHICS_STEP(gt->i915, P, STEP_A0, STEP_B0) &&
+ gt->type == GT_MEDIA)
+ snb_pcode_write_p(gt->uncore, PCODE_MBOX_GT_STATE,
+ PCODE_MBOX_GT_STATE_MEDIA_BUSY,
+ PCODE_MBOX_GT_STATE_DOMAIN_MEDIA, 0);
+}
+
+static void mtl_media_idle(struct intel_gt *gt)
+{
+ /* Wa_14017073508: mtl */
+ if (IS_MTL_GRAPHICS_STEP(gt->i915, P, STEP_A0, STEP_B0) &&
+ gt->type == GT_MEDIA)
+ snb_pcode_write_p(gt->uncore, PCODE_MBOX_GT_STATE,
+ PCODE_MBOX_GT_STATE_MEDIA_NOT_BUSY,
+ PCODE_MBOX_GT_STATE_DOMAIN_MEDIA, 0);
+}
+
static void user_forcewake(struct intel_gt *gt, bool suspend)
{
int count = atomic_read(&gt->user_wakeref);
@@ -70,6 +92,9 @@ static int __gt_unpark(struct intel_wakeref *wf)
GT_TRACE(gt, "\n");
+ /* Wa_14017073508: mtl */
+ mtl_media_busy(gt);
+
/*
* It seems that the DMC likes to transition between the DC states a lot
* when there are no connected displays (no active power domains) during
@@ -119,6 +144,9 @@ static int __gt_park(struct intel_wakeref *wf)
GEM_BUG_ON(!wakeref);
intel_display_power_put_async(i915, POWER_DOMAIN_GT_IRQ, wakeref);
+ /* Wa_14017073508: mtl */
+ mtl_media_idle(gt);
+
return 0;
}
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 108b9e76c32e..83df4cd5e06c 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c
@@ -83,19 +83,6 @@ static int fw_domains_show(struct seq_file *m, void *data)
}
DEFINE_INTEL_GT_DEBUGFS_ATTRIBUTE(fw_domains);
-static void print_rc6_res(struct seq_file *m,
- const char *title,
- const i915_reg_t reg)
-{
- struct intel_gt *gt = m->private;
- intel_wakeref_t wakeref;
-
- with_intel_runtime_pm(gt->uncore->rpm, wakeref)
- seq_printf(m, "%s %u (%llu us)\n", title,
- intel_uncore_read(gt->uncore, reg),
- intel_rc6_residency_us(&gt->rc6, reg));
-}
-
static int vlv_drpc(struct seq_file *m)
{
struct intel_gt *gt = m->private;
@@ -115,8 +102,8 @@ static int vlv_drpc(struct seq_file *m)
seq_printf(m, "Media Power Well: %s\n",
(pw_status & VLV_GTLC_PW_MEDIA_STATUS_MASK) ? "Up" : "Down");
- print_rc6_res(m, "Render RC6 residency since boot:", GEN6_GT_GFX_RC6);
- print_rc6_res(m, "Media RC6 residency since boot:", VLV_GT_MEDIA_RC6);
+ intel_rc6_print_residency(m, "Render RC6 residency since boot:", INTEL_RC6_RES_RC6);
+ intel_rc6_print_residency(m, "Media RC6 residency since boot:", INTEL_RC6_RES_VLV_MEDIA);
return fw_domains_show(m, NULL);
}
@@ -192,11 +179,11 @@ static int gen6_drpc(struct seq_file *m)
}
/* Not exactly sure what this is */
- print_rc6_res(m, "RC6 \"Locked to RPn\" residency since boot:",
- GEN6_GT_GFX_RC6_LOCKED);
- print_rc6_res(m, "RC6 residency since boot:", GEN6_GT_GFX_RC6);
- print_rc6_res(m, "RC6+ residency since boot:", GEN6_GT_GFX_RC6p);
- print_rc6_res(m, "RC6++ residency since boot:", GEN6_GT_GFX_RC6pp);
+ intel_rc6_print_residency(m, "RC6 \"Locked to RPn\" residency since boot:",
+ INTEL_RC6_RES_RC6_LOCKED);
+ intel_rc6_print_residency(m, "RC6 residency since boot:", INTEL_RC6_RES_RC6);
+ intel_rc6_print_residency(m, "RC6+ residency since boot:", INTEL_RC6_RES_RC6p);
+ intel_rc6_print_residency(m, "RC6++ residency since boot:", INTEL_RC6_RES_RC6pp);
if (GRAPHICS_VER(i915) <= 7) {
seq_printf(m, "RC6 voltage: %dmV\n",
@@ -269,6 +256,61 @@ static int ilk_drpc(struct seq_file *m)
return 0;
}
+static int mtl_drpc(struct seq_file *m)
+{
+ struct intel_gt *gt = m->private;
+ struct intel_uncore *uncore = gt->uncore;
+ u32 gt_core_status, rcctl1, mt_fwake_req;
+ u32 mtl_powergate_enable = 0, mtl_powergate_status = 0;
+
+ mt_fwake_req = intel_uncore_read_fw(uncore, FORCEWAKE_MT);
+ gt_core_status = intel_uncore_read(uncore, MTL_MIRROR_TARGET_WP1);
+
+ rcctl1 = intel_uncore_read(uncore, GEN6_RC_CONTROL);
+ mtl_powergate_enable = intel_uncore_read(uncore, GEN9_PG_ENABLE);
+ mtl_powergate_status = intel_uncore_read(uncore,
+ GEN9_PWRGT_DOMAIN_STATUS);
+
+ seq_printf(m, "RC6 Enabled: %s\n",
+ str_yes_no(rcctl1 & GEN6_RC_CTL_RC6_ENABLE));
+ if (gt->type == GT_MEDIA) {
+ seq_printf(m, "Media Well Gating Enabled: %s\n",
+ str_yes_no(mtl_powergate_enable & GEN9_MEDIA_PG_ENABLE));
+ } else {
+ seq_printf(m, "Render Well Gating Enabled: %s\n",
+ str_yes_no(mtl_powergate_enable & GEN9_RENDER_PG_ENABLE));
+ }
+
+ seq_puts(m, "Current RC state: ");
+ switch (REG_FIELD_GET(MTL_CC_MASK, gt_core_status)) {
+ case MTL_CC0:
+ seq_puts(m, "RC0\n");
+ break;
+ case MTL_CC6:
+ seq_puts(m, "RC6\n");
+ break;
+ default:
+ MISSING_CASE(REG_FIELD_GET(MTL_CC_MASK, gt_core_status));
+ seq_puts(m, "Unknown\n");
+ break;
+ }
+
+ seq_printf(m, "Multi-threaded Forcewake Request: 0x%x\n", mt_fwake_req);
+ if (gt->type == GT_MEDIA)
+ seq_printf(m, "Media Power Well: %s\n",
+ (mtl_powergate_status &
+ GEN9_PWRGT_MEDIA_STATUS_MASK) ? "Up" : "Down");
+ else
+ seq_printf(m, "Render Power Well: %s\n",
+ (mtl_powergate_status &
+ GEN9_PWRGT_RENDER_STATUS_MASK) ? "Up" : "Down");
+
+ /* Works for both render and media gt's */
+ intel_rc6_print_residency(m, "RC6 residency since boot:", INTEL_RC6_RES_RC6);
+
+ return fw_domains_show(m, NULL);
+}
+
static int drpc_show(struct seq_file *m, void *unused)
{
struct intel_gt *gt = m->private;
@@ -277,7 +319,9 @@ static int drpc_show(struct seq_file *m, void *unused)
int err = -ENODEV;
with_intel_runtime_pm(gt->uncore->rpm, wakeref) {
- if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70))
+ err = mtl_drpc(m);
+ else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
err = vlv_drpc(m);
else if (GRAPHICS_VER(i915) >= 6)
err = gen6_drpc(m);
@@ -307,7 +351,7 @@ void intel_gt_pm_frequency_dump(struct intel_gt *gt, struct drm_printer *p)
drm_printf(p, "Current VID: %d\n", (rgvstat & MEMSTAT_VID_MASK) >>
MEMSTAT_VID_SHIFT);
drm_printf(p, "Current P-state: %d\n",
- (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
+ REG_FIELD_GET(MEMSTAT_PSTATE_MASK, rgvstat));
} else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
u32 rpmodectl, freq_sts;
@@ -344,162 +388,7 @@ void intel_gt_pm_frequency_dump(struct intel_gt *gt, struct drm_printer *p)
drm_printf(p, "efficient (RPe) frequency: %d MHz\n",
intel_gpu_freq(rps, rps->efficient_freq));
} else if (GRAPHICS_VER(i915) >= 6) {
- u32 rp_state_limits;
- u32 gt_perf_status;
- struct intel_rps_freq_caps caps;
- u32 rpmodectl, rpinclimit, rpdeclimit;
- u32 rpstat, cagf, reqf;
- u32 rpcurupei, rpcurup, rpprevup;
- u32 rpcurdownei, rpcurdown, rpprevdown;
- u32 rpupei, rpupt, rpdownei, rpdownt;
- u32 pm_ier, pm_imr, pm_isr, pm_iir, pm_mask;
-
- rp_state_limits = intel_uncore_read(uncore, GEN6_RP_STATE_LIMITS);
- gen6_rps_get_freq_caps(rps, &caps);
- if (IS_GEN9_LP(i915))
- gt_perf_status = intel_uncore_read(uncore, BXT_GT_PERF_STATUS);
- else
- gt_perf_status = intel_uncore_read(uncore, GEN6_GT_PERF_STATUS);
-
- /* RPSTAT1 is in the GT power well */
- intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
-
- reqf = intel_uncore_read(uncore, GEN6_RPNSWREQ);
- if (GRAPHICS_VER(i915) >= 9) {
- reqf >>= 23;
- } else {
- reqf &= ~GEN6_TURBO_DISABLE;
- if (IS_HASWELL(i915) || IS_BROADWELL(i915))
- reqf >>= 24;
- else
- reqf >>= 25;
- }
- reqf = intel_gpu_freq(rps, reqf);
-
- rpmodectl = intel_uncore_read(uncore, GEN6_RP_CONTROL);
- rpinclimit = intel_uncore_read(uncore, GEN6_RP_UP_THRESHOLD);
- rpdeclimit = intel_uncore_read(uncore, GEN6_RP_DOWN_THRESHOLD);
-
- rpstat = intel_uncore_read(uncore, GEN6_RPSTAT1);
- rpcurupei = intel_uncore_read(uncore, GEN6_RP_CUR_UP_EI) & GEN6_CURICONT_MASK;
- rpcurup = intel_uncore_read(uncore, GEN6_RP_CUR_UP) & GEN6_CURBSYTAVG_MASK;
- rpprevup = intel_uncore_read(uncore, GEN6_RP_PREV_UP) & GEN6_CURBSYTAVG_MASK;
- rpcurdownei = intel_uncore_read(uncore, GEN6_RP_CUR_DOWN_EI) & GEN6_CURIAVG_MASK;
- rpcurdown = intel_uncore_read(uncore, GEN6_RP_CUR_DOWN) & GEN6_CURBSYTAVG_MASK;
- rpprevdown = intel_uncore_read(uncore, GEN6_RP_PREV_DOWN) & GEN6_CURBSYTAVG_MASK;
-
- rpupei = intel_uncore_read(uncore, GEN6_RP_UP_EI);
- rpupt = intel_uncore_read(uncore, GEN6_RP_UP_THRESHOLD);
-
- rpdownei = intel_uncore_read(uncore, GEN6_RP_DOWN_EI);
- rpdownt = intel_uncore_read(uncore, GEN6_RP_DOWN_THRESHOLD);
-
- cagf = intel_rps_read_actual_frequency(rps);
-
- intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL);
-
- if (GRAPHICS_VER(i915) >= 11) {
- pm_ier = intel_uncore_read(uncore, GEN11_GPM_WGBOXPERF_INTR_ENABLE);
- pm_imr = intel_uncore_read(uncore, GEN11_GPM_WGBOXPERF_INTR_MASK);
- /*
- * The equivalent to the PM ISR & IIR cannot be read
- * without affecting the current state of the system
- */
- pm_isr = 0;
- pm_iir = 0;
- } else if (GRAPHICS_VER(i915) >= 8) {
- pm_ier = intel_uncore_read(uncore, GEN8_GT_IER(2));
- pm_imr = intel_uncore_read(uncore, GEN8_GT_IMR(2));
- pm_isr = intel_uncore_read(uncore, GEN8_GT_ISR(2));
- pm_iir = intel_uncore_read(uncore, GEN8_GT_IIR(2));
- } else {
- pm_ier = intel_uncore_read(uncore, GEN6_PMIER);
- pm_imr = intel_uncore_read(uncore, GEN6_PMIMR);
- pm_isr = intel_uncore_read(uncore, GEN6_PMISR);
- pm_iir = intel_uncore_read(uncore, GEN6_PMIIR);
- }
- pm_mask = intel_uncore_read(uncore, GEN6_PMINTRMSK);
-
- drm_printf(p, "Video Turbo Mode: %s\n",
- str_yes_no(rpmodectl & GEN6_RP_MEDIA_TURBO));
- drm_printf(p, "HW control enabled: %s\n",
- str_yes_no(rpmodectl & GEN6_RP_ENABLE));
- drm_printf(p, "SW control enabled: %s\n",
- str_yes_no((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) == GEN6_RP_MEDIA_SW_MODE));
-
- drm_printf(p, "PM IER=0x%08x IMR=0x%08x, MASK=0x%08x\n",
- pm_ier, pm_imr, pm_mask);
- if (GRAPHICS_VER(i915) <= 10)
- drm_printf(p, "PM ISR=0x%08x IIR=0x%08x\n",
- pm_isr, pm_iir);
- drm_printf(p, "pm_intrmsk_mbz: 0x%08x\n",
- rps->pm_intrmsk_mbz);
- drm_printf(p, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status);
- drm_printf(p, "Render p-state ratio: %d\n",
- (gt_perf_status & (GRAPHICS_VER(i915) >= 9 ? 0x1ff00 : 0xff00)) >> 8);
- drm_printf(p, "Render p-state VID: %d\n",
- gt_perf_status & 0xff);
- drm_printf(p, "Render p-state limit: %d\n",
- rp_state_limits & 0xff);
- drm_printf(p, "RPSTAT1: 0x%08x\n", rpstat);
- drm_printf(p, "RPMODECTL: 0x%08x\n", rpmodectl);
- drm_printf(p, "RPINCLIMIT: 0x%08x\n", rpinclimit);
- drm_printf(p, "RPDECLIMIT: 0x%08x\n", rpdeclimit);
- drm_printf(p, "RPNSWREQ: %dMHz\n", reqf);
- drm_printf(p, "CAGF: %dMHz\n", cagf);
- drm_printf(p, "RP CUR UP EI: %d (%lldns)\n",
- rpcurupei,
- intel_gt_pm_interval_to_ns(gt, rpcurupei));
- drm_printf(p, "RP CUR UP: %d (%lldns)\n",
- rpcurup, intel_gt_pm_interval_to_ns(gt, rpcurup));
- drm_printf(p, "RP PREV UP: %d (%lldns)\n",
- rpprevup, intel_gt_pm_interval_to_ns(gt, rpprevup));
- drm_printf(p, "Up threshold: %d%%\n",
- rps->power.up_threshold);
- drm_printf(p, "RP UP EI: %d (%lldns)\n",
- rpupei, intel_gt_pm_interval_to_ns(gt, rpupei));
- drm_printf(p, "RP UP THRESHOLD: %d (%lldns)\n",
- rpupt, intel_gt_pm_interval_to_ns(gt, rpupt));
-
- drm_printf(p, "RP CUR DOWN EI: %d (%lldns)\n",
- rpcurdownei,
- intel_gt_pm_interval_to_ns(gt, rpcurdownei));
- drm_printf(p, "RP CUR DOWN: %d (%lldns)\n",
- rpcurdown,
- intel_gt_pm_interval_to_ns(gt, rpcurdown));
- drm_printf(p, "RP PREV DOWN: %d (%lldns)\n",
- rpprevdown,
- intel_gt_pm_interval_to_ns(gt, rpprevdown));
- drm_printf(p, "Down threshold: %d%%\n",
- rps->power.down_threshold);
- drm_printf(p, "RP DOWN EI: %d (%lldns)\n",
- rpdownei, intel_gt_pm_interval_to_ns(gt, rpdownei));
- drm_printf(p, "RP DOWN THRESHOLD: %d (%lldns)\n",
- rpdownt, intel_gt_pm_interval_to_ns(gt, rpdownt));
-
- drm_printf(p, "Lowest (RPN) frequency: %dMHz\n",
- intel_gpu_freq(rps, caps.min_freq));
- drm_printf(p, "Nominal (RP1) frequency: %dMHz\n",
- intel_gpu_freq(rps, caps.rp1_freq));
- drm_printf(p, "Max non-overclocked (RP0) frequency: %dMHz\n",
- intel_gpu_freq(rps, caps.rp0_freq));
- drm_printf(p, "Max overclocked frequency: %dMHz\n",
- intel_gpu_freq(rps, rps->max_freq));
-
- drm_printf(p, "Current freq: %d MHz\n",
- intel_gpu_freq(rps, rps->cur_freq));
- drm_printf(p, "Actual freq: %d MHz\n", cagf);
- drm_printf(p, "Idle freq: %d MHz\n",
- intel_gpu_freq(rps, rps->idle_freq));
- drm_printf(p, "Min freq: %d MHz\n",
- intel_gpu_freq(rps, rps->min_freq));
- drm_printf(p, "Boost freq: %d MHz\n",
- intel_gpu_freq(rps, rps->boost_freq));
- drm_printf(p, "Max freq: %d MHz\n",
- intel_gpu_freq(rps, rps->max_freq));
- drm_printf(p,
- "efficient (RPe) frequency: %d MHz\n",
- intel_gpu_freq(rps, rps->efficient_freq));
+ gen6_rps_frequency_dump(rps, p);
} else {
drm_puts(p, "no P-state info available\n");
}
@@ -655,6 +544,44 @@ static bool rps_eval(void *data)
DEFINE_INTEL_GT_DEBUGFS_ATTRIBUTE(rps_boost);
+static int perf_limit_reasons_get(void *data, u64 *val)
+{
+ struct intel_gt *gt = data;
+ intel_wakeref_t wakeref;
+
+ with_intel_runtime_pm(gt->uncore->rpm, wakeref)
+ *val = intel_uncore_read(gt->uncore, intel_gt_perf_limit_reasons_reg(gt));
+
+ return 0;
+}
+
+static int perf_limit_reasons_clear(void *data, u64 val)
+{
+ struct intel_gt *gt = data;
+ intel_wakeref_t wakeref;
+
+ /*
+ * Clear the upper 16 "log" bits, the lower 16 "status" bits are
+ * read-only. The upper 16 "log" bits are identical to the lower 16
+ * "status" bits except that the "log" bits remain set until cleared.
+ */
+ with_intel_runtime_pm(gt->uncore->rpm, wakeref)
+ intel_uncore_rmw(gt->uncore, intel_gt_perf_limit_reasons_reg(gt),
+ GT0_PERF_LIMIT_REASONS_LOG_MASK, 0);
+
+ return 0;
+}
+
+static bool perf_limit_reasons_eval(void *data)
+{
+ struct intel_gt *gt = data;
+
+ return i915_mmio_reg_valid(intel_gt_perf_limit_reasons_reg(gt));
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(perf_limit_reasons_fops, perf_limit_reasons_get,
+ perf_limit_reasons_clear, "%llu\n");
+
void intel_gt_pm_debugfs_register(struct intel_gt *gt, struct dentry *root)
{
static const struct intel_gt_debugfs_file files[] = {
@@ -664,6 +591,7 @@ void intel_gt_pm_debugfs_register(struct intel_gt *gt, struct dentry *root)
{ "forcewake_user", &forcewake_user_fops, NULL},
{ "llc", &llc_fops, llc_eval },
{ "rps_boost", &rps_boost_fops, rps_eval },
+ { "perf_limit_reasons", &perf_limit_reasons_fops, perf_limit_reasons_eval },
};
intel_gt_debugfs_register_files(root, files, ARRAY_SIZE(files), gt);
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
index 2275ee47da95..c3cd92691795 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h
@@ -7,6 +7,27 @@
#define __INTEL_GT_REGS__
#include "i915_reg_defs.h"
+#include "display/intel_display_reg_defs.h" /* VLV_DISPLAY_BASE */
+
+#define MCR_REG(offset) ((const i915_mcr_reg_t){ .reg = (offset) })
+
+/*
+ * The perf control registers are technically multicast registers, but the
+ * driver never needs to read/write them directly; we only use them to build
+ * lists of registers (where they're mixed in with other non-MCR registers)
+ * and then operate on the offset directly. For now we'll just define them
+ * as non-multicast so we can place them on the same list, but we may want
+ * to try to come up with a better way to handle heterogeneous lists of
+ * registers in the future.
+ */
+#define PERF_REG(offset) _MMIO(offset)
+
+/* MTL workpoint reg to get core C state and actual freq of 3D, SAMedia */
+#define MTL_MIRROR_TARGET_WP1 _MMIO(0xc60)
+#define MTL_CAGF_MASK REG_GENMASK(8, 0)
+#define MTL_CC0 0x0
+#define MTL_CC6 0x3
+#define MTL_CC_MASK REG_GENMASK(12, 9)
/* RPM unit config (Gen8+) */
#define RPM_CONFIG0 _MMIO(0xd00)
@@ -39,9 +60,17 @@
#define FORCEWAKE_ACK_RENDER_GEN9 _MMIO(0xd84)
#define FORCEWAKE_ACK_MEDIA_GEN9 _MMIO(0xd88)
+#define FORCEWAKE_ACK_GSC _MMIO(0xdf8)
+#define FORCEWAKE_ACK_GT_MTL _MMIO(0xdfc)
+
+#define GMD_ID_GRAPHICS _MMIO(0xd8c)
+#define GMD_ID_MEDIA _MMIO(MTL_MEDIA_GSI_BASE + 0xd8c)
+
#define MCFG_MCR_SELECTOR _MMIO(0xfd0)
+#define MTL_MCR_SELECTOR _MMIO(0xfd4)
#define SF_MCR_SELECTOR _MMIO(0xfd8)
#define GEN8_MCR_SELECTOR _MMIO(0xfdc)
+#define GAM_MCR_SELECTOR _MMIO(0xfe0)
#define GEN8_MCR_SLICE(slice) (((slice) & 3) << 26)
#define GEN8_MCR_SLICE_MASK GEN8_MCR_SLICE(3)
#define GEN8_MCR_SUBSLICE(subslice) (((subslice) & 3) << 24)
@@ -51,6 +80,8 @@
#define GEN11_MCR_SLICE_MASK GEN11_MCR_SLICE(0xf)
#define GEN11_MCR_SUBSLICE(subslice) (((subslice) & 0x7) << 24)
#define GEN11_MCR_SUBSLICE_MASK GEN11_MCR_SUBSLICE(0x7)
+#define MTL_MCR_GROUPID REG_GENMASK(11, 8)
+#define MTL_MCR_INSTANCEID REG_GENMASK(3, 0)
#define IPEIR_I965 _MMIO(0x2064)
#define IPEHR_I965 _MMIO(0x2068)
@@ -326,11 +357,12 @@
#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 XEHP_TILE0_ADDR_RANGE _MMIO(0x4900)
+#define XEHP_TILE0_ADDR_RANGE MCR_REG(0x4900)
#define XEHP_TILE_LMEM_RANGE_SHIFT 8
-#define XEHP_FLAT_CCS_BASE_ADDR _MMIO(0x4910)
+#define XEHP_FLAT_CCS_BASE_ADDR MCR_REG(0x4910)
#define XEHP_CCS_BASE_SHIFT 8
#define GAMTARBMODE _MMIO(0x4a08)
@@ -380,17 +412,18 @@
#define CHICKEN_RASTER_2 _MMIO(0x6208)
#define TBIMR_FAST_CLIP REG_BIT(5)
-#define VFLSKPD _MMIO(0x62a8)
+#define VFLSKPD MCR_REG(0x62a8)
#define DIS_OVER_FETCH_CACHE REG_BIT(1)
#define DIS_MULT_MISS_RD_SQUASH REG_BIT(0)
-#define FF_MODE2 _MMIO(0x6604)
+#define GEN12_FF_MODE2 _MMIO(0x6604)
+#define XEHP_FF_MODE2 MCR_REG(0x6604)
#define FF_MODE2_GS_TIMER_MASK REG_GENMASK(31, 24)
#define FF_MODE2_GS_TIMER_224 REG_FIELD_PREP(FF_MODE2_GS_TIMER_MASK, 224)
#define FF_MODE2_TDS_TIMER_MASK REG_GENMASK(23, 16)
#define FF_MODE2_TDS_TIMER_128 REG_FIELD_PREP(FF_MODE2_TDS_TIMER_MASK, 4)
-#define XEHPG_INSTDONE_GEOM_SVG _MMIO(0x666c)
+#define XEHPG_INSTDONE_GEOM_SVG MCR_REG(0x666c)
#define CACHE_MODE_0_GEN7 _MMIO(0x7000) /* IVB+ */
#define RC_OP_FLUSH_ENABLE (1 << 0)
@@ -418,6 +451,7 @@
#define HIZ_CHICKEN _MMIO(0x7018)
#define CHV_HZ_8X8_MODE_IN_1X REG_BIT(15)
#define DG1_HZ_READ_SUPPRESSION_OPTIMIZATION_DISABLE REG_BIT(14)
+#define HZ_DEPTH_TEST_LE_GE_OPT_DISABLE REG_BIT(13)
#define BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE REG_BIT(3)
#define GEN8_L3CNTLREG _MMIO(0x7034)
@@ -439,23 +473,16 @@
#define GEN8_HDC_CHICKEN1 _MMIO(0x7304)
#define GEN11_COMMON_SLICE_CHICKEN3 _MMIO(0x7304)
+#define XEHP_COMMON_SLICE_CHICKEN3 MCR_REG(0x7304)
#define DG1_FLOAT_POINT_BLEND_OPT_STRICT_MODE_EN REG_BIT(12)
#define XEHP_DUAL_SIMD8_SEQ_MERGE_DISABLE REG_BIT(12)
#define GEN11_BLEND_EMB_FIX_DISABLE_IN_RCC REG_BIT(11)
#define GEN12_DISABLE_CPS_AWARE_COLOR_PIPE REG_BIT(9)
-/* GEN9 chicken */
-#define SLICE_ECO_CHICKEN0 _MMIO(0x7308)
-#define PIXEL_MASK_CAMMING_DISABLE (1 << 14)
-
-#define GEN9_SLICE_COMMON_ECO_CHICKEN0 _MMIO(0x7308)
-#define DISABLE_PIXEL_MASK_CAMMING (1 << 14)
-
#define GEN9_SLICE_COMMON_ECO_CHICKEN1 _MMIO(0x731c)
-#define GEN11_STATE_CACHE_REDIRECT_TO_CS (1 << 11)
-
-#define SLICE_COMMON_ECO_CHICKEN1 _MMIO(0x731c)
+#define XEHP_SLICE_COMMON_ECO_CHICKEN1 MCR_REG(0x731c)
#define MSC_MSAA_REODER_BUF_BYPASS_DISABLE REG_BIT(14)
+#define GEN11_STATE_CACHE_REDIRECT_TO_CS (1 << 11)
#define GEN9_SLICE_PGCTL_ACK(slice) _MMIO(0x804c + (slice) * 0x4)
#define GEN10_SLICE_PGCTL_ACK(slice) _MMIO(0x804c + ((slice) / 3) * 0x34 + \
@@ -482,9 +509,12 @@
#define VF_PREEMPTION _MMIO(0x83a4)
#define PREEMPTION_VERTEX_COUNT REG_GENMASK(15, 0)
+#define VFG_PREEMPTION_CHICKEN _MMIO(0x83b4)
+#define POLYGON_TRIFAN_LINELOOP_DISABLE REG_BIT(4)
+
#define GEN8_RC6_CTX_INFO _MMIO(0x8504)
-#define GEN12_SQCM _MMIO(0x8724)
+#define XEHP_SQCM MCR_REG(0x8724)
#define EN_32B_ACCESS REG_BIT(30)
#define HSW_IDICR _MMIO(0x9008)
@@ -516,6 +546,8 @@
#define GEN6_MBCTL_BOOT_FETCH_MECH (1 << 0)
/* Fuse readout registers for GT */
+#define XEHP_FUSE4 _MMIO(0x9114)
+#define GT_L3_EXC_MASK REG_GENMASK(6, 4)
#define GEN10_MIRROR_FUSE3 _MMIO(0x9118)
#define GEN10_L3BANK_PAIR_COUNT 4
#define GEN10_L3BANK_MASK 0x0F
@@ -619,6 +651,7 @@
#define XEHPC_GRDOM_BLT3 REG_BIT(26)
#define XEHPC_GRDOM_BLT2 REG_BIT(25)
#define XEHPC_GRDOM_BLT1 REG_BIT(24)
+#define GEN12_GRDOM_GSC REG_BIT(21)
#define GEN11_GRDOM_SFC3 REG_BIT(20)
#define GEN11_GRDOM_SFC2 REG_BIT(19)
#define GEN11_GRDOM_SFC1 REG_BIT(18)
@@ -644,6 +677,9 @@
#define GEN7_MISCCPCTL _MMIO(0x9424)
#define GEN7_DOP_CLOCK_GATE_ENABLE (1 << 0)
+
+#define GEN8_MISCCPCTL MCR_REG(0x9424)
+#define GEN8_DOP_CLOCK_GATE_ENABLE REG_BIT(0)
#define GEN12_DOP_CLOCK_GATE_RENDER_ENABLE REG_BIT(1)
#define GEN8_DOP_CLOCK_GATE_CFCLK_ENABLE (1 << 2)
#define GEN8_DOP_CLOCK_GATE_GUC_ENABLE (1 << 4)
@@ -697,7 +733,8 @@
#define GAMTLBVEBOX0_CLKGATE_DIS REG_BIT(16)
#define LTCDD_CLKGATE_DIS REG_BIT(10)
-#define SLICE_UNIT_LEVEL_CLKGATE _MMIO(0x94d4)
+#define GEN11_SLICE_UNIT_LEVEL_CLKGATE _MMIO(0x94d4)
+#define XEHP_SLICE_UNIT_LEVEL_CLKGATE MCR_REG(0x94d4)
#define SARBUNIT_CLKGATE_DIS (1 << 5)
#define RCCUNIT_CLKGATE_DIS (1 << 7)
#define MSCUNIT_CLKGATE_DIS (1 << 10)
@@ -705,27 +742,27 @@
#define L3_CLKGATE_DIS REG_BIT(16)
#define L3_CR2X_CLKGATE_DIS REG_BIT(17)
-#define SCCGCTL94DC _MMIO(0x94dc)
+#define SCCGCTL94DC MCR_REG(0x94dc)
#define CG3DDISURB REG_BIT(14)
#define UNSLICE_UNIT_LEVEL_CLKGATE2 _MMIO(0x94e4)
#define VSUNIT_CLKGATE_DIS_TGL REG_BIT(19)
#define PSDUNIT_CLKGATE_DIS REG_BIT(5)
-#define SUBSLICE_UNIT_LEVEL_CLKGATE _MMIO(0x9524)
+#define GEN11_SUBSLICE_UNIT_LEVEL_CLKGATE MCR_REG(0x9524)
#define DSS_ROUTER_CLKGATE_DIS REG_BIT(28)
#define GWUNIT_CLKGATE_DIS REG_BIT(16)
-#define SUBSLICE_UNIT_LEVEL_CLKGATE2 _MMIO(0x9528)
+#define SUBSLICE_UNIT_LEVEL_CLKGATE2 MCR_REG(0x9528)
#define CPSSUNIT_CLKGATE_DIS REG_BIT(9)
-#define SSMCGCTL9530 _MMIO(0x9530)
+#define SSMCGCTL9530 MCR_REG(0x9530)
#define RTFUNIT_CLKGATE_DIS REG_BIT(18)
-#define GEN10_DFR_RATIO_EN_AND_CHICKEN _MMIO(0x9550)
+#define GEN10_DFR_RATIO_EN_AND_CHICKEN MCR_REG(0x9550)
#define DFR_DISABLE (1 << 9)
-#define INF_UNIT_LEVEL_CLKGATE _MMIO(0x9560)
+#define INF_UNIT_LEVEL_CLKGATE MCR_REG(0x9560)
#define CGPSF_CLKGATE_DIS (1 << 3)
#define MICRO_BP0_0 _MMIO(0x9800)
@@ -770,12 +807,9 @@
#define GEN6_RP_DOWN_TIMEOUT _MMIO(0xa010)
#define GEN6_RP_INTERRUPT_LIMITS _MMIO(0xa014)
#define GEN6_RPSTAT1 _MMIO(0xa01c)
-#define GEN6_CAGF_SHIFT 8
-#define HSW_CAGF_SHIFT 7
-#define GEN9_CAGF_SHIFT 23
-#define GEN6_CAGF_MASK (0x7f << GEN6_CAGF_SHIFT)
-#define HSW_CAGF_MASK (0x7f << HSW_CAGF_SHIFT)
-#define GEN9_CAGF_MASK (0x1ff << GEN9_CAGF_SHIFT)
+#define GEN6_CAGF_MASK REG_GENMASK(14, 8)
+#define HSW_CAGF_MASK REG_GENMASK(13, 7)
+#define GEN9_CAGF_MASK REG_GENMASK(31, 23)
#define GEN6_RP_CONTROL _MMIO(0xa024)
#define GEN6_RP_MEDIA_TURBO (1 << 11)
#define GEN6_RP_MEDIA_MODE_MASK (3 << 9)
@@ -898,6 +932,8 @@
#define FORCEWAKE_MEDIA_VDBOX_GEN11(n) _MMIO(0xa540 + (n) * 4)
#define FORCEWAKE_MEDIA_VEBOX_GEN11(n) _MMIO(0xa560 + (n) * 4)
+#define FORCEWAKE_REQ_GSC _MMIO(0xa618)
+
#define CHV_POWER_SS0_SIG1 _MMIO(0xa720)
#define CHV_POWER_SS0_SIG2 _MMIO(0xa724)
#define CHV_POWER_SS1_SIG1 _MMIO(0xa728)
@@ -935,7 +971,8 @@
/* MOCS (Memory Object Control State) registers */
#define GEN9_LNCFCMOCS(i) _MMIO(0xb020 + (i) * 4) /* L3 Cache Control */
-#define GEN9_LNCFCMOCS_REG_COUNT 32
+#define XEHP_LNCFCMOCS(i) MCR_REG(0xb020 + (i) * 4)
+#define LNCFCMOCS_REG_COUNT 32
#define GEN7_L3CNTLREG3 _MMIO(0xb024)
@@ -951,15 +988,10 @@
#define GEN7_L3LOG(slice, i) _MMIO(0xb070 + (slice) * 0x200 + (i) * 4)
#define GEN7_L3LOG_SIZE 0x80
-#define GEN10_SCRATCH_LNCF2 _MMIO(0xb0a0)
-#define PMFLUSHDONE_LNICRSDROP (1 << 20)
-#define PMFLUSH_GAPL3UNBLOCK (1 << 21)
-#define PMFLUSHDONE_LNEBLK (1 << 22)
-
-#define XEHP_L3NODEARBCFG _MMIO(0xb0b4)
+#define XEHP_L3NODEARBCFG MCR_REG(0xb0b4)
#define XEHP_LNESPARE REG_BIT(19)
-#define GEN8_L3SQCREG1 _MMIO(0xb100)
+#define GEN8_L3SQCREG1 MCR_REG(0xb100)
/*
* Note that on CHV the following has an off-by-one error wrt. to BSpec.
* Using the formula in BSpec leads to a hang, while the formula here works
@@ -970,31 +1002,28 @@
#define L3_HIGH_PRIO_CREDITS(x) (((x) >> 1) << 14)
#define L3_PRIO_CREDITS_MASK ((0x1f << 19) | (0x1f << 14))
-#define GEN10_L3_CHICKEN_MODE_REGISTER _MMIO(0xb114)
-#define GEN11_I2M_WRITE_DISABLE (1 << 28)
-
-#define GEN8_L3SQCREG4 _MMIO(0xb118)
+#define GEN8_L3SQCREG4 MCR_REG(0xb118)
#define GEN11_LQSC_CLEAN_EVICT_DISABLE (1 << 6)
#define GEN8_LQSC_RO_PERF_DIS (1 << 27)
#define GEN8_LQSC_FLUSH_COHERENT_LINES (1 << 21)
#define GEN8_LQSQ_NONIA_COHERENT_ATOMICS_ENABLE REG_BIT(22)
-#define GEN9_SCRATCH1 _MMIO(0xb11c)
+#define GEN9_SCRATCH1 MCR_REG(0xb11c)
#define EVICTION_PERF_FIX_ENABLE REG_BIT(8)
-#define BDW_SCRATCH1 _MMIO(0xb11c)
+#define BDW_SCRATCH1 MCR_REG(0xb11c)
#define GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE (1 << 2)
-#define GEN11_SCRATCH2 _MMIO(0xb140)
+#define GEN11_SCRATCH2 MCR_REG(0xb140)
#define GEN11_COHERENT_PARTIAL_WRITE_MERGE_ENABLE (1 << 19)
-#define GEN11_L3SQCREG5 _MMIO(0xb158)
+#define XEHP_L3SQCREG5 MCR_REG(0xb158)
#define L3_PWM_TIMER_INIT_VAL_MASK REG_GENMASK(9, 0)
-#define MLTICTXCTL _MMIO(0xb170)
+#define MLTICTXCTL MCR_REG(0xb170)
#define TDONRENDER REG_BIT(2)
-#define XEHP_L3SCQREG7 _MMIO(0xb188)
+#define XEHP_L3SCQREG7 MCR_REG(0xb188)
#define BLEND_FILL_CACHING_OPT_DIS REG_BIT(3)
#define XEHPC_L3SCRUB _MMIO(0xb18c)
@@ -1002,7 +1031,7 @@
#define SCRUB_RATE_PER_BANK_MASK REG_GENMASK(2, 0)
#define SCRUB_RATE_4B_PER_CLK REG_FIELD_PREP(SCRUB_RATE_PER_BANK_MASK, 0x6)
-#define L3SQCREG1_CCS0 _MMIO(0xb200)
+#define L3SQCREG1_CCS0 MCR_REG(0xb200)
#define FLUSHALLNONCOH REG_BIT(5)
#define GEN11_GLBLINVL _MMIO(0xb404)
@@ -1027,11 +1056,14 @@
#define GEN9_BLT_MOCS(i) _MMIO(__GEN9_BCS0_MOCS0 + (i) * 4)
#define GEN12_FAULT_TLB_DATA0 _MMIO(0xceb8)
+#define XEHP_FAULT_TLB_DATA0 MCR_REG(0xceb8)
#define GEN12_FAULT_TLB_DATA1 _MMIO(0xcebc)
+#define XEHP_FAULT_TLB_DATA1 MCR_REG(0xcebc)
#define FAULT_VA_HIGH_BITS (0xf << 0)
#define FAULT_GTT_SEL (1 << 4)
#define GEN12_RING_FAULT_REG _MMIO(0xcec4)
+#define XEHP_RING_FAULT_REG MCR_REG(0xcec4)
#define GEN8_RING_FAULT_ENGINE_ID(x) (((x) >> 12) & 0x7)
#define RING_FAULT_GTTSEL_MASK (1 << 11)
#define RING_FAULT_SRCID(x) (((x) >> 3) & 0xff)
@@ -1039,16 +1071,21 @@
#define RING_FAULT_VALID (1 << 0)
#define GEN12_GFX_TLB_INV_CR _MMIO(0xced8)
+#define XEHP_GFX_TLB_INV_CR MCR_REG(0xced8)
#define GEN12_VD_TLB_INV_CR _MMIO(0xcedc)
+#define XEHP_VD_TLB_INV_CR MCR_REG(0xcedc)
#define GEN12_VE_TLB_INV_CR _MMIO(0xcee0)
+#define XEHP_VE_TLB_INV_CR MCR_REG(0xcee0)
#define GEN12_BLT_TLB_INV_CR _MMIO(0xcee4)
+#define XEHP_BLT_TLB_INV_CR MCR_REG(0xcee4)
#define GEN12_COMPCTX_TLB_INV_CR _MMIO(0xcf04)
+#define XEHP_COMPCTX_TLB_INV_CR MCR_REG(0xcf04)
-#define GEN12_MERT_MOD_CTRL _MMIO(0xcf28)
-#define RENDER_MOD_CTRL _MMIO(0xcf2c)
-#define COMP_MOD_CTRL _MMIO(0xcf30)
-#define VDBX_MOD_CTRL _MMIO(0xcf34)
-#define VEBX_MOD_CTRL _MMIO(0xcf38)
+#define XEHP_MERT_MOD_CTRL MCR_REG(0xcf28)
+#define RENDER_MOD_CTRL MCR_REG(0xcf2c)
+#define COMP_MOD_CTRL MCR_REG(0xcf30)
+#define VDBX_MOD_CTRL MCR_REG(0xcf34)
+#define VEBX_MOD_CTRL MCR_REG(0xcf38)
#define FORCE_MISS_FTLB REG_BIT(3)
#define GEN12_GAMSTLB_CTRL _MMIO(0xcf4c)
@@ -1063,48 +1100,52 @@
#define GEN12_GAM_DONE _MMIO(0xcf68)
#define GEN7_HALF_SLICE_CHICKEN1 _MMIO(0xe100) /* IVB GT1 + VLV */
+#define GEN8_HALF_SLICE_CHICKEN1 MCR_REG(0xe100)
#define GEN7_MAX_PS_THREAD_DEP (8 << 12)
#define GEN7_SINGLE_SUBSCAN_DISPATCH_ENABLE (1 << 10)
#define GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE (1 << 4)
#define GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE (1 << 3)
#define GEN7_SAMPLER_INSTDONE _MMIO(0xe160)
+#define GEN8_SAMPLER_INSTDONE MCR_REG(0xe160)
#define GEN7_ROW_INSTDONE _MMIO(0xe164)
+#define GEN8_ROW_INSTDONE MCR_REG(0xe164)
-#define HALF_SLICE_CHICKEN2 _MMIO(0xe180)
+#define HALF_SLICE_CHICKEN2 MCR_REG(0xe180)
#define GEN8_ST_PO_DISABLE (1 << 13)
-#define HALF_SLICE_CHICKEN3 _MMIO(0xe184)
+#define HSW_HALF_SLICE_CHICKEN3 _MMIO(0xe184)
+#define GEN8_HALF_SLICE_CHICKEN3 MCR_REG(0xe184)
#define HSW_SAMPLE_C_PERFORMANCE (1 << 9)
#define GEN8_CENTROID_PIXEL_OPT_DIS (1 << 8)
#define GEN9_DISABLE_OCL_OOB_SUPPRESS_LOGIC (1 << 5)
#define GEN8_SAMPLER_POWER_BYPASS_DIS (1 << 1)
-#define GEN9_HALF_SLICE_CHICKEN5 _MMIO(0xe188)
+#define GEN9_HALF_SLICE_CHICKEN5 MCR_REG(0xe188)
#define GEN9_DG_MIRROR_FIX_ENABLE (1 << 5)
#define GEN9_CCS_TLB_PREFETCH_ENABLE (1 << 3)
-#define GEN10_SAMPLER_MODE _MMIO(0xe18c)
+#define GEN10_SAMPLER_MODE MCR_REG(0xe18c)
#define ENABLE_SMALLPL REG_BIT(15)
#define SC_DISABLE_POWER_OPTIMIZATION_EBB REG_BIT(9)
#define GEN11_SAMPLER_ENABLE_HEADLESS_MSG REG_BIT(5)
-#define GEN9_HALF_SLICE_CHICKEN7 _MMIO(0xe194)
+#define GEN9_HALF_SLICE_CHICKEN7 MCR_REG(0xe194)
#define DG2_DISABLE_ROUND_ENABLE_ALLOW_FOR_SSLA REG_BIT(15)
#define GEN9_SAMPLER_HASH_COMPRESSED_READ_ADDR REG_BIT(8)
#define GEN9_ENABLE_YV12_BUGFIX REG_BIT(4)
#define GEN9_ENABLE_GPGPU_PREEMPTION REG_BIT(2)
-#define GEN10_CACHE_MODE_SS _MMIO(0xe420)
+#define GEN10_CACHE_MODE_SS MCR_REG(0xe420)
#define ENABLE_EU_COUNT_FOR_TDL_FLUSH REG_BIT(10)
#define DISABLE_ECC REG_BIT(5)
#define FLOAT_BLEND_OPTIMIZATION_ENABLE REG_BIT(4)
#define ENABLE_PREFETCH_INTO_IC REG_BIT(3)
-#define EU_PERF_CNTL0 _MMIO(0xe458)
-#define EU_PERF_CNTL4 _MMIO(0xe45c)
+#define EU_PERF_CNTL0 PERF_REG(0xe458)
+#define EU_PERF_CNTL4 PERF_REG(0xe45c)
-#define GEN9_ROW_CHICKEN4 _MMIO(0xe48c)
+#define GEN9_ROW_CHICKEN4 MCR_REG(0xe48c)
#define GEN12_DISABLE_GRF_CLEAR REG_BIT(13)
#define XEHP_DIS_BBL_SYSPIPE REG_BIT(11)
#define GEN12_DISABLE_TDL_PUSH REG_BIT(9)
@@ -1116,7 +1157,7 @@
#define HSW_ROW_CHICKEN3 _MMIO(0xe49c)
#define HSW_ROW_CHICKEN3_L3_GLOBAL_ATOMICS_DISABLE (1 << 6)
-#define GEN8_ROW_CHICKEN _MMIO(0xe4f0)
+#define GEN8_ROW_CHICKEN MCR_REG(0xe4f0)
#define FLOW_CONTROL_ENABLE REG_BIT(15)
#define UGM_BACKUP_MODE REG_BIT(13)
#define MDQ_ARBITRATION_MODE REG_BIT(12)
@@ -1127,42 +1168,43 @@
#define DISABLE_EARLY_EOT REG_BIT(1)
#define GEN7_ROW_CHICKEN2 _MMIO(0xe4f4)
+
+#define GEN8_ROW_CHICKEN2 MCR_REG(0xe4f4)
#define GEN12_DISABLE_READ_SUPPRESSION REG_BIT(15)
#define GEN12_DISABLE_EARLY_READ REG_BIT(14)
#define GEN12_ENABLE_LARGE_GRF_MODE REG_BIT(12)
#define GEN12_PUSH_CONST_DEREF_HOLD_DIS REG_BIT(8)
+#define GEN12_DISABLE_DOP_GATING REG_BIT(0)
-#define RT_CTRL _MMIO(0xe530)
+#define RT_CTRL MCR_REG(0xe530)
#define DIS_NULL_QUERY REG_BIT(10)
#define STACKID_CTRL REG_GENMASK(6, 5)
#define STACKID_CTRL_512 REG_FIELD_PREP(STACKID_CTRL, 0x2)
-#define EU_PERF_CNTL1 _MMIO(0xe558)
-#define EU_PERF_CNTL5 _MMIO(0xe55c)
+#define EU_PERF_CNTL1 PERF_REG(0xe558)
+#define EU_PERF_CNTL5 PERF_REG(0xe55c)
-#define GEN12_HDC_CHICKEN0 _MMIO(0xe5f0)
+#define XEHP_HDC_CHICKEN0 MCR_REG(0xe5f0)
#define LSC_L1_FLUSH_CTL_3D_DATAPORT_FLUSH_EVENTS_MASK REG_GENMASK(13, 11)
-#define ICL_HDC_MODE _MMIO(0xe5f4)
+#define ICL_HDC_MODE MCR_REG(0xe5f4)
-#define EU_PERF_CNTL2 _MMIO(0xe658)
-#define EU_PERF_CNTL6 _MMIO(0xe65c)
-#define EU_PERF_CNTL3 _MMIO(0xe758)
+#define EU_PERF_CNTL2 PERF_REG(0xe658)
+#define EU_PERF_CNTL6 PERF_REG(0xe65c)
+#define EU_PERF_CNTL3 PERF_REG(0xe758)
-#define LSC_CHICKEN_BIT_0 _MMIO(0xe7c8)
+#define LSC_CHICKEN_BIT_0 MCR_REG(0xe7c8)
#define DISABLE_D8_D16_COASLESCE REG_BIT(30)
#define FORCE_1_SUB_MESSAGE_PER_FRAGMENT REG_BIT(15)
-#define LSC_CHICKEN_BIT_0_UDW _MMIO(0xe7c8 + 4)
+#define LSC_CHICKEN_BIT_0_UDW MCR_REG(0xe7c8 + 4)
#define DIS_CHAIN_2XSIMD8 REG_BIT(55 - 32)
#define FORCE_SLM_FENCE_SCOPE_TO_TILE REG_BIT(42 - 32)
#define FORCE_UGM_FENCE_SCOPE_TO_TILE REG_BIT(41 - 32)
#define MAXREQS_PER_BANK REG_GENMASK(39 - 32, 37 - 32)
#define DISABLE_128B_EVICTION_COMMAND_UDW REG_BIT(36 - 32)
-#define SARB_CHICKEN1 _MMIO(0xe90c)
+#define SARB_CHICKEN1 MCR_REG(0xe90c)
#define COMP_CKN_IN REG_GENMASK(30, 29)
-#define GEN7_HALF_SLICE_CHICKEN1_GT2 _MMIO(0xf100)
-
#define GEN7_ROW_CHICKEN2_GT2 _MMIO(0xf4f4)
#define DOP_CLOCK_GATING_DISABLE (1 << 0)
#define PUSH_CONSTANT_DEREF_DISABLE (1 << 8)
@@ -1339,8 +1381,7 @@
#define MEMSTAT_ILK _MMIO(0x111f8)
#define MEMSTAT_VID_MASK 0x7f00
#define MEMSTAT_VID_SHIFT 8
-#define MEMSTAT_PSTATE_MASK 0x00f8
-#define MEMSTAT_PSTATE_SHIFT 3
+#define MEMSTAT_PSTATE_MASK REG_GENMASK(7, 3)
#define MEMSTAT_MON_ACTV (1 << 2)
#define MEMSTAT_SRC_CTL_MASK 0x0003
#define MEMSTAT_SRC_CTL_CORE 0
@@ -1481,6 +1522,8 @@
#define FORCEWAKE_MEDIA_VLV _MMIO(0x1300b8)
#define FORCEWAKE_ACK_MEDIA_VLV _MMIO(0x1300bc)
+#define MTL_MEDIA_MC6 _MMIO(0x138048)
+
#define GEN6_GT_THREAD_STATUS_REG _MMIO(0x13805c)
#define GEN6_GT_THREAD_STATUS_CORE_MASK 0x7
@@ -1510,10 +1553,15 @@
#define VLV_RENDER_C0_COUNT _MMIO(0x138118)
#define VLV_MEDIA_C0_COUNT _MMIO(0x13811c)
+#define GEN12_RPSTAT1 _MMIO(0x1381b4)
+#define GEN12_VOLTAGE_MASK REG_GENMASK(10, 0)
+#define GEN12_CAGF_MASK REG_GENMASK(19, 11)
+
#define GEN11_GT_INTR_DW(x) _MMIO(0x190018 + ((x) * 4))
#define GEN11_CSME (31)
#define GEN11_GUNIT (28)
#define GEN11_GUC (25)
+#define MTL_MGUC (24)
#define GEN11_WDPERF (20)
#define GEN11_KCR (19)
#define GEN11_GTPM (16)
@@ -1568,6 +1616,7 @@
#define GEN11_VECS0_VECS1_INTR_MASK _MMIO(0x1900d0)
#define GEN12_VECS2_VECS3_INTR_MASK _MMIO(0x1900d4)
#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)
#define GEN11_CRYPTO_RSVD_INTR_MASK _MMIO(0x1900f0)
#define GEN11_GUNIT_CSME_INTR_MASK _MMIO(0x1900f4)
@@ -1580,6 +1629,11 @@
#define GEN12_SFC_DONE(n) _MMIO(0x1cc000 + (n) * 0x1000)
+#define GT0_PACKAGE_ENERGY_STATUS _MMIO(0x250004)
+#define GT0_PACKAGE_RAPL_LIMIT _MMIO(0x250008)
+#define GT0_PACKAGE_POWER_SKU_UNIT _MMIO(0x250068)
+#define GT0_PLATFORM_ENERGY_STATUS _MMIO(0x25006c)
+
/*
* Standalone Media's non-engine GT registers are located at their regular GT
* offsets plus 0x380000. This extra offset is stored inside the intel_uncore
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_sysfs.c b/drivers/gpu/drm/i915/gt/intel_gt_sysfs.c
index d651ccd0ab20..9486dd3bed99 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_sysfs.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_sysfs.c
@@ -22,11 +22,9 @@ bool is_object_gt(struct kobject *kobj)
return !strncmp(kobj->name, "gt", 2);
}
-struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
+struct intel_gt *intel_gt_sysfs_get_drvdata(struct kobject *kobj,
const char *name)
{
- struct kobject *kobj = &dev->kobj;
-
/*
* We are interested at knowing from where the interface
* has been called, whether it's called from gt/ or from
@@ -38,6 +36,7 @@ struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
* "struct drm_i915_private *" type.
*/
if (!is_object_gt(kobj)) {
+ struct device *dev = kobj_to_dev(kobj);
struct drm_i915_private *i915 = kdev_minor_to_i915(dev);
return to_gt(i915);
@@ -51,18 +50,18 @@ static struct kobject *gt_get_parent_obj(struct intel_gt *gt)
return &gt->i915->drm.primary->kdev->kobj;
}
-static ssize_t id_show(struct device *dev,
- struct device_attribute *attr,
+static ssize_t id_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
char *buf)
{
- struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+ struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
return sysfs_emit(buf, "%u\n", gt->info.id);
}
-static DEVICE_ATTR_RO(id);
+static struct kobj_attribute attr_id = __ATTR_RO(id);
static struct attribute *id_attrs[] = {
- &dev_attr_id.attr,
+ &attr_id.attr,
NULL,
};
ATTRIBUTE_GROUPS(id);
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_sysfs.h b/drivers/gpu/drm/i915/gt/intel_gt_sysfs.h
index 6232923a420d..18bab835be02 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_sysfs.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_sysfs.h
@@ -18,11 +18,6 @@ bool is_object_gt(struct kobject *kobj);
struct drm_i915_private *kobj_to_i915(struct kobject *kobj);
-struct kobject *
-intel_gt_create_kobj(struct intel_gt *gt,
- struct kobject *dir,
- const char *name);
-
static inline struct intel_gt *kobj_to_gt(struct kobject *kobj)
{
return container_of(kobj, struct intel_gt, sysfs_gt);
@@ -30,7 +25,7 @@ static inline struct intel_gt *kobj_to_gt(struct kobject *kobj)
void intel_gt_sysfs_register(struct intel_gt *gt);
void intel_gt_sysfs_unregister(struct intel_gt *gt);
-struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev,
+struct intel_gt *intel_gt_sysfs_get_drvdata(struct kobject *kobj,
const char *name);
#endif /* SYSFS_GT_H */
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 180dd6f3ef57..cf71305ad586 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c
@@ -24,14 +24,15 @@ enum intel_gt_sysfs_op {
};
static int
-sysfs_gt_attribute_w_func(struct device *dev, struct device_attribute *attr,
+sysfs_gt_attribute_w_func(struct kobject *kobj, struct attribute *attr,
int (func)(struct intel_gt *gt, u32 val), u32 val)
{
struct intel_gt *gt;
int ret;
- if (!is_object_gt(&dev->kobj)) {
+ if (!is_object_gt(kobj)) {
int i;
+ struct device *dev = kobj_to_dev(kobj);
struct drm_i915_private *i915 = kdev_minor_to_i915(dev);
for_each_gt(gt, i915, i) {
@@ -40,7 +41,7 @@ sysfs_gt_attribute_w_func(struct device *dev, struct device_attribute *attr,
break;
}
} else {
- gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+ gt = intel_gt_sysfs_get_drvdata(kobj, attr->name);
ret = func(gt, val);
}
@@ -48,7 +49,7 @@ sysfs_gt_attribute_w_func(struct device *dev, struct device_attribute *attr,
}
static u32
-sysfs_gt_attribute_r_func(struct device *dev, struct device_attribute *attr,
+sysfs_gt_attribute_r_func(struct kobject *kobj, struct attribute *attr,
u32 (func)(struct intel_gt *gt),
enum intel_gt_sysfs_op op)
{
@@ -57,8 +58,9 @@ sysfs_gt_attribute_r_func(struct device *dev, struct device_attribute *attr,
ret = (op == INTEL_GT_SYSFS_MAX) ? 0 : (u32) -1;
- if (!is_object_gt(&dev->kobj)) {
+ if (!is_object_gt(kobj)) {
int i;
+ struct device *dev = kobj_to_dev(kobj);
struct drm_i915_private *i915 = kdev_minor_to_i915(dev);
for_each_gt(gt, i915, i) {
@@ -77,7 +79,7 @@ sysfs_gt_attribute_r_func(struct device *dev, struct device_attribute *attr,
}
}
} else {
- gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+ gt = intel_gt_sysfs_get_drvdata(kobj, attr->name);
ret = func(gt);
}
@@ -92,23 +94,90 @@ sysfs_gt_attribute_r_func(struct device *dev, struct device_attribute *attr,
#define sysfs_gt_attribute_r_max_func(d, a, f) \
sysfs_gt_attribute_r_func(d, a, f, INTEL_GT_SYSFS_MAX)
+#define INTEL_GT_SYSFS_SHOW(_name, _attr_type) \
+ static ssize_t _name##_show_common(struct kobject *kobj, \
+ struct attribute *attr, char *buff) \
+ { \
+ u32 val = sysfs_gt_attribute_r_##_attr_type##_func(kobj, attr, \
+ __##_name##_show); \
+ \
+ return sysfs_emit(buff, "%u\n", val); \
+ } \
+ static ssize_t _name##_show(struct kobject *kobj, \
+ struct kobj_attribute *attr, char *buff) \
+ { \
+ return _name ##_show_common(kobj, &attr->attr, buff); \
+ } \
+ static ssize_t _name##_dev_show(struct device *dev, \
+ struct device_attribute *attr, char *buff) \
+ { \
+ return _name##_show_common(&dev->kobj, &attr->attr, buff); \
+ }
+
+#define INTEL_GT_SYSFS_STORE(_name, _func) \
+ static ssize_t _name##_store_common(struct kobject *kobj, \
+ struct attribute *attr, \
+ const char *buff, size_t count) \
+ { \
+ int ret; \
+ u32 val; \
+ \
+ ret = kstrtou32(buff, 0, &val); \
+ if (ret) \
+ return ret; \
+ \
+ ret = sysfs_gt_attribute_w_func(kobj, attr, _func, val); \
+ \
+ return ret ?: count; \
+ } \
+ static ssize_t _name##_store(struct kobject *kobj, \
+ struct kobj_attribute *attr, const char *buff, \
+ size_t count) \
+ { \
+ return _name##_store_common(kobj, &attr->attr, buff, count); \
+ } \
+ static ssize_t _name##_dev_store(struct device *dev, \
+ struct device_attribute *attr, \
+ const char *buff, size_t count) \
+ { \
+ return _name##_store_common(&dev->kobj, &attr->attr, buff, count); \
+ }
+
+#define INTEL_GT_SYSFS_SHOW_MAX(_name) INTEL_GT_SYSFS_SHOW(_name, max)
+#define INTEL_GT_SYSFS_SHOW_MIN(_name) INTEL_GT_SYSFS_SHOW(_name, min)
+
+#define INTEL_GT_ATTR_RW(_name) \
+ static struct kobj_attribute attr_##_name = __ATTR_RW(_name)
+
+#define INTEL_GT_ATTR_RO(_name) \
+ static struct kobj_attribute attr_##_name = __ATTR_RO(_name)
+
+#define INTEL_GT_DUAL_ATTR_RW(_name) \
+ static struct device_attribute dev_attr_##_name = __ATTR(_name, 0644, \
+ _name##_dev_show, \
+ _name##_dev_store); \
+ INTEL_GT_ATTR_RW(_name)
+
+#define INTEL_GT_DUAL_ATTR_RO(_name) \
+ static struct device_attribute dev_attr_##_name = __ATTR(_name, 0444, \
+ _name##_dev_show, \
+ NULL); \
+ INTEL_GT_ATTR_RO(_name)
+
#ifdef CONFIG_PM
-static u32 get_residency(struct intel_gt *gt, i915_reg_t reg)
+static u32 get_residency(struct intel_gt *gt, enum intel_rc6_res_type id)
{
intel_wakeref_t wakeref;
u64 res = 0;
with_intel_runtime_pm(gt->uncore->rpm, wakeref)
- res = intel_rc6_residency_us(&gt->rc6, reg);
+ res = intel_rc6_residency_us(&gt->rc6, id);
return DIV_ROUND_CLOSEST_ULL(res, 1000);
}
-static ssize_t rc6_enable_show(struct device *dev,
- struct device_attribute *attr,
- char *buff)
+static u8 get_rc6_mask(struct intel_gt *gt)
{
- struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
u8 mask = 0;
if (HAS_RC6(gt->i915))
@@ -118,105 +187,105 @@ static ssize_t rc6_enable_show(struct device *dev,
if (HAS_RC6pp(gt->i915))
mask |= BIT(2);
- return sysfs_emit(buff, "%x\n", mask);
+ return mask;
}
-static u32 __rc6_residency_ms_show(struct intel_gt *gt)
+static ssize_t rc6_enable_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buff)
{
- return get_residency(gt, GEN6_GT_GFX_RC6);
+ struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
+
+ return sysfs_emit(buff, "%x\n", get_rc6_mask(gt));
}
-static ssize_t rc6_residency_ms_show(struct device *dev,
- struct device_attribute *attr,
- char *buff)
+static ssize_t rc6_enable_dev_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buff)
{
- u32 rc6_residency = sysfs_gt_attribute_r_min_func(dev, attr,
- __rc6_residency_ms_show);
+ struct intel_gt *gt = intel_gt_sysfs_get_drvdata(&dev->kobj, attr->attr.name);
- return sysfs_emit(buff, "%u\n", rc6_residency);
+ return sysfs_emit(buff, "%x\n", get_rc6_mask(gt));
}
-static u32 __rc6p_residency_ms_show(struct intel_gt *gt)
+static u32 __rc6_residency_ms_show(struct intel_gt *gt)
{
- return get_residency(gt, GEN6_GT_GFX_RC6p);
+ return get_residency(gt, INTEL_RC6_RES_RC6);
}
-static ssize_t rc6p_residency_ms_show(struct device *dev,
- struct device_attribute *attr,
- char *buff)
+static u32 __rc6p_residency_ms_show(struct intel_gt *gt)
{
- u32 rc6p_residency = sysfs_gt_attribute_r_min_func(dev, attr,
- __rc6p_residency_ms_show);
-
- return sysfs_emit(buff, "%u\n", rc6p_residency);
+ return get_residency(gt, INTEL_RC6_RES_RC6p);
}
static u32 __rc6pp_residency_ms_show(struct intel_gt *gt)
{
- return get_residency(gt, GEN6_GT_GFX_RC6pp);
-}
-
-static ssize_t rc6pp_residency_ms_show(struct device *dev,
- struct device_attribute *attr,
- char *buff)
-{
- u32 rc6pp_residency = sysfs_gt_attribute_r_min_func(dev, attr,
- __rc6pp_residency_ms_show);
-
- return sysfs_emit(buff, "%u\n", rc6pp_residency);
+ return get_residency(gt, INTEL_RC6_RES_RC6pp);
}
static u32 __media_rc6_residency_ms_show(struct intel_gt *gt)
{
- return get_residency(gt, VLV_GT_MEDIA_RC6);
+ return get_residency(gt, INTEL_RC6_RES_VLV_MEDIA);
}
-static ssize_t media_rc6_residency_ms_show(struct device *dev,
- struct device_attribute *attr,
- char *buff)
-{
- u32 rc6_residency = sysfs_gt_attribute_r_min_func(dev, attr,
- __media_rc6_residency_ms_show);
+INTEL_GT_SYSFS_SHOW_MIN(rc6_residency_ms);
+INTEL_GT_SYSFS_SHOW_MIN(rc6p_residency_ms);
+INTEL_GT_SYSFS_SHOW_MIN(rc6pp_residency_ms);
+INTEL_GT_SYSFS_SHOW_MIN(media_rc6_residency_ms);
- return sysfs_emit(buff, "%u\n", rc6_residency);
-}
-
-static DEVICE_ATTR_RO(rc6_enable);
-static DEVICE_ATTR_RO(rc6_residency_ms);
-static DEVICE_ATTR_RO(rc6p_residency_ms);
-static DEVICE_ATTR_RO(rc6pp_residency_ms);
-static DEVICE_ATTR_RO(media_rc6_residency_ms);
+INTEL_GT_DUAL_ATTR_RO(rc6_enable);
+INTEL_GT_DUAL_ATTR_RO(rc6_residency_ms);
+INTEL_GT_DUAL_ATTR_RO(rc6p_residency_ms);
+INTEL_GT_DUAL_ATTR_RO(rc6pp_residency_ms);
+INTEL_GT_DUAL_ATTR_RO(media_rc6_residency_ms);
static struct attribute *rc6_attrs[] = {
+ &attr_rc6_enable.attr,
+ &attr_rc6_residency_ms.attr,
+ NULL
+};
+
+static struct attribute *rc6p_attrs[] = {
+ &attr_rc6p_residency_ms.attr,
+ &attr_rc6pp_residency_ms.attr,
+ NULL
+};
+
+static struct attribute *media_rc6_attrs[] = {
+ &attr_media_rc6_residency_ms.attr,
+ NULL
+};
+
+static struct attribute *rc6_dev_attrs[] = {
&dev_attr_rc6_enable.attr,
&dev_attr_rc6_residency_ms.attr,
NULL
};
-static struct attribute *rc6p_attrs[] = {
+static struct attribute *rc6p_dev_attrs[] = {
&dev_attr_rc6p_residency_ms.attr,
&dev_attr_rc6pp_residency_ms.attr,
NULL
};
-static struct attribute *media_rc6_attrs[] = {
+static struct attribute *media_rc6_dev_attrs[] = {
&dev_attr_media_rc6_residency_ms.attr,
NULL
};
static const struct attribute_group rc6_attr_group[] = {
{ .attrs = rc6_attrs, },
- { .name = power_group_name, .attrs = rc6_attrs, },
+ { .name = power_group_name, .attrs = rc6_dev_attrs, },
};
static const struct attribute_group rc6p_attr_group[] = {
{ .attrs = rc6p_attrs, },
- { .name = power_group_name, .attrs = rc6p_attrs, },
+ { .name = power_group_name, .attrs = rc6p_dev_attrs, },
};
static const struct attribute_group media_rc6_attr_group[] = {
{ .attrs = media_rc6_attrs, },
- { .name = power_group_name, .attrs = media_rc6_attrs, },
+ { .name = power_group_name, .attrs = media_rc6_dev_attrs, },
};
static int __intel_gt_sysfs_create_group(struct kobject *kobj,
@@ -271,104 +340,34 @@ static u32 __act_freq_mhz_show(struct intel_gt *gt)
return intel_rps_read_actual_frequency(&gt->rps);
}
-static ssize_t act_freq_mhz_show(struct device *dev,
- struct device_attribute *attr, char *buff)
-{
- u32 actual_freq = sysfs_gt_attribute_r_max_func(dev, attr,
- __act_freq_mhz_show);
-
- return sysfs_emit(buff, "%u\n", actual_freq);
-}
-
static u32 __cur_freq_mhz_show(struct intel_gt *gt)
{
return intel_rps_get_requested_frequency(&gt->rps);
}
-static ssize_t cur_freq_mhz_show(struct device *dev,
- struct device_attribute *attr, char *buff)
-{
- u32 cur_freq = sysfs_gt_attribute_r_max_func(dev, attr,
- __cur_freq_mhz_show);
-
- return sysfs_emit(buff, "%u\n", cur_freq);
-}
-
static u32 __boost_freq_mhz_show(struct intel_gt *gt)
{
return intel_rps_get_boost_frequency(&gt->rps);
}
-static ssize_t boost_freq_mhz_show(struct device *dev,
- struct device_attribute *attr,
- char *buff)
-{
- u32 boost_freq = sysfs_gt_attribute_r_max_func(dev, attr,
- __boost_freq_mhz_show);
-
- return sysfs_emit(buff, "%u\n", boost_freq);
-}
-
static int __boost_freq_mhz_store(struct intel_gt *gt, u32 val)
{
return intel_rps_set_boost_frequency(&gt->rps, val);
}
-static ssize_t boost_freq_mhz_store(struct device *dev,
- struct device_attribute *attr,
- const char *buff, size_t count)
-{
- ssize_t ret;
- u32 val;
-
- ret = kstrtou32(buff, 0, &val);
- if (ret)
- return ret;
-
- return sysfs_gt_attribute_w_func(dev, attr,
- __boost_freq_mhz_store, val) ?: count;
-}
-
-static u32 __rp0_freq_mhz_show(struct intel_gt *gt)
+static u32 __RP0_freq_mhz_show(struct intel_gt *gt)
{
return intel_rps_get_rp0_frequency(&gt->rps);
}
-static ssize_t RP0_freq_mhz_show(struct device *dev,
- struct device_attribute *attr, char *buff)
-{
- u32 rp0_freq = sysfs_gt_attribute_r_max_func(dev, attr,
- __rp0_freq_mhz_show);
-
- return sysfs_emit(buff, "%u\n", rp0_freq);
-}
-
-static u32 __rp1_freq_mhz_show(struct intel_gt *gt)
-{
- return intel_rps_get_rp1_frequency(&gt->rps);
-}
-
-static ssize_t RP1_freq_mhz_show(struct device *dev,
- struct device_attribute *attr, char *buff)
-{
- u32 rp1_freq = sysfs_gt_attribute_r_max_func(dev, attr,
- __rp1_freq_mhz_show);
-
- return sysfs_emit(buff, "%u\n", rp1_freq);
-}
-
-static u32 __rpn_freq_mhz_show(struct intel_gt *gt)
+static u32 __RPn_freq_mhz_show(struct intel_gt *gt)
{
return intel_rps_get_rpn_frequency(&gt->rps);
}
-static ssize_t RPn_freq_mhz_show(struct device *dev,
- struct device_attribute *attr, char *buff)
+static u32 __RP1_freq_mhz_show(struct intel_gt *gt)
{
- u32 rpn_freq = sysfs_gt_attribute_r_max_func(dev, attr,
- __rpn_freq_mhz_show);
-
- return sysfs_emit(buff, "%u\n", rpn_freq);
+ return intel_rps_get_rp1_frequency(&gt->rps);
}
static u32 __max_freq_mhz_show(struct intel_gt *gt)
@@ -376,71 +375,21 @@ static u32 __max_freq_mhz_show(struct intel_gt *gt)
return intel_rps_get_max_frequency(&gt->rps);
}
-static ssize_t max_freq_mhz_show(struct device *dev,
- struct device_attribute *attr, char *buff)
-{
- u32 max_freq = sysfs_gt_attribute_r_max_func(dev, attr,
- __max_freq_mhz_show);
-
- return sysfs_emit(buff, "%u\n", max_freq);
-}
-
static int __set_max_freq(struct intel_gt *gt, u32 val)
{
return intel_rps_set_max_frequency(&gt->rps, val);
}
-static ssize_t max_freq_mhz_store(struct device *dev,
- struct device_attribute *attr,
- const char *buff, size_t count)
-{
- int ret;
- u32 val;
-
- ret = kstrtou32(buff, 0, &val);
- if (ret)
- return ret;
-
- ret = sysfs_gt_attribute_w_func(dev, attr, __set_max_freq, val);
-
- return ret ?: count;
-}
-
static u32 __min_freq_mhz_show(struct intel_gt *gt)
{
return intel_rps_get_min_frequency(&gt->rps);
}
-static ssize_t min_freq_mhz_show(struct device *dev,
- struct device_attribute *attr, char *buff)
-{
- u32 min_freq = sysfs_gt_attribute_r_min_func(dev, attr,
- __min_freq_mhz_show);
-
- return sysfs_emit(buff, "%u\n", min_freq);
-}
-
static int __set_min_freq(struct intel_gt *gt, u32 val)
{
return intel_rps_set_min_frequency(&gt->rps, val);
}
-static ssize_t min_freq_mhz_store(struct device *dev,
- struct device_attribute *attr,
- const char *buff, size_t count)
-{
- int ret;
- u32 val;
-
- ret = kstrtou32(buff, 0, &val);
- if (ret)
- return ret;
-
- ret = sysfs_gt_attribute_w_func(dev, attr, __set_min_freq, val);
-
- return ret ?: count;
-}
-
static u32 __vlv_rpe_freq_mhz_show(struct intel_gt *gt)
{
struct intel_rps *rps = &gt->rps;
@@ -448,23 +397,31 @@ static u32 __vlv_rpe_freq_mhz_show(struct intel_gt *gt)
return intel_gpu_freq(rps, rps->efficient_freq);
}
-static ssize_t vlv_rpe_freq_mhz_show(struct device *dev,
- struct device_attribute *attr, char *buff)
-{
- u32 rpe_freq = sysfs_gt_attribute_r_max_func(dev, attr,
- __vlv_rpe_freq_mhz_show);
-
- return sysfs_emit(buff, "%u\n", rpe_freq);
-}
-
-#define INTEL_GT_RPS_SYSFS_ATTR(_name, _mode, _show, _store) \
- static struct device_attribute dev_attr_gt_##_name = __ATTR(gt_##_name, _mode, _show, _store); \
- static struct device_attribute dev_attr_rps_##_name = __ATTR(rps_##_name, _mode, _show, _store)
-
-#define INTEL_GT_RPS_SYSFS_ATTR_RO(_name) \
- INTEL_GT_RPS_SYSFS_ATTR(_name, 0444, _name##_show, NULL)
-#define INTEL_GT_RPS_SYSFS_ATTR_RW(_name) \
- INTEL_GT_RPS_SYSFS_ATTR(_name, 0644, _name##_show, _name##_store)
+INTEL_GT_SYSFS_SHOW_MAX(act_freq_mhz);
+INTEL_GT_SYSFS_SHOW_MAX(boost_freq_mhz);
+INTEL_GT_SYSFS_SHOW_MAX(cur_freq_mhz);
+INTEL_GT_SYSFS_SHOW_MAX(RP0_freq_mhz);
+INTEL_GT_SYSFS_SHOW_MAX(RP1_freq_mhz);
+INTEL_GT_SYSFS_SHOW_MAX(RPn_freq_mhz);
+INTEL_GT_SYSFS_SHOW_MAX(max_freq_mhz);
+INTEL_GT_SYSFS_SHOW_MIN(min_freq_mhz);
+INTEL_GT_SYSFS_SHOW_MAX(vlv_rpe_freq_mhz);
+INTEL_GT_SYSFS_STORE(boost_freq_mhz, __boost_freq_mhz_store);
+INTEL_GT_SYSFS_STORE(max_freq_mhz, __set_max_freq);
+INTEL_GT_SYSFS_STORE(min_freq_mhz, __set_min_freq);
+
+#define INTEL_GT_RPS_SYSFS_ATTR(_name, _mode, _show, _store, _show_dev, _store_dev) \
+ static struct device_attribute dev_attr_gt_##_name = __ATTR(gt_##_name, _mode, \
+ _show_dev, _store_dev); \
+ static struct kobj_attribute attr_rps_##_name = __ATTR(rps_##_name, _mode, \
+ _show, _store)
+
+#define INTEL_GT_RPS_SYSFS_ATTR_RO(_name) \
+ INTEL_GT_RPS_SYSFS_ATTR(_name, 0444, _name##_show, NULL, \
+ _name##_dev_show, NULL)
+#define INTEL_GT_RPS_SYSFS_ATTR_RW(_name) \
+ INTEL_GT_RPS_SYSFS_ATTR(_name, 0644, _name##_show, _name##_store, \
+ _name##_dev_show, _name##_dev_store)
/* The below macros generate static structures */
INTEL_GT_RPS_SYSFS_ATTR_RO(act_freq_mhz);
@@ -475,32 +432,31 @@ INTEL_GT_RPS_SYSFS_ATTR_RO(RP1_freq_mhz);
INTEL_GT_RPS_SYSFS_ATTR_RO(RPn_freq_mhz);
INTEL_GT_RPS_SYSFS_ATTR_RW(max_freq_mhz);
INTEL_GT_RPS_SYSFS_ATTR_RW(min_freq_mhz);
-
-static DEVICE_ATTR_RO(vlv_rpe_freq_mhz);
-
-#define GEN6_ATTR(s) { \
- &dev_attr_##s##_act_freq_mhz.attr, \
- &dev_attr_##s##_cur_freq_mhz.attr, \
- &dev_attr_##s##_boost_freq_mhz.attr, \
- &dev_attr_##s##_max_freq_mhz.attr, \
- &dev_attr_##s##_min_freq_mhz.attr, \
- &dev_attr_##s##_RP0_freq_mhz.attr, \
- &dev_attr_##s##_RP1_freq_mhz.attr, \
- &dev_attr_##s##_RPn_freq_mhz.attr, \
+INTEL_GT_RPS_SYSFS_ATTR_RO(vlv_rpe_freq_mhz);
+
+#define GEN6_ATTR(p, s) { \
+ &p##attr_##s##_act_freq_mhz.attr, \
+ &p##attr_##s##_cur_freq_mhz.attr, \
+ &p##attr_##s##_boost_freq_mhz.attr, \
+ &p##attr_##s##_max_freq_mhz.attr, \
+ &p##attr_##s##_min_freq_mhz.attr, \
+ &p##attr_##s##_RP0_freq_mhz.attr, \
+ &p##attr_##s##_RP1_freq_mhz.attr, \
+ &p##attr_##s##_RPn_freq_mhz.attr, \
NULL, \
}
-#define GEN6_RPS_ATTR GEN6_ATTR(rps)
-#define GEN6_GT_ATTR GEN6_ATTR(gt)
+#define GEN6_RPS_ATTR GEN6_ATTR(, rps)
+#define GEN6_GT_ATTR GEN6_ATTR(dev_, gt)
static const struct attribute * const gen6_rps_attrs[] = GEN6_RPS_ATTR;
static const struct attribute * const gen6_gt_attrs[] = GEN6_GT_ATTR;
-static ssize_t punit_req_freq_mhz_show(struct device *dev,
- struct device_attribute *attr,
+static ssize_t punit_req_freq_mhz_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
char *buff)
{
- struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+ struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
u32 preq = intel_rps_read_punit_req_frequency(&gt->rps);
return sysfs_emit(buff, "%u\n", preq);
@@ -508,20 +464,20 @@ static ssize_t punit_req_freq_mhz_show(struct device *dev,
struct intel_gt_bool_throttle_attr {
struct attribute attr;
- ssize_t (*show)(struct device *dev, struct device_attribute *attr,
+ ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,
char *buf);
- i915_reg_t reg32;
+ i915_reg_t (*reg32)(struct intel_gt *gt);
u32 mask;
};
-static ssize_t throttle_reason_bool_show(struct device *dev,
- struct device_attribute *attr,
+static ssize_t throttle_reason_bool_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
char *buff)
{
- struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+ struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
struct intel_gt_bool_throttle_attr *t_attr =
(struct intel_gt_bool_throttle_attr *) attr;
- bool val = rps_read_mask_mmio(&gt->rps, t_attr->reg32, t_attr->mask);
+ bool val = rps_read_mask_mmio(&gt->rps, t_attr->reg32(gt), t_attr->mask);
return sysfs_emit(buff, "%u\n", val);
}
@@ -530,11 +486,11 @@ static ssize_t throttle_reason_bool_show(struct device *dev,
struct intel_gt_bool_throttle_attr attr_##sysfs_func__ = { \
.attr = { .name = __stringify(sysfs_func__), .mode = 0444 }, \
.show = throttle_reason_bool_show, \
- .reg32 = GT0_PERF_LIMIT_REASONS, \
+ .reg32 = intel_gt_perf_limit_reasons_reg, \
.mask = mask__, \
}
-static DEVICE_ATTR_RO(punit_req_freq_mhz);
+INTEL_GT_ATTR_RO(punit_req_freq_mhz);
static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_status, GT0_PERF_LIMIT_REASONS_MASK);
static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_pl1, POWER_LIMIT_1_MASK);
static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_pl2, POWER_LIMIT_2_MASK);
@@ -597,8 +553,8 @@ static const struct attribute *throttle_reason_attrs[] = {
#define U8_8_VAL_MASK 0xffff
#define U8_8_SCALE_TO_VALUE "0.00390625"
-static ssize_t freq_factor_scale_show(struct device *dev,
- struct device_attribute *attr,
+static ssize_t freq_factor_scale_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
char *buff)
{
return sysfs_emit(buff, "%s\n", U8_8_SCALE_TO_VALUE);
@@ -610,11 +566,11 @@ static u32 media_ratio_mode_to_factor(u32 mode)
return !mode ? mode : 256 / mode;
}
-static ssize_t media_freq_factor_show(struct device *dev,
- struct device_attribute *attr,
+static ssize_t media_freq_factor_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
char *buff)
{
- struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+ struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
struct intel_guc_slpc *slpc = &gt->uc.guc.slpc;
intel_wakeref_t wakeref;
u32 mode;
@@ -641,11 +597,11 @@ static ssize_t media_freq_factor_show(struct device *dev,
return sysfs_emit(buff, "%u\n", media_ratio_mode_to_factor(mode));
}
-static ssize_t media_freq_factor_store(struct device *dev,
- struct device_attribute *attr,
+static ssize_t media_freq_factor_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
const char *buff, size_t count)
{
- struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+ struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
struct intel_guc_slpc *slpc = &gt->uc.guc.slpc;
u32 factor, mode;
int err;
@@ -670,11 +626,11 @@ static ssize_t media_freq_factor_store(struct device *dev,
return err ?: count;
}
-static ssize_t media_RP0_freq_mhz_show(struct device *dev,
- struct device_attribute *attr,
+static ssize_t media_RP0_freq_mhz_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
char *buff)
{
- struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+ struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
u32 val;
int err;
@@ -691,11 +647,11 @@ static ssize_t media_RP0_freq_mhz_show(struct device *dev,
return sysfs_emit(buff, "%u\n", val);
}
-static ssize_t media_RPn_freq_mhz_show(struct device *dev,
- struct device_attribute *attr,
+static ssize_t media_RPn_freq_mhz_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
char *buff)
{
- struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name);
+ struct intel_gt *gt = intel_gt_sysfs_get_drvdata(kobj, attr->attr.name);
u32 val;
int err;
@@ -712,17 +668,17 @@ static ssize_t media_RPn_freq_mhz_show(struct device *dev,
return sysfs_emit(buff, "%u\n", val);
}
-static DEVICE_ATTR_RW(media_freq_factor);
-static struct device_attribute dev_attr_media_freq_factor_scale =
+INTEL_GT_ATTR_RW(media_freq_factor);
+static struct kobj_attribute attr_media_freq_factor_scale =
__ATTR(media_freq_factor.scale, 0444, freq_factor_scale_show, NULL);
-static DEVICE_ATTR_RO(media_RP0_freq_mhz);
-static DEVICE_ATTR_RO(media_RPn_freq_mhz);
+INTEL_GT_ATTR_RO(media_RP0_freq_mhz);
+INTEL_GT_ATTR_RO(media_RPn_freq_mhz);
static const struct attribute *media_perf_power_attrs[] = {
- &dev_attr_media_freq_factor.attr,
- &dev_attr_media_freq_factor_scale.attr,
- &dev_attr_media_RP0_freq_mhz.attr,
- &dev_attr_media_RPn_freq_mhz.attr,
+ &attr_media_freq_factor.attr,
+ &attr_media_freq_factor_scale.attr,
+ &attr_media_RP0_freq_mhz.attr,
+ &attr_media_RPn_freq_mhz.attr,
NULL
};
@@ -754,20 +710,29 @@ static const struct attribute * const rps_defaults_attrs[] = {
NULL
};
-static int intel_sysfs_rps_init(struct intel_gt *gt, struct kobject *kobj,
- const struct attribute * const *attrs)
+static int intel_sysfs_rps_init(struct intel_gt *gt, struct kobject *kobj)
{
+ const struct attribute * const *attrs;
+ struct attribute *vlv_attr;
int ret;
if (GRAPHICS_VER(gt->i915) < 6)
return 0;
+ if (is_object_gt(kobj)) {
+ attrs = gen6_rps_attrs;
+ vlv_attr = &attr_rps_vlv_rpe_freq_mhz.attr;
+ } else {
+ attrs = gen6_gt_attrs;
+ vlv_attr = &dev_attr_gt_vlv_rpe_freq_mhz.attr;
+ }
+
ret = sysfs_create_files(kobj, attrs);
if (ret)
return ret;
if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915))
- ret = sysfs_create_file(kobj, &dev_attr_vlv_rpe_freq_mhz.attr);
+ ret = sysfs_create_file(kobj, vlv_attr);
return ret;
}
@@ -778,9 +743,7 @@ void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj)
intel_sysfs_rc6_init(gt, kobj);
- ret = is_object_gt(kobj) ?
- intel_sysfs_rps_init(gt, kobj, gen6_rps_attrs) :
- intel_sysfs_rps_init(gt, kobj, gen6_gt_attrs);
+ ret = intel_sysfs_rps_init(gt, kobj);
if (ret)
drm_warn(&gt->i915->drm,
"failed to create gt%u RPS sysfs files (%pe)",
@@ -790,13 +753,13 @@ void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj)
if (!is_object_gt(kobj))
return;
- ret = sysfs_create_file(kobj, &dev_attr_punit_req_freq_mhz.attr);
+ ret = sysfs_create_file(kobj, &attr_punit_req_freq_mhz.attr);
if (ret)
drm_warn(&gt->i915->drm,
"failed to create gt%u punit_req_freq_mhz sysfs (%pe)",
gt->info.id, ERR_PTR(ret));
- if (GRAPHICS_VER(gt->i915) >= 11) {
+ if (i915_mmio_reg_valid(intel_gt_perf_limit_reasons_reg(gt))) {
ret = sysfs_create_files(kobj, throttle_reason_attrs);
if (ret)
drm_warn(&gt->i915->drm,
diff --git a/drivers/gpu/drm/i915/gt/intel_gt_types.h b/drivers/gpu/drm/i915/gt/intel_gt_types.h
index f19c2de77ff6..c1d9cd255e06 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_gt_types.h
@@ -20,6 +20,7 @@
#include "intel_gsc.h"
#include "i915_vma.h"
+#include "i915_perf_types.h"
#include "intel_engine_types.h"
#include "intel_gt_buffer_pool_types.h"
#include "intel_hwconfig.h"
@@ -30,6 +31,7 @@
#include "intel_migrate_types.h"
#include "intel_wakeref.h"
#include "pxp/intel_pxp_types.h"
+#include "intel_wopcm.h"
struct drm_i915_private;
struct i915_ggtt;
@@ -59,6 +61,9 @@ enum intel_steering_type {
L3BANK,
MSLICE,
LNCF,
+ GAM,
+ DSS,
+ OADDRM,
/*
* On some platforms there are multiple types of MCR registers that
@@ -97,6 +102,7 @@ struct intel_gt {
struct intel_uc uc;
struct intel_gsc gsc;
+ struct intel_wopcm wopcm;
struct {
/* Serialize global tlb invalidations */
@@ -141,20 +147,6 @@ struct intel_gt {
struct intel_wakeref wakeref;
atomic_t user_wakeref;
- /**
- * Protects access to lmem usefault list.
- * It is required, if we are outside of the runtime suspend path,
- * access to @lmem_userfault_list requires always first grabbing the
- * runtime pm, to ensure we can't race against runtime suspend.
- * Once we have that we also need to grab @lmem_userfault_lock,
- * at which point we have exclusive access.
- * The runtime suspend path is special since it doesn't really hold any locks,
- * but instead has exclusive access by virtue of all other accesses requiring
- * holding the runtime pm wakeref.
- */
- struct mutex lmem_userfault_lock;
- struct list_head lmem_userfault_list;
-
struct list_head closed_vma;
spinlock_t closed_lock; /* guards the list of closed_vma */
@@ -170,9 +162,6 @@ struct intel_gt {
*/
intel_wakeref_t awake;
- /* Manual runtime pm autosuspend delay for user GGTT/lmem mmaps */
- struct intel_wakeref_auto userfault_wakeref;
-
u32 clock_frequency;
u32 clock_period_ns;
@@ -286,6 +275,8 @@ struct intel_gt {
/* sysfs defaults per gt */
struct gt_defaults defaults;
struct kobject *sysfs_defaults;
+
+ struct i915_perf_gt perf;
};
struct intel_gt_definition {
diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.c b/drivers/gpu/drm/i915/gt/intel_gtt.c
index 2eaeba14319e..2ba3983984b9 100644
--- a/drivers/gpu/drm/i915/gt/intel_gtt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gtt.c
@@ -12,9 +12,11 @@
#include "gem/i915_gem_internal.h"
#include "gem/i915_gem_lmem.h"
+#include "i915_reg.h"
#include "i915_trace.h"
#include "i915_utils.h"
#include "intel_gt.h"
+#include "intel_gt_mcr.h"
#include "intel_gt_regs.h"
#include "intel_gtt.h"
@@ -269,11 +271,7 @@ void i915_address_space_init(struct i915_address_space *vm, int subclass)
memset64(vm->min_alignment, I915_GTT_MIN_ALIGNMENT,
ARRAY_SIZE(vm->min_alignment));
- if (HAS_64K_PAGES(vm->i915) && NEEDS_COMPACT_PT(vm->i915) &&
- subclass == VM_CLASS_PPGTT) {
- vm->min_alignment[INTEL_MEMORY_LOCAL] = I915_GTT_PAGE_SIZE_2M;
- vm->min_alignment[INTEL_MEMORY_STOLEN_LOCAL] = I915_GTT_PAGE_SIZE_2M;
- } else if (HAS_64K_PAGES(vm->i915)) {
+ if (HAS_64K_PAGES(vm->i915)) {
vm->min_alignment[INTEL_MEMORY_LOCAL] = I915_GTT_PAGE_SIZE_64K;
vm->min_alignment[INTEL_MEMORY_STOLEN_LOCAL] = I915_GTT_PAGE_SIZE_64K;
}
@@ -343,7 +341,8 @@ int setup_scratch_page(struct i915_address_space *vm)
*/
size = I915_GTT_PAGE_SIZE_4K;
if (i915_vm_is_4lvl(vm) &&
- HAS_PAGE_SIZES(vm->i915, I915_GTT_PAGE_SIZE_64K))
+ HAS_PAGE_SIZES(vm->i915, I915_GTT_PAGE_SIZE_64K) &&
+ !HAS_64K_PAGES(vm->i915))
size = I915_GTT_PAGE_SIZE_64K;
do {
@@ -385,18 +384,6 @@ skip:
if (size == I915_GTT_PAGE_SIZE_4K)
return -ENOMEM;
- /*
- * If we need 64K minimum GTT pages for device local-memory,
- * like on XEHPSDV, then we need to fail the allocation here,
- * otherwise we can't safely support the insertion of
- * local-memory pages for this vm, since the HW expects the
- * correct physical alignment and size when the page-table is
- * operating in 64K GTT mode, which includes any scratch PTEs,
- * since userspace can still touch them.
- */
- if (HAS_64K_PAGES(vm->i915))
- return -ENOMEM;
-
size = I915_GTT_PAGE_SIZE_4K;
} while (1);
}
@@ -493,6 +480,18 @@ static void tgl_setup_private_ppat(struct intel_uncore *uncore)
intel_uncore_write(uncore, GEN12_PAT_INDEX(7), GEN8_PPAT_WB);
}
+static void xehp_setup_private_ppat(struct intel_gt *gt)
+{
+ intel_gt_mcr_multicast_write(gt, XEHP_PAT_INDEX(0), GEN8_PPAT_WB);
+ intel_gt_mcr_multicast_write(gt, XEHP_PAT_INDEX(1), GEN8_PPAT_WC);
+ intel_gt_mcr_multicast_write(gt, XEHP_PAT_INDEX(2), GEN8_PPAT_WT);
+ intel_gt_mcr_multicast_write(gt, XEHP_PAT_INDEX(3), GEN8_PPAT_UC);
+ intel_gt_mcr_multicast_write(gt, XEHP_PAT_INDEX(4), GEN8_PPAT_WB);
+ intel_gt_mcr_multicast_write(gt, XEHP_PAT_INDEX(5), GEN8_PPAT_WB);
+ intel_gt_mcr_multicast_write(gt, XEHP_PAT_INDEX(6), GEN8_PPAT_WB);
+ intel_gt_mcr_multicast_write(gt, XEHP_PAT_INDEX(7), GEN8_PPAT_WB);
+}
+
static void icl_setup_private_ppat(struct intel_uncore *uncore)
{
intel_uncore_write(uncore,
@@ -585,13 +584,16 @@ static void chv_setup_private_ppat(struct intel_uncore *uncore)
intel_uncore_write(uncore, GEN8_PRIVATE_PAT_HI, upper_32_bits(pat));
}
-void setup_private_pat(struct intel_uncore *uncore)
+void setup_private_pat(struct intel_gt *gt)
{
- struct drm_i915_private *i915 = uncore->i915;
+ struct intel_uncore *uncore = gt->uncore;
+ struct drm_i915_private *i915 = gt->i915;
GEM_BUG_ON(GRAPHICS_VER(i915) < 8);
- if (GRAPHICS_VER(i915) >= 12)
+ 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);
else if (GRAPHICS_VER(i915) >= 11)
icl_setup_private_ppat(uncore);
diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.h b/drivers/gpu/drm/i915/gt/intel_gtt.h
index c0ca53cba9f0..4d75ba4bb41d 100644
--- a/drivers/gpu/drm/i915/gt/intel_gtt.h
+++ b/drivers/gpu/drm/i915/gt/intel_gtt.h
@@ -93,6 +93,7 @@ typedef u64 gen8_pte_t;
#define GEN12_GGTT_PTE_LM BIT_ULL(1)
#define GEN12_PDE_64K BIT(6)
+#define GEN12_PTE_PS64 BIT(8)
/*
* Cacheability Control is a 4-bit value. The low three bits are stored in bits
@@ -667,7 +668,7 @@ void ppgtt_unbind_vma(struct i915_address_space *vm,
void gtt_write_workarounds(struct intel_gt *gt);
-void setup_private_pat(struct intel_uncore *uncore);
+void setup_private_pat(struct intel_gt *gt);
int i915_vm_alloc_pt_stash(struct i915_address_space *vm,
struct i915_vm_pt_stash *stash,
diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
index 3955292483a6..7771a19008c6 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -20,6 +20,30 @@
#include "intel_ring.h"
#include "shmem_utils.h"
+/*
+ * The per-platform tables are u8-encoded in @data. Decode @data and set the
+ * addresses' offset and commands in @regs. The following encoding is used
+ * for each byte. There are 2 steps: decoding commands and decoding addresses.
+ *
+ * Commands:
+ * [7]: create NOPs - number of NOPs are set in lower bits
+ * [6]: When creating MI_LOAD_REGISTER_IMM command, allow to set
+ * MI_LRI_FORCE_POSTED
+ * [5:0]: Number of NOPs or registers to set values to in case of
+ * MI_LOAD_REGISTER_IMM
+ *
+ * Addresses: these are decoded after a MI_LOAD_REGISTER_IMM command by "count"
+ * number of registers. They are set by using the REG/REG16 macros: the former
+ * is used for offsets smaller than 0x200 while the latter is for values bigger
+ * than that. Those macros already set all the bits documented below correctly:
+ *
+ * [7]: When a register offset needs more than 6 bits, use additional bytes, to
+ * follow, for the lower bits
+ * [6:0]: Register offset, without considering the engine base.
+ *
+ * This function only tweaks the commands and register offsets. Values are not
+ * filled out.
+ */
static void set_offsets(u32 *regs,
const u8 *data,
const struct intel_engine_cs *engine,
@@ -264,6 +288,39 @@ static const u8 dg2_xcs_offsets[] = {
END
};
+static const u8 mtl_xcs_offsets[] = {
+ NOP(1),
+ LRI(13, POSTED),
+ REG16(0x244),
+ REG(0x034),
+ REG(0x030),
+ REG(0x038),
+ REG(0x03c),
+ REG(0x168),
+ REG(0x140),
+ REG(0x110),
+ REG(0x1c0),
+ REG(0x1c4),
+ REG(0x1c8),
+ REG(0x180),
+ REG16(0x2b4),
+ NOP(4),
+
+ NOP(1),
+ LRI(9, POSTED),
+ REG16(0x3a8),
+ REG16(0x28c),
+ REG16(0x288),
+ REG16(0x284),
+ REG16(0x280),
+ REG16(0x27c),
+ REG16(0x278),
+ REG16(0x274),
+ REG16(0x270),
+
+ END
+};
+
static const u8 gen8_rcs_offsets[] = {
NOP(1),
LRI(14, POSTED),
@@ -606,6 +663,49 @@ static const u8 dg2_rcs_offsets[] = {
END
};
+static const u8 mtl_rcs_offsets[] = {
+ NOP(1),
+ LRI(15, POSTED),
+ REG16(0x244),
+ REG(0x034),
+ REG(0x030),
+ REG(0x038),
+ REG(0x03c),
+ REG(0x168),
+ REG(0x140),
+ REG(0x110),
+ REG(0x1c0),
+ REG(0x1c4),
+ REG(0x1c8),
+ REG(0x180),
+ REG16(0x2b4),
+ REG(0x120),
+ REG(0x124),
+
+ NOP(1),
+ LRI(9, POSTED),
+ REG16(0x3a8),
+ REG16(0x28c),
+ REG16(0x288),
+ REG16(0x284),
+ REG16(0x280),
+ REG16(0x27c),
+ REG16(0x278),
+ REG16(0x274),
+ REG16(0x270),
+
+ NOP(2),
+ LRI(2, POSTED),
+ REG16(0x5a8),
+ REG16(0x5ac),
+
+ NOP(6),
+ LRI(1, 0),
+ REG(0x0c8),
+
+ END
+};
+
#undef END
#undef REG16
#undef REG
@@ -624,7 +724,9 @@ static const u8 *reg_offsets(const struct intel_engine_cs *engine)
!intel_engine_has_relative_mmio(engine));
if (engine->flags & I915_ENGINE_HAS_RCS_REG_STATE) {
- if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55))
+ if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 70))
+ return mtl_rcs_offsets;
+ else if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55))
return dg2_rcs_offsets;
else if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50))
return xehp_rcs_offsets;
@@ -637,7 +739,9 @@ static const u8 *reg_offsets(const struct intel_engine_cs *engine)
else
return gen8_rcs_offsets;
} else {
- if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55))
+ if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 70))
+ return mtl_xcs_offsets;
+ else if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 55))
return dg2_xcs_offsets;
else if (GRAPHICS_VER(engine->i915) >= 12)
return gen12_xcs_offsets;
@@ -745,19 +849,18 @@ static int lrc_ring_cmd_buf_cctl(const struct intel_engine_cs *engine)
static u32
lrc_ring_indirect_offset_default(const struct intel_engine_cs *engine)
{
- switch (GRAPHICS_VER(engine->i915)) {
- default:
- MISSING_CASE(GRAPHICS_VER(engine->i915));
- fallthrough;
- case 12:
+ if (GRAPHICS_VER(engine->i915) >= 12)
return GEN12_CTX_RCS_INDIRECT_CTX_OFFSET_DEFAULT;
- case 11:
+ else if (GRAPHICS_VER(engine->i915) >= 11)
return GEN11_CTX_RCS_INDIRECT_CTX_OFFSET_DEFAULT;
- case 9:
+ else if (GRAPHICS_VER(engine->i915) >= 9)
return GEN9_CTX_RCS_INDIRECT_CTX_OFFSET_DEFAULT;
- case 8:
+ else if (GRAPHICS_VER(engine->i915) >= 8)
return GEN8_CTX_RCS_INDIRECT_CTX_OFFSET_DEFAULT;
- }
+
+ GEM_BUG_ON(GRAPHICS_VER(engine->i915) < 8);
+
+ return 0;
}
static void
@@ -1012,7 +1115,7 @@ __lrc_alloc_state(struct intel_context *ce, struct intel_engine_cs *engine)
if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
context_size += I915_GTT_PAGE_SIZE; /* for redzone */
- if (GRAPHICS_VER(engine->i915) == 12) {
+ if (GRAPHICS_VER(engine->i915) >= 12) {
ce->wa_bb_page = context_size / PAGE_SIZE;
context_size += PAGE_SIZE;
}
@@ -1718,24 +1821,16 @@ void lrc_init_wa_ctx(struct intel_engine_cs *engine)
unsigned int i;
int err;
- if (!(engine->flags & I915_ENGINE_HAS_RCS_REG_STATE))
+ if (GRAPHICS_VER(engine->i915) >= 11 ||
+ !(engine->flags & I915_ENGINE_HAS_RCS_REG_STATE))
return;
- switch (GRAPHICS_VER(engine->i915)) {
- case 12:
- case 11:
- return;
- case 9:
+ if (GRAPHICS_VER(engine->i915) == 9) {
wa_bb_fn[0] = gen9_init_indirectctx_bb;
wa_bb_fn[1] = NULL;
- break;
- case 8:
+ } else if (GRAPHICS_VER(engine->i915) == 8) {
wa_bb_fn[0] = gen8_init_indirectctx_bb;
wa_bb_fn[1] = NULL;
- break;
- default:
- MISSING_CASE(GRAPHICS_VER(engine->i915));
- return;
}
err = lrc_create_wa_ctx(engine);
diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.h b/drivers/gpu/drm/i915/gt/intel_lrc.h
index a390f0813c8b..7111bae759f3 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.h
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.h
@@ -110,6 +110,8 @@ enum {
#define XEHP_SW_CTX_ID_WIDTH 16
#define XEHP_SW_COUNTER_SHIFT 58
#define XEHP_SW_COUNTER_WIDTH 6
+#define GEN12_GUC_SW_CTX_ID_SHIFT 39
+#define GEN12_GUC_SW_CTX_ID_WIDTH 16
static inline void lrc_runtime_start(struct intel_context *ce)
{
diff --git a/drivers/gpu/drm/i915/gt/intel_migrate.c b/drivers/gpu/drm/i915/gt/intel_migrate.c
index aaaf1906026c..b405a04135ca 100644
--- a/drivers/gpu/drm/i915/gt/intel_migrate.c
+++ b/drivers/gpu/drm/i915/gt/intel_migrate.c
@@ -10,6 +10,7 @@
#include "intel_gtt.h"
#include "intel_migrate.h"
#include "intel_ring.h"
+#include "gem/i915_gem_lmem.h"
struct insert_pte_data {
u64 offset;
diff --git a/drivers/gpu/drm/i915/gt/intel_mocs.c b/drivers/gpu/drm/i915/gt/intel_mocs.c
index 152244d7f62a..49fdd509527a 100644
--- a/drivers/gpu/drm/i915/gt/intel_mocs.c
+++ b/drivers/gpu/drm/i915/gt/intel_mocs.c
@@ -7,6 +7,7 @@
#include "intel_engine.h"
#include "intel_gt.h"
+#include "intel_gt_mcr.h"
#include "intel_gt_regs.h"
#include "intel_mocs.h"
#include "intel_ring.h"
@@ -609,14 +610,17 @@ static u32 l3cc_combine(u16 low, u16 high)
0; \
i++)
-static void init_l3cc_table(struct intel_uncore *uncore,
+static void init_l3cc_table(struct intel_gt *gt,
const struct drm_i915_mocs_table *table)
{
unsigned int i;
u32 l3cc;
for_each_l3cc(l3cc, table, i)
- intel_uncore_write_fw(uncore, GEN9_LNCFCMOCS(i), l3cc);
+ if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 50))
+ intel_gt_mcr_multicast_write_fw(gt, XEHP_LNCFCMOCS(i), l3cc);
+ else
+ intel_uncore_write_fw(gt->uncore, GEN9_LNCFCMOCS(i), l3cc);
}
void intel_mocs_init_engine(struct intel_engine_cs *engine)
@@ -636,7 +640,7 @@ void intel_mocs_init_engine(struct intel_engine_cs *engine)
init_mocs_table(engine, &table);
if (flags & HAS_RENDER_L3CC && engine->class == RENDER_CLASS)
- init_l3cc_table(engine->uncore, &table);
+ init_l3cc_table(engine->gt, &table);
}
static u32 global_mocs_offset(void)
@@ -672,7 +676,7 @@ void intel_mocs_init(struct intel_gt *gt)
* memory transactions including guc transactions
*/
if (flags & HAS_RENDER_L3CC)
- init_l3cc_table(gt->uncore, &table);
+ init_l3cc_table(gt, &table);
}
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c
index f8d0523f4c18..2ee4051e4d96 100644
--- a/drivers/gpu/drm/i915/gt/intel_rc6.c
+++ b/drivers/gpu/drm/i915/gt/intel_rc6.c
@@ -551,6 +551,23 @@ static void __intel_rc6_disable(struct intel_rc6 *rc6)
intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL);
}
+static void rc6_res_reg_init(struct intel_rc6 *rc6)
+{
+ memset(rc6->res_reg, INVALID_MMIO_REG.reg, sizeof(rc6->res_reg));
+
+ switch (rc6_to_gt(rc6)->type) {
+ case GT_MEDIA:
+ rc6->res_reg[INTEL_RC6_RES_RC6] = MTL_MEDIA_MC6;
+ break;
+ default:
+ rc6->res_reg[INTEL_RC6_RES_RC6_LOCKED] = GEN6_GT_GFX_RC6_LOCKED;
+ rc6->res_reg[INTEL_RC6_RES_RC6] = GEN6_GT_GFX_RC6;
+ rc6->res_reg[INTEL_RC6_RES_RC6p] = GEN6_GT_GFX_RC6p;
+ rc6->res_reg[INTEL_RC6_RES_RC6pp] = GEN6_GT_GFX_RC6pp;
+ break;
+ }
+}
+
void intel_rc6_init(struct intel_rc6 *rc6)
{
struct drm_i915_private *i915 = rc6_to_i915(rc6);
@@ -562,6 +579,8 @@ void intel_rc6_init(struct intel_rc6 *rc6)
if (!rc6_supported(rc6))
return;
+ rc6_res_reg_init(rc6);
+
if (IS_CHERRYVIEW(i915))
err = chv_rc6_init(rc6);
else if (IS_VALLEYVIEW(i915))
@@ -736,31 +755,19 @@ static u64 vlv_residency_raw(struct intel_uncore *uncore, const i915_reg_t reg)
return lower | (u64)upper << 8;
}
-u64 intel_rc6_residency_ns(struct intel_rc6 *rc6, const i915_reg_t reg)
+u64 intel_rc6_residency_ns(struct intel_rc6 *rc6, enum intel_rc6_res_type id)
{
struct drm_i915_private *i915 = rc6_to_i915(rc6);
struct intel_uncore *uncore = rc6_to_uncore(rc6);
u64 time_hw, prev_hw, overflow_hw;
+ i915_reg_t reg = rc6->res_reg[id];
unsigned int fw_domains;
unsigned long flags;
- unsigned int i;
u32 mul, div;
if (!rc6->supported)
return 0;
- /*
- * Store previous hw counter values for counter wrap-around handling.
- *
- * There are only four interesting registers and they live next to each
- * other so we can use the relative address, compared to the smallest
- * one as the index into driver storage.
- */
- i = (i915_mmio_reg_offset(reg) -
- i915_mmio_reg_offset(GEN6_GT_GFX_RC6_LOCKED)) / sizeof(u32);
- if (drm_WARN_ON_ONCE(&i915->drm, i >= ARRAY_SIZE(rc6->cur_residency)))
- return 0;
-
fw_domains = intel_uncore_forcewake_for_reg(uncore, reg, FW_REG_READ);
spin_lock_irqsave(&uncore->lock, flags);
@@ -789,11 +796,11 @@ u64 intel_rc6_residency_ns(struct intel_rc6 *rc6, const i915_reg_t reg)
/*
* Counter wrap handling.
*
- * But relying on a sufficient frequency of queries otherwise counters
- * can still wrap.
+ * Store previous hw counter values for counter wrap-around handling. But
+ * relying on a sufficient frequency of queries otherwise counters can still wrap.
*/
- prev_hw = rc6->prev_hw_residency[i];
- rc6->prev_hw_residency[i] = time_hw;
+ prev_hw = rc6->prev_hw_residency[id];
+ rc6->prev_hw_residency[id] = time_hw;
/* RC6 delta from last sample. */
if (time_hw >= prev_hw)
@@ -802,8 +809,8 @@ u64 intel_rc6_residency_ns(struct intel_rc6 *rc6, const i915_reg_t reg)
time_hw += overflow_hw - prev_hw;
/* Add delta to RC6 extended raw driver copy. */
- time_hw += rc6->cur_residency[i];
- rc6->cur_residency[i] = time_hw;
+ time_hw += rc6->cur_residency[id];
+ rc6->cur_residency[id] = time_hw;
intel_uncore_forcewake_put__locked(uncore, fw_domains);
spin_unlock_irqrestore(&uncore->lock, flags);
@@ -811,9 +818,22 @@ u64 intel_rc6_residency_ns(struct intel_rc6 *rc6, const i915_reg_t reg)
return mul_u64_u32_div(time_hw, mul, div);
}
-u64 intel_rc6_residency_us(struct intel_rc6 *rc6, i915_reg_t reg)
+u64 intel_rc6_residency_us(struct intel_rc6 *rc6, enum intel_rc6_res_type id)
+{
+ return DIV_ROUND_UP_ULL(intel_rc6_residency_ns(rc6, id), 1000);
+}
+
+void intel_rc6_print_residency(struct seq_file *m, const char *title,
+ enum intel_rc6_res_type id)
{
- return DIV_ROUND_UP_ULL(intel_rc6_residency_ns(rc6, reg), 1000);
+ struct intel_gt *gt = m->private;
+ i915_reg_t reg = gt->rc6.res_reg[id];
+ intel_wakeref_t wakeref;
+
+ with_intel_runtime_pm(gt->uncore->rpm, wakeref)
+ seq_printf(m, "%s %u (%llu us)\n", title,
+ intel_uncore_read(gt->uncore, reg),
+ intel_rc6_residency_us(&gt->rc6, id));
}
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.h b/drivers/gpu/drm/i915/gt/intel_rc6.h
index b6fea71afc22..456fa668a276 100644
--- a/drivers/gpu/drm/i915/gt/intel_rc6.h
+++ b/drivers/gpu/drm/i915/gt/intel_rc6.h
@@ -6,10 +6,11 @@
#ifndef INTEL_RC6_H
#define INTEL_RC6_H
-#include "i915_reg_defs.h"
+#include <linux/types.h>
-struct intel_engine_cs;
+enum intel_rc6_res_type;
struct intel_rc6;
+struct seq_file;
void intel_rc6_init(struct intel_rc6 *rc6);
void intel_rc6_fini(struct intel_rc6 *rc6);
@@ -21,7 +22,9 @@ void intel_rc6_sanitize(struct intel_rc6 *rc6);
void intel_rc6_enable(struct intel_rc6 *rc6);
void intel_rc6_disable(struct intel_rc6 *rc6);
-u64 intel_rc6_residency_ns(struct intel_rc6 *rc6, i915_reg_t reg);
-u64 intel_rc6_residency_us(struct intel_rc6 *rc6, i915_reg_t reg);
+u64 intel_rc6_residency_ns(struct intel_rc6 *rc6, enum intel_rc6_res_type id);
+u64 intel_rc6_residency_us(struct intel_rc6 *rc6, enum intel_rc6_res_type id);
+void intel_rc6_print_residency(struct seq_file *m, const char *title,
+ enum intel_rc6_res_type id);
#endif /* INTEL_RC6_H */
diff --git a/drivers/gpu/drm/i915/gt/intel_rc6_types.h b/drivers/gpu/drm/i915/gt/intel_rc6_types.h
index e747492b2f46..fa23c4dce00b 100644
--- a/drivers/gpu/drm/i915/gt/intel_rc6_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_rc6_types.h
@@ -13,9 +13,20 @@
struct drm_i915_gem_object;
+/* RC6 residency types */
+enum intel_rc6_res_type {
+ INTEL_RC6_RES_RC6_LOCKED,
+ INTEL_RC6_RES_RC6,
+ INTEL_RC6_RES_RC6p,
+ INTEL_RC6_RES_RC6pp,
+ INTEL_RC6_RES_MAX,
+ INTEL_RC6_RES_VLV_MEDIA = INTEL_RC6_RES_RC6p,
+};
+
struct intel_rc6 {
- u64 prev_hw_residency[4];
- u64 cur_residency[4];
+ i915_reg_t res_reg[INTEL_RC6_RES_MAX];
+ u64 prev_hw_residency[INTEL_RC6_RES_MAX];
+ u64 cur_residency[INTEL_RC6_RES_MAX];
u32 ctl_enable;
diff --git a/drivers/gpu/drm/i915/gt/intel_renderstate.c b/drivers/gpu/drm/i915/gt/intel_renderstate.c
index 5121e6dc2fa5..9c1ae070ee7b 100644
--- a/drivers/gpu/drm/i915/gt/intel_renderstate.c
+++ b/drivers/gpu/drm/i915/gt/intel_renderstate.c
@@ -215,9 +215,7 @@ int intel_renderstate_emit(struct intel_renderstate *so,
if (!so->vma)
return 0;
- err = i915_request_await_object(rq, so->vma->obj, false);
- if (err == 0)
- err = i915_vma_move_to_active(so->vma, rq, 0);
+ err = i915_vma_move_to_active(so->vma, rq, 0);
if (err)
return err;
diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c
index b36674356986..24736ebee17c 100644
--- a/drivers/gpu/drm/i915/gt/intel_reset.c
+++ b/drivers/gpu/drm/i915/gt/intel_reset.c
@@ -1278,7 +1278,7 @@ static void intel_gt_reset_global(struct intel_gt *gt,
kobject_uevent_env(kobj, KOBJ_CHANGE, reset_event);
/* Use a watchdog to ensure that our reset completes */
- intel_wedge_on_timeout(&w, gt, 5 * HZ) {
+ intel_wedge_on_timeout(&w, gt, 60 * HZ) {
intel_display_prepare_reset(gt->i915);
intel_gt_reset(gt, engine_mask, reason);
@@ -1407,15 +1407,19 @@ out:
intel_runtime_pm_put(gt->uncore->rpm, wakeref);
}
-int intel_gt_reset_trylock(struct intel_gt *gt, int *srcu)
+static int _intel_gt_reset_lock(struct intel_gt *gt, int *srcu, bool retry)
{
might_lock(&gt->reset.backoff_srcu);
- might_sleep();
+ if (retry)
+ might_sleep();
rcu_read_lock();
while (test_bit(I915_RESET_BACKOFF, &gt->reset.flags)) {
rcu_read_unlock();
+ if (!retry)
+ return -EBUSY;
+
if (wait_event_interruptible(gt->reset.queue,
!test_bit(I915_RESET_BACKOFF,
&gt->reset.flags)))
@@ -1429,6 +1433,16 @@ int intel_gt_reset_trylock(struct intel_gt *gt, int *srcu)
return 0;
}
+int intel_gt_reset_trylock(struct intel_gt *gt, int *srcu)
+{
+ return _intel_gt_reset_lock(gt, srcu, false);
+}
+
+int intel_gt_reset_lock_interruptible(struct intel_gt *gt, int *srcu)
+{
+ return _intel_gt_reset_lock(gt, srcu, true);
+}
+
void intel_gt_reset_unlock(struct intel_gt *gt, int tag)
__releases(&gt->reset.backoff_srcu)
{
diff --git a/drivers/gpu/drm/i915/gt/intel_reset.h b/drivers/gpu/drm/i915/gt/intel_reset.h
index adc734e67387..25c975b6e8fc 100644
--- a/drivers/gpu/drm/i915/gt/intel_reset.h
+++ b/drivers/gpu/drm/i915/gt/intel_reset.h
@@ -39,6 +39,7 @@ int __intel_engine_reset_bh(struct intel_engine_cs *engine,
void __i915_request_reset(struct i915_request *rq, bool guilty);
int __must_check intel_gt_reset_trylock(struct intel_gt *gt, int *srcu);
+int __must_check intel_gt_reset_lock_interruptible(struct intel_gt *gt, int *srcu);
void intel_gt_reset_unlock(struct intel_gt *gt, int tag);
void intel_gt_set_wedged(struct intel_gt *gt);
diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c
index d5d6f1fadcae..356c787e11d3 100644
--- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c
+++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c
@@ -12,7 +12,9 @@
#include "gen6_ppgtt.h"
#include "gen7_renderclear.h"
#include "i915_drv.h"
+#include "i915_irq.h"
#include "i915_mitigations.h"
+#include "i915_reg.h"
#include "intel_breadcrumbs.h"
#include "intel_context.h"
#include "intel_engine_regs.h"
diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c
index 6b86250c31ab..9ad3bc7201cb 100644
--- a/drivers/gpu/drm/i915/gt/intel_rps.c
+++ b/drivers/gpu/drm/i915/gt/intel_rps.c
@@ -430,7 +430,8 @@ static int __gen5_rps_set(struct intel_rps *rps, u8 val)
rgvswctl = intel_uncore_read16(uncore, MEMSWCTL);
if (rgvswctl & MEMCTL_CMD_STS) {
- DRM_DEBUG("gpu busy, RCS change rejected\n");
+ drm_dbg(&rps_to_i915(rps)->drm,
+ "gpu busy, RCS change rejected\n");
return -EBUSY; /* still busy with another command */
}
@@ -625,9 +626,7 @@ static void gen5_rps_disable(struct intel_rps *rps)
rgvswctl = intel_uncore_read16(uncore, MEMSWCTL);
/* Ack interrupts, disable EFC interrupt */
- intel_uncore_write(uncore, MEMINTREN,
- intel_uncore_read(uncore, MEMINTREN) &
- ~MEMINT_EVAL_CHG_EN);
+ intel_uncore_rmw(uncore, MEMINTREN, MEMINT_EVAL_CHG_EN, 0);
intel_uncore_write(uncore, MEMINTRSTS, MEMINT_EVAL_CHG);
/* Go back to the starting frequency */
@@ -1016,9 +1015,15 @@ void intel_rps_boost(struct i915_request *rq)
if (rps_uses_slpc(rps)) {
slpc = rps_to_slpc(rps);
+ if (slpc->min_freq_softlimit >= slpc->boost_freq)
+ return;
+
/* Return if old value is non zero */
- if (!atomic_fetch_inc(&slpc->num_waiters))
+ 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);
+ }
return;
}
@@ -1085,15 +1090,25 @@ static u32 intel_rps_read_state_cap(struct intel_rps *rps)
return intel_uncore_read(uncore, GEN6_RP_STATE_CAP);
}
-/**
- * gen6_rps_get_freq_caps - Get freq caps exposed by HW
- * @rps: the intel_rps structure
- * @caps: returned freq caps
- *
- * Returned "caps" frequencies should be converted to MHz using
- * intel_gpu_freq()
- */
-void gen6_rps_get_freq_caps(struct intel_rps *rps, struct intel_rps_freq_caps *caps)
+static void
+mtl_get_freq_caps(struct intel_rps *rps, struct intel_rps_freq_caps *caps)
+{
+ struct intel_uncore *uncore = rps_to_uncore(rps);
+ u32 rp_state_cap = rps_to_gt(rps)->type == GT_MEDIA ?
+ intel_uncore_read(uncore, MTL_MEDIAP_STATE_CAP) :
+ intel_uncore_read(uncore, MTL_RP_STATE_CAP);
+ u32 rpe = rps_to_gt(rps)->type == GT_MEDIA ?
+ intel_uncore_read(uncore, MTL_MPE_FREQUENCY) :
+ intel_uncore_read(uncore, MTL_GT_RPE_FREQUENCY);
+
+ /* MTL values are in units of 16.67 MHz */
+ caps->rp0_freq = REG_FIELD_GET(MTL_RP0_CAP_MASK, rp_state_cap);
+ caps->min_freq = REG_FIELD_GET(MTL_RPN_CAP_MASK, rp_state_cap);
+ caps->rp1_freq = REG_FIELD_GET(MTL_RPE_MASK, rpe);
+}
+
+static void
+__gen6_rps_get_freq_caps(struct intel_rps *rps, struct intel_rps_freq_caps *caps)
{
struct drm_i915_private *i915 = rps_to_i915(rps);
u32 rp_state_cap;
@@ -1128,6 +1143,24 @@ void gen6_rps_get_freq_caps(struct intel_rps *rps, struct intel_rps_freq_caps *c
}
}
+/**
+ * gen6_rps_get_freq_caps - Get freq caps exposed by HW
+ * @rps: the intel_rps structure
+ * @caps: returned freq caps
+ *
+ * Returned "caps" frequencies should be converted to MHz using
+ * intel_gpu_freq()
+ */
+void gen6_rps_get_freq_caps(struct intel_rps *rps, struct intel_rps_freq_caps *caps)
+{
+ struct drm_i915_private *i915 = rps_to_i915(rps);
+
+ if (IS_METEORLAKE(i915))
+ return mtl_get_freq_caps(rps, caps);
+ else
+ return __gen6_rps_get_freq_caps(rps, caps);
+}
+
static void gen6_rps_init(struct intel_rps *rps)
{
struct drm_i915_private *i915 = rps_to_i915(rps);
@@ -1921,7 +1954,8 @@ void gen6_rps_irq_handler(struct intel_rps *rps, u32 pm_iir)
intel_engine_cs_irq(gt->engine[VECS0], pm_iir >> 10);
if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT)
- DRM_DEBUG("Command parser error, pm_iir 0x%08x\n", pm_iir);
+ drm_dbg(&rps_to_i915(rps)->drm,
+ "Command parser error, pm_iir 0x%08x\n", pm_iir);
}
void gen5_rps_irq_handler(struct intel_rps *rps)
@@ -2040,22 +2074,45 @@ void intel_rps_sanitize(struct intel_rps *rps)
rps_disable_interrupts(rps);
}
+u32 intel_rps_read_rpstat_fw(struct intel_rps *rps)
+{
+ struct drm_i915_private *i915 = rps_to_i915(rps);
+ i915_reg_t rpstat;
+
+ rpstat = (GRAPHICS_VER(i915) >= 12) ? GEN12_RPSTAT1 : GEN6_RPSTAT1;
+
+ return intel_uncore_read_fw(rps_to_gt(rps)->uncore, rpstat);
+}
+
+u32 intel_rps_read_rpstat(struct intel_rps *rps)
+{
+ struct drm_i915_private *i915 = rps_to_i915(rps);
+ i915_reg_t rpstat;
+
+ rpstat = (GRAPHICS_VER(i915) >= 12) ? GEN12_RPSTAT1 : GEN6_RPSTAT1;
+
+ return intel_uncore_read(rps_to_gt(rps)->uncore, rpstat);
+}
+
u32 intel_rps_get_cagf(struct intel_rps *rps, u32 rpstat)
{
struct drm_i915_private *i915 = rps_to_i915(rps);
u32 cagf;
- if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
- cagf = (rpstat >> 8) & 0xff;
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70))
+ cagf = REG_FIELD_GET(MTL_CAGF_MASK, rpstat);
+ else if (GRAPHICS_VER(i915) >= 12)
+ cagf = REG_FIELD_GET(GEN12_CAGF_MASK, rpstat);
+ else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
+ cagf = REG_FIELD_GET(RPE_MASK, rpstat);
else if (GRAPHICS_VER(i915) >= 9)
- cagf = (rpstat & GEN9_CAGF_MASK) >> GEN9_CAGF_SHIFT;
+ cagf = REG_FIELD_GET(GEN9_CAGF_MASK, rpstat);
else if (IS_HASWELL(i915) || IS_BROADWELL(i915))
- cagf = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT;
+ cagf = REG_FIELD_GET(HSW_CAGF_MASK, rpstat);
else if (GRAPHICS_VER(i915) >= 6)
- cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT;
+ cagf = REG_FIELD_GET(GEN6_CAGF_MASK, rpstat);
else
- cagf = gen5_invert_freq(rps, (rpstat & MEMSTAT_PSTATE_MASK) >>
- MEMSTAT_PSTATE_SHIFT);
+ cagf = gen5_invert_freq(rps, REG_FIELD_GET(MEMSTAT_PSTATE_MASK, rpstat));
return cagf;
}
@@ -2066,7 +2123,15 @@ static u32 read_cagf(struct intel_rps *rps)
struct intel_uncore *uncore = rps_to_uncore(rps);
u32 freq;
- if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
+ /*
+ * For Gen12+ reading freq from HW does not need a forcewake and
+ * registers will return 0 freq when GT is in RC6
+ */
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70)) {
+ freq = intel_uncore_read(uncore, MTL_MIRROR_TARGET_WP1);
+ } else if (GRAPHICS_VER(i915) >= 12) {
+ freq = intel_uncore_read(uncore, GEN12_RPSTAT1);
+ } else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) {
vlv_punit_get(i915);
freq = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS);
vlv_punit_put(i915);
@@ -2191,6 +2256,213 @@ u32 intel_rps_get_rpn_frequency(struct intel_rps *rps)
return intel_gpu_freq(rps, rps->min_freq);
}
+static void rps_frequency_dump(struct intel_rps *rps, struct drm_printer *p)
+{
+ struct intel_gt *gt = rps_to_gt(rps);
+ struct drm_i915_private *i915 = gt->i915;
+ struct intel_uncore *uncore = gt->uncore;
+ struct intel_rps_freq_caps caps;
+ u32 rp_state_limits;
+ u32 gt_perf_status;
+ u32 rpmodectl, rpinclimit, rpdeclimit;
+ u32 rpstat, cagf, reqf;
+ u32 rpcurupei, rpcurup, rpprevup;
+ u32 rpcurdownei, rpcurdown, rpprevdown;
+ u32 rpupei, rpupt, rpdownei, rpdownt;
+ u32 pm_ier, pm_imr, pm_isr, pm_iir, pm_mask;
+
+ rp_state_limits = intel_uncore_read(uncore, GEN6_RP_STATE_LIMITS);
+ gen6_rps_get_freq_caps(rps, &caps);
+ if (IS_GEN9_LP(i915))
+ gt_perf_status = intel_uncore_read(uncore, BXT_GT_PERF_STATUS);
+ else
+ gt_perf_status = intel_uncore_read(uncore, GEN6_GT_PERF_STATUS);
+
+ /* RPSTAT1 is in the GT power well */
+ intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);
+
+ reqf = intel_uncore_read(uncore, GEN6_RPNSWREQ);
+ if (GRAPHICS_VER(i915) >= 9) {
+ reqf >>= 23;
+ } else {
+ reqf &= ~GEN6_TURBO_DISABLE;
+ if (IS_HASWELL(i915) || IS_BROADWELL(i915))
+ reqf >>= 24;
+ else
+ reqf >>= 25;
+ }
+ reqf = intel_gpu_freq(rps, reqf);
+
+ rpmodectl = intel_uncore_read(uncore, GEN6_RP_CONTROL);
+ rpinclimit = intel_uncore_read(uncore, GEN6_RP_UP_THRESHOLD);
+ rpdeclimit = intel_uncore_read(uncore, GEN6_RP_DOWN_THRESHOLD);
+
+ rpstat = intel_rps_read_rpstat(rps);
+ rpcurupei = intel_uncore_read(uncore, GEN6_RP_CUR_UP_EI) & GEN6_CURICONT_MASK;
+ rpcurup = intel_uncore_read(uncore, GEN6_RP_CUR_UP) & GEN6_CURBSYTAVG_MASK;
+ rpprevup = intel_uncore_read(uncore, GEN6_RP_PREV_UP) & GEN6_CURBSYTAVG_MASK;
+ rpcurdownei = intel_uncore_read(uncore, GEN6_RP_CUR_DOWN_EI) & GEN6_CURIAVG_MASK;
+ rpcurdown = intel_uncore_read(uncore, GEN6_RP_CUR_DOWN) & GEN6_CURBSYTAVG_MASK;
+ rpprevdown = intel_uncore_read(uncore, GEN6_RP_PREV_DOWN) & GEN6_CURBSYTAVG_MASK;
+
+ rpupei = intel_uncore_read(uncore, GEN6_RP_UP_EI);
+ rpupt = intel_uncore_read(uncore, GEN6_RP_UP_THRESHOLD);
+
+ rpdownei = intel_uncore_read(uncore, GEN6_RP_DOWN_EI);
+ rpdownt = intel_uncore_read(uncore, GEN6_RP_DOWN_THRESHOLD);
+
+ cagf = intel_rps_read_actual_frequency(rps);
+
+ intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL);
+
+ if (GRAPHICS_VER(i915) >= 11) {
+ pm_ier = intel_uncore_read(uncore, GEN11_GPM_WGBOXPERF_INTR_ENABLE);
+ pm_imr = intel_uncore_read(uncore, GEN11_GPM_WGBOXPERF_INTR_MASK);
+ /*
+ * The equivalent to the PM ISR & IIR cannot be read
+ * without affecting the current state of the system
+ */
+ pm_isr = 0;
+ pm_iir = 0;
+ } else if (GRAPHICS_VER(i915) >= 8) {
+ pm_ier = intel_uncore_read(uncore, GEN8_GT_IER(2));
+ pm_imr = intel_uncore_read(uncore, GEN8_GT_IMR(2));
+ pm_isr = intel_uncore_read(uncore, GEN8_GT_ISR(2));
+ pm_iir = intel_uncore_read(uncore, GEN8_GT_IIR(2));
+ } else {
+ pm_ier = intel_uncore_read(uncore, GEN6_PMIER);
+ pm_imr = intel_uncore_read(uncore, GEN6_PMIMR);
+ pm_isr = intel_uncore_read(uncore, GEN6_PMISR);
+ pm_iir = intel_uncore_read(uncore, GEN6_PMIIR);
+ }
+ pm_mask = intel_uncore_read(uncore, GEN6_PMINTRMSK);
+
+ drm_printf(p, "Video Turbo Mode: %s\n",
+ str_yes_no(rpmodectl & GEN6_RP_MEDIA_TURBO));
+ drm_printf(p, "HW control enabled: %s\n",
+ str_yes_no(rpmodectl & GEN6_RP_ENABLE));
+ drm_printf(p, "SW control enabled: %s\n",
+ str_yes_no((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) == GEN6_RP_MEDIA_SW_MODE));
+
+ drm_printf(p, "PM IER=0x%08x IMR=0x%08x, MASK=0x%08x\n",
+ pm_ier, pm_imr, pm_mask);
+ if (GRAPHICS_VER(i915) <= 10)
+ drm_printf(p, "PM ISR=0x%08x IIR=0x%08x\n",
+ pm_isr, pm_iir);
+ drm_printf(p, "pm_intrmsk_mbz: 0x%08x\n",
+ rps->pm_intrmsk_mbz);
+ drm_printf(p, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status);
+ drm_printf(p, "Render p-state ratio: %d\n",
+ (gt_perf_status & (GRAPHICS_VER(i915) >= 9 ? 0x1ff00 : 0xff00)) >> 8);
+ drm_printf(p, "Render p-state VID: %d\n",
+ gt_perf_status & 0xff);
+ drm_printf(p, "Render p-state limit: %d\n",
+ rp_state_limits & 0xff);
+ drm_printf(p, "RPSTAT1: 0x%08x\n", rpstat);
+ drm_printf(p, "RPMODECTL: 0x%08x\n", rpmodectl);
+ drm_printf(p, "RPINCLIMIT: 0x%08x\n", rpinclimit);
+ drm_printf(p, "RPDECLIMIT: 0x%08x\n", rpdeclimit);
+ drm_printf(p, "RPNSWREQ: %dMHz\n", reqf);
+ drm_printf(p, "CAGF: %dMHz\n", cagf);
+ drm_printf(p, "RP CUR UP EI: %d (%lldns)\n",
+ rpcurupei,
+ intel_gt_pm_interval_to_ns(gt, rpcurupei));
+ drm_printf(p, "RP CUR UP: %d (%lldns)\n",
+ rpcurup, intel_gt_pm_interval_to_ns(gt, rpcurup));
+ drm_printf(p, "RP PREV UP: %d (%lldns)\n",
+ rpprevup, intel_gt_pm_interval_to_ns(gt, rpprevup));
+ drm_printf(p, "Up threshold: %d%%\n",
+ rps->power.up_threshold);
+ drm_printf(p, "RP UP EI: %d (%lldns)\n",
+ rpupei, intel_gt_pm_interval_to_ns(gt, rpupei));
+ drm_printf(p, "RP UP THRESHOLD: %d (%lldns)\n",
+ rpupt, intel_gt_pm_interval_to_ns(gt, rpupt));
+
+ drm_printf(p, "RP CUR DOWN EI: %d (%lldns)\n",
+ rpcurdownei,
+ intel_gt_pm_interval_to_ns(gt, rpcurdownei));
+ drm_printf(p, "RP CUR DOWN: %d (%lldns)\n",
+ rpcurdown,
+ intel_gt_pm_interval_to_ns(gt, rpcurdown));
+ drm_printf(p, "RP PREV DOWN: %d (%lldns)\n",
+ rpprevdown,
+ intel_gt_pm_interval_to_ns(gt, rpprevdown));
+ drm_printf(p, "Down threshold: %d%%\n",
+ rps->power.down_threshold);
+ drm_printf(p, "RP DOWN EI: %d (%lldns)\n",
+ rpdownei, intel_gt_pm_interval_to_ns(gt, rpdownei));
+ drm_printf(p, "RP DOWN THRESHOLD: %d (%lldns)\n",
+ rpdownt, intel_gt_pm_interval_to_ns(gt, rpdownt));
+
+ drm_printf(p, "Lowest (RPN) frequency: %dMHz\n",
+ intel_gpu_freq(rps, caps.min_freq));
+ drm_printf(p, "Nominal (RP1) frequency: %dMHz\n",
+ intel_gpu_freq(rps, caps.rp1_freq));
+ drm_printf(p, "Max non-overclocked (RP0) frequency: %dMHz\n",
+ intel_gpu_freq(rps, caps.rp0_freq));
+ drm_printf(p, "Max overclocked frequency: %dMHz\n",
+ intel_gpu_freq(rps, rps->max_freq));
+
+ drm_printf(p, "Current freq: %d MHz\n",
+ intel_gpu_freq(rps, rps->cur_freq));
+ drm_printf(p, "Actual freq: %d MHz\n", cagf);
+ drm_printf(p, "Idle freq: %d MHz\n",
+ intel_gpu_freq(rps, rps->idle_freq));
+ drm_printf(p, "Min freq: %d MHz\n",
+ intel_gpu_freq(rps, rps->min_freq));
+ drm_printf(p, "Boost freq: %d MHz\n",
+ intel_gpu_freq(rps, rps->boost_freq));
+ drm_printf(p, "Max freq: %d MHz\n",
+ intel_gpu_freq(rps, rps->max_freq));
+ drm_printf(p,
+ "efficient (RPe) frequency: %d MHz\n",
+ intel_gpu_freq(rps, rps->efficient_freq));
+}
+
+static void slpc_frequency_dump(struct intel_rps *rps, struct drm_printer *p)
+{
+ struct intel_gt *gt = rps_to_gt(rps);
+ struct intel_uncore *uncore = gt->uncore;
+ struct intel_rps_freq_caps caps;
+ u32 pm_mask;
+
+ gen6_rps_get_freq_caps(rps, &caps);
+ pm_mask = intel_uncore_read(uncore, GEN6_PMINTRMSK);
+
+ drm_printf(p, "PM MASK=0x%08x\n", pm_mask);
+ drm_printf(p, "pm_intrmsk_mbz: 0x%08x\n",
+ rps->pm_intrmsk_mbz);
+ drm_printf(p, "RPSTAT1: 0x%08x\n", intel_rps_read_rpstat(rps));
+ drm_printf(p, "RPNSWREQ: %dMHz\n", intel_rps_get_requested_frequency(rps));
+ drm_printf(p, "Lowest (RPN) frequency: %dMHz\n",
+ intel_gpu_freq(rps, caps.min_freq));
+ drm_printf(p, "Nominal (RP1) frequency: %dMHz\n",
+ intel_gpu_freq(rps, caps.rp1_freq));
+ drm_printf(p, "Max non-overclocked (RP0) frequency: %dMHz\n",
+ intel_gpu_freq(rps, caps.rp0_freq));
+ drm_printf(p, "Current freq: %d MHz\n",
+ intel_rps_get_requested_frequency(rps));
+ drm_printf(p, "Actual freq: %d MHz\n",
+ intel_rps_read_actual_frequency(rps));
+ drm_printf(p, "Min freq: %d MHz\n",
+ intel_rps_get_min_frequency(rps));
+ drm_printf(p, "Boost freq: %d MHz\n",
+ intel_rps_get_boost_frequency(rps));
+ drm_printf(p, "Max freq: %d MHz\n",
+ intel_rps_get_max_frequency(rps));
+ drm_printf(p,
+ "efficient (RPe) frequency: %d MHz\n",
+ intel_gpu_freq(rps, caps.rp1_freq));
+}
+
+void gen6_rps_frequency_dump(struct intel_rps *rps, struct drm_printer *p)
+{
+ if (rps_uses_slpc(rps))
+ return slpc_frequency_dump(rps, p);
+ else
+ return rps_frequency_dump(rps, p);
+}
+
static int set_max_freq(struct intel_rps *rps, u32 val)
{
struct drm_i915_private *i915 = rps_to_i915(rps);
diff --git a/drivers/gpu/drm/i915/gt/intel_rps.h b/drivers/gpu/drm/i915/gt/intel_rps.h
index 4509dfdc52e0..9e1cad9ba0e9 100644
--- a/drivers/gpu/drm/i915/gt/intel_rps.h
+++ b/drivers/gpu/drm/i915/gt/intel_rps.h
@@ -10,6 +10,7 @@
#include "i915_reg_defs.h"
struct i915_request;
+struct drm_printer;
void intel_rps_init_early(struct intel_rps *rps);
void intel_rps_init(struct intel_rps *rps);
@@ -47,6 +48,8 @@ u32 intel_rps_get_rp1_frequency(struct intel_rps *rps);
u32 intel_rps_get_rpn_frequency(struct intel_rps *rps);
u32 intel_rps_read_punit_req(struct intel_rps *rps);
u32 intel_rps_read_punit_req_frequency(struct intel_rps *rps);
+u32 intel_rps_read_rpstat(struct intel_rps *rps);
+u32 intel_rps_read_rpstat_fw(struct intel_rps *rps);
void gen6_rps_get_freq_caps(struct intel_rps *rps, struct intel_rps_freq_caps *caps);
void intel_rps_raise_unslice(struct intel_rps *rps);
void intel_rps_lower_unslice(struct intel_rps *rps);
@@ -54,6 +57,8 @@ void intel_rps_lower_unslice(struct intel_rps *rps);
u32 intel_rps_read_throttle_reason(struct intel_rps *rps);
bool rps_read_mask_mmio(struct intel_rps *rps, i915_reg_t reg32, u32 mask);
+void gen6_rps_frequency_dump(struct intel_rps *rps, struct drm_printer *p);
+
void gen5_rps_irq_handler(struct intel_rps *rps);
void gen6_rps_irq_handler(struct intel_rps *rps, u32 pm_iir);
void gen11_rps_irq_handler(struct intel_rps *rps, u32 pm_iir);
diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c
index 66f21c735d54..6c6198a257ac 100644
--- a/drivers/gpu/drm/i915/gt/intel_sseu.c
+++ b/drivers/gpu/drm/i915/gt/intel_sseu.c
@@ -677,8 +677,8 @@ u32 intel_sseu_make_rpcs(struct intel_gt *gt,
* If i915/perf is active, we want a stable powergating configuration
* on the system. Use the configuration pinned by i915/perf.
*/
- if (i915->perf.exclusive_stream)
- req_sseu = &i915->perf.sseu;
+ if (gt->perf.exclusive_stream)
+ req_sseu = &gt->perf.sseu;
slices = hweight8(req_sseu->slice_mask);
subslices = hweight8(req_sseu->subslice_mask);
diff --git a/drivers/gpu/drm/i915/intel_wopcm.c b/drivers/gpu/drm/i915/gt/intel_wopcm.c
index 322fb9eeb880..7ebbcc191c2d 100644
--- a/drivers/gpu/drm/i915/intel_wopcm.c
+++ b/drivers/gpu/drm/i915/gt/intel_wopcm.c
@@ -64,9 +64,9 @@
#define GEN9_GUC_FW_RESERVED SZ_128K
#define GEN9_GUC_WOPCM_OFFSET (GUC_WOPCM_RESERVED + GEN9_GUC_FW_RESERVED)
-static inline struct drm_i915_private *wopcm_to_i915(struct intel_wopcm *wopcm)
+static inline struct intel_gt *wopcm_to_gt(struct intel_wopcm *wopcm)
{
- return container_of(wopcm, struct drm_i915_private, wopcm);
+ return container_of(wopcm, struct intel_gt, wopcm);
}
/**
@@ -77,7 +77,8 @@ static inline struct drm_i915_private *wopcm_to_i915(struct intel_wopcm *wopcm)
*/
void intel_wopcm_init_early(struct intel_wopcm *wopcm)
{
- struct drm_i915_private *i915 = wopcm_to_i915(wopcm);
+ struct intel_gt *gt = wopcm_to_gt(wopcm);
+ struct drm_i915_private *i915 = gt->i915;
if (!HAS_GT_UC(i915))
return;
@@ -157,10 +158,11 @@ static bool check_hw_restrictions(struct drm_i915_private *i915,
return true;
}
-static bool __check_layout(struct drm_i915_private *i915, u32 wopcm_size,
+static bool __check_layout(struct intel_gt *gt, u32 wopcm_size,
u32 guc_wopcm_base, u32 guc_wopcm_size,
u32 guc_fw_size, u32 huc_fw_size)
{
+ struct drm_i915_private *i915 = gt->i915;
const u32 ctx_rsvd = context_reserved_size(i915);
u32 size;
@@ -181,12 +183,14 @@ static bool __check_layout(struct drm_i915_private *i915, u32 wopcm_size,
return false;
}
- size = huc_fw_size + WOPCM_RESERVED_SIZE;
- if (unlikely(guc_wopcm_base < size)) {
- drm_err(&i915->drm, "WOPCM: no space for %s: %uK < %uK\n",
- intel_uc_fw_type_repr(INTEL_UC_FW_TYPE_HUC),
- guc_wopcm_base / SZ_1K, size / SZ_1K);
- return false;
+ if (intel_uc_supports_huc(&gt->uc)) {
+ size = huc_fw_size + WOPCM_RESERVED_SIZE;
+ if (unlikely(guc_wopcm_base < size)) {
+ drm_err(&i915->drm, "WOPCM: no space for %s: %uK < %uK\n",
+ intel_uc_fw_type_repr(INTEL_UC_FW_TYPE_HUC),
+ guc_wopcm_base / SZ_1K, size / SZ_1K);
+ return false;
+ }
}
return check_hw_restrictions(i915, guc_wopcm_base, guc_wopcm_size,
@@ -228,8 +232,8 @@ static bool __wopcm_regs_writable(struct intel_uncore *uncore)
*/
void intel_wopcm_init(struct intel_wopcm *wopcm)
{
- struct drm_i915_private *i915 = wopcm_to_i915(wopcm);
- struct intel_gt *gt = to_gt(i915);
+ struct intel_gt *gt = wopcm_to_gt(wopcm);
+ struct drm_i915_private *i915 = gt->i915;
u32 guc_fw_size = intel_uc_fw_get_upload_size(&gt->uc.guc.fw);
u32 huc_fw_size = intel_uc_fw_get_upload_size(&gt->uc.huc.fw);
u32 ctx_rsvd = context_reserved_size(i915);
@@ -275,6 +279,19 @@ void intel_wopcm_init(struct intel_wopcm *wopcm)
}
/*
+ * On platforms with a media GT, the WOPCM is partitioned between the
+ * two GTs, so we would have to take that into account when doing the
+ * math below. There is also a new section reserved for the GSC context
+ * that would have to be factored in. However, all platforms with a
+ * media GT also have GuC depriv enabled, so the WOPCM regs are
+ * pre-locked and therefore we don't have to do the math ourselves.
+ */
+ if (unlikely(i915->media_gt)) {
+ drm_err(&i915->drm, "Unlocked WOPCM regs with media GT\n");
+ return;
+ }
+
+ /*
* Aligned value of guc_wopcm_base will determine available WOPCM space
* for HuC firmware and mandatory reserved area.
*/
@@ -295,7 +312,7 @@ void intel_wopcm_init(struct intel_wopcm *wopcm)
guc_wopcm_base / SZ_1K, guc_wopcm_size / SZ_1K);
check:
- if (__check_layout(i915, wopcm_size, guc_wopcm_base, guc_wopcm_size,
+ if (__check_layout(gt, wopcm_size, guc_wopcm_base, guc_wopcm_size,
guc_fw_size, huc_fw_size)) {
wopcm->guc.base = guc_wopcm_base;
wopcm->guc.size = guc_wopcm_size;
diff --git a/drivers/gpu/drm/i915/intel_wopcm.h b/drivers/gpu/drm/i915/gt/intel_wopcm.h
index 17d6aa86008a..17d6aa86008a 100644
--- a/drivers/gpu/drm/i915/intel_wopcm.h
+++ b/drivers/gpu/drm/i915/gt/intel_wopcm.h
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
index a821e3d405db..2afb4f80a954 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
@@ -4,6 +4,7 @@
*/
#include "i915_drv.h"
+#include "i915_reg.h"
#include "intel_context.h"
#include "intel_engine_pm.h"
#include "intel_engine_regs.h"
@@ -17,46 +18,68 @@
/**
* DOC: Hardware workarounds
*
- * This file is intended as a central place to implement most [1]_ of the
- * required workarounds for hardware to work as originally intended. They fall
- * in five basic categories depending on how/when they are applied:
+ * Hardware workarounds are register programming documented to be executed in
+ * the driver that fall outside of the normal programming sequences for a
+ * platform. There are some basic categories of workarounds, depending on
+ * how/when they are applied:
*
- * - Workarounds that touch registers that are saved/restored to/from the HW
- * context image. The list is emitted (via Load Register Immediate commands)
- * everytime a new context is created.
- * - GT workarounds. The list of these WAs is applied whenever these registers
- * revert to default values (on GPU reset, suspend/resume [2]_, etc..).
- * - Display workarounds. The list is applied during display clock-gating
- * initialization.
- * - Workarounds that whitelist a privileged register, so that UMDs can manage
- * them directly. This is just a special case of a MMMIO workaround (as we
- * write the list of these to/be-whitelisted registers to some special HW
- * registers).
- * - Workaround batchbuffers, that get executed automatically by the hardware
- * on every HW context restore.
+ * - Context workarounds: workarounds that touch registers that are
+ * saved/restored to/from the HW context image. The list is emitted (via Load
+ * Register Immediate commands) once when initializing the device and saved in
+ * the default context. That default context is then used on every context
+ * creation to have a "primed golden context", i.e. a context image that
+ * already contains the changes needed to all the registers.
*
- * .. [1] Please notice that there are other WAs that, due to their nature,
- * cannot be applied from a central place. Those are peppered around the rest
- * of the code, as needed.
+ * - Engine workarounds: the list of these WAs is applied whenever the specific
+ * engine is reset. It's also possible that a set of engine classes share a
+ * common power domain and they are reset together. This happens on some
+ * platforms with render and compute engines. In this case (at least) one of
+ * them need to keeep the workaround programming: the approach taken in the
+ * driver is to tie those workarounds to the first compute/render engine that
+ * is registered. When executing with GuC submission, engine resets are
+ * outside of kernel driver control, hence the list of registers involved in
+ * written once, on engine initialization, and then passed to GuC, that
+ * saves/restores their values before/after the reset takes place. See
+ * ``drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c`` for reference.
*
- * .. [2] Technically, some registers are powercontext saved & restored, so they
- * survive a suspend/resume. In practice, writing them again is not too
- * costly and simplifies things. We can revisit this in the future.
+ * - GT workarounds: the list of these WAs is applied whenever these registers
+ * revert to their default values: on GPU reset, suspend/resume [1]_, etc.
+ *
+ * - Register whitelist: some workarounds need to be implemented in userspace,
+ * but need to touch privileged registers. The whitelist in the kernel
+ * instructs the hardware to allow the access to happen. From the kernel side,
+ * this is just a special case of a MMIO workaround (as we write the list of
+ * these to/be-whitelisted registers to some special HW registers).
+ *
+ * - Workaround batchbuffers: buffers that get executed automatically by the
+ * hardware on every HW context restore. These buffers are created and
+ * programmed in the default context so the hardware always go through those
+ * programming sequences when switching contexts. The support for workaround
+ * batchbuffers is enabled these hardware mechanisms:
*
- * Layout
- * ~~~~~~
+ * #. INDIRECT_CTX: A batchbuffer and an offset are provided in the default
+ * context, pointing the hardware to jump to that location when that offset
+ * is reached in the context restore. Workaround batchbuffer in the driver
+ * currently uses this mechanism for all platforms.
*
- * Keep things in this file ordered by WA type, as per the above (context, GT,
- * display, register whitelist, batchbuffer). Then, inside each type, keep the
- * following order:
+ * #. BB_PER_CTX_PTR: A batchbuffer is provided in the default context,
+ * pointing the hardware to a buffer to continue executing after the
+ * engine registers are restored in a context restore sequence. This is
+ * currently not used in the driver.
*
- * - Infrastructure functions and macros
- * - WAs per platform in standard gen/chrono order
- * - Public functions to init or apply the given workaround type.
+ * - Other: There are WAs that, due to their nature, cannot be applied from a
+ * central place. Those are peppered around the rest of the code, as needed.
+ * Workarounds related to the display IP are the main example.
+ *
+ * .. [1] Technically, some registers are powercontext saved & restored, so they
+ * survive a suspend/resume. In practice, writing them again is not too
+ * costly and simplifies things, so it's the approach taken in the driver.
*/
-static void wa_init_start(struct i915_wa_list *wal, const char *name, const char *engine_name)
+static void wa_init_start(struct i915_wa_list *wal, struct intel_gt *gt,
+ const char *name, const char *engine_name)
{
+ wal->gt = gt;
wal->name = name;
wal->engine_name = engine_name;
}
@@ -80,13 +103,14 @@ static void wa_init_finish(struct i915_wa_list *wal)
if (!wal->count)
return;
- DRM_DEBUG_DRIVER("Initialized %u %s workarounds on %s\n",
- wal->wa_count, wal->name, wal->engine_name);
+ drm_dbg(&wal->gt->i915->drm, "Initialized %u %s workarounds on %s\n",
+ wal->wa_count, wal->name, wal->engine_name);
}
static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa)
{
unsigned int addr = i915_mmio_reg_offset(wa->reg);
+ struct drm_i915_private *i915 = wal->gt->i915;
unsigned int start = 0, end = wal->count;
const unsigned int grow = WA_LIST_CHUNK;
struct i915_wa *wa_;
@@ -99,7 +123,7 @@ static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa)
list = kmalloc_array(ALIGN(wal->count + 1, grow), sizeof(*wa),
GFP_KERNEL);
if (!list) {
- DRM_ERROR("No space for workaround init!\n");
+ drm_err(&i915->drm, "No space for workaround init!\n");
return;
}
@@ -122,9 +146,10 @@ static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa)
wa_ = &wal->list[mid];
if ((wa->clr | wa_->clr) && !(wa->clr & ~wa_->clr)) {
- DRM_ERROR("Discarding overwritten w/a for reg %04x (clear: %08x, set: %08x)\n",
- i915_mmio_reg_offset(wa_->reg),
- wa_->clr, wa_->set);
+ drm_err(&i915->drm,
+ "Discarding overwritten w/a for reg %04x (clear: %08x, set: %08x)\n",
+ i915_mmio_reg_offset(wa_->reg),
+ wa_->clr, wa_->set);
wa_->set &= ~wa->clr;
}
@@ -166,6 +191,21 @@ static void wa_add(struct i915_wa_list *wal, i915_reg_t reg,
_wa_add(wal, &wa);
}
+static void wa_mcr_add(struct i915_wa_list *wal, i915_mcr_reg_t reg,
+ u32 clear, u32 set, u32 read_mask, bool masked_reg)
+{
+ struct i915_wa wa = {
+ .mcr_reg = reg,
+ .clr = clear,
+ .set = set,
+ .read = read_mask,
+ .masked_reg = masked_reg,
+ .is_mcr = 1,
+ };
+
+ _wa_add(wal, &wa);
+}
+
static void
wa_write_clr_set(struct i915_wa_list *wal, i915_reg_t reg, u32 clear, u32 set)
{
@@ -173,6 +213,12 @@ wa_write_clr_set(struct i915_wa_list *wal, i915_reg_t reg, u32 clear, u32 set)
}
static void
+wa_mcr_write_clr_set(struct i915_wa_list *wal, i915_mcr_reg_t reg, u32 clear, u32 set)
+{
+ wa_mcr_add(wal, reg, clear, set, clear, false);
+}
+
+static void
wa_write(struct i915_wa_list *wal, i915_reg_t reg, u32 set)
{
wa_write_clr_set(wal, reg, ~0, set);
@@ -185,11 +231,23 @@ wa_write_or(struct i915_wa_list *wal, i915_reg_t reg, u32 set)
}
static void
+wa_mcr_write_or(struct i915_wa_list *wal, i915_mcr_reg_t reg, u32 set)
+{
+ wa_mcr_write_clr_set(wal, reg, set, set);
+}
+
+static void
wa_write_clr(struct i915_wa_list *wal, i915_reg_t reg, u32 clr)
{
wa_write_clr_set(wal, reg, clr, 0);
}
+static void
+wa_mcr_write_clr(struct i915_wa_list *wal, i915_mcr_reg_t reg, u32 clr)
+{
+ wa_mcr_write_clr_set(wal, reg, clr, 0);
+}
+
/*
* WA operations on "masked register". A masked register has the upper 16 bits
* documented as "masked" in b-spec. Its purpose is to allow writing to just a
@@ -208,18 +266,37 @@ wa_masked_en(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
}
static void
+wa_mcr_masked_en(struct i915_wa_list *wal, i915_mcr_reg_t reg, u32 val)
+{
+ wa_mcr_add(wal, reg, 0, _MASKED_BIT_ENABLE(val), val, true);
+}
+
+static void
wa_masked_dis(struct i915_wa_list *wal, i915_reg_t reg, u32 val)
{
wa_add(wal, reg, 0, _MASKED_BIT_DISABLE(val), val, true);
}
static void
+wa_mcr_masked_dis(struct i915_wa_list *wal, i915_mcr_reg_t reg, u32 val)
+{
+ wa_mcr_add(wal, reg, 0, _MASKED_BIT_DISABLE(val), val, true);
+}
+
+static void
wa_masked_field_set(struct i915_wa_list *wal, i915_reg_t reg,
u32 mask, u32 val)
{
wa_add(wal, reg, 0, _MASKED_FIELD(mask, val), mask, true);
}
+static void
+wa_mcr_masked_field_set(struct i915_wa_list *wal, i915_mcr_reg_t reg,
+ u32 mask, u32 val)
+{
+ wa_mcr_add(wal, reg, 0, _MASKED_FIELD(mask, val), mask, true);
+}
+
static void gen6_ctx_workarounds_init(struct intel_engine_cs *engine,
struct i915_wa_list *wal)
{
@@ -241,8 +318,8 @@ static void gen8_ctx_workarounds_init(struct intel_engine_cs *engine,
wa_masked_en(wal, RING_MI_MODE(RENDER_RING_BASE), ASYNC_FLIP_PERF_DISABLE);
/* WaDisablePartialInstShootdown:bdw,chv */
- wa_masked_en(wal, GEN8_ROW_CHICKEN,
- PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
+ wa_mcr_masked_en(wal, GEN8_ROW_CHICKEN,
+ PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
/* Use Force Non-Coherent whenever executing a 3D context. This is a
* workaround for a possible hang in the unlikely event a TLB
@@ -288,18 +365,18 @@ static void bdw_ctx_workarounds_init(struct intel_engine_cs *engine,
gen8_ctx_workarounds_init(engine, wal);
/* WaDisableThreadStallDopClockGating:bdw (pre-production) */
- wa_masked_en(wal, GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
+ wa_mcr_masked_en(wal, GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
/* WaDisableDopClockGating:bdw
*
* Also see the related UCGTCL1 write in bdw_init_clock_gating()
* to disable EUTC clock gating.
*/
- wa_masked_en(wal, GEN7_ROW_CHICKEN2,
- DOP_CLOCK_GATING_DISABLE);
+ wa_mcr_masked_en(wal, GEN8_ROW_CHICKEN2,
+ DOP_CLOCK_GATING_DISABLE);
- wa_masked_en(wal, HALF_SLICE_CHICKEN3,
- GEN8_SAMPLER_POWER_BYPASS_DIS);
+ wa_mcr_masked_en(wal, GEN8_HALF_SLICE_CHICKEN3,
+ GEN8_SAMPLER_POWER_BYPASS_DIS);
wa_masked_en(wal, HDC_CHICKEN0,
/* WaForceContextSaveRestoreNonCoherent:bdw */
@@ -314,7 +391,7 @@ static void chv_ctx_workarounds_init(struct intel_engine_cs *engine,
gen8_ctx_workarounds_init(engine, wal);
/* WaDisableThreadStallDopClockGating:chv */
- wa_masked_en(wal, GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
+ wa_mcr_masked_en(wal, GEN8_ROW_CHICKEN, STALL_DOP_GATING_DISABLE);
/* Improve HiZ throughput on CHV. */
wa_masked_en(wal, HIZ_CHICKEN, CHV_HZ_8X8_MODE_IN_1X);
@@ -333,21 +410,21 @@ static void gen9_ctx_workarounds_init(struct intel_engine_cs *engine,
*/
wa_masked_en(wal, COMMON_SLICE_CHICKEN2,
GEN9_PBE_COMPRESSED_HASH_SELECTION);
- wa_masked_en(wal, GEN9_HALF_SLICE_CHICKEN7,
- GEN9_SAMPLER_HASH_COMPRESSED_READ_ADDR);
+ wa_mcr_masked_en(wal, GEN9_HALF_SLICE_CHICKEN7,
+ GEN9_SAMPLER_HASH_COMPRESSED_READ_ADDR);
}
/* WaClearFlowControlGpgpuContextSave:skl,bxt,kbl,glk,cfl */
/* WaDisablePartialInstShootdown:skl,bxt,kbl,glk,cfl */
- wa_masked_en(wal, GEN8_ROW_CHICKEN,
- FLOW_CONTROL_ENABLE |
- PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
+ wa_mcr_masked_en(wal, GEN8_ROW_CHICKEN,
+ FLOW_CONTROL_ENABLE |
+ PARTIAL_INSTRUCTION_SHOOTDOWN_DISABLE);
/* WaEnableYV12BugFixInHalfSliceChicken7:skl,bxt,kbl,glk,cfl */
/* WaEnableSamplerGPGPUPreemptionSupport:skl,bxt,kbl,cfl */
- wa_masked_en(wal, GEN9_HALF_SLICE_CHICKEN7,
- GEN9_ENABLE_YV12_BUGFIX |
- GEN9_ENABLE_GPGPU_PREEMPTION);
+ wa_mcr_masked_en(wal, GEN9_HALF_SLICE_CHICKEN7,
+ GEN9_ENABLE_YV12_BUGFIX |
+ GEN9_ENABLE_GPGPU_PREEMPTION);
/* Wa4x4STCOptimizationDisable:skl,bxt,kbl,glk,cfl */
/* WaDisablePartialResolveInVc:skl,bxt,kbl,cfl */
@@ -356,8 +433,8 @@ static void gen9_ctx_workarounds_init(struct intel_engine_cs *engine,
GEN9_PARTIAL_RESOLVE_IN_VC_DISABLE);
/* WaCcsTlbPrefetchDisable:skl,bxt,kbl,glk,cfl */
- wa_masked_dis(wal, GEN9_HALF_SLICE_CHICKEN5,
- GEN9_CCS_TLB_PREFETCH_ENABLE);
+ wa_mcr_masked_dis(wal, GEN9_HALF_SLICE_CHICKEN5,
+ GEN9_CCS_TLB_PREFETCH_ENABLE);
/* WaForceContextSaveRestoreNonCoherent:skl,bxt,kbl,cfl */
wa_masked_en(wal, HDC_CHICKEN0,
@@ -386,11 +463,11 @@ static void gen9_ctx_workarounds_init(struct intel_engine_cs *engine,
IS_KABYLAKE(i915) ||
IS_COFFEELAKE(i915) ||
IS_COMETLAKE(i915))
- wa_masked_en(wal, HALF_SLICE_CHICKEN3,
- GEN8_SAMPLER_POWER_BYPASS_DIS);
+ wa_mcr_masked_en(wal, GEN8_HALF_SLICE_CHICKEN3,
+ GEN8_SAMPLER_POWER_BYPASS_DIS);
/* WaDisableSTUnitPowerOptimization:skl,bxt,kbl,glk,cfl */
- wa_masked_en(wal, HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE);
+ wa_mcr_masked_en(wal, HALF_SLICE_CHICKEN2, GEN8_ST_PO_DISABLE);
/*
* Supporting preemption with fine-granularity requires changes in the
@@ -469,8 +546,8 @@ static void bxt_ctx_workarounds_init(struct intel_engine_cs *engine,
gen9_ctx_workarounds_init(engine, wal);
/* WaDisableThreadStallDopClockGating:bxt */
- wa_masked_en(wal, GEN8_ROW_CHICKEN,
- STALL_DOP_GATING_DISABLE);
+ wa_mcr_masked_en(wal, GEN8_ROW_CHICKEN,
+ STALL_DOP_GATING_DISABLE);
/* WaToEnableHwFixForPushConstHWBug:bxt */
wa_masked_en(wal, COMMON_SLICE_CHICKEN2,
@@ -490,8 +567,8 @@ static void kbl_ctx_workarounds_init(struct intel_engine_cs *engine,
GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
/* WaDisableSbeCacheDispatchPortSharing:kbl */
- wa_masked_en(wal, GEN7_HALF_SLICE_CHICKEN1,
- GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
+ wa_mcr_masked_en(wal, GEN8_HALF_SLICE_CHICKEN1,
+ GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
}
static void glk_ctx_workarounds_init(struct intel_engine_cs *engine,
@@ -514,8 +591,8 @@ static void cfl_ctx_workarounds_init(struct intel_engine_cs *engine,
GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION);
/* WaDisableSbeCacheDispatchPortSharing:cfl */
- wa_masked_en(wal, GEN7_HALF_SLICE_CHICKEN1,
- GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
+ wa_mcr_masked_en(wal, GEN8_HALF_SLICE_CHICKEN1,
+ GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE);
}
static void icl_ctx_workarounds_init(struct intel_engine_cs *engine,
@@ -534,13 +611,13 @@ static void icl_ctx_workarounds_init(struct intel_engine_cs *engine,
* (the register is whitelisted in hardware now, so UMDs can opt in
* for coherency if they have a good reason).
*/
- wa_masked_en(wal, ICL_HDC_MODE, HDC_FORCE_NON_COHERENT);
+ wa_mcr_masked_en(wal, ICL_HDC_MODE, HDC_FORCE_NON_COHERENT);
/* WaEnableFloatBlendOptimization:icl */
- wa_add(wal, GEN10_CACHE_MODE_SS, 0,
- _MASKED_BIT_ENABLE(FLOAT_BLEND_OPTIMIZATION_ENABLE),
- 0 /* write-only, so skip validation */,
- true);
+ wa_mcr_add(wal, GEN10_CACHE_MODE_SS, 0,
+ _MASKED_BIT_ENABLE(FLOAT_BLEND_OPTIMIZATION_ENABLE),
+ 0 /* write-only, so skip validation */,
+ true);
/* WaDisableGPGPUMidThreadPreemption:icl */
wa_masked_field_set(wal, GEN8_CS_CHICKEN1,
@@ -548,8 +625,8 @@ static void icl_ctx_workarounds_init(struct intel_engine_cs *engine,
GEN9_PREEMPT_GPGPU_THREAD_GROUP_LEVEL);
/* allow headerless messages for preemptible GPGPU context */
- wa_masked_en(wal, GEN10_SAMPLER_MODE,
- GEN11_SAMPLER_ENABLE_HEADLESS_MSG);
+ wa_mcr_masked_en(wal, GEN10_SAMPLER_MODE,
+ GEN11_SAMPLER_ENABLE_HEADLESS_MSG);
/* Wa_1604278689:icl,ehl */
wa_write(wal, IVB_FBC_RT_BASE, 0xFFFFFFFF & ~ILK_FBC_RT_VALID);
@@ -558,7 +635,7 @@ static void icl_ctx_workarounds_init(struct intel_engine_cs *engine,
0xFFFFFFFF);
/* Wa_1406306137:icl,ehl */
- wa_masked_en(wal, GEN9_ROW_CHICKEN4, GEN11_DIS_PICK_2ND_EU);
+ wa_mcr_masked_en(wal, GEN9_ROW_CHICKEN4, GEN11_DIS_PICK_2ND_EU);
}
/*
@@ -569,13 +646,13 @@ static void dg2_ctx_gt_tuning_init(struct intel_engine_cs *engine,
struct i915_wa_list *wal)
{
wa_masked_en(wal, CHICKEN_RASTER_2, TBIMR_FAST_CLIP);
- wa_write_clr_set(wal, GEN11_L3SQCREG5, L3_PWM_TIMER_INIT_VAL_MASK,
- REG_FIELD_PREP(L3_PWM_TIMER_INIT_VAL_MASK, 0x7f));
- wa_add(wal,
- FF_MODE2,
- FF_MODE2_TDS_TIMER_MASK,
- FF_MODE2_TDS_TIMER_128,
- 0, false);
+ wa_mcr_write_clr_set(wal, XEHP_L3SQCREG5, L3_PWM_TIMER_INIT_VAL_MASK,
+ REG_FIELD_PREP(L3_PWM_TIMER_INIT_VAL_MASK, 0x7f));
+ wa_mcr_add(wal,
+ XEHP_FF_MODE2,
+ FF_MODE2_TDS_TIMER_MASK,
+ FF_MODE2_TDS_TIMER_128,
+ 0, false);
}
/*
@@ -599,7 +676,7 @@ static void gen12_ctx_gt_tuning_init(struct intel_engine_cs *engine,
* verification is ignored.
*/
wa_add(wal,
- FF_MODE2,
+ GEN12_FF_MODE2,
FF_MODE2_TDS_TIMER_MASK,
FF_MODE2_TDS_TIMER_128,
0, false);
@@ -608,6 +685,8 @@ static void gen12_ctx_gt_tuning_init(struct intel_engine_cs *engine,
static void gen12_ctx_workarounds_init(struct intel_engine_cs *engine,
struct i915_wa_list *wal)
{
+ struct drm_i915_private *i915 = engine->i915;
+
gen12_ctx_gt_tuning_init(engine, wal);
/*
@@ -637,10 +716,14 @@ static void gen12_ctx_workarounds_init(struct intel_engine_cs *engine,
* to Wa_1608008084.
*/
wa_add(wal,
- FF_MODE2,
+ GEN12_FF_MODE2,
FF_MODE2_GS_TIMER_MASK,
FF_MODE2_GS_TIMER_224,
0, false);
+
+ if (!IS_DG1(i915))
+ /* Wa_1806527549 */
+ wa_masked_en(wal, HIZ_CHICKEN, HZ_DEPTH_TEST_LE_GE_OPT_DISABLE);
}
static void dg1_ctx_workarounds_init(struct intel_engine_cs *engine,
@@ -664,27 +747,27 @@ static void dg2_ctx_workarounds_init(struct intel_engine_cs *engine,
/* Wa_16011186671:dg2_g11 */
if (IS_DG2_GRAPHICS_STEP(engine->i915, G11, STEP_A0, STEP_B0)) {
- wa_masked_dis(wal, VFLSKPD, DIS_MULT_MISS_RD_SQUASH);
- wa_masked_en(wal, VFLSKPD, DIS_OVER_FETCH_CACHE);
+ wa_mcr_masked_dis(wal, VFLSKPD, DIS_MULT_MISS_RD_SQUASH);
+ wa_mcr_masked_en(wal, VFLSKPD, DIS_OVER_FETCH_CACHE);
}
if (IS_DG2_GRAPHICS_STEP(engine->i915, G10, STEP_A0, STEP_B0)) {
/* Wa_14010469329:dg2_g10 */
- wa_masked_en(wal, GEN11_COMMON_SLICE_CHICKEN3,
- XEHP_DUAL_SIMD8_SEQ_MERGE_DISABLE);
+ wa_mcr_masked_en(wal, XEHP_COMMON_SLICE_CHICKEN3,
+ XEHP_DUAL_SIMD8_SEQ_MERGE_DISABLE);
/*
* Wa_22010465075:dg2_g10
* Wa_22010613112:dg2_g10
* Wa_14010698770:dg2_g10
*/
- wa_masked_en(wal, GEN11_COMMON_SLICE_CHICKEN3,
- GEN12_DISABLE_CPS_AWARE_COLOR_PIPE);
+ wa_mcr_masked_en(wal, XEHP_COMMON_SLICE_CHICKEN3,
+ GEN12_DISABLE_CPS_AWARE_COLOR_PIPE);
}
/* Wa_16013271637:dg2 */
- wa_masked_en(wal, SLICE_COMMON_ECO_CHICKEN1,
- MSC_MSAA_REODER_BUF_BYPASS_DISABLE);
+ wa_mcr_masked_en(wal, XEHP_SLICE_COMMON_ECO_CHICKEN1,
+ MSC_MSAA_REODER_BUF_BYPASS_DISABLE);
/* Wa_14014947963:dg2 */
if (IS_DG2_GRAPHICS_STEP(engine->i915, G10, STEP_B0, STEP_FOREVER) ||
@@ -768,7 +851,7 @@ __intel_engine_init_ctx_wa(struct intel_engine_cs *engine,
{
struct drm_i915_private *i915 = engine->i915;
- wa_init_start(wal, name, engine->name);
+ wa_init_start(wal, engine->gt, name, engine->name);
/* Applies to all engines */
/*
@@ -1076,18 +1159,23 @@ static void __set_mcr_steering(struct i915_wa_list *wal,
wa_write_clr_set(wal, steering_reg, mcr_mask, mcr);
}
-static void __add_mcr_wa(struct intel_gt *gt, struct i915_wa_list *wal,
- unsigned int slice, unsigned int subslice)
+static void debug_dump_steering(struct intel_gt *gt)
{
struct drm_printer p = drm_debug_printer("MCR Steering:");
+ if (drm_debug_enabled(DRM_UT_DRIVER))
+ intel_gt_mcr_report_steering(&p, gt, false);
+}
+
+static void __add_mcr_wa(struct intel_gt *gt, struct i915_wa_list *wal,
+ unsigned int slice, unsigned int subslice)
+{
__set_mcr_steering(wal, GEN8_MCR_SELECTOR, slice, subslice);
gt->default_steering.groupid = slice;
gt->default_steering.instanceid = subslice;
- if (drm_debug_enabled(DRM_UT_DRIVER))
- intel_gt_mcr_report_steering(&p, gt, false);
+ debug_dump_steering(gt);
}
static void
@@ -1181,6 +1269,9 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
gt->steering_table[MSLICE] = NULL;
}
+ if (IS_XEHPSDV(gt->i915) && slice_mask & BIT(0))
+ gt->steering_table[GAM] = NULL;
+
slice = __ffs(slice_mask);
subslice = intel_sseu_find_first_xehp_dss(sseu, GEN_DSS_PER_GSLICE, slice) %
GEN_DSS_PER_GSLICE;
@@ -1198,6 +1289,13 @@ xehp_init_mcr(struct intel_gt *gt, struct i915_wa_list *wal)
*/
__set_mcr_steering(wal, MCFG_MCR_SELECTOR, 0, 2);
__set_mcr_steering(wal, SF_MCR_SELECTOR, 0, 2);
+
+ /*
+ * On DG2, GAM registers have a dedicated steering control register
+ * and must always be programmed to a hardcoded groupid of "1."
+ */
+ if (IS_DG2(gt->i915))
+ __set_mcr_steering(wal, GAM_MCR_SELECTOR, 1, 0);
}
static void
@@ -1254,22 +1352,22 @@ icl_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
PSDUNIT_CLKGATE_DIS);
/* Wa_1406680159:icl,ehl */
- wa_write_or(wal,
- SUBSLICE_UNIT_LEVEL_CLKGATE,
- GWUNIT_CLKGATE_DIS);
+ wa_mcr_write_or(wal,
+ GEN11_SUBSLICE_UNIT_LEVEL_CLKGATE,
+ GWUNIT_CLKGATE_DIS);
/* Wa_1607087056:icl,ehl,jsl */
if (IS_ICELAKE(i915) ||
IS_JSL_EHL_GRAPHICS_STEP(i915, STEP_A0, STEP_B0))
wa_write_or(wal,
- SLICE_UNIT_LEVEL_CLKGATE,
+ GEN11_SLICE_UNIT_LEVEL_CLKGATE,
L3_CLKGATE_DIS | L3_CR2X_CLKGATE_DIS);
/*
* This is not a documented workaround, but rather an optimization
* to reduce sampler power.
*/
- wa_write_clr(wal, GEN10_DFR_RATIO_EN_AND_CHICKEN, DFR_DISABLE);
+ wa_mcr_write_clr(wal, GEN10_DFR_RATIO_EN_AND_CHICKEN, DFR_DISABLE);
}
/*
@@ -1303,7 +1401,7 @@ gen12_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
wa_14011060649(gt, wal);
/* Wa_14011059788:tgl,rkl,adl-s,dg1,adl-p */
- wa_write_or(wal, GEN10_DFR_RATIO_EN_AND_CHICKEN, DFR_DISABLE);
+ wa_mcr_write_or(wal, GEN10_DFR_RATIO_EN_AND_CHICKEN, DFR_DISABLE);
}
static void
@@ -1315,14 +1413,14 @@ tgl_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
/* Wa_1409420604:tgl */
if (IS_TGL_UY_GRAPHICS_STEP(i915, STEP_A0, STEP_B0))
- wa_write_or(wal,
- SUBSLICE_UNIT_LEVEL_CLKGATE2,
- CPSSUNIT_CLKGATE_DIS);
+ wa_mcr_write_or(wal,
+ SUBSLICE_UNIT_LEVEL_CLKGATE2,
+ CPSSUNIT_CLKGATE_DIS);
/* Wa_1607087056:tgl also know as BUG:1409180338 */
if (IS_TGL_UY_GRAPHICS_STEP(i915, STEP_A0, STEP_B0))
wa_write_or(wal,
- SLICE_UNIT_LEVEL_CLKGATE,
+ GEN11_SLICE_UNIT_LEVEL_CLKGATE,
L3_CLKGATE_DIS | L3_CR2X_CLKGATE_DIS);
/* Wa_1408615072:tgl[a0] */
@@ -1341,14 +1439,14 @@ dg1_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
/* Wa_1607087056:dg1 */
if (IS_DG1_GRAPHICS_STEP(i915, STEP_A0, STEP_B0))
wa_write_or(wal,
- SLICE_UNIT_LEVEL_CLKGATE,
+ GEN11_SLICE_UNIT_LEVEL_CLKGATE,
L3_CLKGATE_DIS | L3_CR2X_CLKGATE_DIS);
/* Wa_1409420604:dg1 */
if (IS_DG1(i915))
- wa_write_or(wal,
- SUBSLICE_UNIT_LEVEL_CLKGATE2,
- CPSSUNIT_CLKGATE_DIS);
+ wa_mcr_write_or(wal,
+ SUBSLICE_UNIT_LEVEL_CLKGATE2,
+ CPSSUNIT_CLKGATE_DIS);
/* Wa_1408615072:dg1 */
/* Empirical testing shows this register is unaffected by engine reset. */
@@ -1365,7 +1463,7 @@ xehpsdv_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
xehp_init_mcr(gt, wal);
/* Wa_1409757795:xehpsdv */
- wa_write_or(wal, SCCGCTL94DC, CG3DDISURB);
+ wa_mcr_write_or(wal, SCCGCTL94DC, CG3DDISURB);
/* Wa_16011155590:xehpsdv */
if (IS_XEHPSDV_GRAPHICS_STEP(i915, STEP_A0, STEP_B0))
@@ -1445,8 +1543,8 @@ dg2_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
CG3DDISCFEG_CLKGATE_DIS);
/* Wa_14011006942:dg2 */
- wa_write_or(wal, SUBSLICE_UNIT_LEVEL_CLKGATE,
- DSS_ROUTER_CLKGATE_DIS);
+ wa_mcr_write_or(wal, GEN11_SUBSLICE_UNIT_LEVEL_CLKGATE,
+ DSS_ROUTER_CLKGATE_DIS);
}
if (IS_DG2_GRAPHICS_STEP(gt->i915, G10, STEP_A0, STEP_B0)) {
@@ -1457,7 +1555,7 @@ dg2_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
wa_write_or(wal, UNSLCGCTL9444, LTCDD_CLKGATE_DIS);
/* Wa_14011371254:dg2_g10 */
- wa_write_or(wal, SLICE_UNIT_LEVEL_CLKGATE, NODEDSS_CLKGATE_DIS);
+ wa_mcr_write_or(wal, XEHP_SLICE_UNIT_LEVEL_CLKGATE, NODEDSS_CLKGATE_DIS);
/* Wa_14011431319:dg2_g10 */
wa_write_or(wal, UNSLCGCTL9440, GAMTLBOACS_CLKGATE_DIS |
@@ -1493,21 +1591,21 @@ dg2_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
GAMEDIA_CLKGATE_DIS);
/* Wa_14011028019:dg2_g10 */
- wa_write_or(wal, SSMCGCTL9530, RTFUNIT_CLKGATE_DIS);
+ wa_mcr_write_or(wal, SSMCGCTL9530, RTFUNIT_CLKGATE_DIS);
}
/* Wa_14014830051:dg2 */
- wa_write_clr(wal, SARB_CHICKEN1, COMP_CKN_IN);
+ wa_mcr_write_clr(wal, SARB_CHICKEN1, COMP_CKN_IN);
/*
* The following are not actually "workarounds" but rather
* recommended tuning settings documented in the bspec's
* performance guide section.
*/
- wa_write_or(wal, GEN12_SQCM, EN_32B_ACCESS);
+ wa_mcr_write_or(wal, XEHP_SQCM, EN_32B_ACCESS);
/* Wa_14015795083 */
- wa_write_clr(wal, GEN7_MISCCPCTL, GEN12_DOP_CLOCK_GATE_RENDER_ENABLE);
+ wa_mcr_write_clr(wal, GEN8_MISCCPCTL, GEN12_DOP_CLOCK_GATE_RENDER_ENABLE);
}
static void
@@ -1516,7 +1614,27 @@ pvc_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
pvc_init_mcr(gt, wal);
/* Wa_14015795083 */
- wa_write_clr(wal, GEN7_MISCCPCTL, GEN12_DOP_CLOCK_GATE_RENDER_ENABLE);
+ wa_mcr_write_clr(wal, GEN8_MISCCPCTL, GEN12_DOP_CLOCK_GATE_RENDER_ENABLE);
+}
+
+static void
+xelpg_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
+{
+ /* FIXME: Actual workarounds will be added in future patch(es) */
+
+ /*
+ * Unlike older platforms, we no longer setup implicit steering here;
+ * all MCR accesses are explicitly steered.
+ */
+ debug_dump_steering(gt);
+}
+
+static void
+xelpmp_gt_workarounds_init(struct intel_gt *gt, struct i915_wa_list *wal)
+{
+ /* FIXME: Actual workarounds will be added in future patch(es) */
+
+ debug_dump_steering(gt);
}
static void
@@ -1524,7 +1642,18 @@ gt_init_workarounds(struct intel_gt *gt, struct i915_wa_list *wal)
{
struct drm_i915_private *i915 = gt->i915;
- if (IS_PONTEVECCHIO(i915))
+ if (gt->type == GT_MEDIA) {
+ if (MEDIA_VER(i915) >= 13)
+ xelpmp_gt_workarounds_init(gt, wal);
+ else
+ MISSING_CASE(MEDIA_VER(i915));
+
+ return;
+ }
+
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70))
+ xelpg_gt_workarounds_init(gt, wal);
+ else if (IS_PONTEVECCHIO(i915))
pvc_gt_workarounds_init(gt, wal);
else if (IS_DG2(i915))
dg2_gt_workarounds_init(gt, wal);
@@ -1572,7 +1701,7 @@ void intel_gt_init_workarounds(struct intel_gt *gt)
{
struct i915_wa_list *wal = &gt->wa_list;
- wa_init_start(wal, "GT", "global");
+ wa_init_start(wal, gt, "GT", "global");
gt_init_workarounds(gt, wal);
wa_init_finish(wal);
}
@@ -1594,12 +1723,14 @@ wal_get_fw_for_rmw(struct intel_uncore *uncore, const struct i915_wa_list *wal)
}
static bool
-wa_verify(const struct i915_wa *wa, u32 cur, const char *name, const char *from)
+wa_verify(struct intel_gt *gt, const struct i915_wa *wa, u32 cur,
+ const char *name, const char *from)
{
if ((cur ^ wa->set) & wa->read) {
- DRM_ERROR("%s workaround lost on %s! (reg[%x]=0x%x, relevant bits were 0x%x vs expected 0x%x)\n",
- name, from, i915_mmio_reg_offset(wa->reg),
- cur, cur & wa->read, wa->set & wa->read);
+ drm_err(&gt->i915->drm,
+ "%s workaround lost on %s! (reg[%x]=0x%x, relevant bits were 0x%x vs expected 0x%x)\n",
+ name, from, i915_mmio_reg_offset(wa->reg),
+ cur, cur & wa->read, wa->set & wa->read);
return false;
}
@@ -1607,9 +1738,9 @@ wa_verify(const struct i915_wa *wa, u32 cur, const char *name, const char *from)
return true;
}
-static void
-wa_list_apply(struct intel_gt *gt, const struct i915_wa_list *wal)
+static void wa_list_apply(const struct i915_wa_list *wal)
{
+ struct intel_gt *gt = wal->gt;
struct intel_uncore *uncore = gt->uncore;
enum forcewake_domains fw;
unsigned long flags;
@@ -1628,14 +1759,25 @@ wa_list_apply(struct intel_gt *gt, const struct i915_wa_list *wal)
u32 val, old = 0;
/* open-coded rmw due to steering */
- old = wa->clr ? intel_gt_mcr_read_any_fw(gt, wa->reg) : 0;
+ if (wa->clr)
+ old = wa->is_mcr ?
+ intel_gt_mcr_read_any_fw(gt, wa->mcr_reg) :
+ intel_uncore_read_fw(uncore, wa->reg);
val = (old & ~wa->clr) | wa->set;
- if (val != old || !wa->clr)
- intel_uncore_write_fw(uncore, wa->reg, val);
+ if (val != old || !wa->clr) {
+ if (wa->is_mcr)
+ intel_gt_mcr_multicast_write_fw(gt, wa->mcr_reg, val);
+ else
+ intel_uncore_write_fw(uncore, wa->reg, val);
+ }
+
+ if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM)) {
+ u32 val = wa->is_mcr ?
+ intel_gt_mcr_read_any_fw(gt, wa->mcr_reg) :
+ intel_uncore_read_fw(uncore, wa->reg);
- if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
- wa_verify(wa, intel_gt_mcr_read_any_fw(gt, wa->reg),
- wal->name, "application");
+ wa_verify(gt, wa, val, wal->name, "application");
+ }
}
intel_uncore_forcewake_put__locked(uncore, fw);
@@ -1644,7 +1786,7 @@ wa_list_apply(struct intel_gt *gt, const struct i915_wa_list *wal)
void intel_gt_apply_workarounds(struct intel_gt *gt)
{
- wa_list_apply(gt, &gt->wa_list);
+ wa_list_apply(&gt->wa_list);
}
static bool wa_list_verify(struct intel_gt *gt,
@@ -1664,8 +1806,9 @@ static bool wa_list_verify(struct intel_gt *gt,
intel_uncore_forcewake_get__locked(uncore, fw);
for (i = 0, wa = wal->list; i < wal->count; i++, wa++)
- ok &= wa_verify(wa,
- intel_gt_mcr_read_any_fw(gt, wa->reg),
+ ok &= wa_verify(wal->gt, wa, wa->is_mcr ?
+ intel_gt_mcr_read_any_fw(gt, wa->mcr_reg) :
+ intel_uncore_read_fw(uncore, wa->reg),
wal->name, from);
intel_uncore_forcewake_put__locked(uncore, fw);
@@ -1712,11 +1855,35 @@ whitelist_reg_ext(struct i915_wa_list *wal, i915_reg_t reg, u32 flags)
}
static void
+whitelist_mcr_reg_ext(struct i915_wa_list *wal, i915_mcr_reg_t reg, u32 flags)
+{
+ struct i915_wa wa = {
+ .mcr_reg = reg,
+ .is_mcr = 1,
+ };
+
+ if (GEM_DEBUG_WARN_ON(wal->count >= RING_MAX_NONPRIV_SLOTS))
+ return;
+
+ if (GEM_DEBUG_WARN_ON(!is_nonpriv_flags_valid(flags)))
+ return;
+
+ wa.mcr_reg.reg |= flags;
+ _wa_add(wal, &wa);
+}
+
+static void
whitelist_reg(struct i915_wa_list *wal, i915_reg_t reg)
{
whitelist_reg_ext(wal, reg, RING_FORCE_TO_NONPRIV_ACCESS_RW);
}
+static void
+whitelist_mcr_reg(struct i915_wa_list *wal, i915_mcr_reg_t reg)
+{
+ whitelist_mcr_reg_ext(wal, reg, RING_FORCE_TO_NONPRIV_ACCESS_RW);
+}
+
static void gen9_whitelist_build(struct i915_wa_list *w)
{
/* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt,glk,cfl */
@@ -1742,7 +1909,7 @@ static void skl_whitelist_build(struct intel_engine_cs *engine)
gen9_whitelist_build(w);
/* WaDisableLSQCROPERFforOCL:skl */
- whitelist_reg(w, GEN8_L3SQCREG4);
+ whitelist_mcr_reg(w, GEN8_L3SQCREG4);
}
static void bxt_whitelist_build(struct intel_engine_cs *engine)
@@ -1763,7 +1930,7 @@ static void kbl_whitelist_build(struct intel_engine_cs *engine)
gen9_whitelist_build(w);
/* WaDisableLSQCROPERFforOCL:kbl */
- whitelist_reg(w, GEN8_L3SQCREG4);
+ whitelist_mcr_reg(w, GEN8_L3SQCREG4);
}
static void glk_whitelist_build(struct intel_engine_cs *engine)
@@ -1828,10 +1995,10 @@ static void icl_whitelist_build(struct intel_engine_cs *engine)
switch (engine->class) {
case RENDER_CLASS:
/* WaAllowUMDToModifyHalfSliceChicken7:icl */
- whitelist_reg(w, GEN9_HALF_SLICE_CHICKEN7);
+ whitelist_mcr_reg(w, GEN9_HALF_SLICE_CHICKEN7);
/* WaAllowUMDToModifySamplerMode:icl */
- whitelist_reg(w, GEN10_SAMPLER_MODE);
+ whitelist_mcr_reg(w, GEN10_SAMPLER_MODE);
/* WaEnableStateCacheRedirectToCS:icl */
whitelist_reg(w, GEN9_SLICE_COMMON_ECO_CHICKEN1);
@@ -1987,7 +2154,7 @@ void intel_engine_init_whitelist(struct intel_engine_cs *engine)
struct drm_i915_private *i915 = engine->i915;
struct i915_wa_list *w = &engine->whitelist;
- wa_init_start(w, "whitelist", engine->name);
+ wa_init_start(w, engine->gt, "whitelist", engine->name);
if (IS_PONTEVECCHIO(i915))
pvc_whitelist_build(engine);
@@ -2107,24 +2274,21 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
if (IS_DG2_GRAPHICS_STEP(i915, G11, STEP_A0, STEP_B0)) {
/* Wa_14013392000:dg2_g11 */
- wa_masked_en(wal, GEN7_ROW_CHICKEN2, GEN12_ENABLE_LARGE_GRF_MODE);
-
- /* Wa_16011620976:dg2_g11 */
- wa_write_or(wal, LSC_CHICKEN_BIT_0_UDW, DIS_CHAIN_2XSIMD8);
+ wa_mcr_masked_en(wal, GEN8_ROW_CHICKEN2, GEN12_ENABLE_LARGE_GRF_MODE);
}
if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_B0, STEP_FOREVER) ||
IS_DG2_G11(i915) || IS_DG2_G12(i915)) {
/* Wa_1509727124:dg2 */
- wa_masked_en(wal, GEN10_SAMPLER_MODE,
- SC_DISABLE_POWER_OPTIMIZATION_EBB);
+ wa_mcr_masked_en(wal, GEN10_SAMPLER_MODE,
+ SC_DISABLE_POWER_OPTIMIZATION_EBB);
}
if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_A0, STEP_B0) ||
IS_DG2_GRAPHICS_STEP(i915, G11, STEP_A0, STEP_B0)) {
/* Wa_14012419201:dg2 */
- wa_masked_en(wal, GEN9_ROW_CHICKEN4,
- GEN12_DISABLE_HDR_PAST_PAYLOAD_HOLD_FIX);
+ wa_mcr_masked_en(wal, GEN9_ROW_CHICKEN4,
+ GEN12_DISABLE_HDR_PAST_PAYLOAD_HOLD_FIX);
}
if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_B0, STEP_C0) ||
@@ -2133,13 +2297,13 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
* Wa_22012826095:dg2
* Wa_22013059131:dg2
*/
- wa_write_clr_set(wal, LSC_CHICKEN_BIT_0_UDW,
- MAXREQS_PER_BANK,
- REG_FIELD_PREP(MAXREQS_PER_BANK, 2));
+ wa_mcr_write_clr_set(wal, LSC_CHICKEN_BIT_0_UDW,
+ MAXREQS_PER_BANK,
+ REG_FIELD_PREP(MAXREQS_PER_BANK, 2));
/* Wa_22013059131:dg2 */
- wa_write_or(wal, LSC_CHICKEN_BIT_0,
- FORCE_1_SUB_MESSAGE_PER_FRAGMENT);
+ wa_mcr_write_or(wal, LSC_CHICKEN_BIT_0,
+ FORCE_1_SUB_MESSAGE_PER_FRAGMENT);
}
/* Wa_1308578152:dg2_g10 when first gslice is fused off */
@@ -2152,19 +2316,19 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_B0, STEP_FOREVER) ||
IS_DG2_G11(i915) || IS_DG2_G12(i915)) {
/* Wa_22013037850:dg2 */
- wa_write_or(wal, LSC_CHICKEN_BIT_0_UDW,
- DISABLE_128B_EVICTION_COMMAND_UDW);
+ wa_mcr_write_or(wal, LSC_CHICKEN_BIT_0_UDW,
+ DISABLE_128B_EVICTION_COMMAND_UDW);
/* Wa_22012856258:dg2 */
- wa_masked_en(wal, GEN7_ROW_CHICKEN2,
- GEN12_DISABLE_READ_SUPPRESSION);
+ wa_mcr_masked_en(wal, GEN8_ROW_CHICKEN2,
+ GEN12_DISABLE_READ_SUPPRESSION);
/*
* Wa_22010960976:dg2
* Wa_14013347512:dg2
*/
- wa_masked_dis(wal, GEN12_HDC_CHICKEN0,
- LSC_L1_FLUSH_CTL_3D_DATAPORT_FLUSH_EVENTS_MASK);
+ wa_mcr_masked_dis(wal, XEHP_HDC_CHICKEN0,
+ LSC_L1_FLUSH_CTL_3D_DATAPORT_FLUSH_EVENTS_MASK);
}
if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_A0, STEP_B0)) {
@@ -2172,8 +2336,8 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
* Wa_1608949956:dg2_g10
* Wa_14010198302:dg2_g10
*/
- wa_masked_en(wal, GEN8_ROW_CHICKEN,
- MDQ_ARBITRATION_MODE | UGM_BACKUP_MODE);
+ wa_mcr_masked_en(wal, GEN8_ROW_CHICKEN,
+ MDQ_ARBITRATION_MODE | UGM_BACKUP_MODE);
/*
* Wa_14010918519:dg2_g10
@@ -2181,31 +2345,31 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
* LSC_CHICKEN_BIT_0 always reads back as 0 is this stepping,
* so ignoring verification.
*/
- wa_add(wal, LSC_CHICKEN_BIT_0_UDW, 0,
- FORCE_SLM_FENCE_SCOPE_TO_TILE | FORCE_UGM_FENCE_SCOPE_TO_TILE,
- 0, false);
+ wa_mcr_add(wal, LSC_CHICKEN_BIT_0_UDW, 0,
+ FORCE_SLM_FENCE_SCOPE_TO_TILE | FORCE_UGM_FENCE_SCOPE_TO_TILE,
+ 0, false);
}
if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_A0, STEP_B0)) {
/* Wa_22010430635:dg2 */
- wa_masked_en(wal,
- GEN9_ROW_CHICKEN4,
- GEN12_DISABLE_GRF_CLEAR);
+ wa_mcr_masked_en(wal,
+ GEN9_ROW_CHICKEN4,
+ GEN12_DISABLE_GRF_CLEAR);
/* Wa_14010648519:dg2 */
- wa_write_or(wal, XEHP_L3NODEARBCFG, XEHP_LNESPARE);
+ wa_mcr_write_or(wal, XEHP_L3NODEARBCFG, XEHP_LNESPARE);
}
/* Wa_14013202645:dg2 */
if (IS_DG2_GRAPHICS_STEP(i915, G10, STEP_B0, STEP_C0) ||
IS_DG2_GRAPHICS_STEP(i915, G11, STEP_A0, STEP_B0))
- wa_write_or(wal, RT_CTRL, DIS_NULL_QUERY);
+ wa_mcr_write_or(wal, RT_CTRL, DIS_NULL_QUERY);
/* Wa_22012532006:dg2 */
if (IS_DG2_GRAPHICS_STEP(engine->i915, G10, STEP_A0, STEP_C0) ||
IS_DG2_GRAPHICS_STEP(engine->i915, G11, STEP_A0, STEP_B0))
- wa_masked_en(wal, GEN9_HALF_SLICE_CHICKEN7,
- DG2_DISABLE_ROUND_ENABLE_ALLOW_FOR_SSLA);
+ wa_mcr_masked_en(wal, GEN9_HALF_SLICE_CHICKEN7,
+ DG2_DISABLE_ROUND_ENABLE_ALLOW_FOR_SSLA);
if (IS_DG2_GRAPHICS_STEP(engine->i915, G10, STEP_A0, STEP_B0)) {
/* Wa_14010680813:dg2_g10 */
@@ -2216,17 +2380,16 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
if (IS_DG2_GRAPHICS_STEP(engine->i915, G10, STEP_A0, STEP_B0) ||
IS_DG2_GRAPHICS_STEP(engine->i915, G11, STEP_A0, STEP_B0)) {
/* Wa_14012362059:dg2 */
- wa_write_or(wal, GEN12_MERT_MOD_CTRL, FORCE_MISS_FTLB);
+ wa_mcr_write_or(wal, XEHP_MERT_MOD_CTRL, FORCE_MISS_FTLB);
}
if (IS_DG2_GRAPHICS_STEP(i915, G11, STEP_B0, STEP_FOREVER) ||
IS_DG2_G10(i915)) {
/* Wa_22014600077:dg2 */
- wa_add(wal, GEN10_CACHE_MODE_SS, 0,
- _MASKED_BIT_ENABLE(ENABLE_EU_COUNT_FOR_TDL_FLUSH),
- 0 /* Wa_14012342262 :write-only reg, so skip
- verification */,
- true);
+ wa_mcr_add(wal, GEN10_CACHE_MODE_SS, 0,
+ _MASKED_BIT_ENABLE(ENABLE_EU_COUNT_FOR_TDL_FLUSH),
+ 0 /* Wa_14012342262 write-only reg, so skip verification */,
+ true);
}
if (IS_DG1_GRAPHICS_STEP(i915, STEP_A0, STEP_B0) ||
@@ -2253,7 +2416,7 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
if (IS_ALDERLAKE_P(i915) || IS_ALDERLAKE_S(i915) || IS_DG1(i915) ||
IS_ROCKETLAKE(i915) || IS_TIGERLAKE(i915)) {
/* Wa_1606931601:tgl,rkl,dg1,adl-s,adl-p */
- wa_masked_en(wal, GEN7_ROW_CHICKEN2, GEN12_DISABLE_EARLY_READ);
+ wa_mcr_masked_en(wal, GEN8_ROW_CHICKEN2, GEN12_DISABLE_EARLY_READ);
/*
* Wa_1407928979:tgl A*
@@ -2282,14 +2445,14 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
IS_DG1_GRAPHICS_STEP(i915, STEP_A0, STEP_B0) ||
IS_ROCKETLAKE(i915) || IS_TIGERLAKE(i915)) {
/* Wa_1409804808:tgl,rkl,dg1[a0],adl-s,adl-p */
- wa_masked_en(wal, GEN7_ROW_CHICKEN2,
- GEN12_PUSH_CONST_DEREF_HOLD_DIS);
+ wa_mcr_masked_en(wal, GEN8_ROW_CHICKEN2,
+ GEN12_PUSH_CONST_DEREF_HOLD_DIS);
/*
* Wa_1409085225:tgl
* Wa_14010229206:tgl,rkl,dg1[a0],adl-s,adl-p
*/
- wa_masked_en(wal, GEN9_ROW_CHICKEN4, GEN12_DISABLE_TDL_PUSH);
+ wa_mcr_masked_en(wal, GEN9_ROW_CHICKEN4, GEN12_DISABLE_TDL_PUSH);
}
if (IS_DG1_GRAPHICS_STEP(i915, STEP_A0, STEP_B0) ||
@@ -2313,9 +2476,9 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
if (IS_DG1(i915) || IS_ROCKETLAKE(i915) || IS_TIGERLAKE(i915) ||
IS_ALDERLAKE_S(i915) || IS_ALDERLAKE_P(i915)) {
/* Wa_1406941453:tgl,rkl,dg1,adl-s,adl-p */
- wa_masked_en(wal,
- GEN10_SAMPLER_MODE,
- ENABLE_SMALLPL);
+ wa_mcr_masked_en(wal,
+ GEN10_SAMPLER_MODE,
+ ENABLE_SMALLPL);
}
if (GRAPHICS_VER(i915) == 11) {
@@ -2349,9 +2512,9 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
* Wa_1405733216:icl
* Formerly known as WaDisableCleanEvicts
*/
- wa_write_or(wal,
- GEN8_L3SQCREG4,
- GEN11_LQSC_CLEAN_EVICT_DISABLE);
+ wa_mcr_write_or(wal,
+ GEN8_L3SQCREG4,
+ GEN11_LQSC_CLEAN_EVICT_DISABLE);
/* Wa_1606682166:icl */
wa_write_or(wal,
@@ -2359,10 +2522,10 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
GEN7_DISABLE_SAMPLER_PREFETCH);
/* Wa_1409178092:icl */
- wa_write_clr_set(wal,
- GEN11_SCRATCH2,
- GEN11_COHERENT_PARTIAL_WRITE_MERGE_ENABLE,
- 0);
+ wa_mcr_write_clr_set(wal,
+ GEN11_SCRATCH2,
+ GEN11_COHERENT_PARTIAL_WRITE_MERGE_ENABLE,
+ 0);
/* WaEnable32PlaneMode:icl */
wa_masked_en(wal, GEN9_CSFE_CHICKEN1_RCS,
@@ -2389,12 +2552,64 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
FF_DOP_CLOCK_GATE_DISABLE);
}
- if (IS_GRAPHICS_VER(i915, 9, 12)) {
- /* FtrPerCtxtPreemptionGranularityControl:skl,bxt,kbl,cfl,cnl,icl,tgl */
+ /*
+ * Intel platforms that support fine-grained preemption (i.e., gen9 and
+ * beyond) allow the kernel-mode driver to choose between two different
+ * options for controlling preemption granularity and behavior.
+ *
+ * Option 1 (hardware default):
+ * Preemption settings are controlled in a global manner via
+ * kernel-only register CS_DEBUG_MODE1 (0x20EC). Any granularity
+ * and settings chosen by the kernel-mode driver will apply to all
+ * userspace clients.
+ *
+ * Option 2:
+ * Preemption settings are controlled on a per-context basis via
+ * register CS_CHICKEN1 (0x2580). CS_CHICKEN1 is saved/restored on
+ * context switch and is writable by userspace (e.g., via
+ * MI_LOAD_REGISTER_IMMEDIATE instructions placed in a batch buffer)
+ * which allows different userspace drivers/clients to select
+ * different settings, or to change those settings on the fly in
+ * response to runtime needs. This option was known by name
+ * "FtrPerCtxtPreemptionGranularityControl" at one time, although
+ * that name is somewhat misleading as other non-granularity
+ * preemption settings are also impacted by this decision.
+ *
+ * On Linux, our policy has always been to let userspace drivers
+ * control preemption granularity/settings (Option 2). This was
+ * originally mandatory on gen9 to prevent ABI breakage (old gen9
+ * userspace developed before object-level preemption was enabled would
+ * not behave well if i915 were to go with Option 1 and enable that
+ * preemption in a global manner). On gen9 each context would have
+ * object-level preemption disabled by default (see
+ * WaDisable3DMidCmdPreemption in gen9_ctx_workarounds_init), but
+ * userspace drivers could opt-in to object-level preemption as they
+ * saw fit. For post-gen9 platforms, we continue to utilize Option 2;
+ * even though it is no longer necessary for ABI compatibility when
+ * enabling a new platform, it does ensure that userspace will be able
+ * to implement any workarounds that show up requiring temporary
+ * adjustments to preemption behavior at runtime.
+ *
+ * Notes/Workarounds:
+ * - Wa_14015141709: On DG2 and early steppings of MTL,
+ * CS_CHICKEN1[0] does not disable object-level preemption as
+ * it is supposed to (nor does CS_DEBUG_MODE1[0] if we had been
+ * using Option 1). Effectively this means userspace is unable
+ * to disable object-level preemption on these platforms/steppings
+ * despite the setting here.
+ *
+ * - Wa_16013994831: May require that userspace program
+ * CS_CHICKEN1[10] when certain runtime conditions are true.
+ * Userspace requires Option 2 to be in effect for their update of
+ * CS_CHICKEN1[10] to be effective.
+ *
+ * Other workarounds may appear in the future that will also require
+ * Option 2 behavior to allow proper userspace implementation.
+ */
+ if (GRAPHICS_VER(i915) >= 9)
wa_masked_en(wal,
GEN7_FF_SLICE_CS_CHICKEN1,
GEN9_FFSC_PERCTX_PREEMPT_CTRL);
- }
if (IS_SKYLAKE(i915) ||
IS_KABYLAKE(i915) ||
@@ -2420,36 +2635,36 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
GEN9_PREEMPT_GPGPU_SYNC_SWITCH_DISABLE);
/* WaEnableLbsSlaRetryTimerDecrement:skl,bxt,kbl,glk,cfl */
- wa_write_or(wal,
- BDW_SCRATCH1,
- GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE);
+ wa_mcr_write_or(wal,
+ BDW_SCRATCH1,
+ GEN9_LBS_SLA_RETRY_TIMER_DECREMENT_ENABLE);
/* WaProgramL3SqcReg1DefaultForPerf:bxt,glk */
if (IS_GEN9_LP(i915))
- wa_write_clr_set(wal,
- GEN8_L3SQCREG1,
- L3_PRIO_CREDITS_MASK,
- L3_GENERAL_PRIO_CREDITS(62) |
- L3_HIGH_PRIO_CREDITS(2));
+ wa_mcr_write_clr_set(wal,
+ GEN8_L3SQCREG1,
+ L3_PRIO_CREDITS_MASK,
+ L3_GENERAL_PRIO_CREDITS(62) |
+ L3_HIGH_PRIO_CREDITS(2));
/* WaOCLCoherentLineFlush:skl,bxt,kbl,cfl */
- wa_write_or(wal,
- GEN8_L3SQCREG4,
- GEN8_LQSC_FLUSH_COHERENT_LINES);
+ wa_mcr_write_or(wal,
+ GEN8_L3SQCREG4,
+ GEN8_LQSC_FLUSH_COHERENT_LINES);
/* Disable atomics in L3 to prevent unrecoverable hangs */
wa_write_clr_set(wal, GEN9_SCRATCH_LNCF1,
GEN9_LNCF_NONIA_COHERENT_ATOMICS_ENABLE, 0);
- wa_write_clr_set(wal, GEN8_L3SQCREG4,
- GEN8_LQSQ_NONIA_COHERENT_ATOMICS_ENABLE, 0);
- wa_write_clr_set(wal, GEN9_SCRATCH1,
- EVICTION_PERF_FIX_ENABLE, 0);
+ wa_mcr_write_clr_set(wal, GEN8_L3SQCREG4,
+ GEN8_LQSQ_NONIA_COHERENT_ATOMICS_ENABLE, 0);
+ wa_mcr_write_clr_set(wal, GEN9_SCRATCH1,
+ EVICTION_PERF_FIX_ENABLE, 0);
}
if (IS_HASWELL(i915)) {
/* WaSampleCChickenBitEnable:hsw */
wa_masked_en(wal,
- HALF_SLICE_CHICKEN3, HSW_SAMPLE_C_PERFORMANCE);
+ HSW_HALF_SLICE_CHICKEN3, HSW_SAMPLE_C_PERFORMANCE);
wa_masked_dis(wal,
CACHE_MODE_0_GEN7,
@@ -2657,7 +2872,7 @@ ccs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
{
if (IS_PVC_CT_STEP(engine->i915, STEP_A0, STEP_C0)) {
/* Wa_14014999345:pvc */
- wa_masked_en(wal, GEN10_CACHE_MODE_SS, DISABLE_ECC);
+ wa_mcr_masked_en(wal, GEN10_CACHE_MODE_SS, DISABLE_ECC);
}
}
@@ -2683,8 +2898,8 @@ add_render_compute_tuning_settings(struct drm_i915_private *i915,
}
if (IS_DG2(i915)) {
- wa_write_or(wal, XEHP_L3SCQREG7, BLEND_FILL_CACHING_OPT_DIS);
- wa_write_clr_set(wal, RT_CTRL, STACKID_CTRL, STACKID_CTRL_512);
+ wa_mcr_write_or(wal, XEHP_L3SCQREG7, BLEND_FILL_CACHING_OPT_DIS);
+ wa_mcr_write_clr_set(wal, RT_CTRL, STACKID_CTRL, STACKID_CTRL_512);
/*
* This is also listed as Wa_22012654132 for certain DG2
@@ -2695,10 +2910,10 @@ add_render_compute_tuning_settings(struct drm_i915_private *i915,
* back for verification on DG2 (due to Wa_14012342262), so
* we need to explicitly skip the readback.
*/
- wa_add(wal, GEN10_CACHE_MODE_SS, 0,
- _MASKED_BIT_ENABLE(ENABLE_PREFETCH_INTO_IC),
- 0 /* write-only, so skip validation */,
- true);
+ wa_mcr_add(wal, GEN10_CACHE_MODE_SS, 0,
+ _MASKED_BIT_ENABLE(ENABLE_PREFETCH_INTO_IC),
+ 0 /* write-only, so skip validation */,
+ true);
}
/*
@@ -2707,8 +2922,8 @@ add_render_compute_tuning_settings(struct drm_i915_private *i915,
* platforms.
*/
if (INTEL_INFO(i915)->tuning_thread_rr_after_dep)
- wa_masked_field_set(wal, GEN9_ROW_CHICKEN4, THREAD_EX_ARB_MODE,
- THREAD_EX_ARB_MODE_RR_AFTER_DEP);
+ wa_mcr_masked_field_set(wal, GEN9_ROW_CHICKEN4, THREAD_EX_ARB_MODE,
+ THREAD_EX_ARB_MODE_RR_AFTER_DEP);
}
/*
@@ -2734,30 +2949,30 @@ general_render_compute_wa_init(struct intel_engine_cs *engine, struct i915_wa_li
if (IS_XEHPSDV(i915)) {
/* Wa_1409954639 */
- wa_masked_en(wal,
- GEN8_ROW_CHICKEN,
- SYSTOLIC_DOP_CLOCK_GATING_DIS);
+ wa_mcr_masked_en(wal,
+ GEN8_ROW_CHICKEN,
+ SYSTOLIC_DOP_CLOCK_GATING_DIS);
/* Wa_1607196519 */
- wa_masked_en(wal,
- GEN9_ROW_CHICKEN4,
- GEN12_DISABLE_GRF_CLEAR);
+ wa_mcr_masked_en(wal,
+ GEN9_ROW_CHICKEN4,
+ GEN12_DISABLE_GRF_CLEAR);
/* Wa_14010670810:xehpsdv */
- wa_write_or(wal, XEHP_L3NODEARBCFG, XEHP_LNESPARE);
+ wa_mcr_write_or(wal, XEHP_L3NODEARBCFG, XEHP_LNESPARE);
/* Wa_14010449647:xehpsdv */
- wa_masked_en(wal, GEN7_HALF_SLICE_CHICKEN1,
- GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE);
+ wa_mcr_masked_en(wal, GEN8_HALF_SLICE_CHICKEN1,
+ GEN7_PSD_SINGLE_PORT_DISPATCH_ENABLE);
/* Wa_18011725039:xehpsdv */
if (IS_XEHPSDV_GRAPHICS_STEP(i915, STEP_A1, STEP_B0)) {
- wa_masked_dis(wal, MLTICTXCTL, TDONRENDER);
- wa_write_or(wal, L3SQCREG1_CCS0, FLUSHALLNONCOH);
+ wa_mcr_masked_dis(wal, MLTICTXCTL, TDONRENDER);
+ wa_mcr_write_or(wal, L3SQCREG1_CCS0, FLUSHALLNONCOH);
}
/* Wa_14012362059:xehpsdv */
- wa_write_or(wal, GEN12_MERT_MOD_CTRL, FORCE_MISS_FTLB);
+ wa_mcr_write_or(wal, XEHP_MERT_MOD_CTRL, FORCE_MISS_FTLB);
/* Wa_14014368820:xehpsdv */
wa_write_or(wal, GEN12_GAMCNTRL_CTRL, INVALIDATION_BROADCAST_MODE_DIS |
@@ -2766,26 +2981,37 @@ general_render_compute_wa_init(struct intel_engine_cs *engine, struct i915_wa_li
if (IS_DG2(i915) || IS_PONTEVECCHIO(i915)) {
/* Wa_14015227452:dg2,pvc */
- wa_masked_en(wal, GEN9_ROW_CHICKEN4, XEHP_DIS_BBL_SYSPIPE);
+ wa_mcr_masked_en(wal, GEN9_ROW_CHICKEN4, XEHP_DIS_BBL_SYSPIPE);
/* Wa_22014226127:dg2,pvc */
- wa_write_or(wal, LSC_CHICKEN_BIT_0, DISABLE_D8_D16_COASLESCE);
+ wa_mcr_write_or(wal, LSC_CHICKEN_BIT_0, DISABLE_D8_D16_COASLESCE);
/* Wa_16015675438:dg2,pvc */
wa_masked_en(wal, FF_SLICE_CS_CHICKEN2, GEN12_PERF_FIX_BALANCING_CFE_DISABLE);
/* Wa_18018781329:dg2,pvc */
- wa_write_or(wal, RENDER_MOD_CTRL, FORCE_MISS_FTLB);
- wa_write_or(wal, COMP_MOD_CTRL, FORCE_MISS_FTLB);
- wa_write_or(wal, VDBX_MOD_CTRL, FORCE_MISS_FTLB);
- wa_write_or(wal, VEBX_MOD_CTRL, FORCE_MISS_FTLB);
+ wa_mcr_write_or(wal, RENDER_MOD_CTRL, FORCE_MISS_FTLB);
+ wa_mcr_write_or(wal, COMP_MOD_CTRL, FORCE_MISS_FTLB);
+ wa_mcr_write_or(wal, VDBX_MOD_CTRL, FORCE_MISS_FTLB);
+ wa_mcr_write_or(wal, VEBX_MOD_CTRL, FORCE_MISS_FTLB);
+ }
+
+ if (IS_DG2(i915)) {
+ /*
+ * Wa_16011620976:dg2_g11
+ * Wa_22015475538:dg2
+ */
+ wa_mcr_write_or(wal, LSC_CHICKEN_BIT_0_UDW, DIS_CHAIN_2XSIMD8);
+
+ /* Wa_18017747507:dg2 */
+ wa_masked_en(wal, VFG_PREEMPTION_CHICKEN, POLYGON_TRIFAN_LINELOOP_DISABLE);
}
}
static void
engine_init_workarounds(struct intel_engine_cs *engine, struct i915_wa_list *wal)
{
- if (I915_SELFTEST_ONLY(GRAPHICS_VER(engine->i915) < 4))
+ if (GRAPHICS_VER(engine->i915) < 4)
return;
engine_fake_wa_init(engine, wal);
@@ -2810,17 +3036,14 @@ void intel_engine_init_workarounds(struct intel_engine_cs *engine)
{
struct i915_wa_list *wal = &engine->wa_list;
- if (GRAPHICS_VER(engine->i915) < 4)
- return;
-
- wa_init_start(wal, "engine", engine->name);
+ wa_init_start(wal, engine->gt, "engine", engine->name);
engine_init_workarounds(engine, wal);
wa_init_finish(wal);
}
void intel_engine_apply_workarounds(struct intel_engine_cs *engine)
{
- wa_list_apply(engine->gt, &engine->wa_list);
+ wa_list_apply(&engine->wa_list);
}
static const struct i915_range mcr_ranges_gen8[] = {
@@ -2964,9 +3187,7 @@ retry:
goto err_vma;
}
- err = i915_request_await_object(rq, vma->obj, true);
- if (err == 0)
- err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
+ err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
if (err == 0)
err = wa_list_srm(rq, wal, vma);
@@ -2994,7 +3215,7 @@ retry:
if (mcr_range(rq->engine->i915, i915_mmio_reg_offset(wa->reg)))
continue;
- if (!wa_verify(wa, results[i], wal->name, from))
+ if (!wa_verify(wal->gt, wa, results[i], wal->name, from))
err = -ENXIO;
}
diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds_types.h b/drivers/gpu/drm/i915/gt/intel_workarounds_types.h
index 8a4b6de4e754..e14188120e66 100644
--- a/drivers/gpu/drm/i915/gt/intel_workarounds_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_workarounds_types.h
@@ -10,15 +10,23 @@
#include "i915_reg_defs.h"
+struct intel_gt;
+
struct i915_wa {
- i915_reg_t reg;
+ union {
+ i915_reg_t reg;
+ i915_mcr_reg_t mcr_reg;
+ };
u32 clr;
u32 set;
u32 read;
- bool masked_reg;
+
+ u32 masked_reg:1;
+ u32 is_mcr:1;
};
struct i915_wa_list {
+ struct intel_gt *gt;
const char *name;
const char *engine_name;
struct i915_wa *list;
diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_cs.c b/drivers/gpu/drm/i915/gt/selftest_engine_cs.c
index 1b75f478d1b8..881b64f3e7b9 100644
--- a/drivers/gpu/drm/i915/gt/selftest_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/selftest_engine_cs.c
@@ -39,6 +39,16 @@ static int perf_end(struct intel_gt *gt)
return igt_flush_test(gt->i915);
}
+static i915_reg_t timestamp_reg(struct intel_engine_cs *engine)
+{
+ struct drm_i915_private *i915 = engine->i915;
+
+ if (GRAPHICS_VER(i915) == 5 || IS_G4X(i915))
+ return RING_TIMESTAMP_UDW(engine->mmio_base);
+ else
+ return RING_TIMESTAMP(engine->mmio_base);
+}
+
static int write_timestamp(struct i915_request *rq, int slot)
{
struct intel_timeline *tl =
@@ -55,7 +65,7 @@ static int write_timestamp(struct i915_request *rq, int slot)
if (GRAPHICS_VER(rq->engine->i915) >= 8)
cmd++;
*cs++ = cmd;
- *cs++ = i915_mmio_reg_offset(RING_TIMESTAMP(rq->engine->mmio_base));
+ *cs++ = i915_mmio_reg_offset(timestamp_reg(rq->engine));
*cs++ = tl->hwsp_offset + slot * sizeof(u32);
*cs++ = 0;
@@ -125,7 +135,7 @@ static int perf_mi_bb_start(void *arg)
enum intel_engine_id id;
int err = 0;
- if (GRAPHICS_VER(gt->i915) < 7) /* for per-engine CS_TIMESTAMP */
+ if (GRAPHICS_VER(gt->i915) < 4) /* Any CS_TIMESTAMP? */
return 0;
perf_begin(gt);
@@ -135,6 +145,9 @@ static int perf_mi_bb_start(void *arg)
u32 cycles[COUNT];
int i;
+ if (GRAPHICS_VER(engine->i915) < 7 && engine->id != RCS0)
+ continue;
+
intel_engine_pm_get(engine);
batch = create_empty_batch(ce);
@@ -249,7 +262,7 @@ static int perf_mi_noop(void *arg)
enum intel_engine_id id;
int err = 0;
- if (GRAPHICS_VER(gt->i915) < 7) /* for per-engine CS_TIMESTAMP */
+ if (GRAPHICS_VER(gt->i915) < 4) /* Any CS_TIMESTAMP? */
return 0;
perf_begin(gt);
@@ -259,6 +272,9 @@ static int perf_mi_noop(void *arg)
u32 cycles[COUNT];
int i;
+ if (GRAPHICS_VER(engine->i915) < 7 && engine->id != RCS0)
+ continue;
+
intel_engine_pm_get(engine);
base = create_empty_batch(ce);
diff --git a/drivers/gpu/drm/i915/gt/selftest_engine_pm.c b/drivers/gpu/drm/i915/gt/selftest_engine_pm.c
index 0dcb3ed44a73..87c94314cf67 100644
--- a/drivers/gpu/drm/i915/gt/selftest_engine_pm.c
+++ b/drivers/gpu/drm/i915/gt/selftest_engine_pm.c
@@ -317,7 +317,7 @@ static int live_engine_busy_stats(void *arg)
ENGINE_TRACE(engine, "measuring busy time\n");
preempt_disable();
de = intel_engine_get_busy_time(engine, &t[0]);
- mdelay(10);
+ mdelay(100);
de = ktime_sub(intel_engine_get_busy_time(engine, &t[1]), de);
preempt_enable();
dt = ktime_sub(t[1], t[0]);
diff --git a/drivers/gpu/drm/i915/gt/selftest_execlists.c b/drivers/gpu/drm/i915/gt/selftest_execlists.c
index 1e08b2473b99..ab2e9a6a2452 100644
--- a/drivers/gpu/drm/i915/gt/selftest_execlists.c
+++ b/drivers/gpu/drm/i915/gt/selftest_execlists.c
@@ -85,8 +85,6 @@ static int wait_for_reset(struct intel_engine_cs *engine,
break;
} while (time_before(jiffies, timeout));
- flush_scheduled_work();
-
if (rq->fence.error != -EIO) {
pr_err("%s: hanging request %llx:%lld not reset\n",
engine->name,
@@ -2766,9 +2764,7 @@ static int create_gang(struct intel_engine_cs *engine,
i915_request_get(rq);
i915_vma_lock(vma);
- err = i915_request_await_object(rq, vma->obj, false);
- if (!err)
- err = i915_vma_move_to_active(vma, rq, 0);
+ err = i915_vma_move_to_active(vma, rq, 0);
if (!err)
err = rq->engine->emit_bb_start(rq,
vma->node.start,
@@ -3182,15 +3178,11 @@ create_gpr_client(struct intel_engine_cs *engine,
}
i915_vma_lock(vma);
- err = i915_request_await_object(rq, vma->obj, false);
- if (!err)
- err = i915_vma_move_to_active(vma, rq, 0);
+ err = i915_vma_move_to_active(vma, rq, 0);
i915_vma_unlock(vma);
i915_vma_lock(batch);
if (!err)
- err = i915_request_await_object(rq, batch->obj, false);
- if (!err)
err = i915_vma_move_to_active(batch, rq, 0);
if (!err)
err = rq->engine->emit_bb_start(rq,
@@ -3475,12 +3467,14 @@ static int random_priority(struct rnd_state *rnd)
struct preempt_smoke {
struct intel_gt *gt;
+ struct kthread_work work;
struct i915_gem_context **contexts;
struct intel_engine_cs *engine;
struct drm_i915_gem_object *batch;
unsigned int ncontext;
struct rnd_state prng;
unsigned long count;
+ int result;
};
static struct i915_gem_context *smoke_context(struct preempt_smoke *smoke)
@@ -3521,9 +3515,7 @@ static int smoke_submit(struct preempt_smoke *smoke,
if (vma) {
i915_vma_lock(vma);
- err = i915_request_await_object(rq, vma->obj, false);
- if (!err)
- err = i915_vma_move_to_active(vma, rq, 0);
+ err = i915_vma_move_to_active(vma, rq, 0);
if (!err)
err = rq->engine->emit_bb_start(rq,
vma->node.start,
@@ -3540,34 +3532,31 @@ unpin:
return err;
}
-static int smoke_crescendo_thread(void *arg)
+static void smoke_crescendo_work(struct kthread_work *work)
{
- struct preempt_smoke *smoke = arg;
+ struct preempt_smoke *smoke = container_of(work, typeof(*smoke), work);
IGT_TIMEOUT(end_time);
unsigned long count;
count = 0;
do {
struct i915_gem_context *ctx = smoke_context(smoke);
- int err;
- err = smoke_submit(smoke,
- ctx, count % I915_PRIORITY_MAX,
- smoke->batch);
- if (err)
- return err;
+ smoke->result = smoke_submit(smoke, ctx,
+ count % I915_PRIORITY_MAX,
+ smoke->batch);
count++;
- } while (count < smoke->ncontext && !__igt_timeout(end_time, NULL));
+ } while (!smoke->result && count < smoke->ncontext &&
+ !__igt_timeout(end_time, NULL));
smoke->count = count;
- return 0;
}
static int smoke_crescendo(struct preempt_smoke *smoke, unsigned int flags)
#define BATCH BIT(0)
{
- struct task_struct *tsk[I915_NUM_ENGINES] = {};
+ struct kthread_worker *worker[I915_NUM_ENGINES] = {};
struct preempt_smoke *arg;
struct intel_engine_cs *engine;
enum intel_engine_id id;
@@ -3578,6 +3567,8 @@ static int smoke_crescendo(struct preempt_smoke *smoke, unsigned int flags)
if (!arg)
return -ENOMEM;
+ memset(arg, 0, I915_NUM_ENGINES * sizeof(*arg));
+
for_each_engine(engine, smoke->gt, id) {
arg[id] = *smoke;
arg[id].engine = engine;
@@ -3585,31 +3576,28 @@ static int smoke_crescendo(struct preempt_smoke *smoke, unsigned int flags)
arg[id].batch = NULL;
arg[id].count = 0;
- tsk[id] = kthread_run(smoke_crescendo_thread, arg,
- "igt/smoke:%d", id);
- if (IS_ERR(tsk[id])) {
- err = PTR_ERR(tsk[id]);
+ worker[id] = kthread_create_worker(0, "igt/smoke:%d", id);
+ if (IS_ERR(worker[id])) {
+ err = PTR_ERR(worker[id]);
break;
}
- get_task_struct(tsk[id]);
- }
- yield(); /* start all threads before we kthread_stop() */
+ kthread_init_work(&arg[id].work, smoke_crescendo_work);
+ kthread_queue_work(worker[id], &arg[id].work);
+ }
count = 0;
for_each_engine(engine, smoke->gt, id) {
- int status;
-
- if (IS_ERR_OR_NULL(tsk[id]))
+ if (IS_ERR_OR_NULL(worker[id]))
continue;
- status = kthread_stop(tsk[id]);
- if (status && !err)
- err = status;
+ kthread_flush_work(&arg[id].work);
+ if (arg[id].result && !err)
+ err = arg[id].result;
count += arg[id].count;
- put_task_struct(tsk[id]);
+ kthread_destroy_worker(worker[id]);
}
pr_info("Submitted %lu crescendo:%x requests across %d engines and %d contexts\n",
diff --git a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c
index be94f863bdef..b46425aeb2f0 100644
--- a/drivers/gpu/drm/i915/gt/selftest_gt_pm.c
+++ b/drivers/gpu/drm/i915/gt/selftest_gt_pm.c
@@ -36,6 +36,19 @@ static int cmp_u32(const void *A, const void *B)
return 0;
}
+static u32 read_timestamp(struct intel_engine_cs *engine)
+{
+ struct drm_i915_private *i915 = engine->i915;
+
+ /* On i965 the first read tends to give a stale value */
+ ENGINE_READ_FW(engine, RING_TIMESTAMP);
+
+ if (GRAPHICS_VER(i915) == 5 || IS_G4X(i915))
+ return ENGINE_READ_FW(engine, RING_TIMESTAMP_UDW);
+ else
+ return ENGINE_READ_FW(engine, RING_TIMESTAMP);
+}
+
static void measure_clocks(struct intel_engine_cs *engine,
u32 *out_cycles, ktime_t *out_dt)
{
@@ -45,13 +58,13 @@ static void measure_clocks(struct intel_engine_cs *engine,
for (i = 0; i < 5; i++) {
local_irq_disable();
- cycles[i] = -ENGINE_READ_FW(engine, RING_TIMESTAMP);
+ cycles[i] = -read_timestamp(engine);
dt[i] = ktime_get();
udelay(1000);
dt[i] = ktime_sub(ktime_get(), dt[i]);
- cycles[i] += ENGINE_READ_FW(engine, RING_TIMESTAMP);
+ cycles[i] += read_timestamp(engine);
local_irq_enable();
}
@@ -78,25 +91,6 @@ static int live_gt_clocks(void *arg)
if (GRAPHICS_VER(gt->i915) < 4) /* Any CS_TIMESTAMP? */
return 0;
- if (GRAPHICS_VER(gt->i915) == 5)
- /*
- * XXX CS_TIMESTAMP low dword is dysfunctional?
- *
- * Ville's experiments indicate the high dword still works,
- * but at a correspondingly reduced frequency.
- */
- return 0;
-
- if (GRAPHICS_VER(gt->i915) == 4)
- /*
- * XXX CS_TIMESTAMP appears gibberish
- *
- * Ville's experiments indicate that it mostly appears 'stuck'
- * in that we see the register report the same cycle count
- * for a couple of reads.
- */
- return 0;
-
intel_gt_pm_get(gt);
intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL);
diff --git a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
index 7f3bb1d34dfb..bc05ef48c194 100644
--- a/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
+++ b/drivers/gpu/drm/i915/gt/selftest_hangcheck.c
@@ -99,22 +99,6 @@ static u64 hws_address(const struct i915_vma *hws,
return hws->node.start + offset_in_page(sizeof(u32)*rq->fence.context);
}
-static int move_to_active(struct i915_vma *vma,
- struct i915_request *rq,
- unsigned int flags)
-{
- int err;
-
- i915_vma_lock(vma);
- err = i915_request_await_object(rq, vma->obj,
- flags & EXEC_OBJECT_WRITE);
- if (err == 0)
- err = i915_vma_move_to_active(vma, rq, flags);
- i915_vma_unlock(vma);
-
- return err;
-}
-
static struct i915_request *
hang_create_request(struct hang *h, struct intel_engine_cs *engine)
{
@@ -175,11 +159,11 @@ hang_create_request(struct hang *h, struct intel_engine_cs *engine)
goto unpin_hws;
}
- err = move_to_active(vma, rq, 0);
+ err = igt_vma_move_to_active_unlocked(vma, rq, 0);
if (err)
goto cancel_rq;
- err = move_to_active(hws, rq, 0);
+ err = igt_vma_move_to_active_unlocked(hws, rq, 0);
if (err)
goto cancel_rq;
@@ -866,10 +850,13 @@ static int igt_reset_active_engine(void *arg)
}
struct active_engine {
- struct task_struct *task;
+ struct kthread_worker *worker;
+ struct kthread_work work;
struct intel_engine_cs *engine;
unsigned long resets;
unsigned int flags;
+ bool stop;
+ int result;
};
#define TEST_ACTIVE BIT(0)
@@ -900,10 +887,10 @@ static int active_request_put(struct i915_request *rq)
return err;
}
-static int active_engine(void *data)
+static void active_engine(struct kthread_work *work)
{
I915_RND_STATE(prng);
- struct active_engine *arg = data;
+ struct active_engine *arg = container_of(work, typeof(*arg), work);
struct intel_engine_cs *engine = arg->engine;
struct i915_request *rq[8] = {};
struct intel_context *ce[ARRAY_SIZE(rq)];
@@ -913,16 +900,17 @@ static int active_engine(void *data)
for (count = 0; count < ARRAY_SIZE(ce); count++) {
ce[count] = intel_context_create(engine);
if (IS_ERR(ce[count])) {
- err = PTR_ERR(ce[count]);
- pr_err("[%s] Create context #%ld failed: %d!\n", engine->name, count, err);
+ arg->result = PTR_ERR(ce[count]);
+ pr_err("[%s] Create context #%ld failed: %d!\n",
+ engine->name, count, arg->result);
while (--count)
intel_context_put(ce[count]);
- return err;
+ return;
}
}
count = 0;
- while (!kthread_should_stop()) {
+ while (!READ_ONCE(arg->stop)) {
unsigned int idx = count++ & (ARRAY_SIZE(rq) - 1);
struct i915_request *old = rq[idx];
struct i915_request *new;
@@ -967,7 +955,7 @@ static int active_engine(void *data)
intel_context_put(ce[count]);
}
- return err;
+ arg->result = err;
}
static int __igt_reset_engines(struct intel_gt *gt,
@@ -1022,7 +1010,7 @@ static int __igt_reset_engines(struct intel_gt *gt,
memset(threads, 0, sizeof(*threads) * I915_NUM_ENGINES);
for_each_engine(other, gt, tmp) {
- struct task_struct *tsk;
+ struct kthread_worker *worker;
threads[tmp].resets =
i915_reset_engine_count(global, other);
@@ -1036,19 +1024,21 @@ static int __igt_reset_engines(struct intel_gt *gt,
threads[tmp].engine = other;
threads[tmp].flags = flags;
- tsk = kthread_run(active_engine, &threads[tmp],
- "igt/%s", other->name);
- if (IS_ERR(tsk)) {
- err = PTR_ERR(tsk);
- pr_err("[%s] Thread spawn failed: %d!\n", engine->name, err);
+ worker = kthread_create_worker(0, "igt/%s",
+ other->name);
+ if (IS_ERR(worker)) {
+ err = PTR_ERR(worker);
+ pr_err("[%s] Worker create failed: %d!\n",
+ engine->name, err);
goto unwind;
}
- threads[tmp].task = tsk;
- get_task_struct(tsk);
- }
+ threads[tmp].worker = worker;
- yield(); /* start all threads before we begin */
+ kthread_init_work(&threads[tmp].work, active_engine);
+ kthread_queue_work(threads[tmp].worker,
+ &threads[tmp].work);
+ }
st_engine_heartbeat_disable_no_pm(engine);
GEM_BUG_ON(test_and_set_bit(I915_RESET_ENGINE + id,
@@ -1197,17 +1187,20 @@ unwind:
for_each_engine(other, gt, tmp) {
int ret;
- if (!threads[tmp].task)
+ if (!threads[tmp].worker)
continue;
- ret = kthread_stop(threads[tmp].task);
+ WRITE_ONCE(threads[tmp].stop, true);
+ kthread_flush_work(&threads[tmp].work);
+ ret = READ_ONCE(threads[tmp].result);
if (ret) {
pr_err("kthread for other engine %s failed, err=%d\n",
other->name, ret);
if (!err)
err = ret;
}
- put_task_struct(threads[tmp].task);
+
+ kthread_destroy_worker(threads[tmp].worker);
/* GuC based resets are not logged per engine */
if (!using_guc) {
@@ -1510,18 +1503,9 @@ static int __igt_reset_evict_vma(struct intel_gt *gt,
}
}
- i915_vma_lock(arg.vma);
- err = i915_request_await_object(rq, arg.vma->obj,
- flags & EXEC_OBJECT_WRITE);
- if (err == 0) {
- err = i915_vma_move_to_active(arg.vma, rq, flags);
- if (err)
- pr_err("[%s] Move to active failed: %d!\n", engine->name, err);
- } else {
- pr_err("[%s] Request await failed: %d!\n", engine->name, err);
- }
-
- i915_vma_unlock(arg.vma);
+ err = igt_vma_move_to_active_unlocked(arg.vma, rq, flags);
+ if (err)
+ pr_err("[%s] Move to active failed: %d!\n", engine->name, err);
if (flags & EXEC_OBJECT_NEEDS_FENCE)
i915_vma_unpin_fence(arg.vma);
diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c
index 82d3f8058995..7c56ffd2c659 100644
--- a/drivers/gpu/drm/i915/gt/selftest_lrc.c
+++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c
@@ -452,9 +452,7 @@ retry:
*cs++ = i915_ggtt_offset(scratch) + RING_TAIL_IDX * sizeof(u32);
*cs++ = 0;
- err = i915_request_await_object(rq, scratch->obj, true);
- if (!err)
- err = i915_vma_move_to_active(scratch, rq, EXEC_OBJECT_WRITE);
+ err = i915_vma_move_to_active(scratch, rq, EXEC_OBJECT_WRITE);
i915_request_get(rq);
i915_request_add(rq);
@@ -602,9 +600,7 @@ __gpr_read(struct intel_context *ce, struct i915_vma *scratch, u32 *slot)
}
i915_vma_lock(scratch);
- err = i915_request_await_object(rq, scratch->obj, true);
- if (!err)
- err = i915_vma_move_to_active(scratch, rq, EXEC_OBJECT_WRITE);
+ err = i915_vma_move_to_active(scratch, rq, EXEC_OBJECT_WRITE);
i915_vma_unlock(scratch);
i915_request_get(rq);
@@ -1053,21 +1049,6 @@ store_context(struct intel_context *ce, struct i915_vma *scratch)
return batch;
}
-static int move_to_active(struct i915_request *rq,
- struct i915_vma *vma,
- unsigned int flags)
-{
- int err;
-
- i915_vma_lock(vma);
- err = i915_request_await_object(rq, vma->obj, flags);
- if (!err)
- err = i915_vma_move_to_active(vma, rq, flags);
- i915_vma_unlock(vma);
-
- return err;
-}
-
static struct i915_request *
record_registers(struct intel_context *ce,
struct i915_vma *before,
@@ -1093,19 +1074,19 @@ record_registers(struct intel_context *ce,
if (IS_ERR(rq))
goto err_after;
- err = move_to_active(rq, before, EXEC_OBJECT_WRITE);
+ err = igt_vma_move_to_active_unlocked(before, rq, EXEC_OBJECT_WRITE);
if (err)
goto err_rq;
- err = move_to_active(rq, b_before, 0);
+ err = igt_vma_move_to_active_unlocked(b_before, rq, 0);
if (err)
goto err_rq;
- err = move_to_active(rq, after, EXEC_OBJECT_WRITE);
+ err = igt_vma_move_to_active_unlocked(after, rq, EXEC_OBJECT_WRITE);
if (err)
goto err_rq;
- err = move_to_active(rq, b_after, 0);
+ err = igt_vma_move_to_active_unlocked(b_after, rq, 0);
if (err)
goto err_rq;
@@ -1243,7 +1224,7 @@ static int poison_registers(struct intel_context *ce, u32 poison, u32 *sema)
goto err_batch;
}
- err = move_to_active(rq, batch, 0);
+ err = igt_vma_move_to_active_unlocked(batch, rq, 0);
if (err)
goto err_rq;
diff --git a/drivers/gpu/drm/i915/gt/selftest_migrate.c b/drivers/gpu/drm/i915/gt/selftest_migrate.c
index 2b0c87999949..0dc5309c90a4 100644
--- a/drivers/gpu/drm/i915/gt/selftest_migrate.c
+++ b/drivers/gpu/drm/i915/gt/selftest_migrate.c
@@ -6,6 +6,7 @@
#include <linux/sort.h>
#include "gem/i915_gem_internal.h"
+#include "gem/i915_gem_lmem.h"
#include "selftests/i915_random.h"
diff --git a/drivers/gpu/drm/i915/gt/selftest_mocs.c b/drivers/gpu/drm/i915/gt/selftest_mocs.c
index c1d861333c44..f27cc28608d4 100644
--- a/drivers/gpu/drm/i915/gt/selftest_mocs.c
+++ b/drivers/gpu/drm/i915/gt/selftest_mocs.c
@@ -7,6 +7,7 @@
#include "gt/intel_gpu_commands.h"
#include "i915_selftest.h"
+#include "gem/selftests/igt_gem_utils.h"
#include "gem/selftests/mock_context.h"
#include "selftests/igt_reset.h"
#include "selftests/igt_spinner.h"
@@ -228,9 +229,7 @@ static int check_mocs_engine(struct live_mocs *arg,
return PTR_ERR(rq);
i915_vma_lock(vma);
- err = i915_request_await_object(rq, vma->obj, true);
- if (!err)
- err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
+ err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
i915_vma_unlock(vma);
/* Read the mocs tables back using SRM */
diff --git a/drivers/gpu/drm/i915/gt/selftest_rc6.c b/drivers/gpu/drm/i915/gt/selftest_rc6.c
index 8c70b7e12074..2ceeadecc639 100644
--- a/drivers/gpu/drm/i915/gt/selftest_rc6.c
+++ b/drivers/gpu/drm/i915/gt/selftest_rc6.c
@@ -19,11 +19,11 @@ static u64 rc6_residency(struct intel_rc6 *rc6)
/* XXX VLV_GT_MEDIA_RC6? */
- result = intel_rc6_residency_ns(rc6, GEN6_GT_GFX_RC6);
+ result = intel_rc6_residency_ns(rc6, INTEL_RC6_RES_RC6);
if (HAS_RC6p(rc6_to_i915(rc6)))
- result += intel_rc6_residency_ns(rc6, GEN6_GT_GFX_RC6p);
+ result += intel_rc6_residency_ns(rc6, INTEL_RC6_RES_RC6p);
if (HAS_RC6pp(rc6_to_i915(rc6)))
- result += intel_rc6_residency_ns(rc6, GEN6_GT_GFX_RC6pp);
+ result += intel_rc6_residency_ns(rc6, INTEL_RC6_RES_RC6pp);
return result;
}
diff --git a/drivers/gpu/drm/i915/gt/selftest_rps.c b/drivers/gpu/drm/i915/gt/selftest_rps.c
index cfb4708dd62e..39f1b7564170 100644
--- a/drivers/gpu/drm/i915/gt/selftest_rps.c
+++ b/drivers/gpu/drm/i915/gt/selftest_rps.c
@@ -652,9 +652,7 @@ int live_rps_frequency_cs(void *arg)
goto err_vma;
}
- err = i915_request_await_object(rq, vma->obj, false);
- if (!err)
- err = i915_vma_move_to_active(vma, rq, 0);
+ err = i915_vma_move_to_active(vma, rq, 0);
if (!err)
err = rq->engine->emit_bb_start(rq,
vma->node.start,
@@ -793,9 +791,7 @@ int live_rps_frequency_srm(void *arg)
goto err_vma;
}
- err = i915_request_await_object(rq, vma->obj, false);
- if (!err)
- err = i915_vma_move_to_active(vma, rq, 0);
+ err = i915_vma_move_to_active(vma, rq, 0);
if (!err)
err = rq->engine->emit_bb_start(rq,
vma->node.start,
@@ -1107,21 +1103,27 @@ static u64 __measure_power(int duration_ms)
return div64_u64(1000 * 1000 * dE, dt);
}
-static u64 measure_power_at(struct intel_rps *rps, int *freq)
+static u64 measure_power(struct intel_rps *rps, int *freq)
{
u64 x[5];
int i;
- *freq = rps_set_check(rps, *freq);
for (i = 0; i < 5; i++)
x[i] = __measure_power(5);
- *freq = (*freq + read_cagf(rps)) / 2;
+
+ *freq = (*freq + intel_rps_read_actual_frequency(rps)) / 2;
/* A simple triangle filter for better result stability */
sort(x, 5, sizeof(*x), cmp_u64, NULL);
return div_u64(x[1] + 2 * x[2] + x[3], 4);
}
+static u64 measure_power_at(struct intel_rps *rps, int *freq)
+{
+ *freq = rps_set_check(rps, *freq);
+ return measure_power(rps, freq);
+}
+
int live_rps_power(void *arg)
{
struct intel_gt *gt = arg;
diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.c b/drivers/gpu/drm/i915/gt/selftest_slpc.c
index f8a1d27df272..bd44ce73a504 100644
--- a/drivers/gpu/drm/i915/gt/selftest_slpc.c
+++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c
@@ -11,7 +11,16 @@
enum test_type {
VARY_MIN,
VARY_MAX,
- MAX_GRANTED
+ MAX_GRANTED,
+ SLPC_POWER,
+ TILE_INTERACTION,
+};
+
+struct slpc_thread {
+ struct kthread_worker *worker;
+ struct kthread_work work;
+ struct intel_gt *gt;
+ int result;
};
static int slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 freq)
@@ -41,6 +50,39 @@ static int slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 freq)
return ret;
}
+static int slpc_set_freq(struct intel_gt *gt, u32 freq)
+{
+ int err;
+ struct intel_guc_slpc *slpc = &gt->uc.guc.slpc;
+
+ err = slpc_set_max_freq(slpc, freq);
+ if (err) {
+ pr_err("Unable to update max freq");
+ return err;
+ }
+
+ err = slpc_set_min_freq(slpc, freq);
+ if (err) {
+ pr_err("Unable to update min freq");
+ return err;
+ }
+
+ return err;
+}
+
+static u64 measure_power_at_freq(struct intel_gt *gt, int *freq, u64 *power)
+{
+ int err = 0;
+
+ err = slpc_set_freq(gt, *freq);
+ if (err)
+ return err;
+ *freq = intel_rps_read_actual_frequency(&gt->rps);
+ *power = measure_power(&gt->rps, freq);
+
+ return err;
+}
+
static int vary_max_freq(struct intel_guc_slpc *slpc, struct intel_rps *rps,
u32 *max_act_freq)
{
@@ -113,6 +155,58 @@ static int vary_min_freq(struct intel_guc_slpc *slpc, struct intel_rps *rps,
return err;
}
+static int slpc_power(struct intel_gt *gt, struct intel_engine_cs *engine)
+{
+ struct intel_guc_slpc *slpc = &gt->uc.guc.slpc;
+ struct {
+ u64 power;
+ int freq;
+ } min, max;
+ int err = 0;
+
+ /*
+ * Our fundamental assumption is that running at lower frequency
+ * actually saves power. Let's see if our RAPL measurement supports
+ * that theory.
+ */
+ if (!librapl_supported(gt->i915))
+ return 0;
+
+ min.freq = slpc->min_freq;
+ err = measure_power_at_freq(gt, &min.freq, &min.power);
+
+ if (err)
+ return err;
+
+ max.freq = slpc->rp0_freq;
+ err = measure_power_at_freq(gt, &max.freq, &max.power);
+
+ if (err)
+ return err;
+
+ pr_info("%s: min:%llumW @ %uMHz, max:%llumW @ %uMHz\n",
+ engine->name,
+ min.power, min.freq,
+ max.power, max.freq);
+
+ if (10 * min.freq >= 9 * max.freq) {
+ pr_notice("Could not control frequency, ran at [%uMHz, %uMhz]\n",
+ min.freq, max.freq);
+ }
+
+ if (11 * min.power > 10 * max.power) {
+ pr_err("%s: did not conserve power when setting lower frequency!\n",
+ engine->name);
+ err = -EINVAL;
+ }
+
+ /* Restore min/max frequencies */
+ slpc_set_max_freq(slpc, slpc->rp0_freq);
+ slpc_set_min_freq(slpc, slpc->min_freq);
+
+ return err;
+}
+
static int max_granted_freq(struct intel_guc_slpc *slpc, struct intel_rps *rps, u32 *max_act_freq)
{
struct intel_gt *gt = rps_to_gt(rps);
@@ -126,7 +220,8 @@ static int max_granted_freq(struct intel_guc_slpc *slpc, struct intel_rps *rps,
*max_act_freq = intel_rps_read_actual_frequency(rps);
if (*max_act_freq != slpc->rp0_freq) {
/* Check if there was some throttling by pcode */
- perf_limit_reasons = intel_uncore_read(gt->uncore, GT0_PERF_LIMIT_REASONS);
+ perf_limit_reasons = intel_uncore_read(gt->uncore,
+ intel_gt_perf_limit_reasons_reg(gt));
/* If not, this is an error */
if (!(perf_limit_reasons & GT0_PERF_LIMIT_REASONS_MASK)) {
@@ -153,6 +248,11 @@ static int run_test(struct intel_gt *gt, int test_type)
if (!intel_uc_uses_guc_slpc(&gt->uc))
return 0;
+ if (slpc->min_freq == slpc->rp0_freq) {
+ pr_err("Min/Max are fused to the same value\n");
+ return -EINVAL;
+ }
+
if (igt_spinner_init(&spin, gt))
return -ENOMEM;
@@ -167,17 +267,14 @@ static int run_test(struct intel_gt *gt, int test_type)
}
/*
- * FIXME: With efficient frequency enabled, GuC can request
- * frequencies higher than the SLPC max. While this is fixed
- * in GuC, we level set these tests with RPn as min.
+ * 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.
*/
err = slpc_set_min_freq(slpc, slpc->min_freq);
- if (err)
+ if (err) {
+ pr_err("Unable to update min freq!");
return err;
-
- if (slpc->min_freq == slpc->rp0_freq) {
- pr_err("Min/Max are fused to the same value\n");
- return -EINVAL;
}
intel_gt_pm_wait_for_idle(gt);
@@ -222,9 +319,10 @@ static int run_test(struct intel_gt *gt, int test_type)
break;
case MAX_GRANTED:
+ case TILE_INTERACTION:
/* Media engines have a different RP0 */
- if (engine->class == VIDEO_DECODE_CLASS ||
- engine->class == VIDEO_ENHANCEMENT_CLASS) {
+ if (gt->type != GT_MEDIA && (engine->class == VIDEO_DECODE_CLASS ||
+ engine->class == VIDEO_ENHANCEMENT_CLASS)) {
igt_spinner_end(&spin);
st_engine_heartbeat_enable(engine);
err = 0;
@@ -233,17 +331,24 @@ static int run_test(struct intel_gt *gt, int test_type)
err = max_granted_freq(slpc, rps, &max_act_freq);
break;
- }
- pr_info("Max actual frequency for %s was %d\n",
- engine->name, max_act_freq);
+ case SLPC_POWER:
+ err = slpc_power(gt, engine);
+ break;
+ }
- /* Actual frequency should rise above min */
- if (max_act_freq <= slpc_min_freq) {
- pr_err("Actual freq did not rise above min\n");
- pr_err("Perf Limit Reasons: 0x%x\n",
- intel_uncore_read(gt->uncore, GT0_PERF_LIMIT_REASONS));
- err = -EINVAL;
+ if (test_type != SLPC_POWER) {
+ pr_info("Max actual frequency for %s was %d\n",
+ engine->name, max_act_freq);
+
+ /* Actual frequency should rise above min */
+ if (max_act_freq <= slpc->min_freq) {
+ pr_err("Actual freq did not rise above min\n");
+ pr_err("Perf Limit Reasons: 0x%x\n",
+ intel_uncore_read(gt->uncore,
+ intel_gt_perf_limit_reasons_reg(gt)));
+ err = -EINVAL;
+ }
}
igt_spinner_end(&spin);
@@ -270,26 +375,116 @@ static int run_test(struct intel_gt *gt, int test_type)
static int live_slpc_vary_min(void *arg)
{
struct drm_i915_private *i915 = arg;
- struct intel_gt *gt = to_gt(i915);
+ struct intel_gt *gt;
+ unsigned int i;
+ int ret;
+
+ for_each_gt(gt, i915, i) {
+ ret = run_test(gt, VARY_MIN);
+ if (ret)
+ return ret;
+ }
- return run_test(gt, VARY_MIN);
+ return ret;
}
static int live_slpc_vary_max(void *arg)
{
struct drm_i915_private *i915 = arg;
- struct intel_gt *gt = to_gt(i915);
+ struct intel_gt *gt;
+ unsigned int i;
+ int ret;
+
+ for_each_gt(gt, i915, i) {
+ ret = run_test(gt, VARY_MAX);
+ if (ret)
+ return ret;
+ }
- return run_test(gt, VARY_MAX);
+ return ret;
}
/* check if pcode can grant RP0 */
static int live_slpc_max_granted(void *arg)
{
struct drm_i915_private *i915 = arg;
- struct intel_gt *gt = to_gt(i915);
+ struct intel_gt *gt;
+ unsigned int i;
+ int ret;
+
+ for_each_gt(gt, i915, i) {
+ ret = run_test(gt, MAX_GRANTED);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+static int live_slpc_power(void *arg)
+{
+ struct drm_i915_private *i915 = arg;
+ struct intel_gt *gt;
+ unsigned int i;
+ int ret;
+
+ for_each_gt(gt, i915, i) {
+ ret = run_test(gt, SLPC_POWER);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+static void slpc_spinner_thread(struct kthread_work *work)
+{
+ struct slpc_thread *thread = container_of(work, typeof(*thread), work);
+
+ thread->result = run_test(thread->gt, TILE_INTERACTION);
+}
+
+static int live_slpc_tile_interaction(void *arg)
+{
+ struct drm_i915_private *i915 = arg;
+ struct intel_gt *gt;
+ struct slpc_thread *threads;
+ int i = 0, ret = 0;
+
+ threads = kcalloc(I915_MAX_GT, sizeof(*threads), GFP_KERNEL);
+ if (!threads)
+ return -ENOMEM;
+
+ for_each_gt(gt, i915, i) {
+ threads[i].worker = kthread_create_worker(0, "igt/slpc_parallel:%d", gt->info.id);
+
+ if (IS_ERR(threads[i].worker)) {
+ ret = PTR_ERR(threads[i].worker);
+ break;
+ }
+
+ threads[i].gt = gt;
+ kthread_init_work(&threads[i].work, slpc_spinner_thread);
+ kthread_queue_work(threads[i].worker, &threads[i].work);
+ }
+
+ for_each_gt(gt, i915, i) {
+ int status;
+
+ if (IS_ERR_OR_NULL(threads[i].worker))
+ continue;
- return run_test(gt, MAX_GRANTED);
+ kthread_flush_work(&threads[i].work);
+ status = READ_ONCE(threads[i].result);
+ if (status && !ret) {
+ pr_err("%s GT %d failed ", __func__, gt->info.id);
+ ret = status;
+ }
+ kthread_destroy_worker(threads[i].worker);
+ }
+
+ kfree(threads);
+ return ret;
}
int intel_slpc_live_selftests(struct drm_i915_private *i915)
@@ -298,10 +493,17 @@ int intel_slpc_live_selftests(struct drm_i915_private *i915)
SUBTEST(live_slpc_vary_max),
SUBTEST(live_slpc_vary_min),
SUBTEST(live_slpc_max_granted),
+ SUBTEST(live_slpc_power),
+ SUBTEST(live_slpc_tile_interaction),
};
- if (intel_gt_is_wedged(to_gt(i915)))
- return 0;
+ struct intel_gt *gt;
+ unsigned int i;
+
+ for_each_gt(gt, i915, i) {
+ if (intel_gt_is_wedged(gt))
+ return 0;
+ }
return i915_live_subtests(tests, i915);
}
diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
index 67a9aab801dd..96e3861706d6 100644
--- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c
+++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
@@ -66,14 +66,14 @@ reference_lists_init(struct intel_gt *gt, struct wa_lists *lists)
memset(lists, 0, sizeof(*lists));
- wa_init_start(&lists->gt_wa_list, "GT_REF", "global");
+ wa_init_start(&lists->gt_wa_list, gt, "GT_REF", "global");
gt_init_workarounds(gt, &lists->gt_wa_list);
wa_init_finish(&lists->gt_wa_list);
for_each_engine(engine, gt, id) {
struct i915_wa_list *wal = &lists->engine[id].wa_list;
- wa_init_start(wal, "REF", engine->name);
+ wa_init_start(wal, gt, "REF", engine->name);
engine_init_workarounds(engine, wal);
wa_init_finish(wal);
@@ -139,9 +139,7 @@ read_nonprivs(struct intel_context *ce)
}
i915_vma_lock(vma);
- err = i915_request_await_object(rq, vma->obj, true);
- if (err == 0)
- err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
+ err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
i915_vma_unlock(vma);
if (err)
goto err_req;
@@ -632,16 +630,12 @@ retry:
goto err_request;
}
- err = i915_request_await_object(rq, batch->obj, false);
- if (err == 0)
- err = i915_vma_move_to_active(batch, rq, 0);
+ err = i915_vma_move_to_active(batch, rq, 0);
if (err)
goto err_request;
- err = i915_request_await_object(rq, scratch->obj, true);
- if (err == 0)
- err = i915_vma_move_to_active(scratch, rq,
- EXEC_OBJECT_WRITE);
+ err = i915_vma_move_to_active(scratch, rq,
+ EXEC_OBJECT_WRITE);
if (err)
goto err_request;
@@ -860,9 +854,7 @@ static int read_whitelisted_registers(struct intel_context *ce,
return PTR_ERR(rq);
i915_vma_lock(results);
- err = i915_request_await_object(rq, results->obj, true);
- if (err == 0)
- err = i915_vma_move_to_active(results, rq, EXEC_OBJECT_WRITE);
+ err = i915_vma_move_to_active(results, rq, EXEC_OBJECT_WRITE);
i915_vma_unlock(results);
if (err)
goto err_req;
@@ -944,9 +936,7 @@ static int scrub_whitelisted_registers(struct intel_context *ce)
}
i915_vma_lock(batch);
- err = i915_request_await_object(rq, batch->obj, false);
- if (err == 0)
- err = i915_vma_move_to_active(batch, rq, 0);
+ err = i915_vma_move_to_active(batch, rq, 0);
i915_vma_unlock(batch);
if (err)
goto err_request;
@@ -991,7 +981,7 @@ static bool pardon_reg(struct drm_i915_private *i915, i915_reg_t reg)
/* Alas, we must pardon some whitelists. Mistakes already made */
static const struct regmask pardon[] = {
{ GEN9_CTX_PREEMPT_REG, 9 },
- { GEN8_L3SQCREG4, 9 },
+ { _MMIO(0xb118), 9 }, /* GEN8_L3SQCREG4 */
};
return find_reg(i915, reg, pardon, ARRAY_SIZE(pardon));
diff --git a/drivers/gpu/drm/i915/gt/sysfs_engines.c b/drivers/gpu/drm/i915/gt/sysfs_engines.c
index 967031056202..f2d9858d827c 100644
--- a/drivers/gpu/drm/i915/gt/sysfs_engines.c
+++ b/drivers/gpu/drm/i915/gt/sysfs_engines.c
@@ -144,7 +144,7 @@ max_spin_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count)
{
struct intel_engine_cs *engine = kobj_to_engine(kobj);
- unsigned long long duration;
+ unsigned long long duration, clamped;
int err;
/*
@@ -168,7 +168,8 @@ max_spin_store(struct kobject *kobj, struct kobj_attribute *attr,
if (err)
return err;
- if (duration > jiffies_to_nsecs(2))
+ clamped = intel_clamp_max_busywait_duration_ns(engine, duration);
+ if (duration != clamped)
return -EINVAL;
WRITE_ONCE(engine->props.max_busywait_duration_ns, duration);
@@ -203,7 +204,7 @@ timeslice_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count)
{
struct intel_engine_cs *engine = kobj_to_engine(kobj);
- unsigned long long duration;
+ unsigned long long duration, clamped;
int err;
/*
@@ -218,7 +219,8 @@ timeslice_store(struct kobject *kobj, struct kobj_attribute *attr,
if (err)
return err;
- if (duration > jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT))
+ clamped = intel_clamp_timeslice_duration_ms(engine, duration);
+ if (duration != clamped)
return -EINVAL;
WRITE_ONCE(engine->props.timeslice_duration_ms, duration);
@@ -256,7 +258,7 @@ stop_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count)
{
struct intel_engine_cs *engine = kobj_to_engine(kobj);
- unsigned long long duration;
+ unsigned long long duration, clamped;
int err;
/*
@@ -272,7 +274,8 @@ stop_store(struct kobject *kobj, struct kobj_attribute *attr,
if (err)
return err;
- if (duration > jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT))
+ clamped = intel_clamp_stop_timeout_ms(engine, duration);
+ if (duration != clamped)
return -EINVAL;
WRITE_ONCE(engine->props.stop_timeout_ms, duration);
@@ -306,7 +309,7 @@ preempt_timeout_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count)
{
struct intel_engine_cs *engine = kobj_to_engine(kobj);
- unsigned long long timeout;
+ unsigned long long timeout, clamped;
int err;
/*
@@ -322,7 +325,8 @@ preempt_timeout_store(struct kobject *kobj, struct kobj_attribute *attr,
if (err)
return err;
- if (timeout > jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT))
+ clamped = intel_clamp_preempt_timeout_ms(engine, timeout);
+ if (timeout != clamped)
return -EINVAL;
WRITE_ONCE(engine->props.preempt_timeout_ms, timeout);
@@ -362,7 +366,7 @@ heartbeat_store(struct kobject *kobj, struct kobj_attribute *attr,
const char *buf, size_t count)
{
struct intel_engine_cs *engine = kobj_to_engine(kobj);
- unsigned long long delay;
+ unsigned long long delay, clamped;
int err;
/*
@@ -379,7 +383,8 @@ heartbeat_store(struct kobject *kobj, struct kobj_attribute *attr,
if (err)
return err;
- if (delay >= jiffies_to_msecs(MAX_SCHEDULE_TIMEOUT))
+ clamped = intel_clamp_heartbeat_interval_ms(engine, delay);
+ if (delay != clamped)
return -EINVAL;
err = intel_engine_set_heartbeat(engine, delay);
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
index 29ef8afc8c2e..f359bef046e0 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
@@ -117,6 +117,7 @@ enum intel_guc_action {
INTEL_GUC_ACTION_ENTER_S_STATE = 0x501,
INTEL_GUC_ACTION_EXIT_S_STATE = 0x502,
INTEL_GUC_ACTION_GLOBAL_SCHED_POLICY_CHANGE = 0x506,
+ INTEL_GUC_ACTION_UPDATE_SCHEDULING_POLICIES_KLV = 0x509,
INTEL_GUC_ACTION_SCHED_CONTEXT = 0x1000,
INTEL_GUC_ACTION_SCHED_CONTEXT_MODE_SET = 0x1001,
INTEL_GUC_ACTION_SCHED_CONTEXT_MODE_DONE = 0x1002,
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h
index 4c840a2639dc..811add10c30d 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_slpc_abi.h
@@ -128,6 +128,15 @@ enum slpc_media_ratio_mode {
SLPC_MEDIA_RATIO_MODE_FIXED_ONE_TO_TWO = 2,
};
+enum slpc_gucrc_mode {
+ SLPC_GUCRC_MODE_HW = 0,
+ SLPC_GUCRC_MODE_GUCRC_NO_RC6 = 1,
+ SLPC_GUCRC_MODE_GUCRC_STATIC_TIMEOUT = 2,
+ SLPC_GUCRC_MODE_GUCRC_DYNAMIC_HYSTERESIS = 3,
+
+ SLPC_GUCRC_MODE_MAX,
+};
+
enum slpc_event_id {
SLPC_EVENT_RESET = 0,
SLPC_EVENT_SHUTDOWN = 1,
diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h
index 4a59478c3b5c..58012edd4eb0 100644
--- a/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h
+++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h
@@ -82,9 +82,16 @@
#define GUC_KLV_SELF_CFG_G2H_CTB_SIZE_LEN 1u
/*
+ * Global scheduling policy update keys.
+ */
+enum {
+ GUC_SCHEDULING_POLICIES_KLV_ID_RENDER_COMPUTE_YIELD = 0x1001,
+};
+
+/*
* Per context scheduling policy update keys.
*/
-enum {
+enum {
GUC_CONTEXT_POLICIES_KLV_ID_EXECUTION_QUANTUM = 0x2001,
GUC_CONTEXT_POLICIES_KLV_ID_PREEMPTION_TIMEOUT = 0x2002,
GUC_CONTEXT_POLICIES_KLV_ID_SCHEDULING_PRIORITY = 0x2003,
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
index bac06e3d6f2c..52aede324788 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c
@@ -98,6 +98,8 @@ static void gen9_enable_guc_interrupts(struct intel_guc *guc)
gt->pm_guc_events);
gen6_gt_pm_enable_irq(gt, gt->pm_guc_events);
spin_unlock_irq(gt->irq_lock);
+
+ guc->interrupts.enabled = true;
}
static void gen9_disable_guc_interrupts(struct intel_guc *guc)
@@ -105,6 +107,7 @@ static void gen9_disable_guc_interrupts(struct intel_guc *guc)
struct intel_gt *gt = guc_to_gt(guc);
assert_rpm_wakelock_held(&gt->i915->runtime_pm);
+ guc->interrupts.enabled = false;
spin_lock_irq(gt->irq_lock);
@@ -116,39 +119,39 @@ static void gen9_disable_guc_interrupts(struct intel_guc *guc)
gen9_reset_guc_interrupts(guc);
}
+static bool __gen11_reset_guc_interrupts(struct intel_gt *gt)
+{
+ u32 irq = gt->type == GT_MEDIA ? MTL_MGUC : GEN11_GUC;
+
+ lockdep_assert_held(gt->irq_lock);
+ return gen11_gt_reset_one_iir(gt, 0, irq);
+}
+
static void gen11_reset_guc_interrupts(struct intel_guc *guc)
{
struct intel_gt *gt = guc_to_gt(guc);
spin_lock_irq(gt->irq_lock);
- gen11_gt_reset_one_iir(gt, 0, GEN11_GUC);
+ __gen11_reset_guc_interrupts(gt);
spin_unlock_irq(gt->irq_lock);
}
static void gen11_enable_guc_interrupts(struct intel_guc *guc)
{
struct intel_gt *gt = guc_to_gt(guc);
- u32 events = REG_FIELD_PREP(ENGINE1_MASK, GUC_INTR_GUC2HOST);
spin_lock_irq(gt->irq_lock);
- WARN_ON_ONCE(gen11_gt_reset_one_iir(gt, 0, GEN11_GUC));
- intel_uncore_write(gt->uncore,
- GEN11_GUC_SG_INTR_ENABLE, events);
- intel_uncore_write(gt->uncore,
- GEN11_GUC_SG_INTR_MASK, ~events);
+ __gen11_reset_guc_interrupts(gt);
spin_unlock_irq(gt->irq_lock);
+
+ guc->interrupts.enabled = true;
}
static void gen11_disable_guc_interrupts(struct intel_guc *guc)
{
struct intel_gt *gt = guc_to_gt(guc);
- spin_lock_irq(gt->irq_lock);
-
- intel_uncore_write(gt->uncore, GEN11_GUC_SG_INTR_MASK, ~0);
- intel_uncore_write(gt->uncore, GEN11_GUC_SG_INTR_ENABLE, 0);
-
- spin_unlock_irq(gt->irq_lock);
+ guc->interrupts.enabled = false;
intel_synchronize_irq(gt->i915);
gen11_reset_guc_interrupts(guc);
@@ -156,7 +159,8 @@ static void gen11_disable_guc_interrupts(struct intel_guc *guc)
void intel_guc_init_early(struct intel_guc *guc)
{
- struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
+ 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_guc_ct_init_early(&guc->ct);
@@ -168,12 +172,17 @@ void intel_guc_init_early(struct intel_guc *guc)
mutex_init(&guc->send_mutex);
spin_lock_init(&guc->irq_lock);
if (GRAPHICS_VER(i915) >= 11) {
- guc->notify_reg = GEN11_GUC_HOST_INTERRUPT;
guc->interrupts.reset = gen11_reset_guc_interrupts;
guc->interrupts.enable = gen11_enable_guc_interrupts;
guc->interrupts.disable = gen11_disable_guc_interrupts;
- guc->send_regs.base =
- i915_mmio_reg_offset(GEN11_SOFT_SCRATCH(0));
+ if (gt->type == GT_MEDIA) {
+ guc->notify_reg = MEDIA_GUC_HOST_INTERRUPT;
+ guc->send_regs.base = i915_mmio_reg_offset(MEDIA_SOFT_SCRATCH(0));
+ } else {
+ guc->notify_reg = GEN11_GUC_HOST_INTERRUPT;
+ guc->send_regs.base = i915_mmio_reg_offset(GEN11_SOFT_SCRATCH(0));
+ }
+
guc->send_regs.count = GEN11_SOFT_SCRATCH_COUNT;
} else {
@@ -441,6 +450,7 @@ err_log:
err_fw:
intel_uc_fw_fini(&guc->fw);
out:
+ intel_uc_fw_change_status(&guc->fw, INTEL_UC_FIRMWARE_INIT_FAIL);
i915_probe_error(gt->i915, "failed with %d\n", ret);
return ret;
}
@@ -870,14 +880,14 @@ void intel_guc_load_status(struct intel_guc *guc, struct drm_printer *p)
u32 status = intel_uncore_read(uncore, GUC_STATUS);
u32 i;
- drm_printf(p, "\nGuC status 0x%08x:\n", status);
+ drm_printf(p, "GuC status 0x%08x:\n", status);
drm_printf(p, "\tBootrom status = 0x%x\n",
(status & GS_BOOTROM_MASK) >> GS_BOOTROM_SHIFT);
drm_printf(p, "\tuKernel status = 0x%x\n",
(status & GS_UKERNEL_MASK) >> GS_UKERNEL_SHIFT);
drm_printf(p, "\tMIA Core status = 0x%x\n",
(status & GS_MIA_MASK) >> GS_MIA_SHIFT);
- drm_puts(p, "\nScratch registers:\n");
+ drm_puts(p, "Scratch registers:\n");
for (i = 0; i < 16; i++) {
drm_printf(p, "\t%2d: \t0x%x\n",
i, intel_uncore_read(uncore, SOFT_SCRATCH(i)));
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
index 804133df1ac9..1bb3f9829286 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h
@@ -78,6 +78,7 @@ struct intel_guc {
/** @interrupts: pointers to GuC interrupt-managing functions. */
struct {
+ bool enabled;
void (*reset)(struct intel_guc *guc);
void (*enable)(struct intel_guc *guc);
void (*disable)(struct intel_guc *guc);
@@ -113,6 +114,10 @@ struct intel_guc {
*/
struct list_head guc_id_list;
/**
+ * @guc_ids_in_use: Number single-lrc guc_ids in use
+ */
+ unsigned int guc_ids_in_use;
+ /**
* @destroyed_contexts: list of contexts waiting to be destroyed
* (deregistered with the GuC)
*/
@@ -132,6 +137,16 @@ struct intel_guc {
* @reset_fail_mask: mask of engines that failed to reset
*/
intel_engine_mask_t reset_fail_mask;
+ /**
+ * @sched_disable_delay_ms: schedule disable delay, in ms, for
+ * contexts
+ */
+ unsigned int sched_disable_delay_ms;
+ /**
+ * @sched_disable_gucid_threshold: threshold of min remaining available
+ * guc_ids before we start bypassing the schedule disable delay
+ */
+ unsigned int sched_disable_gucid_threshold;
} submission_state;
/**
@@ -316,9 +331,11 @@ retry:
return err;
}
+/* Only call this from the interrupt handler code */
static inline void intel_guc_to_host_event_handler(struct intel_guc *guc)
{
- intel_guc_ct_event_handler(&guc->ct);
+ if (guc->interrupts.enabled)
+ intel_guc_ct_event_handler(&guc->ct);
}
/* GuC addresses above GUC_GGTT_TOP also don't map through the GTT */
@@ -466,4 +483,6 @@ void intel_guc_write_barrier(struct intel_guc *guc);
void intel_guc_dump_time_info(struct intel_guc *guc, struct drm_printer *p);
+int intel_guc_sched_disable_gucid_threshold_max(struct intel_guc *guc);
+
#endif
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 74cbe8eaf531..a7f737c4792e 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c
@@ -5,6 +5,7 @@
#include <linux/bsearch.h>
+#include "gem/i915_gem_lmem.h"
#include "gt/intel_engine_regs.h"
#include "gt/intel_gt.h"
#include "gt/intel_gt_mcr.h"
@@ -277,24 +278,16 @@ __mmio_reg_add(struct temp_regset *regset, struct guc_mmio_reg *reg)
return slot;
}
-#define GUC_REGSET_STEERING(group, instance) ( \
- FIELD_PREP(GUC_REGSET_STEERING_GROUP, (group)) | \
- FIELD_PREP(GUC_REGSET_STEERING_INSTANCE, (instance)) | \
- GUC_REGSET_NEEDS_STEERING \
-)
-
static long __must_check guc_mmio_reg_add(struct intel_gt *gt,
struct temp_regset *regset,
- i915_reg_t reg, u32 flags)
+ u32 offset, u32 flags)
{
u32 count = regset->storage_used - (regset->registers - regset->storage);
- u32 offset = i915_mmio_reg_offset(reg);
struct guc_mmio_reg entry = {
.offset = offset,
.flags = flags,
};
struct guc_mmio_reg *slot;
- u8 group, inst;
/*
* The mmio list is built using separate lists within the driver.
@@ -306,17 +299,6 @@ static long __must_check guc_mmio_reg_add(struct intel_gt *gt,
sizeof(entry), guc_mmio_reg_cmp))
return 0;
- /*
- * The GuC doesn't have a default steering, so we need to explicitly
- * steer all registers that need steering. However, we do not keep track
- * of all the steering ranges, only of those that have a chance of using
- * a non-default steering from the i915 pov. Instead of adding such
- * tracking, it is easier to just program the default steering for all
- * regs that don't need a non-default one.
- */
- intel_gt_mcr_get_nonterminated_steering(gt, reg, &group, &inst);
- entry.flags |= GUC_REGSET_STEERING(group, inst);
-
slot = __mmio_reg_add(regset, &entry);
if (IS_ERR(slot))
return PTR_ERR(slot);
@@ -335,6 +317,38 @@ static long __must_check guc_mmio_reg_add(struct intel_gt *gt,
#define GUC_MMIO_REG_ADD(gt, regset, reg, masked) \
guc_mmio_reg_add(gt, \
regset, \
+ i915_mmio_reg_offset(reg), \
+ (masked) ? GUC_REGSET_MASKED : 0)
+
+#define GUC_REGSET_STEERING(group, instance) ( \
+ FIELD_PREP(GUC_REGSET_STEERING_GROUP, (group)) | \
+ FIELD_PREP(GUC_REGSET_STEERING_INSTANCE, (instance)) | \
+ GUC_REGSET_NEEDS_STEERING \
+)
+
+static long __must_check guc_mcr_reg_add(struct intel_gt *gt,
+ struct temp_regset *regset,
+ i915_mcr_reg_t reg, u32 flags)
+{
+ u8 group, inst;
+
+ /*
+ * The GuC doesn't have a default steering, so we need to explicitly
+ * steer all registers that need steering. However, we do not keep track
+ * of all the steering ranges, only of those that have a chance of using
+ * a non-default steering from the i915 pov. Instead of adding such
+ * tracking, it is easier to just program the default steering for all
+ * regs that don't need a non-default one.
+ */
+ intel_gt_mcr_get_nonterminated_steering(gt, reg, &group, &inst);
+ flags |= GUC_REGSET_STEERING(group, inst);
+
+ return guc_mmio_reg_add(gt, regset, i915_mmio_reg_offset(reg), flags);
+}
+
+#define GUC_MCR_REG_ADD(gt, regset, reg, masked) \
+ guc_mcr_reg_add(gt, \
+ regset, \
(reg), \
(masked) ? GUC_REGSET_MASKED : 0)
@@ -372,8 +386,21 @@ static int guc_mmio_regset_init(struct temp_regset *regset,
false);
/* add in local MOCS registers */
- for (i = 0; i < GEN9_LNCFCMOCS_REG_COUNT; i++)
- ret |= GUC_MMIO_REG_ADD(gt, regset, GEN9_LNCFCMOCS(i), false);
+ for (i = 0; i < LNCFCMOCS_REG_COUNT; i++)
+ if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50))
+ ret |= GUC_MCR_REG_ADD(gt, regset, XEHP_LNCFCMOCS(i), false);
+ else
+ ret |= GUC_MMIO_REG_ADD(gt, regset, GEN9_LNCFCMOCS(i), false);
+
+ if (GRAPHICS_VER(engine->i915) >= 12) {
+ ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL0, false);
+ ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL1, false);
+ ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL2, false);
+ ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL3, false);
+ ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL4, false);
+ ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL5, false);
+ ret |= GUC_MMIO_REG_ADD(gt, regset, EU_PERF_CNTL6, false);
+ }
return ret ? -1 : 0;
}
@@ -461,6 +488,11 @@ static void fill_engine_enable_masks(struct intel_gt *gt,
info_map_write(info_map, engine_enabled_masks[GUC_BLITTER_CLASS], BCS_MASK(gt));
info_map_write(info_map, engine_enabled_masks[GUC_VIDEO_CLASS], VDBOX_MASK(gt));
info_map_write(info_map, engine_enabled_masks[GUC_VIDEOENHANCE_CLASS], VEBOX_MASK(gt));
+
+ /* The GSC engine is an instance (6) of OTHER_CLASS */
+ if (gt->engine[GSC0])
+ info_map_write(info_map, engine_enabled_masks[GUC_GSC_OTHER_CLASS],
+ BIT(gt->engine[GSC0]->instance));
}
#define LR_HW_CONTEXT_SIZE (80 * sizeof(u32))
@@ -502,9 +534,6 @@ static int guc_prep_golden_context(struct intel_guc *guc)
}
for (engine_class = 0; engine_class <= MAX_ENGINE_CLASS; ++engine_class) {
- if (engine_class == OTHER_CLASS)
- continue;
-
guc_class = engine_class_to_guc_class(engine_class);
if (!info_map_read(&info_map, engine_enabled_masks[guc_class]))
@@ -582,9 +611,6 @@ static void guc_init_golden_context(struct intel_guc *guc)
addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset;
for (engine_class = 0; engine_class <= MAX_ENGINE_CLASS; ++engine_class) {
- if (engine_class == OTHER_CLASS)
- continue;
-
guc_class = engine_class_to_guc_class(engine_class);
if (!ads_blob_read(guc, system_info.engine_enabled_masks[guc_class]))
continue;
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 8f1165146013..1c1b85073b4b 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c
@@ -132,6 +132,11 @@ static const struct __guc_mmio_reg_descr xe_lpd_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[] = {
+ COMMON_BASE_ENGINE_INSTANCE,
+};
+
/* GEN9 - Global */
static const struct __guc_mmio_reg_descr default_global_regs[] = {
COMMON_BASE_GLOBAL,
@@ -165,16 +170,20 @@ static const struct __guc_mmio_reg_descr empty_regs_list[] = {
}
/* List of lists */
-static struct __guc_mmio_reg_descr_group default_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),
{}
};
@@ -182,12 +191,16 @@ 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),
{}
};
@@ -240,19 +253,19 @@ static void guc_capture_free_extlists(struct __guc_mmio_reg_descr_group *reglist
struct __ext_steer_reg {
const char *name;
- i915_reg_t reg;
+ i915_mcr_reg_t reg;
};
static const struct __ext_steer_reg xe_extregs[] = {
- {"GEN7_SAMPLER_INSTDONE", GEN7_SAMPLER_INSTDONE},
- {"GEN7_ROW_INSTDONE", GEN7_ROW_INSTDONE}
+ {"GEN8_SAMPLER_INSTDONE", GEN8_SAMPLER_INSTDONE},
+ {"GEN8_ROW_INSTDONE", GEN8_ROW_INSTDONE}
};
static void __fill_ext_reg(struct __guc_mmio_reg_descr *ext,
const struct __ext_steer_reg *extlist,
int slice_id, int subslice_id)
{
- ext->reg = extlist->reg;
+ ext->reg = _MMIO(i915_mmio_reg_offset(extlist->reg));
ext->flags = FIELD_PREP(GUC_REGSET_STEERING_GROUP, slice_id);
ext->flags |= FIELD_PREP(GUC_REGSET_STEERING_INSTANCE, subslice_id);
ext->regname = extlist->name;
@@ -419,6 +432,46 @@ guc_capture_get_device_reglist(struct intel_guc *guc)
return default_lists;
}
+static const char *
+__stringify_type(u32 type)
+{
+ switch (type) {
+ case GUC_CAPTURE_LIST_TYPE_GLOBAL:
+ return "Global";
+ case GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS:
+ return "Class";
+ case GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE:
+ return "Instance";
+ default:
+ break;
+ }
+
+ return "unknown";
+}
+
+static const char *
+__stringify_engclass(u32 class)
+{
+ switch (class) {
+ case GUC_RENDER_CLASS:
+ return "Render";
+ case GUC_VIDEO_CLASS:
+ return "Video";
+ case GUC_VIDEOENHANCE_CLASS:
+ return "VideoEnhance";
+ case GUC_BLITTER_CLASS:
+ return "Blitter";
+ case GUC_COMPUTE_CLASS:
+ return "Compute";
+ case GUC_GSC_OTHER_CLASS:
+ return "GSC-Other";
+ default:
+ break;
+ }
+
+ return "unknown";
+}
+
static int
guc_capture_list_init(struct intel_guc *guc, u32 owner, u32 type, u32 classid,
struct guc_mmio_reg *ptr, u16 num_entries)
@@ -482,32 +535,55 @@ guc_cap_list_num_regs(struct intel_guc_state_capture *gc, u32 owner, u32 type, u
return num_regs;
}
-int
-intel_guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid,
- size_t *size)
+static int
+guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid,
+ size_t *size, bool is_purpose_est)
{
struct intel_guc_state_capture *gc = guc->capture;
+ struct drm_i915_private *i915 = guc_to_gt(guc)->i915;
struct __guc_capture_ads_cache *cache = &gc->ads_cache[owner][type][classid];
int num_regs;
- if (!gc->reglists)
+ if (!gc->reglists) {
+ drm_warn(&i915->drm, "GuC-capture: No reglist on this device\n");
return -ENODEV;
+ }
if (cache->is_valid) {
*size = cache->size;
return cache->status;
}
+ if (!is_purpose_est && owner == GUC_CAPTURE_LIST_INDEX_PF &&
+ !guc_capture_get_one_list(gc->reglists, owner, type, classid)) {
+ if (type == GUC_CAPTURE_LIST_TYPE_GLOBAL)
+ drm_warn(&i915->drm, "Missing GuC-Err-Cap reglist Global!\n");
+ else
+ drm_warn(&i915->drm, "Missing GuC-Err-Cap reglist %s(%u):%s(%u)!\n",
+ __stringify_type(type), type,
+ __stringify_engclass(classid), classid);
+ return -ENODATA;
+ }
+
num_regs = guc_cap_list_num_regs(gc, owner, type, classid);
+ /* intentional empty lists can exist depending on hw config */
if (!num_regs)
return -ENODATA;
- *size = PAGE_ALIGN((sizeof(struct guc_debug_capture_list)) +
- (num_regs * sizeof(struct guc_mmio_reg)));
+ if (size)
+ *size = PAGE_ALIGN((sizeof(struct guc_debug_capture_list)) +
+ (num_regs * sizeof(struct guc_mmio_reg)));
return 0;
}
+int
+intel_guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid,
+ size_t *size)
+{
+ return guc_capture_getlistsize(guc, owner, type, classid, size, false);
+}
+
static void guc_capture_create_prealloc_nodes(struct intel_guc *guc);
int
@@ -606,7 +682,7 @@ guc_capture_output_min_size_est(struct intel_guc *guc)
struct intel_gt *gt = guc_to_gt(guc);
struct intel_engine_cs *engine;
enum intel_engine_id id;
- int worst_min_size = 0, num_regs = 0;
+ int worst_min_size = 0;
size_t tmp = 0;
if (!guc->capture)
@@ -627,21 +703,19 @@ guc_capture_output_min_size_est(struct intel_guc *guc)
worst_min_size += sizeof(struct guc_state_capture_group_header_t) +
(3 * sizeof(struct guc_state_capture_header_t));
- if (!intel_guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0, &tmp))
- num_regs += tmp;
+ if (!guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0, &tmp, true))
+ worst_min_size += tmp;
- if (!intel_guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS,
- engine->class, &tmp)) {
- num_regs += tmp;
+ if (!guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS,
+ engine->class, &tmp, true)) {
+ worst_min_size += tmp;
}
- if (!intel_guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE,
- engine->class, &tmp)) {
- num_regs += tmp;
+ if (!guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE,
+ engine->class, &tmp, true)) {
+ worst_min_size += tmp;
}
}
- worst_min_size += (num_regs * sizeof(struct guc_mmio_reg));
-
return worst_min_size;
}
@@ -658,15 +732,23 @@ static void check_guc_capture_size(struct intel_guc *guc)
int spare_size = min_size * GUC_CAPTURE_OVERBUFFER_MULTIPLIER;
u32 buffer_size = intel_guc_log_section_size_capture(&guc->log);
+ /*
+ * NOTE: min_size is much smaller than the capture region allocation (DG2: <80K vs 1MB)
+ * Additionally, its based on space needed to fit all engines getting reset at once
+ * within the same G2H handler task slot. This is very unlikely. However, if GuC really
+ * does run out of space for whatever reason, we will see an separate warning message
+ * when processing the G2H event capture-notification, search for:
+ * INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_NOSPACE.
+ */
if (min_size < 0)
drm_warn(&i915->drm, "Failed to calculate GuC error state capture buffer minimum size: %d!\n",
min_size);
else if (min_size > buffer_size)
- drm_warn(&i915->drm, "GuC error state capture buffer is too small: %d < %d\n",
+ drm_warn(&i915->drm, "GuC error state capture buffer maybe small: %d < %d\n",
buffer_size, min_size);
else if (spare_size > buffer_size)
- drm_notice(&i915->drm, "GuC error state capture buffer maybe too small: %d < %d (min = %d)\n",
- buffer_size, spare_size, min_size);
+ drm_dbg(&i915->drm, "GuC error state capture buffer lacks spare size: %d < %d (min = %d)\n",
+ buffer_size, spare_size, min_size);
}
/*
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c
index 25f09a420561..7269eb0bbedf 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_debugfs.c
@@ -71,12 +71,73 @@ static bool intel_eval_slpc_support(void *data)
return intel_guc_slpc_is_used(guc);
}
+static int guc_sched_disable_delay_ms_get(void *data, u64 *val)
+{
+ struct intel_guc *guc = data;
+
+ if (!intel_guc_submission_is_used(guc))
+ return -ENODEV;
+
+ *val = (u64)guc->submission_state.sched_disable_delay_ms;
+
+ return 0;
+}
+
+static int guc_sched_disable_delay_ms_set(void *data, u64 val)
+{
+ struct intel_guc *guc = data;
+
+ if (!intel_guc_submission_is_used(guc))
+ return -ENODEV;
+
+ /* clamp to a practical limit, 1 minute is reasonable for a longest delay */
+ guc->submission_state.sched_disable_delay_ms = min_t(u64, val, 60000);
+
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(guc_sched_disable_delay_ms_fops,
+ guc_sched_disable_delay_ms_get,
+ guc_sched_disable_delay_ms_set, "%lld\n");
+
+static int guc_sched_disable_gucid_threshold_get(void *data, u64 *val)
+{
+ struct intel_guc *guc = data;
+
+ if (!intel_guc_submission_is_used(guc))
+ return -ENODEV;
+
+ *val = guc->submission_state.sched_disable_gucid_threshold;
+ return 0;
+}
+
+static int guc_sched_disable_gucid_threshold_set(void *data, u64 val)
+{
+ struct intel_guc *guc = data;
+
+ if (!intel_guc_submission_is_used(guc))
+ return -ENODEV;
+
+ if (val > intel_guc_sched_disable_gucid_threshold_max(guc))
+ guc->submission_state.sched_disable_gucid_threshold =
+ intel_guc_sched_disable_gucid_threshold_max(guc);
+ else
+ guc->submission_state.sched_disable_gucid_threshold = val;
+
+ return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(guc_sched_disable_gucid_threshold_fops,
+ guc_sched_disable_gucid_threshold_get,
+ guc_sched_disable_gucid_threshold_set, "%lld\n");
+
void intel_guc_debugfs_register(struct intel_guc *guc, struct dentry *root)
{
static const struct intel_gt_debugfs_file files[] = {
{ "guc_info", &guc_info_fops, NULL },
{ "guc_registered_contexts", &guc_registered_contexts_fops, NULL },
{ "guc_slpc_info", &guc_slpc_info_fops, &intel_eval_slpc_support},
+ { "guc_sched_disable_delay_ms", &guc_sched_disable_delay_ms_fops, NULL },
+ { "guc_sched_disable_gucid_threshold", &guc_sched_disable_gucid_threshold_fops,
+ NULL },
};
if (!intel_guc_is_supported(guc))
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 a0372735cddb..5b86b2e286e0 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fw.c
@@ -10,12 +10,15 @@
*/
#include "gt/intel_gt.h"
+#include "gt/intel_gt_mcr.h"
#include "gt/intel_gt_regs.h"
#include "intel_guc_fw.h"
#include "i915_drv.h"
-static void guc_prepare_xfer(struct intel_uncore *uncore)
+static void guc_prepare_xfer(struct intel_gt *gt)
{
+ struct intel_uncore *uncore = gt->uncore;
+
u32 shim_flags = GUC_ENABLE_READ_CACHE_LOGIC |
GUC_ENABLE_READ_CACHE_FOR_SRAM_DATA |
GUC_ENABLE_READ_CACHE_FOR_WOPCM_DATA |
@@ -35,8 +38,9 @@ static void guc_prepare_xfer(struct intel_uncore *uncore)
if (GRAPHICS_VER(uncore->i915) == 9) {
/* DOP Clock Gating Enable for GuC clocks */
- intel_uncore_rmw(uncore, GEN7_MISCCPCTL,
- 0, GEN8_DOP_CLOCK_GATE_GUC_ENABLE);
+ intel_gt_mcr_multicast_write(gt, GEN8_MISCCPCTL,
+ GEN8_DOP_CLOCK_GATE_GUC_ENABLE |
+ intel_gt_mcr_read_any(gt, GEN8_MISCCPCTL));
/* allows for 5us (in 10ns units) before GT can go to RC6 */
intel_uncore_write(uncore, GUC_ARAT_C6DIS, 0x1FF);
@@ -168,7 +172,7 @@ int intel_guc_fw_upload(struct intel_guc *guc)
struct intel_uncore *uncore = gt->uncore;
int ret;
- guc_prepare_xfer(uncore);
+ guc_prepare_xfer(gt);
/*
* Note that GuC needs the CSS header plus uKernel code to be copied
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 323b055e5db9..4ae5fc2f6002 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h
@@ -47,7 +47,8 @@
#define GUC_VIDEOENHANCE_CLASS 2
#define GUC_BLITTER_CLASS 3
#define GUC_COMPUTE_CLASS 4
-#define GUC_LAST_ENGINE_CLASS GUC_COMPUTE_CLASS
+#define GUC_GSC_OTHER_CLASS 5
+#define GUC_LAST_ENGINE_CLASS GUC_GSC_OTHER_CLASS
#define GUC_MAX_ENGINE_CLASSES 16
#define GUC_MAX_INSTANCES_PER_CLASS 32
@@ -169,6 +170,7 @@ static u8 engine_class_guc_class_map[] = {
[COPY_ENGINE_CLASS] = GUC_BLITTER_CLASS,
[VIDEO_DECODE_CLASS] = GUC_VIDEO_CLASS,
[VIDEO_ENHANCEMENT_CLASS] = GUC_VIDEOENHANCE_CLASS,
+ [OTHER_CLASS] = GUC_GSC_OTHER_CLASS,
[COMPUTE_CLASS] = GUC_COMPUTE_CLASS,
};
@@ -178,12 +180,13 @@ static u8 guc_class_engine_class_map[] = {
[GUC_VIDEO_CLASS] = VIDEO_DECODE_CLASS,
[GUC_VIDEOENHANCE_CLASS] = VIDEO_ENHANCEMENT_CLASS,
[GUC_COMPUTE_CLASS] = COMPUTE_CLASS,
+ [GUC_GSC_OTHER_CLASS] = OTHER_CLASS,
};
static inline u8 engine_class_to_guc_class(u8 class)
{
BUILD_BUG_ON(ARRAY_SIZE(engine_class_guc_class_map) != MAX_ENGINE_CLASS + 1);
- GEM_BUG_ON(class > MAX_ENGINE_CLASS || class == OTHER_CLASS);
+ GEM_BUG_ON(class > MAX_ENGINE_CLASS);
return engine_class_guc_class_map[class];
}
@@ -290,6 +293,25 @@ struct guc_update_context_policy {
struct guc_klv_generic_dw_t klv[GUC_CONTEXT_POLICIES_KLV_NUM_IDS];
} __packed;
+/* Format of the UPDATE_SCHEDULING_POLICIES H2G data packet */
+struct guc_update_scheduling_policy_header {
+ u32 action;
+} __packed;
+
+/*
+ * Can't dynmically allocate memory for the scheduling policy KLV because
+ * it will be sent from within the reset path. Need a fixed size lump on
+ * the stack instead :(.
+ *
+ * Currently, there is only one KLV defined, which has 1 word of KL + 2 words of V.
+ */
+#define MAX_SCHEDULING_POLICY_SIZE 3
+
+struct guc_update_scheduling_policy {
+ struct guc_update_scheduling_policy_header header;
+ u32 data[MAX_SCHEDULING_POLICY_SIZE];
+} __packed;
+
#define GUC_POWER_UNSPECIFIED 0
#define GUC_POWER_D0 1
#define GUC_POWER_D1 2
@@ -298,6 +320,9 @@ struct guc_update_context_policy {
/* Scheduling policy settings */
+#define GLOBAL_SCHEDULE_POLICY_RC_YIELD_DURATION 100 /* in ms */
+#define GLOBAL_SCHEDULE_POLICY_RC_YIELD_RATIO 50 /* in percent */
+
#define GLOBAL_POLICY_MAX_NUM_WI 15
/* Don't reset an engine upon preemption failure */
@@ -305,6 +330,27 @@ struct guc_update_context_policy {
#define GLOBAL_POLICY_DEFAULT_DPC_PROMOTE_TIME_US 500000
+/*
+ * GuC converts the timeout to clock ticks internally. Different platforms have
+ * different GuC clocks. Thus, the maximum value before overflow is platform
+ * dependent. Current worst case scenario is about 110s. So, the spec says to
+ * limit to 100s to be safe.
+ */
+#define GUC_POLICY_MAX_EXEC_QUANTUM_US (100 * 1000 * 1000UL)
+#define GUC_POLICY_MAX_PREEMPT_TIMEOUT_US (100 * 1000 * 1000UL)
+
+static inline u32 guc_policy_max_exec_quantum_ms(void)
+{
+ BUILD_BUG_ON(GUC_POLICY_MAX_EXEC_QUANTUM_US >= UINT_MAX);
+ return GUC_POLICY_MAX_EXEC_QUANTUM_US / 1000;
+}
+
+static inline u32 guc_policy_max_preempt_timeout_ms(void)
+{
+ BUILD_BUG_ON(GUC_POLICY_MAX_PREEMPT_TIMEOUT_US >= UINT_MAX);
+ return GUC_POLICY_MAX_PREEMPT_TIMEOUT_US / 1000;
+}
+
struct guc_policies {
u32 submission_queue_depth[GUC_MAX_ENGINE_CLASSES];
/* In micro seconds. How much time to allow before DPC processing is
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
index 55d3ef93e86f..68331c538b0a 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
@@ -16,15 +16,15 @@
#if defined(CONFIG_DRM_I915_DEBUG_GUC)
#define GUC_LOG_DEFAULT_CRASH_BUFFER_SIZE SZ_2M
#define GUC_LOG_DEFAULT_DEBUG_BUFFER_SIZE SZ_16M
-#define GUC_LOG_DEFAULT_CAPTURE_BUFFER_SIZE SZ_4M
+#define GUC_LOG_DEFAULT_CAPTURE_BUFFER_SIZE SZ_1M
#elif defined(CONFIG_DRM_I915_DEBUG_GEM)
#define GUC_LOG_DEFAULT_CRASH_BUFFER_SIZE SZ_1M
#define GUC_LOG_DEFAULT_DEBUG_BUFFER_SIZE SZ_2M
-#define GUC_LOG_DEFAULT_CAPTURE_BUFFER_SIZE SZ_4M
+#define GUC_LOG_DEFAULT_CAPTURE_BUFFER_SIZE SZ_1M
#else
#define GUC_LOG_DEFAULT_CRASH_BUFFER_SIZE SZ_8K
#define GUC_LOG_DEFAULT_DEBUG_BUFFER_SIZE SZ_64K
-#define GUC_LOG_DEFAULT_CAPTURE_BUFFER_SIZE SZ_2M
+#define GUC_LOG_DEFAULT_CAPTURE_BUFFER_SIZE SZ_1M
#endif
static void guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log);
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
index 8f8dd05835c5..b5855091cf6a 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c
@@ -11,9 +11,20 @@
static bool __guc_rc_supported(struct intel_guc *guc)
{
+ struct intel_gt *gt = guc_to_gt(guc);
+
+ /*
+ * Wa_14017073508: mtl
+ * Do not enable gucrc to avoid additional interrupts which
+ * may disrupt pcode wa.
+ */
+ if (IS_MTL_GRAPHICS_STEP(gt->i915, P, STEP_A0, STEP_B0) &&
+ gt->type == GT_MEDIA)
+ return false;
+
/* GuC RC is unavailable for pre-Gen12 */
return guc->submission_supported &&
- GRAPHICS_VER(guc_to_gt(guc)->i915) >= 12;
+ GRAPHICS_VER(gt->i915) >= 12;
}
static bool __guc_rc_selected(struct intel_guc *guc)
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h
index a7092f711e9c..9915de32e894 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_reg.h
@@ -36,6 +36,7 @@
#define SOFT_SCRATCH_COUNT 16
#define GEN11_SOFT_SCRATCH(n) _MMIO(0x190240 + (n) * 4)
+#define MEDIA_SOFT_SCRATCH(n) _MMIO(0x190310 + (n) * 4)
#define GEN11_SOFT_SCRATCH_COUNT 4
#define UOS_RSA_SCRATCH(i) _MMIO(0xc200 + (i) * 4)
@@ -101,6 +102,7 @@
#define GUC_SEND_INTERRUPT _MMIO(0xc4c8)
#define GUC_SEND_TRIGGER (1<<0)
#define GEN11_GUC_HOST_INTERRUPT _MMIO(0x1901f0)
+#define MEDIA_GUC_HOST_INTERRUPT _MMIO(0x190304)
#define GEN12_GUC_SEM_INTR_ENABLES _MMIO(0xc71c)
#define GUC_SEM_INTR_ROUTE_TO_GUC BIT(31)
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 fdd895f73f9f..63464933cbce 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c
@@ -137,6 +137,17 @@ static int guc_action_slpc_set_param(struct intel_guc *guc, u8 id, u32 value)
return ret > 0 ? -EPROTO : ret;
}
+static int guc_action_slpc_unset_param(struct intel_guc *guc, u8 id)
+{
+ u32 request[] = {
+ GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST,
+ SLPC_EVENT(SLPC_EVENT_PARAMETER_UNSET, 1),
+ id,
+ };
+
+ return intel_guc_send(guc, request, ARRAY_SIZE(request));
+}
+
static bool slpc_is_running(struct intel_guc_slpc *slpc)
{
return slpc_get_state(slpc) == SLPC_GLOBAL_STATE_RUNNING;
@@ -190,6 +201,15 @@ static int slpc_set_param(struct intel_guc_slpc *slpc, u8 id, u32 value)
return ret;
}
+static int slpc_unset_param(struct intel_guc_slpc *slpc, u8 id)
+{
+ struct intel_guc *guc = slpc_to_guc(slpc);
+
+ GEM_BUG_ON(id >= SLPC_MAX_PARAM);
+
+ return guc_action_slpc_unset_param(guc, id);
+}
+
static int slpc_force_min_freq(struct intel_guc_slpc *slpc, u32 freq)
{
struct drm_i915_private *i915 = slpc_to_i915(slpc);
@@ -263,6 +283,7 @@ int intel_guc_slpc_init(struct intel_guc_slpc *slpc)
slpc->max_freq_softlimit = 0;
slpc->min_freq_softlimit = 0;
+ slpc->min_is_rpmax = false;
slpc->boost_freq = 0;
atomic_set(&slpc->num_waiters, 0);
@@ -588,6 +609,39 @@ static int slpc_set_softlimits(struct intel_guc_slpc *slpc)
return 0;
}
+static bool is_slpc_min_freq_rpmax(struct intel_guc_slpc *slpc)
+{
+ struct drm_i915_private *i915 = slpc_to_i915(slpc);
+ int slpc_min_freq;
+ int ret;
+
+ ret = intel_guc_slpc_get_min_freq(slpc, &slpc_min_freq);
+ if (ret) {
+ drm_err(&i915->drm,
+ "Failed to get min freq: (%d)\n",
+ ret);
+ return false;
+ }
+
+ if (slpc_min_freq == SLPC_MAX_FREQ_MHZ)
+ return true;
+ else
+ return false;
+}
+
+static void update_server_min_softlimit(struct intel_guc_slpc *slpc)
+{
+ /* For server parts, SLPC min will be at RPMax.
+ * Use min softlimit to clamp it to RP0 instead.
+ */
+ if (!slpc->min_freq_softlimit &&
+ is_slpc_min_freq_rpmax(slpc)) {
+ slpc->min_is_rpmax = true;
+ slpc->min_freq_softlimit = slpc->rp0_freq;
+ (slpc_to_gt(slpc))->defaults.min_freq = slpc->min_freq_softlimit;
+ }
+}
+
static int slpc_use_fused_rp0(struct intel_guc_slpc *slpc)
{
/* Force SLPC to used platform rp0 */
@@ -610,6 +664,52 @@ static void slpc_get_rp_values(struct intel_guc_slpc *slpc)
slpc->boost_freq = slpc->rp0_freq;
}
+/**
+ * intel_guc_slpc_override_gucrc_mode() - override GUCRC mode
+ * @slpc: pointer to intel_guc_slpc.
+ * @mode: new value of the mode.
+ *
+ * This function will override the GUCRC mode.
+ *
+ * Return: 0 on success, non-zero error code on failure.
+ */
+int intel_guc_slpc_override_gucrc_mode(struct intel_guc_slpc *slpc, u32 mode)
+{
+ int ret;
+ struct drm_i915_private *i915 = slpc_to_i915(slpc);
+ intel_wakeref_t wakeref;
+
+ if (mode >= SLPC_GUCRC_MODE_MAX)
+ return -EINVAL;
+
+ with_intel_runtime_pm(&i915->runtime_pm, wakeref) {
+ ret = slpc_set_param(slpc, SLPC_PARAM_PWRGATE_RC_MODE, mode);
+ if (ret)
+ drm_err(&i915->drm,
+ "Override gucrc mode %d failed %d\n",
+ mode, ret);
+ }
+
+ return ret;
+}
+
+int intel_guc_slpc_unset_gucrc_mode(struct intel_guc_slpc *slpc)
+{
+ struct drm_i915_private *i915 = slpc_to_i915(slpc);
+ intel_wakeref_t wakeref;
+ int ret = 0;
+
+ with_intel_runtime_pm(&i915->runtime_pm, wakeref) {
+ ret = slpc_unset_param(slpc, SLPC_PARAM_PWRGATE_RC_MODE);
+ if (ret)
+ drm_err(&i915->drm,
+ "Unsetting gucrc mode failed %d\n",
+ ret);
+ }
+
+ return ret;
+}
+
/*
* intel_guc_slpc_enable() - Start SLPC
* @slpc: pointer to intel_guc_slpc.
@@ -647,6 +747,9 @@ int intel_guc_slpc_enable(struct intel_guc_slpc *slpc)
slpc_get_rp_values(slpc);
+ /* Handle the case where min=max=RPmax */
+ update_server_min_softlimit(slpc);
+
/* Set SLPC max limit to RP0 */
ret = slpc_use_fused_rp0(slpc);
if (unlikely(ret)) {
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 82a98f78f96c..17ed515f6a85 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.h
@@ -9,6 +9,8 @@
#include "intel_guc_submission.h"
#include "intel_guc_slpc_types.h"
+#define SLPC_MAX_FREQ_MHZ 4250
+
struct intel_gt;
struct drm_printer;
@@ -42,5 +44,7 @@ int intel_guc_slpc_set_media_ratio_mode(struct intel_guc_slpc *slpc, u32 val);
void intel_guc_pm_intrmsk_enable(struct intel_gt *gt);
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);
#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 73d208123528..a6ef53b04e04 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
@@ -19,6 +19,9 @@ struct intel_guc_slpc {
bool supported;
bool selected;
+ /* Indicates this is a server part */
+ bool min_is_rpmax;
+
/* platform frequency limits */
u32 min_freq;
u32 rp0_freq;
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 1db59eeb34db..0a42f1807f52 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
@@ -6,6 +6,7 @@
#include <linux/circ_buf.h>
#include "gem/i915_gem_context.h"
+#include "gem/i915_gem_lmem.h"
#include "gt/gen8_engine_cs.h"
#include "gt/intel_breadcrumbs.h"
#include "gt/intel_context.h"
@@ -29,6 +30,7 @@
#include "intel_guc_submission.h"
#include "i915_drv.h"
+#include "i915_reg.h"
#include "i915_trace.h"
/**
@@ -65,7 +67,13 @@
* corresponding G2H returns indicating the scheduling disable operation has
* completed it is safe to unpin the context. While a disable is in flight it
* isn't safe to resubmit the context so a fence is used to stall all future
- * requests of that context until the G2H is returned.
+ * requests of that context until the G2H is returned. Because this interaction
+ * with the GuC takes a non-zero amount of time we delay the disabling of
+ * scheduling after the pin count goes to zero by a configurable period of time
+ * (see SCHED_DISABLE_DELAY_MS). The thought is this gives the user a window of
+ * time to resubmit something on the context before doing this costly operation.
+ * This delay is only done if the context isn't closed and the guc_id usage is
+ * less than a threshold (see NUM_SCHED_DISABLE_GUC_IDS_THRESHOLD).
*
* Context deregistration:
* Before a context can be destroyed or if we steal its guc_id we must
@@ -163,7 +171,8 @@ guc_create_parallel(struct intel_engine_cs **engines,
#define SCHED_STATE_PENDING_ENABLE BIT(5)
#define SCHED_STATE_REGISTERED BIT(6)
#define SCHED_STATE_POLICY_REQUIRED BIT(7)
-#define SCHED_STATE_BLOCKED_SHIFT 8
+#define SCHED_STATE_CLOSED BIT(8)
+#define SCHED_STATE_BLOCKED_SHIFT 9
#define SCHED_STATE_BLOCKED BIT(SCHED_STATE_BLOCKED_SHIFT)
#define SCHED_STATE_BLOCKED_MASK (0xfff << SCHED_STATE_BLOCKED_SHIFT)
@@ -173,12 +182,20 @@ static inline void init_sched_state(struct intel_context *ce)
ce->guc_state.sched_state &= SCHED_STATE_BLOCKED_MASK;
}
+/*
+ * Kernel contexts can have SCHED_STATE_REGISTERED after suspend.
+ * A context close can race with the submission path, so SCHED_STATE_CLOSED
+ * can be set immediately before we try to register.
+ */
+#define SCHED_STATE_VALID_INIT \
+ (SCHED_STATE_BLOCKED_MASK | \
+ SCHED_STATE_CLOSED | \
+ SCHED_STATE_REGISTERED)
+
__maybe_unused
static bool sched_state_is_init(struct intel_context *ce)
{
- /* Kernel contexts can have SCHED_STATE_REGISTERED after suspend. */
- return !(ce->guc_state.sched_state &
- ~(SCHED_STATE_BLOCKED_MASK | SCHED_STATE_REGISTERED));
+ return !(ce->guc_state.sched_state & ~SCHED_STATE_VALID_INIT);
}
static inline bool
@@ -319,6 +336,17 @@ static inline void clr_context_policy_required(struct intel_context *ce)
ce->guc_state.sched_state &= ~SCHED_STATE_POLICY_REQUIRED;
}
+static inline bool context_close_done(struct intel_context *ce)
+{
+ return ce->guc_state.sched_state & SCHED_STATE_CLOSED;
+}
+
+static inline void set_context_close_done(struct intel_context *ce)
+{
+ lockdep_assert_held(&ce->guc_state.lock);
+ ce->guc_state.sched_state |= SCHED_STATE_CLOSED;
+}
+
static inline u32 context_blocked(struct intel_context *ce)
{
return (ce->guc_state.sched_state & SCHED_STATE_BLOCKED_MASK) >>
@@ -343,25 +371,6 @@ static inline void decr_context_blocked(struct intel_context *ce)
ce->guc_state.sched_state -= SCHED_STATE_BLOCKED;
}
-static inline bool context_has_committed_requests(struct intel_context *ce)
-{
- return !!ce->guc_state.number_committed_requests;
-}
-
-static inline void incr_context_committed_requests(struct intel_context *ce)
-{
- lockdep_assert_held(&ce->guc_state.lock);
- ++ce->guc_state.number_committed_requests;
- GEM_BUG_ON(ce->guc_state.number_committed_requests < 0);
-}
-
-static inline void decr_context_committed_requests(struct intel_context *ce)
-{
- lockdep_assert_held(&ce->guc_state.lock);
- --ce->guc_state.number_committed_requests;
- GEM_BUG_ON(ce->guc_state.number_committed_requests < 0);
-}
-
static struct intel_context *
request_to_scheduling_context(struct i915_request *rq)
{
@@ -1067,6 +1076,12 @@ static void scrub_guc_desc_for_outstanding_g2h(struct intel_guc *guc)
xa_unlock(&guc->context_lookup);
+ if (test_bit(CONTEXT_GUC_INIT, &ce->flags) &&
+ (cancel_delayed_work(&ce->guc_state.sched_disable_delay_work))) {
+ /* successful cancel so jump straight to close it */
+ intel_context_sched_disable_unpin(ce);
+ }
+
spin_lock(&ce->guc_state.lock);
/*
@@ -1387,7 +1402,9 @@ static void guc_timestamp_ping(struct work_struct *wrk)
/*
* Synchronize with gt reset to make sure the worker does not
- * corrupt the engine/guc stats.
+ * corrupt the engine/guc stats. NB: can't actually block waiting
+ * for a reset to complete as the reset requires flushing out
+ * this worker thread if started. So waiting would deadlock.
*/
ret = intel_gt_reset_trylock(gt, &srcu);
if (ret)
@@ -1994,6 +2011,9 @@ static int new_guc_id(struct intel_guc *guc, struct intel_context *ce)
if (unlikely(ret < 0))
return ret;
+ if (!intel_context_is_parent(ce))
+ ++guc->submission_state.guc_ids_in_use;
+
ce->guc_id.id = ret;
return 0;
}
@@ -2003,14 +2023,16 @@ static void __release_guc_id(struct intel_guc *guc, struct intel_context *ce)
GEM_BUG_ON(intel_context_is_child(ce));
if (!context_guc_id_invalid(ce)) {
- if (intel_context_is_parent(ce))
+ if (intel_context_is_parent(ce)) {
bitmap_release_region(guc->submission_state.guc_ids_bitmap,
ce->guc_id.id,
order_base_2(ce->parallel.number_children
+ 1));
- else
+ } else {
+ --guc->submission_state.guc_ids_in_use;
ida_simple_remove(&guc->submission_state.guc_ids,
ce->guc_id.id);
+ }
clr_ctx_id_mapping(guc, ce->guc_id.id);
set_context_guc_id_invalid(ce);
}
@@ -2429,6 +2451,10 @@ static int guc_context_policy_init_v70(struct intel_context *ce, bool loop)
int ret;
/* NB: For both of these, zero means disabled. */
+ GEM_BUG_ON(overflows_type(engine->props.timeslice_duration_ms * 1000,
+ execution_quantum));
+ GEM_BUG_ON(overflows_type(engine->props.preempt_timeout_ms * 1000,
+ preemption_timeout));
execution_quantum = engine->props.timeslice_duration_ms * 1000;
preemption_timeout = engine->props.preempt_timeout_ms * 1000;
@@ -2462,6 +2488,10 @@ static void guc_context_policy_init_v69(struct intel_engine_cs *engine,
desc->policy_flags |= CONTEXT_POLICY_FLAG_PREEMPT_TO_IDLE_V69;
/* NB: For both of these, zero means disabled. */
+ GEM_BUG_ON(overflows_type(engine->props.timeslice_duration_ms * 1000,
+ desc->execution_quantum));
+ GEM_BUG_ON(overflows_type(engine->props.preempt_timeout_ms * 1000,
+ desc->preemption_timeout));
desc->execution_quantum = engine->props.timeslice_duration_ms * 1000;
desc->preemption_timeout = engine->props.preempt_timeout_ms * 1000;
}
@@ -2998,41 +3028,104 @@ guc_context_revoke(struct intel_context *ce, struct i915_request *rq,
}
}
-static void guc_context_sched_disable(struct intel_context *ce)
+static void do_sched_disable(struct intel_guc *guc, struct intel_context *ce,
+ unsigned long flags)
+ __releases(ce->guc_state.lock)
{
- struct intel_guc *guc = ce_to_guc(ce);
- unsigned long flags;
struct intel_runtime_pm *runtime_pm = &ce->engine->gt->i915->runtime_pm;
intel_wakeref_t wakeref;
u16 guc_id;
+ lockdep_assert_held(&ce->guc_state.lock);
+ guc_id = prep_context_pending_disable(ce);
+
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+
+ with_intel_runtime_pm(runtime_pm, wakeref)
+ __guc_context_sched_disable(guc, ce, guc_id);
+}
+
+static bool bypass_sched_disable(struct intel_guc *guc,
+ struct intel_context *ce)
+{
+ lockdep_assert_held(&ce->guc_state.lock);
GEM_BUG_ON(intel_context_is_child(ce));
+ if (submission_disabled(guc) || context_guc_id_invalid(ce) ||
+ !ctx_id_mapped(guc, ce->guc_id.id)) {
+ clr_context_enabled(ce);
+ return true;
+ }
+
+ return !context_enabled(ce);
+}
+
+static void __delay_sched_disable(struct work_struct *wrk)
+{
+ struct intel_context *ce =
+ container_of(wrk, typeof(*ce), guc_state.sched_disable_delay_work.work);
+ struct intel_guc *guc = ce_to_guc(ce);
+ unsigned long flags;
+
spin_lock_irqsave(&ce->guc_state.lock, flags);
+ if (bypass_sched_disable(guc, ce)) {
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+ intel_context_sched_disable_unpin(ce);
+ } else {
+ do_sched_disable(guc, ce, flags);
+ }
+}
+
+static bool guc_id_pressure(struct intel_guc *guc, struct intel_context *ce)
+{
/*
- * We have to check if the context has been disabled by another thread,
- * check if submssion has been disabled to seal a race with reset and
- * finally check if any more requests have been committed to the
- * context ensursing that a request doesn't slip through the
- * 'context_pending_disable' fence.
+ * parent contexts are perma-pinned, if we are unpinning do schedule
+ * disable immediately.
*/
- if (unlikely(!context_enabled(ce) || submission_disabled(guc) ||
- context_has_committed_requests(ce))) {
- clr_context_enabled(ce);
+ if (intel_context_is_parent(ce))
+ return true;
+
+ /*
+ * If we are beyond the threshold for avail guc_ids, do schedule disable immediately.
+ */
+ return guc->submission_state.guc_ids_in_use >
+ guc->submission_state.sched_disable_gucid_threshold;
+}
+
+static void guc_context_sched_disable(struct intel_context *ce)
+{
+ struct intel_guc *guc = ce_to_guc(ce);
+ u64 delay = guc->submission_state.sched_disable_delay_ms;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ce->guc_state.lock, flags);
+
+ if (bypass_sched_disable(guc, ce)) {
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+ intel_context_sched_disable_unpin(ce);
+ } else if (!intel_context_is_closed(ce) && !guc_id_pressure(guc, ce) &&
+ delay) {
spin_unlock_irqrestore(&ce->guc_state.lock, flags);
- goto unpin;
+ mod_delayed_work(system_unbound_wq,
+ &ce->guc_state.sched_disable_delay_work,
+ msecs_to_jiffies(delay));
+ } else {
+ do_sched_disable(guc, ce, flags);
}
- guc_id = prep_context_pending_disable(ce);
+}
- spin_unlock_irqrestore(&ce->guc_state.lock, flags);
+static void guc_context_close(struct intel_context *ce)
+{
+ unsigned long flags;
- with_intel_runtime_pm(runtime_pm, wakeref)
- __guc_context_sched_disable(guc, ce, guc_id);
+ if (test_bit(CONTEXT_GUC_INIT, &ce->flags) &&
+ cancel_delayed_work(&ce->guc_state.sched_disable_delay_work))
+ __delay_sched_disable(&ce->guc_state.sched_disable_delay_work.work);
- return;
-unpin:
- intel_context_sched_disable_unpin(ce);
+ spin_lock_irqsave(&ce->guc_state.lock, flags);
+ set_context_close_done(ce);
+ spin_unlock_irqrestore(&ce->guc_state.lock, flags);
}
static inline void guc_lrc_desc_unpin(struct intel_context *ce)
@@ -3071,7 +3164,6 @@ static void __guc_context_destroy(struct intel_context *ce)
ce->guc_state.prio_count[GUC_CLIENT_PRIORITY_HIGH] ||
ce->guc_state.prio_count[GUC_CLIENT_PRIORITY_KMD_NORMAL] ||
ce->guc_state.prio_count[GUC_CLIENT_PRIORITY_NORMAL]);
- GEM_BUG_ON(ce->guc_state.number_committed_requests);
lrc_fini(ce);
intel_context_fini(ce);
@@ -3340,8 +3432,6 @@ static void remove_from_context(struct i915_request *rq)
guc_prio_fini(rq, ce);
- decr_context_committed_requests(ce);
-
spin_unlock_irq(&ce->guc_state.lock);
atomic_dec(&ce->guc_id.ref);
@@ -3351,6 +3441,8 @@ static void remove_from_context(struct i915_request *rq)
static const struct intel_context_ops guc_context_ops = {
.alloc = guc_context_alloc,
+ .close = guc_context_close,
+
.pre_pin = guc_context_pre_pin,
.pin = guc_context_pin,
.unpin = guc_context_unpin,
@@ -3433,6 +3525,10 @@ static void guc_context_init(struct intel_context *ce)
rcu_read_unlock();
ce->guc_state.prio = map_i915_prio_to_guc_prio(prio);
+
+ INIT_DELAYED_WORK(&ce->guc_state.sched_disable_delay_work,
+ __delay_sched_disable);
+
set_bit(CONTEXT_GUC_INIT, &ce->flags);
}
@@ -3471,6 +3567,26 @@ static int guc_request_alloc(struct i915_request *rq)
guc_context_init(ce);
/*
+ * If the context gets closed while the execbuf is ongoing, the context
+ * close code will race with the below code to cancel the delayed work.
+ * If the context close wins the race and cancels the work, it will
+ * immediately call the sched disable (see guc_context_close), so there
+ * is a chance we can get past this check while the sched_disable code
+ * is being executed. To make sure that code completes before we check
+ * the status further down, we wait for the close process to complete.
+ * Else, this code path could send a request down thinking that the
+ * context is still in a schedule-enable mode while the GuC ends up
+ * dropping the request completely because the disable did go from the
+ * context_close path right to GuC just prior. In the event the CT is
+ * full, we could potentially need to wait up to 1.5 seconds.
+ */
+ if (cancel_delayed_work_sync(&ce->guc_state.sched_disable_delay_work))
+ intel_context_sched_disable_unpin(ce);
+ else if (intel_context_is_closed(ce))
+ if (wait_for(context_close_done(ce), 1500))
+ drm_warn(&guc_to_gt(guc)->i915->drm,
+ "timed out waiting on context sched close before realloc\n");
+ /*
* Call pin_guc_id here rather than in the pinning step as with
* dma_resv, contexts can be repeatedly pinned / unpinned trashing the
* guc_id and creating horrible race conditions. This is especially bad
@@ -3524,7 +3640,6 @@ out:
list_add_tail(&rq->guc_fence_link, &ce->guc_state.fences);
}
- incr_context_committed_requests(ce);
spin_unlock_irqrestore(&ce->guc_state.lock, flags);
return 0;
@@ -3600,6 +3715,8 @@ static int guc_virtual_context_alloc(struct intel_context *ce)
static const struct intel_context_ops virtual_guc_context_ops = {
.alloc = guc_virtual_context_alloc,
+ .close = guc_context_close,
+
.pre_pin = guc_virtual_context_pre_pin,
.pin = guc_virtual_context_pin,
.unpin = guc_virtual_context_unpin,
@@ -3689,6 +3806,8 @@ static void guc_child_context_destroy(struct kref *kref)
static const struct intel_context_ops virtual_parent_context_ops = {
.alloc = guc_virtual_context_alloc,
+ .close = guc_context_close,
+
.pre_pin = guc_context_pre_pin,
.pin = guc_parent_context_pin,
.unpin = guc_parent_context_unpin,
@@ -3995,6 +4114,9 @@ static inline void guc_kernel_context_pin(struct intel_guc *guc,
if (context_guc_id_invalid(ce))
pin_guc_id(guc, ce);
+ if (!test_bit(CONTEXT_GUC_INIT, &ce->flags))
+ guc_context_init(ce);
+
try_context_registration(ce, true);
}
@@ -4093,7 +4215,7 @@ static void guc_default_vfuncs(struct intel_engine_cs *engine)
engine->emit_bb_start = gen8_emit_bb_start;
if (GRAPHICS_VER_FULL(engine->i915) >= IP_VER(12, 50))
- engine->emit_bb_start = gen125_emit_bb_start;
+ engine->emit_bb_start = xehp_emit_bb_start;
}
static void rcs_submission_override(struct intel_engine_cs *engine)
@@ -4177,6 +4299,98 @@ int intel_guc_submission_setup(struct intel_engine_cs *engine)
return 0;
}
+struct scheduling_policy {
+ /* internal data */
+ u32 max_words, num_words;
+ u32 count;
+ /* API data */
+ struct guc_update_scheduling_policy h2g;
+};
+
+static u32 __guc_scheduling_policy_action_size(struct scheduling_policy *policy)
+{
+ u32 *start = (void *)&policy->h2g;
+ u32 *end = policy->h2g.data + policy->num_words;
+ size_t delta = end - start;
+
+ return delta;
+}
+
+static struct scheduling_policy *__guc_scheduling_policy_start_klv(struct scheduling_policy *policy)
+{
+ policy->h2g.header.action = INTEL_GUC_ACTION_UPDATE_SCHEDULING_POLICIES_KLV;
+ policy->max_words = ARRAY_SIZE(policy->h2g.data);
+ policy->num_words = 0;
+ policy->count = 0;
+
+ return policy;
+}
+
+static void __guc_scheduling_policy_add_klv(struct scheduling_policy *policy,
+ u32 action, u32 *data, u32 len)
+{
+ u32 *klv_ptr = policy->h2g.data + policy->num_words;
+
+ GEM_BUG_ON((policy->num_words + 1 + len) > policy->max_words);
+ *(klv_ptr++) = FIELD_PREP(GUC_KLV_0_KEY, action) |
+ FIELD_PREP(GUC_KLV_0_LEN, len);
+ memcpy(klv_ptr, data, sizeof(u32) * len);
+ policy->num_words += 1 + len;
+ policy->count++;
+}
+
+static int __guc_action_set_scheduling_policies(struct intel_guc *guc,
+ struct scheduling_policy *policy)
+{
+ int ret;
+
+ ret = intel_guc_send(guc, (u32 *)&policy->h2g,
+ __guc_scheduling_policy_action_size(policy));
+ if (ret < 0)
+ return ret;
+
+ if (ret != policy->count) {
+ drm_warn(&guc_to_gt(guc)->i915->drm, "GuC global scheduler policy processed %d of %d KLVs!",
+ ret, policy->count);
+ if (ret > policy->count)
+ return -EPROTO;
+ }
+
+ return 0;
+}
+
+static int guc_init_global_schedule_policy(struct intel_guc *guc)
+{
+ struct scheduling_policy policy;
+ struct intel_gt *gt = guc_to_gt(guc);
+ intel_wakeref_t wakeref;
+ int ret = 0;
+
+ if (GET_UC_VER(guc) < MAKE_UC_VER(70, 3, 0))
+ return 0;
+
+ __guc_scheduling_policy_start_klv(&policy);
+
+ with_intel_runtime_pm(&gt->i915->runtime_pm, wakeref) {
+ u32 yield[] = {
+ GLOBAL_SCHEDULE_POLICY_RC_YIELD_DURATION,
+ GLOBAL_SCHEDULE_POLICY_RC_YIELD_RATIO,
+ };
+
+ __guc_scheduling_policy_add_klv(&policy,
+ GUC_SCHEDULING_POLICIES_KLV_ID_RENDER_COMPUTE_YIELD,
+ yield, ARRAY_SIZE(yield));
+
+ ret = __guc_action_set_scheduling_policies(guc, &policy);
+ if (ret)
+ i915_probe_error(gt->i915,
+ "Failed to configure global scheduling policies: %pe!\n",
+ ERR_PTR(ret));
+ }
+
+ return ret;
+}
+
void intel_guc_submission_enable(struct intel_guc *guc)
{
struct intel_gt *gt = guc_to_gt(guc);
@@ -4189,6 +4403,7 @@ void intel_guc_submission_enable(struct intel_guc *guc)
guc_init_lrc_mapping(guc);
guc_init_engine_stats(guc);
+ guc_init_global_schedule_policy(guc);
}
void intel_guc_submission_disable(struct intel_guc *guc)
@@ -4219,6 +4434,26 @@ static bool __guc_submission_selected(struct intel_guc *guc)
return i915->params.enable_guc & ENABLE_GUC_SUBMISSION;
}
+int intel_guc_sched_disable_gucid_threshold_max(struct intel_guc *guc)
+{
+ return guc->submission_state.num_guc_ids - NUMBER_MULTI_LRC_GUC_ID(guc);
+}
+
+/*
+ * This default value of 33 milisecs (+1 milisec round up) ensures 30fps or higher
+ * workloads are able to enjoy the latency reduction when delaying the schedule-disable
+ * operation. This matches the 30fps game-render + encode (real world) workload this
+ * knob was tested against.
+ */
+#define SCHED_DISABLE_DELAY_MS 34
+
+/*
+ * A threshold of 75% is a reasonable starting point considering that real world apps
+ * generally don't get anywhere near this.
+ */
+#define NUM_SCHED_DISABLE_GUCIDS_DEFAULT_THRESHOLD(__guc) \
+ (((intel_guc_sched_disable_gucid_threshold_max(guc)) * 3) / 4)
+
void intel_guc_submission_init_early(struct intel_guc *guc)
{
xa_init_flags(&guc->context_lookup, XA_FLAGS_LOCK_IRQ);
@@ -4235,7 +4470,10 @@ void intel_guc_submission_init_early(struct intel_guc *guc)
spin_lock_init(&guc->timestamp.lock);
INIT_DELAYED_WORK(&guc->timestamp.work, guc_timestamp_ping);
+ guc->submission_state.sched_disable_delay_ms = SCHED_DISABLE_DELAY_MS;
guc->submission_state.num_guc_ids = GUC_MAX_CONTEXT_ID;
+ guc->submission_state.sched_disable_gucid_threshold =
+ NUM_SCHED_DISABLE_GUCIDS_DEFAULT_THRESHOLD(guc);
guc->submission_supported = __guc_submission_supported(guc);
guc->submission_selected = __guc_submission_selected(guc);
}
@@ -4669,7 +4907,7 @@ void intel_guc_submission_print_info(struct intel_guc *guc,
drm_printf(p, "GuC Number Outstanding Submission G2H: %u\n",
atomic_read(&guc->outstanding_submission_g2h));
- drm_printf(p, "GuC tasklet count: %u\n\n",
+ drm_printf(p, "GuC tasklet count: %u\n",
atomic_read(&sched_engine->tasklet.count));
spin_lock_irqsave(&sched_engine->lock, flags);
@@ -4717,7 +4955,7 @@ static inline void guc_log_context(struct drm_printer *p,
atomic_read(&ce->pin_count));
drm_printf(p, "\t\tGuC ID Ref Count: %u\n",
atomic_read(&ce->guc_id.ref));
- drm_printf(p, "\t\tSchedule State: 0x%x\n\n",
+ drm_printf(p, "\t\tSchedule State: 0x%x\n",
ce->guc_state.sched_state);
}
@@ -4746,7 +4984,7 @@ void intel_guc_submission_print_context_info(struct intel_guc *guc,
READ_ONCE(*ce->parallel.guc.wq_head));
drm_printf(p, "\t\tWQI Tail: %u\n",
READ_ONCE(*ce->parallel.guc.wq_tail));
- drm_printf(p, "\t\tWQI Status: %u\n\n",
+ drm_printf(p, "\t\tWQI Status: %u\n",
READ_ONCE(*ce->parallel.guc.wq_status));
}
@@ -4754,7 +4992,7 @@ void intel_guc_submission_print_context_info(struct intel_guc *guc,
emit_bb_start_parent_no_preempt_mid_batch) {
u8 i;
- drm_printf(p, "\t\tChildren Go: %u\n\n",
+ drm_printf(p, "\t\tChildren Go: %u\n",
get_children_go_value(ce));
for (i = 0; i < ce->parallel.number_children; ++i)
drm_printf(p, "\t\tChildren Join: %u\n",
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.c b/drivers/gpu/drm/i915/gt/uc/intel_huc.c
index 3bb8838e325a..410905da8e97 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_huc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.c
@@ -10,6 +10,9 @@
#include "intel_huc.h"
#include "i915_drv.h"
+#include <linux/device/bus.h>
+#include <linux/mei_aux.h>
+
/**
* DOC: HuC
*
@@ -42,12 +45,240 @@
* HuC-specific commands.
*/
+/*
+ * MEI-GSC load is an async process. The probing of the exposed aux device
+ * (see intel_gsc.c) usually happens a few seconds after i915 probe, depending
+ * on when the kernel schedules it. Unless something goes terribly wrong, we're
+ * guaranteed for this to happen during boot, so the big timeout is a safety net
+ * that we never expect to need.
+ * MEI-PXP + HuC load usually takes ~300ms, but if the GSC needs to be resumed
+ * and/or reset, this can take longer. Note that the kernel might schedule
+ * other work between the i915 init/resume and the MEI one, which can add to
+ * the delay.
+ */
+#define GSC_INIT_TIMEOUT_MS 10000
+#define PXP_INIT_TIMEOUT_MS 5000
+
+static int sw_fence_dummy_notify(struct i915_sw_fence *sf,
+ enum i915_sw_fence_notify state)
+{
+ return NOTIFY_DONE;
+}
+
+static void __delayed_huc_load_complete(struct intel_huc *huc)
+{
+ if (!i915_sw_fence_done(&huc->delayed_load.fence))
+ i915_sw_fence_complete(&huc->delayed_load.fence);
+}
+
+static void delayed_huc_load_complete(struct intel_huc *huc)
+{
+ hrtimer_cancel(&huc->delayed_load.timer);
+ __delayed_huc_load_complete(huc);
+}
+
+static void __gsc_init_error(struct intel_huc *huc)
+{
+ huc->delayed_load.status = INTEL_HUC_DELAYED_LOAD_ERROR;
+ __delayed_huc_load_complete(huc);
+}
+
+static void gsc_init_error(struct intel_huc *huc)
+{
+ hrtimer_cancel(&huc->delayed_load.timer);
+ __gsc_init_error(huc);
+}
+
+static void gsc_init_done(struct intel_huc *huc)
+{
+ hrtimer_cancel(&huc->delayed_load.timer);
+
+ /* MEI-GSC init is done, now we wait for MEI-PXP to bind */
+ huc->delayed_load.status = INTEL_HUC_WAITING_ON_PXP;
+ if (!i915_sw_fence_done(&huc->delayed_load.fence))
+ hrtimer_start(&huc->delayed_load.timer,
+ ms_to_ktime(PXP_INIT_TIMEOUT_MS),
+ HRTIMER_MODE_REL);
+}
+
+static enum hrtimer_restart huc_delayed_load_timer_callback(struct hrtimer *hrtimer)
+{
+ struct intel_huc *huc = container_of(hrtimer, struct intel_huc, delayed_load.timer);
+
+ if (!intel_huc_is_authenticated(huc)) {
+ if (huc->delayed_load.status == INTEL_HUC_WAITING_ON_GSC)
+ drm_notice(&huc_to_gt(huc)->i915->drm,
+ "timed out waiting for MEI GSC init to load HuC\n");
+ else if (huc->delayed_load.status == INTEL_HUC_WAITING_ON_PXP)
+ drm_notice(&huc_to_gt(huc)->i915->drm,
+ "timed out waiting for MEI PXP init to load HuC\n");
+ else
+ MISSING_CASE(huc->delayed_load.status);
+
+ __gsc_init_error(huc);
+ }
+
+ return HRTIMER_NORESTART;
+}
+
+static void huc_delayed_load_start(struct intel_huc *huc)
+{
+ ktime_t delay;
+
+ GEM_BUG_ON(intel_huc_is_authenticated(huc));
+
+ /*
+ * On resume we don't have to wait for MEI-GSC to be re-probed, but we
+ * do need to wait for MEI-PXP to reset & re-bind
+ */
+ switch (huc->delayed_load.status) {
+ case INTEL_HUC_WAITING_ON_GSC:
+ delay = ms_to_ktime(GSC_INIT_TIMEOUT_MS);
+ break;
+ case INTEL_HUC_WAITING_ON_PXP:
+ delay = ms_to_ktime(PXP_INIT_TIMEOUT_MS);
+ break;
+ default:
+ gsc_init_error(huc);
+ return;
+ }
+
+ /*
+ * This fence is always complete unless we're waiting for the
+ * GSC device to come up to load the HuC. We arm the fence here
+ * and complete it when we confirm that the HuC is loaded from
+ * the PXP bind callback.
+ */
+ GEM_BUG_ON(!i915_sw_fence_done(&huc->delayed_load.fence));
+ i915_sw_fence_fini(&huc->delayed_load.fence);
+ i915_sw_fence_reinit(&huc->delayed_load.fence);
+ i915_sw_fence_await(&huc->delayed_load.fence);
+ i915_sw_fence_commit(&huc->delayed_load.fence);
+
+ hrtimer_start(&huc->delayed_load.timer, delay, HRTIMER_MODE_REL);
+}
+
+static int gsc_notifier(struct notifier_block *nb, unsigned long action, void *data)
+{
+ struct device *dev = data;
+ struct intel_huc *huc = container_of(nb, struct intel_huc, delayed_load.nb);
+ struct intel_gsc_intf *intf = &huc_to_gt(huc)->gsc.intf[0];
+
+ if (!intf->adev || &intf->adev->aux_dev.dev != dev)
+ return 0;
+
+ switch (action) {
+ case BUS_NOTIFY_BOUND_DRIVER: /* mei driver bound to aux device */
+ gsc_init_done(huc);
+ break;
+
+ case BUS_NOTIFY_DRIVER_NOT_BOUND: /* mei driver fails to be bound */
+ case BUS_NOTIFY_UNBIND_DRIVER: /* mei driver about to be unbound */
+ drm_info(&huc_to_gt(huc)->i915->drm,
+ "mei driver not bound, disabling HuC load\n");
+ gsc_init_error(huc);
+ break;
+ }
+
+ return 0;
+}
+
+void intel_huc_register_gsc_notifier(struct intel_huc *huc, struct bus_type *bus)
+{
+ int ret;
+
+ if (!intel_huc_is_loaded_by_gsc(huc))
+ return;
+
+ huc->delayed_load.nb.notifier_call = gsc_notifier;
+ ret = bus_register_notifier(bus, &huc->delayed_load.nb);
+ if (ret) {
+ drm_err(&huc_to_gt(huc)->i915->drm,
+ "failed to register GSC notifier\n");
+ huc->delayed_load.nb.notifier_call = NULL;
+ gsc_init_error(huc);
+ }
+}
+
+void intel_huc_unregister_gsc_notifier(struct intel_huc *huc, struct bus_type *bus)
+{
+ if (!huc->delayed_load.nb.notifier_call)
+ return;
+
+ delayed_huc_load_complete(huc);
+
+ bus_unregister_notifier(bus, &huc->delayed_load.nb);
+ huc->delayed_load.nb.notifier_call = NULL;
+}
+
+static void delayed_huc_load_init(struct intel_huc *huc)
+{
+ /*
+ * Initialize fence to be complete as this is expected to be complete
+ * unless there is a delayed HuC load in progress.
+ */
+ i915_sw_fence_init(&huc->delayed_load.fence,
+ sw_fence_dummy_notify);
+ i915_sw_fence_commit(&huc->delayed_load.fence);
+
+ hrtimer_init(&huc->delayed_load.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ huc->delayed_load.timer.function = huc_delayed_load_timer_callback;
+}
+
+static void delayed_huc_load_fini(struct intel_huc *huc)
+{
+ /*
+ * the fence is initialized in init_early, so we need to clean it up
+ * even if HuC loading is off.
+ */
+ delayed_huc_load_complete(huc);
+ i915_sw_fence_fini(&huc->delayed_load.fence);
+}
+
+static bool vcs_supported(struct intel_gt *gt)
+{
+ intel_engine_mask_t mask = gt->info.engine_mask;
+
+ /*
+ * We reach here from i915_driver_early_probe for the primary GT before
+ * its engine mask is set, so we use the device info engine mask for it;
+ * this means we're not taking VCS fusing into account, but if the
+ * primary GT supports VCS engines we expect at least one of them to
+ * remain unfused so we're fine.
+ * For other GTs we expect the GT-specific mask to be set before we
+ * call this function.
+ */
+ GEM_BUG_ON(!gt_is_root(gt) && !gt->info.engine_mask);
+
+ if (gt_is_root(gt))
+ mask = RUNTIME_INFO(gt->i915)->platform_engine_mask;
+ else
+ mask = gt->info.engine_mask;
+
+ return __ENGINE_INSTANCES_MASK(mask, VCS0, I915_MAX_VCS);
+}
+
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);
+ /*
+ * we always init the fence as already completed, even if HuC is not
+ * supported. This way we don't have to distinguish between HuC not
+ * supported/disabled or already loaded, and can focus on if the load
+ * is currently in progress (fence not complete) or not, which is what
+ * we care about for stalling userspace submissions.
+ */
+ delayed_huc_load_init(huc);
+
+ if (!vcs_supported(gt)) {
+ intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_NOT_SUPPORTED);
+ return;
+ }
+
if (GRAPHICS_VER(i915) >= 11) {
huc->status.reg = GEN11_HUC_KERNEL_LOAD_INFO;
huc->status.mask = HUC_LOAD_SUCCESSFUL;
@@ -113,16 +344,59 @@ int intel_huc_init(struct intel_huc *huc)
return 0;
out:
+ intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_INIT_FAIL);
drm_info(&i915->drm, "HuC init failed with %d\n", err);
return err;
}
void intel_huc_fini(struct intel_huc *huc)
{
+ /*
+ * the fence is initialized in init_early, so we need to clean it up
+ * even if HuC loading is off.
+ */
+ delayed_huc_load_fini(huc);
+
+ if (intel_uc_fw_is_loadable(&huc->fw))
+ intel_uc_fw_fini(&huc->fw);
+}
+
+void intel_huc_suspend(struct intel_huc *huc)
+{
if (!intel_uc_fw_is_loadable(&huc->fw))
return;
- intel_uc_fw_fini(&huc->fw);
+ /*
+ * in the unlikely case that we're suspending before the GSC has
+ * completed its loading sequence, just stop waiting. We'll restart
+ * on resume.
+ */
+ delayed_huc_load_complete(huc);
+}
+
+int intel_huc_wait_for_auth_complete(struct intel_huc *huc)
+{
+ 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,
+ 2, 50, NULL);
+
+ /* mark the load process as complete even if the wait failed */
+ delayed_huc_load_complete(huc);
+
+ if (ret) {
+ drm_err(&gt->i915->drm, "HuC: Firmware not verified %d\n", 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);
+ drm_info(&gt->i915->drm, "HuC authenticated\n");
+ return 0;
}
/**
@@ -161,27 +435,18 @@ int intel_huc_auth(struct intel_huc *huc)
}
/* Check authentication status, it should be done by now */
- ret = __intel_wait_for_register(gt->uncore,
- huc->status.reg,
- huc->status.mask,
- huc->status.value,
- 2, 50, NULL);
- if (ret) {
- DRM_ERROR("HuC: Firmware not verified %d\n", ret);
+ ret = intel_huc_wait_for_auth_complete(huc);
+ if (ret)
goto fail;
- }
- intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_RUNNING);
- drm_info(&gt->i915->drm, "HuC authenticated\n");
return 0;
fail:
i915_probe_error(gt->i915, "HuC: Authentication failed %d\n", ret);
- intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_LOAD_FAIL);
return ret;
}
-static bool huc_is_authenticated(struct intel_huc *huc)
+bool intel_huc_is_authenticated(struct intel_huc *huc)
{
struct intel_gt *gt = huc_to_gt(huc);
intel_wakeref_t wakeref;
@@ -200,13 +465,8 @@ static bool huc_is_authenticated(struct intel_huc *huc)
* This function reads status register to verify if HuC
* firmware was successfully loaded.
*
- * Returns:
- * * -ENODEV if HuC is not present on this platform,
- * * -EOPNOTSUPP if HuC firmware is disabled,
- * * -ENOPKG if HuC firmware was not installed,
- * * -ENOEXEC if HuC firmware is invalid or mismatched,
- * * 0 if HuC firmware is not running,
- * * 1 if HuC firmware is authenticated and running.
+ * The return values match what is expected for the I915_PARAM_HUC_STATUS
+ * getparam.
*/
int intel_huc_check_status(struct intel_huc *huc)
{
@@ -219,11 +479,21 @@ int intel_huc_check_status(struct intel_huc *huc)
return -ENOPKG;
case INTEL_UC_FIRMWARE_ERROR:
return -ENOEXEC;
+ case INTEL_UC_FIRMWARE_INIT_FAIL:
+ return -ENOMEM;
+ case INTEL_UC_FIRMWARE_LOAD_FAIL:
+ return -EIO;
default:
break;
}
- return huc_is_authenticated(huc);
+ return intel_huc_is_authenticated(huc);
+}
+
+static bool huc_has_delayed_load(struct intel_huc *huc)
+{
+ return intel_huc_is_loaded_by_gsc(huc) &&
+ (huc->delayed_load.status != INTEL_HUC_DELAYED_LOAD_ERROR);
}
void intel_huc_update_auth_status(struct intel_huc *huc)
@@ -231,9 +501,11 @@ void intel_huc_update_auth_status(struct intel_huc *huc)
if (!intel_uc_fw_is_loadable(&huc->fw))
return;
- if (huc_is_authenticated(huc))
+ if (intel_huc_is_authenticated(huc))
intel_uc_fw_change_status(&huc->fw,
INTEL_UC_FIRMWARE_RUNNING);
+ else if (huc_has_delayed_load(huc))
+ huc_delayed_load_start(huc);
}
/**
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_huc.h b/drivers/gpu/drm/i915/gt/uc/intel_huc.h
index d7e25b6e879e..52db03620c60 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_huc.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_huc.h
@@ -7,9 +7,21 @@
#define _INTEL_HUC_H_
#include "i915_reg_defs.h"
+#include "i915_sw_fence.h"
#include "intel_uc_fw.h"
#include "intel_huc_fw.h"
+#include <linux/notifier.h>
+#include <linux/hrtimer.h>
+
+struct bus_type;
+
+enum intel_huc_delayed_load_status {
+ INTEL_HUC_WAITING_ON_GSC = 0,
+ INTEL_HUC_WAITING_ON_PXP,
+ INTEL_HUC_DELAYED_LOAD_ERROR,
+};
+
struct intel_huc {
/* Generic uC firmware management */
struct intel_uc_fw fw;
@@ -20,14 +32,27 @@ struct intel_huc {
u32 mask;
u32 value;
} status;
+
+ struct {
+ struct i915_sw_fence fence;
+ struct hrtimer timer;
+ struct notifier_block nb;
+ enum intel_huc_delayed_load_status status;
+ } delayed_load;
};
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_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, struct bus_type *bus);
+void intel_huc_unregister_gsc_notifier(struct intel_huc *huc, struct bus_type *bus);
static inline int intel_huc_sanitize(struct intel_huc *huc)
{
@@ -56,6 +81,12 @@ static inline bool intel_huc_is_loaded_by_gsc(const struct intel_huc *huc)
return huc->fw.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);
+}
+
void intel_huc_load_status(struct intel_huc *huc, struct drm_printer *p);
#endif
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 9d6ab1e01639..4f246416db17 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.c
@@ -3,9 +3,43 @@
* Copyright © 2014-2019 Intel Corporation
*/
+#include "gt/intel_gsc.h"
#include "gt/intel_gt.h"
+#include "intel_huc.h"
#include "intel_huc_fw.h"
#include "i915_drv.h"
+#include "pxp/intel_pxp_huc.h"
+
+int intel_huc_fw_load_and_auth_via_gsc(struct intel_huc *huc)
+{
+ int ret;
+
+ if (!intel_huc_is_loaded_by_gsc(huc))
+ return -ENODEV;
+
+ if (!intel_uc_fw_is_loadable(&huc->fw))
+ return -ENOEXEC;
+
+ /*
+ * If we abort a suspend, HuC might still be loaded when the mei
+ * component gets re-bound and this function called again. If so, just
+ * mark the HuC as loaded.
+ */
+ if (intel_huc_is_authenticated(huc)) {
+ intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_RUNNING);
+ return 0;
+ }
+
+ GEM_WARN_ON(intel_uc_fw_is_loaded(&huc->fw));
+
+ ret = intel_pxp_huc_load_and_auth(&huc_to_gt(huc)->pxp);
+ if (ret)
+ return ret;
+
+ intel_uc_fw_change_status(&huc->fw, INTEL_UC_FIRMWARE_TRANSFERRED);
+
+ return intel_huc_wait_for_auth_complete(huc);
+}
/**
* intel_huc_fw_upload() - load HuC uCode to device via DMA transfer
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 12f264ee3e0b..db42e238b45f 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_huc_fw.h
@@ -8,6 +8,7 @@
struct intel_huc;
+int intel_huc_fw_load_and_auth_via_gsc(struct intel_huc *huc);
int intel_huc_fw_upload(struct intel_huc *huc);
#endif
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
index dbd048b77e19..2a508b137e90 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c
@@ -357,8 +357,8 @@ static int uc_init_wopcm(struct intel_uc *uc)
{
struct intel_gt *gt = uc_to_gt(uc);
struct intel_uncore *uncore = gt->uncore;
- u32 base = intel_wopcm_guc_base(&gt->i915->wopcm);
- u32 size = intel_wopcm_guc_size(&gt->i915->wopcm);
+ u32 base = intel_wopcm_guc_base(&gt->wopcm);
+ u32 size = intel_wopcm_guc_size(&gt->wopcm);
u32 huc_agent = intel_uc_uses_huc(uc) ? HUC_LOADING_AGENT_GUC : 0;
u32 mask;
int err;
@@ -636,8 +636,10 @@ void intel_uc_runtime_suspend(struct intel_uc *uc)
{
struct intel_guc *guc = &uc->guc;
- if (!intel_guc_is_ready(guc))
+ if (!intel_guc_is_ready(guc)) {
+ guc->interrupts.enabled = false;
return;
+ }
/*
* Wait for any outstanding CTB before tearing down communication /w the
@@ -657,8 +659,10 @@ void intel_uc_suspend(struct intel_uc *uc)
intel_wakeref_t wakeref;
int err;
- if (!intel_guc_is_ready(guc))
+ if (!intel_guc_is_ready(guc)) {
+ guc->interrupts.enabled = false;
return;
+ }
with_intel_runtime_pm(&uc_to_gt(uc)->i915->runtime_pm, wakeref) {
err = intel_guc_suspend(guc);
@@ -718,6 +722,7 @@ int intel_uc_runtime_resume(struct intel_uc *uc)
static const struct intel_uc_ops uc_ops_off = {
.init_hw = __uc_check_hw,
+ .fini = __uc_fini, /* to clean-up the init_early initialization */
};
static const struct intel_uc_ops uc_ops_on = {
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 b91ad4aede1f..0c80ba51a4bd 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c
@@ -93,7 +93,8 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
fw_def(BROXTON, 0, guc_mmp(bxt, 70, 1, 1)) \
fw_def(SKYLAKE, 0, guc_mmp(skl, 70, 1, 1))
-#define INTEL_HUC_FIRMWARE_DEFS(fw_def, huc_raw, huc_mmp) \
+#define INTEL_HUC_FIRMWARE_DEFS(fw_def, huc_raw, huc_mmp, huc_gsc) \
+ 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)) \
fw_def(ALDERLAKE_S, 0, huc_raw(tgl)) \
@@ -141,6 +142,9 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
#define MAKE_HUC_FW_PATH_BLANK(prefix_) \
__MAKE_UC_FW_PATH_BLANK(prefix_, "_huc")
+#define MAKE_HUC_FW_PATH_GSC(prefix_) \
+ __MAKE_UC_FW_PATH_BLANK(prefix_, "_huc_gsc")
+
#define MAKE_HUC_FW_PATH_MMP(prefix_, major_, minor_, patch_) \
__MAKE_UC_FW_PATH_MMP(prefix_, "_huc_", major_, minor_, patch_)
@@ -153,7 +157,7 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
MODULE_FIRMWARE(uc_);
INTEL_GUC_FIRMWARE_DEFS(INTEL_UC_MODULE_FW, MAKE_GUC_FW_PATH_MAJOR, MAKE_GUC_FW_PATH_MMP)
-INTEL_HUC_FIRMWARE_DEFS(INTEL_UC_MODULE_FW, MAKE_HUC_FW_PATH_BLANK, MAKE_HUC_FW_PATH_MMP)
+INTEL_HUC_FIRMWARE_DEFS(INTEL_UC_MODULE_FW, MAKE_HUC_FW_PATH_BLANK, MAKE_HUC_FW_PATH_MMP, MAKE_HUC_FW_PATH_GSC)
/*
* The next expansion of the table macros (in __uc_fw_auto_select below) provides
@@ -168,6 +172,7 @@ struct __packed uc_fw_blob {
u8 major;
u8 minor;
u8 patch;
+ bool loaded_via_gsc;
};
#define UC_FW_BLOB_BASE(major_, minor_, patch_, path_) \
@@ -176,16 +181,16 @@ struct __packed uc_fw_blob {
.patch = patch_, \
.path = path_,
-#define UC_FW_BLOB_NEW(major_, minor_, patch_, path_) \
+#define UC_FW_BLOB_NEW(major_, minor_, patch_, gsc_, path_) \
{ UC_FW_BLOB_BASE(major_, minor_, patch_, path_) \
- .legacy = false }
+ .legacy = false, .loaded_via_gsc = 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, \
+ UC_FW_BLOB_NEW(major_, minor_, 0, false, \
MAKE_GUC_FW_PATH_MAJOR(prefix_, major_, minor_))
#define GUC_FW_BLOB_MMP(prefix_, major_, minor_, patch_) \
@@ -193,12 +198,15 @@ struct __packed uc_fw_blob {
MAKE_GUC_FW_PATH_MMP(prefix_, major_, minor_, patch_))
#define HUC_FW_BLOB(prefix_) \
- UC_FW_BLOB_NEW(0, 0, 0, MAKE_HUC_FW_PATH_BLANK(prefix_))
+ UC_FW_BLOB_NEW(0, 0, 0, false, MAKE_HUC_FW_PATH_BLANK(prefix_))
#define HUC_FW_BLOB_MMP(prefix_, major_, minor_, patch_) \
UC_FW_BLOB_OLD(major_, minor_, patch_, \
MAKE_HUC_FW_PATH_MMP(prefix_, major_, minor_, patch_))
+#define HUC_FW_BLOB_GSC(prefix_) \
+ UC_FW_BLOB_NEW(0, 0, 0, true, MAKE_HUC_FW_PATH_GSC(prefix_))
+
struct __packed uc_fw_platform_requirement {
enum intel_platform p;
u8 rev; /* first platform rev using this FW */
@@ -224,7 +232,7 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw)
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)
+ 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) },
@@ -272,6 +280,7 @@ __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.major_ver = blob->major;
uc_fw->file_wanted.minor_ver = blob->minor;
+ uc_fw->loaded_via_gsc = blob->loaded_via_gsc;
found = true;
break;
}
@@ -469,10 +478,11 @@ static int check_gsc_manifest(const struct firmware *fw,
return 0;
}
-static int check_ccs_header(struct drm_i915_private *i915,
+static int check_ccs_header(struct intel_gt *gt,
const struct firmware *fw,
struct intel_uc_fw *uc_fw)
{
+ struct drm_i915_private *i915 = gt->i915;
struct uc_css_header *css;
size_t size;
@@ -514,10 +524,10 @@ static int check_ccs_header(struct drm_i915_private *i915,
/* Sanity check whether this fw is not larger than whole WOPCM memory */
size = __intel_uc_fw_get_upload_size(uc_fw);
- if (unlikely(size >= i915->wopcm.size)) {
+ if (unlikely(size >= gt->wopcm.size)) {
drm_warn(&i915->drm, "%s firmware %s: invalid size: %zu > %zu\n",
intel_uc_fw_type_repr(uc_fw->type), uc_fw->file_selected.path,
- size, (size_t)i915->wopcm.size);
+ size, (size_t)gt->wopcm.size);
return -E2BIG;
}
@@ -545,7 +555,8 @@ static int check_ccs_header(struct drm_i915_private *i915,
*/
int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
{
- struct drm_i915_private *i915 = __uc_fw_to_gt(uc_fw)->i915;
+ struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
+ struct drm_i915_private *i915 = gt->i915;
struct intel_uc_fw_file file_ideal;
struct device *dev = i915->drm.dev;
struct drm_i915_gem_object *obj;
@@ -553,7 +564,7 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
bool old_ver = false;
int err;
- GEM_BUG_ON(!i915->wopcm.size);
+ GEM_BUG_ON(!gt->wopcm.size);
GEM_BUG_ON(!intel_uc_fw_is_enabled(uc_fw));
err = i915_inject_probe_error(i915, -ENXIO);
@@ -566,6 +577,17 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
err = firmware_request_nowarn(&fw, uc_fw->file_selected.path, dev);
memcpy(&file_ideal, &uc_fw->file_wanted, sizeof(file_ideal));
+ if (!err && fw->size > INTEL_UC_RSVD_GGTT_PER_FW) {
+ drm_err(&i915->drm,
+ "%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);
+
+ /* try to find another blob to load */
+ release_firmware(fw);
+ err = -ENOENT;
+ }
+
/* Any error is terminal if overriding. Don't bother searching for older versions */
if (err && intel_uc_fw_is_overridden(uc_fw))
goto fail;
@@ -595,7 +617,7 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw)
if (uc_fw->loaded_via_gsc)
err = check_gsc_manifest(fw, uc_fw);
else
- err = check_ccs_header(i915, fw, uc_fw);
+ err = check_ccs_header(gt, fw, uc_fw);
if (err)
goto fail;
@@ -668,14 +690,30 @@ fail:
static u32 uc_fw_ggtt_offset(struct intel_uc_fw *uc_fw)
{
- struct i915_ggtt *ggtt = __uc_fw_to_gt(uc_fw)->ggtt;
+ struct intel_gt *gt = __uc_fw_to_gt(uc_fw);
+ struct i915_ggtt *ggtt = gt->ggtt;
struct drm_mm_node *node = &ggtt->uc_fw;
+ u32 offset = uc_fw->type * INTEL_UC_RSVD_GGTT_PER_FW;
+
+ /*
+ * The media GT shares the GGTT with the root GT, which means that
+ * we need to use different offsets for the binaries on the media GT.
+ * To keep the math simple, we use 8MB for the root tile and 8MB for
+ * the media one. This will need to be updated if we ever have more
+ * than 1 media GT.
+ */
+ BUILD_BUG_ON(INTEL_UC_FW_NUM_TYPES * INTEL_UC_RSVD_GGTT_PER_FW > SZ_8M);
+ GEM_BUG_ON(gt->type == GT_MEDIA && gt->info.id > 1);
+ if (gt->type == GT_MEDIA)
+ offset += SZ_8M;
GEM_BUG_ON(!drm_mm_node_allocated(node));
GEM_BUG_ON(upper_32_bits(node->start));
GEM_BUG_ON(upper_32_bits(node->start + node->size - 1));
+ GEM_BUG_ON(offset + uc_fw->obj->base.size > node->size);
+ GEM_BUG_ON(uc_fw->obj->base.size > INTEL_UC_RSVD_GGTT_PER_FW);
- return lower_32_bits(node->start);
+ return lower_32_bits(node->start + offset);
}
static void uc_fw_bind_ggtt(struct intel_uc_fw *uc_fw)
@@ -690,7 +728,6 @@ static void uc_fw_bind_ggtt(struct intel_uc_fw *uc_fw)
dummy->bi.pages = obj->mm.pages;
GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj));
- GEM_BUG_ON(dummy->node_size > ggtt->uc_fw.size);
/* uc_fw->obj cache domains were not controlled across suspend */
if (i915_gem_object_has_struct_page(obj))
@@ -904,7 +941,6 @@ int intel_uc_fw_init(struct intel_uc_fw *uc_fw)
out_unpin:
i915_gem_object_unpin_pages(uc_fw->obj);
out:
- intel_uc_fw_change_status(uc_fw, INTEL_UC_FIRMWARE_INIT_FAIL);
return err;
}
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 cb586f7df270..bc898ba5355d 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
+++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h
@@ -6,6 +6,7 @@
#ifndef _INTEL_UC_FW_H_
#define _INTEL_UC_FW_H_
+#include <linux/sizes.h>
#include <linux/types.h>
#include "intel_uc_fw_abi.h"
#include "intel_device_info.h"
@@ -114,6 +115,19 @@ struct intel_uc_fw {
(uc)->fw.file_selected.minor_ver, \
(uc)->fw.file_selected.patch_ver))
+/*
+ * When we load the uC binaries, we pin them in a reserved section at the top of
+ * the GGTT, which is ~18 MBs. On multi-GT systems where the GTs share the GGTT,
+ * we also need to make sure that each binary is pinned to a unique location
+ * during load, because the different GT can go through the FW load at the same
+ * time (see uc_fw_ggtt_offset() for details).
+ * Given that the available space is much greater than what is required by the
+ * binaries, to keep things simple instead of dynamically partitioning the
+ * reserved section to make space for all the blobs we can just reserve a static
+ * chunk for each binary.
+ */
+#define INTEL_UC_RSVD_GGTT_PER_FW SZ_2M
+
#ifdef CONFIG_DRM_I915_DEBUG_GUC
void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw,
enum intel_uc_fw_status status);
diff --git a/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c b/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c
index 01f8cd3c3134..d91b58f70403 100644
--- a/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c
+++ b/drivers/gpu/drm/i915/gt/uc/selftest_guc_hangcheck.c
@@ -35,11 +35,14 @@ static int intel_hang_guc(void *arg)
struct i915_request *rq;
intel_wakeref_t wakeref;
struct i915_gpu_error *global = &gt->i915->gpu_error;
- struct intel_engine_cs *engine;
+ struct intel_engine_cs *engine = intel_selftest_find_any_engine(gt);
unsigned int reset_count;
u32 guc_status;
u32 old_beat;
+ if (!engine)
+ return 0;
+
ctx = kernel_context(gt->i915, NULL);
if (IS_ERR(ctx)) {
drm_err(&gt->i915->drm, "Failed get kernel context: %ld\n", PTR_ERR(ctx));
@@ -48,14 +51,13 @@ static int intel_hang_guc(void *arg)
wakeref = intel_runtime_pm_get(gt->uncore->rpm);
- ce = intel_context_create(gt->engine[BCS0]);
+ ce = intel_context_create(engine);
if (IS_ERR(ce)) {
ret = PTR_ERR(ce);
drm_err(&gt->i915->drm, "Failed to create spinner request: %d\n", ret);
goto err;
}
- engine = ce->engine;
reset_count = i915_reset_count(global);
old_beat = engine->props.heartbeat_interval_ms;
diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c
index eef3bba8a41b..9bafac1eaf48 100644
--- a/drivers/gpu/drm/i915/gvt/cfg_space.c
+++ b/drivers/gpu/drm/i915/gvt/cfg_space.c
@@ -244,7 +244,7 @@ static void emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset,
}
/**
- * intel_vgpu_emulate_cfg_read - emulate vGPU configuration space write
+ * intel_vgpu_emulate_cfg_write - emulate vGPU configuration space write
* @vgpu: target vgpu
* @offset: offset
* @p_data: write data ptr
@@ -354,9 +354,9 @@ void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu,
memset(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_OPREGION, 0, 4);
vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_GTTMMIO].size =
- pci_resource_len(pdev, GTTMMADR_BAR);
+ pci_resource_len(pdev, GEN4_GTTMMADR_BAR);
vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].size =
- pci_resource_len(pdev, GTT_APERTURE_BAR);
+ pci_resource_len(pdev, GEN4_GMADR_BAR);
memset(vgpu_cfg_space(vgpu) + PCI_ROM_ADDRESS, 0, 4);
diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c
index de13f102d4fd..0ebf5fbf0e39 100644
--- a/drivers/gpu/drm/i915/gvt/cmd_parser.c
+++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c
@@ -37,6 +37,7 @@
#include <linux/slab.h>
#include "i915_drv.h"
+#include "i915_reg.h"
#include "gt/intel_engine_regs.h"
#include "gt/intel_gpu_commands.h"
#include "gt/intel_gt_regs.h"
diff --git a/drivers/gpu/drm/i915/gvt/display.c b/drivers/gpu/drm/i915/gvt/display.c
index c7722c818b4d..c033249e73f4 100644
--- a/drivers/gpu/drm/i915/gvt/display.c
+++ b/drivers/gpu/drm/i915/gvt/display.c
@@ -36,6 +36,8 @@
#include "i915_reg.h"
#include "gvt.h"
+#include "display/intel_dpio_phy.h"
+
static int get_edp_pipe(struct intel_vgpu *vgpu)
{
u32 data = vgpu_vreg(vgpu, _TRANS_DDI_FUNC_CTL_EDP);
diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c
index 01e54b45c5c1..355f1c0e8664 100644
--- a/drivers/gpu/drm/i915/gvt/dmabuf.c
+++ b/drivers/gpu/drm/i915/gvt/dmabuf.c
@@ -88,7 +88,7 @@ static int vgpu_gem_get_pages(
sg_dma_address(sg) = dma_addr;
}
- __i915_gem_object_set_pages(obj, st, PAGE_SIZE);
+ __i915_gem_object_set_pages(obj, st);
out:
if (ret) {
dma_addr_t dma_addr;
diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.h b/drivers/gpu/drm/i915/gvt/dmabuf.h
index 5f8f03fb1d1b..3dcdb6570eda 100644
--- a/drivers/gpu/drm/i915/gvt/dmabuf.h
+++ b/drivers/gpu/drm/i915/gvt/dmabuf.h
@@ -48,7 +48,7 @@ struct intel_vgpu_fb_info {
struct intel_vgpu_dmabuf_obj *obj;
};
-/**
+/*
* struct intel_vgpu_dmabuf_obj- Intel vGPU device buffer object
*/
struct intel_vgpu_dmabuf_obj {
diff --git a/drivers/gpu/drm/i915/gvt/firmware.c b/drivers/gpu/drm/i915/gvt/firmware.c
index 54fe442238c6..a683c22d5b64 100644
--- a/drivers/gpu/drm/i915/gvt/firmware.c
+++ b/drivers/gpu/drm/i915/gvt/firmware.c
@@ -104,7 +104,7 @@ static int expose_firmware_sysfs(struct intel_gvt *gvt)
memcpy(p, gvt->firmware.mmio, info->mmio_size);
- crc32_start = offsetof(struct gvt_firmware_header, crc32) + 4;
+ crc32_start = offsetof(struct gvt_firmware_header, version);
h->crc32 = crc32_le(0, firmware + crc32_start, size - crc32_start);
firmware_attr.size = size;
diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c
index ce0eb03709c3..51e5e8fb505b 100644
--- a/drivers/gpu/drm/i915/gvt/gtt.c
+++ b/drivers/gpu/drm/i915/gvt/gtt.c
@@ -282,11 +282,6 @@ static inline int get_next_pt_type(int type)
return gtt_type_table[type].next_pt_type;
}
-static inline int get_pt_type(int type)
-{
- return gtt_type_table[type].pt_type;
-}
-
static inline int get_entry_type(int type)
{
return gtt_type_table[type].entry_type;
@@ -2785,7 +2780,7 @@ int intel_gvt_init_gtt(struct intel_gvt *gvt)
* intel_gvt_clean_gtt - clean up mm components of a GVT device
* @gvt: GVT device
*
- * This function is called at the driver unloading stage, to clean up the
+ * This function is called at the driver unloading stage, to clean up
* the mm components of a GVT device.
*
*/
diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h
index dbf8d7470b2c..62823c0e13ab 100644
--- a/drivers/gpu/drm/i915/gvt/gvt.h
+++ b/drivers/gpu/drm/i915/gvt/gvt.h
@@ -227,8 +227,6 @@ struct intel_vgpu {
unsigned long nr_cache_entries;
struct mutex cache_lock;
- atomic_t released;
-
struct kvm_page_track_notifier_node track_node;
#define NR_BKT (1 << 18)
struct hlist_head ptable[NR_BKT];
diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c
index daac2050d77d..735fc83e7026 100644
--- a/drivers/gpu/drm/i915/gvt/handlers.c
+++ b/drivers/gpu/drm/i915/gvt/handlers.c
@@ -43,6 +43,7 @@
#include "intel_mchbar_regs.h"
#include "display/intel_display_types.h"
#include "display/intel_dmc_regs.h"
+#include "display/intel_dpio_phy.h"
#include "display/intel_fbc.h"
#include "display/vlv_dsi_pll_regs.h"
#include "gt/intel_gt_regs.h"
@@ -734,7 +735,7 @@ static i915_reg_t force_nonpriv_white_list[] = {
_MMIO(0x770c),
_MMIO(0x83a8),
_MMIO(0xb110),
- GEN8_L3SQCREG4,//_MMIO(0xb118)
+ _MMIO(0xb118),
_MMIO(0xe100),
_MMIO(0xe18c),
_MMIO(0xe48c),
@@ -2257,7 +2258,7 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
MMIO_DFH(_MMIO(0x2438), D_ALL, F_CMD_ACCESS, NULL, NULL);
MMIO_DFH(_MMIO(0x243c), D_ALL, F_CMD_ACCESS, NULL, NULL);
MMIO_DFH(_MMIO(0x7018), D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
- MMIO_DFH(HALF_SLICE_CHICKEN3, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
+ MMIO_DFH(HSW_HALF_SLICE_CHICKEN3, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
MMIO_DFH(GEN7_HALF_SLICE_CHICKEN1, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
/* display */
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 714221f9a131..077892a9aa8f 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -683,7 +683,6 @@ static int intel_vgpu_open_device(struct vfio_device *vfio_dev)
intel_gvt_activate_vgpu(vgpu);
- atomic_set(&vgpu->released, 0);
return 0;
}
@@ -705,9 +704,6 @@ static void intel_vgpu_close_device(struct vfio_device *vfio_dev)
if (!vgpu->attached)
return;
- if (atomic_cmpxchg(&vgpu->released, 0, 1))
- return;
-
intel_gvt_release_vgpu(vgpu);
debugfs_remove(debugfs_lookup(KVMGT_DEBUGFS_FILENAME, vgpu->debugfs));
diff --git a/drivers/gpu/drm/i915/gvt/mmio.c b/drivers/gpu/drm/i915/gvt/mmio.c
index 9acc00505fde..5b5def6ddef7 100644
--- a/drivers/gpu/drm/i915/gvt/mmio.c
+++ b/drivers/gpu/drm/i915/gvt/mmio.c
@@ -37,6 +37,7 @@
#include "i915_reg.h"
#include "gvt.h"
+#include "display/intel_dpio_phy.h"
#include "gt/intel_gt_regs.h"
/**
diff --git a/drivers/gpu/drm/i915/gvt/mmio_context.c b/drivers/gpu/drm/i915/gvt/mmio_context.c
index 1c6e941c9666..490e8ae51228 100644
--- a/drivers/gpu/drm/i915/gvt/mmio_context.c
+++ b/drivers/gpu/drm/i915/gvt/mmio_context.c
@@ -34,6 +34,7 @@
*/
#include "i915_drv.h"
+#include "i915_reg.h"
#include "gt/intel_context.h"
#include "gt/intel_engine_regs.h"
#include "gt/intel_gpu_commands.h"
@@ -106,15 +107,15 @@ static struct engine_mmio gen9_engine_mmio_list[] __cacheline_aligned = {
{RCS0, GEN8_CS_CHICKEN1, 0xffff, true}, /* 0x2580 */
{RCS0, COMMON_SLICE_CHICKEN2, 0xffff, true}, /* 0x7014 */
{RCS0, GEN9_CS_DEBUG_MODE1, 0xffff, false}, /* 0x20ec */
- {RCS0, GEN8_L3SQCREG4, 0, false}, /* 0xb118 */
- {RCS0, GEN9_SCRATCH1, 0, false}, /* 0xb11c */
+ {RCS0, _MMIO(0xb118), 0, false}, /* GEN8_L3SQCREG4 */
+ {RCS0, _MMIO(0xb11c), 0, false}, /* GEN9_SCRATCH1 */
{RCS0, GEN9_SCRATCH_LNCF1, 0, false}, /* 0xb008 */
{RCS0, GEN7_HALF_SLICE_CHICKEN1, 0xffff, true}, /* 0xe100 */
- {RCS0, HALF_SLICE_CHICKEN2, 0xffff, true}, /* 0xe180 */
- {RCS0, HALF_SLICE_CHICKEN3, 0xffff, true}, /* 0xe184 */
- {RCS0, GEN9_HALF_SLICE_CHICKEN5, 0xffff, true}, /* 0xe188 */
- {RCS0, GEN9_HALF_SLICE_CHICKEN7, 0xffff, true}, /* 0xe194 */
- {RCS0, GEN8_ROW_CHICKEN, 0xffff, true}, /* 0xe4f0 */
+ {RCS0, _MMIO(0xe180), 0xffff, true}, /* HALF_SLICE_CHICKEN2 */
+ {RCS0, _MMIO(0xe184), 0xffff, true}, /* GEN8_HALF_SLICE_CHICKEN3 */
+ {RCS0, _MMIO(0xe188), 0xffff, true}, /* GEN9_HALF_SLICE_CHICKEN5 */
+ {RCS0, _MMIO(0xe194), 0xffff, true}, /* GEN9_HALF_SLICE_CHICKEN7 */
+ {RCS0, _MMIO(0xe4f0), 0xffff, true}, /* GEN8_ROW_CHICKEN */
{RCS0, TRVATTL3PTRDW(0), 0, true}, /* 0x4de0 */
{RCS0, TRVATTL3PTRDW(1), 0, true}, /* 0x4de4 */
{RCS0, TRNULLDETCT, 0, true}, /* 0x4de8 */
diff --git a/drivers/gpu/drm/i915/gvt/page_track.c b/drivers/gpu/drm/i915/gvt/page_track.c
index 3375b51c75f1..df34e73cba41 100644
--- a/drivers/gpu/drm/i915/gvt/page_track.c
+++ b/drivers/gpu/drm/i915/gvt/page_track.c
@@ -120,7 +120,7 @@ int intel_vgpu_enable_page_track(struct intel_vgpu *vgpu, unsigned long gfn)
}
/**
- * intel_vgpu_enable_page_track - cancel write-protection on guest page
+ * intel_vgpu_disable_page_track - cancel write-protection on guest page
* @vgpu: a vGPU
* @gfn: the gfn of guest page
*
diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c
index d6fe94cd0fdb..9cd8fcbf7cad 100644
--- a/drivers/gpu/drm/i915/gvt/scheduler.c
+++ b/drivers/gpu/drm/i915/gvt/scheduler.c
@@ -570,9 +570,8 @@ retry:
if (gmadr_bytes == 8)
bb->bb_start_cmd_va[2] = 0;
- ret = i915_vma_move_to_active(bb->vma,
- workload->req,
- 0);
+ ret = i915_vma_move_to_active(bb->vma, workload->req,
+ __EXEC_OBJECT_NO_REQUEST_AWAIT);
if (ret)
goto err;
diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c
index 56c71474008a..3c529c2705dd 100644
--- a/drivers/gpu/drm/i915/gvt/vgpu.c
+++ b/drivers/gpu/drm/i915/gvt/vgpu.c
@@ -158,7 +158,7 @@ void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt)
}
/**
- * intel_gvt_active_vgpu - activate a virtual GPU
+ * intel_gvt_activate_vgpu - activate a virtual GPU
* @vgpu: virtual GPU
*
* This function is called when user wants to activate a virtual GPU.
@@ -172,7 +172,7 @@ void intel_gvt_activate_vgpu(struct intel_vgpu *vgpu)
}
/**
- * intel_gvt_deactive_vgpu - deactivate a virtual GPU
+ * intel_gvt_deactivate_vgpu - deactivate a virtual GPU
* @vgpu: virtual GPU
*
* This function is called when user wants to deactivate a virtual GPU.
@@ -295,7 +295,7 @@ out_free_vgpu:
}
/**
- * intel_gvt_destroy_vgpu - destroy an idle virtual GPU
+ * intel_gvt_destroy_idle_vgpu - destroy an idle virtual GPU
* @vgpu: virtual GPU
*
* This function is called when user wants to destroy an idle virtual GPU.
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index ae987e92251d..6c7ac73b69a5 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -688,8 +688,8 @@ i915_drop_caches_set(void *data, u64 val)
unsigned int flags;
int ret;
- DRM_DEBUG("Dropping caches: 0x%08llx [0x%08llx]\n",
- val, val & DROP_ALL);
+ drm_dbg(&i915->drm, "Dropping caches: 0x%08llx [0x%08llx]\n",
+ val, val & DROP_ALL);
ret = gt_drop_caches(to_gt(i915), val);
if (ret)
diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c
index f2a15d8155f4..69103ae37779 100644
--- a/drivers/gpu/drm/i915/i915_driver.c
+++ b/drivers/gpu/drm/i915/i915_driver.c
@@ -81,6 +81,7 @@
#include "i915_drm_client.h"
#include "i915_drv.h"
#include "i915_getparam.h"
+#include "i915_hwmon.h"
#include "i915_ioc32.h"
#include "i915_ioctl.h"
#include "i915_irq.h"
@@ -337,7 +338,8 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
if (i915_inject_probe_failure(dev_priv))
return -ENODEV;
- intel_device_info_subplatform_init(dev_priv);
+ intel_device_info_runtime_init_early(dev_priv);
+
intel_step_init(dev_priv);
intel_uncore_mmio_debug_init_early(dev_priv);
@@ -370,8 +372,6 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv)
if (ret)
goto err_ttm;
- intel_wopcm_init_early(&dev_priv->wopcm);
-
ret = intel_root_gt_init_early(dev_priv);
if (ret < 0)
goto err_rootgt;
@@ -739,7 +739,6 @@ static void i915_driver_hw_remove(struct drm_i915_private *dev_priv)
*/
static void i915_driver_register(struct drm_i915_private *dev_priv)
{
- struct drm_device *dev = &dev_priv->drm;
struct intel_gt *gt;
unsigned int i;
@@ -749,7 +748,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
intel_vgpu_register(dev_priv);
/* Reveal our presence to userspace */
- if (drm_dev_register(dev, 0)) {
+ if (drm_dev_register(&dev_priv->drm, 0)) {
drm_err(&dev_priv->drm,
"Failed to register driver for userspace access!\n");
return;
@@ -764,6 +763,8 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
for_each_gt(gt, dev_priv, i)
intel_gt_driver_register(gt);
+ i915_hwmon_register(dev_priv);
+
intel_display_driver_register(dev_priv);
intel_power_domains_enable(dev_priv);
@@ -796,6 +797,8 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
for_each_gt(gt, dev_priv, i)
intel_gt_driver_unregister(gt);
+ i915_hwmon_unregister(dev_priv);
+
i915_perf_unregister(dev_priv);
i915_pmu_unregister(dev_priv);
@@ -894,10 +897,6 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (IS_ERR(i915))
return PTR_ERR(i915);
- /* Disable nuclear pageflip by default on pre-ILK */
- if (!i915->params.nuclear_pageflip && DISPLAY_VER(i915) < 5)
- i915->drm.driver_features &= ~DRIVER_ATOMIC;
-
ret = pci_enable_device(pdev);
if (ret)
goto out_fini;
@@ -1093,32 +1092,30 @@ static void i915_driver_postclose(struct drm_device *dev, struct drm_file *file)
static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
{
- struct drm_device *dev = &dev_priv->drm;
struct intel_encoder *encoder;
if (!HAS_DISPLAY(dev_priv))
return;
- drm_modeset_lock_all(dev);
- for_each_intel_encoder(dev, encoder)
+ 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);
+ drm_modeset_unlock_all(&dev_priv->drm);
}
static void intel_shutdown_encoders(struct drm_i915_private *dev_priv)
{
- struct drm_device *dev = &dev_priv->drm;
struct intel_encoder *encoder;
if (!HAS_DISPLAY(dev_priv))
return;
- drm_modeset_lock_all(dev);
- for_each_intel_encoder(dev, encoder)
+ 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);
+ drm_modeset_unlock_all(&dev_priv->drm);
}
void i915_driver_shutdown(struct drm_i915_private *i915)
@@ -1662,7 +1659,8 @@ static int intel_runtime_suspend(struct device *kdev)
intel_runtime_pm_enable_interrupts(dev_priv);
- intel_gt_runtime_resume(to_gt(dev_priv));
+ for_each_gt(gt, dev_priv, i)
+ intel_gt_runtime_resume(gt);
enable_rpm_wakeref_asserts(rpm);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index bdc81db76dbd..a380db36d52c 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -40,7 +40,6 @@
#include "display/intel_display_core.h"
#include "gem/i915_gem_context_types.h"
-#include "gem/i915_gem_lmem.h"
#include "gem/i915_gem_shrinker.h"
#include "gem/i915_gem_stolen.h"
@@ -63,7 +62,6 @@
#include "intel_runtime_pm.h"
#include "intel_step.h"
#include "intel_uncore.h"
-#include "intel_wopcm.h"
struct drm_i915_clock_gating_funcs;
struct drm_i915_gem_object;
@@ -75,9 +73,6 @@ struct intel_limit;
struct intel_overlay_error_state;
struct vlv_s0ix_state;
-/* Threshold == 5 for long IRQs, 50 for short */
-#define HPD_STORM_DEFAULT_THRESHOLD 50
-
#define I915_GEM_GPU_DOMAINS \
(I915_GEM_DOMAIN_RENDER | \
I915_GEM_DOMAIN_SAMPLER | \
@@ -239,8 +234,6 @@ struct drm_i915_private {
struct intel_gvt *gvt;
- struct intel_wopcm wopcm;
-
struct pci_dev *bridge_dev;
struct rb_root uabi_engines;
@@ -291,28 +284,13 @@ struct drm_i915_private {
unsigned long gem_quirks;
- struct drm_atomic_state *modeset_restore_state;
- struct drm_modeset_acquire_ctx reset_ctx;
-
struct i915_gem_mm mm;
- /* Kernel Modesetting */
-
- struct list_head global_obj_list;
-
bool mchbar_need_disable;
struct intel_l3_parity l3_parity;
/*
- * HTI (aka HDPORT) state read during initial hw readout. Most
- * platforms don't have HTI, so this will just stay 0. Those that do
- * will use this later to figure out which PLLs and PHYs are unavailable
- * for driver usage.
- */
- u32 hti_state;
-
- /*
* edram size in MB.
* Cannot be determined by PCIID. You must always read a register.
*/
@@ -353,6 +331,8 @@ struct drm_i915_private {
struct i915_perf perf;
+ struct i915_hwmon *hwmon;
+
/* Abstract the submission mechanism (legacy ringbuffer or execlists) away */
struct intel_gt gt0;
@@ -742,6 +722,10 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
#define IS_XEHPSDV_GRAPHICS_STEP(__i915, since, until) \
(IS_XEHPSDV(__i915) && IS_GRAPHICS_STEP(__i915, since, until))
+#define IS_MTL_GRAPHICS_STEP(__i915, variant, since, until) \
+ (IS_SUBPLATFORM(__i915, INTEL_METEORLAKE, INTEL_SUBPLATFORM_##variant) && \
+ IS_GRAPHICS_STEP(__i915, since, until))
+
/*
* DG2 hardware steppings are a bit unusual. The hardware design was forked to
* create three variants (G10, G11, and G12) which each have distinct
@@ -780,12 +764,15 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
#define __HAS_ENGINE(engine_mask, id) ((engine_mask) & BIT(id))
#define HAS_ENGINE(gt, id) __HAS_ENGINE((gt)->info.engine_mask, id)
-#define ENGINE_INSTANCES_MASK(gt, first, count) ({ \
+#define __ENGINE_INSTANCES_MASK(mask, first, count) ({ \
unsigned int first__ = (first); \
unsigned int count__ = (count); \
- ((gt)->info.engine_mask & \
- GENMASK(first__ + count__ - 1, first__)) >> first__; \
+ ((mask) & GENMASK(first__ + count__ - 1, first__)) >> first__; \
})
+
+#define ENGINE_INSTANCES_MASK(gt, first, count) \
+ __ENGINE_INSTANCES_MASK((gt)->info.engine_mask, first, count)
+
#define RCS_MASK(gt) \
ENGINE_INSTANCES_MASK(gt, RCS0, I915_MAX_RCS)
#define BCS_MASK(gt) \
@@ -871,6 +858,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
#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)
@@ -900,19 +888,17 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
#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)
+
/*
* 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)
-/*
- * Set this flag when platform doesn't allow both 64k pages and 4k pages in
- * the same PT. this flag means we need to support compact PT layout for the
- * ppGTT when using the 64K GTT pages.
- */
-#define NEEDS_COMPACT_PT(dev_priv) (INTEL_INFO(dev_priv)->needs_compact_pt)
-
#define HAS_IPC(dev_priv) (INTEL_INFO(dev_priv)->display.has_ipc)
#define HAS_REGION(i915, i) (RUNTIME_INFO(i915)->memory_regions & (i))
@@ -938,6 +924,8 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
#define HAS_GMCH(dev_priv) (INTEL_INFO(dev_priv)->display.has_gmch)
+#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)
@@ -976,6 +964,9 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
#define HAS_ONE_EU_PER_FUSE_BIT(i915) (INTEL_INFO(i915)->has_one_eu_per_fuse_bit)
+#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)
@@ -983,16 +974,4 @@ mkwrite_device_info(struct drm_i915_private *dev_priv)
return (struct intel_device_info *)INTEL_INFO(dev_priv);
}
-static inline 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))
- return I915_MAP_WC;
- if (HAS_LLC(i915) || always_coherent)
- return I915_MAP_WB;
- else
- return I915_MAP_WC;
-}
-
#endif
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 2bdddb61ebd7..8468ca9885fd 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -843,7 +843,7 @@ void i915_gem_runtime_suspend(struct drm_i915_private *i915)
__i915_gem_object_release_mmap_gtt(obj);
list_for_each_entry_safe(obj, on,
- &to_gt(i915)->lmem_userfault_list, userfault_link)
+ &i915->runtime_pm.lmem_userfault_list, userfault_link)
i915_gem_object_runtime_pm_release_mmap_offset(obj);
/*
@@ -1128,6 +1128,8 @@ void i915_gem_drain_workqueue(struct drm_i915_private *i915)
int i915_gem_init(struct drm_i915_private *dev_priv)
{
+ struct intel_gt *gt;
+ unsigned int i;
int ret;
/* We need to fallback to 4K pages if host doesn't support huge gtt. */
@@ -1138,8 +1140,10 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
if (ret)
return ret;
- intel_uc_fetch_firmwares(&to_gt(dev_priv)->uc);
- intel_wopcm_init(&dev_priv->wopcm);
+ for_each_gt(gt, dev_priv, i) {
+ intel_uc_fetch_firmwares(&gt->uc);
+ intel_wopcm_init(&gt->wopcm);
+ }
ret = i915_init_ggtt(dev_priv);
if (ret) {
@@ -1158,9 +1162,11 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
*/
intel_init_clock_gating(dev_priv);
- ret = intel_gt_init(to_gt(dev_priv));
- if (ret)
- goto err_unlock;
+ for_each_gt(gt, dev_priv, i) {
+ ret = intel_gt_init(gt);
+ if (ret)
+ goto err_unlock;
+ }
return 0;
@@ -1173,8 +1179,13 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
err_unlock:
i915_gem_drain_workqueue(dev_priv);
- if (ret != -EIO)
- intel_uc_cleanup_firmwares(&to_gt(dev_priv)->uc);
+ if (ret != -EIO) {
+ for_each_gt(gt, dev_priv, i) {
+ intel_gt_driver_remove(gt);
+ intel_gt_driver_release(gt);
+ intel_uc_cleanup_firmwares(&gt->uc);
+ }
+ }
if (ret == -EIO) {
/*
@@ -1182,10 +1193,12 @@ err_unlock:
* as wedged. But we only want to do this when the GPU is angry,
* for all other failure, such as an allocation failure, bail.
*/
- if (!intel_gt_is_wedged(to_gt(dev_priv))) {
- i915_probe_error(dev_priv,
- "Failed to initialize GPU, declaring it wedged!\n");
- intel_gt_set_wedged(to_gt(dev_priv));
+ for_each_gt(gt, dev_priv, i) {
+ if (!intel_gt_is_wedged(gt)) {
+ i915_probe_error(dev_priv,
+ "Failed to initialize GPU, declaring it wedged!\n");
+ intel_gt_set_wedged(gt);
+ }
}
/* Minimal basic recovery for KMS */
@@ -1213,23 +1226,27 @@ void i915_gem_driver_unregister(struct drm_i915_private *i915)
void i915_gem_driver_remove(struct drm_i915_private *dev_priv)
{
- intel_wakeref_auto_fini(&to_gt(dev_priv)->userfault_wakeref);
+ struct intel_gt *gt;
+ unsigned int i;
i915_gem_suspend_late(dev_priv);
- intel_gt_driver_remove(to_gt(dev_priv));
+ for_each_gt(gt, dev_priv, i)
+ intel_gt_driver_remove(gt);
dev_priv->uabi_engines = RB_ROOT;
/* Flush any outstanding unpin_work. */
i915_gem_drain_workqueue(dev_priv);
-
- i915_gem_drain_freed_objects(dev_priv);
}
void i915_gem_driver_release(struct drm_i915_private *dev_priv)
{
- intel_gt_driver_release(to_gt(dev_priv));
+ struct intel_gt *gt;
+ unsigned int i;
- intel_uc_cleanup_firmwares(&to_gt(dev_priv)->uc);
+ for_each_gt(gt, dev_priv, i) {
+ intel_gt_driver_release(gt);
+ intel_uc_cleanup_firmwares(&gt->uc);
+ }
/* Flush any outstanding work, including i915_gem_context.release_work. */
i915_gem_drain_workqueue(dev_priv);
@@ -1259,7 +1276,7 @@ void i915_gem_init_early(struct drm_i915_private *dev_priv)
void i915_gem_cleanup_early(struct drm_i915_private *dev_priv)
{
- i915_gem_drain_freed_objects(dev_priv);
+ i915_gem_drain_workqueue(dev_priv);
GEM_BUG_ON(!llist_empty(&dev_priv->mm.free_list));
GEM_BUG_ON(atomic_read(&dev_priv->mm.free_count));
drm_WARN_ON(&dev_priv->drm, dev_priv->mm.shrink_count);
@@ -1271,7 +1288,7 @@ int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file)
struct i915_drm_client *client;
int ret = -ENOMEM;
- DRM_DEBUG("\n");
+ drm_dbg(&i915->drm, "\n");
file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
if (!file_priv)
diff --git a/drivers/gpu/drm/i915/i915_getparam.c b/drivers/gpu/drm/i915/i915_getparam.c
index 342c8ca6414e..61ef2d9cfa62 100644
--- a/drivers/gpu/drm/i915/i915_getparam.c
+++ b/drivers/gpu/drm/i915/i915_getparam.c
@@ -175,8 +175,11 @@ int i915_getparam_ioctl(struct drm_device *dev, void *data,
case I915_PARAM_PERF_REVISION:
value = i915_perf_ioctl_version();
break;
+ case I915_PARAM_OA_TIMESTAMP_FREQUENCY:
+ value = i915_perf_oa_timestamp_frequency(i915);
+ break;
default:
- DRM_DEBUG("Unknown parameter %d\n", param->param);
+ drm_dbg(&i915->drm, "Unknown parameter %d\n", param->param);
return -EINVAL;
}
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 9ea2fe34e7d3..9d5d5a397b64 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -55,6 +55,7 @@
#include "i915_drv.h"
#include "i915_gpu_error.h"
#include "i915_memcpy.h"
+#include "i915_reg.h"
#include "i915_scatterlist.h"
#include "i915_utils.h"
@@ -1221,7 +1222,10 @@ static void engine_record_registers(struct intel_engine_coredump *ee)
if (GRAPHICS_VER(i915) >= 6) {
ee->rc_psmi = ENGINE_READ(engine, RING_PSMI_CTL);
- if (GRAPHICS_VER(i915) >= 12)
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50))
+ ee->fault_reg = intel_gt_mcr_read_any(engine->gt,
+ XEHP_RING_FAULT_REG);
+ else if (GRAPHICS_VER(i915) >= 12)
ee->fault_reg = intel_uncore_read(engine->uncore,
GEN12_RING_FAULT_REG);
else if (GRAPHICS_VER(i915) >= 8)
@@ -1820,7 +1824,12 @@ static void gt_record_global_regs(struct intel_gt_coredump *gt)
if (GRAPHICS_VER(i915) == 7)
gt->err_int = intel_uncore_read(uncore, GEN7_ERR_INT);
- if (GRAPHICS_VER(i915) >= 12) {
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) {
+ gt->fault_data0 = intel_gt_mcr_read_any((struct intel_gt *)gt->_gt,
+ XEHP_FAULT_TLB_DATA0);
+ gt->fault_data1 = intel_gt_mcr_read_any((struct intel_gt *)gt->_gt,
+ XEHP_FAULT_TLB_DATA1);
+ } else if (GRAPHICS_VER(i915) >= 12) {
gt->fault_data0 = intel_uncore_read(uncore,
GEN12_FAULT_TLB_DATA0);
gt->fault_data1 = intel_uncore_read(uncore,
diff --git a/drivers/gpu/drm/i915/i915_hwmon.c b/drivers/gpu/drm/i915/i915_hwmon.c
new file mode 100644
index 000000000000..c588a17f97e9
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_hwmon.c
@@ -0,0 +1,732 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/types.h>
+
+#include "i915_drv.h"
+#include "i915_hwmon.h"
+#include "i915_reg.h"
+#include "intel_mchbar_regs.h"
+#include "intel_pcode.h"
+#include "gt/intel_gt.h"
+#include "gt/intel_gt_regs.h"
+
+/*
+ * SF_* - scale factors for particular quantities according to hwmon spec.
+ * - voltage - millivolts
+ * - power - microwatts
+ * - curr - milliamperes
+ * - energy - microjoules
+ * - time - milliseconds
+ */
+#define SF_VOLTAGE 1000
+#define SF_POWER 1000000
+#define SF_CURR 1000
+#define SF_ENERGY 1000000
+#define SF_TIME 1000
+
+struct hwm_reg {
+ i915_reg_t gt_perf_status;
+ i915_reg_t pkg_power_sku_unit;
+ i915_reg_t pkg_power_sku;
+ i915_reg_t pkg_rapl_limit;
+ i915_reg_t energy_status_all;
+ i915_reg_t energy_status_tile;
+};
+
+struct hwm_energy_info {
+ u32 reg_val_prev;
+ long accum_energy; /* Accumulated energy for energy1_input */
+};
+
+struct hwm_drvdata {
+ struct i915_hwmon *hwmon;
+ struct intel_uncore *uncore;
+ struct device *hwmon_dev;
+ struct hwm_energy_info ei; /* Energy info for energy1_input */
+ char name[12];
+ int gt_n;
+};
+
+struct i915_hwmon {
+ struct hwm_drvdata ddat;
+ struct hwm_drvdata ddat_gt[I915_MAX_GT];
+ struct mutex hwmon_lock; /* counter overflow logic and rmw */
+ struct hwm_reg rg;
+ int scl_shift_power;
+ int scl_shift_energy;
+ int scl_shift_time;
+};
+
+static void
+hwm_locked_with_pm_intel_uncore_rmw(struct hwm_drvdata *ddat,
+ i915_reg_t reg, u32 clear, u32 set)
+{
+ struct i915_hwmon *hwmon = ddat->hwmon;
+ struct intel_uncore *uncore = ddat->uncore;
+ intel_wakeref_t wakeref;
+
+ mutex_lock(&hwmon->hwmon_lock);
+
+ with_intel_runtime_pm(uncore->rpm, wakeref)
+ intel_uncore_rmw(uncore, reg, clear, set);
+
+ mutex_unlock(&hwmon->hwmon_lock);
+}
+
+/*
+ * This function's return type of u64 allows for the case where the scaling
+ * of the field taken from the 32-bit register value might cause a result to
+ * exceed 32 bits.
+ */
+static u64
+hwm_field_read_and_scale(struct hwm_drvdata *ddat, i915_reg_t rgadr,
+ u32 field_msk, int nshift, u32 scale_factor)
+{
+ struct intel_uncore *uncore = ddat->uncore;
+ intel_wakeref_t wakeref;
+ u32 reg_value;
+
+ with_intel_runtime_pm(uncore->rpm, wakeref)
+ reg_value = intel_uncore_read(uncore, rgadr);
+
+ reg_value = REG_FIELD_GET(field_msk, reg_value);
+
+ return mul_u64_u32_shr(reg_value, scale_factor, nshift);
+}
+
+static void
+hwm_field_scale_and_write(struct hwm_drvdata *ddat, i915_reg_t rgadr,
+ int nshift, unsigned int scale_factor, long lval)
+{
+ u32 nval;
+
+ /* Computation in 64-bits to avoid overflow. Round to nearest. */
+ nval = DIV_ROUND_CLOSEST_ULL((u64)lval << nshift, scale_factor);
+
+ hwm_locked_with_pm_intel_uncore_rmw(ddat, rgadr,
+ PKG_PWR_LIM_1,
+ REG_FIELD_PREP(PKG_PWR_LIM_1, nval));
+}
+
+/*
+ * hwm_energy - Obtain energy value
+ *
+ * The underlying energy hardware register is 32-bits and is subject to
+ * overflow. How long before overflow? For example, with an example
+ * scaling bit shift of 14 bits (see register *PACKAGE_POWER_SKU_UNIT) and
+ * a power draw of 1000 watts, the 32-bit counter will overflow in
+ * approximately 4.36 minutes.
+ *
+ * Examples:
+ * 1 watt: (2^32 >> 14) / 1 W / (60 * 60 * 24) secs/day -> 3 days
+ * 1000 watts: (2^32 >> 14) / 1000 W / 60 secs/min -> 4.36 minutes
+ *
+ * The function significantly increases overflow duration (from 4.36
+ * minutes) by accumulating the energy register into a 'long' as allowed by
+ * the hwmon API. Using x86_64 128 bit arithmetic (see mul_u64_u32_shr()),
+ * a 'long' of 63 bits, SF_ENERGY of 1e6 (~20 bits) and
+ * hwmon->scl_shift_energy of 14 bits we have 57 (63 - 20 + 14) bits before
+ * energy1_input overflows. This at 1000 W is an overflow duration of 278 years.
+ */
+static void
+hwm_energy(struct hwm_drvdata *ddat, long *energy)
+{
+ struct intel_uncore *uncore = ddat->uncore;
+ struct i915_hwmon *hwmon = ddat->hwmon;
+ struct hwm_energy_info *ei = &ddat->ei;
+ intel_wakeref_t wakeref;
+ i915_reg_t rgaddr;
+ u32 reg_val;
+
+ if (ddat->gt_n >= 0)
+ rgaddr = hwmon->rg.energy_status_tile;
+ else
+ rgaddr = hwmon->rg.energy_status_all;
+
+ mutex_lock(&hwmon->hwmon_lock);
+
+ with_intel_runtime_pm(uncore->rpm, wakeref)
+ reg_val = intel_uncore_read(uncore, rgaddr);
+
+ if (reg_val >= ei->reg_val_prev)
+ ei->accum_energy += reg_val - ei->reg_val_prev;
+ else
+ ei->accum_energy += UINT_MAX - ei->reg_val_prev + reg_val;
+ ei->reg_val_prev = reg_val;
+
+ *energy = mul_u64_u32_shr(ei->accum_energy, SF_ENERGY,
+ hwmon->scl_shift_energy);
+ mutex_unlock(&hwmon->hwmon_lock);
+}
+
+static ssize_t
+hwm_power1_max_interval_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+ struct i915_hwmon *hwmon = ddat->hwmon;
+ intel_wakeref_t wakeref;
+ u32 r, x, y, x_w = 2; /* 2 bits */
+ u64 tau4, out;
+
+ with_intel_runtime_pm(ddat->uncore->rpm, wakeref)
+ r = intel_uncore_read(ddat->uncore, hwmon->rg.pkg_rapl_limit);
+
+ x = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_X, r);
+ y = REG_FIELD_GET(PKG_PWR_LIM_1_TIME_Y, r);
+ /*
+ * tau = 1.x * power(2,y), x = bits(23:22), y = bits(21:17)
+ * = (4 | x) << (y - 2)
+ * where (y - 2) ensures a 1.x fixed point representation of 1.x
+ * However because y can be < 2, we compute
+ * tau4 = (4 | x) << y
+ * but add 2 when doing the final right shift to account for units
+ */
+ tau4 = ((1 << x_w) | x) << y;
+ /* val in hwmon interface units (millisec) */
+ out = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
+
+ return sysfs_emit(buf, "%llu\n", out);
+}
+
+static ssize_t
+hwm_power1_max_interval_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+ struct i915_hwmon *hwmon = ddat->hwmon;
+ u32 x, y, rxy, x_w = 2; /* 2 bits */
+ u64 tau4, r, max_win;
+ unsigned long val;
+ int ret;
+
+ ret = kstrtoul(buf, 0, &val);
+ if (ret)
+ return ret;
+
+ /*
+ * Max HW supported tau in '1.x * power(2,y)' format, x = 0, y = 0x12
+ * The hwmon->scl_shift_time default of 0xa results in a max tau of 256 seconds
+ */
+#define PKG_MAX_WIN_DEFAULT 0x12ull
+
+ /*
+ * val must be < max in hwmon interface units. The steps below are
+ * explained in i915_power1_max_interval_show()
+ */
+ r = FIELD_PREP(PKG_MAX_WIN, PKG_MAX_WIN_DEFAULT);
+ x = REG_FIELD_GET(PKG_MAX_WIN_X, r);
+ y = REG_FIELD_GET(PKG_MAX_WIN_Y, r);
+ tau4 = ((1 << x_w) | x) << y;
+ max_win = mul_u64_u32_shr(tau4, SF_TIME, hwmon->scl_shift_time + x_w);
+
+ if (val > max_win)
+ return -EINVAL;
+
+ /* val in hw units */
+ val = DIV_ROUND_CLOSEST_ULL((u64)val << hwmon->scl_shift_time, SF_TIME);
+ /* Convert to 1.x * power(2,y) */
+ if (!val)
+ return -EINVAL;
+ y = ilog2(val);
+ /* x = (val - (1 << y)) >> (y - 2); */
+ x = (val - (1ul << y)) << x_w >> y;
+
+ rxy = REG_FIELD_PREP(PKG_PWR_LIM_1_TIME_X, x) | REG_FIELD_PREP(PKG_PWR_LIM_1_TIME_Y, y);
+
+ hwm_locked_with_pm_intel_uncore_rmw(ddat, hwmon->rg.pkg_rapl_limit,
+ PKG_PWR_LIM_1_TIME, rxy);
+ return count;
+}
+
+static SENSOR_DEVICE_ATTR(power1_max_interval, 0664,
+ hwm_power1_max_interval_show,
+ hwm_power1_max_interval_store, 0);
+
+static struct attribute *hwm_attributes[] = {
+ &sensor_dev_attr_power1_max_interval.dev_attr.attr,
+ NULL
+};
+
+static umode_t hwm_attributes_visible(struct kobject *kobj,
+ struct attribute *attr, int index)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+ struct i915_hwmon *hwmon = ddat->hwmon;
+
+ if (attr == &sensor_dev_attr_power1_max_interval.dev_attr.attr)
+ return i915_mmio_reg_valid(hwmon->rg.pkg_rapl_limit) ? attr->mode : 0;
+
+ return 0;
+}
+
+static const struct attribute_group hwm_attrgroup = {
+ .attrs = hwm_attributes,
+ .is_visible = hwm_attributes_visible,
+};
+
+static const struct attribute_group *hwm_groups[] = {
+ &hwm_attrgroup,
+ NULL
+};
+
+static const struct hwmon_channel_info *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),
+ HWMON_CHANNEL_INFO(curr, HWMON_C_CRIT),
+ NULL
+};
+
+static const struct hwmon_channel_info *hwm_gt_info[] = {
+ HWMON_CHANNEL_INFO(energy, HWMON_E_INPUT),
+ NULL
+};
+
+/* I1 is exposed as power_crit or as curr_crit depending on bit 31 */
+static int hwm_pcode_read_i1(struct drm_i915_private *i915, u32 *uval)
+{
+ return snb_pcode_read_p(&i915->uncore, PCODE_POWER_SETUP,
+ POWER_SETUP_SUBCOMMAND_READ_I1, 0, uval);
+}
+
+static int hwm_pcode_write_i1(struct drm_i915_private *i915, u32 uval)
+{
+ return snb_pcode_write_p(&i915->uncore, PCODE_POWER_SETUP,
+ POWER_SETUP_SUBCOMMAND_WRITE_I1, 0, uval);
+}
+
+static umode_t
+hwm_in_is_visible(const struct hwm_drvdata *ddat, u32 attr)
+{
+ struct drm_i915_private *i915 = ddat->uncore->i915;
+
+ switch (attr) {
+ case hwmon_in_input:
+ return IS_DG1(i915) || IS_DG2(i915) ? 0444 : 0;
+ default:
+ return 0;
+ }
+}
+
+static int
+hwm_in_read(struct hwm_drvdata *ddat, u32 attr, long *val)
+{
+ struct i915_hwmon *hwmon = ddat->hwmon;
+ intel_wakeref_t wakeref;
+ u32 reg_value;
+
+ switch (attr) {
+ case hwmon_in_input:
+ with_intel_runtime_pm(ddat->uncore->rpm, wakeref)
+ reg_value = intel_uncore_read(ddat->uncore, hwmon->rg.gt_perf_status);
+ /* HW register value in units of 2.5 millivolt */
+ *val = DIV_ROUND_CLOSEST(REG_FIELD_GET(GEN12_VOLTAGE_MASK, reg_value) * 25, 10);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static umode_t
+hwm_power_is_visible(const struct hwm_drvdata *ddat, u32 attr, int chan)
+{
+ struct drm_i915_private *i915 = ddat->uncore->i915;
+ struct i915_hwmon *hwmon = ddat->hwmon;
+ u32 uval;
+
+ switch (attr) {
+ case hwmon_power_max:
+ return i915_mmio_reg_valid(hwmon->rg.pkg_rapl_limit) ? 0664 : 0;
+ case hwmon_power_rated_max:
+ return i915_mmio_reg_valid(hwmon->rg.pkg_power_sku) ? 0444 : 0;
+ case hwmon_power_crit:
+ return (hwm_pcode_read_i1(i915, &uval) ||
+ !(uval & POWER_SETUP_I1_WATTS)) ? 0 : 0644;
+ default:
+ return 0;
+ }
+}
+
+static int
+hwm_power_read(struct hwm_drvdata *ddat, u32 attr, int chan, long *val)
+{
+ struct i915_hwmon *hwmon = ddat->hwmon;
+ int ret;
+ u32 uval;
+
+ switch (attr) {
+ case hwmon_power_max:
+ *val = hwm_field_read_and_scale(ddat,
+ hwmon->rg.pkg_rapl_limit,
+ PKG_PWR_LIM_1,
+ hwmon->scl_shift_power,
+ SF_POWER);
+ return 0;
+ case hwmon_power_rated_max:
+ *val = hwm_field_read_and_scale(ddat,
+ hwmon->rg.pkg_power_sku,
+ PKG_PKG_TDP,
+ hwmon->scl_shift_power,
+ SF_POWER);
+ return 0;
+ case hwmon_power_crit:
+ ret = hwm_pcode_read_i1(ddat->uncore->i915, &uval);
+ if (ret)
+ return ret;
+ if (!(uval & POWER_SETUP_I1_WATTS))
+ return -ENODEV;
+ *val = mul_u64_u32_shr(REG_FIELD_GET(POWER_SETUP_I1_DATA_MASK, uval),
+ SF_POWER, POWER_SETUP_I1_SHIFT);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int
+hwm_power_write(struct hwm_drvdata *ddat, u32 attr, int chan, long val)
+{
+ struct i915_hwmon *hwmon = ddat->hwmon;
+ u32 uval;
+
+ switch (attr) {
+ case hwmon_power_max:
+ hwm_field_scale_and_write(ddat,
+ hwmon->rg.pkg_rapl_limit,
+ hwmon->scl_shift_power,
+ SF_POWER, val);
+ return 0;
+ case hwmon_power_crit:
+ uval = DIV_ROUND_CLOSEST_ULL(val << POWER_SETUP_I1_SHIFT, SF_POWER);
+ return hwm_pcode_write_i1(ddat->uncore->i915, uval);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static umode_t
+hwm_energy_is_visible(const struct hwm_drvdata *ddat, u32 attr)
+{
+ struct i915_hwmon *hwmon = ddat->hwmon;
+ i915_reg_t rgaddr;
+
+ switch (attr) {
+ case hwmon_energy_input:
+ if (ddat->gt_n >= 0)
+ rgaddr = hwmon->rg.energy_status_tile;
+ else
+ rgaddr = hwmon->rg.energy_status_all;
+ return i915_mmio_reg_valid(rgaddr) ? 0444 : 0;
+ default:
+ return 0;
+ }
+}
+
+static int
+hwm_energy_read(struct hwm_drvdata *ddat, u32 attr, long *val)
+{
+ switch (attr) {
+ case hwmon_energy_input:
+ hwm_energy(ddat, val);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static umode_t
+hwm_curr_is_visible(const struct hwm_drvdata *ddat, u32 attr)
+{
+ struct drm_i915_private *i915 = ddat->uncore->i915;
+ u32 uval;
+
+ switch (attr) {
+ case hwmon_curr_crit:
+ return (hwm_pcode_read_i1(i915, &uval) ||
+ (uval & POWER_SETUP_I1_WATTS)) ? 0 : 0644;
+ default:
+ return 0;
+ }
+}
+
+static int
+hwm_curr_read(struct hwm_drvdata *ddat, u32 attr, long *val)
+{
+ int ret;
+ u32 uval;
+
+ switch (attr) {
+ case hwmon_curr_crit:
+ ret = hwm_pcode_read_i1(ddat->uncore->i915, &uval);
+ if (ret)
+ return ret;
+ if (uval & POWER_SETUP_I1_WATTS)
+ return -ENODEV;
+ *val = mul_u64_u32_shr(REG_FIELD_GET(POWER_SETUP_I1_DATA_MASK, uval),
+ SF_CURR, POWER_SETUP_I1_SHIFT);
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int
+hwm_curr_write(struct hwm_drvdata *ddat, u32 attr, long val)
+{
+ u32 uval;
+
+ switch (attr) {
+ case hwmon_curr_crit:
+ uval = DIV_ROUND_CLOSEST_ULL(val << POWER_SETUP_I1_SHIFT, SF_CURR);
+ return hwm_pcode_write_i1(ddat->uncore->i915, uval);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static umode_t
+hwm_is_visible(const void *drvdata, enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ struct hwm_drvdata *ddat = (struct hwm_drvdata *)drvdata;
+
+ switch (type) {
+ case hwmon_in:
+ return hwm_in_is_visible(ddat, attr);
+ case hwmon_power:
+ return hwm_power_is_visible(ddat, attr, channel);
+ case hwmon_energy:
+ return hwm_energy_is_visible(ddat, attr);
+ case hwmon_curr:
+ return hwm_curr_is_visible(ddat, attr);
+ default:
+ return 0;
+ }
+}
+
+static int
+hwm_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
+ int channel, long *val)
+{
+ struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+
+ switch (type) {
+ case hwmon_in:
+ return hwm_in_read(ddat, attr, val);
+ case hwmon_power:
+ return hwm_power_read(ddat, attr, channel, val);
+ case hwmon_energy:
+ return hwm_energy_read(ddat, attr, val);
+ case hwmon_curr:
+ return hwm_curr_read(ddat, attr, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int
+hwm_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,
+ int channel, long val)
+{
+ struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+
+ switch (type) {
+ case hwmon_power:
+ return hwm_power_write(ddat, attr, channel, val);
+ case hwmon_curr:
+ return hwm_curr_write(ddat, attr, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static const struct hwmon_ops hwm_ops = {
+ .is_visible = hwm_is_visible,
+ .read = hwm_read,
+ .write = hwm_write,
+};
+
+static const struct hwmon_chip_info hwm_chip_info = {
+ .ops = &hwm_ops,
+ .info = hwm_info,
+};
+
+static umode_t
+hwm_gt_is_visible(const void *drvdata, enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ struct hwm_drvdata *ddat = (struct hwm_drvdata *)drvdata;
+
+ switch (type) {
+ case hwmon_energy:
+ return hwm_energy_is_visible(ddat, attr);
+ default:
+ return 0;
+ }
+}
+
+static int
+hwm_gt_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
+ int channel, long *val)
+{
+ struct hwm_drvdata *ddat = dev_get_drvdata(dev);
+
+ switch (type) {
+ case hwmon_energy:
+ return hwm_energy_read(ddat, attr, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static const struct hwmon_ops hwm_gt_ops = {
+ .is_visible = hwm_gt_is_visible,
+ .read = hwm_gt_read,
+};
+
+static const struct hwmon_chip_info hwm_gt_chip_info = {
+ .ops = &hwm_gt_ops,
+ .info = hwm_gt_info,
+};
+
+static void
+hwm_get_preregistration_info(struct drm_i915_private *i915)
+{
+ struct i915_hwmon *hwmon = i915->hwmon;
+ struct intel_uncore *uncore = &i915->uncore;
+ struct hwm_drvdata *ddat = &hwmon->ddat;
+ intel_wakeref_t wakeref;
+ u32 val_sku_unit = 0;
+ struct intel_gt *gt;
+ long energy;
+ int i;
+
+ /* Available for all Gen12+/dGfx */
+ hwmon->rg.gt_perf_status = GEN12_RPSTAT1;
+
+ if (IS_DG1(i915) || IS_DG2(i915)) {
+ hwmon->rg.pkg_power_sku_unit = PCU_PACKAGE_POWER_SKU_UNIT;
+ hwmon->rg.pkg_power_sku = PCU_PACKAGE_POWER_SKU;
+ hwmon->rg.pkg_rapl_limit = PCU_PACKAGE_RAPL_LIMIT;
+ hwmon->rg.energy_status_all = PCU_PACKAGE_ENERGY_STATUS;
+ hwmon->rg.energy_status_tile = INVALID_MMIO_REG;
+ } else if (IS_XEHPSDV(i915)) {
+ hwmon->rg.pkg_power_sku_unit = GT0_PACKAGE_POWER_SKU_UNIT;
+ hwmon->rg.pkg_power_sku = INVALID_MMIO_REG;
+ hwmon->rg.pkg_rapl_limit = GT0_PACKAGE_RAPL_LIMIT;
+ hwmon->rg.energy_status_all = GT0_PLATFORM_ENERGY_STATUS;
+ hwmon->rg.energy_status_tile = GT0_PACKAGE_ENERGY_STATUS;
+ } else {
+ hwmon->rg.pkg_power_sku_unit = INVALID_MMIO_REG;
+ hwmon->rg.pkg_power_sku = INVALID_MMIO_REG;
+ hwmon->rg.pkg_rapl_limit = INVALID_MMIO_REG;
+ hwmon->rg.energy_status_all = INVALID_MMIO_REG;
+ hwmon->rg.energy_status_tile = INVALID_MMIO_REG;
+ }
+
+ with_intel_runtime_pm(uncore->rpm, wakeref) {
+ /*
+ * The contents of register hwmon->rg.pkg_power_sku_unit do not change,
+ * so read it once and store the shift values.
+ */
+ if (i915_mmio_reg_valid(hwmon->rg.pkg_power_sku_unit))
+ val_sku_unit = intel_uncore_read(uncore,
+ hwmon->rg.pkg_power_sku_unit);
+ }
+
+ hwmon->scl_shift_power = REG_FIELD_GET(PKG_PWR_UNIT, val_sku_unit);
+ hwmon->scl_shift_energy = REG_FIELD_GET(PKG_ENERGY_UNIT, val_sku_unit);
+ hwmon->scl_shift_time = REG_FIELD_GET(PKG_TIME_UNIT, val_sku_unit);
+
+ /*
+ * Initialize 'struct hwm_energy_info', i.e. set fields to the
+ * first value of the energy register read
+ */
+ if (i915_mmio_reg_valid(hwmon->rg.energy_status_all))
+ hwm_energy(ddat, &energy);
+ if (i915_mmio_reg_valid(hwmon->rg.energy_status_tile)) {
+ for_each_gt(gt, i915, i)
+ hwm_energy(&hwmon->ddat_gt[i], &energy);
+ }
+}
+
+void i915_hwmon_register(struct drm_i915_private *i915)
+{
+ struct device *dev = i915->drm.dev;
+ struct i915_hwmon *hwmon;
+ struct device *hwmon_dev;
+ struct hwm_drvdata *ddat;
+ struct hwm_drvdata *ddat_gt;
+ struct intel_gt *gt;
+ int i;
+
+ /* hwmon is available only for dGfx */
+ if (!IS_DGFX(i915))
+ return;
+
+ hwmon = devm_kzalloc(dev, sizeof(*hwmon), GFP_KERNEL);
+ if (!hwmon)
+ return;
+
+ i915->hwmon = hwmon;
+ mutex_init(&hwmon->hwmon_lock);
+ ddat = &hwmon->ddat;
+
+ ddat->hwmon = hwmon;
+ ddat->uncore = &i915->uncore;
+ snprintf(ddat->name, sizeof(ddat->name), "i915");
+ ddat->gt_n = -1;
+
+ for_each_gt(gt, i915, i) {
+ ddat_gt = hwmon->ddat_gt + i;
+
+ ddat_gt->hwmon = hwmon;
+ ddat_gt->uncore = gt->uncore;
+ snprintf(ddat_gt->name, sizeof(ddat_gt->name), "i915_gt%u", i);
+ ddat_gt->gt_n = i;
+ }
+
+ hwm_get_preregistration_info(i915);
+
+ /* hwmon_dev points to device hwmon<i> */
+ hwmon_dev = devm_hwmon_device_register_with_info(dev, ddat->name,
+ ddat,
+ &hwm_chip_info,
+ hwm_groups);
+ if (IS_ERR(hwmon_dev)) {
+ i915->hwmon = NULL;
+ return;
+ }
+
+ ddat->hwmon_dev = hwmon_dev;
+
+ for_each_gt(gt, i915, i) {
+ ddat_gt = hwmon->ddat_gt + i;
+ /*
+ * Create per-gt directories only if a per-gt attribute is
+ * visible. Currently this is only energy
+ */
+ if (!hwm_gt_is_visible(ddat_gt, hwmon_energy, hwmon_energy_input, 0))
+ continue;
+
+ hwmon_dev = devm_hwmon_device_register_with_info(dev, ddat_gt->name,
+ ddat_gt,
+ &hwm_gt_chip_info,
+ NULL);
+ if (!IS_ERR(hwmon_dev))
+ ddat_gt->hwmon_dev = hwmon_dev;
+ }
+}
+
+void i915_hwmon_unregister(struct drm_i915_private *i915)
+{
+ fetch_and_zero(&i915->hwmon);
+}
diff --git a/drivers/gpu/drm/i915/i915_hwmon.h b/drivers/gpu/drm/i915/i915_hwmon.h
new file mode 100644
index 000000000000..7ca9cf2c34c9
--- /dev/null
+++ b/drivers/gpu/drm/i915/i915_hwmon.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: MIT */
+
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+#ifndef __I915_HWMON_H__
+#define __I915_HWMON_H__
+
+struct drm_i915_private;
+
+#if IS_REACHABLE(CONFIG_HWMON)
+void i915_hwmon_register(struct drm_i915_private *i915);
+void i915_hwmon_unregister(struct drm_i915_private *i915);
+#else
+static inline void i915_hwmon_register(struct drm_i915_private *i915) { };
+static inline void i915_hwmon_unregister(struct drm_i915_private *i915) { };
+#endif
+
+#endif /* __I915_HWMON_H__ */
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 86a42d9e8041..edfe363af838 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -28,7 +28,6 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/circ_buf.h>
#include <linux/slab.h>
#include <linux/sysrq.h>
@@ -248,7 +247,7 @@ void gen3_irq_reset(struct intel_uncore *uncore, i915_reg_t imr,
intel_uncore_posting_read(uncore, iir);
}
-void gen2_irq_reset(struct intel_uncore *uncore)
+static void gen2_irq_reset(struct intel_uncore *uncore)
{
intel_uncore_write16(uncore, GEN2_IMR, 0xffff);
intel_uncore_posting_read16(uncore, GEN2_IMR);
@@ -309,8 +308,8 @@ void gen3_irq_init(struct intel_uncore *uncore,
intel_uncore_posting_read(uncore, imr);
}
-void gen2_irq_init(struct intel_uncore *uncore,
- u32 imr_val, u32 ier_val)
+static void gen2_irq_init(struct intel_uncore *uncore,
+ u32 imr_val, u32 ier_val)
{
gen2_assert_iir_is_zero(uncore);
@@ -325,15 +324,10 @@ i915_hotplug_interrupt_update_locked(struct drm_i915_private *dev_priv,
u32 mask,
u32 bits)
{
- u32 val;
-
lockdep_assert_held(&dev_priv->irq_lock);
drm_WARN_ON(&dev_priv->drm, bits & ~mask);
- val = intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_EN);
- val &= ~mask;
- val |= bits;
- intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_EN, val);
+ intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_EN, mask, bits);
}
/**
@@ -1057,8 +1051,8 @@ static void ivb_parity_work(struct work_struct *work)
if (drm_WARN_ON(&dev_priv->drm, !dev_priv->l3_parity.which_slice))
goto out;
- misccpctl = intel_uncore_read(&dev_priv->uncore, GEN7_MISCCPCTL);
- intel_uncore_write(&dev_priv->uncore, GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE);
+ misccpctl = intel_uncore_rmw(&dev_priv->uncore, GEN7_MISCCPCTL,
+ GEN7_DOP_CLOCK_GATE_ENABLE, 0);
intel_uncore_posting_read(&dev_priv->uncore, GEN7_MISCCPCTL);
while ((slice = ffs(dev_priv->l3_parity.which_slice)) != 0) {
@@ -1091,8 +1085,9 @@ static void ivb_parity_work(struct work_struct *work)
kobject_uevent_env(&dev_priv->drm.primary->kdev->kobj,
KOBJ_CHANGE, parity_event);
- DRM_DEBUG("Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n",
- slice, row, bank, subbank);
+ drm_dbg(&dev_priv->drm,
+ "Parity error: Slice = %d, Row = %d, Bank = %d, Sub bank = %d.\n",
+ slice, row, bank, subbank);
kfree(parity_event[4]);
kfree(parity_event[3]);
@@ -1689,8 +1684,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg)
* bits this time around.
*/
intel_uncore_write(&dev_priv->uncore, VLV_MASTER_IER, 0);
- ier = intel_uncore_read(&dev_priv->uncore, VLV_IER);
- intel_uncore_write(&dev_priv->uncore, VLV_IER, 0);
+ ier = intel_uncore_rmw(&dev_priv->uncore, VLV_IER, ~0, 0);
if (gt_iir)
intel_uncore_write(&dev_priv->uncore, GTIIR, gt_iir);
@@ -1775,8 +1769,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
* bits this time around.
*/
intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, 0);
- ier = intel_uncore_read(&dev_priv->uncore, VLV_IER);
- intel_uncore_write(&dev_priv->uncore, VLV_IER, 0);
+ ier = intel_uncore_rmw(&dev_priv->uncore, VLV_IER, ~0, 0);
gen8_gt_irq_handler(to_gt(dev_priv), master_ctl);
@@ -1981,8 +1974,7 @@ static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
if (ddi_hotplug_trigger) {
u32 dig_hotplug_reg;
- dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, SHOTPLUG_CTL_DDI);
- intel_uncore_write(&dev_priv->uncore, SHOTPLUG_CTL_DDI, dig_hotplug_reg);
+ dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI, 0, 0);
intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
ddi_hotplug_trigger, dig_hotplug_reg,
@@ -1993,8 +1985,7 @@ static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
if (tc_hotplug_trigger) {
u32 dig_hotplug_reg;
- dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, SHOTPLUG_CTL_TC);
- intel_uncore_write(&dev_priv->uncore, SHOTPLUG_CTL_TC, 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,
@@ -2019,8 +2010,7 @@ static void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
if (hotplug_trigger) {
u32 dig_hotplug_reg;
- dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG);
- intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, 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,
@@ -2031,8 +2021,7 @@ static void spt_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
if (hotplug2_trigger) {
u32 dig_hotplug_reg;
- dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG2);
- intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG2, 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,
@@ -2052,8 +2041,7 @@ static void ilk_hpd_irq_handler(struct drm_i915_private *dev_priv,
{
u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
- dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL);
- intel_uncore_write(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, dig_hotplug_reg);
+ 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,
@@ -2232,8 +2220,7 @@ static void bxt_hpd_irq_handler(struct drm_i915_private *dev_priv,
{
u32 dig_hotplug_reg, pin_mask = 0, long_mask = 0;
- dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG);
- intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, 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,
@@ -2252,8 +2239,7 @@ static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
if (trigger_tc) {
u32 dig_hotplug_reg;
- dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL);
- intel_uncore_write(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, 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,
@@ -2264,8 +2250,7 @@ static void gen11_hpd_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
if (trigger_tbt) {
u32 dig_hotplug_reg;
- dig_hotplug_reg = intel_uncore_read(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL);
- intel_uncore_write(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, 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,
@@ -2355,8 +2340,7 @@ gen8_de_misc_irq_handler(struct drm_i915_private *dev_priv, u32 iir)
else
iir_reg = EDP_PSR_IIR;
- psr_iir = intel_uncore_read(&dev_priv->uncore, iir_reg);
- intel_uncore_write(&dev_priv->uncore, iir_reg, psr_iir);
+ psr_iir = intel_uncore_rmw(&dev_priv->uncore, iir_reg, 0, 0);
if (psr_iir)
found = true;
@@ -2426,8 +2410,7 @@ static void gen11_dsi_te_interrupt_handler(struct drm_i915_private *dev_priv,
/* clear TE in dsi IIR */
port = (te_trigger & DSI1_TE) ? PORT_B : PORT_A;
- tmp = intel_uncore_read(&dev_priv->uncore, DSI_INTR_IDENT_REG(port));
- intel_uncore_write(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), tmp);
+ 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)
@@ -2791,7 +2774,8 @@ static irqreturn_t dg1_irq_handler(int irq, void *arg)
master_ctl = raw_reg_read(regs, GEN11_GFX_MSTR_IRQ);
raw_reg_write(regs, GEN11_GFX_MSTR_IRQ, master_ctl);
} else {
- DRM_ERROR("Tile not supported: 0x%08x\n", master_tile_ctl);
+ drm_err(&i915->drm, "Tile not supported: 0x%08x\n",
+ master_tile_ctl);
dg1_master_intr_enable(regs);
return IRQ_NONE;
}
@@ -2884,7 +2868,6 @@ static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc,
{
struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
enum port port;
- u32 tmp;
if (!(intel_crtc->mode_flags &
(I915_MODE_FLAG_DSI_USE_TE1 | I915_MODE_FLAG_DSI_USE_TE0)))
@@ -2896,16 +2879,10 @@ static bool gen11_dsi_configure_te(struct intel_crtc *intel_crtc,
else
port = PORT_A;
- tmp = intel_uncore_read(&dev_priv->uncore, DSI_INTR_MASK_REG(port));
- if (enable)
- tmp &= ~DSI_TE_EVENT;
- else
- tmp |= DSI_TE_EVENT;
-
- intel_uncore_write(&dev_priv->uncore, DSI_INTR_MASK_REG(port), tmp);
+ intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_MASK_REG(port), DSI_TE_EVENT,
+ enable ? 0 : DSI_TE_EVENT);
- tmp = intel_uncore_read(&dev_priv->uncore, DSI_INTR_IDENT_REG(port));
- intel_uncore_write(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), tmp);
+ intel_uncore_rmw(&dev_priv->uncore, DSI_INTR_IDENT_REG(port), 0, 0);
return true;
}
@@ -3020,7 +2997,7 @@ static void vlv_display_irq_reset(struct drm_i915_private *dev_priv)
intel_uncore_write(uncore, DPINVGTT, DPINVGTT_STATUS_MASK_VLV);
i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0);
- intel_uncore_write(uncore, PORT_HOTPLUG_STAT, intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT));
+ intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0);
i9xx_pipestat_irq_reset(dev_priv);
@@ -3118,7 +3095,7 @@ static void gen8_irq_reset(struct drm_i915_private *dev_priv)
{
struct intel_uncore *uncore = &dev_priv->uncore;
- gen8_master_intr_disable(dev_priv->uncore.regs);
+ gen8_master_intr_disable(uncore->regs);
gen8_gt_irq_reset(to_gt(dev_priv));
gen8_display_irq_reset(dev_priv);
@@ -3250,7 +3227,7 @@ static void cherryview_irq_reset(struct drm_i915_private *dev_priv)
{
struct intel_uncore *uncore = &dev_priv->uncore;
- intel_uncore_write(&dev_priv->uncore, GEN8_MASTER_IRQ, 0);
+ intel_uncore_write(uncore, GEN8_MASTER_IRQ, 0);
intel_uncore_posting_read(&dev_priv->uncore, GEN8_MASTER_IRQ);
gen8_gt_irq_reset(to_gt(dev_priv));
@@ -3290,23 +3267,20 @@ static u32 ibx_hotplug_enables(struct drm_i915_private *i915,
static void ibx_hpd_detection_setup(struct drm_i915_private *dev_priv)
{
- u32 hotplug;
-
/*
* 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+.
*/
- hotplug = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG);
- 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);
- hotplug |= intel_hpd_hotplug_enables(dev_priv, ibx_hotplug_enables);
- intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, hotplug);
+ 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)
@@ -3353,30 +3327,24 @@ static u32 icp_tc_hotplug_enables(struct drm_i915_private *i915,
static void icp_ddi_hpd_detection_setup(struct drm_i915_private *dev_priv)
{
- u32 hotplug;
-
- hotplug = intel_uncore_read(&dev_priv->uncore, SHOTPLUG_CTL_DDI);
- hotplug &= ~(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));
- hotplug |= intel_hpd_hotplug_enables(dev_priv, icp_ddi_hotplug_enables);
- intel_uncore_write(&dev_priv->uncore, SHOTPLUG_CTL_DDI, hotplug);
+ 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)
{
- u32 hotplug;
-
- hotplug = intel_uncore_read(&dev_priv->uncore, SHOTPLUG_CTL_TC);
- hotplug &= ~(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));
- hotplug |= intel_hpd_hotplug_enables(dev_priv, icp_tc_hotplug_enables);
- intel_uncore_write(&dev_priv->uncore, SHOTPLUG_CTL_TC, hotplug);
+ 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)
@@ -3411,62 +3379,54 @@ static u32 gen11_hotplug_enables(struct drm_i915_private *i915,
}
}
-static void dg1_hpd_irq_setup(struct drm_i915_private *dev_priv)
+static void dg1_hpd_invert(struct drm_i915_private *i915)
{
- u32 val;
-
- val = intel_uncore_read(&dev_priv->uncore, SOUTH_CHICKEN1);
- val |= (INVERT_DDIA_HPD |
- INVERT_DDIB_HPD |
- INVERT_DDIC_HPD |
- INVERT_DDID_HPD);
- intel_uncore_write(&dev_priv->uncore, SOUTH_CHICKEN1, val);
+ 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)
{
- u32 hotplug;
-
- hotplug = intel_uncore_read(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL);
- hotplug &= ~(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));
- hotplug |= intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables);
- intel_uncore_write(&dev_priv->uncore, GEN11_TC_HOTPLUG_CTL, hotplug);
+ 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)
{
- u32 hotplug;
-
- hotplug = intel_uncore_read(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL);
- hotplug &= ~(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));
- hotplug |= intel_hpd_hotplug_enables(dev_priv, gen11_hotplug_enables);
- intel_uncore_write(&dev_priv->uncore, GEN11_TBT_HOTPLUG_CTL, hotplug);
+ 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;
- u32 val;
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);
- val = intel_uncore_read(&dev_priv->uncore, GEN11_DE_HPD_IMR);
- val &= ~hotplug_irqs;
- val |= ~enabled_irqs & hotplug_irqs;
- intel_uncore_write(&dev_priv->uncore, GEN11_DE_HPD_IMR, val);
+ 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);
@@ -3506,29 +3466,22 @@ static u32 spt_hotplug2_enables(struct drm_i915_private *i915,
static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv)
{
- u32 val, hotplug;
-
/* Display WA #1179 WaHardHangonHotPlug: cnp */
if (HAS_PCH_CNP(dev_priv)) {
- val = intel_uncore_read(&dev_priv->uncore, SOUTH_CHICKEN1);
- val &= ~CHASSIS_CLK_REQ_DURATION_MASK;
- val |= CHASSIS_CLK_REQ_DURATION(0xf);
- intel_uncore_write(&dev_priv->uncore, SOUTH_CHICKEN1, val);
+ intel_uncore_rmw(&dev_priv->uncore, SOUTH_CHICKEN1, CHASSIS_CLK_REQ_DURATION_MASK,
+ CHASSIS_CLK_REQ_DURATION(0xf));
}
/* Enable digital hotplug on the PCH */
- hotplug = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG);
- hotplug &= ~(PORTA_HOTPLUG_ENABLE |
- PORTB_HOTPLUG_ENABLE |
- PORTC_HOTPLUG_ENABLE |
- PORTD_HOTPLUG_ENABLE);
- hotplug |= intel_hpd_hotplug_enables(dev_priv, spt_hotplug_enables);
- intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, hotplug);
+ 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));
- hotplug = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG2);
- hotplug &= ~PORTE_HOTPLUG_ENABLE;
- hotplug |= intel_hpd_hotplug_enables(dev_priv, spt_hotplug2_enables);
- intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG2, hotplug);
+ 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)
@@ -3560,18 +3513,14 @@ static u32 ilk_hotplug_enables(struct drm_i915_private *i915,
static void ilk_hpd_detection_setup(struct drm_i915_private *dev_priv)
{
- u32 hotplug;
-
/*
* 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+.
*/
- hotplug = intel_uncore_read(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL);
- hotplug &= ~(DIGITAL_PORTA_HOTPLUG_ENABLE |
- DIGITAL_PORTA_PULSE_DURATION_MASK);
- hotplug |= intel_hpd_hotplug_enables(dev_priv, ilk_hotplug_enables);
- intel_uncore_write(&dev_priv->uncore, DIGITAL_PORT_HOTPLUG_CNTRL, hotplug);
+ 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)
@@ -3619,17 +3568,12 @@ static u32 bxt_hotplug_enables(struct drm_i915_private *i915,
static void bxt_hpd_detection_setup(struct drm_i915_private *dev_priv)
{
- u32 hotplug;
-
- hotplug = intel_uncore_read(&dev_priv->uncore, PCH_PORT_HOTPLUG);
- hotplug &= ~(PORTA_HOTPLUG_ENABLE |
- PORTB_HOTPLUG_ENABLE |
- PORTC_HOTPLUG_ENABLE |
- BXT_DDIA_HPD_INVERT |
- BXT_DDIB_HPD_INVERT |
- BXT_DDIC_HPD_INVERT);
- hotplug |= intel_hpd_hotplug_enables(dev_priv, bxt_hotplug_enables);
- intel_uncore_write(&dev_priv->uncore, PCH_PORT_HOTPLUG, hotplug);
+ 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)
@@ -3928,7 +3872,7 @@ static void i8xx_irq_reset(struct drm_i915_private *dev_priv)
i9xx_pipestat_irq_reset(dev_priv);
- GEN2_IRQ_RESET(uncore);
+ gen2_irq_reset(uncore);
dev_priv->irq_mask = ~0u;
}
@@ -3954,7 +3898,7 @@ static void i8xx_irq_postinstall(struct drm_i915_private *dev_priv)
I915_MASTER_ERROR_INTERRUPT |
I915_USER_INTERRUPT;
- GEN2_IRQ_INIT(uncore, dev_priv->irq_mask, enable_mask);
+ gen2_irq_init(uncore, dev_priv->irq_mask, enable_mask);
/* Interrupt setup is already guaranteed to be single-threaded, this is
* just to make the assert_spin_locked check happy. */
@@ -3997,7 +3941,7 @@ static void i8xx_error_irq_ack(struct drm_i915_private *i915,
static void i8xx_error_irq_handler(struct drm_i915_private *dev_priv,
u16 eir, u16 eir_stuck)
{
- DRM_DEBUG("Master Error: EIR 0x%04x\n", eir);
+ drm_dbg(&dev_priv->drm, "Master Error: EIR 0x%04x\n", eir);
if (eir_stuck)
drm_dbg(&dev_priv->drm, "EIR stuck: 0x%04x, masked\n",
@@ -4009,9 +3953,7 @@ static void i9xx_error_irq_ack(struct drm_i915_private *dev_priv,
{
u32 emr;
- *eir = intel_uncore_read(&dev_priv->uncore, EIR);
-
- intel_uncore_write(&dev_priv->uncore, EIR, *eir);
+ *eir = intel_uncore_rmw(&dev_priv->uncore, EIR, 0, 0);
*eir_stuck = intel_uncore_read(&dev_priv->uncore, EIR);
if (*eir_stuck == 0)
@@ -4027,15 +3969,14 @@ static void i9xx_error_irq_ack(struct drm_i915_private *dev_priv,
* (or by a GPU reset) so we mask any bit that
* remains set.
*/
- emr = intel_uncore_read(&dev_priv->uncore, EMR);
- intel_uncore_write(&dev_priv->uncore, EMR, 0xffffffff);
+ emr = intel_uncore_rmw(&dev_priv->uncore, EMR, ~0, 0xffffffff);
intel_uncore_write(&dev_priv->uncore, EMR, emr | *eir_stuck);
}
static void i9xx_error_irq_handler(struct drm_i915_private *dev_priv,
u32 eir, u32 eir_stuck)
{
- DRM_DEBUG("Master Error, EIR 0x%08x\n", eir);
+ drm_dbg(&dev_priv->drm, "Master Error, EIR 0x%08x\n", eir);
if (eir_stuck)
drm_dbg(&dev_priv->drm, "EIR stuck: 0x%08x, masked\n",
@@ -4095,7 +4036,7 @@ static void i915_irq_reset(struct drm_i915_private *dev_priv)
if (I915_HAS_HOTPLUG(dev_priv)) {
i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
- intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_STAT, intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT));
+ intel_uncore_rmw(&dev_priv->uncore, PORT_HOTPLUG_STAT, 0, 0);
}
i9xx_pipestat_irq_reset(dev_priv);
@@ -4109,8 +4050,8 @@ static void i915_irq_postinstall(struct drm_i915_private *dev_priv)
struct intel_uncore *uncore = &dev_priv->uncore;
u32 enable_mask;
- intel_uncore_write(&dev_priv->uncore, EMR, ~(I915_ERROR_PAGE_TABLE |
- I915_ERROR_MEMORY_REFRESH));
+ intel_uncore_write(uncore, EMR, ~(I915_ERROR_PAGE_TABLE |
+ I915_ERROR_MEMORY_REFRESH));
/* Unmask the interrupts that we always want on. */
dev_priv->irq_mask =
@@ -4205,7 +4146,7 @@ static void i965_irq_reset(struct drm_i915_private *dev_priv)
struct intel_uncore *uncore = &dev_priv->uncore;
i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0);
- intel_uncore_write(&dev_priv->uncore, PORT_HOTPLUG_STAT, intel_uncore_read(&dev_priv->uncore, PORT_HOTPLUG_STAT));
+ intel_uncore_rmw(uncore, PORT_HOTPLUG_STAT, 0, 0);
i9xx_pipestat_irq_reset(dev_priv);
@@ -4232,7 +4173,7 @@ static void i965_irq_postinstall(struct drm_i915_private *dev_priv)
error_mask = ~(I915_ERROR_PAGE_TABLE |
I915_ERROR_MEMORY_REFRESH);
}
- intel_uncore_write(&dev_priv->uncore, EMR, error_mask);
+ intel_uncore_write(uncore, EMR, error_mask);
/* Unmask the interrupts that we always want on. */
dev_priv->irq_mask =
@@ -4383,7 +4324,6 @@ void intel_hpd_irq_setup(struct drm_i915_private *i915)
*/
void intel_irq_init(struct drm_i915_private *dev_priv)
{
- struct drm_device *dev = &dev_priv->drm;
int i;
INIT_WORK(&dev_priv->l3_parity.error_work, ivb_parity_work);
@@ -4399,9 +4339,9 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
intel_hpd_init_pins(dev_priv);
- intel_hpd_init_work(dev_priv);
+ intel_hpd_init_early(dev_priv);
- dev->vblank_disable_immediate = true;
+ dev_priv->drm.vblank_disable_immediate = true;
/* Most platforms treat the display irq block as an always-on
* power domain. vlv/chv can disable it at runtime and need
@@ -4413,15 +4353,6 @@ 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;
- dev_priv->display.hotplug.hpd_storm_threshold = HPD_STORM_DEFAULT_THRESHOLD;
- /* If we have MST support, we want to avoid doing short HPD IRQ storm
- * detection, as short HPD storms will occur as a natural part of
- * sideband messaging with MST.
- * On older platforms however, IRQ storms can occur with both long and
- * short pulses, as seen on some G4x systems.
- */
- dev_priv->display.hotplug.hpd_short_storm_enabled = !HAS_DP_MST(dev_priv);
-
if (HAS_GMCH(dev_priv)) {
if (I915_HAS_HOTPLUG(dev_priv))
dev_priv->display.funcs.hotplug = &i915_hpd_funcs;
diff --git a/drivers/gpu/drm/i915/i915_irq.h b/drivers/gpu/drm/i915/i915_irq.h
index 82639d9d7e82..9b004fc3444e 100644
--- a/drivers/gpu/drm/i915/i915_irq.h
+++ b/drivers/gpu/drm/i915/i915_irq.h
@@ -90,12 +90,9 @@ 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 gen2_irq_reset(struct intel_uncore *uncore);
void gen3_irq_reset(struct intel_uncore *uncore, i915_reg_t imr,
i915_reg_t iir, i915_reg_t ier);
-void gen2_irq_init(struct intel_uncore *uncore,
- u32 imr_val, u32 ier_val);
void gen3_irq_init(struct intel_uncore *uncore,
i915_reg_t imr, u32 imr_val,
i915_reg_t ier, u32 ier_val,
@@ -111,9 +108,6 @@ void gen3_irq_init(struct intel_uncore *uncore,
#define GEN3_IRQ_RESET(uncore, type) \
gen3_irq_reset((uncore), type##IMR, type##IIR, type##IER)
-#define GEN2_IRQ_RESET(uncore) \
- gen2_irq_reset(uncore)
-
#define GEN8_IRQ_INIT_NDX(uncore, type, which, imr_val, ier_val) \
({ \
unsigned int which_ = which; \
@@ -129,7 +123,4 @@ void gen3_irq_init(struct intel_uncore *uncore,
type##IER, ier_val, \
type##IIR)
-#define GEN2_IRQ_INIT(uncore, imr_val, ier_val) \
- gen2_irq_init((uncore), imr_val, ier_val)
-
#endif /* __I915_IRQ_H__ */
diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c
index cd4487a1d3be..6da9784fe4a2 100644
--- a/drivers/gpu/drm/i915/i915_pci.c
+++ b/drivers/gpu/drm/i915/i915_pci.c
@@ -1023,6 +1023,8 @@ static const struct intel_device_info adl_p_info = {
.has_logical_ring_contexts = 1, \
.has_logical_ring_elsq = 1, \
.has_mslice_steering = 1, \
+ .has_oa_bpc_reporting = 1, \
+ .has_oa_slice_contrib_limits = 1, \
.has_rc6 = 1, \
.has_reset_engine = 1, \
.has_rps = 1, \
@@ -1042,7 +1044,6 @@ static const struct intel_device_info xehpsdv_info = {
PLATFORM(INTEL_XEHPSDV),
NO_DISPLAY,
.has_64k_pages = 1,
- .needs_compact_pt = 1,
.has_media_ratio_mode = 1,
.__runtime.platform_engine_mask =
BIT(RCS0) | BIT(BCS0) |
@@ -1064,8 +1065,8 @@ static const struct intel_device_info xehpsdv_info = {
.has_64k_pages = 1, \
.has_guc_deprivilege = 1, \
.has_heci_pxp = 1, \
- .needs_compact_pt = 1, \
.has_media_ratio_mode = 1, \
+ .display.has_cdclk_squash = 1, \
.__runtime.platform_engine_mask = \
BIT(RCS0) | BIT(BCS0) | \
BIT(VECS0) | BIT(VECS1) | \
@@ -1077,7 +1078,6 @@ static const struct intel_device_info dg2_info = {
XE_LPD_FEATURES,
.__runtime.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) |
BIT(TRANSCODER_C) | BIT(TRANSCODER_D),
- .require_force_probe = 1,
};
static const struct intel_device_info ats_m_info = {
@@ -1144,6 +1144,9 @@ static const struct intel_device_info mtl_info = {
.display.has_modular_fia = 1,
.extra_gt_list = xelpmp_extra_gt,
.has_flat_ccs = 0,
+ .has_gmd_id = 1,
+ .has_guc_deprivilege = 1,
+ .has_mslice_steering = 0,
.has_snoop = 1,
.__runtime.memory_regions = REGION_SMEM | REGION_STOLEN_LMEM,
.__runtime.platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(CCS0),
@@ -1296,9 +1299,7 @@ bool i915_pci_resource_valid(struct pci_dev *pdev, int bar)
static bool intel_mmio_bar_valid(struct pci_dev *pdev, struct intel_device_info *intel_info)
{
- int gttmmaddr_bar = intel_info->__runtime.graphics.ip.ver == 2 ? GEN2_GTTMMADR_BAR : GTTMMADR_BAR;
-
- return i915_pci_resource_valid(pdev, gttmmaddr_bar);
+ return i915_pci_resource_valid(pdev, intel_mmio_bar(intel_info->__runtime.graphics.ip.ver));
}
static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c
index 0defbb43ceea..00e09bb18b13 100644
--- a/drivers/gpu/drm/i915/i915_perf.c
+++ b/drivers/gpu/drm/i915/i915_perf.c
@@ -204,15 +204,18 @@
#include "gt/intel_gpu_commands.h"
#include "gt/intel_gt.h"
#include "gt/intel_gt_clock_utils.h"
+#include "gt/intel_gt_mcr.h"
#include "gt/intel_gt_regs.h"
#include "gt/intel_lrc.h"
#include "gt/intel_lrc_reg.h"
#include "gt/intel_ring.h"
+#include "gt/uc/intel_guc_slpc.h"
#include "i915_drv.h"
#include "i915_file_private.h"
#include "i915_perf.h"
#include "i915_perf_oa_regs.h"
+#include "i915_reg.h"
/* HW requires this to be a power of two, between 128k and 16M, though driver
* is currently generally designed assuming the largest 16M size is used such
@@ -286,6 +289,7 @@ static u32 i915_perf_stream_paranoid = true;
#define OAREPORT_REASON_CTX_SWITCH (1<<3)
#define OAREPORT_REASON_CLK_RATIO (1<<5)
+#define HAS_MI_SET_PREDICATE(i915) (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50))
/* For sysctl proc_dointvec_minmax of i915_oa_max_sample_rate
*
@@ -320,6 +324,8 @@ static const struct i915_oa_format oa_formats[I915_OA_FORMAT_MAX] = {
[I915_OA_FORMAT_A12] = { 0, 64 },
[I915_OA_FORMAT_A12_B8_C8] = { 2, 128 },
[I915_OA_FORMAT_A32u40_A4u32_B8_C8] = { 5, 256 },
+ [I915_OAR_FORMAT_A32u40_A4u32_B8_C8] = { 5, 256 },
+ [I915_OA_FORMAT_A24u40_A14u32_B8_C8] = { 5, 256 },
};
#define SAMPLE_OA_REPORT (1<<0)
@@ -462,7 +468,7 @@ static u32 gen7_oa_hw_tail_read(struct i915_perf_stream *stream)
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;
+ int report_size = stream->oa_buffer.format->size;
unsigned long flags;
bool pollin;
u32 hw_tail;
@@ -525,9 +531,9 @@ static bool oa_buffer_check_unlocked(struct i915_perf_stream *stream)
if (OA_TAKEN(hw_tail, tail) > report_size &&
__ratelimit(&stream->perf->tail_pointer_race))
- DRM_NOTE("unlanded report(s) head=0x%x "
- "tail=0x%x hw_tail=0x%x\n",
- head, tail, hw_tail);
+ 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;
@@ -599,7 +605,7 @@ static int append_oa_sample(struct i915_perf_stream *stream,
size_t *offset,
const u8 *report)
{
- int report_size = stream->oa_buffer.format_size;
+ int report_size = stream->oa_buffer.format->size;
struct drm_i915_perf_record_header header;
header.type = DRM_I915_PERF_RECORD_SAMPLE;
@@ -649,14 +655,13 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
size_t *offset)
{
struct intel_uncore *uncore = stream->uncore;
- int report_size = stream->oa_buffer.format_size;
+ int report_size = stream->oa_buffer.format->size;
u8 *oa_buf_base = stream->oa_buffer.vaddr;
u32 gtt_offset = i915_ggtt_offset(stream->oa_buffer.vma);
u32 mask = (OA_BUFFER_SIZE - 1);
size_t start_offset = *offset;
unsigned long flags;
u32 head, tail;
- u32 taken;
int ret = 0;
if (drm_WARN_ON(&uncore->i915->drm, !stream->enabled))
@@ -692,7 +697,7 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
for (/* none */;
- (taken = OA_TAKEN(tail, head));
+ OA_TAKEN(tail, head);
head = (head + report_size) & mask) {
u8 *report = oa_buf_base + head;
u32 *report32 = (void *)report;
@@ -774,7 +779,7 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
* switches since it's not-uncommon for periodic samples to
* identify a switch before any 'context switch' report.
*/
- if (!stream->perf->exclusive_stream->ctx ||
+ if (!stream->ctx ||
stream->specific_ctx_id == ctx_id ||
stream->oa_buffer.last_ctx_id == stream->specific_ctx_id ||
reason & OAREPORT_REASON_CTX_SWITCH) {
@@ -783,7 +788,7 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
* While filtering for a single context we avoid
* leaking the IDs of other contexts.
*/
- if (stream->perf->exclusive_stream->ctx &&
+ if (stream->ctx &&
stream->specific_ctx_id != ctx_id) {
report32[2] = INVALID_CTX_ID;
}
@@ -943,14 +948,13 @@ static int gen7_append_oa_reports(struct i915_perf_stream *stream,
size_t *offset)
{
struct intel_uncore *uncore = stream->uncore;
- int report_size = stream->oa_buffer.format_size;
+ int report_size = stream->oa_buffer.format->size;
u8 *oa_buf_base = stream->oa_buffer.vaddr;
u32 gtt_offset = i915_ggtt_offset(stream->oa_buffer.vma);
u32 mask = (OA_BUFFER_SIZE - 1);
size_t start_offset = *offset;
unsigned long flags;
u32 head, tail;
- u32 taken;
int ret = 0;
if (drm_WARN_ON(&uncore->i915->drm, !stream->enabled))
@@ -984,7 +988,7 @@ static int gen7_append_oa_reports(struct i915_perf_stream *stream,
for (/* none */;
- (taken = OA_TAKEN(tail, head));
+ OA_TAKEN(tail, head);
head = (head + report_size) & mask) {
u8 *report = oa_buf_base + head;
u32 *report32 = (void *)report;
@@ -1012,7 +1016,8 @@ static int gen7_append_oa_reports(struct i915_perf_stream *stream,
*/
if (report32[0] == 0) {
if (__ratelimit(&stream->perf->spurious_report_rs))
- DRM_NOTE("Skipping spurious, invalid OA report\n");
+ drm_notice(&uncore->i915->drm,
+ "Skipping spurious, invalid OA report\n");
continue;
}
@@ -1233,6 +1238,196 @@ retry:
return stream->pinned_ctx;
}
+static int
+__store_reg_to_mem(struct i915_request *rq, i915_reg_t reg, u32 ggtt_offset)
+{
+ u32 *cs, cmd;
+
+ cmd = MI_STORE_REGISTER_MEM | MI_SRM_LRM_GLOBAL_GTT;
+ if (GRAPHICS_VER(rq->engine->i915) >= 8)
+ cmd++;
+
+ cs = intel_ring_begin(rq, 4);
+ if (IS_ERR(cs))
+ return PTR_ERR(cs);
+
+ *cs++ = cmd;
+ *cs++ = i915_mmio_reg_offset(reg);
+ *cs++ = ggtt_offset;
+ *cs++ = 0;
+
+ intel_ring_advance(rq, cs);
+
+ return 0;
+}
+
+static int
+__read_reg(struct intel_context *ce, i915_reg_t reg, u32 ggtt_offset)
+{
+ struct i915_request *rq;
+ int err;
+
+ rq = i915_request_create(ce);
+ if (IS_ERR(rq))
+ return PTR_ERR(rq);
+
+ i915_request_get(rq);
+
+ err = __store_reg_to_mem(rq, reg, ggtt_offset);
+
+ i915_request_add(rq);
+ if (!err && i915_request_wait(rq, 0, HZ / 2) < 0)
+ err = -ETIME;
+
+ i915_request_put(rq);
+
+ return err;
+}
+
+static int
+gen12_guc_sw_ctx_id(struct intel_context *ce, u32 *ctx_id)
+{
+ struct i915_vma *scratch;
+ u32 *val;
+ int err;
+
+ scratch = __vm_create_scratch_for_read_pinned(&ce->engine->gt->ggtt->vm, 4);
+ if (IS_ERR(scratch))
+ return PTR_ERR(scratch);
+
+ err = i915_vma_sync(scratch);
+ if (err)
+ goto err_scratch;
+
+ err = __read_reg(ce, RING_EXECLIST_STATUS_HI(ce->engine->mmio_base),
+ i915_ggtt_offset(scratch));
+ if (err)
+ goto err_scratch;
+
+ val = i915_gem_object_pin_map_unlocked(scratch->obj, I915_MAP_WB);
+ if (IS_ERR(val)) {
+ err = PTR_ERR(val);
+ goto err_scratch;
+ }
+
+ *ctx_id = *val;
+ i915_gem_object_unpin_map(scratch->obj);
+
+err_scratch:
+ i915_vma_unpin_and_release(&scratch, 0);
+ return err;
+}
+
+/*
+ * For execlist mode of submission, pick an unused context id
+ * 0 - (NUM_CONTEXT_TAG -1) are used by other contexts
+ * XXX_MAX_CONTEXT_HW_ID is used by idle context
+ *
+ * For GuC mode of submission read context id from the upper dword of the
+ * EXECLIST_STATUS register. Note that we read this value only once and expect
+ * that the value stays fixed for the entire OA use case. There are cases where
+ * GuC KMD implementation may deregister a context to reuse it's context id, but
+ * we prevent that from happening to the OA context by pinning it.
+ */
+static int gen12_get_render_context_id(struct i915_perf_stream *stream)
+{
+ u32 ctx_id, mask;
+ int ret;
+
+ if (intel_engine_uses_guc(stream->engine)) {
+ ret = gen12_guc_sw_ctx_id(stream->pinned_ctx, &ctx_id);
+ if (ret)
+ return ret;
+
+ mask = ((1U << GEN12_GUC_SW_CTX_ID_WIDTH) - 1) <<
+ (GEN12_GUC_SW_CTX_ID_SHIFT - 32);
+ } else if (GRAPHICS_VER_FULL(stream->engine->i915) >= IP_VER(12, 50)) {
+ ctx_id = (XEHP_MAX_CONTEXT_HW_ID - 1) <<
+ (XEHP_SW_CTX_ID_SHIFT - 32);
+
+ mask = ((1U << XEHP_SW_CTX_ID_WIDTH) - 1) <<
+ (XEHP_SW_CTX_ID_SHIFT - 32);
+ } else {
+ ctx_id = (GEN12_MAX_CONTEXT_HW_ID - 1) <<
+ (GEN11_SW_CTX_ID_SHIFT - 32);
+
+ mask = ((1U << GEN11_SW_CTX_ID_WIDTH) - 1) <<
+ (GEN11_SW_CTX_ID_SHIFT - 32);
+ }
+ stream->specific_ctx_id = ctx_id & mask;
+ stream->specific_ctx_id_mask = mask;
+
+ return 0;
+}
+
+static bool oa_find_reg_in_lri(u32 *state, u32 reg, u32 *offset, u32 end)
+{
+ u32 idx = *offset;
+ u32 len = min(MI_LRI_LEN(state[idx]) + idx, end);
+ bool found = false;
+
+ idx++;
+ for (; idx < len; idx += 2) {
+ if (state[idx] == reg) {
+ found = true;
+ break;
+ }
+ }
+
+ *offset = idx;
+ return found;
+}
+
+static u32 oa_context_image_offset(struct intel_context *ce, u32 reg)
+{
+ u32 offset, len = (ce->engine->context_size - PAGE_SIZE) / 4;
+ u32 *state = ce->lrc_reg_state;
+
+ for (offset = 0; offset < len; ) {
+ if (IS_MI_LRI_CMD(state[offset])) {
+ /*
+ * We expect reg-value pairs in MI_LRI command, so
+ * MI_LRI_LEN() should be even, if not, issue a warning.
+ */
+ drm_WARN_ON(&ce->engine->i915->drm,
+ MI_LRI_LEN(state[offset]) & 0x1);
+
+ if (oa_find_reg_in_lri(state, reg, &offset, len))
+ break;
+ } else {
+ offset++;
+ }
+ }
+
+ return offset < len ? offset : U32_MAX;
+}
+
+static int set_oa_ctx_ctrl_offset(struct intel_context *ce)
+{
+ i915_reg_t reg = GEN12_OACTXCONTROL(ce->engine->mmio_base);
+ struct i915_perf *perf = &ce->engine->i915->perf;
+ u32 offset = perf->ctx_oactxctrl_offset;
+
+ /* Do this only once. Failure is stored as offset of U32_MAX */
+ if (offset)
+ goto exit;
+
+ offset = oa_context_image_offset(ce, i915_mmio_reg_offset(reg));
+ perf->ctx_oactxctrl_offset = offset;
+
+ drm_dbg(&ce->engine->i915->drm,
+ "%s oa ctx control at 0x%08x dword offset\n",
+ ce->engine->name, offset);
+
+exit:
+ return offset && offset != U32_MAX ? 0 : -ENODEV;
+}
+
+static bool engine_supports_mi_query(struct intel_engine_cs *engine)
+{
+ return engine->class == RENDER_CLASS;
+}
+
/**
* oa_get_render_ctx_id - determine and hold ctx hw id
* @stream: An i915-perf stream opened for OA metrics
@@ -1246,11 +1441,27 @@ retry:
static int oa_get_render_ctx_id(struct i915_perf_stream *stream)
{
struct intel_context *ce;
+ int ret = 0;
ce = oa_pin_context(stream);
if (IS_ERR(ce))
return PTR_ERR(ce);
+ if (engine_supports_mi_query(stream->engine)) {
+ /*
+ * We are enabling perf query here. If we don't find the context
+ * offset here, just return an error.
+ */
+ ret = set_oa_ctx_ctrl_offset(ce);
+ if (ret) {
+ intel_context_unpin(ce);
+ drm_err(&stream->perf->i915->drm,
+ "Enabling perf query failed for %s\n",
+ stream->engine->name);
+ return ret;
+ }
+ }
+
switch (GRAPHICS_VER(ce->engine->i915)) {
case 7: {
/*
@@ -1292,24 +1503,7 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream)
case 11:
case 12:
- if (GRAPHICS_VER_FULL(ce->engine->i915) >= IP_VER(12, 50)) {
- stream->specific_ctx_id_mask =
- ((1U << XEHP_SW_CTX_ID_WIDTH) - 1) <<
- (XEHP_SW_CTX_ID_SHIFT - 32);
- stream->specific_ctx_id =
- (XEHP_MAX_CONTEXT_HW_ID - 1) <<
- (XEHP_SW_CTX_ID_SHIFT - 32);
- } else {
- stream->specific_ctx_id_mask =
- ((1U << GEN11_SW_CTX_ID_WIDTH) - 1) << (GEN11_SW_CTX_ID_SHIFT - 32);
- /*
- * Pick an unused context id
- * 0 - BITS_PER_LONG are used by other contexts
- * GEN12_MAX_CONTEXT_HW_ID (0x7ff) is used by idle context
- */
- stream->specific_ctx_id =
- (GEN12_MAX_CONTEXT_HW_ID - 1) << (GEN11_SW_CTX_ID_SHIFT - 32);
- }
+ ret = gen12_get_render_context_id(stream);
break;
default:
@@ -1323,7 +1517,7 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream)
stream->specific_ctx_id,
stream->specific_ctx_id_mask);
- return 0;
+ return ret;
}
/**
@@ -1375,8 +1569,9 @@ free_noa_wait(struct i915_perf_stream *stream)
static void i915_oa_stream_destroy(struct i915_perf_stream *stream)
{
struct i915_perf *perf = stream->perf;
+ struct intel_gt *gt = stream->engine->gt;
- if (WARN_ON(stream != perf->exclusive_stream))
+ if (WARN_ON(stream != gt->perf.exclusive_stream))
return;
/*
@@ -1385,11 +1580,20 @@ static void i915_oa_stream_destroy(struct i915_perf_stream *stream)
*
* See i915_oa_init_reg_state() and lrc_configure_all_contexts()
*/
- WRITE_ONCE(perf->exclusive_stream, NULL);
+ WRITE_ONCE(gt->perf.exclusive_stream, NULL);
perf->ops.disable_metric_set(stream);
free_oa_buffer(stream);
+ /*
+ * Wa_16011777198:dg2: Unset the override of GUCRC mode to enable rc6.
+ */
+ if (intel_uc_uses_guc_rc(&gt->uc) &&
+ (IS_DG2_GRAPHICS_STEP(gt->i915, G10, STEP_A0, STEP_C0) ||
+ IS_DG2_GRAPHICS_STEP(gt->i915, G11, STEP_A0, STEP_B0)))
+ drm_WARN_ON(&gt->i915->drm,
+ intel_guc_slpc_unset_gucrc_mode(&gt->uc.guc.slpc));
+
intel_uncore_forcewake_put(stream->uncore, FORCEWAKE_ALL);
intel_engine_pm_put(stream->engine);
@@ -1400,8 +1604,9 @@ static void i915_oa_stream_destroy(struct i915_perf_stream *stream)
free_noa_wait(stream);
if (perf->spurious_report_rs.missed) {
- DRM_NOTE("%d spurious OA report notices suppressed due to ratelimiting\n",
- perf->spurious_report_rs.missed);
+ drm_notice(&gt->i915->drm,
+ "%d spurious OA report notices suppressed due to ratelimiting\n",
+ perf->spurious_report_rs.missed);
}
}
@@ -1563,6 +1768,7 @@ static void gen12_init_oa_buffer(struct i915_perf_stream *stream)
static int alloc_oa_buffer(struct i915_perf_stream *stream)
{
struct drm_i915_private *i915 = stream->perf->i915;
+ struct intel_gt *gt = stream->engine->gt;
struct drm_i915_gem_object *bo;
struct i915_vma *vma;
int ret;
@@ -1582,11 +1788,22 @@ static int alloc_oa_buffer(struct i915_perf_stream *stream)
i915_gem_object_set_cache_coherency(bo, I915_CACHE_LLC);
/* PreHSW required 512K alignment, HSW requires 16M */
- vma = i915_gem_object_ggtt_pin(bo, NULL, 0, SZ_16M, 0);
+ vma = i915_vma_instance(bo, &gt->ggtt->vm, NULL);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
goto err_unref;
}
+
+ /*
+ * PreHSW required 512K alignment.
+ * HSW and onwards, align to requested size of OA buffer.
+ */
+ ret = i915_vma_pin(vma, 0, SZ_16M, PIN_GLOBAL | PIN_HIGH);
+ if (ret) {
+ drm_err(&gt->i915->drm, "Failed to pin OA buffer %d\n", ret);
+ goto err_unref;
+ }
+
stream->oa_buffer.vma = vma;
stream->oa_buffer.vaddr =
@@ -1636,6 +1853,7 @@ static u32 *save_restore_register(struct i915_perf_stream *stream, u32 *cs,
static int alloc_noa_wait(struct i915_perf_stream *stream)
{
struct drm_i915_private *i915 = stream->perf->i915;
+ struct intel_gt *gt = stream->engine->gt;
struct drm_i915_gem_object *bo;
struct i915_vma *vma;
const u64 delay_ticks = 0xffffffffffffffff -
@@ -1654,6 +1872,9 @@ static int alloc_noa_wait(struct i915_perf_stream *stream)
DELTA_TARGET,
N_CS_GPR
};
+ i915_reg_t mi_predicate_result = HAS_MI_SET_PREDICATE(i915) ?
+ MI_PREDICATE_RESULT_2_ENGINE(base) :
+ MI_PREDICATE_RESULT_1(RENDER_RING_BASE);
bo = i915_gem_object_create_internal(i915, 4096);
if (IS_ERR(bo)) {
@@ -1673,12 +1894,16 @@ retry:
* multiple OA config BOs will have a jump to this address and it
* needs to be fixed during the lifetime of the i915/perf stream.
*/
- vma = i915_gem_object_ggtt_pin_ww(bo, &ww, NULL, 0, 0, PIN_HIGH);
+ vma = i915_vma_instance(bo, &gt->ggtt->vm, NULL);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
goto out_ww;
}
+ ret = i915_vma_pin_ww(vma, &ww, 0, 0, PIN_GLOBAL | PIN_HIGH);
+ if (ret)
+ goto out_ww;
+
batch = cs = i915_gem_object_pin_map(bo, I915_MAP_WB);
if (IS_ERR(batch)) {
ret = PTR_ERR(batch);
@@ -1691,7 +1916,7 @@ retry:
stream, cs, true /* save */, CS_GPR(i),
INTEL_GT_SCRATCH_FIELD_PERF_CS_GPR + 8 * i, 2);
cs = save_restore_register(
- stream, cs, true /* save */, MI_PREDICATE_RESULT_1(RENDER_RING_BASE),
+ stream, cs, true /* save */, mi_predicate_result,
INTEL_GT_SCRATCH_FIELD_PERF_PREDICATE_RESULT_1, 1);
/* First timestamp snapshot location. */
@@ -1745,7 +1970,10 @@ retry:
*/
*cs++ = MI_LOAD_REGISTER_REG | (3 - 2);
*cs++ = i915_mmio_reg_offset(CS_GPR(JUMP_PREDICATE));
- *cs++ = i915_mmio_reg_offset(MI_PREDICATE_RESULT_1(RENDER_RING_BASE));
+ *cs++ = i915_mmio_reg_offset(mi_predicate_result);
+
+ if (HAS_MI_SET_PREDICATE(i915))
+ *cs++ = MI_SET_PREDICATE | 1;
/* Restart from the beginning if we had timestamps roll over. */
*cs++ = (GRAPHICS_VER(i915) < 8 ?
@@ -1755,6 +1983,9 @@ retry:
*cs++ = i915_ggtt_offset(vma) + (ts0 - batch) * 4;
*cs++ = 0;
+ if (HAS_MI_SET_PREDICATE(i915))
+ *cs++ = MI_SET_PREDICATE;
+
/*
* Now add the diff between to previous timestamps and add it to :
* (((1 * << 64) - 1) - delay_ns)
@@ -1782,7 +2013,10 @@ retry:
*/
*cs++ = MI_LOAD_REGISTER_REG | (3 - 2);
*cs++ = i915_mmio_reg_offset(CS_GPR(JUMP_PREDICATE));
- *cs++ = i915_mmio_reg_offset(MI_PREDICATE_RESULT_1(RENDER_RING_BASE));
+ *cs++ = i915_mmio_reg_offset(mi_predicate_result);
+
+ if (HAS_MI_SET_PREDICATE(i915))
+ *cs++ = MI_SET_PREDICATE | 1;
/* Predicate the jump. */
*cs++ = (GRAPHICS_VER(i915) < 8 ?
@@ -1792,13 +2026,16 @@ retry:
*cs++ = i915_ggtt_offset(vma) + (jump - batch) * 4;
*cs++ = 0;
+ if (HAS_MI_SET_PREDICATE(i915))
+ *cs++ = MI_SET_PREDICATE;
+
/* Restore registers. */
for (i = 0; i < N_CS_GPR; i++)
cs = save_restore_register(
stream, cs, false /* restore */, CS_GPR(i),
INTEL_GT_SCRATCH_FIELD_PERF_CS_GPR + 8 * i, 2);
cs = save_restore_register(
- stream, cs, false /* restore */, MI_PREDICATE_RESULT_1(RENDER_RING_BASE),
+ stream, cs, false /* restore */, mi_predicate_result,
INTEL_GT_SCRATCH_FIELD_PERF_PREDICATE_RESULT_1, 1);
/* And return to the ring. */
@@ -2017,9 +2254,7 @@ retry:
goto err_add_request;
}
- err = i915_request_await_object(rq, vma->obj, 0);
- if (!err)
- err = i915_vma_move_to_active(vma, rq, 0);
+ err = i915_vma_move_to_active(vma, rq, 0);
if (err)
goto err_add_request;
@@ -2283,11 +2518,12 @@ static int gen12_configure_oar_context(struct i915_perf_stream *stream,
{
int err;
struct intel_context *ce = stream->pinned_ctx;
- u32 format = stream->oa_buffer.format;
+ u32 format = stream->oa_buffer.format->format;
+ u32 offset = stream->perf->ctx_oactxctrl_offset;
struct flex regs_context[] = {
{
GEN8_OACTXCONTROL,
- stream->perf->ctx_oactxctrl_offset + 1,
+ offset + 1,
active ? GEN8_OA_COUNTER_RESUME : 0,
},
};
@@ -2312,12 +2548,13 @@ static int gen12_configure_oar_context(struct i915_perf_stream *stream,
},
};
- /* Modify the context image of pinned context with regs_context*/
+ /* Modify the context image of pinned context with regs_context */
err = intel_context_lock_pinned(ce);
if (err)
return err;
- err = gen8_modify_context(ce, regs_context, ARRAY_SIZE(regs_context));
+ err = gen8_modify_context(ce, regs_context,
+ ARRAY_SIZE(regs_context));
intel_context_unlock_pinned(ce);
if (err)
return err;
@@ -2359,10 +2596,11 @@ oa_configure_all_contexts(struct i915_perf_stream *stream,
{
struct drm_i915_private *i915 = stream->perf->i915;
struct intel_engine_cs *engine;
+ struct intel_gt *gt = stream->engine->gt;
struct i915_gem_context *ctx, *cn;
int err;
- lockdep_assert_held(&stream->perf->lock);
+ lockdep_assert_held(&gt->perf.lock);
/*
* The OA register config is setup through the context image. This image
@@ -2442,6 +2680,7 @@ lrc_configure_all_contexts(struct i915_perf_stream *stream,
const struct i915_oa_config *oa_config,
struct i915_active *active)
{
+ u32 ctx_oactxctrl = stream->perf->ctx_oactxctrl_offset;
/* The MMIO offsets for Flex EU registers aren't contiguous */
const u32 ctx_flexeu0 = stream->perf->ctx_flexeu0_offset;
#define ctx_flexeuN(N) (ctx_flexeu0 + 2 * (N) + 1)
@@ -2452,7 +2691,7 @@ lrc_configure_all_contexts(struct i915_perf_stream *stream,
},
{
GEN8_OACTXCONTROL,
- stream->perf->ctx_oactxctrl_offset + 1,
+ ctx_oactxctrl + 1,
},
{ EU_PERF_CNTL0, ctx_flexeuN(0) },
{ EU_PERF_CNTL1, ctx_flexeuN(1) },
@@ -2540,12 +2779,26 @@ static int
gen12_enable_metric_set(struct i915_perf_stream *stream,
struct i915_active *active)
{
+ struct drm_i915_private *i915 = stream->perf->i915;
struct intel_uncore *uncore = stream->uncore;
struct i915_oa_config *oa_config = stream->oa_config;
bool periodic = stream->periodic;
u32 period_exponent = stream->period_exponent;
+ u32 sqcnt1;
int ret;
+ /*
+ * Wa_1508761755:xehpsdv, dg2
+ * EU NOA signals behave incorrectly if EU clock gating is enabled.
+ * Disable thread stall DOP gating and EU DOP gating.
+ */
+ if (IS_XEHPSDV(i915) || IS_DG2(i915)) {
+ intel_gt_mcr_multicast_write(uncore->gt, GEN8_ROW_CHICKEN,
+ _MASKED_BIT_ENABLE(STALL_DOP_GATING_DISABLE));
+ intel_uncore_write(uncore, GEN7_ROW_CHICKEN2,
+ _MASKED_BIT_ENABLE(GEN12_DISABLE_DOP_GATING));
+ }
+
intel_uncore_write(uncore, GEN12_OAG_OA_DEBUG,
/* Disable clk ratio reports, like previous Gens. */
_MASKED_BIT_ENABLE(GEN12_OAG_OA_DEBUG_DISABLE_CLK_RATIO_REPORTS |
@@ -2563,6 +2816,16 @@ gen12_enable_metric_set(struct i915_perf_stream *stream,
: 0);
/*
+ * Initialize Super Queue Internal Cnt Register
+ * Set PMON Enable in order to collect valid metrics.
+ * Enable byets per clock reporting in OA for XEHPSDV onward.
+ */
+ sqcnt1 = GEN12_SQCNT1_PMON_ENABLE |
+ (HAS_OA_BPC_REPORTING(i915) ? GEN12_SQCNT1_OABPC : 0);
+
+ intel_uncore_rmw(uncore, GEN12_SQCNT1, 0, sqcnt1);
+
+ /*
* Update all contexts prior writing the mux configurations as we need
* to make sure all slices/subslices are ON before writing to NOA
* registers.
@@ -2611,6 +2874,19 @@ static void gen11_disable_metric_set(struct i915_perf_stream *stream)
static void gen12_disable_metric_set(struct i915_perf_stream *stream)
{
struct intel_uncore *uncore = stream->uncore;
+ struct drm_i915_private *i915 = stream->perf->i915;
+ u32 sqcnt1;
+
+ /*
+ * Wa_1508761755:xehpsdv, dg2
+ * Enable thread stall DOP gating and EU DOP gating.
+ */
+ if (IS_XEHPSDV(i915) || IS_DG2(i915)) {
+ intel_gt_mcr_multicast_write(uncore->gt, GEN8_ROW_CHICKEN,
+ _MASKED_BIT_DISABLE(STALL_DOP_GATING_DISABLE));
+ intel_uncore_write(uncore, GEN7_ROW_CHICKEN2,
+ _MASKED_BIT_DISABLE(GEN12_DISABLE_DOP_GATING));
+ }
/* Reset all contexts' slices/subslices configurations. */
gen12_configure_all_contexts(stream, NULL, NULL);
@@ -2621,6 +2897,12 @@ static void gen12_disable_metric_set(struct i915_perf_stream *stream)
/* Make sure we disable noa to save power. */
intel_uncore_rmw(uncore, RPM_CONFIG1, GEN10_GT_NOA_ENABLE, 0);
+
+ sqcnt1 = GEN12_SQCNT1_PMON_ENABLE |
+ (HAS_OA_BPC_REPORTING(i915) ? GEN12_SQCNT1_OABPC : 0);
+
+ /* Reset PMON Enable to save power. */
+ intel_uncore_rmw(uncore, GEN12_SQCNT1, sqcnt1, 0);
}
static void gen7_oa_enable(struct i915_perf_stream *stream)
@@ -2630,7 +2912,7 @@ static void gen7_oa_enable(struct i915_perf_stream *stream)
u32 ctx_id = stream->specific_ctx_id;
bool periodic = stream->periodic;
u32 period_exponent = stream->period_exponent;
- u32 report_format = stream->oa_buffer.format;
+ u32 report_format = stream->oa_buffer.format->format;
/*
* Reset buf pointers so we don't forward reports from before now.
@@ -2656,7 +2938,7 @@ static void gen7_oa_enable(struct i915_perf_stream *stream)
static void gen8_oa_enable(struct i915_perf_stream *stream)
{
struct intel_uncore *uncore = stream->uncore;
- u32 report_format = stream->oa_buffer.format;
+ u32 report_format = stream->oa_buffer.format->format;
/*
* Reset buf pointers so we don't forward reports from before now.
@@ -2682,7 +2964,7 @@ static void gen8_oa_enable(struct i915_perf_stream *stream)
static void gen12_oa_enable(struct i915_perf_stream *stream)
{
struct intel_uncore *uncore = stream->uncore;
- u32 report_format = stream->oa_buffer.format;
+ u32 report_format = stream->oa_buffer.format->format;
/*
* If we don't want OA reports from the OA buffer, then we don't even
@@ -2838,6 +3120,30 @@ get_sseu_config(struct intel_sseu *out_sseu,
return i915_gem_user_to_context_sseu(engine->gt, drm_sseu, out_sseu);
}
+/*
+ * OA timestamp frequency = CS timestamp frequency in most platforms. On some
+ * platforms OA unit ignores the CTC_SHIFT and the 2 timestamps differ. In such
+ * cases, return the adjusted CS timestamp frequency to the user.
+ */
+u32 i915_perf_oa_timestamp_frequency(struct drm_i915_private *i915)
+{
+ /* Wa_18013179988:dg2 */
+ if (IS_DG2(i915)) {
+ intel_wakeref_t wakeref;
+ u32 reg, shift;
+
+ with_intel_runtime_pm(to_gt(i915)->uncore->rpm, wakeref)
+ reg = intel_uncore_read(to_gt(i915)->uncore, RPM_CONFIG0);
+
+ shift = REG_FIELD_GET(GEN10_RPM_CONFIG0_CTC_SHIFT_PARAMETER_MASK,
+ reg);
+
+ return to_gt(i915)->clock_frequency << (3 - shift);
+ }
+
+ return to_gt(i915)->clock_frequency;
+}
+
/**
* i915_oa_stream_init - validate combined props for OA stream and init
* @stream: An i915 perf stream
@@ -2862,7 +3168,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
{
struct drm_i915_private *i915 = stream->perf->i915;
struct i915_perf *perf = stream->perf;
- int format_size;
+ struct intel_gt *gt;
int ret;
if (!props->engine) {
@@ -2870,6 +3176,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
"OA engine not specified\n");
return -EINVAL;
}
+ gt = props->engine->gt;
/*
* If the sysfs metrics/ directory wasn't registered for some
@@ -2900,7 +3207,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
* counter reports and marshal to the appropriate client
* we currently only allow exclusive access
*/
- if (perf->exclusive_stream) {
+ if (gt->perf.exclusive_stream) {
drm_dbg(&stream->perf->i915->drm,
"OA unit already in use\n");
return -EBUSY;
@@ -2917,20 +3224,15 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
stream->sample_size = sizeof(struct drm_i915_perf_record_header);
- format_size = perf->oa_formats[props->oa_format].size;
+ stream->oa_buffer.format = &perf->oa_formats[props->oa_format];
+ if (drm_WARN_ON(&i915->drm, stream->oa_buffer.format->size == 0))
+ return -EINVAL;
stream->sample_flags = props->sample_flags;
- stream->sample_size += format_size;
-
- stream->oa_buffer.format_size = format_size;
- if (drm_WARN_ON(&i915->drm, stream->oa_buffer.format_size == 0))
- return -EINVAL;
+ stream->sample_size += stream->oa_buffer.format->size;
stream->hold_preemption = props->hold_preemption;
- stream->oa_buffer.format =
- perf->oa_formats[props->oa_format].format;
-
stream->periodic = props->oa_periodic;
if (stream->periodic)
stream->period_exponent = props->oa_period_exponent;
@@ -2974,14 +3276,31 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
intel_engine_pm_get(stream->engine);
intel_uncore_forcewake_get(stream->uncore, FORCEWAKE_ALL);
+ /*
+ * Wa_16011777198:dg2: GuC resets render as part of the Wa. This causes
+ * OA to lose the configuration state. Prevent this by overriding GUCRC
+ * mode.
+ */
+ if (intel_uc_uses_guc_rc(&gt->uc) &&
+ (IS_DG2_GRAPHICS_STEP(gt->i915, G10, STEP_A0, STEP_C0) ||
+ IS_DG2_GRAPHICS_STEP(gt->i915, G11, STEP_A0, STEP_B0))) {
+ ret = intel_guc_slpc_override_gucrc_mode(&gt->uc.guc.slpc,
+ SLPC_GUCRC_MODE_GUCRC_NO_RC6);
+ if (ret) {
+ drm_dbg(&stream->perf->i915->drm,
+ "Unable to override gucrc mode\n");
+ goto err_config;
+ }
+ }
+
ret = alloc_oa_buffer(stream);
if (ret)
goto err_oa_buf_alloc;
stream->ops = &i915_oa_stream_ops;
- perf->sseu = props->sseu;
- WRITE_ONCE(perf->exclusive_stream, stream);
+ stream->engine->gt->perf.sseu = props->sseu;
+ WRITE_ONCE(gt->perf.exclusive_stream, stream);
ret = i915_perf_stream_enable_sync(stream);
if (ret) {
@@ -2999,11 +3318,12 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
stream->poll_check_timer.function = oa_poll_check_timer_cb;
init_waitqueue_head(&stream->poll_wq);
spin_lock_init(&stream->oa_buffer.ptr_lock);
+ mutex_init(&stream->lock);
return 0;
err_enable:
- WRITE_ONCE(perf->exclusive_stream, NULL);
+ WRITE_ONCE(gt->perf.exclusive_stream, NULL);
perf->ops.disable_metric_set(stream);
free_oa_buffer(stream);
@@ -3033,7 +3353,7 @@ void i915_oa_init_reg_state(const struct intel_context *ce,
return;
/* perf.exclusive_stream serialised by lrc_configure_all_contexts() */
- stream = READ_ONCE(engine->i915->perf.exclusive_stream);
+ stream = READ_ONCE(engine->gt->perf.exclusive_stream);
if (stream && GRAPHICS_VER(stream->perf->i915) < 12)
gen8_update_reg_state_unlocked(ce, stream);
}
@@ -3062,7 +3382,6 @@ static ssize_t i915_perf_read(struct file *file,
loff_t *ppos)
{
struct i915_perf_stream *stream = file->private_data;
- struct i915_perf *perf = stream->perf;
size_t offset = 0;
int ret;
@@ -3086,14 +3405,14 @@ static ssize_t i915_perf_read(struct file *file,
if (ret)
return ret;
- mutex_lock(&perf->lock);
+ mutex_lock(&stream->lock);
ret = stream->ops->read(stream, buf, count, &offset);
- mutex_unlock(&perf->lock);
+ mutex_unlock(&stream->lock);
} while (!offset && !ret);
} else {
- mutex_lock(&perf->lock);
+ mutex_lock(&stream->lock);
ret = stream->ops->read(stream, buf, count, &offset);
- mutex_unlock(&perf->lock);
+ mutex_unlock(&stream->lock);
}
/* We allow the poll checking to sometimes report false positive EPOLLIN
@@ -3140,9 +3459,6 @@ static enum hrtimer_restart oa_poll_check_timer_cb(struct hrtimer *hrtimer)
* &i915_perf_stream_ops->poll_wait to call poll_wait() with a wait queue that
* will be woken for new stream data.
*
- * Note: The &perf->lock mutex has been taken to serialize
- * with any non-file-operation driver hooks.
- *
* Returns: any poll events that are ready without sleeping
*/
static __poll_t i915_perf_poll_locked(struct i915_perf_stream *stream,
@@ -3181,12 +3497,11 @@ static __poll_t i915_perf_poll_locked(struct i915_perf_stream *stream,
static __poll_t i915_perf_poll(struct file *file, poll_table *wait)
{
struct i915_perf_stream *stream = file->private_data;
- struct i915_perf *perf = stream->perf;
__poll_t ret;
- mutex_lock(&perf->lock);
+ mutex_lock(&stream->lock);
ret = i915_perf_poll_locked(stream, file, wait);
- mutex_unlock(&perf->lock);
+ mutex_unlock(&stream->lock);
return ret;
}
@@ -3285,9 +3600,6 @@ static long i915_perf_config_locked(struct i915_perf_stream *stream,
* @cmd: the ioctl request
* @arg: the ioctl data
*
- * Note: The &perf->lock mutex has been taken to serialize
- * with any non-file-operation driver hooks.
- *
* Returns: zero on success or a negative error code. Returns -EINVAL for
* an unknown ioctl request.
*/
@@ -3325,12 +3637,11 @@ static long i915_perf_ioctl(struct file *file,
unsigned long arg)
{
struct i915_perf_stream *stream = file->private_data;
- struct i915_perf *perf = stream->perf;
long ret;
- mutex_lock(&perf->lock);
+ mutex_lock(&stream->lock);
ret = i915_perf_ioctl_locked(stream, cmd, arg);
- mutex_unlock(&perf->lock);
+ mutex_unlock(&stream->lock);
return ret;
}
@@ -3342,7 +3653,7 @@ static long i915_perf_ioctl(struct file *file,
* Frees all resources associated with the given i915 perf @stream, disabling
* any associated data capture in the process.
*
- * Note: The &perf->lock mutex has been taken to serialize
+ * Note: The &gt->perf.lock mutex has been taken to serialize
* with any non-file-operation driver hooks.
*/
static void i915_perf_destroy_locked(struct i915_perf_stream *stream)
@@ -3374,10 +3685,16 @@ static int i915_perf_release(struct inode *inode, struct file *file)
{
struct i915_perf_stream *stream = file->private_data;
struct i915_perf *perf = stream->perf;
+ struct intel_gt *gt = stream->engine->gt;
- mutex_lock(&perf->lock);
+ /*
+ * Within this call, we know that the fd is being closed and we have no
+ * other user of stream->lock. Use the perf lock to destroy the stream
+ * here.
+ */
+ mutex_lock(&gt->perf.lock);
i915_perf_destroy_locked(stream);
- mutex_unlock(&perf->lock);
+ mutex_unlock(&gt->perf.lock);
/* Release the reference the perf stream kept on the driver. */
drm_dev_put(&perf->i915->drm);
@@ -3410,7 +3727,7 @@ static const struct file_operations fops = {
* See i915_perf_ioctl_open() for interface details.
*
* Implements further stream config validation and stream initialization on
- * behalf of i915_perf_open_ioctl() with the &perf->lock mutex
+ * behalf of i915_perf_open_ioctl() with the &gt->perf.lock mutex
* taken to serialize with any non-file-operation driver hooks.
*
* Note: at this point the @props have only been validated in isolation and
@@ -3565,8 +3882,10 @@ err:
static u64 oa_exponent_to_ns(struct i915_perf *perf, int exponent)
{
- return intel_gt_clock_interval_to_ns(to_gt(perf->i915),
- 2ULL << exponent);
+ u64 nom = (2ULL << exponent) * NSEC_PER_SEC;
+ u32 den = i915_perf_oa_timestamp_frequency(perf->i915);
+
+ return div_u64(nom + den - 1, den);
}
static __always_inline bool
@@ -3794,7 +4113,7 @@ static int read_properties_unlocked(struct i915_perf *perf,
* mutex to avoid an awkward lockdep with mmap_lock.
*
* Most of the implementation details are handled by
- * i915_perf_open_ioctl_locked() after taking the &perf->lock
+ * i915_perf_open_ioctl_locked() after taking the &gt->perf.lock
* mutex for serializing with any non-file-operation driver hooks.
*
* Return: A newly opened i915 Perf stream file descriptor or negative
@@ -3805,6 +4124,7 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data,
{
struct i915_perf *perf = &to_i915(dev)->perf;
struct drm_i915_perf_open_param *param = data;
+ struct intel_gt *gt;
struct perf_open_properties props;
u32 known_open_flags;
int ret;
@@ -3831,9 +4151,11 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data,
if (ret)
return ret;
- mutex_lock(&perf->lock);
+ gt = props.engine->gt;
+
+ mutex_lock(&gt->perf.lock);
ret = i915_perf_open_ioctl_locked(perf, param, &props, file);
- mutex_unlock(&perf->lock);
+ mutex_unlock(&gt->perf.lock);
return ret;
}
@@ -3849,6 +4171,7 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data,
void i915_perf_register(struct drm_i915_private *i915)
{
struct i915_perf *perf = &i915->perf;
+ struct intel_gt *gt = to_gt(i915);
if (!perf->i915)
return;
@@ -3857,13 +4180,13 @@ void i915_perf_register(struct drm_i915_private *i915)
* i915_perf_open_ioctl(); considering that we register after
* being exposed to userspace.
*/
- mutex_lock(&perf->lock);
+ mutex_lock(&gt->perf.lock);
perf->metrics_kobj =
kobject_create_and_add("metrics",
&i915->drm.primary->kdev->kobj);
- mutex_unlock(&perf->lock);
+ mutex_unlock(&gt->perf.lock);
}
/**
@@ -3939,6 +4262,11 @@ static const struct i915_range gen12_oa_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[] = {
{ .start = 0x91b8, .end = 0x91cc }, /* OA_PERFCNT[1-2], OA_PERFMATRIX */
{ .start = 0x9800, .end = 0x9888 }, /* MICRO_BP0_0 - NOA_WRITE */
@@ -4013,6 +4341,12 @@ static bool gen12_is_valid_b_counter_addr(struct i915_perf *perf, u32 addr)
return reg_in_range_table(addr, gen12_oa_b_counters);
}
+static bool xehp_is_valid_b_counter_addr(struct i915_perf *perf, u32 addr)
+{
+ return reg_in_range_table(addr, xehp_oa_b_counters) ||
+ reg_in_range_table(addr, gen12_oa_b_counters);
+}
+
static bool gen12_is_valid_mux_addr(struct i915_perf *perf, u32 addr)
{
return reg_in_range_table(addr, gen12_oa_mux_regs);
@@ -4411,11 +4745,47 @@ static void oa_init_supported_formats(struct i915_perf *perf)
oa_format_add(perf, I915_OA_FORMAT_C4_B8);
break;
+ case INTEL_DG2:
+ oa_format_add(perf, I915_OAR_FORMAT_A32u40_A4u32_B8_C8);
+ oa_format_add(perf, I915_OA_FORMAT_A24u40_A14u32_B8_C8);
+ break;
+
default:
MISSING_CASE(platform);
}
}
+static void i915_perf_init_info(struct drm_i915_private *i915)
+{
+ struct i915_perf *perf = &i915->perf;
+
+ switch (GRAPHICS_VER(i915)) {
+ case 8:
+ perf->ctx_oactxctrl_offset = 0x120;
+ perf->ctx_flexeu0_offset = 0x2ce;
+ perf->gen8_valid_ctx_bit = BIT(25);
+ break;
+ case 9:
+ perf->ctx_oactxctrl_offset = 0x128;
+ perf->ctx_flexeu0_offset = 0x3de;
+ perf->gen8_valid_ctx_bit = BIT(16);
+ break;
+ case 11:
+ perf->ctx_oactxctrl_offset = 0x124;
+ perf->ctx_flexeu0_offset = 0x78e;
+ perf->gen8_valid_ctx_bit = BIT(16);
+ break;
+ case 12:
+ /*
+ * Calculate offset at runtime in oa_pin_context for gen12 and
+ * cache the value in perf->ctx_oactxctrl_offset.
+ */
+ break;
+ default:
+ MISSING_CASE(GRAPHICS_VER(i915));
+ }
+}
+
/**
* i915_perf_init - initialize i915-perf state on module bind
* @i915: i915 device instance
@@ -4429,12 +4799,6 @@ void i915_perf_init(struct drm_i915_private *i915)
{
struct i915_perf *perf = &i915->perf;
- /* XXX const struct i915_perf_ops! */
-
- /* i915_perf is not enabled for DG2 yet */
- if (IS_DG2(i915))
- return;
-
perf->oa_formats = oa_formats;
if (IS_HASWELL(i915)) {
perf->ops.is_valid_b_counter_reg = gen7_is_valid_b_counter_addr;
@@ -4454,6 +4818,7 @@ void i915_perf_init(struct drm_i915_private *i915)
* execlist mode by default.
*/
perf->ops.read = gen8_oa_read;
+ i915_perf_init_info(i915);
if (IS_GRAPHICS_VER(i915, 8, 9)) {
perf->ops.is_valid_b_counter_reg =
@@ -4473,18 +4838,6 @@ void i915_perf_init(struct drm_i915_private *i915)
perf->ops.enable_metric_set = gen8_enable_metric_set;
perf->ops.disable_metric_set = gen8_disable_metric_set;
perf->ops.oa_hw_tail_read = gen8_oa_hw_tail_read;
-
- if (GRAPHICS_VER(i915) == 8) {
- perf->ctx_oactxctrl_offset = 0x120;
- perf->ctx_flexeu0_offset = 0x2ce;
-
- perf->gen8_valid_ctx_bit = BIT(25);
- } else {
- perf->ctx_oactxctrl_offset = 0x128;
- perf->ctx_flexeu0_offset = 0x3de;
-
- perf->gen8_valid_ctx_bit = BIT(16);
- }
} else if (GRAPHICS_VER(i915) == 11) {
perf->ops.is_valid_b_counter_reg =
gen7_is_valid_b_counter_addr;
@@ -4498,13 +4851,10 @@ void i915_perf_init(struct drm_i915_private *i915)
perf->ops.enable_metric_set = gen8_enable_metric_set;
perf->ops.disable_metric_set = gen11_disable_metric_set;
perf->ops.oa_hw_tail_read = gen8_oa_hw_tail_read;
-
- perf->ctx_oactxctrl_offset = 0x124;
- perf->ctx_flexeu0_offset = 0x78e;
-
- perf->gen8_valid_ctx_bit = BIT(16);
} else if (GRAPHICS_VER(i915) == 12) {
perf->ops.is_valid_b_counter_reg =
+ HAS_OA_SLICE_CONTRIB_LIMITS(i915) ?
+ xehp_is_valid_b_counter_addr :
gen12_is_valid_b_counter_addr;
perf->ops.is_valid_mux_reg =
gen12_is_valid_mux_addr;
@@ -4516,14 +4866,15 @@ void i915_perf_init(struct drm_i915_private *i915)
perf->ops.enable_metric_set = gen12_enable_metric_set;
perf->ops.disable_metric_set = gen12_disable_metric_set;
perf->ops.oa_hw_tail_read = gen12_oa_hw_tail_read;
-
- perf->ctx_flexeu0_offset = 0;
- perf->ctx_oactxctrl_offset = 0x144;
}
}
if (perf->ops.enable_metric_set) {
- mutex_init(&perf->lock);
+ struct intel_gt *gt;
+ int i;
+
+ for_each_gt(gt, i915, i)
+ mutex_init(&gt->perf.lock);
/* Choose a representative limit */
oa_sample_rate_hard_limit = to_gt(i915)->clock_frequency / 2;
diff --git a/drivers/gpu/drm/i915/i915_perf.h b/drivers/gpu/drm/i915/i915_perf.h
index 1d1329e5af3a..f96e09a4af04 100644
--- a/drivers/gpu/drm/i915/i915_perf.h
+++ b/drivers/gpu/drm/i915/i915_perf.h
@@ -57,4 +57,6 @@ static inline void i915_oa_config_put(struct i915_oa_config *oa_config)
kref_put(&oa_config->ref, i915_oa_config_release);
}
+u32 i915_perf_oa_timestamp_frequency(struct drm_i915_private *i915);
+
#endif /* __I915_PERF_H__ */
diff --git a/drivers/gpu/drm/i915/i915_perf_oa_regs.h b/drivers/gpu/drm/i915/i915_perf_oa_regs.h
index f31c9f13a9fc..381d94101610 100644
--- a/drivers/gpu/drm/i915/i915_perf_oa_regs.h
+++ b/drivers/gpu/drm/i915/i915_perf_oa_regs.h
@@ -97,7 +97,7 @@
#define GEN12_OAR_OACONTROL_COUNTER_FORMAT_SHIFT 1
#define GEN12_OAR_OACONTROL_COUNTER_ENABLE (1 << 0)
-#define GEN12_OACTXCONTROL _MMIO(0x2360)
+#define GEN12_OACTXCONTROL(base) _MMIO((base) + 0x360)
#define GEN12_OAR_OASTATUS _MMIO(0x2968)
/* Gen12 OAG unit */
@@ -134,4 +134,8 @@
#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)
+
#endif /* __INTEL_PERF_OA_REGS__ */
diff --git a/drivers/gpu/drm/i915/i915_perf_types.h b/drivers/gpu/drm/i915/i915_perf_types.h
index 05cb9a335a97..ca150b7af3f2 100644
--- a/drivers/gpu/drm/i915/i915_perf_types.h
+++ b/drivers/gpu/drm/i915/i915_perf_types.h
@@ -147,6 +147,11 @@ struct i915_perf_stream {
struct intel_engine_cs *engine;
/**
+ * @lock: Lock associated with operations on stream
+ */
+ struct mutex lock;
+
+ /**
* @sample_flags: Flags representing the `DRM_I915_PERF_PROP_SAMPLE_*`
* properties given when opening a stream, representing the contents
* of a single sample as read() by userspace.
@@ -245,11 +250,10 @@ struct i915_perf_stream {
* @oa_buffer: State of the OA buffer.
*/
struct {
+ const struct i915_oa_format *format;
struct i915_vma *vma;
u8 *vaddr;
u32 last_ctx_id;
- int format;
- int format_size;
int size_exponent;
/**
@@ -380,6 +384,26 @@ struct i915_oa_ops {
u32 (*oa_hw_tail_read)(struct i915_perf_stream *stream);
};
+struct i915_perf_gt {
+ /*
+ * Lock associated with anything below within this structure.
+ */
+ struct mutex lock;
+
+ /**
+ * @sseu: sseu configuration selected to run while perf is active,
+ * applies to all contexts.
+ */
+ struct intel_sseu sseu;
+
+ /*
+ * @exclusive_stream: The stream currently using the OA unit. This is
+ * sometimes accessed outside a syscall associated to its file
+ * descriptor.
+ */
+ struct i915_perf_stream *exclusive_stream;
+};
+
struct i915_perf {
struct drm_i915_private *i915;
@@ -397,25 +421,6 @@ struct i915_perf {
*/
struct idr metrics_idr;
- /*
- * Lock associated with anything below within this structure
- * except exclusive_stream.
- */
- struct mutex lock;
-
- /*
- * The stream currently using the OA unit. If accessed
- * outside a syscall associated to its file
- * descriptor.
- */
- struct i915_perf_stream *exclusive_stream;
-
- /**
- * @sseu: sseu configuration selected to run while perf is active,
- * applies to all contexts.
- */
- struct intel_sseu sseu;
-
/**
* For rate limiting any notifications of spurious
* invalid OA reports
diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c
index 958b37123bf1..52531ab28c5f 100644
--- a/drivers/gpu/drm/i915/i915_pmu.c
+++ b/drivers/gpu/drm/i915/i915_pmu.c
@@ -148,13 +148,13 @@ static u64 __get_rc6(struct intel_gt *gt)
struct drm_i915_private *i915 = gt->i915;
u64 val;
- val = intel_rc6_residency_ns(&gt->rc6, GEN6_GT_GFX_RC6);
+ val = intel_rc6_residency_ns(&gt->rc6, INTEL_RC6_RES_RC6);
if (HAS_RC6p(i915))
- val += intel_rc6_residency_ns(&gt->rc6, GEN6_GT_GFX_RC6p);
+ val += intel_rc6_residency_ns(&gt->rc6, INTEL_RC6_RES_RC6p);
if (HAS_RC6pp(i915))
- val += intel_rc6_residency_ns(&gt->rc6, GEN6_GT_GFX_RC6pp);
+ val += intel_rc6_residency_ns(&gt->rc6, INTEL_RC6_RES_RC6pp);
return val;
}
@@ -371,7 +371,6 @@ static void
frequency_sample(struct intel_gt *gt, unsigned int period_ns)
{
struct drm_i915_private *i915 = gt->i915;
- struct intel_uncore *uncore = gt->uncore;
struct i915_pmu *pmu = &i915->pmu;
struct intel_rps *rps = &gt->rps;
@@ -394,7 +393,7 @@ frequency_sample(struct intel_gt *gt, unsigned int period_ns)
* case we assume the system is running at the intended
* frequency. Fortunately, the read should rarely fail!
*/
- val = intel_uncore_read_fw(uncore, GEN6_RPSTAT1);
+ val = intel_rps_read_rpstat_fw(rps);
if (val)
val = intel_rps_get_cagf(rps, val);
else
diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c
index 6ec9c9fb7b0d..00871ef99792 100644
--- a/drivers/gpu/drm/i915/i915_query.c
+++ b/drivers/gpu/drm/i915/i915_query.c
@@ -250,8 +250,9 @@ static int query_perf_config_data(struct drm_i915_private *i915,
return total_size;
if (query_item->length < total_size) {
- DRM_DEBUG("Invalid query config data item size=%u expected=%u\n",
- query_item->length, total_size);
+ drm_dbg(&i915->drm,
+ "Invalid query config data item size=%u expected=%u\n",
+ query_item->length, total_size);
return -EINVAL;
}
@@ -418,9 +419,10 @@ static int query_perf_config_list(struct drm_i915_private *i915,
} while (n_configs > alloc);
if (query_item->length < sizeof_perf_config_list(n_configs)) {
- DRM_DEBUG("Invalid query config list item size=%u expected=%zu\n",
- query_item->length,
- sizeof_perf_config_list(n_configs));
+ drm_dbg(&i915->drm,
+ "Invalid query config list item size=%u expected=%zu\n",
+ query_item->length,
+ sizeof_perf_config_list(n_configs));
kfree(oa_config_ids);
return -EINVAL;
}
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index da35bb2db26b..8e1892d14774 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -26,6 +26,7 @@
#define _I915_REG_H_
#include "i915_reg_defs.h"
+#include "display/intel_display_reg_defs.h"
/**
* DOC: The i915 register macro definition style guide
@@ -115,75 +116,6 @@
* #define GEN8_BAR _MMIO(0xb888)
*/
-#define DISPLAY_MMIO_BASE(dev_priv) (INTEL_INFO(dev_priv)->display.mmio_offset)
-
-/*
- * Given the first two numbers __a and __b of arbitrarily many evenly spaced
- * numbers, pick the 0-based __index'th value.
- *
- * Always prefer this over _PICK() if the numbers are evenly spaced.
- */
-#define _PICK_EVEN(__index, __a, __b) ((__a) + (__index) * ((__b) - (__a)))
-
-/*
- * Given the arbitrary numbers in varargs, pick the 0-based __index'th number.
- *
- * Always prefer _PICK_EVEN() over this if the numbers are evenly spaced.
- */
-#define _PICK(__index, ...) (((const u32 []){ __VA_ARGS__ })[__index])
-
-/*
- * Named helper wrappers around _PICK_EVEN() and _PICK().
- */
-#define _PIPE(pipe, a, b) _PICK_EVEN(pipe, a, b)
-#define _PLANE(plane, a, b) _PICK_EVEN(plane, a, b)
-#define _TRANS(tran, a, b) _PICK_EVEN(tran, a, b)
-#define _PORT(port, a, b) _PICK_EVEN(port, a, b)
-#define _PLL(pll, a, b) _PICK_EVEN(pll, a, b)
-#define _PHY(phy, a, b) _PICK_EVEN(phy, a, b)
-
-#define _MMIO_PIPE(pipe, a, b) _MMIO(_PIPE(pipe, a, b))
-#define _MMIO_PLANE(plane, a, b) _MMIO(_PLANE(plane, a, b))
-#define _MMIO_TRANS(tran, a, b) _MMIO(_TRANS(tran, a, b))
-#define _MMIO_PORT(port, a, b) _MMIO(_PORT(port, a, b))
-#define _MMIO_PLL(pll, a, b) _MMIO(_PLL(pll, a, b))
-#define _MMIO_PHY(phy, a, b) _MMIO(_PHY(phy, a, b))
-
-#define _PHY3(phy, ...) _PICK(phy, __VA_ARGS__)
-
-#define _MMIO_PIPE3(pipe, a, b, c) _MMIO(_PICK(pipe, a, b, c))
-#define _MMIO_PORT3(pipe, a, b, c) _MMIO(_PICK(pipe, a, b, c))
-#define _MMIO_PHY3(phy, a, b, c) _MMIO(_PHY3(phy, a, b, c))
-#define _MMIO_PLL3(pll, ...) _MMIO(_PICK(pll, __VA_ARGS__))
-
-
-/*
- * 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] + \
- 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] + \
- 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] + \
- DISPLAY_MMIO_BASE(dev_priv) + (reg))
-
-#define __MASKED_FIELD(mask, value) ((mask) << 16 | (value))
-#define _MASKED_FIELD(mask, value) ({ \
- if (__builtin_constant_p(mask)) \
- BUILD_BUG_ON_MSG(((mask) & 0xffff0000), "Incorrect mask"); \
- if (__builtin_constant_p(value)) \
- BUILD_BUG_ON_MSG((value) & 0xffff0000, "Incorrect value"); \
- if (__builtin_constant_p(mask) && __builtin_constant_p(value)) \
- BUILD_BUG_ON_MSG((value) & ~(mask), \
- "Incorrect value for mask"); \
- __MASKED_FIELD(mask, value); })
-#define _MASKED_BIT_ENABLE(a) ({ typeof(a) _a = (a); _MASKED_FIELD(_a, _a); })
-#define _MASKED_BIT_DISABLE(a) (_MASKED_FIELD((a), 0))
-
#define GU_CNTL _MMIO(0x101010)
#define LMEM_INIT REG_BIT(7)
@@ -970,6 +902,7 @@
#define GEN11_VEBOX2_RING_BASE 0x1d8000
#define XEHP_VEBOX3_RING_BASE 0x1e8000
#define XEHP_VEBOX4_RING_BASE 0x1f8000
+#define MTL_GSC_RING_BASE 0x11a000
#define GEN12_COMPUTE0_RING_BASE 0x1a000
#define GEN12_COMPUTE1_RING_BASE 0x1c000
#define GEN12_COMPUTE2_RING_BASE 0x1e000
@@ -1147,11 +1080,6 @@
#define MBUS_JOIN_PIPE_SELECT(pipe) REG_FIELD_PREP(MBUS_JOIN_PIPE_SELECT_MASK, pipe)
#define MBUS_JOIN_PIPE_SELECT_NONE MBUS_JOIN_PIPE_SELECT(7)
-#define HDPORT_STATE _MMIO(0x45050)
-#define HDPORT_DPLL_USED_MASK REG_GENMASK(15, 12)
-#define HDPORT_DDI_USED(phy) REG_BIT(2 * (phy) + 1)
-#define HDPORT_ENABLED REG_BIT(0)
-
/* Make render/texture TLB fetches lower priorty than associated data
* fetches. This is not turned on by default
*/
@@ -1781,9 +1709,10 @@
#define _PALETTE_A 0xa000
#define _PALETTE_B 0xa800
#define _CHV_PALETTE_C 0xc000
-#define PALETTE_RED_MASK REG_GENMASK(23, 16)
-#define PALETTE_GREEN_MASK REG_GENMASK(15, 8)
-#define PALETTE_BLUE_MASK REG_GENMASK(7, 0)
+/* 8bit mode / i965+ 10.6 interpolated mode ldw/udw */
+#define PALETTE_RED_MASK REG_GENMASK(23, 16)
+#define PALETTE_GREEN_MASK REG_GENMASK(15, 8)
+#define PALETTE_BLUE_MASK REG_GENMASK(7, 0)
#define PALETTE(pipe, i) _MMIO(DISPLAY_MMIO_BASE(dev_priv) + \
_PICK((pipe), _PALETTE_A, \
_PALETTE_B, _CHV_PALETTE_C) + \
@@ -1796,6 +1725,15 @@
#define XEHPSDV_RP_STATE_CAP _MMIO(0x250014)
#define PVC_RP_STATE_CAP _MMIO(0x281014)
+#define MTL_RP_STATE_CAP _MMIO(0x138000)
+#define MTL_MEDIAP_STATE_CAP _MMIO(0x138020)
+#define MTL_RP0_CAP_MASK REG_GENMASK(8, 0)
+#define MTL_RPN_CAP_MASK REG_GENMASK(24, 16)
+
+#define MTL_GT_RPE_FREQUENCY _MMIO(0x13800c)
+#define MTL_MPE_FREQUENCY _MMIO(0x13802c)
+#define MTL_RPE_MASK REG_GENMASK(8, 0)
+
#define GT0_PERF_LIMIT_REASONS _MMIO(0x1381a8)
#define GT0_PERF_LIMIT_REASONS_MASK 0xde3
#define PROCHOT_MASK REG_BIT(0)
@@ -1806,6 +1744,8 @@
#define POWER_LIMIT_4_MASK REG_BIT(8)
#define POWER_LIMIT_1_MASK REG_BIT(10)
#define POWER_LIMIT_2_MASK REG_BIT(11)
+#define GT0_PERF_LIMIT_REASONS_LOG_MASK REG_GENMASK(31, 16)
+#define MTL_MEDIA_PERF_LIMIT_REASONS _MMIO(0x138030)
#define CHV_CLK_CTL1 _MMIO(0x101100)
#define VLV_CLK_CTL2 _MMIO(0x101104)
@@ -3747,9 +3687,10 @@
/* Skylake+ pipe bottom (background) color */
#define _SKL_BOTTOM_COLOR_A 0x70034
+#define _SKL_BOTTOM_COLOR_B 0x71034
#define SKL_BOTTOM_COLOR_GAMMA_ENABLE REG_BIT(31)
#define SKL_BOTTOM_COLOR_CSC_ENABLE REG_BIT(30)
-#define SKL_BOTTOM_COLOR(pipe) _MMIO_PIPE2(pipe, _SKL_BOTTOM_COLOR_A)
+#define SKL_BOTTOM_COLOR(pipe) _MMIO_PIPE(pipe, _SKL_BOTTOM_COLOR_A, _SKL_BOTTOM_COLOR_B)
#define _ICL_PIPE_A_STATUS 0x70058
#define ICL_PIPESTATUS(pipe) _MMIO_PIPE2(pipe, _ICL_PIPE_A_STATUS)
@@ -5367,17 +5308,24 @@
/* legacy palette */
#define _LGC_PALETTE_A 0x4a000
#define _LGC_PALETTE_B 0x4a800
-#define LGC_PALETTE_RED_MASK REG_GENMASK(23, 16)
-#define LGC_PALETTE_GREEN_MASK REG_GENMASK(15, 8)
-#define LGC_PALETTE_BLUE_MASK REG_GENMASK(7, 0)
+/* see PALETTE_* for the bits */
#define LGC_PALETTE(pipe, i) _MMIO(_PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B) + (i) * 4)
/* ilk/snb precision palette */
#define _PREC_PALETTE_A 0x4b000
#define _PREC_PALETTE_B 0x4c000
-#define PREC_PALETTE_RED_MASK REG_GENMASK(29, 20)
-#define PREC_PALETTE_GREEN_MASK REG_GENMASK(19, 10)
-#define PREC_PALETTE_BLUE_MASK REG_GENMASK(9, 0)
+/* 10bit mode */
+#define PREC_PALETTE_10_RED_MASK REG_GENMASK(29, 20)
+#define PREC_PALETTE_10_GREEN_MASK REG_GENMASK(19, 10)
+#define PREC_PALETTE_10_BLUE_MASK REG_GENMASK(9, 0)
+/* 12.4 interpolated mode ldw */
+#define PREC_PALETTE_12P4_RED_LDW_MASK REG_GENMASK(29, 24)
+#define PREC_PALETTE_12P4_GREEN_LDW_MASK REG_GENMASK(19, 14)
+#define PREC_PALETTE_12P4_BLUE_LDW_MASK REG_GENMASK(9, 4)
+/* 12.4 interpolated mode udw */
+#define PREC_PALETTE_12P4_RED_UDW_MASK REG_GENMASK(29, 20)
+#define PREC_PALETTE_12P4_GREEN_UDW_MASK REG_GENMASK(19, 10)
+#define PREC_PALETTE_12P4_BLUE_UDW_MASK REG_GENMASK(9, 0)
#define PREC_PALETTE(pipe, i) _MMIO(_PIPE(pipe, _PREC_PALETTE_A, _PREC_PALETTE_B) + (i) * 4)
#define _PREC_PIPEAGCMAX 0x4d000
@@ -5847,6 +5795,11 @@
#define ICL_DSSM_CDCLK_PLL_REFCLK_19_2MHz (1 << 29)
#define ICL_DSSM_CDCLK_PLL_REFCLK_38_4MHz (2 << 29)
+#define GMD_ID_DISPLAY _MMIO(0x510a0)
+#define GMD_ID_ARCH_MASK REG_GENMASK(31, 22)
+#define GMD_ID_RELEASE_MASK REG_GENMASK(21, 14)
+#define GMD_ID_STEP REG_GENMASK(5, 0)
+
/*GEN11 chicken */
#define _PIPEA_CHICKEN 0x70038
#define _PIPEB_CHICKEN 0x71038
@@ -6647,6 +6600,12 @@
#define DG1_PCODE_STATUS 0x7E
#define DG1_UNCORE_GET_INIT_STATUS 0x0
#define DG1_UNCORE_INIT_STATUS_COMPLETE 0x1
+#define PCODE_POWER_SETUP 0x7C
+#define POWER_SETUP_SUBCOMMAND_READ_I1 0x4
+#define POWER_SETUP_SUBCOMMAND_WRITE_I1 0x5
+#define POWER_SETUP_I1_WATTS REG_BIT(31)
+#define POWER_SETUP_I1_SHIFT 6 /* 10.6 fixed point format */
+#define POWER_SETUP_I1_DATA_MASK REG_GENMASK(15, 0)
#define GEN12_PCODE_READ_SAGV_BLOCK_TIME_US 0x23
#define XEHP_PCODE_FREQUENCY_CONFIG 0x6e /* xehpsdv, pvc */
/* XEHP_PCODE_FREQUENCY_CONFIG sub-commands (param1) */
@@ -6656,6 +6615,15 @@
/* XEHP_PCODE_FREQUENCY_CONFIG param2 */
#define PCODE_MBOX_DOMAIN_NONE 0x0
#define PCODE_MBOX_DOMAIN_MEDIAFF 0x3
+
+/* Wa_14017210380: mtl */
+#define PCODE_MBOX_GT_STATE 0x50
+/* sub-commands (param1) */
+#define PCODE_MBOX_GT_STATE_MEDIA_BUSY 0x1
+#define PCODE_MBOX_GT_STATE_MEDIA_NOT_BUSY 0x2
+/* param2 */
+#define PCODE_MBOX_GT_STATE_DOMAIN_MEDIA 0x1
+
#define GEN6_PCODE_DATA _MMIO(0x138128)
#define GEN6_PCODE_FREQ_IA_RATIO_SHIFT 8
#define GEN6_PCODE_FREQ_RING_RATIO_SHIFT 16
@@ -7413,185 +7381,6 @@ enum skl_power_gate {
_ADLS_DPLL4_CFGCR1, \
_ADLS_DPLL3_CFGCR1)
-#define _DKL_PHY1_BASE 0x168000
-#define _DKL_PHY2_BASE 0x169000
-#define _DKL_PHY3_BASE 0x16A000
-#define _DKL_PHY4_BASE 0x16B000
-#define _DKL_PHY5_BASE 0x16C000
-#define _DKL_PHY6_BASE 0x16D000
-
-#define DKL_REG_TC_PORT(__reg) \
- (TC_PORT_1 + ((__reg).reg - _DKL_PHY1_BASE) / (_DKL_PHY2_BASE - _DKL_PHY1_BASE))
-
-/* DEKEL PHY MMIO Address = Phy base + (internal address & ~index_mask) */
-#define _DKL_PCS_DW5 0x14
-#define DKL_PCS_DW5(tc_port) _MMIO(_PORT(tc_port, _DKL_PHY1_BASE, \
- _DKL_PHY2_BASE) + \
- _DKL_PCS_DW5)
-#define DKL_PCS_DW5_CORE_SOFTRESET REG_BIT(11)
-
-#define _DKL_PLL_DIV0 0x200
-#define DKL_PLL_DIV0_AFC_STARTUP_MASK REG_GENMASK(27, 25)
-#define DKL_PLL_DIV0_AFC_STARTUP(val) REG_FIELD_PREP(DKL_PLL_DIV0_AFC_STARTUP_MASK, (val))
-#define DKL_PLL_DIV0_INTEG_COEFF(x) ((x) << 16)
-#define DKL_PLL_DIV0_INTEG_COEFF_MASK (0x1F << 16)
-#define DKL_PLL_DIV0_PROP_COEFF(x) ((x) << 12)
-#define DKL_PLL_DIV0_PROP_COEFF_MASK (0xF << 12)
-#define DKL_PLL_DIV0_FBPREDIV_SHIFT (8)
-#define DKL_PLL_DIV0_FBPREDIV(x) ((x) << DKL_PLL_DIV0_FBPREDIV_SHIFT)
-#define DKL_PLL_DIV0_FBPREDIV_MASK (0xF << DKL_PLL_DIV0_FBPREDIV_SHIFT)
-#define DKL_PLL_DIV0_FBDIV_INT(x) ((x) << 0)
-#define DKL_PLL_DIV0_FBDIV_INT_MASK (0xFF << 0)
-#define DKL_PLL_DIV0_MASK (DKL_PLL_DIV0_INTEG_COEFF_MASK | \
- DKL_PLL_DIV0_PROP_COEFF_MASK | \
- DKL_PLL_DIV0_FBPREDIV_MASK | \
- DKL_PLL_DIV0_FBDIV_INT_MASK)
-#define DKL_PLL_DIV0(tc_port) _MMIO(_PORT(tc_port, _DKL_PHY1_BASE, \
- _DKL_PHY2_BASE) + \
- _DKL_PLL_DIV0)
-
-#define _DKL_PLL_DIV1 0x204
-#define DKL_PLL_DIV1_IREF_TRIM(x) ((x) << 16)
-#define DKL_PLL_DIV1_IREF_TRIM_MASK (0x1F << 16)
-#define DKL_PLL_DIV1_TDC_TARGET_CNT(x) ((x) << 0)
-#define DKL_PLL_DIV1_TDC_TARGET_CNT_MASK (0xFF << 0)
-#define DKL_PLL_DIV1(tc_port) _MMIO(_PORT(tc_port, _DKL_PHY1_BASE, \
- _DKL_PHY2_BASE) + \
- _DKL_PLL_DIV1)
-
-#define _DKL_PLL_SSC 0x210
-#define DKL_PLL_SSC_IREF_NDIV_RATIO(x) ((x) << 29)
-#define DKL_PLL_SSC_IREF_NDIV_RATIO_MASK (0x7 << 29)
-#define DKL_PLL_SSC_STEP_LEN(x) ((x) << 16)
-#define DKL_PLL_SSC_STEP_LEN_MASK (0xFF << 16)
-#define DKL_PLL_SSC_STEP_NUM(x) ((x) << 11)
-#define DKL_PLL_SSC_STEP_NUM_MASK (0x7 << 11)
-#define DKL_PLL_SSC_EN (1 << 9)
-#define DKL_PLL_SSC(tc_port) _MMIO(_PORT(tc_port, _DKL_PHY1_BASE, \
- _DKL_PHY2_BASE) + \
- _DKL_PLL_SSC)
-
-#define _DKL_PLL_BIAS 0x214
-#define DKL_PLL_BIAS_FRAC_EN_H (1 << 30)
-#define DKL_PLL_BIAS_FBDIV_SHIFT (8)
-#define DKL_PLL_BIAS_FBDIV_FRAC(x) ((x) << DKL_PLL_BIAS_FBDIV_SHIFT)
-#define DKL_PLL_BIAS_FBDIV_FRAC_MASK (0x3FFFFF << DKL_PLL_BIAS_FBDIV_SHIFT)
-#define DKL_PLL_BIAS(tc_port) _MMIO(_PORT(tc_port, _DKL_PHY1_BASE, \
- _DKL_PHY2_BASE) + \
- _DKL_PLL_BIAS)
-
-#define _DKL_PLL_TDC_COLDST_BIAS 0x218
-#define DKL_PLL_TDC_SSC_STEP_SIZE(x) ((x) << 8)
-#define DKL_PLL_TDC_SSC_STEP_SIZE_MASK (0xFF << 8)
-#define DKL_PLL_TDC_FEED_FWD_GAIN(x) ((x) << 0)
-#define DKL_PLL_TDC_FEED_FWD_GAIN_MASK (0xFF << 0)
-#define DKL_PLL_TDC_COLDST_BIAS(tc_port) _MMIO(_PORT(tc_port, \
- _DKL_PHY1_BASE, \
- _DKL_PHY2_BASE) + \
- _DKL_PLL_TDC_COLDST_BIAS)
-
-#define _DKL_REFCLKIN_CTL 0x12C
-/* Bits are the same as MG_REFCLKIN_CTL */
-#define DKL_REFCLKIN_CTL(tc_port) _MMIO(_PORT(tc_port, \
- _DKL_PHY1_BASE, \
- _DKL_PHY2_BASE) + \
- _DKL_REFCLKIN_CTL)
-
-#define _DKL_CLKTOP2_HSCLKCTL 0xD4
-/* Bits are the same as MG_CLKTOP2_HSCLKCTL */
-#define DKL_CLKTOP2_HSCLKCTL(tc_port) _MMIO(_PORT(tc_port, \
- _DKL_PHY1_BASE, \
- _DKL_PHY2_BASE) + \
- _DKL_CLKTOP2_HSCLKCTL)
-
-#define _DKL_CLKTOP2_CORECLKCTL1 0xD8
-/* Bits are the same as MG_CLKTOP2_CORECLKCTL1 */
-#define DKL_CLKTOP2_CORECLKCTL1(tc_port) _MMIO(_PORT(tc_port, \
- _DKL_PHY1_BASE, \
- _DKL_PHY2_BASE) + \
- _DKL_CLKTOP2_CORECLKCTL1)
-
-#define _DKL_TX_DPCNTL0 0x2C0
-#define DKL_TX_PRESHOOT_COEFF(x) ((x) << 13)
-#define DKL_TX_PRESHOOT_COEFF_MASK (0x1f << 13)
-#define DKL_TX_DE_EMPHASIS_COEFF(x) ((x) << 8)
-#define DKL_TX_DE_EMPAHSIS_COEFF_MASK (0x1f << 8)
-#define DKL_TX_VSWING_CONTROL(x) ((x) << 0)
-#define DKL_TX_VSWING_CONTROL_MASK (0x7 << 0)
-#define DKL_TX_DPCNTL0(tc_port) _MMIO(_PORT(tc_port, \
- _DKL_PHY1_BASE, \
- _DKL_PHY2_BASE) + \
- _DKL_TX_DPCNTL0)
-
-#define _DKL_TX_DPCNTL1 0x2C4
-/* Bits are the same as DKL_TX_DPCNTRL0 */
-#define DKL_TX_DPCNTL1(tc_port) _MMIO(_PORT(tc_port, \
- _DKL_PHY1_BASE, \
- _DKL_PHY2_BASE) + \
- _DKL_TX_DPCNTL1)
-
-#define _DKL_TX_DPCNTL2 0x2C8
-#define DKL_TX_DP20BITMODE REG_BIT(2)
-#define DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK REG_GENMASK(4, 3)
-#define DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1(val) REG_FIELD_PREP(DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX1_MASK, (val))
-#define DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK REG_GENMASK(6, 5)
-#define DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2(val) REG_FIELD_PREP(DKL_TX_DPCNTL2_CFG_LOADGENSELECT_TX2_MASK, (val))
-#define DKL_TX_DPCNTL2(tc_port) _MMIO(_PORT(tc_port, \
- _DKL_PHY1_BASE, \
- _DKL_PHY2_BASE) + \
- _DKL_TX_DPCNTL2)
-
-#define _DKL_TX_FW_CALIB 0x2F8
-#define DKL_TX_CFG_DISABLE_WAIT_INIT (1 << 7)
-#define DKL_TX_FW_CALIB(tc_port) _MMIO(_PORT(tc_port, \
- _DKL_PHY1_BASE, \
- _DKL_PHY2_BASE) + \
- _DKL_TX_FW_CALIB)
-
-#define _DKL_TX_PMD_LANE_SUS 0xD00
-#define DKL_TX_PMD_LANE_SUS(tc_port) _MMIO(_PORT(tc_port, \
- _DKL_PHY1_BASE, \
- _DKL_PHY2_BASE) + \
- _DKL_TX_PMD_LANE_SUS)
-
-#define _DKL_TX_DW17 0xDC4
-#define DKL_TX_DW17(tc_port) _MMIO(_PORT(tc_port, \
- _DKL_PHY1_BASE, \
- _DKL_PHY2_BASE) + \
- _DKL_TX_DW17)
-
-#define _DKL_TX_DW18 0xDC8
-#define DKL_TX_DW18(tc_port) _MMIO(_PORT(tc_port, \
- _DKL_PHY1_BASE, \
- _DKL_PHY2_BASE) + \
- _DKL_TX_DW18)
-
-#define _DKL_DP_MODE 0xA0
-#define DKL_DP_MODE(tc_port) _MMIO(_PORT(tc_port, \
- _DKL_PHY1_BASE, \
- _DKL_PHY2_BASE) + \
- _DKL_DP_MODE)
-
-#define _DKL_CMN_UC_DW27 0x36C
-#define DKL_CMN_UC_DW27_UC_HEALTH (0x1 << 15)
-#define DKL_CMN_UC_DW_27(tc_port) _MMIO(_PORT(tc_port, \
- _DKL_PHY1_BASE, \
- _DKL_PHY2_BASE) + \
- _DKL_CMN_UC_DW27)
-
-/*
- * Each Dekel PHY is addressed through a 4KB aperture. Each PHY has more than
- * 4KB of register space, so a separate index is programmed in HIP_INDEX_REG0
- * or HIP_INDEX_REG1, based on the port number, to set the upper 2 address
- * bits that point the 4KB window into the full PHY register space.
- */
-#define _HIP_INDEX_REG0 0x1010A0
-#define _HIP_INDEX_REG1 0x1010A4
-#define HIP_INDEX_REG(tc_port) _MMIO((tc_port) < 4 ? _HIP_INDEX_REG0 \
- : _HIP_INDEX_REG1)
-#define _HIP_INDEX_SHIFT(tc_port) (8 * ((tc_port) % 4))
-#define HIP_INDEX_VAL(tc_port, val) ((val) << _HIP_INDEX_SHIFT(tc_port))
-
/* BXT display engine PLL */
#define BXT_DE_PLL_CTL _MMIO(0x6d000)
#define BXT_DE_PLL_RATIO(x) (x) /* {60,65,100} * 19.2MHz */
@@ -7775,12 +7564,10 @@ enum skl_power_gate {
#define _PAL_PREC_DATA_A 0x4A404
#define _PAL_PREC_DATA_B 0x4AC04
#define _PAL_PREC_DATA_C 0x4B404
+/* see PREC_PALETTE_* for the bits */
#define _PAL_PREC_GC_MAX_A 0x4A410
#define _PAL_PREC_GC_MAX_B 0x4AC10
#define _PAL_PREC_GC_MAX_C 0x4B410
-#define PREC_PAL_DATA_RED_MASK REG_GENMASK(29, 20)
-#define PREC_PAL_DATA_GREEN_MASK REG_GENMASK(19, 10)
-#define PREC_PAL_DATA_BLUE_MASK REG_GENMASK(9, 0)
#define _PAL_PREC_EXT_GC_MAX_A 0x4A420
#define _PAL_PREC_EXT_GC_MAX_B 0x4AC20
#define _PAL_PREC_EXT_GC_MAX_C 0x4B420
@@ -7813,12 +7600,7 @@ enum skl_power_gate {
#define _PAL_PREC_MULTI_SEG_DATA_A 0x4A40C
#define _PAL_PREC_MULTI_SEG_DATA_B 0x4AC0C
-#define PAL_PREC_MULTI_SEG_RED_LDW_MASK REG_GENMASK(29, 24)
-#define PAL_PREC_MULTI_SEG_RED_UDW_MASK REG_GENMASK(29, 20)
-#define PAL_PREC_MULTI_SEG_GREEN_LDW_MASK REG_GENMASK(19, 14)
-#define PAL_PREC_MULTI_SEG_GREEN_UDW_MASK REG_GENMASK(19, 10)
-#define PAL_PREC_MULTI_SEG_BLUE_LDW_MASK REG_GENMASK(9, 4)
-#define PAL_PREC_MULTI_SEG_BLUE_UDW_MASK REG_GENMASK(9, 0)
+/* see PREC_PALETTE_12P4_* for the bits */
#define PREC_PAL_MULTI_SEG_INDEX(pipe) _MMIO_PIPE(pipe, \
_PAL_PREC_MULTI_SEG_INDEX_A, \
@@ -7879,13 +7661,17 @@ enum skl_power_gate {
#define _CGM_PIPE_A_CSC_COEFF67 (VLV_DISPLAY_BASE + 0x6790C)
#define _CGM_PIPE_A_CSC_COEFF8 (VLV_DISPLAY_BASE + 0x67910)
#define _CGM_PIPE_A_DEGAMMA (VLV_DISPLAY_BASE + 0x66000)
-#define CGM_PIPE_DEGAMMA_RED_MASK REG_GENMASK(13, 0)
-#define CGM_PIPE_DEGAMMA_GREEN_MASK REG_GENMASK(29, 16)
-#define CGM_PIPE_DEGAMMA_BLUE_MASK REG_GENMASK(13, 0)
+/* cgm degamma ldw */
+#define CGM_PIPE_DEGAMMA_GREEN_LDW_MASK REG_GENMASK(29, 16)
+#define CGM_PIPE_DEGAMMA_BLUE_LDW_MASK REG_GENMASK(13, 0)
+/* cgm degamma udw */
+#define CGM_PIPE_DEGAMMA_RED_UDW_MASK REG_GENMASK(13, 0)
#define _CGM_PIPE_A_GAMMA (VLV_DISPLAY_BASE + 0x67000)
-#define CGM_PIPE_GAMMA_RED_MASK REG_GENMASK(9, 0)
-#define CGM_PIPE_GAMMA_GREEN_MASK REG_GENMASK(25, 16)
-#define CGM_PIPE_GAMMA_BLUE_MASK REG_GENMASK(9, 0)
+/* cgm gamma ldw */
+#define CGM_PIPE_GAMMA_GREEN_LDW_MASK REG_GENMASK(25, 16)
+#define CGM_PIPE_GAMMA_BLUE_LDW_MASK REG_GENMASK(9, 0)
+/* cgm gamma udw */
+#define CGM_PIPE_GAMMA_RED_UDW_MASK REG_GENMASK(9, 0)
#define _CGM_PIPE_A_MODE (VLV_DISPLAY_BASE + 0x67A00)
#define CGM_PIPE_MODE_GAMMA (1 << 2)
#define CGM_PIPE_MODE_CSC (1 << 1)
@@ -7962,8 +7748,13 @@ enum skl_power_gate {
_ICL_PIPE_DSS_CTL2_PB, \
_ICL_PIPE_DSS_CTL2_PC)
+#define GGC _MMIO(0x108040)
+#define GMS_MASK REG_GENMASK(15, 8)
+#define GGMS_MASK REG_GENMASK(7, 6)
+
#define GEN12_GSMBASE _MMIO(0x108100)
#define GEN12_DSMBASE _MMIO(0x1080C0)
+#define GEN12_BDSM_MASK REG_GENMASK64(63, 20)
#define XEHP_CLOCK_GATE_DIS _MMIO(0x101014)
#define SGSI_SIDECLK_DIS REG_BIT(17)
@@ -8344,6 +8135,11 @@ enum skl_power_gate {
#define GEN12_CULLBIT2 _MMIO(0x7030)
#define GEN12_STATE_ACK_DEBUG _MMIO(0x20BC)
+#define _MTL_CLKGATE_DIS_TRANS_A 0x604E8
+#define _MTL_CLKGATE_DIS_TRANS_B 0x614E8
+#define MTL_CLKGATE_DIS_TRANS(trans) _MMIO_TRANS2(trans, _MTL_CLKGATE_DIS_TRANS_A)
+#define MTL_CLKGATE_DIS_TRANS_DMASC_GATING_DIS REG_BIT(7)
+
#define MTL_LATENCY_LP0_LP1 _MMIO(0x45780)
#define MTL_LATENCY_LP2_LP3 _MMIO(0x45784)
#define MTL_LATENCY_LP4_LP5 _MMIO(0x45788)
@@ -8367,4 +8163,6 @@ enum skl_power_gate {
#define MTL_TRAS_MASK REG_GENMASK(16, 8)
#define MTL_TRDPRE_MASK REG_GENMASK(7, 0)
+#define MTL_MEDIA_GSI_BASE 0x380000
+
#endif /* _I915_REG_H_ */
diff --git a/drivers/gpu/drm/i915/i915_reg_defs.h b/drivers/gpu/drm/i915/i915_reg_defs.h
index 8f486f77609f..be43580a6979 100644
--- a/drivers/gpu/drm/i915/i915_reg_defs.h
+++ b/drivers/gpu/drm/i915/i915_reg_defs.h
@@ -98,29 +98,54 @@
*/
#define REG_FIELD_GET64(__mask, __val) ((u64)FIELD_GET(__mask, __val))
+#define __MASKED_FIELD(mask, value) ((mask) << 16 | (value))
+#define _MASKED_FIELD(mask, value) ({ \
+ if (__builtin_constant_p(mask)) \
+ BUILD_BUG_ON_MSG(((mask) & 0xffff0000), "Incorrect mask"); \
+ if (__builtin_constant_p(value)) \
+ BUILD_BUG_ON_MSG((value) & 0xffff0000, "Incorrect value"); \
+ if (__builtin_constant_p(mask) && __builtin_constant_p(value)) \
+ BUILD_BUG_ON_MSG((value) & ~(mask), \
+ "Incorrect value for mask"); \
+ __MASKED_FIELD(mask, value); })
+#define _MASKED_BIT_ENABLE(a) ({ typeof(a) _a = (a); _MASKED_FIELD(_a, _a); })
+#define _MASKED_BIT_DISABLE(a) (_MASKED_FIELD((a), 0))
+
+/*
+ * Given the first two numbers __a and __b of arbitrarily many evenly spaced
+ * numbers, pick the 0-based __index'th value.
+ *
+ * Always prefer this over _PICK() if the numbers are evenly spaced.
+ */
+#define _PICK_EVEN(__index, __a, __b) ((__a) + (__index) * ((__b) - (__a)))
+
+/*
+ * Given the arbitrary numbers in varargs, pick the 0-based __index'th number.
+ *
+ * Always prefer _PICK_EVEN() over this if the numbers are evenly spaced.
+ */
+#define _PICK(__index, ...) (((const u32 []){ __VA_ARGS__ })[__index])
+
typedef struct {
u32 reg;
} i915_reg_t;
#define _MMIO(r) ((const i915_reg_t){ .reg = (r) })
-#define INVALID_MMIO_REG _MMIO(0)
-
-static __always_inline u32 i915_mmio_reg_offset(i915_reg_t reg)
-{
- return reg.reg;
-}
-
-static inline bool i915_mmio_reg_equal(i915_reg_t a, i915_reg_t b)
-{
- return i915_mmio_reg_offset(a) == i915_mmio_reg_offset(b);
-}
+typedef struct {
+ u32 reg;
+} i915_mcr_reg_t;
-static inline bool i915_mmio_reg_valid(i915_reg_t reg)
-{
- return !i915_mmio_reg_equal(reg, INVALID_MMIO_REG);
-}
+#define INVALID_MMIO_REG _MMIO(0)
-#define VLV_DISPLAY_BASE 0x180000
+/*
+ * These macros can be used on either i915_reg_t or i915_mcr_reg_t since they're
+ * simply operations on the register's offset and don't care about the MCR vs
+ * non-MCR nature of the register.
+ */
+#define i915_mmio_reg_offset(r) \
+ _Generic((r), i915_reg_t: (r).reg, i915_mcr_reg_t: (r).reg)
+#define i915_mmio_reg_equal(a, b) (i915_mmio_reg_offset(a) == i915_mmio_reg_offset(b))
+#define i915_mmio_reg_valid(r) (!i915_mmio_reg_equal(r, INVALID_MMIO_REG))
#endif /* __I915_REG_DEFS__ */
diff --git a/drivers/gpu/drm/i915/i915_request.c b/drivers/gpu/drm/i915/i915_request.c
index 62fad16a55e8..f949a9495758 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -1621,6 +1621,20 @@ i915_request_await_object(struct i915_request *to,
return ret;
}
+static void i915_request_await_huc(struct i915_request *rq)
+{
+ struct intel_huc *huc = &rq->context->engine->gt->uc.huc;
+
+ /* don't stall kernel submissions! */
+ if (!rcu_access_pointer(rq->context->gem_context))
+ return;
+
+ if (intel_huc_wait_required(huc))
+ i915_sw_fence_await_sw_fence(&rq->submit,
+ &huc->delayed_load.fence,
+ &rq->hucq);
+}
+
static struct i915_request *
__i915_request_ensure_parallel_ordering(struct i915_request *rq,
struct intel_timeline *timeline)
@@ -1703,6 +1717,16 @@ __i915_request_add_to_timeline(struct i915_request *rq)
struct i915_request *prev;
/*
+ * Media workloads may require HuC, so stall them until HuC loading is
+ * complete. Note that HuC not being loaded when a user submission
+ * arrives can only happen when HuC is loaded via GSC and in that case
+ * we still expect the window between us starting to accept submissions
+ * and HuC loading completion to be small (a few hundred ms).
+ */
+ if (rq->engine->class == VIDEO_DECODE_CLASS)
+ i915_request_await_huc(rq);
+
+ /*
* Dependency tracking and request ordering along the timeline
* is special cased so that we can eliminate redundant ordering
* operations while building the request (we know that the timeline
diff --git a/drivers/gpu/drm/i915/i915_request.h b/drivers/gpu/drm/i915/i915_request.h
index 47041ec68df8..f5e1bb5e857a 100644
--- a/drivers/gpu/drm/i915/i915_request.h
+++ b/drivers/gpu/drm/i915/i915_request.h
@@ -348,6 +348,11 @@ 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_t hucq;
+
I915_SELFTEST_DECLARE(struct {
struct list_head link;
unsigned long delay;
diff --git a/drivers/gpu/drm/i915/i915_scatterlist.c b/drivers/gpu/drm/i915/i915_scatterlist.c
index dcc081874ec8..114e5e39aa72 100644
--- a/drivers/gpu/drm/i915/i915_scatterlist.c
+++ b/drivers/gpu/drm/i915/i915_scatterlist.c
@@ -158,7 +158,7 @@ struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res,
u32 page_alignment)
{
struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res);
- const u64 size = res->num_pages << PAGE_SHIFT;
+ const u64 size = res->size;
const u32 max_segment = round_down(UINT_MAX, page_alignment);
struct drm_buddy *mm = bman_res->mm;
struct list_head *blocks = &bman_res->blocks;
@@ -177,7 +177,7 @@ struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res,
i915_refct_sgt_init(rsgt, size);
st = &rsgt->table;
- if (sg_alloc_table(st, res->num_pages, GFP_KERNEL)) {
+ if (sg_alloc_table(st, PFN_UP(res->size), GFP_KERNEL)) {
i915_refct_sgt_put(rsgt);
return ERR_PTR(-ENOMEM);
}
diff --git a/drivers/gpu/drm/i915/i915_selftest.h b/drivers/gpu/drm/i915/i915_selftest.h
index f54de0499be7..bdf3e22c0a34 100644
--- a/drivers/gpu/drm/i915/i915_selftest.h
+++ b/drivers/gpu/drm/i915/i915_selftest.h
@@ -92,12 +92,14 @@ int __i915_subtests(const char *caller,
T, ARRAY_SIZE(T), data)
#define i915_live_subtests(T, data) ({ \
typecheck(struct drm_i915_private *, data); \
+ (data)->gt[0]->uc.guc.submission_state.sched_disable_delay_ms = 0; \
__i915_subtests(__func__, \
__i915_live_setup, __i915_live_teardown, \
T, ARRAY_SIZE(T), data); \
})
#define intel_gt_live_subtests(T, data) ({ \
typecheck(struct intel_gt *, data); \
+ (data)->uc.guc.submission_state.sched_disable_delay_ms = 0; \
__i915_subtests(__func__, \
__intel_gt_live_setup, __intel_gt_live_teardown, \
T, ARRAY_SIZE(T), data); \
diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c
index 6fc0d1b89690..cc2a8821d22a 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence.c
+++ b/drivers/gpu/drm/i915/i915_sw_fence.c
@@ -571,7 +571,6 @@ int __i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
int i915_sw_fence_await_reservation(struct i915_sw_fence *fence,
struct dma_resv *resv,
- const struct dma_fence_ops *exclude,
bool write,
unsigned long timeout,
gfp_t gfp)
diff --git a/drivers/gpu/drm/i915/i915_sw_fence.h b/drivers/gpu/drm/i915/i915_sw_fence.h
index 619fc5a22f0c..f752bfc7c6e1 100644
--- a/drivers/gpu/drm/i915/i915_sw_fence.h
+++ b/drivers/gpu/drm/i915/i915_sw_fence.h
@@ -91,7 +91,6 @@ int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence,
int i915_sw_fence_await_reservation(struct i915_sw_fence *fence,
struct dma_resv *resv,
- const struct dma_fence_ops *exclude,
bool write,
unsigned long timeout,
gfp_t gfp);
diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c
index 1e2750210831..595e8b574990 100644
--- a/drivers/gpu/drm/i915/i915_sysfs.c
+++ b/drivers/gpu/drm/i915/i915_sysfs.c
@@ -218,7 +218,8 @@ static const struct bin_attribute error_state_attr = {
static void i915_setup_error_capture(struct device *kdev)
{
if (sysfs_create_bin_file(&kdev->kobj, &error_state_attr))
- DRM_ERROR("error_state sysfs setup failed\n");
+ drm_err(&kdev_minor_to_i915(kdev)->drm,
+ "error_state sysfs setup failed\n");
}
static void i915_teardown_error_capture(struct device *kdev)
diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h
index 37b5c9e9d260..f6f9228a1351 100644
--- a/drivers/gpu/drm/i915/i915_trace.h
+++ b/drivers/gpu/drm/i915/i915_trace.h
@@ -15,7 +15,6 @@
#include "gt/intel_engine.h"
#include "i915_drv.h"
-#include "i915_irq.h"
/* object tracking */
@@ -671,21 +670,6 @@ TRACE_EVENT_CONDITION(i915_reg_rw,
(u32)(__entry->val >> 32))
);
-TRACE_EVENT(intel_gpu_freq_change,
- TP_PROTO(u32 freq),
- TP_ARGS(freq),
-
- TP_STRUCT__entry(
- __field(u32, freq)
- ),
-
- TP_fast_assign(
- __entry->freq = freq;
- ),
-
- TP_printk("new_freq=%u", __entry->freq)
-);
-
/**
* DOC: i915_ppgtt_create and i915_ppgtt_release tracepoints
*
diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
index e19452f0e100..7e611476c7a4 100644
--- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
+++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c
@@ -62,8 +62,8 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man,
if (place->fpfn || lpfn != man->size)
bman_res->flags |= DRM_BUDDY_RANGE_ALLOCATION;
- GEM_BUG_ON(!bman_res->base.num_pages);
- size = bman_res->base.num_pages << PAGE_SHIFT;
+ GEM_BUG_ON(!bman_res->base.size);
+ size = bman_res->base.size;
min_page_size = bman->default_page_size;
if (bo->page_alignment)
@@ -72,7 +72,7 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man,
GEM_BUG_ON(min_page_size < mm->chunk_size);
GEM_BUG_ON(!IS_ALIGNED(size, min_page_size));
- if (place->fpfn + bman_res->base.num_pages != place->lpfn &&
+ if (place->fpfn + PFN_UP(bman_res->base.size) != place->lpfn &&
place->flags & TTM_PL_FLAG_CONTIGUOUS) {
unsigned long pages;
@@ -108,7 +108,7 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man,
goto err_free_blocks;
if (place->flags & TTM_PL_FLAG_CONTIGUOUS) {
- u64 original_size = (u64)bman_res->base.num_pages << PAGE_SHIFT;
+ u64 original_size = (u64)bman_res->base.size;
drm_buddy_block_trim(mm,
original_size,
@@ -116,7 +116,7 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man,
}
if (lpfn <= bman->visible_size) {
- bman_res->used_visible_size = bman_res->base.num_pages;
+ bman_res->used_visible_size = PFN_UP(bman_res->base.size);
} else {
struct drm_buddy_block *block;
@@ -228,7 +228,7 @@ static bool i915_ttm_buddy_man_compatible(struct ttm_resource_manager *man,
if (!place->fpfn &&
place->lpfn == i915_ttm_buddy_man_visible_size(man))
- return bman_res->used_visible_size == res->num_pages;
+ return bman_res->used_visible_size == PFN_UP(res->size);
/* Check each drm buddy block individually */
list_for_each_entry(block, &bman_res->blocks, link) {
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
index f17c09ead7d7..703fee6b5f75 100644
--- a/drivers/gpu/drm/i915/i915_vma.c
+++ b/drivers/gpu/drm/i915/i915_vma.c
@@ -73,14 +73,16 @@ static void vma_print_allocator(struct i915_vma *vma, const char *reason)
char buf[512];
if (!vma->node.stack) {
- DRM_DEBUG_DRIVER("vma.node [%08llx + %08llx] %s: unknown owner\n",
- vma->node.start, vma->node.size, reason);
+ drm_dbg(&to_i915(vma->obj->base.dev)->drm,
+ "vma.node [%08llx + %08llx] %s: unknown owner\n",
+ vma->node.start, vma->node.size, reason);
return;
}
stack_depot_snprint(vma->node.stack, buf, sizeof(buf), 0);
- DRM_DEBUG_DRIVER("vma.node [%08llx + %08llx] %s: inserted at %s\n",
- vma->node.start, vma->node.size, reason, buf);
+ drm_dbg(&to_i915(vma->obj->base.dev)->drm,
+ "vma.node [%08llx + %08llx] %s: inserted at %s\n",
+ vma->node.start, vma->node.size, reason, buf);
}
#else
@@ -776,21 +778,15 @@ i915_vma_insert(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
GEM_BUG_ON(!IS_ALIGNED(end, I915_GTT_PAGE_SIZE));
alignment = max(alignment, i915_vm_obj_min_alignment(vma->vm, vma->obj));
- /*
- * for compact-pt we round up the reservation to prevent
- * any smaller pages being used within the same PDE
- */
- if (NEEDS_COMPACT_PT(vma->vm->i915))
- size = round_up(size, alignment);
/* If binding the object/GGTT view requires more space than the entire
* aperture has, reject it early before evicting everything in a vain
* attempt to find space.
*/
if (size > end) {
- DRM_DEBUG("Attempting to bind an object larger than the aperture: request=%llu > %s aperture=%llu\n",
- size, flags & PIN_MAPPABLE ? "mappable" : "total",
- end);
+ drm_dbg(&to_i915(vma->obj->base.dev)->drm,
+ "Attempting to bind an object larger than the aperture: request=%llu > %s aperture=%llu\n",
+ size, flags & PIN_MAPPABLE ? "mappable" : "total", end);
return -ENOSPC;
}
@@ -820,7 +816,8 @@ i915_vma_insert(struct i915_vma *vma, struct i915_gem_ww_ctx *ww,
* forseeable future. See also i915_ggtt_offset().
*/
if (upper_32_bits(end - 1) &&
- vma->page_sizes.sg > I915_GTT_PAGE_SIZE) {
+ vma->page_sizes.sg > I915_GTT_PAGE_SIZE &&
+ !HAS_64K_PAGES(vma->vm->i915)) {
/*
* We can't mix 64K and 4K PTEs in the same page-table
* (2M block), and so to avoid the ugliness and
@@ -1847,6 +1844,11 @@ int _i915_vma_move_to_active(struct i915_vma *vma,
GEM_BUG_ON(!vma->pages);
+ if (!(flags & __EXEC_OBJECT_NO_REQUEST_AWAIT)) {
+ err = i915_request_await_object(rq, vma->obj, flags & EXEC_OBJECT_WRITE);
+ if (unlikely(err))
+ return err;
+ }
err = __i915_vma_move_to_active(vma, rq);
if (unlikely(err))
return err;
diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h
index aecd9c64486b..0757977a489b 100644
--- a/drivers/gpu/drm/i915/i915_vma.h
+++ b/drivers/gpu/drm/i915/i915_vma.h
@@ -55,6 +55,7 @@ static inline bool i915_vma_is_active(const struct i915_vma *vma)
/* do not reserve memory to prevent deadlocks */
#define __EXEC_OBJECT_NO_RESERVE BIT(31)
+#define __EXEC_OBJECT_NO_REQUEST_AWAIT BIT(30)
int __must_check _i915_vma_move_to_active(struct i915_vma *vma,
struct i915_request *rq,
diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c
index 20575eb77ea7..849baf6c3b3c 100644
--- a/drivers/gpu/drm/i915/intel_device_info.c
+++ b/drivers/gpu/drm/i915/intel_device_info.c
@@ -29,9 +29,11 @@
#include "display/intel_cdclk.h"
#include "display/intel_de.h"
-#include "intel_device_info.h"
+#include "gt/intel_gt_regs.h"
#include "i915_drv.h"
+#include "i915_reg.h"
#include "i915_utils.h"
+#include "intel_device_info.h"
#define PLATFORM_NAME(x) [INTEL_##x] = #x
static const char * const platform_names[] = {
@@ -231,7 +233,7 @@ static bool find_devid(u16 id, const u16 *p, unsigned int num)
return false;
}
-void intel_device_info_subplatform_init(struct drm_i915_private *i915)
+static void intel_device_info_subplatform_init(struct drm_i915_private *i915)
{
const struct intel_device_info *info = INTEL_INFO(i915);
const struct intel_runtime_info *rinfo = RUNTIME_INFO(i915);
@@ -288,6 +290,78 @@ void intel_device_info_subplatform_init(struct drm_i915_private *i915)
RUNTIME_INFO(i915)->platform_mask[pi] |= mask;
}
+static void ip_ver_read(struct drm_i915_private *i915, u32 offset, struct intel_ip_version *ip)
+{
+ struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
+ void __iomem *addr;
+ u32 val;
+ u8 expected_ver = ip->ver;
+ u8 expected_rel = ip->rel;
+
+ addr = pci_iomap_range(pdev, 0, offset, sizeof(u32));
+ if (drm_WARN_ON(&i915->drm, !addr))
+ return;
+
+ val = ioread32(addr);
+ pci_iounmap(pdev, addr);
+
+ ip->ver = REG_FIELD_GET(GMD_ID_ARCH_MASK, val);
+ ip->rel = REG_FIELD_GET(GMD_ID_RELEASE_MASK, val);
+ ip->step = REG_FIELD_GET(GMD_ID_STEP, val);
+
+ /* Sanity check against expected versions from device info */
+ if (IP_VER(ip->ver, ip->rel) < IP_VER(expected_ver, expected_rel))
+ drm_dbg(&i915->drm,
+ "Hardware reports GMD IP version %u.%u (REG[0x%x] = 0x%08x) but minimum expected is %u.%u\n",
+ ip->ver, ip->rel, offset, val, expected_ver, expected_rel);
+}
+
+/*
+ * Setup the graphics version for the current device. This must be done before
+ * any code that performs checks on GRAPHICS_VER or DISPLAY_VER, so this
+ * function should be called very early in the driver initialization sequence.
+ *
+ * Regular MMIO access is not yet setup at the point this function is called so
+ * we peek at the appropriate MMIO offset directly. The GMD_ID register is
+ * part of an 'always on' power well by design, so we don't need to worry about
+ * forcewake while reading it.
+ */
+static void intel_ipver_early_init(struct drm_i915_private *i915)
+{
+ struct intel_runtime_info *runtime = RUNTIME_INFO(i915);
+
+ if (!HAS_GMD_ID(i915)) {
+ drm_WARN_ON(&i915->drm, RUNTIME_INFO(i915)->graphics.ip.ver > 12);
+ /*
+ * On older platforms, graphics and media share the same ip
+ * version and release.
+ */
+ RUNTIME_INFO(i915)->media.ip =
+ RUNTIME_INFO(i915)->graphics.ip;
+ return;
+ }
+
+ ip_ver_read(i915, i915_mmio_reg_offset(GMD_ID_GRAPHICS),
+ &runtime->graphics.ip);
+ 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);
+}
+
+/**
+ * intel_device_info_runtime_init_early - initialize early runtime info
+ * @i915: the i915 device
+ *
+ * Determine early intel_device_info fields at runtime. This function needs
+ * to be called before the MMIO has been setup.
+ */
+void intel_device_info_runtime_init_early(struct drm_i915_private *i915)
+{
+ intel_ipver_early_init(i915);
+ intel_device_info_subplatform_init(i915);
+}
+
/**
* intel_device_info_runtime_init - initialize runtime info
* @dev_priv: the i915 device
@@ -415,7 +489,7 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv)
if (DISPLAY_VER(dev_priv) >= 11 && (dfsm & ICL_DFSM_DMC_DISABLE))
runtime->has_dmc = 0;
- if (DISPLAY_VER(dev_priv) >= 10 &&
+ if (IS_DISPLAY_VER(dev_priv, 10, 12) &&
(dfsm & GLK_DFSM_DISPLAY_DSC_DISABLE))
runtime->has_dsc = 0;
}
@@ -442,6 +516,11 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv)
runtime->has_dmc = false;
runtime->has_dsc = false;
}
+
+ /* 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;
}
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 d638235e1d26..d588e5fd2eea 100644
--- a/drivers/gpu/drm/i915/intel_device_info.h
+++ b/drivers/gpu/drm/i915/intel_device_info.h
@@ -146,13 +146,13 @@ enum intel_ppgtt_type {
/* Keep has_* in alphabetical order */ \
func(has_64bit_reloc); \
func(has_64k_pages); \
- func(needs_compact_pt); \
func(gpu_reset_clobbers_display); \
func(has_reset_engine); \
func(has_3d_pipeline); \
func(has_4tile); \
func(has_flat_ccs); \
func(has_global_mocs); \
+ func(has_gmd_id); \
func(has_gt_uc); \
func(has_heci_pxp); \
func(has_heci_gscfi); \
@@ -164,6 +164,8 @@ enum intel_ppgtt_type {
func(has_logical_ring_elsq); \
func(has_media_ratio_mode); \
func(has_mslice_steering); \
+ func(has_oa_bpc_reporting); \
+ func(has_oa_slice_contrib_limits); \
func(has_one_eu_per_fuse_bit); \
func(has_pxp); \
func(has_rc6); \
@@ -180,6 +182,7 @@ enum intel_ppgtt_type {
/* 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); \
@@ -195,20 +198,25 @@ enum intel_ppgtt_type {
func(overlay_needs_physical); \
func(supports_tv);
-struct ip_version {
+struct intel_ip_version {
u8 ver;
u8 rel;
+ u8 step;
};
struct intel_runtime_info {
+ /*
+ * Single "graphics" IP version that represents
+ * render, compute and copy behavior.
+ */
struct {
- struct ip_version ip;
+ struct intel_ip_version ip;
} graphics;
struct {
- struct ip_version ip;
+ struct intel_ip_version ip;
} media;
struct {
- struct ip_version ip;
+ struct intel_ip_version ip;
} display;
/*
@@ -308,7 +316,7 @@ struct intel_driver_caps {
const char *intel_platform_name(enum intel_platform platform);
-void intel_device_info_subplatform_init(struct drm_i915_private *dev_priv);
+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);
void intel_device_info_print(const struct intel_device_info *info,
diff --git a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c
index 8279dc580a3e..ce6b3c3b636a 100644
--- a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c
+++ b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c
@@ -6,6 +6,7 @@
#include "display/intel_audio_regs.h"
#include "display/intel_backlight_regs.h"
#include "display/intel_dmc_regs.h"
+#include "display/intel_dpio_phy.h"
#include "display/vlv_dsi_pll_regs.h"
#include "gt/intel_gt_regs.h"
#include "gvt/gvt.h"
@@ -102,7 +103,7 @@ static int iterate_generic_mmio(struct intel_gvt_mmio_table_iter *iter)
MMIO_D(_MMIO(0x2438));
MMIO_D(_MMIO(0x243c));
MMIO_D(_MMIO(0x7018));
- MMIO_D(HALF_SLICE_CHICKEN3);
+ MMIO_D(HSW_HALF_SLICE_CHICKEN3);
MMIO_D(GEN7_HALF_SLICE_CHICKEN1);
/* display */
MMIO_F(_MMIO(0x60220), 0x20);
diff --git a/drivers/gpu/drm/i915/intel_mchbar_regs.h b/drivers/gpu/drm/i915/intel_mchbar_regs.h
index ffc702b79579..f93e9af43ac3 100644
--- a/drivers/gpu/drm/i915/intel_mchbar_regs.h
+++ b/drivers/gpu/drm/i915/intel_mchbar_regs.h
@@ -189,6 +189,21 @@
#define DG1_QCLK_RATIO_MASK REG_GENMASK(9, 2)
#define DG1_QCLK_REFERENCE REG_BIT(10)
+/*
+ * *_PACKAGE_POWER_SKU - SKU power and timing parameters.
+ */
+#define PCU_PACKAGE_POWER_SKU _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5930)
+#define PKG_PKG_TDP GENMASK_ULL(14, 0)
+#define PKG_MAX_WIN GENMASK_ULL(54, 48)
+#define PKG_MAX_WIN_X GENMASK_ULL(54, 53)
+#define PKG_MAX_WIN_Y GENMASK_ULL(52, 48)
+
+#define PCU_PACKAGE_POWER_SKU_UNIT _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5938)
+#define PKG_PWR_UNIT REG_GENMASK(3, 0)
+#define PKG_ENERGY_UNIT REG_GENMASK(12, 8)
+#define PKG_TIME_UNIT REG_GENMASK(19, 16)
+#define PCU_PACKAGE_ENERGY_STATUS _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x593c)
+
#define GEN6_GT_PERF_STATUS _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5948)
#define GEN6_RP_STATE_LIMITS _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5994)
#define GEN6_RP_STATE_CAP _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5998)
@@ -198,6 +213,12 @@
#define GEN10_FREQ_INFO_REC _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5ef0)
#define RPE_MASK REG_GENMASK(15, 8)
+#define PCU_PACKAGE_RAPL_LIMIT _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x59a0)
+#define PKG_PWR_LIM_1 REG_GENMASK(14, 0)
+#define PKG_PWR_LIM_1_EN REG_BIT(15)
+#define PKG_PWR_LIM_1_TIME REG_GENMASK(23, 17)
+#define PKG_PWR_LIM_1_TIME_X REG_GENMASK(23, 22)
+#define PKG_PWR_LIM_1_TIME_Y REG_GENMASK(21, 17)
/* snb MCH registers for priority tuning */
#define MCH_SSKPD _MMIO(MCHBAR_MIRROR_BASE_SNB + 0x5d10)
diff --git a/drivers/gpu/drm/i915/intel_memory_region.c b/drivers/gpu/drm/i915/intel_memory_region.c
index 9a4a7fb55582..b9a164efd6ae 100644
--- a/drivers/gpu/drm/i915/intel_memory_region.c
+++ b/drivers/gpu/drm/i915/intel_memory_region.c
@@ -38,7 +38,7 @@ static int __iopagetest(struct intel_memory_region *mem,
u8 value, resource_size_t offset,
const void *caller)
{
- int byte = prandom_u32_max(pagesize);
+ int byte = get_random_u32_below(pagesize);
u8 result[3];
memset_io(va, value, pagesize); /* or GPF! */
@@ -92,7 +92,7 @@ static int iopagetest(struct intel_memory_region *mem,
static resource_size_t random_page(resource_size_t last)
{
/* Limited to low 44b (16TiB), but should suffice for a spot check */
- return prandom_u32_max(last >> PAGE_SHIFT) << PAGE_SHIFT;
+ return get_random_u32_below(last >> PAGE_SHIFT) << PAGE_SHIFT;
}
static int iomemtest(struct intel_memory_region *mem,
diff --git a/drivers/gpu/drm/i915/intel_pci_config.h b/drivers/gpu/drm/i915/intel_pci_config.h
index 4977a524ce6f..23b8e519f333 100644
--- a/drivers/gpu/drm/i915/intel_pci_config.h
+++ b/drivers/gpu/drm/i915/intel_pci_config.h
@@ -7,11 +7,29 @@
#define __INTEL_PCI_CONFIG_H__
/* PCI BARs */
-#define GTTMMADR_BAR 0
-#define GEN2_GTTMMADR_BAR 1
-#define GFXMEM_BAR 2
-#define GTT_APERTURE_BAR GFXMEM_BAR
-#define GEN12_LMEM_BAR GFXMEM_BAR
+#define GEN2_GMADR_BAR 0
+#define GEN2_MMADR_BAR 1 /* MMIO+GTT, despite the name */
+#define GEN2_IO_BAR 2 /* 85x/865 */
+
+#define GEN3_MMADR_BAR 0 /* MMIO only */
+#define GEN3_IO_BAR 1
+#define GEN3_GMADR_BAR 2
+#define GEN3_GTTADR_BAR 3 /* GTT only */
+
+#define GEN4_GTTMMADR_BAR 0 /* MMIO+GTT */
+#define GEN4_GMADR_BAR 2
+#define GEN4_IO_BAR 4
+
+#define GEN12_LMEM_BAR 2
+
+static inline int intel_mmio_bar(int graphics_ver)
+{
+ switch (graphics_ver) {
+ case 2: return GEN2_MMADR_BAR;
+ case 3: return GEN3_MMADR_BAR;
+ default: return GEN4_GTTMMADR_BAR;
+ }
+}
/* BSM in include/drm/i915_drm.h */
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 8f86f56e7ca4..73c88b1c9545 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -30,6 +30,8 @@
#include "display/skl_watermark.h"
#include "gt/intel_engine_regs.h"
+#include "gt/intel_gt.h"
+#include "gt/intel_gt_mcr.h"
#include "gt/intel_gt_regs.h"
#include "i915_drv.h"
@@ -58,25 +60,20 @@ static void gen9_init_clock_gating(struct drm_i915_private *dev_priv)
* Must match Sampler, Pixel Back End, and Media. See
* WaCompressedResourceSamplerPbeMediaNewHashMode.
*/
- intel_uncore_write(&dev_priv->uncore, CHICKEN_PAR1_1,
- intel_uncore_read(&dev_priv->uncore, CHICKEN_PAR1_1) |
- SKL_DE_COMPRESSED_HASH_MODE);
+ intel_uncore_rmw(&dev_priv->uncore, CHICKEN_PAR1_1, 0, SKL_DE_COMPRESSED_HASH_MODE);
}
/* See Bspec note for PSR2_CTL bit 31, Wa#828:skl,bxt,kbl,cfl */
- intel_uncore_write(&dev_priv->uncore, CHICKEN_PAR1_1,
- intel_uncore_read(&dev_priv->uncore, CHICKEN_PAR1_1) | SKL_EDP_PSR_FIX_RDWRAP);
+ intel_uncore_rmw(&dev_priv->uncore, CHICKEN_PAR1_1, 0, SKL_EDP_PSR_FIX_RDWRAP);
/* WaEnableChickenDCPR:skl,bxt,kbl,glk,cfl */
- intel_uncore_write(&dev_priv->uncore, GEN8_CHICKEN_DCPR_1,
- intel_uncore_read(&dev_priv->uncore, GEN8_CHICKEN_DCPR_1) | MASK_WAKEMEM);
+ intel_uncore_rmw(&dev_priv->uncore, GEN8_CHICKEN_DCPR_1, 0, MASK_WAKEMEM);
/*
* WaFbcWakeMemOn:skl,bxt,kbl,glk,cfl
* Display WA #0859: skl,bxt,kbl,glk,cfl
*/
- intel_uncore_write(&dev_priv->uncore, DISP_ARB_CTL, intel_uncore_read(&dev_priv->uncore, DISP_ARB_CTL) |
- DISP_FBC_MEMORY_WAKE);
+ intel_uncore_rmw(&dev_priv->uncore, DISP_ARB_CTL, 0, DISP_FBC_MEMORY_WAKE);
}
static void bxt_init_clock_gating(struct drm_i915_private *dev_priv)
@@ -84,15 +81,13 @@ static void bxt_init_clock_gating(struct drm_i915_private *dev_priv)
gen9_init_clock_gating(dev_priv);
/* WaDisableSDEUnitClockGating:bxt */
- intel_uncore_write(&dev_priv->uncore, GEN8_UCGCTL6, intel_uncore_read(&dev_priv->uncore, GEN8_UCGCTL6) |
- GEN8_SDEUNIT_CLOCK_GATE_DISABLE);
+ intel_uncore_rmw(&dev_priv->uncore, GEN8_UCGCTL6, 0, GEN8_SDEUNIT_CLOCK_GATE_DISABLE);
/*
* FIXME:
* GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ applies on 3x6 GT SKUs only.
*/
- intel_uncore_write(&dev_priv->uncore, GEN8_UCGCTL6, intel_uncore_read(&dev_priv->uncore, GEN8_UCGCTL6) |
- GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ);
+ intel_uncore_rmw(&dev_priv->uncore, GEN8_UCGCTL6, 0, GEN8_HDCUNIT_CLOCK_GATE_DISABLE_HDCREQ);
/*
* Wa: Backlight PWM may stop in the asserted state, causing backlight
@@ -113,16 +108,13 @@ static void bxt_init_clock_gating(struct drm_i915_private *dev_priv)
* WaFbcTurnOffFbcWatermark:bxt
* Display WA #0562: bxt
*/
- intel_uncore_write(&dev_priv->uncore, DISP_ARB_CTL, intel_uncore_read(&dev_priv->uncore, DISP_ARB_CTL) |
- DISP_FBC_WM_DIS);
+ intel_uncore_rmw(&dev_priv->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS);
/*
* WaFbcHighMemBwCorruptionAvoidance:bxt
* Display WA #0883: bxt
*/
- intel_uncore_write(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A),
- intel_uncore_read(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A)) |
- DPFC_DISABLE_DUMMY0);
+ intel_uncore_rmw(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), 0, DPFC_DISABLE_DUMMY0);
}
static void glk_init_clock_gating(struct drm_i915_private *dev_priv)
@@ -895,19 +887,14 @@ static void pnv_update_wm(struct drm_i915_private *dev_priv)
wm = intel_calculate_wm(pixel_rate, &pnv_cursor_wm,
pnv_display_wm.fifo_size,
4, latency->cursor_sr);
- reg = intel_uncore_read(&dev_priv->uncore, DSPFW3);
- reg &= ~DSPFW_CURSOR_SR_MASK;
- reg |= FW_WM(wm, CURSOR_SR);
- intel_uncore_write(&dev_priv->uncore, DSPFW3, reg);
+ intel_uncore_rmw(&dev_priv->uncore, DSPFW3, DSPFW_CURSOR_SR_MASK,
+ FW_WM(wm, CURSOR_SR));
/* Display HPLL off SR */
wm = intel_calculate_wm(pixel_rate, &pnv_display_hplloff_wm,
pnv_display_hplloff_wm.fifo_size,
cpp, latency->display_hpll_disable);
- reg = intel_uncore_read(&dev_priv->uncore, DSPFW3);
- reg &= ~DSPFW_HPLL_SR_MASK;
- reg |= FW_WM(wm, HPLL_SR);
- intel_uncore_write(&dev_priv->uncore, DSPFW3, reg);
+ intel_uncore_rmw(&dev_priv->uncore, DSPFW3, DSPFW_HPLL_SR_MASK, FW_WM(wm, HPLL_SR));
/* cursor HPLL off SR */
wm = intel_calculate_wm(pixel_rate, &pnv_cursor_hplloff_wm,
@@ -1337,34 +1324,14 @@ static bool g4x_compute_fbc_en(const struct g4x_wm_state *wm_state,
return true;
}
-static int g4x_compute_pipe_wm(struct intel_atomic_state *state,
- struct intel_crtc *crtc)
+static int _g4x_compute_pipe_wm(struct intel_crtc_state *crtc_state)
{
- struct intel_crtc_state *crtc_state =
- intel_atomic_get_new_crtc_state(state, crtc);
+ struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
struct g4x_wm_state *wm_state = &crtc_state->wm.g4x.optimal;
u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
const struct g4x_pipe_wm *raw;
- const struct intel_plane_state *old_plane_state;
- const struct intel_plane_state *new_plane_state;
- struct intel_plane *plane;
enum plane_id plane_id;
- int i, level;
- unsigned int dirty = 0;
-
- for_each_oldnew_intel_plane_in_state(state, plane,
- old_plane_state,
- new_plane_state, i) {
- if (new_plane_state->hw.crtc != &crtc->base &&
- old_plane_state->hw.crtc != &crtc->base)
- continue;
-
- if (g4x_raw_plane_wm_compute(crtc_state, new_plane_state))
- dirty |= BIT(plane->id);
- }
-
- if (!dirty)
- return 0;
+ int level;
level = G4X_WM_LEVEL_NORMAL;
if (!g4x_raw_crtc_wm_is_valid(crtc_state, level))
@@ -1417,6 +1384,34 @@ static int g4x_compute_pipe_wm(struct intel_atomic_state *state,
return 0;
}
+static int g4x_compute_pipe_wm(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+ struct intel_crtc_state *crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+ const struct intel_plane_state *old_plane_state;
+ const struct intel_plane_state *new_plane_state;
+ struct intel_plane *plane;
+ unsigned int dirty = 0;
+ int i;
+
+ for_each_oldnew_intel_plane_in_state(state, plane,
+ old_plane_state,
+ new_plane_state, i) {
+ if (new_plane_state->hw.crtc != &crtc->base &&
+ old_plane_state->hw.crtc != &crtc->base)
+ continue;
+
+ if (g4x_raw_plane_wm_compute(crtc_state, new_plane_state))
+ dirty |= BIT(plane->id);
+ }
+
+ if (!dirty)
+ return 0;
+
+ return _g4x_compute_pipe_wm(crtc_state);
+}
+
static int g4x_compute_intermediate_wm(struct intel_atomic_state *state,
struct intel_crtc *crtc)
{
@@ -1431,7 +1426,7 @@ static int g4x_compute_intermediate_wm(struct intel_atomic_state *state,
enum plane_id plane_id;
if (!new_crtc_state->hw.active ||
- drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi)) {
+ intel_crtc_needs_modeset(new_crtc_state)) {
*intermediate = *optimal;
intermediate->cxsr = false;
@@ -1857,64 +1852,17 @@ static bool vlv_raw_crtc_wm_is_valid(const struct intel_crtc_state *crtc_state,
vlv_raw_plane_wm_is_valid(crtc_state, PLANE_CURSOR, level);
}
-static int vlv_compute_pipe_wm(struct intel_atomic_state *state,
- struct intel_crtc *crtc)
+static int _vlv_compute_pipe_wm(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_state *crtc_state =
- intel_atomic_get_new_crtc_state(state, crtc);
struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal;
const struct vlv_fifo_state *fifo_state =
&crtc_state->wm.vlv.fifo_state;
u8 active_planes = crtc_state->active_planes & ~BIT(PLANE_CURSOR);
int num_active_planes = hweight8(active_planes);
- bool needs_modeset = drm_atomic_crtc_needs_modeset(&crtc_state->uapi);
- const struct intel_plane_state *old_plane_state;
- const struct intel_plane_state *new_plane_state;
- struct intel_plane *plane;
enum plane_id plane_id;
- int level, ret, i;
- unsigned int dirty = 0;
-
- for_each_oldnew_intel_plane_in_state(state, plane,
- old_plane_state,
- new_plane_state, i) {
- if (new_plane_state->hw.crtc != &crtc->base &&
- old_plane_state->hw.crtc != &crtc->base)
- continue;
-
- if (vlv_raw_plane_wm_compute(crtc_state, new_plane_state))
- dirty |= BIT(plane->id);
- }
-
- /*
- * DSPARB registers may have been reset due to the
- * power well being turned off. Make sure we restore
- * them to a consistent state even if no primary/sprite
- * planes are initially active.
- */
- if (needs_modeset)
- crtc_state->fifo_changed = true;
-
- if (!dirty)
- return 0;
-
- /* cursor changes don't warrant a FIFO recompute */
- if (dirty & ~BIT(PLANE_CURSOR)) {
- const struct intel_crtc_state *old_crtc_state =
- intel_atomic_get_old_crtc_state(state, crtc);
- const struct vlv_fifo_state *old_fifo_state =
- &old_crtc_state->wm.vlv.fifo_state;
-
- ret = vlv_compute_fifo(crtc_state);
- if (ret)
- return ret;
-
- if (needs_modeset ||
- memcmp(old_fifo_state, fifo_state,
- sizeof(*fifo_state)) != 0)
- crtc_state->fifo_changed = true;
- }
+ int level;
/* initially allow all levels */
wm_state->num_levels = intel_wm_num_levels(dev_priv);
@@ -1961,6 +1909,66 @@ static int vlv_compute_pipe_wm(struct intel_atomic_state *state,
return 0;
}
+static int vlv_compute_pipe_wm(struct intel_atomic_state *state,
+ struct intel_crtc *crtc)
+{
+ struct intel_crtc_state *crtc_state =
+ intel_atomic_get_new_crtc_state(state, crtc);
+ const struct intel_plane_state *old_plane_state;
+ const struct intel_plane_state *new_plane_state;
+ struct intel_plane *plane;
+ unsigned int dirty = 0;
+ int i;
+
+ for_each_oldnew_intel_plane_in_state(state, plane,
+ old_plane_state,
+ new_plane_state, i) {
+ if (new_plane_state->hw.crtc != &crtc->base &&
+ old_plane_state->hw.crtc != &crtc->base)
+ continue;
+
+ if (vlv_raw_plane_wm_compute(crtc_state, new_plane_state))
+ dirty |= BIT(plane->id);
+ }
+
+ /*
+ * DSPARB registers may have been reset due to the
+ * power well being turned off. Make sure we restore
+ * them to a consistent state even if no primary/sprite
+ * planes are initially active. We also force a FIFO
+ * recomputation so that we are sure to sanitize the
+ * FIFO setting we took over from the BIOS even if there
+ * are no active planes on the crtc.
+ */
+ if (intel_crtc_needs_modeset(crtc_state))
+ dirty = ~0;
+
+ if (!dirty)
+ return 0;
+
+ /* cursor changes don't warrant a FIFO recompute */
+ if (dirty & ~BIT(PLANE_CURSOR)) {
+ const struct intel_crtc_state *old_crtc_state =
+ intel_atomic_get_old_crtc_state(state, crtc);
+ const struct vlv_fifo_state *old_fifo_state =
+ &old_crtc_state->wm.vlv.fifo_state;
+ const struct vlv_fifo_state *new_fifo_state =
+ &crtc_state->wm.vlv.fifo_state;
+ int ret;
+
+ ret = vlv_compute_fifo(crtc_state);
+ if (ret)
+ return ret;
+
+ if (intel_crtc_needs_modeset(crtc_state) ||
+ memcmp(old_fifo_state, new_fifo_state,
+ sizeof(*new_fifo_state)) != 0)
+ crtc_state->fifo_changed = true;
+ }
+
+ return _vlv_compute_pipe_wm(crtc_state);
+}
+
#define VLV_FIFO(plane, value) \
(((value) << DSPARB_ ## plane ## _SHIFT_VLV) & DSPARB_ ## plane ## _MASK_VLV)
@@ -2075,7 +2083,7 @@ static int vlv_compute_intermediate_wm(struct intel_atomic_state *state,
int level;
if (!new_crtc_state->hw.active ||
- drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi)) {
+ intel_crtc_needs_modeset(new_crtc_state)) {
*intermediate = *optimal;
intermediate->cxsr = false;
@@ -3133,7 +3141,7 @@ static int ilk_compute_intermediate_wm(struct intel_atomic_state *state,
*/
*a = new_crtc_state->wm.ilk.optimal;
if (!new_crtc_state->hw.active ||
- drm_atomic_crtc_needs_modeset(&new_crtc_state->uapi) ||
+ intel_crtc_needs_modeset(new_crtc_state) ||
state->skip_intermediate_wm)
return 0;
@@ -3458,7 +3466,6 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
{
struct ilk_wm_values *previous = &dev_priv->display.wm.hw;
unsigned int dirty;
- u32 val;
dirty = ilk_compute_wm_dirty(dev_priv, previous, results);
if (!dirty)
@@ -3474,32 +3481,20 @@ static void ilk_write_wm_values(struct drm_i915_private *dev_priv,
intel_uncore_write(&dev_priv->uncore, WM0_PIPE_ILK(PIPE_C), results->wm_pipe[2]);
if (dirty & WM_DIRTY_DDB) {
- if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) {
- val = intel_uncore_read(&dev_priv->uncore, WM_MISC);
- if (results->partitioning == INTEL_DDB_PART_1_2)
- val &= ~WM_MISC_DATA_PARTITION_5_6;
- else
- val |= WM_MISC_DATA_PARTITION_5_6;
- intel_uncore_write(&dev_priv->uncore, WM_MISC, val);
- } else {
- val = intel_uncore_read(&dev_priv->uncore, DISP_ARB_CTL2);
- if (results->partitioning == INTEL_DDB_PART_1_2)
- val &= ~DISP_DATA_PARTITION_5_6;
- else
- val |= DISP_DATA_PARTITION_5_6;
- intel_uncore_write(&dev_priv->uncore, DISP_ARB_CTL2, val);
- }
- }
-
- if (dirty & WM_DIRTY_FBC) {
- val = intel_uncore_read(&dev_priv->uncore, DISP_ARB_CTL);
- if (results->enable_fbc_wm)
- val &= ~DISP_FBC_WM_DIS;
+ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
+ intel_uncore_rmw(&dev_priv->uncore, WM_MISC, WM_MISC_DATA_PARTITION_5_6,
+ results->partitioning == INTEL_DDB_PART_1_2 ? 0 :
+ WM_MISC_DATA_PARTITION_5_6);
else
- val |= DISP_FBC_WM_DIS;
- intel_uncore_write(&dev_priv->uncore, DISP_ARB_CTL, val);
+ intel_uncore_rmw(&dev_priv->uncore, DISP_ARB_CTL2, DISP_DATA_PARTITION_5_6,
+ results->partitioning == INTEL_DDB_PART_1_2 ? 0 :
+ DISP_DATA_PARTITION_5_6);
}
+ if (dirty & WM_DIRTY_FBC)
+ intel_uncore_rmw(&dev_priv->uncore, DISP_ARB_CTL, DISP_FBC_WM_DIS,
+ results->enable_fbc_wm ? 0 : DISP_FBC_WM_DIS);
+
if (dirty & WM_DIRTY_LP(1) &&
previous->wm_lp_spr[0] != results->wm_lp_spr[0])
intel_uncore_write(&dev_priv->uncore, WM1S_LP_ILK, results->wm_lp_spr[0]);
@@ -3824,6 +3819,8 @@ void g4x_wm_get_hw_state(struct drm_i915_private *dev_priv)
plane_id, USHRT_MAX);
g4x_raw_fbc_wm_set(crtc_state, level, USHRT_MAX);
+ g4x_invalidate_wms(crtc, active, level);
+
crtc_state->wm.g4x.optimal = *active;
crtc_state->wm.g4x.intermediate = *active;
@@ -3860,37 +3857,30 @@ void g4x_wm_sanitize(struct drm_i915_private *dev_priv)
to_intel_crtc_state(crtc->base.state);
struct intel_plane_state *plane_state =
to_intel_plane_state(plane->base.state);
- struct g4x_wm_state *wm_state = &crtc_state->wm.g4x.optimal;
enum plane_id plane_id = plane->id;
- int level;
+ int level, num_levels = intel_wm_num_levels(dev_priv);
if (plane_state->uapi.visible)
continue;
- for (level = 0; level < 3; level++) {
+ for (level = 0; level < num_levels; level++) {
struct g4x_pipe_wm *raw =
&crtc_state->wm.g4x.raw[level];
raw->plane[plane_id] = 0;
- wm_state->wm.plane[plane_id] = 0;
- }
- if (plane_id == PLANE_PRIMARY) {
- for (level = 0; level < 3; level++) {
- struct g4x_pipe_wm *raw =
- &crtc_state->wm.g4x.raw[level];
+ if (plane_id == PLANE_PRIMARY)
raw->fbc = 0;
- }
-
- wm_state->sr.fbc = 0;
- wm_state->hpll.fbc = 0;
- wm_state->fbc_en = false;
}
}
for_each_intel_crtc(&dev_priv->drm, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
+ int ret;
+
+ ret = _g4x_compute_pipe_wm(crtc_state);
+ drm_WARN_ON(&dev_priv->drm, ret);
crtc_state->wm.g4x.intermediate =
crtc_state->wm.g4x.optimal;
@@ -4016,30 +4006,27 @@ void vlv_wm_sanitize(struct drm_i915_private *dev_priv)
to_intel_crtc_state(crtc->base.state);
struct intel_plane_state *plane_state =
to_intel_plane_state(plane->base.state);
- struct vlv_wm_state *wm_state = &crtc_state->wm.vlv.optimal;
- const struct vlv_fifo_state *fifo_state =
- &crtc_state->wm.vlv.fifo_state;
enum plane_id plane_id = plane->id;
- int level;
+ int level, num_levels = intel_wm_num_levels(dev_priv);
if (plane_state->uapi.visible)
continue;
- for (level = 0; level < wm_state->num_levels; level++) {
+ for (level = 0; level < num_levels; level++) {
struct g4x_pipe_wm *raw =
&crtc_state->wm.vlv.raw[level];
raw->plane[plane_id] = 0;
-
- wm_state->wm[level].plane[plane_id] =
- vlv_invert_wm_value(raw->plane[plane_id],
- fifo_state->plane[plane_id]);
}
}
for_each_intel_crtc(&dev_priv->drm, crtc) {
struct intel_crtc_state *crtc_state =
to_intel_crtc_state(crtc->base.state);
+ int ret;
+
+ ret = _vlv_compute_pipe_wm(crtc_state);
+ drm_WARN_ON(&dev_priv->drm, ret);
crtc_state->wm.vlv.intermediate =
crtc_state->wm.vlv.optimal;
@@ -4057,9 +4044,9 @@ void vlv_wm_sanitize(struct drm_i915_private *dev_priv)
*/
static void ilk_init_lp_watermarks(struct drm_i915_private *dev_priv)
{
- intel_uncore_write(&dev_priv->uncore, WM3_LP_ILK, intel_uncore_read(&dev_priv->uncore, WM3_LP_ILK) & ~WM_LP_ENABLE);
- intel_uncore_write(&dev_priv->uncore, WM2_LP_ILK, intel_uncore_read(&dev_priv->uncore, WM2_LP_ILK) & ~WM_LP_ENABLE);
- intel_uncore_write(&dev_priv->uncore, WM1_LP_ILK, intel_uncore_read(&dev_priv->uncore, WM1_LP_ILK) & ~WM_LP_ENABLE);
+ intel_uncore_rmw(&dev_priv->uncore, WM3_LP_ILK, WM_LP_ENABLE, 0);
+ intel_uncore_rmw(&dev_priv->uncore, WM2_LP_ILK, WM_LP_ENABLE, 0);
+ intel_uncore_rmw(&dev_priv->uncore, WM1_LP_ILK, WM_LP_ENABLE, 0);
/*
* Don't touch WM_LP_SPRITE_ENABLE here.
@@ -4113,11 +4100,9 @@ static void g4x_disable_trickle_feed(struct drm_i915_private *dev_priv)
enum pipe pipe;
for_each_pipe(dev_priv, pipe) {
- intel_uncore_write(&dev_priv->uncore, DSPCNTR(pipe),
- intel_uncore_read(&dev_priv->uncore, DSPCNTR(pipe)) |
- DISP_TRICKLE_FEED_DISABLE);
+ intel_uncore_rmw(&dev_priv->uncore, DSPCNTR(pipe), 0, DISP_TRICKLE_FEED_DISABLE);
- intel_uncore_write(&dev_priv->uncore, DSPSURF(pipe), intel_uncore_read(&dev_priv->uncore, DSPSURF(pipe)));
+ intel_uncore_rmw(&dev_priv->uncore, DSPSURF(pipe), 0, 0);
intel_uncore_posting_read(&dev_priv->uncore, DSPSURF(pipe));
}
}
@@ -4164,19 +4149,13 @@ static void ilk_init_clock_gating(struct drm_i915_private *dev_priv)
*/
if (IS_IRONLAKE_M(dev_priv)) {
/* WaFbcAsynchFlipDisableFbcQueue:ilk */
- intel_uncore_write(&dev_priv->uncore, ILK_DISPLAY_CHICKEN1,
- intel_uncore_read(&dev_priv->uncore, ILK_DISPLAY_CHICKEN1) |
- ILK_FBCQ_DIS);
- intel_uncore_write(&dev_priv->uncore, ILK_DISPLAY_CHICKEN2,
- intel_uncore_read(&dev_priv->uncore, ILK_DISPLAY_CHICKEN2) |
- ILK_DPARB_GATE);
+ intel_uncore_rmw(&dev_priv->uncore, ILK_DISPLAY_CHICKEN1, 0, ILK_FBCQ_DIS);
+ intel_uncore_rmw(&dev_priv->uncore, ILK_DISPLAY_CHICKEN2, 0, ILK_DPARB_GATE);
}
intel_uncore_write(&dev_priv->uncore, ILK_DSPCLK_GATE_D, dspclk_gate);
- intel_uncore_write(&dev_priv->uncore, ILK_DISPLAY_CHICKEN2,
- intel_uncore_read(&dev_priv->uncore, ILK_DISPLAY_CHICKEN2) |
- ILK_ELPIN_409_SELECT);
+ intel_uncore_rmw(&dev_priv->uncore, ILK_DISPLAY_CHICKEN2, 0, ILK_ELPIN_409_SELECT);
g4x_disable_trickle_feed(dev_priv);
@@ -4196,8 +4175,7 @@ static void cpt_init_clock_gating(struct drm_i915_private *dev_priv)
intel_uncore_write(&dev_priv->uncore, SOUTH_DSPCLK_GATE_D, PCH_DPLSUNIT_CLOCK_GATE_DISABLE |
PCH_DPLUNIT_CLOCK_GATE_DISABLE |
PCH_CPUNIT_CLOCK_GATE_DISABLE);
- intel_uncore_write(&dev_priv->uncore, SOUTH_CHICKEN2, intel_uncore_read(&dev_priv->uncore, SOUTH_CHICKEN2) |
- DPLS_EDP_PPS_FIX_DIS);
+ intel_uncore_rmw(&dev_priv->uncore, SOUTH_CHICKEN2, 0, DPLS_EDP_PPS_FIX_DIS);
/* The below fixes the weird display corruption, a few pixels shifted
* downward, on (only) LVDS of some HP laptops with IVY.
*/
@@ -4235,9 +4213,7 @@ static void gen6_init_clock_gating(struct drm_i915_private *dev_priv)
intel_uncore_write(&dev_priv->uncore, ILK_DSPCLK_GATE_D, dspclk_gate);
- intel_uncore_write(&dev_priv->uncore, ILK_DISPLAY_CHICKEN2,
- intel_uncore_read(&dev_priv->uncore, ILK_DISPLAY_CHICKEN2) |
- ILK_ELPIN_409_SELECT);
+ intel_uncore_rmw(&dev_priv->uncore, ILK_DISPLAY_CHICKEN2, 0, ILK_ELPIN_409_SELECT);
intel_uncore_write(&dev_priv->uncore, GEN6_UCGCTL1,
intel_uncore_read(&dev_priv->uncore, GEN6_UCGCTL1) |
@@ -4297,14 +4273,12 @@ static void lpt_init_clock_gating(struct drm_i915_private *dev_priv)
* disabled when not needed anymore in order to save power.
*/
if (HAS_PCH_LPT_LP(dev_priv))
- intel_uncore_write(&dev_priv->uncore, SOUTH_DSPCLK_GATE_D,
- intel_uncore_read(&dev_priv->uncore, SOUTH_DSPCLK_GATE_D) |
- PCH_LP_PARTITION_LEVEL_DISABLE);
+ intel_uncore_rmw(&dev_priv->uncore, SOUTH_DSPCLK_GATE_D,
+ 0, PCH_LP_PARTITION_LEVEL_DISABLE);
/* WADPOClockGatingDisable:hsw */
- intel_uncore_write(&dev_priv->uncore, TRANS_CHICKEN1(PIPE_A),
- intel_uncore_read(&dev_priv->uncore, TRANS_CHICKEN1(PIPE_A)) |
- TRANS_CHICKEN1_DP0UNIT_GC_DISABLE);
+ intel_uncore_rmw(&dev_priv->uncore, TRANS_CHICKEN1(PIPE_A),
+ 0, TRANS_CHICKEN1_DP0UNIT_GC_DISABLE);
}
static void lpt_suspend_hw(struct drm_i915_private *dev_priv)
@@ -4325,22 +4299,22 @@ static void gen8_set_l3sqc_credits(struct drm_i915_private *dev_priv,
u32 val;
/* WaTempDisableDOPClkGating:bdw */
- misccpctl = intel_uncore_read(&dev_priv->uncore, GEN7_MISCCPCTL);
- intel_uncore_write(&dev_priv->uncore, GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE);
+ misccpctl = intel_gt_mcr_multicast_rmw(to_gt(dev_priv), GEN8_MISCCPCTL,
+ GEN8_DOP_CLOCK_GATE_ENABLE, 0);
- val = intel_uncore_read(&dev_priv->uncore, GEN8_L3SQCREG1);
+ val = intel_gt_mcr_read_any(to_gt(dev_priv), GEN8_L3SQCREG1);
val &= ~L3_PRIO_CREDITS_MASK;
val |= L3_GENERAL_PRIO_CREDITS(general_prio_credits);
val |= L3_HIGH_PRIO_CREDITS(high_prio_credits);
- intel_uncore_write(&dev_priv->uncore, GEN8_L3SQCREG1, val);
+ intel_gt_mcr_multicast_write(to_gt(dev_priv), GEN8_L3SQCREG1, val);
/*
* Wait at least 100 clocks before re-enabling clock gating.
* See the definition of L3SQCREG1 in BSpec.
*/
- intel_uncore_posting_read(&dev_priv->uncore, GEN8_L3SQCREG1);
+ intel_gt_mcr_read_any(to_gt(dev_priv), GEN8_L3SQCREG1);
udelay(1);
- intel_uncore_write(&dev_priv->uncore, GEN7_MISCCPCTL, misccpctl);
+ intel_gt_mcr_multicast_write(to_gt(dev_priv), GEN8_MISCCPCTL, misccpctl);
}
static void icl_init_clock_gating(struct drm_i915_private *dev_priv)
@@ -4363,8 +4337,7 @@ static void gen12lp_init_clock_gating(struct drm_i915_private *dev_priv)
/* Wa_1409825376:tgl (pre-prod)*/
if (IS_TGL_DISPLAY_STEP(dev_priv, STEP_A0, STEP_C0))
- intel_uncore_write(&dev_priv->uncore, GEN9_CLKGATE_DIS_3, intel_uncore_read(&dev_priv->uncore, GEN9_CLKGATE_DIS_3) |
- TGL_VRH_GATING_DIS);
+ intel_uncore_rmw(&dev_priv->uncore, GEN9_CLKGATE_DIS_3, 0, TGL_VRH_GATING_DIS);
/* Wa_14013723622:tgl,rkl,dg1,adl-s */
if (DISPLAY_VER(dev_priv) == 12)
@@ -4389,8 +4362,7 @@ static void dg1_init_clock_gating(struct drm_i915_private *dev_priv)
/* Wa_1409836686:dg1[a0] */
if (IS_DG1_GRAPHICS_STEP(dev_priv, STEP_A0, STEP_B0))
- intel_uncore_write(&dev_priv->uncore, GEN9_CLKGATE_DIS_3, intel_uncore_read(&dev_priv->uncore, GEN9_CLKGATE_DIS_3) |
- DPT_GATING_DIS);
+ intel_uncore_rmw(&dev_priv->uncore, GEN9_CLKGATE_DIS_3, 0, DPT_GATING_DIS);
}
static void xehpsdv_init_clock_gating(struct drm_i915_private *dev_priv)
@@ -4432,8 +4404,7 @@ static void cnp_init_clock_gating(struct drm_i915_private *dev_priv)
return;
/* Display WA #1181 WaSouthDisplayDisablePWMCGEGating: cnp */
- intel_uncore_write(&dev_priv->uncore, SOUTH_DSPCLK_GATE_D, intel_uncore_read(&dev_priv->uncore, SOUTH_DSPCLK_GATE_D) |
- CNP_PWM_CGE_GATING_DISABLE);
+ intel_uncore_rmw(&dev_priv->uncore, SOUTH_DSPCLK_GATE_D, 0, CNP_PWM_CGE_GATING_DISABLE);
}
static void cfl_init_clock_gating(struct drm_i915_private *dev_priv)
@@ -4442,23 +4413,20 @@ static void cfl_init_clock_gating(struct drm_i915_private *dev_priv)
gen9_init_clock_gating(dev_priv);
/* WAC6entrylatency:cfl */
- intel_uncore_write(&dev_priv->uncore, FBC_LLC_READ_CTRL, intel_uncore_read(&dev_priv->uncore, FBC_LLC_READ_CTRL) |
- FBC_LLC_FULLY_OPEN);
+ intel_uncore_rmw(&dev_priv->uncore, FBC_LLC_READ_CTRL, 0, FBC_LLC_FULLY_OPEN);
/*
* WaFbcTurnOffFbcWatermark:cfl
* Display WA #0562: cfl
*/
- intel_uncore_write(&dev_priv->uncore, DISP_ARB_CTL, intel_uncore_read(&dev_priv->uncore, DISP_ARB_CTL) |
- DISP_FBC_WM_DIS);
+ intel_uncore_rmw(&dev_priv->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS);
/*
* WaFbcNukeOnHostModify:cfl
* Display WA #0873: cfl
*/
- intel_uncore_write(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A),
- intel_uncore_read(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A)) |
- DPFC_NUKE_ON_ANY_MODIFICATION);
+ intel_uncore_rmw(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A),
+ 0, DPFC_NUKE_ON_ANY_MODIFICATION);
}
static void kbl_init_clock_gating(struct drm_i915_private *dev_priv)
@@ -4466,33 +4434,30 @@ static void kbl_init_clock_gating(struct drm_i915_private *dev_priv)
gen9_init_clock_gating(dev_priv);
/* WAC6entrylatency:kbl */
- intel_uncore_write(&dev_priv->uncore, FBC_LLC_READ_CTRL, intel_uncore_read(&dev_priv->uncore, FBC_LLC_READ_CTRL) |
- FBC_LLC_FULLY_OPEN);
+ intel_uncore_rmw(&dev_priv->uncore, FBC_LLC_READ_CTRL, 0, FBC_LLC_FULLY_OPEN);
/* WaDisableSDEUnitClockGating:kbl */
if (IS_KBL_GRAPHICS_STEP(dev_priv, 0, STEP_C0))
- intel_uncore_write(&dev_priv->uncore, GEN8_UCGCTL6, intel_uncore_read(&dev_priv->uncore, GEN8_UCGCTL6) |
- GEN8_SDEUNIT_CLOCK_GATE_DISABLE);
+ intel_uncore_rmw(&dev_priv->uncore, GEN8_UCGCTL6,
+ 0, GEN8_SDEUNIT_CLOCK_GATE_DISABLE);
/* WaDisableGamClockGating:kbl */
if (IS_KBL_GRAPHICS_STEP(dev_priv, 0, STEP_C0))
- intel_uncore_write(&dev_priv->uncore, GEN6_UCGCTL1, intel_uncore_read(&dev_priv->uncore, GEN6_UCGCTL1) |
- GEN6_GAMUNIT_CLOCK_GATE_DISABLE);
+ intel_uncore_rmw(&dev_priv->uncore, GEN6_UCGCTL1,
+ 0, GEN6_GAMUNIT_CLOCK_GATE_DISABLE);
/*
* WaFbcTurnOffFbcWatermark:kbl
* Display WA #0562: kbl
*/
- intel_uncore_write(&dev_priv->uncore, DISP_ARB_CTL, intel_uncore_read(&dev_priv->uncore, DISP_ARB_CTL) |
- DISP_FBC_WM_DIS);
+ intel_uncore_rmw(&dev_priv->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS);
/*
* WaFbcNukeOnHostModify:kbl
* Display WA #0873: kbl
*/
- intel_uncore_write(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A),
- intel_uncore_read(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A)) |
- DPFC_NUKE_ON_ANY_MODIFICATION);
+ intel_uncore_rmw(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A),
+ 0, DPFC_NUKE_ON_ANY_MODIFICATION);
}
static void skl_init_clock_gating(struct drm_i915_private *dev_priv)
@@ -4500,35 +4465,30 @@ static void skl_init_clock_gating(struct drm_i915_private *dev_priv)
gen9_init_clock_gating(dev_priv);
/* WaDisableDopClockGating:skl */
- intel_uncore_write(&dev_priv->uncore, GEN7_MISCCPCTL, intel_uncore_read(&dev_priv->uncore, GEN7_MISCCPCTL) &
- ~GEN7_DOP_CLOCK_GATE_ENABLE);
+ intel_gt_mcr_multicast_rmw(to_gt(dev_priv), GEN8_MISCCPCTL,
+ GEN8_DOP_CLOCK_GATE_ENABLE, 0);
/* WAC6entrylatency:skl */
- intel_uncore_write(&dev_priv->uncore, FBC_LLC_READ_CTRL, intel_uncore_read(&dev_priv->uncore, FBC_LLC_READ_CTRL) |
- FBC_LLC_FULLY_OPEN);
+ intel_uncore_rmw(&dev_priv->uncore, FBC_LLC_READ_CTRL, 0, FBC_LLC_FULLY_OPEN);
/*
* WaFbcTurnOffFbcWatermark:skl
* Display WA #0562: skl
*/
- intel_uncore_write(&dev_priv->uncore, DISP_ARB_CTL, intel_uncore_read(&dev_priv->uncore, DISP_ARB_CTL) |
- DISP_FBC_WM_DIS);
+ intel_uncore_rmw(&dev_priv->uncore, DISP_ARB_CTL, 0, DISP_FBC_WM_DIS);
/*
* WaFbcNukeOnHostModify:skl
* Display WA #0873: skl
*/
- intel_uncore_write(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A),
- intel_uncore_read(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A)) |
- DPFC_NUKE_ON_ANY_MODIFICATION);
+ intel_uncore_rmw(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A),
+ 0, DPFC_NUKE_ON_ANY_MODIFICATION);
/*
* WaFbcHighMemBwCorruptionAvoidance:skl
* Display WA #0883: skl
*/
- intel_uncore_write(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A),
- intel_uncore_read(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A)) |
- DPFC_DISABLE_DUMMY0);
+ intel_uncore_rmw(&dev_priv->uncore, ILK_DPFC_CHICKEN(INTEL_FBC_A), 0, DPFC_DISABLE_DUMMY0);
}
static void bdw_init_clock_gating(struct drm_i915_private *dev_priv)
@@ -4536,43 +4496,37 @@ static void bdw_init_clock_gating(struct drm_i915_private *dev_priv)
enum pipe pipe;
/* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */
- intel_uncore_write(&dev_priv->uncore, CHICKEN_PIPESL_1(PIPE_A),
- intel_uncore_read(&dev_priv->uncore, CHICKEN_PIPESL_1(PIPE_A)) |
- HSW_FBCQ_DIS);
+ intel_uncore_rmw(&dev_priv->uncore, CHICKEN_PIPESL_1(PIPE_A), 0, HSW_FBCQ_DIS);
/* WaSwitchSolVfFArbitrationPriority:bdw */
- intel_uncore_write(&dev_priv->uncore, GAM_ECOCHK, intel_uncore_read(&dev_priv->uncore, GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL);
+ intel_uncore_rmw(&dev_priv->uncore, GAM_ECOCHK, 0, HSW_ECOCHK_ARB_PRIO_SOL);
/* WaPsrDPAMaskVBlankInSRD:bdw */
- intel_uncore_write(&dev_priv->uncore, CHICKEN_PAR1_1,
- intel_uncore_read(&dev_priv->uncore, CHICKEN_PAR1_1) | DPA_MASK_VBLANK_SRD);
+ intel_uncore_rmw(&dev_priv->uncore, CHICKEN_PAR1_1, 0, DPA_MASK_VBLANK_SRD);
for_each_pipe(dev_priv, pipe) {
/* WaPsrDPRSUnmaskVBlankInSRD:bdw */
- intel_uncore_write(&dev_priv->uncore, CHICKEN_PIPESL_1(pipe),
- intel_uncore_read(&dev_priv->uncore, CHICKEN_PIPESL_1(pipe)) |
- BDW_DPRS_MASK_VBLANK_SRD);
+ intel_uncore_rmw(&dev_priv->uncore, CHICKEN_PIPESL_1(pipe),
+ 0, BDW_DPRS_MASK_VBLANK_SRD);
}
/* WaVSRefCountFullforceMissDisable:bdw */
/* WaDSRefCountFullforceMissDisable:bdw */
- intel_uncore_write(&dev_priv->uncore, GEN7_FF_THREAD_MODE,
- intel_uncore_read(&dev_priv->uncore, GEN7_FF_THREAD_MODE) &
- ~(GEN8_FF_DS_REF_CNT_FFME | GEN7_FF_VS_REF_CNT_FFME));
+ intel_uncore_rmw(&dev_priv->uncore, GEN7_FF_THREAD_MODE,
+ GEN8_FF_DS_REF_CNT_FFME | GEN7_FF_VS_REF_CNT_FFME, 0);
intel_uncore_write(&dev_priv->uncore, RING_PSMI_CTL(RENDER_RING_BASE),
_MASKED_BIT_ENABLE(GEN8_RC_SEMA_IDLE_MSG_DISABLE));
/* WaDisableSDEUnitClockGating:bdw */
- intel_uncore_write(&dev_priv->uncore, GEN8_UCGCTL6, intel_uncore_read(&dev_priv->uncore, GEN8_UCGCTL6) |
- GEN8_SDEUNIT_CLOCK_GATE_DISABLE);
+ intel_uncore_rmw(&dev_priv->uncore, GEN8_UCGCTL6, 0, GEN8_SDEUNIT_CLOCK_GATE_DISABLE);
/* WaProgramL3SqcReg1Default:bdw */
gen8_set_l3sqc_credits(dev_priv, 30, 2);
/* WaKVMNotificationOnConfigChange:bdw */
- intel_uncore_write(&dev_priv->uncore, CHICKEN_PAR2_1, intel_uncore_read(&dev_priv->uncore, CHICKEN_PAR2_1)
- | KVM_CONFIG_CHANGE_NOTIFICATION_SELECT);
+ intel_uncore_rmw(&dev_priv->uncore, CHICKEN_PAR2_1,
+ 0, KVM_CONFIG_CHANGE_NOTIFICATION_SELECT);
lpt_init_clock_gating(dev_priv);
@@ -4581,38 +4535,30 @@ static void bdw_init_clock_gating(struct drm_i915_private *dev_priv)
* Also see the CHICKEN2 write in bdw_init_workarounds() to disable DOP
* clock gating.
*/
- intel_uncore_write(&dev_priv->uncore, GEN6_UCGCTL1,
- intel_uncore_read(&dev_priv->uncore, GEN6_UCGCTL1) | GEN6_EU_TCUNIT_CLOCK_GATE_DISABLE);
+ intel_uncore_rmw(&dev_priv->uncore, GEN6_UCGCTL1, 0, GEN6_EU_TCUNIT_CLOCK_GATE_DISABLE);
}
static void hsw_init_clock_gating(struct drm_i915_private *dev_priv)
{
/* WaFbcAsynchFlipDisableFbcQueue:hsw,bdw */
- intel_uncore_write(&dev_priv->uncore, CHICKEN_PIPESL_1(PIPE_A),
- intel_uncore_read(&dev_priv->uncore, CHICKEN_PIPESL_1(PIPE_A)) |
- HSW_FBCQ_DIS);
+ intel_uncore_rmw(&dev_priv->uncore, CHICKEN_PIPESL_1(PIPE_A), 0, HSW_FBCQ_DIS);
/* This is required by WaCatErrorRejectionIssue:hsw */
- intel_uncore_write(&dev_priv->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
- intel_uncore_read(&dev_priv->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
- GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
+ intel_uncore_rmw(&dev_priv->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
+ 0, GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
/* WaSwitchSolVfFArbitrationPriority:hsw */
- intel_uncore_write(&dev_priv->uncore, GAM_ECOCHK, intel_uncore_read(&dev_priv->uncore, GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL);
+ intel_uncore_rmw(&dev_priv->uncore, GAM_ECOCHK, 0, HSW_ECOCHK_ARB_PRIO_SOL);
lpt_init_clock_gating(dev_priv);
}
static void ivb_init_clock_gating(struct drm_i915_private *dev_priv)
{
- u32 snpcr;
-
intel_uncore_write(&dev_priv->uncore, ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE);
/* WaFbcAsynchFlipDisableFbcQueue:ivb */
- intel_uncore_write(&dev_priv->uncore, ILK_DISPLAY_CHICKEN1,
- intel_uncore_read(&dev_priv->uncore, ILK_DISPLAY_CHICKEN1) |
- ILK_FBCQ_DIS);
+ intel_uncore_rmw(&dev_priv->uncore, ILK_DISPLAY_CHICKEN1, 0, ILK_FBCQ_DIS);
/* WaDisableBackToBackFlipFix:ivb */
intel_uncore_write(&dev_priv->uncore, IVB_CHICKEN3,
@@ -4638,16 +4584,13 @@ static void ivb_init_clock_gating(struct drm_i915_private *dev_priv)
GEN6_RCZUNIT_CLOCK_GATE_DISABLE);
/* This is required by WaCatErrorRejectionIssue:ivb */
- intel_uncore_write(&dev_priv->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
- intel_uncore_read(&dev_priv->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
- GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
+ intel_uncore_rmw(&dev_priv->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
+ 0, GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
g4x_disable_trickle_feed(dev_priv);
- snpcr = intel_uncore_read(&dev_priv->uncore, GEN6_MBCUNIT_SNPCR);
- snpcr &= ~GEN6_MBC_SNPCR_MASK;
- snpcr |= GEN6_MBC_SNPCR_MED;
- intel_uncore_write(&dev_priv->uncore, GEN6_MBCUNIT_SNPCR, snpcr);
+ intel_uncore_rmw(&dev_priv->uncore, GEN6_MBCUNIT_SNPCR, GEN6_MBC_SNPCR_MASK,
+ GEN6_MBC_SNPCR_MED);
if (!HAS_PCH_NOP(dev_priv))
cpt_init_clock_gating(dev_priv);
@@ -4667,9 +4610,8 @@ static void vlv_init_clock_gating(struct drm_i915_private *dev_priv)
_MASKED_BIT_ENABLE(DOP_CLOCK_GATING_DISABLE));
/* This is required by WaCatErrorRejectionIssue:vlv */
- intel_uncore_write(&dev_priv->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
- intel_uncore_read(&dev_priv->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG) |
- GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
+ intel_uncore_rmw(&dev_priv->uncore, GEN7_SQ_CHICKEN_MBCUNIT_CONFIG,
+ 0, GEN7_SQ_CHICKEN_MBCUNIT_SQINTMOB);
/*
* According to the spec, bit 13 (RCZUNIT) must be set on IVB.
@@ -4681,8 +4623,7 @@ static void vlv_init_clock_gating(struct drm_i915_private *dev_priv)
/* WaDisableL3Bank2xClockGate:vlv
* Disabling L3 clock gating- MMIO 940c[25] = 1
* Set bit 25, to disable L3_BANK_2x_CLK_GATING */
- intel_uncore_write(&dev_priv->uncore, GEN7_UCGCTL4,
- intel_uncore_read(&dev_priv->uncore, GEN7_UCGCTL4) | GEN7_L3BANK2X_CLOCK_GATE_DISABLE);
+ intel_uncore_rmw(&dev_priv->uncore, GEN7_UCGCTL4, 0, GEN7_L3BANK2X_CLOCK_GATE_DISABLE);
/*
* WaDisableVLVClockGating_VBIIssue:vlv
@@ -4696,21 +4637,18 @@ static void chv_init_clock_gating(struct drm_i915_private *dev_priv)
{
/* WaVSRefCountFullforceMissDisable:chv */
/* WaDSRefCountFullforceMissDisable:chv */
- intel_uncore_write(&dev_priv->uncore, GEN7_FF_THREAD_MODE,
- intel_uncore_read(&dev_priv->uncore, GEN7_FF_THREAD_MODE) &
- ~(GEN8_FF_DS_REF_CNT_FFME | GEN7_FF_VS_REF_CNT_FFME));
+ intel_uncore_rmw(&dev_priv->uncore, GEN7_FF_THREAD_MODE,
+ GEN8_FF_DS_REF_CNT_FFME | GEN7_FF_VS_REF_CNT_FFME, 0);
/* WaDisableSemaphoreAndSyncFlipWait:chv */
intel_uncore_write(&dev_priv->uncore, RING_PSMI_CTL(RENDER_RING_BASE),
_MASKED_BIT_ENABLE(GEN8_RC_SEMA_IDLE_MSG_DISABLE));
/* WaDisableCSUnitClockGating:chv */
- intel_uncore_write(&dev_priv->uncore, GEN6_UCGCTL1, intel_uncore_read(&dev_priv->uncore, GEN6_UCGCTL1) |
- GEN6_CSUNIT_CLOCK_GATE_DISABLE);
+ intel_uncore_rmw(&dev_priv->uncore, GEN6_UCGCTL1, 0, GEN6_CSUNIT_CLOCK_GATE_DISABLE);
/* WaDisableSDEUnitClockGating:chv */
- intel_uncore_write(&dev_priv->uncore, GEN8_UCGCTL6, intel_uncore_read(&dev_priv->uncore, GEN8_UCGCTL6) |
- GEN8_SDEUNIT_CLOCK_GATE_DISABLE);
+ intel_uncore_rmw(&dev_priv->uncore, GEN8_UCGCTL6, 0, GEN8_SDEUNIT_CLOCK_GATE_DISABLE);
/*
* WaProgramL3SqcReg1Default:chv
diff --git a/drivers/gpu/drm/i915/intel_region_ttm.c b/drivers/gpu/drm/i915/intel_region_ttm.c
index 575d67bc6ffe..cf89d0c2a2d9 100644
--- a/drivers/gpu/drm/i915/intel_region_ttm.c
+++ b/drivers/gpu/drm/i915/intel_region_ttm.c
@@ -244,7 +244,7 @@ void intel_region_ttm_resource_free(struct intel_memory_region *mem,
struct ttm_resource_manager *man = mem->region_private;
struct ttm_buffer_object mock_bo = {};
- mock_bo.base.size = res->num_pages << PAGE_SHIFT;
+ mock_bo.base.size = res->size;
mock_bo.bdev = &mem->i915->bdev;
res->bo = &mock_bo;
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c
index 744cca507946..129746713d07 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.c
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.c
@@ -633,6 +633,8 @@ void intel_runtime_pm_driver_release(struct intel_runtime_pm *rpm)
runtime_pm);
int count = atomic_read(&rpm->wakeref_count);
+ intel_wakeref_auto_fini(&rpm->userfault_wakeref);
+
drm_WARN(&i915->drm, count,
"i915 raw-wakerefs=%d wakelocks=%d on cleanup\n",
intel_rpm_raw_wakeref_count(count),
@@ -652,4 +654,7 @@ void intel_runtime_pm_init_early(struct intel_runtime_pm *rpm)
rpm->available = HAS_RUNTIME_PM(i915);
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);
}
diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.h b/drivers/gpu/drm/i915/intel_runtime_pm.h
index d9160e3ff4af..98b8b28baaa1 100644
--- a/drivers/gpu/drm/i915/intel_runtime_pm.h
+++ b/drivers/gpu/drm/i915/intel_runtime_pm.h
@@ -53,6 +53,28 @@ struct intel_runtime_pm {
bool irqs_enabled;
bool no_wakeref_tracking;
+ /*
+ * Protects access to lmem usefault list.
+ * It is required, if we are outside of the runtime suspend path,
+ * access to @lmem_userfault_list requires always first grabbing the
+ * runtime pm, to ensure we can't race against runtime suspend.
+ * Once we have that we also need to grab @lmem_userfault_lock,
+ * at which point we have exclusive access.
+ * The runtime suspend path is special since it doesn't really hold any locks,
+ * but instead has exclusive access by virtue of all other accesses requiring
+ * holding the runtime pm wakeref.
+ */
+ spinlock_t lmem_userfault_lock;
+
+ /*
+ * Keep list of userfaulted gem obj, which require to release their
+ * mmap mappings at runtime suspend path.
+ */
+ struct list_head lmem_userfault_list;
+
+ /* Manual runtime pm autosuspend delay for user GGTT/lmem mmaps */
+ struct intel_wakeref_auto userfault_wakeref;
+
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
/*
* To aide detection of wakeref leaks and general misuse, we
diff --git a/drivers/gpu/drm/i915/intel_step.c b/drivers/gpu/drm/i915/intel_step.c
index 42b3133d8387..84a6fe736a3b 100644
--- a/drivers/gpu/drm/i915/intel_step.c
+++ b/drivers/gpu/drm/i915/intel_step.c
@@ -131,10 +131,27 @@ static const struct intel_step_info adls_rpls_revids[] = {
[0xC] = { COMMON_GT_MEDIA_STEP(D0), .display_step = STEP_C0 },
};
+static const struct intel_step_info adlp_rplp_revids[] = {
+ [0x4] = { COMMON_GT_MEDIA_STEP(C0), .display_step = STEP_E0 },
+};
+
static const struct intel_step_info adlp_n_revids[] = {
[0x0] = { COMMON_GT_MEDIA_STEP(A0), .display_step = STEP_D0 },
};
+static u8 gmd_to_intel_step(struct drm_i915_private *i915,
+ struct intel_ip_version *gmd)
+{
+ u8 step = gmd->step + STEP_A0;
+
+ if (step >= STEP_FUTURE) {
+ drm_dbg(&i915->drm, "Using future steppings\n");
+ return STEP_FUTURE;
+ }
+
+ return step;
+}
+
static void pvc_step_init(struct drm_i915_private *i915, int pci_revid);
void intel_step_init(struct drm_i915_private *i915)
@@ -144,6 +161,18 @@ void intel_step_init(struct drm_i915_private *i915)
int revid = INTEL_REVID(i915);
struct intel_step_info step = {};
+ if (HAS_GMD_ID(i915)) {
+ step.graphics_step = gmd_to_intel_step(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);
+ RUNTIME_INFO(i915)->step = step;
+
+ return;
+ }
+
if (IS_PONTEVECCHIO(i915)) {
pvc_step_init(i915, revid);
return;
@@ -162,6 +191,9 @@ void intel_step_init(struct drm_i915_private *i915)
} else if (IS_ADLP_N(i915)) {
revids = adlp_n_revids;
size = ARRAY_SIZE(adlp_n_revids);
+ } else if (IS_ADLP_RPLP(i915)) {
+ revids = adlp_rplp_revids;
+ size = ARRAY_SIZE(adlp_rplp_revids);
} else if (IS_ALDERLAKE_P(i915)) {
revids = adlp_revids;
size = ARRAY_SIZE(adlp_revids);
diff --git a/drivers/gpu/drm/i915/intel_step.h b/drivers/gpu/drm/i915/intel_step.h
index a6b12bfa9744..96dfca4cba73 100644
--- a/drivers/gpu/drm/i915/intel_step.h
+++ b/drivers/gpu/drm/i915/intel_step.h
@@ -11,6 +11,10 @@
struct drm_i915_private;
struct intel_step_info {
+ /*
+ * It is expected to have 4 number steps per letter. Deviation from
+ * the expectation breaks gmd_to_intel_step().
+ */
u8 graphics_step; /* Represents the compute tile on Xe_HPC */
u8 display_step;
u8 media_step;
@@ -23,21 +27,43 @@ struct intel_step_info {
func(A0) \
func(A1) \
func(A2) \
+ func(A3) \
func(B0) \
func(B1) \
func(B2) \
func(B3) \
func(C0) \
func(C1) \
+ func(C2) \
+ func(C3) \
func(D0) \
func(D1) \
+ func(D2) \
+ func(D3) \
func(E0) \
+ func(E1) \
+ func(E2) \
+ func(E3) \
func(F0) \
+ func(F1) \
+ func(F2) \
+ func(F3) \
func(G0) \
+ func(G1) \
+ func(G2) \
+ func(G3) \
func(H0) \
+ func(H1) \
+ func(H2) \
+ func(H3) \
func(I0) \
func(I1) \
- func(J0)
+ func(I2) \
+ func(I3) \
+ func(J0) \
+ func(J1) \
+ func(J2) \
+ func(J3)
/*
* Symbolic steppings that do not match the hardware. These are valid both as gt
diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c
index 5cd423c7b646..8006a6c61466 100644
--- a/drivers/gpu/drm/i915/intel_uncore.c
+++ b/drivers/gpu/drm/i915/intel_uncore.c
@@ -29,6 +29,7 @@
#include "i915_drv.h"
#include "i915_iosf_mbi.h"
+#include "i915_reg.h"
#include "i915_trace.h"
#include "i915_vgpu.h"
#include "intel_pm.h"
@@ -104,6 +105,7 @@ static const char * const forcewake_domain_names[] = {
"vebox1",
"vebox2",
"vebox3",
+ "gsc",
};
const char *
@@ -177,8 +179,9 @@ static inline void
fw_domain_wait_ack_clear(const struct intel_uncore_forcewake_domain *d)
{
if (wait_ack_clear(d, FORCEWAKE_KERNEL)) {
- DRM_ERROR("%s: timed out waiting for forcewake ack to clear.\n",
- intel_uncore_forcewake_domain_to_str(d->id));
+ drm_err(&d->uncore->i915->drm,
+ "%s: timed out waiting for forcewake ack to clear.\n",
+ intel_uncore_forcewake_domain_to_str(d->id));
add_taint_for_CI(d->uncore->i915, TAINT_WARN); /* CI now unreliable */
}
}
@@ -225,11 +228,12 @@ fw_domain_wait_ack_with_fallback(const struct intel_uncore_forcewake_domain *d,
fw_clear(d, FORCEWAKE_KERNEL_FALLBACK);
} while (!ack_detected && pass++ < 10);
- DRM_DEBUG_DRIVER("%s had to use fallback to %s ack, 0x%x (passes %u)\n",
- intel_uncore_forcewake_domain_to_str(d->id),
- type == ACK_SET ? "set" : "clear",
- fw_ack(d),
- pass);
+ drm_dbg(&d->uncore->i915->drm,
+ "%s had to use fallback to %s ack, 0x%x (passes %u)\n",
+ intel_uncore_forcewake_domain_to_str(d->id),
+ type == ACK_SET ? "set" : "clear",
+ fw_ack(d),
+ pass);
return ack_detected ? 0 : -ETIMEDOUT;
}
@@ -254,8 +258,9 @@ static inline void
fw_domain_wait_ack_set(const struct intel_uncore_forcewake_domain *d)
{
if (wait_ack_set(d, FORCEWAKE_KERNEL)) {
- DRM_ERROR("%s: timed out waiting for forcewake ack request.\n",
- intel_uncore_forcewake_domain_to_str(d->id));
+ drm_err(&d->uncore->i915->drm,
+ "%s: timed out waiting for forcewake ack request.\n",
+ intel_uncore_forcewake_domain_to_str(d->id));
add_taint_for_CI(d->uncore->i915, TAINT_WARN); /* CI now unreliable */
}
}
@@ -888,10 +893,13 @@ void assert_forcewakes_active(struct intel_uncore *uncore,
spin_unlock_irq(&uncore->lock);
}
-/* We give fast paths for the really cool registers */
+/*
+ * We give fast paths for the really cool registers. The second range includes
+ * media domains (and the GSC starting from Xe_LPM+)
+ */
#define NEEDS_FORCE_WAKE(reg) ({ \
u32 __reg = (reg); \
- __reg < 0x40000 || __reg >= GEN11_BSD_RING_BASE; \
+ __reg < 0x40000 || __reg >= 0x116000; \
})
static int fw_range_cmp(u32 offset, const struct intel_forcewake_range *entry)
@@ -1131,6 +1139,45 @@ static const struct i915_range pvc_shadowed_regs[] = {
{ .start = 0x1F8510, .end = 0x1F8550 },
};
+static const struct i915_range mtl_shadowed_regs[] = {
+ { .start = 0x2030, .end = 0x2030 },
+ { .start = 0x2510, .end = 0x2550 },
+ { .start = 0xA008, .end = 0xA00C },
+ { .start = 0xA188, .end = 0xA188 },
+ { .start = 0xA278, .end = 0xA278 },
+ { .start = 0xA540, .end = 0xA56C },
+ { .start = 0xC050, .end = 0xC050 },
+ { .start = 0xC340, .end = 0xC340 },
+ { .start = 0xC4C8, .end = 0xC4C8 },
+ { .start = 0xC4E0, .end = 0xC4E0 },
+ { .start = 0xC600, .end = 0xC600 },
+ { .start = 0xC658, .end = 0xC658 },
+ { .start = 0xCFD4, .end = 0xCFDC },
+ { .start = 0x22030, .end = 0x22030 },
+ { .start = 0x22510, .end = 0x22550 },
+};
+
+static const struct i915_range xelpmp_shadowed_regs[] = {
+ { .start = 0x1C0030, .end = 0x1C0030 },
+ { .start = 0x1C0510, .end = 0x1C0550 },
+ { .start = 0x1C8030, .end = 0x1C8030 },
+ { .start = 0x1C8510, .end = 0x1C8550 },
+ { .start = 0x1D0030, .end = 0x1D0030 },
+ { .start = 0x1D0510, .end = 0x1D0550 },
+ { .start = 0x38A008, .end = 0x38A00C },
+ { .start = 0x38A188, .end = 0x38A188 },
+ { .start = 0x38A278, .end = 0x38A278 },
+ { .start = 0x38A540, .end = 0x38A56C },
+ { .start = 0x38A618, .end = 0x38A618 },
+ { .start = 0x38C050, .end = 0x38C050 },
+ { .start = 0x38C340, .end = 0x38C340 },
+ { .start = 0x38C4C8, .end = 0x38C4C8 },
+ { .start = 0x38C4E0, .end = 0x38C4E4 },
+ { .start = 0x38C600, .end = 0x38C600 },
+ { .start = 0x38C658, .end = 0x38C658 },
+ { .start = 0x38CFD4, .end = 0x38CFDC },
+};
+
static int mmio_range_cmp(u32 key, const struct i915_range *range)
{
if (key < range->start)
@@ -1639,25 +1686,27 @@ static const struct intel_forcewake_range __pvc_fw_ranges[] = {
GEN_FW_RANGE(0x12000, 0x12fff, 0), /*
0x12000 - 0x127ff: always on
0x12800 - 0x12fff: reserved */
- GEN_FW_RANGE(0x13000, 0x23fff, FORCEWAKE_GT), /*
+ GEN_FW_RANGE(0x13000, 0x19fff, FORCEWAKE_GT), /*
0x13000 - 0x135ff: gt
0x13600 - 0x147ff: reserved
0x14800 - 0x153ff: gt
- 0x15400 - 0x19fff: reserved
- 0x1a000 - 0x1ffff: gt
- 0x20000 - 0x21fff: reserved
- 0x22000 - 0x23fff: gt */
+ 0x15400 - 0x19fff: reserved */
+ GEN_FW_RANGE(0x1a000, 0x21fff, FORCEWAKE_RENDER), /*
+ 0x1a000 - 0x1ffff: render
+ 0x20000 - 0x21fff: reserved */
+ GEN_FW_RANGE(0x22000, 0x23fff, FORCEWAKE_GT),
GEN_FW_RANGE(0x24000, 0x2417f, 0), /*
24000 - 0x2407f: always on
24080 - 0x2417f: reserved */
- GEN_FW_RANGE(0x24180, 0x3ffff, FORCEWAKE_GT), /*
+ GEN_FW_RANGE(0x24180, 0x25fff, FORCEWAKE_GT), /*
0x24180 - 0x241ff: gt
0x24200 - 0x251ff: reserved
0x25200 - 0x252ff: gt
- 0x25300 - 0x25fff: reserved
- 0x26000 - 0x27fff: gt
- 0x28000 - 0x2ffff: reserved
- 0x30000 - 0x3ffff: gt */
+ 0x25300 - 0x25fff: reserved */
+ GEN_FW_RANGE(0x26000, 0x2ffff, FORCEWAKE_RENDER), /*
+ 0x26000 - 0x27fff: render
+ 0x28000 - 0x2ffff: reserved */
+ GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_GT),
GEN_FW_RANGE(0x40000, 0x1bffff, 0),
GEN_FW_RANGE(0x1c0000, 0x1c3fff, FORCEWAKE_MEDIA_VDBOX0), /*
0x1c0000 - 0x1c2bff: VD0
@@ -1679,6 +1728,162 @@ static const struct intel_forcewake_range __pvc_fw_ranges[] = {
GEN_FW_RANGE(0x3e0000, 0x3effff, FORCEWAKE_GT),
};
+static const struct intel_forcewake_range __mtl_fw_ranges[] = {
+ GEN_FW_RANGE(0x0, 0xaff, 0),
+ GEN_FW_RANGE(0xb00, 0xbff, FORCEWAKE_GT),
+ GEN_FW_RANGE(0xc00, 0xfff, 0),
+ GEN_FW_RANGE(0x1000, 0x1fff, FORCEWAKE_GT),
+ GEN_FW_RANGE(0x2000, 0x26ff, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0x2700, 0x2fff, FORCEWAKE_GT),
+ GEN_FW_RANGE(0x3000, 0x3fff, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0x4000, 0x51ff, FORCEWAKE_GT), /*
+ 0x4000 - 0x48ff: render
+ 0x4900 - 0x51ff: reserved */
+ GEN_FW_RANGE(0x5200, 0x7fff, FORCEWAKE_RENDER), /*
+ 0x5200 - 0x53ff: render
+ 0x5400 - 0x54ff: reserved
+ 0x5500 - 0x7fff: render */
+ GEN_FW_RANGE(0x8000, 0x813f, FORCEWAKE_GT),
+ GEN_FW_RANGE(0x8140, 0x817f, FORCEWAKE_RENDER), /*
+ 0x8140 - 0x815f: render
+ 0x8160 - 0x817f: reserved */
+ GEN_FW_RANGE(0x8180, 0x81ff, 0),
+ GEN_FW_RANGE(0x8200, 0x94cf, FORCEWAKE_GT), /*
+ 0x8200 - 0x87ff: gt
+ 0x8800 - 0x8dff: reserved
+ 0x8e00 - 0x8f7f: gt
+ 0x8f80 - 0x8fff: reserved
+ 0x9000 - 0x947f: gt
+ 0x9480 - 0x94cf: reserved */
+ GEN_FW_RANGE(0x94d0, 0x955f, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0x9560, 0x967f, 0), /*
+ 0x9560 - 0x95ff: always on
+ 0x9600 - 0x967f: reserved */
+ GEN_FW_RANGE(0x9680, 0x97ff, FORCEWAKE_RENDER), /*
+ 0x9680 - 0x96ff: render
+ 0x9700 - 0x97ff: reserved */
+ GEN_FW_RANGE(0x9800, 0xcfff, FORCEWAKE_GT), /*
+ 0x9800 - 0xb4ff: gt
+ 0xb500 - 0xbfff: reserved
+ 0xc000 - 0xcfff: gt */
+ GEN_FW_RANGE(0xd000, 0xd7ff, 0), /*
+ 0xd000 - 0xd3ff: always on
+ 0xd400 - 0xd7ff: reserved */
+ GEN_FW_RANGE(0xd800, 0xd87f, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0xd880, 0xdbff, FORCEWAKE_GT),
+ GEN_FW_RANGE(0xdc00, 0xdcff, FORCEWAKE_RENDER),
+ GEN_FW_RANGE(0xdd00, 0xde7f, FORCEWAKE_GT), /*
+ 0xdd00 - 0xddff: gt
+ 0xde00 - 0xde7f: reserved */
+ GEN_FW_RANGE(0xde80, 0xe8ff, FORCEWAKE_RENDER), /*
+ 0xde80 - 0xdfff: render
+ 0xe000 - 0xe0ff: reserved
+ 0xe100 - 0xe8ff: render */
+ GEN_FW_RANGE(0xe900, 0xe9ff, FORCEWAKE_GT),
+ GEN_FW_RANGE(0xea00, 0x147ff, 0), /*
+ 0xea00 - 0x11fff: reserved
+ 0x12000 - 0x127ff: always on
+ 0x12800 - 0x147ff: reserved */
+ GEN_FW_RANGE(0x14800, 0x19fff, FORCEWAKE_GT), /*
+ 0x14800 - 0x153ff: gt
+ 0x15400 - 0x19fff: reserved */
+ GEN_FW_RANGE(0x1a000, 0x21fff, FORCEWAKE_RENDER), /*
+ 0x1a000 - 0x1bfff: render
+ 0x1c000 - 0x21fff: reserved */
+ GEN_FW_RANGE(0x22000, 0x23fff, FORCEWAKE_GT),
+ GEN_FW_RANGE(0x24000, 0x2ffff, 0), /*
+ 0x24000 - 0x2407f: always on
+ 0x24080 - 0x2ffff: reserved */
+ GEN_FW_RANGE(0x30000, 0x3ffff, FORCEWAKE_GT)
+};
+
+/*
+ * Note that the register ranges here are the final offsets after
+ * translation of the GSI block to the 0x380000 offset.
+ *
+ * NOTE: There are a couple MCR ranges near the bottom of this table
+ * that need to power up either VD0 or VD2 depending on which replicated
+ * instance of the register we're trying to access. Our forcewake logic
+ * at the moment doesn't have a good way to take steering into consideration,
+ * and the driver doesn't even access any registers in those ranges today,
+ * so for now we just mark those ranges as FORCEWAKE_ALL. That will ensure
+ * proper operation if we do start using the ranges in the future, and we
+ * can determine at that time whether it's worth adding extra complexity to
+ * the forcewake handling to take steering into consideration.
+ */
+static const struct intel_forcewake_range __xelpmp_fw_ranges[] = {
+ GEN_FW_RANGE(0x0, 0x115fff, 0), /* render GT range */
+ GEN_FW_RANGE(0x116000, 0x11ffff, FORCEWAKE_GSC), /*
+ 0x116000 - 0x117fff: gsc
+ 0x118000 - 0x119fff: reserved
+ 0x11a000 - 0x11efff: gsc
+ 0x11f000 - 0x11ffff: reserved */
+ GEN_FW_RANGE(0x120000, 0x1bffff, 0), /* non-GT range */
+ GEN_FW_RANGE(0x1c0000, 0x1c7fff, FORCEWAKE_MEDIA_VDBOX0), /*
+ 0x1c0000 - 0x1c3dff: VD0
+ 0x1c3e00 - 0x1c3eff: reserved
+ 0x1c3f00 - 0x1c3fff: VD0
+ 0x1c4000 - 0x1c7fff: reserved */
+ GEN_FW_RANGE(0x1c8000, 0x1cbfff, FORCEWAKE_MEDIA_VEBOX0), /*
+ 0x1c8000 - 0x1ca0ff: VE0
+ 0x1ca100 - 0x1cbfff: reserved */
+ GEN_FW_RANGE(0x1cc000, 0x1cffff, FORCEWAKE_MEDIA_VDBOX0), /*
+ 0x1cc000 - 0x1cdfff: VD0
+ 0x1ce000 - 0x1cffff: reserved */
+ GEN_FW_RANGE(0x1d0000, 0x1d7fff, FORCEWAKE_MEDIA_VDBOX2), /*
+ 0x1d0000 - 0x1d3dff: VD2
+ 0x1d3e00 - 0x1d3eff: reserved
+ 0x1d4000 - 0x1d7fff: VD2 */
+ GEN_FW_RANGE(0x1d8000, 0x1da0ff, FORCEWAKE_MEDIA_VEBOX1),
+ GEN_FW_RANGE(0x1da100, 0x380aff, 0), /*
+ 0x1da100 - 0x23ffff: reserved
+ 0x240000 - 0x37ffff: non-GT range
+ 0x380000 - 0x380aff: reserved */
+ GEN_FW_RANGE(0x380b00, 0x380bff, FORCEWAKE_GT),
+ GEN_FW_RANGE(0x380c00, 0x380fff, 0),
+ GEN_FW_RANGE(0x381000, 0x38817f, FORCEWAKE_GT), /*
+ 0x381000 - 0x381fff: gt
+ 0x382000 - 0x383fff: reserved
+ 0x384000 - 0x384aff: gt
+ 0x384b00 - 0x3851ff: reserved
+ 0x385200 - 0x3871ff: gt
+ 0x387200 - 0x387fff: reserved
+ 0x388000 - 0x38813f: gt
+ 0x388140 - 0x38817f: reserved */
+ GEN_FW_RANGE(0x388180, 0x3882ff, 0), /*
+ 0x388180 - 0x3881ff: always on
+ 0x388200 - 0x3882ff: reserved */
+ GEN_FW_RANGE(0x388300, 0x38955f, FORCEWAKE_GT), /*
+ 0x388300 - 0x38887f: gt
+ 0x388880 - 0x388fff: reserved
+ 0x389000 - 0x38947f: gt
+ 0x389480 - 0x38955f: reserved */
+ GEN_FW_RANGE(0x389560, 0x389fff, 0), /*
+ 0x389560 - 0x3895ff: always on
+ 0x389600 - 0x389fff: reserved */
+ GEN_FW_RANGE(0x38a000, 0x38cfff, FORCEWAKE_GT), /*
+ 0x38a000 - 0x38afff: gt
+ 0x38b000 - 0x38bfff: reserved
+ 0x38c000 - 0x38cfff: gt */
+ GEN_FW_RANGE(0x38d000, 0x38d11f, 0),
+ GEN_FW_RANGE(0x38d120, 0x391fff, FORCEWAKE_GT), /*
+ 0x38d120 - 0x38dfff: gt
+ 0x38e000 - 0x38efff: reserved
+ 0x38f000 - 0x38ffff: gt
+ 0x389000 - 0x391fff: reserved */
+ GEN_FW_RANGE(0x392000, 0x392fff, 0), /*
+ 0x392000 - 0x3927ff: always on
+ 0x392800 - 0x292fff: reserved */
+ GEN_FW_RANGE(0x393000, 0x3931ff, FORCEWAKE_GT),
+ GEN_FW_RANGE(0x393200, 0x39323f, FORCEWAKE_ALL), /* instance-based, see note above */
+ GEN_FW_RANGE(0x393240, 0x3933ff, FORCEWAKE_GT),
+ GEN_FW_RANGE(0x393400, 0x3934ff, FORCEWAKE_ALL), /* instance-based, see note above */
+ GEN_FW_RANGE(0x393500, 0x393c7f, 0), /*
+ 0x393500 - 0x393bff: reserved
+ 0x393c00 - 0x393c7f: always on */
+ GEN_FW_RANGE(0x393c80, 0x393dff, FORCEWAKE_GT),
+};
+
static void
ilk_dummy_write(struct intel_uncore *uncore)
{
@@ -2021,6 +2226,7 @@ static int __fw_domain_init(struct intel_uncore *uncore,
BUILD_BUG_ON(FORCEWAKE_MEDIA_VEBOX1 != (1 << FW_DOMAIN_ID_MEDIA_VEBOX1));
BUILD_BUG_ON(FORCEWAKE_MEDIA_VEBOX2 != (1 << FW_DOMAIN_ID_MEDIA_VEBOX2));
BUILD_BUG_ON(FORCEWAKE_MEDIA_VEBOX3 != (1 << FW_DOMAIN_ID_MEDIA_VEBOX3));
+ BUILD_BUG_ON(FORCEWAKE_GSC != (1 << FW_DOMAIN_ID_GSC));
d->mask = BIT(domain_id);
@@ -2085,17 +2291,26 @@ static int intel_uncore_fw_domains_init(struct intel_uncore *uncore)
(ret ?: (ret = __fw_domain_init((uncore__), (id__), (set__), (ack__))))
if (GRAPHICS_VER(i915) >= 11) {
- /* we'll prune the domains of missing engines later */
- intel_engine_mask_t emask = RUNTIME_INFO(i915)->platform_engine_mask;
+ intel_engine_mask_t emask;
int i;
+ /* we'll prune the domains of missing engines later */
+ emask = uncore->gt->info.engine_mask;
+
uncore->fw_get_funcs = &uncore_get_fallback;
- fw_domain_init(uncore, FW_DOMAIN_ID_RENDER,
- FORCEWAKE_RENDER_GEN9,
- FORCEWAKE_ACK_RENDER_GEN9);
- fw_domain_init(uncore, FW_DOMAIN_ID_GT,
- FORCEWAKE_GT_GEN9,
- FORCEWAKE_ACK_GT_GEN9);
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70))
+ fw_domain_init(uncore, FW_DOMAIN_ID_GT,
+ FORCEWAKE_GT_GEN9,
+ FORCEWAKE_ACK_GT_MTL);
+ else
+ fw_domain_init(uncore, FW_DOMAIN_ID_GT,
+ FORCEWAKE_GT_GEN9,
+ FORCEWAKE_ACK_GT_GEN9);
+
+ if (RCS_MASK(uncore->gt) || CCS_MASK(uncore->gt))
+ fw_domain_init(uncore, FW_DOMAIN_ID_RENDER,
+ FORCEWAKE_RENDER_GEN9,
+ FORCEWAKE_ACK_RENDER_GEN9);
for (i = 0; i < I915_MAX_VCS; i++) {
if (!__HAS_ENGINE(emask, _VCS(i)))
@@ -2113,6 +2328,10 @@ static int intel_uncore_fw_domains_init(struct intel_uncore *uncore)
FORCEWAKE_MEDIA_VEBOX_GEN11(i),
FORCEWAKE_ACK_MEDIA_VEBOX_GEN11(i));
}
+
+ if (uncore->gt->type == GT_MEDIA)
+ fw_domain_init(uncore, FW_DOMAIN_ID_GSC,
+ FORCEWAKE_REQ_GSC, FORCEWAKE_ACK_GSC);
} else if (IS_GRAPHICS_VER(i915, 9, 10)) {
uncore->fw_get_funcs = &uncore_get_fallback;
fw_domain_init(uncore, FW_DOMAIN_ID_RENDER,
@@ -2300,6 +2519,22 @@ static void uncore_raw_init(struct intel_uncore *uncore)
}
}
+static int uncore_media_forcewake_init(struct intel_uncore *uncore)
+{
+ struct drm_i915_private *i915 = uncore->i915;
+
+ if (MEDIA_VER(i915) >= 13) {
+ ASSIGN_FW_DOMAINS_TABLE(uncore, __xelpmp_fw_ranges);
+ ASSIGN_SHADOW_TABLE(uncore, xelpmp_shadowed_regs);
+ ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable);
+ } else {
+ MISSING_CASE(MEDIA_VER(i915));
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
static int uncore_forcewake_init(struct intel_uncore *uncore)
{
struct drm_i915_private *i915 = uncore->i915;
@@ -2314,7 +2549,14 @@ static int uncore_forcewake_init(struct intel_uncore *uncore)
ASSIGN_READ_MMIO_VFUNCS(uncore, fwtable);
- if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 60)) {
+ if (uncore->gt->type == GT_MEDIA)
+ return uncore_media_forcewake_init(uncore);
+
+ if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 70)) {
+ ASSIGN_FW_DOMAINS_TABLE(uncore, __mtl_fw_ranges);
+ ASSIGN_SHADOW_TABLE(uncore, mtl_shadowed_regs);
+ ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable);
+ } else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 60)) {
ASSIGN_FW_DOMAINS_TABLE(uncore, __pvc_fw_ranges);
ASSIGN_SHADOW_TABLE(uncore, pvc_shadowed_regs);
ASSIGN_WRITE_MMIO_VFUNCS(uncore, fwtable);
diff --git a/drivers/gpu/drm/i915/intel_uncore.h b/drivers/gpu/drm/i915/intel_uncore.h
index 5022bac80b67..e9e38490815d 100644
--- a/drivers/gpu/drm/i915/intel_uncore.h
+++ b/drivers/gpu/drm/i915/intel_uncore.h
@@ -62,6 +62,7 @@ enum forcewake_domain_id {
FW_DOMAIN_ID_MEDIA_VEBOX1,
FW_DOMAIN_ID_MEDIA_VEBOX2,
FW_DOMAIN_ID_MEDIA_VEBOX3,
+ FW_DOMAIN_ID_GSC,
FW_DOMAIN_ID_COUNT
};
@@ -82,6 +83,7 @@ enum forcewake_domains {
FORCEWAKE_MEDIA_VEBOX1 = BIT(FW_DOMAIN_ID_MEDIA_VEBOX1),
FORCEWAKE_MEDIA_VEBOX2 = BIT(FW_DOMAIN_ID_MEDIA_VEBOX2),
FORCEWAKE_MEDIA_VEBOX3 = BIT(FW_DOMAIN_ID_MEDIA_VEBOX3),
+ FORCEWAKE_GSC = BIT(FW_DOMAIN_ID_GSC),
FORCEWAKE_ALL = BIT(FW_DOMAIN_ID_COUNT) - 1,
};
@@ -380,20 +382,6 @@ __uncore_write(write_notrace, 32, l, false)
*/
__uncore_read(read64, 64, q, true)
-static inline u64
-intel_uncore_read64_2x32(struct intel_uncore *uncore,
- i915_reg_t lower_reg, i915_reg_t upper_reg)
-{
- u32 upper, lower, old_upper, loop = 0;
- upper = intel_uncore_read(uncore, upper_reg);
- do {
- old_upper = upper;
- lower = intel_uncore_read(uncore, lower_reg);
- upper = intel_uncore_read(uncore, upper_reg);
- } while (upper != old_upper && loop++ < 2);
- return (u64)upper << 32 | lower;
-}
-
#define intel_uncore_posting_read(...) ((void)intel_uncore_read_notrace(__VA_ARGS__))
#define intel_uncore_posting_read16(...) ((void)intel_uncore_read16_notrace(__VA_ARGS__))
@@ -431,15 +419,15 @@ intel_uncore_read64_2x32(struct intel_uncore *uncore,
#define intel_uncore_write64_fw(...) __raw_uncore_write64(__VA_ARGS__)
#define intel_uncore_posting_read_fw(...) ((void)intel_uncore_read_fw(__VA_ARGS__))
-static inline void intel_uncore_rmw(struct intel_uncore *uncore,
- i915_reg_t reg, u32 clear, u32 set)
+static inline u32 intel_uncore_rmw(struct intel_uncore *uncore,
+ i915_reg_t reg, u32 clear, u32 set)
{
u32 old, val;
old = intel_uncore_read(uncore, reg);
val = (old & ~clear) | set;
- if (val != old)
- intel_uncore_write(uncore, reg, val);
+ intel_uncore_write(uncore, reg, val);
+ return old;
}
static inline void intel_uncore_rmw_fw(struct intel_uncore *uncore,
@@ -453,6 +441,36 @@ static inline void intel_uncore_rmw_fw(struct intel_uncore *uncore,
intel_uncore_write_fw(uncore, reg, val);
}
+static inline u64
+intel_uncore_read64_2x32(struct intel_uncore *uncore,
+ i915_reg_t lower_reg, i915_reg_t upper_reg)
+{
+ u32 upper, lower, old_upper, loop = 0;
+ enum forcewake_domains fw_domains;
+ unsigned long flags;
+
+ fw_domains = intel_uncore_forcewake_for_reg(uncore, lower_reg,
+ FW_REG_READ);
+
+ fw_domains |= intel_uncore_forcewake_for_reg(uncore, upper_reg,
+ FW_REG_READ);
+
+ spin_lock_irqsave(&uncore->lock, flags);
+ intel_uncore_forcewake_get__locked(uncore, fw_domains);
+
+ upper = intel_uncore_read_fw(uncore, upper_reg);
+ do {
+ old_upper = upper;
+ lower = intel_uncore_read_fw(uncore, lower_reg);
+ upper = intel_uncore_read_fw(uncore, upper_reg);
+ } while (upper != old_upper && loop++ < 2);
+
+ intel_uncore_forcewake_put__locked(uncore, fw_domains);
+ spin_unlock_irqrestore(&uncore->lock, flags);
+
+ return (u64)upper << 32 | lower;
+}
+
static inline int intel_uncore_write_and_verify(struct intel_uncore *uncore,
i915_reg_t reg, u32 val,
u32 mask, u32 expected_val)
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.c b/drivers/gpu/drm/i915/pxp/intel_pxp.c
index 69cdaaddc4a9..5efe61f67546 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp.c
@@ -103,19 +103,15 @@ static int create_vcs_context(struct intel_pxp *pxp)
static void destroy_vcs_context(struct intel_pxp *pxp)
{
- intel_engine_destroy_pinned_context(fetch_and_zero(&pxp->ce));
+ if (pxp->ce)
+ intel_engine_destroy_pinned_context(fetch_and_zero(&pxp->ce));
}
-void intel_pxp_init(struct intel_pxp *pxp)
+static void pxp_init_full(struct intel_pxp *pxp)
{
struct intel_gt *gt = pxp_to_gt(pxp);
int ret;
- if (!HAS_PXP(gt->i915))
- return;
-
- mutex_init(&pxp->tee_mutex);
-
/*
* we'll use the completion to check if there is a termination pending,
* so we start it as completed and we reinit it when a termination
@@ -124,8 +120,7 @@ void intel_pxp_init(struct intel_pxp *pxp)
init_completion(&pxp->termination);
complete_all(&pxp->termination);
- mutex_init(&pxp->arb_mutex);
- INIT_WORK(&pxp->session_work, intel_pxp_session_work);
+ intel_pxp_session_management_init(pxp);
ret = create_vcs_context(pxp);
if (ret)
@@ -143,11 +138,26 @@ out_context:
destroy_vcs_context(pxp);
}
-void intel_pxp_fini(struct intel_pxp *pxp)
+void intel_pxp_init(struct intel_pxp *pxp)
{
- if (!intel_pxp_is_enabled(pxp))
+ struct intel_gt *gt = pxp_to_gt(pxp);
+
+ /* we rely on the mei PXP module */
+ if (!IS_ENABLED(CONFIG_INTEL_MEI_PXP))
return;
+ /*
+ * If HuC is loaded by GSC but PXP is disabled, we can skip the init of
+ * the full PXP session/object management and just init the tee channel.
+ */
+ if (HAS_PXP(gt->i915))
+ pxp_init_full(pxp);
+ else if (intel_huc_is_loaded_by_gsc(&gt->uc.huc) && intel_uc_uses_huc(&gt->uc))
+ intel_pxp_tee_component_init(pxp);
+}
+
+void intel_pxp_fini(struct intel_pxp *pxp)
+{
pxp->arb_is_valid = false;
intel_pxp_tee_component_fini(pxp);
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp.h b/drivers/gpu/drm/i915/pxp/intel_pxp.h
index 73847e535cab..2da309088c6d 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp.h
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp.h
@@ -12,7 +12,6 @@
struct intel_pxp;
struct drm_i915_gem_object;
-#ifdef CONFIG_DRM_I915_PXP
struct intel_gt *pxp_to_gt(const struct intel_pxp *pxp);
bool intel_pxp_is_enabled(const struct intel_pxp *pxp);
bool intel_pxp_is_active(const struct intel_pxp *pxp);
@@ -32,36 +31,5 @@ int intel_pxp_key_check(struct intel_pxp *pxp,
bool assign);
void intel_pxp_invalidate(struct intel_pxp *pxp);
-#else
-static inline void intel_pxp_init(struct intel_pxp *pxp)
-{
-}
-
-static inline void intel_pxp_fini(struct intel_pxp *pxp)
-{
-}
-
-static inline int intel_pxp_start(struct intel_pxp *pxp)
-{
- return -ENODEV;
-}
-
-static inline bool intel_pxp_is_enabled(const struct intel_pxp *pxp)
-{
- return false;
-}
-
-static inline bool intel_pxp_is_active(const struct intel_pxp *pxp)
-{
- return false;
-}
-
-static inline int intel_pxp_key_check(struct intel_pxp *pxp,
- struct drm_i915_gem_object *obj,
- bool assign)
-{
- return -ENODEV;
-}
-#endif
#endif /* __INTEL_PXP_H__ */
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_42.h b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_42.h
new file mode 100644
index 000000000000..739f9072fa5f
--- /dev/null
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_42.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright(c) 2020, Intel Corporation. All rights reserved.
+ */
+
+#ifndef __INTEL_PXP_FW_INTERFACE_42_H__
+#define __INTEL_PXP_FW_INTERFACE_42_H__
+
+#include <linux/types.h>
+#include "intel_pxp_cmd_interface_cmn.h"
+
+/* PXP-Opcode for Init Session */
+#define PXP42_CMDID_INIT_SESSION 0x1e
+
+/* PXP-Input-Packet: Init Session (Arb-Session) */
+struct pxp42_create_arb_in {
+ struct pxp_cmd_header header;
+ u32 protection_mode;
+#define PXP42_ARB_SESSION_MODE_HEAVY 0x2
+ u32 session_id;
+} __packed;
+
+/* PXP-Output-Packet: Init Session */
+struct pxp42_create_arb_out {
+ struct pxp_cmd_header header;
+} __packed;
+
+#endif /* __INTEL_PXP_FW_INTERFACE_42_H__ */
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
new file mode 100644
index 000000000000..ad67e3f49c20
--- /dev/null
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_43.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright(c) 2022, Intel Corporation. All rights reserved.
+ */
+
+#ifndef __INTEL_PXP_FW_INTERFACE_43_H__
+#define __INTEL_PXP_FW_INTERFACE_43_H__
+
+#include <linux/types.h>
+#include "intel_pxp_cmd_interface_cmn.h"
+
+/* PXP-Cmd-Op definitions */
+#define PXP43_CMDID_START_HUC_AUTH 0x0000003A
+
+/* PXP-Input-Packet: HUC-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 {
+ struct pxp_cmd_header header;
+} __packed;
+
+#endif /* __INTEL_PXP_FW_INTERFACE_43_H__ */
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_cmn.h b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_cmn.h
new file mode 100644
index 000000000000..c2f23394f9b8
--- /dev/null
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_cmd_interface_cmn.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright(c) 2022, Intel Corporation. All rights reserved.
+ */
+
+#ifndef __INTEL_PXP_FW_INTERFACE_CMN_H__
+#define __INTEL_PXP_FW_INTERFACE_CMN_H__
+
+#include <linux/types.h>
+
+#define PXP_APIVER(x, y) (((x) & 0xFFFF) << 16 | ((y) & 0xFFFF))
+
+/*
+ * there are a lot of status codes for PXP, but we only define the cross-API
+ * common ones that we actually can handle in the kernel driver. Other failure
+ * codes should be printed to error msg for debug.
+ */
+enum pxp_status {
+ PXP_STATUS_SUCCESS = 0x0,
+ PXP_STATUS_OP_NOT_PERMITTED = 0x4013
+};
+
+/* Common PXP FW message header */
+struct pxp_cmd_header {
+ u32 api_version;
+ u32 command_id;
+ union {
+ u32 status; /* out */
+ u32 stream_id; /* in */
+ };
+ /* Length of the message (excluding the header) */
+ u32 buffer_len;
+} __packed;
+
+#endif /* __INTEL_PXP_FW_INTERFACE_CMN_H__ */
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_huc.c b/drivers/gpu/drm/i915/pxp/intel_pxp_huc.c
new file mode 100644
index 000000000000..2e1165522950
--- /dev/null
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_huc.c
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright(c) 2021-2022, Intel Corporation. All rights reserved.
+ */
+
+#include <drm/i915_drm.h>
+
+#include "i915_drv.h"
+
+#include "gem/i915_gem_region.h"
+#include "gt/intel_gt.h"
+
+#include "intel_pxp.h"
+#include "intel_pxp_huc.h"
+#include "intel_pxp_tee.h"
+#include "intel_pxp_types.h"
+#include "intel_pxp_cmd_interface_43.h"
+
+int intel_pxp_huc_load_and_auth(struct intel_pxp *pxp)
+{
+ struct intel_gt *gt = pxp_to_gt(pxp);
+ struct intel_huc *huc = &gt->uc.huc;
+ struct pxp43_start_huc_auth_in huc_in = {0};
+ struct pxp43_start_huc_auth_out huc_out = {0};
+ dma_addr_t huc_phys_addr;
+ u8 client_id = 0;
+ u8 fence_id = 0;
+ int err;
+
+ if (!pxp->pxp_component)
+ return -ENODEV;
+
+ huc_phys_addr = i915_gem_object_get_dma_address(huc->fw.obj, 0);
+
+ /* write the PXP message into the lmem (the sg list) */
+ huc_in.header.api_version = PXP_APIVER(4, 3);
+ huc_in.header.command_id = PXP43_CMDID_START_HUC_AUTH;
+ huc_in.header.status = 0;
+ huc_in.header.buffer_len = sizeof(huc_in.huc_base_address);
+ huc_in.huc_base_address = huc_phys_addr;
+
+ err = intel_pxp_tee_stream_message(pxp, client_id, fence_id,
+ &huc_in, sizeof(huc_in),
+ &huc_out, sizeof(huc_out));
+ if (err < 0) {
+ drm_err(&gt->i915->drm,
+ "Failed to send HuC load and auth command to GSC [%d]!\n",
+ err);
+ return err;
+ }
+
+ /*
+ * HuC does sometimes survive suspend/resume (it depends on how "deep"
+ * a sleep state the device reaches) so we can end up here on resume
+ * with HuC already loaded, in which case the GSC will return
+ * PXP_STATUS_OP_NOT_PERMITTED. We can therefore consider the GuC
+ * correctly transferred in this scenario; if the same error is ever
+ * returned with HuC not loaded we'll still catch it when we check the
+ * authentication bit later.
+ */
+ if (huc_out.header.status != PXP_STATUS_SUCCESS &&
+ huc_out.header.status != PXP_STATUS_OP_NOT_PERMITTED) {
+ drm_err(&gt->i915->drm,
+ "HuC load failed with GSC error = 0x%x\n",
+ huc_out.header.status);
+ return -EPROTO;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_huc.h b/drivers/gpu/drm/i915/pxp/intel_pxp_huc.h
new file mode 100644
index 000000000000..e40847a91c39
--- /dev/null
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_huc.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright(c) 2021-2022, Intel Corporation. All rights reserved.
+ */
+
+#ifndef __INTEL_PXP_HUC_H__
+#define __INTEL_PXP_HUC_H__
+
+struct intel_pxp;
+
+int intel_pxp_huc_load_and_auth(struct intel_pxp *pxp);
+
+#endif /* __INTEL_PXP_HUC_H__ */
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_irq.h b/drivers/gpu/drm/i915/pxp/intel_pxp_irq.h
index 8b5793654844..8c292dc86f68 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_irq.h
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_irq.h
@@ -27,6 +27,14 @@ void intel_pxp_irq_handler(struct intel_pxp *pxp, u16 iir);
static inline void intel_pxp_irq_handler(struct intel_pxp *pxp, u16 iir)
{
}
+
+static inline void intel_pxp_irq_enable(struct intel_pxp *pxp)
+{
+}
+
+static inline void intel_pxp_irq_disable(struct intel_pxp *pxp)
+{
+}
#endif
#endif /* __INTEL_PXP_IRQ_H__ */
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_session.c b/drivers/gpu/drm/i915/pxp/intel_pxp_session.c
index 1bb5b5249157..85572360c71a 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_session.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_session.c
@@ -77,6 +77,7 @@ static int pxp_create_arb_session(struct intel_pxp *pxp)
drm_err(&gt->i915->drm, "arb session failed to go in play\n");
return ret;
}
+ drm_dbg(&gt->i915->drm, "PXP ARB session is alive\n");
if (!++pxp->key_instance)
++pxp->key_instance;
@@ -137,7 +138,7 @@ static void pxp_terminate_complete(struct intel_pxp *pxp)
complete_all(&pxp->termination);
}
-void intel_pxp_session_work(struct work_struct *work)
+static void pxp_session_work(struct work_struct *work)
{
struct intel_pxp *pxp = container_of(work, typeof(*pxp), session_work);
struct intel_gt *gt = pxp_to_gt(pxp);
@@ -172,3 +173,9 @@ void intel_pxp_session_work(struct work_struct *work)
intel_runtime_pm_put(gt->uncore->rpm, wakeref);
}
+
+void intel_pxp_session_management_init(struct intel_pxp *pxp)
+{
+ mutex_init(&pxp->arb_mutex);
+ INIT_WORK(&pxp->session_work, pxp_session_work);
+}
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_session.h b/drivers/gpu/drm/i915/pxp/intel_pxp_session.h
index ba4c9d2b94b7..903ac52cffa1 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_session.h
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_session.h
@@ -8,8 +8,13 @@
#include <linux/types.h>
-struct work_struct;
-
-void intel_pxp_session_work(struct work_struct *work);
+struct intel_pxp;
+#ifdef CONFIG_DRM_I915_PXP
+void intel_pxp_session_management_init(struct intel_pxp *pxp);
+#else
+static inline void intel_pxp_session_management_init(struct intel_pxp *pxp)
+{
+}
+#endif
#endif /* __INTEL_PXP_SESSION_H__ */
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c
index 4b6f5655fab5..b0c9170b1395 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.c
@@ -8,11 +8,14 @@
#include <drm/i915_pxp_tee_interface.h>
#include <drm/i915_component.h>
+#include "gem/i915_gem_lmem.h"
+
#include "i915_drv.h"
#include "intel_pxp.h"
#include "intel_pxp_session.h"
#include "intel_pxp_tee.h"
-#include "intel_pxp_tee_interface.h"
+#include "intel_pxp_cmd_interface_42.h"
+#include "intel_pxp_huc.h"
static inline struct intel_pxp *i915_dev_to_pxp(struct device *i915_kdev)
{
@@ -69,6 +72,47 @@ unlock:
return ret;
}
+int intel_pxp_tee_stream_message(struct intel_pxp *pxp,
+ u8 client_id, u32 fence_id,
+ void *msg_in, size_t msg_in_len,
+ void *msg_out, size_t msg_out_len)
+{
+ /* TODO: for bigger objects we need to use a sg of 4k pages */
+ const size_t max_msg_size = PAGE_SIZE;
+ struct drm_i915_private *i915 = pxp_to_gt(pxp)->i915;
+ struct i915_pxp_component *pxp_component = pxp->pxp_component;
+ unsigned int offset = 0;
+ struct scatterlist *sg;
+ int ret;
+
+ if (msg_in_len > max_msg_size || msg_out_len > max_msg_size)
+ return -ENOSPC;
+
+ mutex_lock(&pxp->tee_mutex);
+
+ if (unlikely(!pxp_component || !pxp_component->ops->gsc_command)) {
+ ret = -ENODEV;
+ goto unlock;
+ }
+
+ GEM_BUG_ON(!pxp->stream_cmd.obj);
+
+ sg = i915_gem_object_get_sg_dma(pxp->stream_cmd.obj, 0, &offset);
+
+ memcpy(pxp->stream_cmd.vaddr, msg_in, msg_in_len);
+
+ ret = pxp_component->ops->gsc_command(pxp_component->tee_dev, client_id,
+ fence_id, sg, msg_in_len, sg);
+ if (ret < 0)
+ drm_err(&i915->drm, "Failed to send PXP TEE gsc command\n");
+ else
+ memcpy(msg_out, pxp->stream_cmd.vaddr, msg_out_len);
+
+unlock:
+ mutex_unlock(&pxp->tee_mutex);
+ return ret;
+}
+
/**
* i915_pxp_tee_component_bind - bind function to pass the function pointers to pxp_tee
* @i915_kdev: pointer to i915 kernel device
@@ -84,24 +128,36 @@ static int i915_pxp_tee_component_bind(struct device *i915_kdev,
{
struct drm_i915_private *i915 = kdev_to_i915(i915_kdev);
struct intel_pxp *pxp = i915_dev_to_pxp(i915_kdev);
+ struct intel_uc *uc = &pxp_to_gt(pxp)->uc;
intel_wakeref_t wakeref;
+ int ret = 0;
mutex_lock(&pxp->tee_mutex);
pxp->pxp_component = data;
pxp->pxp_component->tee_dev = tee_kdev;
mutex_unlock(&pxp->tee_mutex);
+ if (intel_uc_uses_huc(uc) && intel_huc_is_loaded_by_gsc(&uc->huc)) {
+ with_intel_runtime_pm(&i915->runtime_pm, wakeref) {
+ /* load huc via pxp */
+ ret = intel_huc_fw_load_and_auth_via_gsc(&uc->huc);
+ if (ret < 0)
+ drm_err(&i915->drm, "failed to load huc via gsc %d\n", ret);
+ }
+ }
+
/* if we are suspended, the HW will be re-initialized on resume */
wakeref = intel_runtime_pm_get_if_in_use(&i915->runtime_pm);
if (!wakeref)
return 0;
/* the component is required to fully start the PXP HW */
- intel_pxp_init_hw(pxp);
+ if (intel_pxp_is_enabled(pxp))
+ intel_pxp_init_hw(pxp);
intel_runtime_pm_put(&i915->runtime_pm, wakeref);
- return 0;
+ return ret;
}
static void i915_pxp_tee_component_unbind(struct device *i915_kdev,
@@ -111,8 +167,9 @@ static void i915_pxp_tee_component_unbind(struct device *i915_kdev,
struct intel_pxp *pxp = i915_dev_to_pxp(i915_kdev);
intel_wakeref_t wakeref;
- with_intel_runtime_pm_if_in_use(&i915->runtime_pm, wakeref)
- intel_pxp_fini_hw(pxp);
+ if (intel_pxp_is_enabled(pxp))
+ with_intel_runtime_pm_if_in_use(&i915->runtime_pm, wakeref)
+ intel_pxp_fini_hw(pxp);
mutex_lock(&pxp->tee_mutex);
pxp->pxp_component = NULL;
@@ -124,22 +181,92 @@ static const struct component_ops i915_pxp_tee_component_ops = {
.unbind = i915_pxp_tee_component_unbind,
};
+static int alloc_streaming_command(struct intel_pxp *pxp)
+{
+ struct drm_i915_private *i915 = pxp_to_gt(pxp)->i915;
+ struct drm_i915_gem_object *obj = NULL;
+ void *cmd;
+ int err;
+
+ pxp->stream_cmd.obj = NULL;
+ pxp->stream_cmd.vaddr = NULL;
+
+ if (!IS_DGFX(i915))
+ return 0;
+
+ /* allocate lmem object of one page for PXP command memory and store it */
+ obj = i915_gem_object_create_lmem(i915, PAGE_SIZE, I915_BO_ALLOC_CONTIGUOUS);
+ if (IS_ERR(obj)) {
+ drm_err(&i915->drm, "Failed to allocate pxp streaming command!\n");
+ return PTR_ERR(obj);
+ }
+
+ err = i915_gem_object_pin_pages_unlocked(obj);
+ if (err) {
+ drm_err(&i915->drm, "Failed to pin gsc message page!\n");
+ goto out_put;
+ }
+
+ /* map the lmem into the virtual memory pointer */
+ cmd = i915_gem_object_pin_map_unlocked(obj, i915_coherent_map_type(i915, obj, true));
+ if (IS_ERR(cmd)) {
+ drm_err(&i915->drm, "Failed to map gsc message page!\n");
+ err = PTR_ERR(cmd);
+ goto out_unpin;
+ }
+
+ memset(cmd, 0, obj->base.size);
+
+ pxp->stream_cmd.obj = obj;
+ pxp->stream_cmd.vaddr = cmd;
+
+ return 0;
+
+out_unpin:
+ i915_gem_object_unpin_pages(obj);
+out_put:
+ i915_gem_object_put(obj);
+ return err;
+}
+
+static void free_streaming_command(struct intel_pxp *pxp)
+{
+ struct drm_i915_gem_object *obj = fetch_and_zero(&pxp->stream_cmd.obj);
+
+ if (!obj)
+ return;
+
+ i915_gem_object_unpin_map(obj);
+ i915_gem_object_unpin_pages(obj);
+ i915_gem_object_put(obj);
+}
+
int intel_pxp_tee_component_init(struct intel_pxp *pxp)
{
int ret;
struct intel_gt *gt = pxp_to_gt(pxp);
struct drm_i915_private *i915 = gt->i915;
+ mutex_init(&pxp->tee_mutex);
+
+ ret = alloc_streaming_command(pxp);
+ if (ret)
+ return ret;
+
ret = component_add_typed(i915->drm.dev, &i915_pxp_tee_component_ops,
I915_COMPONENT_PXP);
if (ret < 0) {
drm_err(&i915->drm, "Failed to add PXP component (%d)\n", ret);
- return ret;
+ goto out_free;
}
pxp->pxp_component_added = true;
return 0;
+
+out_free:
+ free_streaming_command(pxp);
+ return ret;
}
void intel_pxp_tee_component_fini(struct intel_pxp *pxp)
@@ -151,20 +278,22 @@ void intel_pxp_tee_component_fini(struct intel_pxp *pxp)
component_del(i915->drm.dev, &i915_pxp_tee_component_ops);
pxp->pxp_component_added = false;
+
+ free_streaming_command(pxp);
}
int intel_pxp_tee_cmd_create_arb_session(struct intel_pxp *pxp,
int arb_session_id)
{
struct drm_i915_private *i915 = pxp_to_gt(pxp)->i915;
- struct pxp_tee_create_arb_in msg_in = {0};
- struct pxp_tee_create_arb_out msg_out = {0};
+ struct pxp42_create_arb_in msg_in = {0};
+ struct pxp42_create_arb_out msg_out = {0};
int ret;
- msg_in.header.api_version = PXP_TEE_APIVER;
- msg_in.header.command_id = PXP_TEE_ARB_CMDID;
+ msg_in.header.api_version = PXP_APIVER(4, 2);
+ msg_in.header.command_id = PXP42_CMDID_INIT_SESSION;
msg_in.header.buffer_len = sizeof(msg_in) - sizeof(msg_in.header);
- msg_in.protection_mode = PXP_TEE_ARB_PROTECTION_MODE;
+ msg_in.protection_mode = PXP42_ARB_SESSION_MODE_HEAVY;
msg_in.session_id = arb_session_id;
ret = intel_pxp_tee_io_message(pxp,
@@ -174,6 +303,9 @@ int intel_pxp_tee_cmd_create_arb_session(struct intel_pxp *pxp,
if (ret)
drm_err(&i915->drm, "Failed to send tee msg ret=[%d]\n", ret);
+ else if (msg_out.header.status != 0x0)
+ drm_warn(&i915->drm, "PXP firmware failed arb session init request ret=[0x%08x]\n",
+ msg_out.header.status);
return ret;
}
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.h b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.h
index c136053ce340..aeb3dfe7ce96 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_tee.h
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_tee.h
@@ -14,4 +14,9 @@ void intel_pxp_tee_component_fini(struct intel_pxp *pxp);
int intel_pxp_tee_cmd_create_arb_session(struct intel_pxp *pxp,
int arb_session_id);
+int intel_pxp_tee_stream_message(struct intel_pxp *pxp,
+ u8 client_id, u32 fence_id,
+ void *msg_in, size_t msg_in_len,
+ void *msg_out, size_t msg_out_len);
+
#endif /* __INTEL_PXP_TEE_H__ */
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_tee_interface.h b/drivers/gpu/drm/i915/pxp/intel_pxp_tee_interface.h
deleted file mode 100644
index 36e9b0868f5c..000000000000
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_tee_interface.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright(c) 2020, Intel Corporation. All rights reserved.
- */
-
-#ifndef __INTEL_PXP_TEE_INTERFACE_H__
-#define __INTEL_PXP_TEE_INTERFACE_H__
-
-#include <linux/types.h>
-
-#define PXP_TEE_APIVER 0x40002
-#define PXP_TEE_ARB_CMDID 0x1e
-#define PXP_TEE_ARB_PROTECTION_MODE 0x2
-
-/* PXP TEE message header */
-struct pxp_tee_cmd_header {
- u32 api_version;
- u32 command_id;
- u32 status;
- /* Length of the message (excluding the header) */
- u32 buffer_len;
-} __packed;
-
-/* PXP TEE message input to create a arbitrary session */
-struct pxp_tee_create_arb_in {
- struct pxp_tee_cmd_header header;
- u32 protection_mode;
- u32 session_id;
-} __packed;
-
-/* PXP TEE message output to create a arbitrary session */
-struct pxp_tee_create_arb_out {
- struct pxp_tee_cmd_header header;
-} __packed;
-
-#endif /* __INTEL_PXP_TEE_INTERFACE_H__ */
diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_types.h b/drivers/gpu/drm/i915/pxp/intel_pxp_types.h
index 7ce5f37ee12e..f74b1e11a505 100644
--- a/drivers/gpu/drm/i915/pxp/intel_pxp_types.h
+++ b/drivers/gpu/drm/i915/pxp/intel_pxp_types.h
@@ -53,6 +53,12 @@ struct intel_pxp {
/** @tee_mutex: protects the tee channel binding and messaging. */
struct mutex tee_mutex;
+ /** @stream_cmd: LMEM obj used to send stream PXP commands to the GSC */
+ struct {
+ struct drm_i915_gem_object *obj; /* contains PXP command memory */
+ void *vaddr; /* virtual memory for PXP command */
+ } stream_cmd;
+
/**
* @hw_state_invalidated: if the HW perceives an attack on the integrity
* of the encryption it will invalidate the keys and expect SW to
diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
index e050a2de5fd1..eae7d947d7de 100644
--- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c
@@ -27,6 +27,7 @@
#include "gem/i915_gem_context.h"
#include "gem/i915_gem_internal.h"
+#include "gem/i915_gem_lmem.h"
#include "gem/i915_gem_region.h"
#include "gem/selftests/mock_context.h"
#include "gt/intel_context.h"
@@ -60,7 +61,6 @@ static int fake_get_pages(struct drm_i915_gem_object *obj)
#define PFN_BIAS 0x1000
struct sg_table *pages;
struct scatterlist *sg;
- unsigned int sg_page_sizes;
typeof(obj->base.size) rem;
pages = kmalloc(sizeof(*pages), GFP);
@@ -73,7 +73,6 @@ static int fake_get_pages(struct drm_i915_gem_object *obj)
return -ENOMEM;
}
- sg_page_sizes = 0;
rem = obj->base.size;
for (sg = pages->sgl; sg; sg = sg_next(sg)) {
unsigned long len = min_t(typeof(rem), rem, BIT(31));
@@ -82,13 +81,12 @@ static int fake_get_pages(struct drm_i915_gem_object *obj)
sg_set_page(sg, pfn_to_page(PFN_BIAS), len, 0);
sg_dma_address(sg) = page_to_phys(sg_page(sg));
sg_dma_len(sg) = len;
- sg_page_sizes |= len;
rem -= len;
}
GEM_BUG_ON(rem);
- __i915_gem_object_set_pages(obj, pages, sg_page_sizes);
+ __i915_gem_object_set_pages(obj, pages);
return 0;
#undef GFP
@@ -1113,15 +1111,8 @@ static int misaligned_case(struct i915_address_space *vm, struct intel_memory_re
expected_node_size = expected_vma_size;
if (HAS_64K_PAGES(vm->i915) && i915_gem_object_is_lmem(obj)) {
- /*
- * The compact-pt should expand lmem node to 2MB for the ppGTT,
- * for all other cases we should only expect 64K.
- */
expected_vma_size = round_up(size, I915_GTT_PAGE_SIZE_64K);
- if (NEEDS_COMPACT_PT(vm->i915) && !i915_is_ggtt(vm))
- expected_node_size = round_up(size, I915_GTT_PAGE_SIZE_2M);
- else
- expected_node_size = round_up(size, I915_GTT_PAGE_SIZE_64K);
+ expected_node_size = round_up(size, I915_GTT_PAGE_SIZE_64K);
}
if (vma->size != expected_vma_size || vma->node.size != expected_node_size) {
diff --git a/drivers/gpu/drm/i915/selftests/i915_perf.c b/drivers/gpu/drm/i915/selftests/i915_perf.c
index 429c6d73b159..24dde5531423 100644
--- a/drivers/gpu/drm/i915/selftests/i915_perf.c
+++ b/drivers/gpu/drm/i915/selftests/i915_perf.c
@@ -102,6 +102,12 @@ test_stream(struct i915_perf *perf)
I915_OA_FORMAT_A32u40_A4u32_B8_C8 : I915_OA_FORMAT_C4_B8,
};
struct i915_perf_stream *stream;
+ struct intel_gt *gt;
+
+ if (!props.engine)
+ return NULL;
+
+ gt = props.engine->gt;
if (!oa_config)
return NULL;
@@ -116,12 +122,12 @@ test_stream(struct i915_perf *perf)
stream->perf = perf;
- mutex_lock(&perf->lock);
+ mutex_lock(&gt->perf.lock);
if (i915_oa_stream_init(stream, &param, &props)) {
kfree(stream);
stream = NULL;
}
- mutex_unlock(&perf->lock);
+ mutex_unlock(&gt->perf.lock);
i915_oa_config_put(oa_config);
@@ -130,11 +136,11 @@ test_stream(struct i915_perf *perf)
static void stream_destroy(struct i915_perf_stream *stream)
{
- struct i915_perf *perf = stream->perf;
+ struct intel_gt *gt = stream->engine->gt;
- mutex_lock(&perf->lock);
+ mutex_lock(&gt->perf.lock);
i915_perf_destroy_locked(stream);
- mutex_unlock(&perf->lock);
+ mutex_unlock(&gt->perf.lock);
}
static int live_sanitycheck(void *arg)
diff --git a/drivers/gpu/drm/i915/selftests/i915_request.c b/drivers/gpu/drm/i915/selftests/i915_request.c
index 818a4909c1f3..0daa8669181d 100644
--- a/drivers/gpu/drm/i915/selftests/i915_request.c
+++ b/drivers/gpu/drm/i915/selftests/i915_request.c
@@ -299,9 +299,18 @@ __live_request_alloc(struct intel_context *ce)
return intel_context_create_request(ce);
}
-static int __igt_breadcrumbs_smoketest(void *arg)
+struct smoke_thread {
+ struct kthread_worker *worker;
+ struct kthread_work work;
+ struct smoketest *t;
+ bool stop;
+ int result;
+};
+
+static void __igt_breadcrumbs_smoketest(struct kthread_work *work)
{
- struct smoketest *t = arg;
+ struct smoke_thread *thread = container_of(work, typeof(*thread), work);
+ struct smoketest *t = thread->t;
const unsigned int max_batch = min(t->ncontexts, t->max_batch) - 1;
const unsigned int total = 4 * t->ncontexts + 1;
unsigned int num_waits = 0, num_fences = 0;
@@ -320,8 +329,10 @@ static int __igt_breadcrumbs_smoketest(void *arg)
*/
requests = kcalloc(total, sizeof(*requests), GFP_KERNEL);
- if (!requests)
- return -ENOMEM;
+ if (!requests) {
+ thread->result = -ENOMEM;
+ return;
+ }
order = i915_random_order(total, &prng);
if (!order) {
@@ -329,7 +340,7 @@ static int __igt_breadcrumbs_smoketest(void *arg)
goto out_requests;
}
- while (!kthread_should_stop()) {
+ while (!READ_ONCE(thread->stop)) {
struct i915_sw_fence *submit, *wait;
unsigned int n, count;
@@ -437,7 +448,7 @@ static int __igt_breadcrumbs_smoketest(void *arg)
kfree(order);
out_requests:
kfree(requests);
- return err;
+ thread->result = err;
}
static int mock_breadcrumbs_smoketest(void *arg)
@@ -450,7 +461,7 @@ static int mock_breadcrumbs_smoketest(void *arg)
.request_alloc = __mock_request_alloc
};
unsigned int ncpus = num_online_cpus();
- struct task_struct **threads;
+ struct smoke_thread *threads;
unsigned int n;
int ret = 0;
@@ -479,28 +490,37 @@ static int mock_breadcrumbs_smoketest(void *arg)
}
for (n = 0; n < ncpus; n++) {
- threads[n] = kthread_run(__igt_breadcrumbs_smoketest,
- &t, "igt/%d", n);
- if (IS_ERR(threads[n])) {
- ret = PTR_ERR(threads[n]);
+ struct kthread_worker *worker;
+
+ worker = kthread_create_worker(0, "igt/%d", n);
+ if (IS_ERR(worker)) {
+ ret = PTR_ERR(worker);
ncpus = n;
break;
}
- get_task_struct(threads[n]);
+ threads[n].worker = worker;
+ threads[n].t = &t;
+ threads[n].stop = false;
+ threads[n].result = 0;
+
+ kthread_init_work(&threads[n].work,
+ __igt_breadcrumbs_smoketest);
+ kthread_queue_work(worker, &threads[n].work);
}
- yield(); /* start all threads before we begin */
msleep(jiffies_to_msecs(i915_selftest.timeout_jiffies));
for (n = 0; n < ncpus; n++) {
int err;
- err = kthread_stop(threads[n]);
+ WRITE_ONCE(threads[n].stop, true);
+ kthread_flush_work(&threads[n].work);
+ err = READ_ONCE(threads[n].result);
if (err < 0 && !ret)
ret = err;
- put_task_struct(threads[n]);
+ kthread_destroy_worker(threads[n].worker);
}
pr_info("Completed %lu waits for %lu fence across %d cpus\n",
atomic_long_read(&t.num_waits),
@@ -1203,9 +1223,7 @@ static int live_all_engines(void *arg)
goto out_request;
}
- err = i915_request_await_object(request[idx], batch->obj, 0);
- if (err == 0)
- err = i915_vma_move_to_active(batch, request[idx], 0);
+ err = i915_vma_move_to_active(batch, request[idx], 0);
GEM_BUG_ON(err);
err = engine->emit_bb_start(request[idx],
@@ -1332,10 +1350,7 @@ static int live_sequential_engines(void *arg)
}
}
- err = i915_request_await_object(request[idx],
- batch->obj, false);
- if (err == 0)
- err = i915_vma_move_to_active(batch, request[idx], 0);
+ err = i915_vma_move_to_active(batch, request[idx], 0);
GEM_BUG_ON(err);
err = engine->emit_bb_start(request[idx],
@@ -1419,9 +1434,18 @@ out_free:
return err;
}
-static int __live_parallel_engine1(void *arg)
+struct parallel_thread {
+ struct kthread_worker *worker;
+ struct kthread_work work;
+ struct intel_engine_cs *engine;
+ int result;
+};
+
+static void __live_parallel_engine1(struct kthread_work *work)
{
- struct intel_engine_cs *engine = arg;
+ struct parallel_thread *thread =
+ container_of(work, typeof(*thread), work);
+ struct intel_engine_cs *engine = thread->engine;
IGT_TIMEOUT(end_time);
unsigned long count;
int err = 0;
@@ -1452,12 +1476,14 @@ static int __live_parallel_engine1(void *arg)
intel_engine_pm_put(engine);
pr_info("%s: %lu request + sync\n", engine->name, count);
- return err;
+ thread->result = err;
}
-static int __live_parallel_engineN(void *arg)
+static void __live_parallel_engineN(struct kthread_work *work)
{
- struct intel_engine_cs *engine = arg;
+ struct parallel_thread *thread =
+ container_of(work, typeof(*thread), work);
+ struct intel_engine_cs *engine = thread->engine;
IGT_TIMEOUT(end_time);
unsigned long count;
int err = 0;
@@ -1479,7 +1505,7 @@ static int __live_parallel_engineN(void *arg)
intel_engine_pm_put(engine);
pr_info("%s: %lu requests\n", engine->name, count);
- return err;
+ thread->result = err;
}
static bool wake_all(struct drm_i915_private *i915)
@@ -1505,9 +1531,11 @@ static int wait_for_all(struct drm_i915_private *i915)
return -ETIME;
}
-static int __live_parallel_spin(void *arg)
+static void __live_parallel_spin(struct kthread_work *work)
{
- struct intel_engine_cs *engine = arg;
+ struct parallel_thread *thread =
+ container_of(work, typeof(*thread), work);
+ struct intel_engine_cs *engine = thread->engine;
struct igt_spinner spin;
struct i915_request *rq;
int err = 0;
@@ -1520,7 +1548,8 @@ static int __live_parallel_spin(void *arg)
if (igt_spinner_init(&spin, engine->gt)) {
wake_all(engine->i915);
- return -ENOMEM;
+ thread->result = -ENOMEM;
+ return;
}
intel_engine_pm_get(engine);
@@ -1553,22 +1582,22 @@ static int __live_parallel_spin(void *arg)
out_spin:
igt_spinner_fini(&spin);
- return err;
+ thread->result = err;
}
static int live_parallel_engines(void *arg)
{
struct drm_i915_private *i915 = arg;
- static int (* const func[])(void *arg) = {
+ static void (* const func[])(struct kthread_work *) = {
__live_parallel_engine1,
__live_parallel_engineN,
__live_parallel_spin,
NULL,
};
const unsigned int nengines = num_uabi_engines(i915);
+ struct parallel_thread *threads;
struct intel_engine_cs *engine;
- int (* const *fn)(void *arg);
- struct task_struct **tsk;
+ void (* const *fn)(struct kthread_work *);
int err = 0;
/*
@@ -1576,8 +1605,8 @@ static int live_parallel_engines(void *arg)
* tests that we load up the system maximally.
*/
- tsk = kcalloc(nengines, sizeof(*tsk), GFP_KERNEL);
- if (!tsk)
+ threads = kcalloc(nengines, sizeof(*threads), GFP_KERNEL);
+ if (!threads)
return -ENOMEM;
for (fn = func; !err && *fn; fn++) {
@@ -1594,37 +1623,44 @@ static int live_parallel_engines(void *arg)
idx = 0;
for_each_uabi_engine(engine, i915) {
- tsk[idx] = kthread_run(*fn, engine,
- "igt/parallel:%s",
- engine->name);
- if (IS_ERR(tsk[idx])) {
- err = PTR_ERR(tsk[idx]);
+ struct kthread_worker *worker;
+
+ worker = kthread_create_worker(0, "igt/parallel:%s",
+ engine->name);
+ if (IS_ERR(worker)) {
+ err = PTR_ERR(worker);
break;
}
- get_task_struct(tsk[idx++]);
- }
- yield(); /* start all threads before we kthread_stop() */
+ threads[idx].worker = worker;
+ threads[idx].result = 0;
+ threads[idx].engine = engine;
+
+ kthread_init_work(&threads[idx].work, *fn);
+ kthread_queue_work(worker, &threads[idx].work);
+ idx++;
+ }
idx = 0;
for_each_uabi_engine(engine, i915) {
int status;
- if (IS_ERR(tsk[idx]))
+ if (!threads[idx].worker)
break;
- status = kthread_stop(tsk[idx]);
+ kthread_flush_work(&threads[idx].work);
+ status = READ_ONCE(threads[idx].result);
if (status && !err)
err = status;
- put_task_struct(tsk[idx++]);
+ kthread_destroy_worker(threads[idx++].worker);
}
if (igt_live_test_end(&t))
err = -EIO;
}
- kfree(tsk);
+ kfree(threads);
return err;
}
@@ -1669,10 +1705,11 @@ static int live_breadcrumbs_smoketest(void *arg)
{
struct drm_i915_private *i915 = arg;
const unsigned int nengines = num_uabi_engines(i915);
- const unsigned int ncpus = num_online_cpus();
+ const unsigned int ncpus = /* saturate with nengines * ncpus */
+ max_t(int, 2, DIV_ROUND_UP(num_online_cpus(), nengines));
unsigned long num_waits, num_fences;
struct intel_engine_cs *engine;
- struct task_struct **threads;
+ struct smoke_thread *threads;
struct igt_live_test live;
intel_wakeref_t wakeref;
struct smoketest *smoke;
@@ -1741,28 +1778,31 @@ static int live_breadcrumbs_smoketest(void *arg)
goto out_flush;
}
/* One ring interleaved between requests from all cpus */
- smoke[idx].max_batch /= num_online_cpus() + 1;
+ smoke[idx].max_batch /= ncpus + 1;
pr_debug("Limiting batches to %d requests on %s\n",
smoke[idx].max_batch, engine->name);
for (n = 0; n < ncpus; n++) {
- struct task_struct *tsk;
+ unsigned int i = idx * ncpus + n;
+ struct kthread_worker *worker;
- tsk = kthread_run(__igt_breadcrumbs_smoketest,
- &smoke[idx], "igt/%d.%d", idx, n);
- if (IS_ERR(tsk)) {
- ret = PTR_ERR(tsk);
+ worker = kthread_create_worker(0, "igt/%d.%d", idx, n);
+ if (IS_ERR(worker)) {
+ ret = PTR_ERR(worker);
goto out_flush;
}
- get_task_struct(tsk);
- threads[idx * ncpus + n] = tsk;
+ threads[i].worker = worker;
+ threads[i].t = &smoke[idx];
+
+ kthread_init_work(&threads[i].work,
+ __igt_breadcrumbs_smoketest);
+ kthread_queue_work(worker, &threads[i].work);
}
idx++;
}
- yield(); /* start all threads before we begin */
msleep(jiffies_to_msecs(i915_selftest.timeout_jiffies));
out_flush:
@@ -1771,17 +1811,19 @@ out_flush:
num_fences = 0;
for_each_uabi_engine(engine, i915) {
for (n = 0; n < ncpus; n++) {
- struct task_struct *tsk = threads[idx * ncpus + n];
+ unsigned int i = idx * ncpus + n;
int err;
- if (!tsk)
+ if (!threads[i].worker)
continue;
- err = kthread_stop(tsk);
+ WRITE_ONCE(threads[i].stop, true);
+ kthread_flush_work(&threads[i].work);
+ err = READ_ONCE(threads[i].result);
if (err < 0 && !ret)
ret = err;
- put_task_struct(tsk);
+ kthread_destroy_worker(threads[i].worker);
}
num_waits += atomic_long_read(&smoke[idx].num_waits);
@@ -2891,9 +2933,18 @@ out:
return err;
}
-static int p_sync0(void *arg)
+struct p_thread {
+ struct perf_stats p;
+ struct kthread_worker *worker;
+ struct kthread_work work;
+ struct intel_engine_cs *engine;
+ int result;
+};
+
+static void p_sync0(struct kthread_work *work)
{
- struct perf_stats *p = arg;
+ struct p_thread *thread = container_of(work, typeof(*thread), work);
+ struct perf_stats *p = &thread->p;
struct intel_engine_cs *engine = p->engine;
struct intel_context *ce;
IGT_TIMEOUT(end_time);
@@ -2902,13 +2953,16 @@ static int p_sync0(void *arg)
int err = 0;
ce = intel_context_create(engine);
- if (IS_ERR(ce))
- return PTR_ERR(ce);
+ if (IS_ERR(ce)) {
+ thread->result = PTR_ERR(ce);
+ return;
+ }
err = intel_context_pin(ce);
if (err) {
intel_context_put(ce);
- return err;
+ thread->result = err;
+ return;
}
if (intel_engine_supports_stats(engine)) {
@@ -2958,12 +3012,13 @@ static int p_sync0(void *arg)
intel_context_unpin(ce);
intel_context_put(ce);
- return err;
+ thread->result = err;
}
-static int p_sync1(void *arg)
+static void p_sync1(struct kthread_work *work)
{
- struct perf_stats *p = arg;
+ struct p_thread *thread = container_of(work, typeof(*thread), work);
+ struct perf_stats *p = &thread->p;
struct intel_engine_cs *engine = p->engine;
struct i915_request *prev = NULL;
struct intel_context *ce;
@@ -2973,13 +3028,16 @@ static int p_sync1(void *arg)
int err = 0;
ce = intel_context_create(engine);
- if (IS_ERR(ce))
- return PTR_ERR(ce);
+ if (IS_ERR(ce)) {
+ thread->result = PTR_ERR(ce);
+ return;
+ }
err = intel_context_pin(ce);
if (err) {
intel_context_put(ce);
- return err;
+ thread->result = err;
+ return;
}
if (intel_engine_supports_stats(engine)) {
@@ -3031,12 +3089,13 @@ static int p_sync1(void *arg)
intel_context_unpin(ce);
intel_context_put(ce);
- return err;
+ thread->result = err;
}
-static int p_many(void *arg)
+static void p_many(struct kthread_work *work)
{
- struct perf_stats *p = arg;
+ struct p_thread *thread = container_of(work, typeof(*thread), work);
+ struct perf_stats *p = &thread->p;
struct intel_engine_cs *engine = p->engine;
struct intel_context *ce;
IGT_TIMEOUT(end_time);
@@ -3045,13 +3104,16 @@ static int p_many(void *arg)
bool busy;
ce = intel_context_create(engine);
- if (IS_ERR(ce))
- return PTR_ERR(ce);
+ if (IS_ERR(ce)) {
+ thread->result = PTR_ERR(ce);
+ return;
+ }
err = intel_context_pin(ce);
if (err) {
intel_context_put(ce);
- return err;
+ thread->result = err;
+ return;
}
if (intel_engine_supports_stats(engine)) {
@@ -3092,26 +3154,23 @@ static int p_many(void *arg)
intel_context_unpin(ce);
intel_context_put(ce);
- return err;
+ thread->result = err;
}
static int perf_parallel_engines(void *arg)
{
struct drm_i915_private *i915 = arg;
- static int (* const func[])(void *arg) = {
+ static void (* const func[])(struct kthread_work *) = {
p_sync0,
p_sync1,
p_many,
NULL,
};
const unsigned int nengines = num_uabi_engines(i915);
+ void (* const *fn)(struct kthread_work *);
struct intel_engine_cs *engine;
- int (* const *fn)(void *arg);
struct pm_qos_request qos;
- struct {
- struct perf_stats p;
- struct task_struct *tsk;
- } *engines;
+ struct p_thread *engines;
int err = 0;
engines = kcalloc(nengines, sizeof(*engines), GFP_KERNEL);
@@ -3134,36 +3193,45 @@ static int perf_parallel_engines(void *arg)
idx = 0;
for_each_uabi_engine(engine, i915) {
+ struct kthread_worker *worker;
+
intel_engine_pm_get(engine);
memset(&engines[idx].p, 0, sizeof(engines[idx].p));
- engines[idx].p.engine = engine;
- engines[idx].tsk = kthread_run(*fn, &engines[idx].p,
- "igt:%s", engine->name);
- if (IS_ERR(engines[idx].tsk)) {
- err = PTR_ERR(engines[idx].tsk);
+ worker = kthread_create_worker(0, "igt:%s",
+ engine->name);
+ if (IS_ERR(worker)) {
+ err = PTR_ERR(worker);
intel_engine_pm_put(engine);
break;
}
- get_task_struct(engines[idx++].tsk);
- }
+ engines[idx].worker = worker;
+ engines[idx].result = 0;
+ engines[idx].p.engine = engine;
+ engines[idx].engine = engine;
- yield(); /* start all threads before we kthread_stop() */
+ kthread_init_work(&engines[idx].work, *fn);
+ kthread_queue_work(worker, &engines[idx].work);
+ idx++;
+ }
idx = 0;
for_each_uabi_engine(engine, i915) {
int status;
- if (IS_ERR(engines[idx].tsk))
+ if (!engines[idx].worker)
break;
- status = kthread_stop(engines[idx].tsk);
+ kthread_flush_work(&engines[idx].work);
+ status = READ_ONCE(engines[idx].result);
if (status && !err)
err = status;
intel_engine_pm_put(engine);
- put_task_struct(engines[idx++].tsk);
+
+ kthread_destroy_worker(engines[idx].worker);
+ idx++;
}
if (igt_live_test_end(&t))
diff --git a/drivers/gpu/drm/i915/selftests/igt_spinner.c b/drivers/gpu/drm/i915/selftests/igt_spinner.c
index 0c22594ae274..16978ac59797 100644
--- a/drivers/gpu/drm/i915/selftests/igt_spinner.c
+++ b/drivers/gpu/drm/i915/selftests/igt_spinner.c
@@ -119,22 +119,6 @@ static u64 hws_address(const struct i915_vma *hws,
return hws->node.start + seqno_offset(rq->fence.context);
}
-static int move_to_active(struct i915_vma *vma,
- struct i915_request *rq,
- unsigned int flags)
-{
- int err;
-
- i915_vma_lock(vma);
- err = i915_request_await_object(rq, vma->obj,
- flags & EXEC_OBJECT_WRITE);
- if (err == 0)
- err = i915_vma_move_to_active(vma, rq, flags);
- i915_vma_unlock(vma);
-
- return err;
-}
-
struct i915_request *
igt_spinner_create_request(struct igt_spinner *spin,
struct intel_context *ce,
@@ -165,11 +149,11 @@ igt_spinner_create_request(struct igt_spinner *spin,
if (IS_ERR(rq))
return ERR_CAST(rq);
- err = move_to_active(vma, rq, 0);
+ err = igt_vma_move_to_active_unlocked(vma, rq, 0);
if (err)
goto cancel_rq;
- err = move_to_active(hws, rq, 0);
+ err = igt_vma_move_to_active_unlocked(hws, rq, 0);
if (err)
goto cancel_rq;
diff --git a/drivers/gpu/drm/i915/selftests/intel_uncore.c b/drivers/gpu/drm/i915/selftests/intel_uncore.c
index fda9bb79c049..e4281508d580 100644
--- a/drivers/gpu/drm/i915/selftests/intel_uncore.c
+++ b/drivers/gpu/drm/i915/selftests/intel_uncore.c
@@ -70,6 +70,8 @@ static int intel_shadow_table_check(void)
{ gen12_shadowed_regs, ARRAY_SIZE(gen12_shadowed_regs) },
{ dg2_shadowed_regs, ARRAY_SIZE(dg2_shadowed_regs) },
{ pvc_shadowed_regs, ARRAY_SIZE(pvc_shadowed_regs) },
+ { mtl_shadowed_regs, ARRAY_SIZE(mtl_shadowed_regs) },
+ { xelpmp_shadowed_regs, ARRAY_SIZE(xelpmp_shadowed_regs) },
};
const struct i915_range *range;
unsigned int i, j;
@@ -117,6 +119,8 @@ int intel_uncore_mock_selftests(void)
{ __gen12_fw_ranges, ARRAY_SIZE(__gen12_fw_ranges), true },
{ __xehp_fw_ranges, ARRAY_SIZE(__xehp_fw_ranges), true },
{ __pvc_fw_ranges, ARRAY_SIZE(__pvc_fw_ranges), true },
+ { __mtl_fw_ranges, ARRAY_SIZE(__mtl_fw_ranges), true },
+ { __xelpmp_fw_ranges, ARRAY_SIZE(__xelpmp_fw_ranges), true },
};
int err, i;
diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
index fff11c90f1fa..f6a7c0bd2955 100644
--- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c
+++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c
@@ -67,7 +67,6 @@ static void mock_device_release(struct drm_device *dev)
intel_gt_driver_remove(to_gt(i915));
i915_gem_drain_workqueue(i915);
- i915_gem_drain_freed_objects(i915);
mock_fini_ggtt(to_gt(i915)->ggtt);
destroy_workqueue(i915->wq);
diff --git a/drivers/gpu/drm/i915/selftests/mock_region.c b/drivers/gpu/drm/i915/selftests/mock_region.c
index bac21fe84ca5..6324eb32d4dd 100644
--- a/drivers/gpu/drm/i915/selftests/mock_region.c
+++ b/drivers/gpu/drm/i915/selftests/mock_region.c
@@ -41,7 +41,7 @@ static int mock_region_get_pages(struct drm_i915_gem_object *obj)
}
pages = &obj->mm.rsgt->table;
- __i915_gem_object_set_pages(obj, pages, i915_sg_dma_sizes(pages->sgl));
+ __i915_gem_object_set_pages(obj, pages);
return 0;
diff --git a/drivers/gpu/drm/i915/vlv_sideband.c b/drivers/gpu/drm/i915/vlv_sideband.c
index c26001300ebd..6eea6e1a99c0 100644
--- a/drivers/gpu/drm/i915/vlv_sideband.c
+++ b/drivers/gpu/drm/i915/vlv_sideband.c
@@ -8,6 +8,8 @@
#include "i915_reg.h"
#include "vlv_sideband.h"
+#include "display/intel_dpio_phy.h"
+
/*
* IOSF sideband, see VLV2_SidebandMsg_HAS.docx and
* VLV_VLV2_PUNIT_HAS_0.8.docx
diff --git a/drivers/gpu/drm/i915/vlv_suspend.c b/drivers/gpu/drm/i915/vlv_suspend.c
index 664fde244f59..02e63ed77f60 100644
--- a/drivers/gpu/drm/i915/vlv_suspend.c
+++ b/drivers/gpu/drm/i915/vlv_suspend.c
@@ -194,7 +194,6 @@ static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *i915)
{
struct vlv_s0ix_state *s = i915->vlv_s0ix_state;
struct intel_uncore *uncore = &i915->uncore;
- u32 val;
int i;
if (!s)
@@ -262,15 +261,11 @@ static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *i915)
* be restored, as they are used to control the s0ix suspend/resume
* sequence by the caller.
*/
- val = intel_uncore_read(uncore, VLV_GTLC_WAKE_CTRL);
- val &= VLV_GTLC_ALLOWWAKEREQ;
- val |= s->gtlc_wake_ctrl & ~VLV_GTLC_ALLOWWAKEREQ;
- intel_uncore_write(uncore, VLV_GTLC_WAKE_CTRL, val);
+ intel_uncore_rmw(uncore, VLV_GTLC_WAKE_CTRL, ~VLV_GTLC_ALLOWWAKEREQ,
+ s->gtlc_wake_ctrl & ~VLV_GTLC_ALLOWWAKEREQ);
- val = intel_uncore_read(uncore, VLV_GTLC_SURVIVABILITY_REG);
- val &= VLV_GFX_CLK_FORCE_ON_BIT;
- val |= s->gtlc_survive & ~VLV_GFX_CLK_FORCE_ON_BIT;
- intel_uncore_write(uncore, VLV_GTLC_SURVIVABILITY_REG, val);
+ intel_uncore_rmw(uncore, VLV_GTLC_SURVIVABILITY_REG, ~VLV_GFX_CLK_FORCE_ON_BIT,
+ s->gtlc_survive & ~VLV_GFX_CLK_FORCE_ON_BIT);
intel_uncore_write(uncore, VLV_PMWGICZ, s->pmwgicz);
@@ -308,14 +303,10 @@ static int vlv_wait_for_pw_status(struct drm_i915_private *i915,
static int vlv_force_gfx_clock(struct drm_i915_private *i915, bool force_on)
{
struct intel_uncore *uncore = &i915->uncore;
- u32 val;
int err;
- val = intel_uncore_read(uncore, VLV_GTLC_SURVIVABILITY_REG);
- val &= ~VLV_GFX_CLK_FORCE_ON_BIT;
- if (force_on)
- val |= VLV_GFX_CLK_FORCE_ON_BIT;
- intel_uncore_write(uncore, VLV_GTLC_SURVIVABILITY_REG, val);
+ intel_uncore_rmw(uncore, VLV_GTLC_SURVIVABILITY_REG, VLV_GFX_CLK_FORCE_ON_BIT,
+ force_on ? VLV_GFX_CLK_FORCE_ON_BIT : 0);
if (!force_on)
return 0;
@@ -340,11 +331,8 @@ static int vlv_allow_gt_wake(struct drm_i915_private *i915, bool allow)
u32 val;
int err;
- val = intel_uncore_read(uncore, VLV_GTLC_WAKE_CTRL);
- val &= ~VLV_GTLC_ALLOWWAKEREQ;
- if (allow)
- val |= VLV_GTLC_ALLOWWAKEREQ;
- intel_uncore_write(uncore, VLV_GTLC_WAKE_CTRL, val);
+ intel_uncore_rmw(uncore, VLV_GTLC_WAKE_CTRL, VLV_GTLC_ALLOWWAKEREQ,
+ allow ? VLV_GTLC_ALLOWWAKEREQ : 0);
intel_uncore_posting_read(uncore, VLV_GTLC_WAKE_CTRL);
mask = VLV_GTLC_ALLOWWAKEACK;
diff --git a/drivers/gpu/drm/imx/dcss/dcss-kms.c b/drivers/gpu/drm/imx/dcss/dcss-kms.c
index b4f82ebca532..18df3888b7f9 100644
--- a/drivers/gpu/drm/imx/dcss/dcss-kms.c
+++ b/drivers/gpu/drm/imx/dcss/dcss-kms.c
@@ -7,7 +7,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge_connector.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_of.h>
@@ -21,7 +21,6 @@ DEFINE_DRM_GEM_DMA_FOPS(dcss_cma_fops);
static const struct drm_mode_config_funcs dcss_drm_mode_config_funcs = {
.fb_create = drm_gem_fb_create,
- .output_poll_changed = drm_fb_helper_output_poll_changed,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit,
};
diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c
index 8dd8b0f912af..e060fa6cbcb9 100644
--- a/drivers/gpu/drm/imx/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/imx-drm-core.c
@@ -16,7 +16,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_managed.h>
diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c
index 41799011f73b..c45fc8f4744d 100644
--- a/drivers/gpu/drm/imx/imx-ldb.c
+++ b/drivers/gpu/drm/imx/imx-ldb.c
@@ -7,6 +7,7 @@
#include <linux/clk.h>
#include <linux/component.h>
+#include <linux/i2c.h>
#include <linux/media-bus-format.h>
#include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
@@ -23,7 +24,6 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_managed.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c
index ab4d1c878fda..d6832f506322 100644
--- a/drivers/gpu/drm/imx/imx-tve.c
+++ b/drivers/gpu/drm/imx/imx-tve.c
@@ -19,7 +19,6 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_managed.h>
#include <drm/drm_probe_helper.h>
#include <drm/drm_simple_kms_helper.h>
diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c
index 06723b2e9b84..0fa0b590830b 100644
--- a/drivers/gpu/drm/imx/parallel-display.c
+++ b/drivers/gpu/drm/imx/parallel-display.c
@@ -8,6 +8,7 @@
#include <linux/component.h>
#include <linux/media-bus-format.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/videodev2.h>
@@ -16,7 +17,6 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_managed.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index ab0515d2c420..3d5af44bf92d 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -32,7 +32,7 @@
#include <drm/drm_encoder.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_fb_dma_helper.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -1018,7 +1018,6 @@ static const struct drm_bridge_funcs ingenic_drm_bridge_funcs = {
static const struct drm_mode_config_funcs ingenic_drm_mode_config_funcs = {
.fb_create = ingenic_drm_gem_fb_create,
- .output_poll_changed = drm_fb_helper_output_poll_changed,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit,
};
@@ -1629,7 +1628,11 @@ static int ingenic_drm_init(void)
return err;
}
- return platform_driver_register(&ingenic_drm_driver);
+ err = platform_driver_register(&ingenic_drm_driver);
+ if (IS_ENABLED(CONFIG_DRM_INGENIC_IPU) && err)
+ platform_driver_unregister(ingenic_ipu_driver_ptr);
+
+ return err;
}
module_init(ingenic_drm_init);
diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 2382ccb3ee99..d29c678f6c91 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -15,7 +15,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_module.h>
diff --git a/drivers/gpu/drm/kmb/kmb_plane.c b/drivers/gpu/drm/kmb/kmb_plane.c
index a42f63f6f957..d172a302f902 100644
--- a/drivers/gpu/drm/kmb/kmb_plane.c
+++ b/drivers/gpu/drm/kmb/kmb_plane.c
@@ -9,7 +9,6 @@
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_dma_helper.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_dma_helper.h>
diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c
index e82931712d8a..ff003403fbbc 100644
--- a/drivers/gpu/drm/lima/lima_sched.c
+++ b/drivers/gpu/drm/lima/lima_sched.c
@@ -371,7 +371,7 @@ static void lima_sched_build_error_task_list(struct lima_sched_task *task)
} else {
buffer_chunk->size = lima_bo_size(bo);
- ret = drm_gem_shmem_vmap(&bo->base, &map);
+ ret = drm_gem_vmap_unlocked(&bo->base.base, &map);
if (ret) {
kvfree(et);
goto out;
@@ -379,7 +379,7 @@ static void lima_sched_build_error_task_list(struct lima_sched_task *task)
memcpy(buffer_chunk + 1, map.vaddr, buffer_chunk->size);
- drm_gem_shmem_vunmap(&bo->base, &map);
+ drm_gem_vunmap_unlocked(&bo->base.base, &map);
}
buffer_chunk = (void *)(buffer_chunk + 1) + buffer_chunk->size;
diff --git a/drivers/gpu/drm/logicvc/logicvc_drm.c b/drivers/gpu/drm/logicvc/logicvc_drm.c
index cc9a4e965f77..9de24d9f0c96 100644
--- a/drivers/gpu/drm/logicvc/logicvc_drm.c
+++ b/drivers/gpu/drm/logicvc/logicvc_drm.c
@@ -17,7 +17,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_print.h>
diff --git a/drivers/gpu/drm/logicvc/logicvc_mode.c b/drivers/gpu/drm/logicvc/logicvc_mode.c
index d8207ffda1af..9971950ebd4e 100644
--- a/drivers/gpu/drm/logicvc/logicvc_mode.c
+++ b/drivers/gpu/drm/logicvc/logicvc_mode.c
@@ -10,7 +10,6 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_mode_config.h>
@@ -26,7 +25,6 @@
static const struct drm_mode_config_funcs logicvc_mode_config_funcs = {
.fb_create = drm_gem_fb_create,
- .output_poll_changed = drm_fb_helper_output_poll_changed,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit,
};
diff --git a/drivers/gpu/drm/mcde/mcde_drv.c b/drivers/gpu/drm/mcde/mcde_drv.c
index 1c4482ad507d..4aedb050d2a5 100644
--- a/drivers/gpu/drm/mcde/mcde_drv.c
+++ b/drivers/gpu/drm/mcde/mcde_drv.c
@@ -69,7 +69,7 @@
#include <drm/drm_bridge.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_dma_helper.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
@@ -203,7 +203,6 @@ DEFINE_DRM_GEM_DMA_FOPS(drm_fops);
static const struct drm_driver mcde_drm_driver = {
.driver_features =
DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
- .lastclose = drm_fb_helper_lastclose,
.ioctls = NULL,
.fops = &drm_fops,
.name = "mcde",
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index 002b0f6cae1a..84daeaffab6a 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -29,17 +29,22 @@
#define DISP_REG_OVL_DATAPATH_CON 0x0024
#define OVL_LAYER_SMI_ID_EN BIT(0)
#define OVL_BGCLR_SEL_IN BIT(2)
+#define OVL_LAYER_AFBC_EN(n) BIT(4+n)
#define DISP_REG_OVL_ROI_BGCLR 0x0028
#define DISP_REG_OVL_SRC_CON 0x002c
#define DISP_REG_OVL_CON(n) (0x0030 + 0x20 * (n))
#define DISP_REG_OVL_SRC_SIZE(n) (0x0038 + 0x20 * (n))
#define DISP_REG_OVL_OFFSET(n) (0x003c + 0x20 * (n))
+#define DISP_REG_OVL_PITCH_MSB(n) (0x0040 + 0x20 * (n))
+#define OVL_PITCH_MSB_2ND_SUBBUF BIT(16)
#define DISP_REG_OVL_PITCH(n) (0x0044 + 0x20 * (n))
#define DISP_REG_OVL_RDMA_CTRL(n) (0x00c0 + 0x20 * (n))
#define DISP_REG_OVL_RDMA_GMC(n) (0x00c8 + 0x20 * (n))
#define DISP_REG_OVL_ADDR_MT2701 0x0040
#define DISP_REG_OVL_ADDR_MT8173 0x0f40
#define DISP_REG_OVL_ADDR(ovl, n) ((ovl)->data->addr + 0x20 * (n))
+#define DISP_REG_OVL_HDR_ADDR(ovl, n) ((ovl)->data->addr + 0x20 * (n) + 0x04)
+#define DISP_REG_OVL_HDR_PITCH(ovl, n) ((ovl)->data->addr + 0x20 * (n) + 0x08)
#define GMC_THRESHOLD_BITS 16
#define GMC_THRESHOLD_HIGH ((1 << GMC_THRESHOLD_BITS) / 4)
@@ -67,6 +72,7 @@ struct mtk_disp_ovl_data {
unsigned int layer_nr;
bool fmt_rgb565_is_0;
bool smi_id_en;
+ bool supports_afbc;
};
/*
@@ -172,7 +178,14 @@ void mtk_ovl_stop(struct device *dev)
reg = reg & ~OVL_LAYER_SMI_ID_EN;
writel_relaxed(reg, ovl->regs + DISP_REG_OVL_DATAPATH_CON);
}
+}
+static void mtk_ovl_set_afbc(struct mtk_disp_ovl *ovl, struct cmdq_pkt *cmdq_pkt,
+ int idx, bool enabled)
+{
+ mtk_ddp_write_mask(cmdq_pkt, enabled ? OVL_LAYER_AFBC_EN(idx) : 0,
+ &ovl->cmdq_reg, ovl->regs,
+ DISP_REG_OVL_DATAPATH_CON, OVL_LAYER_AFBC_EN(idx));
}
void mtk_ovl_config(struct device *dev, unsigned int w,
@@ -310,11 +323,23 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
struct mtk_disp_ovl *ovl = dev_get_drvdata(dev);
struct mtk_plane_pending_state *pending = &state->pending;
unsigned int addr = pending->addr;
- unsigned int pitch = pending->pitch & 0xffff;
+ unsigned int hdr_addr = pending->hdr_addr;
+ unsigned int pitch = pending->pitch;
+ unsigned int hdr_pitch = pending->hdr_pitch;
unsigned int fmt = pending->format;
unsigned int offset = (pending->y << 16) | pending->x;
unsigned int src_size = (pending->height << 16) | pending->width;
unsigned int con;
+ bool is_afbc = pending->modifier != DRM_FORMAT_MOD_LINEAR;
+ union overlay_pitch {
+ struct split_pitch {
+ u16 lsb;
+ u16 msb;
+ } split_pitch;
+ u32 pitch;
+ } overlay_pitch;
+
+ overlay_pitch.pitch = pitch;
if (!pending->enable) {
mtk_ovl_layer_off(dev, idx, cmdq_pkt);
@@ -335,9 +360,12 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
addr += pending->pitch - 1;
}
+ if (ovl->data->supports_afbc)
+ mtk_ovl_set_afbc(ovl, cmdq_pkt, idx, is_afbc);
+
mtk_ddp_write_relaxed(cmdq_pkt, con, &ovl->cmdq_reg, ovl->regs,
DISP_REG_OVL_CON(idx));
- mtk_ddp_write_relaxed(cmdq_pkt, pitch, &ovl->cmdq_reg, ovl->regs,
+ mtk_ddp_write_relaxed(cmdq_pkt, overlay_pitch.split_pitch.lsb, &ovl->cmdq_reg, ovl->regs,
DISP_REG_OVL_PITCH(idx));
mtk_ddp_write_relaxed(cmdq_pkt, src_size, &ovl->cmdq_reg, ovl->regs,
DISP_REG_OVL_SRC_SIZE(idx));
@@ -346,6 +374,20 @@ void mtk_ovl_layer_config(struct device *dev, unsigned int idx,
mtk_ddp_write_relaxed(cmdq_pkt, addr, &ovl->cmdq_reg, ovl->regs,
DISP_REG_OVL_ADDR(ovl, idx));
+ if (is_afbc) {
+ mtk_ddp_write_relaxed(cmdq_pkt, hdr_addr, &ovl->cmdq_reg, ovl->regs,
+ DISP_REG_OVL_HDR_ADDR(ovl, idx));
+ mtk_ddp_write_relaxed(cmdq_pkt,
+ OVL_PITCH_MSB_2ND_SUBBUF | overlay_pitch.split_pitch.msb,
+ &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH_MSB(idx));
+ mtk_ddp_write_relaxed(cmdq_pkt, hdr_pitch, &ovl->cmdq_reg, ovl->regs,
+ DISP_REG_OVL_HDR_PITCH(ovl, idx));
+ } else {
+ mtk_ddp_write_relaxed(cmdq_pkt,
+ overlay_pitch.split_pitch.msb,
+ &ovl->cmdq_reg, ovl->regs, DISP_REG_OVL_PITCH_MSB(idx));
+ }
+
mtk_ovl_layer_on(dev, idx, cmdq_pkt);
}
@@ -492,6 +534,15 @@ static const struct mtk_disp_ovl_data mt8192_ovl_2l_driver_data = {
.smi_id_en = true,
};
+static const struct mtk_disp_ovl_data mt8195_ovl_driver_data = {
+ .addr = DISP_REG_OVL_ADDR_MT8173,
+ .gmc_bits = 10,
+ .layer_nr = 4,
+ .fmt_rgb565_is_0 = true,
+ .smi_id_en = true,
+ .supports_afbc = true,
+};
+
static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {
{ .compatible = "mediatek,mt2701-disp-ovl",
.data = &mt2701_ovl_driver_data},
@@ -505,6 +556,8 @@ static const struct of_device_id mtk_disp_ovl_driver_dt_match[] = {
.data = &mt8192_ovl_driver_data},
{ .compatible = "mediatek,mt8192-disp-ovl-2l",
.data = &mt8192_ovl_2l_driver_data},
+ { .compatible = "mediatek,mt8195-disp-ovl",
+ .data = &mt8195_ovl_driver_data},
{},
};
MODULE_DEVICE_TABLE(of, mtk_disp_ovl_driver_dt_match);
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
index 508a6d994e83..4317595a15d1 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -461,9 +461,6 @@ static void mtk_dpi_power_off(struct mtk_dpi *dpi)
if (--dpi->refcount != 0)
return;
- if (dpi->pinctrl && dpi->pins_gpio)
- pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio);
-
mtk_dpi_disable(dpi);
clk_disable_unprepare(dpi->pixel_clk);
clk_disable_unprepare(dpi->engine_clk);
@@ -488,9 +485,6 @@ static int mtk_dpi_power_on(struct mtk_dpi *dpi)
goto err_pixel;
}
- if (dpi->pinctrl && dpi->pins_dpi)
- pinctrl_select_state(dpi->pinctrl, dpi->pins_dpi);
-
return 0;
err_pixel:
@@ -721,12 +715,18 @@ static void mtk_dpi_bridge_disable(struct drm_bridge *bridge)
struct mtk_dpi *dpi = bridge_to_dpi(bridge);
mtk_dpi_power_off(dpi);
+
+ if (dpi->pinctrl && dpi->pins_gpio)
+ pinctrl_select_state(dpi->pinctrl, dpi->pins_gpio);
}
static void mtk_dpi_bridge_enable(struct drm_bridge *bridge)
{
struct mtk_dpi *dpi = bridge_to_dpi(bridge);
+ if (dpi->pinctrl && dpi->pins_dpi)
+ pinctrl_select_state(dpi->pinctrl, dpi->pins_dpi);
+
mtk_dpi_power_on(dpi);
mtk_dpi_set_display_mode(dpi, &dpi->mode);
mtk_dpi_enable(dpi);
@@ -929,6 +929,20 @@ static const struct mtk_dpi_conf mt8183_conf = {
.csc_enable_bit = CSC_ENABLE,
};
+static const struct mtk_dpi_conf mt8188_dpintf_conf = {
+ .cal_factor = mt8195_dpintf_calculate_factor,
+ .max_clock_khz = 600000,
+ .output_fmts = mt8195_output_fmts,
+ .num_output_fmts = ARRAY_SIZE(mt8195_output_fmts),
+ .pixels_per_iter = 4,
+ .input_2pixel = false,
+ .dimension_mask = DPINTF_HPW_MASK,
+ .hvsize_mask = DPINTF_HSIZE_MASK,
+ .channel_swap_shift = DPINTF_CH_SWAP,
+ .yuv422_en_bit = DPINTF_YUV422_EN,
+ .csc_enable_bit = DPINTF_CSC_ENABLE,
+};
+
static const struct mtk_dpi_conf mt8192_conf = {
.cal_factor = mt8183_calculate_factor,
.reg_h_fre_con = 0xe0,
@@ -1079,6 +1093,9 @@ static const struct of_device_id mtk_dpi_of_ids[] = {
{ .compatible = "mediatek,mt8183-dpi",
.data = &mt8183_conf,
},
+ { .compatible = "mediatek,mt8188-dp-intf",
+ .data = &mt8188_dpintf_conf,
+ },
{ .compatible = "mediatek,mt8192-dpi",
.data = &mt8192_conf,
},
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 91f58db5915f..cd5b18ef7951 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -17,7 +17,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem.h>
#include <drm/drm_gem_dma_helper.h>
@@ -387,6 +387,12 @@ static int mtk_drm_kms_init(struct drm_device *drm)
goto put_mutex_dev;
/*
+ * Ensure internal panels are at the top of the connector list before
+ * crtc creation.
+ */
+ drm_helper_move_panel_connectors_to_head(drm);
+
+ /*
* We currently support two fixed data streams, each optional,
* and each statically assigned to a crtc:
* OVL0 -> COLOR0 -> AAL -> OD -> RDMA0 -> UFOE -> DSI0 ...
@@ -631,6 +637,8 @@ static const struct of_device_id mtk_ddp_comp_dt_ids[] = {
.data = (void *)MTK_DPI },
{ .compatible = "mediatek,mt8183-dpi",
.data = (void *)MTK_DPI },
+ { .compatible = "mediatek,mt8188-dp-intf",
+ .data = (void *)MTK_DP_INTF },
{ .compatible = "mediatek,mt8192-dpi",
.data = (void *)MTK_DPI },
{ .compatible = "mediatek,mt8195-dp-intf",
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
index 2f5e007dd380..d54fbf34b000 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c
@@ -11,6 +11,7 @@
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
+#include <linux/align.h>
#include "mtk_drm_crtc.h"
#include "mtk_drm_ddp_comp.h"
@@ -32,6 +33,14 @@ static const u32 formats[] = {
DRM_FORMAT_YUYV,
};
+static const u64 modifiers[] = {
+ DRM_FORMAT_MOD_LINEAR,
+ DRM_FORMAT_MOD_ARM_AFBC(AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
+ AFBC_FORMAT_MOD_SPLIT |
+ AFBC_FORMAT_MOD_SPARSE),
+ DRM_FORMAT_MOD_INVALID,
+};
+
static void mtk_plane_reset(struct drm_plane *plane)
{
struct mtk_plane_state *state;
@@ -51,6 +60,7 @@ static void mtk_plane_reset(struct drm_plane *plane)
state->base.plane = plane;
state->pending.format = DRM_FORMAT_RGB565;
+ state->pending.modifier = DRM_FORMAT_MOD_LINEAR;
}
static struct drm_plane_state *mtk_plane_duplicate_state(struct drm_plane *plane)
@@ -71,6 +81,32 @@ static struct drm_plane_state *mtk_plane_duplicate_state(struct drm_plane *plane
return &state->base;
}
+static bool mtk_plane_format_mod_supported(struct drm_plane *plane,
+ uint32_t format,
+ uint64_t modifier)
+{
+ if (modifier == DRM_FORMAT_MOD_LINEAR)
+ return true;
+
+ if (modifier != DRM_FORMAT_MOD_ARM_AFBC(
+ AFBC_FORMAT_MOD_BLOCK_SIZE_32x8 |
+ AFBC_FORMAT_MOD_SPLIT |
+ AFBC_FORMAT_MOD_SPARSE))
+ return false;
+
+ if (format != DRM_FORMAT_XRGB8888 &&
+ format != DRM_FORMAT_ARGB8888 &&
+ format != DRM_FORMAT_BGRX8888 &&
+ format != DRM_FORMAT_BGRA8888 &&
+ format != DRM_FORMAT_ABGR8888 &&
+ format != DRM_FORMAT_XBGR8888 &&
+ format != DRM_FORMAT_RGB888 &&
+ format != DRM_FORMAT_BGR888)
+ return false;
+
+ return true;
+}
+
static void mtk_drm_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state)
{
@@ -119,21 +155,52 @@ static void mtk_plane_update_new_state(struct drm_plane_state *new_state,
struct drm_gem_object *gem;
struct mtk_drm_gem_obj *mtk_gem;
unsigned int pitch, format;
+ u64 modifier;
dma_addr_t addr;
+ dma_addr_t hdr_addr = 0;
+ unsigned int hdr_pitch = 0;
gem = fb->obj[0];
mtk_gem = to_mtk_gem_obj(gem);
addr = mtk_gem->dma_addr;
pitch = fb->pitches[0];
format = fb->format->format;
+ modifier = fb->modifier;
- addr += (new_state->src.x1 >> 16) * fb->format->cpp[0];
- addr += (new_state->src.y1 >> 16) * pitch;
+ if (modifier == DRM_FORMAT_MOD_LINEAR) {
+ addr += (new_state->src.x1 >> 16) * fb->format->cpp[0];
+ addr += (new_state->src.y1 >> 16) * pitch;
+ } else {
+ int width_in_blocks = ALIGN(fb->width, AFBC_DATA_BLOCK_WIDTH)
+ / AFBC_DATA_BLOCK_WIDTH;
+ int height_in_blocks = ALIGN(fb->height, AFBC_DATA_BLOCK_HEIGHT)
+ / AFBC_DATA_BLOCK_HEIGHT;
+ int x_offset_in_blocks = (new_state->src.x1 >> 16) / AFBC_DATA_BLOCK_WIDTH;
+ int y_offset_in_blocks = (new_state->src.y1 >> 16) / AFBC_DATA_BLOCK_HEIGHT;
+ int hdr_size;
+
+ hdr_pitch = width_in_blocks * AFBC_HEADER_BLOCK_SIZE;
+ pitch = width_in_blocks * AFBC_DATA_BLOCK_WIDTH *
+ AFBC_DATA_BLOCK_HEIGHT * fb->format->cpp[0];
+
+ hdr_size = ALIGN(hdr_pitch * height_in_blocks, AFBC_HEADER_ALIGNMENT);
+
+ hdr_addr = addr + hdr_pitch * y_offset_in_blocks +
+ AFBC_HEADER_BLOCK_SIZE * x_offset_in_blocks;
+ /* The data plane is offset by 1 additional block. */
+ addr = addr + hdr_size +
+ pitch * y_offset_in_blocks +
+ AFBC_DATA_BLOCK_WIDTH * AFBC_DATA_BLOCK_HEIGHT *
+ fb->format->cpp[0] * (x_offset_in_blocks + 1);
+ }
mtk_plane_state->pending.enable = true;
mtk_plane_state->pending.pitch = pitch;
+ mtk_plane_state->pending.hdr_pitch = hdr_pitch;
mtk_plane_state->pending.format = format;
+ mtk_plane_state->pending.modifier = modifier;
mtk_plane_state->pending.addr = addr;
+ mtk_plane_state->pending.hdr_addr = hdr_addr;
mtk_plane_state->pending.x = new_state->dst.x1;
mtk_plane_state->pending.y = new_state->dst.y1;
mtk_plane_state->pending.width = drm_rect_width(&new_state->dst);
@@ -172,6 +239,7 @@ static const struct drm_plane_funcs mtk_plane_funcs = {
.reset = mtk_plane_reset,
.atomic_duplicate_state = mtk_plane_duplicate_state,
.atomic_destroy_state = mtk_drm_plane_destroy_state,
+ .format_mod_supported = mtk_plane_format_mod_supported,
};
static int mtk_plane_atomic_check(struct drm_plane *plane,
@@ -253,7 +321,7 @@ int mtk_plane_init(struct drm_device *dev, struct drm_plane *plane,
err = drm_universal_plane_init(dev, plane, possible_crtcs,
&mtk_plane_funcs, formats,
- ARRAY_SIZE(formats), NULL, type, NULL);
+ ARRAY_SIZE(formats), modifiers, type, NULL);
if (err) {
DRM_ERROR("failed to initialize plane\n");
return err;
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.h b/drivers/gpu/drm/mediatek/mtk_drm_plane.h
index 2d5ec66e3df1..8f39011cdbfc 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_plane.h
+++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.h
@@ -10,12 +10,20 @@
#include <drm/drm_crtc.h>
#include <linux/types.h>
+#define AFBC_DATA_BLOCK_WIDTH 32
+#define AFBC_DATA_BLOCK_HEIGHT 8
+#define AFBC_HEADER_BLOCK_SIZE 16
+#define AFBC_HEADER_ALIGNMENT 1024
+
struct mtk_plane_pending_state {
bool config;
bool enable;
dma_addr_t addr;
+ dma_addr_t hdr_addr;
unsigned int pitch;
+ unsigned int hdr_pitch;
unsigned int format;
+ unsigned long long modifier;
unsigned int x;
unsigned int y;
unsigned int width;
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index 4c80b6896dc3..0a8e0a13f516 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -1202,9 +1202,10 @@ static enum drm_connector_status mtk_hdmi_detect(struct mtk_hdmi *hdmi)
return mtk_hdmi_update_plugged_status(hdmi);
}
-static int mtk_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
- const struct drm_display_info *info,
- const struct drm_display_mode *mode)
+static enum drm_mode_status
+mtk_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
+ const struct drm_display_info *info,
+ const struct drm_display_mode *mode)
{
struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
struct drm_bridge *next_bridge;
@@ -1217,7 +1218,7 @@ static int mtk_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
if (next_bridge) {
struct drm_display_mode adjusted_mode;
- drm_mode_copy(&adjusted_mode, mode);
+ drm_mode_init(&adjusted_mode, mode);
if (!drm_bridge_chain_mode_fixup(next_bridge, mode,
&adjusted_mode))
return MODE_BAD;
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
index 3b24a924b7b9..79bfe3938d3c 100644
--- a/drivers/gpu/drm/meson/meson_drv.c
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -18,7 +18,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_modeset_helper_vtables.h>
diff --git a/drivers/gpu/drm/meson/meson_encoder_cvbs.c b/drivers/gpu/drm/meson/meson_encoder_cvbs.c
index 5675bc2a92cf..3f73b211fa8e 100644
--- a/drivers/gpu/drm/meson/meson_encoder_cvbs.c
+++ b/drivers/gpu/drm/meson/meson_encoder_cvbs.c
@@ -116,9 +116,10 @@ static int meson_encoder_cvbs_get_modes(struct drm_bridge *bridge,
return i;
}
-static int meson_encoder_cvbs_mode_valid(struct drm_bridge *bridge,
- const struct drm_display_info *display_info,
- const struct drm_display_mode *mode)
+static enum drm_mode_status
+meson_encoder_cvbs_mode_valid(struct drm_bridge *bridge,
+ const struct drm_display_info *display_info,
+ const struct drm_display_mode *mode)
{
if (meson_cvbs_get_mode(mode))
return MODE_OK;
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c
index ece6cd102dbb..976f0ab2006b 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.c
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -11,6 +11,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_drv.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_file.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_managed.h>
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
index f0c2349404b4..9e604dbb8e44 100644
--- a/drivers/gpu/drm/mgag200/mgag200_drv.h
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -18,7 +18,6 @@
#include <drm/drm_connector.h>
#include <drm/drm_crtc.h>
#include <drm/drm_encoder.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_gem.h>
#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_plane.h>
diff --git a/drivers/gpu/drm/mgag200/mgag200_g200se.c b/drivers/gpu/drm/mgag200/mgag200_g200se.c
index be389ed91cbd..bd6e573c9a1a 100644
--- a/drivers/gpu/drm/mgag200/mgag200_g200se.c
+++ b/drivers/gpu/drm/mgag200/mgag200_g200se.c
@@ -284,7 +284,8 @@ static void mgag200_g200se_04_pixpllc_atomic_update(struct drm_crtc *crtc,
pixpllcp = pixpllc->p - 1;
pixpllcs = pixpllc->s;
- xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1);
+ // For G200SE A, BIT(7) should be set unconditionally.
+ xpixpllcm = BIT(7) | pixpllcm;
xpixpllcn = pixpllcn;
xpixpllcp = (pixpllcs << 3) | pixpllcp;
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index bbab2549243a..0a5aaf78172a 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -579,13 +579,13 @@ int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_st
struct drm_property_blob *new_gamma_lut = new_crtc_state->gamma_lut;
int ret;
- ret = drm_atomic_helper_check_crtc_state(new_crtc_state, false);
- if (ret)
- return ret;
-
if (!new_crtc_state->enable)
return 0;
+ ret = drm_atomic_helper_check_crtc_primary_plane(new_crtc_state);
+ if (ret)
+ return ret;
+
if (new_crtc_state->mode_changed) {
if (funcs->pixpllc_atomic_check) {
ret = funcs->pixpllc_atomic_check(crtc, new_state);
@@ -601,7 +601,7 @@ int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_st
}
}
- return drm_atomic_add_affected_planes(new_state, crtc);
+ return 0;
}
void mgag200_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *old_state)
@@ -824,7 +824,6 @@ int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vram_avail
dev->mode_config.max_width = MGAG200_MAX_FB_WIDTH;
dev->mode_config.max_height = MGAG200_MAX_FB_HEIGHT;
dev->mode_config.preferred_depth = 24;
- dev->mode_config.fb_base = mdev->vram_res->start;
dev->mode_config.funcs = &mgag200_mode_config_funcs;
dev->mode_config.helper_private = &mgag200_mode_config_helper_funcs;
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
index 2c8b9899625b..948785ed07bb 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
@@ -500,7 +500,7 @@ static const struct adreno_gpu_funcs funcs = {
#endif
.gpu_state_get = a3xx_gpu_state_get,
.gpu_state_put = adreno_gpu_state_put,
- .create_address_space = adreno_iommu_create_address_space,
+ .create_address_space = adreno_create_address_space,
.get_rptr = a3xx_get_rptr,
},
};
diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
index 7cb8d9849c07..3e09d3a7a0ac 100644
--- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
@@ -606,8 +606,7 @@ static int a4xx_pm_suspend(struct msm_gpu *gpu) {
static int a4xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
{
- *value = gpu_read64(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_LO,
- REG_A4XX_RBBM_PERFCTR_CP_0_HI);
+ *value = gpu_read64(gpu, REG_A4XX_RBBM_PERFCTR_CP_0_LO);
return 0;
}
@@ -635,7 +634,7 @@ static const struct adreno_gpu_funcs funcs = {
#endif
.gpu_state_get = a4xx_gpu_state_get,
.gpu_state_put = adreno_gpu_state_put,
- .create_address_space = adreno_iommu_create_address_space,
+ .create_address_space = adreno_create_address_space,
.get_rptr = a4xx_get_rptr,
},
.get_timestamp = a4xx_get_timestamp,
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index 3dcec7acb384..660ba0db8900 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -605,11 +605,9 @@ static int a5xx_ucode_init(struct msm_gpu *gpu)
a5xx_ucode_check_version(a5xx_gpu, a5xx_gpu->pfp_bo);
}
- gpu_write64(gpu, REG_A5XX_CP_ME_INSTR_BASE_LO,
- REG_A5XX_CP_ME_INSTR_BASE_HI, a5xx_gpu->pm4_iova);
+ gpu_write64(gpu, REG_A5XX_CP_ME_INSTR_BASE_LO, a5xx_gpu->pm4_iova);
- gpu_write64(gpu, REG_A5XX_CP_PFP_INSTR_BASE_LO,
- REG_A5XX_CP_PFP_INSTR_BASE_HI, a5xx_gpu->pfp_iova);
+ gpu_write64(gpu, REG_A5XX_CP_PFP_INSTR_BASE_LO, a5xx_gpu->pfp_iova);
return 0;
}
@@ -868,8 +866,7 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
* memory rendering at this point in time and we don't want to block off
* part of the virtual memory space.
*/
- gpu_write64(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO,
- REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI, 0x00000000);
+ gpu_write64(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO, 0x00000000);
gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_SIZE, 0x00000000);
/* Put the GPU into 64 bit by default */
@@ -908,8 +905,7 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
return ret;
/* Set the ringbuffer address */
- gpu_write64(gpu, REG_A5XX_CP_RB_BASE, REG_A5XX_CP_RB_BASE_HI,
- gpu->rb[0]->iova);
+ gpu_write64(gpu, REG_A5XX_CP_RB_BASE, gpu->rb[0]->iova);
/*
* If the microcode supports the WHERE_AM_I opcode then we can use that
@@ -936,7 +932,7 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
}
gpu_write64(gpu, REG_A5XX_CP_RB_RPTR_ADDR,
- REG_A5XX_CP_RB_RPTR_ADDR_HI, shadowptr(a5xx_gpu, gpu->rb[0]));
+ shadowptr(a5xx_gpu, gpu->rb[0]));
} else if (gpu->nr_rings > 1) {
/* Disable preemption if WHERE_AM_I isn't available */
a5xx_preempt_fini(gpu);
@@ -1239,9 +1235,9 @@ static void a5xx_fault_detect_irq(struct msm_gpu *gpu)
gpu_read(gpu, REG_A5XX_RBBM_STATUS),
gpu_read(gpu, REG_A5XX_CP_RB_RPTR),
gpu_read(gpu, REG_A5XX_CP_RB_WPTR),
- gpu_read64(gpu, REG_A5XX_CP_IB1_BASE, REG_A5XX_CP_IB1_BASE_HI),
+ gpu_read64(gpu, REG_A5XX_CP_IB1_BASE),
gpu_read(gpu, REG_A5XX_CP_IB1_BUFSZ),
- gpu_read64(gpu, REG_A5XX_CP_IB2_BASE, REG_A5XX_CP_IB2_BASE_HI),
+ gpu_read64(gpu, REG_A5XX_CP_IB2_BASE),
gpu_read(gpu, REG_A5XX_CP_IB2_BUFSZ));
/* Turn off the hangcheck timer to keep it from bothering us */
@@ -1427,8 +1423,7 @@ static int a5xx_pm_suspend(struct msm_gpu *gpu)
static int a5xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
{
- *value = gpu_read64(gpu, REG_A5XX_RBBM_ALWAYSON_COUNTER_LO,
- REG_A5XX_RBBM_ALWAYSON_COUNTER_HI);
+ *value = gpu_read64(gpu, REG_A5XX_RBBM_ALWAYSON_COUNTER_LO);
return 0;
}
@@ -1465,8 +1460,7 @@ static int a5xx_crashdumper_run(struct msm_gpu *gpu,
if (IS_ERR_OR_NULL(dumper->ptr))
return -EINVAL;
- gpu_write64(gpu, REG_A5XX_CP_CRASH_SCRIPT_BASE_LO,
- REG_A5XX_CP_CRASH_SCRIPT_BASE_HI, dumper->iova);
+ gpu_write64(gpu, REG_A5XX_CP_CRASH_SCRIPT_BASE_LO, dumper->iova);
gpu_write(gpu, REG_A5XX_CP_CRASH_DUMP_CNTL, 1);
@@ -1666,8 +1660,7 @@ static u64 a5xx_gpu_busy(struct msm_gpu *gpu, unsigned long *out_sample_rate)
{
u64 busy_cycles;
- busy_cycles = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_RBBM_0_LO,
- REG_A5XX_RBBM_PERFCTR_RBBM_0_HI);
+ busy_cycles = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_RBBM_0_LO);
*out_sample_rate = clk_get_rate(gpu->core_clk);
return busy_cycles;
@@ -1705,7 +1698,7 @@ static const struct adreno_gpu_funcs funcs = {
.gpu_busy = a5xx_gpu_busy,
.gpu_state_get = a5xx_gpu_state_get,
.gpu_state_put = a5xx_gpu_state_put,
- .create_address_space = adreno_iommu_create_address_space,
+ .create_address_space = adreno_create_address_space,
.get_rptr = a5xx_get_rptr,
},
.get_timestamp = a5xx_get_timestamp,
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
index 8abc9a2b114a..7658e89844b4 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c
@@ -137,7 +137,6 @@ void a5xx_preempt_trigger(struct msm_gpu *gpu)
/* Set the address of the incoming preemption record */
gpu_write64(gpu, REG_A5XX_CP_CONTEXT_SWITCH_RESTORE_ADDR_LO,
- REG_A5XX_CP_CONTEXT_SWITCH_RESTORE_ADDR_HI,
a5xx_gpu->preempt_iova[ring->id]);
a5xx_gpu->next_ring = ring;
@@ -211,8 +210,7 @@ void a5xx_preempt_hw_init(struct msm_gpu *gpu)
}
/* Write a 0 to signal that we aren't switching pagetables */
- gpu_write64(gpu, REG_A5XX_CP_CONTEXT_SWITCH_SMMU_INFO_LO,
- REG_A5XX_CP_CONTEXT_SWITCH_SMMU_INFO_HI, 0);
+ gpu_write64(gpu, REG_A5XX_CP_CONTEXT_SWITCH_SMMU_INFO_LO, 0);
/* Reset the preemption state */
set_preempt_state(a5xx_gpu, PREEMPT_NONE);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
index e033d6a67a20..6484b97c5344 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gmu.c
@@ -1213,19 +1213,17 @@ static int a6xx_gmu_memory_alloc(struct a6xx_gmu *gmu, struct a6xx_gmu_bo *bo,
static int a6xx_gmu_memory_probe(struct a6xx_gmu *gmu)
{
- struct iommu_domain *domain;
struct msm_mmu *mmu;
- domain = iommu_domain_alloc(&platform_bus_type);
- if (!domain)
+ mmu = msm_iommu_new(gmu->dev, 0);
+ if (!mmu)
return -ENODEV;
+ if (IS_ERR(mmu))
+ return PTR_ERR(mmu);
- mmu = msm_iommu_new(gmu->dev, domain);
gmu->aspace = msm_gem_address_space_create(mmu, "gmu", 0x0, 0x80000000);
- if (IS_ERR(gmu->aspace)) {
- iommu_domain_free(domain);
+ if (IS_ERR(gmu->aspace))
return PTR_ERR(gmu->aspace);
- }
return 0;
}
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index fdc578016e0b..36c8fb699b56 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -247,8 +247,7 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
OUT_RING(ring, submit->seqno);
trace_msm_gpu_submit_flush(submit,
- gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER_LO,
- REG_A6XX_CP_ALWAYS_ON_COUNTER_HI));
+ gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER_LO));
a6xx_flush(gpu, ring);
}
@@ -947,8 +946,7 @@ static int a6xx_ucode_init(struct msm_gpu *gpu)
}
}
- gpu_write64(gpu, REG_A6XX_CP_SQE_INSTR_BASE,
- REG_A6XX_CP_SQE_INSTR_BASE+1, a6xx_gpu->sqe_iova);
+ gpu_write64(gpu, REG_A6XX_CP_SQE_INSTR_BASE, a6xx_gpu->sqe_iova);
return 0;
}
@@ -999,8 +997,7 @@ static int hw_init(struct msm_gpu *gpu)
* memory rendering at this point in time and we don't want to block off
* part of the virtual memory space.
*/
- gpu_write64(gpu, REG_A6XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO,
- REG_A6XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI, 0x00000000);
+ gpu_write64(gpu, REG_A6XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO, 0x00000000);
gpu_write(gpu, REG_A6XX_RBBM_SECVID_TSB_TRUSTED_SIZE, 0x00000000);
/* Turn on 64 bit addressing for all blocks */
@@ -1049,11 +1046,9 @@ static int hw_init(struct msm_gpu *gpu)
if (!adreno_is_a650_family(adreno_gpu)) {
/* Set the GMEM VA range [0x100000:0x100000 + gpu->gmem - 1] */
- gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MIN_LO,
- REG_A6XX_UCHE_GMEM_RANGE_MIN_HI, 0x00100000);
+ gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MIN_LO, 0x00100000);
gpu_write64(gpu, REG_A6XX_UCHE_GMEM_RANGE_MAX_LO,
- REG_A6XX_UCHE_GMEM_RANGE_MAX_HI,
0x00100000 + adreno_gpu->gmem - 1);
}
@@ -1145,8 +1140,7 @@ static int hw_init(struct msm_gpu *gpu)
goto out;
/* Set the ringbuffer address */
- gpu_write64(gpu, REG_A6XX_CP_RB_BASE, REG_A6XX_CP_RB_BASE_HI,
- gpu->rb[0]->iova);
+ gpu_write64(gpu, REG_A6XX_CP_RB_BASE, gpu->rb[0]->iova);
/* Targets that support extended APRIV can use the RPTR shadow from
* hardware but all the other ones need to disable the feature. Targets
@@ -1178,7 +1172,6 @@ static int hw_init(struct msm_gpu *gpu)
}
gpu_write64(gpu, REG_A6XX_CP_RB_RPTR_ADDR_LO,
- REG_A6XX_CP_RB_RPTR_ADDR_HI,
shadowptr(a6xx_gpu, gpu->rb[0]));
}
@@ -1499,9 +1492,9 @@ static void a6xx_fault_detect_irq(struct msm_gpu *gpu)
gpu_read(gpu, REG_A6XX_RBBM_STATUS),
gpu_read(gpu, REG_A6XX_CP_RB_RPTR),
gpu_read(gpu, REG_A6XX_CP_RB_WPTR),
- gpu_read64(gpu, REG_A6XX_CP_IB1_BASE, REG_A6XX_CP_IB1_BASE_HI),
+ gpu_read64(gpu, REG_A6XX_CP_IB1_BASE),
gpu_read(gpu, REG_A6XX_CP_IB1_REM_SIZE),
- gpu_read64(gpu, REG_A6XX_CP_IB2_BASE, REG_A6XX_CP_IB2_BASE_HI),
+ gpu_read64(gpu, REG_A6XX_CP_IB2_BASE),
gpu_read(gpu, REG_A6XX_CP_IB2_REM_SIZE));
/* Turn off the hangcheck timer to keep it from bothering us */
@@ -1712,8 +1705,7 @@ static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value)
/* Force the GPU power on so we can read this register */
a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET);
- *value = gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER_LO,
- REG_A6XX_CP_ALWAYS_ON_COUNTER_HI);
+ *value = gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER_LO);
a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET);
@@ -1786,43 +1778,16 @@ a6xx_create_address_space(struct msm_gpu *gpu, struct platform_device *pdev)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a6xx_gpu *a6xx_gpu = to_a6xx_gpu(adreno_gpu);
- struct iommu_domain *iommu;
- struct msm_mmu *mmu;
- struct msm_gem_address_space *aspace;
- u64 start, size;
-
- iommu = iommu_domain_alloc(&platform_bus_type);
- if (!iommu)
- return NULL;
+ unsigned long quirks = 0;
/*
* 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))
- adreno_set_llc_attributes(iommu);
-
- mmu = msm_iommu_new(&pdev->dev, iommu);
- if (IS_ERR(mmu)) {
- iommu_domain_free(iommu);
- return ERR_CAST(mmu);
- }
-
- /*
- * Use the aperture start or SZ_16M, whichever is greater. This will
- * ensure that we align with the allocated pagetable range while still
- * allowing room in the lower 32 bits for GMEM and whatnot
- */
- start = max_t(u64, SZ_16M, iommu->geometry.aperture_start);
- size = iommu->geometry.aperture_end - start + 1;
-
- aspace = msm_gem_address_space_create(mmu, "gpu",
- start & GENMASK_ULL(48, 0), size);
+ quirks |= IO_PGTABLE_QUIRK_ARM_OUTER_WBWA;
- if (IS_ERR(aspace) && !IS_ERR(mmu))
- mmu->funcs->destroy(mmu);
-
- return aspace;
+ return adreno_iommu_create_address_space(gpu, pdev, quirks);
}
static struct msm_gem_address_space *
@@ -1851,6 +1816,39 @@ static uint32_t a6xx_get_rptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
return ring->memptrs->rptr = gpu_read(gpu, REG_A6XX_CP_RB_RPTR);
}
+static bool a6xx_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
+{
+ struct msm_cp_state cp_state = {
+ .ib1_base = gpu_read64(gpu, REG_A6XX_CP_IB1_BASE),
+ .ib2_base = gpu_read64(gpu, REG_A6XX_CP_IB2_BASE),
+ .ib1_rem = gpu_read(gpu, REG_A6XX_CP_IB1_REM_SIZE),
+ .ib2_rem = gpu_read(gpu, REG_A6XX_CP_IB2_REM_SIZE),
+ };
+ bool progress;
+
+ /*
+ * Adjust the remaining data to account for what has already been
+ * fetched from memory, but not yet consumed by the SQE.
+ *
+ * This is not *technically* correct, the amount buffered could
+ * exceed the IB size due to hw prefetching ahead, but:
+ *
+ * (1) We aren't trying to find the exact position, just whether
+ * progress has been made
+ * (2) The CP_REG_TO_MEM at the end of a submit should be enough
+ * to prevent prefetching into an unrelated submit. (And
+ * either way, at some point the ROQ will be full.)
+ */
+ cp_state.ib1_rem += gpu_read(gpu, REG_A6XX_CP_CSQ_IB1_STAT) >> 16;
+ cp_state.ib2_rem += gpu_read(gpu, REG_A6XX_CP_CSQ_IB2_STAT) >> 16;
+
+ progress = !!memcmp(&cp_state, &ring->last_cp_state, sizeof(cp_state));
+
+ ring->last_cp_state = cp_state;
+
+ return progress;
+}
+
static u32 a618_get_speed_bin(u32 fuse)
{
if (fuse == 0)
@@ -1906,7 +1904,7 @@ static u32 fuse_to_supp_hw(struct device *dev, struct adreno_rev rev, u32 fuse)
if (val == UINT_MAX) {
DRM_DEV_ERROR(dev,
- "missing support for speed-bin: %u. Some OPPs may not be supported by hardware",
+ "missing support for speed-bin: %u. Some OPPs may not be supported by hardware\n",
fuse);
return UINT_MAX;
}
@@ -1916,7 +1914,7 @@ static u32 fuse_to_supp_hw(struct device *dev, struct adreno_rev rev, u32 fuse)
static int a6xx_set_supported_hw(struct device *dev, struct adreno_rev rev)
{
- u32 supp_hw = UINT_MAX;
+ u32 supp_hw;
u32 speedbin;
int ret;
@@ -1928,15 +1926,13 @@ static int a6xx_set_supported_hw(struct device *dev, struct adreno_rev rev)
if (ret == -ENOENT) {
return 0;
} else if (ret) {
- DRM_DEV_ERROR(dev,
- "failed to read speed-bin (%d). Some OPPs may not be supported by hardware",
- ret);
- goto done;
+ dev_err_probe(dev, ret,
+ "failed to read speed-bin. Some OPPs may not be supported by hardware\n");
+ return ret;
}
supp_hw = fuse_to_supp_hw(dev, rev, speedbin);
-done:
ret = devm_pm_opp_set_supported_hw(dev, &supp_hw, 1);
if (ret)
return ret;
@@ -1969,6 +1965,7 @@ static const struct adreno_gpu_funcs funcs = {
.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,
};
@@ -2005,13 +2002,6 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
adreno_cmp_rev(ADRENO_REV(6, 3, 5, ANY_ID), info->rev)))
adreno_gpu->base.hw_apriv = true;
- /*
- * For now only clamp to idle freq for devices where this is known not
- * to cause power supply issues:
- */
- if (info && (info->revn == 618))
- gpu->clamp_to_idle = true;
-
a6xx_llc_slices_init(pdev, a6xx_gpu);
ret = a6xx_set_supported_hw(&pdev->dev, config->rev);
@@ -2026,6 +2016,13 @@ struct msm_gpu *a6xx_gpu_init(struct drm_device *dev)
return ERR_PTR(ret);
}
+ /*
+ * For now only clamp to idle freq for devices where this is known not
+ * to cause power supply issues:
+ */
+ if (adreno_is_a618(adreno_gpu) || adreno_is_7c3(adreno_gpu))
+ 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);
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
index a5c3d1ed255a..a023d5f962dc 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu_state.c
@@ -147,8 +147,7 @@ static int a6xx_crashdumper_run(struct msm_gpu *gpu,
/* Make sure all pending memory writes are posted */
wmb();
- gpu_write64(gpu, REG_A6XX_CP_CRASH_SCRIPT_BASE_LO,
- REG_A6XX_CP_CRASH_SCRIPT_BASE_HI, dumper->iova);
+ gpu_write64(gpu, REG_A6XX_CP_CRASH_SCRIPT_BASE_LO, dumper->iova);
gpu_write(gpu, REG_A6XX_CP_CRASH_DUMP_CNTL, 1);
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 5a0e8491cd3a..57586c794b84 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -191,37 +191,38 @@ int adreno_zap_shader_load(struct msm_gpu *gpu, u32 pasid)
return zap_shader_load_mdt(gpu, adreno_gpu->info->zapfw, pasid);
}
-void adreno_set_llc_attributes(struct iommu_domain *iommu)
+struct msm_gem_address_space *
+adreno_create_address_space(struct msm_gpu *gpu,
+ struct platform_device *pdev)
{
- iommu_set_pgtable_quirks(iommu, IO_PGTABLE_QUIRK_ARM_OUTER_WBWA);
+ return adreno_iommu_create_address_space(gpu, pdev, 0);
}
struct msm_gem_address_space *
adreno_iommu_create_address_space(struct msm_gpu *gpu,
- struct platform_device *pdev)
+ struct platform_device *pdev,
+ unsigned long quirks)
{
- struct iommu_domain *iommu;
+ struct iommu_domain_geometry *geometry;
struct msm_mmu *mmu;
struct msm_gem_address_space *aspace;
u64 start, size;
- iommu = iommu_domain_alloc(&platform_bus_type);
- if (!iommu)
- return NULL;
-
- mmu = msm_iommu_new(&pdev->dev, iommu);
- if (IS_ERR(mmu)) {
- iommu_domain_free(iommu);
+ mmu = msm_iommu_new(&pdev->dev, quirks);
+ if (IS_ERR_OR_NULL(mmu))
return ERR_CAST(mmu);
- }
+
+ geometry = msm_iommu_get_geometry(mmu);
+ if (IS_ERR(geometry))
+ return ERR_CAST(geometry);
/*
* Use the aperture start or SZ_16M, whichever is greater. This will
* ensure that we align with the allocated pagetable range while still
* allowing room in the lower 32 bits for GMEM and whatnot
*/
- start = max_t(u64, SZ_16M, iommu->geometry.aperture_start);
- size = iommu->geometry.aperture_end - start + 1;
+ start = max_t(u64, SZ_16M, geometry->aperture_start);
+ size = geometry->aperture_end - start + 1;
aspace = msm_gem_address_space_create(mmu, "gpu",
start & GENMASK_ULL(48, 0), size);
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index e7adc5c632d0..5d4b1c95033f 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -335,10 +335,13 @@ void adreno_show_object(struct drm_printer *p, void **ptr, int len,
* attached targets
*/
struct msm_gem_address_space *
-adreno_iommu_create_address_space(struct msm_gpu *gpu,
- struct platform_device *pdev);
+adreno_create_address_space(struct msm_gpu *gpu,
+ struct platform_device *pdev);
-void adreno_set_llc_attributes(struct iommu_domain *iommu);
+struct msm_gem_address_space *
+adreno_iommu_create_address_space(struct msm_gpu *gpu,
+ struct platform_device *pdev,
+ unsigned long quirks);
int adreno_read_speedbin(struct device *dev, u32 *speedbin);
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 2c14646661b7..0f71e8fe7be7 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
@@ -237,12 +237,13 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
unsigned long lock_flags;
struct dpu_hw_intf_cfg intf_cfg = { 0 };
+ drm_mode_init(&mode, &phys_enc->cached_mode);
+
if (!phys_enc->hw_ctl->ops.setup_intf_cfg) {
DPU_ERROR("invalid encoder %d\n", phys_enc != NULL);
return;
}
- mode = phys_enc->cached_mode;
if (!phys_enc->hw_intf->ops.setup_timing_gen) {
DPU_ERROR("timing engine setup is not supported\n");
return;
@@ -634,7 +635,9 @@ static int dpu_encoder_phys_vid_get_frame_count(
{
struct intf_status s = {0};
u32 fetch_start = 0;
- struct drm_display_mode mode = phys_enc->cached_mode;
+ struct drm_display_mode mode;
+
+ drm_mode_init(&mode, &phys_enc->cached_mode);
if (!dpu_encoder_phys_vid_is_master(phys_enc))
return -EINVAL;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
index f436a1f3419d..d95540309d4d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
@@ -434,6 +434,12 @@ static const struct dpu_format dpu_format_map[] = {
DPU_CHROMA_H2V1, DPU_FORMAT_FLAG_YUV,
DPU_FETCH_LINEAR, 2),
+ PSEUDO_YUV_FMT_LOOSE(P010,
+ 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
+ C1_B_Cb, C2_R_Cr,
+ DPU_CHROMA_420, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_YUV,
+ DPU_FETCH_LINEAR, 2),
+
INTERLEAVED_YUV_FMT(VYUY,
0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
C2_R_Cr, C0_G_Y, C1_B_Cb, C0_G_Y,
@@ -524,12 +530,26 @@ static const struct dpu_format dpu_format_map_ubwc[] = {
true, 4, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_COMPRESSED,
DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
+ INTERLEAVED_RGB_FMT_TILED(XRGB2101010,
+ COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
+ C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
+ true, 4, DPU_FORMAT_FLAG_DX | DPU_FORMAT_FLAG_COMPRESSED,
+ DPU_FETCH_UBWC, 2, DPU_TILE_HEIGHT_UBWC),
+
PSEUDO_YUV_FMT_TILED(NV12,
0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
C1_B_Cb, C2_R_Cr,
DPU_CHROMA_420, DPU_FORMAT_FLAG_YUV |
DPU_FORMAT_FLAG_COMPRESSED,
DPU_FETCH_UBWC, 4, DPU_TILE_HEIGHT_NV12),
+
+ PSEUDO_YUV_FMT_TILED(P010,
+ 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
+ C1_B_Cb, C2_R_Cr,
+ DPU_CHROMA_420, DPU_FORMAT_FLAG_DX |
+ DPU_FORMAT_FLAG_YUV |
+ DPU_FORMAT_FLAG_COMPRESSED,
+ DPU_FETCH_UBWC, 4, DPU_TILE_HEIGHT_UBWC),
};
/* _dpu_get_v_h_subsample_rate - Get subsample rates for all formats we support
@@ -571,13 +591,15 @@ static int _dpu_format_get_media_color_ubwc(const struct dpu_format *fmt)
{DRM_FORMAT_XBGR8888, COLOR_FMT_RGBA8888_UBWC},
{DRM_FORMAT_XRGB8888, COLOR_FMT_RGBA8888_UBWC},
{DRM_FORMAT_ABGR2101010, COLOR_FMT_RGBA1010102_UBWC},
+ {DRM_FORMAT_XRGB2101010, COLOR_FMT_RGBA1010102_UBWC},
{DRM_FORMAT_XBGR2101010, COLOR_FMT_RGBA1010102_UBWC},
{DRM_FORMAT_BGR565, COLOR_FMT_RGB565_UBWC},
};
int color_fmt = -1;
int i;
- if (fmt->base.pixel_format == DRM_FORMAT_NV12) {
+ if (fmt->base.pixel_format == DRM_FORMAT_NV12 ||
+ fmt->base.pixel_format == DRM_FORMAT_P010) {
if (DPU_FORMAT_IS_DX(fmt)) {
if (fmt->unpack_tight)
color_fmt = COLOR_FMT_NV12_BPP10_UBWC;
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 27f029fdc682..2196e205efa5 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -156,6 +156,7 @@ static const uint32_t plane_formats[] = {
DRM_FORMAT_RGBX8888,
DRM_FORMAT_BGRX8888,
DRM_FORMAT_XBGR8888,
+ DRM_FORMAT_XRGB2101010,
DRM_FORMAT_RGB888,
DRM_FORMAT_BGR888,
DRM_FORMAT_RGB565,
@@ -184,6 +185,7 @@ static const uint32_t plane_formats_yuv[] = {
DRM_FORMAT_RGBA8888,
DRM_FORMAT_BGRX8888,
DRM_FORMAT_BGRA8888,
+ DRM_FORMAT_XRGB2101010,
DRM_FORMAT_XRGB8888,
DRM_FORMAT_XBGR8888,
DRM_FORMAT_RGBX8888,
@@ -208,6 +210,7 @@ static const uint32_t plane_formats_yuv[] = {
DRM_FORMAT_RGBX4444,
DRM_FORMAT_BGRX4444,
+ DRM_FORMAT_P010,
DRM_FORMAT_NV12,
DRM_FORMAT_NV21,
DRM_FORMAT_NV16,
@@ -318,6 +321,18 @@ static const struct dpu_caps sc7180_dpu_caps = {
.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
};
+static const struct dpu_caps sm6115_dpu_caps = {
+ .max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
+ .max_mixer_blendstages = 0x4,
+ .qseed_type = DPU_SSPP_SCALER_QSEED3LITE,
+ .smart_dma_rev = DPU_SSPP_SMART_DMA_V2, /* TODO: v2.5 */
+ .ubwc_version = DPU_HW_UBWC_VER_20,
+ .has_dim_layer = true,
+ .has_idle_pc = true,
+ .max_linewidth = 2160,
+ .pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
+};
+
static const struct dpu_caps sm8150_dpu_caps = {
.max_mixer_width = DEFAULT_DPU_OUTPUT_LINE_WIDTH,
.max_mixer_blendstages = 0xb,
@@ -472,6 +487,19 @@ static const struct dpu_mdp_cfg sc8180x_mdp[] = {
},
};
+static const struct dpu_mdp_cfg sm6115_mdp[] = {
+ {
+ .name = "top_0", .id = MDP_TOP,
+ .base = 0x0, .len = 0x494,
+ .features = 0,
+ .highest_bank_bit = 0x1,
+ .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_mdp_cfg sm8250_mdp[] = {
{
.name = "top_0", .id = MDP_TOP,
@@ -849,6 +877,16 @@ static const struct dpu_sspp_cfg sc7180_sspp[] = {
sdm845_dma_sblk_2, 9, SSPP_TYPE_DMA, DPU_CLK_CTRL_CURSOR1),
};
+static const struct dpu_sspp_sub_blks sm6115_vig_sblk_0 =
+ _VIG_SBLK("0", 2, DPU_SSPP_SCALER_QSEED3LITE);
+
+static const struct dpu_sspp_cfg sm6115_sspp[] = {
+ SSPP_BLK("sspp_0", SSPP_VIG0, 0x4000, VIG_SM8250_MASK,
+ sm6115_vig_sblk_0, 0, SSPP_TYPE_VIG, DPU_CLK_CTRL_VIG0),
+ SSPP_BLK("sspp_8", SSPP_DMA0, 0x24000, DMA_SDM845_MASK,
+ sdm845_dma_sblk_0, 1, SSPP_TYPE_DMA, DPU_CLK_CTRL_DMA0),
+};
+
static const struct dpu_sspp_sub_blks sm8250_vig_sblk_0 =
_VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED3LITE);
static const struct dpu_sspp_sub_blks sm8250_vig_sblk_1 =
@@ -1175,6 +1213,13 @@ static const struct dpu_pingpong_cfg sm8150_pp[] = {
-1),
};
+static const struct dpu_pingpong_cfg sc7280_pp[] = {
+ PP_BLK("pingpong_0", PINGPONG_0, 0x59000, 0, sc7280_pp_sblk, -1, -1),
+ PP_BLK("pingpong_1", PINGPONG_1, 0x6a000, 0, sc7280_pp_sblk, -1, -1),
+ PP_BLK("pingpong_2", PINGPONG_2, 0x6b000, 0, sc7280_pp_sblk, -1, -1),
+ PP_BLK("pingpong_3", PINGPONG_3, 0x6c000, 0, sc7280_pp_sblk, -1, -1),
+};
+
static struct dpu_pingpong_cfg qcm2290_pp[] = {
PP_BLK("pingpong_0", PINGPONG_0, 0x70000, 0, sdm845_pp_sblk,
DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8),
@@ -1198,13 +1243,6 @@ static const struct dpu_merge_3d_cfg sm8150_merge_3d[] = {
MERGE_3D_BLK("merge_3d_2", MERGE_3D_2, 0x83200),
};
-static const struct dpu_pingpong_cfg sc7280_pp[] = {
- PP_BLK("pingpong_0", PINGPONG_0, 0x59000, 0, sc7280_pp_sblk, -1, -1),
- PP_BLK("pingpong_1", PINGPONG_1, 0x6a000, 0, sc7280_pp_sblk, -1, -1),
- PP_BLK("pingpong_2", PINGPONG_2, 0x6b000, 0, sc7280_pp_sblk, -1, -1),
- PP_BLK("pingpong_3", PINGPONG_3, 0x6c000, 0, sc7280_pp_sblk, -1, -1),
-};
-
/*************************************************************
* DSC sub blocks config
*************************************************************/
@@ -1587,6 +1625,35 @@ static const struct dpu_perf_cfg sc7180_perf_data = {
.bw_inefficiency_factor = 120,
};
+static const struct dpu_perf_cfg sm6115_perf_data = {
+ .max_bw_low = 3100000,
+ .max_bw_high = 4000000,
+ .min_core_ib = 2400000,
+ .min_llcc_ib = 800000,
+ .min_dram_ib = 800000,
+ .min_prefill_lines = 24,
+ .danger_lut_tbl = {0xff, 0xffff, 0x0},
+ .safe_lut_tbl = {0xfff0, 0xff00, 0xffff},
+ .qos_lut_tbl = {
+ {.nentry = ARRAY_SIZE(sc7180_qos_linear),
+ .entries = sc7180_qos_linear
+ },
+ {.nentry = ARRAY_SIZE(sc7180_qos_macrotile),
+ .entries = sc7180_qos_macrotile
+ },
+ {.nentry = ARRAY_SIZE(sc7180_qos_nrt),
+ .entries = sc7180_qos_nrt
+ },
+ /* TODO: macrotile-qseed is different from macrotile */
+ },
+ .cdp_cfg = {
+ {.rd_enable = 1, .wr_enable = 1},
+ {.rd_enable = 1, .wr_enable = 0}
+ },
+ .clk_inefficiency_factor = 105,
+ .bw_inefficiency_factor = 120,
+};
+
static const struct dpu_perf_cfg sm8150_perf_data = {
.max_bw_low = 12800000,
.max_bw_high = 12800000,
@@ -1798,6 +1865,28 @@ static const struct dpu_mdss_cfg sc7180_dpu_cfg = {
.mdss_irqs = IRQ_SC7180_MASK,
};
+static const struct dpu_mdss_cfg sm6115_dpu_cfg = {
+ .caps = &sm6115_dpu_caps,
+ .mdp_count = ARRAY_SIZE(sm6115_mdp),
+ .mdp = sm6115_mdp,
+ .ctl_count = ARRAY_SIZE(qcm2290_ctl),
+ .ctl = qcm2290_ctl,
+ .sspp_count = ARRAY_SIZE(sm6115_sspp),
+ .sspp = sm6115_sspp,
+ .mixer_count = ARRAY_SIZE(qcm2290_lm),
+ .mixer = qcm2290_lm,
+ .dspp_count = ARRAY_SIZE(qcm2290_dspp),
+ .dspp = qcm2290_dspp,
+ .pingpong_count = ARRAY_SIZE(qcm2290_pp),
+ .pingpong = qcm2290_pp,
+ .intf_count = ARRAY_SIZE(qcm2290_intf),
+ .intf = qcm2290_intf,
+ .vbif_count = ARRAY_SIZE(sdm845_vbif),
+ .vbif = sdm845_vbif,
+ .perf = &sm6115_perf_data,
+ .mdss_irqs = IRQ_SC7180_MASK,
+};
+
static const struct dpu_mdss_cfg sm8150_dpu_cfg = {
.caps = &sm8150_dpu_caps,
.mdp_count = ARRAY_SIZE(sdm845_mdp),
@@ -1932,6 +2021,7 @@ static const struct dpu_mdss_hw_cfg_handler cfg_handler[] = {
{ .hw_rev = DPU_HW_VER_510, .dpu_cfg = &sc8180x_dpu_cfg},
{ .hw_rev = DPU_HW_VER_600, .dpu_cfg = &sm8250_dpu_cfg},
{ .hw_rev = DPU_HW_VER_620, .dpu_cfg = &sc7180_dpu_cfg},
+ { .hw_rev = DPU_HW_VER_630, .dpu_cfg = &sm6115_dpu_cfg},
{ .hw_rev = DPU_HW_VER_650, .dpu_cfg = &qcm2290_dpu_cfg},
{ .hw_rev = DPU_HW_VER_720, .dpu_cfg = &sc7280_dpu_cfg},
};
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 38aa38ab1568..3b645d5aa9aa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -44,6 +44,7 @@
#define DPU_HW_VER_510 DPU_HW_VER(5, 1, 1) /* sc8180 */
#define DPU_HW_VER_600 DPU_HW_VER(6, 0, 0) /* sm8250 */
#define DPU_HW_VER_620 DPU_HW_VER(6, 2, 0) /* sc7180 v1.0 */
+#define DPU_HW_VER_630 DPU_HW_VER(6, 3, 0) /* sm6115|sm4250 */
#define DPU_HW_VER_650 DPU_HW_VER(6, 5, 0) /* qcm2290|sm4125 */
#define DPU_HW_VER_720 DPU_HW_VER(7, 2, 0) /* sc7280 */
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 f2ddcfb6f7ee..3662df698dae 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
@@ -42,7 +42,7 @@ static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
u32 initial_lines)
{
struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
- u32 data, lsb, bpp;
+ u32 data;
u32 slice_last_group_size;
u32 det_thresh_flatness;
bool is_cmd_mode = !(mode & DSC_MODE_VIDEO);
@@ -56,14 +56,7 @@ static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
data = (initial_lines << 20);
data |= ((slice_last_group_size - 1) << 18);
/* bpp is 6.4 format, 4 LSBs bits are for fractional part */
- data |= dsc->bits_per_pixel << 12;
- lsb = dsc->bits_per_pixel % 4;
- bpp = dsc->bits_per_pixel / 4;
- bpp *= 4;
- bpp <<= 4;
- bpp |= lsb;
-
- data |= bpp << 8;
+ data |= (dsc->bits_per_pixel << 8);
data |= (dsc->block_pred_enable << 7);
data |= (dsc->line_buf_depth << 3);
data |= (dsc->simple_422 << 2);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 5e6e2626151e..b71199511a52 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -194,7 +194,7 @@ struct dpu_debugfs_regset32 {
struct dpu_kms *dpu_kms;
};
-static int _dpu_debugfs_show_regset32(struct seq_file *s, void *data)
+static int dpu_regset32_show(struct seq_file *s, void *data)
{
struct dpu_debugfs_regset32 *regset = s->private;
struct dpu_kms *dpu_kms = regset->dpu_kms;
@@ -227,19 +227,7 @@ static int _dpu_debugfs_show_regset32(struct seq_file *s, void *data)
return 0;
}
-
-static int dpu_debugfs_open_regset32(struct inode *inode,
- struct file *file)
-{
- return single_open(file, _dpu_debugfs_show_regset32, inode->i_private);
-}
-
-static const struct file_operations dpu_fops_regset32 = {
- .open = dpu_debugfs_open_regset32,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(dpu_regset32);
void dpu_debugfs_create_regset32(const char *name, umode_t mode,
void *parent,
@@ -259,7 +247,7 @@ void dpu_debugfs_create_regset32(const char *name, umode_t mode,
regset->blk_len = length;
regset->dpu_kms = dpu_kms;
- debugfs_create_file(name, mode, parent, regset, &dpu_fops_regset32);
+ debugfs_create_file(name, mode, parent, regset, &dpu_regset32_fops);
}
static int dpu_kms_debugfs_init(struct msm_kms *kms, struct drm_minor *minor)
@@ -1304,6 +1292,7 @@ static const struct of_device_id dpu_dt_match[] = {
{ .compatible = "qcom,sc7180-dpu", },
{ .compatible = "qcom,sc7280-dpu", },
{ .compatible = "qcom,sc8180x-dpu", },
+ { .compatible = "qcom,sm6115-dpu", },
{ .compatible = "qcom,sm8150-dpu", },
{ .compatible = "qcom,sm8250-dpu", },
{}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 658005f609f4..86719020afe2 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -69,9 +69,11 @@ static const uint32_t qcom_compressed_supported_formats[] = {
DRM_FORMAT_ARGB8888,
DRM_FORMAT_XBGR8888,
DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_XRGB2101010,
DRM_FORMAT_BGR565,
DRM_FORMAT_NV12,
+ DRM_FORMAT_P010,
};
/**
diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
index 964573d26d26..9a1a0769575d 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
@@ -387,7 +387,7 @@ static int mdp4_kms_init(struct drm_device *dev)
struct msm_drm_private *priv = dev->dev_private;
struct mdp4_kms *mdp4_kms;
struct msm_kms *kms = NULL;
- struct iommu_domain *iommu;
+ struct msm_mmu *mmu;
struct msm_gem_address_space *aspace;
int irq, ret;
u32 major, minor;
@@ -499,10 +499,15 @@ static int mdp4_kms_init(struct drm_device *dev)
mdp4_disable(mdp4_kms);
mdelay(16);
- iommu = iommu_domain_alloc(pdev->dev.bus);
- if (iommu) {
- struct msm_mmu *mmu = msm_iommu_new(&pdev->dev, iommu);
-
+ mmu = msm_iommu_new(&pdev->dev, 0);
+ if (IS_ERR(mmu)) {
+ ret = PTR_ERR(mmu);
+ goto fail;
+ } else if (!mmu) {
+ DRM_DEV_INFO(dev->dev, "no iommu, fallback to phys "
+ "contig buffers for scanout\n");
+ aspace = NULL;
+ } else {
aspace = msm_gem_address_space_create(mmu,
"mdp4", 0x1000, 0x100000000 - 0x1000);
@@ -514,10 +519,6 @@ static int mdp4_kms_init(struct drm_device *dev)
}
kms->aspace = aspace;
- } else {
- DRM_DEV_INFO(dev->dev, "no iommu, fallback to phys "
- "contig buffers for scanout\n");
- aspace = NULL;
}
ret = modeset_init(mdp4_kms);
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index b0d21838a134..29ae5c9613f3 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -203,7 +203,7 @@ static int mdp5_set_split_display(struct msm_kms *kms,
slave_encoder);
}
-static void mdp5_destroy(struct platform_device *pdev);
+static void mdp5_destroy(struct mdp5_kms *mdp5_kms);
static void mdp5_kms_destroy(struct msm_kms *kms)
{
@@ -223,7 +223,7 @@ static void mdp5_kms_destroy(struct msm_kms *kms)
}
mdp_kms_destroy(&mdp5_kms->base);
- mdp5_destroy(mdp5_kms->pdev);
+ mdp5_destroy(mdp5_kms);
}
#ifdef CONFIG_DEBUG_FS
@@ -559,6 +559,8 @@ static int mdp5_kms_init(struct drm_device *dev)
int irq, i, ret;
ret = mdp5_init(to_platform_device(dev->dev), dev);
+ if (ret)
+ return ret;
/* priv->kms would have been populated by the MDP5 driver */
kms = priv->kms;
@@ -632,9 +634,8 @@ fail:
return ret;
}
-static void mdp5_destroy(struct platform_device *pdev)
+static void mdp5_destroy(struct mdp5_kms *mdp5_kms)
{
- struct mdp5_kms *mdp5_kms = platform_get_drvdata(pdev);
int i;
if (mdp5_kms->ctlm)
@@ -648,7 +649,7 @@ static void mdp5_destroy(struct platform_device *pdev)
kfree(mdp5_kms->intfs[i]);
if (mdp5_kms->rpm_enabled)
- pm_runtime_disable(&pdev->dev);
+ pm_runtime_disable(&mdp5_kms->pdev->dev);
drm_atomic_private_obj_fini(&mdp5_kms->glob_state);
drm_modeset_lock_fini(&mdp5_kms->glob_state_lock);
@@ -797,8 +798,6 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev)
goto fail;
}
- platform_set_drvdata(pdev, mdp5_kms);
-
spin_lock_init(&mdp5_kms->resource_lock);
mdp5_kms->dev = dev;
@@ -839,6 +838,9 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev)
*/
clk_set_rate(mdp5_kms->core_clk, 200000000);
+ /* set uninit-ed kms */
+ priv->kms = &mdp5_kms->base.base;
+
pm_runtime_enable(&pdev->dev);
mdp5_kms->rpm_enabled = true;
@@ -890,13 +892,10 @@ static int mdp5_init(struct platform_device *pdev, struct drm_device *dev)
if (ret)
goto fail;
- /* set uninit-ed kms */
- priv->kms = &mdp5_kms->base.base;
-
return 0;
fail:
if (mdp5_kms)
- mdp5_destroy(pdev);
+ mdp5_destroy(mdp5_kms);
return ret;
}
@@ -953,7 +952,8 @@ static int mdp5_dev_remove(struct platform_device *pdev)
static __maybe_unused int mdp5_runtime_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
- struct mdp5_kms *mdp5_kms = platform_get_drvdata(pdev);
+ struct msm_drm_private *priv = platform_get_drvdata(pdev);
+ struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
DBG("");
@@ -963,7 +963,8 @@ static __maybe_unused int mdp5_runtime_suspend(struct device *dev)
static __maybe_unused int mdp5_runtime_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
- struct mdp5_kms *mdp5_kms = platform_get_drvdata(pdev);
+ struct msm_drm_private *priv = platform_get_drvdata(pdev);
+ struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms));
DBG("");
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index a49f6dbbe888..7ff60e5ff325 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -857,7 +857,7 @@ static int dp_display_set_mode(struct msm_dp *dp_display,
dp = container_of(dp_display, struct dp_display_private, dp_display);
- dp->panel->dp_mode.drm_mode = mode->drm_mode;
+ drm_mode_copy(&dp->panel->dp_mode.drm_mode, &mode->drm_mode);
dp->panel->dp_mode.bpp = mode->bpp;
dp->panel->dp_mode.capabilities = mode->capabilities;
dp_panel_init_panel_info(dp->panel);
@@ -1600,20 +1600,10 @@ error:
int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
struct drm_encoder *encoder)
{
- struct msm_drm_private *priv;
+ struct msm_drm_private *priv = dev->dev_private;
struct dp_display_private *dp_priv;
int ret;
- if (WARN_ON(!encoder) || WARN_ON(!dp_display) || WARN_ON(!dev))
- return -EINVAL;
-
- priv = dev->dev_private;
-
- if (priv->num_bridges == ARRAY_SIZE(priv->bridges)) {
- DRM_DEV_ERROR(dev->dev, "too many bridges\n");
- return -ENOSPC;
- }
-
dp_display->drm_dev = dev;
dp_priv = container_of(dp_display, struct dp_display_private, dp_display);
diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c
index 36bb6191d2f0..f1f1d646539d 100644
--- a/drivers/gpu/drm/msm/dp/dp_link.c
+++ b/drivers/gpu/drm/msm/dp/dp_link.c
@@ -49,23 +49,26 @@ static int dp_aux_link_power_up(struct drm_dp_aux *aux,
struct dp_link_info *link)
{
u8 value;
- int err;
+ ssize_t len;
+ int i;
if (link->revision < 0x11)
return 0;
- err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
- if (err < 0)
- return err;
+ len = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
+ if (len < 0)
+ return len;
value &= ~DP_SET_POWER_MASK;
value |= DP_SET_POWER_D0;
- err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
- if (err < 0)
- return err;
-
- usleep_range(1000, 2000);
+ /* retry for 1ms to give the sink time to wake up */
+ for (i = 0; i < 3; i++) {
+ len = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
+ usleep_range(1000, 2000);
+ if (len == 1)
+ break;
+ }
return 0;
}
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index 8a95c744972a..31fdee2052be 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -211,14 +211,9 @@ void __exit msm_dsi_unregister(void)
int msm_dsi_modeset_init(struct msm_dsi *msm_dsi, struct drm_device *dev,
struct drm_encoder *encoder)
{
- struct msm_drm_private *priv;
+ struct msm_drm_private *priv = dev->dev_private;
int ret;
- if (WARN_ON(!encoder) || WARN_ON(!msm_dsi) || WARN_ON(!dev))
- return -EINVAL;
-
- priv = dev->dev_private;
-
if (priv->num_bridges == ARRAY_SIZE(priv->bridges)) {
DRM_DEV_ERROR(dev->dev, "too many bridges\n");
return -ENOSPC;
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 7fbf391c024f..89aadd3b3202 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -21,6 +21,7 @@
#include <video/mipi_display.h>
+#include <drm/display/drm_dsc_helper.h>
#include <drm/drm_of.h>
#include "dsi.h"
@@ -33,7 +34,7 @@
#define DSI_RESET_TOGGLE_DELAY_MS 20
-static int dsi_populate_dsc_params(struct drm_dsc_config *dsc);
+static int dsi_populate_dsc_params(struct msm_dsi_host *msm_host, struct drm_dsc_config *dsc);
static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
{
@@ -842,17 +843,15 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mode, u32 hdisplay)
{
struct drm_dsc_config *dsc = msm_host->dsc;
- u32 reg, intf_width, reg_ctrl, reg_ctrl2;
+ u32 reg, reg_ctrl, reg_ctrl2;
u32 slice_per_intf, total_bytes_per_intf;
u32 pkt_per_line;
- u32 bytes_in_slice;
u32 eol_byte_num;
/* first calculate dsc parameters and then program
* compress mode registers
*/
- intf_width = hdisplay;
- slice_per_intf = DIV_ROUND_UP(intf_width, dsc->slice_width);
+ slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->slice_width);
/* If slice_per_pkt is greater than slice_per_intf
* then default to 1. This can happen during partial
@@ -861,12 +860,7 @@ static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mod
if (slice_per_intf > dsc->slice_count)
dsc->slice_count = 1;
- slice_per_intf = DIV_ROUND_UP(hdisplay, dsc->slice_width);
- bytes_in_slice = DIV_ROUND_UP(dsc->slice_width * dsc->bits_per_pixel, 8);
-
- dsc->slice_chunk_size = bytes_in_slice;
-
- total_bytes_per_intf = bytes_in_slice * slice_per_intf;
+ 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;
@@ -892,7 +886,7 @@ static void dsi_update_dsc_timing(struct msm_dsi_host *msm_host, bool is_cmd_mod
reg_ctrl |= reg;
reg_ctrl2 &= ~DSI_COMMAND_COMPRESSION_MODE_CTRL2_STREAM0_SLICE_WIDTH__MASK;
- reg_ctrl2 |= DSI_COMMAND_COMPRESSION_MODE_CTRL2_STREAM0_SLICE_WIDTH(bytes_in_slice);
+ reg_ctrl2 |= DSI_COMMAND_COMPRESSION_MODE_CTRL2_STREAM0_SLICE_WIDTH(dsc->slice_chunk_size);
dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL, reg_ctrl);
dsi_write(msm_host, REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2, reg_ctrl2);
@@ -915,6 +909,7 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
u32 va_end = va_start + mode->vdisplay;
u32 hdisplay = mode->hdisplay;
u32 wc;
+ int ret;
DBG("");
@@ -950,7 +945,9 @@ static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
/* we do the calculations for dsc parameters here so that
* panel can use these parameters
*/
- dsi_populate_dsc_params(dsc);
+ ret = dsi_populate_dsc_params(msm_host, dsc);
+ if (ret)
+ return;
/* Divide the display by 3 but keep back/font porch and
* pulse width same
@@ -1754,18 +1751,20 @@ 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 drm_dsc_config *dsc)
-{
- int mux_words_size;
- int groups_per_line, groups_total;
- int min_rate_buffer_size;
- int hrd_delay;
- int pre_num_extra_mux_bits, num_extra_mux_bits;
- int slice_bits;
- int target_bpp_x16;
- int data;
- int final_value, final_scale;
+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;
+
+ if (dsc->bits_per_pixel & 0xf) {
+ DRM_DEV_ERROR(&msm_host->pdev->dev, "DSI does not support fractional bits_per_pixel\n");
+ return -EINVAL;
+ }
+
+ if (dsc->bits_per_component != 8) {
+ DRM_DEV_ERROR(&msm_host->pdev->dev, "DSI does not support bits_per_component != 8 yet\n");
+ return -EOPNOTSUPP;
+ }
dsc->rc_model_size = 8192;
dsc->first_line_bpg_offset = 12;
@@ -1783,16 +1782,21 @@ static int dsi_populate_dsc_params(struct drm_dsc_config *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];
- dsc->rc_range_params[i].range_bpg_offset = bpg_offset[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;
}
- dsc->initial_offset = 6144; /* Not bpp 12 */
- if (dsc->bits_per_pixel != 8)
+ dsc->initial_offset = 6144; /* Not bpp 12 */
+ if (bpp != 8)
dsc->initial_offset = 2048; /* bpp = 12 */
- mux_words_size = 48; /* bpc == 8/10 */
- if (dsc->bits_per_component == 12)
- mux_words_size = 64;
+ 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;
@@ -1804,63 +1808,8 @@ static int dsi_populate_dsc_params(struct drm_dsc_config *dsc)
dsc->flatness_max_qp = 12;
dsc->rc_quant_incr_limit0 = 11;
dsc->rc_quant_incr_limit1 = 11;
- dsc->mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC;
-
- /* FIXME: need to call drm_dsc_compute_rc_parameters() so that rest of
- * params are calculated
- */
- groups_per_line = DIV_ROUND_UP(dsc->slice_width, 3);
- dsc->slice_chunk_size = dsc->slice_width * dsc->bits_per_pixel / 8;
- if ((dsc->slice_width * dsc->bits_per_pixel) % 8)
- dsc->slice_chunk_size++;
- /* rbs-min */
- min_rate_buffer_size = dsc->rc_model_size - dsc->initial_offset +
- dsc->initial_xmit_delay * dsc->bits_per_pixel +
- groups_per_line * dsc->first_line_bpg_offset;
-
- hrd_delay = DIV_ROUND_UP(min_rate_buffer_size, dsc->bits_per_pixel);
-
- dsc->initial_dec_delay = hrd_delay - dsc->initial_xmit_delay;
-
- dsc->initial_scale_value = 8 * dsc->rc_model_size /
- (dsc->rc_model_size - dsc->initial_offset);
-
- slice_bits = 8 * dsc->slice_chunk_size * dsc->slice_height;
-
- groups_total = groups_per_line * dsc->slice_height;
-
- data = dsc->first_line_bpg_offset * 2048;
-
- dsc->nfl_bpg_offset = DIV_ROUND_UP(data, (dsc->slice_height - 1));
-
- pre_num_extra_mux_bits = 3 * (mux_words_size + (4 * dsc->bits_per_component + 4) - 2);
-
- num_extra_mux_bits = pre_num_extra_mux_bits - (mux_words_size -
- ((slice_bits - pre_num_extra_mux_bits) % mux_words_size));
-
- data = 2048 * (dsc->rc_model_size - dsc->initial_offset + num_extra_mux_bits);
- dsc->slice_bpg_offset = DIV_ROUND_UP(data, groups_total);
-
- /* bpp * 16 + 0.5 */
- data = dsc->bits_per_pixel * 16;
- data *= 2;
- data++;
- data /= 2;
- target_bpp_x16 = data;
-
- data = (dsc->initial_xmit_delay * target_bpp_x16) / 16;
- final_value = dsc->rc_model_size - data + num_extra_mux_bits;
- dsc->final_offset = final_value;
-
- final_scale = 8 * dsc->rc_model_size / (dsc->rc_model_size - final_value);
-
- data = (final_scale - 9) * (dsc->nfl_bpg_offset + dsc->slice_bpg_offset);
- dsc->scale_increment_interval = (2048 * dsc->final_offset) / data;
-
- dsc->scale_decrement_interval = groups_per_line / (dsc->initial_scale_value - 8);
-
- return 0;
+ return drm_dsc_compute_rc_parameters(dsc);
}
static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index 7fc0975cb869..ee6051367679 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -549,6 +549,8 @@ static const struct of_device_id dsi_phy_dt_match[] = {
#ifdef CONFIG_DRM_MSM_DSI_14NM_PHY
{ .compatible = "qcom,dsi-phy-14nm",
.data = &dsi_phy_14nm_cfgs },
+ { .compatible = "qcom,dsi-phy-14nm-2290",
+ .data = &dsi_phy_14nm_2290_cfgs },
{ .compatible = "qcom,dsi-phy-14nm-660",
.data = &dsi_phy_14nm_660_cfgs },
{ .compatible = "qcom,dsi-phy-14nm-8953",
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
index 60a99c6525b2..1096afedd616 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
@@ -50,6 +50,7 @@ extern const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_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;
extern const struct msm_dsi_phy_cfg dsi_phy_14nm_8953_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_10nm_cfgs;
extern const struct msm_dsi_phy_cfg dsi_phy_10nm_8998_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 0f8f4ca46429..9f488adea7f5 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
@@ -1081,3 +1081,20 @@ const struct msm_dsi_phy_cfg dsi_phy_14nm_8953_cfgs = {
.io_start = { 0x1a94400, 0x1a96400 },
.num_dsi_phy = 2,
};
+
+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,
+ .pll_init = dsi_pll_14nm_init,
+ .save_pll_state = dsi_14nm_pll_save_state,
+ .restore_pll_state = dsi_14nm_pll_restore_state,
+ },
+ .min_pll_rate = VCO_MIN_RATE,
+ .max_pll_rate = VCO_MAX_RATE,
+ .io_start = { 0x5e94400 },
+ .num_dsi_phy = 1,
+};
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index f28fb21e3891..4d3fdc806bef 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -68,16 +68,17 @@ static void msm_hdmi_destroy(struct hdmi *hdmi)
destroy_workqueue(hdmi->workq);
msm_hdmi_hdcp_destroy(hdmi);
+ if (hdmi->i2c)
+ msm_hdmi_i2c_destroy(hdmi->i2c);
+}
+
+static void msm_hdmi_put_phy(struct hdmi *hdmi)
+{
if (hdmi->phy_dev) {
put_device(hdmi->phy_dev);
hdmi->phy = NULL;
hdmi->phy_dev = NULL;
}
-
- if (hdmi->i2c)
- msm_hdmi_i2c_destroy(hdmi->i2c);
-
- platform_set_drvdata(hdmi->pdev, NULL);
}
static int msm_hdmi_get_phy(struct hdmi *hdmi)
@@ -93,22 +94,18 @@ static int msm_hdmi_get_phy(struct hdmi *hdmi)
}
phy_pdev = of_find_device_by_node(phy_node);
- if (phy_pdev)
- hdmi->phy = platform_get_drvdata(phy_pdev);
-
of_node_put(phy_node);
- if (!phy_pdev) {
- DRM_DEV_ERROR(&pdev->dev, "phy driver is not ready\n");
- return -EPROBE_DEFER;
- }
+ if (!phy_pdev)
+ return dev_err_probe(&pdev->dev, -EPROBE_DEFER, "phy driver is not ready\n");
+
+ hdmi->phy = platform_get_drvdata(phy_pdev);
if (!hdmi->phy) {
- DRM_DEV_ERROR(&pdev->dev, "phy driver is not ready\n");
put_device(&phy_pdev->dev);
- return -EPROBE_DEFER;
+ return dev_err_probe(&pdev->dev, -EPROBE_DEFER, "phy driver is not ready\n");
}
- hdmi->phy_dev = get_device(&phy_pdev->dev);
+ hdmi->phy_dev = &phy_pdev->dev;
return 0;
}
@@ -117,142 +114,10 @@ static int msm_hdmi_get_phy(struct hdmi *hdmi)
* we are to EPROBE_DEFER we want to do it here, rather than later
* at modeset_init() time
*/
-static struct hdmi *msm_hdmi_init(struct platform_device *pdev)
+static int msm_hdmi_init(struct hdmi *hdmi)
{
- struct hdmi_platform_config *config = pdev->dev.platform_data;
- struct hdmi *hdmi = NULL;
- struct resource *res;
- int i, ret;
-
- hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
- if (!hdmi) {
- ret = -ENOMEM;
- goto fail;
- }
-
- hdmi->pdev = pdev;
- hdmi->config = config;
- spin_lock_init(&hdmi->reg_lock);
-
- ret = drm_of_find_panel_or_bridge(pdev->dev.of_node, 1, 0, NULL, &hdmi->next_bridge);
- if (ret && ret != -ENODEV)
- goto fail;
-
- hdmi->mmio = msm_ioremap(pdev, config->mmio_name);
- if (IS_ERR(hdmi->mmio)) {
- ret = PTR_ERR(hdmi->mmio);
- goto fail;
- }
-
- /* HDCP needs physical address of hdmi register */
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- config->mmio_name);
- if (!res) {
- ret = -EINVAL;
- goto fail;
- }
- hdmi->mmio_phy_addr = res->start;
-
- hdmi->qfprom_mmio = msm_ioremap(pdev, config->qfprom_mmio_name);
- if (IS_ERR(hdmi->qfprom_mmio)) {
- DRM_DEV_INFO(&pdev->dev, "can't find qfprom resource\n");
- hdmi->qfprom_mmio = NULL;
- }
-
- hdmi->hpd_regs = devm_kcalloc(&pdev->dev,
- config->hpd_reg_cnt,
- sizeof(hdmi->hpd_regs[0]),
- GFP_KERNEL);
- if (!hdmi->hpd_regs) {
- ret = -ENOMEM;
- goto fail;
- }
- for (i = 0; i < config->hpd_reg_cnt; i++)
- hdmi->hpd_regs[i].supply = config->hpd_reg_names[i];
-
- ret = devm_regulator_bulk_get(&pdev->dev, config->hpd_reg_cnt, hdmi->hpd_regs);
- if (ret) {
- DRM_DEV_ERROR(&pdev->dev, "failed to get hpd regulator: %d\n", ret);
- goto fail;
- }
-
- hdmi->pwr_regs = devm_kcalloc(&pdev->dev,
- config->pwr_reg_cnt,
- sizeof(hdmi->pwr_regs[0]),
- GFP_KERNEL);
- if (!hdmi->pwr_regs) {
- ret = -ENOMEM;
- goto fail;
- }
-
- for (i = 0; i < config->pwr_reg_cnt; i++)
- hdmi->pwr_regs[i].supply = config->pwr_reg_names[i];
-
- ret = devm_regulator_bulk_get(&pdev->dev, config->pwr_reg_cnt, hdmi->pwr_regs);
- if (ret) {
- DRM_DEV_ERROR(&pdev->dev, "failed to get pwr regulator: %d\n", ret);
- goto fail;
- }
-
- hdmi->hpd_clks = devm_kcalloc(&pdev->dev,
- config->hpd_clk_cnt,
- sizeof(hdmi->hpd_clks[0]),
- GFP_KERNEL);
- if (!hdmi->hpd_clks) {
- ret = -ENOMEM;
- goto fail;
- }
- for (i = 0; i < config->hpd_clk_cnt; i++) {
- struct clk *clk;
-
- clk = msm_clk_get(pdev, config->hpd_clk_names[i]);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- DRM_DEV_ERROR(&pdev->dev, "failed to get hpd clk: %s (%d)\n",
- config->hpd_clk_names[i], ret);
- goto fail;
- }
-
- hdmi->hpd_clks[i] = clk;
- }
-
- hdmi->pwr_clks = devm_kcalloc(&pdev->dev,
- config->pwr_clk_cnt,
- sizeof(hdmi->pwr_clks[0]),
- GFP_KERNEL);
- if (!hdmi->pwr_clks) {
- ret = -ENOMEM;
- goto fail;
- }
- for (i = 0; i < config->pwr_clk_cnt; i++) {
- struct clk *clk;
-
- clk = msm_clk_get(pdev, config->pwr_clk_names[i]);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- DRM_DEV_ERROR(&pdev->dev, "failed to get pwr clk: %s (%d)\n",
- config->pwr_clk_names[i], ret);
- goto fail;
- }
-
- hdmi->pwr_clks[i] = clk;
- }
-
- hdmi->hpd_gpiod = devm_gpiod_get_optional(&pdev->dev, "hpd", GPIOD_IN);
- /* This will catch e.g. -EPROBE_DEFER */
- if (IS_ERR(hdmi->hpd_gpiod)) {
- ret = PTR_ERR(hdmi->hpd_gpiod);
- DRM_DEV_ERROR(&pdev->dev, "failed to get hpd gpio: (%d)\n", ret);
- goto fail;
- }
-
- if (!hdmi->hpd_gpiod)
- DBG("failed to get HPD gpio");
-
- if (hdmi->hpd_gpiod)
- gpiod_set_consumer_name(hdmi->hpd_gpiod, "HDMI_HPD");
-
- pm_runtime_enable(&pdev->dev);
+ struct platform_device *pdev = hdmi->pdev;
+ int ret;
hdmi->workq = alloc_ordered_workqueue("msm_hdmi", 0);
@@ -264,25 +129,18 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev)
goto fail;
}
- ret = msm_hdmi_get_phy(hdmi);
- if (ret) {
- DRM_DEV_ERROR(&pdev->dev, "failed to get phy\n");
- goto fail;
- }
-
hdmi->hdcp_ctrl = msm_hdmi_hdcp_init(hdmi);
if (IS_ERR(hdmi->hdcp_ctrl)) {
dev_warn(&pdev->dev, "failed to init hdcp: disabled\n");
hdmi->hdcp_ctrl = NULL;
}
- return hdmi;
+ return 0;
fail:
- if (hdmi)
- msm_hdmi_destroy(hdmi);
+ msm_hdmi_destroy(hdmi);
- return ERR_PTR(ret);
+ return ret;
}
/* Second part of initialization, the drm/kms level modeset_init,
@@ -297,7 +155,6 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
struct drm_device *dev, struct drm_encoder *encoder)
{
struct msm_drm_private *priv = dev->dev_private;
- struct platform_device *pdev = hdmi->pdev;
int ret;
if (priv->num_bridges == ARRAY_SIZE(priv->bridges)) {
@@ -337,13 +194,6 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
drm_connector_attach_encoder(hdmi->connector, hdmi->encoder);
- hdmi->irq = irq_of_parse_and_map(pdev->dev.of_node, 0);
- if (!hdmi->irq) {
- ret = -EINVAL;
- DRM_DEV_ERROR(dev->dev, "failed to get irq\n");
- goto fail;
- }
-
ret = devm_request_irq(dev->dev, hdmi->irq,
msm_hdmi_irq, IRQF_TRIGGER_HIGH,
"hdmi_isr", hdmi);
@@ -363,8 +213,6 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi,
priv->bridges[priv->num_bridges++] = hdmi->bridge;
- platform_set_drvdata(pdev, hdmi);
-
return 0;
fail:
@@ -392,7 +240,7 @@ fail:
static const char *hpd_reg_names_8960[] = {"core-vdda"};
static const char *hpd_clk_names_8960[] = {"core", "master_iface", "slave_iface"};
-static struct hdmi_platform_config hdmi_tx_8960_config = {
+static const struct hdmi_platform_config hdmi_tx_8960_config = {
HDMI_CFG(hpd_reg, 8960),
HDMI_CFG(hpd_clk, 8960),
};
@@ -402,7 +250,7 @@ static const char *pwr_clk_names_8x74[] = {"extp", "alt_iface"};
static const char *hpd_clk_names_8x74[] = {"iface", "core", "mdp_core"};
static unsigned long hpd_clk_freq_8x74[] = {0, 19200000, 0};
-static struct hdmi_platform_config hdmi_tx_8974_config = {
+static const struct hdmi_platform_config hdmi_tx_8974_config = {
HDMI_CFG(pwr_reg, 8x74),
HDMI_CFG(pwr_clk, 8x74),
HDMI_CFG(hpd_clk, 8x74),
@@ -517,26 +365,12 @@ static int msm_hdmi_register_audio_driver(struct hdmi *hdmi, struct device *dev)
static int msm_hdmi_bind(struct device *dev, struct device *master, void *data)
{
struct msm_drm_private *priv = dev_get_drvdata(master);
- struct hdmi_platform_config *hdmi_cfg;
- struct hdmi *hdmi;
- struct device_node *of_node = dev->of_node;
+ struct hdmi *hdmi = dev_get_drvdata(dev);
int err;
- hdmi_cfg = (struct hdmi_platform_config *)
- of_device_get_match_data(dev);
- if (!hdmi_cfg) {
- DRM_DEV_ERROR(dev, "unknown hdmi_cfg: %pOFn\n", of_node);
- return -ENXIO;
- }
-
- hdmi_cfg->mmio_name = "core_physical";
- hdmi_cfg->qfprom_mmio_name = "qfprom_physical";
-
- dev->platform_data = hdmi_cfg;
-
- hdmi = msm_hdmi_init(to_platform_device(dev));
- if (IS_ERR(hdmi))
- return PTR_ERR(hdmi);
+ err = msm_hdmi_init(hdmi);
+ if (err)
+ return err;
priv->hdmi = hdmi;
err = msm_hdmi_register_audio_driver(hdmi, dev);
@@ -569,12 +403,150 @@ static const struct component_ops msm_hdmi_ops = {
static int msm_hdmi_dev_probe(struct platform_device *pdev)
{
+ const struct hdmi_platform_config *config;
+ struct device *dev = &pdev->dev;
+ struct hdmi *hdmi;
+ struct resource *res;
+ int i, ret;
+
+ config = of_device_get_match_data(dev);
+ if (!config)
+ return -EINVAL;
+
+ hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
+ if (!hdmi)
+ return -ENOMEM;
+
+ hdmi->pdev = pdev;
+ hdmi->config = config;
+ spin_lock_init(&hdmi->reg_lock);
+
+ ret = drm_of_find_panel_or_bridge(pdev->dev.of_node, 1, 0, NULL, &hdmi->next_bridge);
+ if (ret && ret != -ENODEV)
+ return ret;
+
+ hdmi->mmio = msm_ioremap(pdev, "core_physical");
+ if (IS_ERR(hdmi->mmio))
+ return PTR_ERR(hdmi->mmio);
+
+ /* HDCP needs physical address of hdmi register */
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "core_physical");
+ if (!res)
+ return -EINVAL;
+ hdmi->mmio_phy_addr = res->start;
+
+ hdmi->qfprom_mmio = msm_ioremap(pdev, "qfprom_physical");
+ if (IS_ERR(hdmi->qfprom_mmio)) {
+ DRM_DEV_INFO(&pdev->dev, "can't find qfprom resource\n");
+ hdmi->qfprom_mmio = NULL;
+ }
+
+ hdmi->irq = platform_get_irq(pdev, 0);
+ if (hdmi->irq < 0)
+ return hdmi->irq;
+
+ hdmi->hpd_regs = devm_kcalloc(&pdev->dev,
+ config->hpd_reg_cnt,
+ sizeof(hdmi->hpd_regs[0]),
+ GFP_KERNEL);
+ if (!hdmi->hpd_regs)
+ return -ENOMEM;
+
+ for (i = 0; i < config->hpd_reg_cnt; i++)
+ hdmi->hpd_regs[i].supply = config->hpd_reg_names[i];
+
+ ret = devm_regulator_bulk_get(&pdev->dev, config->hpd_reg_cnt, hdmi->hpd_regs);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to get hpd regulators\n");
+
+ hdmi->pwr_regs = devm_kcalloc(&pdev->dev,
+ config->pwr_reg_cnt,
+ sizeof(hdmi->pwr_regs[0]),
+ GFP_KERNEL);
+ if (!hdmi->pwr_regs)
+ return -ENOMEM;
+
+ for (i = 0; i < config->pwr_reg_cnt; i++)
+ hdmi->pwr_regs[i].supply = config->pwr_reg_names[i];
+
+ ret = devm_regulator_bulk_get(&pdev->dev, config->pwr_reg_cnt, hdmi->pwr_regs);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to get pwr regulators\n");
+
+ hdmi->hpd_clks = devm_kcalloc(&pdev->dev,
+ config->hpd_clk_cnt,
+ sizeof(hdmi->hpd_clks[0]),
+ GFP_KERNEL);
+ if (!hdmi->hpd_clks)
+ return -ENOMEM;
+
+ for (i = 0; i < config->hpd_clk_cnt; i++) {
+ struct clk *clk;
+
+ clk = msm_clk_get(pdev, config->hpd_clk_names[i]);
+ if (IS_ERR(clk))
+ return dev_err_probe(dev, PTR_ERR(clk),
+ "failed to get hpd clk: %s\n",
+ config->hpd_clk_names[i]);
+
+ hdmi->hpd_clks[i] = clk;
+ }
+
+ hdmi->pwr_clks = devm_kcalloc(&pdev->dev,
+ config->pwr_clk_cnt,
+ sizeof(hdmi->pwr_clks[0]),
+ GFP_KERNEL);
+ if (!hdmi->pwr_clks)
+ return -ENOMEM;
+
+ for (i = 0; i < config->pwr_clk_cnt; i++) {
+ struct clk *clk;
+
+ clk = msm_clk_get(pdev, config->pwr_clk_names[i]);
+ if (IS_ERR(clk))
+ return dev_err_probe(dev, PTR_ERR(clk),
+ "failed to get pwr clk: %s\n",
+ config->pwr_clk_names[i]);
+
+ hdmi->pwr_clks[i] = clk;
+ }
+
+ hdmi->hpd_gpiod = devm_gpiod_get_optional(&pdev->dev, "hpd", GPIOD_IN);
+ /* This will catch e.g. -EPROBE_DEFER */
+ if (IS_ERR(hdmi->hpd_gpiod))
+ return dev_err_probe(dev, PTR_ERR(hdmi->hpd_gpiod),
+ "failed to get hpd gpio\n");
+
+ if (!hdmi->hpd_gpiod)
+ DBG("failed to get HPD gpio");
+
+ if (hdmi->hpd_gpiod)
+ gpiod_set_consumer_name(hdmi->hpd_gpiod, "HDMI_HPD");
+
+ ret = msm_hdmi_get_phy(hdmi);
+ if (ret) {
+ DRM_DEV_ERROR(&pdev->dev, "failed to get phy\n");
+ return ret;
+ }
+
+ ret = devm_pm_runtime_enable(&pdev->dev);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, hdmi);
+
return component_add(&pdev->dev, &msm_hdmi_ops);
}
static int msm_hdmi_dev_remove(struct platform_device *pdev)
{
+ struct hdmi *hdmi = dev_get_drvdata(&pdev->dev);
+
component_del(&pdev->dev, &msm_hdmi_ops);
+
+ msm_hdmi_put_phy(hdmi);
+
return 0;
}
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 04a74381aaf7..e8dbee50637f 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -86,9 +86,6 @@ struct hdmi {
/* platform config data (ie. from DT, or pdata) */
struct hdmi_platform_config {
- const char *mmio_name;
- const char *qfprom_mmio_name;
-
/* regulators that need to be on for hpd: */
const char **hpd_reg_names;
int hpd_reg_cnt;
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 105b5b48e828..8b0b0ac74a6f 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -277,7 +277,6 @@ static int msm_drm_uninit(struct device *dev)
struct msm_gem_address_space *msm_kms_init_aspace(struct drm_device *dev)
{
- struct iommu_domain *domain;
struct msm_gem_address_space *aspace;
struct msm_mmu *mmu;
struct device *mdp_dev = dev->dev;
@@ -293,22 +292,21 @@ struct msm_gem_address_space *msm_kms_init_aspace(struct drm_device *dev)
else
iommu_dev = mdss_dev;
- domain = iommu_domain_alloc(iommu_dev->bus);
- if (!domain) {
+ mmu = msm_iommu_new(iommu_dev, 0);
+ if (IS_ERR(mmu))
+ return ERR_CAST(mmu);
+
+ if (!mmu) {
drm_info(dev, "no IOMMU, fallback to phys contig buffers for scanout\n");
return NULL;
}
- mmu = msm_iommu_new(iommu_dev, domain);
- if (IS_ERR(mmu)) {
- iommu_domain_free(domain);
- return ERR_CAST(mmu);
- }
-
aspace = msm_gem_address_space_create(mmu, "mdp_kms",
0x1000, 0x100000000 - 0x1000);
- if (IS_ERR(aspace))
+ if (IS_ERR(aspace)) {
+ dev_err(mdp_dev, "aspace create, error %pe\n", aspace);
mmu->funcs->destroy(mmu);
+ }
return aspace;
}
@@ -420,7 +418,6 @@ static int msm_drm_init(struct device *dev, const struct drm_driver *drv)
priv->dev = ddev;
priv->wq = alloc_ordered_workqueue("msm", 0);
- priv->hangcheck_period = DRM_MSM_HANGCHECK_DEFAULT_PERIOD;
INIT_LIST_HEAD(&priv->objects);
mutex_init(&priv->obj_lock);
@@ -819,6 +816,7 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data,
case MSM_INFO_GET_OFFSET:
case MSM_INFO_GET_IOVA:
case MSM_INFO_SET_IOVA:
+ case MSM_INFO_GET_FLAGS:
/* value returned as immediate, not pointer, so len==0: */
if (args->len)
return -EINVAL;
@@ -846,6 +844,15 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data,
case MSM_INFO_SET_IOVA:
ret = msm_ioctl_gem_info_set_iova(dev, file, obj, args->value);
break;
+ case MSM_INFO_GET_FLAGS:
+ if (obj->import_attach) {
+ ret = -EINVAL;
+ break;
+ }
+ /* Hide internal kernel-only flags: */
+ args->value = to_msm_bo(obj)->flags & MSM_BO_FLAGS;
+ ret = 0;
+ break;
case MSM_INFO_SET_NAME:
/* length check should leave room for terminating null: */
if (args->len >= sizeof(msm_obj->name)) {
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index b2ea262296a4..d4e0ef608950 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -224,7 +224,13 @@ struct msm_drm_private {
struct drm_atomic_state *pm_state;
- /* For hang detection, in ms */
+ /**
+ * hangcheck_period: For hang detection, in ms
+ *
+ * Note that in practice, a submit/job will get at least two hangcheck
+ * periods, due to checking for progress being implemented as simply
+ * "have the CP position registers changed since last time?"
+ */
unsigned int hangcheck_period;
/**
diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c
index 46168eccfac4..31e1e30cb52a 100644
--- a/drivers/gpu/drm/msm/msm_fbdev.c
+++ b/drivers/gpu/drm/msm/msm_fbdev.c
@@ -93,7 +93,7 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
goto fail;
}
- fbi = drm_fb_helper_alloc_fbi(helper);
+ fbi = drm_fb_helper_alloc_info(helper);
if (IS_ERR(fbi)) {
DRM_DEV_ERROR(dev->dev, "failed to allocate fb info\n");
ret = PTR_ERR(fbi);
@@ -109,8 +109,6 @@ static int msm_fbdev_create(struct drm_fb_helper *helper,
drm_fb_helper_fill_info(fbi, helper, sizes);
- dev->mode_config.fb_base = paddr;
-
fbi->screen_base = msm_gem_get_vaddr(bo);
if (IS_ERR(fbi->screen_base)) {
ret = PTR_ERR(fbi->screen_base);
@@ -184,7 +182,7 @@ void msm_fbdev_free(struct drm_device *dev)
DBG();
- drm_fb_helper_unregister_fbi(helper);
+ drm_fb_helper_unregister_info(helper);
drm_fb_helper_fini(helper);
diff --git a/drivers/gpu/drm/msm/msm_gem_shrinker.c b/drivers/gpu/drm/msm/msm_gem_shrinker.c
index 1de14e67f96b..051bdbc093cf 100644
--- a/drivers/gpu/drm/msm/msm_gem_shrinker.c
+++ b/drivers/gpu/drm/msm/msm_gem_shrinker.c
@@ -15,7 +15,7 @@
/* Default disabled for now until it has some more testing on the different
* iommu combinations that can be paired with the driver:
*/
-static bool enable_eviction = false;
+static bool enable_eviction = true;
MODULE_PARM_DESC(enable_eviction, "Enable swappable GEM buffers");
module_param(enable_eviction, bool, 0600);
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 45a3e5cadc7d..73a2ca122c57 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -334,8 +334,7 @@ static int submit_fence_sync(struct msm_gem_submit *submit, bool no_implicit)
if (ret)
return ret;
- /* exclusive fences must be ordered */
- if (no_implicit && !write)
+ if (no_implicit)
continue;
ret = drm_sched_job_add_implicit_dependencies(&submit->base,
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 021f4e29b613..30ed45af76ad 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -492,6 +492,21 @@ static void hangcheck_timer_reset(struct msm_gpu *gpu)
round_jiffies_up(jiffies + msecs_to_jiffies(priv->hangcheck_period)));
}
+static bool made_progress(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
+{
+ if (ring->hangcheck_progress_retries >= DRM_MSM_HANGCHECK_PROGRESS_RETRIES)
+ return false;
+
+ if (!gpu->funcs->progress)
+ return false;
+
+ if (!gpu->funcs->progress(gpu, ring))
+ return false;
+
+ ring->hangcheck_progress_retries++;
+ return true;
+}
+
static void hangcheck_handler(struct timer_list *t)
{
struct msm_gpu *gpu = from_timer(gpu, t, hangcheck_timer);
@@ -502,9 +517,12 @@ static void hangcheck_handler(struct timer_list *t)
if (fence != ring->hangcheck_fence) {
/* some progress has been made.. ya! */
ring->hangcheck_fence = fence;
- } else if (fence_before(fence, ring->fctx->last_fence)) {
+ ring->hangcheck_progress_retries = 0;
+ } else if (fence_before(fence, ring->fctx->last_fence) &&
+ !made_progress(gpu, ring)) {
/* no progress and not done.. hung! */
ring->hangcheck_fence = fence;
+ ring->hangcheck_progress_retries = 0;
DRM_DEV_ERROR(dev->dev, "%s: hangcheck detected gpu lockup rb %d!\n",
gpu->name, ring->id);
DRM_DEV_ERROR(dev->dev, "%s: completed fence: %u\n",
@@ -830,6 +848,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
struct msm_gpu *gpu, const struct msm_gpu_funcs *funcs,
const char *name, struct msm_gpu_config *config)
{
+ struct msm_drm_private *priv = drm->dev_private;
int i, ret, nr_rings = config->nr_rings;
void *memptrs;
uint64_t memptrs_iova;
@@ -857,6 +876,16 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
kthread_init_work(&gpu->recover_work, recover_worker);
kthread_init_work(&gpu->fault_work, fault_worker);
+ priv->hangcheck_period = DRM_MSM_HANGCHECK_DEFAULT_PERIOD;
+
+ /*
+ * If progress detection is supported, halve the hangcheck timer
+ * duration, as it takes two iterations of the hangcheck handler
+ * to detect a hang.
+ */
+ if (funcs->progress)
+ priv->hangcheck_period /= 2;
+
timer_setup(&gpu->hangcheck_timer, hangcheck_handler, 0);
spin_lock_init(&gpu->perf_lock);
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 58a72e6b1400..651786bc55e5 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -78,6 +78,15 @@ struct msm_gpu_funcs {
struct msm_gem_address_space *(*create_private_address_space)
(struct msm_gpu *gpu);
uint32_t (*get_rptr)(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
+
+ /**
+ * progress: Has the GPU made progress?
+ *
+ * Return true if GPU position in cmdstream has advanced (or changed)
+ * since the last call. To avoid false negatives, this should account
+ * for cmdstream that is buffered in this FIFO upstream of the CP fw.
+ */
+ bool (*progress)(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
};
/* Additional state for iommu faults: */
@@ -237,6 +246,7 @@ struct msm_gpu {
#define DRM_MSM_INACTIVE_PERIOD 66 /* in ms (roughly four frames) */
#define DRM_MSM_HANGCHECK_DEFAULT_PERIOD 500 /* in ms */
+#define DRM_MSM_HANGCHECK_PROGRESS_RETRIES 3
struct timer_list hangcheck_timer;
/* Fault info for most recent iova fault: */
@@ -540,7 +550,7 @@ static inline void gpu_rmw(struct msm_gpu *gpu, u32 reg, u32 mask, u32 or)
msm_rmw(gpu->mmio + (reg << 2), mask, or);
}
-static inline u64 gpu_read64(struct msm_gpu *gpu, u32 lo, u32 hi)
+static inline u64 gpu_read64(struct msm_gpu *gpu, u32 reg)
{
u64 val;
@@ -558,17 +568,17 @@ static inline u64 gpu_read64(struct msm_gpu *gpu, u32 lo, u32 hi)
* when the lo is read, so make sure to read the lo first to trigger
* that
*/
- val = (u64) msm_readl(gpu->mmio + (lo << 2));
- val |= ((u64) msm_readl(gpu->mmio + (hi << 2)) << 32);
+ val = (u64) msm_readl(gpu->mmio + (reg << 2));
+ val |= ((u64) msm_readl(gpu->mmio + ((reg + 1) << 2)) << 32);
return val;
}
-static inline void gpu_write64(struct msm_gpu *gpu, u32 lo, u32 hi, u64 val)
+static inline void gpu_write64(struct msm_gpu *gpu, u32 reg, u64 val)
{
/* Why not a writeq here? Read the screed above */
- msm_writel(lower_32_bits(val), gpu->mmio + (lo << 2));
- msm_writel(upper_32_bits(val), gpu->mmio + (hi << 2));
+ msm_writel(lower_32_bits(val), gpu->mmio + (reg << 2));
+ msm_writel(upper_32_bits(val), gpu->mmio + ((reg + 1) << 2));
}
int msm_gpu_pm_suspend(struct msm_gpu *gpu);
diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
index 5577cea7c009..c2507582ecf3 100644
--- a/drivers/gpu/drm/msm/msm_iommu.c
+++ b/drivers/gpu/drm/msm/msm_iommu.c
@@ -186,6 +186,13 @@ int msm_iommu_pagetable_params(struct msm_mmu *mmu,
return 0;
}
+struct iommu_domain_geometry *msm_iommu_get_geometry(struct msm_mmu *mmu)
+{
+ struct msm_iommu *iommu = to_msm_iommu(mmu);
+
+ return &iommu->domain->geometry;
+}
+
static const struct msm_mmu_funcs pagetable_funcs = {
.map = msm_iommu_pagetable_map,
.unmap = msm_iommu_pagetable_unmap,
@@ -367,17 +374,23 @@ static const struct msm_mmu_funcs funcs = {
.resume_translation = msm_iommu_resume_translation,
};
-struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain)
+struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks)
{
+ struct iommu_domain *domain;
struct msm_iommu *iommu;
int ret;
+ domain = iommu_domain_alloc(dev->bus);
if (!domain)
- return ERR_PTR(-ENODEV);
+ return NULL;
+
+ iommu_set_pgtable_quirks(domain, quirks);
iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
- if (!iommu)
+ if (!iommu) {
+ iommu_domain_free(domain);
return ERR_PTR(-ENOMEM);
+ }
iommu->domain = domain;
msm_mmu_init(&iommu->base, dev, &funcs, MSM_MMU_IOMMU);
@@ -386,6 +399,7 @@ struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain)
ret = iommu_attach_device(iommu->domain, dev);
if (ret) {
+ iommu_domain_free(domain);
kfree(iommu);
return ERR_PTR(ret);
}
diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
index e13c5c12b775..86b28add1fff 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
@@ -22,6 +22,7 @@
#define HW_REV 0x0
#define HW_INTR_STATUS 0x0010
+#define UBWC_DEC_HW_VERSION 0x58
#define UBWC_STATIC 0x144
#define UBWC_CTRL_2 0x150
#define UBWC_PREDICTION_MODE 0x154
@@ -174,9 +175,63 @@ static int _msm_mdss_irq_domain_add(struct msm_mdss *msm_mdss)
return 0;
}
+#define UBWC_1_0 0x10000000
+#define UBWC_2_0 0x20000000
+#define UBWC_3_0 0x30000000
+#define UBWC_4_0 0x40000000
+
+static void msm_mdss_setup_ubwc_dec_20(struct msm_mdss *msm_mdss,
+ u32 ubwc_static)
+{
+ writel_relaxed(ubwc_static, msm_mdss->mmio + UBWC_STATIC);
+}
+
+static void msm_mdss_setup_ubwc_dec_30(struct msm_mdss *msm_mdss,
+ unsigned int ubwc_version,
+ u32 ubwc_swizzle,
+ u32 highest_bank_bit,
+ u32 macrotile_mode)
+{
+ u32 value = (ubwc_swizzle & 0x1) |
+ (highest_bank_bit & 0x3) << 4 |
+ (macrotile_mode & 0x1) << 12;
+
+ if (ubwc_version == UBWC_3_0)
+ value |= BIT(10);
+
+ if (ubwc_version == UBWC_1_0)
+ value |= BIT(8);
+
+ writel_relaxed(value, msm_mdss->mmio + UBWC_STATIC);
+}
+
+static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss,
+ unsigned int ubwc_version,
+ u32 ubwc_swizzle,
+ u32 ubwc_static,
+ u32 highest_bank_bit,
+ u32 macrotile_mode)
+{
+ u32 value = (ubwc_swizzle & 0x7) |
+ (ubwc_static & 0x1) << 3 |
+ (highest_bank_bit & 0x7) << 4 |
+ (macrotile_mode & 0x1) << 12;
+
+ writel_relaxed(value, msm_mdss->mmio + UBWC_STATIC);
+
+ if (ubwc_version == UBWC_3_0) {
+ 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);
+ writel_relaxed(1, msm_mdss->mmio + UBWC_PREDICTION_MODE);
+ }
+}
+
static int msm_mdss_enable(struct msm_mdss *msm_mdss)
{
int ret;
+ u32 hw_rev;
/*
* Several components have AXI clocks that can only be turned on if
@@ -198,26 +253,39 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss)
if (msm_mdss->is_mdp5)
return 0;
+ hw_rev = readl_relaxed(msm_mdss->mmio + HW_REV);
+ dev_dbg(msm_mdss->dev, "HW_REV: 0x%x\n", hw_rev);
+ dev_dbg(msm_mdss->dev, "UBWC_DEC_HW_VERSION: 0x%x\n",
+ readl_relaxed(msm_mdss->mmio + UBWC_DEC_HW_VERSION));
+
/*
* ubwc config is part of the "mdss" region which is not accessible
* from the rest of the driver. hardcode known configurations here
+ *
+ * Decoder version can be read from the UBWC_DEC_HW_VERSION reg,
+ * UBWC_n and the rest of params comes from hw_catalog.
+ * Unforunately this driver can not access hw catalog, so we have to
+ * hardcode them here.
*/
- switch (readl_relaxed(msm_mdss->mmio + HW_REV)) {
+ switch (hw_rev) {
case DPU_HW_VER_500:
case DPU_HW_VER_501:
- writel_relaxed(0x420, msm_mdss->mmio + UBWC_STATIC);
+ msm_mdss_setup_ubwc_dec_30(msm_mdss, UBWC_3_0, 0, 2, 0);
break;
case DPU_HW_VER_600:
- /* TODO: 0x102e for LP_DDR4 */
- writel_relaxed(0x103e, msm_mdss->mmio + UBWC_STATIC);
- writel_relaxed(2, msm_mdss->mmio + UBWC_CTRL_2);
- writel_relaxed(1, msm_mdss->mmio + UBWC_PREDICTION_MODE);
+ /* TODO: highest_bank_bit = 2 for LP_DDR4 */
+ msm_mdss_setup_ubwc_dec_40(msm_mdss, UBWC_4_0, 6, 1, 3, 1);
break;
case DPU_HW_VER_620:
- writel_relaxed(0x1e, msm_mdss->mmio + UBWC_STATIC);
+ /* UBWC_2_0 */
+ msm_mdss_setup_ubwc_dec_20(msm_mdss, 0x1e);
+ break;
+ case DPU_HW_VER_630:
+ /* UBWC_2_0 */
+ msm_mdss_setup_ubwc_dec_20(msm_mdss, 0x11f);
break;
case DPU_HW_VER_720:
- writel_relaxed(0x101e, msm_mdss->mmio + UBWC_STATIC);
+ msm_mdss_setup_ubwc_dec_40(msm_mdss, UBWC_3_0, 6, 1, 1, 1);
break;
}
@@ -445,6 +513,7 @@ static const struct of_device_id mdss_dt_match[] = {
{ .compatible = "qcom,sc7180-mdss" },
{ .compatible = "qcom,sc7280-mdss" },
{ .compatible = "qcom,sc8180x-mdss" },
+ { .compatible = "qcom,sm6115-mdss" },
{ .compatible = "qcom,sm8150-mdss" },
{ .compatible = "qcom,sm8250-mdss" },
{}
diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h
index de158e1bf765..74cd81e701ff 100644
--- a/drivers/gpu/drm/msm/msm_mmu.h
+++ b/drivers/gpu/drm/msm/msm_mmu.h
@@ -40,7 +40,7 @@ static inline void msm_mmu_init(struct msm_mmu *mmu, struct device *dev,
mmu->type = type;
}
-struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain);
+struct msm_mmu *msm_iommu_new(struct device *dev, unsigned long quirks);
struct msm_mmu *msm_gpummu_new(struct device *dev, struct msm_gpu *gpu);
static inline void msm_mmu_set_fault_handler(struct msm_mmu *mmu, void *arg,
@@ -58,5 +58,6 @@ void msm_gpummu_params(struct msm_mmu *mmu, dma_addr_t *pt_base,
int msm_iommu_pagetable_params(struct msm_mmu *mmu, phys_addr_t *ttbr,
int *asid);
+struct iommu_domain_geometry *msm_iommu_get_geometry(struct msm_mmu *mmu);
#endif /* __MSM_MMU_H__ */
diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.h b/drivers/gpu/drm/msm/msm_ringbuffer.h
index 2a5045abe46e..698b333abccd 100644
--- a/drivers/gpu/drm/msm/msm_ringbuffer.h
+++ b/drivers/gpu/drm/msm/msm_ringbuffer.h
@@ -35,6 +35,11 @@ struct msm_rbmemptrs {
volatile u64 ttbr0;
};
+struct msm_cp_state {
+ uint64_t ib1_base, ib2_base;
+ uint32_t ib1_rem, ib2_rem;
+};
+
struct msm_ringbuffer {
struct msm_gpu *gpu;
int id;
@@ -64,6 +69,29 @@ struct msm_ringbuffer {
uint64_t memptrs_iova;
struct msm_fence_context *fctx;
+ /**
+ * hangcheck_progress_retries:
+ *
+ * The number of extra hangcheck duration cycles that we have given
+ * due to it appearing that the GPU is making forward progress.
+ *
+ * For GPU generations which support progress detection (see.
+ * msm_gpu_funcs::progress()), if the GPU appears to be making progress
+ * (ie. the CP has advanced in the command stream, we'll allow up to
+ * DRM_MSM_HANGCHECK_PROGRESS_RETRIES expirations of the hangcheck timer
+ * before killing the job. But to detect progress we need two sample
+ * points, so the duration of the hangcheck timer is halved. In other
+ * words we'll let the submit run for up to:
+ *
+ * (DRM_MSM_HANGCHECK_DEFAULT_PERIOD / 2) * (DRM_MSM_HANGCHECK_PROGRESS_RETRIES + 1)
+ */
+ int hangcheck_progress_retries;
+
+ /**
+ * last_cp_state: The state of the CP at the last call to gpu->progress()
+ */
+ struct msm_cp_state last_cp_state;
+
/*
* preempt_lock protects preemption and serializes wptr updates against
* preemption. Can be aquired from irq context.
diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index 075002ed6fb0..cc2ceb301b96 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -16,7 +16,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_mode_config.h>
diff --git a/drivers/gpu/drm/mxsfb/lcdif_kms.c b/drivers/gpu/drm/mxsfb/lcdif_kms.c
index b1092aab1423..262bc43b1079 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_kms.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_kms.c
@@ -5,6 +5,7 @@
* This code is based on drivers/gpu/drm/mxsfb/mxsfb*
*/
+#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/iopoll.h>
@@ -15,6 +16,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
+#include <drm/drm_color_mgmt.h>
#include <drm/drm_crtc.h>
#include <drm/drm_encoder.h>
#include <drm/drm_fb_dma_helper.h>
@@ -31,13 +33,126 @@
/* -----------------------------------------------------------------------------
* CRTC
*/
+
+/*
+ * For conversion from YCbCr to RGB, the CSC operates as follows:
+ *
+ * |R| |A1 A2 A3| |Y + D1|
+ * |G| = |B1 B2 B3| * |Cb + D2|
+ * |B| |C1 C2 C3| |Cr + D3|
+ *
+ * The A, B and C coefficients are expressed as Q2.8 fixed point values, and
+ * the D coefficients as Q0.8. Despite the reference manual stating the
+ * opposite, the D1, D2 and D3 offset values are added to Y, Cb and Cr, not
+ * subtracted. They must thus be programmed with negative values.
+ */
+static const u32 lcdif_yuv2rgb_coeffs[3][2][6] = {
+ [DRM_COLOR_YCBCR_BT601] = {
+ [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
+ /*
+ * BT.601 limited range:
+ *
+ * |R| |1.1644 0.0000 1.5960| |Y - 16 |
+ * |G| = |1.1644 -0.3917 -0.8129| * |Cb - 128|
+ * |B| |1.1644 2.0172 0.0000| |Cr - 128|
+ */
+ CSC0_COEF0_A1(0x12a) | CSC0_COEF0_A2(0x000),
+ CSC0_COEF1_A3(0x199) | CSC0_COEF1_B1(0x12a),
+ CSC0_COEF2_B2(0x79c) | CSC0_COEF2_B3(0x730),
+ CSC0_COEF3_C1(0x12a) | CSC0_COEF3_C2(0x204),
+ CSC0_COEF4_C3(0x000) | CSC0_COEF4_D1(0x1f0),
+ CSC0_COEF5_D2(0x180) | CSC0_COEF5_D3(0x180),
+ },
+ [DRM_COLOR_YCBCR_FULL_RANGE] = {
+ /*
+ * BT.601 full range:
+ *
+ * |R| |1.0000 0.0000 1.4020| |Y - 0 |
+ * |G| = |1.0000 -0.3441 -0.7141| * |Cb - 128|
+ * |B| |1.0000 1.7720 0.0000| |Cr - 128|
+ */
+ CSC0_COEF0_A1(0x100) | CSC0_COEF0_A2(0x000),
+ CSC0_COEF1_A3(0x167) | CSC0_COEF1_B1(0x100),
+ CSC0_COEF2_B2(0x7a8) | CSC0_COEF2_B3(0x749),
+ CSC0_COEF3_C1(0x100) | CSC0_COEF3_C2(0x1c6),
+ CSC0_COEF4_C3(0x000) | CSC0_COEF4_D1(0x000),
+ CSC0_COEF5_D2(0x180) | CSC0_COEF5_D3(0x180),
+ },
+ },
+ [DRM_COLOR_YCBCR_BT709] = {
+ [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
+ /*
+ * Rec.709 limited range:
+ *
+ * |R| |1.1644 0.0000 1.7927| |Y - 16 |
+ * |G| = |1.1644 -0.2132 -0.5329| * |Cb - 128|
+ * |B| |1.1644 2.1124 0.0000| |Cr - 128|
+ */
+ CSC0_COEF0_A1(0x12a) | CSC0_COEF0_A2(0x000),
+ CSC0_COEF1_A3(0x1cb) | CSC0_COEF1_B1(0x12a),
+ CSC0_COEF2_B2(0x7c9) | CSC0_COEF2_B3(0x778),
+ CSC0_COEF3_C1(0x12a) | CSC0_COEF3_C2(0x21d),
+ CSC0_COEF4_C3(0x000) | CSC0_COEF4_D1(0x1f0),
+ CSC0_COEF5_D2(0x180) | CSC0_COEF5_D3(0x180),
+ },
+ [DRM_COLOR_YCBCR_FULL_RANGE] = {
+ /*
+ * Rec.709 full range:
+ *
+ * |R| |1.0000 0.0000 1.5748| |Y - 0 |
+ * |G| = |1.0000 -0.1873 -0.4681| * |Cb - 128|
+ * |B| |1.0000 1.8556 0.0000| |Cr - 128|
+ */
+ CSC0_COEF0_A1(0x100) | CSC0_COEF0_A2(0x000),
+ CSC0_COEF1_A3(0x193) | CSC0_COEF1_B1(0x100),
+ CSC0_COEF2_B2(0x7d0) | CSC0_COEF2_B3(0x788),
+ CSC0_COEF3_C1(0x100) | CSC0_COEF3_C2(0x1db),
+ CSC0_COEF4_C3(0x000) | CSC0_COEF4_D1(0x000),
+ CSC0_COEF5_D2(0x180) | CSC0_COEF5_D3(0x180),
+ },
+ },
+ [DRM_COLOR_YCBCR_BT2020] = {
+ [DRM_COLOR_YCBCR_LIMITED_RANGE] = {
+ /*
+ * BT.2020 limited range:
+ *
+ * |R| |1.1644 0.0000 1.6787| |Y - 16 |
+ * |G| = |1.1644 -0.1874 -0.6505| * |Cb - 128|
+ * |B| |1.1644 2.1418 0.0000| |Cr - 128|
+ */
+ CSC0_COEF0_A1(0x12a) | CSC0_COEF0_A2(0x000),
+ CSC0_COEF1_A3(0x1ae) | CSC0_COEF1_B1(0x12a),
+ CSC0_COEF2_B2(0x7d0) | CSC0_COEF2_B3(0x759),
+ CSC0_COEF3_C1(0x12a) | CSC0_COEF3_C2(0x224),
+ CSC0_COEF4_C3(0x000) | CSC0_COEF4_D1(0x1f0),
+ CSC0_COEF5_D2(0x180) | CSC0_COEF5_D3(0x180),
+ },
+ [DRM_COLOR_YCBCR_FULL_RANGE] = {
+ /*
+ * BT.2020 full range:
+ *
+ * |R| |1.0000 0.0000 1.4746| |Y - 0 |
+ * |G| = |1.0000 -0.1646 -0.5714| * |Cb - 128|
+ * |B| |1.0000 1.8814 0.0000| |Cr - 128|
+ */
+ CSC0_COEF0_A1(0x100) | CSC0_COEF0_A2(0x000),
+ CSC0_COEF1_A3(0x179) | CSC0_COEF1_B1(0x100),
+ CSC0_COEF2_B2(0x7d6) | CSC0_COEF2_B3(0x76e),
+ CSC0_COEF3_C1(0x100) | CSC0_COEF3_C2(0x1e2),
+ CSC0_COEF4_C3(0x000) | CSC0_COEF4_D1(0x000),
+ CSC0_COEF5_D2(0x180) | CSC0_COEF5_D3(0x180),
+ },
+ },
+};
+
static void lcdif_set_formats(struct lcdif_drm_private *lcdif,
+ struct drm_plane_state *plane_state,
const u32 bus_format)
{
struct drm_device *drm = lcdif->drm;
- const u32 format = lcdif->crtc.primary->state->fb->format->format;
-
- writel(CSC0_CTRL_BYPASS, lcdif->base + LCDC_V8_CSC0_CTRL);
+ const u32 format = plane_state->fb->format->format;
+ bool in_yuv = false;
+ bool out_yuv = false;
switch (bus_format) {
case MEDIA_BUS_FMT_RGB565_1X16:
@@ -51,24 +166,7 @@ static void lcdif_set_formats(struct lcdif_drm_private *lcdif,
case MEDIA_BUS_FMT_UYVY8_1X16:
writel(DISP_PARA_LINE_PATTERN_UYVY_H,
lcdif->base + LCDC_V8_DISP_PARA);
-
- /* CSC: BT.601 Full Range RGB to YCbCr coefficients. */
- writel(CSC0_COEF0_A2(0x096) | CSC0_COEF0_A1(0x04c),
- lcdif->base + LCDC_V8_CSC0_COEF0);
- writel(CSC0_COEF1_B1(0x7d5) | CSC0_COEF1_A3(0x01d),
- lcdif->base + LCDC_V8_CSC0_COEF1);
- writel(CSC0_COEF2_B3(0x080) | CSC0_COEF2_B2(0x7ac),
- lcdif->base + LCDC_V8_CSC0_COEF2);
- writel(CSC0_COEF3_C2(0x795) | CSC0_COEF3_C1(0x080),
- lcdif->base + LCDC_V8_CSC0_COEF3);
- writel(CSC0_COEF4_D1(0x000) | CSC0_COEF4_C3(0x7ec),
- lcdif->base + LCDC_V8_CSC0_COEF4);
- writel(CSC0_COEF5_D3(0x080) | CSC0_COEF5_D2(0x080),
- lcdif->base + LCDC_V8_CSC0_COEF5);
-
- writel(CSC0_CTRL_CSC_MODE_RGB2YCbCr,
- lcdif->base + LCDC_V8_CSC0_CTRL);
-
+ out_yuv = true;
break;
default:
dev_err(drm->dev, "Unknown media bus format 0x%x\n", bus_format);
@@ -76,6 +174,7 @@ static void lcdif_set_formats(struct lcdif_drm_private *lcdif,
}
switch (format) {
+ /* RGB Formats */
case DRM_FORMAT_RGB565:
writel(CTRLDESCL0_5_BPP_16_RGB565,
lcdif->base + LCDC_V8_CTRLDESCL0_5);
@@ -100,10 +199,84 @@ static void lcdif_set_formats(struct lcdif_drm_private *lcdif,
writel(CTRLDESCL0_5_BPP_32_ARGB8888,
lcdif->base + LCDC_V8_CTRLDESCL0_5);
break;
+
+ /* YUV Formats */
+ case DRM_FORMAT_YUYV:
+ writel(CTRLDESCL0_5_BPP_YCbCr422 | CTRLDESCL0_5_YUV_FORMAT_VY2UY1,
+ lcdif->base + LCDC_V8_CTRLDESCL0_5);
+ in_yuv = true;
+ break;
+ case DRM_FORMAT_YVYU:
+ writel(CTRLDESCL0_5_BPP_YCbCr422 | CTRLDESCL0_5_YUV_FORMAT_UY2VY1,
+ lcdif->base + LCDC_V8_CTRLDESCL0_5);
+ in_yuv = true;
+ break;
+ case DRM_FORMAT_UYVY:
+ writel(CTRLDESCL0_5_BPP_YCbCr422 | CTRLDESCL0_5_YUV_FORMAT_Y2VY1U,
+ lcdif->base + LCDC_V8_CTRLDESCL0_5);
+ in_yuv = true;
+ break;
+ case DRM_FORMAT_VYUY:
+ writel(CTRLDESCL0_5_BPP_YCbCr422 | CTRLDESCL0_5_YUV_FORMAT_Y2UY1V,
+ lcdif->base + LCDC_V8_CTRLDESCL0_5);
+ in_yuv = true;
+ break;
+
default:
dev_err(drm->dev, "Unknown pixel format 0x%x\n", format);
break;
}
+
+ /*
+ * The CSC differentiates between "YCbCr" and "YUV", but the reference
+ * manual doesn't detail how they differ. Experiments showed that the
+ * luminance value is unaffected, only the calculations involving chroma
+ * values differ. The YCbCr mode behaves as expected, with chroma values
+ * being offset by 128. The YUV mode isn't fully understood.
+ */
+ if (!in_yuv && out_yuv) {
+ /* RGB -> YCbCr */
+ writel(CSC0_CTRL_CSC_MODE_RGB2YCbCr,
+ lcdif->base + LCDC_V8_CSC0_CTRL);
+
+ /*
+ * CSC: BT.601 Limited Range RGB to YCbCr coefficients.
+ *
+ * |Y | | 0.2568 0.5041 0.0979| |R| |16 |
+ * |Cb| = |-0.1482 -0.2910 0.4392| * |G| + |128|
+ * |Cr| | 0.4392 0.4392 -0.3678| |B| |128|
+ */
+ writel(CSC0_COEF0_A2(0x081) | CSC0_COEF0_A1(0x041),
+ lcdif->base + LCDC_V8_CSC0_COEF0);
+ writel(CSC0_COEF1_B1(0x7db) | CSC0_COEF1_A3(0x019),
+ lcdif->base + LCDC_V8_CSC0_COEF1);
+ writel(CSC0_COEF2_B3(0x070) | CSC0_COEF2_B2(0x7b6),
+ lcdif->base + LCDC_V8_CSC0_COEF2);
+ writel(CSC0_COEF3_C2(0x7a2) | CSC0_COEF3_C1(0x070),
+ lcdif->base + LCDC_V8_CSC0_COEF3);
+ writel(CSC0_COEF4_D1(0x010) | CSC0_COEF4_C3(0x7ee),
+ lcdif->base + LCDC_V8_CSC0_COEF4);
+ writel(CSC0_COEF5_D3(0x080) | CSC0_COEF5_D2(0x080),
+ lcdif->base + LCDC_V8_CSC0_COEF5);
+ } else if (in_yuv && !out_yuv) {
+ /* YCbCr -> RGB */
+ const u32 *coeffs =
+ lcdif_yuv2rgb_coeffs[plane_state->color_encoding]
+ [plane_state->color_range];
+
+ writel(CSC0_CTRL_CSC_MODE_YCbCr2RGB,
+ lcdif->base + LCDC_V8_CSC0_CTRL);
+
+ writel(coeffs[0], lcdif->base + LCDC_V8_CSC0_COEF0);
+ writel(coeffs[1], lcdif->base + LCDC_V8_CSC0_COEF1);
+ writel(coeffs[2], lcdif->base + LCDC_V8_CSC0_COEF2);
+ writel(coeffs[3], lcdif->base + LCDC_V8_CSC0_COEF3);
+ writel(coeffs[4], lcdif->base + LCDC_V8_CSC0_COEF4);
+ writel(coeffs[5], lcdif->base + LCDC_V8_CSC0_COEF5);
+ } else {
+ /* RGB -> RGB, YCbCr -> YCbCr: bypass colorspace converter. */
+ writel(CSC0_CTRL_BYPASS, lcdif->base + LCDC_V8_CSC0_CTRL);
+ }
}
static void lcdif_set_mode(struct lcdif_drm_private *lcdif, u32 bus_flags)
@@ -142,14 +315,36 @@ static void lcdif_set_mode(struct lcdif_drm_private *lcdif, u32 bus_flags)
CTRLDESCL0_1_WIDTH(m->hdisplay),
lcdif->base + LCDC_V8_CTRLDESCL0_1);
- writel(CTRLDESCL0_3_PITCH(lcdif->crtc.primary->state->fb->pitches[0]),
- lcdif->base + LCDC_V8_CTRLDESCL0_3);
+ /*
+ * Undocumented P_SIZE and T_SIZE register but those written in the
+ * downstream kernel those registers control the AXI burst size. As of
+ * now there are two known values:
+ * 1 - 128Byte
+ * 2 - 256Byte
+ * Downstream set it to 256B burst size to improve the memory
+ * efficiency so set it here too.
+ */
+ ctrl = CTRLDESCL0_3_P_SIZE(2) | CTRLDESCL0_3_T_SIZE(2) |
+ CTRLDESCL0_3_PITCH(lcdif->crtc.primary->state->fb->pitches[0]);
+ writel(ctrl, lcdif->base + LCDC_V8_CTRLDESCL0_3);
}
static void lcdif_enable_controller(struct lcdif_drm_private *lcdif)
{
u32 reg;
+ /* Set FIFO Panic watermarks, low 1/3, high 2/3 . */
+ writel(FIELD_PREP(PANIC0_THRES_LOW_MASK, 1 * PANIC0_THRES_MAX / 3) |
+ FIELD_PREP(PANIC0_THRES_HIGH_MASK, 2 * PANIC0_THRES_MAX / 3),
+ lcdif->base + LCDC_V8_PANIC0_THRES);
+
+ /*
+ * Enable FIFO Panic, this does not generate interrupt, but
+ * boosts NoC priority based on FIFO Panic watermarks.
+ */
+ writel(INT_ENABLE_D1_PLANE_PANIC_EN,
+ lcdif->base + LCDC_V8_INT_ENABLE_D1);
+
reg = readl(lcdif->base + LCDC_V8_DISP_PARA);
reg |= DISP_PARA_DISP_ON;
writel(reg, lcdif->base + LCDC_V8_DISP_PARA);
@@ -177,6 +372,9 @@ static void lcdif_disable_controller(struct lcdif_drm_private *lcdif)
reg = readl(lcdif->base + LCDC_V8_DISP_PARA);
reg &= ~DISP_PARA_DISP_ON;
writel(reg, lcdif->base + LCDC_V8_DISP_PARA);
+
+ /* Disable FIFO Panic NoC priority booster. */
+ writel(0, lcdif->base + LCDC_V8_INT_ENABLE_D1);
}
static void lcdif_reset_block(struct lcdif_drm_private *lcdif)
@@ -188,6 +386,7 @@ static void lcdif_reset_block(struct lcdif_drm_private *lcdif)
}
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)
{
@@ -210,7 +409,7 @@ static void lcdif_crtc_mode_set_nofb(struct lcdif_drm_private *lcdif,
/* Mandatory eLCDIF reset as per the Reference Manual */
lcdif_reset_block(lcdif);
- lcdif_set_formats(lcdif, bus_format);
+ lcdif_set_formats(lcdif, plane_state, bus_format);
lcdif_set_mode(lcdif, bus_flags);
}
@@ -293,7 +492,7 @@ static void lcdif_crtc_atomic_enable(struct drm_crtc *crtc,
pm_runtime_get_sync(drm->dev);
- lcdif_crtc_mode_set_nofb(lcdif, bridge_state, bus_format);
+ lcdif_crtc_mode_set_nofb(lcdif, new_pstate, bridge_state, bus_format);
/* Write cur_buf as well to avoid an initial corrupt frame */
paddr = drm_fb_dma_get_gem_addr(new_pstate->fb, new_pstate, 0);
@@ -437,12 +636,19 @@ static const struct drm_plane_funcs lcdif_plane_funcs = {
};
static const u32 lcdif_primary_plane_formats[] = {
+ /* RGB */
DRM_FORMAT_RGB565,
DRM_FORMAT_RGB888,
DRM_FORMAT_XBGR8888,
DRM_FORMAT_XRGB1555,
DRM_FORMAT_XRGB4444,
DRM_FORMAT_XRGB8888,
+
+ /* Packed YCbCr */
+ DRM_FORMAT_YUYV,
+ DRM_FORMAT_YVYU,
+ DRM_FORMAT_UYVY,
+ DRM_FORMAT_VYUY,
};
static const u64 lcdif_modifiers[] = {
@@ -456,6 +662,11 @@ static const u64 lcdif_modifiers[] = {
int lcdif_kms_init(struct lcdif_drm_private *lcdif)
{
+ const u32 supported_encodings = BIT(DRM_COLOR_YCBCR_BT601) |
+ BIT(DRM_COLOR_YCBCR_BT709) |
+ 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;
@@ -471,6 +682,14 @@ int lcdif_kms_init(struct lcdif_drm_private *lcdif)
if (ret)
return ret;
+ ret = drm_plane_create_color_properties(&lcdif->planes.primary,
+ supported_encodings,
+ supported_ranges,
+ DRM_COLOR_YCBCR_BT601,
+ DRM_COLOR_YCBCR_LIMITED_RANGE);
+ if (ret)
+ return ret;
+
drm_crtc_helper_add(crtc, &lcdif_crtc_helper_funcs);
ret = drm_crtc_init_with_planes(lcdif->drm, crtc,
&lcdif->planes.primary, NULL,
diff --git a/drivers/gpu/drm/mxsfb/lcdif_regs.h b/drivers/gpu/drm/mxsfb/lcdif_regs.h
index c70220651e3a..c55dfb236c1d 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_regs.h
+++ b/drivers/gpu/drm/mxsfb/lcdif_regs.h
@@ -130,7 +130,7 @@
#define CTRL_FETCH_START_OPTION_BPV BIT(9)
#define CTRL_FETCH_START_OPTION_RESV GENMASK(9, 8)
#define CTRL_FETCH_START_OPTION_MASK GENMASK(9, 8)
-#define CTRL_NEG BIT(4)
+#define CTRL_NEG BIT(4)
#define CTRL_INV_PXCK BIT(3)
#define CTRL_INV_DE BIT(2)
#define CTRL_INV_VS BIT(1)
@@ -138,9 +138,9 @@
#define DISP_PARA_DISP_ON BIT(31)
#define DISP_PARA_SWAP_EN BIT(30)
-#define DISP_PARA_LINE_PATTERN_UYVY_H (GENMASK(29, 28) | BIT(26))
-#define DISP_PARA_LINE_PATTERN_RGB565 GENMASK(28, 26)
-#define DISP_PARA_LINE_PATTERN_RGB888 0
+#define DISP_PARA_LINE_PATTERN_UYVY_H (0xd << 26)
+#define DISP_PARA_LINE_PATTERN_RGB565 (0x7 << 26)
+#define DISP_PARA_LINE_PATTERN_RGB888 (0x0 << 26)
#define DISP_PARA_LINE_PATTERN_MASK GENMASK(29, 26)
#define DISP_PARA_DISP_MODE_MASK GENMASK(25, 24)
#define DISP_PARA_BGND_R_MASK GENMASK(23, 16)
@@ -186,10 +186,14 @@
#define INT_ENABLE_D1_PLANE_PANIC_EN BIT(0)
#define CTRLDESCL0_1_HEIGHT(n) (((n) & 0xffff) << 16)
-#define CTRLDESCL0_1_HEIGHT_MASK GENMASK(31, 16)
+#define CTRLDESCL0_1_HEIGHT_MASK GENMASK(31, 16)
#define CTRLDESCL0_1_WIDTH(n) ((n) & 0xffff)
#define CTRLDESCL0_1_WIDTH_MASK GENMASK(15, 0)
+#define CTRLDESCL0_3_P_SIZE(n) (((n) << 20) & CTRLDESCL0_3_P_SIZE_MASK)
+#define CTRLDESCL0_3_P_SIZE_MASK GENMASK(22, 20)
+#define CTRLDESCL0_3_T_SIZE(n) (((n) << 16) & CTRLDESCL0_3_T_SIZE_MASK)
+#define CTRLDESCL0_3_T_SIZE_MASK GENMASK(17, 16)
#define CTRLDESCL0_3_PITCH(n) ((n) & 0xffff)
#define CTRLDESCL0_3_PITCH_MASK GENMASK(15, 0)
@@ -198,21 +202,24 @@
#define CTRLDESCL0_5_EN BIT(31)
#define CTRLDESCL0_5_SHADOW_LOAD_EN BIT(30)
-#define CTRLDESCL0_5_BPP_16_RGB565 BIT(26)
-#define CTRLDESCL0_5_BPP_16_ARGB1555 (BIT(26) | BIT(24))
-#define CTRLDESCL0_5_BPP_16_ARGB4444 (BIT(26) | BIT(25))
-#define CTRLDESCL0_5_BPP_YCbCr422 (BIT(26) | BIT(25) | BIT(24))
-#define CTRLDESCL0_5_BPP_24_RGB888 BIT(27)
-#define CTRLDESCL0_5_BPP_32_ARGB8888 (BIT(27) | BIT(24))
-#define CTRLDESCL0_5_BPP_32_ABGR8888 (BIT(27) | BIT(25))
+#define CTRLDESCL0_5_BPP_16_RGB565 (0x4 << 24)
+#define CTRLDESCL0_5_BPP_16_ARGB1555 (0x5 << 24)
+#define CTRLDESCL0_5_BPP_16_ARGB4444 (0x6 << 24)
+#define CTRLDESCL0_5_BPP_YCbCr422 (0x7 << 24)
+#define CTRLDESCL0_5_BPP_24_RGB888 (0x8 << 24)
+#define CTRLDESCL0_5_BPP_32_ARGB8888 (0x9 << 24)
+#define CTRLDESCL0_5_BPP_32_ABGR8888 (0xa << 24)
#define CTRLDESCL0_5_BPP_MASK GENMASK(27, 24)
-#define CTRLDESCL0_5_YUV_FORMAT_Y2VY1U 0
-#define CTRLDESCL0_5_YUV_FORMAT_Y2UY1V BIT(14)
-#define CTRLDESCL0_5_YUV_FORMAT_VY2UY1 BIT(15)
-#define CTRLDESCL0_5_YUV_FORMAT_UY2VY1 (BIT(15) | BIT(14))
+#define CTRLDESCL0_5_YUV_FORMAT_Y2VY1U (0x0 << 14)
+#define CTRLDESCL0_5_YUV_FORMAT_Y2UY1V (0x1 << 14)
+#define CTRLDESCL0_5_YUV_FORMAT_VY2UY1 (0x2 << 14)
+#define CTRLDESCL0_5_YUV_FORMAT_UY2VY1 (0x3 << 14)
#define CTRLDESCL0_5_YUV_FORMAT_MASK GENMASK(15, 14)
-#define CSC0_CTRL_CSC_MODE_RGB2YCbCr GENMASK(2, 1)
+#define CSC0_CTRL_CSC_MODE_YUV2RGB (0x0 << 1)
+#define CSC0_CTRL_CSC_MODE_YCbCr2RGB (0x1 << 1)
+#define CSC0_CTRL_CSC_MODE_RGB2YUV (0x2 << 1)
+#define CSC0_CTRL_CSC_MODE_RGB2YCbCr (0x3 << 1)
#define CSC0_CTRL_CSC_MODE_MASK GENMASK(2, 1)
#define CSC0_CTRL_BYPASS BIT(0)
@@ -248,6 +255,7 @@
#define PANIC0_THRES_LOW_MASK GENMASK(24, 16)
#define PANIC0_THRES_HIGH_MASK GENMASK(8, 0)
+#define PANIC0_THRES_MAX 511
#define LCDIF_MIN_XRES 120
#define LCDIF_MIN_YRES 120
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index b29b332ed381..810edea0a31e 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -20,7 +20,7 @@
#include <drm/drm_bridge.h>
#include <drm/drm_connector.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
diff --git a/drivers/gpu/drm/nouveau/Kbuild b/drivers/gpu/drm/nouveau/Kbuild
index 60586fb8275e..5e5617006da5 100644
--- a/drivers/gpu/drm/nouveau/Kbuild
+++ b/drivers/gpu/drm/nouveau/Kbuild
@@ -54,10 +54,6 @@ nouveau-y += nouveau_bios.o
nouveau-y += nouveau_connector.o
nouveau-y += nouveau_display.o
nouveau-y += nouveau_dp.o
-nouveau-y += nouveau_fbcon.o
-nouveau-y += nv04_fbcon.o
-nouveau-y += nv50_fbcon.o
-nouveau-y += nvc0_fbcon.o
include $(src)/dispnv04/Kbuild
include $(src)/dispnv50/Kbuild
diff --git a/drivers/gpu/drm/nouveau/dispnv04/crtc.c b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
index ee92d576d277..0e0f117bc70b 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/crtc.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/crtc.c
@@ -23,6 +23,7 @@
* DEALINGS IN THE SOFTWARE.
*/
#include <drm/drm_crtc_helper.h>
+#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_vblank.h>
@@ -37,7 +38,6 @@
#include "nouveau_crtc.h"
#include "hw.h"
#include "nvreg.h"
-#include "nouveau_fbcon.h"
#include "disp.h"
#include "nouveau_dma.h"
@@ -761,7 +761,8 @@ static void nv_crtc_destroy(struct drm_crtc *crtc)
nouveau_bo_unmap(nv_crtc->cursor.nvbo);
nouveau_bo_unpin(nv_crtc->cursor.nvbo);
nouveau_bo_ref(NULL, &nv_crtc->cursor.nvbo);
- nvif_notify_dtor(&nv_crtc->vblank);
+ nvif_event_dtor(&nv_crtc->vblank);
+ nvif_head_dtor(&nv_crtc->head);
kfree(nv_crtc);
}
@@ -914,14 +915,6 @@ nv04_crtc_mode_set_base_atomic(struct drm_crtc *crtc,
struct drm_framebuffer *fb,
int x, int y, enum mode_set_atomic state)
{
- struct nouveau_drm *drm = nouveau_drm(crtc->dev);
- struct drm_device *dev = drm->dev;
-
- if (state == ENTER_ATOMIC_MODE_SET)
- nouveau_fbcon_accel_save_disable(dev);
- else
- nouveau_fbcon_accel_restore(dev);
-
return nv04_crtc_do_mode_set_base(crtc, fb, x, y, true);
}
@@ -1080,10 +1073,10 @@ nv04_finish_page_flip(struct nouveau_channel *chan,
}
int
-nv04_flip_complete(struct nvif_notify *notify)
+nv04_flip_complete(struct nvif_event *event, void *argv, u32 argc)
{
- struct nouveau_cli *cli = (void *)notify->object->client;
- struct nouveau_drm *drm = cli->drm;
+ struct nv04_display *disp = container_of(event, typeof(*disp), flip);
+ struct nouveau_drm *drm = disp->drm;
struct nouveau_channel *chan = drm->channel;
struct nv04_page_flip_state state;
@@ -1094,7 +1087,7 @@ nv04_flip_complete(struct nvif_notify *notify)
state.bpp / 8);
}
- return NVIF_NOTIFY_KEEP;
+ return NVIF_EVENT_KEEP;
}
static int
@@ -1279,13 +1272,13 @@ static const struct drm_plane_funcs nv04_primary_plane_funcs = {
DRM_PLANE_NON_ATOMIC_FUNCS,
};
-static int nv04_crtc_vblank_handler(struct nvif_notify *notify)
+static int
+nv04_crtc_vblank_handler(struct nvif_event *event, void *repv, u32 repc)
{
- struct nouveau_crtc *nv_crtc =
- container_of(notify, struct nouveau_crtc, vblank);
+ struct nouveau_crtc *nv_crtc = container_of(event, struct nouveau_crtc, vblank);
drm_crtc_handle_vblank(&nv_crtc->base);
- return NVIF_NOTIFY_KEEP;
+ return NVIF_EVENT_KEEP;
}
int
@@ -1341,14 +1334,10 @@ nv04_crtc_create(struct drm_device *dev, int crtc_num)
nv04_cursor_init(nv_crtc);
- ret = nvif_notify_ctor(&disp->disp.object, "kmsVbl", nv04_crtc_vblank_handler,
- false, NV04_DISP_NTFY_VBLANK,
- &(struct nvif_notify_head_req_v0) {
- .head = nv_crtc->index,
- },
- sizeof(struct nvif_notify_head_req_v0),
- sizeof(struct nvif_notify_head_rep_v0),
- &nv_crtc->vblank);
+ ret = nvif_head_ctor(&disp->disp, nv_crtc->base.name, nv_crtc->index, &nv_crtc->head);
+ if (ret)
+ return ret;
- return ret;
+ return nvif_head_vblank_event_ctor(&nv_crtc->head, "kmsVbl", nv04_crtc_vblank_handler,
+ false, &nv_crtc->vblank);
}
diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c
index 99fee4d8cd31..e9ac3fb27ff7 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c
@@ -61,7 +61,7 @@ nv04_display_fini(struct drm_device *dev, bool runtime, bool suspend)
struct drm_crtc *crtc;
/* Disable flip completion events. */
- nvif_notify_put(&disp->flip);
+ nvif_event_block(&disp->flip);
/* Disable vblank interrupts. */
NVWriteCRTC(dev, 0, NV_PCRTC_INTR_EN_0, 0);
@@ -121,7 +121,7 @@ nv04_display_init(struct drm_device *dev, bool resume, bool runtime)
encoder->enc_save(&encoder->base.base);
/* Enable flip completion events. */
- nvif_notify_get(&disp->flip);
+ nvif_event_allow(&disp->flip);
if (!resume)
return 0;
@@ -202,7 +202,7 @@ nv04_display_destroy(struct drm_device *dev)
nouveau_hw_save_vga_fonts(dev, 0);
- nvif_notify_dtor(&disp->flip);
+ nvif_event_dtor(&disp->flip);
nouveau_display(dev)->priv = NULL;
vfree(disp);
@@ -227,6 +227,8 @@ nv04_display_create(struct drm_device *dev)
if (!disp)
return -ENOMEM;
+ disp->drm = drm;
+
nvif_object_map(&drm->client.device.object, NULL, 0);
nouveau_display(dev)->priv = disp;
@@ -239,9 +241,10 @@ nv04_display_create(struct drm_device *dev)
/* Request page flip completion event. */
if (drm->channel) {
- nvif_notify_ctor(&drm->channel->nvsw, "kmsFlip", nv04_flip_complete,
- false, NV04_NVSW_NTFY_UEVENT,
- NULL, 0, 0, &disp->flip);
+ ret = nvif_event_ctor(&drm->channel->nvsw, "kmsFlip", 0, nv04_flip_complete,
+ true, NULL, 0, &disp->flip);
+ if (ret)
+ return ret;
}
nouveau_hw_save_vga_fonts(dev, 1);
diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.h b/drivers/gpu/drm/nouveau/dispnv04/disp.h
index f0a24126641a..11a6663758ec 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/disp.h
+++ b/drivers/gpu/drm/nouveau/dispnv04/disp.h
@@ -6,6 +6,8 @@
#include "nouveau_display.h"
+#include <nvif/event.h>
+
struct nouveau_encoder;
enum nv04_fp_display_regs {
@@ -84,7 +86,8 @@ struct nv04_display {
uint32_t saved_vga_font[4][16384];
uint32_t dac_users[4];
struct nouveau_bo *image[2];
- struct nvif_notify flip;
+ struct nvif_event flip;
+ struct nouveau_drm *drm;
};
static inline struct nv04_display *
@@ -179,5 +182,5 @@ nouveau_bios_run_init_table(struct drm_device *dev, u16 table,
);
}
-int nv04_flip_complete(struct nvif_notify *);
+int nv04_flip_complete(struct nvif_event *, void *, u32);
#endif
diff --git a/drivers/gpu/drm/nouveau/dispnv50/crc.c b/drivers/gpu/drm/nouveau/dispnv50/crc.c
index b834e8a9ae77..9c942fbd836d 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/crc.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/crc.c
@@ -463,7 +463,7 @@ void nv50_crc_atomic_set(struct nv50_head *head,
if (!outp)
return;
- func->set_src(head, outp->or, nv50_crc_source_type(outp, asyh->crc.src),
+ func->set_src(head, outp->outp.or.id, nv50_crc_source_type(outp, asyh->crc.src),
&crc->ctx[crc->ctx_idx]);
}
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c
index 33c97d510999..edcb2529b402 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/disp.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c
@@ -46,8 +46,8 @@
#include <nvif/class.h>
#include <nvif/cl0002.h>
-#include <nvif/cl5070.h>
#include <nvif/event.h>
+#include <nvif/if0012.h>
#include <nvif/if0014.h>
#include <nvif/timer.h>
@@ -64,7 +64,6 @@
#include "nouveau_connector.h"
#include "nouveau_encoder.h"
#include "nouveau_fence.h"
-#include "nouveau_fbcon.h"
#include <subdev/bios/dp.h>
@@ -131,7 +130,7 @@ nv50_dmac_kick(struct nvif_push *push)
{
struct nv50_dmac *dmac = container_of(push, typeof(*dmac), _push);
- dmac->cur = push->cur - (u32 *)dmac->_push.mem.object.map.ptr;
+ dmac->cur = push->cur - (u32 __iomem *)dmac->_push.mem.object.map.ptr;
if (dmac->put != dmac->cur) {
/* Push buffer fetches are not coherent with BAR1, we need to ensure
* writes have been flushed right through to VRAM before writing PUT.
@@ -194,7 +193,7 @@ nv50_dmac_wait(struct nvif_push *push, u32 size)
if (WARN_ON(size > dmac->max))
return -EINVAL;
- dmac->cur = push->cur - (u32 *)dmac->_push.mem.object.map.ptr;
+ dmac->cur = push->cur - (u32 __iomem *)dmac->_push.mem.object.map.ptr;
if (dmac->cur + size >= dmac->max) {
int ret = nv50_dmac_wind(dmac);
if (ret)
@@ -317,52 +316,6 @@ nv50_outp_dump_caps(struct nouveau_drm *drm,
outp->base.base.name, outp->caps.dp_interlace);
}
-static void
-nv50_outp_release(struct nouveau_encoder *nv_encoder)
-{
- struct nv50_disp *disp = nv50_disp(nv_encoder->base.base.dev);
- struct {
- struct nv50_disp_mthd_v1 base;
- } args = {
- .base.version = 1,
- .base.method = NV50_DISP_MTHD_V1_RELEASE,
- .base.hasht = nv_encoder->dcb->hasht,
- .base.hashm = nv_encoder->dcb->hashm,
- };
-
- nvif_mthd(&disp->disp->object, 0, &args, sizeof(args));
- nv_encoder->or = -1;
- nv_encoder->link = 0;
-}
-
-static int
-nv50_outp_acquire(struct nouveau_encoder *nv_encoder, bool hda)
-{
- struct nouveau_drm *drm = nouveau_drm(nv_encoder->base.base.dev);
- struct nv50_disp *disp = nv50_disp(drm->dev);
- struct {
- struct nv50_disp_mthd_v1 base;
- struct nv50_disp_acquire_v0 info;
- } args = {
- .base.version = 1,
- .base.method = NV50_DISP_MTHD_V1_ACQUIRE,
- .base.hasht = nv_encoder->dcb->hasht,
- .base.hashm = nv_encoder->dcb->hashm,
- .info.hda = hda,
- };
- int ret;
-
- ret = nvif_mthd(&disp->disp->object, 0, &args, sizeof(args));
- if (ret) {
- NV_ERROR(drm, "error acquiring output path: %d\n", ret);
- return ret;
- }
-
- nv_encoder->or = args.info.or;
- nv_encoder->link = args.info.link;
- return 0;
-}
-
static int
nv50_outp_atomic_check_view(struct drm_encoder *encoder,
struct drm_crtc_state *crtc_state,
@@ -489,9 +442,9 @@ nv50_dac_atomic_disable(struct drm_encoder *encoder, struct drm_atomic_state *st
struct nv50_core *core = nv50_disp(encoder->dev)->core;
const u32 ctrl = NVDEF(NV507D, DAC_SET_CONTROL, OWNER, NONE);
- core->func->dac->ctrl(core, nv_encoder->or, ctrl, NULL);
+ core->func->dac->ctrl(core, nv_encoder->outp.or.id, ctrl, NULL);
nv_encoder->crtc = NULL;
- nv50_outp_release(nv_encoder);
+ nvif_outp_release(&nv_encoder->outp);
}
static void
@@ -516,9 +469,9 @@ nv50_dac_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta
ctrl |= NVDEF(NV507D, DAC_SET_CONTROL, PROTOCOL, RGB_CRT);
- nv50_outp_acquire(nv_encoder, false);
+ nvif_outp_acquire_rgb_crt(&nv_encoder->outp);
- core->func->dac->ctrl(core, nv_encoder->or, ctrl, asyh);
+ core->func->dac->ctrl(core, nv_encoder->outp.or.id, ctrl, asyh);
asyh->or.depth = 0;
nv_encoder->crtc = &nv_crtc->base;
@@ -634,7 +587,7 @@ nv50_audio_component_get_eld(struct device *kdev, int port, int dev_id,
nv_connector = nouveau_connector(nv_encoder->audio.connector);
nv_crtc = nouveau_crtc(nv_encoder->crtc);
- if (!nv_crtc || nv_encoder->or != port || nv_crtc->index != dev_id)
+ if (!nv_crtc || nv_encoder->outp.or.id != port || nv_crtc->index != dev_id)
continue;
*enabled = nv_encoder->audio.enabled;
@@ -718,33 +671,37 @@ nv50_audio_component_fini(struct nouveau_drm *drm)
/******************************************************************************
* Audio
*****************************************************************************/
+static bool
+nv50_audio_supported(struct drm_encoder *encoder)
+{
+ struct nv50_disp *disp = nv50_disp(encoder->dev);
+
+ if (disp->disp->object.oclass <= GT200_DISP ||
+ disp->disp->object.oclass == GT206_DISP)
+ return false;
+
+ return true;
+}
+
static void
nv50_audio_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
{
struct nouveau_drm *drm = nouveau_drm(encoder->dev);
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- struct nv50_disp *disp = nv50_disp(encoder->dev);
- struct {
- struct nv50_disp_mthd_v1 base;
- struct nv50_disp_sor_hda_eld_v0 eld;
- } args = {
- .base.version = 1,
- .base.method = NV50_DISP_MTHD_V1_SOR_HDA_ELD,
- .base.hasht = nv_encoder->dcb->hasht,
- .base.hashm = (0xf0ff & nv_encoder->dcb->hashm) |
- (0x0100 << nv_crtc->index),
- };
+ struct nvif_outp *outp = &nv_encoder->outp;
+
+ if (!nv50_audio_supported(encoder))
+ return;
mutex_lock(&drm->audio.lock);
if (nv_encoder->audio.enabled) {
nv_encoder->audio.enabled = false;
nv_encoder->audio.connector = NULL;
- nvif_mthd(&disp->disp->object, 0, &args, sizeof(args));
+ nvif_outp_hda_eld(&nv_encoder->outp, nv_crtc->index, NULL, 0);
}
mutex_unlock(&drm->audio.lock);
- nv50_audio_component_eld_notify(drm->audio.component, nv_encoder->or,
- nv_crtc->index);
+ nv50_audio_component_eld_notify(drm->audio.component, outp->or.id, nv_crtc->index);
}
static void
@@ -754,159 +711,101 @@ nv50_audio_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc,
{
struct nouveau_drm *drm = nouveau_drm(encoder->dev);
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- struct nv50_disp *disp = nv50_disp(encoder->dev);
- struct __packed {
- struct {
- struct nv50_disp_mthd_v1 mthd;
- struct nv50_disp_sor_hda_eld_v0 eld;
- } base;
- u8 data[sizeof(nv_connector->base.eld)];
- } args = {
- .base.mthd.version = 1,
- .base.mthd.method = NV50_DISP_MTHD_V1_SOR_HDA_ELD,
- .base.mthd.hasht = nv_encoder->dcb->hasht,
- .base.mthd.hashm = (0xf0ff & nv_encoder->dcb->hashm) |
- (0x0100 << nv_crtc->index),
- };
-
- if (!drm_detect_monitor_audio(nv_connector->edid))
+ struct nvif_outp *outp = &nv_encoder->outp;
+
+ if (!nv50_audio_supported(encoder) || !drm_detect_monitor_audio(nv_connector->edid))
return;
mutex_lock(&drm->audio.lock);
- memcpy(args.data, nv_connector->base.eld, sizeof(args.data));
-
- nvif_mthd(&disp->disp->object, 0, &args,
- sizeof(args.base) + drm_eld_size(args.data));
+ nvif_outp_hda_eld(&nv_encoder->outp, nv_crtc->index, nv_connector->base.eld,
+ drm_eld_size(nv_connector->base.eld));
nv_encoder->audio.enabled = true;
nv_encoder->audio.connector = &nv_connector->base;
mutex_unlock(&drm->audio.lock);
- nv50_audio_component_eld_notify(drm->audio.component, nv_encoder->or,
- nv_crtc->index);
+ nv50_audio_component_eld_notify(drm->audio.component, outp->or.id, nv_crtc->index);
}
/******************************************************************************
* HDMI
*****************************************************************************/
static void
-nv50_hdmi_disable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc)
-{
- struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- struct nv50_disp *disp = nv50_disp(encoder->dev);
- struct {
- struct nv50_disp_mthd_v1 base;
- struct nv50_disp_sor_hdmi_pwr_v0 pwr;
- } args = {
- .base.version = 1,
- .base.method = NV50_DISP_MTHD_V1_SOR_HDMI_PWR,
- .base.hasht = nv_encoder->dcb->hasht,
- .base.hashm = (0xf0ff & nv_encoder->dcb->hashm) |
- (0x0100 << nv_crtc->index),
- };
-
- nvif_mthd(&disp->disp->object, 0, &args, sizeof(args));
-}
-
-static void
nv50_hdmi_enable(struct drm_encoder *encoder, struct nouveau_crtc *nv_crtc,
struct nouveau_connector *nv_connector, struct drm_atomic_state *state,
- struct drm_display_mode *mode)
+ struct drm_display_mode *mode, bool hda)
{
struct nouveau_drm *drm = nouveau_drm(encoder->dev);
struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
- struct nv50_disp *disp = nv50_disp(encoder->dev);
- struct {
- struct nv50_disp_mthd_v1 base;
- struct nv50_disp_sor_hdmi_pwr_v0 pwr;
- u8 infoframes[2 * 17]; /* two frames, up to 17 bytes each */
- } args = {
- .base.version = 1,
- .base.method = NV50_DISP_MTHD_V1_SOR_HDMI_PWR,
- .base.hasht = nv_encoder->dcb->hasht,
- .base.hashm = (0xf0ff & nv_encoder->dcb->hashm) |
- (0x0100 << nv_crtc->index),
- .pwr.state = 1,
- .pwr.rekey = 56, /* binary driver, and tegra, constant */
- };
- struct drm_hdmi_info *hdmi;
+ struct drm_hdmi_info *hdmi = &nv_connector->base.display_info.hdmi;
+ union hdmi_infoframe infoframe = { 0 };
+ const u8 rekey = 56; /* binary driver, and tegra, constant */
+ u8 scdc = 0;
u32 max_ac_packet;
- union hdmi_infoframe avi_frame;
- union hdmi_infoframe vendor_frame;
- bool high_tmds_clock_ratio = false, scrambling = false;
- u8 config;
- int ret;
- int size;
-
- if (!drm_detect_hdmi_monitor(nv_connector->edid))
- return;
-
- hdmi = &nv_connector->base.display_info.hdmi;
-
- ret = drm_hdmi_avi_infoframe_from_display_mode(&avi_frame.avi,
- &nv_connector->base, mode);
- if (!ret) {
- drm_hdmi_avi_infoframe_quant_range(&avi_frame.avi,
- &nv_connector->base, mode,
- HDMI_QUANTIZATION_RANGE_FULL);
- /* We have an AVI InfoFrame, populate it to the display */
- args.pwr.avi_infoframe_length
- = hdmi_infoframe_pack(&avi_frame, args.infoframes, 17);
- }
-
- ret = drm_hdmi_vendor_infoframe_from_display_mode(&vendor_frame.vendor.hdmi,
- &nv_connector->base, mode);
- if (!ret) {
- /* We have a Vendor InfoFrame, populate it to the display */
- args.pwr.vendor_infoframe_length
- = hdmi_infoframe_pack(&vendor_frame,
- args.infoframes
- + args.pwr.avi_infoframe_length,
- 17);
- }
+ struct {
+ struct nvif_outp_infoframe_v0 infoframe;
+ u8 data[17];
+ } args = { 0 };
+ int ret, size;
max_ac_packet = mode->htotal - mode->hdisplay;
- max_ac_packet -= args.pwr.rekey;
+ max_ac_packet -= rekey;
max_ac_packet -= 18; /* constant from tegra */
- args.pwr.max_ac_packet = max_ac_packet / 32;
+ max_ac_packet /= 32;
if (hdmi->scdc.scrambling.supported) {
- high_tmds_clock_ratio = mode->clock > 340000;
- scrambling = high_tmds_clock_ratio ||
- hdmi->scdc.scrambling.low_rates;
- }
+ const bool high_tmds_clock_ratio = mode->clock > 340000;
- args.pwr.scdc =
- NV50_DISP_SOR_HDMI_PWR_V0_SCDC_SCRAMBLE * scrambling |
- NV50_DISP_SOR_HDMI_PWR_V0_SCDC_DIV_BY_4 * high_tmds_clock_ratio;
+ ret = drm_scdc_readb(nv_encoder->i2c, SCDC_TMDS_CONFIG, &scdc);
+ if (ret < 0) {
+ NV_ERROR(drm, "Failure to read SCDC_TMDS_CONFIG: %d\n", ret);
+ return;
+ }
- size = sizeof(args.base)
- + sizeof(args.pwr)
- + args.pwr.avi_infoframe_length
- + args.pwr.vendor_infoframe_length;
- nvif_mthd(&disp->disp->object, 0, &args, size);
+ scdc &= ~(SCDC_TMDS_BIT_CLOCK_RATIO_BY_40 | SCDC_SCRAMBLING_ENABLE);
+ if (high_tmds_clock_ratio || hdmi->scdc.scrambling.low_rates)
+ scdc |= SCDC_SCRAMBLING_ENABLE;
+ if (high_tmds_clock_ratio)
+ scdc |= SCDC_TMDS_BIT_CLOCK_RATIO_BY_40;
- nv50_audio_enable(encoder, nv_crtc, nv_connector, state, mode);
+ ret = drm_scdc_writeb(nv_encoder->i2c, SCDC_TMDS_CONFIG, scdc);
+ if (ret < 0)
+ NV_ERROR(drm, "Failure to write SCDC_TMDS_CONFIG = 0x%02x: %d\n",
+ scdc, ret);
+ }
- /* If SCDC is supported by the downstream monitor, update
- * divider / scrambling settings to what we programmed above.
- */
- if (!hdmi->scdc.scrambling.supported)
+ ret = nvif_outp_acquire_tmds(&nv_encoder->outp, nv_crtc->index, true,
+ max_ac_packet, rekey, scdc, hda);
+ if (ret)
return;
- ret = drm_scdc_readb(nv_encoder->i2c, SCDC_TMDS_CONFIG, &config);
- if (ret < 0) {
- NV_ERROR(drm, "Failure to read SCDC_TMDS_CONFIG: %d\n", ret);
- return;
+ /* AVI InfoFrame. */
+ args.infoframe.version = 0;
+ args.infoframe.head = nv_crtc->index;
+
+ if (!drm_hdmi_avi_infoframe_from_display_mode(&infoframe.avi, &nv_connector->base, mode)) {
+ drm_hdmi_avi_infoframe_quant_range(&infoframe.avi, &nv_connector->base, mode,
+ HDMI_QUANTIZATION_RANGE_FULL);
+
+ size = hdmi_infoframe_pack(&infoframe, args.data, ARRAY_SIZE(args.data));
+ } else {
+ size = 0;
}
- config &= ~(SCDC_TMDS_BIT_CLOCK_RATIO_BY_40 | SCDC_SCRAMBLING_ENABLE);
- config |= SCDC_TMDS_BIT_CLOCK_RATIO_BY_40 * high_tmds_clock_ratio;
- config |= SCDC_SCRAMBLING_ENABLE * scrambling;
- ret = drm_scdc_writeb(nv_encoder->i2c, SCDC_TMDS_CONFIG, config);
- if (ret < 0)
- NV_ERROR(drm, "Failure to write SCDC_TMDS_CONFIG = 0x%02x: %d\n",
- config, ret);
+
+ nvif_outp_infoframe(&nv_encoder->outp, NVIF_OUTP_INFOFRAME_V0_AVI, &args.infoframe, size);
+
+ /* Vendor InfoFrame. */
+ memset(&args.data, 0, sizeof(args.data));
+ if (!drm_hdmi_vendor_infoframe_from_display_mode(&infoframe.vendor.hdmi,
+ &nv_connector->base, mode))
+ size = hdmi_infoframe_pack(&infoframe, args.data, ARRAY_SIZE(args.data));
+ else
+ size = 0;
+
+ nvif_outp_infoframe(&nv_encoder->outp, NVIF_OUTP_INFOFRAME_V0_VSI, &args.infoframe, size);
+
+ nv50_audio_enable(encoder, nv_crtc, nv_connector, state, mode);
}
/******************************************************************************
@@ -979,16 +878,6 @@ nv50_msto_prepare(struct drm_atomic_state *state,
struct nv50_mstc *mstc = msto->mstc;
struct nv50_mstm *mstm = mstc->mstm;
struct drm_dp_mst_atomic_payload *payload;
- struct {
- struct nv50_disp_mthd_v1 base;
- struct nv50_disp_sor_dp_mst_vcpi_v0 vcpi;
- } args = {
- .base.version = 1,
- .base.method = NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI,
- .base.hasht = mstm->outp->dcb->hasht,
- .base.hashm = (0xf0ff & mstm->outp->dcb->hashm) |
- (0x0100 << msto->head->base.index),
- };
NV_ATOMIC(drm, "%s: msto prepare\n", msto->encoder.name);
@@ -997,22 +886,16 @@ nv50_msto_prepare(struct drm_atomic_state *state,
// 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);
+
+ nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
} else {
if (msto->enabled)
drm_dp_add_payload_part1(mgr, mst_state, payload);
- args.vcpi.start_slot = payload->vc_start_slot;
- args.vcpi.num_slots = payload->time_slots;
- args.vcpi.pbn = payload->pbn;
- args.vcpi.aligned_pbn = payload->time_slots * mst_state->pbn_div;
+ nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index,
+ payload->vc_start_slot, payload->time_slots,
+ payload->pbn, payload->time_slots * mst_state->pbn_div);
}
-
- NV_ATOMIC(drm, "%s: %s: %02x %02x %04x %04x\n",
- msto->encoder.name, msto->head->base.base.name,
- args.vcpi.start_slot, args.vcpi.num_slots,
- args.vcpi.pbn, args.vcpi.aligned_pbn);
-
- nvif_mthd(&drm->display->disp.object, 0, &args, sizeof(args));
}
static int
@@ -1107,10 +990,12 @@ nv50_msto_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *st
if (WARN_ON(!mstc))
return;
- if (!mstm->links++)
- nv50_outp_acquire(mstm->outp, false /*XXX: MST audio.*/);
+ if (!mstm->links++) {
+ /*XXX: MST audio. */
+ nvif_outp_acquire_dp(&mstm->outp->outp, mstm->outp->dp.dpcd, 0, 0, false, true);
+ }
- if (mstm->outp->link & 1)
+ if (mstm->outp->outp.or.link & 1)
proto = NV917D_SOR_SET_CONTROL_PROTOCOL_DP_A;
else
proto = NV917D_SOR_SET_CONTROL_PROTOCOL_DP_B;
@@ -1405,7 +1290,7 @@ nv50_mstm_prepare(struct drm_atomic_state *state,
if (mstm->disabled) {
if (!mstm->links)
- nv50_outp_release(mstm->outp);
+ nvif_outp_release(&mstm->outp->outp);
mstm->disabled = false;
}
}
@@ -1473,26 +1358,6 @@ nv50_mstm_remove(struct nv50_mstm *mstm)
drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, false);
}
-static int
-nv50_mstm_enable(struct nv50_mstm *mstm, int state)
-{
- struct nouveau_encoder *outp = mstm->outp;
- struct {
- struct nv50_disp_mthd_v1 base;
- struct nv50_disp_sor_dp_mst_link_v0 mst;
- } args = {
- .base.version = 1,
- .base.method = NV50_DISP_MTHD_V1_SOR_DP_MST_LINK,
- .base.hasht = outp->dcb->hasht,
- .base.hashm = outp->dcb->hashm,
- .mst.state = state,
- };
- struct nouveau_drm *drm = nouveau_drm(outp->base.base.dev);
- struct nvif_object *disp = &drm->display->disp.object;
-
- return nvif_mthd(disp, 0, &args, sizeof(args));
-}
-
int
nv50_mstm_detect(struct nouveau_encoder *outp)
{
@@ -1513,15 +1378,9 @@ nv50_mstm_detect(struct nouveau_encoder *outp)
return ret;
/* And start enabling */
- ret = nv50_mstm_enable(mstm, true);
- if (ret)
- return ret;
-
ret = drm_dp_mst_topology_mgr_set_mst(&mstm->mgr, true);
- if (ret) {
- nv50_mstm_enable(mstm, false);
+ if (ret)
return ret;
- }
mstm->is_mst = true;
return 1;
@@ -1623,7 +1482,7 @@ nv50_sor_update(struct nouveau_encoder *nv_encoder, u8 head,
asyh->or.depth = depth;
}
- core->func->sor->ctrl(core, nv_encoder->or, nv_encoder->ctrl, asyh);
+ core->func->sor->ctrl(core, nv_encoder->outp.or.id, nv_encoder->ctrl, asyh);
}
/* TODO: Should we extend this to PWM-only backlights?
@@ -1666,8 +1525,7 @@ nv50_sor_atomic_disable(struct drm_encoder *encoder, struct drm_atomic_state *st
nv_encoder->update(nv_encoder, nv_crtc->index, NULL, 0, 0);
nv50_audio_disable(encoder, nv_crtc);
- nv50_hdmi_disable(&nv_encoder->base.base, nv_crtc);
- nv50_outp_release(nv_encoder);
+ nvif_outp_release(&nv_encoder->outp);
nv_encoder->crtc = NULL;
}
@@ -1679,16 +1537,8 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta
struct nv50_head_atom *asyh =
nv50_head_atom(drm_atomic_get_new_crtc_state(state, &nv_crtc->base));
struct drm_display_mode *mode = &asyh->state.adjusted_mode;
- struct {
- struct nv50_disp_mthd_v1 base;
- struct nv50_disp_sor_lvds_script_v0 lvds;
- } lvds = {
- .base.version = 1,
- .base.method = NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT,
- .base.hasht = nv_encoder->dcb->hasht,
- .base.hashm = nv_encoder->dcb->hashm,
- };
struct nv50_disp *disp = nv50_disp(encoder->dev);
+ struct nvif_outp *outp = &nv_encoder->outp;
struct drm_device *dev = encoder->dev;
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_connector *nv_connector;
@@ -1696,7 +1546,7 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta
struct nouveau_backlight *backlight;
#endif
struct nvbios *bios = &drm->vbios;
- bool hda = false;
+ bool lvds_dual = false, lvds_8bpc = false, hda = false;
u8 proto = NV507D_SOR_SET_CONTROL_PROTOCOL_CUSTOM;
u8 depth = NV837D_SOR_SET_CONTROL_PIXEL_DEPTH_DEFAULT;
@@ -1707,11 +1557,16 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta
disp->disp->object.oclass >= GF110_DISP) &&
drm_detect_monitor_audio(nv_connector->edid))
hda = true;
- nv50_outp_acquire(nv_encoder, hda);
switch (nv_encoder->dcb->type) {
case DCB_OUTPUT_TMDS:
- if (nv_encoder->link & 1) {
+ if (disp->disp->object.oclass == NV50_DISP ||
+ !drm_detect_hdmi_monitor(nv_connector->edid))
+ nvif_outp_acquire_tmds(outp, nv_crtc->index, false, 0, 0, 0, false);
+ else
+ nv50_hdmi_enable(encoder, nv_crtc, nv_connector, state, mode, hda);
+
+ if (nv_encoder->outp.or.link & 1) {
proto = NV507D_SOR_SET_CONTROL_PROTOCOL_SINGLE_TMDS_A;
/* Only enable dual-link if:
* - Need to (i.e. rate > 165MHz)
@@ -1726,44 +1581,41 @@ nv50_sor_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *sta
} else {
proto = NV507D_SOR_SET_CONTROL_PROTOCOL_SINGLE_TMDS_B;
}
-
- nv50_hdmi_enable(&nv_encoder->base.base, nv_crtc, nv_connector, state, mode);
break;
case DCB_OUTPUT_LVDS:
proto = NV507D_SOR_SET_CONTROL_PROTOCOL_LVDS_CUSTOM;
if (bios->fp_no_ddc) {
- if (bios->fp.dual_link)
- lvds.lvds.script |= 0x0100;
- if (bios->fp.if_is_24bit)
- lvds.lvds.script |= 0x0200;
+ lvds_dual = bios->fp.dual_link;
+ lvds_8bpc = bios->fp.if_is_24bit;
} else {
if (nv_connector->type == DCB_CONNECTOR_LVDS_SPWG) {
if (((u8 *)nv_connector->edid)[121] == 2)
- lvds.lvds.script |= 0x0100;
+ lvds_dual = true;
} else
if (mode->clock >= bios->fp.duallink_transition_clk) {
- lvds.lvds.script |= 0x0100;
+ lvds_dual = true;
}
- if (lvds.lvds.script & 0x0100) {
+ if (lvds_dual) {
if (bios->fp.strapless_is_24bit & 2)
- lvds.lvds.script |= 0x0200;
+ lvds_8bpc = true;
} else {
if (bios->fp.strapless_is_24bit & 1)
- lvds.lvds.script |= 0x0200;
+ lvds_8bpc = true;
}
if (asyh->or.bpc == 8)
- lvds.lvds.script |= 0x0200;
+ lvds_8bpc = true;
}
- nvif_mthd(&disp->disp->object, 0, &lvds, sizeof(lvds));
+ nvif_outp_acquire_lvds(&nv_encoder->outp, lvds_dual, lvds_8bpc);
break;
case DCB_OUTPUT_DP:
+ nvif_outp_acquire_dp(&nv_encoder->outp, nv_encoder->dp.dpcd, 0, 0, hda, false);
depth = nv50_dp_bpc_to_depth(asyh->or.bpc);
- if (nv_encoder->link & 1)
+ if (nv_encoder->outp.or.link & 1)
proto = NV887D_SOR_SET_CONTROL_PROTOCOL_DP_A;
else
proto = NV887D_SOR_SET_CONTROL_PROTOCOL_DP_B;
@@ -1921,9 +1773,9 @@ nv50_pior_atomic_disable(struct drm_encoder *encoder, struct drm_atomic_state *s
struct nv50_core *core = nv50_disp(encoder->dev)->core;
const u32 ctrl = NVDEF(NV507D, PIOR_SET_CONTROL, OWNER, NONE);
- core->func->pior->ctrl(core, nv_encoder->or, ctrl, NULL);
+ core->func->pior->ctrl(core, nv_encoder->outp.or.id, ctrl, NULL);
nv_encoder->crtc = NULL;
- nv50_outp_release(nv_encoder);
+ nvif_outp_release(&nv_encoder->outp);
}
static void
@@ -1944,8 +1796,6 @@ nv50_pior_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *st
break;
}
- nv50_outp_acquire(nv_encoder, false);
-
switch (asyh->or.bpc) {
case 10: asyh->or.depth = NV837D_PIOR_SET_CONTROL_PIXEL_DEPTH_BPP_30_444; break;
case 8: asyh->or.depth = NV837D_PIOR_SET_CONTROL_PIXEL_DEPTH_BPP_24_444; break;
@@ -1955,15 +1805,19 @@ nv50_pior_atomic_enable(struct drm_encoder *encoder, struct drm_atomic_state *st
switch (nv_encoder->dcb->type) {
case DCB_OUTPUT_TMDS:
+ ctrl |= NVDEF(NV507D, PIOR_SET_CONTROL, PROTOCOL, EXT_TMDS_ENC);
+ nvif_outp_acquire_tmds(&nv_encoder->outp, false, false, 0, 0, 0, false);
+ break;
case DCB_OUTPUT_DP:
ctrl |= NVDEF(NV507D, PIOR_SET_CONTROL, PROTOCOL, EXT_TMDS_ENC);
+ nvif_outp_acquire_dp(&nv_encoder->outp, nv_encoder->dp.dpcd, 0, 0, false, false);
break;
default:
BUG();
break;
}
- core->func->pior->ctrl(core, nv_encoder->or, ctrl, asyh);
+ core->func->pior->ctrl(core, nv_encoder->outp.or.id, ctrl, asyh);
nv_encoder->crtc = &nv_crtc->base;
}
@@ -2587,7 +2441,7 @@ nv50_disp_atomic_state_alloc(struct drm_device *dev)
static const struct drm_mode_config_funcs
nv50_disp_func = {
.fb_create = nouveau_user_framebuffer_create,
- .output_poll_changed = nouveau_fbcon_output_poll_changed,
+ .output_poll_changed = drm_fb_helper_output_poll_changed,
.atomic_check = nv50_disp_atomic_check,
.atomic_commit = nv50_disp_atomic_commit,
.atomic_state_alloc = nv50_disp_atomic_state_alloc,
diff --git a/drivers/gpu/drm/nouveau/dispnv50/head.c b/drivers/gpu/drm/nouveau/dispnv50/head.c
index c3c57be54e1c..f006e56e1e08 100644
--- a/drivers/gpu/drm/nouveau/dispnv50/head.c
+++ b/drivers/gpu/drm/nouveau/dispnv50/head.c
@@ -517,7 +517,8 @@ nv50_head_destroy(struct drm_crtc *crtc)
{
struct nv50_head *head = nv50_head(crtc);
- nvif_notify_dtor(&head->base.vblank);
+ nvif_event_dtor(&head->base.vblank);
+ nvif_head_dtor(&head->base.head);
nv50_lut_fini(&head->olut);
drm_crtc_cleanup(crtc);
kfree(head);
@@ -554,15 +555,15 @@ nvd9_head_func = {
.late_register = nv50_head_late_register,
};
-static int nv50_head_vblank_handler(struct nvif_notify *notify)
+static int
+nv50_head_vblank_handler(struct nvif_event *event, void *repv, u32 repc)
{
- struct nouveau_crtc *nv_crtc =
- container_of(notify, struct nouveau_crtc, vblank);
+ struct nouveau_crtc *nv_crtc = container_of(event, struct nouveau_crtc, vblank);
if (drm_crtc_handle_vblank(&nv_crtc->base))
nv50_crc_handle_vblank(nv50_head(&nv_crtc->base));
- return NVIF_NOTIFY_KEEP;
+ return NVIF_EVENT_KEEP;
}
struct nv50_head *
@@ -624,14 +625,12 @@ nv50_head_create(struct drm_device *dev, int index)
}
}
- ret = nvif_notify_ctor(&disp->disp->object, "kmsVbl", nv50_head_vblank_handler,
- false, NV04_DISP_NTFY_VBLANK,
- &(struct nvif_notify_head_req_v0) {
- .head = nv_crtc->index,
- },
- sizeof(struct nvif_notify_head_req_v0),
- sizeof(struct nvif_notify_head_rep_v0),
- &nv_crtc->vblank);
+ ret = nvif_head_ctor(disp->disp, head->base.base.name, head->base.index, &head->base.head);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ret = nvif_head_vblank_event_ctor(&head->base.head, "kmsVbl", nv50_head_vblank_handler,
+ false, &nv_crtc->vblank);
if (ret)
return ERR_PTR(ret);
diff --git a/drivers/gpu/drm/nouveau/include/nvfw/acr.h b/drivers/gpu/drm/nouveau/include/nvfw/acr.h
index e65d6a8db104..6f19560bc54b 100644
--- a/drivers/gpu/drm/nouveau/include/nvfw/acr.h
+++ b/drivers/gpu/drm/nouveau/include/nvfw/acr.h
@@ -39,6 +39,23 @@ struct wpr_header_v1 {
void wpr_header_v1_dump(struct nvkm_subdev *, const struct wpr_header_v1 *);
+struct wpr_generic_header {
+#define WPR_GENERIC_HEADER_ID_LSF_UCODE_DESC 1
+#define WPR_GENERIC_HEADER_ID_LSF_WPR_HEADER 2
+#define WPR_GENERIC_HEADER_ID_LSF_SHARED_SUB_WPR 3
+#define WPR_GENERIC_HEADER_ID_LSF_LSB_HEADER 4
+ u16 identifier;
+ u16 version;
+ u32 size;
+};
+
+struct wpr_header_v2 {
+ struct wpr_generic_header hdr;
+ struct wpr_header_v1 wpr;
+};
+
+void wpr_header_v2_dump(struct nvkm_subdev *, const struct wpr_header_v2 *);
+
struct lsf_signature {
u8 prd_keys[2][16];
u8 dbg_keys[2][16];
@@ -89,6 +106,74 @@ struct lsb_header_v1 {
void lsb_header_v1_dump(struct nvkm_subdev *, struct lsb_header_v1 *);
+struct lsb_header_v2 {
+ struct wpr_generic_header hdr;
+ struct lsf_signature_v2 {
+ struct wpr_generic_header hdr;
+ u32 falcon_id;
+ u8 prd_present;
+ u8 dbg_present;
+ u16 reserved;
+ u32 sig_size;
+ u8 prod_sig[2][384 + 128];
+ u8 debug_sig[2][384 + 128];
+ u16 sig_algo_ver;
+ u16 sig_algo;
+ u16 hash_algo_ver;
+ u16 hash_algo;
+ u32 sig_algo_padding_type;
+ u8 depmap[11 * 2 * 4];
+ u32 depmap_count;
+ u8 supports_versioning;
+ u8 pad[3];
+ u32 ls_ucode_version;
+ u32 ls_ucode_id;
+ u32 ucode_ls_encrypted;
+ u32 ls_eng_algo_type;
+ u32 ls_eng_algo_ver;
+ u8 ls_enc_iv[16];
+ u8 rsvd[36];
+ } signature;
+ u32 ucode_off;
+ u32 ucode_size;
+ u32 data_size;
+ u32 bl_code_size;
+ u32 bl_imem_off;
+ u32 bl_data_off;
+ u32 bl_data_size;
+ u32 rsvd0;
+ u32 app_code_off;
+ u32 app_code_size;
+ u32 app_data_off;
+ u32 app_data_size;
+ u32 app_imem_offset;
+ u32 app_dmem_offset;
+ u32 flags;
+ u32 monitor_code_offset;
+ u32 monitor_data_offset;
+ u32 manifest_offset;
+ struct hs_fmc_params {
+ u8 hs_fmc;
+ u8 padding[3];
+ u16 pkc_algo;
+ u16 pkc_algo_version;
+ u32 engid_mask;
+ u32 ucode_id;
+ u32 fuse_ver;
+ u8 pkc_signature[384 + 128];
+ u8 pkc_key[2048];
+ u8 rsvd[4];
+ } hs_fmc_params;
+ struct hs_ovl_sig_blob_params {
+ u8 hs_ovl_sig_blob_present;
+ u32 hs_ovl_sig_blob_offset;
+ u32 hs_ovl_sig_blob_size;
+ } hs_ovl_sig_blob_params;
+ u8 rsvd[20];
+};
+
+void lsb_header_v2_dump(struct nvkm_subdev *, struct lsb_header_v2 *);
+
struct flcn_acr_desc {
union {
u8 reserved_dmem[0x200];
diff --git a/drivers/gpu/drm/nouveau/include/nvfw/hs.h b/drivers/gpu/drm/nouveau/include/nvfw/hs.h
index b53bbc4cd130..8c4cd08a7b5f 100644
--- a/drivers/gpu/drm/nouveau/include/nvfw/hs.h
+++ b/drivers/gpu/drm/nouveau/include/nvfw/hs.h
@@ -17,6 +17,20 @@ struct nvfw_hs_header {
const struct nvfw_hs_header *nvfw_hs_header(struct nvkm_subdev *, const void *);
+struct nvfw_hs_header_v2 {
+ u32 sig_prod_offset;
+ u32 sig_prod_size;
+ u32 patch_loc;
+ u32 patch_sig;
+ u32 meta_data_offset;
+ u32 meta_data_size;
+ u32 num_sig;
+ u32 header_offset;
+ u32 header_size;
+};
+
+const struct nvfw_hs_header_v2 *nvfw_hs_header_v2(struct nvkm_subdev *, const void *);
+
struct nvfw_hs_load_header {
u32 non_sec_code_off;
u32 non_sec_code_size;
@@ -28,4 +42,18 @@ struct nvfw_hs_load_header {
const struct nvfw_hs_load_header *
nvfw_hs_load_header(struct nvkm_subdev *, const void *);
+
+struct nvfw_hs_load_header_v2 {
+ u32 os_code_offset;
+ u32 os_code_size;
+ u32 os_data_offset;
+ u32 os_data_size;
+ u32 num_apps;
+ struct {
+ u32 offset;
+ u32 size;
+ } app[0];
+};
+
+const struct nvfw_hs_load_header_v2 *nvfw_hs_load_header_v2(struct nvkm_subdev *, const void *);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvfw/ls.h b/drivers/gpu/drm/nouveau/include/nvfw/ls.h
index f63692a2a16c..d531121bfa35 100644
--- a/drivers/gpu/drm/nouveau/include/nvfw/ls.h
+++ b/drivers/gpu/drm/nouveau/include/nvfw/ls.h
@@ -50,4 +50,55 @@ struct nvfw_ls_desc_v1 {
const struct nvfw_ls_desc_v1 *
nvfw_ls_desc_v1(struct nvkm_subdev *, const void *);
+
+struct nvfw_ls_desc_v2 {
+ u32 descriptor_size;
+ u32 image_size;
+ u32 tools_version;
+ u32 app_version;
+ char date[64];
+ u32 secure_bootloader;
+ u32 bootloader_start_offset;
+ u32 bootloader_size;
+ u32 bootloader_imem_offset;
+ u32 bootloader_entry_point;
+ u32 app_start_offset;
+ u32 app_size;
+ u32 app_imem_offset;
+ u32 app_imem_entry;
+ u32 app_dmem_offset;
+ u32 app_resident_code_offset;
+ u32 app_resident_code_size;
+ u32 app_resident_data_offset;
+ u32 app_resident_data_size;
+ u32 nb_imem_overlays;
+ u32 nb_dmem_overlays;
+ struct {
+ u32 start;
+ u32 size;
+ } load_ovl[64];
+};
+
+const struct nvfw_ls_desc_v2 *nvfw_ls_desc_v2(struct nvkm_subdev *, const void *);
+
+struct nvfw_ls_hsbl_bin_hdr {
+ u32 bin_magic;
+ u32 bin_ver;
+ u32 bin_size;
+ u32 header_offset;
+};
+
+const struct nvfw_ls_hsbl_bin_hdr *nvfw_ls_hsbl_bin_hdr(struct nvkm_subdev *, const void *);
+
+struct nvfw_ls_hsbl_hdr {
+ u32 sig_prod_offset;
+ u32 sig_prod_size;
+ u32 patch_loc;
+ u32 patch_sig;
+ u32 meta_data_offset;
+ u32 meta_data_size;
+ u32 num_sig;
+};
+
+const struct nvfw_ls_hsbl_hdr *nvfw_ls_hsbl_hdr(struct nvkm_subdev *, const void *);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvfw/sec2.h b/drivers/gpu/drm/nouveau/include/nvfw/sec2.h
index 9a37ad4179cb..b3331d679c4e 100644
--- a/drivers/gpu/drm/nouveau/include/nvfw/sec2.h
+++ b/drivers/gpu/drm/nouveau/include/nvfw/sec2.h
@@ -10,6 +10,7 @@ struct nv_sec2_args {
};
#define NV_SEC2_UNIT_INIT 0x01
+#define NV_SEC2_UNIT_UNLOAD 0x06
#define NV_SEC2_UNIT_ACR 0x08
struct nv_sec2_init_msg {
@@ -33,6 +34,29 @@ struct nv_sec2_init_msg {
u16 sw_managed_area_size;
};
+struct nv_sec2_init_msg_v1 {
+ struct nvfw_falcon_msg hdr;
+#define NV_SEC2_INIT_MSG_INIT 0x00
+ u8 msg_type;
+
+ u8 num_queues;
+ u16 os_debug_entry_point;
+
+ struct {
+ u32 offset;
+ u16 size;
+ u8 index;
+#define NV_SEC2_INIT_MSG_QUEUE_ID_CMDQ 0x00
+#define NV_SEC2_INIT_MSG_QUEUE_ID_MSGQ 0x01
+ u8 id;
+ } queue_info[2];
+
+ u32 sw_managed_area_offset;
+ u16 sw_managed_area_size;
+
+ u32 unkn[8];
+};
+
struct nv_sec2_acr_cmd {
struct nvfw_falcon_cmd hdr;
#define NV_SEC2_ACR_CMD_BOOTSTRAP_FALCON 0x00
@@ -57,4 +81,25 @@ struct nv_sec2_acr_bootstrap_falcon_msg {
u32 error_code;
u32 falcon_id;
};
+
+#define NV_SEC2_UNIT_V2_INIT 0x01
+#define NV_SEC2_UNIT_V2_UNLOAD 0x05
+#define NV_SEC2_UNIT_V2_ACR 0x07
+
+struct nv_sec2_acr_bootstrap_falcon_cmd_v1 {
+ struct nv_sec2_acr_cmd cmd;
+#define NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES 0x00000000
+#define NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_NO 0x00000001
+ u32 flags;
+ u32 falcon_id;
+ u32 unkn08;
+ u32 unkn0c;
+};
+
+struct nv_sec2_acr_bootstrap_falcon_msg_v1 {
+ struct nv_sec2_acr_msg msg;
+ u32 error_code;
+ u32 falcon_id;
+ u32 unkn08;
+};
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl0046.h b/drivers/gpu/drm/nouveau/include/nvif/cl0046.h
index d490d401870a..eca7c3950654 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/cl0046.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl0046.h
@@ -2,28 +2,5 @@
#ifndef __NVIF_CL0046_H__
#define __NVIF_CL0046_H__
-#define NV04_DISP_NTFY_VBLANK 0x00
#define NV04_DISP_NTFY_CONN 0x01
-
-struct nv04_disp_mthd_v0 {
- __u8 version;
-#define NV04_DISP_SCANOUTPOS 0x00
- __u8 method;
- __u8 head;
- __u8 pad03[5];
-};
-
-struct nv04_disp_scanoutpos_v0 {
- __u8 version;
- __u8 pad01[7];
- __s64 time[2];
- __u16 vblanks;
- __u16 vblanke;
- __u16 vtotal;
- __u16 vline;
- __u16 hblanks;
- __u16 hblanke;
- __u16 htotal;
- __u16 hline;
-};
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl006b.h b/drivers/gpu/drm/nouveau/include/nvif/cl006b.h
deleted file mode 100644
index c960c449e430..000000000000
--- a/drivers/gpu/drm/nouveau/include/nvif/cl006b.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-#ifndef __NVIF_CL006B_H__
-#define __NVIF_CL006B_H__
-
-struct nv03_channel_dma_v0 {
- __u8 version;
- __u8 chid;
- __u8 pad02[2];
- __u32 offset;
- __u64 pushbuf;
-};
-#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl0080.h b/drivers/gpu/drm/nouveau/include/nvif/cl0080.h
index 59759c4fb62e..8b5a240d57e4 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/cl0080.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/cl0080.h
@@ -68,7 +68,7 @@ struct nv_device_time_v0 {
/* Returns the number of available runlists. */
#define NV_DEVICE_HOST_RUNLISTS NV_DEVICE_HOST(0x00000000)
-/* Returns the number of available channels. */
+/* Returns the number of available channels (0 if per-runlist). */
#define NV_DEVICE_HOST_CHANNELS NV_DEVICE_HOST(0x00000001)
/* Returns a mask of available engine types on runlist(data). */
@@ -90,4 +90,6 @@ struct nv_device_time_v0 {
#define NV_DEVICE_HOST_RUNLIST_ENGINES_SEC2 0x00004000
#define NV_DEVICE_HOST_RUNLIST_ENGINES_NVDEC 0x00008000
#define NV_DEVICE_HOST_RUNLIST_ENGINES_NVENC 0x00010000
+/* Returns the number of available channels on runlist(data). */
+#define NV_DEVICE_HOST_RUNLIST_CHANNELS NV_DEVICE_HOST(0x00000101)
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl506e.h b/drivers/gpu/drm/nouveau/include/nvif/cl506e.h
deleted file mode 100644
index 9df289c7a84f..000000000000
--- a/drivers/gpu/drm/nouveau/include/nvif/cl506e.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-#ifndef __NVIF_CL506E_H__
-#define __NVIF_CL506E_H__
-
-struct nv50_channel_dma_v0 {
- __u8 version;
- __u8 chid;
- __u8 pad02[6];
- __u64 vmm;
- __u64 pushbuf;
- __u64 offset;
-};
-#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl506f.h b/drivers/gpu/drm/nouveau/include/nvif/cl506f.h
deleted file mode 100644
index 327c96a994bb..000000000000
--- a/drivers/gpu/drm/nouveau/include/nvif/cl506f.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-#ifndef __NVIF_CL506F_H__
-#define __NVIF_CL506F_H__
-
-struct nv50_channel_gpfifo_v0 {
- __u8 version;
- __u8 chid;
- __u8 pad02[2];
- __u32 ilength;
- __u64 ioffset;
- __u64 pushbuf;
- __u64 vmm;
-};
-#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
deleted file mode 100644
index 56affb606adf..000000000000
--- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-#ifndef __NVIF_CL5070_H__
-#define __NVIF_CL5070_H__
-
-#define NV50_DISP_MTHD 0x00
-
-struct nv50_disp_mthd_v0 {
- __u8 version;
-#define NV50_DISP_SCANOUTPOS 0x00
- __u8 method;
- __u8 head;
- __u8 pad03[5];
-};
-
-struct nv50_disp_scanoutpos_v0 {
- __u8 version;
- __u8 pad01[7];
- __s64 time[2];
- __u16 vblanks;
- __u16 vblanke;
- __u16 vtotal;
- __u16 vline;
- __u16 hblanks;
- __u16 hblanke;
- __u16 htotal;
- __u16 hline;
-};
-
-struct nv50_disp_mthd_v1 {
- __u8 version;
-#define NV50_DISP_MTHD_V1_ACQUIRE 0x01
-#define NV50_DISP_MTHD_V1_RELEASE 0x02
-#define NV50_DISP_MTHD_V1_SOR_HDA_ELD 0x21
-#define NV50_DISP_MTHD_V1_SOR_HDMI_PWR 0x22
-#define NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT 0x23
-#define NV50_DISP_MTHD_V1_SOR_DP_MST_LINK 0x25
-#define NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI 0x26
- __u8 method;
- __u16 hasht;
- __u16 hashm;
- __u8 pad06[2];
-};
-
-struct nv50_disp_acquire_v0 {
- __u8 version;
- __u8 or;
- __u8 link;
- __u8 hda;
- __u8 pad04[4];
-};
-
-struct nv50_disp_sor_hda_eld_v0 {
- __u8 version;
- __u8 pad01[7];
- __u8 data[];
-};
-
-struct nv50_disp_sor_hdmi_pwr_v0 {
- __u8 version;
- __u8 state;
- __u8 max_ac_packet;
- __u8 rekey;
- __u8 avi_infoframe_length;
- __u8 vendor_infoframe_length;
-#define NV50_DISP_SOR_HDMI_PWR_V0_SCDC_SCRAMBLE (1 << 0)
-#define NV50_DISP_SOR_HDMI_PWR_V0_SCDC_DIV_BY_4 (1 << 1)
- __u8 scdc;
- __u8 pad07[1];
-};
-
-struct nv50_disp_sor_lvds_script_v0 {
- __u8 version;
- __u8 pad01[1];
- __u16 script;
- __u8 pad04[4];
-};
-
-struct nv50_disp_sor_dp_mst_link_v0 {
- __u8 version;
- __u8 state;
- __u8 pad02[6];
-};
-
-struct nv50_disp_sor_dp_mst_vcpi_v0 {
- __u8 version;
- __u8 pad01[1];
- __u8 start_slot;
- __u8 num_slots;
- __u16 pbn;
- __u16 aligned_pbn;
-};
-#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl826e.h b/drivers/gpu/drm/nouveau/include/nvif/cl826e.h
deleted file mode 100644
index 1b6496d31580..000000000000
--- a/drivers/gpu/drm/nouveau/include/nvif/cl826e.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-#ifndef __NVIF_CL826E_H__
-#define __NVIF_CL826E_H__
-
-struct g82_channel_dma_v0 {
- __u8 version;
- __u8 chid;
- __u8 pad02[6];
- __u64 vmm;
- __u64 pushbuf;
- __u64 offset;
-};
-
-#define NV826E_V0_NTFY_NON_STALL_INTERRUPT 0x00
-#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl826f.h b/drivers/gpu/drm/nouveau/include/nvif/cl826f.h
deleted file mode 100644
index 148602264a76..000000000000
--- a/drivers/gpu/drm/nouveau/include/nvif/cl826f.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-#ifndef __NVIF_CL826F_H__
-#define __NVIF_CL826F_H__
-
-struct g82_channel_gpfifo_v0 {
- __u8 version;
- __u8 chid;
- __u8 pad02[2];
- __u32 ilength;
- __u64 ioffset;
- __u64 pushbuf;
- __u64 vmm;
-};
-
-#define NV826F_V0_NTFY_NON_STALL_INTERRUPT 0x00
-#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl906f.h b/drivers/gpu/drm/nouveau/include/nvif/cl906f.h
deleted file mode 100644
index 3823d6891b55..000000000000
--- a/drivers/gpu/drm/nouveau/include/nvif/cl906f.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-#ifndef __NVIF_CL906F_H__
-#define __NVIF_CL906F_H__
-
-struct fermi_channel_gpfifo_v0 {
- __u8 version;
- __u8 chid;
- __u8 pad02[2];
- __u32 ilength;
- __u64 ioffset;
- __u64 vmm;
-};
-
-#define NV906F_V0_NTFY_NON_STALL_INTERRUPT 0x00
-#define NV906F_V0_NTFY_KILLED 0x01
-#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/cla06f.h b/drivers/gpu/drm/nouveau/include/nvif/cla06f.h
deleted file mode 100644
index cfa18f1fbf83..000000000000
--- a/drivers/gpu/drm/nouveau/include/nvif/cla06f.h
+++ /dev/null
@@ -1,18 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-#ifndef __NVIF_CLA06F_H__
-#define __NVIF_CLA06F_H__
-
-struct kepler_channel_gpfifo_a_v0 {
- __u8 version;
- __u8 priv;
- __u16 chid;
- __u32 ilength;
- __u64 ioffset;
- __u64 runlist;
- __u64 vmm;
- __u64 inst;
-};
-
-#define NVA06F_V0_NTFY_NON_STALL_INTERRUPT 0x00
-#define NVA06F_V0_NTFY_KILLED 0x01
-#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h
index 8641db649f48..ad1e5de84e80 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/class.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/class.h
@@ -32,11 +32,17 @@
#define NVIF_CLASS_VMM_GM200 /* ifb00d.h */ 0x8000b00d
#define NVIF_CLASS_VMM_GP100 /* ifc00d.h */ 0x8000c00d
+#define NVIF_CLASS_EVENT /* if000e.h */ 0x8000000e
+
#define NVIF_CLASS_DISP /* if0010.h */ 0x80000010
#define NVIF_CLASS_CONN /* if0011.h */ 0x80000011
#define NVIF_CLASS_OUTP /* if0012.h */ 0x80000012
+#define NVIF_CLASS_HEAD /* if0013.h */ 0x80000013
#define NVIF_CLASS_DISP_CHAN /* if0014.h */ 0x80000014
+#define NVIF_CLASS_CHAN /* if0020.h */ 0x80000020
+#define NVIF_CLASS_CGRP /* if0021.h */ 0x80000021
+
/* the below match nvidia-assigned (either in hw, or sw) class numbers */
#define NV_NULL_CLASS 0x00000030
@@ -58,25 +64,30 @@
#define NV04_DISP /* cl0046.h */ 0x00000046
#define VOLTA_USERMODE_A 0x0000c361
+#define TURING_USERMODE_A 0x0000c461
+#define AMPERE_USERMODE_A 0x0000c561
#define MAXWELL_FAULT_BUFFER_A /* clb069.h */ 0x0000b069
#define VOLTA_FAULT_BUFFER_A /* clb069.h */ 0x0000c369
-#define NV03_CHANNEL_DMA /* cl506b.h */ 0x0000006b
-#define NV10_CHANNEL_DMA /* cl506b.h */ 0x0000006e
-#define NV17_CHANNEL_DMA /* cl506b.h */ 0x0000176e
-#define NV40_CHANNEL_DMA /* cl506b.h */ 0x0000406e
-
-#define NV50_CHANNEL_GPFIFO /* cl506f.h */ 0x0000506f
-#define G82_CHANNEL_GPFIFO /* cl826f.h */ 0x0000826f
-#define FERMI_CHANNEL_GPFIFO /* cl906f.h */ 0x0000906f
-#define KEPLER_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000a06f
-#define KEPLER_CHANNEL_GPFIFO_B /* cla06f.h */ 0x0000a16f
-#define MAXWELL_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000b06f
-#define PASCAL_CHANNEL_GPFIFO_A /* cla06f.h */ 0x0000c06f
-#define VOLTA_CHANNEL_GPFIFO_A /* clc36f.h */ 0x0000c36f
-#define TURING_CHANNEL_GPFIFO_A /* clc36f.h */ 0x0000c46f
-#define AMPERE_CHANNEL_GPFIFO_B /* clc36f.h */ 0x0000c76f
+#define NV03_CHANNEL_DMA /* if0020.h */ 0x0000006b
+#define NV10_CHANNEL_DMA /* if0020.h */ 0x0000006e
+#define NV17_CHANNEL_DMA /* if0020.h */ 0x0000176e
+#define NV40_CHANNEL_DMA /* if0020.h */ 0x0000406e
+
+#define KEPLER_CHANNEL_GROUP_A /* if0021.h */ 0x0000a06c
+
+#define NV50_CHANNEL_GPFIFO /* if0020.h */ 0x0000506f
+#define G82_CHANNEL_GPFIFO /* if0020.h */ 0x0000826f
+#define FERMI_CHANNEL_GPFIFO /* if0020.h */ 0x0000906f
+#define KEPLER_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000a06f
+#define KEPLER_CHANNEL_GPFIFO_B /* if0020.h */ 0x0000a16f
+#define MAXWELL_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000b06f
+#define PASCAL_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000c06f
+#define VOLTA_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000c36f
+#define TURING_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000c46f
+#define AMPERE_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000c56f
+#define AMPERE_CHANNEL_GPFIFO_B /* if0020.h */ 0x0000c76f
#define NV50_DISP /* if0010.h */ 0x00005070
#define G82_DISP /* if0010.h */ 0x00008270
@@ -179,6 +190,8 @@
#define TURING_A /* cl9097.h */ 0x0000c597
+#define AMPERE_B /* cl9097.h */ 0x0000c797
+
#define NV74_BSP 0x000074b0
#define GT212_MSVLD 0x000085b1
@@ -206,6 +219,7 @@
#define PASCAL_DMA_COPY_B 0x0000c1b5
#define VOLTA_DMA_COPY_A 0x0000c3b5
#define TURING_DMA_COPY_A 0x0000c5b5
+#define AMPERE_DMA_COPY_A 0x0000c6b5
#define AMPERE_DMA_COPY_B 0x0000c7b5
#define FERMI_DECOMPRESS 0x000090b8
@@ -222,6 +236,7 @@
#define PASCAL_COMPUTE_B 0x0000c1c0
#define VOLTA_COMPUTE_A 0x0000c3c0
#define TURING_COMPUTE_A 0x0000c5c0
+#define AMPERE_COMPUTE_B 0x0000c7c0
#define NV74_CIPHER 0x000074c1
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/clb069.h b/drivers/gpu/drm/nouveau/include/nvif/clb069.h
index eef5d0227bab..d7689de35ab2 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/clb069.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/clb069.h
@@ -8,5 +8,8 @@ struct nvif_clb069_v0 {
__u32 put;
};
-#define NVB069_V0_NTFY_FAULT 0x00
+union nvif_clb069_event_args {
+ struct nvif_clb069_event_vn {
+ } vn;
+};
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/clc36f.h b/drivers/gpu/drm/nouveau/include/nvif/clc36f.h
deleted file mode 100644
index f66885891238..000000000000
--- a/drivers/gpu/drm/nouveau/include/nvif/clc36f.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-#ifndef __NVIF_CLC36F_H__
-#define __NVIF_CLC36F_H__
-
-struct volta_channel_gpfifo_a_v0 {
- __u8 version;
- __u8 priv;
- __u16 chid;
- __u32 ilength;
- __u64 ioffset;
- __u64 runlist;
- __u64 vmm;
- __u64 inst;
- __u32 token;
-};
-
-#define NVC36F_V0_NTFY_NON_STALL_INTERRUPT 0x00
-#define NVC36F_V0_NTFY_KILLED 0x01
-#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/conn.h b/drivers/gpu/drm/nouveau/include/nvif/conn.h
index f72a8f138f47..dc355e1dfafa 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/conn.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/conn.h
@@ -2,6 +2,7 @@
#ifndef __NVIF_CONN_H__
#define __NVIF_CONN_H__
#include <nvif/object.h>
+#include <nvif/event.h>
struct nvif_disp;
struct nvif_conn {
@@ -11,8 +12,17 @@ struct nvif_conn {
int nvif_conn_ctor(struct nvif_disp *, const char *name, int id, struct nvif_conn *);
void nvif_conn_dtor(struct nvif_conn *);
+static inline int
+nvif_conn_id(struct nvif_conn *conn)
+{
+ return conn->object.handle;
+}
+
#define NVIF_CONN_HPD_STATUS_UNSUPPORTED 0 /* negative if query fails */
#define NVIF_CONN_HPD_STATUS_NOT_PRESENT 1
#define NVIF_CONN_HPD_STATUS_PRESENT 2
int nvif_conn_hpd_status(struct nvif_conn *);
+
+int nvif_conn_event_ctor(struct nvif_conn *, const char *name, nvif_event_func, u8 types,
+ struct nvif_event *);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/disp.h b/drivers/gpu/drm/nouveau/include/nvif/disp.h
index 742632ad3bea..56eb7293e01c 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/disp.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/disp.h
@@ -7,6 +7,7 @@ struct nvif_disp {
struct nvif_object object;
unsigned long conn_mask;
unsigned long outp_mask;
+ unsigned long head_mask;
};
int nvif_disp_ctor(struct nvif_device *, const char *name, s32 oclass,
diff --git a/drivers/gpu/drm/nouveau/include/nvif/event.h b/drivers/gpu/drm/nouveau/include/nvif/event.h
index a6b1ee4f10ca..68bf6635841f 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/event.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/event.h
@@ -1,63 +1,36 @@
/* SPDX-License-Identifier: MIT */
#ifndef __NVIF_EVENT_H__
#define __NVIF_EVENT_H__
-
-struct nvif_notify_req_v0 {
- __u8 version;
- __u8 reply;
- __u8 pad02[5];
-#define NVIF_NOTIFY_V0_ROUTE_NVIF 0x00
- __u8 route;
- __u64 token; /* must be unique */
- __u8 data[]; /* request data (below) */
-};
-
-struct nvif_notify_rep_v0 {
- __u8 version;
- __u8 pad01[6];
- __u8 route;
- __u64 token;
- __u8 data[]; /* reply data (below) */
-};
-
-struct nvif_notify_head_req_v0 {
- /* nvif_notify_req ... */
- __u8 version;
- __u8 head;
- __u8 pad02[6];
-};
-
-struct nvif_notify_head_rep_v0 {
- /* nvif_notify_rep ... */
- __u8 version;
- __u8 pad01[7];
-};
-
-struct nvif_notify_conn_req_v0 {
- /* nvif_notify_req ... */
- __u8 version;
-#define NVIF_NOTIFY_CONN_V0_PLUG 0x01
-#define NVIF_NOTIFY_CONN_V0_UNPLUG 0x02
-#define NVIF_NOTIFY_CONN_V0_IRQ 0x04
-#define NVIF_NOTIFY_CONN_V0_ANY 0x07
- __u8 mask;
- __u8 conn;
- __u8 pad03[5];
-};
-
-struct nvif_notify_conn_rep_v0 {
- /* nvif_notify_rep ... */
- __u8 version;
- __u8 mask;
- __u8 pad02[6];
-};
-
-struct nvif_notify_uevent_req {
- /* nvif_notify_req ... */
-};
-
-struct nvif_notify_uevent_rep {
- /* nvif_notify_rep ... */
-};
-
+#include <nvif/object.h>
+#include <nvif/if000e.h>
+struct nvif_event;
+
+#define NVIF_EVENT_KEEP 0
+#define NVIF_EVENT_DROP 1
+typedef int (*nvif_event_func)(struct nvif_event *, void *repv, u32 repc);
+
+struct nvif_event {
+ struct nvif_object object;
+ nvif_event_func func;
+};
+
+static inline bool
+nvif_event_constructed(struct nvif_event *event)
+{
+ return nvif_object_constructed(&event->object);
+}
+
+int nvif_event_ctor_(struct nvif_object *, const char *, u32, nvif_event_func, bool,
+ struct nvif_event_v0 *, u32, bool, struct nvif_event *);
+
+static inline int
+nvif_event_ctor(struct nvif_object *parent, const char *name, u32 handle, nvif_event_func func,
+ bool wait, struct nvif_event_v0 *args, u32 argc, struct nvif_event *event)
+{
+ return nvif_event_ctor_(parent, name, handle, func, wait, args, argc, true, event);
+}
+
+void nvif_event_dtor(struct nvif_event *);
+int nvif_event_allow(struct nvif_event *);
+int nvif_event_block(struct nvif_event *);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/head.h b/drivers/gpu/drm/nouveau/include/nvif/head.h
new file mode 100644
index 000000000000..3ec36999e956
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/head.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: MIT */
+#ifndef __NVIF_HEAD_H__
+#define __NVIF_HEAD_H__
+#include <nvif/object.h>
+#include <nvif/event.h>
+struct nvif_disp;
+
+struct nvif_head {
+ struct nvif_object object;
+};
+
+int nvif_head_ctor(struct nvif_disp *, const char *name, int id, struct nvif_head *);
+void nvif_head_dtor(struct nvif_head *);
+
+static inline int
+nvif_head_id(struct nvif_head *head)
+{
+ return head->object.handle;
+}
+
+int nvif_head_vblank_event_ctor(struct nvif_head *, const char *name, nvif_event_func, bool wait,
+ struct nvif_event *);
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0004.h b/drivers/gpu/drm/nouveau/include/nvif/if0004.h
index d324c73c27fb..1d916a137941 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0004.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0004.h
@@ -2,7 +2,10 @@
#ifndef __NVIF_IF0004_H__
#define __NVIF_IF0004_H__
-#define NV04_NVSW_NTFY_UEVENT 0x00
+union nv04_nvsw_event_args {
+ struct nv04_nvsw_event_vn {
+ } vn;
+};
#define NV04_NVSW_GET_REF 0x00
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if000e.h b/drivers/gpu/drm/nouveau/include/nvif/if000e.h
new file mode 100644
index 000000000000..90a936cb1766
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/if000e.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: MIT */
+#ifndef __NVIF_IF000E_H__
+#define __NVIF_IF000E_H__
+
+union nvif_event_args {
+ struct nvif_event_v0 {
+ __u8 version;
+ __u8 wait;
+ __u8 pad02[6];
+ __u8 data[];
+ } v0;
+};
+
+#define NVIF_EVENT_V0_ALLOW 0x00
+#define NVIF_EVENT_V0_BLOCK 0x01
+
+union nvif_event_allow_args {
+ struct nvif_event_allow_vn {
+ } vn;
+};
+
+union nvif_event_block_args {
+ struct nvif_event_block_vn {
+ } vn;
+};
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0010.h b/drivers/gpu/drm/nouveau/include/nvif/if0010.h
index fc236ef28965..4c835bbe6fe3 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0010.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0010.h
@@ -8,6 +8,7 @@ union nvif_disp_args {
__u8 pad01[3];
__u32 conn_mask;
__u32 outp_mask;
+ __u32 head_mask;
} v0;
};
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0011.h b/drivers/gpu/drm/nouveau/include/nvif/if0011.h
index 04ba6581f840..69b0b779f942 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0011.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0011.h
@@ -10,6 +10,17 @@ union nvif_conn_args {
} v0;
};
+union nvif_conn_event_args {
+ struct nvif_conn_event_v0 {
+ __u8 version;
+#define NVIF_CONN_EVENT_V0_PLUG 0x01
+#define NVIF_CONN_EVENT_V0_UNPLUG 0x02
+#define NVIF_CONN_EVENT_V0_IRQ 0x04
+ __u8 types;
+ __u8 pad02[6];
+ } v0;
+};
+
#define NVIF_CONN_V0_HPD_STATUS 0x00000000
union nvif_conn_hpd_status_args {
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
index 243bd35d942f..eb99d84eb844 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/if0012.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h
@@ -11,6 +11,13 @@ union nvif_outp_args {
};
#define NVIF_OUTP_V0_LOAD_DETECT 0x00
+#define NVIF_OUTP_V0_ACQUIRE 0x01
+#define NVIF_OUTP_V0_RELEASE 0x02
+#define NVIF_OUTP_V0_INFOFRAME 0x03
+#define NVIF_OUTP_V0_HDA_ELD 0x04
+#define NVIF_OUTP_V0_DP_AUX_PWR 0x05
+#define NVIF_OUTP_V0_DP_RETRAIN 0x06
+#define NVIF_OUTP_V0_DP_MST_VCPI 0x07
union nvif_outp_load_detect_args {
struct nvif_outp_load_detect_v0 {
@@ -20,4 +27,95 @@ union nvif_outp_load_detect_args {
__u32 data; /*TODO: move vbios loadval parsing into nvkm */
} v0;
};
+
+union nvif_outp_acquire_args {
+ struct nvif_outp_acquire_v0 {
+ __u8 version;
+#define NVIF_OUTP_ACQUIRE_V0_RGB_CRT 0x00
+#define NVIF_OUTP_ACQUIRE_V0_TV 0x01
+#define NVIF_OUTP_ACQUIRE_V0_TMDS 0x02
+#define NVIF_OUTP_ACQUIRE_V0_LVDS 0x03
+#define NVIF_OUTP_ACQUIRE_V0_DP 0x04
+ __u8 proto;
+ __u8 or;
+ __u8 link;
+ __u8 pad04[4];
+ union {
+ struct {
+ __u8 head;
+ __u8 hdmi;
+ __u8 hdmi_max_ac_packet;
+ __u8 hdmi_rekey;
+#define NVIF_OUTP_ACQUIRE_V0_TMDS_HDMI_SCDC_SCRAMBLE (1 << 0)
+#define NVIF_OUTP_ACQUIRE_V0_TMDS_HDMI_SCDC_DIV_BY_4 (1 << 1)
+ __u8 hdmi_scdc;
+ __u8 hdmi_hda;
+ __u8 pad06[2];
+ } tmds;
+ struct {
+ __u8 dual;
+ __u8 bpc8;
+ __u8 pad02[6];
+ } lvds;
+ struct {
+ __u8 link_nr; /* 0 = highest possible. */
+ __u8 link_bw; /* 0 = highest possible, DP BW code otherwise. */
+ __u8 hda;
+ __u8 mst;
+ __u8 pad04[4];
+ __u8 dpcd[16];
+ } dp;
+ };
+ } v0;
+};
+
+union nvif_outp_release_args {
+ struct nvif_outp_release_vn {
+ } vn;
+};
+
+union nvif_outp_infoframe_args {
+ struct nvif_outp_infoframe_v0 {
+ __u8 version;
+#define NVIF_OUTP_INFOFRAME_V0_AVI 0
+#define NVIF_OUTP_INFOFRAME_V0_VSI 1
+ __u8 type;
+ __u8 head;
+ __u8 pad03[5];
+ __u8 data[];
+ } v0;
+};
+
+union nvif_outp_hda_eld_args {
+ struct nvif_outp_hda_eld_v0 {
+ __u8 version;
+ __u8 head;
+ __u8 pad02[6];
+ __u8 data[];
+ } v0;
+};
+
+union nvif_outp_dp_aux_pwr_args {
+ struct nvif_outp_dp_aux_pwr_v0 {
+ __u8 version;
+ __u8 state;
+ __u8 pad02[6];
+ } v0;
+};
+
+union nvif_outp_dp_retrain_args {
+ struct nvif_outp_dp_retrain_vn {
+ } vn;
+};
+
+union nvif_outp_dp_mst_vcpi_args {
+ struct nvif_outp_dp_mst_vcpi_v0 {
+ __u8 version;
+ __u8 head;
+ __u8 start_slot;
+ __u8 num_slots;
+ __u16 pbn;
+ __u16 aligned_pbn;
+ } v0;
+};
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0013.h b/drivers/gpu/drm/nouveau/include/nvif/if0013.h
new file mode 100644
index 000000000000..6756c7467ae4
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0013.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: MIT */
+#ifndef __NVIF_IF0013_H__
+#define __NVIF_IF0013_H__
+
+union nvif_head_args {
+ struct nvif_head_v0 {
+ __u8 version;
+ __u8 id;
+ __u8 pad02[6];
+ } v0;
+};
+
+union nvif_head_event_args {
+ struct nvif_head_event_vn {
+ } vn;
+};
+
+#define NVIF_HEAD_V0_SCANOUTPOS 0x00
+
+union nvif_head_scanoutpos_args {
+ struct nvif_head_scanoutpos_v0 {
+ __u8 version;
+ __u8 pad01[7];
+ __s64 time[2];
+ __u16 vblanks;
+ __u16 vblanke;
+ __u16 vtotal;
+ __u16 vline;
+ __u16 hblanks;
+ __u16 hblanke;
+ __u16 htotal;
+ __u16 hline;
+ } v0;
+};
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0020.h b/drivers/gpu/drm/nouveau/include/nvif/if0020.h
new file mode 100644
index 000000000000..085e0ae8a450
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0020.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: MIT */
+#ifndef __NVIF_IF0020_H__
+#define __NVIF_IF0020_H__
+
+union nvif_chan_args {
+ struct nvif_chan_v0 {
+ __u8 version;
+ __u8 namelen;
+ __u8 runlist;
+ __u8 runq;
+ __u8 priv;
+ __u8 pad05;
+ __u16 devm;
+ __u64 vmm;
+
+ __u64 ctxdma;
+ __u64 offset;
+ __u64 length;
+
+ __u64 huserd;
+ __u64 ouserd;
+
+ __u32 token;
+ __u16 chid;
+ __u8 pad3e;
+#define NVIF_CHAN_V0_INST_APER_VRAM 0
+#define NVIF_CHAN_V0_INST_APER_HOST 1
+#define NVIF_CHAN_V0_INST_APER_NCOH 2
+#define NVIF_CHAN_V0_INST_APER_INST 0xff
+ __u8 aper;
+ __u64 inst;
+
+ __u8 name[];
+ } v0;
+};
+
+union nvif_chan_event_args {
+ struct nvif_chan_event_v0 {
+ __u8 version;
+#define NVIF_CHAN_EVENT_V0_NON_STALL_INTR 0x00
+#define NVIF_CHAN_EVENT_V0_KILLED 0x01
+ __u8 type;
+ } v0;
+};
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0021.h b/drivers/gpu/drm/nouveau/include/nvif/if0021.h
new file mode 100644
index 000000000000..5013def90455
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvif/if0021.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: MIT */
+#ifndef __NVIF_IF0021_H__
+#define __NVIF_IF0021_H__
+
+union nvif_cgrp_args {
+ struct nvif_cgrp_v0 {
+ __u8 version;
+ __u8 namelen;
+ __u8 runlist;
+ __u8 pad03[3];
+ __u16 cgid;
+ __u64 vmm;
+ __u8 name[];
+ } v0;
+};
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/ioctl.h b/drivers/gpu/drm/nouveau/include/nvif/ioctl.h
index 886c63fe753f..4e047bb1fc07 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/ioctl.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/ioctl.h
@@ -15,10 +15,6 @@ struct nvif_ioctl_v0 {
#define NVIF_IOCTL_V0_WR 0x06
#define NVIF_IOCTL_V0_MAP 0x07
#define NVIF_IOCTL_V0_UNMAP 0x08
-#define NVIF_IOCTL_V0_NTFY_NEW 0x09
-#define NVIF_IOCTL_V0_NTFY_DEL 0x0a
-#define NVIF_IOCTL_V0_NTFY_GET 0x0b
-#define NVIF_IOCTL_V0_NTFY_PUT 0x0c
__u8 type;
__u8 pad02[4];
#define NVIF_IOCTL_V0_OWNER_NVIF 0x00
@@ -63,6 +59,14 @@ struct nvif_ioctl_new_v0 {
struct nvif_ioctl_del {
};
+struct nvif_ioctl_mthd_v0 {
+ /* nvif_ioctl ... */
+ __u8 version;
+ __u8 method;
+ __u8 pad02[6];
+ __u8 data[]; /* method data (class.h) */
+};
+
struct nvif_ioctl_rd_v0 {
/* nvif_ioctl ... */
__u8 version;
@@ -95,43 +99,4 @@ struct nvif_ioctl_map_v0 {
struct nvif_ioctl_unmap {
};
-
-struct nvif_ioctl_ntfy_new_v0 {
- /* nvif_ioctl ... */
- __u8 version;
- __u8 event;
- __u8 index;
- __u8 pad03[5];
- __u8 data[]; /* event request data (event.h) */
-};
-
-struct nvif_ioctl_ntfy_del_v0 {
- /* nvif_ioctl ... */
- __u8 version;
- __u8 index;
- __u8 pad02[6];
-};
-
-struct nvif_ioctl_ntfy_get_v0 {
- /* nvif_ioctl ... */
- __u8 version;
- __u8 index;
- __u8 pad02[6];
-};
-
-struct nvif_ioctl_ntfy_put_v0 {
- /* nvif_ioctl ... */
- __u8 version;
- __u8 index;
- __u8 pad02[6];
-};
-
-struct nvif_ioctl_mthd_v0 {
- /* nvif_ioctl ... */
- __u8 version;
- __u8 method;
- __u8 pad02[6];
- __u8 data[]; /* method data (class.h) */
-};
-
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/notify.h b/drivers/gpu/drm/nouveau/include/nvif/notify.h
deleted file mode 100644
index 39f6b7ee1719..000000000000
--- a/drivers/gpu/drm/nouveau/include/nvif/notify.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-#ifndef __NVIF_NOTIFY_H__
-#define __NVIF_NOTIFY_H__
-
-struct nvif_notify {
- struct nvif_object *object;
- const char *name;
- int index;
-
-#define NVIF_NOTIFY_USER 0
-#define NVIF_NOTIFY_WORK 1
- unsigned long flags;
- atomic_t putcnt;
- void (*dtor)(struct nvif_notify *);
-#define NVIF_NOTIFY_DROP 0
-#define NVIF_NOTIFY_KEEP 1
- int (*func)(struct nvif_notify *);
-
- /* this is const for a *very* good reason - the data might be on the
- * stack from an irq handler. if you're not nvif/notify.c then you
- * should probably think twice before casting it away...
- */
- const void *data;
- u32 size;
- struct work_struct work;
-};
-
-int nvif_notify_ctor(struct nvif_object *, const char *name,
- int (*func)(struct nvif_notify *), bool work, u8 type,
- void *data, u32 size, u32 reply, struct nvif_notify *);
-int nvif_notify_dtor(struct nvif_notify *);
-int nvif_notify_get(struct nvif_notify *);
-int nvif_notify_put(struct nvif_notify *);
-int nvif_notify(const void *, u32, const void *, u32);
-#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h b/drivers/gpu/drm/nouveau/include/nvif/outp.h
index 0d6aa07a9184..45daadec3c0c 100644
--- a/drivers/gpu/drm/nouveau/include/nvif/outp.h
+++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h
@@ -2,13 +2,32 @@
#ifndef __NVIF_OUTP_H__
#define __NVIF_OUTP_H__
#include <nvif/object.h>
+#include <nvif/if0012.h>
struct nvif_disp;
struct nvif_outp {
struct nvif_object object;
+
+ struct {
+ int id;
+ int link;
+ } or;
};
int nvif_outp_ctor(struct nvif_disp *, const char *name, int id, struct nvif_outp *);
void nvif_outp_dtor(struct nvif_outp *);
int nvif_outp_load_detect(struct nvif_outp *, u32 loadval);
+int nvif_outp_acquire_rgb_crt(struct nvif_outp *);
+int nvif_outp_acquire_tmds(struct nvif_outp *, int head,
+ bool hdmi, u8 max_ac_packet, u8 rekey, u8 scdc, bool hda);
+int nvif_outp_acquire_lvds(struct nvif_outp *, bool dual, bool bpc8);
+int nvif_outp_acquire_dp(struct nvif_outp *, u8 dpcd[16],
+ int link_nr, int link_bw, bool hda, bool mst);
+void nvif_outp_release(struct nvif_outp *);
+int nvif_outp_infoframe(struct nvif_outp *, u8 type, struct nvif_outp_infoframe_v0 *, u32 size);
+int nvif_outp_hda_eld(struct nvif_outp *, int head, void *data, u32 size);
+int nvif_outp_dp_aux_pwr(struct nvif_outp *, bool enable);
+int nvif_outp_dp_retrain(struct nvif_outp *);
+int nvif_outp_dp_mst_vcpi(struct nvif_outp *, int head,
+ u8 start_slot, u8 num_slots, u16 pbn, u16 aligned_pbn);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h
index 2f86606e708c..0d9fc741a719 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h
@@ -10,28 +10,19 @@ struct nvkm_client {
u64 device;
u32 debug;
- struct nvkm_client_notify *notify[32];
struct rb_root objroot;
void *data;
- int (*ntfy)(const void *, u32, const void *, u32);
+ int (*event)(u64 token, void *argv, u32 argc);
struct list_head umem;
spinlock_t lock;
};
-int nvkm_client_new(const char *name, u64 device, const char *cfg,
- const char *dbg,
- int (*)(const void *, u32, const void *, u32),
- struct nvkm_client **);
+int nvkm_client_new(const char *name, u64 device, const char *cfg, const char *dbg,
+ int (*)(u64, void *, u32), struct nvkm_client **);
struct nvkm_client *nvkm_client_search(struct nvkm_client *, u64 handle);
-int nvkm_client_notify_new(struct nvkm_object *, struct nvkm_event *,
- void *data, u32 size);
-int nvkm_client_notify_del(struct nvkm_client *, int index);
-int nvkm_client_notify_get(struct nvkm_client *, int index);
-int nvkm_client_notify_put(struct nvkm_client *, int index);
-
/* logging for client-facing objects */
#define nvif_printk(o,l,p,f,a...) do { \
const struct nvkm_object *_object = (o); \
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
index efede1f11e1d..f65b5009acf7 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h
@@ -2,6 +2,7 @@
#ifndef __NVKM_DEVICE_H__
#define __NVKM_DEVICE_H__
#include <core/oclass.h>
+#include <core/intr.h>
enum nvkm_subdev_type;
enum nvkm_device_type {
@@ -60,6 +61,16 @@ struct nvkm_device {
#undef NVKM_LAYOUT_INST
#undef NVKM_LAYOUT_ONCE
struct list_head subdev;
+
+ struct {
+ struct list_head intr;
+ struct list_head prio[NVKM_INTR_PRIO_NR];
+ spinlock_t lock;
+ int irq;
+ bool alloc;
+ bool armed;
+ bool legacy_done;
+ } intr;
};
struct nvkm_subdev *nvkm_device_subdev(struct nvkm_device *, int type, int inst);
@@ -72,6 +83,7 @@ struct nvkm_device_func {
int (*preinit)(struct nvkm_device *);
int (*init)(struct nvkm_device *);
void (*fini)(struct nvkm_device *, bool suspend);
+ int (*irq)(struct nvkm_device *);
resource_size_t (*resource_addr)(struct nvkm_device *, unsigned bar);
resource_size_t (*resource_size)(struct nvkm_device *, unsigned bar);
bool cpu_coherent;
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h b/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h
index e58923b67d74..b67b9c1a6b4e 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h
@@ -12,12 +12,6 @@ struct nvkm_engine {
const struct nvkm_engine_func *func;
struct nvkm_subdev subdev;
spinlock_t lock;
-
- struct {
- refcount_t refcount;
- struct mutex mutex;
- bool enabled;
- } use;
};
struct nvkm_engine_func {
@@ -27,6 +21,7 @@ struct nvkm_engine_func {
int (*info)(struct nvkm_engine *, u64 mthd, u64 *data);
int (*init)(struct nvkm_engine *);
int (*fini)(struct nvkm_engine *, bool suspend);
+ int (*reset)(struct nvkm_engine *);
void (*intr)(struct nvkm_engine *);
void (*tile)(struct nvkm_engine *, int region, struct nvkm_fb_tile *);
bool (*chsw_load)(struct nvkm_engine *);
@@ -54,6 +49,7 @@ int nvkm_engine_new_(const struct nvkm_engine_func *, struct nvkm_device *,
struct nvkm_engine *nvkm_engine_ref(struct nvkm_engine *);
void nvkm_engine_unref(struct nvkm_engine **);
+int nvkm_engine_reset(struct nvkm_engine *);
void nvkm_engine_tile(struct nvkm_engine *, int region);
bool nvkm_engine_chsw_load(struct nvkm_engine *);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/event.h b/drivers/gpu/drm/nouveau/include/nvkm/core/event.h
index a7a413f07a78..82b267c11147 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/event.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/event.h
@@ -2,34 +2,76 @@
#ifndef __NVKM_EVENT_H__
#define __NVKM_EVENT_H__
#include <core/os.h>
-struct nvkm_notify;
struct nvkm_object;
+struct nvkm_oclass;
+struct nvkm_uevent;
struct nvkm_event {
const struct nvkm_event_func *func;
+ struct nvkm_subdev *subdev;
int types_nr;
int index_nr;
spinlock_t refs_lock;
spinlock_t list_lock;
- struct list_head list;
int *refs;
+
+ struct list_head ntfy;
};
struct nvkm_event_func {
- int (*ctor)(struct nvkm_object *, void *data, u32 size,
- struct nvkm_notify *);
- void (*send)(void *data, u32 size, struct nvkm_notify *);
void (*init)(struct nvkm_event *, int type, int index);
void (*fini)(struct nvkm_event *, int type, int index);
};
-int nvkm_event_init(const struct nvkm_event_func *func, int types_nr,
- int index_nr, struct nvkm_event *);
+int __nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *, int types_nr,
+ int index_nr, struct nvkm_event *);
+
+/* Each nvkm_event needs its own lockdep class due to inter-dependencies, to
+ * prevent lockdep false-positives.
+ *
+ * Inlining the spinlock initialisation ensures each is unique.
+ */
+static __always_inline int
+nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *subdev,
+ int types_nr, int index_nr, struct nvkm_event *event)
+{
+ spin_lock_init(&event->refs_lock);
+ spin_lock_init(&event->list_lock);
+ return __nvkm_event_init(func, subdev, types_nr, index_nr, event);
+}
+
void nvkm_event_fini(struct nvkm_event *);
-void nvkm_event_get(struct nvkm_event *, u32 types, int index);
-void nvkm_event_put(struct nvkm_event *, u32 types, int index);
-void nvkm_event_send(struct nvkm_event *, u32 types, int index,
- void *data, u32 size);
+
+#define NVKM_EVENT_KEEP 0
+#define NVKM_EVENT_DROP 1
+struct nvkm_event_ntfy;
+typedef int (*nvkm_event_func)(struct nvkm_event_ntfy *, u32 bits);
+
+struct nvkm_event_ntfy {
+ struct nvkm_event *event;
+ int id;
+ u32 bits;
+ bool wait;
+ nvkm_event_func func;
+
+ atomic_t allowed;
+ bool running;
+
+ struct list_head head;
+};
+
+void nvkm_event_ntfy(struct nvkm_event *, int id, u32 bits);
+bool nvkm_event_ntfy_valid(struct nvkm_event *, int id, u32 bits);
+void nvkm_event_ntfy_add(struct nvkm_event *, int id, u32 bits, bool wait, nvkm_event_func,
+ struct nvkm_event_ntfy *);
+void nvkm_event_ntfy_del(struct nvkm_event_ntfy *);
+void nvkm_event_ntfy_allow(struct nvkm_event_ntfy *);
+void nvkm_event_ntfy_block(struct nvkm_event_ntfy *);
+
+typedef int (*nvkm_uevent_func)(struct nvkm_object *, u64 token, u32 bits);
+
+int nvkm_uevent_new(const struct nvkm_oclass *, void *argv, u32 argc, struct nvkm_object **);
+int nvkm_uevent_add(struct nvkm_uevent *, struct nvkm_event *, int id, u32 bits, nvkm_uevent_func);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h
index fd9a3f9a518e..b857cf142c4a 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/falcon.h
@@ -1,34 +1,166 @@
#ifndef __NVKM_FALCON_H__
#define __NVKM_FALCON_H__
+#include <core/firmware.h>
#include <engine/falcon.h>
+enum nvkm_falcon_mem {
+ IMEM,
+ DMEM,
+ EMEM,
+};
+
+static inline const char *
+nvkm_falcon_mem(enum nvkm_falcon_mem mem)
+{
+ switch (mem) {
+ case IMEM: return "imem";
+ case DMEM: return "dmem";
+ case EMEM: return "emem";
+ default:
+ WARN_ON(1);
+ return "?mem";
+ }
+}
+
+struct nvkm_falcon_func_pio {
+ int min;
+ int max;
+ void (*wr_init)(struct nvkm_falcon *, u8 port, bool sec, u32 mem_base);
+ void (*wr)(struct nvkm_falcon *, u8 port, const u8 *img, int len, u16 tag);
+ void (*rd_init)(struct nvkm_falcon *, u8 port, u32 mem_base);
+ void (*rd)(struct nvkm_falcon *, u8 port, const u8 *img, int len);
+};
+
+struct nvkm_falcon_func_dma {
+ int (*init)(struct nvkm_falcon *, u64 dma_addr, int xfer_len,
+ enum nvkm_falcon_mem, bool sec, u32 *cmd);
+ void (*xfer)(struct nvkm_falcon *, u32 mem_base, u32 dma_base, u32 cmd);
+ bool (*done)(struct nvkm_falcon *);
+};
+
int nvkm_falcon_ctor(const struct nvkm_falcon_func *, struct nvkm_subdev *owner,
const char *name, u32 addr, struct nvkm_falcon *);
void nvkm_falcon_dtor(struct nvkm_falcon *);
+int nvkm_falcon_reset(struct nvkm_falcon *);
+int nvkm_falcon_pio_wr(struct nvkm_falcon *, const u8 *img, u32 img_base, u8 port,
+ enum nvkm_falcon_mem mem_type, u32 mem_base, int len, u16 tag, bool sec);
+int nvkm_falcon_pio_rd(struct nvkm_falcon *, u8 port, enum nvkm_falcon_mem type, u32 mem_base,
+ const u8 *img, u32 img_base, int len);
+int nvkm_falcon_dma_wr(struct nvkm_falcon *, const u8 *img, u64 dma_addr, u32 dma_base,
+ enum nvkm_falcon_mem mem_type, u32 mem_base, int len, bool sec);
+
+int gm200_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *);
+int gm200_flcn_disable(struct nvkm_falcon *);
+int gm200_flcn_enable(struct nvkm_falcon *);
+void gm200_flcn_bind_inst(struct nvkm_falcon *, int, u64);
+int gm200_flcn_bind_stat(struct nvkm_falcon *, bool);
+extern const struct nvkm_falcon_func_pio gm200_flcn_imem_pio;
+extern const struct nvkm_falcon_func_pio gm200_flcn_dmem_pio;
+void gm200_flcn_tracepc(struct nvkm_falcon *);
+
+int gp102_flcn_reset_eng(struct nvkm_falcon *);
+extern const struct nvkm_falcon_func_pio gp102_flcn_emem_pio;
+
+int ga102_flcn_select(struct nvkm_falcon *);
+int ga102_flcn_reset_prep(struct nvkm_falcon *);
+int ga102_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *);
+extern const struct nvkm_falcon_func_dma ga102_flcn_dma;
void nvkm_falcon_v1_load_imem(struct nvkm_falcon *,
void *, u32, u32, u16, u8, bool);
void nvkm_falcon_v1_load_dmem(struct nvkm_falcon *, void *, u32, u32, u8);
-void nvkm_falcon_v1_read_dmem(struct nvkm_falcon *, u32, u32, u8, void *);
-void nvkm_falcon_v1_bind_context(struct nvkm_falcon *, struct nvkm_memory *);
-int nvkm_falcon_v1_wait_for_halt(struct nvkm_falcon *, u32);
-int nvkm_falcon_v1_clear_interrupt(struct nvkm_falcon *, u32);
-void nvkm_falcon_v1_set_start_addr(struct nvkm_falcon *, u32 start_addr);
void nvkm_falcon_v1_start(struct nvkm_falcon *);
-int nvkm_falcon_v1_enable(struct nvkm_falcon *);
-void nvkm_falcon_v1_disable(struct nvkm_falcon *);
-void gp102_sec2_flcn_bind_context(struct nvkm_falcon *, struct nvkm_memory *);
-int gp102_sec2_flcn_enable(struct nvkm_falcon *);
+#define FLCN_PRINTK(f,l,p,fmt,a...) ({ \
+ if ((f)->owner->name != (f)->name) \
+ nvkm_printk___((f)->owner, (f)->user, NV_DBG_##l, p, "%s:"fmt, (f)->name, ##a); \
+ else \
+ nvkm_printk___((f)->owner, (f)->user, NV_DBG_##l, p, fmt, ##a); \
+})
+#define FLCN_DBG(f,fmt,a...) FLCN_PRINTK((f), DEBUG, info, " "fmt"\n", ##a)
+#define FLCN_ERR(f,fmt,a...) FLCN_PRINTK((f), ERROR, err, " "fmt"\n", ##a)
+#define FLCN_ERRON(f,c,fmt,a...) \
+ ({ bool _cond = (c); _cond ? FLCN_ERR(f, fmt, ##a) : FLCN_DBG(f, fmt, ##a); _cond; })
+
+
+struct nvkm_falcon_fw {
+ const struct nvkm_falcon_fw_func {
+ int (*signature)(struct nvkm_falcon_fw *, u32 *sig_base_src);
+ int (*reset)(struct nvkm_falcon_fw *);
+ int (*setup)(struct nvkm_falcon_fw *);
+ int (*load)(struct nvkm_falcon_fw *);
+ int (*load_bld)(struct nvkm_falcon_fw *);
+ int (*boot)(struct nvkm_falcon_fw *,
+ u32 *mbox0, u32 *mbox1, u32 mbox0_ok, u32 irqsclr);
+ } *func;
+ struct nvkm_firmware fw;
+
+ u32 sig_base_prd;
+ u32 sig_base_dbg;
+ u32 sig_base_img;
+ u32 sig_size;
+ int sig_nr;
+ u8 *sigs;
+ u32 fuse_ver;
+ u32 engine_id;
+ u32 ucode_id;
+
+ u32 nmem_base_img;
+ u32 nmem_base;
+ u32 nmem_size;
+
+ u32 imem_base_img;
+ u32 imem_base;
+ u32 imem_size;
+
+ u32 dmem_base_img;
+ u32 dmem_base;
+ u32 dmem_size;
+ u32 dmem_sign;
+
+ u8 *boot;
+ u32 boot_size;
+ u32 boot_addr;
+
+ struct nvkm_falcon *falcon;
+ struct nvkm_memory *inst;
+ struct nvkm_vmm *vmm;
+ struct nvkm_vma *vma;
+};
+
+int nvkm_falcon_fw_ctor(const struct nvkm_falcon_fw_func *, const char *name, struct nvkm_device *,
+ bool bl, const void *src, u32 len, struct nvkm_falcon *,
+ struct nvkm_falcon_fw *);
+int nvkm_falcon_fw_ctor_hs(const struct nvkm_falcon_fw_func *, const char *name,
+ struct nvkm_subdev *, const char *bl, const char *img, int ver,
+ struct nvkm_falcon *falcon, struct nvkm_falcon_fw *fw);
+int nvkm_falcon_fw_ctor_hs_v2(const struct nvkm_falcon_fw_func *, const char *name,
+ struct nvkm_subdev *, const char *img, int ver, struct nvkm_falcon *,
+ struct nvkm_falcon_fw *);
+int nvkm_falcon_fw_sign(struct nvkm_falcon_fw *, u32 sig_base_img, u32 sig_size, const u8 *sigs,
+ int sig_nr_prd, u32 sig_base_prd, int sig_nr_dbg, u32 sig_base_dbg);
+int nvkm_falcon_fw_patch(struct nvkm_falcon_fw *);
+void nvkm_falcon_fw_dtor(struct nvkm_falcon_fw *);
+int nvkm_falcon_fw_oneinit(struct nvkm_falcon_fw *, struct nvkm_falcon *, struct nvkm_vmm *,
+ struct nvkm_memory *inst);
+int nvkm_falcon_fw_boot(struct nvkm_falcon_fw *, struct nvkm_subdev *user,
+ bool release, u32 *pmbox0, u32 *pmbox1, u32 mbox0_ok, u32 irqsclr);
+
+extern const struct nvkm_falcon_fw_func gm200_flcn_fw;
+int gm200_flcn_fw_signature(struct nvkm_falcon_fw *, u32 *);
+int gm200_flcn_fw_reset(struct nvkm_falcon_fw *);
+int gm200_flcn_fw_load(struct nvkm_falcon_fw *);
+int gm200_flcn_fw_boot(struct nvkm_falcon_fw *, u32 *, u32 *, u32, u32);
+
+int ga100_flcn_fw_signature(struct nvkm_falcon_fw *, u32 *);
+
+extern const struct nvkm_falcon_fw_func ga102_flcn_fw;
+int ga102_flcn_fw_load(struct nvkm_falcon_fw *);
+int ga102_flcn_fw_boot(struct nvkm_falcon_fw *, u32 *, u32 *, u32, u32);
-#define FLCN_PRINTK(t,f,fmt,a...) do { \
- if ((f)->owner->name != (f)->name) \
- nvkm_##t((f)->owner, "%s: "fmt"\n", (f)->name, ##a); \
- else \
- nvkm_##t((f)->owner, fmt"\n", ##a); \
-} while(0)
-#define FLCN_DBG(f,fmt,a...) FLCN_PRINTK(debug, (f), fmt, ##a)
-#define FLCN_ERR(f,fmt,a...) FLCN_PRINTK(error, (f), fmt, ##a)
+#define FLCNFW_PRINTK(f,l,p,fmt,a...) FLCN_PRINTK((f)->falcon, l, p, "%s: "fmt, (f)->fw.name, ##a)
+#define FLCNFW_DBG(f,fmt,a...) FLCNFW_PRINTK((f), DEBUG, info, fmt"\n", ##a)
+#define FLCNFW_ERR(f,fmt,a...) FLCNFW_PRINTK((f), ERROR, err, fmt"\n", ##a)
/**
* struct nvfw_falcon_msg - header for all messages
@@ -72,6 +204,7 @@ int nvkm_falcon_msgq_new(struct nvkm_falcon_qmgr *, const char *name,
void nvkm_falcon_msgq_del(struct nvkm_falcon_msgq **);
void nvkm_falcon_msgq_init(struct nvkm_falcon_msgq *,
u32 index, u32 offset, u32 size);
+bool nvkm_falcon_msgq_empty(struct nvkm_falcon_msgq *);
int nvkm_falcon_msgq_recv_initmsg(struct nvkm_falcon_msgq *, void *, u32 size);
void nvkm_falcon_msgq_recv(struct nvkm_falcon_msgq *);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h b/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h
index 85bcb80f6873..d4e507e252b1 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/firmware.h
@@ -1,9 +1,34 @@
/* SPDX-License-Identifier: MIT */
#ifndef __NVKM_FIRMWARE_H__
#define __NVKM_FIRMWARE_H__
+#include <core/memory.h>
#include <core/option.h>
#include <core/subdev.h>
+struct nvkm_firmware {
+ const struct nvkm_firmware_func {
+ enum nvkm_firmware_type {
+ NVKM_FIRMWARE_IMG_RAM,
+ NVKM_FIRMWARE_IMG_DMA,
+ } type;
+ } *func;
+ const char *name;
+ struct nvkm_device *device;
+
+ int len;
+ u8 *img;
+ u64 phys;
+
+ struct nvkm_firmware_mem {
+ struct nvkm_memory memory;
+ struct scatterlist sgl;
+ } mem;
+};
+
+int nvkm_firmware_ctor(const struct nvkm_firmware_func *, const char *name, struct nvkm_device *,
+ const void *ptr, int len, struct nvkm_firmware *);
+void nvkm_firmware_dtor(struct nvkm_firmware *);
+
int nvkm_firmware_get(const struct nvkm_subdev *, const char *fwname, int ver,
const struct firmware **);
void nvkm_firmware_put(const struct firmware *);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/intr.h b/drivers/gpu/drm/nouveau/include/nvkm/core/intr.h
new file mode 100644
index 000000000000..a003d6a544b0
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/intr.h
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: MIT */
+#ifndef __NVKM_INTR_H__
+#define __NVKM_INTR_H__
+#include <core/os.h>
+struct nvkm_device;
+struct nvkm_subdev;
+
+enum nvkm_intr_prio {
+ NVKM_INTR_PRIO_VBLANK = 0,
+ NVKM_INTR_PRIO_NORMAL,
+ NVKM_INTR_PRIO_NR
+};
+
+enum nvkm_intr_type {
+ NVKM_INTR_SUBDEV = -1, /* lookup vector by requesting subdev, in mapping table. */
+ NVKM_INTR_VECTOR_0 = 0,
+};
+
+struct nvkm_intr {
+ const struct nvkm_intr_func {
+ bool (*pending)(struct nvkm_intr *);
+ void (*unarm)(struct nvkm_intr *);
+ void (*rearm)(struct nvkm_intr *);
+ void (*block)(struct nvkm_intr *, int leaf, u32 mask);
+ void (*allow)(struct nvkm_intr *, int leaf, u32 mask);
+ void (*reset)(struct nvkm_intr *, int leaf, u32 mask);
+ } *func;
+ const struct nvkm_intr_data {
+ int type; /* enum nvkm_subdev_type (+ve), enum nvkm_intr_type (-ve) */
+ int inst;
+ int leaf;
+ u32 mask; /* 0-terminated. */
+ bool legacy; /* auto-create "legacy" nvkm_subdev_intr() handler */
+ } *data;
+
+ struct nvkm_subdev *subdev;
+ int leaves;
+ u32 *stat;
+ u32 *mask;
+
+ struct list_head head;
+};
+
+void nvkm_intr_ctor(struct nvkm_device *);
+void nvkm_intr_dtor(struct nvkm_device *);
+int nvkm_intr_install(struct nvkm_device *);
+void nvkm_intr_unarm(struct nvkm_device *);
+void nvkm_intr_rearm(struct nvkm_device *);
+
+int nvkm_intr_add(const struct nvkm_intr_func *, const struct nvkm_intr_data *,
+ struct nvkm_subdev *, int leaves, struct nvkm_intr *);
+void nvkm_intr_block(struct nvkm_subdev *, enum nvkm_intr_type);
+void nvkm_intr_allow(struct nvkm_subdev *, enum nvkm_intr_type);
+
+struct nvkm_inth;
+typedef irqreturn_t (*nvkm_inth_func)(struct nvkm_inth *);
+
+struct nvkm_inth {
+ struct nvkm_intr *intr;
+ int leaf;
+ u32 mask;
+ nvkm_inth_func func;
+
+ atomic_t allowed;
+
+ struct list_head head;
+};
+
+int nvkm_inth_add(struct nvkm_intr *, enum nvkm_intr_type, enum nvkm_intr_prio,
+ struct nvkm_subdev *, nvkm_inth_func, struct nvkm_inth *);
+void nvkm_inth_allow(struct nvkm_inth *);
+void nvkm_inth_block(struct nvkm_inth *);
+#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/layout.h b/drivers/gpu/drm/nouveau/include/nvkm/core/layout.h
index 7afe1579b20f..58108dea5aeb 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/layout.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/layout.h
@@ -1,8 +1,10 @@
/* SPDX-License-Identifier: MIT */
+NVKM_LAYOUT_ONCE(NVKM_SUBDEV_TOP , struct nvkm_top , top)
+NVKM_LAYOUT_ONCE(NVKM_SUBDEV_GSP , struct nvkm_gsp , gsp)
+NVKM_LAYOUT_ONCE(NVKM_SUBDEV_VFN , struct nvkm_vfn , vfn)
NVKM_LAYOUT_ONCE(NVKM_SUBDEV_PCI , struct nvkm_pci , pci)
NVKM_LAYOUT_ONCE(NVKM_SUBDEV_VBIOS , struct nvkm_bios , bios)
NVKM_LAYOUT_ONCE(NVKM_SUBDEV_DEVINIT , struct nvkm_devinit , devinit)
-NVKM_LAYOUT_ONCE(NVKM_SUBDEV_TOP , struct nvkm_top , top)
NVKM_LAYOUT_ONCE(NVKM_SUBDEV_PRIVRING, struct nvkm_subdev , privring)
NVKM_LAYOUT_ONCE(NVKM_SUBDEV_GPIO , struct nvkm_gpio , gpio)
NVKM_LAYOUT_ONCE(NVKM_SUBDEV_I2C , struct nvkm_i2c , i2c)
@@ -23,7 +25,6 @@ NVKM_LAYOUT_ONCE(NVKM_SUBDEV_VOLT , struct nvkm_volt , volt)
NVKM_LAYOUT_ONCE(NVKM_SUBDEV_ICCSENSE, struct nvkm_iccsense, iccsense)
NVKM_LAYOUT_ONCE(NVKM_SUBDEV_THERM , struct nvkm_therm , therm)
NVKM_LAYOUT_ONCE(NVKM_SUBDEV_CLK , struct nvkm_clk , clk)
-NVKM_LAYOUT_ONCE(NVKM_SUBDEV_GSP , struct nvkm_gsp , gsp)
NVKM_LAYOUT_INST(NVKM_SUBDEV_IOCTRL , struct nvkm_subdev , ioctrl, 3)
NVKM_LAYOUT_ONCE(NVKM_SUBDEV_FLA , struct nvkm_subdev , fla)
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h b/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h
index 74d3f1a809d7..d3b6a68ddda3 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h
@@ -37,6 +37,7 @@ struct nvkm_memory_func {
void (*release)(struct nvkm_memory *);
int (*map)(struct nvkm_memory *, u64 offset, struct nvkm_vmm *,
struct nvkm_vma *, void *argv, u32 argc);
+ int (*kmap)(struct nvkm_memory *, struct nvkm_memory **);
};
struct nvkm_memory_ptrs {
@@ -63,6 +64,7 @@ void nvkm_memory_tags_put(struct nvkm_memory *, struct nvkm_device *,
#define nvkm_memory_boot(p,v) (p)->func->boot((p),(v))
#define nvkm_memory_map(p,o,vm,va,av,ac) \
(p)->func->map((p),(o),(vm),(va),(av),(ac))
+#define nvkm_memory_kmap(p,i) ((p)->func->kmap ? (p)->func->kmap((p), (i)) : -ENOSYS)
/* accessor macros - kmap()/done() must bracket use of the other accessor
* macros to guarantee correct behaviour across all chipsets
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/notify.h b/drivers/gpu/drm/nouveau/include/nvkm/core/notify.h
deleted file mode 100644
index 3d358a66db3a..000000000000
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/notify.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-#ifndef __NVKM_NOTIFY_H__
-#define __NVKM_NOTIFY_H__
-#include <core/os.h>
-struct nvkm_object;
-
-struct nvkm_notify {
- struct nvkm_event *event;
- struct list_head head;
-#define NVKM_NOTIFY_USER 0
-#define NVKM_NOTIFY_WORK 1
- unsigned long flags;
- int block;
-#define NVKM_NOTIFY_DROP 0
-#define NVKM_NOTIFY_KEEP 1
- int (*func)(struct nvkm_notify *);
-
- /* set by nvkm_event ctor */
- u32 types;
- int index;
- u32 size;
-
- struct work_struct work;
- /* this is const for a *very* good reason - the data might be on the
- * stack from an irq handler. if you're not core/notify.c then you
- * should probably think twice before casting it away...
- */
- const void *data;
-};
-
-int nvkm_notify_init(struct nvkm_object *, struct nvkm_event *,
- int (*func)(struct nvkm_notify *), bool work,
- void *data, u32 size, u32 reply,
- struct nvkm_notify *);
-void nvkm_notify_fini(struct nvkm_notify *);
-void nvkm_notify_get(struct nvkm_notify *);
-void nvkm_notify_put(struct nvkm_notify *);
-void nvkm_notify_send(struct nvkm_notify *, void *data, u32 size);
-#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h
index 7efcd5d2f2ff..ed1f66360782 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h
@@ -4,6 +4,7 @@
#include <core/oclass.h>
struct nvkm_event;
struct nvkm_gpuobj;
+struct nvkm_uevent;
struct nvkm_object {
const struct nvkm_object_func *func;
@@ -43,6 +44,7 @@ struct nvkm_object_func {
int (*bind)(struct nvkm_object *, struct nvkm_gpuobj *, int align,
struct nvkm_gpuobj **);
int (*sclass)(struct nvkm_object *, int index, struct nvkm_oclass *);
+ int (*uevent)(struct nvkm_object *, void *argv, u32 argc, struct nvkm_uevent *);
};
void nvkm_object_ctor(const struct nvkm_object_func *,
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/os.h b/drivers/gpu/drm/nouveau/include/nvkm/core/os.h
index d7ba3205207f..4486d9862849 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/os.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/os.h
@@ -34,4 +34,24 @@ nvkm_blob_dtor(struct nvkm_blob *blob)
blob->data = NULL;
blob->size = 0;
}
+
+#define nvkm_list_find_next(p,h,m,c) ({ \
+ typeof(p) _p = NULL; \
+ list_for_each_entry_continue(p, (h), m) { \
+ if (c) { \
+ _p = p; \
+ break; \
+ } \
+ } \
+ _p; \
+})
+#define nvkm_list_find(p,h,m,c) \
+ (p = container_of((h), typeof(*p), m), nvkm_list_find_next(p, (h), m, (c)))
+#define nvkm_list_foreach(p,h,m,c) \
+ for (p = nvkm_list_find(p, (h), m, (c)); p; p = nvkm_list_find_next(p, (h), m, (c)))
+
+/*FIXME: remove after */
+#define nvkm_fifo_chan nvkm_chan
+#define nvkm_fifo_chan_func nvkm_chan_func
+#define nvkm_fifo_cgrp nvkm_cgrp
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h
index 96113c8bee8c..bce6e1ba09ea 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h
@@ -17,10 +17,19 @@ struct nvkm_subdev {
struct nvkm_device *device;
enum nvkm_subdev_type type;
int inst;
+
char name[16];
u32 debug;
- struct list_head head;
+ struct {
+ refcount_t refcount;
+ struct mutex mutex;
+ bool enabled;
+ } use;
+
+ struct nvkm_inth inth;
+
+ struct list_head head;
void **pself;
bool oneinit;
};
@@ -38,22 +47,41 @@ struct nvkm_subdev_func {
extern const char *nvkm_subdev_type[NVKM_SUBDEV_NR];
int nvkm_subdev_new_(const struct nvkm_subdev_func *, struct nvkm_device *, enum nvkm_subdev_type,
int inst, struct nvkm_subdev **);
-void nvkm_subdev_ctor(const struct nvkm_subdev_func *, struct nvkm_device *,
- enum nvkm_subdev_type, int inst, struct nvkm_subdev *);
+void __nvkm_subdev_ctor(const struct nvkm_subdev_func *, struct nvkm_device *,
+ enum nvkm_subdev_type, int inst, struct nvkm_subdev *);
+
+static inline void
+nvkm_subdev_ctor(const struct nvkm_subdev_func *func, struct nvkm_device *device,
+ enum nvkm_subdev_type type, int inst, struct nvkm_subdev *subdev)
+{
+ __nvkm_subdev_ctor(func, device, type, inst, subdev);
+ mutex_init(&subdev->use.mutex);
+}
+
void nvkm_subdev_disable(struct nvkm_device *, enum nvkm_subdev_type, int inst);
void nvkm_subdev_del(struct nvkm_subdev **);
+int nvkm_subdev_ref(struct nvkm_subdev *);
+void nvkm_subdev_unref(struct nvkm_subdev *);
int nvkm_subdev_preinit(struct nvkm_subdev *);
+int nvkm_subdev_oneinit(struct nvkm_subdev *);
int nvkm_subdev_init(struct nvkm_subdev *);
int nvkm_subdev_fini(struct nvkm_subdev *, bool suspend);
int nvkm_subdev_info(struct nvkm_subdev *, u64, u64 *);
void nvkm_subdev_intr(struct nvkm_subdev *);
/* subdev logging */
-#define nvkm_printk_(s,l,p,f,a...) do { \
- const struct nvkm_subdev *_subdev = (s); \
- if (CONFIG_NOUVEAU_DEBUG >= (l) && _subdev->debug >= (l)) \
- dev_##p(_subdev->device->dev, "%s: "f, _subdev->name, ##a); \
+#define nvkm_printk_ok(s,u,l) \
+ ((CONFIG_NOUVEAU_DEBUG >= (l)) && ((s)->debug >= (l) || ((u) && (u)->debug >= (l))))
+#define nvkm_printk___(s,u,l,p,f,a...) do { \
+ if (nvkm_printk_ok((s), (u), (l))) { \
+ if ((u) && (u) != (s)) \
+ dev_##p((s)->device->dev, "%s(%s):"f, (s)->name, (u)->name, ##a); \
+ else \
+ dev_##p((s)->device->dev, "%s:"f, (s)->name, ##a); \
+ } \
} while(0)
+#define nvkm_printk__(s,l,p,f,a...) nvkm_printk___((s), (s), (l), p, f, ##a)
+#define nvkm_printk_(s,l,p,f,a...) nvkm_printk__((s), (l), p, " "f, ##a)
#define nvkm_printk(s,l,p,f,a...) nvkm_printk_((s), NV_DBG_##l, p, f, ##a)
#define nvkm_fatal(s,f,a...) nvkm_printk((s), FATAL, crit, f, ##a)
#define nvkm_error(s,f,a...) nvkm_printk((s), ERROR, err, f, ##a)
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h b/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h
index 924009dd2bb0..ccee53d4e4ec 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/core/tegra.h
@@ -8,7 +8,6 @@ struct nvkm_device_tegra {
const struct nvkm_device_tegra_func *func;
struct nvkm_device device;
struct platform_device *pdev;
- int irq;
struct reset_control *rst;
struct clk *clk;
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h
index cfd2da8e66fe..b616a1e8ca02 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/ce.h
@@ -12,4 +12,6 @@ int gp100_ce_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct n
int gp102_ce_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_engine **);
int gv100_ce_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_engine **);
int tu102_ce_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_engine **);
+int ga100_ce_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_engine **);
+int ga102_ce_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_engine **);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
index 8b5d8a434be8..ad9aef2df48f 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h
@@ -16,6 +16,7 @@ struct nvkm_disp {
struct list_head conns;
struct nvkm_event hpd;
+#define NVKM_DISP_HEAD_EVENT_VBLANK BIT(0)
struct nvkm_event vblank;
struct {
@@ -31,13 +32,7 @@ struct nvkm_disp {
struct {
unsigned long mask;
int nr;
- } wndw, head, dac;
-
- struct {
- unsigned long mask;
- int nr;
- u32 lvdsconf;
- } sor;
+ } wndw, head, dac, sor;
struct {
unsigned long mask;
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h
index b593407b9e36..cd86d9198e4a 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h
@@ -16,15 +16,16 @@ enum nvkm_falcon_dmaidx {
struct nvkm_falcon {
const struct nvkm_falcon_func *func;
- const struct nvkm_subdev *owner;
+ struct nvkm_subdev *owner;
const char *name;
u32 addr;
+ u32 addr2;
struct mutex mutex;
struct mutex dmem_mutex;
bool oneinit;
- const struct nvkm_subdev *user;
+ struct nvkm_subdev *user;
u8 version;
u8 secret;
@@ -50,13 +51,42 @@ struct nvkm_falcon {
struct nvkm_engine engine;
};
-int nvkm_falcon_get(struct nvkm_falcon *, const struct nvkm_subdev *);
-void nvkm_falcon_put(struct nvkm_falcon *, const struct nvkm_subdev *);
+int nvkm_falcon_get(struct nvkm_falcon *, struct nvkm_subdev *);
+void nvkm_falcon_put(struct nvkm_falcon *, struct nvkm_subdev *);
int nvkm_falcon_new_(const struct nvkm_falcon_func *, struct nvkm_device *,
enum nvkm_subdev_type, int inst, bool enable, u32 addr, struct nvkm_engine **);
struct nvkm_falcon_func {
+ int (*disable)(struct nvkm_falcon *);
+ int (*enable)(struct nvkm_falcon *);
+ int (*select)(struct nvkm_falcon *);
+ u32 addr2;
+ bool reset_pmc;
+ int (*reset_eng)(struct nvkm_falcon *);
+ int (*reset_prep)(struct nvkm_falcon *);
+ int (*reset_wait_mem_scrubbing)(struct nvkm_falcon *);
+
+ u32 debug;
+ void (*bind_inst)(struct nvkm_falcon *, int target, u64 addr);
+ int (*bind_stat)(struct nvkm_falcon *, bool intr);
+ bool bind_intr;
+
+ const struct nvkm_falcon_func_pio *imem_pio;
+ const struct nvkm_falcon_func_dma *imem_dma;
+
+ const struct nvkm_falcon_func_pio *dmem_pio;
+ const struct nvkm_falcon_func_dma *dmem_dma;
+
+ u32 emem_addr;
+ const struct nvkm_falcon_func_pio *emem_pio;
+
+ struct {
+ u32 head;
+ u32 tail;
+ u32 stride;
+ } cmdq, msgq;
+
struct {
u32 *data;
u32 size;
@@ -66,29 +96,11 @@ struct nvkm_falcon_func {
u32 size;
} data;
void (*init)(struct nvkm_falcon *);
- void (*intr)(struct nvkm_falcon *, struct nvkm_fifo_chan *);
-
- u32 debug;
- u32 fbif;
+ void (*intr)(struct nvkm_falcon *, struct nvkm_chan *);
void (*load_imem)(struct nvkm_falcon *, void *, u32, u32, u16, u8, bool);
void (*load_dmem)(struct nvkm_falcon *, void *, u32, u32, u8);
- void (*read_dmem)(struct nvkm_falcon *, u32, u32, u8, void *);
- u32 emem_addr;
- void (*bind_context)(struct nvkm_falcon *, struct nvkm_memory *);
- int (*wait_for_halt)(struct nvkm_falcon *, u32);
- int (*clear_interrupt)(struct nvkm_falcon *, u32);
- void (*set_start_addr)(struct nvkm_falcon *, u32 start_addr);
void (*start)(struct nvkm_falcon *);
- int (*enable)(struct nvkm_falcon *falcon);
- void (*disable)(struct nvkm_falcon *falcon);
- int (*reset)(struct nvkm_falcon *);
-
- struct {
- u32 head;
- u32 tail;
- u32 stride;
- } cmdq, msgq;
struct nvkm_sclass sclass[];
};
@@ -116,13 +128,5 @@ nvkm_falcon_mask(struct nvkm_falcon *falcon, u32 addr, u32 mask, u32 val)
void nvkm_falcon_load_imem(struct nvkm_falcon *, void *, u32, u32, u16, u8,
bool);
void nvkm_falcon_load_dmem(struct nvkm_falcon *, void *, u32, u32, u8);
-void nvkm_falcon_read_dmem(struct nvkm_falcon *, u32, u32, u8, void *);
-void nvkm_falcon_bind_context(struct nvkm_falcon *, struct nvkm_memory *);
-void nvkm_falcon_set_start_addr(struct nvkm_falcon *, u32);
void nvkm_falcon_start(struct nvkm_falcon *);
-int nvkm_falcon_wait_for_halt(struct nvkm_falcon *, u32);
-int nvkm_falcon_clear_interrupt(struct nvkm_falcon *, u32);
-int nvkm_falcon_enable(struct nvkm_falcon *);
-void nvkm_falcon_disable(struct nvkm_falcon *);
-int nvkm_falcon_reset(struct nvkm_falcon *);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h
index 15099913504d..221abd6c4310 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h
@@ -6,56 +6,76 @@
#include <core/event.h>
struct nvkm_fault_data;
-#define NVKM_FIFO_CHID_NR 4096
#define NVKM_FIFO_ENGN_NR 16
-struct nvkm_fifo_engn {
- struct nvkm_object *object;
- int refcount;
- int usecount;
-};
-
-struct nvkm_fifo_chan {
- const struct nvkm_fifo_chan_func *func;
- struct nvkm_fifo *fifo;
- u32 engm;
- struct nvkm_object object;
+struct nvkm_chan {
+ const struct nvkm_chan_func *func;
+ char name[64];
+ struct nvkm_cgrp *cgrp;
+ int runq;
- struct list_head head;
- u16 chid;
struct nvkm_gpuobj *inst;
- struct nvkm_gpuobj *push;
struct nvkm_vmm *vmm;
- u64 addr;
- u32 size;
+ struct nvkm_gpuobj *push;
+ int id;
+
+ struct {
+ struct nvkm_memory *mem;
+ u32 base;
+ } userd;
+
+ u32 ramfc_offset;
+ struct nvkm_gpuobj *ramfc;
+ struct nvkm_gpuobj *cache;
+ struct nvkm_gpuobj *eng;
+ struct nvkm_gpuobj *pgd;
+ struct nvkm_ramht *ramht;
+
+ spinlock_t lock;
+ atomic_t blocked;
+ atomic_t errored;
- struct nvkm_fifo_engn engn[NVKM_FIFO_ENGN_NR];
+ struct list_head cctxs;
+ struct list_head head;
};
+struct nvkm_chan *nvkm_chan_get_chid(struct nvkm_engine *, int id, unsigned long *irqflags);
+struct nvkm_chan *nvkm_chan_get_inst(struct nvkm_engine *, u64 inst, unsigned long *irqflags);
+void nvkm_chan_put(struct nvkm_chan **, unsigned long irqflags);
+
struct nvkm_fifo {
const struct nvkm_fifo_func *func;
struct nvkm_engine engine;
- DECLARE_BITMAP(mask, NVKM_FIFO_CHID_NR);
- int nr;
- struct list_head chan;
+ struct nvkm_chid *chid;
+ struct nvkm_chid *cgid;
+
+ struct list_head runqs;
+ struct list_head runls;
+
+ struct {
+#define NVKM_FIFO_NONSTALL_EVENT BIT(0)
+ struct nvkm_event event;
+ struct nvkm_inth intr;
+ } nonstall;
+
+ struct {
+ u32 chan_msec;
+ } timeout;
+
+ struct {
+ struct nvkm_memory *mem;
+ struct nvkm_vma *bar1;
+ } userd;
+
spinlock_t lock;
struct mutex mutex;
-
- struct nvkm_event uevent; /* async user trigger */
- struct nvkm_event kevent; /* channel killed */
};
void nvkm_fifo_fault(struct nvkm_fifo *, struct nvkm_fault_data *);
void nvkm_fifo_pause(struct nvkm_fifo *, unsigned long *);
void nvkm_fifo_start(struct nvkm_fifo *, unsigned long *);
-
-void nvkm_fifo_chan_put(struct nvkm_fifo *, unsigned long flags,
- struct nvkm_fifo_chan **);
-struct nvkm_fifo_chan *
-nvkm_fifo_chan_inst(struct nvkm_fifo *, u64 inst, unsigned long *flags);
-struct nvkm_fifo_chan *
-nvkm_fifo_chan_chid(struct nvkm_fifo *, int chid, unsigned long *flags);
+bool nvkm_fifo_ctxsw_in_progress(struct nvkm_engine *);
int nv04_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **);
int nv10_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **);
@@ -63,6 +83,7 @@ int nv17_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct
int nv40_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **);
int nv50_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **);
int g84_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **);
+int g98_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **);
int gf100_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **);
int gk104_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **);
int gk110_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **);
@@ -70,10 +91,9 @@ int gk208_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct
int gk20a_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **);
int gm107_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **);
int gm200_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **);
-int gm20b_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **);
int gp100_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **);
-int gp10b_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **);
int gv100_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **);
int tu102_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **);
+int ga100_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **);
int ga102_fifo_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fifo **);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h
index b28b752ffaa2..a2333cfe6955 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/gr.h
@@ -54,4 +54,5 @@ int gp108_gr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct n
int gp10b_gr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_gr **);
int gv100_gr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_gr **);
int tu102_gr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_gr **);
+int ga102_gr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_gr **);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h
index 97bd3092f68a..9baf197ac833 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/nvdec.h
@@ -12,4 +12,5 @@ struct nvkm_nvdec {
};
int gm107_nvdec_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_nvdec **);
+int ga102_nvdec_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_nvdec **);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h
index 06264c840eae..8d48fb20fa54 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/sec2.h
@@ -10,15 +10,18 @@ struct nvkm_sec2 {
struct nvkm_engine engine;
struct nvkm_falcon falcon;
+ atomic_t running;
+ atomic_t initmsg;
+
struct nvkm_falcon_qmgr *qmgr;
struct nvkm_falcon_cmdq *cmdq;
struct nvkm_falcon_msgq *msgq;
struct work_struct work;
- bool initmsg_received;
};
int gp102_sec2_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_sec2 **);
int gp108_sec2_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_sec2 **);
int tu102_sec2_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_sec2 **);
+int ga102_sec2_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_sec2 **);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h
index c0b254f7f0b5..73d2a6ae9ab2 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/acr.h
@@ -36,7 +36,7 @@ struct nvkm_acr {
const struct nvkm_acr_func *func;
struct nvkm_subdev subdev;
- struct list_head hsfw, hsf;
+ struct list_head hsfw;
struct list_head lsfw, lsf;
u64 managed_falcons;
@@ -50,6 +50,7 @@ struct nvkm_acr {
struct nvkm_vmm *vmm;
bool done;
+ struct nvkm_acr_lsf *rtos;
const struct firmware *wpr_fw;
bool wpr_comp;
@@ -64,7 +65,9 @@ int gm20b_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct
int gp102_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **);
int gp108_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **);
int gp10b_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **);
+int gv100_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **);
int tu102_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **);
+int ga102_acr_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_acr **);
struct nvkm_acr_lsfw {
const struct nvkm_acr_lsf_func *func;
@@ -77,6 +80,7 @@ struct nvkm_acr_lsfw {
const struct firmware *sig;
+ bool secure_bootloader;
u32 bootloader_size;
u32 bootloader_imem_offset;
@@ -87,10 +91,19 @@ struct nvkm_acr_lsfw {
u32 app_resident_code_size;
u32 app_resident_data_offset;
u32 app_resident_data_size;
+ u32 app_imem_offset;
+ u32 app_dmem_offset;
u32 ucode_size;
u32 data_size;
+ u32 fuse_ver;
+ u32 engine_id;
+ u32 ucode_id;
+ u32 sig_size;
+ u32 sig_nr;
+ u8 *sigs;
+
struct {
u32 lsb;
u32 img;
@@ -105,10 +118,10 @@ struct nvkm_acr_lsf_func {
#define NVKM_ACR_LSF_DMACTL_REQ_CTX 0x00000004
#define NVKM_ACR_LSF_FORCE_PRIV_LOAD 0x00000008
u32 flags;
+ u32 bl_entry;
u32 bld_size;
void (*bld_write)(struct nvkm_acr *, u32 bld, struct nvkm_acr_lsfw *);
void (*bld_patch)(struct nvkm_acr *, u32 bld, s64 adjust);
- int (*boot)(struct nvkm_falcon *);
u64 bootstrap_falcons;
int (*bootstrap_falcon)(struct nvkm_falcon *, enum nvkm_acr_lsf_id);
int (*bootstrap_multiple_falcons)(struct nvkm_falcon *, u32 mask);
@@ -122,8 +135,20 @@ int
nvkm_acr_lsfw_load_sig_image_desc_v1(struct nvkm_subdev *, struct nvkm_falcon *,
enum nvkm_acr_lsf_id, const char *path,
int ver, const struct nvkm_acr_lsf_func *);
+
+int
+nvkm_acr_lsfw_load_sig_image_desc_v2(struct nvkm_subdev *, struct nvkm_falcon *,
+ enum nvkm_acr_lsf_id, const char *path,
+ int ver, const struct nvkm_acr_lsf_func *);
+
int
nvkm_acr_lsfw_load_bl_inst_data_sig(struct nvkm_subdev *, struct nvkm_falcon *,
enum nvkm_acr_lsf_id, const char *path,
int ver, const struct nvkm_acr_lsf_func *);
+
+int
+nvkm_acr_lsfw_load_bl_sig_net(struct nvkm_subdev *, struct nvkm_falcon *,
+ enum nvkm_acr_lsf_id, const char *path,
+ int ver, const struct nvkm_acr_lsf_func *,
+ const void *, u32, const void *, u32);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h
index 9c78f072d62b..e40bbf378a8d 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fault.h
@@ -2,18 +2,21 @@
#define __NVKM_FAULT_H__
#include <core/subdev.h>
#include <core/event.h>
-#include <core/notify.h>
struct nvkm_fault {
const struct nvkm_fault_func *func;
struct nvkm_subdev subdev;
+ struct nvkm_inth info_fault;
+
struct nvkm_fault_buffer *buffer[2];
int buffer_nr;
+#define NVKM_FAULT_BUFFER_EVENT_PENDING BIT(0)
struct nvkm_event event;
- struct nvkm_notify nrpfb;
+ struct nvkm_event_ntfy nrpfb;
+ struct work_struct nrpfb_work;
struct nvkm_device_oclass user;
};
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
index ef6a6297148c..40768373cdd9 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h
@@ -35,6 +35,11 @@ struct nvkm_fb {
struct nvkm_blob vpr_scrubber;
+ struct {
+ struct page *flush_page;
+ dma_addr_t flush_page_addr;
+ } sysmem;
+
struct nvkm_ram *ram;
struct {
@@ -53,6 +58,8 @@ struct nvkm_fb {
struct nvkm_memory *mmu_wr;
};
+int nvkm_fb_mem_unlock(struct nvkm_fb *);
+
void nvkm_fb_tile_init(struct nvkm_fb *, int region, u32 addr, u32 size,
u32 pitch, u32 flags, struct nvkm_fb_tile *);
void nvkm_fb_tile_fini(struct nvkm_fb *, int region, struct nvkm_fb_tile *);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gpio.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gpio.h
index 0e46ea1fe972..537c4fc58b4f 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gpio.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gpio.h
@@ -8,9 +8,6 @@
#include <subdev/bios/gpio.h>
struct nvkm_gpio_ntfy_req {
-#define NVKM_GPIO_HI 0x01
-#define NVKM_GPIO_LO 0x02
-#define NVKM_GPIO_TOGGLED 0x03
u8 mask;
u8 line;
};
@@ -23,6 +20,9 @@ struct nvkm_gpio {
const struct nvkm_gpio_func *func;
struct nvkm_subdev subdev;
+#define NVKM_GPIO_HI BIT(0)
+#define NVKM_GPIO_LO BIT(1)
+#define NVKM_GPIO_TOGGLED (NVKM_GPIO_HI | NVKM_GPIO_LO)
struct nvkm_event event;
};
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
index cf42a59d4e58..72619d7df73e 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/gsp.h
@@ -5,9 +5,12 @@
#include <core/falcon.h>
struct nvkm_gsp {
+ const struct nvkm_gsp_func *func;
struct nvkm_subdev subdev;
+
struct nvkm_falcon falcon;
};
int gv100_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
+int ga102_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h
index 146e13292203..40a1065ae626 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h
@@ -7,20 +7,6 @@
#include <subdev/bios.h>
#include <subdev/bios/i2c.h>
-struct nvkm_i2c_ntfy_req {
-#define NVKM_I2C_PLUG 0x01
-#define NVKM_I2C_UNPLUG 0x02
-#define NVKM_I2C_IRQ 0x04
-#define NVKM_I2C_DONE 0x08
-#define NVKM_I2C_ANY 0x0f
- u8 mask;
- u8 port;
-};
-
-struct nvkm_i2c_ntfy_rep {
- u8 mask;
-};
-
struct nvkm_i2c_bus_probe {
struct i2c_board_info dev;
u8 udelay; /* set to 0 to use the standard delay */
@@ -79,6 +65,11 @@ struct nvkm_i2c {
struct list_head bus;
struct list_head aux;
+#define NVKM_I2C_PLUG BIT(0)
+#define NVKM_I2C_UNPLUG BIT(1)
+#define NVKM_I2C_IRQ BIT(2)
+#define NVKM_I2C_DONE BIT(3)
+#define NVKM_I2C_ANY (NVKM_I2C_PLUG | NVKM_I2C_UNPLUG | NVKM_I2C_IRQ | NVKM_I2C_DONE)
struct nvkm_event event;
};
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h
index f967b97d163c..fcdaefc99fe8 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h
@@ -28,7 +28,7 @@ u32 nvkm_instmem_rd32(struct nvkm_instmem *, u32 addr);
void nvkm_instmem_wr32(struct nvkm_instmem *, u32 addr, u32 data);
int nvkm_instobj_new(struct nvkm_instmem *, u32 size, u32 align, bool zero,
struct nvkm_memory **);
-
+int nvkm_instobj_wrap(struct nvkm_device *, struct nvkm_memory *, struct nvkm_memory **);
int nv04_instmem_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_instmem **);
int nv40_instmem_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_instmem **);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h
index d32a326a9290..64294042ec07 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h
@@ -4,7 +4,8 @@
#include <core/subdev.h>
#include <core/mm.h>
-#define NVKM_LTC_MAX_ZBC_CNT 16
+#define NVKM_LTC_MAX_ZBC_COLOR_CNT 32
+#define NVKM_LTC_MAX_ZBC_DEPTH_CNT 16
struct nvkm_ltc {
const struct nvkm_ltc_func *func;
@@ -18,11 +19,13 @@ struct nvkm_ltc {
u32 tag_base;
struct nvkm_memory *tag_ram;
- int zbc_min;
- int zbc_max;
- u32 zbc_color[NVKM_LTC_MAX_ZBC_CNT][4];
- u32 zbc_depth[NVKM_LTC_MAX_ZBC_CNT];
- u32 zbc_stencil[NVKM_LTC_MAX_ZBC_CNT];
+ int zbc_color_min;
+ int zbc_color_max;
+ u32 zbc_color[NVKM_LTC_MAX_ZBC_COLOR_CNT][4];
+ int zbc_depth_min;
+ int zbc_depth_max;
+ u32 zbc_depth[NVKM_LTC_MAX_ZBC_DEPTH_CNT];
+ u32 zbc_stencil[NVKM_LTC_MAX_ZBC_DEPTH_CNT];
};
void nvkm_ltc_tags_clear(struct nvkm_device *, u32 first, u32 count);
@@ -41,4 +44,5 @@ int gm200_ltc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct
int gp100_ltc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_ltc **);
int gp102_ltc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_ltc **);
int gp10b_ltc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_ltc **);
+int ga102_ltc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_ltc **);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h
index cb86a56e68d4..127ac545e4b2 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mc.h
@@ -6,15 +6,14 @@
struct nvkm_mc {
const struct nvkm_mc_func *func;
struct nvkm_subdev subdev;
+
+ struct nvkm_intr intr;
};
void nvkm_mc_enable(struct nvkm_device *, enum nvkm_subdev_type, int);
void nvkm_mc_disable(struct nvkm_device *, enum nvkm_subdev_type, int);
bool nvkm_mc_enabled(struct nvkm_device *, enum nvkm_subdev_type, int);
void nvkm_mc_reset(struct nvkm_device *, enum nvkm_subdev_type, int);
-void nvkm_mc_intr(struct nvkm_device *, bool *handled);
-void nvkm_mc_intr_unarm(struct nvkm_device *);
-void nvkm_mc_intr_rearm(struct nvkm_device *);
void nvkm_mc_intr_mask(struct nvkm_device *, enum nvkm_subdev_type, int, bool enable);
void nvkm_mc_unk260(struct nvkm_device *, u32 data);
@@ -31,6 +30,5 @@ int gk104_mc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct n
int gk20a_mc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mc **);
int gp100_mc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mc **);
int gp10b_mc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mc **);
-int tu102_mc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mc **);
int ga100_mc_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mc **);
#endif
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h
index 74c19bdfb757..3c103101d5fc 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/pci.h
@@ -13,7 +13,6 @@ struct nvkm_pci {
const struct nvkm_pci_func *func;
struct nvkm_subdev subdev;
struct pci_dev *pdev;
- int irq;
struct {
struct agp_bridge_data *bridge;
@@ -38,6 +37,7 @@ void nvkm_pci_wr08(struct nvkm_pci *, u16 addr, u8 data);
void nvkm_pci_wr32(struct nvkm_pci *, u16 addr, u32 data);
u32 nvkm_pci_mask(struct nvkm_pci *, u16 addr, u32 mask, u32 value);
void nvkm_pci_rom_shadow(struct nvkm_pci *, bool shadow);
+void nvkm_pci_msi_rearm(struct nvkm_device *);
int nv04_pci_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_pci **);
int nv40_pci_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_pci **);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h
index ee75c5524c43..73e717b980b8 100644
--- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/top.h
@@ -21,6 +21,7 @@ struct nvkm_top_device {
struct list_head head;
};
+int nvkm_top_parse(struct nvkm_device *);
u32 nvkm_top_addr(struct nvkm_device *, enum nvkm_subdev_type, int);
u32 nvkm_top_reset(struct nvkm_device *, enum nvkm_subdev_type, int);
u32 nvkm_top_intr_mask(struct nvkm_device *, enum nvkm_subdev_type, int);
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h
new file mode 100644
index 000000000000..cc6d0796c265
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/vfn.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: MIT */
+#ifndef __NVKM_VFN_H__
+#define __NVKM_VFN_H__
+#include <core/subdev.h>
+
+struct nvkm_vfn {
+ const struct nvkm_vfn_func *func;
+ struct nvkm_subdev subdev;
+
+ struct {
+ u32 priv;
+ u32 user;
+ } addr;
+
+ struct nvkm_intr intr;
+
+ struct nvkm_device_oclass user;
+};
+
+int gv100_vfn_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_vfn **);
+int tu102_vfn_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_vfn **);
+int ga100_vfn_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_vfn **);
+#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c
index 5bee655e7e63..82dab51d8aeb 100644
--- a/drivers/gpu/drm/nouveau/nouveau_abi16.c
+++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c
@@ -27,7 +27,6 @@
#include <nvif/ioctl.h>
#include <nvif/class.h>
#include <nvif/cl0002.h>
-#include <nvif/cla06f.h>
#include <nvif/unpack.h>
#include "nouveau_drv.h"
@@ -253,7 +252,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv);
struct nouveau_abi16_chan *chan;
struct nvif_device *device;
- u64 engine;
+ u64 engine, runm;
int ret;
if (unlikely(!abi16))
@@ -263,6 +262,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
return nouveau_abi16_put(abi16, -ENODEV);
device = &abi16->device;
+ engine = NV_DEVICE_HOST_RUNLIST_ENGINES_GR;
/* hack to allow channel engine type specification on kepler */
if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
@@ -276,19 +276,18 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
default:
return nouveau_abi16_put(abi16, -ENOSYS);
}
- } else {
- engine = NV_DEVICE_HOST_RUNLIST_ENGINES_GR;
- }
- if (engine != NV_DEVICE_HOST_RUNLIST_ENGINES_CE)
- engine = nvif_fifo_runlist(device, engine);
- else
- engine = nvif_fifo_runlist_ce(device);
- init->fb_ctxdma_handle = engine;
- init->tt_ctxdma_handle = 0;
+ init->fb_ctxdma_handle = 0;
+ init->tt_ctxdma_handle = 0;
+ }
}
- if (init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0)
+ if (engine != NV_DEVICE_HOST_RUNLIST_ENGINES_CE)
+ runm = nvif_fifo_runlist(device, engine);
+ else
+ runm = nvif_fifo_runlist_ce(device);
+
+ if (!runm || init->fb_ctxdma_handle == ~0 || init->tt_ctxdma_handle == ~0)
return nouveau_abi16_put(abi16, -EINVAL);
/* allocate "abi16 channel" data and make up a handle for it */
@@ -300,8 +299,8 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS)
list_add(&chan->head, &abi16->channels);
/* create channel object and initialise dma and fence management */
- ret = nouveau_channel_new(drm, device, init->fb_ctxdma_handle,
- init->tt_ctxdma_handle, false, &chan->chan);
+ ret = nouveau_channel_new(drm, device, false, runm, init->fb_ctxdma_handle,
+ init->tt_ctxdma_handle, &chan->chan);
if (ret)
goto done;
diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c
index a614582779ca..40409a29f5b6 100644
--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c
+++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c
@@ -264,7 +264,11 @@ nva3_set_intensity(struct backlight_device *bd)
u32 div, val;
div = nvif_rd32(device, NV50_PDISP_SOR_PWM_DIV(or));
- val = (bd->props.brightness * div) / 100;
+
+ val = backlight_get_brightness(bd);
+ if (val)
+ val = (val * div) / 100;
+
if (div) {
nvif_wr32(device, NV50_PDISP_SOR_PWM_CTL(or),
val |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c
index 126b3c6e12f9..a11871e3119c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo.c
@@ -532,7 +532,7 @@ nouveau_bo_map(struct nouveau_bo *nvbo)
if (ret)
return ret;
- ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.resource->num_pages, &nvbo->kmap);
+ ret = ttm_bo_kmap(&nvbo->bo, 0, PFN_UP(nvbo->bo.base.size), &nvbo->kmap);
ttm_bo_unreserve(&nvbo->bo);
return ret;
@@ -856,6 +856,9 @@ nouveau_bo_move_init(struct nouveau_drm *drm)
int (*init)(struct nouveau_channel *, u32 handle);
} _methods[] = {
{ "COPY", 4, 0xc7b5, nve0_bo_move_copy, nve0_bo_move_init },
+ { "GRCE", 0, 0xc7b5, nve0_bo_move_copy, nvc0_bo_move_init },
+ { "COPY", 4, 0xc6b5, nve0_bo_move_copy, nve0_bo_move_init },
+ { "GRCE", 0, 0xc6b5, nve0_bo_move_copy, nvc0_bo_move_init },
{ "COPY", 4, 0xc5b5, nve0_bo_move_copy, nve0_bo_move_init },
{ "GRCE", 0, 0xc5b5, nve0_bo_move_copy, nvc0_bo_move_init },
{ "COPY", 4, 0xc3b5, nve0_bo_move_copy, nve0_bo_move_init },
@@ -1236,7 +1239,7 @@ vm_fault_t nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo)
} else {
/* make sure bo is in mappable vram */
if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA ||
- bo->resource->start + bo->resource->num_pages < mappable)
+ bo->resource->start + PFN_UP(bo->resource->size) < mappable)
return 0;
for (i = 0; i < nvbo->placement.num_placement; ++i) {
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo0039.c b/drivers/gpu/drm/nouveau/nouveau_bo0039.c
index 7390132129fe..e2ce44adaa5c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo0039.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo0039.c
@@ -52,7 +52,7 @@ nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
u32 src_offset = old_reg->start << PAGE_SHIFT;
u32 dst_ctxdma = nouveau_bo_mem_ctxdma(bo, chan, new_reg);
u32 dst_offset = new_reg->start << PAGE_SHIFT;
- u32 page_count = new_reg->num_pages;
+ u32 page_count = PFN_UP(new_reg->size);
int ret;
ret = PUSH_WAIT(push, 3);
@@ -62,7 +62,7 @@ nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
PUSH_MTHD(push, NV039, SET_CONTEXT_DMA_BUFFER_IN, src_ctxdma,
SET_CONTEXT_DMA_BUFFER_OUT, dst_ctxdma);
- page_count = new_reg->num_pages;
+ page_count = PFN_UP(new_reg->size);
while (page_count) {
int line_count = (page_count > 2047) ? 2047 : page_count;
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo5039.c b/drivers/gpu/drm/nouveau/nouveau_bo5039.c
index 4c75c7b3804c..c6cf3629a9f9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo5039.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo5039.c
@@ -41,7 +41,7 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
{
struct nouveau_mem *mem = nouveau_mem(old_reg);
struct nvif_push *push = chan->chan.push;
- u64 length = (new_reg->num_pages << PAGE_SHIFT);
+ u64 length = new_reg->size;
u64 src_offset = mem->vma[0].addr;
u64 dst_offset = mem->vma[1].addr;
int src_tiled = !!mem->kind;
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo74c1.c b/drivers/gpu/drm/nouveau/nouveau_bo74c1.c
index ed6c09d67840..9b7ba31fae13 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo74c1.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo74c1.c
@@ -44,7 +44,7 @@ nv84_bo_move_exec(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
if (ret)
return ret;
- PUSH_NVSQ(push, NV74C1, 0x0304, new_reg->num_pages << PAGE_SHIFT,
+ PUSH_NVSQ(push, NV74C1, 0x0304, new_reg->size,
0x0308, upper_32_bits(mem->vma[0].addr),
0x030c, lower_32_bits(mem->vma[0].addr),
0x0310, upper_32_bits(mem->vma[1].addr),
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo85b5.c b/drivers/gpu/drm/nouveau/nouveau_bo85b5.c
index dec29b2d8bb2..a15a38a87a95 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo85b5.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo85b5.c
@@ -44,10 +44,10 @@ nva3_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
struct nvif_push *push = chan->chan.push;
u64 src_offset = mem->vma[0].addr;
u64 dst_offset = mem->vma[1].addr;
- u32 page_count = new_reg->num_pages;
+ u32 page_count = PFN_UP(new_reg->size);
int ret;
- page_count = new_reg->num_pages;
+ page_count = PFN_UP(new_reg->size);
while (page_count) {
int line_count = (page_count > 8191) ? 8191 : page_count;
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo9039.c b/drivers/gpu/drm/nouveau/nouveau_bo9039.c
index 776b04976cdf..d2bb2687d401 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo9039.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo9039.c
@@ -42,10 +42,10 @@ nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
struct nouveau_mem *mem = nouveau_mem(old_reg);
u64 src_offset = mem->vma[0].addr;
u64 dst_offset = mem->vma[1].addr;
- u32 page_count = new_reg->num_pages;
+ u32 page_count = PFN_UP(new_reg->size);
int ret;
- page_count = new_reg->num_pages;
+ page_count = PFN_UP(new_reg->size);
while (page_count) {
int line_count = (page_count > 2047) ? 2047 : page_count;
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo90b5.c b/drivers/gpu/drm/nouveau/nouveau_bo90b5.c
index 8499f58213e3..4618f4f5ab56 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bo90b5.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bo90b5.c
@@ -37,10 +37,10 @@ nvc0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
struct nvif_push *push = chan->chan.push;
u64 src_offset = mem->vma[0].addr;
u64 dst_offset = mem->vma[1].addr;
- u32 page_count = new_reg->num_pages;
+ u32 page_count = PFN_UP(new_reg->size);
int ret;
- page_count = new_reg->num_pages;
+ page_count = PFN_UP(new_reg->size);
while (page_count) {
int line_count = (page_count > 8191) ? 8191 : page_count;
diff --git a/drivers/gpu/drm/nouveau/nouveau_boa0b5.c b/drivers/gpu/drm/nouveau/nouveau_boa0b5.c
index 575212472e7a..07a5c6302c98 100644
--- a/drivers/gpu/drm/nouveau/nouveau_boa0b5.c
+++ b/drivers/gpu/drm/nouveau/nouveau_boa0b5.c
@@ -58,7 +58,7 @@ nve0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
PITCH_IN, PAGE_SIZE,
PITCH_OUT, PAGE_SIZE,
LINE_LENGTH_IN, PAGE_SIZE,
- LINE_COUNT, new_reg->num_pages);
+ LINE_COUNT, PFN_UP(new_reg->size));
PUSH_IMMD(push, NVA0B5, LAUNCH_DMA,
NVDEF(NVA0B5, LAUNCH_DMA, DATA_TRANSFER_TYPE, NON_PIPELINED) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c
index 48dea5d0c580..e648ecd0c1a0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_chan.c
+++ b/drivers/gpu/drm/nouveau/nouveau_chan.c
@@ -25,12 +25,7 @@
#include <nvif/class.h>
#include <nvif/cl0002.h>
-#include <nvif/cl006b.h>
-#include <nvif/cl506f.h>
-#include <nvif/cl906f.h>
-#include <nvif/cla06f.h>
-#include <nvif/clc36f.h>
-#include <nvif/ioctl.h>
+#include <nvif/if0020.h>
#include "nouveau_drv.h"
#include "nouveau_dma.h"
@@ -46,15 +41,17 @@ int nouveau_vram_pushbuf;
module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400);
static int
-nouveau_channel_killed(struct nvif_notify *ntfy)
+nouveau_channel_killed(struct nvif_event *event, void *repv, u32 repc)
{
- struct nouveau_channel *chan = container_of(ntfy, typeof(*chan), kill);
+ struct nouveau_channel *chan = container_of(event, typeof(*chan), kill);
struct nouveau_cli *cli = (void *)chan->user.client;
+
NV_PRINTK(warn, cli, "channel %d killed!\n", chan->chid);
atomic_set(&chan->killed, 1);
if (chan->fence)
nouveau_fence_context_kill(chan->fence, -ENODEV);
- return NVIF_NOTIFY_DROP;
+
+ return NVIF_EVENT_DROP;
}
int
@@ -96,8 +93,9 @@ nouveau_channel_del(struct nouveau_channel **pchan)
nvif_object_dtor(&chan->nvsw);
nvif_object_dtor(&chan->gart);
nvif_object_dtor(&chan->vram);
- nvif_notify_dtor(&chan->kill);
+ nvif_event_dtor(&chan->kill);
nvif_object_dtor(&chan->user);
+ nvif_mem_dtor(&chan->mem_userd);
nvif_object_dtor(&chan->push.ctxdma);
nouveau_vma_del(&chan->push.vma);
nouveau_bo_unmap(chan->push.buffer);
@@ -247,134 +245,113 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device,
}
static int
-nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device,
- u64 runlist, bool priv, struct nouveau_channel **pchan)
+nouveau_channel_ctor(struct nouveau_drm *drm, struct nvif_device *device, bool priv, u64 runm,
+ struct nouveau_channel **pchan)
{
- static const u16 oclasses[] = { AMPERE_CHANNEL_GPFIFO_B,
- TURING_CHANNEL_GPFIFO_A,
- VOLTA_CHANNEL_GPFIFO_A,
- PASCAL_CHANNEL_GPFIFO_A,
- MAXWELL_CHANNEL_GPFIFO_A,
- KEPLER_CHANNEL_GPFIFO_B,
- KEPLER_CHANNEL_GPFIFO_A,
- FERMI_CHANNEL_GPFIFO,
- G82_CHANNEL_GPFIFO,
- NV50_CHANNEL_GPFIFO,
- 0 };
- const u16 *oclass = oclasses;
- union {
- struct nv50_channel_gpfifo_v0 nv50;
- struct fermi_channel_gpfifo_v0 fermi;
- struct kepler_channel_gpfifo_a_v0 kepler;
- struct volta_channel_gpfifo_a_v0 volta;
+ static const struct {
+ s32 oclass;
+ int version;
+ } hosts[] = {
+ { AMPERE_CHANNEL_GPFIFO_B, 0 },
+ { AMPERE_CHANNEL_GPFIFO_A, 0 },
+ { TURING_CHANNEL_GPFIFO_A, 0 },
+ { VOLTA_CHANNEL_GPFIFO_A, 0 },
+ { PASCAL_CHANNEL_GPFIFO_A, 0 },
+ { MAXWELL_CHANNEL_GPFIFO_A, 0 },
+ { KEPLER_CHANNEL_GPFIFO_B, 0 },
+ { KEPLER_CHANNEL_GPFIFO_A, 0 },
+ { FERMI_CHANNEL_GPFIFO , 0 },
+ { G82_CHANNEL_GPFIFO , 0 },
+ { NV50_CHANNEL_GPFIFO , 0 },
+ { NV40_CHANNEL_DMA , 0 },
+ { NV17_CHANNEL_DMA , 0 },
+ { NV10_CHANNEL_DMA , 0 },
+ { NV03_CHANNEL_DMA , 0 },
+ {}
+ };
+ struct {
+ struct nvif_chan_v0 chan;
+ char name[TASK_COMM_LEN+16];
} args;
+ struct nouveau_cli *cli = (void *)device->object.client;
struct nouveau_channel *chan;
- u32 size;
- int ret;
+ const u64 plength = 0x10000;
+ const u64 ioffset = plength;
+ const u64 ilength = 0x02000;
+ char name[TASK_COMM_LEN];
+ int cid, ret;
+ u64 size;
+
+ cid = nvif_mclass(&device->object, hosts);
+ if (cid < 0)
+ return cid;
+
+ if (hosts[cid].oclass < NV50_CHANNEL_GPFIFO)
+ size = plength;
+ else
+ size = ioffset + ilength;
/* allocate dma push buffer */
- ret = nouveau_channel_prep(drm, device, 0x12000, &chan);
+ ret = nouveau_channel_prep(drm, device, size, &chan);
*pchan = chan;
if (ret)
return ret;
/* create channel object */
- do {
- if (oclass[0] >= VOLTA_CHANNEL_GPFIFO_A) {
- args.volta.version = 0;
- args.volta.ilength = 0x02000;
- args.volta.ioffset = 0x10000 + chan->push.addr;
- args.volta.runlist = runlist;
- args.volta.vmm = nvif_handle(&chan->vmm->vmm.object);
- args.volta.priv = priv;
- size = sizeof(args.volta);
- } else
- if (oclass[0] >= KEPLER_CHANNEL_GPFIFO_A) {
- args.kepler.version = 0;
- args.kepler.ilength = 0x02000;
- args.kepler.ioffset = 0x10000 + chan->push.addr;
- args.kepler.runlist = runlist;
- args.kepler.vmm = nvif_handle(&chan->vmm->vmm.object);
- args.kepler.priv = priv;
- size = sizeof(args.kepler);
- } else
- if (oclass[0] >= FERMI_CHANNEL_GPFIFO) {
- args.fermi.version = 0;
- args.fermi.ilength = 0x02000;
- args.fermi.ioffset = 0x10000 + chan->push.addr;
- args.fermi.vmm = nvif_handle(&chan->vmm->vmm.object);
- size = sizeof(args.fermi);
- } else {
- args.nv50.version = 0;
- args.nv50.ilength = 0x02000;
- args.nv50.ioffset = 0x10000 + chan->push.addr;
- args.nv50.pushbuf = nvif_handle(&chan->push.ctxdma);
- args.nv50.vmm = nvif_handle(&chan->vmm->vmm.object);
- size = sizeof(args.nv50);
- }
-
- ret = nvif_object_ctor(&device->object, "abi16ChanUser", 0,
- *oclass++, &args, size, &chan->user);
- if (ret == 0) {
- if (chan->user.oclass >= VOLTA_CHANNEL_GPFIFO_A) {
- chan->chid = args.volta.chid;
- chan->inst = args.volta.inst;
- chan->token = args.volta.token;
- } else
- if (chan->user.oclass >= KEPLER_CHANNEL_GPFIFO_A) {
- chan->chid = args.kepler.chid;
- chan->inst = args.kepler.inst;
- } else
- if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO) {
- chan->chid = args.fermi.chid;
- } else {
- chan->chid = args.nv50.chid;
- }
+ args.chan.version = 0;
+ args.chan.namelen = sizeof(args.name);
+ args.chan.runlist = __ffs64(runm);
+ args.chan.runq = 0;
+ args.chan.priv = priv;
+ args.chan.devm = BIT(0);
+ if (hosts[cid].oclass < NV50_CHANNEL_GPFIFO) {
+ args.chan.vmm = 0;
+ args.chan.ctxdma = nvif_handle(&chan->push.ctxdma);
+ args.chan.offset = chan->push.addr;
+ args.chan.length = 0;
+ } else {
+ args.chan.vmm = nvif_handle(&chan->vmm->vmm.object);
+ if (hosts[cid].oclass < FERMI_CHANNEL_GPFIFO)
+ args.chan.ctxdma = nvif_handle(&chan->push.ctxdma);
+ else
+ args.chan.ctxdma = 0;
+ args.chan.offset = ioffset + chan->push.addr;
+ args.chan.length = ilength;
+ }
+ args.chan.huserd = 0;
+ args.chan.ouserd = 0;
+
+ /* allocate userd */
+ if (hosts[cid].oclass >= VOLTA_CHANNEL_GPFIFO_A) {
+ ret = nvif_mem_ctor(&cli->mmu, "abi16ChanUSERD", NVIF_CLASS_MEM_GF100,
+ NVIF_MEM_VRAM | NVIF_MEM_COHERENT | NVIF_MEM_MAPPABLE,
+ 0, PAGE_SIZE, NULL, 0, &chan->mem_userd);
+ if (ret)
return ret;
- }
- } while (*oclass);
- nouveau_channel_del(pchan);
- return ret;
-}
+ args.chan.huserd = nvif_handle(&chan->mem_userd.object);
+ args.chan.ouserd = 0;
-static int
-nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device,
- struct nouveau_channel **pchan)
-{
- static const u16 oclasses[] = { NV40_CHANNEL_DMA,
- NV17_CHANNEL_DMA,
- NV10_CHANNEL_DMA,
- NV03_CHANNEL_DMA,
- 0 };
- const u16 *oclass = oclasses;
- struct nv03_channel_dma_v0 args;
- struct nouveau_channel *chan;
- int ret;
+ chan->userd = &chan->mem_userd.object;
+ } else {
+ chan->userd = &chan->user;
+ }
- /* allocate dma push buffer */
- ret = nouveau_channel_prep(drm, device, 0x10000, &chan);
- *pchan = chan;
- if (ret)
- return ret;
+ get_task_comm(name, current);
+ snprintf(args.name, sizeof(args.name), "%s[%d]", name, task_pid_nr(current));
- /* create channel object */
- args.version = 0;
- args.pushbuf = nvif_handle(&chan->push.ctxdma);
- args.offset = chan->push.addr;
-
- do {
- ret = nvif_object_ctor(&device->object, "abi16ChanUser", 0,
- *oclass++, &args, sizeof(args),
- &chan->user);
- if (ret == 0) {
- chan->chid = args.chid;
- return ret;
- }
- } while (ret && *oclass);
+ ret = nvif_object_ctor(&device->object, "abi16ChanUser", 0, hosts[cid].oclass,
+ &args, sizeof(args), &chan->user);
+ if (ret) {
+ nouveau_channel_del(pchan);
+ return ret;
+ }
- nouveau_channel_del(pchan);
- return ret;
+ chan->runlist = args.chan.runlist;
+ chan->chid = args.chan.chid;
+ chan->inst = args.chan.inst;
+ chan->token = args.chan.token;
+ return 0;
}
static int
@@ -385,18 +362,24 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
struct nv_dma_v0 args = {};
int ret, i;
- ret = nvif_object_map(&chan->user, NULL, 0);
+ ret = nvif_object_map(chan->userd, NULL, 0);
if (ret)
return ret;
- if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO &&
- chan->user.oclass < AMPERE_CHANNEL_GPFIFO_B) {
- ret = nvif_notify_ctor(&chan->user, "abi16ChanKilled",
- nouveau_channel_killed,
- true, NV906F_V0_NTFY_KILLED,
- NULL, 0, 0, &chan->kill);
+ if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO) {
+ struct {
+ struct nvif_event_v0 base;
+ struct nvif_chan_event_v0 host;
+ } args;
+
+ args.host.version = 0;
+ args.host.type = NVIF_CHAN_EVENT_V0_KILLED;
+
+ ret = nvif_event_ctor(&chan->user, "abi16ChanKilled", chan->chid,
+ nouveau_channel_killed, false,
+ &args.base, sizeof(args), &chan->kill);
if (ret == 0)
- ret = nvif_notify_get(&chan->kill);
+ ret = nvif_event_allow(&chan->kill);
if (ret) {
NV_ERROR(drm, "Failed to request channel kill "
"notification: %d\n", ret);
@@ -503,24 +486,18 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart)
int
nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
- u32 arg0, u32 arg1, bool priv,
- struct nouveau_channel **pchan)
+ bool priv, u64 runm, u32 vram, u32 gart, struct nouveau_channel **pchan)
{
struct nouveau_cli *cli = (void *)device->object.client;
int ret;
- /* hack until fencenv50 is fixed, and agp access relaxed */
- ret = nouveau_channel_ind(drm, device, arg0, priv, pchan);
+ ret = nouveau_channel_ctor(drm, device, priv, runm, pchan);
if (ret) {
- NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret);
- ret = nouveau_channel_dma(drm, device, pchan);
- if (ret) {
- NV_PRINTK(dbg, cli, "dma channel create, %d\n", ret);
- return ret;
- }
+ NV_PRINTK(dbg, cli, "channel create, %d\n", ret);
+ return ret;
}
- ret = nouveau_channel_init(*pchan, arg0, arg1);
+ ret = nouveau_channel_init(*pchan, vram, gart);
if (ret) {
NV_PRINTK(err, cli, "channel failed to initialise, %d\n", ret);
nouveau_channel_del(pchan);
@@ -534,6 +511,12 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
return ret;
}
+void
+nouveau_channels_fini(struct nouveau_drm *drm)
+{
+ kfree(drm->runl);
+}
+
int
nouveau_channels_init(struct nouveau_drm *drm)
{
@@ -541,20 +524,53 @@ nouveau_channels_init(struct nouveau_drm *drm)
struct nv_device_info_v1 m;
struct {
struct nv_device_info_v1_data channels;
+ struct nv_device_info_v1_data runlists;
} v;
} args = {
.m.version = 1,
.m.count = sizeof(args.v) / sizeof(args.v.channels),
.v.channels.mthd = NV_DEVICE_HOST_CHANNELS,
+ .v.runlists.mthd = NV_DEVICE_HOST_RUNLISTS,
};
struct nvif_object *device = &drm->client.device.object;
- int ret;
+ int ret, i;
ret = nvif_object_mthd(device, NV_DEVICE_V0_INFO, &args, sizeof(args));
- if (ret || args.v.channels.mthd == NV_DEVICE_INFO_INVALID)
+ if (ret ||
+ args.v.runlists.mthd == NV_DEVICE_INFO_INVALID || !args.v.runlists.data ||
+ args.v.channels.mthd == NV_DEVICE_INFO_INVALID)
return -ENODEV;
- drm->chan.nr = args.v.channels.data;
- drm->chan.context_base = dma_fence_context_alloc(drm->chan.nr);
+ drm->chan_nr = drm->chan_total = args.v.channels.data;
+ drm->runl_nr = fls64(args.v.runlists.data);
+ drm->runl = kcalloc(drm->runl_nr, sizeof(*drm->runl), GFP_KERNEL);
+ if (!drm->runl)
+ return -ENOMEM;
+
+ if (drm->chan_nr == 0) {
+ for (i = 0; i < drm->runl_nr; i++) {
+ if (!(args.v.runlists.data & BIT(i)))
+ continue;
+
+ args.v.channels.mthd = NV_DEVICE_HOST_RUNLIST_CHANNELS;
+ args.v.channels.data = i;
+
+ ret = nvif_object_mthd(device, NV_DEVICE_V0_INFO, &args, sizeof(args));
+ if (ret || args.v.channels.mthd == NV_DEVICE_INFO_INVALID)
+ return -ENODEV;
+
+ drm->runl[i].chan_nr = args.v.channels.data;
+ drm->runl[i].chan_id_base = drm->chan_total;
+ drm->runl[i].context_base = dma_fence_context_alloc(drm->runl[i].chan_nr);
+
+ drm->chan_total += drm->runl[i].chan_nr;
+ }
+ } else {
+ drm->runl[0].context_base = dma_fence_context_alloc(drm->chan_nr);
+ for (i = 1; i < drm->runl_nr; i++)
+ drm->runl[i].context_base = drm->runl[0].context_base;
+
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h
index 98ba9d27e6b4..e06a8ffed31a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_chan.h
+++ b/drivers/gpu/drm/nouveau/nouveau_chan.h
@@ -2,7 +2,7 @@
#ifndef __NOUVEAU_CHAN_H__
#define __NOUVEAU_CHAN_H__
#include <nvif/object.h>
-#include <nvif/notify.h>
+#include <nvif/event.h>
#include <nvif/push.h>
struct nvif_device;
@@ -16,6 +16,10 @@ struct nouveau_channel {
struct nouveau_drm *drm;
struct nouveau_vmm *vmm;
+ struct nvif_mem mem_userd;
+ struct nvif_object *userd;
+
+ int runlist;
int chid;
u64 inst;
u32 token;
@@ -50,15 +54,15 @@ struct nouveau_channel {
struct nvif_object user;
- struct nvif_notify kill;
+ struct nvif_event kill;
atomic_t killed;
};
int nouveau_channels_init(struct nouveau_drm *);
+void nouveau_channels_fini(struct nouveau_drm *);
-int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *,
- u32 arg0, u32 arg1, bool priv,
- struct nouveau_channel **);
+int nouveau_channel_new(struct nouveau_drm *, struct nvif_device *, bool priv, u64 runm,
+ u32 vram, u32 gart, struct nouveau_channel **);
void nouveau_channel_del(struct nouveau_channel **);
int nouveau_channel_idle(struct nouveau_channel *);
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 1991bbb1d05c..086b66b60d91 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -47,8 +47,7 @@
#include "nouveau_crtc.h"
#include <nvif/class.h>
-#include <nvif/cl0046.h>
-#include <nvif/event.h>
+#include <nvif/if0011.h>
struct drm_display_mode *
nouveau_conn_native_mode(struct drm_connector *connector)
@@ -396,7 +395,8 @@ static void
nouveau_connector_destroy(struct drm_connector *connector)
{
struct nouveau_connector *nv_connector = nouveau_connector(connector);
- nvif_notify_dtor(&nv_connector->hpd);
+ nvif_event_dtor(&nv_connector->irq);
+ nvif_event_dtor(&nv_connector->hpd);
kfree(nv_connector->edid);
drm_connector_unregister(connector);
drm_connector_cleanup(connector);
@@ -1162,39 +1162,38 @@ nouveau_connector_funcs_lvds = {
};
void
-nouveau_connector_hpd(struct drm_connector *connector)
+nouveau_connector_hpd(struct nouveau_connector *nv_connector, u64 bits)
{
- struct nouveau_drm *drm = nouveau_drm(connector->dev);
- u32 mask = drm_connector_mask(connector);
+ struct nouveau_drm *drm = nouveau_drm(nv_connector->base.dev);
+ u32 mask = drm_connector_mask(&nv_connector->base);
+ unsigned long flags;
- mutex_lock(&drm->hpd_lock);
+ spin_lock_irqsave(&drm->hpd_lock, flags);
if (!(drm->hpd_pending & mask)) {
+ nv_connector->hpd_pending |= bits;
drm->hpd_pending |= mask;
schedule_work(&drm->hpd_work);
}
- mutex_unlock(&drm->hpd_lock);
+ spin_unlock_irqrestore(&drm->hpd_lock, flags);
}
static int
-nouveau_connector_hotplug(struct nvif_notify *notify)
+nouveau_connector_irq(struct nvif_event *event, void *repv, u32 repc)
{
- struct nouveau_connector *nv_connector =
- container_of(notify, typeof(*nv_connector), hpd);
- struct drm_connector *connector = &nv_connector->base;
- struct drm_device *dev = connector->dev;
- struct nouveau_drm *drm = nouveau_drm(dev);
- const struct nvif_notify_conn_rep_v0 *rep = notify->data;
- bool plugged = (rep->mask != NVIF_NOTIFY_CONN_V0_UNPLUG);
+ struct nouveau_connector *nv_connector = container_of(event, typeof(*nv_connector), irq);
- if (rep->mask & NVIF_NOTIFY_CONN_V0_IRQ) {
- nouveau_dp_irq(drm, nv_connector);
- return NVIF_NOTIFY_KEEP;
- }
+ schedule_work(&nv_connector->irq_work);
+ return NVIF_EVENT_KEEP;
+}
- NV_DEBUG(drm, "%splugged %s\n", plugged ? "" : "un", connector->name);
- nouveau_connector_hpd(connector);
+static int
+nouveau_connector_hotplug(struct nvif_event *event, void *repv, u32 repc)
+{
+ struct nouveau_connector *nv_connector = container_of(event, typeof(*nv_connector), hpd);
+ struct nvif_conn_event_v0 *rep = repv;
- return NVIF_NOTIFY_KEEP;
+ nouveau_connector_hpd(nv_connector, rep->types);
+ return NVIF_EVENT_KEEP;
}
static ssize_t
@@ -1290,6 +1289,7 @@ nouveau_connector_create(struct drm_device *dev,
connector = &nv_connector->base;
nv_connector->index = index;
+ INIT_WORK(&nv_connector->irq_work, nouveau_dp_irq);
/* attempt to parse vbios connector type and hotplug gpio */
nv_connector->dcb = olddcb_conn(dev, index);
@@ -1401,6 +1401,7 @@ nouveau_connector_create(struct drm_device *dev,
drm_connector_init(dev, connector, funcs, type);
drm_connector_helper_add(connector, &nouveau_connector_helper_funcs);
+ connector->polled = DRM_CONNECTOR_POLL_CONNECT;
if (nv_connector->dcb && (disp->disp.conn_mask & BIT(nv_connector->index))) {
ret = nvif_conn_ctor(&disp->disp, nv_connector->base.name, nv_connector->index,
@@ -1409,6 +1410,25 @@ nouveau_connector_create(struct drm_device *dev,
kfree(nv_connector);
return ERR_PTR(ret);
}
+
+ ret = nvif_conn_event_ctor(&nv_connector->conn, "kmsHotplug",
+ nouveau_connector_hotplug,
+ NVIF_CONN_EVENT_V0_PLUG | NVIF_CONN_EVENT_V0_UNPLUG,
+ &nv_connector->hpd);
+ if (ret == 0)
+ connector->polled = DRM_CONNECTOR_POLL_HPD;
+
+ if (nv_connector->aux.transfer) {
+ ret = nvif_conn_event_ctor(&nv_connector->conn, "kmsDpIrq",
+ nouveau_connector_irq, NVIF_CONN_EVENT_V0_IRQ,
+ &nv_connector->irq);
+ if (ret) {
+ nvif_event_dtor(&nv_connector->hpd);
+ nvif_conn_dtor(&nv_connector->conn);
+ kfree(nv_connector);
+ return ERR_PTR(ret);
+ }
+ }
}
connector->funcs->reset(connector);
@@ -1452,21 +1472,6 @@ nouveau_connector_create(struct drm_device *dev,
break;
}
- ret = nvif_notify_ctor(&disp->disp.object, "kmsHotplug",
- nouveau_connector_hotplug,
- true, NV04_DISP_NTFY_CONN,
- &(struct nvif_notify_conn_req_v0) {
- .mask = NVIF_NOTIFY_CONN_V0_ANY,
- .conn = index,
- },
- sizeof(struct nvif_notify_conn_req_v0),
- sizeof(struct nvif_notify_conn_rep_v0),
- &nv_connector->hpd);
- if (ret)
- connector->polled = DRM_CONNECTOR_POLL_CONNECT;
- else
- connector->polled = DRM_CONNECTOR_POLL_HPD;
-
drm_connector_register(connector);
return connector;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h
index f4e17ff68bf9..35bcb541722b 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.h
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.h
@@ -27,7 +27,7 @@
#ifndef __NOUVEAU_CONNECTOR_H__
#define __NOUVEAU_CONNECTOR_H__
#include <nvif/conn.h>
-#include <nvif/notify.h>
+#include <nvif/event.h>
#include <nvhw/class/cl507d.h>
#include <nvhw/class/cl907d.h>
@@ -124,7 +124,10 @@ struct nouveau_connector {
u8 *dcb;
struct nvif_conn conn;
- struct nvif_notify hpd;
+ u64 hpd_pending;
+ struct nvif_event hpd;
+ struct nvif_event irq;
+ struct work_struct irq_work;
struct drm_dp_aux aux;
@@ -198,7 +201,7 @@ nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc)
struct drm_connector *
nouveau_connector_create(struct drm_device *, const struct dcb_output *);
-void nouveau_connector_hpd(struct drm_connector *connector);
+void nouveau_connector_hpd(struct nouveau_connector *, u64 bits);
extern int nouveau_tv_disable;
extern int nouveau_ignorelid;
diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h
index 7f63be2ec35d..c717f664a7b8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_crtc.h
+++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h
@@ -26,16 +26,17 @@
#ifndef __NOUVEAU_CRTC_H__
#define __NOUVEAU_CRTC_H__
-
#include <drm/drm_crtc.h>
-#include <nvif/notify.h>
+#include <nvif/head.h>
+#include <nvif/event.h>
struct nouveau_crtc {
struct drm_crtc base;
+ struct nvif_head head;
int index;
- struct nvif_notify vblank;
+ struct nvif_event vblank;
uint32_t dpms_saved_fp_control;
uint32_t fp_users;
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index a2f5df568ca5..ec3ffff487fc 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -35,15 +35,14 @@
#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>
-#include "nouveau_fbcon.h"
#include "nouveau_crtc.h"
#include "nouveau_gem.h"
#include "nouveau_connector.h"
#include "nv50_display.h"
#include <nvif/class.h>
-#include <nvif/cl0046.h>
-#include <nvif/event.h>
+#include <nvif/if0011.h>
+#include <nvif/if0013.h>
#include <dispnv50/crc.h>
int
@@ -52,7 +51,7 @@ nouveau_display_vblank_enable(struct drm_crtc *crtc)
struct nouveau_crtc *nv_crtc;
nv_crtc = nouveau_crtc(crtc);
- nvif_notify_get(&nv_crtc->vblank);
+ nvif_event_allow(&nv_crtc->vblank);
return 0;
}
@@ -63,7 +62,7 @@ nouveau_display_vblank_disable(struct drm_crtc *crtc)
struct nouveau_crtc *nv_crtc;
nv_crtc = nouveau_crtc(crtc);
- nvif_notify_put(&nv_crtc->vblank);
+ nvif_event_block(&nv_crtc->vblank);
}
static inline int
@@ -84,24 +83,20 @@ static bool
nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
ktime_t *stime, ktime_t *etime)
{
- struct {
- struct nv04_disp_mthd_v0 base;
- struct nv04_disp_scanoutpos_v0 scan;
- } args = {
- .base.method = NV04_DISP_SCANOUTPOS,
- .base.head = nouveau_crtc(crtc)->index,
- };
- struct nouveau_display *disp = nouveau_display(crtc->dev);
struct drm_vblank_crtc *vblank = &crtc->dev->vblank[drm_crtc_index(crtc)];
+ struct nvif_head *head = &nouveau_crtc(crtc)->head;
+ struct nvif_head_scanoutpos_v0 args;
int retry = 20;
bool ret = false;
+ args.version = 0;
+
do {
- ret = nvif_mthd(&disp->disp.object, 0, &args, sizeof(args));
+ ret = nvif_mthd(&head->object, NVIF_HEAD_V0_SCANOUTPOS, &args, sizeof(args));
if (ret != 0)
return false;
- if (args.scan.vline) {
+ if (args.vline) {
ret = true;
break;
}
@@ -109,11 +104,10 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
if (retry) ndelay(vblank->linedur_ns);
} while (retry--);
- *hpos = args.scan.hline;
- *vpos = calc(args.scan.vblanks, args.scan.vblanke,
- args.scan.vtotal, args.scan.vline);
- if (stime) *stime = ns_to_ktime(args.scan.time[0]);
- if (etime) *etime = ns_to_ktime(args.scan.time[1]);
+ *hpos = args.hline;
+ *vpos = calc(args.vblanks, args.vblanke, args.vtotal, args.vline);
+ if (stime) *stime = ns_to_ktime(args.time[0]);
+ if (etime) *etime = ns_to_ktime(args.time[1]);
return ret;
}
@@ -397,7 +391,7 @@ nouveau_user_framebuffer_create(struct drm_device *dev,
static const struct drm_mode_config_funcs nouveau_mode_config_funcs = {
.fb_create = nouveau_user_framebuffer_create,
- .output_poll_changed = nouveau_fbcon_output_poll_changed,
+ .output_poll_changed = drm_fb_helper_output_poll_changed,
};
@@ -456,9 +450,9 @@ nouveau_display_hpd_resume(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
- mutex_lock(&drm->hpd_lock);
+ spin_lock_irq(&drm->hpd_lock);
drm->hpd_pending = ~0;
- mutex_unlock(&drm->hpd_lock);
+ spin_unlock_irq(&drm->hpd_lock);
schedule_work(&drm->hpd_work);
}
@@ -475,10 +469,10 @@ nouveau_display_hpd_work(struct work_struct *work)
pm_runtime_get_sync(dev->dev);
- mutex_lock(&drm->hpd_lock);
+ spin_lock_irq(&drm->hpd_lock);
pending = drm->hpd_pending;
drm->hpd_pending = 0;
- mutex_unlock(&drm->hpd_lock);
+ spin_unlock_irq(&drm->hpd_lock);
/* Nothing to do, exit early without updating the last busy counter */
if (!pending)
@@ -488,14 +482,30 @@ nouveau_display_hpd_work(struct work_struct *work)
drm_connector_list_iter_begin(dev, &conn_iter);
nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) {
+ struct nouveau_connector *nv_connector = nouveau_connector(connector);
enum drm_connector_status old_status = connector->status;
- u64 old_epoch_counter = connector->epoch_counter;
+ u64 bits, old_epoch_counter = connector->epoch_counter;
if (!(pending & drm_connector_mask(connector)))
continue;
- connector->status = drm_helper_probe_detect(connector, NULL,
- false);
+ spin_lock_irq(&drm->hpd_lock);
+ bits = nv_connector->hpd_pending;
+ nv_connector->hpd_pending = 0;
+ spin_unlock_irq(&drm->hpd_lock);
+
+ drm_dbg_kms(dev, "[CONNECTOR:%d:%s] plug:%d unplug:%d irq:%d\n",
+ connector->base.id, connector->name,
+ !!(bits & NVIF_CONN_EVENT_V0_PLUG),
+ !!(bits & NVIF_CONN_EVENT_V0_UNPLUG),
+ !!(bits & NVIF_CONN_EVENT_V0_IRQ));
+
+ if (bits & NVIF_CONN_EVENT_V0_IRQ) {
+ if (nouveau_dp_link_check(nv_connector))
+ continue;
+ }
+
+ connector->status = drm_helper_probe_detect(connector, NULL, false);
if (old_epoch_counter == connector->epoch_counter)
continue;
@@ -573,7 +583,8 @@ nouveau_display_init(struct drm_device *dev, bool resume, bool runtime)
drm_connector_list_iter_begin(dev, &conn_iter);
nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) {
struct nouveau_connector *conn = nouveau_connector(connector);
- nvif_notify_get(&conn->hpd);
+ nvif_event_allow(&conn->hpd);
+ nvif_event_allow(&conn->irq);
}
drm_connector_list_iter_end(&conn_iter);
@@ -608,7 +619,8 @@ nouveau_display_fini(struct drm_device *dev, bool suspend, bool runtime)
drm_connector_list_iter_begin(dev, &conn_iter);
nouveau_for_each_non_mst_connector_iter(connector, &conn_iter) {
struct nouveau_connector *conn = nouveau_connector(connector);
- nvif_notify_put(&conn->hpd);
+ nvif_event_block(&conn->irq);
+ nvif_event_block(&conn->hpd);
}
drm_connector_list_iter_end(&conn_iter);
@@ -659,7 +671,6 @@ int
nouveau_display_create(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
- struct nvkm_device *device = nvxx_device(&drm->client.device);
struct nouveau_display *disp;
int ret;
@@ -672,7 +683,6 @@ nouveau_display_create(struct drm_device *dev)
drm_mode_create_dvi_i_properties(dev);
dev->mode_config.funcs = &nouveau_mode_config_funcs;
- dev->mode_config.fb_base = device->func->resource_addr(device, 1);
dev->mode_config.min_width = 0;
dev->mode_config.min_height = 0;
@@ -734,7 +744,7 @@ nouveau_display_create(struct drm_device *dev)
}
INIT_WORK(&drm->hpd_work, nouveau_display_hpd_work);
- mutex_init(&drm->hpd_lock);
+ spin_lock_init(&drm->hpd_lock);
#ifdef CONFIG_ACPI
drm->acpi_nb.notifier_call = nouveau_display_acpi_ntfy;
register_acpi_notifier(&drm->acpi_nb);
@@ -768,8 +778,7 @@ nouveau_display_destroy(struct drm_device *dev)
nvif_disp_dtor(&disp->disp);
- nouveau_drm(dev)->display = NULL;
- mutex_destroy(&drm->hpd_lock);
+ drm->display = NULL;
kfree(disp);
}
@@ -778,6 +787,9 @@ nouveau_display_suspend(struct drm_device *dev, bool runtime)
{
struct nouveau_display *disp = nouveau_display(dev);
+ /* Disable console. */
+ drm_fb_helper_set_suspend_unlocked(dev->fb_helper, true);
+
if (drm_drv_uses_atomic_modeset(dev)) {
if (!runtime) {
disp->suspend = drm_atomic_helper_suspend(dev);
@@ -805,8 +817,10 @@ nouveau_display_resume(struct drm_device *dev, bool runtime)
drm_atomic_helper_resume(dev, disp->suspend);
disp->suspend = NULL;
}
- return;
}
+
+ /* Enable console. */
+ drm_fb_helper_set_suspend_unlocked(dev->fb_helper, false);
}
int
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c
index ddb75d80bc53..b90cac6d5772 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dma.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dma.c
@@ -42,9 +42,9 @@ READ_GET(struct nouveau_channel *chan, uint64_t *prev_get, int *timeout)
{
uint64_t val;
- val = nvif_rd32(&chan->user, chan->user_get);
+ val = nvif_rd32(chan->userd, chan->user_get);
if (chan->user_get_hi)
- val |= (uint64_t)nvif_rd32(&chan->user, chan->user_get_hi) << 32;
+ val |= (uint64_t)nvif_rd32(chan->userd, chan->user_get_hi) << 32;
/* reset counter as long as GET is still advancing, this is
* to avoid misdetecting a GPU lockup if the GPU happens to
@@ -86,7 +86,7 @@ nv50_dma_push(struct nouveau_channel *chan, u64 offset, int length)
/* Flush writes. */
nouveau_bo_rd32(pb, 0);
- nvif_wr32(&chan->user, 0x8c, chan->dma.ib_put);
+ nvif_wr32(chan->userd, 0x8c, chan->dma.ib_put);
if (user->func && user->func->doorbell)
user->func->doorbell(user, chan->token);
chan->dma.ib_free--;
@@ -98,7 +98,7 @@ nv50_dma_push_wait(struct nouveau_channel *chan, int count)
uint32_t cnt = 0, prev_get = 0;
while (chan->dma.ib_free < count) {
- uint32_t get = nvif_rd32(&chan->user, 0x88);
+ uint32_t get = nvif_rd32(chan->userd, 0x88);
if (get != prev_get) {
prev_get = get;
cnt = 0;
diff --git a/drivers/gpu/drm/nouveau/nouveau_dmem.c b/drivers/gpu/drm/nouveau/nouveau_dmem.c
index 20fe53815b20..789857faa048 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dmem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dmem.c
@@ -33,7 +33,6 @@
#include <nvif/if000c.h>
#include <nvif/if500b.h>
#include <nvif/if900b.h>
-#include <nvif/if000c.h>
#include <nvhw/class/cla0b5.h>
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c
index 20db8ea1a0ba..e00876f92aee 100644
--- a/drivers/gpu/drm/nouveau/nouveau_dp.c
+++ b/drivers/gpu/drm/nouveau/nouveau_dp.c
@@ -29,8 +29,7 @@
#include "nouveau_encoder.h"
#include "nouveau_crtc.h"
-#include <nvif/class.h>
-#include <nvif/cl5070.h>
+#include <nvif/if0011.h>
MODULE_PARM_DESC(mst, "Enable DisplayPort multi-stream (default: enabled)");
static int nouveau_mst = 1;
@@ -140,12 +139,17 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector,
* TODO: look into checking this before probing I2C to detect DVI/HDMI
*/
hpd = nvif_conn_hpd_status(&nv_connector->conn);
- if (hpd == NVIF_CONN_HPD_STATUS_NOT_PRESENT)
+ if (hpd == NVIF_CONN_HPD_STATUS_NOT_PRESENT) {
+ nvif_outp_dp_aux_pwr(&nv_encoder->outp, false);
goto out;
+ }
+ nvif_outp_dp_aux_pwr(&nv_encoder->outp, true);
status = nouveau_dp_probe_dpcd(nv_connector, nv_encoder);
- if (status == connector_status_disconnected)
+ if (status == connector_status_disconnected) {
+ nvif_outp_dp_aux_pwr(&nv_encoder->outp, false);
goto out;
+ }
/* If we're in MST mode, we're done here */
if (mstm && mstm->can_mst && mstm->is_mst) {
@@ -193,6 +197,7 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector,
ret = NOUVEAU_DP_MST;
goto out;
} else if (ret != 0) {
+ nvif_outp_dp_aux_pwr(&nv_encoder->outp, false);
goto out;
}
}
@@ -206,14 +211,28 @@ out:
return ret;
}
-void nouveau_dp_irq(struct nouveau_drm *drm,
- struct nouveau_connector *nv_connector)
+bool
+nouveau_dp_link_check(struct nouveau_connector *nv_connector)
+{
+ struct nouveau_encoder *nv_encoder = find_encoder(&nv_connector->base, DCB_OUTPUT_DP);
+
+ if (!nv_encoder || nv_encoder->outp.or.id < 0)
+ return true;
+
+ return nvif_outp_dp_retrain(&nv_encoder->outp) == 0;
+}
+
+void
+nouveau_dp_irq(struct work_struct *work)
{
+ struct nouveau_connector *nv_connector =
+ container_of(work, typeof(*nv_connector), irq_work);
struct drm_connector *connector = &nv_connector->base;
struct nouveau_encoder *outp = find_encoder(connector, DCB_OUTPUT_DP);
+ struct nouveau_drm *drm = nouveau_drm(outp->base.base.dev);
struct nv50_mstm *mstm;
+ u64 hpd = 0;
int ret;
- bool send_hpd = false;
if (!outp)
return;
@@ -225,14 +244,14 @@ void nouveau_dp_irq(struct nouveau_drm *drm,
if (mstm && mstm->is_mst) {
if (!nv50_mstm_service(drm, nv_connector, mstm))
- send_hpd = true;
+ hpd |= NVIF_CONN_EVENT_V0_UNPLUG;
} else {
drm_dp_cec_irq(&nv_connector->aux);
if (nouveau_dp_has_sink_count(connector, outp)) {
ret = drm_dp_read_sink_count(&nv_connector->aux);
if (ret != outp->dp.sink_count)
- send_hpd = true;
+ hpd |= NVIF_CONN_EVENT_V0_PLUG;
if (ret >= 0)
outp->dp.sink_count = ret;
}
@@ -240,8 +259,7 @@ void nouveau_dp_irq(struct nouveau_drm *drm,
mutex_unlock(&outp->dp.hpd_irq_lock);
- if (send_hpd)
- nouveau_connector_hpd(connector);
+ nouveau_connector_hpd(nv_connector, NVIF_CONN_EVENT_V0_IRQ | hpd);
}
/* TODO:
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index fd99ec0f4257..80f154b6adab 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -33,6 +33,8 @@
#include <drm/drm_aperture.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_drv.h>
+#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_ttm_helper.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_vblank.h>
@@ -49,7 +51,6 @@
#include <nvif/class.h>
#include <nvif/cl0002.h>
-#include <nvif/cla06f.h>
#include "nouveau_drv.h"
#include "nouveau_dma.h"
@@ -62,7 +63,6 @@
#include "nouveau_bios.h"
#include "nouveau_ioctl.h"
#include "nouveau_abi16.h"
-#include "nouveau_fbcon.h"
#include "nouveau_fence.h"
#include "nouveau_debugfs.h"
#include "nouveau_usif.h"
@@ -316,28 +316,19 @@ static void
nouveau_accel_ce_init(struct nouveau_drm *drm)
{
struct nvif_device *device = &drm->client.device;
+ u64 runm;
int ret = 0;
/* Allocate channel that has access to a (preferably async) copy
* engine, to use for TTM buffer moves.
*/
- if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
- ret = nouveau_channel_new(drm, device,
- nvif_fifo_runlist_ce(device), 0,
- true, &drm->cechan);
- } else
- if (device->info.chipset >= 0xa3 &&
- device->info.chipset != 0xaa &&
- device->info.chipset != 0xac) {
- /* Prior to Kepler, there's only a single runlist, so all
- * engines can be accessed from any channel.
- *
- * We still want to use a separate channel though.
- */
- ret = nouveau_channel_new(drm, device, NvDmaFB, NvDmaTT, false,
- &drm->cechan);
+ runm = nvif_fifo_runlist_ce(device);
+ if (!runm) {
+ NV_DEBUG(drm, "no ce runlist\n");
+ return;
}
+ ret = nouveau_channel_new(drm, device, false, runm, NvDmaFB, NvDmaTT, &drm->cechan);
if (ret)
NV_ERROR(drm, "failed to create ce channel, %d\n", ret);
}
@@ -355,23 +346,17 @@ static void
nouveau_accel_gr_init(struct nouveau_drm *drm)
{
struct nvif_device *device = &drm->client.device;
- u32 arg0, arg1;
+ u64 runm;
int ret;
- if (device->info.family >= NV_DEVICE_INFO_V0_AMPERE)
- return;
-
/* Allocate channel that has access to the graphics engine. */
- if (device->info.family >= NV_DEVICE_INFO_V0_KEPLER) {
- arg0 = nvif_fifo_runlist(device, NV_DEVICE_HOST_RUNLIST_ENGINES_GR);
- arg1 = 1;
- } else {
- arg0 = NvDmaFB;
- arg1 = NvDmaTT;
+ runm = nvif_fifo_runlist(device, NV_DEVICE_HOST_RUNLIST_ENGINES_GR);
+ if (!runm) {
+ NV_DEBUG(drm, "no gr runlist\n");
+ return;
}
- ret = nouveau_channel_new(drm, device, arg0, arg1, false,
- &drm->channel);
+ ret = nouveau_channel_new(drm, device, false, runm, NvDmaFB, NvDmaTT, &drm->channel);
if (ret) {
NV_ERROR(drm, "failed to create kernel channel, %d\n", ret);
nouveau_accel_gr_fini(drm);
@@ -436,6 +421,7 @@ nouveau_accel_fini(struct nouveau_drm *drm)
nouveau_accel_gr_fini(drm);
if (drm->fence)
nouveau_fence(drm)->dtor(drm);
+ nouveau_channels_fini(drm);
}
static void
@@ -485,6 +471,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
case PASCAL_CHANNEL_GPFIFO_A:
case VOLTA_CHANNEL_GPFIFO_A:
case TURING_CHANNEL_GPFIFO_A:
+ case AMPERE_CHANNEL_GPFIFO_A:
case AMPERE_CHANNEL_GPFIFO_B:
ret = nvc0_fence_create(drm);
break;
@@ -611,7 +598,6 @@ nouveau_drm_device_init(struct drm_device *dev)
nouveau_hwmon_init(dev);
nouveau_svm_init(drm);
nouveau_dmem_init(drm);
- nouveau_fbcon_init(dev);
nouveau_led_init(dev);
if (nouveau_pmops_runtime()) {
@@ -655,7 +641,6 @@ nouveau_drm_device_fini(struct drm_device *dev)
}
nouveau_led_fini(dev);
- nouveau_fbcon_fini(dev);
nouveau_dmem_fini(drm);
nouveau_svm_fini(drm);
nouveau_hwmon_fini(dev);
@@ -809,6 +794,11 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
if (ret)
goto fail_drm_dev_init;
+ if (nouveau_drm(drm_dev)->client.device.info.ram_size <= 32 * 1024 * 1024)
+ drm_fbdev_generic_setup(drm_dev, 8);
+ else
+ drm_fbdev_generic_setup(drm_dev, 32);
+
quirk_broken_nv_runpm(pdev);
return 0;
@@ -865,8 +855,6 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime)
nouveau_led_suspend(dev);
if (dev->mode_config.num_crtc) {
- NV_DEBUG(drm, "suspending console...\n");
- nouveau_fbcon_set_suspend(dev, 1);
NV_DEBUG(drm, "suspending display...\n");
ret = nouveau_display_suspend(dev, runtime);
if (ret)
@@ -940,8 +928,6 @@ nouveau_do_resume(struct drm_device *dev, bool runtime)
if (dev->mode_config.num_crtc) {
NV_DEBUG(drm, "resuming display...\n");
nouveau_display_resume(dev, runtime);
- NV_DEBUG(drm, "resuming console...\n");
- nouveau_fbcon_set_suspend(dev, 0);
}
nouveau_led_resume(dev);
@@ -1296,7 +1282,6 @@ static void nouveau_display_options(void)
DRM_DEBUG_DRIVER("... tv_disable : %d\n", nouveau_tv_disable);
DRM_DEBUG_DRIVER("... ignorelid : %d\n", nouveau_ignorelid);
DRM_DEBUG_DRIVER("... duallink : %d\n", nouveau_duallink);
- DRM_DEBUG_DRIVER("... nofbaccel : %d\n", nouveau_nofbaccel);
DRM_DEBUG_DRIVER("... config : %s\n", nouveau_config);
DRM_DEBUG_DRIVER("... debug : %s\n", nouveau_debug);
DRM_DEBUG_DRIVER("... noaccel : %d\n", nouveau_noaccel);
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 84df5ddae4d0..d6dd07bfa64a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -78,11 +78,6 @@ enum nouveau_drm_object_route {
NVDRM_OBJECT_ANY = NVIF_IOCTL_V0_OWNER_ANY,
};
-enum nouveau_drm_notify_route {
- NVDRM_NOTIFY_NVIF = 0,
- NVDRM_NOTIFY_USIF
-};
-
enum nouveau_drm_handle {
NVDRM_CHAN = 0xcccc0000, /* |= client chid */
NVDRM_NVSW = 0x55550000,
@@ -179,16 +174,19 @@ struct nouveau_drm {
void *fence;
/* Global channel management. */
+ int chan_total; /* Number of channels across all runlists. */
+ int chan_nr; /* 0 if per-runlist CHIDs. */
+ int runl_nr;
struct {
- int nr;
+ int chan_nr;
+ int chan_id_base;
u64 context_base;
- } chan;
+ } *runl;
/* context for accelerated drm-internal operations */
struct nouveau_channel *cechan;
struct nouveau_channel *channel;
struct nvkm_gpuobj *notify;
- struct nouveau_fbdev *fbcon;
struct nvif_object ntfy;
/* nv10-nv40 tiling regions */
@@ -201,10 +199,8 @@ struct nouveau_drm {
struct nvbios vbios;
struct nouveau_display *display;
struct work_struct hpd_work;
- struct mutex hpd_lock;
+ spinlock_t hpd_lock;
u32 hpd_pending;
- struct work_struct fbcon_work;
- int fbcon_new_state;
#ifdef CONFIG_ACPI
struct notifier_block acpi_nb;
#endif
diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h
index b72e5783a00f..70c1ad6c4d9d 100644
--- a/drivers/gpu/drm/nouveau/nouveau_encoder.h
+++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h
@@ -48,7 +48,6 @@ struct nouveau_encoder {
struct dcb_output *dcb;
struct nvif_outp outp;
int or;
- int link;
struct i2c_adapter *i2c;
struct nvkm_i2c_aux *aux;
@@ -142,8 +141,8 @@ enum nouveau_dp_status {
};
int nouveau_dp_detect(struct nouveau_connector *, struct nouveau_encoder *);
-void nouveau_dp_irq(struct nouveau_drm *drm,
- struct nouveau_connector *nv_connector);
+bool nouveau_dp_link_check(struct nouveau_connector *);
+void nouveau_dp_irq(struct work_struct *);
enum drm_mode_status nv50_dp_mode_valid(struct drm_connector *,
struct nouveau_encoder *,
const struct drm_display_mode *,
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
index 3c7e0c9d6baf..e87de7906f78 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c
@@ -231,9 +231,9 @@ void
nouveau_fbcon_accel_save_disable(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
- if (drm->fbcon && drm->fbcon->helper.fbdev) {
- drm->fbcon->saved_flags = drm->fbcon->helper.fbdev->flags;
- drm->fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED;
+ if (drm->fbcon && drm->fbcon->helper.info) {
+ drm->fbcon->saved_flags = drm->fbcon->helper.info->flags;
+ drm->fbcon->helper.info->flags |= FBINFO_HWACCEL_DISABLED;
}
}
@@ -241,9 +241,8 @@ void
nouveau_fbcon_accel_restore(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
- if (drm->fbcon && drm->fbcon->helper.fbdev) {
- drm->fbcon->helper.fbdev->flags = drm->fbcon->saved_flags;
- }
+ if (drm->fbcon && drm->fbcon->helper.info)
+ drm->fbcon->helper.info->flags = drm->fbcon->saved_flags;
}
static void
@@ -253,8 +252,8 @@ nouveau_fbcon_accel_fini(struct drm_device *dev)
struct nouveau_fbdev *fbcon = drm->fbcon;
if (fbcon && drm->channel) {
console_lock();
- if (fbcon->helper.fbdev)
- fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED;
+ if (fbcon->helper.info)
+ fbcon->helper.info->flags |= FBINFO_HWACCEL_DISABLED;
console_unlock();
nouveau_channel_idle(drm->channel);
nvif_object_dtor(&fbcon->twod);
@@ -272,7 +271,7 @@ nouveau_fbcon_accel_init(struct drm_device *dev)
{
struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_fbdev *fbcon = drm->fbcon;
- struct fb_info *info = fbcon->helper.fbdev;
+ struct fb_info *info = fbcon->helper.info;
int ret;
if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA)
@@ -290,7 +289,7 @@ nouveau_fbcon_accel_init(struct drm_device *dev)
static void
nouveau_fbcon_zfill(struct drm_device *dev, struct nouveau_fbdev *fbcon)
{
- struct fb_info *info = fbcon->helper.fbdev;
+ struct fb_info *info = fbcon->helper.info;
struct fb_fillrect rect;
/* Clear the entire fbcon. The drm will program every connector
@@ -363,7 +362,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
}
}
- info = drm_fb_helper_alloc_fbi(helper);
+ info = drm_fb_helper_alloc_info(helper);
if (IS_ERR(info)) {
ret = PTR_ERR(info);
goto out_unlock;
@@ -420,7 +419,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon)
struct drm_framebuffer *fb = fbcon->helper.fb;
struct nouveau_bo *nvbo;
- drm_fb_helper_unregister_fbi(&fbcon->helper);
+ drm_fb_helper_unregister_info(&fbcon->helper);
drm_fb_helper_fini(&fbcon->helper);
if (fb && fb->obj[0]) {
@@ -586,8 +585,8 @@ nouveau_fbcon_init(struct drm_device *dev)
if (ret)
goto fini;
- if (fbcon->helper.fbdev)
- fbcon->helper.fbdev->pixmap.buf_align = 4;
+ if (fbcon->helper.info)
+ fbcon->helper.info->pixmap.buf_align = 4;
return 0;
fini:
diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h
deleted file mode 100644
index 1796d8824580..000000000000
--- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2008 Maarten Maathuis.
- * All Rights Reserved.
- *
- * 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 (including the
- * next paragraph) 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 OWNER(S) AND/OR ITS SUPPLIERS 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 __NOUVEAU_FBCON_H__
-#define __NOUVEAU_FBCON_H__
-
-#include <drm/drm_fb_helper.h>
-
-#include "nouveau_display.h"
-
-struct nouveau_vma;
-
-struct nouveau_fbdev {
- struct drm_fb_helper helper; /* must be first */
- unsigned int saved_flags;
- struct nvif_object surf2d;
- struct nvif_object clip;
- struct nvif_object rop;
- struct nvif_object patt;
- struct nvif_object gdi;
- struct nvif_object blit;
- struct nvif_object twod;
- struct nouveau_vma *vma;
-
- struct mutex hotplug_lock;
- bool hotplug_waiting;
-};
-
-void nouveau_fbcon_restore(void);
-
-int nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region);
-int nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
-int nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image);
-int nv04_fbcon_accel_init(struct fb_info *info);
-
-int nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
-int nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region);
-int nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image);
-int nv50_fbcon_accel_init(struct fb_info *info);
-
-int nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
-int nvc0_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region);
-int nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image);
-int nvc0_fbcon_accel_init(struct fb_info *info);
-
-void nouveau_fbcon_gpu_lockup(struct fb_info *info);
-
-int nouveau_fbcon_init(struct drm_device *dev);
-void nouveau_fbcon_fini(struct drm_device *dev);
-void nouveau_fbcon_set_suspend(struct drm_device *dev, int state);
-void nouveau_fbcon_accel_save_disable(struct drm_device *dev);
-void nouveau_fbcon_accel_restore(struct drm_device *dev);
-
-void nouveau_fbcon_output_poll_changed(struct drm_device *dev);
-void nouveau_fbcon_hotplug_resume(struct nouveau_fbdev *fbcon);
-extern int nouveau_nofbaccel;
-
-#endif /* __NV50_FBCON_H__ */
-
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c
index abcac7db4347..ee5e9d40c166 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.c
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.c
@@ -29,9 +29,7 @@
#include <linux/sched/signal.h>
#include <trace/events/dma_fence.h>
-#include <nvif/cl826e.h>
-#include <nvif/notify.h>
-#include <nvif/event.h>
+#include <nvif/if0020.h>
#include "nouveau_drv.h"
#include "nouveau_dma.h"
@@ -79,10 +77,6 @@ nouveau_local_fence(struct dma_fence *fence, struct nouveau_drm *drm)
fence->ops != &nouveau_fence_ops_uevent)
return NULL;
- if (fence->context < drm->chan.context_base ||
- fence->context >= drm->chan.context_base + drm->chan.nr)
- return NULL;
-
return from_fence(fence);
}
@@ -90,8 +84,9 @@ void
nouveau_fence_context_kill(struct nouveau_fence_chan *fctx, int error)
{
struct nouveau_fence *fence;
+ unsigned long flags;
- spin_lock_irq(&fctx->lock);
+ spin_lock_irqsave(&fctx->lock, flags);
while (!list_empty(&fctx->pending)) {
fence = list_entry(fctx->pending.next, typeof(*fence), head);
@@ -99,16 +94,16 @@ nouveau_fence_context_kill(struct nouveau_fence_chan *fctx, int error)
dma_fence_set_error(&fence->base, error);
if (nouveau_fence_signal(fence))
- nvif_notify_put(&fctx->notify);
+ nvif_event_block(&fctx->event);
}
- spin_unlock_irq(&fctx->lock);
+ spin_unlock_irqrestore(&fctx->lock, flags);
}
void
nouveau_fence_context_del(struct nouveau_fence_chan *fctx)
{
nouveau_fence_context_kill(fctx, 0);
- nvif_notify_dtor(&fctx->notify);
+ nvif_event_dtor(&fctx->event);
fctx->dead = 1;
/*
@@ -150,12 +145,11 @@ nouveau_fence_update(struct nouveau_channel *chan, struct nouveau_fence_chan *fc
}
static int
-nouveau_fence_wait_uevent_handler(struct nvif_notify *notify)
+nouveau_fence_wait_uevent_handler(struct nvif_event *event, void *repv, u32 repc)
{
- struct nouveau_fence_chan *fctx =
- container_of(notify, typeof(*fctx), notify);
+ struct nouveau_fence_chan *fctx = container_of(event, typeof(*fctx), event);
unsigned long flags;
- int ret = NVIF_NOTIFY_KEEP;
+ int ret = NVIF_EVENT_KEEP;
spin_lock_irqsave(&fctx->lock, flags);
if (!list_empty(&fctx->pending)) {
@@ -165,7 +159,7 @@ nouveau_fence_wait_uevent_handler(struct nvif_notify *notify)
fence = list_entry(fctx->pending.next, typeof(*fence), head);
chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock));
if (nouveau_fence_update(chan, fctx))
- ret = NVIF_NOTIFY_DROP;
+ ret = NVIF_EVENT_DROP;
}
spin_unlock_irqrestore(&fctx->lock, flags);
@@ -177,12 +171,16 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha
{
struct nouveau_fence_priv *priv = (void*)chan->drm->fence;
struct nouveau_cli *cli = (void *)chan->user.client;
+ struct {
+ struct nvif_event_v0 base;
+ struct nvif_chan_event_v0 host;
+ } args;
int ret;
INIT_LIST_HEAD(&fctx->flip);
INIT_LIST_HEAD(&fctx->pending);
spin_lock_init(&fctx->lock);
- fctx->context = chan->drm->chan.context_base + chan->chid;
+ fctx->context = chan->drm->runl[chan->runlist].context_base + chan->chid;
if (chan == chan->drm->cechan)
strcpy(fctx->name, "copy engine channel");
@@ -195,13 +193,12 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha
if (!priv->uevent)
return;
- ret = nvif_notify_ctor(&chan->user, "fenceNonStallIntr",
- nouveau_fence_wait_uevent_handler,
- false, NV826E_V0_NTFY_NON_STALL_INTERRUPT,
- &(struct nvif_notify_uevent_req) { },
- sizeof(struct nvif_notify_uevent_req),
- sizeof(struct nvif_notify_uevent_rep),
- &fctx->notify);
+ args.host.version = 0;
+ args.host.type = NVIF_CHAN_EVENT_V0_NON_STALL_INTR;
+
+ ret = nvif_event_ctor(&chan->user, "fenceNonStallIntr", (chan->runlist << 16) | chan->chid,
+ nouveau_fence_wait_uevent_handler, false,
+ &args.base, sizeof(args), &fctx->event);
WARN_ON(ret);
}
@@ -230,7 +227,7 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan)
spin_lock_irq(&fctx->lock);
if (nouveau_fence_update(chan, fctx))
- nvif_notify_put(&fctx->notify);
+ nvif_event_block(&fctx->event);
list_add_tail(&fence->head, &fctx->pending);
spin_unlock_irq(&fctx->lock);
@@ -254,7 +251,7 @@ nouveau_fence_done(struct nouveau_fence *fence)
spin_lock_irqsave(&fctx->lock, flags);
chan = rcu_dereference_protected(fence->channel, lockdep_is_held(&fctx->lock));
if (chan && nouveau_fence_update(chan, fctx))
- nvif_notify_put(&fctx->notify);
+ nvif_event_block(&fctx->event);
spin_unlock_irqrestore(&fctx->lock, flags);
}
return dma_fence_is_signaled(&fence->base);
@@ -505,13 +502,13 @@ static bool nouveau_fence_enable_signaling(struct dma_fence *f)
bool ret;
if (!fctx->notify_ref++)
- nvif_notify_get(&fctx->notify);
+ nvif_event_allow(&fctx->event);
ret = nouveau_fence_no_signaling(f);
if (ret)
set_bit(DMA_FENCE_FLAG_USER_BITS, &fence->base.flags);
else if (!--fctx->notify_ref)
- nvif_notify_put(&fctx->notify);
+ nvif_event_block(&fctx->event);
return ret;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h
index 4887caa69c65..0ca2bc85adf6 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.h
@@ -3,7 +3,7 @@
#define __NOUVEAU_FENCE_H__
#include <linux/dma-fence.h>
-#include <nvif/notify.h>
+#include <nvif/event.h>
struct nouveau_drm;
struct nouveau_bo;
@@ -44,7 +44,7 @@ struct nouveau_fence_chan {
u32 context;
char name[32];
- struct nvif_notify notify;
+ struct nvif_event event;
int notify_ref, dead;
};
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c
index fab542a758ff..ac5793c96957 100644
--- a/drivers/gpu/drm/nouveau/nouveau_gem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_gem.c
@@ -679,7 +679,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli,
}
if (!nvbo->kmap.virtual) {
- ret = ttm_bo_kmap(&nvbo->bo, 0, nvbo->bo.resource->num_pages,
+ ret = ttm_bo_kmap(&nvbo->bo, 0, PFN_UP(nvbo->bo.base.size),
&nvbo->kmap);
if (ret) {
NV_PRINTK(err, cli, "failed kmap for reloc\n");
@@ -868,8 +868,7 @@ revalidate:
if (unlikely(cmd != req->suffix0)) {
if (!nvbo->kmap.virtual) {
ret = ttm_bo_kmap(&nvbo->bo, 0,
- nvbo->bo.resource->
- num_pages,
+ PFN_UP(nvbo->bo.base.size),
&nvbo->kmap);
if (ret) {
WIND_RING(chan);
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c
index 76f8edefa637..1fde3a5d7c32 100644
--- a/drivers/gpu/drm/nouveau/nouveau_mem.c
+++ b/drivers/gpu/drm/nouveau/nouveau_mem.c
@@ -115,7 +115,7 @@ nouveau_mem_host(struct ttm_resource *reg, struct ttm_tt *tt)
mutex_lock(&drm->master.lock);
ret = nvif_mem_ctor_type(mmu, "ttmHostMem", cli->mem->oclass, type, PAGE_SHIFT,
- reg->num_pages << PAGE_SHIFT,
+ reg->size,
&args, sizeof(args), &mem->mem);
mutex_unlock(&drm->master.lock);
return ret;
@@ -128,7 +128,7 @@ nouveau_mem_vram(struct ttm_resource *reg, bool contig, u8 page)
struct nouveau_cli *cli = mem->cli;
struct nouveau_drm *drm = cli->drm;
struct nvif_mmu *mmu = &cli->mmu;
- u64 size = ALIGN(reg->num_pages << PAGE_SHIFT, 1 << page);
+ u64 size = ALIGN(reg->size, 1 << page);
int ret;
mutex_lock(&drm->master.lock);
diff --git a/drivers/gpu/drm/nouveau/nouveau_nvif.c b/drivers/gpu/drm/nouveau/nouveau_nvif.c
index df0fe58ca3ab..1d49ebdfd5dc 100644
--- a/drivers/gpu/drm/nouveau/nouveau_nvif.c
+++ b/drivers/gpu/drm/nouveau/nouveau_nvif.c
@@ -27,12 +27,10 @@
******************************************************************************/
#include <core/client.h>
-#include <core/notify.h>
#include <core/ioctl.h>
#include <nvif/client.h>
#include <nvif/driver.h>
-#include <nvif/notify.h>
#include <nvif/event.h>
#include <nvif/ioctl.h>
@@ -72,10 +70,23 @@ nvkm_client_suspend(void *priv)
}
static int
+nvkm_client_event(u64 token, void *repv, u32 repc)
+{
+ struct nvif_object *object = (void *)(unsigned long)token;
+ struct nvif_event *event = container_of(object, typeof(*event), object);
+
+ if (event->func(event, repv, repc) == NVIF_EVENT_KEEP)
+ return NVKM_EVENT_KEEP;
+
+ return NVKM_EVENT_DROP;
+}
+
+static int
nvkm_client_driver_init(const char *name, u64 device, const char *cfg,
const char *dbg, void **ppriv)
{
- return nvkm_client_new(name, device, cfg, dbg, nvif_notify, (struct nvkm_client **)ppriv);
+ return nvkm_client_new(name, device, cfg, dbg, nvkm_client_event,
+ (struct nvkm_client **)ppriv);
}
const struct nvif_driver
diff --git a/drivers/gpu/drm/nouveau/nouveau_svm.c b/drivers/gpu/drm/nouveau/nouveau_svm.c
index 31a5b81ee9fc..a74ba8d84ba7 100644
--- a/drivers/gpu/drm/nouveau/nouveau_svm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_svm.c
@@ -24,7 +24,7 @@
#include "nouveau_chan.h"
#include "nouveau_dmem.h"
-#include <nvif/notify.h>
+#include <nvif/event.h>
#include <nvif/object.h>
#include <nvif/vmm.h>
@@ -51,7 +51,8 @@ struct nouveau_svm {
u32 putaddr;
u32 get;
u32 put;
- struct nvif_notify notify;
+ struct nvif_event notify;
+ struct work_struct work;
struct nouveau_svm_fault {
u64 inst;
@@ -711,13 +712,11 @@ out:
return ret;
}
-static int
-nouveau_svm_fault(struct nvif_notify *notify)
+static void
+nouveau_svm_fault(struct work_struct *work)
{
- struct nouveau_svm_fault_buffer *buffer =
- container_of(notify, typeof(*buffer), notify);
- struct nouveau_svm *svm =
- container_of(buffer, typeof(*svm), buffer[buffer->id]);
+ struct nouveau_svm_fault_buffer *buffer = container_of(work, typeof(*buffer), work);
+ struct nouveau_svm *svm = container_of(buffer, typeof(*svm), buffer[buffer->id]);
struct nvif_object *device = &svm->drm->client.device.object;
struct nouveau_svmm *svmm;
struct {
@@ -737,7 +736,7 @@ nouveau_svm_fault(struct nvif_notify *notify)
buffer->put = nvif_rd32(device, buffer->putaddr);
buffer->get = nvif_rd32(device, buffer->getaddr);
if (buffer->get == buffer->put)
- return NVIF_NOTIFY_KEEP;
+ return;
}
buffer->fault_nr = 0;
@@ -881,7 +880,15 @@ nouveau_svm_fault(struct nvif_notify *notify)
/* Issue fault replay to the GPU. */
if (replay)
nouveau_svm_fault_replay(svm);
- return NVIF_NOTIFY_KEEP;
+}
+
+static int
+nouveau_svm_event(struct nvif_event *event, void *argv, u32 argc)
+{
+ struct nouveau_svm_fault_buffer *buffer = container_of(event, typeof(*buffer), notify);
+
+ schedule_work(&buffer->work);
+ return NVIF_EVENT_KEEP;
}
static struct nouveau_pfnmap_args *
@@ -936,7 +943,9 @@ static void
nouveau_svm_fault_buffer_fini(struct nouveau_svm *svm, int id)
{
struct nouveau_svm_fault_buffer *buffer = &svm->buffer[id];
- nvif_notify_put(&buffer->notify);
+
+ nvif_event_block(&buffer->notify);
+ flush_work(&buffer->work);
}
static int
@@ -944,10 +953,12 @@ nouveau_svm_fault_buffer_init(struct nouveau_svm *svm, int id)
{
struct nouveau_svm_fault_buffer *buffer = &svm->buffer[id];
struct nvif_object *device = &svm->drm->client.device.object;
+
buffer->get = nvif_rd32(device, buffer->getaddr);
buffer->put = nvif_rd32(device, buffer->putaddr);
SVM_DBG(svm, "get %08x put %08x (init)", buffer->get, buffer->put);
- return nvif_notify_get(&buffer->notify);
+
+ return nvif_event_allow(&buffer->notify);
}
static void
@@ -956,15 +967,18 @@ nouveau_svm_fault_buffer_dtor(struct nouveau_svm *svm, int id)
struct nouveau_svm_fault_buffer *buffer = &svm->buffer[id];
int i;
+ if (!nvif_object_constructed(&buffer->object))
+ return;
+
+ nouveau_svm_fault_buffer_fini(svm, id);
+
if (buffer->fault) {
for (i = 0; buffer->fault[i] && i < buffer->entries; i++)
kfree(buffer->fault[i]);
kvfree(buffer->fault);
}
- nouveau_svm_fault_buffer_fini(svm, id);
-
- nvif_notify_dtor(&buffer->notify);
+ nvif_event_dtor(&buffer->notify);
nvif_object_dtor(&buffer->object);
}
@@ -990,10 +1004,10 @@ nouveau_svm_fault_buffer_ctor(struct nouveau_svm *svm, s32 oclass, int id)
buffer->entries = args.entries;
buffer->getaddr = args.get;
buffer->putaddr = args.put;
+ INIT_WORK(&buffer->work, nouveau_svm_fault);
- ret = nvif_notify_ctor(&buffer->object, "svmFault", nouveau_svm_fault,
- true, NVB069_V0_NTFY_FAULT, NULL, 0, 0,
- &buffer->notify);
+ ret = nvif_event_ctor(&buffer->object, "svmFault", id, nouveau_svm_event, true, NULL, 0,
+ &buffer->notify);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c
index 9602c30928f2..1469a88910e4 100644
--- a/drivers/gpu/drm/nouveau/nouveau_ttm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c
@@ -139,7 +139,7 @@ nv04_gart_manager_new(struct ttm_resource_manager *man,
mem = nouveau_mem(*res);
ttm_resource_init(bo, place, *res);
ret = nvif_vmm_get(&mem->cli->vmm.vmm, PTES, false, 12, 0,
- (long)(*res)->num_pages << PAGE_SHIFT, &mem->vma[0]);
+ (long)(*res)->size, &mem->vma[0]);
if (ret) {
nouveau_mem_del(man, *res);
return ret;
diff --git a/drivers/gpu/drm/nouveau/nouveau_usif.c b/drivers/gpu/drm/nouveau/nouveau_usif.c
index 36df6840c099..002d1479ba89 100644
--- a/drivers/gpu/drm/nouveau/nouveau_usif.c
+++ b/drivers/gpu/drm/nouveau/nouveau_usif.c
@@ -151,12 +151,6 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
case NVIF_IOCTL_V0_NEW:
ret = usif_object_new(filp, data, size, argv, argc, abi16);
break;
- case NVIF_IOCTL_V0_NTFY_NEW:
- case NVIF_IOCTL_V0_NTFY_DEL:
- case NVIF_IOCTL_V0_NTFY_GET:
- case NVIF_IOCTL_V0_NTFY_PUT:
- ret = -ENOSYS;
- break;
default:
ret = nvif_client_ioctl(client, argv, argc);
break;
diff --git a/drivers/gpu/drm/nouveau/nouveau_vga.c b/drivers/gpu/drm/nouveau/nouveau_vga.c
index 60cd8c0463df..789393b94291 100644
--- a/drivers/gpu/drm/nouveau/nouveau_vga.c
+++ b/drivers/gpu/drm/nouveau/nouveau_vga.c
@@ -7,7 +7,6 @@
#include "nouveau_drv.h"
#include "nouveau_acpi.h"
-#include "nouveau_fbcon.h"
#include "nouveau_vga.h"
static unsigned int
diff --git a/drivers/gpu/drm/nouveau/nv04_fbcon.c b/drivers/gpu/drm/nouveau/nv04_fbcon.c
deleted file mode 100644
index 92f3fb6765ab..000000000000
--- a/drivers/gpu/drm/nouveau/nv04_fbcon.c
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
- * Copyright 2009 Ben Skeggs
- * Copyright 2008 Stuart Bennett
- *
- * 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 (including the next
- * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
- */
-#define NVIF_DEBUG_PRINT_DISABLE
-#include "nouveau_drv.h"
-#include "nouveau_dma.h"
-#include "nouveau_fbcon.h"
-
-#include <nvif/push006c.h>
-
-int
-nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
-{
- struct nouveau_fbdev *nfbdev = info->par;
- struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
- struct nouveau_channel *chan = drm->channel;
- struct nvif_push *push = chan->chan.push;
- int ret;
-
- ret = PUSH_WAIT(push, 4);
- if (ret)
- return ret;
-
- PUSH_NVSQ(push, NV05F, 0x0300, (region->sy << 16) | region->sx,
- 0x0304, (region->dy << 16) | region->dx,
- 0x0308, (region->height << 16) | region->width);
- PUSH_KICK(push);
- return 0;
-}
-
-int
-nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
- struct nouveau_fbdev *nfbdev = info->par;
- struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
- struct nouveau_channel *chan = drm->channel;
- struct nvif_push *push = chan->chan.push;
- int ret;
-
- ret = PUSH_WAIT(push, 7);
- if (ret)
- return ret;
-
- PUSH_NVSQ(push, NV04A, 0x02fc, (rect->rop != ROP_COPY) ? 1 : 3);
- if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
- info->fix.visual == FB_VISUAL_DIRECTCOLOR)
- PUSH_NVSQ(push, NV04A, 0x03fc, ((uint32_t *)info->pseudo_palette)[rect->color]);
- else
- PUSH_NVSQ(push, NV04A, 0x03fc, rect->color);
- PUSH_NVSQ(push, NV04A, 0x0400, (rect->dx << 16) | rect->dy,
- 0x0404, (rect->width << 16) | rect->height);
- PUSH_KICK(push);
- return 0;
-}
-
-int
-nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
-{
- struct nouveau_fbdev *nfbdev = info->par;
- struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
- struct nouveau_channel *chan = drm->channel;
- struct nvif_push *push = chan->chan.push;
- uint32_t fg;
- uint32_t bg;
- uint32_t dsize;
- uint32_t *data = (uint32_t *)image->data;
- int ret;
-
- if (image->depth != 1)
- return -ENODEV;
-
- ret = PUSH_WAIT(push, 8);
- if (ret)
- return ret;
-
- if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
- info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
- fg = ((uint32_t *) info->pseudo_palette)[image->fg_color];
- bg = ((uint32_t *) info->pseudo_palette)[image->bg_color];
- } else {
- fg = image->fg_color;
- bg = image->bg_color;
- }
-
- PUSH_NVSQ(push, NV04A, 0x0be4, (image->dy << 16) | (image->dx & 0xffff),
- 0x0be8, ((image->dy + image->height) << 16) |
- ((image->dx + image->width) & 0xffff),
- 0x0bec, bg,
- 0x0bf0, fg,
- 0x0bf4, (image->height << 16) | ALIGN(image->width, 8),
- 0x0bf8, (image->height << 16) | image->width,
- 0x0bfc, (image->dy << 16) | (image->dx & 0xffff));
-
- dsize = ALIGN(ALIGN(image->width, 8) * image->height, 32) >> 5;
- while (dsize) {
- int iter_len = dsize > 128 ? 128 : dsize;
-
- ret = PUSH_WAIT(push, iter_len + 1);
- if (ret)
- return ret;
-
- PUSH_NVSQ(push, NV04A, 0x0c00, data, iter_len);
- data += iter_len;
- dsize -= iter_len;
- }
-
- PUSH_KICK(push);
- return 0;
-}
-
-int
-nv04_fbcon_accel_init(struct fb_info *info)
-{
- struct nouveau_fbdev *nfbdev = info->par;
- struct drm_device *dev = nfbdev->helper.dev;
- struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_channel *chan = drm->channel;
- struct nvif_device *device = &drm->client.device;
- struct nvif_push *push = chan->chan.push;
- int surface_fmt, pattern_fmt, rect_fmt;
- int ret;
-
- switch (info->var.bits_per_pixel) {
- case 8:
- surface_fmt = 1;
- pattern_fmt = 3;
- rect_fmt = 3;
- break;
- case 16:
- surface_fmt = 4;
- pattern_fmt = 1;
- rect_fmt = 1;
- break;
- case 32:
- switch (info->var.transp.length) {
- case 0: /* depth 24 */
- case 8: /* depth 32 */
- break;
- default:
- return -EINVAL;
- }
-
- surface_fmt = 6;
- pattern_fmt = 3;
- rect_fmt = 3;
- break;
- default:
- return -EINVAL;
- }
-
- ret = nvif_object_ctor(&chan->user, "fbconCtxSurf2d", 0x0062,
- device->info.family >= NV_DEVICE_INFO_V0_CELSIUS ?
- 0x0062 : 0x0042, NULL, 0, &nfbdev->surf2d);
- if (ret)
- return ret;
-
- ret = nvif_object_ctor(&chan->user, "fbconCtxClip", 0x0019, 0x0019,
- NULL, 0, &nfbdev->clip);
- if (ret)
- return ret;
-
- ret = nvif_object_ctor(&chan->user, "fbconCtxRop", 0x0043, 0x0043,
- NULL, 0, &nfbdev->rop);
- if (ret)
- return ret;
-
- ret = nvif_object_ctor(&chan->user, "fbconCtxPatt", 0x0044, 0x0044,
- NULL, 0, &nfbdev->patt);
- if (ret)
- return ret;
-
- ret = nvif_object_ctor(&chan->user, "fbconGdiRectText", 0x004a, 0x004a,
- NULL, 0, &nfbdev->gdi);
- if (ret)
- return ret;
-
- ret = nvif_object_ctor(&chan->user, "fbconImageBlit", 0x005f,
- device->info.chipset >= 0x11 ? 0x009f : 0x005f,
- NULL, 0, &nfbdev->blit);
- if (ret)
- return ret;
-
- if (PUSH_WAIT(push, 49 + (device->info.chipset >= 0x11 ? 4 : 0))) {
- nouveau_fbcon_gpu_lockup(info);
- return 0;
- }
-
- PUSH_NVSQ(push, NV042, 0x0000, nfbdev->surf2d.handle);
- PUSH_NVSQ(push, NV042, 0x0184, chan->vram.handle,
- 0x0188, chan->vram.handle);
- PUSH_NVSQ(push, NV042, 0x0300, surface_fmt,
- 0x0304, info->fix.line_length | (info->fix.line_length << 16),
- 0x0308, info->fix.smem_start - dev->mode_config.fb_base,
- 0x030c, info->fix.smem_start - dev->mode_config.fb_base);
-
- PUSH_NVSQ(push, NV043, 0x0000, nfbdev->rop.handle);
- PUSH_NVSQ(push, NV043, 0x0300, 0x55);
-
- PUSH_NVSQ(push, NV044, 0x0000, nfbdev->patt.handle);
- PUSH_NVSQ(push, NV044, 0x0300, pattern_fmt,
-#ifdef __BIG_ENDIAN
- 0x0304, 2,
-#else
- 0x0304, 1,
-#endif
- 0x0308, 0,
- 0x030c, 1,
- 0x0310, ~0,
- 0x0314, ~0,
- 0x0318, ~0,
- 0x031c, ~0);
-
- PUSH_NVSQ(push, NV019, 0x0000, nfbdev->clip.handle);
- PUSH_NVSQ(push, NV019, 0x0300, 0,
- 0x0304, (info->var.yres_virtual << 16) | info->var.xres_virtual);
-
- PUSH_NVSQ(push, NV05F, 0x0000, nfbdev->blit.handle);
- PUSH_NVSQ(push, NV05F, 0x019c, nfbdev->surf2d.handle);
- PUSH_NVSQ(push, NV05F, 0x02fc, 3);
- if (nfbdev->blit.oclass == 0x009f) {
- PUSH_NVSQ(push, NV09F, 0x0120, 0,
- 0x0124, 1,
- 0x0128, 2);
- }
-
- PUSH_NVSQ(push, NV04A, 0x0000, nfbdev->gdi.handle);
- PUSH_NVSQ(push, NV04A, 0x0198, nfbdev->surf2d.handle);
- PUSH_NVSQ(push, NV04A, 0x0188, nfbdev->patt.handle,
- 0x018c, nfbdev->rop.handle);
- PUSH_NVSQ(push, NV04A, 0x0304, 1);
- PUSH_NVSQ(push, NV04A, 0x0300, rect_fmt);
- PUSH_NVSQ(push, NV04A, 0x02fc, 3);
-
- PUSH_KICK(push);
- return 0;
-}
-
diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c
deleted file mode 100644
index 71f92e4750f9..000000000000
--- a/drivers/gpu/drm/nouveau/nv50_fbcon.c
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright 2010 Red Hat 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: Ben Skeggs
- */
-#define NVIF_DEBUG_PRINT_DISABLE
-#include "nouveau_drv.h"
-#include "nouveau_dma.h"
-#include "nouveau_fbcon.h"
-#include "nouveau_vmm.h"
-
-#include <nvif/push206e.h>
-
-#include <nvhw/class/cl502d.h>
-
-int
-nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
- struct nouveau_fbdev *nfbdev = info->par;
- struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
- struct nouveau_channel *chan = drm->channel;
- struct nvif_push *push = chan->chan.push;
- u32 colour;
- int ret;
-
- if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
- info->fix.visual == FB_VISUAL_DIRECTCOLOR)
- colour = ((uint32_t *)info->pseudo_palette)[rect->color];
- else
- colour = rect->color;
-
- ret = PUSH_WAIT(push, rect->rop == ROP_COPY ? 7 : 11);
- if (ret)
- return ret;
-
- if (rect->rop != ROP_COPY) {
- PUSH_MTHD(push, NV502D, SET_OPERATION,
- NVDEF(NV502D, SET_OPERATION, V, ROP_AND));
- }
-
- PUSH_MTHD(push, NV502D, SET_RENDER_SOLID_PRIM_COLOR, colour);
-
- PUSH_MTHD(push, NV502D, RENDER_SOLID_PRIM_POINT_SET_X(0), rect->dx,
- RENDER_SOLID_PRIM_POINT_Y(0), rect->dy,
- RENDER_SOLID_PRIM_POINT_SET_X(1), rect->dx + rect->width,
- RENDER_SOLID_PRIM_POINT_Y(1), rect->dy + rect->height);
-
- if (rect->rop != ROP_COPY) {
- PUSH_MTHD(push, NV502D, SET_OPERATION,
- NVDEF(NV502D, SET_OPERATION, V, SRCCOPY));
- }
-
- PUSH_KICK(push);
- return 0;
-}
-
-int
-nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
-{
- struct nouveau_fbdev *nfbdev = info->par;
- struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
- struct nouveau_channel *chan = drm->channel;
- struct nvif_push *push = chan->chan.push;
- int ret;
-
- ret = PUSH_WAIT(push, 12);
- if (ret)
- return ret;
-
- PUSH_MTHD(push, NV502D, WAIT_FOR_IDLE, 0);
-
- PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_MEMORY_DST_X0, region->dx,
- SET_PIXELS_FROM_MEMORY_DST_Y0, region->dy,
- SET_PIXELS_FROM_MEMORY_DST_WIDTH, region->width,
- SET_PIXELS_FROM_MEMORY_DST_HEIGHT, region->height);
-
- PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_MEMORY_SRC_X0_FRAC, 0,
- SET_PIXELS_FROM_MEMORY_SRC_X0_INT, region->sx,
- SET_PIXELS_FROM_MEMORY_SRC_Y0_FRAC, 0,
- PIXELS_FROM_MEMORY_SRC_Y0_INT, region->sy);
- PUSH_KICK(push);
- return 0;
-}
-
-int
-nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
-{
- struct nouveau_fbdev *nfbdev = info->par;
- struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
- struct nouveau_channel *chan = drm->channel;
- struct nvif_push *push = chan->chan.push;
- uint32_t dwords, *data = (uint32_t *)image->data;
- uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
- uint32_t *palette = info->pseudo_palette, bg, fg;
- int ret;
-
- if (image->depth != 1)
- return -ENODEV;
-
- if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
- info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
- bg = palette[image->bg_color] | mask;
- fg = palette[image->fg_color] | mask;
- } else {
- bg = image->bg_color;
- fg = image->fg_color;
- }
-
- ret = PUSH_WAIT(push, 11);
- if (ret)
- return ret;
-
- PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_CPU_COLOR0, bg,
- SET_PIXELS_FROM_CPU_COLOR1, fg);
-
- PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_CPU_SRC_WIDTH, image->width,
- SET_PIXELS_FROM_CPU_SRC_HEIGHT, image->height);
-
- PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_CPU_DST_X0_FRAC, 0,
- SET_PIXELS_FROM_CPU_DST_X0_INT, image->dx,
- SET_PIXELS_FROM_CPU_DST_Y0_FRAC, 0,
- SET_PIXELS_FROM_CPU_DST_Y0_INT, image->dy);
-
- dwords = ALIGN(ALIGN(image->width, 8) * image->height, 32) >> 5;
- while (dwords) {
- int count = dwords > 2047 ? 2047 : dwords;
-
- ret = PUSH_WAIT(push, count + 1);
- if (ret)
- return ret;
-
- dwords -= count;
-
- PUSH_NINC(push, NV502D, PIXELS_FROM_CPU_DATA, data, count);
- data += count;
- }
-
- PUSH_KICK(push);
- return 0;
-}
-
-int
-nv50_fbcon_accel_init(struct fb_info *info)
-{
- struct nouveau_fbdev *nfbdev = info->par;
- struct drm_device *dev = nfbdev->helper.dev;
- struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_channel *chan = drm->channel;
- struct nvif_push *push = chan->chan.push;
- int ret, format;
-
- switch (info->var.bits_per_pixel) {
- case 8:
- format = NV502D_SET_DST_FORMAT_V_Y8;
- break;
- case 15:
- format = NV502D_SET_DST_FORMAT_V_X1R5G5B5;
- break;
- case 16:
- format = NV502D_SET_DST_FORMAT_V_R5G6B5;
- break;
- case 32:
- switch (info->var.transp.length) {
- case 0: /* depth 24 */
- case 8: /* depth 32, just use 24.. */
- format = NV502D_SET_DST_FORMAT_V_X8R8G8B8;
- break;
- case 2: /* depth 30 */
- format = NV502D_SET_DST_FORMAT_V_A2B10G10R10;
- break;
- default:
- return -EINVAL;
- }
- break;
- default:
- return -EINVAL;
- }
-
- ret = nvif_object_ctor(&chan->user, "fbconTwoD", 0x502d, 0x502d,
- NULL, 0, &nfbdev->twod);
- if (ret)
- return ret;
-
- ret = PUSH_WAIT(push, 56);
- if (ret) {
- nouveau_fbcon_gpu_lockup(info);
- return ret;
- }
-
- PUSH_MTHD(push, NV502D, SET_OBJECT, nfbdev->twod.handle);
- PUSH_MTHD(push, NV502D, SET_DST_CONTEXT_DMA, chan->vram.handle,
- SET_SRC_CONTEXT_DMA, chan->vram.handle,
- SET_SEMAPHORE_CONTEXT_DMA, chan->vram.handle);
-
- PUSH_MTHD(push, NV502D, SET_DST_FORMAT,
- NVVAL(NV502D, SET_DST_FORMAT, V, format),
-
- SET_DST_MEMORY_LAYOUT,
- NVDEF(NV502D, SET_DST_MEMORY_LAYOUT, V, PITCH));
-
- PUSH_MTHD(push, NV502D, SET_DST_PITCH, info->fix.line_length,
- SET_DST_WIDTH, info->var.xres_virtual,
- SET_DST_HEIGHT, info->var.yres_virtual,
-
- SET_DST_OFFSET_UPPER,
- NVVAL(NV502D, SET_DST_OFFSET_UPPER, V, upper_32_bits(nfbdev->vma->addr)),
-
- SET_DST_OFFSET_LOWER,
- NVVAL(NV502D, SET_DST_OFFSET_LOWER, V, lower_32_bits(nfbdev->vma->addr)));
-
- PUSH_MTHD(push, NV502D, SET_SRC_FORMAT,
- NVVAL(NV502D, SET_SRC_FORMAT, V, format),
-
- SET_SRC_MEMORY_LAYOUT,
- NVDEF(NV502D, SET_SRC_MEMORY_LAYOUT, V, PITCH));
-
- PUSH_MTHD(push, NV502D, SET_SRC_PITCH, info->fix.line_length,
- SET_SRC_WIDTH, info->var.xres_virtual,
- SET_SRC_HEIGHT, info->var.yres_virtual,
-
- SET_SRC_OFFSET_UPPER,
- NVVAL(NV502D, SET_SRC_OFFSET_UPPER, V, upper_32_bits(nfbdev->vma->addr)),
-
- SET_SRC_OFFSET_LOWER,
- NVVAL(NV502D, SET_SRC_OFFSET_LOWER, V, lower_32_bits(nfbdev->vma->addr)));
-
- PUSH_MTHD(push, NV502D, SET_CLIP_ENABLE,
- NVDEF(NV502D, SET_CLIP_ENABLE, V, FALSE));
-
- PUSH_MTHD(push, NV502D, SET_ROP,
- NVVAL(NV502D, SET_ROP, V, 0x55));
-
- PUSH_MTHD(push, NV502D, SET_OPERATION,
- NVDEF(NV502D, SET_OPERATION, V, SRCCOPY));
-
- PUSH_MTHD(push, NV502D, SET_MONOCHROME_PATTERN_COLOR_FORMAT,
- NVDEF(NV502D, SET_MONOCHROME_PATTERN_COLOR_FORMAT, V, A8R8G8B8),
-
- SET_MONOCHROME_PATTERN_FORMAT,
- NVDEF(NV502D, SET_MONOCHROME_PATTERN_FORMAT, V, LE_M1));
-
- PUSH_MTHD(push, NV502D, RENDER_SOLID_PRIM_MODE,
- NVDEF(NV502D, RENDER_SOLID_PRIM_MODE, V, RECTS),
-
- SET_RENDER_SOLID_PRIM_COLOR_FORMAT,
- NVVAL(NV502D, SET_RENDER_SOLID_PRIM_COLOR_FORMAT, V, format));
-
- PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_CPU_DATA_TYPE,
- NVDEF(NV502D, SET_PIXELS_FROM_CPU_DATA_TYPE, V, INDEX),
-
- SET_PIXELS_FROM_CPU_COLOR_FORMAT,
- NVVAL(NV502D, SET_PIXELS_FROM_CPU_COLOR_FORMAT, V, format),
-
- SET_PIXELS_FROM_CPU_INDEX_FORMAT,
- NVDEF(NV502D, SET_PIXELS_FROM_CPU_INDEX_FORMAT, V, I1),
-
- SET_PIXELS_FROM_CPU_MONO_FORMAT,
- NVDEF(NV502D, SET_PIXELS_FROM_CPU_MONO_FORMAT, V, CGA6_M1),
-
- SET_PIXELS_FROM_CPU_WRAP,
- NVDEF(NV502D, SET_PIXELS_FROM_CPU_WRAP, V, WRAP_BYTE));
-
- PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_CPU_MONO_OPACITY,
- NVDEF(NV502D, SET_PIXELS_FROM_CPU_MONO_OPACITY, V, OPAQUE));
-
- PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_CPU_DX_DU_FRAC, 0,
- SET_PIXELS_FROM_CPU_DX_DU_INT, 1,
- SET_PIXELS_FROM_CPU_DY_DV_FRAC, 0,
- SET_PIXELS_FROM_CPU_DY_DV_INT, 1);
-
- PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_MEMORY_SAFE_OVERLAP,
- NVDEF(NV502D, SET_PIXELS_FROM_MEMORY_SAFE_OVERLAP, V, TRUE));
-
- PUSH_MTHD(push, NV502D, SET_PIXELS_FROM_MEMORY_DU_DX_FRAC, 0,
- SET_PIXELS_FROM_MEMORY_DU_DX_INT, 1,
- SET_PIXELS_FROM_MEMORY_DV_DY_FRAC, 0,
- SET_PIXELS_FROM_MEMORY_DV_DY_INT, 1);
- PUSH_KICK(push);
- return 0;
-}
-
diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c
index c3526a8622e3..812b8c62eeba 100644
--- a/drivers/gpu/drm/nouveau/nv84_fence.c
+++ b/drivers/gpu/drm/nouveau/nv84_fence.c
@@ -76,12 +76,18 @@ nv84_fence_sync32(struct nouveau_channel *chan, u64 virtual, u32 sequence)
return ret;
}
+static inline u32
+nv84_fence_chid(struct nouveau_channel *chan)
+{
+ return chan->drm->runl[chan->runlist].chan_id_base + chan->chid;
+}
+
static int
nv84_fence_emit(struct nouveau_fence *fence)
{
struct nouveau_channel *chan = fence->channel;
struct nv84_fence_chan *fctx = chan->fence;
- u64 addr = fctx->vma->addr + chan->chid * 16;
+ u64 addr = fctx->vma->addr + nv84_fence_chid(chan) * 16;
return fctx->base.emit32(chan, addr, fence->base.seqno);
}
@@ -91,7 +97,7 @@ nv84_fence_sync(struct nouveau_fence *fence,
struct nouveau_channel *prev, struct nouveau_channel *chan)
{
struct nv84_fence_chan *fctx = chan->fence;
- u64 addr = fctx->vma->addr + prev->chid * 16;
+ u64 addr = fctx->vma->addr + nv84_fence_chid(prev) * 16;
return fctx->base.sync32(chan, addr, fence->base.seqno);
}
@@ -100,7 +106,7 @@ static u32
nv84_fence_read(struct nouveau_channel *chan)
{
struct nv84_fence_priv *priv = chan->drm->fence;
- return nouveau_bo_rd32(priv->bo, chan->chid * 16/4);
+ return nouveau_bo_rd32(priv->bo, nv84_fence_chid(chan) * 16/4);
}
static void
@@ -109,7 +115,7 @@ nv84_fence_context_del(struct nouveau_channel *chan)
struct nv84_fence_priv *priv = chan->drm->fence;
struct nv84_fence_chan *fctx = chan->fence;
- nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence);
+ nouveau_bo_wr32(priv->bo, nv84_fence_chid(chan) * 16 / 4, fctx->base.sequence);
mutex_lock(&priv->mutex);
nouveau_vma_del(&fctx->vma);
mutex_unlock(&priv->mutex);
@@ -152,9 +158,9 @@ nv84_fence_suspend(struct nouveau_drm *drm)
struct nv84_fence_priv *priv = drm->fence;
int i;
- priv->suspend = vmalloc(array_size(sizeof(u32), drm->chan.nr));
+ priv->suspend = vmalloc(array_size(sizeof(u32), drm->chan_total));
if (priv->suspend) {
- for (i = 0; i < drm->chan.nr; i++)
+ for (i = 0; i < drm->chan_total; i++)
priv->suspend[i] = nouveau_bo_rd32(priv->bo, i*4);
}
@@ -168,7 +174,7 @@ nv84_fence_resume(struct nouveau_drm *drm)
int i;
if (priv->suspend) {
- for (i = 0; i < drm->chan.nr; i++)
+ for (i = 0; i < drm->chan_total; i++)
nouveau_bo_wr32(priv->bo, i*4, priv->suspend[i]);
vfree(priv->suspend);
priv->suspend = NULL;
@@ -204,7 +210,7 @@ nv84_fence_create(struct nouveau_drm *drm)
priv->base.context_new = nv84_fence_context_new;
priv->base.context_del = nv84_fence_context_del;
- priv->base.uevent = drm->client.device.info.family < NV_DEVICE_INFO_V0_AMPERE;
+ priv->base.uevent = true;
mutex_init(&priv->mutex);
@@ -216,7 +222,7 @@ nv84_fence_create(struct nouveau_drm *drm)
* will lose CPU/GPU coherency!
*/
NOUVEAU_GEM_DOMAIN_GART | NOUVEAU_GEM_DOMAIN_COHERENT;
- ret = nouveau_bo_new(&drm->client, 16 * drm->chan.nr, 0,
+ ret = nouveau_bo_new(&drm->client, 16 * drm->chan_total, 0,
domain, 0, 0, NULL, NULL, &priv->bo);
if (ret == 0) {
ret = nouveau_bo_pin(priv->bo, domain, false);
diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c
deleted file mode 100644
index 7908a1a3e00f..000000000000
--- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * Copyright 2010 Red Hat 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: Ben Skeggs
- */
-#define NVIF_DEBUG_PRINT_DISABLE
-#include "nouveau_drv.h"
-#include "nouveau_dma.h"
-#include "nouveau_fbcon.h"
-#include "nouveau_vmm.h"
-
-#include <nvif/push906f.h>
-
-#include <nvhw/class/cl902d.h>
-
-int
-nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
- struct nouveau_fbdev *nfbdev = info->par;
- struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
- struct nouveau_channel *chan = drm->channel;
- struct nvif_push *push = chan->chan.push;
- u32 colour;
- int ret;
-
- if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
- info->fix.visual == FB_VISUAL_DIRECTCOLOR)
- colour = ((uint32_t *)info->pseudo_palette)[rect->color];
- else
- colour = rect->color;
-
- ret = PUSH_WAIT(push, rect->rop == ROP_COPY ? 7 : 9);
- if (ret)
- return ret;
-
- if (rect->rop != ROP_COPY) {
- PUSH_IMMD(push, NV902D, SET_OPERATION,
- NVDEF(NV902D, SET_OPERATION, V, ROP_AND));
- }
-
- PUSH_MTHD(push, NV902D, SET_RENDER_SOLID_PRIM_COLOR, colour);
-
- PUSH_MTHD(push, NV902D, RENDER_SOLID_PRIM_POINT_SET_X(0), rect->dx,
- RENDER_SOLID_PRIM_POINT_Y(0), rect->dy,
- RENDER_SOLID_PRIM_POINT_SET_X(1), rect->dx + rect->width,
- RENDER_SOLID_PRIM_POINT_Y(1), rect->dy + rect->height);
-
- if (rect->rop != ROP_COPY) {
- PUSH_IMMD(push, NV902D, SET_OPERATION,
- NVDEF(NV902D, SET_OPERATION, V, SRCCOPY));
- }
-
- PUSH_KICK(push);
- return 0;
-}
-
-int
-nvc0_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
-{
- struct nouveau_fbdev *nfbdev = info->par;
- struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
- struct nouveau_channel *chan = drm->channel;
- struct nvif_push *push = chan->chan.push;
- int ret;
-
- ret = PUSH_WAIT(push, 11);
- if (ret)
- return ret;
-
- PUSH_IMMD(push, NV902D, WAIT_FOR_IDLE, 0);
-
- PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_MEMORY_DST_X0, region->dx,
- SET_PIXELS_FROM_MEMORY_DST_Y0, region->dy,
- SET_PIXELS_FROM_MEMORY_DST_WIDTH, region->width,
- SET_PIXELS_FROM_MEMORY_DST_HEIGHT, region->height);
-
- PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_MEMORY_SRC_X0_FRAC, 0,
- SET_PIXELS_FROM_MEMORY_SRC_X0_INT, region->sx,
- SET_PIXELS_FROM_MEMORY_SRC_Y0_FRAC, 0,
- PIXELS_FROM_MEMORY_SRC_Y0_INT, region->sy);
- PUSH_KICK(push);
- return 0;
-}
-
-int
-nvc0_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
-{
- struct nouveau_fbdev *nfbdev = info->par;
- struct nouveau_drm *drm = nouveau_drm(nfbdev->helper.dev);
- struct nouveau_channel *chan = drm->channel;
- struct nvif_push *push = chan->chan.push;
- uint32_t dwords, *data = (uint32_t *)image->data;
- uint32_t mask = ~(~0 >> (32 - info->var.bits_per_pixel));
- uint32_t *palette = info->pseudo_palette, bg, fg;
- int ret;
-
- if (image->depth != 1)
- return -ENODEV;
-
- if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
- info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
- bg = palette[image->bg_color] | mask;
- fg = palette[image->fg_color] | mask;
- } else {
- bg = image->bg_color;
- fg = image->fg_color;
- }
-
- ret = PUSH_WAIT(push, 11);
- if (ret)
- return ret;
-
- PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_CPU_COLOR0, bg,
- SET_PIXELS_FROM_CPU_COLOR1, fg);
-
- PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_CPU_SRC_WIDTH, image->width,
- SET_PIXELS_FROM_CPU_SRC_HEIGHT, image->height);
-
- PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_CPU_DST_X0_FRAC, 0,
- SET_PIXELS_FROM_CPU_DST_X0_INT, image->dx,
- SET_PIXELS_FROM_CPU_DST_Y0_FRAC, 0,
- SET_PIXELS_FROM_CPU_DST_Y0_INT, image->dy);
-
- dwords = ALIGN(ALIGN(image->width, 8) * image->height, 32) >> 5;
- while (dwords) {
- int count = dwords > 2047 ? 2047 : dwords;
-
- ret = PUSH_WAIT(push, count + 1);
- if (ret)
- return ret;
-
- dwords -= count;
-
- PUSH_NINC(push, NV902D, PIXELS_FROM_CPU_DATA, data, count);
- data += count;
- }
-
- PUSH_KICK(push);
- return 0;
-}
-
-int
-nvc0_fbcon_accel_init(struct fb_info *info)
-{
- struct nouveau_fbdev *nfbdev = info->par;
- struct drm_device *dev = nfbdev->helper.dev;
- struct nouveau_drm *drm = nouveau_drm(dev);
- struct nouveau_channel *chan = drm->channel;
- struct nvif_push *push = chan->chan.push;
- int ret, format;
-
- ret = nvif_object_ctor(&chan->user, "fbconTwoD", 0x902d, 0x902d,
- NULL, 0, &nfbdev->twod);
- if (ret)
- return ret;
-
- switch (info->var.bits_per_pixel) {
- case 8:
- format = NV902D_SET_DST_FORMAT_V_Y8;
- break;
- case 15:
- format = NV902D_SET_DST_FORMAT_V_X1R5G5B5;
- break;
- case 16:
- format = NV902D_SET_DST_FORMAT_V_R5G6B5;
- break;
- case 32:
- switch (info->var.transp.length) {
- case 0: /* depth 24 */
- case 8: /* depth 32, just use 24.. */
- format = NV902D_SET_DST_FORMAT_V_X8R8G8B8;
- break;
- case 2: /* depth 30 */
- format = NV902D_SET_DST_FORMAT_V_A2B10G10R10;
- break;
- default:
- return -EINVAL;
- }
- break;
- default:
- return -EINVAL;
- }
-
- ret = PUSH_WAIT(push, 52);
- if (ret) {
- WARN_ON(1);
- nouveau_fbcon_gpu_lockup(info);
- return ret;
- }
-
- PUSH_MTHD(push, NV902D, SET_OBJECT, nfbdev->twod.handle);
-
- PUSH_MTHD(push, NV902D, SET_DST_FORMAT,
- NVVAL(NV902D, SET_DST_FORMAT, V, format),
-
- SET_DST_MEMORY_LAYOUT,
- NVDEF(NV902D, SET_DST_MEMORY_LAYOUT, V, PITCH));
-
- PUSH_MTHD(push, NV902D, SET_DST_PITCH, info->fix.line_length,
- SET_DST_WIDTH, info->var.xres_virtual,
- SET_DST_HEIGHT, info->var.yres_virtual,
-
- SET_DST_OFFSET_UPPER,
- NVVAL(NV902D, SET_DST_OFFSET_UPPER, V, upper_32_bits(nfbdev->vma->addr)),
-
- SET_DST_OFFSET_LOWER,
- NVVAL(NV902D, SET_DST_OFFSET_LOWER, V, lower_32_bits(nfbdev->vma->addr)));
-
- PUSH_MTHD(push, NV902D, SET_SRC_FORMAT,
- NVVAL(NV902D, SET_SRC_FORMAT, V, format),
-
- SET_SRC_MEMORY_LAYOUT,
- NVDEF(NV902D, SET_SRC_MEMORY_LAYOUT, V, PITCH));
-
- PUSH_MTHD(push, NV902D, SET_SRC_PITCH, info->fix.line_length,
- SET_SRC_WIDTH, info->var.xres_virtual,
- SET_SRC_HEIGHT, info->var.yres_virtual,
-
- SET_SRC_OFFSET_UPPER,
- NVVAL(NV902D, SET_SRC_OFFSET_UPPER, V, upper_32_bits(nfbdev->vma->addr)),
-
- SET_SRC_OFFSET_LOWER,
- NVVAL(NV902D, SET_SRC_OFFSET_LOWER, V, lower_32_bits(nfbdev->vma->addr)));
-
- PUSH_IMMD(push, NV902D, SET_CLIP_ENABLE,
- NVDEF(NV902D, SET_CLIP_ENABLE, V, FALSE));
-
- PUSH_IMMD(push, NV902D, SET_ROP,
- NVVAL(NV902D, SET_ROP, V, 0x55));
-
- PUSH_IMMD(push, NV902D, SET_OPERATION,
- NVDEF(NV902D, SET_OPERATION, V, SRCCOPY));
-
- PUSH_MTHD(push, NV902D, SET_MONOCHROME_PATTERN_COLOR_FORMAT,
- NVDEF(NV902D, SET_MONOCHROME_PATTERN_COLOR_FORMAT, V, A8R8G8B8),
-
- SET_MONOCHROME_PATTERN_FORMAT,
- NVDEF(NV902D, SET_MONOCHROME_PATTERN_FORMAT, V, LE_M1));
-
- PUSH_MTHD(push, NV902D, RENDER_SOLID_PRIM_MODE,
- NVDEF(NV902D, RENDER_SOLID_PRIM_MODE, V, RECTS),
-
- SET_RENDER_SOLID_PRIM_COLOR_FORMAT,
- NVVAL(NV902D, SET_RENDER_SOLID_PRIM_COLOR_FORMAT, V, format));
-
- PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_CPU_DATA_TYPE,
- NVDEF(NV902D, SET_PIXELS_FROM_CPU_DATA_TYPE, V, INDEX),
-
- SET_PIXELS_FROM_CPU_COLOR_FORMAT,
- NVVAL(NV902D, SET_PIXELS_FROM_CPU_COLOR_FORMAT, V, format),
-
- SET_PIXELS_FROM_CPU_INDEX_FORMAT,
- NVDEF(NV902D, SET_PIXELS_FROM_CPU_INDEX_FORMAT, V, I1),
-
- SET_PIXELS_FROM_CPU_MONO_FORMAT,
- NVDEF(NV902D, SET_PIXELS_FROM_CPU_MONO_FORMAT, V, CGA6_M1),
-
- SET_PIXELS_FROM_CPU_WRAP,
- NVDEF(NV902D, SET_PIXELS_FROM_CPU_WRAP, V, WRAP_BYTE));
-
- PUSH_IMMD(push, NV902D, SET_PIXELS_FROM_CPU_MONO_OPACITY,
- NVDEF(NV902D, SET_PIXELS_FROM_CPU_MONO_OPACITY, V, OPAQUE));
-
- PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_CPU_DX_DU_FRAC, 0,
- SET_PIXELS_FROM_CPU_DX_DU_INT, 1,
- SET_PIXELS_FROM_CPU_DY_DV_FRAC, 0,
- SET_PIXELS_FROM_CPU_DY_DV_INT, 1);
-
- PUSH_IMMD(push, NV902D, SET_PIXELS_FROM_MEMORY_SAFE_OVERLAP,
- NVDEF(NV902D, SET_PIXELS_FROM_MEMORY_SAFE_OVERLAP, V, TRUE));
-
- PUSH_MTHD(push, NV902D, SET_PIXELS_FROM_MEMORY_DU_DX_FRAC, 0,
- SET_PIXELS_FROM_MEMORY_DU_DX_INT, 1,
- SET_PIXELS_FROM_MEMORY_DV_DY_FRAC, 0,
- SET_PIXELS_FROM_MEMORY_DV_DY_INT, 1);
- PUSH_KICK(push);
- return 0;
-}
-
diff --git a/drivers/gpu/drm/nouveau/nvif/Kbuild b/drivers/gpu/drm/nouveau/nvif/Kbuild
index 6abc4bc42e35..b7963a39dd91 100644
--- a/drivers/gpu/drm/nouveau/nvif/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvif/Kbuild
@@ -5,10 +5,11 @@ nvif-y += nvif/conn.o
nvif-y += nvif/device.o
nvif-y += nvif/disp.o
nvif-y += nvif/driver.o
+nvif-y += nvif/event.o
nvif-y += nvif/fifo.o
+nvif-y += nvif/head.o
nvif-y += nvif/mem.o
nvif-y += nvif/mmu.o
-nvif-y += nvif/notify.o
nvif-y += nvif/outp.o
nvif-y += nvif/timer.o
nvif-y += nvif/vmm.o
diff --git a/drivers/gpu/drm/nouveau/nvif/conn.c b/drivers/gpu/drm/nouveau/nvif/conn.c
index 4ce935d58c90..a3cf91aeae2d 100644
--- a/drivers/gpu/drm/nouveau/nvif/conn.c
+++ b/drivers/gpu/drm/nouveau/nvif/conn.c
@@ -27,6 +27,25 @@
#include <nvif/if0011.h>
int
+nvif_conn_event_ctor(struct nvif_conn *conn, const char *name, nvif_event_func func, u8 types,
+ struct nvif_event *event)
+{
+ struct {
+ struct nvif_event_v0 base;
+ struct nvif_conn_event_v0 conn;
+ } args;
+ int ret;
+
+ args.conn.version = 0;
+ args.conn.types = types;
+
+ ret = nvif_event_ctor_(&conn->object, name ?: "nvifConnHpd", nvif_conn_id(conn),
+ func, true, &args.base, sizeof(args), false, event);
+ NVIF_DEBUG(&conn->object, "[NEW EVENT:HPD types:%02x]", types);
+ return ret;
+}
+
+int
nvif_conn_hpd_status(struct nvif_conn *conn)
{
struct nvif_conn_hpd_status_v0 args;
diff --git a/drivers/gpu/drm/nouveau/nvif/disp.c b/drivers/gpu/drm/nouveau/nvif/disp.c
index 926b0c04b1e8..09915f2715af 100644
--- a/drivers/gpu/drm/nouveau/nvif/disp.c
+++ b/drivers/gpu/drm/nouveau/nvif/disp.c
@@ -72,9 +72,10 @@ nvif_disp_ctor(struct nvif_device *device, const char *name, s32 oclass, struct
if (ret)
return ret;
- NVIF_DEBUG(&disp->object, "[NEW] conn_mask:%08x outp_mask:%08x",
- args.conn_mask, args.outp_mask);
+ NVIF_DEBUG(&disp->object, "[NEW] conn_mask:%08x outp_mask:%08x head_mask:%08x",
+ args.conn_mask, args.outp_mask, args.head_mask);
disp->conn_mask = args.conn_mask;
disp->outp_mask = args.outp_mask;
+ disp->head_mask = args.head_mask;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvif/event.c b/drivers/gpu/drm/nouveau/nvif/event.c
new file mode 100644
index 000000000000..61ff4d6eba9f
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/event.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2021 Red Hat 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 <nvif/event.h>
+#include <nvif/printf.h>
+
+#include <nvif/class.h>
+#include <nvif/if000e.h>
+
+int
+nvif_event_block(struct nvif_event *event)
+{
+ if (nvif_event_constructed(event)) {
+ int ret = nvif_mthd(&event->object, NVIF_EVENT_V0_BLOCK, NULL, 0);
+ NVIF_ERRON(ret, &event->object, "[BLOCK]");
+ return ret;
+ }
+ return 0;
+}
+
+int
+nvif_event_allow(struct nvif_event *event)
+{
+ if (nvif_event_constructed(event)) {
+ int ret = nvif_mthd(&event->object, NVIF_EVENT_V0_ALLOW, NULL, 0);
+ NVIF_ERRON(ret, &event->object, "[ALLOW]");
+ return ret;
+ }
+ return 0;
+}
+
+void
+nvif_event_dtor(struct nvif_event *event)
+{
+ nvif_object_dtor(&event->object);
+}
+
+int
+nvif_event_ctor_(struct nvif_object *parent, const char *name, u32 handle, nvif_event_func func,
+ bool wait, struct nvif_event_v0 *args, u32 argc, bool warn,
+ struct nvif_event *event)
+{
+ struct nvif_event_v0 _args;
+ int ret;
+
+ if (!args) {
+ args = &_args;
+ argc = sizeof(_args);
+ }
+
+ args->version = 0;
+ args->wait = wait;
+
+ ret = nvif_object_ctor(parent, name ?: "nvifEvent", handle,
+ NVIF_CLASS_EVENT, args, argc, &event->object);
+ NVIF_ERRON(ret && warn, parent, "[NEW EVENT wait:%d size:%zd]",
+ args->wait, argc - sizeof(*args));
+ if (ret)
+ return ret;
+
+ event->func = func;
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/nvif/head.c b/drivers/gpu/drm/nouveau/nvif/head.c
new file mode 100644
index 000000000000..f00e01d232db
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvif/head.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2021 Red Hat 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 <nvif/head.h>
+#include <nvif/disp.h>
+#include <nvif/printf.h>
+
+#include <nvif/class.h>
+#include <nvif/if0013.h>
+
+int
+nvif_head_vblank_event_ctor(struct nvif_head *head, const char *name, nvif_event_func func,
+ bool wait, struct nvif_event *event)
+{
+ int ret = nvif_event_ctor(&head->object, name ?: "nvifHeadVBlank", nvif_head_id(head),
+ func, wait, NULL, 0, event);
+ NVIF_ERRON(ret, &head->object, "[NEW EVENT:VBLANK]");
+ return ret;
+}
+
+void
+nvif_head_dtor(struct nvif_head *head)
+{
+ nvif_object_dtor(&head->object);
+}
+
+int
+nvif_head_ctor(struct nvif_disp *disp, const char *name, int id, struct nvif_head *head)
+{
+ struct nvif_head_v0 args;
+ int ret;
+
+ args.version = 0;
+ args.id = id;
+
+ ret = nvif_object_ctor(&disp->object, name ? name : "nvifHead", id, NVIF_CLASS_HEAD,
+ &args, sizeof(args), &head->object);
+ NVIF_ERRON(ret, &disp->object, "[NEW head id:%d]", args.id);
+ return ret;
+}
diff --git a/drivers/gpu/drm/nouveau/nvif/notify.c b/drivers/gpu/drm/nouveau/nvif/notify.c
deleted file mode 100644
index 143c8dc6889e..000000000000
--- a/drivers/gpu/drm/nouveau/nvif/notify.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright 2014 Red Hat 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: Ben Skeggs <bskeggs@redhat.com>
- */
-
-#include <nvif/client.h>
-#include <nvif/driver.h>
-#include <nvif/notify.h>
-#include <nvif/object.h>
-#include <nvif/ioctl.h>
-#include <nvif/event.h>
-
-static inline int
-nvif_notify_put_(struct nvif_notify *notify)
-{
- struct nvif_object *object = notify->object;
- struct {
- struct nvif_ioctl_v0 ioctl;
- struct nvif_ioctl_ntfy_put_v0 ntfy;
- } args = {
- .ioctl.type = NVIF_IOCTL_V0_NTFY_PUT,
- .ntfy.index = notify->index,
- };
-
- if (atomic_inc_return(&notify->putcnt) != 1)
- return 0;
-
- return nvif_object_ioctl(object, &args, sizeof(args), NULL);
-}
-
-int
-nvif_notify_put(struct nvif_notify *notify)
-{
- if (likely(notify->object) &&
- test_and_clear_bit(NVIF_NOTIFY_USER, &notify->flags)) {
- int ret = nvif_notify_put_(notify);
- if (test_bit(NVIF_NOTIFY_WORK, &notify->flags))
- flush_work(&notify->work);
- return ret;
- }
- return 0;
-}
-
-static inline int
-nvif_notify_get_(struct nvif_notify *notify)
-{
- struct nvif_object *object = notify->object;
- struct {
- struct nvif_ioctl_v0 ioctl;
- struct nvif_ioctl_ntfy_get_v0 ntfy;
- } args = {
- .ioctl.type = NVIF_IOCTL_V0_NTFY_GET,
- .ntfy.index = notify->index,
- };
-
- if (atomic_dec_return(&notify->putcnt) != 0)
- return 0;
-
- return nvif_object_ioctl(object, &args, sizeof(args), NULL);
-}
-
-int
-nvif_notify_get(struct nvif_notify *notify)
-{
- if (likely(notify->object) &&
- !test_and_set_bit(NVIF_NOTIFY_USER, &notify->flags))
- return nvif_notify_get_(notify);
- return 0;
-}
-
-static inline int
-nvif_notify_func(struct nvif_notify *notify, bool keep)
-{
- int ret = notify->func(notify);
- if (ret == NVIF_NOTIFY_KEEP ||
- !test_and_clear_bit(NVIF_NOTIFY_USER, &notify->flags)) {
- if (!keep)
- atomic_dec(&notify->putcnt);
- else
- nvif_notify_get_(notify);
- }
- return ret;
-}
-
-static void
-nvif_notify_work(struct work_struct *work)
-{
- struct nvif_notify *notify = container_of(work, typeof(*notify), work);
- nvif_notify_func(notify, true);
-}
-
-int
-nvif_notify(const void *header, u32 length, const void *data, u32 size)
-{
- struct nvif_notify *notify = NULL;
- const union {
- struct nvif_notify_rep_v0 v0;
- } *args = header;
- int ret = NVIF_NOTIFY_DROP;
-
- if (length == sizeof(args->v0) && args->v0.version == 0) {
- if (WARN_ON(args->v0.route))
- return NVIF_NOTIFY_DROP;
- notify = (void *)(unsigned long)args->v0.token;
- }
-
- if (!WARN_ON(notify == NULL)) {
- struct nvif_client *client = notify->object->client;
- if (!WARN_ON(notify->size != size)) {
- atomic_inc(&notify->putcnt);
- if (test_bit(NVIF_NOTIFY_WORK, &notify->flags)) {
- memcpy((void *)notify->data, data, size);
- schedule_work(&notify->work);
- return NVIF_NOTIFY_DROP;
- }
- notify->data = data;
- ret = nvif_notify_func(notify, client->driver->keep);
- notify->data = NULL;
- }
- }
-
- return ret;
-}
-
-int
-nvif_notify_dtor(struct nvif_notify *notify)
-{
- struct nvif_object *object = notify->object;
- struct {
- struct nvif_ioctl_v0 ioctl;
- struct nvif_ioctl_ntfy_del_v0 ntfy;
- } args = {
- .ioctl.type = NVIF_IOCTL_V0_NTFY_DEL,
- .ntfy.index = notify->index,
- };
- int ret = nvif_notify_put(notify);
- if (ret >= 0 && object) {
- ret = nvif_object_ioctl(object, &args, sizeof(args), NULL);
- notify->object = NULL;
- kfree((void *)notify->data);
- }
- return ret;
-}
-
-int
-nvif_notify_ctor(struct nvif_object *object, const char *name,
- int (*func)(struct nvif_notify *), bool work, u8 event,
- void *data, u32 size, u32 reply, struct nvif_notify *notify)
-{
- struct {
- struct nvif_ioctl_v0 ioctl;
- struct nvif_ioctl_ntfy_new_v0 ntfy;
- struct nvif_notify_req_v0 req;
- } *args;
- int ret = -ENOMEM;
-
- notify->object = object;
- notify->name = name ? name : "nvifNotify";
- notify->flags = 0;
- atomic_set(&notify->putcnt, 1);
- notify->func = func;
- notify->data = NULL;
- notify->size = reply;
- if (work) {
- INIT_WORK(&notify->work, nvif_notify_work);
- set_bit(NVIF_NOTIFY_WORK, &notify->flags);
- notify->data = kmalloc(notify->size, GFP_KERNEL);
- if (!notify->data)
- goto done;
- }
-
- if (!(args = kmalloc(sizeof(*args) + size, GFP_KERNEL)))
- goto done;
- args->ioctl.version = 0;
- args->ioctl.type = NVIF_IOCTL_V0_NTFY_NEW;
- args->ntfy.version = 0;
- args->ntfy.event = event;
- args->req.version = 0;
- args->req.reply = notify->size;
- args->req.route = 0;
- args->req.token = (unsigned long)(void *)notify;
-
- memcpy(args->req.data, data, size);
- ret = nvif_object_ioctl(object, args, sizeof(*args) + size, NULL);
- notify->index = args->ntfy.index;
- kfree(args);
-done:
- if (ret)
- nvif_notify_dtor(notify);
- return ret;
-}
diff --git a/drivers/gpu/drm/nouveau/nvif/outp.c b/drivers/gpu/drm/nouveau/nvif/outp.c
index 7bfe91a8d6f9..7da39f1eae9f 100644
--- a/drivers/gpu/drm/nouveau/nvif/outp.c
+++ b/drivers/gpu/drm/nouveau/nvif/outp.c
@@ -24,7 +24,177 @@
#include <nvif/printf.h>
#include <nvif/class.h>
-#include <nvif/if0012.h>
+
+int
+nvif_outp_dp_mst_vcpi(struct nvif_outp *outp, int head,
+ u8 start_slot, u8 num_slots, u16 pbn, u16 aligned_pbn)
+{
+ struct nvif_outp_dp_mst_vcpi_v0 args;
+ int ret;
+
+ args.version = 0;
+ args.head = head;
+ args.start_slot = start_slot;
+ args.num_slots = num_slots;
+ args.pbn = pbn;
+ args.aligned_pbn = aligned_pbn;
+
+ ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_DP_MST_VCPI, &args, sizeof(args));
+ NVIF_ERRON(ret, &outp->object,
+ "[DP_MST_VCPI head:%d start_slot:%02x num_slots:%02x pbn:%04x aligned_pbn:%04x]",
+ args.head, args.start_slot, args.num_slots, args.pbn, args.aligned_pbn);
+ return ret;
+}
+
+int
+nvif_outp_dp_retrain(struct nvif_outp *outp)
+{
+ int ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_DP_RETRAIN, NULL, 0);
+ NVIF_ERRON(ret, &outp->object, "[DP_RETRAIN]");
+ return ret;
+}
+
+int
+nvif_outp_dp_aux_pwr(struct nvif_outp *outp, bool enable)
+{
+ struct nvif_outp_dp_aux_pwr_v0 args;
+ int ret;
+
+ args.version = 0;
+ args.state = enable;
+
+ ret = nvif_object_mthd(&outp->object, NVIF_OUTP_V0_DP_AUX_PWR, &args, sizeof(args));
+ NVIF_ERRON(ret, &outp->object, "[DP_AUX_PWR state:%d]", args.state);
+ return ret;
+}
+
+int
+nvif_outp_hda_eld(struct nvif_outp *outp, int head, void *data, u32 size)
+{
+ struct {
+ struct nvif_outp_hda_eld_v0 mthd;
+ u8 data[128];
+ } args;
+ int ret;
+
+ if (WARN_ON(size > ARRAY_SIZE(args.data)))
+ return -EINVAL;
+
+ args.mthd.version = 0;
+ args.mthd.head = head;
+
+ memcpy(args.data, data, size);
+ ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_HDA_ELD, &args, sizeof(args.mthd) + size);
+ NVIF_ERRON(ret, &outp->object, "[HDA_ELD head:%d size:%d]", head, size);
+ return ret;
+}
+
+int
+nvif_outp_infoframe(struct nvif_outp *outp, u8 type, struct nvif_outp_infoframe_v0 *args, u32 size)
+{
+ int ret;
+
+ args->type = type;
+
+ ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_INFOFRAME, args, sizeof(*args) + size);
+ NVIF_ERRON(ret, &outp->object, "[INFOFRAME type:%d size:%d]", type, size);
+ return ret;
+}
+
+void
+nvif_outp_release(struct nvif_outp *outp)
+{
+ int ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_RELEASE, NULL, 0);
+ NVIF_ERRON(ret, &outp->object, "[RELEASE]");
+ outp->or.id = -1;
+}
+
+static inline int
+nvif_outp_acquire(struct nvif_outp *outp, u8 proto, struct nvif_outp_acquire_v0 *args)
+{
+ int ret;
+
+ args->version = 0;
+ args->proto = proto;
+
+ ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_ACQUIRE, args, sizeof(*args));
+ if (ret)
+ return ret;
+
+ outp->or.id = args->or;
+ outp->or.link = args->link;
+ return 0;
+}
+
+int
+nvif_outp_acquire_dp(struct nvif_outp *outp, u8 dpcd[16],
+ int link_nr, int link_bw, bool hda, bool mst)
+{
+ struct nvif_outp_acquire_v0 args;
+ int ret;
+
+ args.dp.link_nr = link_nr;
+ args.dp.link_bw = link_bw;
+ args.dp.hda = hda;
+ args.dp.mst = mst;
+ memcpy(args.dp.dpcd, dpcd, sizeof(args.dp.dpcd));
+
+ ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_DP, &args);
+ NVIF_ERRON(ret, &outp->object,
+ "[ACQUIRE proto:DP link_nr:%d link_bw:%02x hda:%d mst:%d] or:%d link:%d",
+ args.dp.link_nr, args.dp.link_bw, args.dp.hda, args.dp.mst, args.or, args.link);
+ return ret;
+}
+
+int
+nvif_outp_acquire_lvds(struct nvif_outp *outp, bool dual, bool bpc8)
+{
+ struct nvif_outp_acquire_v0 args;
+ int ret;
+
+ args.lvds.dual = dual;
+ args.lvds.bpc8 = bpc8;
+
+ ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_LVDS, &args);
+ NVIF_ERRON(ret, &outp->object,
+ "[ACQUIRE proto:LVDS dual:%d 8bpc:%d] or:%d link:%d",
+ args.lvds.dual, args.lvds.bpc8, args.or, args.link);
+ return ret;
+}
+
+int
+nvif_outp_acquire_tmds(struct nvif_outp *outp, int head,
+ bool hdmi, u8 max_ac_packet, u8 rekey, u8 scdc, bool hda)
+{
+ struct nvif_outp_acquire_v0 args;
+ int ret;
+
+ args.tmds.head = head;
+ args.tmds.hdmi = hdmi;
+ args.tmds.hdmi_max_ac_packet = max_ac_packet;
+ args.tmds.hdmi_rekey = rekey;
+ args.tmds.hdmi_scdc = scdc;
+ args.tmds.hdmi_hda = hda;
+
+ ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_TMDS, &args);
+ NVIF_ERRON(ret, &outp->object,
+ "[ACQUIRE proto:TMDS head:%d hdmi:%d max_ac_packet:%d rekey:%d scdc:%d hda:%d]"
+ " or:%d link:%d", args.tmds.head, args.tmds.hdmi, args.tmds.hdmi_max_ac_packet,
+ args.tmds.hdmi_rekey, args.tmds.hdmi_scdc, args.tmds.hdmi_hda,
+ args.or, args.link);
+ return ret;
+}
+
+int
+nvif_outp_acquire_rgb_crt(struct nvif_outp *outp)
+{
+ struct nvif_outp_acquire_v0 args;
+ int ret;
+
+ ret = nvif_outp_acquire(outp, NVIF_OUTP_ACQUIRE_V0_RGB_CRT, &args);
+ NVIF_ERRON(ret, &outp->object, "[ACQUIRE proto:RGB_CRT] or:%d", args.or);
+ return ret;
+}
int
nvif_outp_load_detect(struct nvif_outp *outp, u32 loadval)
@@ -58,5 +228,9 @@ nvif_outp_ctor(struct nvif_disp *disp, const char *name, int id, struct nvif_out
ret = nvif_object_ctor(&disp->object, name ?: "nvifOutp", id, NVIF_CLASS_OUTP,
&args, sizeof(args), &outp->object);
NVIF_ERRON(ret, &disp->object, "[NEW outp id:%d]", id);
- return ret;
+ if (ret)
+ return ret;
+
+ outp->or.id = -1;
+ return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvif/user.c b/drivers/gpu/drm/nouveau/nvif/user.c
index d89f5b67b304..b648a5e036af 100644
--- a/drivers/gpu/drm/nouveau/nvif/user.c
+++ b/drivers/gpu/drm/nouveau/nvif/user.c
@@ -41,7 +41,9 @@ nvif_user_ctor(struct nvif_device *device, const char *name)
int version;
const struct nvif_user_func *func;
} users[] = {
- { VOLTA_USERMODE_A, -1, &nvif_userc361 },
+ { AMPERE_USERMODE_A, -1, &nvif_userc361 },
+ { TURING_USERMODE_A, -1, &nvif_userc361 },
+ { VOLTA_USERMODE_A, -1, &nvif_userc361 },
{}
};
int cid, ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/Kbuild b/drivers/gpu/drm/nouveau/nvkm/core/Kbuild
index 2b471ab585b4..e40712023c73 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/core/Kbuild
@@ -5,12 +5,13 @@ nvkm-y += nvkm/core/enum.o
nvkm-y += nvkm/core/event.o
nvkm-y += nvkm/core/firmware.o
nvkm-y += nvkm/core/gpuobj.o
+nvkm-y += nvkm/core/intr.o
nvkm-y += nvkm/core/ioctl.o
nvkm-y += nvkm/core/memory.o
nvkm-y += nvkm/core/mm.o
-nvkm-y += nvkm/core/notify.o
nvkm-y += nvkm/core/object.o
nvkm-y += nvkm/core/oproxy.o
nvkm-y += nvkm/core/option.o
nvkm-y += nvkm/core/ramht.o
nvkm-y += nvkm/core/subdev.o
+nvkm-y += nvkm/core/uevent.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/client.c b/drivers/gpu/drm/nouveau/nvkm/core/client.c
index 0c8c55c73b12..ebdeb8eb9e77 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/client.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/client.c
@@ -23,7 +23,6 @@
*/
#include <core/client.h>
#include <core/device.h>
-#include <core/notify.h>
#include <core/option.h>
#include <nvif/class.h>
@@ -44,7 +43,7 @@ nvkm_uclient_new(const struct nvkm_oclass *oclass, void *argv, u32 argc,
if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))){
args->v0.name[sizeof(args->v0.name) - 1] = 0;
ret = nvkm_client_new(args->v0.name, args->v0.device, NULL,
- NULL, oclass->client->ntfy, &client);
+ NULL, oclass->client->event, &client);
if (ret)
return ret;
} else
@@ -68,113 +67,6 @@ nvkm_uclient_sclass = {
.ctor = nvkm_uclient_new,
};
-struct nvkm_client_notify {
- struct nvkm_client *client;
- struct nvkm_notify n;
- u8 version;
- u8 size;
- union {
- struct nvif_notify_rep_v0 v0;
- } rep;
-};
-
-static int
-nvkm_client_notify(struct nvkm_notify *n)
-{
- struct nvkm_client_notify *notify = container_of(n, typeof(*notify), n);
- struct nvkm_client *client = notify->client;
- return client->ntfy(&notify->rep, notify->size, n->data, n->size);
-}
-
-int
-nvkm_client_notify_put(struct nvkm_client *client, int index)
-{
- if (index < ARRAY_SIZE(client->notify)) {
- if (client->notify[index]) {
- nvkm_notify_put(&client->notify[index]->n);
- return 0;
- }
- }
- return -ENOENT;
-}
-
-int
-nvkm_client_notify_get(struct nvkm_client *client, int index)
-{
- if (index < ARRAY_SIZE(client->notify)) {
- if (client->notify[index]) {
- nvkm_notify_get(&client->notify[index]->n);
- return 0;
- }
- }
- return -ENOENT;
-}
-
-int
-nvkm_client_notify_del(struct nvkm_client *client, int index)
-{
- if (index < ARRAY_SIZE(client->notify)) {
- if (client->notify[index]) {
- nvkm_notify_fini(&client->notify[index]->n);
- kfree(client->notify[index]);
- client->notify[index] = NULL;
- return 0;
- }
- }
- return -ENOENT;
-}
-
-int
-nvkm_client_notify_new(struct nvkm_object *object,
- struct nvkm_event *event, void *data, u32 size)
-{
- struct nvkm_client *client = object->client;
- struct nvkm_client_notify *notify;
- union {
- struct nvif_notify_req_v0 v0;
- } *req = data;
- u8 index, reply;
- int ret = -ENOSYS;
-
- for (index = 0; index < ARRAY_SIZE(client->notify); index++) {
- if (!client->notify[index])
- break;
- }
-
- if (index == ARRAY_SIZE(client->notify))
- return -ENOSPC;
-
- notify = kzalloc(sizeof(*notify), GFP_KERNEL);
- if (!notify)
- return -ENOMEM;
-
- nvif_ioctl(object, "notify new size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, req->v0, 0, 0, true))) {
- nvif_ioctl(object, "notify new vers %d reply %d route %02x "
- "token %llx\n", req->v0.version,
- req->v0.reply, req->v0.route, req->v0.token);
- notify->version = req->v0.version;
- notify->size = sizeof(notify->rep.v0);
- notify->rep.v0.version = req->v0.version;
- notify->rep.v0.route = req->v0.route;
- notify->rep.v0.token = req->v0.token;
- reply = req->v0.reply;
- }
-
- if (ret == 0) {
- ret = nvkm_notify_init(object, event, nvkm_client_notify,
- false, data, size, reply, &notify->n);
- if (ret == 0) {
- client->notify[index] = notify;
- notify->client = client;
- return index;
- }
- }
-
- kfree(notify);
- return ret;
-}
-
static const struct nvkm_object_func nvkm_client;
struct nvkm_client *
nvkm_client_search(struct nvkm_client *client, u64 handle)
@@ -255,23 +147,13 @@ nvkm_client_child_get(struct nvkm_object *object, int index,
static int
nvkm_client_fini(struct nvkm_object *object, bool suspend)
{
- struct nvkm_client *client = nvkm_client(object);
- const char *name[2] = { "fini", "suspend" };
- int i;
- nvif_debug(object, "%s notify\n", name[suspend]);
- for (i = 0; i < ARRAY_SIZE(client->notify); i++)
- nvkm_client_notify_put(client, i);
return 0;
}
static void *
nvkm_client_dtor(struct nvkm_object *object)
{
- struct nvkm_client *client = nvkm_client(object);
- int i;
- for (i = 0; i < ARRAY_SIZE(client->notify); i++)
- nvkm_client_notify_del(client, i);
- return client;
+ return nvkm_client(object);
}
static const struct nvkm_object_func
@@ -283,10 +165,8 @@ nvkm_client = {
};
int
-nvkm_client_new(const char *name, u64 device, const char *cfg,
- const char *dbg,
- int (*ntfy)(const void *, u32, const void *, u32),
- struct nvkm_client **pclient)
+nvkm_client_new(const char *name, u64 device, const char *cfg, const char *dbg,
+ int (*event)(u64, void *, u32), struct nvkm_client **pclient)
{
struct nvkm_oclass oclass = { .base = nvkm_uclient_sclass };
struct nvkm_client *client;
@@ -300,7 +180,7 @@ nvkm_client_new(const char *name, u64 device, const char *cfg,
client->device = device;
client->debug = nvkm_dbgopt(dbg, "CLIENT");
client->objroot = RB_ROOT;
- client->ntfy = ntfy;
+ client->event = event;
INIT_LIST_HEAD(&client->umem);
spin_lock_init(&client->lock);
return 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/engine.c b/drivers/gpu/drm/nouveau/nvkm/core/engine.c
index e41a39ae1597..36a31e9eea22 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/engine.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/engine.c
@@ -35,16 +35,23 @@ nvkm_engine_chsw_load(struct nvkm_engine *engine)
return false;
}
+int
+nvkm_engine_reset(struct nvkm_engine *engine)
+{
+ if (engine->func->reset)
+ return engine->func->reset(engine);
+
+ nvkm_subdev_fini(&engine->subdev, false);
+ return nvkm_subdev_init(&engine->subdev);
+}
+
void
nvkm_engine_unref(struct nvkm_engine **pengine)
{
struct nvkm_engine *engine = *pengine;
+
if (engine) {
- if (refcount_dec_and_mutex_lock(&engine->use.refcount, &engine->use.mutex)) {
- nvkm_subdev_fini(&engine->subdev, false);
- engine->use.enabled = false;
- mutex_unlock(&engine->use.mutex);
- }
+ nvkm_subdev_unref(&engine->subdev);
*pengine = NULL;
}
}
@@ -53,21 +60,13 @@ struct nvkm_engine *
nvkm_engine_ref(struct nvkm_engine *engine)
{
int ret;
+
if (engine) {
- if (!refcount_inc_not_zero(&engine->use.refcount)) {
- mutex_lock(&engine->use.mutex);
- if (!refcount_inc_not_zero(&engine->use.refcount)) {
- engine->use.enabled = true;
- if ((ret = nvkm_subdev_init(&engine->subdev))) {
- engine->use.enabled = false;
- mutex_unlock(&engine->use.mutex);
- return ERR_PTR(ret);
- }
- refcount_set(&engine->use.refcount, 1);
- }
- mutex_unlock(&engine->use.mutex);
- }
+ ret = nvkm_subdev_ref(&engine->subdev);
+ if (ret)
+ return ERR_PTR(ret);
}
+
return engine;
}
@@ -91,14 +90,10 @@ static int
nvkm_engine_info(struct nvkm_subdev *subdev, u64 mthd, u64 *data)
{
struct nvkm_engine *engine = nvkm_engine(subdev);
- if (engine->func->info) {
- if (!IS_ERR((engine = nvkm_engine_ref(engine)))) {
- int ret = engine->func->info(engine, mthd, data);
- nvkm_engine_unref(&engine);
- return ret;
- }
- return PTR_ERR(engine);
- }
+
+ if (engine->func->info)
+ return engine->func->info(engine, mthd, data);
+
return -ENOSYS;
}
@@ -117,26 +112,6 @@ nvkm_engine_init(struct nvkm_subdev *subdev)
struct nvkm_engine *engine = nvkm_engine(subdev);
struct nvkm_fb *fb = subdev->device->fb;
int ret = 0, i;
- s64 time;
-
- if (!engine->use.enabled) {
- nvkm_trace(subdev, "init skipped, engine has no users\n");
- return ret;
- }
-
- if (engine->func->oneinit && !engine->subdev.oneinit) {
- nvkm_trace(subdev, "one-time init running...\n");
- time = ktime_to_us(ktime_get());
- ret = engine->func->oneinit(engine);
- if (ret) {
- nvkm_trace(subdev, "one-time init failed, %d\n", ret);
- return ret;
- }
-
- engine->subdev.oneinit = true;
- time = ktime_to_us(ktime_get()) - time;
- nvkm_trace(subdev, "one-time init completed in %lldus\n", time);
- }
if (engine->func->init)
ret = engine->func->init(engine);
@@ -147,6 +122,17 @@ nvkm_engine_init(struct nvkm_subdev *subdev)
}
static int
+nvkm_engine_oneinit(struct nvkm_subdev *subdev)
+{
+ struct nvkm_engine *engine = nvkm_engine(subdev);
+
+ if (engine->func->oneinit)
+ return engine->func->oneinit(engine);
+
+ return 0;
+}
+
+static int
nvkm_engine_preinit(struct nvkm_subdev *subdev)
{
struct nvkm_engine *engine = nvkm_engine(subdev);
@@ -161,7 +147,6 @@ nvkm_engine_dtor(struct nvkm_subdev *subdev)
struct nvkm_engine *engine = nvkm_engine(subdev);
if (engine->func->dtor)
return engine->func->dtor(engine);
- mutex_destroy(&engine->use.mutex);
return engine;
}
@@ -169,6 +154,7 @@ const struct nvkm_subdev_func
nvkm_engine = {
.dtor = nvkm_engine_dtor,
.preinit = nvkm_engine_preinit,
+ .oneinit = nvkm_engine_oneinit,
.init = nvkm_engine_init,
.fini = nvkm_engine_fini,
.info = nvkm_engine_info,
@@ -179,10 +165,9 @@ int
nvkm_engine_ctor(const struct nvkm_engine_func *func, struct nvkm_device *device,
enum nvkm_subdev_type type, int inst, bool enable, struct nvkm_engine *engine)
{
- nvkm_subdev_ctor(&nvkm_engine, device, type, inst, &engine->subdev);
engine->func = func;
- refcount_set(&engine->use.refcount, 0);
- mutex_init(&engine->use.mutex);
+ nvkm_subdev_ctor(&nvkm_engine, device, type, inst, &engine->subdev);
+ refcount_set(&engine->subdev.use.refcount, 0);
if (!nvkm_boolopt(device->cfgopt, engine->subdev.name, enable)) {
nvkm_debug(&engine->subdev, "disabled\n");
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/event.c b/drivers/gpu/drm/nouveau/nvkm/core/event.c
index 006618d77aa4..a6c877135598 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/event.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/event.c
@@ -20,54 +20,171 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <core/event.h>
-#include <core/notify.h>
+#include <core/subdev.h>
-void
+static void
nvkm_event_put(struct nvkm_event *event, u32 types, int index)
{
assert_spin_locked(&event->refs_lock);
+
+ nvkm_trace(event->subdev, "event: decr %08x on %d\n", types, index);
+
while (types) {
int type = __ffs(types); types &= ~(1 << type);
if (--event->refs[index * event->types_nr + type] == 0) {
+ nvkm_trace(event->subdev, "event: blocking %d on %d\n", type, index);
if (event->func->fini)
event->func->fini(event, 1 << type, index);
}
}
}
-void
+static void
nvkm_event_get(struct nvkm_event *event, u32 types, int index)
{
assert_spin_locked(&event->refs_lock);
+
+ nvkm_trace(event->subdev, "event: incr %08x on %d\n", types, index);
+
while (types) {
int type = __ffs(types); types &= ~(1 << type);
if (++event->refs[index * event->types_nr + type] == 1) {
+ nvkm_trace(event->subdev, "event: allowing %d on %d\n", type, index);
if (event->func->init)
event->func->init(event, 1 << type, index);
}
}
}
+static void
+nvkm_event_ntfy_state(struct nvkm_event_ntfy *ntfy)
+{
+ struct nvkm_event *event = ntfy->event;
+ unsigned long flags;
+
+ nvkm_trace(event->subdev, "event: ntfy state changed\n");
+ spin_lock_irqsave(&event->refs_lock, flags);
+
+ if (atomic_read(&ntfy->allowed) != ntfy->running) {
+ if (ntfy->running) {
+ nvkm_event_put(ntfy->event, ntfy->bits, ntfy->id);
+ ntfy->running = false;
+ } else {
+ nvkm_event_get(ntfy->event, ntfy->bits, ntfy->id);
+ ntfy->running = true;
+ }
+ }
+
+ spin_unlock_irqrestore(&event->refs_lock, flags);
+}
+
+static void
+nvkm_event_ntfy_remove(struct nvkm_event_ntfy *ntfy)
+{
+ spin_lock_irq(&ntfy->event->list_lock);
+ list_del_init(&ntfy->head);
+ spin_unlock_irq(&ntfy->event->list_lock);
+}
+
+static void
+nvkm_event_ntfy_insert(struct nvkm_event_ntfy *ntfy)
+{
+ spin_lock_irq(&ntfy->event->list_lock);
+ list_add_tail(&ntfy->head, &ntfy->event->ntfy);
+ spin_unlock_irq(&ntfy->event->list_lock);
+}
+
+static void
+nvkm_event_ntfy_block_(struct nvkm_event_ntfy *ntfy, bool wait)
+{
+ struct nvkm_subdev *subdev = ntfy->event->subdev;
+
+ nvkm_trace(subdev, "event: ntfy block %08x on %d wait:%d\n", ntfy->bits, ntfy->id, wait);
+
+ if (atomic_xchg(&ntfy->allowed, 0) == 1) {
+ nvkm_event_ntfy_state(ntfy);
+ if (wait)
+ nvkm_event_ntfy_remove(ntfy);
+ }
+}
+
void
-nvkm_event_send(struct nvkm_event *event, u32 types, int index,
- void *data, u32 size)
+nvkm_event_ntfy_block(struct nvkm_event_ntfy *ntfy)
{
- struct nvkm_notify *notify;
+ if (ntfy->event)
+ nvkm_event_ntfy_block_(ntfy, ntfy->wait);
+}
+
+void
+nvkm_event_ntfy_allow(struct nvkm_event_ntfy *ntfy)
+{
+ nvkm_trace(ntfy->event->subdev, "event: ntfy allow %08x on %d\n", ntfy->bits, ntfy->id);
+
+ if (atomic_xchg(&ntfy->allowed, 1) == 0) {
+ nvkm_event_ntfy_state(ntfy);
+ if (ntfy->wait)
+ nvkm_event_ntfy_insert(ntfy);
+ }
+}
+
+void
+nvkm_event_ntfy_del(struct nvkm_event_ntfy *ntfy)
+{
+ struct nvkm_event *event = ntfy->event;
+
+ if (!event)
+ return;
+
+ nvkm_trace(event->subdev, "event: ntfy del %08x on %d\n", ntfy->bits, ntfy->id);
+
+ nvkm_event_ntfy_block_(ntfy, false);
+ nvkm_event_ntfy_remove(ntfy);
+ ntfy->event = NULL;
+}
+
+void
+nvkm_event_ntfy_add(struct nvkm_event *event, int id, u32 bits, bool wait, nvkm_event_func func,
+ struct nvkm_event_ntfy *ntfy)
+{
+ nvkm_trace(event->subdev, "event: ntfy add %08x on %d wait:%d\n", id, bits, wait);
+
+ ntfy->event = event;
+ ntfy->id = id;
+ ntfy->bits = bits;
+ ntfy->wait = wait;
+ ntfy->func = func;
+ atomic_set(&ntfy->allowed, 0);
+ ntfy->running = false;
+ INIT_LIST_HEAD(&ntfy->head);
+ if (!ntfy->wait)
+ nvkm_event_ntfy_insert(ntfy);
+}
+
+bool
+nvkm_event_ntfy_valid(struct nvkm_event *event, int id, u32 bits)
+{
+ return true;
+}
+
+void
+nvkm_event_ntfy(struct nvkm_event *event, int id, u32 bits)
+{
+ struct nvkm_event_ntfy *ntfy, *ntmp;
unsigned long flags;
- if (!event->refs || WARN_ON(index >= event->index_nr))
+ if (!event->refs || WARN_ON(id >= event->index_nr))
return;
+ nvkm_trace(event->subdev, "event: ntfy %08x on %d\n", bits, id);
spin_lock_irqsave(&event->list_lock, flags);
- list_for_each_entry(notify, &event->list, head) {
- if (notify->index == index && (notify->types & types)) {
- if (event->func->send) {
- event->func->send(data, size, notify);
- continue;
- }
- nvkm_notify_send(notify, data, size);
+
+ list_for_each_entry_safe(ntfy, ntmp, &event->ntfy, head) {
+ if (ntfy->id == id && ntfy->bits & bits) {
+ if (atomic_read(&ntfy->allowed))
+ ntfy->func(ntfy, ntfy->bits & bits);
}
}
+
spin_unlock_irqrestore(&event->list_lock, flags);
}
@@ -81,20 +198,17 @@ nvkm_event_fini(struct nvkm_event *event)
}
int
-nvkm_event_init(const struct nvkm_event_func *func, int types_nr, int index_nr,
- struct nvkm_event *event)
+__nvkm_event_init(const struct nvkm_event_func *func, struct nvkm_subdev *subdev,
+ int types_nr, int index_nr, struct nvkm_event *event)
{
- event->refs = kzalloc(array3_size(index_nr, types_nr,
- sizeof(*event->refs)),
- GFP_KERNEL);
+ event->refs = kzalloc(array3_size(index_nr, types_nr, sizeof(*event->refs)), GFP_KERNEL);
if (!event->refs)
return -ENOMEM;
event->func = func;
+ event->subdev = subdev;
event->types_nr = types_nr;
event->index_nr = index_nr;
- spin_lock_init(&event->refs_lock);
- spin_lock_init(&event->list_lock);
- INIT_LIST_HEAD(&event->list);
+ INIT_LIST_HEAD(&event->ntfy);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
index ca1f8463cff5..fcf2a002f6cb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/firmware.c
@@ -22,6 +22,9 @@
#include <core/device.h>
#include <core/firmware.h>
+#include <subdev/fb.h>
+#include <subdev/mmu.h>
+
int
nvkm_firmware_load_name(const struct nvkm_subdev *subdev, const char *base,
const char *name, int ver, const struct firmware **pfw)
@@ -107,3 +110,127 @@ nvkm_firmware_put(const struct firmware *fw)
{
release_firmware(fw);
}
+
+#define nvkm_firmware_mem(p) container_of((p), struct nvkm_firmware, mem.memory)
+
+static int
+nvkm_firmware_mem_map(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm,
+ struct nvkm_vma *vma, void *argv, u32 argc)
+{
+ struct nvkm_firmware *fw = nvkm_firmware_mem(memory);
+ struct nvkm_vmm_map map = {
+ .memory = &fw->mem.memory,
+ .offset = offset,
+ .sgl = &fw->mem.sgl,
+ };
+
+ if (WARN_ON(fw->func->type != NVKM_FIRMWARE_IMG_DMA))
+ return -ENOSYS;
+
+ return nvkm_vmm_map(vmm, vma, argv, argc, &map);
+}
+
+static u64
+nvkm_firmware_mem_size(struct nvkm_memory *memory)
+{
+ return sg_dma_len(&nvkm_firmware_mem(memory)->mem.sgl);
+}
+
+static u64
+nvkm_firmware_mem_addr(struct nvkm_memory *memory)
+{
+ return nvkm_firmware_mem(memory)->phys;
+}
+
+static u8
+nvkm_firmware_mem_page(struct nvkm_memory *memory)
+{
+ return PAGE_SHIFT;
+}
+
+static enum nvkm_memory_target
+nvkm_firmware_mem_target(struct nvkm_memory *memory)
+{
+ return NVKM_MEM_TARGET_HOST;
+}
+
+static void *
+nvkm_firmware_mem_dtor(struct nvkm_memory *memory)
+{
+ return NULL;
+}
+
+static const struct nvkm_memory_func
+nvkm_firmware_mem = {
+ .dtor = nvkm_firmware_mem_dtor,
+ .target = nvkm_firmware_mem_target,
+ .page = nvkm_firmware_mem_page,
+ .addr = nvkm_firmware_mem_addr,
+ .size = nvkm_firmware_mem_size,
+ .map = nvkm_firmware_mem_map,
+};
+
+void
+nvkm_firmware_dtor(struct nvkm_firmware *fw)
+{
+ struct nvkm_memory *memory = &fw->mem.memory;
+
+ if (!fw->img)
+ return;
+
+ switch (fw->func->type) {
+ case NVKM_FIRMWARE_IMG_RAM:
+ kfree(fw->img);
+ break;
+ case NVKM_FIRMWARE_IMG_DMA:
+ nvkm_memory_unref(&memory);
+ dma_free_coherent(fw->device->dev, sg_dma_len(&fw->mem.sgl), fw->img, fw->phys);
+ break;
+ default:
+ WARN_ON(1);
+ break;
+ }
+
+ fw->img = NULL;
+}
+
+int
+nvkm_firmware_ctor(const struct nvkm_firmware_func *func, const char *name,
+ struct nvkm_device *device, const void *src, int len, struct nvkm_firmware *fw)
+{
+ fw->func = func;
+ fw->name = name;
+ fw->device = device;
+ fw->len = len;
+
+ switch (fw->func->type) {
+ case NVKM_FIRMWARE_IMG_RAM:
+ fw->img = kmemdup(src, fw->len, GFP_KERNEL);
+ break;
+ case NVKM_FIRMWARE_IMG_DMA: {
+ dma_addr_t addr;
+
+ len = ALIGN(fw->len, PAGE_SIZE);
+
+ fw->img = dma_alloc_coherent(fw->device->dev, len, &addr, GFP_KERNEL);
+ if (fw->img) {
+ memcpy(fw->img, src, fw->len);
+ fw->phys = addr;
+ }
+
+ sg_init_one(&fw->mem.sgl, fw->img, len);
+ sg_dma_address(&fw->mem.sgl) = fw->phys;
+ sg_dma_len(&fw->mem.sgl) = len;
+ }
+ break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ if (!fw->img)
+ return -ENOMEM;
+
+ nvkm_memory_ctor(&nvkm_firmware_mem, &fw->mem.memory);
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/intr.c b/drivers/gpu/drm/nouveau/nvkm/core/intr.c
new file mode 100644
index 000000000000..e20b7ca218c3
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/core/intr.c
@@ -0,0 +1,442 @@
+/*
+ * Copyright 2021 Red Hat 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 <core/intr.h>
+#include <core/device.h>
+#include <core/subdev.h>
+#include <subdev/pci.h>
+#include <subdev/top.h>
+
+static int
+nvkm_intr_xlat(struct nvkm_subdev *subdev, struct nvkm_intr *intr,
+ enum nvkm_intr_type type, int *leaf, u32 *mask)
+{
+ struct nvkm_device *device = subdev->device;
+
+ if (type < NVKM_INTR_VECTOR_0) {
+ if (type == NVKM_INTR_SUBDEV) {
+ const struct nvkm_intr_data *data = intr->data;
+ struct nvkm_top_device *tdev;
+
+ while (data && data->mask) {
+ if (data->type == NVKM_SUBDEV_TOP) {
+ list_for_each_entry(tdev, &device->top->device, head) {
+ if (tdev->intr >= 0 &&
+ tdev->type == subdev->type &&
+ tdev->inst == subdev->inst) {
+ if (data->mask & BIT(tdev->intr)) {
+ *leaf = data->leaf;
+ *mask = BIT(tdev->intr);
+ return 0;
+ }
+ }
+ }
+ } else
+ if (data->type == subdev->type && data->inst == subdev->inst) {
+ *leaf = data->leaf;
+ *mask = data->mask;
+ return 0;
+ }
+
+ data++;
+ }
+ } else {
+ return -ENOSYS;
+ }
+ } else {
+ if (type < intr->leaves * sizeof(*intr->stat) * 8) {
+ *leaf = type / 32;
+ *mask = BIT(type % 32);
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static struct nvkm_intr *
+nvkm_intr_find(struct nvkm_subdev *subdev, enum nvkm_intr_type type, int *leaf, u32 *mask)
+{
+ struct nvkm_intr *intr;
+ int ret;
+
+ list_for_each_entry(intr, &subdev->device->intr.intr, head) {
+ ret = nvkm_intr_xlat(subdev, intr, type, leaf, mask);
+ if (ret == 0)
+ return intr;
+ }
+
+ return NULL;
+}
+
+static void
+nvkm_intr_allow_locked(struct nvkm_intr *intr, int leaf, u32 mask)
+{
+ intr->mask[leaf] |= mask;
+ if (intr->func->allow) {
+ if (intr->func->reset)
+ intr->func->reset(intr, leaf, mask);
+ intr->func->allow(intr, leaf, mask);
+ }
+}
+
+void
+nvkm_intr_allow(struct nvkm_subdev *subdev, enum nvkm_intr_type type)
+{
+ struct nvkm_device *device = subdev->device;
+ struct nvkm_intr *intr;
+ unsigned long flags;
+ int leaf;
+ u32 mask;
+
+ intr = nvkm_intr_find(subdev, type, &leaf, &mask);
+ if (intr) {
+ nvkm_debug(intr->subdev, "intr %d/%08x allowed by %s\n", leaf, mask, subdev->name);
+ spin_lock_irqsave(&device->intr.lock, flags);
+ nvkm_intr_allow_locked(intr, leaf, mask);
+ spin_unlock_irqrestore(&device->intr.lock, flags);
+ }
+}
+
+static void
+nvkm_intr_block_locked(struct nvkm_intr *intr, int leaf, u32 mask)
+{
+ intr->mask[leaf] &= ~mask;
+ if (intr->func->block)
+ intr->func->block(intr, leaf, mask);
+}
+
+void
+nvkm_intr_block(struct nvkm_subdev *subdev, enum nvkm_intr_type type)
+{
+ struct nvkm_device *device = subdev->device;
+ struct nvkm_intr *intr;
+ unsigned long flags;
+ int leaf;
+ u32 mask;
+
+ intr = nvkm_intr_find(subdev, type, &leaf, &mask);
+ if (intr) {
+ nvkm_debug(intr->subdev, "intr %d/%08x blocked by %s\n", leaf, mask, subdev->name);
+ spin_lock_irqsave(&device->intr.lock, flags);
+ nvkm_intr_block_locked(intr, leaf, mask);
+ spin_unlock_irqrestore(&device->intr.lock, flags);
+ }
+}
+
+static void
+nvkm_intr_rearm_locked(struct nvkm_device *device)
+{
+ struct nvkm_intr *intr;
+
+ list_for_each_entry(intr, &device->intr.intr, head)
+ intr->func->rearm(intr);
+}
+
+static void
+nvkm_intr_unarm_locked(struct nvkm_device *device)
+{
+ struct nvkm_intr *intr;
+
+ list_for_each_entry(intr, &device->intr.intr, head)
+ intr->func->unarm(intr);
+}
+
+static irqreturn_t
+nvkm_intr(int irq, void *arg)
+{
+ struct nvkm_device *device = arg;
+ struct nvkm_intr *intr;
+ struct nvkm_inth *inth;
+ irqreturn_t ret = IRQ_NONE;
+ bool pending = false;
+ int prio, leaf;
+
+ /* Disable all top-level interrupt sources, and re-arm MSI interrupts. */
+ spin_lock(&device->intr.lock);
+ if (!device->intr.armed)
+ goto done_unlock;
+
+ nvkm_intr_unarm_locked(device);
+ nvkm_pci_msi_rearm(device);
+
+ /* Fetch pending interrupt masks. */
+ list_for_each_entry(intr, &device->intr.intr, head) {
+ if (intr->func->pending(intr))
+ pending = true;
+ }
+
+ if (!pending)
+ goto done;
+
+ /* Check that GPU is still on the bus by reading NV_PMC_BOOT_0. */
+ if (WARN_ON(nvkm_rd32(device, 0x000000) == 0xffffffff))
+ goto done;
+
+ /* Execute handlers. */
+ for (prio = 0; prio < ARRAY_SIZE(device->intr.prio); prio++) {
+ list_for_each_entry(inth, &device->intr.prio[prio], head) {
+ struct nvkm_intr *intr = inth->intr;
+
+ if (intr->stat[inth->leaf] & inth->mask) {
+ if (atomic_read(&inth->allowed)) {
+ if (intr->func->reset)
+ intr->func->reset(intr, inth->leaf, inth->mask);
+ if (inth->func(inth) == IRQ_HANDLED)
+ ret = IRQ_HANDLED;
+ }
+ }
+ }
+ }
+
+ /* Nothing handled? Some debugging/protection from IRQ storms is in order... */
+ if (ret == IRQ_NONE) {
+ list_for_each_entry(intr, &device->intr.intr, head) {
+ for (leaf = 0; leaf < intr->leaves; leaf++) {
+ if (intr->stat[leaf]) {
+ nvkm_warn(intr->subdev, "intr%d: %08x\n",
+ leaf, intr->stat[leaf]);
+ nvkm_intr_block_locked(intr, leaf, intr->stat[leaf]);
+ }
+ }
+ }
+ }
+
+done:
+ /* Re-enable all top-level interrupt sources. */
+ nvkm_intr_rearm_locked(device);
+done_unlock:
+ spin_unlock(&device->intr.lock);
+ return ret;
+}
+
+int
+nvkm_intr_add(const struct nvkm_intr_func *func, const struct nvkm_intr_data *data,
+ struct nvkm_subdev *subdev, int leaves, struct nvkm_intr *intr)
+{
+ struct nvkm_device *device = subdev->device;
+ int i;
+
+ intr->func = func;
+ intr->data = data;
+ intr->subdev = subdev;
+ intr->leaves = leaves;
+ intr->stat = kcalloc(leaves, sizeof(*intr->stat), GFP_KERNEL);
+ intr->mask = kcalloc(leaves, sizeof(*intr->mask), GFP_KERNEL);
+ if (!intr->stat || !intr->mask) {
+ kfree(intr->stat);
+ return -ENOMEM;
+ }
+
+ if (intr->subdev->debug >= NV_DBG_DEBUG) {
+ for (i = 0; i < intr->leaves; i++)
+ intr->mask[i] = ~0;
+ }
+
+ spin_lock_irq(&device->intr.lock);
+ list_add_tail(&intr->head, &device->intr.intr);
+ spin_unlock_irq(&device->intr.lock);
+ return 0;
+}
+
+static irqreturn_t
+nvkm_intr_subdev(struct nvkm_inth *inth)
+{
+ struct nvkm_subdev *subdev = container_of(inth, typeof(*subdev), inth);
+
+ nvkm_subdev_intr(subdev);
+ return IRQ_HANDLED;
+}
+
+static void
+nvkm_intr_subdev_add_dev(struct nvkm_intr *intr, enum nvkm_subdev_type type, int inst)
+{
+ struct nvkm_subdev *subdev;
+ enum nvkm_intr_prio prio;
+ int ret;
+
+ subdev = nvkm_device_subdev(intr->subdev->device, type, inst);
+ if (!subdev || !subdev->func->intr)
+ return;
+
+ if (type == NVKM_ENGINE_DISP)
+ prio = NVKM_INTR_PRIO_VBLANK;
+ else
+ prio = NVKM_INTR_PRIO_NORMAL;
+
+ ret = nvkm_inth_add(intr, NVKM_INTR_SUBDEV, prio, subdev, nvkm_intr_subdev, &subdev->inth);
+ if (WARN_ON(ret))
+ return;
+
+ nvkm_inth_allow(&subdev->inth);
+}
+
+static void
+nvkm_intr_subdev_add(struct nvkm_intr *intr)
+{
+ const struct nvkm_intr_data *data;
+ struct nvkm_device *device = intr->subdev->device;
+ struct nvkm_top_device *tdev;
+
+ for (data = intr->data; data && data->mask; data++) {
+ if (data->legacy) {
+ if (data->type == NVKM_SUBDEV_TOP) {
+ list_for_each_entry(tdev, &device->top->device, head) {
+ if (tdev->intr < 0 || !(data->mask & BIT(tdev->intr)))
+ continue;
+
+ nvkm_intr_subdev_add_dev(intr, tdev->type, tdev->inst);
+ }
+ } else {
+ nvkm_intr_subdev_add_dev(intr, data->type, data->inst);
+ }
+ }
+ }
+}
+
+void
+nvkm_intr_rearm(struct nvkm_device *device)
+{
+ struct nvkm_intr *intr;
+ int i;
+
+ if (unlikely(!device->intr.legacy_done)) {
+ list_for_each_entry(intr, &device->intr.intr, head)
+ nvkm_intr_subdev_add(intr);
+ device->intr.legacy_done = true;
+ }
+
+ spin_lock_irq(&device->intr.lock);
+ list_for_each_entry(intr, &device->intr.intr, head) {
+ for (i = 0; intr->func->block && i < intr->leaves; i++) {
+ intr->func->block(intr, i, ~0);
+ intr->func->allow(intr, i, intr->mask[i]);
+ }
+ }
+
+ nvkm_intr_rearm_locked(device);
+ device->intr.armed = true;
+ spin_unlock_irq(&device->intr.lock);
+}
+
+void
+nvkm_intr_unarm(struct nvkm_device *device)
+{
+ spin_lock_irq(&device->intr.lock);
+ nvkm_intr_unarm_locked(device);
+ device->intr.armed = false;
+ spin_unlock_irq(&device->intr.lock);
+}
+
+int
+nvkm_intr_install(struct nvkm_device *device)
+{
+ int ret;
+
+ device->intr.irq = device->func->irq(device);
+ if (device->intr.irq < 0)
+ return device->intr.irq;
+
+ ret = request_irq(device->intr.irq, nvkm_intr, IRQF_SHARED, "nvkm", device);
+ if (ret)
+ return ret;
+
+ device->intr.alloc = true;
+ return 0;
+}
+
+void
+nvkm_intr_dtor(struct nvkm_device *device)
+{
+ struct nvkm_intr *intr, *intt;
+
+ list_for_each_entry_safe(intr, intt, &device->intr.intr, head) {
+ list_del(&intr->head);
+ kfree(intr->mask);
+ kfree(intr->stat);
+ }
+
+ if (device->intr.alloc)
+ free_irq(device->intr.irq, device);
+}
+
+void
+nvkm_intr_ctor(struct nvkm_device *device)
+{
+ int i;
+
+ INIT_LIST_HEAD(&device->intr.intr);
+ for (i = 0; i < ARRAY_SIZE(device->intr.prio); i++)
+ INIT_LIST_HEAD(&device->intr.prio[i]);
+
+ spin_lock_init(&device->intr.lock);
+ device->intr.armed = false;
+}
+
+void
+nvkm_inth_block(struct nvkm_inth *inth)
+{
+ if (unlikely(!inth->intr))
+ return;
+
+ atomic_set(&inth->allowed, 0);
+}
+
+void
+nvkm_inth_allow(struct nvkm_inth *inth)
+{
+ struct nvkm_intr *intr = inth->intr;
+ unsigned long flags;
+
+ if (unlikely(!inth->intr))
+ return;
+
+ spin_lock_irqsave(&intr->subdev->device->intr.lock, flags);
+ if (!atomic_xchg(&inth->allowed, 1)) {
+ if ((intr->mask[inth->leaf] & inth->mask) != inth->mask)
+ nvkm_intr_allow_locked(intr, inth->leaf, inth->mask);
+ }
+ spin_unlock_irqrestore(&intr->subdev->device->intr.lock, flags);
+}
+
+int
+nvkm_inth_add(struct nvkm_intr *intr, enum nvkm_intr_type type, enum nvkm_intr_prio prio,
+ struct nvkm_subdev *subdev, nvkm_inth_func func, struct nvkm_inth *inth)
+{
+ struct nvkm_device *device = subdev->device;
+ int ret;
+
+ if (WARN_ON(inth->mask))
+ return -EBUSY;
+
+ ret = nvkm_intr_xlat(subdev, intr, type, &inth->leaf, &inth->mask);
+ if (ret)
+ return ret;
+
+ nvkm_debug(intr->subdev, "intr %d/%08x requested by %s\n",
+ inth->leaf, inth->mask, subdev->name);
+
+ inth->intr = intr;
+ inth->func = func;
+ atomic_set(&inth->allowed, 0);
+ list_add_tail(&inth->head, &device->intr.prio[prio]);
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
index 45f920da89af..0b33287e43a7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
@@ -47,6 +47,26 @@ nvkm_ioctl_nop(struct nvkm_client *client,
return ret;
}
+#include <nvif/class.h>
+
+static int
+nvkm_ioctl_sclass_(struct nvkm_object *object, int index, struct nvkm_oclass *oclass)
+{
+ if ( object->func->uevent &&
+ !object->func->uevent(object, NULL, 0, NULL) && index-- == 0) {
+ oclass->ctor = nvkm_uevent_new;
+ oclass->base.minver = 0;
+ oclass->base.maxver = 0;
+ oclass->base.oclass = NVIF_CLASS_EVENT;
+ return 0;
+ }
+
+ if (object->func->sclass)
+ return object->func->sclass(object, index, oclass);
+
+ return -ENOSYS;
+}
+
static int
nvkm_ioctl_sclass(struct nvkm_client *client,
struct nvkm_object *object, void *data, u32 size)
@@ -64,8 +84,7 @@ nvkm_ioctl_sclass(struct nvkm_client *client,
if (size != args->v0.count * sizeof(args->v0.oclass[0]))
return -EINVAL;
- while (object->func->sclass &&
- object->func->sclass(object, i, &oclass) >= 0) {
+ while (nvkm_ioctl_sclass_(object, i, &oclass) >= 0) {
if (i < args->v0.count) {
args->v0.oclass[i].oclass = oclass.base.oclass;
args->v0.oclass[i].minver = oclass.base.minver;
@@ -100,7 +119,7 @@ nvkm_ioctl_new(struct nvkm_client *client,
} else
return ret;
- if (!parent->func->sclass) {
+ if (!parent->func->sclass && !parent->func->uevent) {
nvif_ioctl(parent, "cannot have children\n");
return -EINVAL;
}
@@ -113,7 +132,7 @@ nvkm_ioctl_new(struct nvkm_client *client,
oclass.object = args->v0.object;
oclass.client = client;
oclass.parent = parent;
- ret = parent->func->sclass(parent, i++, &oclass);
+ ret = nvkm_ioctl_sclass_(parent, i++, &oclass);
if (ret)
return ret;
} while (oclass.base.oclass != args->v0.oclass);
@@ -294,90 +313,6 @@ nvkm_ioctl_unmap(struct nvkm_client *client,
return ret;
}
-static int
-nvkm_ioctl_ntfy_new(struct nvkm_client *client,
- struct nvkm_object *object, void *data, u32 size)
-{
- union {
- struct nvif_ioctl_ntfy_new_v0 v0;
- } *args = data;
- struct nvkm_event *event;
- int ret = -ENOSYS;
-
- nvif_ioctl(object, "ntfy new size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
- nvif_ioctl(object, "ntfy new vers %d event %02x\n",
- args->v0.version, args->v0.event);
- ret = nvkm_object_ntfy(object, args->v0.event, &event);
- if (ret == 0) {
- ret = nvkm_client_notify_new(object, event, data, size);
- if (ret >= 0) {
- args->v0.index = ret;
- ret = 0;
- }
- }
- }
-
- return ret;
-}
-
-static int
-nvkm_ioctl_ntfy_del(struct nvkm_client *client,
- struct nvkm_object *object, void *data, u32 size)
-{
- union {
- struct nvif_ioctl_ntfy_del_v0 v0;
- } *args = data;
- int ret = -ENOSYS;
-
- nvif_ioctl(object, "ntfy del size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
- nvif_ioctl(object, "ntfy del vers %d index %d\n",
- args->v0.version, args->v0.index);
- ret = nvkm_client_notify_del(client, args->v0.index);
- }
-
- return ret;
-}
-
-static int
-nvkm_ioctl_ntfy_get(struct nvkm_client *client,
- struct nvkm_object *object, void *data, u32 size)
-{
- union {
- struct nvif_ioctl_ntfy_get_v0 v0;
- } *args = data;
- int ret = -ENOSYS;
-
- nvif_ioctl(object, "ntfy get size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
- nvif_ioctl(object, "ntfy get vers %d index %d\n",
- args->v0.version, args->v0.index);
- ret = nvkm_client_notify_get(client, args->v0.index);
- }
-
- return ret;
-}
-
-static int
-nvkm_ioctl_ntfy_put(struct nvkm_client *client,
- struct nvkm_object *object, void *data, u32 size)
-{
- union {
- struct nvif_ioctl_ntfy_put_v0 v0;
- } *args = data;
- int ret = -ENOSYS;
-
- nvif_ioctl(object, "ntfy put size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
- nvif_ioctl(object, "ntfy put vers %d index %d\n",
- args->v0.version, args->v0.index);
- ret = nvkm_client_notify_put(client, args->v0.index);
- }
-
- return ret;
-}
-
static struct {
int version;
int (*func)(struct nvkm_client *, struct nvkm_object *, void *, u32);
@@ -392,10 +327,6 @@ nvkm_ioctl_v0[] = {
{ 0x00, nvkm_ioctl_wr },
{ 0x00, nvkm_ioctl_map },
{ 0x00, nvkm_ioctl_unmap },
- { 0x00, nvkm_ioctl_ntfy_new },
- { 0x00, nvkm_ioctl_ntfy_del },
- { 0x00, nvkm_ioctl_ntfy_get },
- { 0x00, nvkm_ioctl_ntfy_put },
};
static int
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/notify.c b/drivers/gpu/drm/nouveau/nvkm/core/notify.c
deleted file mode 100644
index 023610d01458..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/core/notify.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright 2014 Red Hat 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: Ben Skeggs <bskeggs@redhat.com>
- */
-#include <core/notify.h>
-#include <core/event.h>
-
-static inline void
-nvkm_notify_put_locked(struct nvkm_notify *notify)
-{
- if (notify->block++ == 0)
- nvkm_event_put(notify->event, notify->types, notify->index);
-}
-
-void
-nvkm_notify_put(struct nvkm_notify *notify)
-{
- struct nvkm_event *event = notify->event;
- unsigned long flags;
- if (likely(event) &&
- test_and_clear_bit(NVKM_NOTIFY_USER, &notify->flags)) {
- spin_lock_irqsave(&event->refs_lock, flags);
- nvkm_notify_put_locked(notify);
- spin_unlock_irqrestore(&event->refs_lock, flags);
- if (test_bit(NVKM_NOTIFY_WORK, &notify->flags))
- flush_work(&notify->work);
- }
-}
-
-static inline void
-nvkm_notify_get_locked(struct nvkm_notify *notify)
-{
- if (--notify->block == 0)
- nvkm_event_get(notify->event, notify->types, notify->index);
-}
-
-void
-nvkm_notify_get(struct nvkm_notify *notify)
-{
- struct nvkm_event *event = notify->event;
- unsigned long flags;
- if (likely(event) &&
- !test_and_set_bit(NVKM_NOTIFY_USER, &notify->flags)) {
- spin_lock_irqsave(&event->refs_lock, flags);
- nvkm_notify_get_locked(notify);
- spin_unlock_irqrestore(&event->refs_lock, flags);
- }
-}
-
-static inline void
-nvkm_notify_func(struct nvkm_notify *notify)
-{
- struct nvkm_event *event = notify->event;
- int ret = notify->func(notify);
- unsigned long flags;
- if ((ret == NVKM_NOTIFY_KEEP) ||
- !test_and_clear_bit(NVKM_NOTIFY_USER, &notify->flags)) {
- spin_lock_irqsave(&event->refs_lock, flags);
- nvkm_notify_get_locked(notify);
- spin_unlock_irqrestore(&event->refs_lock, flags);
- }
-}
-
-static void
-nvkm_notify_work(struct work_struct *work)
-{
- struct nvkm_notify *notify = container_of(work, typeof(*notify), work);
- nvkm_notify_func(notify);
-}
-
-void
-nvkm_notify_send(struct nvkm_notify *notify, void *data, u32 size)
-{
- struct nvkm_event *event = notify->event;
- unsigned long flags;
-
- assert_spin_locked(&event->list_lock);
- BUG_ON(size != notify->size);
-
- spin_lock_irqsave(&event->refs_lock, flags);
- if (notify->block) {
- spin_unlock_irqrestore(&event->refs_lock, flags);
- return;
- }
- nvkm_notify_put_locked(notify);
- spin_unlock_irqrestore(&event->refs_lock, flags);
-
- if (test_bit(NVKM_NOTIFY_WORK, &notify->flags)) {
- memcpy((void *)notify->data, data, size);
- schedule_work(&notify->work);
- } else {
- notify->data = data;
- nvkm_notify_func(notify);
- notify->data = NULL;
- }
-}
-
-void
-nvkm_notify_fini(struct nvkm_notify *notify)
-{
- unsigned long flags;
- if (notify->event) {
- nvkm_notify_put(notify);
- spin_lock_irqsave(&notify->event->list_lock, flags);
- list_del(&notify->head);
- spin_unlock_irqrestore(&notify->event->list_lock, flags);
- kfree((void *)notify->data);
- notify->event = NULL;
- }
-}
-
-int
-nvkm_notify_init(struct nvkm_object *object, struct nvkm_event *event,
- int (*func)(struct nvkm_notify *), bool work,
- void *data, u32 size, u32 reply,
- struct nvkm_notify *notify)
-{
- unsigned long flags;
- int ret = -ENODEV;
- if ((notify->event = event), event->refs) {
- ret = event->func->ctor(object, data, size, notify);
- if (ret == 0 && (ret = -EINVAL, notify->size == reply)) {
- notify->flags = 0;
- notify->block = 1;
- notify->func = func;
- notify->data = NULL;
- if (ret = 0, work) {
- INIT_WORK(&notify->work, nvkm_notify_work);
- set_bit(NVKM_NOTIFY_WORK, &notify->flags);
- notify->data = kmalloc(reply, GFP_KERNEL);
- if (!notify->data)
- ret = -ENOMEM;
- }
- }
- if (ret == 0) {
- spin_lock_irqsave(&event->list_lock, flags);
- list_add_tail(&notify->head, &event->list);
- spin_unlock_irqrestore(&event->list_lock, flags);
- }
- }
- if (ret)
- notify->event = NULL;
- return ret;
-}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c
index 16299837a296..3385528da650 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c
@@ -47,7 +47,12 @@ nvkm_oproxy_map(struct nvkm_object *object, void *argv, u32 argc,
static int
nvkm_oproxy_unmap(struct nvkm_object *object)
{
- return nvkm_object_unmap(nvkm_oproxy(object)->object);
+ struct nvkm_oproxy *oproxy = nvkm_oproxy(object);
+
+ if (unlikely(!oproxy->object))
+ return 0;
+
+ return nvkm_object_unmap(oproxy->object);
}
static int
@@ -106,6 +111,18 @@ nvkm_oproxy_sclass(struct nvkm_object *object, int index,
}
static int
+nvkm_oproxy_uevent(struct nvkm_object *object, void *argv, u32 argc,
+ struct nvkm_uevent *uevent)
+{
+ struct nvkm_oproxy *oproxy = nvkm_oproxy(object);
+
+ if (!oproxy->object->func->uevent)
+ return -ENOSYS;
+
+ return oproxy->object->func->uevent(oproxy->object, argv, argc, uevent);
+}
+
+static int
nvkm_oproxy_fini(struct nvkm_object *object, bool suspend)
{
struct nvkm_oproxy *oproxy = nvkm_oproxy(object);
@@ -188,6 +205,7 @@ nvkm_oproxy_func = {
.wr32 = nvkm_oproxy_wr32,
.bind = nvkm_oproxy_bind,
.sclass = nvkm_oproxy_sclass,
+ .uevent = nvkm_oproxy_uevent,
};
void
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/subdev.c b/drivers/gpu/drm/nouveau/nvkm/core/subdev.c
index a74b7acb6832..6c20e827a069 100644
--- a/drivers/gpu/drm/nouveau/nvkm/core/subdev.c
+++ b/drivers/gpu/drm/nouveau/nvkm/core/subdev.c
@@ -54,7 +54,7 @@ int
nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend)
{
struct nvkm_device *device = subdev->device;
- const char *action = suspend ? "suspend" : "fini";
+ const char *action = suspend ? "suspend" : subdev->use.enabled ? "fini" : "reset";
s64 time;
nvkm_trace(subdev, "%s running...\n", action);
@@ -68,6 +68,7 @@ nvkm_subdev_fini(struct nvkm_subdev *subdev, bool suspend)
return ret;
}
}
+ subdev->use.enabled = false;
nvkm_mc_reset(device, subdev->type, subdev->inst);
@@ -97,30 +98,49 @@ nvkm_subdev_preinit(struct nvkm_subdev *subdev)
return 0;
}
-int
-nvkm_subdev_init(struct nvkm_subdev *subdev)
+static int
+nvkm_subdev_oneinit_(struct nvkm_subdev *subdev)
{
s64 time;
int ret;
- nvkm_trace(subdev, "init running...\n");
+ if (!subdev->func->oneinit || subdev->oneinit)
+ return 0;
+
+ nvkm_trace(subdev, "one-time init running...\n");
time = ktime_to_us(ktime_get());
+ ret = subdev->func->oneinit(subdev);
+ if (ret) {
+ nvkm_error(subdev, "one-time init failed, %d\n", ret);
+ return ret;
+ }
- if (subdev->func->oneinit && !subdev->oneinit) {
- s64 time;
- nvkm_trace(subdev, "one-time init running...\n");
- time = ktime_to_us(ktime_get());
- ret = subdev->func->oneinit(subdev);
- if (ret) {
- nvkm_error(subdev, "one-time init failed, %d\n", ret);
- return ret;
- }
+ subdev->oneinit = true;
+ time = ktime_to_us(ktime_get()) - time;
+ nvkm_trace(subdev, "one-time init completed in %lldus\n", time);
+ return 0;
+}
- subdev->oneinit = true;
- time = ktime_to_us(ktime_get()) - time;
- nvkm_trace(subdev, "one-time init completed in %lldus\n", time);
+static int
+nvkm_subdev_init_(struct nvkm_subdev *subdev)
+{
+ s64 time;
+ int ret;
+
+ if (subdev->use.enabled) {
+ nvkm_trace(subdev, "init skipped, already running\n");
+ return 0;
}
+ nvkm_trace(subdev, "init running...\n");
+ time = ktime_to_us(ktime_get());
+
+ ret = nvkm_subdev_oneinit_(subdev);
+ if (ret)
+ return ret;
+
+ subdev->use.enabled = true;
+
if (subdev->func->init) {
ret = subdev->func->init(subdev);
if (ret) {
@@ -134,6 +154,64 @@ nvkm_subdev_init(struct nvkm_subdev *subdev)
return 0;
}
+int
+nvkm_subdev_init(struct nvkm_subdev *subdev)
+{
+ int ret;
+
+ mutex_lock(&subdev->use.mutex);
+ if (refcount_read(&subdev->use.refcount) == 0) {
+ nvkm_trace(subdev, "init skipped, no users\n");
+ mutex_unlock(&subdev->use.mutex);
+ return 0;
+ }
+
+ ret = nvkm_subdev_init_(subdev);
+ mutex_unlock(&subdev->use.mutex);
+ return ret;
+}
+
+int
+nvkm_subdev_oneinit(struct nvkm_subdev *subdev)
+{
+ int ret;
+
+ mutex_lock(&subdev->use.mutex);
+ ret = nvkm_subdev_oneinit_(subdev);
+ mutex_unlock(&subdev->use.mutex);
+ return ret;
+}
+
+void
+nvkm_subdev_unref(struct nvkm_subdev *subdev)
+{
+ if (refcount_dec_and_mutex_lock(&subdev->use.refcount, &subdev->use.mutex)) {
+ nvkm_subdev_fini(subdev, false);
+ mutex_unlock(&subdev->use.mutex);
+ }
+}
+
+int
+nvkm_subdev_ref(struct nvkm_subdev *subdev)
+{
+ int ret;
+
+ if (subdev && !refcount_inc_not_zero(&subdev->use.refcount)) {
+ mutex_lock(&subdev->use.mutex);
+ if (!refcount_inc_not_zero(&subdev->use.refcount)) {
+ if ((ret = nvkm_subdev_init_(subdev))) {
+ mutex_unlock(&subdev->use.mutex);
+ return ret;
+ }
+
+ refcount_set(&subdev->use.refcount, 1);
+ }
+ mutex_unlock(&subdev->use.mutex);
+ }
+
+ return 0;
+}
+
void
nvkm_subdev_del(struct nvkm_subdev **psubdev)
{
@@ -146,6 +224,7 @@ nvkm_subdev_del(struct nvkm_subdev **psubdev)
list_del(&subdev->head);
if (subdev->func->dtor)
*psubdev = subdev->func->dtor(subdev);
+ mutex_destroy(&subdev->use.mutex);
time = ktime_to_us(ktime_get()) - time;
nvkm_trace(subdev, "destroy completed in %lldus\n", time);
kfree(*psubdev);
@@ -167,8 +246,8 @@ nvkm_subdev_disable(struct nvkm_device *device, enum nvkm_subdev_type type, int
}
void
-nvkm_subdev_ctor(const struct nvkm_subdev_func *func, struct nvkm_device *device,
- enum nvkm_subdev_type type, int inst, struct nvkm_subdev *subdev)
+__nvkm_subdev_ctor(const struct nvkm_subdev_func *func, struct nvkm_device *device,
+ enum nvkm_subdev_type type, int inst, struct nvkm_subdev *subdev)
{
subdev->func = func;
subdev->device = device;
@@ -180,6 +259,8 @@ nvkm_subdev_ctor(const struct nvkm_subdev_func *func, struct nvkm_device *device
else
strscpy(subdev->name, nvkm_subdev_type[type], sizeof(subdev->name));
subdev->debug = nvkm_dbgopt(device->dbgopt, subdev->name);
+
+ refcount_set(&subdev->use.refcount, 1);
list_add_tail(&subdev->head, &device->subdev);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/core/uevent.c b/drivers/gpu/drm/nouveau/nvkm/core/uevent.c
new file mode 100644
index 000000000000..ba9d9edaec75
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/core/uevent.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2021 Red Hat 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.
+ */
+#define nvkm_uevent(p) container_of((p), struct nvkm_uevent, object)
+#include <core/event.h>
+#include <core/client.h>
+
+#include <nvif/if000e.h>
+
+struct nvkm_uevent {
+ struct nvkm_object object;
+ struct nvkm_object *parent;
+ nvkm_uevent_func func;
+ bool wait;
+
+ struct nvkm_event_ntfy ntfy;
+ atomic_t allowed;
+};
+
+static int
+nvkm_uevent_mthd_block(struct nvkm_uevent *uevent, union nvif_event_block_args *args, u32 argc)
+{
+ if (argc != sizeof(args->vn))
+ return -ENOSYS;
+
+ nvkm_event_ntfy_block(&uevent->ntfy);
+ atomic_set(&uevent->allowed, 0);
+ return 0;
+}
+
+static int
+nvkm_uevent_mthd_allow(struct nvkm_uevent *uevent, union nvif_event_allow_args *args, u32 argc)
+{
+ if (argc != sizeof(args->vn))
+ return -ENOSYS;
+
+ nvkm_event_ntfy_allow(&uevent->ntfy);
+ atomic_set(&uevent->allowed, 1);
+ return 0;
+}
+
+static int
+nvkm_uevent_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc)
+{
+ struct nvkm_uevent *uevent = nvkm_uevent(object);
+
+ switch (mthd) {
+ case NVIF_EVENT_V0_ALLOW: return nvkm_uevent_mthd_allow(uevent, argv, argc);
+ case NVIF_EVENT_V0_BLOCK: return nvkm_uevent_mthd_block(uevent, argv, argc);
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static int
+nvkm_uevent_fini(struct nvkm_object *object, bool suspend)
+{
+ struct nvkm_uevent *uevent = nvkm_uevent(object);
+
+ nvkm_event_ntfy_block(&uevent->ntfy);
+ return 0;
+}
+
+static int
+nvkm_uevent_init(struct nvkm_object *object)
+{
+ struct nvkm_uevent *uevent = nvkm_uevent(object);
+
+ if (atomic_read(&uevent->allowed))
+ nvkm_event_ntfy_allow(&uevent->ntfy);
+
+ return 0;
+}
+
+static void *
+nvkm_uevent_dtor(struct nvkm_object *object)
+{
+ struct nvkm_uevent *uevent = nvkm_uevent(object);
+
+ nvkm_event_ntfy_del(&uevent->ntfy);
+ return uevent;
+}
+
+static const struct nvkm_object_func
+nvkm_uevent = {
+ .dtor = nvkm_uevent_dtor,
+ .init = nvkm_uevent_init,
+ .fini = nvkm_uevent_fini,
+ .mthd = nvkm_uevent_mthd,
+};
+
+static int
+nvkm_uevent_ntfy(struct nvkm_event_ntfy *ntfy, u32 bits)
+{
+ struct nvkm_uevent *uevent = container_of(ntfy, typeof(*uevent), ntfy);
+ struct nvkm_client *client = uevent->object.client;
+
+ if (uevent->func)
+ return uevent->func(uevent->parent, uevent->object.token, bits);
+
+ return client->event(uevent->object.token, NULL, 0);
+}
+
+int
+nvkm_uevent_add(struct nvkm_uevent *uevent, struct nvkm_event *event, int id, u32 bits,
+ nvkm_uevent_func func)
+{
+ if (WARN_ON(uevent->func))
+ return -EBUSY;
+
+ nvkm_event_ntfy_add(event, id, bits, uevent->wait, nvkm_uevent_ntfy, &uevent->ntfy);
+ uevent->func = func;
+ return 0;
+}
+
+int
+nvkm_uevent_new(const struct nvkm_oclass *oclass, void *argv, u32 argc,
+ struct nvkm_object **pobject)
+{
+ struct nvkm_object *parent = oclass->parent;
+ struct nvkm_uevent *uevent;
+ union nvif_event_args *args = argv;
+
+ if (argc < sizeof(args->v0) || args->v0.version != 0)
+ return -ENOSYS;
+
+ if (!(uevent = kzalloc(sizeof(*uevent), GFP_KERNEL)))
+ return -ENOMEM;
+ *pobject = &uevent->object;
+
+ nvkm_object_ctor(&nvkm_uevent, oclass, &uevent->object);
+ uevent->parent = parent;
+ uevent->func = NULL;
+ uevent->wait = args->v0.wait;
+ uevent->ntfy.event = NULL;
+ return parent->func->uevent(parent, &args->v0.data, argc - sizeof(args->v0), uevent);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild
index ba88613e1e46..8bf1635ffabc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/Kbuild
@@ -8,3 +8,5 @@ nvkm-y += nvkm/engine/ce/gp100.o
nvkm-y += nvkm/engine/ce/gp102.o
nvkm-y += nvkm/engine/ce/gv100.o
nvkm-y += nvkm/engine/ce/tu102.o
+nvkm-y += nvkm/engine/ce/ga100.o
+nvkm-y += nvkm/engine/ce/ga102.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga100.c b/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga100.c
new file mode 100644
index 000000000000..6648ed62daa6
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga100.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2021 Red Hat 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 "priv.h"
+
+#include <subdev/vfn.h>
+
+#include <nvif/class.h>
+
+static irqreturn_t
+ga100_ce_intr(struct nvkm_inth *inth)
+{
+ struct nvkm_subdev *subdev = container_of(inth, typeof(*subdev), inth);
+
+ /*TODO*/
+ nvkm_error(subdev, "intr\n");
+ return IRQ_NONE;
+}
+
+int
+ga100_ce_fini(struct nvkm_engine *engine, bool suspend)
+{
+ nvkm_inth_block(&engine->subdev.inth);
+ return 0;
+}
+
+int
+ga100_ce_init(struct nvkm_engine *engine)
+{
+ nvkm_inth_allow(&engine->subdev.inth);
+ return 0;
+}
+
+int
+ga100_ce_oneinit(struct nvkm_engine *engine)
+{
+ struct nvkm_subdev *subdev = &engine->subdev;
+ struct nvkm_device *device = subdev->device;
+ u32 vector;
+
+ vector = nvkm_rd32(device, 0x10442c + (subdev->inst * 0x80)) & 0x00000fff;
+
+ return nvkm_inth_add(&device->vfn->intr, vector, NVKM_INTR_PRIO_NORMAL,
+ subdev, ga100_ce_intr, &subdev->inth);
+}
+
+static const struct nvkm_engine_func
+ga100_ce = {
+ .oneinit = ga100_ce_oneinit,
+ .init = ga100_ce_init,
+ .fini = ga100_ce_fini,
+ .cclass = &gv100_ce_cclass,
+ .sclass = {
+ { -1, -1, AMPERE_DMA_COPY_A },
+ {}
+ }
+};
+
+int
+ga100_ce_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
+ struct nvkm_engine **pengine)
+{
+ return nvkm_engine_new_(&ga100_ce, device, type, inst, true, pengine);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/usergv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga102.c
index 3dc3b8b312de..9f3448ad625f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/usergv100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/ga102.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 Red Hat Inc.
+ * Copyright 2021 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -19,27 +19,26 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "user.h"
+#include "priv.h"
-static int
-gv100_fifo_user_map(struct nvkm_object *object, void *argv, u32 argc,
- enum nvkm_object_map *type, u64 *addr, u64 *size)
-{
- struct nvkm_device *device = object->engine->subdev.device;
- *addr = 0x810000 + device->func->resource_addr(device, 0);
- *size = 0x010000;
- *type = NVKM_OBJECT_MAP_IO;
- return 0;
-}
+#include <nvif/class.h>
-static const struct nvkm_object_func
-gv100_fifo_user = {
- .map = gv100_fifo_user_map,
+static const struct nvkm_engine_func
+ga102_ce = {
+ .oneinit = ga100_ce_oneinit,
+ .init = ga100_ce_init,
+ .fini = ga100_ce_fini,
+ .cclass = &gv100_ce_cclass,
+ .sclass = {
+ { -1, -1, AMPERE_DMA_COPY_A },
+ { -1, -1, AMPERE_DMA_COPY_B },
+ {}
+ }
};
int
-gv100_fifo_user_new(const struct nvkm_oclass *oclass, void *argv, u32 argc,
- struct nvkm_object **pobject)
+ga102_ce_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
+ struct nvkm_engine **pengine)
{
- return nvkm_object_new_(&gv100_fifo_user, oclass, argv, argc, pobject);
+ return nvkm_engine_new_(&ga102_ce, device, type, inst, true, pengine);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c
index 09a112af2f89..c9bf6305c3ec 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/gt215.c
@@ -40,7 +40,7 @@ gt215_ce_isr_error_name[] = {
};
void
-gt215_ce_intr(struct nvkm_falcon *ce, struct nvkm_fifo_chan *chan)
+gt215_ce_intr(struct nvkm_falcon *ce, struct nvkm_chan *chan)
{
struct nvkm_subdev *subdev = &ce->engine.subdev;
struct nvkm_device *device = subdev->device;
@@ -55,9 +55,9 @@ gt215_ce_intr(struct nvkm_falcon *ce, struct nvkm_fifo_chan *chan)
nvkm_error(subdev, "DISPATCH_ERROR %04x [%s] ch %d [%010llx %s] "
"subc %d mthd %04x data %08x\n", ssta,
- en ? en->name : "", chan ? chan->chid : -1,
+ en ? en->name : "", chan ? chan->id : -1,
chan ? chan->inst->addr : 0,
- chan ? chan->object.client->name : "unknown",
+ chan ? chan->name : "unknown",
subc, mthd, data);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h
index cd53b93664d6..c4c046916fa6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/ce/priv.h
@@ -8,4 +8,8 @@ void gk104_ce_intr(struct nvkm_engine *);
void gp100_ce_intr(struct nvkm_engine *);
extern const struct nvkm_object_func gv100_ce_cclass;
+
+int ga100_ce_oneinit(struct nvkm_engine *);
+int ga100_ce_init(struct nvkm_engine *);
+int ga100_ce_fini(struct nvkm_engine *, bool);
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c
index be2a7181dc15..caca4f639895 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/cipher/g84.c
@@ -81,8 +81,7 @@ g84_cipher_intr(struct nvkm_engine *cipher)
{
struct nvkm_subdev *subdev = &cipher->subdev;
struct nvkm_device *device = subdev->device;
- struct nvkm_fifo *fifo = device->fifo;
- struct nvkm_fifo_chan *chan;
+ struct nvkm_chan *chan;
u32 stat = nvkm_rd32(device, 0x102130);
u32 mthd = nvkm_rd32(device, 0x102190);
u32 data = nvkm_rd32(device, 0x102194);
@@ -90,16 +89,16 @@ g84_cipher_intr(struct nvkm_engine *cipher)
unsigned long flags;
char msg[128];
- chan = nvkm_fifo_chan_inst(fifo, (u64)inst << 12, &flags);
+ chan = nvkm_chan_get_inst(cipher, (u64)inst << 12, &flags);
if (stat) {
nvkm_snprintbf(msg, sizeof(msg), g84_cipher_intr_mask, stat);
nvkm_error(subdev, "%08x [%s] ch %d [%010llx %s] "
"mthd %04x data %08x\n", stat, msg,
- chan ? chan->chid : -1, (u64)inst << 12,
- chan ? chan->object.client->name : "unknown",
+ chan ? chan->id : -1, (u64)inst << 12,
+ chan ? chan->name : "unknown",
mthd, data);
}
- nvkm_fifo_chan_put(fifo, flags, &chan);
+ nvkm_chan_put(&chan, flags);
nvkm_wr32(device, 0x102130, stat);
nvkm_wr32(device, 0x10200c, 0x10);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
index d8cf71fb0512..364fea320cb3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
@@ -1095,7 +1095,7 @@ nv98_chipset = {
.volt = { 0x00000001, nv40_volt_new },
.disp = { 0x00000001, g94_disp_new },
.dma = { 0x00000001, nv50_dma_new },
- .fifo = { 0x00000001, g84_fifo_new },
+ .fifo = { 0x00000001, g98_fifo_new },
.gr = { 0x00000001, g84_gr_new },
.mspdec = { 0x00000001, g98_mspdec_new },
.msppp = { 0x00000001, g98_msppp_new },
@@ -1161,7 +1161,7 @@ nva3_chipset = {
.ce = { 0x00000001, gt215_ce_new },
.disp = { 0x00000001, gt215_disp_new },
.dma = { 0x00000001, nv50_dma_new },
- .fifo = { 0x00000001, g84_fifo_new },
+ .fifo = { 0x00000001, g98_fifo_new },
.gr = { 0x00000001, gt215_gr_new },
.mpeg = { 0x00000001, g84_mpeg_new },
.mspdec = { 0x00000001, gt215_mspdec_new },
@@ -1195,7 +1195,7 @@ nva5_chipset = {
.ce = { 0x00000001, gt215_ce_new },
.disp = { 0x00000001, gt215_disp_new },
.dma = { 0x00000001, nv50_dma_new },
- .fifo = { 0x00000001, g84_fifo_new },
+ .fifo = { 0x00000001, g98_fifo_new },
.gr = { 0x00000001, gt215_gr_new },
.mspdec = { 0x00000001, gt215_mspdec_new },
.msppp = { 0x00000001, gt215_msppp_new },
@@ -1228,7 +1228,7 @@ nva8_chipset = {
.ce = { 0x00000001, gt215_ce_new },
.disp = { 0x00000001, gt215_disp_new },
.dma = { 0x00000001, nv50_dma_new },
- .fifo = { 0x00000001, g84_fifo_new },
+ .fifo = { 0x00000001, g98_fifo_new },
.gr = { 0x00000001, gt215_gr_new },
.mspdec = { 0x00000001, gt215_mspdec_new },
.msppp = { 0x00000001, gt215_msppp_new },
@@ -1259,7 +1259,7 @@ nvaa_chipset = {
.volt = { 0x00000001, nv40_volt_new },
.disp = { 0x00000001, mcp77_disp_new },
.dma = { 0x00000001, nv50_dma_new },
- .fifo = { 0x00000001, g84_fifo_new },
+ .fifo = { 0x00000001, g98_fifo_new },
.gr = { 0x00000001, gt200_gr_new },
.mspdec = { 0x00000001, g98_mspdec_new },
.msppp = { 0x00000001, g98_msppp_new },
@@ -1291,7 +1291,7 @@ nvac_chipset = {
.volt = { 0x00000001, nv40_volt_new },
.disp = { 0x00000001, mcp77_disp_new },
.dma = { 0x00000001, nv50_dma_new },
- .fifo = { 0x00000001, g84_fifo_new },
+ .fifo = { 0x00000001, g98_fifo_new },
.gr = { 0x00000001, mcp79_gr_new },
.mspdec = { 0x00000001, g98_mspdec_new },
.msppp = { 0x00000001, g98_msppp_new },
@@ -1325,7 +1325,7 @@ nvaf_chipset = {
.ce = { 0x00000001, gt215_ce_new },
.disp = { 0x00000001, mcp89_disp_new },
.dma = { 0x00000001, nv50_dma_new },
- .fifo = { 0x00000001, g84_fifo_new },
+ .fifo = { 0x00000001, g98_fifo_new },
.gr = { 0x00000001, mcp89_gr_new },
.mspdec = { 0x00000001, gt215_mspdec_new },
.msppp = { 0x00000001, gt215_msppp_new },
@@ -2130,7 +2130,7 @@ nv12b_chipset = {
.volt = { 0x00000001, gm20b_volt_new },
.ce = { 0x00000004, gm200_ce_new },
.dma = { 0x00000001, gf119_dma_new },
- .fifo = { 0x00000001, gm20b_fifo_new },
+ .fifo = { 0x00000001, gm200_fifo_new },
.gr = { 0x00000001, gm20b_gr_new },
.sw = { 0x00000001, gf100_sw_new },
};
@@ -2356,7 +2356,7 @@ nv13b_chipset = {
.top = { 0x00000001, gk104_top_new },
.ce = { 0x00000001, gp100_ce_new },
.dma = { 0x00000001, gf119_dma_new },
- .fifo = { 0x00000001, gp10b_fifo_new },
+ .fifo = { 0x00000001, gp100_fifo_new },
.gr = { 0x00000001, gp10b_gr_new },
.sw = { 0x00000001, gf100_sw_new },
};
@@ -2364,7 +2364,7 @@ nv13b_chipset = {
static const struct nvkm_device_chip
nv140_chipset = {
.name = "GV100",
- .acr = { 0x00000001, gp108_acr_new },
+ .acr = { 0x00000001, gv100_acr_new },
.bar = { 0x00000001, gm107_bar_new },
.bios = { 0x00000001, nvkm_bios_new },
.bus = { 0x00000001, gf100_bus_new },
@@ -2385,6 +2385,7 @@ nv140_chipset = {
.therm = { 0x00000001, gp100_therm_new },
.timer = { 0x00000001, gk20a_timer_new },
.top = { 0x00000001, gk104_top_new },
+ .vfn = { 0x00000001, gv100_vfn_new },
.ce = { 0x000001ff, gv100_ce_new },
.disp = { 0x00000001, gv100_disp_new },
.dma = { 0x00000001, gv100_dma_new },
@@ -2411,7 +2412,7 @@ nv162_chipset = {
.i2c = { 0x00000001, gm200_i2c_new },
.imem = { 0x00000001, nv50_instmem_new },
.ltc = { 0x00000001, gp102_ltc_new },
- .mc = { 0x00000001, tu102_mc_new },
+ .mc = { 0x00000001, gp100_mc_new },
.mmu = { 0x00000001, tu102_mmu_new },
.pci = { 0x00000001, gp100_pci_new },
.pmu = { 0x00000001, gp102_pmu_new },
@@ -2419,6 +2420,7 @@ nv162_chipset = {
.therm = { 0x00000001, gp100_therm_new },
.timer = { 0x00000001, gk20a_timer_new },
.top = { 0x00000001, gk104_top_new },
+ .vfn = { 0x00000001, tu102_vfn_new },
.ce = { 0x0000001f, tu102_ce_new },
.disp = { 0x00000001, tu102_disp_new },
.dma = { 0x00000001, gv100_dma_new },
@@ -2445,7 +2447,7 @@ nv164_chipset = {
.i2c = { 0x00000001, gm200_i2c_new },
.imem = { 0x00000001, nv50_instmem_new },
.ltc = { 0x00000001, gp102_ltc_new },
- .mc = { 0x00000001, tu102_mc_new },
+ .mc = { 0x00000001, gp100_mc_new },
.mmu = { 0x00000001, tu102_mmu_new },
.pci = { 0x00000001, gp100_pci_new },
.pmu = { 0x00000001, gp102_pmu_new },
@@ -2453,6 +2455,7 @@ nv164_chipset = {
.therm = { 0x00000001, gp100_therm_new },
.timer = { 0x00000001, gk20a_timer_new },
.top = { 0x00000001, gk104_top_new },
+ .vfn = { 0x00000001, tu102_vfn_new },
.ce = { 0x0000001f, tu102_ce_new },
.disp = { 0x00000001, tu102_disp_new },
.dma = { 0x00000001, gv100_dma_new },
@@ -2479,7 +2482,7 @@ nv166_chipset = {
.i2c = { 0x00000001, gm200_i2c_new },
.imem = { 0x00000001, nv50_instmem_new },
.ltc = { 0x00000001, gp102_ltc_new },
- .mc = { 0x00000001, tu102_mc_new },
+ .mc = { 0x00000001, gp100_mc_new },
.mmu = { 0x00000001, tu102_mmu_new },
.pci = { 0x00000001, gp100_pci_new },
.pmu = { 0x00000001, gp102_pmu_new },
@@ -2487,6 +2490,7 @@ nv166_chipset = {
.therm = { 0x00000001, gp100_therm_new },
.timer = { 0x00000001, gk20a_timer_new },
.top = { 0x00000001, gk104_top_new },
+ .vfn = { 0x00000001, tu102_vfn_new },
.ce = { 0x0000001f, tu102_ce_new },
.disp = { 0x00000001, tu102_disp_new },
.dma = { 0x00000001, gv100_dma_new },
@@ -2513,7 +2517,7 @@ nv167_chipset = {
.i2c = { 0x00000001, gm200_i2c_new },
.imem = { 0x00000001, nv50_instmem_new },
.ltc = { 0x00000001, gp102_ltc_new },
- .mc = { 0x00000001, tu102_mc_new },
+ .mc = { 0x00000001, gp100_mc_new },
.mmu = { 0x00000001, tu102_mmu_new },
.pci = { 0x00000001, gp100_pci_new },
.pmu = { 0x00000001, gp102_pmu_new },
@@ -2521,6 +2525,7 @@ nv167_chipset = {
.therm = { 0x00000001, gp100_therm_new },
.timer = { 0x00000001, gk20a_timer_new },
.top = { 0x00000001, gk104_top_new },
+ .vfn = { 0x00000001, tu102_vfn_new },
.ce = { 0x0000001f, tu102_ce_new },
.disp = { 0x00000001, tu102_disp_new },
.dma = { 0x00000001, gv100_dma_new },
@@ -2547,7 +2552,7 @@ nv168_chipset = {
.i2c = { 0x00000001, gm200_i2c_new },
.imem = { 0x00000001, nv50_instmem_new },
.ltc = { 0x00000001, gp102_ltc_new },
- .mc = { 0x00000001, tu102_mc_new },
+ .mc = { 0x00000001, gp100_mc_new },
.mmu = { 0x00000001, tu102_mmu_new },
.pci = { 0x00000001, gp100_pci_new },
.pmu = { 0x00000001, gp102_pmu_new },
@@ -2555,6 +2560,7 @@ nv168_chipset = {
.therm = { 0x00000001, gp100_therm_new },
.timer = { 0x00000001, gk20a_timer_new },
.top = { 0x00000001, gk104_top_new },
+ .vfn = { 0x00000001, tu102_vfn_new },
.ce = { 0x0000001f, tu102_ce_new },
.disp = { 0x00000001, tu102_disp_new },
.dma = { 0x00000001, gv100_dma_new },
@@ -2571,6 +2577,7 @@ nv170_chipset = {
.bar = { 0x00000001, tu102_bar_new },
.bios = { 0x00000001, nvkm_bios_new },
.devinit = { 0x00000001, ga100_devinit_new },
+ .fault = { 0x00000001, tu102_fault_new },
.fb = { 0x00000001, ga100_fb_new },
.gpio = { 0x00000001, gk104_gpio_new },
.i2c = { 0x00000001, gm200_i2c_new },
@@ -2581,111 +2588,159 @@ nv170_chipset = {
.privring = { 0x00000001, gm200_privring_new },
.timer = { 0x00000001, gk20a_timer_new },
.top = { 0x00000001, ga100_top_new },
+ .vfn = { 0x00000001, ga100_vfn_new },
+ .ce = { 0x000003ff, ga100_ce_new },
+ .fifo = { 0x00000001, ga100_fifo_new },
};
static const struct nvkm_device_chip
nv172_chipset = {
.name = "GA102",
+ .acr = { 0x00000001, ga102_acr_new },
.bar = { 0x00000001, tu102_bar_new },
.bios = { 0x00000001, nvkm_bios_new },
.devinit = { 0x00000001, ga100_devinit_new },
+ .fault = { 0x00000001, tu102_fault_new },
.fb = { 0x00000001, ga102_fb_new },
.gpio = { 0x00000001, ga102_gpio_new },
+ .gsp = { 0x00000001, ga102_gsp_new },
.i2c = { 0x00000001, gm200_i2c_new },
.imem = { 0x00000001, nv50_instmem_new },
+ .ltc = { 0x00000001, ga102_ltc_new },
.mc = { 0x00000001, ga100_mc_new },
.mmu = { 0x00000001, tu102_mmu_new },
.pci = { 0x00000001, gp100_pci_new },
.privring = { 0x00000001, gm200_privring_new },
.timer = { 0x00000001, gk20a_timer_new },
.top = { 0x00000001, ga100_top_new },
+ .vfn = { 0x00000001, ga100_vfn_new },
+ .ce = { 0x0000001f, ga102_ce_new },
.disp = { 0x00000001, ga102_disp_new },
.dma = { 0x00000001, gv100_dma_new },
.fifo = { 0x00000001, ga102_fifo_new },
+ .gr = { 0x00000001, ga102_gr_new },
+ .nvdec = { 0x00000001, ga102_nvdec_new },
+ .sec2 = { 0x00000001, ga102_sec2_new },
};
static const struct nvkm_device_chip
nv173_chipset = {
.name = "GA103",
+ .acr = { 0x00000001, ga102_acr_new },
.bar = { 0x00000001, tu102_bar_new },
.bios = { 0x00000001, nvkm_bios_new },
.devinit = { 0x00000001, ga100_devinit_new },
+ .fault = { 0x00000001, tu102_fault_new },
.fb = { 0x00000001, ga102_fb_new },
.gpio = { 0x00000001, ga102_gpio_new },
+ .gsp = { 0x00000001, ga102_gsp_new },
.i2c = { 0x00000001, gm200_i2c_new },
.imem = { 0x00000001, nv50_instmem_new },
+ .ltc = { 0x00000001, ga102_ltc_new },
.mc = { 0x00000001, ga100_mc_new },
.mmu = { 0x00000001, tu102_mmu_new },
.pci = { 0x00000001, gp100_pci_new },
.privring = { 0x00000001, gm200_privring_new },
.timer = { 0x00000001, gk20a_timer_new },
.top = { 0x00000001, ga100_top_new },
+ .vfn = { 0x00000001, ga100_vfn_new },
+ .ce = { 0x0000001f, ga102_ce_new },
.disp = { 0x00000001, ga102_disp_new },
.dma = { 0x00000001, gv100_dma_new },
.fifo = { 0x00000001, ga102_fifo_new },
+ .gr = { 0x00000001, ga102_gr_new },
+ .nvdec = { 0x00000001, ga102_nvdec_new },
+ .sec2 = { 0x00000001, ga102_sec2_new },
};
static const struct nvkm_device_chip
nv174_chipset = {
.name = "GA104",
+ .acr = { 0x00000001, ga102_acr_new },
.bar = { 0x00000001, tu102_bar_new },
.bios = { 0x00000001, nvkm_bios_new },
.devinit = { 0x00000001, ga100_devinit_new },
+ .fault = { 0x00000001, tu102_fault_new },
.fb = { 0x00000001, ga102_fb_new },
.gpio = { 0x00000001, ga102_gpio_new },
+ .gsp = { 0x00000001, ga102_gsp_new },
.i2c = { 0x00000001, gm200_i2c_new },
.imem = { 0x00000001, nv50_instmem_new },
+ .ltc = { 0x00000001, ga102_ltc_new },
.mc = { 0x00000001, ga100_mc_new },
.mmu = { 0x00000001, tu102_mmu_new },
.pci = { 0x00000001, gp100_pci_new },
.privring = { 0x00000001, gm200_privring_new },
.timer = { 0x00000001, gk20a_timer_new },
.top = { 0x00000001, ga100_top_new },
+ .vfn = { 0x00000001, ga100_vfn_new },
+ .ce = { 0x0000001f, ga102_ce_new },
.disp = { 0x00000001, ga102_disp_new },
.dma = { 0x00000001, gv100_dma_new },
.fifo = { 0x00000001, ga102_fifo_new },
+ .gr = { 0x00000001, ga102_gr_new },
+ .nvdec = { 0x00000001, ga102_nvdec_new },
+ .sec2 = { 0x00000001, ga102_sec2_new },
};
static const struct nvkm_device_chip
nv176_chipset = {
.name = "GA106",
+ .acr = { 0x00000001, ga102_acr_new },
.bar = { 0x00000001, tu102_bar_new },
.bios = { 0x00000001, nvkm_bios_new },
.devinit = { 0x00000001, ga100_devinit_new },
+ .fault = { 0x00000001, tu102_fault_new },
.fb = { 0x00000001, ga102_fb_new },
.gpio = { 0x00000001, ga102_gpio_new },
+ .gsp = { 0x00000001, ga102_gsp_new },
.i2c = { 0x00000001, gm200_i2c_new },
.imem = { 0x00000001, nv50_instmem_new },
+ .ltc = { 0x00000001, ga102_ltc_new },
.mc = { 0x00000001, ga100_mc_new },
.mmu = { 0x00000001, tu102_mmu_new },
.pci = { 0x00000001, gp100_pci_new },
.privring = { 0x00000001, gm200_privring_new },
.timer = { 0x00000001, gk20a_timer_new },
.top = { 0x00000001, ga100_top_new },
+ .vfn = { 0x00000001, ga100_vfn_new },
+ .ce = { 0x0000001f, ga102_ce_new },
.disp = { 0x00000001, ga102_disp_new },
.dma = { 0x00000001, gv100_dma_new },
.fifo = { 0x00000001, ga102_fifo_new },
+ .gr = { 0x00000001, ga102_gr_new },
+ .nvdec = { 0x00000001, ga102_nvdec_new },
+ .sec2 = { 0x00000001, ga102_sec2_new },
};
static const struct nvkm_device_chip
nv177_chipset = {
.name = "GA107",
+ .acr = { 0x00000001, ga102_acr_new },
.bar = { 0x00000001, tu102_bar_new },
.bios = { 0x00000001, nvkm_bios_new },
.devinit = { 0x00000001, ga100_devinit_new },
+ .fault = { 0x00000001, tu102_fault_new },
.fb = { 0x00000001, ga102_fb_new },
.gpio = { 0x00000001, ga102_gpio_new },
+ .gsp = { 0x00000001, ga102_gsp_new },
.i2c = { 0x00000001, gm200_i2c_new },
.imem = { 0x00000001, nv50_instmem_new },
+ .ltc = { 0x00000001, ga102_ltc_new },
.mc = { 0x00000001, ga100_mc_new },
.mmu = { 0x00000001, tu102_mmu_new },
.pci = { 0x00000001, gp100_pci_new },
.privring = { 0x00000001, gm200_privring_new },
.timer = { 0x00000001, gk20a_timer_new },
.top = { 0x00000001, ga100_top_new },
+ .vfn = { 0x00000001, ga100_vfn_new },
+ .ce = { 0x0000001f, ga102_ce_new },
.disp = { 0x00000001, ga102_disp_new },
.dma = { 0x00000001, gv100_dma_new },
.fifo = { 0x00000001, ga102_fifo_new },
+ .gr = { 0x00000001, ga102_gr_new },
+ .nvdec = { 0x00000001, ga102_nvdec_new },
+ .sec2 = { 0x00000001, ga102_sec2_new },
};
struct nvkm_subdev *
@@ -2734,6 +2789,8 @@ nvkm_device_fini(struct nvkm_device *device, bool suspend)
if (device->func->fini)
device->func->fini(device, suspend);
+ nvkm_intr_unarm(device);
+
time = ktime_to_us(ktime_get()) - time;
nvdev_trace(device, "%s completed in %lldus...\n", action, time);
return 0;
@@ -2759,6 +2816,8 @@ nvkm_device_preinit(struct nvkm_device *device)
nvdev_trace(device, "preinit running...\n");
time = ktime_to_us(ktime_get());
+ nvkm_intr_unarm(device);
+
if (device->func->preinit) {
ret = device->func->preinit(device);
if (ret)
@@ -2775,6 +2834,14 @@ nvkm_device_preinit(struct nvkm_device *device)
if (ret)
goto fail;
+ ret = nvkm_top_parse(device);
+ if (ret)
+ goto fail;
+
+ ret = nvkm_fb_mem_unlock(device->fb);
+ if (ret)
+ goto fail;
+
time = ktime_to_us(ktime_get()) - time;
nvdev_trace(device, "preinit completed in %lldus\n", time);
return 0;
@@ -2800,6 +2867,8 @@ nvkm_device_init(struct nvkm_device *device)
nvdev_trace(device, "init running...\n");
time = ktime_to_us(ktime_get());
+ nvkm_intr_rearm(device);
+
if (device->func->init) {
ret = device->func->init(device);
if (ret)
@@ -2837,6 +2906,8 @@ nvkm_device_del(struct nvkm_device **pdevice)
if (device) {
mutex_lock(&nv_devices_mutex);
+ nvkm_intr_dtor(device);
+
list_for_each_entry_safe_reverse(subdev, subtmp, &device->subdev, head)
nvkm_subdev_del(&subdev);
@@ -3144,6 +3215,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
device->name = device->chip->name;
mutex_init(&device->mutex);
+ nvkm_intr_ctor(device);
#define NVKM_LAYOUT_ONCE(type,data,ptr) \
if (device->chip->ptr.inst && (subdev_mask & (BIT_ULL(type)))) { \
@@ -3185,7 +3257,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
#undef NVKM_LAYOUT_INST
#undef NVKM_LAYOUT_ONCE
- ret = 0;
+ ret = nvkm_intr_install(device);
done:
if (device->pri && (!mmio || ret)) {
iounmap(device->pri);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
index f302d2b5782a..abccb2bb68a6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c
@@ -1574,6 +1574,12 @@ nvkm_device_pci_resource_size(struct nvkm_device *device, unsigned bar)
return pci_resource_len(pdev->pdev, bar);
}
+static int
+nvkm_device_pci_irq(struct nvkm_device *device)
+{
+ return nvkm_device_pci(device)->pdev->irq;
+}
+
static void
nvkm_device_pci_fini(struct nvkm_device *device, bool suspend)
{
@@ -1612,6 +1618,7 @@ nvkm_device_pci_func = {
.dtor = nvkm_device_pci_dtor,
.preinit = nvkm_device_pci_preinit,
.fini = nvkm_device_pci_fini,
+ .irq = nvkm_device_pci_irq,
.resource_addr = nvkm_device_pci_resource_addr,
.resource_size = nvkm_device_pci_resource_size,
.cpu_coherent = !IS_ENABLED(CONFIG_ARM),
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h
index 93949b3c7214..24faaac15891 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/priv.h
@@ -27,6 +27,7 @@
#include <subdev/therm.h>
#include <subdev/timer.h>
#include <subdev/top.h>
+#include <subdev/vfn.h>
#include <subdev/volt.h>
#include <engine/bsp.h>
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
index ac9e122586bc..87caa4a72921 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
@@ -206,45 +206,12 @@ nvkm_device_tegra_resource_size(struct nvkm_device *device, unsigned bar)
return res ? resource_size(res) : 0;
}
-static irqreturn_t
-nvkm_device_tegra_intr(int irq, void *arg)
-{
- struct nvkm_device_tegra *tdev = arg;
- struct nvkm_device *device = &tdev->device;
- bool handled = false;
- nvkm_mc_intr_unarm(device);
- nvkm_mc_intr(device, &handled);
- nvkm_mc_intr_rearm(device);
- return handled ? IRQ_HANDLED : IRQ_NONE;
-}
-
-static void
-nvkm_device_tegra_fini(struct nvkm_device *device, bool suspend)
-{
- struct nvkm_device_tegra *tdev = nvkm_device_tegra(device);
- if (tdev->irq) {
- free_irq(tdev->irq, tdev);
- tdev->irq = 0;
- }
-}
-
static int
-nvkm_device_tegra_init(struct nvkm_device *device)
+nvkm_device_tegra_irq(struct nvkm_device *device)
{
struct nvkm_device_tegra *tdev = nvkm_device_tegra(device);
- int irq, ret;
-
- irq = platform_get_irq_byname(tdev->pdev, "stall");
- if (irq < 0)
- return irq;
- ret = request_irq(irq, nvkm_device_tegra_intr,
- IRQF_SHARED, "nvkm", tdev);
- if (ret)
- return ret;
-
- tdev->irq = irq;
- return 0;
+ return platform_get_irq_byname(tdev->pdev, "stall");
}
static void *
@@ -260,8 +227,7 @@ static const struct nvkm_device_func
nvkm_device_tegra_func = {
.tegra = nvkm_device_tegra,
.dtor = nvkm_device_tegra_dtor,
- .init = nvkm_device_tegra_init,
- .fini = nvkm_device_tegra_fini,
+ .irq = nvkm_device_tegra_irq,
.resource_addr = nvkm_device_tegra_resource_addr,
.resource_size = nvkm_device_tegra_resource_size,
.cpu_coherent = false,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
index 45f509c11c36..9b39ec341615 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
@@ -342,6 +342,8 @@ nvkm_udevice_child_get(struct nvkm_object *object, int index,
sclass = &device->mmu->user;
else if (device->fault && index-- == 0)
sclass = &device->fault->user;
+ else if (device->vfn && index-- == 0)
+ sclass = &device->vfn->user;
else
return -EINVAL;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
index 600072a904be..e1aecd3fe96c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild
@@ -28,9 +28,7 @@ nvkm-y += nvkm/engine/disp/gv100.o
nvkm-y += nvkm/engine/disp/tu102.o
nvkm-y += nvkm/engine/disp/ga102.o
-nvkm-y += nvkm/engine/disp/rootnv04.o
-nvkm-y += nvkm/engine/disp/rootnv50.o
-
nvkm-y += nvkm/engine/disp/udisp.o
nvkm-y += nvkm/engine/disp/uconn.o
nvkm-y += nvkm/engine/disp/uoutp.o
+nvkm-y += nvkm/engine/disp/uhead.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
index 65c99d948b68..73104b59f97f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c
@@ -29,7 +29,6 @@
#include "outp.h"
#include <core/client.h>
-#include <core/notify.h>
#include <core/ramht.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
@@ -57,32 +56,8 @@ nvkm_disp_vblank_init(struct nvkm_event *event, int type, int id)
head->func->vblank_get(head);
}
-static int
-nvkm_disp_vblank_ctor(struct nvkm_object *object, void *data, u32 size,
- struct nvkm_notify *notify)
-{
- struct nvkm_disp *disp =
- container_of(notify->event, typeof(*disp), vblank);
- union {
- struct nvif_notify_head_req_v0 v0;
- } *req = data;
- int ret = -ENOSYS;
-
- if (!(ret = nvif_unpack(ret, &data, &size, req->v0, 0, 0, false))) {
- notify->size = sizeof(struct nvif_notify_head_rep_v0);
- if (ret = -ENXIO, req->v0.head <= disp->vblank.index_nr) {
- notify->types = 1;
- notify->index = req->v0.head;
- return 0;
- }
- }
-
- return ret;
-}
-
static const struct nvkm_event_func
nvkm_disp_vblank_func = {
- .ctor = nvkm_disp_vblank_ctor,
.init = nvkm_disp_vblank_init,
.fini = nvkm_disp_vblank_fini,
};
@@ -90,59 +65,7 @@ nvkm_disp_vblank_func = {
void
nvkm_disp_vblank(struct nvkm_disp *disp, int head)
{
- struct nvif_notify_head_rep_v0 rep = {};
- nvkm_event_send(&disp->vblank, 1, head, &rep, sizeof(rep));
-}
-
-static int
-nvkm_disp_hpd_ctor(struct nvkm_object *object, void *data, u32 size,
- struct nvkm_notify *notify)
-{
- struct nvkm_disp *disp =
- container_of(notify->event, typeof(*disp), hpd);
- union {
- struct nvif_notify_conn_req_v0 v0;
- } *req = data;
- struct nvkm_outp *outp;
- int ret = -ENOSYS;
-
- if (!(ret = nvif_unpack(ret, &data, &size, req->v0, 0, 0, false))) {
- notify->size = sizeof(struct nvif_notify_conn_rep_v0);
- list_for_each_entry(outp, &disp->outps, head) {
- if (ret = -ENXIO, outp->conn->index == req->v0.conn) {
- if (ret = -ENODEV, outp->conn->hpd.event) {
- notify->types = req->v0.mask;
- notify->index = req->v0.conn;
- ret = 0;
- }
- break;
- }
- }
- }
-
- return ret;
-}
-
-static const struct nvkm_event_func
-nvkm_disp_hpd_func = {
- .ctor = nvkm_disp_hpd_ctor
-};
-
-int
-nvkm_disp_ntfy(struct nvkm_object *object, u32 type, struct nvkm_event **event)
-{
- struct nvkm_disp *disp = nvkm_disp(object->engine);
- switch (type) {
- case NV04_DISP_NTFY_VBLANK:
- *event = &disp->vblank;
- return 0;
- case NV04_DISP_NTFY_CONN:
- *event = &disp->hpd;
- return 0;
- default:
- break;
- }
- return -EINVAL;
+ nvkm_event_ntfy(&disp->vblank, head, NVKM_DISP_HEAD_EVENT_VBLANK);
}
static int
@@ -343,9 +266,7 @@ nvkm_disp_oneinit(struct nvkm_engine *engine)
/* Apparently we need to create a new one! */
ret = nvkm_conn_new(disp, i, &connE, &outp->conn);
if (ret) {
- nvkm_error(&disp->engine.subdev,
- "failed to create outp %d conn: %d\n",
- outp->index, ret);
+ nvkm_error(subdev, "failed to create outp %d conn: %d\n", outp->index, ret);
nvkm_conn_del(&outp->conn);
list_del(&outp->head);
nvkm_outp_del(&outp);
@@ -355,10 +276,6 @@ nvkm_disp_oneinit(struct nvkm_engine *engine)
list_add_tail(&outp->conn->head, &disp->conns);
}
- ret = nvkm_event_init(&nvkm_disp_hpd_func, 3, hpd, &disp->hpd);
- if (ret)
- return ret;
-
if (disp->func->oneinit) {
ret = disp->func->oneinit(disp);
if (ret)
@@ -382,7 +299,7 @@ nvkm_disp_oneinit(struct nvkm_engine *engine)
list_for_each_entry(head, &disp->heads, head)
i = max(i, head->id + 1);
- return nvkm_event_init(&nvkm_disp_vblank_func, 1, i, &disp->vblank);
+ return nvkm_event_init(&nvkm_disp_vblank_func, subdev, 1, i, &disp->vblank);
}
static void *
@@ -406,7 +323,6 @@ nvkm_disp_dtor(struct nvkm_engine *engine)
}
nvkm_event_fini(&disp->vblank);
- nvkm_event_fini(&disp->hpd);
while (!list_empty(&disp->conns)) {
conn = list_first_entry(&disp->conns, typeof(*conn), head);
@@ -473,5 +389,6 @@ nvkm_disp_new_(const struct nvkm_disp_func *func, struct nvkm_device *device,
mutex_init(&disp->super.mutex);
}
- return nvkm_event_init(func->uevent, 1, ARRAY_SIZE(disp->chan), &disp->uevent);
+ return nvkm_event_init(func->uevent, &disp->engine.subdev, 1, ARRAY_SIZE(disp->chan),
+ &disp->uevent);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c
index 7ed11801a3ae..fbdae1137864 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c
@@ -29,38 +29,14 @@
#include <nvif/event.h>
-static int
-nvkm_conn_hpd(struct nvkm_notify *notify)
-{
- struct nvkm_conn *conn = container_of(notify, typeof(*conn), hpd);
- struct nvkm_disp *disp = conn->disp;
- struct nvkm_gpio *gpio = disp->engine.subdev.device->gpio;
- const struct nvkm_gpio_ntfy_rep *line = notify->data;
- struct nvif_notify_conn_rep_v0 rep;
- int index = conn->index;
-
- CONN_DBG(conn, "HPD: %d", line->mask);
-
- if (!nvkm_gpio_get(gpio, 0, DCB_GPIO_UNUSED, conn->hpd.index))
- rep.mask = NVIF_NOTIFY_CONN_V0_UNPLUG;
- else
- rep.mask = NVIF_NOTIFY_CONN_V0_PLUG;
- rep.version = 0;
-
- nvkm_event_send(&disp->hpd, rep.mask, index, &rep, sizeof(rep));
- return NVKM_NOTIFY_KEEP;
-}
-
void
nvkm_conn_fini(struct nvkm_conn *conn)
{
- nvkm_notify_put(&conn->hpd);
}
void
nvkm_conn_init(struct nvkm_conn *conn)
{
- nvkm_notify_get(&conn->hpd);
}
void
@@ -68,7 +44,6 @@ nvkm_conn_del(struct nvkm_conn **pconn)
{
struct nvkm_conn *conn = *pconn;
if (conn) {
- nvkm_notify_fini(&conn->hpd);
kfree(*pconn);
*pconn = NULL;
}
@@ -106,20 +81,6 @@ nvkm_conn_ctor(struct nvkm_disp *disp, int index, struct nvbios_connE *info,
}
conn->info.hpd = func.line;
-
- ret = nvkm_notify_init(NULL, &gpio->event, nvkm_conn_hpd,
- true, &(struct nvkm_gpio_ntfy_req) {
- .mask = NVKM_GPIO_TOGGLED,
- .line = func.line,
- },
- sizeof(struct nvkm_gpio_ntfy_req),
- sizeof(struct nvkm_gpio_ntfy_rep),
- &conn->hpd);
- if (ret) {
- CONN_ERR(conn, "func %02x failed, %d", info->hpd, ret);
- } else {
- CONN_DBG(conn, "func %02x (HPD)", info->hpd);
- }
}
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h
index f109634ce5ca..a0600e72b0ec 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h
@@ -3,7 +3,6 @@
#define __NVKM_DISP_CONN_H__
#include "priv.h"
-#include <core/notify.h>
#include <subdev/bios.h>
#include <subdev/bios/conn.h>
@@ -12,8 +11,6 @@ struct nvkm_conn {
int index;
struct nvbios_connE info;
- struct nvkm_notify hpd;
-
struct list_head head;
struct nvkm_object object;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
index c1b3206f27e6..40c8ea43c42f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
@@ -274,70 +274,17 @@ nvkm_dp_train_cr(struct lt_state *lt)
}
static int
-nvkm_dp_train_links(struct nvkm_outp *outp, int rate)
+nvkm_dp_train_link(struct nvkm_outp *outp, int rate)
{
struct nvkm_ior *ior = outp->ior;
- struct nvkm_disp *disp = outp->disp;
- struct nvkm_subdev *subdev = &disp->engine.subdev;
- struct nvkm_bios *bios = subdev->device->bios;
struct lt_state lt = {
.outp = outp,
+ .pc2 = outp->dp.dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED,
};
- u32 lnkcmp;
u8 sink[2], data;
int ret;
- OUTP_DBG(outp, "training %d x %d MB/s", ior->dp.nr, ior->dp.bw * 27);
-
- /* Intersect misc. capabilities of the OR and sink. */
- if (disp->engine.subdev.device->chipset < 0x110)
- outp->dp.dpcd[DPCD_RC03] &= ~DPCD_RC03_TPS4_SUPPORTED;
- if (disp->engine.subdev.device->chipset < 0xd0)
- outp->dp.dpcd[DPCD_RC02] &= ~DPCD_RC02_TPS3_SUPPORTED;
- lt.pc2 = outp->dp.dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED;
-
- if (AMPERE_IED_HACK(disp) && (lnkcmp = lt.outp->dp.info.script[0])) {
- /* Execute BeforeLinkTraining script from DP Info table. */
- while (ior->dp.bw < nvbios_rd08(bios, lnkcmp))
- lnkcmp += 3;
- lnkcmp = nvbios_rd16(bios, lnkcmp + 1);
-
- nvbios_init(&outp->disp->engine.subdev, lnkcmp,
- init.outp = &outp->info;
- init.or = ior->id;
- init.link = ior->asy.link;
- );
- }
-
- /* Set desired link configuration on the source. */
- if ((lnkcmp = lt.outp->dp.info.lnkcmp)) {
- if (outp->dp.version < 0x30) {
- while ((ior->dp.bw * 2700) < nvbios_rd16(bios, lnkcmp))
- lnkcmp += 4;
- lnkcmp = nvbios_rd16(bios, lnkcmp + 2);
- } else {
- while (ior->dp.bw < nvbios_rd08(bios, lnkcmp))
- lnkcmp += 3;
- lnkcmp = nvbios_rd16(bios, lnkcmp + 1);
- }
-
- nvbios_init(subdev, lnkcmp,
- init.outp = &outp->info;
- init.or = ior->id;
- init.link = ior->asy.link;
- );
- }
-
- ret = ior->func->dp->links(ior, outp->dp.aux);
- if (ret) {
- if (ret < 0) {
- OUTP_ERR(outp, "train failed with %d", ret);
- return ret;
- }
- return 0;
- }
-
- ior->func->dp->power(ior, ior->dp.nr);
+ OUTP_DBG(outp, "training %dx%02x", ior->dp.nr, ior->dp.bw);
/* Select LTTPR non-transparent mode if we have a valid configuration,
* use transparent mode otherwise.
@@ -393,6 +340,71 @@ nvkm_dp_train_links(struct nvkm_outp *outp, int rate)
return ret;
}
+static int
+nvkm_dp_train_links(struct nvkm_outp *outp, int rate)
+{
+ struct nvkm_ior *ior = outp->ior;
+ struct nvkm_disp *disp = outp->disp;
+ struct nvkm_subdev *subdev = &disp->engine.subdev;
+ struct nvkm_bios *bios = subdev->device->bios;
+ u32 lnkcmp;
+ int ret;
+
+ OUTP_DBG(outp, "programming link for %dx%02x", ior->dp.nr, ior->dp.bw);
+
+ /* Intersect misc. capabilities of the OR and sink. */
+ if (disp->engine.subdev.device->chipset < 0x110)
+ outp->dp.dpcd[DPCD_RC03] &= ~DPCD_RC03_TPS4_SUPPORTED;
+ if (disp->engine.subdev.device->chipset < 0xd0)
+ outp->dp.dpcd[DPCD_RC02] &= ~DPCD_RC02_TPS3_SUPPORTED;
+
+ if (AMPERE_IED_HACK(disp) && (lnkcmp = outp->dp.info.script[0])) {
+ /* Execute BeforeLinkTraining script from DP Info table. */
+ while (ior->dp.bw < nvbios_rd08(bios, lnkcmp))
+ lnkcmp += 3;
+ lnkcmp = nvbios_rd16(bios, lnkcmp + 1);
+
+ nvbios_init(&outp->disp->engine.subdev, lnkcmp,
+ init.outp = &outp->info;
+ init.or = ior->id;
+ init.link = ior->asy.link;
+ );
+ }
+
+ /* Set desired link configuration on the source. */
+ if ((lnkcmp = outp->dp.info.lnkcmp)) {
+ if (outp->dp.version < 0x30) {
+ while ((ior->dp.bw * 2700) < nvbios_rd16(bios, lnkcmp))
+ lnkcmp += 4;
+ lnkcmp = nvbios_rd16(bios, lnkcmp + 2);
+ } else {
+ while (ior->dp.bw < nvbios_rd08(bios, lnkcmp))
+ lnkcmp += 3;
+ lnkcmp = nvbios_rd16(bios, lnkcmp + 1);
+ }
+
+ nvbios_init(subdev, lnkcmp,
+ init.outp = &outp->info;
+ init.or = ior->id;
+ init.link = ior->asy.link;
+ );
+ }
+
+ ret = ior->func->dp->links(ior, outp->dp.aux);
+ if (ret) {
+ if (ret < 0) {
+ OUTP_ERR(outp, "train failed with %d", ret);
+ return ret;
+ }
+ return 0;
+ }
+
+ ior->func->dp->power(ior, ior->dp.nr);
+
+ /* Attempt to train the link in this configuration. */
+ return nvkm_dp_train_link(outp, rate);
+}
+
static void
nvkm_dp_train_fini(struct nvkm_outp *outp)
{
@@ -439,6 +451,16 @@ nvkm_dp_train(struct nvkm_outp *outp, u32 dataKBps)
int ret = -EINVAL, nr, rate;
u8 pwr;
+ /* Retraining link? Skip source configuration, it can mess up the active modeset. */
+ if (atomic_read(&outp->dp.lt.done)) {
+ for (rate = 0; rate < outp->dp.rates; rate++) {
+ if (outp->dp.rate[rate].rate == ior->dp.bw * 27000)
+ return nvkm_dp_train_link(outp, ret);
+ }
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
/* Ensure sink is not in a low-power state. */
if (!nvkm_rdaux(outp->dp.aux, DPCD_SC00, &pwr, 1)) {
if ((pwr & DPCD_SC00_SET_POWER) != DPCD_SC00_SET_POWER_D0) {
@@ -455,6 +477,21 @@ nvkm_dp_train(struct nvkm_outp *outp, u32 dataKBps)
/* Link training. */
OUTP_DBG(outp, "training");
nvkm_dp_train_init(outp);
+
+ /* Validate and train at configuration requested (if any) on ACQUIRE. */
+ if (outp->dp.lt.nr) {
+ for (nr = outp->dp.links; ret < 0 && nr; nr >>= 1) {
+ for (rate = 0; nr == outp->dp.lt.nr && rate < outp->dp.rates; rate++) {
+ if (outp->dp.rate[rate].rate / 27000 == outp->dp.lt.bw) {
+ ior->dp.bw = outp->dp.rate[rate].rate / 27000;
+ ior->dp.nr = nr;
+ ret = nvkm_dp_train_links(outp, rate);
+ }
+ }
+ }
+ }
+
+ /* Otherwise, loop through all valid link configurations that support the data rate. */
for (nr = outp->dp.links; ret < 0 && nr; nr >>= 1) {
for (rate = 0; ret < 0 && rate < outp->dp.rates; rate++) {
if (outp->dp.rate[rate].rate * nr >= dataKBps || WARN_ON(!ior->dp.nr)) {
@@ -465,6 +502,8 @@ nvkm_dp_train(struct nvkm_outp *outp, u32 dataKBps)
}
}
}
+
+ /* Finish up. */
nvkm_dp_train_fini(outp);
if (ret < 0)
OUTP_ERR(outp, "training failed");
@@ -595,18 +634,38 @@ nvkm_dp_enable_supported_link_rates(struct nvkm_outp *outp)
return outp->dp.rates != 0;
}
-static bool
-nvkm_dp_enable(struct nvkm_outp *outp, bool enable)
+void
+nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr)
{
+ struct nvkm_gpio *gpio = outp->disp->engine.subdev.device->gpio;
struct nvkm_i2c_aux *aux = outp->dp.aux;
- if (enable) {
- if (!outp->dp.present) {
- OUTP_DBG(outp, "aux power -> always");
- nvkm_i2c_aux_monitor(aux, true);
- outp->dp.present = true;
+ if (auxpwr && !outp->dp.aux_pwr) {
+ /* eDP panels need powering on by us (if the VBIOS doesn't default it
+ * to on) before doing any AUX channel transactions. LVDS panel power
+ * is handled by the SOR itself, and not required for LVDS DDC.
+ */
+ if (outp->conn->info.type == DCB_CONNECTOR_eDP) {
+ int power = nvkm_gpio_get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff);
+ if (power == 0) {
+ nvkm_gpio_set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1);
+ outp->dp.aux_pwr_pu = true;
+ }
+
+ /* We delay here unconditionally, even if already powered,
+ * because some laptop panels having a significant resume
+ * delay before the panel begins responding.
+ *
+ * This is likely a bit of a hack, but no better idea for
+ * handling this at the moment.
+ */
+ msleep(300);
}
+ OUTP_DBG(outp, "aux power -> always");
+ nvkm_i2c_aux_monitor(aux, true);
+ outp->dp.aux_pwr = true;
+
/* Detect any LTTPRs before reading DPCD receiver caps. */
if (!nvkm_rdaux(aux, DPCD_LTTPR_REV, outp->dp.lttpr, sizeof(outp->dp.lttpr)) &&
outp->dp.lttpr[0] >= 0x14 && outp->dp.lttpr[2]) {
@@ -659,96 +718,41 @@ nvkm_dp_enable(struct nvkm_outp *outp, bool enable)
outp->dp.rates++;
}
}
-
- return true;
}
- }
-
- if (outp->dp.present) {
+ } else
+ if (!auxpwr && outp->dp.aux_pwr) {
OUTP_DBG(outp, "aux power -> demand");
nvkm_i2c_aux_monitor(aux, false);
- outp->dp.present = false;
- }
-
- atomic_set(&outp->dp.lt.done, 0);
- return false;
-}
-
-static int
-nvkm_dp_hpd(struct nvkm_notify *notify)
-{
- const struct nvkm_i2c_ntfy_rep *line = notify->data;
- struct nvkm_outp *outp = container_of(notify, typeof(*outp), dp.hpd);
- struct nvkm_conn *conn = outp->conn;
- struct nvkm_disp *disp = outp->disp;
- struct nvif_notify_conn_rep_v0 rep = {};
+ outp->dp.aux_pwr = false;
+ atomic_set(&outp->dp.lt.done, 0);
- OUTP_DBG(outp, "HPD: %d", line->mask);
- if (line->mask & NVKM_I2C_IRQ) {
- if (atomic_read(&outp->dp.lt.done))
- outp->func->acquire(outp);
- rep.mask |= NVIF_NOTIFY_CONN_V0_IRQ;
- } else {
- nvkm_dp_enable(outp, true);
+ /* Restore eDP panel GPIO to its prior state if we changed it, as
+ * it could potentially interfere with other outputs.
+ */
+ if (outp->conn->info.type == DCB_CONNECTOR_eDP) {
+ if (outp->dp.aux_pwr_pu) {
+ nvkm_gpio_set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 0);
+ outp->dp.aux_pwr_pu = false;
+ }
+ }
}
-
- if (line->mask & NVKM_I2C_UNPLUG)
- rep.mask |= NVIF_NOTIFY_CONN_V0_UNPLUG;
- if (line->mask & NVKM_I2C_PLUG)
- rep.mask |= NVIF_NOTIFY_CONN_V0_PLUG;
-
- nvkm_event_send(&disp->hpd, rep.mask, conn->index, &rep, sizeof(rep));
- return NVKM_NOTIFY_KEEP;
}
static void
nvkm_dp_fini(struct nvkm_outp *outp)
{
- nvkm_notify_put(&outp->dp.hpd);
nvkm_dp_enable(outp, false);
}
static void
nvkm_dp_init(struct nvkm_outp *outp)
{
- struct nvkm_gpio *gpio = outp->disp->engine.subdev.device->gpio;
-
- nvkm_notify_put(&outp->conn->hpd);
-
- /* eDP panels need powering on by us (if the VBIOS doesn't default it
- * to on) before doing any AUX channel transactions. LVDS panel power
- * is handled by the SOR itself, and not required for LVDS DDC.
- */
- if (outp->conn->info.type == DCB_CONNECTOR_eDP) {
- int power = nvkm_gpio_get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff);
- if (power == 0)
- nvkm_gpio_set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1);
-
- /* We delay here unconditionally, even if already powered,
- * because some laptop panels having a significant resume
- * delay before the panel begins responding.
- *
- * This is likely a bit of a hack, but no better idea for
- * handling this at the moment.
- */
- msleep(300);
-
- /* If the eDP panel can't be detected, we need to restore
- * the panel power GPIO to avoid breaking another output.
- */
- if (!nvkm_dp_enable(outp, true) && power == 0)
- nvkm_gpio_set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 0);
- } else {
- nvkm_dp_enable(outp, true);
- }
-
- nvkm_notify_get(&outp->dp.hpd);
+ nvkm_dp_enable(outp, outp->dp.enabled);
}
static void *
nvkm_dp_dtor(struct nvkm_outp *outp)
{
- nvkm_notify_fini(&outp->dp.hpd);
return outp;
}
@@ -797,21 +801,6 @@ nvkm_dp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE, struct n
OUTP_DBG(outp, "bios dp %02x %02x %02x %02x", outp->dp.version, hdr, cnt, len);
- /* hotplug detect, replaces gpio-based mechanism with aux events */
- ret = nvkm_notify_init(NULL, &i2c->event, nvkm_dp_hpd, true,
- &(struct nvkm_i2c_ntfy_req) {
- .mask = NVKM_I2C_PLUG | NVKM_I2C_UNPLUG |
- NVKM_I2C_IRQ,
- .port = outp->dp.aux->id,
- },
- sizeof(struct nvkm_i2c_ntfy_req),
- sizeof(struct nvkm_i2c_ntfy_rep),
- &outp->dp.hpd);
- if (ret) {
- OUTP_ERR(outp, "error monitoring aux hpd: %d", ret);
- return ret;
- }
-
mutex_init(&outp->dp.mutex);
atomic_set(&outp->dp.lt.done, 0);
return 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h
index 1d86baa6a424..9a6be43916bc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h
@@ -6,6 +6,7 @@
int nvkm_dp_new(struct nvkm_disp *, int index, struct dcb_output *,
struct nvkm_outp **);
void nvkm_dp_disable(struct nvkm_outp *, struct nvkm_ior *);
+void nvkm_dp_enable(struct nvkm_outp *, bool auxpwr);
/* DPCD Receiver Capabilities */
#define DPCD_RC00_DPCD_REV 0x00000
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c
index 4966a51af3d7..23ae451ba473 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c
@@ -29,9 +29,54 @@
#include <nvif/class.h>
-void
-g84_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet,
- u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size)
+static void
+g84_sor_hdmi_infoframe_vsi(struct nvkm_ior *ior, int head, void *data, u32 size)
+{
+ struct nvkm_device *device = ior->disp->engine.subdev.device;
+ struct packed_hdmi_infoframe vsi;
+ const u32 hoff = head * 0x800;
+
+ nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010000);
+ if (!size)
+ return;
+
+ pack_hdmi_infoframe(&vsi, data, size);
+
+ nvkm_wr32(device, 0x616544 + hoff, vsi.header);
+ nvkm_wr32(device, 0x616548 + hoff, vsi.subpack0_low);
+ nvkm_wr32(device, 0x61654c + hoff, vsi.subpack0_high);
+ /* Is there a second (or up to fourth?) set of subpack registers here? */
+ /* nvkm_wr32(device, 0x616550 + hoff, vsi.subpack1_low); */
+ /* nvkm_wr32(device, 0x616554 + hoff, vsi.subpack1_high); */
+
+ nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010001);
+}
+
+static void
+g84_sor_hdmi_infoframe_avi(struct nvkm_ior *ior, int head, void *data, u32 size)
+{
+ struct nvkm_device *device = ior->disp->engine.subdev.device;
+ struct packed_hdmi_infoframe avi;
+ const u32 hoff = head * 0x800;
+
+ pack_hdmi_infoframe(&avi, data, size);
+
+ nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000);
+ if (!size)
+ return;
+
+ nvkm_wr32(device, 0x616528 + hoff, avi.header);
+ nvkm_wr32(device, 0x61652c + hoff, avi.subpack0_low);
+ nvkm_wr32(device, 0x616530 + hoff, avi.subpack0_high);
+ nvkm_wr32(device, 0x616534 + hoff, avi.subpack1_low);
+ nvkm_wr32(device, 0x616538 + hoff, avi.subpack1_high);
+
+ nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000001);
+}
+
+
+static void
+g84_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, u8 rekey)
{
struct nvkm_device *device = ior->disp->engine.subdev.device;
const u32 ctrl = 0x40000000 * enable |
@@ -39,31 +84,13 @@ g84_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet,
max_ac_packet << 16 |
rekey;
const u32 hoff = head * 0x800;
- struct packed_hdmi_infoframe avi_infoframe;
- struct packed_hdmi_infoframe vendor_infoframe;
-
- pack_hdmi_infoframe(&avi_infoframe, avi, avi_size);
- pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size);
if (!(ctrl & 0x40000000)) {
nvkm_mask(device, 0x6165a4 + hoff, 0x40000000, 0x00000000);
- nvkm_mask(device, 0x61653c + hoff, 0x00000001, 0x00000000);
- nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000);
nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000);
return;
}
- /* AVI InfoFrame */
- nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000);
- if (avi_size) {
- nvkm_wr32(device, 0x616528 + hoff, avi_infoframe.header);
- nvkm_wr32(device, 0x61652c + hoff, avi_infoframe.subpack0_low);
- nvkm_wr32(device, 0x616530 + hoff, avi_infoframe.subpack0_high);
- nvkm_wr32(device, 0x616534 + hoff, avi_infoframe.subpack1_low);
- nvkm_wr32(device, 0x616538 + hoff, avi_infoframe.subpack1_high);
- nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000001);
- }
-
/* Audio InfoFrame */
nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000);
nvkm_wr32(device, 0x616508 + hoff, 0x000a0184);
@@ -71,17 +98,6 @@ g84_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet,
nvkm_wr32(device, 0x616510 + hoff, 0x00000000);
nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000001);
- /* Vendor InfoFrame */
- nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010000);
- if (vendor_size) {
- nvkm_wr32(device, 0x616544 + hoff, vendor_infoframe.header);
- nvkm_wr32(device, 0x616548 + hoff, vendor_infoframe.subpack0_low);
- nvkm_wr32(device, 0x61654c + hoff, vendor_infoframe.subpack0_high);
- /* Is there a second (or up to fourth?) set of subpack registers here? */
- /* nvkm_wr32(device, 0x616550 + hoff, vendor_infoframe->subpack1_low); */
- /* nvkm_wr32(device, 0x616554 + hoff, vendor_infoframe->subpack1_high); */
- nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010001);
- }
nvkm_mask(device, 0x6165d0 + hoff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */
nvkm_mask(device, 0x616568 + hoff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */
@@ -96,14 +112,19 @@ g84_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet,
nvkm_mask(device, 0x6165a4 + hoff, 0x5f1f007f, ctrl);
}
+const struct nvkm_ior_func_hdmi
+g84_sor_hdmi = {
+ .ctrl = g84_sor_hdmi_ctrl,
+ .infoframe_avi = g84_sor_hdmi_infoframe_avi,
+ .infoframe_vsi = g84_sor_hdmi_infoframe_vsi,
+};
+
static const struct nvkm_ior_func
g84_sor = {
.state = nv50_sor_state,
.power = nv50_sor_power,
.clock = nv50_sor_clock,
- .hdmi = {
- .ctrl = g84_sor_hdmi_ctrl,
- },
+ .hdmi = &g84_sor_hdmi,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c
index 7489d0d7fce0..52099b75f52a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c
@@ -105,10 +105,7 @@ ga102_sor = {
.state = gv100_sor_state,
.power = nv50_sor_power,
.clock = ga102_sor_clock,
- .hdmi = {
- .ctrl = gv100_sor_hdmi_ctrl,
- .scdc = gm200_sor_hdmi_scdc,
- },
+ .hdmi = &gv100_sor_hdmi,
.dp = &ga102_sor_dp,
.hda = &gv100_sor_hda,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
index 39822f1b5b95..a48e9bdf4cd0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c
@@ -202,19 +202,61 @@ gf119_sor_dp = {
};
static void
-gf119_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet,
- u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size)
+gf119_sor_hdmi_infoframe_vsi(struct nvkm_ior *ior, int head, void *data, u32 size)
+{
+ struct nvkm_device *device = ior->disp->engine.subdev.device;
+ struct packed_hdmi_infoframe vsi;
+ const u32 hoff = head * 0x800;
+
+ pack_hdmi_infoframe(&vsi, data, size);
+
+ nvkm_mask(device, 0x616730 + hoff, 0x00010001, 0x00010000);
+ if (!size)
+ return;
+
+ /*
+ * These appear to be the audio infoframe registers,
+ * but no other set of infoframe registers has yet
+ * been found.
+ */
+ nvkm_wr32(device, 0x616738 + hoff, vsi.header);
+ nvkm_wr32(device, 0x61673c + hoff, vsi.subpack0_low);
+ nvkm_wr32(device, 0x616740 + hoff, vsi.subpack0_high);
+ /* Is there a second (or further?) set of subpack registers here? */
+
+ nvkm_mask(device, 0x616730 + hoff, 0x00000001, 0x00000001);
+}
+
+static void
+gf119_sor_hdmi_infoframe_avi(struct nvkm_ior *ior, int head, void *data, u32 size)
+{
+ struct nvkm_device *device = ior->disp->engine.subdev.device;
+ struct packed_hdmi_infoframe avi;
+ const u32 hoff = head * 0x800;
+
+ pack_hdmi_infoframe(&avi, data, size);
+
+ nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000);
+ if (!size)
+ return;
+
+ nvkm_wr32(device, 0x61671c + hoff, avi.header);
+ nvkm_wr32(device, 0x616720 + hoff, avi.subpack0_low);
+ nvkm_wr32(device, 0x616724 + hoff, avi.subpack0_high);
+ nvkm_wr32(device, 0x616728 + hoff, avi.subpack1_low);
+ nvkm_wr32(device, 0x61672c + hoff, avi.subpack1_high);
+
+ nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000001);
+}
+
+static void
+gf119_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, u8 rekey)
{
struct nvkm_device *device = ior->disp->engine.subdev.device;
const u32 ctrl = 0x40000000 * enable |
max_ac_packet << 16 |
rekey;
const u32 hoff = head * 0x800;
- struct packed_hdmi_infoframe avi_infoframe;
- struct packed_hdmi_infoframe vendor_infoframe;
-
- pack_hdmi_infoframe(&avi_infoframe, avi, avi_size);
- pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size);
if (!(ctrl & 0x40000000)) {
nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000);
@@ -224,32 +266,6 @@ gf119_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe
return;
}
- /* AVI InfoFrame */
- nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000);
- if (avi_size) {
- nvkm_wr32(device, 0x61671c + hoff, avi_infoframe.header);
- nvkm_wr32(device, 0x616720 + hoff, avi_infoframe.subpack0_low);
- nvkm_wr32(device, 0x616724 + hoff, avi_infoframe.subpack0_high);
- nvkm_wr32(device, 0x616728 + hoff, avi_infoframe.subpack1_low);
- nvkm_wr32(device, 0x61672c + hoff, avi_infoframe.subpack1_high);
- nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000001);
- }
-
- /* GENERIC(?) / Vendor InfoFrame? */
- nvkm_mask(device, 0x616730 + hoff, 0x00010001, 0x00010000);
- if (vendor_size) {
- /*
- * These appear to be the audio infoframe registers,
- * but no other set of infoframe registers has yet
- * been found.
- */
- nvkm_wr32(device, 0x616738 + hoff, vendor_infoframe.header);
- nvkm_wr32(device, 0x61673c + hoff, vendor_infoframe.subpack0_low);
- nvkm_wr32(device, 0x616740 + hoff, vendor_infoframe.subpack0_high);
- /* Is there a second (or further?) set of subpack registers here? */
- nvkm_mask(device, 0x616730 + hoff, 0x00000001, 0x00000001);
- }
-
/* ??? InfoFrame? */
nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000);
nvkm_wr32(device, 0x6167ac + hoff, 0x00000010);
@@ -259,6 +275,13 @@ gf119_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe
nvkm_mask(device, 0x616798 + hoff, 0x401f007f, ctrl);
}
+static const struct nvkm_ior_func_hdmi
+gf119_sor_hdmi = {
+ .ctrl = gf119_sor_hdmi_ctrl,
+ .infoframe_avi = gf119_sor_hdmi_infoframe_avi,
+ .infoframe_vsi = gf119_sor_hdmi_infoframe_vsi,
+};
+
void
gf119_sor_clock(struct nvkm_ior *sor)
{
@@ -305,9 +328,7 @@ gf119_sor = {
.state = gf119_sor_state,
.power = nv50_sor_power,
.clock = gf119_sor_clock,
- .hdmi = {
- .ctrl = gf119_sor_hdmi_ctrl,
- },
+ .hdmi = &gf119_sor_hdmi,
.dp = &gf119_sor_dp,
.hda = &gf119_sor_hda,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c
index 7248e9ec835e..876a21a0cebb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c
@@ -30,8 +30,51 @@
#include <nvif/class.h>
void
-gk104_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet,
- u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size)
+gk104_sor_hdmi_infoframe_vsi(struct nvkm_ior *ior, int head, void *data, u32 size)
+{
+ struct nvkm_device *device = ior->disp->engine.subdev.device;
+ struct packed_hdmi_infoframe vsi;
+ const u32 hoff = head * 0x400;
+
+ pack_hdmi_infoframe(&vsi, data, size);
+
+ /* GENERIC(?) / Vendor InfoFrame? */
+ nvkm_mask(device, 0x690100 + hoff, 0x00010001, 0x00000000);
+ if (!size)
+ return;
+
+ nvkm_wr32(device, 0x690108 + hoff, vsi.header);
+ nvkm_wr32(device, 0x69010c + hoff, vsi.subpack0_low);
+ nvkm_wr32(device, 0x690110 + hoff, vsi.subpack0_high);
+ /* Is there a second (or further?) set of subpack registers here? */
+ nvkm_mask(device, 0x690100 + hoff, 0x00000001, 0x00000001);
+}
+
+void
+gk104_sor_hdmi_infoframe_avi(struct nvkm_ior *ior, int head, void *data, u32 size)
+{
+ struct nvkm_device *device = ior->disp->engine.subdev.device;
+ struct packed_hdmi_infoframe avi;
+ const u32 hoff = head * 0x400;
+
+ pack_hdmi_infoframe(&avi, data, size);
+
+ /* AVI InfoFrame */
+ nvkm_mask(device, 0x690000 + hoff, 0x00000001, 0x00000000);
+ if (!size)
+ return;
+
+ nvkm_wr32(device, 0x690008 + hoff, avi.header);
+ nvkm_wr32(device, 0x69000c + hoff, avi.subpack0_low);
+ nvkm_wr32(device, 0x690010 + hoff, avi.subpack0_high);
+ nvkm_wr32(device, 0x690014 + hoff, avi.subpack1_low);
+ nvkm_wr32(device, 0x690018 + hoff, avi.subpack1_high);
+
+ nvkm_mask(device, 0x690000 + hoff, 0x00000001, 0x00000001);
+}
+
+void
+gk104_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, u8 rekey)
{
struct nvkm_device *device = ior->disp->engine.subdev.device;
const u32 ctrl = 0x40000000 * enable |
@@ -39,11 +82,6 @@ gk104_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe
rekey;
const u32 hoff = head * 0x800;
const u32 hdmi = head * 0x400;
- struct packed_hdmi_infoframe avi_infoframe;
- struct packed_hdmi_infoframe vendor_infoframe;
-
- pack_hdmi_infoframe(&avi_infoframe, avi, avi_size);
- pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size);
if (!(ctrl & 0x40000000)) {
nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000);
@@ -53,28 +91,6 @@ gk104_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe
return;
}
- /* AVI InfoFrame */
- nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000000);
- if (avi_size) {
- nvkm_wr32(device, 0x690008 + hdmi, avi_infoframe.header);
- nvkm_wr32(device, 0x69000c + hdmi, avi_infoframe.subpack0_low);
- nvkm_wr32(device, 0x690010 + hdmi, avi_infoframe.subpack0_high);
- nvkm_wr32(device, 0x690014 + hdmi, avi_infoframe.subpack1_low);
- nvkm_wr32(device, 0x690018 + hdmi, avi_infoframe.subpack1_high);
- nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000001);
- }
-
- /* GENERIC(?) / Vendor InfoFrame? */
- nvkm_mask(device, 0x690100 + hdmi, 0x00010001, 0x00000000);
- if (vendor_size) {
- nvkm_wr32(device, 0x690108 + hdmi, vendor_infoframe.header);
- nvkm_wr32(device, 0x69010c + hdmi, vendor_infoframe.subpack0_low);
- nvkm_wr32(device, 0x690110 + hdmi, vendor_infoframe.subpack0_high);
- /* Is there a second (or further?) set of subpack registers here? */
- nvkm_mask(device, 0x690100 + hdmi, 0x00000001, 0x00000001);
- }
-
-
/* ??? InfoFrame? */
nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000);
nvkm_wr32(device, 0x6900cc + hdmi, 0x00000010);
@@ -87,14 +103,19 @@ gk104_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe
nvkm_mask(device, 0x616798 + hoff, 0x401f007f, ctrl);
}
+const struct nvkm_ior_func_hdmi
+gk104_sor_hdmi = {
+ .ctrl = gk104_sor_hdmi_ctrl,
+ .infoframe_avi = gk104_sor_hdmi_infoframe_avi,
+ .infoframe_vsi = gk104_sor_hdmi_infoframe_vsi,
+};
+
static const struct nvkm_ior_func
gk104_sor = {
.state = gf119_sor_state,
.power = nv50_sor_power,
.clock = gf119_sor_clock,
- .hdmi = {
- .ctrl = gk104_sor_hdmi_ctrl,
- },
+ .hdmi = &gk104_sor_hdmi,
.dp = &gf119_sor_dp,
.hda = &gf119_sor_hda,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
index 9e9ef49bd8ac..b4d8e868616f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c
@@ -70,9 +70,7 @@ gm107_sor = {
.state = gf119_sor_state,
.power = nv50_sor_power,
.clock = gf119_sor_clock,
- .hdmi = {
- .ctrl = gk104_sor_hdmi_ctrl,
- },
+ .hdmi = &gk104_sor_hdmi,
.dp = &gm107_sor_dp,
.hda = &gf119_sor_hda,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c
index 4ecc8f98af6e..562ebae57d44 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c
@@ -79,6 +79,14 @@ gm200_sor_hdmi_scdc(struct nvkm_ior *ior, u8 scdc)
ior->tmds.high_speed = !!(scdc & 0x2);
}
+const struct nvkm_ior_func_hdmi
+gm200_sor_hdmi = {
+ .ctrl = gk104_sor_hdmi_ctrl,
+ .scdc = gm200_sor_hdmi_scdc,
+ .infoframe_avi = gk104_sor_hdmi_infoframe_avi,
+ .infoframe_vsi = gk104_sor_hdmi_infoframe_vsi,
+};
+
void
gm200_sor_route_set(struct nvkm_outp *outp, struct nvkm_ior *ior)
{
@@ -131,10 +139,7 @@ gm200_sor = {
.state = gf119_sor_state,
.power = nv50_sor_power,
.clock = gf119_sor_clock,
- .hdmi = {
- .ctrl = gk104_sor_hdmi_ctrl,
- .scdc = gm200_sor_hdmi_scdc,
- },
+ .hdmi = &gm200_sor_hdmi,
.dp = &gm200_sor_dp,
.hda = &gf119_sor_hda,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c
index 7172a9dfd89b..7f1eb4332040 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c
@@ -37,10 +37,7 @@ gp100_sor = {
.state = gf119_sor_state,
.power = nv50_sor_power,
.clock = gf119_sor_clock,
- .hdmi = {
- .ctrl = gk104_sor_hdmi_ctrl,
- .scdc = gm200_sor_hdmi_scdc,
- },
+ .hdmi = &gm200_sor_hdmi,
.dp = &gm200_sor_dp,
.hda = &gf119_sor_hda,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c
index 70c49e7af9cf..a2c7c6f83dcd 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c
@@ -92,9 +92,53 @@ gt215_sor_dp = {
.watermark = g94_sor_dp_watermark,
};
-void
-gt215_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet,
- u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size)
+static void
+gt215_sor_hdmi_infoframe_vsi(struct nvkm_ior *ior, int head, void *data, u32 size)
+{
+ struct nvkm_device *device = ior->disp->engine.subdev.device;
+ struct packed_hdmi_infoframe vsi;
+ const u32 soff = nv50_ior_base(ior);
+
+ pack_hdmi_infoframe(&vsi, data, size);
+
+ nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010000);
+ if (!size)
+ return;
+
+ nvkm_wr32(device, 0x61c544 + soff, vsi.header);
+ nvkm_wr32(device, 0x61c548 + soff, vsi.subpack0_low);
+ nvkm_wr32(device, 0x61c54c + soff, vsi.subpack0_high);
+ /* Is there a second (or up to fourth?) set of subpack registers here? */
+ /* nvkm_wr32(device, 0x61c550 + soff, vsi.subpack1_low); */
+ /* nvkm_wr32(device, 0x61c554 + soff, vsi.subpack1_high); */
+
+ nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010001);
+}
+
+static void
+gt215_sor_hdmi_infoframe_avi(struct nvkm_ior *ior, int head, void *data, u32 size)
+{
+ struct nvkm_device *device = ior->disp->engine.subdev.device;
+ struct packed_hdmi_infoframe avi;
+ const u32 soff = nv50_ior_base(ior);
+
+ pack_hdmi_infoframe(&avi, data, size);
+
+ nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000);
+ if (size)
+ return;
+
+ nvkm_wr32(device, 0x61c528 + soff, avi.header);
+ nvkm_wr32(device, 0x61c52c + soff, avi.subpack0_low);
+ nvkm_wr32(device, 0x61c530 + soff, avi.subpack0_high);
+ nvkm_wr32(device, 0x61c534 + soff, avi.subpack1_low);
+ nvkm_wr32(device, 0x61c538 + soff, avi.subpack1_high);
+
+ nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000001);
+}
+
+static void
+gt215_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, u8 rekey)
{
struct nvkm_device *device = ior->disp->engine.subdev.device;
const u32 ctrl = 0x40000000 * enable |
@@ -102,11 +146,6 @@ gt215_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe
max_ac_packet << 16 |
rekey;
const u32 soff = nv50_ior_base(ior);
- struct packed_hdmi_infoframe avi_infoframe;
- struct packed_hdmi_infoframe vendor_infoframe;
-
- pack_hdmi_infoframe(&avi_infoframe, avi, avi_size);
- pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size);
if (!(ctrl & 0x40000000)) {
nvkm_mask(device, 0x61c5a4 + soff, 0x40000000, 0x00000000);
@@ -116,17 +155,6 @@ gt215_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe
return;
}
- /* AVI InfoFrame */
- nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000);
- if (avi_size) {
- nvkm_wr32(device, 0x61c528 + soff, avi_infoframe.header);
- nvkm_wr32(device, 0x61c52c + soff, avi_infoframe.subpack0_low);
- nvkm_wr32(device, 0x61c530 + soff, avi_infoframe.subpack0_high);
- nvkm_wr32(device, 0x61c534 + soff, avi_infoframe.subpack1_low);
- nvkm_wr32(device, 0x61c538 + soff, avi_infoframe.subpack1_high);
- nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000001);
- }
-
/* Audio InfoFrame */
nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000000);
nvkm_wr32(device, 0x61c508 + soff, 0x000a0184);
@@ -134,18 +162,6 @@ gt215_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe
nvkm_wr32(device, 0x61c510 + soff, 0x00000000);
nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000001);
- /* Vendor InfoFrame */
- nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010000);
- if (vendor_size) {
- nvkm_wr32(device, 0x61c544 + soff, vendor_infoframe.header);
- nvkm_wr32(device, 0x61c548 + soff, vendor_infoframe.subpack0_low);
- nvkm_wr32(device, 0x61c54c + soff, vendor_infoframe.subpack0_high);
- /* Is there a second (or up to fourth?) set of subpack registers here? */
- /* nvkm_wr32(device, 0x61c550 + soff, vendor_infoframe.subpack1_low); */
- /* nvkm_wr32(device, 0x61c554 + soff, vendor_infoframe.subpack1_high); */
- nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010001);
- }
-
nvkm_mask(device, 0x61c5d0 + soff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */
nvkm_mask(device, 0x61c568 + soff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */
nvkm_mask(device, 0x61c578 + soff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */
@@ -159,14 +175,19 @@ gt215_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe
nvkm_mask(device, 0x61c5a4 + soff, 0x5f1f007f, ctrl);
}
+const struct nvkm_ior_func_hdmi
+gt215_sor_hdmi = {
+ .ctrl = gt215_sor_hdmi_ctrl,
+ .infoframe_avi = gt215_sor_hdmi_infoframe_avi,
+ .infoframe_vsi = gt215_sor_hdmi_infoframe_vsi,
+};
+
static const struct nvkm_ior_func
gt215_sor = {
.state = g94_sor_state,
.power = nv50_sor_power,
.clock = nv50_sor_clock,
- .hdmi = {
- .ctrl = gt215_sor_hdmi_ctrl,
- },
+ .hdmi = &gt215_sor_hdmi,
.dp = &gt215_sor_dp,
.hda = &gt215_sor_hda,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c
index 6b9d49270fa7..115d0997fd62 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c
@@ -96,9 +96,54 @@ gv100_sor_dp = {
.watermark = gv100_sor_dp_watermark,
};
-void
-gv100_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet,
- u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size)
+static void
+gv100_sor_hdmi_infoframe_vsi(struct nvkm_ior *ior, int head, void *data, u32 size)
+{
+ struct nvkm_device *device = ior->disp->engine.subdev.device;
+ struct packed_hdmi_infoframe vsi;
+ const u32 hoff = head * 0x400;
+
+ pack_hdmi_infoframe(&vsi, data, size);
+
+ nvkm_mask(device, 0x6f0100 + hoff, 0x00010001, 0x00000000);
+ if (!size)
+ return;
+
+ nvkm_wr32(device, 0x6f0108 + hoff, vsi.header);
+ nvkm_wr32(device, 0x6f010c + hoff, vsi.subpack0_low);
+ nvkm_wr32(device, 0x6f0110 + hoff, vsi.subpack0_high);
+ nvkm_wr32(device, 0x6f0114 + hoff, 0x00000000);
+ nvkm_wr32(device, 0x6f0118 + hoff, 0x00000000);
+ nvkm_wr32(device, 0x6f011c + hoff, 0x00000000);
+ nvkm_wr32(device, 0x6f0120 + hoff, 0x00000000);
+ nvkm_wr32(device, 0x6f0124 + hoff, 0x00000000);
+ nvkm_mask(device, 0x6f0100 + hoff, 0x00000001, 0x00000001);
+}
+
+static void
+gv100_sor_hdmi_infoframe_avi(struct nvkm_ior *ior, int head, void *data, u32 size)
+{
+ struct nvkm_device *device = ior->disp->engine.subdev.device;
+ struct packed_hdmi_infoframe avi;
+ const u32 hoff = head * 0x400;
+
+ pack_hdmi_infoframe(&avi, data, size);
+
+ nvkm_mask(device, 0x6f0000 + hoff, 0x00000001, 0x00000000);
+ if (!size)
+ return;
+
+ nvkm_wr32(device, 0x6f0008 + hoff, avi.header);
+ nvkm_wr32(device, 0x6f000c + hoff, avi.subpack0_low);
+ nvkm_wr32(device, 0x6f0010 + hoff, avi.subpack0_high);
+ nvkm_wr32(device, 0x6f0014 + hoff, avi.subpack1_low);
+ nvkm_wr32(device, 0x6f0018 + hoff, avi.subpack1_high);
+
+ nvkm_mask(device, 0x6f0000 + hoff, 0x00000001, 0x00000001);
+}
+
+static void
+gv100_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, u8 rekey)
{
struct nvkm_device *device = ior->disp->engine.subdev.device;
const u32 ctrl = 0x40000000 * enable |
@@ -106,11 +151,6 @@ gv100_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe
rekey;
const u32 hoff = head * 0x800;
const u32 hdmi = head * 0x400;
- struct packed_hdmi_infoframe avi_infoframe;
- struct packed_hdmi_infoframe vendor_infoframe;
-
- pack_hdmi_infoframe(&avi_infoframe, avi, avi_size);
- pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size);
if (!(ctrl & 0x40000000)) {
nvkm_mask(device, 0x6165c0 + hoff, 0x40000000, 0x00000000);
@@ -120,32 +160,6 @@ gv100_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe
return;
}
- /* AVI InfoFrame (AVI). */
- nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000000);
- if (avi_size) {
- nvkm_wr32(device, 0x6f0008 + hdmi, avi_infoframe.header);
- nvkm_wr32(device, 0x6f000c + hdmi, avi_infoframe.subpack0_low);
- nvkm_wr32(device, 0x6f0010 + hdmi, avi_infoframe.subpack0_high);
- nvkm_wr32(device, 0x6f0014 + hdmi, avi_infoframe.subpack1_low);
- nvkm_wr32(device, 0x6f0018 + hdmi, avi_infoframe.subpack1_high);
- nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000001);
- }
-
- /* Vendor-specific InfoFrame (VSI). */
- nvkm_mask(device, 0x6f0100 + hdmi, 0x00010001, 0x00000000);
- if (vendor_size) {
- nvkm_wr32(device, 0x6f0108 + hdmi, vendor_infoframe.header);
- nvkm_wr32(device, 0x6f010c + hdmi, vendor_infoframe.subpack0_low);
- nvkm_wr32(device, 0x6f0110 + hdmi, vendor_infoframe.subpack0_high);
- nvkm_wr32(device, 0x6f0114 + hdmi, 0x00000000);
- nvkm_wr32(device, 0x6f0118 + hdmi, 0x00000000);
- nvkm_wr32(device, 0x6f011c + hdmi, 0x00000000);
- nvkm_wr32(device, 0x6f0120 + hdmi, 0x00000000);
- nvkm_wr32(device, 0x6f0124 + hdmi, 0x00000000);
- nvkm_mask(device, 0x6f0100 + hdmi, 0x00000001, 0x00000001);
- }
-
-
/* General Control (GCP). */
nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000000);
nvkm_wr32(device, 0x6f00cc + hdmi, 0x00000010);
@@ -158,6 +172,14 @@ gv100_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packe
nvkm_mask(device, 0x6165c0 + hoff, 0x401f007f, ctrl);
}
+const struct nvkm_ior_func_hdmi
+gv100_sor_hdmi = {
+ .ctrl = gv100_sor_hdmi_ctrl,
+ .scdc = gm200_sor_hdmi_scdc,
+ .infoframe_avi = gv100_sor_hdmi_infoframe_avi,
+ .infoframe_vsi = gv100_sor_hdmi_infoframe_vsi,
+};
+
void
gv100_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state)
{
@@ -190,10 +212,7 @@ gv100_sor = {
.state = gv100_sor_state,
.power = nv50_sor_power,
.clock = gf119_sor_clock,
- .hdmi = {
- .ctrl = gv100_sor_hdmi_ctrl,
- .scdc = gm200_sor_hdmi_scdc,
- },
+ .hdmi = &gv100_sor_hdmi,
.dp = &gv100_sor_dp,
.hda = &gv100_sor_hda,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c
index 83152c26fe3e..7f5d13d13c94 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c
@@ -39,44 +39,6 @@ nvkm_head_find(struct nvkm_disp *disp, int id)
return NULL;
}
-int
-nvkm_head_mthd_scanoutpos(struct nvkm_object *object,
- struct nvkm_head *head, void *data, u32 size)
-{
- union {
- struct nv04_disp_scanoutpos_v0 v0;
- } *args = data;
- int ret = -ENOSYS;
-
- nvif_ioctl(object, "head scanoutpos size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
- nvif_ioctl(object, "head scanoutpos vers %d\n",
- args->v0.version);
-
- head->func->state(head, &head->arm);
- args->v0.vtotal = head->arm.vtotal;
- args->v0.vblanks = head->arm.vblanks;
- args->v0.vblanke = head->arm.vblanke;
- args->v0.htotal = head->arm.htotal;
- args->v0.hblanks = head->arm.hblanks;
- args->v0.hblanke = head->arm.hblanke;
-
- /* We don't support reading htotal/vtotal on pre-NV50 VGA,
- * so we have to give up and trigger the timestamping
- * fallback in the drm core.
- */
- if (!args->v0.vtotal || !args->v0.htotal)
- return -ENOTSUPP;
-
- args->v0.time[0] = ktime_to_ns(ktime_get());
- head->func->rgpos(head, &args->v0.hline, &args->v0.vline);
- args->v0.time[1] = ktime_to_ns(ktime_get());
- } else
- return ret;
-
- return 0;
-}
-
void
nvkm_head_del(struct nvkm_head **phead)
{
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h
index 84a2989193cf..856252bf559a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: MIT */
#ifndef __NVKM_DISP_HEAD_H__
#define __NVKM_DISP_HEAD_H__
+#include <nvif/object.h>
#include "priv.h"
struct nvkm_head {
@@ -26,12 +27,12 @@ struct nvkm_head {
u8 depth;
} or;
} arm, asy;
+
+ struct nvkm_object object;
};
int nvkm_head_new_(const struct nvkm_head_func *, struct nvkm_disp *, int id);
void nvkm_head_del(struct nvkm_head **);
-int nvkm_head_mthd_scanoutpos(struct nvkm_object *,
- struct nvkm_head *, void *, u32);
struct nvkm_head *nvkm_head_find(struct nvkm_disp *, int id);
struct nvkm_head_func {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
index 671c4674ffcc..da1b1a626ef2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h
@@ -63,12 +63,12 @@ struct nvkm_ior_func {
void (*war_2)(struct nvkm_ior *);
void (*war_3)(struct nvkm_ior *);
- struct {
- void (*ctrl)(struct nvkm_ior *, int head, bool enable,
- u8 max_ac_packet, u8 rekey, u8 *avi, u8 avi_size,
- u8 *vendor, u8 vendor_size);
+ const struct nvkm_ior_func_hdmi {
+ void (*ctrl)(struct nvkm_ior *, int head, bool enable, u8 max_ac_packet, u8 rekey);
void (*scdc)(struct nvkm_ior *, u8 scdc);
- } hdmi;
+ void (*infoframe_avi)(struct nvkm_ior *, int head, void *data, u32 size);
+ void (*infoframe_vsi)(struct nvkm_ior *, int head, void *data, u32 size);
+ } *hdmi;
const struct nvkm_ior_func_dp {
u8 lanes[4];
@@ -124,9 +124,10 @@ void nv50_sor_power(struct nvkm_ior *, bool, bool, bool, bool, bool);
void nv50_sor_clock(struct nvkm_ior *);
int g84_sor_new(struct nvkm_disp *, int);
-void g84_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
+extern const struct nvkm_ior_func_hdmi g84_sor_hdmi;
int g94_sor_cnt(struct nvkm_disp *, unsigned long *);
+
void g94_sor_state(struct nvkm_ior *, struct nvkm_ior_state *);
extern const struct nvkm_ior_func_dp g94_sor_dp;
int g94_sor_dp_links(struct nvkm_ior *, struct nvkm_i2c_aux *);
@@ -137,7 +138,7 @@ void g94_sor_dp_audio_sym(struct nvkm_ior *, int, u16, u32);
void g94_sor_dp_activesym(struct nvkm_ior *, int, u8, u8, u8, u8);
void g94_sor_dp_watermark(struct nvkm_ior *, int, u8);
-void gt215_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
+extern const struct nvkm_ior_func_hdmi gt215_sor_hdmi;
void gt215_sor_dp_audio(struct nvkm_ior *, int, bool);
extern const struct nvkm_ior_func_hda gt215_sor_hda;
@@ -156,12 +157,16 @@ void gf119_sor_hda_hpd(struct nvkm_ior *, int, bool);
void gf119_sor_hda_eld(struct nvkm_ior *, int, u8 *, u8);
int gk104_sor_new(struct nvkm_disp *, int);
-void gk104_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
+extern const struct nvkm_ior_func_hdmi gk104_sor_hdmi;
+void gk104_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8);
+void gk104_sor_hdmi_infoframe_avi(struct nvkm_ior *, int, void *, u32);
+void gk104_sor_hdmi_infoframe_vsi(struct nvkm_ior *, int, void *, u32);
void gm107_sor_dp_pattern(struct nvkm_ior *, int);
void gm200_sor_route_set(struct nvkm_outp *, struct nvkm_ior *);
int gm200_sor_route_get(struct nvkm_outp *, int *);
+extern const struct nvkm_ior_func_hdmi gm200_sor_hdmi;
void gm200_sor_hdmi_scdc(struct nvkm_ior *, u8);
extern const struct nvkm_ior_func_dp gm200_sor_dp;
void gm200_sor_dp_drive(struct nvkm_ior *, int, int, int, int, int);
@@ -170,7 +175,7 @@ int gp100_sor_new(struct nvkm_disp *, int);
int gv100_sor_cnt(struct nvkm_disp *, unsigned long *);
void gv100_sor_state(struct nvkm_ior *, struct nvkm_ior_state *);
-void gv100_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8);
+extern const struct nvkm_ior_func_hdmi gv100_sor_hdmi;
void gv100_sor_dp_audio(struct nvkm_ior *, int, bool);
void gv100_sor_dp_audio_sym(struct nvkm_ior *, int, u16, u32);
void gv100_sor_dp_watermark(struct nvkm_ior *, int, u8);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c
index 916b1d477b0b..841e3b69fcaf 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c
@@ -31,9 +31,7 @@ mcp77_sor = {
.state = g94_sor_state,
.power = nv50_sor_power,
.clock = nv50_sor_clock,
- .hdmi = {
- .ctrl = g84_sor_hdmi_ctrl,
- },
+ .hdmi = &g84_sor_hdmi,
.dp = &g94_sor_dp,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c
index a5a0b9439374..f96ba4752655 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c
@@ -44,9 +44,7 @@ mcp89_sor = {
.state = g94_sor_state,
.power = nv50_sor_power,
.clock = nv50_sor_clock,
- .hdmi = {
- .ctrl = gt215_sor_hdmi_ctrl,
- },
+ .hdmi = &gt215_sor_hdmi,
.dp = &mcp89_sor_dp,
.hda = &gt215_sor_hda,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
index a46e13cc9ff1..be8116802960 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c
@@ -503,7 +503,7 @@ nv50_disp_chan_uevent_init(struct nvkm_event *event, int types, int index)
void
nv50_disp_chan_uevent_send(struct nvkm_disp *disp, int chid)
{
- nvkm_event_send(&disp->uevent, NVKM_DISP_EVENT_CHAN_AWAKEN, chid, NULL, 0);
+ nvkm_event_ntfy(&disp->uevent, chid, NVKM_DISP_EVENT_CHAN_AWAKEN);
}
const struct nvkm_event_func
@@ -1238,6 +1238,8 @@ nv50_disp_super_2_2(struct nvkm_disp *disp, struct nvkm_head *head)
if (!ior)
return;
+ outp = ior->asy.outp;
+
/* For some reason, NVIDIA decided not to:
*
* A) Give dual-link LVDS a separate EVO protocol, like for TMDS.
@@ -1247,13 +1249,13 @@ nv50_disp_super_2_2(struct nvkm_disp *disp, struct nvkm_head *head)
* Override the values we usually read from HW with the same
* data we pass though an ioctl instead.
*/
- if (ior->type == SOR && ior->asy.proto == LVDS) {
- head->asy.or.depth = (disp->sor.lvdsconf & 0x0200) ? 24 : 18;
- ior->asy.link = (disp->sor.lvdsconf & 0x0100) ? 3 : 1;
+ if (outp && ior->type == SOR && ior->asy.proto == LVDS) {
+ head->asy.or.depth = outp->lvds.bpc8 ? 24 : 18;
+ ior->asy.link = outp->lvds.dual ? 3 : 1;
}
/* Handle any link training, etc. */
- if ((outp = ior->asy.outp) && outp->func->acquire)
+ if (outp && outp->func->acquire)
outp->func->acquire(outp);
/* Execute OnInt2 IED script. */
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
index 3f3924c41957..b7631c1ab242 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h
@@ -2,7 +2,6 @@
#ifndef __NVKM_DISP_OUTP_H__
#define __NVKM_DISP_OUTP_H__
#include "priv.h"
-#include <core/notify.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
@@ -28,13 +27,19 @@ struct nvkm_outp {
union {
struct {
+ bool dual;
+ bool bpc8;
+ } lvds;
+
+ struct {
struct nvbios_dpout info;
u8 version;
struct nvkm_i2c_aux *aux;
- struct nvkm_notify hpd;
- bool present;
+ bool enabled;
+ bool aux_pwr;
+ bool aux_pwr_pu;
u8 lttpr[6];
u8 lttprs;
u8 dpcd[16];
@@ -49,12 +54,17 @@ struct nvkm_outp {
struct mutex mutex;
struct {
atomic_t done;
+ u8 nr;
+ u8 bw;
bool mst;
} lt;
} dp;
};
struct nvkm_object object;
+ struct {
+ struct nvkm_head *head;
+ } asy;
};
int nvkm_outp_new_(const struct nvkm_outp_func *, struct nvkm_disp *, int index,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h
index cb25dfe849f0..ec5292a8f3c8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h
@@ -42,10 +42,6 @@ struct nvkm_disp_func {
} user[];
};
-int nvkm_disp_ntfy(struct nvkm_object *, u32, struct nvkm_event **);
-int nv04_disp_mthd(struct nvkm_object *, u32, void *, u32);
-int nv50_disp_root_mthd_(struct nvkm_object *, u32, void *, u32);
-
int nv50_disp_oneinit(struct nvkm_disp *);
int nv50_disp_init(struct nvkm_disp *);
void nv50_disp_fini(struct nvkm_disp *);
@@ -86,4 +82,5 @@ extern const struct nvkm_event_func gv100_disp_chan_uevent;
int nvkm_udisp_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **);
int nvkm_uconn_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **);
int nvkm_uoutp_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **);
+int nvkm_uhead_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **);
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
deleted file mode 100644
index 0af45ccd140c..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * Copyright 2012 Red Hat 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: Ben Skeggs
- */
-#include "chan.h"
-#include "head.h"
-#include "ior.h"
-#include "outp.h"
-
-#include <core/client.h>
-
-#include <nvif/class.h>
-#include <nvif/cl5070.h>
-#include <nvif/unpack.h>
-
-int
-nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
-{
- union {
- struct nv50_disp_mthd_v0 v0;
- struct nv50_disp_mthd_v1 v1;
- } *args = data;
- struct nvkm_disp *disp = nvkm_udisp(object);
- struct nvkm_outp *temp, *outp = NULL;
- struct nvkm_head *head;
- u16 type, mask = 0;
- int hidx, ret = -ENOSYS;
-
- if (mthd != NV50_DISP_MTHD)
- return -EINVAL;
-
- nvif_ioctl(object, "disp mthd size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
- nvif_ioctl(object, "disp mthd vers %d mthd %02x head %d\n",
- args->v0.version, args->v0.method, args->v0.head);
- mthd = args->v0.method;
- hidx = args->v0.head;
- } else
- if (!(ret = nvif_unpack(ret, &data, &size, args->v1, 1, 1, true))) {
- nvif_ioctl(object, "disp mthd vers %d mthd %02x "
- "type %04x mask %04x\n",
- args->v1.version, args->v1.method,
- args->v1.hasht, args->v1.hashm);
- mthd = args->v1.method;
- type = args->v1.hasht;
- mask = args->v1.hashm;
- hidx = ffs((mask >> 8) & 0x0f) - 1;
- } else
- return ret;
-
- if (!(head = nvkm_head_find(disp, hidx)))
- return -ENXIO;
-
- if (mask) {
- list_for_each_entry(temp, &disp->outps, head) {
- if ((temp->info.hasht == type) &&
- (temp->info.hashm & mask) == mask) {
- outp = temp;
- break;
- }
- }
- if (outp == NULL)
- return -ENXIO;
- }
-
- switch (mthd) {
- case NV50_DISP_SCANOUTPOS: {
- return nvkm_head_mthd_scanoutpos(object, head, data, size);
- }
- default:
- break;
- }
-
- switch (mthd * !!outp) {
- case NV50_DISP_MTHD_V1_ACQUIRE: {
- union {
- struct nv50_disp_acquire_v0 v0;
- } *args = data;
- int ret = -ENOSYS;
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
- ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, args->v0.hda);
- if (ret == 0) {
- args->v0.or = outp->ior->id;
- args->v0.link = outp->ior->asy.link;
- }
- }
- return ret;
- }
- break;
- case NV50_DISP_MTHD_V1_RELEASE:
- nvkm_outp_release(outp, NVKM_OUTP_USER);
- return 0;
- case NV50_DISP_MTHD_V1_SOR_HDA_ELD: {
- union {
- struct nv50_disp_sor_hda_eld_v0 v0;
- } *args = data;
- struct nvkm_ior *ior = outp->ior;
- int ret = -ENOSYS;
-
- nvif_ioctl(object, "disp sor hda eld size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
- nvif_ioctl(object, "disp sor hda eld vers %d\n",
- args->v0.version);
- if (size > 0x60)
- return -E2BIG;
- } else
- return ret;
-
- if (!ior->hda)
- return -ENODEV;
-
- if (size && args->v0.data[0]) {
- if (outp->info.type == DCB_OUTPUT_DP)
- ior->func->dp->audio(ior, hidx, true);
- ior->func->hda->hpd(ior, hidx, true);
- ior->func->hda->eld(ior, hidx, data, size);
- } else {
- if (outp->info.type == DCB_OUTPUT_DP)
- ior->func->dp->audio(ior, hidx, false);
- ior->func->hda->hpd(ior, hidx, false);
- }
-
- return 0;
- }
- break;
- case NV50_DISP_MTHD_V1_SOR_HDMI_PWR: {
- union {
- struct nv50_disp_sor_hdmi_pwr_v0 v0;
- } *args = data;
- u8 *vendor, vendor_size;
- u8 *avi, avi_size;
- int ret = -ENOSYS;
-
- nvif_ioctl(object, "disp sor hdmi ctrl size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
- nvif_ioctl(object, "disp sor hdmi ctrl vers %d state %d "
- "max_ac_packet %d rekey %d scdc %d\n",
- args->v0.version, args->v0.state,
- args->v0.max_ac_packet, args->v0.rekey,
- args->v0.scdc);
- if (args->v0.max_ac_packet > 0x1f || args->v0.rekey > 0x7f)
- return -EINVAL;
- if ((args->v0.avi_infoframe_length
- + args->v0.vendor_infoframe_length) > size)
- return -EINVAL;
- else
- if ((args->v0.avi_infoframe_length
- + args->v0.vendor_infoframe_length) < size)
- return -E2BIG;
- avi = data;
- avi_size = args->v0.avi_infoframe_length;
- vendor = avi + avi_size;
- vendor_size = args->v0.vendor_infoframe_length;
- } else
- return ret;
-
- if (!outp->ior->func->hdmi.ctrl)
- return -ENODEV;
-
- outp->ior->func->hdmi.ctrl(outp->ior, hidx, args->v0.state,
- args->v0.max_ac_packet,
- args->v0.rekey, avi, avi_size,
- vendor, vendor_size);
-
- if (outp->ior->func->hdmi.scdc)
- outp->ior->func->hdmi.scdc(outp->ior, args->v0.scdc);
-
- return 0;
- }
- break;
- case NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT: {
- union {
- struct nv50_disp_sor_lvds_script_v0 v0;
- } *args = data;
- int ret = -ENOSYS;
- nvif_ioctl(object, "disp sor lvds script size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
- nvif_ioctl(object, "disp sor lvds script "
- "vers %d name %04x\n",
- args->v0.version, args->v0.script);
- disp->sor.lvdsconf = args->v0.script;
- return 0;
- } else
- return ret;
- }
- break;
- case NV50_DISP_MTHD_V1_SOR_DP_MST_LINK: {
- union {
- struct nv50_disp_sor_dp_mst_link_v0 v0;
- } *args = data;
- int ret = -ENOSYS;
- nvif_ioctl(object, "disp sor dp mst link size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
- nvif_ioctl(object, "disp sor dp mst link vers %d state %d\n",
- args->v0.version, args->v0.state);
- outp->dp.lt.mst = !!args->v0.state;
- return 0;
- } else
- return ret;
- }
- break;
- case NV50_DISP_MTHD_V1_SOR_DP_MST_VCPI: {
- union {
- struct nv50_disp_sor_dp_mst_vcpi_v0 v0;
- } *args = data;
- int ret = -ENOSYS;
- nvif_ioctl(object, "disp sor dp mst vcpi size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
- nvif_ioctl(object, "disp sor dp mst vcpi vers %d "
- "slot %02x/%02x pbn %04x/%04x\n",
- args->v0.version, args->v0.start_slot,
- args->v0.num_slots, args->v0.pbn,
- args->v0.aligned_pbn);
- if (!outp->ior->func->dp->vcpi)
- return -ENODEV;
- outp->ior->func->dp->vcpi(outp->ior, hidx,
- args->v0.start_slot,
- args->v0.num_slots,
- args->v0.pbn,
- args->v0.aligned_pbn);
- return 0;
- } else
- return ret;
- }
- break;
- default:
- break;
- }
-
- return -EINVAL;
-}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c
index e4ad1a6f6c88..f5242a672279 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c
@@ -88,10 +88,7 @@ tu102_sor = {
.state = gv100_sor_state,
.power = nv50_sor_power,
.clock = gf119_sor_clock,
- .hdmi = {
- .ctrl = gv100_sor_hdmi_ctrl,
- .scdc = gm200_sor_hdmi_scdc,
- },
+ .hdmi = &gv100_sor_hdmi,
.dp = &tu102_sor_dp,
.hda = &gv100_sor_hda,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
index fd9f18144c26..dad942be6679 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
@@ -21,12 +21,86 @@
*/
#define nvkm_uconn(p) container_of((p), struct nvkm_conn, object)
#include "conn.h"
+#include "outp.h"
+#include <core/client.h>
+#include <core/event.h>
#include <subdev/gpio.h>
+#include <subdev/i2c.h>
#include <nvif/if0011.h>
static int
+nvkm_uconn_uevent_aux(struct nvkm_object *object, u64 token, u32 bits)
+{
+ union nvif_conn_event_args args;
+
+ args.v0.version = 0;
+ args.v0.types = 0;
+ if (bits & NVKM_I2C_PLUG)
+ args.v0.types |= NVIF_CONN_EVENT_V0_PLUG;
+ if (bits & NVKM_I2C_UNPLUG)
+ args.v0.types |= NVIF_CONN_EVENT_V0_UNPLUG;
+ if (bits & NVKM_I2C_IRQ)
+ args.v0.types |= NVIF_CONN_EVENT_V0_IRQ;
+
+ return object->client->event(token, &args, sizeof(args.v0));
+}
+
+static int
+nvkm_uconn_uevent_gpio(struct nvkm_object *object, u64 token, u32 bits)
+{
+ union nvif_conn_event_args args;
+
+ args.v0.version = 0;
+ args.v0.types = 0;
+ if (bits & NVKM_GPIO_HI)
+ args.v0.types |= NVIF_CONN_EVENT_V0_PLUG;
+ if (bits & NVKM_GPIO_LO)
+ args.v0.types |= NVIF_CONN_EVENT_V0_UNPLUG;
+
+ return object->client->event(token, &args, sizeof(args.v0));
+}
+
+static int
+nvkm_uconn_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent)
+{
+ struct nvkm_conn *conn = nvkm_uconn(object);
+ struct nvkm_device *device = conn->disp->engine.subdev.device;
+ struct nvkm_outp *outp;
+ union nvif_conn_event_args *args = argv;
+ u64 bits = 0;
+
+ if (!uevent) {
+ if (conn->info.hpd == DCB_GPIO_UNUSED)
+ return -ENOSYS;
+ return 0;
+ }
+
+ if (argc != sizeof(args->v0) || args->v0.version != 0)
+ 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;
+
+ 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;
+
+ return nvkm_uevent_add(uevent, &device->gpio->event, conn->info.hpd, bits,
+ nvkm_uconn_uevent_gpio);
+}
+
+static int
nvkm_uconn_mthd_hpd_status(struct nvkm_conn *conn, void *argv, u32 argc)
{
struct nvkm_gpio *gpio = conn->disp->engine.subdev.device->gpio;
@@ -82,6 +156,7 @@ static const struct nvkm_object_func
nvkm_uconn = {
.dtor = nvkm_uconn_dtor,
.mthd = nvkm_uconn_mthd,
+ .uevent = nvkm_uconn_uevent,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c
index 0841e7ce0343..0268d1d75805 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c
@@ -21,6 +21,7 @@
*/
#include "priv.h"
#include "conn.h"
+#include "head.h"
#include "outp.h"
#include <nvif/class.h>
@@ -43,6 +44,12 @@ nvkm_udisp_sclass(struct nvkm_object *object, int index, struct nvkm_oclass *scl
return 0;
}
+ if (index-- == 0) {
+ sclass->base = (struct nvkm_sclass) { 0, 0, NVIF_CLASS_HEAD };
+ sclass->ctor = nvkm_uhead_new;
+ return 0;
+ }
+
if (disp->func->user[index].ctor) {
sclass->base = disp->func->user[index].base;
sclass->ctor = disp->func->user[index].ctor;
@@ -52,17 +59,6 @@ nvkm_udisp_sclass(struct nvkm_object *object, int index, struct nvkm_oclass *scl
return -EINVAL;
}
-static int
-nvkm_udisp_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc)
-{
- struct nvkm_disp *disp = nvkm_udisp(object);
-
- if (disp->engine.subdev.device->card_type >= NV_50)
- return nv50_disp_root_mthd_(object, mthd, argv, argc);
-
- return nv04_disp_mthd(object, mthd, argv, argc);
-}
-
static void *
nvkm_udisp_dtor(struct nvkm_object *object)
{
@@ -78,8 +74,6 @@ nvkm_udisp_dtor(struct nvkm_object *object)
static const struct nvkm_object_func
nvkm_udisp = {
.dtor = nvkm_udisp_dtor,
- .mthd = nvkm_udisp_mthd,
- .ntfy = nvkm_disp_ntfy,
.sclass = nvkm_udisp_sclass,
};
@@ -89,6 +83,7 @@ nvkm_udisp_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nv
struct nvkm_disp *disp = nvkm_disp(oclass->engine);
struct nvkm_conn *conn;
struct nvkm_outp *outp;
+ struct nvkm_head *head;
union nvif_disp_args *args = argv;
if (argc != sizeof(args->v0) || args->v0.version != 0)
@@ -111,5 +106,9 @@ nvkm_udisp_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nv
list_for_each_entry(outp, &disp->outps, head)
args->v0.outp_mask |= BIT(outp->index);
+ args->v0.head_mask = 0;
+ list_for_each_entry(head, &disp->heads, head)
+ args->v0.head_mask |= BIT(head->id);
+
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uhead.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uhead.c
new file mode 100644
index 000000000000..f072cec16040
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uhead.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2021 Red Hat 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.
+ */
+#define nvkm_uhead(p) container_of((p), struct nvkm_head, object)
+#include "head.h"
+#include <core/event.h>
+
+#include <nvif/if0013.h>
+
+#include <nvif/event.h>
+
+static int
+nvkm_uhead_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent)
+{
+ struct nvkm_head *head = nvkm_uhead(object);
+ union nvif_head_event_args *args = argv;
+
+ if (!uevent)
+ return 0;
+ if (argc != sizeof(args->vn))
+ return -ENOSYS;
+
+ return nvkm_uevent_add(uevent, &head->disp->vblank, head->id,
+ NVKM_DISP_HEAD_EVENT_VBLANK, NULL);
+}
+
+static int
+nvkm_uhead_mthd_scanoutpos(struct nvkm_head *head, void *argv, u32 argc)
+{
+ union nvif_head_scanoutpos_args *args = argv;
+
+ if (argc != sizeof(args->v0) || args->v0.version != 0)
+ return -ENOSYS;
+
+ head->func->state(head, &head->arm);
+ args->v0.vtotal = head->arm.vtotal;
+ args->v0.vblanks = head->arm.vblanks;
+ args->v0.vblanke = head->arm.vblanke;
+ args->v0.htotal = head->arm.htotal;
+ args->v0.hblanks = head->arm.hblanks;
+ args->v0.hblanke = head->arm.hblanke;
+
+ /* We don't support reading htotal/vtotal on pre-NV50 VGA,
+ * so we have to give up and trigger the timestamping
+ * fallback in the drm core.
+ */
+ if (!args->v0.vtotal || !args->v0.htotal)
+ return -ENOTSUPP;
+
+ args->v0.time[0] = ktime_to_ns(ktime_get());
+ head->func->rgpos(head, &args->v0.hline, &args->v0.vline);
+ args->v0.time[1] = ktime_to_ns(ktime_get());
+ return 0;
+}
+
+static int
+nvkm_uhead_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc)
+{
+ struct nvkm_head *head = nvkm_uhead(object);
+
+ switch (mthd) {
+ case NVIF_HEAD_V0_SCANOUTPOS: return nvkm_uhead_mthd_scanoutpos(head, argv, argc);
+ default:
+ return -EINVAL;
+ }
+}
+
+static void *
+nvkm_uhead_dtor(struct nvkm_object *object)
+{
+ struct nvkm_head *head = nvkm_uhead(object);
+ struct nvkm_disp *disp = head->disp;
+
+ spin_lock(&disp->client.lock);
+ head->object.func = NULL;
+ spin_unlock(&disp->client.lock);
+ return NULL;
+}
+
+static const struct nvkm_object_func
+nvkm_uhead = {
+ .dtor = nvkm_uhead_dtor,
+ .mthd = nvkm_uhead_mthd,
+ .uevent = nvkm_uhead_uevent,
+};
+
+int
+nvkm_uhead_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **pobject)
+{
+ struct nvkm_disp *disp = nvkm_udisp(oclass->parent);
+ struct nvkm_head *head;
+ union nvif_head_args *args = argv;
+ int ret;
+
+ if (argc != sizeof(args->v0) || args->v0.version != 0)
+ return -ENOSYS;
+ if (!(head = nvkm_head_find(disp, args->v0.id)))
+ return -EINVAL;
+
+ ret = -EBUSY;
+ spin_lock(&disp->client.lock);
+ if (!head->object.func) {
+ nvkm_object_ctor(&nvkm_uhead, oclass, &head->object);
+ *pobject = &head->object;
+ ret = 0;
+ }
+ spin_unlock(&disp->client.lock);
+ return ret;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
index abedb3e86361..4f0ca709c85a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c
@@ -21,11 +21,238 @@
*/
#define nvkm_uoutp(p) container_of((p), struct nvkm_outp, object)
#include "outp.h"
+#include "dp.h"
+#include "head.h"
#include "ior.h"
#include <nvif/if0012.h>
static int
+nvkm_uoutp_mthd_dp_mst_vcpi(struct nvkm_outp *outp, void *argv, u32 argc)
+{
+ struct nvkm_ior *ior = outp->ior;
+ union nvif_outp_dp_mst_vcpi_args *args = argv;
+
+ if (argc != sizeof(args->v0) || args->v0.version != 0)
+ return -ENOSYS;
+ if (!ior->func->dp || !ior->func->dp->vcpi || !nvkm_head_find(outp->disp, args->v0.head))
+ return -EINVAL;
+
+ ior->func->dp->vcpi(ior, args->v0.head, args->v0.start_slot, args->v0.num_slots,
+ args->v0.pbn, args->v0.aligned_pbn);
+ return 0;
+}
+
+static int
+nvkm_uoutp_mthd_dp_retrain(struct nvkm_outp *outp, void *argv, u32 argc)
+{
+ union nvif_outp_dp_retrain_args *args = argv;
+
+ if (argc != sizeof(args->vn))
+ return -ENOSYS;
+
+ if (!atomic_read(&outp->dp.lt.done))
+ return 0;
+
+ return outp->func->acquire(outp);
+}
+
+static int
+nvkm_uoutp_mthd_dp_aux_pwr(struct nvkm_outp *outp, void *argv, u32 argc)
+{
+ union nvif_outp_dp_aux_pwr_args *args = argv;
+
+ if (argc != sizeof(args->v0) || args->v0.version != 0)
+ return -ENOSYS;
+
+ outp->dp.enabled = !!args->v0.state;
+ nvkm_dp_enable(outp, outp->dp.enabled);
+ return 0;
+}
+
+static int
+nvkm_uoutp_mthd_hda_eld(struct nvkm_outp *outp, void *argv, u32 argc)
+{
+ struct nvkm_ior *ior = outp->ior;
+ union nvif_outp_hda_eld_args *args = argv;
+
+ if (argc < sizeof(args->v0) || args->v0.version != 0)
+ return -ENOSYS;
+ argc -= sizeof(args->v0);
+
+ if (!ior->hda || !nvkm_head_find(outp->disp, args->v0.head))
+ return -EINVAL;
+ if (argc > 0x60)
+ return -E2BIG;
+
+ if (argc && args->v0.data[0]) {
+ if (outp->info.type == DCB_OUTPUT_DP)
+ ior->func->dp->audio(ior, args->v0.head, true);
+ ior->func->hda->hpd(ior, args->v0.head, true);
+ ior->func->hda->eld(ior, args->v0.head, args->v0.data, argc);
+ } else {
+ if (outp->info.type == DCB_OUTPUT_DP)
+ ior->func->dp->audio(ior, args->v0.head, false);
+ ior->func->hda->hpd(ior, args->v0.head, false);
+ }
+
+ return 0;
+}
+
+static int
+nvkm_uoutp_mthd_infoframe(struct nvkm_outp *outp, void *argv, u32 argc)
+{
+ struct nvkm_ior *ior = outp->ior;
+ union nvif_outp_infoframe_args *args = argv;
+ ssize_t size = argc - sizeof(*args);
+
+ if (argc < sizeof(args->v0) || args->v0.version != 0)
+ return -ENOSYS;
+ if (!nvkm_head_find(outp->disp, args->v0.head))
+ return -EINVAL;
+
+ switch (ior->func->hdmi ? args->v0.type : 0xff) {
+ case NVIF_OUTP_INFOFRAME_V0_AVI:
+ ior->func->hdmi->infoframe_avi(ior, args->v0.head, &args->v0.data, size);
+ return 0;
+ case NVIF_OUTP_INFOFRAME_V0_VSI:
+ ior->func->hdmi->infoframe_vsi(ior, args->v0.head, &args->v0.data, size);
+ return 0;
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static int
+nvkm_uoutp_mthd_release(struct nvkm_outp *outp, void *argv, u32 argc)
+{
+ struct nvkm_head *head = outp->asy.head;
+ struct nvkm_ior *ior = outp->ior;
+ union nvif_outp_release_args *args = argv;
+
+ if (argc != sizeof(args->vn))
+ return -ENOSYS;
+
+ if (ior->func->hdmi && head) {
+ ior->func->hdmi->infoframe_avi(ior, head->id, NULL, 0);
+ ior->func->hdmi->infoframe_vsi(ior, head->id, NULL, 0);
+ ior->func->hdmi->ctrl(ior, head->id, false, 0, 0);
+ }
+
+ nvkm_outp_release(outp, NVKM_OUTP_USER);
+ return 0;
+}
+
+static int
+nvkm_uoutp_mthd_acquire_dp(struct nvkm_outp *outp, u8 dpcd[16],
+ u8 link_nr, u8 link_bw, bool hda, bool mst)
+{
+ int ret;
+
+ ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, hda);
+ if (ret)
+ return ret;
+
+ memcpy(outp->dp.dpcd, dpcd, sizeof(outp->dp.dpcd));
+ outp->dp.lt.nr = link_nr;
+ outp->dp.lt.bw = link_bw;
+ outp->dp.lt.mst = mst;
+ return 0;
+}
+
+static int
+nvkm_uoutp_mthd_acquire_tmds(struct nvkm_outp *outp, u8 head, u8 hdmi, u8 hdmi_max_ac_packet,
+ u8 hdmi_rekey, u8 hdmi_scdc, u8 hdmi_hda)
+{
+ struct nvkm_ior *ior;
+ int ret;
+
+ if (!(outp->asy.head = nvkm_head_find(outp->disp, head)))
+ return -EINVAL;
+
+ ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, hdmi && hdmi_hda);
+ if (ret)
+ return ret;
+
+ ior = outp->ior;
+
+ if (hdmi) {
+ if (!ior->func->hdmi ||
+ hdmi_max_ac_packet > 0x1f || hdmi_rekey > 0x7f ||
+ (hdmi_scdc && !ior->func->hdmi->scdc)) {
+ nvkm_outp_release(outp, NVKM_OUTP_USER);
+ return -EINVAL;
+ }
+
+ ior->func->hdmi->ctrl(ior, head, hdmi, hdmi_max_ac_packet, hdmi_rekey);
+ if (ior->func->hdmi->scdc)
+ ior->func->hdmi->scdc(ior, hdmi_scdc);
+ }
+
+ return 0;
+}
+
+static int
+nvkm_uoutp_mthd_acquire_lvds(struct nvkm_outp *outp, bool dual, bool bpc8)
+{
+ if (outp->info.type != DCB_OUTPUT_LVDS)
+ return -EINVAL;
+
+ outp->lvds.dual = dual;
+ outp->lvds.bpc8 = bpc8;
+
+ return nvkm_outp_acquire(outp, NVKM_OUTP_USER, false);
+}
+
+static int
+nvkm_uoutp_mthd_acquire(struct nvkm_outp *outp, void *argv, u32 argc)
+{
+ union nvif_outp_acquire_args *args = argv;
+ int ret;
+
+ if (argc != sizeof(args->v0) || args->v0.version != 0)
+ return -ENOSYS;
+ if (outp->ior)
+ return -EBUSY;
+
+ switch (args->v0.proto) {
+ case NVIF_OUTP_ACQUIRE_V0_RGB_CRT:
+ ret = nvkm_outp_acquire(outp, NVKM_OUTP_USER, false);
+ break;
+ case NVIF_OUTP_ACQUIRE_V0_TMDS:
+ ret = nvkm_uoutp_mthd_acquire_tmds(outp, args->v0.tmds.head,
+ args->v0.tmds.hdmi,
+ args->v0.tmds.hdmi_max_ac_packet,
+ args->v0.tmds.hdmi_rekey,
+ args->v0.tmds.hdmi_scdc,
+ args->v0.tmds.hdmi_hda);
+ break;
+ case NVIF_OUTP_ACQUIRE_V0_LVDS:
+ ret = nvkm_uoutp_mthd_acquire_lvds(outp, args->v0.lvds.dual, args->v0.lvds.bpc8);
+ break;
+ case NVIF_OUTP_ACQUIRE_V0_DP:
+ ret = nvkm_uoutp_mthd_acquire_dp(outp, args->v0.dp.dpcd,
+ args->v0.dp.link_nr,
+ args->v0.dp.link_bw,
+ args->v0.dp.hda != 0,
+ args->v0.dp.mst != 0);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ if (ret)
+ return ret;
+
+ args->v0.or = outp->ior->id;
+ args->v0.link = outp->ior->asy.link;
+ return 0;
+}
+
+static int
nvkm_uoutp_mthd_load_detect(struct nvkm_outp *outp, void *argv, u32 argc)
{
union nvif_outp_load_detect_args *args = argv;
@@ -49,10 +276,28 @@ nvkm_uoutp_mthd_load_detect(struct nvkm_outp *outp, void *argv, u32 argc)
}
static int
+nvkm_uoutp_mthd_acquired(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc)
+{
+ switch (mthd) {
+ case NVIF_OUTP_V0_RELEASE : return nvkm_uoutp_mthd_release (outp, argv, argc);
+ case NVIF_OUTP_V0_INFOFRAME : return nvkm_uoutp_mthd_infoframe (outp, argv, argc);
+ case NVIF_OUTP_V0_HDA_ELD : return nvkm_uoutp_mthd_hda_eld (outp, argv, argc);
+ case NVIF_OUTP_V0_DP_RETRAIN : return nvkm_uoutp_mthd_dp_retrain (outp, argv, argc);
+ case NVIF_OUTP_V0_DP_MST_VCPI: return nvkm_uoutp_mthd_dp_mst_vcpi(outp, argv, argc);
+ default:
+ break;
+ }
+
+ return -EINVAL;
+}
+
+static int
nvkm_uoutp_mthd_noacquire(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc)
{
switch (mthd) {
case NVIF_OUTP_V0_LOAD_DETECT: return nvkm_uoutp_mthd_load_detect(outp, argv, argc);
+ case NVIF_OUTP_V0_ACQUIRE : return nvkm_uoutp_mthd_acquire (outp, argv, argc);
+ case NVIF_OUTP_V0_DP_AUX_PWR : return nvkm_uoutp_mthd_dp_aux_pwr (outp, argv, argc);
default:
break;
}
@@ -73,6 +318,11 @@ nvkm_uoutp_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc)
if (ret <= 0)
goto done;
+ if (outp->ior)
+ ret = nvkm_uoutp_mthd_acquired(outp, mthd, argv, argc);
+ else
+ ret = -EIO;
+
done:
mutex_unlock(&disp->super.mutex);
return ret;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
index 43b7dec45179..d619b40a42c3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c
@@ -65,10 +65,10 @@ nvkm_falcon_intr(struct nvkm_engine *engine)
u32 dest = nvkm_rd32(device, base + 0x01c);
u32 intr = nvkm_rd32(device, base + 0x008) & dest & ~(dest >> 16);
u32 inst = nvkm_rd32(device, base + 0x050) & 0x3fffffff;
- struct nvkm_fifo_chan *chan;
+ struct nvkm_chan *chan;
unsigned long flags;
- chan = nvkm_fifo_chan_inst(device->fifo, (u64)inst << 12, &flags);
+ chan = nvkm_chan_get_inst(engine, (u64)inst << 12, &flags);
if (intr & 0x00000040) {
if (falcon->func->intr) {
@@ -89,7 +89,7 @@ nvkm_falcon_intr(struct nvkm_engine *engine)
nvkm_wr32(device, base + 0x004, intr);
}
- nvkm_fifo_chan_put(device->fifo, flags, &chan);
+ nvkm_chan_put(&chan, flags);
}
static int
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild
index 5e831d347a95..5a074b9970ab 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild
@@ -1,11 +1,18 @@
# SPDX-License-Identifier: MIT
nvkm-y += nvkm/engine/fifo/base.o
+nvkm-y += nvkm/engine/fifo/cgrp.o
+nvkm-y += nvkm/engine/fifo/chan.o
+nvkm-y += nvkm/engine/fifo/chid.o
+nvkm-y += nvkm/engine/fifo/runl.o
+nvkm-y += nvkm/engine/fifo/runq.o
+
nvkm-y += nvkm/engine/fifo/nv04.o
nvkm-y += nvkm/engine/fifo/nv10.o
nvkm-y += nvkm/engine/fifo/nv17.o
nvkm-y += nvkm/engine/fifo/nv40.o
nvkm-y += nvkm/engine/fifo/nv50.o
nvkm-y += nvkm/engine/fifo/g84.o
+nvkm-y += nvkm/engine/fifo/g98.o
nvkm-y += nvkm/engine/fifo/gf100.o
nvkm-y += nvkm/engine/fifo/gk104.o
nvkm-y += nvkm/engine/fifo/gk110.o
@@ -13,28 +20,11 @@ nvkm-y += nvkm/engine/fifo/gk208.o
nvkm-y += nvkm/engine/fifo/gk20a.o
nvkm-y += nvkm/engine/fifo/gm107.o
nvkm-y += nvkm/engine/fifo/gm200.o
-nvkm-y += nvkm/engine/fifo/gm20b.o
nvkm-y += nvkm/engine/fifo/gp100.o
-nvkm-y += nvkm/engine/fifo/gp10b.o
nvkm-y += nvkm/engine/fifo/gv100.o
nvkm-y += nvkm/engine/fifo/tu102.o
+nvkm-y += nvkm/engine/fifo/ga100.o
nvkm-y += nvkm/engine/fifo/ga102.o
-nvkm-y += nvkm/engine/fifo/chan.o
-nvkm-y += nvkm/engine/fifo/channv50.o
-nvkm-y += nvkm/engine/fifo/chang84.o
-
-nvkm-y += nvkm/engine/fifo/dmanv04.o
-nvkm-y += nvkm/engine/fifo/dmanv10.o
-nvkm-y += nvkm/engine/fifo/dmanv17.o
-nvkm-y += nvkm/engine/fifo/dmanv40.o
-
-nvkm-y += nvkm/engine/fifo/gpfifonv50.o
-nvkm-y += nvkm/engine/fifo/gpfifog84.o
-nvkm-y += nvkm/engine/fifo/gpfifogf100.o
-nvkm-y += nvkm/engine/fifo/gpfifogk104.o
-nvkm-y += nvkm/engine/fifo/gpfifogv100.o
-nvkm-y += nvkm/engine/fifo/gpfifotu102.o
-
-nvkm-y += nvkm/engine/fifo/usergv100.o
-nvkm-y += nvkm/engine/fifo/usertu102.o
+nvkm-y += nvkm/engine/fifo/ucgrp.o
+nvkm-y += nvkm/engine/fifo/uchan.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
index 58b8df75fc40..5ea9a2ff0663 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c
@@ -23,25 +23,32 @@
*/
#include "priv.h"
#include "chan.h"
+#include "chid.h"
+#include "runl.h"
+#include "runq.h"
-#include <core/client.h>
#include <core/gpuobj.h>
-#include <core/notify.h>
+#include <subdev/bar.h>
#include <subdev/mc.h>
+#include <subdev/mmu.h>
-#include <nvif/event.h>
#include <nvif/cl0080.h>
#include <nvif/unpack.h>
-void
-nvkm_fifo_recover_chan(struct nvkm_fifo *fifo, int chid)
+bool
+nvkm_fifo_ctxsw_in_progress(struct nvkm_engine *engine)
{
- unsigned long flags;
- if (WARN_ON(!fifo->func->recover_chan))
- return;
- spin_lock_irqsave(&fifo->lock, flags);
- fifo->func->recover_chan(fifo, chid);
- spin_unlock_irqrestore(&fifo->lock, flags);
+ struct nvkm_runl *runl;
+ struct nvkm_engn *engn;
+
+ nvkm_runl_foreach(runl, engine->subdev.device->fifo) {
+ nvkm_runl_foreach_engn(engn, runl) {
+ if (engn->engine == engine)
+ return engn->func->chsw ? engn->func->chsw(engn) : false;
+ }
+ }
+
+ return false;
}
void
@@ -59,160 +66,23 @@ nvkm_fifo_start(struct nvkm_fifo *fifo, unsigned long *flags)
void
nvkm_fifo_fault(struct nvkm_fifo *fifo, struct nvkm_fault_data *info)
{
- return fifo->func->fault(fifo, info);
-}
-
-void
-nvkm_fifo_chan_put(struct nvkm_fifo *fifo, unsigned long flags,
- struct nvkm_fifo_chan **pchan)
-{
- struct nvkm_fifo_chan *chan = *pchan;
- if (likely(chan)) {
- *pchan = NULL;
- spin_unlock_irqrestore(&fifo->lock, flags);
- }
-}
-
-struct nvkm_fifo_chan *
-nvkm_fifo_chan_inst_locked(struct nvkm_fifo *fifo, u64 inst)
-{
- struct nvkm_fifo_chan *chan;
- list_for_each_entry(chan, &fifo->chan, head) {
- if (chan->inst->addr == inst) {
- list_del(&chan->head);
- list_add(&chan->head, &fifo->chan);
- return chan;
- }
- }
- return NULL;
-}
-
-struct nvkm_fifo_chan *
-nvkm_fifo_chan_inst(struct nvkm_fifo *fifo, u64 inst, unsigned long *rflags)
-{
- struct nvkm_fifo_chan *chan;
- unsigned long flags;
- spin_lock_irqsave(&fifo->lock, flags);
- if ((chan = nvkm_fifo_chan_inst_locked(fifo, inst))) {
- *rflags = flags;
- return chan;
- }
- spin_unlock_irqrestore(&fifo->lock, flags);
- return NULL;
-}
-
-struct nvkm_fifo_chan *
-nvkm_fifo_chan_chid(struct nvkm_fifo *fifo, int chid, unsigned long *rflags)
-{
- struct nvkm_fifo_chan *chan;
- unsigned long flags;
- spin_lock_irqsave(&fifo->lock, flags);
- list_for_each_entry(chan, &fifo->chan, head) {
- if (chan->chid == chid) {
- list_del(&chan->head);
- list_add(&chan->head, &fifo->chan);
- *rflags = flags;
- return chan;
- }
- }
- spin_unlock_irqrestore(&fifo->lock, flags);
- return NULL;
-}
-
-void
-nvkm_fifo_kevent(struct nvkm_fifo *fifo, int chid)
-{
- nvkm_event_send(&fifo->kevent, 1, chid, NULL, 0);
-}
-
-static int
-nvkm_fifo_kevent_ctor(struct nvkm_object *object, void *data, u32 size,
- struct nvkm_notify *notify)
-{
- struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
- if (size == 0) {
- notify->size = 0;
- notify->types = 1;
- notify->index = chan->chid;
- return 0;
- }
- return -ENOSYS;
-}
-
-static const struct nvkm_event_func
-nvkm_fifo_kevent_func = {
- .ctor = nvkm_fifo_kevent_ctor,
-};
-
-static void
-nvkm_fifo_uevent_fini(struct nvkm_event *event, int type, int index)
-{
- struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent);
- fifo->func->uevent_fini(fifo);
-}
-
-static void
-nvkm_fifo_uevent_init(struct nvkm_event *event, int type, int index)
-{
- struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), uevent);
- fifo->func->uevent_init(fifo);
-}
-
-static int
-nvkm_fifo_uevent_ctor(struct nvkm_object *object, void *data, u32 size,
- struct nvkm_notify *notify)
-{
- union {
- struct nvif_notify_uevent_req none;
- } *req = data;
- int ret = -ENOSYS;
-
- if (!(ret = nvif_unvers(ret, &data, &size, req->none))) {
- notify->size = sizeof(struct nvif_notify_uevent_rep);
- notify->types = 1;
- notify->index = 0;
- }
-
- return ret;
-}
-
-static const struct nvkm_event_func
-nvkm_fifo_uevent_func = {
- .ctor = nvkm_fifo_uevent_ctor,
- .init = nvkm_fifo_uevent_init,
- .fini = nvkm_fifo_uevent_fini,
-};
-
-void
-nvkm_fifo_uevent(struct nvkm_fifo *fifo)
-{
- struct nvif_notify_uevent_rep rep = {
- };
- nvkm_event_send(&fifo->uevent, 1, 0, &rep, sizeof(rep));
+ return fifo->func->mmu_fault->recover(fifo, info);
}
static int
-nvkm_fifo_class_new_(struct nvkm_device *device,
- const struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+nvkm_fifo_class_new(struct nvkm_device *device, const struct nvkm_oclass *oclass,
+ void *argv, u32 argc, struct nvkm_object **pobject)
{
struct nvkm_fifo *fifo = nvkm_fifo(oclass->engine);
- return fifo->func->class_new(fifo, oclass, data, size, pobject);
-}
-static const struct nvkm_device_oclass
-nvkm_fifo_class_ = {
- .ctor = nvkm_fifo_class_new_,
-};
+ if (oclass->engn == &fifo->func->cgrp.user)
+ return nvkm_ucgrp_new(fifo, oclass, argv, argc, pobject);
-static int
-nvkm_fifo_class_new(struct nvkm_device *device,
- const struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
-{
- const struct nvkm_fifo_chan_oclass *sclass = oclass->engn;
- struct nvkm_fifo *fifo = nvkm_fifo(oclass->engine);
- return sclass->ctor(fifo, oclass, data, size, pobject);
+ if (oclass->engn == &fifo->func->chan.user)
+ return nvkm_uchan_new(fifo, NULL, oclass, argv, argc, pobject);
+
+ WARN_ON(1);
+ return -ENOSYS;
}
static const struct nvkm_device_oclass
@@ -221,24 +91,28 @@ nvkm_fifo_class = {
};
static int
-nvkm_fifo_class_get(struct nvkm_oclass *oclass, int index,
- const struct nvkm_device_oclass **class)
+nvkm_fifo_class_get(struct nvkm_oclass *oclass, int index, const struct nvkm_device_oclass **class)
{
struct nvkm_fifo *fifo = nvkm_fifo(oclass->engine);
- const struct nvkm_fifo_chan_oclass *sclass;
+ const struct nvkm_fifo_func_cgrp *cgrp = &fifo->func->cgrp;
+ const struct nvkm_fifo_func_chan *chan = &fifo->func->chan;
int c = 0;
- if (fifo->func->class_get) {
- int ret = fifo->func->class_get(fifo, index, oclass);
- if (ret == 0)
- *class = &nvkm_fifo_class_;
- return ret;
+ /* *_CHANNEL_GROUP_* */
+ if (cgrp->user.oclass) {
+ if (c++ == index) {
+ oclass->base = cgrp->user;
+ oclass->engn = &fifo->func->cgrp.user;
+ *class = &nvkm_fifo_class;
+ return 0;
+ }
}
- while ((sclass = fifo->func->chan[c])) {
+ /* *_CHANNEL_DMA, *_CHANNEL_GPFIFO_* */
+ if (chan->user.oclass) {
if (c++ == index) {
- oclass->base = sclass->base;
- oclass->engn = sclass;
+ oclass->base = chan->user;
+ oclass->engn = &fifo->func->chan.user;
*class = &nvkm_fifo_class;
return 0;
}
@@ -247,19 +121,47 @@ nvkm_fifo_class_get(struct nvkm_oclass *oclass, int index,
return c;
}
-static void
-nvkm_fifo_intr(struct nvkm_engine *engine)
+static int
+nvkm_fifo_fini(struct nvkm_engine *engine, bool suspend)
{
struct nvkm_fifo *fifo = nvkm_fifo(engine);
- fifo->func->intr(fifo);
+ struct nvkm_runl *runl;
+
+ nvkm_inth_block(&fifo->engine.subdev.inth);
+
+ nvkm_runl_foreach(runl, fifo)
+ nvkm_runl_fini(runl);
+
+ return 0;
}
static int
-nvkm_fifo_fini(struct nvkm_engine *engine, bool suspend)
+nvkm_fifo_init(struct nvkm_engine *engine)
{
struct nvkm_fifo *fifo = nvkm_fifo(engine);
- if (fifo->func->fini)
- fifo->func->fini(fifo);
+ struct nvkm_runq *runq;
+ struct nvkm_runl *runl;
+ u32 mask = 0;
+
+ if (fifo->func->init_pbdmas) {
+ nvkm_runq_foreach(runq, fifo)
+ mask |= BIT(runq->id);
+
+ fifo->func->init_pbdmas(fifo, mask);
+
+ nvkm_runq_foreach(runq, fifo)
+ runq->func->init(runq);
+ }
+
+ nvkm_runl_foreach(runl, fifo) {
+ if (runl->func->init)
+ runl->func->init(runl);
+ }
+
+ if (fifo->func->init)
+ fifo->func->init(fifo);
+
+ nvkm_inth_allow(&fifo->engine.subdev.inth);
return 0;
}
@@ -267,22 +169,146 @@ static int
nvkm_fifo_info(struct nvkm_engine *engine, u64 mthd, u64 *data)
{
struct nvkm_fifo *fifo = nvkm_fifo(engine);
+ struct nvkm_runl *runl;
+ struct nvkm_engn *engn;
+ int ret;
+
+ ret = nvkm_subdev_oneinit(&fifo->engine.subdev);
+ if (ret)
+ return ret;
+
switch (mthd) {
- case NV_DEVICE_HOST_CHANNELS: *data = fifo->nr; return 0;
+ case NV_DEVICE_HOST_CHANNELS: *data = fifo->chid ? fifo->chid->nr : 0; return 0;
+ case NV_DEVICE_HOST_RUNLISTS:
+ *data = 0;
+ nvkm_runl_foreach(runl, fifo)
+ *data |= BIT(runl->id);
+ return 0;
+ case NV_DEVICE_HOST_RUNLIST_ENGINES:
+ runl = nvkm_runl_get(fifo, *data, 0);
+ if (runl) {
+ *data = 0;
+ nvkm_runl_foreach_engn(engn, runl) {
+#define CASE(n) case NVKM_ENGINE_##n: *data |= NV_DEVICE_HOST_RUNLIST_ENGINES_##n; break
+ switch (engn->engine->subdev.type) {
+ case NVKM_ENGINE_DMAOBJ:
+ break;
+ CASE(SW );
+ CASE(GR );
+ CASE(MPEG );
+ CASE(ME );
+ CASE(CIPHER);
+ CASE(BSP );
+ CASE(VP );
+ CASE(CE );
+ CASE(SEC );
+ CASE(MSVLD );
+ CASE(MSPDEC);
+ CASE(MSPPP );
+ CASE(MSENC );
+ CASE(VIC );
+ CASE(SEC2 );
+ CASE(NVDEC );
+ CASE(NVENC );
+ default:
+ WARN_ON(1);
+ break;
+ }
+#undef CASE
+ }
+ return 0;
+ }
+ return -EINVAL;
+ case NV_DEVICE_HOST_RUNLIST_CHANNELS:
+ if (!fifo->chid) {
+ runl = nvkm_runl_get(fifo, *data, 0);
+ if (runl) {
+ *data = runl->chid->nr;
+ return 0;
+ }
+ }
+ return -EINVAL;
default:
- if (fifo->func->info)
- return fifo->func->info(fifo, mthd, data);
break;
}
+
return -ENOSYS;
}
static int
nvkm_fifo_oneinit(struct nvkm_engine *engine)
{
+ struct nvkm_subdev *subdev = &engine->subdev;
+ struct nvkm_device *device = subdev->device;
struct nvkm_fifo *fifo = nvkm_fifo(engine);
- if (fifo->func->oneinit)
- return fifo->func->oneinit(fifo);
+ struct nvkm_runl *runl;
+ struct nvkm_engn *engn;
+ int ret, nr, i;
+
+ /* Initialise CHID/CGID allocator(s) on GPUs where they aren't per-runlist. */
+ if (fifo->func->chid_nr) {
+ ret = fifo->func->chid_ctor(fifo, fifo->func->chid_nr(fifo));
+ if (ret)
+ return ret;
+ }
+
+ /* Create runqueues for each PBDMA. */
+ if (fifo->func->runq_nr) {
+ for (nr = fifo->func->runq_nr(fifo), i = 0; i < nr; i++) {
+ if (!nvkm_runq_new(fifo, i))
+ return -ENOMEM;
+ }
+ }
+
+ /* Create runlists. */
+ ret = fifo->func->runl_ctor(fifo);
+ if (ret)
+ return ret;
+
+ nvkm_runl_foreach(runl, fifo) {
+ RUNL_DEBUG(runl, "chan:%06x", runl->chan);
+ nvkm_runl_foreach_engn(engn, runl) {
+ ENGN_DEBUG(engn, "");
+ }
+ }
+
+ /* Register interrupt handler. */
+ if (fifo->func->intr) {
+ ret = nvkm_inth_add(&device->mc->intr, NVKM_INTR_SUBDEV, NVKM_INTR_PRIO_NORMAL,
+ subdev, fifo->func->intr, &subdev->inth);
+ if (ret) {
+ nvkm_error(subdev, "intr %d\n", ret);
+ return ret;
+ }
+ }
+
+ /* Initialise non-stall intr handling. */
+ if (fifo->func->nonstall_ctor) {
+ ret = fifo->func->nonstall_ctor(fifo);
+ if (ret) {
+ nvkm_error(subdev, "nonstall %d\n", ret);
+ }
+ }
+
+ /* Allocate USERD + BAR1 polling area. */
+ if (fifo->func->chan.func->userd->bar == 1) {
+ struct nvkm_vmm *bar1 = nvkm_bar_bar1_vmm(device);
+
+ ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, fifo->chid->nr *
+ fifo->func->chan.func->userd->size, 0, true,
+ &fifo->userd.mem);
+ if (ret)
+ return ret;
+
+ ret = nvkm_vmm_get(bar1, 12, nvkm_memory_size(fifo->userd.mem), &fifo->userd.bar1);
+ if (ret)
+ return ret;
+
+ ret = nvkm_memory_map(fifo->userd.mem, 0, bar1, fifo->userd.bar1, NULL, 0);
+ if (ret)
+ return ret;
+ }
+
return 0;
}
@@ -292,25 +318,28 @@ nvkm_fifo_preinit(struct nvkm_engine *engine)
nvkm_mc_reset(engine->subdev.device, NVKM_ENGINE_FIFO, 0);
}
-static int
-nvkm_fifo_init(struct nvkm_engine *engine)
-{
- struct nvkm_fifo *fifo = nvkm_fifo(engine);
- fifo->func->init(fifo);
- return 0;
-}
-
static void *
nvkm_fifo_dtor(struct nvkm_engine *engine)
{
struct nvkm_fifo *fifo = nvkm_fifo(engine);
- void *data = fifo;
- if (fifo->func->dtor)
- data = fifo->func->dtor(fifo);
- nvkm_event_fini(&fifo->kevent);
- nvkm_event_fini(&fifo->uevent);
+ struct nvkm_runl *runl, *runt;
+ struct nvkm_runq *runq, *rtmp;
+
+ if (fifo->userd.bar1)
+ nvkm_vmm_put(nvkm_bar_bar1_vmm(engine->subdev.device), &fifo->userd.bar1);
+ nvkm_memory_unref(&fifo->userd.mem);
+
+ list_for_each_entry_safe(runl, runt, &fifo->runls, head)
+ nvkm_runl_del(runl);
+ list_for_each_entry_safe(runq, rtmp, &fifo->runqs, head)
+ nvkm_runq_del(runq);
+
+ nvkm_chid_unref(&fifo->cgid);
+ nvkm_chid_unref(&fifo->chid);
+
+ nvkm_event_fini(&fifo->nonstall.event);
mutex_destroy(&fifo->mutex);
- return data;
+ return fifo;
}
static const struct nvkm_engine_func
@@ -321,37 +350,40 @@ nvkm_fifo = {
.info = nvkm_fifo_info,
.init = nvkm_fifo_init,
.fini = nvkm_fifo_fini,
- .intr = nvkm_fifo_intr,
.base.sclass = nvkm_fifo_class_get,
};
int
-nvkm_fifo_ctor(const struct nvkm_fifo_func *func, struct nvkm_device *device,
- enum nvkm_subdev_type type, int inst, int nr, struct nvkm_fifo *fifo)
+nvkm_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device,
+ enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo)
{
+ struct nvkm_fifo *fifo;
int ret;
+ if (!(fifo = *pfifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
+ return -ENOMEM;
+
fifo->func = func;
- INIT_LIST_HEAD(&fifo->chan);
+ INIT_LIST_HEAD(&fifo->runqs);
+ INIT_LIST_HEAD(&fifo->runls);
+ /*TODO: Needs to be >CTXSW_TIMEOUT, so RC can recover before this is hit.
+ * CTXSW_TIMEOUT HW default seems to differ between GPUs, so just a
+ * large number for now until we support changing it.
+ */
+ fifo->timeout.chan_msec = 10000;
spin_lock_init(&fifo->lock);
mutex_init(&fifo->mutex);
- if (WARN_ON(fifo->nr > NVKM_FIFO_CHID_NR))
- fifo->nr = NVKM_FIFO_CHID_NR;
- else
- fifo->nr = nr;
- bitmap_clear(fifo->mask, 0, fifo->nr);
-
ret = nvkm_engine_ctor(&nvkm_fifo, device, type, inst, true, &fifo->engine);
if (ret)
return ret;
- if (func->uevent_init) {
- ret = nvkm_event_init(&nvkm_fifo_uevent_func, 1, 1,
- &fifo->uevent);
+ if (func->nonstall) {
+ ret = nvkm_event_init(func->nonstall, &fifo->engine.subdev, 1, 1,
+ &fifo->nonstall.event);
if (ret)
return ret;
}
- return nvkm_event_init(&nvkm_fifo_kevent_func, 1, nr, &fifo->kevent);
+ return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c
new file mode 100644
index 000000000000..ea53fb3d5d06
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.c
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2021 Red Hat 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 "cgrp.h"
+#include "chan.h"
+#include "chid.h"
+#include "runl.h"
+#include "priv.h"
+
+#include <core/gpuobj.h>
+#include <subdev/mmu.h>
+
+static void
+nvkm_cgrp_ectx_put(struct nvkm_cgrp *cgrp, struct nvkm_ectx **pectx)
+{
+ struct nvkm_ectx *ectx = *pectx;
+
+ if (ectx) {
+ struct nvkm_engn *engn = ectx->engn;
+
+ if (refcount_dec_and_test(&ectx->refs)) {
+ CGRP_TRACE(cgrp, "dtor ectx %d[%s]", engn->id, engn->engine->subdev.name);
+ nvkm_object_del(&ectx->object);
+ list_del(&ectx->head);
+ kfree(ectx);
+ }
+
+ *pectx = NULL;
+ }
+}
+
+static int
+nvkm_cgrp_ectx_get(struct nvkm_cgrp *cgrp, struct nvkm_engn *engn, struct nvkm_ectx **pectx,
+ struct nvkm_chan *chan, struct nvkm_client *client)
+{
+ struct nvkm_engine *engine = engn->engine;
+ struct nvkm_oclass cclass = {
+ .client = client,
+ .engine = engine,
+ };
+ struct nvkm_ectx *ectx;
+ int ret = 0;
+
+ /* Look for an existing context for this engine in the channel group. */
+ ectx = nvkm_list_find(ectx, &cgrp->ectxs, head, ectx->engn == engn);
+ if (ectx) {
+ refcount_inc(&ectx->refs);
+ *pectx = ectx;
+ return 0;
+ }
+
+ /* Nope - create a fresh one. */
+ CGRP_TRACE(cgrp, "ctor ectx %d[%s]", engn->id, engn->engine->subdev.name);
+ if (!(ectx = *pectx = kzalloc(sizeof(*ectx), GFP_KERNEL)))
+ return -ENOMEM;
+
+ ectx->engn = engn;
+ refcount_set(&ectx->refs, 1);
+ refcount_set(&ectx->uses, 0);
+ list_add_tail(&ectx->head, &cgrp->ectxs);
+
+ /* Allocate the HW structures. */
+ if (engine->func->fifo.cclass)
+ ret = engine->func->fifo.cclass(chan, &cclass, &ectx->object);
+ else if (engine->func->cclass)
+ ret = nvkm_object_new_(engine->func->cclass, &cclass, NULL, 0, &ectx->object);
+
+ if (ret)
+ nvkm_cgrp_ectx_put(cgrp, pectx);
+
+ return ret;
+}
+
+void
+nvkm_cgrp_vctx_put(struct nvkm_cgrp *cgrp, struct nvkm_vctx **pvctx)
+{
+ struct nvkm_vctx *vctx = *pvctx;
+
+ if (vctx) {
+ struct nvkm_engn *engn = vctx->ectx->engn;
+
+ if (refcount_dec_and_test(&vctx->refs)) {
+ CGRP_TRACE(cgrp, "dtor vctx %d[%s]", engn->id, engn->engine->subdev.name);
+ nvkm_vmm_put(vctx->vmm, &vctx->vma);
+ nvkm_gpuobj_del(&vctx->inst);
+
+ nvkm_cgrp_ectx_put(cgrp, &vctx->ectx);
+ if (vctx->vmm) {
+ atomic_dec(&vctx->vmm->engref[engn->engine->subdev.type]);
+ nvkm_vmm_unref(&vctx->vmm);
+ }
+ list_del(&vctx->head);
+ kfree(vctx);
+ }
+
+ *pvctx = NULL;
+ }
+}
+
+int
+nvkm_cgrp_vctx_get(struct nvkm_cgrp *cgrp, struct nvkm_engn *engn, struct nvkm_chan *chan,
+ struct nvkm_vctx **pvctx, struct nvkm_client *client)
+{
+ struct nvkm_ectx *ectx;
+ struct nvkm_vctx *vctx;
+ int ret;
+
+ /* Look for an existing sub-context for this engine+VEID in the channel group. */
+ vctx = nvkm_list_find(vctx, &cgrp->vctxs, head,
+ vctx->ectx->engn == engn && vctx->vmm == chan->vmm);
+ if (vctx) {
+ refcount_inc(&vctx->refs);
+ *pvctx = vctx;
+ return 0;
+ }
+
+ /* Nope - create a fresh one. But, context first. */
+ ret = nvkm_cgrp_ectx_get(cgrp, engn, &ectx, chan, client);
+ if (ret) {
+ CGRP_ERROR(cgrp, "ectx %d[%s]: %d", engn->id, engn->engine->subdev.name, ret);
+ return ret;
+ }
+
+ /* Now, create the sub-context. */
+ CGRP_TRACE(cgrp, "ctor vctx %d[%s]", engn->id, engn->engine->subdev.name);
+ if (!(vctx = *pvctx = kzalloc(sizeof(*vctx), GFP_KERNEL))) {
+ nvkm_cgrp_ectx_put(cgrp, &ectx);
+ return -ENOMEM;
+ }
+
+ vctx->ectx = ectx;
+ vctx->vmm = nvkm_vmm_ref(chan->vmm);
+ refcount_set(&vctx->refs, 1);
+ list_add_tail(&vctx->head, &cgrp->vctxs);
+
+ /* MMU on some GPUs needs to know engine usage for TLB invalidation. */
+ if (vctx->vmm)
+ atomic_inc(&vctx->vmm->engref[engn->engine->subdev.type]);
+
+ /* Allocate the HW structures. */
+ if (engn->func->bind) {
+ ret = nvkm_object_bind(vctx->ectx->object, NULL, 0, &vctx->inst);
+ if (ret == 0 && engn->func->ctor)
+ ret = engn->func->ctor(engn, vctx);
+ }
+
+ if (ret)
+ nvkm_cgrp_vctx_put(cgrp, pvctx);
+
+ return ret;
+}
+
+static void
+nvkm_cgrp_del(struct kref *kref)
+{
+ struct nvkm_cgrp *cgrp = container_of(kref, typeof(*cgrp), kref);
+ struct nvkm_runl *runl = cgrp->runl;
+
+ if (runl->cgid)
+ nvkm_chid_put(runl->cgid, cgrp->id, &cgrp->lock);
+
+ mutex_destroy(&cgrp->mutex);
+ nvkm_vmm_unref(&cgrp->vmm);
+ kfree(cgrp);
+}
+
+void
+nvkm_cgrp_unref(struct nvkm_cgrp **pcgrp)
+{
+ struct nvkm_cgrp *cgrp = *pcgrp;
+
+ if (!cgrp)
+ return;
+
+ kref_put(&cgrp->kref, nvkm_cgrp_del);
+ *pcgrp = NULL;
+}
+
+struct nvkm_cgrp *
+nvkm_cgrp_ref(struct nvkm_cgrp *cgrp)
+{
+ if (cgrp)
+ kref_get(&cgrp->kref);
+
+ return cgrp;
+}
+
+void
+nvkm_cgrp_put(struct nvkm_cgrp **pcgrp, unsigned long irqflags)
+{
+ struct nvkm_cgrp *cgrp = *pcgrp;
+
+ if (!cgrp)
+ return;
+
+ *pcgrp = NULL;
+ spin_unlock_irqrestore(&cgrp->lock, irqflags);
+}
+
+int
+nvkm_cgrp_new(struct nvkm_runl *runl, const char *name, struct nvkm_vmm *vmm, bool hw,
+ struct nvkm_cgrp **pcgrp)
+{
+ struct nvkm_cgrp *cgrp;
+
+ if (!(cgrp = *pcgrp = kmalloc(sizeof(*cgrp), GFP_KERNEL)))
+ return -ENOMEM;
+
+ cgrp->func = runl->fifo->func->cgrp.func;
+ strscpy(cgrp->name, name, sizeof(cgrp->name));
+ cgrp->runl = runl;
+ cgrp->vmm = nvkm_vmm_ref(vmm);
+ cgrp->hw = hw;
+ cgrp->id = -1;
+ kref_init(&cgrp->kref);
+ INIT_LIST_HEAD(&cgrp->chans);
+ cgrp->chan_nr = 0;
+ spin_lock_init(&cgrp->lock);
+ INIT_LIST_HEAD(&cgrp->ectxs);
+ INIT_LIST_HEAD(&cgrp->vctxs);
+ mutex_init(&cgrp->mutex);
+ atomic_set(&cgrp->rc, NVKM_CGRP_RC_NONE);
+
+ if (runl->cgid) {
+ cgrp->id = nvkm_chid_get(runl->cgid, cgrp);
+ if (cgrp->id < 0) {
+ RUNL_ERROR(runl, "!cgids");
+ nvkm_cgrp_unref(pcgrp);
+ return -ENOSPC;
+ }
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h
index d0ac60b06720..5f6abd59a6ff 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/cgrp.h
@@ -1,11 +1,75 @@
-#ifndef __NVKM_FIFO_CGRP_H__
-#define __NVKM_FIFO_CGRP_H__
-#include "priv.h"
+/* SPDX-License-Identifier: MIT */
+#ifndef __NVKM_CGRP_H__
+#define __NVKM_CGRP_H__
+#include <core/os.h>
+struct nvkm_chan;
+struct nvkm_client;
+
+struct nvkm_vctx {
+ struct nvkm_ectx *ectx;
+ struct nvkm_vmm *vmm;
+ refcount_t refs;
+
+ struct nvkm_gpuobj *inst;
+ struct nvkm_vma *vma;
-struct nvkm_fifo_cgrp {
- int id;
struct list_head head;
- struct list_head chan;
+};
+
+struct nvkm_ectx {
+ struct nvkm_engn *engn;
+ refcount_t refs;
+ refcount_t uses;
+
+ struct nvkm_object *object;
+
+ struct list_head head;
+};
+
+struct nvkm_cgrp {
+ const struct nvkm_cgrp_func {
+ void (*preempt)(struct nvkm_cgrp *);
+ } *func;
+ char name[64];
+ struct nvkm_runl *runl;
+ struct nvkm_vmm *vmm;
+ bool hw;
+ int id;
+ struct kref kref;
+
+ struct list_head chans;
int chan_nr;
+
+ spinlock_t lock; /* protects irq handler channel (group) lookup */
+
+ struct list_head ectxs;
+ struct list_head vctxs;
+ struct mutex mutex;
+
+#define NVKM_CGRP_RC_NONE 0
+#define NVKM_CGRP_RC_PENDING 1
+#define NVKM_CGRP_RC_RUNNING 2
+ atomic_t rc;
+
+ struct list_head head;
};
+
+int nvkm_cgrp_new(struct nvkm_runl *, const char *name, struct nvkm_vmm *, bool hw,
+ struct nvkm_cgrp **);
+struct nvkm_cgrp *nvkm_cgrp_ref(struct nvkm_cgrp *);
+void nvkm_cgrp_unref(struct nvkm_cgrp **);
+int nvkm_cgrp_vctx_get(struct nvkm_cgrp *, struct nvkm_engn *, struct nvkm_chan *,
+ struct nvkm_vctx **, struct nvkm_client *);
+void nvkm_cgrp_vctx_put(struct nvkm_cgrp *, struct nvkm_vctx **);
+
+void nvkm_cgrp_put(struct nvkm_cgrp **, unsigned long irqflags);
+
+#define nvkm_cgrp_foreach_chan(chan,cgrp) list_for_each_entry((chan), &(cgrp)->chans, head)
+#define nvkm_cgrp_foreach_chan_safe(chan,ctmp,cgrp) \
+ list_for_each_entry_safe((chan), (ctmp), &(cgrp)->chans, head)
+
+#define CGRP_PRCLI(c,l,p,f,a...) RUNL_PRINT((c)->runl, l, p, "%04x:[%s]"f, (c)->id, (c)->name, ##a)
+#define CGRP_PRINT(c,l,p,f,a...) RUNL_PRINT((c)->runl, l, p, "%04x:"f, (c)->id, ##a)
+#define CGRP_ERROR(c,f,a...) CGRP_PRCLI((c), ERROR, err, " "f"\n", ##a)
+#define CGRP_TRACE(c,f,a...) CGRP_PRINT((c), TRACE, info, " "f"\n", ##a)
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
index 2e7f32cebf2a..b7c9d6115bce 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c
@@ -22,285 +22,265 @@
* Authors: Ben Skeggs
*/
#include "chan.h"
+#include "chid.h"
+#include "cgrp.h"
+#include "chid.h"
+#include "runl.h"
+#include "priv.h"
-#include <core/client.h>
-#include <core/gpuobj.h>
-#include <core/oproxy.h>
+#include <core/ramht.h>
#include <subdev/mmu.h>
#include <engine/dma.h>
-struct nvkm_fifo_chan_object {
- struct nvkm_oproxy oproxy;
- struct nvkm_fifo_chan *chan;
- int hash;
+#include <nvif/if0020.h>
+
+const struct nvkm_event_func
+nvkm_chan_event = {
};
-static struct nvkm_fifo_engn *
-nvkm_fifo_chan_engn(struct nvkm_fifo_chan *chan, struct nvkm_engine *engine)
+void
+nvkm_chan_cctx_bind(struct nvkm_chan *chan, struct nvkm_engn *engn, struct nvkm_cctx *cctx)
{
- int engi = chan->fifo->func->engine_id(chan->fifo, engine);
- if (engi >= 0)
- return &chan->engn[engi];
- return NULL;
+ struct nvkm_cgrp *cgrp = chan->cgrp;
+ struct nvkm_runl *runl = cgrp->runl;
+ struct nvkm_engine *engine = engn->engine;
+
+ if (!engn->func->bind)
+ return;
+
+ CHAN_TRACE(chan, "%sbind cctx %d[%s]", cctx ? "" : "un", engn->id, engine->subdev.name);
+
+ /* Prevent any channel in channel group from being rescheduled, kick them
+ * off host and any engine(s) they're loaded on.
+ */
+ if (cgrp->hw)
+ nvkm_runl_block(runl);
+ else
+ nvkm_chan_block(chan);
+ nvkm_chan_preempt(chan, true);
+
+ /* Update context pointer. */
+ engn->func->bind(engn, cctx, chan);
+
+ /* Resume normal operation. */
+ if (cgrp->hw)
+ nvkm_runl_allow(runl);
+ else
+ nvkm_chan_allow(chan);
}
-static int
-nvkm_fifo_chan_child_fini(struct nvkm_oproxy *base, bool suspend)
+void
+nvkm_chan_cctx_put(struct nvkm_chan *chan, struct nvkm_cctx **pcctx)
{
- struct nvkm_fifo_chan_object *object =
- container_of(base, typeof(*object), oproxy);
- struct nvkm_engine *engine = object->oproxy.object->engine;
- struct nvkm_fifo_chan *chan = object->chan;
- struct nvkm_fifo_engn *engn = nvkm_fifo_chan_engn(chan, engine);
- const char *name = engine->subdev.name;
- int ret = 0;
-
- if (--engn->usecount)
- return 0;
+ struct nvkm_cctx *cctx = *pcctx;
- if (chan->func->engine_fini) {
- ret = chan->func->engine_fini(chan, engine, suspend);
- if (ret) {
- nvif_error(&chan->object,
- "detach %s failed, %d\n", name, ret);
- return ret;
+ if (cctx) {
+ struct nvkm_engn *engn = cctx->vctx->ectx->engn;
+
+ if (refcount_dec_and_mutex_lock(&cctx->refs, &chan->cgrp->mutex)) {
+ CHAN_TRACE(chan, "dtor cctx %d[%s]", engn->id, engn->engine->subdev.name);
+ nvkm_cgrp_vctx_put(chan->cgrp, &cctx->vctx);
+ list_del(&cctx->head);
+ kfree(cctx);
+ mutex_unlock(&chan->cgrp->mutex);
}
- }
- if (engn->object) {
- ret = nvkm_object_fini(engn->object, suspend);
- if (ret && suspend)
- return ret;
+ *pcctx = NULL;
}
-
- nvif_trace(&chan->object, "detached %s\n", name);
- return ret;
}
-static int
-nvkm_fifo_chan_child_init(struct nvkm_oproxy *base)
+int
+nvkm_chan_cctx_get(struct nvkm_chan *chan, struct nvkm_engn *engn, struct nvkm_cctx **pcctx,
+ struct nvkm_client *client)
{
- struct nvkm_fifo_chan_object *object =
- container_of(base, typeof(*object), oproxy);
- struct nvkm_engine *engine = object->oproxy.object->engine;
- struct nvkm_fifo_chan *chan = object->chan;
- struct nvkm_fifo_engn *engn = nvkm_fifo_chan_engn(chan, engine);
- const char *name = engine->subdev.name;
+ struct nvkm_cgrp *cgrp = chan->cgrp;
+ struct nvkm_vctx *vctx;
+ struct nvkm_cctx *cctx;
int ret;
- if (engn->usecount++)
+ /* Look for an existing channel context for this engine+VEID. */
+ mutex_lock(&cgrp->mutex);
+ cctx = nvkm_list_find(cctx, &chan->cctxs, head,
+ cctx->vctx->ectx->engn == engn && cctx->vctx->vmm == chan->vmm);
+ if (cctx) {
+ refcount_inc(&cctx->refs);
+ *pcctx = cctx;
+ mutex_unlock(&chan->cgrp->mutex);
return 0;
+ }
- if (engn->object) {
- ret = nvkm_object_init(engn->object);
- if (ret)
- return ret;
+ /* Nope - create a fresh one. But, sub-context first. */
+ ret = nvkm_cgrp_vctx_get(cgrp, engn, chan, &vctx, client);
+ if (ret) {
+ CHAN_ERROR(chan, "vctx %d[%s]: %d", engn->id, engn->engine->subdev.name, ret);
+ goto done;
}
- if (chan->func->engine_init) {
- ret = chan->func->engine_init(chan, engine);
- if (ret) {
- nvif_error(&chan->object,
- "attach %s failed, %d\n", name, ret);
- return ret;
- }
+ /* Now, create the channel context - to track engine binding. */
+ CHAN_TRACE(chan, "ctor cctx %d[%s]", engn->id, engn->engine->subdev.name);
+ if (!(cctx = *pcctx = kzalloc(sizeof(*cctx), GFP_KERNEL))) {
+ nvkm_cgrp_vctx_put(cgrp, &vctx);
+ ret = -ENOMEM;
+ goto done;
}
- nvif_trace(&chan->object, "attached %s\n", name);
- return 0;
+ cctx->vctx = vctx;
+ refcount_set(&cctx->refs, 1);
+ refcount_set(&cctx->uses, 0);
+ list_add_tail(&cctx->head, &chan->cctxs);
+done:
+ mutex_unlock(&cgrp->mutex);
+ return ret;
}
-static void
-nvkm_fifo_chan_child_del(struct nvkm_oproxy *base)
+int
+nvkm_chan_preempt_locked(struct nvkm_chan *chan, bool wait)
{
- struct nvkm_fifo_chan_object *object =
- container_of(base, typeof(*object), oproxy);
- struct nvkm_engine *engine = object->oproxy.base.engine;
- struct nvkm_fifo_chan *chan = object->chan;
- struct nvkm_fifo_engn *engn = nvkm_fifo_chan_engn(chan, engine);
-
- if (chan->func->object_dtor)
- chan->func->object_dtor(chan, object->hash);
-
- if (!--engn->refcount) {
- if (chan->func->engine_dtor)
- chan->func->engine_dtor(chan, engine);
- nvkm_object_del(&engn->object);
- if (chan->vmm)
- atomic_dec(&chan->vmm->engref[engine->subdev.type]);
- }
-}
+ struct nvkm_runl *runl = chan->cgrp->runl;
-static const struct nvkm_oproxy_func
-nvkm_fifo_chan_child_func = {
- .dtor[0] = nvkm_fifo_chan_child_del,
- .init[0] = nvkm_fifo_chan_child_init,
- .fini[0] = nvkm_fifo_chan_child_fini,
-};
+ CHAN_TRACE(chan, "preempt");
+ chan->func->preempt(chan);
+ if (!wait)
+ return 0;
+
+ return nvkm_runl_preempt_wait(runl);
+}
-static int
-nvkm_fifo_chan_child_new(const struct nvkm_oclass *oclass, void *data, u32 size,
- struct nvkm_object **pobject)
+int
+nvkm_chan_preempt(struct nvkm_chan *chan, bool wait)
{
- struct nvkm_engine *engine = oclass->engine;
- struct nvkm_fifo_chan *chan = nvkm_fifo_chan(oclass->parent);
- struct nvkm_fifo_engn *engn = nvkm_fifo_chan_engn(chan, engine);
- struct nvkm_fifo_chan_object *object;
- int ret = 0;
+ int ret;
- if (!(object = kzalloc(sizeof(*object), GFP_KERNEL)))
- return -ENOMEM;
- nvkm_oproxy_ctor(&nvkm_fifo_chan_child_func, oclass, &object->oproxy);
- object->chan = chan;
- *pobject = &object->oproxy.base;
-
- if (!engn->refcount++) {
- struct nvkm_oclass cclass = {
- .client = oclass->client,
- .engine = oclass->engine,
- };
-
- if (chan->vmm)
- atomic_inc(&chan->vmm->engref[engine->subdev.type]);
-
- if (engine->func->fifo.cclass) {
- ret = engine->func->fifo.cclass(chan, &cclass,
- &engn->object);
- } else
- if (engine->func->cclass) {
- ret = nvkm_object_new_(engine->func->cclass, &cclass,
- NULL, 0, &engn->object);
- }
- if (ret)
- return ret;
+ if (!chan->func->preempt)
+ return 0;
- if (chan->func->engine_ctor) {
- ret = chan->func->engine_ctor(chan, oclass->engine,
- engn->object);
- if (ret)
- return ret;
- }
- }
+ mutex_lock(&chan->cgrp->runl->mutex);
+ ret = nvkm_chan_preempt_locked(chan, wait);
+ mutex_unlock(&chan->cgrp->runl->mutex);
+ return ret;
+}
- ret = oclass->base.ctor(&(const struct nvkm_oclass) {
- .base = oclass->base,
- .engn = oclass->engn,
- .handle = oclass->handle,
- .object = oclass->object,
- .client = oclass->client,
- .parent = engn->object ?
- engn->object :
- oclass->parent,
- .engine = engine,
- }, data, size, &object->oproxy.object);
- if (ret)
- return ret;
+void
+nvkm_chan_remove_locked(struct nvkm_chan *chan)
+{
+ struct nvkm_cgrp *cgrp = chan->cgrp;
+ struct nvkm_runl *runl = cgrp->runl;
- if (chan->func->object_ctor) {
- object->hash =
- chan->func->object_ctor(chan, object->oproxy.object);
- if (object->hash < 0)
- return object->hash;
- }
+ if (list_empty(&chan->head))
+ return;
- return 0;
+ CHAN_TRACE(chan, "remove");
+ if (!--cgrp->chan_nr) {
+ runl->cgrp_nr--;
+ list_del(&cgrp->head);
+ }
+ runl->chan_nr--;
+ list_del_init(&chan->head);
+ atomic_set(&runl->changed, 1);
}
-static int
-nvkm_fifo_chan_child_get(struct nvkm_object *object, int index,
- struct nvkm_oclass *oclass)
+void
+nvkm_chan_remove(struct nvkm_chan *chan, bool preempt)
{
- struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
- struct nvkm_fifo *fifo = chan->fifo;
- struct nvkm_engine *engine;
- u32 engm = chan->engm;
- int engi, ret, c;
-
- for (; c = 0, engi = __ffs(engm), engm; engm &= ~(1ULL << engi)) {
- if (!(engine = fifo->func->id_engine(fifo, engi)))
- continue;
- oclass->engine = engine;
- oclass->base.oclass = 0;
-
- if (engine->func->fifo.sclass) {
- ret = engine->func->fifo.sclass(oclass, index);
- if (oclass->base.oclass) {
- if (!oclass->base.ctor)
- oclass->base.ctor = nvkm_object_new;
- oclass->ctor = nvkm_fifo_chan_child_new;
- return 0;
- }
+ struct nvkm_runl *runl = chan->cgrp->runl;
+
+ mutex_lock(&runl->mutex);
+ if (preempt && chan->func->preempt)
+ nvkm_chan_preempt_locked(chan, true);
+ nvkm_chan_remove_locked(chan);
+ nvkm_runl_update_locked(runl, true);
+ mutex_unlock(&runl->mutex);
+}
- index -= ret;
- continue;
- }
+void
+nvkm_chan_insert(struct nvkm_chan *chan)
+{
+ struct nvkm_cgrp *cgrp = chan->cgrp;
+ struct nvkm_runl *runl = cgrp->runl;
- while (engine->func->sclass[c].oclass) {
- if (c++ == index) {
- oclass->base = engine->func->sclass[index];
- if (!oclass->base.ctor)
- oclass->base.ctor = nvkm_object_new;
- oclass->ctor = nvkm_fifo_chan_child_new;
- return 0;
- }
- }
- index -= c;
+ mutex_lock(&runl->mutex);
+ if (WARN_ON(!list_empty(&chan->head))) {
+ mutex_unlock(&runl->mutex);
+ return;
}
- return -EINVAL;
+ CHAN_TRACE(chan, "insert");
+ list_add_tail(&chan->head, &cgrp->chans);
+ runl->chan_nr++;
+ if (!cgrp->chan_nr++) {
+ list_add_tail(&cgrp->head, &cgrp->runl->cgrps);
+ runl->cgrp_nr++;
+ }
+ atomic_set(&runl->changed, 1);
+ nvkm_runl_update_locked(runl, true);
+ mutex_unlock(&runl->mutex);
}
-static int
-nvkm_fifo_chan_ntfy(struct nvkm_object *object, u32 type,
- struct nvkm_event **pevent)
+static void
+nvkm_chan_block_locked(struct nvkm_chan *chan)
{
- struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
- if (chan->func->ntfy)
- return chan->func->ntfy(chan, type, pevent);
- return -ENODEV;
+ CHAN_TRACE(chan, "block %d", atomic_read(&chan->blocked));
+ if (atomic_inc_return(&chan->blocked) == 1)
+ chan->func->stop(chan);
}
-static int
-nvkm_fifo_chan_map(struct nvkm_object *object, void *argv, u32 argc,
- enum nvkm_object_map *type, u64 *addr, u64 *size)
+void
+nvkm_chan_error(struct nvkm_chan *chan, bool preempt)
{
- struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
- *type = NVKM_OBJECT_MAP_IO;
- *addr = chan->addr;
- *size = chan->size;
- return 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chan->lock, flags);
+ if (atomic_inc_return(&chan->errored) == 1) {
+ CHAN_ERROR(chan, "errored - disabling channel");
+ nvkm_chan_block_locked(chan);
+ if (preempt)
+ chan->func->preempt(chan);
+ nvkm_event_ntfy(&chan->cgrp->runl->chid->event, chan->id, NVKM_CHAN_EVENT_ERRORED);
+ }
+ spin_unlock_irqrestore(&chan->lock, flags);
}
-static int
-nvkm_fifo_chan_fini(struct nvkm_object *object, bool suspend)
+void
+nvkm_chan_block(struct nvkm_chan *chan)
{
- struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
- chan->func->fini(chan);
- return 0;
+ spin_lock_irq(&chan->lock);
+ nvkm_chan_block_locked(chan);
+ spin_unlock_irq(&chan->lock);
}
-static int
-nvkm_fifo_chan_init(struct nvkm_object *object)
+void
+nvkm_chan_allow(struct nvkm_chan *chan)
{
- struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
- chan->func->init(chan);
- return 0;
+ spin_lock_irq(&chan->lock);
+ CHAN_TRACE(chan, "allow %d", atomic_read(&chan->blocked));
+ if (atomic_dec_and_test(&chan->blocked))
+ chan->func->start(chan);
+ spin_unlock_irq(&chan->lock);
}
-static void *
-nvkm_fifo_chan_dtor(struct nvkm_object *object)
+void
+nvkm_chan_del(struct nvkm_chan **pchan)
{
- struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object);
- struct nvkm_fifo *fifo = chan->fifo;
- void *data = chan->func->dtor(chan);
- unsigned long flags;
+ struct nvkm_chan *chan = *pchan;
+
+ if (!chan)
+ return;
+
+ if (chan->func->ramfc->clear)
+ chan->func->ramfc->clear(chan);
- spin_lock_irqsave(&fifo->lock, flags);
- if (!list_empty(&chan->head)) {
- __clear_bit(chan->chid, fifo->mask);
- list_del(&chan->head);
+ nvkm_ramht_del(&chan->ramht);
+ nvkm_gpuobj_del(&chan->pgd);
+ nvkm_gpuobj_del(&chan->eng);
+ nvkm_gpuobj_del(&chan->cache);
+ nvkm_gpuobj_del(&chan->ramfc);
+
+ nvkm_memory_unref(&chan->userd.mem);
+
+ if (chan->cgrp) {
+ nvkm_chid_put(chan->cgrp->runl->chid, chan->id, &chan->cgrp->lock);
+ nvkm_cgrp_unref(&chan->cgrp);
}
- spin_unlock_irqrestore(&fifo->lock, flags);
if (chan->vmm) {
nvkm_vmm_part(chan->vmm, chan->inst->memory);
@@ -309,85 +289,192 @@ nvkm_fifo_chan_dtor(struct nvkm_object *object)
nvkm_gpuobj_del(&chan->push);
nvkm_gpuobj_del(&chan->inst);
- return data;
+ kfree(chan);
}
-static const struct nvkm_object_func
-nvkm_fifo_chan_func = {
- .dtor = nvkm_fifo_chan_dtor,
- .init = nvkm_fifo_chan_init,
- .fini = nvkm_fifo_chan_fini,
- .ntfy = nvkm_fifo_chan_ntfy,
- .map = nvkm_fifo_chan_map,
- .sclass = nvkm_fifo_chan_child_get,
-};
+void
+nvkm_chan_put(struct nvkm_chan **pchan, unsigned long irqflags)
+{
+ struct nvkm_chan *chan = *pchan;
+
+ if (!chan)
+ return;
+
+ *pchan = NULL;
+ spin_unlock_irqrestore(&chan->cgrp->lock, irqflags);
+}
+
+struct nvkm_chan *
+nvkm_chan_get_inst(struct nvkm_engine *engine, u64 inst, unsigned long *pirqflags)
+{
+ struct nvkm_fifo *fifo = engine->subdev.device->fifo;
+ struct nvkm_runl *runl;
+ struct nvkm_engn *engn;
+ struct nvkm_chan *chan;
+
+ nvkm_runl_foreach(runl, fifo) {
+ nvkm_runl_foreach_engn(engn, runl) {
+ if (engine == &fifo->engine || engn->engine == engine) {
+ chan = nvkm_runl_chan_get_inst(runl, inst, pirqflags);
+ if (chan || engn->engine == engine)
+ return chan;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+struct nvkm_chan *
+nvkm_chan_get_chid(struct nvkm_engine *engine, int id, unsigned long *pirqflags)
+{
+ struct nvkm_fifo *fifo = engine->subdev.device->fifo;
+ struct nvkm_runl *runl;
+ struct nvkm_engn *engn;
+
+ nvkm_runl_foreach(runl, fifo) {
+ nvkm_runl_foreach_engn(engn, runl) {
+ if (fifo->chid || engn->engine == engine)
+ return nvkm_runl_chan_get_chid(runl, id, pirqflags);
+ }
+ }
+
+ return NULL;
+}
int
-nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *func,
- struct nvkm_fifo *fifo, u32 size, u32 align, bool zero,
- u64 hvmm, u64 push, u32 engm, int bar, u32 base,
- u32 user, const struct nvkm_oclass *oclass,
- struct nvkm_fifo_chan *chan)
+nvkm_chan_new_(const struct nvkm_chan_func *func, struct nvkm_runl *runl, int runq,
+ struct nvkm_cgrp *cgrp, const char *name, bool priv, u32 devm, struct nvkm_vmm *vmm,
+ struct nvkm_dmaobj *dmaobj, u64 offset, u64 length,
+ struct nvkm_memory *userd, u64 ouserd, struct nvkm_chan **pchan)
{
- struct nvkm_client *client = oclass->client;
+ struct nvkm_fifo *fifo = runl->fifo;
struct nvkm_device *device = fifo->engine.subdev.device;
- struct nvkm_dmaobj *dmaobj;
- unsigned long flags;
+ struct nvkm_chan *chan;
int ret;
- nvkm_object_ctor(&nvkm_fifo_chan_func, oclass, &chan->object);
+ /* Validate arguments against class requirements. */
+ if ((runq && runq >= runl->func->runqs) ||
+ (!func->inst->vmm != !vmm) ||
+ ((func->userd->bar < 0) == !userd) ||
+ (!func->ramfc->ctxdma != !dmaobj) ||
+ ((func->ramfc->devm < devm) && devm != BIT(0)) ||
+ (!func->ramfc->priv && priv)) {
+ RUNL_DEBUG(runl, "args runq:%d:%d vmm:%d:%p userd:%d:%p "
+ "push:%d:%p devm:%08x:%08x priv:%d:%d",
+ runl->func->runqs, runq, func->inst->vmm, vmm,
+ func->userd->bar < 0, userd, func->ramfc->ctxdma, dmaobj,
+ func->ramfc->devm, devm, func->ramfc->priv, priv);
+ return -EINVAL;
+ }
+
+ if (!(chan = *pchan = kzalloc(sizeof(*chan), GFP_KERNEL)))
+ return -ENOMEM;
+
chan->func = func;
- chan->fifo = fifo;
- chan->engm = engm;
+ strscpy(chan->name, name, sizeof(chan->name));
+ chan->runq = runq;
+ chan->id = -1;
+ spin_lock_init(&chan->lock);
+ atomic_set(&chan->blocked, 1);
+ atomic_set(&chan->errored, 0);
+ INIT_LIST_HEAD(&chan->cctxs);
INIT_LIST_HEAD(&chan->head);
- /* instance memory */
- ret = nvkm_gpuobj_new(device, size, align, zero, NULL, &chan->inst);
- if (ret)
- return ret;
+ /* Join channel group.
+ *
+ * GK110 and newer support channel groups (aka TSGs), where individual channels
+ * share a timeslice, and, engine context(s).
+ *
+ * As such, engine contexts are tracked in nvkm_cgrp and we need them even when
+ * channels aren't in an API channel group, and on HW that doesn't support TSGs.
+ */
+ if (!cgrp) {
+ ret = nvkm_cgrp_new(runl, chan->name, vmm, fifo->func->cgrp.force, &chan->cgrp);
+ if (ret) {
+ RUNL_DEBUG(runl, "cgrp %d", ret);
+ return ret;
+ }
- /* allocate push buffer ctxdma instance */
- if (push) {
- dmaobj = nvkm_dmaobj_search(client, push);
- if (IS_ERR(dmaobj))
- return PTR_ERR(dmaobj);
+ cgrp = chan->cgrp;
+ } else {
+ if (cgrp->runl != runl || cgrp->vmm != vmm) {
+ RUNL_DEBUG(runl, "cgrp %d %d", cgrp->runl != runl, cgrp->vmm != vmm);
+ return -EINVAL;
+ }
- ret = nvkm_object_bind(&dmaobj->object, chan->inst, -16,
- &chan->push);
- if (ret)
- return ret;
+ chan->cgrp = nvkm_cgrp_ref(cgrp);
}
- /* channel address space */
- if (hvmm) {
- struct nvkm_vmm *vmm = nvkm_uvmm_search(client, hvmm);
- if (IS_ERR(vmm))
- return PTR_ERR(vmm);
+ /* Allocate instance block. */
+ ret = nvkm_gpuobj_new(device, func->inst->size, 0x1000, func->inst->zero, NULL,
+ &chan->inst);
+ if (ret) {
+ RUNL_DEBUG(runl, "inst %d", ret);
+ return ret;
+ }
- if (vmm->mmu != device->mmu)
+ /* Initialise virtual address-space. */
+ if (func->inst->vmm) {
+ if (WARN_ON(vmm->mmu != device->mmu))
return -EINVAL;
ret = nvkm_vmm_join(vmm, chan->inst->memory);
- if (ret)
+ if (ret) {
+ RUNL_DEBUG(runl, "vmm %d", ret);
return ret;
+ }
chan->vmm = nvkm_vmm_ref(vmm);
}
- /* allocate channel id */
- spin_lock_irqsave(&fifo->lock, flags);
- chan->chid = find_first_zero_bit(fifo->mask, NVKM_FIFO_CHID_NR);
- if (chan->chid >= NVKM_FIFO_CHID_NR) {
- spin_unlock_irqrestore(&fifo->lock, flags);
+ /* Allocate HW ctxdma for push buffer. */
+ if (func->ramfc->ctxdma) {
+ ret = nvkm_object_bind(&dmaobj->object, chan->inst, -16, &chan->push);
+ if (ret) {
+ RUNL_DEBUG(runl, "bind %d", ret);
+ return ret;
+ }
+ }
+
+ /* Allocate channel ID. */
+ chan->id = nvkm_chid_get(runl->chid, chan);
+ if (chan->id < 0) {
+ RUNL_ERROR(runl, "!chids");
return -ENOSPC;
}
- list_add(&chan->head, &fifo->chan);
- __set_bit(chan->chid, fifo->mask);
- spin_unlock_irqrestore(&fifo->lock, flags);
-
- /* determine address of this channel's user registers */
- chan->addr = device->func->resource_addr(device, bar) +
- base + user * chan->chid;
- chan->size = user;
+
+ if (cgrp->id < 0)
+ cgrp->id = chan->id;
+
+ /* Initialise USERD. */
+ if (func->userd->bar < 0) {
+ if (ouserd + chan->func->userd->size >= nvkm_memory_size(userd)) {
+ RUNL_DEBUG(runl, "ouserd %llx", ouserd);
+ return -EINVAL;
+ }
+
+ ret = nvkm_memory_kmap(userd, &chan->userd.mem);
+ if (ret) {
+ RUNL_DEBUG(runl, "userd %d", ret);
+ return ret;
+ }
+
+ chan->userd.base = ouserd;
+ } else {
+ chan->userd.mem = nvkm_memory_ref(fifo->userd.mem);
+ chan->userd.base = chan->id * chan->func->userd->size;
+ }
+
+ if (chan->func->userd->clear)
+ chan->func->userd->clear(chan);
+
+ /* Initialise RAMFC. */
+ ret = chan->func->ramfc->write(chan, offset, length, devm, priv);
+ if (ret) {
+ RUNL_DEBUG(runl, "ramfc %d", ret);
+ return ret;
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h
index e53504354841..85b94f699128 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.h
@@ -1,35 +1,78 @@
/* SPDX-License-Identifier: MIT */
-#ifndef __NVKM_FIFO_CHAN_H__
-#define __NVKM_FIFO_CHAN_H__
-#define nvkm_fifo_chan(p) container_of((p), struct nvkm_fifo_chan, object)
-#include "priv.h"
-
-struct nvkm_fifo_chan_func {
- void *(*dtor)(struct nvkm_fifo_chan *);
- void (*init)(struct nvkm_fifo_chan *);
- void (*fini)(struct nvkm_fifo_chan *);
- int (*ntfy)(struct nvkm_fifo_chan *, u32 type, struct nvkm_event **);
- int (*engine_ctor)(struct nvkm_fifo_chan *, struct nvkm_engine *,
- struct nvkm_object *);
- void (*engine_dtor)(struct nvkm_fifo_chan *, struct nvkm_engine *);
- int (*engine_init)(struct nvkm_fifo_chan *, struct nvkm_engine *);
- int (*engine_fini)(struct nvkm_fifo_chan *, struct nvkm_engine *,
- bool suspend);
- int (*object_ctor)(struct nvkm_fifo_chan *, struct nvkm_object *);
- void (*object_dtor)(struct nvkm_fifo_chan *, int);
- u32 (*submit_token)(struct nvkm_fifo_chan *);
+#ifndef __NVKM_CHAN_H__
+#define __NVKM_CHAN_H__
+#include <engine/fifo.h>
+struct nvkm_dmaobj;
+struct nvkm_engn;
+struct nvkm_runl;
+
+extern const struct nvkm_event_func nvkm_chan_event;
+
+struct nvkm_cctx {
+ struct nvkm_vctx *vctx;
+ refcount_t refs;
+ refcount_t uses;
+
+ struct list_head head;
};
-int nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *, struct nvkm_fifo *,
- u32 size, u32 align, bool zero, u64 vm, u64 push,
- u32 engm, int bar, u32 base, u32 user,
- const struct nvkm_oclass *, struct nvkm_fifo_chan *);
+struct nvkm_chan_func {
+ const struct nvkm_chan_func_inst {
+ u32 size;
+ bool zero;
+ bool vmm;
+ } *inst;
-struct nvkm_fifo_chan_oclass {
- int (*ctor)(struct nvkm_fifo *, const struct nvkm_oclass *,
- void *data, u32 size, struct nvkm_object **);
- struct nvkm_sclass base;
+ const struct nvkm_chan_func_userd {
+ int bar;
+ u32 base;
+ u32 size;
+ void (*clear)(struct nvkm_chan *);
+ } *userd;
+
+ const struct nvkm_chan_func_ramfc {
+ const struct nvkm_ramfc_layout {
+ unsigned bits:6;
+ unsigned ctxs:5;
+ unsigned ctxp:8;
+ unsigned regs:5;
+ unsigned regp;
+ } *layout;
+ int (*write)(struct nvkm_chan *, u64 offset, u64 length, u32 devm, bool priv);
+ void (*clear)(struct nvkm_chan *);
+ bool ctxdma;
+ u32 devm;
+ bool priv;
+ } *ramfc;
+
+ void (*bind)(struct nvkm_chan *);
+ void (*unbind)(struct nvkm_chan *);
+ void (*start)(struct nvkm_chan *);
+ void (*stop)(struct nvkm_chan *);
+ void (*preempt)(struct nvkm_chan *);
+ u32 (*doorbell_handle)(struct nvkm_chan *);
};
-int gf100_fifo_chan_ntfy(struct nvkm_fifo_chan *, u32, struct nvkm_event **);
+int nvkm_chan_new_(const struct nvkm_chan_func *, struct nvkm_runl *, int runq, struct nvkm_cgrp *,
+ const char *name, bool priv, u32 devm, struct nvkm_vmm *, struct nvkm_dmaobj *,
+ u64 offset, u64 length, struct nvkm_memory *userd, u64 userd_bar1,
+ struct nvkm_chan **);
+void nvkm_chan_del(struct nvkm_chan **);
+void nvkm_chan_allow(struct nvkm_chan *);
+void nvkm_chan_block(struct nvkm_chan *);
+void nvkm_chan_error(struct nvkm_chan *, bool preempt);
+void nvkm_chan_insert(struct nvkm_chan *);
+void nvkm_chan_remove(struct nvkm_chan *, bool preempt);
+void nvkm_chan_remove_locked(struct nvkm_chan *);
+int nvkm_chan_preempt(struct nvkm_chan *, bool wait);
+int nvkm_chan_preempt_locked(struct nvkm_chan *, bool wait);
+int nvkm_chan_cctx_get(struct nvkm_chan *, struct nvkm_engn *, struct nvkm_cctx **,
+ struct nvkm_client * /*TODO: remove need for this */);
+void nvkm_chan_cctx_put(struct nvkm_chan *, struct nvkm_cctx **);
+void nvkm_chan_cctx_bind(struct nvkm_chan *, struct nvkm_engn *, struct nvkm_cctx *);
+
+#define CHAN_PRCLI(c,l,p,f,a...) CGRP_PRINT((c)->cgrp, l, p, "%04x:[%s]"f, (c)->id, (c)->name, ##a)
+#define CHAN_PRINT(c,l,p,f,a...) CGRP_PRINT((c)->cgrp, l, p, "%04x:"f, (c)->id, ##a)
+#define CHAN_ERROR(c,f,a...) CHAN_PRCLI((c), ERROR, err, " "f"\n", ##a)
+#define CHAN_TRACE(c,f,a...) CHAN_PRINT((c), TRACE, info, " "f"\n", ##a)
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c
deleted file mode 100644
index 3492c561f2cf..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright 2012 Red Hat 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: Ben Skeggs
- */
-#include "channv50.h"
-
-#include <core/client.h>
-#include <core/ramht.h>
-#include <subdev/mmu.h>
-#include <subdev/timer.h>
-
-#include <nvif/cl826e.h>
-
-static int
-g84_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type,
- struct nvkm_event **pevent)
-{
- switch (type) {
- case NV826E_V0_NTFY_NON_STALL_INTERRUPT:
- *pevent = &chan->fifo->uevent;
- return 0;
- default:
- break;
- }
- return -EINVAL;
-}
-
-static int
-g84_fifo_chan_engine_addr(struct nvkm_engine *engine)
-{
- switch (engine->subdev.type) {
- case NVKM_ENGINE_DMAOBJ:
- case NVKM_ENGINE_SW : return -1;
- case NVKM_ENGINE_GR : return 0x0020;
- case NVKM_ENGINE_VP :
- case NVKM_ENGINE_MSPDEC: return 0x0040;
- case NVKM_ENGINE_MPEG :
- case NVKM_ENGINE_MSPPP : return 0x0060;
- case NVKM_ENGINE_BSP :
- case NVKM_ENGINE_MSVLD : return 0x0080;
- case NVKM_ENGINE_CIPHER:
- case NVKM_ENGINE_SEC : return 0x00a0;
- case NVKM_ENGINE_CE : return 0x00c0;
- default:
- WARN_ON(1);
- return -1;
- }
-}
-
-static int
-g84_fifo_chan_engine_fini(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine, bool suspend)
-{
- struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
- struct nv50_fifo *fifo = chan->fifo;
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- u32 engn, save;
- int offset;
- bool done;
-
- offset = g84_fifo_chan_engine_addr(engine);
- if (offset < 0)
- return 0;
-
- engn = fifo->base.func->engine_id(&fifo->base, engine) - 1;
- save = nvkm_mask(device, 0x002520, 0x0000003f, 1 << engn);
- nvkm_wr32(device, 0x0032fc, chan->base.inst->addr >> 12);
- done = nvkm_msec(device, 2000,
- if (nvkm_rd32(device, 0x0032fc) != 0xffffffff)
- break;
- ) >= 0;
- nvkm_wr32(device, 0x002520, save);
- if (!done) {
- nvkm_error(subdev, "channel %d [%s] unload timeout\n",
- chan->base.chid, chan->base.object.client->name);
- if (suspend)
- return -EBUSY;
- }
-
- nvkm_kmap(chan->eng);
- nvkm_wo32(chan->eng, offset + 0x00, 0x00000000);
- nvkm_wo32(chan->eng, offset + 0x04, 0x00000000);
- nvkm_wo32(chan->eng, offset + 0x08, 0x00000000);
- nvkm_wo32(chan->eng, offset + 0x0c, 0x00000000);
- nvkm_wo32(chan->eng, offset + 0x10, 0x00000000);
- nvkm_wo32(chan->eng, offset + 0x14, 0x00000000);
- nvkm_done(chan->eng);
- return 0;
-}
-
-
-static int
-g84_fifo_chan_engine_init(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine)
-{
- struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
- struct nvkm_gpuobj *engn = *nv50_fifo_chan_engine(chan, engine);
- u64 limit, start;
- int offset;
-
- offset = g84_fifo_chan_engine_addr(engine);
- if (offset < 0)
- return 0;
- limit = engn->addr + engn->size - 1;
- start = engn->addr;
-
- nvkm_kmap(chan->eng);
- nvkm_wo32(chan->eng, offset + 0x00, 0x00190000);
- nvkm_wo32(chan->eng, offset + 0x04, lower_32_bits(limit));
- nvkm_wo32(chan->eng, offset + 0x08, lower_32_bits(start));
- nvkm_wo32(chan->eng, offset + 0x0c, upper_32_bits(limit) << 24 |
- upper_32_bits(start));
- nvkm_wo32(chan->eng, offset + 0x10, 0x00000000);
- nvkm_wo32(chan->eng, offset + 0x14, 0x00000000);
- nvkm_done(chan->eng);
- return 0;
-}
-
-static int
-g84_fifo_chan_engine_ctor(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine,
- struct nvkm_object *object)
-{
- struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
-
- if (g84_fifo_chan_engine_addr(engine) < 0)
- return 0;
-
- return nvkm_object_bind(object, NULL, 0, nv50_fifo_chan_engine(chan, engine));
-}
-
-static int
-g84_fifo_chan_object_ctor(struct nvkm_fifo_chan *base,
- struct nvkm_object *object)
-{
- struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
- u32 handle = object->handle;
- u32 context;
-
- switch (object->engine->subdev.type) {
- case NVKM_ENGINE_DMAOBJ:
- case NVKM_ENGINE_SW : context = 0x00000000; break;
- case NVKM_ENGINE_GR : context = 0x00100000; break;
- case NVKM_ENGINE_MPEG :
- case NVKM_ENGINE_MSPPP : context = 0x00200000; break;
- case NVKM_ENGINE_ME :
- case NVKM_ENGINE_CE : context = 0x00300000; break;
- case NVKM_ENGINE_VP :
- case NVKM_ENGINE_MSPDEC: context = 0x00400000; break;
- case NVKM_ENGINE_CIPHER:
- case NVKM_ENGINE_SEC :
- case NVKM_ENGINE_VIC : context = 0x00500000; break;
- case NVKM_ENGINE_BSP :
- case NVKM_ENGINE_MSVLD : context = 0x00600000; break;
- default:
- WARN_ON(1);
- return -EINVAL;
- }
-
- return nvkm_ramht_insert(chan->ramht, object, 0, 4, handle, context);
-}
-
-static void
-g84_fifo_chan_init(struct nvkm_fifo_chan *base)
-{
- struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
- struct nv50_fifo *fifo = chan->fifo;
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- u64 addr = chan->ramfc->addr >> 8;
- u32 chid = chan->base.chid;
-
- nvkm_wr32(device, 0x002600 + (chid * 4), 0x80000000 | addr);
- nv50_fifo_runlist_update(fifo);
-}
-
-static const struct nvkm_fifo_chan_func
-g84_fifo_chan_func = {
- .dtor = nv50_fifo_chan_dtor,
- .init = g84_fifo_chan_init,
- .fini = nv50_fifo_chan_fini,
- .ntfy = g84_fifo_chan_ntfy,
- .engine_ctor = g84_fifo_chan_engine_ctor,
- .engine_dtor = nv50_fifo_chan_engine_dtor,
- .engine_init = g84_fifo_chan_engine_init,
- .engine_fini = g84_fifo_chan_engine_fini,
- .object_ctor = g84_fifo_chan_object_ctor,
- .object_dtor = nv50_fifo_chan_object_dtor,
-};
-
-int
-g84_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vmm, u64 push,
- const struct nvkm_oclass *oclass,
- struct nv50_fifo_chan *chan)
-{
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- int ret;
-
- if (!vmm)
- return -EINVAL;
-
- ret = nvkm_fifo_chan_ctor(&g84_fifo_chan_func, &fifo->base,
- 0x10000, 0x1000, false, vmm, push,
- BIT(G84_FIFO_ENGN_SW) |
- BIT(G84_FIFO_ENGN_GR) |
- BIT(G84_FIFO_ENGN_MPEG) |
- BIT(G84_FIFO_ENGN_MSPPP) |
- BIT(G84_FIFO_ENGN_ME) |
- BIT(G84_FIFO_ENGN_CE0) |
- BIT(G84_FIFO_ENGN_VP) |
- BIT(G84_FIFO_ENGN_MSPDEC) |
- BIT(G84_FIFO_ENGN_CIPHER) |
- BIT(G84_FIFO_ENGN_SEC) |
- BIT(G84_FIFO_ENGN_VIC) |
- BIT(G84_FIFO_ENGN_BSP) |
- BIT(G84_FIFO_ENGN_MSVLD) |
- BIT(G84_FIFO_ENGN_DMA),
- 0, 0xc00000, 0x2000, oclass, &chan->base);
- chan->fifo = fifo;
- if (ret)
- return ret;
-
- ret = nvkm_gpuobj_new(device, 0x0200, 0, true, chan->base.inst,
- &chan->eng);
- if (ret)
- return ret;
-
- ret = nvkm_gpuobj_new(device, 0x4000, 0, false, chan->base.inst,
- &chan->pgd);
- if (ret)
- return ret;
-
- ret = nvkm_gpuobj_new(device, 0x1000, 0x400, true, chan->base.inst,
- &chan->cache);
- if (ret)
- return ret;
-
- ret = nvkm_gpuobj_new(device, 0x100, 0x100, true, chan->base.inst,
- &chan->ramfc);
- if (ret)
- return ret;
-
- return nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht);
-}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h
deleted file mode 100644
index f7ac1061fa84..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-#ifndef __GF100_FIFO_CHAN_H__
-#define __GF100_FIFO_CHAN_H__
-#define gf100_fifo_chan(p) container_of((p), struct gf100_fifo_chan, base)
-#include "chan.h"
-#include "gf100.h"
-
-struct gf100_fifo_chan {
- struct nvkm_fifo_chan base;
- struct gf100_fifo *fifo;
-
- struct list_head head;
- bool killed;
-
-#define GF100_FIFO_ENGN_GR 0
-#define GF100_FIFO_ENGN_MSPDEC 1
-#define GF100_FIFO_ENGN_MSPPP 2
-#define GF100_FIFO_ENGN_MSVLD 3
-#define GF100_FIFO_ENGN_CE0 4
-#define GF100_FIFO_ENGN_CE1 5
-#define GF100_FIFO_ENGN_SW 15
- struct gf100_fifo_engn {
- struct nvkm_gpuobj *inst;
- struct nvkm_vma *vma;
- } engn[NVKM_FIFO_ENGN_NR];
-};
-
-extern const struct nvkm_fifo_chan_oclass gf100_fifo_gpfifo_oclass;
-#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h
deleted file mode 100644
index 9713daee6c76..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-#ifndef __GK104_FIFO_CHAN_H__
-#define __GK104_FIFO_CHAN_H__
-#define gk104_fifo_chan(p) container_of((p), struct gk104_fifo_chan, base)
-#include "chan.h"
-#include "gk104.h"
-
-struct gk104_fifo_chan {
- struct nvkm_fifo_chan base;
- struct gk104_fifo *fifo;
- int runl;
-
- struct nvkm_fifo_cgrp *cgrp;
- struct list_head head;
- bool killed;
-
-#define GK104_FIFO_ENGN_SW 15
- struct gk104_fifo_engn {
- struct nvkm_gpuobj *inst;
- struct nvkm_vma *vma;
- } engn[NVKM_FIFO_ENGN_NR];
-};
-
-extern const struct nvkm_fifo_chan_func gk104_fifo_gpfifo_func;
-
-int gk104_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *,
- void *data, u32 size, struct nvkm_object **);
-void *gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *);
-void gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *);
-void gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *);
-struct gk104_fifo_engn *gk104_fifo_gpfifo_engine(struct gk104_fifo_chan *, struct nvkm_engine *);
-int gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *, struct nvkm_engine *,
- struct nvkm_object *);
-void gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *,
- struct nvkm_engine *);
-int gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *);
-int gk104_fifo_gpfifo_kick_locked(struct gk104_fifo_chan *);
-
-int gv100_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *,
- void *data, u32 size, struct nvkm_object **);
-int gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *,
- struct gk104_fifo *, u64 *, u16 *, u64, u64, u64,
- u64 *, bool, u32 *, const struct nvkm_oclass *,
- struct nvkm_object **);
-int gv100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *,
- struct nvkm_engine *);
-int gv100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *,
- struct nvkm_engine *, bool);
-
-int tu102_fifo_gpfifo_new(struct gk104_fifo *, const struct nvkm_oclass *,
- void *data, u32 size, struct nvkm_object **);
-#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h
deleted file mode 100644
index 727bc8976b40..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv04.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-#ifndef __NV04_FIFO_CHAN_H__
-#define __NV04_FIFO_CHAN_H__
-#define nv04_fifo_chan(p) container_of((p), struct nv04_fifo_chan, base)
-#include "chan.h"
-#include "nv04.h"
-
-struct nv04_fifo_chan {
- struct nvkm_fifo_chan base;
- struct nv04_fifo *fifo;
- u32 ramfc;
-#define NV04_FIFO_ENGN_SW 0
-#define NV04_FIFO_ENGN_GR 1
-#define NV04_FIFO_ENGN_MPEG 2
-#define NV04_FIFO_ENGN_DMA 3
- struct nvkm_gpuobj *engn[NVKM_FIFO_ENGN_NR];
-};
-
-extern const struct nvkm_fifo_chan_func nv04_fifo_dma_func;
-void *nv04_fifo_dma_dtor(struct nvkm_fifo_chan *);
-void nv04_fifo_dma_init(struct nvkm_fifo_chan *);
-void nv04_fifo_dma_fini(struct nvkm_fifo_chan *);
-void nv04_fifo_dma_object_dtor(struct nvkm_fifo_chan *, int);
-
-extern const struct nvkm_fifo_chan_oclass nv04_fifo_dma_oclass;
-extern const struct nvkm_fifo_chan_oclass nv10_fifo_dma_oclass;
-extern const struct nvkm_fifo_chan_oclass nv17_fifo_dma_oclass;
-extern const struct nvkm_fifo_chan_oclass nv40_fifo_dma_oclass;
-#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c
deleted file mode 100644
index c44d7c81dd52..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * Copyright 2012 Red Hat 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: Ben Skeggs
- */
-#include "channv50.h"
-
-#include <core/client.h>
-#include <core/ramht.h>
-#include <subdev/mmu.h>
-#include <subdev/timer.h>
-
-static int
-nv50_fifo_chan_engine_addr(struct nvkm_engine *engine)
-{
- switch (engine->subdev.type) {
- case NVKM_ENGINE_DMAOBJ:
- case NVKM_ENGINE_SW : return -1;
- case NVKM_ENGINE_GR : return 0x0000;
- case NVKM_ENGINE_MPEG : return 0x0060;
- default:
- WARN_ON(1);
- return -1;
- }
-}
-
-struct nvkm_gpuobj **
-nv50_fifo_chan_engine(struct nv50_fifo_chan *chan, struct nvkm_engine *engine)
-{
- int engi = chan->base.fifo->func->engine_id(chan->base.fifo, engine);
- if (engi >= 0)
- return &chan->engn[engi];
- return NULL;
-}
-
-static int
-nv50_fifo_chan_engine_fini(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine, bool suspend)
-{
- struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
- struct nv50_fifo *fifo = chan->fifo;
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- int offset, ret = 0;
- u32 me;
-
- offset = nv50_fifo_chan_engine_addr(engine);
- if (offset < 0)
- return 0;
-
- /* HW bug workaround:
- *
- * PFIFO will hang forever if the connected engines don't report
- * that they've processed the context switch request.
- *
- * In order for the kickoff to work, we need to ensure all the
- * connected engines are in a state where they can answer.
- *
- * Newer chipsets don't seem to suffer from this issue, and well,
- * there's also a "ignore these engines" bitmask reg we can use
- * if we hit the issue there..
- */
- me = nvkm_mask(device, 0x00b860, 0x00000001, 0x00000001);
-
- /* do the kickoff... */
- nvkm_wr32(device, 0x0032fc, chan->base.inst->addr >> 12);
- if (nvkm_msec(device, 2000,
- if (nvkm_rd32(device, 0x0032fc) != 0xffffffff)
- break;
- ) < 0) {
- nvkm_error(subdev, "channel %d [%s] unload timeout\n",
- chan->base.chid, chan->base.object.client->name);
- if (suspend)
- ret = -EBUSY;
- }
- nvkm_wr32(device, 0x00b860, me);
-
- if (ret == 0) {
- nvkm_kmap(chan->eng);
- nvkm_wo32(chan->eng, offset + 0x00, 0x00000000);
- nvkm_wo32(chan->eng, offset + 0x04, 0x00000000);
- nvkm_wo32(chan->eng, offset + 0x08, 0x00000000);
- nvkm_wo32(chan->eng, offset + 0x0c, 0x00000000);
- nvkm_wo32(chan->eng, offset + 0x10, 0x00000000);
- nvkm_wo32(chan->eng, offset + 0x14, 0x00000000);
- nvkm_done(chan->eng);
- }
-
- return ret;
-}
-
-static int
-nv50_fifo_chan_engine_init(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine)
-{
- struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
- struct nvkm_gpuobj *engn = *nv50_fifo_chan_engine(chan, engine);
- u64 limit, start;
- int offset;
-
- offset = nv50_fifo_chan_engine_addr(engine);
- if (offset < 0)
- return 0;
- limit = engn->addr + engn->size - 1;
- start = engn->addr;
-
- nvkm_kmap(chan->eng);
- nvkm_wo32(chan->eng, offset + 0x00, 0x00190000);
- nvkm_wo32(chan->eng, offset + 0x04, lower_32_bits(limit));
- nvkm_wo32(chan->eng, offset + 0x08, lower_32_bits(start));
- nvkm_wo32(chan->eng, offset + 0x0c, upper_32_bits(limit) << 24 |
- upper_32_bits(start));
- nvkm_wo32(chan->eng, offset + 0x10, 0x00000000);
- nvkm_wo32(chan->eng, offset + 0x14, 0x00000000);
- nvkm_done(chan->eng);
- return 0;
-}
-
-void
-nv50_fifo_chan_engine_dtor(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine)
-{
- struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
- nvkm_gpuobj_del(nv50_fifo_chan_engine(chan, engine));
-}
-
-static int
-nv50_fifo_chan_engine_ctor(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine,
- struct nvkm_object *object)
-{
- struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
-
- if (nv50_fifo_chan_engine_addr(engine) < 0)
- return 0;
-
- return nvkm_object_bind(object, NULL, 0, nv50_fifo_chan_engine(chan, engine));
-}
-
-void
-nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *base, int cookie)
-{
- struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
- nvkm_ramht_remove(chan->ramht, cookie);
-}
-
-static int
-nv50_fifo_chan_object_ctor(struct nvkm_fifo_chan *base,
- struct nvkm_object *object)
-{
- struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
- u32 handle = object->handle;
- u32 context;
-
- switch (object->engine->subdev.type) {
- case NVKM_ENGINE_DMAOBJ:
- case NVKM_ENGINE_SW : context = 0x00000000; break;
- case NVKM_ENGINE_GR : context = 0x00100000; break;
- case NVKM_ENGINE_MPEG : context = 0x00200000; break;
- default:
- WARN_ON(1);
- return -EINVAL;
- }
-
- return nvkm_ramht_insert(chan->ramht, object, 0, 4, handle, context);
-}
-
-void
-nv50_fifo_chan_fini(struct nvkm_fifo_chan *base)
-{
- struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
- struct nv50_fifo *fifo = chan->fifo;
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- u32 chid = chan->base.chid;
-
- /* remove channel from runlist, fifo will unload context */
- nvkm_mask(device, 0x002600 + (chid * 4), 0x80000000, 0x00000000);
- nv50_fifo_runlist_update(fifo);
- nvkm_wr32(device, 0x002600 + (chid * 4), 0x00000000);
-}
-
-static void
-nv50_fifo_chan_init(struct nvkm_fifo_chan *base)
-{
- struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
- struct nv50_fifo *fifo = chan->fifo;
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- u64 addr = chan->ramfc->addr >> 12;
- u32 chid = chan->base.chid;
-
- nvkm_wr32(device, 0x002600 + (chid * 4), 0x80000000 | addr);
- nv50_fifo_runlist_update(fifo);
-}
-
-void *
-nv50_fifo_chan_dtor(struct nvkm_fifo_chan *base)
-{
- struct nv50_fifo_chan *chan = nv50_fifo_chan(base);
- nvkm_ramht_del(&chan->ramht);
- nvkm_gpuobj_del(&chan->pgd);
- nvkm_gpuobj_del(&chan->eng);
- nvkm_gpuobj_del(&chan->cache);
- nvkm_gpuobj_del(&chan->ramfc);
- return chan;
-}
-
-static const struct nvkm_fifo_chan_func
-nv50_fifo_chan_func = {
- .dtor = nv50_fifo_chan_dtor,
- .init = nv50_fifo_chan_init,
- .fini = nv50_fifo_chan_fini,
- .engine_ctor = nv50_fifo_chan_engine_ctor,
- .engine_dtor = nv50_fifo_chan_engine_dtor,
- .engine_init = nv50_fifo_chan_engine_init,
- .engine_fini = nv50_fifo_chan_engine_fini,
- .object_ctor = nv50_fifo_chan_object_ctor,
- .object_dtor = nv50_fifo_chan_object_dtor,
-};
-
-int
-nv50_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vmm, u64 push,
- const struct nvkm_oclass *oclass,
- struct nv50_fifo_chan *chan)
-{
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- int ret;
-
- if (!vmm)
- return -EINVAL;
-
- ret = nvkm_fifo_chan_ctor(&nv50_fifo_chan_func, &fifo->base,
- 0x10000, 0x1000, false, vmm, push,
- BIT(NV50_FIFO_ENGN_SW) |
- BIT(NV50_FIFO_ENGN_GR) |
- BIT(NV50_FIFO_ENGN_MPEG) |
- BIT(NV50_FIFO_ENGN_DMA),
- 0, 0xc00000, 0x2000, oclass, &chan->base);
- chan->fifo = fifo;
- if (ret)
- return ret;
-
- ret = nvkm_gpuobj_new(device, 0x0200, 0x1000, true, chan->base.inst,
- &chan->ramfc);
- if (ret)
- return ret;
-
- ret = nvkm_gpuobj_new(device, 0x1200, 0, true, chan->base.inst,
- &chan->eng);
- if (ret)
- return ret;
-
- ret = nvkm_gpuobj_new(device, 0x4000, 0, false, chan->base.inst,
- &chan->pgd);
- if (ret)
- return ret;
-
- return nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht);
-}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h
deleted file mode 100644
index 3a95730d7ff5..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-#ifndef __NV50_FIFO_CHAN_H__
-#define __NV50_FIFO_CHAN_H__
-#define nv50_fifo_chan(p) container_of((p), struct nv50_fifo_chan, base)
-#include "chan.h"
-#include "nv50.h"
-
-struct nv50_fifo_chan {
- struct nv50_fifo *fifo;
- struct nvkm_fifo_chan base;
-
- struct nvkm_gpuobj *ramfc;
- struct nvkm_gpuobj *cache;
- struct nvkm_gpuobj *eng;
- struct nvkm_gpuobj *pgd;
- struct nvkm_ramht *ramht;
-
-#define NV50_FIFO_ENGN_SW 0
-#define NV50_FIFO_ENGN_GR 1
-#define NV50_FIFO_ENGN_MPEG 2
-#define NV50_FIFO_ENGN_DMA 3
-
-#define G84_FIFO_ENGN_SW 0
-#define G84_FIFO_ENGN_GR 1
-#define G84_FIFO_ENGN_MPEG 2
-#define G84_FIFO_ENGN_MSPPP 2
-#define G84_FIFO_ENGN_ME 3
-#define G84_FIFO_ENGN_CE0 3
-#define G84_FIFO_ENGN_VP 4
-#define G84_FIFO_ENGN_MSPDEC 4
-#define G84_FIFO_ENGN_CIPHER 5
-#define G84_FIFO_ENGN_SEC 5
-#define G84_FIFO_ENGN_VIC 5
-#define G84_FIFO_ENGN_BSP 6
-#define G84_FIFO_ENGN_MSVLD 6
-#define G84_FIFO_ENGN_DMA 7
- struct nvkm_gpuobj *engn[NVKM_FIFO_ENGN_NR];
-};
-
-int nv50_fifo_chan_ctor(struct nv50_fifo *, u64 vmm, u64 push,
- const struct nvkm_oclass *, struct nv50_fifo_chan *);
-void *nv50_fifo_chan_dtor(struct nvkm_fifo_chan *);
-void nv50_fifo_chan_fini(struct nvkm_fifo_chan *);
-struct nvkm_gpuobj **nv50_fifo_chan_engine(struct nv50_fifo_chan *, struct nvkm_engine *);
-void nv50_fifo_chan_engine_dtor(struct nvkm_fifo_chan *, struct nvkm_engine *);
-void nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *, int);
-
-int g84_fifo_chan_ctor(struct nv50_fifo *, u64 vmm, u64 push,
- const struct nvkm_oclass *, struct nv50_fifo_chan *);
-
-extern const struct nvkm_fifo_chan_oclass nv50_fifo_gpfifo_oclass;
-extern const struct nvkm_fifo_chan_oclass g84_fifo_gpfifo_oclass;
-#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.c
new file mode 100644
index 000000000000..23944d95efd5
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2020 Red Hat 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 "chid.h"
+
+void
+nvkm_chid_put(struct nvkm_chid *chid, int id, spinlock_t *data_lock)
+{
+ if (id >= 0) {
+ spin_lock_irq(&chid->lock);
+ spin_lock(data_lock);
+ chid->data[id] = NULL;
+ spin_unlock(data_lock);
+ clear_bit(id, chid->used);
+ spin_unlock_irq(&chid->lock);
+ }
+}
+
+int
+nvkm_chid_get(struct nvkm_chid *chid, void *data)
+{
+ int id = -1, cid;
+
+ spin_lock_irq(&chid->lock);
+ cid = find_first_zero_bit(chid->used, chid->nr);
+ if (cid < chid->nr) {
+ set_bit(cid, chid->used);
+ chid->data[cid] = data;
+ id = cid;
+ }
+ spin_unlock_irq(&chid->lock);
+ return id;
+}
+
+static void
+nvkm_chid_del(struct kref *kref)
+{
+ struct nvkm_chid *chid = container_of(kref, typeof(*chid), kref);
+
+ nvkm_event_fini(&chid->event);
+
+ kvfree(chid->data);
+ kfree(chid);
+}
+
+void
+nvkm_chid_unref(struct nvkm_chid **pchid)
+{
+ struct nvkm_chid *chid = *pchid;
+
+ if (!chid)
+ return;
+
+ kref_put(&chid->kref, nvkm_chid_del);
+ *pchid = NULL;
+}
+
+struct nvkm_chid *
+nvkm_chid_ref(struct nvkm_chid *chid)
+{
+ if (chid)
+ kref_get(&chid->kref);
+
+ return chid;
+}
+
+int
+nvkm_chid_new(const struct nvkm_event_func *func, struct nvkm_subdev *subdev,
+ int nr, int first, int count, struct nvkm_chid **pchid)
+{
+ struct nvkm_chid *chid;
+ int id;
+
+ if (!(chid = *pchid = kzalloc(struct_size(chid, used, nr), GFP_KERNEL)))
+ return -ENOMEM;
+
+ kref_init(&chid->kref);
+ chid->nr = nr;
+ chid->mask = chid->nr - 1;
+ spin_lock_init(&chid->lock);
+
+ if (!(chid->data = kvzalloc(sizeof(*chid->data) * nr, GFP_KERNEL))) {
+ nvkm_chid_unref(pchid);
+ return -ENOMEM;
+ }
+
+ for (id = 0; id < first; id++)
+ __set_bit(id, chid->used);
+ for (id = first + count; id < nr; id++)
+ __set_bit(id, chid->used);
+
+ return nvkm_event_init(func, subdev, 1, nr, &chid->event);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.h
new file mode 100644
index 000000000000..2a42efb18401
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chid.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: MIT */
+#ifndef __NVKM_CHID_H__
+#define __NVKM_CHID_H__
+#include <core/event.h>
+
+struct nvkm_chid {
+ struct kref kref;
+ int nr;
+ u32 mask;
+
+ struct nvkm_event event;
+
+ void **data;
+
+ spinlock_t lock;
+ unsigned long used[];
+};
+
+int nvkm_chid_new(const struct nvkm_event_func *, struct nvkm_subdev *,
+ int nr, int first, int count, struct nvkm_chid **pchid);
+struct nvkm_chid *nvkm_chid_ref(struct nvkm_chid *);
+void nvkm_chid_unref(struct nvkm_chid **);
+int nvkm_chid_get(struct nvkm_chid *, void *data);
+void nvkm_chid_put(struct nvkm_chid *, int id, spinlock_t *data_lock);
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c
deleted file mode 100644
index dbcdc5fab990..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright 2012 Red Hat 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: Ben Skeggs
- */
-#include "channv04.h"
-#include "regsnv04.h"
-
-#include <core/client.h>
-#include <core/ramht.h>
-#include <subdev/instmem.h>
-
-#include <nvif/class.h>
-#include <nvif/cl006b.h>
-#include <nvif/unpack.h>
-
-void
-nv04_fifo_dma_object_dtor(struct nvkm_fifo_chan *base, int cookie)
-{
- struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
- struct nvkm_instmem *imem = chan->fifo->base.engine.subdev.device->imem;
-
- mutex_lock(&chan->fifo->base.mutex);
- nvkm_ramht_remove(imem->ramht, cookie);
- mutex_unlock(&chan->fifo->base.mutex);
-}
-
-static int
-nv04_fifo_dma_object_ctor(struct nvkm_fifo_chan *base,
- struct nvkm_object *object)
-{
- struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
- struct nvkm_instmem *imem = chan->fifo->base.engine.subdev.device->imem;
- u32 context = 0x80000000 | chan->base.chid << 24;
- u32 handle = object->handle;
- int hash;
-
- switch (object->engine->subdev.type) {
- case NVKM_ENGINE_DMAOBJ:
- case NVKM_ENGINE_SW : context |= 0x00000000; break;
- case NVKM_ENGINE_GR : context |= 0x00010000; break;
- case NVKM_ENGINE_MPEG : context |= 0x00020000; break;
- default:
- WARN_ON(1);
- return -EINVAL;
- }
-
- mutex_lock(&chan->fifo->base.mutex);
- hash = nvkm_ramht_insert(imem->ramht, object, chan->base.chid, 4,
- handle, context);
- mutex_unlock(&chan->fifo->base.mutex);
- return hash;
-}
-
-void
-nv04_fifo_dma_fini(struct nvkm_fifo_chan *base)
-{
- struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
- struct nv04_fifo *fifo = chan->fifo;
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- struct nvkm_memory *fctx = device->imem->ramfc;
- const struct nv04_fifo_ramfc *c;
- unsigned long flags;
- u32 mask = fifo->base.nr - 1;
- u32 data = chan->ramfc;
- u32 chid;
-
- /* prevent fifo context switches */
- spin_lock_irqsave(&fifo->base.lock, flags);
- nvkm_wr32(device, NV03_PFIFO_CACHES, 0);
-
- /* if this channel is active, replace it with a null context */
- chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & mask;
- if (chid == chan->base.chid) {
- nvkm_mask(device, NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001, 0);
- nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 0);
- nvkm_mask(device, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0);
-
- c = fifo->ramfc;
- nvkm_kmap(fctx);
- do {
- u32 rm = ((1ULL << c->bits) - 1) << c->regs;
- u32 cm = ((1ULL << c->bits) - 1) << c->ctxs;
- u32 rv = (nvkm_rd32(device, c->regp) & rm) >> c->regs;
- u32 cv = (nvkm_ro32(fctx, c->ctxp + data) & ~cm);
- nvkm_wo32(fctx, c->ctxp + data, cv | (rv << c->ctxs));
- } while ((++c)->bits);
- nvkm_done(fctx);
-
- c = fifo->ramfc;
- do {
- nvkm_wr32(device, c->regp, 0x00000000);
- } while ((++c)->bits);
-
- nvkm_wr32(device, NV03_PFIFO_CACHE1_GET, 0);
- nvkm_wr32(device, NV03_PFIFO_CACHE1_PUT, 0);
- nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, mask);
- nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 1);
- nvkm_wr32(device, NV04_PFIFO_CACHE1_PULL0, 1);
- }
-
- /* restore normal operation, after disabling dma mode */
- nvkm_mask(device, NV04_PFIFO_MODE, 1 << chan->base.chid, 0);
- nvkm_wr32(device, NV03_PFIFO_CACHES, 1);
- spin_unlock_irqrestore(&fifo->base.lock, flags);
-}
-
-void
-nv04_fifo_dma_init(struct nvkm_fifo_chan *base)
-{
- struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
- struct nv04_fifo *fifo = chan->fifo;
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- u32 mask = 1 << chan->base.chid;
- unsigned long flags;
- spin_lock_irqsave(&fifo->base.lock, flags);
- nvkm_mask(device, NV04_PFIFO_MODE, mask, mask);
- spin_unlock_irqrestore(&fifo->base.lock, flags);
-}
-
-void *
-nv04_fifo_dma_dtor(struct nvkm_fifo_chan *base)
-{
- struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
- struct nv04_fifo *fifo = chan->fifo;
- struct nvkm_instmem *imem = fifo->base.engine.subdev.device->imem;
- const struct nv04_fifo_ramfc *c = fifo->ramfc;
-
- nvkm_kmap(imem->ramfc);
- do {
- nvkm_wo32(imem->ramfc, chan->ramfc + c->ctxp, 0x00000000);
- } while ((++c)->bits);
- nvkm_done(imem->ramfc);
- return chan;
-}
-
-const struct nvkm_fifo_chan_func
-nv04_fifo_dma_func = {
- .dtor = nv04_fifo_dma_dtor,
- .init = nv04_fifo_dma_init,
- .fini = nv04_fifo_dma_fini,
- .object_ctor = nv04_fifo_dma_object_ctor,
- .object_dtor = nv04_fifo_dma_object_dtor,
-};
-
-static int
-nv04_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
- void *data, u32 size, struct nvkm_object **pobject)
-{
- struct nvkm_object *parent = oclass->parent;
- union {
- struct nv03_channel_dma_v0 v0;
- } *args = data;
- struct nv04_fifo *fifo = nv04_fifo(base);
- struct nv04_fifo_chan *chan = NULL;
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- struct nvkm_instmem *imem = device->imem;
- int ret = -ENOSYS;
-
- nvif_ioctl(parent, "create channel dma size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
- nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx "
- "offset %08x\n", args->v0.version,
- args->v0.pushbuf, args->v0.offset);
- if (!args->v0.pushbuf)
- return -EINVAL;
- } else
- return ret;
-
- if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
- return -ENOMEM;
- *pobject = &chan->base.object;
-
- ret = nvkm_fifo_chan_ctor(&nv04_fifo_dma_func, &fifo->base,
- 0x1000, 0x1000, false, 0, args->v0.pushbuf,
- BIT(NV04_FIFO_ENGN_SW) |
- BIT(NV04_FIFO_ENGN_GR) |
- BIT(NV04_FIFO_ENGN_DMA),
- 0, 0x800000, 0x10000, oclass, &chan->base);
- chan->fifo = fifo;
- if (ret)
- return ret;
-
- args->v0.chid = chan->base.chid;
- chan->ramfc = chan->base.chid * 32;
-
- nvkm_kmap(imem->ramfc);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x08, chan->base.push->addr >> 4);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x10,
- NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
- NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
-#ifdef __BIG_ENDIAN
- NV_PFIFO_CACHE1_BIG_ENDIAN |
-#endif
- NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8);
- nvkm_done(imem->ramfc);
- return 0;
-}
-
-const struct nvkm_fifo_chan_oclass
-nv04_fifo_dma_oclass = {
- .base.oclass = NV03_CHANNEL_DMA,
- .base.minver = 0,
- .base.maxver = 0,
- .ctor = nv04_fifo_dma_new,
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c
deleted file mode 100644
index 07d80d54a07c..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv10.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2012 Red Hat 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: Ben Skeggs
- */
-#include "channv04.h"
-#include "regsnv04.h"
-
-#include <core/client.h>
-#include <core/gpuobj.h>
-#include <subdev/instmem.h>
-
-#include <nvif/class.h>
-#include <nvif/cl006b.h>
-#include <nvif/unpack.h>
-
-static int
-nv10_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
- void *data, u32 size, struct nvkm_object **pobject)
-{
- struct nvkm_object *parent = oclass->parent;
- union {
- struct nv03_channel_dma_v0 v0;
- } *args = data;
- struct nv04_fifo *fifo = nv04_fifo(base);
- struct nv04_fifo_chan *chan = NULL;
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- struct nvkm_instmem *imem = device->imem;
- int ret = -ENOSYS;
-
- nvif_ioctl(parent, "create channel dma size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
- nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx "
- "offset %08x\n", args->v0.version,
- args->v0.pushbuf, args->v0.offset);
- if (!args->v0.pushbuf)
- return -EINVAL;
- } else
- return ret;
-
- if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
- return -ENOMEM;
- *pobject = &chan->base.object;
-
- ret = nvkm_fifo_chan_ctor(&nv04_fifo_dma_func, &fifo->base,
- 0x1000, 0x1000, false, 0, args->v0.pushbuf,
- BIT(NV04_FIFO_ENGN_SW) |
- BIT(NV04_FIFO_ENGN_GR) |
- BIT(NV04_FIFO_ENGN_DMA),
- 0, 0x800000, 0x10000, oclass, &chan->base);
- chan->fifo = fifo;
- if (ret)
- return ret;
-
- args->v0.chid = chan->base.chid;
- chan->ramfc = chan->base.chid * 32;
-
- nvkm_kmap(imem->ramfc);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.push->addr >> 4);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x14,
- NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
- NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
-#ifdef __BIG_ENDIAN
- NV_PFIFO_CACHE1_BIG_ENDIAN |
-#endif
- NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8);
- nvkm_done(imem->ramfc);
- return 0;
-}
-
-const struct nvkm_fifo_chan_oclass
-nv10_fifo_dma_oclass = {
- .base.oclass = NV10_CHANNEL_DMA,
- .base.minver = 0,
- .base.maxver = 0,
- .ctor = nv10_fifo_dma_new,
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c
deleted file mode 100644
index edd70a114218..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv17.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2012 Red Hat 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: Ben Skeggs
- */
-#include "channv04.h"
-#include "regsnv04.h"
-
-#include <core/client.h>
-#include <core/gpuobj.h>
-#include <subdev/instmem.h>
-
-#include <nvif/class.h>
-#include <nvif/cl006b.h>
-#include <nvif/unpack.h>
-
-static int
-nv17_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
- void *data, u32 size, struct nvkm_object **pobject)
-{
- struct nvkm_object *parent = oclass->parent;
- union {
- struct nv03_channel_dma_v0 v0;
- } *args = data;
- struct nv04_fifo *fifo = nv04_fifo(base);
- struct nv04_fifo_chan *chan = NULL;
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- struct nvkm_instmem *imem = device->imem;
- int ret = -ENOSYS;
-
- nvif_ioctl(parent, "create channel dma size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
- nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx "
- "offset %08x\n", args->v0.version,
- args->v0.pushbuf, args->v0.offset);
- if (!args->v0.pushbuf)
- return -EINVAL;
- } else
- return ret;
-
- if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
- return -ENOMEM;
- *pobject = &chan->base.object;
-
- ret = nvkm_fifo_chan_ctor(&nv04_fifo_dma_func, &fifo->base,
- 0x1000, 0x1000, false, 0, args->v0.pushbuf,
- BIT(NV04_FIFO_ENGN_SW) |
- BIT(NV04_FIFO_ENGN_GR) |
- BIT(NV04_FIFO_ENGN_MPEG) | /* NV31- */
- BIT(NV04_FIFO_ENGN_DMA),
- 0, 0x800000, 0x10000, oclass, &chan->base);
- chan->fifo = fifo;
- if (ret)
- return ret;
-
- args->v0.chid = chan->base.chid;
- chan->ramfc = chan->base.chid * 64;
-
- nvkm_kmap(imem->ramfc);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.push->addr >> 4);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x14,
- NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
- NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
-#ifdef __BIG_ENDIAN
- NV_PFIFO_CACHE1_BIG_ENDIAN |
-#endif
- NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8);
- nvkm_done(imem->ramfc);
- return 0;
-}
-
-const struct nvkm_fifo_chan_oclass
-nv17_fifo_dma_oclass = {
- .base.oclass = NV17_CHANNEL_DMA,
- .base.minver = 0,
- .base.maxver = 0,
- .ctor = nv17_fifo_dma_new,
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c
deleted file mode 100644
index 0411fb908457..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv40.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Copyright 2012 Red Hat 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: Ben Skeggs
- */
-#include "channv04.h"
-#include "regsnv04.h"
-
-#include <core/client.h>
-#include <core/ramht.h>
-#include <subdev/instmem.h>
-
-#include <nvif/class.h>
-#include <nvif/cl006b.h>
-#include <nvif/unpack.h>
-
-static bool
-nv40_fifo_dma_engine(struct nvkm_engine *engine, u32 *reg, u32 *ctx)
-{
- switch (engine->subdev.type) {
- case NVKM_ENGINE_DMAOBJ:
- case NVKM_ENGINE_SW:
- return false;
- case NVKM_ENGINE_GR:
- *reg = 0x0032e0;
- *ctx = 0x38;
- return true;
- case NVKM_ENGINE_MPEG:
- if (engine->subdev.device->chipset < 0x44)
- return false;
- *reg = 0x00330c;
- *ctx = 0x54;
- return true;
- default:
- WARN_ON(1);
- return false;
- }
-}
-
-static struct nvkm_gpuobj **
-nv40_fifo_dma_engn(struct nv04_fifo_chan *chan, struct nvkm_engine *engine)
-{
- int engi = chan->base.fifo->func->engine_id(chan->base.fifo, engine);
- if (engi >= 0)
- return &chan->engn[engi];
- return NULL;
-}
-
-static int
-nv40_fifo_dma_engine_fini(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine, bool suspend)
-{
- struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
- struct nv04_fifo *fifo = chan->fifo;
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- struct nvkm_instmem *imem = device->imem;
- unsigned long flags;
- u32 reg, ctx;
- int chid;
-
- if (!nv40_fifo_dma_engine(engine, &reg, &ctx))
- return 0;
-
- spin_lock_irqsave(&fifo->base.lock, flags);
- nvkm_mask(device, 0x002500, 0x00000001, 0x00000000);
-
- chid = nvkm_rd32(device, 0x003204) & (fifo->base.nr - 1);
- if (chid == chan->base.chid)
- nvkm_wr32(device, reg, 0x00000000);
- nvkm_kmap(imem->ramfc);
- nvkm_wo32(imem->ramfc, chan->ramfc + ctx, 0x00000000);
- nvkm_done(imem->ramfc);
-
- nvkm_mask(device, 0x002500, 0x00000001, 0x00000001);
- spin_unlock_irqrestore(&fifo->base.lock, flags);
- return 0;
-}
-
-static int
-nv40_fifo_dma_engine_init(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine)
-{
- struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
- struct nv04_fifo *fifo = chan->fifo;
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- struct nvkm_instmem *imem = device->imem;
- unsigned long flags;
- u32 inst, reg, ctx;
- int chid;
-
- if (!nv40_fifo_dma_engine(engine, &reg, &ctx))
- return 0;
- inst = (*nv40_fifo_dma_engn(chan, engine))->addr >> 4;
-
- spin_lock_irqsave(&fifo->base.lock, flags);
- nvkm_mask(device, 0x002500, 0x00000001, 0x00000000);
-
- chid = nvkm_rd32(device, 0x003204) & (fifo->base.nr - 1);
- if (chid == chan->base.chid)
- nvkm_wr32(device, reg, inst);
- nvkm_kmap(imem->ramfc);
- nvkm_wo32(imem->ramfc, chan->ramfc + ctx, inst);
- nvkm_done(imem->ramfc);
-
- nvkm_mask(device, 0x002500, 0x00000001, 0x00000001);
- spin_unlock_irqrestore(&fifo->base.lock, flags);
- return 0;
-}
-
-static void
-nv40_fifo_dma_engine_dtor(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine)
-{
- struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
- nvkm_gpuobj_del(nv40_fifo_dma_engn(chan, engine));
-}
-
-static int
-nv40_fifo_dma_engine_ctor(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine,
- struct nvkm_object *object)
-{
- struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
- u32 reg, ctx;
-
- if (!nv40_fifo_dma_engine(engine, &reg, &ctx))
- return 0;
-
- return nvkm_object_bind(object, NULL, 0, nv40_fifo_dma_engn(chan, engine));
-}
-
-static int
-nv40_fifo_dma_object_ctor(struct nvkm_fifo_chan *base,
- struct nvkm_object *object)
-{
- struct nv04_fifo_chan *chan = nv04_fifo_chan(base);
- struct nvkm_instmem *imem = chan->fifo->base.engine.subdev.device->imem;
- u32 context = chan->base.chid << 23;
- u32 handle = object->handle;
- int hash;
-
- switch (object->engine->subdev.type) {
- case NVKM_ENGINE_DMAOBJ:
- case NVKM_ENGINE_SW : context |= 0x00000000; break;
- case NVKM_ENGINE_GR : context |= 0x00100000; break;
- case NVKM_ENGINE_MPEG : context |= 0x00200000; break;
- default:
- WARN_ON(1);
- return -EINVAL;
- }
-
- mutex_lock(&chan->fifo->base.mutex);
- hash = nvkm_ramht_insert(imem->ramht, object, chan->base.chid, 4,
- handle, context);
- mutex_unlock(&chan->fifo->base.mutex);
- return hash;
-}
-
-static const struct nvkm_fifo_chan_func
-nv40_fifo_dma_func = {
- .dtor = nv04_fifo_dma_dtor,
- .init = nv04_fifo_dma_init,
- .fini = nv04_fifo_dma_fini,
- .engine_ctor = nv40_fifo_dma_engine_ctor,
- .engine_dtor = nv40_fifo_dma_engine_dtor,
- .engine_init = nv40_fifo_dma_engine_init,
- .engine_fini = nv40_fifo_dma_engine_fini,
- .object_ctor = nv40_fifo_dma_object_ctor,
- .object_dtor = nv04_fifo_dma_object_dtor,
-};
-
-static int
-nv40_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
- void *data, u32 size, struct nvkm_object **pobject)
-{
- struct nvkm_object *parent = oclass->parent;
- union {
- struct nv03_channel_dma_v0 v0;
- } *args = data;
- struct nv04_fifo *fifo = nv04_fifo(base);
- struct nv04_fifo_chan *chan = NULL;
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- struct nvkm_instmem *imem = device->imem;
- int ret = -ENOSYS;
-
- nvif_ioctl(parent, "create channel dma size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
- nvif_ioctl(parent, "create channel dma vers %d pushbuf %llx "
- "offset %08x\n", args->v0.version,
- args->v0.pushbuf, args->v0.offset);
- if (!args->v0.pushbuf)
- return -EINVAL;
- } else
- return ret;
-
- if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
- return -ENOMEM;
- *pobject = &chan->base.object;
-
- ret = nvkm_fifo_chan_ctor(&nv40_fifo_dma_func, &fifo->base,
- 0x1000, 0x1000, false, 0, args->v0.pushbuf,
- BIT(NV04_FIFO_ENGN_SW) |
- BIT(NV04_FIFO_ENGN_GR) |
- BIT(NV04_FIFO_ENGN_MPEG) |
- BIT(NV04_FIFO_ENGN_DMA),
- 0, 0xc00000, 0x1000, oclass, &chan->base);
- chan->fifo = fifo;
- if (ret)
- return ret;
-
- args->v0.chid = chan->base.chid;
- chan->ramfc = chan->base.chid * 128;
-
- nvkm_kmap(imem->ramfc);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x00, args->v0.offset);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x04, args->v0.offset);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x0c, chan->base.push->addr >> 4);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x18, 0x30000000 |
- NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
- NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
-#ifdef __BIG_ENDIAN
- NV_PFIFO_CACHE1_BIG_ENDIAN |
-#endif
- NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8);
- nvkm_wo32(imem->ramfc, chan->ramfc + 0x3c, 0x0001ffff);
- nvkm_done(imem->ramfc);
- return 0;
-}
-
-const struct nvkm_fifo_chan_oclass
-nv40_fifo_dma_oclass = {
- .base.oclass = NV40_CHANNEL_DMA,
- .base.minver = 0,
- .base.maxver = 0,
- .ctor = nv40_fifo_dma_new,
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c
index 3885c3830b94..6b229a3fbd97 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c
@@ -21,112 +21,211 @@
*
* Authors: Ben Skeggs
*/
-#include "nv50.h"
-#include "channv50.h"
+#include "priv.h"
+#include "cgrp.h"
+#include "chan.h"
+#include "runl.h"
+
+#include <core/ramht.h>
+#include <subdev/timer.h>
+
+#include <nvif/class.h>
static void
-g84_fifo_uevent_fini(struct nvkm_fifo *fifo)
+g84_chan_bind(struct nvkm_chan *chan)
{
- struct nvkm_device *device = fifo->engine.subdev.device;
- nvkm_mask(device, 0x002140, 0x40000000, 0x00000000);
+ struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
+
+ nvkm_wr32(device, 0x002600 + (chan->id * 4), chan->ramfc->addr >> 8);
}
-static void
-g84_fifo_uevent_init(struct nvkm_fifo *fifo)
+static int
+g84_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv)
{
- struct nvkm_device *device = fifo->engine.subdev.device;
- nvkm_mask(device, 0x002140, 0x40000000, 0x40000000);
+ struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
+ const u32 limit2 = ilog2(length / 8);
+ int ret;
+
+ ret = nvkm_gpuobj_new(device, 0x0200, 0, true, chan->inst, &chan->eng);
+ if (ret)
+ return ret;
+
+ ret = nvkm_gpuobj_new(device, 0x4000, 0, false, chan->inst, &chan->pgd);
+ if (ret)
+ return ret;
+
+ ret = nvkm_gpuobj_new(device, 0x1000, 0x400, true, chan->inst, &chan->cache);
+ if (ret)
+ return ret;
+
+ ret = nvkm_gpuobj_new(device, 0x100, 0x100, true, chan->inst, &chan->ramfc);
+ if (ret)
+ return ret;
+
+ ret = nvkm_ramht_new(device, 0x8000, 16, chan->inst, &chan->ramht);
+ if (ret)
+ return ret;
+
+ nvkm_kmap(chan->ramfc);
+ nvkm_wo32(chan->ramfc, 0x3c, 0x403f6078);
+ nvkm_wo32(chan->ramfc, 0x44, 0x01003fff);
+ nvkm_wo32(chan->ramfc, 0x48, chan->push->node->offset >> 4);
+ nvkm_wo32(chan->ramfc, 0x50, lower_32_bits(offset));
+ nvkm_wo32(chan->ramfc, 0x54, upper_32_bits(offset) | (limit2 << 16));
+ nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff);
+ nvkm_wo32(chan->ramfc, 0x78, 0x00000000);
+ nvkm_wo32(chan->ramfc, 0x7c, 0x30000000 | devm);
+ nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
+ (4 << 24) /* SEARCH_FULL */ |
+ (chan->ramht->gpuobj->node->offset >> 4));
+ nvkm_wo32(chan->ramfc, 0x88, chan->cache->addr >> 10);
+ nvkm_wo32(chan->ramfc, 0x98, chan->inst->addr >> 12);
+ nvkm_done(chan->ramfc);
+ return 0;
}
-static struct nvkm_engine *
-g84_fifo_id_engine(struct nvkm_fifo *fifo, int engi)
+static const struct nvkm_chan_func_ramfc
+g84_chan_ramfc = {
+ .write = g84_chan_ramfc_write,
+ .ctxdma = true,
+ .devm = 0xfff,
+};
+
+const struct nvkm_chan_func
+g84_chan = {
+ .inst = &nv50_chan_inst,
+ .userd = &nv50_chan_userd,
+ .ramfc = &g84_chan_ramfc,
+ .bind = g84_chan_bind,
+ .unbind = nv50_chan_unbind,
+ .start = nv50_chan_start,
+ .stop = nv50_chan_stop,
+};
+
+static void
+g84_ectx_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan *chan)
{
- struct nvkm_device *device = fifo->engine.subdev.device;
- struct nvkm_engine *engine;
- enum nvkm_subdev_type type;
-
- switch (engi) {
- case G84_FIFO_ENGN_SW : type = NVKM_ENGINE_SW; break;
- case G84_FIFO_ENGN_GR : type = NVKM_ENGINE_GR; break;
- case G84_FIFO_ENGN_MPEG :
- if ((engine = nvkm_device_engine(device, NVKM_ENGINE_MSPPP, 0)))
- return engine;
- type = NVKM_ENGINE_MPEG;
- break;
- case G84_FIFO_ENGN_ME :
- if ((engine = nvkm_device_engine(device, NVKM_ENGINE_CE, 0)))
- return engine;
- type = NVKM_ENGINE_ME;
- break;
- case G84_FIFO_ENGN_VP :
- if ((engine = nvkm_device_engine(device, NVKM_ENGINE_MSPDEC, 0)))
- return engine;
- type = NVKM_ENGINE_VP;
- break;
- case G84_FIFO_ENGN_CIPHER:
- if ((engine = nvkm_device_engine(device, NVKM_ENGINE_VIC, 0)))
- return engine;
- if ((engine = nvkm_device_engine(device, NVKM_ENGINE_SEC, 0)))
- return engine;
- type = NVKM_ENGINE_CIPHER;
- break;
- case G84_FIFO_ENGN_BSP :
- if ((engine = nvkm_device_engine(device, NVKM_ENGINE_MSVLD, 0)))
- return engine;
- type = NVKM_ENGINE_BSP;
- break;
- case G84_FIFO_ENGN_DMA : type = NVKM_ENGINE_DMAOBJ; break;
+ struct nvkm_subdev *subdev = &chan->cgrp->runl->fifo->engine.subdev;
+ struct nvkm_device *device = subdev->device;
+ u64 start = 0, limit = 0;
+ u32 flags = 0, ptr0, save;
+
+ switch (engn->engine->subdev.type) {
+ case NVKM_ENGINE_GR : ptr0 = 0x0020; break;
+ case NVKM_ENGINE_VP :
+ case NVKM_ENGINE_MSPDEC: ptr0 = 0x0040; break;
+ case NVKM_ENGINE_MPEG :
+ case NVKM_ENGINE_MSPPP : ptr0 = 0x0060; break;
+ case NVKM_ENGINE_BSP :
+ case NVKM_ENGINE_MSVLD : ptr0 = 0x0080; break;
+ case NVKM_ENGINE_CIPHER:
+ case NVKM_ENGINE_SEC : ptr0 = 0x00a0; break;
+ case NVKM_ENGINE_CE : ptr0 = 0x00c0; break;
default:
WARN_ON(1);
- return NULL;
+ return;
+ }
+
+ if (!cctx) {
+ save = nvkm_mask(device, 0x002520, 0x0000003f, BIT(engn->id - 1));
+ nvkm_wr32(device, 0x0032fc, chan->inst->addr >> 12);
+ nvkm_msec(device, 2000,
+ if (nvkm_rd32(device, 0x0032fc) != 0xffffffff)
+ break;
+ );
+ nvkm_wr32(device, 0x002520, save);
+ } else {
+ flags = 0x00190000;
+ start = cctx->vctx->inst->addr;
+ limit = start + cctx->vctx->inst->size - 1;
}
- return nvkm_device_engine(fifo->engine.subdev.device, type, 0);
+ nvkm_kmap(chan->eng);
+ nvkm_wo32(chan->eng, ptr0 + 0x00, flags);
+ nvkm_wo32(chan->eng, ptr0 + 0x04, lower_32_bits(limit));
+ nvkm_wo32(chan->eng, ptr0 + 0x08, lower_32_bits(start));
+ nvkm_wo32(chan->eng, ptr0 + 0x0c, upper_32_bits(limit) << 24 |
+ lower_32_bits(start));
+ nvkm_wo32(chan->eng, ptr0 + 0x10, 0x00000000);
+ nvkm_wo32(chan->eng, ptr0 + 0x14, 0x00000000);
+ nvkm_done(chan->eng);
}
+const struct nvkm_engn_func
+g84_engn = {
+ .bind = g84_ectx_bind,
+ .ramht_add = nv50_eobj_ramht_add,
+ .ramht_del = nv50_eobj_ramht_del,
+};
+
+static void
+g84_fifo_nonstall_block(struct nvkm_event *event, int type, int index)
+{
+ struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event);
+ unsigned long flags;
+
+ spin_lock_irqsave(&fifo->lock, flags);
+ nvkm_mask(fifo->engine.subdev.device, 0x002140, 0x40000000, 0x00000000);
+ spin_unlock_irqrestore(&fifo->lock, flags);
+}
+
+static void
+g84_fifo_nonstall_allow(struct nvkm_event *event, int type, int index)
+{
+ struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event);
+ unsigned long flags;
+
+ spin_lock_irqsave(&fifo->lock, flags);
+ nvkm_mask(fifo->engine.subdev.device, 0x002140, 0x40000000, 0x40000000);
+ spin_unlock_irqrestore(&fifo->lock, flags);
+}
+
+const struct nvkm_event_func
+g84_fifo_nonstall = {
+ .init = g84_fifo_nonstall_allow,
+ .fini = g84_fifo_nonstall_block,
+};
+
static int
-g84_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine)
+g84_fifo_runl_ctor(struct nvkm_fifo *fifo)
{
- switch (engine->subdev.type) {
- case NVKM_ENGINE_SW : return G84_FIFO_ENGN_SW;
- case NVKM_ENGINE_GR : return G84_FIFO_ENGN_GR;
- case NVKM_ENGINE_MPEG :
- case NVKM_ENGINE_MSPPP : return G84_FIFO_ENGN_MPEG;
- case NVKM_ENGINE_CE : return G84_FIFO_ENGN_CE0;
- case NVKM_ENGINE_VP :
- case NVKM_ENGINE_MSPDEC: return G84_FIFO_ENGN_VP;
- case NVKM_ENGINE_CIPHER:
- case NVKM_ENGINE_SEC : return G84_FIFO_ENGN_CIPHER;
- case NVKM_ENGINE_BSP :
- case NVKM_ENGINE_MSVLD : return G84_FIFO_ENGN_BSP;
- case NVKM_ENGINE_DMAOBJ: return G84_FIFO_ENGN_DMA;
- default:
- WARN_ON(1);
- return -1;
- }
+ struct nvkm_runl *runl;
+
+ runl = nvkm_runl_new(fifo, 0, 0, 0);
+ if (IS_ERR(runl))
+ return PTR_ERR(runl);
+
+ nvkm_runl_add(runl, 0, fifo->func->engn_sw, NVKM_ENGINE_SW, 0);
+ nvkm_runl_add(runl, 0, fifo->func->engn_sw, NVKM_ENGINE_DMAOBJ, 0);
+ nvkm_runl_add(runl, 1, fifo->func->engn, NVKM_ENGINE_GR, 0);
+ nvkm_runl_add(runl, 2, fifo->func->engn, NVKM_ENGINE_MPEG, 0);
+ nvkm_runl_add(runl, 3, fifo->func->engn, NVKM_ENGINE_ME, 0);
+ nvkm_runl_add(runl, 4, fifo->func->engn, NVKM_ENGINE_VP, 0);
+ nvkm_runl_add(runl, 5, fifo->func->engn, NVKM_ENGINE_CIPHER, 0);
+ nvkm_runl_add(runl, 6, fifo->func->engn, NVKM_ENGINE_BSP, 0);
+ return 0;
}
static const struct nvkm_fifo_func
g84_fifo = {
- .dtor = nv50_fifo_dtor,
- .oneinit = nv50_fifo_oneinit,
+ .chid_nr = nv50_fifo_chid_nr,
+ .chid_ctor = nv50_fifo_chid_ctor,
+ .runl_ctor = g84_fifo_runl_ctor,
.init = nv50_fifo_init,
.intr = nv04_fifo_intr,
- .engine_id = g84_fifo_engine_id,
- .id_engine = g84_fifo_id_engine,
.pause = nv04_fifo_pause,
.start = nv04_fifo_start,
- .uevent_init = g84_fifo_uevent_init,
- .uevent_fini = g84_fifo_uevent_fini,
- .chan = {
- &g84_fifo_gpfifo_oclass,
- NULL
- },
+ .nonstall = &g84_fifo_nonstall,
+ .runl = &nv50_runl,
+ .engn = &g84_engn,
+ .engn_sw = &nv50_engn_sw,
+ .cgrp = {{ }, &nv04_cgrp },
+ .chan = {{ 0, 0, G82_CHANNEL_GPFIFO }, &g84_chan },
};
int
g84_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
- return nv50_fifo_new_(&g84_fifo, device, type, inst, pfifo);
+ return nvkm_fifo_new_(&g84_fifo, device, type, inst, pfifo);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c
new file mode 100644
index 000000000000..c6ca050c38bf
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/g98.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2021 Red Hat 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 "priv.h"
+#include "chan.h"
+#include "runl.h"
+
+#include <nvif/class.h>
+
+static int
+g98_fifo_runl_ctor(struct nvkm_fifo *fifo)
+{
+ struct nvkm_runl *runl;
+
+ runl = nvkm_runl_new(fifo, 0, 0, 0);
+ if (IS_ERR(runl))
+ return PTR_ERR(runl);
+
+ nvkm_runl_add(runl, 0, fifo->func->engn_sw, NVKM_ENGINE_SW, 0);
+ nvkm_runl_add(runl, 0, fifo->func->engn_sw, NVKM_ENGINE_DMAOBJ, 0);
+ nvkm_runl_add(runl, 1, fifo->func->engn, NVKM_ENGINE_GR, 0);
+ nvkm_runl_add(runl, 2, fifo->func->engn, NVKM_ENGINE_MSPPP, 0);
+ nvkm_runl_add(runl, 3, fifo->func->engn, NVKM_ENGINE_CE, 0);
+ nvkm_runl_add(runl, 4, fifo->func->engn, NVKM_ENGINE_MSPDEC, 0);
+ nvkm_runl_add(runl, 5, fifo->func->engn, NVKM_ENGINE_SEC, 0);
+ nvkm_runl_add(runl, 6, fifo->func->engn, NVKM_ENGINE_MSVLD, 0);
+ return 0;
+}
+
+static const struct nvkm_fifo_func
+g98_fifo = {
+ .chid_nr = nv50_fifo_chid_nr,
+ .chid_ctor = nv50_fifo_chid_ctor,
+ .runl_ctor = g98_fifo_runl_ctor,
+ .init = nv50_fifo_init,
+ .intr = nv04_fifo_intr,
+ .pause = nv04_fifo_pause,
+ .start = nv04_fifo_start,
+ .nonstall = &g84_fifo_nonstall,
+ .runl = &nv50_runl,
+ .engn = &g84_engn,
+ .engn_sw = &nv50_engn_sw,
+ .cgrp = {{ }, &nv04_cgrp },
+ .chan = {{ 0, 0, G82_CHANNEL_GPFIFO }, &g84_chan },
+};
+
+int
+g98_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
+ struct nvkm_fifo **pfifo)
+{
+ return nvkm_fifo_new_(&g98_fifo, device, type, inst, pfifo);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c
new file mode 100644
index 000000000000..12a5d99d5e77
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga100.c
@@ -0,0 +1,550 @@
+/*
+ * Copyright 2021 Red Hat 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 "priv.h"
+#include "cgrp.h"
+#include "chan.h"
+#include "chid.h"
+#include "runl.h"
+#include "runq.h"
+
+#include <core/gpuobj.h>
+#include <subdev/top.h>
+#include <subdev/vfn.h>
+
+#include <nvif/class.h>
+
+/*TODO: allocate? */
+#define GA100_FIFO_NONSTALL_VECTOR 0
+
+static u32
+ga100_chan_doorbell_handle(struct nvkm_chan *chan)
+{
+ return (chan->cgrp->runl->doorbell << 16) | chan->id;
+}
+
+static void
+ga100_chan_stop(struct nvkm_chan *chan)
+{
+ struct nvkm_runl *runl = chan->cgrp->runl;
+
+ nvkm_wr32(runl->fifo->engine.subdev.device, runl->chan + (chan->id * 4), 0x00000003);
+}
+
+static void
+ga100_chan_start(struct nvkm_chan *chan)
+{
+ struct nvkm_runl *runl = chan->cgrp->runl;
+ struct nvkm_device *device = runl->fifo->engine.subdev.device;
+ const int gfid = 0;
+
+ nvkm_wr32(device, runl->chan + (chan->id * 4), 0x00000002);
+ nvkm_wr32(device, runl->addr + 0x0090, (gfid << 16) | chan->id); /* INTERNAL_DOORBELL. */
+}
+
+static void
+ga100_chan_unbind(struct nvkm_chan *chan)
+{
+ struct nvkm_runl *runl = chan->cgrp->runl;
+
+ nvkm_wr32(runl->fifo->engine.subdev.device, runl->chan + (chan->id * 4), 0xffffffff);
+}
+
+static int
+ga100_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv)
+{
+ const u32 limit2 = ilog2(length / 8);
+
+ nvkm_kmap(chan->inst);
+ nvkm_wo32(chan->inst, 0x010, 0x0000face);
+ nvkm_wo32(chan->inst, 0x030, 0x7ffff902);
+ nvkm_wo32(chan->inst, 0x048, lower_32_bits(offset));
+ nvkm_wo32(chan->inst, 0x04c, upper_32_bits(offset) | (limit2 << 16));
+ nvkm_wo32(chan->inst, 0x084, 0x20400000);
+ nvkm_wo32(chan->inst, 0x094, 0x30000000 | devm);
+ nvkm_wo32(chan->inst, 0x0e4, priv ? 0x00000020 : 0x00000000);
+ nvkm_wo32(chan->inst, 0x0e8, chan->id);
+ nvkm_wo32(chan->inst, 0x0f4, 0x00001000 | (priv ? 0x00000100 : 0x00000000));
+ nvkm_wo32(chan->inst, 0x0f8, 0x80000000 | GA100_FIFO_NONSTALL_VECTOR);
+ nvkm_mo32(chan->inst, 0x218, 0x00000000, 0x00000000);
+ nvkm_done(chan->inst);
+ return 0;
+}
+
+static const struct nvkm_chan_func_ramfc
+ga100_chan_ramfc = {
+ .write = ga100_chan_ramfc_write,
+ .devm = 0xfff,
+ .priv = true,
+};
+
+const struct nvkm_chan_func
+ga100_chan = {
+ .inst = &gf100_chan_inst,
+ .userd = &gv100_chan_userd,
+ .ramfc = &ga100_chan_ramfc,
+ .unbind = ga100_chan_unbind,
+ .start = ga100_chan_start,
+ .stop = ga100_chan_stop,
+ .preempt = gk110_chan_preempt,
+ .doorbell_handle = ga100_chan_doorbell_handle,
+};
+
+static void
+ga100_cgrp_preempt(struct nvkm_cgrp *cgrp)
+{
+ struct nvkm_runl *runl = cgrp->runl;
+
+ nvkm_wr32(runl->fifo->engine.subdev.device, runl->addr + 0x098, 0x01000000 | cgrp->id);
+}
+
+const struct nvkm_cgrp_func
+ga100_cgrp = {
+ .preempt = ga100_cgrp_preempt,
+};
+
+static int
+ga100_engn_cxid(struct nvkm_engn *engn, bool *cgid)
+{
+ struct nvkm_runl *runl = engn->runl;
+ struct nvkm_device *device = runl->fifo->engine.subdev.device;
+ u32 stat = nvkm_rd32(device, runl->addr + 0x200 + engn->id * 0x40);
+
+ ENGN_DEBUG(engn, "status %08x", stat);
+ *cgid = true;
+
+ switch ((stat & 0x0000e000) >> 13) {
+ case 0 /* INVALID */: return -ENODEV;
+ case 1 /* VALID */:
+ case 5 /* SAVE */: return (stat & 0x00000fff);
+ case 6 /* LOAD */: return (stat & 0x0fff0000) >> 16;
+ case 7 /* SWITCH */:
+ if (nvkm_engine_chsw_load(engn->engine))
+ return (stat & 0x0fff0000) >> 16;
+ return (stat & 0x00000fff);
+ default:
+ WARN_ON(1);
+ break;
+ }
+
+ return -ENODEV;
+}
+
+const struct nvkm_engn_func
+ga100_engn = {
+ .cxid = ga100_engn_cxid,
+ .ctor = gk104_ectx_ctor,
+ .bind = gv100_ectx_bind,
+};
+
+const struct nvkm_engn_func
+ga100_engn_ce = {
+ .cxid = ga100_engn_cxid,
+ .ctor = gv100_ectx_ce_ctor,
+ .bind = gv100_ectx_ce_bind,
+};
+
+static bool
+ga100_runq_idle(struct nvkm_runq *runq)
+{
+ struct nvkm_device *device = runq->fifo->engine.subdev.device;
+
+ return !(nvkm_rd32(device, 0x04015c + (runq->id * 0x800)) & 0x0000e000);
+}
+
+static bool
+ga100_runq_intr_1(struct nvkm_runq *runq, struct nvkm_runl *runl)
+{
+ struct nvkm_device *device = runq->fifo->engine.subdev.device;
+ u32 inte = nvkm_rd32(device, 0x040180 + (runq->id * 0x800));
+ u32 intr = nvkm_rd32(device, 0x040148 + (runq->id * 0x800));
+ u32 stat = intr & inte;
+
+ if (!stat) {
+ RUNQ_DEBUG(runq, "inte1 %08x %08x", intr, inte);
+ return false;
+ }
+
+ if (stat & 0x80000000) {
+ u32 chid = nvkm_rd32(device, 0x040120 + (runq->id * 0x0800)) & runl->chid->mask;
+ struct nvkm_chan *chan;
+ unsigned long flags;
+
+ RUNQ_ERROR(runq, "CTXNOTVALID chid:%d", chid);
+ chan = nvkm_runl_chan_get_chid(runl, chid, &flags);
+ if (chan) {
+ nvkm_chan_error(chan, true);
+ nvkm_chan_put(&chan, flags);
+ }
+
+ nvkm_mask(device, 0x0400ac + (runq->id * 0x800), 0x00030000, 0x00030000);
+ stat &= ~0x80000000;
+ }
+
+ if (stat) {
+ RUNQ_ERROR(runq, "intr1 %08x", stat);
+ nvkm_wr32(device, 0x0401a0 + (runq->id * 0x800), stat);
+ }
+
+ nvkm_wr32(device, 0x040148 + (runq->id * 0x800), intr);
+ return true;
+}
+
+static bool
+ga100_runq_intr_0(struct nvkm_runq *runq, struct nvkm_runl *runl)
+{
+ struct nvkm_device *device = runq->fifo->engine.subdev.device;
+ u32 inte = nvkm_rd32(device, 0x040170 + (runq->id * 0x800));
+ u32 intr = nvkm_rd32(device, 0x040108 + (runq->id * 0x800));
+ u32 stat = intr & inte;
+
+ if (!stat) {
+ RUNQ_DEBUG(runq, "inte0 %08x %08x", intr, inte);
+ return false;
+ }
+
+ /*TODO: expand on this when fixing up gf100's version. */
+ if (stat & 0xc6afe000) {
+ u32 chid = nvkm_rd32(device, 0x040120 + (runq->id * 0x0800)) & runl->chid->mask;
+ struct nvkm_chan *chan;
+ unsigned long flags;
+
+ RUNQ_ERROR(runq, "intr0 %08x", stat);
+ chan = nvkm_runl_chan_get_chid(runl, chid, &flags);
+ if (chan) {
+ nvkm_chan_error(chan, true);
+ nvkm_chan_put(&chan, flags);
+ }
+
+ stat &= ~0xc6afe000;
+ }
+
+ if (stat) {
+ RUNQ_ERROR(runq, "intr0 %08x", stat);
+ nvkm_wr32(device, 0x040190 + (runq->id * 0x800), stat);
+ }
+
+ nvkm_wr32(device, 0x040108 + (runq->id * 0x800), intr);
+ return true;
+}
+
+static bool
+ga100_runq_intr(struct nvkm_runq *runq, struct nvkm_runl *runl)
+{
+ bool intr0 = ga100_runq_intr_0(runq, runl);
+ bool intr1 = ga100_runq_intr_1(runq, runl);
+
+ return intr0 || intr1;
+}
+
+static void
+ga100_runq_init(struct nvkm_runq *runq)
+{
+ struct nvkm_device *device = runq->fifo->engine.subdev.device;
+
+ nvkm_wr32(device, 0x040108 + (runq->id * 0x800), 0xffffffff); /* INTR_0 */
+ nvkm_wr32(device, 0x040148 + (runq->id * 0x800), 0xffffffff); /* INTR_1 */
+ nvkm_wr32(device, 0x040170 + (runq->id * 0x800), 0xffffffff); /* INTR_0_EN_SET_TREE */
+ nvkm_wr32(device, 0x040180 + (runq->id * 0x800), 0xffffffff); /* INTR_1_EN_SET_TREE */
+}
+
+const struct nvkm_runq_func
+ga100_runq = {
+ .init = ga100_runq_init,
+ .intr = ga100_runq_intr,
+ .idle = ga100_runq_idle,
+};
+
+static bool
+ga100_runl_preempt_pending(struct nvkm_runl *runl)
+{
+ return nvkm_rd32(runl->fifo->engine.subdev.device, runl->addr + 0x098) & 0x00100000;
+}
+
+static void
+ga100_runl_preempt(struct nvkm_runl *runl)
+{
+ nvkm_wr32(runl->fifo->engine.subdev.device, runl->addr + 0x098, 0x00000000);
+}
+
+static void
+ga100_runl_allow(struct nvkm_runl *runl, u32 engm)
+{
+ nvkm_mask(runl->fifo->engine.subdev.device, runl->addr + 0x094, 0x00000001, 0x00000000);
+}
+
+static void
+ga100_runl_block(struct nvkm_runl *runl, u32 engm)
+{
+ nvkm_mask(runl->fifo->engine.subdev.device, runl->addr + 0x094, 0x00000001, 0x00000001);
+}
+
+static bool
+ga100_runl_pending(struct nvkm_runl *runl)
+{
+ struct nvkm_device *device = runl->fifo->engine.subdev.device;
+
+ return nvkm_rd32(device, runl->addr + 0x08c) & 0x00008000;
+}
+
+static void
+ga100_runl_commit(struct nvkm_runl *runl, struct nvkm_memory *memory, u32 start, int count)
+{
+ struct nvkm_device *device = runl->fifo->engine.subdev.device;
+ u64 addr = nvkm_memory_addr(memory) + start;
+
+ nvkm_wr32(device, runl->addr + 0x080, lower_32_bits(addr));
+ nvkm_wr32(device, runl->addr + 0x084, upper_32_bits(addr));
+ nvkm_wr32(device, runl->addr + 0x088, count);
+}
+
+static irqreturn_t
+ga100_runl_intr(struct nvkm_inth *inth)
+{
+ struct nvkm_runl *runl = container_of(inth, typeof(*runl), inth);
+ struct nvkm_engn *engn;
+ struct nvkm_device *device = runl->fifo->engine.subdev.device;
+ u32 inte = nvkm_rd32(device, runl->addr + 0x120);
+ u32 intr = nvkm_rd32(device, runl->addr + 0x100);
+ u32 stat = intr & inte;
+ u32 info;
+
+ if (!stat) {
+ RUNL_DEBUG(runl, "inte %08x %08x", intr, inte);
+ return IRQ_NONE;
+ }
+
+ if (stat & 0x00000007) {
+ nvkm_runl_foreach_engn_cond(engn, runl, stat & BIT(engn->id)) {
+ info = nvkm_rd32(device, runl->addr + 0x224 + (engn->id * 0x40));
+
+ tu102_fifo_intr_ctxsw_timeout_info(engn, info);
+
+ nvkm_wr32(device, runl->addr + 0x100, BIT(engn->id));
+ stat &= ~BIT(engn->id);
+ }
+ }
+
+ if (stat & 0x00000300) {
+ nvkm_wr32(device, runl->addr + 0x100, stat & 0x00000300);
+ stat &= ~0x00000300;
+ }
+
+ if (stat & 0x00010000) {
+ if (runl->runq[0]) {
+ if (runl->runq[0]->func->intr(runl->runq[0], runl))
+ stat &= ~0x00010000;
+ }
+ }
+
+ if (stat & 0x00020000) {
+ if (runl->runq[1]) {
+ if (runl->runq[1]->func->intr(runl->runq[1], runl))
+ stat &= ~0x00020000;
+ }
+ }
+
+ if (stat) {
+ RUNL_ERROR(runl, "intr %08x", stat);
+ nvkm_wr32(device, runl->addr + 0x140, stat);
+ }
+
+ nvkm_wr32(device, runl->addr + 0x180, 0x00000001);
+ return IRQ_HANDLED;
+}
+
+static void
+ga100_runl_fini(struct nvkm_runl *runl)
+{
+ nvkm_mask(runl->fifo->engine.subdev.device, runl->addr + 0x300, 0x80000000, 0x00000000);
+ nvkm_inth_block(&runl->inth);
+}
+
+static void
+ga100_runl_init(struct nvkm_runl *runl)
+{
+ struct nvkm_fifo *fifo = runl->fifo;
+ struct nvkm_runq *runq;
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ int i;
+
+ /* Submit NULL runlist and preempt. */
+ nvkm_wr32(device, runl->addr + 0x088, 0x00000000);
+ runl->func->preempt(runl);
+
+ /* Enable doorbell. */
+ nvkm_mask(device, runl->addr + 0x300, 0x80000000, 0x80000000);
+
+ nvkm_wr32(device, runl->addr + 0x100, 0xffffffff); /* INTR_0 */
+ nvkm_wr32(device, runl->addr + 0x140, 0xffffffff); /* INTR_0_EN_CLEAR_TREE(0) */
+ nvkm_wr32(device, runl->addr + 0x120, 0x000f1307); /* INTR_0_EN_SET_TREE(0) */
+ nvkm_wr32(device, runl->addr + 0x148, 0xffffffff); /* INTR_0_EN_CLEAR_TREE(1) */
+ nvkm_wr32(device, runl->addr + 0x128, 0x00000000); /* INTR_0_EN_SET_TREE(1) */
+
+ /* Init PBDMA(s). */
+ for (i = 0; i < runl->runq_nr; i++) {
+ runq = runl->runq[i];
+ runq->func->init(runq);
+ }
+
+ nvkm_inth_allow(&runl->inth);
+}
+
+const struct nvkm_runl_func
+ga100_runl = {
+ .init = ga100_runl_init,
+ .fini = ga100_runl_fini,
+ .size = 16,
+ .update = nv50_runl_update,
+ .insert_cgrp = gv100_runl_insert_cgrp,
+ .insert_chan = gv100_runl_insert_chan,
+ .commit = ga100_runl_commit,
+ .wait = nv50_runl_wait,
+ .pending = ga100_runl_pending,
+ .block = ga100_runl_block,
+ .allow = ga100_runl_allow,
+ .preempt = ga100_runl_preempt,
+ .preempt_pending = ga100_runl_preempt_pending,
+};
+
+static int
+ga100_runl_new(struct nvkm_fifo *fifo, int id, u32 addr, struct nvkm_runl **prunl)
+{
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ struct nvkm_runl *runl;
+ u32 chcfg = nvkm_rd32(device, addr + 0x004);
+ u32 chnum = 1 << (chcfg & 0x0000000f);
+ u32 chaddr = (chcfg & 0xfffffff0);
+ u32 dbcfg = nvkm_rd32(device, addr + 0x008);
+ u32 vector = nvkm_rd32(device, addr + 0x160);
+ int i, ret;
+
+ runl = *prunl = nvkm_runl_new(fifo, id, addr, chnum);
+ if (IS_ERR(runl))
+ return PTR_ERR(runl);
+
+ for (i = 0; i < 2; i++) {
+ u32 pbcfg = nvkm_rd32(device, addr + 0x010 + (i * 0x04));
+ if (pbcfg & 0x80000000) {
+ runl->runq[runl->runq_nr] =
+ nvkm_runq_new(fifo, ((pbcfg & 0x03fffc00) - 0x040000) / 0x800);
+ if (!runl->runq[runl->runq_nr])
+ return -ENOMEM;
+
+ runl->runq_nr++;
+ }
+ }
+
+ ret = nvkm_inth_add(&device->vfn->intr, vector & 0x00000fff, NVKM_INTR_PRIO_NORMAL,
+ &fifo->engine.subdev, ga100_runl_intr, &runl->inth);
+ if (ret)
+ return ret;
+
+ runl->chan = chaddr;
+ runl->doorbell = dbcfg >> 16;
+ return 0;
+}
+
+static irqreturn_t
+ga100_fifo_nonstall_intr(struct nvkm_inth *inth)
+{
+ struct nvkm_fifo *fifo = container_of(inth, typeof(*fifo), nonstall.intr);
+
+ nvkm_event_ntfy(&fifo->nonstall.event, 0, NVKM_FIFO_NONSTALL_EVENT);
+ return IRQ_HANDLED;
+}
+
+static void
+ga100_fifo_nonstall_block(struct nvkm_event *event, int type, int index)
+{
+ struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event);
+
+ nvkm_inth_block(&fifo->nonstall.intr);
+}
+
+static void
+ga100_fifo_nonstall_allow(struct nvkm_event *event, int type, int index)
+{
+ struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event);
+
+ nvkm_inth_allow(&fifo->nonstall.intr);
+}
+
+const struct nvkm_event_func
+ga100_fifo_nonstall = {
+ .init = ga100_fifo_nonstall_allow,
+ .fini = ga100_fifo_nonstall_block,
+};
+
+int
+ga100_fifo_nonstall_ctor(struct nvkm_fifo *fifo)
+{
+ return nvkm_inth_add(&fifo->engine.subdev.device->vfn->intr, GA100_FIFO_NONSTALL_VECTOR,
+ NVKM_INTR_PRIO_NORMAL, &fifo->engine.subdev, ga100_fifo_nonstall_intr,
+ &fifo->nonstall.intr);
+}
+
+int
+ga100_fifo_runl_ctor(struct nvkm_fifo *fifo)
+{
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ struct nvkm_top_device *tdev;
+ struct nvkm_runl *runl;
+ int id = 0, ret;
+
+ nvkm_list_foreach(tdev, &device->top->device, head, tdev->runlist >= 0) {
+ runl = nvkm_runl_get(fifo, -1, tdev->runlist);
+ if (!runl) {
+ ret = ga100_runl_new(fifo, id++, tdev->runlist, &runl);
+ if (ret)
+ return ret;
+ }
+
+ if (tdev->engine < 0)
+ continue;
+
+ nvkm_runl_add(runl, tdev->engine, (tdev->type == NVKM_ENGINE_CE) ?
+ fifo->func->engn_ce : fifo->func->engn, tdev->type, tdev->inst);
+ }
+
+ return 0;
+}
+
+static const struct nvkm_fifo_func
+ga100_fifo = {
+ .runl_ctor = ga100_fifo_runl_ctor,
+ .mmu_fault = &tu102_fifo_mmu_fault,
+ .nonstall_ctor = ga100_fifo_nonstall_ctor,
+ .nonstall = &ga100_fifo_nonstall,
+ .runl = &ga100_runl,
+ .runq = &ga100_runq,
+ .engn = &ga100_engn,
+ .engn_ce = &ga100_engn_ce,
+ .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &ga100_cgrp, .force = true },
+ .chan = {{ 0, 0, AMPERE_CHANNEL_GPFIFO_A }, &ga100_chan },
+};
+
+int
+ga100_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
+ struct nvkm_fifo **pfifo)
+{
+ return nvkm_fifo_new_(&ga100_fifo, device, type, inst, pfifo);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c
index c630dbd2911a..2cdf5da339b6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ga102.c
@@ -19,293 +19,27 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#define ga102_fifo(p) container_of((p), struct ga102_fifo, base.engine)
-#define ga102_chan(p) container_of((p), struct ga102_chan, object)
-#include <engine/fifo.h>
-#include "user.h"
+#include "priv.h"
-#include <core/memory.h>
-#include <subdev/mmu.h>
-#include <subdev/timer.h>
-#include <subdev/top.h>
-
-#include <nvif/cl0080.h>
-#include <nvif/clc36f.h>
#include <nvif/class.h>
-struct ga102_fifo {
- struct nvkm_fifo base;
-};
-
-struct ga102_chan {
- struct nvkm_object object;
-
- struct {
- u32 runl;
- u32 chan;
- } ctrl;
-
- struct nvkm_memory *mthd;
- struct nvkm_memory *inst;
- struct nvkm_memory *user;
- struct nvkm_memory *runl;
-
- struct nvkm_vmm *vmm;
-};
-
-static int
-ga102_chan_sclass(struct nvkm_object *object, int index, struct nvkm_oclass *oclass)
-{
- if (index == 0) {
- oclass->ctor = nvkm_object_new;
- oclass->base = (struct nvkm_sclass) { -1, -1, AMPERE_DMA_COPY_B };
- return 0;
- }
-
- return -EINVAL;
-}
-
-static int
-ga102_chan_map(struct nvkm_object *object, void *argv, u32 argc,
- enum nvkm_object_map *type, u64 *addr, u64 *size)
-{
- struct ga102_chan *chan = ga102_chan(object);
- struct nvkm_device *device = chan->object.engine->subdev.device;
- u64 bar2 = nvkm_memory_bar2(chan->user);
-
- if (bar2 == ~0ULL)
- return -EFAULT;
-
- *type = NVKM_OBJECT_MAP_IO;
- *addr = device->func->resource_addr(device, 3) + bar2;
- *size = 0x1000;
- return 0;
-}
-
-static int
-ga102_chan_fini(struct nvkm_object *object, bool suspend)
-{
- struct ga102_chan *chan = ga102_chan(object);
- struct nvkm_device *device = chan->object.engine->subdev.device;
-
- nvkm_wr32(device, chan->ctrl.chan, 0x00000003);
-
- nvkm_wr32(device, chan->ctrl.runl + 0x098, 0x01000000);
- nvkm_msec(device, 2000,
- if (!(nvkm_rd32(device, chan->ctrl.runl + 0x098) & 0x00100000))
- break;
- );
-
- nvkm_wr32(device, chan->ctrl.runl + 0x088, 0);
-
- nvkm_wr32(device, chan->ctrl.chan, 0xffffffff);
- return 0;
-}
-
-static int
-ga102_chan_init(struct nvkm_object *object)
-{
- struct ga102_chan *chan = ga102_chan(object);
- struct nvkm_device *device = chan->object.engine->subdev.device;
-
- nvkm_mask(device, chan->ctrl.runl + 0x300, 0x80000000, 0x80000000);
-
- nvkm_wr32(device, chan->ctrl.runl + 0x080, lower_32_bits(nvkm_memory_addr(chan->runl)));
- nvkm_wr32(device, chan->ctrl.runl + 0x084, upper_32_bits(nvkm_memory_addr(chan->runl)));
- nvkm_wr32(device, chan->ctrl.runl + 0x088, 2);
-
- nvkm_wr32(device, chan->ctrl.chan, 0x00000002);
- nvkm_wr32(device, chan->ctrl.runl + 0x0090, 0);
- return 0;
-}
-
-static void *
-ga102_chan_dtor(struct nvkm_object *object)
-{
- struct ga102_chan *chan = ga102_chan(object);
-
- if (chan->vmm) {
- nvkm_vmm_part(chan->vmm, chan->inst);
- nvkm_vmm_unref(&chan->vmm);
- }
-
- nvkm_memory_unref(&chan->runl);
- nvkm_memory_unref(&chan->user);
- nvkm_memory_unref(&chan->inst);
- nvkm_memory_unref(&chan->mthd);
- return chan;
-}
-
-static const struct nvkm_object_func
-ga102_chan = {
- .dtor = ga102_chan_dtor,
- .init = ga102_chan_init,
- .fini = ga102_chan_fini,
- .map = ga102_chan_map,
- .sclass = ga102_chan_sclass,
-};
-
-static int
-ga102_chan_new(struct nvkm_device *device,
- const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **pobject)
-{
- struct volta_channel_gpfifo_a_v0 *args = argv;
- struct nvkm_top_device *tdev;
- struct nvkm_vmm *vmm;
- struct ga102_chan *chan;
- int ret;
-
- if (argc != sizeof(*args))
- return -ENOSYS;
-
- vmm = nvkm_uvmm_search(oclass->client, args->vmm);
- if (IS_ERR(vmm))
- return PTR_ERR(vmm);
-
- if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
- return -ENOMEM;
-
- nvkm_object_ctor(&ga102_chan, oclass, &chan->object);
- *pobject = &chan->object;
-
- list_for_each_entry(tdev, &device->top->device, head) {
- if (tdev->type == NVKM_ENGINE_CE) {
- chan->ctrl.runl = tdev->runlist;
- break;
- }
- }
-
- if (!chan->ctrl.runl)
- return -ENODEV;
-
- chan->ctrl.chan = nvkm_rd32(device, chan->ctrl.runl + 0x004) & 0xfffffff0;
-
- args->chid = 0;
- args->inst = 0;
- args->token = nvkm_rd32(device, chan->ctrl.runl + 0x008) & 0xffff0000;
-
- ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, true, &chan->mthd);
- if (ret)
- return ret;
-
- ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, true, &chan->inst);
- if (ret)
- return ret;
-
- nvkm_kmap(chan->inst);
- nvkm_wo32(chan->inst, 0x010, 0x0000face);
- nvkm_wo32(chan->inst, 0x030, 0x7ffff902);
- nvkm_wo32(chan->inst, 0x048, lower_32_bits(args->ioffset));
- nvkm_wo32(chan->inst, 0x04c, upper_32_bits(args->ioffset) |
- (order_base_2(args->ilength / 8) << 16));
- nvkm_wo32(chan->inst, 0x084, 0x20400000);
- nvkm_wo32(chan->inst, 0x094, 0x30000001);
- nvkm_wo32(chan->inst, 0x0ac, 0x00020000);
- nvkm_wo32(chan->inst, 0x0e4, 0x00000000);
- nvkm_wo32(chan->inst, 0x0e8, 0);
- nvkm_wo32(chan->inst, 0x0f4, 0x00001000);
- nvkm_wo32(chan->inst, 0x0f8, 0x10003080);
- nvkm_mo32(chan->inst, 0x218, 0x00000000, 0x00000000);
- nvkm_wo32(chan->inst, 0x220, lower_32_bits(nvkm_memory_bar2(chan->mthd)));
- nvkm_wo32(chan->inst, 0x224, upper_32_bits(nvkm_memory_bar2(chan->mthd)));
- nvkm_done(chan->inst);
-
- ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, true, &chan->user);
- if (ret)
- return ret;
-
- ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000, true, &chan->runl);
- if (ret)
- return ret;
-
- nvkm_kmap(chan->runl);
- nvkm_wo32(chan->runl, 0x00, 0x80030001);
- nvkm_wo32(chan->runl, 0x04, 1);
- nvkm_wo32(chan->runl, 0x08, 0);
- nvkm_wo32(chan->runl, 0x0c, 0x00000000);
- nvkm_wo32(chan->runl, 0x10, lower_32_bits(nvkm_memory_addr(chan->user)));
- nvkm_wo32(chan->runl, 0x14, upper_32_bits(nvkm_memory_addr(chan->user)));
- nvkm_wo32(chan->runl, 0x18, lower_32_bits(nvkm_memory_addr(chan->inst)));
- nvkm_wo32(chan->runl, 0x1c, upper_32_bits(nvkm_memory_addr(chan->inst)));
- nvkm_done(chan->runl);
-
- ret = nvkm_vmm_join(vmm, chan->inst);
- if (ret)
- return ret;
-
- chan->vmm = nvkm_vmm_ref(vmm);
- return 0;
-}
-
-static const struct nvkm_device_oclass
-ga102_chan_oclass = {
- .ctor = ga102_chan_new,
-};
-
-static int
-ga102_user_new(struct nvkm_device *device,
- const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **pobject)
-{
- return tu102_fifo_user_new(oclass, argv, argc, pobject);
-}
-
-static const struct nvkm_device_oclass
-ga102_user_oclass = {
- .ctor = ga102_user_new,
-};
-
-static int
-ga102_fifo_sclass(struct nvkm_oclass *oclass, int index, const struct nvkm_device_oclass **class)
-{
- if (index == 0) {
- oclass->base = (struct nvkm_sclass) { -1, -1, VOLTA_USERMODE_A };
- *class = &ga102_user_oclass;
- return 0;
- } else
- if (index == 1) {
- oclass->base = (struct nvkm_sclass) { 0, 0, AMPERE_CHANNEL_GPFIFO_B };
- *class = &ga102_chan_oclass;
- return 0;
- }
-
- return 2;
-}
-
-static int
-ga102_fifo_info(struct nvkm_engine *engine, u64 mthd, u64 *data)
-{
- switch (mthd) {
- case NV_DEVICE_HOST_CHANNELS: *data = 1; return 0;
- default:
- break;
- }
-
- return -ENOSYS;
-}
-
-static void *
-ga102_fifo_dtor(struct nvkm_engine *engine)
-{
- return ga102_fifo(engine);
-}
-
-static const struct nvkm_engine_func
+static const struct nvkm_fifo_func
ga102_fifo = {
- .dtor = ga102_fifo_dtor,
- .info = ga102_fifo_info,
- .base.sclass = ga102_fifo_sclass,
+ .runl_ctor = ga100_fifo_runl_ctor,
+ .mmu_fault = &tu102_fifo_mmu_fault,
+ .nonstall_ctor = ga100_fifo_nonstall_ctor,
+ .nonstall = &ga100_fifo_nonstall,
+ .runl = &ga100_runl,
+ .runq = &ga100_runq,
+ .engn = &ga100_engn,
+ .engn_ce = &ga100_engn_ce,
+ .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &ga100_cgrp, .force = true },
+ .chan = {{ 0, 0, AMPERE_CHANNEL_GPFIFO_B }, &ga100_chan },
};
int
ga102_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
- struct ga102_fifo *fifo;
-
- if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
- return -ENOMEM;
-
- nvkm_engine_ctor(&ga102_fifo, device, type, inst, true, &fifo->base.engine);
- *pfifo = &fifo->base;
- return 0;
+ return nvkm_fifo_new_(&ga102_fifo, device, type, inst, pfifo);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
index 8b4f36b3e34b..5bb65258c36d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c
@@ -21,186 +21,456 @@
*
* Authors: Ben Skeggs
*/
-#include "gf100.h"
-#include "changf100.h"
+#include "priv.h"
+#include "cgrp.h"
+#include "chan.h"
+#include "chid.h"
+#include "runl.h"
+#include "runq.h"
-#include <core/client.h>
-#include <core/enum.h>
#include <core/gpuobj.h>
#include <subdev/bar.h>
#include <subdev/fault.h>
+#include <subdev/mc.h>
+#include <subdev/mmu.h>
#include <engine/sw.h>
#include <nvif/class.h>
+void
+gf100_chan_preempt(struct nvkm_chan *chan)
+{
+ nvkm_wr32(chan->cgrp->runl->fifo->engine.subdev.device, 0x002634, chan->id);
+}
+
static void
-gf100_fifo_uevent_init(struct nvkm_fifo *fifo)
+gf100_chan_stop(struct nvkm_chan *chan)
{
- struct nvkm_device *device = fifo->engine.subdev.device;
- nvkm_mask(device, 0x002140, 0x80000000, 0x80000000);
+ struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
+
+ nvkm_mask(device, 0x003004 + (chan->id * 8), 0x00000001, 0x00000000);
}
static void
-gf100_fifo_uevent_fini(struct nvkm_fifo *fifo)
+gf100_chan_start(struct nvkm_chan *chan)
{
+ struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
+
+ nvkm_wr32(device, 0x003004 + (chan->id * 8), 0x001f0001);
+}
+
+static void gf100_fifo_intr_engine(struct nvkm_fifo *);
+
+static void
+gf100_chan_unbind(struct nvkm_chan *chan)
+{
+ struct nvkm_fifo *fifo = chan->cgrp->runl->fifo;
struct nvkm_device *device = fifo->engine.subdev.device;
- nvkm_mask(device, 0x002140, 0x80000000, 0x00000000);
+
+ /*TODO: Is this cargo-culted, or necessary? RM does *something* here... Why? */
+ gf100_fifo_intr_engine(fifo);
+
+ nvkm_wr32(device, 0x003000 + (chan->id * 8), 0x00000000);
}
+static void
+gf100_chan_bind(struct nvkm_chan *chan)
+{
+ struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
+
+ nvkm_wr32(device, 0x003000 + (chan->id * 8), 0xc0000000 | chan->inst->addr >> 12);
+}
+
+static int
+gf100_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv)
+{
+ const u64 userd = nvkm_memory_addr(chan->userd.mem) + chan->userd.base;
+ const u32 limit2 = ilog2(length / 8);
+
+ nvkm_kmap(chan->inst);
+ nvkm_wo32(chan->inst, 0x08, lower_32_bits(userd));
+ nvkm_wo32(chan->inst, 0x0c, upper_32_bits(userd));
+ nvkm_wo32(chan->inst, 0x10, 0x0000face);
+ nvkm_wo32(chan->inst, 0x30, 0xfffff902);
+ nvkm_wo32(chan->inst, 0x48, lower_32_bits(offset));
+ nvkm_wo32(chan->inst, 0x4c, upper_32_bits(offset) | (limit2 << 16));
+ nvkm_wo32(chan->inst, 0x54, 0x00000002);
+ nvkm_wo32(chan->inst, 0x84, 0x20400000);
+ nvkm_wo32(chan->inst, 0x94, 0x30000000 | devm);
+ nvkm_wo32(chan->inst, 0x9c, 0x00000100);
+ nvkm_wo32(chan->inst, 0xa4, 0x1f1f1f1f);
+ nvkm_wo32(chan->inst, 0xa8, 0x1f1f1f1f);
+ nvkm_wo32(chan->inst, 0xac, 0x0000001f);
+ nvkm_wo32(chan->inst, 0xb8, 0xf8000000);
+ nvkm_wo32(chan->inst, 0xf8, 0x10003080); /* 0x002310 */
+ nvkm_wo32(chan->inst, 0xfc, 0x10000010); /* 0x002350 */
+ nvkm_done(chan->inst);
+ return 0;
+}
+
+static const struct nvkm_chan_func_ramfc
+gf100_chan_ramfc = {
+ .write = gf100_chan_ramfc_write,
+ .devm = 0xfff,
+};
+
void
-gf100_fifo_runlist_commit(struct gf100_fifo *fifo)
+gf100_chan_userd_clear(struct nvkm_chan *chan)
{
- struct gf100_fifo_chan *chan;
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- struct nvkm_memory *cur;
- int nr = 0;
- int target;
+ nvkm_kmap(chan->userd.mem);
+ nvkm_wo32(chan->userd.mem, chan->userd.base + 0x040, 0x00000000);
+ nvkm_wo32(chan->userd.mem, chan->userd.base + 0x044, 0x00000000);
+ nvkm_wo32(chan->userd.mem, chan->userd.base + 0x048, 0x00000000);
+ nvkm_wo32(chan->userd.mem, chan->userd.base + 0x04c, 0x00000000);
+ nvkm_wo32(chan->userd.mem, chan->userd.base + 0x050, 0x00000000);
+ nvkm_wo32(chan->userd.mem, chan->userd.base + 0x058, 0x00000000);
+ nvkm_wo32(chan->userd.mem, chan->userd.base + 0x05c, 0x00000000);
+ nvkm_wo32(chan->userd.mem, chan->userd.base + 0x060, 0x00000000);
+ nvkm_wo32(chan->userd.mem, chan->userd.base + 0x088, 0x00000000);
+ nvkm_wo32(chan->userd.mem, chan->userd.base + 0x08c, 0x00000000);
+ nvkm_done(chan->userd.mem);
+}
- mutex_lock(&fifo->base.mutex);
- cur = fifo->runlist.mem[fifo->runlist.active];
- fifo->runlist.active = !fifo->runlist.active;
+static const struct nvkm_chan_func_userd
+gf100_chan_userd = {
+ .bar = 1,
+ .size = 0x1000,
+ .clear = gf100_chan_userd_clear,
+};
- nvkm_kmap(cur);
- list_for_each_entry(chan, &fifo->chan, head) {
- nvkm_wo32(cur, (nr * 8) + 0, chan->base.chid);
- nvkm_wo32(cur, (nr * 8) + 4, 0x00000004);
- nr++;
- }
- nvkm_done(cur);
+const struct nvkm_chan_func_inst
+gf100_chan_inst = {
+ .size = 0x1000,
+ .zero = true,
+ .vmm = true,
+};
- switch (nvkm_memory_target(cur)) {
- case NVKM_MEM_TARGET_VRAM: target = 0; break;
- case NVKM_MEM_TARGET_NCOH: target = 3; break;
+static const struct nvkm_chan_func
+gf100_chan = {
+ .inst = &gf100_chan_inst,
+ .userd = &gf100_chan_userd,
+ .ramfc = &gf100_chan_ramfc,
+ .bind = gf100_chan_bind,
+ .unbind = gf100_chan_unbind,
+ .start = gf100_chan_start,
+ .stop = gf100_chan_stop,
+ .preempt = gf100_chan_preempt,
+};
+
+static void
+gf100_ectx_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan *chan)
+{
+ u64 addr = 0ULL;
+ u32 ptr0;
+
+ switch (engn->engine->subdev.type) {
+ case NVKM_ENGINE_SW : return;
+ case NVKM_ENGINE_GR : ptr0 = 0x0210; break;
+ case NVKM_ENGINE_CE : ptr0 = 0x0230 + (engn->engine->subdev.inst * 0x10); break;
+ case NVKM_ENGINE_MSPDEC: ptr0 = 0x0250; break;
+ case NVKM_ENGINE_MSPPP : ptr0 = 0x0260; break;
+ case NVKM_ENGINE_MSVLD : ptr0 = 0x0270; break;
default:
- mutex_unlock(&fifo->base.mutex);
WARN_ON(1);
return;
}
- nvkm_wr32(device, 0x002270, (nvkm_memory_addr(cur) >> 12) |
- (target << 28));
- nvkm_wr32(device, 0x002274, 0x01f00000 | nr);
+ if (cctx) {
+ addr = cctx->vctx->vma->addr;
+ addr |= 4ULL;
+ }
- if (wait_event_timeout(fifo->runlist.wait,
- !(nvkm_rd32(device, 0x00227c) & 0x00100000),
- msecs_to_jiffies(2000)) == 0)
- nvkm_error(subdev, "runlist update timeout\n");
- mutex_unlock(&fifo->base.mutex);
+ nvkm_kmap(chan->inst);
+ nvkm_wo32(chan->inst, ptr0 + 0, lower_32_bits(addr));
+ nvkm_wo32(chan->inst, ptr0 + 4, upper_32_bits(addr));
+ nvkm_done(chan->inst);
}
-void
-gf100_fifo_runlist_remove(struct gf100_fifo *fifo, struct gf100_fifo_chan *chan)
+static int
+gf100_ectx_ctor(struct nvkm_engn *engn, struct nvkm_vctx *vctx)
+{
+ int ret;
+
+ ret = nvkm_vmm_get(vctx->vmm, 12, vctx->inst->size, &vctx->vma);
+ if (ret)
+ return ret;
+
+ return nvkm_memory_map(vctx->inst, 0, vctx->vmm, vctx->vma, NULL, 0);
+}
+
+bool
+gf100_engn_mmu_fault_triggered(struct nvkm_engn *engn)
{
- mutex_lock(&fifo->base.mutex);
- list_del_init(&chan->head);
- mutex_unlock(&fifo->base.mutex);
+ struct nvkm_runl *runl = engn->runl;
+ struct nvkm_fifo *fifo = runl->fifo;
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ u32 data = nvkm_rd32(device, 0x002a30 + (engn->id * 4));
+
+ ENGN_DEBUG(engn, "%08x: mmu fault triggered", data);
+ if (!(data & 0x00000100))
+ return false;
+
+ spin_lock(&fifo->lock);
+ nvkm_mask(device, 0x002a30 + (engn->id * 4), 0x00000100, 0x00000000);
+ if (atomic_dec_and_test(&runl->rc_triggered))
+ nvkm_mask(device, 0x002140, 0x00000100, 0x00000100);
+ spin_unlock(&fifo->lock);
+ return true;
}
void
-gf100_fifo_runlist_insert(struct gf100_fifo *fifo, struct gf100_fifo_chan *chan)
+gf100_engn_mmu_fault_trigger(struct nvkm_engn *engn)
{
- mutex_lock(&fifo->base.mutex);
- list_add_tail(&chan->head, &fifo->chan);
- mutex_unlock(&fifo->base.mutex);
+ struct nvkm_runl *runl = engn->runl;
+ struct nvkm_fifo *fifo = runl->fifo;
+ struct nvkm_device *device = fifo->engine.subdev.device;
+
+ ENGN_DEBUG(engn, "triggering mmu fault on 0x%02x", engn->fault);
+ spin_lock(&fifo->lock);
+ if (atomic_inc_return(&runl->rc_triggered) == 1)
+ nvkm_mask(device, 0x002140, 0x00000100, 0x00000000);
+ nvkm_wr32(device, 0x002100, 0x00000100);
+ nvkm_wr32(device, 0x002a30 + (engn->id * 4), 0x00000100 | engn->fault);
+ spin_unlock(&fifo->lock);
}
-static struct nvkm_engine *
-gf100_fifo_id_engine(struct nvkm_fifo *fifo, int engi)
+/*TODO: clean all this up. */
+struct gf100_engn_status {
+ bool busy;
+ bool save;
+ bool unk0;
+ bool unk1;
+ u8 chid;
+};
+
+static void
+gf100_engn_status(struct nvkm_engn *engn, struct gf100_engn_status *status)
{
- enum nvkm_subdev_type type;
- int inst;
+ u32 stat = nvkm_rd32(engn->engine->subdev.device, 0x002640 + (engn->id * 4));
- switch (engi) {
- case GF100_FIFO_ENGN_GR : type = NVKM_ENGINE_GR ; inst = 0; break;
- case GF100_FIFO_ENGN_MSPDEC: type = NVKM_ENGINE_MSPDEC; inst = 0; break;
- case GF100_FIFO_ENGN_MSPPP : type = NVKM_ENGINE_MSPPP ; inst = 0; break;
- case GF100_FIFO_ENGN_MSVLD : type = NVKM_ENGINE_MSVLD ; inst = 0; break;
- case GF100_FIFO_ENGN_CE0 : type = NVKM_ENGINE_CE ; inst = 0; break;
- case GF100_FIFO_ENGN_CE1 : type = NVKM_ENGINE_CE ; inst = 1; break;
- case GF100_FIFO_ENGN_SW : type = NVKM_ENGINE_SW ; inst = 0; break;
- default:
- WARN_ON(1);
- return NULL;
- }
+ status->busy = (stat & 0x10000000);
+ status->save = (stat & 0x00100000);
+ status->unk0 = (stat & 0x00004000);
+ status->unk1 = (stat & 0x00001000);
+ status->chid = (stat & 0x0000007f);
- return nvkm_device_engine(fifo->engine.subdev.device, type, inst);
+ ENGN_DEBUG(engn, "%08x: busy %d save %d unk0 %d unk1 %d chid %d",
+ stat, status->busy, status->save, status->unk0, status->unk1, status->chid);
}
static int
-gf100_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine)
-{
- switch (engine->subdev.type) {
- case NVKM_ENGINE_GR : return GF100_FIFO_ENGN_GR;
- case NVKM_ENGINE_MSPDEC: return GF100_FIFO_ENGN_MSPDEC;
- case NVKM_ENGINE_MSPPP : return GF100_FIFO_ENGN_MSPPP;
- case NVKM_ENGINE_MSVLD : return GF100_FIFO_ENGN_MSVLD;
- case NVKM_ENGINE_CE : return GF100_FIFO_ENGN_CE0 + engine->subdev.inst;
- case NVKM_ENGINE_SW : return GF100_FIFO_ENGN_SW;
- default:
- WARN_ON(1);
- return -1;
+gf100_engn_cxid(struct nvkm_engn *engn, bool *cgid)
+{
+ struct gf100_engn_status status;
+
+ gf100_engn_status(engn, &status);
+ if (status.busy) {
+ *cgid = false;
+ return status.chid;
}
+
+ return -ENODEV;
}
-static void
-gf100_fifo_recover_work(struct work_struct *w)
+static bool
+gf100_engn_chsw(struct nvkm_engn *engn)
{
- struct gf100_fifo *fifo = container_of(w, typeof(*fifo), recover.work);
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- struct nvkm_engine *engine;
- unsigned long flags;
- u32 engm, engn, todo;
+ struct gf100_engn_status status;
+
+ gf100_engn_status(engn, &status);
+ if (status.busy && (status.unk0 || status.unk1))
+ return true;
- spin_lock_irqsave(&fifo->base.lock, flags);
- engm = fifo->recover.mask;
- fifo->recover.mask = 0ULL;
- spin_unlock_irqrestore(&fifo->base.lock, flags);
+ return false;
+}
- nvkm_mask(device, 0x002630, engm, engm);
+static const struct nvkm_engn_func
+gf100_engn = {
+ .chsw = gf100_engn_chsw,
+ .cxid = gf100_engn_cxid,
+ .mmu_fault_trigger = gf100_engn_mmu_fault_trigger,
+ .mmu_fault_triggered = gf100_engn_mmu_fault_triggered,
+ .ctor = gf100_ectx_ctor,
+ .bind = gf100_ectx_bind,
+};
- for (todo = engm; engn = __ffs(todo), todo; todo &= ~BIT_ULL(engn)) {
- if ((engine = gf100_fifo_id_engine(&fifo->base, engn))) {
- nvkm_subdev_fini(&engine->subdev, false);
- WARN_ON(nvkm_subdev_init(&engine->subdev));
+const struct nvkm_engn_func
+gf100_engn_sw = {
+};
+
+static const struct nvkm_bitfield
+gf100_runq_intr_0_names[] = {
+/* { 0x00008000, "" } seen with null ib push */
+ { 0x00200000, "ILLEGAL_MTHD" },
+ { 0x00800000, "EMPTY_SUBC" },
+ {}
+};
+
+bool
+gf100_runq_intr(struct nvkm_runq *runq, struct nvkm_runl *null)
+{
+ struct nvkm_subdev *subdev = &runq->fifo->engine.subdev;
+ struct nvkm_device *device = subdev->device;
+ u32 mask = nvkm_rd32(device, 0x04010c + (runq->id * 0x2000));
+ u32 stat = nvkm_rd32(device, 0x040108 + (runq->id * 0x2000)) & mask;
+ u32 addr = nvkm_rd32(device, 0x0400c0 + (runq->id * 0x2000));
+ u32 data = nvkm_rd32(device, 0x0400c4 + (runq->id * 0x2000));
+ u32 chid = nvkm_rd32(device, 0x040120 + (runq->id * 0x2000)) & runq->fifo->chid->mask;
+ u32 subc = (addr & 0x00070000) >> 16;
+ u32 mthd = (addr & 0x00003ffc);
+ u32 show = stat;
+ struct nvkm_chan *chan;
+ unsigned long flags;
+ char msg[128];
+
+ if (stat & 0x00800000) {
+ if (device->sw) {
+ if (nvkm_sw_mthd(device->sw, chid, subc, mthd, data))
+ show &= ~0x00800000;
}
}
- gf100_fifo_runlist_commit(fifo);
- nvkm_wr32(device, 0x00262c, engm);
- nvkm_mask(device, 0x002630, engm, 0x00000000);
+ if (show) {
+ nvkm_snprintbf(msg, sizeof(msg), runq->func->intr_0_names, show);
+ chan = nvkm_chan_get_chid(&runq->fifo->engine, chid, &flags);
+ nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%010llx %s] "
+ "subc %d mthd %04x data %08x\n",
+ runq->id, show, msg, chid, chan ? chan->inst->addr : 0,
+ chan ? chan->name : "unknown", subc, mthd, data);
+
+ /*TODO: use proper procedure for clearing each exception / debug output */
+ if ((stat & 0xc67fe000) && chan)
+ nvkm_chan_error(chan, true);
+ nvkm_chan_put(&chan, flags);
+ }
+
+ nvkm_wr32(device, 0x0400c0 + (runq->id * 0x2000), 0x80600008);
+ nvkm_wr32(device, 0x040108 + (runq->id * 0x2000), stat);
+ return true;
+}
+
+void
+gf100_runq_init(struct nvkm_runq *runq)
+{
+ struct nvkm_device *device = runq->fifo->engine.subdev.device;
+
+ nvkm_mask(device, 0x04013c + (runq->id * 0x2000), 0x10000100, 0x00000000);
+ nvkm_wr32(device, 0x040108 + (runq->id * 0x2000), 0xffffffff); /* INTR */
+ nvkm_wr32(device, 0x04010c + (runq->id * 0x2000), 0xfffffeff); /* INTREN */
+}
+
+static const struct nvkm_runq_func
+gf100_runq = {
+ .init = gf100_runq_init,
+ .intr = gf100_runq_intr,
+ .intr_0_names = gf100_runq_intr_0_names,
+};
+
+bool
+gf100_runl_preempt_pending(struct nvkm_runl *runl)
+{
+ return nvkm_rd32(runl->fifo->engine.subdev.device, 0x002634) & 0x00100000;
}
static void
-gf100_fifo_recover(struct gf100_fifo *fifo, struct nvkm_engine *engine,
- struct gf100_fifo_chan *chan)
+gf100_runl_fault_clear(struct nvkm_runl *runl)
{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- u32 chid = chan->base.chid;
- int engi = gf100_fifo_engine_id(&fifo->base, engine);
+ nvkm_mask(runl->fifo->engine.subdev.device, 0x00262c, 0x00000000, 0x00000000);
+}
+
+static void
+gf100_runl_allow(struct nvkm_runl *runl, u32 engm)
+{
+ nvkm_mask(runl->fifo->engine.subdev.device, 0x002630, engm, 0x00000000);
+}
+
+static void
+gf100_runl_block(struct nvkm_runl *runl, u32 engm)
+{
+ nvkm_mask(runl->fifo->engine.subdev.device, 0x002630, engm, engm);
+}
+
+static bool
+gf100_runl_pending(struct nvkm_runl *runl)
+{
+ return nvkm_rd32(runl->fifo->engine.subdev.device, 0x00227c) & 0x00100000;
+}
+
+static void
+gf100_runl_commit(struct nvkm_runl *runl, struct nvkm_memory *memory, u32 start, int count)
+{
+ struct nvkm_device *device = runl->fifo->engine.subdev.device;
+ u64 addr = nvkm_memory_addr(memory) + start;
+ int target;
+
+ switch (nvkm_memory_target(memory)) {
+ case NVKM_MEM_TARGET_VRAM: target = 0; break;
+ case NVKM_MEM_TARGET_NCOH: target = 3; break;
+ default:
+ WARN_ON(1);
+ return;
+ }
+
+ nvkm_wr32(device, 0x002270, (target << 28) | (addr >> 12));
+ nvkm_wr32(device, 0x002274, 0x01f00000 | count);
+}
+
+static void
+gf100_runl_insert_chan(struct nvkm_chan *chan, struct nvkm_memory *memory, u64 offset)
+{
+ nvkm_wo32(memory, offset + 0, chan->id);
+ nvkm_wo32(memory, offset + 4, 0x00000004);
+}
- nvkm_error(subdev, "%s engine fault on channel %d, recovering...\n",
- engine->subdev.name, chid);
- assert_spin_locked(&fifo->base.lock);
+static const struct nvkm_runl_func
+gf100_runl = {
+ .size = 8,
+ .update = nv50_runl_update,
+ .insert_chan = gf100_runl_insert_chan,
+ .commit = gf100_runl_commit,
+ .wait = nv50_runl_wait,
+ .pending = gf100_runl_pending,
+ .block = gf100_runl_block,
+ .allow = gf100_runl_allow,
+ .fault_clear = gf100_runl_fault_clear,
+ .preempt_pending = gf100_runl_preempt_pending,
+};
- nvkm_mask(device, 0x003004 + (chid * 0x08), 0x00000001, 0x00000000);
- list_del_init(&chan->head);
- chan->killed = true;
+static void
+gf100_fifo_nonstall_allow(struct nvkm_event *event, int type, int index)
+{
+ struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event);
+ unsigned long flags;
- if (engi >= 0 && engi != GF100_FIFO_ENGN_SW)
- fifo->recover.mask |= BIT(engi);
- schedule_work(&fifo->recover.work);
- nvkm_fifo_kevent(&fifo->base, chid);
+ spin_lock_irqsave(&fifo->lock, flags);
+ nvkm_mask(fifo->engine.subdev.device, 0x002140, 0x80000000, 0x80000000);
+ spin_unlock_irqrestore(&fifo->lock, flags);
}
+void
+gf100_fifo_nonstall_block(struct nvkm_event *event, int type, int index)
+{
+ struct nvkm_fifo *fifo = container_of(event, typeof(*fifo), nonstall.event);
+ unsigned long flags;
+
+ spin_lock_irqsave(&fifo->lock, flags);
+ nvkm_mask(fifo->engine.subdev.device, 0x002140, 0x80000000, 0x00000000);
+ spin_unlock_irqrestore(&fifo->lock, flags);
+}
+
+const struct nvkm_event_func
+gf100_fifo_nonstall = {
+ .init = gf100_fifo_nonstall_allow,
+ .fini = gf100_fifo_nonstall_block,
+};
+
static const struct nvkm_enum
-gf100_fifo_fault_engine[] = {
+gf100_fifo_mmu_fault_engine[] = {
{ 0x00, "PGRAPH", NULL, NVKM_ENGINE_GR },
{ 0x03, "PEEPHOLE", NULL, NVKM_ENGINE_IFB },
{ 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
{ 0x05, "BAR3", NULL, NVKM_SUBDEV_INSTMEM },
- { 0x07, "PFIFO", NULL, NVKM_ENGINE_FIFO },
+ { 0x07, "PFIFO" },
{ 0x10, "PMSVLD", NULL, NVKM_ENGINE_MSVLD },
{ 0x11, "PMSPPP", NULL, NVKM_ENGINE_MSPPP },
{ 0x13, "PCOUNTER" },
@@ -212,7 +482,7 @@ gf100_fifo_fault_engine[] = {
};
static const struct nvkm_enum
-gf100_fifo_fault_reason[] = {
+gf100_fifo_mmu_fault_reason[] = {
{ 0x00, "PT_NOT_PRESENT" },
{ 0x01, "PT_TOO_SHORT" },
{ 0x02, "PAGE_NOT_PRESENT" },
@@ -226,7 +496,7 @@ gf100_fifo_fault_reason[] = {
};
static const struct nvkm_enum
-gf100_fifo_fault_hubclient[] = {
+gf100_fifo_mmu_fault_hubclient[] = {
{ 0x01, "PCOPY0" },
{ 0x02, "PCOPY1" },
{ 0x04, "DISPATCH" },
@@ -245,7 +515,7 @@ gf100_fifo_fault_hubclient[] = {
};
static const struct nvkm_enum
-gf100_fifo_fault_gpcclient[] = {
+gf100_fifo_mmu_fault_gpcclient[] = {
{ 0x01, "TEX" },
{ 0x0c, "ESETUP" },
{ 0x0e, "CTXCTL" },
@@ -253,29 +523,55 @@ gf100_fifo_fault_gpcclient[] = {
{}
};
-static void
-gf100_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info)
+const struct nvkm_enum
+gf100_fifo_mmu_fault_access[] = {
+ { 0x00, "READ" },
+ { 0x01, "WRITE" },
+ {}
+};
+
+void
+gf100_fifo_mmu_fault_recover(struct nvkm_fifo *fifo, struct nvkm_fault_data *info)
{
- struct gf100_fifo *fifo = gf100_fifo(base);
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
+ struct nvkm_subdev *subdev = &fifo->engine.subdev;
struct nvkm_device *device = subdev->device;
- const struct nvkm_enum *er, *eu, *ec;
+ const struct nvkm_enum *er, *ee, *ec, *ea;
struct nvkm_engine *engine = NULL;
- struct nvkm_fifo_chan *chan;
+ struct nvkm_runl *runl;
+ struct nvkm_engn *engn;
+ struct nvkm_chan *chan;
unsigned long flags;
- char gpcid[8] = "";
+ char ct[8] = "HUB/";
+
+ /* Lookup engine by MMU fault ID. */
+ nvkm_runl_foreach(runl, fifo) {
+ engn = nvkm_runl_find_engn(engn, runl, engn->fault == info->engine);
+ if (engn) {
+ /* Fault triggered by CTXSW_TIMEOUT recovery procedure. */
+ if (engn->func->mmu_fault_triggered &&
+ engn->func->mmu_fault_triggered(engn)) {
+ nvkm_runl_rc_engn(runl, engn);
+ return;
+ }
+
+ engine = engn->engine;
+ break;
+ }
+ }
- er = nvkm_enum_find(gf100_fifo_fault_reason, info->reason);
- eu = nvkm_enum_find(gf100_fifo_fault_engine, info->engine);
+ er = nvkm_enum_find(fifo->func->mmu_fault->reason, info->reason);
+ ee = nvkm_enum_find(fifo->func->mmu_fault->engine, info->engine);
if (info->hub) {
- ec = nvkm_enum_find(gf100_fifo_fault_hubclient, info->client);
+ ec = nvkm_enum_find(fifo->func->mmu_fault->hubclient, info->client);
} else {
- ec = nvkm_enum_find(gf100_fifo_fault_gpcclient, info->client);
- snprintf(gpcid, sizeof(gpcid), "GPC%d/", info->gpc);
+ ec = nvkm_enum_find(fifo->func->mmu_fault->gpcclient, info->client);
+ snprintf(ct, sizeof(ct), "GPC%d/", info->gpc);
}
+ ea = nvkm_enum_find(fifo->func->mmu_fault->access, info->access);
- if (eu && eu->data2) {
- switch (eu->data2) {
+ /* Handle BAR faults. */
+ if (ee && ee->data2) {
+ switch (ee->data2) {
case NVKM_SUBDEV_BAR:
nvkm_bar_bar1_reset(device);
break;
@@ -286,77 +582,104 @@ gf100_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info)
nvkm_mask(device, 0x001718, 0x00000000, 0x00000000);
break;
default:
- engine = nvkm_device_engine(device, eu->data2, eu->inst);
break;
}
}
- chan = nvkm_fifo_chan_inst(&fifo->base, info->inst, &flags);
+ chan = nvkm_chan_get_inst(&fifo->engine, info->inst, &flags);
nvkm_error(subdev,
- "%s fault at %010llx engine %02x [%s] client %02x [%s%s] "
- "reason %02x [%s] on channel %d [%010llx %s]\n",
- info->access ? "write" : "read", info->addr,
- info->engine, eu ? eu->name : "",
- info->client, gpcid, ec ? ec->name : "",
- info->reason, er ? er->name : "", chan ? chan->chid : -1,
- info->inst, chan ? chan->object.client->name : "unknown");
-
- if (engine && chan)
- gf100_fifo_recover(fifo, engine, (void *)chan);
- nvkm_fifo_chan_put(&fifo->base, flags, &chan);
+ "fault %02x [%s] at %016llx engine %02x [%s] client %02x "
+ "[%s%s] reason %02x [%s] on channel %d [%010llx %s]\n",
+ info->access, ea ? ea->name : "", info->addr,
+ info->engine, ee ? ee->name : engine ? engine->subdev.name : "",
+ info->client, ct, ec ? ec->name : "",
+ info->reason, er ? er->name : "",
+ chan ? chan->id : -1, info->inst, chan ? chan->name : "unknown");
+
+ /* Handle host/engine faults. */
+ if (chan)
+ nvkm_runl_rc_cgrp(chan->cgrp);
+
+ nvkm_chan_put(&chan, flags);
}
-static const struct nvkm_enum
-gf100_fifo_sched_reason[] = {
- { 0x0a, "CTXSW_TIMEOUT" },
- {}
+static const struct nvkm_fifo_func_mmu_fault
+gf100_fifo_mmu_fault = {
+ .recover = gf100_fifo_mmu_fault_recover,
+ .access = gf100_fifo_mmu_fault_access,
+ .engine = gf100_fifo_mmu_fault_engine,
+ .reason = gf100_fifo_mmu_fault_reason,
+ .hubclient = gf100_fifo_mmu_fault_hubclient,
+ .gpcclient = gf100_fifo_mmu_fault_gpcclient,
};
-static void
-gf100_fifo_intr_sched_ctxsw(struct gf100_fifo *fifo)
+void
+gf100_fifo_intr_ctxsw_timeout(struct nvkm_fifo *fifo, u32 engm)
{
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- struct nvkm_engine *engine;
- struct gf100_fifo_chan *chan;
- unsigned long flags;
- u32 engn;
-
- spin_lock_irqsave(&fifo->base.lock, flags);
- for (engn = 0; engn < 6; engn++) {
- u32 stat = nvkm_rd32(device, 0x002640 + (engn * 0x04));
- u32 busy = (stat & 0x80000000);
- u32 save = (stat & 0x00100000); /* maybe? */
- u32 unk0 = (stat & 0x00040000);
- u32 unk1 = (stat & 0x00001000);
- u32 chid = (stat & 0x0000007f);
- (void)save;
-
- if (busy && unk0 && unk1) {
- list_for_each_entry(chan, &fifo->chan, head) {
- if (chan->base.chid == chid) {
- engine = gf100_fifo_id_engine(&fifo->base, engn);
- if (!engine)
- break;
- gf100_fifo_recover(fifo, engine, chan);
- break;
+ struct nvkm_runl *runl;
+ struct nvkm_engn *engn, *engn2;
+ bool cgid, cgid2;
+ int id, id2;
+
+ nvkm_runl_foreach(runl, fifo) {
+ /* Stop the runlist, and go through all engines serving it. */
+ nvkm_runl_block(runl);
+ nvkm_runl_foreach_engn_cond(engn, runl, engm & BIT(engn->id)) {
+ /* Determine what channel (group) the engine is on. */
+ id = engn->func->cxid(engn, &cgid);
+ if (id >= 0) {
+ /* Trigger MMU fault on any engine(s) on that channel (group). */
+ nvkm_runl_foreach_engn_cond(engn2, runl, engn2->func->cxid) {
+ id2 = engn2->func->cxid(engn2, &cgid2);
+ if (cgid2 == cgid && id2 == id)
+ engn2->func->mmu_fault_trigger(engn2);
}
}
}
+ nvkm_runl_allow(runl); /* HW will keep runlist blocked via ERROR_SCHED_DISABLE. */
}
- spin_unlock_irqrestore(&fifo->base.lock, flags);
}
static void
-gf100_fifo_intr_sched(struct gf100_fifo *fifo)
+gf100_fifo_intr_sched_ctxsw(struct nvkm_fifo *fifo)
{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
+ struct nvkm_runl *runl;
+ struct nvkm_engn *engn;
+ u32 engm = 0;
+
+ /* Look for any engines that are busy, and awaiting chsw ack. */
+ nvkm_runl_foreach(runl, fifo) {
+ nvkm_runl_foreach_engn_cond(engn, runl, engn->func->chsw) {
+ if (WARN_ON(engn->fault < 0) || !engn->func->chsw(engn))
+ continue;
+
+ engm |= BIT(engn->id);
+ }
+ }
+
+ if (!engm)
+ return;
+
+ fifo->func->intr_ctxsw_timeout(fifo, engm);
+}
+
+static const struct nvkm_enum
+gf100_fifo_intr_sched_names[] = {
+ { 0x0a, "CTXSW_TIMEOUT" },
+ {}
+};
+
+void
+gf100_fifo_intr_sched(struct nvkm_fifo *fifo)
+{
+ struct nvkm_subdev *subdev = &fifo->engine.subdev;
struct nvkm_device *device = subdev->device;
u32 intr = nvkm_rd32(device, 0x00254c);
u32 code = intr & 0x000000ff;
const struct nvkm_enum *en;
- en = nvkm_enum_find(gf100_fifo_sched_reason, code);
+ en = nvkm_enum_find(gf100_fifo_intr_sched_names, code);
nvkm_error(subdev, "SCHED_ERROR %02x [%s]\n", code, en ? en->name : "");
@@ -370,7 +693,7 @@ gf100_fifo_intr_sched(struct gf100_fifo *fifo)
}
void
-gf100_fifo_intr_fault(struct nvkm_fifo *fifo, int unit)
+gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *fifo, int unit)
{
struct nvkm_device *device = fifo->engine.subdev.device;
u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10));
@@ -393,61 +716,45 @@ gf100_fifo_intr_fault(struct nvkm_fifo *fifo, int unit)
nvkm_fifo_fault(fifo, &info);
}
-static const struct nvkm_bitfield
-gf100_fifo_pbdma_intr[] = {
-/* { 0x00008000, "" } seen with null ib push */
- { 0x00200000, "ILLEGAL_MTHD" },
- { 0x00800000, "EMPTY_SUBC" },
- {}
-};
-
-static void
-gf100_fifo_intr_pbdma(struct gf100_fifo *fifo, int unit)
+void
+gf100_fifo_intr_mmu_fault(struct nvkm_fifo *fifo)
{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- u32 stat = nvkm_rd32(device, 0x040108 + (unit * 0x2000));
- u32 addr = nvkm_rd32(device, 0x0400c0 + (unit * 0x2000));
- u32 data = nvkm_rd32(device, 0x0400c4 + (unit * 0x2000));
- u32 chid = nvkm_rd32(device, 0x040120 + (unit * 0x2000)) & 0x7f;
- u32 subc = (addr & 0x00070000) >> 16;
- u32 mthd = (addr & 0x00003ffc);
- struct nvkm_fifo_chan *chan;
- unsigned long flags;
- u32 show= stat;
- char msg[128];
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ unsigned long mask = nvkm_rd32(device, 0x00259c);
+ int unit;
- if (stat & 0x00800000) {
- if (device->sw) {
- if (nvkm_sw_mthd(device->sw, chid, subc, mthd, data))
- show &= ~0x00800000;
- }
+ for_each_set_bit(unit, &mask, 32) {
+ fifo->func->intr_mmu_fault_unit(fifo, unit);
+ nvkm_wr32(device, 0x00259c, BIT(unit));
}
+}
- if (show) {
- nvkm_snprintbf(msg, sizeof(msg), gf100_fifo_pbdma_intr, show);
- chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags);
- nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%010llx %s] "
- "subc %d mthd %04x data %08x\n",
- unit, show, msg, chid, chan ? chan->inst->addr : 0,
- chan ? chan->object.client->name : "unknown",
- subc, mthd, data);
- nvkm_fifo_chan_put(&fifo->base, flags, &chan);
+bool
+gf100_fifo_intr_pbdma(struct nvkm_fifo *fifo)
+{
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ struct nvkm_runq *runq;
+ u32 mask = nvkm_rd32(device, 0x0025a0);
+ bool handled = false;
+
+ nvkm_runq_foreach_cond(runq, fifo, mask & BIT(runq->id)) {
+ if (runq->func->intr(runq, NULL))
+ handled = true;
+
+ nvkm_wr32(device, 0x0025a0, BIT(runq->id));
}
- nvkm_wr32(device, 0x0400c0 + (unit * 0x2000), 0x80600008);
- nvkm_wr32(device, 0x040108 + (unit * 0x2000), stat);
+ return handled;
}
static void
-gf100_fifo_intr_runlist(struct gf100_fifo *fifo)
+gf100_fifo_intr_runlist(struct nvkm_fifo *fifo)
{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
+ struct nvkm_subdev *subdev = &fifo->engine.subdev;
struct nvkm_device *device = subdev->device;
u32 intr = nvkm_rd32(device, 0x002a00);
if (intr & 0x10000000) {
- wake_up(&fifo->runlist.wait);
nvkm_wr32(device, 0x002a00, 0x10000000);
intr &= ~0x10000000;
}
@@ -459,9 +766,9 @@ gf100_fifo_intr_runlist(struct gf100_fifo *fifo)
}
static void
-gf100_fifo_intr_engine_unit(struct gf100_fifo *fifo, int engn)
+gf100_fifo_intr_engine_unit(struct nvkm_fifo *fifo, int engn)
{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
+ struct nvkm_subdev *subdev = &fifo->engine.subdev;
struct nvkm_device *device = subdev->device;
u32 intr = nvkm_rd32(device, 0x0025a8 + (engn * 0x04));
u32 inte = nvkm_rd32(device, 0x002628);
@@ -472,22 +779,22 @@ gf100_fifo_intr_engine_unit(struct gf100_fifo *fifo, int engn)
for (unkn = 0; unkn < 8; unkn++) {
u32 ints = (intr >> (unkn * 0x04)) & inte;
if (ints & 0x1) {
- nvkm_fifo_uevent(&fifo->base);
+ nvkm_event_ntfy(&fifo->nonstall.event, 0, NVKM_FIFO_NONSTALL_EVENT);
ints &= ~1;
}
if (ints) {
- nvkm_error(subdev, "ENGINE %d %d %01x",
- engn, unkn, ints);
+ nvkm_error(subdev, "ENGINE %d %d %01x", engn, unkn, ints);
nvkm_mask(device, 0x002628, ints, 0);
}
}
}
-void
-gf100_fifo_intr_engine(struct gf100_fifo *fifo)
+static void
+gf100_fifo_intr_engine(struct nvkm_fifo *fifo)
{
- struct nvkm_device *device = fifo->base.engine.subdev.device;
+ struct nvkm_device *device = fifo->engine.subdev.device;
u32 mask = nvkm_rd32(device, 0x0025a4);
+
while (mask) {
u32 unit = __ffs(mask);
gf100_fifo_intr_engine_unit(fifo, unit);
@@ -495,11 +802,11 @@ gf100_fifo_intr_engine(struct gf100_fifo *fifo)
}
}
-static void
-gf100_fifo_intr(struct nvkm_fifo *base)
+static irqreturn_t
+gf100_fifo_intr(struct nvkm_inth *inth)
{
- struct gf100_fifo *fifo = gf100_fifo(base);
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
+ struct nvkm_fifo *fifo = container_of(inth, typeof(*fifo), engine.subdev.inth);
+ struct nvkm_subdev *subdev = &fifo->engine.subdev;
struct nvkm_device *device = subdev->device;
u32 mask = nvkm_rd32(device, 0x002140);
u32 stat = nvkm_rd32(device, 0x002100) & mask;
@@ -532,25 +839,13 @@ gf100_fifo_intr(struct nvkm_fifo *base)
}
if (stat & 0x10000000) {
- u32 mask = nvkm_rd32(device, 0x00259c);
- while (mask) {
- u32 unit = __ffs(mask);
- gf100_fifo_intr_fault(&fifo->base, unit);
- nvkm_wr32(device, 0x00259c, (1 << unit));
- mask &= ~(1 << unit);
- }
+ gf100_fifo_intr_mmu_fault(fifo);
stat &= ~0x10000000;
}
if (stat & 0x20000000) {
- u32 mask = nvkm_rd32(device, 0x0025a0);
- while (mask) {
- u32 unit = __ffs(mask);
- gf100_fifo_intr_pbdma(fifo, unit);
- nvkm_wr32(device, 0x0025a0, (1 << unit));
- mask &= ~(1 << unit);
- }
- stat &= ~0x20000000;
+ if (gf100_fifo_intr_pbdma(fifo))
+ stat &= ~0x20000000;
}
if (stat & 0x40000000) {
@@ -565,71 +860,26 @@ gf100_fifo_intr(struct nvkm_fifo *base)
if (stat) {
nvkm_error(subdev, "INTR %08x\n", stat);
+ spin_lock(&fifo->lock);
nvkm_mask(device, 0x002140, stat, 0x00000000);
+ spin_unlock(&fifo->lock);
nvkm_wr32(device, 0x002100, stat);
}
-}
-
-static int
-gf100_fifo_oneinit(struct nvkm_fifo *base)
-{
- struct gf100_fifo *fifo = gf100_fifo(base);
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- struct nvkm_vmm *bar = nvkm_bar_bar1_vmm(device);
- int ret;
-
- /* Determine number of PBDMAs by checking valid enable bits. */
- nvkm_wr32(device, 0x002204, 0xffffffff);
- fifo->pbdma_nr = hweight32(nvkm_rd32(device, 0x002204));
- nvkm_debug(subdev, "%d PBDMA(s)\n", fifo->pbdma_nr);
-
-
- ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000,
- false, &fifo->runlist.mem[0]);
- if (ret)
- return ret;
-
- ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x1000,
- false, &fifo->runlist.mem[1]);
- if (ret)
- return ret;
- init_waitqueue_head(&fifo->runlist.wait);
-
- ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 0x1000,
- 0x1000, false, &fifo->user.mem);
- if (ret)
- return ret;
-
- ret = nvkm_vmm_get(bar, 12, nvkm_memory_size(fifo->user.mem),
- &fifo->user.bar);
- if (ret)
- return ret;
-
- return nvkm_memory_map(fifo->user.mem, 0, bar, fifo->user.bar, NULL, 0);
-}
-
-static void
-gf100_fifo_fini(struct nvkm_fifo *base)
-{
- struct gf100_fifo *fifo = gf100_fifo(base);
- flush_work(&fifo->recover.work);
+ return IRQ_HANDLED;
}
static void
-gf100_fifo_init(struct nvkm_fifo *base)
+gf100_fifo_init_pbdmas(struct nvkm_fifo *fifo, u32 mask)
{
- struct gf100_fifo *fifo = gf100_fifo(base);
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- int i;
+ struct nvkm_device *device = fifo->engine.subdev.device;
/* Enable PBDMAs. */
- nvkm_wr32(device, 0x000204, (1 << fifo->pbdma_nr) - 1);
- nvkm_wr32(device, 0x002204, (1 << fifo->pbdma_nr) - 1);
+ nvkm_wr32(device, 0x000204, mask);
+ nvkm_wr32(device, 0x002204, mask);
/* Assign engines to PBDMAs. */
- if (fifo->pbdma_nr >= 3) {
+ if ((mask & 7) == 7) {
nvkm_wr32(device, 0x002208, ~(1 << 0)); /* PGRAPH */
nvkm_wr32(device, 0x00220c, ~(1 << 1)); /* PVP */
nvkm_wr32(device, 0x002210, ~(1 << 1)); /* PMSPP */
@@ -638,62 +888,82 @@ gf100_fifo_init(struct nvkm_fifo *base)
nvkm_wr32(device, 0x00221c, ~(1 << 1)); /* PCE1 */
}
- /* PBDMA[n] */
- for (i = 0; i < fifo->pbdma_nr; i++) {
- nvkm_mask(device, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000);
- nvkm_wr32(device, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */
- nvkm_wr32(device, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */
- }
+ nvkm_mask(device, 0x002a04, 0xbfffffff, 0xbfffffff);
+}
+
+static void
+gf100_fifo_init(struct nvkm_fifo *fifo)
+{
+ struct nvkm_device *device = fifo->engine.subdev.device;
nvkm_mask(device, 0x002200, 0x00000001, 0x00000001);
- nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar->addr >> 12);
+ nvkm_wr32(device, 0x002254, 0x10000000 | fifo->userd.bar1->addr >> 12);
nvkm_wr32(device, 0x002100, 0xffffffff);
nvkm_wr32(device, 0x002140, 0x7fffffff);
nvkm_wr32(device, 0x002628, 0x00000001); /* ENGINE_INTR_EN */
}
-static void *
-gf100_fifo_dtor(struct nvkm_fifo *base)
+static int
+gf100_fifo_runl_ctor(struct nvkm_fifo *fifo)
+{
+ struct nvkm_runl *runl;
+
+ runl = nvkm_runl_new(fifo, 0, 0, 0);
+ if (IS_ERR(runl))
+ return PTR_ERR(runl);
+
+ nvkm_runl_add(runl, 0, fifo->func->engn, NVKM_ENGINE_GR, 0);
+ nvkm_runl_add(runl, 1, fifo->func->engn, NVKM_ENGINE_MSPDEC, 0);
+ nvkm_runl_add(runl, 2, fifo->func->engn, NVKM_ENGINE_MSPPP, 0);
+ nvkm_runl_add(runl, 3, fifo->func->engn, NVKM_ENGINE_MSVLD, 0);
+ nvkm_runl_add(runl, 4, fifo->func->engn, NVKM_ENGINE_CE, 0);
+ nvkm_runl_add(runl, 5, fifo->func->engn, NVKM_ENGINE_CE, 1);
+ nvkm_runl_add(runl, 15, &gf100_engn_sw, NVKM_ENGINE_SW, 0);
+ return 0;
+}
+
+int
+gf100_fifo_runq_nr(struct nvkm_fifo *fifo)
+{
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ u32 save;
+
+ /* Determine number of PBDMAs by checking valid enable bits. */
+ save = nvkm_mask(device, 0x000204, 0xffffffff, 0xffffffff);
+ save = nvkm_mask(device, 0x000204, 0xffffffff, save);
+ return hweight32(save);
+}
+
+int
+gf100_fifo_chid_ctor(struct nvkm_fifo *fifo, int nr)
{
- struct gf100_fifo *fifo = gf100_fifo(base);
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- nvkm_vmm_put(nvkm_bar_bar1_vmm(device), &fifo->user.bar);
- nvkm_memory_unref(&fifo->user.mem);
- nvkm_memory_unref(&fifo->runlist.mem[0]);
- nvkm_memory_unref(&fifo->runlist.mem[1]);
- return fifo;
+ return nvkm_chid_new(&nvkm_chan_event, &fifo->engine.subdev, nr, 0, nr, &fifo->chid);
}
static const struct nvkm_fifo_func
gf100_fifo = {
- .dtor = gf100_fifo_dtor,
- .oneinit = gf100_fifo_oneinit,
+ .chid_nr = nv50_fifo_chid_nr,
+ .chid_ctor = gf100_fifo_chid_ctor,
+ .runq_nr = gf100_fifo_runq_nr,
+ .runl_ctor = gf100_fifo_runl_ctor,
.init = gf100_fifo_init,
- .fini = gf100_fifo_fini,
+ .init_pbdmas = gf100_fifo_init_pbdmas,
.intr = gf100_fifo_intr,
- .fault = gf100_fifo_fault,
- .engine_id = gf100_fifo_engine_id,
- .id_engine = gf100_fifo_id_engine,
- .uevent_init = gf100_fifo_uevent_init,
- .uevent_fini = gf100_fifo_uevent_fini,
- .chan = {
- &gf100_fifo_gpfifo_oclass,
- NULL
- },
+ .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit,
+ .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout,
+ .mmu_fault = &gf100_fifo_mmu_fault,
+ .nonstall = &gf100_fifo_nonstall,
+ .runl = &gf100_runl,
+ .runq = &gf100_runq,
+ .engn = &gf100_engn,
+ .cgrp = {{ }, &nv04_cgrp },
+ .chan = {{ 0, 0, FERMI_CHANNEL_GPFIFO }, &gf100_chan },
};
int
gf100_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
- struct gf100_fifo *fifo;
-
- if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
- return -ENOMEM;
- INIT_LIST_HEAD(&fifo->chan);
- INIT_WORK(&fifo->recover.work, gf100_fifo_recover_work);
- *pfifo = &fifo->base;
-
- return nvkm_fifo_ctor(&gf100_fifo, device, type, inst, 128, &fifo->base);
+ return nvkm_fifo_new_(&gf100_fifo, device, type, inst, pfifo);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h
deleted file mode 100644
index b8642490eb2f..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-#ifndef __GF100_FIFO_H__
-#define __GF100_FIFO_H__
-#define gf100_fifo(p) container_of((p), struct gf100_fifo, base)
-#include "priv.h"
-
-#include <subdev/mmu.h>
-
-struct gf100_fifo_chan;
-struct gf100_fifo {
- struct nvkm_fifo base;
-
- struct list_head chan;
-
- struct {
- struct work_struct work;
- u64 mask;
- } recover;
-
- int pbdma_nr;
-
- struct {
- struct nvkm_memory *mem[2];
- int active;
- wait_queue_head_t wait;
- } runlist;
-
- struct {
- struct nvkm_memory *mem;
- struct nvkm_vma *bar;
- } user;
-};
-
-void gf100_fifo_intr_engine(struct gf100_fifo *);
-void gf100_fifo_runlist_insert(struct gf100_fifo *, struct gf100_fifo_chan *);
-void gf100_fifo_runlist_remove(struct gf100_fifo *, struct gf100_fifo_chan *);
-void gf100_fifo_runlist_commit(struct gf100_fifo *);
-#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
index e771bd519ee2..d8a4d773a58c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c
@@ -21,643 +21,318 @@
*
* Authors: Ben Skeggs
*/
-#include "gk104.h"
+#include "priv.h"
#include "cgrp.h"
-#include "changk104.h"
+#include "chan.h"
+#include "chid.h"
+#include "runl.h"
+#include "runq.h"
-#include <core/client.h>
#include <core/gpuobj.h>
-#include <subdev/bar.h>
-#include <subdev/fault.h>
-#include <subdev/timer.h>
+#include <subdev/mc.h>
+#include <subdev/mmu.h>
#include <subdev/top.h>
-#include <engine/sw.h>
#include <nvif/class.h>
-#include <nvif/cl0080.h>
+#include <nvif/if900d.h>
void
-gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn,
- struct gk104_fifo_engine_status *status)
+gk104_chan_stop(struct nvkm_chan *chan)
{
- struct nvkm_engine *engine = fifo->engine[engn].engine;
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- u32 stat = nvkm_rd32(device, 0x002640 + (engn * 0x08));
-
- status->busy = !!(stat & 0x80000000);
- status->faulted = !!(stat & 0x40000000);
- status->next.tsg = !!(stat & 0x10000000);
- status->next.id = (stat & 0x0fff0000) >> 16;
- status->chsw = !!(stat & 0x00008000);
- status->save = !!(stat & 0x00004000);
- status->load = !!(stat & 0x00002000);
- status->prev.tsg = !!(stat & 0x00001000);
- status->prev.id = (stat & 0x00000fff);
- status->chan = NULL;
-
- if (status->busy && status->chsw) {
- if (status->load && status->save) {
- if (engine && nvkm_engine_chsw_load(engine))
- status->chan = &status->next;
- else
- status->chan = &status->prev;
- } else
- if (status->load) {
- status->chan = &status->next;
- } else {
- status->chan = &status->prev;
- }
- } else
- if (status->load) {
- status->chan = &status->prev;
- }
+ struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
- nvkm_debug(subdev, "engine %02d: busy %d faulted %d chsw %d "
- "save %d load %d %sid %d%s-> %sid %d%s\n",
- engn, status->busy, status->faulted,
- status->chsw, status->save, status->load,
- status->prev.tsg ? "tsg" : "ch", status->prev.id,
- status->chan == &status->prev ? "*" : " ",
- status->next.tsg ? "tsg" : "ch", status->next.id,
- status->chan == &status->next ? "*" : " ");
-}
-
-int
-gk104_fifo_class_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
- void *argv, u32 argc, struct nvkm_object **pobject)
-{
- struct gk104_fifo *fifo = gk104_fifo(base);
- if (oclass->engn == &fifo->func->chan) {
- const struct gk104_fifo_chan_user *user = oclass->engn;
- return user->ctor(fifo, oclass, argv, argc, pobject);
- } else
- if (oclass->engn == &fifo->func->user) {
- const struct gk104_fifo_user_user *user = oclass->engn;
- return user->ctor(oclass, argv, argc, pobject);
- }
- WARN_ON(1);
- return -EINVAL;
-}
-
-int
-gk104_fifo_class_get(struct nvkm_fifo *base, int index,
- struct nvkm_oclass *oclass)
-{
- struct gk104_fifo *fifo = gk104_fifo(base);
- int c = 0;
-
- if (fifo->func->user.ctor && c++ == index) {
- oclass->base = fifo->func->user.user;
- oclass->engn = &fifo->func->user;
- return 0;
- }
-
- if (fifo->func->chan.ctor && c++ == index) {
- oclass->base = fifo->func->chan.user;
- oclass->engn = &fifo->func->chan;
- return 0;
- }
-
- return c;
+ nvkm_mask(device, 0x800004 + (chan->id * 8), 0x00000800, 0x00000800);
}
void
-gk104_fifo_uevent_fini(struct nvkm_fifo *fifo)
+gk104_chan_start(struct nvkm_chan *chan)
{
- struct nvkm_device *device = fifo->engine.subdev.device;
- nvkm_mask(device, 0x002140, 0x80000000, 0x00000000);
-}
+ struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
-void
-gk104_fifo_uevent_init(struct nvkm_fifo *fifo)
-{
- struct nvkm_device *device = fifo->engine.subdev.device;
- nvkm_mask(device, 0x002140, 0x80000000, 0x80000000);
+ nvkm_mask(device, 0x800004 + (chan->id * 8), 0x00000400, 0x00000400);
}
void
-gk104_fifo_runlist_commit(struct gk104_fifo *fifo, int runl,
- struct nvkm_memory *mem, int nr)
+gk104_chan_unbind(struct nvkm_chan *chan)
{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- int target;
+ struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
- switch (nvkm_memory_target(mem)) {
- case NVKM_MEM_TARGET_VRAM: target = 0; break;
- case NVKM_MEM_TARGET_NCOH: target = 3; break;
- default:
- WARN_ON(1);
- return;
- }
-
- nvkm_wr32(device, 0x002270, (nvkm_memory_addr(mem) >> 12) |
- (target << 28));
- nvkm_wr32(device, 0x002274, (runl << 20) | nr);
-
- if (nvkm_msec(device, 2000,
- if (!(nvkm_rd32(device, 0x002284 + (runl * 0x08)) & 0x00100000))
- break;
- ) < 0)
- nvkm_error(subdev, "runlist %d update timeout\n", runl);
+ nvkm_wr32(device, 0x800000 + (chan->id * 8), 0x00000000);
}
void
-gk104_fifo_runlist_update(struct gk104_fifo *fifo, int runl)
+gk104_chan_bind_inst(struct nvkm_chan *chan)
{
- const struct gk104_fifo_runlist_func *func = fifo->func->runlist;
- struct gk104_fifo_chan *chan;
- struct nvkm_memory *mem;
- struct nvkm_fifo_cgrp *cgrp;
- int nr = 0;
-
- mutex_lock(&fifo->base.mutex);
- mem = fifo->runlist[runl].mem[fifo->runlist[runl].next];
- fifo->runlist[runl].next = !fifo->runlist[runl].next;
-
- nvkm_kmap(mem);
- list_for_each_entry(chan, &fifo->runlist[runl].chan, head) {
- func->chan(chan, mem, nr++ * func->size);
- }
-
- list_for_each_entry(cgrp, &fifo->runlist[runl].cgrp, head) {
- func->cgrp(cgrp, mem, nr++ * func->size);
- list_for_each_entry(chan, &cgrp->chan, head) {
- func->chan(chan, mem, nr++ * func->size);
- }
- }
- nvkm_done(mem);
+ struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
- func->commit(fifo, runl, mem, nr);
- mutex_unlock(&fifo->base.mutex);
+ nvkm_wr32(device, 0x800000 + (chan->id * 8), 0x80000000 | chan->inst->addr >> 12);
}
void
-gk104_fifo_runlist_remove(struct gk104_fifo *fifo, struct gk104_fifo_chan *chan)
-{
- struct nvkm_fifo_cgrp *cgrp = chan->cgrp;
- mutex_lock(&fifo->base.mutex);
- if (!list_empty(&chan->head)) {
- list_del_init(&chan->head);
- if (cgrp && !--cgrp->chan_nr)
- list_del_init(&cgrp->head);
- }
- mutex_unlock(&fifo->base.mutex);
-}
-
-void
-gk104_fifo_runlist_insert(struct gk104_fifo *fifo, struct gk104_fifo_chan *chan)
-{
- struct nvkm_fifo_cgrp *cgrp = chan->cgrp;
- mutex_lock(&fifo->base.mutex);
- if (cgrp) {
- if (!cgrp->chan_nr++)
- list_add_tail(&cgrp->head, &fifo->runlist[chan->runl].cgrp);
- list_add_tail(&chan->head, &cgrp->chan);
- } else {
- list_add_tail(&chan->head, &fifo->runlist[chan->runl].chan);
- }
- mutex_unlock(&fifo->base.mutex);
-}
-
-void
-gk104_fifo_runlist_chan(struct gk104_fifo_chan *chan,
- struct nvkm_memory *memory, u32 offset)
-{
- nvkm_wo32(memory, offset + 0, chan->base.chid);
- nvkm_wo32(memory, offset + 4, 0x00000000);
-}
-
-const struct gk104_fifo_runlist_func
-gk104_fifo_runlist = {
- .size = 8,
- .chan = gk104_fifo_runlist_chan,
- .commit = gk104_fifo_runlist_commit,
+gk104_chan_bind(struct nvkm_chan *chan)
+{
+ struct nvkm_runl *runl = chan->cgrp->runl;
+ struct nvkm_device *device = runl->fifo->engine.subdev.device;
+
+ nvkm_mask(device, 0x800004 + (chan->id * 8), 0x000f0000, runl->id << 16);
+ gk104_chan_bind_inst(chan);
+}
+
+static int
+gk104_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv)
+{
+ const u64 userd = nvkm_memory_addr(chan->userd.mem) + chan->userd.base;
+ const u32 limit2 = ilog2(length / 8);
+
+ nvkm_kmap(chan->inst);
+ nvkm_wo32(chan->inst, 0x08, lower_32_bits(userd));
+ nvkm_wo32(chan->inst, 0x0c, upper_32_bits(userd));
+ nvkm_wo32(chan->inst, 0x10, 0x0000face);
+ nvkm_wo32(chan->inst, 0x30, 0xfffff902);
+ nvkm_wo32(chan->inst, 0x48, lower_32_bits(offset));
+ nvkm_wo32(chan->inst, 0x4c, upper_32_bits(offset) | (limit2 << 16));
+ nvkm_wo32(chan->inst, 0x84, 0x20400000);
+ nvkm_wo32(chan->inst, 0x94, 0x30000000 | devm);
+ nvkm_wo32(chan->inst, 0x9c, 0x00000100);
+ nvkm_wo32(chan->inst, 0xac, 0x0000001f);
+ nvkm_wo32(chan->inst, 0xe4, priv ? 0x00000020 : 0x00000000);
+ nvkm_wo32(chan->inst, 0xe8, chan->id);
+ nvkm_wo32(chan->inst, 0xb8, 0xf8000000);
+ nvkm_wo32(chan->inst, 0xf8, 0x10003080); /* 0x002310 */
+ nvkm_wo32(chan->inst, 0xfc, 0x10000010); /* 0x002350 */
+ nvkm_done(chan->inst);
+ return 0;
+}
+
+const struct nvkm_chan_func_ramfc
+gk104_chan_ramfc = {
+ .write = gk104_chan_ramfc_write,
+ .devm = 0xfff,
+ .priv = true,
};
-void
-gk104_fifo_pbdma_init(struct gk104_fifo *fifo)
-{
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- nvkm_wr32(device, 0x000204, (1 << fifo->pbdma_nr) - 1);
-}
-
-int
-gk104_fifo_pbdma_nr(struct gk104_fifo *fifo)
-{
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- /* Determine number of PBDMAs by checking valid enable bits. */
- nvkm_wr32(device, 0x000204, 0xffffffff);
- return hweight32(nvkm_rd32(device, 0x000204));
-}
-
-const struct gk104_fifo_pbdma_func
-gk104_fifo_pbdma = {
- .nr = gk104_fifo_pbdma_nr,
- .init = gk104_fifo_pbdma_init,
+const struct nvkm_chan_func_userd
+gk104_chan_userd = {
+ .bar = 1,
+ .size = 0x200,
+ .clear = gf100_chan_userd_clear,
};
-struct nvkm_engine *
-gk104_fifo_id_engine(struct nvkm_fifo *base, int engi)
-{
- if (engi == GK104_FIFO_ENGN_SW)
- return nvkm_device_engine(base->engine.subdev.device, NVKM_ENGINE_SW, 0);
-
- return gk104_fifo(base)->engine[engi].engine;
-}
-
-int
-gk104_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine)
-{
- struct gk104_fifo *fifo = gk104_fifo(base);
- int engn;
+static const struct nvkm_chan_func
+gk104_chan = {
+ .inst = &gf100_chan_inst,
+ .userd = &gk104_chan_userd,
+ .ramfc = &gk104_chan_ramfc,
+ .bind = gk104_chan_bind,
+ .unbind = gk104_chan_unbind,
+ .start = gk104_chan_start,
+ .stop = gk104_chan_stop,
+ .preempt = gf100_chan_preempt,
+};
- if (engine->subdev.type == NVKM_ENGINE_SW)
- return GK104_FIFO_ENGN_SW;
+static void
+gk104_ectx_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan *chan)
+{
+ u32 ptr0, ptr1 = 0;
+ u64 addr = 0ULL;
+
+ switch (engn->engine->subdev.type) {
+ case NVKM_ENGINE_SW : return;
+ case NVKM_ENGINE_GR : ptr0 = 0x0210; break;
+ case NVKM_ENGINE_SEC : ptr0 = 0x0220; break;
+ case NVKM_ENGINE_MSPDEC: ptr0 = 0x0250; break;
+ case NVKM_ENGINE_MSPPP : ptr0 = 0x0260; break;
+ case NVKM_ENGINE_MSVLD : ptr0 = 0x0270; break;
+ case NVKM_ENGINE_VIC : ptr0 = 0x0280; break;
+ case NVKM_ENGINE_MSENC : ptr0 = 0x0290; break;
+ case NVKM_ENGINE_NVDEC :
+ ptr1 = 0x0270;
+ ptr0 = 0x0210;
+ break;
+ case NVKM_ENGINE_NVENC :
+ if (!engn->engine->subdev.inst)
+ ptr1 = 0x0290;
+ ptr0 = 0x0210;
+ break;
+ default:
+ WARN_ON(1);
+ return;
+ }
- for (engn = 0; engn < fifo->engine_nr && engine; engn++) {
- if (fifo->engine[engn].engine == engine)
- return engn;
+ if (cctx) {
+ addr = cctx->vctx->vma->addr;
+ addr |= 4ULL;
}
- WARN_ON(1);
- return -1;
+ nvkm_kmap(chan->inst);
+ nvkm_wo32(chan->inst, ptr0 + 0, lower_32_bits(addr));
+ nvkm_wo32(chan->inst, ptr0 + 4, upper_32_bits(addr));
+ if (ptr1) {
+ nvkm_wo32(chan->inst, ptr1 + 0, lower_32_bits(addr));
+ nvkm_wo32(chan->inst, ptr1 + 4, upper_32_bits(addr));
+ }
+ nvkm_done(chan->inst);
}
-static void
-gk104_fifo_recover_work(struct work_struct *w)
+int
+gk104_ectx_ctor(struct nvkm_engn *engn, struct nvkm_vctx *vctx)
{
- struct gk104_fifo *fifo = container_of(w, typeof(*fifo), recover.work);
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- struct nvkm_engine *engine;
- unsigned long flags;
- u32 engm, runm, todo;
- int engn, runl;
-
- spin_lock_irqsave(&fifo->base.lock, flags);
- runm = fifo->recover.runm;
- engm = fifo->recover.engm;
- fifo->recover.engm = 0;
- fifo->recover.runm = 0;
- spin_unlock_irqrestore(&fifo->base.lock, flags);
-
- nvkm_mask(device, 0x002630, runm, runm);
-
- for (todo = engm; engn = __ffs(todo), todo; todo &= ~BIT(engn)) {
- if ((engine = fifo->engine[engn].engine)) {
- nvkm_subdev_fini(&engine->subdev, false);
- WARN_ON(nvkm_subdev_init(&engine->subdev));
- }
- }
+ struct gf100_vmm_map_v0 args = { .priv = 1 };
+ int ret;
- for (todo = runm; runl = __ffs(todo), todo; todo &= ~BIT(runl))
- gk104_fifo_runlist_update(fifo, runl);
+ ret = nvkm_vmm_get(vctx->vmm, 12, vctx->inst->size, &vctx->vma);
+ if (ret)
+ return ret;
- nvkm_wr32(device, 0x00262c, runm);
- nvkm_mask(device, 0x002630, runm, 0x00000000);
+ return nvkm_memory_map(vctx->inst, 0, vctx->vmm, vctx->vma, &args, sizeof(args));
}
-static void gk104_fifo_recover_engn(struct gk104_fifo *fifo, int engn);
+/*TODO: clean this up */
+struct gk104_engn_status {
+ bool busy;
+ bool faulted;
+ bool chsw;
+ bool save;
+ bool load;
+ struct {
+ bool tsg;
+ u32 id;
+ } prev, next, *chan;
+};
static void
-gk104_fifo_recover_runl(struct gk104_fifo *fifo, int runl)
-{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- const u32 runm = BIT(runl);
-
- assert_spin_locked(&fifo->base.lock);
- if (fifo->recover.runm & runm)
- return;
- fifo->recover.runm |= runm;
-
- /* Block runlist to prevent channel assignment(s) from changing. */
- nvkm_mask(device, 0x002630, runm, runm);
-
- /* Schedule recovery. */
- nvkm_warn(subdev, "runlist %d: scheduled for recovery\n", runl);
- schedule_work(&fifo->recover.work);
-}
-
-static struct gk104_fifo_chan *
-gk104_fifo_recover_chid(struct gk104_fifo *fifo, int runl, int chid)
+gk104_engn_status(struct nvkm_engn *engn, struct gk104_engn_status *status)
{
- struct gk104_fifo_chan *chan;
- struct nvkm_fifo_cgrp *cgrp;
+ u32 stat = nvkm_rd32(engn->runl->fifo->engine.subdev.device, 0x002640 + (engn->id * 0x08));
- list_for_each_entry(chan, &fifo->runlist[runl].chan, head) {
- if (chan->base.chid == chid) {
- list_del_init(&chan->head);
- return chan;
- }
- }
+ status->busy = !!(stat & 0x80000000);
+ status->faulted = !!(stat & 0x40000000);
+ status->next.tsg = !!(stat & 0x10000000);
+ status->next.id = (stat & 0x0fff0000) >> 16;
+ status->chsw = !!(stat & 0x00008000);
+ status->save = !!(stat & 0x00004000);
+ status->load = !!(stat & 0x00002000);
+ status->prev.tsg = !!(stat & 0x00001000);
+ status->prev.id = (stat & 0x00000fff);
+ status->chan = NULL;
- list_for_each_entry(cgrp, &fifo->runlist[runl].cgrp, head) {
- if (cgrp->id == chid) {
- chan = list_first_entry(&cgrp->chan, typeof(*chan), head);
- list_del_init(&chan->head);
- if (!--cgrp->chan_nr)
- list_del_init(&cgrp->head);
- return chan;
+ if (status->busy && status->chsw) {
+ if (status->load && status->save) {
+ if (nvkm_engine_chsw_load(engn->engine))
+ status->chan = &status->next;
+ else
+ status->chan = &status->prev;
+ } else
+ if (status->load) {
+ status->chan = &status->next;
+ } else {
+ status->chan = &status->prev;
}
+ } else
+ if (status->load) {
+ status->chan = &status->prev;
}
- return NULL;
-}
-
-static void
-gk104_fifo_recover_chan(struct nvkm_fifo *base, int chid)
-{
- struct gk104_fifo *fifo = gk104_fifo(base);
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- const u32 stat = nvkm_rd32(device, 0x800004 + (chid * 0x08));
- const u32 runl = (stat & 0x000f0000) >> 16;
- const bool used = (stat & 0x00000001);
- unsigned long engn, engm = fifo->runlist[runl].engm;
- struct gk104_fifo_chan *chan;
-
- assert_spin_locked(&fifo->base.lock);
- if (!used)
- return;
-
- /* Lookup SW state for channel, and mark it as dead. */
- chan = gk104_fifo_recover_chid(fifo, runl, chid);
- if (chan) {
- chan->killed = true;
- nvkm_fifo_kevent(&fifo->base, chid);
- }
-
- /* Disable channel. */
- nvkm_wr32(device, 0x800004 + (chid * 0x08), stat | 0x00000800);
- nvkm_warn(subdev, "channel %d: killed\n", chid);
-
- /* Block channel assignments from changing during recovery. */
- gk104_fifo_recover_runl(fifo, runl);
-
- /* Schedule recovery for any engines the channel is on. */
- for_each_set_bit(engn, &engm, fifo->engine_nr) {
- struct gk104_fifo_engine_status status;
- gk104_fifo_engine_status(fifo, engn, &status);
- if (!status.chan || status.chan->id != chid)
- continue;
- gk104_fifo_recover_engn(fifo, engn);
- }
+ ENGN_DEBUG(engn, "%08x: busy %d faulted %d chsw %d save %d load %d %sid %d%s-> %sid %d%s",
+ stat, status->busy, status->faulted, status->chsw, status->save, status->load,
+ status->prev.tsg ? "tsg" : "ch", status->prev.id,
+ status->chan == &status->prev ? "*" : " ",
+ status->next.tsg ? "tsg" : "ch", status->next.id,
+ status->chan == &status->next ? "*" : " ");
}
-static void
-gk104_fifo_recover_engn(struct gk104_fifo *fifo, int engn)
+int
+gk104_engn_cxid(struct nvkm_engn *engn, bool *cgid)
{
- struct nvkm_engine *engine = fifo->engine[engn].engine;
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- const u32 runl = fifo->engine[engn].runl;
- const u32 engm = BIT(engn);
- struct gk104_fifo_engine_status status;
- int mmui = -1;
-
- assert_spin_locked(&fifo->base.lock);
- if (fifo->recover.engm & engm)
- return;
- fifo->recover.engm |= engm;
-
- /* Block channel assignments from changing during recovery. */
- gk104_fifo_recover_runl(fifo, runl);
+ struct gk104_engn_status status;
- /* Determine which channel (if any) is currently on the engine. */
- gk104_fifo_engine_status(fifo, engn, &status);
+ gk104_engn_status(engn, &status);
if (status.chan) {
- /* The channel is not longer viable, kill it. */
- gk104_fifo_recover_chan(&fifo->base, status.chan->id);
+ *cgid = status.chan->tsg;
+ return status.chan->id;
}
- /* Determine MMU fault ID for the engine, if we're not being
- * called from the fault handler already.
- */
- if (!status.faulted && engine) {
- mmui = nvkm_top_fault_id(device, engine->subdev.type, engine->subdev.inst);
- if (mmui < 0) {
- const struct nvkm_enum *en = fifo->func->fault.engine;
- for (; en && en->name; en++) {
- if (en->data2 == engine->subdev.type &&
- en->inst == engine->subdev.inst) {
- mmui = en->value;
- break;
- }
- }
- }
- WARN_ON(mmui < 0);
- }
-
- /* Trigger a MMU fault for the engine.
- *
- * No good idea why this is needed, but nvgpu does something similar,
- * and it makes recovery from CTXSW_TIMEOUT a lot more reliable.
- */
- if (mmui >= 0) {
- nvkm_wr32(device, 0x002a30 + (engn * 0x04), 0x00000100 | mmui);
-
- /* Wait for fault to trigger. */
- nvkm_msec(device, 2000,
- gk104_fifo_engine_status(fifo, engn, &status);
- if (status.faulted)
- break;
- );
-
- /* Release MMU fault trigger, and ACK the fault. */
- nvkm_wr32(device, 0x002a30 + (engn * 0x04), 0x00000000);
- nvkm_wr32(device, 0x00259c, BIT(mmui));
- nvkm_wr32(device, 0x002100, 0x10000000);
- }
-
- /* Schedule recovery. */
- nvkm_warn(subdev, "engine %d: scheduled for recovery\n", engn);
- schedule_work(&fifo->recover.work);
+ return -ENODEV;
}
-static void
-gk104_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info)
+bool
+gk104_engn_chsw(struct nvkm_engn *engn)
{
- struct gk104_fifo *fifo = gk104_fifo(base);
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- const struct nvkm_enum *er, *ee, *ec, *ea;
- struct nvkm_engine *engine = NULL;
- struct nvkm_fifo_chan *chan;
- unsigned long flags;
- const char *en = "";
- char ct[8] = "HUB/";
-
- er = nvkm_enum_find(fifo->func->fault.reason, info->reason);
- ee = nvkm_enum_find(fifo->func->fault.engine, info->engine);
- if (info->hub) {
- ec = nvkm_enum_find(fifo->func->fault.hubclient, info->client);
- } else {
- ec = nvkm_enum_find(fifo->func->fault.gpcclient, info->client);
- snprintf(ct, sizeof(ct), "GPC%d/", info->gpc);
- }
- ea = nvkm_enum_find(fifo->func->fault.access, info->access);
+ struct gk104_engn_status status;
- if (ee && ee->data2) {
- switch (ee->data2) {
- case NVKM_SUBDEV_BAR:
- nvkm_bar_bar1_reset(device);
- break;
- case NVKM_SUBDEV_INSTMEM:
- nvkm_bar_bar2_reset(device);
- break;
- case NVKM_ENGINE_IFB:
- nvkm_mask(device, 0x001718, 0x00000000, 0x00000000);
- break;
- default:
- engine = nvkm_device_engine(device, ee->data2, 0);
- break;
- }
- }
-
- if (ee == NULL) {
- struct nvkm_subdev *subdev = nvkm_top_fault(device, info->engine);
- if (subdev) {
- if (subdev->func == &nvkm_engine)
- engine = container_of(subdev, typeof(*engine), subdev);
- en = engine->subdev.name;
- }
- } else {
- en = ee->name;
- }
-
- spin_lock_irqsave(&fifo->base.lock, flags);
- chan = nvkm_fifo_chan_inst_locked(&fifo->base, info->inst);
-
- nvkm_error(subdev,
- "fault %02x [%s] at %016llx engine %02x [%s] client %02x "
- "[%s%s] reason %02x [%s] on channel %d [%010llx %s]\n",
- info->access, ea ? ea->name : "", info->addr,
- info->engine, ee ? ee->name : en,
- info->client, ct, ec ? ec->name : "",
- info->reason, er ? er->name : "", chan ? chan->chid : -1,
- info->inst, chan ? chan->object.client->name : "unknown");
-
- /* Kill the channel that caused the fault. */
- if (chan)
- gk104_fifo_recover_chan(&fifo->base, chan->chid);
-
- /* Channel recovery will probably have already done this for the
- * correct engine(s), but just in case we can't find the channel
- * information...
- */
- if (engine) {
- int engn = fifo->base.func->engine_id(&fifo->base, engine);
- if (engn >= 0 && engn != GK104_FIFO_ENGN_SW)
- gk104_fifo_recover_engn(fifo, engn);
- }
+ gk104_engn_status(engn, &status);
+ if (status.busy && status.chsw)
+ return true;
- spin_unlock_irqrestore(&fifo->base.lock, flags);
+ return false;
}
-static const struct nvkm_enum
-gk104_fifo_bind_reason[] = {
- { 0x01, "BIND_NOT_UNBOUND" },
- { 0x02, "SNOOP_WITHOUT_BAR1" },
- { 0x03, "UNBIND_WHILE_RUNNING" },
- { 0x05, "INVALID_RUNLIST" },
- { 0x06, "INVALID_CTX_TGT" },
- { 0x0b, "UNBIND_WHILE_PARKED" },
- {}
+const struct nvkm_engn_func
+gk104_engn = {
+ .chsw = gk104_engn_chsw,
+ .cxid = gk104_engn_cxid,
+ .mmu_fault_trigger = gf100_engn_mmu_fault_trigger,
+ .mmu_fault_triggered = gf100_engn_mmu_fault_triggered,
+ .ctor = gk104_ectx_ctor,
+ .bind = gk104_ectx_bind,
};
-void
-gk104_fifo_intr_bind(struct gk104_fifo *fifo)
+const struct nvkm_engn_func
+gk104_engn_ce = {
+ .chsw = gk104_engn_chsw,
+ .cxid = gk104_engn_cxid,
+ .mmu_fault_trigger = gf100_engn_mmu_fault_trigger,
+ .mmu_fault_triggered = gf100_engn_mmu_fault_triggered,
+};
+
+bool
+gk104_runq_idle(struct nvkm_runq *runq)
{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- u32 intr = nvkm_rd32(device, 0x00252c);
- u32 code = intr & 0x000000ff;
- const struct nvkm_enum *en =
- nvkm_enum_find(gk104_fifo_bind_reason, code);
+ struct nvkm_device *device = runq->fifo->engine.subdev.device;
- nvkm_error(subdev, "BIND_ERROR %02x [%s]\n", code, en ? en->name : "");
+ return !(nvkm_rd32(device, 0x003080 + (runq->id * 4)) & 0x0000e000);
}
-static const struct nvkm_enum
-gk104_fifo_sched_reason[] = {
- { 0x0a, "CTXSW_TIMEOUT" },
+static const struct nvkm_bitfield
+gk104_runq_intr_1_names[] = {
+ { 0x00000001, "HCE_RE_ILLEGAL_OP" },
+ { 0x00000002, "HCE_RE_ALIGNB" },
+ { 0x00000004, "HCE_PRIV" },
+ { 0x00000008, "HCE_ILLEGAL_MTHD" },
+ { 0x00000010, "HCE_ILLEGAL_CLASS" },
{}
};
-static void
-gk104_fifo_intr_sched_ctxsw(struct gk104_fifo *fifo)
+static bool
+gk104_runq_intr_1(struct nvkm_runq *runq)
{
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- unsigned long flags, engm = 0;
- u32 engn;
-
- /* We need to ACK the SCHED_ERROR here, and prevent it reasserting,
- * as MMU_FAULT cannot be triggered while it's pending.
- */
- spin_lock_irqsave(&fifo->base.lock, flags);
- nvkm_mask(device, 0x002140, 0x00000100, 0x00000000);
- nvkm_wr32(device, 0x002100, 0x00000100);
-
- for (engn = 0; engn < fifo->engine_nr; engn++) {
- struct gk104_fifo_engine_status status;
-
- gk104_fifo_engine_status(fifo, engn, &status);
- if (!status.busy || !status.chsw)
- continue;
-
- engm |= BIT(engn);
- }
-
- for_each_set_bit(engn, &engm, fifo->engine_nr)
- gk104_fifo_recover_engn(fifo, engn);
-
- nvkm_mask(device, 0x002140, 0x00000100, 0x00000100);
- spin_unlock_irqrestore(&fifo->base.lock, flags);
-}
-
-static void
-gk104_fifo_intr_sched(struct gk104_fifo *fifo)
-{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
+ struct nvkm_subdev *subdev = &runq->fifo->engine.subdev;
struct nvkm_device *device = subdev->device;
- u32 intr = nvkm_rd32(device, 0x00254c);
- u32 code = intr & 0x000000ff;
- const struct nvkm_enum *en =
- nvkm_enum_find(gk104_fifo_sched_reason, code);
-
- nvkm_error(subdev, "SCHED_ERROR %02x [%s]\n", code, en ? en->name : "");
+ u32 mask = nvkm_rd32(device, 0x04014c + (runq->id * 0x2000));
+ u32 stat = nvkm_rd32(device, 0x040148 + (runq->id * 0x2000)) & mask;
+ u32 chid = nvkm_rd32(device, 0x040120 + (runq->id * 0x2000)) & 0xfff;
+ char msg[128];
- switch (code) {
- case 0x0a:
- gk104_fifo_intr_sched_ctxsw(fifo);
- break;
- default:
- break;
+ if (stat & 0x80000000) {
+ if (runq->func->intr_1_ctxnotvalid &&
+ runq->func->intr_1_ctxnotvalid(runq, chid))
+ stat &= ~0x80000000;
}
-}
-void
-gk104_fifo_intr_chsw(struct gk104_fifo *fifo)
-{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- u32 stat = nvkm_rd32(device, 0x00256c);
- nvkm_error(subdev, "CHSW_ERROR %08x\n", stat);
- nvkm_wr32(device, 0x00256c, stat);
-}
+ if (stat) {
+ nvkm_snprintbf(msg, sizeof(msg), gk104_runq_intr_1_names, stat);
+ nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d %08x %08x\n",
+ runq->id, stat, msg, chid,
+ nvkm_rd32(device, 0x040150 + (runq->id * 0x2000)),
+ nvkm_rd32(device, 0x040154 + (runq->id * 0x2000)));
+ }
-void
-gk104_fifo_intr_dropped_fault(struct gk104_fifo *fifo)
-{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- u32 stat = nvkm_rd32(device, 0x00259c);
- nvkm_error(subdev, "DROPPED_MMU_FAULT %08x\n", stat);
+ nvkm_wr32(device, 0x040148 + (runq->id * 0x2000), stat);
+ return true;
}
-static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = {
+const struct nvkm_bitfield
+gk104_runq_intr_0_names[] = {
{ 0x00000001, "MEMREQ" },
{ 0x00000002, "MEMACK_TIMEOUT" },
{ 0x00000004, "MEMACK_EXTRA" },
@@ -691,430 +366,111 @@ static const struct nvkm_bitfield gk104_fifo_pbdma_intr_0[] = {
{}
};
-void
-gk104_fifo_intr_pbdma_0(struct gk104_fifo *fifo, int unit)
+bool
+gk104_runq_intr(struct nvkm_runq *runq, struct nvkm_runl *null)
{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- u32 mask = nvkm_rd32(device, 0x04010c + (unit * 0x2000));
- u32 stat = nvkm_rd32(device, 0x040108 + (unit * 0x2000)) & mask;
- u32 addr = nvkm_rd32(device, 0x0400c0 + (unit * 0x2000));
- u32 data = nvkm_rd32(device, 0x0400c4 + (unit * 0x2000));
- u32 chid = nvkm_rd32(device, 0x040120 + (unit * 0x2000)) & 0xfff;
- u32 subc = (addr & 0x00070000) >> 16;
- u32 mthd = (addr & 0x00003ffc);
- u32 show = stat;
- struct nvkm_fifo_chan *chan;
- unsigned long flags;
- char msg[128];
-
- if (stat & 0x00800000) {
- if (device->sw) {
- if (nvkm_sw_mthd(device->sw, chid, subc, mthd, data))
- show &= ~0x00800000;
- }
- }
-
- nvkm_wr32(device, 0x0400c0 + (unit * 0x2000), 0x80600008);
-
- if (show) {
- nvkm_snprintbf(msg, sizeof(msg), gk104_fifo_pbdma_intr_0, show);
- chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags);
- nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d [%010llx %s] "
- "subc %d mthd %04x data %08x\n",
- unit, show, msg, chid, chan ? chan->inst->addr : 0,
- chan ? chan->object.client->name : "unknown",
- subc, mthd, data);
- nvkm_fifo_chan_put(&fifo->base, flags, &chan);
- }
+ bool intr0 = gf100_runq_intr(runq, NULL);
+ bool intr1 = gk104_runq_intr_1(runq);
- nvkm_wr32(device, 0x040108 + (unit * 0x2000), stat);
+ return intr0 || intr1;
}
-static const struct nvkm_bitfield gk104_fifo_pbdma_intr_1[] = {
- { 0x00000001, "HCE_RE_ILLEGAL_OP" },
- { 0x00000002, "HCE_RE_ALIGNB" },
- { 0x00000004, "HCE_PRIV" },
- { 0x00000008, "HCE_ILLEGAL_MTHD" },
- { 0x00000010, "HCE_ILLEGAL_CLASS" },
- {}
-};
-
void
-gk104_fifo_intr_pbdma_1(struct gk104_fifo *fifo, int unit)
+gk104_runq_init(struct nvkm_runq *runq)
{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- u32 mask = nvkm_rd32(device, 0x04014c + (unit * 0x2000));
- u32 stat = nvkm_rd32(device, 0x040148 + (unit * 0x2000)) & mask;
- u32 chid = nvkm_rd32(device, 0x040120 + (unit * 0x2000)) & 0xfff;
- char msg[128];
+ struct nvkm_device *device = runq->fifo->engine.subdev.device;
- if (stat) {
- nvkm_snprintbf(msg, sizeof(msg), gk104_fifo_pbdma_intr_1, stat);
- nvkm_error(subdev, "PBDMA%d: %08x [%s] ch %d %08x %08x\n",
- unit, stat, msg, chid,
- nvkm_rd32(device, 0x040150 + (unit * 0x2000)),
- nvkm_rd32(device, 0x040154 + (unit * 0x2000)));
- }
+ gf100_runq_init(runq);
- nvkm_wr32(device, 0x040148 + (unit * 0x2000), stat);
+ nvkm_wr32(device, 0x040148 + (runq->id * 0x2000), 0xffffffff); /* HCE.INTR */
+ nvkm_wr32(device, 0x04014c + (runq->id * 0x2000), 0xffffffff); /* HCE.INTREN */
}
-void
-gk104_fifo_intr_runlist(struct gk104_fifo *fifo)
+static u32
+gk104_runq_runm(struct nvkm_runq *runq)
{
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- u32 mask = nvkm_rd32(device, 0x002a00);
- while (mask) {
- int runl = __ffs(mask);
- wake_up(&fifo->runlist[runl].wait);
- nvkm_wr32(device, 0x002a00, 1 << runl);
- mask &= ~(1 << runl);
- }
+ return nvkm_rd32(runq->fifo->engine.subdev.device, 0x002390 + (runq->id * 0x04));
}
+const struct nvkm_runq_func
+gk104_runq = {
+ .init = gk104_runq_init,
+ .intr = gk104_runq_intr,
+ .intr_0_names = gk104_runq_intr_0_names,
+ .idle = gk104_runq_idle,
+};
+
void
-gk104_fifo_intr_engine(struct gk104_fifo *fifo)
+gk104_runl_fault_clear(struct nvkm_runl *runl)
{
- nvkm_fifo_uevent(&fifo->base);
-}
-
-static void
-gk104_fifo_intr(struct nvkm_fifo *base)
-{
- struct gk104_fifo *fifo = gk104_fifo(base);
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- u32 mask = nvkm_rd32(device, 0x002140);
- u32 stat = nvkm_rd32(device, 0x002100) & mask;
-
- if (stat & 0x00000001) {
- gk104_fifo_intr_bind(fifo);
- nvkm_wr32(device, 0x002100, 0x00000001);
- stat &= ~0x00000001;
- }
-
- if (stat & 0x00000010) {
- nvkm_error(subdev, "PIO_ERROR\n");
- nvkm_wr32(device, 0x002100, 0x00000010);
- stat &= ~0x00000010;
- }
-
- if (stat & 0x00000100) {
- gk104_fifo_intr_sched(fifo);
- nvkm_wr32(device, 0x002100, 0x00000100);
- stat &= ~0x00000100;
- }
-
- if (stat & 0x00010000) {
- gk104_fifo_intr_chsw(fifo);
- nvkm_wr32(device, 0x002100, 0x00010000);
- stat &= ~0x00010000;
- }
-
- if (stat & 0x00800000) {
- nvkm_error(subdev, "FB_FLUSH_TIMEOUT\n");
- nvkm_wr32(device, 0x002100, 0x00800000);
- stat &= ~0x00800000;
- }
-
- if (stat & 0x01000000) {
- nvkm_error(subdev, "LB_ERROR\n");
- nvkm_wr32(device, 0x002100, 0x01000000);
- stat &= ~0x01000000;
- }
-
- if (stat & 0x08000000) {
- gk104_fifo_intr_dropped_fault(fifo);
- nvkm_wr32(device, 0x002100, 0x08000000);
- stat &= ~0x08000000;
- }
-
- if (stat & 0x10000000) {
- u32 mask = nvkm_rd32(device, 0x00259c);
- while (mask) {
- u32 unit = __ffs(mask);
- fifo->func->intr.fault(&fifo->base, unit);
- nvkm_wr32(device, 0x00259c, (1 << unit));
- mask &= ~(1 << unit);
- }
- stat &= ~0x10000000;
- }
-
- if (stat & 0x20000000) {
- u32 mask = nvkm_rd32(device, 0x0025a0);
- while (mask) {
- u32 unit = __ffs(mask);
- gk104_fifo_intr_pbdma_0(fifo, unit);
- gk104_fifo_intr_pbdma_1(fifo, unit);
- nvkm_wr32(device, 0x0025a0, (1 << unit));
- mask &= ~(1 << unit);
- }
- stat &= ~0x20000000;
- }
-
- if (stat & 0x40000000) {
- gk104_fifo_intr_runlist(fifo);
- stat &= ~0x40000000;
- }
-
- if (stat & 0x80000000) {
- nvkm_wr32(device, 0x002100, 0x80000000);
- gk104_fifo_intr_engine(fifo);
- stat &= ~0x80000000;
- }
-
- if (stat) {
- nvkm_error(subdev, "INTR %08x\n", stat);
- nvkm_mask(device, 0x002140, stat, 0x00000000);
- nvkm_wr32(device, 0x002100, stat);
- }
+ nvkm_wr32(runl->fifo->engine.subdev.device, 0x00262c, BIT(runl->id));
}
void
-gk104_fifo_fini(struct nvkm_fifo *base)
+gk104_runl_allow(struct nvkm_runl *runl, u32 engm)
{
- struct gk104_fifo *fifo = gk104_fifo(base);
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- flush_work(&fifo->recover.work);
- /* allow mmu fault interrupts, even when we're not using fifo */
- nvkm_mask(device, 0x002140, 0x10000000, 0x10000000);
+ nvkm_mask(runl->fifo->engine.subdev.device, 0x002630, BIT(runl->id), 0x00000000);
}
-int
-gk104_fifo_info(struct nvkm_fifo *base, u64 mthd, u64 *data)
+void
+gk104_runl_block(struct nvkm_runl *runl, u32 engm)
{
- struct gk104_fifo *fifo = gk104_fifo(base);
- switch (mthd) {
- case NV_DEVICE_HOST_RUNLISTS:
- *data = (1ULL << fifo->runlist_nr) - 1;
- return 0;
- case NV_DEVICE_HOST_RUNLIST_ENGINES: {
- if (*data < fifo->runlist_nr) {
- unsigned long engm = fifo->runlist[*data].engm;
- struct nvkm_engine *engine;
- int engn;
- *data = 0;
- for_each_set_bit(engn, &engm, fifo->engine_nr) {
- if ((engine = fifo->engine[engn].engine)) {
-#define CASE(n) case NVKM_ENGINE_##n: *data |= NV_DEVICE_HOST_RUNLIST_ENGINES_##n; break
- switch (engine->subdev.type) {
- CASE(SW );
- CASE(GR );
- CASE(MPEG );
- CASE(ME );
- CASE(CIPHER);
- CASE(BSP );
- CASE(VP );
- CASE(CE );
- CASE(SEC );
- CASE(MSVLD );
- CASE(MSPDEC);
- CASE(MSPPP );
- CASE(MSENC );
- CASE(VIC );
- CASE(SEC2 );
- CASE(NVDEC );
- CASE(NVENC );
- default:
- WARN_ON(1);
- break;
- }
- }
- }
- return 0;
- }
- }
- return -EINVAL;
- default:
- return -EINVAL;
- }
+ nvkm_mask(runl->fifo->engine.subdev.device, 0x002630, BIT(runl->id), BIT(runl->id));
}
-int
-gk104_fifo_oneinit(struct nvkm_fifo *base)
+bool
+gk104_runl_pending(struct nvkm_runl *runl)
{
- struct gk104_fifo *fifo = gk104_fifo(base);
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- struct nvkm_vmm *bar = nvkm_bar_bar1_vmm(device);
- struct nvkm_top_device *tdev;
- int pbid, ret, i, j;
- u32 *map;
-
- fifo->pbdma_nr = fifo->func->pbdma->nr(fifo);
- nvkm_debug(subdev, "%d PBDMA(s)\n", fifo->pbdma_nr);
-
- /* Read PBDMA->runlist(s) mapping from HW. */
- if (!(map = kcalloc(fifo->pbdma_nr, sizeof(*map), GFP_KERNEL)))
- return -ENOMEM;
+ struct nvkm_device *device = runl->fifo->engine.subdev.device;
- for (i = 0; i < fifo->pbdma_nr; i++)
- map[i] = nvkm_rd32(device, 0x002390 + (i * 0x04));
-
- /* Determine runlist configuration from topology device info. */
- list_for_each_entry(tdev, &device->top->device, head) {
- const int engn = tdev->engine;
- char _en[16], *en;
-
- if (engn < 0)
- continue;
-
- /* Determine which PBDMA handles requests for this engine. */
- for (j = 0, pbid = -1; j < fifo->pbdma_nr; j++) {
- if (map[j] & BIT(tdev->runlist)) {
- pbid = j;
- break;
- }
- }
-
- fifo->engine[engn].engine = nvkm_device_engine(device, tdev->type, tdev->inst);
- if (!fifo->engine[engn].engine) {
- snprintf(_en, sizeof(_en), "%s, %d",
- nvkm_subdev_type[tdev->type], tdev->inst);
- en = _en;
- } else {
- en = fifo->engine[engn].engine->subdev.name;
- }
-
- nvkm_debug(subdev, "engine %2d: runlist %2d pbdma %2d (%s)\n",
- tdev->engine, tdev->runlist, pbid, en);
-
- fifo->engine[engn].runl = tdev->runlist;
- fifo->engine[engn].pbid = pbid;
- fifo->engine_nr = max(fifo->engine_nr, engn + 1);
- fifo->runlist[tdev->runlist].engm |= BIT(engn);
- fifo->runlist[tdev->runlist].engm_sw |= BIT(engn);
- if (tdev->type == NVKM_ENGINE_GR)
- fifo->runlist[tdev->runlist].engm_sw |= BIT(GK104_FIFO_ENGN_SW);
- fifo->runlist_nr = max(fifo->runlist_nr, tdev->runlist + 1);
- }
-
- kfree(map);
-
- for (i = 0; i < fifo->runlist_nr; i++) {
- for (j = 0; j < ARRAY_SIZE(fifo->runlist[i].mem); j++) {
- ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
- fifo->base.nr * 2/* TSG+chan */ *
- fifo->func->runlist->size,
- 0x1000, false,
- &fifo->runlist[i].mem[j]);
- if (ret)
- return ret;
- }
-
- init_waitqueue_head(&fifo->runlist[i].wait);
- INIT_LIST_HEAD(&fifo->runlist[i].cgrp);
- INIT_LIST_HEAD(&fifo->runlist[i].chan);
- }
-
- ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
- fifo->base.nr * 0x200, 0x1000, true,
- &fifo->user.mem);
- if (ret)
- return ret;
-
- ret = nvkm_vmm_get(bar, 12, nvkm_memory_size(fifo->user.mem),
- &fifo->user.bar);
- if (ret)
- return ret;
-
- return nvkm_memory_map(fifo->user.mem, 0, bar, fifo->user.bar, NULL, 0);
+ return nvkm_rd32(device, 0x002284 + (runl->id * 0x08)) & 0x00100000;
}
void
-gk104_fifo_init(struct nvkm_fifo *base)
+gk104_runl_commit(struct nvkm_runl *runl, struct nvkm_memory *memory, u32 start, int count)
{
- struct gk104_fifo *fifo = gk104_fifo(base);
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- int i;
-
- /* Enable PBDMAs. */
- fifo->func->pbdma->init(fifo);
-
- /* PBDMA[n] */
- for (i = 0; i < fifo->pbdma_nr; i++) {
- nvkm_mask(device, 0x04013c + (i * 0x2000), 0x10000100, 0x00000000);
- nvkm_wr32(device, 0x040108 + (i * 0x2000), 0xffffffff); /* INTR */
- nvkm_wr32(device, 0x04010c + (i * 0x2000), 0xfffffeff); /* INTREN */
- }
-
- /* PBDMA[n].HCE */
- for (i = 0; i < fifo->pbdma_nr; i++) {
- nvkm_wr32(device, 0x040148 + (i * 0x2000), 0xffffffff); /* INTR */
- nvkm_wr32(device, 0x04014c + (i * 0x2000), 0xffffffff); /* INTREN */
- }
-
- nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar->addr >> 12);
-
- if (fifo->func->pbdma->init_timeout)
- fifo->func->pbdma->init_timeout(fifo);
-
- nvkm_wr32(device, 0x002100, 0xffffffff);
- nvkm_wr32(device, 0x002140, 0x7fffffff);
-}
-
-void *
-gk104_fifo_dtor(struct nvkm_fifo *base)
-{
- struct gk104_fifo *fifo = gk104_fifo(base);
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- int i;
-
- nvkm_vmm_put(nvkm_bar_bar1_vmm(device), &fifo->user.bar);
- nvkm_memory_unref(&fifo->user.mem);
+ struct nvkm_fifo *fifo = runl->fifo;
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ u64 addr = nvkm_memory_addr(memory) + start;
+ int target;
- for (i = 0; i < fifo->runlist_nr; i++) {
- nvkm_memory_unref(&fifo->runlist[i].mem[1]);
- nvkm_memory_unref(&fifo->runlist[i].mem[0]);
+ switch (nvkm_memory_target(memory)) {
+ case NVKM_MEM_TARGET_VRAM: target = 0; break;
+ case NVKM_MEM_TARGET_NCOH: target = 3; break;
+ default:
+ WARN_ON(1);
+ return;
}
- return fifo;
+ spin_lock_irq(&fifo->lock);
+ nvkm_wr32(device, 0x002270, (target << 28) | (addr >> 12));
+ nvkm_wr32(device, 0x002274, (runl->id << 20) | count);
+ spin_unlock_irq(&fifo->lock);
}
-static const struct nvkm_fifo_func
-gk104_fifo_ = {
- .dtor = gk104_fifo_dtor,
- .oneinit = gk104_fifo_oneinit,
- .info = gk104_fifo_info,
- .init = gk104_fifo_init,
- .fini = gk104_fifo_fini,
- .intr = gk104_fifo_intr,
- .fault = gk104_fifo_fault,
- .engine_id = gk104_fifo_engine_id,
- .id_engine = gk104_fifo_id_engine,
- .uevent_init = gk104_fifo_uevent_init,
- .uevent_fini = gk104_fifo_uevent_fini,
- .recover_chan = gk104_fifo_recover_chan,
- .class_get = gk104_fifo_class_get,
- .class_new = gk104_fifo_class_new,
-};
-
-int
-gk104_fifo_new_(const struct gk104_fifo_func *func, struct nvkm_device *device,
- enum nvkm_subdev_type type, int inst, int nr, struct nvkm_fifo **pfifo)
+void
+gk104_runl_insert_chan(struct nvkm_chan *chan, struct nvkm_memory *memory, u64 offset)
{
- struct gk104_fifo *fifo;
-
- if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
- return -ENOMEM;
- fifo->func = func;
- INIT_WORK(&fifo->recover.work, gk104_fifo_recover_work);
- *pfifo = &fifo->base;
-
- return nvkm_fifo_ctor(&gk104_fifo_, device, type, inst, nr, &fifo->base);
+ nvkm_wo32(memory, offset + 0, chan->id);
+ nvkm_wo32(memory, offset + 4, 0x00000000);
}
-const struct nvkm_enum
-gk104_fifo_fault_access[] = {
- { 0x0, "READ" },
- { 0x1, "WRITE" },
- {}
+static const struct nvkm_runl_func
+gk104_runl = {
+ .size = 8,
+ .update = nv50_runl_update,
+ .insert_chan = gk104_runl_insert_chan,
+ .commit = gk104_runl_commit,
+ .wait = nv50_runl_wait,
+ .pending = gk104_runl_pending,
+ .block = gk104_runl_block,
+ .allow = gk104_runl_allow,
+ .fault_clear = gk104_runl_fault_clear,
+ .preempt_pending = gf100_runl_preempt_pending,
};
-const struct nvkm_enum
-gk104_fifo_fault_engine[] = {
+static const struct nvkm_enum
+gk104_fifo_mmu_fault_engine[] = {
{ 0x00, "GR", NULL, NVKM_ENGINE_GR },
{ 0x01, "DISPLAY" },
{ 0x02, "CAPTURE" },
@@ -1122,14 +478,14 @@ gk104_fifo_fault_engine[] = {
{ 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
{ 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM },
{ 0x06, "SCHED" },
- { 0x07, "HOST0", NULL, NVKM_ENGINE_FIFO },
- { 0x08, "HOST1", NULL, NVKM_ENGINE_FIFO },
- { 0x09, "HOST2", NULL, NVKM_ENGINE_FIFO },
- { 0x0a, "HOST3", NULL, NVKM_ENGINE_FIFO },
- { 0x0b, "HOST4", NULL, NVKM_ENGINE_FIFO },
- { 0x0c, "HOST5", NULL, NVKM_ENGINE_FIFO },
- { 0x0d, "HOST6", NULL, NVKM_ENGINE_FIFO },
- { 0x0e, "HOST7", NULL, NVKM_ENGINE_FIFO },
+ { 0x07, "HOST0" },
+ { 0x08, "HOST1" },
+ { 0x09, "HOST2" },
+ { 0x0a, "HOST3" },
+ { 0x0b, "HOST4" },
+ { 0x0c, "HOST5" },
+ { 0x0d, "HOST6" },
+ { 0x0e, "HOST7" },
{ 0x0f, "HOSTSR" },
{ 0x10, "MSVLD", NULL, NVKM_ENGINE_MSVLD },
{ 0x11, "MSPPP", NULL, NVKM_ENGINE_MSPPP },
@@ -1145,7 +501,7 @@ gk104_fifo_fault_engine[] = {
};
const struct nvkm_enum
-gk104_fifo_fault_reason[] = {
+gk104_fifo_mmu_fault_reason[] = {
{ 0x00, "PDE" },
{ 0x01, "PDE_SIZE" },
{ 0x02, "PTE" },
@@ -1166,7 +522,7 @@ gk104_fifo_fault_reason[] = {
};
const struct nvkm_enum
-gk104_fifo_fault_hubclient[] = {
+gk104_fifo_mmu_fault_hubclient[] = {
{ 0x00, "VIP" },
{ 0x01, "CE0" },
{ 0x02, "CE1" },
@@ -1203,7 +559,7 @@ gk104_fifo_fault_hubclient[] = {
};
const struct nvkm_enum
-gk104_fifo_fault_gpcclient[] = {
+gk104_fifo_mmu_fault_gpcclient[] = {
{ 0x00, "L1_0" }, { 0x01, "T1_0" }, { 0x02, "PE_0" },
{ 0x03, "L1_1" }, { 0x04, "T1_1" }, { 0x05, "PE_1" },
{ 0x06, "L1_2" }, { 0x07, "T1_2" }, { 0x08, "PE_2" },
@@ -1228,22 +584,250 @@ gk104_fifo_fault_gpcclient[] = {
{}
};
-static const struct gk104_fifo_func
+const struct nvkm_fifo_func_mmu_fault
+gk104_fifo_mmu_fault = {
+ .recover = gf100_fifo_mmu_fault_recover,
+ .access = gf100_fifo_mmu_fault_access,
+ .engine = gk104_fifo_mmu_fault_engine,
+ .reason = gk104_fifo_mmu_fault_reason,
+ .hubclient = gk104_fifo_mmu_fault_hubclient,
+ .gpcclient = gk104_fifo_mmu_fault_gpcclient,
+};
+
+static const struct nvkm_enum
+gk104_fifo_intr_bind_reason[] = {
+ { 0x01, "BIND_NOT_UNBOUND" },
+ { 0x02, "SNOOP_WITHOUT_BAR1" },
+ { 0x03, "UNBIND_WHILE_RUNNING" },
+ { 0x05, "INVALID_RUNLIST" },
+ { 0x06, "INVALID_CTX_TGT" },
+ { 0x0b, "UNBIND_WHILE_PARKED" },
+ {}
+};
+
+void
+gk104_fifo_intr_bind(struct nvkm_fifo *fifo)
+{
+ struct nvkm_subdev *subdev = &fifo->engine.subdev;
+ u32 intr = nvkm_rd32(subdev->device, 0x00252c);
+ u32 code = intr & 0x000000ff;
+ const struct nvkm_enum *en = nvkm_enum_find(gk104_fifo_intr_bind_reason, code);
+
+ nvkm_error(subdev, "BIND_ERROR %02x [%s]\n", code, en ? en->name : "");
+}
+
+void
+gk104_fifo_intr_chsw(struct nvkm_fifo *fifo)
+{
+ struct nvkm_subdev *subdev = &fifo->engine.subdev;
+ struct nvkm_device *device = subdev->device;
+ u32 stat = nvkm_rd32(device, 0x00256c);
+
+ nvkm_error(subdev, "CHSW_ERROR %08x\n", stat);
+ nvkm_wr32(device, 0x00256c, stat);
+}
+
+static void
+gk104_fifo_intr_dropped_fault(struct nvkm_fifo *fifo)
+{
+ struct nvkm_subdev *subdev = &fifo->engine.subdev;
+ u32 stat = nvkm_rd32(subdev->device, 0x00259c);
+
+ nvkm_error(subdev, "DROPPED_MMU_FAULT %08x\n", stat);
+}
+
+void
+gk104_fifo_intr_runlist(struct nvkm_fifo *fifo)
+{
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ struct nvkm_runl *runl;
+ u32 mask = nvkm_rd32(device, 0x002a00);
+
+ nvkm_runl_foreach_cond(runl, fifo, mask & BIT(runl->id)) {
+ nvkm_wr32(device, 0x002a00, BIT(runl->id));
+ }
+}
+
+irqreturn_t
+gk104_fifo_intr(struct nvkm_inth *inth)
+{
+ struct nvkm_fifo *fifo = container_of(inth, typeof(*fifo), engine.subdev.inth);
+ struct nvkm_subdev *subdev = &fifo->engine.subdev;
+ struct nvkm_device *device = subdev->device;
+ u32 mask = nvkm_rd32(device, 0x002140);
+ u32 stat = nvkm_rd32(device, 0x002100) & mask;
+
+ if (stat & 0x00000001) {
+ gk104_fifo_intr_bind(fifo);
+ nvkm_wr32(device, 0x002100, 0x00000001);
+ stat &= ~0x00000001;
+ }
+
+ if (stat & 0x00000010) {
+ nvkm_error(subdev, "PIO_ERROR\n");
+ nvkm_wr32(device, 0x002100, 0x00000010);
+ stat &= ~0x00000010;
+ }
+
+ if (stat & 0x00000100) {
+ gf100_fifo_intr_sched(fifo);
+ nvkm_wr32(device, 0x002100, 0x00000100);
+ stat &= ~0x00000100;
+ }
+
+ if (stat & 0x00010000) {
+ gk104_fifo_intr_chsw(fifo);
+ nvkm_wr32(device, 0x002100, 0x00010000);
+ stat &= ~0x00010000;
+ }
+
+ if (stat & 0x00800000) {
+ nvkm_error(subdev, "FB_FLUSH_TIMEOUT\n");
+ nvkm_wr32(device, 0x002100, 0x00800000);
+ stat &= ~0x00800000;
+ }
+
+ if (stat & 0x01000000) {
+ nvkm_error(subdev, "LB_ERROR\n");
+ nvkm_wr32(device, 0x002100, 0x01000000);
+ stat &= ~0x01000000;
+ }
+
+ if (stat & 0x08000000) {
+ gk104_fifo_intr_dropped_fault(fifo);
+ nvkm_wr32(device, 0x002100, 0x08000000);
+ stat &= ~0x08000000;
+ }
+
+ if (stat & 0x10000000) {
+ gf100_fifo_intr_mmu_fault(fifo);
+ stat &= ~0x10000000;
+ }
+
+ if (stat & 0x20000000) {
+ if (gf100_fifo_intr_pbdma(fifo))
+ stat &= ~0x20000000;
+ }
+
+ if (stat & 0x40000000) {
+ gk104_fifo_intr_runlist(fifo);
+ stat &= ~0x40000000;
+ }
+
+ if (stat & 0x80000000) {
+ nvkm_wr32(device, 0x002100, 0x80000000);
+ nvkm_event_ntfy(&fifo->nonstall.event, 0, NVKM_FIFO_NONSTALL_EVENT);
+ stat &= ~0x80000000;
+ }
+
+ if (stat) {
+ nvkm_error(subdev, "INTR %08x\n", stat);
+ spin_lock(&fifo->lock);
+ nvkm_mask(device, 0x002140, stat, 0x00000000);
+ spin_unlock(&fifo->lock);
+ nvkm_wr32(device, 0x002100, stat);
+ }
+
+ return IRQ_HANDLED;
+}
+
+void
+gk104_fifo_init_pbdmas(struct nvkm_fifo *fifo, u32 mask)
+{
+ struct nvkm_device *device = fifo->engine.subdev.device;
+
+ nvkm_wr32(device, 0x000204, mask);
+ nvkm_mask(device, 0x002a04, 0xbfffffff, 0xbfffffff);
+}
+
+void
+gk104_fifo_init(struct nvkm_fifo *fifo)
+{
+ struct nvkm_device *device = fifo->engine.subdev.device;
+
+ if (fifo->func->chan.func->userd->bar == 1)
+ nvkm_wr32(device, 0x002254, 0x10000000 | fifo->userd.bar1->addr >> 12);
+
+ nvkm_wr32(device, 0x002100, 0xffffffff);
+ nvkm_wr32(device, 0x002140, 0x7fffffff);
+}
+
+int
+gk104_fifo_runl_ctor(struct nvkm_fifo *fifo)
+{
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ struct nvkm_top_device *tdev;
+ struct nvkm_runl *runl;
+ struct nvkm_runq *runq;
+ const struct nvkm_engn_func *func;
+
+ nvkm_list_foreach(tdev, &device->top->device, head, tdev->runlist >= 0) {
+ runl = nvkm_runl_get(fifo, tdev->runlist, tdev->runlist);
+ if (!runl) {
+ runl = nvkm_runl_new(fifo, tdev->runlist, tdev->runlist, 0);
+ if (IS_ERR(runl))
+ return PTR_ERR(runl);
+
+ nvkm_runq_foreach_cond(runq, fifo, gk104_runq_runm(runq) & BIT(runl->id)) {
+ if (WARN_ON(runl->runq_nr == ARRAY_SIZE(runl->runq)))
+ return -ENOMEM;
+
+ runl->runq[runl->runq_nr++] = runq;
+ }
+
+ }
+
+ if (tdev->engine < 0)
+ continue;
+
+ switch (tdev->type) {
+ case NVKM_ENGINE_CE:
+ func = fifo->func->engn_ce;
+ break;
+ case NVKM_ENGINE_GR:
+ nvkm_runl_add(runl, 15, &gf100_engn_sw, NVKM_ENGINE_SW, 0);
+ fallthrough;
+ default:
+ func = fifo->func->engn;
+ break;
+ }
+
+ nvkm_runl_add(runl, tdev->engine, func, tdev->type, tdev->inst);
+ }
+
+ return 0;
+}
+
+int
+gk104_fifo_chid_nr(struct nvkm_fifo *fifo)
+{
+ return 4096;
+}
+
+static const struct nvkm_fifo_func
gk104_fifo = {
- .intr.fault = gf100_fifo_intr_fault,
- .pbdma = &gk104_fifo_pbdma,
- .fault.access = gk104_fifo_fault_access,
- .fault.engine = gk104_fifo_fault_engine,
- .fault.reason = gk104_fifo_fault_reason,
- .fault.hubclient = gk104_fifo_fault_hubclient,
- .fault.gpcclient = gk104_fifo_fault_gpcclient,
- .runlist = &gk104_fifo_runlist,
- .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new },
+ .chid_nr = gk104_fifo_chid_nr,
+ .chid_ctor = gf100_fifo_chid_ctor,
+ .runq_nr = gf100_fifo_runq_nr,
+ .runl_ctor = gk104_fifo_runl_ctor,
+ .init = gk104_fifo_init,
+ .init_pbdmas = gk104_fifo_init_pbdmas,
+ .intr = gk104_fifo_intr,
+ .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit,
+ .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout,
+ .mmu_fault = &gk104_fifo_mmu_fault,
+ .nonstall = &gf100_fifo_nonstall,
+ .runl = &gk104_runl,
+ .runq = &gk104_runq,
+ .engn = &gk104_engn,
+ .engn_ce = &gk104_engn_ce,
+ .cgrp = {{ }, &nv04_cgrp },
+ .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk104_chan },
};
int
gk104_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
- return gk104_fifo_new_(&gk104_fifo, device, type, inst, 4096, pfifo);
+ return nvkm_fifo_new_(&gk104_fifo, device, type, inst, pfifo);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
deleted file mode 100644
index f2d12ae73944..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-#ifndef __GK104_FIFO_H__
-#define __GK104_FIFO_H__
-#define gk104_fifo(p) container_of((p), struct gk104_fifo, base)
-#include "priv.h"
-struct nvkm_fifo_cgrp;
-
-#include <core/enum.h>
-#include <subdev/mmu.h>
-
-struct gk104_fifo_chan;
-struct gk104_fifo {
- const struct gk104_fifo_func *func;
- struct nvkm_fifo base;
-
- struct {
- struct work_struct work;
- u32 engm;
- u32 runm;
- } recover;
-
- int pbdma_nr;
-
- struct {
- struct nvkm_engine *engine;
- int runl;
- int pbid;
- } engine[16];
- int engine_nr;
-
- struct {
- struct nvkm_memory *mem[2];
- int next;
- wait_queue_head_t wait;
- struct list_head cgrp;
- struct list_head chan;
- u32 engm;
- u32 engm_sw;
- } runlist[16];
- int runlist_nr;
-
- struct {
- struct nvkm_memory *mem;
- struct nvkm_vma *bar;
- } user;
-};
-
-struct gk104_fifo_func {
- struct {
- void (*fault)(struct nvkm_fifo *, int unit);
- } intr;
-
- const struct gk104_fifo_pbdma_func {
- int (*nr)(struct gk104_fifo *);
- void (*init)(struct gk104_fifo *);
- void (*init_timeout)(struct gk104_fifo *);
- } *pbdma;
-
- struct {
- const struct nvkm_enum *access;
- const struct nvkm_enum *engine;
- const struct nvkm_enum *reason;
- const struct nvkm_enum *hubclient;
- const struct nvkm_enum *gpcclient;
- } fault;
-
- const struct gk104_fifo_runlist_func {
- u8 size;
- void (*cgrp)(struct nvkm_fifo_cgrp *,
- struct nvkm_memory *, u32 offset);
- void (*chan)(struct gk104_fifo_chan *,
- struct nvkm_memory *, u32 offset);
- void (*commit)(struct gk104_fifo *, int runl,
- struct nvkm_memory *, int entries);
- } *runlist;
-
- struct gk104_fifo_user_user {
- struct nvkm_sclass user;
- int (*ctor)(const struct nvkm_oclass *, void *, u32,
- struct nvkm_object **);
- } user;
-
- struct gk104_fifo_chan_user {
- struct nvkm_sclass user;
- int (*ctor)(struct gk104_fifo *, const struct nvkm_oclass *,
- void *, u32, struct nvkm_object **);
- } chan;
- bool cgrp_force;
-};
-
-struct gk104_fifo_engine_status {
- bool busy;
- bool faulted;
- bool chsw;
- bool save;
- bool load;
- struct {
- bool tsg;
- u32 id;
- } prev, next, *chan;
-};
-
-int gk104_fifo_new_(const struct gk104_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type,
- int index, int nr, struct nvkm_fifo **);
-void gk104_fifo_runlist_insert(struct gk104_fifo *, struct gk104_fifo_chan *);
-void gk104_fifo_runlist_remove(struct gk104_fifo *, struct gk104_fifo_chan *);
-void gk104_fifo_runlist_update(struct gk104_fifo *, int runl);
-void gk104_fifo_engine_status(struct gk104_fifo *fifo, int engn,
- struct gk104_fifo_engine_status *status);
-void gk104_fifo_intr_bind(struct gk104_fifo *fifo);
-void gk104_fifo_intr_chsw(struct gk104_fifo *fifo);
-void gk104_fifo_intr_dropped_fault(struct gk104_fifo *fifo);
-void gk104_fifo_intr_pbdma_0(struct gk104_fifo *fifo, int unit);
-void gk104_fifo_intr_pbdma_1(struct gk104_fifo *fifo, int unit);
-void gk104_fifo_intr_runlist(struct gk104_fifo *fifo);
-void gk104_fifo_intr_engine(struct gk104_fifo *fifo);
-void *gk104_fifo_dtor(struct nvkm_fifo *base);
-int gk104_fifo_oneinit(struct nvkm_fifo *base);
-int gk104_fifo_info(struct nvkm_fifo *base, u64 mthd, u64 *data);
-void gk104_fifo_init(struct nvkm_fifo *base);
-void gk104_fifo_fini(struct nvkm_fifo *base);
-int gk104_fifo_class_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
- void *argv, u32 argc, struct nvkm_object **pobject);
-int gk104_fifo_class_get(struct nvkm_fifo *base, int index,
- struct nvkm_oclass *oclass);
-void gk104_fifo_uevent_fini(struct nvkm_fifo *fifo);
-void gk104_fifo_uevent_init(struct nvkm_fifo *fifo);
-
-extern const struct gk104_fifo_pbdma_func gk104_fifo_pbdma;
-int gk104_fifo_pbdma_nr(struct gk104_fifo *);
-void gk104_fifo_pbdma_init(struct gk104_fifo *);
-extern const struct nvkm_enum gk104_fifo_fault_access[];
-extern const struct nvkm_enum gk104_fifo_fault_engine[];
-extern const struct nvkm_enum gk104_fifo_fault_reason[];
-extern const struct nvkm_enum gk104_fifo_fault_hubclient[];
-extern const struct nvkm_enum gk104_fifo_fault_gpcclient[];
-extern const struct gk104_fifo_runlist_func gk104_fifo_runlist;
-void gk104_fifo_runlist_chan(struct gk104_fifo_chan *,
- struct nvkm_memory *, u32);
-void gk104_fifo_runlist_commit(struct gk104_fifo *, int runl,
- struct nvkm_memory *, int);
-
-extern const struct gk104_fifo_runlist_func gk110_fifo_runlist;
-void gk110_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *,
- struct nvkm_memory *, u32);
-
-extern const struct gk104_fifo_pbdma_func gk208_fifo_pbdma;
-void gk208_fifo_pbdma_init_timeout(struct gk104_fifo *);
-
-void gm107_fifo_intr_fault(struct nvkm_fifo *, int);
-extern const struct nvkm_enum gm107_fifo_fault_engine[];
-extern const struct gk104_fifo_runlist_func gm107_fifo_runlist;
-
-extern const struct gk104_fifo_pbdma_func gm200_fifo_pbdma;
-int gm200_fifo_pbdma_nr(struct gk104_fifo *);
-
-void gp100_fifo_intr_fault(struct nvkm_fifo *, int);
-extern const struct nvkm_enum gp100_fifo_fault_engine[];
-
-extern const struct nvkm_enum gv100_fifo_fault_access[];
-extern const struct nvkm_enum gv100_fifo_fault_reason[];
-extern const struct nvkm_enum gv100_fifo_fault_hubclient[];
-extern const struct nvkm_enum gv100_fifo_fault_gpcclient[];
-void gv100_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *,
- struct nvkm_memory *, u32);
-void gv100_fifo_runlist_chan(struct gk104_fifo_chan *,
- struct nvkm_memory *, u32);
-#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c
index 915278c7e012..a8ff21cf7712 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk110.c
@@ -21,47 +21,112 @@
*
* Authors: Ben Skeggs
*/
-#include "gk104.h"
+#include "priv.h"
#include "cgrp.h"
-#include "changk104.h"
+#include "chan.h"
+#include "chid.h"
+#include "runl.h"
#include <core/memory.h>
+#include <subdev/timer.h>
#include <nvif/class.h>
void
-gk110_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *cgrp,
- struct nvkm_memory *memory, u32 offset)
+gk110_chan_preempt(struct nvkm_chan *chan)
+{
+ struct nvkm_cgrp *cgrp = chan->cgrp;
+
+ if (cgrp->hw) {
+ cgrp->func->preempt(cgrp);
+ return;
+ }
+
+ gf100_chan_preempt(chan);
+}
+
+const struct nvkm_chan_func
+gk110_chan = {
+ .inst = &gf100_chan_inst,
+ .userd = &gk104_chan_userd,
+ .ramfc = &gk104_chan_ramfc,
+ .bind = gk104_chan_bind,
+ .unbind = gk104_chan_unbind,
+ .start = gk104_chan_start,
+ .stop = gk104_chan_stop,
+ .preempt = gk110_chan_preempt,
+};
+
+static void
+gk110_cgrp_preempt(struct nvkm_cgrp *cgrp)
+{
+ nvkm_wr32(cgrp->runl->fifo->engine.subdev.device, 0x002634, 0x01000000 | cgrp->id);
+}
+
+const struct nvkm_cgrp_func
+gk110_cgrp = {
+ .preempt = gk110_cgrp_preempt,
+};
+
+void
+gk110_runl_insert_cgrp(struct nvkm_cgrp *cgrp, struct nvkm_memory *memory, u64 offset)
{
nvkm_wo32(memory, offset + 0, (cgrp->chan_nr << 26) | (128 << 18) |
(3 << 14) | 0x00002000 | cgrp->id);
nvkm_wo32(memory, offset + 4, 0x00000000);
}
-const struct gk104_fifo_runlist_func
-gk110_fifo_runlist = {
+const struct nvkm_runl_func
+gk110_runl = {
.size = 8,
- .cgrp = gk110_fifo_runlist_cgrp,
- .chan = gk104_fifo_runlist_chan,
- .commit = gk104_fifo_runlist_commit,
+ .update = nv50_runl_update,
+ .insert_cgrp = gk110_runl_insert_cgrp,
+ .insert_chan = gk104_runl_insert_chan,
+ .commit = gk104_runl_commit,
+ .wait = nv50_runl_wait,
+ .pending = gk104_runl_pending,
+ .block = gk104_runl_block,
+ .allow = gk104_runl_allow,
+ .fault_clear = gk104_runl_fault_clear,
+ .preempt_pending = gf100_runl_preempt_pending,
};
-static const struct gk104_fifo_func
+int
+gk110_fifo_chid_ctor(struct nvkm_fifo *fifo, int nr)
+{
+ int ret;
+
+ ret = nvkm_chid_new(&nvkm_chan_event, &fifo->engine.subdev, nr, 0, nr, &fifo->cgid);
+ if (ret)
+ return ret;
+
+ return gf100_fifo_chid_ctor(fifo, nr);
+}
+
+static const struct nvkm_fifo_func
gk110_fifo = {
- .intr.fault = gf100_fifo_intr_fault,
- .pbdma = &gk104_fifo_pbdma,
- .fault.access = gk104_fifo_fault_access,
- .fault.engine = gk104_fifo_fault_engine,
- .fault.reason = gk104_fifo_fault_reason,
- .fault.hubclient = gk104_fifo_fault_hubclient,
- .fault.gpcclient = gk104_fifo_fault_gpcclient,
- .runlist = &gk110_fifo_runlist,
- .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_B}, gk104_fifo_gpfifo_new },
+ .chid_nr = gk104_fifo_chid_nr,
+ .chid_ctor = gk110_fifo_chid_ctor,
+ .runq_nr = gf100_fifo_runq_nr,
+ .runl_ctor = gk104_fifo_runl_ctor,
+ .init = gk104_fifo_init,
+ .init_pbdmas = gk104_fifo_init_pbdmas,
+ .intr = gk104_fifo_intr,
+ .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit,
+ .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout,
+ .mmu_fault = &gk104_fifo_mmu_fault,
+ .nonstall = &gf100_fifo_nonstall,
+ .runl = &gk110_runl,
+ .runq = &gk104_runq,
+ .engn = &gk104_engn,
+ .engn_ce = &gk104_engn_ce,
+ .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp },
+ .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_B }, &gk110_chan },
};
int
gk110_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
- return gk104_fifo_new_(&gk110_fifo, device, type, inst, 4096, pfifo);
+ return nvkm_fifo_new_(&gk110_fifo, device, type, inst, pfifo);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c
index cb703693de52..8fa2b0be141a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk208.c
@@ -21,44 +21,57 @@
*
* Authors: Ben Skeggs
*/
-#include "gk104.h"
-#include "changk104.h"
+#include "priv.h"
+#include "runq.h"
#include <nvif/class.h>
void
-gk208_fifo_pbdma_init_timeout(struct gk104_fifo *fifo)
+gk208_runq_init(struct nvkm_runq *runq)
{
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- int i;
+ gk104_runq_init(runq);
- for (i = 0; i < fifo->pbdma_nr; i++)
- nvkm_wr32(device, 0x04012c + (i * 0x2000), 0x0000ffff);
+ nvkm_wr32(runq->fifo->engine.subdev.device, 0x04012c + (runq->id * 0x2000), 0x000f4240);
}
-const struct gk104_fifo_pbdma_func
-gk208_fifo_pbdma = {
- .nr = gk104_fifo_pbdma_nr,
- .init = gk104_fifo_pbdma_init,
- .init_timeout = gk208_fifo_pbdma_init_timeout,
+const struct nvkm_runq_func
+gk208_runq = {
+ .init = gk208_runq_init,
+ .intr = gk104_runq_intr,
+ .intr_0_names = gk104_runq_intr_0_names,
+ .idle = gk104_runq_idle,
};
-static const struct gk104_fifo_func
+static int
+gk208_fifo_chid_nr(struct nvkm_fifo *fifo)
+{
+ return 1024;
+}
+
+static const struct nvkm_fifo_func
gk208_fifo = {
- .intr.fault = gf100_fifo_intr_fault,
- .pbdma = &gk208_fifo_pbdma,
- .fault.access = gk104_fifo_fault_access,
- .fault.engine = gk104_fifo_fault_engine,
- .fault.reason = gk104_fifo_fault_reason,
- .fault.hubclient = gk104_fifo_fault_hubclient,
- .fault.gpcclient = gk104_fifo_fault_gpcclient,
- .runlist = &gk110_fifo_runlist,
- .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new },
+ .chid_nr = gk208_fifo_chid_nr,
+ .chid_ctor = gk110_fifo_chid_ctor,
+ .runq_nr = gf100_fifo_runq_nr,
+ .runl_ctor = gk104_fifo_runl_ctor,
+ .init = gk104_fifo_init,
+ .init_pbdmas = gk104_fifo_init_pbdmas,
+ .intr = gk104_fifo_intr,
+ .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit,
+ .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout,
+ .mmu_fault = &gk104_fifo_mmu_fault,
+ .nonstall = &gf100_fifo_nonstall,
+ .runl = &gk110_runl,
+ .runq = &gk208_runq,
+ .engn = &gk104_engn,
+ .engn_ce = &gk104_engn_ce,
+ .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp },
+ .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk110_chan },
};
int
gk208_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
- return gk104_fifo_new_(&gk208_fifo, device, type, inst, 1024, pfifo);
+ return nvkm_fifo_new_(&gk208_fifo, device, type, inst, pfifo);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c
index 6e35cf44c640..b63ca836130f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk20a.c
@@ -19,27 +19,34 @@
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
-#include "gk104.h"
-#include "changk104.h"
+#include "priv.h"
#include <nvif/class.h>
-static const struct gk104_fifo_func
+static const struct nvkm_fifo_func
gk20a_fifo = {
- .intr.fault = gf100_fifo_intr_fault,
- .pbdma = &gk208_fifo_pbdma,
- .fault.access = gk104_fifo_fault_access,
- .fault.engine = gk104_fifo_fault_engine,
- .fault.reason = gk104_fifo_fault_reason,
- .fault.hubclient = gk104_fifo_fault_hubclient,
- .fault.gpcclient = gk104_fifo_fault_gpcclient,
- .runlist = &gk110_fifo_runlist,
- .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new },
+ .chid_nr = nv50_fifo_chid_nr,
+ .chid_ctor = gk110_fifo_chid_ctor,
+ .runq_nr = gf100_fifo_runq_nr,
+ .runl_ctor = gk104_fifo_runl_ctor,
+ .init = gk104_fifo_init,
+ .init_pbdmas = gk104_fifo_init_pbdmas,
+ .intr = gk104_fifo_intr,
+ .intr_mmu_fault_unit = gf100_fifo_intr_mmu_fault_unit,
+ .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout,
+ .mmu_fault = &gk104_fifo_mmu_fault,
+ .nonstall = &gf100_fifo_nonstall,
+ .runl = &gk110_runl,
+ .runq = &gk208_runq,
+ .engn = &gk104_engn,
+ .engn_ce = &gk104_engn_ce,
+ .cgrp = {{ }, &gk110_cgrp },
+ .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_A }, &gk110_chan },
};
int
gk20a_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
- return gk104_fifo_new_(&gk20a_fifo, device, type, inst, 128, pfifo);
+ return nvkm_fifo_new_(&gk20a_fifo, device, type, inst, pfifo);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c
index 7af6e687d474..5ba60021b510 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm107.c
@@ -21,46 +21,65 @@
*
* Authors: Ben Skeggs
*/
-#include "gk104.h"
-#include "changk104.h"
+#include "priv.h"
+#include "chan.h"
+#include "runl.h"
#include <core/gpuobj.h>
#include <subdev/fault.h>
#include <nvif/class.h>
+const struct nvkm_chan_func
+gm107_chan = {
+ .inst = &gf100_chan_inst,
+ .userd = &gk104_chan_userd,
+ .ramfc = &gk104_chan_ramfc,
+ .bind = gk104_chan_bind_inst,
+ .unbind = gk104_chan_unbind,
+ .start = gk104_chan_start,
+ .stop = gk104_chan_stop,
+ .preempt = gk110_chan_preempt,
+};
+
static void
-gm107_fifo_runlist_chan(struct gk104_fifo_chan *chan,
- struct nvkm_memory *memory, u32 offset)
+gm107_runl_insert_chan(struct nvkm_chan *chan, struct nvkm_memory *memory, u64 offset)
{
- nvkm_wo32(memory, offset + 0, chan->base.chid);
- nvkm_wo32(memory, offset + 4, chan->base.inst->addr >> 12);
+ nvkm_wo32(memory, offset + 0, chan->id);
+ nvkm_wo32(memory, offset + 4, chan->inst->addr >> 12);
}
-const struct gk104_fifo_runlist_func
-gm107_fifo_runlist = {
+const struct nvkm_runl_func
+gm107_runl = {
.size = 8,
- .cgrp = gk110_fifo_runlist_cgrp,
- .chan = gm107_fifo_runlist_chan,
- .commit = gk104_fifo_runlist_commit,
+ .update = nv50_runl_update,
+ .insert_cgrp = gk110_runl_insert_cgrp,
+ .insert_chan = gm107_runl_insert_chan,
+ .commit = gk104_runl_commit,
+ .wait = nv50_runl_wait,
+ .pending = gk104_runl_pending,
+ .block = gk104_runl_block,
+ .allow = gk104_runl_allow,
+ .fault_clear = gk104_runl_fault_clear,
+ .preempt_pending = gf100_runl_preempt_pending,
};
-const struct nvkm_enum
-gm107_fifo_fault_engine[] = {
+static const struct nvkm_enum
+gm107_fifo_mmu_fault_engine[] = {
{ 0x01, "DISPLAY" },
{ 0x02, "CAPTURE" },
{ 0x03, "IFB", NULL, NVKM_ENGINE_IFB },
{ 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
{ 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM },
{ 0x06, "SCHED" },
- { 0x07, "HOST0", NULL, NVKM_ENGINE_FIFO },
- { 0x08, "HOST1", NULL, NVKM_ENGINE_FIFO },
- { 0x09, "HOST2", NULL, NVKM_ENGINE_FIFO },
- { 0x0a, "HOST3", NULL, NVKM_ENGINE_FIFO },
- { 0x0b, "HOST4", NULL, NVKM_ENGINE_FIFO },
- { 0x0c, "HOST5", NULL, NVKM_ENGINE_FIFO },
- { 0x0d, "HOST6", NULL, NVKM_ENGINE_FIFO },
- { 0x0e, "HOST7", NULL, NVKM_ENGINE_FIFO },
+ { 0x07, "HOST0" },
+ { 0x08, "HOST1" },
+ { 0x09, "HOST2" },
+ { 0x0a, "HOST3" },
+ { 0x0b, "HOST4" },
+ { 0x0c, "HOST5" },
+ { 0x0d, "HOST6" },
+ { 0x0e, "HOST7" },
{ 0x0f, "HOSTSR" },
{ 0x13, "PERF" },
{ 0x17, "PMU" },
@@ -68,8 +87,18 @@ gm107_fifo_fault_engine[] = {
{}
};
+const struct nvkm_fifo_func_mmu_fault
+gm107_fifo_mmu_fault = {
+ .recover = gf100_fifo_mmu_fault_recover,
+ .access = gf100_fifo_mmu_fault_access,
+ .engine = gm107_fifo_mmu_fault_engine,
+ .reason = gk104_fifo_mmu_fault_reason,
+ .hubclient = gk104_fifo_mmu_fault_hubclient,
+ .gpcclient = gk104_fifo_mmu_fault_gpcclient,
+};
+
void
-gm107_fifo_intr_fault(struct nvkm_fifo *fifo, int unit)
+gm107_fifo_intr_mmu_fault_unit(struct nvkm_fifo *fifo, int unit)
{
struct nvkm_device *device = fifo->engine.subdev.device;
u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10));
@@ -92,22 +121,36 @@ gm107_fifo_intr_fault(struct nvkm_fifo *fifo, int unit)
nvkm_fifo_fault(fifo, &info);
}
-static const struct gk104_fifo_func
+static int
+gm107_fifo_chid_nr(struct nvkm_fifo *fifo)
+{
+ return 2048;
+}
+
+static const struct nvkm_fifo_func
gm107_fifo = {
- .intr.fault = gm107_fifo_intr_fault,
- .pbdma = &gk208_fifo_pbdma,
- .fault.access = gk104_fifo_fault_access,
- .fault.engine = gm107_fifo_fault_engine,
- .fault.reason = gk104_fifo_fault_reason,
- .fault.hubclient = gk104_fifo_fault_hubclient,
- .fault.gpcclient = gk104_fifo_fault_gpcclient,
- .runlist = &gm107_fifo_runlist,
- .chan = {{0,0,KEPLER_CHANNEL_GPFIFO_B}, gk104_fifo_gpfifo_new },
+ .chid_nr = gm107_fifo_chid_nr,
+ .chid_ctor = gk110_fifo_chid_ctor,
+ .runq_nr = gf100_fifo_runq_nr,
+ .runl_ctor = gk104_fifo_runl_ctor,
+ .init = gk104_fifo_init,
+ .init_pbdmas = gk104_fifo_init_pbdmas,
+ .intr = gk104_fifo_intr,
+ .intr_mmu_fault_unit = gm107_fifo_intr_mmu_fault_unit,
+ .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout,
+ .mmu_fault = &gm107_fifo_mmu_fault,
+ .nonstall = &gf100_fifo_nonstall,
+ .runl = &gm107_runl,
+ .runq = &gk208_runq,
+ .engn = &gk104_engn,
+ .engn_ce = &gk104_engn_ce,
+ .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp },
+ .chan = {{ 0, 0, KEPLER_CHANNEL_GPFIFO_B }, &gm107_chan },
};
int
gm107_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
- return gk104_fifo_new_(&gm107_fifo, device, type, inst, 2048, pfifo);
+ return nvkm_fifo_new_(&gm107_fifo, device, type, inst, pfifo);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c
index 573658cb6c73..d92d1ac39191 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm200.c
@@ -21,41 +21,46 @@
*
* Authors: Ben Skeggs
*/
-#include "gk104.h"
-#include "changk104.h"
+#include "priv.h"
#include <nvif/class.h>
int
-gm200_fifo_pbdma_nr(struct gk104_fifo *fifo)
+gm200_fifo_runq_nr(struct nvkm_fifo *fifo)
{
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- return nvkm_rd32(device, 0x002004) & 0x000000ff;
+ return nvkm_rd32(fifo->engine.subdev.device, 0x002004) & 0x000000ff;
}
-const struct gk104_fifo_pbdma_func
-gm200_fifo_pbdma = {
- .nr = gm200_fifo_pbdma_nr,
- .init = gk104_fifo_pbdma_init,
- .init_timeout = gk208_fifo_pbdma_init_timeout,
-};
+int
+gm200_fifo_chid_nr(struct nvkm_fifo *fifo)
+{
+ return nvkm_rd32(fifo->engine.subdev.device, 0x002008);
+}
-static const struct gk104_fifo_func
+static const struct nvkm_fifo_func
gm200_fifo = {
- .intr.fault = gm107_fifo_intr_fault,
- .pbdma = &gm200_fifo_pbdma,
- .fault.access = gk104_fifo_fault_access,
- .fault.engine = gm107_fifo_fault_engine,
- .fault.reason = gk104_fifo_fault_reason,
- .fault.hubclient = gk104_fifo_fault_hubclient,
- .fault.gpcclient = gk104_fifo_fault_gpcclient,
- .runlist = &gm107_fifo_runlist,
- .chan = {{0,0,MAXWELL_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new },
+ .chid_nr = gm200_fifo_chid_nr,
+ .chid_ctor = gk110_fifo_chid_ctor,
+ .runq_nr = gm200_fifo_runq_nr,
+ .runl_ctor = gk104_fifo_runl_ctor,
+ .init = gk104_fifo_init,
+ .init_pbdmas = gk104_fifo_init_pbdmas,
+ .intr = gk104_fifo_intr,
+ .intr_mmu_fault_unit = gm107_fifo_intr_mmu_fault_unit,
+ .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout,
+ .mmu_fault = &gm107_fifo_mmu_fault,
+ .nonstall = &gf100_fifo_nonstall,
+ .runl = &gm107_runl,
+ .runq = &gk208_runq,
+ .engn = &gk104_engn,
+ .engn_ce = &gk104_engn_ce,
+ .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp },
+ .chan = {{ 0, 0, MAXWELL_CHANNEL_GPFIFO_A }, &gm107_chan },
};
int
gm200_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
- return gk104_fifo_new_(&gm200_fifo, device, type, inst, 4096, pfifo);
+ return nvkm_fifo_new_(&gm200_fifo, device, type, inst, pfifo);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c
deleted file mode 100644
index 556c97e54f14..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gm20b.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved.
- *
- * 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 AUTHORS OR COPYRIGHT HOLDERS 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 "gk104.h"
-#include "changk104.h"
-
-#include <nvif/class.h>
-
-static const struct gk104_fifo_func
-gm20b_fifo = {
- .intr.fault = gm107_fifo_intr_fault,
- .pbdma = &gm200_fifo_pbdma,
- .fault.access = gk104_fifo_fault_access,
- .fault.engine = gm107_fifo_fault_engine,
- .fault.reason = gk104_fifo_fault_reason,
- .fault.hubclient = gk104_fifo_fault_hubclient,
- .fault.gpcclient = gk104_fifo_fault_gpcclient,
- .runlist = &gm107_fifo_runlist,
- .chan = {{0,0,MAXWELL_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new },
-};
-
-int
-gm20b_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
- struct nvkm_fifo **pfifo)
-{
- return gk104_fifo_new_(&gm20b_fifo, device, type, inst, 512, pfifo);
-}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c
index 6b46b6b65b87..65bdb6a7d517 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp100.c
@@ -21,30 +21,54 @@
*
* Authors: Ben Skeggs
*/
-#include "gk104.h"
-#include "changk104.h"
+#include "priv.h"
+#include "runl.h"
+#include <core/gpuobj.h>
#include <subdev/fault.h>
#include <nvif/class.h>
-const struct nvkm_enum
-gp100_fifo_fault_engine[] = {
+static void
+gp100_runl_insert_chan(struct nvkm_chan *chan, struct nvkm_memory *memory, u64 offset)
+{
+ nvkm_wo32(memory, offset + 0, chan->id | chan->runq << 14);
+ nvkm_wo32(memory, offset + 4, chan->inst->addr >> 12);
+}
+
+static const struct nvkm_runl_func
+gp100_runl = {
+ .runqs = 2,
+ .size = 8,
+ .update = nv50_runl_update,
+ .insert_cgrp = gk110_runl_insert_cgrp,
+ .insert_chan = gp100_runl_insert_chan,
+ .commit = gk104_runl_commit,
+ .wait = nv50_runl_wait,
+ .pending = gk104_runl_pending,
+ .block = gk104_runl_block,
+ .allow = gk104_runl_allow,
+ .fault_clear = gk104_runl_fault_clear,
+ .preempt_pending = gf100_runl_preempt_pending,
+};
+
+static const struct nvkm_enum
+gp100_fifo_mmu_fault_engine[] = {
{ 0x01, "DISPLAY" },
{ 0x03, "IFB", NULL, NVKM_ENGINE_IFB },
{ 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
{ 0x05, "BAR2", NULL, NVKM_SUBDEV_INSTMEM },
- { 0x06, "HOST0", NULL, NVKM_ENGINE_FIFO },
- { 0x07, "HOST1", NULL, NVKM_ENGINE_FIFO },
- { 0x08, "HOST2", NULL, NVKM_ENGINE_FIFO },
- { 0x09, "HOST3", NULL, NVKM_ENGINE_FIFO },
- { 0x0a, "HOST4", NULL, NVKM_ENGINE_FIFO },
- { 0x0b, "HOST5", NULL, NVKM_ENGINE_FIFO },
- { 0x0c, "HOST6", NULL, NVKM_ENGINE_FIFO },
- { 0x0d, "HOST7", NULL, NVKM_ENGINE_FIFO },
- { 0x0e, "HOST8", NULL, NVKM_ENGINE_FIFO },
- { 0x0f, "HOST9", NULL, NVKM_ENGINE_FIFO },
- { 0x10, "HOST10", NULL, NVKM_ENGINE_FIFO },
+ { 0x06, "HOST0" },
+ { 0x07, "HOST1" },
+ { 0x08, "HOST2" },
+ { 0x09, "HOST3" },
+ { 0x0a, "HOST4" },
+ { 0x0b, "HOST5" },
+ { 0x0c, "HOST6" },
+ { 0x0d, "HOST7" },
+ { 0x0e, "HOST8" },
+ { 0x0f, "HOST9" },
+ { 0x10, "HOST10" },
{ 0x13, "PERF" },
{ 0x17, "PMU" },
{ 0x18, "PTP" },
@@ -52,8 +76,18 @@ gp100_fifo_fault_engine[] = {
{}
};
-void
-gp100_fifo_intr_fault(struct nvkm_fifo *fifo, int unit)
+static const struct nvkm_fifo_func_mmu_fault
+gp100_fifo_mmu_fault = {
+ .recover = gf100_fifo_mmu_fault_recover,
+ .access = gf100_fifo_mmu_fault_access,
+ .engine = gp100_fifo_mmu_fault_engine,
+ .reason = gk104_fifo_mmu_fault_reason,
+ .hubclient = gk104_fifo_mmu_fault_hubclient,
+ .gpcclient = gk104_fifo_mmu_fault_gpcclient,
+};
+
+static void
+gp100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *fifo, int unit)
{
struct nvkm_device *device = fifo->engine.subdev.device;
u32 inst = nvkm_rd32(device, 0x002800 + (unit * 0x10));
@@ -76,23 +110,30 @@ gp100_fifo_intr_fault(struct nvkm_fifo *fifo, int unit)
nvkm_fifo_fault(fifo, &info);
}
-static const struct gk104_fifo_func
+static const struct nvkm_fifo_func
gp100_fifo = {
- .intr.fault = gp100_fifo_intr_fault,
- .pbdma = &gm200_fifo_pbdma,
- .fault.access = gk104_fifo_fault_access,
- .fault.engine = gp100_fifo_fault_engine,
- .fault.reason = gk104_fifo_fault_reason,
- .fault.hubclient = gk104_fifo_fault_hubclient,
- .fault.gpcclient = gk104_fifo_fault_gpcclient,
- .runlist = &gm107_fifo_runlist,
- .chan = {{0,0,PASCAL_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new },
- .cgrp_force = true,
+ .chid_nr = gm200_fifo_chid_nr,
+ .chid_ctor = gk110_fifo_chid_ctor,
+ .runq_nr = gm200_fifo_runq_nr,
+ .runl_ctor = gk104_fifo_runl_ctor,
+ .init = gk104_fifo_init,
+ .init_pbdmas = gk104_fifo_init_pbdmas,
+ .intr = gk104_fifo_intr,
+ .intr_mmu_fault_unit = gp100_fifo_intr_mmu_fault_unit,
+ .intr_ctxsw_timeout = gf100_fifo_intr_ctxsw_timeout,
+ .mmu_fault = &gp100_fifo_mmu_fault,
+ .nonstall = &gf100_fifo_nonstall,
+ .runl = &gp100_runl,
+ .runq = &gk208_runq,
+ .engn = &gk104_engn,
+ .engn_ce = &gk104_engn_ce,
+ .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true },
+ .chan = {{ 0, 0, PASCAL_CHANNEL_GPFIFO_A }, &gm107_chan },
};
int
gp100_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
- return gk104_fifo_new_(&gp100_fifo, device, type, inst, 4096, pfifo);
+ return nvkm_fifo_new_(&gp100_fifo, device, type, inst, pfifo);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c
deleted file mode 100644
index 7a5929cb4d29..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gp10b.c
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
- *
- * 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 AUTHORS OR COPYRIGHT HOLDERS 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 "gk104.h"
-#include "changk104.h"
-
-#include <nvif/class.h>
-
-static const struct gk104_fifo_func
-gp10b_fifo = {
- .intr.fault = gp100_fifo_intr_fault,
- .pbdma = &gm200_fifo_pbdma,
- .fault.access = gk104_fifo_fault_access,
- .fault.engine = gp100_fifo_fault_engine,
- .fault.reason = gk104_fifo_fault_reason,
- .fault.hubclient = gk104_fifo_fault_hubclient,
- .fault.gpcclient = gk104_fifo_fault_gpcclient,
- .runlist = &gm107_fifo_runlist,
- .chan = {{0,0,PASCAL_CHANNEL_GPFIFO_A}, gk104_fifo_gpfifo_new },
- .cgrp_force = true,
-};
-
-int
-gp10b_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
- struct nvkm_fifo **pfifo)
-{
- return gk104_fifo_new_(&gp10b_fifo, device, type, inst, 512, pfifo);
-}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c
deleted file mode 100644
index 2121f517b1dd..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright 2012 Red Hat 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: Ben Skeggs
- */
-#include "channv50.h"
-
-#include <core/client.h>
-#include <core/ramht.h>
-
-#include <nvif/class.h>
-#include <nvif/cl826f.h>
-#include <nvif/unpack.h>
-
-static int
-g84_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
- void *data, u32 size, struct nvkm_object **pobject)
-{
- struct nvkm_object *parent = oclass->parent;
- union {
- struct g82_channel_gpfifo_v0 v0;
- } *args = data;
- struct nv50_fifo *fifo = nv50_fifo(base);
- struct nv50_fifo_chan *chan;
- u64 ioffset, ilength;
- int ret = -ENOSYS;
-
- nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
- nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
- "pushbuf %llx ioffset %016llx "
- "ilength %08x\n",
- args->v0.version, args->v0.vmm, args->v0.pushbuf,
- args->v0.ioffset, args->v0.ilength);
- if (!args->v0.pushbuf)
- return -EINVAL;
- } else
- return ret;
-
- if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
- return -ENOMEM;
- *pobject = &chan->base.object;
-
- ret = g84_fifo_chan_ctor(fifo, args->v0.vmm, args->v0.pushbuf,
- oclass, chan);
- if (ret)
- return ret;
-
- args->v0.chid = chan->base.chid;
- ioffset = args->v0.ioffset;
- ilength = order_base_2(args->v0.ilength / 8);
-
- nvkm_kmap(chan->ramfc);
- nvkm_wo32(chan->ramfc, 0x3c, 0x403f6078);
- nvkm_wo32(chan->ramfc, 0x44, 0x01003fff);
- nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4);
- nvkm_wo32(chan->ramfc, 0x50, lower_32_bits(ioffset));
- nvkm_wo32(chan->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16));
- nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff);
- nvkm_wo32(chan->ramfc, 0x78, 0x00000000);
- nvkm_wo32(chan->ramfc, 0x7c, 0x30000001);
- nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
- (4 << 24) /* SEARCH_FULL */ |
- (chan->ramht->gpuobj->node->offset >> 4));
- nvkm_wo32(chan->ramfc, 0x88, chan->cache->addr >> 10);
- nvkm_wo32(chan->ramfc, 0x98, chan->base.inst->addr >> 12);
- nvkm_done(chan->ramfc);
- return 0;
-}
-
-const struct nvkm_fifo_chan_oclass
-g84_fifo_gpfifo_oclass = {
- .base.oclass = G82_CHANNEL_GPFIFO,
- .base.minver = 0,
- .base.maxver = 0,
- .ctor = g84_fifo_gpfifo_new,
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
deleted file mode 100644
index 4e78bbe3b94b..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/*
- * Copyright 2012 Red Hat 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: Ben Skeggs
- */
-#include "changf100.h"
-
-#include <core/client.h>
-#include <core/gpuobj.h>
-#include <subdev/fb.h>
-#include <subdev/timer.h>
-
-#include <nvif/class.h>
-#include <nvif/cl906f.h>
-#include <nvif/unpack.h>
-
-int
-gf100_fifo_chan_ntfy(struct nvkm_fifo_chan *chan, u32 type,
- struct nvkm_event **pevent)
-{
- switch (type) {
- case NV906F_V0_NTFY_NON_STALL_INTERRUPT:
- *pevent = &chan->fifo->uevent;
- return 0;
- case NV906F_V0_NTFY_KILLED:
- *pevent = &chan->fifo->kevent;
- return 0;
- default:
- break;
- }
- return -EINVAL;
-}
-
-static u32
-gf100_fifo_gpfifo_engine_addr(struct nvkm_engine *engine)
-{
- switch (engine->subdev.type) {
- case NVKM_ENGINE_SW : return 0;
- case NVKM_ENGINE_GR : return 0x0210;
- case NVKM_ENGINE_CE : return 0x0230 + (engine->subdev.inst * 0x10);
- case NVKM_ENGINE_MSPDEC: return 0x0250;
- case NVKM_ENGINE_MSPPP : return 0x0260;
- case NVKM_ENGINE_MSVLD : return 0x0270;
- default:
- WARN_ON(1);
- return 0;
- }
-}
-
-static struct gf100_fifo_engn *
-gf100_fifo_gpfifo_engine(struct gf100_fifo_chan *chan, struct nvkm_engine *engine)
-{
- int engi = chan->base.fifo->func->engine_id(chan->base.fifo, engine);
- if (engi >= 0)
- return &chan->engn[engi];
- return NULL;
-}
-
-static int
-gf100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine, bool suspend)
-{
- const u32 offset = gf100_fifo_gpfifo_engine_addr(engine);
- struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
- struct nvkm_subdev *subdev = &chan->fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- struct nvkm_gpuobj *inst = chan->base.inst;
- int ret = 0;
-
- mutex_lock(&chan->fifo->base.mutex);
- nvkm_wr32(device, 0x002634, chan->base.chid);
- if (nvkm_msec(device, 2000,
- if (nvkm_rd32(device, 0x002634) == chan->base.chid)
- break;
- ) < 0) {
- nvkm_error(subdev, "channel %d [%s] kick timeout\n",
- chan->base.chid, chan->base.object.client->name);
- ret = -ETIMEDOUT;
- }
- mutex_unlock(&chan->fifo->base.mutex);
-
- if (ret && suspend)
- return ret;
-
- if (offset) {
- nvkm_kmap(inst);
- nvkm_wo32(inst, offset + 0x00, 0x00000000);
- nvkm_wo32(inst, offset + 0x04, 0x00000000);
- nvkm_done(inst);
- }
-
- return ret;
-}
-
-static int
-gf100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine)
-{
- const u32 offset = gf100_fifo_gpfifo_engine_addr(engine);
- struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
- struct gf100_fifo_engn *engn = gf100_fifo_gpfifo_engine(chan, engine);
- struct nvkm_gpuobj *inst = chan->base.inst;
-
- if (offset) {
- nvkm_kmap(inst);
- nvkm_wo32(inst, offset + 0x00, lower_32_bits(engn->vma->addr) | 4);
- nvkm_wo32(inst, offset + 0x04, upper_32_bits(engn->vma->addr));
- nvkm_done(inst);
- }
-
- return 0;
-}
-
-static void
-gf100_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine)
-{
- struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
- struct gf100_fifo_engn *engn = gf100_fifo_gpfifo_engine(chan, engine);
- nvkm_vmm_put(chan->base.vmm, &engn->vma);
- nvkm_gpuobj_del(&engn->inst);
-}
-
-static int
-gf100_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine,
- struct nvkm_object *object)
-{
- struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
- struct gf100_fifo_engn *engn = gf100_fifo_gpfifo_engine(chan, engine);
- int ret;
-
- if (!gf100_fifo_gpfifo_engine_addr(engine))
- return 0;
-
- ret = nvkm_object_bind(object, NULL, 0, &engn->inst);
- if (ret)
- return ret;
-
- ret = nvkm_vmm_get(chan->base.vmm, 12, engn->inst->size, &engn->vma);
- if (ret)
- return ret;
-
- return nvkm_memory_map(engn->inst, 0, chan->base.vmm, engn->vma, NULL, 0);
-}
-
-static void
-gf100_fifo_gpfifo_fini(struct nvkm_fifo_chan *base)
-{
- struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
- struct gf100_fifo *fifo = chan->fifo;
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- u32 coff = chan->base.chid * 8;
-
- if (!list_empty(&chan->head) && !chan->killed) {
- gf100_fifo_runlist_remove(fifo, chan);
- nvkm_mask(device, 0x003004 + coff, 0x00000001, 0x00000000);
- gf100_fifo_runlist_commit(fifo);
- }
-
- gf100_fifo_intr_engine(fifo);
-
- nvkm_wr32(device, 0x003000 + coff, 0x00000000);
-}
-
-static void
-gf100_fifo_gpfifo_init(struct nvkm_fifo_chan *base)
-{
- struct gf100_fifo_chan *chan = gf100_fifo_chan(base);
- struct gf100_fifo *fifo = chan->fifo;
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- u32 addr = chan->base.inst->addr >> 12;
- u32 coff = chan->base.chid * 8;
-
- nvkm_wr32(device, 0x003000 + coff, 0xc0000000 | addr);
-
- if (list_empty(&chan->head) && !chan->killed) {
- gf100_fifo_runlist_insert(fifo, chan);
- nvkm_wr32(device, 0x003004 + coff, 0x001f0001);
- gf100_fifo_runlist_commit(fifo);
- }
-}
-
-static void *
-gf100_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base)
-{
- return gf100_fifo_chan(base);
-}
-
-static const struct nvkm_fifo_chan_func
-gf100_fifo_gpfifo_func = {
- .dtor = gf100_fifo_gpfifo_dtor,
- .init = gf100_fifo_gpfifo_init,
- .fini = gf100_fifo_gpfifo_fini,
- .ntfy = gf100_fifo_chan_ntfy,
- .engine_ctor = gf100_fifo_gpfifo_engine_ctor,
- .engine_dtor = gf100_fifo_gpfifo_engine_dtor,
- .engine_init = gf100_fifo_gpfifo_engine_init,
- .engine_fini = gf100_fifo_gpfifo_engine_fini,
-};
-
-static int
-gf100_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
- void *data, u32 size, struct nvkm_object **pobject)
-{
- union {
- struct fermi_channel_gpfifo_v0 v0;
- } *args = data;
- struct gf100_fifo *fifo = gf100_fifo(base);
- struct nvkm_object *parent = oclass->parent;
- struct gf100_fifo_chan *chan;
- u64 usermem, ioffset, ilength;
- int ret = -ENOSYS, i;
-
- nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
- nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
- "ioffset %016llx ilength %08x\n",
- args->v0.version, args->v0.vmm, args->v0.ioffset,
- args->v0.ilength);
- if (!args->v0.vmm)
- return -EINVAL;
- } else
- return ret;
-
- /* allocate channel */
- if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
- return -ENOMEM;
- *pobject = &chan->base.object;
- chan->fifo = fifo;
- INIT_LIST_HEAD(&chan->head);
-
- ret = nvkm_fifo_chan_ctor(&gf100_fifo_gpfifo_func, &fifo->base,
- 0x1000, 0x1000, true, args->v0.vmm, 0,
- BIT(GF100_FIFO_ENGN_GR) |
- BIT(GF100_FIFO_ENGN_MSPDEC) |
- BIT(GF100_FIFO_ENGN_MSPPP) |
- BIT(GF100_FIFO_ENGN_MSVLD) |
- BIT(GF100_FIFO_ENGN_CE0) |
- BIT(GF100_FIFO_ENGN_CE1) |
- BIT(GF100_FIFO_ENGN_SW),
- 1, fifo->user.bar->addr, 0x1000,
- oclass, &chan->base);
- if (ret)
- return ret;
-
- args->v0.chid = chan->base.chid;
-
- /* clear channel control registers */
-
- usermem = chan->base.chid * 0x1000;
- ioffset = args->v0.ioffset;
- ilength = order_base_2(args->v0.ilength / 8);
-
- nvkm_kmap(fifo->user.mem);
- for (i = 0; i < 0x1000; i += 4)
- nvkm_wo32(fifo->user.mem, usermem + i, 0x00000000);
- nvkm_done(fifo->user.mem);
- usermem = nvkm_memory_addr(fifo->user.mem) + usermem;
-
- /* RAMFC */
- nvkm_kmap(chan->base.inst);
- nvkm_wo32(chan->base.inst, 0x08, lower_32_bits(usermem));
- nvkm_wo32(chan->base.inst, 0x0c, upper_32_bits(usermem));
- nvkm_wo32(chan->base.inst, 0x10, 0x0000face);
- nvkm_wo32(chan->base.inst, 0x30, 0xfffff902);
- nvkm_wo32(chan->base.inst, 0x48, lower_32_bits(ioffset));
- nvkm_wo32(chan->base.inst, 0x4c, upper_32_bits(ioffset) |
- (ilength << 16));
- nvkm_wo32(chan->base.inst, 0x54, 0x00000002);
- nvkm_wo32(chan->base.inst, 0x84, 0x20400000);
- nvkm_wo32(chan->base.inst, 0x94, 0x30000001);
- nvkm_wo32(chan->base.inst, 0x9c, 0x00000100);
- nvkm_wo32(chan->base.inst, 0xa4, 0x1f1f1f1f);
- nvkm_wo32(chan->base.inst, 0xa8, 0x1f1f1f1f);
- nvkm_wo32(chan->base.inst, 0xac, 0x0000001f);
- nvkm_wo32(chan->base.inst, 0xb8, 0xf8000000);
- nvkm_wo32(chan->base.inst, 0xf8, 0x10003080); /* 0x002310 */
- nvkm_wo32(chan->base.inst, 0xfc, 0x10000010); /* 0x002350 */
- nvkm_done(chan->base.inst);
- return 0;
-}
-
-const struct nvkm_fifo_chan_oclass
-gf100_fifo_gpfifo_oclass = {
- .base.oclass = FERMI_CHANNEL_GPFIFO,
- .base.minver = 0,
- .base.maxver = 0,
- .ctor = gf100_fifo_gpfifo_new,
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
deleted file mode 100644
index 80456ec70e8a..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * Copyright 2012 Red Hat 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: Ben Skeggs
- */
-#include "changk104.h"
-#include "cgrp.h"
-
-#include <core/client.h>
-#include <core/gpuobj.h>
-#include <subdev/fb.h>
-#include <subdev/mmu.h>
-#include <subdev/timer.h>
-
-#include <nvif/class.h>
-#include <nvif/cla06f.h>
-#include <nvif/unpack.h>
-
-int
-gk104_fifo_gpfifo_kick_locked(struct gk104_fifo_chan *chan)
-{
- struct gk104_fifo *fifo = chan->fifo;
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- struct nvkm_client *client = chan->base.object.client;
- struct nvkm_fifo_cgrp *cgrp = chan->cgrp;
- int ret = 0;
-
- if (cgrp)
- nvkm_wr32(device, 0x002634, cgrp->id | 0x01000000);
- else
- nvkm_wr32(device, 0x002634, chan->base.chid);
- if (nvkm_msec(device, 2000,
- if (!(nvkm_rd32(device, 0x002634) & 0x00100000))
- break;
- ) < 0) {
- nvkm_error(subdev, "%s %d [%s] kick timeout\n",
- cgrp ? "tsg" : "channel",
- cgrp ? cgrp->id : chan->base.chid, client->name);
- nvkm_fifo_recover_chan(&fifo->base, chan->base.chid);
- ret = -ETIMEDOUT;
- }
- return ret;
-}
-
-int
-gk104_fifo_gpfifo_kick(struct gk104_fifo_chan *chan)
-{
- int ret;
- mutex_lock(&chan->base.fifo->mutex);
- ret = gk104_fifo_gpfifo_kick_locked(chan);
- mutex_unlock(&chan->base.fifo->mutex);
- return ret;
-}
-
-static u32
-gk104_fifo_gpfifo_engine_addr(struct nvkm_engine *engine)
-{
- switch (engine->subdev.type) {
- case NVKM_ENGINE_SW :
- case NVKM_ENGINE_CE : return 0;
- case NVKM_ENGINE_GR : return 0x0210;
- case NVKM_ENGINE_SEC : return 0x0220;
- case NVKM_ENGINE_MSPDEC: return 0x0250;
- case NVKM_ENGINE_MSPPP : return 0x0260;
- case NVKM_ENGINE_MSVLD : return 0x0270;
- case NVKM_ENGINE_VIC : return 0x0280;
- case NVKM_ENGINE_MSENC : return 0x0290;
- case NVKM_ENGINE_NVDEC : return 0x02100270;
- case NVKM_ENGINE_NVENC :
- if (engine->subdev.inst)
- return 0x0210;
- return 0x02100290;
- default:
- WARN_ON(1);
- return 0;
- }
-}
-
-struct gk104_fifo_engn *
-gk104_fifo_gpfifo_engine(struct gk104_fifo_chan *chan, struct nvkm_engine *engine)
-{
- int engi = chan->base.fifo->func->engine_id(chan->base.fifo, engine);
- if (engi >= 0)
- return &chan->engn[engi];
- return NULL;
-}
-
-static int
-gk104_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine, bool suspend)
-{
- struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
- struct nvkm_gpuobj *inst = chan->base.inst;
- u32 offset = gk104_fifo_gpfifo_engine_addr(engine);
- int ret;
-
- ret = gk104_fifo_gpfifo_kick(chan);
- if (ret && suspend)
- return ret;
-
- if (offset) {
- nvkm_kmap(inst);
- nvkm_wo32(inst, (offset & 0xffff) + 0x00, 0x00000000);
- nvkm_wo32(inst, (offset & 0xffff) + 0x04, 0x00000000);
- if ((offset >>= 16)) {
- nvkm_wo32(inst, offset + 0x00, 0x00000000);
- nvkm_wo32(inst, offset + 0x04, 0x00000000);
- }
- nvkm_done(inst);
- }
-
- return ret;
-}
-
-static int
-gk104_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine)
-{
- struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
- struct gk104_fifo_engn *engn = gk104_fifo_gpfifo_engine(chan, engine);
- struct nvkm_gpuobj *inst = chan->base.inst;
- u32 offset = gk104_fifo_gpfifo_engine_addr(engine);
-
- if (offset) {
- u32 datalo = lower_32_bits(engn->vma->addr) | 0x00000004;
- u32 datahi = upper_32_bits(engn->vma->addr);
- nvkm_kmap(inst);
- nvkm_wo32(inst, (offset & 0xffff) + 0x00, datalo);
- nvkm_wo32(inst, (offset & 0xffff) + 0x04, datahi);
- if ((offset >>= 16)) {
- nvkm_wo32(inst, offset + 0x00, datalo);
- nvkm_wo32(inst, offset + 0x04, datahi);
- }
- nvkm_done(inst);
- }
-
- return 0;
-}
-
-void
-gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine)
-{
- struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
- struct gk104_fifo_engn *engn = gk104_fifo_gpfifo_engine(chan, engine);
- nvkm_vmm_put(chan->base.vmm, &engn->vma);
- nvkm_gpuobj_del(&engn->inst);
-}
-
-int
-gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine,
- struct nvkm_object *object)
-{
- struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
- struct gk104_fifo_engn *engn = gk104_fifo_gpfifo_engine(chan, engine);
- int ret;
-
- if (!gk104_fifo_gpfifo_engine_addr(engine)) {
- if (engine->subdev.type != NVKM_ENGINE_CE ||
- engine->subdev.device->card_type < GV100)
- return 0;
- }
-
- ret = nvkm_object_bind(object, NULL, 0, &engn->inst);
- if (ret)
- return ret;
-
- if (!gk104_fifo_gpfifo_engine_addr(engine))
- return 0;
-
- ret = nvkm_vmm_get(chan->base.vmm, 12, engn->inst->size, &engn->vma);
- if (ret)
- return ret;
-
- return nvkm_memory_map(engn->inst, 0, chan->base.vmm, engn->vma, NULL, 0);
-}
-
-void
-gk104_fifo_gpfifo_fini(struct nvkm_fifo_chan *base)
-{
- struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
- struct gk104_fifo *fifo = chan->fifo;
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- u32 coff = chan->base.chid * 8;
-
- if (!list_empty(&chan->head)) {
- gk104_fifo_runlist_remove(fifo, chan);
- nvkm_mask(device, 0x800004 + coff, 0x00000800, 0x00000800);
- gk104_fifo_gpfifo_kick(chan);
- gk104_fifo_runlist_update(fifo, chan->runl);
- }
-
- nvkm_wr32(device, 0x800000 + coff, 0x00000000);
-}
-
-void
-gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base)
-{
- struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
- struct gk104_fifo *fifo = chan->fifo;
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- u32 addr = chan->base.inst->addr >> 12;
- u32 coff = chan->base.chid * 8;
-
- nvkm_mask(device, 0x800004 + coff, 0x000f0000, chan->runl << 16);
- nvkm_wr32(device, 0x800000 + coff, 0x80000000 | addr);
-
- if (list_empty(&chan->head) && !chan->killed) {
- gk104_fifo_runlist_insert(fifo, chan);
- nvkm_mask(device, 0x800004 + coff, 0x00000400, 0x00000400);
- gk104_fifo_runlist_update(fifo, chan->runl);
- nvkm_mask(device, 0x800004 + coff, 0x00000400, 0x00000400);
- }
-}
-
-void *
-gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base)
-{
- struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
- kfree(chan->cgrp);
- return chan;
-}
-
-const struct nvkm_fifo_chan_func
-gk104_fifo_gpfifo_func = {
- .dtor = gk104_fifo_gpfifo_dtor,
- .init = gk104_fifo_gpfifo_init,
- .fini = gk104_fifo_gpfifo_fini,
- .ntfy = gf100_fifo_chan_ntfy,
- .engine_ctor = gk104_fifo_gpfifo_engine_ctor,
- .engine_dtor = gk104_fifo_gpfifo_engine_dtor,
- .engine_init = gk104_fifo_gpfifo_engine_init,
- .engine_fini = gk104_fifo_gpfifo_engine_fini,
-};
-
-static int
-gk104_fifo_gpfifo_new_(struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
- u64 vmm, u64 ioffset, u64 ilength, u64 *inst, bool priv,
- const struct nvkm_oclass *oclass,
- struct nvkm_object **pobject)
-{
- struct gk104_fifo_chan *chan;
- int runlist = ffs(*runlists) -1, ret, i;
- u64 usermem;
-
- if (!vmm || runlist < 0 || runlist >= fifo->runlist_nr)
- return -EINVAL;
- *runlists = BIT_ULL(runlist);
-
- /* Allocate the channel. */
- if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
- return -ENOMEM;
- *pobject = &chan->base.object;
- chan->fifo = fifo;
- chan->runl = runlist;
- INIT_LIST_HEAD(&chan->head);
-
- ret = nvkm_fifo_chan_ctor(&gk104_fifo_gpfifo_func, &fifo->base,
- 0x1000, 0x1000, true, vmm, 0, fifo->runlist[runlist].engm_sw,
- 1, fifo->user.bar->addr, 0x200,
- oclass, &chan->base);
- if (ret)
- return ret;
-
- *chid = chan->base.chid;
- *inst = chan->base.inst->addr;
-
- /* Hack to support GPUs where even individual channels should be
- * part of a channel group.
- */
- if (fifo->func->cgrp_force) {
- if (!(chan->cgrp = kmalloc(sizeof(*chan->cgrp), GFP_KERNEL)))
- return -ENOMEM;
- chan->cgrp->id = chan->base.chid;
- INIT_LIST_HEAD(&chan->cgrp->head);
- INIT_LIST_HEAD(&chan->cgrp->chan);
- chan->cgrp->chan_nr = 0;
- }
-
- /* Clear channel control registers. */
- usermem = chan->base.chid * 0x200;
- ilength = order_base_2(ilength / 8);
-
- nvkm_kmap(fifo->user.mem);
- for (i = 0; i < 0x200; i += 4)
- nvkm_wo32(fifo->user.mem, usermem + i, 0x00000000);
- nvkm_done(fifo->user.mem);
- usermem = nvkm_memory_addr(fifo->user.mem) + usermem;
-
- /* RAMFC */
- nvkm_kmap(chan->base.inst);
- nvkm_wo32(chan->base.inst, 0x08, lower_32_bits(usermem));
- nvkm_wo32(chan->base.inst, 0x0c, upper_32_bits(usermem));
- nvkm_wo32(chan->base.inst, 0x10, 0x0000face);
- nvkm_wo32(chan->base.inst, 0x30, 0xfffff902);
- nvkm_wo32(chan->base.inst, 0x48, lower_32_bits(ioffset));
- nvkm_wo32(chan->base.inst, 0x4c, upper_32_bits(ioffset) |
- (ilength << 16));
- nvkm_wo32(chan->base.inst, 0x84, 0x20400000);
- nvkm_wo32(chan->base.inst, 0x94, 0x30000001);
- nvkm_wo32(chan->base.inst, 0x9c, 0x00000100);
- nvkm_wo32(chan->base.inst, 0xac, 0x0000001f);
- nvkm_wo32(chan->base.inst, 0xe4, priv ? 0x00000020 : 0x00000000);
- nvkm_wo32(chan->base.inst, 0xe8, chan->base.chid);
- nvkm_wo32(chan->base.inst, 0xb8, 0xf8000000);
- nvkm_wo32(chan->base.inst, 0xf8, 0x10003080); /* 0x002310 */
- nvkm_wo32(chan->base.inst, 0xfc, 0x10000010); /* 0x002350 */
- nvkm_done(chan->base.inst);
- return 0;
-}
-
-int
-gk104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
- void *data, u32 size, struct nvkm_object **pobject)
-{
- struct nvkm_object *parent = oclass->parent;
- union {
- struct kepler_channel_gpfifo_a_v0 v0;
- } *args = data;
- int ret = -ENOSYS;
-
- nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
- nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
- "ioffset %016llx ilength %08x "
- "runlist %016llx priv %d\n",
- args->v0.version, args->v0.vmm, args->v0.ioffset,
- args->v0.ilength, args->v0.runlist, args->v0.priv);
- return gk104_fifo_gpfifo_new_(fifo,
- &args->v0.runlist,
- &args->v0.chid,
- args->v0.vmm,
- args->v0.ioffset,
- args->v0.ilength,
- &args->v0.inst,
- args->v0.priv,
- oclass, pobject);
- }
-
- return ret;
-}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c
deleted file mode 100644
index 428f9b41165c..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c
+++ /dev/null
@@ -1,241 +0,0 @@
-/*
- * Copyright 2018 Red Hat 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 "changk104.h"
-#include "cgrp.h"
-
-#include <core/client.h>
-#include <core/gpuobj.h>
-
-#include <nvif/clc36f.h>
-#include <nvif/unpack.h>
-
-static u32
-gv100_fifo_gpfifo_submit_token(struct nvkm_fifo_chan *chan)
-{
- return chan->chid;
-}
-
-static int
-gv100_fifo_gpfifo_engine_valid(struct gk104_fifo_chan *chan, bool ce, bool valid)
-{
- struct nvkm_subdev *subdev = &chan->base.fifo->engine.subdev;
- struct nvkm_device *device = subdev->device;
- const u32 mask = ce ? 0x00020000 : 0x00010000;
- const u32 data = valid ? mask : 0x00000000;
- int ret;
-
- /* Block runlist to prevent the channel from being rescheduled. */
- mutex_lock(&chan->fifo->base.mutex);
- nvkm_mask(device, 0x002630, BIT(chan->runl), BIT(chan->runl));
-
- /* Preempt the channel. */
- ret = gk104_fifo_gpfifo_kick_locked(chan);
- if (ret == 0) {
- /* Update engine context validity. */
- nvkm_kmap(chan->base.inst);
- nvkm_mo32(chan->base.inst, 0x0ac, mask, data);
- nvkm_done(chan->base.inst);
- }
-
- /* Resume runlist. */
- nvkm_mask(device, 0x002630, BIT(chan->runl), 0);
- mutex_unlock(&chan->fifo->base.mutex);
- return ret;
-}
-
-int
-gv100_fifo_gpfifo_engine_fini(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine, bool suspend)
-{
- struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
- struct nvkm_gpuobj *inst = chan->base.inst;
- int ret;
-
- if (engine->subdev.type == NVKM_ENGINE_CE) {
- ret = gv100_fifo_gpfifo_engine_valid(chan, true, false);
- if (ret && suspend)
- return ret;
-
- nvkm_kmap(inst);
- nvkm_wo32(chan->base.inst, 0x220, 0x00000000);
- nvkm_wo32(chan->base.inst, 0x224, 0x00000000);
- nvkm_done(inst);
- return ret;
- }
-
- ret = gv100_fifo_gpfifo_engine_valid(chan, false, false);
- if (ret && suspend)
- return ret;
-
- nvkm_kmap(inst);
- nvkm_wo32(inst, 0x0210, 0x00000000);
- nvkm_wo32(inst, 0x0214, 0x00000000);
- nvkm_done(inst);
- return ret;
-}
-
-int
-gv100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base,
- struct nvkm_engine *engine)
-{
- struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
- struct gk104_fifo_engn *engn = gk104_fifo_gpfifo_engine(chan, engine);
- struct nvkm_gpuobj *inst = chan->base.inst;
-
- if (engine->subdev.type == NVKM_ENGINE_CE) {
- const u64 bar2 = nvkm_memory_bar2(engn->inst->memory);
-
- nvkm_kmap(inst);
- nvkm_wo32(chan->base.inst, 0x220, lower_32_bits(bar2));
- nvkm_wo32(chan->base.inst, 0x224, upper_32_bits(bar2));
- nvkm_done(inst);
-
- return gv100_fifo_gpfifo_engine_valid(chan, true, true);
- }
-
- nvkm_kmap(inst);
- nvkm_wo32(inst, 0x210, lower_32_bits(engn->vma->addr) | 0x00000004);
- nvkm_wo32(inst, 0x214, upper_32_bits(engn->vma->addr));
- nvkm_done(inst);
-
- return gv100_fifo_gpfifo_engine_valid(chan, false, true);
-}
-
-static const struct nvkm_fifo_chan_func
-gv100_fifo_gpfifo = {
- .dtor = gk104_fifo_gpfifo_dtor,
- .init = gk104_fifo_gpfifo_init,
- .fini = gk104_fifo_gpfifo_fini,
- .ntfy = gf100_fifo_chan_ntfy,
- .engine_ctor = gk104_fifo_gpfifo_engine_ctor,
- .engine_dtor = gk104_fifo_gpfifo_engine_dtor,
- .engine_init = gv100_fifo_gpfifo_engine_init,
- .engine_fini = gv100_fifo_gpfifo_engine_fini,
- .submit_token = gv100_fifo_gpfifo_submit_token,
-};
-
-int
-gv100_fifo_gpfifo_new_(const struct nvkm_fifo_chan_func *func,
- struct gk104_fifo *fifo, u64 *runlists, u16 *chid,
- u64 vmm, u64 ioffset, u64 ilength, u64 *inst, bool priv,
- u32 *token, const struct nvkm_oclass *oclass,
- struct nvkm_object **pobject)
-{
- struct gk104_fifo_chan *chan;
- int runlist = ffs(*runlists) -1, ret, i;
- u64 usermem;
-
- if (!vmm || runlist < 0 || runlist >= fifo->runlist_nr)
- return -EINVAL;
- *runlists = BIT_ULL(runlist);
-
- /* Allocate the channel. */
- if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
- return -ENOMEM;
- *pobject = &chan->base.object;
- chan->fifo = fifo;
- chan->runl = runlist;
- INIT_LIST_HEAD(&chan->head);
-
- ret = nvkm_fifo_chan_ctor(func, &fifo->base, 0x1000, 0x1000, true, vmm,
- 0, fifo->runlist[runlist].engm, 1, fifo->user.bar->addr, 0x200,
- oclass, &chan->base);
- if (ret)
- return ret;
-
- *chid = chan->base.chid;
- *inst = chan->base.inst->addr;
- *token = chan->base.func->submit_token(&chan->base);
-
- /* Hack to support GPUs where even individual channels should be
- * part of a channel group.
- */
- if (fifo->func->cgrp_force) {
- if (!(chan->cgrp = kmalloc(sizeof(*chan->cgrp), GFP_KERNEL)))
- return -ENOMEM;
- chan->cgrp->id = chan->base.chid;
- INIT_LIST_HEAD(&chan->cgrp->head);
- INIT_LIST_HEAD(&chan->cgrp->chan);
- chan->cgrp->chan_nr = 0;
- }
-
- /* Clear channel control registers. */
- usermem = chan->base.chid * 0x200;
- ilength = order_base_2(ilength / 8);
-
- nvkm_kmap(fifo->user.mem);
- for (i = 0; i < 0x200; i += 4)
- nvkm_wo32(fifo->user.mem, usermem + i, 0x00000000);
- nvkm_done(fifo->user.mem);
- usermem = nvkm_memory_addr(fifo->user.mem) + usermem;
-
- /* RAMFC */
- nvkm_kmap(chan->base.inst);
- nvkm_wo32(chan->base.inst, 0x008, lower_32_bits(usermem));
- nvkm_wo32(chan->base.inst, 0x00c, upper_32_bits(usermem));
- nvkm_wo32(chan->base.inst, 0x010, 0x0000face);
- nvkm_wo32(chan->base.inst, 0x030, 0x7ffff902);
- nvkm_wo32(chan->base.inst, 0x048, lower_32_bits(ioffset));
- nvkm_wo32(chan->base.inst, 0x04c, upper_32_bits(ioffset) |
- (ilength << 16));
- nvkm_wo32(chan->base.inst, 0x084, 0x20400000);
- nvkm_wo32(chan->base.inst, 0x094, 0x30000001);
- nvkm_wo32(chan->base.inst, 0x0e4, priv ? 0x00000020 : 0x00000000);
- nvkm_wo32(chan->base.inst, 0x0e8, chan->base.chid);
- nvkm_wo32(chan->base.inst, 0x0f4, 0x00001000);
- nvkm_wo32(chan->base.inst, 0x0f8, 0x10003080);
- nvkm_mo32(chan->base.inst, 0x218, 0x00000000, 0x00000000);
- nvkm_done(chan->base.inst);
- return 0;
-}
-
-int
-gv100_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
- void *data, u32 size, struct nvkm_object **pobject)
-{
- struct nvkm_object *parent = oclass->parent;
- union {
- struct volta_channel_gpfifo_a_v0 v0;
- } *args = data;
- int ret = -ENOSYS;
-
- nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
- nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
- "ioffset %016llx ilength %08x "
- "runlist %016llx priv %d\n",
- args->v0.version, args->v0.vmm, args->v0.ioffset,
- args->v0.ilength, args->v0.runlist, args->v0.priv);
- return gv100_fifo_gpfifo_new_(&gv100_fifo_gpfifo, fifo,
- &args->v0.runlist,
- &args->v0.chid,
- args->v0.vmm,
- args->v0.ioffset,
- args->v0.ilength,
- &args->v0.inst,
- args->v0.priv,
- &args->v0.token,
- oclass, pobject);
- }
-
- return ret;
-}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c
deleted file mode 100644
index d8f28ec1e4a8..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright 2012 Red Hat 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: Ben Skeggs
- */
-#include "channv50.h"
-
-#include <core/client.h>
-#include <core/ramht.h>
-
-#include <nvif/class.h>
-#include <nvif/cl506f.h>
-#include <nvif/unpack.h>
-
-static int
-nv50_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
- void *data, u32 size, struct nvkm_object **pobject)
-{
- struct nvkm_object *parent = oclass->parent;
- union {
- struct nv50_channel_gpfifo_v0 v0;
- } *args = data;
- struct nv50_fifo *fifo = nv50_fifo(base);
- struct nv50_fifo_chan *chan;
- u64 ioffset, ilength;
- int ret = -ENOSYS;
-
- nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
- nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
- "pushbuf %llx ioffset %016llx "
- "ilength %08x\n",
- args->v0.version, args->v0.vmm, args->v0.pushbuf,
- args->v0.ioffset, args->v0.ilength);
- if (!args->v0.pushbuf)
- return -EINVAL;
- } else
- return ret;
-
- if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
- return -ENOMEM;
- *pobject = &chan->base.object;
-
- ret = nv50_fifo_chan_ctor(fifo, args->v0.vmm, args->v0.pushbuf,
- oclass, chan);
- if (ret)
- return ret;
-
- args->v0.chid = chan->base.chid;
- ioffset = args->v0.ioffset;
- ilength = order_base_2(args->v0.ilength / 8);
-
- nvkm_kmap(chan->ramfc);
- nvkm_wo32(chan->ramfc, 0x3c, 0x403f6078);
- nvkm_wo32(chan->ramfc, 0x44, 0x01003fff);
- nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4);
- nvkm_wo32(chan->ramfc, 0x50, lower_32_bits(ioffset));
- nvkm_wo32(chan->ramfc, 0x54, upper_32_bits(ioffset) | (ilength << 16));
- nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff);
- nvkm_wo32(chan->ramfc, 0x78, 0x00000000);
- nvkm_wo32(chan->ramfc, 0x7c, 0x30000001);
- nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
- (4 << 24) /* SEARCH_FULL */ |
- (chan->ramht->gpuobj->node->offset >> 4));
- nvkm_done(chan->ramfc);
- return 0;
-}
-
-const struct nvkm_fifo_chan_oclass
-nv50_fifo_gpfifo_oclass = {
- .base.oclass = NV50_CHANNEL_GPFIFO,
- .base.minver = 0,
- .base.maxver = 0,
- .ctor = nv50_fifo_gpfifo_new,
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c
deleted file mode 100644
index 99aafa103a31..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2018 Red Hat 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 "changk104.h"
-#include "cgrp.h"
-
-#include <core/client.h>
-#include <core/gpuobj.h>
-
-#include <nvif/clc36f.h>
-#include <nvif/unpack.h>
-
-static u32
-tu102_fifo_gpfifo_submit_token(struct nvkm_fifo_chan *base)
-{
- struct gk104_fifo_chan *chan = gk104_fifo_chan(base);
- return (chan->runl << 16) | chan->base.chid;
-}
-
-static const struct nvkm_fifo_chan_func
-tu102_fifo_gpfifo = {
- .dtor = gk104_fifo_gpfifo_dtor,
- .init = gk104_fifo_gpfifo_init,
- .fini = gk104_fifo_gpfifo_fini,
- .ntfy = gf100_fifo_chan_ntfy,
- .engine_ctor = gk104_fifo_gpfifo_engine_ctor,
- .engine_dtor = gk104_fifo_gpfifo_engine_dtor,
- .engine_init = gv100_fifo_gpfifo_engine_init,
- .engine_fini = gv100_fifo_gpfifo_engine_fini,
- .submit_token = tu102_fifo_gpfifo_submit_token,
-};
-
-int
-tu102_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
- void *data, u32 size, struct nvkm_object **pobject)
-{
- struct nvkm_object *parent = oclass->parent;
- union {
- struct volta_channel_gpfifo_a_v0 v0;
- } *args = data;
- int ret = -ENOSYS;
-
- nvif_ioctl(parent, "create channel gpfifo size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
- nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx "
- "ioffset %016llx ilength %08x "
- "runlist %016llx priv %d\n",
- args->v0.version, args->v0.vmm, args->v0.ioffset,
- args->v0.ilength, args->v0.runlist, args->v0.priv);
- return gv100_fifo_gpfifo_new_(&tu102_fifo_gpfifo, fifo,
- &args->v0.runlist,
- &args->v0.chid,
- args->v0.vmm,
- args->v0.ioffset,
- args->v0.ilength,
- &args->v0.inst,
- args->v0.priv,
- &args->v0.token,
- oclass, pobject);
- }
-
- return ret;
-}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c
index faf0fe9f704c..33066c8cdc64 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gv100.c
@@ -19,32 +19,180 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "gk104.h"
+#include "priv.h"
+#include "chan.h"
+#include "chid.h"
#include "cgrp.h"
-#include "changk104.h"
-#include "user.h"
+#include "runl.h"
+#include "runq.h"
#include <core/gpuobj.h>
+#include <subdev/mmu.h>
#include <nvif/class.h>
+static u32
+gv100_chan_doorbell_handle(struct nvkm_chan *chan)
+{
+ return chan->id;
+}
+
+static int
+gv100_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv)
+{
+ const u64 userd = nvkm_memory_addr(chan->userd.mem) + chan->userd.base;
+ const u32 limit2 = ilog2(length / 8);
+
+ nvkm_kmap(chan->inst);
+ nvkm_wo32(chan->inst, 0x008, lower_32_bits(userd));
+ nvkm_wo32(chan->inst, 0x00c, upper_32_bits(userd));
+ nvkm_wo32(chan->inst, 0x010, 0x0000face);
+ nvkm_wo32(chan->inst, 0x030, 0x7ffff902);
+ nvkm_wo32(chan->inst, 0x048, lower_32_bits(offset));
+ nvkm_wo32(chan->inst, 0x04c, upper_32_bits(offset) | (limit2 << 16));
+ nvkm_wo32(chan->inst, 0x084, 0x20400000);
+ nvkm_wo32(chan->inst, 0x094, 0x30000000 | devm);
+ nvkm_wo32(chan->inst, 0x0e4, priv ? 0x00000020 : 0x00000000);
+ nvkm_wo32(chan->inst, 0x0e8, chan->id);
+ nvkm_wo32(chan->inst, 0x0f4, 0x00001000 | (priv ? 0x00000100 : 0x00000000));
+ nvkm_wo32(chan->inst, 0x0f8, 0x10003080);
+ nvkm_mo32(chan->inst, 0x218, 0x00000000, 0x00000000);
+ nvkm_done(chan->inst);
+ return 0;
+}
+
+const struct nvkm_chan_func_ramfc
+gv100_chan_ramfc = {
+ .write = gv100_chan_ramfc_write,
+ .devm = 0xfff,
+ .priv = true,
+};
+
+const struct nvkm_chan_func_userd
+gv100_chan_userd = {
+ .bar = -1,
+ .size = 0x200,
+ .clear = gf100_chan_userd_clear,
+};
+
+static const struct nvkm_chan_func
+gv100_chan = {
+ .inst = &gf100_chan_inst,
+ .userd = &gv100_chan_userd,
+ .ramfc = &gv100_chan_ramfc,
+ .bind = gk104_chan_bind_inst,
+ .unbind = gk104_chan_unbind,
+ .start = gk104_chan_start,
+ .stop = gk104_chan_stop,
+ .preempt = gk110_chan_preempt,
+ .doorbell_handle = gv100_chan_doorbell_handle,
+};
+
+void
+gv100_ectx_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan *chan)
+{
+ u64 addr = 0ULL;
+
+ if (cctx) {
+ addr = cctx->vctx->vma->addr;
+ addr |= 4ULL;
+ }
+
+ nvkm_kmap(chan->inst);
+ nvkm_wo32(chan->inst, 0x210, lower_32_bits(addr));
+ nvkm_wo32(chan->inst, 0x214, upper_32_bits(addr));
+ nvkm_mo32(chan->inst, 0x0ac, 0x00010000, cctx ? 0x00010000 : 0x00000000);
+ nvkm_done(chan->inst);
+}
+
+const struct nvkm_engn_func
+gv100_engn = {
+ .chsw = gk104_engn_chsw,
+ .cxid = gk104_engn_cxid,
+ .ctor = gk104_ectx_ctor,
+ .bind = gv100_ectx_bind,
+};
+
+void
+gv100_ectx_ce_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan *chan)
+{
+ const u64 bar2 = cctx ? nvkm_memory_bar2(cctx->vctx->inst->memory) : 0ULL;
+
+ nvkm_kmap(chan->inst);
+ nvkm_wo32(chan->inst, 0x220, lower_32_bits(bar2));
+ nvkm_wo32(chan->inst, 0x224, upper_32_bits(bar2));
+ nvkm_mo32(chan->inst, 0x0ac, 0x00020000, cctx ? 0x00020000 : 0x00000000);
+ nvkm_done(chan->inst);
+}
+
+int
+gv100_ectx_ce_ctor(struct nvkm_engn *engn, struct nvkm_vctx *vctx)
+{
+ if (nvkm_memory_bar2(vctx->inst->memory) == ~0ULL)
+ return -EFAULT;
+
+ return 0;
+}
+
+const struct nvkm_engn_func
+gv100_engn_ce = {
+ .chsw = gk104_engn_chsw,
+ .cxid = gk104_engn_cxid,
+ .ctor = gv100_ectx_ce_ctor,
+ .bind = gv100_ectx_ce_bind,
+};
+
+static bool
+gv100_runq_intr_1_ctxnotvalid(struct nvkm_runq *runq, int chid)
+{
+ struct nvkm_fifo *fifo = runq->fifo;
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ struct nvkm_chan *chan;
+ unsigned long flags;
+
+ RUNQ_ERROR(runq, "CTXNOTVALID chid:%d", chid);
+
+ chan = nvkm_chan_get_chid(&fifo->engine, chid, &flags);
+ if (WARN_ON_ONCE(!chan))
+ return false;
+
+ nvkm_chan_error(chan, true);
+ nvkm_chan_put(&chan, flags);
+
+ nvkm_mask(device, 0x0400ac + (runq->id * 0x2000), 0x00030000, 0x00030000);
+ nvkm_wr32(device, 0x040148 + (runq->id * 0x2000), 0x80000000);
+ return true;
+}
+
+const struct nvkm_runq_func
+gv100_runq = {
+ .init = gk208_runq_init,
+ .intr = gk104_runq_intr,
+ .intr_0_names = gk104_runq_intr_0_names,
+ .intr_1_ctxnotvalid = gv100_runq_intr_1_ctxnotvalid,
+ .idle = gk104_runq_idle,
+};
+
+void
+gv100_runl_preempt(struct nvkm_runl *runl)
+{
+ nvkm_wr32(runl->fifo->engine.subdev.device, 0x002638, BIT(runl->id));
+}
+
void
-gv100_fifo_runlist_chan(struct gk104_fifo_chan *chan,
- struct nvkm_memory *memory, u32 offset)
+gv100_runl_insert_chan(struct nvkm_chan *chan, struct nvkm_memory *memory, u64 offset)
{
- struct nvkm_memory *usermem = chan->fifo->user.mem;
- const u64 user = nvkm_memory_addr(usermem) + (chan->base.chid * 0x200);
- const u64 inst = chan->base.inst->addr;
+ const u64 user = nvkm_memory_addr(chan->userd.mem) + chan->userd.base;
+ const u64 inst = chan->inst->addr;
- nvkm_wo32(memory, offset + 0x0, lower_32_bits(user));
+ nvkm_wo32(memory, offset + 0x0, lower_32_bits(user) | chan->runq << 1);
nvkm_wo32(memory, offset + 0x4, upper_32_bits(user));
- nvkm_wo32(memory, offset + 0x8, lower_32_bits(inst) | chan->base.chid);
+ nvkm_wo32(memory, offset + 0x8, lower_32_bits(inst) | chan->id);
nvkm_wo32(memory, offset + 0xc, upper_32_bits(inst));
}
void
-gv100_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *cgrp,
- struct nvkm_memory *memory, u32 offset)
+gv100_runl_insert_cgrp(struct nvkm_cgrp *cgrp, struct nvkm_memory *memory, u64 offset)
{
nvkm_wo32(memory, offset + 0x0, (128 << 24) | (3 << 16) | 0x00000001);
nvkm_wo32(memory, offset + 0x4, cgrp->chan_nr);
@@ -52,16 +200,24 @@ gv100_fifo_runlist_cgrp(struct nvkm_fifo_cgrp *cgrp,
nvkm_wo32(memory, offset + 0xc, 0x00000000);
}
-static const struct gk104_fifo_runlist_func
-gv100_fifo_runlist = {
+static const struct nvkm_runl_func
+gv100_runl = {
+ .runqs = 2,
.size = 16,
- .cgrp = gv100_fifo_runlist_cgrp,
- .chan = gv100_fifo_runlist_chan,
- .commit = gk104_fifo_runlist_commit,
+ .update = nv50_runl_update,
+ .insert_cgrp = gv100_runl_insert_cgrp,
+ .insert_chan = gv100_runl_insert_chan,
+ .commit = gk104_runl_commit,
+ .wait = nv50_runl_wait,
+ .pending = gk104_runl_pending,
+ .block = gk104_runl_block,
+ .allow = gk104_runl_allow,
+ .preempt = gv100_runl_preempt,
+ .preempt_pending = gf100_runl_preempt_pending,
};
const struct nvkm_enum
-gv100_fifo_fault_gpcclient[] = {
+gv100_fifo_mmu_fault_gpcclient[] = {
{ 0x00, "T1_0" },
{ 0x01, "T1_1" },
{ 0x02, "T1_2" },
@@ -163,7 +319,7 @@ gv100_fifo_fault_gpcclient[] = {
};
const struct nvkm_enum
-gv100_fifo_fault_hubclient[] = {
+gv100_fifo_mmu_fault_hubclient[] = {
{ 0x00, "VIP" },
{ 0x01, "CE0" },
{ 0x02, "CE1" },
@@ -225,7 +381,7 @@ gv100_fifo_fault_hubclient[] = {
};
const struct nvkm_enum
-gv100_fifo_fault_reason[] = {
+gv100_fifo_mmu_fault_reason[] = {
{ 0x00, "PDE" },
{ 0x01, "PDE_SIZE" },
{ 0x02, "PTE" },
@@ -246,7 +402,7 @@ gv100_fifo_fault_reason[] = {
};
static const struct nvkm_enum
-gv100_fifo_fault_engine[] = {
+gv100_fifo_mmu_fault_engine[] = {
{ 0x01, "DISPLAY" },
{ 0x03, "PTP" },
{ 0x04, "BAR1", NULL, NVKM_SUBDEV_BAR },
@@ -273,7 +429,7 @@ gv100_fifo_fault_engine[] = {
};
const struct nvkm_enum
-gv100_fifo_fault_access[] = {
+gv100_fifo_mmu_fault_access[] = {
{ 0x0, "VIRT_READ" },
{ 0x1, "VIRT_WRITE" },
{ 0x2, "VIRT_ATOMIC" },
@@ -286,23 +442,51 @@ gv100_fifo_fault_access[] = {
{}
};
-static const struct gk104_fifo_func
+static const struct nvkm_fifo_func_mmu_fault
+gv100_fifo_mmu_fault = {
+ .recover = gf100_fifo_mmu_fault_recover,
+ .access = gv100_fifo_mmu_fault_access,
+ .engine = gv100_fifo_mmu_fault_engine,
+ .reason = gv100_fifo_mmu_fault_reason,
+ .hubclient = gv100_fifo_mmu_fault_hubclient,
+ .gpcclient = gv100_fifo_mmu_fault_gpcclient,
+};
+
+static void
+gv100_fifo_intr_ctxsw_timeout(struct nvkm_fifo *fifo, u32 engm)
+{
+ struct nvkm_runl *runl;
+ struct nvkm_engn *engn;
+
+ nvkm_runl_foreach(runl, fifo) {
+ nvkm_runl_foreach_engn_cond(engn, runl, engm & BIT(engn->id))
+ nvkm_runl_rc_engn(runl, engn);
+ }
+}
+
+static const struct nvkm_fifo_func
gv100_fifo = {
- .pbdma = &gm200_fifo_pbdma,
- .fault.access = gv100_fifo_fault_access,
- .fault.engine = gv100_fifo_fault_engine,
- .fault.reason = gv100_fifo_fault_reason,
- .fault.hubclient = gv100_fifo_fault_hubclient,
- .fault.gpcclient = gv100_fifo_fault_gpcclient,
- .runlist = &gv100_fifo_runlist,
- .user = {{-1,-1,VOLTA_USERMODE_A }, gv100_fifo_user_new },
- .chan = {{ 0, 0,VOLTA_CHANNEL_GPFIFO_A}, gv100_fifo_gpfifo_new },
- .cgrp_force = true,
+ .chid_nr = gm200_fifo_chid_nr,
+ .chid_ctor = gk110_fifo_chid_ctor,
+ .runq_nr = gm200_fifo_runq_nr,
+ .runl_ctor = gk104_fifo_runl_ctor,
+ .init = gk104_fifo_init,
+ .init_pbdmas = gk104_fifo_init_pbdmas,
+ .intr = gk104_fifo_intr,
+ .intr_ctxsw_timeout = gv100_fifo_intr_ctxsw_timeout,
+ .mmu_fault = &gv100_fifo_mmu_fault,
+ .nonstall = &gf100_fifo_nonstall,
+ .runl = &gv100_runl,
+ .runq = &gv100_runq,
+ .engn = &gv100_engn,
+ .engn_ce = &gv100_engn_ce,
+ .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true },
+ .chan = {{ 0, 0, VOLTA_CHANNEL_GPFIFO_A }, &gv100_chan },
};
int
gv100_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
- return gk104_fifo_new_(&gv100_fifo, device, type, inst, 4096, pfifo);
+ return nvkm_fifo_new_(&gv100_fifo, device, type, inst, pfifo);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c
index c6730c124769..674faf002b20 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.c
@@ -21,38 +21,201 @@
*
* Authors: Ben Skeggs
*/
-#include "nv04.h"
-#include "channv04.h"
+#include "priv.h"
+#include "cgrp.h"
+#include "chan.h"
+#include "chid.h"
+#include "runl.h"
+
#include "regsnv04.h"
-#include <core/client.h>
#include <core/ramht.h>
#include <subdev/instmem.h>
+#include <subdev/mc.h>
#include <subdev/timer.h>
#include <engine/sw.h>
-static const struct nv04_fifo_ramfc
-nv04_fifo_ramfc[] = {
- { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT },
- { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET },
- { 16, 0, 0x08, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE },
- { 16, 16, 0x08, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT },
- { 32, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_STATE },
- { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_FETCH },
- { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_ENGINE },
- { 32, 0, 0x18, 0, NV04_PFIFO_CACHE1_PULL1 },
- {}
+#include <nvif/class.h>
+
+void
+nv04_chan_stop(struct nvkm_chan *chan)
+{
+ struct nvkm_fifo *fifo = chan->cgrp->runl->fifo;
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ struct nvkm_memory *fctx = device->imem->ramfc;
+ const struct nvkm_ramfc_layout *c;
+ unsigned long flags;
+ u32 data = chan->ramfc_offset;
+ u32 chid;
+
+ /* prevent fifo context switches */
+ spin_lock_irqsave(&fifo->lock, flags);
+ nvkm_wr32(device, NV03_PFIFO_CACHES, 0);
+
+ /* if this channel is active, replace it with a null context */
+ chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & fifo->chid->mask;
+ if (chid == chan->id) {
+ nvkm_mask(device, NV04_PFIFO_CACHE1_DMA_PUSH, 0x00000001, 0);
+ nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 0);
+ nvkm_mask(device, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0);
+
+ c = chan->func->ramfc->layout;
+ nvkm_kmap(fctx);
+ do {
+ u32 rm = ((1ULL << c->bits) - 1) << c->regs;
+ u32 cm = ((1ULL << c->bits) - 1) << c->ctxs;
+ u32 rv = (nvkm_rd32(device, c->regp) & rm) >> c->regs;
+ u32 cv = (nvkm_ro32(fctx, c->ctxp + data) & ~cm);
+ nvkm_wo32(fctx, c->ctxp + data, cv | (rv << c->ctxs));
+ } while ((++c)->bits);
+ nvkm_done(fctx);
+
+ c = chan->func->ramfc->layout;
+ do {
+ nvkm_wr32(device, c->regp, 0x00000000);
+ } while ((++c)->bits);
+
+ nvkm_wr32(device, NV03_PFIFO_CACHE1_GET, 0);
+ nvkm_wr32(device, NV03_PFIFO_CACHE1_PUT, 0);
+ nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->chid->mask);
+ nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH0, 1);
+ nvkm_wr32(device, NV04_PFIFO_CACHE1_PULL0, 1);
+ }
+
+ /* restore normal operation, after disabling dma mode */
+ nvkm_mask(device, NV04_PFIFO_MODE, BIT(chan->id), 0);
+ nvkm_wr32(device, NV03_PFIFO_CACHES, 1);
+ spin_unlock_irqrestore(&fifo->lock, flags);
+}
+
+void
+nv04_chan_start(struct nvkm_chan *chan)
+{
+ struct nvkm_fifo *fifo = chan->cgrp->runl->fifo;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fifo->lock, flags);
+ nvkm_mask(fifo->engine.subdev.device, NV04_PFIFO_MODE, BIT(chan->id), BIT(chan->id));
+ spin_unlock_irqrestore(&fifo->lock, flags);
+}
+
+void
+nv04_chan_ramfc_clear(struct nvkm_chan *chan)
+{
+ struct nvkm_memory *ramfc = chan->cgrp->runl->fifo->engine.subdev.device->imem->ramfc;
+ const struct nvkm_ramfc_layout *c = chan->func->ramfc->layout;
+
+ nvkm_kmap(ramfc);
+ do {
+ nvkm_wo32(ramfc, chan->ramfc_offset + c->ctxp, 0x00000000);
+ } while ((++c)->bits);
+ nvkm_done(ramfc);
+}
+
+static int
+nv04_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv)
+{
+ struct nvkm_memory *ramfc = chan->cgrp->runl->fifo->engine.subdev.device->imem->ramfc;
+ const u32 base = chan->id * 32;
+
+ chan->ramfc_offset = base;
+
+ nvkm_kmap(ramfc);
+ nvkm_wo32(ramfc, base + 0x00, offset);
+ nvkm_wo32(ramfc, base + 0x04, offset);
+ nvkm_wo32(ramfc, base + 0x08, chan->push->addr >> 4);
+ nvkm_wo32(ramfc, base + 0x10, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
+ NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
+#ifdef __BIG_ENDIAN
+ NV_PFIFO_CACHE1_BIG_ENDIAN |
+#endif
+ NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8);
+ nvkm_done(ramfc);
+ return 0;
+}
+
+static const struct nvkm_chan_func_ramfc
+nv04_chan_ramfc = {
+ .layout = (const struct nvkm_ramfc_layout[]) {
+ { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT },
+ { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET },
+ { 16, 0, 0x08, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE },
+ { 16, 16, 0x08, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT },
+ { 32, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_STATE },
+ { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_FETCH },
+ { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_ENGINE },
+ { 32, 0, 0x18, 0, NV04_PFIFO_CACHE1_PULL1 },
+ {}
+ },
+ .write = nv04_chan_ramfc_write,
+ .clear = nv04_chan_ramfc_clear,
+ .ctxdma = true,
+};
+
+const struct nvkm_chan_func_userd
+nv04_chan_userd = {
+ .bar = 0,
+ .base = 0x800000,
+ .size = 0x010000,
+};
+
+const struct nvkm_chan_func_inst
+nv04_chan_inst = {
+ .size = 0x1000,
+};
+
+static const struct nvkm_chan_func
+nv04_chan = {
+ .inst = &nv04_chan_inst,
+ .userd = &nv04_chan_userd,
+ .ramfc = &nv04_chan_ramfc,
+ .start = nv04_chan_start,
+ .stop = nv04_chan_stop,
+};
+
+const struct nvkm_cgrp_func
+nv04_cgrp = {
+};
+
+void
+nv04_eobj_ramht_del(struct nvkm_chan *chan, int hash)
+{
+ struct nvkm_fifo *fifo = chan->cgrp->runl->fifo;
+ struct nvkm_instmem *imem = fifo->engine.subdev.device->imem;
+
+ mutex_lock(&fifo->mutex);
+ nvkm_ramht_remove(imem->ramht, hash);
+ mutex_unlock(&fifo->mutex);
+}
+
+static int
+nv04_eobj_ramht_add(struct nvkm_engn *engn, struct nvkm_object *eobj, struct nvkm_chan *chan)
+{
+ struct nvkm_fifo *fifo = chan->cgrp->runl->fifo;
+ struct nvkm_instmem *imem = fifo->engine.subdev.device->imem;
+ u32 context = 0x80000000 | chan->id << 24 | engn->id << 16;
+ int hash;
+
+ mutex_lock(&fifo->mutex);
+ hash = nvkm_ramht_insert(imem->ramht, eobj, chan->id, 4, eobj->handle, context);
+ mutex_unlock(&fifo->mutex);
+ return hash;
+}
+
+const struct nvkm_engn_func
+nv04_engn = {
+ .ramht_add = nv04_eobj_ramht_add,
+ .ramht_del = nv04_eobj_ramht_del,
};
void
-nv04_fifo_pause(struct nvkm_fifo *base, unsigned long *pflags)
-__acquires(fifo->base.lock)
+nv04_fifo_pause(struct nvkm_fifo *fifo, unsigned long *pflags)
+__acquires(fifo->lock)
{
- struct nv04_fifo *fifo = nv04_fifo(base);
- struct nvkm_device *device = fifo->base.engine.subdev.device;
+ struct nvkm_device *device = fifo->engine.subdev.device;
unsigned long flags;
- spin_lock_irqsave(&fifo->base.lock, flags);
+ spin_lock_irqsave(&fifo->lock, flags);
*pflags = flags;
nvkm_wr32(device, NV03_PFIFO_CACHES, 0x00000000);
@@ -81,50 +244,21 @@ __acquires(fifo->base.lock)
}
void
-nv04_fifo_start(struct nvkm_fifo *base, unsigned long *pflags)
-__releases(fifo->base.lock)
+nv04_fifo_start(struct nvkm_fifo *fifo, unsigned long *pflags)
+__releases(fifo->lock)
{
- struct nv04_fifo *fifo = nv04_fifo(base);
- struct nvkm_device *device = fifo->base.engine.subdev.device;
+ struct nvkm_device *device = fifo->engine.subdev.device;
unsigned long flags = *pflags;
nvkm_mask(device, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0x00000001);
nvkm_wr32(device, NV03_PFIFO_CACHES, 0x00000001);
- spin_unlock_irqrestore(&fifo->base.lock, flags);
+ spin_unlock_irqrestore(&fifo->lock, flags);
}
-struct nvkm_engine *
-nv04_fifo_id_engine(struct nvkm_fifo *fifo, int engi)
-{
- enum nvkm_subdev_type type;
-
- switch (engi) {
- case NV04_FIFO_ENGN_SW : type = NVKM_ENGINE_SW; break;
- case NV04_FIFO_ENGN_GR : type = NVKM_ENGINE_GR; break;
- case NV04_FIFO_ENGN_MPEG: type = NVKM_ENGINE_MPEG; break;
- case NV04_FIFO_ENGN_DMA : type = NVKM_ENGINE_DMAOBJ; break;
- default:
- WARN_ON(1);
- return NULL;
- }
-
- return nvkm_device_engine(fifo->engine.subdev.device, type, 0);
-}
-
-int
-nv04_fifo_engine_id(struct nvkm_fifo *base, struct nvkm_engine *engine)
-{
- switch (engine->subdev.type) {
- case NVKM_ENGINE_SW : return NV04_FIFO_ENGN_SW;
- case NVKM_ENGINE_GR : return NV04_FIFO_ENGN_GR;
- case NVKM_ENGINE_MPEG : return NV04_FIFO_ENGN_MPEG;
- case NVKM_ENGINE_DMAOBJ: return NV04_FIFO_ENGN_DMA;
- default:
- WARN_ON(1);
- return 0;
- }
-}
+const struct nvkm_runl_func
+nv04_runl = {
+};
static const char *
nv_dma_state_err(u32 state)
@@ -166,11 +300,11 @@ nv04_fifo_swmthd(struct nvkm_device *device, u32 chid, u32 addr, u32 data)
}
static void
-nv04_fifo_cache_error(struct nv04_fifo *fifo, u32 chid, u32 get)
+nv04_fifo_intr_cache_error(struct nvkm_fifo *fifo, u32 chid, u32 get)
{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
+ struct nvkm_subdev *subdev = &fifo->engine.subdev;
struct nvkm_device *device = subdev->device;
- struct nvkm_fifo_chan *chan;
+ struct nvkm_chan *chan;
unsigned long flags;
u32 pull0 = nvkm_rd32(device, 0x003250);
u32 mthd, data;
@@ -193,12 +327,12 @@ nv04_fifo_cache_error(struct nv04_fifo *fifo, u32 chid, u32 get)
if (!(pull0 & 0x00000100) ||
!nv04_fifo_swmthd(device, chid, mthd, data)) {
- chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags);
+ chan = nvkm_chan_get_chid(&fifo->engine, chid, &flags);
nvkm_error(subdev, "CACHE_ERROR - "
"ch %d [%s] subc %d mthd %04x data %08x\n",
- chid, chan ? chan->object.client->name : "unknown",
+ chid, chan ? chan->name : "unknown",
(mthd >> 13) & 7, mthd & 0x1ffc, data);
- nvkm_fifo_chan_put(&fifo->base, flags, &chan);
+ nvkm_chan_put(&chan, flags);
}
nvkm_wr32(device, NV04_PFIFO_CACHE1_DMA_PUSH, 0);
@@ -217,20 +351,20 @@ nv04_fifo_cache_error(struct nv04_fifo *fifo, u32 chid, u32 get)
}
static void
-nv04_fifo_dma_pusher(struct nv04_fifo *fifo, u32 chid)
+nv04_fifo_intr_dma_pusher(struct nvkm_fifo *fifo, u32 chid)
{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
+ struct nvkm_subdev *subdev = &fifo->engine.subdev;
struct nvkm_device *device = subdev->device;
u32 dma_get = nvkm_rd32(device, 0x003244);
u32 dma_put = nvkm_rd32(device, 0x003240);
u32 push = nvkm_rd32(device, 0x003220);
u32 state = nvkm_rd32(device, 0x003228);
- struct nvkm_fifo_chan *chan;
+ struct nvkm_chan *chan;
unsigned long flags;
const char *name;
- chan = nvkm_fifo_chan_chid(&fifo->base, chid, &flags);
- name = chan ? chan->object.client->name : "unknown";
+ chan = nvkm_chan_get_chid(&fifo->engine, chid, &flags);
+ name = chan ? chan->name : "unknown";
if (device->card_type == NV_50) {
u32 ho_get = nvkm_rd32(device, 0x003328);
u32 ho_put = nvkm_rd32(device, 0x003320);
@@ -261,18 +395,18 @@ nv04_fifo_dma_pusher(struct nv04_fifo *fifo, u32 chid)
if (dma_get != dma_put)
nvkm_wr32(device, 0x003244, dma_put);
}
- nvkm_fifo_chan_put(&fifo->base, flags, &chan);
+ nvkm_chan_put(&chan, flags);
nvkm_wr32(device, 0x003228, 0x00000000);
nvkm_wr32(device, 0x003220, 0x00000001);
nvkm_wr32(device, 0x002100, NV_PFIFO_INTR_DMA_PUSHER);
}
-void
-nv04_fifo_intr(struct nvkm_fifo *base)
+irqreturn_t
+nv04_fifo_intr(struct nvkm_inth *inth)
{
- struct nv04_fifo *fifo = nv04_fifo(base);
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
+ struct nvkm_fifo *fifo = container_of(inth, typeof(*fifo), engine.subdev.inth);
+ struct nvkm_subdev *subdev = &fifo->engine.subdev;
struct nvkm_device *device = subdev->device;
u32 mask = nvkm_rd32(device, NV03_PFIFO_INTR_EN_0);
u32 stat = nvkm_rd32(device, NV03_PFIFO_INTR_0) & mask;
@@ -281,16 +415,16 @@ nv04_fifo_intr(struct nvkm_fifo *base)
reassign = nvkm_rd32(device, NV03_PFIFO_CACHES) & 1;
nvkm_wr32(device, NV03_PFIFO_CACHES, 0);
- chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & (fifo->base.nr - 1);
+ chid = nvkm_rd32(device, NV03_PFIFO_CACHE1_PUSH1) & fifo->chid->mask;
get = nvkm_rd32(device, NV03_PFIFO_CACHE1_GET);
if (stat & NV_PFIFO_INTR_CACHE_ERROR) {
- nv04_fifo_cache_error(fifo, chid, get);
+ nv04_fifo_intr_cache_error(fifo, chid, get);
stat &= ~NV_PFIFO_INTR_CACHE_ERROR;
}
if (stat & NV_PFIFO_INTR_DMA_PUSHER) {
- nv04_fifo_dma_pusher(fifo, chid);
+ nv04_fifo_intr_dma_pusher(fifo, chid);
stat &= ~NV_PFIFO_INTR_DMA_PUSHER;
}
@@ -313,7 +447,7 @@ nv04_fifo_intr(struct nvkm_fifo *base)
if (stat & 0x40000000) {
nvkm_wr32(device, 0x002100, 0x40000000);
- nvkm_fifo_uevent(&fifo->base);
+ nvkm_event_ntfy(&fifo->nonstall.event, 0, NVKM_FIFO_NONSTALL_EVENT);
stat &= ~0x40000000;
}
}
@@ -325,13 +459,13 @@ nv04_fifo_intr(struct nvkm_fifo *base)
}
nvkm_wr32(device, NV03_PFIFO_CACHES, reassign);
+ return IRQ_HANDLED;
}
void
-nv04_fifo_init(struct nvkm_fifo *base)
+nv04_fifo_init(struct nvkm_fifo *fifo)
{
- struct nv04_fifo *fifo = nv04_fifo(base);
- struct nvkm_device *device = fifo->base.engine.subdev.device;
+ struct nvkm_device *device = fifo->engine.subdev.device;
struct nvkm_instmem *imem = device->imem;
struct nvkm_ramht *ramht = imem->ramht;
struct nvkm_memory *ramro = imem->ramro;
@@ -346,7 +480,7 @@ nv04_fifo_init(struct nvkm_fifo *base)
nvkm_wr32(device, NV03_PFIFO_RAMRO, nvkm_memory_addr(ramro) >> 8);
nvkm_wr32(device, NV03_PFIFO_RAMFC, nvkm_memory_addr(ramfc) >> 8);
- nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.nr - 1);
+ nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->chid->mask);
nvkm_wr32(device, NV03_PFIFO_INTR_0, 0xffffffff);
nvkm_wr32(device, NV03_PFIFO_INTR_EN_0, 0xffffffff);
@@ -357,43 +491,53 @@ nv04_fifo_init(struct nvkm_fifo *base)
}
int
-nv04_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device,
- enum nvkm_subdev_type type, int inst, int nr, const struct nv04_fifo_ramfc *ramfc,
- struct nvkm_fifo **pfifo)
+nv04_fifo_runl_ctor(struct nvkm_fifo *fifo)
{
- struct nv04_fifo *fifo;
- int ret;
-
- if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
- return -ENOMEM;
- fifo->ramfc = ramfc;
- *pfifo = &fifo->base;
+ struct nvkm_runl *runl;
- ret = nvkm_fifo_ctor(func, device, type, inst, nr, &fifo->base);
- if (ret)
- return ret;
+ runl = nvkm_runl_new(fifo, 0, 0, 0);
+ if (IS_ERR(runl))
+ return PTR_ERR(runl);
- set_bit(nr - 1, fifo->base.mask); /* inactive channel */
+ nvkm_runl_add(runl, 0, fifo->func->engn_sw, NVKM_ENGINE_SW, 0);
+ nvkm_runl_add(runl, 0, fifo->func->engn_sw, NVKM_ENGINE_DMAOBJ, 0);
+ nvkm_runl_add(runl, 1, fifo->func->engn , NVKM_ENGINE_GR, 0);
+ nvkm_runl_add(runl, 2, fifo->func->engn , NVKM_ENGINE_MPEG, 0); /* NV31- */
return 0;
}
+int
+nv04_fifo_chid_ctor(struct nvkm_fifo *fifo, int nr)
+{
+ /* The last CHID is reserved by HW as a "channel invalid" marker. */
+ return nvkm_chid_new(&nvkm_chan_event, &fifo->engine.subdev, nr, 0, nr - 1, &fifo->chid);
+}
+
+static int
+nv04_fifo_chid_nr(struct nvkm_fifo *fifo)
+{
+ return 16;
+}
+
static const struct nvkm_fifo_func
nv04_fifo = {
+ .chid_nr = nv04_fifo_chid_nr,
+ .chid_ctor = nv04_fifo_chid_ctor,
+ .runl_ctor = nv04_fifo_runl_ctor,
.init = nv04_fifo_init,
.intr = nv04_fifo_intr,
- .engine_id = nv04_fifo_engine_id,
- .id_engine = nv04_fifo_id_engine,
.pause = nv04_fifo_pause,
.start = nv04_fifo_start,
- .chan = {
- &nv04_fifo_dma_oclass,
- NULL
- },
+ .runl = &nv04_runl,
+ .engn = &nv04_engn,
+ .engn_sw = &nv04_engn,
+ .cgrp = {{ }, &nv04_cgrp },
+ .chan = {{ 0, 0, NV03_CHANNEL_DMA }, &nv04_chan },
};
int
nv04_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
- return nv04_fifo_new_(&nv04_fifo, device, type, inst, 16, nv04_fifo_ramfc, pfifo);
+ return nvkm_fifo_new_(&nv04_fifo, device, type, inst, pfifo);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h
deleted file mode 100644
index 3f23bcde4a54..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv04.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-#ifndef __NV04_FIFO_H__
-#define __NV04_FIFO_H__
-#define nv04_fifo(p) container_of((p), struct nv04_fifo, base)
-#include "priv.h"
-
-struct nv04_fifo_ramfc {
- unsigned bits:6;
- unsigned ctxs:5;
- unsigned ctxp:8;
- unsigned regs:5;
- unsigned regp;
-};
-
-struct nv04_fifo {
- struct nvkm_fifo base;
- const struct nv04_fifo_ramfc *ramfc;
-};
-
-int nv04_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int,
- int nr, const struct nv04_fifo_ramfc *, struct nvkm_fifo **);
-void nv04_fifo_init(struct nvkm_fifo *);
-#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c
index f8887f0f2f82..a4bcf6b0a7e2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv10.c
@@ -21,41 +21,93 @@
*
* Authors: Ben Skeggs
*/
-#include "nv04.h"
-#include "channv04.h"
+#include "priv.h"
+#include "cgrp.h"
+#include "chan.h"
+#include "runl.h"
+
+#include <core/gpuobj.h>
+#include <subdev/instmem.h>
+
#include "regsnv04.h"
-static const struct nv04_fifo_ramfc
-nv10_fifo_ramfc[] = {
- { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT },
- { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET },
- { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT },
- { 16, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE },
- { 16, 16, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT },
- { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_STATE },
- { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_DMA_FETCH },
- { 32, 0, 0x18, 0, NV04_PFIFO_CACHE1_ENGINE },
- { 32, 0, 0x1c, 0, NV04_PFIFO_CACHE1_PULL1 },
- {}
+#include <nvif/class.h>
+
+static int
+nv10_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv)
+{
+ struct nvkm_memory *ramfc = chan->cgrp->runl->fifo->engine.subdev.device->imem->ramfc;
+ const u32 base = chan->id * 32;
+
+ chan->ramfc_offset = base;
+
+ nvkm_kmap(ramfc);
+ nvkm_wo32(ramfc, base + 0x00, offset);
+ nvkm_wo32(ramfc, base + 0x04, offset);
+ nvkm_wo32(ramfc, base + 0x0c, chan->push->addr >> 4);
+ nvkm_wo32(ramfc, base + 0x14, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
+ NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
+#ifdef __BIG_ENDIAN
+ NV_PFIFO_CACHE1_BIG_ENDIAN |
+#endif
+ NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8);
+ nvkm_done(ramfc);
+ return 0;
+}
+
+static const struct nvkm_chan_func_ramfc
+nv10_chan_ramfc = {
+ .layout = (const struct nvkm_ramfc_layout[]) {
+ { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT },
+ { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET },
+ { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT },
+ { 16, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE },
+ { 16, 16, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT },
+ { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_STATE },
+ { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_DMA_FETCH },
+ { 32, 0, 0x18, 0, NV04_PFIFO_CACHE1_ENGINE },
+ { 32, 0, 0x1c, 0, NV04_PFIFO_CACHE1_PULL1 },
+ {}
+ },
+ .write = nv10_chan_ramfc_write,
+ .clear = nv04_chan_ramfc_clear,
+ .ctxdma = true,
+};
+
+static const struct nvkm_chan_func
+nv10_chan = {
+ .inst = &nv04_chan_inst,
+ .userd = &nv04_chan_userd,
+ .ramfc = &nv10_chan_ramfc,
+ .start = nv04_chan_start,
+ .stop = nv04_chan_stop,
};
+int
+nv10_fifo_chid_nr(struct nvkm_fifo *fifo)
+{
+ return 32;
+}
+
static const struct nvkm_fifo_func
nv10_fifo = {
+ .chid_nr = nv10_fifo_chid_nr,
+ .chid_ctor = nv04_fifo_chid_ctor,
+ .runl_ctor = nv04_fifo_runl_ctor,
.init = nv04_fifo_init,
.intr = nv04_fifo_intr,
- .engine_id = nv04_fifo_engine_id,
- .id_engine = nv04_fifo_id_engine,
.pause = nv04_fifo_pause,
.start = nv04_fifo_start,
- .chan = {
- &nv10_fifo_dma_oclass,
- NULL
- },
+ .runl = &nv04_runl,
+ .engn = &nv04_engn,
+ .engn_sw = &nv04_engn,
+ .cgrp = {{ }, &nv04_cgrp },
+ .chan = {{ 0, 0, NV10_CHANNEL_DMA }, &nv10_chan },
};
int
nv10_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
- return nv04_fifo_new_(&nv10_fifo, device, type, inst, 32, nv10_fifo_ramfc, pfifo);
+ return nvkm_fifo_new_(&nv10_fifo, device, type, inst, pfifo);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c
index 3f94c7b5b054..c70f44fd4f3b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv17.c
@@ -21,37 +21,78 @@
*
* Authors: Ben Skeggs
*/
-#include "nv04.h"
-#include "channv04.h"
+#include "priv.h"
+#include "cgrp.h"
+#include "chan.h"
+#include "chid.h"
+#include "runl.h"
+
#include "regsnv04.h"
#include <core/ramht.h>
#include <subdev/instmem.h>
-static const struct nv04_fifo_ramfc
-nv17_fifo_ramfc[] = {
- { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT },
- { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET },
- { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT },
- { 16, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE },
- { 16, 16, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT },
- { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_STATE },
- { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_DMA_FETCH },
- { 32, 0, 0x18, 0, NV04_PFIFO_CACHE1_ENGINE },
- { 32, 0, 0x1c, 0, NV04_PFIFO_CACHE1_PULL1 },
- { 32, 0, 0x20, 0, NV10_PFIFO_CACHE1_ACQUIRE_VALUE },
- { 32, 0, 0x24, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP },
- { 32, 0, 0x28, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT },
- { 32, 0, 0x2c, 0, NV10_PFIFO_CACHE1_SEMAPHORE },
- { 32, 0, 0x30, 0, NV10_PFIFO_CACHE1_DMA_SUBROUTINE },
- {}
+#include <nvif/class.h>
+
+static int
+nv17_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv)
+{
+ struct nvkm_memory *ramfc = chan->cgrp->runl->fifo->engine.subdev.device->imem->ramfc;
+ const u32 base = chan->id * 64;
+
+ chan->ramfc_offset = base;
+
+ nvkm_kmap(ramfc);
+ nvkm_wo32(ramfc, base + 0x00, offset);
+ nvkm_wo32(ramfc, base + 0x04, offset);
+ nvkm_wo32(ramfc, base + 0x0c, chan->push->addr >> 4);
+ nvkm_wo32(ramfc, base + 0x14, NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
+ NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
+#ifdef __BIG_ENDIAN
+ NV_PFIFO_CACHE1_BIG_ENDIAN |
+#endif
+ NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8);
+ nvkm_done(ramfc);
+ return 0;
+}
+
+static const struct nvkm_chan_func_ramfc
+nv17_chan_ramfc = {
+ .layout = (const struct nvkm_ramfc_layout[]) {
+ { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT },
+ { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET },
+ { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT },
+ { 16, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE },
+ { 16, 16, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT },
+ { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_STATE },
+ { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_DMA_FETCH },
+ { 32, 0, 0x18, 0, NV04_PFIFO_CACHE1_ENGINE },
+ { 32, 0, 0x1c, 0, NV04_PFIFO_CACHE1_PULL1 },
+ { 32, 0, 0x20, 0, NV10_PFIFO_CACHE1_ACQUIRE_VALUE },
+ { 32, 0, 0x24, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP },
+ { 32, 0, 0x28, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT },
+ { 32, 0, 0x2c, 0, NV10_PFIFO_CACHE1_SEMAPHORE },
+ { 32, 0, 0x30, 0, NV10_PFIFO_CACHE1_DMA_SUBROUTINE },
+ {}
+ },
+ .write = nv17_chan_ramfc_write,
+ .clear = nv04_chan_ramfc_clear,
+ .ctxdma = true,
+};
+
+static const struct nvkm_chan_func
+nv17_chan = {
+ .inst = &nv04_chan_inst,
+ .userd = &nv04_chan_userd,
+ .ramfc = &nv17_chan_ramfc,
+ .start = nv04_chan_start,
+ .stop = nv04_chan_stop,
};
static void
-nv17_fifo_init(struct nvkm_fifo *base)
+nv17_fifo_init(struct nvkm_fifo *fifo)
{
- struct nv04_fifo *fifo = nv04_fifo(base);
- struct nvkm_device *device = fifo->base.engine.subdev.device;
+ struct nvkm_device *device = fifo->engine.subdev.device;
struct nvkm_instmem *imem = device->imem;
struct nvkm_ramht *ramht = imem->ramht;
struct nvkm_memory *ramro = imem->ramro;
@@ -67,7 +108,7 @@ nv17_fifo_init(struct nvkm_fifo *base)
nvkm_wr32(device, NV03_PFIFO_RAMFC, nvkm_memory_addr(ramfc) >> 8 |
0x00010000);
- nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.nr - 1);
+ nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->chid->mask);
nvkm_wr32(device, NV03_PFIFO_INTR_0, 0xffffffff);
nvkm_wr32(device, NV03_PFIFO_INTR_EN_0, 0xffffffff);
@@ -79,21 +120,23 @@ nv17_fifo_init(struct nvkm_fifo *base)
static const struct nvkm_fifo_func
nv17_fifo = {
+ .chid_nr = nv10_fifo_chid_nr,
+ .chid_ctor = nv04_fifo_chid_ctor,
+ .runl_ctor = nv04_fifo_runl_ctor,
.init = nv17_fifo_init,
.intr = nv04_fifo_intr,
- .engine_id = nv04_fifo_engine_id,
- .id_engine = nv04_fifo_id_engine,
.pause = nv04_fifo_pause,
.start = nv04_fifo_start,
- .chan = {
- &nv17_fifo_dma_oclass,
- NULL
- },
+ .runl = &nv04_runl,
+ .engn = &nv04_engn,
+ .engn_sw = &nv04_engn,
+ .cgrp = {{ }, &nv04_cgrp },
+ .chan = {{ 0, 0, NV17_CHANNEL_DMA }, &nv17_chan },
};
int
nv17_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
- return nv04_fifo_new_(&nv17_fifo, device, type, inst, 32, nv17_fifo_ramfc, pfifo);
+ return nvkm_fifo_new_(&nv17_fifo, device, type, inst, pfifo);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c
index f9ea46809bc0..e50a94b6d7f8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv40.c
@@ -21,46 +21,166 @@
*
* Authors: Ben Skeggs
*/
-#include "nv04.h"
-#include "channv04.h"
+#include "priv.h"
+#include "cgrp.h"
+#include "chan.h"
+#include "chid.h"
+#include "runl.h"
+
#include "regsnv04.h"
#include <core/ramht.h>
#include <subdev/fb.h>
#include <subdev/instmem.h>
-static const struct nv04_fifo_ramfc
-nv40_fifo_ramfc[] = {
- { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT },
- { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET },
- { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT },
- { 32, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE },
- { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT },
- { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_DMA_STATE },
- { 28, 0, 0x18, 0, NV04_PFIFO_CACHE1_DMA_FETCH },
- { 2, 28, 0x18, 28, 0x002058 },
- { 32, 0, 0x1c, 0, NV04_PFIFO_CACHE1_ENGINE },
- { 32, 0, 0x20, 0, NV04_PFIFO_CACHE1_PULL1 },
- { 32, 0, 0x24, 0, NV10_PFIFO_CACHE1_ACQUIRE_VALUE },
- { 32, 0, 0x28, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP },
- { 32, 0, 0x2c, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT },
- { 32, 0, 0x30, 0, NV10_PFIFO_CACHE1_SEMAPHORE },
- { 32, 0, 0x34, 0, NV10_PFIFO_CACHE1_DMA_SUBROUTINE },
- { 32, 0, 0x38, 0, NV40_PFIFO_GRCTX_INSTANCE },
- { 17, 0, 0x3c, 0, NV04_PFIFO_DMA_TIMESLICE },
- { 32, 0, 0x40, 0, 0x0032e4 },
- { 32, 0, 0x44, 0, 0x0032e8 },
- { 32, 0, 0x4c, 0, 0x002088 },
- { 32, 0, 0x50, 0, 0x003300 },
- { 32, 0, 0x54, 0, 0x00330c },
- {}
+#include <nvif/class.h>
+
+static int
+nv40_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv)
+{
+ struct nvkm_memory *ramfc = chan->cgrp->runl->fifo->engine.subdev.device->imem->ramfc;
+ const u32 base = chan->id * 128;
+
+ chan->ramfc_offset = base;
+
+ nvkm_kmap(ramfc);
+ nvkm_wo32(ramfc, base + 0x00, offset);
+ nvkm_wo32(ramfc, base + 0x04, offset);
+ nvkm_wo32(ramfc, base + 0x0c, chan->push->addr >> 4);
+ nvkm_wo32(ramfc, base + 0x18, 0x30000000 |
+ NV_PFIFO_CACHE1_DMA_FETCH_TRIG_128_BYTES |
+ NV_PFIFO_CACHE1_DMA_FETCH_SIZE_128_BYTES |
+#ifdef __BIG_ENDIAN
+ NV_PFIFO_CACHE1_BIG_ENDIAN |
+#endif
+ NV_PFIFO_CACHE1_DMA_FETCH_MAX_REQS_8);
+ nvkm_wo32(ramfc, base + 0x3c, 0x0001ffff);
+ nvkm_done(ramfc);
+ return 0;
+}
+
+static const struct nvkm_chan_func_ramfc
+nv40_chan_ramfc = {
+ .layout = (const struct nvkm_ramfc_layout[]) {
+ { 32, 0, 0x00, 0, NV04_PFIFO_CACHE1_DMA_PUT },
+ { 32, 0, 0x04, 0, NV04_PFIFO_CACHE1_DMA_GET },
+ { 32, 0, 0x08, 0, NV10_PFIFO_CACHE1_REF_CNT },
+ { 32, 0, 0x0c, 0, NV04_PFIFO_CACHE1_DMA_INSTANCE },
+ { 32, 0, 0x10, 0, NV04_PFIFO_CACHE1_DMA_DCOUNT },
+ { 32, 0, 0x14, 0, NV04_PFIFO_CACHE1_DMA_STATE },
+ { 28, 0, 0x18, 0, NV04_PFIFO_CACHE1_DMA_FETCH },
+ { 2, 28, 0x18, 28, 0x002058 },
+ { 32, 0, 0x1c, 0, NV04_PFIFO_CACHE1_ENGINE },
+ { 32, 0, 0x20, 0, NV04_PFIFO_CACHE1_PULL1 },
+ { 32, 0, 0x24, 0, NV10_PFIFO_CACHE1_ACQUIRE_VALUE },
+ { 32, 0, 0x28, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMESTAMP },
+ { 32, 0, 0x2c, 0, NV10_PFIFO_CACHE1_ACQUIRE_TIMEOUT },
+ { 32, 0, 0x30, 0, NV10_PFIFO_CACHE1_SEMAPHORE },
+ { 32, 0, 0x34, 0, NV10_PFIFO_CACHE1_DMA_SUBROUTINE },
+ { 32, 0, 0x38, 0, NV40_PFIFO_GRCTX_INSTANCE },
+ { 17, 0, 0x3c, 0, NV04_PFIFO_DMA_TIMESLICE },
+ { 32, 0, 0x40, 0, 0x0032e4 },
+ { 32, 0, 0x44, 0, 0x0032e8 },
+ { 32, 0, 0x4c, 0, 0x002088 },
+ { 32, 0, 0x50, 0, 0x003300 },
+ { 32, 0, 0x54, 0, 0x00330c },
+ {}
+ },
+ .write = nv40_chan_ramfc_write,
+ .clear = nv04_chan_ramfc_clear,
+ .ctxdma = true,
+};
+
+static const struct nvkm_chan_func_userd
+nv40_chan_userd = {
+ .bar = 0,
+ .base = 0xc00000,
+ .size = 0x001000,
+};
+
+static const struct nvkm_chan_func
+nv40_chan = {
+ .inst = &nv04_chan_inst,
+ .userd = &nv40_chan_userd,
+ .ramfc = &nv40_chan_ramfc,
+ .start = nv04_chan_start,
+ .stop = nv04_chan_stop,
};
+static int
+nv40_eobj_ramht_add(struct nvkm_engn *engn, struct nvkm_object *eobj, struct nvkm_chan *chan)
+{
+ struct nvkm_fifo *fifo = chan->cgrp->runl->fifo;
+ struct nvkm_instmem *imem = fifo->engine.subdev.device->imem;
+ u32 context = chan->id << 23 | engn->id << 20;
+ int hash;
+
+ mutex_lock(&fifo->mutex);
+ hash = nvkm_ramht_insert(imem->ramht, eobj, chan->id, 4, eobj->handle, context);
+ mutex_unlock(&fifo->mutex);
+ return hash;
+}
+
static void
-nv40_fifo_init(struct nvkm_fifo *base)
+nv40_ectx_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan *chan)
{
- struct nv04_fifo *fifo = nv04_fifo(base);
- struct nvkm_device *device = fifo->base.engine.subdev.device;
+ struct nvkm_fifo *fifo = chan->cgrp->runl->fifo;
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ struct nvkm_memory *ramfc = device->imem->ramfc;
+ u32 inst = 0x00000000, reg, ctx;
+ int chid;
+
+ switch (engn->engine->subdev.type) {
+ case NVKM_ENGINE_GR:
+ reg = 0x0032e0;
+ ctx = 0x38;
+ break;
+ case NVKM_ENGINE_MPEG:
+ if (WARN_ON(device->chipset < 0x44))
+ return;
+ reg = 0x00330c;
+ ctx = 0x54;
+ break;
+ default:
+ WARN_ON(1);
+ return;
+ }
+
+ if (cctx)
+ inst = cctx->vctx->inst->addr >> 4;
+
+ spin_lock_irq(&fifo->lock);
+ nvkm_mask(device, 0x002500, 0x00000001, 0x00000000);
+
+ chid = nvkm_rd32(device, 0x003204) & (fifo->chid->nr - 1);
+ if (chid == chan->id)
+ nvkm_wr32(device, reg, inst);
+
+ nvkm_kmap(ramfc);
+ nvkm_wo32(ramfc, chan->ramfc_offset + ctx, inst);
+ nvkm_done(ramfc);
+
+ nvkm_mask(device, 0x002500, 0x00000001, 0x00000001);
+ spin_unlock_irq(&fifo->lock);
+}
+
+static const struct nvkm_engn_func
+nv40_engn = {
+ .bind = nv40_ectx_bind,
+ .ramht_add = nv40_eobj_ramht_add,
+ .ramht_del = nv04_eobj_ramht_del,
+};
+
+static const struct nvkm_engn_func
+nv40_engn_sw = {
+ .ramht_add = nv40_eobj_ramht_add,
+ .ramht_del = nv04_eobj_ramht_del,
+};
+
+static void
+nv40_fifo_init(struct nvkm_fifo *fifo)
+{
+ struct nvkm_device *device = fifo->engine.subdev.device;
struct nvkm_fb *fb = device->fb;
struct nvkm_instmem *imem = device->imem;
struct nvkm_ramht *ramht = imem->ramht;
@@ -98,7 +218,7 @@ nv40_fifo_init(struct nvkm_fifo *base)
break;
}
- nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->base.nr - 1);
+ nvkm_wr32(device, NV03_PFIFO_CACHE1_PUSH1, fifo->chid->mask);
nvkm_wr32(device, NV03_PFIFO_INTR_0, 0xffffffff);
nvkm_wr32(device, NV03_PFIFO_INTR_EN_0, 0xffffffff);
@@ -110,21 +230,23 @@ nv40_fifo_init(struct nvkm_fifo *base)
static const struct nvkm_fifo_func
nv40_fifo = {
+ .chid_nr = nv10_fifo_chid_nr,
+ .chid_ctor = nv04_fifo_chid_ctor,
+ .runl_ctor = nv04_fifo_runl_ctor,
.init = nv40_fifo_init,
.intr = nv04_fifo_intr,
- .engine_id = nv04_fifo_engine_id,
- .id_engine = nv04_fifo_id_engine,
.pause = nv04_fifo_pause,
.start = nv04_fifo_start,
- .chan = {
- &nv40_fifo_dma_oclass,
- NULL
- },
+ .runl = &nv04_runl,
+ .engn = &nv40_engn,
+ .engn_sw = &nv40_engn_sw,
+ .cgrp = {{ }, &nv04_cgrp },
+ .chan = {{ 0, 0, NV40_CHANNEL_DMA }, &nv40_chan },
};
int
nv40_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
- return nv04_fifo_new_(&nv40_fifo, device, type, inst, 32, nv40_fifo_ramfc, pfifo);
+ return nvkm_fifo_new_(&nv40_fifo, device, type, inst, pfifo);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c
index a08742cf425a..954b5f3a7d57 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c
@@ -21,62 +21,325 @@
*
* Authors: Ben Skeggs
*/
-#include "nv50.h"
-#include "channv50.h"
+#include "priv.h"
+#include "cgrp.h"
+#include "chan.h"
+#include "chid.h"
+#include "runl.h"
-#include <core/gpuobj.h>
+#include <core/ramht.h>
+#include <subdev/timer.h>
-static void
-nv50_fifo_runlist_update_locked(struct nv50_fifo *fifo)
+#include <nvif/class.h>
+
+void
+nv50_eobj_ramht_del(struct nvkm_chan *chan, int hash)
{
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- struct nvkm_memory *cur;
- int i, p;
+ nvkm_ramht_remove(chan->ramht, hash);
+}
- cur = fifo->runlist[fifo->cur_runlist];
- fifo->cur_runlist = !fifo->cur_runlist;
+int
+nv50_eobj_ramht_add(struct nvkm_engn *engn, struct nvkm_object *eobj, struct nvkm_chan *chan)
+{
+ return nvkm_ramht_insert(chan->ramht, eobj, 0, 4, eobj->handle, engn->id << 20);
+}
- nvkm_kmap(cur);
- for (i = 0, p = 0; i < fifo->base.nr; i++) {
- if (nvkm_rd32(device, 0x002600 + (i * 4)) & 0x80000000)
- nvkm_wo32(cur, p++ * 4, i);
- }
- nvkm_done(cur);
+void
+nv50_chan_stop(struct nvkm_chan *chan)
+{
+ struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
- nvkm_wr32(device, 0x0032f4, nvkm_memory_addr(cur) >> 12);
- nvkm_wr32(device, 0x0032ec, p);
- nvkm_wr32(device, 0x002500, 0x00000101);
+ nvkm_mask(device, 0x002600 + (chan->id * 4), 0x80000000, 0x00000000);
}
void
-nv50_fifo_runlist_update(struct nv50_fifo *fifo)
+nv50_chan_start(struct nvkm_chan *chan)
{
- mutex_lock(&fifo->base.mutex);
- nv50_fifo_runlist_update_locked(fifo);
- mutex_unlock(&fifo->base.mutex);
+ struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
+
+ nvkm_mask(device, 0x002600 + (chan->id * 4), 0x80000000, 0x80000000);
}
-int
-nv50_fifo_oneinit(struct nvkm_fifo *base)
+void
+nv50_chan_unbind(struct nvkm_chan *chan)
{
- struct nv50_fifo *fifo = nv50_fifo(base);
- struct nvkm_device *device = fifo->base.engine.subdev.device;
+ struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
+
+ nvkm_wr32(device, 0x002600 + (chan->id * 4), 0x00000000);
+}
+
+static void
+nv50_chan_bind(struct nvkm_chan *chan)
+{
+ struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
+
+ nvkm_wr32(device, 0x002600 + (chan->id * 4), chan->ramfc->addr >> 12);
+}
+
+static int
+nv50_chan_ramfc_write(struct nvkm_chan *chan, u64 offset, u64 length, u32 devm, bool priv)
+{
+ struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
+ const u32 limit2 = ilog2(length / 8);
int ret;
- ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000,
- false, &fifo->runlist[0]);
+ ret = nvkm_gpuobj_new(device, 0x0200, 0x1000, true, chan->inst, &chan->ramfc);
+ if (ret)
+ return ret;
+
+ ret = nvkm_gpuobj_new(device, 0x1200, 0, true, chan->inst, &chan->eng);
if (ret)
return ret;
- return nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 128 * 4, 0x1000,
- false, &fifo->runlist[1]);
+ ret = nvkm_gpuobj_new(device, 0x4000, 0, false, chan->inst, &chan->pgd);
+ if (ret)
+ return ret;
+
+ ret = nvkm_ramht_new(device, 0x8000, 16, chan->inst, &chan->ramht);
+ if (ret)
+ return ret;
+
+ nvkm_kmap(chan->ramfc);
+ nvkm_wo32(chan->ramfc, 0x3c, 0x403f6078);
+ nvkm_wo32(chan->ramfc, 0x44, 0x01003fff);
+ nvkm_wo32(chan->ramfc, 0x48, chan->push->node->offset >> 4);
+ nvkm_wo32(chan->ramfc, 0x50, lower_32_bits(offset));
+ nvkm_wo32(chan->ramfc, 0x54, upper_32_bits(offset) | (limit2 << 16));
+ nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff);
+ nvkm_wo32(chan->ramfc, 0x78, 0x00000000);
+ nvkm_wo32(chan->ramfc, 0x7c, 0x30000000 | devm);
+ nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
+ (4 << 24) /* SEARCH_FULL */ |
+ (chan->ramht->gpuobj->node->offset >> 4));
+ nvkm_done(chan->ramfc);
+ return 0;
+}
+
+static const struct nvkm_chan_func_ramfc
+nv50_chan_ramfc = {
+ .write = nv50_chan_ramfc_write,
+ .ctxdma = true,
+ .devm = 0xfff,
+};
+
+const struct nvkm_chan_func_userd
+nv50_chan_userd = {
+ .bar = 0,
+ .base = 0xc00000,
+ .size = 0x002000,
+};
+
+const struct nvkm_chan_func_inst
+nv50_chan_inst = {
+ .size = 0x10000,
+ .vmm = true,
+};
+
+static const struct nvkm_chan_func
+nv50_chan = {
+ .inst = &nv50_chan_inst,
+ .userd = &nv50_chan_userd,
+ .ramfc = &nv50_chan_ramfc,
+ .bind = nv50_chan_bind,
+ .unbind = nv50_chan_unbind,
+ .start = nv50_chan_start,
+ .stop = nv50_chan_stop,
+};
+
+static void
+nv50_ectx_bind(struct nvkm_engn *engn, struct nvkm_cctx *cctx, struct nvkm_chan *chan)
+{
+ struct nvkm_subdev *subdev = &chan->cgrp->runl->fifo->engine.subdev;
+ struct nvkm_device *device = subdev->device;
+ u64 start = 0, limit = 0;
+ u32 flags = 0, ptr0, save;
+
+ switch (engn->engine->subdev.type) {
+ case NVKM_ENGINE_GR : ptr0 = 0x0000; break;
+ case NVKM_ENGINE_MPEG : ptr0 = 0x0060; break;
+ default:
+ WARN_ON(1);
+ return;
+ }
+
+ if (!cctx) {
+ /* HW bug workaround:
+ *
+ * PFIFO will hang forever if the connected engines don't report
+ * that they've processed the context switch request.
+ *
+ * In order for the kickoff to work, we need to ensure all the
+ * connected engines are in a state where they can answer.
+ *
+ * Newer chipsets don't seem to suffer from this issue, and well,
+ * there's also a "ignore these engines" bitmask reg we can use
+ * if we hit the issue there..
+ */
+ save = nvkm_mask(device, 0x00b860, 0x00000001, 0x00000001);
+
+ /* Tell engines to save out contexts. */
+ nvkm_wr32(device, 0x0032fc, chan->inst->addr >> 12);
+ nvkm_msec(device, 2000,
+ if (nvkm_rd32(device, 0x0032fc) != 0xffffffff)
+ break;
+ );
+ nvkm_wr32(device, 0x00b860, save);
+ } else {
+ flags = 0x00190000;
+ start = cctx->vctx->inst->addr;
+ limit = start + cctx->vctx->inst->size - 1;
+ }
+
+ nvkm_kmap(chan->eng);
+ nvkm_wo32(chan->eng, ptr0 + 0x00, flags);
+ nvkm_wo32(chan->eng, ptr0 + 0x04, lower_32_bits(limit));
+ nvkm_wo32(chan->eng, ptr0 + 0x08, lower_32_bits(start));
+ nvkm_wo32(chan->eng, ptr0 + 0x0c, upper_32_bits(limit) << 24 |
+ lower_32_bits(start));
+ nvkm_wo32(chan->eng, ptr0 + 0x10, 0x00000000);
+ nvkm_wo32(chan->eng, ptr0 + 0x14, 0x00000000);
+ nvkm_done(chan->eng);
}
+static const struct nvkm_engn_func
+nv50_engn = {
+ .bind = nv50_ectx_bind,
+ .ramht_add = nv50_eobj_ramht_add,
+ .ramht_del = nv50_eobj_ramht_del,
+};
+
+const struct nvkm_engn_func
+nv50_engn_sw = {
+ .ramht_add = nv50_eobj_ramht_add,
+ .ramht_del = nv50_eobj_ramht_del,
+};
+
+static bool
+nv50_runl_pending(struct nvkm_runl *runl)
+{
+ return nvkm_rd32(runl->fifo->engine.subdev.device, 0x0032ec) & 0x00000100;
+}
+
+int
+nv50_runl_wait(struct nvkm_runl *runl)
+{
+ struct nvkm_fifo *fifo = runl->fifo;
+
+ nvkm_msec(fifo->engine.subdev.device, fifo->timeout.chan_msec,
+ if (!nvkm_runl_update_pending(runl))
+ return 0;
+ usleep_range(1, 2);
+ );
+
+ return -ETIMEDOUT;
+}
+
+static void
+nv50_runl_commit(struct nvkm_runl *runl, struct nvkm_memory *memory, u32 start, int count)
+{
+ struct nvkm_device *device = runl->fifo->engine.subdev.device;
+ u64 addr = nvkm_memory_addr(memory) + start;
+
+ nvkm_wr32(device, 0x0032f4, addr >> 12);
+ nvkm_wr32(device, 0x0032ec, count);
+}
+
+static void
+nv50_runl_insert_chan(struct nvkm_chan *chan, struct nvkm_memory *memory, u64 offset)
+{
+ nvkm_wo32(memory, offset, chan->id);
+}
+
+static struct nvkm_memory *
+nv50_runl_alloc(struct nvkm_runl *runl, u32 *offset)
+{
+ const u32 segment = ALIGN((runl->cgrp_nr + runl->chan_nr) * runl->func->size, 0x1000);
+ const u32 maxsize = (runl->cgid ? runl->cgid->nr : 0) + runl->chid->nr;
+ int ret;
+
+ if (unlikely(!runl->mem)) {
+ ret = nvkm_memory_new(runl->fifo->engine.subdev.device, NVKM_MEM_TARGET_INST,
+ maxsize * 2 * runl->func->size, 0, false, &runl->mem);
+ if (ret) {
+ RUNL_ERROR(runl, "alloc %d\n", ret);
+ return ERR_PTR(ret);
+ }
+ } else {
+ if (runl->offset + segment >= nvkm_memory_size(runl->mem)) {
+ ret = runl->func->wait(runl);
+ if (ret) {
+ RUNL_DEBUG(runl, "rewind timeout");
+ return ERR_PTR(ret);
+ }
+
+ runl->offset = 0;
+ }
+ }
+
+ *offset = runl->offset;
+ runl->offset += segment;
+ return runl->mem;
+}
+
+int
+nv50_runl_update(struct nvkm_runl *runl)
+{
+ struct nvkm_memory *memory;
+ struct nvkm_cgrp *cgrp;
+ struct nvkm_chan *chan;
+ u32 start, offset, count;
+
+ /*TODO: prio, interleaving. */
+
+ RUNL_TRACE(runl, "RAMRL: update cgrps:%d chans:%d", runl->cgrp_nr, runl->chan_nr);
+ memory = nv50_runl_alloc(runl, &start);
+ if (IS_ERR(memory))
+ return PTR_ERR(memory);
+
+ RUNL_TRACE(runl, "RAMRL: update start:%08x", start);
+ offset = start;
+
+ nvkm_kmap(memory);
+ nvkm_runl_foreach_cgrp(cgrp, runl) {
+ if (cgrp->hw) {
+ CGRP_TRACE(cgrp, " RAMRL+%08x: chans:%d", offset, cgrp->chan_nr);
+ runl->func->insert_cgrp(cgrp, memory, offset);
+ offset += runl->func->size;
+ }
+
+ nvkm_cgrp_foreach_chan(chan, cgrp) {
+ CHAN_TRACE(chan, "RAMRL+%08x: [%s]", offset, chan->name);
+ runl->func->insert_chan(chan, memory, offset);
+ offset += runl->func->size;
+ }
+ }
+ nvkm_done(memory);
+
+ /*TODO: look into using features on newer HW to guarantee forward progress. */
+ list_rotate_left(&runl->cgrps);
+
+ count = (offset - start) / runl->func->size;
+ RUNL_TRACE(runl, "RAMRL: commit start:%08x count:%d", start, count);
+
+ runl->func->commit(runl, memory, start, count);
+ return 0;
+}
+
+const struct nvkm_runl_func
+nv50_runl = {
+ .size = 4,
+ .update = nv50_runl_update,
+ .insert_chan = nv50_runl_insert_chan,
+ .commit = nv50_runl_commit,
+ .wait = nv50_runl_wait,
+ .pending = nv50_runl_pending,
+};
+
void
-nv50_fifo_init(struct nvkm_fifo *base)
+nv50_fifo_init(struct nvkm_fifo *fifo)
{
- struct nv50_fifo *fifo = nv50_fifo(base);
- struct nvkm_device *device = fifo->base.engine.subdev.device;
+ struct nvkm_runl *runl = nvkm_runl_first(fifo);
+ struct nvkm_device *device = fifo->engine.subdev.device;
int i;
nvkm_mask(device, 0x000200, 0x00000100, 0x00000000);
@@ -89,61 +352,47 @@ nv50_fifo_init(struct nvkm_fifo *base)
for (i = 0; i < 128; i++)
nvkm_wr32(device, 0x002600 + (i * 4), 0x00000000);
- nv50_fifo_runlist_update_locked(fifo);
+
+ atomic_set(&runl->changed, 1);
+ runl->func->update(runl);
nvkm_wr32(device, 0x003200, 0x00000001);
nvkm_wr32(device, 0x003250, 0x00000001);
nvkm_wr32(device, 0x002500, 0x00000001);
}
-void *
-nv50_fifo_dtor(struct nvkm_fifo *base)
+int
+nv50_fifo_chid_ctor(struct nvkm_fifo *fifo, int nr)
{
- struct nv50_fifo *fifo = nv50_fifo(base);
- nvkm_memory_unref(&fifo->runlist[1]);
- nvkm_memory_unref(&fifo->runlist[0]);
- return fifo;
+ /* CHID 0 is unusable (some kind of PIO channel?), 127 is "channel invalid". */
+ return nvkm_chid_new(&nvkm_chan_event, &fifo->engine.subdev, nr, 1, nr - 2, &fifo->chid);
}
int
-nv50_fifo_new_(const struct nvkm_fifo_func *func, struct nvkm_device *device,
- enum nvkm_subdev_type type, int inst, struct nvkm_fifo **pfifo)
+nv50_fifo_chid_nr(struct nvkm_fifo *fifo)
{
- struct nv50_fifo *fifo;
- int ret;
-
- if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
- return -ENOMEM;
- *pfifo = &fifo->base;
-
- ret = nvkm_fifo_ctor(func, device, type, inst, 128, &fifo->base);
- if (ret)
- return ret;
-
- set_bit(0, fifo->base.mask); /* PIO channel */
- set_bit(127, fifo->base.mask); /* inactive channel */
- return 0;
+ return 128;
}
static const struct nvkm_fifo_func
nv50_fifo = {
- .dtor = nv50_fifo_dtor,
- .oneinit = nv50_fifo_oneinit,
+ .chid_nr = nv50_fifo_chid_nr,
+ .chid_ctor = nv50_fifo_chid_ctor,
+ .runl_ctor = nv04_fifo_runl_ctor,
.init = nv50_fifo_init,
.intr = nv04_fifo_intr,
- .engine_id = nv04_fifo_engine_id,
- .id_engine = nv04_fifo_id_engine,
.pause = nv04_fifo_pause,
.start = nv04_fifo_start,
- .chan = {
- &nv50_fifo_gpfifo_oclass,
- NULL
- },
+ .runl = &nv50_runl,
+ .engn = &nv50_engn,
+ .engn_sw = &nv50_engn_sw,
+ .cgrp = {{ }, &nv04_cgrp },
+ .chan = {{ 0, 0, NV50_CHANNEL_GPFIFO }, &nv50_chan },
};
int
nv50_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
- return nv50_fifo_new_(&nv50_fifo, device, type, inst, pfifo);
+ return nvkm_fifo_new_(&nv50_fifo, device, type, inst, pfifo);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h
deleted file mode 100644
index 0111e7e5a4e3..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: MIT */
-#ifndef __NV50_FIFO_H__
-#define __NV50_FIFO_H__
-#define nv50_fifo(p) container_of((p), struct nv50_fifo, base)
-#include "priv.h"
-
-struct nv50_fifo {
- struct nvkm_fifo base;
- struct nvkm_memory *runlist[2];
- int cur_runlist;
-};
-
-int nv50_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int,
- struct nvkm_fifo **);
-
-void *nv50_fifo_dtor(struct nvkm_fifo *);
-int nv50_fifo_oneinit(struct nvkm_fifo *);
-void nv50_fifo_init(struct nvkm_fifo *);
-void nv50_fifo_runlist_update(struct nv50_fifo *);
-#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h
index 79cec57647f0..4d448be19224 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/priv.h
@@ -3,46 +3,207 @@
#define __NVKM_FIFO_PRIV_H__
#define nvkm_fifo(p) container_of((p), struct nvkm_fifo, engine)
#include <engine/fifo.h>
+#include <core/enum.h>
+struct nvkm_cctx;
+struct nvkm_cgrp;
+struct nvkm_engn;
+struct nvkm_memory;
+struct nvkm_runl;
+struct nvkm_runq;
+struct nvkm_vctx;
-int nvkm_fifo_ctor(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int,
- int nr, struct nvkm_fifo *);
-void nvkm_fifo_uevent(struct nvkm_fifo *);
-void nvkm_fifo_kevent(struct nvkm_fifo *, int chid);
-void nvkm_fifo_recover_chan(struct nvkm_fifo *, int chid);
-
-struct nvkm_fifo_chan *
-nvkm_fifo_chan_inst_locked(struct nvkm_fifo *, u64 inst);
-
-struct nvkm_fifo_chan_oclass;
struct nvkm_fifo_func {
- void *(*dtor)(struct nvkm_fifo *);
- int (*oneinit)(struct nvkm_fifo *);
- int (*info)(struct nvkm_fifo *, u64 mthd, u64 *data);
+ int (*chid_nr)(struct nvkm_fifo *);
+ int (*chid_ctor)(struct nvkm_fifo *, int nr);
+ int (*runq_nr)(struct nvkm_fifo *);
+ int (*runl_ctor)(struct nvkm_fifo *);
+
void (*init)(struct nvkm_fifo *);
- void (*fini)(struct nvkm_fifo *);
- void (*intr)(struct nvkm_fifo *);
- void (*fault)(struct nvkm_fifo *, struct nvkm_fault_data *);
- int (*engine_id)(struct nvkm_fifo *, struct nvkm_engine *);
- struct nvkm_engine *(*id_engine)(struct nvkm_fifo *, int engi);
+ void (*init_pbdmas)(struct nvkm_fifo *, u32 mask);
+
+ irqreturn_t (*intr)(struct nvkm_inth *);
+ void (*intr_mmu_fault_unit)(struct nvkm_fifo *, int unit);
+ void (*intr_ctxsw_timeout)(struct nvkm_fifo *, u32 engm);
+
+ const struct nvkm_fifo_func_mmu_fault {
+ void (*recover)(struct nvkm_fifo *, struct nvkm_fault_data *);
+ const struct nvkm_enum *access;
+ const struct nvkm_enum *engine;
+ const struct nvkm_enum *reason;
+ const struct nvkm_enum *hubclient;
+ const struct nvkm_enum *gpcclient;
+ } *mmu_fault;
+
void (*pause)(struct nvkm_fifo *, unsigned long *);
void (*start)(struct nvkm_fifo *, unsigned long *);
- void (*uevent_init)(struct nvkm_fifo *);
- void (*uevent_fini)(struct nvkm_fifo *);
- void (*recover_chan)(struct nvkm_fifo *, int chid);
- int (*class_get)(struct nvkm_fifo *, int index, struct nvkm_oclass *);
- int (*class_new)(struct nvkm_fifo *, const struct nvkm_oclass *,
- void *, u32, struct nvkm_object **);
- const struct nvkm_fifo_chan_oclass *chan[];
+
+ int (*nonstall_ctor)(struct nvkm_fifo *);
+ const struct nvkm_event_func *nonstall;
+
+ const struct nvkm_runl_func *runl;
+ const struct nvkm_runq_func *runq;
+ const struct nvkm_engn_func *engn;
+ const struct nvkm_engn_func *engn_sw;
+ const struct nvkm_engn_func *engn_ce;
+
+ struct nvkm_fifo_func_cgrp {
+ struct nvkm_sclass user;
+ const struct nvkm_cgrp_func *func;
+ bool force;
+ } cgrp;
+
+ struct nvkm_fifo_func_chan {
+ struct nvkm_sclass user;
+ const struct nvkm_chan_func *func;
+ } chan;
};
-void nv04_fifo_intr(struct nvkm_fifo *);
-int nv04_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *);
-struct nvkm_engine *nv04_fifo_id_engine(struct nvkm_fifo *, int);
+int nvkm_fifo_new_(const struct nvkm_fifo_func *, struct nvkm_device *, enum nvkm_subdev_type, int,
+ struct nvkm_fifo **);
+
+int nv04_fifo_chid_ctor(struct nvkm_fifo *, int);
+int nv04_fifo_runl_ctor(struct nvkm_fifo *);
+void nv04_fifo_init(struct nvkm_fifo *);
+irqreturn_t nv04_fifo_intr(struct nvkm_inth *);
void nv04_fifo_pause(struct nvkm_fifo *, unsigned long *);
void nv04_fifo_start(struct nvkm_fifo *, unsigned long *);
+extern const struct nvkm_runl_func nv04_runl;
+extern const struct nvkm_engn_func nv04_engn;
+extern const struct nvkm_cgrp_func nv04_cgrp;
+extern const struct nvkm_chan_func_inst nv04_chan_inst;
+extern const struct nvkm_chan_func_userd nv04_chan_userd;
+void nv04_chan_ramfc_clear(struct nvkm_chan *);
+void nv04_chan_start(struct nvkm_chan *);
+void nv04_chan_stop(struct nvkm_chan *);
+void nv04_eobj_ramht_del(struct nvkm_chan *, int);
+
+int nv10_fifo_chid_nr(struct nvkm_fifo *);
+
+int nv50_fifo_chid_nr(struct nvkm_fifo *);
+int nv50_fifo_chid_ctor(struct nvkm_fifo *, int);
+void nv50_fifo_init(struct nvkm_fifo *);
+extern const struct nvkm_runl_func nv50_runl;
+int nv50_runl_update(struct nvkm_runl *);
+int nv50_runl_wait(struct nvkm_runl *);
+extern const struct nvkm_engn_func nv50_engn_sw;
+extern const struct nvkm_chan_func_inst nv50_chan_inst;
+extern const struct nvkm_chan_func_userd nv50_chan_userd;
+void nv50_chan_unbind(struct nvkm_chan *);
+void nv50_chan_start(struct nvkm_chan *);
+void nv50_chan_stop(struct nvkm_chan *);
+void nv50_chan_preempt(struct nvkm_chan *);
+int nv50_eobj_ramht_add(struct nvkm_engn *, struct nvkm_object *, struct nvkm_chan *);
+void nv50_eobj_ramht_del(struct nvkm_chan *, int);
+
+extern const struct nvkm_event_func g84_fifo_nonstall;
+extern const struct nvkm_engn_func g84_engn;
+extern const struct nvkm_chan_func g84_chan;
+
+int gf100_fifo_chid_ctor(struct nvkm_fifo *, int);
+int gf100_fifo_runq_nr(struct nvkm_fifo *);
+bool gf100_fifo_intr_pbdma(struct nvkm_fifo *);
+void gf100_fifo_intr_mmu_fault(struct nvkm_fifo *);
+void gf100_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int);
+void gf100_fifo_intr_sched(struct nvkm_fifo *);
+void gf100_fifo_intr_ctxsw_timeout(struct nvkm_fifo *, u32);
+void gf100_fifo_mmu_fault_recover(struct nvkm_fifo *, struct nvkm_fault_data *);
+extern const struct nvkm_enum gf100_fifo_mmu_fault_access[];
+extern const struct nvkm_event_func gf100_fifo_nonstall;
+bool gf100_runl_preempt_pending(struct nvkm_runl *);
+void gf100_runq_init(struct nvkm_runq *);
+bool gf100_runq_intr(struct nvkm_runq *, struct nvkm_runl *);
+void gf100_engn_mmu_fault_trigger(struct nvkm_engn *);
+bool gf100_engn_mmu_fault_triggered(struct nvkm_engn *);
+extern const struct nvkm_engn_func gf100_engn_sw;
+extern const struct nvkm_chan_func_inst gf100_chan_inst;
+void gf100_chan_userd_clear(struct nvkm_chan *);
+void gf100_chan_preempt(struct nvkm_chan *);
+
+int gk104_fifo_chid_nr(struct nvkm_fifo *);
+int gk104_fifo_runl_ctor(struct nvkm_fifo *);
+void gk104_fifo_init(struct nvkm_fifo *);
+void gk104_fifo_init_pbdmas(struct nvkm_fifo *, u32);
+irqreturn_t gk104_fifo_intr(struct nvkm_inth *);
+void gk104_fifo_intr_runlist(struct nvkm_fifo *);
+void gk104_fifo_intr_chsw(struct nvkm_fifo *);
+void gk104_fifo_intr_bind(struct nvkm_fifo *);
+extern const struct nvkm_fifo_func_mmu_fault gk104_fifo_mmu_fault;
+extern const struct nvkm_enum gk104_fifo_mmu_fault_reason[];
+extern const struct nvkm_enum gk104_fifo_mmu_fault_hubclient[];
+extern const struct nvkm_enum gk104_fifo_mmu_fault_gpcclient[];
+void gk104_runl_insert_chan(struct nvkm_chan *, struct nvkm_memory *, u64);
+void gk104_runl_commit(struct nvkm_runl *, struct nvkm_memory *, u32, int);
+bool gk104_runl_pending(struct nvkm_runl *);
+void gk104_runl_block(struct nvkm_runl *, u32);
+void gk104_runl_allow(struct nvkm_runl *, u32);
+void gk104_runl_fault_clear(struct nvkm_runl *);
+extern const struct nvkm_runq_func gk104_runq;
+void gk104_runq_init(struct nvkm_runq *);
+bool gk104_runq_intr(struct nvkm_runq *, struct nvkm_runl *);
+extern const struct nvkm_bitfield gk104_runq_intr_0_names[];
+bool gk104_runq_idle(struct nvkm_runq *);
+extern const struct nvkm_engn_func gk104_engn;
+bool gk104_engn_chsw(struct nvkm_engn *);
+int gk104_engn_cxid(struct nvkm_engn *, bool *cgid);
+int gk104_ectx_ctor(struct nvkm_engn *, struct nvkm_vctx *);
+extern const struct nvkm_engn_func gk104_engn_ce;
+extern const struct nvkm_chan_func_userd gk104_chan_userd;
+extern const struct nvkm_chan_func_ramfc gk104_chan_ramfc;
+void gk104_chan_bind(struct nvkm_chan *);
+void gk104_chan_bind_inst(struct nvkm_chan *);
+void gk104_chan_unbind(struct nvkm_chan *);
+void gk104_chan_start(struct nvkm_chan *);
+void gk104_chan_stop(struct nvkm_chan *);
+
+int gk110_fifo_chid_ctor(struct nvkm_fifo *, int);
+extern const struct nvkm_runl_func gk110_runl;
+extern const struct nvkm_cgrp_func gk110_cgrp;
+void gk110_runl_insert_cgrp(struct nvkm_cgrp *, struct nvkm_memory *, u64);
+extern const struct nvkm_chan_func gk110_chan;
+void gk110_chan_preempt(struct nvkm_chan *);
+
+extern const struct nvkm_runq_func gk208_runq;
+void gk208_runq_init(struct nvkm_runq *);
+
+void gm107_fifo_intr_mmu_fault_unit(struct nvkm_fifo *, int);
+extern const struct nvkm_fifo_func_mmu_fault gm107_fifo_mmu_fault;
+extern const struct nvkm_runl_func gm107_runl;
+extern const struct nvkm_chan_func gm107_chan;
+
+int gm200_fifo_chid_nr(struct nvkm_fifo *);
+int gm200_fifo_runq_nr(struct nvkm_fifo *);
+
+extern const struct nvkm_enum gv100_fifo_mmu_fault_access[];
+extern const struct nvkm_enum gv100_fifo_mmu_fault_reason[];
+extern const struct nvkm_enum gv100_fifo_mmu_fault_hubclient[];
+extern const struct nvkm_enum gv100_fifo_mmu_fault_gpcclient[];
+void gv100_runl_insert_cgrp(struct nvkm_cgrp *, struct nvkm_memory *, u64);
+void gv100_runl_insert_chan(struct nvkm_chan *, struct nvkm_memory *, u64);
+void gv100_runl_preempt(struct nvkm_runl *);
+extern const struct nvkm_runq_func gv100_runq;
+extern const struct nvkm_engn_func gv100_engn;
+void gv100_ectx_bind(struct nvkm_engn *, struct nvkm_cctx *, struct nvkm_chan *);
+extern const struct nvkm_engn_func gv100_engn_ce;
+int gv100_ectx_ce_ctor(struct nvkm_engn *, struct nvkm_vctx *);
+void gv100_ectx_ce_bind(struct nvkm_engn *, struct nvkm_cctx *, struct nvkm_chan *);
+extern const struct nvkm_chan_func_userd gv100_chan_userd;
+extern const struct nvkm_chan_func_ramfc gv100_chan_ramfc;
+
+void tu102_fifo_intr_ctxsw_timeout_info(struct nvkm_engn *, u32 info);
+extern const struct nvkm_fifo_func_mmu_fault tu102_fifo_mmu_fault;
-void gf100_fifo_intr_fault(struct nvkm_fifo *, int);
+int ga100_fifo_runl_ctor(struct nvkm_fifo *);
+int ga100_fifo_nonstall_ctor(struct nvkm_fifo *);
+extern const struct nvkm_event_func ga100_fifo_nonstall;
+extern const struct nvkm_runl_func ga100_runl;
+extern const struct nvkm_runq_func ga100_runq;
+extern const struct nvkm_engn_func ga100_engn;
+extern const struct nvkm_engn_func ga100_engn_ce;
+extern const struct nvkm_cgrp_func ga100_cgrp;
+extern const struct nvkm_chan_func ga100_chan;
-int gk104_fifo_engine_id(struct nvkm_fifo *, struct nvkm_engine *);
-struct nvkm_engine *gk104_fifo_id_engine(struct nvkm_fifo *, int);
+int nvkm_uchan_new(struct nvkm_fifo *, struct nvkm_cgrp *, const struct nvkm_oclass *,
+ void *argv, u32 argc, struct nvkm_object **);
+int nvkm_ucgrp_new(struct nvkm_fifo *, const struct nvkm_oclass *, void *argv, u32 argc,
+ struct nvkm_object **);
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c
new file mode 100644
index 000000000000..b5836cbc29aa
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.c
@@ -0,0 +1,430 @@
+/*
+ * Copyright 2021 Red Hat 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 "runl.h"
+#include "cgrp.h"
+#include "chan.h"
+#include "chid.h"
+#include "priv.h"
+#include "runq.h"
+
+#include <core/gpuobj.h>
+#include <subdev/timer.h>
+#include <subdev/top.h>
+
+struct nvkm_cgrp *
+nvkm_engn_cgrp_get(struct nvkm_engn *engn, unsigned long *pirqflags)
+{
+ struct nvkm_cgrp *cgrp = NULL;
+ struct nvkm_chan *chan;
+ bool cgid;
+ int id;
+
+ id = engn->func->cxid(engn, &cgid);
+ if (id < 0)
+ return NULL;
+
+ if (!cgid) {
+ chan = nvkm_runl_chan_get_chid(engn->runl, id, pirqflags);
+ if (chan)
+ cgrp = chan->cgrp;
+ } else {
+ cgrp = nvkm_runl_cgrp_get_cgid(engn->runl, id, pirqflags);
+ }
+
+ WARN_ON(!cgrp);
+ return cgrp;
+}
+
+static void
+nvkm_runl_rc(struct nvkm_runl *runl)
+{
+ struct nvkm_fifo *fifo = runl->fifo;
+ struct nvkm_cgrp *cgrp, *gtmp;
+ struct nvkm_chan *chan, *ctmp;
+ struct nvkm_engn *engn;
+ unsigned long flags;
+ int rc, state, i;
+ bool reset;
+
+ /* Runlist is blocked before scheduling recovery - fetch count. */
+ BUG_ON(!mutex_is_locked(&runl->mutex));
+ rc = atomic_xchg(&runl->rc_pending, 0);
+ if (!rc)
+ return;
+
+ /* Look for channel groups flagged for RC. */
+ nvkm_runl_foreach_cgrp_safe(cgrp, gtmp, runl) {
+ state = atomic_cmpxchg(&cgrp->rc, NVKM_CGRP_RC_PENDING, NVKM_CGRP_RC_RUNNING);
+ if (state == NVKM_CGRP_RC_PENDING) {
+ /* Disable all channels in them, and remove from runlist. */
+ nvkm_cgrp_foreach_chan_safe(chan, ctmp, cgrp) {
+ nvkm_chan_error(chan, false);
+ nvkm_chan_remove_locked(chan);
+ }
+ }
+ }
+
+ /* On GPUs with runlist preempt, wait for PBDMA(s) servicing runlist to go idle. */
+ if (runl->func->preempt) {
+ for (i = 0; i < runl->runq_nr; i++) {
+ struct nvkm_runq *runq = runl->runq[i];
+
+ if (runq) {
+ nvkm_msec(fifo->engine.subdev.device, 2000,
+ if (runq->func->idle(runq))
+ break;
+ );
+ }
+ }
+ }
+
+ /* Look for engines that are still on flagged channel groups - reset them. */
+ nvkm_runl_foreach_engn_cond(engn, runl, engn->func->cxid) {
+ cgrp = nvkm_engn_cgrp_get(engn, &flags);
+ if (!cgrp) {
+ ENGN_DEBUG(engn, "cxid not valid");
+ continue;
+ }
+
+ reset = atomic_read(&cgrp->rc) == NVKM_CGRP_RC_RUNNING;
+ nvkm_cgrp_put(&cgrp, flags);
+ if (!reset) {
+ ENGN_DEBUG(engn, "cxid not in recovery");
+ continue;
+ }
+
+ ENGN_DEBUG(engn, "resetting...");
+ /*TODO: can we do something less of a potential catastrophe on failure? */
+ WARN_ON(nvkm_engine_reset(engn->engine));
+ }
+
+ /* Submit runlist update, and clear any remaining exception state. */
+ runl->func->update(runl);
+ if (runl->func->fault_clear)
+ runl->func->fault_clear(runl);
+
+ /* Unblock runlist processing. */
+ while (rc--)
+ nvkm_runl_allow(runl);
+ runl->func->wait(runl);
+}
+
+static void
+nvkm_runl_rc_runl(struct nvkm_runl *runl)
+{
+ RUNL_ERROR(runl, "rc scheduled");
+
+ nvkm_runl_block(runl);
+ if (runl->func->preempt)
+ runl->func->preempt(runl);
+
+ atomic_inc(&runl->rc_pending);
+ schedule_work(&runl->work);
+}
+
+void
+nvkm_runl_rc_cgrp(struct nvkm_cgrp *cgrp)
+{
+ if (atomic_cmpxchg(&cgrp->rc, NVKM_CGRP_RC_NONE, NVKM_CGRP_RC_PENDING) != NVKM_CGRP_RC_NONE)
+ return;
+
+ CGRP_ERROR(cgrp, "rc scheduled");
+ nvkm_runl_rc_runl(cgrp->runl);
+}
+
+void
+nvkm_runl_rc_engn(struct nvkm_runl *runl, struct nvkm_engn *engn)
+{
+ struct nvkm_cgrp *cgrp;
+ unsigned long flags;
+
+ /* Lookup channel group currently on engine. */
+ cgrp = nvkm_engn_cgrp_get(engn, &flags);
+ if (!cgrp) {
+ ENGN_DEBUG(engn, "rc skipped, not on channel");
+ return;
+ }
+
+ nvkm_runl_rc_cgrp(cgrp);
+ nvkm_cgrp_put(&cgrp, flags);
+}
+
+static void
+nvkm_runl_work(struct work_struct *work)
+{
+ struct nvkm_runl *runl = container_of(work, typeof(*runl), work);
+
+ mutex_lock(&runl->mutex);
+ nvkm_runl_rc(runl);
+ mutex_unlock(&runl->mutex);
+
+}
+
+struct nvkm_chan *
+nvkm_runl_chan_get_inst(struct nvkm_runl *runl, u64 inst, unsigned long *pirqflags)
+{
+ struct nvkm_chid *chid = runl->chid;
+ struct nvkm_chan *chan;
+ unsigned long flags;
+ int id;
+
+ spin_lock_irqsave(&chid->lock, flags);
+ for_each_set_bit(id, chid->used, chid->nr) {
+ chan = chid->data[id];
+ if (likely(chan)) {
+ if (chan->inst->addr == inst) {
+ spin_lock(&chan->cgrp->lock);
+ *pirqflags = flags;
+ spin_unlock(&chid->lock);
+ return chan;
+ }
+ }
+ }
+ spin_unlock_irqrestore(&chid->lock, flags);
+ return NULL;
+}
+
+struct nvkm_chan *
+nvkm_runl_chan_get_chid(struct nvkm_runl *runl, int id, unsigned long *pirqflags)
+{
+ struct nvkm_chid *chid = runl->chid;
+ struct nvkm_chan *chan;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chid->lock, flags);
+ if (!WARN_ON(id >= chid->nr)) {
+ chan = chid->data[id];
+ if (likely(chan)) {
+ spin_lock(&chan->cgrp->lock);
+ *pirqflags = flags;
+ spin_unlock(&chid->lock);
+ return chan;
+ }
+ }
+ spin_unlock_irqrestore(&chid->lock, flags);
+ return NULL;
+}
+
+struct nvkm_cgrp *
+nvkm_runl_cgrp_get_cgid(struct nvkm_runl *runl, int id, unsigned long *pirqflags)
+{
+ struct nvkm_chid *cgid = runl->cgid;
+ struct nvkm_cgrp *cgrp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&cgid->lock, flags);
+ if (!WARN_ON(id >= cgid->nr)) {
+ cgrp = cgid->data[id];
+ if (likely(cgrp)) {
+ spin_lock(&cgrp->lock);
+ *pirqflags = flags;
+ spin_unlock(&cgid->lock);
+ return cgrp;
+ }
+ }
+ spin_unlock_irqrestore(&cgid->lock, flags);
+ return NULL;
+}
+
+int
+nvkm_runl_preempt_wait(struct nvkm_runl *runl)
+{
+ return nvkm_msec(runl->fifo->engine.subdev.device, runl->fifo->timeout.chan_msec,
+ if (!runl->func->preempt_pending(runl))
+ break;
+
+ nvkm_runl_rc(runl);
+ usleep_range(1, 2);
+ ) < 0 ? -ETIMEDOUT : 0;
+}
+
+bool
+nvkm_runl_update_pending(struct nvkm_runl *runl)
+{
+ if (!runl->func->pending(runl))
+ return false;
+
+ nvkm_runl_rc(runl);
+ return true;
+}
+
+void
+nvkm_runl_update_locked(struct nvkm_runl *runl, bool wait)
+{
+ if (atomic_xchg(&runl->changed, 0) && runl->func->update) {
+ runl->func->update(runl);
+ if (wait)
+ runl->func->wait(runl);
+ }
+}
+
+void
+nvkm_runl_allow(struct nvkm_runl *runl)
+{
+ struct nvkm_fifo *fifo = runl->fifo;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fifo->lock, flags);
+ if (!--runl->blocked) {
+ RUNL_TRACE(runl, "running");
+ runl->func->allow(runl, ~0);
+ }
+ spin_unlock_irqrestore(&fifo->lock, flags);
+}
+
+void
+nvkm_runl_block(struct nvkm_runl *runl)
+{
+ struct nvkm_fifo *fifo = runl->fifo;
+ unsigned long flags;
+
+ spin_lock_irqsave(&fifo->lock, flags);
+ if (!runl->blocked++) {
+ RUNL_TRACE(runl, "stopped");
+ runl->func->block(runl, ~0);
+ }
+ spin_unlock_irqrestore(&fifo->lock, flags);
+}
+
+void
+nvkm_runl_fini(struct nvkm_runl *runl)
+{
+ if (runl->func->fini)
+ runl->func->fini(runl);
+
+ flush_work(&runl->work);
+}
+
+void
+nvkm_runl_del(struct nvkm_runl *runl)
+{
+ struct nvkm_engn *engn, *engt;
+
+ nvkm_memory_unref(&runl->mem);
+
+ list_for_each_entry_safe(engn, engt, &runl->engns, head) {
+ list_del(&engn->head);
+ kfree(engn);
+ }
+
+ nvkm_chid_unref(&runl->chid);
+ nvkm_chid_unref(&runl->cgid);
+
+ list_del(&runl->head);
+ mutex_destroy(&runl->mutex);
+ kfree(runl);
+}
+
+struct nvkm_engn *
+nvkm_runl_add(struct nvkm_runl *runl, int engi, const struct nvkm_engn_func *func,
+ enum nvkm_subdev_type type, int inst)
+{
+ struct nvkm_fifo *fifo = runl->fifo;
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ struct nvkm_engine *engine;
+ struct nvkm_engn *engn;
+
+ engine = nvkm_device_engine(device, type, inst);
+ if (!engine) {
+ RUNL_DEBUG(runl, "engn %d.%d[%s] not found", engi, inst, nvkm_subdev_type[type]);
+ return NULL;
+ }
+
+ if (!(engn = kzalloc(sizeof(*engn), GFP_KERNEL)))
+ return NULL;
+
+ engn->func = func;
+ engn->runl = runl;
+ engn->id = engi;
+ engn->engine = engine;
+ engn->fault = -1;
+ list_add_tail(&engn->head, &runl->engns);
+
+ /* Lookup MMU engine ID for fault handling. */
+ if (device->top)
+ engn->fault = nvkm_top_fault_id(device, engine->subdev.type, engine->subdev.inst);
+
+ if (engn->fault < 0 && fifo->func->mmu_fault) {
+ const struct nvkm_enum *map = fifo->func->mmu_fault->engine;
+
+ while (map->name) {
+ if (map->data2 == engine->subdev.type && map->inst == engine->subdev.inst) {
+ engn->fault = map->value;
+ break;
+ }
+ map++;
+ }
+ }
+
+ return engn;
+}
+
+struct nvkm_runl *
+nvkm_runl_get(struct nvkm_fifo *fifo, int runi, u32 addr)
+{
+ struct nvkm_runl *runl;
+
+ nvkm_runl_foreach(runl, fifo) {
+ if ((runi >= 0 && runl->id == runi) || (runi < 0 && runl->addr == addr))
+ return runl;
+ }
+
+ return NULL;
+}
+
+struct nvkm_runl *
+nvkm_runl_new(struct nvkm_fifo *fifo, int runi, u32 addr, int id_nr)
+{
+ struct nvkm_subdev *subdev = &fifo->engine.subdev;
+ struct nvkm_runl *runl;
+ int ret;
+
+ if (!(runl = kzalloc(sizeof(*runl), GFP_KERNEL)))
+ return NULL;
+
+ runl->func = fifo->func->runl;
+ runl->fifo = fifo;
+ runl->id = runi;
+ runl->addr = addr;
+ INIT_LIST_HEAD(&runl->engns);
+ INIT_LIST_HEAD(&runl->cgrps);
+ atomic_set(&runl->changed, 0);
+ mutex_init(&runl->mutex);
+ INIT_WORK(&runl->work, nvkm_runl_work);
+ atomic_set(&runl->rc_triggered, 0);
+ atomic_set(&runl->rc_pending, 0);
+ list_add_tail(&runl->head, &fifo->runls);
+
+ if (!fifo->chid) {
+ if ((ret = nvkm_chid_new(&nvkm_chan_event, subdev, id_nr, 0, id_nr, &runl->cgid)) ||
+ (ret = nvkm_chid_new(&nvkm_chan_event, subdev, id_nr, 0, id_nr, &runl->chid))) {
+ RUNL_ERROR(runl, "cgid/chid: %d", ret);
+ nvkm_runl_del(runl);
+ return NULL;
+ }
+ } else {
+ runl->cgid = nvkm_chid_ref(fifo->cgid);
+ runl->chid = nvkm_chid_ref(fifo->chid);
+ }
+
+ return runl;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h
new file mode 100644
index 000000000000..c93d21bb7bd5
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runl.h
@@ -0,0 +1,125 @@
+#ifndef __NVKM_RUNL_H__
+#define __NVKM_RUNL_H__
+#include <core/intr.h>
+struct nvkm_cctx;
+struct nvkm_cgrp;
+struct nvkm_chan;
+struct nvkm_memory;
+struct nvkm_object;
+struct nvkm_vctx;
+enum nvkm_subdev_type;
+
+struct nvkm_engn {
+ const struct nvkm_engn_func {
+ bool (*chsw)(struct nvkm_engn *);
+ int (*cxid)(struct nvkm_engn *, bool *cgid);
+ void (*mmu_fault_trigger)(struct nvkm_engn *);
+ bool (*mmu_fault_triggered)(struct nvkm_engn *);
+ int (*ctor)(struct nvkm_engn *, struct nvkm_vctx *);
+ void (*bind)(struct nvkm_engn *, struct nvkm_cctx *, struct nvkm_chan *);
+ int (*ramht_add)(struct nvkm_engn *, struct nvkm_object *, struct nvkm_chan *);
+ void (*ramht_del)(struct nvkm_chan *, int hash);
+ } *func;
+ struct nvkm_runl *runl;
+ int id;
+
+ struct nvkm_engine *engine;
+
+ int fault;
+
+ struct list_head head;
+};
+
+#define ENGN_PRINT(e,l,p,f,a...) \
+ RUNL_PRINT((e)->runl, l, p, "%02d[%8s]:"f, (e)->id, (e)->engine->subdev.name, ##a)
+#define ENGN_DEBUG(e,f,a...) ENGN_PRINT((e), DEBUG, info, " "f"\n", ##a)
+
+struct nvkm_runl {
+ const struct nvkm_runl_func {
+ void (*init)(struct nvkm_runl *);
+ void (*fini)(struct nvkm_runl *);
+ int runqs;
+ u8 size;
+ int (*update)(struct nvkm_runl *);
+ void (*insert_cgrp)(struct nvkm_cgrp *, struct nvkm_memory *, u64 offset);
+ void (*insert_chan)(struct nvkm_chan *, struct nvkm_memory *, u64 offset);
+ void (*commit)(struct nvkm_runl *, struct nvkm_memory *, u32 start, int count);
+ int (*wait)(struct nvkm_runl *);
+ bool (*pending)(struct nvkm_runl *);
+ void (*block)(struct nvkm_runl *, u32 engm);
+ void (*allow)(struct nvkm_runl *, u32 engm);
+ void (*fault_clear)(struct nvkm_runl *);
+ void (*preempt)(struct nvkm_runl *);
+ bool (*preempt_pending)(struct nvkm_runl *);
+ } *func;
+ struct nvkm_fifo *fifo;
+ int id;
+ u32 addr;
+ u32 chan;
+ u16 doorbell;
+
+ struct nvkm_chid *cgid;
+#define NVKM_CHAN_EVENT_ERRORED BIT(0)
+ struct nvkm_chid *chid;
+
+ struct list_head engns;
+
+ struct nvkm_runq *runq[2];
+ int runq_nr;
+
+ struct nvkm_inth inth;
+
+ struct list_head cgrps;
+ int cgrp_nr;
+ int chan_nr;
+ atomic_t changed;
+ struct nvkm_memory *mem;
+ u32 offset;
+ struct mutex mutex;
+
+ int blocked;
+
+ struct work_struct work;
+ atomic_t rc_triggered;
+ atomic_t rc_pending;
+
+ struct list_head head;
+};
+
+struct nvkm_runl *nvkm_runl_new(struct nvkm_fifo *, int runi, u32 addr, int id_nr);
+struct nvkm_runl *nvkm_runl_get(struct nvkm_fifo *, int runi, u32 addr);
+struct nvkm_engn *nvkm_runl_add(struct nvkm_runl *, int engi, const struct nvkm_engn_func *,
+ enum nvkm_subdev_type, int inst);
+void nvkm_runl_del(struct nvkm_runl *);
+void nvkm_runl_fini(struct nvkm_runl *);
+void nvkm_runl_block(struct nvkm_runl *);
+void nvkm_runl_allow(struct nvkm_runl *);
+void nvkm_runl_update_locked(struct nvkm_runl *, bool wait);
+bool nvkm_runl_update_pending(struct nvkm_runl *);
+int nvkm_runl_preempt_wait(struct nvkm_runl *);
+
+void nvkm_runl_rc_engn(struct nvkm_runl *, struct nvkm_engn *);
+void nvkm_runl_rc_cgrp(struct nvkm_cgrp *);
+
+struct nvkm_cgrp *nvkm_runl_cgrp_get_cgid(struct nvkm_runl *, int cgid, unsigned long *irqflags);
+struct nvkm_chan *nvkm_runl_chan_get_chid(struct nvkm_runl *, int chid, unsigned long *irqflags);
+struct nvkm_chan *nvkm_runl_chan_get_inst(struct nvkm_runl *, u64 inst, unsigned long *irqflags);
+
+#define nvkm_runl_find_engn(engn,runl,cond) nvkm_list_find(engn, &(runl)->engns, head, (cond))
+
+#define nvkm_runl_first(fifo) list_first_entry(&(fifo)->runls, struct nvkm_runl, head)
+#define nvkm_runl_foreach(runl,fifo) list_for_each_entry((runl), &(fifo)->runls, head)
+#define nvkm_runl_foreach_cond(runl,fifo,cond) nvkm_list_foreach(runl, &(fifo)->runls, head, (cond))
+#define nvkm_runl_foreach_engn(engn,runl) list_for_each_entry((engn), &(runl)->engns, head)
+#define nvkm_runl_foreach_engn_cond(engn,runl,cond) \
+ nvkm_list_foreach(engn, &(runl)->engns, head, (cond))
+#define nvkm_runl_foreach_cgrp(cgrp,runl) list_for_each_entry((cgrp), &(runl)->cgrps, head)
+#define nvkm_runl_foreach_cgrp_safe(cgrp,gtmp,runl) \
+ list_for_each_entry_safe((cgrp), (gtmp), &(runl)->cgrps, head)
+
+#define RUNL_PRINT(r,l,p,f,a...) \
+ nvkm_printk__(&(r)->fifo->engine.subdev, NV_DBG_##l, p, "%06x:"f, (r)->addr, ##a)
+#define RUNL_ERROR(r,f,a...) RUNL_PRINT((r), ERROR, err, " "f"\n", ##a)
+#define RUNL_DEBUG(r,f,a...) RUNL_PRINT((r), DEBUG, info, " "f"\n", ##a)
+#define RUNL_TRACE(r,f,a...) RUNL_PRINT((r), TRACE, info, " "f"\n", ##a)
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.c
new file mode 100644
index 000000000000..33bcf5fb3ef0
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2021 Red Hat 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 "runq.h"
+#include "priv.h"
+
+void
+nvkm_runq_del(struct nvkm_runq *runq)
+{
+ list_del(&runq->head);
+ kfree(runq);
+}
+
+struct nvkm_runq *
+nvkm_runq_new(struct nvkm_fifo *fifo, int pbid)
+{
+ struct nvkm_runq *runq;
+
+ if (!(runq = kzalloc(sizeof(*runq), GFP_KERNEL)))
+ return NULL;
+
+ runq->func = fifo->func->runq;
+ runq->fifo = fifo;
+ runq->id = pbid;
+ list_add_tail(&runq->head, &fifo->runqs);
+ return runq;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h
new file mode 100644
index 000000000000..2cb4836e8b31
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/runq.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: MIT */
+#ifndef __NVKM_RUNQ_H__
+#define __NVKM_RUNQ_H__
+#include <core/os.h>
+struct nvkm_runl;
+
+struct nvkm_runq {
+ const struct nvkm_runq_func {
+ void (*init)(struct nvkm_runq *);
+ bool (*intr)(struct nvkm_runq *, struct nvkm_runl *);
+ const struct nvkm_bitfield *intr_0_names;
+ bool (*intr_1_ctxnotvalid)(struct nvkm_runq *, int chid);
+ bool (*idle)(struct nvkm_runq *);
+ } *func;
+ struct nvkm_fifo *fifo;
+ int id;
+
+ struct list_head head;
+};
+
+struct nvkm_runq *nvkm_runq_new(struct nvkm_fifo *, int pbid);
+void nvkm_runq_del(struct nvkm_runq *);
+
+#define nvkm_runq_foreach(runq,fifo) list_for_each_entry((runq), &(fifo)->runqs, head)
+#define nvkm_runq_foreach_cond(runq,fifo,cond) nvkm_list_foreach(runq, &(fifo)->runqs, head, (cond))
+
+#define RUNQ_PRINT(r,l,p,f,a...) \
+ nvkm_printk__(&(r)->fifo->engine.subdev, NV_DBG_##l, p, "PBDMA%d:"f, (r)->id, ##a)
+#define RUNQ_ERROR(r,f,a...) RUNQ_PRINT((r), ERROR, err, " "f"\n", ##a)
+#define RUNQ_DEBUG(r,f,a...) RUNQ_PRINT((r), DEBUG, info, " "f"\n", ##a)
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c
index 260b197f81bc..ea9e151dbb48 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/tu102.c
@@ -19,46 +19,83 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "gk104.h"
+#include "priv.h"
#include "cgrp.h"
-#include "changk104.h"
-#include "user.h"
+#include "chan.h"
+#include "runl.h"
-#include <core/client.h>
-#include <core/gpuobj.h>
-#include <subdev/bar.h>
-#include <subdev/fault.h>
-#include <subdev/top.h>
-#include <subdev/timer.h>
-#include <engine/sw.h>
+#include <core/memory.h>
+#include <subdev/mc.h>
+#include <subdev/vfn.h>
#include <nvif/class.h>
+static u32
+tu102_chan_doorbell_handle(struct nvkm_chan *chan)
+{
+ return (chan->cgrp->runl->id << 16) | chan->id;
+}
+
static void
-tu102_fifo_runlist_commit(struct gk104_fifo *fifo, int runl,
- struct nvkm_memory *mem, int nr)
+tu102_chan_start(struct nvkm_chan *chan)
{
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- u64 addr = nvkm_memory_addr(mem);
- /*XXX: target? */
+ struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
+
+ gk104_chan_start(chan);
+ nvkm_wr32(device, device->vfn->addr.user + 0x0090, chan->func->doorbell_handle(chan));
+}
+
+static const struct nvkm_chan_func
+tu102_chan = {
+ .inst = &gf100_chan_inst,
+ .userd = &gv100_chan_userd,
+ .ramfc = &gv100_chan_ramfc,
+ .bind = gk104_chan_bind_inst,
+ .unbind = gk104_chan_unbind,
+ .start = tu102_chan_start,
+ .stop = gk104_chan_stop,
+ .preempt = gk110_chan_preempt,
+ .doorbell_handle = tu102_chan_doorbell_handle,
+};
+
+static bool
+tu102_runl_pending(struct nvkm_runl *runl)
+{
+ struct nvkm_device *device = runl->fifo->engine.subdev.device;
+
+ return nvkm_rd32(device, 0x002b0c + (runl->id * 0x10)) & 0x00008000;
+}
- nvkm_wr32(device, 0x002b00 + (runl * 0x10), lower_32_bits(addr));
- nvkm_wr32(device, 0x002b04 + (runl * 0x10), upper_32_bits(addr));
- nvkm_wr32(device, 0x002b08 + (runl * 0x10), nr);
+static void
+tu102_runl_commit(struct nvkm_runl *runl, struct nvkm_memory *memory, u32 start, int count)
+{
+ struct nvkm_device *device = runl->fifo->engine.subdev.device;
+ u64 addr = nvkm_memory_addr(memory) + start;
+ /*XXX: target? */
- /*XXX: how to wait? can you even wait? */
+ nvkm_wr32(device, 0x002b00 + (runl->id * 0x10), lower_32_bits(addr));
+ nvkm_wr32(device, 0x002b04 + (runl->id * 0x10), upper_32_bits(addr));
+ nvkm_wr32(device, 0x002b08 + (runl->id * 0x10), count);
}
-static const struct gk104_fifo_runlist_func
-tu102_fifo_runlist = {
+static const struct nvkm_runl_func
+tu102_runl = {
+ .runqs = 2,
.size = 16,
- .cgrp = gv100_fifo_runlist_cgrp,
- .chan = gv100_fifo_runlist_chan,
- .commit = tu102_fifo_runlist_commit,
+ .update = nv50_runl_update,
+ .insert_cgrp = gv100_runl_insert_cgrp,
+ .insert_chan = gv100_runl_insert_chan,
+ .commit = tu102_runl_commit,
+ .wait = nv50_runl_wait,
+ .pending = tu102_runl_pending,
+ .block = gk104_runl_block,
+ .allow = gk104_runl_allow,
+ .preempt = gv100_runl_preempt,
+ .preempt_pending = gf100_runl_preempt_pending,
};
static const struct nvkm_enum
-tu102_fifo_fault_engine[] = {
+tu102_fifo_mmu_fault_engine[] = {
{ 0x01, "DISPLAY" },
{ 0x03, "PTP" },
{ 0x06, "PWR_PMU" },
@@ -85,305 +122,82 @@ tu102_fifo_fault_engine[] = {
{}
};
-static void
-tu102_fifo_pbdma_init(struct gk104_fifo *fifo)
-{
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- const u32 mask = (1 << fifo->pbdma_nr) - 1;
- /*XXX: this is a bit of a guess at this point in time. */
- nvkm_mask(device, 0xb65000, 0x80000fff, 0x80000000 | mask);
-}
-
-static const struct gk104_fifo_pbdma_func
-tu102_fifo_pbdma = {
- .nr = gm200_fifo_pbdma_nr,
- .init = tu102_fifo_pbdma_init,
- .init_timeout = gk208_fifo_pbdma_init_timeout,
-};
-
-static const struct gk104_fifo_func
-tu102_fifo = {
- .pbdma = &tu102_fifo_pbdma,
- .fault.access = gv100_fifo_fault_access,
- .fault.engine = tu102_fifo_fault_engine,
- .fault.reason = gv100_fifo_fault_reason,
- .fault.hubclient = gv100_fifo_fault_hubclient,
- .fault.gpcclient = gv100_fifo_fault_gpcclient,
- .runlist = &tu102_fifo_runlist,
- .user = {{-1,-1,VOLTA_USERMODE_A }, tu102_fifo_user_new },
- .chan = {{ 0, 0,TURING_CHANNEL_GPFIFO_A}, tu102_fifo_gpfifo_new },
- .cgrp_force = true,
+const struct nvkm_fifo_func_mmu_fault
+tu102_fifo_mmu_fault = {
+ .recover = gf100_fifo_mmu_fault_recover,
+ .access = gv100_fifo_mmu_fault_access,
+ .engine = tu102_fifo_mmu_fault_engine,
+ .reason = gv100_fifo_mmu_fault_reason,
+ .hubclient = gv100_fifo_mmu_fault_hubclient,
+ .gpcclient = gv100_fifo_mmu_fault_gpcclient,
};
-static void
-tu102_fifo_recover_work(struct work_struct *w)
+void
+tu102_fifo_intr_ctxsw_timeout_info(struct nvkm_engn *engn, u32 info)
{
- struct gk104_fifo *fifo = container_of(w, typeof(*fifo), recover.work);
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- struct nvkm_engine *engine;
+ struct nvkm_runl *runl = engn->runl;
+ struct nvkm_cgrp *cgrp;
unsigned long flags;
- u32 engm, runm, todo;
- int engn, runl;
-
- spin_lock_irqsave(&fifo->base.lock, flags);
- runm = fifo->recover.runm;
- engm = fifo->recover.engm;
- fifo->recover.engm = 0;
- fifo->recover.runm = 0;
- spin_unlock_irqrestore(&fifo->base.lock, flags);
-
- nvkm_mask(device, 0x002630, runm, runm);
-
- for (todo = engm; engn = __ffs(todo), todo; todo &= ~BIT(engn)) {
- if ((engine = fifo->engine[engn].engine)) {
- nvkm_subdev_fini(&engine->subdev, false);
- WARN_ON(nvkm_subdev_init(&engine->subdev));
- }
- }
-
- for (todo = runm; runl = __ffs(todo), todo; todo &= ~BIT(runl))
- gk104_fifo_runlist_update(fifo, runl);
-
- nvkm_mask(device, 0x002630, runm, 0x00000000);
-}
-
-static void tu102_fifo_recover_engn(struct gk104_fifo *fifo, int engn);
-
-static void
-tu102_fifo_recover_runl(struct gk104_fifo *fifo, int runl)
-{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- const u32 runm = BIT(runl);
-
- assert_spin_locked(&fifo->base.lock);
- if (fifo->recover.runm & runm)
- return;
- fifo->recover.runm |= runm;
-
- /* Block runlist to prevent channel assignment(s) from changing. */
- nvkm_mask(device, 0x002630, runm, runm);
-
- /* Schedule recovery. */
- nvkm_warn(subdev, "runlist %d: scheduled for recovery\n", runl);
- schedule_work(&fifo->recover.work);
-}
-
-static struct gk104_fifo_chan *
-tu102_fifo_recover_chid(struct gk104_fifo *fifo, int runl, int chid)
-{
- struct gk104_fifo_chan *chan;
- struct nvkm_fifo_cgrp *cgrp;
-
- list_for_each_entry(chan, &fifo->runlist[runl].chan, head) {
- if (chan->base.chid == chid) {
- list_del_init(&chan->head);
- return chan;
- }
- }
-
- list_for_each_entry(cgrp, &fifo->runlist[runl].cgrp, head) {
- if (cgrp->id == chid) {
- chan = list_first_entry(&cgrp->chan, typeof(*chan), head);
- list_del_init(&chan->head);
- if (!--cgrp->chan_nr)
- list_del_init(&cgrp->head);
- return chan;
- }
- }
-
- return NULL;
-}
-static void
-tu102_fifo_recover_chan(struct nvkm_fifo *base, int chid)
-{
- struct gk104_fifo *fifo = gk104_fifo(base);
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- const u32 stat = nvkm_rd32(device, 0x800004 + (chid * 0x08));
- const u32 runl = (stat & 0x000f0000) >> 16;
- const bool used = (stat & 0x00000001);
- unsigned long engn, engm = fifo->runlist[runl].engm;
- struct gk104_fifo_chan *chan;
-
- assert_spin_locked(&fifo->base.lock);
- if (!used)
+ /* Check that engine hasn't become unstuck since timeout raised. */
+ ENGN_DEBUG(engn, "CTXSW_TIMEOUT %08x", info);
+ if (info & 0xc0000000)
return;
- /* Lookup SW state for channel, and mark it as dead. */
- chan = tu102_fifo_recover_chid(fifo, runl, chid);
- if (chan) {
- chan->killed = true;
- nvkm_fifo_kevent(&fifo->base, chid);
- }
-
- /* Disable channel. */
- nvkm_wr32(device, 0x800004 + (chid * 0x08), stat | 0x00000800);
- nvkm_warn(subdev, "channel %d: killed\n", chid);
-
- /* Block channel assignments from changing during recovery. */
- tu102_fifo_recover_runl(fifo, runl);
-
- /* Schedule recovery for any engines the channel is on. */
- for_each_set_bit(engn, &engm, fifo->engine_nr) {
- struct gk104_fifo_engine_status status;
-
- gk104_fifo_engine_status(fifo, engn, &status);
- if (!status.chan || status.chan->id != chid)
- continue;
- tu102_fifo_recover_engn(fifo, engn);
+ /* Determine channel group the engine is stuck on, and schedule recovery. */
+ switch (info & 0x0000c000) {
+ case 0x00004000: /* LOAD */
+ cgrp = nvkm_runl_cgrp_get_cgid(runl, info & 0x3fff0000, &flags);
+ break;
+ case 0x00008000: /* SAVE */
+ case 0x0000c000: /* SWITCH */
+ cgrp = nvkm_runl_cgrp_get_cgid(runl, info & 0x00003fff, &flags);
+ break;
+ default:
+ cgrp = NULL;
+ break;
}
-}
-
-static void
-tu102_fifo_recover_engn(struct gk104_fifo *fifo, int engn)
-{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- const u32 runl = fifo->engine[engn].runl;
- const u32 engm = BIT(engn);
- struct gk104_fifo_engine_status status;
-
- assert_spin_locked(&fifo->base.lock);
- if (fifo->recover.engm & engm)
- return;
- fifo->recover.engm |= engm;
- /* Block channel assignments from changing during recovery. */
- tu102_fifo_recover_runl(fifo, runl);
-
- /* Determine which channel (if any) is currently on the engine. */
- gk104_fifo_engine_status(fifo, engn, &status);
- if (status.chan) {
- /* The channel is not longer viable, kill it. */
- tu102_fifo_recover_chan(&fifo->base, status.chan->id);
+ if (!WARN_ON(!cgrp)) {
+ nvkm_runl_rc_cgrp(cgrp);
+ nvkm_cgrp_put(&cgrp, flags);
}
-
- /* Preempt the runlist */
- nvkm_wr32(device, 0x2638, BIT(runl));
-
- /* Schedule recovery. */
- nvkm_warn(subdev, "engine %d: scheduled for recovery\n", engn);
- schedule_work(&fifo->recover.work);
}
static void
-tu102_fifo_fault(struct nvkm_fifo *base, struct nvkm_fault_data *info)
+tu102_fifo_intr_ctxsw_timeout(struct nvkm_fifo *fifo)
{
- struct gk104_fifo *fifo = gk104_fifo(base);
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- const struct nvkm_enum *er, *ee, *ec, *ea;
- struct nvkm_engine *engine = NULL;
- struct nvkm_fifo_chan *chan;
- unsigned long flags;
- const char *en = "";
- char ct[8] = "HUB/";
- int engn;
-
- er = nvkm_enum_find(fifo->func->fault.reason, info->reason);
- ee = nvkm_enum_find(fifo->func->fault.engine, info->engine);
- if (info->hub) {
- ec = nvkm_enum_find(fifo->func->fault.hubclient, info->client);
- } else {
- ec = nvkm_enum_find(fifo->func->fault.gpcclient, info->client);
- snprintf(ct, sizeof(ct), "GPC%d/", info->gpc);
- }
- ea = nvkm_enum_find(fifo->func->fault.access, info->access);
-
- if (ee && ee->data2) {
- switch (ee->data2) {
- case NVKM_SUBDEV_BAR:
- nvkm_bar_bar1_reset(device);
- break;
- case NVKM_SUBDEV_INSTMEM:
- nvkm_bar_bar2_reset(device);
- break;
- case NVKM_ENGINE_IFB:
- nvkm_mask(device, 0x001718, 0x00000000, 0x00000000);
- break;
- default:
- engine = nvkm_device_engine(device, ee->data2, 0);
- break;
- }
- }
-
- if (ee == NULL) {
- struct nvkm_subdev *subdev = nvkm_top_fault(device, info->engine);
- if (subdev) {
- if (subdev->func == &nvkm_engine)
- engine = container_of(subdev, typeof(*engine), subdev);
- en = engine->subdev.name;
+ struct nvkm_device *device = fifo->engine.subdev.device;
+ struct nvkm_runl *runl;
+ struct nvkm_engn *engn;
+ u32 engm = nvkm_rd32(device, 0x002a30);
+ u32 info;
+
+ nvkm_runl_foreach(runl, fifo) {
+ nvkm_runl_foreach_engn_cond(engn, runl, engm & BIT(engn->id)) {
+ info = nvkm_rd32(device, 0x003200 + (engn->id * 4));
+ tu102_fifo_intr_ctxsw_timeout_info(engn, info);
}
- } else {
- en = ee->name;
}
- spin_lock_irqsave(&fifo->base.lock, flags);
- chan = nvkm_fifo_chan_inst_locked(&fifo->base, info->inst);
-
- nvkm_error(subdev,
- "fault %02x [%s] at %016llx engine %02x [%s] client %02x "
- "[%s%s] reason %02x [%s] on channel %d [%010llx %s]\n",
- info->access, ea ? ea->name : "", info->addr,
- info->engine, ee ? ee->name : en,
- info->client, ct, ec ? ec->name : "",
- info->reason, er ? er->name : "", chan ? chan->chid : -1,
- info->inst, chan ? chan->object.client->name : "unknown");
-
- /* Kill the channel that caused the fault. */
- if (chan)
- tu102_fifo_recover_chan(&fifo->base, chan->chid);
-
- /* Channel recovery will probably have already done this for the
- * correct engine(s), but just in case we can't find the channel
- * information...
- */
- for (engn = 0; engn < fifo->engine_nr && engine; engn++) {
- if (fifo->engine[engn].engine == engine) {
- tu102_fifo_recover_engn(fifo, engn);
- break;
- }
- }
-
- spin_unlock_irqrestore(&fifo->base.lock, flags);
-}
-
-static void
-tu102_fifo_intr_ctxsw_timeout(struct gk104_fifo *fifo)
-{
- struct nvkm_device *device = fifo->base.engine.subdev.device;
- unsigned long flags, engm;
- u32 engn;
-
- spin_lock_irqsave(&fifo->base.lock, flags);
-
- engm = nvkm_rd32(device, 0x2a30);
- nvkm_wr32(device, 0x2a30, engm);
-
- for_each_set_bit(engn, &engm, 32)
- tu102_fifo_recover_engn(fifo, engn);
-
- spin_unlock_irqrestore(&fifo->base.lock, flags);
+ nvkm_wr32(device, 0x002a30, engm);
}
static void
-tu102_fifo_intr_sched(struct gk104_fifo *fifo)
+tu102_fifo_intr_sched(struct nvkm_fifo *fifo)
{
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
- struct nvkm_device *device = subdev->device;
- u32 intr = nvkm_rd32(device, 0x00254c);
+ struct nvkm_subdev *subdev = &fifo->engine.subdev;
+ u32 intr = nvkm_rd32(subdev->device, 0x00254c);
u32 code = intr & 0x000000ff;
nvkm_error(subdev, "SCHED_ERROR %02x\n", code);
}
-static void
-tu102_fifo_intr(struct nvkm_fifo *base)
+static irqreturn_t
+tu102_fifo_intr(struct nvkm_inth *inth)
{
- struct gk104_fifo *fifo = gk104_fifo(base);
- struct nvkm_subdev *subdev = &fifo->base.engine.subdev;
+ struct nvkm_fifo *fifo = container_of(inth, typeof(*fifo), engine.subdev.inth);
+ struct nvkm_subdev *subdev = &fifo->engine.subdev;
struct nvkm_device *device = subdev->device;
u32 mask = nvkm_rd32(device, 0x002140);
u32 stat = nvkm_rd32(device, 0x002100) & mask;
@@ -412,17 +226,8 @@ tu102_fifo_intr(struct nvkm_fifo *base)
}
if (stat & 0x20000000) {
- u32 mask = nvkm_rd32(device, 0x0025a0);
-
- while (mask) {
- u32 unit = __ffs(mask);
-
- gk104_fifo_intr_pbdma_0(fifo, unit);
- gk104_fifo_intr_pbdma_1(fifo, unit);
- nvkm_wr32(device, 0x0025a0, (1 << unit));
- mask &= ~(1 << unit);
- }
- stat &= ~0x20000000;
+ if (gf100_fifo_intr_pbdma(fifo))
+ stat &= ~0x20000000;
}
if (stat & 0x40000000) {
@@ -432,46 +237,50 @@ tu102_fifo_intr(struct nvkm_fifo *base)
if (stat & 0x80000000) {
nvkm_wr32(device, 0x002100, 0x80000000);
- gk104_fifo_intr_engine(fifo);
+ nvkm_event_ntfy(&fifo->nonstall.event, 0, NVKM_FIFO_NONSTALL_EVENT);
stat &= ~0x80000000;
}
if (stat) {
nvkm_error(subdev, "INTR %08x\n", stat);
+ spin_lock(&fifo->lock);
nvkm_mask(device, 0x002140, stat, 0x00000000);
+ spin_unlock(&fifo->lock);
nvkm_wr32(device, 0x002100, stat);
}
+
+ return IRQ_HANDLED;
+}
+
+static void
+tu102_fifo_init_pbdmas(struct nvkm_fifo *fifo, u32 mask)
+{
+ /* Not directly related to PBDMAs, but, enables doorbell to function. */
+ nvkm_mask(fifo->engine.subdev.device, 0xb65000, 0x80000000, 0x80000000);
}
static const struct nvkm_fifo_func
-tu102_fifo_ = {
- .dtor = gk104_fifo_dtor,
- .oneinit = gk104_fifo_oneinit,
- .info = gk104_fifo_info,
+tu102_fifo = {
+ .chid_nr = gm200_fifo_chid_nr,
+ .chid_ctor = gk110_fifo_chid_ctor,
+ .runq_nr = gm200_fifo_runq_nr,
+ .runl_ctor = gk104_fifo_runl_ctor,
.init = gk104_fifo_init,
- .fini = gk104_fifo_fini,
+ .init_pbdmas = tu102_fifo_init_pbdmas,
.intr = tu102_fifo_intr,
- .fault = tu102_fifo_fault,
- .engine_id = gk104_fifo_engine_id,
- .id_engine = gk104_fifo_id_engine,
- .uevent_init = gk104_fifo_uevent_init,
- .uevent_fini = gk104_fifo_uevent_fini,
- .recover_chan = tu102_fifo_recover_chan,
- .class_get = gk104_fifo_class_get,
- .class_new = gk104_fifo_class_new,
+ .mmu_fault = &tu102_fifo_mmu_fault,
+ .nonstall = &gf100_fifo_nonstall,
+ .runl = &tu102_runl,
+ .runq = &gv100_runq,
+ .engn = &gv100_engn,
+ .engn_ce = &gv100_engn_ce,
+ .cgrp = {{ 0, 0, KEPLER_CHANNEL_GROUP_A }, &gk110_cgrp, .force = true },
+ .chan = {{ 0, 0, TURING_CHANNEL_GPFIFO_A }, &tu102_chan },
};
int
tu102_fifo_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fifo **pfifo)
{
- struct gk104_fifo *fifo;
-
- if (!(fifo = kzalloc(sizeof(*fifo), GFP_KERNEL)))
- return -ENOMEM;
- fifo->func = &tu102_fifo;
- INIT_WORK(&fifo->recover.work, tu102_fifo_recover_work);
- *pfifo = &fifo->base;
-
- return nvkm_fifo_ctor(&tu102_fifo_, device, type, inst, 4096, &fifo->base);
+ return nvkm_fifo_new_(&tu102_fifo, device, type, inst, pfifo);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ucgrp.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ucgrp.c
new file mode 100644
index 000000000000..52c594dfb1b8
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/ucgrp.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2021 Red Hat 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.
+ */
+#define nvkm_ucgrp(p) container_of((p), struct nvkm_ucgrp, object)
+#include "priv.h"
+#include "cgrp.h"
+#include "runl.h"
+
+#include <subdev/mmu.h>
+
+#include <nvif/if0021.h>
+
+struct nvkm_ucgrp {
+ struct nvkm_object object;
+ struct nvkm_cgrp *cgrp;
+};
+
+static int
+nvkm_ucgrp_chan_new(const struct nvkm_oclass *oclass, void *argv, u32 argc,
+ struct nvkm_object **pobject)
+{
+ struct nvkm_cgrp *cgrp = nvkm_ucgrp(oclass->parent)->cgrp;
+
+ return nvkm_uchan_new(cgrp->runl->fifo, cgrp, oclass, argv, argc, pobject);
+}
+
+static int
+nvkm_ucgrp_sclass(struct nvkm_object *object, int index, struct nvkm_oclass *oclass)
+{
+ struct nvkm_cgrp *cgrp = nvkm_ucgrp(object)->cgrp;
+ struct nvkm_fifo *fifo = cgrp->runl->fifo;
+ const struct nvkm_fifo_func_chan *chan = &fifo->func->chan;
+ int c = 0;
+
+ /* *_CHANNEL_GPFIFO_* */
+ if (chan->user.oclass) {
+ if (c++ == index) {
+ oclass->base = chan->user;
+ oclass->ctor = nvkm_ucgrp_chan_new;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static void *
+nvkm_ucgrp_dtor(struct nvkm_object *object)
+{
+ struct nvkm_ucgrp *ucgrp = nvkm_ucgrp(object);
+
+ nvkm_cgrp_unref(&ucgrp->cgrp);
+ return ucgrp;
+}
+
+static const struct nvkm_object_func
+nvkm_ucgrp = {
+ .dtor = nvkm_ucgrp_dtor,
+ .sclass = nvkm_ucgrp_sclass,
+};
+
+int
+nvkm_ucgrp_new(struct nvkm_fifo *fifo, const struct nvkm_oclass *oclass, void *argv, u32 argc,
+ struct nvkm_object **pobject)
+{
+ union nvif_cgrp_args *args = argv;
+ struct nvkm_runl *runl;
+ struct nvkm_vmm *vmm;
+ struct nvkm_ucgrp *ucgrp;
+ int ret;
+
+ if (argc < sizeof(args->v0) || args->v0.version != 0)
+ return -ENOSYS;
+ argc -= sizeof(args->v0);
+
+ if (args->v0.namelen != argc)
+ return -EINVAL;
+
+ /* Lookup objects referenced in args. */
+ runl = nvkm_runl_get(fifo, args->v0.runlist, 0);
+ if (!runl)
+ return -EINVAL;
+
+ vmm = nvkm_uvmm_search(oclass->client, args->v0.vmm);
+ if (IS_ERR(vmm))
+ return PTR_ERR(vmm);
+
+ /* Allocate channel group. */
+ if (!(ucgrp = kzalloc(sizeof(*ucgrp), GFP_KERNEL))) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ nvkm_object_ctor(&nvkm_ucgrp, oclass, &ucgrp->object);
+ *pobject = &ucgrp->object;
+
+ ret = nvkm_cgrp_new(runl, args->v0.name, vmm, true, &ucgrp->cgrp);
+ if (ret)
+ goto done;
+
+ /* Return channel group info to caller. */
+ args->v0.cgid = ucgrp->cgrp->id;
+
+done:
+ nvkm_vmm_unref(&vmm);
+ return ret;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c
new file mode 100644
index 000000000000..1dac95ae7b43
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/uchan.c
@@ -0,0 +1,409 @@
+/*
+ * Copyright 2021 Red Hat 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.
+ */
+#define nvkm_uchan(p) container_of((p), struct nvkm_uchan, object)
+#include "priv.h"
+#include "cgrp.h"
+#include "chan.h"
+#include "chid.h"
+#include "runl.h"
+
+#include <core/gpuobj.h>
+#include <core/oproxy.h>
+#include <subdev/mmu.h>
+#include <engine/dma.h>
+
+#include <nvif/if0020.h>
+
+struct nvkm_uchan {
+ struct nvkm_object object;
+ struct nvkm_chan *chan;
+};
+
+static int
+nvkm_uchan_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent)
+{
+ struct nvkm_chan *chan = nvkm_uchan(object)->chan;
+ struct nvkm_runl *runl = chan->cgrp->runl;
+ union nvif_chan_event_args *args = argv;
+
+ if (!uevent)
+ return 0;
+ if (argc != sizeof(args->v0) || args->v0.version != 0)
+ return -ENOSYS;
+
+ switch (args->v0.type) {
+ case NVIF_CHAN_EVENT_V0_NON_STALL_INTR:
+ return nvkm_uevent_add(uevent, &runl->fifo->nonstall.event, 0,
+ NVKM_FIFO_NONSTALL_EVENT, NULL);
+ case NVIF_CHAN_EVENT_V0_KILLED:
+ return nvkm_uevent_add(uevent, &runl->chid->event, chan->id,
+ NVKM_CHAN_EVENT_ERRORED, NULL);
+ default:
+ break;
+ }
+
+ return -ENOSYS;
+}
+
+struct nvkm_uobj {
+ struct nvkm_oproxy oproxy;
+ struct nvkm_chan *chan;
+ struct nvkm_cctx *cctx;
+ int hash;
+};
+
+static int
+nvkm_uchan_object_fini_1(struct nvkm_oproxy *oproxy, bool suspend)
+{
+ struct nvkm_uobj *uobj = container_of(oproxy, typeof(*uobj), oproxy);
+ struct nvkm_chan *chan = uobj->chan;
+ struct nvkm_cctx *cctx = uobj->cctx;
+ struct nvkm_ectx *ectx = cctx->vctx->ectx;
+
+ if (!ectx->object)
+ return 0;
+
+ /* Unbind engine context from channel, if no longer required. */
+ if (refcount_dec_and_mutex_lock(&cctx->uses, &chan->cgrp->mutex)) {
+ nvkm_chan_cctx_bind(chan, ectx->engn, NULL);
+
+ if (refcount_dec_and_test(&ectx->uses))
+ nvkm_object_fini(ectx->object, false);
+ mutex_unlock(&chan->cgrp->mutex);
+ }
+
+ return 0;
+}
+
+static int
+nvkm_uchan_object_init_0(struct nvkm_oproxy *oproxy)
+{
+ struct nvkm_uobj *uobj = container_of(oproxy, typeof(*uobj), oproxy);
+ struct nvkm_chan *chan = uobj->chan;
+ struct nvkm_cctx *cctx = uobj->cctx;
+ struct nvkm_ectx *ectx = cctx->vctx->ectx;
+ int ret = 0;
+
+ if (!ectx->object)
+ return 0;
+
+ /* Bind engine context to channel, if it hasn't been already. */
+ if (!refcount_inc_not_zero(&cctx->uses)) {
+ mutex_lock(&chan->cgrp->mutex);
+ if (!refcount_inc_not_zero(&cctx->uses)) {
+ if (!refcount_inc_not_zero(&ectx->uses)) {
+ ret = nvkm_object_init(ectx->object);
+ if (ret == 0)
+ refcount_set(&ectx->uses, 1);
+ }
+
+ if (ret == 0) {
+ nvkm_chan_cctx_bind(chan, ectx->engn, cctx);
+ refcount_set(&cctx->uses, 1);
+ }
+ }
+ mutex_unlock(&chan->cgrp->mutex);
+ }
+
+ return ret;
+}
+
+static void
+nvkm_uchan_object_dtor(struct nvkm_oproxy *oproxy)
+{
+ struct nvkm_uobj *uobj = container_of(oproxy, typeof(*uobj), oproxy);
+ struct nvkm_engn *engn;
+
+ if (!uobj->cctx)
+ return;
+
+ engn = uobj->cctx->vctx->ectx->engn;
+ if (engn->func->ramht_del)
+ engn->func->ramht_del(uobj->chan, uobj->hash);
+
+ nvkm_chan_cctx_put(uobj->chan, &uobj->cctx);
+}
+
+static const struct nvkm_oproxy_func
+nvkm_uchan_object = {
+ .dtor[1] = nvkm_uchan_object_dtor,
+ .init[0] = nvkm_uchan_object_init_0,
+ .fini[1] = nvkm_uchan_object_fini_1,
+};
+
+static int
+nvkm_uchan_object_new(const struct nvkm_oclass *oclass, void *argv, u32 argc,
+ struct nvkm_object **pobject)
+{
+ struct nvkm_chan *chan = nvkm_uchan(oclass->parent)->chan;
+ struct nvkm_cgrp *cgrp = chan->cgrp;
+ struct nvkm_engn *engn;
+ struct nvkm_uobj *uobj;
+ int ret;
+
+ /* Lookup host engine state for target engine. */
+ engn = nvkm_runl_find_engn(engn, cgrp->runl, engn->engine == oclass->engine);
+ if (WARN_ON(!engn))
+ return -EINVAL;
+
+ /* Allocate SW object. */
+ if (!(uobj = kzalloc(sizeof(*uobj), GFP_KERNEL)))
+ return -ENOMEM;
+
+ nvkm_oproxy_ctor(&nvkm_uchan_object, oclass, &uobj->oproxy);
+ uobj->chan = chan;
+ *pobject = &uobj->oproxy.base;
+
+ /* Ref. channel context for target engine.*/
+ ret = nvkm_chan_cctx_get(chan, engn, &uobj->cctx, oclass->client);
+ if (ret)
+ return ret;
+
+ /* Allocate HW object. */
+ ret = oclass->base.ctor(&(const struct nvkm_oclass) {
+ .base = oclass->base,
+ .engn = oclass->engn,
+ .handle = oclass->handle,
+ .object = oclass->object,
+ .client = oclass->client,
+ .parent = uobj->cctx->vctx->ectx->object ?: oclass->parent,
+ .engine = engn->engine,
+ }, argv, argc, &uobj->oproxy.object);
+ if (ret)
+ return ret;
+
+ if (engn->func->ramht_add) {
+ uobj->hash = engn->func->ramht_add(engn, uobj->oproxy.object, uobj->chan);
+ if (uobj->hash < 0)
+ return uobj->hash;
+ }
+
+ return 0;
+}
+
+static int
+nvkm_uchan_sclass(struct nvkm_object *object, int index, struct nvkm_oclass *oclass)
+{
+ struct nvkm_chan *chan = nvkm_uchan(object)->chan;
+ struct nvkm_engn *engn;
+ int ret, runq = 0;
+
+ nvkm_runl_foreach_engn(engn, chan->cgrp->runl) {
+ struct nvkm_engine *engine = engn->engine;
+ int c = 0;
+
+ /* Each runqueue, on runlists with multiple, has its own LCE. */
+ if (engn->runl->func->runqs) {
+ if (engine->subdev.type == NVKM_ENGINE_CE) {
+ if (chan->runq != runq++)
+ continue;
+ }
+ }
+
+ oclass->engine = engine;
+ oclass->base.oclass = 0;
+
+ if (engine->func->fifo.sclass) {
+ ret = engine->func->fifo.sclass(oclass, index);
+ if (oclass->base.oclass) {
+ if (!oclass->base.ctor)
+ oclass->base.ctor = nvkm_object_new;
+ oclass->ctor = nvkm_uchan_object_new;
+ return 0;
+ }
+
+ index -= ret;
+ continue;
+ }
+
+ while (engine->func->sclass[c].oclass) {
+ if (c++ == index) {
+ oclass->base = engine->func->sclass[index];
+ if (!oclass->base.ctor)
+ oclass->base.ctor = nvkm_object_new;
+ oclass->ctor = nvkm_uchan_object_new;
+ return 0;
+ }
+ }
+
+ index -= c;
+ }
+
+ return -EINVAL;
+}
+
+static int
+nvkm_uchan_map(struct nvkm_object *object, void *argv, u32 argc,
+ enum nvkm_object_map *type, u64 *addr, u64 *size)
+{
+ struct nvkm_chan *chan = nvkm_uchan(object)->chan;
+ struct nvkm_device *device = chan->cgrp->runl->fifo->engine.subdev.device;
+
+ if (chan->func->userd->bar < 0)
+ return -ENOSYS;
+
+ *type = NVKM_OBJECT_MAP_IO;
+ *addr = device->func->resource_addr(device, chan->func->userd->bar) +
+ chan->func->userd->base + chan->userd.base;
+ *size = chan->func->userd->size;
+ return 0;
+}
+
+static int
+nvkm_uchan_fini(struct nvkm_object *object, bool suspend)
+{
+ struct nvkm_chan *chan = nvkm_uchan(object)->chan;
+
+ nvkm_chan_block(chan);
+ nvkm_chan_remove(chan, true);
+
+ if (chan->func->unbind)
+ chan->func->unbind(chan);
+
+ return 0;
+}
+
+static int
+nvkm_uchan_init(struct nvkm_object *object)
+{
+ struct nvkm_chan *chan = nvkm_uchan(object)->chan;
+
+ if (atomic_read(&chan->errored))
+ return 0;
+
+ if (chan->func->bind)
+ chan->func->bind(chan);
+
+ nvkm_chan_allow(chan);
+ nvkm_chan_insert(chan);
+ return 0;
+}
+
+static void *
+nvkm_uchan_dtor(struct nvkm_object *object)
+{
+ struct nvkm_uchan *uchan = nvkm_uchan(object);
+
+ nvkm_chan_del(&uchan->chan);
+ return uchan;
+}
+
+static const struct nvkm_object_func
+nvkm_uchan = {
+ .dtor = nvkm_uchan_dtor,
+ .init = nvkm_uchan_init,
+ .fini = nvkm_uchan_fini,
+ .map = nvkm_uchan_map,
+ .sclass = nvkm_uchan_sclass,
+ .uevent = nvkm_uchan_uevent,
+};
+
+int
+nvkm_uchan_new(struct nvkm_fifo *fifo, struct nvkm_cgrp *cgrp, const struct nvkm_oclass *oclass,
+ void *argv, u32 argc, struct nvkm_object **pobject)
+{
+ union nvif_chan_args *args = argv;
+ struct nvkm_runl *runl;
+ struct nvkm_vmm *vmm = NULL;
+ struct nvkm_dmaobj *ctxdma = NULL;
+ struct nvkm_memory *userd = NULL;
+ struct nvkm_uchan *uchan;
+ struct nvkm_chan *chan;
+ int ret;
+
+ if (argc < sizeof(args->v0) || args->v0.version != 0)
+ return -ENOSYS;
+ argc -= sizeof(args->v0);
+
+ if (args->v0.namelen != argc)
+ return -EINVAL;
+
+ /* Lookup objects referenced in args. */
+ runl = nvkm_runl_get(fifo, args->v0.runlist, 0);
+ if (!runl)
+ return -EINVAL;
+
+ if (args->v0.vmm) {
+ vmm = nvkm_uvmm_search(oclass->client, args->v0.vmm);
+ if (IS_ERR(vmm))
+ return PTR_ERR(vmm);
+ }
+
+ if (args->v0.ctxdma) {
+ ctxdma = nvkm_dmaobj_search(oclass->client, args->v0.ctxdma);
+ if (IS_ERR(ctxdma)) {
+ ret = PTR_ERR(ctxdma);
+ goto done;
+ }
+ }
+
+ if (args->v0.huserd) {
+ userd = nvkm_umem_search(oclass->client, args->v0.huserd);
+ if (IS_ERR(userd)) {
+ ret = PTR_ERR(userd);
+ userd = NULL;
+ goto done;
+ }
+ }
+
+ /* Allocate channel. */
+ if (!(uchan = kzalloc(sizeof(*uchan), GFP_KERNEL))) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ nvkm_object_ctor(&nvkm_uchan, oclass, &uchan->object);
+ *pobject = &uchan->object;
+
+ ret = nvkm_chan_new_(fifo->func->chan.func, runl, args->v0.runq, cgrp, args->v0.name,
+ args->v0.priv != 0, args->v0.devm, vmm, ctxdma, args->v0.offset,
+ args->v0.length, userd, args->v0.ouserd, &uchan->chan);
+ if (ret)
+ goto done;
+
+ chan = uchan->chan;
+
+ /* Return channel info to caller. */
+ if (chan->func->doorbell_handle)
+ args->v0.token = chan->func->doorbell_handle(chan);
+ else
+ args->v0.token = ~0;
+
+ args->v0.chid = chan->id;
+
+ switch (nvkm_memory_target(chan->inst->memory)) {
+ case NVKM_MEM_TARGET_INST: args->v0.aper = NVIF_CHAN_V0_INST_APER_INST; break;
+ case NVKM_MEM_TARGET_VRAM: args->v0.aper = NVIF_CHAN_V0_INST_APER_VRAM; break;
+ case NVKM_MEM_TARGET_HOST: args->v0.aper = NVIF_CHAN_V0_INST_APER_HOST; break;
+ case NVKM_MEM_TARGET_NCOH: args->v0.aper = NVIF_CHAN_V0_INST_APER_NCOH; break;
+ default:
+ WARN_ON(1);
+ ret = -EFAULT;
+ break;
+ }
+
+ args->v0.inst = nvkm_memory_addr(chan->inst->memory);
+done:
+ nvkm_memory_unref(&userd);
+ nvkm_vmm_unref(&vmm);
+ return ret;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/user.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/user.h
deleted file mode 100644
index 54a3a3092cc0..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/user.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef __NVKM_FIFO_USER_H__
-#define __NVKM_FIFO_USER_H__
-#include "priv.h"
-int gv100_fifo_user_new(const struct nvkm_oclass *, void *, u32,
- struct nvkm_object **);
-int tu102_fifo_user_new(const struct nvkm_oclass *, void *, u32,
- struct nvkm_object **);
-#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild
index 558c86fd8e82..b5418f05ccd8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/Kbuild
@@ -40,6 +40,7 @@ nvkm-y += nvkm/engine/gr/gp108.o
nvkm-y += nvkm/engine/gr/gp10b.o
nvkm-y += nvkm/engine/gr/gv100.o
nvkm-y += nvkm/engine/gr/tu102.o
+nvkm-y += nvkm/engine/gr/ga102.o
nvkm-y += nvkm/engine/gr/ctxnv40.o
nvkm-y += nvkm/engine/gr/ctxnv50.o
@@ -63,3 +64,4 @@ nvkm-y += nvkm/engine/gr/ctxgp104.o
nvkm-y += nvkm/engine/gr/ctxgp107.o
nvkm-y += nvkm/engine/gr/ctxgv100.o
nvkm-y += nvkm/engine/gr/ctxtu102.o
+nvkm-y += nvkm/engine/gr/ctxga102.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c
index 61759f54406e..71b824e6da9d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/base.c
@@ -136,6 +136,17 @@ nvkm_gr_oneinit(struct nvkm_engine *engine)
}
static int
+nvkm_gr_reset(struct nvkm_engine *engine)
+{
+ struct nvkm_gr *gr = nvkm_gr(engine);
+
+ if (gr->func->reset)
+ return gr->func->reset(gr);
+
+ return -ENOSYS;
+}
+
+static int
nvkm_gr_init(struct nvkm_engine *engine)
{
struct nvkm_gr *gr = nvkm_gr(engine);
@@ -166,6 +177,7 @@ nvkm_gr = {
.oneinit = nvkm_gr_oneinit,
.init = nvkm_gr_init,
.fini = nvkm_gr_fini,
+ .reset = nvkm_gr_reset,
.intr = nvkm_gr_intr,
.tile = nvkm_gr_tile,
.chsw_load = nvkm_gr_chsw_load,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxga102.c
new file mode 100644
index 000000000000..11461adf5036
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxga102.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2019 Red Hat 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 "ctxgf100.h"
+
+static void
+ga102_grctx_generate_sm_id(struct gf100_gr *gr, int gpc, int tpc, int sm)
+{
+ struct nvkm_device *device = gr->base.engine.subdev.device;
+
+ tpc = gv100_gr_nonpes_aware_tpc(gr, gpc, tpc);
+
+ nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x608), sm);
+}
+
+static void
+ga102_grctx_generate_unkn(struct gf100_gr *gr)
+{
+ struct nvkm_device *device = gr->base.engine.subdev.device;
+
+ nvkm_mask(device, 0x41980c, 0x00000010, 0x00000010);
+ nvkm_mask(device, 0x41be08, 0x00000004, 0x00000004);
+}
+
+static void
+ga102_grctx_generate_r419ea8(struct gf100_gr *gr)
+{
+ struct nvkm_device *device = gr->base.engine.subdev.device;
+
+ nvkm_wr32(device, 0x419ea8, nvkm_rd32(device, 0x504728) | 0x08000000);
+}
+
+const struct gf100_grctx_func
+ga102_grctx = {
+ .main = gf100_grctx_generate_main,
+ .unkn = ga102_grctx_generate_unkn,
+ .bundle = gm107_grctx_generate_bundle,
+ .bundle_size = 0x3000,
+ .bundle_min_gpm_fifo_depth = 0x180,
+ .bundle_token_limit = 0x1140,
+ .pagepool = gp100_grctx_generate_pagepool,
+ .pagepool_size = 0x20000,
+ .attrib_cb_size = gp102_grctx_generate_attrib_cb_size,
+ .attrib_cb = gv100_grctx_generate_attrib_cb,
+ .attrib = gv100_grctx_generate_attrib,
+ .attrib_nr_max = 0x800,
+ .attrib_nr = 0x4a1,
+ .alpha_nr_max = 0xc00,
+ .alpha_nr = 0x800,
+ .unknown_size = 0x80000,
+ .unknown = tu102_grctx_generate_unknown,
+ .gfxp_nr = 0xd28,
+ .sm_id = ga102_grctx_generate_sm_id,
+ .skip_pd_num_tpc_per_gpc = true,
+ .rop_mapping = gv100_grctx_generate_rop_mapping,
+ .r406500 = gm200_grctx_generate_r406500,
+ .r400088 = gv100_grctx_generate_r400088,
+ .r419ea8 = ga102_grctx_generate_r419ea8,
+};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c
index 297915719bf2..cb390e0134a2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c
@@ -26,6 +26,7 @@
#include <subdev/fb.h>
#include <subdev/mc.h>
#include <subdev/timer.h>
+#include <engine/fifo.h>
/*******************************************************************************
* PGRAPH context register lists
@@ -990,43 +991,16 @@ gf100_grctx_pack_tpc[] = {
* PGRAPH context implementation
******************************************************************************/
-int
-gf100_grctx_mmio_data(struct gf100_grctx *info, u32 size, u32 align, bool priv)
-{
- if (info->data) {
- info->buffer[info->buffer_nr] = round_up(info->addr, align);
- info->addr = info->buffer[info->buffer_nr] + size;
- info->data->size = size;
- info->data->align = align;
- info->data->priv = priv;
- info->data++;
- return info->buffer_nr++;
- }
- return -1;
-}
-
void
-gf100_grctx_mmio_item(struct gf100_grctx *info, u32 addr, u32 data,
- int shift, int buffer)
+gf100_grctx_patch_wr32(struct gf100_gr_chan *chan, u32 addr, u32 data)
{
- struct nvkm_device *device = info->gr->base.engine.subdev.device;
- if (info->data) {
- if (shift >= 0) {
- info->mmio->addr = addr;
- info->mmio->data = data;
- info->mmio->shift = shift;
- info->mmio->buffer = buffer;
- if (buffer >= 0)
- data |= info->buffer[buffer] >> shift;
- info->mmio++;
- } else
- return;
- } else {
- if (buffer >= 0)
- return;
+ if (unlikely(!chan->mmio)) {
+ nvkm_wr32(chan->gr->base.engine.subdev.device, addr, data);
+ return;
}
- nvkm_wr32(device, addr, data);
+ nvkm_wo32(chan->mmio, chan->mmio_nr++ * 4, addr);
+ nvkm_wo32(chan->mmio, chan->mmio_nr++ * 4, data);
}
void
@@ -1037,56 +1011,60 @@ gf100_grctx_generate_r419cb8(struct gf100_gr *gr)
}
void
-gf100_grctx_generate_bundle(struct gf100_grctx *info)
+gf100_grctx_generate_bundle(struct gf100_gr_chan *chan, u64 addr, u32 size)
{
- const struct gf100_grctx_func *grctx = info->gr->func->grctx;
- const int s = 8;
- const int b = mmio_vram(info, grctx->bundle_size, (1 << s), true);
- mmio_refn(info, 0x408004, 0x00000000, s, b);
- mmio_wr32(info, 0x408008, 0x80000000 | (grctx->bundle_size >> s));
- mmio_refn(info, 0x418808, 0x00000000, s, b);
- mmio_wr32(info, 0x41880c, 0x80000000 | (grctx->bundle_size >> s));
+ gf100_grctx_patch_wr32(chan, 0x408004, addr >> 8);
+ gf100_grctx_patch_wr32(chan, 0x408008, 0x80000000 | (size >> 8));
+ gf100_grctx_patch_wr32(chan, 0x418808, addr >> 8);
+ gf100_grctx_patch_wr32(chan, 0x41880c, 0x80000000 | (size >> 8));
}
void
-gf100_grctx_generate_pagepool(struct gf100_grctx *info)
+gf100_grctx_generate_pagepool(struct gf100_gr_chan *chan, u64 addr)
{
- const struct gf100_grctx_func *grctx = info->gr->func->grctx;
- const int s = 8;
- const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), true);
- mmio_refn(info, 0x40800c, 0x00000000, s, b);
- mmio_wr32(info, 0x408010, 0x80000000);
- mmio_refn(info, 0x419004, 0x00000000, s, b);
- mmio_wr32(info, 0x419008, 0x00000000);
+ gf100_grctx_patch_wr32(chan, 0x40800c, addr >> 8);
+ gf100_grctx_patch_wr32(chan, 0x408010, 0x80000000);
+ gf100_grctx_patch_wr32(chan, 0x419004, addr >> 8);
+ gf100_grctx_patch_wr32(chan, 0x419008, 0x00000000);
}
void
-gf100_grctx_generate_attrib(struct gf100_grctx *info)
+gf100_grctx_generate_attrib(struct gf100_gr_chan *chan)
{
- struct gf100_gr *gr = info->gr;
+ struct gf100_gr *gr = chan->gr;
const struct gf100_grctx_func *grctx = gr->func->grctx;
const u32 attrib = grctx->attrib_nr;
- const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max);
- const int s = 12;
- const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), false);
int gpc, tpc;
u32 bo = 0;
- mmio_refn(info, 0x418810, 0x80000000, s, b);
- mmio_refn(info, 0x419848, 0x10000000, s, b);
- mmio_wr32(info, 0x405830, (attrib << 16));
+ gf100_grctx_patch_wr32(chan, 0x405830, (attrib << 16));
for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
for (tpc = 0; tpc < gr->tpc_nr[gpc]; tpc++) {
const u32 o = TPC_UNIT(gpc, tpc, 0x0520);
- mmio_skip(info, o, (attrib << 16) | ++bo);
- mmio_wr32(info, o, (attrib << 16) | --bo);
+
+ gf100_grctx_patch_wr32(chan, o, (attrib << 16) | bo);
bo += grctx->attrib_nr_max;
}
}
}
void
+gf100_grctx_generate_attrib_cb(struct gf100_gr_chan *chan, u64 addr, u32 size)
+{
+ gf100_grctx_patch_wr32(chan, 0x418810, 0x80000000 | addr >> 12);
+ gf100_grctx_patch_wr32(chan, 0x419848, 0x10000000 | addr >> 12);
+}
+
+u32
+gf100_grctx_generate_attrib_cb_size(struct gf100_gr *gr)
+{
+ const struct gf100_grctx_func *grctx = gr->func->grctx;
+
+ return 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max) * gr->tpc_total;
+}
+
+void
gf100_grctx_generate_unkn(struct gf100_gr *gr)
{
}
@@ -1361,8 +1339,9 @@ gf100_grctx_generate_floorsweep(struct gf100_gr *gr)
}
void
-gf100_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info)
+gf100_grctx_generate_main(struct gf100_gr_chan *chan)
{
+ struct gf100_gr *gr = chan->gr;
struct nvkm_device *device = gr->base.engine.subdev.device;
const struct gf100_grctx_func *grctx = gr->func->grctx;
u32 idle_timeout;
@@ -1380,15 +1359,23 @@ gf100_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info)
gf100_gr_mmio(gr, gr->sw_ctx);
}
+ if (gr->func->init_419bd8)
+ gr->func->init_419bd8(gr);
+ if (grctx->r419ea8)
+ grctx->r419ea8(gr);
+
gf100_gr_wait_idle(gr);
idle_timeout = nvkm_mask(device, 0x404154, 0xffffffff, 0x00000000);
- grctx->pagepool(info);
- grctx->bundle(info);
- grctx->attrib(info);
+ grctx->pagepool(chan, chan->pagepool->addr);
+ grctx->bundle(chan, chan->bundle_cb->addr, grctx->bundle_size);
+ grctx->attrib_cb(chan, chan->attrib_cb->addr, grctx->attrib_cb_size(gr));
+ grctx->attrib(chan);
if (grctx->patch_ltc)
- grctx->patch_ltc(info);
+ grctx->patch_ltc(chan);
+ if (grctx->unknown_size)
+ grctx->unknown(chan, chan->unknown->addr, grctx->unknown_size);
grctx->unkn(gr);
gf100_grctx_generate_floorsweep(gr);
@@ -1396,12 +1383,23 @@ gf100_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info)
gf100_gr_wait_idle(gr);
if (grctx->r400088) grctx->r400088(gr, false);
+
if (gr->bundle)
gf100_gr_icmd(gr, gr->bundle);
else
gf100_gr_icmd(gr, grctx->icmd);
- if (grctx->sw_veid_bundle_init)
+
+ if (gr->bundle_veid)
+ gf100_gr_icmd(gr, gr->bundle_veid);
+ else
gf100_gr_icmd(gr, grctx->sw_veid_bundle_init);
+
+ if (gr->bundle64)
+ gf100_gr_icmd(gr, gr->bundle64);
+ else
+ if (grctx->sw_bundle64_init)
+ gf100_gr_icmd(gr, grctx->sw_bundle64_init);
+
if (grctx->r400088) grctx->r400088(gr, true);
nvkm_wr32(device, 0x404154, idle_timeout);
@@ -1428,21 +1426,20 @@ gf100_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info)
grctx->r408840(gr);
if (grctx->r419c0c)
grctx->r419c0c(gr);
+
+ gf100_gr_wait_idle(gr);
}
#define CB_RESERVED 0x80000
int
-gf100_grctx_generate(struct gf100_gr *gr)
+gf100_grctx_generate(struct gf100_gr *gr, struct gf100_gr_chan *chan, struct nvkm_gpuobj *inst)
{
const struct gf100_grctx_func *grctx = gr->func->grctx;
struct nvkm_subdev *subdev = &gr->base.engine.subdev;
struct nvkm_device *device = subdev->device;
- struct nvkm_memory *inst = NULL;
struct nvkm_memory *data = NULL;
- struct nvkm_vmm *vmm = NULL;
struct nvkm_vma *ctx = NULL;
- struct gf100_grctx info;
int ret, i;
u64 addr;
@@ -1457,72 +1454,47 @@ gf100_grctx_generate(struct gf100_gr *gr)
grctx->unkn88c(gr, true);
/* Reset FECS. */
- nvkm_wr32(device, 0x409614, 0x00000070);
- nvkm_usec(device, 10, NVKM_DELAY);
- nvkm_mask(device, 0x409614, 0x00000700, 0x00000700);
- nvkm_usec(device, 10, NVKM_DELAY);
- nvkm_rd32(device, 0x409614);
+ gr->func->fecs.reset(gr);
if (grctx->unkn88c)
grctx->unkn88c(gr, false);
/* NV_PGRAPH_FE_PWR_MODE_AUTO. */
nvkm_wr32(device, 0x404170, 0x00000010);
+ nvkm_msec(device, 2000,
+ if (!(nvkm_rd32(device, 0x404170) & 0x00000010))
+ break;
+ );
/* Init SCC RAM. */
nvkm_wr32(device, 0x40802c, 0x00000001);
- /* Allocate memory to for a "channel", which we'll use to generate
- * the default context values.
- */
- ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
- 0x1000, 0x1000, true, &inst);
- if (ret)
- goto done;
-
- ret = nvkm_vmm_new(device, 0, 0, NULL, 0, NULL, "grctx", &vmm);
- if (ret)
- goto done;
-
- vmm->debug = subdev->debug;
-
- ret = nvkm_vmm_join(vmm, inst);
- if (ret)
- goto done;
-
+ /* Allocate memory to store context, and dummy global context buffers. */
ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
CB_RESERVED + gr->size, 0, true, &data);
if (ret)
goto done;
- ret = nvkm_vmm_get(vmm, 0, nvkm_memory_size(data), &ctx);
+ ret = nvkm_vmm_get(chan->vmm, 0, nvkm_memory_size(data), &ctx);
if (ret)
goto done;
- ret = nvkm_memory_map(data, 0, vmm, ctx, NULL, 0);
+ ret = nvkm_memory_map(data, 0, chan->vmm, ctx, NULL, 0);
if (ret)
goto done;
-
/* Setup context pointer. */
nvkm_kmap(inst);
nvkm_wo32(inst, 0x0210, lower_32_bits(ctx->addr + CB_RESERVED) | 4);
nvkm_wo32(inst, 0x0214, upper_32_bits(ctx->addr + CB_RESERVED));
nvkm_done(inst);
- /* Setup default state for mmio list construction. */
- info.gr = gr;
- info.data = gr->mmio_data;
- info.mmio = gr->mmio_list;
- info.addr = ctx->addr;
- info.buffer_nr = 0;
-
/* Make channel current. */
- addr = nvkm_memory_addr(inst) >> 12;
+ addr = inst->addr >> 12;
if (gr->firmware) {
ret = gf100_gr_fecs_bind_pointer(gr, 0x80000000 | addr);
if (ret)
- goto done;
+ goto done_inst;
nvkm_kmap(data);
nvkm_wo32(data, 0x1c, 1);
@@ -1540,19 +1512,27 @@ gf100_grctx_generate(struct gf100_gr *gr)
);
}
- grctx->main(gr, &info);
+ grctx->main(chan);
- /* Trigger a context unload by unsetting the "next channel valid" bit
- * and faking a context switch interrupt.
- */
- nvkm_mask(device, 0x409b04, 0x80000000, 0x00000000);
- nvkm_wr32(device, 0x409000, 0x00000100);
- if (nvkm_msec(device, 2000,
- if (!(nvkm_rd32(device, 0x409b00) & 0x80000000))
- break;
- ) < 0) {
- ret = -EBUSY;
- goto done;
+ if (!gr->firmware) {
+ /* Trigger a context unload by unsetting the "next channel valid" bit
+ * and faking a context switch interrupt.
+ */
+ nvkm_mask(device, 0x409b04, 0x80000000, 0x00000000);
+ nvkm_wr32(device, 0x409000, 0x00000100);
+ if (nvkm_msec(device, 2000,
+ if (!(nvkm_rd32(device, 0x409b00) & 0x80000000))
+ break;
+ ) < 0) {
+ ret = -EBUSY;
+ goto done_inst;
+ }
+ } else {
+ ret = gf100_gr_fecs_wfi_golden_save(gr, 0x80000000 | addr);
+ if (ret)
+ goto done_inst;
+
+ nvkm_mask(device, 0x409b00, 0x80000000, 0x00000000);
}
gr->data = kmalloc(gr->size, GFP_KERNEL);
@@ -1566,12 +1546,14 @@ gf100_grctx_generate(struct gf100_gr *gr)
ret = -ENOMEM;
}
+done_inst:
+ nvkm_kmap(inst);
+ nvkm_wo32(inst, 0x0210, 0);
+ nvkm_wo32(inst, 0x0214, 0);
+ nvkm_done(inst);
done:
- nvkm_vmm_put(vmm, &ctx);
+ nvkm_vmm_put(chan->vmm, &ctx);
nvkm_memory_unref(&data);
- nvkm_vmm_part(vmm, inst);
- nvkm_vmm_unref(&vmm);
- nvkm_memory_unref(&inst);
return ret;
}
@@ -1590,6 +1572,8 @@ gf100_grctx = {
.bundle_size = 0x1800,
.pagepool = gf100_grctx_generate_pagepool,
.pagepool_size = 0x8000,
+ .attrib_cb_size = gf100_grctx_generate_attrib_cb_size,
+ .attrib_cb = gf100_grctx_generate_attrib_cb,
.attrib = gf100_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
index 32bbddc0993e..00dbeda7e346 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h
@@ -3,27 +3,12 @@
#define __NVKM_GRCTX_NVC0_H__
#include "gf100.h"
-struct gf100_grctx {
- struct gf100_gr *gr;
- struct gf100_gr_data *data;
- struct gf100_gr_mmio *mmio;
- int buffer_nr;
- u64 buffer[4];
- u64 addr;
-};
-
-int gf100_grctx_mmio_data(struct gf100_grctx *, u32 size, u32 align, bool priv);
-void gf100_grctx_mmio_item(struct gf100_grctx *, u32 addr, u32 data, int s, int);
-
-#define mmio_vram(a,b,c,d) gf100_grctx_mmio_data((a), (b), (c), (d))
-#define mmio_refn(a,b,c,d,e) gf100_grctx_mmio_item((a), (b), (c), (d), (e))
-#define mmio_skip(a,b,c) mmio_refn((a), (b), (c), -1, -1)
-#define mmio_wr32(a,b,c) mmio_refn((a), (b), (c), 0, -1)
+void gf100_grctx_patch_wr32(struct gf100_gr_chan *, u32 addr, u32 data);
struct gf100_grctx_func {
void (*unkn88c)(struct gf100_gr *, bool on);
/* main context generation function */
- void (*main)(struct gf100_gr *, struct gf100_grctx *);
+ void (*main)(struct gf100_gr_chan *);
/* context-specific modify-on-first-load list generation function */
void (*unkn)(struct gf100_gr *);
/* mmio context data */
@@ -37,23 +22,29 @@ struct gf100_grctx_func {
const struct gf100_gr_pack *icmd;
const struct gf100_gr_pack *mthd;
const struct gf100_gr_pack *sw_veid_bundle_init;
+ const struct gf100_gr_pack *sw_bundle64_init;
/* bundle circular buffer */
- void (*bundle)(struct gf100_grctx *);
+ void (*bundle)(struct gf100_gr_chan *, u64 addr, u32 size);
u32 bundle_size;
u32 bundle_min_gpm_fifo_depth;
u32 bundle_token_limit;
/* pagepool */
- void (*pagepool)(struct gf100_grctx *);
+ void (*pagepool)(struct gf100_gr_chan *, u64 addr);
u32 pagepool_size;
/* attribute(/alpha) circular buffer */
- void (*attrib)(struct gf100_grctx *);
+ u32 (*attrib_cb_size)(struct gf100_gr *);
+ void (*attrib_cb)(struct gf100_gr_chan *, u64 addr, u32 size);
+ void (*attrib)(struct gf100_gr_chan *);
u32 attrib_nr_max;
u32 attrib_nr;
u32 alpha_nr_max;
u32 alpha_nr;
u32 gfxp_nr;
+ /* some other context buffer */
+ void (*unknown)(struct gf100_gr_chan *, u64 addr, u32 size);
+ u32 unknown_size;
/* other patch buffer stuff */
- void (*patch_ltc)(struct gf100_grctx *);
+ void (*patch_ltc)(struct gf100_gr_chan *);
/* floorsweeping */
void (*sm_id)(struct gf100_gr *, int gpc, int tpc, int sm);
void (*tpc_nr)(struct gf100_gr *, int gpc);
@@ -78,14 +69,17 @@ struct gf100_grctx_func {
void (*r419a3c)(struct gf100_gr *);
void (*r408840)(struct gf100_gr *);
void (*r419c0c)(struct gf100_gr *);
+ void (*r419ea8)(struct gf100_gr *);
};
extern const struct gf100_grctx_func gf100_grctx;
-int gf100_grctx_generate(struct gf100_gr *);
-void gf100_grctx_generate_main(struct gf100_gr *, struct gf100_grctx *);
-void gf100_grctx_generate_bundle(struct gf100_grctx *);
-void gf100_grctx_generate_pagepool(struct gf100_grctx *);
-void gf100_grctx_generate_attrib(struct gf100_grctx *);
+int gf100_grctx_generate(struct gf100_gr *, struct gf100_gr_chan *, struct nvkm_gpuobj *inst);
+void gf100_grctx_generate_main(struct gf100_gr_chan *);
+void gf100_grctx_generate_pagepool(struct gf100_gr_chan *, u64);
+void gf100_grctx_generate_bundle(struct gf100_gr_chan *, u64, u32);
+u32 gf100_grctx_generate_attrib_cb_size(struct gf100_gr *);
+void gf100_grctx_generate_attrib_cb(struct gf100_gr_chan *, u64, u32);
+void gf100_grctx_generate_attrib(struct gf100_gr_chan *);
void gf100_grctx_generate_unkn(struct gf100_gr *);
void gf100_grctx_generate_floorsweep(struct gf100_gr *);
void gf100_grctx_generate_sm_id(struct gf100_gr *, int, int, int);
@@ -97,14 +91,14 @@ void gf100_grctx_generate_max_ways_evict(struct gf100_gr *);
void gf100_grctx_generate_r419cb8(struct gf100_gr *);
extern const struct gf100_grctx_func gf108_grctx;
-void gf108_grctx_generate_attrib(struct gf100_grctx *);
+void gf108_grctx_generate_attrib(struct gf100_gr_chan *);
void gf108_grctx_generate_unkn(struct gf100_gr *);
extern const struct gf100_grctx_func gf104_grctx;
extern const struct gf100_grctx_func gf110_grctx;
extern const struct gf100_grctx_func gf117_grctx;
-void gf117_grctx_generate_attrib(struct gf100_grctx *);
+void gf117_grctx_generate_attrib(struct gf100_gr_chan *);
void gf117_grctx_generate_rop_mapping(struct gf100_gr *);
void gf117_grctx_generate_dist_skip_table(struct gf100_gr *);
@@ -115,9 +109,9 @@ void gk104_grctx_generate_alpha_beta_tables(struct gf100_gr *);
void gk104_grctx_generate_gpc_tpc_nr(struct gf100_gr *);
extern const struct gf100_grctx_func gk20a_grctx;
-void gk104_grctx_generate_bundle(struct gf100_grctx *);
-void gk104_grctx_generate_pagepool(struct gf100_grctx *);
-void gk104_grctx_generate_patch_ltc(struct gf100_grctx *);
+void gk104_grctx_generate_pagepool(struct gf100_gr_chan *, u64);
+void gk104_grctx_generate_bundle(struct gf100_gr_chan *, u64, u32);
+void gk104_grctx_generate_patch_ltc(struct gf100_gr_chan *);
void gk104_grctx_generate_unkn(struct gf100_gr *);
void gk104_grctx_generate_r418800(struct gf100_gr *);
@@ -128,9 +122,10 @@ extern const struct gf100_grctx_func gk110b_grctx;
extern const struct gf100_grctx_func gk208_grctx;
extern const struct gf100_grctx_func gm107_grctx;
-void gm107_grctx_generate_bundle(struct gf100_grctx *);
-void gm107_grctx_generate_pagepool(struct gf100_grctx *);
-void gm107_grctx_generate_attrib(struct gf100_grctx *);
+void gm107_grctx_generate_pagepool(struct gf100_gr_chan *, u64);
+void gm107_grctx_generate_bundle(struct gf100_gr_chan *, u64, u32);
+void gm107_grctx_generate_attrib_cb(struct gf100_gr_chan *, u64, u32);
+void gm107_grctx_generate_attrib(struct gf100_gr_chan *);
void gm107_grctx_generate_sm_id(struct gf100_gr *, int, int, int);
extern const struct gf100_grctx_func gm200_grctx;
@@ -143,11 +138,13 @@ void gm200_grctx_generate_r419a3c(struct gf100_gr *);
extern const struct gf100_grctx_func gm20b_grctx;
extern const struct gf100_grctx_func gp100_grctx;
-void gp100_grctx_generate_pagepool(struct gf100_grctx *);
+void gp100_grctx_generate_pagepool(struct gf100_gr_chan *, u64);
+void gp100_grctx_generate_attrib_cb(struct gf100_gr_chan *, u64, u32);
void gp100_grctx_generate_smid_config(struct gf100_gr *);
extern const struct gf100_grctx_func gp102_grctx;
-void gp102_grctx_generate_attrib(struct gf100_grctx *);
+u32 gp102_grctx_generate_attrib_cb_size(struct gf100_gr *);
+void gp102_grctx_generate_attrib(struct gf100_gr_chan *);
extern const struct gf100_grctx_func gp104_grctx;
@@ -158,11 +155,15 @@ extern const struct gf100_grctx_func gv100_grctx;
extern const struct gf100_grctx_func tu102_grctx;
void gv100_grctx_unkn88c(struct gf100_gr *, bool);
void gv100_grctx_generate_unkn(struct gf100_gr *);
-extern const struct gf100_gr_init gv100_grctx_init_sw_veid_bundle_init_0[];
-void gv100_grctx_generate_attrib(struct gf100_grctx *);
+void gv100_grctx_generate_attrib_cb(struct gf100_gr_chan *, u64, u32);
+void gv100_grctx_generate_attrib(struct gf100_gr_chan *);
void gv100_grctx_generate_rop_mapping(struct gf100_gr *);
void gv100_grctx_generate_r400088(struct gf100_gr *, bool);
+void tu102_grctx_generate_unknown(struct gf100_gr_chan *, u64, u32);
+
+extern const struct gf100_grctx_func ga102_grctx;
+
/* context init value lists */
extern const struct gf100_gr_pack gf100_grctx_pack_icmd[];
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf104.c
index 7a0564b6e3c7..ba63a3b46518 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf104.c
@@ -94,6 +94,8 @@ gf104_grctx = {
.bundle_size = 0x1800,
.pagepool = gf100_grctx_generate_pagepool,
.pagepool_size = 0x8000,
+ .attrib_cb_size = gf100_grctx_generate_attrib_cb_size,
+ .attrib_cb = gf100_grctx_generate_attrib_cb,
.attrib = gf100_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c
index dda2c32e6232..0bc2eab6ad98 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c
@@ -733,25 +733,20 @@ gf108_grctx_pack_tpc[] = {
******************************************************************************/
void
-gf108_grctx_generate_attrib(struct gf100_grctx *info)
+gf108_grctx_generate_attrib(struct gf100_gr_chan *chan)
{
- struct gf100_gr *gr = info->gr;
+ struct gf100_gr *gr = chan->gr;
const struct gf100_grctx_func *grctx = gr->func->grctx;
const u32 alpha = grctx->alpha_nr;
const u32 beta = grctx->attrib_nr;
- const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max);
- const int s = 12;
- const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), false);
const int timeslice_mode = 1;
const int max_batches = 0xffff;
u32 bo = 0;
u32 ao = bo + grctx->attrib_nr_max * gr->tpc_total;
int gpc, tpc;
- mmio_refn(info, 0x418810, 0x80000000, s, b);
- mmio_refn(info, 0x419848, 0x10000000, s, b);
- mmio_wr32(info, 0x405830, (beta << 16) | alpha);
- mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches);
+ gf100_grctx_patch_wr32(chan, 0x405830, (beta << 16) | alpha);
+ gf100_grctx_patch_wr32(chan, 0x4064c4, ((alpha / 4) << 16) | max_batches);
for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
for (tpc = 0; tpc < gr->tpc_nr[gpc]; tpc++) {
@@ -759,10 +754,10 @@ gf108_grctx_generate_attrib(struct gf100_grctx *info)
const u32 b = beta;
const u32 t = timeslice_mode;
const u32 o = TPC_UNIT(gpc, tpc, 0x500);
- mmio_skip(info, o + 0x20, (t << 28) | (b << 16) | ++bo);
- mmio_wr32(info, o + 0x20, (t << 28) | (b << 16) | --bo);
+
+ gf100_grctx_patch_wr32(chan, o + 0x20, (t << 28) | (b << 16) | bo);
bo += grctx->attrib_nr_max;
- mmio_wr32(info, o + 0x44, (a << 16) | ao);
+ gf100_grctx_patch_wr32(chan, o + 0x44, (a << 16) | ao);
ao += grctx->alpha_nr_max;
}
}
@@ -795,6 +790,8 @@ gf108_grctx = {
.bundle_size = 0x1800,
.pagepool = gf100_grctx_generate_pagepool,
.pagepool_size = 0x8000,
+ .attrib_cb_size = gf100_grctx_generate_attrib_cb_size,
+ .attrib_cb = gf100_grctx_generate_attrib_cb,
.attrib = gf108_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf110.c
index f5cca5e6a4f2..64b723b0afb5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf110.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf110.c
@@ -342,6 +342,8 @@ gf110_grctx = {
.bundle_size = 0x1800,
.pagepool = gf100_grctx_generate_pagepool,
.pagepool_size = 0x8000,
+ .attrib_cb_size = gf100_grctx_generate_attrib_cb_size,
+ .attrib_cb = gf100_grctx_generate_attrib_cb,
.attrib = gf100_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c
index 276c282d19aa..e34c5da2a9ff 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c
@@ -241,38 +241,34 @@ gf117_grctx_generate_rop_mapping(struct gf100_gr *gr)
}
void
-gf117_grctx_generate_attrib(struct gf100_grctx *info)
+gf117_grctx_generate_attrib(struct gf100_gr_chan *chan)
{
- struct gf100_gr *gr = info->gr;
+ struct gf100_gr *gr = chan->gr;
const struct gf100_grctx_func *grctx = gr->func->grctx;
const u32 alpha = grctx->alpha_nr;
const u32 beta = grctx->attrib_nr;
- const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max);
- const int s = 12;
- const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), false);
const int timeslice_mode = 1;
const int max_batches = 0xffff;
u32 bo = 0;
u32 ao = bo + grctx->attrib_nr_max * gr->tpc_total;
int gpc, ppc;
- mmio_refn(info, 0x418810, 0x80000000, s, b);
- mmio_refn(info, 0x419848, 0x10000000, s, b);
- mmio_wr32(info, 0x405830, (beta << 16) | alpha);
- mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches);
+ gf100_grctx_patch_wr32(chan, 0x405830, (beta << 16) | alpha);
+ gf100_grctx_patch_wr32(chan, 0x4064c4, ((alpha / 4) << 16) | max_batches);
for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
- for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++) {
+ for (ppc = 0; ppc < gr->func->ppc_nr; ppc++) {
const u32 a = alpha * gr->ppc_tpc_nr[gpc][ppc];
const u32 b = beta * gr->ppc_tpc_nr[gpc][ppc];
const u32 t = timeslice_mode;
const u32 o = PPC_UNIT(gpc, ppc, 0);
+
if (!(gr->ppc_mask[gpc] & (1 << ppc)))
continue;
- mmio_skip(info, o + 0xc0, (t << 28) | (b << 16) | ++bo);
- mmio_wr32(info, o + 0xc0, (t << 28) | (b << 16) | --bo);
+
+ gf100_grctx_patch_wr32(chan, o + 0xc0, (t << 28) | (b << 16) | bo);
bo += grctx->attrib_nr_max * gr->ppc_tpc_nr[gpc][ppc];
- mmio_wr32(info, o + 0xe4, (a << 16) | ao);
+ gf100_grctx_patch_wr32(chan, o + 0xe4, (a << 16) | ao);
ao += grctx->alpha_nr_max * gr->ppc_tpc_nr[gpc][ppc];
}
}
@@ -294,6 +290,8 @@ gf117_grctx = {
.bundle_size = 0x1800,
.pagepool = gf100_grctx_generate_pagepool,
.pagepool_size = 0x8000,
+ .attrib_cb_size = gf100_grctx_generate_attrib_cb_size,
+ .attrib_cb = gf100_grctx_generate_attrib_cb,
.attrib = gf117_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf119.c
index 0cfe46366af6..426ad1b8d426 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf119.c
@@ -510,6 +510,8 @@ gf119_grctx = {
.bundle_size = 0x1800,
.pagepool = gf100_grctx_generate_pagepool,
.pagepool_size = 0x8000,
+ .attrib_cb_size = gf100_grctx_generate_attrib_cb_size,
+ .attrib_cb = gf100_grctx_generate_attrib_cb,
.attrib = gf108_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c
index 304e9d268bad..94233d0119df 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c
@@ -861,43 +861,33 @@ gk104_grctx_generate_r418800(struct gf100_gr *gr)
}
void
-gk104_grctx_generate_patch_ltc(struct gf100_grctx *info)
+gk104_grctx_generate_patch_ltc(struct gf100_gr_chan *chan)
{
- struct nvkm_device *device = info->gr->base.engine.subdev.device;
+ struct nvkm_device *device = chan->gr->base.engine.subdev.device;
u32 data0 = nvkm_rd32(device, 0x17e91c);
u32 data1 = nvkm_rd32(device, 0x17e920);
+
/*XXX: Figure out how to modify this correctly! */
- mmio_wr32(info, 0x17e91c, data0);
- mmio_wr32(info, 0x17e920, data1);
+ gf100_grctx_patch_wr32(chan, 0x17e91c, data0);
+ gf100_grctx_patch_wr32(chan, 0x17e920, data1);
}
void
-gk104_grctx_generate_bundle(struct gf100_grctx *info)
+gk104_grctx_generate_bundle(struct gf100_gr_chan *chan, u64 addr, u32 size)
{
- const struct gf100_grctx_func *grctx = info->gr->func->grctx;
- const u32 state_limit = min(grctx->bundle_min_gpm_fifo_depth,
- grctx->bundle_size / 0x20);
+ const struct gf100_grctx_func *grctx = chan->gr->func->grctx;
+ const u32 state_limit = min(grctx->bundle_min_gpm_fifo_depth, size / 0x20);
const u32 token_limit = grctx->bundle_token_limit;
- const int s = 8;
- const int b = mmio_vram(info, grctx->bundle_size, (1 << s), true);
- mmio_refn(info, 0x408004, 0x00000000, s, b);
- mmio_wr32(info, 0x408008, 0x80000000 | (grctx->bundle_size >> s));
- mmio_refn(info, 0x418808, 0x00000000, s, b);
- mmio_wr32(info, 0x41880c, 0x80000000 | (grctx->bundle_size >> s));
- mmio_wr32(info, 0x4064c8, (state_limit << 16) | token_limit);
+
+ gf100_grctx_generate_bundle(chan, addr, size);
+ gf100_grctx_patch_wr32(chan, 0x4064c8, (state_limit << 16) | token_limit);
}
void
-gk104_grctx_generate_pagepool(struct gf100_grctx *info)
+gk104_grctx_generate_pagepool(struct gf100_gr_chan *chan, u64 addr)
{
- const struct gf100_grctx_func *grctx = info->gr->func->grctx;
- const int s = 8;
- const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), true);
- mmio_refn(info, 0x40800c, 0x00000000, s, b);
- mmio_wr32(info, 0x408010, 0x80000000);
- mmio_refn(info, 0x419004, 0x00000000, s, b);
- mmio_wr32(info, 0x419008, 0x00000000);
- mmio_wr32(info, 0x4064cc, 0x80000000);
+ gf100_grctx_generate_pagepool(chan, addr);
+ gf100_grctx_patch_wr32(chan, 0x4064cc, 0x80000000);
}
void
@@ -991,6 +981,8 @@ gk104_grctx = {
.bundle_token_limit = 0x600,
.pagepool = gk104_grctx_generate_pagepool,
.pagepool_size = 0x8000,
+ .attrib_cb_size = gf100_grctx_generate_attrib_cb_size,
+ .attrib_cb = gf100_grctx_generate_attrib_cb,
.attrib = gf117_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c
index 86547cfc38dc..4391458e1fb2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110.c
@@ -838,6 +838,8 @@ gk110_grctx = {
.bundle_token_limit = 0x7c0,
.pagepool = gk104_grctx_generate_pagepool,
.pagepool_size = 0x8000,
+ .attrib_cb_size = gf100_grctx_generate_attrib_cb_size,
+ .attrib_cb = gf100_grctx_generate_attrib_cb,
.attrib = gf117_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c
index ebb947bd1446..7b9a34f9ec3c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk110b.c
@@ -87,6 +87,8 @@ gk110b_grctx = {
.bundle_token_limit = 0x600,
.pagepool = gk104_grctx_generate_pagepool,
.pagepool_size = 0x8000,
+ .attrib_cb_size = gf100_grctx_generate_attrib_cb_size,
+ .attrib_cb = gf100_grctx_generate_attrib_cb,
.attrib = gf117_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c
index 4d40512b5c99..c78d07a8bb7d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk208.c
@@ -553,6 +553,8 @@ gk208_grctx = {
.bundle_token_limit = 0x200,
.pagepool = gk104_grctx_generate_pagepool,
.pagepool_size = 0x8000,
+ .attrib_cb_size = gf100_grctx_generate_attrib_cb_size,
+ .attrib_cb = gf100_grctx_generate_attrib_cb,
.attrib = gf117_grctx_generate_attrib,
.attrib_nr_max = 0x324,
.attrib_nr = 0x218,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c
index c0d36bc601f9..ac5fdcb5cd3f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk20a.c
@@ -25,8 +25,9 @@
#include <subdev/mc.h>
static void
-gk20a_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info)
+gk20a_grctx_generate_main(struct gf100_gr_chan *chan)
{
+ struct gf100_gr *gr = chan->gr;
struct nvkm_device *device = gr->base.engine.subdev.device;
const struct gf100_grctx_func *grctx = gr->func->grctx;
u32 idle_timeout;
@@ -38,7 +39,8 @@ gk20a_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info)
idle_timeout = nvkm_mask(device, 0x404154, 0xffffffff, 0x00000000);
- grctx->attrib(info);
+ grctx->attrib_cb(chan, chan->attrib_cb->addr, grctx->attrib_cb_size(gr));
+ grctx->attrib(chan);
grctx->unkn(gr);
@@ -60,8 +62,8 @@ gk20a_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info)
gf100_gr_wait_idle(gr);
gf100_gr_icmd(gr, gr->bundle);
- grctx->pagepool(info);
- grctx->bundle(info);
+ grctx->pagepool(chan, chan->pagepool->addr);
+ grctx->bundle(chan, chan->bundle_cb->addr, grctx->bundle_size);
}
const struct gf100_grctx_func
@@ -74,6 +76,8 @@ gk20a_grctx = {
.bundle_token_limit = 0x100,
.pagepool = gk104_grctx_generate_pagepool,
.pagepool_size = 0x8000,
+ .attrib_cb_size = gf100_grctx_generate_attrib_cb_size,
+ .attrib_cb = gf100_grctx_generate_attrib_cb,
.attrib = gf117_grctx_generate_attrib,
.attrib_nr_max = 0x240,
.attrib_nr = 0x240,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
index 0b3964e6b36e..beac66eb2a80 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c
@@ -876,75 +876,70 @@ gm107_grctx_generate_r419e00(struct gf100_gr *gr)
}
void
-gm107_grctx_generate_bundle(struct gf100_grctx *info)
+gm107_grctx_generate_bundle(struct gf100_gr_chan *chan, u64 addr, u32 size)
{
- const struct gf100_grctx_func *grctx = info->gr->func->grctx;
- const u32 state_limit = min(grctx->bundle_min_gpm_fifo_depth,
- grctx->bundle_size / 0x20);
+ const struct gf100_grctx_func *grctx = chan->gr->func->grctx;
+ const u32 state_limit = min(grctx->bundle_min_gpm_fifo_depth, size / 0x20);
const u32 token_limit = grctx->bundle_token_limit;
- const int s = 8;
- const int b = mmio_vram(info, grctx->bundle_size, (1 << s), true);
- mmio_refn(info, 0x408004, 0x00000000, s, b);
- mmio_wr32(info, 0x408008, 0x80000000 | (grctx->bundle_size >> s));
- mmio_refn(info, 0x418e24, 0x00000000, s, b);
- mmio_wr32(info, 0x418e28, 0x80000000 | (grctx->bundle_size >> s));
- mmio_wr32(info, 0x4064c8, (state_limit << 16) | token_limit);
+
+ gf100_grctx_patch_wr32(chan, 0x408004, addr >> 8);
+ gf100_grctx_patch_wr32(chan, 0x408008, 0x80000000 | (size >> 8));
+ gf100_grctx_patch_wr32(chan, 0x418e24, addr >> 8);
+ gf100_grctx_patch_wr32(chan, 0x418e28, 0x80000000 | (size >> 8));
+ gf100_grctx_patch_wr32(chan, 0x4064c8, (state_limit << 16) | token_limit);
}
void
-gm107_grctx_generate_pagepool(struct gf100_grctx *info)
+gm107_grctx_generate_pagepool(struct gf100_gr_chan *chan, u64 addr)
{
- const struct gf100_grctx_func *grctx = info->gr->func->grctx;
- const int s = 8;
- const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), true);
- mmio_refn(info, 0x40800c, 0x00000000, s, b);
- mmio_wr32(info, 0x408010, 0x80000000);
- mmio_refn(info, 0x419004, 0x00000000, s, b);
- mmio_wr32(info, 0x419008, 0x00000000);
- mmio_wr32(info, 0x4064cc, 0x80000000);
- mmio_wr32(info, 0x418e30, 0x80000000); /* guess at it being related */
+ gk104_grctx_generate_pagepool(chan, addr);
+ gf100_grctx_patch_wr32(chan, 0x418e30, 0x80000000);
}
void
-gm107_grctx_generate_attrib(struct gf100_grctx *info)
+gm107_grctx_generate_attrib(struct gf100_gr_chan *chan)
{
- struct gf100_gr *gr = info->gr;
+ struct gf100_gr *gr = chan->gr;
const struct gf100_grctx_func *grctx = gr->func->grctx;
const u32 alpha = grctx->alpha_nr;
const u32 attrib = grctx->attrib_nr;
- const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max);
- const int s = 12;
- const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), false);
const int max_batches = 0xffff;
u32 bo = 0;
u32 ao = bo + grctx->attrib_nr_max * gr->tpc_total;
int gpc, ppc, n = 0;
- mmio_refn(info, 0x418810, 0x80000000, s, b);
- mmio_refn(info, 0x419848, 0x10000000, s, b);
- mmio_refn(info, 0x419c2c, 0x10000000, s, b);
- mmio_wr32(info, 0x405830, (attrib << 16) | alpha);
- mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches);
+ gf100_grctx_patch_wr32(chan, 0x405830, (attrib << 16) | alpha);
+ gf100_grctx_patch_wr32(chan, 0x4064c4, ((alpha / 4) << 16) | max_batches);
for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
- for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++, n++) {
+ for (ppc = 0; ppc < gr->func->ppc_nr; ppc++, n++) {
const u32 as = alpha * gr->ppc_tpc_nr[gpc][ppc];
const u32 bs = attrib * gr->ppc_tpc_nr[gpc][ppc];
const u32 u = 0x418ea0 + (n * 0x04);
const u32 o = PPC_UNIT(gpc, ppc, 0);
+
if (!(gr->ppc_mask[gpc] & (1 << ppc)))
continue;
- mmio_wr32(info, o + 0xc0, bs);
- mmio_wr32(info, o + 0xf4, bo);
+
+ gf100_grctx_patch_wr32(chan, o + 0xc0, bs);
+ gf100_grctx_patch_wr32(chan, o + 0xf4, bo);
bo += grctx->attrib_nr_max * gr->ppc_tpc_nr[gpc][ppc];
- mmio_wr32(info, o + 0xe4, as);
- mmio_wr32(info, o + 0xf8, ao);
+ gf100_grctx_patch_wr32(chan, o + 0xe4, as);
+ gf100_grctx_patch_wr32(chan, o + 0xf8, ao);
ao += grctx->alpha_nr_max * gr->ppc_tpc_nr[gpc][ppc];
- mmio_wr32(info, u, ((bs / 3) << 16) | bs);
+ gf100_grctx_patch_wr32(chan, u, ((bs / 3) << 16) | bs);
}
}
}
+void
+gm107_grctx_generate_attrib_cb(struct gf100_gr_chan *chan, u64 addr, u32 size)
+{
+ gf100_grctx_generate_attrib_cb(chan, addr, size);
+
+ gf100_grctx_patch_wr32(chan, 0x419c2c, 0x10000000 | addr >> 12);
+}
+
static void
gm107_grctx_generate_r406500(struct gf100_gr *gr)
{
@@ -978,6 +973,8 @@ gm107_grctx = {
.bundle_token_limit = 0x2c0,
.pagepool = gm107_grctx_generate_pagepool,
.pagepool_size = 0x8000,
+ .attrib_cb_size = gf100_grctx_generate_attrib_cb_size,
+ .attrib_cb = gm107_grctx_generate_attrib_cb,
.attrib = gm107_grctx_generate_attrib,
.attrib_nr_max = 0xff0,
.attrib_nr = 0xaa0,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm200.c
index 013d05a0f0f6..175da8ac656c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm200.c
@@ -87,7 +87,7 @@ gm200_grctx_generate_dist_skip_table(struct gf100_gr *gr)
int gpc, ppc, i;
for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
- for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++) {
+ for (ppc = 0; ppc < gr->func->ppc_nr; ppc++) {
u8 ppc_tpcs = gr->ppc_tpc_nr[gpc][ppc];
u8 ppc_tpcm = gr->ppc_tpc_mask[gpc][ppc];
while (ppc_tpcs-- > gr->ppc_tpc_min)
@@ -111,6 +111,8 @@ gm200_grctx = {
.bundle_token_limit = 0x780,
.pagepool = gm107_grctx_generate_pagepool,
.pagepool_size = 0x20000,
+ .attrib_cb_size = gf100_grctx_generate_attrib_cb_size,
+ .attrib_cb = gm107_grctx_generate_attrib_cb,
.attrib = gm107_grctx_generate_attrib,
.attrib_nr_max = 0x600,
.attrib_nr = 0x400,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c
index 6b92f8aa18a3..b8edccfada58 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm20b.c
@@ -22,8 +22,9 @@
#include "ctxgf100.h"
static void
-gm20b_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info)
+gm20b_grctx_generate_main(struct gf100_gr_chan *chan)
{
+ struct gf100_gr *gr = chan->gr;
struct nvkm_device *device = gr->base.engine.subdev.device;
const struct gf100_grctx_func *grctx = gr->func->grctx;
u32 idle_timeout;
@@ -35,7 +36,8 @@ gm20b_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info)
idle_timeout = nvkm_mask(device, 0x404154, 0xffffffff, 0x00000000);
- grctx->attrib(info);
+ grctx->attrib_cb(chan, chan->attrib_cb->addr, grctx->attrib_cb_size(gr));
+ grctx->attrib(chan);
grctx->unkn(gr);
@@ -63,8 +65,8 @@ gm20b_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info)
gf100_gr_wait_idle(gr);
gf100_gr_icmd(gr, gr->bundle);
- grctx->pagepool(info);
- grctx->bundle(info);
+ grctx->pagepool(chan, chan->pagepool->addr);
+ grctx->bundle(chan, chan->bundle_cb->addr, grctx->bundle_size);
}
const struct gf100_grctx_func
@@ -77,6 +79,8 @@ gm20b_grctx = {
.bundle_token_limit = 0x1c0,
.pagepool = gm107_grctx_generate_pagepool,
.pagepool_size = 0x8000,
+ .attrib_cb_size = gf100_grctx_generate_attrib_cb_size,
+ .attrib_cb = gm107_grctx_generate_attrib_cb,
.attrib = gm107_grctx_generate_attrib,
.attrib_nr_max = 0x600,
.attrib_nr = 0x400,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c
index 0b3326262e12..8485aaeae7a9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c
@@ -30,66 +30,76 @@
******************************************************************************/
void
-gp100_grctx_generate_pagepool(struct gf100_grctx *info)
+gp100_grctx_generate_pagepool(struct gf100_gr_chan *chan, u64 addr)
{
- const struct gf100_grctx_func *grctx = info->gr->func->grctx;
- const int s = 8;
- const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), true);
- mmio_refn(info, 0x40800c, 0x00000000, s, b);
- mmio_wr32(info, 0x408010, 0x8007d800);
- mmio_refn(info, 0x419004, 0x00000000, s, b);
- mmio_wr32(info, 0x419008, 0x00000000);
+ gf100_grctx_patch_wr32(chan, 0x40800c, addr >> 8);
+ gf100_grctx_patch_wr32(chan, 0x408010, 0x8007d800);
+ gf100_grctx_patch_wr32(chan, 0x419004, addr >> 8);
+ gf100_grctx_patch_wr32(chan, 0x419008, 0x00000000);
}
static void
-gp100_grctx_generate_attrib(struct gf100_grctx *info)
+gp100_grctx_generate_attrib(struct gf100_gr_chan *chan)
{
- struct gf100_gr *gr = info->gr;
+ struct gf100_gr *gr = chan->gr;
const struct gf100_grctx_func *grctx = gr->func->grctx;
const u32 alpha = grctx->alpha_nr;
const u32 attrib = grctx->attrib_nr;
- const int s = 12;
const int max_batches = 0xffff;
u32 size = grctx->alpha_nr_max * gr->tpc_total;
u32 ao = 0;
u32 bo = ao + size;
- int gpc, ppc, b, n = 0;
+ int gpc, ppc, n = 0;
- for (gpc = 0; gpc < gr->gpc_nr; gpc++)
- size += grctx->attrib_nr_max * gr->ppc_nr[gpc] * gr->ppc_tpc_max;
- size = ((size * 0x20) + 128) & ~127;
- b = mmio_vram(info, size, (1 << s), false);
-
- mmio_refn(info, 0x418810, 0x80000000, s, b);
- mmio_refn(info, 0x419848, 0x10000000, s, b);
- mmio_refn(info, 0x419c2c, 0x10000000, s, b);
- mmio_refn(info, 0x419b00, 0x00000000, s, b);
- mmio_wr32(info, 0x419b04, 0x80000000 | size >> 7);
- mmio_wr32(info, 0x405830, attrib);
- mmio_wr32(info, 0x40585c, alpha);
- mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches);
+ gf100_grctx_patch_wr32(chan, 0x405830, attrib);
+ gf100_grctx_patch_wr32(chan, 0x40585c, alpha);
+ gf100_grctx_patch_wr32(chan, 0x4064c4, ((alpha / 4) << 16) | max_batches);
for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
- for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++, n++) {
+ for (ppc = 0; ppc < gr->func->ppc_nr; ppc++, n++) {
const u32 as = alpha * gr->ppc_tpc_nr[gpc][ppc];
const u32 bs = attrib * gr->ppc_tpc_max;
const u32 u = 0x418ea0 + (n * 0x04);
const u32 o = PPC_UNIT(gpc, ppc, 0);
+
if (!(gr->ppc_mask[gpc] & (1 << ppc)))
continue;
- mmio_wr32(info, o + 0xc0, bs);
- mmio_wr32(info, o + 0xf4, bo);
- mmio_wr32(info, o + 0xf0, bs);
+
+ gf100_grctx_patch_wr32(chan, o + 0xc0, bs);
+ gf100_grctx_patch_wr32(chan, o + 0xf4, bo);
+ gf100_grctx_patch_wr32(chan, o + 0xf0, bs);
bo += grctx->attrib_nr_max * gr->ppc_tpc_max;
- mmio_wr32(info, o + 0xe4, as);
- mmio_wr32(info, o + 0xf8, ao);
+ gf100_grctx_patch_wr32(chan, o + 0xe4, as);
+ gf100_grctx_patch_wr32(chan, o + 0xf8, ao);
ao += grctx->alpha_nr_max * gr->ppc_tpc_nr[gpc][ppc];
- mmio_wr32(info, u, bs);
+ gf100_grctx_patch_wr32(chan, u, bs);
}
}
- mmio_wr32(info, 0x418eec, 0x00000000);
- mmio_wr32(info, 0x41befc, 0x00000000);
+ gf100_grctx_patch_wr32(chan, 0x418eec, 0x00000000);
+ gf100_grctx_patch_wr32(chan, 0x41befc, 0x00000000);
+}
+
+void
+gp100_grctx_generate_attrib_cb(struct gf100_gr_chan *chan, u64 addr, u32 size)
+{
+ gm107_grctx_generate_attrib_cb(chan, addr, size);
+
+ gf100_grctx_patch_wr32(chan, 0x419b00, 0x00000000 | addr >> 12);
+ gf100_grctx_patch_wr32(chan, 0x419b04, 0x80000000 | size >> 7);
+}
+
+static u32
+gp100_grctx_generate_attrib_cb_size(struct gf100_gr *gr)
+{
+ const struct gf100_grctx_func *grctx = gr->func->grctx;
+ u32 size = grctx->alpha_nr_max * gr->tpc_total;
+ int gpc;
+
+ for (gpc = 0; gpc < gr->gpc_nr; gpc++)
+ size += grctx->attrib_nr_max * gr->func->ppc_nr * gr->ppc_tpc_max;
+
+ return ((size * 0x20) + 128) & ~127;
}
void
@@ -123,6 +133,8 @@ gp100_grctx = {
.bundle_token_limit = 0x1080,
.pagepool = gp100_grctx_generate_pagepool,
.pagepool_size = 0x20000,
+ .attrib_cb_size = gp100_grctx_generate_attrib_cb_size,
+ .attrib_cb = gp100_grctx_generate_attrib_cb,
.attrib = gp100_grctx_generate_attrib,
.attrib_nr_max = 0x660,
.attrib_nr = 0x440,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c
index daee17bf7d0d..7537979a5492 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c
@@ -37,58 +37,62 @@ gp102_grctx_generate_r408840(struct gf100_gr *gr)
}
void
-gp102_grctx_generate_attrib(struct gf100_grctx *info)
+gp102_grctx_generate_attrib(struct gf100_gr_chan *chan)
{
- struct gf100_gr *gr = info->gr;
+ struct gf100_gr *gr = chan->gr;
const struct gf100_grctx_func *grctx = gr->func->grctx;
const u32 alpha = grctx->alpha_nr;
const u32 attrib = grctx->attrib_nr;
const u32 gfxp = grctx->gfxp_nr;
- const int s = 12;
const int max_batches = 0xffff;
u32 size = grctx->alpha_nr_max * gr->tpc_total;
u32 ao = 0;
u32 bo = ao + size;
- int gpc, ppc, b, n = 0;
+ int gpc, ppc, n = 0;
- for (gpc = 0; gpc < gr->gpc_nr; gpc++)
- size += grctx->gfxp_nr * gr->ppc_nr[gpc] * gr->ppc_tpc_max;
- size = ((size * 0x20) + 128) & ~127;
- b = mmio_vram(info, size, (1 << s), false);
-
- mmio_refn(info, 0x418810, 0x80000000, s, b);
- mmio_refn(info, 0x419848, 0x10000000, s, b);
- mmio_refn(info, 0x419c2c, 0x10000000, s, b);
- mmio_refn(info, 0x419b00, 0x00000000, s, b);
- mmio_wr32(info, 0x419b04, 0x80000000 | size >> 7);
- mmio_wr32(info, 0x405830, attrib);
- mmio_wr32(info, 0x40585c, alpha);
- mmio_wr32(info, 0x4064c4, ((alpha / 4) << 16) | max_batches);
+ gf100_grctx_patch_wr32(chan, 0x405830, attrib);
+ gf100_grctx_patch_wr32(chan, 0x40585c, alpha);
+ gf100_grctx_patch_wr32(chan, 0x4064c4, ((alpha / 4) << 16) | max_batches);
for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
- for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++, n++) {
+ for (ppc = 0; ppc < gr->func->ppc_nr; ppc++, n++) {
const u32 as = alpha * gr->ppc_tpc_nr[gpc][ppc];
const u32 bs = attrib * gr->ppc_tpc_max;
const u32 gs = gfxp * gr->ppc_tpc_max;
const u32 u = 0x418ea0 + (n * 0x04);
const u32 o = PPC_UNIT(gpc, ppc, 0);
const u32 p = GPC_UNIT(gpc, 0xc44 + (ppc * 4));
+
if (!(gr->ppc_mask[gpc] & (1 << ppc)))
continue;
- mmio_wr32(info, o + 0xc0, gs);
- mmio_wr32(info, p, bs);
- mmio_wr32(info, o + 0xf4, bo);
- mmio_wr32(info, o + 0xf0, bs);
+
+ gf100_grctx_patch_wr32(chan, o + 0xc0, gs);
+ gf100_grctx_patch_wr32(chan, p, bs);
+ gf100_grctx_patch_wr32(chan, o + 0xf4, bo);
+ gf100_grctx_patch_wr32(chan, o + 0xf0, bs);
bo += gs;
- mmio_wr32(info, o + 0xe4, as);
- mmio_wr32(info, o + 0xf8, ao);
+ gf100_grctx_patch_wr32(chan, o + 0xe4, as);
+ gf100_grctx_patch_wr32(chan, o + 0xf8, ao);
ao += grctx->alpha_nr_max * gr->ppc_tpc_nr[gpc][ppc];
- mmio_wr32(info, u, bs);
+ gf100_grctx_patch_wr32(chan, u, bs);
}
}
- mmio_wr32(info, 0x4181e4, 0x00000100);
- mmio_wr32(info, 0x41befc, 0x00000100);
+ gf100_grctx_patch_wr32(chan, 0x4181e4, 0x00000100);
+ gf100_grctx_patch_wr32(chan, 0x41befc, 0x00000100);
+}
+
+u32
+gp102_grctx_generate_attrib_cb_size(struct gf100_gr *gr)
+{
+ const struct gf100_grctx_func *grctx = gr->func->grctx;
+ u32 size = grctx->alpha_nr_max * gr->tpc_total;
+ int gpc;
+
+ for (gpc = 0; gpc < gr->gpc_nr; gpc++)
+ size += grctx->gfxp_nr * gr->func->ppc_nr * gr->ppc_tpc_max;
+
+ return ((size * 0x20) + 127) & ~127;
}
const struct gf100_grctx_func
@@ -101,6 +105,8 @@ gp102_grctx = {
.bundle_token_limit = 0x900,
.pagepool = gp100_grctx_generate_pagepool,
.pagepool_size = 0x20000,
+ .attrib_cb_size = gp102_grctx_generate_attrib_cb_size,
+ .attrib_cb = gp100_grctx_generate_attrib_cb,
.attrib = gp102_grctx_generate_attrib,
.attrib_nr_max = 0x4b0,
.attrib_nr = 0x320,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp104.c
index 3b85e3d326b2..90b5f793e567 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp104.c
@@ -31,6 +31,8 @@ gp104_grctx = {
.bundle_token_limit = 0x900,
.pagepool = gp100_grctx_generate_pagepool,
.pagepool_size = 0x20000,
+ .attrib_cb_size = gp102_grctx_generate_attrib_cb_size,
+ .attrib_cb = gp100_grctx_generate_attrib_cb,
.attrib = gp102_grctx_generate_attrib,
.attrib_nr_max = 0x4b0,
.attrib_nr = 0x320,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp107.c
index 5060c5ee5ce0..d191761a0471 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp107.c
@@ -39,6 +39,8 @@ gp107_grctx = {
.bundle_token_limit = 0x300,
.pagepool = gp100_grctx_generate_pagepool,
.pagepool_size = 0x20000,
+ .attrib_cb_size = gp102_grctx_generate_attrib_cb_size,
+ .attrib_cb = gp100_grctx_generate_attrib_cb,
.attrib = gp102_grctx_generate_attrib,
.attrib_nr_max = 0x15de,
.attrib_nr = 0x540,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c
index 39553d55d3f3..957ea9d6bad4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgv100.c
@@ -25,7 +25,7 @@
* PGRAPH context implementation
******************************************************************************/
-const struct gf100_gr_init
+static const struct gf100_gr_init
gv100_grctx_init_sw_veid_bundle_init_0[] = {
{ 0x00001000, 64, 0x00100000, 0x00000008 },
{ 0x00000941, 64, 0x00100000, 0x00000000 },
@@ -59,67 +59,70 @@ gv100_grctx_pack_sw_veid_bundle_init[] = {
};
void
-gv100_grctx_generate_attrib(struct gf100_grctx *info)
+gv100_grctx_generate_attrib(struct gf100_gr_chan *chan)
{
- struct gf100_gr *gr = info->gr;
+ struct gf100_gr *gr = chan->gr;
const struct gf100_grctx_func *grctx = gr->func->grctx;
const u32 alpha = grctx->alpha_nr;
const u32 attrib = grctx->attrib_nr;
const u32 gfxp = grctx->gfxp_nr;
- const int s = 12;
+ const int max_batches = 0xffff;
u32 size = grctx->alpha_nr_max * gr->tpc_total;
u32 ao = 0;
u32 bo = ao + size;
- int gpc, ppc, b, n = 0;
+ int gpc, ppc, n = 0;
- for (gpc = 0; gpc < gr->gpc_nr; gpc++)
- size += grctx->gfxp_nr * gr->ppc_nr[gpc] * gr->ppc_tpc_max;
- size = ((size * 0x20) + 127) & ~127;
- b = mmio_vram(info, size, (1 << s), false);
-
- mmio_refn(info, 0x418810, 0x80000000, s, b);
- mmio_refn(info, 0x419848, 0x10000000, s, b);
- mmio_refn(info, 0x419c2c, 0x10000000, s, b);
- mmio_refn(info, 0x419e00, 0x00000000, s, b);
- mmio_wr32(info, 0x419e04, 0x80000000 | size >> 7);
- mmio_wr32(info, 0x405830, attrib);
- mmio_wr32(info, 0x40585c, alpha);
+ gf100_grctx_patch_wr32(chan, 0x405830, attrib);
+ gf100_grctx_patch_wr32(chan, 0x40585c, alpha);
+ gf100_grctx_patch_wr32(chan, 0x4064c4, ((alpha / 4) << 16) | max_batches);
for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
- for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++, n++) {
+ for (ppc = 0; ppc < gr->func->ppc_nr; ppc++, n++) {
const u32 as = alpha * gr->ppc_tpc_nr[gpc][ppc];
const u32 bs = attrib * gr->ppc_tpc_max;
const u32 gs = gfxp * gr->ppc_tpc_max;
const u32 u = 0x418ea0 + (n * 0x04);
const u32 o = PPC_UNIT(gpc, ppc, 0);
+
if (!(gr->ppc_mask[gpc] & (1 << ppc)))
continue;
- mmio_wr32(info, o + 0xc0, gs);
- mmio_wr32(info, o + 0xf4, bo);
- mmio_wr32(info, o + 0xf0, bs);
+
+ gf100_grctx_patch_wr32(chan, o + 0xc0, gs);
+ gf100_grctx_patch_wr32(chan, o + 0xf4, bo);
+ gf100_grctx_patch_wr32(chan, o + 0xf0, bs);
bo += gs;
- mmio_wr32(info, o + 0xe4, as);
- mmio_wr32(info, o + 0xf8, ao);
+ gf100_grctx_patch_wr32(chan, o + 0xe4, as);
+ gf100_grctx_patch_wr32(chan, o + 0xf8, ao);
ao += grctx->alpha_nr_max * gr->ppc_tpc_nr[gpc][ppc];
- mmio_wr32(info, u, bs);
+ gf100_grctx_patch_wr32(chan, u, bs);
}
}
- mmio_wr32(info, 0x4181e4, 0x00000100);
- mmio_wr32(info, 0x41befc, 0x00000100);
+ gf100_grctx_patch_wr32(chan, 0x4181e4, 0x00000100);
+ gf100_grctx_patch_wr32(chan, 0x41befc, 0x00000100);
+}
+
+void
+gv100_grctx_generate_attrib_cb(struct gf100_gr_chan *chan, u64 addr, u32 size)
+{
+ gm107_grctx_generate_attrib_cb(chan, addr, size);
+
+ gf100_grctx_patch_wr32(chan, 0x419e00, 0x00000000 | addr >> 12);
+ gf100_grctx_patch_wr32(chan, 0x419e04, 0x80000000 | size >> 7);
}
void
gv100_grctx_generate_rop_mapping(struct gf100_gr *gr)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
+ const u32 mapregs = DIV_ROUND_UP(gr->func->gpc_nr * gr->func->tpc_nr, 6);
u32 data;
int i, j;
/* Pack tile map into register format. */
nvkm_wr32(device, 0x418bb8, (gr->tpc_total << 8) |
gr->screen_tile_row_offset);
- for (i = 0; i < 11; i++) {
+ for (i = 0; i < mapregs; i++) {
for (data = 0, j = 0; j < 6; j++)
data |= (gr->tile[i * 6 + j] & 0x1f) << (j * 5);
nvkm_wr32(device, 0x418b08 + (i * 4), data);
@@ -157,6 +160,9 @@ static void
gv100_grctx_generate_sm_id(struct gf100_gr *gr, int gpc, int tpc, int sm)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
+
+ tpc = gv100_gr_nonpes_aware_tpc(gr, gpc, tpc);
+
nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x608), sm);
nvkm_wr32(device, GPC_UNIT(gpc, 0x0c10 + tpc * 4), sm);
nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x088), sm);
@@ -198,6 +204,8 @@ gv100_grctx = {
.bundle_token_limit = 0x1680,
.pagepool = gp100_grctx_generate_pagepool,
.pagepool_size = 0x20000,
+ .attrib_cb_size = gp102_grctx_generate_attrib_cb_size,
+ .attrib_cb = gv100_grctx_generate_attrib_cb,
.attrib = gv100_grctx_generate_attrib,
.attrib_nr_max = 0x6c0,
.attrib_nr = 0x480,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c
index 2299ca07d04a..542ab0c78be6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxtu102.c
@@ -34,6 +34,9 @@ static void
tu102_grctx_generate_sm_id(struct gf100_gr *gr, int gpc, int tpc, int sm)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
+
+ tpc = gv100_gr_nonpes_aware_tpc(gr, gpc, tpc);
+
nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x608), sm);
nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x088), sm);
}
@@ -47,42 +50,38 @@ tu102_grctx_init_unknown_bundle_init_0[] = {
};
static const struct gf100_gr_pack
-tu102_grctx_pack_sw_veid_bundle_init[] = {
- { gv100_grctx_init_sw_veid_bundle_init_0 },
- { tu102_grctx_init_unknown_bundle_init_0 },
+tu102_grctx_pack_sw_bundle64_init[] = {
+ { tu102_grctx_init_unknown_bundle_init_0, .type = 64 },
{}
};
-static void
-tu102_grctx_generate_attrib(struct gf100_grctx *info)
+void
+tu102_grctx_generate_unknown(struct gf100_gr_chan *chan, u64 addr, u32 size)
{
- const u64 size = 0x80000; /*XXX: educated guess */
- const int s = 8;
- const int b = mmio_vram(info, size, (1 << s), true);
-
- gv100_grctx_generate_attrib(info);
-
- mmio_refn(info, 0x408070, 0x00000000, s, b);
- mmio_wr32(info, 0x408074, size >> s); /*XXX: guess */
- mmio_refn(info, 0x419034, 0x00000000, s, b);
- mmio_wr32(info, 0x408078, 0x00000000);
+ gf100_grctx_patch_wr32(chan, 0x408070, addr >> 8);
+ gf100_grctx_patch_wr32(chan, 0x408074, size >> 8); /*XXX: guess */
+ gf100_grctx_patch_wr32(chan, 0x419034, addr >> 8);
+ gf100_grctx_patch_wr32(chan, 0x408078, 0x00000000);
}
const struct gf100_grctx_func
tu102_grctx = {
- .unkn88c = gv100_grctx_unkn88c,
.main = gf100_grctx_generate_main,
.unkn = gv100_grctx_generate_unkn,
- .sw_veid_bundle_init = tu102_grctx_pack_sw_veid_bundle_init,
+ .sw_bundle64_init = tu102_grctx_pack_sw_bundle64_init,
.bundle = gm107_grctx_generate_bundle,
.bundle_size = 0x3000,
.bundle_min_gpm_fifo_depth = 0x180,
.bundle_token_limit = 0xa80,
.pagepool = gp100_grctx_generate_pagepool,
.pagepool_size = 0x20000,
- .attrib = tu102_grctx_generate_attrib,
+ .attrib_cb_size = gp102_grctx_generate_attrib_cb_size,
+ .attrib_cb = gv100_grctx_generate_attrib_cb,
+ .attrib = gv100_grctx_generate_attrib,
.attrib_nr_max = 0x800,
.attrib_nr = 0x700,
+ .unknown_size = 0x80000,
+ .unknown = tu102_grctx_generate_unknown,
.alpha_nr_max = 0xc00,
.alpha_nr = 0x800,
.gfxp_nr = 0xfa8,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ga102.c
new file mode 100644
index 000000000000..a5b5ac2755a2
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ga102.c
@@ -0,0 +1,347 @@
+/*
+ * Copyright 2019 Red Hat 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 "gf100.h"
+#include "ctxgf100.h"
+
+#include <core/firmware.h>
+#include <subdev/acr.h>
+#include <subdev/timer.h>
+#include <subdev/vfn.h>
+
+#include <nvfw/flcn.h>
+
+#include <nvif/class.h>
+
+static void
+ga102_gr_zbc_clear_color(struct gf100_gr *gr, int zbc)
+{
+ struct nvkm_device *device = gr->base.engine.subdev.device;
+ u32 invalid[] = { 0, 0, 0, 0 }, *color;
+
+ if (gr->zbc_color[zbc].format)
+ color = gr->zbc_color[zbc].l2;
+ else
+ color = invalid;
+
+ nvkm_mask(device, 0x41bcb4, 0x0000001f, zbc);
+ nvkm_wr32(device, 0x41bcec, color[0]);
+ nvkm_wr32(device, 0x41bcf0, color[1]);
+ nvkm_wr32(device, 0x41bcf4, color[2]);
+ nvkm_wr32(device, 0x41bcf8, color[3]);
+}
+
+static const struct gf100_gr_func_zbc
+ga102_gr_zbc = {
+ .clear_color = ga102_gr_zbc_clear_color,
+ .clear_depth = gp100_gr_zbc_clear_depth,
+ .stencil_get = gp102_gr_zbc_stencil_get,
+ .clear_stencil = gp102_gr_zbc_clear_stencil,
+};
+
+static void
+ga102_gr_gpccs_reset(struct gf100_gr *gr)
+{
+ struct nvkm_device *device = gr->base.engine.subdev.device;
+
+ nvkm_wr32(device, 0x41a610, 0x00000000);
+ nvkm_msec(device, 1, NVKM_DELAY);
+ nvkm_wr32(device, 0x41a610, 0x00000001);
+}
+
+static const struct nvkm_acr_lsf_func
+ga102_gr_gpccs_acr = {
+ .flags = NVKM_ACR_LSF_FORCE_PRIV_LOAD,
+ .bl_entry = 0x3400,
+ .bld_size = sizeof(struct flcn_bl_dmem_desc_v2),
+ .bld_write = gp108_gr_acr_bld_write,
+ .bld_patch = gp108_gr_acr_bld_patch,
+};
+
+static void
+ga102_gr_fecs_reset(struct gf100_gr *gr)
+{
+ struct nvkm_device *device = gr->base.engine.subdev.device;
+
+ nvkm_wr32(device, 0x409614, 0x00000010);
+ nvkm_wr32(device, 0x41a614, 0x00000020);
+ nvkm_usec(device, 10, NVKM_DELAY);
+ nvkm_wr32(device, 0x409614, 0x00000110);
+ nvkm_wr32(device, 0x41a614, 0x00000a20);
+ nvkm_usec(device, 10, NVKM_DELAY);
+ nvkm_rd32(device, 0x409614);
+ nvkm_rd32(device, 0x41a614);
+}
+
+static const struct nvkm_acr_lsf_func
+ga102_gr_fecs_acr = {
+ .bl_entry = 0x7e00,
+ .bld_size = sizeof(struct flcn_bl_dmem_desc_v2),
+ .bld_write = gp108_gr_acr_bld_write,
+ .bld_patch = gp108_gr_acr_bld_patch,
+};
+
+static void
+ga102_gr_init_rop_exceptions(struct gf100_gr *gr)
+{
+ struct nvkm_device *device = gr->base.engine.subdev.device;
+
+ nvkm_wr32(device, 0x41bcbc, 0x40000000);
+ nvkm_wr32(device, 0x41bc38, 0x40000000);
+ nvkm_wr32(device, 0x41ac94, nvkm_rd32(device, 0x502c94));
+}
+
+static void
+ga102_gr_init_40a790(struct gf100_gr *gr)
+{
+ nvkm_wr32(gr->base.engine.subdev.device, 0x40a790, 0xc0000000);
+}
+
+static void
+ga102_gr_init_gpc_mmu(struct gf100_gr *gr)
+{
+ struct nvkm_device *device = gr->base.engine.subdev.device;
+
+ nvkm_wr32(device, 0x418880, nvkm_rd32(device, 0x100c80) & 0xf8001fff);
+ nvkm_wr32(device, 0x418894, 0x00000000);
+
+ nvkm_wr32(device, 0x4188b4, nvkm_rd32(device, 0x100cc8));
+ nvkm_wr32(device, 0x4188b8, nvkm_rd32(device, 0x100ccc));
+ nvkm_wr32(device, 0x4188b0, nvkm_rd32(device, 0x100cc4));
+}
+
+static struct nvkm_intr *
+ga102_gr_oneinit_intr(struct gf100_gr *gr, enum nvkm_intr_type *pvector)
+{
+ struct nvkm_device *device = gr->base.engine.subdev.device;
+
+ *pvector = nvkm_rd32(device, 0x400154) & 0x00000fff;
+ return &device->vfn->intr;
+}
+
+static const struct gf100_gr_func
+ga102_gr = {
+ .oneinit_intr = ga102_gr_oneinit_intr,
+ .oneinit_tiles = gm200_gr_oneinit_tiles,
+ .oneinit_sm_id = gv100_gr_oneinit_sm_id,
+ .init = gf100_gr_init,
+ .init_419bd8 = gv100_gr_init_419bd8,
+ .init_gpc_mmu = ga102_gr_init_gpc_mmu,
+ .init_vsc_stream_master = gk104_gr_init_vsc_stream_master,
+ .init_zcull = tu102_gr_init_zcull,
+ .init_num_active_ltcs = gf100_gr_init_num_active_ltcs,
+ .init_swdx_pes_mask = gp102_gr_init_swdx_pes_mask,
+ .init_fs = tu102_gr_init_fs,
+ .init_fecs_exceptions = tu102_gr_init_fecs_exceptions,
+ .init_40a790 = ga102_gr_init_40a790,
+ .init_ds_hww_esr_2 = gm200_gr_init_ds_hww_esr_2,
+ .init_sked_hww_esr = gk104_gr_init_sked_hww_esr,
+ .init_ppc_exceptions = gk104_gr_init_ppc_exceptions,
+ .init_504430 = gv100_gr_init_504430,
+ .init_shader_exceptions = gv100_gr_init_shader_exceptions,
+ .init_rop_exceptions = ga102_gr_init_rop_exceptions,
+ .init_4188a4 = gv100_gr_init_4188a4,
+ .trap_mp = gv100_gr_trap_mp,
+ .fecs.reset = ga102_gr_fecs_reset,
+ .gpccs.reset = ga102_gr_gpccs_reset,
+ .rops = gm200_gr_rops,
+ .gpc_nr = 7,
+ .tpc_nr = 6,
+ .ppc_nr = 3,
+ .grctx = &ga102_grctx,
+ .zbc = &ga102_gr_zbc,
+ .sclass = {
+ { -1, -1, FERMI_TWOD_A },
+ { -1, -1, KEPLER_INLINE_TO_MEMORY_B },
+ { -1, -1, AMPERE_B, &gf100_fermi },
+ { -1, -1, AMPERE_COMPUTE_B },
+ {}
+ }
+};
+
+MODULE_FIRMWARE("nvidia/ga102/gr/fecs_bl.bin");
+MODULE_FIRMWARE("nvidia/ga102/gr/fecs_sig.bin");
+MODULE_FIRMWARE("nvidia/ga102/gr/gpccs_bl.bin");
+MODULE_FIRMWARE("nvidia/ga102/gr/gpccs_sig.bin");
+MODULE_FIRMWARE("nvidia/ga102/gr/NET_img.bin");
+
+MODULE_FIRMWARE("nvidia/ga103/gr/fecs_bl.bin");
+MODULE_FIRMWARE("nvidia/ga103/gr/fecs_sig.bin");
+MODULE_FIRMWARE("nvidia/ga103/gr/gpccs_bl.bin");
+MODULE_FIRMWARE("nvidia/ga103/gr/gpccs_sig.bin");
+MODULE_FIRMWARE("nvidia/ga103/gr/NET_img.bin");
+
+MODULE_FIRMWARE("nvidia/ga104/gr/fecs_bl.bin");
+MODULE_FIRMWARE("nvidia/ga104/gr/fecs_sig.bin");
+MODULE_FIRMWARE("nvidia/ga104/gr/gpccs_bl.bin");
+MODULE_FIRMWARE("nvidia/ga104/gr/gpccs_sig.bin");
+MODULE_FIRMWARE("nvidia/ga104/gr/NET_img.bin");
+
+MODULE_FIRMWARE("nvidia/ga106/gr/fecs_bl.bin");
+MODULE_FIRMWARE("nvidia/ga106/gr/fecs_sig.bin");
+MODULE_FIRMWARE("nvidia/ga106/gr/gpccs_bl.bin");
+MODULE_FIRMWARE("nvidia/ga106/gr/gpccs_sig.bin");
+MODULE_FIRMWARE("nvidia/ga106/gr/NET_img.bin");
+
+MODULE_FIRMWARE("nvidia/ga107/gr/fecs_bl.bin");
+MODULE_FIRMWARE("nvidia/ga107/gr/fecs_sig.bin");
+MODULE_FIRMWARE("nvidia/ga107/gr/gpccs_bl.bin");
+MODULE_FIRMWARE("nvidia/ga107/gr/gpccs_sig.bin");
+MODULE_FIRMWARE("nvidia/ga107/gr/NET_img.bin");
+
+struct netlist_region {
+ u32 region_id;
+ u32 data_size;
+ u32 data_offset;
+};
+
+struct netlist_image_header {
+ u32 version;
+ u32 regions;
+};
+
+struct netlist_image {
+ struct netlist_image_header header;
+ struct netlist_region regions[];
+};
+
+struct netlist_av64 {
+ u32 addr;
+ u32 data_hi;
+ u32 data_lo;
+};
+
+static int
+ga102_gr_av64_to_init(struct nvkm_blob *blob, struct gf100_gr_pack **ppack)
+{
+ struct gf100_gr_init *init;
+ struct gf100_gr_pack *pack;
+ int nent;
+ int i;
+
+ nent = (blob->size / sizeof(struct netlist_av64));
+ pack = vzalloc((sizeof(*pack) * 2) + (sizeof(*init) * (nent + 1)));
+ if (!pack)
+ return -ENOMEM;
+
+ init = (void *)(pack + 2);
+ pack[0].init = init;
+ pack[0].type = 64;
+
+ for (i = 0; i < nent; i++) {
+ struct gf100_gr_init *ent = &init[i];
+ struct netlist_av64 *av = &((struct netlist_av64 *)blob->data)[i];
+
+ ent->addr = av->addr;
+ ent->data = ((u64)av->data_hi << 32) | av->data_lo;
+ ent->count = 1;
+ ent->pitch = 1;
+ }
+
+ *ppack = pack;
+ return 0;
+}
+
+static int
+ga102_gr_load(struct gf100_gr *gr, int ver, const struct gf100_gr_fwif *fwif)
+{
+ struct nvkm_subdev *subdev = &gr->base.engine.subdev;
+ const struct firmware *fw;
+ const struct netlist_image *net;
+ const struct netlist_region *fecs_inst = NULL;
+ const struct netlist_region *fecs_data = NULL;
+ const struct netlist_region *gpccs_inst = NULL;
+ const struct netlist_region *gpccs_data = NULL;
+ int ret, i;
+
+ ret = nvkm_firmware_get(subdev, "gr/NET_img", 0, &fw);
+ if (ret)
+ return ret;
+
+ net = (const void *)fw->data;
+ nvkm_debug(subdev, "netlist version %d, %d regions\n",
+ net->header.version, net->header.regions);
+
+ for (i = 0; i < net->header.regions; i++) {
+ const struct netlist_region *reg = &net->regions[i];
+ struct nvkm_blob blob = {
+ .data = (void *)fw->data + reg->data_offset,
+ .size = reg->data_size,
+ };
+
+ nvkm_debug(subdev, "\t%2d: %08x %08x\n",
+ reg->region_id, reg->data_offset, reg->data_size);
+
+ switch (reg->region_id) {
+ case 0: fecs_data = reg; break;
+ case 1: fecs_inst = reg; break;
+ case 2: gpccs_data = reg; break;
+ case 3: gpccs_inst = reg; break;
+ case 4: gk20a_gr_av_to_init(&blob, &gr->bundle); break;
+ case 5: gk20a_gr_aiv_to_init(&blob, &gr->sw_ctx); break;
+ case 7: gk20a_gr_av_to_method(&blob, &gr->method); break;
+ case 28: tu102_gr_av_to_init_veid(&blob, &gr->bundle_veid); break;
+ case 34: ga102_gr_av64_to_init(&blob, &gr->bundle64); break;
+ case 48: gk20a_gr_av_to_init(&blob, &gr->sw_nonctx1); break;
+ case 49: gk20a_gr_av_to_init(&blob, &gr->sw_nonctx2); break;
+ case 50: gk20a_gr_av_to_init(&blob, &gr->sw_nonctx3); break;
+ case 51: gk20a_gr_av_to_init(&blob, &gr->sw_nonctx4); break;
+ default:
+ break;
+ }
+ }
+
+ ret = nvkm_acr_lsfw_load_bl_sig_net(subdev, &gr->fecs.falcon, NVKM_ACR_LSF_FECS,
+ "gr/fecs_", ver, fwif->fecs,
+ fw->data + fecs_inst->data_offset,
+ fecs_inst->data_size,
+ fw->data + fecs_data->data_offset,
+ fecs_data->data_size);
+ if (ret)
+ return ret;
+
+ ret = nvkm_acr_lsfw_load_bl_sig_net(subdev, &gr->gpccs.falcon, NVKM_ACR_LSF_GPCCS,
+ "gr/gpccs_", ver, fwif->gpccs,
+ fw->data + gpccs_inst->data_offset,
+ gpccs_inst->data_size,
+ fw->data + gpccs_data->data_offset,
+ gpccs_data->data_size);
+ if (ret)
+ return ret;
+
+ gr->firmware = true;
+
+ nvkm_firmware_put(fw);
+ return 0;
+}
+
+static const struct gf100_gr_fwif
+ga102_gr_fwif[] = {
+ { 0, ga102_gr_load, &ga102_gr, &ga102_gr_fecs_acr, &ga102_gr_gpccs_acr },
+ { -1, gm200_gr_nofw },
+ {}
+};
+
+int
+ga102_gr_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_gr **pgr)
+{
+ return gf100_gr_new_(ga102_gr_fwif, device, type, inst, pgr);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
index f16eabf4f642..5f20079c3660 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c
@@ -67,7 +67,7 @@ gf100_gr_zbc_color_get(struct gf100_gr *gr, int format,
struct nvkm_ltc *ltc = gr->base.engine.subdev.device->ltc;
int zbc = -ENOSPC, i;
- for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) {
+ for (i = ltc->zbc_color_min; i <= ltc->zbc_color_max; i++) {
if (gr->zbc_color[i].format) {
if (gr->zbc_color[i].format != format)
continue;
@@ -114,7 +114,7 @@ gf100_gr_zbc_depth_get(struct gf100_gr *gr, int format,
struct nvkm_ltc *ltc = gr->base.engine.subdev.device->ltc;
int zbc = -ENOSPC, i;
- for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) {
+ for (i = ltc->zbc_depth_min; i <= ltc->zbc_depth_max; i++) {
if (gr->zbc_depth[i].format) {
if (gr->zbc_depth[i].format != format)
continue;
@@ -355,15 +355,14 @@ static void *
gf100_gr_chan_dtor(struct nvkm_object *object)
{
struct gf100_gr_chan *chan = gf100_gr_chan(object);
- int i;
-
- for (i = 0; i < ARRAY_SIZE(chan->data); i++) {
- nvkm_vmm_put(chan->vmm, &chan->data[i].vma);
- nvkm_memory_unref(&chan->data[i].mem);
- }
nvkm_vmm_put(chan->vmm, &chan->mmio_vma);
nvkm_memory_unref(&chan->mmio);
+
+ nvkm_vmm_put(chan->vmm, &chan->attrib_cb);
+ nvkm_vmm_put(chan->vmm, &chan->unknown);
+ nvkm_vmm_put(chan->vmm, &chan->bundle_cb);
+ nvkm_vmm_put(chan->vmm, &chan->pagepool);
nvkm_vmm_unref(&chan->vmm);
return chan;
}
@@ -380,12 +379,10 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
struct nvkm_object **pobject)
{
struct gf100_gr *gr = gf100_gr(base);
- struct gf100_gr_data *data = gr->mmio_data;
- struct gf100_gr_mmio *mmio = gr->mmio_list;
struct gf100_gr_chan *chan;
struct gf100_vmm_map_v0 args = { .priv = 1 };
struct nvkm_device *device = gr->base.engine.subdev.device;
- int ret, i;
+ int ret;
if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
return -ENOMEM;
@@ -394,63 +391,91 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
chan->vmm = nvkm_vmm_ref(fifoch->vmm);
*pobject = &chan->object;
- /* allocate memory for a "mmio list" buffer that's used by the HUB
- * fuc to modify some per-context register settings on first load
- * of the context.
- */
- ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x100,
- false, &chan->mmio);
+ /* Map pagepool. */
+ ret = nvkm_vmm_get(chan->vmm, 12, nvkm_memory_size(gr->pagepool), &chan->pagepool);
if (ret)
return ret;
- ret = nvkm_vmm_get(fifoch->vmm, 12, 0x1000, &chan->mmio_vma);
+ ret = nvkm_memory_map(gr->pagepool, 0, chan->vmm, chan->pagepool, &args, sizeof(args));
if (ret)
return ret;
- ret = nvkm_memory_map(chan->mmio, 0, fifoch->vmm,
- chan->mmio_vma, &args, sizeof(args));
+ /* Map bundle circular buffer. */
+ ret = nvkm_vmm_get(chan->vmm, 12, nvkm_memory_size(gr->bundle_cb), &chan->bundle_cb);
+ if (ret)
+ return ret;
+
+ ret = nvkm_memory_map(gr->bundle_cb, 0, chan->vmm, chan->bundle_cb, &args, sizeof(args));
+ if (ret)
+ return ret;
+
+ /* Map attribute circular buffer. */
+ ret = nvkm_vmm_get(chan->vmm, 12, nvkm_memory_size(gr->attrib_cb), &chan->attrib_cb);
if (ret)
return ret;
- /* allocate buffers referenced by mmio list */
- for (i = 0; data->size && i < ARRAY_SIZE(gr->mmio_data); i++) {
- ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST,
- data->size, data->align, false,
- &chan->data[i].mem);
+ if (device->card_type < GP100) {
+ ret = nvkm_memory_map(gr->attrib_cb, 0, chan->vmm, chan->attrib_cb, NULL, 0);
if (ret)
return ret;
-
- ret = nvkm_vmm_get(fifoch->vmm, 12,
- nvkm_memory_size(chan->data[i].mem),
- &chan->data[i].vma);
+ } else {
+ ret = nvkm_memory_map(gr->attrib_cb, 0, chan->vmm, chan->attrib_cb,
+ &args, sizeof(args));;
if (ret)
return ret;
+ }
- args.priv = data->priv;
+ /* Map some context buffer of unknown purpose. */
+ if (gr->func->grctx->unknown_size) {
+ ret = nvkm_vmm_get(chan->vmm, 12, nvkm_memory_size(gr->unknown), &chan->unknown);
+ if (ret)
+ return ret;
- ret = nvkm_memory_map(chan->data[i].mem, 0, chan->vmm,
- chan->data[i].vma, &args, sizeof(args));
+ ret = nvkm_memory_map(gr->unknown, 0, chan->vmm, chan->unknown,
+ &args, sizeof(args));
if (ret)
return ret;
+ }
- data++;
+ /* Generate golden context image. */
+ mutex_lock(&gr->fecs.mutex);
+ if (gr->data == NULL) {
+ ret = gf100_grctx_generate(gr, chan, fifoch->inst);
+ if (ret) {
+ nvkm_error(&base->engine.subdev, "failed to construct context\n");
+ return ret;
+ }
}
+ mutex_unlock(&gr->fecs.mutex);
- /* finally, fill in the mmio list and point the context at it */
- nvkm_kmap(chan->mmio);
- for (i = 0; mmio->addr && i < ARRAY_SIZE(gr->mmio_list); i++) {
- u32 addr = mmio->addr;
- u32 data = mmio->data;
+ /* allocate memory for a "mmio list" buffer that's used by the HUB
+ * fuc to modify some per-context register settings on first load
+ * of the context.
+ */
+ ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0x100,
+ false, &chan->mmio);
+ if (ret)
+ return ret;
- if (mmio->buffer >= 0) {
- u64 info = chan->data[mmio->buffer].vma->addr;
- data |= info >> mmio->shift;
- }
+ ret = nvkm_vmm_get(fifoch->vmm, 12, 0x1000, &chan->mmio_vma);
+ if (ret)
+ return ret;
- nvkm_wo32(chan->mmio, chan->mmio_nr++ * 4, addr);
- nvkm_wo32(chan->mmio, chan->mmio_nr++ * 4, data);
- mmio++;
- }
+ ret = nvkm_memory_map(chan->mmio, 0, fifoch->vmm,
+ chan->mmio_vma, &args, sizeof(args));
+ if (ret)
+ return ret;
+
+ /* finally, fill in the mmio list and point the context at it */
+ nvkm_kmap(chan->mmio);
+ gr->func->grctx->pagepool(chan, chan->pagepool->addr);
+ gr->func->grctx->bundle(chan, chan->bundle_cb->addr, gr->func->grctx->bundle_size);
+ gr->func->grctx->attrib_cb(chan, chan->attrib_cb->addr, gr->func->grctx->attrib_cb_size(gr));
+ gr->func->grctx->attrib(chan);
+ if (gr->func->grctx->patch_ltc)
+ gr->func->grctx->patch_ltc(chan);
+ if (gr->func->grctx->unknown_size)
+ gr->func->grctx->unknown(chan, chan->unknown->addr, gr->func->grctx->unknown_size);
nvkm_done(chan->mmio);
return 0;
}
@@ -727,7 +752,7 @@ gf100_gr_fecs_ctrl_ctxsw(struct gf100_gr *gr, u32 mthd)
struct nvkm_device *device = gr->base.engine.subdev.device;
nvkm_wr32(device, 0x409804, 0xffffffff);
- nvkm_wr32(device, 0x409840, 0xffffffff);
+ nvkm_wr32(device, 0x409800, 0x00000000);
nvkm_wr32(device, 0x409500, 0xffffffff);
nvkm_wr32(device, 0x409504, mthd);
nvkm_msec(device, 2000,
@@ -771,12 +796,45 @@ gf100_gr_fecs_stop_ctxsw(struct nvkm_gr *base)
return ret;
}
+static int
+gf100_gr_fecs_halt_pipeline(struct gf100_gr *gr)
+{
+ int ret = 0;
+
+ if (gr->firmware) {
+ mutex_lock(&gr->fecs.mutex);
+ ret = gf100_gr_fecs_ctrl_ctxsw(gr, 0x04);
+ mutex_unlock(&gr->fecs.mutex);
+ }
+
+ return ret;
+}
+
+int
+gf100_gr_fecs_wfi_golden_save(struct gf100_gr *gr, u32 inst)
+{
+ struct nvkm_device *device = gr->base.engine.subdev.device;
+
+ nvkm_mask(device, 0x409800, 0x00000003, 0x00000000);
+ nvkm_wr32(device, 0x409500, inst);
+ nvkm_wr32(device, 0x409504, 0x00000009);
+ nvkm_msec(device, 2000,
+ u32 stat = nvkm_rd32(device, 0x409800);
+ if (stat & 0x00000002)
+ return -EIO;
+ if (stat & 0x00000001)
+ return 0;
+ );
+
+ return -ETIMEDOUT;
+}
+
int
gf100_gr_fecs_bind_pointer(struct gf100_gr *gr, u32 inst)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
- nvkm_wr32(device, 0x409840, 0x00000030);
+ nvkm_mask(device, 0x409800, 0x00000030, 0x00000000);
nvkm_wr32(device, 0x409500, inst);
nvkm_wr32(device, 0x409504, 0x00000003);
nvkm_msec(device, 2000,
@@ -867,7 +925,7 @@ gf100_gr_fecs_discover_pm_image_size(struct gf100_gr *gr, u32 *psize)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
- nvkm_wr32(device, 0x409840, 0xffffffff);
+ nvkm_wr32(device, 0x409800, 0x00000000);
nvkm_wr32(device, 0x409500, 0x00000000);
nvkm_wr32(device, 0x409504, 0x00000025);
nvkm_msec(device, 2000,
@@ -883,7 +941,7 @@ gf100_gr_fecs_discover_zcull_image_size(struct gf100_gr *gr, u32 *psize)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
- nvkm_wr32(device, 0x409840, 0xffffffff);
+ nvkm_wr32(device, 0x409800, 0x00000000);
nvkm_wr32(device, 0x409500, 0x00000000);
nvkm_wr32(device, 0x409504, 0x00000016);
nvkm_msec(device, 2000,
@@ -899,7 +957,7 @@ gf100_gr_fecs_discover_image_size(struct gf100_gr *gr, u32 *psize)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
- nvkm_wr32(device, 0x409840, 0xffffffff);
+ nvkm_wr32(device, 0x409800, 0x00000000);
nvkm_wr32(device, 0x409500, 0x00000000);
nvkm_wr32(device, 0x409504, 0x00000010);
nvkm_msec(device, 2000,
@@ -915,7 +973,7 @@ gf100_gr_fecs_set_watchdog_timeout(struct gf100_gr *gr, u32 timeout)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
- nvkm_wr32(device, 0x409840, 0xffffffff);
+ nvkm_wr32(device, 0x409800, 0x00000000);
nvkm_wr32(device, 0x409500, timeout);
nvkm_wr32(device, 0x409504, 0x00000021);
}
@@ -955,7 +1013,7 @@ gf100_gr_zbc_init(struct gf100_gr *gr)
const u32 f32_1[] = { 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000,
0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000 };
struct nvkm_ltc *ltc = gr->base.engine.subdev.device->ltc;
- int index, c = ltc->zbc_min, d = ltc->zbc_min, s = ltc->zbc_min;
+ int index, c = ltc->zbc_color_min, d = ltc->zbc_depth_min, s = ltc->zbc_depth_min;
if (!gr->zbc_color[0].format) {
gf100_gr_zbc_color_get(gr, 1, & zero[0], &zero[4]); c++;
@@ -971,13 +1029,13 @@ gf100_gr_zbc_init(struct gf100_gr *gr)
}
}
- for (index = c; index <= ltc->zbc_max; index++)
+ for (index = c; index <= ltc->zbc_color_max; index++)
gr->func->zbc->clear_color(gr, index);
- for (index = d; index <= ltc->zbc_max; index++)
+ for (index = d; index <= ltc->zbc_depth_max; index++)
gr->func->zbc->clear_depth(gr, index);
if (gr->func->zbc->clear_stencil) {
- for (index = s; index <= ltc->zbc_max; index++)
+ for (index = s; index <= ltc->zbc_depth_max; index++)
gr->func->zbc->clear_stencil(gr, index);
}
}
@@ -1003,7 +1061,7 @@ gf100_gr_wait_idle(struct gf100_gr *gr)
nvkm_rd32(device, 0x400700);
gr_enabled = nvkm_rd32(device, 0x200) & 0x1000;
- ctxsw_active = nvkm_rd32(device, 0x2640) & 0x8000;
+ ctxsw_active = nvkm_fifo_ctxsw_in_progress(&gr->base.engine);
gr_busy = nvkm_rd32(device, 0x40060c) & 0x1;
if (!gr_enabled || (!gr_busy && !ctxsw_active))
@@ -1039,7 +1097,7 @@ gf100_gr_icmd(struct gf100_gr *gr, const struct gf100_gr_pack *p)
struct nvkm_device *device = gr->base.engine.subdev.device;
const struct gf100_gr_pack *pack;
const struct gf100_gr_init *init;
- u32 data = 0;
+ u64 data = 0;
nvkm_wr32(device, 0x400208, 0x80000000);
@@ -1049,6 +1107,8 @@ gf100_gr_icmd(struct gf100_gr *gr, const struct gf100_gr_pack *p)
if ((pack == p && init == p->init) || data != init->data) {
nvkm_wr32(device, 0x400204, init->data);
+ if (pack->type == 64)
+ nvkm_wr32(device, 0x40020c, upper_32_bits(init->data));
data = init->data;
}
@@ -1542,13 +1602,13 @@ gf100_gr_ctxctl_isr(struct gf100_gr *gr)
}
}
-static void
-gf100_gr_intr(struct nvkm_gr *base)
+static irqreturn_t
+gf100_gr_intr(struct nvkm_inth *inth)
{
- struct gf100_gr *gr = gf100_gr(base);
+ struct gf100_gr *gr = container_of(inth, typeof(*gr), base.engine.subdev.inth);
struct nvkm_subdev *subdev = &gr->base.engine.subdev;
struct nvkm_device *device = subdev->device;
- struct nvkm_fifo_chan *chan;
+ struct nvkm_chan *chan;
unsigned long flags;
u64 inst = nvkm_rd32(device, 0x409b00) & 0x0fffffff;
u32 stat = nvkm_rd32(device, 0x400100);
@@ -1561,10 +1621,10 @@ gf100_gr_intr(struct nvkm_gr *base)
const char *name = "unknown";
int chid = -1;
- chan = nvkm_fifo_chan_inst(device->fifo, (u64)inst << 12, &flags);
+ chan = nvkm_chan_get_inst(&gr->base.engine, (u64)inst << 12, &flags);
if (chan) {
- name = chan->object.client->name;
- chid = chan->chid;
+ name = chan->name;
+ chid = chan->id;
}
if (device->card_type < NV_E0 || subc < 4)
@@ -1631,7 +1691,8 @@ gf100_gr_intr(struct nvkm_gr *base)
}
nvkm_wr32(device, 0x400500, 0x00010001);
- nvkm_fifo_chan_put(device->fifo, flags, &chan);
+ nvkm_chan_put(&chan, flags);
+ return IRQ_HANDLED;
}
static void
@@ -1721,7 +1782,7 @@ gf100_gr_init_ctxctl_ext(struct gf100_gr *gr)
nvkm_mc_unk260(device, 1);
/* start both of them running */
- nvkm_wr32(device, 0x409840, 0xffffffff);
+ nvkm_wr32(device, 0x409800, 0x00000000);
nvkm_wr32(device, 0x41a10c, 0x00000000);
nvkm_wr32(device, 0x40910c, 0x00000000);
@@ -1763,15 +1824,6 @@ gf100_gr_init_ctxctl_ext(struct gf100_gr *gr)
return ret;
}
- /* Generate golden context image. */
- if (gr->data == NULL) {
- int ret = gf100_grctx_generate(gr);
- if (ret) {
- nvkm_error(subdev, "failed to construct context\n");
- return ret;
- }
- }
-
return 0;
}
@@ -1823,14 +1875,6 @@ gf100_gr_init_ctxctl_int(struct gf100_gr *gr)
}
gr->size = nvkm_rd32(device, 0x409804);
- if (gr->data == NULL) {
- int ret = gf100_grctx_generate(gr);
- if (ret) {
- nvkm_error(subdev, "failed to construct context\n");
- return ret;
- }
- }
-
return 0;
}
@@ -1847,10 +1891,11 @@ gf100_gr_init_ctxctl(struct gf100_gr *gr)
return ret;
}
-void
+int
gf100_gr_oneinit_sm_id(struct gf100_gr *gr)
{
int tpc, gpc;
+
for (tpc = 0; tpc < gr->tpc_max; tpc++) {
for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
if (tpc < gr->tpc_nr[gpc]) {
@@ -1860,6 +1905,8 @@ gf100_gr_oneinit_sm_id(struct gf100_gr *gr)
}
}
}
+
+ return 0;
}
void
@@ -1944,7 +1991,17 @@ gf100_gr_oneinit(struct nvkm_gr *base)
struct gf100_gr *gr = gf100_gr(base);
struct nvkm_subdev *subdev = &gr->base.engine.subdev;
struct nvkm_device *device = subdev->device;
- int i, j;
+ struct nvkm_intr *intr = &device->mc->intr;
+ enum nvkm_intr_type intr_type = NVKM_INTR_SUBDEV;
+ int ret, i, j;
+
+ if (gr->func->oneinit_intr)
+ intr = gr->func->oneinit_intr(gr, &intr_type);
+
+ ret = nvkm_inth_add(intr, intr_type, NVKM_INTR_PRIO_NORMAL, &gr->base.engine.subdev,
+ gf100_gr_intr, &gr->base.engine.subdev.inth);
+ if (ret)
+ return ret;
nvkm_pmu_pgob(device->pmu, false);
@@ -1954,12 +2011,14 @@ gf100_gr_oneinit(struct nvkm_gr *base)
gr->tpc_nr[i] = nvkm_rd32(device, GPC_UNIT(i, 0x2608));
gr->tpc_max = max(gr->tpc_max, gr->tpc_nr[i]);
gr->tpc_total += gr->tpc_nr[i];
- gr->ppc_nr[i] = gr->func->ppc_nr;
- for (j = 0; j < gr->ppc_nr[i]; j++) {
+ for (j = 0; j < gr->func->ppc_nr; j++) {
gr->ppc_tpc_mask[i][j] =
nvkm_rd32(device, GPC_UNIT(i, 0x0c30 + (j * 4)));
if (gr->ppc_tpc_mask[i][j] == 0)
continue;
+
+ gr->ppc_nr[i]++;
+
gr->ppc_mask[i] |= (1 << j);
gr->ppc_tpc_nr[i][j] = hweight8(gr->ppc_tpc_mask[i][j]);
if (gr->ppc_tpc_min == 0 ||
@@ -1968,12 +2027,37 @@ gf100_gr_oneinit(struct nvkm_gr *base)
if (gr->ppc_tpc_max < gr->ppc_tpc_nr[i][j])
gr->ppc_tpc_max = gr->ppc_tpc_nr[i][j];
}
+
+ gr->ppc_total += gr->ppc_nr[i];
+ }
+
+ /* Allocate global context buffers. */
+ ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, gr->func->grctx->pagepool_size,
+ 0x100, false, &gr->pagepool);
+ if (ret)
+ return ret;
+
+ ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, gr->func->grctx->bundle_size,
+ 0x100, false, &gr->bundle_cb);
+ if (ret)
+ return ret;
+
+ ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, gr->func->grctx->attrib_cb_size(gr),
+ 0x1000, false, &gr->attrib_cb);
+ if (ret)
+ return ret;
+
+ if (gr->func->grctx->unknown_size) {
+ ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, gr->func->grctx->unknown_size,
+ 0x100, false, &gr->unknown);
+ if (ret)
+ return ret;
}
memset(gr->tile, 0xff, sizeof(gr->tile));
gr->func->oneinit_tiles(gr);
- gr->func->oneinit_sm_id(gr);
- return 0;
+
+ return gr->func->oneinit_sm_id(gr);
}
static int
@@ -1983,7 +2067,7 @@ gf100_gr_init_(struct nvkm_gr *base)
struct nvkm_subdev *subdev = &base->engine.subdev;
struct nvkm_device *device = subdev->device;
bool reset = device->chipset == 0x137 || device->chipset == 0x138;
- u32 ret;
+ int ret;
/* On certain GP107/GP108 boards, we trigger a weird issue where
* GR will stop responding to PRI accesses after we've asked the
@@ -2019,7 +2103,12 @@ gf100_gr_init_(struct nvkm_gr *base)
if (ret)
return ret;
- return gr->func->init(gr);
+ ret = gr->func->init(gr);
+ if (ret)
+ return ret;
+
+ nvkm_inth_allow(&subdev->inth);
+ return 0;
}
static int
@@ -2027,6 +2116,9 @@ gf100_gr_fini(struct nvkm_gr *base, bool suspend)
{
struct gf100_gr *gr = gf100_gr(base);
struct nvkm_subdev *subdev = &gr->base.engine.subdev;
+
+ nvkm_inth_block(&subdev->inth);
+
nvkm_falcon_put(&gr->gpccs.falcon, subdev);
nvkm_falcon_put(&gr->fecs.falcon, subdev);
return 0;
@@ -2039,6 +2131,11 @@ gf100_gr_dtor(struct nvkm_gr *base)
kfree(gr->data);
+ nvkm_memory_unref(&gr->unknown);
+ nvkm_memory_unref(&gr->attrib_cb);
+ nvkm_memory_unref(&gr->bundle_cb);
+ nvkm_memory_unref(&gr->pagepool);
+
nvkm_falcon_dtor(&gr->gpccs.falcon);
nvkm_falcon_dtor(&gr->fecs.falcon);
@@ -2047,81 +2144,27 @@ gf100_gr_dtor(struct nvkm_gr *base)
nvkm_blob_dtor(&gr->gpccs.inst);
nvkm_blob_dtor(&gr->gpccs.data);
+ vfree(gr->bundle64);
+ vfree(gr->bundle_veid);
vfree(gr->bundle);
vfree(gr->method);
vfree(gr->sw_ctx);
vfree(gr->sw_nonctx);
+ vfree(gr->sw_nonctx1);
+ vfree(gr->sw_nonctx2);
+ vfree(gr->sw_nonctx3);
+ vfree(gr->sw_nonctx4);
return gr;
}
-static const struct nvkm_gr_func
-gf100_gr_ = {
- .dtor = gf100_gr_dtor,
- .oneinit = gf100_gr_oneinit,
- .init = gf100_gr_init_,
- .fini = gf100_gr_fini,
- .intr = gf100_gr_intr,
- .units = gf100_gr_units,
- .chan_new = gf100_gr_chan_new,
- .object_get = gf100_gr_object_get,
- .chsw_load = gf100_gr_chsw_load,
- .ctxsw.pause = gf100_gr_fecs_stop_ctxsw,
- .ctxsw.resume = gf100_gr_fecs_start_ctxsw,
- .ctxsw.inst = gf100_gr_ctxsw_inst,
-};
-
static const struct nvkm_falcon_func
gf100_gr_flcn = {
- .fbif = 0x600,
.load_imem = nvkm_falcon_v1_load_imem,
.load_dmem = nvkm_falcon_v1_load_dmem,
- .read_dmem = nvkm_falcon_v1_read_dmem,
- .bind_context = nvkm_falcon_v1_bind_context,
- .wait_for_halt = nvkm_falcon_v1_wait_for_halt,
- .clear_interrupt = nvkm_falcon_v1_clear_interrupt,
- .set_start_addr = nvkm_falcon_v1_set_start_addr,
.start = nvkm_falcon_v1_start,
- .enable = nvkm_falcon_v1_enable,
- .disable = nvkm_falcon_v1_disable,
};
-int
-gf100_gr_new_(const struct gf100_gr_fwif *fwif, struct nvkm_device *device,
- enum nvkm_subdev_type type, int inst, struct nvkm_gr **pgr)
-{
- struct gf100_gr *gr;
- int ret;
-
- if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL)))
- return -ENOMEM;
- *pgr = &gr->base;
-
- ret = nvkm_gr_ctor(&gf100_gr_, device, type, inst, true, &gr->base);
- if (ret)
- return ret;
-
- fwif = nvkm_firmware_load(&gr->base.engine.subdev, fwif, "Gr", gr);
- if (IS_ERR(fwif))
- return PTR_ERR(fwif);
-
- gr->func = fwif->func;
-
- ret = nvkm_falcon_ctor(&gf100_gr_flcn, &gr->base.engine.subdev,
- "fecs", 0x409000, &gr->fecs.falcon);
- if (ret)
- return ret;
-
- mutex_init(&gr->fecs.mutex);
-
- ret = nvkm_falcon_ctor(&gf100_gr_flcn, &gr->base.engine.subdev,
- "gpccs", 0x41a000, &gr->gpccs.falcon);
- if (ret)
- return ret;
-
- return 0;
-}
-
void
gf100_gr_init_num_tpc_per_gpc(struct gf100_gr *gr, bool pd, bool ds)
{
@@ -2146,6 +2189,29 @@ gf100_gr_init_400054(struct gf100_gr *gr)
}
void
+gf100_gr_init_exception2(struct gf100_gr *gr)
+{
+ struct nvkm_device *device = gr->base.engine.subdev.device;
+
+ nvkm_wr32(device, 0x40011c, 0xffffffff);
+ nvkm_wr32(device, 0x400134, 0xffffffff);
+}
+
+void
+gf100_gr_init_rop_exceptions(struct gf100_gr *gr)
+{
+ struct nvkm_device *device = gr->base.engine.subdev.device;
+ int rop;
+
+ for (rop = 0; rop < gr->rop_nr; rop++) {
+ nvkm_wr32(device, ROP_UNIT(rop, 0x144), 0x40000000);
+ nvkm_wr32(device, ROP_UNIT(rop, 0x070), 0x40000000);
+ nvkm_wr32(device, ROP_UNIT(rop, 0x204), 0xffffffff);
+ nvkm_wr32(device, ROP_UNIT(rop, 0x208), 0xffffffff);
+ }
+}
+
+void
gf100_gr_init_shader_exceptions(struct gf100_gr *gr, int gpc, int tpc)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
@@ -2252,21 +2318,47 @@ gf100_gr_init_vsc_stream_master(struct gf100_gr *gr)
nvkm_mask(device, TPC_UNIT(0, 0, 0x05c), 0x00000001, 0x00000001);
}
+static int
+gf100_gr_reset(struct nvkm_gr *base)
+{
+ struct nvkm_subdev *subdev = &base->engine.subdev;
+ struct nvkm_device *device = subdev->device;
+ struct gf100_gr *gr = gf100_gr(base);
+
+ nvkm_mask(device, 0x400500, 0x00000001, 0x00000000);
+
+ WARN_ON(gf100_gr_fecs_halt_pipeline(gr));
+
+ subdev->func->fini(subdev, false);
+ nvkm_mc_disable(device, subdev->type, subdev->inst);
+ if (gr->func->gpccs.reset)
+ gr->func->gpccs.reset(gr);
+
+ nvkm_mc_enable(device, subdev->type, subdev->inst);
+ return subdev->func->init(subdev);
+}
+
int
gf100_gr_init(struct gf100_gr *gr)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
- int gpc, tpc, rop;
+ int gpc, tpc;
- if (gr->func->init_419bd8)
- gr->func->init_419bd8(gr);
+ nvkm_mask(device, 0x400500, 0x00010001, 0x00000000);
gr->func->init_gpc_mmu(gr);
- if (gr->sw_nonctx)
+ if (gr->sw_nonctx1) {
+ gf100_gr_mmio(gr, gr->sw_nonctx1);
+ gf100_gr_mmio(gr, gr->sw_nonctx2);
+ gf100_gr_mmio(gr, gr->sw_nonctx3);
+ gf100_gr_mmio(gr, gr->sw_nonctx4);
+ } else
+ if (gr->sw_nonctx) {
gf100_gr_mmio(gr, gr->sw_nonctx);
- else
+ } else {
gf100_gr_mmio(gr, gr->func->mmio);
+ }
gf100_gr_wait_idle(gr);
@@ -2298,6 +2390,10 @@ gf100_gr_init(struct gf100_gr *gr)
nvkm_wr32(device, 0x400124, 0x00000002);
gr->func->init_fecs_exceptions(gr);
+
+ if (gr->func->init_40a790)
+ gr->func->init_40a790(gr);
+
if (gr->func->init_ds_hww_esr_2)
gr->func->init_ds_hww_esr_2(gr);
@@ -2346,19 +2442,14 @@ gf100_gr_init(struct gf100_gr *gr)
nvkm_wr32(device, GPC_UNIT(gpc, 0x2c94), 0xffffffff);
}
- for (rop = 0; rop < gr->rop_nr; rop++) {
- nvkm_wr32(device, ROP_UNIT(rop, 0x144), 0x40000000);
- nvkm_wr32(device, ROP_UNIT(rop, 0x070), 0x40000000);
- nvkm_wr32(device, ROP_UNIT(rop, 0x204), 0xffffffff);
- nvkm_wr32(device, ROP_UNIT(rop, 0x208), 0xffffffff);
- }
+ gr->func->init_rop_exceptions(gr);
nvkm_wr32(device, 0x400108, 0xffffffff);
nvkm_wr32(device, 0x400138, 0xffffffff);
nvkm_wr32(device, 0x400118, 0xffffffff);
nvkm_wr32(device, 0x400130, 0xffffffff);
- nvkm_wr32(device, 0x40011c, 0xffffffff);
- nvkm_wr32(device, 0x400134, 0xffffffff);
+ if (gr->func->init_exception2)
+ gr->func->init_exception2(gr);
if (gr->func->init_400054)
gr->func->init_400054(gr);
@@ -2371,6 +2462,18 @@ gf100_gr_init(struct gf100_gr *gr)
return gf100_gr_init_ctxctl(gr);
}
+void
+gf100_gr_fecs_reset(struct gf100_gr *gr)
+{
+ struct nvkm_device *device = gr->base.engine.subdev.device;
+
+ nvkm_wr32(device, 0x409614, 0x00000070);
+ nvkm_usec(device, 10, NVKM_DELAY);
+ nvkm_mask(device, 0x409614, 0x00000700, 0x00000700);
+ nvkm_usec(device, 10, NVKM_DELAY);
+ nvkm_rd32(device, 0x409614);
+}
+
#include "fuc/hubgf100.fuc3.h"
struct gf100_gr_ucode
@@ -2391,6 +2494,22 @@ gf100_gr_gpccs_ucode = {
.data.size = sizeof(gf100_grgpc_data),
};
+static const struct nvkm_gr_func
+gf100_gr_ = {
+ .dtor = gf100_gr_dtor,
+ .oneinit = gf100_gr_oneinit,
+ .init = gf100_gr_init_,
+ .fini = gf100_gr_fini,
+ .reset = gf100_gr_reset,
+ .units = gf100_gr_units,
+ .chan_new = gf100_gr_chan_new,
+ .object_get = gf100_gr_object_get,
+ .chsw_load = gf100_gr_chsw_load,
+ .ctxsw.pause = gf100_gr_fecs_stop_ctxsw,
+ .ctxsw.resume = gf100_gr_fecs_start_ctxsw,
+ .ctxsw.inst = gf100_gr_ctxsw_inst,
+};
+
static const struct gf100_gr_func
gf100_gr = {
.oneinit_tiles = gf100_gr_oneinit_tiles,
@@ -2406,10 +2525,13 @@ gf100_gr = {
.init_419eb4 = gf100_gr_init_419eb4,
.init_tex_hww_esr = gf100_gr_init_tex_hww_esr,
.init_shader_exceptions = gf100_gr_init_shader_exceptions,
+ .init_rop_exceptions = gf100_gr_init_rop_exceptions,
+ .init_exception2 = gf100_gr_init_exception2,
.init_400054 = gf100_gr_init_400054,
.trap_mp = gf100_gr_trap_mp,
.mmio = gf100_gr_pack_mmio,
.fecs.ucode = &gf100_gr_fecs_ucode,
+ .fecs.reset = gf100_gr_fecs_reset,
.gpccs.ucode = &gf100_gr_gpccs_ucode,
.rops = gf100_gr_rops,
.grctx = &gf100_grctx,
@@ -2483,6 +2605,42 @@ gf100_gr_fwif[] = {
};
int
+gf100_gr_new_(const struct gf100_gr_fwif *fwif, struct nvkm_device *device,
+ enum nvkm_subdev_type type, int inst, struct nvkm_gr **pgr)
+{
+ struct gf100_gr *gr;
+ int ret;
+
+ if (!(gr = kzalloc(sizeof(*gr), GFP_KERNEL)))
+ return -ENOMEM;
+ *pgr = &gr->base;
+
+ ret = nvkm_gr_ctor(&gf100_gr_, device, type, inst, true, &gr->base);
+ if (ret)
+ return ret;
+
+ fwif = nvkm_firmware_load(&gr->base.engine.subdev, fwif, "Gr", gr);
+ if (IS_ERR(fwif))
+ return PTR_ERR(fwif);
+
+ gr->func = fwif->func;
+
+ ret = nvkm_falcon_ctor(&gf100_gr_flcn, &gr->base.engine.subdev,
+ "fecs", 0x409000, &gr->fecs.falcon);
+ if (ret)
+ return ret;
+
+ mutex_init(&gr->fecs.mutex);
+
+ ret = nvkm_falcon_ctor(&gf100_gr_flcn, &gr->base.engine.subdev,
+ "gpccs", 0x41a000, &gr->gpccs.falcon);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int
gf100_gr_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_gr **pgr)
{
return gf100_gr_new_(gf100_gr_fwif, device, type, inst, pgr);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h
index c0038f906135..94ca7ac16acf 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h
@@ -44,19 +44,6 @@ struct nvkm_acr_lsfw;
#define PPC_UNIT(t, m, r) (0x503000 + (t) * 0x8000 + (m) * 0x200 + (r))
#define TPC_UNIT(t, m, r) (0x504000 + (t) * 0x8000 + (m) * 0x800 + (r))
-struct gf100_gr_data {
- u32 size;
- u32 align;
- bool priv;
-};
-
-struct gf100_gr_mmio {
- u32 addr;
- u32 data;
- u32 shift;
- int buffer;
-};
-
struct gf100_gr_zbc_color {
u32 format;
u32 ds[4];
@@ -101,13 +88,19 @@ struct gf100_gr {
* using hardcoded arrays. To be allocated with vzalloc().
*/
struct gf100_gr_pack *sw_nonctx;
+ struct gf100_gr_pack *sw_nonctx1;
+ struct gf100_gr_pack *sw_nonctx2;
+ struct gf100_gr_pack *sw_nonctx3;
+ struct gf100_gr_pack *sw_nonctx4;
struct gf100_gr_pack *sw_ctx;
struct gf100_gr_pack *bundle;
+ struct gf100_gr_pack *bundle_veid;
+ struct gf100_gr_pack *bundle64;
struct gf100_gr_pack *method;
- struct gf100_gr_zbc_color zbc_color[NVKM_LTC_MAX_ZBC_CNT];
- struct gf100_gr_zbc_depth zbc_depth[NVKM_LTC_MAX_ZBC_CNT];
- struct gf100_gr_zbc_stencil zbc_stencil[NVKM_LTC_MAX_ZBC_CNT];
+ struct gf100_gr_zbc_color zbc_color[NVKM_LTC_MAX_ZBC_COLOR_CNT];
+ struct gf100_gr_zbc_depth zbc_depth[NVKM_LTC_MAX_ZBC_DEPTH_CNT];
+ struct gf100_gr_zbc_stencil zbc_stencil[NVKM_LTC_MAX_ZBC_DEPTH_CNT];
u8 rop_nr;
u8 gpc_nr;
@@ -120,6 +113,12 @@ struct gf100_gr {
u8 ppc_tpc_nr[GPC_MAX][4];
u8 ppc_tpc_min;
u8 ppc_tpc_max;
+ u8 ppc_total;
+
+ struct nvkm_memory *pagepool;
+ struct nvkm_memory *bundle_cb;
+ struct nvkm_memory *attrib_cb;
+ struct nvkm_memory *unknown;
u8 screen_tile_row_offset;
u8 tile[TPC_MAX];
@@ -130,8 +129,6 @@ struct gf100_gr {
} sm[TPC_MAX];
u8 sm_nr;
- struct gf100_gr_data mmio_data[4];
- struct gf100_gr_mmio mmio_list[4096/8];
u32 size;
u32 *data;
u32 size_zcull;
@@ -139,6 +136,7 @@ struct gf100_gr {
};
int gf100_gr_fecs_bind_pointer(struct gf100_gr *, u32 inst);
+int gf100_gr_fecs_wfi_golden_save(struct gf100_gr *, u32 inst);
struct gf100_gr_func_zbc {
void (*clear_color)(struct gf100_gr *, int zbc);
@@ -149,8 +147,9 @@ struct gf100_gr_func_zbc {
};
struct gf100_gr_func {
+ struct nvkm_intr *(*oneinit_intr)(struct gf100_gr *, enum nvkm_intr_type *);
void (*oneinit_tiles)(struct gf100_gr *);
- void (*oneinit_sm_id)(struct gf100_gr *);
+ int (*oneinit_sm_id)(struct gf100_gr *);
int (*init)(struct gf100_gr *);
void (*init_419bd8)(struct gf100_gr *);
void (*init_gpc_mmu)(struct gf100_gr *);
@@ -164,6 +163,7 @@ struct gf100_gr_func {
void (*init_swdx_pes_mask)(struct gf100_gr *);
void (*init_fs)(struct gf100_gr *);
void (*init_fecs_exceptions)(struct gf100_gr *);
+ void (*init_40a790)(struct gf100_gr *);
void (*init_ds_hww_esr_2)(struct gf100_gr *);
void (*init_40601c)(struct gf100_gr *);
void (*init_sked_hww_esr)(struct gf100_gr *);
@@ -174,6 +174,8 @@ struct gf100_gr_func {
void (*init_tex_hww_esr)(struct gf100_gr *, int gpc, int tpc);
void (*init_504430)(struct gf100_gr *, int gpc, int tpc);
void (*init_shader_exceptions)(struct gf100_gr *, int gpc, int tpc);
+ void (*init_rop_exceptions)(struct gf100_gr *);
+ void (*init_exception2)(struct gf100_gr *);
void (*init_400054)(struct gf100_gr *);
void (*init_4188a4)(struct gf100_gr *);
void (*trap_mp)(struct gf100_gr *, int gpc, int tpc);
@@ -181,9 +183,11 @@ struct gf100_gr_func {
const struct gf100_gr_pack *mmio;
struct {
struct gf100_gr_ucode *ucode;
+ void (*reset)(struct gf100_gr *);
} fecs;
struct {
struct gf100_gr_ucode *ucode;
+ void (*reset)(struct gf100_gr *);
} gpccs;
int (*rops)(struct gf100_gr *);
int gpc_nr;
@@ -197,7 +201,7 @@ struct gf100_gr_func {
int gf100_gr_rops(struct gf100_gr *);
void gf100_gr_oneinit_tiles(struct gf100_gr *);
-void gf100_gr_oneinit_sm_id(struct gf100_gr *);
+int gf100_gr_oneinit_sm_id(struct gf100_gr *);
int gf100_gr_init(struct gf100_gr *);
void gf100_gr_init_vsc_stream_master(struct gf100_gr *);
void gf100_gr_init_zcull(struct gf100_gr *);
@@ -208,9 +212,12 @@ void gf100_gr_init_419cc0(struct gf100_gr *);
void gf100_gr_init_419eb4(struct gf100_gr *);
void gf100_gr_init_tex_hww_esr(struct gf100_gr *, int, int);
void gf100_gr_init_shader_exceptions(struct gf100_gr *, int, int);
+void gf100_gr_init_rop_exceptions(struct gf100_gr *);
+void gf100_gr_init_exception2(struct gf100_gr *);
void gf100_gr_init_400054(struct gf100_gr *);
void gf100_gr_init_num_tpc_per_gpc(struct gf100_gr *, bool, bool);
extern const struct gf100_gr_func_zbc gf100_gr_zbc;
+void gf100_gr_fecs_reset(struct gf100_gr *);
void gf117_gr_init_zcull(struct gf100_gr *);
@@ -226,9 +233,13 @@ void gm107_gr_init_shader_exceptions(struct gf100_gr *, int, int);
void gm107_gr_init_400054(struct gf100_gr *);
int gk20a_gr_init(struct gf100_gr *);
+int gk20a_gr_av_to_init_(struct nvkm_blob *, u8 count, u32 pitch, struct gf100_gr_pack **);
+int gk20a_gr_av_to_init(struct nvkm_blob *, struct gf100_gr_pack **);
+int gk20a_gr_aiv_to_init(struct nvkm_blob *, struct gf100_gr_pack **);
+int gk20a_gr_av_to_method(struct nvkm_blob *, struct gf100_gr_pack **);
void gm200_gr_oneinit_tiles(struct gf100_gr *);
-void gm200_gr_oneinit_sm_id(struct gf100_gr *);
+int gm200_gr_oneinit_sm_id(struct gf100_gr *);
int gm200_gr_rops(struct gf100_gr *);
void gm200_gr_init_num_active_ltcs(struct gf100_gr *);
void gm200_gr_init_ds_hww_esr_2(struct gf100_gr *);
@@ -242,14 +253,24 @@ extern const struct gf100_gr_func_zbc gp100_gr_zbc;
void gp102_gr_init_swdx_pes_mask(struct gf100_gr *);
extern const struct gf100_gr_func_zbc gp102_gr_zbc;
+int gp102_gr_zbc_stencil_get(struct gf100_gr *, int, const u32, const u32);
+void gp102_gr_zbc_clear_stencil(struct gf100_gr *, int);
extern const struct gf100_gr_func gp107_gr;
+int gv100_gr_oneinit_sm_id(struct gf100_gr *);
+u32 gv100_gr_nonpes_aware_tpc(struct gf100_gr *gr, u32 gpc, u32 tpc);
void gv100_gr_init_419bd8(struct gf100_gr *);
void gv100_gr_init_504430(struct gf100_gr *, int, int);
void gv100_gr_init_shader_exceptions(struct gf100_gr *, int, int);
+void gv100_gr_init_4188a4(struct gf100_gr *);
void gv100_gr_trap_mp(struct gf100_gr *, int, int);
+int tu102_gr_av_to_init_veid(struct nvkm_blob *, struct gf100_gr_pack **);
+void tu102_gr_init_zcull(struct gf100_gr *);
+void tu102_gr_init_fs(struct gf100_gr *);
+void tu102_gr_init_fecs_exceptions(struct gf100_gr *);
+
#define gf100_gr_chan(p) container_of((p), struct gf100_gr_chan, object)
#include <core/object.h>
@@ -258,14 +279,14 @@ struct gf100_gr_chan {
struct gf100_gr *gr;
struct nvkm_vmm *vmm;
+ struct nvkm_vma *pagepool;
+ struct nvkm_vma *bundle_cb;
+ struct nvkm_vma *attrib_cb;
+ struct nvkm_vma *unknown;
+
struct nvkm_memory *mmio;
struct nvkm_vma *mmio_vma;
int mmio_nr;
-
- struct {
- struct nvkm_memory *mem;
- struct nvkm_vma *vma;
- } data[4];
};
void gf100_gr_ctxctl_debug(struct gf100_gr *);
@@ -279,7 +300,7 @@ struct gf100_gr_init {
u32 addr;
u8 count;
u32 pitch;
- u32 data;
+ u64 data;
};
struct gf100_gr_pack {
@@ -403,6 +424,9 @@ int gf100_gr_load(struct gf100_gr *, int, const struct gf100_gr_fwif *);
int gf100_gr_nofw(struct gf100_gr *, int, const struct gf100_gr_fwif *);
int gk20a_gr_load_sw(struct gf100_gr *, const char *path, int ver);
+int gk20a_gr_load_net(struct gf100_gr *, const char *, const char *, int,
+ int (*)(struct nvkm_blob *, struct gf100_gr_pack **),
+ struct gf100_gr_pack **);
int gm200_gr_nofw(struct gf100_gr *, int, const struct gf100_gr_fwif *);
int gm200_gr_load(struct gf100_gr *, int, const struct gf100_gr_fwif *);
@@ -415,6 +439,8 @@ void gm20b_gr_acr_bld_patch(struct nvkm_acr *, u32, s64);
extern const struct nvkm_acr_lsf_func gp108_gr_gpccs_acr;
extern const struct nvkm_acr_lsf_func gp108_gr_fecs_acr;
+void gp108_gr_acr_bld_write(struct nvkm_acr *, u32, struct nvkm_acr_lsfw *);
+void gp108_gr_acr_bld_patch(struct nvkm_acr *, u32, s64);
int gf100_gr_new_(const struct gf100_gr_fwif *, struct nvkm_device *, enum nvkm_subdev_type, int,
struct nvkm_gr **);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c
index 3acd99c306f2..63bd29c22fe1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c
@@ -127,10 +127,13 @@ gf104_gr = {
.init_419eb4 = gf100_gr_init_419eb4,
.init_tex_hww_esr = gf100_gr_init_tex_hww_esr,
.init_shader_exceptions = gf100_gr_init_shader_exceptions,
+ .init_rop_exceptions = gf100_gr_init_rop_exceptions,
+ .init_exception2 = gf100_gr_init_exception2,
.init_400054 = gf100_gr_init_400054,
.trap_mp = gf100_gr_trap_mp,
.mmio = gf104_gr_pack_mmio,
.fecs.ucode = &gf100_gr_fecs_ucode,
+ .fecs.reset = gf100_gr_fecs_reset,
.gpccs.ucode = &gf100_gr_gpccs_ucode,
.rops = gf100_gr_rops,
.grctx = &gf104_grctx,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c
index ab3760e804b8..495a844f925f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c
@@ -125,10 +125,13 @@ gf108_gr = {
.init_419eb4 = gf100_gr_init_419eb4,
.init_tex_hww_esr = gf100_gr_init_tex_hww_esr,
.init_shader_exceptions = gf100_gr_init_shader_exceptions,
+ .init_rop_exceptions = gf100_gr_init_rop_exceptions,
+ .init_exception2 = gf100_gr_init_exception2,
.init_400054 = gf100_gr_init_400054,
.trap_mp = gf100_gr_trap_mp,
.mmio = gf108_gr_pack_mmio,
.fecs.ucode = &gf100_gr_fecs_ucode,
+ .fecs.reset = gf100_gr_fecs_reset,
.gpccs.ucode = &gf100_gr_gpccs_ucode,
.rops = gf100_gr_rops,
.grctx = &gf108_grctx,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c
index 616e2def1865..70fad235d161 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c
@@ -99,10 +99,13 @@ gf110_gr = {
.init_419eb4 = gf100_gr_init_419eb4,
.init_tex_hww_esr = gf100_gr_init_tex_hww_esr,
.init_shader_exceptions = gf100_gr_init_shader_exceptions,
+ .init_rop_exceptions = gf100_gr_init_rop_exceptions,
+ .init_exception2 = gf100_gr_init_exception2,
.init_400054 = gf100_gr_init_400054,
.trap_mp = gf100_gr_trap_mp,
.mmio = gf110_gr_pack_mmio,
.fecs.ucode = &gf100_gr_fecs_ucode,
+ .fecs.reset = gf100_gr_fecs_reset,
.gpccs.ucode = &gf100_gr_gpccs_ucode,
.rops = gf100_gr_rops,
.grctx = &gf110_grctx,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c
index 669e7536970e..f12728248048 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c
@@ -125,7 +125,9 @@ gf117_gr_init_zcull(struct gf100_gr *gr)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total);
- const u8 tile_nr = ALIGN(gr->tpc_total, 32);
+ /*TODO: fill in litter vals for gf117-gm2xx */
+ const u8 tile_nr = !gr->func->gpc_nr ? ALIGN(gr->tpc_total, 32) :
+ (gr->func->gpc_nr * gr->func->tpc_nr);
u8 bank[GPC_MAX] = {}, gpc, i, j;
u32 data;
@@ -163,10 +165,13 @@ gf117_gr = {
.init_419eb4 = gf100_gr_init_419eb4,
.init_tex_hww_esr = gf100_gr_init_tex_hww_esr,
.init_shader_exceptions = gf100_gr_init_shader_exceptions,
+ .init_rop_exceptions = gf100_gr_init_rop_exceptions,
+ .init_exception2 = gf100_gr_init_exception2,
.init_400054 = gf100_gr_init_400054,
.trap_mp = gf100_gr_trap_mp,
.mmio = gf117_gr_pack_mmio,
.fecs.ucode = &gf117_gr_fecs_ucode,
+ .fecs.reset = gf100_gr_fecs_reset,
.gpccs.ucode = &gf117_gr_gpccs_ucode,
.rops = gf100_gr_rops,
.ppc_nr = 1,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c
index 5b09bda8110c..75ceb514c06e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c
@@ -190,10 +190,13 @@ gf119_gr = {
.init_419eb4 = gf100_gr_init_419eb4,
.init_tex_hww_esr = gf100_gr_init_tex_hww_esr,
.init_shader_exceptions = gf100_gr_init_shader_exceptions,
+ .init_rop_exceptions = gf100_gr_init_rop_exceptions,
+ .init_exception2 = gf100_gr_init_exception2,
.init_400054 = gf100_gr_init_400054,
.trap_mp = gf100_gr_trap_mp,
.mmio = gf119_gr_pack_mmio,
.fecs.ucode = &gf100_gr_fecs_ucode,
+ .fecs.reset = gf100_gr_fecs_reset,
.gpccs.ucode = &gf100_gr_gpccs_ucode,
.rops = gf100_gr_rops,
.grctx = &gf119_grctx,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c
index b680eaa0f350..e53ade24ad23 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c
@@ -418,7 +418,7 @@ gk104_gr_init_ppc_exceptions(struct gf100_gr *gr)
int gpc, ppc;
for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
- for (ppc = 0; ppc < gr->ppc_nr[gpc]; ppc++) {
+ for (ppc = 0; ppc < gr->func->ppc_nr; ppc++) {
if (!(gr->ppc_mask[gpc] & (1 << ppc)))
continue;
nvkm_wr32(device, PPC_UNIT(gpc, ppc, 0x038), 0xc0000000);
@@ -470,10 +470,13 @@ gk104_gr = {
.init_ppc_exceptions = gk104_gr_init_ppc_exceptions,
.init_tex_hww_esr = gf100_gr_init_tex_hww_esr,
.init_shader_exceptions = gf100_gr_init_shader_exceptions,
+ .init_rop_exceptions = gf100_gr_init_rop_exceptions,
+ .init_exception2 = gf100_gr_init_exception2,
.init_400054 = gf100_gr_init_400054,
.trap_mp = gf100_gr_trap_mp,
.mmio = gk104_gr_pack_mmio,
.fecs.ucode = &gk104_gr_fecs_ucode,
+ .fecs.reset = gf100_gr_fecs_reset,
.gpccs.ucode = &gk104_gr_gpccs_ucode,
.rops = gf100_gr_rops,
.ppc_nr = 1,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c
index 103e06a77e65..c7e1c5dbc6a9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c
@@ -366,10 +366,13 @@ gk110_gr = {
.init_ppc_exceptions = gk104_gr_init_ppc_exceptions,
.init_tex_hww_esr = gf100_gr_init_tex_hww_esr,
.init_shader_exceptions = gf100_gr_init_shader_exceptions,
+ .init_rop_exceptions = gf100_gr_init_rop_exceptions,
+ .init_exception2 = gf100_gr_init_exception2,
.init_400054 = gf100_gr_init_400054,
.trap_mp = gf100_gr_trap_mp,
.mmio = gk110_gr_pack_mmio,
.fecs.ucode = &gk110_gr_fecs_ucode,
+ .fecs.reset = gf100_gr_fecs_reset,
.gpccs.ucode = &gk110_gr_gpccs_ucode,
.rops = gf100_gr_rops,
.ppc_nr = 2,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c
index 034d0b11a17d..458abae571bf 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c
@@ -118,10 +118,13 @@ gk110b_gr = {
.init_ppc_exceptions = gk104_gr_init_ppc_exceptions,
.init_tex_hww_esr = gf100_gr_init_tex_hww_esr,
.init_shader_exceptions = gf100_gr_init_shader_exceptions,
+ .init_rop_exceptions = gf100_gr_init_rop_exceptions,
+ .init_exception2 = gf100_gr_init_exception2,
.init_400054 = gf100_gr_init_400054,
.trap_mp = gf100_gr_trap_mp,
.mmio = gk110b_gr_pack_mmio,
.fecs.ucode = &gk110_gr_fecs_ucode,
+ .fecs.reset = gf100_gr_fecs_reset,
.gpccs.ucode = &gk110_gr_gpccs_ucode,
.rops = gf100_gr_rops,
.ppc_nr = 2,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c
index 116d682f9f96..d3f6b65c21d2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c
@@ -176,10 +176,13 @@ gk208_gr = {
.init_ppc_exceptions = gk104_gr_init_ppc_exceptions,
.init_tex_hww_esr = gf100_gr_init_tex_hww_esr,
.init_shader_exceptions = gf100_gr_init_shader_exceptions,
+ .init_rop_exceptions = gf100_gr_init_rop_exceptions,
+ .init_exception2 = gf100_gr_init_exception2,
.init_400054 = gf100_gr_init_400054,
.trap_mp = gf100_gr_trap_mp,
.mmio = gk208_gr_pack_mmio,
.fecs.ucode = &gk208_gr_fecs_ucode,
+ .fecs.reset = gf100_gr_fecs_reset,
.gpccs.ucode = &gk208_gr_gpccs_ucode,
.rops = gf100_gr_rops,
.ppc_nr = 1,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c
index be0b2cefd8e8..035ea213f543 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk20a.c
@@ -33,47 +33,40 @@ struct gk20a_fw_av
u32 data;
};
-static int
-gk20a_gr_av_to_init(struct gf100_gr *gr, const char *path, const char *name,
- int ver, struct gf100_gr_pack **ppack)
+int
+gk20a_gr_av_to_init_(struct nvkm_blob *blob, u8 count, u32 pitch, struct gf100_gr_pack **ppack)
{
- struct nvkm_subdev *subdev = &gr->base.engine.subdev;
- struct nvkm_blob blob;
struct gf100_gr_init *init;
struct gf100_gr_pack *pack;
int nent;
- int ret;
int i;
- ret = nvkm_firmware_load_blob(subdev, path, name, ver, &blob);
- if (ret)
- return ret;
-
- nent = (blob.size / sizeof(struct gk20a_fw_av));
+ nent = (blob->size / sizeof(struct gk20a_fw_av));
pack = vzalloc((sizeof(*pack) * 2) + (sizeof(*init) * (nent + 1)));
- if (!pack) {
- ret = -ENOMEM;
- goto end;
- }
+ if (!pack)
+ return -ENOMEM;
init = (void *)(pack + 2);
pack[0].init = init;
for (i = 0; i < nent; i++) {
struct gf100_gr_init *ent = &init[i];
- struct gk20a_fw_av *av = &((struct gk20a_fw_av *)blob.data)[i];
+ struct gk20a_fw_av *av = &((struct gk20a_fw_av *)blob->data)[i];
ent->addr = av->addr;
ent->data = av->data;
- ent->count = 1;
- ent->pitch = 1;
+ ent->count = ((ent->addr & 0xffff) != 0xe100) ? count : 1;
+ ent->pitch = pitch;
}
*ppack = pack;
+ return 0;
+}
-end:
- nvkm_blob_dtor(&blob);
- return ret;
+int
+gk20a_gr_av_to_init(struct nvkm_blob *blob, struct gf100_gr_pack **ppack)
+{
+ return gk20a_gr_av_to_init_(blob, 1, 1, ppack);
}
struct gk20a_fw_aiv
@@ -83,35 +76,25 @@ struct gk20a_fw_aiv
u32 data;
};
-static int
-gk20a_gr_aiv_to_init(struct gf100_gr *gr, const char *path, const char *name,
- int ver, struct gf100_gr_pack **ppack)
+int
+gk20a_gr_aiv_to_init(struct nvkm_blob *blob, struct gf100_gr_pack **ppack)
{
- struct nvkm_subdev *subdev = &gr->base.engine.subdev;
- struct nvkm_blob blob;
struct gf100_gr_init *init;
struct gf100_gr_pack *pack;
int nent;
- int ret;
int i;
- ret = nvkm_firmware_load_blob(subdev, path, name, ver, &blob);
- if (ret)
- return ret;
-
- nent = (blob.size / sizeof(struct gk20a_fw_aiv));
+ nent = (blob->size / sizeof(struct gk20a_fw_aiv));
pack = vzalloc((sizeof(*pack) * 2) + (sizeof(*init) * (nent + 1)));
- if (!pack) {
- ret = -ENOMEM;
- goto end;
- }
+ if (!pack)
+ return -ENOMEM;
init = (void *)(pack + 2);
pack[0].init = init;
for (i = 0; i < nent; i++) {
struct gf100_gr_init *ent = &init[i];
- struct gk20a_fw_aiv *av = &((struct gk20a_fw_aiv *)blob.data)[i];
+ struct gk20a_fw_aiv *av = &((struct gk20a_fw_aiv *)blob->data)[i];
ent->addr = av->addr;
ent->data = av->data;
@@ -120,44 +103,30 @@ gk20a_gr_aiv_to_init(struct gf100_gr *gr, const char *path, const char *name,
}
*ppack = pack;
-
-end:
- nvkm_blob_dtor(&blob);
- return ret;
+ return 0;
}
-static int
-gk20a_gr_av_to_method(struct gf100_gr *gr, const char *path, const char *name,
- int ver, struct gf100_gr_pack **ppack)
+int
+gk20a_gr_av_to_method(struct nvkm_blob *blob, struct gf100_gr_pack **ppack)
{
- struct nvkm_subdev *subdev = &gr->base.engine.subdev;
- struct nvkm_blob blob;
struct gf100_gr_init *init;
struct gf100_gr_pack *pack;
/* We don't suppose we will initialize more than 16 classes here... */
static const unsigned int max_classes = 16;
u32 classidx = 0, prevclass = 0;
int nent;
- int ret;
int i;
- ret = nvkm_firmware_load_blob(subdev, path, name, ver, &blob);
- if (ret)
- return ret;
-
- nent = (blob.size / sizeof(struct gk20a_fw_av));
-
+ nent = (blob->size / sizeof(struct gk20a_fw_av));
pack = vzalloc((sizeof(*pack) * (max_classes + 1)) +
(sizeof(*init) * (nent + max_classes + 1)));
- if (!pack) {
- ret = -ENOMEM;
- goto end;
- }
+ if (!pack)
+ return -ENOMEM;
init = (void *)(pack + max_classes + 1);
for (i = 0; i < nent; i++, init++) {
- struct gk20a_fw_av *av = &((struct gk20a_fw_av *)blob.data)[i];
+ struct gk20a_fw_av *av = &((struct gk20a_fw_av *)blob->data)[i];
u32 class = av->addr & 0xffff;
u32 addr = (av->addr & 0xffff0000) >> 14;
@@ -169,8 +138,7 @@ gk20a_gr_av_to_method(struct gf100_gr *gr, const char *path, const char *name,
prevclass = class;
if (++classidx >= max_classes) {
vfree(pack);
- ret = -ENOSPC;
- goto end;
+ return -ENOSPC;
}
}
@@ -181,10 +149,7 @@ gk20a_gr_av_to_method(struct gf100_gr *gr, const char *path, const char *name,
}
*ppack = pack;
-
-end:
- nvkm_blob_dtor(&blob);
- return ret;
+ return 0;
}
static int
@@ -294,6 +259,7 @@ gk20a_gr = {
.init_rop_active_fbps = gk104_gr_init_rop_active_fbps,
.trap_mp = gf100_gr_trap_mp,
.set_hww_esr_report_mask = gk20a_gr_set_hww_esr_report_mask,
+ .fecs.reset = gf100_gr_fecs_reset,
.rops = gf100_gr_rops,
.ppc_nr = 1,
.grctx = &gk20a_grctx,
@@ -308,12 +274,29 @@ gk20a_gr = {
};
int
+gk20a_gr_load_net(struct gf100_gr *gr, const char *path, const char *name, int ver,
+ int (*load)(struct nvkm_blob *, struct gf100_gr_pack **),
+ struct gf100_gr_pack **ppack)
+{
+ struct nvkm_blob blob;
+ int ret;
+
+ ret = nvkm_firmware_load_blob(&gr->base.engine.subdev, path, name, ver, &blob);
+ if (ret)
+ return ret;
+
+ ret = load(&blob, ppack);
+ nvkm_blob_dtor(&blob);
+ return 0;
+}
+
+int
gk20a_gr_load_sw(struct gf100_gr *gr, const char *path, int ver)
{
- if (gk20a_gr_av_to_init(gr, path, "sw_nonctx", ver, &gr->sw_nonctx) ||
- gk20a_gr_aiv_to_init(gr, path, "sw_ctx", ver, &gr->sw_ctx) ||
- gk20a_gr_av_to_init(gr, path, "sw_bundle_init", ver, &gr->bundle) ||
- gk20a_gr_av_to_method(gr, path, "sw_method_init", ver, &gr->method))
+ if (gk20a_gr_load_net(gr, path, "sw_nonctx", ver, gk20a_gr_av_to_init, &gr->sw_nonctx) ||
+ gk20a_gr_load_net(gr, path, "sw_ctx", ver, gk20a_gr_aiv_to_init, &gr->sw_ctx) ||
+ gk20a_gr_load_net(gr, path, "sw_bundle_init", ver, gk20a_gr_av_to_init, &gr->bundle) ||
+ gk20a_gr_load_net(gr, path, "sw_method_init", ver, gk20a_gr_av_to_method, &gr->method))
return -ENOENT;
return 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c
index 310987174cb5..797b828a943b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm107.c
@@ -411,10 +411,13 @@ gm107_gr = {
.init_tex_hww_esr = gf100_gr_init_tex_hww_esr,
.init_504430 = gm107_gr_init_504430,
.init_shader_exceptions = gm107_gr_init_shader_exceptions,
+ .init_rop_exceptions = gf100_gr_init_rop_exceptions,
+ .init_exception2 = gf100_gr_init_exception2,
.init_400054 = gm107_gr_init_400054,
.trap_mp = gf100_gr_trap_mp,
.mmio = gm107_gr_pack_mmio,
.fecs.ucode = &gm107_gr_fecs_ucode,
+ .fecs.reset = gf100_gr_fecs_reset,
.gpccs.ucode = &gm107_gr_gpccs_ucode,
.rops = gf100_gr_rops,
.ppc_nr = 2,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c
index 385cfd91b266..b5210b31c1b2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm200.c
@@ -148,11 +148,11 @@ gm200_gr_tile_map_2_8[] = {
0, 1, 1, 0, 0, 1, 1, 0,
};
-void
+int
gm200_gr_oneinit_sm_id(struct gf100_gr *gr)
{
/*XXX: There's a different algorithm here I've not yet figured out. */
- gf100_gr_oneinit_sm_id(gr);
+ return gf100_gr_oneinit_sm_id(gr);
}
void
@@ -199,8 +199,11 @@ gm200_gr = {
.init_tex_hww_esr = gf100_gr_init_tex_hww_esr,
.init_504430 = gm107_gr_init_504430,
.init_shader_exceptions = gm107_gr_init_shader_exceptions,
+ .init_rop_exceptions = gf100_gr_init_rop_exceptions,
+ .init_exception2 = gf100_gr_init_exception2,
.init_400054 = gm107_gr_init_400054,
.trap_mp = gf100_gr_trap_mp,
+ .fecs.reset = gf100_gr_fecs_reset,
.rops = gm200_gr_rops,
.tpc_nr = 4,
.ppc_nr = 2,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c
index ec1c46e47e00..458cd1a00d3f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gm20b.c
@@ -123,6 +123,7 @@ gm20b_gr = {
.init_rop_active_fbps = gk104_gr_init_rop_active_fbps,
.trap_mp = gf100_gr_trap_mp,
.set_hww_esr_report_mask = gm20b_gr_set_hww_esr_report_mask,
+ .fecs.reset = gf100_gr_fecs_reset,
.rops = gm200_gr_rops,
.ppc_nr = 1,
.grctx = &gm20b_grctx,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c
index 0550dd6f46f1..851e743d2cab 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp100.c
@@ -87,7 +87,7 @@ gp100_gr_init_419c9c(struct gf100_gr *gr)
void
gp100_gr_init_fecs_exceptions(struct gf100_gr *gr)
{
- nvkm_wr32(gr->base.engine.subdev.device, 0x409c24, 0x000f0002);
+ nvkm_wr32(gr->base.engine.subdev.device, 0x409c24, 0x000e0002);
}
void
@@ -119,7 +119,10 @@ gp100_gr = {
.init_tex_hww_esr = gf100_gr_init_tex_hww_esr,
.init_504430 = gm107_gr_init_504430,
.init_shader_exceptions = gp100_gr_init_shader_exceptions,
+ .init_rop_exceptions = gf100_gr_init_rop_exceptions,
+ .init_exception2 = gf100_gr_init_exception2,
.trap_mp = gf100_gr_trap_mp,
+ .fecs.reset = gf100_gr_fecs_reset,
.rops = gm200_gr_rops,
.gpc_nr = 6,
.tpc_nr = 5,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c
index 5b001f374be0..0e223b7b5f0e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp102.c
@@ -26,7 +26,7 @@
#include <nvif/class.h>
-static void
+void
gp102_gr_zbc_clear_stencil(struct gf100_gr *gr, int zbc)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
@@ -40,14 +40,14 @@ gp102_gr_zbc_clear_stencil(struct gf100_gr *gr, int zbc)
gr->zbc_stencil[zbc].format << ((znum % 4) * 7));
}
-static int
+int
gp102_gr_zbc_stencil_get(struct gf100_gr *gr, int format,
const u32 ds, const u32 l2)
{
struct nvkm_ltc *ltc = gr->base.engine.subdev.device->ltc;
int zbc = -ENOSPC, i;
- for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) {
+ for (i = ltc->zbc_depth_min; i <= ltc->zbc_depth_max; i++) {
if (gr->zbc_stencil[i].format) {
if (gr->zbc_stencil[i].format != format)
continue;
@@ -115,7 +115,10 @@ gp102_gr = {
.init_tex_hww_esr = gf100_gr_init_tex_hww_esr,
.init_504430 = gm107_gr_init_504430,
.init_shader_exceptions = gp100_gr_init_shader_exceptions,
+ .init_rop_exceptions = gf100_gr_init_rop_exceptions,
+ .init_exception2 = gf100_gr_init_exception2,
.trap_mp = gf100_gr_trap_mp,
+ .fecs.reset = gf100_gr_fecs_reset,
.rops = gm200_gr_rops,
.gpc_nr = 6,
.tpc_nr = 5,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c
index 2655574ec63b..6802cb9b199f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp104.c
@@ -43,7 +43,10 @@ gp104_gr = {
.init_tex_hww_esr = gf100_gr_init_tex_hww_esr,
.init_504430 = gm107_gr_init_504430,
.init_shader_exceptions = gp100_gr_init_shader_exceptions,
+ .init_rop_exceptions = gf100_gr_init_rop_exceptions,
+ .init_exception2 = gf100_gr_init_exception2,
.trap_mp = gf100_gr_trap_mp,
+ .fecs.reset = gf100_gr_fecs_reset,
.rops = gm200_gr_rops,
.gpc_nr = 6,
.tpc_nr = 5,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c
index adabc04d4f3a..cc2bb0d0a987 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp107.c
@@ -45,7 +45,10 @@ gp107_gr = {
.init_tex_hww_esr = gf100_gr_init_tex_hww_esr,
.init_504430 = gm107_gr_init_504430,
.init_shader_exceptions = gp100_gr_init_shader_exceptions,
+ .init_rop_exceptions = gf100_gr_init_rop_exceptions,
+ .init_exception2 = gf100_gr_init_exception2,
.trap_mp = gf100_gr_trap_mp,
+ .fecs.reset = gf100_gr_fecs_reset,
.rops = gm200_gr_rops,
.gpc_nr = 2,
.tpc_nr = 3,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c
index 7310f0466bb7..311f703439e4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp108.c
@@ -25,7 +25,7 @@
#include <nvfw/flcn.h>
-static void
+void
gp108_gr_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust)
{
struct flcn_bl_dmem_desc_v2 hdr;
@@ -36,7 +36,7 @@ gp108_gr_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust)
flcn_bl_dmem_desc_v2_dump(&acr->subdev, &hdr);
}
-static void
+void
gp108_gr_acr_bld_write(struct nvkm_acr *acr, u32 bld,
struct nvkm_acr_lsfw *lsfw)
{
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c
index e13683b6e7b1..5008881ca079 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gp10b.c
@@ -55,7 +55,10 @@ gp10b_gr = {
.init_tex_hww_esr = gf100_gr_init_tex_hww_esr,
.init_504430 = gm107_gr_init_504430,
.init_shader_exceptions = gp100_gr_init_shader_exceptions,
+ .init_rop_exceptions = gf100_gr_init_rop_exceptions,
+ .init_exception2 = gf100_gr_init_exception2,
.trap_mp = gf100_gr_trap_mp,
+ .fecs.reset = gf100_gr_fecs_reset,
.rops = gm200_gr_rops,
.gpc_nr = 1,
.tpc_nr = 2,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c
index 4d043c1173ea..7f7404a76140 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gv100.c
@@ -52,10 +52,11 @@ gv100_gr_trap_mp(struct gf100_gr *gr, int gpc, int tpc)
gv100_gr_trap_sm(gr, gpc, tpc, 1);
}
-static void
+void
gv100_gr_init_4188a4(struct gf100_gr *gr)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
+
nvkm_mask(device, 0x4188a4, 0x03000000, 0x03000000);
}
@@ -65,7 +66,6 @@ gv100_gr_init_shader_exceptions(struct gf100_gr *gr, int gpc, int tpc)
struct nvkm_device *device = gr->base.engine.subdev.device;
int sm;
for (sm = 0; sm < 0x100; sm += 0x80) {
- nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x728 + sm), 0x0085eb64);
nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x610), 0x00000001);
nvkm_wr32(device, TPC_UNIT(gpc, tpc, 0x72c + sm), 0x00000004);
}
@@ -85,10 +85,202 @@ gv100_gr_init_419bd8(struct gf100_gr *gr)
nvkm_mask(device, 0x419bd8, 0x00000700, 0x00000000);
}
+u32
+gv100_gr_nonpes_aware_tpc(struct gf100_gr *gr, u32 gpc, u32 tpc)
+{
+ u32 pes, temp, tpc_new = 0;
+
+ for (pes = 0; pes < gr->ppc_nr[gpc]; pes++) {
+ if (gr->ppc_tpc_mask[gpc][pes] & BIT(tpc))
+ break;
+
+ tpc_new += gr->ppc_tpc_nr[gpc][pes];
+ }
+
+ temp = (BIT(tpc) - 1) & gr->ppc_tpc_mask[gpc][pes];
+ temp = hweight32(temp);
+ return tpc_new + temp;
+}
+
+static int
+gv100_gr_scg_estimate_perf(struct gf100_gr *gr, unsigned long *gpc_tpc_mask,
+ u32 disable_gpc, u32 disable_tpc, int *perf)
+{
+ const u32 scale_factor = 512UL; /* Use fx23.9 */
+ const u32 pix_scale = 1024*1024UL; /* Pix perf in [29:20] */
+ const u32 world_scale = 1024UL; /* World performance in [19:10] */
+ const u32 tpc_scale = 1; /* TPC balancing in [9:0] */
+ u32 scg_num_pes = 0;
+ u32 min_scg_gpc_pix_perf = scale_factor; /* Init perf as maximum */
+ u32 average_tpcs = 0; /* Average of # of TPCs per GPC */
+ u32 deviation; /* absolute diff between TPC# and average_tpcs, averaged across GPCs */
+ u32 norm_tpc_deviation; /* deviation/max_tpc_per_gpc */
+ u32 tpc_balance;
+ u32 scg_gpc_pix_perf;
+ u32 scg_world_perf;
+ u32 gpc;
+ u32 pes;
+ int diff;
+ bool tpc_removed_gpc = false;
+ bool tpc_removed_pes = false;
+ u32 max_tpc_gpc = 0;
+ u32 num_tpc_mask;
+ u32 *num_tpc_gpc;
+ int ret = -EINVAL;
+
+ if (!(num_tpc_gpc = kcalloc(gr->gpc_nr, sizeof(*num_tpc_gpc), GFP_KERNEL)))
+ return -ENOMEM;
+
+ /* Calculate pix-perf-reduction-rate per GPC and find bottleneck TPC */
+ for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
+ num_tpc_mask = gpc_tpc_mask[gpc];
+
+ if ((gpc == disable_gpc) && num_tpc_mask & BIT(disable_tpc)) {
+ /* Safety check if a TPC is removed twice */
+ if (WARN_ON(tpc_removed_gpc))
+ goto done;
+
+ /* Remove logical TPC from set */
+ num_tpc_mask &= ~BIT(disable_tpc);
+ tpc_removed_gpc = true;
+ }
+
+ /* track balancing of tpcs across gpcs */
+ num_tpc_gpc[gpc] = hweight32(num_tpc_mask);
+ average_tpcs += num_tpc_gpc[gpc];
+
+ /* save the maximum numer of gpcs */
+ max_tpc_gpc = num_tpc_gpc[gpc] > max_tpc_gpc ? num_tpc_gpc[gpc] : max_tpc_gpc;
+
+ /*
+ * Calculate ratio between TPC count and post-FS and post-SCG
+ *
+ * ratio represents relative throughput of the GPC
+ */
+ scg_gpc_pix_perf = scale_factor * num_tpc_gpc[gpc] / gr->tpc_nr[gpc];
+ if (min_scg_gpc_pix_perf > scg_gpc_pix_perf)
+ min_scg_gpc_pix_perf = scg_gpc_pix_perf;
+
+ /* Calculate # of surviving PES */
+ for (pes = 0; pes < gr->ppc_nr[gpc]; pes++) {
+ /* Count the number of TPC on the set */
+ num_tpc_mask = gr->ppc_tpc_mask[gpc][pes] & gpc_tpc_mask[gpc];
+
+ if ((gpc == disable_gpc) && (num_tpc_mask & BIT(disable_tpc))) {
+ if (WARN_ON(tpc_removed_pes))
+ goto done;
+
+ num_tpc_mask &= ~BIT(disable_tpc);
+ tpc_removed_pes = true;
+ }
+
+ if (hweight32(num_tpc_mask))
+ scg_num_pes++;
+ }
+ }
+
+ if (WARN_ON(!tpc_removed_gpc || !tpc_removed_pes))
+ goto done;
+
+ if (max_tpc_gpc == 0) {
+ *perf = 0;
+ goto done_ok;
+ }
+
+ /* Now calculate perf */
+ scg_world_perf = (scale_factor * scg_num_pes) / gr->ppc_total;
+ deviation = 0;
+ average_tpcs = scale_factor * average_tpcs / gr->gpc_nr;
+ for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
+ diff = average_tpcs - scale_factor * num_tpc_gpc[gpc];
+ if (diff < 0)
+ diff = -diff;
+
+ deviation += diff;
+ }
+
+ deviation /= gr->gpc_nr;
+
+ norm_tpc_deviation = deviation / max_tpc_gpc;
+
+ tpc_balance = scale_factor - norm_tpc_deviation;
+
+ if ((tpc_balance > scale_factor) ||
+ (scg_world_perf > scale_factor) ||
+ (min_scg_gpc_pix_perf > scale_factor) ||
+ (norm_tpc_deviation > scale_factor)) {
+ WARN_ON(1);
+ goto done;
+ }
+
+ *perf = (pix_scale * min_scg_gpc_pix_perf) +
+ (world_scale * scg_world_perf) +
+ (tpc_scale * tpc_balance);
+done_ok:
+ ret = 0;
+done:
+ kfree(num_tpc_gpc);
+ return ret;
+}
+
+int
+gv100_gr_oneinit_sm_id(struct gf100_gr *gr)
+{
+ unsigned long *gpc_tpc_mask;
+ u32 *tpc_table, *gpc_table;
+ u32 gpc, tpc, pes, gtpc;
+ int perf, maxperf, ret = 0;
+
+ gpc_tpc_mask = kcalloc(gr->gpc_nr, sizeof(*gpc_tpc_mask), GFP_KERNEL);
+ gpc_table = kcalloc(gr->tpc_total, sizeof(*gpc_table), GFP_KERNEL);
+ tpc_table = kcalloc(gr->tpc_total, sizeof(*tpc_table), GFP_KERNEL);
+ if (!gpc_table || !tpc_table || !gpc_tpc_mask) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ for (gpc = 0; gpc < gr->gpc_nr; gpc++) {
+ for (pes = 0; pes < gr->ppc_nr[gpc]; pes++)
+ gpc_tpc_mask[gpc] |= gr->ppc_tpc_mask[gpc][pes];
+ }
+
+ for (gtpc = 0; gtpc < gr->tpc_total; gtpc++) {
+ for (maxperf = -1, gpc = 0; gpc < gr->gpc_nr; gpc++) {
+ for_each_set_bit(tpc, &gpc_tpc_mask[gpc], gr->tpc_nr[gpc]) {
+ ret = gv100_gr_scg_estimate_perf(gr, gpc_tpc_mask, gpc, tpc, &perf);
+ if (ret)
+ goto done;
+
+ /* nvgpu does ">=" here, but this gets us RM's numbers. */
+ if (perf > maxperf) {
+ maxperf = perf;
+ gpc_table[gtpc] = gpc;
+ tpc_table[gtpc] = tpc;
+ }
+ }
+ }
+
+ gpc_tpc_mask[gpc_table[gtpc]] &= ~BIT(tpc_table[gtpc]);
+ }
+
+ /*TODO: build table for sm_per_tpc != 1, don't use yet, but might need later? */
+ for (gtpc = 0; gtpc < gr->tpc_total; gtpc++) {
+ gr->sm[gtpc].gpc = gpc_table[gtpc];
+ gr->sm[gtpc].tpc = tpc_table[gtpc];
+ gr->sm_nr++;
+ }
+
+done:
+ kfree(gpc_table);
+ kfree(tpc_table);
+ kfree(gpc_tpc_mask);
+ return ret;
+}
+
static const struct gf100_gr_func
gv100_gr = {
.oneinit_tiles = gm200_gr_oneinit_tiles,
- .oneinit_sm_id = gm200_gr_oneinit_sm_id,
+ .oneinit_sm_id = gv100_gr_oneinit_sm_id,
.init = gf100_gr_init,
.init_419bd8 = gv100_gr_init_419bd8,
.init_gpc_mmu = gm200_gr_init_gpc_mmu,
@@ -103,11 +295,14 @@ gv100_gr = {
.init_ppc_exceptions = gk104_gr_init_ppc_exceptions,
.init_504430 = gv100_gr_init_504430,
.init_shader_exceptions = gv100_gr_init_shader_exceptions,
+ .init_rop_exceptions = gf100_gr_init_rop_exceptions,
+ .init_exception2 = gf100_gr_init_exception2,
.init_4188a4 = gv100_gr_init_4188a4,
.trap_mp = gv100_gr_trap_mp,
+ .fecs.reset = gf100_gr_fecs_reset,
.rops = gm200_gr_rops,
.gpc_nr = 6,
- .tpc_nr = 5,
+ .tpc_nr = 7,
.ppc_nr = 3,
.grctx = &gv100_grctx,
.zbc = &gp102_gr_zbc,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c
index 0bc1a238de43..81bd682c2102 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv04.c
@@ -1192,7 +1192,7 @@ nv04_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
return -ENOMEM;
nvkm_object_ctor(&nv04_gr_chan, oclass, &chan->object);
chan->gr = gr;
- chan->chid = fifoch->chid;
+ chan->chid = fifoch->id;
*pobject = &chan->object;
*ctx_reg(chan, NV04_PGRAPH_DEBUG_3) = 0xfad4ff31;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c
index 942450b33bc6..7fe6e58f6bab 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv10.c
@@ -1011,7 +1011,7 @@ nv10_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
return -ENOMEM;
nvkm_object_ctor(&nv10_gr_chan, oclass, &chan->object);
chan->gr = gr;
- chan->chid = fifoch->chid;
+ chan->chid = fifoch->id;
*pobject = &chan->object;
NV_WRITE_CTX(0x00400e88, 0x08000000);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c
index 6bff10cee71b..75434f5de7ad 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c
@@ -83,7 +83,7 @@ nv20_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
return -ENOMEM;
nvkm_object_ctor(&nv20_gr_chan, oclass, &chan->object);
chan->gr = gr;
- chan->chid = fifoch->chid;
+ chan->chid = fifoch->id;
*pobject = &chan->object;
ret = nvkm_memory_new(gr->base.engine.subdev.device,
@@ -182,7 +182,7 @@ nv20_gr_intr(struct nvkm_gr *base)
struct nv20_gr *gr = nv20_gr(base);
struct nvkm_subdev *subdev = &gr->base.engine.subdev;
struct nvkm_device *device = subdev->device;
- struct nvkm_fifo_chan *chan;
+ struct nvkm_chan *chan;
u32 stat = nvkm_rd32(device, NV03_PGRAPH_INTR);
u32 nsource = nvkm_rd32(device, NV03_PGRAPH_NSOURCE);
u32 nstatus = nvkm_rd32(device, NV03_PGRAPH_NSTATUS);
@@ -196,7 +196,7 @@ nv20_gr_intr(struct nvkm_gr *base)
char msg[128], src[128], sta[128];
unsigned long flags;
- chan = nvkm_fifo_chan_chid(device->fifo, chid, &flags);
+ chan = nvkm_chan_get_chid(&gr->base.engine, chid, &flags);
nvkm_wr32(device, NV03_PGRAPH_INTR, stat);
nvkm_wr32(device, NV04_PGRAPH_FIFO, 0x00000001);
@@ -209,11 +209,11 @@ nv20_gr_intr(struct nvkm_gr *base)
"nstatus %08x [%s] ch %d [%s] subc %d "
"class %04x mthd %04x data %08x\n",
show, msg, nsource, src, nstatus, sta, chid,
- chan ? chan->object.client->name : "unknown",
+ chan ? chan->name : "unknown",
subc, class, mthd, data);
}
- nvkm_fifo_chan_put(device->fifo, flags, &chan);
+ nvkm_chan_put(&chan, flags);
}
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c
index f3a56f17d94a..94685e4d4f87 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv25.c
@@ -29,7 +29,7 @@ nv25_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
return -ENOMEM;
nvkm_object_ctor(&nv25_gr_chan, oclass, &chan->object);
chan->gr = gr;
- chan->chid = fifoch->chid;
+ chan->chid = fifoch->id;
*pobject = &chan->object;
ret = nvkm_memory_new(gr->base.engine.subdev.device,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c
index f268d2642d29..2d6273675291 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv2a.c
@@ -29,7 +29,7 @@ nv2a_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
return -ENOMEM;
nvkm_object_ctor(&nv2a_gr_chan, oclass, &chan->object);
chan->gr = gr;
- chan->chid = fifoch->chid;
+ chan->chid = fifoch->id;
*pobject = &chan->object;
ret = nvkm_memory_new(gr->base.engine.subdev.device,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
index e5737cdf2fa1..647bd6fede04 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv30.c
@@ -30,7 +30,7 @@ nv30_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
return -ENOMEM;
nvkm_object_ctor(&nv30_gr_chan, oclass, &chan->object);
chan->gr = gr;
- chan->chid = fifoch->chid;
+ chan->chid = fifoch->id;
*pobject = &chan->object;
ret = nvkm_memory_new(gr->base.engine.subdev.device,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
index 1ab2da8ebf4e..2eae3fe4ef4e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv34.c
@@ -29,7 +29,7 @@ nv34_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
return -ENOMEM;
nvkm_object_ctor(&nv34_gr_chan, oclass, &chan->object);
chan->gr = gr;
- chan->chid = fifoch->chid;
+ chan->chid = fifoch->id;
*pobject = &chan->object;
ret = nvkm_memory_new(gr->base.engine.subdev.device,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c
index 591260f5676b..657d7cdba369 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv35.c
@@ -29,7 +29,7 @@ nv35_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch,
return -ENOMEM;
nvkm_object_ctor(&nv35_gr_chan, oclass, &chan->object);
chan->gr = gr;
- chan->chid = fifoch->chid;
+ chan->chid = fifoch->id;
*pobject = &chan->object;
ret = nvkm_memory_new(gr->base.engine.subdev.device,
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c
index 67f3535ff97e..d2df097a6cf6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.c
@@ -275,8 +275,8 @@ nv40_gr_intr(struct nvkm_gr *base)
"nstatus %08x [%s] ch %d [%08x %s] subc %d "
"class %04x mthd %04x data %08x\n",
show, msg, nsource, src, nstatus, sta,
- chan ? chan->fifo->chid : -1, inst << 4,
- chan ? chan->fifo->object.client->name : "unknown",
+ chan ? chan->fifo->id : -1, inst << 4,
+ chan ? chan->fifo->name : "unknown",
subc, class, mthd, data);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c
index 563a10097e95..1ba18a8e380f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.c
@@ -622,7 +622,7 @@ nv50_gr_intr(struct nvkm_gr *base)
struct nv50_gr *gr = nv50_gr(base);
struct nvkm_subdev *subdev = &gr->base.engine.subdev;
struct nvkm_device *device = subdev->device;
- struct nvkm_fifo_chan *chan;
+ struct nvkm_chan *chan;
u32 stat = nvkm_rd32(device, 0x400100);
u32 inst = nvkm_rd32(device, 0x40032c) & 0x0fffffff;
u32 addr = nvkm_rd32(device, 0x400704);
@@ -637,10 +637,10 @@ nv50_gr_intr(struct nvkm_gr *base)
char msg[128];
int chid = -1;
- chan = nvkm_fifo_chan_inst(device->fifo, (u64)inst << 12, &flags);
+ chan = nvkm_chan_get_inst(&gr->base.engine, (u64)inst << 12, &flags);
if (chan) {
- name = chan->object.client->name;
- chid = chan->chid;
+ name = chan->name;
+ chid = chan->id;
}
if (show & 0x00100000) {
@@ -672,7 +672,7 @@ nv50_gr_intr(struct nvkm_gr *base)
if (nvkm_rd32(device, 0x400824) & (1 << 31))
nvkm_wr32(device, 0x400824, nvkm_rd32(device, 0x400824) & ~(1 << 31));
- nvkm_fifo_chan_put(device->fifo, flags, &chan);
+ nvkm_chan_put(&chan, flags);
}
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h
index 9b2c66e8be90..08d5c96e6458 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/priv.h
@@ -17,6 +17,7 @@ struct nvkm_gr_func {
int (*oneinit)(struct nvkm_gr *);
int (*init)(struct nvkm_gr *);
int (*fini)(struct nvkm_gr *, bool);
+ int (*reset)(struct nvkm_gr *);
void (*intr)(struct nvkm_gr *);
void (*tile)(struct nvkm_gr *, int region, struct nvkm_fb_tile *);
int (*tlb_flush)(struct nvkm_gr *);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c
index 1a8a21844e12..3b6c8100a242 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/tu102.c
@@ -24,13 +24,13 @@
#include <nvif/class.h>
-static void
+void
tu102_gr_init_fecs_exceptions(struct gf100_gr *gr)
{
- nvkm_wr32(gr->base.engine.subdev.device, 0x409c24, 0x006f0002);
+ nvkm_wr32(gr->base.engine.subdev.device, 0x409c24, 0x006e0003);
}
-static void
+void
tu102_gr_init_fs(struct gf100_gr *gr)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
@@ -40,20 +40,21 @@ tu102_gr_init_fs(struct gf100_gr *gr)
gk104_grctx_generate_gpc_tpc_nr(gr);
for (sm = 0; sm < gr->sm_nr; sm++) {
- nvkm_wr32(device, GPC_UNIT(gr->sm[sm].gpc, 0x0c10 +
- gr->sm[sm].tpc * 4), sm);
+ int tpc = gv100_gr_nonpes_aware_tpc(gr, gr->sm[sm].gpc, gr->sm[sm].tpc);
+
+ nvkm_wr32(device, GPC_UNIT(gr->sm[sm].gpc, 0x0c10 + tpc * 4), sm);
}
gm200_grctx_generate_dist_skip_table(gr);
gf100_gr_init_num_tpc_per_gpc(gr, true, true);
}
-static void
+void
tu102_gr_init_zcull(struct gf100_gr *gr)
{
struct nvkm_device *device = gr->base.engine.subdev.device;
const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total);
- const u8 tile_nr = ALIGN(gr->tpc_total, 64);
+ const u8 tile_nr = gr->func->gpc_nr * gr->func->tpc_nr;
u8 bank[GPC_MAX] = {}, gpc, i, j;
u32 data;
@@ -93,7 +94,7 @@ tu102_gr_init_gpc_mmu(struct gf100_gr *gr)
static const struct gf100_gr_func
tu102_gr = {
.oneinit_tiles = gm200_gr_oneinit_tiles,
- .oneinit_sm_id = gm200_gr_oneinit_sm_id,
+ .oneinit_sm_id = gv100_gr_oneinit_sm_id,
.init = gf100_gr_init,
.init_419bd8 = gv100_gr_init_419bd8,
.init_gpc_mmu = tu102_gr_init_gpc_mmu,
@@ -109,10 +110,14 @@ tu102_gr = {
.init_ppc_exceptions = gk104_gr_init_ppc_exceptions,
.init_504430 = gv100_gr_init_504430,
.init_shader_exceptions = gv100_gr_init_shader_exceptions,
+ .init_rop_exceptions = gf100_gr_init_rop_exceptions,
+ .init_exception2 = gf100_gr_init_exception2,
+ .init_4188a4 = gv100_gr_init_4188a4,
.trap_mp = gv100_gr_trap_mp,
+ .fecs.reset = gf100_gr_fecs_reset,
.rops = gm200_gr_rops,
.gpc_nr = 6,
- .tpc_nr = 5,
+ .tpc_nr = 6,
.ppc_nr = 3,
.grctx = &tu102_grctx,
.zbc = &gp102_gr_zbc,
@@ -137,6 +142,7 @@ MODULE_FIRMWARE("nvidia/tu102/gr/sw_ctx.bin");
MODULE_FIRMWARE("nvidia/tu102/gr/sw_nonctx.bin");
MODULE_FIRMWARE("nvidia/tu102/gr/sw_bundle_init.bin");
MODULE_FIRMWARE("nvidia/tu102/gr/sw_method_init.bin");
+MODULE_FIRMWARE("nvidia/tu102/gr/sw_veid_bundle_init.bin");
MODULE_FIRMWARE("nvidia/tu104/gr/fecs_bl.bin");
MODULE_FIRMWARE("nvidia/tu104/gr/fecs_inst.bin");
@@ -150,6 +156,7 @@ MODULE_FIRMWARE("nvidia/tu104/gr/sw_ctx.bin");
MODULE_FIRMWARE("nvidia/tu104/gr/sw_nonctx.bin");
MODULE_FIRMWARE("nvidia/tu104/gr/sw_bundle_init.bin");
MODULE_FIRMWARE("nvidia/tu104/gr/sw_method_init.bin");
+MODULE_FIRMWARE("nvidia/tu104/gr/sw_veid_bundle_init.bin");
MODULE_FIRMWARE("nvidia/tu106/gr/fecs_bl.bin");
MODULE_FIRMWARE("nvidia/tu106/gr/fecs_inst.bin");
@@ -163,6 +170,7 @@ MODULE_FIRMWARE("nvidia/tu106/gr/sw_ctx.bin");
MODULE_FIRMWARE("nvidia/tu106/gr/sw_nonctx.bin");
MODULE_FIRMWARE("nvidia/tu106/gr/sw_bundle_init.bin");
MODULE_FIRMWARE("nvidia/tu106/gr/sw_method_init.bin");
+MODULE_FIRMWARE("nvidia/tu106/gr/sw_veid_bundle_init.bin");
MODULE_FIRMWARE("nvidia/tu117/gr/fecs_bl.bin");
MODULE_FIRMWARE("nvidia/tu117/gr/fecs_inst.bin");
@@ -176,6 +184,7 @@ MODULE_FIRMWARE("nvidia/tu117/gr/sw_ctx.bin");
MODULE_FIRMWARE("nvidia/tu117/gr/sw_nonctx.bin");
MODULE_FIRMWARE("nvidia/tu117/gr/sw_bundle_init.bin");
MODULE_FIRMWARE("nvidia/tu117/gr/sw_method_init.bin");
+MODULE_FIRMWARE("nvidia/tu117/gr/sw_veid_bundle_init.bin");
MODULE_FIRMWARE("nvidia/tu116/gr/fecs_bl.bin");
MODULE_FIRMWARE("nvidia/tu116/gr/fecs_inst.bin");
@@ -189,6 +198,26 @@ MODULE_FIRMWARE("nvidia/tu116/gr/sw_ctx.bin");
MODULE_FIRMWARE("nvidia/tu116/gr/sw_nonctx.bin");
MODULE_FIRMWARE("nvidia/tu116/gr/sw_bundle_init.bin");
MODULE_FIRMWARE("nvidia/tu116/gr/sw_method_init.bin");
+MODULE_FIRMWARE("nvidia/tu116/gr/sw_veid_bundle_init.bin");
+
+int
+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[] = {
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
index b1054db4c1b8..cb0c3991b2ad 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.c
@@ -213,8 +213,8 @@ nv31_mpeg_intr(struct nvkm_engine *engine)
if (show) {
nvkm_error(subdev, "ch %d [%s] %08x %08x %08x %08x\n",
- mpeg->chan ? mpeg->chan->fifo->chid : -1,
- mpeg->chan ? mpeg->chan->object.client->name :
+ mpeg->chan ? mpeg->chan->fifo->id : -1,
+ mpeg->chan ? mpeg->chan->fifo->name :
"unknown", stat, type, mthd, data);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
index 521ce43a2871..0890a279458e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv44.c
@@ -182,8 +182,8 @@ nv44_mpeg_intr(struct nvkm_engine *engine)
if (show) {
nvkm_error(subdev, "ch %d [%08x %s] %08x %08x %08x %08x\n",
- chan ? chan->fifo->chid : -1, inst << 4,
- chan ? chan->object.client->name : "unknown",
+ chan ? chan->fifo->id : -1, inst << 4,
+ chan ? chan->fifo->name : "unknown",
stat, type, mthd, data);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/Kbuild
index 9a0fd9812750..f05e79670d22 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/Kbuild
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: MIT
nvkm-y += nvkm/engine/nvdec/base.o
nvkm-y += nvkm/engine/nvdec/gm107.o
+nvkm-y += nvkm/engine/nvdec/ga102.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c
index b0181cc5953b..1f6e3b32ba16 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/base.c
@@ -37,7 +37,7 @@ nvkm_nvdec = {
int
nvkm_nvdec_new_(const struct nvkm_nvdec_fwif *fwif, struct nvkm_device *device,
- enum nvkm_subdev_type type, int inst, struct nvkm_nvdec **pnvdec)
+ enum nvkm_subdev_type type, int inst, u32 addr, struct nvkm_nvdec **pnvdec)
{
struct nvkm_nvdec *nvdec;
int ret;
@@ -57,5 +57,5 @@ nvkm_nvdec_new_(const struct nvkm_nvdec_fwif *fwif, struct nvkm_device *device,
nvdec->func = fwif->func;
return nvkm_falcon_ctor(nvdec->func->flcn, &nvdec->engine.subdev,
- nvdec->engine.subdev.name, 0, &nvdec->falcon);
+ nvdec->engine.subdev.name, addr, &nvdec->falcon);
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/ga102.c
new file mode 100644
index 000000000000..37d8c3c0f3ab
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/ga102.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2021 Red Hat 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 "priv.h"
+
+#include <subdev/mc.h>
+#include <subdev/timer.h>
+
+static const struct nvkm_falcon_func
+ga102_nvdec_flcn = {
+ .disable = gm200_flcn_disable,
+ .enable = gm200_flcn_enable,
+ .addr2 = 0x1c00,
+ .reset_pmc = true,
+ .reset_prep = ga102_flcn_reset_prep,
+ .reset_wait_mem_scrubbing = ga102_flcn_reset_wait_mem_scrubbing,
+ .imem_dma = &ga102_flcn_dma,
+ .dmem_dma = &ga102_flcn_dma,
+};
+
+static const struct nvkm_nvdec_func
+ga102_nvdec = {
+ .flcn = &ga102_nvdec_flcn,
+};
+
+static int
+ga102_nvdec_nofw(struct nvkm_nvdec *nvdec, int ver, const struct nvkm_nvdec_fwif *fwif)
+{
+ return 0;
+}
+
+static const struct nvkm_nvdec_fwif
+ga102_nvdec_fwif[] = {
+ { -1, ga102_nvdec_nofw, &ga102_nvdec },
+ {}
+};
+
+int
+ga102_nvdec_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
+ struct nvkm_nvdec **pnvdec)
+{
+ return nvkm_nvdec_new_(ga102_nvdec_fwif, device, type, inst, 0x848000, pnvdec);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c
index 8c44ce44a6d7..564f7e8960a2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/gm107.c
@@ -23,18 +23,13 @@
static const struct nvkm_falcon_func
gm107_nvdec_flcn = {
+ .disable = gm200_flcn_disable,
+ .enable = gm200_flcn_enable,
+ .reset_pmc = true,
+ .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing,
.debug = 0xd00,
- .fbif = 0x600,
- .load_imem = nvkm_falcon_v1_load_imem,
- .load_dmem = nvkm_falcon_v1_load_dmem,
- .read_dmem = nvkm_falcon_v1_read_dmem,
- .bind_context = nvkm_falcon_v1_bind_context,
- .wait_for_halt = nvkm_falcon_v1_wait_for_halt,
- .clear_interrupt = nvkm_falcon_v1_clear_interrupt,
- .set_start_addr = nvkm_falcon_v1_set_start_addr,
- .start = nvkm_falcon_v1_start,
- .enable = nvkm_falcon_v1_enable,
- .disable = nvkm_falcon_v1_disable,
+ .imem_pio = &gm200_flcn_imem_pio,
+ .dmem_pio = &gm200_flcn_dmem_pio,
};
static const struct nvkm_nvdec_func
@@ -59,5 +54,5 @@ int
gm107_nvdec_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_nvdec **pnvdec)
{
- return nvkm_nvdec_new_(gm107_nvdec_fwif, device, type, inst, pnvdec);
+ return nvkm_nvdec_new_(gm107_nvdec_fwif, device, type, inst, 0, pnvdec);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h
index 0920f6a887e2..61e1f7aaa509 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvdec/priv.h
@@ -15,5 +15,5 @@ struct nvkm_nvdec_fwif {
};
int nvkm_nvdec_new_(const struct nvkm_nvdec_fwif *fwif, struct nvkm_device *,
- enum nvkm_subdev_type, int, struct nvkm_nvdec **);
+ enum nvkm_subdev_type, int, u32 addr, struct nvkm_nvdec **);
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c
index f44d41bf2034..ad27d8b97569 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/nvenc/gm107.c
@@ -24,17 +24,6 @@
static const struct nvkm_falcon_func
gm107_nvenc_flcn = {
- .fbif = 0x800,
- .load_imem = nvkm_falcon_v1_load_imem,
- .load_dmem = nvkm_falcon_v1_load_dmem,
- .read_dmem = nvkm_falcon_v1_read_dmem,
- .bind_context = nvkm_falcon_v1_bind_context,
- .wait_for_halt = nvkm_falcon_v1_wait_for_halt,
- .clear_interrupt = nvkm_falcon_v1_clear_interrupt,
- .set_start_addr = nvkm_falcon_v1_set_start_addr,
- .start = nvkm_falcon_v1_start,
- .enable = nvkm_falcon_v1_enable,
- .disable = nvkm_falcon_v1_disable,
};
static const struct nvkm_nvenc_func
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c
index 1b87df03c823..c15b2cbf506b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec/g98.c
@@ -40,7 +40,7 @@ static const struct nvkm_enum g98_sec_isr_error_name[] = {
};
static void
-g98_sec_intr(struct nvkm_falcon *sec, struct nvkm_fifo_chan *chan)
+g98_sec_intr(struct nvkm_falcon *sec, struct nvkm_chan *chan)
{
struct nvkm_subdev *subdev = &sec->engine.subdev;
struct nvkm_device *device = subdev->device;
@@ -54,9 +54,9 @@ g98_sec_intr(struct nvkm_falcon *sec, struct nvkm_fifo_chan *chan)
nvkm_error(subdev, "DISPATCH_ERROR %04x [%s] ch %d [%010llx %s] "
"subc %d mthd %04x data %08x\n", ssta,
- en ? en->name : "UNKNOWN", chan ? chan->chid : -1,
+ en ? en->name : "UNKNOWN", chan ? chan->id : -1,
chan ? chan->inst->addr : 0,
- chan ? chan->object.client->name : "unknown",
+ chan ? chan->name : "unknown",
subc, mthd, data);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild
index 63cd2be3de08..19feadb1f67b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/Kbuild
@@ -3,3 +3,4 @@ nvkm-y += nvkm/engine/sec2/base.o
nvkm-y += nvkm/engine/sec2/gp102.o
nvkm-y += nvkm/engine/sec2/gp108.o
nvkm-y += nvkm/engine/sec2/tu102.o
+nvkm-y += nvkm/engine/sec2/ga102.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c
index 092c6d0b8e01..f2c60da5d1e8 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/base.c
@@ -22,53 +22,99 @@
#include "priv.h"
#include <core/firmware.h>
-#include <subdev/top.h>
+#include <subdev/mc.h>
+#include <subdev/timer.h>
-static void
-nvkm_sec2_recv(struct work_struct *work)
+#include <nvfw/sec2.h>
+
+static int
+nvkm_sec2_finimsg(void *priv, struct nvfw_falcon_msg *hdr)
+{
+ struct nvkm_sec2 *sec2 = priv;
+
+ atomic_set(&sec2->running, 0);
+ return 0;
+}
+
+static int
+nvkm_sec2_fini(struct nvkm_engine *engine, bool suspend)
{
- struct nvkm_sec2 *sec2 = container_of(work, typeof(*sec2), work);
+ struct nvkm_sec2 *sec2 = nvkm_sec2(engine);
+ struct nvkm_subdev *subdev = &sec2->engine.subdev;
+ struct nvkm_falcon *falcon = &sec2->falcon;
+ struct nvkm_falcon_cmdq *cmdq = sec2->cmdq;
+ struct nvfw_falcon_cmd cmd = {
+ .unit_id = sec2->func->unit_unload,
+ .size = sizeof(cmd),
+ };
+ int ret;
- if (!sec2->initmsg_received) {
- int ret = sec2->func->initmsg(sec2);
- if (ret) {
- nvkm_error(&sec2->engine.subdev,
- "error parsing init message: %d\n", ret);
- return;
- }
+ if (!subdev->use.enabled)
+ return 0;
- sec2->initmsg_received = true;
+ if (atomic_read(&sec2->initmsg) == 1) {
+ ret = nvkm_falcon_cmdq_send(cmdq, &cmd, nvkm_sec2_finimsg, sec2,
+ msecs_to_jiffies(1000));
+ WARN_ON(ret);
+
+ nvkm_msec(subdev->device, 2000,
+ if (nvkm_falcon_rd32(falcon, 0x100) & 0x00000010)
+ break;
+ );
}
- nvkm_falcon_msgq_recv(sec2->msgq);
+ nvkm_inth_block(&subdev->inth);
+
+ nvkm_falcon_cmdq_fini(cmdq);
+ falcon->func->disable(falcon);
+ nvkm_falcon_put(falcon, subdev);
+ return 0;
}
-static void
-nvkm_sec2_intr(struct nvkm_engine *engine)
+static int
+nvkm_sec2_init(struct nvkm_engine *engine)
{
struct nvkm_sec2 *sec2 = nvkm_sec2(engine);
- sec2->func->intr(sec2);
+ struct nvkm_subdev *subdev = &sec2->engine.subdev;
+ struct nvkm_falcon *falcon = &sec2->falcon;
+ int ret;
+
+ ret = nvkm_falcon_get(falcon, subdev);
+ if (ret)
+ return ret;
+
+ nvkm_falcon_wr32(falcon, 0x014, 0xffffffff);
+ atomic_set(&sec2->initmsg, 0);
+ atomic_set(&sec2->running, 1);
+ nvkm_inth_allow(&subdev->inth);
+
+ nvkm_falcon_start(falcon);
+ return 0;
}
static int
-nvkm_sec2_fini(struct nvkm_engine *engine, bool suspend)
+nvkm_sec2_oneinit(struct nvkm_engine *engine)
{
struct nvkm_sec2 *sec2 = nvkm_sec2(engine);
-
- flush_work(&sec2->work);
-
- if (suspend) {
- nvkm_falcon_cmdq_fini(sec2->cmdq);
- sec2->initmsg_received = false;
+ struct nvkm_subdev *subdev = &sec2->engine.subdev;
+ struct nvkm_intr *intr = &sec2->engine.subdev.device->mc->intr;
+ enum nvkm_intr_type type = NVKM_INTR_SUBDEV;
+
+ if (sec2->func->intr_vector) {
+ intr = sec2->func->intr_vector(sec2, &type);
+ if (IS_ERR(intr))
+ return PTR_ERR(intr);
}
- return 0;
+ return nvkm_inth_add(intr, type, NVKM_INTR_PRIO_NORMAL, subdev, sec2->func->intr,
+ &subdev->inth);
}
static void *
nvkm_sec2_dtor(struct nvkm_engine *engine)
{
struct nvkm_sec2 *sec2 = nvkm_sec2(engine);
+
nvkm_falcon_msgq_del(&sec2->msgq);
nvkm_falcon_cmdq_del(&sec2->cmdq);
nvkm_falcon_qmgr_del(&sec2->qmgr);
@@ -79,8 +125,9 @@ nvkm_sec2_dtor(struct nvkm_engine *engine)
static const struct nvkm_engine_func
nvkm_sec2 = {
.dtor = nvkm_sec2_dtor,
+ .oneinit = nvkm_sec2_oneinit,
+ .init = nvkm_sec2_init,
.fini = nvkm_sec2_fini,
- .intr = nvkm_sec2_intr,
};
int
@@ -113,6 +160,5 @@ nvkm_sec2_new_(const struct nvkm_sec2_fwif *fwif, struct nvkm_device *device,
(ret = nvkm_falcon_msgq_new(sec2->qmgr, "msgq", &sec2->msgq)))
return ret;
- INIT_WORK(&sec2->work, nvkm_sec2_recv);
return 0;
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/ga102.c
new file mode 100644
index 000000000000..945abb8156d7
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/ga102.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2021 Red Hat 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 "priv.h"
+#include <subdev/acr.h>
+#include <subdev/vfn.h>
+
+#include <nvfw/flcn.h>
+#include <nvfw/sec2.h>
+
+static int
+ga102_sec2_initmsg(struct nvkm_sec2 *sec2)
+{
+ struct nv_sec2_init_msg_v1 msg;
+ int ret, i;
+
+ ret = nvkm_falcon_msgq_recv_initmsg(sec2->msgq, &msg, sizeof(msg));
+ if (ret)
+ return ret;
+
+ if (msg.hdr.unit_id != NV_SEC2_UNIT_INIT ||
+ msg.msg_type != NV_SEC2_INIT_MSG_INIT)
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(msg.queue_info); i++) {
+ if (msg.queue_info[i].id == NV_SEC2_INIT_MSG_QUEUE_ID_MSGQ) {
+ nvkm_falcon_msgq_init(sec2->msgq, msg.queue_info[i].index,
+ msg.queue_info[i].offset,
+ msg.queue_info[i].size);
+ } else {
+ nvkm_falcon_cmdq_init(sec2->cmdq, msg.queue_info[i].index,
+ msg.queue_info[i].offset,
+ msg.queue_info[i].size);
+ }
+ }
+
+ return 0;
+}
+
+static struct nvkm_intr *
+ga102_sec2_intr_vector(struct nvkm_sec2 *sec2, enum nvkm_intr_type *pvector)
+{
+ struct nvkm_device *device = sec2->engine.subdev.device;
+ struct nvkm_falcon *falcon = &sec2->falcon;
+ int ret;
+
+ ret = ga102_flcn_select(falcon);
+ if (ret)
+ return ERR_PTR(ret);
+
+ *pvector = nvkm_rd32(device, 0x8403e0) & 0x000000ff;
+ return &device->vfn->intr;
+}
+
+static int
+ga102_sec2_acr_bootstrap_falcon_callback(void *priv, struct nvfw_falcon_msg *hdr)
+{
+ struct nv_sec2_acr_bootstrap_falcon_msg_v1 *msg =
+ container_of(hdr, typeof(*msg), msg.hdr);
+ struct nvkm_subdev *subdev = priv;
+ const char *name = nvkm_acr_lsf_id(msg->falcon_id);
+
+ if (msg->error_code) {
+ nvkm_error(subdev, "ACR_BOOTSTRAP_FALCON failed for falcon %d [%s]: %08x %08x\n",
+ msg->falcon_id, name, msg->error_code, msg->unkn08);
+ return -EINVAL;
+ }
+
+ nvkm_debug(subdev, "%s booted\n", name);
+ return 0;
+}
+
+static int
+ga102_sec2_acr_bootstrap_falcon(struct nvkm_falcon *falcon, enum nvkm_acr_lsf_id id)
+{
+ struct nvkm_sec2 *sec2 = container_of(falcon, typeof(*sec2), falcon);
+ struct nv_sec2_acr_bootstrap_falcon_cmd_v1 cmd = {
+ .cmd.hdr.unit_id = sec2->func->unit_acr,
+ .cmd.hdr.size = sizeof(cmd),
+ .cmd.cmd_type = NV_SEC2_ACR_CMD_BOOTSTRAP_FALCON,
+ .flags = NV_SEC2_ACR_BOOTSTRAP_FALCON_FLAGS_RESET_YES,
+ .falcon_id = id,
+ };
+
+ return nvkm_falcon_cmdq_send(sec2->cmdq, &cmd.cmd.hdr,
+ ga102_sec2_acr_bootstrap_falcon_callback,
+ &sec2->engine.subdev,
+ msecs_to_jiffies(1000));
+}
+
+static const struct nvkm_acr_lsf_func
+ga102_sec2_acr_0 = {
+ .bld_size = sizeof(struct flcn_bl_dmem_desc_v2),
+ .bld_write = gp102_sec2_acr_bld_write_1,
+ .bld_patch = gp102_sec2_acr_bld_patch_1,
+ .bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) |
+ BIT_ULL(NVKM_ACR_LSF_GPCCS) |
+ BIT_ULL(NVKM_ACR_LSF_SEC2),
+ .bootstrap_falcon = ga102_sec2_acr_bootstrap_falcon,
+};
+
+static const struct nvkm_falcon_func
+ga102_sec2_flcn = {
+ .disable = gm200_flcn_disable,
+ .enable = gm200_flcn_enable,
+ .select = ga102_flcn_select,
+ .addr2 = 0x1000,
+ .reset_pmc = true,
+ .reset_eng = gp102_flcn_reset_eng,
+ .reset_prep = ga102_flcn_reset_prep,
+ .reset_wait_mem_scrubbing = ga102_flcn_reset_wait_mem_scrubbing,
+ .imem_dma = &ga102_flcn_dma,
+ .dmem_pio = &gm200_flcn_dmem_pio,
+ .dmem_dma = &ga102_flcn_dma,
+ .emem_addr = 0x01000000,
+ .emem_pio = &gp102_flcn_emem_pio,
+ .start = nvkm_falcon_v1_start,
+ .cmdq = { 0xc00, 0xc04, 8 },
+ .msgq = { 0xc80, 0xc84, 8 },
+};
+
+static const struct nvkm_sec2_func
+ga102_sec2 = {
+ .flcn = &ga102_sec2_flcn,
+ .intr_vector = ga102_sec2_intr_vector,
+ .intr = gp102_sec2_intr,
+ .initmsg = ga102_sec2_initmsg,
+ .unit_acr = NV_SEC2_UNIT_V2_ACR,
+ .unit_unload = NV_SEC2_UNIT_V2_UNLOAD,
+};
+
+MODULE_FIRMWARE("nvidia/ga102/sec2/desc.bin");
+MODULE_FIRMWARE("nvidia/ga102/sec2/image.bin");
+MODULE_FIRMWARE("nvidia/ga102/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/ga102/sec2/hs_bl_sig.bin");
+
+MODULE_FIRMWARE("nvidia/ga103/sec2/desc.bin");
+MODULE_FIRMWARE("nvidia/ga103/sec2/image.bin");
+MODULE_FIRMWARE("nvidia/ga103/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/ga103/sec2/hs_bl_sig.bin");
+
+MODULE_FIRMWARE("nvidia/ga104/sec2/desc.bin");
+MODULE_FIRMWARE("nvidia/ga104/sec2/image.bin");
+MODULE_FIRMWARE("nvidia/ga104/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/ga104/sec2/hs_bl_sig.bin");
+
+MODULE_FIRMWARE("nvidia/ga106/sec2/desc.bin");
+MODULE_FIRMWARE("nvidia/ga106/sec2/image.bin");
+MODULE_FIRMWARE("nvidia/ga106/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/ga106/sec2/hs_bl_sig.bin");
+
+MODULE_FIRMWARE("nvidia/ga107/sec2/desc.bin");
+MODULE_FIRMWARE("nvidia/ga107/sec2/image.bin");
+MODULE_FIRMWARE("nvidia/ga107/sec2/sig.bin");
+MODULE_FIRMWARE("nvidia/ga107/sec2/hs_bl_sig.bin");
+
+static int
+ga102_sec2_load(struct nvkm_sec2 *sec2, int ver,
+ const struct nvkm_sec2_fwif *fwif)
+{
+ return nvkm_acr_lsfw_load_sig_image_desc_v2(&sec2->engine.subdev, &sec2->falcon,
+ NVKM_ACR_LSF_SEC2, "sec2/", ver, fwif->acr);
+}
+
+static const struct nvkm_sec2_fwif
+ga102_sec2_fwif[] = {
+ { 0, ga102_sec2_load, &ga102_sec2, &ga102_sec2_acr_0 },
+ { -1, gp102_sec2_nofw, &ga102_sec2 }
+};
+
+int
+ga102_sec2_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
+ struct nvkm_sec2 **psec2)
+{
+ /* TOP info wasn't updated on Turing to reflect the PRI
+ * address change for some reason. We override it here.
+ */
+ return nvkm_sec2_new_(ga102_sec2_fwif, device, type, inst, 0x840000, psec2);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c
index 44e39f5743d5..c64013d10500 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/gp102.c
@@ -74,16 +74,6 @@ gp102_sec2_acr_bootstrap_falcon(struct nvkm_falcon *falcon,
msecs_to_jiffies(1000));
}
-static int
-gp102_sec2_acr_boot(struct nvkm_falcon *falcon)
-{
- struct nv_sec2_args args = {};
- nvkm_falcon_load_dmem(falcon, &args,
- falcon->func->emem_addr, sizeof(args), 0);
- nvkm_falcon_start(falcon);
- return 0;
-}
-
static void
gp102_sec2_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust)
{
@@ -122,7 +112,6 @@ gp102_sec2_acr_0 = {
.bld_size = sizeof(struct loader_config_v1),
.bld_write = gp102_sec2_acr_bld_write,
.bld_patch = gp102_sec2_acr_bld_patch,
- .boot = gp102_sec2_acr_boot,
.bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) |
BIT_ULL(NVKM_ACR_LSF_GPCCS) |
BIT_ULL(NVKM_ACR_LSF_SEC2),
@@ -160,89 +149,68 @@ gp102_sec2_initmsg(struct nvkm_sec2 *sec2)
return 0;
}
-void
-gp102_sec2_intr(struct nvkm_sec2 *sec2)
+irqreturn_t
+gp102_sec2_intr(struct nvkm_inth *inth)
{
+ struct nvkm_sec2 *sec2 = container_of(inth, typeof(*sec2), engine.subdev.inth);
struct nvkm_subdev *subdev = &sec2->engine.subdev;
struct nvkm_falcon *falcon = &sec2->falcon;
u32 disp = nvkm_falcon_rd32(falcon, 0x01c);
u32 intr = nvkm_falcon_rd32(falcon, 0x008) & disp & ~(disp >> 16);
if (intr & 0x00000040) {
- schedule_work(&sec2->work);
+ if (unlikely(atomic_read(&sec2->initmsg) == 0)) {
+ int ret = sec2->func->initmsg(sec2);
+
+ if (ret)
+ nvkm_error(subdev, "error parsing init message: %d\n", ret);
+
+ atomic_set(&sec2->initmsg, ret ?: 1);
+ }
+
+ if (atomic_read(&sec2->initmsg) > 0) {
+ if (!nvkm_falcon_msgq_empty(sec2->msgq))
+ nvkm_falcon_msgq_recv(sec2->msgq);
+ }
+
nvkm_falcon_wr32(falcon, 0x004, 0x00000040);
intr &= ~0x00000040;
}
+ if (intr & 0x00000010) {
+ if (atomic_read(&sec2->running)) {
+ FLCN_ERR(falcon, "halted");
+ gm200_flcn_tracepc(falcon);
+ }
+
+ nvkm_falcon_wr32(falcon, 0x004, 0x00000010);
+ intr &= ~0x00000010;
+ }
+
if (intr) {
nvkm_error(subdev, "unhandled intr %08x\n", intr);
nvkm_falcon_wr32(falcon, 0x004, intr);
}
-}
-int
-gp102_sec2_flcn_enable(struct nvkm_falcon *falcon)
-{
- nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000001);
- udelay(10);
- nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000000);
- return nvkm_falcon_v1_enable(falcon);
-}
-
-void
-gp102_sec2_flcn_bind_context(struct nvkm_falcon *falcon,
- struct nvkm_memory *ctx)
-{
- struct nvkm_device *device = falcon->owner->device;
-
- nvkm_falcon_v1_bind_context(falcon, ctx);
- if (!ctx)
- return;
-
- /* Not sure if this is a WAR for a HW issue, or some additional
- * programming sequence that's needed to properly complete the
- * context switch we trigger above.
- *
- * Fixes unreliability of booting the SEC2 RTOS on Quadro P620,
- * particularly when resuming from suspend.
- *
- * Also removes the need for an odd workaround where we needed
- * to program SEC2's FALCON_CPUCTL_ALIAS_STARTCPU twice before
- * the SEC2 RTOS would begin executing.
- */
- nvkm_msec(device, 10,
- u32 irqstat = nvkm_falcon_rd32(falcon, 0x008);
- u32 flcn0dc = nvkm_falcon_rd32(falcon, 0x0dc);
- if ((irqstat & 0x00000008) &&
- (flcn0dc & 0x00007000) == 0x00005000)
- break;
- );
-
- nvkm_falcon_mask(falcon, 0x004, 0x00000008, 0x00000008);
- nvkm_falcon_mask(falcon, 0x058, 0x00000002, 0x00000002);
-
- nvkm_msec(device, 10,
- u32 flcn0dc = nvkm_falcon_rd32(falcon, 0x0dc);
- if ((flcn0dc & 0x00007000) == 0x00000000)
- break;
- );
+ return IRQ_HANDLED;
}
static const struct nvkm_falcon_func
gp102_sec2_flcn = {
+ .disable = gm200_flcn_disable,
+ .enable = gm200_flcn_enable,
+ .reset_pmc = true,
+ .reset_eng = gp102_flcn_reset_eng,
+ .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing,
.debug = 0x408,
- .fbif = 0x600,
- .load_imem = nvkm_falcon_v1_load_imem,
- .load_dmem = nvkm_falcon_v1_load_dmem,
- .read_dmem = nvkm_falcon_v1_read_dmem,
+ .bind_inst = gm200_flcn_bind_inst,
+ .bind_stat = gm200_flcn_bind_stat,
+ .bind_intr = true,
+ .imem_pio = &gm200_flcn_imem_pio,
+ .dmem_pio = &gm200_flcn_dmem_pio,
.emem_addr = 0x01000000,
- .bind_context = gp102_sec2_flcn_bind_context,
- .wait_for_halt = nvkm_falcon_v1_wait_for_halt,
- .clear_interrupt = nvkm_falcon_v1_clear_interrupt,
- .set_start_addr = nvkm_falcon_v1_set_start_addr,
+ .emem_pio = &gp102_flcn_emem_pio,
.start = nvkm_falcon_v1_start,
- .enable = gp102_sec2_flcn_enable,
- .disable = nvkm_falcon_v1_disable,
.cmdq = { 0xa00, 0xa04, 8 },
.msgq = { 0xa30, 0xa34, 8 },
};
@@ -250,6 +218,7 @@ gp102_sec2_flcn = {
const struct nvkm_sec2_func
gp102_sec2 = {
.flcn = &gp102_sec2_flcn,
+ .unit_unload = NV_SEC2_UNIT_UNLOAD,
.unit_acr = NV_SEC2_UNIT_ACR,
.intr = gp102_sec2_intr,
.initmsg = gp102_sec2_initmsg,
@@ -268,7 +237,7 @@ MODULE_FIRMWARE("nvidia/gp107/sec2/desc.bin");
MODULE_FIRMWARE("nvidia/gp107/sec2/image.bin");
MODULE_FIRMWARE("nvidia/gp107/sec2/sig.bin");
-static void
+void
gp102_sec2_acr_bld_patch_1(struct nvkm_acr *acr, u32 bld, s64 adjust)
{
struct flcn_bl_dmem_desc_v2 hdr;
@@ -279,7 +248,7 @@ gp102_sec2_acr_bld_patch_1(struct nvkm_acr *acr, u32 bld, s64 adjust)
flcn_bl_dmem_desc_v2_dump(&acr->subdev, &hdr);
}
-static void
+void
gp102_sec2_acr_bld_write_1(struct nvkm_acr *acr, u32 bld,
struct nvkm_acr_lsfw *lsfw)
{
@@ -304,7 +273,6 @@ gp102_sec2_acr_1 = {
.bld_size = sizeof(struct flcn_bl_dmem_desc_v2),
.bld_write = gp102_sec2_acr_bld_write_1,
.bld_patch = gp102_sec2_acr_bld_patch_1,
- .boot = gp102_sec2_acr_boot,
.bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_FECS) |
BIT_ULL(NVKM_ACR_LSF_GPCCS) |
BIT_ULL(NVKM_ACR_LSF_SEC2),
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h
index af19229e885d..172d2705c199 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/priv.h
@@ -2,15 +2,18 @@
#ifndef __NVKM_SEC2_PRIV_H__
#define __NVKM_SEC2_PRIV_H__
#include <engine/sec2.h>
+struct nvkm_acr_lsfw;
struct nvkm_sec2_func {
const struct nvkm_falcon_func *flcn;
+ u8 unit_unload;
u8 unit_acr;
- void (*intr)(struct nvkm_sec2 *);
+ struct nvkm_intr *(*intr_vector)(struct nvkm_sec2 *, enum nvkm_intr_type *);
+ irqreturn_t (*intr)(struct nvkm_inth *);
int (*initmsg)(struct nvkm_sec2 *);
};
-void gp102_sec2_intr(struct nvkm_sec2 *);
+irqreturn_t gp102_sec2_intr(struct nvkm_inth *);
int gp102_sec2_initmsg(struct nvkm_sec2 *);
struct nvkm_sec2_fwif {
@@ -24,6 +27,8 @@ int gp102_sec2_nofw(struct nvkm_sec2 *, int, const struct nvkm_sec2_fwif *);
int gp102_sec2_load(struct nvkm_sec2 *, int, const struct nvkm_sec2_fwif *);
extern const struct nvkm_sec2_func gp102_sec2;
extern const struct nvkm_acr_lsf_func gp102_sec2_acr_1;
+void gp102_sec2_acr_bld_write_1(struct nvkm_acr *, u32, struct nvkm_acr_lsfw *);
+void gp102_sec2_acr_bld_patch_1(struct nvkm_acr *, u32, s64);
int nvkm_sec2_new_(const struct nvkm_sec2_fwif *, struct nvkm_device *, enum nvkm_subdev_type,
int, u32 addr, struct nvkm_sec2 **);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c
index f3faeb705575..0afc4b2fa529 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sec2/tu102.c
@@ -22,21 +22,24 @@
#include "priv.h"
#include <subdev/acr.h>
+#include <nvfw/sec2.h>
+
static const struct nvkm_falcon_func
tu102_sec2_flcn = {
+ .disable = gm200_flcn_disable,
+ .enable = gm200_flcn_enable,
+ .reset_pmc = true,
+ .reset_eng = gp102_flcn_reset_eng,
+ .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing,
.debug = 0x408,
- .fbif = 0x600,
- .load_imem = nvkm_falcon_v1_load_imem,
- .load_dmem = nvkm_falcon_v1_load_dmem,
- .read_dmem = nvkm_falcon_v1_read_dmem,
+ .bind_inst = gm200_flcn_bind_inst,
+ .bind_stat = gm200_flcn_bind_stat,
+ .bind_intr = true,
+ .imem_pio = &gm200_flcn_imem_pio,
+ .dmem_pio = &gm200_flcn_dmem_pio,
.emem_addr = 0x01000000,
- .bind_context = gp102_sec2_flcn_bind_context,
- .wait_for_halt = nvkm_falcon_v1_wait_for_halt,
- .clear_interrupt = nvkm_falcon_v1_clear_interrupt,
- .set_start_addr = nvkm_falcon_v1_set_start_addr,
+ .emem_pio = &gp102_flcn_emem_pio,
.start = nvkm_falcon_v1_start,
- .enable = nvkm_falcon_v1_enable,
- .disable = nvkm_falcon_v1_disable,
.cmdq = { 0xc00, 0xc04, 8 },
.msgq = { 0xc80, 0xc84, 8 },
};
@@ -44,7 +47,8 @@ tu102_sec2_flcn = {
static const struct nvkm_sec2_func
tu102_sec2 = {
.flcn = &tu102_sec2_flcn,
- .unit_acr = 0x07,
+ .unit_unload = NV_SEC2_UNIT_V2_UNLOAD,
+ .unit_acr = NV_SEC2_UNIT_V2_ACR,
.intr = gp102_sec2_intr,
.initmsg = gp102_sec2_initmsg,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c
index 14871d0bd746..a9d464db6974 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/base.c
@@ -35,7 +35,7 @@ nvkm_sw_mthd(struct nvkm_sw *sw, int chid, int subc, u32 mthd, u32 data)
spin_lock_irqsave(&sw->engine.lock, flags);
list_for_each_entry(chan, &sw->chan, head) {
- if (chan->fifo->chid == chid) {
+ if (chan->fifo->id == chid) {
handled = nvkm_sw_chan_mthd(chan, subc, mthd, data);
list_del(&chan->head);
list_add(&chan->head, &sw->chan);
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c
index f28967065639..834b8cbed51d 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.c
@@ -23,7 +23,6 @@
*/
#include "chan.h"
-#include <core/notify.h>
#include <engine/fifo.h>
#include <nvif/event.h>
@@ -36,7 +35,7 @@ nvkm_sw_chan_mthd(struct nvkm_sw_chan *chan, int subc, u32 mthd, u32 data)
case 0x0000:
return true;
case 0x0500:
- nvkm_event_send(&chan->event, 1, 0, NULL, 0);
+ nvkm_event_ntfy(&chan->event, 0, NVKM_SW_CHAN_EVENT_PAGE_FLIP);
return true;
default:
if (chan->func->mthd)
@@ -46,27 +45,8 @@ nvkm_sw_chan_mthd(struct nvkm_sw_chan *chan, int subc, u32 mthd, u32 data)
return false;
}
-static int
-nvkm_sw_chan_event_ctor(struct nvkm_object *object, void *data, u32 size,
- struct nvkm_notify *notify)
-{
- union {
- struct nvif_notify_uevent_req none;
- } *req = data;
- int ret = -ENOSYS;
-
- if (!(ret = nvif_unvers(ret, &data, &size, req->none))) {
- notify->size = sizeof(struct nvif_notify_uevent_rep);
- notify->types = 1;
- notify->index = 0;
- }
-
- return ret;
-}
-
static const struct nvkm_event_func
nvkm_sw_chan_event = {
- .ctor = nvkm_sw_chan_event_ctor,
};
static void *
@@ -107,5 +87,5 @@ nvkm_sw_chan_ctor(const struct nvkm_sw_chan_func *func, struct nvkm_sw *sw,
list_add(&chan->head, &sw->chan);
spin_unlock_irqrestore(&sw->engine.lock, flags);
- return nvkm_event_init(&nvkm_sw_chan_event, 1, 1, &chan->event);
+ return nvkm_event_init(&nvkm_sw_chan_event, &sw->engine.subdev, 1, 1, &chan->event);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h
index 32de53427aa4..67b2e5ea93d9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h
@@ -14,6 +14,7 @@ struct nvkm_sw_chan {
struct nvkm_fifo_chan *fifo;
struct list_head head;
+#define NVKM_SW_CHAN_EVENT_PAGE_FLIP BIT(0)
struct nvkm_event event;
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c
index 55abf839f29d..c3cf6f2ff86c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/gf100.c
@@ -36,10 +36,10 @@
******************************************************************************/
static int
-gf100_sw_chan_vblsem_release(struct nvkm_notify *notify)
+gf100_sw_chan_vblsem_release(struct nvkm_event_ntfy *notify, u32 bits)
{
struct nv50_sw_chan *chan =
- container_of(notify, typeof(*chan), vblank.notify[notify->index]);
+ container_of(notify, typeof(*chan), vblank.notify[notify->id]);
struct nvkm_sw *sw = chan->base.sw;
struct nvkm_device *device = sw->engine.subdev.device;
u32 inst = chan->base.fifo->inst->addr >> 12;
@@ -50,7 +50,7 @@ gf100_sw_chan_vblsem_release(struct nvkm_notify *notify)
nvkm_wr32(device, 0x060010, lower_32_bits(chan->vblank.offset));
nvkm_wr32(device, 0x060014, chan->vblank.value);
- return NVKM_NOTIFY_DROP;
+ return NVKM_EVENT_DROP;
}
static bool
@@ -73,7 +73,7 @@ gf100_sw_chan_mthd(struct nvkm_sw_chan *base, int subc, u32 mthd, u32 data)
return true;
case 0x040c:
if (data < device->disp->vblank.index_nr) {
- nvkm_notify_get(&chan->vblank.notify[data]);
+ nvkm_event_ntfy_allow(&chan->vblank.notify[data]);
return true;
}
break;
@@ -120,16 +120,8 @@ gf100_sw_chan_new(struct nvkm_sw *sw, struct nvkm_fifo_chan *fifoch,
return ret;
for (i = 0; disp && i < disp->vblank.index_nr; i++) {
- ret = nvkm_notify_init(NULL, &disp->vblank,
- gf100_sw_chan_vblsem_release, false,
- &(struct nvif_notify_head_req_v0) {
- .head = i,
- },
- sizeof(struct nvif_notify_head_req_v0),
- sizeof(struct nvif_notify_head_rep_v0),
- &chan->vblank.notify[i]);
- if (ret)
- return ret;
+ nvkm_event_ntfy_add(&disp->vblank, i, NVKM_DISP_HEAD_EVENT_VBLANK, true,
+ gf100_sw_chan_vblsem_release, &chan->vblank.notify[i]);
}
return 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c
index 1fdd094c8b7e..9d7a9b7d5be3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.c
@@ -36,10 +36,10 @@
******************************************************************************/
static int
-nv50_sw_chan_vblsem_release(struct nvkm_notify *notify)
+nv50_sw_chan_vblsem_release(struct nvkm_event_ntfy *notify, u32 bits)
{
struct nv50_sw_chan *chan =
- container_of(notify, typeof(*chan), vblank.notify[notify->index]);
+ container_of(notify, typeof(*chan), vblank.notify[notify->id]);
struct nvkm_sw *sw = chan->base.sw;
struct nvkm_device *device = sw->engine.subdev.device;
@@ -55,7 +55,7 @@ nv50_sw_chan_vblsem_release(struct nvkm_notify *notify)
nvkm_wr32(device, 0x060014, chan->vblank.value);
}
- return NVKM_NOTIFY_DROP;
+ return NVKM_EVENT_DROP;
}
static bool
@@ -70,7 +70,7 @@ nv50_sw_chan_mthd(struct nvkm_sw_chan *base, int subc, u32 mthd, u32 data)
case 0x0404: chan->vblank.value = data; return true;
case 0x0408:
if (data < device->disp->vblank.index_nr) {
- nvkm_notify_get(&chan->vblank.notify[data]);
+ nvkm_event_ntfy_allow(&chan->vblank.notify[data]);
return true;
}
break;
@@ -85,8 +85,10 @@ nv50_sw_chan_dtor(struct nvkm_sw_chan *base)
{
struct nv50_sw_chan *chan = nv50_sw_chan(base);
int i;
+
for (i = 0; i < ARRAY_SIZE(chan->vblank.notify); i++)
- nvkm_notify_fini(&chan->vblank.notify[i]);
+ nvkm_event_ntfy_del(&chan->vblank.notify[i]);
+
return chan;
}
@@ -113,16 +115,8 @@ nv50_sw_chan_new(struct nvkm_sw *sw, struct nvkm_fifo_chan *fifoch,
return ret;
for (i = 0; disp && i < disp->vblank.index_nr; i++) {
- ret = nvkm_notify_init(NULL, &disp->vblank,
- nv50_sw_chan_vblsem_release, false,
- &(struct nvif_notify_head_req_v0) {
- .head = i,
- },
- sizeof(struct nvif_notify_head_req_v0),
- sizeof(struct nvif_notify_head_rep_v0),
- &chan->vblank.notify[i]);
- if (ret)
- return ret;
+ nvkm_event_ntfy_add(&disp->vblank, i, NVKM_DISP_HEAD_EVENT_VBLANK, true,
+ nv50_sw_chan_vblsem_release, &chan->vblank.notify[i]);
}
return 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h
index 6d364d7b406a..b42289ce8826 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nv50.h
@@ -5,12 +5,12 @@
#include "priv.h"
#include "chan.h"
#include "nvsw.h"
-#include <core/notify.h>
+#include <core/event.h>
struct nv50_sw_chan {
struct nvkm_sw_chan base;
struct {
- struct nvkm_notify notify[4];
+ struct nvkm_event_ntfy notify[4];
u32 ctxdma;
u64 offset;
u32 value;
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c
index 33dd03fff3c4..f5affa1c8f34 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.c
@@ -27,33 +27,34 @@
#include <nvif/if0004.h>
static int
-nvkm_nvsw_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size)
+nvkm_nvsw_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent)
{
- struct nvkm_nvsw *nvsw = nvkm_nvsw(object);
- if (nvsw->func->mthd)
- return nvsw->func->mthd(nvsw, mthd, data, size);
- return -ENODEV;
+ union nv04_nvsw_event_args *args = argv;
+
+ if (!uevent)
+ return 0;
+ if (argc != sizeof(args->vn))
+ return -ENOSYS;
+
+ return nvkm_uevent_add(uevent, &nvkm_nvsw(object)->chan->event, 0,
+ NVKM_SW_CHAN_EVENT_PAGE_FLIP, NULL);
}
static int
-nvkm_nvsw_ntfy_(struct nvkm_object *object, u32 mthd,
- struct nvkm_event **pevent)
+nvkm_nvsw_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
{
struct nvkm_nvsw *nvsw = nvkm_nvsw(object);
- switch (mthd) {
- case NV04_NVSW_NTFY_UEVENT:
- *pevent = &nvsw->chan->event;
- return 0;
- default:
- break;
- }
- return -EINVAL;
+
+ if (nvsw->func->mthd)
+ return nvsw->func->mthd(nvsw, mthd, data, size);
+
+ return -ENODEV;
}
static const struct nvkm_object_func
nvkm_nvsw_ = {
- .mthd = nvkm_nvsw_mthd_,
- .ntfy = nvkm_nvsw_ntfy_,
+ .mthd = nvkm_nvsw_mthd,
+ .uevent = nvkm_nvsw_uevent,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild b/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild
index d79d783904ee..9ffe7b921ccb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/Kbuild
@@ -1,6 +1,12 @@
# SPDX-License-Identifier: MIT
nvkm-y += nvkm/falcon/base.o
nvkm-y += nvkm/falcon/cmdq.o
+nvkm-y += nvkm/falcon/fw.o
nvkm-y += nvkm/falcon/msgq.o
nvkm-y += nvkm/falcon/qmgr.o
nvkm-y += nvkm/falcon/v1.o
+
+nvkm-y += nvkm/falcon/gm200.o
+nvkm-y += nvkm/falcon/gp102.o
+nvkm-y += nvkm/falcon/ga100.o
+nvkm-y += nvkm/falcon/ga102.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c
index f3f90c1063dd..235149f73a69 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c
@@ -22,119 +22,217 @@
#include "priv.h"
#include <subdev/mc.h>
+#include <subdev/timer.h>
#include <subdev/top.h>
-void
-nvkm_falcon_load_imem(struct nvkm_falcon *falcon, void *data, u32 start,
- u32 size, u16 tag, u8 port, bool secure)
+static const struct nvkm_falcon_func_dma *
+nvkm_falcon_dma(struct nvkm_falcon *falcon, enum nvkm_falcon_mem *mem_type, u32 *mem_base)
{
- if (secure && !falcon->secret) {
- nvkm_warn(falcon->user,
- "writing with secure tag on a non-secure falcon!\n");
- return;
+ switch (*mem_type) {
+ case IMEM: return falcon->func->imem_dma;
+ case DMEM: return falcon->func->dmem_dma;
+ default:
+ return NULL;
}
-
- falcon->func->load_imem(falcon, data, start, size, tag, port,
- secure);
}
-void
-nvkm_falcon_load_dmem(struct nvkm_falcon *falcon, void *data, u32 start,
- u32 size, u8 port)
+int
+nvkm_falcon_dma_wr(struct nvkm_falcon *falcon, const u8 *img, u64 dma_addr, u32 dma_base,
+ enum nvkm_falcon_mem mem_type, u32 mem_base, int len, bool sec)
{
- mutex_lock(&falcon->dmem_mutex);
-
- falcon->func->load_dmem(falcon, data, start, size, port);
+ const struct nvkm_falcon_func_dma *dma = nvkm_falcon_dma(falcon, &mem_type, &mem_base);
+ const char *type = nvkm_falcon_mem(mem_type);
+ const int dmalen = 256;
+ u32 dma_start = 0;
+ u32 dst, src, cmd;
+ int ret, i;
+
+ if (WARN_ON(!dma->xfer))
+ return -EINVAL;
+
+ if (mem_type == DMEM) {
+ dma_start = dma_base;
+ dma_addr += dma_base;
+ }
- mutex_unlock(&falcon->dmem_mutex);
-}
+ FLCN_DBG(falcon, "%s %08x <- %08x bytes at %08x (%010llx %08x)",
+ type, mem_base, len, dma_base, dma_addr - dma_base, dma_start);
+ if (WARN_ON(!len || (len & (dmalen - 1))))
+ return -EINVAL;
-void
-nvkm_falcon_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size, u8 port,
- void *data)
-{
- mutex_lock(&falcon->dmem_mutex);
+ ret = dma->init(falcon, dma_addr, dmalen, mem_type, sec, &cmd);
+ if (ret)
+ return ret;
- falcon->func->read_dmem(falcon, start, size, port, data);
+ dst = mem_base;
+ src = dma_base;
+ if (len) {
+ while (len >= dmalen) {
+ dma->xfer(falcon, dst, src - dma_start, cmd);
+
+ if (img && nvkm_printk_ok(falcon->owner, falcon->user, NV_DBG_TRACE)) {
+ for (i = 0; i < dmalen; i += 4, mem_base += 4) {
+ const int w = 8, x = (i / 4) % w;
+
+ if (x == 0)
+ printk(KERN_INFO "%s %08x <-", type, mem_base);
+ printk(KERN_CONT " %08x", *(u32 *)(img + src + i));
+ if (x == (w - 1) || ((i + 4) == dmalen))
+ printk(KERN_CONT " <- %08x+%08x", dma_base,
+ src + i - dma_base - (x * 4));
+ if (i == (7 * 4))
+ printk(KERN_CONT " *");
+ }
+ }
+
+ if (nvkm_msec(falcon->owner->device, 2000,
+ if (dma->done(falcon))
+ break;
+ ) < 0)
+ return -ETIMEDOUT;
+
+ src += dmalen;
+ dst += dmalen;
+ len -= dmalen;
+ }
+ WARN_ON(len);
+ }
- mutex_unlock(&falcon->dmem_mutex);
+ return 0;
}
-void
-nvkm_falcon_bind_context(struct nvkm_falcon *falcon, struct nvkm_memory *inst)
+static const struct nvkm_falcon_func_pio *
+nvkm_falcon_pio(struct nvkm_falcon *falcon, enum nvkm_falcon_mem *mem_type, u32 *mem_base)
{
- if (!falcon->func->bind_context) {
- nvkm_error(falcon->user,
- "Context binding not supported on this falcon!\n");
- return;
+ switch (*mem_type) {
+ case IMEM:
+ return falcon->func->imem_pio;
+ case DMEM:
+ if (!falcon->func->emem_addr || *mem_base < falcon->func->emem_addr)
+ return falcon->func->dmem_pio;
+
+ *mem_base -= falcon->func->emem_addr;
+ fallthrough;
+ case EMEM:
+ return falcon->func->emem_pio;
+ default:
+ return NULL;
}
-
- falcon->func->bind_context(falcon, inst);
}
-void
-nvkm_falcon_set_start_addr(struct nvkm_falcon *falcon, u32 start_addr)
+int
+nvkm_falcon_pio_rd(struct nvkm_falcon *falcon, u8 port, enum nvkm_falcon_mem mem_type, u32 mem_base,
+ const u8 *img, u32 img_base, int len)
{
- falcon->func->set_start_addr(falcon, start_addr);
-}
+ const struct nvkm_falcon_func_pio *pio = nvkm_falcon_pio(falcon, &mem_type, &mem_base);
+ const char *type = nvkm_falcon_mem(mem_type);
+ int xfer_len;
+
+ if (WARN_ON(!pio || !pio->rd))
+ return -EINVAL;
+
+ FLCN_DBG(falcon, "%s %08x -> %08x bytes at %08x", type, mem_base, len, img_base);
+ if (WARN_ON(!len || (len & (pio->min - 1))))
+ return -EINVAL;
+
+ pio->rd_init(falcon, port, mem_base);
+ do {
+ xfer_len = min(len, pio->max);
+ pio->rd(falcon, port, img, xfer_len);
+
+ if (nvkm_printk_ok(falcon->owner, falcon->user, NV_DBG_TRACE)) {
+ for (img_base = 0; img_base < xfer_len; img_base += 4, mem_base += 4) {
+ if (((img_base / 4) % 8) == 0)
+ printk(KERN_INFO "%s %08x ->", type, mem_base);
+ printk(KERN_CONT " %08x", *(u32 *)(img + img_base));
+ }
+ }
+
+ img += xfer_len;
+ len -= xfer_len;
+ } while (len);
-void
-nvkm_falcon_start(struct nvkm_falcon *falcon)
-{
- falcon->func->start(falcon);
+ return 0;
}
int
-nvkm_falcon_enable(struct nvkm_falcon *falcon)
+nvkm_falcon_pio_wr(struct nvkm_falcon *falcon, const u8 *img, u32 img_base, u8 port,
+ enum nvkm_falcon_mem mem_type, u32 mem_base, int len, u16 tag, bool sec)
{
- struct nvkm_device *device = falcon->owner->device;
- int ret;
-
- nvkm_mc_enable(device, falcon->owner->type, falcon->owner->inst);
- ret = falcon->func->enable(falcon);
- if (ret) {
- nvkm_mc_disable(device, falcon->owner->type, falcon->owner->inst);
- return ret;
- }
+ const struct nvkm_falcon_func_pio *pio = nvkm_falcon_pio(falcon, &mem_type, &mem_base);
+ const char *type = nvkm_falcon_mem(mem_type);
+ int xfer_len;
+
+ if (WARN_ON(!pio || !pio->wr))
+ return -EINVAL;
+
+ FLCN_DBG(falcon, "%s %08x <- %08x bytes at %08x", type, mem_base, len, img_base);
+ if (WARN_ON(!len || (len & (pio->min - 1))))
+ return -EINVAL;
+
+ pio->wr_init(falcon, port, sec, mem_base);
+ do {
+ xfer_len = min(len, pio->max);
+ pio->wr(falcon, port, img, xfer_len, tag++);
+
+ if (nvkm_printk_ok(falcon->owner, falcon->user, NV_DBG_TRACE)) {
+ for (img_base = 0; img_base < xfer_len; img_base += 4, mem_base += 4) {
+ if (((img_base / 4) % 8) == 0)
+ printk(KERN_INFO "%s %08x <-", type, mem_base);
+ printk(KERN_CONT " %08x", *(u32 *)(img + img_base));
+ if ((img_base / 4) == 7 && mem_type == IMEM)
+ printk(KERN_CONT " %04x", tag - 1);
+ }
+ }
+
+ img += xfer_len;
+ len -= xfer_len;
+ } while (len);
return 0;
}
void
-nvkm_falcon_disable(struct nvkm_falcon *falcon)
+nvkm_falcon_load_imem(struct nvkm_falcon *falcon, void *data, u32 start,
+ u32 size, u16 tag, u8 port, bool secure)
{
- struct nvkm_device *device = falcon->owner->device;
-
- /* already disabled, return or wait_idle will timeout */
- if (!nvkm_mc_enabled(device, falcon->owner->type, falcon->owner->inst))
+ if (secure && !falcon->secret) {
+ nvkm_warn(falcon->user,
+ "writing with secure tag on a non-secure falcon!\n");
return;
+ }
- falcon->func->disable(falcon);
-
- nvkm_mc_disable(device, falcon->owner->type, falcon->owner->inst);
+ falcon->func->load_imem(falcon, data, start, size, tag, port,
+ secure);
}
-int
-nvkm_falcon_reset(struct nvkm_falcon *falcon)
+void
+nvkm_falcon_load_dmem(struct nvkm_falcon *falcon, void *data, u32 start,
+ u32 size, u8 port)
{
- if (!falcon->func->reset) {
- nvkm_falcon_disable(falcon);
- return nvkm_falcon_enable(falcon);
- }
+ mutex_lock(&falcon->dmem_mutex);
- return falcon->func->reset(falcon);
+ falcon->func->load_dmem(falcon, data, start, size, port);
+
+ mutex_unlock(&falcon->dmem_mutex);
}
-int
-nvkm_falcon_wait_for_halt(struct nvkm_falcon *falcon, u32 ms)
+void
+nvkm_falcon_start(struct nvkm_falcon *falcon)
{
- return falcon->func->wait_for_halt(falcon, ms);
+ falcon->func->start(falcon);
}
int
-nvkm_falcon_clear_interrupt(struct nvkm_falcon *falcon, u32 mask)
+nvkm_falcon_reset(struct nvkm_falcon *falcon)
{
- return falcon->func->clear_interrupt(falcon, mask);
+ int ret;
+
+ ret = falcon->func->disable(falcon);
+ if (WARN_ON(ret))
+ return ret;
+
+ return nvkm_falcon_enable(falcon);
}
static int
@@ -169,7 +267,7 @@ nvkm_falcon_oneinit(struct nvkm_falcon *falcon)
}
void
-nvkm_falcon_put(struct nvkm_falcon *falcon, const struct nvkm_subdev *user)
+nvkm_falcon_put(struct nvkm_falcon *falcon, struct nvkm_subdev *user)
{
if (unlikely(!falcon))
return;
@@ -183,7 +281,7 @@ nvkm_falcon_put(struct nvkm_falcon *falcon, const struct nvkm_subdev *user)
}
int
-nvkm_falcon_get(struct nvkm_falcon *falcon, const struct nvkm_subdev *user)
+nvkm_falcon_get(struct nvkm_falcon *falcon, struct nvkm_subdev *user)
{
int ret = 0;
@@ -217,6 +315,7 @@ nvkm_falcon_ctor(const struct nvkm_falcon_func *func,
falcon->owner = subdev;
falcon->name = name;
falcon->addr = addr;
+ falcon->addr2 = func->addr2;
mutex_init(&falcon->mutex);
mutex_init(&falcon->dmem_mutex);
return 0;
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c
index 44cf6a8862e1..211ebe7afac6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/cmdq.c
@@ -51,7 +51,7 @@ static void
nvkm_falcon_cmdq_push(struct nvkm_falcon_cmdq *cmdq, void *data, u32 size)
{
struct nvkm_falcon *falcon = cmdq->qmgr->falcon;
- nvkm_falcon_load_dmem(falcon, data, cmdq->position, size, 0);
+ nvkm_falcon_pio_wr(falcon, data, 0, 0, DMEM, cmdq->position, size, 0, false);
cmdq->position += ALIGN(size, QUEUE_ALIGNMENT);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c b/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c
new file mode 100644
index 000000000000..80a480b12174
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/fw.c
@@ -0,0 +1,354 @@
+/*
+ * Copyright 2022 Red Hat 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 "priv.h"
+
+#include <core/memory.h>
+#include <subdev/mmu.h>
+
+#include <nvfw/fw.h>
+#include <nvfw/hs.h>
+
+int
+nvkm_falcon_fw_patch(struct nvkm_falcon_fw *fw)
+{
+ struct nvkm_falcon *falcon = fw->falcon;
+ u32 sig_base_src = fw->sig_base_prd;
+ u32 src, dst, len, i;
+ int idx = 0;
+
+ FLCNFW_DBG(fw, "patching sigs:%d size:%d", fw->sig_nr, fw->sig_size);
+ if (fw->func->signature) {
+ idx = fw->func->signature(fw, &sig_base_src);
+ if (idx < 0)
+ return idx;
+ }
+
+ src = idx * fw->sig_size;
+ dst = fw->sig_base_img;
+ len = fw->sig_size / 4;
+ FLCNFW_DBG(fw, "patch idx:%d src:%08x dst:%08x", idx, sig_base_src + src, dst);
+ for (i = 0; i < len; i++) {
+ u32 sig = *(u32 *)(fw->sigs + src);
+
+ if (nvkm_printk_ok(falcon->owner, falcon->user, NV_DBG_TRACE)) {
+ if (i % 8 == 0)
+ printk(KERN_INFO "sig -> %08x:", dst);
+ printk(KERN_CONT " %08x", sig);
+ }
+
+ *(u32 *)(fw->fw.img + dst) = sig;
+ src += 4;
+ dst += 4;
+ }
+
+ return 0;
+}
+
+static void
+nvkm_falcon_fw_dtor_sigs(struct nvkm_falcon_fw *fw)
+{
+ kfree(fw->sigs);
+ fw->sigs = NULL;
+}
+
+int
+nvkm_falcon_fw_boot(struct nvkm_falcon_fw *fw, struct nvkm_subdev *user,
+ bool release, u32 *pmbox0, u32 *pmbox1, u32 mbox0_ok, u32 irqsclr)
+{
+ struct nvkm_falcon *falcon = fw->falcon;
+ int ret;
+
+ ret = nvkm_falcon_get(falcon, user);
+ if (ret)
+ return ret;
+
+ if (fw->sigs) {
+ ret = nvkm_falcon_fw_patch(fw);
+ if (ret)
+ goto done;
+
+ nvkm_falcon_fw_dtor_sigs(fw);
+ }
+
+ FLCNFW_DBG(fw, "resetting");
+ fw->func->reset(fw);
+
+ FLCNFW_DBG(fw, "loading");
+ if (fw->func->setup) {
+ ret = fw->func->setup(fw);
+ if (ret)
+ goto done;
+ }
+
+ ret = fw->func->load(fw);
+ if (ret)
+ goto done;
+
+ FLCNFW_DBG(fw, "booting");
+ ret = fw->func->boot(fw, pmbox0, pmbox1, mbox0_ok, irqsclr);
+ if (ret)
+ FLCNFW_ERR(fw, "boot failed: %d", ret);
+ else
+ FLCNFW_DBG(fw, "booted");
+
+done:
+ if (ret || release)
+ nvkm_falcon_put(falcon, user);
+ return ret;
+}
+
+int
+nvkm_falcon_fw_oneinit(struct nvkm_falcon_fw *fw, struct nvkm_falcon *falcon,
+ struct nvkm_vmm *vmm, struct nvkm_memory *inst)
+{
+ int ret;
+
+ fw->falcon = falcon;
+ fw->vmm = nvkm_vmm_ref(vmm);
+ fw->inst = nvkm_memory_ref(inst);
+
+ if (fw->boot) {
+ FLCN_DBG(falcon, "mapping %s fw", fw->fw.name);
+ ret = nvkm_vmm_get(fw->vmm, 12, nvkm_memory_size(&fw->fw.mem.memory), &fw->vma);
+ if (ret) {
+ FLCN_ERR(falcon, "get %d", ret);
+ return ret;
+ }
+
+ ret = nvkm_memory_map(&fw->fw.mem.memory, 0, fw->vmm, fw->vma, NULL, 0);
+ if (ret) {
+ FLCN_ERR(falcon, "map %d", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+void
+nvkm_falcon_fw_dtor(struct nvkm_falcon_fw *fw)
+{
+ nvkm_vmm_put(fw->vmm, &fw->vma);
+ nvkm_vmm_unref(&fw->vmm);
+ nvkm_memory_unref(&fw->inst);
+ nvkm_falcon_fw_dtor_sigs(fw);
+ nvkm_firmware_dtor(&fw->fw);
+}
+
+static const struct nvkm_firmware_func
+nvkm_falcon_fw_dma = {
+ .type = NVKM_FIRMWARE_IMG_DMA,
+};
+
+static const struct nvkm_firmware_func
+nvkm_falcon_fw = {
+ .type = NVKM_FIRMWARE_IMG_RAM,
+};
+
+int
+nvkm_falcon_fw_sign(struct nvkm_falcon_fw *fw, u32 sig_base_img, u32 sig_size, const u8 *sigs,
+ int sig_nr_prd, u32 sig_base_prd, int sig_nr_dbg, u32 sig_base_dbg)
+{
+ fw->sig_base_prd = sig_base_prd;
+ fw->sig_base_dbg = sig_base_dbg;
+ fw->sig_base_img = sig_base_img;
+ fw->sig_size = sig_size;
+ fw->sig_nr = sig_nr_prd + sig_nr_dbg;
+
+ fw->sigs = kmalloc_array(fw->sig_nr, fw->sig_size, GFP_KERNEL);
+ if (!fw->sigs)
+ return -ENOMEM;
+
+ memcpy(fw->sigs, sigs + sig_base_prd, sig_nr_prd * fw->sig_size);
+ if (sig_nr_dbg)
+ memcpy(fw->sigs + sig_size, sigs + sig_base_dbg, sig_nr_dbg * fw->sig_size);
+
+ return 0;
+}
+
+int
+nvkm_falcon_fw_ctor(const struct nvkm_falcon_fw_func *func, const char *name,
+ struct nvkm_device *device, bool dma, const void *src, u32 len,
+ struct nvkm_falcon *falcon, struct nvkm_falcon_fw *fw)
+{
+ const struct nvkm_firmware_func *type = dma ? &nvkm_falcon_fw_dma : &nvkm_falcon_fw;
+ int ret;
+
+ fw->func = func;
+
+ ret = nvkm_firmware_ctor(type, name, device, src, len, &fw->fw);
+ if (ret)
+ return ret;
+
+ return falcon ? nvkm_falcon_fw_oneinit(fw, falcon, NULL, NULL) : 0;
+}
+
+int
+nvkm_falcon_fw_ctor_hs(const struct nvkm_falcon_fw_func *func, const char *name,
+ struct nvkm_subdev *subdev, const char *bl, const char *img, int ver,
+ struct nvkm_falcon *falcon, struct nvkm_falcon_fw *fw)
+{
+ const struct firmware *blob;
+ const struct nvfw_bin_hdr *hdr;
+ const struct nvfw_hs_header *hshdr;
+ const struct nvfw_hs_load_header *lhdr;
+ const struct nvfw_bl_desc *desc;
+ u32 loc, sig;
+ int ret;
+
+ ret = nvkm_firmware_load_name(subdev, img, "", ver, &blob);
+ if (ret)
+ return ret;
+
+ hdr = nvfw_bin_hdr(subdev, blob->data);
+ hshdr = nvfw_hs_header(subdev, blob->data + hdr->header_offset);
+
+ ret = nvkm_falcon_fw_ctor(func, name, subdev->device, bl != NULL,
+ blob->data + hdr->data_offset, hdr->data_size, falcon, fw);
+ if (ret)
+ goto done;
+
+ /* Earlier FW releases by NVIDIA for Nouveau's use aren't in NVIDIA's
+ * standard format, and don't have the indirection seen in the 0x10de
+ * case.
+ */
+ switch (hdr->bin_magic) {
+ case 0x000010de:
+ loc = *(u32 *)(blob->data + hshdr->patch_loc);
+ sig = *(u32 *)(blob->data + hshdr->patch_sig);
+ break;
+ case 0x3b1d14f0:
+ loc = hshdr->patch_loc;
+ sig = hshdr->patch_sig;
+ break;
+ default:
+ WARN_ON(1);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = nvkm_falcon_fw_sign(fw, loc, hshdr->sig_prod_size, blob->data,
+ 1, hshdr->sig_prod_offset + sig,
+ 1, hshdr->sig_dbg_offset + sig);
+ if (ret)
+ goto done;
+
+ lhdr = nvfw_hs_load_header(subdev, blob->data + hshdr->hdr_offset);
+
+ fw->nmem_base_img = 0;
+ fw->nmem_base = lhdr->non_sec_code_off;
+ fw->nmem_size = lhdr->non_sec_code_size;
+
+ fw->imem_base_img = lhdr->apps[0];
+ fw->imem_base = ALIGN(lhdr->apps[0], 0x100);
+ fw->imem_size = lhdr->apps[lhdr->num_apps + 0];
+
+ fw->dmem_base_img = lhdr->data_dma_base;
+ fw->dmem_base = 0;
+ fw->dmem_size = lhdr->data_size;
+ fw->dmem_sign = loc - lhdr->data_dma_base;
+
+ if (bl) {
+ nvkm_firmware_put(blob);
+
+ ret = nvkm_firmware_load_name(subdev, bl, "", ver, &blob);
+ if (ret)
+ return ret;
+
+ hdr = nvfw_bin_hdr(subdev, blob->data);
+ desc = nvfw_bl_desc(subdev, blob->data + hdr->header_offset);
+
+ fw->boot_addr = desc->start_tag << 8;
+ fw->boot_size = desc->code_size;
+ fw->boot = kmemdup(blob->data + hdr->data_offset + desc->code_off,
+ fw->boot_size, GFP_KERNEL);
+ if (!fw->boot)
+ ret = -ENOMEM;
+ } else {
+ fw->boot_addr = fw->nmem_base;
+ }
+
+done:
+ if (ret)
+ nvkm_falcon_fw_dtor(fw);
+
+ nvkm_firmware_put(blob);
+ return ret;
+}
+
+int
+nvkm_falcon_fw_ctor_hs_v2(const struct nvkm_falcon_fw_func *func, const char *name,
+ struct nvkm_subdev *subdev, const char *img, int ver,
+ struct nvkm_falcon *falcon, struct nvkm_falcon_fw *fw)
+{
+ const struct nvfw_bin_hdr *hdr;
+ const struct nvfw_hs_header_v2 *hshdr;
+ const struct nvfw_hs_load_header_v2 *lhdr;
+ const struct firmware *blob;
+ u32 loc, sig, cnt, *meta;
+ int ret;
+
+ ret = nvkm_firmware_load_name(subdev, img, "", ver, &blob);
+ if (ret)
+ return ret;
+
+ hdr = nvfw_bin_hdr(subdev, blob->data);
+ hshdr = nvfw_hs_header_v2(subdev, blob->data + hdr->header_offset);
+ meta = (u32 *)(blob->data + hshdr->meta_data_offset);
+ loc = *(u32 *)(blob->data + hshdr->patch_loc);
+ sig = *(u32 *)(blob->data + hshdr->patch_sig);
+ cnt = *(u32 *)(blob->data + hshdr->num_sig);
+
+ ret = nvkm_falcon_fw_ctor(func, name, subdev->device, true,
+ blob->data + hdr->data_offset, hdr->data_size, falcon, fw);
+ if (ret)
+ goto done;
+
+ ret = nvkm_falcon_fw_sign(fw, loc, hshdr->sig_prod_size / cnt, blob->data,
+ cnt, hshdr->sig_prod_offset + sig, 0, 0);
+ if (ret)
+ goto done;
+
+ lhdr = nvfw_hs_load_header_v2(subdev, blob->data + hshdr->header_offset);
+
+ fw->imem_base_img = lhdr->app[0].offset;
+ fw->imem_base = 0;
+ fw->imem_size = lhdr->app[0].size;
+
+ fw->dmem_base_img = lhdr->os_data_offset;
+ fw->dmem_base = 0;
+ fw->dmem_size = lhdr->os_data_size;
+ fw->dmem_sign = loc - lhdr->os_data_offset;
+
+ fw->boot_addr = lhdr->app[0].offset;
+
+ fw->fuse_ver = meta[0];
+ fw->engine_id = meta[1];
+ fw->ucode_id = meta[2];
+
+done:
+ if (ret)
+ nvkm_falcon_fw_dtor(fw);
+
+ nvkm_firmware_put(blob);
+ return ret;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/ga100.c b/drivers/gpu/drm/nouveau/nvkm/falcon/ga100.c
new file mode 100644
index 000000000000..49fd32943916
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/ga100.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2021 Red Hat 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 "priv.h"
+
+int
+ga100_flcn_fw_signature(struct nvkm_falcon_fw *fw, u32 *src_base_src)
+{
+ struct nvkm_falcon *falcon = fw->falcon;
+ struct nvkm_device *device = falcon->owner->device;
+ u32 reg_fuse_version;
+ int idx;
+
+ FLCN_DBG(falcon, "brom: %08x %08x", fw->engine_id, fw->ucode_id);
+ FLCN_DBG(falcon, "fuse_version: %d", fw->fuse_ver);
+
+ if (fw->engine_id & 0x00000001) {
+ reg_fuse_version = nvkm_rd32(device, 0x824140 + (fw->ucode_id - 1) * 4);
+ } else
+ if (fw->engine_id & 0x00000004) {
+ reg_fuse_version = nvkm_rd32(device, 0x824100 + (fw->ucode_id - 1) * 4);
+ } else
+ if (fw->engine_id & 0x00000400) {
+ reg_fuse_version = nvkm_rd32(device, 0x8241c0 + (fw->ucode_id - 1) * 4);
+ } else {
+ WARN_ON(1);
+ return -ENOSYS;
+ }
+
+ FLCN_DBG(falcon, "reg_fuse_version: %08x", reg_fuse_version);
+ if (reg_fuse_version) {
+ reg_fuse_version = fls(reg_fuse_version);
+ FLCN_DBG(falcon, "reg_fuse_version: %d", reg_fuse_version);
+
+ if (WARN_ON(fw->fuse_ver < reg_fuse_version))
+ return -EINVAL;
+
+ idx = fw->fuse_ver - reg_fuse_version;
+ } else {
+ idx = fw->sig_nr - 1;
+ }
+
+ return idx;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/ga102.c b/drivers/gpu/drm/nouveau/nvkm/falcon/ga102.c
new file mode 100644
index 000000000000..0ff450fe3590
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/ga102.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2022 Red Hat 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 "priv.h"
+
+#include <subdev/mc.h>
+#include <subdev/timer.h>
+
+static bool
+ga102_flcn_dma_done(struct nvkm_falcon *falcon)
+{
+ return !!(nvkm_falcon_rd32(falcon, 0x118) & 0x00000002);
+}
+
+static void
+ga102_flcn_dma_xfer(struct nvkm_falcon *falcon, u32 mem_base, u32 dma_base, u32 cmd)
+{
+ nvkm_falcon_wr32(falcon, 0x114, mem_base);
+ nvkm_falcon_wr32(falcon, 0x11c, dma_base);
+ nvkm_falcon_wr32(falcon, 0x118, cmd);
+}
+
+static int
+ga102_flcn_dma_init(struct nvkm_falcon *falcon, u64 dma_addr, int xfer_len,
+ enum nvkm_falcon_mem mem_type, bool sec, u32 *cmd)
+{
+ *cmd = (ilog2(xfer_len) - 2) << 8;
+ if (mem_type == IMEM)
+ *cmd |= 0x00000010;
+ if (sec)
+ *cmd |= 0x00000004;
+
+ nvkm_falcon_wr32(falcon, 0x110, dma_addr >> 8);
+ nvkm_falcon_wr32(falcon, 0x128, 0x00000000);
+ return 0;
+}
+
+const struct nvkm_falcon_func_dma
+ga102_flcn_dma = {
+ .init = ga102_flcn_dma_init,
+ .xfer = ga102_flcn_dma_xfer,
+ .done = ga102_flcn_dma_done,
+};
+
+int
+ga102_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *falcon)
+{
+ nvkm_falcon_mask(falcon, 0x040, 0x00000000, 0x00000000);
+
+ if (nvkm_msec(falcon->owner->device, 20,
+ if (!(nvkm_falcon_rd32(falcon, 0x0f4) & 0x00001000))
+ break;
+ ) < 0)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+int
+ga102_flcn_reset_prep(struct nvkm_falcon *falcon)
+{
+ nvkm_falcon_rd32(falcon, 0x0f4);
+
+ nvkm_usec(falcon->owner->device, 150,
+ if (nvkm_falcon_rd32(falcon, 0x0f4) & 0x80000000)
+ break;
+ _warn = false;
+ );
+
+ return 0;
+}
+
+int
+ga102_flcn_select(struct nvkm_falcon *falcon)
+{
+ if ((nvkm_falcon_rd32(falcon, falcon->addr2 + 0x668) & 0x00000010) != 0x00000000) {
+ nvkm_falcon_wr32(falcon, falcon->addr2 + 0x668, 0x00000000);
+ if (nvkm_msec(falcon->owner->device, 10,
+ if (nvkm_falcon_rd32(falcon, falcon->addr2 + 0x668) & 0x00000001)
+ break;
+ ) < 0)
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+int
+ga102_flcn_fw_boot(struct nvkm_falcon_fw *fw, u32 *mbox0, u32 *mbox1, u32 mbox0_ok, u32 irqsclr)
+{
+ struct nvkm_falcon *falcon = fw->falcon;
+
+ nvkm_falcon_wr32(falcon, falcon->addr2 + 0x210, fw->dmem_sign);
+ nvkm_falcon_wr32(falcon, falcon->addr2 + 0x19c, fw->engine_id);
+ nvkm_falcon_wr32(falcon, falcon->addr2 + 0x198, fw->ucode_id);
+ nvkm_falcon_wr32(falcon, falcon->addr2 + 0x180, 0x00000001);
+
+ return gm200_flcn_fw_boot(fw, mbox0, mbox1, mbox0_ok, irqsclr);
+}
+
+int
+ga102_flcn_fw_load(struct nvkm_falcon_fw *fw)
+{
+ struct nvkm_falcon *falcon = fw->falcon;
+ int ret = 0;
+
+ nvkm_falcon_mask(falcon, 0x624, 0x00000080, 0x00000080);
+ nvkm_falcon_wr32(falcon, 0x10c, 0x00000000);
+ nvkm_falcon_mask(falcon, 0x600, 0x00010007, (0 << 16) | (1 << 2) | 1);
+
+ ret = nvkm_falcon_dma_wr(falcon, fw->fw.img, fw->fw.phys, fw->imem_base_img,
+ IMEM, fw->imem_base, fw->imem_size, true);
+ if (ret)
+ return ret;
+
+ ret = nvkm_falcon_dma_wr(falcon, fw->fw.img, fw->fw.phys, fw->dmem_base_img,
+ DMEM, fw->dmem_base, fw->dmem_size, false);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+const struct nvkm_falcon_fw_func
+ga102_flcn_fw = {
+ .signature = ga100_flcn_fw_signature,
+ .reset = gm200_flcn_fw_reset,
+ .load = ga102_flcn_fw_load,
+ .boot = ga102_flcn_fw_boot,
+};
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c
new file mode 100644
index 000000000000..393ade9f7e6c
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/gm200.c
@@ -0,0 +1,345 @@
+/*
+ * Copyright 2022 Red Hat 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 "priv.h"
+
+#include <core/memory.h>
+#include <subdev/mc.h>
+#include <subdev/timer.h>
+
+void
+gm200_flcn_tracepc(struct nvkm_falcon *falcon)
+{
+ u32 sctl = nvkm_falcon_rd32(falcon, 0x240);
+ u32 tidx = nvkm_falcon_rd32(falcon, 0x148);
+ int nr = (tidx & 0x00ff0000) >> 16, sp, ip;
+
+ FLCN_ERR(falcon, "TRACEPC SCTL %08x TIDX %08x", sctl, tidx);
+ for (sp = 0; sp < nr; sp++) {
+ nvkm_falcon_wr32(falcon, 0x148, sp);
+ ip = nvkm_falcon_rd32(falcon, 0x14c);
+ FLCN_ERR(falcon, "TRACEPC: %08x", ip);
+ }
+}
+
+static void
+gm200_flcn_pio_dmem_rd(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len)
+{
+ while (len >= 4) {
+ *(u32 *)img = nvkm_falcon_rd32(falcon, 0x1c4 + (port * 8));
+ img += 4;
+ len -= 4;
+ }
+}
+
+static void
+gm200_flcn_pio_dmem_rd_init(struct nvkm_falcon *falcon, u8 port, u32 dmem_base)
+{
+ nvkm_falcon_wr32(falcon, 0x1c0 + (port * 8), BIT(25) | dmem_base);
+}
+
+static void
+gm200_flcn_pio_dmem_wr(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len, u16 tag)
+{
+ while (len >= 4) {
+ nvkm_falcon_wr32(falcon, 0x1c4 + (port * 8), *(u32 *)img);
+ img += 4;
+ len -= 4;
+ }
+}
+
+static void
+gm200_flcn_pio_dmem_wr_init(struct nvkm_falcon *falcon, u8 port, bool sec, u32 dmem_base)
+{
+ nvkm_falcon_wr32(falcon, 0x1c0 + (port * 8), BIT(24) | dmem_base);
+}
+
+const struct nvkm_falcon_func_pio
+gm200_flcn_dmem_pio = {
+ .min = 4,
+ .max = 0x100,
+ .wr_init = gm200_flcn_pio_dmem_wr_init,
+ .wr = gm200_flcn_pio_dmem_wr,
+ .rd_init = gm200_flcn_pio_dmem_rd_init,
+ .rd = gm200_flcn_pio_dmem_rd,
+};
+
+static void
+gm200_flcn_pio_imem_wr_init(struct nvkm_falcon *falcon, u8 port, bool sec, u32 imem_base)
+{
+ nvkm_falcon_wr32(falcon, 0x180 + (port * 0x10), (sec ? BIT(28) : 0) | BIT(24) | imem_base);
+}
+
+static void
+gm200_flcn_pio_imem_wr(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len, u16 tag)
+{
+ nvkm_falcon_wr32(falcon, 0x188 + (port * 0x10), tag++);
+ while (len >= 4) {
+ nvkm_falcon_wr32(falcon, 0x184 + (port * 0x10), *(u32 *)img);
+ img += 4;
+ len -= 4;
+ }
+}
+
+const struct nvkm_falcon_func_pio
+gm200_flcn_imem_pio = {
+ .min = 0x100,
+ .max = 0x100,
+ .wr_init = gm200_flcn_pio_imem_wr_init,
+ .wr = gm200_flcn_pio_imem_wr,
+};
+
+int
+gm200_flcn_bind_stat(struct nvkm_falcon *falcon, bool intr)
+{
+ if (intr && !(nvkm_falcon_rd32(falcon, 0x008) & 0x00000008))
+ return -1;
+
+ return (nvkm_falcon_rd32(falcon, 0x0dc) & 0x00007000) >> 12;
+}
+
+void
+gm200_flcn_bind_inst(struct nvkm_falcon *falcon, int target, u64 addr)
+{
+ nvkm_falcon_mask(falcon, 0x604, 0x00000007, 0x00000000); /* DMAIDX_VIRT */
+ nvkm_falcon_wr32(falcon, 0x054, (1 << 30) | (target << 28) | (addr >> 12));
+ nvkm_falcon_mask(falcon, 0x090, 0x00010000, 0x00010000);
+ nvkm_falcon_mask(falcon, 0x0a4, 0x00000008, 0x00000008);
+}
+
+int
+gm200_flcn_reset_wait_mem_scrubbing(struct nvkm_falcon *falcon)
+{
+ nvkm_falcon_mask(falcon, 0x040, 0x00000000, 0x00000000);
+
+ if (nvkm_msec(falcon->owner->device, 10,
+ if (!(nvkm_falcon_rd32(falcon, 0x10c) & 0x00000006))
+ break;
+ ) < 0)
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+int
+gm200_flcn_enable(struct nvkm_falcon *falcon)
+{
+ struct nvkm_device *device = falcon->owner->device;
+ int ret;
+
+ if (falcon->func->reset_eng) {
+ ret = falcon->func->reset_eng(falcon);
+ if (ret)
+ return ret;
+ }
+
+ if (falcon->func->select) {
+ ret = falcon->func->select(falcon);
+ if (ret)
+ return ret;
+ }
+
+ if (falcon->func->reset_pmc)
+ nvkm_mc_enable(device, falcon->owner->type, falcon->owner->inst);
+
+ ret = falcon->func->reset_wait_mem_scrubbing(falcon);
+ if (ret)
+ return ret;
+
+ nvkm_falcon_wr32(falcon, 0x084, nvkm_rd32(device, 0x000000));
+ return 0;
+}
+
+int
+gm200_flcn_disable(struct nvkm_falcon *falcon)
+{
+ struct nvkm_device *device = falcon->owner->device;
+ int ret;
+
+ if (falcon->func->select) {
+ ret = falcon->func->select(falcon);
+ if (ret)
+ return ret;
+ }
+
+ nvkm_falcon_mask(falcon, 0x048, 0x00000003, 0x00000000);
+ nvkm_falcon_wr32(falcon, 0x014, 0xffffffff);
+
+ if (falcon->func->reset_pmc) {
+ if (falcon->func->reset_prep) {
+ ret = falcon->func->reset_prep(falcon);
+ if (ret)
+ return ret;
+ }
+
+ nvkm_mc_disable(device, falcon->owner->type, falcon->owner->inst);
+ }
+
+ if (falcon->func->reset_eng) {
+ ret = falcon->func->reset_eng(falcon);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+int
+gm200_flcn_fw_boot(struct nvkm_falcon_fw *fw, u32 *pmbox0, u32 *pmbox1, u32 mbox0_ok, u32 irqsclr)
+{
+ struct nvkm_falcon *falcon = fw->falcon;
+ u32 mbox0, mbox1;
+ int ret = 0;
+
+ nvkm_falcon_wr32(falcon, 0x040, pmbox0 ? *pmbox0 : 0xcafebeef);
+ if (pmbox1)
+ nvkm_falcon_wr32(falcon, 0x044, *pmbox1);
+
+ nvkm_falcon_wr32(falcon, 0x104, fw->boot_addr);
+ nvkm_falcon_wr32(falcon, 0x100, 0x00000002);
+
+ if (nvkm_msec(falcon->owner->device, 2000,
+ if (nvkm_falcon_rd32(falcon, 0x100) & 0x00000010)
+ break;
+ ) < 0)
+ ret = -ETIMEDOUT;
+
+ mbox0 = nvkm_falcon_rd32(falcon, 0x040);
+ mbox1 = nvkm_falcon_rd32(falcon, 0x044);
+ if (FLCN_ERRON(falcon, ret || mbox0 != mbox0_ok, "mbox %08x %08x", mbox0, mbox1))
+ ret = ret ?: -EIO;
+
+ if (irqsclr)
+ nvkm_falcon_mask(falcon, 0x004, 0xffffffff, irqsclr);
+
+ return ret;
+}
+
+int
+gm200_flcn_fw_load(struct nvkm_falcon_fw *fw)
+{
+ struct nvkm_falcon *falcon = fw->falcon;
+ int target, ret;
+
+ if (fw->inst) {
+ nvkm_falcon_mask(falcon, 0x048, 0x00000001, 0x00000001);
+
+ switch (nvkm_memory_target(fw->inst)) {
+ case NVKM_MEM_TARGET_VRAM: target = 0; break;
+ case NVKM_MEM_TARGET_HOST: target = 2; break;
+ case NVKM_MEM_TARGET_NCOH: target = 3; break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ falcon->func->bind_inst(falcon, target, nvkm_memory_addr(fw->inst));
+
+ if (nvkm_msec(falcon->owner->device, 10,
+ if (falcon->func->bind_stat(falcon, falcon->func->bind_intr) == 5)
+ break;
+ ) < 0)
+ return -ETIMEDOUT;
+
+ nvkm_falcon_mask(falcon, 0x004, 0x00000008, 0x00000008);
+ nvkm_falcon_mask(falcon, 0x058, 0x00000002, 0x00000002);
+
+ if (nvkm_msec(falcon->owner->device, 10,
+ if (falcon->func->bind_stat(falcon, false) == 0)
+ break;
+ ) < 0)
+ return -ETIMEDOUT;
+ } else {
+ nvkm_falcon_mask(falcon, 0x624, 0x00000080, 0x00000080);
+ nvkm_falcon_wr32(falcon, 0x10c, 0x00000000);
+ }
+
+ if (fw->boot) {
+ switch (nvkm_memory_target(&fw->fw.mem.memory)) {
+ case NVKM_MEM_TARGET_VRAM: target = 4; break;
+ case NVKM_MEM_TARGET_HOST: target = 5; break;
+ case NVKM_MEM_TARGET_NCOH: target = 6; break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ ret = nvkm_falcon_pio_wr(falcon, fw->boot, 0, 0,
+ IMEM, falcon->code.limit - fw->boot_size, fw->boot_size,
+ fw->boot_addr >> 8, false);
+ if (ret)
+ return ret;
+
+ return fw->func->load_bld(fw);
+ }
+
+ ret = nvkm_falcon_pio_wr(falcon, fw->fw.img + fw->nmem_base_img, fw->nmem_base_img, 0,
+ IMEM, fw->nmem_base, fw->nmem_size, fw->nmem_base >> 8, false);
+ if (ret)
+ return ret;
+
+ ret = nvkm_falcon_pio_wr(falcon, fw->fw.img + fw->imem_base_img, fw->imem_base_img, 0,
+ IMEM, fw->imem_base, fw->imem_size, fw->imem_base >> 8, true);
+ if (ret)
+ return ret;
+
+ ret = nvkm_falcon_pio_wr(falcon, fw->fw.img + fw->dmem_base_img, fw->dmem_base_img, 0,
+ DMEM, fw->dmem_base, fw->dmem_size, 0, false);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int
+gm200_flcn_fw_reset(struct nvkm_falcon_fw *fw)
+{
+ return nvkm_falcon_reset(fw->falcon);
+}
+
+int
+gm200_flcn_fw_signature(struct nvkm_falcon_fw *fw, u32 *sig_base_src)
+{
+ struct nvkm_falcon *falcon = fw->falcon;
+ u32 addr = falcon->func->debug;
+ int ret = 0;
+
+ if (addr) {
+ ret = nvkm_falcon_enable(falcon);
+ if (ret)
+ return ret;
+
+ if (nvkm_falcon_rd32(falcon, addr) & 0x00100000) {
+ *sig_base_src = fw->sig_base_dbg;
+ return 1;
+ }
+ }
+
+ return ret;
+}
+
+const struct nvkm_falcon_fw_func
+gm200_flcn_fw = {
+ .signature = gm200_flcn_fw_signature,
+ .reset = gm200_flcn_fw_reset,
+ .load = gm200_flcn_fw_load,
+ .boot = gm200_flcn_fw_boot,
+};
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/gp102.c b/drivers/gpu/drm/nouveau/nvkm/falcon/gp102.c
new file mode 100644
index 000000000000..c774935f3077
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/gp102.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2022 Red Hat 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 "priv.h"
+
+static void
+gp102_flcn_pio_emem_rd(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len)
+{
+ while (len >= 4) {
+ *(u32 *)img = nvkm_falcon_rd32(falcon, 0xac4 + (port * 8));
+ img += 4;
+ len -= 4;
+ }
+}
+
+static void
+gp102_flcn_pio_emem_rd_init(struct nvkm_falcon *falcon, u8 port, u32 dmem_base)
+{
+ nvkm_falcon_wr32(falcon, 0xac0 + (port * 8), BIT(25) | dmem_base);
+}
+
+static void
+gp102_flcn_pio_emem_wr(struct nvkm_falcon *falcon, u8 port, const u8 *img, int len, u16 tag)
+{
+ while (len >= 4) {
+ nvkm_falcon_wr32(falcon, 0xac4 + (port * 8), *(u32 *)img);
+ img += 4;
+ len -= 4;
+ }
+}
+
+static void
+gp102_flcn_pio_emem_wr_init(struct nvkm_falcon *falcon, u8 port, bool sec, u32 emem_base)
+{
+ nvkm_falcon_wr32(falcon, 0xac0 + (port * 8), BIT(24) | emem_base);
+}
+
+const struct nvkm_falcon_func_pio
+gp102_flcn_emem_pio = {
+ .min = 4,
+ .max = 0x100,
+ .wr_init = gp102_flcn_pio_emem_wr_init,
+ .wr = gp102_flcn_pio_emem_wr,
+ .rd_init = gp102_flcn_pio_emem_rd_init,
+ .rd = gp102_flcn_pio_emem_rd,
+};
+
+int
+gp102_flcn_reset_eng(struct nvkm_falcon *falcon)
+{
+ int ret;
+
+ if (falcon->func->reset_prep) {
+ ret = falcon->func->reset_prep(falcon);
+ if (ret)
+ return ret;
+ }
+
+ nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000001);
+ udelay(10);
+ nvkm_falcon_mask(falcon, 0x3c0, 0x00000001, 0x00000000);
+
+ return falcon->func->reset_wait_mem_scrubbing(falcon);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c
index e74371dffc76..16b246fda666 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgq.c
@@ -25,7 +25,7 @@
static void
nvkm_falcon_msgq_open(struct nvkm_falcon_msgq *msgq)
{
- mutex_lock(&msgq->mutex);
+ spin_lock(&msgq->lock);
msgq->position = nvkm_falcon_rd32(msgq->qmgr->falcon, msgq->tail_reg);
}
@@ -37,10 +37,10 @@ nvkm_falcon_msgq_close(struct nvkm_falcon_msgq *msgq, bool commit)
if (commit)
nvkm_falcon_wr32(falcon, msgq->tail_reg, msgq->position);
- mutex_unlock(&msgq->mutex);
+ spin_unlock(&msgq->lock);
}
-static bool
+bool
nvkm_falcon_msgq_empty(struct nvkm_falcon_msgq *msgq)
{
u32 head = nvkm_falcon_rd32(msgq->qmgr->falcon, msgq->head_reg);
@@ -68,7 +68,7 @@ nvkm_falcon_msgq_pop(struct nvkm_falcon_msgq *msgq, void *data, u32 size)
return -EINVAL;
}
- nvkm_falcon_read_dmem(falcon, tail, size, 0, data);
+ nvkm_falcon_pio_rd(falcon, 0, DMEM, tail, data, 0, size);
msgq->position += ALIGN(size, QUEUE_ALIGNMENT);
return 0;
}
@@ -208,6 +208,6 @@ nvkm_falcon_msgq_new(struct nvkm_falcon_qmgr *qmgr, const char *name,
msgq->qmgr = qmgr;
msgq->name = name;
- mutex_init(&msgq->mutex);
+ spin_lock_init(&msgq->lock);
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/priv.h b/drivers/gpu/drm/nouveau/nvkm/falcon/priv.h
index 466188752eb0..11a24b9c8569 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/priv.h
@@ -2,4 +2,12 @@
#ifndef __NVKM_FALCON_PRIV_H__
#define __NVKM_FALCON_PRIV_H__
#include <core/falcon.h>
+
+static inline int
+nvkm_falcon_enable(struct nvkm_falcon *falcon)
+{
+ if (falcon->func->enable)
+ return falcon->func->enable(falcon);
+ return 0;
+}
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h
index 976cb7b7aa99..79f0da9e749f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/qmgr.h
@@ -73,7 +73,7 @@ struct nvkm_falcon_cmdq {
struct nvkm_falcon_msgq {
struct nvkm_falcon_qmgr *qmgr;
const char *name;
- struct mutex mutex;
+ spinlock_t lock;
u32 head_reg;
u32 tail_reg;
@@ -82,8 +82,7 @@ struct nvkm_falcon_msgq {
u32 position;
};
-#define FLCNQ_PRINTK(t,q,f,a...) \
- FLCN_PRINTK(t, (q)->qmgr->falcon, "%s: "f, (q)->name, ##a)
-#define FLCNQ_DBG(q,f,a...) FLCNQ_PRINTK(debug, (q), f, ##a)
-#define FLCNQ_ERR(q,f,a...) FLCNQ_PRINTK(error, (q), f, ##a)
+#define FLCNQ_PRINTK(q,l,p,f,a...) FLCN_PRINTK((q)->qmgr->falcon, l, p, "%s: "f, (q)->name, ##a)
+#define FLCNQ_DBG(q,f,a...) FLCNQ_PRINTK((q), DEBUG, info, f, ##a)
+#define FLCNQ_ERR(q,f,a...) FLCNQ_PRINTK((q), ERROR, err, f, ##a)
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c
index b0ee4c31414c..dd2ddc54ac60 100644
--- a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c
+++ b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c
@@ -64,44 +64,13 @@ nvkm_falcon_v1_load_imem(struct nvkm_falcon *falcon, void *data, u32 start,
nvkm_falcon_wr32(falcon, 0x184 + (port * 16), 0);
}
-static void
-nvkm_falcon_v1_load_emem(struct nvkm_falcon *falcon, void *data, u32 start,
- u32 size, u8 port)
-{
- u8 rem = size % 4;
- int i;
-
- size -= rem;
-
- nvkm_falcon_wr32(falcon, 0xac0 + (port * 8), start | (0x1 << 24));
- for (i = 0; i < size / 4; i++)
- nvkm_falcon_wr32(falcon, 0xac4 + (port * 8), ((u32 *)data)[i]);
-
- /*
- * If size is not a multiple of 4, mask the last word to ensure garbage
- * does not get written
- */
- if (rem) {
- u32 extra = ((u32 *)data)[i];
-
- nvkm_falcon_wr32(falcon, 0xac4 + (port * 8),
- extra & (BIT(rem * 8) - 1));
- }
-}
-
void
nvkm_falcon_v1_load_dmem(struct nvkm_falcon *falcon, void *data, u32 start,
u32 size, u8 port)
{
- const struct nvkm_falcon_func *func = falcon->func;
u8 rem = size % 4;
int i;
- if (func->emem_addr && start >= func->emem_addr)
- return nvkm_falcon_v1_load_emem(falcon, data,
- start - func->emem_addr, size,
- port);
-
size -= rem;
nvkm_falcon_wr32(falcon, 0x1c0 + (port * 8), start | (0x1 << 24));
@@ -120,113 +89,6 @@ nvkm_falcon_v1_load_dmem(struct nvkm_falcon *falcon, void *data, u32 start,
}
}
-static void
-nvkm_falcon_v1_read_emem(struct nvkm_falcon *falcon, u32 start, u32 size,
- u8 port, void *data)
-{
- u8 rem = size % 4;
- int i;
-
- size -= rem;
-
- nvkm_falcon_wr32(falcon, 0xac0 + (port * 8), start | (0x1 << 25));
- for (i = 0; i < size / 4; i++)
- ((u32 *)data)[i] = nvkm_falcon_rd32(falcon, 0xac4 + (port * 8));
-
- /*
- * If size is not a multiple of 4, mask the last word to ensure garbage
- * does not get read
- */
- if (rem) {
- u32 extra = nvkm_falcon_rd32(falcon, 0xac4 + (port * 8));
-
- for (i = size; i < size + rem; i++) {
- ((u8 *)data)[i] = (u8)(extra & 0xff);
- extra >>= 8;
- }
- }
-}
-
-void
-nvkm_falcon_v1_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size,
- u8 port, void *data)
-{
- const struct nvkm_falcon_func *func = falcon->func;
- u8 rem = size % 4;
- int i;
-
- if (func->emem_addr && start >= func->emem_addr)
- return nvkm_falcon_v1_read_emem(falcon, start - func->emem_addr,
- size, port, data);
-
- size -= rem;
-
- nvkm_falcon_wr32(falcon, 0x1c0 + (port * 8), start | (0x1 << 25));
- for (i = 0; i < size / 4; i++)
- ((u32 *)data)[i] = nvkm_falcon_rd32(falcon, 0x1c4 + (port * 8));
-
- /*
- * If size is not a multiple of 4, mask the last word to ensure garbage
- * does not get read
- */
- if (rem) {
- u32 extra = nvkm_falcon_rd32(falcon, 0x1c4 + (port * 8));
-
- for (i = size; i < size + rem; i++) {
- ((u8 *)data)[i] = (u8)(extra & 0xff);
- extra >>= 8;
- }
- }
-}
-
-void
-nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_memory *ctx)
-{
- const u32 fbif = falcon->func->fbif;
- u32 inst_loc;
-
- /* disable instance block binding */
- if (ctx == NULL) {
- nvkm_falcon_wr32(falcon, 0x10c, 0x0);
- return;
- }
-
- nvkm_falcon_wr32(falcon, 0x10c, 0x1);
-
- /* setup apertures - virtual */
- nvkm_falcon_wr32(falcon, fbif + 4 * FALCON_DMAIDX_UCODE, 0x4);
- nvkm_falcon_wr32(falcon, fbif + 4 * FALCON_DMAIDX_VIRT, 0x0);
- /* setup apertures - physical */
- nvkm_falcon_wr32(falcon, fbif + 4 * FALCON_DMAIDX_PHYS_VID, 0x4);
- nvkm_falcon_wr32(falcon, fbif + 4 * FALCON_DMAIDX_PHYS_SYS_COH, 0x5);
- nvkm_falcon_wr32(falcon, fbif + 4 * FALCON_DMAIDX_PHYS_SYS_NCOH, 0x6);
-
- /* Set context */
- switch (nvkm_memory_target(ctx)) {
- case NVKM_MEM_TARGET_VRAM: inst_loc = 0; break;
- case NVKM_MEM_TARGET_HOST: inst_loc = 2; break;
- case NVKM_MEM_TARGET_NCOH: inst_loc = 3; break;
- default:
- WARN_ON(1);
- return;
- }
-
- /* Enable context */
- nvkm_falcon_mask(falcon, 0x048, 0x1, 0x1);
- nvkm_falcon_wr32(falcon, 0x054,
- ((nvkm_memory_addr(ctx) >> 12) & 0xfffffff) |
- (inst_loc << 28) | (1 << 30));
-
- nvkm_falcon_mask(falcon, 0x090, 0x10000, 0x10000);
- nvkm_falcon_mask(falcon, 0x0a4, 0x8, 0x8);
-}
-
-void
-nvkm_falcon_v1_set_start_addr(struct nvkm_falcon *falcon, u32 start_addr)
-{
- nvkm_falcon_wr32(falcon, 0x104, start_addr);
-}
-
void
nvkm_falcon_v1_start(struct nvkm_falcon *falcon)
{
@@ -237,75 +99,3 @@ nvkm_falcon_v1_start(struct nvkm_falcon *falcon)
else
nvkm_falcon_wr32(falcon, 0x100, 0x2);
}
-
-int
-nvkm_falcon_v1_wait_for_halt(struct nvkm_falcon *falcon, u32 ms)
-{
- struct nvkm_device *device = falcon->owner->device;
- int ret;
-
- ret = nvkm_wait_msec(device, ms, falcon->addr + 0x100, 0x10, 0x10);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-int
-nvkm_falcon_v1_clear_interrupt(struct nvkm_falcon *falcon, u32 mask)
-{
- struct nvkm_device *device = falcon->owner->device;
- int ret;
-
- /* clear interrupt(s) */
- nvkm_falcon_mask(falcon, 0x004, mask, mask);
- /* wait until interrupts are cleared */
- ret = nvkm_wait_msec(device, 10, falcon->addr + 0x008, mask, 0x0);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static int
-falcon_v1_wait_idle(struct nvkm_falcon *falcon)
-{
- struct nvkm_device *device = falcon->owner->device;
- int ret;
-
- ret = nvkm_wait_msec(device, 10, falcon->addr + 0x04c, 0xffff, 0x0);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-int
-nvkm_falcon_v1_enable(struct nvkm_falcon *falcon)
-{
- struct nvkm_device *device = falcon->owner->device;
- int ret;
-
- ret = nvkm_wait_msec(device, 10, falcon->addr + 0x10c, 0x6, 0x0);
- if (ret < 0) {
- nvkm_error(falcon->user, "Falcon mem scrubbing timeout\n");
- return ret;
- }
-
- ret = falcon_v1_wait_idle(falcon);
- if (ret)
- return ret;
-
- /* enable IRQs */
- nvkm_falcon_wr32(falcon, 0x010, 0xff);
-
- return 0;
-}
-
-void
-nvkm_falcon_v1_disable(struct nvkm_falcon *falcon)
-{
- /* disable IRQs and wait for any previous code to complete */
- nvkm_falcon_wr32(falcon, 0x014, 0xff);
- falcon_v1_wait_idle(falcon);
-}
diff --git a/drivers/gpu/drm/nouveau/nvkm/nvfw/acr.c b/drivers/gpu/drm/nouveau/nvkm/nvfw/acr.c
index bef790ad8f2f..83a9c48bc58c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/nvfw/acr.c
+++ b/drivers/gpu/drm/nouveau/nvkm/nvfw/acr.c
@@ -45,6 +45,47 @@ wpr_header_v1_dump(struct nvkm_subdev *subdev, const struct wpr_header_v1 *hdr)
nvkm_debug(subdev, "\tstatus : %d\n", hdr->status);
}
+void
+wpr_generic_header_dump(struct nvkm_subdev *subdev, const struct wpr_generic_header *hdr)
+{
+ nvkm_debug(subdev, "wprGenericHeader\n");
+ nvkm_debug(subdev, "\tidentifier : %04x\n", hdr->identifier);
+ nvkm_debug(subdev, "\tversion : %04x\n", hdr->version);
+ nvkm_debug(subdev, "\tsize : %08x\n", hdr->size);
+}
+
+void
+wpr_header_v2_dump(struct nvkm_subdev *subdev, const struct wpr_header_v2 *hdr)
+{
+ wpr_generic_header_dump(subdev, &hdr->hdr);
+ wpr_header_v1_dump(subdev, &hdr->wpr);
+}
+
+void
+lsb_header_v2_dump(struct nvkm_subdev *subdev, struct lsb_header_v2 *hdr)
+{
+ wpr_generic_header_dump(subdev, &hdr->hdr);
+ nvkm_debug(subdev, "lsbHeader\n");
+ nvkm_debug(subdev, "\tucodeOff : 0x%x\n", hdr->ucode_off);
+ nvkm_debug(subdev, "\tucodeSize : 0x%x\n", hdr->ucode_size);
+ nvkm_debug(subdev, "\tdataSize : 0x%x\n", hdr->data_size);
+ nvkm_debug(subdev, "\tblCodeSize : 0x%x\n", hdr->bl_code_size);
+ nvkm_debug(subdev, "\tblImemOff : 0x%x\n", hdr->bl_imem_off);
+ nvkm_debug(subdev, "\tblDataOff : 0x%x\n", hdr->bl_data_off);
+ nvkm_debug(subdev, "\tblDataSize : 0x%x\n", hdr->bl_data_size);
+ nvkm_debug(subdev, "\treserved0 : %08x\n", hdr->rsvd0);
+ nvkm_debug(subdev, "\tappCodeOff : 0x%x\n", hdr->app_code_off);
+ nvkm_debug(subdev, "\tappCodeSize : 0x%x\n", hdr->app_code_size);
+ nvkm_debug(subdev, "\tappDataOff : 0x%x\n", hdr->app_data_off);
+ nvkm_debug(subdev, "\tappDataSize : 0x%x\n", hdr->app_data_size);
+ nvkm_debug(subdev, "\tappImemOffset : 0x%x\n", hdr->app_imem_offset);
+ nvkm_debug(subdev, "\tappDmemOffset : 0x%x\n", hdr->app_dmem_offset);
+ nvkm_debug(subdev, "\tflags : 0x%x\n", hdr->flags);
+ nvkm_debug(subdev, "\tmonitorCodeOff: 0x%x\n", hdr->monitor_code_offset);
+ nvkm_debug(subdev, "\tmonitorDataOff: 0x%x\n", hdr->monitor_data_offset);
+ nvkm_debug(subdev, "\tmanifestOffset: 0x%x\n", hdr->manifest_offset);
+}
+
static void
lsb_header_tail_dump(struct nvkm_subdev *subdev, struct lsb_header_tail *hdr)
{
diff --git a/drivers/gpu/drm/nouveau/nvkm/nvfw/hs.c b/drivers/gpu/drm/nouveau/nvkm/nvfw/hs.c
index 04ed77cb2eba..a7e0583401d0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/nvfw/hs.c
+++ b/drivers/gpu/drm/nouveau/nvkm/nvfw/hs.c
@@ -38,6 +38,24 @@ nvfw_hs_header(struct nvkm_subdev *subdev, const void *data)
return hdr;
}
+const struct nvfw_hs_header_v2 *
+nvfw_hs_header_v2(struct nvkm_subdev *subdev, const void *data)
+{
+ const struct nvfw_hs_header_v2 *hdr = data;
+
+ nvkm_debug(subdev, "hsHeader:\n");
+ nvkm_debug(subdev, "\tsigProdOffset : 0x%x\n", hdr->sig_prod_offset);
+ nvkm_debug(subdev, "\tsigProdSize : 0x%x\n", hdr->sig_prod_size);
+ nvkm_debug(subdev, "\tpatchLoc : 0x%x\n", hdr->patch_loc);
+ nvkm_debug(subdev, "\tpatchSig : 0x%x\n", hdr->patch_sig);
+ nvkm_debug(subdev, "\tmetadataOffset : 0x%x\n", hdr->meta_data_offset);
+ nvkm_debug(subdev, "\tmetadataSize : 0x%x\n", hdr->meta_data_size);
+ nvkm_debug(subdev, "\tnumSig : 0x%x\n", hdr->num_sig);
+ nvkm_debug(subdev, "\theaderOffset : 0x%x\n", hdr->header_offset);
+ nvkm_debug(subdev, "\theaderSize : 0x%x\n", hdr->header_size);
+ return hdr;
+}
+
const struct nvfw_hs_load_header *
nvfw_hs_load_header(struct nvkm_subdev *subdev, const void *data)
{
@@ -60,3 +78,24 @@ nvfw_hs_load_header(struct nvkm_subdev *subdev, const void *data)
return hdr;
}
+
+const struct nvfw_hs_load_header_v2 *
+nvfw_hs_load_header_v2(struct nvkm_subdev *subdev, const void *data)
+{
+ const struct nvfw_hs_load_header_v2 *hdr = data;
+ int i;
+
+ nvkm_debug(subdev, "hsLoadHeader:\n");
+ nvkm_debug(subdev, "\tosCodeOffset : 0x%x\n", hdr->os_code_offset);
+ nvkm_debug(subdev, "\tosCodeSize : 0x%x\n", hdr->os_code_size);
+ nvkm_debug(subdev, "\tosDataOffset : 0x%x\n", hdr->os_data_offset);
+ nvkm_debug(subdev, "\tosDataSize : 0x%x\n", hdr->os_data_size);
+ nvkm_debug(subdev, "\tnumApps : 0x%x\n", hdr->num_apps);
+ for (i = 0; i < hdr->num_apps; i++) {
+ nvkm_debug(subdev,
+ "\tApp[%d] : offset 0x%x size 0x%x\n", i,
+ hdr->app[i].offset, hdr->app[i].size);
+ }
+
+ return hdr;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/nvfw/ls.c b/drivers/gpu/drm/nouveau/nvkm/nvfw/ls.c
index b847f281ce97..45c3a6c5e088 100644
--- a/drivers/gpu/drm/nouveau/nvkm/nvfw/ls.c
+++ b/drivers/gpu/drm/nouveau/nvkm/nvfw/ls.c
@@ -106,3 +106,75 @@ nvfw_ls_desc_v1(struct nvkm_subdev *subdev, const void *data)
return hdr;
}
+
+const struct nvfw_ls_desc_v2 *
+nvfw_ls_desc_v2(struct nvkm_subdev *subdev, const void *data)
+{
+ const struct nvfw_ls_desc_v2 *hdr = data;
+ char *date;
+ int i;
+
+ nvkm_debug(subdev, "lsUcodeImgDesc:\n");
+ nvkm_debug(subdev, "\tdescriptorSize : %d\n", hdr->descriptor_size);
+ nvkm_debug(subdev, "\timageSize : %d\n", hdr->image_size);
+ nvkm_debug(subdev, "\ttoolsVersion : 0x%x\n", hdr->tools_version);
+ nvkm_debug(subdev, "\tappVersion : 0x%x\n", hdr->app_version);
+
+ date = kstrndup(hdr->date, sizeof(hdr->date), GFP_KERNEL);
+ nvkm_debug(subdev, "\tdate : %s\n", date);
+ kfree(date);
+
+ nvkm_debug(subdev, "\tsecureBootloader : 0x%x\n", hdr->secure_bootloader);
+ nvkm_debug(subdev, "\tbootloaderStartOffset: 0x%x\n", hdr->bootloader_start_offset);
+ nvkm_debug(subdev, "\tbootloaderSize : 0x%x\n", hdr->bootloader_size);
+ nvkm_debug(subdev, "\tbootloaderImemOffset : 0x%x\n", hdr->bootloader_imem_offset);
+ nvkm_debug(subdev, "\tbootloaderEntryPoint : 0x%x\n", hdr->bootloader_entry_point);
+
+ nvkm_debug(subdev, "\tappStartOffset : 0x%x\n", hdr->app_start_offset);
+ nvkm_debug(subdev, "\tappSize : 0x%x\n", hdr->app_size);
+ nvkm_debug(subdev, "\tappImemOffset : 0x%x\n", hdr->app_imem_offset);
+ nvkm_debug(subdev, "\tappImemEntry : 0x%x\n", hdr->app_imem_entry);
+ nvkm_debug(subdev, "\tappDmemOffset : 0x%x\n", hdr->app_dmem_offset);
+ nvkm_debug(subdev, "\tappResidentCodeOffset: 0x%x\n", hdr->app_resident_code_offset);
+ nvkm_debug(subdev, "\tappResidentCodeSize : 0x%x\n", hdr->app_resident_code_size);
+ nvkm_debug(subdev, "\tappResidentDataOffset: 0x%x\n", hdr->app_resident_data_offset);
+ nvkm_debug(subdev, "\tappResidentDataSize : 0x%x\n", hdr->app_resident_data_size);
+
+ nvkm_debug(subdev, "\tnbImemOverlays : %d\n", hdr->nb_imem_overlays);
+ nvkm_debug(subdev, "\tnbDmemOverlays : %d\n", hdr->nb_dmem_overlays);
+ for (i = 0; i < ARRAY_SIZE(hdr->load_ovl); i++) {
+ nvkm_debug(subdev, "\tloadOvl[%d] : 0x%x %d\n", i,
+ hdr->load_ovl[i].start, hdr->load_ovl[i].size);
+ }
+
+ return hdr;
+}
+
+const struct nvfw_ls_hsbl_bin_hdr *
+nvfw_ls_hsbl_bin_hdr(struct nvkm_subdev *subdev, const void *data)
+{
+ const struct nvfw_ls_hsbl_bin_hdr *hdr = data;
+
+ nvkm_debug(subdev, "lsHsblBinHdr:\n");
+ nvkm_debug(subdev, "\tbinMagic : 0x%08x\n", hdr->bin_magic);
+ nvkm_debug(subdev, "\tbinVer : %d\n", hdr->bin_ver);
+ nvkm_debug(subdev, "\tbinSize : %d\n", hdr->bin_size);
+ nvkm_debug(subdev, "\theaderOffset : 0x%x\n", hdr->header_offset);
+ return hdr;
+}
+
+const struct nvfw_ls_hsbl_hdr *
+nvfw_ls_hsbl_hdr(struct nvkm_subdev *subdev, const void *data)
+{
+ const struct nvfw_ls_hsbl_hdr *hdr = data;
+
+ nvkm_debug(subdev, "lsHsblHdr:\n");
+ nvkm_debug(subdev, "\tsigProdOffset : 0x%x\n", hdr->sig_prod_offset);
+ nvkm_debug(subdev, "\tsigProdSize : 0x%x\n", hdr->sig_prod_size);
+ nvkm_debug(subdev, "\tpatchLoc : 0x%x\n", hdr->patch_loc);
+ nvkm_debug(subdev, "\tpatchSig : 0x%x\n", hdr->patch_sig);
+ nvkm_debug(subdev, "\tmetadataOffset : 0x%x\n", hdr->meta_data_offset);
+ nvkm_debug(subdev, "\tmetadataSize : 0x%x\n", hdr->meta_data_size);
+ nvkm_debug(subdev, "\tnumSig : 0x%x\n", hdr->num_sig);
+ return hdr;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild
index 2cb24fff7e32..4c2f6fc4ef58 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/Kbuild
@@ -23,4 +23,5 @@ include $(src)/nvkm/subdev/privring/Kbuild
include $(src)/nvkm/subdev/therm/Kbuild
include $(src)/nvkm/subdev/timer/Kbuild
include $(src)/nvkm/subdev/top/Kbuild
+include $(src)/nvkm/subdev/vfn/Kbuild
include $(src)/nvkm/subdev/volt/Kbuild
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild
index 5b9f64a8957f..5731f35b11e1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/Kbuild
@@ -1,10 +1,12 @@
# SPDX-License-Identifier: MIT
nvkm-y += nvkm/subdev/acr/base.o
-nvkm-y += nvkm/subdev/acr/hsfw.o
nvkm-y += nvkm/subdev/acr/lsfw.o
nvkm-y += nvkm/subdev/acr/gm200.o
nvkm-y += nvkm/subdev/acr/gm20b.o
nvkm-y += nvkm/subdev/acr/gp102.o
nvkm-y += nvkm/subdev/acr/gp108.o
+nvkm-y += nvkm/subdev/acr/gv100.o
nvkm-y += nvkm/subdev/acr/gp10b.o
nvkm-y += nvkm/subdev/acr/tu102.o
+nvkm-y += nvkm/subdev/acr/ga100.o
+nvkm-y += nvkm/subdev/acr/ga102.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
index af6cac696d43..795f3a649b12 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
@@ -24,50 +24,63 @@
#include <core/firmware.h>
#include <core/memory.h>
#include <subdev/mmu.h>
+#include <subdev/gsp.h>
+#include <subdev/pmu.h>
+#include <engine/sec2.h>
+#include <engine/nvdec.h>
-static struct nvkm_acr_hsf *
-nvkm_acr_hsf_find(struct nvkm_acr *acr, const char *name)
+static struct nvkm_acr_hsfw *
+nvkm_acr_hsfw_find(struct nvkm_acr *acr, const char *name)
{
- struct nvkm_acr_hsf *hsf;
- list_for_each_entry(hsf, &acr->hsf, head) {
- if (!strcmp(hsf->name, name))
- return hsf;
+ struct nvkm_acr_hsfw *hsfw;
+
+ list_for_each_entry(hsfw, &acr->hsfw, head) {
+ if (!strcmp(hsfw->fw.fw.name, name))
+ return hsfw;
}
+
return NULL;
}
int
-nvkm_acr_hsf_boot(struct nvkm_acr *acr, const char *name)
+nvkm_acr_hsfw_boot(struct nvkm_acr *acr, const char *name)
{
struct nvkm_subdev *subdev = &acr->subdev;
- struct nvkm_acr_hsf *hsf;
- int ret;
+ struct nvkm_acr_hsfw *hsfw;
- hsf = nvkm_acr_hsf_find(acr, name);
- if (!hsf)
+ hsfw = nvkm_acr_hsfw_find(acr, name);
+ if (!hsfw)
return -EINVAL;
- nvkm_debug(subdev, "executing %s binary\n", hsf->name);
- ret = nvkm_falcon_get(hsf->falcon, subdev);
- if (ret)
- return ret;
+ return nvkm_falcon_fw_boot(&hsfw->fw, subdev, true, NULL, NULL,
+ hsfw->boot_mbox0, hsfw->intr_clear);
+}
- ret = hsf->func->boot(acr, hsf);
- nvkm_falcon_put(hsf->falcon, subdev);
- if (ret) {
- nvkm_error(subdev, "%s binary failed\n", hsf->name);
- return ret;
+static struct nvkm_acr_lsf *
+nvkm_acr_rtos(struct nvkm_acr *acr)
+{
+ struct nvkm_acr_lsf *lsf;
+
+ if (acr) {
+ list_for_each_entry(lsf, &acr->lsf, head) {
+ if (lsf->func->bootstrap_falcon)
+ return lsf;
+ }
}
- nvkm_debug(subdev, "%s binary completed successfully\n", hsf->name);
- return 0;
+ return NULL;
}
static void
nvkm_acr_unload(struct nvkm_acr *acr)
{
if (acr->done) {
- nvkm_acr_hsf_boot(acr, "unload");
+ if (acr->rtos) {
+ nvkm_subdev_unref(acr->rtos->falcon->owner);
+ acr->rtos = NULL;
+ }
+
+ nvkm_acr_hsfw_boot(acr, "unload");
acr->done = false;
}
}
@@ -76,7 +89,7 @@ static int
nvkm_acr_load(struct nvkm_acr *acr)
{
struct nvkm_subdev *subdev = &acr->subdev;
- struct nvkm_acr_lsf *lsf;
+ struct nvkm_acr_lsf *rtos = nvkm_acr_rtos(acr);
u64 start, limit;
int ret;
@@ -100,12 +113,12 @@ nvkm_acr_load(struct nvkm_acr *acr)
acr->done = true;
- list_for_each_entry(lsf, &acr->lsf, head) {
- if (lsf->func->boot) {
- ret = lsf->func->boot(lsf->falcon);
- if (ret)
- break;
- }
+ if (rtos) {
+ ret = nvkm_subdev_ref(rtos->falcon->owner);
+ if (ret)
+ return ret;
+
+ acr->rtos = rtos;
}
return ret;
@@ -118,33 +131,17 @@ nvkm_acr_reload(struct nvkm_acr *acr)
return nvkm_acr_load(acr);
}
-static struct nvkm_acr_lsf *
-nvkm_acr_falcon(struct nvkm_device *device)
-{
- struct nvkm_acr *acr = device->acr;
- struct nvkm_acr_lsf *lsf;
-
- if (acr) {
- list_for_each_entry(lsf, &acr->lsf, head) {
- if (lsf->func->bootstrap_falcon)
- return lsf;
- }
- }
-
- return NULL;
-}
-
int
nvkm_acr_bootstrap_falcons(struct nvkm_device *device, unsigned long mask)
{
- struct nvkm_acr_lsf *acrflcn = nvkm_acr_falcon(device);
struct nvkm_acr *acr = device->acr;
+ struct nvkm_acr_lsf *rtos = nvkm_acr_rtos(acr);
unsigned long id;
/* If there's no LS FW managing bootstrapping of other LS falcons,
* we depend on the HS firmware being able to do it instead.
*/
- if (!acrflcn) {
+ if (!rtos) {
/* Which isn't possible everywhere... */
if ((mask & acr->func->bootstrap_falcons) == mask) {
int ret = nvkm_acr_reload(acr);
@@ -156,16 +153,14 @@ nvkm_acr_bootstrap_falcons(struct nvkm_device *device, unsigned long mask)
return -ENOSYS;
}
- if ((mask & acrflcn->func->bootstrap_falcons) != mask)
+ if ((mask & rtos->func->bootstrap_falcons) != mask)
return -ENOSYS;
- if (acrflcn->func->bootstrap_multiple_falcons) {
- return acrflcn->func->
- bootstrap_multiple_falcons(acrflcn->falcon, mask);
- }
+ if (rtos->func->bootstrap_multiple_falcons)
+ return rtos->func->bootstrap_multiple_falcons(rtos->falcon, mask);
for_each_set_bit(id, &mask, NVKM_ACR_LSF_NUM) {
- int ret = acrflcn->func->bootstrap_falcon(acrflcn->falcon, id);
+ int ret = rtos->func->bootstrap_falcon(rtos->falcon, id);
if (ret)
return ret;
}
@@ -189,6 +184,9 @@ nvkm_acr_managed_falcon(struct nvkm_device *device, enum nvkm_acr_lsf_id id)
static int
nvkm_acr_fini(struct nvkm_subdev *subdev, bool suspend)
{
+ if (!subdev->use.enabled)
+ return 0;
+
nvkm_acr_unload(nvkm_acr(subdev));
return 0;
}
@@ -196,17 +194,19 @@ nvkm_acr_fini(struct nvkm_subdev *subdev, bool suspend)
static int
nvkm_acr_init(struct nvkm_subdev *subdev)
{
- if (!nvkm_acr_falcon(subdev->device))
+ struct nvkm_acr *acr = nvkm_acr(subdev);
+
+ if (!nvkm_acr_rtos(acr))
return 0;
- return nvkm_acr_load(nvkm_acr(subdev));
+ return nvkm_acr_load(acr);
}
static void
nvkm_acr_cleanup(struct nvkm_acr *acr)
{
nvkm_acr_lsfw_del_all(acr);
- nvkm_acr_hsfw_del_all(acr);
+
nvkm_firmware_put(acr->wpr_fw);
acr->wpr_fw = NULL;
}
@@ -218,7 +218,8 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev)
struct nvkm_acr *acr = nvkm_acr(subdev);
struct nvkm_acr_hsfw *hsfw;
struct nvkm_acr_lsfw *lsfw, *lsft;
- struct nvkm_acr_lsf *lsf;
+ struct nvkm_acr_lsf *lsf, *rtos;
+ struct nvkm_falcon *falcon;
u32 wpr_size = 0;
u64 falcons;
int ret, i;
@@ -260,10 +261,10 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev)
}
/* Ensure the falcon that'll provide ACR functions is booted first. */
- lsf = nvkm_acr_falcon(device);
- if (lsf) {
- falcons = lsf->func->bootstrap_falcons;
- list_move(&lsf->head, &acr->lsf);
+ rtos = nvkm_acr_rtos(acr);
+ if (rtos) {
+ falcons = rtos->func->bootstrap_falcons;
+ list_move(&rtos->head, &acr->lsf);
} else {
falcons = acr->func->bootstrap_falcons;
}
@@ -301,7 +302,7 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev)
nvkm_wobj(acr->wpr, 0, acr->wpr_fw->data, acr->wpr_fw->size);
if (!acr->wpr_fw || acr->wpr_comp)
- acr->func->wpr_build(acr, nvkm_acr_falcon(device));
+ acr->func->wpr_build(acr, rtos);
acr->func->wpr_patch(acr, (s64)acr->wpr_start - acr->wpr_prev);
if (acr->wpr_fw && acr->wpr_comp) {
@@ -336,8 +337,16 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev)
/* Load HS firmware blobs into ACR VMM. */
list_for_each_entry(hsfw, &acr->hsfw, head) {
- nvkm_debug(subdev, "loading %s fw\n", hsfw->name);
- ret = hsfw->func->load(acr, hsfw);
+ switch (hsfw->falcon_id) {
+ case NVKM_ACR_HSF_PMU : falcon = &device->pmu->falcon; break;
+ case NVKM_ACR_HSF_SEC2: falcon = &device->sec2->falcon; break;
+ case NVKM_ACR_HSF_GSP : falcon = &device->gsp->falcon; break;
+ default:
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ ret = nvkm_falcon_fw_oneinit(&hsfw->fw, falcon, acr->vmm, acr->inst);
if (ret)
return ret;
}
@@ -351,15 +360,13 @@ static void *
nvkm_acr_dtor(struct nvkm_subdev *subdev)
{
struct nvkm_acr *acr = nvkm_acr(subdev);
- struct nvkm_acr_hsf *hsf, *hst;
+ struct nvkm_acr_hsfw *hsfw, *hsft;
struct nvkm_acr_lsf *lsf, *lst;
- list_for_each_entry_safe(hsf, hst, &acr->hsf, head) {
- nvkm_vmm_put(acr->vmm, &hsf->vma);
- nvkm_memory_unref(&hsf->ucode);
- kfree(hsf->imem);
- list_del(&hsf->head);
- kfree(hsf);
+ list_for_each_entry_safe(hsfw, hsft, &acr->hsfw, head) {
+ nvkm_falcon_fw_dtor(&hsfw->fw);
+ list_del(&hsfw->head);
+ kfree(hsfw);
}
nvkm_vmm_part(acr->vmm, acr->inst);
@@ -420,7 +427,6 @@ nvkm_acr_new_(const struct nvkm_acr_fwif *fwif, struct nvkm_device *device,
nvkm_subdev_ctor(&nvkm_acr, device, type, inst, &acr->subdev);
INIT_LIST_HEAD(&acr->hsfw);
INIT_LIST_HEAD(&acr->lsfw);
- INIT_LIST_HEAD(&acr->hsf);
INIT_LIST_HEAD(&acr->lsf);
fwif = nvkm_firmware_load(&acr->subdev, fwif, "Acr", acr);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga100.c
new file mode 100644
index 000000000000..e3370c1551c0
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga100.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2021 Red Hat 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 "priv.h"
+
+void
+ga100_acr_wpr_check(struct nvkm_acr *acr, u64 *start, u64 *limit)
+{
+ struct nvkm_device *device = acr->subdev.device;
+
+ *start = (u64)(nvkm_rd32(device, 0x1fa81c) & 0xffffff00) << 8;
+ *limit = (u64)(nvkm_rd32(device, 0x1fa820) & 0xffffff00) << 8;
+ *limit = *limit + 0x20000;
+}
+
+int
+ga100_acr_hsfw_ctor(struct nvkm_acr *acr, const char *bl, const char *fw,
+ const char *name, int ver, const struct nvkm_acr_hsf_fwif *fwif)
+{
+ struct nvkm_acr_hsfw *hsfw;
+
+ if (!(hsfw = kzalloc(sizeof(*hsfw), GFP_KERNEL)))
+ return -ENOMEM;
+
+ hsfw->falcon_id = fwif->falcon_id;
+ hsfw->boot_mbox0 = fwif->boot_mbox0;
+ hsfw->intr_clear = fwif->intr_clear;
+ list_add_tail(&hsfw->head, &acr->hsfw);
+
+ return nvkm_falcon_fw_ctor_hs_v2(fwif->func, name, &acr->subdev, fw, ver, NULL, &hsfw->fw);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga102.c
new file mode 100644
index 000000000000..45dcf493e972
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/ga102.c
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2021 Red Hat 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 "priv.h"
+
+#include <nvfw/acr.h>
+
+static int
+ga102_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust)
+{
+ struct wpr_header_v2 hdr;
+ struct lsb_header_v2 *lsb;
+ struct nvkm_acr_lsfw *lsfw;
+ u32 offset = 0;
+
+ lsb = kvmalloc(sizeof(*lsb), GFP_KERNEL);
+ if (!lsb)
+ return -ENOMEM;
+
+ do {
+ nvkm_robj(acr->wpr, offset, &hdr, sizeof(hdr));
+ wpr_header_v2_dump(&acr->subdev, &hdr);
+
+ list_for_each_entry(lsfw, &acr->lsfw, head) {
+ if (lsfw->id != hdr.wpr.falcon_id)
+ continue;
+
+ nvkm_robj(acr->wpr, hdr.wpr.lsb_offset, lsb, sizeof(*lsb));
+ lsb_header_v2_dump(&acr->subdev, lsb);
+
+ lsfw->func->bld_patch(acr, lsb->bl_data_off, adjust);
+ break;
+ }
+
+ offset += sizeof(hdr);
+ } while (hdr.wpr.falcon_id != WPR_HEADER_V1_FALCON_ID_INVALID);
+
+ kvfree(lsb);
+ return 0;
+}
+
+static int
+ga102_acr_wpr_build_lsb(struct nvkm_acr *acr, struct nvkm_acr_lsfw *lsfw)
+{
+ struct lsb_header_v2 *hdr;
+ int ret = 0;
+
+ if (WARN_ON(lsfw->sig->size != sizeof(hdr->signature)))
+ return -EINVAL;
+
+ hdr = kvzalloc(sizeof(*hdr), GFP_KERNEL);
+ if (!hdr)
+ return -ENOMEM;
+
+ hdr->hdr.identifier = WPR_GENERIC_HEADER_ID_LSF_LSB_HEADER;
+ hdr->hdr.version = 2;
+ hdr->hdr.size = sizeof(*hdr);
+
+ memcpy(&hdr->signature, lsfw->sig->data, lsfw->sig->size);
+ hdr->ucode_off = lsfw->offset.img;
+ hdr->ucode_size = lsfw->ucode_size;
+ hdr->data_size = lsfw->data_size;
+ hdr->bl_code_size = lsfw->bootloader_size;
+ hdr->bl_imem_off = lsfw->bootloader_imem_offset;
+ hdr->bl_data_off = lsfw->offset.bld;
+ hdr->bl_data_size = lsfw->bl_data_size;
+ hdr->app_code_off = lsfw->app_start_offset + lsfw->app_resident_code_offset;
+ hdr->app_code_size = ALIGN(lsfw->app_resident_code_size, 0x100);
+ hdr->app_data_off = lsfw->app_start_offset + lsfw->app_resident_data_offset;
+ hdr->app_data_size = ALIGN(lsfw->app_resident_data_size, 0x100);
+ hdr->app_imem_offset = lsfw->app_imem_offset;
+ hdr->app_dmem_offset = lsfw->app_dmem_offset;
+ hdr->flags = lsfw->func->flags;
+ hdr->monitor_code_offset = 0;
+ hdr->monitor_data_offset = 0;
+ hdr->manifest_offset = 0;
+
+ if (lsfw->secure_bootloader) {
+ struct nvkm_falcon_fw fw = {
+ .fw.img = hdr->hs_fmc_params.pkc_signature,
+ .fw.name = "LSFW",
+ .func = &(const struct nvkm_falcon_fw_func) {
+ .signature = ga100_flcn_fw_signature,
+ },
+ .sig_size = lsfw->sig_size,
+ .sig_nr = lsfw->sig_nr,
+ .sigs = lsfw->sigs,
+ .fuse_ver = lsfw->fuse_ver,
+ .engine_id = lsfw->engine_id,
+ .ucode_id = lsfw->ucode_id,
+ .falcon = lsfw->falcon,
+
+ };
+
+ ret = nvkm_falcon_get(fw.falcon, &acr->subdev);
+ if (ret == 0) {
+ hdr->hs_fmc_params.hs_fmc = 1;
+ hdr->hs_fmc_params.pkc_algo = 0;
+ hdr->hs_fmc_params.pkc_algo_version = 1;
+ hdr->hs_fmc_params.engid_mask = lsfw->engine_id;
+ hdr->hs_fmc_params.ucode_id = lsfw->ucode_id;
+ hdr->hs_fmc_params.fuse_ver = lsfw->fuse_ver;
+ ret = nvkm_falcon_fw_patch(&fw);
+ nvkm_falcon_put(fw.falcon, &acr->subdev);
+ }
+ }
+
+ nvkm_wobj(acr->wpr, lsfw->offset.lsb, hdr, sizeof(*hdr));
+ kvfree(hdr);
+ return ret;
+}
+
+static int
+ga102_acr_wpr_build(struct nvkm_acr *acr, struct nvkm_acr_lsf *rtos)
+{
+ struct nvkm_acr_lsfw *lsfw;
+ struct wpr_header_v2 hdr;
+ u32 offset = 0;
+ int ret;
+
+ /*XXX: shared sub-WPR headers, fill terminator for now. */
+ nvkm_wo32(acr->wpr, 0x300, (2 << 16) | WPR_GENERIC_HEADER_ID_LSF_SHARED_SUB_WPR);
+ nvkm_wo32(acr->wpr, 0x304, 0x14);
+ nvkm_wo32(acr->wpr, 0x308, 0xffffffff);
+ nvkm_wo32(acr->wpr, 0x30c, 0);
+ nvkm_wo32(acr->wpr, 0x310, 0);
+
+ /* Fill per-LSF structures. */
+ list_for_each_entry(lsfw, &acr->lsfw, head) {
+ struct lsf_signature_v2 *sig = (void *)lsfw->sig->data;
+
+ hdr.hdr.identifier = WPR_GENERIC_HEADER_ID_LSF_WPR_HEADER;
+ hdr.hdr.version = 2;
+ hdr.hdr.size = sizeof(hdr);
+ hdr.wpr.falcon_id = lsfw->id;
+ hdr.wpr.lsb_offset = lsfw->offset.lsb;
+ hdr.wpr.bootstrap_owner = NVKM_ACR_LSF_GSPLITE;
+ hdr.wpr.lazy_bootstrap = 1;
+ hdr.wpr.bin_version = sig->ls_ucode_version;
+ hdr.wpr.status = WPR_HEADER_V1_STATUS_COPY;
+
+ /* Write WPR header. */
+ nvkm_wobj(acr->wpr, offset, &hdr, sizeof(hdr));
+ offset += sizeof(hdr);
+
+ /* Write LSB header. */
+ ret = ga102_acr_wpr_build_lsb(acr, lsfw);
+ if (ret)
+ return ret;
+
+ /* Write ucode image. */
+ nvkm_wobj(acr->wpr, lsfw->offset.img,
+ lsfw->img.data,
+ lsfw->img.size);
+
+ /* Write bootloader data. */
+ lsfw->func->bld_write(acr, lsfw->offset.bld, lsfw);
+ }
+
+ /* Finalise WPR. */
+ hdr.hdr.identifier = WPR_GENERIC_HEADER_ID_LSF_WPR_HEADER;
+ hdr.hdr.version = 2;
+ hdr.hdr.size = sizeof(hdr);
+ hdr.wpr.falcon_id = WPR_HEADER_V1_FALCON_ID_INVALID;
+ nvkm_wobj(acr->wpr, offset, &hdr, sizeof(hdr));
+ return 0;
+}
+
+static u32
+ga102_acr_wpr_layout(struct nvkm_acr *acr)
+{
+ struct nvkm_acr_lsfw *lsfw;
+ u32 wpr = 0;
+
+ wpr += 21 /* MAX_LSF */ * sizeof(struct wpr_header_v2);
+ wpr = ALIGN(wpr, 256);
+
+ wpr += 0x100; /* Shared sub-WPR headers. */
+
+ list_for_each_entry(lsfw, &acr->lsfw, head) {
+ wpr = ALIGN(wpr, 256);
+ lsfw->offset.lsb = wpr;
+ wpr += sizeof(struct lsb_header_v2);
+
+ wpr = ALIGN(wpr, 4096);
+ lsfw->offset.img = wpr;
+ wpr += lsfw->img.size;
+
+ wpr = ALIGN(wpr, 256);
+ lsfw->offset.bld = wpr;
+ lsfw->bl_data_size = ALIGN(lsfw->func->bld_size, 256);
+ wpr += lsfw->bl_data_size;
+ }
+
+ return wpr;
+}
+
+static int
+ga102_acr_wpr_parse(struct nvkm_acr *acr)
+{
+ const struct wpr_header_v2 *hdr = (void *)acr->wpr_fw->data;
+
+ while (hdr->wpr.falcon_id != WPR_HEADER_V1_FALCON_ID_INVALID) {
+ wpr_header_v2_dump(&acr->subdev, hdr);
+ if (!nvkm_acr_lsfw_add(NULL, acr, NULL, (hdr++)->wpr.falcon_id))
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+MODULE_FIRMWARE("nvidia/ga102/acr/ucode_unload.bin");
+MODULE_FIRMWARE("nvidia/ga103/acr/ucode_unload.bin");
+MODULE_FIRMWARE("nvidia/ga104/acr/ucode_unload.bin");
+MODULE_FIRMWARE("nvidia/ga106/acr/ucode_unload.bin");
+MODULE_FIRMWARE("nvidia/ga107/acr/ucode_unload.bin");
+
+static const struct nvkm_acr_hsf_fwif
+ga102_acr_unload_fwif[] = {
+ { 0, ga100_acr_hsfw_ctor, &ga102_flcn_fw, NVKM_ACR_HSF_SEC2 },
+ {}
+};
+
+MODULE_FIRMWARE("nvidia/ga102/acr/ucode_asb.bin");
+MODULE_FIRMWARE("nvidia/ga103/acr/ucode_asb.bin");
+MODULE_FIRMWARE("nvidia/ga104/acr/ucode_asb.bin");
+MODULE_FIRMWARE("nvidia/ga106/acr/ucode_asb.bin");
+MODULE_FIRMWARE("nvidia/ga107/acr/ucode_asb.bin");
+
+static const struct nvkm_acr_hsf_fwif
+ga102_acr_asb_fwif[] = {
+ { 0, ga100_acr_hsfw_ctor, &ga102_flcn_fw, NVKM_ACR_HSF_GSP },
+ {}
+};
+
+static const struct nvkm_falcon_fw_func
+ga102_acr_ahesasc_0 = {
+ .signature = ga100_flcn_fw_signature,
+ .reset = gm200_flcn_fw_reset,
+ .setup = gp102_acr_load_setup,
+ .load = ga102_flcn_fw_load,
+ .boot = ga102_flcn_fw_boot,
+};
+
+MODULE_FIRMWARE("nvidia/ga102/acr/ucode_ahesasc.bin");
+MODULE_FIRMWARE("nvidia/ga103/acr/ucode_ahesasc.bin");
+MODULE_FIRMWARE("nvidia/ga104/acr/ucode_ahesasc.bin");
+MODULE_FIRMWARE("nvidia/ga106/acr/ucode_ahesasc.bin");
+MODULE_FIRMWARE("nvidia/ga107/acr/ucode_ahesasc.bin");
+
+static const struct nvkm_acr_hsf_fwif
+ga102_acr_ahesasc_fwif[] = {
+ { 0, ga100_acr_hsfw_ctor, &ga102_acr_ahesasc_0, NVKM_ACR_HSF_SEC2 },
+ {}
+};
+
+static const struct nvkm_acr_func
+ga102_acr = {
+ .ahesasc = ga102_acr_ahesasc_fwif,
+ .asb = ga102_acr_asb_fwif,
+ .unload = ga102_acr_unload_fwif,
+ .wpr_parse = ga102_acr_wpr_parse,
+ .wpr_layout = ga102_acr_wpr_layout,
+ .wpr_alloc = gp102_acr_wpr_alloc,
+ .wpr_patch = ga102_acr_wpr_patch,
+ .wpr_build = ga102_acr_wpr_build,
+ .wpr_check = ga100_acr_wpr_check,
+ .init = tu102_acr_init,
+};
+
+static int
+ga102_acr_load(struct nvkm_acr *acr, int version,
+ const struct nvkm_acr_fwif *fwif)
+{
+ struct nvkm_subdev *subdev = &acr->subdev;
+ const struct nvkm_acr_hsf_fwif *hsfwif;
+
+ hsfwif = nvkm_firmware_load(subdev, fwif->func->ahesasc, "AcrAHESASC",
+ acr, NULL, "acr/ucode_ahesasc", "AHESASC");
+ if (IS_ERR(hsfwif))
+ return PTR_ERR(hsfwif);
+
+ hsfwif = nvkm_firmware_load(subdev, fwif->func->asb, "AcrASB",
+ acr, NULL, "acr/ucode_asb", "ASB");
+ if (IS_ERR(hsfwif))
+ return PTR_ERR(hsfwif);
+
+ hsfwif = nvkm_firmware_load(subdev, fwif->func->unload, "AcrUnload",
+ acr, NULL, "acr/ucode_unload", "unload");
+ if (IS_ERR(hsfwif))
+ return PTR_ERR(hsfwif);
+
+ return 0;
+}
+
+static const struct nvkm_acr_fwif
+ga102_acr_fwif[] = {
+ { 0, ga102_acr_load, &ga102_acr },
+ { -1, gm200_acr_nofw, &gm200_acr },
+ {}
+};
+
+int
+ga102_acr_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
+ struct nvkm_acr **pacr)
+{
+ return nvkm_acr_new_(ga102_acr_fwif, device, type, inst, pacr);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c
index 82b4c8e1457c..31079c947758 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm200.c
@@ -46,7 +46,7 @@ gm200_acr_nofw(struct nvkm_acr *acr, int ver, const struct nvkm_acr_fwif *fwif)
int
gm200_acr_init(struct nvkm_acr *acr)
{
- return nvkm_acr_hsf_boot(acr, "load");
+ return nvkm_acr_hsfw_boot(acr, "load");
}
void
@@ -61,7 +61,7 @@ gm200_acr_wpr_check(struct nvkm_acr *acr, u64 *start, u64 *limit)
*limit = *limit + 0x20000;
}
-void
+int
gm200_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust)
{
struct nvkm_subdev *subdev = &acr->subdev;
@@ -86,6 +86,8 @@ gm200_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust)
}
offset += sizeof(hdr);
} while (hdr.falcon_id != WPR_HEADER_V0_FALCON_ID_INVALID);
+
+ return 0;
}
void
@@ -219,162 +221,50 @@ gm200_acr_wpr_parse(struct nvkm_acr *acr)
return 0;
}
-void
-gm200_acr_hsfw_bld(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf)
+int
+gm200_acr_hsfw_load_bld(struct nvkm_falcon_fw *fw)
{
struct flcn_bl_dmem_desc_v1 hsdesc = {
.ctx_dma = FALCON_DMAIDX_VIRT,
- .code_dma_base = hsf->vma->addr,
- .non_sec_code_off = hsf->non_sec_addr,
- .non_sec_code_size = hsf->non_sec_size,
- .sec_code_off = hsf->sec_addr,
- .sec_code_size = hsf->sec_size,
+ .code_dma_base = fw->vma->addr,
+ .non_sec_code_off = fw->nmem_base,
+ .non_sec_code_size = fw->nmem_size,
+ .sec_code_off = fw->imem_base,
+ .sec_code_size = fw->imem_size,
.code_entry_point = 0,
- .data_dma_base = hsf->vma->addr + hsf->data_addr,
- .data_size = hsf->data_size,
+ .data_dma_base = fw->vma->addr + fw->dmem_base_img,
+ .data_size = fw->dmem_size,
};
- flcn_bl_dmem_desc_v1_dump(&acr->subdev, &hsdesc);
-
- nvkm_falcon_load_dmem(hsf->falcon, &hsdesc, 0, sizeof(hsdesc), 0);
-}
-
-int
-gm200_acr_hsfw_boot(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf,
- u32 intr_clear, u32 mbox0_ok)
-{
- struct nvkm_subdev *subdev = &acr->subdev;
- struct nvkm_device *device = subdev->device;
- struct nvkm_falcon *falcon = hsf->falcon;
- u32 mbox0, mbox1;
- int ret;
-
- /* Reset falcon. */
- nvkm_falcon_reset(falcon);
- nvkm_falcon_bind_context(falcon, acr->inst);
+ flcn_bl_dmem_desc_v1_dump(fw->falcon->user, &hsdesc);
- /* Load bootloader into IMEM. */
- nvkm_falcon_load_imem(falcon, hsf->imem,
- falcon->code.limit - hsf->imem_size,
- hsf->imem_size,
- hsf->imem_tag,
- 0, false);
-
- /* Load bootloader data into DMEM. */
- hsf->func->bld(acr, hsf);
-
- /* Boot the falcon. */
- nvkm_mc_intr_mask(device, falcon->owner->type, falcon->owner->inst, false);
-
- nvkm_falcon_wr32(falcon, 0x040, 0xdeada5a5);
- nvkm_falcon_set_start_addr(falcon, hsf->imem_tag << 8);
- nvkm_falcon_start(falcon);
- ret = nvkm_falcon_wait_for_halt(falcon, 100);
- if (ret)
- return ret;
-
- /* Check for successful completion. */
- mbox0 = nvkm_falcon_rd32(falcon, 0x040);
- mbox1 = nvkm_falcon_rd32(falcon, 0x044);
- nvkm_debug(subdev, "mailbox %08x %08x\n", mbox0, mbox1);
- if (mbox0 && mbox0 != mbox0_ok)
- return -EIO;
-
- nvkm_falcon_clear_interrupt(falcon, intr_clear);
- nvkm_mc_intr_mask(device, falcon->owner->type, falcon->owner->inst, true);
- return ret;
+ return nvkm_falcon_pio_wr(fw->falcon, (u8 *)&hsdesc, 0, 0, DMEM, 0, sizeof(hsdesc), 0, 0);
}
int
-gm200_acr_hsfw_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw,
- struct nvkm_falcon *falcon)
+gm200_acr_hsfw_ctor(struct nvkm_acr *acr, const char *bl, const char *fw, const char *name, int ver,
+ const struct nvkm_acr_hsf_fwif *fwif)
{
- struct nvkm_subdev *subdev = &acr->subdev;
- struct nvkm_acr_hsf *hsf;
- int ret;
-
- /* Patch the appropriate signature (production/debug) into the FW
- * image, as determined by the mode the falcon is in.
- */
- ret = nvkm_falcon_get(falcon, subdev);
- if (ret)
- return ret;
-
- if (hsfw->sig.patch_loc) {
- if (!falcon->debug) {
- nvkm_debug(subdev, "patching production signature\n");
- memcpy(hsfw->image + hsfw->sig.patch_loc,
- hsfw->sig.prod.data,
- hsfw->sig.prod.size);
- } else {
- nvkm_debug(subdev, "patching debug signature\n");
- memcpy(hsfw->image + hsfw->sig.patch_loc,
- hsfw->sig.dbg.data,
- hsfw->sig.dbg.size);
- }
- }
-
- nvkm_falcon_put(falcon, subdev);
+ struct nvkm_acr_hsfw *hsfw;
- if (!(hsf = kzalloc(sizeof(*hsf), GFP_KERNEL)))
+ if (!(hsfw = kzalloc(sizeof(*hsfw), GFP_KERNEL)))
return -ENOMEM;
- hsf->func = hsfw->func;
- hsf->name = hsfw->name;
- list_add_tail(&hsf->head, &acr->hsf);
-
- hsf->imem_size = hsfw->imem_size;
- hsf->imem_tag = hsfw->imem_tag;
- hsf->imem = kmemdup(hsfw->imem, hsfw->imem_size, GFP_KERNEL);
- if (!hsf->imem)
- return -ENOMEM;
-
- hsf->non_sec_addr = hsfw->non_sec_addr;
- hsf->non_sec_size = hsfw->non_sec_size;
- hsf->sec_addr = hsfw->sec_addr;
- hsf->sec_size = hsfw->sec_size;
- hsf->data_addr = hsfw->data_addr;
- hsf->data_size = hsfw->data_size;
-
- /* Make the FW image accessible to the HS bootloader. */
- ret = nvkm_memory_new(subdev->device, NVKM_MEM_TARGET_INST,
- hsfw->image_size, 0x1000, false, &hsf->ucode);
- if (ret)
- return ret;
-
- nvkm_kmap(hsf->ucode);
- nvkm_wobj(hsf->ucode, 0, hsfw->image, hsfw->image_size);
- nvkm_done(hsf->ucode);
-
- ret = nvkm_vmm_get(acr->vmm, 12, nvkm_memory_size(hsf->ucode),
- &hsf->vma);
- if (ret)
- return ret;
-
- ret = nvkm_memory_map(hsf->ucode, 0, acr->vmm, hsf->vma, NULL, 0);
- if (ret)
- return ret;
- hsf->falcon = falcon;
- return 0;
-}
+ hsfw->falcon_id = fwif->falcon_id;
+ hsfw->boot_mbox0 = fwif->boot_mbox0;
+ hsfw->intr_clear = fwif->intr_clear;
+ list_add_tail(&hsfw->head, &acr->hsfw);
-int
-gm200_acr_unload_boot(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf)
-{
- return gm200_acr_hsfw_boot(acr, hsf, 0, 0x1d);
-}
-
-int
-gm200_acr_unload_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw)
-{
- return gm200_acr_hsfw_load(acr, hsfw, &acr->subdev.device->pmu->falcon);
+ return nvkm_falcon_fw_ctor_hs(fwif->func, name, &acr->subdev, bl, fw, ver, NULL, &hsfw->fw);
}
-const struct nvkm_acr_hsf_func
+const struct nvkm_falcon_fw_func
gm200_acr_unload_0 = {
- .load = gm200_acr_unload_load,
- .boot = gm200_acr_unload_boot,
- .bld = gm200_acr_hsfw_bld,
+ .signature = gm200_flcn_fw_signature,
+ .reset = gm200_flcn_fw_reset,
+ .load = gm200_flcn_fw_load,
+ .load_bld = gm200_acr_hsfw_load_bld,
+ .boot = gm200_flcn_fw_boot,
};
MODULE_FIRMWARE("nvidia/gm200/acr/ucode_unload.bin");
@@ -384,20 +274,15 @@ MODULE_FIRMWARE("nvidia/gp100/acr/ucode_unload.bin");
static const struct nvkm_acr_hsf_fwif
gm200_acr_unload_fwif[] = {
- { 0, nvkm_acr_hsfw_load, &gm200_acr_unload_0 },
+ { 0, gm200_acr_hsfw_ctor, &gm200_acr_unload_0, NVKM_ACR_HSF_PMU, 0, 0x00000010 },
{}
};
-int
-gm200_acr_load_boot(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf)
-{
- return gm200_acr_hsfw_boot(acr, hsf, 0x10, 0);
-}
-
static int
-gm200_acr_load_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw)
+gm200_acr_load_setup(struct nvkm_falcon_fw *fw)
{
- struct flcn_acr_desc *desc = (void *)&hsfw->image[hsfw->data_addr];
+ struct flcn_acr_desc *desc = (void *)&fw->fw.img[fw->dmem_base_img];
+ struct nvkm_acr *acr = fw->falcon->owner->device->acr;
desc->wpr_region_id = 1;
desc->regions.no_regions = 2;
@@ -408,15 +293,17 @@ gm200_acr_load_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw)
desc->regions.region_props[0].write_mask = 0xc;
desc->regions.region_props[0].client_mask = 0x2;
flcn_acr_desc_dump(&acr->subdev, desc);
-
- return gm200_acr_hsfw_load(acr, hsfw, &acr->subdev.device->pmu->falcon);
+ return 0;
}
-static const struct nvkm_acr_hsf_func
+static const struct nvkm_falcon_fw_func
gm200_acr_load_0 = {
- .load = gm200_acr_load_load,
- .boot = gm200_acr_load_boot,
- .bld = gm200_acr_hsfw_bld,
+ .signature = gm200_flcn_fw_signature,
+ .reset = gm200_flcn_fw_reset,
+ .setup = gm200_acr_load_setup,
+ .load = gm200_flcn_fw_load,
+ .load_bld = gm200_acr_hsfw_load_bld,
+ .boot = gm200_flcn_fw_boot,
};
MODULE_FIRMWARE("nvidia/gm200/acr/bl.bin");
@@ -433,7 +320,7 @@ MODULE_FIRMWARE("nvidia/gp100/acr/ucode_load.bin");
static const struct nvkm_acr_hsf_fwif
gm200_acr_load_fwif[] = {
- { 0, nvkm_acr_hsfw_load, &gm200_acr_load_0 },
+ { 0, gm200_acr_hsfw_ctor, &gm200_acr_load_0, NVKM_ACR_HSF_PMU, 0, 0x00000010 },
{}
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c
index 54e996f2f630..ef5fb79128b1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gm20b.c
@@ -45,43 +45,47 @@ gm20b_acr_wpr_alloc(struct nvkm_acr *acr, u32 wpr_size)
wpr_size, 0, true, &acr->wpr);
}
-static void
-gm20b_acr_load_bld(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf)
+static int
+gm20b_acr_hsfw_load_bld(struct nvkm_falcon_fw *fw)
{
struct flcn_bl_dmem_desc hsdesc = {
.ctx_dma = FALCON_DMAIDX_VIRT,
- .code_dma_base = hsf->vma->addr >> 8,
- .non_sec_code_off = hsf->non_sec_addr,
- .non_sec_code_size = hsf->non_sec_size,
- .sec_code_off = hsf->sec_addr,
- .sec_code_size = hsf->sec_size,
+ .code_dma_base = fw->vma->addr >> 8,
+ .non_sec_code_off = fw->nmem_base,
+ .non_sec_code_size = fw->nmem_size,
+ .sec_code_off = fw->imem_base,
+ .sec_code_size = fw->imem_size,
.code_entry_point = 0,
- .data_dma_base = (hsf->vma->addr + hsf->data_addr) >> 8,
- .data_size = hsf->data_size,
+ .data_dma_base = (fw->vma->addr + fw->dmem_base_img) >> 8,
+ .data_size = fw->dmem_size,
};
- flcn_bl_dmem_desc_dump(&acr->subdev, &hsdesc);
+ flcn_bl_dmem_desc_dump(fw->falcon->user, &hsdesc);
- nvkm_falcon_load_dmem(hsf->falcon, &hsdesc, 0, sizeof(hsdesc), 0);
+ return nvkm_falcon_pio_wr(fw->falcon, (u8 *)&hsdesc, 0, 0, DMEM, 0, sizeof(hsdesc), 0, 0);
}
+
static int
-gm20b_acr_load_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw)
+gm20b_acr_load_setup(struct nvkm_falcon_fw *fw)
{
- struct flcn_acr_desc *desc = (void *)&hsfw->image[hsfw->data_addr];
+ struct flcn_acr_desc *desc = (void *)&fw->fw.img[fw->dmem_base_img];
+ struct nvkm_acr *acr = fw->falcon->owner->device->acr;
desc->ucode_blob_base = nvkm_memory_addr(acr->wpr);
desc->ucode_blob_size = nvkm_memory_size(acr->wpr);
flcn_acr_desc_dump(&acr->subdev, desc);
-
- return gm200_acr_hsfw_load(acr, hsfw, &acr->subdev.device->pmu->falcon);
+ return 0;
}
-const struct nvkm_acr_hsf_func
+const struct nvkm_falcon_fw_func
gm20b_acr_load_0 = {
- .load = gm20b_acr_load_load,
- .boot = gm200_acr_load_boot,
- .bld = gm20b_acr_load_bld,
+ .signature = gm200_flcn_fw_signature,
+ .reset = gm200_flcn_fw_reset,
+ .setup = gm20b_acr_load_setup,
+ .load = gm200_flcn_fw_load,
+ .load_bld = gm20b_acr_hsfw_load_bld,
+ .boot = gm200_flcn_fw_boot,
};
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
@@ -91,7 +95,7 @@ MODULE_FIRMWARE("nvidia/gm20b/acr/ucode_load.bin");
static const struct nvkm_acr_hsf_fwif
gm20b_acr_load_fwif[] = {
- { 0, nvkm_acr_hsfw_load, &gm20b_acr_load_0 },
+ { 0, gm200_acr_hsfw_ctor, &gm20b_acr_load_0, NVKM_ACR_HSF_PMU, 0, 0x10 },
{}
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c
index fd97a935a380..084f28449e52 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp102.c
@@ -29,7 +29,7 @@
#include <nvfw/acr.h>
#include <nvfw/flcn.h>
-void
+int
gp102_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust)
{
struct wpr_header_v1 hdr;
@@ -54,6 +54,8 @@ gp102_acr_wpr_patch(struct nvkm_acr *acr, s64 adjust)
offset += sizeof(hdr);
} while (hdr.falcon_id != WPR_HEADER_V1_FALCON_ID_INVALID);
+
+ return 0;
}
int
@@ -187,14 +189,15 @@ MODULE_FIRMWARE("nvidia/gp107/acr/ucode_unload.bin");
static const struct nvkm_acr_hsf_fwif
gp102_acr_unload_fwif[] = {
- { 0, nvkm_acr_hsfw_load, &gm200_acr_unload_0 },
+ { 0, gm200_acr_hsfw_ctor, &gm200_acr_unload_0, NVKM_ACR_HSF_PMU, 0x1d, 0x00000010 },
{}
};
int
-gp102_acr_load_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw)
+gp102_acr_load_setup(struct nvkm_falcon_fw *fw)
{
- struct flcn_acr_desc_v1 *desc = (void *)&hsfw->image[hsfw->data_addr];
+ struct flcn_acr_desc_v1 *desc = (void *)&fw->fw.img[fw->dmem_base_img];
+ struct nvkm_acr *acr = fw->falcon->owner->device->acr;
desc->wpr_region_id = 1;
desc->regions.no_regions = 2;
@@ -204,19 +207,19 @@ gp102_acr_load_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw)
desc->regions.region_props[0].read_mask = 0xf;
desc->regions.region_props[0].write_mask = 0xc;
desc->regions.region_props[0].client_mask = 0x2;
- desc->regions.region_props[0].shadow_mem_start_addr =
- acr->shadow_start >> 8;
+ desc->regions.region_props[0].shadow_mem_start_addr = acr->shadow_start >> 8;
flcn_acr_desc_v1_dump(&acr->subdev, desc);
-
- return gm200_acr_hsfw_load(acr, hsfw,
- &acr->subdev.device->sec2->falcon);
+ return 0;
}
-static const struct nvkm_acr_hsf_func
+static const struct nvkm_falcon_fw_func
gp102_acr_load_0 = {
- .load = gp102_acr_load_load,
- .boot = gm200_acr_load_boot,
- .bld = gm200_acr_hsfw_bld,
+ .signature = gm200_flcn_fw_signature,
+ .reset = gm200_flcn_fw_reset,
+ .setup = gp102_acr_load_setup,
+ .load = gm200_flcn_fw_load,
+ .load_bld = gm200_acr_hsfw_load_bld,
+ .boot = gm200_flcn_fw_boot,
};
MODULE_FIRMWARE("nvidia/gp102/acr/bl.bin");
@@ -233,7 +236,7 @@ MODULE_FIRMWARE("nvidia/gp107/acr/ucode_load.bin");
static const struct nvkm_acr_hsf_fwif
gp102_acr_load_fwif[] = {
- { 0, nvkm_acr_hsfw_load, &gp102_acr_load_0 },
+ { 0, gm200_acr_hsfw_ctor, &gp102_acr_load_0, NVKM_ACR_HSF_SEC2, 0, 0x00000010 },
{}
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c
index 373d638a2177..6ab9d4959c17 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp108.c
@@ -25,63 +25,62 @@
#include <nvfw/flcn.h>
-void
-gp108_acr_hsfw_bld(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf)
+int
+gp108_acr_hsfw_load_bld(struct nvkm_falcon_fw *fw)
{
struct flcn_bl_dmem_desc_v2 hsdesc = {
.ctx_dma = FALCON_DMAIDX_VIRT,
- .code_dma_base = hsf->vma->addr,
- .non_sec_code_off = hsf->non_sec_addr,
- .non_sec_code_size = hsf->non_sec_size,
- .sec_code_off = hsf->sec_addr,
- .sec_code_size = hsf->sec_size,
+ .code_dma_base = fw->vma->addr,
+ .non_sec_code_off = fw->nmem_base,
+ .non_sec_code_size = fw->nmem_size,
+ .sec_code_off = fw->imem_base,
+ .sec_code_size = fw->imem_size,
.code_entry_point = 0,
- .data_dma_base = hsf->vma->addr + hsf->data_addr,
- .data_size = hsf->data_size,
+ .data_dma_base = fw->vma->addr + fw->dmem_base_img,
+ .data_size = fw->dmem_size,
.argc = 0,
.argv = 0,
};
- flcn_bl_dmem_desc_v2_dump(&acr->subdev, &hsdesc);
+ flcn_bl_dmem_desc_v2_dump(fw->falcon->user, &hsdesc);
- nvkm_falcon_load_dmem(hsf->falcon, &hsdesc, 0, sizeof(hsdesc), 0);
+ return nvkm_falcon_pio_wr(fw->falcon, (u8 *)&hsdesc, 0, 0, DMEM, 0, sizeof(hsdesc), 0, 0);
}
-const struct nvkm_acr_hsf_func
-gp108_acr_unload_0 = {
- .load = gm200_acr_unload_load,
- .boot = gm200_acr_unload_boot,
- .bld = gp108_acr_hsfw_bld,
+const struct nvkm_falcon_fw_func
+gp108_acr_hsfw_0 = {
+ .signature = gm200_flcn_fw_signature,
+ .reset = gm200_flcn_fw_reset,
+ .load = gm200_flcn_fw_load,
+ .load_bld = gp108_acr_hsfw_load_bld,
+ .boot = gm200_flcn_fw_boot,
};
MODULE_FIRMWARE("nvidia/gp108/acr/unload_bl.bin");
MODULE_FIRMWARE("nvidia/gp108/acr/ucode_unload.bin");
-MODULE_FIRMWARE("nvidia/gv100/acr/unload_bl.bin");
-MODULE_FIRMWARE("nvidia/gv100/acr/ucode_unload.bin");
-
static const struct nvkm_acr_hsf_fwif
gp108_acr_unload_fwif[] = {
- { 0, nvkm_acr_hsfw_load, &gp108_acr_unload_0 },
+ { 0, gm200_acr_hsfw_ctor, &gp108_acr_hsfw_0, NVKM_ACR_HSF_PMU, 0x1d, 0x00000010 },
{}
};
-static const struct nvkm_acr_hsf_func
+const struct nvkm_falcon_fw_func
gp108_acr_load_0 = {
- .load = gp102_acr_load_load,
- .boot = gm200_acr_load_boot,
- .bld = gp108_acr_hsfw_bld,
+ .signature = gm200_flcn_fw_signature,
+ .reset = gm200_flcn_fw_reset,
+ .setup = gp102_acr_load_setup,
+ .load = gm200_flcn_fw_load,
+ .load_bld = gp108_acr_hsfw_load_bld,
+ .boot = gm200_flcn_fw_boot,
};
MODULE_FIRMWARE("nvidia/gp108/acr/bl.bin");
MODULE_FIRMWARE("nvidia/gp108/acr/ucode_load.bin");
-MODULE_FIRMWARE("nvidia/gv100/acr/bl.bin");
-MODULE_FIRMWARE("nvidia/gv100/acr/ucode_load.bin");
-
static const struct nvkm_acr_hsf_fwif
gp108_acr_load_fwif[] = {
- { 0, nvkm_acr_hsfw_load, &gp108_acr_load_0 },
+ { 0, gm200_acr_hsfw_ctor, &gp108_acr_load_0, NVKM_ACR_HSF_SEC2, 0, 0x00000010 },
{}
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c
index f03ba028867b..a3422ab6deab 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gp10b.c
@@ -28,7 +28,7 @@ MODULE_FIRMWARE("nvidia/gp10b/acr/ucode_load.bin");
static const struct nvkm_acr_hsf_fwif
gp10b_acr_load_fwif[] = {
- { 0, nvkm_acr_hsfw_load, &gm20b_acr_load_0 },
+ { 0, gm200_acr_hsfw_ctor, &gm20b_acr_load_0, NVKM_ACR_HSF_PMU, 0, 0x00000010 },
{}
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gv100.c
new file mode 100644
index 000000000000..4c5ca6b40027
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/gv100.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2022 Red Hat 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 "priv.h"
+
+MODULE_FIRMWARE("nvidia/gv100/acr/unload_bl.bin");
+MODULE_FIRMWARE("nvidia/gv100/acr/ucode_unload.bin");
+
+static const struct nvkm_acr_hsf_fwif
+gv100_acr_unload_fwif[] = {
+ { 0, gm200_acr_hsfw_ctor, &gp108_acr_hsfw_0, NVKM_ACR_HSF_PMU, 0, 0x00000000 },
+ {}
+};
+
+MODULE_FIRMWARE("nvidia/gv100/acr/bl.bin");
+MODULE_FIRMWARE("nvidia/gv100/acr/ucode_load.bin");
+
+static const struct nvkm_acr_hsf_fwif
+gv100_acr_load_fwif[] = {
+ { 0, gm200_acr_hsfw_ctor, &gp108_acr_load_0, NVKM_ACR_HSF_SEC2, 0, 0x00000010 },
+ {}
+};
+
+static const struct nvkm_acr_func
+gv100_acr = {
+ .load = gv100_acr_load_fwif,
+ .unload = gv100_acr_unload_fwif,
+ .wpr_parse = gp102_acr_wpr_parse,
+ .wpr_layout = gp102_acr_wpr_layout,
+ .wpr_alloc = gp102_acr_wpr_alloc,
+ .wpr_build = gp102_acr_wpr_build,
+ .wpr_patch = gp102_acr_wpr_patch,
+ .wpr_check = gm200_acr_wpr_check,
+ .init = gm200_acr_init,
+};
+
+static const struct nvkm_acr_fwif
+gv100_acr_fwif[] = {
+ { 0, gp102_acr_load, &gv100_acr },
+ { -1, gm200_acr_nofw, &gm200_acr },
+ {}
+};
+
+int
+gv100_acr_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
+ struct nvkm_acr **pacr)
+{
+ return nvkm_acr_new_(gv100_acr_fwif, device, type, inst, pacr);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c
deleted file mode 100644
index a6ea89a5d51a..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/hsfw.c
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright 2019 Red Hat 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 "priv.h"
-
-#include <core/firmware.h>
-
-#include <nvfw/fw.h>
-#include <nvfw/hs.h>
-
-static void
-nvkm_acr_hsfw_del(struct nvkm_acr_hsfw *hsfw)
-{
- list_del(&hsfw->head);
- kfree(hsfw->imem);
- kfree(hsfw->image);
- kfree(hsfw->sig.prod.data);
- kfree(hsfw->sig.dbg.data);
- kfree(hsfw);
-}
-
-void
-nvkm_acr_hsfw_del_all(struct nvkm_acr *acr)
-{
- struct nvkm_acr_hsfw *hsfw, *hsft;
- list_for_each_entry_safe(hsfw, hsft, &acr->hsfw, head) {
- nvkm_acr_hsfw_del(hsfw);
- }
-}
-
-static int
-nvkm_acr_hsfw_load_image(struct nvkm_acr *acr, const char *name, int ver,
- struct nvkm_acr_hsfw *hsfw)
-{
- struct nvkm_subdev *subdev = &acr->subdev;
- const struct firmware *fw;
- const struct nvfw_bin_hdr *hdr;
- const struct nvfw_hs_header *fwhdr;
- const struct nvfw_hs_load_header *lhdr;
- u32 loc, sig;
- int ret;
-
- ret = nvkm_firmware_get(subdev, name, ver, &fw);
- if (ret < 0)
- return ret;
-
- hdr = nvfw_bin_hdr(subdev, fw->data);
- fwhdr = nvfw_hs_header(subdev, fw->data + hdr->header_offset);
-
- /* Earlier FW releases by NVIDIA for Nouveau's use aren't in NVIDIA's
- * standard format, and don't have the indirection seen in the 0x10de
- * case.
- */
- switch (hdr->bin_magic) {
- case 0x000010de:
- loc = *(u32 *)(fw->data + fwhdr->patch_loc);
- sig = *(u32 *)(fw->data + fwhdr->patch_sig);
- break;
- case 0x3b1d14f0:
- loc = fwhdr->patch_loc;
- sig = fwhdr->patch_sig;
- break;
- default:
- ret = -EINVAL;
- goto done;
- }
-
- lhdr = nvfw_hs_load_header(subdev, fw->data + fwhdr->hdr_offset);
-
- if (!(hsfw->image = kmalloc(hdr->data_size, GFP_KERNEL))) {
- ret = -ENOMEM;
- goto done;
- }
-
- memcpy(hsfw->image, fw->data + hdr->data_offset, hdr->data_size);
- hsfw->image_size = hdr->data_size;
- hsfw->non_sec_addr = lhdr->non_sec_code_off;
- hsfw->non_sec_size = lhdr->non_sec_code_size;
- hsfw->sec_addr = lhdr->apps[0];
- hsfw->sec_size = lhdr->apps[lhdr->num_apps];
- hsfw->data_addr = lhdr->data_dma_base;
- hsfw->data_size = lhdr->data_size;
-
- hsfw->sig.prod.size = fwhdr->sig_prod_size;
- hsfw->sig.prod.data = kmemdup(fw->data + fwhdr->sig_prod_offset + sig,
- hsfw->sig.prod.size, GFP_KERNEL);
- if (!hsfw->sig.prod.data) {
- ret = -ENOMEM;
- goto done;
- }
-
- hsfw->sig.dbg.size = fwhdr->sig_dbg_size;
- hsfw->sig.dbg.data = kmemdup(fw->data + fwhdr->sig_dbg_offset + sig,
- hsfw->sig.dbg.size, GFP_KERNEL);
- if (!hsfw->sig.dbg.data) {
- ret = -ENOMEM;
- goto done;
- }
-
- hsfw->sig.patch_loc = loc;
-done:
- nvkm_firmware_put(fw);
- return ret;
-}
-
-static int
-nvkm_acr_hsfw_load_bl(struct nvkm_acr *acr, const char *name, int ver,
- struct nvkm_acr_hsfw *hsfw)
-{
- struct nvkm_subdev *subdev = &acr->subdev;
- const struct nvfw_bin_hdr *hdr;
- const struct nvfw_bl_desc *desc;
- const struct firmware *fw;
- u8 *data;
- int ret;
-
- ret = nvkm_firmware_get(subdev, name, ver, &fw);
- if (ret)
- return ret;
-
- hdr = nvfw_bin_hdr(subdev, fw->data);
- desc = nvfw_bl_desc(subdev, fw->data + hdr->header_offset);
- data = (void *)fw->data + hdr->data_offset;
-
- hsfw->imem_size = desc->code_size;
- hsfw->imem_tag = desc->start_tag;
- hsfw->imem = kmemdup(data + desc->code_off, desc->code_size, GFP_KERNEL);
- nvkm_firmware_put(fw);
- if (!hsfw->imem)
- return -ENOMEM;
- else
- return 0;
-}
-
-int
-nvkm_acr_hsfw_load(struct nvkm_acr *acr, const char *bl, const char *fw,
- const char *name, int version,
- const struct nvkm_acr_hsf_fwif *fwif)
-{
- struct nvkm_acr_hsfw *hsfw;
- int ret;
-
- if (!(hsfw = kzalloc(sizeof(*hsfw), GFP_KERNEL)))
- return -ENOMEM;
-
- hsfw->func = fwif->func;
- hsfw->name = name;
- list_add_tail(&hsfw->head, &acr->hsfw);
-
- ret = nvkm_acr_hsfw_load_bl(acr, bl, version, hsfw);
- if (ret)
- goto done;
-
- ret = nvkm_acr_hsfw_load_image(acr, fw, version, hsfw);
-done:
- if (ret)
- nvkm_acr_hsfw_del(hsfw);
- return ret;
-}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c
index 9b1cf6711ae9..f36a359d4531 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/lsfw.c
@@ -29,6 +29,7 @@ void
nvkm_acr_lsfw_del(struct nvkm_acr_lsfw *lsfw)
{
nvkm_blob_dtor(&lsfw->img);
+ kfree(lsfw->sigs);
nvkm_firmware_put(lsfw->sig);
list_del(&lsfw->head);
kfree(lsfw);
@@ -177,6 +178,75 @@ nvkm_acr_lsfw_load_sig_image_desc_v1(struct nvkm_subdev *subdev,
}
int
+nvkm_acr_lsfw_load_sig_image_desc_v2(struct nvkm_subdev *subdev,
+ struct nvkm_falcon *falcon,
+ enum nvkm_acr_lsf_id id,
+ const char *path, int ver,
+ const struct nvkm_acr_lsf_func *func)
+{
+ const struct firmware *fw;
+ struct nvkm_acr_lsfw *lsfw;
+ const struct nvfw_ls_desc_v2 *desc;
+ int ret = 0;
+
+ lsfw = nvkm_acr_lsfw_load_sig_image_desc_(subdev, falcon, id, path, ver, func, &fw);
+ if (IS_ERR(lsfw))
+ return PTR_ERR(lsfw);
+
+ desc = nvfw_ls_desc_v2(subdev, fw->data);
+
+ lsfw->secure_bootloader = desc->secure_bootloader;
+ lsfw->bootloader_size = ALIGN(desc->bootloader_size, 256);
+ lsfw->bootloader_imem_offset = desc->bootloader_imem_offset;
+
+ lsfw->app_size = ALIGN(desc->app_size, 256);
+ lsfw->app_start_offset = desc->app_start_offset;
+ lsfw->app_imem_entry = desc->app_imem_entry;
+ lsfw->app_resident_code_offset = desc->app_resident_code_offset;
+ lsfw->app_resident_code_size = desc->app_resident_code_size;
+ lsfw->app_resident_data_offset = desc->app_resident_data_offset;
+ lsfw->app_resident_data_size = desc->app_resident_data_size;
+ lsfw->app_imem_offset = desc->app_imem_offset;
+ lsfw->app_dmem_offset = desc->app_dmem_offset;
+
+ lsfw->ucode_size = ALIGN(lsfw->app_resident_data_offset, 256) + lsfw->bootloader_size;
+ lsfw->data_size = lsfw->app_size + lsfw->bootloader_size - lsfw->ucode_size;
+
+ nvkm_firmware_put(fw);
+
+ if (lsfw->secure_bootloader) {
+ const struct firmware *hsbl;
+ const struct nvfw_ls_hsbl_bin_hdr *hdr;
+ const struct nvfw_ls_hsbl_hdr *hshdr;
+ u32 loc, sig, cnt, *meta;
+
+ ret = nvkm_firmware_load_name(subdev, path, "hs_bl_sig", ver, &hsbl);
+ if (ret)
+ return ret;
+
+ hdr = nvfw_ls_hsbl_bin_hdr(subdev, hsbl->data);
+ hshdr = nvfw_ls_hsbl_hdr(subdev, hsbl->data + hdr->header_offset);
+ meta = (u32 *)(hsbl->data + hshdr->meta_data_offset);
+ loc = *(u32 *)(hsbl->data + hshdr->patch_loc);
+ sig = *(u32 *)(hsbl->data + hshdr->patch_sig);
+ cnt = *(u32 *)(hsbl->data + hshdr->num_sig);
+
+ lsfw->fuse_ver = meta[0];
+ lsfw->engine_id = meta[1];
+ lsfw->ucode_id = meta[2];
+ lsfw->sig_size = hshdr->sig_prod_size / cnt;
+ lsfw->sig_nr = cnt;
+ lsfw->sigs = kmemdup(hsbl->data + hshdr->sig_prod_offset + sig,
+ lsfw->sig_nr * lsfw->sig_size, GFP_KERNEL);
+ nvkm_firmware_put(hsbl);
+ if (!lsfw->sigs)
+ ret = -ENOMEM;
+ }
+
+ return ret;
+}
+
+int
nvkm_acr_lsfw_load_bl_inst_data_sig(struct nvkm_subdev *subdev,
struct nvkm_falcon *falcon,
enum nvkm_acr_lsf_id id,
@@ -251,3 +321,78 @@ done:
nvkm_firmware_put(bl);
return ret;
}
+
+int
+nvkm_acr_lsfw_load_bl_sig_net(struct nvkm_subdev *subdev,
+ struct nvkm_falcon *falcon,
+ enum nvkm_acr_lsf_id id,
+ const char *path, int ver,
+ const struct nvkm_acr_lsf_func *func,
+ const void *inst_data, u32 inst_size,
+ const void *data_data, u32 data_size)
+{
+ struct nvkm_acr *acr = subdev->device->acr;
+ struct nvkm_acr_lsfw *lsfw;
+ const struct firmware _inst = { .data = inst_data, .size = inst_size };
+ const struct firmware _data = { .data = data_data, .size = data_size };
+ const struct firmware *bl = NULL, *inst = &_inst, *data = &_data;
+ const struct {
+ int bin_magic;
+ int bin_version;
+ int bin_size;
+ int header_offset;
+ int header_size;
+ } *hdr;
+ u32 *bldata;
+ int ret;
+
+ if (IS_ERR((lsfw = nvkm_acr_lsfw_add(func, acr, falcon, id))))
+ return PTR_ERR(lsfw);
+
+ ret = nvkm_firmware_load_name(subdev, path, "bl", ver, &bl);
+ if (ret)
+ goto done;
+
+ hdr = (const void *)bl->data;
+ bldata = (void *)(bl->data + hdr->header_offset);
+
+ ret = nvkm_firmware_load_name(subdev, path, "sig", ver, &lsfw->sig);
+ if (ret)
+ goto done;
+
+ lsfw->bootloader_size = ALIGN(hdr->header_size, 256);
+ lsfw->bootloader_imem_offset = func->bl_entry;
+
+ lsfw->app_start_offset = lsfw->bootloader_size;
+ lsfw->app_imem_entry = 0;
+ lsfw->app_resident_code_offset = 0;
+ lsfw->app_resident_code_size = ALIGN(inst->size, 256);
+ lsfw->app_resident_data_offset = lsfw->app_resident_code_size;
+ lsfw->app_resident_data_size = ALIGN(data->size, 256);
+ lsfw->app_imem_offset = 0;
+ lsfw->app_dmem_offset = 0;
+ lsfw->app_size = lsfw->app_resident_code_size + lsfw->app_resident_data_size;
+
+ lsfw->img.size = lsfw->bootloader_size + lsfw->app_size;
+ if (!(lsfw->img.data = kzalloc(lsfw->img.size, GFP_KERNEL))) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ memcpy(lsfw->img.data, bldata, lsfw->bootloader_size);
+ memcpy(lsfw->img.data + lsfw->app_start_offset +
+ lsfw->app_resident_code_offset, inst->data, inst->size);
+ memcpy(lsfw->img.data + lsfw->app_start_offset +
+ lsfw->app_resident_data_offset, data->data, data->size);
+
+ lsfw->ucode_size = ALIGN(lsfw->app_resident_data_offset, 256) +
+ lsfw->bootloader_size;
+ lsfw->data_size = lsfw->app_size + lsfw->bootloader_size -
+ lsfw->ucode_size;
+
+done:
+ if (ret)
+ nvkm_acr_lsfw_del(lsfw);
+ nvkm_firmware_put(bl);
+ return ret;
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h
index c30b841c9d35..4881c8ba3880 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/priv.h
@@ -24,7 +24,7 @@ struct nvkm_acr_func {
u32 (*wpr_layout)(struct nvkm_acr *);
int (*wpr_alloc)(struct nvkm_acr *, u32 wpr_size);
int (*wpr_build)(struct nvkm_acr *, struct nvkm_acr_lsf *rtos);
- void (*wpr_patch)(struct nvkm_acr *, s64 adjust);
+ int (*wpr_patch)(struct nvkm_acr *, s64 adjust);
void (*wpr_check)(struct nvkm_acr *, u64 *start, u64 *limit);
int (*init)(struct nvkm_acr *);
void (*fini)(struct nvkm_acr *);
@@ -35,7 +35,7 @@ extern const struct nvkm_acr_func gm200_acr;
int gm200_acr_wpr_parse(struct nvkm_acr *);
u32 gm200_acr_wpr_layout(struct nvkm_acr *);
int gm200_acr_wpr_build(struct nvkm_acr *, struct nvkm_acr_lsf *);
-void gm200_acr_wpr_patch(struct nvkm_acr *, s64);
+int gm200_acr_wpr_patch(struct nvkm_acr *, s64);
void gm200_acr_wpr_check(struct nvkm_acr *, u64 *, u64 *);
void gm200_acr_wpr_build_lsb_tail(struct nvkm_acr_lsfw *,
struct lsb_header_tail *);
@@ -48,96 +48,60 @@ u32 gp102_acr_wpr_layout(struct nvkm_acr *);
int gp102_acr_wpr_alloc(struct nvkm_acr *, u32 wpr_size);
int gp102_acr_wpr_build(struct nvkm_acr *, struct nvkm_acr_lsf *);
int gp102_acr_wpr_build_lsb(struct nvkm_acr *, struct nvkm_acr_lsfw *);
-void gp102_acr_wpr_patch(struct nvkm_acr *, s64);
+int gp102_acr_wpr_patch(struct nvkm_acr *, s64);
+
+int tu102_acr_init(struct nvkm_acr *);
+
+void ga100_acr_wpr_check(struct nvkm_acr *, u64 *, u64 *);
struct nvkm_acr_hsfw {
- const struct nvkm_acr_hsf_func *func;
- const char *name;
- struct list_head head;
+ struct nvkm_falcon_fw fw;
+
+ enum nvkm_acr_hsf_id {
+ NVKM_ACR_HSF_PMU,
+ NVKM_ACR_HSF_SEC2,
+ NVKM_ACR_HSF_GSP,
+ } falcon_id;
+ u32 boot_mbox0;
+ u32 intr_clear;
- u32 imem_size;
- u32 imem_tag;
- u32 *imem;
-
- u8 *image;
- u32 image_size;
- u32 non_sec_addr;
- u32 non_sec_size;
- u32 sec_addr;
- u32 sec_size;
- u32 data_addr;
- u32 data_size;
-
- struct {
- struct {
- void *data;
- u32 size;
- } prod, dbg;
- u32 patch_loc;
- } sig;
+ struct list_head head;
};
+int nvkm_acr_hsfw_boot(struct nvkm_acr *, const char *name);
+
struct nvkm_acr_hsf_fwif {
int version;
int (*load)(struct nvkm_acr *, const char *bl, const char *fw,
const char *name, int version,
const struct nvkm_acr_hsf_fwif *);
- const struct nvkm_acr_hsf_func *func;
-};
+ const struct nvkm_falcon_fw_func *func;
-int nvkm_acr_hsfw_load(struct nvkm_acr *, const char *, const char *,
- const char *, int, const struct nvkm_acr_hsf_fwif *);
-void nvkm_acr_hsfw_del_all(struct nvkm_acr *);
-
-struct nvkm_acr_hsf {
- const struct nvkm_acr_hsf_func *func;
- const char *name;
- struct list_head head;
-
- u32 imem_size;
- u32 imem_tag;
- u32 *imem;
-
- u32 non_sec_addr;
- u32 non_sec_size;
- u32 sec_addr;
- u32 sec_size;
- u32 data_addr;
- u32 data_size;
-
- struct nvkm_memory *ucode;
- struct nvkm_vma *vma;
- struct nvkm_falcon *falcon;
+ enum nvkm_acr_hsf_id falcon_id;
+ u32 boot_mbox0;
+ u32 intr_clear;
};
-struct nvkm_acr_hsf_func {
- int (*load)(struct nvkm_acr *, struct nvkm_acr_hsfw *);
- int (*boot)(struct nvkm_acr *, struct nvkm_acr_hsf *);
- void (*bld)(struct nvkm_acr *, struct nvkm_acr_hsf *);
-};
-int gm200_acr_hsfw_load(struct nvkm_acr *, struct nvkm_acr_hsfw *,
- struct nvkm_falcon *);
-int gm200_acr_hsfw_boot(struct nvkm_acr *, struct nvkm_acr_hsf *,
- u32 clear_intr, u32 mbox0_ok);
+int gm200_acr_hsfw_ctor(struct nvkm_acr *, const char *, const char *, const char *, int,
+ const struct nvkm_acr_hsf_fwif *);
+int gm200_acr_hsfw_load_bld(struct nvkm_falcon_fw *);
+extern const struct nvkm_falcon_fw_func gm200_acr_unload_0;
-int gm200_acr_load_boot(struct nvkm_acr *, struct nvkm_acr_hsf *);
+extern const struct nvkm_falcon_fw_func gm20b_acr_load_0;
-extern const struct nvkm_acr_hsf_func gm200_acr_unload_0;
-int gm200_acr_unload_load(struct nvkm_acr *, struct nvkm_acr_hsfw *);
-int gm200_acr_unload_boot(struct nvkm_acr *, struct nvkm_acr_hsf *);
-void gm200_acr_hsfw_bld(struct nvkm_acr *, struct nvkm_acr_hsf *);
+int gp102_acr_load_setup(struct nvkm_falcon_fw *);
-extern const struct nvkm_acr_hsf_func gm20b_acr_load_0;
+extern const struct nvkm_falcon_fw_func gp108_acr_load_0;
-int gp102_acr_load_load(struct nvkm_acr *, struct nvkm_acr_hsfw *);
+extern const struct nvkm_falcon_fw_func gp108_acr_hsfw_0;
+int gp108_acr_hsfw_load_bld(struct nvkm_falcon_fw *);
-extern const struct nvkm_acr_hsf_func gp108_acr_unload_0;
-void gp108_acr_hsfw_bld(struct nvkm_acr *, struct nvkm_acr_hsf *);
+int ga100_acr_hsfw_ctor(struct nvkm_acr *, const char *, const char *, const char *, int,
+ const struct nvkm_acr_hsf_fwif *);
int nvkm_acr_new_(const struct nvkm_acr_fwif *, struct nvkm_device *, enum nvkm_subdev_type,
int inst, struct nvkm_acr **);
-int nvkm_acr_hsf_boot(struct nvkm_acr *, const char *name);
struct nvkm_acr_lsf {
const struct nvkm_acr_lsf_func *func;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c
index 05a87e77525f..c22d551c0078 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/acr/tu102.c
@@ -29,14 +29,14 @@
#include <nvfw/acr.h>
-static int
+int
tu102_acr_init(struct nvkm_acr *acr)
{
- int ret = nvkm_acr_hsf_boot(acr, "AHESASC");
+ int ret = nvkm_acr_hsfw_boot(acr, "AHESASC");
if (ret)
return ret;
- return nvkm_acr_hsf_boot(acr, "ASB");
+ return nvkm_acr_hsfw_boot(acr, "ASB");
}
static int
@@ -85,12 +85,6 @@ tu102_acr_wpr_build(struct nvkm_acr *acr, struct nvkm_acr_lsf *rtos)
}
static int
-tu102_acr_hsfw_boot(struct nvkm_acr *acr, struct nvkm_acr_hsf *hsf)
-{
- return gm200_acr_hsfw_boot(acr, hsf, 0, 0);
-}
-
-static int
tu102_acr_hsfw_nofw(struct nvkm_acr *acr, const char *bl, const char *fw,
const char *name, int version,
const struct nvkm_acr_hsf_fwif *fwif)
@@ -115,24 +109,11 @@ MODULE_FIRMWARE("nvidia/tu117/acr/ucode_unload.bin");
static const struct nvkm_acr_hsf_fwif
tu102_acr_unload_fwif[] = {
- { 0, nvkm_acr_hsfw_load, &gp108_acr_unload_0 },
+ { 0, gm200_acr_hsfw_ctor, &gp108_acr_hsfw_0, NVKM_ACR_HSF_PMU, 0, 0x00000000 },
{ -1, tu102_acr_hsfw_nofw },
{}
};
-static int
-tu102_acr_asb_load(struct nvkm_acr *acr, struct nvkm_acr_hsfw *hsfw)
-{
- return gm200_acr_hsfw_load(acr, hsfw, &acr->subdev.device->gsp->falcon);
-}
-
-static const struct nvkm_acr_hsf_func
-tu102_acr_asb_0 = {
- .load = tu102_acr_asb_load,
- .boot = tu102_acr_hsfw_boot,
- .bld = gp108_acr_hsfw_bld,
-};
-
MODULE_FIRMWARE("nvidia/tu102/acr/ucode_asb.bin");
MODULE_FIRMWARE("nvidia/tu104/acr/ucode_asb.bin");
MODULE_FIRMWARE("nvidia/tu106/acr/ucode_asb.bin");
@@ -141,18 +122,11 @@ MODULE_FIRMWARE("nvidia/tu117/acr/ucode_asb.bin");
static const struct nvkm_acr_hsf_fwif
tu102_acr_asb_fwif[] = {
- { 0, nvkm_acr_hsfw_load, &tu102_acr_asb_0 },
+ { 0, gm200_acr_hsfw_ctor, &gp108_acr_hsfw_0, NVKM_ACR_HSF_GSP, 0, 0x00000000 },
{ -1, tu102_acr_hsfw_nofw },
{}
};
-static const struct nvkm_acr_hsf_func
-tu102_acr_ahesasc_0 = {
- .load = gp102_acr_load_load,
- .boot = tu102_acr_hsfw_boot,
- .bld = gp108_acr_hsfw_bld,
-};
-
MODULE_FIRMWARE("nvidia/tu102/acr/bl.bin");
MODULE_FIRMWARE("nvidia/tu102/acr/ucode_ahesasc.bin");
@@ -170,7 +144,7 @@ MODULE_FIRMWARE("nvidia/tu117/acr/ucode_ahesasc.bin");
static const struct nvkm_acr_hsf_fwif
tu102_acr_ahesasc_fwif[] = {
- { 0, nvkm_acr_hsfw_load, &tu102_acr_ahesasc_0 },
+ { 0, gm200_acr_hsfw_ctor, &gp108_acr_load_0, NVKM_ACR_HSF_SEC2, 0, 0x00000000 },
{ -1, tu102_acr_hsfw_nofw },
{}
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c
index a308b9bde449..f30718d7e61a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/gm200.c
@@ -26,6 +26,7 @@
#include <subdev/bios.h>
#include <subdev/bios/bit.h>
#include <subdev/bios/pmu.h>
+#include <subdev/pmu.h>
#include <subdev/timer.h>
static void
@@ -85,13 +86,18 @@ pmu_load(struct nv50_devinit *init, u8 type, bool post,
struct nvkm_subdev *subdev = &init->base.subdev;
struct nvkm_bios *bios = subdev->device->bios;
struct nvbios_pmuR pmu;
+ int ret;
if (!nvbios_pmuRm(bios, type, &pmu))
return -EINVAL;
- if (!post)
+ if (!post || !subdev->device->pmu)
return 0;
+ ret = nvkm_falcon_reset(&subdev->device->pmu->falcon);
+ if (ret)
+ return ret;
+
pmu_code(init, pmu.boot_addr_pmu, pmu.boot_addr, pmu.boot_size, false);
pmu_code(init, pmu.code_addr_pmu, pmu.code_addr, pmu.code_size, true);
pmu_data(init, pmu.data_addr_pmu, pmu.data_addr, pmu.data_size);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c
index fd54fa504efa..b53ac9a2552f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/base.c
@@ -22,7 +22,6 @@
#include "priv.h"
#include <core/memory.h>
-#include <core/notify.h>
static void
nvkm_fault_ntfy_fini(struct nvkm_event *event, int type, int index)
@@ -38,23 +37,8 @@ nvkm_fault_ntfy_init(struct nvkm_event *event, int type, int index)
fault->func->buffer.intr(fault->buffer[index], true);
}
-static int
-nvkm_fault_ntfy_ctor(struct nvkm_object *object, void *argv, u32 argc,
- struct nvkm_notify *notify)
-{
- struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object);
- if (argc == 0) {
- notify->size = 0;
- notify->types = 1;
- notify->index = buffer->id;
- return 0;
- }
- return -ENOSYS;
-}
-
static const struct nvkm_event_func
nvkm_fault_ntfy = {
- .ctor = nvkm_fault_ntfy_ctor,
.init = nvkm_fault_ntfy_init,
.fini = nvkm_fault_ntfy_fini,
};
@@ -130,8 +114,7 @@ nvkm_fault_oneinit(struct nvkm_subdev *subdev)
}
}
- ret = nvkm_event_init(&nvkm_fault_ntfy, 1, fault->buffer_nr,
- &fault->event);
+ ret = nvkm_event_init(&nvkm_fault_ntfy, subdev, 1, fault->buffer_nr, &fault->event);
if (ret)
return ret;
@@ -146,7 +129,7 @@ nvkm_fault_dtor(struct nvkm_subdev *subdev)
struct nvkm_fault *fault = nvkm_fault(subdev);
int i;
- nvkm_notify_fini(&fault->nrpfb);
+ nvkm_event_ntfy_del(&fault->nrpfb);
nvkm_event_fini(&fault->event);
for (i = 0; i < fault->buffer_nr; i++) {
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c
index 6af7959e02ea..04c7526888bc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gp100.c
@@ -65,7 +65,7 @@ gp100_fault_buffer_info(struct nvkm_fault_buffer *buffer)
void
gp100_fault_intr(struct nvkm_fault *fault)
{
- nvkm_event_send(&fault->event, 1, 0, NULL, 0);
+ nvkm_event_ntfy(&fault->event, 0, NVKM_FAULT_BUFFER_EVENT_PENDING);
}
static const struct nvkm_fault_func
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c
index cd9d2ade5ac7..8e34d40e7649 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/gv100.c
@@ -27,10 +27,12 @@
#include <nvif/class.h>
-static void
-gv100_fault_buffer_process(struct nvkm_fault_buffer *buffer)
+void
+gv100_fault_buffer_process(struct work_struct *work)
{
- struct nvkm_device *device = buffer->fault->subdev.device;
+ struct nvkm_fault *fault = container_of(work, typeof(*fault), nrpfb_work);
+ struct nvkm_fault_buffer *buffer = fault->buffer[0];
+ struct nvkm_device *device = fault->subdev.device;
struct nvkm_memory *mem = buffer->mem;
u32 get = nvkm_rd32(device, buffer->get);
u32 put = nvkm_rd32(device, buffer->put);
@@ -115,11 +117,12 @@ gv100_fault_buffer_info(struct nvkm_fault_buffer *buffer)
}
static int
-gv100_fault_ntfy_nrpfb(struct nvkm_notify *notify)
+gv100_fault_ntfy_nrpfb(struct nvkm_event_ntfy *ntfy, u32 bits)
{
- struct nvkm_fault *fault = container_of(notify, typeof(*fault), nrpfb);
- gv100_fault_buffer_process(fault->buffer[0]);
- return NVKM_NOTIFY_KEEP;
+ struct nvkm_fault *fault = container_of(ntfy, typeof(*fault), nrpfb);
+
+ schedule_work(&fault->nrpfb_work);
+ return NVKM_EVENT_KEEP;
}
static void
@@ -163,14 +166,14 @@ gv100_fault_intr(struct nvkm_fault *fault)
if (stat & 0x20000000) {
if (fault->buffer[0]) {
- nvkm_event_send(&fault->event, 1, 0, NULL, 0);
+ nvkm_event_ntfy(&fault->event, 0, NVKM_FAULT_BUFFER_EVENT_PENDING);
stat &= ~0x20000000;
}
}
if (stat & 0x08000000) {
if (fault->buffer[1]) {
- nvkm_event_send(&fault->event, 1, 1, NULL, 0);
+ nvkm_event_ntfy(&fault->event, 1, NVKM_FAULT_BUFFER_EVENT_PENDING);
stat &= ~0x08000000;
}
}
@@ -183,9 +186,12 @@ gv100_fault_intr(struct nvkm_fault *fault)
static void
gv100_fault_fini(struct nvkm_fault *fault)
{
- nvkm_notify_put(&fault->nrpfb);
+ nvkm_event_ntfy_block(&fault->nrpfb);
+ flush_work(&fault->nrpfb_work);
+
if (fault->buffer[0])
fault->func->buffer.fini(fault->buffer[0]);
+
nvkm_mask(fault->subdev.device, 0x100a34, 0x80000000, 0x80000000);
}
@@ -194,15 +200,15 @@ gv100_fault_init(struct nvkm_fault *fault)
{
nvkm_mask(fault->subdev.device, 0x100a2c, 0x80000000, 0x80000000);
fault->func->buffer.init(fault->buffer[0]);
- nvkm_notify_get(&fault->nrpfb);
+ nvkm_event_ntfy_allow(&fault->nrpfb);
}
int
gv100_fault_oneinit(struct nvkm_fault *fault)
{
- return nvkm_notify_init(&fault->buffer[0]->object, &fault->event,
- gv100_fault_ntfy_nrpfb, true, NULL, 0, 0,
- &fault->nrpfb);
+ nvkm_event_ntfy_add(&fault->event, 0, NVKM_FAULT_BUFFER_EVENT_PENDING, true,
+ gv100_fault_ntfy_nrpfb, &fault->nrpfb);
+ return 0;
}
static const struct nvkm_fault_func
@@ -231,5 +237,10 @@ int
gv100_fault_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fault **pfault)
{
- return nvkm_fault_new_(&gv100_fault, device, type, inst, pfault);
+ int ret = nvkm_fault_new_(&gv100_fault, device, type, inst, pfault);
+ if (ret)
+ return ret;
+
+ INIT_WORK(&(*pfault)->nrpfb_work, gv100_fault_buffer_process);
+ return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h
index 36681c347fb5..a5510332c402 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/priv.h
@@ -16,6 +16,8 @@ struct nvkm_fault_buffer {
u32 put;
struct nvkm_memory *mem;
u64 addr;
+
+ struct nvkm_inth inth;
};
int nvkm_fault_new_(const struct nvkm_fault_func *, struct nvkm_device *, enum nvkm_subdev_type,
@@ -46,6 +48,7 @@ void gp100_fault_buffer_fini(struct nvkm_fault_buffer *);
void gp100_fault_buffer_init(struct nvkm_fault_buffer *);
u64 gp100_fault_buffer_pin(struct nvkm_fault_buffer *);
void gp100_fault_buffer_info(struct nvkm_fault_buffer *);
+void gv100_fault_buffer_process(struct work_struct *);
void gp100_fault_intr(struct nvkm_fault *);
u64 gp10b_fault_buffer_pin(struct nvkm_fault_buffer *);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c
index 91eb6729c84d..967efaddae28 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/tu102.c
@@ -24,20 +24,27 @@
#include <core/memory.h>
#include <subdev/mc.h>
#include <subdev/mmu.h>
+#include <subdev/vfn.h>
#include <engine/fifo.h>
#include <nvif/class.h>
+static irqreturn_t
+tu102_fault_buffer_notify(struct nvkm_inth *inth)
+{
+ struct nvkm_fault_buffer *buffer = container_of(inth, typeof(*buffer), inth);
+
+ nvkm_event_ntfy(&buffer->fault->event, buffer->id, NVKM_FAULT_BUFFER_EVENT_PENDING);
+ return IRQ_HANDLED;
+}
+
static void
tu102_fault_buffer_intr(struct nvkm_fault_buffer *buffer, bool enable)
{
- /*XXX: Earlier versions of RM touched the old regs on Turing,
- * which don't appear to actually work anymore, but newer
- * versions of RM don't appear to touch anything at all..
- */
- struct nvkm_device *device = buffer->fault->subdev.device;
-
- nvkm_mc_intr_mask(device, NVKM_SUBDEV_FAULT, 0, enable);
+ if (enable)
+ nvkm_inth_allow(&buffer->inth);
+ else
+ nvkm_inth_block(&buffer->inth);
}
static void
@@ -46,10 +53,6 @@ tu102_fault_buffer_fini(struct nvkm_fault_buffer *buffer)
struct nvkm_device *device = buffer->fault->subdev.device;
const u32 foff = buffer->id * 0x20;
- /* Disable the fault interrupts */
- nvkm_wr32(device, 0xb81408, 0x1);
- nvkm_wr32(device, 0xb81410, 0x10);
-
nvkm_mask(device, 0xb83010 + foff, 0x80000000, 0x00000000);
}
@@ -59,10 +62,6 @@ tu102_fault_buffer_init(struct nvkm_fault_buffer *buffer)
struct nvkm_device *device = buffer->fault->subdev.device;
const u32 foff = buffer->id * 0x20;
- /* Enable the fault interrupts */
- nvkm_wr32(device, 0xb81208, 0x1);
- nvkm_wr32(device, 0xb81210, 0x10);
-
nvkm_mask(device, 0xb83010 + foff, 0xc0000000, 0x40000000);
nvkm_wr32(device, 0xb83004 + foff, upper_32_bits(buffer->addr));
nvkm_wr32(device, 0xb83000 + foff, lower_32_bits(buffer->addr));
@@ -82,9 +81,10 @@ tu102_fault_buffer_info(struct nvkm_fault_buffer *buffer)
buffer->put = 0xb8300c + foff;
}
-static void
-tu102_fault_intr_fault(struct nvkm_fault *fault)
+static irqreturn_t
+tu102_fault_info_fault(struct nvkm_inth *inth)
{
+ struct nvkm_fault *fault = container_of(inth, typeof(*fault), info_fault);
struct nvkm_subdev *subdev = &fault->subdev;
struct nvkm_device *device = subdev->device;
struct nvkm_fault_data info;
@@ -106,70 +106,61 @@ tu102_fault_intr_fault(struct nvkm_fault *fault)
info.reason = (info1 & 0x0000001f);
nvkm_fifo_fault(device->fifo, &info);
-}
-
-static void
-tu102_fault_intr(struct nvkm_fault *fault)
-{
- struct nvkm_subdev *subdev = &fault->subdev;
- struct nvkm_device *device = subdev->device;
- u32 stat = nvkm_rd32(device, 0xb83094);
-
- if (stat & 0x80000000) {
- tu102_fault_intr_fault(fault);
- nvkm_wr32(device, 0xb83094, 0x80000000);
- stat &= ~0x80000000;
- }
- if (stat & 0x00000200) {
- /* Clear the associated interrupt flag */
- nvkm_wr32(device, 0xb81010, 0x10);
-
- if (fault->buffer[0]) {
- nvkm_event_send(&fault->event, 1, 0, NULL, 0);
- stat &= ~0x00000200;
- }
- }
-
- /* Replayable MMU fault */
- if (stat & 0x00000100) {
- /* Clear the associated interrupt flag */
- nvkm_wr32(device, 0xb81008, 0x1);
-
- if (fault->buffer[1]) {
- nvkm_event_send(&fault->event, 1, 1, NULL, 0);
- stat &= ~0x00000100;
- }
- }
-
- if (stat) {
- nvkm_debug(subdev, "intr %08x\n", stat);
- }
+ nvkm_wr32(device, 0xb83094, 0x80000000);
+ return IRQ_HANDLED;
}
static void
tu102_fault_fini(struct nvkm_fault *fault)
{
- nvkm_notify_put(&fault->nrpfb);
+ nvkm_event_ntfy_block(&fault->nrpfb);
+ flush_work(&fault->nrpfb_work);
+
if (fault->buffer[0])
fault->func->buffer.fini(fault->buffer[0]);
- /*XXX: disable priv faults */
+
+ nvkm_inth_block(&fault->info_fault);
}
static void
tu102_fault_init(struct nvkm_fault *fault)
{
- /*XXX: enable priv faults */
+ nvkm_inth_allow(&fault->info_fault);
+
fault->func->buffer.init(fault->buffer[0]);
- nvkm_notify_get(&fault->nrpfb);
+ nvkm_event_ntfy_allow(&fault->nrpfb);
+}
+
+static int
+tu102_fault_oneinit(struct nvkm_fault *fault)
+{
+ struct nvkm_device *device = fault->subdev.device;
+ struct nvkm_intr *intr = &device->vfn->intr;
+ int ret, i;
+
+ ret = nvkm_inth_add(intr, nvkm_rd32(device, 0x100ee0) & 0x0000ffff,
+ NVKM_INTR_PRIO_NORMAL, &fault->subdev, tu102_fault_info_fault,
+ &fault->info_fault);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < fault->buffer_nr; i++) {
+ ret = nvkm_inth_add(intr, nvkm_rd32(device, 0x100ee4 + (i * 4)) >> 16,
+ NVKM_INTR_PRIO_NORMAL, &fault->subdev,
+ tu102_fault_buffer_notify, &fault->buffer[i]->inth);
+ if (ret)
+ return ret;
+ }
+
+ return gv100_fault_oneinit(fault);
}
static const struct nvkm_fault_func
tu102_fault = {
- .oneinit = gv100_fault_oneinit,
+ .oneinit = tu102_fault_oneinit,
.init = tu102_fault_init,
.fini = tu102_fault_fini,
- .intr = tu102_fault_intr,
.buffer.nr = 2,
.buffer.entry_size = 32,
.buffer.info = tu102_fault_buffer_info,
@@ -184,5 +175,10 @@ int
tu102_fault_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fault **pfault)
{
- return nvkm_fault_new_(&tu102_fault, device, type, inst, pfault);
+ int ret = nvkm_fault_new_(&tu102_fault, device, type, inst, pfault);
+ if (ret)
+ return ret;
+
+ INIT_WORK(&(*pfault)->nrpfb_work, gv100_fault_buffer_process);
+ return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.c
index ac835c9582fd..c123e5893d76 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fault/user.c
@@ -22,12 +22,28 @@
#include "priv.h"
#include <core/memory.h>
+#include <core/event.h>
#include <subdev/mmu.h>
#include <nvif/clb069.h>
#include <nvif/unpack.h>
static int
+nvkm_ufault_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_uevent *uevent)
+{
+ struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object);
+ union nvif_clb069_event_args *args = argv;
+
+ if (!uevent)
+ return 0;
+ if (argc != sizeof(args->vn))
+ return -ENOSYS;
+
+ return nvkm_uevent_add(uevent, &buffer->fault->event, buffer->id,
+ NVKM_FAULT_BUFFER_EVENT_PENDING, NULL);
+}
+
+static int
nvkm_ufault_map(struct nvkm_object *object, void *argv, u32 argc,
enum nvkm_object_map *type, u64 *addr, u64 *size)
{
@@ -40,18 +56,6 @@ nvkm_ufault_map(struct nvkm_object *object, void *argv, u32 argc,
}
static int
-nvkm_ufault_ntfy(struct nvkm_object *object, u32 type,
- struct nvkm_event **pevent)
-{
- struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object);
- if (type == NVB069_V0_NTFY_FAULT) {
- *pevent = &buffer->fault->event;
- return 0;
- }
- return -EINVAL;
-}
-
-static int
nvkm_ufault_fini(struct nvkm_object *object, bool suspend)
{
struct nvkm_fault_buffer *buffer = nvkm_fault_buffer(object);
@@ -78,8 +82,8 @@ nvkm_ufault = {
.dtor = nvkm_ufault_dtor,
.init = nvkm_ufault_init,
.fini = nvkm_ufault_fini,
- .ntfy = nvkm_ufault_ntfy,
.map = nvkm_ufault_map,
+ .uevent = nvkm_ufault_uevent,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c
index 6faaea948fc4..bac7dcc4c2c1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c
@@ -57,6 +57,15 @@ nvkm_fb_tile_prog(struct nvkm_fb *fb, int region, struct nvkm_fb_tile *tile)
}
}
+static void
+nvkm_fb_sysmem_flush_page_init(struct nvkm_device *device)
+{
+ struct nvkm_fb *fb = device->fb;
+
+ if (fb->func->sysmem.flush_page_init)
+ fb->func->sysmem.flush_page_init(fb);
+}
+
int
nvkm_fb_bios_memtype(struct nvkm_bios *bios)
{
@@ -125,12 +134,20 @@ nvkm_fb_oneinit(struct nvkm_subdev *subdev)
return nvkm_mm_init(&fb->tags.mm, 0, 0, tags, 1);
}
-static int
-nvkm_fb_init_scrub_vpr(struct nvkm_fb *fb)
+int
+nvkm_fb_mem_unlock(struct nvkm_fb *fb)
{
struct nvkm_subdev *subdev = &fb->subdev;
int ret;
+ if (!fb->func->vpr.scrub_required)
+ return 0;
+
+ if (!fb->func->vpr.scrub_required(fb)) {
+ nvkm_debug(subdev, "VPR not locked\n");
+ return 0;
+ }
+
nvkm_debug(subdev, "VPR locked, running scrubber binary\n");
if (!fb->vpr_scrubber.size) {
@@ -168,6 +185,8 @@ nvkm_fb_init(struct nvkm_subdev *subdev)
for (i = 0; i < fb->tile.regions; i++)
fb->func->tile.prog(fb, i, &fb->tile.region[i]);
+ nvkm_fb_sysmem_flush_page_init(subdev->device);
+
if (fb->func->init)
fb->func->init(fb);
@@ -183,13 +202,13 @@ nvkm_fb_init(struct nvkm_subdev *subdev)
if (fb->func->init_unkn)
fb->func->init_unkn(fb);
- if (fb->func->vpr.scrub_required &&
- fb->func->vpr.scrub_required(fb)) {
- ret = nvkm_fb_init_scrub_vpr(fb);
- if (ret)
- return ret;
- }
+ return 0;
+}
+static int
+nvkm_fb_preinit(struct nvkm_subdev *subdev)
+{
+ nvkm_fb_sysmem_flush_page_init(subdev->device);
return 0;
}
@@ -212,20 +231,28 @@ nvkm_fb_dtor(struct nvkm_subdev *subdev)
nvkm_blob_dtor(&fb->vpr_scrubber);
+ if (fb->sysmem.flush_page) {
+ dma_unmap_page(subdev->device->dev, fb->sysmem.flush_page_addr,
+ PAGE_SIZE, DMA_BIDIRECTIONAL);
+ __free_page(fb->sysmem.flush_page);
+ }
+
if (fb->func->dtor)
return fb->func->dtor(fb);
+
return fb;
}
static const struct nvkm_subdev_func
nvkm_fb = {
.dtor = nvkm_fb_dtor,
+ .preinit = nvkm_fb_preinit,
.oneinit = nvkm_fb_oneinit,
.init = nvkm_fb_init,
.intr = nvkm_fb_intr,
};
-void
+int
nvkm_fb_ctor(const struct nvkm_fb_func *func, struct nvkm_device *device,
enum nvkm_subdev_type type, int inst, struct nvkm_fb *fb)
{
@@ -234,6 +261,19 @@ nvkm_fb_ctor(const struct nvkm_fb_func *func, struct nvkm_device *device,
fb->tile.regions = fb->func->tile.regions;
fb->page = nvkm_longopt(device->cfgopt, "NvFbBigPage", fb->func->default_bigpage);
mutex_init(&fb->tags.mutex);
+
+ if (func->sysmem.flush_page_init) {
+ fb->sysmem.flush_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+ if (!fb->sysmem.flush_page)
+ return -ENOMEM;
+
+ fb->sysmem.flush_page_addr = dma_map_page(device->dev, fb->sysmem.flush_page,
+ 0, PAGE_SIZE, DMA_BIDIRECTIONAL);
+ if (dma_mapping_error(device->dev, fb->sysmem.flush_page_addr))
+ return -EFAULT;
+ }
+
+ return 0;
}
int
@@ -242,6 +282,5 @@ nvkm_fb_new_(const struct nvkm_fb_func *func, struct nvkm_device *device,
{
if (!(*pfb = kzalloc(sizeof(**pfb), GFP_KERNEL)))
return -ENOMEM;
- nvkm_fb_ctor(func, device, type, inst, *pfb);
- return 0;
+ return nvkm_fb_ctor(func, device, type, inst, *pfb);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c
index b47bebfbc26f..5098f219e3e6 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga100.c
@@ -26,9 +26,10 @@ static const struct nvkm_fb_func
ga100_fb = {
.dtor = gf100_fb_dtor,
.oneinit = gf100_fb_oneinit,
- .init = gp100_fb_init,
+ .init = gm200_fb_init,
.init_page = gv100_fb_init_page,
.init_unkn = gp100_fb_init_unkn,
+ .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
.ram_new = gp100_ram_new,
.default_bigpage = 16,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c
index 6ea7908f0563..8b7c8ea5e8a5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ga102.c
@@ -22,15 +22,42 @@
#include "gf100.h"
#include "ram.h"
+#include <engine/nvdec.h>
+
+static int
+ga102_fb_vpr_scrub(struct nvkm_fb *fb)
+{
+ struct nvkm_falcon_fw fw = {};
+ int ret;
+
+ ret = nvkm_falcon_fw_ctor_hs_v2(&ga102_flcn_fw, "mem-unlock", &fb->subdev, "nvdec/scrubber",
+ 0, &fb->subdev.device->nvdec[0]->falcon, &fw);
+ if (ret)
+ return ret;
+
+ ret = nvkm_falcon_fw_boot(&fw, &fb->subdev, true, NULL, NULL, 0, 0);
+ nvkm_falcon_fw_dtor(&fw);
+ return ret;
+}
+
+static bool
+ga102_fb_vpr_scrub_required(struct nvkm_fb *fb)
+{
+ return (nvkm_rd32(fb->subdev.device, 0x1fa80c) & 0x00000010) != 0;
+}
+
static const struct nvkm_fb_func
ga102_fb = {
.dtor = gf100_fb_dtor,
.oneinit = gf100_fb_oneinit,
- .init = gp100_fb_init,
+ .init = gm200_fb_init,
.init_page = gv100_fb_init_page,
.init_unkn = gp100_fb_init_unkn,
+ .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
.ram_new = ga102_ram_new,
.default_bigpage = 16,
+ .vpr.scrub_required = ga102_fb_vpr_scrub_required,
+ .vpr.scrub = ga102_fb_vpr_scrub,
};
int
@@ -38,3 +65,9 @@ ga102_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, s
{
return gp102_fb_new_(&ga102_fb, device, type, inst, pfb);
}
+
+MODULE_FIRMWARE("nvidia/ga102/nvdec/scrubber.bin");
+MODULE_FIRMWARE("nvidia/ga103/nvdec/scrubber.bin");
+MODULE_FIRMWARE("nvidia/ga104/nvdec/scrubber.bin");
+MODULE_FIRMWARE("nvidia/ga106/nvdec/scrubber.bin");
+MODULE_FIRMWARE("nvidia/ga107/nvdec/scrubber.bin");
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c
index 9dcc40f9ef79..07db9b397ac1 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c
@@ -61,14 +61,6 @@ gf100_fb_oneinit(struct nvkm_fb *base)
if (ret)
return ret;
- fb->r100c10_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
- if (fb->r100c10_page) {
- fb->r100c10 = dma_map_page(device->dev, fb->r100c10_page, 0,
- PAGE_SIZE, DMA_BIDIRECTIONAL);
- if (dma_mapping_error(device->dev, fb->r100c10))
- return -EFAULT;
- }
-
return 0;
}
@@ -86,14 +78,17 @@ gf100_fb_init_page(struct nvkm_fb *fb)
}
void
+gf100_fb_sysmem_flush_page_init(struct nvkm_fb *fb)
+{
+ nvkm_wr32(fb->subdev.device, 0x100c10, fb->sysmem.flush_page_addr >> 8);
+}
+
+void
gf100_fb_init(struct nvkm_fb *base)
{
struct gf100_fb *fb = gf100_fb(base);
struct nvkm_device *device = fb->base.subdev.device;
- if (fb->r100c10_page)
- nvkm_wr32(device, 0x100c10, fb->r100c10 >> 8);
-
if (base->func->clkgate_pack) {
nvkm_therm_clkgate_init(device->therm,
base->func->clkgate_pack);
@@ -104,13 +99,6 @@ void *
gf100_fb_dtor(struct nvkm_fb *base)
{
struct gf100_fb *fb = gf100_fb(base);
- struct nvkm_device *device = fb->base.subdev.device;
-
- if (fb->r100c10_page) {
- dma_unmap_page(device->dev, fb->r100c10, PAGE_SIZE,
- DMA_BIDIRECTIONAL);
- __free_page(fb->r100c10_page);
- }
return fb;
}
@@ -136,6 +124,7 @@ gf100_fb = {
.init = gf100_fb_init,
.init_page = gf100_fb_init_page,
.intr = gf100_fb_intr,
+ .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
.ram_new = gf100_ram_new,
.default_bigpage = 17,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h
index 0cac7b06acc8..77472b558591 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h
@@ -6,8 +6,6 @@
struct gf100_fb {
struct nvkm_fb base;
- struct page *r100c10_page;
- dma_addr_t r100c10;
};
int gf100_fb_new_(const struct nvkm_fb_func *, struct nvkm_device *, enum nvkm_subdev_type, int,
@@ -16,7 +14,5 @@ void *gf100_fb_dtor(struct nvkm_fb *);
void gf100_fb_init(struct nvkm_fb *);
void gf100_fb_intr(struct nvkm_fb *);
-void gp100_fb_init(struct nvkm_fb *);
-
void gm200_fb_init(struct nvkm_fb *base);
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c
index 5acf8d15d06f..fb02092a65eb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c
@@ -46,9 +46,6 @@ gm200_fb_init(struct nvkm_fb *base)
struct gf100_fb *fb = gf100_fb(base);
struct nvkm_device *device = fb->base.subdev.device;
- if (fb->r100c10_page)
- nvkm_wr32(device, 0x100c10, fb->r100c10 >> 8);
-
nvkm_wr32(device, 0x100cc8, nvkm_memory_addr(fb->base.mmu_wr) >> 8);
nvkm_wr32(device, 0x100ccc, nvkm_memory_addr(fb->base.mmu_rd) >> 8);
nvkm_mask(device, 0x100cc4, 0x00060000,
@@ -62,6 +59,7 @@ gm200_fb = {
.init = gm200_fb_init,
.init_page = gm200_fb_init_page,
.intr = gf100_fb_intr,
+ .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
.ram_new = gm200_ram_new,
.default_bigpage = 0 /* per-instance. */,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c
index 86f61a3f2fea..50875af94c18 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c
@@ -30,6 +30,7 @@ gm20b_fb = {
.init = gm200_fb_init,
.init_page = gm200_fb_init_page,
.intr = gf100_fb_intr,
+ .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
.default_bigpage = 0 /* per-instance. */,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c
index 09e943edc362..110c08c94849 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c
@@ -44,29 +44,15 @@ gp100_fb_init_remapper(struct nvkm_fb *fb)
nvkm_mask(device, 0x100c14, 0x00040000, 0x00000000);
}
-void
-gp100_fb_init(struct nvkm_fb *base)
-{
- struct gf100_fb *fb = gf100_fb(base);
- struct nvkm_device *device = fb->base.subdev.device;
-
- if (fb->r100c10_page)
- nvkm_wr32(device, 0x100c10, fb->r100c10 >> 8);
-
- nvkm_wr32(device, 0x100cc8, nvkm_memory_addr(fb->base.mmu_wr) >> 8);
- nvkm_wr32(device, 0x100ccc, nvkm_memory_addr(fb->base.mmu_rd) >> 8);
- nvkm_mask(device, 0x100cc4, 0x00060000,
- min(nvkm_memory_size(fb->base.mmu_rd) >> 16, (u64)2) << 17);
-}
-
static const struct nvkm_fb_func
gp100_fb = {
.dtor = gf100_fb_dtor,
.oneinit = gf100_fb_oneinit,
- .init = gp100_fb_init,
+ .init = gm200_fb_init,
.init_remapper = gp100_fb_init_remapper,
.init_page = gm200_fb_init_page,
.init_unkn = gp100_fb_init_unkn,
+ .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
.ram_new = gp100_ram_new,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c
index 0e78b3d734a0..2658481d575b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c
@@ -24,71 +24,22 @@
#include "gf100.h"
#include "ram.h"
-#include <core/firmware.h>
-#include <core/memory.h>
-#include <nvfw/fw.h>
-#include <nvfw/hs.h>
#include <engine/nvdec.h>
int
gp102_fb_vpr_scrub(struct nvkm_fb *fb)
{
struct nvkm_subdev *subdev = &fb->subdev;
- struct nvkm_device *device = subdev->device;
- struct nvkm_falcon *falcon = &device->nvdec[0]->falcon;
- struct nvkm_blob *blob = &fb->vpr_scrubber;
- const struct nvfw_bin_hdr *hsbin_hdr;
- const struct nvfw_hs_header *fw_hdr;
- const struct nvfw_hs_load_header *lhdr;
- void *scrub_data;
- u32 patch_loc, patch_sig;
+ struct nvkm_falcon_fw fw = {};
int ret;
- nvkm_falcon_get(falcon, subdev);
-
- hsbin_hdr = nvfw_bin_hdr(subdev, blob->data);
- fw_hdr = nvfw_hs_header(subdev, blob->data + hsbin_hdr->header_offset);
- lhdr = nvfw_hs_load_header(subdev, blob->data + fw_hdr->hdr_offset);
- scrub_data = blob->data + hsbin_hdr->data_offset;
-
- patch_loc = *(u32 *)(blob->data + fw_hdr->patch_loc);
- patch_sig = *(u32 *)(blob->data + fw_hdr->patch_sig);
- if (falcon->debug) {
- memcpy(scrub_data + patch_loc,
- blob->data + fw_hdr->sig_dbg_offset + patch_sig,
- fw_hdr->sig_dbg_size);
- } else {
- memcpy(scrub_data + patch_loc,
- blob->data + fw_hdr->sig_prod_offset + patch_sig,
- fw_hdr->sig_prod_size);
- }
-
- nvkm_falcon_reset(falcon);
- nvkm_falcon_bind_context(falcon, NULL);
-
- nvkm_falcon_load_imem(falcon, scrub_data, lhdr->non_sec_code_off,
- lhdr->non_sec_code_size,
- lhdr->non_sec_code_off >> 8, 0, false);
- nvkm_falcon_load_imem(falcon, scrub_data + lhdr->apps[0],
- ALIGN(lhdr->apps[0], 0x100),
- lhdr->apps[1],
- lhdr->apps[0] >> 8, 0, true);
- nvkm_falcon_load_dmem(falcon, scrub_data + lhdr->data_dma_base, 0,
- lhdr->data_size, 0);
-
- nvkm_falcon_set_start_addr(falcon, 0x0);
- nvkm_falcon_start(falcon);
-
- ret = nvkm_falcon_wait_for_halt(falcon, 500);
- if (ret < 0) {
- ret = -ETIMEDOUT;
- goto end;
- }
+ ret = nvkm_falcon_fw_ctor_hs(&gm200_flcn_fw, "mem-unlock", subdev, NULL,
+ "nvdec/scrubber", 0, &subdev->device->nvdec[0]->falcon, &fw);
+ if (ret)
+ return ret;
- /* put nvdec in clean state - without reset it will remain in HS mode */
- nvkm_falcon_reset(falcon);
-end:
- nvkm_falcon_put(falcon, subdev);
+ ret = nvkm_falcon_fw_boot(&fw, subdev, true, NULL, NULL, 0, 0x00000000);
+ nvkm_falcon_fw_dtor(&fw);
return ret;
}
@@ -104,9 +55,10 @@ static const struct nvkm_fb_func
gp102_fb = {
.dtor = gf100_fb_dtor,
.oneinit = gf100_fb_oneinit,
- .init = gp100_fb_init,
+ .init = gm200_fb_init,
.init_remapper = gp100_fb_init_remapper,
.init_page = gm200_fb_init_page,
+ .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
.vpr.scrub_required = gp102_fb_vpr_scrub_required,
.vpr.scrub = gp102_fb_vpr_scrub,
.ram_new = gp100_ram_new,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.c
index 84c9815a6d48..a04a5f712019 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.c
@@ -28,6 +28,7 @@ gp10b_fb = {
.init = gm200_fb_init,
.init_page = gm200_fb_init_page,
.intr = gf100_fb_intr,
+ .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c
index 63daa83ae12d..1f0126437c1a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gv100.c
@@ -32,9 +32,10 @@ static const struct nvkm_fb_func
gv100_fb = {
.dtor = gf100_fb_dtor,
.oneinit = gf100_fb_oneinit,
- .init = gp100_fb_init,
+ .init = gm200_fb_init,
.init_page = gv100_fb_init_page,
.init_unkn = gp100_fb_init_unkn,
+ .sysmem.flush_page_init = gf100_fb_sysmem_flush_page_init,
.vpr.scrub_required = gp102_fb_vpr_scrub_required,
.vpr.scrub = gp102_fb_vpr_scrub,
.ram_new = gp100_ram_new,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c
index 95fd8f834010..a6efbd913c13 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c
@@ -137,8 +137,7 @@ nv50_fb_intr(struct nvkm_fb *base)
struct nv50_fb *fb = nv50_fb(base);
struct nvkm_subdev *subdev = &fb->base.subdev;
struct nvkm_device *device = subdev->device;
- struct nvkm_fifo *fifo = device->fifo;
- struct nvkm_fifo_chan *chan;
+ struct nvkm_chan *chan;
const struct nvkm_enum *en, *re, *cl, *sc;
u32 trap[6], idx, inst;
u8 st0, st1, st2, st3;
@@ -178,35 +177,18 @@ nv50_fb_intr(struct nvkm_fb *base)
else if (en && en->data) sc = nvkm_enum_find(en->data, st3);
else sc = NULL;
- chan = nvkm_fifo_chan_inst(fifo, inst, &flags);
+ chan = nvkm_chan_get_inst(&device->fifo->engine, inst, &flags);
nvkm_error(subdev, "trapped %s at %02x%04x%04x on channel %d [%08x %s] "
"engine %02x [%s] client %02x [%s] "
"subclient %02x [%s] reason %08x [%s]\n",
(trap[5] & 0x00000100) ? "read" : "write",
trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff,
- chan ? chan->chid : -1, inst,
- chan ? chan->object.client->name : "unknown",
+ chan ? chan->id : -1, inst,
+ chan ? chan->name : "unknown",
st0, en ? en->name : "",
st2, cl ? cl->name : "", st3, sc ? sc->name : "",
st1, re ? re->name : "");
- nvkm_fifo_chan_put(fifo, flags, &chan);
-}
-
-static int
-nv50_fb_oneinit(struct nvkm_fb *base)
-{
- struct nv50_fb *fb = nv50_fb(base);
- struct nvkm_device *device = fb->base.subdev.device;
-
- fb->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
- if (fb->r100c08_page) {
- fb->r100c08 = dma_map_page(device->dev, fb->r100c08_page, 0,
- PAGE_SIZE, DMA_BIDIRECTIONAL);
- if (dma_mapping_error(device->dev, fb->r100c08))
- return -EFAULT;
- }
-
- return 0;
+ nvkm_chan_put(&chan, flags);
}
static void
@@ -215,12 +197,6 @@ nv50_fb_init(struct nvkm_fb *base)
struct nv50_fb *fb = nv50_fb(base);
struct nvkm_device *device = fb->base.subdev.device;
- /* Not a clue what this is exactly. Without pointing it at a
- * scratch page, VRAM->GART blits with M2MF (as in DDX DFS)
- * cause IOMMU "read from address 0" errors (rh#561267)
- */
- nvkm_wr32(device, 0x100c08, fb->r100c08 >> 8);
-
/* This is needed to get meaningful information from 100c90
* on traps. No idea what these values mean exactly. */
nvkm_wr32(device, 0x100c90, fb->func->trap);
@@ -235,17 +211,16 @@ nv50_fb_tags(struct nvkm_fb *base)
return 0;
}
+static void
+nv50_fb_sysmem_flush_page_init(struct nvkm_fb *fb)
+{
+ nvkm_wr32(fb->subdev.device, 0x100c08, fb->sysmem.flush_page_addr >> 8);
+}
+
static void *
nv50_fb_dtor(struct nvkm_fb *base)
{
struct nv50_fb *fb = nv50_fb(base);
- struct nvkm_device *device = fb->base.subdev.device;
-
- if (fb->r100c08_page) {
- dma_unmap_page(device->dev, fb->r100c08, PAGE_SIZE,
- DMA_BIDIRECTIONAL);
- __free_page(fb->r100c08_page);
- }
return fb;
}
@@ -254,9 +229,9 @@ static const struct nvkm_fb_func
nv50_fb_ = {
.dtor = nv50_fb_dtor,
.tags = nv50_fb_tags,
- .oneinit = nv50_fb_oneinit,
.init = nv50_fb_init,
.intr = nv50_fb_intr,
+ .sysmem.flush_page_init = nv50_fb_sysmem_flush_page_init,
.ram_new = nv50_fb_ram_new,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h
index a5e673859a90..4f68bc4513a7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h
@@ -7,8 +7,6 @@
struct nv50_fb {
const struct nv50_fb_func *func;
struct nvkm_fb base;
- struct page *r100c08_page;
- dma_addr_t r100c08;
};
struct nv50_fb_func {
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h
index 3f1be9780c65..ac03eac0f261 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h
@@ -16,6 +16,10 @@ struct nvkm_fb_func {
void (*init_unkn)(struct nvkm_fb *);
void (*intr)(struct nvkm_fb *);
+ struct nvkm_fb_func_sysmem {
+ void (*flush_page_init)(struct nvkm_fb *);
+ } sysmem;
+
struct {
bool (*scrub_required)(struct nvkm_fb *);
int (*scrub)(struct nvkm_fb *);
@@ -37,8 +41,8 @@ struct nvkm_fb_func {
const struct nvkm_therm_clkgate_pack *clkgate_pack;
};
-void nvkm_fb_ctor(const struct nvkm_fb_func *, struct nvkm_device *device,
- enum nvkm_subdev_type type, int inst, struct nvkm_fb *);
+int nvkm_fb_ctor(const struct nvkm_fb_func *, struct nvkm_device *device,
+ enum nvkm_subdev_type type, int inst, struct nvkm_fb *);
int nvkm_fb_new_(const struct nvkm_fb_func *, struct nvkm_device *device,
enum nvkm_subdev_type type, int inst, struct nvkm_fb **);
int nvkm_fb_bios_memtype(struct nvkm_bios *);
@@ -72,6 +76,7 @@ void nv46_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size,
int gf100_fb_oneinit(struct nvkm_fb *);
int gf100_fb_init_page(struct nvkm_fb *);
+void gf100_fb_sysmem_flush_page_init(struct nvkm_fb *);
int gm200_fb_init_page(struct nvkm_fb *);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c
index 03b1bdb27770..5c34416cb637 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c
@@ -25,6 +25,7 @@
#include "ram.h"
#include <core/memory.h>
+#include <subdev/instmem.h>
#include <subdev/mmu.h>
struct nvkm_vram {
@@ -35,6 +36,12 @@ struct nvkm_vram {
};
static int
+nvkm_vram_kmap(struct nvkm_memory *memory, struct nvkm_memory **pmemory)
+{
+ return nvkm_instobj_wrap(nvkm_vram(memory)->ram->fb->subdev.device, memory, pmemory);
+}
+
+static int
nvkm_vram_map(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm,
struct nvkm_vma *vma, void *argv, u32 argc)
{
@@ -98,6 +105,7 @@ nvkm_vram = {
.addr = nvkm_vram_addr,
.size = nvkm_vram_size,
.map = nvkm_vram_map,
+ .kmap = nvkm_vram_kmap,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c
index 048bcc70c3f4..b196baa376dc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gpio/base.c
@@ -24,7 +24,6 @@
#include "priv.h"
#include <core/option.h>
-#include <core/notify.h>
static int
nvkm_gpio_drive(struct nvkm_gpio *gpio, int idx, int line, int dir, int out)
@@ -123,23 +122,8 @@ nvkm_gpio_intr_init(struct nvkm_event *event, int type, int index)
gpio->func->intr_mask(gpio, type, 1 << index, 1 << index);
}
-static int
-nvkm_gpio_intr_ctor(struct nvkm_object *object, void *data, u32 size,
- struct nvkm_notify *notify)
-{
- struct nvkm_gpio_ntfy_req *req = data;
- if (!WARN_ON(size != sizeof(*req))) {
- notify->size = sizeof(struct nvkm_gpio_ntfy_rep);
- notify->types = req->mask;
- notify->index = req->line;
- return 0;
- }
- return -EINVAL;
-}
-
static const struct nvkm_event_func
nvkm_gpio_intr_func = {
- .ctor = nvkm_gpio_intr_ctor,
.init = nvkm_gpio_intr_init,
.fini = nvkm_gpio_intr_fini,
};
@@ -153,11 +137,9 @@ nvkm_gpio_intr(struct nvkm_subdev *subdev)
gpio->func->intr_stat(gpio, &hi, &lo);
for (i = 0; (hi | lo) && i < gpio->func->lines; i++) {
- struct nvkm_gpio_ntfy_rep rep = {
- .mask = (NVKM_GPIO_HI * !!(hi & (1 << i))) |
- (NVKM_GPIO_LO * !!(lo & (1 << i))),
- };
- nvkm_event_send(&gpio->event, rep.mask, i, &rep, sizeof(rep));
+ u32 mask = (NVKM_GPIO_HI * !!(hi & (1 << i))) |
+ (NVKM_GPIO_LO * !!(lo & (1 << i)));
+ nvkm_event_ntfy(&gpio->event, i, mask);
}
}
@@ -251,6 +233,5 @@ nvkm_gpio_new_(const struct nvkm_gpio_func *func, struct nvkm_device *device,
nvkm_subdev_ctor(&nvkm_gpio, device, type, inst, &gpio->subdev);
gpio->func = func;
- return nvkm_event_init(&nvkm_gpio_intr_func, 2, func->lines,
- &gpio->event);
+ return nvkm_event_init(&nvkm_gpio_intr_func, &gpio->subdev, 2, func->lines, &gpio->event);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/Kbuild
index 67cc3b320169..7f61a1ed158b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/Kbuild
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: MIT
nvkm-y += nvkm/subdev/gsp/base.o
nvkm-y += nvkm/subdev/gsp/gv100.o
+nvkm-y += nvkm/subdev/gsp/ga102.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c
index 22574886b819..591ac95c2669 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/base.c
@@ -53,5 +53,7 @@ nvkm_gsp_new_(const struct nvkm_gsp_fwif *fwif, struct nvkm_device *device,
if (IS_ERR(fwif))
return PTR_ERR(fwif);
- return nvkm_falcon_ctor(fwif->flcn, &gsp->subdev, gsp->subdev.name, 0, &gsp->falcon);
+ gsp->func = fwif->func;
+
+ return nvkm_falcon_ctor(gsp->func->flcn, &gsp->subdev, gsp->subdev.name, 0, &gsp->falcon);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga102.c
new file mode 100644
index 000000000000..525267412c3e
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/ga102.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2021 Red Hat 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 "priv.h"
+
+static const struct nvkm_falcon_func
+ga102_gsp_flcn = {
+ .disable = gm200_flcn_disable,
+ .enable = gm200_flcn_enable,
+ .select = ga102_flcn_select,
+ .addr2 = 0x1000,
+ .reset_eng = gp102_flcn_reset_eng,
+ .reset_prep = ga102_flcn_reset_prep,
+ .reset_wait_mem_scrubbing = ga102_flcn_reset_wait_mem_scrubbing,
+ .imem_dma = &ga102_flcn_dma,
+ .dmem_dma = &ga102_flcn_dma,
+};
+
+static const struct nvkm_gsp_func
+ga102_gsp = {
+ .flcn = &ga102_gsp_flcn,
+};
+
+static int
+ga102_gsp_nofw(struct nvkm_gsp *gsp, int ver, const struct nvkm_gsp_fwif *fwif)
+{
+ return 0;
+}
+
+struct nvkm_gsp_fwif
+ga102_gsps[] = {
+ { -1, ga102_gsp_nofw, &ga102_gsp },
+ {}
+};
+
+int
+ga102_gsp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
+ struct nvkm_gsp **pgsp)
+{
+ return nvkm_gsp_new_(ga102_gsps, device, type, inst, pgsp);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c
index 6c4ef62a746a..da6a809cd317 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/gv100.c
@@ -23,17 +23,20 @@
static const struct nvkm_falcon_func
gv100_gsp_flcn = {
- .fbif = 0x600,
- .load_imem = nvkm_falcon_v1_load_imem,
- .load_dmem = nvkm_falcon_v1_load_dmem,
- .read_dmem = nvkm_falcon_v1_read_dmem,
- .bind_context = gp102_sec2_flcn_bind_context,
- .wait_for_halt = nvkm_falcon_v1_wait_for_halt,
- .clear_interrupt = nvkm_falcon_v1_clear_interrupt,
- .set_start_addr = nvkm_falcon_v1_set_start_addr,
- .start = nvkm_falcon_v1_start,
- .enable = gp102_sec2_flcn_enable,
- .disable = nvkm_falcon_v1_disable,
+ .disable = gm200_flcn_disable,
+ .enable = gm200_flcn_enable,
+ .reset_eng = gp102_flcn_reset_eng,
+ .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing,
+ .bind_inst = gm200_flcn_bind_inst,
+ .bind_stat = gm200_flcn_bind_stat,
+ .bind_intr = true,
+ .imem_pio = &gm200_flcn_imem_pio,
+ .dmem_pio = &gm200_flcn_dmem_pio,
+};
+
+static const struct nvkm_gsp_func
+gv100_gsp = {
+ .flcn = &gv100_gsp_flcn,
};
static int
@@ -43,8 +46,8 @@ gv100_gsp_nofw(struct nvkm_gsp *gsp, int ver, const struct nvkm_gsp_fwif *fwif)
}
static struct nvkm_gsp_fwif
-gv100_gsp[] = {
- { -1, gv100_gsp_nofw, &gv100_gsp_flcn },
+gv100_gsps[] = {
+ { -1, gv100_gsp_nofw, &gv100_gsp },
{}
};
@@ -52,5 +55,5 @@ int
gv100_gsp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_gsp **pgsp)
{
- return nvkm_gsp_new_(gv100_gsp, device, type, inst, pgsp);
+ return nvkm_gsp_new_(gv100_gsps, device, type, inst, pgsp);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h
index 19381ddd38d4..89749a40203c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/gsp/priv.h
@@ -4,10 +4,14 @@
#include <subdev/gsp.h>
enum nvkm_acr_lsf_id;
+struct nvkm_gsp_func {
+ const struct nvkm_falcon_func *flcn;
+};
+
struct nvkm_gsp_fwif {
int version;
int (*load)(struct nvkm_gsp *, int ver, const struct nvkm_gsp_fwif *);
- const struct nvkm_falcon_func *flcn;
+ const struct nvkm_gsp_func *func;
};
int nvkm_gsp_new_(const struct nvkm_gsp_fwif *, struct nvkm_device *, enum nvkm_subdev_type, int,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c
index cb5cb533d91c..976539de4220 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c
@@ -26,7 +26,6 @@
#include "bus.h"
#include "pad.h"
-#include <core/notify.h>
#include <core/option.h>
#include <subdev/bios.h>
#include <subdev/bios/dcb.h>
@@ -104,23 +103,8 @@ nvkm_i2c_intr_init(struct nvkm_event *event, int type, int id)
i2c->func->aux_mask(i2c, type, aux->intr, aux->intr);
}
-static int
-nvkm_i2c_intr_ctor(struct nvkm_object *object, void *data, u32 size,
- struct nvkm_notify *notify)
-{
- struct nvkm_i2c_ntfy_req *req = data;
- if (!WARN_ON(size != sizeof(*req))) {
- notify->size = sizeof(struct nvkm_i2c_ntfy_rep);
- notify->types = req->mask;
- notify->index = req->port;
- return 0;
- }
- return -EINVAL;
-}
-
static const struct nvkm_event_func
nvkm_i2c_intr_func = {
- .ctor = nvkm_i2c_intr_ctor,
.init = nvkm_i2c_intr_init,
.fini = nvkm_i2c_intr_fini,
};
@@ -145,13 +129,8 @@ nvkm_i2c_intr(struct nvkm_subdev *subdev)
if (lo & aux->intr) mask |= NVKM_I2C_UNPLUG;
if (rq & aux->intr) mask |= NVKM_I2C_IRQ;
if (tx & aux->intr) mask |= NVKM_I2C_DONE;
- if (mask) {
- struct nvkm_i2c_ntfy_rep rep = {
- .mask = mask,
- };
- nvkm_event_send(&i2c->event, rep.mask, aux->id,
- &rep, sizeof(rep));
- }
+ if (mask)
+ nvkm_event_ntfy(&i2c->event, aux->id, mask);
}
}
@@ -427,5 +406,5 @@ nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device,
}
}
- return nvkm_event_init(&nvkm_i2c_intr_func, 4, i, &i2c->event);
+ return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, i, &i2c->event);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
index cd8163a52bb6..e0e4f97be029 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c
@@ -90,6 +90,18 @@ nvkm_instobj_ctor(const struct nvkm_memory_func *func,
}
int
+nvkm_instobj_wrap(struct nvkm_device *device,
+ struct nvkm_memory *memory, struct nvkm_memory **pmemory)
+{
+ struct nvkm_instmem *imem = device->imem;
+
+ if (!imem->func->memory_wrap)
+ return -ENOSYS;
+
+ return imem->func->memory_wrap(imem, memory, pmemory);
+}
+
+int
nvkm_instobj_new(struct nvkm_instmem *imem, u32 size, u32 align, bool zero,
struct nvkm_memory **pmemory)
{
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
index c51bac76174c..4b2d7465d22f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c
@@ -348,13 +348,11 @@ nv50_instobj_func = {
};
static int
-nv50_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero,
- struct nvkm_memory **pmemory)
+nv50_instobj_wrap(struct nvkm_instmem *base,
+ struct nvkm_memory *memory, struct nvkm_memory **pmemory)
{
struct nv50_instmem *imem = nv50_instmem(base);
struct nv50_instobj *iobj;
- struct nvkm_device *device = imem->base.subdev.device;
- u8 page = max(order_base_2(align), 12);
if (!(iobj = kzalloc(sizeof(*iobj), GFP_KERNEL)))
return -ENOMEM;
@@ -365,7 +363,25 @@ nv50_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero,
refcount_set(&iobj->maps, 0);
INIT_LIST_HEAD(&iobj->lru);
- return nvkm_ram_get(device, 0, 1, page, size, true, true, &iobj->ram);
+ iobj->ram = nvkm_memory_ref(memory);
+ return 0;
+}
+
+static int
+nv50_instobj_new(struct nvkm_instmem *imem, u32 size, u32 align, bool zero,
+ struct nvkm_memory **pmemory)
+{
+ u8 page = max(order_base_2(align), 12);
+ struct nvkm_memory *ram;
+ int ret;
+
+ ret = nvkm_ram_get(imem->subdev.device, 0, 1, page, size, true, true, &ram);
+ if (ret)
+ return ret;
+
+ ret = nv50_instobj_wrap(imem, ram, pmemory);
+ nvkm_memory_unref(&ram);
+ return ret;
}
/******************************************************************************
@@ -382,6 +398,7 @@ static const struct nvkm_instmem_func
nv50_instmem = {
.fini = nv50_instmem_fini,
.memory_new = nv50_instobj_new,
+ .memory_wrap = nv50_instobj_wrap,
.zero = false,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
index 56c15e30a5dd..fe92986a3885 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h
@@ -12,6 +12,7 @@ struct nvkm_instmem_func {
void (*wr32)(struct nvkm_instmem *, u32 addr, u32 data);
int (*memory_new)(struct nvkm_instmem *, u32 size, u32 align,
bool zero, struct nvkm_memory **);
+ int (*memory_wrap)(struct nvkm_instmem *, struct nvkm_memory *, struct nvkm_memory **);
bool zero;
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/Kbuild
index 728d75010847..0d8a915d727e 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/Kbuild
@@ -7,3 +7,4 @@ nvkm-y += nvkm/subdev/ltc/gm200.o
nvkm-y += nvkm/subdev/ltc/gp100.o
nvkm-y += nvkm/subdev/ltc/gp102.o
nvkm-y += nvkm/subdev/ltc/gp10b.o
+nvkm-y += nvkm/subdev/ltc/ga102.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c
index fa683c190795..f742a7b7b175 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c
@@ -97,8 +97,10 @@ nvkm_ltc_init(struct nvkm_subdev *subdev)
struct nvkm_ltc *ltc = nvkm_ltc(subdev);
int i;
- for (i = ltc->zbc_min; i <= ltc->zbc_max; i++) {
+ for (i = ltc->zbc_color_min; i <= ltc->zbc_color_max; i++)
ltc->func->zbc_clear_color(ltc, i, ltc->zbc_color[i]);
+
+ for (i = ltc->zbc_depth_min; i <= ltc->zbc_depth_max; i++) {
ltc->func->zbc_clear_depth(ltc, i, ltc->zbc_depth[i]);
if (ltc->func->zbc_clear_stencil)
ltc->func->zbc_clear_stencil(ltc, i, ltc->zbc_stencil[i]);
@@ -137,7 +139,9 @@ nvkm_ltc_new_(const struct nvkm_ltc_func *func, struct nvkm_device *device,
nvkm_subdev_ctor(&nvkm_ltc, device, type, inst, &ltc->subdev);
ltc->func = func;
mutex_init(&ltc->mutex);
- ltc->zbc_min = 1; /* reserve 0 for disabled */
- ltc->zbc_max = min(func->zbc, NVKM_LTC_MAX_ZBC_CNT) - 1;
+ ltc->zbc_color_min = 1; /* reserve 0 for disabled */
+ ltc->zbc_color_max = min(func->zbc_color, NVKM_LTC_MAX_ZBC_COLOR_CNT) - 1;
+ ltc->zbc_depth_min = 1; /* reserve 0 for disabled */
+ ltc->zbc_depth_max = min(func->zbc_depth, NVKM_LTC_MAX_ZBC_DEPTH_CNT) - 1;
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/ga102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/ga102.c
new file mode 100644
index 000000000000..159d9f8c95f3
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/ga102.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2021 Red Hat 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 "priv.h"
+
+static void
+ga102_ltc_zbc_clear_color(struct nvkm_ltc *ltc, int i, const u32 color[4])
+{
+ struct nvkm_device *device = ltc->subdev.device;
+
+ nvkm_mask(device, 0x17e338, 0x0000001f, i);
+ nvkm_wr32(device, 0x17e33c, color[0]);
+ nvkm_wr32(device, 0x17e340, color[1]);
+ nvkm_wr32(device, 0x17e344, color[2]);
+ nvkm_wr32(device, 0x17e348, color[3]);
+}
+
+static const struct nvkm_ltc_func
+ga102_ltc = {
+ .oneinit = gp100_ltc_oneinit,
+ .init = gp100_ltc_init,
+ .intr = gp100_ltc_intr,
+ .cbc_clear = gm107_ltc_cbc_clear,
+ .cbc_wait = gm107_ltc_cbc_wait,
+ .zbc_color = 31,
+ .zbc_depth = 16,
+ .zbc_clear_color = ga102_ltc_zbc_clear_color,
+ .zbc_clear_depth = gm107_ltc_zbc_clear_depth,
+ .zbc_clear_stencil = gp102_ltc_zbc_clear_stencil,
+ .invalidate = gf100_ltc_invalidate,
+ .flush = gf100_ltc_flush,
+};
+
+int
+ga102_ltc_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
+ struct nvkm_ltc **pltc)
+{
+ return nvkm_ltc_new_(&ga102_ltc, device, type, inst, pltc);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c
index fd8aeafc812d..de71ba3c9292 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c
@@ -241,7 +241,8 @@ gf100_ltc = {
.intr = gf100_ltc_intr,
.cbc_clear = gf100_ltc_cbc_clear,
.cbc_wait = gf100_ltc_cbc_wait,
- .zbc = 16,
+ .zbc_color = 16,
+ .zbc_depth = 16,
.zbc_clear_color = gf100_ltc_zbc_clear_color,
.zbc_clear_depth = gf100_ltc_zbc_clear_depth,
.invalidate = gf100_ltc_invalidate,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c
index 94aa09244d67..5d61e3c6ff59 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gk104.c
@@ -42,7 +42,8 @@ gk104_ltc = {
.intr = gf100_ltc_intr,
.cbc_clear = gf100_ltc_cbc_clear,
.cbc_wait = gf100_ltc_cbc_wait,
- .zbc = 16,
+ .zbc_color = 16,
+ .zbc_depth = 16,
.zbc_clear_color = gf100_ltc_zbc_clear_color,
.zbc_clear_depth = gf100_ltc_zbc_clear_depth,
.invalidate = gf100_ltc_invalidate,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c
index 54d1d65d5a85..18685d849657 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm107.c
@@ -137,7 +137,8 @@ gm107_ltc = {
.intr = gm107_ltc_intr,
.cbc_clear = gm107_ltc_cbc_clear,
.cbc_wait = gm107_ltc_cbc_wait,
- .zbc = 16,
+ .zbc_color = 16,
+ .zbc_depth = 16,
.zbc_clear_color = gm107_ltc_zbc_clear_color,
.zbc_clear_depth = gm107_ltc_zbc_clear_depth,
.invalidate = gf100_ltc_invalidate,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm200.c
index 8cfdbbdd8e8d..7a9464b9def5 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gm200.c
@@ -49,7 +49,8 @@ gm200_ltc = {
.intr = gm107_ltc_intr,
.cbc_clear = gm107_ltc_cbc_clear,
.cbc_wait = gm107_ltc_cbc_wait,
- .zbc = 16,
+ .zbc_color = 16,
+ .zbc_depth = 16,
.zbc_clear_color = gm107_ltc_zbc_clear_color,
.zbc_clear_depth = gm107_ltc_zbc_clear_depth,
.invalidate = gf100_ltc_invalidate,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp100.c
index a4a6cd9b435a..1a17a451754c 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp100.c
@@ -61,7 +61,8 @@ gp100_ltc = {
.intr = gp100_ltc_intr,
.cbc_clear = gm107_ltc_cbc_clear,
.cbc_wait = gm107_ltc_cbc_wait,
- .zbc = 16,
+ .zbc_color = 16,
+ .zbc_depth = 16,
.zbc_clear_color = gm107_ltc_zbc_clear_color,
.zbc_clear_depth = gm107_ltc_zbc_clear_depth,
.invalidate = gf100_ltc_invalidate,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp102.c
index ff05d617e7f4..265a05fd5f6b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp102.c
@@ -36,7 +36,8 @@ gp102_ltc = {
.intr = gp100_ltc_intr,
.cbc_clear = gm107_ltc_cbc_clear,
.cbc_wait = gm107_ltc_cbc_wait,
- .zbc = 16,
+ .zbc_color = 16,
+ .zbc_depth = 16,
.zbc_clear_color = gm107_ltc_zbc_clear_color,
.zbc_clear_depth = gm107_ltc_zbc_clear_depth,
.zbc_clear_stencil = gp102_ltc_zbc_clear_stencil,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp10b.c
index dfebd796cb4b..e7e8fdf3adab 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp10b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp10b.c
@@ -50,7 +50,8 @@ gp10b_ltc = {
.intr = gp100_ltc_intr,
.cbc_clear = gm107_ltc_cbc_clear,
.cbc_wait = gm107_ltc_cbc_wait,
- .zbc = 16,
+ .zbc_color = 16,
+ .zbc_depth = 16,
.zbc_clear_color = gm107_ltc_zbc_clear_color,
.zbc_clear_depth = gm107_ltc_zbc_clear_depth,
.zbc_clear_stencil = gp102_ltc_zbc_clear_stencil,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h
index 2bebe139005d..134e90c9e861 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/priv.h
@@ -16,7 +16,8 @@ struct nvkm_ltc_func {
void (*cbc_clear)(struct nvkm_ltc *, u32 start, u32 limit);
void (*cbc_wait)(struct nvkm_ltc *);
- int zbc;
+ int zbc_color;
+ int zbc_depth;
void (*zbc_clear_color)(struct nvkm_ltc *, int, const u32[4]);
void (*zbc_clear_depth)(struct nvkm_ltc *, int, const u32);
void (*zbc_clear_stencil)(struct nvkm_ltc *, int, const u32);
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild
index ac2b34e9ac6a..2a3255ced8b7 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/Kbuild
@@ -13,5 +13,4 @@ nvkm-y += nvkm/subdev/mc/gk104.o
nvkm-y += nvkm/subdev/mc/gk20a.o
nvkm-y += nvkm/subdev/mc/gp100.o
nvkm-y += nvkm/subdev/mc/gp10b.o
-nvkm-y += nvkm/subdev/mc/tu102.o
nvkm-y += nvkm/subdev/mc/ga100.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c
index 21c4af3f81d5..c85600ba69f9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/base.c
@@ -37,84 +37,14 @@ nvkm_mc_unk260(struct nvkm_device *device, u32 data)
void
nvkm_mc_intr_mask(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, bool en)
{
- struct nvkm_mc *mc = device->mc;
- const struct nvkm_mc_map *map;
- if (likely(mc) && mc->func->intr_mask) {
- u32 mask = nvkm_top_intr_mask(device, type, inst);
- for (map = mc->func->intr; !mask && map->stat; map++) {
- if (map->type == type && map->inst == inst)
- mask = map->stat;
- }
- mc->func->intr_mask(mc, mask, en ? mask : 0);
- }
-}
-
-void
-nvkm_mc_intr_unarm(struct nvkm_device *device)
-{
- struct nvkm_mc *mc = device->mc;
- if (likely(mc))
- mc->func->intr_unarm(mc);
-}
-
-void
-nvkm_mc_intr_rearm(struct nvkm_device *device)
-{
- struct nvkm_mc *mc = device->mc;
- if (likely(mc))
- mc->func->intr_rearm(mc);
-}
-
-static u32
-nvkm_mc_intr_stat(struct nvkm_mc *mc)
-{
- u32 intr = mc->func->intr_stat(mc);
- if (WARN_ON_ONCE(intr == 0xffffffff))
- intr = 0; /* likely fallen off the bus */
- return intr;
-}
-
-void
-nvkm_mc_intr(struct nvkm_device *device, bool *handled)
-{
- struct nvkm_mc *mc = device->mc;
- struct nvkm_top *top = device->top;
- struct nvkm_top_device *tdev;
- struct nvkm_subdev *subdev;
- const struct nvkm_mc_map *map;
- u32 stat, intr;
-
- if (unlikely(!mc))
- return;
-
- stat = intr = nvkm_mc_intr_stat(mc);
-
- if (top) {
- list_for_each_entry(tdev, &top->device, head) {
- if (tdev->intr >= 0 && (stat & BIT(tdev->intr))) {
- subdev = nvkm_device_subdev(device, tdev->type, tdev->inst);
- if (subdev) {
- nvkm_subdev_intr(subdev);
- stat &= ~BIT(tdev->intr);
- if (!stat)
- break;
- }
- }
- }
- }
+ struct nvkm_subdev *subdev = nvkm_device_subdev(device, type, inst);
- for (map = mc->func->intr; map->stat; map++) {
- if (intr & map->stat) {
- subdev = nvkm_device_subdev(device, map->type, map->inst);
- if (subdev)
- nvkm_subdev_intr(subdev);
- stat &= ~map->stat;
- }
+ if (subdev) {
+ if (en)
+ nvkm_intr_allow(subdev, NVKM_INTR_SUBDEV);
+ else
+ nvkm_intr_block(subdev, NVKM_INTR_SUBDEV);
}
-
- if (stat)
- nvkm_error(&mc->subdev, "intr %08x\n", stat);
- *handled = intr != 0;
}
static u32
@@ -143,9 +73,8 @@ nvkm_mc_reset(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
{
u64 pmc_enable = nvkm_mc_reset_mask(device, true, type, inst);
if (pmc_enable) {
- nvkm_mask(device, 0x000200, pmc_enable, 0x00000000);
- nvkm_mask(device, 0x000200, pmc_enable, pmc_enable);
- nvkm_rd32(device, 0x000200);
+ device->mc->func->device->disable(device->mc, pmc_enable);
+ device->mc->func->device->enable(device->mc, pmc_enable);
}
}
@@ -154,17 +83,15 @@ nvkm_mc_disable(struct nvkm_device *device, enum nvkm_subdev_type type, int inst
{
u64 pmc_enable = nvkm_mc_reset_mask(device, false, type, inst);
if (pmc_enable)
- nvkm_mask(device, 0x000200, pmc_enable, 0x00000000);
+ device->mc->func->device->disable(device->mc, pmc_enable);
}
void
nvkm_mc_enable(struct nvkm_device *device, enum nvkm_subdev_type type, int inst)
{
u64 pmc_enable = nvkm_mc_reset_mask(device, false, type, inst);
- if (pmc_enable) {
- nvkm_mask(device, 0x000200, pmc_enable, pmc_enable);
- nvkm_rd32(device, 0x000200);
- }
+ if (pmc_enable)
+ device->mc->func->device->enable(device->mc, pmc_enable);
}
bool
@@ -172,16 +99,7 @@ nvkm_mc_enabled(struct nvkm_device *device, enum nvkm_subdev_type type, int inst
{
u64 pmc_enable = nvkm_mc_reset_mask(device, false, type, inst);
- return (pmc_enable != 0) &&
- ((nvkm_rd32(device, 0x000200) & pmc_enable) == pmc_enable);
-}
-
-
-static int
-nvkm_mc_fini(struct nvkm_subdev *subdev, bool suspend)
-{
- nvkm_mc_intr_unarm(subdev->device);
- return 0;
+ return (pmc_enable != 0) && device->mc->func->device->enabled(device->mc, pmc_enable);
}
static int
@@ -190,7 +108,6 @@ nvkm_mc_init(struct nvkm_subdev *subdev)
struct nvkm_mc *mc = nvkm_mc(subdev);
if (mc->func->init)
mc->func->init(mc);
- nvkm_mc_intr_rearm(subdev->device);
return 0;
}
@@ -204,24 +121,27 @@ static const struct nvkm_subdev_func
nvkm_mc = {
.dtor = nvkm_mc_dtor,
.init = nvkm_mc_init,
- .fini = nvkm_mc_fini,
};
-void
-nvkm_mc_ctor(const struct nvkm_mc_func *func, struct nvkm_device *device,
- enum nvkm_subdev_type type, int inst, struct nvkm_mc *mc)
-{
- nvkm_subdev_ctor(&nvkm_mc, device, type, inst, &mc->subdev);
- mc->func = func;
-}
-
int
nvkm_mc_new_(const struct nvkm_mc_func *func, struct nvkm_device *device,
enum nvkm_subdev_type type, int inst, struct nvkm_mc **pmc)
{
struct nvkm_mc *mc;
+ int ret;
+
if (!(mc = *pmc = kzalloc(sizeof(*mc), GFP_KERNEL)))
return -ENOMEM;
- nvkm_mc_ctor(func, device, type, inst, *pmc);
+
+ nvkm_subdev_ctor(&nvkm_mc, device, type, inst, &mc->subdev);
+ mc->func = func;
+
+ if (mc->func->intr) {
+ ret = nvkm_intr_add(mc->func->intr, mc->func->intrs, &mc->subdev,
+ mc->func->intr_nonstall ? 2 : 1, &mc->intr);
+ if (ret)
+ return ret;
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c
index 4cfc1c984006..f4ee99137b1f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g84.c
@@ -34,30 +34,29 @@ g84_mc_reset[] = {
{}
};
-static const struct nvkm_mc_map
-g84_mc_intr[] = {
- { 0x04000000, NVKM_ENGINE_DISP },
- { 0x00020000, NVKM_ENGINE_VP },
- { 0x00008000, NVKM_ENGINE_BSP },
- { 0x00004000, NVKM_ENGINE_CIPHER },
- { 0x00001000, NVKM_ENGINE_GR },
- { 0x00000100, NVKM_ENGINE_FIFO },
- { 0x00000001, NVKM_ENGINE_MPEG },
- { 0x0002d101, NVKM_SUBDEV_FB },
- { 0x10000000, NVKM_SUBDEV_BUS },
- { 0x00200000, NVKM_SUBDEV_GPIO },
- { 0x00200000, NVKM_SUBDEV_I2C },
- { 0x00100000, NVKM_SUBDEV_TIMER },
+static const struct nvkm_intr_data
+g84_mc_intrs[] = {
+ { NVKM_ENGINE_DISP , 0, 0, 0x04000000, true },
+ { NVKM_ENGINE_VP , 0, 0, 0x00020000, true },
+ { NVKM_ENGINE_BSP , 0, 0, 0x00008000, true },
+ { NVKM_ENGINE_CIPHER, 0, 0, 0x00004000, true },
+ { NVKM_ENGINE_GR , 0, 0, 0x00001000, true },
+ { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 },
+ { NVKM_ENGINE_MPEG , 0, 0, 0x00000001, true },
+ { NVKM_SUBDEV_FB , 0, 0, 0x0002d101, true },
+ { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true },
+ { NVKM_SUBDEV_GPIO , 0, 0, 0x00200000, true },
+ { NVKM_SUBDEV_I2C , 0, 0, 0x00200000, true },
+ { NVKM_SUBDEV_TIMER , 0, 0, 0x00100000, true },
{},
};
static const struct nvkm_mc_func
g84_mc = {
.init = nv50_mc_init,
- .intr = g84_mc_intr,
- .intr_unarm = nv04_mc_intr_unarm,
- .intr_rearm = nv04_mc_intr_rearm,
- .intr_stat = nv04_mc_intr_stat,
+ .intr = &nv04_mc_intr,
+ .intrs = g84_mc_intrs,
+ .device = &nv04_mc_device,
.reset = g84_mc_reset,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c
index b7e58d75d894..f42684809f08 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/g98.c
@@ -34,30 +34,29 @@ g98_mc_reset[] = {
{}
};
-static const struct nvkm_mc_map
-g98_mc_intr[] = {
- { 0x04000000, NVKM_ENGINE_DISP },
- { 0x00020000, NVKM_ENGINE_MSPDEC },
- { 0x00008000, NVKM_ENGINE_MSVLD },
- { 0x00004000, NVKM_ENGINE_SEC },
- { 0x00001000, NVKM_ENGINE_GR },
- { 0x00000100, NVKM_ENGINE_FIFO },
- { 0x00000001, NVKM_ENGINE_MSPPP },
- { 0x0002d101, NVKM_SUBDEV_FB },
- { 0x10000000, NVKM_SUBDEV_BUS },
- { 0x00200000, NVKM_SUBDEV_GPIO },
- { 0x00200000, NVKM_SUBDEV_I2C },
- { 0x00100000, NVKM_SUBDEV_TIMER },
+static const struct nvkm_intr_data
+g98_mc_intrs[] = {
+ { NVKM_ENGINE_DISP , 0, 0, 0x04000000, true },
+ { NVKM_ENGINE_MSPDEC, 0, 0, 0x00020000, true },
+ { NVKM_ENGINE_MSVLD , 0, 0, 0x00008000, true },
+ { NVKM_ENGINE_SEC , 0, 0, 0x00004000, true },
+ { NVKM_ENGINE_GR , 0, 0, 0x00001000, true },
+ { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 },
+ { NVKM_ENGINE_MSPPP , 0, 0, 0x00000001, true },
+ { NVKM_SUBDEV_FB , 0, 0, 0x0002d101, true },
+ { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true },
+ { NVKM_SUBDEV_GPIO , 0, 0, 0x00200000, true },
+ { NVKM_SUBDEV_I2C , 0, 0, 0x00200000, true },
+ { NVKM_SUBDEV_TIMER , 0, 0, 0x00100000, true },
{},
};
static const struct nvkm_mc_func
g98_mc = {
.init = nv50_mc_init,
- .intr = g98_mc_intr,
- .intr_unarm = nv04_mc_intr_unarm,
- .intr_rearm = nv04_mc_intr_rearm,
- .intr_stat = nv04_mc_intr_stat,
+ .intr = &nv04_mc_intr,
+ .intrs = g98_mc_intrs,
+ .device = &nv04_mc_device,
.reset = g98_mc_reset,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c
index 4105175dfccd..1e2eabec1a76 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/ga100.c
@@ -22,49 +22,51 @@
#include "priv.h"
static void
-ga100_mc_intr_unarm(struct nvkm_mc *mc)
+ga100_mc_device_disable(struct nvkm_mc *mc, u32 mask)
{
- nvkm_wr32(mc->subdev.device, 0xb81610, 0x00000004);
-}
+ struct nvkm_device *device = mc->subdev.device;
-static void
-ga100_mc_intr_rearm(struct nvkm_mc *mc)
-{
- nvkm_wr32(mc->subdev.device, 0xb81608, 0x00000004);
+ nvkm_mask(device, 0x000600, mask, 0x00000000);
+ nvkm_rd32(device, 0x000600);
+ nvkm_rd32(device, 0x000600);
}
static void
-ga100_mc_intr_mask(struct nvkm_mc *mc, u32 mask, u32 intr)
+ga100_mc_device_enable(struct nvkm_mc *mc, u32 mask)
{
- nvkm_wr32(mc->subdev.device, 0xb81210, mask & intr );
- nvkm_wr32(mc->subdev.device, 0xb81410, mask & ~(mask & intr));
+ struct nvkm_device *device = mc->subdev.device;
+
+ nvkm_mask(device, 0x000600, mask, mask);
+ nvkm_rd32(device, 0x000600);
+ nvkm_rd32(device, 0x000600);
}
-static u32
-ga100_mc_intr_stat(struct nvkm_mc *mc)
+static bool
+ga100_mc_device_enabled(struct nvkm_mc *mc, u32 mask)
{
- u32 intr_top = nvkm_rd32(mc->subdev.device, 0xb81600), intr = 0x00000000;
- if (intr_top & 0x00000004)
- intr = nvkm_mask(mc->subdev.device, 0xb81010, 0x00000000, 0x00000000);
- return intr;
+ return (nvkm_rd32(mc->subdev.device, 0x000600) & mask) == mask;
}
+const struct nvkm_mc_device_func
+ga100_mc_device = {
+ .enabled = ga100_mc_device_enabled,
+ .enable = ga100_mc_device_enable,
+ .disable = ga100_mc_device_disable,
+};
+
static void
ga100_mc_init(struct nvkm_mc *mc)
{
- nv50_mc_init(mc);
- nvkm_wr32(mc->subdev.device, 0xb81210, 0xffffffff);
+ struct nvkm_device *device = mc->subdev.device;
+
+ nvkm_wr32(device, 0x000200, 0xffffffff);
+ nvkm_wr32(device, 0x000600, 0xffffffff);
}
static const struct nvkm_mc_func
ga100_mc = {
.init = ga100_mc_init,
- .intr = gp100_mc_intr,
- .intr_unarm = ga100_mc_intr_unarm,
- .intr_rearm = ga100_mc_intr_rearm,
- .intr_mask = ga100_mc_intr_mask,
- .intr_stat = ga100_mc_intr_stat,
- .reset = gk104_mc_reset,
+ .device = &ga100_mc_device,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c
index 3a589c6f7fad..ab1eaa37123a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gf100.c
@@ -36,64 +36,29 @@ gf100_mc_reset[] = {
{}
};
-static const struct nvkm_mc_map
-gf100_mc_intr[] = {
- { 0x04000000, NVKM_ENGINE_DISP },
- { 0x00020000, NVKM_ENGINE_MSPDEC },
- { 0x00008000, NVKM_ENGINE_MSVLD },
- { 0x00001000, NVKM_ENGINE_GR },
- { 0x00000100, NVKM_ENGINE_FIFO },
- { 0x00000040, NVKM_ENGINE_CE, 1 },
- { 0x00000020, NVKM_ENGINE_CE, 0 },
- { 0x00000001, NVKM_ENGINE_MSPPP },
- { 0x40000000, NVKM_SUBDEV_PRIVRING },
- { 0x10000000, NVKM_SUBDEV_BUS },
- { 0x08000000, NVKM_SUBDEV_FB },
- { 0x02000000, NVKM_SUBDEV_LTC },
- { 0x01000000, NVKM_SUBDEV_PMU },
- { 0x00200000, NVKM_SUBDEV_GPIO },
- { 0x00200000, NVKM_SUBDEV_I2C },
- { 0x00100000, NVKM_SUBDEV_TIMER },
- { 0x00040000, NVKM_SUBDEV_THERM },
- { 0x00002000, NVKM_SUBDEV_FB },
+static const struct nvkm_intr_data
+gf100_mc_intrs[] = {
+ { NVKM_ENGINE_DISP , 0, 0, 0x04000000, true },
+ { NVKM_ENGINE_MSPDEC , 0, 0, 0x00020000, true },
+ { NVKM_ENGINE_MSVLD , 0, 0, 0x00008000, true },
+ { NVKM_ENGINE_GR , 0, 0, 0x00001000 },
+ { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 },
+ { NVKM_ENGINE_CE , 1, 0, 0x00000040, true },
+ { NVKM_ENGINE_CE , 0, 0, 0x00000020, true },
+ { NVKM_ENGINE_MSPPP , 0, 0, 0x00000001, true },
+ { NVKM_SUBDEV_PRIVRING, 0, 0, 0x40000000, true },
+ { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true },
+ { NVKM_SUBDEV_FB , 0, 0, 0x08002000, true },
+ { NVKM_SUBDEV_LTC , 0, 0, 0x02000000, true },
+ { NVKM_SUBDEV_PMU , 0, 0, 0x01000000, true },
+ { NVKM_SUBDEV_GPIO , 0, 0, 0x00200000, true },
+ { NVKM_SUBDEV_I2C , 0, 0, 0x00200000, true },
+ { NVKM_SUBDEV_TIMER , 0, 0, 0x00100000, true },
+ { NVKM_SUBDEV_THERM , 0, 0, 0x00040000, true },
{},
};
void
-gf100_mc_intr_unarm(struct nvkm_mc *mc)
-{
- struct nvkm_device *device = mc->subdev.device;
- nvkm_wr32(device, 0x000140, 0x00000000);
- nvkm_wr32(device, 0x000144, 0x00000000);
- nvkm_rd32(device, 0x000140);
-}
-
-void
-gf100_mc_intr_rearm(struct nvkm_mc *mc)
-{
- struct nvkm_device *device = mc->subdev.device;
- nvkm_wr32(device, 0x000140, 0x00000001);
- nvkm_wr32(device, 0x000144, 0x00000001);
-}
-
-u32
-gf100_mc_intr_stat(struct nvkm_mc *mc)
-{
- struct nvkm_device *device = mc->subdev.device;
- u32 intr0 = nvkm_rd32(device, 0x000100);
- u32 intr1 = nvkm_rd32(device, 0x000104);
- return intr0 | intr1;
-}
-
-void
-gf100_mc_intr_mask(struct nvkm_mc *mc, u32 mask, u32 stat)
-{
- struct nvkm_device *device = mc->subdev.device;
- nvkm_mask(device, 0x000640, mask, stat);
- nvkm_mask(device, 0x000644, mask, stat);
-}
-
-void
gf100_mc_unk260(struct nvkm_mc *mc, u32 data)
{
nvkm_wr32(mc->subdev.device, 0x000260, data);
@@ -102,12 +67,11 @@ gf100_mc_unk260(struct nvkm_mc *mc, u32 data)
static const struct nvkm_mc_func
gf100_mc = {
.init = nv50_mc_init,
- .intr = gf100_mc_intr,
- .intr_unarm = gf100_mc_intr_unarm,
- .intr_rearm = gf100_mc_intr_rearm,
- .intr_mask = gf100_mc_intr_mask,
- .intr_stat = gf100_mc_intr_stat,
+ .intr = &gt215_mc_intr,
+ .intrs = gf100_mc_intrs,
+ .intr_nonstall = true,
.reset = gf100_mc_reset,
+ .device = &nv04_mc_device,
.unk260 = gf100_mc_unk260,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c
index d9b9067fa93f..66829586a124 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk104.c
@@ -30,32 +30,32 @@ gk104_mc_reset[] = {
{}
};
-const struct nvkm_mc_map
-gk104_mc_intr[] = {
- { 0x04000000, NVKM_ENGINE_DISP },
- { 0x00000100, NVKM_ENGINE_FIFO },
- { 0x40000000, NVKM_SUBDEV_PRIVRING },
- { 0x10000000, NVKM_SUBDEV_BUS },
- { 0x08000000, NVKM_SUBDEV_FB },
- { 0x02000000, NVKM_SUBDEV_LTC },
- { 0x01000000, NVKM_SUBDEV_PMU },
- { 0x00200000, NVKM_SUBDEV_GPIO },
- { 0x00200000, NVKM_SUBDEV_I2C },
- { 0x00100000, NVKM_SUBDEV_TIMER },
- { 0x00040000, NVKM_SUBDEV_THERM },
- { 0x00002000, NVKM_SUBDEV_FB },
+const struct nvkm_intr_data
+gk104_mc_intrs[] = {
+ { NVKM_ENGINE_DISP , 0, 0, 0x04000000, true },
+ { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 },
+ { NVKM_SUBDEV_PRIVRING, 0, 0, 0x40000000, true },
+ { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true },
+ { NVKM_SUBDEV_FB , 0, 0, 0x08002000, true },
+ { NVKM_SUBDEV_LTC , 0, 0, 0x02000000, true },
+ { NVKM_SUBDEV_PMU , 0, 0, 0x01000000, true },
+ { NVKM_SUBDEV_GPIO , 0, 0, 0x00200000, true },
+ { NVKM_SUBDEV_I2C , 0, 0, 0x00200000, true },
+ { NVKM_SUBDEV_TIMER , 0, 0, 0x00100000, true },
+ { NVKM_SUBDEV_THERM , 0, 0, 0x00040000, true },
+ { NVKM_SUBDEV_TOP , 0, 0, 0x00001000 },
+ { NVKM_SUBDEV_TOP , 0, 0, 0xffffefff, true },
{},
};
static const struct nvkm_mc_func
gk104_mc = {
.init = nv50_mc_init,
- .intr = gk104_mc_intr,
- .intr_unarm = gf100_mc_intr_unarm,
- .intr_rearm = gf100_mc_intr_rearm,
- .intr_mask = gf100_mc_intr_mask,
- .intr_stat = gf100_mc_intr_stat,
+ .intr = &gt215_mc_intr,
+ .intrs = gk104_mc_intrs,
+ .intr_nonstall = true,
.reset = gk104_mc_reset,
+ .device = &nv04_mc_device,
.unk260 = gf100_mc_unk260,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c
index 03590292749a..d98a6563a411 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gk20a.c
@@ -26,11 +26,10 @@
static const struct nvkm_mc_func
gk20a_mc = {
.init = nv50_mc_init,
- .intr = gk104_mc_intr,
- .intr_unarm = gf100_mc_intr_unarm,
- .intr_rearm = gf100_mc_intr_rearm,
- .intr_mask = gf100_mc_intr_mask,
- .intr_stat = gf100_mc_intr_stat,
+ .intr = &gt215_mc_intr,
+ .intrs = gk104_mc_intrs,
+ .intr_nonstall = true,
+ .device = &nv04_mc_device,
.reset = gk104_mc_reset,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c
index 5fd1a0595c33..eb2ab03f4360 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp100.c
@@ -21,108 +21,82 @@
*
* Authors: Ben Skeggs
*/
-#define gp100_mc(p) container_of((p), struct gp100_mc, base)
#include "priv.h"
-struct gp100_mc {
- struct nvkm_mc base;
- spinlock_t lock;
- bool intr;
- u32 mask;
+const struct nvkm_intr_data
+gp100_mc_intrs[] = {
+ { NVKM_ENGINE_DISP , 0, 0, 0x04000000, true },
+ { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 },
+ { NVKM_SUBDEV_FAULT , 0, 0, 0x00000200, true },
+ { NVKM_SUBDEV_PRIVRING, 0, 0, 0x40000000, true },
+ { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true },
+ { NVKM_SUBDEV_FB , 0, 0, 0x08002000, true },
+ { NVKM_SUBDEV_LTC , 0, 0, 0x02000000, true },
+ { NVKM_SUBDEV_PMU , 0, 0, 0x01000000, true },
+ { NVKM_SUBDEV_GPIO , 0, 0, 0x00200000, true },
+ { NVKM_SUBDEV_I2C , 0, 0, 0x00200000, true },
+ { NVKM_SUBDEV_TIMER , 0, 0, 0x00100000, true },
+ { NVKM_SUBDEV_THERM , 0, 0, 0x00040000, true },
+ { NVKM_SUBDEV_TOP , 0, 0, 0x00009000 },
+ { NVKM_SUBDEV_TOP , 0, 0, 0xffff6fff, true },
+ {},
};
static void
-gp100_mc_intr_update(struct gp100_mc *mc)
+gp100_mc_intr_allow(struct nvkm_intr *intr, int leaf, u32 mask)
{
- struct nvkm_device *device = mc->base.subdev.device;
- u32 mask = mc->intr ? mc->mask : 0, i;
- for (i = 0; i < 2; i++) {
- nvkm_wr32(device, 0x000180 + (i * 0x04), ~mask);
- nvkm_wr32(device, 0x000160 + (i * 0x04), mask);
- }
+ struct nvkm_mc *mc = container_of(intr, typeof(*mc), intr);
+
+ nvkm_wr32(mc->subdev.device, 0x000160 + (leaf * 4), mask);
}
-void
-gp100_mc_intr_unarm(struct nvkm_mc *base)
+static void
+gp100_mc_intr_block(struct nvkm_intr *intr, int leaf, u32 mask)
{
- struct gp100_mc *mc = gp100_mc(base);
- unsigned long flags;
- spin_lock_irqsave(&mc->lock, flags);
- mc->intr = false;
- gp100_mc_intr_update(mc);
- spin_unlock_irqrestore(&mc->lock, flags);
+ struct nvkm_mc *mc = container_of(intr, typeof(*mc), intr);
+
+ nvkm_wr32(mc->subdev.device, 0x000180 + (leaf * 4), mask);
}
-void
-gp100_mc_intr_rearm(struct nvkm_mc *base)
+static void
+gp100_mc_intr_rearm(struct nvkm_intr *intr)
{
- struct gp100_mc *mc = gp100_mc(base);
- unsigned long flags;
- spin_lock_irqsave(&mc->lock, flags);
- mc->intr = true;
- gp100_mc_intr_update(mc);
- spin_unlock_irqrestore(&mc->lock, flags);
+ int i;
+
+ for (i = 0; i < intr->leaves; i++)
+ intr->func->allow(intr, i, intr->mask[i]);
}
-void
-gp100_mc_intr_mask(struct nvkm_mc *base, u32 mask, u32 intr)
+static void
+gp100_mc_intr_unarm(struct nvkm_intr *intr)
{
- struct gp100_mc *mc = gp100_mc(base);
- unsigned long flags;
- spin_lock_irqsave(&mc->lock, flags);
- mc->mask = (mc->mask & ~mask) | intr;
- gp100_mc_intr_update(mc);
- spin_unlock_irqrestore(&mc->lock, flags);
+ int i;
+
+ for (i = 0; i < intr->leaves; i++)
+ intr->func->block(intr, i, 0xffffffff);
}
-const struct nvkm_mc_map
-gp100_mc_intr[] = {
- { 0x04000000, NVKM_ENGINE_DISP },
- { 0x00000100, NVKM_ENGINE_FIFO },
- { 0x00000200, NVKM_SUBDEV_FAULT },
- { 0x40000000, NVKM_SUBDEV_PRIVRING },
- { 0x10000000, NVKM_SUBDEV_BUS },
- { 0x08000000, NVKM_SUBDEV_FB },
- { 0x02000000, NVKM_SUBDEV_LTC },
- { 0x01000000, NVKM_SUBDEV_PMU },
- { 0x00200000, NVKM_SUBDEV_GPIO },
- { 0x00200000, NVKM_SUBDEV_I2C },
- { 0x00100000, NVKM_SUBDEV_TIMER },
- { 0x00040000, NVKM_SUBDEV_THERM },
- { 0x00002000, NVKM_SUBDEV_FB },
- {},
+const struct nvkm_intr_func
+gp100_mc_intr = {
+ .pending = nv04_mc_intr_pending,
+ .unarm = gp100_mc_intr_unarm,
+ .rearm = gp100_mc_intr_rearm,
+ .block = gp100_mc_intr_block,
+ .allow = gp100_mc_intr_allow,
};
static const struct nvkm_mc_func
gp100_mc = {
.init = nv50_mc_init,
- .intr = gp100_mc_intr,
- .intr_unarm = gp100_mc_intr_unarm,
- .intr_rearm = gp100_mc_intr_rearm,
- .intr_mask = gp100_mc_intr_mask,
- .intr_stat = gf100_mc_intr_stat,
+ .intr = &gp100_mc_intr,
+ .intrs = gp100_mc_intrs,
+ .intr_nonstall = true,
+ .device = &nv04_mc_device,
.reset = gk104_mc_reset,
};
int
-gp100_mc_new_(const struct nvkm_mc_func *func, struct nvkm_device *device,
- enum nvkm_subdev_type type, int inst, struct nvkm_mc **pmc)
-{
- struct gp100_mc *mc;
-
- if (!(mc = kzalloc(sizeof(*mc), GFP_KERNEL)))
- return -ENOMEM;
- nvkm_mc_ctor(func, device, type, inst, &mc->base);
- *pmc = &mc->base;
-
- spin_lock_init(&mc->lock);
- mc->intr = false;
- mc->mask = 0x7fffffff;
- return 0;
-}
-
-int
gp100_mc_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_mc **pmc)
{
- return gp100_mc_new_(&gp100_mc, device, type, inst, pmc);
+ return nvkm_mc_new_(&gp100_mc, device, type, inst, pmc);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp10b.c
index dd581d030ced..9bed9c5ea5d3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp10b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gp10b.c
@@ -34,16 +34,15 @@ gp10b_mc_init(struct nvkm_mc *mc)
static const struct nvkm_mc_func
gp10b_mc = {
.init = gp10b_mc_init,
- .intr = gp100_mc_intr,
- .intr_unarm = gp100_mc_intr_unarm,
- .intr_rearm = gp100_mc_intr_rearm,
- .intr_mask = gp100_mc_intr_mask,
- .intr_stat = gf100_mc_intr_stat,
+ .intr = &gp100_mc_intr,
+ .intrs = gp100_mc_intrs,
+ .intr_nonstall = true,
+ .device = &nv04_mc_device,
.reset = gk104_mc_reset,
};
int
gp10b_mc_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_mc **pmc)
{
- return gp100_mc_new_(&gp10b_mc, device, type, inst, pmc);
+ return nvkm_mc_new_(&gp10b_mc, device, type, inst, pmc);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c
index 1b4d43531dba..3d61836e42a3 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/gt215.c
@@ -34,39 +34,56 @@ gt215_mc_reset[] = {
{}
};
-static const struct nvkm_mc_map
-gt215_mc_intr[] = {
- { 0x04000000, NVKM_ENGINE_DISP },
- { 0x00400000, NVKM_ENGINE_CE, 0 },
- { 0x00020000, NVKM_ENGINE_MSPDEC },
- { 0x00008000, NVKM_ENGINE_MSVLD },
- { 0x00001000, NVKM_ENGINE_GR },
- { 0x00000100, NVKM_ENGINE_FIFO },
- { 0x00000001, NVKM_ENGINE_MSPPP },
- { 0x00429101, NVKM_SUBDEV_FB },
- { 0x10000000, NVKM_SUBDEV_BUS },
- { 0x00200000, NVKM_SUBDEV_GPIO },
- { 0x00200000, NVKM_SUBDEV_I2C },
- { 0x00100000, NVKM_SUBDEV_TIMER },
- { 0x00080000, NVKM_SUBDEV_THERM },
- { 0x00040000, NVKM_SUBDEV_PMU },
+static const struct nvkm_intr_data
+gt215_mc_intrs[] = {
+ { NVKM_ENGINE_DISP , 0, 0, 0x04000000, true },
+ { NVKM_ENGINE_CE , 0, 0, 0x00400000, true },
+ { NVKM_ENGINE_MSPDEC, 0, 0, 0x00020000, true },
+ { NVKM_ENGINE_MSVLD , 0, 0, 0x00008000, true },
+ { NVKM_ENGINE_GR , 0, 0, 0x00001000, true },
+ { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 },
+ { NVKM_ENGINE_MSPPP , 0, 0, 0x00000001, true },
+ { NVKM_SUBDEV_FB , 0, 0, 0x00429101, true },
+ { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true },
+ { NVKM_SUBDEV_GPIO , 0, 0, 0x00200000, true },
+ { NVKM_SUBDEV_I2C , 0, 0, 0x00200000, true },
+ { NVKM_SUBDEV_TIMER , 0, 0, 0x00100000, true },
+ { NVKM_SUBDEV_THERM , 0, 0, 0x00080000, true },
+ { NVKM_SUBDEV_PMU , 0, 0, 0x00040000, true },
{},
};
static void
-gt215_mc_intr_mask(struct nvkm_mc *mc, u32 mask, u32 stat)
+gt215_mc_intr_allow(struct nvkm_intr *intr, int leaf, u32 mask)
+{
+ struct nvkm_mc *mc = container_of(intr, typeof(*mc), intr);
+
+ nvkm_mask(mc->subdev.device, 0x000640 + (leaf * 4), mask, mask);
+}
+
+static void
+gt215_mc_intr_block(struct nvkm_intr *intr, int leaf, u32 mask)
{
- nvkm_mask(mc->subdev.device, 0x000640, mask, stat);
+ struct nvkm_mc *mc = container_of(intr, typeof(*mc), intr);
+
+ nvkm_mask(mc->subdev.device, 0x000640 + (leaf * 4), mask, 0);
}
+const struct nvkm_intr_func
+gt215_mc_intr = {
+ .pending = nv04_mc_intr_pending,
+ .unarm = nv04_mc_intr_unarm,
+ .rearm = nv04_mc_intr_rearm,
+ .block = gt215_mc_intr_block,
+ .allow = gt215_mc_intr_allow,
+};
+
static const struct nvkm_mc_func
gt215_mc = {
.init = nv50_mc_init,
- .intr = gt215_mc_intr,
- .intr_unarm = nv04_mc_intr_unarm,
- .intr_rearm = nv04_mc_intr_rearm,
- .intr_mask = gt215_mc_intr_mask,
- .intr_stat = nv04_mc_intr_stat,
+ .intr = &nv04_mc_intr,
+ .intrs = gt215_mc_intrs,
+ .device = &nv04_mc_device,
.reset = gt215_mc_reset,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c
index bc0d09bafa99..8482a5550e5f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv04.c
@@ -30,37 +30,89 @@ nv04_mc_reset[] = {
{}
};
-static const struct nvkm_mc_map
-nv04_mc_intr[] = {
- { 0x01010000, NVKM_ENGINE_DISP },
- { 0x00001000, NVKM_ENGINE_GR },
- { 0x00000100, NVKM_ENGINE_FIFO },
- { 0x10000000, NVKM_SUBDEV_BUS },
- { 0x00100000, NVKM_SUBDEV_TIMER },
+static void
+nv04_mc_device_disable(struct nvkm_mc *mc, u32 mask)
+{
+ nvkm_mask(mc->subdev.device, 0x000200, mask, 0x00000000);
+}
+
+static void
+nv04_mc_device_enable(struct nvkm_mc *mc, u32 mask)
+{
+ struct nvkm_device *device = mc->subdev.device;
+
+ nvkm_mask(device, 0x000200, mask, mask);
+ nvkm_rd32(device, 0x000200);
+}
+
+static bool
+nv04_mc_device_enabled(struct nvkm_mc *mc, u32 mask)
+{
+ return (nvkm_rd32(mc->subdev.device, 0x000200) & mask) == mask;
+}
+
+const struct nvkm_mc_device_func
+nv04_mc_device = {
+ .enabled = nv04_mc_device_enabled,
+ .enable = nv04_mc_device_enable,
+ .disable = nv04_mc_device_disable,
+};
+
+static const struct nvkm_intr_data
+nv04_mc_intrs[] = {
+ { NVKM_ENGINE_DISP , 0, 0, 0x01010000, true },
+ { NVKM_ENGINE_GR , 0, 0, 0x00001000, true },
+ { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 },
+ { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true },
+ { NVKM_SUBDEV_TIMER, 0, 0, 0x00100000, true },
{}
};
void
-nv04_mc_intr_unarm(struct nvkm_mc *mc)
+nv04_mc_intr_rearm(struct nvkm_intr *intr)
{
- struct nvkm_device *device = mc->subdev.device;
- nvkm_wr32(device, 0x000140, 0x00000000);
- nvkm_rd32(device, 0x000140);
+ struct nvkm_mc *mc = container_of(intr, typeof(*mc), intr);
+ int leaf;
+
+ for (leaf = 0; leaf < intr->leaves; leaf++)
+ nvkm_wr32(mc->subdev.device, 0x000140 + (leaf * 4), 0x00000001);
}
void
-nv04_mc_intr_rearm(struct nvkm_mc *mc)
+nv04_mc_intr_unarm(struct nvkm_intr *intr)
{
- struct nvkm_device *device = mc->subdev.device;
- nvkm_wr32(device, 0x000140, 0x00000001);
+ struct nvkm_mc *mc = container_of(intr, typeof(*mc), intr);
+ int leaf;
+
+ for (leaf = 0; leaf < intr->leaves; leaf++)
+ nvkm_wr32(mc->subdev.device, 0x000140 + (leaf * 4), 0x00000000);
+
+ nvkm_rd32(mc->subdev.device, 0x000140);
}
-u32
-nv04_mc_intr_stat(struct nvkm_mc *mc)
+bool
+nv04_mc_intr_pending(struct nvkm_intr *intr)
{
- return nvkm_rd32(mc->subdev.device, 0x000100);
+ struct nvkm_mc *mc = container_of(intr, typeof(*mc), intr);
+ bool pending = false;
+ int leaf;
+
+ for (leaf = 0; leaf < intr->leaves; leaf++) {
+ intr->stat[leaf] = nvkm_rd32(mc->subdev.device, 0x000100 + (leaf * 4));
+ if (intr->stat[leaf])
+ pending = true;
+ }
+
+ return pending;
}
+const struct nvkm_intr_func
+nv04_mc_intr = {
+ .pending = nv04_mc_intr_pending,
+ .unarm = nv04_mc_intr_unarm,
+ .rearm = nv04_mc_intr_rearm,
+};
+
void
nv04_mc_init(struct nvkm_mc *mc)
{
@@ -72,10 +124,9 @@ nv04_mc_init(struct nvkm_mc *mc)
static const struct nvkm_mc_func
nv04_mc = {
.init = nv04_mc_init,
- .intr = nv04_mc_intr,
- .intr_unarm = nv04_mc_intr_unarm,
- .intr_rearm = nv04_mc_intr_rearm,
- .intr_stat = nv04_mc_intr_stat,
+ .intr = &nv04_mc_intr,
+ .intrs = nv04_mc_intrs,
+ .device = &nv04_mc_device,
.reset = nv04_mc_reset,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c
index ab59ca1ee068..6d6278f434a4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv11.c
@@ -23,23 +23,22 @@
*/
#include "priv.h"
-static const struct nvkm_mc_map
-nv11_mc_intr[] = {
- { 0x03010000, NVKM_ENGINE_DISP },
- { 0x00001000, NVKM_ENGINE_GR },
- { 0x00000100, NVKM_ENGINE_FIFO },
- { 0x10000000, NVKM_SUBDEV_BUS },
- { 0x00100000, NVKM_SUBDEV_TIMER },
+static const struct nvkm_intr_data
+nv11_mc_intrs[] = {
+ { NVKM_ENGINE_DISP , 0, 0, 0x03010000, true },
+ { NVKM_ENGINE_GR , 0, 0, 0x00001000, true },
+ { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 },
+ { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true },
+ { NVKM_SUBDEV_TIMER, 0, 0, 0x00100000, true },
{}
};
static const struct nvkm_mc_func
nv11_mc = {
.init = nv04_mc_init,
- .intr = nv11_mc_intr,
- .intr_unarm = nv04_mc_intr_unarm,
- .intr_rearm = nv04_mc_intr_rearm,
- .intr_stat = nv04_mc_intr_stat,
+ .intr = &nv04_mc_intr,
+ .intrs = nv11_mc_intrs,
+ .device = &nv04_mc_device,
.reset = nv04_mc_reset,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c
index 03d756e26e57..dbad7c111ceb 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv17.c
@@ -31,24 +31,23 @@ nv17_mc_reset[] = {
{}
};
-const struct nvkm_mc_map
-nv17_mc_intr[] = {
- { 0x03010000, NVKM_ENGINE_DISP },
- { 0x00001000, NVKM_ENGINE_GR },
- { 0x00000100, NVKM_ENGINE_FIFO },
- { 0x00000001, NVKM_ENGINE_MPEG },
- { 0x10000000, NVKM_SUBDEV_BUS },
- { 0x00100000, NVKM_SUBDEV_TIMER },
+const struct nvkm_intr_data
+nv17_mc_intrs[] = {
+ { NVKM_ENGINE_DISP , 0, 0, 0x03010000, true },
+ { NVKM_ENGINE_GR , 0, 0, 0x00001000, true },
+ { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 },
+ { NVKM_ENGINE_MPEG , 0, 0, 0x00000001, true },
+ { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true },
+ { NVKM_SUBDEV_TIMER, 0, 0, 0x00100000, true },
{}
};
static const struct nvkm_mc_func
nv17_mc = {
.init = nv04_mc_init,
- .intr = nv17_mc_intr,
- .intr_unarm = nv04_mc_intr_unarm,
- .intr_rearm = nv04_mc_intr_rearm,
- .intr_stat = nv04_mc_intr_stat,
+ .intr = &nv04_mc_intr,
+ .intrs = nv17_mc_intrs,
+ .device = &nv04_mc_device,
.reset = nv17_mc_reset,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c
index 95f65766e8b0..649a9fcc0a2f 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv44.c
@@ -40,10 +40,9 @@ nv44_mc_init(struct nvkm_mc *mc)
static const struct nvkm_mc_func
nv44_mc = {
.init = nv44_mc_init,
- .intr = nv17_mc_intr,
- .intr_unarm = nv04_mc_intr_unarm,
- .intr_rearm = nv04_mc_intr_rearm,
- .intr_stat = nv04_mc_intr_stat,
+ .intr = &nv04_mc_intr,
+ .intrs = nv17_mc_intrs,
+ .device = &nv04_mc_device,
.reset = nv17_mc_reset,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c
index fce3613cdfa5..d41099d35690 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/nv50.c
@@ -23,17 +23,17 @@
*/
#include "priv.h"
-static const struct nvkm_mc_map
-nv50_mc_intr[] = {
- { 0x04000000, NVKM_ENGINE_DISP },
- { 0x00001000, NVKM_ENGINE_GR },
- { 0x00000100, NVKM_ENGINE_FIFO },
- { 0x00000001, NVKM_ENGINE_MPEG },
- { 0x00001101, NVKM_SUBDEV_FB },
- { 0x10000000, NVKM_SUBDEV_BUS },
- { 0x00200000, NVKM_SUBDEV_GPIO },
- { 0x00200000, NVKM_SUBDEV_I2C },
- { 0x00100000, NVKM_SUBDEV_TIMER },
+static const struct nvkm_intr_data
+nv50_mc_intrs[] = {
+ { NVKM_ENGINE_DISP , 0, 0, 0x04000000, true },
+ { NVKM_ENGINE_GR , 0, 0, 0x00001000, true },
+ { NVKM_ENGINE_FIFO , 0, 0, 0x00000100 },
+ { NVKM_ENGINE_MPEG , 0, 0, 0x00000001, true },
+ { NVKM_SUBDEV_FB , 0, 0, 0x00001101, true },
+ { NVKM_SUBDEV_BUS , 0, 0, 0x10000000, true },
+ { NVKM_SUBDEV_GPIO , 0, 0, 0x00200000, true },
+ { NVKM_SUBDEV_I2C , 0, 0, 0x00200000, true },
+ { NVKM_SUBDEV_TIMER, 0, 0, 0x00100000, true },
{},
};
@@ -47,10 +47,9 @@ nv50_mc_init(struct nvkm_mc *mc)
static const struct nvkm_mc_func
nv50_mc = {
.init = nv50_mc_init,
- .intr = nv50_mc_intr,
- .intr_unarm = nv04_mc_intr_unarm,
- .intr_rearm = nv04_mc_intr_rearm,
- .intr_stat = nv04_mc_intr_stat,
+ .intr = &nv04_mc_intr,
+ .intrs = nv50_mc_intrs,
+ .device = &nv04_mc_device,
.reset = nv17_mc_reset,
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h
index c8bcabb98f99..7f38d54b4bc2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/priv.h
@@ -4,8 +4,6 @@
#define nvkm_mc(p) container_of((p), struct nvkm_mc, subdev)
#include <subdev/mc.h>
-void nvkm_mc_ctor(const struct nvkm_mc_func *, struct nvkm_device *, enum nvkm_subdev_type, int,
- struct nvkm_mc *);
int nvkm_mc_new_(const struct nvkm_mc_func *, struct nvkm_device *, enum nvkm_subdev_type, int,
struct nvkm_mc **);
@@ -18,46 +16,44 @@ struct nvkm_mc_map {
struct nvkm_mc_func {
void (*init)(struct nvkm_mc *);
- const struct nvkm_mc_map *intr;
- /* disable reporting of interrupts to host */
- void (*intr_unarm)(struct nvkm_mc *);
- /* enable reporting of interrupts to host */
- void (*intr_rearm)(struct nvkm_mc *);
- /* (un)mask delivery of specific interrupts */
- void (*intr_mask)(struct nvkm_mc *, u32 mask, u32 stat);
- /* retrieve pending interrupt mask (NV_PMC_INTR) */
- u32 (*intr_stat)(struct nvkm_mc *);
+
+ const struct nvkm_intr_func *intr;
+ const struct nvkm_intr_data *intrs;
+ bool intr_nonstall;
+
+ const struct nvkm_mc_device_func {
+ bool (*enabled)(struct nvkm_mc *, u32 mask);
+ void (*enable)(struct nvkm_mc *, u32 mask);
+ void (*disable)(struct nvkm_mc *, u32 mask);
+ } *device;
+
const struct nvkm_mc_map *reset;
+
void (*unk260)(struct nvkm_mc *, u32);
};
void nv04_mc_init(struct nvkm_mc *);
-void nv04_mc_intr_unarm(struct nvkm_mc *);
-void nv04_mc_intr_rearm(struct nvkm_mc *);
-u32 nv04_mc_intr_stat(struct nvkm_mc *);
+extern const struct nvkm_intr_func nv04_mc_intr;
+bool nv04_mc_intr_pending(struct nvkm_intr *);
+void nv04_mc_intr_unarm(struct nvkm_intr *);
+void nv04_mc_intr_rearm(struct nvkm_intr *);
+extern const struct nvkm_mc_device_func nv04_mc_device;
extern const struct nvkm_mc_map nv04_mc_reset[];
-extern const struct nvkm_mc_map nv17_mc_intr[];
+extern const struct nvkm_intr_data nv17_mc_intrs[];
extern const struct nvkm_mc_map nv17_mc_reset[];
void nv44_mc_init(struct nvkm_mc *);
void nv50_mc_init(struct nvkm_mc *);
-void gk104_mc_init(struct nvkm_mc *);
-void gf100_mc_intr_unarm(struct nvkm_mc *);
-void gf100_mc_intr_rearm(struct nvkm_mc *);
-void gf100_mc_intr_mask(struct nvkm_mc *, u32, u32);
-u32 gf100_mc_intr_stat(struct nvkm_mc *);
+extern const struct nvkm_intr_func gt215_mc_intr;
void gf100_mc_unk260(struct nvkm_mc *, u32);
-void gp100_mc_intr_unarm(struct nvkm_mc *);
-void gp100_mc_intr_rearm(struct nvkm_mc *);
-void gp100_mc_intr_mask(struct nvkm_mc *, u32, u32);
-int gp100_mc_new_(const struct nvkm_mc_func *, struct nvkm_device *, enum nvkm_subdev_type, int,
- struct nvkm_mc **);
-extern const struct nvkm_mc_map gk104_mc_intr[];
+void gk104_mc_init(struct nvkm_mc *);
+extern const struct nvkm_intr_data gk104_mc_intrs[];
extern const struct nvkm_mc_map gk104_mc_reset[];
-extern const struct nvkm_mc_map gp100_mc_intr[];
+extern const struct nvkm_intr_func gp100_mc_intr;
+extern const struct nvkm_intr_data gp100_mc_intrs[];
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mc/tu102.c
deleted file mode 100644
index a96084b34a78..000000000000
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mc/tu102.c
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright 2018 Red Hat 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.
- */
-#define tu102_mc(p) container_of((p), struct tu102_mc, base)
-#include "priv.h"
-
-struct tu102_mc {
- struct nvkm_mc base;
- spinlock_t lock;
- bool intr;
- u32 mask;
-};
-
-static void
-tu102_mc_intr_update(struct tu102_mc *mc)
-{
- struct nvkm_device *device = mc->base.subdev.device;
- u32 mask = mc->intr ? mc->mask : 0, i;
-
- for (i = 0; i < 2; i++) {
- nvkm_wr32(device, 0x000180 + (i * 0x04), ~mask);
- nvkm_wr32(device, 0x000160 + (i * 0x04), mask);
- }
-
- if (mask & 0x00000200)
- nvkm_wr32(device, 0xb81608, 0x6);
- else
- nvkm_wr32(device, 0xb81610, 0x6);
-}
-
-static void
-tu102_mc_intr_unarm(struct nvkm_mc *base)
-{
- struct tu102_mc *mc = tu102_mc(base);
- unsigned long flags;
-
- spin_lock_irqsave(&mc->lock, flags);
- mc->intr = false;
- tu102_mc_intr_update(mc);
- spin_unlock_irqrestore(&mc->lock, flags);
-}
-
-static void
-tu102_mc_intr_rearm(struct nvkm_mc *base)
-{
- struct tu102_mc *mc = tu102_mc(base);
- unsigned long flags;
-
- spin_lock_irqsave(&mc->lock, flags);
- mc->intr = true;
- tu102_mc_intr_update(mc);
- spin_unlock_irqrestore(&mc->lock, flags);
-}
-
-static void
-tu102_mc_intr_mask(struct nvkm_mc *base, u32 mask, u32 intr)
-{
- struct tu102_mc *mc = tu102_mc(base);
- unsigned long flags;
-
- spin_lock_irqsave(&mc->lock, flags);
- mc->mask = (mc->mask & ~mask) | intr;
- tu102_mc_intr_update(mc);
- spin_unlock_irqrestore(&mc->lock, flags);
-}
-
-static u32
-tu102_mc_intr_stat(struct nvkm_mc *mc)
-{
- struct nvkm_device *device = mc->subdev.device;
- u32 intr0 = nvkm_rd32(device, 0x000100);
- u32 intr1 = nvkm_rd32(device, 0x000104);
- u32 intr_top = nvkm_rd32(device, 0xb81600);
-
- /* Turing and above route the MMU fault interrupts via a different
- * interrupt tree with different control registers. For the moment remap
- * them back to the old PMC vector.
- */
- if (intr_top & 0x00000006)
- intr0 |= 0x00000200;
-
- return intr0 | intr1;
-}
-
-
-static const struct nvkm_mc_func
-tu102_mc = {
- .init = nv50_mc_init,
- .intr = gp100_mc_intr,
- .intr_unarm = tu102_mc_intr_unarm,
- .intr_rearm = tu102_mc_intr_rearm,
- .intr_mask = tu102_mc_intr_mask,
- .intr_stat = tu102_mc_intr_stat,
- .reset = gk104_mc_reset,
-};
-
-static int
-tu102_mc_new_(const struct nvkm_mc_func *func, struct nvkm_device *device,
- enum nvkm_subdev_type type, int inst, struct nvkm_mc **pmc)
-{
- struct tu102_mc *mc;
-
- if (!(mc = kzalloc(sizeof(*mc), GFP_KERNEL)))
- return -ENOMEM;
- nvkm_mc_ctor(func, device, type, inst, &mc->base);
- *pmc = &mc->base;
-
- spin_lock_init(&mc->lock);
- mc->intr = false;
- mc->mask = 0x7fffffff;
- return 0;
-}
-
-int
-tu102_mc_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_mc **pmc)
-{
- return tu102_mc_new_(&tu102_mc, device, type, inst, pmc);
-}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c
index 186b4e63e559..524cd3c0e3fe 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c
@@ -39,7 +39,7 @@ nvkm_uvmm_search(struct nvkm_client *client, u64 handle)
if (IS_ERR(object))
return (void *)object;
- return nvkm_uvmm(object)->vmm;
+ return nvkm_vmm_ref(nvkm_uvmm(object)->vmm);
}
static int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
index a7d42ea8ba28..5a0de45d36ce 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c
@@ -26,7 +26,15 @@
#include <core/option.h>
#include <core/pci.h>
-#include <subdev/mc.h>
+
+void
+nvkm_pci_msi_rearm(struct nvkm_device *device)
+{
+ struct nvkm_pci *pci = device->pci;
+
+ if (pci && pci->msi)
+ pci->func->msi_rearm(pci);
+}
u32
nvkm_pci_rd32(struct nvkm_pci *pci, u16 addr)
@@ -65,24 +73,6 @@ nvkm_pci_rom_shadow(struct nvkm_pci *pci, bool shadow)
nvkm_pci_wr32(pci, 0x0050, data);
}
-static irqreturn_t
-nvkm_pci_intr(int irq, void *arg)
-{
- struct nvkm_pci *pci = arg;
- struct nvkm_device *device = pci->subdev.device;
- bool handled = false;
-
- if (pci->irq < 0)
- return IRQ_HANDLED;
-
- nvkm_mc_intr_unarm(device);
- if (pci->msi)
- pci->func->msi_rearm(pci);
- nvkm_mc_intr(device, &handled);
- nvkm_mc_intr_rearm(device);
- return handled ? IRQ_HANDLED : IRQ_NONE;
-}
-
static int
nvkm_pci_fini(struct nvkm_subdev *subdev, bool suspend)
{
@@ -107,7 +97,6 @@ static int
nvkm_pci_oneinit(struct nvkm_subdev *subdev)
{
struct nvkm_pci *pci = nvkm_pci(subdev);
- struct pci_dev *pdev = pci->pdev;
int ret;
if (pci_is_pcie(pci->pdev)) {
@@ -116,11 +105,6 @@ nvkm_pci_oneinit(struct nvkm_subdev *subdev)
return ret;
}
- ret = request_irq(pdev->irq, nvkm_pci_intr, IRQF_SHARED, "nvkm", pci);
- if (ret)
- return ret;
-
- pci->irq = pdev->irq;
return 0;
}
@@ -157,15 +141,6 @@ nvkm_pci_dtor(struct nvkm_subdev *subdev)
nvkm_agp_dtor(pci);
- if (pci->irq >= 0) {
- /* freq_irq() will call the handler, we use pci->irq == -1
- * to signal that it's been torn down and should be a noop.
- */
- int irq = pci->irq;
- pci->irq = -1;
- free_irq(irq, pci);
- }
-
if (pci->msi)
pci_disable_msi(pci->pdev);
@@ -192,7 +167,6 @@ nvkm_pci_new_(const struct nvkm_pci_func *func, struct nvkm_device *device,
nvkm_subdev_ctor(&nvkm_pci_func, device, type, inst, &pci->subdev);
pci->func = func;
pci->pdev = device->func->pci(device)->pdev;
- pci->irq = -1;
pci->pcie.speed = -1;
pci->pcie.width = -1;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
index 455e95a89259..8f2f50ad4ded 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/base.c
@@ -81,43 +81,12 @@ nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend)
{
struct nvkm_pmu *pmu = nvkm_pmu(subdev);
+ if (!subdev->use.enabled)
+ return 0;
+
if (pmu->func->fini)
pmu->func->fini(pmu);
- flush_work(&pmu->recv.work);
-
- reinit_completion(&pmu->wpr_ready);
-
- nvkm_falcon_cmdq_fini(pmu->lpq);
- nvkm_falcon_cmdq_fini(pmu->hpq);
- pmu->initmsg_received = false;
- return 0;
-}
-
-static void
-nvkm_pmu_reset(struct nvkm_pmu *pmu)
-{
- struct nvkm_device *device = pmu->subdev.device;
-
- if (!pmu->func->enabled(pmu))
- return;
-
- /* Reset. */
- if (pmu->func->reset)
- pmu->func->reset(pmu);
-
- /* Wait for IMEM/DMEM scrubbing to be complete. */
- nvkm_msec(device, 2000,
- if (!(nvkm_rd32(device, 0x10a10c) & 0x00000006))
- break;
- );
-}
-
-static int
-nvkm_pmu_preinit(struct nvkm_subdev *subdev)
-{
- struct nvkm_pmu *pmu = nvkm_pmu(subdev);
- nvkm_pmu_reset(pmu);
return 0;
}
@@ -125,22 +94,10 @@ static int
nvkm_pmu_init(struct nvkm_subdev *subdev)
{
struct nvkm_pmu *pmu = nvkm_pmu(subdev);
- struct nvkm_device *device = pmu->subdev.device;
if (!pmu->func->init)
return 0;
- if (pmu->func->enabled(pmu)) {
- /* Inhibit interrupts, and wait for idle. */
- nvkm_wr32(device, 0x10a014, 0x0000ffff);
- nvkm_msec(device, 2000,
- if (!nvkm_rd32(device, 0x10a04c))
- break;
- );
-
- nvkm_pmu_reset(pmu);
- }
-
return pmu->func->init(pmu);
}
@@ -160,7 +117,6 @@ nvkm_pmu_dtor(struct nvkm_subdev *subdev)
static const struct nvkm_subdev_func
nvkm_pmu = {
.dtor = nvkm_pmu_dtor,
- .preinit = nvkm_pmu_preinit,
.init = nvkm_pmu_init,
.fini = nvkm_pmu_fini,
.intr = nvkm_pmu_intr,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c
index a67a42e73f08..b5e52b35f5d0 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gk20a.c
@@ -197,7 +197,6 @@ gk20a_dvfs_data= {
static const struct nvkm_pmu_func
gk20a_pmu = {
.flcn = &gt215_pmu_flcn,
- .enabled = gf100_pmu_enabled,
.init = gk20a_pmu_init,
.fini = gk20a_pmu_fini,
.reset = gf100_pmu_reset,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c
index 40439e329aa9..7359991f94c2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm200.c
@@ -24,30 +24,36 @@
#include "priv.h"
static int
-gm200_pmu_flcn_reset(struct nvkm_falcon *falcon)
+gm200_pmu_flcn_bind_stat(struct nvkm_falcon *falcon, bool intr)
{
- struct nvkm_pmu *pmu = container_of(falcon, typeof(*pmu), falcon);
+ nvkm_falcon_wr32(falcon, 0x200, 0x0000030e);
+ return (nvkm_falcon_rd32(falcon, 0x20c) & 0x00007000) >> 12;
+}
- nvkm_falcon_wr32(falcon, 0x014, 0x0000ffff);
- pmu->func->reset(pmu);
- return nvkm_falcon_enable(falcon);
+void
+gm200_pmu_flcn_bind_inst(struct nvkm_falcon *falcon, int target, u64 addr)
+{
+ nvkm_falcon_wr32(falcon, 0xe00, 4); /* DMAIDX_UCODE */
+ nvkm_falcon_wr32(falcon, 0xe04, 0); /* DMAIDX_VIRT */
+ nvkm_falcon_wr32(falcon, 0xe08, 4); /* DMAIDX_PHYS_VID */
+ nvkm_falcon_wr32(falcon, 0xe0c, 5); /* DMAIDX_PHYS_SYS_COH */
+ nvkm_falcon_wr32(falcon, 0xe10, 6); /* DMAIDX_PHYS_SYS_NCOH */
+ nvkm_falcon_mask(falcon, 0x090, 0x00010000, 0x00010000);
+ nvkm_falcon_wr32(falcon, 0x480, (1 << 30) | (target << 28) | (addr >> 12));
}
const struct nvkm_falcon_func
gm200_pmu_flcn = {
+ .disable = gm200_flcn_disable,
+ .enable = gm200_flcn_enable,
+ .reset_pmc = true,
+ .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing,
.debug = 0xc08,
- .fbif = 0xe00,
- .load_imem = nvkm_falcon_v1_load_imem,
- .load_dmem = nvkm_falcon_v1_load_dmem,
- .read_dmem = nvkm_falcon_v1_read_dmem,
- .bind_context = nvkm_falcon_v1_bind_context,
- .wait_for_halt = nvkm_falcon_v1_wait_for_halt,
- .clear_interrupt = nvkm_falcon_v1_clear_interrupt,
- .set_start_addr = nvkm_falcon_v1_set_start_addr,
+ .bind_inst = gm200_pmu_flcn_bind_inst,
+ .bind_stat = gm200_pmu_flcn_bind_stat,
+ .imem_pio = &gm200_flcn_imem_pio,
+ .dmem_pio = &gm200_flcn_dmem_pio,
.start = nvkm_falcon_v1_start,
- .enable = nvkm_falcon_v1_enable,
- .disable = nvkm_falcon_v1_disable,
- .reset = gm200_pmu_flcn_reset,
.cmdq = { 0x4a0, 0x4b0, 4 },
.msgq = { 0x4c8, 0x4cc, 0 },
};
@@ -55,11 +61,9 @@ gm200_pmu_flcn = {
static const struct nvkm_pmu_func
gm200_pmu = {
.flcn = &gm200_pmu_flcn,
- .enabled = gf100_pmu_enabled,
.reset = gf100_pmu_reset,
};
-
int
gm200_pmu_nofw(struct nvkm_pmu *pmu, int ver, const struct nvkm_pmu_fwif *fwif)
{
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
index 612310d5d481..a72403777329 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gm20b.c
@@ -62,16 +62,6 @@ gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *falcon,
return ret;
}
-int
-gm20b_pmu_acr_boot(struct nvkm_falcon *falcon)
-{
- struct nv_pmu_args args = { .secure_mode = true };
- const u32 addr_args = falcon->data.limit - sizeof(struct nv_pmu_args);
- nvkm_falcon_load_dmem(falcon, &args, addr_args, sizeof(args), 0);
- nvkm_falcon_start(falcon);
- return 0;
-}
-
void
gm20b_pmu_acr_bld_patch(struct nvkm_acr *acr, u32 bld, s64 adjust)
{
@@ -125,7 +115,6 @@ gm20b_pmu_acr = {
.bld_size = sizeof(struct loader_config),
.bld_write = gm20b_pmu_acr_bld_write,
.bld_patch = gm20b_pmu_acr_bld_patch,
- .boot = gm20b_pmu_acr_boot,
.bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_PMU) |
BIT_ULL(NVKM_ACR_LSF_FECS) |
BIT_ULL(NVKM_ACR_LSF_GPCCS),
@@ -166,7 +155,7 @@ gm20b_pmu_acr_init_wpr(struct nvkm_pmu *pmu)
gm20b_pmu_acr_init_wpr_callback, pmu, 0);
}
-int
+static int
gm20b_pmu_initmsg(struct nvkm_pmu *pmu)
{
struct nv_pmu_init_msg msg;
@@ -192,14 +181,13 @@ gm20b_pmu_initmsg(struct nvkm_pmu *pmu)
return gm20b_pmu_acr_init_wpr(pmu);
}
-void
+static void
gm20b_pmu_recv(struct nvkm_pmu *pmu)
{
if (!pmu->initmsg_received) {
int ret = pmu->func->initmsg(pmu);
if (ret) {
- nvkm_error(&pmu->subdev,
- "error parsing init message: %d\n", ret);
+ nvkm_error(&pmu->subdev, "error parsing init message: %d\n", ret);
return;
}
@@ -209,10 +197,44 @@ gm20b_pmu_recv(struct nvkm_pmu *pmu)
nvkm_falcon_msgq_recv(pmu->msgq);
}
-static const struct nvkm_pmu_func
+static void
+gm20b_pmu_fini(struct nvkm_pmu *pmu)
+{
+ /*TODO: shutdown RTOS. */
+
+ flush_work(&pmu->recv.work);
+ nvkm_falcon_cmdq_fini(pmu->lpq);
+ nvkm_falcon_cmdq_fini(pmu->hpq);
+
+ reinit_completion(&pmu->wpr_ready);
+
+ nvkm_falcon_put(&pmu->falcon, &pmu->subdev);
+}
+
+static int
+gm20b_pmu_init(struct nvkm_pmu *pmu)
+{
+ struct nvkm_falcon *falcon = &pmu->falcon;
+ struct nv_pmu_args args = { .secure_mode = true };
+ u32 addr_args = falcon->data.limit - sizeof(args);
+ int ret;
+
+ ret = nvkm_falcon_get(&pmu->falcon, &pmu->subdev);
+ if (ret)
+ return ret;
+
+ pmu->initmsg_received = false;
+
+ nvkm_falcon_load_dmem(falcon, &args, addr_args, sizeof(args), 0);
+ nvkm_falcon_start(falcon);
+ return 0;
+}
+
+const struct nvkm_pmu_func
gm20b_pmu = {
.flcn = &gm200_pmu_flcn,
- .enabled = gf100_pmu_enabled,
+ .init = gm20b_pmu_init,
+ .fini = gm20b_pmu_fini,
.intr = gt215_pmu_intr,
.recv = gm20b_pmu_recv,
.initmsg = gm20b_pmu_initmsg,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c
index 1a6f9c3af5ec..cd3148360996 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp102.c
@@ -23,25 +23,25 @@
*/
#include "priv.h"
-void
-gp102_pmu_reset(struct nvkm_pmu *pmu)
-{
- struct nvkm_device *device = pmu->subdev.device;
- nvkm_mask(device, 0x10a3c0, 0x00000001, 0x00000001);
- nvkm_mask(device, 0x10a3c0, 0x00000001, 0x00000000);
-}
-
-static bool
-gp102_pmu_enabled(struct nvkm_pmu *pmu)
-{
- return !(nvkm_rd32(pmu->subdev.device, 0x10a3c0) & 0x00000001);
-}
+static const struct nvkm_falcon_func
+gp102_pmu_flcn = {
+ .disable = gm200_flcn_disable,
+ .enable = gm200_flcn_enable,
+ .reset_eng = gp102_flcn_reset_eng,
+ .reset_wait_mem_scrubbing = gm200_flcn_reset_wait_mem_scrubbing,
+ .debug = 0xc08,
+ .bind_inst = gm200_pmu_flcn_bind_inst,
+ .bind_stat = gm200_flcn_bind_stat,
+ .imem_pio = &gm200_flcn_imem_pio,
+ .dmem_pio = &gm200_flcn_dmem_pio,
+ .start = nvkm_falcon_v1_start,
+ .cmdq = { 0x4a0, 0x4b0, 4 },
+ .msgq = { 0x4c8, 0x4cc, 0 },
+};
static const struct nvkm_pmu_func
gp102_pmu = {
- .flcn = &gm200_pmu_flcn,
- .enabled = gp102_pmu_enabled,
- .reset = gp102_pmu_reset,
+ .flcn = &gp102_pmu_flcn,
};
static const struct nvkm_pmu_fwif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c
index 94cfb1791af6..a6f410ba60bc 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gp10b.c
@@ -68,7 +68,6 @@ gp10b_pmu_acr = {
.bld_size = sizeof(struct loader_config),
.bld_write = gm20b_pmu_acr_bld_write,
.bld_patch = gm20b_pmu_acr_bld_patch,
- .boot = gm20b_pmu_acr_boot,
.bootstrap_falcons = BIT_ULL(NVKM_ACR_LSF_PMU) |
BIT_ULL(NVKM_ACR_LSF_FECS) |
BIT_ULL(NVKM_ACR_LSF_GPCCS),
@@ -76,16 +75,6 @@ gp10b_pmu_acr = {
.bootstrap_multiple_falcons = gp10b_pmu_acr_bootstrap_multiple_falcons,
};
-static const struct nvkm_pmu_func
-gp10b_pmu = {
- .flcn = &gm200_pmu_flcn,
- .enabled = gf100_pmu_enabled,
- .intr = gt215_pmu_intr,
- .recv = gm20b_pmu_recv,
- .initmsg = gm20b_pmu_initmsg,
- .reset = gp102_pmu_reset,
-};
-
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
MODULE_FIRMWARE("nvidia/gp10b/pmu/desc.bin");
MODULE_FIRMWARE("nvidia/gp10b/pmu/image.bin");
@@ -94,8 +83,8 @@ MODULE_FIRMWARE("nvidia/gp10b/pmu/sig.bin");
static const struct nvkm_pmu_fwif
gp10b_pmu_fwif[] = {
- { 0, gm20b_pmu_load, &gp10b_pmu, &gp10b_pmu_acr },
- { -1, gm200_pmu_nofw, &gp10b_pmu },
+ { 0, gm20b_pmu_load, &gm20b_pmu, &gp10b_pmu_acr },
+ { -1, gm200_pmu_nofw, &gm20b_pmu },
{}
};
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c
index b0407b86bc10..32cee21ed858 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/gt215.c
@@ -178,12 +178,14 @@ void
gt215_pmu_fini(struct nvkm_pmu *pmu)
{
nvkm_wr32(pmu->subdev.device, 0x10a014, 0x00000060);
+ flush_work(&pmu->recv.work);
}
static void
gt215_pmu_reset(struct nvkm_pmu *pmu)
{
struct nvkm_device *device = pmu->subdev.device;
+
nvkm_mask(device, 0x022210, 0x00000001, 0x00000000);
nvkm_mask(device, 0x022210, 0x00000001, 0x00000001);
nvkm_rd32(device, 0x022210);
@@ -201,6 +203,23 @@ gt215_pmu_init(struct nvkm_pmu *pmu)
struct nvkm_device *device = pmu->subdev.device;
int i;
+ /* Inhibit interrupts, and wait for idle. */
+ if (pmu->func->enabled(pmu)) {
+ nvkm_wr32(device, 0x10a014, 0x0000ffff);
+ nvkm_msec(device, 2000,
+ if (!nvkm_rd32(device, 0x10a04c))
+ break;
+ );
+ }
+
+ pmu->func->reset(pmu);
+
+ /* Wait for IMEM/DMEM scrubbing to be complete. */
+ nvkm_msec(device, 2000,
+ if (!(nvkm_rd32(device, 0x10a10c) & 0x00000006))
+ break;
+ );
+
/* upload data segment */
nvkm_wr32(device, 0x10a1c0, 0x01000000);
for (i = 0; i < pmu->func->data.size / 4; i++)
@@ -243,20 +262,6 @@ gt215_pmu_init(struct nvkm_pmu *pmu)
const struct nvkm_falcon_func
gt215_pmu_flcn = {
- .debug = 0xc08,
- .fbif = 0xe00,
- .load_imem = nvkm_falcon_v1_load_imem,
- .load_dmem = nvkm_falcon_v1_load_dmem,
- .read_dmem = nvkm_falcon_v1_read_dmem,
- .bind_context = nvkm_falcon_v1_bind_context,
- .wait_for_halt = nvkm_falcon_v1_wait_for_halt,
- .clear_interrupt = nvkm_falcon_v1_clear_interrupt,
- .set_start_addr = nvkm_falcon_v1_set_start_addr,
- .start = nvkm_falcon_v1_start,
- .enable = nvkm_falcon_v1_enable,
- .disable = nvkm_falcon_v1_disable,
- .cmdq = { 0x4a0, 0x4b0, 4 },
- .msgq = { 0x4c8, 0x4cc, 0 },
};
static const struct nvkm_pmu_func
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
index 21abf31f4442..2d0a8fa6f196 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/priv.h
@@ -46,13 +46,12 @@ void gp102_pmu_reset(struct nvkm_pmu *pmu);
void gk110_pmu_pgob(struct nvkm_pmu *, bool);
extern const struct nvkm_falcon_func gm200_pmu_flcn;
+void gm200_pmu_flcn_bind_inst(struct nvkm_falcon *, int, u64);
+extern const struct nvkm_pmu_func gm20b_pmu;
void gm20b_pmu_acr_bld_patch(struct nvkm_acr *, u32, s64);
void gm20b_pmu_acr_bld_write(struct nvkm_acr *, u32, struct nvkm_acr_lsfw *);
-int gm20b_pmu_acr_boot(struct nvkm_falcon *);
int gm20b_pmu_acr_bootstrap_falcon(struct nvkm_falcon *, enum nvkm_acr_lsf_id);
-void gm20b_pmu_recv(struct nvkm_pmu *);
-int gm20b_pmu_initmsg(struct nvkm_pmu *);
struct nvkm_pmu_fwif {
int version;
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/top/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/top/base.c
index 28d0789f50fe..eb348dfc1d7a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/top/base.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/top/base.c
@@ -117,11 +117,15 @@ nvkm_top_fault(struct nvkm_device *device, int fault)
return NULL;
}
-static int
-nvkm_top_oneinit(struct nvkm_subdev *subdev)
+int
+nvkm_top_parse(struct nvkm_device *device)
{
- struct nvkm_top *top = nvkm_top(subdev);
- return top->func->oneinit(top);
+ struct nvkm_top *top = device->top;
+
+ if (!top || !list_empty(&top->device))
+ return 0;
+
+ return top->func->parse(top);
}
static void *
@@ -141,7 +145,6 @@ nvkm_top_dtor(struct nvkm_subdev *subdev)
static const struct nvkm_subdev_func
nvkm_top = {
.dtor = nvkm_top_dtor,
- .oneinit = nvkm_top_oneinit,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/top/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/top/ga100.c
index c982d834c8d9..84790cf52b90 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/top/ga100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/top/ga100.c
@@ -22,7 +22,7 @@
#include "priv.h"
static int
-ga100_top_oneinit(struct nvkm_top *top)
+ga100_top_parse(struct nvkm_top *top)
{
struct nvkm_subdev *subdev = &top->subdev;
struct nvkm_device *device = subdev->device;
@@ -97,7 +97,7 @@ ga100_top_oneinit(struct nvkm_top *top)
static const struct nvkm_top_func
ga100_top = {
- .oneinit = ga100_top_oneinit,
+ .parse = ga100_top_parse,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/top/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/top/gk104.c
index 4dcad97bd505..2bbba8244cbf 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/top/gk104.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/top/gk104.c
@@ -24,7 +24,7 @@
#include "priv.h"
static int
-gk104_top_oneinit(struct nvkm_top *top)
+gk104_top_parse(struct nvkm_top *top)
{
struct nvkm_subdev *subdev = &top->subdev;
struct nvkm_device *device = subdev->device;
@@ -108,7 +108,7 @@ gk104_top_oneinit(struct nvkm_top *top)
static const struct nvkm_top_func
gk104_top = {
- .oneinit = gk104_top_oneinit,
+ .parse = gk104_top_parse,
};
int
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/top/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/top/priv.h
index 8e103a836705..532be91d8fd9 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/top/priv.h
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/top/priv.h
@@ -5,7 +5,7 @@
#include <subdev/top.h>
struct nvkm_top_func {
- int (*oneinit)(struct nvkm_top *);
+ int (*parse)(struct nvkm_top *);
};
int nvkm_top_new_(const struct nvkm_top_func *, struct nvkm_device *, enum nvkm_subdev_type, int,
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/Kbuild
new file mode 100644
index 000000000000..23cd21b40a25
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/Kbuild
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: MIT
+nvkm-y += nvkm/subdev/vfn/base.o
+nvkm-y += nvkm/subdev/vfn/uvfn.o
+nvkm-y += nvkm/subdev/vfn/gv100.o
+nvkm-y += nvkm/subdev/vfn/tu102.o
+nvkm-y += nvkm/subdev/vfn/ga100.o
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c
index 9acaec5c271e..62e81d551f44 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/base.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2012 Red Hat Inc.
+ * Copyright 2021 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -18,45 +18,43 @@
* 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: Ben Skeggs
*/
#include "priv.h"
-#include "head.h"
-#include <core/client.h>
+static void *
+nvkm_vfn_dtor(struct nvkm_subdev *subdev)
+{
+ return nvkm_vfn(subdev);
+}
-#include <nvif/cl0046.h>
-#include <nvif/unpack.h>
+static const struct nvkm_subdev_func
+nvkm_vfn = {
+ .dtor = nvkm_vfn_dtor,
+};
int
-nv04_disp_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size)
+nvkm_vfn_new_(const struct nvkm_vfn_func *func, struct nvkm_device *device,
+ enum nvkm_subdev_type type, int inst, u32 addr, struct nvkm_vfn **pvfn)
{
- struct nvkm_disp *disp = nvkm_disp(object->engine);
- union {
- struct nv04_disp_mthd_v0 v0;
- } *args = data;
- struct nvkm_head *head;
- int id, ret = -ENOSYS;
+ struct nvkm_vfn *vfn;
+ int ret;
- nvif_ioctl(object, "disp mthd size %d\n", size);
- if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
- nvif_ioctl(object, "disp mthd vers %d mthd %02x head %d\n",
- args->v0.version, args->v0.method, args->v0.head);
- mthd = args->v0.method;
- id = args->v0.head;
- } else
- return ret;
+ if (!(vfn = *pvfn = kzalloc(sizeof(*vfn), GFP_KERNEL)))
+ return -ENOMEM;
- if (!(head = nvkm_head_find(disp, id)))
- return -ENXIO;
+ nvkm_subdev_ctor(&nvkm_vfn, device, type, inst, &vfn->subdev);
+ vfn->func = func;
+ vfn->addr.priv = addr;
+ vfn->addr.user = vfn->addr.priv + func->user.addr;
- switch (mthd) {
- case NV04_DISP_SCANOUTPOS:
- return nvkm_head_mthd_scanoutpos(object, head, data, size);
- default:
- break;
+ if (vfn->func->intr) {
+ ret = nvkm_intr_add(vfn->func->intr, vfn->func->intrs,
+ &vfn->subdev, 8, &vfn->intr);
+ if (ret)
+ return ret;
}
- return -EINVAL;
+ vfn->user.ctor = nvkm_uvfn_new;
+ vfn->user.base = func->user.base;
+ return 0;
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c
new file mode 100644
index 000000000000..fd5c6931322d
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/ga100.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2021 Red Hat 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 "priv.h"
+
+#include <nvif/class.h>
+
+static const struct nvkm_intr_data
+ga100_vfn_intrs[] = {
+ { NVKM_ENGINE_DISP , 0, 4, 0x04000000, true },
+ { NVKM_SUBDEV_GPIO , 0, 4, 0x00200000, true },
+ { NVKM_SUBDEV_I2C , 0, 4, 0x00200000, true },
+ { NVKM_SUBDEV_PRIVRING, 0, 4, 0x40000000, true },
+ {}
+};
+
+static const struct nvkm_vfn_func
+ga100_vfn = {
+ .intr = &tu102_vfn_intr,
+ .intrs = ga100_vfn_intrs,
+ .user = { 0x030000, 0x010000, { -1, -1, AMPERE_USERMODE_A } },
+};
+
+int
+ga100_vfn_new(struct nvkm_device *device,
+ enum nvkm_subdev_type type, int inst, struct nvkm_vfn **pvfn)
+{
+ return nvkm_vfn_new_(&ga100_vfn, device, type, inst, 0xb80000, pvfn);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/usertu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/gv100.c
index 217268f8ccad..ddd39d714c4a 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/usertu102.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/gv100.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2018 Red Hat Inc.
+ * Copyright 2021 Red Hat Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -19,27 +19,18 @@
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
-#include "user.h"
+#include "priv.h"
-static int
-tu102_fifo_user_map(struct nvkm_object *object, void *argv, u32 argc,
- enum nvkm_object_map *type, u64 *addr, u64 *size)
-{
- struct nvkm_device *device = object->engine->subdev.device;
- *addr = 0xbb0000 + device->func->resource_addr(device, 0);
- *size = 0x010000;
- *type = NVKM_OBJECT_MAP_IO;
- return 0;
-}
+#include <nvif/class.h>
-static const struct nvkm_object_func
-tu102_fifo_user = {
- .map = tu102_fifo_user_map,
+static const struct nvkm_vfn_func
+gv100_vfn = {
+ .user = { 0x810000, 0x010000, { -1, -1, VOLTA_USERMODE_A } },
};
int
-tu102_fifo_user_new(const struct nvkm_oclass *oclass, void *argv, u32 argc,
- struct nvkm_object **pobject)
+gv100_vfn_new(struct nvkm_device *device,
+ enum nvkm_subdev_type type, int inst, struct nvkm_vfn **pvfn)
{
- return nvkm_object_new_(&tu102_fifo_user, oclass, argv, argc, pobject);
+ return nvkm_vfn_new_(&gv100_vfn, device, type, inst, 0, pvfn);
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h
new file mode 100644
index 000000000000..96d53c02041b
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/priv.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: MIT */
+#ifndef __NVKM_VFN_PRIV_H__
+#define __NVKM_VFN_PRIV_H__
+#define nvkm_vfn(p) container_of((p), struct nvkm_vfn, subdev)
+#include <subdev/vfn.h>
+
+struct nvkm_vfn_func {
+ const struct nvkm_intr_func *intr;
+ const struct nvkm_intr_data *intrs;
+
+ struct {
+ u32 addr;
+ u32 size;
+ const struct nvkm_sclass base;
+ } user;
+};
+
+int nvkm_vfn_new_(const struct nvkm_vfn_func *, struct nvkm_device *, enum nvkm_subdev_type, int,
+ u32 addr, struct nvkm_vfn **);
+
+extern const struct nvkm_intr_func tu102_vfn_intr;
+
+int nvkm_uvfn_new(struct nvkm_device *, const struct nvkm_oclass *, void *, u32,
+ struct nvkm_object **);
+#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c
new file mode 100644
index 000000000000..3d063fb5e136
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/tu102.c
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2021 Red Hat 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 "priv.h"
+
+#include <nvif/class.h>
+
+static void
+tu102_vfn_intr_reset(struct nvkm_intr *intr, int leaf, u32 mask)
+{
+ struct nvkm_vfn *vfn = container_of(intr, typeof(*vfn), intr);
+
+ nvkm_wr32(vfn->subdev.device, vfn->addr.priv + 0x1000 + (leaf * 4), mask);
+}
+
+static void
+tu102_vfn_intr_allow(struct nvkm_intr *intr, int leaf, u32 mask)
+{
+ struct nvkm_vfn *vfn = container_of(intr, typeof(*vfn), intr);
+
+ nvkm_wr32(vfn->subdev.device, vfn->addr.priv + 0x1200 + (leaf * 4), mask);
+}
+
+static void
+tu102_vfn_intr_block(struct nvkm_intr *intr, int leaf, u32 mask)
+{
+ struct nvkm_vfn *vfn = container_of(intr, typeof(*vfn), intr);
+
+ nvkm_wr32(vfn->subdev.device, vfn->addr.priv + 0x1400 + (leaf * 4), mask);
+}
+
+static void
+tu102_vfn_intr_rearm(struct nvkm_intr *intr)
+{
+ struct nvkm_vfn *vfn = container_of(intr, typeof(*vfn), intr);
+
+ nvkm_wr32(vfn->subdev.device, vfn->addr.priv + 0x1608, 0x0000000f);
+}
+
+static void
+tu102_vfn_intr_unarm(struct nvkm_intr *intr)
+{
+ struct nvkm_vfn *vfn = container_of(intr, typeof(*vfn), intr);
+
+ nvkm_wr32(vfn->subdev.device, vfn->addr.priv + 0x1610, 0x0000000f);
+}
+
+static bool
+tu102_vfn_intr_pending(struct nvkm_intr *intr)
+{
+ struct nvkm_vfn *vfn = container_of(intr, typeof(*vfn), intr);
+ struct nvkm_device *device = vfn->subdev.device;
+ u32 intr_top = nvkm_rd32(device, vfn->addr.priv + 0x1600);
+ int pending = 0, leaf;
+
+ for (leaf = 0; leaf < 8; leaf++) {
+ if (intr_top & BIT(leaf / 2)) {
+ intr->stat[leaf] = nvkm_rd32(device, vfn->addr.priv + 0x1000 + (leaf * 4));
+ if (intr->stat[leaf])
+ pending++;
+ } else {
+ intr->stat[leaf] = 0;
+ }
+ }
+
+ return pending != 0;
+}
+
+const struct nvkm_intr_func
+tu102_vfn_intr = {
+ .pending = tu102_vfn_intr_pending,
+ .unarm = tu102_vfn_intr_unarm,
+ .rearm = tu102_vfn_intr_rearm,
+ .block = tu102_vfn_intr_block,
+ .allow = tu102_vfn_intr_allow,
+ .reset = tu102_vfn_intr_reset,
+};
+
+static const struct nvkm_vfn_func
+tu102_vfn = {
+ .intr = &tu102_vfn_intr,
+ .user = { 0x030000, 0x010000, { -1, -1, TURING_USERMODE_A } },
+};
+
+int
+tu102_vfn_new(struct nvkm_device *device,
+ enum nvkm_subdev_type type, int inst, struct nvkm_vfn **pvfn)
+{
+ return nvkm_vfn_new_(&tu102_vfn, device, type, inst, 0xb80000, pvfn);
+}
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/uvfn.c b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/uvfn.c
new file mode 100644
index 000000000000..c5460a14c541
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/vfn/uvfn.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2021 Red Hat 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.
+ */
+#define nvkm_uvfn(p) container_of((p), struct nvkm_uvfn, object)
+#include "priv.h"
+
+#include <core/object.h>
+
+struct nvkm_uvfn {
+ struct nvkm_object object;
+ struct nvkm_vfn *vfn;
+};
+
+static int
+nvkm_uvfn_map(struct nvkm_object *object, void *argv, u32 argc,
+ enum nvkm_object_map *type, u64 *addr, u64 *size)
+{
+ struct nvkm_vfn *vfn = nvkm_uvfn(object)->vfn;
+ struct nvkm_device *device = vfn->subdev.device;
+
+ *addr = device->func->resource_addr(device, 0) + vfn->addr.user;
+ *size = vfn->func->user.size;
+ *type = NVKM_OBJECT_MAP_IO;
+ return 0;
+}
+
+static const struct nvkm_object_func
+nvkm_uvfn = {
+ .map = nvkm_uvfn_map,
+};
+
+int
+nvkm_uvfn_new(struct nvkm_device *device, const struct nvkm_oclass *oclass,
+ void *argv, u32 argc, struct nvkm_object **pobject)
+{
+ struct nvkm_uvfn *uvfn;
+
+ if (argc != 0)
+ return -ENOSYS;
+
+ if (!(uvfn = kzalloc(sizeof(*uvfn), GFP_KERNEL)))
+ return -ENOMEM;
+
+ nvkm_object_ctor(&nvkm_uvfn, oclass, &uvfn->object);
+ uvfn->vfn = device->vfn;
+
+ *pobject = &uvfn->object;
+ return 0;
+}
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c
index 40706c5aad7b..98d8758048fc 100644
--- a/drivers/gpu/drm/omapdrm/omap_fbdev.c
+++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c
@@ -38,7 +38,7 @@ static struct drm_fb_helper *get_fb(struct fb_info *fbi);
static void pan_worker(struct work_struct *work)
{
struct omap_fbdev *fbdev = container_of(work, struct omap_fbdev, work);
- struct fb_info *fbi = fbdev->base.fbdev;
+ struct fb_info *fbi = fbdev->base.info;
int npages;
/* DMM roll shifts in 4K pages: */
@@ -161,7 +161,7 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
goto fail;
}
- fbi = drm_fb_helper_alloc_fbi(helper);
+ fbi = drm_fb_helper_alloc_info(helper);
if (IS_ERR(fbi)) {
dev_err(dev->dev, "failed to allocate fb info\n");
ret = PTR_ERR(fbi);
@@ -177,8 +177,6 @@ static int omap_fbdev_create(struct drm_fb_helper *helper,
drm_fb_helper_fill_info(fbi, helper, sizes);
- dev->mode_config.fb_base = dma_addr;
-
fbi->screen_buffer = omap_gem_vaddr(fbdev->bo);
fbi->screen_size = fbdev->bo->size;
fbi->fix.smem_start = dma_addr;
@@ -274,7 +272,7 @@ void omap_fbdev_fini(struct drm_device *dev)
if (!helper)
return;
- drm_fb_helper_unregister_fbi(helper);
+ drm_fb_helper_unregister_info(helper);
drm_fb_helper_fini(helper);
diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
index 393f82e26927..3abc47521b2c 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
@@ -66,6 +66,8 @@ static int omap_gem_dmabuf_mmap(struct dma_buf *buffer,
struct drm_gem_object *obj = buffer->priv;
int ret = 0;
+ dma_resv_assert_held(buffer->resv);
+
ret = drm_gem_mmap_obj(obj, omap_gem_mmap_size(obj), vma);
if (ret < 0)
return ret;
@@ -125,7 +127,7 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
get_dma_buf(dma_buf);
- sgt = dma_buf_map_attachment(attach, DMA_TO_DEVICE);
+ sgt = dma_buf_map_attachment_unlocked(attach, DMA_TO_DEVICE);
if (IS_ERR(sgt)) {
ret = PTR_ERR(sgt);
goto fail_detach;
@@ -142,7 +144,7 @@ struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
return obj;
fail_unmap:
- dma_buf_unmap_attachment(attach, sgt, DMA_TO_DEVICE);
+ dma_buf_unmap_attachment_unlocked(attach, sgt, DMA_TO_DEVICE);
fail_detach:
dma_buf_detach(dma_buf, attach);
dma_buf_put(dma_buf);
diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig
index a582ddd583c2..737edcdf9eef 100644
--- a/drivers/gpu/drm/panel/Kconfig
+++ b/drivers/gpu/drm/panel/Kconfig
@@ -203,6 +203,16 @@ config DRM_PANEL_INNOLUX_P079ZCA
24 bit RGB per pixel. It provides a MIPI DSI interface to
the host and has a built-in LED backlight.
+config DRM_PANEL_JADARD_JD9365DA_H3
+ tristate "Jadard JD9365DA-H3 WXGA DSI panel"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ Say Y here if you want to enable support for Jadard JD9365DA-H3
+ WXGA MIPI DSI panel. The panel support TFT dot matrix LCD with
+ 800RGBx1280 dots at maximum.
+
config DRM_PANEL_JDI_LT070ME05000
tristate "JDI LT070ME05000 WUXGA DSI panel"
depends on OF
@@ -296,6 +306,15 @@ config DRM_PANEL_NEC_NL8048HL11
panel (found on the Zoom2/3/3630 SDP boards). To compile this driver
as a module, choose M here.
+config DRM_PANEL_NEWVISION_NV3051D
+ tristate "NewVision NV3051D DSI panel"
+ depends on OF
+ depends on DRM_MIPI_DSI
+ depends on BACKLIGHT_CLASS_DEVICE
+ help
+ This driver supports the NV3051D based panel found on the Anbernic
+ RG353P and RG353V.
+
config DRM_PANEL_NEWVISION_NV3052C
tristate "NewVision NV3052C RGB/SPI panel"
depends on OF && SPI
diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile
index 34e717382dbb..f8f9d9f6a307 100644
--- a/drivers/gpu/drm/panel/Makefile
+++ b/drivers/gpu/drm/panel/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9341) += panel-ilitek-ili9341.o
obj-$(CONFIG_DRM_PANEL_ILITEK_ILI9881C) += panel-ilitek-ili9881c.o
obj-$(CONFIG_DRM_PANEL_INNOLUX_EJ030NA) += panel-innolux-ej030na.o
obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o
+obj-$(CONFIG_DRM_PANEL_JADARD_JD9365DA_H3) += panel-jadard-jd9365da-h3.o
obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o
obj-$(CONFIG_DRM_PANEL_JDI_R63452) += panel-jdi-fhd-r63452.o
obj-$(CONFIG_DRM_PANEL_KHADAS_TS050) += panel-khadas-ts050.o
@@ -27,6 +28,7 @@ obj-$(CONFIG_DRM_PANEL_LEADTEK_LTK500HD1829) += panel-leadtek-ltk500hd1829.o
obj-$(CONFIG_DRM_PANEL_LG_LB035Q02) += panel-lg-lb035q02.o
obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o
obj-$(CONFIG_DRM_PANEL_NEC_NL8048HL11) += panel-nec-nl8048hl11.o
+obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3051D) += panel-newvision-nv3051d.o
obj-$(CONFIG_DRM_PANEL_NEWVISION_NV3052C) += panel-newvision-nv3052c.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35510) += panel-novatek-nt35510.o
obj-$(CONFIG_DRM_PANEL_NOVATEK_NT35560) += panel-novatek-nt35560.o
diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c
index 4b39d1dd9140..5cb8dc2ebe18 100644
--- a/drivers/gpu/drm/panel/panel-edp.c
+++ b/drivers/gpu/drm/panel/panel-edp.c
@@ -1883,8 +1883,10 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0a5d, &delay_200_500_e50, "NV116WHM-N45"),
EDP_PANEL_ENTRY('B', 'O', 'E', 0x0ac5, &delay_200_500_e50, "NV116WHM-N4C"),
+ EDP_PANEL_ENTRY('C', 'M', 'N', 0x1139, &delay_200_500_e80_d50, "N116BGE-EA2"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x114c, &innolux_n116bca_ea1.delay, "N116BCA-EA1"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x1152, &delay_200_500_e80_d50, "N116BCN-EA1"),
+ EDP_PANEL_ENTRY('C', 'M', 'N', 0x1153, &delay_200_500_e80_d50, "N116BGE-EA2"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x1154, &delay_200_500_e80_d50, "N116BCA-EA2"),
EDP_PANEL_ENTRY('C', 'M', 'N', 0x1247, &delay_200_500_e80_d50, "N120ACA-EA1"),
diff --git a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
index 39dc40cf681f..384a724f2822 100644
--- a/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
+++ b/drivers/gpu/drm/panel/panel-ilitek-ili9341.c
@@ -18,6 +18,7 @@
* Copyright 2018 David Lechner <david@lechnology.com>
*/
+#include <linux/backlight.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
@@ -30,7 +31,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
diff --git a/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
new file mode 100644
index 000000000000..48c1702a863b
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-jadard-jd9365da-h3.c
@@ -0,0 +1,473 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2019 Radxa Limited
+ * Copyright (c) 2022 Edgeble AI Technologies Pvt. Ltd.
+ *
+ * Author:
+ * - Jagan Teki <jagan@amarulasolutions.com>
+ * - Stephen Chen <stephen@radxa.com>
+ */
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_print.h>
+
+#include <linux/gpio/consumer.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
+
+#define JD9365DA_INIT_CMD_LEN 2
+
+struct jadard_init_cmd {
+ u8 data[JD9365DA_INIT_CMD_LEN];
+};
+
+struct jadard_panel_desc {
+ const struct drm_display_mode mode;
+ unsigned int lanes;
+ enum mipi_dsi_pixel_format format;
+ const struct jadard_init_cmd *init_cmds;
+ u32 num_init_cmds;
+};
+
+struct jadard {
+ struct drm_panel panel;
+ struct mipi_dsi_device *dsi;
+ const struct jadard_panel_desc *desc;
+
+ struct regulator *vdd;
+ struct regulator *vccio;
+ struct gpio_desc *reset;
+};
+
+static inline struct jadard *panel_to_jadard(struct drm_panel *panel)
+{
+ return container_of(panel, struct jadard, panel);
+}
+
+static int jadard_enable(struct drm_panel *panel)
+{
+ struct device *dev = panel->dev;
+ struct jadard *jadard = panel_to_jadard(panel);
+ const struct jadard_panel_desc *desc = jadard->desc;
+ struct mipi_dsi_device *dsi = jadard->dsi;
+ unsigned int i;
+ int err;
+
+ msleep(10);
+
+ for (i = 0; i < desc->num_init_cmds; i++) {
+ const struct jadard_init_cmd *cmd = &desc->init_cmds[i];
+
+ err = mipi_dsi_dcs_write_buffer(dsi, cmd->data, JD9365DA_INIT_CMD_LEN);
+ if (err < 0)
+ return err;
+ }
+
+ msleep(120);
+
+ err = mipi_dsi_dcs_exit_sleep_mode(dsi);
+ if (err < 0)
+ DRM_DEV_ERROR(dev, "failed to exit sleep mode ret = %d\n", err);
+
+ err = mipi_dsi_dcs_set_display_on(dsi);
+ if (err < 0)
+ DRM_DEV_ERROR(dev, "failed to set display on ret = %d\n", err);
+
+ return 0;
+}
+
+static int jadard_disable(struct drm_panel *panel)
+{
+ struct device *dev = panel->dev;
+ struct jadard *jadard = panel_to_jadard(panel);
+ int ret;
+
+ ret = mipi_dsi_dcs_set_display_off(jadard->dsi);
+ if (ret < 0)
+ DRM_DEV_ERROR(dev, "failed to set display off: %d\n", ret);
+
+ ret = mipi_dsi_dcs_enter_sleep_mode(jadard->dsi);
+ if (ret < 0)
+ DRM_DEV_ERROR(dev, "failed to enter sleep mode: %d\n", ret);
+
+ return 0;
+}
+
+static int jadard_prepare(struct drm_panel *panel)
+{
+ struct jadard *jadard = panel_to_jadard(panel);
+ int ret;
+
+ ret = regulator_enable(jadard->vccio);
+ if (ret)
+ return ret;
+
+ ret = regulator_enable(jadard->vdd);
+ if (ret)
+ return ret;
+
+ gpiod_set_value(jadard->reset, 1);
+ msleep(5);
+
+ gpiod_set_value(jadard->reset, 0);
+ msleep(10);
+
+ gpiod_set_value(jadard->reset, 1);
+ msleep(120);
+
+ return 0;
+}
+
+static int jadard_unprepare(struct drm_panel *panel)
+{
+ struct jadard *jadard = panel_to_jadard(panel);
+
+ gpiod_set_value(jadard->reset, 1);
+ msleep(120);
+
+ regulator_disable(jadard->vdd);
+ regulator_disable(jadard->vccio);
+
+ return 0;
+}
+
+static int jadard_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct jadard *jadard = panel_to_jadard(panel);
+ const struct drm_display_mode *desc_mode = &jadard->desc->mode;
+ struct drm_display_mode *mode;
+
+ mode = drm_mode_duplicate(connector->dev, desc_mode);
+ if (!mode) {
+ DRM_DEV_ERROR(&jadard->dsi->dev, "failed to add mode %ux%ux@%u\n",
+ desc_mode->hdisplay, desc_mode->vdisplay,
+ drm_mode_vrefresh(desc_mode));
+ return -ENOMEM;
+ }
+
+ drm_mode_set_name(mode);
+ drm_mode_probed_add(connector, mode);
+
+ connector->display_info.width_mm = mode->width_mm;
+ connector->display_info.height_mm = mode->height_mm;
+
+ return 1;
+}
+
+static const struct drm_panel_funcs jadard_funcs = {
+ .disable = jadard_disable,
+ .unprepare = jadard_unprepare,
+ .prepare = jadard_prepare,
+ .enable = jadard_enable,
+ .get_modes = jadard_get_modes,
+};
+
+static const struct jadard_init_cmd cz101b4001_init_cmds[] = {
+ { .data = { 0xE0, 0x00 } },
+ { .data = { 0xE1, 0x93 } },
+ { .data = { 0xE2, 0x65 } },
+ { .data = { 0xE3, 0xF8 } },
+ { .data = { 0x80, 0x03 } },
+ { .data = { 0xE0, 0x01 } },
+ { .data = { 0x00, 0x00 } },
+ { .data = { 0x01, 0x3B } },
+ { .data = { 0x0C, 0x74 } },
+ { .data = { 0x17, 0x00 } },
+ { .data = { 0x18, 0xAF } },
+ { .data = { 0x19, 0x00 } },
+ { .data = { 0x1A, 0x00 } },
+ { .data = { 0x1B, 0xAF } },
+ { .data = { 0x1C, 0x00 } },
+ { .data = { 0x35, 0x26 } },
+ { .data = { 0x37, 0x09 } },
+ { .data = { 0x38, 0x04 } },
+ { .data = { 0x39, 0x00 } },
+ { .data = { 0x3A, 0x01 } },
+ { .data = { 0x3C, 0x78 } },
+ { .data = { 0x3D, 0xFF } },
+ { .data = { 0x3E, 0xFF } },
+ { .data = { 0x3F, 0x7F } },
+ { .data = { 0x40, 0x06 } },
+ { .data = { 0x41, 0xA0 } },
+ { .data = { 0x42, 0x81 } },
+ { .data = { 0x43, 0x14 } },
+ { .data = { 0x44, 0x23 } },
+ { .data = { 0x45, 0x28 } },
+ { .data = { 0x55, 0x02 } },
+ { .data = { 0x57, 0x69 } },
+ { .data = { 0x59, 0x0A } },
+ { .data = { 0x5A, 0x2A } },
+ { .data = { 0x5B, 0x17 } },
+ { .data = { 0x5D, 0x7F } },
+ { .data = { 0x5E, 0x6B } },
+ { .data = { 0x5F, 0x5C } },
+ { .data = { 0x60, 0x4F } },
+ { .data = { 0x61, 0x4D } },
+ { .data = { 0x62, 0x3F } },
+ { .data = { 0x63, 0x42 } },
+ { .data = { 0x64, 0x2B } },
+ { .data = { 0x65, 0x44 } },
+ { .data = { 0x66, 0x43 } },
+ { .data = { 0x67, 0x43 } },
+ { .data = { 0x68, 0x63 } },
+ { .data = { 0x69, 0x52 } },
+ { .data = { 0x6A, 0x5A } },
+ { .data = { 0x6B, 0x4F } },
+ { .data = { 0x6C, 0x4E } },
+ { .data = { 0x6D, 0x20 } },
+ { .data = { 0x6E, 0x0F } },
+ { .data = { 0x6F, 0x00 } },
+ { .data = { 0x70, 0x7F } },
+ { .data = { 0x71, 0x6B } },
+ { .data = { 0x72, 0x5C } },
+ { .data = { 0x73, 0x4F } },
+ { .data = { 0x74, 0x4D } },
+ { .data = { 0x75, 0x3F } },
+ { .data = { 0x76, 0x42 } },
+ { .data = { 0x77, 0x2B } },
+ { .data = { 0x78, 0x44 } },
+ { .data = { 0x79, 0x43 } },
+ { .data = { 0x7A, 0x43 } },
+ { .data = { 0x7B, 0x63 } },
+ { .data = { 0x7C, 0x52 } },
+ { .data = { 0x7D, 0x5A } },
+ { .data = { 0x7E, 0x4F } },
+ { .data = { 0x7F, 0x4E } },
+ { .data = { 0x80, 0x20 } },
+ { .data = { 0x81, 0x0F } },
+ { .data = { 0x82, 0x00 } },
+ { .data = { 0xE0, 0x02 } },
+ { .data = { 0x00, 0x02 } },
+ { .data = { 0x01, 0x02 } },
+ { .data = { 0x02, 0x00 } },
+ { .data = { 0x03, 0x00 } },
+ { .data = { 0x04, 0x1E } },
+ { .data = { 0x05, 0x1E } },
+ { .data = { 0x06, 0x1F } },
+ { .data = { 0x07, 0x1F } },
+ { .data = { 0x08, 0x1F } },
+ { .data = { 0x09, 0x17 } },
+ { .data = { 0x0A, 0x17 } },
+ { .data = { 0x0B, 0x37 } },
+ { .data = { 0x0C, 0x37 } },
+ { .data = { 0x0D, 0x47 } },
+ { .data = { 0x0E, 0x47 } },
+ { .data = { 0x0F, 0x45 } },
+ { .data = { 0x10, 0x45 } },
+ { .data = { 0x11, 0x4B } },
+ { .data = { 0x12, 0x4B } },
+ { .data = { 0x13, 0x49 } },
+ { .data = { 0x14, 0x49 } },
+ { .data = { 0x15, 0x1F } },
+ { .data = { 0x16, 0x01 } },
+ { .data = { 0x17, 0x01 } },
+ { .data = { 0x18, 0x00 } },
+ { .data = { 0x19, 0x00 } },
+ { .data = { 0x1A, 0x1E } },
+ { .data = { 0x1B, 0x1E } },
+ { .data = { 0x1C, 0x1F } },
+ { .data = { 0x1D, 0x1F } },
+ { .data = { 0x1E, 0x1F } },
+ { .data = { 0x1F, 0x17 } },
+ { .data = { 0x20, 0x17 } },
+ { .data = { 0x21, 0x37 } },
+ { .data = { 0x22, 0x37 } },
+ { .data = { 0x23, 0x46 } },
+ { .data = { 0x24, 0x46 } },
+ { .data = { 0x25, 0x44 } },
+ { .data = { 0x26, 0x44 } },
+ { .data = { 0x27, 0x4A } },
+ { .data = { 0x28, 0x4A } },
+ { .data = { 0x29, 0x48 } },
+ { .data = { 0x2A, 0x48 } },
+ { .data = { 0x2B, 0x1F } },
+ { .data = { 0x2C, 0x01 } },
+ { .data = { 0x2D, 0x01 } },
+ { .data = { 0x2E, 0x00 } },
+ { .data = { 0x2F, 0x00 } },
+ { .data = { 0x30, 0x1F } },
+ { .data = { 0x31, 0x1F } },
+ { .data = { 0x32, 0x1E } },
+ { .data = { 0x33, 0x1E } },
+ { .data = { 0x34, 0x1F } },
+ { .data = { 0x35, 0x17 } },
+ { .data = { 0x36, 0x17 } },
+ { .data = { 0x37, 0x37 } },
+ { .data = { 0x38, 0x37 } },
+ { .data = { 0x39, 0x08 } },
+ { .data = { 0x3A, 0x08 } },
+ { .data = { 0x3B, 0x0A } },
+ { .data = { 0x3C, 0x0A } },
+ { .data = { 0x3D, 0x04 } },
+ { .data = { 0x3E, 0x04 } },
+ { .data = { 0x3F, 0x06 } },
+ { .data = { 0x40, 0x06 } },
+ { .data = { 0x41, 0x1F } },
+ { .data = { 0x42, 0x02 } },
+ { .data = { 0x43, 0x02 } },
+ { .data = { 0x44, 0x00 } },
+ { .data = { 0x45, 0x00 } },
+ { .data = { 0x46, 0x1F } },
+ { .data = { 0x47, 0x1F } },
+ { .data = { 0x48, 0x1E } },
+ { .data = { 0x49, 0x1E } },
+ { .data = { 0x4A, 0x1F } },
+ { .data = { 0x4B, 0x17 } },
+ { .data = { 0x4C, 0x17 } },
+ { .data = { 0x4D, 0x37 } },
+ { .data = { 0x4E, 0x37 } },
+ { .data = { 0x4F, 0x09 } },
+ { .data = { 0x50, 0x09 } },
+ { .data = { 0x51, 0x0B } },
+ { .data = { 0x52, 0x0B } },
+ { .data = { 0x53, 0x05 } },
+ { .data = { 0x54, 0x05 } },
+ { .data = { 0x55, 0x07 } },
+ { .data = { 0x56, 0x07 } },
+ { .data = { 0x57, 0x1F } },
+ { .data = { 0x58, 0x40 } },
+ { .data = { 0x5B, 0x30 } },
+ { .data = { 0x5C, 0x16 } },
+ { .data = { 0x5D, 0x34 } },
+ { .data = { 0x5E, 0x05 } },
+ { .data = { 0x5F, 0x02 } },
+ { .data = { 0x63, 0x00 } },
+ { .data = { 0x64, 0x6A } },
+ { .data = { 0x67, 0x73 } },
+ { .data = { 0x68, 0x1D } },
+ { .data = { 0x69, 0x08 } },
+ { .data = { 0x6A, 0x6A } },
+ { .data = { 0x6B, 0x08 } },
+ { .data = { 0x6C, 0x00 } },
+ { .data = { 0x6D, 0x00 } },
+ { .data = { 0x6E, 0x00 } },
+ { .data = { 0x6F, 0x88 } },
+ { .data = { 0x75, 0xFF } },
+ { .data = { 0x77, 0xDD } },
+ { .data = { 0x78, 0x3F } },
+ { .data = { 0x79, 0x15 } },
+ { .data = { 0x7A, 0x17 } },
+ { .data = { 0x7D, 0x14 } },
+ { .data = { 0x7E, 0x82 } },
+ { .data = { 0xE0, 0x04 } },
+ { .data = { 0x00, 0x0E } },
+ { .data = { 0x02, 0xB3 } },
+ { .data = { 0x09, 0x61 } },
+ { .data = { 0x0E, 0x48 } },
+ { .data = { 0xE0, 0x00 } },
+ { .data = { 0xE6, 0x02 } },
+ { .data = { 0xE7, 0x0C } },
+};
+
+static const struct jadard_panel_desc cz101b4001_desc = {
+ .mode = {
+ .clock = 70000,
+
+ .hdisplay = 800,
+ .hsync_start = 800 + 40,
+ .hsync_end = 800 + 40 + 18,
+ .htotal = 800 + 40 + 18 + 20,
+
+ .vdisplay = 1280,
+ .vsync_start = 1280 + 20,
+ .vsync_end = 1280 + 20 + 4,
+ .vtotal = 1280 + 20 + 4 + 20,
+
+ .width_mm = 62,
+ .height_mm = 110,
+ .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
+ },
+ .lanes = 4,
+ .format = MIPI_DSI_FMT_RGB888,
+ .init_cmds = cz101b4001_init_cmds,
+ .num_init_cmds = ARRAY_SIZE(cz101b4001_init_cmds),
+};
+
+static int jadard_dsi_probe(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ const struct jadard_panel_desc *desc;
+ struct jadard *jadard;
+ int ret;
+
+ jadard = devm_kzalloc(&dsi->dev, sizeof(*jadard), GFP_KERNEL);
+ if (!jadard)
+ return -ENOMEM;
+
+ desc = of_device_get_match_data(dev);
+ dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
+ MIPI_DSI_MODE_NO_EOT_PACKET;
+ dsi->format = desc->format;
+ dsi->lanes = desc->lanes;
+
+ jadard->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(jadard->reset)) {
+ DRM_DEV_ERROR(&dsi->dev, "failed to get our reset GPIO\n");
+ return PTR_ERR(jadard->reset);
+ }
+
+ jadard->vdd = devm_regulator_get(dev, "vdd");
+ if (IS_ERR(jadard->vdd)) {
+ DRM_DEV_ERROR(&dsi->dev, "failed to get vdd regulator\n");
+ return PTR_ERR(jadard->vdd);
+ }
+
+ jadard->vccio = devm_regulator_get(dev, "vccio");
+ if (IS_ERR(jadard->vccio)) {
+ DRM_DEV_ERROR(&dsi->dev, "failed to get vccio regulator\n");
+ return PTR_ERR(jadard->vccio);
+ }
+
+ drm_panel_init(&jadard->panel, dev, &jadard_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+
+ ret = drm_panel_of_backlight(&jadard->panel);
+ if (ret)
+ return ret;
+
+ drm_panel_add(&jadard->panel);
+
+ mipi_dsi_set_drvdata(dsi, jadard);
+ jadard->dsi = dsi;
+ jadard->desc = desc;
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret < 0)
+ drm_panel_remove(&jadard->panel);
+
+ return ret;
+}
+
+static void jadard_dsi_remove(struct mipi_dsi_device *dsi)
+{
+ struct jadard *jadard = mipi_dsi_get_drvdata(dsi);
+
+ mipi_dsi_detach(dsi);
+ drm_panel_remove(&jadard->panel);
+}
+
+static const struct of_device_id jadard_of_match[] = {
+ { .compatible = "chongzhou,cz101b4001", .data = &cz101b4001_desc },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, jadard_of_match);
+
+static struct mipi_dsi_driver jadard_driver = {
+ .probe = jadard_dsi_probe,
+ .remove = jadard_dsi_remove,
+ .driver = {
+ .name = "jadard-jd9365da",
+ .of_match_table = jadard_of_match,
+ },
+};
+module_mipi_dsi_driver(jadard_driver);
+
+MODULE_AUTHOR("Jagan Teki <jagan@edgeble.ai>");
+MODULE_AUTHOR("Stephen Chen <stephen@radxa.com>");
+MODULE_DESCRIPTION("Jadard JD9365DA-H3 WXGA DSI panel");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/panel/panel-newvision-nv3051d.c b/drivers/gpu/drm/panel/panel-newvision-nv3051d.c
new file mode 100644
index 000000000000..a07958038ffd
--- /dev/null
+++ b/drivers/gpu/drm/panel/panel-newvision-nv3051d.c
@@ -0,0 +1,504 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * NV3051D MIPI-DSI panel driver for Anbernic RG353x
+ * Copyright (C) 2022 Chris Morgan
+ *
+ * based on
+ *
+ * Elida kd35t133 3.5" MIPI-DSI panel driver
+ * Copyright (C) Theobroma Systems 2020
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/media-bus-format.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regulator/consumer.h>
+
+#include <video/display_timing.h>
+#include <video/mipi_display.h>
+
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_panel.h>
+
+struct nv3051d_panel_info {
+ const struct drm_display_mode *display_modes;
+ unsigned int num_modes;
+ u16 width_mm, height_mm;
+ u32 bus_flags;
+};
+
+struct panel_nv3051d {
+ struct device *dev;
+ struct drm_panel panel;
+ struct gpio_desc *reset_gpio;
+ const struct nv3051d_panel_info *panel_info;
+ struct regulator *vdd;
+};
+
+static inline struct panel_nv3051d *panel_to_panelnv3051d(struct drm_panel *panel)
+{
+ return container_of(panel, struct panel_nv3051d, panel);
+}
+
+static int panel_nv3051d_init_sequence(struct panel_nv3051d *ctx)
+{
+ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
+
+ /*
+ * Init sequence was supplied by device vendor with no
+ * documentation.
+ */
+
+ mipi_dsi_dcs_write_seq(dsi, 0xFF, 0x30);
+ mipi_dsi_dcs_write_seq(dsi, 0xFF, 0x52);
+ mipi_dsi_dcs_write_seq(dsi, 0xFF, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xE3, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x03, 0x40);
+ mipi_dsi_dcs_write_seq(dsi, 0x04, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x05, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0x24, 0x12);
+ mipi_dsi_dcs_write_seq(dsi, 0x25, 0x1E);
+ mipi_dsi_dcs_write_seq(dsi, 0x26, 0x28);
+ mipi_dsi_dcs_write_seq(dsi, 0x27, 0x52);
+ mipi_dsi_dcs_write_seq(dsi, 0x28, 0x57);
+ mipi_dsi_dcs_write_seq(dsi, 0x29, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x2A, 0xDF);
+ mipi_dsi_dcs_write_seq(dsi, 0x38, 0x9C);
+ mipi_dsi_dcs_write_seq(dsi, 0x39, 0xA7);
+ mipi_dsi_dcs_write_seq(dsi, 0x3A, 0x53);
+ mipi_dsi_dcs_write_seq(dsi, 0x44, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x49, 0x3C);
+ mipi_dsi_dcs_write_seq(dsi, 0x59, 0xFE);
+ mipi_dsi_dcs_write_seq(dsi, 0x5C, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x91, 0x77);
+ mipi_dsi_dcs_write_seq(dsi, 0x92, 0x77);
+ mipi_dsi_dcs_write_seq(dsi, 0xA0, 0x55);
+ mipi_dsi_dcs_write_seq(dsi, 0xA1, 0x50);
+ mipi_dsi_dcs_write_seq(dsi, 0xA4, 0x9C);
+ mipi_dsi_dcs_write_seq(dsi, 0xA7, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0xA8, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xA9, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xAA, 0xFC);
+ mipi_dsi_dcs_write_seq(dsi, 0xAB, 0x28);
+ mipi_dsi_dcs_write_seq(dsi, 0xAC, 0x06);
+ mipi_dsi_dcs_write_seq(dsi, 0xAD, 0x06);
+ mipi_dsi_dcs_write_seq(dsi, 0xAE, 0x06);
+ mipi_dsi_dcs_write_seq(dsi, 0xAF, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0xB0, 0x08);
+ mipi_dsi_dcs_write_seq(dsi, 0xB1, 0x26);
+ mipi_dsi_dcs_write_seq(dsi, 0xB2, 0x28);
+ mipi_dsi_dcs_write_seq(dsi, 0xB3, 0x28);
+ mipi_dsi_dcs_write_seq(dsi, 0xB4, 0x33);
+ mipi_dsi_dcs_write_seq(dsi, 0xB5, 0x08);
+ mipi_dsi_dcs_write_seq(dsi, 0xB6, 0x26);
+ mipi_dsi_dcs_write_seq(dsi, 0xB7, 0x08);
+ mipi_dsi_dcs_write_seq(dsi, 0xB8, 0x26);
+ mipi_dsi_dcs_write_seq(dsi, 0xFF, 0x30);
+ mipi_dsi_dcs_write_seq(dsi, 0xFF, 0x52);
+ mipi_dsi_dcs_write_seq(dsi, 0xFF, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0xB1, 0x0E);
+ mipi_dsi_dcs_write_seq(dsi, 0xD1, 0x0E);
+ mipi_dsi_dcs_write_seq(dsi, 0xB4, 0x29);
+ mipi_dsi_dcs_write_seq(dsi, 0xD4, 0x2B);
+ mipi_dsi_dcs_write_seq(dsi, 0xB2, 0x0C);
+ mipi_dsi_dcs_write_seq(dsi, 0xD2, 0x0A);
+ mipi_dsi_dcs_write_seq(dsi, 0xB3, 0x28);
+ mipi_dsi_dcs_write_seq(dsi, 0xD3, 0x28);
+ mipi_dsi_dcs_write_seq(dsi, 0xB6, 0x11);
+ mipi_dsi_dcs_write_seq(dsi, 0xD6, 0x0D);
+ mipi_dsi_dcs_write_seq(dsi, 0xB7, 0x32);
+ mipi_dsi_dcs_write_seq(dsi, 0xD7, 0x30);
+ mipi_dsi_dcs_write_seq(dsi, 0xC1, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0xE1, 0x06);
+ mipi_dsi_dcs_write_seq(dsi, 0xB8, 0x0A);
+ mipi_dsi_dcs_write_seq(dsi, 0xD8, 0x0A);
+ mipi_dsi_dcs_write_seq(dsi, 0xB9, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xD9, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0xBD, 0x13);
+ mipi_dsi_dcs_write_seq(dsi, 0xDD, 0x13);
+ mipi_dsi_dcs_write_seq(dsi, 0xBC, 0x11);
+ mipi_dsi_dcs_write_seq(dsi, 0xDC, 0x11);
+ mipi_dsi_dcs_write_seq(dsi, 0xBB, 0x0F);
+ mipi_dsi_dcs_write_seq(dsi, 0xDB, 0x0F);
+ mipi_dsi_dcs_write_seq(dsi, 0xBA, 0x0F);
+ mipi_dsi_dcs_write_seq(dsi, 0xDA, 0x0F);
+ mipi_dsi_dcs_write_seq(dsi, 0xBE, 0x18);
+ mipi_dsi_dcs_write_seq(dsi, 0xDE, 0x18);
+ mipi_dsi_dcs_write_seq(dsi, 0xBF, 0x0F);
+ mipi_dsi_dcs_write_seq(dsi, 0xDF, 0x0F);
+ mipi_dsi_dcs_write_seq(dsi, 0xC0, 0x17);
+ mipi_dsi_dcs_write_seq(dsi, 0xE0, 0x17);
+ mipi_dsi_dcs_write_seq(dsi, 0xB5, 0x3B);
+ mipi_dsi_dcs_write_seq(dsi, 0xD5, 0x3C);
+ mipi_dsi_dcs_write_seq(dsi, 0xB0, 0x0B);
+ mipi_dsi_dcs_write_seq(dsi, 0xD0, 0x0C);
+ mipi_dsi_dcs_write_seq(dsi, 0xFF, 0x30);
+ mipi_dsi_dcs_write_seq(dsi, 0xFF, 0x52);
+ mipi_dsi_dcs_write_seq(dsi, 0xFF, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0x00, 0x2A);
+ mipi_dsi_dcs_write_seq(dsi, 0x01, 0x2A);
+ mipi_dsi_dcs_write_seq(dsi, 0x02, 0x2A);
+ mipi_dsi_dcs_write_seq(dsi, 0x03, 0x2A);
+ mipi_dsi_dcs_write_seq(dsi, 0x04, 0x61);
+ mipi_dsi_dcs_write_seq(dsi, 0x05, 0x80);
+ mipi_dsi_dcs_write_seq(dsi, 0x06, 0xC7);
+ mipi_dsi_dcs_write_seq(dsi, 0x07, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x08, 0x82);
+ mipi_dsi_dcs_write_seq(dsi, 0x09, 0x83);
+ mipi_dsi_dcs_write_seq(dsi, 0x30, 0x2A);
+ mipi_dsi_dcs_write_seq(dsi, 0x31, 0x2A);
+ mipi_dsi_dcs_write_seq(dsi, 0x32, 0x2A);
+ mipi_dsi_dcs_write_seq(dsi, 0x33, 0x2A);
+ mipi_dsi_dcs_write_seq(dsi, 0x34, 0x61);
+ mipi_dsi_dcs_write_seq(dsi, 0x35, 0xC5);
+ mipi_dsi_dcs_write_seq(dsi, 0x36, 0x80);
+ mipi_dsi_dcs_write_seq(dsi, 0x37, 0x23);
+ mipi_dsi_dcs_write_seq(dsi, 0x40, 0x82);
+ mipi_dsi_dcs_write_seq(dsi, 0x41, 0x83);
+ mipi_dsi_dcs_write_seq(dsi, 0x42, 0x80);
+ mipi_dsi_dcs_write_seq(dsi, 0x43, 0x81);
+ mipi_dsi_dcs_write_seq(dsi, 0x44, 0x11);
+ mipi_dsi_dcs_write_seq(dsi, 0x45, 0xF2);
+ mipi_dsi_dcs_write_seq(dsi, 0x46, 0xF1);
+ mipi_dsi_dcs_write_seq(dsi, 0x47, 0x11);
+ mipi_dsi_dcs_write_seq(dsi, 0x48, 0xF4);
+ mipi_dsi_dcs_write_seq(dsi, 0x49, 0xF3);
+ mipi_dsi_dcs_write_seq(dsi, 0x50, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x51, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x52, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x53, 0x03);
+ mipi_dsi_dcs_write_seq(dsi, 0x54, 0x11);
+ mipi_dsi_dcs_write_seq(dsi, 0x55, 0xF6);
+ mipi_dsi_dcs_write_seq(dsi, 0x56, 0xF5);
+ mipi_dsi_dcs_write_seq(dsi, 0x57, 0x11);
+ mipi_dsi_dcs_write_seq(dsi, 0x58, 0xF8);
+ mipi_dsi_dcs_write_seq(dsi, 0x59, 0xF7);
+ mipi_dsi_dcs_write_seq(dsi, 0x7E, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x7F, 0x80);
+ mipi_dsi_dcs_write_seq(dsi, 0xE0, 0x5A);
+ mipi_dsi_dcs_write_seq(dsi, 0xB1, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0xB4, 0x0E);
+ mipi_dsi_dcs_write_seq(dsi, 0xB5, 0x0F);
+ mipi_dsi_dcs_write_seq(dsi, 0xB6, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0xB7, 0x07);
+ mipi_dsi_dcs_write_seq(dsi, 0xB8, 0x06);
+ mipi_dsi_dcs_write_seq(dsi, 0xB9, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xBA, 0x0F);
+ mipi_dsi_dcs_write_seq(dsi, 0xC7, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0xCA, 0x0E);
+ mipi_dsi_dcs_write_seq(dsi, 0xCB, 0x0F);
+ mipi_dsi_dcs_write_seq(dsi, 0xCC, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0xCD, 0x07);
+ mipi_dsi_dcs_write_seq(dsi, 0xCE, 0x06);
+ mipi_dsi_dcs_write_seq(dsi, 0xCF, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0xD0, 0x0F);
+ mipi_dsi_dcs_write_seq(dsi, 0x81, 0x0F);
+ mipi_dsi_dcs_write_seq(dsi, 0x84, 0x0E);
+ mipi_dsi_dcs_write_seq(dsi, 0x85, 0x0F);
+ mipi_dsi_dcs_write_seq(dsi, 0x86, 0x07);
+ mipi_dsi_dcs_write_seq(dsi, 0x87, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x88, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x89, 0x06);
+ mipi_dsi_dcs_write_seq(dsi, 0x8A, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x97, 0x0F);
+ mipi_dsi_dcs_write_seq(dsi, 0x9A, 0x0E);
+ mipi_dsi_dcs_write_seq(dsi, 0x9B, 0x0F);
+ mipi_dsi_dcs_write_seq(dsi, 0x9C, 0x07);
+ mipi_dsi_dcs_write_seq(dsi, 0x9D, 0x04);
+ mipi_dsi_dcs_write_seq(dsi, 0x9E, 0x05);
+ mipi_dsi_dcs_write_seq(dsi, 0x9F, 0x06);
+ mipi_dsi_dcs_write_seq(dsi, 0xA0, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0xFF, 0x30);
+ mipi_dsi_dcs_write_seq(dsi, 0xFF, 0x52);
+ mipi_dsi_dcs_write_seq(dsi, 0xFF, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x01, 0x01);
+ mipi_dsi_dcs_write_seq(dsi, 0x02, 0xDA);
+ mipi_dsi_dcs_write_seq(dsi, 0x03, 0xBA);
+ mipi_dsi_dcs_write_seq(dsi, 0x04, 0xA8);
+ mipi_dsi_dcs_write_seq(dsi, 0x05, 0x9A);
+ mipi_dsi_dcs_write_seq(dsi, 0x06, 0x70);
+ mipi_dsi_dcs_write_seq(dsi, 0x07, 0xFF);
+ mipi_dsi_dcs_write_seq(dsi, 0x08, 0x91);
+ mipi_dsi_dcs_write_seq(dsi, 0x09, 0x90);
+ mipi_dsi_dcs_write_seq(dsi, 0x0A, 0xFF);
+ mipi_dsi_dcs_write_seq(dsi, 0x0B, 0x8F);
+ mipi_dsi_dcs_write_seq(dsi, 0x0C, 0x60);
+ mipi_dsi_dcs_write_seq(dsi, 0x0D, 0x58);
+ mipi_dsi_dcs_write_seq(dsi, 0x0E, 0x48);
+ mipi_dsi_dcs_write_seq(dsi, 0x0F, 0x38);
+ mipi_dsi_dcs_write_seq(dsi, 0x10, 0x2B);
+ mipi_dsi_dcs_write_seq(dsi, 0xFF, 0x30);
+ mipi_dsi_dcs_write_seq(dsi, 0xFF, 0x52);
+ mipi_dsi_dcs_write_seq(dsi, 0xFF, 0x00);
+ mipi_dsi_dcs_write_seq(dsi, 0x36, 0x02);
+ mipi_dsi_dcs_write_seq(dsi, 0x3A, 0x70);
+
+ dev_dbg(ctx->dev, "Panel init sequence done\n");
+
+ return 0;
+}
+
+static int panel_nv3051d_unprepare(struct drm_panel *panel)
+{
+ struct panel_nv3051d *ctx = panel_to_panelnv3051d(panel);
+ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
+ int ret;
+
+ ret = mipi_dsi_dcs_set_display_off(dsi);
+ if (ret < 0)
+ dev_err(ctx->dev, "failed to set display off: %d\n", ret);
+
+ msleep(20);
+
+ ret = mipi_dsi_dcs_enter_sleep_mode(dsi);
+ if (ret < 0) {
+ dev_err(ctx->dev, "failed to enter sleep mode: %d\n", ret);
+ return ret;
+ }
+
+ usleep_range(10000, 15000);
+
+ regulator_disable(ctx->vdd);
+
+ return 0;
+}
+
+static int panel_nv3051d_prepare(struct drm_panel *panel)
+{
+ struct panel_nv3051d *ctx = panel_to_panelnv3051d(panel);
+ struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev);
+ int ret;
+
+ dev_dbg(ctx->dev, "Resetting the panel\n");
+ ret = regulator_enable(ctx->vdd);
+ if (ret < 0) {
+ dev_err(ctx->dev, "Failed to enable vdd supply: %d\n", ret);
+ return ret;
+ }
+
+ usleep_range(2000, 3000);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 1);
+ msleep(150);
+ gpiod_set_value_cansleep(ctx->reset_gpio, 0);
+ msleep(20);
+
+ ret = panel_nv3051d_init_sequence(ctx);
+ if (ret < 0) {
+ dev_err(ctx->dev, "Panel init sequence failed: %d\n", ret);
+ goto disable_vdd;
+ }
+
+ ret = mipi_dsi_dcs_exit_sleep_mode(dsi);
+ if (ret < 0) {
+ dev_err(ctx->dev, "Failed to exit sleep mode: %d\n", ret);
+ goto disable_vdd;
+ }
+
+ msleep(200);
+
+ ret = mipi_dsi_dcs_set_display_on(dsi);
+ if (ret < 0) {
+ dev_err(ctx->dev, "Failed to set display on: %d\n", ret);
+ goto disable_vdd;
+ }
+
+ usleep_range(10000, 15000);
+
+ return 0;
+
+disable_vdd:
+ regulator_disable(ctx->vdd);
+ return ret;
+}
+
+static int panel_nv3051d_get_modes(struct drm_panel *panel,
+ struct drm_connector *connector)
+{
+ struct panel_nv3051d *ctx = panel_to_panelnv3051d(panel);
+ const struct nv3051d_panel_info *panel_info = ctx->panel_info;
+ struct drm_display_mode *mode;
+ unsigned int i;
+
+ for (i = 0; i < panel_info->num_modes; i++) {
+ mode = drm_mode_duplicate(connector->dev,
+ &panel_info->display_modes[i]);
+ if (!mode)
+ return -ENOMEM;
+
+ drm_mode_set_name(mode);
+
+ mode->type = DRM_MODE_TYPE_DRIVER;
+ if (panel_info->num_modes == 1)
+ mode->type |= DRM_MODE_TYPE_PREFERRED;
+
+ drm_mode_probed_add(connector, mode);
+ }
+
+ connector->display_info.bpc = 8;
+ connector->display_info.width_mm = panel_info->width_mm;
+ connector->display_info.height_mm = panel_info->height_mm;
+ connector->display_info.bus_flags = panel_info->bus_flags;
+
+ return panel_info->num_modes;
+}
+
+static const struct drm_panel_funcs panel_nv3051d_funcs = {
+ .unprepare = panel_nv3051d_unprepare,
+ .prepare = panel_nv3051d_prepare,
+ .get_modes = panel_nv3051d_get_modes,
+};
+
+static int panel_nv3051d_probe(struct mipi_dsi_device *dsi)
+{
+ struct device *dev = &dsi->dev;
+ struct panel_nv3051d *ctx;
+ int ret;
+
+ ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ ctx->dev = dev;
+
+ ctx->panel_info = of_device_get_match_data(dev);
+ if (!ctx->panel_info)
+ return -EINVAL;
+
+ ctx->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(ctx->reset_gpio)) {
+ dev_err(dev, "cannot get reset gpio\n");
+ return PTR_ERR(ctx->reset_gpio);
+ }
+
+ ctx->vdd = devm_regulator_get(dev, "vdd");
+ if (IS_ERR(ctx->vdd)) {
+ ret = PTR_ERR(ctx->vdd);
+ if (ret != -EPROBE_DEFER)
+ dev_err(dev, "Failed to request vdd regulator: %d\n", ret);
+ return ret;
+ }
+
+ 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 |
+ MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_NO_EOT_PACKET;
+
+ drm_panel_init(&ctx->panel, &dsi->dev, &panel_nv3051d_funcs,
+ DRM_MODE_CONNECTOR_DSI);
+
+ ret = drm_panel_of_backlight(&ctx->panel);
+ if (ret)
+ return ret;
+
+ drm_panel_add(&ctx->panel);
+
+ ret = mipi_dsi_attach(dsi);
+ if (ret < 0) {
+ dev_err(dev, "mipi_dsi_attach failed: %d\n", ret);
+ drm_panel_remove(&ctx->panel);
+ return ret;
+ }
+
+ return 0;
+}
+
+static void panel_nv3051d_shutdown(struct mipi_dsi_device *dsi)
+{
+ struct panel_nv3051d *ctx = mipi_dsi_get_drvdata(dsi);
+ int ret;
+
+ ret = drm_panel_unprepare(&ctx->panel);
+ if (ret < 0)
+ dev_err(&dsi->dev, "Failed to unprepare panel: %d\n", ret);
+
+ ret = drm_panel_disable(&ctx->panel);
+ if (ret < 0)
+ dev_err(&dsi->dev, "Failed to disable panel: %d\n", ret);
+}
+
+static void panel_nv3051d_remove(struct mipi_dsi_device *dsi)
+{
+ struct panel_nv3051d *ctx = mipi_dsi_get_drvdata(dsi);
+ int ret;
+
+ panel_nv3051d_shutdown(dsi);
+
+ 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 drm_display_mode nv3051d_rgxx3_modes[] = {
+ { /* 120hz */
+ .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 = 48300,
+ .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+ },
+ { /* 100hz */
+ .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 = 40250,
+ .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
+ },
+ { /* 60hz */
+ .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,
+ },
+};
+
+static const struct nv3051d_panel_info nv3051d_rgxx3_info = {
+ .display_modes = nv3051d_rgxx3_modes,
+ .num_modes = ARRAY_SIZE(nv3051d_rgxx3_modes),
+ .width_mm = 70,
+ .height_mm = 57,
+ .bus_flags = DRM_BUS_FLAG_DE_LOW | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE,
+};
+
+static const struct of_device_id newvision_nv3051d_of_match[] = {
+ { .compatible = "newvision,nv3051d", .data = &nv3051d_rgxx3_info },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, newvision_nv3051d_of_match);
+
+static struct mipi_dsi_driver newvision_nv3051d_driver = {
+ .driver = {
+ .name = "panel-newvision-nv3051d",
+ .of_match_table = newvision_nv3051d_of_match,
+ },
+ .probe = panel_nv3051d_probe,
+ .remove = panel_nv3051d_remove,
+ .shutdown = panel_nv3051d_shutdown,
+};
+module_mipi_dsi_driver(newvision_nv3051d_driver);
+
+MODULE_AUTHOR("Chris Morgan <macromorgan@hotmail.com>");
+MODULE_DESCRIPTION("DRM driver for Newvision NV3051D based MIPI DSI panels");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/panel/panel-samsung-db7430.c b/drivers/gpu/drm/panel/panel-samsung-db7430.c
index 04640c5256a8..117b26845083 100644
--- a/drivers/gpu/drm/panel/panel-samsung-db7430.c
+++ b/drivers/gpu/drm/panel/panel-samsung-db7430.c
@@ -331,9 +331,16 @@ static const struct of_device_id db7430_match[] = {
};
MODULE_DEVICE_TABLE(of, db7430_match);
+static const struct spi_device_id db7430_ids[] = {
+ { "lms397kf04" },
+ { },
+};
+MODULE_DEVICE_TABLE(spi, db7430_ids);
+
static struct spi_driver db7430_driver = {
.probe = db7430_probe,
.remove = db7430_remove,
+ .id_table = db7430_ids,
.driver = {
.name = "db7430-panel",
.of_match_table = db7430_match,
diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c
index c481daa4bbce..0b8cf65172ff 100644
--- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c
@@ -19,6 +19,9 @@
/* Command2 BKx selection command */
#define DSI_CMD2BKX_SEL 0xFF
+#define DSI_CMD1 0
+#define DSI_CMD2 BIT(4)
+#define DSI_CMD2BK_MASK GENMASK(3, 0)
/* Command2, BK0 commands */
#define DSI_CMD2_BK0_PVGAMCTRL 0xB0 /* Positive Voltage Gamma Control */
@@ -39,21 +42,6 @@
#define DSI_CMD2_BK1_SPD2 0xC2 /* Source EQ2 Setting */
#define DSI_CMD2_BK1_MIPISET1 0xD0 /* MIPI Setting 1 */
-/*
- * Command2 with BK function selection.
- *
- * BIT[4].....CN2
- * BIT[1:0]...BKXSEL
- * 1:00 = CMD2BK0, Command2 BK0
- * 1:01 = CMD2BK1, Command2 BK1
- * 1:11 = CMD2BK3, Command2 BK3
- * 0:00 = Command2 disable
- */
-#define DSI_CMD2BK0_SEL 0x10
-#define DSI_CMD2BK1_SEL 0x11
-#define DSI_CMD2BK3_SEL 0x13
-#define DSI_CMD2BKX_SEL_NONE 0x00
-
/* Command2, BK0 bytes */
#define DSI_CMD2_BK0_GAMCTRL_AJ_MASK GENMASK(7, 6)
#define DSI_CMD2_BK0_GAMCTRL_VC0_MASK GENMASK(3, 0)
@@ -191,6 +179,18 @@ static u8 st7701_vgls_map(struct st7701 *st7701)
return 0;
}
+static void st7701_switch_cmd_bkx(struct st7701 *st7701, bool cmd2, u8 bkx)
+{
+ u8 val;
+
+ if (cmd2)
+ val = DSI_CMD2 | FIELD_PREP(DSI_CMD2BK_MASK, bkx);
+ else
+ val = DSI_CMD1;
+
+ ST7701_DSI(st7701, DSI_CMD2BKX_SEL, 0x77, 0x01, 0x00, 0x00, val);
+}
+
static void st7701_init_sequence(struct st7701 *st7701)
{
const struct st7701_panel_desc *desc = st7701->desc;
@@ -208,8 +208,8 @@ static void st7701_init_sequence(struct st7701 *st7701)
msleep(st7701->sleep_delay);
/* Command2, BK0 */
- ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
- 0x77, 0x01, 0x00, 0x00, DSI_CMD2BK0_SEL);
+ st7701_switch_cmd_bkx(st7701, true, 0);
+
mipi_dsi_dcs_write(st7701->dsi, DSI_CMD2_BK0_PVGAMCTRL,
desc->pv_gamma, ARRAY_SIZE(desc->pv_gamma));
mipi_dsi_dcs_write(st7701->dsi, DSI_CMD2_BK0_NVGAMCTRL,
@@ -244,11 +244,10 @@ static void st7701_init_sequence(struct st7701 *st7701)
DSI_CMD2_BK0_INVSEL_ONES_MASK |
FIELD_PREP(DSI_CMD2_BK0_INVSEL_NLINV_MASK, desc->nlinv),
FIELD_PREP(DSI_CMD2_BK0_INVSEL_RTNI_MASK,
- DIV_ROUND_UP(mode->htotal, 16)));
+ (clamp((u32)mode->htotal, 512U, 1008U) - 512) / 16));
/* Command2, BK1 */
- ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
- 0x77, 0x01, 0x00, 0x00, DSI_CMD2BK1_SEL);
+ st7701_switch_cmd_bkx(st7701, true, 1);
/* Vop = 3.5375V + (VRHA[7:0] * 0.0125V) */
ST7701_DSI(st7701, DSI_CMD2_BK1_VRHS,
@@ -373,33 +372,27 @@ static void dmt028vghmcmi_1a_gip_sequence(struct st7701 *st7701)
0x08, 0x08, 0x08, 0x40,
0x3F, 0x64);
- ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
- 0x77, 0x01, 0x00, 0x00, DSI_CMD2BKX_SEL_NONE);
+ st7701_switch_cmd_bkx(st7701, false, 0);
- ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
- 0x77, 0x01, 0x00, 0x00, DSI_CMD2BK3_SEL);
+ st7701_switch_cmd_bkx(st7701, true, 3);
ST7701_DSI(st7701, 0xE6, 0x7C);
ST7701_DSI(st7701, 0xE8, 0x00, 0x0E);
- ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
- 0x77, 0x01, 0x00, 0x00, DSI_CMD2BKX_SEL_NONE);
+ st7701_switch_cmd_bkx(st7701, false, 0);
ST7701_DSI(st7701, 0x11);
msleep(120);
- ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
- 0x77, 0x01, 0x00, 0x00, DSI_CMD2BK3_SEL);
+ st7701_switch_cmd_bkx(st7701, true, 3);
ST7701_DSI(st7701, 0xE8, 0x00, 0x0C);
msleep(10);
ST7701_DSI(st7701, 0xE8, 0x00, 0x00);
- ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
- 0x77, 0x01, 0x00, 0x00, DSI_CMD2BKX_SEL_NONE);
+ st7701_switch_cmd_bkx(st7701, false, 0);
ST7701_DSI(st7701, 0x11);
msleep(120);
ST7701_DSI(st7701, 0xE8, 0x00, 0x00);
- ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
- 0x77, 0x01, 0x00, 0x00, DSI_CMD2BKX_SEL_NONE);
+ st7701_switch_cmd_bkx(st7701, false, 0);
ST7701_DSI(st7701, 0x3A, 0x70);
}
@@ -426,8 +419,7 @@ static int st7701_prepare(struct drm_panel *panel)
st7701->desc->gip_sequence(st7701);
/* Disable Command2 */
- ST7701_DSI(st7701, DSI_CMD2BKX_SEL,
- 0x77, 0x01, 0x00, 0x00, DSI_CMD2BKX_SEL_NONE);
+ st7701_switch_cmd_bkx(st7701, false, 0);
return 0;
}
@@ -762,7 +754,15 @@ static int st7701_dsi_probe(struct mipi_dsi_device *dsi)
st7701->dsi = dsi;
st7701->desc = desc;
- return mipi_dsi_attach(dsi);
+ ret = mipi_dsi_attach(dsi);
+ if (ret)
+ goto err_attach;
+
+ return 0;
+
+err_attach:
+ drm_panel_remove(&st7701->panel);
+ return ret;
}
static void st7701_dsi_remove(struct mipi_dsi_device *dsi)
diff --git a/drivers/gpu/drm/panel/panel-tpo-tpg110.c b/drivers/gpu/drm/panel/panel-tpo-tpg110.c
index 0b1f5a11a055..845304435e23 100644
--- a/drivers/gpu/drm/panel/panel-tpo-tpg110.c
+++ b/drivers/gpu/drm/panel/panel-tpo-tpg110.c
@@ -463,9 +463,16 @@ static const struct of_device_id tpg110_match[] = {
};
MODULE_DEVICE_TABLE(of, tpg110_match);
+static const struct spi_device_id tpg110_ids[] = {
+ { "tpg110" },
+ { },
+};
+MODULE_DEVICE_TABLE(spi, tpg110_ids);
+
static struct spi_driver tpg110_driver = {
.probe = tpg110_probe,
.remove = tpg110_remove,
+ .id_table = tpg110_ids,
.driver = {
.name = "tpo-tpg110-panel",
.of_match_table = tpg110_match,
diff --git a/drivers/gpu/drm/panel/panel-widechips-ws2401.c b/drivers/gpu/drm/panel/panel-widechips-ws2401.c
index 236f3cb2b594..2591ff8f0d4e 100644
--- a/drivers/gpu/drm/panel/panel-widechips-ws2401.c
+++ b/drivers/gpu/drm/panel/panel-widechips-ws2401.c
@@ -425,9 +425,16 @@ static const struct of_device_id ws2401_match[] = {
};
MODULE_DEVICE_TABLE(of, ws2401_match);
+static const struct spi_device_id ws2401_ids[] = {
+ { "lms380kf01" },
+ { },
+};
+MODULE_DEVICE_TABLE(spi, ws2401_ids);
+
static struct spi_driver ws2401_driver = {
.probe = ws2401_probe,
.remove = ws2401_remove,
+ .id_table = ws2401_ids,
.driver = {
.name = "ws2401-panel",
.of_match_table = ws2401_match,
diff --git a/drivers/gpu/drm/panfrost/panfrost_dump.c b/drivers/gpu/drm/panfrost/panfrost_dump.c
index 6bd0634e2d58..e7942ac449c6 100644
--- a/drivers/gpu/drm/panfrost/panfrost_dump.c
+++ b/drivers/gpu/drm/panfrost/panfrost_dump.c
@@ -209,7 +209,7 @@ void panfrost_core_dump(struct panfrost_job *job)
goto dump_header;
}
- ret = drm_gem_shmem_vmap(&bo->base, &map);
+ ret = drm_gem_vmap_unlocked(&bo->base.base, &map);
if (ret) {
dev_err(pfdev->dev, "Panfrost Dump: couldn't map Buffer Object\n");
iter.hdr->bomap.valid = 0;
@@ -236,7 +236,7 @@ void panfrost_core_dump(struct panfrost_job *job)
vaddr = map.vaddr;
memcpy(iter.data, vaddr, bo->base.base.size);
- drm_gem_shmem_vunmap(&bo->base, &map);
+ drm_gem_vunmap_unlocked(&bo->base.base, &map);
iter.hdr->bomap.valid = 1;
diff --git a/drivers/gpu/drm/panfrost/panfrost_perfcnt.c b/drivers/gpu/drm/panfrost/panfrost_perfcnt.c
index bc0df93f7f21..ba9b6e2b2636 100644
--- a/drivers/gpu/drm/panfrost/panfrost_perfcnt.c
+++ b/drivers/gpu/drm/panfrost/panfrost_perfcnt.c
@@ -106,7 +106,7 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev,
goto err_close_bo;
}
- ret = drm_gem_shmem_vmap(bo, &map);
+ ret = drm_gem_vmap_unlocked(&bo->base, &map);
if (ret)
goto err_put_mapping;
perfcnt->buf = map.vaddr;
@@ -165,7 +165,7 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev,
return 0;
err_vunmap:
- drm_gem_shmem_vunmap(bo, &map);
+ drm_gem_vunmap_unlocked(&bo->base, &map);
err_put_mapping:
panfrost_gem_mapping_put(perfcnt->mapping);
err_close_bo:
@@ -195,7 +195,7 @@ static int panfrost_perfcnt_disable_locked(struct panfrost_device *pfdev,
GPU_PERFCNT_CFG_MODE(GPU_PERFCNT_CFG_MODE_OFF));
perfcnt->user = NULL;
- drm_gem_shmem_vunmap(&perfcnt->mapping->obj->base, &map);
+ drm_gem_vunmap_unlocked(&perfcnt->mapping->obj->base.base, &map);
perfcnt->buf = NULL;
panfrost_gem_close(&perfcnt->mapping->obj->base.base, file_priv);
panfrost_mmu_as_put(pfdev, perfcnt->mapping->mmu);
diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c
index eb25eedb5ee0..00deba0b7271 100644
--- a/drivers/gpu/drm/pl111/pl111_drv.c
+++ b/drivers/gpu/drm/pl111/pl111_drv.c
@@ -48,7 +48,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
index a152a7c6db21..6492a70e3c39 100644
--- a/drivers/gpu/drm/qxl/qxl_display.c
+++ b/drivers/gpu/drm/qxl/qxl_display.c
@@ -1261,8 +1261,6 @@ int qxl_modeset_init(struct qxl_device *qdev)
qdev->ddev.mode_config.max_width = 8192;
qdev->ddev.mode_config.max_height = 8192;
- qdev->ddev.mode_config.fb_base = qdev->vram_base;
-
drm_mode_create_suggested_offset_properties(&qdev->ddev);
qxl_mode_create_hotplug_mode_update_property(qdev);
diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c
index 3044ca948ce2..a3b83f89e061 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.c
+++ b/drivers/gpu/drm/qxl/qxl_drv.c
@@ -37,6 +37,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_file.h>
#include <drm/drm_gem_ttm_helper.h>
#include <drm/drm_module.h>
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
index 432758ad39a3..76f060810f63 100644
--- a/drivers/gpu/drm/qxl/qxl_drv.h
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
@@ -38,7 +38,6 @@
#include <drm/drm_crtc.h>
#include <drm/drm_encoder.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_gem_ttm_helper.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_gem.h>
diff --git a/drivers/gpu/drm/qxl/qxl_object.c b/drivers/gpu/drm/qxl/qxl_object.c
index 695d9308d1f0..06a58dad5f5c 100644
--- a/drivers/gpu/drm/qxl/qxl_object.c
+++ b/drivers/gpu/drm/qxl/qxl_object.c
@@ -168,9 +168,16 @@ int qxl_bo_vmap_locked(struct qxl_bo *bo, struct iosys_map *map)
bo->map_count++;
goto out;
}
- r = ttm_bo_vmap(&bo->tbo, &bo->map);
+
+ r = __qxl_bo_pin(bo);
if (r)
return r;
+
+ r = ttm_bo_vmap(&bo->tbo, &bo->map);
+ if (r) {
+ __qxl_bo_unpin(bo);
+ return r;
+ }
bo->map_count = 1;
/* TODO: Remove kptr in favor of map everywhere. */
@@ -192,12 +199,6 @@ int qxl_bo_vmap(struct qxl_bo *bo, struct iosys_map *map)
if (r)
return r;
- r = __qxl_bo_pin(bo);
- if (r) {
- qxl_bo_unreserve(bo);
- return r;
- }
-
r = qxl_bo_vmap_locked(bo, map);
qxl_bo_unreserve(bo);
return r;
@@ -247,6 +248,7 @@ void qxl_bo_vunmap_locked(struct qxl_bo *bo)
return;
bo->kptr = NULL;
ttm_bo_vunmap(&bo->tbo, &bo->map);
+ __qxl_bo_unpin(bo);
}
int qxl_bo_vunmap(struct qxl_bo *bo)
@@ -258,7 +260,6 @@ int qxl_bo_vunmap(struct qxl_bo *bo)
return r;
qxl_bo_vunmap_locked(bo);
- __qxl_bo_unpin(bo);
qxl_bo_unreserve(bo);
return 0;
}
diff --git a/drivers/gpu/drm/qxl/qxl_prime.c b/drivers/gpu/drm/qxl/qxl_prime.c
index 142d01415acb..9169c26357d3 100644
--- a/drivers/gpu/drm/qxl/qxl_prime.c
+++ b/drivers/gpu/drm/qxl/qxl_prime.c
@@ -59,7 +59,7 @@ int qxl_gem_prime_vmap(struct drm_gem_object *obj, struct iosys_map *map)
struct qxl_bo *bo = gem_to_qxl_bo(obj);
int ret;
- ret = qxl_bo_vmap(bo, map);
+ ret = qxl_bo_vmap_locked(bo, map);
if (ret < 0)
return ret;
@@ -71,5 +71,5 @@ void qxl_gem_prime_vunmap(struct drm_gem_object *obj,
{
struct qxl_bo *bo = gem_to_qxl_bo(obj);
- qxl_bo_vunmap(bo);
+ qxl_bo_vunmap_locked(bo);
}
diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig
index 52819e7f1fca..97a277f9a25e 100644
--- a/drivers/gpu/drm/radeon/Kconfig
+++ b/drivers/gpu/drm/radeon/Kconfig
@@ -1,4 +1,34 @@
# SPDX-License-Identifier: MIT
+
+config DRM_RADEON
+ tristate "ATI Radeon"
+ depends on DRM && PCI && MMU
+ depends on AGP || !AGP
+ select FW_LOADER
+ select DRM_DISPLAY_DP_HELPER
+ select DRM_DISPLAY_HELPER
+ select DRM_KMS_HELPER
+ select DRM_TTM
+ select DRM_TTM_HELPER
+ select SND_HDA_COMPONENT if SND_HDA_CORE
+ select POWER_SUPPLY
+ select HWMON
+ select BACKLIGHT_CLASS_DEVICE
+ select INTERVAL_TREE
+ # radeon depends on ACPI_VIDEO when ACPI is enabled, for select to work
+ # ACPI_VIDEO's dependencies must also be selected.
+ select INPUT if ACPI
+ select ACPI_VIDEO if ACPI
+ # On x86 ACPI_VIDEO also needs ACPI_WMI
+ select X86_PLATFORM_DEVICES if ACPI && X86
+ select ACPI_WMI if ACPI && X86
+ help
+ Choose this option if you have an ATI Radeon graphics card. There
+ are both PCI and AGP versions. You don't need to choose this to
+ run the Radeon in plain VGA mode.
+
+ If M is selected, the module will be called radeon.
+
config DRM_RADEON_USERPTR
bool "Always enable userptr support"
depends on DRM_RADEON
diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h
index da35a970fcc0..235e59b547a1 100644
--- a/drivers/gpu/drm/radeon/atombios.h
+++ b/drivers/gpu/drm/radeon/atombios.h
@@ -3615,7 +3615,7 @@ typedef struct _ATOM_FAKE_EDID_PATCH_RECORD
{
UCHAR ucRecordType;
UCHAR ucFakeEDIDLength;
- UCHAR ucFakeEDIDString[1]; // This actually has ucFakeEdidLength elements.
+ UCHAR ucFakeEDIDString[]; // This actually has ucFakeEdidLength elements.
} ATOM_FAKE_EDID_PATCH_RECORD;
typedef struct _ATOM_PANEL_RESOLUTION_PATCH_RECORD
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 166c18d62f6d..2e7161acd443 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -79,6 +79,7 @@
#include <drm/ttm/ttm_execbuf_util.h>
#include <drm/drm_gem.h>
+#include <drm/drm_audio_component.h>
#include "radeon_family.h"
#include "radeon_mode.h"
@@ -1796,6 +1797,9 @@ struct r600_audio {
struct radeon_audio_funcs *hdmi_funcs;
struct radeon_audio_funcs *dp_funcs;
struct radeon_audio_basic_funcs *funcs;
+ struct drm_audio_component *component;
+ bool component_registered;
+ struct mutex component_mutex;
};
/*
@@ -2994,6 +2998,10 @@ void radeon_irq_kms_set_irq_n_enabled(struct radeon_device *rdev,
bool enable, const char *name,
unsigned n);
+/* Audio component binding */
+void radeon_audio_component_init(struct radeon_device *rdev);
+void radeon_audio_component_fini(struct radeon_device *rdev);
+
#include "radeon_object.h"
#endif
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 204127bad89c..4ad5a328d920 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -1727,8 +1727,11 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
}
}
record += fake_edid_record->ucFakeEDIDLength ?
- fake_edid_record->ucFakeEDIDLength + 2 :
- sizeof(ATOM_FAKE_EDID_PATCH_RECORD);
+ struct_size(fake_edid_record,
+ ucFakeEDIDString,
+ fake_edid_record->ucFakeEDIDLength) :
+ /* empty fake edid record must be 3 bytes long */
+ sizeof(ATOM_FAKE_EDID_PATCH_RECORD) + 1;
break;
case LCD_PANEL_RESOLUTION_RECORD_TYPE:
panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record;
diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c
index 7c5e80d03fc9..d6ccaf24ee0c 100644
--- a/drivers/gpu/drm/radeon/radeon_audio.c
+++ b/drivers/gpu/drm/radeon/radeon_audio.c
@@ -23,6 +23,7 @@
*/
#include <linux/gcd.h>
+#include <linux/component.h>
#include <drm/drm_crtc.h>
#include "dce6_afmt.h"
@@ -180,6 +181,8 @@ static struct radeon_audio_funcs dce6_dp_funcs = {
.dpms = evergreen_dp_enable,
};
+static void radeon_audio_component_notify(struct radeon_device *rdev, int port);
+
static void radeon_audio_enable(struct radeon_device *rdev,
struct r600_audio_pin *pin, u8 enable_mask)
{
@@ -207,6 +210,8 @@ static void radeon_audio_enable(struct radeon_device *rdev,
if (rdev->audio.funcs->enable)
rdev->audio.funcs->enable(rdev, pin, enable_mask);
+
+ radeon_audio_component_notify(rdev, pin->id);
}
static void radeon_audio_interface_init(struct radeon_device *rdev)
@@ -721,3 +726,115 @@ unsigned int radeon_audio_decode_dfs_div(unsigned int div)
else
return 0;
}
+
+/*
+ * Audio component support
+ */
+static void radeon_audio_component_notify(struct radeon_device *rdev, int port)
+{
+ struct drm_audio_component *acomp;
+
+ mutex_lock(&rdev->audio.component_mutex);
+ acomp = rdev->audio.component;
+ if (acomp && acomp->audio_ops && acomp->audio_ops->pin_eld_notify)
+ acomp->audio_ops->pin_eld_notify(acomp->audio_ops->audio_ptr,
+ port, -1);
+ mutex_unlock(&rdev->audio.component_mutex);
+}
+
+static int radeon_audio_component_get_eld(struct device *kdev, int port,
+ int pipe, bool *enabled,
+ unsigned char *buf, int max_bytes)
+{
+ struct drm_device *dev = dev_get_drvdata(kdev);
+ struct radeon_device *rdev = dev->dev_private;
+ struct drm_encoder *encoder;
+ struct radeon_encoder *radeon_encoder;
+ struct radeon_encoder_atom_dig *dig;
+ struct drm_connector *connector;
+ int ret = 0;
+
+ *enabled = false;
+ if (!rdev->audio.enabled || !rdev->mode_info.mode_config_initialized)
+ return 0;
+
+ list_for_each_entry(encoder, &rdev->ddev->mode_config.encoder_list, head) {
+ if (!radeon_encoder_is_digital(encoder))
+ continue;
+ radeon_encoder = to_radeon_encoder(encoder);
+ dig = radeon_encoder->enc_priv;
+ if (!dig->pin || dig->pin->id != port)
+ continue;
+ connector = radeon_get_connector_for_encoder(encoder);
+ if (!connector)
+ continue;
+ *enabled = true;
+ ret = drm_eld_size(connector->eld);
+ memcpy(buf, connector->eld, min(max_bytes, ret));
+ break;
+ }
+
+ return ret;
+}
+
+static const struct drm_audio_component_ops radeon_audio_component_ops = {
+ .get_eld = radeon_audio_component_get_eld,
+};
+
+static int radeon_audio_component_bind(struct device *kdev,
+ struct device *hda_kdev, void *data)
+{
+ struct drm_device *dev = dev_get_drvdata(kdev);
+ struct radeon_device *rdev = dev->dev_private;
+ struct drm_audio_component *acomp = data;
+
+ if (WARN_ON(!device_link_add(hda_kdev, kdev, DL_FLAG_STATELESS)))
+ return -ENOMEM;
+
+ mutex_lock(&rdev->audio.component_mutex);
+ acomp->ops = &radeon_audio_component_ops;
+ acomp->dev = kdev;
+ rdev->audio.component = acomp;
+ mutex_unlock(&rdev->audio.component_mutex);
+
+ return 0;
+}
+
+static void radeon_audio_component_unbind(struct device *kdev,
+ struct device *hda_kdev, void *data)
+{
+ struct drm_device *dev = dev_get_drvdata(kdev);
+ struct radeon_device *rdev = dev->dev_private;
+ struct drm_audio_component *acomp = data;
+
+ device_link_remove(hda_kdev, kdev);
+
+ mutex_lock(&rdev->audio.component_mutex);
+ rdev->audio.component = NULL;
+ acomp->ops = NULL;
+ acomp->dev = NULL;
+ mutex_unlock(&rdev->audio.component_mutex);
+}
+
+static const struct component_ops radeon_audio_component_bind_ops = {
+ .bind = radeon_audio_component_bind,
+ .unbind = radeon_audio_component_unbind,
+};
+
+void radeon_audio_component_init(struct radeon_device *rdev)
+{
+ if (rdev->audio.component_registered ||
+ !radeon_audio || !radeon_audio_chipset_supported(rdev))
+ return;
+
+ if (!component_add(rdev->dev, &radeon_audio_component_bind_ops))
+ rdev->audio.component_registered = true;
+}
+
+void radeon_audio_component_fini(struct radeon_device *rdev)
+{
+ if (rdev->audio.component_registered) {
+ component_del(rdev->dev, &radeon_audio_component_bind_ops);
+ rdev->audio.component_registered = false;
+ }
+}
diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c
index 33121655d50b..63bdc9f6fc24 100644
--- a/drivers/gpu/drm/radeon/radeon_bios.c
+++ b/drivers/gpu/drm/radeon/radeon_bios.c
@@ -227,6 +227,7 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev)
if (!found)
return false;
+ pci_dev_put(pdev);
rdev->bios = kmalloc(size, GFP_KERNEL);
if (!rdev->bios) {
@@ -612,13 +613,14 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
acpi_size tbl_size;
UEFI_ACPI_VFCT *vfct;
unsigned offset;
+ bool r = false;
if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
return false;
tbl_size = hdr->length;
if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n");
- return false;
+ goto out;
}
vfct = (UEFI_ACPI_VFCT *)hdr;
@@ -631,13 +633,13 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
offset += sizeof(VFCT_IMAGE_HEADER);
if (offset > tbl_size) {
DRM_ERROR("ACPI VFCT image header truncated\n");
- return false;
+ goto out;
}
offset += vhdr->ImageLength;
if (offset > tbl_size) {
DRM_ERROR("ACPI VFCT image truncated\n");
- return false;
+ goto out;
}
if (vhdr->ImageLength &&
@@ -649,15 +651,18 @@ static bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
rdev->bios = kmemdup(&vbios->VbiosContent,
vhdr->ImageLength,
GFP_KERNEL);
+ if (rdev->bios)
+ r = true;
- if (!rdev->bios)
- return false;
- return true;
+ goto out;
}
}
DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n");
- return false;
+
+out:
+ acpi_put_table(hdr);
+ return r;
}
#else
static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev)
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index 446f7bae54c4..46a27ebf4588 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -400,8 +400,11 @@ static int cmp_size_smaller_first(void *priv, const struct list_head *a,
struct radeon_bo_list *lb = list_entry(b, struct radeon_bo_list, tv.head);
/* Sort A before B if A is smaller. */
- return (int)la->robj->tbo.resource->num_pages -
- (int)lb->robj->tbo.resource->num_pages;
+ if (la->robj->tbo.base.size > lb->robj->tbo.base.size)
+ return 1;
+ if (la->robj->tbo.base.size < lb->robj->tbo.base.size)
+ return -1;
+ return 0;
}
/**
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index a556b6be1137..6344454a7721 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -1207,7 +1207,7 @@ static void radeon_check_arguments(struct radeon_device *rdev)
* @pdev: pci dev pointer
* @state: vga_switcheroo state
*
- * Callback for the switcheroo driver. Suspends or resumes the
+ * Callback for the switcheroo driver. Suspends or resumes
* the asics before or after it is powered up using ACPI methods.
*/
static void radeon_switcheroo_set_state(struct pci_dev *pdev, enum vga_switcheroo_state state)
@@ -1312,6 +1312,7 @@ int radeon_device_init(struct radeon_device *rdev,
mutex_init(&rdev->pm.mutex);
mutex_init(&rdev->gpu_clock_mutex);
mutex_init(&rdev->srbm_mutex);
+ mutex_init(&rdev->audio.component_mutex);
init_rwsem(&rdev->pm.mclk_lock);
init_rwsem(&rdev->exclusive_lock);
init_waitqueue_head(&rdev->irq.vblank_queue);
@@ -1451,6 +1452,8 @@ int radeon_device_init(struct radeon_device *rdev,
goto failed;
}
+ radeon_audio_component_init(rdev);
+
r = radeon_ib_ring_tests(rdev);
if (r)
DRM_ERROR("ib ring test failed (%d).\n", r);
@@ -1513,6 +1516,7 @@ void radeon_device_fini(struct radeon_device *rdev)
rdev->shutdown = true;
/* evict vram memory */
radeon_bo_evict_vram(rdev);
+ radeon_audio_component_fini(rdev);
radeon_fini(rdev);
if (!pci_is_thunderbolt_attached(rdev->pdev))
vga_switcheroo_unregister_client(rdev->pdev);
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index ca5598ae8bfc..9bed1a6cb163 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -1604,8 +1604,6 @@ int radeon_modeset_init(struct radeon_device *rdev)
rdev->ddev->mode_config.fb_modifiers_not_supported = true;
- rdev->ddev->mode_config.fb_base = rdev->mc.aper_base;
-
ret = radeon_modeset_create_props(rdev);
if (ret) {
return ret;
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index 6ccea51d4072..c1710ed1cab8 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -80,6 +80,8 @@ static const struct fb_ops radeonfb_ops = {
DRM_FB_HELPER_DEFAULT_OPS,
.fb_open = radeonfb_open,
.fb_release = radeonfb_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,
@@ -243,7 +245,7 @@ static int radeonfb_create(struct drm_fb_helper *helper,
rbo = gem_to_radeon_bo(gobj);
/* okay we have an object now allocate the framebuffer */
- info = drm_fb_helper_alloc_fbi(helper);
+ info = drm_fb_helper_alloc_info(helper);
if (IS_ERR(info)) {
ret = PTR_ERR(info);
goto out;
@@ -276,7 +278,7 @@ static int radeonfb_create(struct drm_fb_helper *helper,
drm_fb_helper_fill_info(info, &rfbdev->helper, sizes);
/* setup aperture base/size for vesafb takeover */
- info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base;
+ info->apertures->ranges[0].base = rdev->mc.aper_base;
info->apertures->ranges[0].size = rdev->mc.aper_size;
/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
@@ -309,7 +311,7 @@ static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfb
{
struct drm_framebuffer *fb = &rfbdev->fb;
- drm_fb_helper_unregister_fbi(&rfbdev->helper);
+ drm_fb_helper_unregister_info(&rfbdev->helper);
if (fb->obj[0]) {
radeonfb_destroy_pinned_object(fb->obj[0]);
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 00c33b24d5d3..10c0fbd9d2b4 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -232,7 +232,7 @@ int radeon_bo_kmap(struct radeon_bo *bo, void **ptr)
}
return 0;
}
- r = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.resource->num_pages, &bo->kmap);
+ r = ttm_bo_kmap(&bo->tbo, 0, PFN_UP(bo->tbo.base.size), &bo->kmap);
if (r) {
return r;
}
@@ -737,7 +737,7 @@ vm_fault_t radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
if (bo->resource->mem_type != TTM_PL_VRAM)
return 0;
- size = bo->resource->num_pages << PAGE_SHIFT;
+ size = bo->resource->size;
offset = bo->resource->start << PAGE_SHIFT;
if ((offset + size) <= rdev->mc.visible_vram_size)
return 0;
diff --git a/drivers/gpu/drm/radeon/radeon_trace.h b/drivers/gpu/drm/radeon/radeon_trace.h
index c9fed5f2b870..22676617e1a5 100644
--- a/drivers/gpu/drm/radeon/radeon_trace.h
+++ b/drivers/gpu/drm/radeon/radeon_trace.h
@@ -22,7 +22,7 @@ TRACE_EVENT(radeon_bo_create,
TP_fast_assign(
__entry->bo = bo;
- __entry->pages = bo->tbo.resource->num_pages;
+ __entry->pages = PFN_UP(bo->tbo.resource->size);
),
TP_printk("bo=%p, pages=%u", __entry->bo, __entry->pages)
);
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index d33fec488713..30402b5ce4c5 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -181,7 +181,7 @@ static int radeon_move_blit(struct ttm_buffer_object *bo,
BUILD_BUG_ON((PAGE_SIZE % RADEON_GPU_PAGE_SIZE) != 0);
- num_pages = new_mem->num_pages * (PAGE_SIZE / RADEON_GPU_PAGE_SIZE);
+ num_pages = PFN_UP(new_mem->size) * (PAGE_SIZE / RADEON_GPU_PAGE_SIZE);
fence = radeon_copy(rdev, old_start, new_start, num_pages, bo->base.resv);
if (IS_ERR(fence))
return PTR_ERR(fence);
@@ -268,7 +268,7 @@ out:
static int radeon_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource *mem)
{
struct radeon_device *rdev = radeon_get_rdev(bdev);
- size_t bus_size = (size_t)mem->num_pages << PAGE_SHIFT;
+ size_t bus_size = (size_t)mem->size;
switch (mem->mem_type) {
case TTM_PL_SYSTEM:
@@ -869,11 +869,11 @@ static ssize_t radeon_ttm_gtt_read(struct file *f, char __user *buf,
page = rdev->gart.pages[p];
if (page) {
- ptr = kmap(page);
+ ptr = kmap_local_page(page);
ptr += off;
r = copy_to_user(buf, ptr, cur_size);
- kunmap(rdev->gart.pages[p]);
+ kunmap_local(ptr);
} else
r = clear_user(buf, cur_size);
diff --git a/drivers/gpu/drm/rcar-du/Kconfig b/drivers/gpu/drm/rcar-du/Kconfig
index fd2c2eaee26b..b2bddbeca878 100644
--- a/drivers/gpu/drm/rcar-du/Kconfig
+++ b/drivers/gpu/drm/rcar-du/Kconfig
@@ -41,8 +41,6 @@ config DRM_RCAR_LVDS
depends on DRM_RCAR_USE_LVDS
select DRM_KMS_HELPER
select DRM_PANEL
- select OF_FLATTREE
- select OF_OVERLAY
config DRM_RCAR_USE_MIPI_DSI
bool "R-Car DU MIPI DSI Encoder Support"
@@ -56,6 +54,14 @@ config DRM_RCAR_MIPI_DSI
depends on DRM_RCAR_USE_MIPI_DSI
select DRM_MIPI_DSI
+config DRM_RZG2L_MIPI_DSI
+ tristate "RZ/G2L MIPI DSI Encoder Support"
+ depends on DRM && DRM_BRIDGE && OF
+ depends on ARCH_RENESAS || COMPILE_TEST
+ select DRM_MIPI_DSI
+ help
+ Enable support for the RZ/G2L Display Unit embedded MIPI DSI encoders.
+
config DRM_RCAR_VSP
bool "R-Car DU VSP Compositor Support" if ARM
default y if ARM64
diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
index 6f132325c8b7..b8f2c82651d9 100644
--- a/drivers/gpu/drm/rcar-du/Makefile
+++ b/drivers/gpu/drm/rcar-du/Makefile
@@ -14,3 +14,5 @@ obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o
obj-$(CONFIG_DRM_RCAR_DW_HDMI) += rcar_dw_hdmi.o
obj-$(CONFIG_DRM_RCAR_LVDS) += rcar_lvds.o
obj-$(CONFIG_DRM_RCAR_MIPI_DSI) += rcar_mipi_dsi.o
+
+obj-$(CONFIG_DRM_RZG2L_MIPI_DSI) += rzg2l_mipi_dsi.o
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index a2776f1d6f2c..d003e8d9e7a2 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -20,7 +20,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
#include <drm/drm_probe_helper.h>
diff --git a/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c b/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c
new file mode 100644
index 000000000000..aa95b85a2964
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi.c
@@ -0,0 +1,816 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RZ/G2L MIPI DSI Encoder Driver
+ *
+ * Copyright (C) 2022 Renesas Electronics Corporation
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/iopoll.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 <linux/reset.h>
+#include <linux/slab.h>
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_mipi_dsi.h>
+#include <drm/drm_of.h>
+#include <drm/drm_panel.h>
+#include <drm/drm_probe_helper.h>
+
+#include "rzg2l_mipi_dsi_regs.h"
+
+struct rzg2l_mipi_dsi {
+ struct device *dev;
+ void __iomem *mmio;
+
+ struct reset_control *rstc;
+ struct reset_control *arstc;
+ struct reset_control *prstc;
+
+ struct mipi_dsi_host host;
+ struct drm_bridge bridge;
+ struct drm_bridge *next_bridge;
+
+ struct clk *vclk;
+
+ enum mipi_dsi_pixel_format format;
+ unsigned int num_data_lanes;
+ unsigned int lanes;
+ unsigned long mode_flags;
+};
+
+static inline struct rzg2l_mipi_dsi *
+bridge_to_rzg2l_mipi_dsi(struct drm_bridge *bridge)
+{
+ return container_of(bridge, struct rzg2l_mipi_dsi, bridge);
+}
+
+static inline struct rzg2l_mipi_dsi *
+host_to_rzg2l_mipi_dsi(struct mipi_dsi_host *host)
+{
+ return container_of(host, struct rzg2l_mipi_dsi, host);
+}
+
+struct rzg2l_mipi_dsi_timings {
+ unsigned long hsfreq_max;
+ u32 t_init;
+ u32 tclk_prepare;
+ u32 ths_prepare;
+ u32 tclk_zero;
+ u32 tclk_pre;
+ u32 tclk_post;
+ u32 tclk_trail;
+ u32 ths_zero;
+ u32 ths_trail;
+ u32 ths_exit;
+ u32 tlpx;
+};
+
+static const struct rzg2l_mipi_dsi_timings rzg2l_mipi_dsi_global_timings[] = {
+ {
+ .hsfreq_max = 80000,
+ .t_init = 79801,
+ .tclk_prepare = 8,
+ .ths_prepare = 13,
+ .tclk_zero = 33,
+ .tclk_pre = 24,
+ .tclk_post = 94,
+ .tclk_trail = 10,
+ .ths_zero = 23,
+ .ths_trail = 17,
+ .ths_exit = 13,
+ .tlpx = 6,
+ },
+ {
+ .hsfreq_max = 125000,
+ .t_init = 79801,
+ .tclk_prepare = 8,
+ .ths_prepare = 12,
+ .tclk_zero = 33,
+ .tclk_pre = 15,
+ .tclk_post = 94,
+ .tclk_trail = 10,
+ .ths_zero = 23,
+ .ths_trail = 17,
+ .ths_exit = 13,
+ .tlpx = 6,
+ },
+ {
+ .hsfreq_max = 250000,
+ .t_init = 79801,
+ .tclk_prepare = 8,
+ .ths_prepare = 12,
+ .tclk_zero = 33,
+ .tclk_pre = 13,
+ .tclk_post = 94,
+ .tclk_trail = 10,
+ .ths_zero = 23,
+ .ths_trail = 16,
+ .ths_exit = 13,
+ .tlpx = 6,
+ },
+ {
+ .hsfreq_max = 360000,
+ .t_init = 79801,
+ .tclk_prepare = 8,
+ .ths_prepare = 10,
+ .tclk_zero = 33,
+ .tclk_pre = 4,
+ .tclk_post = 35,
+ .tclk_trail = 7,
+ .ths_zero = 16,
+ .ths_trail = 9,
+ .ths_exit = 13,
+ .tlpx = 6,
+ },
+ {
+ .hsfreq_max = 720000,
+ .t_init = 79801,
+ .tclk_prepare = 8,
+ .ths_prepare = 9,
+ .tclk_zero = 33,
+ .tclk_pre = 4,
+ .tclk_post = 35,
+ .tclk_trail = 7,
+ .ths_zero = 16,
+ .ths_trail = 9,
+ .ths_exit = 13,
+ .tlpx = 6,
+ },
+ {
+ .hsfreq_max = 1500000,
+ .t_init = 79801,
+ .tclk_prepare = 8,
+ .ths_prepare = 9,
+ .tclk_zero = 33,
+ .tclk_pre = 4,
+ .tclk_post = 35,
+ .tclk_trail = 7,
+ .ths_zero = 16,
+ .ths_trail = 9,
+ .ths_exit = 13,
+ .tlpx = 6,
+ },
+};
+
+static void rzg2l_mipi_dsi_phy_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data)
+{
+ iowrite32(data, dsi->mmio + reg);
+}
+
+static void rzg2l_mipi_dsi_link_write(struct rzg2l_mipi_dsi *dsi, u32 reg, u32 data)
+{
+ iowrite32(data, dsi->mmio + LINK_REG_OFFSET + reg);
+}
+
+static u32 rzg2l_mipi_dsi_phy_read(struct rzg2l_mipi_dsi *dsi, u32 reg)
+{
+ return ioread32(dsi->mmio + reg);
+}
+
+static u32 rzg2l_mipi_dsi_link_read(struct rzg2l_mipi_dsi *dsi, u32 reg)
+{
+ return ioread32(dsi->mmio + LINK_REG_OFFSET + reg);
+}
+
+/* -----------------------------------------------------------------------------
+ * Hardware Setup
+ */
+
+static int rzg2l_mipi_dsi_dphy_init(struct rzg2l_mipi_dsi *dsi,
+ unsigned long hsfreq)
+{
+ const struct rzg2l_mipi_dsi_timings *dphy_timings;
+ unsigned int i;
+ u32 dphyctrl0;
+ u32 dphytim0;
+ u32 dphytim1;
+ u32 dphytim2;
+ u32 dphytim3;
+ int ret;
+
+ /* All DSI global operation timings are set with recommended setting */
+ for (i = 0; i < ARRAY_SIZE(rzg2l_mipi_dsi_global_timings); ++i) {
+ dphy_timings = &rzg2l_mipi_dsi_global_timings[i];
+ if (hsfreq <= dphy_timings->hsfreq_max)
+ break;
+ }
+
+ /* Initializing DPHY before accessing LINK */
+ dphyctrl0 = DSIDPHYCTRL0_CAL_EN_HSRX_OFS | DSIDPHYCTRL0_CMN_MASTER_EN |
+ DSIDPHYCTRL0_RE_VDD_DETVCCQLV18 | DSIDPHYCTRL0_EN_BGR;
+
+ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);
+ usleep_range(20, 30);
+
+ dphyctrl0 |= DSIDPHYCTRL0_EN_LDO1200;
+ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);
+ usleep_range(10, 20);
+
+ dphytim0 = DSIDPHYTIM0_TCLK_MISS(0) |
+ DSIDPHYTIM0_T_INIT(dphy_timings->t_init);
+ dphytim1 = DSIDPHYTIM1_THS_PREPARE(dphy_timings->ths_prepare) |
+ DSIDPHYTIM1_TCLK_PREPARE(dphy_timings->tclk_prepare) |
+ DSIDPHYTIM1_THS_SETTLE(0) |
+ DSIDPHYTIM1_TCLK_SETTLE(0);
+ dphytim2 = DSIDPHYTIM2_TCLK_TRAIL(dphy_timings->tclk_trail) |
+ DSIDPHYTIM2_TCLK_POST(dphy_timings->tclk_post) |
+ DSIDPHYTIM2_TCLK_PRE(dphy_timings->tclk_pre) |
+ DSIDPHYTIM2_TCLK_ZERO(dphy_timings->tclk_zero);
+ dphytim3 = DSIDPHYTIM3_TLPX(dphy_timings->tlpx) |
+ DSIDPHYTIM3_THS_EXIT(dphy_timings->ths_exit) |
+ DSIDPHYTIM3_THS_TRAIL(dphy_timings->ths_trail) |
+ DSIDPHYTIM3_THS_ZERO(dphy_timings->ths_zero);
+
+ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM0, dphytim0);
+ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM1, dphytim1);
+ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM2, dphytim2);
+ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYTIM3, dphytim3);
+
+ ret = reset_control_deassert(dsi->rstc);
+ if (ret < 0)
+ return ret;
+
+ udelay(1);
+
+ return 0;
+}
+
+static void rzg2l_mipi_dsi_dphy_exit(struct rzg2l_mipi_dsi *dsi)
+{
+ u32 dphyctrl0;
+
+ dphyctrl0 = rzg2l_mipi_dsi_phy_read(dsi, DSIDPHYCTRL0);
+
+ dphyctrl0 &= ~(DSIDPHYCTRL0_EN_LDO1200 | DSIDPHYCTRL0_EN_BGR);
+ rzg2l_mipi_dsi_phy_write(dsi, DSIDPHYCTRL0, dphyctrl0);
+
+ reset_control_assert(dsi->rstc);
+}
+
+static int rzg2l_mipi_dsi_startup(struct rzg2l_mipi_dsi *dsi,
+ const struct drm_display_mode *mode)
+{
+ unsigned long hsfreq;
+ unsigned int bpp;
+ u32 txsetr;
+ u32 clstptsetr;
+ u32 lptrnstsetr;
+ u32 clkkpt;
+ u32 clkbfht;
+ u32 clkstpt;
+ u32 golpbkt;
+ int ret;
+
+ /*
+ * Relationship between hsclk and vclk must follow
+ * vclk * bpp = hsclk * 8 * lanes
+ * where vclk: video clock (Hz)
+ * bpp: video pixel bit depth
+ * hsclk: DSI HS Byte clock frequency (Hz)
+ * lanes: number of data lanes
+ *
+ * hsclk(bit) = hsclk(byte) * 8
+ */
+ bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
+ hsfreq = (mode->clock * bpp * 8) / (8 * dsi->lanes);
+
+ ret = pm_runtime_resume_and_get(dsi->dev);
+ if (ret < 0)
+ return ret;
+
+ clk_set_rate(dsi->vclk, mode->clock * 1000);
+
+ ret = rzg2l_mipi_dsi_dphy_init(dsi, hsfreq);
+ if (ret < 0)
+ goto err_phy;
+
+ /* Enable Data lanes and Clock lanes */
+ txsetr = TXSETR_DLEN | TXSETR_NUMLANEUSE(dsi->lanes - 1) | TXSETR_CLEN;
+ rzg2l_mipi_dsi_link_write(dsi, TXSETR, txsetr);
+
+ /*
+ * Global timings characteristic depends on high speed Clock Frequency
+ * Currently MIPI DSI-IF just supports maximum FHD@60 with:
+ * - videoclock = 148.5 (MHz)
+ * - bpp: maximum 24bpp
+ * - data lanes: maximum 4 lanes
+ * Therefore maximum hsclk will be 891 Mbps.
+ */
+ if (hsfreq > 445500) {
+ clkkpt = 12;
+ clkbfht = 15;
+ clkstpt = 48;
+ golpbkt = 75;
+ } else if (hsfreq > 250000) {
+ clkkpt = 7;
+ clkbfht = 8;
+ clkstpt = 27;
+ golpbkt = 40;
+ } else {
+ clkkpt = 8;
+ clkbfht = 6;
+ clkstpt = 24;
+ golpbkt = 29;
+ }
+
+ clstptsetr = CLSTPTSETR_CLKKPT(clkkpt) | CLSTPTSETR_CLKBFHT(clkbfht) |
+ CLSTPTSETR_CLKSTPT(clkstpt);
+ rzg2l_mipi_dsi_link_write(dsi, CLSTPTSETR, clstptsetr);
+
+ lptrnstsetr = LPTRNSTSETR_GOLPBKT(golpbkt);
+ rzg2l_mipi_dsi_link_write(dsi, LPTRNSTSETR, lptrnstsetr);
+
+ return 0;
+
+err_phy:
+ rzg2l_mipi_dsi_dphy_exit(dsi);
+ pm_runtime_put(dsi->dev);
+
+ return ret;
+}
+
+static void rzg2l_mipi_dsi_stop(struct rzg2l_mipi_dsi *dsi)
+{
+ rzg2l_mipi_dsi_dphy_exit(dsi);
+ pm_runtime_put(dsi->dev);
+}
+
+static void rzg2l_mipi_dsi_set_display_timing(struct rzg2l_mipi_dsi *dsi,
+ const struct drm_display_mode *mode)
+{
+ u32 vich1ppsetr;
+ u32 vich1vssetr;
+ u32 vich1vpsetr;
+ u32 vich1hssetr;
+ u32 vich1hpsetr;
+ int dsi_format;
+ u32 delay[2];
+ u8 index;
+
+ /* Configuration for Pixel Packet */
+ dsi_format = mipi_dsi_pixel_format_to_bpp(dsi->format);
+ switch (dsi_format) {
+ case 24:
+ vich1ppsetr = VICH1PPSETR_DT_RGB24;
+ break;
+ case 18:
+ vich1ppsetr = VICH1PPSETR_DT_RGB18;
+ break;
+ }
+
+ if ((dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) &&
+ !(dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST))
+ vich1ppsetr |= VICH1PPSETR_TXESYNC_PULSE;
+
+ rzg2l_mipi_dsi_link_write(dsi, VICH1PPSETR, vich1ppsetr);
+
+ /* Configuration for Video Parameters */
+ vich1vssetr = VICH1VSSETR_VACTIVE(mode->vdisplay) |
+ VICH1VSSETR_VSA(mode->vsync_end - mode->vsync_start);
+ vich1vssetr |= (mode->flags & DRM_MODE_FLAG_PVSYNC) ?
+ VICH1VSSETR_VSPOL_HIGH : VICH1VSSETR_VSPOL_LOW;
+
+ vich1vpsetr = VICH1VPSETR_VFP(mode->vsync_start - mode->vdisplay) |
+ VICH1VPSETR_VBP(mode->vtotal - mode->vsync_end);
+
+ vich1hssetr = VICH1HSSETR_HACTIVE(mode->hdisplay) |
+ VICH1HSSETR_HSA(mode->hsync_end - mode->hsync_start);
+ vich1hssetr |= (mode->flags & DRM_MODE_FLAG_PHSYNC) ?
+ VICH1HSSETR_HSPOL_HIGH : VICH1HSSETR_HSPOL_LOW;
+
+ vich1hpsetr = VICH1HPSETR_HFP(mode->hsync_start - mode->hdisplay) |
+ VICH1HPSETR_HBP(mode->htotal - mode->hsync_end);
+
+ rzg2l_mipi_dsi_link_write(dsi, VICH1VSSETR, vich1vssetr);
+ rzg2l_mipi_dsi_link_write(dsi, VICH1VPSETR, vich1vpsetr);
+ rzg2l_mipi_dsi_link_write(dsi, VICH1HSSETR, vich1hssetr);
+ rzg2l_mipi_dsi_link_write(dsi, VICH1HPSETR, vich1hpsetr);
+
+ /*
+ * Configuration for Delay Value
+ * Delay value based on 2 ranges of video clock.
+ * 74.25MHz is videoclock of HD@60p or FHD@30p
+ */
+ if (mode->clock > 74250) {
+ delay[0] = 231;
+ delay[1] = 216;
+ } else {
+ delay[0] = 220;
+ delay[1] = 212;
+ }
+
+ if (dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
+ index = 0;
+ else
+ index = 1;
+
+ rzg2l_mipi_dsi_link_write(dsi, VICH1SET1R,
+ VICH1SET1R_DLY(delay[index]));
+}
+
+static int rzg2l_mipi_dsi_start_hs_clock(struct rzg2l_mipi_dsi *dsi)
+{
+ bool is_clk_cont;
+ u32 hsclksetr;
+ u32 status;
+ int ret;
+
+ is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS);
+
+ /* Start HS clock */
+ hsclksetr = HSCLKSETR_HSCLKRUN_HS | (is_clk_cont ?
+ HSCLKSETR_HSCLKMODE_CONT :
+ HSCLKSETR_HSCLKMODE_NON_CONT);
+ rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR, hsclksetr);
+
+ if (is_clk_cont) {
+ ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
+ status & PLSR_CLLP2HS,
+ 2000, 20000, false, dsi, PLSR);
+ if (ret < 0) {
+ dev_err(dsi->dev, "failed to start HS clock\n");
+ return ret;
+ }
+ }
+
+ dev_dbg(dsi->dev, "Start High Speed Clock with %s clock mode",
+ is_clk_cont ? "continuous" : "non-continuous");
+
+ return 0;
+}
+
+static int rzg2l_mipi_dsi_stop_hs_clock(struct rzg2l_mipi_dsi *dsi)
+{
+ bool is_clk_cont;
+ u32 status;
+ int ret;
+
+ is_clk_cont = !(dsi->mode_flags & MIPI_DSI_CLOCK_NON_CONTINUOUS);
+
+ /* Stop HS clock */
+ rzg2l_mipi_dsi_link_write(dsi, HSCLKSETR,
+ is_clk_cont ? HSCLKSETR_HSCLKMODE_CONT :
+ HSCLKSETR_HSCLKMODE_NON_CONT);
+
+ if (is_clk_cont) {
+ ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
+ status & PLSR_CLHS2LP,
+ 2000, 20000, false, dsi, PLSR);
+ if (ret < 0) {
+ dev_err(dsi->dev, "failed to stop HS clock\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int rzg2l_mipi_dsi_start_video(struct rzg2l_mipi_dsi *dsi)
+{
+ u32 vich1set0r;
+ u32 status;
+ int ret;
+
+ /* Configuration for Blanking sequence and start video input*/
+ vich1set0r = VICH1SET0R_HFPNOLP | VICH1SET0R_HBPNOLP |
+ VICH1SET0R_HSANOLP | VICH1SET0R_VSTART;
+ rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, vich1set0r);
+
+ ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
+ status & VICH1SR_VIRDY,
+ 2000, 20000, false, dsi, VICH1SR);
+ if (ret < 0)
+ dev_err(dsi->dev, "Failed to start video signal input\n");
+
+ return ret;
+}
+
+static int rzg2l_mipi_dsi_stop_video(struct rzg2l_mipi_dsi *dsi)
+{
+ u32 status;
+ int ret;
+
+ rzg2l_mipi_dsi_link_write(dsi, VICH1SET0R, VICH1SET0R_VSTPAFT);
+ ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
+ (status & VICH1SR_STOP) && (!(status & VICH1SR_RUNNING)),
+ 2000, 20000, false, dsi, VICH1SR);
+ if (ret < 0)
+ goto err;
+
+ ret = read_poll_timeout(rzg2l_mipi_dsi_link_read, status,
+ !(status & LINKSR_HSBUSY),
+ 2000, 20000, false, dsi, LINKSR);
+ if (ret < 0)
+ goto err;
+
+ return 0;
+
+err:
+ dev_err(dsi->dev, "Failed to stop video signal input\n");
+ return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Bridge
+ */
+
+static int rzg2l_mipi_dsi_attach(struct drm_bridge *bridge,
+ enum drm_bridge_attach_flags flags)
+{
+ struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
+
+ return drm_bridge_attach(bridge->encoder, dsi->next_bridge, bridge,
+ flags);
+}
+
+static void rzg2l_mipi_dsi_atomic_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
+{
+ struct drm_atomic_state *state = old_bridge_state->base.state;
+ struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
+ const struct drm_display_mode *mode;
+ struct drm_connector *connector;
+ struct drm_crtc *crtc;
+ int ret;
+
+ connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder);
+ crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
+ mode = &drm_atomic_get_new_crtc_state(state, crtc)->adjusted_mode;
+
+ ret = rzg2l_mipi_dsi_startup(dsi, mode);
+ if (ret < 0)
+ return;
+
+ rzg2l_mipi_dsi_set_display_timing(dsi, mode);
+
+ ret = rzg2l_mipi_dsi_start_hs_clock(dsi);
+ if (ret < 0)
+ goto err_stop;
+
+ ret = rzg2l_mipi_dsi_start_video(dsi);
+ if (ret < 0)
+ goto err_stop_clock;
+
+ return;
+
+err_stop_clock:
+ rzg2l_mipi_dsi_stop_hs_clock(dsi);
+err_stop:
+ rzg2l_mipi_dsi_stop(dsi);
+}
+
+static void rzg2l_mipi_dsi_atomic_disable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
+{
+ struct rzg2l_mipi_dsi *dsi = bridge_to_rzg2l_mipi_dsi(bridge);
+
+ rzg2l_mipi_dsi_stop_video(dsi);
+ rzg2l_mipi_dsi_stop_hs_clock(dsi);
+ rzg2l_mipi_dsi_stop(dsi);
+}
+
+static enum drm_mode_status
+rzg2l_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge,
+ const struct drm_display_info *info,
+ const struct drm_display_mode *mode)
+{
+ if (mode->clock > 148500)
+ return MODE_CLOCK_HIGH;
+
+ return MODE_OK;
+}
+
+static const struct drm_bridge_funcs rzg2l_mipi_dsi_bridge_ops = {
+ .attach = rzg2l_mipi_dsi_attach,
+ .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_enable = rzg2l_mipi_dsi_atomic_enable,
+ .atomic_disable = rzg2l_mipi_dsi_atomic_disable,
+ .mode_valid = rzg2l_mipi_dsi_bridge_mode_valid,
+};
+
+/* -----------------------------------------------------------------------------
+ * Host setting
+ */
+
+static int rzg2l_mipi_dsi_host_attach(struct mipi_dsi_host *host,
+ struct mipi_dsi_device *device)
+{
+ struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);
+ int ret;
+
+ if (device->lanes > dsi->num_data_lanes) {
+ dev_err(dsi->dev,
+ "Number of lines of device (%u) exceeds host (%u)\n",
+ device->lanes, dsi->num_data_lanes);
+ return -EINVAL;
+ }
+
+ switch (mipi_dsi_pixel_format_to_bpp(device->format)) {
+ case 24:
+ case 18:
+ break;
+ default:
+ dev_err(dsi->dev, "Unsupported format 0x%04x\n", device->format);
+ return -EINVAL;
+ }
+
+ dsi->lanes = device->lanes;
+ dsi->format = device->format;
+ dsi->mode_flags = device->mode_flags;
+
+ dsi->next_bridge = devm_drm_of_get_bridge(dsi->dev, dsi->dev->of_node,
+ 1, 0);
+ if (IS_ERR(dsi->next_bridge)) {
+ ret = PTR_ERR(dsi->next_bridge);
+ dev_err(dsi->dev, "failed to get next bridge: %d\n", ret);
+ return ret;
+ }
+
+ drm_bridge_add(&dsi->bridge);
+
+ return 0;
+}
+
+static int rzg2l_mipi_dsi_host_detach(struct mipi_dsi_host *host,
+ struct mipi_dsi_device *device)
+{
+ struct rzg2l_mipi_dsi *dsi = host_to_rzg2l_mipi_dsi(host);
+
+ drm_bridge_remove(&dsi->bridge);
+
+ return 0;
+}
+
+static const struct mipi_dsi_host_ops rzg2l_mipi_dsi_host_ops = {
+ .attach = rzg2l_mipi_dsi_host_attach,
+ .detach = rzg2l_mipi_dsi_host_detach,
+};
+
+/* -----------------------------------------------------------------------------
+ * Power Management
+ */
+
+static int __maybe_unused rzg2l_mipi_pm_runtime_suspend(struct device *dev)
+{
+ struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev);
+
+ reset_control_assert(dsi->prstc);
+ reset_control_assert(dsi->arstc);
+
+ return 0;
+}
+
+static int __maybe_unused rzg2l_mipi_pm_runtime_resume(struct device *dev)
+{
+ struct rzg2l_mipi_dsi *dsi = dev_get_drvdata(dev);
+ int ret;
+
+ ret = reset_control_deassert(dsi->arstc);
+ if (ret < 0)
+ return ret;
+
+ ret = reset_control_deassert(dsi->prstc);
+ if (ret < 0)
+ reset_control_assert(dsi->arstc);
+
+ return ret;
+}
+
+static const struct dev_pm_ops rzg2l_mipi_pm_ops = {
+ SET_RUNTIME_PM_OPS(rzg2l_mipi_pm_runtime_suspend, rzg2l_mipi_pm_runtime_resume, NULL)
+};
+
+/* -----------------------------------------------------------------------------
+ * Probe & Remove
+ */
+
+static int rzg2l_mipi_dsi_probe(struct platform_device *pdev)
+{
+ unsigned int num_data_lanes;
+ struct rzg2l_mipi_dsi *dsi;
+ u32 txsetr;
+ int ret;
+
+ dsi = devm_kzalloc(&pdev->dev, sizeof(*dsi), GFP_KERNEL);
+ if (!dsi)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, dsi);
+ dsi->dev = &pdev->dev;
+
+ ret = drm_of_get_data_lanes_count_ep(dsi->dev->of_node, 1, 0, 1, 4);
+ if (ret < 0)
+ return dev_err_probe(dsi->dev, ret,
+ "missing or invalid data-lanes property\n");
+
+ num_data_lanes = ret;
+
+ dsi->mmio = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(dsi->mmio))
+ return PTR_ERR(dsi->mmio);
+
+ dsi->vclk = devm_clk_get(dsi->dev, "vclk");
+ if (IS_ERR(dsi->vclk))
+ return PTR_ERR(dsi->vclk);
+
+ dsi->rstc = devm_reset_control_get_exclusive(dsi->dev, "rst");
+ if (IS_ERR(dsi->rstc))
+ return dev_err_probe(dsi->dev, PTR_ERR(dsi->rstc),
+ "failed to get rst\n");
+
+ dsi->arstc = devm_reset_control_get_exclusive(dsi->dev, "arst");
+ if (IS_ERR(dsi->arstc))
+ return dev_err_probe(&pdev->dev, PTR_ERR(dsi->arstc),
+ "failed to get arst\n");
+
+ dsi->prstc = devm_reset_control_get_exclusive(dsi->dev, "prst");
+ if (IS_ERR(dsi->prstc))
+ return dev_err_probe(dsi->dev, PTR_ERR(dsi->prstc),
+ "failed to get prst\n");
+
+ platform_set_drvdata(pdev, dsi);
+
+ pm_runtime_enable(dsi->dev);
+
+ ret = pm_runtime_resume_and_get(dsi->dev);
+ if (ret < 0)
+ goto err_pm_disable;
+
+ /*
+ * TXSETR register can be read only after DPHY init. But during probe
+ * mode->clock and format are not available. So initialize DPHY with
+ * timing parameters for 80Mbps.
+ */
+ ret = rzg2l_mipi_dsi_dphy_init(dsi, 80000);
+ if (ret < 0)
+ goto err_phy;
+
+ txsetr = rzg2l_mipi_dsi_link_read(dsi, TXSETR);
+ dsi->num_data_lanes = min(((txsetr >> 16) & 3) + 1, num_data_lanes);
+ rzg2l_mipi_dsi_dphy_exit(dsi);
+ pm_runtime_put(dsi->dev);
+
+ /* Initialize the DRM bridge. */
+ dsi->bridge.funcs = &rzg2l_mipi_dsi_bridge_ops;
+ dsi->bridge.of_node = dsi->dev->of_node;
+
+ /* Init host device */
+ dsi->host.dev = dsi->dev;
+ dsi->host.ops = &rzg2l_mipi_dsi_host_ops;
+ ret = mipi_dsi_host_register(&dsi->host);
+ if (ret < 0)
+ goto err_pm_disable;
+
+ return 0;
+
+err_phy:
+ rzg2l_mipi_dsi_dphy_exit(dsi);
+ pm_runtime_put(dsi->dev);
+err_pm_disable:
+ pm_runtime_disable(dsi->dev);
+ return ret;
+}
+
+static int rzg2l_mipi_dsi_remove(struct platform_device *pdev)
+{
+ struct rzg2l_mipi_dsi *dsi = platform_get_drvdata(pdev);
+
+ mipi_dsi_host_unregister(&dsi->host);
+ pm_runtime_disable(&pdev->dev);
+
+ return 0;
+}
+
+static const struct of_device_id rzg2l_mipi_dsi_of_table[] = {
+ { .compatible = "renesas,rzg2l-mipi-dsi" },
+ { /* sentinel */ }
+};
+
+MODULE_DEVICE_TABLE(of, rzg2l_mipi_dsi_of_table);
+
+static struct platform_driver rzg2l_mipi_dsi_platform_driver = {
+ .probe = rzg2l_mipi_dsi_probe,
+ .remove = rzg2l_mipi_dsi_remove,
+ .driver = {
+ .name = "rzg2l-mipi-dsi",
+ .pm = &rzg2l_mipi_pm_ops,
+ .of_match_table = rzg2l_mipi_dsi_of_table,
+ },
+};
+
+module_platform_driver(rzg2l_mipi_dsi_platform_driver);
+
+MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
+MODULE_DESCRIPTION("Renesas RZ/G2L MIPI DSI Encoder Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi_regs.h b/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi_regs.h
new file mode 100644
index 000000000000..1dbc16ec64a4
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rzg2l_mipi_dsi_regs.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * RZ/G2L MIPI DSI Interface Registers Definitions
+ *
+ * Copyright (C) 2022 Renesas Electronics Corporation
+ */
+
+#ifndef __RZG2L_MIPI_DSI_REGS_H__
+#define __RZG2L_MIPI_DSI_REGS_H__
+
+#include <linux/bits.h>
+
+/* DPHY Registers */
+#define DSIDPHYCTRL0 0x00
+#define DSIDPHYCTRL0_CAL_EN_HSRX_OFS BIT(16)
+#define DSIDPHYCTRL0_CMN_MASTER_EN BIT(8)
+#define DSIDPHYCTRL0_RE_VDD_DETVCCQLV18 BIT(2)
+#define DSIDPHYCTRL0_EN_LDO1200 BIT(1)
+#define DSIDPHYCTRL0_EN_BGR BIT(0)
+
+#define DSIDPHYTIM0 0x04
+#define DSIDPHYTIM0_TCLK_MISS(x) ((x) << 24)
+#define DSIDPHYTIM0_T_INIT(x) ((x) << 0)
+
+#define DSIDPHYTIM1 0x08
+#define DSIDPHYTIM1_THS_PREPARE(x) ((x) << 24)
+#define DSIDPHYTIM1_TCLK_PREPARE(x) ((x) << 16)
+#define DSIDPHYTIM1_THS_SETTLE(x) ((x) << 8)
+#define DSIDPHYTIM1_TCLK_SETTLE(x) ((x) << 0)
+
+#define DSIDPHYTIM2 0x0c
+#define DSIDPHYTIM2_TCLK_TRAIL(x) ((x) << 24)
+#define DSIDPHYTIM2_TCLK_POST(x) ((x) << 16)
+#define DSIDPHYTIM2_TCLK_PRE(x) ((x) << 8)
+#define DSIDPHYTIM2_TCLK_ZERO(x) ((x) << 0)
+
+#define DSIDPHYTIM3 0x10
+#define DSIDPHYTIM3_TLPX(x) ((x) << 24)
+#define DSIDPHYTIM3_THS_EXIT(x) ((x) << 16)
+#define DSIDPHYTIM3_THS_TRAIL(x) ((x) << 8)
+#define DSIDPHYTIM3_THS_ZERO(x) ((x) << 0)
+
+/* --------------------------------------------------------*/
+/* Link Registers */
+#define LINK_REG_OFFSET 0x10000
+
+/* Link Status Register */
+#define LINKSR 0x10
+#define LINKSR_LPBUSY BIT(13)
+#define LINKSR_HSBUSY BIT(12)
+#define LINKSR_VICHRUN1 BIT(8)
+#define LINKSR_SQCHRUN1 BIT(4)
+#define LINKSR_SQCHRUN0 BIT(0)
+
+/* Tx Set Register */
+#define TXSETR 0x100
+#define TXSETR_NUMLANECAP (0x3 << 16)
+#define TXSETR_DLEN (1 << 9)
+#define TXSETR_CLEN (1 << 8)
+#define TXSETR_NUMLANEUSE(x) (((x) & 0x3) << 0)
+
+/* HS Clock Set Register */
+#define HSCLKSETR 0x104
+#define HSCLKSETR_HSCLKMODE_CONT (1 << 1)
+#define HSCLKSETR_HSCLKMODE_NON_CONT (0 << 1)
+#define HSCLKSETR_HSCLKRUN_HS (1 << 0)
+#define HSCLKSETR_HSCLKRUN_LP (0 << 0)
+
+/* Reset Control Register */
+#define RSTCR 0x110
+#define RSTCR_SWRST BIT(0)
+#define RSTCR_FCETXSTP BIT(16)
+
+/* Reset Status Register */
+#define RSTSR 0x114
+#define RSTSR_DL0DIR (1 << 15)
+#define RSTSR_DLSTPST (0xf << 8)
+#define RSTSR_SWRSTV1 (1 << 4)
+#define RSTSR_SWRSTIB (1 << 3)
+#define RSTSR_SWRSTAPB (1 << 2)
+#define RSTSR_SWRSTLP (1 << 1)
+#define RSTSR_SWRSTHS (1 << 0)
+
+/* Clock Lane Stop Time Set Register */
+#define CLSTPTSETR 0x314
+#define CLSTPTSETR_CLKKPT(x) ((x) << 24)
+#define CLSTPTSETR_CLKBFHT(x) ((x) << 16)
+#define CLSTPTSETR_CLKSTPT(x) ((x) << 2)
+
+/* LP Transition Time Set Register */
+#define LPTRNSTSETR 0x318
+#define LPTRNSTSETR_GOLPBKT(x) ((x) << 0)
+
+/* Physical Lane Status Register */
+#define PLSR 0x320
+#define PLSR_CLHS2LP BIT(27)
+#define PLSR_CLLP2HS BIT(26)
+
+/* Video-Input Channel 1 Set 0 Register */
+#define VICH1SET0R 0x400
+#define VICH1SET0R_VSEN BIT(12)
+#define VICH1SET0R_HFPNOLP BIT(10)
+#define VICH1SET0R_HBPNOLP BIT(9)
+#define VICH1SET0R_HSANOLP BIT(8)
+#define VICH1SET0R_VSTPAFT BIT(1)
+#define VICH1SET0R_VSTART BIT(0)
+
+/* Video-Input Channel 1 Set 1 Register */
+#define VICH1SET1R 0x404
+#define VICH1SET1R_DLY(x) (((x) & 0xfff) << 2)
+
+/* Video-Input Channel 1 Status Register */
+#define VICH1SR 0x410
+#define VICH1SR_VIRDY BIT(3)
+#define VICH1SR_RUNNING BIT(2)
+#define VICH1SR_STOP BIT(1)
+#define VICH1SR_START BIT(0)
+
+/* Video-Input Channel 1 Pixel Packet Set Register */
+#define VICH1PPSETR 0x420
+#define VICH1PPSETR_DT_RGB18 (0x1e << 16)
+#define VICH1PPSETR_DT_RGB18_LS (0x2e << 16)
+#define VICH1PPSETR_DT_RGB24 (0x3e << 16)
+#define VICH1PPSETR_TXESYNC_PULSE (1 << 15)
+#define VICH1PPSETR_VC(x) ((x) << 22)
+
+/* Video-Input Channel 1 Vertical Size Set Register */
+#define VICH1VSSETR 0x428
+#define VICH1VSSETR_VACTIVE(x) (((x) & 0x7fff) << 16)
+#define VICH1VSSETR_VSPOL_LOW (1 << 15)
+#define VICH1VSSETR_VSPOL_HIGH (0 << 15)
+#define VICH1VSSETR_VSA(x) (((x) & 0xfff) << 0)
+
+/* Video-Input Channel 1 Vertical Porch Set Register */
+#define VICH1VPSETR 0x42c
+#define VICH1VPSETR_VFP(x) (((x) & 0x1fff) << 16)
+#define VICH1VPSETR_VBP(x) (((x) & 0x1fff) << 0)
+
+/* Video-Input Channel 1 Horizontal Size Set Register */
+#define VICH1HSSETR 0x430
+#define VICH1HSSETR_HACTIVE(x) (((x) & 0x7fff) << 16)
+#define VICH1HSSETR_HSPOL_LOW (1 << 15)
+#define VICH1HSSETR_HSPOL_HIGH (0 << 15)
+#define VICH1HSSETR_HSA(x) (((x) & 0xfff) << 0)
+
+/* Video-Input Channel 1 Horizontal Porch Set Register */
+#define VICH1HPSETR 0x434
+#define VICH1HPSETR_HFP(x) (((x) & 0x1fff) << 16)
+#define VICH1HPSETR_HBP(x) (((x) & 0x1fff) << 0)
+
+#endif /* __RZG2L_MIPI_DSI_REGS_H__ */
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index 518ee13b1d6f..8526dda91931 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -571,7 +571,7 @@ static void cdn_dp_encoder_mode_set(struct drm_encoder *encoder,
video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC);
video->h_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NHSYNC);
- memcpy(&dp->mode, adjusted, sizeof(*mode));
+ drm_mode_copy(&dp->mode, adjusted);
}
static bool cdn_dp_check_link_status(struct cdn_dp_device *dp)
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
index f4df9820b295..7901c3babc8c 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
@@ -364,12 +364,6 @@ static inline u32 dsi_read(struct dw_mipi_dsi_rockchip *dsi, u32 reg)
return readl(dsi->base + reg);
}
-static inline void dsi_update_bits(struct dw_mipi_dsi_rockchip *dsi, u32 reg,
- u32 mask, u32 val)
-{
- dsi_write(dsi, reg, (dsi_read(dsi, reg) & ~mask) | val);
-}
-
static void dw_mipi_dsi_phy_write(struct dw_mipi_dsi_rockchip *dsi,
u8 test_code,
u8 test_data)
@@ -1221,7 +1215,7 @@ static int dw_mipi_dsi_dphy_power_on(struct phy *phy)
return i;
}
- ret = pm_runtime_get_sync(dsi->dev);
+ ret = pm_runtime_resume_and_get(dsi->dev);
if (ret < 0) {
DRM_DEV_ERROR(dsi->dev, "failed to enable device: %d\n", ret);
return ret;
diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c
index 87b2243ea23e..f51774866f41 100644
--- a/drivers/gpu/drm/rockchip/inno_hdmi.c
+++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
@@ -499,7 +499,7 @@ static void inno_hdmi_encoder_mode_set(struct drm_encoder *encoder,
inno_hdmi_setup(hdmi, adj_mode);
/* Store the display mode for plugin/DPMS poweron events */
- memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode));
+ drm_mode_copy(&hdmi->previous_mode, adj_mode);
}
static void inno_hdmi_encoder_enable(struct drm_encoder *encoder)
diff --git a/drivers/gpu/drm/rockchip/rk3066_hdmi.c b/drivers/gpu/drm/rockchip/rk3066_hdmi.c
index cf2cf51091a3..90145ad96984 100644
--- a/drivers/gpu/drm/rockchip/rk3066_hdmi.c
+++ b/drivers/gpu/drm/rockchip/rk3066_hdmi.c
@@ -395,7 +395,7 @@ rk3066_hdmi_encoder_mode_set(struct drm_encoder *encoder,
struct rk3066_hdmi *hdmi = encoder_to_rk3066_hdmi(encoder);
/* Store the display mode for plugin/DPMS poweron events. */
- memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode));
+ drm_mode_copy(&hdmi->previous_mode, adj_mode);
}
static void rk3066_hdmi_encoder_enable(struct drm_encoder *encoder)
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 813f9f8c8698..6e0788d14c10 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -17,7 +17,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_of.h>
#include <drm/drm_probe_helper.h>
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
index 1641440837af..aeb03a57240f 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h
@@ -9,10 +9,10 @@
#ifndef _ROCKCHIP_DRM_DRV_H
#define _ROCKCHIP_DRM_DRV_H
-#include <drm/drm_fb_helper.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_gem.h>
+#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/component.h>
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index 092bf863110b..cfe8b793d344 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -9,7 +9,6 @@
#include <drm/drm.h>
#include <drm/drm_atomic.h>
#include <drm/drm_damage_helper.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_framebuffer_helper.h>
@@ -25,35 +24,6 @@ static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = {
.dirty = drm_atomic_helper_dirtyfb,
};
-static struct drm_framebuffer *
-rockchip_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd,
- struct drm_gem_object **obj, unsigned int num_planes)
-{
- struct drm_framebuffer *fb;
- int ret;
- int i;
-
- fb = kzalloc(sizeof(*fb), GFP_KERNEL);
- if (!fb)
- return ERR_PTR(-ENOMEM);
-
- drm_helper_mode_fill_fb_struct(dev, fb, mode_cmd);
-
- for (i = 0; i < num_planes; i++)
- fb->obj[i] = obj[i];
-
- ret = drm_framebuffer_init(dev, fb, &rockchip_drm_fb_funcs);
- if (ret) {
- DRM_DEV_ERROR(dev->dev,
- "Failed to initialize framebuffer: %d\n",
- ret);
- kfree(fb);
- return ERR_PTR(ret);
- }
-
- return fb;
-}
-
static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = {
.atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
};
@@ -101,25 +71,10 @@ rockchip_fb_create(struct drm_device *dev, struct drm_file *file,
static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {
.fb_create = rockchip_fb_create,
- .output_poll_changed = drm_fb_helper_output_poll_changed,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit,
};
-struct drm_framebuffer *
-rockchip_drm_framebuffer_init(struct drm_device *dev,
- const struct drm_mode_fb_cmd2 *mode_cmd,
- struct drm_gem_object *obj)
-{
- struct drm_framebuffer *fb;
-
- fb = rockchip_fb_alloc(dev, mode_cmd, &obj, 1);
- if (IS_ERR(fb))
- return ERR_CAST(fb);
-
- return fb;
-}
-
void rockchip_drm_mode_config_init(struct drm_device *dev)
{
dev->mode_config.min_width = 0;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.h b/drivers/gpu/drm/rockchip/rockchip_drm_fb.h
index 1a696521096d..bae4e079dfb1 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.h
@@ -7,11 +7,5 @@
#ifndef _ROCKCHIP_DRM_FB_H
#define _ROCKCHIP_DRM_FB_H
-struct drm_framebuffer *
-rockchip_drm_framebuffer_init(struct drm_device *dev,
- const struct drm_mode_fb_cmd2 *mode_cmd,
- struct drm_gem_object *obj);
-void rockchip_drm_framebuffer_fini(struct drm_framebuffer *fb);
-
void rockchip_drm_mode_config_init(struct drm_device *dev);
#endif /* _ROCKCHIP_DRM_FB_H */
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
index da8a69953706..6edb7c52cb3d 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c
@@ -9,6 +9,7 @@
#include <linux/vmalloc.h>
#include <drm/drm.h>
+#include <drm/drm_fb_helper.h>
#include <drm/drm_gem.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_prime.h>
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index c356de5dd220..fa1f4ee6d195 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -602,7 +602,7 @@ static int vop_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
struct vop *vop = to_vop(crtc);
int ret, i;
- ret = pm_runtime_get_sync(vop->dev);
+ ret = pm_runtime_resume_and_get(vop->dev);
if (ret < 0) {
DRM_DEV_ERROR(vop->dev, "failed to get pm runtime: %d\n", ret);
return ret;
@@ -1983,7 +1983,7 @@ static int vop_initial(struct vop *vop)
return PTR_ERR(vop->dclk);
}
- ret = pm_runtime_get_sync(vop->dev);
+ ret = pm_runtime_resume_and_get(vop->dev);
if (ret < 0) {
DRM_DEV_ERROR(vop->dev, "failed to get pm runtime: %d\n", ret);
return ret;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
index 105a548d0abe..8cecf81a5ae0 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop2.c
@@ -822,7 +822,7 @@ static void vop2_enable(struct vop2 *vop2)
{
int ret;
- ret = pm_runtime_get_sync(vop2->dev);
+ ret = pm_runtime_resume_and_get(vop2->dev);
if (ret < 0) {
drm_err(vop2->drm, "failed to get pm runtime: %d\n", ret);
return;
diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
index 5a284332ec49..68f6ebb33460 100644
--- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
+++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
@@ -152,7 +152,7 @@ static int rk3288_lvds_poweron(struct rockchip_lvds *lvds)
DRM_DEV_ERROR(lvds->dev, "failed to enable lvds pclk %d\n", ret);
return ret;
}
- ret = pm_runtime_get_sync(lvds->dev);
+ ret = pm_runtime_resume_and_get(lvds->dev);
if (ret < 0) {
DRM_DEV_ERROR(lvds->dev, "failed to get pm runtime: %d\n", ret);
clk_disable(lvds->pclk);
@@ -336,16 +336,20 @@ static int px30_lvds_poweron(struct rockchip_lvds *lvds)
{
int ret;
- ret = pm_runtime_get_sync(lvds->dev);
+ ret = pm_runtime_resume_and_get(lvds->dev);
if (ret < 0) {
DRM_DEV_ERROR(lvds->dev, "failed to get pm runtime: %d\n", ret);
return ret;
}
/* Enable LVDS mode */
- return regmap_update_bits(lvds->grf, PX30_LVDS_GRF_PD_VO_CON1,
+ ret = regmap_update_bits(lvds->grf, PX30_LVDS_GRF_PD_VO_CON1,
PX30_LVDS_MODE_EN(1) | PX30_LVDS_P2S_EN(1),
PX30_LVDS_MODE_EN(1) | PX30_LVDS_P2S_EN(1));
+ if (ret)
+ pm_runtime_put(lvds->dev);
+
+ return ret;
}
static void px30_lvds_poweroff(struct rockchip_lvds *lvds)
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
index 9bf0637bf8e2..9d30aa73b542 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
@@ -188,7 +188,7 @@ static const struct vop2_win_data rk3568_vop_win_data[] = {
.base = 0x1800,
.layer_sel_id = 2,
.supported_rotations = DRM_MODE_REFLECT_Y,
- .type = DRM_PLANE_TYPE_OVERLAY,
+ .type = DRM_PLANE_TYPE_PRIMARY,
.max_upscale_factor = 8,
.max_downscale_factor = 8,
.dly = { 20, 47, 41 },
diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c
index 4b913dbb7d7b..fe09e5be79bd 100644
--- a/drivers/gpu/drm/scheduler/sched_entity.c
+++ b/drivers/gpu/drm/scheduler/sched_entity.c
@@ -73,6 +73,7 @@ int drm_sched_entity_init(struct drm_sched_entity *entity,
entity->priority = priority;
entity->sched_list = num_sched_list > 1 ? sched_list : NULL;
entity->last_scheduled = NULL;
+ RB_CLEAR_NODE(&entity->rb_tree_node);
if(num_sched_list)
entity->rq = &sched_list[0]->sched_rq[entity->priority];
@@ -139,6 +140,73 @@ bool drm_sched_entity_is_ready(struct drm_sched_entity *entity)
return true;
}
+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);
+ WARN_ON(job->s_fence->parent);
+ job->sched->ops->free_job(job);
+}
+
+/* Signal the scheduler finished fence when the entity in question is killed. */
+static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f,
+ struct dma_fence_cb *cb)
+{
+ struct drm_sched_job *job = container_of(cb, struct drm_sched_job,
+ finish_cb);
+ int r;
+
+ 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)
+ return;
+
+ dma_fence_put(f);
+ }
+
+ INIT_WORK(&job->work, drm_sched_entity_kill_jobs_work);
+ schedule_work(&job->work);
+}
+
+/* Remove the entity from the scheduler and kill all pending jobs */
+static void drm_sched_entity_kill(struct drm_sched_entity *entity)
+{
+ struct drm_sched_job *job;
+ struct dma_fence *prev;
+
+ if (!entity->rq)
+ return;
+
+ spin_lock(&entity->rq_lock);
+ entity->stopped = true;
+ drm_sched_rq_remove_entity(entity->rq, entity);
+ spin_unlock(&entity->rq_lock);
+
+ /* 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);
+ 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))
+ drm_sched_entity_kill_jobs_cb(NULL, &job->finish_cb);
+
+ prev = &s_fence->finished;
+ }
+ dma_fence_put(prev);
+}
+
/**
* drm_sched_entity_flush - Flush a context entity
*
@@ -179,91 +247,13 @@ long drm_sched_entity_flush(struct drm_sched_entity *entity, long timeout)
/* For killed process disable any more IBs enqueue right now */
last_user = cmpxchg(&entity->last_user, current->group_leader, NULL);
if ((!last_user || last_user == current->group_leader) &&
- (current->flags & PF_EXITING) && (current->exit_code == SIGKILL)) {
- spin_lock(&entity->rq_lock);
- entity->stopped = true;
- drm_sched_rq_remove_entity(entity->rq, entity);
- spin_unlock(&entity->rq_lock);
- }
+ (current->flags & PF_EXITING) && (current->exit_code == SIGKILL))
+ drm_sched_entity_kill(entity);
return ret;
}
EXPORT_SYMBOL(drm_sched_entity_flush);
-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);
- WARN_ON(job->s_fence->parent);
- job->sched->ops->free_job(job);
-}
-
-
-/* Signal the scheduler finished fence when the entity in question is killed. */
-static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f,
- struct dma_fence_cb *cb)
-{
- struct drm_sched_job *job = container_of(cb, struct drm_sched_job,
- finish_cb);
-
- dma_fence_put(f);
- INIT_WORK(&job->work, drm_sched_entity_kill_jobs_work);
- schedule_work(&job->work);
-}
-
-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++);
-
- if (job->sched->ops->dependency)
- return job->sched->ops->dependency(job, entity);
-
- return NULL;
-}
-
-static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity)
-{
- struct drm_sched_job *job;
- struct dma_fence *f;
- int r;
-
- while ((job = to_drm_sched_job(spsc_queue_pop(&entity->job_queue)))) {
- struct drm_sched_fence *s_fence = job->s_fence;
-
- /* Wait for all dependencies to avoid data corruptions */
- while ((f = drm_sched_job_dependency(job, entity))) {
- dma_fence_wait(f, false);
- dma_fence_put(f);
- }
-
- drm_sched_fence_scheduled(s_fence);
- dma_fence_set_error(&s_fence->finished, -ESRCH);
-
- /*
- * When pipe is hanged by older entity, new entity might
- * not even have chance to submit it's first job to HW
- * and so entity->last_scheduled will remain NULL
- */
- if (!entity->last_scheduled) {
- drm_sched_entity_kill_jobs_cb(NULL, &job->finish_cb);
- continue;
- }
-
- dma_fence_get(entity->last_scheduled);
- r = dma_fence_add_callback(entity->last_scheduled,
- &job->finish_cb,
- drm_sched_entity_kill_jobs_cb);
- if (r == -ENOENT)
- drm_sched_entity_kill_jobs_cb(NULL, &job->finish_cb);
- else if (r)
- DRM_ERROR("fence add callback failed (%d)\n", r);
- }
-}
-
/**
* drm_sched_entity_fini - Destroy a context entity
*
@@ -277,33 +267,17 @@ static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity)
*/
void drm_sched_entity_fini(struct drm_sched_entity *entity)
{
- struct drm_gpu_scheduler *sched = NULL;
-
- if (entity->rq) {
- sched = entity->rq->sched;
- drm_sched_rq_remove_entity(entity->rq, entity);
- }
-
- /* Consumption of existing IBs wasn't completed. Forcefully
- * remove them here.
+ /*
+ * If consumption of existing IBs wasn't completed. Forcefully remove
+ * them here. Also makes sure that the scheduler won't touch this entity
+ * any more.
*/
- if (spsc_queue_count(&entity->job_queue)) {
- if (sched) {
- /*
- * Wait for thread to idle to make sure it isn't processing
- * this entity.
- */
- wait_for_completion(&entity->entity_idle);
+ drm_sched_entity_kill(entity);
- }
- if (entity->dependency) {
- dma_fence_remove_callback(entity->dependency,
- &entity->cb);
- dma_fence_put(entity->dependency);
- entity->dependency = NULL;
- }
-
- drm_sched_entity_kill_jobs(entity);
+ if (entity->dependency) {
+ dma_fence_remove_callback(entity->dependency, &entity->cb);
+ dma_fence_put(entity->dependency);
+ entity->dependency = NULL;
}
dma_fence_put(entity->last_scheduled);
@@ -416,6 +390,19 @@ static bool drm_sched_entity_add_dependency_cb(struct drm_sched_entity *entity)
return false;
}
+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++);
+
+ if (job->sched->ops->prepare_job)
+ return job->sched->ops->prepare_job(job, entity);
+
+ return NULL;
+}
+
struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)
{
struct drm_sched_job *sched_job;
@@ -448,6 +435,19 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)
smp_wmb();
spsc_queue_pop(&entity->job_queue);
+
+ /*
+ * Update the entity's location in the min heap according to
+ * the timestamp of the next job, if any.
+ */
+ if (drm_sched_policy == DRM_SCHED_POLICY_FIFO) {
+ struct drm_sched_job *next;
+
+ next = to_drm_sched_job(spsc_queue_peek(&entity->job_queue));
+ if (next)
+ drm_sched_rq_update_fifo(entity, next->submit_ts);
+ }
+
return sched_job;
}
@@ -512,6 +512,7 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
atomic_inc(entity->rq->sched->score);
WRITE_ONCE(entity->last_user, current->group_leader);
first = spsc_queue_push(&entity->job_queue, &sched_job->queue_node);
+ sched_job->submit_ts = ktime_get();
/* first job wakes up scheduler */
if (first) {
@@ -523,8 +524,13 @@ void drm_sched_entity_push_job(struct drm_sched_job *sched_job)
DRM_ERROR("Trying to push to a killed entity\n");
return;
}
+
drm_sched_rq_add_entity(entity->rq, entity);
spin_unlock(&entity->rq_lock);
+
+ if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
+ drm_sched_rq_update_fifo(entity, sched_job->submit_ts);
+
drm_sched_wakeup(entity->rq->sched);
}
}
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index e5a4ecde0063..31f3a1267be4 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -62,6 +62,55 @@
#define to_drm_sched_job(sched_job) \
container_of((sched_job), struct drm_sched_job, queue_node)
+int drm_sched_policy = DRM_SCHED_POLICY_FIFO;
+
+/**
+ * DOC: sched_policy (int)
+ * Used to override default entities scheduling policy in a run queue.
+ */
+MODULE_PARM_DESC(sched_policy, "Specify the scheduling policy for entities on a run-queue, " __stringify(DRM_SCHED_POLICY_RR) " = Round Robin, " __stringify(DRM_SCHED_POLICY_FIFO) " = FIFO (default).");
+module_param_named(sched_policy, drm_sched_policy, int, 0444);
+
+static __always_inline bool drm_sched_entity_compare_before(struct rb_node *a,
+ const struct rb_node *b)
+{
+ struct drm_sched_entity *ent_a = rb_entry((a), struct drm_sched_entity, rb_tree_node);
+ struct drm_sched_entity *ent_b = rb_entry((b), struct drm_sched_entity, rb_tree_node);
+
+ return ktime_before(ent_a->oldest_job_waiting, ent_b->oldest_job_waiting);
+}
+
+static inline void drm_sched_rq_remove_fifo_locked(struct drm_sched_entity *entity)
+{
+ struct drm_sched_rq *rq = entity->rq;
+
+ if (!RB_EMPTY_NODE(&entity->rb_tree_node)) {
+ rb_erase_cached(&entity->rb_tree_node, &rq->rb_tree_root);
+ RB_CLEAR_NODE(&entity->rb_tree_node);
+ }
+}
+
+void drm_sched_rq_update_fifo(struct drm_sched_entity *entity, ktime_t ts)
+{
+ /*
+ * Both locks need to be grabbed, one to protect from entity->rq change
+ * for entity from within concurrent drm_sched_entity_select_rq and the
+ * other to update the rb tree structure.
+ */
+ spin_lock(&entity->rq_lock);
+ spin_lock(&entity->rq->lock);
+
+ drm_sched_rq_remove_fifo_locked(entity);
+
+ entity->oldest_job_waiting = ts;
+
+ rb_add_cached(&entity->rb_tree_node, &entity->rq->rb_tree_root,
+ drm_sched_entity_compare_before);
+
+ spin_unlock(&entity->rq->lock);
+ spin_unlock(&entity->rq_lock);
+}
+
/**
* drm_sched_rq_init - initialize a given run queue struct
*
@@ -75,6 +124,7 @@ static void drm_sched_rq_init(struct drm_gpu_scheduler *sched,
{
spin_lock_init(&rq->lock);
INIT_LIST_HEAD(&rq->entities);
+ rq->rb_tree_root = RB_ROOT_CACHED;
rq->current_entity = NULL;
rq->sched = sched;
}
@@ -92,9 +142,12 @@ void drm_sched_rq_add_entity(struct drm_sched_rq *rq,
{
if (!list_empty(&entity->list))
return;
+
spin_lock(&rq->lock);
+
atomic_inc(rq->sched->score);
list_add_tail(&entity->list, &rq->entities);
+
spin_unlock(&rq->lock);
}
@@ -111,23 +164,30 @@ void drm_sched_rq_remove_entity(struct drm_sched_rq *rq,
{
if (list_empty(&entity->list))
return;
+
spin_lock(&rq->lock);
+
atomic_dec(rq->sched->score);
list_del_init(&entity->list);
+
if (rq->current_entity == entity)
rq->current_entity = NULL;
+
+ if (drm_sched_policy == DRM_SCHED_POLICY_FIFO)
+ drm_sched_rq_remove_fifo_locked(entity);
+
spin_unlock(&rq->lock);
}
/**
- * drm_sched_rq_select_entity - Select an entity which could provide a job to run
+ * drm_sched_rq_select_entity_rr - Select an entity which could provide a job to run
*
* @rq: scheduler run queue to check.
*
* Try to find a ready entity, returns NULL if none found.
*/
static struct drm_sched_entity *
-drm_sched_rq_select_entity(struct drm_sched_rq *rq)
+drm_sched_rq_select_entity_rr(struct drm_sched_rq *rq)
{
struct drm_sched_entity *entity;
@@ -164,6 +224,34 @@ drm_sched_rq_select_entity(struct drm_sched_rq *rq)
}
/**
+ * drm_sched_rq_select_entity_fifo - Select an entity which provides a job to run
+ *
+ * @rq: scheduler run queue to check.
+ *
+ * Find oldest waiting ready entity, returns NULL if none found.
+ */
+static struct drm_sched_entity *
+drm_sched_rq_select_entity_fifo(struct drm_sched_rq *rq)
+{
+ struct rb_node *rb;
+
+ spin_lock(&rq->lock);
+ for (rb = rb_first_cached(&rq->rb_tree_root); rb; rb = rb_next(rb)) {
+ struct drm_sched_entity *entity;
+
+ entity = rb_entry(rb, struct drm_sched_entity, rb_tree_node);
+ if (drm_sched_entity_is_ready(entity)) {
+ rq->current_entity = entity;
+ reinit_completion(&entity->entity_idle);
+ break;
+ }
+ }
+ spin_unlock(&rq->lock);
+
+ return rb ? rb_entry(rb, struct drm_sched_entity, rb_tree_node) : NULL;
+}
+
+/**
* drm_sched_job_done - complete a job
* @s_job: pointer to the job which is done
*
@@ -198,32 +286,6 @@ static void drm_sched_job_done_cb(struct dma_fence *f, struct dma_fence_cb *cb)
}
/**
- * drm_sched_dependency_optimized - test if the dependency can be optimized
- *
- * @fence: the dependency fence
- * @entity: the entity which depends on the above fence
- *
- * Returns true if the dependency can be optimized and false otherwise
- */
-bool drm_sched_dependency_optimized(struct dma_fence* fence,
- struct drm_sched_entity *entity)
-{
- struct drm_gpu_scheduler *sched = entity->rq->sched;
- struct drm_sched_fence *s_fence;
-
- if (!fence || dma_fence_is_signaled(fence))
- return false;
- if (fence->context == entity->fence_context)
- return true;
- s_fence = to_drm_sched_fence(fence);
- if (s_fence && s_fence->sched == sched)
- return true;
-
- return false;
-}
-EXPORT_SYMBOL(drm_sched_dependency_optimized);
-
-/**
* drm_sched_start_timeout - start timeout for reset worker
*
* @sched: scheduler instance to start the worker for
@@ -355,27 +417,6 @@ static void drm_sched_job_timedout(struct work_struct *work)
}
}
- /**
- * drm_sched_increase_karma - Update sched_entity guilty flag
- *
- * @bad: The job guilty of time out
- *
- * Increment on every hang caused by the 'bad' job. If this exceeds the hang
- * limit of the scheduler then the respective sched entity is marked guilty and
- * jobs from it will not be scheduled further
- */
-void drm_sched_increase_karma(struct drm_sched_job *bad)
-{
- drm_sched_increase_karma_ext(bad, 1);
-}
-EXPORT_SYMBOL(drm_sched_increase_karma);
-
-void drm_sched_reset_karma(struct drm_sched_job *bad)
-{
- drm_sched_increase_karma_ext(bad, 0);
-}
-EXPORT_SYMBOL(drm_sched_reset_karma);
-
/**
* drm_sched_stop - stop the scheduler
*
@@ -517,31 +558,14 @@ EXPORT_SYMBOL(drm_sched_start);
*/
void drm_sched_resubmit_jobs(struct drm_gpu_scheduler *sched)
{
- drm_sched_resubmit_jobs_ext(sched, INT_MAX);
-}
-EXPORT_SYMBOL(drm_sched_resubmit_jobs);
-
-/**
- * drm_sched_resubmit_jobs_ext - helper to relunch certain number of jobs from mirror ring list
- *
- * @sched: scheduler instance
- * @max: job numbers to relaunch
- *
- */
-void drm_sched_resubmit_jobs_ext(struct drm_gpu_scheduler *sched, int max)
-{
struct drm_sched_job *s_job, *tmp;
uint64_t guilty_context;
bool found_guilty = false;
struct dma_fence *fence;
- int i = 0;
list_for_each_entry_safe(s_job, tmp, &sched->pending_list, list) {
struct drm_sched_fence *s_fence = s_job->s_fence;
- if (i >= max)
- break;
-
if (!found_guilty && atomic_read(&s_job->karma) > sched->hang_limit) {
found_guilty = true;
guilty_context = s_job->s_fence->scheduled.context;
@@ -551,7 +575,6 @@ void drm_sched_resubmit_jobs_ext(struct drm_gpu_scheduler *sched, int max)
dma_fence_set_error(&s_fence->finished, -ECANCELED);
fence = sched->ops->run_job(s_job);
- i++;
if (IS_ERR_OR_NULL(fence)) {
if (IS_ERR(fence))
@@ -567,7 +590,7 @@ void drm_sched_resubmit_jobs_ext(struct drm_gpu_scheduler *sched, int max)
}
}
}
-EXPORT_SYMBOL(drm_sched_resubmit_jobs_ext);
+EXPORT_SYMBOL(drm_sched_resubmit_jobs);
/**
* drm_sched_job_init - init a scheduler job
@@ -685,32 +708,28 @@ int drm_sched_job_add_dependency(struct drm_sched_job *job,
EXPORT_SYMBOL(drm_sched_job_add_dependency);
/**
- * drm_sched_job_add_implicit_dependencies - adds implicit dependencies as job
- * dependencies
+ * drm_sched_job_add_resv_dependencies - add all fences from the resv to the job
* @job: scheduler job to add the dependencies to
- * @obj: the gem object to add new dependencies from.
- * @write: whether the job might write the object (so we need to depend on
- * shared fences in the reservation object).
+ * @resv: the dma_resv object to get the fences from
+ * @usage: the dma_resv_usage to use to filter the fences
*
- * This should be called after drm_gem_lock_reservations() on your array of
- * GEM objects used in the job but before updating the reservations with your
- * own fences.
+ * This adds all fences matching the given usage from @resv to @job.
+ * Must be called with the @resv lock held.
*
* Returns:
* 0 on success, or an error on failing to expand the array.
*/
-int drm_sched_job_add_implicit_dependencies(struct drm_sched_job *job,
- struct drm_gem_object *obj,
- bool write)
+int drm_sched_job_add_resv_dependencies(struct drm_sched_job *job,
+ struct dma_resv *resv,
+ enum dma_resv_usage usage)
{
struct dma_resv_iter cursor;
struct dma_fence *fence;
int ret;
- dma_resv_assert_held(obj->resv);
+ dma_resv_assert_held(resv);
- dma_resv_for_each_fence(&cursor, obj->resv, dma_resv_usage_rw(write),
- fence) {
+ dma_resv_for_each_fence(&cursor, resv, usage, fence) {
/* Make sure to grab an additional ref on the added fence */
dma_fence_get(fence);
ret = drm_sched_job_add_dependency(job, fence);
@@ -721,8 +740,31 @@ int drm_sched_job_add_implicit_dependencies(struct drm_sched_job *job,
}
return 0;
}
-EXPORT_SYMBOL(drm_sched_job_add_implicit_dependencies);
+EXPORT_SYMBOL(drm_sched_job_add_resv_dependencies);
+/**
+ * drm_sched_job_add_implicit_dependencies - adds implicit dependencies as job
+ * dependencies
+ * @job: scheduler job to add the dependencies to
+ * @obj: the gem object to add new dependencies from.
+ * @write: whether the job might write the object (so we need to depend on
+ * shared fences in the reservation object).
+ *
+ * This should be called after drm_gem_lock_reservations() on your array of
+ * GEM objects used in the job but before updating the reservations with your
+ * own fences.
+ *
+ * Returns:
+ * 0 on success, or an error on failing to expand the array.
+ */
+int drm_sched_job_add_implicit_dependencies(struct drm_sched_job *job,
+ struct drm_gem_object *obj,
+ bool write)
+{
+ return drm_sched_job_add_resv_dependencies(job, obj->resv,
+ dma_resv_usage_rw(write));
+}
+EXPORT_SYMBOL(drm_sched_job_add_implicit_dependencies);
/**
* drm_sched_job_cleanup - clean up scheduler job resources
@@ -803,7 +845,9 @@ drm_sched_select_entity(struct drm_gpu_scheduler *sched)
/* Kernel run queue has higher priority than normal run queue*/
for (i = DRM_SCHED_PRIORITY_COUNT - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) {
- entity = drm_sched_rq_select_entity(&sched->sched_rq[i]);
+ entity = drm_sched_policy == DRM_SCHED_POLICY_FIFO ?
+ drm_sched_rq_select_entity_fifo(&sched->sched_rq[i]) :
+ drm_sched_rq_select_entity_rr(&sched->sched_rq[i]);
if (entity)
break;
}
@@ -1082,13 +1126,15 @@ void drm_sched_fini(struct drm_gpu_scheduler *sched)
EXPORT_SYMBOL(drm_sched_fini);
/**
- * drm_sched_increase_karma_ext - Update sched_entity guilty flag
+ * drm_sched_increase_karma - Update sched_entity guilty flag
*
* @bad: The job guilty of time out
- * @type: type for increase/reset karma
*
+ * Increment on every hang caused by the 'bad' job. If this exceeds the hang
+ * limit of the scheduler then the respective sched entity is marked guilty and
+ * jobs from it will not be scheduled further
*/
-void drm_sched_increase_karma_ext(struct drm_sched_job *bad, int type)
+void drm_sched_increase_karma(struct drm_sched_job *bad)
{
int i;
struct drm_sched_entity *tmp;
@@ -1100,10 +1146,7 @@ void drm_sched_increase_karma_ext(struct drm_sched_job *bad, int type)
* corrupt but keep in mind that kernel jobs always considered good.
*/
if (bad->s_priority != DRM_SCHED_PRIORITY_KERNEL) {
- if (type == 0)
- atomic_set(&bad->karma, 0);
- else if (type == 1)
- atomic_inc(&bad->karma);
+ atomic_inc(&bad->karma);
for (i = DRM_SCHED_PRIORITY_MIN; i < DRM_SCHED_PRIORITY_KERNEL;
i++) {
@@ -1114,7 +1157,7 @@ void drm_sched_increase_karma_ext(struct drm_sched_job *bad, int type)
if (bad->s_fence->scheduled.context ==
entity->fence_context) {
if (entity->guilty)
- atomic_set(entity->guilty, type);
+ atomic_set(entity->guilty, 1);
break;
}
}
@@ -1124,4 +1167,4 @@ void drm_sched_increase_karma_ext(struct drm_sched_job *bad, int type)
}
}
}
-EXPORT_SYMBOL(drm_sched_increase_karma_ext);
+EXPORT_SYMBOL(drm_sched_increase_karma);
diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c
index bc41a5ae810a..53464afc2b9a 100644
--- a/drivers/gpu/drm/solomon/ssd130x.c
+++ b/drivers/gpu/drm/solomon/ssd130x.c
@@ -20,9 +20,10 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
@@ -578,21 +579,24 @@ static void ssd130x_primary_plane_helper_atomic_update(struct drm_plane *plane,
struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
+ struct drm_atomic_helper_damage_iter iter;
struct drm_device *drm = plane->dev;
- struct drm_rect src_clip, dst_clip;
+ struct drm_rect dst_clip;
+ struct drm_rect damage;
int idx;
- if (!drm_atomic_helper_damage_merged(old_plane_state, plane_state, &src_clip))
+ if (!drm_dev_enter(drm, &idx))
return;
- dst_clip = plane_state->dst;
- if (!drm_rect_intersect(&dst_clip, &src_clip))
- return;
+ drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_for_each_plane_damage(&iter, &damage) {
+ dst_clip = plane_state->dst;
- if (!drm_dev_enter(drm, &idx))
- return;
+ if (!drm_rect_intersect(&dst_clip, &damage))
+ continue;
- ssd130x_fb_blit_rect(plane_state->fb, &shadow_plane_state->data[0], &dst_clip);
+ ssd130x_fb_blit_rect(plane_state->fb, &shadow_plane_state->data[0], &dst_clip);
+ }
drm_dev_exit(idx);
}
@@ -642,19 +646,6 @@ static enum drm_mode_status ssd130x_crtc_helper_mode_valid(struct drm_crtc *crtc
return MODE_OK;
}
-static int ssd130x_crtc_helper_atomic_check(struct drm_crtc *crtc,
- struct drm_atomic_state *new_state)
-{
- struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
- int ret;
-
- ret = drm_atomic_helper_check_crtc_state(new_crtc_state, false);
- if (ret)
- return ret;
-
- return drm_atomic_add_affected_planes(new_state, crtc);
-}
-
/*
* The CRTC is always enabled. Screen updates are performed by
* the primary plane's atomic_update function. Disabling clears
@@ -662,7 +653,7 @@ static int ssd130x_crtc_helper_atomic_check(struct drm_crtc *crtc,
*/
static const struct drm_crtc_helper_funcs ssd130x_crtc_helper_funcs = {
.mode_valid = ssd130x_crtc_helper_mode_valid,
- .atomic_check = ssd130x_crtc_helper_atomic_check,
+ .atomic_check = drm_crtc_helper_atomic_check,
};
static void ssd130x_crtc_reset(struct drm_crtc *crtc)
diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c
index 7abf010a3293..ef6a4e63198f 100644
--- a/drivers/gpu/drm/sti/sti_drv.c
+++ b/drivers/gpu/drm/sti/sti_drv.c
@@ -14,7 +14,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_debugfs.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_of.h>
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index b6ee8a82e656..f3a5616b7daf 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -288,7 +288,7 @@ static void sti_dvo_set_mode(struct drm_bridge *bridge,
DRM_DEBUG_DRIVER("\n");
- memcpy(&dvo->mode, mode, sizeof(struct drm_display_mode));
+ drm_mode_copy(&dvo->mode, mode);
/* According to the path used (main or aux), the dvo clocks should
* have a different parent clock. */
diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
index 03cc401ed593..ec6656b9ee7c 100644
--- a/drivers/gpu/drm/sti/sti_hda.c
+++ b/drivers/gpu/drm/sti/sti_hda.c
@@ -524,7 +524,7 @@ static void sti_hda_set_mode(struct drm_bridge *bridge,
DRM_DEBUG_DRIVER("\n");
- memcpy(&hda->mode, mode, sizeof(struct drm_display_mode));
+ drm_mode_copy(&hda->mode, mode);
if (!hda_get_mode_idx(hda->mode, &mode_idx)) {
DRM_ERROR("Undefined mode\n");
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index cb82622877d2..fcc2194869d6 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -941,7 +941,7 @@ static void sti_hdmi_set_mode(struct drm_bridge *bridge,
DRM_DEBUG_DRIVER("\n");
/* Copy the drm display mode in the connector local structure */
- memcpy(&hdmi->mode, mode, sizeof(struct drm_display_mode));
+ drm_mode_copy(&hdmi->mode, mode);
/* Update clock framerate according to the selected mode */
ret = clk_set_rate(hdmi->clk_pix, mode->clock * 1000);
diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c
index d7914f5122df..50410bd99dfe 100644
--- a/drivers/gpu/drm/stm/drv.c
+++ b/drivers/gpu/drm/stm/drv.c
@@ -18,7 +18,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_module.h>
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index d06ffd99d86e..cc94efbbf2d4 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -17,7 +17,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_module.h>
#include <drm/drm_of.h>
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 34234a144e87..760ff05eabf4 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -1101,12 +1101,16 @@ static const struct component_ops sun6i_dsi_ops = {
static int sun6i_dsi_probe(struct platform_device *pdev)
{
+ const struct sun6i_dsi_variant *variant;
struct device *dev = &pdev->dev;
- const char *bus_clk_name = NULL;
struct sun6i_dsi *dsi;
void __iomem *base;
int ret;
+ variant = device_get_match_data(dev);
+ if (!variant)
+ return -EINVAL;
+
dsi = devm_kzalloc(dev, sizeof(*dsi), GFP_KERNEL);
if (!dsi)
return -ENOMEM;
@@ -1114,10 +1118,7 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
dsi->dev = dev;
dsi->host.ops = &sun6i_dsi_host_ops;
dsi->host.dev = dev;
-
- if (of_device_is_compatible(dev->of_node,
- "allwinner,sun6i-a31-mipi-dsi"))
- bus_clk_name = "bus";
+ dsi->variant = variant;
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base)) {
@@ -1142,7 +1143,7 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
return PTR_ERR(dsi->regs);
}
- dsi->bus_clk = devm_clk_get(dev, bus_clk_name);
+ dsi->bus_clk = devm_clk_get(dev, variant->has_mod_clk ? "bus" : NULL);
if (IS_ERR(dsi->bus_clk))
return dev_err_probe(dev, PTR_ERR(dsi->bus_clk),
"Couldn't get the DSI bus clock\n");
@@ -1151,21 +1152,21 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
if (ret)
return ret;
- if (of_device_is_compatible(dev->of_node,
- "allwinner,sun6i-a31-mipi-dsi")) {
+ if (variant->has_mod_clk) {
dsi->mod_clk = devm_clk_get(dev, "mod");
if (IS_ERR(dsi->mod_clk)) {
dev_err(dev, "Couldn't get the DSI mod clock\n");
ret = PTR_ERR(dsi->mod_clk);
goto err_attach_clk;
}
- }
- /*
- * In order to operate properly, that clock seems to be always
- * set to 297MHz.
- */
- clk_set_rate_exclusive(dsi->mod_clk, 297000000);
+ /*
+ * In order to operate properly, the module clock on the
+ * A31 variant always seems to be set to 297MHz.
+ */
+ if (variant->set_mod_clk)
+ clk_set_rate_exclusive(dsi->mod_clk, 297000000);
+ }
dsi->dphy = devm_phy_get(dev, "dphy");
if (IS_ERR(dsi->dphy)) {
@@ -1191,7 +1192,8 @@ static int sun6i_dsi_probe(struct platform_device *pdev)
err_remove_dsi_host:
mipi_dsi_host_unregister(&dsi->host);
err_unprotect_clk:
- clk_rate_exclusive_put(dsi->mod_clk);
+ if (dsi->variant->has_mod_clk && dsi->variant->set_mod_clk)
+ clk_rate_exclusive_put(dsi->mod_clk);
err_attach_clk:
regmap_mmio_detach_clk(dsi->regs);
@@ -1205,16 +1207,39 @@ static int sun6i_dsi_remove(struct platform_device *pdev)
component_del(&pdev->dev, &sun6i_dsi_ops);
mipi_dsi_host_unregister(&dsi->host);
- clk_rate_exclusive_put(dsi->mod_clk);
+ if (dsi->variant->has_mod_clk && dsi->variant->set_mod_clk)
+ clk_rate_exclusive_put(dsi->mod_clk);
regmap_mmio_detach_clk(dsi->regs);
return 0;
}
+static const struct sun6i_dsi_variant sun6i_a31_mipi_dsi_variant = {
+ .has_mod_clk = true,
+ .set_mod_clk = true,
+};
+
+static const struct sun6i_dsi_variant sun50i_a64_mipi_dsi_variant = {
+};
+
+static const struct sun6i_dsi_variant sun50i_a100_mipi_dsi_variant = {
+ .has_mod_clk = true,
+};
+
static const struct of_device_id sun6i_dsi_of_table[] = {
- { .compatible = "allwinner,sun6i-a31-mipi-dsi" },
- { .compatible = "allwinner,sun50i-a64-mipi-dsi" },
+ {
+ .compatible = "allwinner,sun6i-a31-mipi-dsi",
+ .data = &sun6i_a31_mipi_dsi_variant,
+ },
+ {
+ .compatible = "allwinner,sun50i-a64-mipi-dsi",
+ .data = &sun50i_a64_mipi_dsi_variant,
+ },
+ {
+ .compatible = "allwinner,sun50i-a100-mipi-dsi",
+ .data = &sun50i_a100_mipi_dsi_variant,
+ },
{ }
};
MODULE_DEVICE_TABLE(of, sun6i_dsi_of_table);
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
index c863900ae3b4..f1ddefe0f554 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.h
@@ -15,6 +15,11 @@
#define SUN6I_DSI_TCON_DIV 4
+struct sun6i_dsi_variant {
+ bool has_mod_clk;
+ bool set_mod_clk;
+};
+
struct sun6i_dsi {
struct drm_connector connector;
struct drm_encoder encoder;
@@ -31,6 +36,8 @@ struct sun6i_dsi {
struct mipi_dsi_device *device;
struct drm_device *drm;
struct drm_panel *panel;
+
+ const struct sun6i_dsi_variant *variant;
};
static inline struct sun6i_dsi *host_to_sun6i_dsi(struct mipi_dsi_host *host)
diff --git a/drivers/gpu/drm/tegra/Makefile b/drivers/gpu/drm/tegra/Makefile
index df6cc986aeba..bb0d2c144b55 100644
--- a/drivers/gpu/drm/tegra/Makefile
+++ b/drivers/gpu/drm/tegra/Makefile
@@ -24,7 +24,8 @@ tegra-drm-y := \
gr3d.o \
falcon.o \
vic.o \
- nvdec.o
+ nvdec.o \
+ riscv.o
tegra-drm-y += trace.o
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index bd0f60704467..a67453cee883 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -3205,8 +3205,10 @@ static int tegra_dc_probe(struct platform_device *pdev)
usleep_range(2000, 4000);
err = reset_control_assert(dc->rst);
- if (err < 0)
+ if (err < 0) {
+ clk_disable_unprepare(dc->clk);
return err;
+ }
usleep_range(2000, 4000);
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index a1f909dac89a..7bd2e65c2a16 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -1386,6 +1386,7 @@ static const struct of_device_id host1x_drm_subdevs[] = {
{ .compatible = "nvidia,tegra194-vic", },
{ .compatible = "nvidia,tegra194-nvdec", },
{ .compatible = "nvidia,tegra234-vic", },
+ { .compatible = "nvidia,tegra234-nvdec", },
{ /* sentinel */ }
};
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index 9291209154a7..a900300ae5bd 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -206,6 +206,8 @@ static int tegra_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
static const struct fb_ops tegra_fb_ops = {
.owner = THIS_MODULE,
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,
@@ -243,7 +245,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
if (IS_ERR(bo))
return PTR_ERR(bo);
- info = drm_fb_helper_alloc_fbi(helper);
+ info = drm_fb_helper_alloc_info(helper);
if (IS_ERR(info)) {
dev_err(drm->dev, "failed to allocate framebuffer info\n");
drm_gem_object_put(&bo->gem);
@@ -261,7 +263,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
fb = fbdev->fb;
helper->fb = fb;
- helper->fbdev = info;
+ helper->info = info;
info->fbops = &tegra_fb_ops;
@@ -280,7 +282,6 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
}
}
- drm->mode_config.fb_base = (resource_size_t)bo->iova;
info->screen_base = (void __iomem *)bo->vaddr + offset;
info->screen_size = size;
info->fix.smem_start = (unsigned long)(bo->iova + offset);
@@ -348,7 +349,7 @@ fini:
static void tegra_fbdev_exit(struct tegra_fbdev *fbdev)
{
- drm_fb_helper_unregister_fbi(&fbdev->base);
+ drm_fb_helper_unregister_info(&fbdev->base);
if (fbdev->fb) {
struct tegra_bo *bo = tegra_fb_get_plane(fbdev->fb, 0);
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index 81991090adcc..979e7bc902f6 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -84,7 +84,7 @@ static struct host1x_bo_mapping *tegra_bo_pin(struct device *dev, struct host1x_
goto free;
}
- map->sgt = dma_buf_map_attachment(map->attach, direction);
+ map->sgt = dma_buf_map_attachment_unlocked(map->attach, direction);
if (IS_ERR(map->sgt)) {
dma_buf_detach(buf, map->attach);
err = PTR_ERR(map->sgt);
@@ -160,7 +160,8 @@ free:
static void tegra_bo_unpin(struct host1x_bo_mapping *map)
{
if (map->attach) {
- dma_buf_unmap_attachment(map->attach, map->sgt, map->direction);
+ dma_buf_unmap_attachment_unlocked(map->attach, map->sgt,
+ map->direction);
dma_buf_detach(map->attach->dmabuf, map->attach);
} else {
dma_unmap_sgtable(map->dev, map->sgt, map->direction, 0);
@@ -181,7 +182,7 @@ static void *tegra_bo_mmap(struct host1x_bo *bo)
if (obj->vaddr) {
return obj->vaddr;
} else if (obj->gem.import_attach) {
- ret = dma_buf_vmap(obj->gem.import_attach->dmabuf, &map);
+ ret = dma_buf_vmap_unlocked(obj->gem.import_attach->dmabuf, &map);
return ret ? NULL : map.vaddr;
} else {
return vmap(obj->pages, obj->num_pages, VM_MAP,
@@ -197,7 +198,7 @@ static void tegra_bo_munmap(struct host1x_bo *bo, void *addr)
if (obj->vaddr)
return;
else if (obj->gem.import_attach)
- dma_buf_vunmap(obj->gem.import_attach->dmabuf, &map);
+ dma_buf_vunmap_unlocked(obj->gem.import_attach->dmabuf, &map);
else
vunmap(addr);
}
@@ -461,7 +462,7 @@ static struct tegra_bo *tegra_bo_import(struct drm_device *drm,
get_dma_buf(buf);
- bo->sgt = dma_buf_map_attachment(attach, DMA_TO_DEVICE);
+ bo->sgt = dma_buf_map_attachment_unlocked(attach, DMA_TO_DEVICE);
if (IS_ERR(bo->sgt)) {
err = PTR_ERR(bo->sgt);
goto detach;
@@ -479,7 +480,7 @@ static struct tegra_bo *tegra_bo_import(struct drm_device *drm,
detach:
if (!IS_ERR_OR_NULL(bo->sgt))
- dma_buf_unmap_attachment(attach, bo->sgt, DMA_TO_DEVICE);
+ dma_buf_unmap_attachment_unlocked(attach, bo->sgt, DMA_TO_DEVICE);
dma_buf_detach(buf, attach);
dma_buf_put(buf);
@@ -508,8 +509,8 @@ void tegra_bo_free_object(struct drm_gem_object *gem)
tegra_bo_iommu_unmap(tegra, bo);
if (gem->import_attach) {
- dma_buf_unmap_attachment(gem->import_attach, bo->sgt,
- DMA_TO_DEVICE);
+ dma_buf_unmap_attachment_unlocked(gem->import_attach, bo->sgt,
+ DMA_TO_DEVICE);
drm_prime_gem_destroy(gem, NULL);
} else {
tegra_bo_free(gem->dev, bo);
@@ -693,6 +694,8 @@ static int tegra_gem_prime_mmap(struct dma_buf *buf, struct vm_area_struct *vma)
struct drm_gem_object *gem = buf->priv;
int err;
+ dma_resv_assert_held(buf->resv);
+
err = drm_gem_mmap_obj(gem, gem->size, vma);
if (err < 0)
return err;
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index bf240767dad9..40ec3e6cf204 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -867,14 +867,7 @@ static int tegra_hdmi_reconfigure_audio(struct tegra_hdmi *hdmi)
static bool tegra_output_is_hdmi(struct tegra_output *output)
{
- struct edid *edid;
-
- if (!output->connector.edid_blob_ptr)
- return false;
-
- edid = (struct edid *)output->connector.edid_blob_ptr->data;
-
- return drm_detect_hdmi_monitor(edid);
+ return output->connector.display_info.is_hdmi;
}
static enum drm_connector_status
diff --git a/drivers/gpu/drm/tegra/nvdec.c b/drivers/gpu/drm/tegra/nvdec.c
index 276fe0472730..10fd21517281 100644
--- a/drivers/gpu/drm/tegra/nvdec.c
+++ b/drivers/gpu/drm/tegra/nvdec.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2015-2021, NVIDIA Corporation.
+ * Copyright (c) 2015-2022, NVIDIA Corporation.
*/
#include <linux/clk.h>
@@ -8,6 +8,7 @@
#include <linux/dma-mapping.h>
#include <linux/host1x.h>
#include <linux/iommu.h>
+#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
@@ -16,18 +17,22 @@
#include <linux/pm_runtime.h>
#include <linux/reset.h>
-#include <soc/tegra/pmc.h>
+#include <soc/tegra/mc.h>
#include "drm.h"
#include "falcon.h"
+#include "riscv.h"
#include "vic.h"
+#define NVDEC_FALCON_DEBUGINFO 0x1094
#define NVDEC_TFBIF_TRANSCFG 0x2c44
struct nvdec_config {
const char *firmware;
unsigned int version;
bool supports_sid;
+ bool has_riscv;
+ bool has_extra_clocks;
};
struct nvdec {
@@ -37,10 +42,16 @@ struct nvdec {
struct tegra_drm_client client;
struct host1x_channel *channel;
struct device *dev;
- struct clk *clk;
+ struct clk_bulk_data clks[3];
+ unsigned int num_clks;
+ struct reset_control *reset;
/* Platform configuration */
const struct nvdec_config *config;
+
+ /* RISC-V specific data */
+ struct tegra_drm_riscv riscv;
+ phys_addr_t carveout_base;
};
static inline struct nvdec *to_nvdec(struct tegra_drm_client *client)
@@ -54,7 +65,7 @@ static inline void nvdec_writel(struct nvdec *nvdec, u32 value,
writel(value, nvdec->regs + offset);
}
-static int nvdec_boot(struct nvdec *nvdec)
+static int nvdec_boot_falcon(struct nvdec *nvdec)
{
#ifdef CONFIG_IOMMU_API
struct iommu_fwspec *spec = dev_iommu_fwspec_get(nvdec->dev);
@@ -90,6 +101,64 @@ static int nvdec_boot(struct nvdec *nvdec)
return 0;
}
+static int nvdec_wait_debuginfo(struct nvdec *nvdec, const char *phase)
+{
+ int err;
+ u32 val;
+
+ err = readl_poll_timeout(nvdec->regs + NVDEC_FALCON_DEBUGINFO, val, val == 0x0, 10, 100000);
+ if (err) {
+ dev_err(nvdec->dev, "failed to boot %s, debuginfo=0x%x\n", phase, val);
+ return err;
+ }
+
+ return 0;
+}
+
+static int nvdec_boot_riscv(struct nvdec *nvdec)
+{
+ int err;
+
+ err = reset_control_acquire(nvdec->reset);
+ if (err)
+ return err;
+
+ nvdec_writel(nvdec, 0xabcd1234, NVDEC_FALCON_DEBUGINFO);
+
+ err = tegra_drm_riscv_boot_bootrom(&nvdec->riscv, nvdec->carveout_base, 1,
+ &nvdec->riscv.bl_desc);
+ if (err) {
+ dev_err(nvdec->dev, "failed to execute bootloader\n");
+ goto release_reset;
+ }
+
+ err = nvdec_wait_debuginfo(nvdec, "bootloader");
+ if (err)
+ goto release_reset;
+
+ err = reset_control_reset(nvdec->reset);
+ if (err)
+ goto release_reset;
+
+ nvdec_writel(nvdec, 0xabcd1234, NVDEC_FALCON_DEBUGINFO);
+
+ err = tegra_drm_riscv_boot_bootrom(&nvdec->riscv, nvdec->carveout_base, 1,
+ &nvdec->riscv.os_desc);
+ if (err) {
+ dev_err(nvdec->dev, "failed to execute firmware\n");
+ goto release_reset;
+ }
+
+ err = nvdec_wait_debuginfo(nvdec, "firmware");
+ if (err)
+ goto release_reset;
+
+release_reset:
+ reset_control_release(nvdec->reset);
+
+ return err;
+}
+
static int nvdec_init(struct host1x_client *client)
{
struct tegra_drm_client *drm = host1x_to_drm_client(client);
@@ -189,7 +258,7 @@ static const struct host1x_client_ops nvdec_client_ops = {
.exit = nvdec_exit,
};
-static int nvdec_load_firmware(struct nvdec *nvdec)
+static int nvdec_load_falcon_firmware(struct nvdec *nvdec)
{
struct host1x_client *client = &nvdec->client.base;
struct tegra_drm *tegra = nvdec->client.drm;
@@ -252,30 +321,35 @@ cleanup:
return err;
}
-
static __maybe_unused int nvdec_runtime_resume(struct device *dev)
{
struct nvdec *nvdec = dev_get_drvdata(dev);
int err;
- err = clk_prepare_enable(nvdec->clk);
+ err = clk_bulk_prepare_enable(nvdec->num_clks, nvdec->clks);
if (err < 0)
return err;
usleep_range(10, 20);
- err = nvdec_load_firmware(nvdec);
- if (err < 0)
- goto disable;
+ if (nvdec->config->has_riscv) {
+ err = nvdec_boot_riscv(nvdec);
+ if (err < 0)
+ goto disable;
+ } else {
+ err = nvdec_load_falcon_firmware(nvdec);
+ if (err < 0)
+ goto disable;
- err = nvdec_boot(nvdec);
- if (err < 0)
- goto disable;
+ err = nvdec_boot_falcon(nvdec);
+ if (err < 0)
+ goto disable;
+ }
return 0;
disable:
- clk_disable_unprepare(nvdec->clk);
+ clk_bulk_disable_unprepare(nvdec->num_clks, nvdec->clks);
return err;
}
@@ -285,7 +359,7 @@ static __maybe_unused int nvdec_runtime_suspend(struct device *dev)
host1x_channel_stop(nvdec->channel);
- clk_disable_unprepare(nvdec->clk);
+ clk_bulk_disable_unprepare(nvdec->num_clks, nvdec->clks);
return 0;
}
@@ -346,10 +420,18 @@ static const struct nvdec_config nvdec_t194_config = {
.supports_sid = true,
};
+static const struct nvdec_config nvdec_t234_config = {
+ .version = 0x23,
+ .supports_sid = true,
+ .has_riscv = true,
+ .has_extra_clocks = true,
+};
+
static const struct of_device_id tegra_nvdec_of_match[] = {
{ .compatible = "nvidia,tegra210-nvdec", .data = &nvdec_t210_config },
{ .compatible = "nvidia,tegra186-nvdec", .data = &nvdec_t186_config },
{ .compatible = "nvidia,tegra194-nvdec", .data = &nvdec_t194_config },
+ { .compatible = "nvidia,tegra234-nvdec", .data = &nvdec_t234_config },
{ },
};
MODULE_DEVICE_TABLE(of, tegra_nvdec_of_match);
@@ -383,13 +465,22 @@ static int nvdec_probe(struct platform_device *pdev)
if (IS_ERR(nvdec->regs))
return PTR_ERR(nvdec->regs);
- nvdec->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(nvdec->clk)) {
- dev_err(&pdev->dev, "failed to get clock\n");
- return PTR_ERR(nvdec->clk);
+ nvdec->clks[0].id = "nvdec";
+ nvdec->num_clks = 1;
+
+ if (nvdec->config->has_extra_clocks) {
+ nvdec->num_clks = 3;
+ nvdec->clks[1].id = "fuse";
+ nvdec->clks[2].id = "tsec_pka";
}
- err = clk_set_rate(nvdec->clk, ULONG_MAX);
+ err = devm_clk_bulk_get(dev, nvdec->num_clks, nvdec->clks);
+ if (err) {
+ dev_err(&pdev->dev, "failed to get clock(s)\n");
+ return err;
+ }
+
+ err = clk_set_rate(nvdec->clks[0].clk, ULONG_MAX);
if (err < 0) {
dev_err(&pdev->dev, "failed to set clock rate\n");
return err;
@@ -399,12 +490,42 @@ static int nvdec_probe(struct platform_device *pdev)
if (err < 0)
host_class = HOST1X_CLASS_NVDEC;
- nvdec->falcon.dev = dev;
- nvdec->falcon.regs = nvdec->regs;
+ if (nvdec->config->has_riscv) {
+ struct tegra_mc *mc;
- err = falcon_init(&nvdec->falcon);
- if (err < 0)
- return err;
+ mc = devm_tegra_memory_controller_get(dev);
+ if (IS_ERR(mc)) {
+ dev_err_probe(dev, PTR_ERR(mc),
+ "failed to get memory controller handle\n");
+ return PTR_ERR(mc);
+ }
+
+ err = tegra_mc_get_carveout_info(mc, 1, &nvdec->carveout_base, NULL);
+ if (err) {
+ dev_err(dev, "failed to get carveout info: %d\n", err);
+ return err;
+ }
+
+ nvdec->reset = devm_reset_control_get_exclusive_released(dev, "nvdec");
+ if (IS_ERR(nvdec->reset)) {
+ dev_err_probe(dev, PTR_ERR(nvdec->reset), "failed to get reset\n");
+ return PTR_ERR(nvdec->reset);
+ }
+
+ nvdec->riscv.dev = dev;
+ nvdec->riscv.regs = nvdec->regs;
+
+ err = tegra_drm_riscv_read_descriptors(&nvdec->riscv);
+ if (err < 0)
+ return err;
+ } else {
+ nvdec->falcon.dev = dev;
+ nvdec->falcon.regs = nvdec->regs;
+
+ err = falcon_init(&nvdec->falcon);
+ if (err < 0)
+ return err;
+ }
platform_set_drvdata(pdev, nvdec);
diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c
index 47d26b5d9945..a8925dcd7edd 100644
--- a/drivers/gpu/drm/tegra/output.c
+++ b/drivers/gpu/drm/tegra/output.c
@@ -133,11 +133,11 @@ int tegra_output_probe(struct tegra_output *output)
}
}
- output->hpd_gpio = devm_gpiod_get_from_of_node(output->dev,
- output->of_node,
- "nvidia,hpd-gpio", 0,
- GPIOD_IN,
- "HDMI hotplug detect");
+ output->hpd_gpio = devm_fwnode_gpiod_get(output->dev,
+ of_fwnode_handle(output->of_node),
+ "nvidia,hpd",
+ GPIOD_IN,
+ "HDMI hotplug detect");
if (IS_ERR(output->hpd_gpio)) {
if (PTR_ERR(output->hpd_gpio) != -ENOENT)
return PTR_ERR(output->hpd_gpio);
diff --git a/drivers/gpu/drm/tegra/riscv.c b/drivers/gpu/drm/tegra/riscv.c
new file mode 100644
index 000000000000..6580416408f8
--- /dev/null
+++ b/drivers/gpu/drm/tegra/riscv.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2022, NVIDIA Corporation.
+ */
+
+#include <linux/dev_printk.h>
+#include <linux/device.h>
+#include <linux/iopoll.h>
+#include <linux/of.h>
+
+#include "riscv.h"
+
+#define RISCV_CPUCTL 0x4388
+#define RISCV_CPUCTL_STARTCPU_TRUE (1 << 0)
+#define RISCV_BR_RETCODE 0x465c
+#define RISCV_BR_RETCODE_RESULT_V(x) ((x) & 0x3)
+#define RISCV_BR_RETCODE_RESULT_PASS_V 3
+#define RISCV_BCR_CTRL 0x4668
+#define RISCV_BCR_CTRL_CORE_SELECT_RISCV (1 << 4)
+#define RISCV_BCR_DMACFG 0x466c
+#define RISCV_BCR_DMACFG_TARGET_LOCAL_FB (0 << 0)
+#define RISCV_BCR_DMACFG_LOCK_LOCKED (1 << 31)
+#define RISCV_BCR_DMAADDR_PKCPARAM_LO 0x4670
+#define RISCV_BCR_DMAADDR_PKCPARAM_HI 0x4674
+#define RISCV_BCR_DMAADDR_FMCCODE_LO 0x4678
+#define RISCV_BCR_DMAADDR_FMCCODE_HI 0x467c
+#define RISCV_BCR_DMAADDR_FMCDATA_LO 0x4680
+#define RISCV_BCR_DMAADDR_FMCDATA_HI 0x4684
+#define RISCV_BCR_DMACFG_SEC 0x4694
+#define RISCV_BCR_DMACFG_SEC_GSCID(v) ((v) << 16)
+
+static void riscv_writel(struct tegra_drm_riscv *riscv, u32 value, u32 offset)
+{
+ writel(value, riscv->regs + offset);
+}
+
+int tegra_drm_riscv_read_descriptors(struct tegra_drm_riscv *riscv)
+{
+ struct tegra_drm_riscv_descriptor *bl = &riscv->bl_desc;
+ struct tegra_drm_riscv_descriptor *os = &riscv->os_desc;
+ const struct device_node *np = riscv->dev->of_node;
+ int err;
+
+#define READ_PROP(name, location) \
+ err = of_property_read_u32(np, name, location); \
+ if (err) { \
+ dev_err(riscv->dev, "failed to read " name ": %d\n", err); \
+ return err; \
+ }
+
+ READ_PROP("nvidia,bl-manifest-offset", &bl->manifest_offset);
+ READ_PROP("nvidia,bl-code-offset", &bl->code_offset);
+ READ_PROP("nvidia,bl-data-offset", &bl->data_offset);
+ READ_PROP("nvidia,os-manifest-offset", &os->manifest_offset);
+ READ_PROP("nvidia,os-code-offset", &os->code_offset);
+ READ_PROP("nvidia,os-data-offset", &os->data_offset);
+#undef READ_PROP
+
+ if (bl->manifest_offset == 0 && bl->code_offset == 0 &&
+ bl->data_offset == 0 && os->manifest_offset == 0 &&
+ os->code_offset == 0 && os->data_offset == 0) {
+ dev_err(riscv->dev, "descriptors not available\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int tegra_drm_riscv_boot_bootrom(struct tegra_drm_riscv *riscv, phys_addr_t image_address,
+ u32 gscid, const struct tegra_drm_riscv_descriptor *desc)
+{
+ phys_addr_t addr;
+ int err;
+ u32 val;
+
+ riscv_writel(riscv, RISCV_BCR_CTRL_CORE_SELECT_RISCV, RISCV_BCR_CTRL);
+
+ addr = image_address + desc->manifest_offset;
+ riscv_writel(riscv, lower_32_bits(addr >> 8), RISCV_BCR_DMAADDR_PKCPARAM_LO);
+ riscv_writel(riscv, upper_32_bits(addr >> 8), RISCV_BCR_DMAADDR_PKCPARAM_HI);
+
+ addr = image_address + desc->code_offset;
+ riscv_writel(riscv, lower_32_bits(addr >> 8), RISCV_BCR_DMAADDR_FMCCODE_LO);
+ riscv_writel(riscv, upper_32_bits(addr >> 8), RISCV_BCR_DMAADDR_FMCCODE_HI);
+
+ addr = image_address + desc->data_offset;
+ riscv_writel(riscv, lower_32_bits(addr >> 8), RISCV_BCR_DMAADDR_FMCDATA_LO);
+ riscv_writel(riscv, upper_32_bits(addr >> 8), RISCV_BCR_DMAADDR_FMCDATA_HI);
+
+ riscv_writel(riscv, RISCV_BCR_DMACFG_SEC_GSCID(gscid), RISCV_BCR_DMACFG_SEC);
+ riscv_writel(riscv,
+ RISCV_BCR_DMACFG_TARGET_LOCAL_FB | RISCV_BCR_DMACFG_LOCK_LOCKED, RISCV_BCR_DMACFG);
+
+ riscv_writel(riscv, RISCV_CPUCTL_STARTCPU_TRUE, RISCV_CPUCTL);
+
+ err = readl_poll_timeout(
+ riscv->regs + RISCV_BR_RETCODE, val,
+ RISCV_BR_RETCODE_RESULT_V(val) == RISCV_BR_RETCODE_RESULT_PASS_V,
+ 10, 100000);
+ if (err) {
+ dev_err(riscv->dev, "error during bootrom execution. BR_RETCODE=%d\n", val);
+ return err;
+ }
+
+ return 0;
+}
diff --git a/drivers/gpu/drm/tegra/riscv.h b/drivers/gpu/drm/tegra/riscv.h
new file mode 100644
index 000000000000..bbeb2db078b6
--- /dev/null
+++ b/drivers/gpu/drm/tegra/riscv.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2022, NVIDIA Corporation.
+ */
+
+#ifndef DRM_TEGRA_RISCV_H
+#define DRM_TEGRA_RISCV_H
+
+struct tegra_drm_riscv_descriptor {
+ u32 manifest_offset;
+ u32 code_offset;
+ u32 code_size;
+ u32 data_offset;
+ u32 data_size;
+};
+
+struct tegra_drm_riscv {
+ /* User initializes */
+ struct device *dev;
+ void __iomem *regs;
+
+ struct tegra_drm_riscv_descriptor bl_desc;
+ struct tegra_drm_riscv_descriptor os_desc;
+};
+
+int tegra_drm_riscv_read_descriptors(struct tegra_drm_riscv *riscv);
+int tegra_drm_riscv_boot_bootrom(struct tegra_drm_riscv *riscv, phys_addr_t image_address,
+ u32 gscid, const struct tegra_drm_riscv_descriptor *desc);
+
+#endif
diff --git a/drivers/gpu/drm/tegra/submit.c b/drivers/gpu/drm/tegra/submit.c
index b24738bdf3df..066f88564169 100644
--- a/drivers/gpu/drm/tegra/submit.c
+++ b/drivers/gpu/drm/tegra/submit.c
@@ -133,7 +133,7 @@ static void gather_bo_munmap(struct host1x_bo *host_bo, void *addr)
{
}
-const struct host1x_bo_ops gather_bo_ops = {
+static const struct host1x_bo_ops gather_bo_ops = {
.get = gather_bo_get,
.put = gather_bo_put,
.pin = gather_bo_pin,
@@ -169,14 +169,9 @@ static void *alloc_copy_user_array(void __user *from, size_t count, size_t size)
if (copy_len > 0x4000)
return ERR_PTR(-E2BIG);
- data = kvmalloc(copy_len, GFP_KERNEL);
- if (!data)
- return ERR_PTR(-ENOMEM);
-
- if (copy_from_user(data, from, copy_len)) {
- kvfree(data);
- return ERR_PTR(-EFAULT);
- }
+ data = vmemdup_user(from, copy_len);
+ if (IS_ERR(data))
+ return ERR_CAST(data);
return data;
}
diff --git a/drivers/gpu/drm/tegra/uapi.c b/drivers/gpu/drm/tegra/uapi.c
index a98239cb0e29..5adab6b22916 100644
--- a/drivers/gpu/drm/tegra/uapi.c
+++ b/drivers/gpu/drm/tegra/uapi.c
@@ -116,7 +116,7 @@ int tegra_drm_ioctl_channel_open(struct drm_device *drm, void *data, struct drm_
if (supported)
context->memory_context = host1x_memory_context_alloc(
- host, get_task_pid(current, PIDTYPE_TGID));
+ host, client->base.dev, get_task_pid(current, PIDTYPE_TGID));
if (IS_ERR(context->memory_context)) {
if (PTR_ERR(context->memory_context) != -EOPNOTSUPP) {
diff --git a/drivers/gpu/drm/tests/Makefile b/drivers/gpu/drm/tests/Makefile
index 91b70f7d2769..b29ef1085cad 100644
--- a/drivers/gpu/drm/tests/Makefile
+++ b/drivers/gpu/drm/tests/Makefile
@@ -1,5 +1,14 @@
# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_DRM_KUNIT_TEST) += drm_format_helper_test.o drm_damage_helper_test.o \
- drm_cmdline_parser_test.o drm_rect_test.o drm_format_test.o drm_plane_helper_test.o \
- drm_dp_mst_helper_test.o drm_framebuffer_test.o drm_buddy_test.o drm_mm_test.o
+obj-$(CONFIG_DRM_KUNIT_TEST) += \
+ drm_buddy_test.o \
+ drm_cmdline_parser_test.o \
+ drm_damage_helper_test.o \
+ drm_dp_mst_helper_test.o \
+ drm_format_helper_test.o \
+ drm_format_test.o \
+ drm_framebuffer_test.o \
+ drm_kunit_helpers.o \
+ drm_mm_test.o \
+ drm_plane_helper_test.o \
+ drm_rect_test.o
diff --git a/drivers/gpu/drm/tests/drm_buddy_test.c b/drivers/gpu/drm/tests/drm_buddy_test.c
index 62f69589a72d..f8ee714df396 100644
--- a/drivers/gpu/drm/tests/drm_buddy_test.c
+++ b/drivers/gpu/drm/tests/drm_buddy_test.c
@@ -726,11 +726,13 @@ static void drm_test_buddy_alloc_limit(struct kunit *test)
drm_buddy_fini(&mm);
}
-static int drm_buddy_init_test(struct kunit *test)
+static int drm_buddy_suite_init(struct kunit_suite *suite)
{
while (!random_seed)
random_seed = get_random_u32();
+ kunit_info(suite, "Testing DRM buddy manager, with random_seed=0x%x\n", random_seed);
+
return 0;
}
@@ -746,7 +748,7 @@ static struct kunit_case drm_buddy_tests[] = {
static struct kunit_suite drm_buddy_test_suite = {
.name = "drm_buddy",
- .init = drm_buddy_init_test,
+ .suite_init = drm_buddy_suite_init,
.test_cases = drm_buddy_tests,
};
diff --git a/drivers/gpu/drm/tests/drm_client_modeset_test.c b/drivers/gpu/drm/tests/drm_client_modeset_test.c
new file mode 100644
index 000000000000..362a5fbd82f5
--- /dev/null
+++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c
@@ -0,0 +1,98 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 Maxime Ripard <mripard@kernel.org>
+ */
+
+#include <kunit/test.h>
+
+#include <drm/drm_connector.h>
+#include <drm/drm_edid.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_modes.h>
+#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_probe_helper.h>
+
+#include "drm_kunit_helpers.h"
+
+struct drm_client_modeset_test_priv {
+ struct drm_device *drm;
+ struct drm_connector connector;
+};
+
+static int drm_client_modeset_connector_get_modes(struct drm_connector *connector)
+{
+ return drm_add_modes_noedid(connector, 1920, 1200);
+}
+
+static const struct drm_connector_helper_funcs drm_client_modeset_connector_helper_funcs = {
+ .get_modes = drm_client_modeset_connector_get_modes,
+};
+
+static const struct drm_connector_funcs drm_client_modeset_connector_funcs = {
+};
+
+static int drm_client_modeset_test_init(struct kunit *test)
+{
+ struct drm_client_modeset_test_priv *priv;
+ int ret;
+
+ priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ test->priv = priv;
+
+ priv->drm = drm_kunit_device_init(test, DRIVER_MODESET, "drm-client-modeset-test");
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->drm);
+
+ ret = drmm_connector_init(priv->drm, &priv->connector,
+ &drm_client_modeset_connector_funcs,
+ DRM_MODE_CONNECTOR_Unknown,
+ NULL);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ drm_connector_helper_add(&priv->connector, &drm_client_modeset_connector_helper_funcs);
+
+ return 0;
+}
+
+static void drm_test_pick_cmdline_res_1920_1080_60(struct kunit *test)
+{
+ struct drm_client_modeset_test_priv *priv = test->priv;
+ struct drm_device *drm = priv->drm;
+ struct drm_connector *connector = &priv->connector;
+ struct drm_cmdline_mode *cmdline_mode = &connector->cmdline_mode;
+ struct drm_display_mode *expected_mode, *mode;
+ const char *cmdline = "1920x1080@60";
+ int ret;
+
+ expected_mode = drm_mode_find_dmt(priv->drm, 1920, 1080, 60, false);
+ KUNIT_ASSERT_NOT_NULL(test, expected_mode);
+
+ KUNIT_ASSERT_TRUE(test,
+ drm_mode_parse_command_line_for_connector(cmdline,
+ connector,
+ cmdline_mode));
+
+ mutex_lock(&drm->mode_config.mutex);
+ ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);
+ mutex_unlock(&drm->mode_config.mutex);
+ KUNIT_ASSERT_GT(test, ret, 0);
+
+ mode = drm_connector_pick_cmdline_mode(connector);
+ KUNIT_ASSERT_NOT_NULL(test, mode);
+
+ KUNIT_EXPECT_TRUE(test, drm_mode_equal(expected_mode, mode));
+}
+
+static struct kunit_case drm_test_pick_cmdline_tests[] = {
+ KUNIT_CASE(drm_test_pick_cmdline_res_1920_1080_60),
+ {}
+};
+
+static struct kunit_suite drm_test_pick_cmdline_test_suite = {
+ .name = "drm_test_pick_cmdline",
+ .init = drm_client_modeset_test_init,
+ .test_cases = drm_test_pick_cmdline_tests
+};
+
+kunit_test_suite(drm_test_pick_cmdline_test_suite);
diff --git a/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c b/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
index 65c9d225b558..545beea33e8c 100644
--- a/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_dp_mst_helper_test.c
@@ -5,44 +5,280 @@
* Copyright (c) 2022 Maíra Canal <mairacanal@riseup.net>
*/
-#define PREFIX_STR "[drm_dp_mst_helper]"
-
#include <kunit/test.h>
-#include <linux/random.h>
-
#include <drm/display/drm_dp_mst_helper.h>
#include <drm/drm_print.h>
#include "../display/drm_dp_mst_topology_internal.h"
+struct drm_dp_mst_calc_pbn_mode_test {
+ const int clock;
+ const int bpp;
+ const bool dsc;
+ const int expected;
+};
+
+static const struct drm_dp_mst_calc_pbn_mode_test drm_dp_mst_calc_pbn_mode_cases[] = {
+ {
+ .clock = 154000,
+ .bpp = 30,
+ .dsc = false,
+ .expected = 689
+ },
+ {
+ .clock = 234000,
+ .bpp = 30,
+ .dsc = false,
+ .expected = 1047
+ },
+ {
+ .clock = 297000,
+ .bpp = 24,
+ .dsc = false,
+ .expected = 1063
+ },
+ {
+ .clock = 332880,
+ .bpp = 24,
+ .dsc = true,
+ .expected = 50
+ },
+ {
+ .clock = 324540,
+ .bpp = 24,
+ .dsc = true,
+ .expected = 49
+ },
+};
+
static void drm_test_dp_mst_calc_pbn_mode(struct kunit *test)
{
- int pbn, i;
- const struct {
- int rate;
- int bpp;
- int expected;
- bool dsc;
- } test_params[] = {
- { 154000, 30, 689, false },
- { 234000, 30, 1047, false },
- { 297000, 24, 1063, false },
- { 332880, 24, 50, true },
- { 324540, 24, 49, true },
- };
+ const struct drm_dp_mst_calc_pbn_mode_test *params = test->param_value;
- for (i = 0; i < ARRAY_SIZE(test_params); i++) {
- pbn = drm_dp_calc_pbn_mode(test_params[i].rate,
- test_params[i].bpp,
- test_params[i].dsc);
- KUNIT_EXPECT_EQ_MSG(test, pbn, test_params[i].expected,
- "Expected PBN %d for clock %d bpp %d, got %d\n",
- test_params[i].expected, test_params[i].rate,
- test_params[i].bpp, pbn);
- }
+ KUNIT_EXPECT_EQ(test, drm_dp_calc_pbn_mode(params->clock, params->bpp, params->dsc),
+ params->expected);
}
+static void dp_mst_calc_pbn_mode_desc(const struct drm_dp_mst_calc_pbn_mode_test *t, char *desc)
+{
+ sprintf(desc, "Clock %d BPP %d DSC %s", t->clock, t->bpp, t->dsc ? "enabled" : "disabled");
+}
+
+KUNIT_ARRAY_PARAM(drm_dp_mst_calc_pbn_mode, drm_dp_mst_calc_pbn_mode_cases,
+ dp_mst_calc_pbn_mode_desc);
+
+static u8 data[] = { 0xff, 0x00, 0xdd };
+
+struct drm_dp_mst_sideband_msg_req_test {
+ const char *desc;
+ const struct drm_dp_sideband_msg_req_body in;
+};
+
+static const struct drm_dp_mst_sideband_msg_req_test drm_dp_mst_sideband_msg_req_cases[] = {
+ {
+ .desc = "DP_ENUM_PATH_RESOURCES with port number",
+ .in = {
+ .req_type = DP_ENUM_PATH_RESOURCES,
+ .u.port_num.port_number = 5,
+ },
+ },
+ {
+ .desc = "DP_POWER_UP_PHY with port number",
+ .in = {
+ .req_type = DP_POWER_UP_PHY,
+ .u.port_num.port_number = 5,
+ },
+ },
+ {
+ .desc = "DP_POWER_DOWN_PHY with port number",
+ .in = {
+ .req_type = DP_POWER_DOWN_PHY,
+ .u.port_num.port_number = 5,
+ },
+ },
+ {
+ .desc = "DP_ALLOCATE_PAYLOAD with SDP stream sinks",
+ .in = {
+ .req_type = DP_ALLOCATE_PAYLOAD,
+ .u.allocate_payload.number_sdp_streams = 3,
+ .u.allocate_payload.sdp_stream_sink = { 1, 2, 3 },
+ },
+ },
+ {
+ .desc = "DP_ALLOCATE_PAYLOAD with port number",
+ .in = {
+ .req_type = DP_ALLOCATE_PAYLOAD,
+ .u.allocate_payload.port_number = 0xf,
+ },
+ },
+ {
+ .desc = "DP_ALLOCATE_PAYLOAD with VCPI",
+ .in = {
+ .req_type = DP_ALLOCATE_PAYLOAD,
+ .u.allocate_payload.vcpi = 0x7f,
+ },
+ },
+ {
+ .desc = "DP_ALLOCATE_PAYLOAD with PBN",
+ .in = {
+ .req_type = DP_ALLOCATE_PAYLOAD,
+ .u.allocate_payload.pbn = U16_MAX,
+ },
+ },
+ {
+ .desc = "DP_QUERY_PAYLOAD with port number",
+ .in = {
+ .req_type = DP_QUERY_PAYLOAD,
+ .u.query_payload.port_number = 0xf,
+ },
+ },
+ {
+ .desc = "DP_QUERY_PAYLOAD with VCPI",
+ .in = {
+ .req_type = DP_QUERY_PAYLOAD,
+ .u.query_payload.vcpi = 0x7f,
+ },
+ },
+ {
+ .desc = "DP_REMOTE_DPCD_READ with port number",
+ .in = {
+ .req_type = DP_REMOTE_DPCD_READ,
+ .u.dpcd_read.port_number = 0xf,
+ },
+ },
+ {
+ .desc = "DP_REMOTE_DPCD_READ with DPCD address",
+ .in = {
+ .req_type = DP_REMOTE_DPCD_READ,
+ .u.dpcd_read.dpcd_address = 0xfedcb,
+ },
+ },
+ {
+ .desc = "DP_REMOTE_DPCD_READ with max number of bytes",
+ .in = {
+ .req_type = DP_REMOTE_DPCD_READ,
+ .u.dpcd_read.num_bytes = U8_MAX,
+ },
+ },
+ {
+ .desc = "DP_REMOTE_DPCD_WRITE with port number",
+ .in = {
+ .req_type = DP_REMOTE_DPCD_WRITE,
+ .u.dpcd_write.port_number = 0xf,
+ },
+ },
+ {
+ .desc = "DP_REMOTE_DPCD_WRITE with DPCD address",
+ .in = {
+ .req_type = DP_REMOTE_DPCD_WRITE,
+ .u.dpcd_write.dpcd_address = 0xfedcb,
+ },
+ },
+ {
+ .desc = "DP_REMOTE_DPCD_WRITE with data array",
+ .in = {
+ .req_type = DP_REMOTE_DPCD_WRITE,
+ .u.dpcd_write.num_bytes = ARRAY_SIZE(data),
+ .u.dpcd_write.bytes = data,
+ },
+ },
+ {
+ .desc = "DP_REMOTE_I2C_READ with port number",
+ .in = {
+ .req_type = DP_REMOTE_I2C_READ,
+ .u.i2c_read.port_number = 0xf,
+ },
+ },
+ {
+ .desc = "DP_REMOTE_I2C_READ with I2C device ID",
+ .in = {
+ .req_type = DP_REMOTE_I2C_READ,
+ .u.i2c_read.read_i2c_device_id = 0x7f,
+ },
+ },
+ {
+ .desc = "DP_REMOTE_I2C_READ with transactions array",
+ .in = {
+ .req_type = DP_REMOTE_I2C_READ,
+ .u.i2c_read.num_transactions = 3,
+ .u.i2c_read.num_bytes_read = ARRAY_SIZE(data) * 3,
+ .u.i2c_read.transactions = {
+ { .bytes = data, .num_bytes = ARRAY_SIZE(data), .i2c_dev_id = 0x7f,
+ .i2c_transaction_delay = 0xf, },
+ { .bytes = data, .num_bytes = ARRAY_SIZE(data), .i2c_dev_id = 0x7e,
+ .i2c_transaction_delay = 0xe, },
+ { .bytes = data, .num_bytes = ARRAY_SIZE(data), .i2c_dev_id = 0x7d,
+ .i2c_transaction_delay = 0xd, },
+ },
+ },
+ },
+ {
+ .desc = "DP_REMOTE_I2C_WRITE with port number",
+ .in = {
+ .req_type = DP_REMOTE_I2C_WRITE,
+ .u.i2c_write.port_number = 0xf,
+ },
+ },
+ {
+ .desc = "DP_REMOTE_I2C_WRITE with I2C device ID",
+ .in = {
+ .req_type = DP_REMOTE_I2C_WRITE,
+ .u.i2c_write.write_i2c_device_id = 0x7f,
+ },
+ },
+ {
+ .desc = "DP_REMOTE_I2C_WRITE with data array",
+ .in = {
+ .req_type = DP_REMOTE_I2C_WRITE,
+ .u.i2c_write.num_bytes = ARRAY_SIZE(data),
+ .u.i2c_write.bytes = data,
+ },
+ },
+ {
+ .desc = "DP_QUERY_STREAM_ENC_STATUS with stream ID",
+ .in = {
+ .req_type = DP_QUERY_STREAM_ENC_STATUS,
+ .u.enc_status.stream_id = 1,
+ },
+ },
+ {
+ .desc = "DP_QUERY_STREAM_ENC_STATUS with client ID",
+ .in = {
+ .req_type = DP_QUERY_STREAM_ENC_STATUS,
+ .u.enc_status.client_id = { 0x4f, 0x7f, 0xb4, 0x00, 0x8c, 0x0d, 0x67 },
+ },
+ },
+ {
+ .desc = "DP_QUERY_STREAM_ENC_STATUS with stream event",
+ .in = {
+ .req_type = DP_QUERY_STREAM_ENC_STATUS,
+ .u.enc_status.stream_event = 3,
+ },
+ },
+ {
+ .desc = "DP_QUERY_STREAM_ENC_STATUS with valid stream event",
+ .in = {
+ .req_type = DP_QUERY_STREAM_ENC_STATUS,
+ .u.enc_status.valid_stream_event = 0,
+ },
+ },
+ {
+ .desc = "DP_QUERY_STREAM_ENC_STATUS with stream behavior",
+ .in = {
+ .req_type = DP_QUERY_STREAM_ENC_STATUS,
+ .u.enc_status.stream_behavior = 3,
+ },
+ },
+ {
+ .desc = "DP_QUERY_STREAM_ENC_STATUS with a valid stream behavior",
+ .in = {
+ .req_type = DP_QUERY_STREAM_ENC_STATUS,
+ .u.enc_status.valid_stream_behavior = 1,
+ }
+ },
+};
+
static bool
sideband_msg_req_equal(const struct drm_dp_sideband_msg_req_body *in,
const struct drm_dp_sideband_msg_req_body *out)
@@ -118,41 +354,41 @@ sideband_msg_req_equal(const struct drm_dp_sideband_msg_req_body *in,
return true;
}
-static bool
-sideband_msg_req_encode_decode(struct drm_dp_sideband_msg_req_body *in)
+static void drm_test_dp_mst_msg_printf(struct drm_printer *p, struct va_format *vaf)
{
+ struct kunit *test = p->arg;
+
+ kunit_err(test, "%pV", vaf);
+}
+
+static void drm_test_dp_mst_sideband_msg_req_decode(struct kunit *test)
+{
+ const struct drm_dp_mst_sideband_msg_req_test *params = test->param_value;
+ const struct drm_dp_sideband_msg_req_body *in = &params->in;
struct drm_dp_sideband_msg_req_body *out;
- struct drm_printer p = drm_err_printer(PREFIX_STR);
struct drm_dp_sideband_msg_tx *txmsg;
- int i, ret;
- bool result = true;
+ struct drm_printer p = {
+ .printfn = drm_test_dp_mst_msg_printf,
+ .arg = test
+ };
+ int i;
- out = kzalloc(sizeof(*out), GFP_KERNEL);
- if (!out)
- return false;
+ out = kunit_kzalloc(test, sizeof(*out), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, out);
- txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL);
- if (!txmsg) {
- kfree(out);
- return false;
- }
+ txmsg = kunit_kzalloc(test, sizeof(*txmsg), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, txmsg);
drm_dp_encode_sideband_req(in, txmsg);
- ret = drm_dp_decode_sideband_req(txmsg, out);
- if (ret < 0) {
- drm_printf(&p, "Failed to decode sideband request: %d\n",
- ret);
- result = false;
- goto out;
- }
+ KUNIT_EXPECT_GE_MSG(test, drm_dp_decode_sideband_req(txmsg, out), 0,
+ "Failed to decode sideband request");
if (!sideband_msg_req_equal(in, out)) {
- drm_printf(&p, "Encode/decode failed, expected:\n");
+ KUNIT_FAIL(test, "Encode/decode failed");
+ kunit_err(test, "Expected:");
drm_dp_dump_sideband_msg_req_body(in, 1, &p);
- drm_printf(&p, "Got:\n");
+ kunit_err(test, "Got:");
drm_dp_dump_sideband_msg_req_body(out, 1, &p);
- result = false;
- goto out;
}
switch (in->req_type) {
@@ -167,112 +403,21 @@ sideband_msg_req_encode_decode(struct drm_dp_sideband_msg_req_body *in)
kfree(out->u.i2c_write.bytes);
break;
}
-
- /* Clear everything but the req_type for the input */
- memset(&in->u, 0, sizeof(in->u));
-
-out:
- kfree(out);
- kfree(txmsg);
- return result;
}
-static void drm_test_dp_mst_sideband_msg_req_decode(struct kunit *test)
+static void
+drm_dp_mst_sideband_msg_req_desc(const struct drm_dp_mst_sideband_msg_req_test *t, char *desc)
{
- struct drm_dp_sideband_msg_req_body in = { 0 };
- u8 data[] = { 0xff, 0x0, 0xdd };
- int i;
-
- in.req_type = DP_ENUM_PATH_RESOURCES;
- in.u.port_num.port_number = 5;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
-
- in.req_type = DP_POWER_UP_PHY;
- in.u.port_num.port_number = 5;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
-
- in.req_type = DP_POWER_DOWN_PHY;
- in.u.port_num.port_number = 5;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
-
- in.req_type = DP_ALLOCATE_PAYLOAD;
- in.u.allocate_payload.number_sdp_streams = 3;
- for (i = 0; i < in.u.allocate_payload.number_sdp_streams; i++)
- in.u.allocate_payload.sdp_stream_sink[i] = i + 1;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
- in.u.allocate_payload.port_number = 0xf;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
- in.u.allocate_payload.vcpi = 0x7f;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
- in.u.allocate_payload.pbn = U16_MAX;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
-
- in.req_type = DP_QUERY_PAYLOAD;
- in.u.query_payload.port_number = 0xf;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
- in.u.query_payload.vcpi = 0x7f;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
-
- in.req_type = DP_REMOTE_DPCD_READ;
- in.u.dpcd_read.port_number = 0xf;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
- in.u.dpcd_read.dpcd_address = 0xfedcb;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
- in.u.dpcd_read.num_bytes = U8_MAX;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
-
- in.req_type = DP_REMOTE_DPCD_WRITE;
- in.u.dpcd_write.port_number = 0xf;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
- in.u.dpcd_write.dpcd_address = 0xfedcb;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
- in.u.dpcd_write.num_bytes = ARRAY_SIZE(data);
- in.u.dpcd_write.bytes = data;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
-
- in.req_type = DP_REMOTE_I2C_READ;
- in.u.i2c_read.port_number = 0xf;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
- in.u.i2c_read.read_i2c_device_id = 0x7f;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
- in.u.i2c_read.num_transactions = 3;
- in.u.i2c_read.num_bytes_read = ARRAY_SIZE(data) * 3;
- for (i = 0; i < in.u.i2c_read.num_transactions; i++) {
- in.u.i2c_read.transactions[i].bytes = data;
- in.u.i2c_read.transactions[i].num_bytes = ARRAY_SIZE(data);
- in.u.i2c_read.transactions[i].i2c_dev_id = 0x7f & ~i;
- in.u.i2c_read.transactions[i].i2c_transaction_delay = 0xf & ~i;
- }
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
-
- in.req_type = DP_REMOTE_I2C_WRITE;
- in.u.i2c_write.port_number = 0xf;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
- in.u.i2c_write.write_i2c_device_id = 0x7f;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
- in.u.i2c_write.num_bytes = ARRAY_SIZE(data);
- in.u.i2c_write.bytes = data;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
-
- in.req_type = DP_QUERY_STREAM_ENC_STATUS;
- in.u.enc_status.stream_id = 1;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
- get_random_bytes(in.u.enc_status.client_id,
- sizeof(in.u.enc_status.client_id));
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
- in.u.enc_status.stream_event = 3;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
- in.u.enc_status.valid_stream_event = 0;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
- in.u.enc_status.stream_behavior = 3;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
- in.u.enc_status.valid_stream_behavior = 1;
- KUNIT_EXPECT_TRUE(test, sideband_msg_req_encode_decode(&in));
+ strcpy(desc, t->desc);
}
+KUNIT_ARRAY_PARAM(drm_dp_mst_sideband_msg_req, drm_dp_mst_sideband_msg_req_cases,
+ drm_dp_mst_sideband_msg_req_desc);
+
static struct kunit_case drm_dp_mst_helper_tests[] = {
- KUNIT_CASE(drm_test_dp_mst_calc_pbn_mode),
- KUNIT_CASE(drm_test_dp_mst_sideband_msg_req_decode),
+ KUNIT_CASE_PARAM(drm_test_dp_mst_calc_pbn_mode, drm_dp_mst_calc_pbn_mode_gen_params),
+ KUNIT_CASE_PARAM(drm_test_dp_mst_sideband_msg_req_decode,
+ drm_dp_mst_sideband_msg_req_gen_params),
{ }
};
diff --git a/drivers/gpu/drm/tests/drm_format_helper_test.c b/drivers/gpu/drm/tests/drm_format_helper_test.c
index 2191e57f2297..567c71f95edc 100644
--- a/drivers/gpu/drm/tests/drm_format_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_format_helper_test.c
@@ -315,7 +315,7 @@ static void drm_test_fb_xrgb8888_to_gray8(struct kunit *test)
iosys_map_set_vaddr(&src, xrgb8888);
drm_fb_xrgb8888_to_gray8(&dst, &result->dst_pitch, &src, &fb, &params->clip);
- KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);
+ KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
}
static void drm_test_fb_xrgb8888_to_rgb332(struct kunit *test)
@@ -345,7 +345,7 @@ static void drm_test_fb_xrgb8888_to_rgb332(struct kunit *test)
iosys_map_set_vaddr(&src, xrgb8888);
drm_fb_xrgb8888_to_rgb332(&dst, &result->dst_pitch, &src, &fb, &params->clip);
- KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);
+ KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
}
static void drm_test_fb_xrgb8888_to_rgb565(struct kunit *test)
@@ -375,10 +375,10 @@ static void drm_test_fb_xrgb8888_to_rgb565(struct kunit *test)
iosys_map_set_vaddr(&src, xrgb8888);
drm_fb_xrgb8888_to_rgb565(&dst, &result->dst_pitch, &src, &fb, &params->clip, false);
- KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);
+ KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
drm_fb_xrgb8888_to_rgb565(&dst, &result->dst_pitch, &src, &fb, &params->clip, true);
- KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected_swab, dst_size), 0);
+ KUNIT_EXPECT_MEMEQ(test, buf, result->expected_swab, dst_size);
}
static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test)
@@ -408,7 +408,7 @@ static void drm_test_fb_xrgb8888_to_rgb888(struct kunit *test)
iosys_map_set_vaddr(&src, xrgb8888);
drm_fb_xrgb8888_to_rgb888(&dst, &result->dst_pitch, &src, &fb, &params->clip);
- KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);
+ KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
}
static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test)
@@ -439,7 +439,7 @@ static void drm_test_fb_xrgb8888_to_xrgb2101010(struct kunit *test)
drm_fb_xrgb8888_to_xrgb2101010(&dst, &result->dst_pitch, &src, &fb, &params->clip);
buf = le32buf_to_cpu(test, buf, dst_size / sizeof(u32));
- KUNIT_EXPECT_EQ(test, memcmp(buf, result->expected, dst_size), 0);
+ KUNIT_EXPECT_MEMEQ(test, buf, result->expected, dst_size);
}
static struct kunit_case drm_format_helper_test_cases[] = {
diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.c b/drivers/gpu/drm/tests/drm_kunit_helpers.c
new file mode 100644
index 000000000000..f1662091f250
--- /dev/null
+++ b/drivers/gpu/drm/tests/drm_kunit_helpers.c
@@ -0,0 +1,71 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <drm/drm_drv.h>
+#include <drm/drm_managed.h>
+
+#include <kunit/resource.h>
+
+#include <linux/device.h>
+
+#include "drm_kunit_helpers.h"
+
+struct kunit_dev {
+ struct drm_device base;
+};
+
+static const struct drm_mode_config_funcs drm_mode_config_funcs = {
+};
+
+static int dev_init(struct kunit_resource *res, void *ptr)
+{
+ char *name = ptr;
+ struct device *dev;
+
+ dev = root_device_register(name);
+ if (IS_ERR(dev))
+ return PTR_ERR(dev);
+
+ res->data = dev;
+ return 0;
+}
+
+static void dev_free(struct kunit_resource *res)
+{
+ struct device *dev = res->data;
+
+ root_device_unregister(dev);
+}
+
+struct drm_device *drm_kunit_device_init(struct kunit *test, u32 features, char *name)
+{
+ struct kunit_dev *kdev;
+ struct drm_device *drm;
+ struct drm_driver *driver;
+ struct device *dev;
+ int ret;
+
+ dev = kunit_alloc_resource(test, dev_init, dev_free, GFP_KERNEL, name);
+ if (!dev)
+ return ERR_PTR(-ENOMEM);
+
+ driver = kunit_kzalloc(test, sizeof(*driver), GFP_KERNEL);
+ if (!driver)
+ return ERR_PTR(-ENOMEM);
+
+ driver->driver_features = features;
+ kdev = devm_drm_dev_alloc(dev, driver, struct kunit_dev, base);
+ if (IS_ERR(kdev))
+ return ERR_CAST(kdev);
+
+ drm = &kdev->base;
+ drm->mode_config.funcs = &drm_mode_config_funcs;
+
+ ret = drmm_mode_config_init(drm);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return drm;
+}
+
+MODULE_AUTHOR("Maxime Ripard <maxime@cerno.tech>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tests/drm_kunit_helpers.h b/drivers/gpu/drm/tests/drm_kunit_helpers.h
new file mode 100644
index 000000000000..20ab6eec4c89
--- /dev/null
+++ b/drivers/gpu/drm/tests/drm_kunit_helpers.h
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#ifndef DRM_KUNIT_HELPERS_H_
+#define DRM_KUNIT_HELPERS_H_
+
+struct drm_device;
+struct kunit;
+
+struct drm_device *drm_kunit_device_init(struct kunit *test, u32 features, char *name);
+
+#endif // DRM_KUNIT_HELPERS_H_
diff --git a/drivers/gpu/drm/tests/drm_mm_test.c b/drivers/gpu/drm/tests/drm_mm_test.c
index c4b66eeae203..89f12d3b4a21 100644
--- a/drivers/gpu/drm/tests/drm_mm_test.c
+++ b/drivers/gpu/drm/tests/drm_mm_test.c
@@ -2209,11 +2209,15 @@ err_nodes:
vfree(nodes);
}
-static int drm_mm_init_test(struct kunit *test)
+static int drm_mm_suite_init(struct kunit_suite *suite)
{
while (!random_seed)
random_seed = get_random_u32();
+ kunit_info(suite,
+ "Testing DRM range manager, with random_seed=0x%x max_iterations=%u max_prime=%u\n",
+ random_seed, max_iterations, max_prime);
+
return 0;
}
@@ -2246,7 +2250,7 @@ static struct kunit_case drm_mm_tests[] = {
static struct kunit_suite drm_mm_test_suite = {
.name = "drm_mm",
- .init = drm_mm_init_test,
+ .suite_init = drm_mm_suite_init,
.test_cases = drm_mm_tests,
};
diff --git a/drivers/gpu/drm/tests/drm_plane_helper_test.c b/drivers/gpu/drm/tests/drm_plane_helper_test.c
index ec71af791f1f..0f392146b233 100644
--- a/drivers/gpu/drm/tests/drm_plane_helper_test.c
+++ b/drivers/gpu/drm/tests/drm_plane_helper_test.c
@@ -10,225 +10,306 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_modes.h>
+#include <drm/drm_rect.h>
-static void set_src(struct drm_plane_state *plane_state,
- unsigned int src_x, unsigned int src_y,
- unsigned int src_w, unsigned int src_h)
+static const struct drm_crtc_state crtc_state = {
+ .crtc = ZERO_SIZE_PTR,
+ .enable = true,
+ .active = true,
+ .mode = {
+ DRM_MODE("1024x768", 0, 65000, 1024, 1048,
+ 1184, 1344, 0, 768, 771, 777, 806, 0,
+ DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)
+ },
+};
+
+struct drm_check_plane_state_test {
+ const char *name;
+ const char *msg;
+ struct {
+ unsigned int x;
+ unsigned int y;
+ unsigned int w;
+ unsigned int h;
+ } src, src_expected;
+ struct {
+ int x;
+ int y;
+ unsigned int w;
+ unsigned int h;
+ } crtc, crtc_expected;
+ unsigned int rotation;
+ int min_scale;
+ int max_scale;
+ bool can_position;
+};
+
+static int drm_plane_helper_init(struct kunit *test)
{
- plane_state->src_x = src_x;
- plane_state->src_y = src_y;
- plane_state->src_w = src_w;
- plane_state->src_h = src_h;
+ const struct drm_check_plane_state_test *params = test->param_value;
+ struct drm_plane *plane;
+ struct drm_framebuffer *fb;
+ struct drm_plane_state *mock;
+
+ plane = kunit_kzalloc(test, sizeof(*plane), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, plane);
+
+ fb = kunit_kzalloc(test, sizeof(*fb), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, fb);
+ fb->width = 2048;
+ fb->height = 2048;
+
+ mock = kunit_kzalloc(test, sizeof(*mock), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, mock);
+ mock->plane = plane;
+ mock->crtc = ZERO_SIZE_PTR;
+ mock->fb = fb;
+ mock->rotation = params->rotation;
+ mock->src_x = params->src.x;
+ mock->src_y = params->src.y;
+ mock->src_w = params->src.w;
+ mock->src_h = params->src.h;
+ mock->crtc_x = params->crtc.x;
+ mock->crtc_y = params->crtc.y;
+ mock->crtc_w = params->crtc.w;
+ mock->crtc_h = params->crtc.h;
+
+ test->priv = mock;
+
+ return 0;
}
-static bool check_src_eq(struct drm_plane_state *plane_state,
+static void check_src_eq(struct kunit *test, struct drm_plane_state *plane_state,
unsigned int src_x, unsigned int src_y,
unsigned int src_w, unsigned int src_h)
{
- if (plane_state->src.x1 < 0) {
- pr_err("src x coordinate %x should never be below 0.\n", plane_state->src.x1);
- drm_rect_debug_print("src: ", &plane_state->src, true);
- return false;
- }
- if (plane_state->src.y1 < 0) {
- pr_err("src y coordinate %x should never be below 0.\n", plane_state->src.y1);
- drm_rect_debug_print("src: ", &plane_state->src, true);
- return false;
- }
-
- if (plane_state->src.x1 != src_x ||
- plane_state->src.y1 != src_y ||
- drm_rect_width(&plane_state->src) != src_w ||
- drm_rect_height(&plane_state->src) != src_h) {
- drm_rect_debug_print("src: ", &plane_state->src, true);
- return false;
- }
-
- return true;
-}
+ struct drm_rect expected = DRM_RECT_INIT(src_x, src_y, src_w, src_h);
-static void set_crtc(struct drm_plane_state *plane_state,
- int crtc_x, int crtc_y,
- unsigned int crtc_w, unsigned int crtc_h)
-{
- plane_state->crtc_x = crtc_x;
- plane_state->crtc_y = crtc_y;
- plane_state->crtc_w = crtc_w;
- plane_state->crtc_h = crtc_h;
+ KUNIT_ASSERT_GE_MSG(test, plane_state->src.x1, 0,
+ "src x coordinate %x should never be below 0, src: " DRM_RECT_FP_FMT,
+ plane_state->src.x1, DRM_RECT_FP_ARG(&plane_state->src));
+
+ KUNIT_ASSERT_GE_MSG(test, plane_state->src.y1, 0,
+ "src y coordinate %x should never be below 0, src: " DRM_RECT_FP_FMT,
+ plane_state->src.y1, DRM_RECT_FP_ARG(&plane_state->src));
+
+ KUNIT_EXPECT_TRUE_MSG(test, drm_rect_equals(&plane_state->src, &expected),
+ "dst: " DRM_RECT_FP_FMT ", expected: " DRM_RECT_FP_FMT,
+ DRM_RECT_FP_ARG(&plane_state->src), DRM_RECT_FP_ARG(&expected));
}
-static bool check_crtc_eq(struct drm_plane_state *plane_state,
+static void check_crtc_eq(struct kunit *test, struct drm_plane_state *plane_state,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h)
{
- if (plane_state->dst.x1 != crtc_x ||
- plane_state->dst.y1 != crtc_y ||
- drm_rect_width(&plane_state->dst) != crtc_w ||
- drm_rect_height(&plane_state->dst) != crtc_h) {
- drm_rect_debug_print("dst: ", &plane_state->dst, false);
-
- return false;
- }
+ struct drm_rect expected = DRM_RECT_INIT(crtc_x, crtc_y, crtc_w, crtc_h);
- return true;
+ KUNIT_EXPECT_TRUE_MSG(test, drm_rect_equals(&plane_state->dst, &expected),
+ "dst: " DRM_RECT_FMT ", expected: " DRM_RECT_FMT,
+ DRM_RECT_ARG(&plane_state->dst), DRM_RECT_ARG(&expected));
}
static void drm_test_check_plane_state(struct kunit *test)
{
- int ret;
-
- static const struct drm_crtc_state crtc_state = {
- .crtc = ZERO_SIZE_PTR,
- .enable = true,
- .active = true,
- .mode = {
- DRM_MODE("1024x768", 0, 65000, 1024, 1048, 1184, 1344, 0, 768, 771,
- 777, 806, 0, DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC)
- },
- };
- static struct drm_plane plane = {
- .dev = NULL
- };
- static struct drm_framebuffer fb = {
- .width = 2048,
- .height = 2048
- };
- static struct drm_plane_state plane_state = {
- .plane = &plane,
- .crtc = ZERO_SIZE_PTR,
- .fb = &fb,
- .rotation = DRM_MODE_ROTATE_0
- };
-
- /* Simple clipping, no scaling. */
- set_src(&plane_state, 0, 0, fb.width << 16, fb.height << 16);
- set_crtc(&plane_state, 0, 0, fb.width, fb.height);
- ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
- DRM_PLANE_NO_SCALING,
- DRM_PLANE_NO_SCALING,
- false, false);
- KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Simple clipping check should pass\n");
- KUNIT_EXPECT_TRUE(test, plane_state.visible);
- KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 1024 << 16, 768 << 16));
- KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1024, 768));
-
- /* Rotated clipping + reflection, no scaling. */
- plane_state.rotation = DRM_MODE_ROTATE_90 | DRM_MODE_REFLECT_X;
- ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
- DRM_PLANE_NO_SCALING,
- DRM_PLANE_NO_SCALING,
- false, false);
- KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Rotated clipping check should pass\n");
- KUNIT_EXPECT_TRUE(test, plane_state.visible);
- KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 768 << 16, 1024 << 16));
- KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1024, 768));
- plane_state.rotation = DRM_MODE_ROTATE_0;
-
- /* Check whether positioning works correctly. */
- set_src(&plane_state, 0, 0, 1023 << 16, 767 << 16);
- set_crtc(&plane_state, 0, 0, 1023, 767);
- ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
- DRM_PLANE_NO_SCALING,
- DRM_PLANE_NO_SCALING,
- false, false);
- KUNIT_EXPECT_TRUE_MSG(test, ret,
- "Should not be able to position on the crtc with can_position=false\n");
-
- ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
- DRM_PLANE_NO_SCALING,
- DRM_PLANE_NO_SCALING,
- true, false);
- KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Simple positioning should work\n");
- KUNIT_EXPECT_TRUE(test, plane_state.visible);
- KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 1023 << 16, 767 << 16));
- KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1023, 767));
-
- /* Simple scaling tests. */
- set_src(&plane_state, 0, 0, 512 << 16, 384 << 16);
- set_crtc(&plane_state, 0, 0, 1024, 768);
- ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
- 0x8001,
- DRM_PLANE_NO_SCALING,
- false, false);
- KUNIT_EXPECT_TRUE_MSG(test, ret, "Upscaling out of range should fail.\n");
- ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
- 0x8000,
- DRM_PLANE_NO_SCALING,
- false, false);
- KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Upscaling exactly 2x should work\n");
- KUNIT_EXPECT_TRUE(test, plane_state.visible);
- KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 512 << 16, 384 << 16));
- KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1024, 768));
-
- set_src(&plane_state, 0, 0, 2048 << 16, 1536 << 16);
- ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
- DRM_PLANE_NO_SCALING,
- 0x1ffff, false, false);
- KUNIT_EXPECT_TRUE_MSG(test, ret, "Downscaling out of range should fail.\n");
- ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
- DRM_PLANE_NO_SCALING,
- 0x20000, false, false);
- KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed with exact scaling limit\n");
- KUNIT_EXPECT_TRUE(test, plane_state.visible);
- KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 2048 << 16, 1536 << 16));
- KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1024, 768));
-
- /* Testing rounding errors. */
- set_src(&plane_state, 0, 0, 0x40001, 0x40001);
- set_crtc(&plane_state, 1022, 766, 4, 4);
- ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
- DRM_PLANE_NO_SCALING,
- 0x10001,
- true, false);
- KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed by clipping to exact multiple");
- KUNIT_EXPECT_TRUE(test, plane_state.visible);
- KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16));
- KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 1022, 766, 2, 2));
-
- set_src(&plane_state, 0x20001, 0x20001, 0x4040001, 0x3040001);
- set_crtc(&plane_state, -2, -2, 1028, 772);
- ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
- DRM_PLANE_NO_SCALING,
- 0x10001,
- false, false);
- KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed by clipping to exact multiple");
- KUNIT_EXPECT_TRUE(test, plane_state.visible);
- KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0x40002, 0x40002,
- 1024 << 16, 768 << 16));
- KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1024, 768));
-
- set_src(&plane_state, 0, 0, 0x3ffff, 0x3ffff);
- set_crtc(&plane_state, 1022, 766, 4, 4);
- ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
- 0xffff,
- DRM_PLANE_NO_SCALING,
- true, false);
- KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed by clipping to exact multiple");
- KUNIT_EXPECT_TRUE(test, plane_state.visible);
- /* Should not be rounded to 0x20001, which would be upscaling. */
- KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0, 0, 2 << 16, 2 << 16));
- KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 1022, 766, 2, 2));
-
- set_src(&plane_state, 0x1ffff, 0x1ffff, 0x403ffff, 0x303ffff);
- set_crtc(&plane_state, -2, -2, 1028, 772);
- ret = drm_atomic_helper_check_plane_state(&plane_state, &crtc_state,
- 0xffff,
- DRM_PLANE_NO_SCALING,
- false, false);
- KUNIT_EXPECT_FALSE_MSG(test, ret, 0, "Should succeed by clipping to exact multiple");
- KUNIT_EXPECT_TRUE(test, plane_state.visible);
- KUNIT_EXPECT_TRUE(test, check_src_eq(&plane_state, 0x3fffe, 0x3fffe,
- 1024 << 16, 768 << 16));
- KUNIT_EXPECT_TRUE(test, check_crtc_eq(&plane_state, 0, 0, 1024, 768));
+ const struct drm_check_plane_state_test *params = test->param_value;
+ struct drm_plane_state *plane_state = test->priv;
+
+ KUNIT_ASSERT_EQ_MSG(test,
+ drm_atomic_helper_check_plane_state(plane_state, &crtc_state,
+ params->min_scale,
+ params->max_scale,
+ params->can_position, false),
+ 0, params->msg);
+ KUNIT_EXPECT_TRUE(test, plane_state->visible);
+ check_src_eq(test, plane_state, params->src_expected.x, params->src_expected.y,
+ params->src_expected.w, params->src_expected.h);
+ check_crtc_eq(test, plane_state, params->crtc_expected.x, params->crtc_expected.y,
+ params->crtc_expected.w, params->crtc_expected.h);
+}
+
+static void drm_check_plane_state_desc(const struct drm_check_plane_state_test *t,
+ char *desc)
+{
+ sprintf(desc, "%s", t->name);
+}
+
+static const struct drm_check_plane_state_test drm_check_plane_state_tests[] = {
+ {
+ .name = "clipping_simple",
+ .msg = "Simple clipping check should pass",
+ .src = { 0, 0,
+ 2048 << 16,
+ 2048 << 16 },
+ .crtc = { 0, 0, 2048, 2048 },
+ .rotation = DRM_MODE_ROTATE_0,
+ .min_scale = DRM_PLANE_NO_SCALING,
+ .max_scale = DRM_PLANE_NO_SCALING,
+ .can_position = false,
+ .src_expected = { 0, 0, 1024 << 16, 768 << 16 },
+ .crtc_expected = { 0, 0, 1024, 768 },
+ },
+ {
+ .name = "clipping_rotate_reflect",
+ .msg = "Rotated clipping check should pass",
+ .src = { 0, 0,
+ 2048 << 16,
+ 2048 << 16 },
+ .crtc = { 0, 0, 2048, 2048 },
+ .rotation = DRM_MODE_ROTATE_90 | DRM_MODE_REFLECT_X,
+ .min_scale = DRM_PLANE_NO_SCALING,
+ .max_scale = DRM_PLANE_NO_SCALING,
+ .can_position = false,
+ .src_expected = { 0, 0, 768 << 16, 1024 << 16 },
+ .crtc_expected = { 0, 0, 1024, 768 },
+ },
+ {
+ .name = "positioning_simple",
+ .msg = "Simple positioning should work",
+ .src = { 0, 0, 1023 << 16, 767 << 16 },
+ .crtc = { 0, 0, 1023, 767 },
+ .rotation = DRM_MODE_ROTATE_0,
+ .min_scale = DRM_PLANE_NO_SCALING,
+ .max_scale = DRM_PLANE_NO_SCALING,
+ .can_position = true,
+ .src_expected = { 0, 0, 1023 << 16, 767 << 16 },
+ .crtc_expected = { 0, 0, 1023, 767 },
+ },
+ {
+ .name = "upscaling",
+ .msg = "Upscaling exactly 2x should work",
+ .src = { 0, 0, 512 << 16, 384 << 16 },
+ .crtc = { 0, 0, 1024, 768 },
+ .rotation = DRM_MODE_ROTATE_0,
+ .min_scale = 0x8000,
+ .max_scale = DRM_PLANE_NO_SCALING,
+ .can_position = false,
+ .src_expected = { 0, 0, 512 << 16, 384 << 16 },
+ .crtc_expected = { 0, 0, 1024, 768 },
+ },
+ {
+ .name = "downscaling",
+ .msg = "Should succeed with exact scaling limit",
+ .src = { 0, 0, 2048 << 16, 1536 << 16 },
+ .crtc = { 0, 0, 1024, 768 },
+ .rotation = DRM_MODE_ROTATE_0,
+ .min_scale = DRM_PLANE_NO_SCALING,
+ .max_scale = 0x20000,
+ .can_position = false,
+ .src_expected = { 0, 0, 2048 << 16, 1536 << 16 },
+ .crtc_expected = { 0, 0, 1024, 768 },
+ },
+ {
+ .name = "rounding1",
+ .msg = "Should succeed by clipping to exact multiple",
+ .src = { 0, 0, 0x40001, 0x40001 },
+ .crtc = { 1022, 766, 4, 4 },
+ .rotation = DRM_MODE_ROTATE_0,
+ .min_scale = DRM_PLANE_NO_SCALING,
+ .max_scale = 0x10001,
+ .can_position = true,
+ .src_expected = { 0, 0, 2 << 16, 2 << 16 },
+ .crtc_expected = { 1022, 766, 2, 2 },
+ },
+ {
+ .name = "rounding2",
+ .msg = "Should succeed by clipping to exact multiple",
+ .src = { 0x20001, 0x20001, 0x4040001, 0x3040001 },
+ .crtc = { -2, -2, 1028, 772 },
+ .rotation = DRM_MODE_ROTATE_0,
+ .min_scale = DRM_PLANE_NO_SCALING,
+ .max_scale = 0x10001,
+ .can_position = false,
+ .src_expected = { 0x40002, 0x40002, 1024 << 16, 768 << 16 },
+ .crtc_expected = { 0, 0, 1024, 768 },
+ },
+ {
+ .name = "rounding3",
+ .msg = "Should succeed by clipping to exact multiple",
+ .src = { 0, 0, 0x3ffff, 0x3ffff },
+ .crtc = { 1022, 766, 4, 4 },
+ .rotation = DRM_MODE_ROTATE_0,
+ .min_scale = 0xffff,
+ .max_scale = DRM_PLANE_NO_SCALING,
+ .can_position = true,
+ /* Should not be rounded to 0x20001, which would be upscaling. */
+ .src_expected = { 0, 0, 2 << 16, 2 << 16 },
+ .crtc_expected = { 1022, 766, 2, 2 },
+ },
+ {
+ .name = "rounding4",
+ .msg = "Should succeed by clipping to exact multiple",
+ .src = { 0x1ffff, 0x1ffff, 0x403ffff, 0x303ffff },
+ .crtc = { -2, -2, 1028, 772 },
+ .rotation = DRM_MODE_ROTATE_0,
+ .min_scale = 0xffff,
+ .max_scale = DRM_PLANE_NO_SCALING,
+ .can_position = false,
+ .src_expected = { 0x3fffe, 0x3fffe, 1024 << 16, 768 << 16 },
+ .crtc_expected = { 0, 0, 1024, 768 },
+ },
+};
+
+KUNIT_ARRAY_PARAM(drm_check_plane_state, drm_check_plane_state_tests, drm_check_plane_state_desc);
+
+static void drm_test_check_invalid_plane_state(struct kunit *test)
+{
+ const struct drm_check_plane_state_test *params = test->param_value;
+ struct drm_plane_state *plane_state = test->priv;
+
+ KUNIT_ASSERT_LT_MSG(test,
+ drm_atomic_helper_check_plane_state(plane_state, &crtc_state,
+ params->min_scale,
+ params->max_scale,
+ params->can_position, false),
+ 0, params->msg);
}
+static const struct drm_check_plane_state_test drm_check_invalid_plane_state_tests[] = {
+ {
+ .name = "positioning_invalid",
+ .msg = "Should not be able to position on the crtc with can_position=false",
+ .src = { 0, 0, 1023 << 16, 767 << 16 },
+ .crtc = { 0, 0, 1023, 767 },
+ .rotation = DRM_MODE_ROTATE_0,
+ .min_scale = DRM_PLANE_NO_SCALING,
+ .max_scale = DRM_PLANE_NO_SCALING,
+ .can_position = false,
+ },
+ {
+ .name = "upscaling_invalid",
+ .msg = "Upscaling out of range should fail",
+ .src = { 0, 0, 512 << 16, 384 << 16 },
+ .crtc = { 0, 0, 1024, 768 },
+ .rotation = DRM_MODE_ROTATE_0,
+ .min_scale = 0x8001,
+ .max_scale = DRM_PLANE_NO_SCALING,
+ .can_position = false,
+ },
+ {
+ .name = "downscaling_invalid",
+ .msg = "Downscaling out of range should fail",
+ .src = { 0, 0, 2048 << 16, 1536 << 16 },
+ .crtc = { 0, 0, 1024, 768 },
+ .rotation = DRM_MODE_ROTATE_0,
+ .min_scale = DRM_PLANE_NO_SCALING,
+ .max_scale = 0x1ffff,
+ .can_position = false,
+ },
+};
+
+KUNIT_ARRAY_PARAM(drm_check_invalid_plane_state, drm_check_invalid_plane_state_tests,
+ drm_check_plane_state_desc);
+
static struct kunit_case drm_plane_helper_test[] = {
- KUNIT_CASE(drm_test_check_plane_state),
+ KUNIT_CASE_PARAM(drm_test_check_plane_state, drm_check_plane_state_gen_params),
+ KUNIT_CASE_PARAM(drm_test_check_invalid_plane_state,
+ drm_check_invalid_plane_state_gen_params),
{}
};
static struct kunit_suite drm_plane_helper_test_suite = {
.name = "drm_plane_helper",
+ .init = drm_plane_helper_init,
.test_cases = drm_plane_helper_test,
};
diff --git a/drivers/gpu/drm/tidss/tidss_drv.c b/drivers/gpu/drm/tidss/tidss_drv.c
index 15cd9b91b7e2..07d94b1e8089 100644
--- a/drivers/gpu/drm/tidss/tidss_drv.c
+++ b/drivers/gpu/drm/tidss/tidss_drv.c
@@ -14,7 +14,7 @@
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
#include <drm/drm_module.h>
diff --git a/drivers/gpu/drm/tidss/tidss_kms.c b/drivers/gpu/drm/tidss/tidss_kms.c
index afb2879980c6..345bcc3011e4 100644
--- a/drivers/gpu/drm/tidss/tidss_kms.c
+++ b/drivers/gpu/drm/tidss/tidss_kms.c
@@ -10,7 +10,6 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_crtc_helper.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_of.h>
#include <drm/drm_panel.h>
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index f72755b8ea14..80615ecdae0b 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -16,7 +16,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_debugfs.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
diff --git a/drivers/gpu/drm/tiny/Kconfig b/drivers/gpu/drm/tiny/Kconfig
index 565957264875..f6889f649bc1 100644
--- a/drivers/gpu/drm/tiny/Kconfig
+++ b/drivers/gpu/drm/tiny/Kconfig
@@ -51,6 +51,19 @@ config DRM_GM12U320
This is a KMS driver for projectors which use the GM12U320 chipset
for video transfer over USB2/3, such as the Acer C120 mini projector.
+config DRM_OFDRM
+ tristate "Open Firmware display driver"
+ depends on DRM && MMU && OF && (PPC || COMPILE_TEST)
+ select APERTURE_HELPERS
+ select DRM_GEM_SHMEM_HELPER
+ select DRM_KMS_HELPER
+ help
+ DRM driver for Open Firmware framebuffers.
+
+ This driver assumes that the display hardware has been initialized
+ by the Open Firmware before the kernel boots. Scanout buffer, size,
+ and display format must be provided via device tree.
+
config DRM_PANEL_MIPI_DBI
tristate "DRM support for MIPI DBI compatible panels"
depends on DRM && SPI
diff --git a/drivers/gpu/drm/tiny/Makefile b/drivers/gpu/drm/tiny/Makefile
index 1d9d6227e7ab..76dde89a044b 100644
--- a/drivers/gpu/drm/tiny/Makefile
+++ b/drivers/gpu/drm/tiny/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_DRM_ARCPGU) += arcpgu.o
obj-$(CONFIG_DRM_BOCHS) += bochs.o
obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus.o
obj-$(CONFIG_DRM_GM12U320) += gm12u320.o
+obj-$(CONFIG_DRM_OFDRM) += ofdrm.o
obj-$(CONFIG_DRM_PANEL_MIPI_DBI) += panel-mipi-dbi.o
obj-$(CONFIG_DRM_SIMPLEDRM) += simpledrm.o
obj-$(CONFIG_TINYDRM_HX8357D) += hx8357d.o
diff --git a/drivers/gpu/drm/tiny/arcpgu.c b/drivers/gpu/drm/tiny/arcpgu.c
index bb302a3fd6b5..611bbee15071 100644
--- a/drivers/gpu/drm/tiny/arcpgu.c
+++ b/drivers/gpu/drm/tiny/arcpgu.c
@@ -12,7 +12,7 @@
#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
#include <drm/drm_fb_dma_helper.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_dma_helper.h>
diff --git a/drivers/gpu/drm/tiny/bochs.c b/drivers/gpu/drm/tiny/bochs.c
index a51262289aef..024346054c70 100644
--- a/drivers/gpu/drm/tiny/bochs.c
+++ b/drivers/gpu/drm/tiny/bochs.c
@@ -7,7 +7,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_framebuffer_helper.h>
@@ -543,7 +543,6 @@ static int bochs_kms_init(struct bochs_device *bochs)
bochs->dev->mode_config.max_width = 8192;
bochs->dev->mode_config.max_height = 8192;
- bochs->dev->mode_config.fb_base = bochs->fb_base;
bochs->dev->mode_config.preferred_depth = 24;
bochs->dev->mode_config.prefer_shadow = 0;
bochs->dev->mode_config.prefer_shadow_fbdev = 1;
diff --git a/drivers/gpu/drm/tiny/cirrus.c b/drivers/gpu/drm/tiny/cirrus.c
index 354d5e854a6f..678c2ef1cae7 100644
--- a/drivers/gpu/drm/tiny/cirrus.c
+++ b/drivers/gpu/drm/tiny/cirrus.c
@@ -30,7 +30,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_file.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_fourcc.h>
diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c
index 7441d992a5d7..130fd07a967d 100644
--- a/drivers/gpu/drm/tiny/gm12u320.c
+++ b/drivers/gpu/drm/tiny/gm12u320.c
@@ -12,7 +12,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_file.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_fourcc.h>
diff --git a/drivers/gpu/drm/tiny/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c
index 48c24aa8c28a..9f634f720817 100644
--- a/drivers/gpu/drm/tiny/hx8357d.c
+++ b/drivers/gpu/drm/tiny/hx8357d.c
@@ -18,7 +18,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
diff --git a/drivers/gpu/drm/tiny/ili9163.c b/drivers/gpu/drm/tiny/ili9163.c
index 9a1a5943bee0..ca0451f79962 100644
--- a/drivers/gpu/drm/tiny/ili9163.c
+++ b/drivers/gpu/drm/tiny/ili9163.c
@@ -9,7 +9,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_mipi_dbi.h>
diff --git a/drivers/gpu/drm/tiny/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c
index a79da2b4af64..815bab285823 100644
--- a/drivers/gpu/drm/tiny/ili9225.c
+++ b/drivers/gpu/drm/tiny/ili9225.c
@@ -20,7 +20,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_dma_helper.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
diff --git a/drivers/gpu/drm/tiny/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c
index 69b265e78096..420f6005a956 100644
--- a/drivers/gpu/drm/tiny/ili9341.c
+++ b/drivers/gpu/drm/tiny/ili9341.c
@@ -17,7 +17,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
diff --git a/drivers/gpu/drm/tiny/ili9486.c b/drivers/gpu/drm/tiny/ili9486.c
index c80028bb1d11..1bb847466b10 100644
--- a/drivers/gpu/drm/tiny/ili9486.c
+++ b/drivers/gpu/drm/tiny/ili9486.c
@@ -16,7 +16,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
diff --git a/drivers/gpu/drm/tiny/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c
index bc522fb3d94d..47df2b5a3048 100644
--- a/drivers/gpu/drm/tiny/mi0283qt.c
+++ b/drivers/gpu/drm/tiny/mi0283qt.c
@@ -15,7 +15,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
diff --git a/drivers/gpu/drm/tiny/ofdrm.c b/drivers/gpu/drm/tiny/ofdrm.c
new file mode 100644
index 000000000000..dc9e4d71b12a
--- /dev/null
+++ b/drivers/gpu/drm/tiny/ofdrm.c
@@ -0,0 +1,1429 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/of_address.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+
+#include <drm/drm_aperture.h>
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_state_helper.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_damage_helper.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_format_helper.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_gem_atomic_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_gem_shmem_helper.h>
+#include <drm/drm_managed.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>
+
+#define DRIVER_NAME "ofdrm"
+#define DRIVER_DESC "DRM driver for OF platform devices"
+#define DRIVER_DATE "20220501"
+#define DRIVER_MAJOR 1
+#define DRIVER_MINOR 0
+
+#define PCI_VENDOR_ID_ATI_R520 0x7100
+#define PCI_VENDOR_ID_ATI_R600 0x9400
+
+#define OFDRM_GAMMA_LUT_SIZE 256
+
+/* Definitions used by the Avivo palette */
+#define AVIVO_DC_LUT_RW_SELECT 0x6480
+#define AVIVO_DC_LUT_RW_MODE 0x6484
+#define AVIVO_DC_LUT_RW_INDEX 0x6488
+#define AVIVO_DC_LUT_SEQ_COLOR 0x648c
+#define AVIVO_DC_LUT_PWL_DATA 0x6490
+#define AVIVO_DC_LUT_30_COLOR 0x6494
+#define AVIVO_DC_LUT_READ_PIPE_SELECT 0x6498
+#define AVIVO_DC_LUT_WRITE_EN_MASK 0x649c
+#define AVIVO_DC_LUT_AUTOFILL 0x64a0
+#define AVIVO_DC_LUTA_CONTROL 0x64c0
+#define AVIVO_DC_LUTA_BLACK_OFFSET_BLUE 0x64c4
+#define AVIVO_DC_LUTA_BLACK_OFFSET_GREEN 0x64c8
+#define AVIVO_DC_LUTA_BLACK_OFFSET_RED 0x64cc
+#define AVIVO_DC_LUTA_WHITE_OFFSET_BLUE 0x64d0
+#define AVIVO_DC_LUTA_WHITE_OFFSET_GREEN 0x64d4
+#define AVIVO_DC_LUTA_WHITE_OFFSET_RED 0x64d8
+#define AVIVO_DC_LUTB_CONTROL 0x6cc0
+#define AVIVO_DC_LUTB_BLACK_OFFSET_BLUE 0x6cc4
+#define AVIVO_DC_LUTB_BLACK_OFFSET_GREEN 0x6cc8
+#define AVIVO_DC_LUTB_BLACK_OFFSET_RED 0x6ccc
+#define AVIVO_DC_LUTB_WHITE_OFFSET_BLUE 0x6cd0
+#define AVIVO_DC_LUTB_WHITE_OFFSET_GREEN 0x6cd4
+#define AVIVO_DC_LUTB_WHITE_OFFSET_RED 0x6cd8
+
+enum ofdrm_model {
+ OFDRM_MODEL_UNKNOWN,
+ OFDRM_MODEL_MACH64, /* ATI Mach64 */
+ OFDRM_MODEL_RAGE128, /* ATI Rage128 */
+ OFDRM_MODEL_RAGE_M3A, /* ATI Rage Mobility M3 Head A */
+ OFDRM_MODEL_RAGE_M3B, /* ATI Rage Mobility M3 Head B */
+ OFDRM_MODEL_RADEON, /* ATI Radeon */
+ OFDRM_MODEL_GXT2000, /* IBM GXT2000 */
+ OFDRM_MODEL_AVIVO, /* ATI R5xx */
+ OFDRM_MODEL_QEMU, /* QEMU VGA */
+};
+
+/*
+ * Helpers for display nodes
+ */
+
+static int display_get_validated_int(struct drm_device *dev, const char *name, uint32_t value)
+{
+ if (value > INT_MAX) {
+ drm_err(dev, "invalid framebuffer %s of %u\n", name, value);
+ return -EINVAL;
+ }
+ return (int)value;
+}
+
+static int display_get_validated_int0(struct drm_device *dev, const char *name, uint32_t value)
+{
+ if (!value) {
+ drm_err(dev, "invalid framebuffer %s of %u\n", name, value);
+ return -EINVAL;
+ }
+ return display_get_validated_int(dev, name, value);
+}
+
+static const struct drm_format_info *display_get_validated_format(struct drm_device *dev,
+ u32 depth, bool big_endian)
+{
+ const struct drm_format_info *info;
+ u32 format;
+
+ switch (depth) {
+ case 8:
+ format = drm_mode_legacy_fb_format(8, 8);
+ break;
+ case 15:
+ case 16:
+ format = drm_mode_legacy_fb_format(16, depth);
+ break;
+ case 32:
+ format = drm_mode_legacy_fb_format(32, 24);
+ break;
+ default:
+ drm_err(dev, "unsupported framebuffer depth %u\n", depth);
+ return ERR_PTR(-EINVAL);
+ }
+
+ /*
+ * DRM formats assume little-endian byte order. Update the format
+ * if the scanout buffer uses big-endian ordering.
+ */
+ if (big_endian) {
+ switch (format) {
+ case DRM_FORMAT_XRGB8888:
+ format = DRM_FORMAT_BGRX8888;
+ break;
+ case DRM_FORMAT_ARGB8888:
+ format = DRM_FORMAT_BGRA8888;
+ break;
+ case DRM_FORMAT_RGB565:
+ format = DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN;
+ break;
+ case DRM_FORMAT_XRGB1555:
+ format = DRM_FORMAT_XRGB1555 | DRM_FORMAT_BIG_ENDIAN;
+ break;
+ default:
+ break;
+ }
+ }
+
+ info = drm_format_info(format);
+ if (!info) {
+ drm_err(dev, "cannot find framebuffer format for depth %u\n", depth);
+ return ERR_PTR(-EINVAL);
+ }
+
+ return info;
+}
+
+static int display_read_u32_of(struct drm_device *dev, struct device_node *of_node,
+ const char *name, u32 *value)
+{
+ int ret = of_property_read_u32(of_node, name, value);
+
+ if (ret)
+ drm_err(dev, "cannot parse framebuffer %s: error %d\n", name, ret);
+ return ret;
+}
+
+static bool display_get_big_endian_of(struct drm_device *dev, struct device_node *of_node)
+{
+ bool big_endian;
+
+#ifdef __BIG_ENDIAN
+ big_endian = true;
+ if (of_get_property(of_node, "little-endian", NULL))
+ big_endian = false;
+#else
+ big_endian = false;
+ if (of_get_property(of_node, "big-endian", NULL))
+ big_endian = true;
+#endif
+
+ return big_endian;
+}
+
+static int display_get_width_of(struct drm_device *dev, struct device_node *of_node)
+{
+ u32 width;
+ int ret = display_read_u32_of(dev, of_node, "width", &width);
+
+ if (ret)
+ return ret;
+ return display_get_validated_int0(dev, "width", width);
+}
+
+static int display_get_height_of(struct drm_device *dev, struct device_node *of_node)
+{
+ u32 height;
+ int ret = display_read_u32_of(dev, of_node, "height", &height);
+
+ if (ret)
+ return ret;
+ return display_get_validated_int0(dev, "height", height);
+}
+
+static int display_get_depth_of(struct drm_device *dev, struct device_node *of_node)
+{
+ u32 depth;
+ int ret = display_read_u32_of(dev, of_node, "depth", &depth);
+
+ if (ret)
+ return ret;
+ return display_get_validated_int0(dev, "depth", depth);
+}
+
+static int display_get_linebytes_of(struct drm_device *dev, struct device_node *of_node)
+{
+ u32 linebytes;
+ int ret = display_read_u32_of(dev, of_node, "linebytes", &linebytes);
+
+ if (ret)
+ return ret;
+ return display_get_validated_int(dev, "linebytes", linebytes);
+}
+
+static u64 display_get_address_of(struct drm_device *dev, struct device_node *of_node)
+{
+ u32 address;
+ int ret;
+
+ /*
+ * Not all devices provide an address property, it's not
+ * a bug if this fails. The driver will try to find the
+ * framebuffer base address from the device's memory regions.
+ */
+ ret = of_property_read_u32(of_node, "address", &address);
+ if (ret)
+ return OF_BAD_ADDR;
+
+ return address;
+}
+
+static bool is_avivo(u32 vendor, u32 device)
+{
+ /* This will match most R5xx */
+ return (vendor == PCI_VENDOR_ID_ATI) &&
+ ((device >= PCI_VENDOR_ID_ATI_R520 && device < 0x7800) ||
+ (PCI_VENDOR_ID_ATI_R600 >= 0x9400));
+}
+
+static enum ofdrm_model display_get_model_of(struct drm_device *dev, struct device_node *of_node)
+{
+ enum ofdrm_model model = OFDRM_MODEL_UNKNOWN;
+
+ if (of_node_name_prefix(of_node, "ATY,Rage128")) {
+ model = OFDRM_MODEL_RAGE128;
+ } else if (of_node_name_prefix(of_node, "ATY,RageM3pA") ||
+ of_node_name_prefix(of_node, "ATY,RageM3p12A")) {
+ model = OFDRM_MODEL_RAGE_M3A;
+ } else if (of_node_name_prefix(of_node, "ATY,RageM3pB")) {
+ model = OFDRM_MODEL_RAGE_M3B;
+ } else if (of_node_name_prefix(of_node, "ATY,Rage6")) {
+ model = OFDRM_MODEL_RADEON;
+ } else if (of_node_name_prefix(of_node, "ATY,")) {
+ return OFDRM_MODEL_MACH64;
+ } else if (of_device_is_compatible(of_node, "pci1014,b7") ||
+ of_device_is_compatible(of_node, "pci1014,21c")) {
+ model = OFDRM_MODEL_GXT2000;
+ } else if (of_node_name_prefix(of_node, "vga,Display-")) {
+ struct device_node *of_parent;
+ const __be32 *vendor_p, *device_p;
+
+ /* Look for AVIVO initialized by SLOF */
+ of_parent = of_get_parent(of_node);
+ vendor_p = of_get_property(of_parent, "vendor-id", NULL);
+ device_p = of_get_property(of_parent, "device-id", NULL);
+ if (vendor_p && device_p) {
+ u32 vendor = be32_to_cpup(vendor_p);
+ u32 device = be32_to_cpup(device_p);
+
+ if (is_avivo(vendor, device))
+ model = OFDRM_MODEL_AVIVO;
+ }
+ of_node_put(of_parent);
+ } else if (of_device_is_compatible(of_node, "qemu,std-vga")) {
+ model = OFDRM_MODEL_QEMU;
+ }
+
+ return model;
+}
+
+/*
+ * Open Firmware display device
+ */
+
+struct ofdrm_device;
+
+struct ofdrm_device_funcs {
+ void __iomem *(*cmap_ioremap)(struct ofdrm_device *odev,
+ struct device_node *of_node,
+ u64 fb_bas);
+ void (*cmap_write)(struct ofdrm_device *odev, unsigned char index,
+ unsigned char r, unsigned char g, unsigned char b);
+};
+
+struct ofdrm_device {
+ struct drm_device dev;
+ struct platform_device *pdev;
+
+ const struct ofdrm_device_funcs *funcs;
+
+ /* firmware-buffer settings */
+ struct iosys_map screen_base;
+ struct drm_display_mode mode;
+ const struct drm_format_info *format;
+ unsigned int pitch;
+
+ /* colormap */
+ void __iomem *cmap_base;
+
+ /* modesetting */
+ uint32_t formats[8];
+ struct drm_plane primary_plane;
+ struct drm_crtc crtc;
+ struct drm_encoder encoder;
+ struct drm_connector connector;
+};
+
+static struct ofdrm_device *ofdrm_device_of_dev(struct drm_device *dev)
+{
+ return container_of(dev, struct ofdrm_device, dev);
+}
+
+/*
+ * Hardware
+ */
+
+#if defined(CONFIG_PCI)
+static struct pci_dev *display_get_pci_dev_of(struct drm_device *dev, struct device_node *of_node)
+{
+ const __be32 *vendor_p, *device_p;
+ u32 vendor, device;
+ struct pci_dev *pcidev;
+
+ vendor_p = of_get_property(of_node, "vendor-id", NULL);
+ if (!vendor_p)
+ return ERR_PTR(-ENODEV);
+ vendor = be32_to_cpup(vendor_p);
+
+ device_p = of_get_property(of_node, "device-id", NULL);
+ if (!device_p)
+ return ERR_PTR(-ENODEV);
+ device = be32_to_cpup(device_p);
+
+ pcidev = pci_get_device(vendor, device, NULL);
+ if (!pcidev)
+ return ERR_PTR(-ENODEV);
+
+ return pcidev;
+}
+
+static void ofdrm_pci_release(void *data)
+{
+ struct pci_dev *pcidev = data;
+
+ pci_disable_device(pcidev);
+}
+
+static int ofdrm_device_init_pci(struct ofdrm_device *odev)
+{
+ struct drm_device *dev = &odev->dev;
+ struct platform_device *pdev = to_platform_device(dev->dev);
+ struct device_node *of_node = pdev->dev.of_node;
+ struct pci_dev *pcidev;
+ int ret;
+
+ /*
+ * Never use pcim_ or other managed helpers on the returned PCI
+ * device. Otherwise, probing the native driver will fail for
+ * resource conflicts. PCI-device management has to be tied to
+ * the lifetime of the platform device until the native driver
+ * takes over.
+ */
+ pcidev = display_get_pci_dev_of(dev, of_node);
+ if (IS_ERR(pcidev))
+ return 0; /* no PCI device found; ignore the error */
+
+ ret = pci_enable_device(pcidev);
+ if (ret) {
+ drm_err(dev, "pci_enable_device(%s) failed: %d\n",
+ dev_name(&pcidev->dev), ret);
+ return ret;
+ }
+ ret = devm_add_action_or_reset(&pdev->dev, ofdrm_pci_release, pcidev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+#else
+static int ofdrm_device_init_pci(struct ofdrm_device *odev)
+{
+ return 0;
+}
+#endif
+
+/*
+ * OF display settings
+ */
+
+static struct resource *ofdrm_find_fb_resource(struct ofdrm_device *odev,
+ struct resource *fb_res)
+{
+ struct platform_device *pdev = to_platform_device(odev->dev.dev);
+ struct resource *res, *max_res = NULL;
+ u32 i;
+
+ for (i = 0; pdev->num_resources; ++i) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+ if (!res)
+ break; /* all resources processed */
+ if (resource_size(res) < resource_size(fb_res))
+ continue; /* resource too small */
+ if (fb_res->start && resource_contains(res, fb_res))
+ return res; /* resource contains framebuffer */
+ if (!max_res || resource_size(res) > resource_size(max_res))
+ max_res = res; /* store largest resource as fallback */
+ }
+
+ return max_res;
+}
+
+/*
+ * Colormap / Palette
+ */
+
+static void __iomem *get_cmap_address_of(struct ofdrm_device *odev, struct device_node *of_node,
+ int bar_no, unsigned long offset, unsigned long size)
+{
+ struct drm_device *dev = &odev->dev;
+ const __be32 *addr_p;
+ u64 max_size, address;
+ unsigned int flags;
+ void __iomem *mem;
+
+ addr_p = of_get_pci_address(of_node, bar_no, &max_size, &flags);
+ if (!addr_p)
+ addr_p = of_get_address(of_node, bar_no, &max_size, &flags);
+ if (!addr_p)
+ return IOMEM_ERR_PTR(-ENODEV);
+
+ if ((flags & (IORESOURCE_IO | IORESOURCE_MEM)) == 0)
+ return IOMEM_ERR_PTR(-ENODEV);
+
+ if ((offset + size) >= max_size)
+ return IOMEM_ERR_PTR(-ENODEV);
+
+ address = of_translate_address(of_node, addr_p);
+ if (address == OF_BAD_ADDR)
+ return IOMEM_ERR_PTR(-ENODEV);
+
+ mem = devm_ioremap(dev->dev, address + offset, size);
+ if (!mem)
+ return IOMEM_ERR_PTR(-ENOMEM);
+
+ return mem;
+}
+
+static void __iomem *ofdrm_mach64_cmap_ioremap(struct ofdrm_device *odev,
+ struct device_node *of_node,
+ u64 fb_base)
+{
+ struct drm_device *dev = &odev->dev;
+ u64 address;
+ void __iomem *cmap_base;
+
+ address = fb_base & 0xff000000ul;
+ address += 0x7ff000;
+
+ cmap_base = devm_ioremap(dev->dev, address, 0x1000);
+ if (!cmap_base)
+ return IOMEM_ERR_PTR(-ENOMEM);
+
+ return cmap_base;
+}
+
+static void ofdrm_mach64_cmap_write(struct ofdrm_device *odev, unsigned char index,
+ unsigned char r, unsigned char g, unsigned char b)
+{
+ void __iomem *addr = odev->cmap_base + 0xcc0;
+ void __iomem *data = odev->cmap_base + 0xcc0 + 1;
+
+ writeb(index, addr);
+ writeb(r, data);
+ writeb(g, data);
+ writeb(b, data);
+}
+
+static void __iomem *ofdrm_rage128_cmap_ioremap(struct ofdrm_device *odev,
+ struct device_node *of_node,
+ u64 fb_base)
+{
+ return get_cmap_address_of(odev, of_node, 2, 0, 0x1fff);
+}
+
+static void ofdrm_rage128_cmap_write(struct ofdrm_device *odev, unsigned char index,
+ unsigned char r, unsigned char g, unsigned char b)
+{
+ void __iomem *addr = odev->cmap_base + 0xb0;
+ void __iomem *data = odev->cmap_base + 0xb4;
+ u32 color = (r << 16) | (g << 8) | b;
+
+ writeb(index, addr);
+ writel(color, data);
+}
+
+static void __iomem *ofdrm_rage_m3a_cmap_ioremap(struct ofdrm_device *odev,
+ struct device_node *of_node,
+ u64 fb_base)
+{
+ return get_cmap_address_of(odev, of_node, 2, 0, 0x1fff);
+}
+
+static void ofdrm_rage_m3a_cmap_write(struct ofdrm_device *odev, unsigned char index,
+ unsigned char r, unsigned char g, unsigned char b)
+{
+ void __iomem *dac_ctl = odev->cmap_base + 0x58;
+ void __iomem *addr = odev->cmap_base + 0xb0;
+ void __iomem *data = odev->cmap_base + 0xb4;
+ u32 color = (r << 16) | (g << 8) | b;
+ u32 val;
+
+ /* Clear PALETTE_ACCESS_CNTL in DAC_CNTL */
+ val = readl(dac_ctl);
+ val &= ~0x20;
+ writel(val, dac_ctl);
+
+ /* Set color at palette index */
+ writeb(index, addr);
+ writel(color, data);
+}
+
+static void __iomem *ofdrm_rage_m3b_cmap_ioremap(struct ofdrm_device *odev,
+ struct device_node *of_node,
+ u64 fb_base)
+{
+ return get_cmap_address_of(odev, of_node, 2, 0, 0x1fff);
+}
+
+static void ofdrm_rage_m3b_cmap_write(struct ofdrm_device *odev, unsigned char index,
+ unsigned char r, unsigned char g, unsigned char b)
+{
+ void __iomem *dac_ctl = odev->cmap_base + 0x58;
+ void __iomem *addr = odev->cmap_base + 0xb0;
+ void __iomem *data = odev->cmap_base + 0xb4;
+ u32 color = (r << 16) | (g << 8) | b;
+ u32 val;
+
+ /* Set PALETTE_ACCESS_CNTL in DAC_CNTL */
+ val = readl(dac_ctl);
+ val |= 0x20;
+ writel(val, dac_ctl);
+
+ /* Set color at palette index */
+ writeb(index, addr);
+ writel(color, data);
+}
+
+static void __iomem *ofdrm_radeon_cmap_ioremap(struct ofdrm_device *odev,
+ struct device_node *of_node,
+ u64 fb_base)
+{
+ return get_cmap_address_of(odev, of_node, 1, 0, 0x1fff);
+}
+
+static void __iomem *ofdrm_gxt2000_cmap_ioremap(struct ofdrm_device *odev,
+ struct device_node *of_node,
+ u64 fb_base)
+{
+ return get_cmap_address_of(odev, of_node, 0, 0x6000, 0x1000);
+}
+
+static void ofdrm_gxt2000_cmap_write(struct ofdrm_device *odev, unsigned char index,
+ unsigned char r, unsigned char g, unsigned char b)
+{
+ void __iomem *data = ((unsigned int __iomem *)odev->cmap_base) + index;
+ u32 color = (r << 16) | (g << 8) | b;
+
+ writel(color, data);
+}
+
+static void __iomem *ofdrm_avivo_cmap_ioremap(struct ofdrm_device *odev,
+ struct device_node *of_node,
+ u64 fb_base)
+{
+ struct device_node *of_parent;
+ void __iomem *cmap_base;
+
+ of_parent = of_get_parent(of_node);
+ cmap_base = get_cmap_address_of(odev, of_parent, 0, 0, 0x10000);
+ of_node_put(of_parent);
+
+ return cmap_base;
+}
+
+static void ofdrm_avivo_cmap_write(struct ofdrm_device *odev, unsigned char index,
+ unsigned char r, unsigned char g, unsigned char b)
+{
+ void __iomem *lutsel = odev->cmap_base + AVIVO_DC_LUT_RW_SELECT;
+ void __iomem *addr = odev->cmap_base + AVIVO_DC_LUT_RW_INDEX;
+ void __iomem *data = odev->cmap_base + AVIVO_DC_LUT_30_COLOR;
+ u32 color = (r << 22) | (g << 12) | (b << 2);
+
+ /* Write to both LUTs for now */
+
+ writel(1, lutsel);
+ writeb(index, addr);
+ writel(color, data);
+
+ writel(0, lutsel);
+ writeb(index, addr);
+ writel(color, data);
+}
+
+static void __iomem *ofdrm_qemu_cmap_ioremap(struct ofdrm_device *odev,
+ struct device_node *of_node,
+ u64 fb_base)
+{
+ static const __be32 io_of_addr[3] = {
+ cpu_to_be32(0x01000000),
+ cpu_to_be32(0x00),
+ cpu_to_be32(0x00),
+ };
+
+ struct drm_device *dev = &odev->dev;
+ u64 address;
+ void __iomem *cmap_base;
+
+ address = of_translate_address(of_node, io_of_addr);
+ if (address == OF_BAD_ADDR)
+ return IOMEM_ERR_PTR(-ENODEV);
+
+ cmap_base = devm_ioremap(dev->dev, address + 0x3c8, 2);
+ if (!cmap_base)
+ return IOMEM_ERR_PTR(-ENOMEM);
+
+ return cmap_base;
+}
+
+static void ofdrm_qemu_cmap_write(struct ofdrm_device *odev, unsigned char index,
+ unsigned char r, unsigned char g, unsigned char b)
+{
+ void __iomem *addr = odev->cmap_base;
+ void __iomem *data = odev->cmap_base + 1;
+
+ writeb(index, addr);
+ writeb(r, data);
+ writeb(g, data);
+ writeb(b, data);
+}
+
+static void ofdrm_device_set_gamma_linear(struct ofdrm_device *odev,
+ const struct drm_format_info *format)
+{
+ struct drm_device *dev = &odev->dev;
+ int i;
+
+ switch (format->format) {
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN:
+ /* Use better interpolation, to take 32 values from 0 to 255 */
+ for (i = 0; i < OFDRM_GAMMA_LUT_SIZE / 8; i++) {
+ unsigned char r = i * 8 + i / 4;
+ unsigned char g = i * 4 + i / 16;
+ unsigned char b = i * 8 + i / 4;
+
+ odev->funcs->cmap_write(odev, i, r, g, b);
+ }
+ /* Green has one more bit, so add padding with 0 for red and blue. */
+ for (i = OFDRM_GAMMA_LUT_SIZE / 8; i < OFDRM_GAMMA_LUT_SIZE / 4; i++) {
+ unsigned char r = 0;
+ unsigned char g = i * 4 + i / 16;
+ unsigned char b = 0;
+
+ odev->funcs->cmap_write(odev, i, r, g, b);
+ }
+ break;
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_BGRX8888:
+ for (i = 0; i < OFDRM_GAMMA_LUT_SIZE; i++)
+ odev->funcs->cmap_write(odev, i, i, i, i);
+ break;
+ default:
+ drm_warn_once(dev, "Unsupported format %p4cc for gamma correction\n",
+ &format->format);
+ break;
+ }
+}
+
+static void ofdrm_device_set_gamma(struct ofdrm_device *odev,
+ const struct drm_format_info *format,
+ struct drm_color_lut *lut)
+{
+ struct drm_device *dev = &odev->dev;
+ int i;
+
+ switch (format->format) {
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN:
+ /* Use better interpolation, to take 32 values from lut[0] to lut[255] */
+ for (i = 0; i < OFDRM_GAMMA_LUT_SIZE / 8; i++) {
+ unsigned char r = lut[i * 8 + i / 4].red >> 8;
+ unsigned char g = lut[i * 4 + i / 16].green >> 8;
+ unsigned char b = lut[i * 8 + i / 4].blue >> 8;
+
+ odev->funcs->cmap_write(odev, i, r, g, b);
+ }
+ /* Green has one more bit, so add padding with 0 for red and blue. */
+ for (i = OFDRM_GAMMA_LUT_SIZE / 8; i < OFDRM_GAMMA_LUT_SIZE / 4; i++) {
+ unsigned char r = 0;
+ unsigned char g = lut[i * 4 + i / 16].green >> 8;
+ unsigned char b = 0;
+
+ odev->funcs->cmap_write(odev, i, r, g, b);
+ }
+ break;
+ case DRM_FORMAT_XRGB8888:
+ case DRM_FORMAT_BGRX8888:
+ for (i = 0; i < OFDRM_GAMMA_LUT_SIZE; i++) {
+ unsigned char r = lut[i].red >> 8;
+ unsigned char g = lut[i].green >> 8;
+ unsigned char b = lut[i].blue >> 8;
+
+ odev->funcs->cmap_write(odev, i, r, g, b);
+ }
+ break;
+ default:
+ drm_warn_once(dev, "Unsupported format %p4cc for gamma correction\n",
+ &format->format);
+ break;
+ }
+}
+
+/*
+ * Modesetting
+ */
+
+struct ofdrm_crtc_state {
+ struct drm_crtc_state base;
+
+ /* Primary-plane format; required for color mgmt. */
+ const struct drm_format_info *format;
+};
+
+static struct ofdrm_crtc_state *to_ofdrm_crtc_state(struct drm_crtc_state *base)
+{
+ return container_of(base, struct ofdrm_crtc_state, base);
+}
+
+static void ofdrm_crtc_state_destroy(struct ofdrm_crtc_state *ofdrm_crtc_state)
+{
+ __drm_atomic_helper_crtc_destroy_state(&ofdrm_crtc_state->base);
+ kfree(ofdrm_crtc_state);
+}
+
+/*
+ * Support all formats of OF display and maybe more; in order
+ * of preference. The display's update function will do any
+ * conversion necessary.
+ *
+ * TODO: Add blit helpers for remaining formats and uncomment
+ * constants.
+ */
+static const uint32_t ofdrm_primary_plane_formats[] = {
+ DRM_FORMAT_XRGB8888,
+ DRM_FORMAT_RGB565,
+ //DRM_FORMAT_XRGB1555,
+ //DRM_FORMAT_C8,
+ /* Big-endian formats below */
+ DRM_FORMAT_BGRX8888,
+ DRM_FORMAT_RGB565 | DRM_FORMAT_BIG_ENDIAN,
+};
+
+static const uint64_t ofdrm_primary_plane_format_modifiers[] = {
+ DRM_FORMAT_MOD_LINEAR,
+ DRM_FORMAT_MOD_INVALID
+};
+
+static int ofdrm_primary_plane_helper_atomic_check(struct drm_plane *plane,
+ struct drm_atomic_state *new_state)
+{
+ struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(new_state, plane);
+ struct drm_framebuffer *new_fb = new_plane_state->fb;
+ struct drm_crtc *new_crtc = new_plane_state->crtc;
+ struct drm_crtc_state *new_crtc_state = NULL;
+ struct ofdrm_crtc_state *new_ofdrm_crtc_state;
+ int ret;
+
+ if (new_crtc)
+ new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_plane_state->crtc);
+
+ ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
+ DRM_PLANE_NO_SCALING,
+ DRM_PLANE_NO_SCALING,
+ false, false);
+ if (ret)
+ return ret;
+ else if (!new_plane_state->visible)
+ return 0;
+
+ new_crtc_state = drm_atomic_get_new_crtc_state(new_state, new_plane_state->crtc);
+
+ new_ofdrm_crtc_state = to_ofdrm_crtc_state(new_crtc_state);
+ new_ofdrm_crtc_state->format = new_fb->format;
+
+ return 0;
+}
+
+static void ofdrm_primary_plane_helper_atomic_update(struct drm_plane *plane,
+ struct drm_atomic_state *state)
+{
+ struct drm_device *dev = plane->dev;
+ struct ofdrm_device *odev = ofdrm_device_of_dev(dev);
+ struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
+ struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
+ struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
+ struct drm_framebuffer *fb = plane_state->fb;
+ unsigned int dst_pitch = odev->pitch;
+ const struct drm_format_info *dst_format = odev->format;
+ struct drm_atomic_helper_damage_iter iter;
+ struct drm_rect damage;
+ int ret, idx;
+
+ ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
+ if (ret)
+ return;
+
+ if (!drm_dev_enter(dev, &idx))
+ goto out_drm_gem_fb_end_cpu_access;
+
+ drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_for_each_plane_damage(&iter, &damage) {
+ struct iosys_map dst = odev->screen_base;
+ struct drm_rect dst_clip = plane_state->dst;
+
+ if (!drm_rect_intersect(&dst_clip, &damage))
+ continue;
+
+ iosys_map_incr(&dst, drm_fb_clip_offset(dst_pitch, dst_format, &dst_clip));
+ drm_fb_blit(&dst, &dst_pitch, dst_format->format, shadow_plane_state->data, fb,
+ &damage);
+ }
+
+ drm_dev_exit(idx);
+out_drm_gem_fb_end_cpu_access:
+ drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
+}
+
+static void ofdrm_primary_plane_helper_atomic_disable(struct drm_plane *plane,
+ struct drm_atomic_state *state)
+{
+ struct drm_device *dev = plane->dev;
+ struct ofdrm_device *odev = ofdrm_device_of_dev(dev);
+ struct iosys_map dst = odev->screen_base;
+ struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
+ void __iomem *dst_vmap = dst.vaddr_iomem; /* TODO: Use mapping abstraction */
+ unsigned int dst_pitch = odev->pitch;
+ const struct drm_format_info *dst_format = odev->format;
+ struct drm_rect dst_clip;
+ unsigned long lines, linepixels, i;
+ int idx;
+
+ drm_rect_init(&dst_clip,
+ plane_state->src_x >> 16, plane_state->src_y >> 16,
+ plane_state->src_w >> 16, plane_state->src_h >> 16);
+
+ lines = drm_rect_height(&dst_clip);
+ linepixels = drm_rect_width(&dst_clip);
+
+ if (!drm_dev_enter(dev, &idx))
+ return;
+
+ /* Clear buffer to black if disabled */
+ dst_vmap += drm_fb_clip_offset(dst_pitch, dst_format, &dst_clip);
+ for (i = 0; i < lines; ++i) {
+ memset_io(dst_vmap, 0, linepixels * dst_format->cpp[0]);
+ dst_vmap += dst_pitch;
+ }
+
+ drm_dev_exit(idx);
+}
+
+static const struct drm_plane_helper_funcs ofdrm_primary_plane_helper_funcs = {
+ DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
+ .atomic_check = ofdrm_primary_plane_helper_atomic_check,
+ .atomic_update = ofdrm_primary_plane_helper_atomic_update,
+ .atomic_disable = ofdrm_primary_plane_helper_atomic_disable,
+};
+
+static const struct drm_plane_funcs ofdrm_primary_plane_funcs = {
+ .update_plane = drm_atomic_helper_update_plane,
+ .disable_plane = drm_atomic_helper_disable_plane,
+ .destroy = drm_plane_cleanup,
+ DRM_GEM_SHADOW_PLANE_FUNCS,
+};
+
+static enum drm_mode_status ofdrm_crtc_helper_mode_valid(struct drm_crtc *crtc,
+ const struct drm_display_mode *mode)
+{
+ struct ofdrm_device *odev = ofdrm_device_of_dev(crtc->dev);
+
+ return drm_crtc_helper_mode_valid_fixed(crtc, mode, &odev->mode);
+}
+
+static int ofdrm_crtc_helper_atomic_check(struct drm_crtc *crtc,
+ struct drm_atomic_state *new_state)
+{
+ static const size_t gamma_lut_length = OFDRM_GAMMA_LUT_SIZE * sizeof(struct drm_color_lut);
+
+ struct drm_device *dev = crtc->dev;
+ struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
+ int ret;
+
+ if (!new_crtc_state->enable)
+ return 0;
+
+ ret = drm_atomic_helper_check_crtc_primary_plane(new_crtc_state);
+ if (ret)
+ return ret;
+
+ if (new_crtc_state->color_mgmt_changed) {
+ struct drm_property_blob *gamma_lut = new_crtc_state->gamma_lut;
+
+ if (gamma_lut && (gamma_lut->length != gamma_lut_length)) {
+ drm_dbg(dev, "Incorrect gamma_lut length %zu\n", gamma_lut->length);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static void ofdrm_crtc_helper_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state)
+{
+ struct ofdrm_device *odev = ofdrm_device_of_dev(crtc->dev);
+ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+ struct ofdrm_crtc_state *ofdrm_crtc_state = to_ofdrm_crtc_state(crtc_state);
+
+ if (crtc_state->enable && crtc_state->color_mgmt_changed) {
+ const struct drm_format_info *format = ofdrm_crtc_state->format;
+
+ if (crtc_state->gamma_lut)
+ ofdrm_device_set_gamma(odev, format, crtc_state->gamma_lut->data);
+ else
+ ofdrm_device_set_gamma_linear(odev, format);
+ }
+}
+
+/*
+ * The CRTC is always enabled. Screen updates are performed by
+ * the primary plane's atomic_update function. Disabling clears
+ * the screen in the primary plane's atomic_disable function.
+ */
+static const struct drm_crtc_helper_funcs ofdrm_crtc_helper_funcs = {
+ .mode_valid = ofdrm_crtc_helper_mode_valid,
+ .atomic_check = ofdrm_crtc_helper_atomic_check,
+ .atomic_flush = ofdrm_crtc_helper_atomic_flush,
+};
+
+static void ofdrm_crtc_reset(struct drm_crtc *crtc)
+{
+ struct ofdrm_crtc_state *ofdrm_crtc_state =
+ kzalloc(sizeof(*ofdrm_crtc_state), GFP_KERNEL);
+
+ if (crtc->state)
+ ofdrm_crtc_state_destroy(to_ofdrm_crtc_state(crtc->state));
+
+ if (ofdrm_crtc_state)
+ __drm_atomic_helper_crtc_reset(crtc, &ofdrm_crtc_state->base);
+ else
+ __drm_atomic_helper_crtc_reset(crtc, NULL);
+}
+
+static struct drm_crtc_state *ofdrm_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct drm_crtc_state *crtc_state = crtc->state;
+ struct ofdrm_crtc_state *new_ofdrm_crtc_state;
+ struct ofdrm_crtc_state *ofdrm_crtc_state;
+
+ if (drm_WARN_ON(dev, !crtc_state))
+ return NULL;
+
+ new_ofdrm_crtc_state = kzalloc(sizeof(*new_ofdrm_crtc_state), GFP_KERNEL);
+ if (!new_ofdrm_crtc_state)
+ return NULL;
+
+ ofdrm_crtc_state = to_ofdrm_crtc_state(crtc_state);
+
+ __drm_atomic_helper_crtc_duplicate_state(crtc, &new_ofdrm_crtc_state->base);
+ new_ofdrm_crtc_state->format = ofdrm_crtc_state->format;
+
+ return &new_ofdrm_crtc_state->base;
+}
+
+static void ofdrm_crtc_atomic_destroy_state(struct drm_crtc *crtc,
+ struct drm_crtc_state *crtc_state)
+{
+ ofdrm_crtc_state_destroy(to_ofdrm_crtc_state(crtc_state));
+}
+
+static const struct drm_crtc_funcs ofdrm_crtc_funcs = {
+ .reset = ofdrm_crtc_reset,
+ .destroy = drm_crtc_cleanup,
+ .set_config = drm_atomic_helper_set_config,
+ .page_flip = drm_atomic_helper_page_flip,
+ .atomic_duplicate_state = ofdrm_crtc_atomic_duplicate_state,
+ .atomic_destroy_state = ofdrm_crtc_atomic_destroy_state,
+};
+
+static int ofdrm_connector_helper_get_modes(struct drm_connector *connector)
+{
+ struct ofdrm_device *odev = ofdrm_device_of_dev(connector->dev);
+
+ return drm_connector_helper_get_modes_fixed(connector, &odev->mode);
+}
+
+static const struct drm_connector_helper_funcs ofdrm_connector_helper_funcs = {
+ .get_modes = ofdrm_connector_helper_get_modes,
+};
+
+static const struct drm_connector_funcs ofdrm_connector_funcs = {
+ .reset = drm_atomic_helper_connector_reset,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = drm_connector_cleanup,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static const struct drm_mode_config_funcs ofdrm_mode_config_funcs = {
+ .fb_create = drm_gem_fb_create_with_dirty,
+ .atomic_check = drm_atomic_helper_check,
+ .atomic_commit = drm_atomic_helper_commit,
+};
+
+/*
+ * Init / Cleanup
+ */
+
+static const struct ofdrm_device_funcs ofdrm_unknown_device_funcs = {
+};
+
+static const struct ofdrm_device_funcs ofdrm_mach64_device_funcs = {
+ .cmap_ioremap = ofdrm_mach64_cmap_ioremap,
+ .cmap_write = ofdrm_mach64_cmap_write,
+};
+
+static const struct ofdrm_device_funcs ofdrm_rage128_device_funcs = {
+ .cmap_ioremap = ofdrm_rage128_cmap_ioremap,
+ .cmap_write = ofdrm_rage128_cmap_write,
+};
+
+static const struct ofdrm_device_funcs ofdrm_rage_m3a_device_funcs = {
+ .cmap_ioremap = ofdrm_rage_m3a_cmap_ioremap,
+ .cmap_write = ofdrm_rage_m3a_cmap_write,
+};
+
+static const struct ofdrm_device_funcs ofdrm_rage_m3b_device_funcs = {
+ .cmap_ioremap = ofdrm_rage_m3b_cmap_ioremap,
+ .cmap_write = ofdrm_rage_m3b_cmap_write,
+};
+
+static const struct ofdrm_device_funcs ofdrm_radeon_device_funcs = {
+ .cmap_ioremap = ofdrm_radeon_cmap_ioremap,
+ .cmap_write = ofdrm_rage128_cmap_write, /* same as Rage128 */
+};
+
+static const struct ofdrm_device_funcs ofdrm_gxt2000_device_funcs = {
+ .cmap_ioremap = ofdrm_gxt2000_cmap_ioremap,
+ .cmap_write = ofdrm_gxt2000_cmap_write,
+};
+
+static const struct ofdrm_device_funcs ofdrm_avivo_device_funcs = {
+ .cmap_ioremap = ofdrm_avivo_cmap_ioremap,
+ .cmap_write = ofdrm_avivo_cmap_write,
+};
+
+static const struct ofdrm_device_funcs ofdrm_qemu_device_funcs = {
+ .cmap_ioremap = ofdrm_qemu_cmap_ioremap,
+ .cmap_write = ofdrm_qemu_cmap_write,
+};
+
+static struct drm_display_mode ofdrm_mode(unsigned int width, unsigned int height)
+{
+ /*
+ * Assume a monitor resolution of 96 dpi to
+ * get a somewhat reasonable screen size.
+ */
+ const struct drm_display_mode mode = {
+ DRM_MODE_INIT(60, width, height,
+ DRM_MODE_RES_MM(width, 96ul),
+ DRM_MODE_RES_MM(height, 96ul))
+ };
+
+ return mode;
+}
+
+static struct ofdrm_device *ofdrm_device_create(struct drm_driver *drv,
+ struct platform_device *pdev)
+{
+ struct device_node *of_node = pdev->dev.of_node;
+ struct ofdrm_device *odev;
+ struct drm_device *dev;
+ enum ofdrm_model model;
+ bool big_endian;
+ int width, height, depth, linebytes;
+ const struct drm_format_info *format;
+ u64 address;
+ resource_size_t fb_size, fb_base, fb_pgbase, fb_pgsize;
+ struct resource *res, *mem;
+ void __iomem *screen_base;
+ struct drm_plane *primary_plane;
+ struct drm_crtc *crtc;
+ struct drm_encoder *encoder;
+ struct drm_connector *connector;
+ unsigned long max_width, max_height;
+ size_t nformats;
+ int ret;
+
+ odev = devm_drm_dev_alloc(&pdev->dev, drv, struct ofdrm_device, dev);
+ if (IS_ERR(odev))
+ return ERR_CAST(odev);
+ dev = &odev->dev;
+ platform_set_drvdata(pdev, dev);
+
+ ret = ofdrm_device_init_pci(odev);
+ if (ret)
+ return ERR_PTR(ret);
+
+ /*
+ * OF display-node settings
+ */
+
+ model = display_get_model_of(dev, of_node);
+ drm_dbg(dev, "detected model %d\n", model);
+
+ switch (model) {
+ case OFDRM_MODEL_UNKNOWN:
+ odev->funcs = &ofdrm_unknown_device_funcs;
+ break;
+ case OFDRM_MODEL_MACH64:
+ odev->funcs = &ofdrm_mach64_device_funcs;
+ break;
+ case OFDRM_MODEL_RAGE128:
+ odev->funcs = &ofdrm_rage128_device_funcs;
+ break;
+ case OFDRM_MODEL_RAGE_M3A:
+ odev->funcs = &ofdrm_rage_m3a_device_funcs;
+ break;
+ case OFDRM_MODEL_RAGE_M3B:
+ odev->funcs = &ofdrm_rage_m3b_device_funcs;
+ break;
+ case OFDRM_MODEL_RADEON:
+ odev->funcs = &ofdrm_radeon_device_funcs;
+ break;
+ case OFDRM_MODEL_GXT2000:
+ odev->funcs = &ofdrm_gxt2000_device_funcs;
+ break;
+ case OFDRM_MODEL_AVIVO:
+ odev->funcs = &ofdrm_avivo_device_funcs;
+ break;
+ case OFDRM_MODEL_QEMU:
+ odev->funcs = &ofdrm_qemu_device_funcs;
+ break;
+ }
+
+ big_endian = display_get_big_endian_of(dev, of_node);
+
+ width = display_get_width_of(dev, of_node);
+ if (width < 0)
+ return ERR_PTR(width);
+ height = display_get_height_of(dev, of_node);
+ if (height < 0)
+ return ERR_PTR(height);
+ depth = display_get_depth_of(dev, of_node);
+ if (depth < 0)
+ return ERR_PTR(depth);
+ linebytes = display_get_linebytes_of(dev, of_node);
+ if (linebytes < 0)
+ return ERR_PTR(linebytes);
+
+ format = display_get_validated_format(dev, depth, big_endian);
+ if (IS_ERR(format))
+ return ERR_CAST(format);
+ if (!linebytes) {
+ linebytes = drm_format_info_min_pitch(format, 0, width);
+ if (drm_WARN_ON(dev, !linebytes))
+ return ERR_PTR(-EINVAL);
+ }
+
+ fb_size = linebytes * height;
+
+ /*
+ * Try to figure out the address of the framebuffer. Unfortunately, Open
+ * Firmware doesn't provide a standard way to do so. All we can do is a
+ * dodgy heuristic that happens to work in practice.
+ *
+ * On most machines, the "address" property contains what we need, though
+ * not on Matrox cards found in IBM machines. What appears to give good
+ * results is to go through the PCI ranges and pick one that encloses the
+ * "address" property. If none match, we pick the largest.
+ */
+ address = display_get_address_of(dev, of_node);
+ if (address != OF_BAD_ADDR) {
+ struct resource fb_res = DEFINE_RES_MEM(address, fb_size);
+
+ res = ofdrm_find_fb_resource(odev, &fb_res);
+ if (!res)
+ return ERR_PTR(-EINVAL);
+ if (resource_contains(res, &fb_res))
+ fb_base = address;
+ else
+ fb_base = res->start;
+ } else {
+ struct resource fb_res = DEFINE_RES_MEM(0u, fb_size);
+
+ res = ofdrm_find_fb_resource(odev, &fb_res);
+ if (!res)
+ return ERR_PTR(-EINVAL);
+ fb_base = res->start;
+ }
+
+ /*
+ * I/O resources
+ */
+
+ fb_pgbase = round_down(fb_base, PAGE_SIZE);
+ fb_pgsize = fb_base - fb_pgbase + round_up(fb_size, PAGE_SIZE);
+
+ ret = devm_aperture_acquire_from_firmware(dev, fb_pgbase, fb_pgsize);
+ if (ret) {
+ drm_err(dev, "could not acquire memory range %pr: error %d\n", &res, ret);
+ return ERR_PTR(ret);
+ }
+
+ mem = devm_request_mem_region(&pdev->dev, fb_pgbase, fb_pgsize, drv->name);
+ if (!mem) {
+ drm_warn(dev, "could not acquire memory region %pr\n", &res);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ screen_base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+ if (!screen_base)
+ return ERR_PTR(-ENOMEM);
+
+ if (odev->funcs->cmap_ioremap) {
+ void __iomem *cmap_base = odev->funcs->cmap_ioremap(odev, of_node, fb_base);
+
+ if (IS_ERR(cmap_base)) {
+ /* Don't fail; continue without colormap */
+ drm_warn(dev, "could not find colormap: error %ld\n", PTR_ERR(cmap_base));
+ } else {
+ odev->cmap_base = cmap_base;
+ }
+ }
+
+ /*
+ * Firmware framebuffer
+ */
+
+ iosys_map_set_vaddr_iomem(&odev->screen_base, screen_base);
+ odev->mode = ofdrm_mode(width, height);
+ odev->format = format;
+ odev->pitch = linebytes;
+
+ drm_dbg(dev, "display mode={" DRM_MODE_FMT "}\n", DRM_MODE_ARG(&odev->mode));
+ drm_dbg(dev, "framebuffer format=%p4cc, size=%dx%d, linebytes=%d byte\n",
+ &format->format, width, height, linebytes);
+
+ /*
+ * Mode-setting pipeline
+ */
+
+ ret = drmm_mode_config_init(dev);
+ if (ret)
+ return ERR_PTR(ret);
+
+ max_width = max_t(unsigned long, width, DRM_SHADOW_PLANE_MAX_WIDTH);
+ max_height = max_t(unsigned long, height, DRM_SHADOW_PLANE_MAX_HEIGHT);
+
+ dev->mode_config.min_width = width;
+ dev->mode_config.max_width = max_width;
+ dev->mode_config.min_height = height;
+ dev->mode_config.max_height = max_height;
+ dev->mode_config.funcs = &ofdrm_mode_config_funcs;
+ switch (depth) {
+ case 32:
+ dev->mode_config.preferred_depth = 24;
+ break;
+ default:
+ dev->mode_config.preferred_depth = depth;
+ break;
+ }
+ dev->mode_config.quirk_addfb_prefer_host_byte_order = true;
+
+ /* Primary plane */
+
+ nformats = drm_fb_build_fourcc_list(dev, &format->format, 1,
+ ofdrm_primary_plane_formats,
+ ARRAY_SIZE(ofdrm_primary_plane_formats),
+ odev->formats, ARRAY_SIZE(odev->formats));
+
+ primary_plane = &odev->primary_plane;
+ ret = drm_universal_plane_init(dev, primary_plane, 0, &ofdrm_primary_plane_funcs,
+ odev->formats, nformats,
+ ofdrm_primary_plane_format_modifiers,
+ DRM_PLANE_TYPE_PRIMARY, NULL);
+ if (ret)
+ return ERR_PTR(ret);
+ drm_plane_helper_add(primary_plane, &ofdrm_primary_plane_helper_funcs);
+ drm_plane_enable_fb_damage_clips(primary_plane);
+
+ /* CRTC */
+
+ crtc = &odev->crtc;
+ ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
+ &ofdrm_crtc_funcs, NULL);
+ if (ret)
+ return ERR_PTR(ret);
+ drm_crtc_helper_add(crtc, &ofdrm_crtc_helper_funcs);
+
+ if (odev->cmap_base) {
+ drm_mode_crtc_set_gamma_size(crtc, OFDRM_GAMMA_LUT_SIZE);
+ drm_crtc_enable_color_mgmt(crtc, 0, false, OFDRM_GAMMA_LUT_SIZE);
+ }
+
+ /* Encoder */
+
+ encoder = &odev->encoder;
+ ret = drm_simple_encoder_init(dev, encoder, DRM_MODE_ENCODER_NONE);
+ if (ret)
+ return ERR_PTR(ret);
+ encoder->possible_crtcs = drm_crtc_mask(crtc);
+
+ /* Connector */
+
+ connector = &odev->connector;
+ ret = drm_connector_init(dev, connector, &ofdrm_connector_funcs,
+ DRM_MODE_CONNECTOR_Unknown);
+ if (ret)
+ return ERR_PTR(ret);
+ drm_connector_helper_add(connector, &ofdrm_connector_helper_funcs);
+ drm_connector_set_panel_orientation_with_quirk(connector,
+ DRM_MODE_PANEL_ORIENTATION_UNKNOWN,
+ width, height);
+
+ ret = drm_connector_attach_encoder(connector, encoder);
+ if (ret)
+ return ERR_PTR(ret);
+
+ drm_mode_config_reset(dev);
+
+ return odev;
+}
+
+/*
+ * DRM driver
+ */
+
+DEFINE_DRM_GEM_FOPS(ofdrm_fops);
+
+static struct drm_driver ofdrm_driver = {
+ DRM_GEM_SHMEM_DRIVER_OPS,
+ .name = DRIVER_NAME,
+ .desc = DRIVER_DESC,
+ .date = DRIVER_DATE,
+ .major = DRIVER_MAJOR,
+ .minor = DRIVER_MINOR,
+ .driver_features = DRIVER_ATOMIC | DRIVER_GEM | DRIVER_MODESET,
+ .fops = &ofdrm_fops,
+};
+
+/*
+ * Platform driver
+ */
+
+static int ofdrm_probe(struct platform_device *pdev)
+{
+ struct ofdrm_device *odev;
+ struct drm_device *dev;
+ int ret;
+
+ odev = ofdrm_device_create(&ofdrm_driver, pdev);
+ if (IS_ERR(odev))
+ return PTR_ERR(odev);
+ dev = &odev->dev;
+
+ ret = drm_dev_register(dev, 0);
+ if (ret)
+ return ret;
+
+ /*
+ * FIXME: 24-bit color depth does not work reliably with a 32-bpp
+ * value. Force the bpp value of the scanout buffer's format.
+ */
+ drm_fbdev_generic_setup(dev, drm_format_info_bpp(odev->format, 0));
+
+ return 0;
+}
+
+static int ofdrm_remove(struct platform_device *pdev)
+{
+ struct drm_device *dev = platform_get_drvdata(pdev);
+
+ drm_dev_unplug(dev);
+
+ return 0;
+}
+
+static const struct of_device_id ofdrm_of_match_display[] = {
+ { .compatible = "display", },
+ { },
+};
+MODULE_DEVICE_TABLE(of, ofdrm_of_match_display);
+
+static struct platform_driver ofdrm_platform_driver = {
+ .driver = {
+ .name = "of-display",
+ .of_match_table = ofdrm_of_match_display,
+ },
+ .probe = ofdrm_probe,
+ .remove = ofdrm_remove,
+};
+
+module_platform_driver(ofdrm_platform_driver);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/tiny/panel-mipi-dbi.c b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
index 955a61d628e7..03a7d569cd56 100644
--- a/drivers/gpu/drm/tiny/panel-mipi-dbi.c
+++ b/drivers/gpu/drm/tiny/panel-mipi-dbi.c
@@ -16,7 +16,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c
index e62f4d16b2c6..c2677d081a7b 100644
--- a/drivers/gpu/drm/tiny/repaper.c
+++ b/drivers/gpu/drm/tiny/repaper.c
@@ -26,7 +26,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_dma_helper.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 18489779fb8a..162eb44dcba8 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -11,10 +11,11 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_connector.h>
+#include <drm/drm_crtc_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_device.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
@@ -545,19 +546,6 @@ static enum drm_mode_status simpledrm_crtc_helper_mode_valid(struct drm_crtc *cr
return drm_crtc_helper_mode_valid_fixed(crtc, mode, &sdev->mode);
}
-static int simpledrm_crtc_helper_atomic_check(struct drm_crtc *crtc,
- struct drm_atomic_state *new_state)
-{
- struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
- int ret;
-
- ret = drm_atomic_helper_check_crtc_state(new_crtc_state, false);
- if (ret)
- return ret;
-
- return drm_atomic_add_affected_planes(new_state, crtc);
-}
-
/*
* The CRTC is always enabled. Screen updates are performed by
* the primary plane's atomic_update function. Disabling clears
@@ -565,7 +553,7 @@ static int simpledrm_crtc_helper_atomic_check(struct drm_crtc *crtc,
*/
static const struct drm_crtc_helper_funcs simpledrm_crtc_helper_funcs = {
.mode_valid = simpledrm_crtc_helper_mode_valid,
- .atomic_check = simpledrm_crtc_helper_atomic_check,
+ .atomic_check = drm_crtc_helper_atomic_check,
};
static const struct drm_crtc_funcs simpledrm_crtc_funcs = {
diff --git a/drivers/gpu/drm/tiny/st7586.c b/drivers/gpu/drm/tiny/st7586.c
index b6f620b902e6..ce57fa9917e5 100644
--- a/drivers/gpu/drm/tiny/st7586.c
+++ b/drivers/gpu/drm/tiny/st7586.c
@@ -16,7 +16,7 @@
#include <drm/drm_damage_helper.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_dma_helper.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_format_helper.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
diff --git a/drivers/gpu/drm/tiny/st7735r.c b/drivers/gpu/drm/tiny/st7735r.c
index c36ba08acda1..15d9cf283c66 100644
--- a/drivers/gpu/drm/tiny/st7735r.c
+++ b/drivers/gpu/drm/tiny/st7735r.c
@@ -18,7 +18,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_managed.h>
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 7c8e8be774f1..c3f4b33136e5 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -51,9 +51,6 @@ static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo,
struct ttm_resource_manager *man;
int i, mem_type;
- drm_printf(&p, "No space for %p (%lu pages, %zuK, %zuM)\n",
- bo, bo->resource->num_pages, bo->base.size >> 10,
- bo->base.size >> 20);
for (i = 0; i < placement->num_placement; i++) {
mem_type = placement->placement[i].mem_type;
drm_printf(&p, " placement[%d]=0x%08X (%d)\n",
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index fa04e62202c1..ba3aa0a0fc43 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -173,7 +173,7 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
clear = src_iter->ops->maps_tt && (!ttm || !ttm_tt_is_populated(ttm));
if (!(clear && ttm && !(ttm->page_flags & TTM_TT_FLAG_ZERO_ALLOC)))
- ttm_move_memcpy(clear, dst_mem->num_pages, dst_iter, src_iter);
+ ttm_move_memcpy(clear, ttm->num_pages, dst_iter, src_iter);
if (!src_iter->ops->maps_tt)
ttm_kmap_iter_linear_io_fini(&_src_iter.io, bdev, src_mem);
@@ -357,9 +357,9 @@ int ttm_bo_kmap(struct ttm_buffer_object *bo,
map->virtual = NULL;
map->bo = bo;
- if (num_pages > bo->resource->num_pages)
+ if (num_pages > PFN_UP(bo->resource->size))
return -EINVAL;
- if ((start_page + num_pages) > bo->resource->num_pages)
+ if ((start_page + num_pages) > PFN_UP(bo->resource->size))
return -EINVAL;
ret = ttm_mem_io_reserve(bo->bdev, bo->resource);
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
index 38119311284d..5a3e4b891377 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
@@ -217,7 +217,7 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf,
page_last = vma_pages(vma) + vma->vm_pgoff -
drm_vma_node_start(&bo->base.vma_node);
- if (unlikely(page_offset >= bo->resource->num_pages))
+ if (unlikely(page_offset >= PFN_UP(bo->base.size)))
return VM_FAULT_SIGBUS;
prot = ttm_io_prot(bo, bo->resource, prot);
@@ -412,7 +412,7 @@ int ttm_bo_vm_access(struct vm_area_struct *vma, unsigned long addr,
<< PAGE_SHIFT);
int ret;
- if (len < 1 || (offset + len) >> PAGE_SHIFT > bo->resource->num_pages)
+ if (len < 1 || (offset + len) > bo->base.size)
return -EIO;
ret = ttm_bo_reserve(bo, true, false, NULL);
diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c
index 21b61631f73a..9f6764bf3b15 100644
--- a/drivers/gpu/drm/ttm/ttm_pool.c
+++ b/drivers/gpu/drm/ttm/ttm_pool.c
@@ -344,6 +344,28 @@ static unsigned int ttm_pool_page_order(struct ttm_pool *pool, struct page *p)
return p->private;
}
+/* Called when we got a page, either from a pool or newly allocated */
+static int ttm_pool_page_allocated(struct ttm_pool *pool, unsigned int order,
+ struct page *p, dma_addr_t **dma_addr,
+ unsigned long *num_pages,
+ struct page ***pages)
+{
+ unsigned int i;
+ int r;
+
+ if (*dma_addr) {
+ r = ttm_pool_map(pool, order, p, dma_addr);
+ if (r)
+ return r;
+ }
+
+ *num_pages -= 1 << order;
+ for (i = 1 << order; i; --i, ++(*pages), ++p)
+ **pages = p;
+
+ return 0;
+}
+
/**
* ttm_pool_alloc - Fill a ttm_tt object
*
@@ -385,45 +407,57 @@ int ttm_pool_alloc(struct ttm_pool *pool, struct ttm_tt *tt,
for (order = min_t(unsigned int, MAX_ORDER - 1, __fls(num_pages));
num_pages;
order = min_t(unsigned int, order, __fls(num_pages))) {
- bool apply_caching = false;
struct ttm_pool_type *pt;
pt = ttm_pool_select_type(pool, tt->caching, order);
p = pt ? ttm_pool_type_take(pt) : NULL;
if (p) {
- apply_caching = true;
- } else {
- p = ttm_pool_alloc_page(pool, gfp_flags, order);
- if (p && PageHighMem(p))
- apply_caching = true;
- }
-
- if (!p) {
- if (order) {
- --order;
- continue;
- }
- r = -ENOMEM;
- goto error_free_all;
- }
-
- if (apply_caching) {
r = ttm_pool_apply_caching(caching, pages,
tt->caching);
if (r)
goto error_free_page;
- caching = pages + (1 << order);
+
+ do {
+ r = ttm_pool_page_allocated(pool, order, p,
+ &dma_addr,
+ &num_pages,
+ &pages);
+ if (r)
+ goto error_free_page;
+
+ if (num_pages < (1 << order))
+ break;
+
+ p = ttm_pool_type_take(pt);
+ } while (p);
+ caching = pages;
}
- if (dma_addr) {
- r = ttm_pool_map(pool, order, p, &dma_addr);
+ while (num_pages >= (1 << order) &&
+ (p = ttm_pool_alloc_page(pool, gfp_flags, order))) {
+
+ if (PageHighMem(p)) {
+ r = ttm_pool_apply_caching(caching, pages,
+ tt->caching);
+ if (r)
+ goto error_free_page;
+ }
+ r = ttm_pool_page_allocated(pool, order, p, &dma_addr,
+ &num_pages, &pages);
if (r)
goto error_free_page;
+ if (PageHighMem(p))
+ caching = pages;
}
- num_pages -= 1 << order;
- for (i = 1 << order; i; --i)
- *(pages++) = p++;
+ if (!p) {
+ if (order) {
+ --order;
+ continue;
+ }
+ r = -ENOMEM;
+ goto error_free_all;
+ }
}
r = ttm_pool_apply_caching(caching, pages, tt->caching);
diff --git a/drivers/gpu/drm/ttm/ttm_range_manager.c b/drivers/gpu/drm/ttm/ttm_range_manager.c
index 4cfef2b3514d..0a8bc0b7f380 100644
--- a/drivers/gpu/drm/ttm/ttm_range_manager.c
+++ b/drivers/gpu/drm/ttm/ttm_range_manager.c
@@ -83,7 +83,7 @@ static int ttm_range_man_alloc(struct ttm_resource_manager *man,
spin_lock(&rman->lock);
ret = drm_mm_insert_node_in_range(mm, &node->mm_nodes[0],
- node->base.num_pages,
+ PFN_UP(node->base.size),
bo->page_alignment, 0,
place->fpfn, lpfn, mode);
spin_unlock(&rman->lock);
@@ -229,7 +229,6 @@ int ttm_range_man_fini_nocheck(struct ttm_device *bdev,
return ret;
spin_lock(&rman->lock);
- drm_mm_clean(mm);
drm_mm_takedown(mm);
spin_unlock(&rman->lock);
diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c
index a729c32a1e48..328391bb1d87 100644
--- a/drivers/gpu/drm/ttm/ttm_resource.c
+++ b/drivers/gpu/drm/ttm/ttm_resource.c
@@ -177,7 +177,7 @@ void ttm_resource_init(struct ttm_buffer_object *bo,
struct ttm_resource_manager *man;
res->start = 0;
- res->num_pages = PFN_UP(bo->base.size);
+ res->size = bo->base.size;
res->mem_type = place->mem_type;
res->placement = place->flags;
res->bus.addr = NULL;
@@ -192,7 +192,7 @@ void ttm_resource_init(struct ttm_buffer_object *bo,
list_add_tail(&res->lru, &bo->bdev->pinned);
else
list_add_tail(&res->lru, &man->lru[bo->priority]);
- man->usage += res->num_pages << PAGE_SHIFT;
+ man->usage += res->size;
spin_unlock(&bo->bdev->lru_lock);
}
EXPORT_SYMBOL(ttm_resource_init);
@@ -214,7 +214,7 @@ void ttm_resource_fini(struct ttm_resource_manager *man,
spin_lock(&bdev->lru_lock);
list_del_init(&res->lru);
- man->usage -= res->num_pages << PAGE_SHIFT;
+ man->usage -= res->size;
spin_unlock(&bdev->lru_lock);
}
EXPORT_SYMBOL(ttm_resource_fini);
@@ -665,17 +665,15 @@ ttm_kmap_iter_linear_io_init(struct ttm_kmap_iter_linear_io *iter_io,
iosys_map_set_vaddr(&iter_io->dmap, mem->bus.addr);
iter_io->needs_unmap = false;
} else {
- size_t bus_size = (size_t)mem->num_pages << PAGE_SHIFT;
-
iter_io->needs_unmap = true;
memset(&iter_io->dmap, 0, sizeof(iter_io->dmap));
if (mem->bus.caching == ttm_write_combined)
iosys_map_set_vaddr_iomem(&iter_io->dmap,
ioremap_wc(mem->bus.offset,
- bus_size));
+ mem->size));
else if (mem->bus.caching == ttm_cached)
iosys_map_set_vaddr(&iter_io->dmap,
- memremap(mem->bus.offset, bus_size,
+ memremap(mem->bus.offset, mem->size,
MEMREMAP_WB |
MEMREMAP_WT |
MEMREMAP_WC));
@@ -684,7 +682,7 @@ ttm_kmap_iter_linear_io_init(struct ttm_kmap_iter_linear_io *iter_io,
if (iosys_map_is_null(&iter_io->dmap))
iosys_map_set_vaddr_iomem(&iter_io->dmap,
ioremap(mem->bus.offset,
- bus_size));
+ mem->size));
if (iosys_map_is_null(&iter_io->dmap)) {
ret = -ENOMEM;
diff --git a/drivers/gpu/drm/tve200/tve200_drv.c b/drivers/gpu/drm/tve200/tve200_drv.c
index 04db72e3fa9c..0d05c386d303 100644
--- a/drivers/gpu/drm/tve200/tve200_drv.c
+++ b/drivers/gpu/drm/tve200/tve200_drv.c
@@ -32,6 +32,7 @@
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/shmem_fs.h>
#include <linux/slab.h>
@@ -39,7 +40,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_dma_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_module.h>
diff --git a/drivers/gpu/drm/udl/Makefile b/drivers/gpu/drm/udl/Makefile
index 24d61f61d7db..3f6db179455d 100644
--- a/drivers/gpu/drm/udl/Makefile
+++ b/drivers/gpu/drm/udl/Makefile
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
-udl-y := udl_drv.o udl_modeset.o udl_connector.o udl_main.o udl_transfer.o
+udl-y := udl_drv.o udl_modeset.o udl_main.o udl_transfer.o
obj-$(CONFIG_DRM_UDL) := udl.o
diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
deleted file mode 100644
index fade4c7adbf7..000000000000
--- a/drivers/gpu/drm/udl/udl_connector.c
+++ /dev/null
@@ -1,139 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Copyright (C) 2012 Red Hat
- * based in parts on udlfb.c:
- * Copyright (C) 2009 Roberto De Ioris <roberto@unbit.it>
- * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com>
- * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
- */
-
-#include <drm/drm_atomic_state_helper.h>
-#include <drm/drm_edid.h>
-#include <drm/drm_crtc_helper.h>
-#include <drm/drm_probe_helper.h>
-
-#include "udl_connector.h"
-#include "udl_drv.h"
-
-static int udl_get_edid_block(void *data, u8 *buf, unsigned int block,
- size_t len)
-{
- int ret, i;
- u8 *read_buff;
- struct udl_device *udl = data;
- struct usb_device *udev = udl_to_usb_device(udl);
-
- read_buff = kmalloc(2, GFP_KERNEL);
- if (!read_buff)
- return -1;
-
- for (i = 0; i < len; i++) {
- int bval = (i + block * EDID_LENGTH) << 8;
- ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
- 0x02, (0x80 | (0x02 << 5)), bval,
- 0xA1, read_buff, 2, 1000);
- if (ret < 1) {
- DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret);
- kfree(read_buff);
- return -1;
- }
- buf[i] = read_buff[1];
- }
-
- kfree(read_buff);
- return 0;
-}
-
-static int udl_get_modes(struct drm_connector *connector)
-{
- struct udl_drm_connector *udl_connector =
- container_of(connector,
- struct udl_drm_connector,
- connector);
-
- drm_connector_update_edid_property(connector, udl_connector->edid);
- if (udl_connector->edid)
- return drm_add_edid_modes(connector, udl_connector->edid);
- return 0;
-}
-
-static enum drm_mode_status udl_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
-{
- struct udl_device *udl = to_udl(connector->dev);
- if (!udl->sku_pixel_limit)
- return 0;
-
- if (mode->vdisplay * mode->hdisplay > udl->sku_pixel_limit)
- return MODE_VIRTUAL_Y;
-
- return 0;
-}
-
-static enum drm_connector_status
-udl_detect(struct drm_connector *connector, bool force)
-{
- struct udl_device *udl = to_udl(connector->dev);
- struct udl_drm_connector *udl_connector =
- container_of(connector,
- struct udl_drm_connector,
- connector);
-
- /* cleanup previous edid */
- if (udl_connector->edid != NULL) {
- kfree(udl_connector->edid);
- udl_connector->edid = NULL;
- }
-
- udl_connector->edid = drm_do_get_edid(connector, udl_get_edid_block, udl);
- if (!udl_connector->edid)
- return connector_status_disconnected;
-
- return connector_status_connected;
-}
-
-static void udl_connector_destroy(struct drm_connector *connector)
-{
- struct udl_drm_connector *udl_connector =
- container_of(connector,
- struct udl_drm_connector,
- connector);
-
- drm_connector_cleanup(connector);
- kfree(udl_connector->edid);
- kfree(connector);
-}
-
-static const struct drm_connector_helper_funcs udl_connector_helper_funcs = {
- .get_modes = udl_get_modes,
- .mode_valid = udl_mode_valid,
-};
-
-static const struct drm_connector_funcs udl_connector_funcs = {
- .reset = drm_atomic_helper_connector_reset,
- .detect = udl_detect,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = udl_connector_destroy,
- .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
-};
-
-struct drm_connector *udl_connector_init(struct drm_device *dev)
-{
- struct udl_drm_connector *udl_connector;
- struct drm_connector *connector;
-
- udl_connector = kzalloc(sizeof(struct udl_drm_connector), GFP_KERNEL);
- if (!udl_connector)
- return ERR_PTR(-ENOMEM);
-
- connector = &udl_connector->connector;
- drm_connector_init(dev, connector, &udl_connector_funcs,
- DRM_MODE_CONNECTOR_VGA);
- drm_connector_helper_add(connector, &udl_connector_helper_funcs);
-
- connector->polled = DRM_CONNECTOR_POLL_HPD |
- DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
-
- return connector;
-}
diff --git a/drivers/gpu/drm/udl/udl_connector.h b/drivers/gpu/drm/udl/udl_connector.h
deleted file mode 100644
index 7f2d392df173..000000000000
--- a/drivers/gpu/drm/udl/udl_connector.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __UDL_CONNECTOR_H__
-#define __UDL_CONNECTOR_H__
-
-#include <drm/drm_crtc.h>
-
-struct edid;
-
-struct udl_drm_connector {
- struct drm_connector connector;
- /* last udl_detect edid */
- struct edid *edid;
-};
-
-
-#endif //__UDL_CONNECTOR_H__
diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c
index 91effdcefb6d..e81352126a0f 100644
--- a/drivers/gpu/drm/udl/udl_drv.c
+++ b/drivers/gpu/drm/udl/udl_drv.c
@@ -7,7 +7,7 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_file.h>
#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_managed.h>
diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h
index b4cc7cc568c7..282ebd6c02fd 100644
--- a/drivers/gpu/drm/udl/udl_drv.h
+++ b/drivers/gpu/drm/udl/udl_drv.h
@@ -14,10 +14,13 @@
#include <linux/mm_types.h>
#include <linux/usb.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc.h>
#include <drm/drm_device.h>
+#include <drm/drm_encoder.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem.h>
-#include <drm/drm_simple_kms_helper.h>
+#include <drm/drm_plane.h>
struct drm_mode_create_dumb;
@@ -46,21 +49,31 @@ struct urb_list {
size_t size;
};
+struct udl_connector {
+ struct drm_connector connector;
+ /* last udl_detect edid */
+ struct edid *edid;
+};
+
+static inline struct udl_connector *to_udl_connector(struct drm_connector *connector)
+{
+ return container_of(connector, struct udl_connector, connector);
+}
+
struct udl_device {
struct drm_device drm;
struct device *dev;
struct device *dmadev;
- struct drm_simple_display_pipe display_pipe;
+ struct drm_plane primary_plane;
+ struct drm_crtc crtc;
+ struct drm_encoder encoder;
struct mutex gem_lock;
int sku_pixel_limit;
struct urb_list urbs;
-
- char mode_buf[1024];
- uint32_t mode_buf_len;
};
#define to_udl(x) container_of(x, struct udl_device, drm)
@@ -89,23 +102,4 @@ int udl_render_hline(struct drm_device *dev, int log_bpp, struct urb **urb_ptr,
int udl_drop_usb(struct drm_device *dev);
int udl_select_std_channel(struct udl_device *udl);
-#define CMD_WRITE_RAW8 "\xAF\x60" /**< 8 bit raw write command. */
-#define CMD_WRITE_RL8 "\xAF\x61" /**< 8 bit run length command. */
-#define CMD_WRITE_COPY8 "\xAF\x62" /**< 8 bit copy command. */
-#define CMD_WRITE_RLX8 "\xAF\x63" /**< 8 bit extended run length command. */
-
-#define CMD_WRITE_RAW16 "\xAF\x68" /**< 16 bit raw write command. */
-#define CMD_WRITE_RL16 "\xAF\x69" /**< 16 bit run length command. */
-#define CMD_WRITE_COPY16 "\xAF\x6A" /**< 16 bit copy command. */
-#define CMD_WRITE_RLX16 "\xAF\x6B" /**< 16 bit extended run length command. */
-
-/* On/Off for driving the DisplayLink framebuffer to the display */
-#define UDL_REG_BLANK_MODE 0x1f
-
-#define UDL_BLANK_MODE_ON 0x00 /* hsync and vsync on, visible */
-#define UDL_BLANK_MODE_BLANKED 0x01 /* hsync and vsync on, blanked */
-#define UDL_BLANK_MODE_VSYNC_OFF 0x03 /* vsync off, blanked */
-#define UDL_BLANK_MODE_HSYNC_OFF 0x05 /* hsync off, blanked */
-#define UDL_BLANK_MODE_POWERDOWN 0x07 /* powered off; requires modeset */
-
#endif
diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c
index ec6876f449f3..4b79d44752c9 100644
--- a/drivers/gpu/drm/udl/udl_modeset.c
+++ b/drivers/gpu/drm/udl/udl_modeset.c
@@ -8,70 +8,91 @@
* Copyright (C) 2009 Bernie Thompson <bernie@plugable.com>
*/
+#include <linux/bitfield.h>
+
+#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_damage_helper.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_edid.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_gem_shmem_helper.h>
#include <drm/drm_modeset_helper_vtables.h>
+#include <drm/drm_plane_helper.h>
+#include <drm/drm_probe_helper.h>
#include <drm/drm_vblank.h>
#include "udl_drv.h"
-
-#define UDL_COLOR_DEPTH_16BPP 0
+#include "udl_proto.h"
/*
- * All DisplayLink bulk operations start with 0xAF, followed by specific code
- * All operations are written to buffers which then later get sent to device
+ * All DisplayLink bulk operations start with 0xaf (UDL_MSG_BULK), followed by
+ * a specific command code. All operations are written to a command buffer, which
+ * the driver sends to the device.
*/
static char *udl_set_register(char *buf, u8 reg, u8 val)
{
- *buf++ = 0xAF;
- *buf++ = 0x20;
+ *buf++ = UDL_MSG_BULK;
+ *buf++ = UDL_CMD_WRITEREG;
*buf++ = reg;
*buf++ = val;
+
return buf;
}
static char *udl_vidreg_lock(char *buf)
{
- return udl_set_register(buf, 0xFF, 0x00);
+ return udl_set_register(buf, UDL_REG_VIDREG, UDL_VIDREG_LOCK);
}
static char *udl_vidreg_unlock(char *buf)
{
- return udl_set_register(buf, 0xFF, 0xFF);
+ return udl_set_register(buf, UDL_REG_VIDREG, UDL_VIDREG_UNLOCK);
}
static char *udl_set_blank_mode(char *buf, u8 mode)
{
- return udl_set_register(buf, UDL_REG_BLANK_MODE, mode);
+ return udl_set_register(buf, UDL_REG_BLANKMODE, mode);
}
static char *udl_set_color_depth(char *buf, u8 selection)
{
- return udl_set_register(buf, 0x00, selection);
+ return udl_set_register(buf, UDL_REG_COLORDEPTH, selection);
}
-static char *udl_set_base16bpp(char *wrptr, u32 base)
+static char *udl_set_base16bpp(char *buf, u32 base)
{
- /* the base pointer is 16 bits wide, 0x20 is hi byte. */
- wrptr = udl_set_register(wrptr, 0x20, base >> 16);
- wrptr = udl_set_register(wrptr, 0x21, base >> 8);
- return udl_set_register(wrptr, 0x22, base);
+ /* the base pointer is 24 bits wide, 0x20 is hi byte. */
+ u8 reg20 = FIELD_GET(UDL_BASE_ADDR2_MASK, base);
+ u8 reg21 = FIELD_GET(UDL_BASE_ADDR1_MASK, base);
+ u8 reg22 = FIELD_GET(UDL_BASE_ADDR0_MASK, base);
+
+ buf = udl_set_register(buf, UDL_REG_BASE16BPP_ADDR2, reg20);
+ buf = udl_set_register(buf, UDL_REG_BASE16BPP_ADDR1, reg21);
+ buf = udl_set_register(buf, UDL_REG_BASE16BPP_ADDR0, reg22);
+
+ return buf;
}
/*
* DisplayLink HW has separate 16bpp and 8bpp framebuffers.
* In 24bpp modes, the low 323 RGB bits go in the 8bpp framebuffer
*/
-static char *udl_set_base8bpp(char *wrptr, u32 base)
+static char *udl_set_base8bpp(char *buf, u32 base)
{
- wrptr = udl_set_register(wrptr, 0x26, base >> 16);
- wrptr = udl_set_register(wrptr, 0x27, base >> 8);
- return udl_set_register(wrptr, 0x28, base);
+ /* the base pointer is 24 bits wide, 0x26 is hi byte. */
+ u8 reg26 = FIELD_GET(UDL_BASE_ADDR2_MASK, base);
+ u8 reg27 = FIELD_GET(UDL_BASE_ADDR1_MASK, base);
+ u8 reg28 = FIELD_GET(UDL_BASE_ADDR0_MASK, base);
+
+ buf = udl_set_register(buf, UDL_REG_BASE8BPP_ADDR2, reg26);
+ buf = udl_set_register(buf, UDL_REG_BASE8BPP_ADDR1, reg27);
+ buf = udl_set_register(buf, UDL_REG_BASE8BPP_ADDR0, reg28);
+
+ return buf;
}
static char *udl_set_register_16(char *wrptr, u8 reg, u16 value)
@@ -122,84 +143,46 @@ static char *udl_set_register_lfsr16(char *wrptr, u8 reg, u16 value)
}
/*
- * This takes a standard fbdev screeninfo struct and all of its monitor mode
- * details and converts them into the DisplayLink equivalent register commands.
- ERR(vreg(dev, 0x00, (color_depth == 16) ? 0 : 1));
- ERR(vreg_lfsr16(dev, 0x01, xDisplayStart));
- ERR(vreg_lfsr16(dev, 0x03, xDisplayEnd));
- ERR(vreg_lfsr16(dev, 0x05, yDisplayStart));
- ERR(vreg_lfsr16(dev, 0x07, yDisplayEnd));
- ERR(vreg_lfsr16(dev, 0x09, xEndCount));
- ERR(vreg_lfsr16(dev, 0x0B, hSyncStart));
- ERR(vreg_lfsr16(dev, 0x0D, hSyncEnd));
- ERR(vreg_big_endian(dev, 0x0F, hPixels));
- ERR(vreg_lfsr16(dev, 0x11, yEndCount));
- ERR(vreg_lfsr16(dev, 0x13, vSyncStart));
- ERR(vreg_lfsr16(dev, 0x15, vSyncEnd));
- ERR(vreg_big_endian(dev, 0x17, vPixels));
- ERR(vreg_little_endian(dev, 0x1B, pixelClock5KHz));
-
- ERR(vreg(dev, 0x1F, 0));
-
- ERR(vbuf(dev, WRITE_VIDREG_UNLOCK, DSIZEOF(WRITE_VIDREG_UNLOCK)));
+ * Takes a DRM display mode and converts it into the DisplayLink
+ * equivalent register commands.
*/
-static char *udl_set_vid_cmds(char *wrptr, struct drm_display_mode *mode)
+static char *udl_set_display_mode(char *buf, struct drm_display_mode *mode)
{
- u16 xds, yds;
- u16 xde, yde;
- u16 yec;
-
- /* x display start */
- xds = mode->crtc_htotal - mode->crtc_hsync_start;
- wrptr = udl_set_register_lfsr16(wrptr, 0x01, xds);
- /* x display end */
- xde = xds + mode->crtc_hdisplay;
- wrptr = udl_set_register_lfsr16(wrptr, 0x03, xde);
-
- /* y display start */
- yds = mode->crtc_vtotal - mode->crtc_vsync_start;
- wrptr = udl_set_register_lfsr16(wrptr, 0x05, yds);
- /* y display end */
- yde = yds + mode->crtc_vdisplay;
- wrptr = udl_set_register_lfsr16(wrptr, 0x07, yde);
-
- /* x end count is active + blanking - 1 */
- wrptr = udl_set_register_lfsr16(wrptr, 0x09,
- mode->crtc_htotal - 1);
+ u16 reg01 = mode->crtc_htotal - mode->crtc_hsync_start;
+ u16 reg03 = reg01 + mode->crtc_hdisplay;
+ u16 reg05 = mode->crtc_vtotal - mode->crtc_vsync_start;
+ u16 reg07 = reg05 + mode->crtc_vdisplay;
+ u16 reg09 = mode->crtc_htotal - 1;
+ u16 reg0b = 1; /* libdlo hardcodes hsync start to 1 */
+ u16 reg0d = mode->crtc_hsync_end - mode->crtc_hsync_start + 1;
+ u16 reg0f = mode->hdisplay;
+ u16 reg11 = mode->crtc_vtotal;
+ u16 reg13 = 0; /* libdlo hardcodes vsync start to 0 */
+ u16 reg15 = mode->crtc_vsync_end - mode->crtc_vsync_start;
+ u16 reg17 = mode->crtc_vdisplay;
+ u16 reg1b = mode->clock / 5;
+
+ buf = udl_set_register_lfsr16(buf, UDL_REG_XDISPLAYSTART, reg01);
+ buf = udl_set_register_lfsr16(buf, UDL_REG_XDISPLAYEND, reg03);
+ buf = udl_set_register_lfsr16(buf, UDL_REG_YDISPLAYSTART, reg05);
+ buf = udl_set_register_lfsr16(buf, UDL_REG_YDISPLAYEND, reg07);
+ buf = udl_set_register_lfsr16(buf, UDL_REG_XENDCOUNT, reg09);
+ buf = udl_set_register_lfsr16(buf, UDL_REG_HSYNCSTART, reg0b);
+ buf = udl_set_register_lfsr16(buf, UDL_REG_HSYNCEND, reg0d);
+ buf = udl_set_register_16(buf, UDL_REG_HPIXELS, reg0f);
+ buf = udl_set_register_lfsr16(buf, UDL_REG_YENDCOUNT, reg11);
+ buf = udl_set_register_lfsr16(buf, UDL_REG_VSYNCSTART, reg13);
+ buf = udl_set_register_lfsr16(buf, UDL_REG_VSYNCEND, reg15);
+ buf = udl_set_register_16(buf, UDL_REG_VPIXELS, reg17);
+ buf = udl_set_register_16be(buf, UDL_REG_PIXELCLOCK5KHZ, reg1b);
- /* libdlo hardcodes hsync start to 1 */
- wrptr = udl_set_register_lfsr16(wrptr, 0x0B, 1);
-
- /* hsync end is width of sync pulse + 1 */
- wrptr = udl_set_register_lfsr16(wrptr, 0x0D,
- mode->crtc_hsync_end - mode->crtc_hsync_start + 1);
-
- /* hpixels is active pixels */
- wrptr = udl_set_register_16(wrptr, 0x0F, mode->hdisplay);
-
- /* yendcount is vertical active + vertical blanking */
- yec = mode->crtc_vtotal;
- wrptr = udl_set_register_lfsr16(wrptr, 0x11, yec);
-
- /* libdlo hardcodes vsync start to 0 */
- wrptr = udl_set_register_lfsr16(wrptr, 0x13, 0);
-
- /* vsync end is width of vsync pulse */
- wrptr = udl_set_register_lfsr16(wrptr, 0x15, mode->crtc_vsync_end - mode->crtc_vsync_start);
-
- /* vpixels is active pixels */
- wrptr = udl_set_register_16(wrptr, 0x17, mode->crtc_vdisplay);
-
- wrptr = udl_set_register_16be(wrptr, 0x1B,
- mode->clock / 5);
-
- return wrptr;
+ return buf;
}
static char *udl_dummy_render(char *wrptr)
{
- *wrptr++ = 0xAF;
- *wrptr++ = 0x6A; /* copy */
+ *wrptr++ = UDL_MSG_BULK;
+ *wrptr++ = UDL_CMD_WRITECOPY16;
*wrptr++ = 0x00; /* from addr */
*wrptr++ = 0x00;
*wrptr++ = 0x00;
@@ -210,31 +193,6 @@ static char *udl_dummy_render(char *wrptr)
return wrptr;
}
-static int udl_crtc_write_mode_to_hw(struct drm_crtc *crtc)
-{
- struct drm_device *dev = crtc->dev;
- struct udl_device *udl = to_udl(dev);
- struct urb *urb;
- char *buf;
- int retval;
-
- if (udl->mode_buf_len == 0) {
- DRM_ERROR("No mode set\n");
- return -EINVAL;
- }
-
- urb = udl_get_urb(dev);
- if (!urb)
- return -ENOMEM;
-
- buf = (char *)urb->transfer_buffer;
-
- memcpy(buf, udl->mode_buf, udl->mode_buf_len);
- retval = udl_submit_urb(dev, urb, udl->mode_buf_len);
- DRM_DEBUG("write mode info %d\n", udl->mode_buf_len);
- return retval;
-}
-
static long udl_log_cpp(unsigned int cpp)
{
if (WARN_ON(!is_power_of_2(cpp)))
@@ -258,15 +216,9 @@ static int udl_handle_damage(struct drm_framebuffer *fb,
return ret;
log_bpp = ret;
- ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
- if (ret)
- return ret;
-
urb = udl_get_urb(dev);
- if (!urb) {
- ret = -ENOMEM;
- goto out_drm_gem_fb_end_cpu_access;
- }
+ if (!urb)
+ return -ENOMEM;
cmd = urb->transfer_buffer;
for (i = clip->y1; i < clip->y2; i++) {
@@ -278,145 +230,339 @@ static int udl_handle_damage(struct drm_framebuffer *fb,
&cmd, byte_offset, dev_byte_offset,
byte_width);
if (ret)
- goto out_drm_gem_fb_end_cpu_access;
+ return ret;
}
if (cmd > (char *)urb->transfer_buffer) {
/* Send partial buffer remaining before exiting */
int len;
if (cmd < (char *)urb->transfer_buffer + urb->transfer_buffer_length)
- *cmd++ = 0xAF;
+ *cmd++ = UDL_MSG_BULK;
len = cmd - (char *)urb->transfer_buffer;
ret = udl_submit_urb(dev, urb, len);
} else {
udl_urb_completion(urb);
}
- ret = 0;
-
-out_drm_gem_fb_end_cpu_access:
- drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
- return ret;
+ return 0;
}
/*
- * Simple display pipeline
+ * Primary plane
*/
-static const uint32_t udl_simple_display_pipe_formats[] = {
+static const uint32_t udl_primary_plane_formats[] = {
DRM_FORMAT_RGB565,
DRM_FORMAT_XRGB8888,
};
-static enum drm_mode_status
-udl_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
- const struct drm_display_mode *mode)
+static const uint64_t udl_primary_plane_fmtmods[] = {
+ DRM_FORMAT_MOD_LINEAR,
+ DRM_FORMAT_MOD_INVALID
+};
+
+static void udl_primary_plane_helper_atomic_update(struct drm_plane *plane,
+ struct drm_atomic_state *state)
{
- return MODE_OK;
+ struct drm_device *dev = plane->dev;
+ struct drm_plane_state *plane_state = drm_atomic_get_new_plane_state(state, plane);
+ struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
+ struct drm_framebuffer *fb = plane_state->fb;
+ struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
+ struct drm_atomic_helper_damage_iter iter;
+ struct drm_rect damage;
+ int ret, idx;
+
+ if (!fb)
+ return; /* no framebuffer; plane is disabled */
+
+ ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
+ if (ret)
+ return;
+
+ if (!drm_dev_enter(dev, &idx))
+ goto out_drm_gem_fb_end_cpu_access;
+
+ drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_for_each_plane_damage(&iter, &damage) {
+ udl_handle_damage(fb, &shadow_plane_state->data[0], &damage);
+ }
+
+ drm_dev_exit(idx);
+
+out_drm_gem_fb_end_cpu_access:
+ drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
+}
+
+static const struct drm_plane_helper_funcs udl_primary_plane_helper_funcs = {
+ DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
+ .atomic_check = drm_plane_helper_atomic_check,
+ .atomic_update = udl_primary_plane_helper_atomic_update,
+};
+
+static const struct drm_plane_funcs udl_primary_plane_funcs = {
+ .update_plane = drm_atomic_helper_update_plane,
+ .disable_plane = drm_atomic_helper_disable_plane,
+ .destroy = drm_plane_cleanup,
+ DRM_GEM_SHADOW_PLANE_FUNCS,
+};
+
+/*
+ * CRTC
+ */
+
+static int udl_crtc_helper_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state)
+{
+ struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+
+ if (!new_crtc_state->enable)
+ return 0;
+
+ return drm_atomic_helper_check_crtc_primary_plane(new_crtc_state);
}
-static void
-udl_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
- struct drm_crtc_state *crtc_state,
- struct drm_plane_state *plane_state)
+static void udl_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state)
{
- struct drm_crtc *crtc = &pipe->crtc;
struct drm_device *dev = crtc->dev;
- struct drm_framebuffer *fb = plane_state->fb;
- struct udl_device *udl = to_udl(dev);
+ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
struct drm_display_mode *mode = &crtc_state->mode;
- struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
- struct drm_rect clip = DRM_RECT_INIT(0, 0, fb->width, fb->height);
+ struct urb *urb;
char *buf;
- char *wrptr;
- int color_depth = UDL_COLOR_DEPTH_16BPP;
+ int idx;
- buf = (char *)udl->mode_buf;
+ if (!drm_dev_enter(dev, &idx))
+ return;
- /* This first section has to do with setting the base address on the
- * controller associated with the display. There are 2 base
- * pointers, currently, we only use the 16 bpp segment.
- */
- wrptr = udl_vidreg_lock(buf);
- wrptr = udl_set_color_depth(wrptr, color_depth);
+ urb = udl_get_urb(dev);
+ if (!urb)
+ goto out;
+
+ buf = (char *)urb->transfer_buffer;
+ buf = udl_vidreg_lock(buf);
+ buf = udl_set_color_depth(buf, UDL_COLORDEPTH_16BPP);
/* set base for 16bpp segment to 0 */
- wrptr = udl_set_base16bpp(wrptr, 0);
+ buf = udl_set_base16bpp(buf, 0);
/* set base for 8bpp segment to end of fb */
- wrptr = udl_set_base8bpp(wrptr, 2 * mode->vdisplay * mode->hdisplay);
-
- wrptr = udl_set_vid_cmds(wrptr, mode);
- wrptr = udl_set_blank_mode(wrptr, UDL_BLANK_MODE_ON);
- wrptr = udl_vidreg_unlock(wrptr);
-
- wrptr = udl_dummy_render(wrptr);
-
- udl->mode_buf_len = wrptr - buf;
+ buf = udl_set_base8bpp(buf, 2 * mode->vdisplay * mode->hdisplay);
+ buf = udl_set_display_mode(buf, mode);
+ buf = udl_set_blank_mode(buf, UDL_BLANKMODE_ON);
+ buf = udl_vidreg_unlock(buf);
+ buf = udl_dummy_render(buf);
- udl_handle_damage(fb, &shadow_plane_state->data[0], &clip);
+ udl_submit_urb(dev, urb, buf - (char *)urb->transfer_buffer);
- /* enable display */
- udl_crtc_write_mode_to_hw(crtc);
+out:
+ drm_dev_exit(idx);
}
-static void
-udl_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe)
+static void udl_crtc_helper_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state)
{
- struct drm_crtc *crtc = &pipe->crtc;
struct drm_device *dev = crtc->dev;
struct urb *urb;
char *buf;
+ int idx;
+
+ if (!drm_dev_enter(dev, &idx))
+ return;
urb = udl_get_urb(dev);
if (!urb)
- return;
+ goto out;
buf = (char *)urb->transfer_buffer;
buf = udl_vidreg_lock(buf);
- buf = udl_set_blank_mode(buf, UDL_BLANK_MODE_POWERDOWN);
+ buf = udl_set_blank_mode(buf, UDL_BLANKMODE_POWERDOWN);
buf = udl_vidreg_unlock(buf);
buf = udl_dummy_render(buf);
udl_submit_urb(dev, urb, buf - (char *)urb->transfer_buffer);
+
+out:
+ drm_dev_exit(idx);
+}
+
+static const struct drm_crtc_helper_funcs udl_crtc_helper_funcs = {
+ .atomic_check = udl_crtc_helper_atomic_check,
+ .atomic_enable = udl_crtc_helper_atomic_enable,
+ .atomic_disable = udl_crtc_helper_atomic_disable,
+};
+
+static const struct drm_crtc_funcs udl_crtc_funcs = {
+ .reset = drm_atomic_helper_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,
+};
+
+/*
+ * Encoder
+ */
+
+static const struct drm_encoder_funcs udl_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
+};
+
+/*
+ * Connector
+ */
+
+static int udl_connector_helper_get_modes(struct drm_connector *connector)
+{
+ struct udl_connector *udl_connector = to_udl_connector(connector);
+
+ drm_connector_update_edid_property(connector, udl_connector->edid);
+ if (udl_connector->edid)
+ return drm_add_edid_modes(connector, udl_connector->edid);
+
+ return 0;
}
-static void
-udl_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
- struct drm_plane_state *old_plane_state)
+static const struct drm_connector_helper_funcs udl_connector_helper_funcs = {
+ .get_modes = udl_connector_helper_get_modes,
+};
+
+static int udl_get_edid_block(void *data, u8 *buf, unsigned int block, size_t len)
{
- struct drm_plane_state *state = pipe->plane.state;
- struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state);
- struct drm_framebuffer *fb = state->fb;
- struct drm_rect rect;
+ struct udl_device *udl = data;
+ struct drm_device *dev = &udl->drm;
+ struct usb_device *udev = udl_to_usb_device(udl);
+ u8 *read_buff;
+ int ret;
+ size_t i;
- if (!fb)
- return;
+ read_buff = kmalloc(2, GFP_KERNEL);
+ if (!read_buff)
+ return -ENOMEM;
+
+ for (i = 0; i < len; i++) {
+ int bval = (i + block * EDID_LENGTH) << 8;
+
+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ 0x02, (0x80 | (0x02 << 5)), bval,
+ 0xA1, read_buff, 2, USB_CTRL_GET_TIMEOUT);
+ if (ret < 0) {
+ drm_err(dev, "Read EDID byte %zu failed err %x\n", i, ret);
+ goto err_kfree;
+ } else if (ret < 1) {
+ ret = -EIO;
+ drm_err(dev, "Read EDID byte %zu failed\n", i);
+ goto err_kfree;
+ }
+
+ buf[i] = read_buff[1];
+ }
+
+ kfree(read_buff);
+
+ return 0;
+
+err_kfree:
+ kfree(read_buff);
+ return ret;
+}
+
+static enum drm_connector_status udl_connector_detect(struct drm_connector *connector, bool force)
+{
+ struct drm_device *dev = connector->dev;
+ struct udl_device *udl = to_udl(dev);
+ struct udl_connector *udl_connector = to_udl_connector(connector);
+ enum drm_connector_status status = connector_status_disconnected;
+ int idx;
+
+ /* cleanup previous EDID */
+ kfree(udl_connector->edid);
+ udl_connector->edid = NULL;
+
+ if (!drm_dev_enter(dev, &idx))
+ return connector_status_disconnected;
+
+ udl_connector->edid = drm_do_get_edid(connector, udl_get_edid_block, udl);
+ if (udl_connector->edid)
+ status = connector_status_connected;
+
+ drm_dev_exit(idx);
+
+ return status;
+}
- if (drm_atomic_helper_damage_merged(old_plane_state, state, &rect))
- udl_handle_damage(fb, &shadow_plane_state->data[0], &rect);
+static void udl_connector_destroy(struct drm_connector *connector)
+{
+ struct udl_connector *udl_connector = to_udl_connector(connector);
+
+ drm_connector_cleanup(connector);
+ kfree(udl_connector->edid);
+ kfree(udl_connector);
}
-static const struct drm_simple_display_pipe_funcs udl_simple_display_pipe_funcs = {
- .mode_valid = udl_simple_display_pipe_mode_valid,
- .enable = udl_simple_display_pipe_enable,
- .disable = udl_simple_display_pipe_disable,
- .update = udl_simple_display_pipe_update,
- DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
+static const struct drm_connector_funcs udl_connector_funcs = {
+ .reset = drm_atomic_helper_connector_reset,
+ .detect = udl_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = udl_connector_destroy,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
+struct drm_connector *udl_connector_init(struct drm_device *dev)
+{
+ struct udl_connector *udl_connector;
+ struct drm_connector *connector;
+ int ret;
+
+ udl_connector = kzalloc(sizeof(*udl_connector), GFP_KERNEL);
+ if (!udl_connector)
+ return ERR_PTR(-ENOMEM);
+
+ connector = &udl_connector->connector;
+ ret = drm_connector_init(dev, connector, &udl_connector_funcs, DRM_MODE_CONNECTOR_VGA);
+ if (ret)
+ goto err_kfree;
+
+ drm_connector_helper_add(connector, &udl_connector_helper_funcs);
+
+ connector->polled = DRM_CONNECTOR_POLL_HPD |
+ DRM_CONNECTOR_POLL_CONNECT |
+ DRM_CONNECTOR_POLL_DISCONNECT;
+
+ return connector;
+
+err_kfree:
+ kfree(udl_connector);
+ return ERR_PTR(ret);
+}
+
/*
* Modesetting
*/
-static const struct drm_mode_config_funcs udl_mode_funcs = {
+static enum drm_mode_status udl_mode_config_mode_valid(struct drm_device *dev,
+ const struct drm_display_mode *mode)
+{
+ struct udl_device *udl = to_udl(dev);
+
+ if (udl->sku_pixel_limit) {
+ if (mode->vdisplay * mode->hdisplay > udl->sku_pixel_limit)
+ return MODE_MEM;
+ }
+
+ return MODE_OK;
+}
+
+static const struct drm_mode_config_funcs udl_mode_config_funcs = {
.fb_create = drm_gem_fb_create_with_dirty,
+ .mode_valid = udl_mode_config_mode_valid,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit,
};
int udl_modeset_init(struct drm_device *dev)
{
- size_t format_count = ARRAY_SIZE(udl_simple_display_pipe_formats);
struct udl_device *udl = to_udl(dev);
+ struct drm_plane *primary_plane;
+ struct drm_crtc *crtc;
+ struct drm_encoder *encoder;
struct drm_connector *connector;
int ret;
@@ -426,28 +572,42 @@ int udl_modeset_init(struct drm_device *dev)
dev->mode_config.min_width = 640;
dev->mode_config.min_height = 480;
-
dev->mode_config.max_width = 2048;
dev->mode_config.max_height = 2048;
-
- dev->mode_config.prefer_shadow = 0;
dev->mode_config.preferred_depth = 16;
+ dev->mode_config.funcs = &udl_mode_config_funcs;
+
+ primary_plane = &udl->primary_plane;
+ ret = drm_universal_plane_init(dev, primary_plane, 0,
+ &udl_primary_plane_funcs,
+ udl_primary_plane_formats,
+ ARRAY_SIZE(udl_primary_plane_formats),
+ udl_primary_plane_fmtmods,
+ DRM_PLANE_TYPE_PRIMARY, NULL);
+ if (ret)
+ return ret;
+ drm_plane_helper_add(primary_plane, &udl_primary_plane_helper_funcs);
+ drm_plane_enable_fb_damage_clips(primary_plane);
- dev->mode_config.funcs = &udl_mode_funcs;
+ crtc = &udl->crtc;
+ ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL,
+ &udl_crtc_funcs, NULL);
+ if (ret)
+ return ret;
+ drm_crtc_helper_add(crtc, &udl_crtc_helper_funcs);
+
+ encoder = &udl->encoder;
+ ret = drm_encoder_init(dev, encoder, &udl_encoder_funcs, DRM_MODE_ENCODER_DAC, NULL);
+ if (ret)
+ return ret;
+ encoder->possible_crtcs = drm_crtc_mask(crtc);
connector = udl_connector_init(dev);
if (IS_ERR(connector))
return PTR_ERR(connector);
-
- format_count = ARRAY_SIZE(udl_simple_display_pipe_formats);
-
- ret = drm_simple_display_pipe_init(dev, &udl->display_pipe,
- &udl_simple_display_pipe_funcs,
- udl_simple_display_pipe_formats,
- format_count, NULL, connector);
+ ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
return ret;
- drm_plane_enable_fb_damage_clips(&udl->display_pipe.plane);
drm_mode_config_reset(dev);
diff --git a/drivers/gpu/drm/udl/udl_proto.h b/drivers/gpu/drm/udl/udl_proto.h
new file mode 100644
index 000000000000..c92d2109584c
--- /dev/null
+++ b/drivers/gpu/drm/udl/udl_proto.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef UDL_PROTO_H
+#define UDL_PROTO_H
+
+#include <linux/bits.h>
+
+#define UDL_MSG_BULK 0xaf
+
+/* Register access */
+#define UDL_CMD_WRITEREG 0x20 /* See register constants below */
+
+/* Framebuffer access */
+#define UDL_CMD_WRITERAW8 0x60 /* 8 bit raw write command. */
+#define UDL_CMD_WRITERL8 0x61 /* 8 bit run length command. */
+#define UDL_CMD_WRITECOPY8 0x62 /* 8 bit copy command. */
+#define UDL_CMD_WRITERLX8 0x63 /* 8 bit extended run length command. */
+#define UDL_CMD_WRITERAW16 0x68 /* 16 bit raw write command. */
+#define UDL_CMD_WRITERL16 0x69 /* 16 bit run length command. */
+#define UDL_CMD_WRITECOPY16 0x6a /* 16 bit copy command. */
+#define UDL_CMD_WRITERLX16 0x6b /* 16 bit extended run length command. */
+
+/* Color depth */
+#define UDL_REG_COLORDEPTH 0x00
+#define UDL_COLORDEPTH_16BPP 0
+#define UDL_COLORDEPTH_24BPP 1
+
+/* Display-mode settings */
+#define UDL_REG_XDISPLAYSTART 0x01
+#define UDL_REG_XDISPLAYEND 0x03
+#define UDL_REG_YDISPLAYSTART 0x05
+#define UDL_REG_YDISPLAYEND 0x07
+#define UDL_REG_XENDCOUNT 0x09
+#define UDL_REG_HSYNCSTART 0x0b
+#define UDL_REG_HSYNCEND 0x0d
+#define UDL_REG_HPIXELS 0x0f
+#define UDL_REG_YENDCOUNT 0x11
+#define UDL_REG_VSYNCSTART 0x13
+#define UDL_REG_VSYNCEND 0x15
+#define UDL_REG_VPIXELS 0x17
+#define UDL_REG_PIXELCLOCK5KHZ 0x1b
+
+/* On/Off for driving the DisplayLink framebuffer to the display */
+#define UDL_REG_BLANKMODE 0x1f
+#define UDL_BLANKMODE_ON 0x00 /* hsync and vsync on, visible */
+#define UDL_BLANKMODE_BLANKED 0x01 /* hsync and vsync on, blanked */
+#define UDL_BLANKMODE_VSYNC_OFF 0x03 /* vsync off, blanked */
+#define UDL_BLANKMODE_HSYNC_OFF 0x05 /* hsync off, blanked */
+#define UDL_BLANKMODE_POWERDOWN 0x07 /* powered off; requires modeset */
+
+/* Framebuffer address */
+#define UDL_REG_BASE16BPP_ADDR2 0x20
+#define UDL_REG_BASE16BPP_ADDR1 0x21
+#define UDL_REG_BASE16BPP_ADDR0 0x22
+#define UDL_REG_BASE8BPP_ADDR2 0x26
+#define UDL_REG_BASE8BPP_ADDR1 0x27
+#define UDL_REG_BASE8BPP_ADDR0 0x28
+
+#define UDL_BASE_ADDR0_MASK GENMASK(7, 0)
+#define UDL_BASE_ADDR1_MASK GENMASK(15, 8)
+#define UDL_BASE_ADDR2_MASK GENMASK(23, 16)
+
+/* Lock/unlock video registers */
+#define UDL_REG_VIDREG 0xff
+#define UDL_VIDREG_LOCK 0x00
+#define UDL_VIDREG_UNLOCK 0xff
+
+#endif
diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c
index b57844632dbd..5ff1037a3453 100644
--- a/drivers/gpu/drm/udl/udl_transfer.c
+++ b/drivers/gpu/drm/udl/udl_transfer.c
@@ -10,6 +10,7 @@
#include <asm/unaligned.h>
#include "udl_drv.h"
+#include "udl_proto.h"
#define MAX_CMD_PIXELS 255
@@ -89,8 +90,8 @@ static void udl_compress_hline16(
const u8 *cmd_pixel_start, *cmd_pixel_end = NULL;
uint16_t pixel_val16;
- *cmd++ = 0xaf;
- *cmd++ = 0x6b;
+ *cmd++ = UDL_MSG_BULK;
+ *cmd++ = UDL_CMD_WRITERLX16;
*cmd++ = (uint8_t) ((dev_addr >> 16) & 0xFF);
*cmd++ = (uint8_t) ((dev_addr >> 8) & 0xFF);
*cmd++ = (uint8_t) ((dev_addr) & 0xFF);
@@ -152,7 +153,7 @@ static void udl_compress_hline16(
if (cmd_buffer_end <= MIN_RLX_CMD_BYTES + cmd) {
/* Fill leftover bytes with no-ops */
if (cmd_buffer_end > cmd)
- memset(cmd, 0xAF, cmd_buffer_end - cmd);
+ memset(cmd, UDL_MSG_BULK, cmd_buffer_end - cmd);
cmd = (uint8_t *) cmd_buffer_end;
}
diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c
index e8c975b81585..478f1f0f60de 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.c
+++ b/drivers/gpu/drm/v3d/v3d_drv.c
@@ -22,7 +22,6 @@
#include <linux/reset.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_managed.h>
#include <uapi/drm/v3d_drm.h>
diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c
index b8980440d137..96af1cb5202a 100644
--- a/drivers/gpu/drm/v3d/v3d_gem.c
+++ b/drivers/gpu/drm/v3d/v3d_gem.c
@@ -10,6 +10,7 @@
#include <linux/sched/signal.h>
#include <linux/uaccess.h>
+#include <drm/drm_managed.h>
#include <drm/drm_syncobj.h>
#include <uapi/drm/v3d_drm.h>
@@ -1075,10 +1076,18 @@ v3d_gem_init(struct drm_device *dev)
spin_lock_init(&v3d->mm_lock);
spin_lock_init(&v3d->job_lock);
- mutex_init(&v3d->bo_lock);
- mutex_init(&v3d->reset_lock);
- mutex_init(&v3d->sched_lock);
- mutex_init(&v3d->cache_clean_lock);
+ ret = drmm_mutex_init(dev, &v3d->bo_lock);
+ if (ret)
+ return ret;
+ ret = drmm_mutex_init(dev, &v3d->reset_lock);
+ if (ret)
+ return ret;
+ ret = drmm_mutex_init(dev, &v3d->sched_lock);
+ if (ret)
+ return ret;
+ ret = drmm_mutex_init(dev, &v3d->cache_clean_lock);
+ if (ret)
+ return ret;
/* Note: We don't allocate address 0. Various bits of HW
* treat 0 as special, such as the occlusion query counters
diff --git a/drivers/gpu/drm/v3d/v3d_perfmon.c b/drivers/gpu/drm/v3d/v3d_perfmon.c
index 48aaaa972c49..e1be7368b87d 100644
--- a/drivers/gpu/drm/v3d/v3d_perfmon.c
+++ b/drivers/gpu/drm/v3d/v3d_perfmon.c
@@ -17,8 +17,10 @@ void v3d_perfmon_get(struct v3d_perfmon *perfmon)
void v3d_perfmon_put(struct v3d_perfmon *perfmon)
{
- if (perfmon && refcount_dec_and_test(&perfmon->refcnt))
+ if (perfmon && refcount_dec_and_test(&perfmon->refcnt)) {
+ mutex_destroy(&perfmon->lock);
kfree(perfmon);
+ }
}
void v3d_perfmon_start(struct v3d_dev *v3d, struct v3d_perfmon *perfmon)
@@ -113,6 +115,7 @@ void v3d_perfmon_close_file(struct v3d_file_priv *v3d_priv)
idr_for_each(&v3d_priv->perfmon.idr, v3d_perfmon_idr_del, NULL);
idr_destroy(&v3d_priv->perfmon.idr);
mutex_unlock(&v3d_priv->perfmon.lock);
+ mutex_destroy(&v3d_priv->perfmon.lock);
}
int v3d_perfmon_create_ioctl(struct drm_device *dev, void *data,
@@ -154,6 +157,7 @@ int v3d_perfmon_create_ioctl(struct drm_device *dev, void *data,
mutex_unlock(&v3d_priv->perfmon.lock);
if (ret < 0) {
+ mutex_destroy(&perfmon->lock);
kfree(perfmon);
return ret;
}
diff --git a/drivers/gpu/drm/vboxvideo/vbox_drv.c b/drivers/gpu/drm/vboxvideo/vbox_drv.c
index f4f2bd79a7cb..b450f449a3ab 100644
--- a/drivers/gpu/drm/vboxvideo/vbox_drv.c
+++ b/drivers/gpu/drm/vboxvideo/vbox_drv.c
@@ -14,7 +14,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_file.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_managed.h>
@@ -178,8 +178,6 @@ static const struct drm_driver driver = {
.driver_features =
DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
- .lastclose = drm_fb_helper_lastclose,
-
.fops = &vbox_fops,
.name = DRIVER_NAME,
.desc = DRIVER_DESC,
diff --git a/drivers/gpu/drm/vboxvideo/vbox_main.c b/drivers/gpu/drm/vboxvideo/vbox_main.c
index c9e8b3a63c62..3b83e550f4df 100644
--- a/drivers/gpu/drm/vboxvideo/vbox_main.c
+++ b/drivers/gpu/drm/vboxvideo/vbox_main.c
@@ -11,7 +11,6 @@
#include <linux/pci.h>
#include <linux/vbox_err.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_damage_helper.h>
diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c
index 231add8b8e12..43d9b3a6a352 100644
--- a/drivers/gpu/drm/vc4/vc4_bo.c
+++ b/drivers/gpu/drm/vc4/vc4_bo.c
@@ -736,12 +736,12 @@ static int vc4_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struct
struct vc4_bo *bo = to_vc4_bo(obj);
if (bo->validated_shader && (vma->vm_flags & VM_WRITE)) {
- DRM_DEBUG("mmaping of shader BOs for writing not allowed.\n");
+ DRM_DEBUG("mmapping of shader BOs for writing not allowed.\n");
return -EINVAL;
}
if (bo->madv != VC4_MADV_WILLNEED) {
- DRM_DEBUG("mmaping of %s BO not allowed\n",
+ DRM_DEBUG("mmapping of %s BO not allowed\n",
bo->madv == VC4_MADV_DONTNEED ?
"purgeable" : "purged");
return -EINVAL;
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index 8c329c071c62..5990d8f8c363 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -33,7 +33,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_vblank.h>
#include <soc/bcm2835/raspberrypi-firmware.h>
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index 418a8242691f..515228682e8e 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -326,6 +326,8 @@ struct vc4_hvs {
struct clk *core_clk;
+ unsigned long max_core_rate;
+
/* Memory manager for CRTCs to allocate space in the display
* list. Units are dwords.
*/
@@ -337,6 +339,20 @@ struct vc4_hvs {
struct drm_mm_node mitchell_netravali_filter;
struct debugfs_regset32 regset;
+
+ /*
+ * Even if HDMI0 on the RPi4 can output modes requiring a pixel
+ * rate higher than 297MHz, it needs some adjustments in the
+ * config.txt file to be able to do so and thus won't always be
+ * available.
+ */
+ bool vc5_hdmi_enable_hdmi_20;
+
+ /*
+ * 4096x2160@60 requires a core overclock to work, so register
+ * whether that is sufficient.
+ */
+ bool vc5_hdmi_enable_4096by2160;
};
struct vc4_plane {
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 470432c8fd70..12a00d644b61 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -124,9 +124,8 @@ static unsigned long long
vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode,
unsigned int bpc, enum vc4_hdmi_output_format fmt);
-static bool vc4_hdmi_supports_scrambling(struct drm_encoder *encoder)
+static bool vc4_hdmi_supports_scrambling(struct vc4_hdmi *vc4_hdmi)
{
- struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder);
struct drm_display_info *display = &vc4_hdmi->connector.display_info;
lockdep_assert_held(&vc4_hdmi->mutex);
@@ -319,9 +318,8 @@ out:
static int vc4_hdmi_reset_link(struct drm_connector *connector,
struct drm_modeset_acquire_ctx *ctx)
{
- struct drm_device *drm = connector->dev;
- struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
- struct drm_encoder *encoder = &vc4_hdmi->encoder.base;
+ struct drm_device *drm;
+ struct vc4_hdmi *vc4_hdmi;
struct drm_connector_state *conn_state;
struct drm_crtc_state *crtc_state;
struct drm_crtc *crtc;
@@ -332,6 +330,7 @@ static int vc4_hdmi_reset_link(struct drm_connector *connector,
if (!connector)
return 0;
+ drm = connector->dev;
ret = drm_modeset_lock(&drm->mode_config.connection_mutex, ctx);
if (ret)
return ret;
@@ -349,9 +348,10 @@ static int vc4_hdmi_reset_link(struct drm_connector *connector,
if (!crtc_state->active)
return 0;
+ vc4_hdmi = connector_to_vc4_hdmi(connector);
mutex_lock(&vc4_hdmi->mutex);
- if (!vc4_hdmi_supports_scrambling(encoder)) {
+ if (!vc4_hdmi_supports_scrambling(vc4_hdmi)) {
mutex_unlock(&vc4_hdmi->mutex);
return 0;
}
@@ -471,6 +471,7 @@ static int vc4_hdmi_connector_detect_ctx(struct drm_connector *connector,
static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
{
struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector);
+ struct vc4_dev *vc4 = to_vc4_dev(connector->dev);
int ret = 0;
struct edid *edid;
@@ -494,7 +495,7 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector)
ret = drm_add_edid_modes(connector, edid);
kfree(edid);
- if (vc4_hdmi->disable_4kp60) {
+ if (!vc4->hvs->vc5_hdmi_enable_hdmi_20) {
struct drm_device *drm = connector->dev;
const struct drm_display_mode *mode;
@@ -554,7 +555,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;
- drm_atomic_helper_connector_tv_reset(connector);
+ drm_atomic_helper_connector_tv_margins_reset(connector);
}
static struct drm_connector_state *
@@ -878,7 +879,7 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder)
lockdep_assert_held(&vc4_hdmi->mutex);
- if (!vc4_hdmi_supports_scrambling(encoder))
+ if (!vc4_hdmi_supports_scrambling(vc4_hdmi))
return;
if (!vc4_hdmi_mode_needs_scrambling(mode,
@@ -1764,15 +1765,23 @@ vc4_hdmi_sink_supports_format_bpc(const struct vc4_hdmi *vc4_hdmi,
static enum drm_mode_status
vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi,
+ const struct drm_display_mode *mode,
unsigned long long clock)
{
const struct drm_connector *connector = &vc4_hdmi->connector;
const struct drm_display_info *info = &connector->display_info;
+ struct vc4_dev *vc4 = to_vc4_dev(connector->dev);
if (clock > vc4_hdmi->variant->max_pixel_clock)
return MODE_CLOCK_HIGH;
- if (vc4_hdmi->disable_4kp60 && clock > HDMI_14_MAX_TMDS_CLK)
+ if (!vc4->hvs->vc5_hdmi_enable_hdmi_20 && clock > HDMI_14_MAX_TMDS_CLK)
+ return MODE_CLOCK_HIGH;
+
+ /* 4096x2160@60 is not reliable without overclocking core */
+ if (!vc4->hvs->vc5_hdmi_enable_4096by2160 &&
+ mode->hdisplay > 3840 && mode->vdisplay >= 2160 &&
+ drm_mode_vrefresh(mode) >= 50)
return MODE_CLOCK_HIGH;
if (info->max_tmds_clock && clock > (info->max_tmds_clock * 1000))
@@ -1809,7 +1818,7 @@ vc4_hdmi_encoder_compute_clock(const struct vc4_hdmi *vc4_hdmi,
unsigned long long clock;
clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc, fmt);
- if (vc4_hdmi_encoder_clock_valid(vc4_hdmi, clock) != MODE_OK)
+ if (vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode, clock) != MODE_OK)
return -EINVAL;
vc4_state->tmds_char_rate = clock;
@@ -1972,7 +1981,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder,
(mode->hsync_end % 2) || (mode->htotal % 2)))
return MODE_H_ILLEGAL;
- return vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode->clock * 1000);
+ return vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode, mode->clock * 1000);
}
static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = {
@@ -3481,14 +3490,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
vc4_hdmi->disable_wifi_frequencies =
of_property_read_bool(dev->of_node, "wifi-2.4ghz-coexistence");
- if (variant->max_pixel_clock == 600000000) {
- struct vc4_dev *vc4 = to_vc4_dev(drm);
- long max_rate = clk_round_rate(vc4->hvs->core_clk, 550000000);
-
- if (max_rate < 550000000)
- vc4_hdmi->disable_4kp60 = true;
- }
-
ret = devm_pm_runtime_enable(dev);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h
index 1ad8e8c377e2..dc3ccd8002a0 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.h
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.h
@@ -156,14 +156,6 @@ struct vc4_hdmi {
*/
bool disable_wifi_frequencies;
- /*
- * Even if HDMI0 on the RPi4 can output modes requiring a pixel
- * rate higher than 297MHz, it needs some adjustments in the
- * config.txt file to be able to do so and thus won't always be
- * available.
- */
- bool disable_4kp60;
-
struct cec_adapter *cec_adap;
struct cec_msg cec_rx_msg;
bool cec_tx_ok;
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 4ac9f5a2d5f9..c4453a5ae163 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -28,6 +28,8 @@
#include <drm/drm_drv.h>
#include <drm/drm_vblank.h>
+#include <soc/bcm2835/raspberrypi-firmware.h>
+
#include "vc4_drv.h"
#include "vc4_regs.h"
@@ -791,12 +793,36 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
if (vc4->is_vc5) {
+ struct rpi_firmware *firmware;
+ struct device_node *node;
+ unsigned int max_rate;
+
+ node = rpi_firmware_find_node();
+ if (!node)
+ return -EINVAL;
+
+ firmware = rpi_firmware_get(node);
+ of_node_put(node);
+ if (!firmware)
+ return -EPROBE_DEFER;
+
hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(hvs->core_clk)) {
dev_err(&pdev->dev, "Couldn't get core clock\n");
return PTR_ERR(hvs->core_clk);
}
+ max_rate = rpi_firmware_clk_get_max_rate(firmware,
+ RPI_FIRMWARE_CORE_CLK_ID);
+ rpi_firmware_put(firmware);
+ if (max_rate >= 550000000)
+ hvs->vc5_hdmi_enable_hdmi_20 = true;
+
+ if (max_rate >= 600000000)
+ hvs->vc5_hdmi_enable_4096by2160 = true;
+
+ hvs->max_core_rate = max_rate;
+
ret = clk_prepare_enable(hvs->core_clk);
if (ret) {
dev_err(&pdev->dev, "Couldn't enable the core clock\n");
diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c
index 0a6347c05df4..8fbeecdf2ec4 100644
--- a/drivers/gpu/drm/vc4/vc4_kms.c
+++ b/drivers/gpu/drm/vc4/vc4_kms.c
@@ -396,8 +396,8 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state)
if (vc4->is_vc5) {
unsigned long state_rate = max(old_hvs_state->core_clock_rate,
new_hvs_state->core_clock_rate);
- unsigned long core_rate = max_t(unsigned long,
- 500000000, state_rate);
+ unsigned long core_rate = clamp_t(unsigned long, state_rate,
+ 500000000, hvs->max_core_rate);
drm_dbg(dev, "Raising the core clock at %lu Hz\n", core_rate);
@@ -431,14 +431,17 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state)
drm_atomic_helper_cleanup_planes(dev, state);
if (vc4->is_vc5) {
- drm_dbg(dev, "Running the core clock at %lu Hz\n",
- new_hvs_state->core_clock_rate);
+ unsigned long core_rate = min_t(unsigned long,
+ hvs->max_core_rate,
+ new_hvs_state->core_clock_rate);
+
+ drm_dbg(dev, "Running the core clock at %lu Hz\n", core_rate);
/*
* Request a clock rate based on the current HVS
* requirements.
*/
- WARN_ON(clk_set_min_rate(hvs->core_clk, new_hvs_state->core_clock_rate));
+ WARN_ON(clk_set_min_rate(hvs->core_clk, core_rate));
drm_dbg(dev, "Core clock actual rate: %lu Hz\n",
clk_get_rate(hvs->core_clk));
diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index 0b3333865702..92c07e31d632 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -69,6 +69,7 @@
#define VEC_CONFIG0_STD_MASK GENMASK(1, 0)
#define VEC_CONFIG0_NTSC_STD 0
#define VEC_CONFIG0_PAL_BDGHI_STD 1
+#define VEC_CONFIG0_PAL_M_STD 2
#define VEC_CONFIG0_PAL_N_STD 3
#define VEC_SCHPH 0x108
@@ -255,10 +256,9 @@ static const struct vc4_vec_tv_mode vc4_vec_tv_modes[] = {
.config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
[VC4_VEC_TV_MODE_PAL_M] = {
- .mode = &pal_mode,
- .config0 = VEC_CONFIG0_PAL_BDGHI_STD,
- .config1 = VEC_CONFIG1_C_CVBS_CVBS | VEC_CONFIG1_CUSTOM_FREQ,
- .custom_freq = 0x223b61d1,
+ .mode = &ntsc_mode,
+ .config0 = VEC_CONFIG0_PAL_M_STD,
+ .config1 = VEC_CONFIG1_C_CVBS_CVBS,
},
};
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c
index 0035affc3e59..ae97b98750b6 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.c
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.c
@@ -35,6 +35,7 @@
#include <drm/drm_aperture.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_file.h>
#include "virtgpu_drv.h"
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index 9b98470593b0..b7a64c7dcc2c 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -35,7 +35,6 @@
#include <drm/drm_atomic.h>
#include <drm/drm_drv.h>
#include <drm/drm_encoder.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem.h>
diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c
index 0ffe5f0e33f7..293dbca50c31 100644
--- a/drivers/gpu/drm/vkms/vkms_drv.c
+++ b/drivers/gpu/drm/vkms/vkms_drv.c
@@ -17,7 +17,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_file.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_ioctl.h>
diff --git a/drivers/gpu/drm/vmwgfx/Kconfig b/drivers/gpu/drm/vmwgfx/Kconfig
index a4fabe208d9f..faddae3d6ac2 100644
--- a/drivers/gpu/drm/vmwgfx/Kconfig
+++ b/drivers/gpu/drm/vmwgfx/Kconfig
@@ -16,13 +16,6 @@ config DRM_VMWGFX
virtual hardware.
The compiled module will be called "vmwgfx.ko".
-config DRM_VMWGFX_FBCON
- depends on DRM_VMWGFX && DRM_FBDEV_EMULATION
- bool "Enable framebuffer console under vmwgfx by default"
- help
- Choose this option if you are shipping a new vmwgfx
- userspace driver that supports using the kernel driver.
-
config DRM_VMWGFX_MKSSTATS
bool "Enable mksGuestStats instrumentation of vmwgfx by default"
depends on DRM_VMWGFX
diff --git a/drivers/gpu/drm/vmwgfx/Makefile b/drivers/gpu/drm/vmwgfx/Makefile
index eee73b9aa404..2a644f035597 100644
--- a/drivers/gpu/drm/vmwgfx/Makefile
+++ b/drivers/gpu/drm/vmwgfx/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_hashtab.o vmwgfx_kms.o vmwgfx_drv.o \
+vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \
vmwgfx_ioctl.o vmwgfx_resource.o vmwgfx_ttm_buffer.o \
vmwgfx_cmd.o vmwgfx_irq.o vmwgfx_ldu.o vmwgfx_ttm_glue.o \
vmwgfx_overlay.o vmwgfx_gmrid_manager.o vmwgfx_fence.o \
@@ -12,6 +12,4 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_hashtab.o vmwgfx_kms.o vmwgfx_d
vmwgfx_devcaps.o ttm_object.o vmwgfx_system_manager.o \
vmwgfx_gem.o
-vmwgfx-$(CONFIG_DRM_FBDEV_EMULATION) += vmwgfx_fb.o
-
obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o
diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.c b/drivers/gpu/drm/vmwgfx/ttm_object.c
index 26a55fef1ab5..932b125ebf3d 100644
--- a/drivers/gpu/drm/vmwgfx/ttm_object.c
+++ b/drivers/gpu/drm/vmwgfx/ttm_object.c
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR MIT */
/**************************************************************************
*
- * Copyright (c) 2009-2013 VMware, Inc., Palo Alto, CA., USA
+ * Copyright (c) 2009-2022 VMware, Inc., Palo Alto, CA., USA
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -44,16 +44,20 @@
#define pr_fmt(fmt) "[TTM] " fmt
+#include "ttm_object.h"
+#include "vmwgfx_drv.h"
+
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/atomic.h>
#include <linux/module.h>
-#include "ttm_object.h"
-#include "vmwgfx_drv.h"
+#include <linux/hashtable.h>
MODULE_IMPORT_NS(DMA_BUF);
+#define VMW_TTM_OBJECT_REF_HT_ORDER 10
+
/**
* struct ttm_object_file
*
@@ -74,16 +78,14 @@ struct ttm_object_file {
struct ttm_object_device *tdev;
spinlock_t lock;
struct list_head ref_list;
- struct vmwgfx_open_hash ref_hash;
+ DECLARE_HASHTABLE(ref_hash, VMW_TTM_OBJECT_REF_HT_ORDER);
struct kref refcount;
};
/*
* struct ttm_object_device
*
- * @object_lock: lock that protects the object_hash hash table.
- *
- * @object_hash: hash table for fast lookup of object global names.
+ * @object_lock: lock that protects idr.
*
* @object_count: Per device object count.
*
@@ -92,7 +94,6 @@ struct ttm_object_file {
struct ttm_object_device {
spinlock_t object_lock;
- struct vmwgfx_open_hash object_hash;
atomic_t object_count;
struct dma_buf_ops ops;
void (*dmabuf_release)(struct dma_buf *dma_buf);
@@ -138,6 +139,36 @@ ttm_object_file_ref(struct ttm_object_file *tfile)
return tfile;
}
+static int ttm_tfile_find_ref_rcu(struct ttm_object_file *tfile,
+ uint64_t key,
+ struct vmwgfx_hash_item **p_hash)
+{
+ struct vmwgfx_hash_item *hash;
+
+ hash_for_each_possible_rcu(tfile->ref_hash, hash, head, key) {
+ if (hash->key == key) {
+ *p_hash = hash;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
+static int ttm_tfile_find_ref(struct ttm_object_file *tfile,
+ uint64_t key,
+ struct vmwgfx_hash_item **p_hash)
+{
+ struct vmwgfx_hash_item *hash;
+
+ hash_for_each_possible(tfile->ref_hash, hash, head, key) {
+ if (hash->key == key) {
+ *p_hash = hash;
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+
static void ttm_object_file_destroy(struct kref *kref)
{
struct ttm_object_file *tfile =
@@ -240,37 +271,35 @@ void ttm_base_object_unref(struct ttm_base_object **p_base)
* Return: A pointer to the object if successful or NULL otherwise.
*/
struct ttm_base_object *
-ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint32_t key)
+ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint64_t key)
{
struct vmwgfx_hash_item *hash;
- struct vmwgfx_open_hash *ht = &tfile->ref_hash;
int ret;
rcu_read_lock();
- ret = vmwgfx_ht_find_item_rcu(ht, key, &hash);
+ ret = ttm_tfile_find_ref_rcu(tfile, key, &hash);
if (ret) {
rcu_read_unlock();
return NULL;
}
__release(RCU);
- return drm_hash_entry(hash, struct ttm_ref_object, hash)->obj;
+ return hlist_entry(hash, struct ttm_ref_object, hash)->obj;
}
EXPORT_SYMBOL(ttm_base_object_noref_lookup);
struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
- uint32_t key)
+ uint64_t key)
{
struct ttm_base_object *base = NULL;
struct vmwgfx_hash_item *hash;
- struct vmwgfx_open_hash *ht = &tfile->ref_hash;
int ret;
rcu_read_lock();
- ret = vmwgfx_ht_find_item_rcu(ht, key, &hash);
+ ret = ttm_tfile_find_ref_rcu(tfile, key, &hash);
if (likely(ret == 0)) {
- base = drm_hash_entry(hash, struct ttm_ref_object, hash)->obj;
+ base = hlist_entry(hash, struct ttm_ref_object, hash)->obj;
if (!kref_get_unless_zero(&base->refcount))
base = NULL;
}
@@ -280,7 +309,7 @@ struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file *tfile,
}
struct ttm_base_object *
-ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key)
+ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint64_t key)
{
struct ttm_base_object *base;
@@ -299,7 +328,6 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
bool *existed,
bool require_existed)
{
- struct vmwgfx_open_hash *ht = &tfile->ref_hash;
struct ttm_ref_object *ref;
struct vmwgfx_hash_item *hash;
int ret = -EINVAL;
@@ -312,10 +340,10 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
while (ret == -EINVAL) {
rcu_read_lock();
- ret = vmwgfx_ht_find_item_rcu(ht, base->handle, &hash);
+ ret = ttm_tfile_find_ref_rcu(tfile, base->handle, &hash);
if (ret == 0) {
- ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
+ ref = hlist_entry(hash, struct ttm_ref_object, hash);
if (kref_get_unless_zero(&ref->kref)) {
rcu_read_unlock();
break;
@@ -337,21 +365,14 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
kref_init(&ref->kref);
spin_lock(&tfile->lock);
- ret = vmwgfx_ht_insert_item_rcu(ht, &ref->hash);
-
- if (likely(ret == 0)) {
- list_add_tail(&ref->head, &tfile->ref_list);
- kref_get(&base->refcount);
- spin_unlock(&tfile->lock);
- if (existed != NULL)
- *existed = false;
- break;
- }
+ hash_add_rcu(tfile->ref_hash, &ref->hash.head, ref->hash.key);
+ ret = 0;
+ list_add_tail(&ref->head, &tfile->ref_list);
+ kref_get(&base->refcount);
spin_unlock(&tfile->lock);
- BUG_ON(ret != -EINVAL);
-
- kfree(ref);
+ if (existed != NULL)
+ *existed = false;
}
return ret;
@@ -363,10 +384,8 @@ ttm_ref_object_release(struct kref *kref)
struct ttm_ref_object *ref =
container_of(kref, struct ttm_ref_object, kref);
struct ttm_object_file *tfile = ref->tfile;
- struct vmwgfx_open_hash *ht;
- ht = &tfile->ref_hash;
- (void)vmwgfx_ht_remove_item_rcu(ht, &ref->hash);
+ hash_del_rcu(&ref->hash.head);
list_del(&ref->head);
spin_unlock(&tfile->lock);
@@ -378,18 +397,17 @@ ttm_ref_object_release(struct kref *kref)
int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
unsigned long key)
{
- struct vmwgfx_open_hash *ht = &tfile->ref_hash;
struct ttm_ref_object *ref;
struct vmwgfx_hash_item *hash;
int ret;
spin_lock(&tfile->lock);
- ret = vmwgfx_ht_find_item(ht, key, &hash);
+ ret = ttm_tfile_find_ref(tfile, key, &hash);
if (unlikely(ret != 0)) {
spin_unlock(&tfile->lock);
return -EINVAL;
}
- ref = drm_hash_entry(hash, struct ttm_ref_object, hash);
+ ref = hlist_entry(hash, struct ttm_ref_object, hash);
kref_put(&ref->kref, ttm_ref_object_release);
spin_unlock(&tfile->lock);
return 0;
@@ -416,16 +434,13 @@ void ttm_object_file_release(struct ttm_object_file **p_tfile)
}
spin_unlock(&tfile->lock);
- vmwgfx_ht_remove(&tfile->ref_hash);
ttm_object_file_unref(&tfile);
}
-struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev,
- unsigned int hash_order)
+struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev)
{
struct ttm_object_file *tfile = kmalloc(sizeof(*tfile), GFP_KERNEL);
- int ret;
if (unlikely(tfile == NULL))
return NULL;
@@ -435,34 +450,21 @@ struct ttm_object_file *ttm_object_file_init(struct ttm_object_device *tdev,
kref_init(&tfile->refcount);
INIT_LIST_HEAD(&tfile->ref_list);
- ret = vmwgfx_ht_create(&tfile->ref_hash, hash_order);
- if (ret)
- goto out_err;
+ hash_init(tfile->ref_hash);
return tfile;
-out_err:
- vmwgfx_ht_remove(&tfile->ref_hash);
-
- kfree(tfile);
-
- return NULL;
}
struct ttm_object_device *
-ttm_object_device_init(unsigned int hash_order,
- const struct dma_buf_ops *ops)
+ttm_object_device_init(const struct dma_buf_ops *ops)
{
struct ttm_object_device *tdev = kmalloc(sizeof(*tdev), GFP_KERNEL);
- int ret;
if (unlikely(tdev == NULL))
return NULL;
spin_lock_init(&tdev->object_lock);
atomic_set(&tdev->object_count, 0);
- ret = vmwgfx_ht_create(&tdev->object_hash, hash_order);
- if (ret != 0)
- goto out_no_object_hash;
/*
* Our base is at VMWGFX_NUM_MOB + 1 because we want to create
@@ -477,10 +479,6 @@ ttm_object_device_init(unsigned int hash_order,
tdev->dmabuf_release = tdev->ops.release;
tdev->ops.release = ttm_prime_dmabuf_release;
return tdev;
-
-out_no_object_hash:
- kfree(tdev);
- return NULL;
}
void ttm_object_device_release(struct ttm_object_device **p_tdev)
@@ -491,7 +489,6 @@ void ttm_object_device_release(struct ttm_object_device **p_tdev)
WARN_ON_ONCE(!idr_is_empty(&tdev->idr));
idr_destroy(&tdev->idr);
- vmwgfx_ht_remove(&tdev->object_hash);
kfree(tdev);
}
diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.h b/drivers/gpu/drm/vmwgfx/ttm_object.h
index 1a2fa0f83f5f..f0ebbe340ad6 100644
--- a/drivers/gpu/drm/vmwgfx/ttm_object.h
+++ b/drivers/gpu/drm/vmwgfx/ttm_object.h
@@ -1,6 +1,6 @@
/**************************************************************************
*
- * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
+ * Copyright (c) 2006-2022 VMware, Inc., Palo Alto, CA., USA
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -42,8 +42,6 @@
#include <linux/list.h>
#include <linux/rcupdate.h>
-#include "vmwgfx_hashtab.h"
-
/**
* enum ttm_object_type
*
@@ -104,7 +102,7 @@ struct ttm_base_object {
struct ttm_object_file *tfile;
struct kref refcount;
void (*refcount_release) (struct ttm_base_object **base);
- u32 handle;
+ u64 handle;
enum ttm_object_type object_type;
u32 shareable;
};
@@ -164,7 +162,7 @@ extern int ttm_base_object_init(struct ttm_object_file *tfile,
*/
extern struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file
- *tfile, uint32_t key);
+ *tfile, uint64_t key);
/**
* ttm_base_object_lookup_for_ref
@@ -178,7 +176,7 @@ extern struct ttm_base_object *ttm_base_object_lookup(struct ttm_object_file
*/
extern struct ttm_base_object *
-ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint32_t key);
+ttm_base_object_lookup_for_ref(struct ttm_object_device *tdev, uint64_t key);
/**
* ttm_base_object_unref
@@ -237,14 +235,12 @@ extern int ttm_ref_object_base_unref(struct ttm_object_file *tfile,
* ttm_object_file_init - initialize a struct ttm_object file
*
* @tdev: A struct ttm_object device this file is initialized on.
- * @hash_order: Order of the hash table used to hold the reference objects.
*
* This is typically called by the file_ops::open function.
*/
extern struct ttm_object_file *ttm_object_file_init(struct ttm_object_device
- *tdev,
- unsigned int hash_order);
+ *tdev);
/**
* ttm_object_file_release - release data held by a ttm_object_file
@@ -262,7 +258,6 @@ extern void ttm_object_file_release(struct ttm_object_file **p_tfile);
/**
* ttm_object device init - initialize a struct ttm_object_device
*
- * @hash_order: Order of hash table used to hash the base objects.
* @ops: DMA buf ops for prime objects of this device.
*
* This function is typically called on device initialization to prepare
@@ -270,8 +265,7 @@ extern void ttm_object_file_release(struct ttm_object_file **p_tfile);
*/
extern struct ttm_object_device *
-ttm_object_device_init(unsigned int hash_order,
- const struct dma_buf_ops *ops);
+ttm_object_device_init(const struct dma_buf_ops *ops);
/**
* ttm_object_device_release - release data held by a ttm_object_device
@@ -314,7 +308,7 @@ extern int ttm_prime_handle_to_fd(struct ttm_object_file *tfile,
kfree_rcu(__obj, __prime.base.rhead)
struct ttm_base_object *
-ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint32_t key);
+ttm_base_object_noref_lookup(struct ttm_object_file *tfile, uint64_t key);
/**
* ttm_base_object_noref_release - release a base object pointer looked up
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
index 09fe20e918f9..c52c7bf1485b 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
@@ -483,8 +483,8 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
d.src_addr = NULL;
d.dst_pages = dst->ttm->pages;
d.src_pages = src->ttm->pages;
- d.dst_num_pages = dst->resource->num_pages;
- d.src_num_pages = src->resource->num_pages;
+ d.dst_num_pages = PFN_UP(dst->resource->size);
+ d.src_num_pages = PFN_UP(src->resource->size);
d.dst_prot = ttm_io_prot(dst, dst->resource, PAGE_KERNEL);
d.src_prot = ttm_io_prot(src, src->resource, PAGE_KERNEL);
d.diff = diff;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
index 822251aaab0a..321c551784a1 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
@@ -194,7 +194,7 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv,
int ret = 0;
place = vmw_vram_placement.placement[0];
- place.lpfn = bo->resource->num_pages;
+ place.lpfn = PFN_UP(bo->resource->size);
placement.num_placement = 1;
placement.placement = &place;
placement.num_busy_placement = 1;
@@ -211,7 +211,7 @@ int vmw_bo_pin_in_start_of_vram(struct vmw_private *dev_priv,
* that situation.
*/
if (bo->resource->mem_type == TTM_PL_VRAM &&
- bo->resource->start < bo->resource->num_pages &&
+ bo->resource->start < PFN_UP(bo->resource->size) &&
bo->resource->start > 0 &&
buf->base.pin_count == 0) {
ctx.interruptible = false;
@@ -352,7 +352,7 @@ void *vmw_bo_map_and_cache(struct vmw_buffer_object *vbo)
if (virtual)
return virtual;
- ret = ttm_bo_kmap(bo, 0, bo->resource->num_pages, &vbo->map);
+ ret = ttm_bo_kmap(bo, 0, PFN_UP(bo->base.size), &vbo->map);
if (ret)
DRM_ERROR("Buffer object map failed: %d.\n", ret);
@@ -807,9 +807,23 @@ int vmw_dumb_create(struct drm_file *file_priv,
{
struct vmw_private *dev_priv = vmw_priv(dev);
struct vmw_buffer_object *vbo;
+ int cpp = DIV_ROUND_UP(args->bpp, 8);
int ret;
- args->pitch = args->width * ((args->bpp + 7) / 8);
+ switch (cpp) {
+ case 1: /* DRM_FORMAT_C8 */
+ case 2: /* DRM_FORMAT_RGB565 */
+ case 4: /* DRM_FORMAT_XRGB8888 */
+ break;
+ default:
+ /*
+ * Dumb buffers don't allow anything else.
+ * This is tested via IGT's dumb_buffers
+ */
+ return -EINVAL;
+ }
+
+ args->pitch = args->width * cpp;
args->size = ALIGN(args->pitch * args->height, PAGE_SIZE);
ret = vmw_gem_object_create_with_handle(dev_priv, file_priv,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
index 82ef58ccdd42..47bc0b411055 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR MIT
/**************************************************************************
*
- * Copyright 2014-2015 VMware, Inc., Palo Alto, CA., USA
+ * Copyright 2014-2022 VMware, Inc., Palo Alto, CA., USA
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
@@ -28,6 +28,8 @@
#include "vmwgfx_drv.h"
#include "vmwgfx_resource_priv.h"
+#include <linux/hashtable.h>
+
#define VMW_CMDBUF_RES_MAN_HT_ORDER 12
/**
@@ -59,7 +61,7 @@ struct vmw_cmdbuf_res {
* @resources and @list are protected by the cmdbuf mutex for now.
*/
struct vmw_cmdbuf_res_manager {
- struct vmwgfx_open_hash resources;
+ DECLARE_HASHTABLE(resources, VMW_CMDBUF_RES_MAN_HT_ORDER);
struct list_head list;
struct vmw_private *dev_priv;
};
@@ -82,14 +84,13 @@ vmw_cmdbuf_res_lookup(struct vmw_cmdbuf_res_manager *man,
u32 user_key)
{
struct vmwgfx_hash_item *hash;
- int ret;
unsigned long key = user_key | (res_type << 24);
- ret = vmwgfx_ht_find_item(&man->resources, key, &hash);
- if (unlikely(ret != 0))
- return ERR_PTR(ret);
-
- return drm_hash_entry(hash, struct vmw_cmdbuf_res, hash)->res;
+ hash_for_each_possible_rcu(man->resources, hash, head, key) {
+ if (hash->key == key)
+ return hlist_entry(hash, struct vmw_cmdbuf_res, hash)->res;
+ }
+ return ERR_PTR(-EINVAL);
}
/**
@@ -105,7 +106,7 @@ static void vmw_cmdbuf_res_free(struct vmw_cmdbuf_res_manager *man,
struct vmw_cmdbuf_res *entry)
{
list_del(&entry->head);
- WARN_ON(vmwgfx_ht_remove_item(&man->resources, &entry->hash));
+ hash_del_rcu(&entry->hash.head);
vmw_resource_unreference(&entry->res);
kfree(entry);
}
@@ -159,7 +160,6 @@ void vmw_cmdbuf_res_commit(struct list_head *list)
void vmw_cmdbuf_res_revert(struct list_head *list)
{
struct vmw_cmdbuf_res *entry, *next;
- int ret;
list_for_each_entry_safe(entry, next, list, head) {
switch (entry->state) {
@@ -167,8 +167,8 @@ void vmw_cmdbuf_res_revert(struct list_head *list)
vmw_cmdbuf_res_free(entry->man, entry);
break;
case VMW_CMDBUF_RES_DEL:
- ret = vmwgfx_ht_insert_item(&entry->man->resources, &entry->hash);
- BUG_ON(ret);
+ hash_add_rcu(entry->man->resources, &entry->hash.head,
+ entry->hash.key);
list_move_tail(&entry->head, &entry->man->list);
entry->state = VMW_CMDBUF_RES_COMMITTED;
break;
@@ -199,26 +199,20 @@ int vmw_cmdbuf_res_add(struct vmw_cmdbuf_res_manager *man,
struct list_head *list)
{
struct vmw_cmdbuf_res *cres;
- int ret;
cres = kzalloc(sizeof(*cres), GFP_KERNEL);
if (unlikely(!cres))
return -ENOMEM;
cres->hash.key = user_key | (res_type << 24);
- ret = vmwgfx_ht_insert_item(&man->resources, &cres->hash);
- if (unlikely(ret != 0)) {
- kfree(cres);
- goto out_invalid_key;
- }
+ hash_add_rcu(man->resources, &cres->hash.head, cres->hash.key);
cres->state = VMW_CMDBUF_RES_ADD;
cres->res = vmw_resource_reference(res);
cres->man = man;
list_add_tail(&cres->head, list);
-out_invalid_key:
- return ret;
+ return 0;
}
/**
@@ -243,24 +237,26 @@ int vmw_cmdbuf_res_remove(struct vmw_cmdbuf_res_manager *man,
struct list_head *list,
struct vmw_resource **res_p)
{
- struct vmw_cmdbuf_res *entry;
+ struct vmw_cmdbuf_res *entry = NULL;
struct vmwgfx_hash_item *hash;
- int ret;
+ unsigned long key = user_key | (res_type << 24);
- ret = vmwgfx_ht_find_item(&man->resources, user_key | (res_type << 24),
- &hash);
- if (likely(ret != 0))
+ hash_for_each_possible_rcu(man->resources, hash, head, key) {
+ if (hash->key == key) {
+ entry = hlist_entry(hash, struct vmw_cmdbuf_res, hash);
+ break;
+ }
+ }
+ if (unlikely(!entry))
return -EINVAL;
- entry = drm_hash_entry(hash, struct vmw_cmdbuf_res, hash);
-
switch (entry->state) {
case VMW_CMDBUF_RES_ADD:
vmw_cmdbuf_res_free(man, entry);
*res_p = NULL;
break;
case VMW_CMDBUF_RES_COMMITTED:
- (void) vmwgfx_ht_remove_item(&man->resources, &entry->hash);
+ hash_del_rcu(&entry->hash.head);
list_del(&entry->head);
entry->state = VMW_CMDBUF_RES_DEL;
list_add_tail(&entry->head, list);
@@ -287,7 +283,6 @@ struct vmw_cmdbuf_res_manager *
vmw_cmdbuf_res_man_create(struct vmw_private *dev_priv)
{
struct vmw_cmdbuf_res_manager *man;
- int ret;
man = kzalloc(sizeof(*man), GFP_KERNEL);
if (!man)
@@ -295,12 +290,8 @@ vmw_cmdbuf_res_man_create(struct vmw_private *dev_priv)
man->dev_priv = dev_priv;
INIT_LIST_HEAD(&man->list);
- ret = vmwgfx_ht_create(&man->resources, VMW_CMDBUF_RES_MAN_HT_ORDER);
- if (ret == 0)
- return man;
-
- kfree(man);
- return ERR_PTR(ret);
+ hash_init(man->resources);
+ return man;
}
/**
@@ -320,7 +311,6 @@ void vmw_cmdbuf_res_man_destroy(struct vmw_cmdbuf_res_manager *man)
list_for_each_entry_safe(entry, next, &man->list, head)
vmw_cmdbuf_res_free(man, entry);
- vmwgfx_ht_remove(&man->resources);
kfree(man);
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c
index 79b30dc9d825..b78a10312fad 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c
@@ -33,6 +33,7 @@
#include <drm/ttm/ttm_placement.h>
#include "vmwgfx_drv.h"
+#include "vmwgfx_mksstat.h"
#include "vmwgfx_resource_priv.h"
#include "vmwgfx_so.h"
@@ -72,12 +73,24 @@ struct vmw_cotable_info {
bool);
};
+
+/*
+ * Getting the initial size right is difficult because it all depends
+ * on what the userspace is doing. The sizes will be aligned up to
+ * a PAGE_SIZE so we just want to make sure that for majority of apps
+ * the initial number of entries doesn't require an immediate resize.
+ * For all cotables except SVGACOTableDXElementLayoutEntry and
+ * SVGACOTableDXBlendStateEntry the initial number of entries fits
+ * within the PAGE_SIZE. For SVGACOTableDXElementLayoutEntry and
+ * SVGACOTableDXBlendStateEntry we want to reserve two pages,
+ * because that's what all apps will require initially.
+ */
static const struct vmw_cotable_info co_info[] = {
{1, sizeof(SVGACOTableDXRTViewEntry), &vmw_view_cotable_list_destroy},
{1, sizeof(SVGACOTableDXDSViewEntry), &vmw_view_cotable_list_destroy},
{1, sizeof(SVGACOTableDXSRViewEntry), &vmw_view_cotable_list_destroy},
- {1, sizeof(SVGACOTableDXElementLayoutEntry), NULL},
- {1, sizeof(SVGACOTableDXBlendStateEntry), NULL},
+ {PAGE_SIZE/sizeof(SVGACOTableDXElementLayoutEntry) + 1, sizeof(SVGACOTableDXElementLayoutEntry), NULL},
+ {PAGE_SIZE/sizeof(SVGACOTableDXBlendStateEntry) + 1, sizeof(SVGACOTableDXBlendStateEntry), NULL},
{1, sizeof(SVGACOTableDXDepthStencilEntry), NULL},
{1, sizeof(SVGACOTableDXRasterizerStateEntry), NULL},
{1, sizeof(SVGACOTableDXSamplerEntry), NULL},
@@ -395,9 +408,12 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size)
int ret;
size_t i;
+ MKS_STAT_TIME_DECL(MKSSTAT_KERN_COTABLE_RESIZE);
+ MKS_STAT_TIME_PUSH(MKSSTAT_KERN_COTABLE_RESIZE);
+
ret = vmw_cotable_readback(res);
if (ret)
- return ret;
+ goto out_done;
cur_size_read_back = vcotbl->size_read_back;
vcotbl->size_read_back = old_size_read_back;
@@ -411,7 +427,7 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size)
true, true, vmw_bo_bo_free, &buf);
if (ret) {
DRM_ERROR("Failed initializing new cotable MOB.\n");
- return ret;
+ goto out_done;
}
bo = &buf->base;
@@ -427,7 +443,7 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size)
* Do a page by page copy of COTables. This eliminates slow vmap()s.
* This should really be a TTM utility.
*/
- for (i = 0; i < old_bo->resource->num_pages; ++i) {
+ for (i = 0; i < PFN_UP(old_bo->resource->size); ++i) {
bool dummy;
ret = ttm_bo_kmap(old_bo, i, 1, &old_map);
@@ -485,6 +501,8 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size)
/* Release the pin acquired in vmw_bo_init */
ttm_bo_unpin(bo);
+ MKS_STAT_TIME_POP(MKSSTAT_KERN_COTABLE_RESIZE);
+
return 0;
out_map_new:
@@ -494,6 +512,9 @@ out_wait:
ttm_bo_unreserve(bo);
vmw_bo_unreference(&buf);
+out_done:
+ MKS_STAT_TIME_POP(MKSSTAT_KERN_COTABLE_RESIZE);
+
return ret;
}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index d7bd5eb1d3ac..bd02cb0e6837 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -25,13 +25,17 @@
*
**************************************************************************/
-#include <linux/dma-mapping.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/cc_platform.h>
+
+#include "vmwgfx_drv.h"
+
+#include "vmwgfx_devcaps.h"
+#include "vmwgfx_mksstat.h"
+#include "vmwgfx_binding.h"
+#include "ttm_object.h"
#include <drm/drm_aperture.h>
#include <drm/drm_drv.h>
+#include <drm/drm_fbdev_generic.h>
#include <drm/drm_gem_ttm_helper.h>
#include <drm/drm_ioctl.h>
#include <drm/drm_module.h>
@@ -41,17 +45,14 @@
#include <drm/ttm/ttm_placement.h>
#include <generated/utsrelease.h>
-#include "ttm_object.h"
-#include "vmwgfx_binding.h"
-#include "vmwgfx_devcaps.h"
-#include "vmwgfx_drv.h"
-#include "vmwgfx_mksstat.h"
+#include <linux/cc_platform.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/version.h>
#define VMWGFX_DRIVER_DESC "Linux drm driver for VMware graphics devices"
-#define VMW_MIN_INITIAL_WIDTH 800
-#define VMW_MIN_INITIAL_HEIGHT 600
-
/*
* Fully encoded drm commands. Might move to vmw_drm.h
*/
@@ -262,7 +263,6 @@ static const struct pci_device_id vmw_pci_id_list[] = {
};
MODULE_DEVICE_TABLE(pci, vmw_pci_id_list);
-static int enable_fbdev = IS_ENABLED(CONFIG_DRM_VMWGFX_FBCON);
static int vmw_restrict_iommu;
static int vmw_force_coherent;
static int vmw_restrict_dma_mask;
@@ -272,8 +272,6 @@ static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
void *ptr);
-MODULE_PARM_DESC(enable_fbdev, "Enable vmwgfx fbdev");
-module_param_named(enable_fbdev, enable_fbdev, int, 0600);
MODULE_PARM_DESC(restrict_iommu, "Try to limit IOMMU usage for TTM pages");
module_param_named(restrict_iommu, vmw_restrict_iommu, int, 0600);
MODULE_PARM_DESC(force_coherent, "Force coherent TTM pages");
@@ -623,8 +621,8 @@ static void vmw_get_initial_size(struct vmw_private *dev_priv)
width = vmw_read(dev_priv, SVGA_REG_WIDTH);
height = vmw_read(dev_priv, SVGA_REG_HEIGHT);
- width = max_t(uint32_t, width, VMW_MIN_INITIAL_WIDTH);
- height = max_t(uint32_t, height, VMW_MIN_INITIAL_HEIGHT);
+ width = max_t(uint32_t, width, VMWGFX_MIN_INITIAL_WIDTH);
+ height = max_t(uint32_t, height, VMWGFX_MIN_INITIAL_HEIGHT);
if (width > dev_priv->fb_max_width ||
height > dev_priv->fb_max_height) {
@@ -633,8 +631,8 @@ static void vmw_get_initial_size(struct vmw_private *dev_priv)
* This is a host error and shouldn't occur.
*/
- width = VMW_MIN_INITIAL_WIDTH;
- height = VMW_MIN_INITIAL_HEIGHT;
+ width = VMWGFX_MIN_INITIAL_WIDTH;
+ height = VMWGFX_MIN_INITIAL_HEIGHT;
}
dev_priv->initial_width = width;
@@ -806,6 +804,43 @@ static int vmw_detect_version(struct vmw_private *dev)
return 0;
}
+static void vmw_write_driver_id(struct vmw_private *dev)
+{
+ if ((dev->capabilities2 & SVGA_CAP2_DX2) != 0) {
+ vmw_write(dev, SVGA_REG_GUEST_DRIVER_ID,
+ SVGA_REG_GUEST_DRIVER_ID_LINUX);
+
+ vmw_write(dev, SVGA_REG_GUEST_DRIVER_VERSION1,
+ LINUX_VERSION_MAJOR << 24 |
+ LINUX_VERSION_PATCHLEVEL << 16 |
+ LINUX_VERSION_SUBLEVEL);
+ vmw_write(dev, SVGA_REG_GUEST_DRIVER_VERSION2,
+ VMWGFX_DRIVER_MAJOR << 24 |
+ VMWGFX_DRIVER_MINOR << 16 |
+ VMWGFX_DRIVER_PATCHLEVEL);
+ vmw_write(dev, SVGA_REG_GUEST_DRIVER_VERSION3, 0);
+
+ vmw_write(dev, SVGA_REG_GUEST_DRIVER_ID,
+ SVGA_REG_GUEST_DRIVER_ID_SUBMIT);
+ }
+}
+
+static void vmw_sw_context_init(struct vmw_private *dev_priv)
+{
+ struct vmw_sw_context *sw_context = &dev_priv->ctx;
+
+ hash_init(sw_context->res_ht);
+}
+
+static void vmw_sw_context_fini(struct vmw_private *dev_priv)
+{
+ struct vmw_sw_context *sw_context = &dev_priv->ctx;
+
+ vfree(sw_context->cmd_bounce);
+ if (sw_context->staged_bindings)
+ vmw_binding_state_free(sw_context->staged_bindings);
+}
+
static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
{
int ret;
@@ -815,6 +850,8 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
dev_priv->drm.dev_private = dev_priv;
+ vmw_sw_context_init(dev_priv);
+
mutex_init(&dev_priv->cmdbuf_mutex);
mutex_init(&dev_priv->binding_mutex);
spin_lock_init(&dev_priv->resource_lock);
@@ -844,9 +881,6 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
dev_priv->assume_16bpp = !!vmw_assume_16bpp;
- dev_priv->enable_fb = enable_fbdev;
-
-
dev_priv->capabilities = vmw_read(dev_priv, SVGA_REG_CAPABILITIES);
vmw_print_bitmap(&dev_priv->drm, "Capabilities",
dev_priv->capabilities,
@@ -970,7 +1004,7 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
goto out_err0;
}
- dev_priv->tdev = ttm_object_device_init(12, &vmw_prime_dmabuf_ops);
+ dev_priv->tdev = ttm_object_device_init(&vmw_prime_dmabuf_ops);
if (unlikely(dev_priv->tdev == NULL)) {
drm_err(&dev_priv->drm,
@@ -1091,12 +1125,7 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id)
vmw_host_printf("vmwgfx: Module Version: %d.%d.%d (kernel: %s)",
VMWGFX_DRIVER_MAJOR, VMWGFX_DRIVER_MINOR,
VMWGFX_DRIVER_PATCHLEVEL, UTS_RELEASE);
-
- if (dev_priv->enable_fb) {
- vmw_fifo_resource_inc(dev_priv);
- vmw_svga_enable(dev_priv);
- vmw_fb_init(dev_priv);
- }
+ vmw_write_driver_id(dev_priv);
dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier;
register_pm_notifier(&dev_priv->pm_nb);
@@ -1143,15 +1172,10 @@ static void vmw_driver_unload(struct drm_device *dev)
unregister_pm_notifier(&dev_priv->pm_nb);
- if (dev_priv->ctx.res_ht_initialized)
- vmwgfx_ht_remove(&dev_priv->ctx.res_ht);
- vfree(dev_priv->ctx.cmd_bounce);
- if (dev_priv->enable_fb) {
- vmw_fb_off(dev_priv);
- vmw_fb_close(dev_priv);
- vmw_fifo_resource_dec(dev_priv);
- vmw_svga_disable(dev_priv);
- }
+ vmw_sw_context_fini(dev_priv);
+ vmw_fifo_resource_dec(dev_priv);
+
+ vmw_svga_disable(dev_priv);
vmw_kms_close(dev_priv);
vmw_overlay_close(dev_priv);
@@ -1173,8 +1197,6 @@ static void vmw_driver_unload(struct drm_device *dev)
vmw_irq_uninstall(&dev_priv->drm);
ttm_object_device_release(&dev_priv->tdev);
- if (dev_priv->ctx.staged_bindings)
- vmw_binding_state_free(dev_priv->ctx.staged_bindings);
for (i = vmw_res_context; i < vmw_res_max; ++i)
idr_destroy(&dev_priv->res_idr[i]);
@@ -1203,7 +1225,7 @@ static int vmw_driver_open(struct drm_device *dev, struct drm_file *file_priv)
if (unlikely(!vmw_fp))
return ret;
- vmw_fp->tfile = ttm_object_file_init(dev_priv->tdev, 10);
+ vmw_fp->tfile = ttm_object_file_init(dev_priv->tdev);
if (unlikely(vmw_fp->tfile == NULL))
goto out_no_tfile;
@@ -1291,8 +1313,6 @@ static void vmw_master_drop(struct drm_device *dev,
struct vmw_private *dev_priv = vmw_priv(dev);
vmw_kms_legacy_hotspot_clear(dev_priv);
- if (!dev_priv->enable_fb)
- vmw_svga_disable(dev_priv);
}
/**
@@ -1485,25 +1505,19 @@ static int vmw_pm_freeze(struct device *kdev)
DRM_ERROR("Failed to freeze modesetting.\n");
return ret;
}
- if (dev_priv->enable_fb)
- vmw_fb_off(dev_priv);
vmw_execbuf_release_pinned_bo(dev_priv);
vmw_resource_evict_all(dev_priv);
vmw_release_device_early(dev_priv);
while (ttm_device_swapout(&dev_priv->bdev, &ctx, GFP_KERNEL) > 0);
- if (dev_priv->enable_fb)
- vmw_fifo_resource_dec(dev_priv);
+ vmw_fifo_resource_dec(dev_priv);
if (atomic_read(&dev_priv->num_fifo_resources) != 0) {
DRM_ERROR("Can't hibernate while 3D resources are active.\n");
- if (dev_priv->enable_fb)
- vmw_fifo_resource_inc(dev_priv);
+ vmw_fifo_resource_inc(dev_priv);
WARN_ON(vmw_request_device_late(dev_priv));
dev_priv->suspend_locked = false;
if (dev_priv->suspend_state)
vmw_kms_resume(dev);
- if (dev_priv->enable_fb)
- vmw_fb_on(dev_priv);
return -EBUSY;
}
@@ -1523,24 +1537,19 @@ static int vmw_pm_restore(struct device *kdev)
vmw_detect_version(dev_priv);
- if (dev_priv->enable_fb)
- vmw_fifo_resource_inc(dev_priv);
+ vmw_fifo_resource_inc(dev_priv);
ret = vmw_request_device(dev_priv);
if (ret)
return ret;
- if (dev_priv->enable_fb)
- __vmw_svga_enable(dev_priv);
+ __vmw_svga_enable(dev_priv);
vmw_fence_fifo_up(dev_priv->fman);
dev_priv->suspend_locked = false;
if (dev_priv->suspend_state)
vmw_kms_resume(&dev_priv->drm);
- if (dev_priv->enable_fb)
- vmw_fb_on(dev_priv);
-
return 0;
}
@@ -1631,6 +1640,10 @@ static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
goto out_unload;
+ vmw_fifo_resource_inc(vmw);
+ vmw_svga_enable(vmw);
+ drm_fbdev_generic_setup(&vmw->drm, 0);
+
vmw_debugfs_gem_init(vmw);
vmw_debugfs_resource_managers_init(vmw);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
index 09e2d738aa87..b062b020b378 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
@@ -30,6 +30,7 @@
#include <linux/suspend.h>
#include <linux/sync_file.h>
+#include <linux/hashtable.h>
#include <drm/drm_auth.h>
#include <drm/drm_device.h>
@@ -42,7 +43,6 @@
#include "ttm_object.h"
#include "vmwgfx_fence.h"
-#include "vmwgfx_hashtab.h"
#include "vmwgfx_reg.h"
#include "vmwgfx_validation.h"
@@ -62,6 +62,9 @@
#define VMWGFX_MAX_DISPLAYS 16
#define VMWGFX_CMD_BOUNCE_INIT_SIZE 32768
+#define VMWGFX_MIN_INITIAL_WIDTH 1280
+#define VMWGFX_MIN_INITIAL_HEIGHT 800
+
#define VMWGFX_PCI_ID_SVGA2 0x0405
#define VMWGFX_PCI_ID_SVGA3 0x0406
@@ -93,6 +96,11 @@
#define VMW_RES_STREAM ttm_driver_type2
#define VMW_RES_FENCE ttm_driver_type3
#define VMW_RES_SHADER ttm_driver_type4
+#define VMW_RES_HT_ORDER 12
+
+#define VMW_CURSOR_SNOOP_FORMAT SVGA3D_A8R8G8B8
+#define VMW_CURSOR_SNOOP_WIDTH 64
+#define VMW_CURSOR_SNOOP_HEIGHT 64
#define MKSSTAT_CAPACITY_LOG2 5U
#define MKSSTAT_CAPACITY (1U << MKSSTAT_CAPACITY_LOG2)
@@ -102,6 +110,11 @@ struct vmw_fpriv {
bool gb_aware; /* user-space is guest-backed aware */
};
+struct vmwgfx_hash_item {
+ struct hlist_node head;
+ unsigned long key;
+};
+
/**
* struct vmw_buffer_object - TTM buffer object with vmwgfx additions
* @base: The TTM buffer object
@@ -425,8 +438,7 @@ struct vmw_ctx_validation_info;
* @ctx: The validation context
*/
struct vmw_sw_context{
- struct vmwgfx_open_hash res_ht;
- bool res_ht_initialized;
+ DECLARE_HASHTABLE(res_ht, VMW_RES_HT_ORDER);
bool kernel;
struct vmw_fpriv *fp;
struct drm_file *filp;
@@ -546,7 +558,6 @@ struct vmw_private {
* Framebuffer info.
*/
- void *fb_info;
enum vmw_display_unit_type active_display_unit;
struct vmw_legacy_display *ldu_priv;
struct vmw_overlay *overlay_priv;
@@ -605,8 +616,6 @@ struct vmw_private {
struct mutex cmdbuf_mutex;
struct mutex binding_mutex;
- bool enable_fb;
-
/**
* PM management.
*/
@@ -1184,35 +1193,6 @@ extern void vmw_generic_waiter_add(struct vmw_private *dev_priv, u32 flag,
extern void vmw_generic_waiter_remove(struct vmw_private *dev_priv,
u32 flag, int *waiter_count);
-
-/**
- * Kernel framebuffer - vmwgfx_fb.c
- */
-
-#ifdef CONFIG_DRM_FBDEV_EMULATION
-int vmw_fb_init(struct vmw_private *vmw_priv);
-int vmw_fb_close(struct vmw_private *dev_priv);
-int vmw_fb_off(struct vmw_private *vmw_priv);
-int vmw_fb_on(struct vmw_private *vmw_priv);
-#else
-static inline int vmw_fb_init(struct vmw_private *vmw_priv)
-{
- return 0;
-}
-static inline int vmw_fb_close(struct vmw_private *dev_priv)
-{
- return 0;
-}
-static inline int vmw_fb_off(struct vmw_private *vmw_priv)
-{
- return 0;
-}
-static inline int vmw_fb_on(struct vmw_private *vmw_priv)
-{
- return 0;
-}
-#endif
-
/**
* Kernel modesetting - vmwgfx_kms.c
*/
@@ -1232,9 +1212,6 @@ int vmw_kms_write_svga(struct vmw_private *vmw_priv,
bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
uint32_t pitch,
uint32_t height);
-u32 vmw_get_vblank_counter(struct drm_crtc *crtc);
-int vmw_enable_vblank(struct drm_crtc *crtc);
-void vmw_disable_vblank(struct drm_crtc *crtc);
int vmw_kms_present(struct vmw_private *dev_priv,
struct drm_file *file_priv,
struct vmw_framebuffer *vfb,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index f085dbd4736d..a5379f6fb5ab 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR MIT
/**************************************************************************
*
- * Copyright 2009 - 2015 VMware, Inc., Palo Alto, CA., USA
+ * Copyright 2009 - 2022 VMware, Inc., Palo Alto, CA., USA
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
@@ -25,6 +25,7 @@
*
**************************************************************************/
#include <linux/sync_file.h>
+#include <linux/hashtable.h>
#include "vmwgfx_drv.h"
#include "vmwgfx_reg.h"
@@ -34,7 +35,6 @@
#include "vmwgfx_binding.h"
#include "vmwgfx_mksstat.h"
-#define VMW_RES_HT_ORDER 12
/*
* Helper macro to get dx_ctx_node if available otherwise print an error
@@ -1047,7 +1047,7 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv,
if (unlikely(new_query_bo != sw_context->cur_query_bo)) {
- if (unlikely(new_query_bo->base.resource->num_pages > 4)) {
+ if (unlikely(PFN_UP(new_query_bo->base.resource->size) > 4)) {
VMW_DEBUG_USER("Query buffer too large.\n");
return -EINVAL;
}
@@ -3869,7 +3869,6 @@ int vmw_execbuf_fence_commands(struct drm_file *file_priv,
* @fence: Pointer to the fenc object.
* @fence_handle: User-space fence handle.
* @out_fence_fd: exported file descriptor for the fence. -1 if not used
- * @sync_file: Only used to clean up in case of an error in this function.
*
* This function copies fence information to user-space. If copying fails, the
* user-space struct drm_vmw_fence_rep::error member is hopefully left
@@ -4101,7 +4100,7 @@ int vmw_execbuf_process(struct drm_file *file_priv,
int ret;
int32_t out_fence_fd = -1;
struct sync_file *sync_file = NULL;
- DECLARE_VAL_CONTEXT(val_ctx, &sw_context->res_ht, 1);
+ DECLARE_VAL_CONTEXT(val_ctx, sw_context, 1);
if (flags & DRM_VMW_EXECBUF_FLAG_EXPORT_FENCE_FD) {
out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
@@ -4164,14 +4163,6 @@ int vmw_execbuf_process(struct drm_file *file_priv,
if (sw_context->staged_bindings)
vmw_binding_state_reset(sw_context->staged_bindings);
- if (!sw_context->res_ht_initialized) {
- ret = vmwgfx_ht_create(&sw_context->res_ht, VMW_RES_HT_ORDER);
- if (unlikely(ret != 0))
- goto out_unlock;
-
- sw_context->res_ht_initialized = true;
- }
-
INIT_LIST_HEAD(&sw_context->staged_cmd_res);
sw_context->ctx = &val_ctx;
ret = vmw_execbuf_tie_context(dev_priv, sw_context, dx_context_handle);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
deleted file mode 100644
index 5b85b477e4c6..000000000000
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
+++ /dev/null
@@ -1,831 +0,0 @@
-/**************************************************************************
- *
- * Copyright © 2007 David Airlie
- * Copyright © 2009-2015 VMware, Inc., Palo Alto, CA., USA
- * All Rights Reserved.
- *
- * 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, sub license, 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 (including the
- * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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/fb.h>
-#include <linux/pci.h>
-
-#include <drm/drm_fourcc.h>
-#include <drm/ttm/ttm_placement.h>
-
-#include "vmwgfx_drv.h"
-#include "vmwgfx_kms.h"
-
-#define VMW_DIRTY_DELAY (HZ / 30)
-
-struct vmw_fb_par {
- struct vmw_private *vmw_priv;
-
- void *vmalloc;
-
- struct mutex bo_mutex;
- struct vmw_buffer_object *vmw_bo;
- unsigned bo_size;
- struct drm_framebuffer *set_fb;
- struct drm_display_mode *set_mode;
- u32 fb_x;
- u32 fb_y;
- bool bo_iowrite;
-
- u32 pseudo_palette[17];
-
- unsigned max_width;
- unsigned max_height;
-
- struct {
- spinlock_t lock;
- bool active;
- unsigned x1;
- unsigned y1;
- unsigned x2;
- unsigned y2;
- } dirty;
-
- struct drm_crtc *crtc;
- struct drm_connector *con;
- struct delayed_work local_work;
-};
-
-static int vmw_fb_setcolreg(unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp,
- struct fb_info *info)
-{
- struct vmw_fb_par *par = info->par;
- u32 *pal = par->pseudo_palette;
-
- if (regno > 15) {
- DRM_ERROR("Bad regno %u.\n", regno);
- return 1;
- }
-
- switch (par->set_fb->format->depth) {
- case 24:
- case 32:
- pal[regno] = ((red & 0xff00) << 8) |
- (green & 0xff00) |
- ((blue & 0xff00) >> 8);
- break;
- default:
- DRM_ERROR("Bad depth %u, bpp %u.\n",
- par->set_fb->format->depth,
- par->set_fb->format->cpp[0] * 8);
- return 1;
- }
-
- return 0;
-}
-
-static int vmw_fb_check_var(struct fb_var_screeninfo *var,
- struct fb_info *info)
-{
- int depth = var->bits_per_pixel;
- struct vmw_fb_par *par = info->par;
- struct vmw_private *vmw_priv = par->vmw_priv;
-
- switch (var->bits_per_pixel) {
- case 32:
- depth = (var->transp.length > 0) ? 32 : 24;
- break;
- default:
- DRM_ERROR("Bad bpp %u.\n", var->bits_per_pixel);
- return -EINVAL;
- }
-
- switch (depth) {
- case 24:
- var->red.offset = 16;
- var->green.offset = 8;
- var->blue.offset = 0;
- var->red.length = 8;
- var->green.length = 8;
- var->blue.length = 8;
- var->transp.length = 0;
- var->transp.offset = 0;
- break;
- case 32:
- var->red.offset = 16;
- var->green.offset = 8;
- var->blue.offset = 0;
- var->red.length = 8;
- var->green.length = 8;
- var->blue.length = 8;
- var->transp.length = 8;
- var->transp.offset = 24;
- break;
- default:
- DRM_ERROR("Bad depth %u.\n", depth);
- return -EINVAL;
- }
-
- if ((var->xoffset + var->xres) > par->max_width ||
- (var->yoffset + var->yres) > par->max_height) {
- DRM_ERROR("Requested geom can not fit in framebuffer\n");
- return -EINVAL;
- }
-
- if (!vmw_kms_validate_mode_vram(vmw_priv,
- var->xres * var->bits_per_pixel/8,
- var->yoffset + var->yres)) {
- DRM_ERROR("Requested geom can not fit in framebuffer\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int vmw_fb_blank(int blank, struct fb_info *info)
-{
- return 0;
-}
-
-/**
- * vmw_fb_dirty_flush - flush dirty regions to the kms framebuffer
- *
- * @work: The struct work_struct associated with this task.
- *
- * This function flushes the dirty regions of the vmalloc framebuffer to the
- * kms framebuffer, and if the kms framebuffer is visible, also updated the
- * corresponding displays. Note that this function runs even if the kms
- * framebuffer is not bound to a crtc and thus not visible, but it's turned
- * off during hibernation using the par->dirty.active bool.
- */
-static void vmw_fb_dirty_flush(struct work_struct *work)
-{
- struct vmw_fb_par *par = container_of(work, struct vmw_fb_par,
- local_work.work);
- struct vmw_private *vmw_priv = par->vmw_priv;
- struct fb_info *info = vmw_priv->fb_info;
- unsigned long irq_flags;
- s32 dst_x1, dst_x2, dst_y1, dst_y2, w = 0, h = 0;
- u32 cpp, max_x, max_y;
- struct drm_clip_rect clip;
- struct drm_framebuffer *cur_fb;
- u8 *src_ptr, *dst_ptr;
- struct vmw_buffer_object *vbo = par->vmw_bo;
- void *virtual;
-
- if (!READ_ONCE(par->dirty.active))
- return;
-
- mutex_lock(&par->bo_mutex);
- cur_fb = par->set_fb;
- if (!cur_fb)
- goto out_unlock;
-
- (void) ttm_bo_reserve(&vbo->base, false, false, NULL);
- virtual = vmw_bo_map_and_cache(vbo);
- if (!virtual)
- goto out_unreserve;
-
- spin_lock_irqsave(&par->dirty.lock, irq_flags);
- if (!par->dirty.active) {
- spin_unlock_irqrestore(&par->dirty.lock, irq_flags);
- goto out_unreserve;
- }
-
- /*
- * Handle panning when copying from vmalloc to framebuffer.
- * Clip dirty area to framebuffer.
- */
- cpp = cur_fb->format->cpp[0];
- max_x = par->fb_x + cur_fb->width;
- max_y = par->fb_y + cur_fb->height;
-
- dst_x1 = par->dirty.x1 - par->fb_x;
- dst_y1 = par->dirty.y1 - par->fb_y;
- dst_x1 = max_t(s32, dst_x1, 0);
- dst_y1 = max_t(s32, dst_y1, 0);
-
- dst_x2 = par->dirty.x2 - par->fb_x;
- dst_y2 = par->dirty.y2 - par->fb_y;
- dst_x2 = min_t(s32, dst_x2, max_x);
- dst_y2 = min_t(s32, dst_y2, max_y);
- w = dst_x2 - dst_x1;
- h = dst_y2 - dst_y1;
- w = max_t(s32, 0, w);
- h = max_t(s32, 0, h);
-
- par->dirty.x1 = par->dirty.x2 = 0;
- par->dirty.y1 = par->dirty.y2 = 0;
- spin_unlock_irqrestore(&par->dirty.lock, irq_flags);
-
- if (w && h) {
- dst_ptr = (u8 *)virtual +
- (dst_y1 * par->set_fb->pitches[0] + dst_x1 * cpp);
- src_ptr = (u8 *)par->vmalloc +
- ((dst_y1 + par->fb_y) * info->fix.line_length +
- (dst_x1 + par->fb_x) * cpp);
-
- while (h-- > 0) {
- memcpy(dst_ptr, src_ptr, w*cpp);
- dst_ptr += par->set_fb->pitches[0];
- src_ptr += info->fix.line_length;
- }
-
- clip.x1 = dst_x1;
- clip.x2 = dst_x2;
- clip.y1 = dst_y1;
- clip.y2 = dst_y2;
- }
-
-out_unreserve:
- ttm_bo_unreserve(&vbo->base);
- if (w && h) {
- WARN_ON_ONCE(par->set_fb->funcs->dirty(cur_fb, NULL, 0, 0,
- &clip, 1));
- vmw_cmd_flush(vmw_priv, false);
- }
-out_unlock:
- mutex_unlock(&par->bo_mutex);
-}
-
-static void vmw_fb_dirty_mark(struct vmw_fb_par *par,
- unsigned x1, unsigned y1,
- unsigned width, unsigned height)
-{
- unsigned long flags;
- unsigned x2 = x1 + width;
- unsigned y2 = y1 + height;
-
- spin_lock_irqsave(&par->dirty.lock, flags);
- if (par->dirty.x1 == par->dirty.x2) {
- par->dirty.x1 = x1;
- par->dirty.y1 = y1;
- par->dirty.x2 = x2;
- par->dirty.y2 = y2;
- /* if we are active start the dirty work
- * we share the work with the defio system */
- if (par->dirty.active)
- schedule_delayed_work(&par->local_work,
- VMW_DIRTY_DELAY);
- } else {
- if (x1 < par->dirty.x1)
- par->dirty.x1 = x1;
- if (y1 < par->dirty.y1)
- par->dirty.y1 = y1;
- if (x2 > par->dirty.x2)
- par->dirty.x2 = x2;
- if (y2 > par->dirty.y2)
- par->dirty.y2 = y2;
- }
- spin_unlock_irqrestore(&par->dirty.lock, flags);
-}
-
-static int vmw_fb_pan_display(struct fb_var_screeninfo *var,
- struct fb_info *info)
-{
- struct vmw_fb_par *par = info->par;
-
- if ((var->xoffset + var->xres) > var->xres_virtual ||
- (var->yoffset + var->yres) > var->yres_virtual) {
- DRM_ERROR("Requested panning can not fit in framebuffer\n");
- return -EINVAL;
- }
-
- mutex_lock(&par->bo_mutex);
- par->fb_x = var->xoffset;
- par->fb_y = var->yoffset;
- if (par->set_fb)
- vmw_fb_dirty_mark(par, par->fb_x, par->fb_y, par->set_fb->width,
- par->set_fb->height);
- mutex_unlock(&par->bo_mutex);
-
- return 0;
-}
-
-static void vmw_deferred_io(struct fb_info *info, struct list_head *pagereflist)
-{
- struct vmw_fb_par *par = info->par;
- unsigned long start, end, min, max;
- unsigned long flags;
- struct fb_deferred_io_pageref *pageref;
- int y1, y2;
-
- min = ULONG_MAX;
- max = 0;
- list_for_each_entry(pageref, pagereflist, list) {
- start = pageref->offset;
- end = start + PAGE_SIZE - 1;
- min = min(min, start);
- max = max(max, end);
- }
-
- if (min < max) {
- y1 = min / info->fix.line_length;
- y2 = (max / info->fix.line_length) + 1;
-
- spin_lock_irqsave(&par->dirty.lock, flags);
- par->dirty.x1 = 0;
- par->dirty.y1 = y1;
- par->dirty.x2 = info->var.xres;
- par->dirty.y2 = y2;
- spin_unlock_irqrestore(&par->dirty.lock, flags);
-
- /*
- * Since we've already waited on this work once, try to
- * execute asap.
- */
- cancel_delayed_work(&par->local_work);
- schedule_delayed_work(&par->local_work, 0);
- }
-};
-
-static struct fb_deferred_io vmw_defio = {
- .delay = VMW_DIRTY_DELAY,
- .deferred_io = vmw_deferred_io,
-};
-
-/*
- * Draw code
- */
-
-static void vmw_fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
-{
- cfb_fillrect(info, rect);
- vmw_fb_dirty_mark(info->par, rect->dx, rect->dy,
- rect->width, rect->height);
-}
-
-static void vmw_fb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
-{
- cfb_copyarea(info, region);
- vmw_fb_dirty_mark(info->par, region->dx, region->dy,
- region->width, region->height);
-}
-
-static void vmw_fb_imageblit(struct fb_info *info, const struct fb_image *image)
-{
- cfb_imageblit(info, image);
- vmw_fb_dirty_mark(info->par, image->dx, image->dy,
- image->width, image->height);
-}
-
-/*
- * Bring up code
- */
-
-static int vmw_fb_create_bo(struct vmw_private *vmw_priv,
- size_t size, struct vmw_buffer_object **out)
-{
- struct vmw_buffer_object *vmw_bo;
- int ret;
-
- ret = vmw_bo_create(vmw_priv, size,
- &vmw_sys_placement,
- false, false,
- &vmw_bo_bo_free, &vmw_bo);
- if (unlikely(ret != 0))
- return ret;
-
- *out = vmw_bo;
-
- return ret;
-}
-
-static int vmw_fb_compute_depth(struct fb_var_screeninfo *var,
- int *depth)
-{
- switch (var->bits_per_pixel) {
- case 32:
- *depth = (var->transp.length > 0) ? 32 : 24;
- break;
- default:
- DRM_ERROR("Bad bpp %u.\n", var->bits_per_pixel);
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int vmwgfx_set_config_internal(struct drm_mode_set *set)
-{
- struct drm_crtc *crtc = set->crtc;
- struct drm_modeset_acquire_ctx ctx;
- int ret;
-
- drm_modeset_acquire_init(&ctx, 0);
-
-restart:
- ret = crtc->funcs->set_config(set, &ctx);
-
- if (ret == -EDEADLK) {
- drm_modeset_backoff(&ctx);
- goto restart;
- }
-
- drm_modeset_drop_locks(&ctx);
- drm_modeset_acquire_fini(&ctx);
-
- return ret;
-}
-
-static int vmw_fb_kms_detach(struct vmw_fb_par *par,
- bool detach_bo,
- bool unref_bo)
-{
- struct drm_framebuffer *cur_fb = par->set_fb;
- int ret;
-
- /* Detach the KMS framebuffer from crtcs */
- if (par->set_mode) {
- struct drm_mode_set set;
-
- set.crtc = par->crtc;
- set.x = 0;
- set.y = 0;
- set.mode = NULL;
- set.fb = NULL;
- set.num_connectors = 0;
- set.connectors = &par->con;
- ret = vmwgfx_set_config_internal(&set);
- if (ret) {
- DRM_ERROR("Could not unset a mode.\n");
- return ret;
- }
- drm_mode_destroy(&par->vmw_priv->drm, par->set_mode);
- par->set_mode = NULL;
- }
-
- if (cur_fb) {
- drm_framebuffer_put(cur_fb);
- par->set_fb = NULL;
- }
-
- if (par->vmw_bo && detach_bo && unref_bo)
- vmw_bo_unreference(&par->vmw_bo);
-
- return 0;
-}
-
-static int vmw_fb_kms_framebuffer(struct fb_info *info)
-{
- struct drm_mode_fb_cmd2 mode_cmd = {0};
- struct vmw_fb_par *par = info->par;
- struct fb_var_screeninfo *var = &info->var;
- struct drm_framebuffer *cur_fb;
- struct vmw_framebuffer *vfb;
- int ret = 0, depth;
- size_t new_bo_size;
-
- ret = vmw_fb_compute_depth(var, &depth);
- if (ret)
- return ret;
-
- mode_cmd.width = var->xres;
- mode_cmd.height = var->yres;
- mode_cmd.pitches[0] = ((var->bits_per_pixel + 7) / 8) * mode_cmd.width;
- mode_cmd.pixel_format =
- drm_mode_legacy_fb_format(var->bits_per_pixel, depth);
-
- cur_fb = par->set_fb;
- if (cur_fb && cur_fb->width == mode_cmd.width &&
- cur_fb->height == mode_cmd.height &&
- cur_fb->format->format == mode_cmd.pixel_format &&
- cur_fb->pitches[0] == mode_cmd.pitches[0])
- return 0;
-
- /* Need new buffer object ? */
- new_bo_size = (size_t) mode_cmd.pitches[0] * (size_t) mode_cmd.height;
- ret = vmw_fb_kms_detach(par,
- par->bo_size < new_bo_size ||
- par->bo_size > 2*new_bo_size,
- true);
- if (ret)
- return ret;
-
- if (!par->vmw_bo) {
- ret = vmw_fb_create_bo(par->vmw_priv, new_bo_size,
- &par->vmw_bo);
- if (ret) {
- DRM_ERROR("Failed creating a buffer object for "
- "fbdev.\n");
- return ret;
- }
- par->bo_size = new_bo_size;
- }
-
- vfb = vmw_kms_new_framebuffer(par->vmw_priv, par->vmw_bo, NULL,
- true, &mode_cmd);
- if (IS_ERR(vfb))
- return PTR_ERR(vfb);
-
- par->set_fb = &vfb->base;
-
- return 0;
-}
-
-static int vmw_fb_set_par(struct fb_info *info)
-{
- struct vmw_fb_par *par = info->par;
- struct vmw_private *vmw_priv = par->vmw_priv;
- struct drm_mode_set set;
- struct fb_var_screeninfo *var = &info->var;
- struct drm_display_mode new_mode = { DRM_MODE("fb_mode",
- DRM_MODE_TYPE_DRIVER,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_PVSYNC)
- };
- struct drm_display_mode *mode;
- int ret;
-
- mode = drm_mode_duplicate(&vmw_priv->drm, &new_mode);
- if (!mode) {
- DRM_ERROR("Could not create new fb mode.\n");
- return -ENOMEM;
- }
-
- mode->hdisplay = var->xres;
- mode->vdisplay = var->yres;
- vmw_guess_mode_timing(mode);
-
- if (!vmw_kms_validate_mode_vram(vmw_priv,
- mode->hdisplay *
- DIV_ROUND_UP(var->bits_per_pixel, 8),
- mode->vdisplay)) {
- drm_mode_destroy(&vmw_priv->drm, mode);
- return -EINVAL;
- }
-
- mutex_lock(&par->bo_mutex);
- ret = vmw_fb_kms_framebuffer(info);
- if (ret)
- goto out_unlock;
-
- par->fb_x = var->xoffset;
- par->fb_y = var->yoffset;
-
- set.crtc = par->crtc;
- set.x = 0;
- set.y = 0;
- set.mode = mode;
- set.fb = par->set_fb;
- set.num_connectors = 1;
- set.connectors = &par->con;
-
- ret = vmwgfx_set_config_internal(&set);
- if (ret)
- goto out_unlock;
-
- vmw_fb_dirty_mark(par, par->fb_x, par->fb_y,
- par->set_fb->width, par->set_fb->height);
-
- /* If there already was stuff dirty we wont
- * schedule a new work, so lets do it now */
-
- schedule_delayed_work(&par->local_work, 0);
-
-out_unlock:
- if (par->set_mode)
- drm_mode_destroy(&vmw_priv->drm, par->set_mode);
- par->set_mode = mode;
-
- mutex_unlock(&par->bo_mutex);
-
- return ret;
-}
-
-
-static const struct fb_ops vmw_fb_ops = {
- .owner = THIS_MODULE,
- .fb_check_var = vmw_fb_check_var,
- .fb_set_par = vmw_fb_set_par,
- .fb_setcolreg = vmw_fb_setcolreg,
- .fb_fillrect = vmw_fb_fillrect,
- .fb_copyarea = vmw_fb_copyarea,
- .fb_imageblit = vmw_fb_imageblit,
- .fb_pan_display = vmw_fb_pan_display,
- .fb_blank = vmw_fb_blank,
- .fb_mmap = fb_deferred_io_mmap,
-};
-
-int vmw_fb_init(struct vmw_private *vmw_priv)
-{
- struct device *device = vmw_priv->drm.dev;
- struct vmw_fb_par *par;
- struct fb_info *info;
- unsigned fb_width, fb_height;
- unsigned int fb_bpp, fb_pitch, fb_size;
- struct drm_display_mode *init_mode;
- int ret;
-
- fb_bpp = 32;
-
- /* XXX As shouldn't these be as well. */
- fb_width = min(vmw_priv->fb_max_width, (unsigned)2048);
- fb_height = min(vmw_priv->fb_max_height, (unsigned)2048);
-
- fb_pitch = fb_width * fb_bpp / 8;
- fb_size = fb_pitch * fb_height;
-
- info = framebuffer_alloc(sizeof(*par), device);
- if (!info)
- return -ENOMEM;
-
- /*
- * Par
- */
- vmw_priv->fb_info = info;
- par = info->par;
- memset(par, 0, sizeof(*par));
- INIT_DELAYED_WORK(&par->local_work, &vmw_fb_dirty_flush);
- par->vmw_priv = vmw_priv;
- par->vmalloc = NULL;
- par->max_width = fb_width;
- par->max_height = fb_height;
-
- ret = vmw_kms_fbdev_init_data(vmw_priv, 0, par->max_width,
- par->max_height, &par->con,
- &par->crtc, &init_mode);
- if (ret)
- goto err_kms;
-
- info->var.xres = init_mode->hdisplay;
- info->var.yres = init_mode->vdisplay;
-
- /*
- * Create buffers and alloc memory
- */
- par->vmalloc = vzalloc(fb_size);
- if (unlikely(par->vmalloc == NULL)) {
- ret = -ENOMEM;
- goto err_free;
- }
-
- /*
- * Fixed and var
- */
- strcpy(info->fix.id, "svgadrmfb");
- info->fix.type = FB_TYPE_PACKED_PIXELS;
- info->fix.visual = FB_VISUAL_TRUECOLOR;
- info->fix.type_aux = 0;
- info->fix.xpanstep = 1; /* doing it in hw */
- info->fix.ypanstep = 1; /* doing it in hw */
- info->fix.ywrapstep = 0;
- info->fix.accel = FB_ACCEL_NONE;
- info->fix.line_length = fb_pitch;
-
- info->fix.smem_start = 0;
- info->fix.smem_len = fb_size;
-
- info->pseudo_palette = par->pseudo_palette;
- info->screen_base = (char __iomem *)par->vmalloc;
- info->screen_size = fb_size;
-
- info->fbops = &vmw_fb_ops;
-
- /* 24 depth per default */
- info->var.red.offset = 16;
- info->var.green.offset = 8;
- info->var.blue.offset = 0;
- info->var.red.length = 8;
- info->var.green.length = 8;
- info->var.blue.length = 8;
- info->var.transp.offset = 0;
- info->var.transp.length = 0;
-
- info->var.xres_virtual = fb_width;
- info->var.yres_virtual = fb_height;
- info->var.bits_per_pixel = fb_bpp;
- info->var.xoffset = 0;
- info->var.yoffset = 0;
- info->var.activate = FB_ACTIVATE_NOW;
- info->var.height = -1;
- info->var.width = -1;
-
- /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
- info->apertures = alloc_apertures(1);
- if (!info->apertures) {
- ret = -ENOMEM;
- goto err_aper;
- }
- info->apertures->ranges[0].base = vmw_priv->vram_start;
- info->apertures->ranges[0].size = vmw_priv->vram_size;
-
- /*
- * Dirty & Deferred IO
- */
- par->dirty.x1 = par->dirty.x2 = 0;
- par->dirty.y1 = par->dirty.y2 = 0;
- par->dirty.active = true;
- spin_lock_init(&par->dirty.lock);
- mutex_init(&par->bo_mutex);
- info->fbdefio = &vmw_defio;
- fb_deferred_io_init(info);
-
- ret = register_framebuffer(info);
- if (unlikely(ret != 0))
- goto err_defio;
-
- vmw_fb_set_par(info);
-
- return 0;
-
-err_defio:
- fb_deferred_io_cleanup(info);
-err_aper:
-err_free:
- vfree(par->vmalloc);
-err_kms:
- framebuffer_release(info);
- vmw_priv->fb_info = NULL;
-
- return ret;
-}
-
-int vmw_fb_close(struct vmw_private *vmw_priv)
-{
- struct fb_info *info;
- struct vmw_fb_par *par;
-
- if (!vmw_priv->fb_info)
- return 0;
-
- info = vmw_priv->fb_info;
- par = info->par;
-
- /* ??? order */
- fb_deferred_io_cleanup(info);
- cancel_delayed_work_sync(&par->local_work);
- unregister_framebuffer(info);
-
- mutex_lock(&par->bo_mutex);
- (void) vmw_fb_kms_detach(par, true, true);
- mutex_unlock(&par->bo_mutex);
-
- vfree(par->vmalloc);
- framebuffer_release(info);
-
- return 0;
-}
-
-int vmw_fb_off(struct vmw_private *vmw_priv)
-{
- struct fb_info *info;
- struct vmw_fb_par *par;
- unsigned long flags;
-
- if (!vmw_priv->fb_info)
- return -EINVAL;
-
- info = vmw_priv->fb_info;
- par = info->par;
-
- spin_lock_irqsave(&par->dirty.lock, flags);
- par->dirty.active = false;
- spin_unlock_irqrestore(&par->dirty.lock, flags);
-
- flush_delayed_work(&info->deferred_work);
- flush_delayed_work(&par->local_work);
-
- return 0;
-}
-
-int vmw_fb_on(struct vmw_private *vmw_priv)
-{
- struct fb_info *info;
- struct vmw_fb_par *par;
- unsigned long flags;
-
- if (!vmw_priv->fb_info)
- return -EINVAL;
-
- info = vmw_priv->fb_info;
- par = info->par;
-
- spin_lock_irqsave(&par->dirty.lock, flags);
- par->dirty.active = true;
- spin_unlock_irqrestore(&par->dirty.lock, flags);
-
- /*
- * Need to reschedule a dirty update, because otherwise that's
- * only done in dirty_mark() if the previous coalesced
- * dirty region was empty.
- */
- schedule_delayed_work(&par->local_work, 0);
-
- return 0;
-}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
index 60e3cc537f36..abd5e3323ebf 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmrid_manager.c
@@ -71,7 +71,7 @@ static int vmw_gmrid_man_get_node(struct ttm_resource_manager *man,
spin_lock(&gman->lock);
if (gman->max_gmr_pages > 0) {
- gman->used_gmr_pages += (*res)->num_pages;
+ gman->used_gmr_pages += PFN_UP((*res)->size);
/*
* Because the graphics memory is a soft limit we can try to
* expand it instead of letting the userspace apps crash.
@@ -114,7 +114,7 @@ static int vmw_gmrid_man_get_node(struct ttm_resource_manager *man,
return 0;
nospace:
- gman->used_gmr_pages -= (*res)->num_pages;
+ gman->used_gmr_pages -= PFN_UP((*res)->size);
spin_unlock(&gman->lock);
ida_free(&gman->gmr_ida, id);
ttm_resource_fini(man, *res);
@@ -129,7 +129,7 @@ static void vmw_gmrid_man_put_node(struct ttm_resource_manager *man,
ida_free(&gman->gmr_ida, res->start);
spin_lock(&gman->lock);
- gman->used_gmr_pages -= res->num_pages;
+ gman->used_gmr_pages -= PFN_UP(res->size);
spin_unlock(&gman->lock);
ttm_resource_fini(man, res);
kfree(res);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.c b/drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.c
deleted file mode 100644
index 06aebc12774e..000000000000
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA.
- * All Rights Reserved.
- *
- * 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, sub license, 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 (including the
- * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
- */
-
-/*
- * Simple open hash tab implementation.
- *
- * Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
- */
-
-#include <linux/export.h>
-#include <linux/hash.h>
-#include <linux/mm.h>
-#include <linux/rculist.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-
-#include <drm/drm_print.h>
-
-#include "vmwgfx_hashtab.h"
-
-int vmwgfx_ht_create(struct vmwgfx_open_hash *ht, unsigned int order)
-{
- unsigned int size = 1 << order;
-
- ht->order = order;
- ht->table = NULL;
- if (size <= PAGE_SIZE / sizeof(*ht->table))
- ht->table = kcalloc(size, sizeof(*ht->table), GFP_KERNEL);
- else
- ht->table = vzalloc(array_size(size, sizeof(*ht->table)));
- if (!ht->table) {
- DRM_ERROR("Out of memory for hash table\n");
- return -ENOMEM;
- }
- return 0;
-}
-
-void vmwgfx_ht_verbose_list(struct vmwgfx_open_hash *ht, unsigned long key)
-{
- struct vmwgfx_hash_item *entry;
- struct hlist_head *h_list;
- unsigned int hashed_key;
- int count = 0;
-
- hashed_key = hash_long(key, ht->order);
- DRM_DEBUG("Key is 0x%08lx, Hashed key is 0x%08x\n", key, hashed_key);
- h_list = &ht->table[hashed_key];
- hlist_for_each_entry(entry, h_list, head)
- DRM_DEBUG("count %d, key: 0x%08lx\n", count++, entry->key);
-}
-
-static struct hlist_node *vmwgfx_ht_find_key(struct vmwgfx_open_hash *ht, unsigned long key)
-{
- struct vmwgfx_hash_item *entry;
- struct hlist_head *h_list;
- unsigned int hashed_key;
-
- hashed_key = hash_long(key, ht->order);
- h_list = &ht->table[hashed_key];
- hlist_for_each_entry(entry, h_list, head) {
- if (entry->key == key)
- return &entry->head;
- if (entry->key > key)
- break;
- }
- return NULL;
-}
-
-static struct hlist_node *vmwgfx_ht_find_key_rcu(struct vmwgfx_open_hash *ht, unsigned long key)
-{
- struct vmwgfx_hash_item *entry;
- struct hlist_head *h_list;
- unsigned int hashed_key;
-
- hashed_key = hash_long(key, ht->order);
- h_list = &ht->table[hashed_key];
- hlist_for_each_entry_rcu(entry, h_list, head) {
- if (entry->key == key)
- return &entry->head;
- if (entry->key > key)
- break;
- }
- return NULL;
-}
-
-int vmwgfx_ht_insert_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item)
-{
- struct vmwgfx_hash_item *entry;
- struct hlist_head *h_list;
- struct hlist_node *parent;
- unsigned int hashed_key;
- unsigned long key = item->key;
-
- hashed_key = hash_long(key, ht->order);
- h_list = &ht->table[hashed_key];
- parent = NULL;
- hlist_for_each_entry(entry, h_list, head) {
- if (entry->key == key)
- return -EINVAL;
- if (entry->key > key)
- break;
- parent = &entry->head;
- }
- if (parent)
- hlist_add_behind_rcu(&item->head, parent);
- else
- hlist_add_head_rcu(&item->head, h_list);
- return 0;
-}
-
-/*
- * Just insert an item and return any "bits" bit key that hasn't been
- * used before.
- */
-int vmwgfx_ht_just_insert_please(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item,
- unsigned long seed, int bits, int shift,
- unsigned long add)
-{
- int ret;
- unsigned long mask = (1UL << bits) - 1;
- unsigned long first, unshifted_key;
-
- unshifted_key = hash_long(seed, bits);
- first = unshifted_key;
- do {
- item->key = (unshifted_key << shift) + add;
- ret = vmwgfx_ht_insert_item(ht, item);
- if (ret)
- unshifted_key = (unshifted_key + 1) & mask;
- } while (ret && (unshifted_key != first));
-
- if (ret) {
- DRM_ERROR("Available key bit space exhausted\n");
- return -EINVAL;
- }
- return 0;
-}
-
-int vmwgfx_ht_find_item(struct vmwgfx_open_hash *ht, unsigned long key,
- struct vmwgfx_hash_item **item)
-{
- struct hlist_node *list;
-
- list = vmwgfx_ht_find_key_rcu(ht, key);
- if (!list)
- return -EINVAL;
-
- *item = hlist_entry(list, struct vmwgfx_hash_item, head);
- return 0;
-}
-
-int vmwgfx_ht_remove_key(struct vmwgfx_open_hash *ht, unsigned long key)
-{
- struct hlist_node *list;
-
- list = vmwgfx_ht_find_key(ht, key);
- if (list) {
- hlist_del_init_rcu(list);
- return 0;
- }
- return -EINVAL;
-}
-
-int vmwgfx_ht_remove_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item)
-{
- hlist_del_init_rcu(&item->head);
- return 0;
-}
-
-void vmwgfx_ht_remove(struct vmwgfx_open_hash *ht)
-{
- if (ht->table) {
- kvfree(ht->table);
- ht->table = NULL;
- }
-}
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.h b/drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.h
deleted file mode 100644
index a9ce12922e21..000000000000
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_hashtab.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright 2006 Tungsten Graphics, Inc., Bismack, ND. USA.
- * All Rights Reserved.
- *
- * 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, sub license, 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 (including the
- * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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.
- */
-
-/*
- * Simple open hash tab implementation.
- *
- * Authors:
- * Thomas Hellström <thomas-at-tungstengraphics-dot-com>
- */
-
-/*
- * TODO: Replace this hashtable with Linux' generic implementation
- * from <linux/hashtable.h>.
- */
-
-#ifndef VMWGFX_HASHTAB_H
-#define VMWGFX_HASHTAB_H
-
-#include <linux/list.h>
-
-#define drm_hash_entry(_ptr, _type, _member) container_of(_ptr, _type, _member)
-
-struct vmwgfx_hash_item {
- struct hlist_node head;
- unsigned long key;
-};
-
-struct vmwgfx_open_hash {
- struct hlist_head *table;
- u8 order;
-};
-
-int vmwgfx_ht_create(struct vmwgfx_open_hash *ht, unsigned int order);
-int vmwgfx_ht_insert_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item);
-int vmwgfx_ht_just_insert_please(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item,
- unsigned long seed, int bits, int shift,
- unsigned long add);
-int vmwgfx_ht_find_item(struct vmwgfx_open_hash *ht, unsigned long key,
- struct vmwgfx_hash_item **item);
-
-void vmwgfx_ht_verbose_list(struct vmwgfx_open_hash *ht, unsigned long key);
-int vmwgfx_ht_remove_key(struct vmwgfx_open_hash *ht, unsigned long key);
-int vmwgfx_ht_remove_item(struct vmwgfx_open_hash *ht, struct vmwgfx_hash_item *item);
-void vmwgfx_ht_remove(struct vmwgfx_open_hash *ht);
-
-/*
- * RCU-safe interface
- *
- * The user of this API needs to make sure that two or more instances of the
- * hash table manipulation functions are never run simultaneously.
- * The lookup function vmwgfx_ht_find_item_rcu may, however, run simultaneously
- * with any of the manipulation functions as long as it's called from within
- * an RCU read-locked section.
- */
-#define vmwgfx_ht_insert_item_rcu vmwgfx_ht_insert_item
-#define vmwgfx_ht_just_insert_please_rcu vmwgfx_ht_just_insert_please
-#define vmwgfx_ht_remove_key_rcu vmwgfx_ht_remove_key
-#define vmwgfx_ht_remove_item_rcu vmwgfx_ht_remove_item
-#define vmwgfx_ht_find_item_rcu vmwgfx_ht_find_item
-
-#endif
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 214829c32ed8..257f090071f1 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -25,15 +25,15 @@
*
**************************************************************************/
+#include "vmwgfx_kms.h"
+#include "vmw_surface_cache.h"
+
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_rect.h>
#include <drm/drm_sysfs.h>
-#include <drm/drm_vblank.h>
-
-#include "vmwgfx_kms.h"
void vmw_du_cleanup(struct vmw_display_unit *du)
{
@@ -52,9 +52,9 @@ void vmw_du_cleanup(struct vmw_display_unit *du)
* Display Unit Cursor functions
*/
+static int vmw_du_cursor_plane_unmap_cm(struct vmw_plane_state *vps);
static void vmw_cursor_update_mob(struct vmw_private *dev_priv,
- struct ttm_buffer_object *bo,
- struct ttm_bo_kmap_obj *map,
+ struct vmw_plane_state *vps,
u32 *image, u32 width, u32 height,
u32 hotspotX, u32 hotspotY);
@@ -63,23 +63,23 @@ struct vmw_svga_fifo_cmd_define_cursor {
SVGAFifoCmdDefineAlphaCursor cursor;
};
-static void vmw_cursor_update_image(struct vmw_private *dev_priv,
- struct ttm_buffer_object *cm_bo,
- struct ttm_bo_kmap_obj *cm_map,
- u32 *image, u32 width, u32 height,
- u32 hotspotX, u32 hotspotY)
+/**
+ * vmw_send_define_cursor_cmd - queue a define cursor command
+ * @dev_priv: the private driver struct
+ * @image: buffer which holds the cursor image
+ * @width: width of the mouse cursor image
+ * @height: height of the mouse cursor image
+ * @hotspotX: the horizontal position of mouse hotspot
+ * @hotspotY: the vertical position of mouse hotspot
+ */
+static void vmw_send_define_cursor_cmd(struct vmw_private *dev_priv,
+ u32 *image, u32 width, u32 height,
+ u32 hotspotX, u32 hotspotY)
{
struct vmw_svga_fifo_cmd_define_cursor *cmd;
const u32 image_size = width * height * sizeof(*image);
const u32 cmd_size = sizeof(*cmd) + image_size;
- if (cm_bo != NULL) {
- vmw_cursor_update_mob(dev_priv, cm_bo, cm_map, image,
- width, height,
- hotspotX, hotspotY);
- return;
- }
-
/* Try to reserve fifocmd space and swallow any failures;
such reservations cannot be left unconsumed for long
under the risk of clogging other fifocmd users, so
@@ -87,7 +87,7 @@ static void vmw_cursor_update_image(struct vmw_private *dev_priv,
other fallible KMS-atomic resources at prepare_fb */
cmd = VMW_CMD_RESERVE(dev_priv, cmd_size);
- if (unlikely(cmd == NULL))
+ if (unlikely(!cmd))
return;
memset(cmd, 0, sizeof(*cmd));
@@ -105,11 +105,39 @@ static void vmw_cursor_update_image(struct vmw_private *dev_priv,
}
/**
+ * vmw_cursor_update_image - update the cursor image on the provided plane
+ * @dev_priv: the private driver struct
+ * @vps: the plane state of the cursor plane
+ * @image: buffer which holds the cursor image
+ * @width: width of the mouse cursor image
+ * @height: height of the mouse cursor image
+ * @hotspotX: the horizontal position of mouse hotspot
+ * @hotspotY: the vertical position of mouse hotspot
+ */
+static void vmw_cursor_update_image(struct vmw_private *dev_priv,
+ struct vmw_plane_state *vps,
+ u32 *image, u32 width, u32 height,
+ u32 hotspotX, u32 hotspotY)
+{
+ if (vps->cursor.bo)
+ vmw_cursor_update_mob(dev_priv, vps, image,
+ vps->base.crtc_w, vps->base.crtc_h,
+ hotspotX, hotspotY);
+
+ else
+ vmw_send_define_cursor_cmd(dev_priv, image, width, height,
+ hotspotX, hotspotY);
+}
+
+
+/**
* vmw_cursor_update_mob - Update cursor vis CursorMob mechanism
*
+ * Called from inside vmw_du_cursor_plane_atomic_update to actually
+ * make the cursor-image live.
+ *
* @dev_priv: device to work with
- * @bo: BO for the MOB
- * @map: kmap obj for the BO
+ * @vps: the plane state of the cursor plane
* @image: cursor source data to fill the MOB with
* @width: source data width
* @height: source data height
@@ -117,8 +145,7 @@ static void vmw_cursor_update_image(struct vmw_private *dev_priv,
* @hotspotY: cursor hotspot Y
*/
static void vmw_cursor_update_mob(struct vmw_private *dev_priv,
- struct ttm_buffer_object *bo,
- struct ttm_bo_kmap_obj *map,
+ struct vmw_plane_state *vps,
u32 *image, u32 width, u32 height,
u32 hotspotX, u32 hotspotY)
{
@@ -127,11 +154,11 @@ static void vmw_cursor_update_mob(struct vmw_private *dev_priv,
const u32 image_size = width * height * sizeof(*image);
bool dummy;
- BUG_ON(!image);
-
- header = (SVGAGBCursorHeader *)ttm_kmap_obj_virtual(map, &dummy);
+ header = ttm_kmap_obj_virtual(&vps->cursor.map, &dummy);
alpha_header = &header->header.alphaHeader;
+ memset(header, 0, sizeof(*header));
+
header->type = SVGA_ALPHA_CURSOR;
header->sizeInBytes = image_size;
@@ -141,100 +168,159 @@ static void vmw_cursor_update_mob(struct vmw_private *dev_priv,
alpha_header->height = height;
memcpy(header + 1, image, image_size);
-
- vmw_write(dev_priv, SVGA_REG_CURSOR_MOBID, bo->resource->start);
+ vmw_write(dev_priv, SVGA_REG_CURSOR_MOBID,
+ vps->cursor.bo->resource->start);
}
-void vmw_du_destroy_cursor_mob_array(struct vmw_cursor_plane *vcp)
-{
- size_t i;
- for (i = 0; i < ARRAY_SIZE(vcp->cursor_mob); i++) {
- if (vcp->cursor_mob[i] != NULL) {
- ttm_bo_unpin(vcp->cursor_mob[i]);
- ttm_bo_put(vcp->cursor_mob[i]);
- kfree(vcp->cursor_mob[i]);
- vcp->cursor_mob[i] = NULL;
- }
- }
+static u32 vmw_du_cursor_mob_size(u32 w, u32 h)
+{
+ return w * h * sizeof(u32) + sizeof(SVGAGBCursorHeader);
}
-#define CURSOR_MOB_SIZE(dimension) \
- ((dimension) * (dimension) * sizeof(u32) + sizeof(SVGAGBCursorHeader))
+/**
+ * vmw_du_cursor_plane_acquire_image -- Acquire the image data
+ * @vps: cursor plane state
+ */
+static u32 *vmw_du_cursor_plane_acquire_image(struct vmw_plane_state *vps)
+{
+ bool dummy;
+ if (vps->surf) {
+ if (vps->surf_mapped)
+ return vmw_bo_map_and_cache(vps->surf->res.backup);
+ return vps->surf->snooper.image;
+ } else if (vps->bo)
+ return ttm_kmap_obj_virtual(&vps->bo->map, &dummy);
+ return NULL;
+}
-int vmw_du_create_cursor_mob_array(struct vmw_cursor_plane *cursor)
+static bool vmw_du_cursor_plane_has_changed(struct vmw_plane_state *old_vps,
+ struct vmw_plane_state *new_vps)
{
- struct vmw_private *dev_priv = cursor->base.dev->dev_private;
- uint32_t cursor_max_dim, mob_max_size;
- int ret = 0;
- size_t i;
+ void *old_image;
+ void *new_image;
+ u32 size;
+ bool changed;
- if (!dev_priv->has_mob || (dev_priv->capabilities2 & SVGA_CAP2_CURSOR_MOB) == 0)
- return -ENOSYS;
+ if (old_vps->base.crtc_w != new_vps->base.crtc_w ||
+ old_vps->base.crtc_h != new_vps->base.crtc_h)
+ return true;
- mob_max_size = vmw_read(dev_priv, SVGA_REG_MOB_MAX_SIZE);
- cursor_max_dim = vmw_read(dev_priv, SVGA_REG_CURSOR_MAX_DIMENSION);
+ if (old_vps->cursor.hotspot_x != new_vps->cursor.hotspot_x ||
+ old_vps->cursor.hotspot_y != new_vps->cursor.hotspot_y)
+ return true;
- if (CURSOR_MOB_SIZE(cursor_max_dim) > mob_max_size)
- cursor_max_dim = 64; /* Mandatorily-supported cursor dimension */
+ size = new_vps->base.crtc_w * new_vps->base.crtc_h * sizeof(u32);
- for (i = 0; i < ARRAY_SIZE(cursor->cursor_mob); i++) {
- struct ttm_buffer_object **const bo = &cursor->cursor_mob[i];
+ old_image = vmw_du_cursor_plane_acquire_image(old_vps);
+ new_image = vmw_du_cursor_plane_acquire_image(new_vps);
- ret = vmw_bo_create_kernel(dev_priv,
- CURSOR_MOB_SIZE(cursor_max_dim),
- &vmw_mob_placement, bo);
+ changed = false;
+ if (old_image && new_image)
+ changed = memcmp(old_image, new_image, size) != 0;
- if (ret != 0)
- goto teardown;
+ return changed;
+}
- if ((*bo)->resource->mem_type != VMW_PL_MOB) {
- DRM_ERROR("Obtained buffer object is not a MOB.\n");
- ret = -ENOSYS;
- goto teardown;
- }
+static void vmw_du_destroy_cursor_mob(struct ttm_buffer_object **bo)
+{
+ if (!(*bo))
+ return;
- /* Fence the mob creation so we are guarateed to have the mob */
- ret = ttm_bo_reserve(*bo, false, false, NULL);
+ ttm_bo_unpin(*bo);
+ ttm_bo_put(*bo);
+ kfree(*bo);
+ *bo = NULL;
+}
- if (ret != 0)
- goto teardown;
+static void vmw_du_put_cursor_mob(struct vmw_cursor_plane *vcp,
+ struct vmw_plane_state *vps)
+{
+ u32 i;
- vmw_bo_fence_single(*bo, NULL);
+ if (!vps->cursor.bo)
+ return;
- ttm_bo_unreserve(*bo);
+ vmw_du_cursor_plane_unmap_cm(vps);
- drm_info(&dev_priv->drm, "Using CursorMob mobid %lu, max dimension %u\n",
- (*bo)->resource->start, cursor_max_dim);
+ /* Look for a free slot to return this mob to the cache. */
+ for (i = 0; i < ARRAY_SIZE(vcp->cursor_mobs); i++) {
+ if (!vcp->cursor_mobs[i]) {
+ vcp->cursor_mobs[i] = vps->cursor.bo;
+ vps->cursor.bo = NULL;
+ return;
+ }
}
- return 0;
-
-teardown:
- vmw_du_destroy_cursor_mob_array(cursor);
+ /* Cache is full: See if this mob is bigger than an existing mob. */
+ for (i = 0; i < ARRAY_SIZE(vcp->cursor_mobs); i++) {
+ if (vcp->cursor_mobs[i]->base.size <
+ vps->cursor.bo->base.size) {
+ vmw_du_destroy_cursor_mob(&vcp->cursor_mobs[i]);
+ vcp->cursor_mobs[i] = vps->cursor.bo;
+ vps->cursor.bo = NULL;
+ return;
+ }
+ }
- return ret;
+ /* Destroy it if it's not worth caching. */
+ vmw_du_destroy_cursor_mob(&vps->cursor.bo);
}
-#undef CURSOR_MOB_SIZE
-
-static void vmw_cursor_update_bo(struct vmw_private *dev_priv,
- struct ttm_buffer_object *cm_bo,
- struct ttm_bo_kmap_obj *cm_map,
- struct vmw_buffer_object *bo,
- u32 width, u32 height,
- u32 hotspotX, u32 hotspotY)
+static int vmw_du_get_cursor_mob(struct vmw_cursor_plane *vcp,
+ struct vmw_plane_state *vps)
{
- void *virtual;
- bool dummy;
+ struct vmw_private *dev_priv = vcp->base.dev->dev_private;
+ u32 size = vmw_du_cursor_mob_size(vps->base.crtc_w, vps->base.crtc_h);
+ u32 i;
+ u32 cursor_max_dim, mob_max_size;
+ int ret;
+
+ if (!dev_priv->has_mob ||
+ (dev_priv->capabilities2 & SVGA_CAP2_CURSOR_MOB) == 0)
+ return -EINVAL;
+
+ mob_max_size = vmw_read(dev_priv, SVGA_REG_MOB_MAX_SIZE);
+ cursor_max_dim = vmw_read(dev_priv, SVGA_REG_CURSOR_MAX_DIMENSION);
+
+ if (size > mob_max_size || vps->base.crtc_w > cursor_max_dim ||
+ vps->base.crtc_h > cursor_max_dim)
+ return -EINVAL;
- virtual = ttm_kmap_obj_virtual(&bo->map, &dummy);
- if (virtual) {
- vmw_cursor_update_image(dev_priv, cm_bo, cm_map, virtual,
- width, height,
- hotspotX, hotspotY);
- atomic_dec(&bo->base_mapped_count);
+ if (vps->cursor.bo) {
+ if (vps->cursor.bo->base.size >= size)
+ return 0;
+ vmw_du_put_cursor_mob(vcp, vps);
+ }
+
+ /* Look for an unused mob in the cache. */
+ for (i = 0; i < ARRAY_SIZE(vcp->cursor_mobs); i++) {
+ if (vcp->cursor_mobs[i] &&
+ vcp->cursor_mobs[i]->base.size >= size) {
+ vps->cursor.bo = vcp->cursor_mobs[i];
+ vcp->cursor_mobs[i] = NULL;
+ return 0;
+ }
}
+ /* Create a new mob if we can't find an existing one. */
+ ret = vmw_bo_create_kernel(dev_priv, size, &vmw_mob_placement,
+ &vps->cursor.bo);
+
+ if (ret != 0)
+ return ret;
+
+ /* Fence the mob creation so we are guarateed to have the mob */
+ ret = ttm_bo_reserve(vps->cursor.bo, false, false, NULL);
+ if (ret != 0)
+ goto teardown;
+
+ vmw_bo_fence_single(vps->cursor.bo, NULL);
+ ttm_bo_unreserve(vps->cursor.bo);
+ return 0;
+
+teardown:
+ vmw_du_destroy_cursor_mob(&vps->cursor.bo);
+ return ret;
}
@@ -266,7 +352,6 @@ static void vmw_cursor_update_position(struct vmw_private *dev_priv,
spin_unlock(&dev_priv->cursor_lock);
}
-
void vmw_kms_cursor_snoop(struct vmw_surface *srf,
struct ttm_object_file *tfile,
struct ttm_buffer_object *bo,
@@ -284,10 +369,13 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
SVGA3dCmdSurfaceDMA dma;
} *cmd;
int i, ret;
+ const struct SVGA3dSurfaceDesc *desc =
+ vmw_surface_get_desc(VMW_CURSOR_SNOOP_FORMAT);
+ const u32 image_pitch = VMW_CURSOR_SNOOP_WIDTH * desc->pitchBytesPerBlock;
cmd = container_of(header, struct vmw_dma_cmd, header);
- /* No snooper installed */
+ /* No snooper installed, nothing to copy */
if (!srf->snooper.image)
return;
@@ -308,7 +396,8 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
if (cmd->dma.guest.ptr.offset % PAGE_SIZE ||
box->x != 0 || box->y != 0 || box->z != 0 ||
box->srcx != 0 || box->srcy != 0 || box->srcz != 0 ||
- box->d != 1 || box_count != 1) {
+ box->d != 1 || box_count != 1 ||
+ box->w > VMW_CURSOR_SNOOP_WIDTH || box->h > VMW_CURSOR_SNOOP_HEIGHT) {
/* TODO handle none page aligned offsets */
/* TODO handle more dst & src != 0 */
/* TODO handle more then one copy */
@@ -322,7 +411,7 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
}
kmap_offset = cmd->dma.guest.ptr.offset >> PAGE_SHIFT;
- kmap_num = (64*64*4) >> PAGE_SHIFT;
+ kmap_num = (VMW_CURSOR_SNOOP_HEIGHT*image_pitch) >> PAGE_SHIFT;
ret = ttm_bo_reserve(bo, true, false, NULL);
if (unlikely(ret != 0)) {
@@ -336,14 +425,15 @@ void vmw_kms_cursor_snoop(struct vmw_surface *srf,
virtual = ttm_kmap_obj_virtual(&map, &dummy);
- if (box->w == 64 && cmd->dma.guest.pitch == 64*4) {
- memcpy(srf->snooper.image, virtual, 64*64*4);
+ if (box->w == VMW_CURSOR_SNOOP_WIDTH && cmd->dma.guest.pitch == image_pitch) {
+ memcpy(srf->snooper.image, virtual,
+ VMW_CURSOR_SNOOP_HEIGHT*image_pitch);
} else {
/* Image is unsigned pointer. */
for (i = 0; i < box->h; i++)
- memcpy(srf->snooper.image + i * 64,
+ memcpy(srf->snooper.image + i * image_pitch,
virtual + i * cmd->dma.guest.pitch,
- box->w * 4);
+ box->w * desc->pitchBytesPerBlock);
}
srf->snooper.age++;
@@ -387,15 +477,17 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
du = vmw_crtc_to_du(crtc);
if (!du->cursor_surface ||
- du->cursor_age == du->cursor_surface->snooper.age)
+ du->cursor_age == du->cursor_surface->snooper.age ||
+ !du->cursor_surface->snooper.image)
continue;
du->cursor_age = du->cursor_surface->snooper.age;
- vmw_cursor_update_image(dev_priv, NULL, NULL,
- du->cursor_surface->snooper.image,
- 64, 64,
- du->hotspot_x + du->core_hotspot_x,
- du->hotspot_y + du->core_hotspot_y);
+ vmw_send_define_cursor_cmd(dev_priv,
+ du->cursor_surface->snooper.image,
+ VMW_CURSOR_SNOOP_WIDTH,
+ VMW_CURSOR_SNOOP_HEIGHT,
+ du->hotspot_x + du->core_hotspot_x,
+ du->hotspot_y + du->core_hotspot_y);
}
mutex_unlock(&dev->mode_config.mutex);
@@ -404,8 +496,14 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv)
void vmw_du_cursor_plane_destroy(struct drm_plane *plane)
{
+ struct vmw_cursor_plane *vcp = vmw_plane_to_vcp(plane);
+ u32 i;
+
vmw_cursor_update_position(plane->dev->dev_private, false, 0, 0);
- vmw_du_destroy_cursor_mob_array(vmw_plane_to_vcp(plane));
+
+ for (i = 0; i < ARRAY_SIZE(vcp->cursor_mobs); i++)
+ vmw_du_destroy_cursor_mob(&vcp->cursor_mobs[i]);
+
drm_plane_cleanup(plane);
}
@@ -463,6 +561,87 @@ vmw_du_plane_cleanup_fb(struct drm_plane *plane,
/**
+ * vmw_du_cursor_plane_map_cm - Maps the cursor mobs.
+ *
+ * @vps: plane_state
+ *
+ * Returns 0 on success
+ */
+
+static int
+vmw_du_cursor_plane_map_cm(struct vmw_plane_state *vps)
+{
+ int ret;
+ u32 size = vmw_du_cursor_mob_size(vps->base.crtc_w, vps->base.crtc_h);
+ struct ttm_buffer_object *bo = vps->cursor.bo;
+
+ if (!bo)
+ return -EINVAL;
+
+ if (bo->base.size < size)
+ return -EINVAL;
+
+ if (vps->cursor.mapped)
+ return 0;
+
+ ret = ttm_bo_reserve(bo, false, false, NULL);
+
+ if (unlikely(ret != 0))
+ return -ENOMEM;
+
+ ret = ttm_bo_kmap(bo, 0, PFN_UP(size), &vps->cursor.map);
+
+ /*
+ * We just want to try to get mob bind to finish
+ * so that the first write to SVGA_REG_CURSOR_MOBID
+ * is done with a buffer that the device has already
+ * seen
+ */
+ (void) ttm_bo_wait(bo, false, false);
+
+ ttm_bo_unreserve(bo);
+
+ if (unlikely(ret != 0))
+ return -ENOMEM;
+
+ vps->cursor.mapped = true;
+
+ return 0;
+}
+
+
+/**
+ * vmw_du_cursor_plane_unmap_cm - Unmaps the cursor mobs.
+ *
+ * @vps: state of the cursor plane
+ *
+ * Returns 0 on success
+ */
+
+static int
+vmw_du_cursor_plane_unmap_cm(struct vmw_plane_state *vps)
+{
+ int ret = 0;
+ struct ttm_buffer_object *bo = vps->cursor.bo;
+
+ if (!vps->cursor.mapped)
+ return 0;
+
+ if (!bo)
+ return 0;
+
+ ret = ttm_bo_reserve(bo, true, false, NULL);
+ if (likely(ret == 0)) {
+ ttm_bo_kunmap(&vps->cursor.map);
+ ttm_bo_unreserve(bo);
+ vps->cursor.mapped = false;
+ }
+
+ return ret;
+}
+
+
+/**
* vmw_du_cursor_plane_cleanup_fb - Unpins the plane surface
*
* @plane: cursor plane
@@ -476,10 +655,16 @@ void
vmw_du_cursor_plane_cleanup_fb(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
+ struct vmw_cursor_plane *vcp = vmw_plane_to_vcp(plane);
struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state);
bool dummy;
- if (vps->bo != NULL && ttm_kmap_obj_virtual(&vps->bo->map, &dummy) != NULL) {
+ if (vps->surf_mapped) {
+ vmw_bo_unmap(vps->surf->res.backup);
+ vps->surf_mapped = false;
+ }
+
+ if (vps->bo && ttm_kmap_obj_virtual(&vps->bo->map, &dummy)) {
const int ret = ttm_bo_reserve(&vps->bo->base, true, false, NULL);
if (likely(ret == 0)) {
@@ -489,14 +674,8 @@ vmw_du_cursor_plane_cleanup_fb(struct drm_plane *plane,
}
}
- if (vps->cm_bo != NULL && ttm_kmap_obj_virtual(&vps->cm_map, &dummy) != NULL) {
- const int ret = ttm_bo_reserve(vps->cm_bo, true, false, NULL);
-
- if (likely(ret == 0)) {
- ttm_bo_kunmap(&vps->cm_map);
- ttm_bo_unreserve(vps->cm_bo);
- }
- }
+ vmw_du_cursor_plane_unmap_cm(vps);
+ vmw_du_put_cursor_mob(vcp, vps);
vmw_du_plane_unpin_surf(vps, false);
@@ -511,6 +690,7 @@ vmw_du_cursor_plane_cleanup_fb(struct drm_plane *plane,
}
}
+
/**
* vmw_du_cursor_plane_prepare_fb - Readies the cursor by referencing it
*
@@ -526,8 +706,6 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,
struct drm_framebuffer *fb = new_state->fb;
struct vmw_cursor_plane *vcp = vmw_plane_to_vcp(plane);
struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state);
- struct ttm_buffer_object *cm_bo = NULL;
- bool dummy;
int ret = 0;
if (vps->surf) {
@@ -550,13 +728,14 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,
}
}
- vps->cm_bo = NULL;
-
- if (vps->surf == NULL && vps->bo != NULL) {
+ if (!vps->surf && vps->bo) {
const u32 size = new_state->crtc_w * new_state->crtc_h * sizeof(u32);
- /* Not using vmw_bo_map_and_cache() helper here as we need to reserve
- the ttm_buffer_object first which wmw_bo_map_and_cache() omits. */
+ /*
+ * Not using vmw_bo_map_and_cache() helper here as we need to
+ * reserve the ttm_buffer_object first which
+ * vmw_bo_map_and_cache() omits.
+ */
ret = ttm_bo_reserve(&vps->bo->base, true, false, NULL);
if (unlikely(ret != 0))
@@ -571,69 +750,24 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane,
if (unlikely(ret != 0))
return -ENOMEM;
+ } else if (vps->surf && !vps->bo && vps->surf->res.backup) {
+
+ WARN_ON(vps->surf->snooper.image);
+ ret = ttm_bo_reserve(&vps->surf->res.backup->base, true, false,
+ NULL);
+ if (unlikely(ret != 0))
+ return -ENOMEM;
+ vmw_bo_map_and_cache(vps->surf->res.backup);
+ ttm_bo_unreserve(&vps->surf->res.backup->base);
+ vps->surf_mapped = true;
}
if (vps->surf || vps->bo) {
- unsigned cursor_mob_idx = vps->cursor_mob_idx;
-
- /* Lazily set up cursor MOBs just once -- no reattempts. */
- if (cursor_mob_idx == 0 && vcp->cursor_mob[0] == NULL)
- if (vmw_du_create_cursor_mob_array(vcp) != 0)
- vps->cursor_mob_idx = cursor_mob_idx = -1U;
-
- if (cursor_mob_idx < ARRAY_SIZE(vcp->cursor_mob)) {
- const u32 size = sizeof(SVGAGBCursorHeader) +
- new_state->crtc_w * new_state->crtc_h * sizeof(u32);
-
- cm_bo = vcp->cursor_mob[cursor_mob_idx];
-
- if (cm_bo->resource->num_pages * PAGE_SIZE < size) {
- ret = -EINVAL;
- goto error_bo_unmap;
- }
-
- ret = ttm_bo_reserve(cm_bo, false, false, NULL);
-
- if (unlikely(ret != 0)) {
- ret = -ENOMEM;
- goto error_bo_unmap;
- }
-
- ret = ttm_bo_kmap(cm_bo, 0, PFN_UP(size), &vps->cm_map);
-
- /*
- * We just want to try to get mob bind to finish
- * so that the first write to SVGA_REG_CURSOR_MOBID
- * is done with a buffer that the device has already
- * seen
- */
- (void) ttm_bo_wait(cm_bo, false, false);
-
- ttm_bo_unreserve(cm_bo);
-
- if (unlikely(ret != 0)) {
- ret = -ENOMEM;
- goto error_bo_unmap;
- }
-
- vps->cursor_mob_idx = cursor_mob_idx ^ 1;
- vps->cm_bo = cm_bo;
- }
+ vmw_du_get_cursor_mob(vcp, vps);
+ vmw_du_cursor_plane_map_cm(vps);
}
return 0;
-
-error_bo_unmap:
- if (vps->bo != NULL && ttm_kmap_obj_virtual(&vps->bo->map, &dummy) != NULL) {
- const int ret = ttm_bo_reserve(&vps->bo->base, true, false, NULL);
- if (likely(ret == 0)) {
- atomic_dec(&vps->bo->base_mapped_count);
- ttm_bo_kunmap(&vps->bo->map);
- ttm_bo_unreserve(&vps->bo->base);
- }
- }
-
- return ret;
}
@@ -649,7 +783,9 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
struct vmw_private *dev_priv = vmw_priv(crtc->dev);
struct vmw_display_unit *du = vmw_crtc_to_du(crtc);
struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state);
+ struct vmw_plane_state *old_vps = vmw_plane_state_to_vps(old_state);
s32 hotspot_x, hotspot_y;
+ bool dummy;
hotspot_x = du->hotspot_x;
hotspot_y = du->hotspot_y;
@@ -662,23 +798,38 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane,
du->cursor_surface = vps->surf;
du->cursor_bo = vps->bo;
+ if (!vps->surf && !vps->bo) {
+ vmw_cursor_update_position(dev_priv, false, 0, 0);
+ return;
+ }
+
+ vps->cursor.hotspot_x = hotspot_x;
+ vps->cursor.hotspot_y = hotspot_y;
+
if (vps->surf) {
du->cursor_age = du->cursor_surface->snooper.age;
+ }
- vmw_cursor_update_image(dev_priv, vps->cm_bo, &vps->cm_map,
- vps->surf->snooper.image,
- new_state->crtc_w,
- new_state->crtc_h,
- hotspot_x, hotspot_y);
- } else if (vps->bo) {
- vmw_cursor_update_bo(dev_priv, vps->cm_bo, &vps->cm_map,
- vps->bo,
- new_state->crtc_w,
- new_state->crtc_h,
- hotspot_x, hotspot_y);
+ if (!vmw_du_cursor_plane_has_changed(old_vps, vps)) {
+ /*
+ * If it hasn't changed, avoid making the device do extra
+ * work by keeping the old cursor active.
+ */
+ struct vmw_cursor_plane_state tmp = old_vps->cursor;
+ old_vps->cursor = vps->cursor;
+ vps->cursor = tmp;
} else {
- vmw_cursor_update_position(dev_priv, false, 0, 0);
- return;
+ void *image = vmw_du_cursor_plane_acquire_image(vps);
+ if (image)
+ vmw_cursor_update_image(dev_priv, vps, image,
+ new_state->crtc_w,
+ new_state->crtc_h,
+ hotspot_x, hotspot_y);
+ }
+
+ if (vps->bo) {
+ if (ttm_kmap_obj_virtual(&vps->bo->map, &dummy))
+ atomic_dec(&vps->bo->base_mapped_count);
}
du->cursor_x = new_state->crtc_x + du->set_gui_x;
@@ -778,12 +929,16 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane,
return -EINVAL;
}
- if (!vmw_framebuffer_to_vfb(fb)->bo)
+ if (!vmw_framebuffer_to_vfb(fb)->bo) {
surface = vmw_framebuffer_to_vfbs(fb)->surface;
- if (surface && !surface->snooper.image) {
- DRM_ERROR("surface not suitable for cursor\n");
- return -EINVAL;
+ WARN_ON(!surface);
+
+ if (!surface ||
+ (!surface->snooper.image && !surface->res.backup)) {
+ DRM_ERROR("surface not suitable for cursor\n");
+ return -EINVAL;
+ }
}
return 0;
@@ -831,15 +986,6 @@ void vmw_du_crtc_atomic_begin(struct drm_crtc *crtc,
void vmw_du_crtc_atomic_flush(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
- struct drm_pending_vblank_event *event = crtc->state->event;
-
- if (event) {
- crtc->state->event = NULL;
-
- spin_lock_irq(&crtc->dev->event_lock);
- drm_crtc_send_vblank_event(crtc, event);
- spin_unlock_irq(&crtc->dev->event_lock);
- }
}
@@ -943,6 +1089,8 @@ vmw_du_plane_duplicate_state(struct drm_plane *plane)
vps->pinned = 0;
vps->cpp = 0;
+ memset(&vps->cursor, 0, sizeof(vps->cursor));
+
/* Each ref counted resource needs to be acquired again */
if (vps->surf)
(void) vmw_surface_reference(vps->surf);
@@ -997,7 +1145,6 @@ vmw_du_plane_destroy_state(struct drm_plane *plane,
{
struct vmw_plane_state *vps = vmw_plane_state_to_vps(state);
-
/* Should have been freed by cleanup_fb */
if (vps->surf)
vmw_surface_unreference(&vps->surf);
@@ -1664,7 +1811,7 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
if (IS_ERR(vfb)) {
ret = PTR_ERR(vfb);
goto err_out;
- }
+ }
err_out:
/* vmw_user_lookup_handle takes one ref so does new_fb */
@@ -2052,6 +2199,8 @@ int vmw_kms_init(struct vmw_private *dev_priv)
dev->mode_config.min_height = 1;
dev->mode_config.max_width = dev_priv->texture_max_width;
dev->mode_config.max_height = dev_priv->texture_max_height;
+ dev->mode_config.preferred_depth = dev_priv->assume_16bpp ? 16 : 32;
+ dev->mode_config.prefer_shadow_fbdev = !dev_priv->has_mob;
drm_mode_create_suggested_offset_properties(dev);
vmw_kms_create_hotplug_mode_update_property(dev_priv);
@@ -2093,7 +2242,6 @@ int vmw_kms_cursor_bypass_ioctl(struct drm_device *dev, void *data,
struct drm_crtc *crtc;
int ret = 0;
-
mutex_lock(&dev->mode_config.mutex);
if (arg->flags & DRM_VMW_CURSOR_BYPASS_ALL) {
@@ -2155,30 +2303,6 @@ bool vmw_kms_validate_mode_vram(struct vmw_private *dev_priv,
dev_priv->max_primary_mem : dev_priv->vram_size);
}
-
-/*
- * Function called by DRM code called with vbl_lock held.
- */
-u32 vmw_get_vblank_counter(struct drm_crtc *crtc)
-{
- return 0;
-}
-
-/*
- * Function called by DRM code called with vbl_lock held.
- */
-int vmw_enable_vblank(struct drm_crtc *crtc)
-{
- return -EINVAL;
-}
-
-/*
- * Function called by DRM code called with vbl_lock held.
- */
-void vmw_disable_vblank(struct drm_crtc *crtc)
-{
-}
-
/**
* vmw_du_update_layout - Update the display unit with topology from resolution
* plugin and generate DRM uevent
@@ -2207,7 +2331,7 @@ retry:
if (ret == -EDEADLK) {
drm_modeset_backoff(&ctx);
goto retry;
- }
+ }
goto out_fini;
}
}
@@ -2222,8 +2346,8 @@ retry:
du->gui_x = rects[du->unit].x1;
du->gui_y = rects[du->unit].y1;
} else {
- du->pref_width = 800;
- du->pref_height = 600;
+ du->pref_width = VMWGFX_MIN_INITIAL_WIDTH;
+ du->pref_height = VMWGFX_MIN_INITIAL_HEIGHT;
du->pref_active = false;
du->gui_x = 0;
du->gui_y = 0;
@@ -2250,13 +2374,13 @@ retry:
}
con->status = vmw_du_connector_detect(con, true);
}
-
- drm_sysfs_hotplug_event(dev);
out_fini:
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
mutex_unlock(&dev->mode_config.mutex);
+ drm_sysfs_hotplug_event(dev);
+
return 0;
}
@@ -2536,10 +2660,9 @@ int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
int ret, i;
if (!arg->num_outputs) {
- struct drm_rect def_rect = {0, 0, 800, 600};
- VMW_DEBUG_KMS("Default layout x1 = %d y1 = %d x2 = %d y2 = %d\n",
- def_rect.x1, def_rect.y1,
- def_rect.x2, def_rect.y2);
+ struct drm_rect def_rect = {0, 0,
+ VMWGFX_MIN_INITIAL_WIDTH,
+ VMWGFX_MIN_INITIAL_HEIGHT};
vmw_du_update_layout(dev_priv, 1, &def_rect);
return 0;
}
@@ -2834,68 +2957,6 @@ int vmw_kms_update_proxy(struct vmw_resource *res,
return 0;
}
-int vmw_kms_fbdev_init_data(struct vmw_private *dev_priv,
- unsigned unit,
- u32 max_width,
- u32 max_height,
- struct drm_connector **p_con,
- struct drm_crtc **p_crtc,
- struct drm_display_mode **p_mode)
-{
- struct drm_connector *con;
- struct vmw_display_unit *du;
- struct drm_display_mode *mode;
- int i = 0;
- int ret = 0;
-
- mutex_lock(&dev_priv->drm.mode_config.mutex);
- list_for_each_entry(con, &dev_priv->drm.mode_config.connector_list,
- head) {
- if (i == unit)
- break;
-
- ++i;
- }
-
- if (&con->head == &dev_priv->drm.mode_config.connector_list) {
- DRM_ERROR("Could not find initial display unit.\n");
- ret = -EINVAL;
- goto out_unlock;
- }
-
- if (list_empty(&con->modes))
- (void) vmw_du_connector_fill_modes(con, max_width, max_height);
-
- if (list_empty(&con->modes)) {
- DRM_ERROR("Could not find initial display mode.\n");
- ret = -EINVAL;
- goto out_unlock;
- }
-
- du = vmw_connector_to_du(con);
- *p_con = con;
- *p_crtc = &du->crtc;
-
- list_for_each_entry(mode, &con->modes, head) {
- if (mode->type & DRM_MODE_TYPE_PREFERRED)
- break;
- }
-
- if (&mode->head == &con->modes) {
- WARN_ONCE(true, "Could not find initial preferred mode.\n");
- *p_mode = list_first_entry(&con->modes,
- struct drm_display_mode,
- head);
- } else {
- *p_mode = mode;
- }
-
- out_unlock:
- mutex_unlock(&dev_priv->drm.mode_config.mutex);
-
- return ret;
-}
-
/**
* vmw_kms_create_implicit_placement_property - Set up the implicit placement
* property.
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
index 85f86faa3243..4d6e7b555db7 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
@@ -272,6 +272,14 @@ struct vmw_crtc_state {
struct drm_crtc_state base;
};
+struct vmw_cursor_plane_state {
+ struct ttm_buffer_object *bo;
+ struct ttm_bo_kmap_obj map;
+ bool mapped;
+ s32 hotspot_x;
+ s32 hotspot_y;
+};
+
/**
* Derived class for plane state object
*
@@ -295,13 +303,8 @@ struct vmw_plane_state {
/* For CPU Blit */
unsigned int cpp;
- /* CursorMob flipping index; -1 if cursor mobs not used */
- unsigned int cursor_mob_idx;
- /* Currently-active CursorMob */
- struct ttm_buffer_object *cm_bo;
- /* CursorMob kmap_obj; expected valid at cursor_plane_atomic_update
- IFF currently-active CursorMob above is valid */
- struct ttm_bo_kmap_obj cm_map;
+ bool surf_mapped;
+ struct vmw_cursor_plane_state cursor;
};
@@ -338,11 +341,12 @@ struct vmw_connector_state {
* Derived class for cursor plane object
*
* @base DRM plane object
- * @cursor_mob array of two MOBs for CursorMob flipping
+ * @cursor.cursor_mobs Cursor mobs available for re-use
*/
struct vmw_cursor_plane {
struct drm_plane base;
- struct ttm_buffer_object *cursor_mob[2];
+
+ struct ttm_buffer_object *cursor_mobs[3];
};
/**
@@ -458,13 +462,6 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv,
struct vmw_surface *surface,
bool only_2d,
const struct drm_mode_fb_cmd2 *mode_cmd);
-int vmw_kms_fbdev_init_data(struct vmw_private *dev_priv,
- unsigned unit,
- u32 max_width,
- u32 max_height,
- struct drm_connector **p_con,
- struct drm_crtc **p_crtc,
- struct drm_display_mode **p_mode);
void vmw_guess_mode_timing(struct drm_display_mode *mode);
void vmw_kms_update_implicit_fb(struct vmw_private *dev_priv);
void vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv);
@@ -472,8 +469,6 @@ void vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv);
/* Universal Plane Helpers */
void vmw_du_primary_plane_destroy(struct drm_plane *plane);
void vmw_du_cursor_plane_destroy(struct drm_plane *plane);
-int vmw_du_create_cursor_mob_array(struct vmw_cursor_plane *vcp);
-void vmw_du_destroy_cursor_mob_array(struct vmw_cursor_plane *vcp);
/* Atomic Helpers */
int vmw_du_primary_plane_atomic_check(struct drm_plane *plane,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index b8761f16dd78..a56e5d0ca3c6 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -28,7 +28,6 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_fourcc.h>
-#include <drm/drm_vblank.h>
#include "vmwgfx_kms.h"
@@ -235,9 +234,6 @@ static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = {
.atomic_duplicate_state = vmw_du_crtc_duplicate_state,
.atomic_destroy_state = vmw_du_crtc_destroy_state,
.set_config = drm_atomic_helper_set_config,
- .get_vblank_counter = vmw_get_vblank_counter,
- .enable_vblank = vmw_enable_vblank,
- .disable_vblank = vmw_disable_vblank,
};
@@ -507,10 +503,6 @@ int vmw_kms_ldu_init_display(struct vmw_private *dev_priv)
dev_priv->ldu_priv->last_num_active = 0;
dev_priv->ldu_priv->fb = NULL;
- ret = drm_vblank_init(dev, num_display_units);
- if (ret != 0)
- goto err_free;
-
vmw_kms_create_implicit_placement_property(dev_priv);
for (i = 0; i < num_display_units; ++i) {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_mksstat.h b/drivers/gpu/drm/vmwgfx/vmwgfx_mksstat.h
index 0509f55f07b4..ede74c7fdbbf 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_mksstat.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_mksstat.h
@@ -29,6 +29,7 @@
#define _VMWGFX_MKSSTAT_H_
#include <asm/page.h>
+#include <linux/kconfig.h>
/* Reservation marker for mksstat pid's */
#define MKSSTAT_PID_RESERVED -1
@@ -41,6 +42,7 @@
typedef enum {
MKSSTAT_KERN_EXECBUF, /* vmw_execbuf_ioctl */
+ MKSSTAT_KERN_COTABLE_RESIZE,
MKSSTAT_KERN_COUNT /* Reserved entry; always last */
} mksstat_kern_stats_t;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
index 089046fa21be..e76976a95a1e 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_msg.c
@@ -85,7 +85,14 @@ struct rpc_channel {
u32 cookie_low;
};
-
+#if IS_ENABLED(CONFIG_DRM_VMWGFX_MKSSTATS)
+/* Kernel mksGuestStats counter names and desciptions; same order as enum mksstat_kern_stats_t */
+static const char* const mksstat_kern_name_desc[MKSSTAT_KERN_COUNT][2] =
+{
+ { "vmw_execbuf_ioctl", "vmw_execbuf_ioctl" },
+ { "vmw_cotable_resize", "vmw_cotable_resize" },
+};
+#endif
/**
* vmw_open_channel
@@ -695,12 +702,6 @@ static inline void hypervisor_ppn_remove(PPN64 pfn)
/* Header to the text description of mksGuestStat instance descriptor */
#define MKSSTAT_KERNEL_DESCRIPTION "vmwgfx"
-/* Kernel mksGuestStats counter names and desciptions; same order as enum mksstat_kern_stats_t */
-static const char* const mksstat_kern_name_desc[MKSSTAT_KERN_COUNT][2] =
-{
- { "vmw_execbuf_ioctl", "vmw_execbuf_ioctl" },
-};
-
/**
* mksstat_init_record: Initializes an MKSGuestStatCounter-based record
* for the respective mksGuestStat index.
@@ -786,6 +787,7 @@ static int mksstat_init_kern_id(struct page **ppage)
/* Set up all kernel-internal counters and corresponding structures */
pstrs_acc = pstrs;
pstrs_acc = mksstat_init_record_time(MKSSTAT_KERN_EXECBUF, pstat, pinfo, pstrs_acc);
+ pstrs_acc = mksstat_init_record_time(MKSSTAT_KERN_COTABLE_RESIZE, pstat, pinfo, pstrs_acc);
/* Add new counters above, in their order of appearance in mksstat_kern_stats_t */
@@ -1014,8 +1016,6 @@ int vmw_mksstat_add_ioctl(struct drm_device *dev, void *data,
struct vmw_private *const dev_priv = vmw_priv(dev);
- struct page *page;
- MKSGuestStatInstanceDescriptor *pdesc;
const size_t num_pages_stat = PFN_UP(arg->stat_len);
const size_t num_pages_info = PFN_UP(arg->info_len);
const size_t num_pages_strs = PFN_UP(arg->strs_len);
@@ -1023,10 +1023,13 @@ int vmw_mksstat_add_ioctl(struct drm_device *dev, void *data,
long nr_pinned_stat;
long nr_pinned_info;
long nr_pinned_strs;
- struct page *pages_stat[ARRAY_SIZE(pdesc->statPPNs)];
- struct page *pages_info[ARRAY_SIZE(pdesc->infoPPNs)];
- struct page *pages_strs[ARRAY_SIZE(pdesc->strsPPNs)];
+ MKSGuestStatInstanceDescriptor *pdesc;
+ struct page *page = NULL;
+ struct page **pages_stat = NULL;
+ struct page **pages_info = NULL;
+ struct page **pages_strs = NULL;
size_t i, slot;
+ int ret_err = -ENOMEM;
arg->id = -1;
@@ -1054,13 +1057,23 @@ int vmw_mksstat_add_ioctl(struct drm_device *dev, void *data,
BUG_ON(dev_priv->mksstat_user_pages[slot]);
+ /* Allocate statically-sized temp arrays for pages -- too big to keep in frame */
+ pages_stat = (struct page **)kmalloc_array(
+ ARRAY_SIZE(pdesc->statPPNs) +
+ ARRAY_SIZE(pdesc->infoPPNs) +
+ ARRAY_SIZE(pdesc->strsPPNs), sizeof(*pages_stat), GFP_KERNEL);
+
+ if (!pages_stat)
+ goto err_nomem;
+
+ pages_info = pages_stat + ARRAY_SIZE(pdesc->statPPNs);
+ pages_strs = pages_info + ARRAY_SIZE(pdesc->infoPPNs);
+
/* Allocate a page for the instance descriptor */
page = alloc_page(GFP_KERNEL | __GFP_ZERO);
- if (!page) {
- atomic_set(&dev_priv->mksstat_user_pids[slot], 0);
- return -ENOMEM;
- }
+ if (!page)
+ goto err_nomem;
/* Set up the instance descriptor */
pdesc = page_address(page);
@@ -1075,9 +1088,8 @@ int vmw_mksstat_add_ioctl(struct drm_device *dev, void *data,
ARRAY_SIZE(pdesc->description) - 1);
if (desc_len < 0) {
- atomic_set(&dev_priv->mksstat_user_pids[slot], 0);
- __free_page(page);
- return -EFAULT;
+ ret_err = -EFAULT;
+ goto err_nomem;
}
reset_ppn_array(pdesc->statPPNs, ARRAY_SIZE(pdesc->statPPNs));
@@ -1085,21 +1097,21 @@ int vmw_mksstat_add_ioctl(struct drm_device *dev, void *data,
reset_ppn_array(pdesc->strsPPNs, ARRAY_SIZE(pdesc->strsPPNs));
/* Pin mksGuestStat user pages and store those in the instance descriptor */
- nr_pinned_stat = pin_user_pages(arg->stat, num_pages_stat, FOLL_LONGTERM, pages_stat, NULL);
+ nr_pinned_stat = pin_user_pages_fast(arg->stat, num_pages_stat, FOLL_LONGTERM, pages_stat);
if (num_pages_stat != nr_pinned_stat)
goto err_pin_stat;
for (i = 0; i < num_pages_stat; ++i)
pdesc->statPPNs[i] = page_to_pfn(pages_stat[i]);
- nr_pinned_info = pin_user_pages(arg->info, num_pages_info, FOLL_LONGTERM, pages_info, NULL);
+ nr_pinned_info = pin_user_pages_fast(arg->info, num_pages_info, FOLL_LONGTERM, pages_info);
if (num_pages_info != nr_pinned_info)
goto err_pin_info;
for (i = 0; i < num_pages_info; ++i)
pdesc->infoPPNs[i] = page_to_pfn(pages_info[i]);
- nr_pinned_strs = pin_user_pages(arg->strs, num_pages_strs, FOLL_LONGTERM, pages_strs, NULL);
+ nr_pinned_strs = pin_user_pages_fast(arg->strs, num_pages_strs, FOLL_LONGTERM, pages_strs);
if (num_pages_strs != nr_pinned_strs)
goto err_pin_strs;
@@ -1118,6 +1130,7 @@ int vmw_mksstat_add_ioctl(struct drm_device *dev, void *data,
DRM_DEV_INFO(dev->dev, "pid=%d arg.description='%.*s' id=%zu\n", current->pid, (int)desc_len, pdesc->description, slot);
+ kfree(pages_stat);
return 0;
err_pin_strs:
@@ -1132,9 +1145,13 @@ err_pin_stat:
if (nr_pinned_stat > 0)
unpin_user_pages(pages_stat, nr_pinned_stat);
+err_nomem:
atomic_set(&dev_priv->mksstat_user_pids[slot], 0);
- __free_page(page);
- return -ENOMEM;
+ if (page)
+ __free_page(page);
+ kfree(pages_stat);
+
+ return ret_err;
}
/**
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c b/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c
index 7bc99b1279f7..f41f041559f4 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c
@@ -230,7 +230,7 @@ void vmw_bo_dirty_unmap(struct vmw_buffer_object *vbo,
int vmw_bo_dirty_add(struct vmw_buffer_object *vbo)
{
struct vmw_bo_dirty *dirty = vbo->dirty;
- pgoff_t num_pages = vbo->base.resource->num_pages;
+ pgoff_t num_pages = PFN_UP(vbo->base.resource->size);
size_t size;
int ret;
@@ -395,7 +395,7 @@ vm_fault_t vmw_bo_vm_mkwrite(struct vm_fault *vmf)
return ret;
page_offset = vmf->pgoff - drm_vma_node_start(&bo->base.vma_node);
- if (unlikely(page_offset >= bo->resource->num_pages)) {
+ if (unlikely(page_offset >= PFN_UP(bo->resource->size))) {
ret = VM_FAULT_SIGBUS;
goto out_unlock;
}
@@ -438,7 +438,7 @@ vm_fault_t vmw_bo_vm_fault(struct vm_fault *vmf)
page_offset = vmf->pgoff -
drm_vma_node_start(&bo->base.vma_node);
- if (page_offset >= bo->resource->num_pages ||
+ if (page_offset >= PFN_UP(bo->resource->size) ||
vmw_resources_clean(vbo, page_offset,
page_offset + PAGE_SIZE,
&allowed_prefault)) {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
index ecd3c2fc978b..e1f36a09c59c 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
@@ -29,7 +29,6 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_fourcc.h>
-#include <drm/drm_vblank.h>
#include "vmwgfx_kms.h"
@@ -320,9 +319,6 @@ static const struct drm_crtc_funcs vmw_screen_object_crtc_funcs = {
.atomic_destroy_state = vmw_du_crtc_destroy_state,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
- .get_vblank_counter = vmw_get_vblank_counter,
- .enable_vblank = vmw_enable_vblank,
- .disable_vblank = vmw_disable_vblank,
};
/*
@@ -730,7 +726,6 @@ vmw_sou_primary_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane);
struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane);
struct drm_crtc *crtc = new_state->crtc;
- struct drm_pending_vblank_event *event = NULL;
struct vmw_fence_obj *fence = NULL;
int ret;
@@ -754,24 +749,6 @@ vmw_sou_primary_plane_atomic_update(struct drm_plane *plane,
return;
}
- /* For error case vblank event is send from vmw_du_crtc_atomic_flush */
- event = crtc->state->event;
- if (event && fence) {
- struct drm_file *file_priv = event->base.file_priv;
-
- ret = vmw_event_fence_action_queue(file_priv,
- fence,
- &event->base,
- &event->event.vbl.tv_sec,
- &event->event.vbl.tv_usec,
- true);
-
- if (unlikely(ret != 0))
- DRM_ERROR("Failed to queue event on fence.\n");
- else
- crtc->state->event = NULL;
- }
-
if (fence)
vmw_fence_obj_unreference(&fence);
}
@@ -947,18 +924,16 @@ err_free:
int vmw_kms_sou_init_display(struct vmw_private *dev_priv)
{
struct drm_device *dev = &dev_priv->drm;
- int i, ret;
+ int i;
+
+ /* Screen objects won't work if GMR's aren't available */
+ if (!dev_priv->has_gmr)
+ return -ENOSYS;
if (!(dev_priv->capabilities & SVGA_CAP_SCREEN_OBJECT_2)) {
return -ENOSYS;
}
- ret = -ENOMEM;
-
- ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS);
- if (unlikely(ret != 0))
- return ret;
-
for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i)
vmw_sou_init(dev_priv, i);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
index 8650c3aea8f0..0090abe89254 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
@@ -29,7 +29,6 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_damage_helper.h>
#include <drm/drm_fourcc.h>
-#include <drm/drm_vblank.h>
#include "vmwgfx_kms.h"
#include "vmw_surface_cache.h"
@@ -925,9 +924,6 @@ static const struct drm_crtc_funcs vmw_stdu_crtc_funcs = {
.atomic_destroy_state = vmw_du_crtc_destroy_state,
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
- .get_vblank_counter = vmw_get_vblank_counter,
- .enable_vblank = vmw_enable_vblank,
- .disable_vblank = vmw_disable_vblank,
};
@@ -1591,7 +1587,6 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state);
struct drm_crtc *crtc = new_state->crtc;
struct vmw_screen_target_display_unit *stdu;
- struct drm_pending_vblank_event *event;
struct vmw_fence_obj *fence = NULL;
struct vmw_private *dev_priv;
int ret;
@@ -1640,23 +1635,6 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane,
return;
}
- /* In case of error, vblank event is send in vmw_du_crtc_atomic_flush */
- event = crtc->state->event;
- if (event && fence) {
- struct drm_file *file_priv = event->base.file_priv;
-
- ret = vmw_event_fence_action_queue(file_priv,
- fence,
- &event->base,
- &event->event.vbl.tv_sec,
- &event->event.vbl.tv_usec,
- true);
- if (ret)
- DRM_ERROR("Failed to queue event on fence.\n");
- else
- crtc->state->event = NULL;
- }
-
if (fence)
vmw_fence_obj_unreference(&fence);
}
@@ -1883,10 +1861,6 @@ int vmw_kms_stdu_init_display(struct vmw_private *dev_priv)
if (!(dev_priv->capabilities & SVGA_CAP_GBOBJECTS))
return -ENOSYS;
- ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS);
- if (unlikely(ret != 0))
- return ret;
-
dev_priv->active_display_unit = vmw_du_screen_target;
for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) {
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
index ace7ca150b03..3bc63ae768f3 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -815,11 +815,15 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
res->backup_size = cur_bo_offset;
if (metadata->scanout &&
metadata->num_sizes == 1 &&
- metadata->sizes[0].width == 64 &&
- metadata->sizes[0].height == 64 &&
- metadata->format == SVGA3D_A8R8G8B8) {
-
- srf->snooper.image = kzalloc(64 * 64 * 4, GFP_KERNEL);
+ metadata->sizes[0].width == VMW_CURSOR_SNOOP_WIDTH &&
+ metadata->sizes[0].height == VMW_CURSOR_SNOOP_HEIGHT &&
+ metadata->format == VMW_CURSOR_SNOOP_FORMAT) {
+ const struct SVGA3dSurfaceDesc *desc =
+ vmw_surface_get_desc(VMW_CURSOR_SNOOP_FORMAT);
+ const u32 cursor_size_bytes = VMW_CURSOR_SNOOP_WIDTH *
+ VMW_CURSOR_SNOOP_HEIGHT *
+ desc->pitchBytesPerBlock;
+ srf->snooper.image = kzalloc(cursor_size_bytes, GFP_KERNEL);
if (!srf->snooper.image) {
DRM_ERROR("Failed to allocate cursor_image\n");
ret = -ENOMEM;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c
index f46891012be3..f5c4a40fb16d 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0 OR MIT
/**************************************************************************
*
- * Copyright © 2018 VMware, Inc., Palo Alto, CA., USA
+ * Copyright © 2018 - 2022 VMware, Inc., Palo Alto, CA., USA
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -180,11 +180,16 @@ vmw_validation_find_bo_dup(struct vmw_validation_context *ctx,
if (!ctx->merge_dups)
return NULL;
- if (ctx->ht) {
+ if (ctx->sw_context) {
struct vmwgfx_hash_item *hash;
+ unsigned long key = (unsigned long) vbo;
- if (!vmwgfx_ht_find_item(ctx->ht, (unsigned long) vbo, &hash))
- bo_node = container_of(hash, typeof(*bo_node), hash);
+ hash_for_each_possible_rcu(ctx->sw_context->res_ht, hash, head, key) {
+ if (hash->key == key) {
+ bo_node = container_of(hash, typeof(*bo_node), hash);
+ break;
+ }
+ }
} else {
struct vmw_validation_bo_node *entry;
@@ -217,11 +222,16 @@ vmw_validation_find_res_dup(struct vmw_validation_context *ctx,
if (!ctx->merge_dups)
return NULL;
- if (ctx->ht) {
+ if (ctx->sw_context) {
struct vmwgfx_hash_item *hash;
+ unsigned long key = (unsigned long) res;
- if (!vmwgfx_ht_find_item(ctx->ht, (unsigned long) res, &hash))
- res_node = container_of(hash, typeof(*res_node), hash);
+ hash_for_each_possible_rcu(ctx->sw_context->res_ht, hash, head, key) {
+ if (hash->key == key) {
+ res_node = container_of(hash, typeof(*res_node), hash);
+ break;
+ }
+ }
} else {
struct vmw_validation_res_node *entry;
@@ -269,20 +279,15 @@ int vmw_validation_add_bo(struct vmw_validation_context *ctx,
}
} else {
struct ttm_validate_buffer *val_buf;
- int ret;
bo_node = vmw_validation_mem_alloc(ctx, sizeof(*bo_node));
if (!bo_node)
return -ENOMEM;
- if (ctx->ht) {
+ if (ctx->sw_context) {
bo_node->hash.key = (unsigned long) vbo;
- ret = vmwgfx_ht_insert_item(ctx->ht, &bo_node->hash);
- if (ret) {
- DRM_ERROR("Failed to initialize a buffer "
- "validation entry.\n");
- return ret;
- }
+ hash_add_rcu(ctx->sw_context->res_ht, &bo_node->hash.head,
+ bo_node->hash.key);
}
val_buf = &bo_node->base;
val_buf->bo = ttm_bo_get_unless_zero(&vbo->base);
@@ -316,7 +321,6 @@ int vmw_validation_add_resource(struct vmw_validation_context *ctx,
bool *first_usage)
{
struct vmw_validation_res_node *node;
- int ret;
node = vmw_validation_find_res_dup(ctx, res);
if (node) {
@@ -330,14 +334,9 @@ int vmw_validation_add_resource(struct vmw_validation_context *ctx,
return -ENOMEM;
}
- if (ctx->ht) {
+ if (ctx->sw_context) {
node->hash.key = (unsigned long) res;
- ret = vmwgfx_ht_insert_item(ctx->ht, &node->hash);
- if (ret) {
- DRM_ERROR("Failed to initialize a resource validation "
- "entry.\n");
- return ret;
- }
+ hash_add_rcu(ctx->sw_context->res_ht, &node->hash.head, node->hash.key);
}
node->res = vmw_resource_reference_unless_doomed(res);
if (!node->res)
@@ -681,19 +680,19 @@ void vmw_validation_drop_ht(struct vmw_validation_context *ctx)
struct vmw_validation_bo_node *entry;
struct vmw_validation_res_node *val;
- if (!ctx->ht)
+ if (!ctx->sw_context)
return;
list_for_each_entry(entry, &ctx->bo_list, base.head)
- (void) vmwgfx_ht_remove_item(ctx->ht, &entry->hash);
+ hash_del_rcu(&entry->hash.head);
list_for_each_entry(val, &ctx->resource_list, head)
- (void) vmwgfx_ht_remove_item(ctx->ht, &val->hash);
+ hash_del_rcu(&val->hash.head);
list_for_each_entry(val, &ctx->resource_ctx_list, head)
- (void) vmwgfx_ht_remove_item(ctx->ht, &val->hash);
+ hash_del_rcu(&entry->hash.head);
- ctx->ht = NULL;
+ ctx->sw_context = NULL;
}
/**
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h
index f21df053882b..ab9ec226f433 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h
@@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR MIT */
/**************************************************************************
*
- * Copyright © 2018 VMware, Inc., Palo Alto, CA., USA
+ * Copyright © 2018 - 2022 VMware, Inc., Palo Alto, CA., USA
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -29,12 +29,11 @@
#define _VMWGFX_VALIDATION_H_
#include <linux/list.h>
+#include <linux/hashtable.h>
#include <linux/ww_mutex.h>
#include <drm/ttm/ttm_execbuf_util.h>
-#include "vmwgfx_hashtab.h"
-
#define VMW_RES_DIRTY_NONE 0
#define VMW_RES_DIRTY_SET BIT(0)
#define VMW_RES_DIRTY_CLEAR BIT(1)
@@ -59,7 +58,7 @@
* @total_mem: Amount of reserved memory.
*/
struct vmw_validation_context {
- struct vmwgfx_open_hash *ht;
+ struct vmw_sw_context *sw_context;
struct list_head resource_list;
struct list_head resource_ctx_list;
struct list_head bo_list;
@@ -82,16 +81,16 @@ struct vmw_fence_obj;
/**
* DECLARE_VAL_CONTEXT - Declare a validation context with initialization
* @_name: The name of the variable
- * @_ht: The hash table used to find dups or NULL if none
+ * @_sw_context: Contains the hash table used to find dups or NULL if none
* @_merge_dups: Whether to merge duplicate buffer object- or resource
* entries. If set to true, ideally a hash table pointer should be supplied
* as well unless the number of resources and buffer objects per validation
* is known to be very small
*/
#endif
-#define DECLARE_VAL_CONTEXT(_name, _ht, _merge_dups) \
+#define DECLARE_VAL_CONTEXT(_name, _sw_context, _merge_dups) \
struct vmw_validation_context _name = \
- { .ht = _ht, \
+ { .sw_context = _sw_context, \
.resource_list = LIST_HEAD_INIT((_name).resource_list), \
.resource_ctx_list = LIST_HEAD_INIT((_name).resource_ctx_list), \
.bo_list = LIST_HEAD_INIT((_name).bo_list), \
@@ -115,19 +114,6 @@ vmw_validation_has_bos(struct vmw_validation_context *ctx)
}
/**
- * vmw_validation_set_ht - Register a hash table for duplicate finding
- * @ctx: The validation context
- * @ht: Pointer to a hash table to use for duplicate finding
- * This function is intended to be used if the hash table wasn't
- * available at validation context declaration time
- */
-static inline void vmw_validation_set_ht(struct vmw_validation_context *ctx,
- struct vmwgfx_open_hash *ht)
-{
- ctx->ht = ht;
-}
-
-/**
* vmw_validation_bo_reserve - Reserve buffer objects registered with a
* validation context
* @ctx: The validation context
diff --git a/drivers/gpu/drm/xen/xen_drm_front_gem.c b/drivers/gpu/drm/xen/xen_drm_front_gem.c
index e31554d7139f..4c95ebcdcc2d 100644
--- a/drivers/gpu/drm/xen/xen_drm_front_gem.c
+++ b/drivers/gpu/drm/xen/xen_drm_front_gem.c
@@ -12,7 +12,6 @@
#include <linux/scatterlist.h>
#include <linux/shmem_fs.h>
-#include <drm/drm_fb_helper.h>
#include <drm/drm_gem.h>
#include <drm/drm_prime.h>
#include <drm/drm_probe_helper.h>
diff --git a/drivers/gpu/drm/xlnx/Makefile b/drivers/gpu/drm/xlnx/Makefile
index 51c24b72217b..ea1422a39502 100644
--- a/drivers/gpu/drm/xlnx/Makefile
+++ b/drivers/gpu/drm/xlnx/Makefile
@@ -1,2 +1,2 @@
-zynqmp-dpsub-y := zynqmp_disp.o zynqmp_dpsub.o zynqmp_dp.o
+zynqmp-dpsub-y := zynqmp_disp.o zynqmp_dpsub.o zynqmp_dp.o zynqmp_kms.o
obj-$(CONFIG_DRM_ZYNQMP_DPSUB) += zynqmp-dpsub.o
diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.c b/drivers/gpu/drm/xlnx/zynqmp_disp.c
index bbb365f2d087..3b87eebddc97 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_disp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_disp.c
@@ -9,29 +9,19 @@
* - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
*/
-#include <drm/drm_atomic.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_atomic_uapi.h>
-#include <drm/drm_blend.h>
-#include <drm/drm_crtc.h>
-#include <drm/drm_device.h>
#include <drm/drm_fb_dma_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
-#include <drm/drm_managed.h>
#include <drm/drm_plane.h>
-#include <drm/drm_vblank.h>
#include <linux/clk.h>
-#include <linux/delay.h>
#include <linux/dma/xilinx_dpdma.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/pm_runtime.h>
-#include <linux/spinlock.h>
+#include <linux/slab.h>
#include "zynqmp_disp.h"
#include "zynqmp_disp_regs.h"
@@ -72,46 +62,23 @@
#define ZYNQMP_DISP_AV_BUF_NUM_VID_GFX_BUFFERS 4
#define ZYNQMP_DISP_AV_BUF_NUM_BUFFERS 6
-#define ZYNQMP_DISP_NUM_LAYERS 2
#define ZYNQMP_DISP_MAX_NUM_SUB_PLANES 3
/**
* struct zynqmp_disp_format - Display subsystem format information
* @drm_fmt: DRM format (4CC)
* @buf_fmt: AV buffer format
- * @bus_fmt: Media bus formats (live formats)
* @swap: Flag to swap R & B for RGB formats, and U & V for YUV formats
* @sf: Scaling factors for color components
*/
struct zynqmp_disp_format {
u32 drm_fmt;
u32 buf_fmt;
- u32 bus_fmt;
bool swap;
const u32 *sf;
};
/**
- * enum zynqmp_disp_layer_id - Layer identifier
- * @ZYNQMP_DISP_LAYER_VID: Video layer
- * @ZYNQMP_DISP_LAYER_GFX: Graphics layer
- */
-enum zynqmp_disp_layer_id {
- ZYNQMP_DISP_LAYER_VID,
- ZYNQMP_DISP_LAYER_GFX
-};
-
-/**
- * enum zynqmp_disp_layer_mode - Layer mode
- * @ZYNQMP_DISP_LAYER_NONLIVE: non-live (memory) mode
- * @ZYNQMP_DISP_LAYER_LIVE: live (stream) mode
- */
-enum zynqmp_disp_layer_mode {
- ZYNQMP_DISP_LAYER_NONLIVE,
- ZYNQMP_DISP_LAYER_LIVE
-};
-
-/**
* struct zynqmp_disp_layer_dma - DMA channel for one data plane of a layer
* @chan: DMA channel
* @xt: Interleaved DMA descriptor template
@@ -136,8 +103,7 @@ struct zynqmp_disp_layer_info {
};
/**
- * struct zynqmp_disp_layer - Display layer (DRM plane)
- * @plane: DRM plane
+ * struct zynqmp_disp_layer - Display layer
* @id: Layer ID
* @disp: Back pointer to struct zynqmp_disp
* @info: Static layer information
@@ -147,8 +113,7 @@ struct zynqmp_disp_layer_info {
* @mode: Current operation mode
*/
struct zynqmp_disp_layer {
- struct drm_plane plane;
- enum zynqmp_disp_layer_id id;
+ enum zynqmp_dpsub_layer_id id;
struct zynqmp_disp *disp;
const struct zynqmp_disp_layer_info *info;
@@ -156,32 +121,22 @@ struct zynqmp_disp_layer {
const struct zynqmp_disp_format *disp_fmt;
const struct drm_format_info *drm_fmt;
- enum zynqmp_disp_layer_mode mode;
+ enum zynqmp_dpsub_layer_mode mode;
};
/**
* struct zynqmp_disp - Display controller
* @dev: Device structure
- * @drm: DRM core
* @dpsub: Display subsystem
- * @crtc: DRM CRTC
* @blend.base: Register I/O base address for the blender
* @avbuf.base: Register I/O base address for the audio/video buffer manager
* @audio.base: Registers I/O base address for the audio mixer
- * @audio.clk: Audio clock
- * @audio.clk_from_ps: True of the audio clock comes from PS, false from PL
* @layers: Layers (planes)
- * @event: Pending vblank event request
- * @pclk: Pixel clock
- * @pclk_from_ps: True of the video clock comes from PS, false from PL
*/
struct zynqmp_disp {
struct device *dev;
- struct drm_device *drm;
struct zynqmp_dpsub *dpsub;
- struct drm_crtc crtc;
-
struct {
void __iomem *base;
} blend;
@@ -190,16 +145,9 @@ struct zynqmp_disp {
} avbuf;
struct {
void __iomem *base;
- struct clk *clk;
- bool clk_from_ps;
} audio;
- struct zynqmp_disp_layer layers[ZYNQMP_DISP_NUM_LAYERS];
-
- struct drm_pending_vblank_event *event;
-
- struct clk *pclk;
- bool pclk_from_ps;
+ struct zynqmp_disp_layer layers[ZYNQMP_DPSUB_NUM_LAYERS];
};
/* -----------------------------------------------------------------------------
@@ -416,14 +364,9 @@ static void zynqmp_disp_avbuf_write(struct zynqmp_disp *disp, int reg, u32 val)
writel(val, disp->avbuf.base + reg);
}
-static bool zynqmp_disp_layer_is_gfx(const struct zynqmp_disp_layer *layer)
-{
- return layer->id == ZYNQMP_DISP_LAYER_GFX;
-}
-
static bool zynqmp_disp_layer_is_video(const struct zynqmp_disp_layer *layer)
{
- return layer->id == ZYNQMP_DISP_LAYER_VID;
+ return layer->id == ZYNQMP_DPSUB_LAYER_VID;
}
/**
@@ -566,27 +509,25 @@ static void zynqmp_disp_avbuf_disable_audio(struct zynqmp_disp *disp)
* zynqmp_disp_avbuf_enable_video - Enable a video layer
* @disp: Display controller
* @layer: The layer
- * @mode: Operating mode of layer
*
* Enable the video/graphics buffer for @layer.
*/
static void zynqmp_disp_avbuf_enable_video(struct zynqmp_disp *disp,
- struct zynqmp_disp_layer *layer,
- enum zynqmp_disp_layer_mode mode)
+ struct zynqmp_disp_layer *layer)
{
u32 val;
val = zynqmp_disp_avbuf_read(disp, ZYNQMP_DISP_AV_BUF_OUTPUT);
if (zynqmp_disp_layer_is_video(layer)) {
val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MASK;
- if (mode == ZYNQMP_DISP_LAYER_NONLIVE)
+ if (layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE)
val |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_MEM;
else
val |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID1_LIVE;
} else {
val &= ~ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MASK;
val |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MEM;
- if (mode == ZYNQMP_DISP_LAYER_NONLIVE)
+ if (layer->mode == ZYNQMP_DPSUB_LAYER_NONLIVE)
val |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_MEM;
else
val |= ZYNQMP_DISP_AV_BUF_OUTPUT_VID2_LIVE;
@@ -758,8 +699,8 @@ static void zynqmp_disp_blend_set_bg_color(struct zynqmp_disp *disp,
* @enable: True to enable global alpha blending
* @alpha: Global alpha value (ignored if @enabled is false)
*/
-static void zynqmp_disp_blend_set_global_alpha(struct zynqmp_disp *disp,
- bool enable, u32 alpha)
+void zynqmp_disp_blend_set_global_alpha(struct zynqmp_disp *disp,
+ bool enable, u32 alpha)
{
zynqmp_disp_blend_write(disp, ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA,
ZYNQMP_DISP_V_BLEND_SET_GLOBAL_ALPHA_VALUE(alpha) |
@@ -902,80 +843,6 @@ static void zynqmp_disp_audio_disable(struct zynqmp_disp *disp)
ZYNQMP_DISP_AUD_SOFT_RESET_AUD_SRST);
}
-static void zynqmp_disp_audio_init(struct zynqmp_disp *disp)
-{
- /* Try the live PL audio clock. */
- disp->audio.clk = devm_clk_get(disp->dev, "dp_live_audio_aclk");
- if (!IS_ERR(disp->audio.clk)) {
- disp->audio.clk_from_ps = false;
- return;
- }
-
- /* If the live PL audio clock is not valid, fall back to PS clock. */
- disp->audio.clk = devm_clk_get(disp->dev, "dp_aud_clk");
- if (!IS_ERR(disp->audio.clk)) {
- disp->audio.clk_from_ps = true;
- return;
- }
-
- dev_err(disp->dev, "audio disabled due to missing clock\n");
-}
-
-/* -----------------------------------------------------------------------------
- * ZynqMP Display external functions for zynqmp_dp
- */
-
-/**
- * zynqmp_disp_handle_vblank - Handle the vblank event
- * @disp: Display controller
- *
- * This function handles the vblank interrupt, and sends an event to
- * CRTC object. This will be called by the DP vblank interrupt handler.
- */
-void zynqmp_disp_handle_vblank(struct zynqmp_disp *disp)
-{
- struct drm_crtc *crtc = &disp->crtc;
-
- drm_crtc_handle_vblank(crtc);
-}
-
-/**
- * zynqmp_disp_audio_enabled - If the audio is enabled
- * @disp: Display controller
- *
- * Return if the audio is enabled depending on the audio clock.
- *
- * Return: true if audio is enabled, or false.
- */
-bool zynqmp_disp_audio_enabled(struct zynqmp_disp *disp)
-{
- return !!disp->audio.clk;
-}
-
-/**
- * zynqmp_disp_get_audio_clk_rate - Get the current audio clock rate
- * @disp: Display controller
- *
- * Return: the current audio clock rate.
- */
-unsigned int zynqmp_disp_get_audio_clk_rate(struct zynqmp_disp *disp)
-{
- if (zynqmp_disp_audio_enabled(disp))
- return 0;
- return clk_get_rate(disp->audio.clk);
-}
-
-/**
- * zynqmp_disp_get_crtc_mask - Return the CRTC bit mask
- * @disp: Display controller
- *
- * Return: the crtc mask of the zyqnmp_disp CRTC.
- */
-uint32_t zynqmp_disp_get_crtc_mask(struct zynqmp_disp *disp)
-{
- return drm_crtc_mask(&disp->crtc);
-}
-
/* -----------------------------------------------------------------------------
* ZynqMP Display Layer & DRM Plane
*/
@@ -1006,19 +873,46 @@ zynqmp_disp_layer_find_format(struct zynqmp_disp_layer *layer,
}
/**
+ * zynqmp_disp_layer_drm_formats - Return the DRM formats supported by the layer
+ * @layer: The layer
+ * @num_formats: Pointer to the returned number of formats
+ *
+ * Return: A newly allocated u32 array that stores all the DRM formats
+ * supported by the layer. The number of formats in the array is returned
+ * through the num_formats argument.
+ */
+u32 *zynqmp_disp_layer_drm_formats(struct zynqmp_disp_layer *layer,
+ unsigned int *num_formats)
+{
+ unsigned int i;
+ u32 *formats;
+
+ formats = kcalloc(layer->info->num_formats, sizeof(*formats),
+ GFP_KERNEL);
+ if (!formats)
+ return NULL;
+
+ for (i = 0; i < layer->info->num_formats; ++i)
+ formats[i] = layer->info->formats[i].drm_fmt;
+
+ *num_formats = layer->info->num_formats;
+ return formats;
+}
+
+/**
* zynqmp_disp_layer_enable - Enable a layer
* @layer: The layer
+ * @mode: Operating mode of layer
*
* Enable the @layer in the audio/video buffer manager and the blender. DMA
* channels are started separately by zynqmp_disp_layer_update().
*/
-static void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer)
+void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer,
+ enum zynqmp_dpsub_layer_mode mode)
{
- zynqmp_disp_avbuf_enable_video(layer->disp, layer,
- ZYNQMP_DISP_LAYER_NONLIVE);
+ layer->mode = mode;
+ zynqmp_disp_avbuf_enable_video(layer->disp, layer);
zynqmp_disp_blend_layer_enable(layer->disp, layer);
-
- layer->mode = ZYNQMP_DISP_LAYER_NONLIVE;
}
/**
@@ -1028,12 +922,14 @@ static void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer)
* Disable the layer by stopping its DMA channels and disabling it in the
* audio/video buffer manager and the blender.
*/
-static void zynqmp_disp_layer_disable(struct zynqmp_disp_layer *layer)
+void zynqmp_disp_layer_disable(struct zynqmp_disp_layer *layer)
{
unsigned int i;
- for (i = 0; i < layer->drm_fmt->num_planes; i++)
- dmaengine_terminate_sync(layer->dmas[i].chan);
+ if (layer->disp->dpsub->dma_enabled) {
+ for (i = 0; i < layer->drm_fmt->num_planes; i++)
+ dmaengine_terminate_sync(layer->dmas[i].chan);
+ }
zynqmp_disp_avbuf_disable_video(layer->disp, layer);
zynqmp_disp_blend_layer_disable(layer->disp, layer);
@@ -1042,15 +938,13 @@ static void zynqmp_disp_layer_disable(struct zynqmp_disp_layer *layer)
/**
* zynqmp_disp_layer_set_format - Set the layer format
* @layer: The layer
- * @state: The plane state
+ * @info: The format info
*
- * Set the format for @layer based on @state->fb->format. The layer must be
- * disabled.
+ * Set the format for @layer to @info. The layer must be disabled.
*/
-static void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
- struct drm_plane_state *state)
+void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
+ const struct drm_format_info *info)
{
- const struct drm_format_info *info = state->fb->format;
unsigned int i;
layer->disp_fmt = zynqmp_disp_layer_find_format(layer, info->format);
@@ -1058,6 +952,9 @@ static void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
zynqmp_disp_avbuf_set_format(layer->disp, layer, layer->disp_fmt);
+ if (!layer->disp->dpsub->dma_enabled)
+ return;
+
/*
* Set pconfig for each DMA channel to indicate they're part of a
* video group.
@@ -1087,13 +984,16 @@ static void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
*
* Return: 0 on success, or the DMA descriptor failure error otherwise
*/
-static int zynqmp_disp_layer_update(struct zynqmp_disp_layer *layer,
- struct drm_plane_state *state)
+int zynqmp_disp_layer_update(struct zynqmp_disp_layer *layer,
+ struct drm_plane_state *state)
{
const struct drm_format_info *info = layer->drm_fmt;
unsigned int i;
- for (i = 0; i < layer->drm_fmt->num_planes; i++) {
+ if (!layer->disp->dpsub->dma_enabled)
+ return 0;
+
+ for (i = 0; i < info->num_planes; i++) {
unsigned int width = state->crtc_w / (i ? info->hsub : 1);
unsigned int height = state->crtc_h / (i ? info->vsub : 1);
struct zynqmp_disp_layer_dma *dma = &layer->dmas[i];
@@ -1128,143 +1028,6 @@ static int zynqmp_disp_layer_update(struct zynqmp_disp_layer *layer,
return 0;
}
-static inline struct zynqmp_disp_layer *plane_to_layer(struct drm_plane *plane)
-{
- return container_of(plane, struct zynqmp_disp_layer, plane);
-}
-
-static int
-zynqmp_disp_plane_atomic_check(struct drm_plane *plane,
- struct drm_atomic_state *state)
-{
- struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
- plane);
- struct drm_crtc_state *crtc_state;
-
- if (!new_plane_state->crtc)
- return 0;
-
- crtc_state = drm_atomic_get_crtc_state(state, new_plane_state->crtc);
- if (IS_ERR(crtc_state))
- return PTR_ERR(crtc_state);
-
- return drm_atomic_helper_check_plane_state(new_plane_state,
- crtc_state,
- DRM_PLANE_NO_SCALING,
- DRM_PLANE_NO_SCALING,
- false, false);
-}
-
-static void
-zynqmp_disp_plane_atomic_disable(struct drm_plane *plane,
- struct drm_atomic_state *state)
-{
- struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
- plane);
- struct zynqmp_disp_layer *layer = plane_to_layer(plane);
-
- if (!old_state->fb)
- return;
-
- zynqmp_disp_layer_disable(layer);
-
- if (zynqmp_disp_layer_is_gfx(layer))
- zynqmp_disp_blend_set_global_alpha(layer->disp, false,
- plane->state->alpha >> 8);
-}
-
-static void
-zynqmp_disp_plane_atomic_update(struct drm_plane *plane,
- struct drm_atomic_state *state)
-{
- struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane);
- struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane);
- struct zynqmp_disp_layer *layer = plane_to_layer(plane);
- bool format_changed = false;
-
- if (!old_state->fb ||
- old_state->fb->format->format != new_state->fb->format->format)
- format_changed = true;
-
- /*
- * If the format has changed (including going from a previously
- * disabled state to any format), reconfigure the format. Disable the
- * plane first if needed.
- */
- if (format_changed) {
- if (old_state->fb)
- zynqmp_disp_layer_disable(layer);
-
- zynqmp_disp_layer_set_format(layer, new_state);
- }
-
- zynqmp_disp_layer_update(layer, new_state);
-
- if (zynqmp_disp_layer_is_gfx(layer))
- zynqmp_disp_blend_set_global_alpha(layer->disp, true,
- plane->state->alpha >> 8);
-
- /* Enable or re-enable the plane is the format has changed. */
- if (format_changed)
- zynqmp_disp_layer_enable(layer);
-}
-
-static const struct drm_plane_helper_funcs zynqmp_disp_plane_helper_funcs = {
- .atomic_check = zynqmp_disp_plane_atomic_check,
- .atomic_update = zynqmp_disp_plane_atomic_update,
- .atomic_disable = zynqmp_disp_plane_atomic_disable,
-};
-
-static const struct drm_plane_funcs zynqmp_disp_plane_funcs = {
- .update_plane = drm_atomic_helper_update_plane,
- .disable_plane = drm_atomic_helper_disable_plane,
- .destroy = drm_plane_cleanup,
- .reset = drm_atomic_helper_plane_reset,
- .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
-};
-
-static int zynqmp_disp_create_planes(struct zynqmp_disp *disp)
-{
- unsigned int i, j;
- int ret;
-
- for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
- struct zynqmp_disp_layer *layer = &disp->layers[i];
- enum drm_plane_type type;
- u32 *drm_formats;
-
- drm_formats = drmm_kcalloc(disp->drm, sizeof(*drm_formats),
- layer->info->num_formats,
- GFP_KERNEL);
- if (!drm_formats)
- return -ENOMEM;
-
- for (j = 0; j < layer->info->num_formats; ++j)
- drm_formats[j] = layer->info->formats[j].drm_fmt;
-
- /* Graphics layer is primary, and video layer is overlay. */
- type = zynqmp_disp_layer_is_video(layer)
- ? DRM_PLANE_TYPE_OVERLAY : DRM_PLANE_TYPE_PRIMARY;
- ret = drm_universal_plane_init(disp->drm, &layer->plane, 0,
- &zynqmp_disp_plane_funcs,
- drm_formats,
- layer->info->num_formats,
- NULL, type, NULL);
- if (ret)
- return ret;
-
- drm_plane_helper_add(&layer->plane,
- &zynqmp_disp_plane_helper_funcs);
-
- drm_plane_create_zpos_immutable_property(&layer->plane, i);
- if (zynqmp_disp_layer_is_gfx(layer))
- drm_plane_create_alpha_property(&layer->plane);
- }
-
- return 0;
-}
-
/**
* zynqmp_disp_layer_release_dma - Release DMA channels for a layer
* @disp: Display controller
@@ -1277,7 +1040,7 @@ static void zynqmp_disp_layer_release_dma(struct zynqmp_disp *disp,
{
unsigned int i;
- if (!layer->info)
+ if (!layer->info || !disp->dpsub->dma_enabled)
return;
for (i = 0; i < layer->info->num_channels; i++) {
@@ -1300,7 +1063,7 @@ static void zynqmp_disp_destroy_layers(struct zynqmp_disp *disp)
{
unsigned int i;
- for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++)
+ for (i = 0; i < ARRAY_SIZE(disp->layers); i++)
zynqmp_disp_layer_release_dma(disp, &disp->layers[i]);
}
@@ -1320,6 +1083,9 @@ static int zynqmp_disp_layer_request_dma(struct zynqmp_disp *disp,
unsigned int i;
int ret;
+ if (!disp->dpsub->dma_enabled)
+ return 0;
+
for (i = 0; i < layer->info->num_channels; i++) {
struct zynqmp_disp_layer_dma *dma = &layer->dmas[i];
char dma_channel_name[16];
@@ -1347,12 +1113,12 @@ static int zynqmp_disp_layer_request_dma(struct zynqmp_disp *disp,
static int zynqmp_disp_create_layers(struct zynqmp_disp *disp)
{
static const struct zynqmp_disp_layer_info layer_info[] = {
- [ZYNQMP_DISP_LAYER_VID] = {
+ [ZYNQMP_DPSUB_LAYER_VID] = {
.formats = avbuf_vid_fmts,
.num_formats = ARRAY_SIZE(avbuf_vid_fmts),
.num_channels = 3,
},
- [ZYNQMP_DISP_LAYER_GFX] = {
+ [ZYNQMP_DPSUB_LAYER_GFX] = {
.formats = avbuf_gfx_fmts,
.num_formats = ARRAY_SIZE(avbuf_gfx_fmts),
.num_channels = 1,
@@ -1362,7 +1128,7 @@ static int zynqmp_disp_create_layers(struct zynqmp_disp *disp)
unsigned int i;
int ret;
- for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++) {
+ for (i = 0; i < ARRAY_SIZE(disp->layers); i++) {
struct zynqmp_disp_layer *layer = &disp->layers[i];
layer->id = i;
@@ -1372,6 +1138,8 @@ static int zynqmp_disp_create_layers(struct zynqmp_disp *disp)
ret = zynqmp_disp_layer_request_dma(disp, layer);
if (ret)
goto err;
+
+ disp->dpsub->layers[i] = layer;
}
return 0;
@@ -1382,19 +1150,23 @@ err:
}
/* -----------------------------------------------------------------------------
- * ZynqMP Display & DRM CRTC
+ * ZynqMP Display
*/
/**
* zynqmp_disp_enable - Enable the display controller
* @disp: Display controller
*/
-static void zynqmp_disp_enable(struct zynqmp_disp *disp)
+void zynqmp_disp_enable(struct zynqmp_disp *disp)
{
+ zynqmp_disp_blend_set_output_format(disp, ZYNQMP_DPSUB_FORMAT_RGB);
+ zynqmp_disp_blend_set_bg_color(disp, 0, 0, 0);
+
zynqmp_disp_avbuf_enable(disp);
/* Choose clock source based on the DT clock handle. */
- zynqmp_disp_avbuf_set_clocks_sources(disp, disp->pclk_from_ps,
- disp->audio.clk_from_ps, true);
+ zynqmp_disp_avbuf_set_clocks_sources(disp, disp->dpsub->vid_clk_from_ps,
+ disp->dpsub->aud_clk_from_ps,
+ true);
zynqmp_disp_avbuf_enable_channels(disp);
zynqmp_disp_avbuf_enable_audio(disp);
@@ -1405,7 +1177,7 @@ static void zynqmp_disp_enable(struct zynqmp_disp *disp)
* zynqmp_disp_disable - Disable the display controller
* @disp: Display controller
*/
-static void zynqmp_disp_disable(struct zynqmp_disp *disp)
+void zynqmp_disp_disable(struct zynqmp_disp *disp)
{
zynqmp_disp_audio_disable(disp);
@@ -1414,27 +1186,27 @@ static void zynqmp_disp_disable(struct zynqmp_disp *disp)
zynqmp_disp_avbuf_disable(disp);
}
-static inline struct zynqmp_disp *crtc_to_disp(struct drm_crtc *crtc)
-{
- return container_of(crtc, struct zynqmp_disp, crtc);
-}
-
-static int zynqmp_disp_crtc_setup_clock(struct drm_crtc *crtc,
- struct drm_display_mode *adjusted_mode)
+/**
+ * zynqmp_disp_setup_clock - Configure the display controller pixel clock rate
+ * @disp: Display controller
+ * @mode_clock: The pixel clock rate, in Hz
+ *
+ * Return: 0 on success, or a negative error clock otherwise
+ */
+int zynqmp_disp_setup_clock(struct zynqmp_disp *disp,
+ unsigned long mode_clock)
{
- struct zynqmp_disp *disp = crtc_to_disp(crtc);
- unsigned long mode_clock = adjusted_mode->clock * 1000;
unsigned long rate;
long diff;
int ret;
- ret = clk_set_rate(disp->pclk, mode_clock);
+ ret = clk_set_rate(disp->dpsub->vid_clk, mode_clock);
if (ret) {
- dev_err(disp->dev, "failed to set a pixel clock\n");
+ dev_err(disp->dev, "failed to set the video clock\n");
return ret;
}
- rate = clk_get_rate(disp->pclk);
+ rate = clk_get_rate(disp->dpsub->vid_clk);
diff = rate - mode_clock;
if (abs(diff) > mode_clock / 20)
dev_info(disp->dev,
@@ -1448,245 +1220,63 @@ static int zynqmp_disp_crtc_setup_clock(struct drm_crtc *crtc,
return 0;
}
-static void
-zynqmp_disp_crtc_atomic_enable(struct drm_crtc *crtc,
- struct drm_atomic_state *state)
-{
- struct zynqmp_disp *disp = crtc_to_disp(crtc);
- struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
- int ret, vrefresh;
-
- pm_runtime_get_sync(disp->dev);
-
- zynqmp_disp_crtc_setup_clock(crtc, adjusted_mode);
-
- ret = clk_prepare_enable(disp->pclk);
- if (ret) {
- dev_err(disp->dev, "failed to enable a pixel clock\n");
- pm_runtime_put_sync(disp->dev);
- return;
- }
-
- zynqmp_disp_blend_set_output_format(disp, ZYNQMP_DPSUB_FORMAT_RGB);
- zynqmp_disp_blend_set_bg_color(disp, 0, 0, 0);
-
- zynqmp_disp_enable(disp);
-
- /* Delay of 3 vblank intervals for timing gen to be stable */
- vrefresh = (adjusted_mode->clock * 1000) /
- (adjusted_mode->vtotal * adjusted_mode->htotal);
- msleep(3 * 1000 / vrefresh);
-}
-
-static void
-zynqmp_disp_crtc_atomic_disable(struct drm_crtc *crtc,
- struct drm_atomic_state *state)
-{
- struct zynqmp_disp *disp = crtc_to_disp(crtc);
- struct drm_plane_state *old_plane_state;
-
- /*
- * Disable the plane if active. The old plane state can be NULL in the
- * .shutdown() path if the plane is already disabled, skip
- * zynqmp_disp_plane_atomic_disable() in that case.
- */
- old_plane_state = drm_atomic_get_old_plane_state(state, crtc->primary);
- if (old_plane_state)
- zynqmp_disp_plane_atomic_disable(crtc->primary, state);
-
- zynqmp_disp_disable(disp);
-
- drm_crtc_vblank_off(&disp->crtc);
-
- spin_lock_irq(&crtc->dev->event_lock);
- if (crtc->state->event) {
- drm_crtc_send_vblank_event(crtc, crtc->state->event);
- crtc->state->event = NULL;
- }
- spin_unlock_irq(&crtc->dev->event_lock);
-
- clk_disable_unprepare(disp->pclk);
- pm_runtime_put_sync(disp->dev);
-}
-
-static int zynqmp_disp_crtc_atomic_check(struct drm_crtc *crtc,
- struct drm_atomic_state *state)
-{
- return drm_atomic_add_affected_planes(state, crtc);
-}
-
-static void
-zynqmp_disp_crtc_atomic_begin(struct drm_crtc *crtc,
- struct drm_atomic_state *state)
-{
- drm_crtc_vblank_on(crtc);
-}
-
-static void
-zynqmp_disp_crtc_atomic_flush(struct drm_crtc *crtc,
- struct drm_atomic_state *state)
-{
- if (crtc->state->event) {
- struct drm_pending_vblank_event *event;
-
- /* Consume the flip_done event from atomic helper. */
- event = crtc->state->event;
- crtc->state->event = NULL;
-
- event->pipe = drm_crtc_index(crtc);
-
- WARN_ON(drm_crtc_vblank_get(crtc) != 0);
-
- spin_lock_irq(&crtc->dev->event_lock);
- drm_crtc_arm_vblank_event(crtc, event);
- spin_unlock_irq(&crtc->dev->event_lock);
- }
-}
-
-static const struct drm_crtc_helper_funcs zynqmp_disp_crtc_helper_funcs = {
- .atomic_enable = zynqmp_disp_crtc_atomic_enable,
- .atomic_disable = zynqmp_disp_crtc_atomic_disable,
- .atomic_check = zynqmp_disp_crtc_atomic_check,
- .atomic_begin = zynqmp_disp_crtc_atomic_begin,
- .atomic_flush = zynqmp_disp_crtc_atomic_flush,
-};
-
-static int zynqmp_disp_crtc_enable_vblank(struct drm_crtc *crtc)
-{
- struct zynqmp_disp *disp = crtc_to_disp(crtc);
-
- zynqmp_dp_enable_vblank(disp->dpsub->dp);
-
- return 0;
-}
-
-static void zynqmp_disp_crtc_disable_vblank(struct drm_crtc *crtc)
-{
- struct zynqmp_disp *disp = crtc_to_disp(crtc);
-
- zynqmp_dp_disable_vblank(disp->dpsub->dp);
-}
-
-static const struct drm_crtc_funcs zynqmp_disp_crtc_funcs = {
- .destroy = drm_crtc_cleanup,
- .set_config = drm_atomic_helper_set_config,
- .page_flip = drm_atomic_helper_page_flip,
- .reset = drm_atomic_helper_crtc_reset,
- .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
- .enable_vblank = zynqmp_disp_crtc_enable_vblank,
- .disable_vblank = zynqmp_disp_crtc_disable_vblank,
-};
-
-static int zynqmp_disp_create_crtc(struct zynqmp_disp *disp)
-{
- struct drm_plane *plane = &disp->layers[ZYNQMP_DISP_LAYER_GFX].plane;
- int ret;
-
- ret = drm_crtc_init_with_planes(disp->drm, &disp->crtc, plane,
- NULL, &zynqmp_disp_crtc_funcs, NULL);
- if (ret < 0)
- return ret;
-
- drm_crtc_helper_add(&disp->crtc, &zynqmp_disp_crtc_helper_funcs);
-
- /* Start with vertical blanking interrupt reporting disabled. */
- drm_crtc_vblank_off(&disp->crtc);
-
- return 0;
-}
-
-static void zynqmp_disp_map_crtc_to_plane(struct zynqmp_disp *disp)
-{
- u32 possible_crtcs = drm_crtc_mask(&disp->crtc);
- unsigned int i;
-
- for (i = 0; i < ZYNQMP_DISP_NUM_LAYERS; i++)
- disp->layers[i].plane.possible_crtcs = possible_crtcs;
-}
-
/* -----------------------------------------------------------------------------
* Initialization & Cleanup
*/
-int zynqmp_disp_drm_init(struct zynqmp_dpsub *dpsub)
-{
- struct zynqmp_disp *disp = dpsub->disp;
- int ret;
-
- ret = zynqmp_disp_create_planes(disp);
- if (ret)
- return ret;
-
- ret = zynqmp_disp_create_crtc(disp);
- if (ret < 0)
- return ret;
-
- zynqmp_disp_map_crtc_to_plane(disp);
-
- return 0;
-}
-
-int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
+int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub)
{
struct platform_device *pdev = to_platform_device(dpsub->dev);
struct zynqmp_disp *disp;
- struct zynqmp_disp_layer *layer;
struct resource *res;
int ret;
- disp = drmm_kzalloc(drm, sizeof(*disp), GFP_KERNEL);
+ disp = kzalloc(sizeof(*disp), GFP_KERNEL);
if (!disp)
return -ENOMEM;
disp->dev = &pdev->dev;
disp->dpsub = dpsub;
- disp->drm = drm;
-
- dpsub->disp = disp;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "blend");
disp->blend.base = devm_ioremap_resource(disp->dev, res);
- if (IS_ERR(disp->blend.base))
- return PTR_ERR(disp->blend.base);
+ if (IS_ERR(disp->blend.base)) {
+ ret = PTR_ERR(disp->blend.base);
+ goto error;
+ }
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "av_buf");
disp->avbuf.base = devm_ioremap_resource(disp->dev, res);
- if (IS_ERR(disp->avbuf.base))
- return PTR_ERR(disp->avbuf.base);
+ if (IS_ERR(disp->avbuf.base)) {
+ ret = PTR_ERR(disp->avbuf.base);
+ goto error;
+ }
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aud");
disp->audio.base = devm_ioremap_resource(disp->dev, res);
- if (IS_ERR(disp->audio.base))
- return PTR_ERR(disp->audio.base);
-
- /* Try the live PL video clock */
- disp->pclk = devm_clk_get(disp->dev, "dp_live_video_in_clk");
- if (!IS_ERR(disp->pclk))
- disp->pclk_from_ps = false;
- else if (PTR_ERR(disp->pclk) == -EPROBE_DEFER)
- return PTR_ERR(disp->pclk);
-
- /* If the live PL video clock is not valid, fall back to PS clock */
- if (IS_ERR_OR_NULL(disp->pclk)) {
- disp->pclk = devm_clk_get(disp->dev, "dp_vtc_pixel_clk_in");
- if (IS_ERR(disp->pclk)) {
- dev_err(disp->dev, "failed to init any video clock\n");
- return PTR_ERR(disp->pclk);
- }
- disp->pclk_from_ps = true;
+ if (IS_ERR(disp->audio.base)) {
+ ret = PTR_ERR(disp->audio.base);
+ goto error;
}
- zynqmp_disp_audio_init(disp);
-
ret = zynqmp_disp_create_layers(disp);
if (ret)
- return ret;
+ goto error;
+
+ if (disp->dpsub->dma_enabled) {
+ struct zynqmp_disp_layer *layer;
- layer = &disp->layers[ZYNQMP_DISP_LAYER_VID];
- dpsub->dma_align = 1 << layer->dmas[0].chan->device->copy_align;
+ layer = &disp->layers[ZYNQMP_DPSUB_LAYER_VID];
+ dpsub->dma_align = 1 << layer->dmas[0].chan->device->copy_align;
+ }
+
+ dpsub->disp = disp;
return 0;
+
+error:
+ kfree(disp);
+ return ret;
}
void zynqmp_disp_remove(struct zynqmp_dpsub *dpsub)
diff --git a/drivers/gpu/drm/xlnx/zynqmp_disp.h b/drivers/gpu/drm/xlnx/zynqmp_disp.h
index f402901afb23..123cffac08be 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_disp.h
+++ b/drivers/gpu/drm/xlnx/zynqmp_disp.h
@@ -25,18 +25,52 @@
#define ZYNQMP_DISP_MAX_DMA_BIT 44
struct device;
-struct drm_device;
+struct drm_format_info;
+struct drm_plane_state;
struct platform_device;
struct zynqmp_disp;
+struct zynqmp_disp_layer;
struct zynqmp_dpsub;
-void zynqmp_disp_handle_vblank(struct zynqmp_disp *disp);
-bool zynqmp_disp_audio_enabled(struct zynqmp_disp *disp);
-unsigned int zynqmp_disp_get_audio_clk_rate(struct zynqmp_disp *disp);
-uint32_t zynqmp_disp_get_crtc_mask(struct zynqmp_disp *disp);
+/**
+ * enum zynqmp_dpsub_layer_id - Layer identifier
+ * @ZYNQMP_DPSUB_LAYER_VID: Video layer
+ * @ZYNQMP_DPSUB_LAYER_GFX: Graphics layer
+ */
+enum zynqmp_dpsub_layer_id {
+ ZYNQMP_DPSUB_LAYER_VID,
+ ZYNQMP_DPSUB_LAYER_GFX,
+};
+
+/**
+ * enum zynqmp_dpsub_layer_mode - Layer mode
+ * @ZYNQMP_DPSUB_LAYER_NONLIVE: non-live (memory) mode
+ * @ZYNQMP_DPSUB_LAYER_LIVE: live (stream) mode
+ */
+enum zynqmp_dpsub_layer_mode {
+ ZYNQMP_DPSUB_LAYER_NONLIVE,
+ ZYNQMP_DPSUB_LAYER_LIVE,
+};
+
+void zynqmp_disp_enable(struct zynqmp_disp *disp);
+void zynqmp_disp_disable(struct zynqmp_disp *disp);
+int zynqmp_disp_setup_clock(struct zynqmp_disp *disp,
+ unsigned long mode_clock);
+
+void zynqmp_disp_blend_set_global_alpha(struct zynqmp_disp *disp,
+ bool enable, u32 alpha);
+
+u32 *zynqmp_disp_layer_drm_formats(struct zynqmp_disp_layer *layer,
+ unsigned int *num_formats);
+void zynqmp_disp_layer_enable(struct zynqmp_disp_layer *layer,
+ enum zynqmp_dpsub_layer_mode mode);
+void zynqmp_disp_layer_disable(struct zynqmp_disp_layer *layer);
+void zynqmp_disp_layer_set_format(struct zynqmp_disp_layer *layer,
+ const struct drm_format_info *info);
+int zynqmp_disp_layer_update(struct zynqmp_disp_layer *layer,
+ struct drm_plane_state *state);
-int zynqmp_disp_drm_init(struct zynqmp_dpsub *dpsub);
-int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm);
+int zynqmp_disp_probe(struct zynqmp_dpsub *dpsub);
void zynqmp_disp_remove(struct zynqmp_dpsub *dpsub);
#endif /* _ZYNQMP_DISP_H_ */
diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.c b/drivers/gpu/drm/xlnx/zynqmp_dp.c
index d14612b34796..0a7b466446fb 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dp.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_dp.c
@@ -11,16 +11,12 @@
#include <drm/display/drm_dp_helper.h>
#include <drm/drm_atomic_helper.h>
-#include <drm/drm_connector.h>
#include <drm/drm_crtc.h>
#include <drm/drm_device.h>
#include <drm/drm_edid.h>
-#include <drm/drm_encoder.h>
-#include <drm/drm_managed.h>
+#include <drm/drm_fourcc.h>
#include <drm/drm_modes.h>
#include <drm/drm_of.h>
-#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
#include <linux/clk.h>
#include <linux/delay.h>
@@ -31,10 +27,12 @@
#include <linux/pm_runtime.h>
#include <linux/phy/phy.h>
#include <linux/reset.h>
+#include <linux/slab.h>
#include "zynqmp_disp.h"
#include "zynqmp_dp.h"
#include "zynqmp_dpsub.h"
+#include "zynqmp_kms.h"
static uint zynqmp_dp_aux_timeout_ms = 50;
module_param_named(aux_timeout_ms, zynqmp_dp_aux_timeout_ms, uint, 0444);
@@ -277,14 +275,13 @@ struct zynqmp_dp_config {
/**
* struct zynqmp_dp - Xilinx DisplayPort core
- * @encoder: the drm encoder structure
- * @connector: the drm connector structure
* @dev: device structure
* @dpsub: Display subsystem
- * @drm: DRM core
* @iomem: device I/O memory for register access
* @reset: reset controller
* @irq: irq
+ * @bridge: DRM bridge for the DP encoder
+ * @next_bridge: The downstream bridge
* @config: IP core configuration from DTS
* @aux: aux channel
* @phy: PHY handles for DP lanes
@@ -298,15 +295,15 @@ struct zynqmp_dp_config {
* @train_set: set of training data
*/
struct zynqmp_dp {
- struct drm_encoder encoder;
- struct drm_connector connector;
struct device *dev;
struct zynqmp_dpsub *dpsub;
- struct drm_device *drm;
void __iomem *iomem;
struct reset_control *reset;
int irq;
+ struct drm_bridge bridge;
+ struct drm_bridge *next_bridge;
+
struct zynqmp_dp_config config;
struct drm_dp_aux aux;
struct phy *phy[ZYNQMP_DP_MAX_LANES];
@@ -321,14 +318,9 @@ struct zynqmp_dp {
u8 train_set[ZYNQMP_DP_MAX_LANES];
};
-static inline struct zynqmp_dp *encoder_to_dp(struct drm_encoder *encoder)
-{
- return container_of(encoder, struct zynqmp_dp, encoder);
-}
-
-static inline struct zynqmp_dp *connector_to_dp(struct drm_connector *connector)
+static inline struct zynqmp_dp *bridge_to_dp(struct drm_bridge *bridge)
{
- return container_of(connector, struct zynqmp_dp, connector);
+ return container_of(bridge, struct zynqmp_dp, bridge);
}
static void zynqmp_dp_write(struct zynqmp_dp *dp, int offset, u32 val)
@@ -1064,7 +1056,7 @@ static int zynqmp_dp_aux_init(struct zynqmp_dp *dp)
dp->aux.name = "ZynqMP DP AUX";
dp->aux.dev = dp->dev;
- dp->aux.drm_dev = dp->drm;
+ dp->aux.drm_dev = dp->bridge.dev;
dp->aux.transfer = zynqmp_dp_aux_transfer;
return drm_dp_aux_register(&dp->aux);
@@ -1101,6 +1093,7 @@ static void zynqmp_dp_update_misc(struct zynqmp_dp *dp)
/**
* zynqmp_dp_set_format - Set the input format
* @dp: DisplayPort IP core structure
+ * @info: Display info
* @format: input format
* @bpc: bits per component
*
@@ -1109,10 +1102,10 @@ static void zynqmp_dp_update_misc(struct zynqmp_dp *dp)
* Return: 0 on success, or -EINVAL.
*/
static int zynqmp_dp_set_format(struct zynqmp_dp *dp,
+ const struct drm_display_info *info,
enum zynqmp_dpsub_format format,
unsigned int bpc)
{
- static const struct drm_display_info *display;
struct zynqmp_dp_config *config = &dp->config;
unsigned int num_colors;
@@ -1145,12 +1138,11 @@ static int zynqmp_dp_set_format(struct zynqmp_dp *dp,
return -EINVAL;
}
- display = &dp->connector.display_info;
- if (display->bpc && bpc > display->bpc) {
+ if (info && info->bpc && bpc > info->bpc) {
dev_warn(dp->dev,
"downgrading requested %ubpc to display limit %ubpc\n",
- bpc, display->bpc);
- bpc = display->bpc;
+ bpc, info->bpc);
+ bpc = info->bpc;
}
config->misc0 &= ~ZYNQMP_DP_MAIN_STREAM_MISC0_BPC_MASK;
@@ -1195,7 +1187,7 @@ static int zynqmp_dp_set_format(struct zynqmp_dp *dp,
*/
static void
zynqmp_dp_encoder_mode_set_transfer_unit(struct zynqmp_dp *dp,
- struct drm_display_mode *mode)
+ const struct drm_display_mode *mode)
{
u32 tu = ZYNQMP_DP_MSA_TRANSFER_UNIT_SIZE_TU_SIZE_DEF;
u32 bw, vid_kbytes, avg_bytes_per_tu, init_wait;
@@ -1255,12 +1247,12 @@ static void zynqmp_dp_encoder_mode_set_stream(struct zynqmp_dp *dp,
zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_VSTART,
mode->vtotal - mode->vsync_start);
- /* In synchronous mode, set the diviers */
+ /* In synchronous mode, set the dividers */
if (dp->config.misc0 & ZYNQMP_DP_MAIN_STREAM_MISC0_SYNC_LOCK) {
reg = drm_dp_bw_code_to_link_rate(dp->mode.bw_code);
zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_N_VID, reg);
zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_M_VID, mode->clock);
- rate = zynqmp_disp_get_audio_clk_rate(dp->dpsub->disp);
+ rate = zynqmp_dpsub_get_audio_clk_rate(dp->dpsub);
if (rate) {
dev_dbg(dp->dev, "Audio rate: %d\n", rate / 512);
zynqmp_dp_write(dp, ZYNQMP_DP_TX_N_AUD, reg);
@@ -1269,7 +1261,7 @@ static void zynqmp_dp_encoder_mode_set_stream(struct zynqmp_dp *dp,
}
/* Only 2 channel audio is supported now */
- if (zynqmp_disp_audio_enabled(dp->dpsub->disp))
+ if (zynqmp_dpsub_audio_enabled(dp->dpsub))
zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CHANNELS, 1);
zynqmp_dp_write(dp, ZYNQMP_DP_USER_PIX_WIDTH, 1);
@@ -1281,97 +1273,115 @@ static void zynqmp_dp_encoder_mode_set_stream(struct zynqmp_dp *dp,
}
/* -----------------------------------------------------------------------------
- * DRM Connector
+ * DISP Configuration
*/
-static enum drm_connector_status
-zynqmp_dp_connector_detect(struct drm_connector *connector, bool force)
+static void zynqmp_dp_disp_enable(struct zynqmp_dp *dp,
+ struct drm_bridge_state *old_bridge_state)
{
- struct zynqmp_dp *dp = connector_to_dp(connector);
- struct zynqmp_dp_link_config *link_config = &dp->link_config;
- u32 state, i;
- int ret;
+ enum zynqmp_dpsub_layer_id layer_id;
+ struct zynqmp_disp_layer *layer;
+ const struct drm_format_info *info;
+
+ if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO))
+ layer_id = ZYNQMP_DPSUB_LAYER_VID;
+ else if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX))
+ layer_id = ZYNQMP_DPSUB_LAYER_GFX;
+ else
+ return;
- /*
- * This is from heuristic. It takes some delay (ex, 100 ~ 500 msec) to
- * get the HPD signal with some monitors.
- */
- for (i = 0; i < 10; i++) {
- state = zynqmp_dp_read(dp, ZYNQMP_DP_INTERRUPT_SIGNAL_STATE);
- if (state & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_HPD)
- break;
- msleep(100);
- }
+ layer = dp->dpsub->layers[layer_id];
- if (state & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_HPD) {
- ret = drm_dp_dpcd_read(&dp->aux, 0x0, dp->dpcd,
- sizeof(dp->dpcd));
- if (ret < 0) {
- dev_dbg(dp->dev, "DPCD read failed");
- goto disconnected;
- }
+ /* TODO: Make the format configurable. */
+ info = drm_format_info(DRM_FORMAT_YUV422);
+ zynqmp_disp_layer_set_format(layer, info);
+ zynqmp_disp_layer_enable(layer, ZYNQMP_DPSUB_LAYER_LIVE);
- link_config->max_rate = min_t(int,
- drm_dp_max_link_rate(dp->dpcd),
- DP_HIGH_BIT_RATE2);
- link_config->max_lanes = min_t(u8,
- drm_dp_max_lane_count(dp->dpcd),
- dp->num_lanes);
+ if (layer_id == ZYNQMP_DPSUB_LAYER_GFX)
+ zynqmp_disp_blend_set_global_alpha(dp->dpsub->disp, true, 255);
+ else
+ zynqmp_disp_blend_set_global_alpha(dp->dpsub->disp, false, 0);
- dp->status = connector_status_connected;
- return connector_status_connected;
- }
+ zynqmp_disp_enable(dp->dpsub->disp);
+}
-disconnected:
- dp->status = connector_status_disconnected;
- return connector_status_disconnected;
+static void zynqmp_dp_disp_disable(struct zynqmp_dp *dp,
+ struct drm_bridge_state *old_bridge_state)
+{
+ struct zynqmp_disp_layer *layer;
+
+ if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO))
+ layer = dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_VID];
+ else if (dp->dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX))
+ layer = dp->dpsub->layers[ZYNQMP_DPSUB_LAYER_GFX];
+ else
+ return;
+
+ zynqmp_disp_disable(dp->dpsub->disp);
+ zynqmp_disp_layer_disable(layer);
}
-static int zynqmp_dp_connector_get_modes(struct drm_connector *connector)
+/* -----------------------------------------------------------------------------
+ * DRM Bridge
+ */
+
+static int zynqmp_dp_bridge_attach(struct drm_bridge *bridge,
+ enum drm_bridge_attach_flags flags)
{
- struct zynqmp_dp *dp = connector_to_dp(connector);
- struct edid *edid;
+ struct zynqmp_dp *dp = bridge_to_dp(bridge);
int ret;
- edid = drm_get_edid(connector, &dp->aux.ddc);
- if (!edid)
- return 0;
+ /* Initialize and register the AUX adapter. */
+ ret = zynqmp_dp_aux_init(dp);
+ if (ret) {
+ dev_err(dp->dev, "failed to initialize DP aux\n");
+ return ret;
+ }
- drm_connector_update_edid_property(connector, edid);
- ret = drm_add_edid_modes(connector, edid);
- kfree(edid);
+ if (dp->next_bridge) {
+ ret = drm_bridge_attach(bridge->encoder, dp->next_bridge,
+ bridge, flags);
+ if (ret < 0)
+ goto error;
+ }
+ /* Now that initialisation is complete, enable interrupts. */
+ zynqmp_dp_write(dp, ZYNQMP_DP_INT_EN, ZYNQMP_DP_INT_ALL);
+
+ return 0;
+
+error:
+ zynqmp_dp_aux_cleanup(dp);
return ret;
}
-static struct drm_encoder *
-zynqmp_dp_connector_best_encoder(struct drm_connector *connector)
+static void zynqmp_dp_bridge_detach(struct drm_bridge *bridge)
{
- struct zynqmp_dp *dp = connector_to_dp(connector);
+ struct zynqmp_dp *dp = bridge_to_dp(bridge);
- return &dp->encoder;
+ zynqmp_dp_aux_cleanup(dp);
}
-static int zynqmp_dp_connector_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode)
+static enum drm_mode_status
+zynqmp_dp_bridge_mode_valid(struct drm_bridge *bridge,
+ const struct drm_display_info *info,
+ const struct drm_display_mode *mode)
{
- struct zynqmp_dp *dp = connector_to_dp(connector);
- u8 max_lanes = dp->link_config.max_lanes;
- u8 bpp = dp->config.bpp;
- int max_rate = dp->link_config.max_rate;
+ struct zynqmp_dp *dp = bridge_to_dp(bridge);
int rate;
if (mode->clock > ZYNQMP_MAX_FREQ) {
- dev_dbg(dp->dev, "filtered the mode, %s,for high pixel rate\n",
+ dev_dbg(dp->dev, "filtered mode %s for high pixel rate\n",
mode->name);
drm_mode_debug_printmodeline(mode);
return MODE_CLOCK_HIGH;
}
/* Check with link rate and lane count */
- rate = zynqmp_dp_max_rate(max_rate, max_lanes, bpp);
+ rate = zynqmp_dp_max_rate(dp->link_config.max_rate,
+ dp->link_config.max_lanes, dp->config.bpp);
if (mode->clock > rate) {
- dev_dbg(dp->dev, "filtered the mode, %s,for high pixel rate\n",
+ dev_dbg(dp->dev, "filtered mode %s for high pixel rate\n",
mode->name);
drm_mode_debug_printmodeline(mode);
return MODE_CLOCK_HIGH;
@@ -1380,36 +1390,62 @@ static int zynqmp_dp_connector_mode_valid(struct drm_connector *connector,
return MODE_OK;
}
-static const struct drm_connector_funcs zynqmp_dp_connector_funcs = {
- .detect = zynqmp_dp_connector_detect,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = drm_connector_cleanup,
- .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
- .reset = drm_atomic_helper_connector_reset,
-};
-
-static const struct drm_connector_helper_funcs
-zynqmp_dp_connector_helper_funcs = {
- .get_modes = zynqmp_dp_connector_get_modes,
- .best_encoder = zynqmp_dp_connector_best_encoder,
- .mode_valid = zynqmp_dp_connector_mode_valid,
-};
-
-/* -----------------------------------------------------------------------------
- * DRM Encoder
- */
-
-static void zynqmp_dp_encoder_enable(struct drm_encoder *encoder)
+static void zynqmp_dp_bridge_atomic_enable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
{
- struct zynqmp_dp *dp = encoder_to_dp(encoder);
+ struct zynqmp_dp *dp = bridge_to_dp(bridge);
+ struct drm_atomic_state *state = old_bridge_state->base.state;
+ const struct drm_crtc_state *crtc_state;
+ const struct drm_display_mode *adjusted_mode;
+ const struct drm_display_mode *mode;
+ struct drm_connector *connector;
+ struct drm_crtc *crtc;
unsigned int i;
- int ret = 0;
+ int rate;
+ int ret;
pm_runtime_get_sync(dp->dev);
+
+ zynqmp_dp_disp_enable(dp, old_bridge_state);
+
+ /*
+ * Retrieve the CRTC mode and adjusted mode. This requires a little
+ * dance to go from the bridge to the encoder, to the connector and to
+ * the CRTC.
+ */
+ connector = drm_atomic_get_new_connector_for_encoder(state,
+ bridge->encoder);
+ crtc = drm_atomic_get_new_connector_state(state, connector)->crtc;
+ crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
+ adjusted_mode = &crtc_state->adjusted_mode;
+ mode = &crtc_state->mode;
+
+ zynqmp_dp_set_format(dp, &connector->display_info,
+ ZYNQMP_DPSUB_FORMAT_RGB, 8);
+
+ /* Check again as bpp or format might have been changed */
+ rate = zynqmp_dp_max_rate(dp->link_config.max_rate,
+ dp->link_config.max_lanes, dp->config.bpp);
+ if (mode->clock > rate) {
+ dev_err(dp->dev, "mode %s has too high pixel rate\n",
+ mode->name);
+ drm_mode_debug_printmodeline(mode);
+ }
+
+ /* Configure the mode */
+ ret = zynqmp_dp_mode_configure(dp, adjusted_mode->clock, 0);
+ if (ret < 0) {
+ pm_runtime_put_sync(dp->dev);
+ return;
+ }
+
+ zynqmp_dp_encoder_mode_set_transfer_unit(dp, adjusted_mode);
+ zynqmp_dp_encoder_mode_set_stream(dp, adjusted_mode);
+
+ /* Enable the encoder */
dp->enabled = true;
zynqmp_dp_update_misc(dp);
- if (zynqmp_disp_audio_enabled(dp->dpsub->disp))
+ if (zynqmp_dpsub_audio_enabled(dp->dpsub))
zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CONTROL, 1);
zynqmp_dp_write(dp, ZYNQMP_DP_TX_PHY_POWER_DOWN, 0);
if (dp->status == connector_status_connected) {
@@ -1432,9 +1468,10 @@ static void zynqmp_dp_encoder_enable(struct drm_encoder *encoder)
zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_ENABLE, 1);
}
-static void zynqmp_dp_encoder_disable(struct drm_encoder *encoder)
+static void zynqmp_dp_bridge_atomic_disable(struct drm_bridge *bridge,
+ struct drm_bridge_state *old_bridge_state)
{
- struct zynqmp_dp *dp = encoder_to_dp(encoder);
+ struct zynqmp_dp *dp = bridge_to_dp(bridge);
dp->enabled = false;
cancel_delayed_work(&dp->hpd_work);
@@ -1442,49 +1479,22 @@ static void zynqmp_dp_encoder_disable(struct drm_encoder *encoder)
drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, DP_SET_POWER_D3);
zynqmp_dp_write(dp, ZYNQMP_DP_TX_PHY_POWER_DOWN,
ZYNQMP_DP_TX_PHY_POWER_DOWN_ALL);
- if (zynqmp_disp_audio_enabled(dp->dpsub->disp))
+ if (zynqmp_dpsub_audio_enabled(dp->dpsub))
zynqmp_dp_write(dp, ZYNQMP_DP_TX_AUDIO_CONTROL, 0);
- pm_runtime_put_sync(dp->dev);
-}
-
-static void
-zynqmp_dp_encoder_atomic_mode_set(struct drm_encoder *encoder,
- struct drm_crtc_state *crtc_state,
- struct drm_connector_state *connector_state)
-{
- struct zynqmp_dp *dp = encoder_to_dp(encoder);
- struct drm_display_mode *mode = &crtc_state->mode;
- struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
- u8 max_lanes = dp->link_config.max_lanes;
- u8 bpp = dp->config.bpp;
- int rate, max_rate = dp->link_config.max_rate;
- int ret;
- zynqmp_dp_set_format(dp, ZYNQMP_DPSUB_FORMAT_RGB, 8);
+ zynqmp_dp_disp_disable(dp, old_bridge_state);
- /* Check again as bpp or format might have been chagned */
- rate = zynqmp_dp_max_rate(max_rate, max_lanes, bpp);
- if (mode->clock > rate) {
- dev_err(dp->dev, "the mode, %s,has too high pixel rate\n",
- mode->name);
- drm_mode_debug_printmodeline(mode);
- }
-
- ret = zynqmp_dp_mode_configure(dp, adjusted_mode->clock, 0);
- if (ret < 0)
- return;
-
- zynqmp_dp_encoder_mode_set_transfer_unit(dp, adjusted_mode);
- zynqmp_dp_encoder_mode_set_stream(dp, adjusted_mode);
+ pm_runtime_put_sync(dp->dev);
}
#define ZYNQMP_DP_MIN_H_BACKPORCH 20
-static int
-zynqmp_dp_encoder_atomic_check(struct drm_encoder *encoder,
- struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state)
+static int zynqmp_dp_bridge_atomic_check(struct drm_bridge *bridge,
+ struct drm_bridge_state *bridge_state,
+ struct drm_crtc_state *crtc_state,
+ struct drm_connector_state *conn_state)
{
+ struct zynqmp_dp *dp = bridge_to_dp(bridge);
struct drm_display_mode *mode = &crtc_state->mode;
struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
int diff = mode->htotal - mode->hsync_end;
@@ -1497,7 +1507,7 @@ zynqmp_dp_encoder_atomic_check(struct drm_encoder *encoder,
int vrefresh = (adjusted_mode->clock * 1000) /
(adjusted_mode->vtotal * adjusted_mode->htotal);
- dev_dbg(encoder->dev->dev, "hbackporch adjusted: %d to %d",
+ dev_dbg(dp->dev, "hbackporch adjusted: %d to %d",
diff, ZYNQMP_DP_MIN_H_BACKPORCH - diff);
diff = ZYNQMP_DP_MIN_H_BACKPORCH - diff;
adjusted_mode->htotal += diff;
@@ -1508,11 +1518,68 @@ zynqmp_dp_encoder_atomic_check(struct drm_encoder *encoder,
return 0;
}
-static const struct drm_encoder_helper_funcs zynqmp_dp_encoder_helper_funcs = {
- .enable = zynqmp_dp_encoder_enable,
- .disable = zynqmp_dp_encoder_disable,
- .atomic_mode_set = zynqmp_dp_encoder_atomic_mode_set,
- .atomic_check = zynqmp_dp_encoder_atomic_check,
+static enum drm_connector_status zynqmp_dp_bridge_detect(struct drm_bridge *bridge)
+{
+ struct zynqmp_dp *dp = bridge_to_dp(bridge);
+ struct zynqmp_dp_link_config *link_config = &dp->link_config;
+ u32 state, i;
+ int ret;
+
+ /*
+ * This is from heuristic. It takes some delay (ex, 100 ~ 500 msec) to
+ * get the HPD signal with some monitors.
+ */
+ for (i = 0; i < 10; i++) {
+ state = zynqmp_dp_read(dp, ZYNQMP_DP_INTERRUPT_SIGNAL_STATE);
+ if (state & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_HPD)
+ break;
+ msleep(100);
+ }
+
+ if (state & ZYNQMP_DP_INTERRUPT_SIGNAL_STATE_HPD) {
+ ret = drm_dp_dpcd_read(&dp->aux, 0x0, dp->dpcd,
+ sizeof(dp->dpcd));
+ if (ret < 0) {
+ dev_dbg(dp->dev, "DPCD read failed");
+ goto disconnected;
+ }
+
+ link_config->max_rate = min_t(int,
+ drm_dp_max_link_rate(dp->dpcd),
+ DP_HIGH_BIT_RATE2);
+ link_config->max_lanes = min_t(u8,
+ drm_dp_max_lane_count(dp->dpcd),
+ dp->num_lanes);
+
+ dp->status = connector_status_connected;
+ return connector_status_connected;
+ }
+
+disconnected:
+ dp->status = connector_status_disconnected;
+ return connector_status_disconnected;
+}
+
+static struct edid *zynqmp_dp_bridge_get_edid(struct drm_bridge *bridge,
+ struct drm_connector *connector)
+{
+ struct zynqmp_dp *dp = bridge_to_dp(bridge);
+
+ return drm_get_edid(connector, &dp->aux.ddc);
+}
+
+static const struct drm_bridge_funcs zynqmp_dp_bridge_funcs = {
+ .attach = zynqmp_dp_bridge_attach,
+ .detach = zynqmp_dp_bridge_detach,
+ .mode_valid = zynqmp_dp_bridge_mode_valid,
+ .atomic_enable = zynqmp_dp_bridge_atomic_enable,
+ .atomic_disable = zynqmp_dp_bridge_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,
+ .atomic_check = zynqmp_dp_bridge_atomic_check,
+ .detect = zynqmp_dp_bridge_detect,
+ .get_edid = zynqmp_dp_bridge_get_edid,
};
/* -----------------------------------------------------------------------------
@@ -1543,12 +1610,12 @@ void zynqmp_dp_disable_vblank(struct zynqmp_dp *dp)
static void zynqmp_dp_hpd_work_func(struct work_struct *work)
{
- struct zynqmp_dp *dp;
-
- dp = container_of(work, struct zynqmp_dp, hpd_work.work);
+ struct zynqmp_dp *dp = container_of(work, struct zynqmp_dp,
+ hpd_work.work);
+ enum drm_connector_status status;
- if (dp->drm)
- drm_helper_hpd_irq_event(dp->drm);
+ status = zynqmp_dp_bridge_detect(&dp->bridge);
+ drm_bridge_hpd_notify(&dp->bridge, status);
}
static irqreturn_t zynqmp_dp_irq_handler(int irq, void *data)
@@ -1570,7 +1637,7 @@ static irqreturn_t zynqmp_dp_irq_handler(int irq, void *data)
zynqmp_dp_write(dp, ZYNQMP_DP_INT_STATUS, status);
if (status & ZYNQMP_DP_INT_VBLANK_START)
- zynqmp_disp_handle_vblank(dp->dpsub->disp);
+ zynqmp_dpsub_drm_handle_vblank(dp->dpsub);
if (status & ZYNQMP_DP_INT_HPD_EVENT)
schedule_delayed_work(&dp->hpd_work, 0);
@@ -1599,94 +1666,76 @@ handled:
* Initialization & Cleanup
*/
-int zynqmp_dp_drm_init(struct zynqmp_dpsub *dpsub)
-{
- struct zynqmp_dp *dp = dpsub->dp;
- struct drm_encoder *encoder = &dp->encoder;
- struct drm_connector *connector = &dp->connector;
- int ret;
-
- dp->config.misc0 &= ~ZYNQMP_DP_MAIN_STREAM_MISC0_SYNC_LOCK;
- zynqmp_dp_set_format(dp, ZYNQMP_DPSUB_FORMAT_RGB, 8);
-
- /* Create the DRM encoder and connector. */
- encoder->possible_crtcs |= zynqmp_disp_get_crtc_mask(dpsub->disp);
- drm_simple_encoder_init(dp->drm, encoder, DRM_MODE_ENCODER_TMDS);
- drm_encoder_helper_add(encoder, &zynqmp_dp_encoder_helper_funcs);
-
- connector->polled = DRM_CONNECTOR_POLL_HPD;
- ret = drm_connector_init(encoder->dev, connector,
- &zynqmp_dp_connector_funcs,
- DRM_MODE_CONNECTOR_DisplayPort);
- if (ret) {
- dev_err(dp->dev, "failed to create the DRM connector\n");
- return ret;
- }
-
- drm_connector_helper_add(connector, &zynqmp_dp_connector_helper_funcs);
- drm_connector_register(connector);
- drm_connector_attach_encoder(connector, encoder);
-
- /* Initialize and register the AUX adapter. */
- ret = zynqmp_dp_aux_init(dp);
- if (ret) {
- dev_err(dp->dev, "failed to initialize DP aux\n");
- return ret;
- }
-
- /* Now that initialisation is complete, enable interrupts. */
- zynqmp_dp_write(dp, ZYNQMP_DP_INT_EN, ZYNQMP_DP_INT_ALL);
-
- return 0;
-}
-
-int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
+int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub)
{
struct platform_device *pdev = to_platform_device(dpsub->dev);
+ struct drm_bridge *bridge;
struct zynqmp_dp *dp;
struct resource *res;
int ret;
- dp = drmm_kzalloc(drm, sizeof(*dp), GFP_KERNEL);
+ dp = kzalloc(sizeof(*dp), GFP_KERNEL);
if (!dp)
return -ENOMEM;
dp->dev = &pdev->dev;
dp->dpsub = dpsub;
dp->status = connector_status_disconnected;
- dp->drm = drm;
INIT_DELAYED_WORK(&dp->hpd_work, zynqmp_dp_hpd_work_func);
- dpsub->dp = dp;
-
/* Acquire all resources (IOMEM, IRQ and PHYs). */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dp");
dp->iomem = devm_ioremap_resource(dp->dev, res);
- if (IS_ERR(dp->iomem))
- return PTR_ERR(dp->iomem);
+ if (IS_ERR(dp->iomem)) {
+ ret = PTR_ERR(dp->iomem);
+ goto err_free;
+ }
dp->irq = platform_get_irq(pdev, 0);
- if (dp->irq < 0)
- return dp->irq;
+ if (dp->irq < 0) {
+ ret = dp->irq;
+ goto err_free;
+ }
dp->reset = devm_reset_control_get(dp->dev, NULL);
if (IS_ERR(dp->reset)) {
if (PTR_ERR(dp->reset) != -EPROBE_DEFER)
dev_err(dp->dev, "failed to get reset: %ld\n",
PTR_ERR(dp->reset));
- return PTR_ERR(dp->reset);
+ ret = PTR_ERR(dp->reset);
+ goto err_free;
}
ret = zynqmp_dp_reset(dp, false);
if (ret < 0)
- return ret;
+ goto err_free;
ret = zynqmp_dp_phy_probe(dp);
if (ret)
goto err_reset;
+ /* Initialize the bridge. */
+ bridge = &dp->bridge;
+ bridge->funcs = &zynqmp_dp_bridge_funcs;
+ bridge->ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID
+ | DRM_BRIDGE_OP_HPD;
+ bridge->type = DRM_MODE_CONNECTOR_DisplayPort;
+ dpsub->bridge = bridge;
+
+ /*
+ * Acquire the next bridge in the chain. Ignore errors caused by port@5
+ * not being connected for backward-compatibility with older DTs.
+ */
+ ret = drm_of_find_panel_or_bridge(dp->dev->of_node, 5, 0, NULL,
+ &dp->next_bridge);
+ if (ret < 0 && ret != -ENODEV)
+ goto err_reset;
+
/* Initialize the hardware. */
+ dp->config.misc0 &= ~ZYNQMP_DP_MAIN_STREAM_MISC0_SYNC_LOCK;
+ zynqmp_dp_set_format(dp, NULL, ZYNQMP_DPSUB_FORMAT_RGB, 8);
+
zynqmp_dp_write(dp, ZYNQMP_DP_TX_PHY_POWER_DOWN,
ZYNQMP_DP_TX_PHY_POWER_DOWN_ALL);
zynqmp_dp_set(dp, ZYNQMP_DP_PHY_RESET, ZYNQMP_DP_PHY_RESET_ALL_RESET);
@@ -1710,6 +1759,8 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm)
if (ret < 0)
goto err_phy_exit;
+ dpsub->dp = dp;
+
dev_dbg(dp->dev, "ZynqMP DisplayPort Tx probed with %u lanes\n",
dp->num_lanes);
@@ -1719,7 +1770,8 @@ err_phy_exit:
zynqmp_dp_phy_exit(dp);
err_reset:
zynqmp_dp_reset(dp, true);
-
+err_free:
+ kfree(dp);
return ret;
}
@@ -1731,7 +1783,6 @@ void zynqmp_dp_remove(struct zynqmp_dpsub *dpsub)
disable_irq(dp->irq);
cancel_delayed_work_sync(&dp->hpd_work);
- zynqmp_dp_aux_cleanup(dp);
zynqmp_dp_write(dp, ZYNQMP_DP_TRANSMITTER_ENABLE, 0);
zynqmp_dp_write(dp, ZYNQMP_DP_INT_DS, 0xffffffff);
diff --git a/drivers/gpu/drm/xlnx/zynqmp_dp.h b/drivers/gpu/drm/xlnx/zynqmp_dp.h
index 4507740093f6..f077d7fbd0ad 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dp.h
+++ b/drivers/gpu/drm/xlnx/zynqmp_dp.h
@@ -12,7 +12,6 @@
#ifndef _ZYNQMP_DP_H_
#define _ZYNQMP_DP_H_
-struct drm_device;
struct platform_device;
struct zynqmp_dp;
struct zynqmp_dpsub;
@@ -20,8 +19,7 @@ struct zynqmp_dpsub;
void zynqmp_dp_enable_vblank(struct zynqmp_dp *dp);
void zynqmp_dp_disable_vblank(struct zynqmp_dp *dp);
-int zynqmp_dp_drm_init(struct zynqmp_dpsub *dpsub);
-int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub, struct drm_device *drm);
+int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub);
void zynqmp_dp_remove(struct zynqmp_dpsub *dpsub);
#endif /* _ZYNQMP_DP_H_ */
diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
index 1de2d927c32b..bab862484d42 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
@@ -12,191 +12,217 @@
#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
+#include <linux/of_graph.h>
#include <linux/of_reserved_mem.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/slab.h>
#include <drm/drm_atomic_helper.h>
-#include <drm/drm_device.h>
-#include <drm/drm_drv.h>
-#include <drm/drm_fb_helper.h>
-#include <drm/drm_fourcc.h>
-#include <drm/drm_gem_dma_helper.h>
-#include <drm/drm_gem_framebuffer_helper.h>
-#include <drm/drm_managed.h>
-#include <drm/drm_mode_config.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_modeset_helper.h>
#include <drm/drm_module.h>
-#include <drm/drm_probe_helper.h>
-#include <drm/drm_vblank.h>
#include "zynqmp_disp.h"
#include "zynqmp_dp.h"
#include "zynqmp_dpsub.h"
+#include "zynqmp_kms.h"
/* -----------------------------------------------------------------------------
- * Dumb Buffer & Framebuffer Allocation
+ * Power Management
*/
-static int zynqmp_dpsub_dumb_create(struct drm_file *file_priv,
- struct drm_device *drm,
- struct drm_mode_create_dumb *args)
+static int __maybe_unused zynqmp_dpsub_suspend(struct device *dev)
{
- struct zynqmp_dpsub *dpsub = to_zynqmp_dpsub(drm);
- unsigned int pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+ struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
- /* Enforce the alignment constraints of the DMA engine. */
- args->pitch = ALIGN(pitch, dpsub->dma_align);
+ if (!dpsub->drm)
+ return 0;
- return drm_gem_dma_dumb_create_internal(file_priv, drm, args);
+ return drm_mode_config_helper_suspend(&dpsub->drm->dev);
}
-static struct drm_framebuffer *
-zynqmp_dpsub_fb_create(struct drm_device *drm, struct drm_file *file_priv,
- const struct drm_mode_fb_cmd2 *mode_cmd)
+static int __maybe_unused zynqmp_dpsub_resume(struct device *dev)
{
- struct zynqmp_dpsub *dpsub = to_zynqmp_dpsub(drm);
- struct drm_mode_fb_cmd2 cmd = *mode_cmd;
- unsigned int i;
+ struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
- /* Enforce the alignment constraints of the DMA engine. */
- for (i = 0; i < ARRAY_SIZE(cmd.pitches); ++i)
- cmd.pitches[i] = ALIGN(cmd.pitches[i], dpsub->dma_align);
+ if (!dpsub->drm)
+ return 0;
- return drm_gem_fb_create(drm, file_priv, &cmd);
+ return drm_mode_config_helper_resume(&dpsub->drm->dev);
}
-static const struct drm_mode_config_funcs zynqmp_dpsub_mode_config_funcs = {
- .fb_create = zynqmp_dpsub_fb_create,
- .atomic_check = drm_atomic_helper_check,
- .atomic_commit = drm_atomic_helper_commit,
+static const struct dev_pm_ops zynqmp_dpsub_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(zynqmp_dpsub_suspend, zynqmp_dpsub_resume)
};
/* -----------------------------------------------------------------------------
- * DRM/KMS Driver
+ * DPSUB Configuration
*/
-DEFINE_DRM_GEM_DMA_FOPS(zynqmp_dpsub_drm_fops);
-
-static const struct drm_driver zynqmp_dpsub_drm_driver = {
- .driver_features = DRIVER_MODESET | DRIVER_GEM |
- DRIVER_ATOMIC,
-
- DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(zynqmp_dpsub_dumb_create),
+/**
+ * zynqmp_dpsub_audio_enabled - If the audio is enabled
+ * @dpsub: DisplayPort subsystem
+ *
+ * Return if the audio is enabled depending on the audio clock.
+ *
+ * Return: true if audio is enabled, or false.
+ */
+bool zynqmp_dpsub_audio_enabled(struct zynqmp_dpsub *dpsub)
+{
+ return !!dpsub->aud_clk;
+}
- .fops = &zynqmp_dpsub_drm_fops,
+/**
+ * zynqmp_dpsub_get_audio_clk_rate - Get the current audio clock rate
+ * @dpsub: DisplayPort subsystem
+ *
+ * Return: the current audio clock rate.
+ */
+unsigned int zynqmp_dpsub_get_audio_clk_rate(struct zynqmp_dpsub *dpsub)
+{
+ if (zynqmp_dpsub_audio_enabled(dpsub))
+ return 0;
+ return clk_get_rate(dpsub->aud_clk);
+}
- .name = "zynqmp-dpsub",
- .desc = "Xilinx DisplayPort Subsystem Driver",
- .date = "20130509",
- .major = 1,
- .minor = 0,
-};
+/* -----------------------------------------------------------------------------
+ * Probe & Remove
+ */
-static int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub)
+static int zynqmp_dpsub_init_clocks(struct zynqmp_dpsub *dpsub)
{
- struct drm_device *drm = &dpsub->drm;
int ret;
- /* Initialize mode config, vblank and the KMS poll helper. */
- ret = drmm_mode_config_init(drm);
- if (ret < 0)
- return ret;
-
- drm->mode_config.funcs = &zynqmp_dpsub_mode_config_funcs;
- drm->mode_config.min_width = 0;
- drm->mode_config.min_height = 0;
- drm->mode_config.max_width = ZYNQMP_DISP_MAX_WIDTH;
- drm->mode_config.max_height = ZYNQMP_DISP_MAX_HEIGHT;
+ dpsub->apb_clk = devm_clk_get(dpsub->dev, "dp_apb_clk");
+ if (IS_ERR(dpsub->apb_clk))
+ return PTR_ERR(dpsub->apb_clk);
- ret = drm_vblank_init(drm, 1);
- if (ret)
+ ret = clk_prepare_enable(dpsub->apb_clk);
+ if (ret) {
+ dev_err(dpsub->dev, "failed to enable the APB clock\n");
return ret;
-
- drm_kms_helper_poll_init(drm);
+ }
/*
- * Initialize the DISP and DP components. This will creates planes,
- * CRTC, encoder and connector. The DISP should be initialized first as
- * the DP encoder needs the CRTC.
+ * Try the live PL video clock, and fall back to the PS clock if the
+ * live PL video clock isn't valid.
*/
- ret = zynqmp_disp_drm_init(dpsub);
- if (ret)
- goto err_poll_fini;
-
- ret = zynqmp_dp_drm_init(dpsub);
- if (ret)
- goto err_poll_fini;
-
- /* Reset all components and register the DRM device. */
- drm_mode_config_reset(drm);
+ dpsub->vid_clk = devm_clk_get(dpsub->dev, "dp_live_video_in_clk");
+ if (!IS_ERR(dpsub->vid_clk))
+ dpsub->vid_clk_from_ps = false;
+ else if (PTR_ERR(dpsub->vid_clk) == -EPROBE_DEFER)
+ return PTR_ERR(dpsub->vid_clk);
+
+ if (IS_ERR_OR_NULL(dpsub->vid_clk)) {
+ dpsub->vid_clk = devm_clk_get(dpsub->dev, "dp_vtc_pixel_clk_in");
+ if (IS_ERR(dpsub->vid_clk)) {
+ dev_err(dpsub->dev, "failed to init any video clock\n");
+ return PTR_ERR(dpsub->vid_clk);
+ }
+ dpsub->vid_clk_from_ps = true;
+ }
- ret = drm_dev_register(drm, 0);
- if (ret < 0)
- goto err_poll_fini;
+ /*
+ * Try the live PL audio clock, and fall back to the PS clock if the
+ * live PL audio clock isn't valid. Missing audio clock disables audio
+ * but isn't an error.
+ */
+ dpsub->aud_clk = devm_clk_get(dpsub->dev, "dp_live_audio_aclk");
+ if (!IS_ERR(dpsub->aud_clk)) {
+ dpsub->aud_clk_from_ps = false;
+ return 0;
+ }
- /* Initialize fbdev generic emulation. */
- drm_fbdev_generic_setup(drm, 24);
+ dpsub->aud_clk = devm_clk_get(dpsub->dev, "dp_aud_clk");
+ if (!IS_ERR(dpsub->aud_clk)) {
+ dpsub->aud_clk_from_ps = true;
+ return 0;
+ }
+ dev_info(dpsub->dev, "audio disabled due to missing clock\n");
return 0;
-
-err_poll_fini:
- drm_kms_helper_poll_fini(drm);
- return ret;
}
-/* -----------------------------------------------------------------------------
- * Power Management
- */
-
-static int __maybe_unused zynqmp_dpsub_suspend(struct device *dev)
+static int zynqmp_dpsub_parse_dt(struct zynqmp_dpsub *dpsub)
{
- struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
+ struct device_node *np;
+ unsigned int i;
- return drm_mode_config_helper_suspend(&dpsub->drm);
-}
+ /*
+ * For backward compatibility with old device trees that don't contain
+ * ports, consider that only the DP output port is connected if no
+ * ports child no exists.
+ */
+ np = of_get_child_by_name(dpsub->dev->of_node, "ports");
+ of_node_put(np);
+ if (!np) {
+ dev_warn(dpsub->dev, "missing ports, update DT bindings\n");
+ dpsub->connected_ports = BIT(ZYNQMP_DPSUB_PORT_OUT_DP);
+ dpsub->dma_enabled = true;
+ return 0;
+ }
-static int __maybe_unused zynqmp_dpsub_resume(struct device *dev)
-{
- struct zynqmp_dpsub *dpsub = dev_get_drvdata(dev);
+ /* Check which ports are connected. */
+ for (i = 0; i < ZYNQMP_DPSUB_NUM_PORTS; ++i) {
+ struct device_node *np;
- return drm_mode_config_helper_resume(&dpsub->drm);
-}
+ np = of_graph_get_remote_node(dpsub->dev->of_node, i, -1);
+ if (np) {
+ dpsub->connected_ports |= BIT(i);
+ of_node_put(np);
+ }
+ }
-static const struct dev_pm_ops zynqmp_dpsub_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(zynqmp_dpsub_suspend, zynqmp_dpsub_resume)
-};
+ /* Sanity checks. */
+ if ((dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) &&
+ (dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX))) {
+ dev_err(dpsub->dev, "only one live video input is supported\n");
+ return -EINVAL;
+ }
-/* -----------------------------------------------------------------------------
- * Probe & Remove
- */
+ if ((dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_VIDEO)) ||
+ (dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_GFX))) {
+ if (dpsub->vid_clk_from_ps) {
+ dev_err(dpsub->dev,
+ "live video input requires PL clock\n");
+ return -EINVAL;
+ }
+ } else {
+ dpsub->dma_enabled = true;
+ }
-static int zynqmp_dpsub_init_clocks(struct zynqmp_dpsub *dpsub)
-{
- int ret;
+ if (dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_LIVE_AUDIO))
+ dev_warn(dpsub->dev, "live audio unsupported, ignoring\n");
- dpsub->apb_clk = devm_clk_get(dpsub->dev, "dp_apb_clk");
- if (IS_ERR(dpsub->apb_clk))
- return PTR_ERR(dpsub->apb_clk);
+ if ((dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_OUT_VIDEO)) ||
+ (dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_OUT_AUDIO)))
+ dev_warn(dpsub->dev, "output to PL unsupported, ignoring\n");
- ret = clk_prepare_enable(dpsub->apb_clk);
- if (ret) {
- dev_err(dpsub->dev, "failed to enable the APB clock\n");
- return ret;
+ if (!(dpsub->connected_ports & BIT(ZYNQMP_DPSUB_PORT_OUT_DP))) {
+ dev_err(dpsub->dev, "DP output port not connected\n");
+ return -EINVAL;
}
return 0;
}
+void zynqmp_dpsub_release(struct zynqmp_dpsub *dpsub)
+{
+ kfree(dpsub->disp);
+ kfree(dpsub->dp);
+ kfree(dpsub);
+}
+
static int zynqmp_dpsub_probe(struct platform_device *pdev)
{
struct zynqmp_dpsub *dpsub;
int ret;
/* Allocate private data. */
- dpsub = devm_drm_dev_alloc(&pdev->dev, &zynqmp_dpsub_drm_driver,
- struct zynqmp_dpsub, drm);
- if (IS_ERR(dpsub))
- return PTR_ERR(dpsub);
+ dpsub = kzalloc(sizeof(*dpsub), GFP_KERNEL);
+ if (!dpsub)
+ return -ENOMEM;
dpsub->dev = &pdev->dev;
platform_set_drvdata(pdev, dpsub);
@@ -210,23 +236,31 @@ static int zynqmp_dpsub_probe(struct platform_device *pdev)
if (ret < 0)
goto err_mem;
+ ret = zynqmp_dpsub_parse_dt(dpsub);
+ if (ret < 0)
+ goto err_mem;
+
pm_runtime_enable(&pdev->dev);
/*
* DP should be probed first so that the zynqmp_disp can set the output
* format accordingly.
*/
- ret = zynqmp_dp_probe(dpsub, &dpsub->drm);
+ ret = zynqmp_dp_probe(dpsub);
if (ret)
goto err_pm;
- ret = zynqmp_disp_probe(dpsub, &dpsub->drm);
+ ret = zynqmp_disp_probe(dpsub);
if (ret)
goto err_dp;
- ret = zynqmp_dpsub_drm_init(dpsub);
- if (ret)
- goto err_disp;
+ if (dpsub->dma_enabled) {
+ ret = zynqmp_dpsub_drm_init(dpsub);
+ if (ret)
+ goto err_disp;
+ } else {
+ drm_bridge_add(dpsub->bridge);
+ }
dev_info(&pdev->dev, "ZynqMP DisplayPort Subsystem driver probed");
@@ -241,17 +275,19 @@ err_pm:
clk_disable_unprepare(dpsub->apb_clk);
err_mem:
of_reserved_mem_device_release(&pdev->dev);
+ if (!dpsub->drm)
+ zynqmp_dpsub_release(dpsub);
return ret;
}
static int zynqmp_dpsub_remove(struct platform_device *pdev)
{
struct zynqmp_dpsub *dpsub = platform_get_drvdata(pdev);
- struct drm_device *drm = &dpsub->drm;
- drm_dev_unregister(drm);
- drm_atomic_helper_shutdown(drm);
- drm_kms_helper_poll_fini(drm);
+ if (dpsub->drm)
+ zynqmp_dpsub_drm_cleanup(dpsub);
+ else
+ drm_bridge_remove(dpsub->bridge);
zynqmp_disp_remove(dpsub);
zynqmp_dp_remove(dpsub);
@@ -260,6 +296,9 @@ static int zynqmp_dpsub_remove(struct platform_device *pdev)
clk_disable_unprepare(dpsub->apb_clk);
of_reserved_mem_device_release(&pdev->dev);
+ if (!dpsub->drm)
+ zynqmp_dpsub_release(dpsub);
+
return 0;
}
@@ -267,7 +306,10 @@ static void zynqmp_dpsub_shutdown(struct platform_device *pdev)
{
struct zynqmp_dpsub *dpsub = platform_get_drvdata(pdev);
- drm_atomic_helper_shutdown(&dpsub->drm);
+ if (!dpsub->drm)
+ return;
+
+ drm_atomic_helper_shutdown(&dpsub->drm->dev);
}
static const struct of_device_id zynqmp_dpsub_of_match[] = {
diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.h b/drivers/gpu/drm/xlnx/zynqmp_dpsub.h
index c04026d82639..09ea01878f2a 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.h
+++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.h
@@ -14,9 +14,23 @@
struct clk;
struct device;
-struct drm_device;
+struct drm_bridge;
struct zynqmp_disp;
+struct zynqmp_disp_layer;
struct zynqmp_dp;
+struct zynqmp_dpsub_drm;
+
+#define ZYNQMP_DPSUB_NUM_LAYERS 2
+
+enum zynqmp_dpsub_port {
+ ZYNQMP_DPSUB_PORT_LIVE_VIDEO,
+ ZYNQMP_DPSUB_PORT_LIVE_GFX,
+ ZYNQMP_DPSUB_PORT_LIVE_AUDIO,
+ ZYNQMP_DPSUB_PORT_OUT_VIDEO,
+ ZYNQMP_DPSUB_PORT_OUT_AUDIO,
+ ZYNQMP_DPSUB_PORT_OUT_DP,
+ ZYNQMP_DPSUB_NUM_PORTS,
+};
enum zynqmp_dpsub_format {
ZYNQMP_DPSUB_FORMAT_RGB,
@@ -27,28 +41,46 @@ enum zynqmp_dpsub_format {
/**
* struct zynqmp_dpsub - ZynqMP DisplayPort Subsystem
- * @drm: The DRM/KMS device
* @dev: The physical device
* @apb_clk: The APB clock
+ * @vid_clk: Video clock
+ * @vid_clk_from_ps: True of the video clock comes from PS, false from PL
+ * @aud_clk: Audio clock
+ * @aud_clk_from_ps: True of the audio clock comes from PS, false from PL
+ * @connected_ports: Bitmask of connected ports in the device tree
+ * @dma_enabled: True if the DMA interface is enabled, false if the DPSUB is
+ * driven by the live input
+ * @drm: The DRM/KMS device data
+ * @bridge: The DP encoder bridge
* @disp: The display controller
* @dp: The DisplayPort controller
* @dma_align: DMA alignment constraint (must be a power of 2)
*/
struct zynqmp_dpsub {
- struct drm_device drm;
struct device *dev;
struct clk *apb_clk;
+ struct clk *vid_clk;
+ bool vid_clk_from_ps;
+ struct clk *aud_clk;
+ bool aud_clk_from_ps;
+
+ unsigned int connected_ports;
+ bool dma_enabled;
+
+ struct zynqmp_dpsub_drm *drm;
+ struct drm_bridge *bridge;
struct zynqmp_disp *disp;
+ struct zynqmp_disp_layer *layers[ZYNQMP_DPSUB_NUM_LAYERS];
struct zynqmp_dp *dp;
unsigned int dma_align;
};
-static inline struct zynqmp_dpsub *to_zynqmp_dpsub(struct drm_device *drm)
-{
- return container_of(drm, struct zynqmp_dpsub, drm);
-}
+bool zynqmp_dpsub_audio_enabled(struct zynqmp_dpsub *dpsub);
+unsigned int zynqmp_dpsub_get_audio_clk_rate(struct zynqmp_dpsub *dpsub);
+
+void zynqmp_dpsub_release(struct zynqmp_dpsub *dpsub);
#endif /* _ZYNQMP_DPSUB_H_ */
diff --git a/drivers/gpu/drm/xlnx/zynqmp_kms.c b/drivers/gpu/drm/xlnx/zynqmp_kms.c
new file mode 100644
index 000000000000..776ef5480206
--- /dev/null
+++ b/drivers/gpu/drm/xlnx/zynqmp_kms.c
@@ -0,0 +1,534 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ZynqMP DisplayPort Subsystem - KMS API
+ *
+ * Copyright (C) 2017 - 2021 Xilinx, Inc.
+ *
+ * Authors:
+ * - Hyun Woo Kwon <hyun.kwon@xilinx.com>
+ * - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ */
+
+#include <drm/drm_atomic.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_blend.h>
+#include <drm/drm_bridge.h>
+#include <drm/drm_bridge_connector.h>
+#include <drm/drm_connector.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
+#include <drm/drm_encoder.h>
+#include <drm/drm_fbdev_generic.h>
+#include <drm/drm_fourcc.h>
+#include <drm/drm_framebuffer.h>
+#include <drm/drm_gem_dma_helper.h>
+#include <drm/drm_gem_framebuffer_helper.h>
+#include <drm/drm_managed.h>
+#include <drm/drm_mode_config.h>
+#include <drm/drm_plane.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>
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/pm_runtime.h>
+#include <linux/spinlock.h>
+
+#include "zynqmp_disp.h"
+#include "zynqmp_dp.h"
+#include "zynqmp_dpsub.h"
+#include "zynqmp_kms.h"
+
+static inline struct zynqmp_dpsub *to_zynqmp_dpsub(struct drm_device *drm)
+{
+ return container_of(drm, struct zynqmp_dpsub_drm, dev)->dpsub;
+}
+
+/* -----------------------------------------------------------------------------
+ * DRM Planes
+ */
+
+static int zynqmp_dpsub_plane_atomic_check(struct drm_plane *plane,
+ struct drm_atomic_state *state)
+{
+ struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
+ plane);
+ struct drm_crtc_state *crtc_state;
+
+ if (!new_plane_state->crtc)
+ return 0;
+
+ crtc_state = drm_atomic_get_crtc_state(state, new_plane_state->crtc);
+ if (IS_ERR(crtc_state))
+ return PTR_ERR(crtc_state);
+
+ return drm_atomic_helper_check_plane_state(new_plane_state,
+ crtc_state,
+ DRM_PLANE_NO_SCALING,
+ DRM_PLANE_NO_SCALING,
+ false, false);
+}
+
+static void zynqmp_dpsub_plane_atomic_disable(struct drm_plane *plane,
+ struct drm_atomic_state *state)
+{
+ struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state,
+ plane);
+ struct zynqmp_dpsub *dpsub = to_zynqmp_dpsub(plane->dev);
+ struct zynqmp_disp_layer *layer = dpsub->layers[plane->index];
+
+ if (!old_state->fb)
+ return;
+
+ zynqmp_disp_layer_disable(layer);
+
+ if (plane->index == ZYNQMP_DPSUB_LAYER_GFX)
+ zynqmp_disp_blend_set_global_alpha(dpsub->disp, false,
+ plane->state->alpha >> 8);
+}
+
+static void zynqmp_dpsub_plane_atomic_update(struct drm_plane *plane,
+ struct drm_atomic_state *state)
+{
+ struct drm_plane_state *old_state = drm_atomic_get_old_plane_state(state, plane);
+ struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, plane);
+ struct zynqmp_dpsub *dpsub = to_zynqmp_dpsub(plane->dev);
+ struct zynqmp_disp_layer *layer = dpsub->layers[plane->index];
+ bool format_changed = false;
+
+ if (!old_state->fb ||
+ old_state->fb->format->format != new_state->fb->format->format)
+ format_changed = true;
+
+ /*
+ * If the format has changed (including going from a previously
+ * disabled state to any format), reconfigure the format. Disable the
+ * plane first if needed.
+ */
+ if (format_changed) {
+ if (old_state->fb)
+ zynqmp_disp_layer_disable(layer);
+
+ zynqmp_disp_layer_set_format(layer, new_state->fb->format);
+ }
+
+ zynqmp_disp_layer_update(layer, new_state);
+
+ if (plane->index == ZYNQMP_DPSUB_LAYER_GFX)
+ zynqmp_disp_blend_set_global_alpha(dpsub->disp, true,
+ plane->state->alpha >> 8);
+
+ /* Enable or re-enable the plane if the format has changed. */
+ if (format_changed)
+ zynqmp_disp_layer_enable(layer, ZYNQMP_DPSUB_LAYER_NONLIVE);
+}
+
+static const struct drm_plane_helper_funcs zynqmp_dpsub_plane_helper_funcs = {
+ .atomic_check = zynqmp_dpsub_plane_atomic_check,
+ .atomic_update = zynqmp_dpsub_plane_atomic_update,
+ .atomic_disable = zynqmp_dpsub_plane_atomic_disable,
+};
+
+static const struct drm_plane_funcs zynqmp_dpsub_plane_funcs = {
+ .update_plane = drm_atomic_helper_update_plane,
+ .disable_plane = drm_atomic_helper_disable_plane,
+ .destroy = drm_plane_cleanup,
+ .reset = drm_atomic_helper_plane_reset,
+ .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
+};
+
+static int zynqmp_dpsub_create_planes(struct zynqmp_dpsub *dpsub)
+{
+ unsigned int i;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(dpsub->drm->planes); i++) {
+ struct zynqmp_disp_layer *layer = dpsub->layers[i];
+ struct drm_plane *plane = &dpsub->drm->planes[i];
+ enum drm_plane_type type;
+ unsigned int num_formats;
+ u32 *formats;
+
+ formats = zynqmp_disp_layer_drm_formats(layer, &num_formats);
+ if (!formats)
+ return -ENOMEM;
+
+ /* Graphics layer is primary, and video layer is overlay. */
+ type = i == ZYNQMP_DPSUB_LAYER_VID
+ ? DRM_PLANE_TYPE_OVERLAY : DRM_PLANE_TYPE_PRIMARY;
+ ret = drm_universal_plane_init(&dpsub->drm->dev, plane, 0,
+ &zynqmp_dpsub_plane_funcs,
+ formats, num_formats,
+ NULL, type, NULL);
+ kfree(formats);
+ if (ret)
+ return ret;
+
+ drm_plane_helper_add(plane, &zynqmp_dpsub_plane_helper_funcs);
+
+ drm_plane_create_zpos_immutable_property(plane, i);
+ if (i == ZYNQMP_DPSUB_LAYER_GFX)
+ drm_plane_create_alpha_property(plane);
+ }
+
+ return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * DRM CRTC
+ */
+
+static inline struct zynqmp_dpsub *crtc_to_dpsub(struct drm_crtc *crtc)
+{
+ return container_of(crtc, struct zynqmp_dpsub_drm, crtc)->dpsub;
+}
+
+static void zynqmp_dpsub_crtc_atomic_enable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ struct zynqmp_dpsub *dpsub = crtc_to_dpsub(crtc);
+ struct drm_display_mode *adjusted_mode = &crtc->state->adjusted_mode;
+ int ret, vrefresh;
+
+ pm_runtime_get_sync(dpsub->dev);
+
+ zynqmp_disp_setup_clock(dpsub->disp, adjusted_mode->clock * 1000);
+
+ ret = clk_prepare_enable(dpsub->vid_clk);
+ if (ret) {
+ dev_err(dpsub->dev, "failed to enable a pixel clock\n");
+ pm_runtime_put_sync(dpsub->dev);
+ return;
+ }
+
+ zynqmp_disp_enable(dpsub->disp);
+
+ /* Delay of 3 vblank intervals for timing gen to be stable */
+ vrefresh = (adjusted_mode->clock * 1000) /
+ (adjusted_mode->vtotal * adjusted_mode->htotal);
+ msleep(3 * 1000 / vrefresh);
+}
+
+static void zynqmp_dpsub_crtc_atomic_disable(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ struct zynqmp_dpsub *dpsub = crtc_to_dpsub(crtc);
+ struct drm_plane_state *old_plane_state;
+
+ /*
+ * Disable the plane if active. The old plane state can be NULL in the
+ * .shutdown() path if the plane is already disabled, skip
+ * zynqmp_disp_plane_atomic_disable() in that case.
+ */
+ old_plane_state = drm_atomic_get_old_plane_state(state, crtc->primary);
+ if (old_plane_state)
+ zynqmp_dpsub_plane_atomic_disable(crtc->primary, state);
+
+ zynqmp_disp_disable(dpsub->disp);
+
+ drm_crtc_vblank_off(crtc);
+
+ spin_lock_irq(&crtc->dev->event_lock);
+ if (crtc->state->event) {
+ drm_crtc_send_vblank_event(crtc, crtc->state->event);
+ crtc->state->event = NULL;
+ }
+ spin_unlock_irq(&crtc->dev->event_lock);
+
+ clk_disable_unprepare(dpsub->vid_clk);
+ pm_runtime_put_sync(dpsub->dev);
+}
+
+static int zynqmp_dpsub_crtc_atomic_check(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ return drm_atomic_add_affected_planes(state, crtc);
+}
+
+static void zynqmp_dpsub_crtc_atomic_begin(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ drm_crtc_vblank_on(crtc);
+}
+
+static void zynqmp_dpsub_crtc_atomic_flush(struct drm_crtc *crtc,
+ struct drm_atomic_state *state)
+{
+ if (crtc->state->event) {
+ struct drm_pending_vblank_event *event;
+
+ /* Consume the flip_done event from atomic helper. */
+ event = crtc->state->event;
+ crtc->state->event = NULL;
+
+ event->pipe = drm_crtc_index(crtc);
+
+ WARN_ON(drm_crtc_vblank_get(crtc) != 0);
+
+ spin_lock_irq(&crtc->dev->event_lock);
+ drm_crtc_arm_vblank_event(crtc, event);
+ spin_unlock_irq(&crtc->dev->event_lock);
+ }
+}
+
+static const struct drm_crtc_helper_funcs zynqmp_dpsub_crtc_helper_funcs = {
+ .atomic_enable = zynqmp_dpsub_crtc_atomic_enable,
+ .atomic_disable = zynqmp_dpsub_crtc_atomic_disable,
+ .atomic_check = zynqmp_dpsub_crtc_atomic_check,
+ .atomic_begin = zynqmp_dpsub_crtc_atomic_begin,
+ .atomic_flush = zynqmp_dpsub_crtc_atomic_flush,
+};
+
+static int zynqmp_dpsub_crtc_enable_vblank(struct drm_crtc *crtc)
+{
+ struct zynqmp_dpsub *dpsub = crtc_to_dpsub(crtc);
+
+ zynqmp_dp_enable_vblank(dpsub->dp);
+
+ return 0;
+}
+
+static void zynqmp_dpsub_crtc_disable_vblank(struct drm_crtc *crtc)
+{
+ struct zynqmp_dpsub *dpsub = crtc_to_dpsub(crtc);
+
+ zynqmp_dp_disable_vblank(dpsub->dp);
+}
+
+static const struct drm_crtc_funcs zynqmp_dpsub_crtc_funcs = {
+ .destroy = drm_crtc_cleanup,
+ .set_config = drm_atomic_helper_set_config,
+ .page_flip = drm_atomic_helper_page_flip,
+ .reset = drm_atomic_helper_crtc_reset,
+ .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
+ .enable_vblank = zynqmp_dpsub_crtc_enable_vblank,
+ .disable_vblank = zynqmp_dpsub_crtc_disable_vblank,
+};
+
+static int zynqmp_dpsub_create_crtc(struct zynqmp_dpsub *dpsub)
+{
+ struct drm_plane *plane = &dpsub->drm->planes[ZYNQMP_DPSUB_LAYER_GFX];
+ struct drm_crtc *crtc = &dpsub->drm->crtc;
+ int ret;
+
+ ret = drm_crtc_init_with_planes(&dpsub->drm->dev, crtc, plane,
+ NULL, &zynqmp_dpsub_crtc_funcs, NULL);
+ if (ret < 0)
+ return ret;
+
+ drm_crtc_helper_add(crtc, &zynqmp_dpsub_crtc_helper_funcs);
+
+ /* Start with vertical blanking interrupt reporting disabled. */
+ drm_crtc_vblank_off(crtc);
+
+ return 0;
+}
+
+static void zynqmp_dpsub_map_crtc_to_plane(struct zynqmp_dpsub *dpsub)
+{
+ u32 possible_crtcs = drm_crtc_mask(&dpsub->drm->crtc);
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(dpsub->drm->planes); i++)
+ dpsub->drm->planes[i].possible_crtcs = possible_crtcs;
+}
+
+/**
+ * zynqmp_dpsub_drm_handle_vblank - Handle the vblank event
+ * @dpsub: DisplayPort subsystem
+ *
+ * This function handles the vblank interrupt, and sends an event to
+ * CRTC object. This will be called by the DP vblank interrupt handler.
+ */
+void zynqmp_dpsub_drm_handle_vblank(struct zynqmp_dpsub *dpsub)
+{
+ drm_crtc_handle_vblank(&dpsub->drm->crtc);
+}
+
+/* -----------------------------------------------------------------------------
+ * Dumb Buffer & Framebuffer Allocation
+ */
+
+static int zynqmp_dpsub_dumb_create(struct drm_file *file_priv,
+ struct drm_device *drm,
+ struct drm_mode_create_dumb *args)
+{
+ struct zynqmp_dpsub *dpsub = to_zynqmp_dpsub(drm);
+ unsigned int pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
+
+ /* Enforce the alignment constraints of the DMA engine. */
+ args->pitch = ALIGN(pitch, dpsub->dma_align);
+
+ return drm_gem_dma_dumb_create_internal(file_priv, drm, args);
+}
+
+static struct drm_framebuffer *
+zynqmp_dpsub_fb_create(struct drm_device *drm, struct drm_file *file_priv,
+ const struct drm_mode_fb_cmd2 *mode_cmd)
+{
+ struct zynqmp_dpsub *dpsub = to_zynqmp_dpsub(drm);
+ struct drm_mode_fb_cmd2 cmd = *mode_cmd;
+ unsigned int i;
+
+ /* Enforce the alignment constraints of the DMA engine. */
+ for (i = 0; i < ARRAY_SIZE(cmd.pitches); ++i)
+ cmd.pitches[i] = ALIGN(cmd.pitches[i], dpsub->dma_align);
+
+ return drm_gem_fb_create(drm, file_priv, &cmd);
+}
+
+static const struct drm_mode_config_funcs zynqmp_dpsub_mode_config_funcs = {
+ .fb_create = zynqmp_dpsub_fb_create,
+ .atomic_check = drm_atomic_helper_check,
+ .atomic_commit = drm_atomic_helper_commit,
+};
+
+/* -----------------------------------------------------------------------------
+ * DRM/KMS Driver
+ */
+
+DEFINE_DRM_GEM_DMA_FOPS(zynqmp_dpsub_drm_fops);
+
+static const struct drm_driver zynqmp_dpsub_drm_driver = {
+ .driver_features = DRIVER_MODESET | DRIVER_GEM |
+ DRIVER_ATOMIC,
+
+ DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(zynqmp_dpsub_dumb_create),
+
+ .fops = &zynqmp_dpsub_drm_fops,
+
+ .name = "zynqmp-dpsub",
+ .desc = "Xilinx DisplayPort Subsystem Driver",
+ .date = "20130509",
+ .major = 1,
+ .minor = 0,
+};
+
+static int zynqmp_dpsub_kms_init(struct zynqmp_dpsub *dpsub)
+{
+ struct drm_encoder *encoder = &dpsub->drm->encoder;
+ struct drm_connector *connector;
+ int ret;
+
+ /* Create the planes and the CRTC. */
+ ret = zynqmp_dpsub_create_planes(dpsub);
+ if (ret)
+ return ret;
+
+ ret = zynqmp_dpsub_create_crtc(dpsub);
+ if (ret < 0)
+ return ret;
+
+ zynqmp_dpsub_map_crtc_to_plane(dpsub);
+
+ /* Create the encoder and attach the bridge. */
+ encoder->possible_crtcs |= drm_crtc_mask(&dpsub->drm->crtc);
+ drm_simple_encoder_init(&dpsub->drm->dev, encoder, DRM_MODE_ENCODER_NONE);
+
+ ret = drm_bridge_attach(encoder, dpsub->bridge, NULL,
+ DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+ if (ret) {
+ dev_err(dpsub->dev, "failed to attach bridge to encoder\n");
+ return ret;
+ }
+
+ /* Create the connector for the chain of bridges. */
+ connector = drm_bridge_connector_init(&dpsub->drm->dev, encoder);
+ if (IS_ERR(connector)) {
+ dev_err(dpsub->dev, "failed to created connector\n");
+ return PTR_ERR(connector);
+ }
+
+ ret = drm_connector_attach_encoder(connector, encoder);
+ if (ret < 0) {
+ dev_err(dpsub->dev, "failed to attach connector to encoder\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static void zynqmp_dpsub_drm_release(struct drm_device *drm, void *res)
+{
+ struct zynqmp_dpsub_drm *dpdrm = res;
+
+ zynqmp_dpsub_release(dpdrm->dpsub);
+}
+
+int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub)
+{
+ struct zynqmp_dpsub_drm *dpdrm;
+ struct drm_device *drm;
+ int ret;
+
+ /*
+ * Allocate the drm_device and immediately add a cleanup action to
+ * release the zynqmp_dpsub instance. If any of those operations fail,
+ * dpsub->drm will remain NULL, which tells the caller that it must
+ * cleanup manually.
+ */
+ dpdrm = devm_drm_dev_alloc(dpsub->dev, &zynqmp_dpsub_drm_driver,
+ struct zynqmp_dpsub_drm, dev);
+ if (IS_ERR(dpdrm))
+ return PTR_ERR(dpdrm);
+
+ dpdrm->dpsub = dpsub;
+ drm = &dpdrm->dev;
+
+ ret = drmm_add_action(drm, zynqmp_dpsub_drm_release, dpdrm);
+ if (ret < 0)
+ return ret;
+
+ dpsub->drm = dpdrm;
+
+ /* Initialize mode config, vblank and the KMS poll helper. */
+ ret = drmm_mode_config_init(drm);
+ if (ret < 0)
+ return ret;
+
+ drm->mode_config.funcs = &zynqmp_dpsub_mode_config_funcs;
+ drm->mode_config.min_width = 0;
+ drm->mode_config.min_height = 0;
+ drm->mode_config.max_width = ZYNQMP_DISP_MAX_WIDTH;
+ drm->mode_config.max_height = ZYNQMP_DISP_MAX_HEIGHT;
+
+ ret = drm_vblank_init(drm, 1);
+ if (ret)
+ return ret;
+
+ drm_kms_helper_poll_init(drm);
+
+ ret = zynqmp_dpsub_kms_init(dpsub);
+ if (ret < 0)
+ goto err_poll_fini;
+
+ /* Reset all components and register the DRM device. */
+ drm_mode_config_reset(drm);
+
+ ret = drm_dev_register(drm, 0);
+ if (ret < 0)
+ goto err_poll_fini;
+
+ /* Initialize fbdev generic emulation. */
+ drm_fbdev_generic_setup(drm, 24);
+
+ return 0;
+
+err_poll_fini:
+ drm_kms_helper_poll_fini(drm);
+ return ret;
+}
+
+void zynqmp_dpsub_drm_cleanup(struct zynqmp_dpsub *dpsub)
+{
+ struct drm_device *drm = &dpsub->drm->dev;
+
+ drm_dev_unregister(drm);
+ drm_atomic_helper_shutdown(drm);
+ drm_kms_helper_poll_fini(drm);
+}
diff --git a/drivers/gpu/drm/xlnx/zynqmp_kms.h b/drivers/gpu/drm/xlnx/zynqmp_kms.h
new file mode 100644
index 000000000000..01be96b00e3f
--- /dev/null
+++ b/drivers/gpu/drm/xlnx/zynqmp_kms.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * ZynqMP DisplayPort Subsystem - KMS API
+ *
+ * Copyright (C) 2017 - 2021 Xilinx, Inc.
+ *
+ * Authors:
+ * - Hyun Woo Kwon <hyun.kwon@xilinx.com>
+ * - Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ */
+
+#ifndef _ZYNQMP_KMS_H_
+#define _ZYNQMP_KMS_H_
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_device.h>
+#include <drm/drm_encoder.h>
+#include <drm/drm_plane.h>
+
+#include "zynqmp_dpsub.h"
+
+struct zynqmp_dpsub;
+
+/**
+ * struct zynqmp_dpsub - ZynqMP DisplayPort Subsystem DRM/KMS data
+ * @dpsub: Backpointer to the DisplayPort subsystem
+ * @drm: The DRM/KMS device
+ * @planes: The DRM planes
+ * @crtc: The DRM CRTC
+ * @encoder: The dummy DRM encoder
+ */
+struct zynqmp_dpsub_drm {
+ struct zynqmp_dpsub *dpsub;
+
+ struct drm_device dev;
+ struct drm_plane planes[ZYNQMP_DPSUB_NUM_LAYERS];
+ struct drm_crtc crtc;
+ struct drm_encoder encoder;
+};
+
+void zynqmp_dpsub_drm_handle_vblank(struct zynqmp_dpsub *dpsub);
+
+int zynqmp_dpsub_drm_init(struct zynqmp_dpsub *dpsub);
+void zynqmp_dpsub_drm_cleanup(struct zynqmp_dpsub *dpsub);
+
+#endif /* _ZYNQMP_KMS_H_ */
diff --git a/drivers/gpu/host1x/context.c b/drivers/gpu/host1x/context.c
index b08cf11f9a66..c8e7994c2c9c 100644
--- a/drivers/gpu/host1x/context.c
+++ b/drivers/gpu/host1x/context.c
@@ -104,6 +104,7 @@ void host1x_memory_context_list_free(struct host1x_memory_context_list *cdl)
}
struct host1x_memory_context *host1x_memory_context_alloc(struct host1x *host1x,
+ struct device *dev,
struct pid *pid)
{
struct host1x_memory_context_list *cdl = &host1x->context_list;
@@ -118,6 +119,9 @@ struct host1x_memory_context *host1x_memory_context_alloc(struct host1x *host1x,
for (i = 0; i < cdl->len; i++) {
struct host1x_memory_context *cd = &cdl->devs[i];
+ if (cd->dev.iommu->iommu_dev != dev->iommu->iommu_dev)
+ continue;
+
if (cd->owner == pid) {
refcount_inc(&cd->ref);
mutex_unlock(&cdl->lock);
diff --git a/drivers/gpu/host1x/debug.c b/drivers/gpu/host1x/debug.c
index 34c2e36d09e9..6649b04b7131 100644
--- a/drivers/gpu/host1x/debug.c
+++ b/drivers/gpu/host1x/debug.c
@@ -140,7 +140,7 @@ static void show_all(struct host1x *m, struct output *o, bool show_fifo)
}
}
-static int host1x_debug_show_all(struct seq_file *s, void *unused)
+static int host1x_debug_all_show(struct seq_file *s, void *unused)
{
struct output o = {
.fn = write_to_seqfile,
@@ -151,6 +151,7 @@ static int host1x_debug_show_all(struct seq_file *s, void *unused)
return 0;
}
+DEFINE_SHOW_ATTRIBUTE(host1x_debug_all);
static int host1x_debug_show(struct seq_file *s, void *unused)
{
@@ -163,30 +164,7 @@ static int host1x_debug_show(struct seq_file *s, void *unused)
return 0;
}
-
-static int host1x_debug_open_all(struct inode *inode, struct file *file)
-{
- return single_open(file, host1x_debug_show_all, inode->i_private);
-}
-
-static const struct file_operations host1x_debug_all_fops = {
- .open = host1x_debug_open_all,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static int host1x_debug_open(struct inode *inode, struct file *file)
-{
- return single_open(file, host1x_debug_show, inode->i_private);
-}
-
-static const struct file_operations host1x_debug_fops = {
- .open = host1x_debug_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
+DEFINE_SHOW_ATTRIBUTE(host1x_debug);
static void host1x_debugfs_init(struct host1x *host1x)
{
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index f60ea24db0ec..f31039aca03c 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -225,6 +225,18 @@ static const struct host1x_sid_entry tegra234_sid_table[] = {
.offset = 0x34,
.limit = 0x34
},
+ {
+ /* NVDEC channel */
+ .base = 0x17c8,
+ .offset = 0x30,
+ .limit = 0x30,
+ },
+ {
+ /* NVDEC MMIO */
+ .base = 0x1698,
+ .offset = 0x34,
+ .limit = 0x34,
+ },
};
static const struct host1x_info host1x08_info = {
diff --git a/drivers/gpu/host1x/fence.c b/drivers/gpu/host1x/fence.c
index ecab72882192..df428bcbae69 100644
--- a/drivers/gpu/host1x/fence.c
+++ b/drivers/gpu/host1x/fence.c
@@ -99,7 +99,7 @@ static void host1x_syncpt_fence_release(struct dma_fence *f)
dma_fence_free(f);
}
-const struct dma_fence_ops host1x_syncpt_fence_ops = {
+static const struct dma_fence_ops host1x_syncpt_fence_ops = {
.get_driver_name = host1x_syncpt_fence_get_driver_name,
.get_timeline_name = host1x_syncpt_fence_get_timeline_name,
.enable_signaling = host1x_syncpt_fence_enable_signaling,
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 185a077d59cd..17cce4c50e8d 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -1252,7 +1252,8 @@ config HID_ALPS
config HID_MCP2221
tristate "Microchip MCP2221 HID USB-to-I2C/SMbus host support"
depends on USB_HID && I2C
- depends on GPIOLIB
+ imply GPIOLIB
+ imply IIO
help
Provides I2C and SMBUS host adapter functionality over USB-HID
through MCP2221 device.
diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c
index db146d0f7937..669d769ea1dc 100644
--- a/drivers/hid/hid-alps.c
+++ b/drivers/hid/hid-alps.c
@@ -820,11 +820,6 @@ static int alps_probe(struct hid_device *hdev, const struct hid_device_id *id)
return 0;
}
-static void alps_remove(struct hid_device *hdev)
-{
- hid_hw_stop(hdev);
-}
-
static const struct hid_device_id alps_id[] = {
{ HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY,
USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_DUAL) },
@@ -842,7 +837,6 @@ static struct hid_driver alps_driver = {
.name = "hid-alps",
.id_table = alps_id,
.probe = alps_probe,
- .remove = alps_remove,
.raw_event = alps_raw_event,
.input_mapping = alps_input_mapping,
.input_configured = alps_input_configured,
diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c
index 6970797cdc56..1ccab8aa326c 100644
--- a/drivers/hid/hid-apple.c
+++ b/drivers/hid/hid-apple.c
@@ -59,6 +59,12 @@ MODULE_PARM_DESC(swap_opt_cmd, "Swap the Option (\"Alt\") and Command (\"Flag\")
"(For people who want to keep Windows PC keyboard muscle memory. "
"[0] = as-is, Mac layout. 1 = swapped, Windows layout.)");
+static unsigned int swap_ctrl_cmd;
+module_param(swap_ctrl_cmd, uint, 0644);
+MODULE_PARM_DESC(swap_ctrl_cmd, "Swap the Control (\"Ctrl\") and Command (\"Flag\") keys. "
+ "(For people who are used to Mac shortcuts involving Command instead of Control. "
+ "[0] = No change. 1 = Swapped.)");
+
static unsigned int swap_fn_leftctrl;
module_param(swap_fn_leftctrl, uint, 0644);
MODULE_PARM_DESC(swap_fn_leftctrl, "Swap the Fn and left Control keys. "
@@ -308,12 +314,21 @@ static const struct apple_key_translation swapped_option_cmd_keys[] = {
{ KEY_LEFTALT, KEY_LEFTMETA },
{ KEY_LEFTMETA, KEY_LEFTALT },
{ KEY_RIGHTALT, KEY_RIGHTMETA },
- { KEY_RIGHTMETA,KEY_RIGHTALT },
+ { KEY_RIGHTMETA, KEY_RIGHTALT },
+ { }
+};
+
+static const struct apple_key_translation swapped_ctrl_cmd_keys[] = {
+ { KEY_LEFTCTRL, KEY_LEFTMETA },
+ { KEY_LEFTMETA, KEY_LEFTCTRL },
+ { KEY_RIGHTCTRL, KEY_RIGHTMETA },
+ { KEY_RIGHTMETA, KEY_RIGHTCTRL },
{ }
};
static const struct apple_key_translation swapped_fn_leftctrl_keys[] = {
{ KEY_FN, KEY_LEFTCTRL },
+ { KEY_LEFTCTRL, KEY_FN },
{ }
};
@@ -375,24 +390,47 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
struct apple_sc *asc = hid_get_drvdata(hid);
const struct apple_key_translation *trans, *table;
bool do_translate;
- u16 code = 0;
+ u16 code = usage->code;
unsigned int real_fnmode;
- u16 fn_keycode = (swap_fn_leftctrl) ? (KEY_LEFTCTRL) : (KEY_FN);
-
- if (usage->code == fn_keycode) {
- asc->fn_on = !!value;
- input_event_with_scancode(input, usage->type, KEY_FN,
- usage->hid, value);
- return 1;
- }
-
if (fnmode == 3) {
real_fnmode = (asc->quirks & APPLE_IS_NON_APPLE) ? 2 : 1;
} else {
real_fnmode = fnmode;
}
+ if (swap_fn_leftctrl) {
+ trans = apple_find_translation(swapped_fn_leftctrl_keys, code);
+
+ if (trans)
+ code = trans->to;
+ }
+
+ if (iso_layout > 0 || (iso_layout < 0 && (asc->quirks & APPLE_ISO_TILDE_QUIRK) &&
+ hid->country == HID_COUNTRY_INTERNATIONAL_ISO)) {
+ trans = apple_find_translation(apple_iso_keyboard, code);
+
+ if (trans)
+ code = trans->to;
+ }
+
+ if (swap_opt_cmd) {
+ trans = apple_find_translation(swapped_option_cmd_keys, code);
+
+ if (trans)
+ code = trans->to;
+ }
+
+ if (swap_ctrl_cmd) {
+ trans = apple_find_translation(swapped_ctrl_cmd_keys, code);
+
+ if (trans)
+ code = trans->to;
+ }
+
+ if (code == KEY_FN)
+ asc->fn_on = !!value;
+
if (real_fnmode) {
if (hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI ||
hid->product == USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO ||
@@ -430,15 +468,18 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
else
table = apple_fn_keys;
- trans = apple_find_translation (table, usage->code);
+ trans = apple_find_translation(table, code);
if (trans) {
- if (test_bit(trans->from, input->key))
+ bool from_is_set = test_bit(trans->from, input->key);
+ bool to_is_set = test_bit(trans->to, input->key);
+
+ if (from_is_set)
code = trans->from;
- else if (test_bit(trans->to, input->key))
+ else if (to_is_set)
code = trans->to;
- if (!code) {
+ if (!(from_is_set || to_is_set)) {
if (trans->flags & APPLE_FLAG_FKEY) {
switch (real_fnmode) {
case 1:
@@ -455,62 +496,31 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
do_translate = asc->fn_on;
}
- code = do_translate ? trans->to : trans->from;
+ if (do_translate)
+ code = trans->to;
}
-
- input_event_with_scancode(input, usage->type, code,
- usage->hid, value);
- return 1;
}
if (asc->quirks & APPLE_NUMLOCK_EMULATION &&
- (test_bit(usage->code, asc->pressed_numlock) ||
+ (test_bit(code, asc->pressed_numlock) ||
test_bit(LED_NUML, input->led))) {
- trans = apple_find_translation(powerbook_numlock_keys,
- usage->code);
+ trans = apple_find_translation(powerbook_numlock_keys, code);
if (trans) {
if (value)
- set_bit(usage->code,
- asc->pressed_numlock);
+ set_bit(code, asc->pressed_numlock);
else
- clear_bit(usage->code,
- asc->pressed_numlock);
+ clear_bit(code, asc->pressed_numlock);
- input_event_with_scancode(input, usage->type,
- trans->to, usage->hid, value);
+ code = trans->to;
}
-
- return 1;
- }
- }
-
- if (iso_layout > 0 || (iso_layout < 0 && (asc->quirks & APPLE_ISO_TILDE_QUIRK) &&
- hid->country == HID_COUNTRY_INTERNATIONAL_ISO)) {
- trans = apple_find_translation(apple_iso_keyboard, usage->code);
- if (trans) {
- input_event_with_scancode(input, usage->type,
- trans->to, usage->hid, value);
- return 1;
}
}
- if (swap_opt_cmd) {
- trans = apple_find_translation(swapped_option_cmd_keys, usage->code);
- if (trans) {
- input_event_with_scancode(input, usage->type,
- trans->to, usage->hid, value);
- return 1;
- }
- }
+ if (usage->code != code) {
+ input_event_with_scancode(input, usage->type, code, usage->hid, value);
- if (swap_fn_leftctrl) {
- trans = apple_find_translation(swapped_fn_leftctrl_keys, usage->code);
- if (trans) {
- input_event_with_scancode(input, usage->type,
- trans->to, usage->hid, value);
- return 1;
- }
+ return 1;
}
return 0;
@@ -640,9 +650,6 @@ static void apple_setup_input(struct input_dev *input)
apple_setup_key_translation(input, apple2021_fn_keys);
apple_setup_key_translation(input, macbookpro_no_esc_fn_keys);
apple_setup_key_translation(input, macbookpro_dedicated_esc_fn_keys);
-
- if (swap_fn_leftctrl)
- apple_setup_key_translation(input, swapped_fn_leftctrl_keys);
}
static int apple_input_mapping(struct hid_device *hdev, struct hid_input *hi,
@@ -1011,21 +1018,21 @@ static const struct hid_device_id apple_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING9_JIS),
.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J140K),
- .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL },
+ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J132),
- .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL },
+ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J680),
- .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL },
+ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J213),
- .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL },
+ .driver_data = APPLE_HAS_FN | APPLE_BACKLIGHT_CTL | APPLE_ISO_TILDE_QUIRK },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J214K),
- .driver_data = APPLE_HAS_FN },
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J223),
- .driver_data = APPLE_HAS_FN },
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J230K),
- .driver_data = APPLE_HAS_FN },
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRINGT2_J152F),
- .driver_data = APPLE_HAS_FN },
+ .driver_data = APPLE_HAS_FN | APPLE_ISO_TILDE_QUIRK },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c
index 2ca6ab600bc9..e213bdde543a 100644
--- a/drivers/hid/hid-debug.c
+++ b/drivers/hid/hid-debug.c
@@ -971,6 +971,9 @@ static const char *keys[KEY_MAX + 1] = {
[KEY_ASSISTANT] = "Assistant",
[KEY_KBD_LAYOUT_NEXT] = "KbdLayoutNext",
[KEY_EMOJI_PICKER] = "EmojiPicker",
+ [KEY_CAMERA_ACCESS_ENABLE] = "CameraAccessEnable",
+ [KEY_CAMERA_ACCESS_DISABLE] = "CameraAccessDisable",
+ [KEY_CAMERA_ACCESS_TOGGLE] = "CameraAccessToggle",
[KEY_DICTATE] = "Dictate",
[KEY_BRIGHTNESS_MIN] = "BrightnessMin",
[KEY_BRIGHTNESS_MAX] = "BrightnessMax",
diff --git a/drivers/hid/hid-elan.c b/drivers/hid/hid-elan.c
index 8e4a5528e25d..76d93fc48f6a 100644
--- a/drivers/hid/hid-elan.c
+++ b/drivers/hid/hid-elan.c
@@ -507,11 +507,6 @@ err:
return ret;
}
-static void elan_remove(struct hid_device *hdev)
-{
- hid_hw_stop(hdev);
-}
-
static const struct hid_device_id elan_devices[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_HP_X2),
.driver_data = ELAN_HAS_LED },
@@ -529,7 +524,6 @@ static struct hid_driver elan_driver = {
.input_configured = elan_input_configured,
.raw_event = elan_raw_event,
.probe = elan_probe,
- .remove = elan_remove,
};
module_hid_driver(elan_driver);
diff --git a/drivers/hid/hid-ft260.c b/drivers/hid/hid-ft260.c
index 79505c64dbfe..333341e80b0e 100644
--- a/drivers/hid/hid-ft260.c
+++ b/drivers/hid/hid-ft260.c
@@ -30,12 +30,21 @@ MODULE_PARM_DESC(debug, "Toggle FT260 debugging messages");
#define FT260_REPORT_MAX_LENGTH (64)
#define FT260_I2C_DATA_REPORT_ID(len) (FT260_I2C_REPORT_MIN + (len - 1) / 4)
+
+#define FT260_WAKEUP_NEEDED_AFTER_MS (4800) /* 5s minus 200ms margin */
+
/*
- * The input report format assigns 62 bytes for the data payload, but ft260
- * returns 60 and 2 in two separate transactions. To minimize transfer time
- * in reading chunks mode, set the maximum read payload length to 60 bytes.
- */
-#define FT260_RD_DATA_MAX (60)
+ * The ft260 input report format defines 62 bytes for the data payload, but
+ * when requested 62 bytes, the controller returns 60 and 2 in separate input
+ * reports. To achieve better performance with the multi-report read data
+ * transfers, we set the maximum read payload length to a multiple of 60.
+ * With a 100 kHz I2C clock, one 240 bytes read takes about 1/27 second,
+ * which is excessive; On the other hand, some higher layer drivers like at24
+ * or optoe limit the i2c reads to 128 bytes. To not block other drivers out
+ * of I2C for potentially troublesome amounts of time, we select the maximum
+ * read payload length to be 180 bytes.
+*/
+#define FT260_RD_DATA_MAX (180)
#define FT260_WR_DATA_MAX (60)
/*
@@ -230,6 +239,7 @@ struct ft260_device {
struct completion wait;
struct mutex lock;
u8 write_buf[FT260_REPORT_MAX_LENGTH];
+ unsigned long need_wakeup_at;
u8 *read_buf;
u16 read_idx;
u16 read_len;
@@ -293,12 +303,26 @@ static int ft260_i2c_reset(struct hid_device *hdev)
return ret;
}
-static int ft260_xfer_status(struct ft260_device *dev)
+static int ft260_xfer_status(struct ft260_device *dev, u8 bus_busy)
{
struct hid_device *hdev = dev->hdev;
struct ft260_get_i2c_status_report report;
int ret;
+ if (time_is_before_jiffies(dev->need_wakeup_at)) {
+ ret = ft260_hid_feature_report_get(hdev, FT260_I2C_STATUS,
+ (u8 *)&report, sizeof(report));
+ if (unlikely(ret < 0)) {
+ hid_err(hdev, "failed to retrieve status: %d, no wakeup\n",
+ ret);
+ } else {
+ dev->need_wakeup_at = jiffies +
+ msecs_to_jiffies(FT260_WAKEUP_NEEDED_AFTER_MS);
+ ft260_dbg("bus_status %#02x, wakeup\n",
+ report.bus_status);
+ }
+ }
+
ret = ft260_hid_feature_report_get(hdev, FT260_I2C_STATUS,
(u8 *)&report, sizeof(report));
if (unlikely(ret < 0)) {
@@ -310,30 +334,20 @@ static int ft260_xfer_status(struct ft260_device *dev)
ft260_dbg("bus_status %#02x, clock %u\n", report.bus_status,
dev->clock);
- if (report.bus_status & FT260_I2C_STATUS_CTRL_BUSY)
+ if (report.bus_status & (FT260_I2C_STATUS_CTRL_BUSY | bus_busy))
return -EAGAIN;
- if (report.bus_status & FT260_I2C_STATUS_BUS_BUSY)
- return -EBUSY;
-
- if (report.bus_status & FT260_I2C_STATUS_ERROR)
+ /*
+ * The error condition (bit 1) is a status bit reflecting any
+ * error conditions. When any of the bits 2, 3, or 4 are raised
+ * to 1, bit 1 is also set to 1.
+ */
+ if (report.bus_status & FT260_I2C_STATUS_ERROR) {
+ hid_err(hdev, "i2c bus error: %#02x\n", report.bus_status);
return -EIO;
+ }
- ret = -EIO;
-
- if (report.bus_status & FT260_I2C_STATUS_ADDR_NO_ACK)
- ft260_dbg("unacknowledged address\n");
-
- if (report.bus_status & FT260_I2C_STATUS_DATA_NO_ACK)
- ft260_dbg("unacknowledged data\n");
-
- if (report.bus_status & FT260_I2C_STATUS_ARBITR_LOST)
- ft260_dbg("arbitration loss\n");
-
- if (report.bus_status & FT260_I2C_STATUS_CTRL_IDLE)
- ret = 0;
-
- return ret;
+ return 0;
}
static int ft260_hid_output_report(struct hid_device *hdev, u8 *data,
@@ -355,8 +369,11 @@ static int ft260_hid_output_report(struct hid_device *hdev, u8 *data,
static int ft260_hid_output_report_check_status(struct ft260_device *dev,
u8 *data, int len)
{
- int ret, usec, try = 3;
+ u8 bus_busy;
+ int ret, usec, try = 100;
struct hid_device *hdev = dev->hdev;
+ struct ft260_i2c_write_request_report *rep =
+ (struct ft260_i2c_write_request_report *)data;
ret = ft260_hid_output_report(hdev, data, len);
if (ret < 0) {
@@ -366,17 +383,31 @@ static int ft260_hid_output_report_check_status(struct ft260_device *dev,
return ret;
}
- /* transfer time = 1 / clock(KHz) * 10 bits * bytes */
- usec = 10000 / dev->clock * len;
- usleep_range(usec, usec + 100);
- ft260_dbg("wait %d usec, len %d\n", usec, len);
+ /* transfer time = 1 / clock(KHz) * 9 bits * bytes */
+ usec = len * 9000 / dev->clock;
+ if (usec > 2000) {
+ usec -= 1500;
+ usleep_range(usec, usec + 100);
+ ft260_dbg("wait %d usec, len %d\n", usec, len);
+ }
+
+ /*
+ * Do not check the busy bit for combined transactions
+ * since the controller keeps the bus busy between writing
+ * and reading IOs to ensure an atomic operation.
+ */
+ if (rep->flag == FT260_FLAG_START)
+ bus_busy = 0;
+ else
+ bus_busy = FT260_I2C_STATUS_BUS_BUSY;
+
do {
- ret = ft260_xfer_status(dev);
+ ret = ft260_xfer_status(dev, bus_busy);
if (ret != -EAGAIN)
break;
} while (--try);
- if (ret == 0 || ret == -EBUSY)
+ if (ret == 0)
return 0;
ft260_i2c_reset(hdev);
@@ -384,41 +415,49 @@ static int ft260_hid_output_report_check_status(struct ft260_device *dev,
}
static int ft260_i2c_write(struct ft260_device *dev, u8 addr, u8 *data,
- int data_len, u8 flag)
+ int len, u8 flag)
{
- int len, ret, idx = 0;
+ int ret, wr_len, idx = 0;
struct hid_device *hdev = dev->hdev;
struct ft260_i2c_write_request_report *rep =
(struct ft260_i2c_write_request_report *)dev->write_buf;
+ if (len < 1)
+ return -EINVAL;
+
+ rep->flag = FT260_FLAG_START;
+
do {
- if (data_len <= FT260_WR_DATA_MAX)
- len = data_len;
- else
- len = FT260_WR_DATA_MAX;
+ if (len <= FT260_WR_DATA_MAX) {
+ wr_len = len;
+ if (flag == FT260_FLAG_START_STOP)
+ rep->flag |= FT260_FLAG_STOP;
+ } else {
+ wr_len = FT260_WR_DATA_MAX;
+ }
- rep->report = FT260_I2C_DATA_REPORT_ID(len);
+ rep->report = FT260_I2C_DATA_REPORT_ID(wr_len);
rep->address = addr;
- rep->length = len;
- rep->flag = flag;
+ rep->length = wr_len;
- memcpy(rep->data, &data[idx], len);
+ memcpy(rep->data, &data[idx], wr_len);
- ft260_dbg("rep %#02x addr %#02x off %d len %d d[0] %#02x\n",
- rep->report, addr, idx, len, data[0]);
+ ft260_dbg("rep %#02x addr %#02x off %d len %d wlen %d flag %#x d[0] %#02x\n",
+ rep->report, addr, idx, len, wr_len,
+ rep->flag, data[0]);
ret = ft260_hid_output_report_check_status(dev, (u8 *)rep,
- len + 4);
+ wr_len + 4);
if (ret < 0) {
- hid_err(hdev, "%s: failed to start transfer, ret %d\n",
- __func__, ret);
+ hid_err(hdev, "%s: failed with %d\n", __func__, ret);
return ret;
}
- data_len -= len;
- idx += len;
+ len -= wr_len;
+ idx += wr_len;
+ rep->flag = 0;
- } while (data_len > 0);
+ } while (len > 0);
return 0;
}
@@ -457,49 +496,74 @@ static int ft260_smbus_write(struct ft260_device *dev, u8 addr, u8 cmd,
static int ft260_i2c_read(struct ft260_device *dev, u8 addr, u8 *data,
u16 len, u8 flag)
{
+ u16 rd_len;
+ u16 rd_data_max = 60;
+ int timeout, ret = 0;
struct ft260_i2c_read_request_report rep;
struct hid_device *hdev = dev->hdev;
- int timeout;
- int ret;
+ u8 bus_busy = 0;
- if (len > FT260_RD_DATA_MAX) {
- hid_err(hdev, "%s: unsupported rd len: %d\n", __func__, len);
- return -EINVAL;
- }
+ if ((flag & FT260_FLAG_START_REPEATED) == FT260_FLAG_START_REPEATED)
+ flag = FT260_FLAG_START_REPEATED;
+ else
+ flag = FT260_FLAG_START;
+ do {
+ if (len <= rd_data_max) {
+ rd_len = len;
+ flag |= FT260_FLAG_STOP;
+ } else {
+ rd_len = rd_data_max;
+ }
+ rd_data_max = FT260_RD_DATA_MAX;
- dev->read_idx = 0;
- dev->read_buf = data;
- dev->read_len = len;
+ rep.report = FT260_I2C_READ_REQ;
+ rep.length = cpu_to_le16(rd_len);
+ rep.address = addr;
+ rep.flag = flag;
- rep.report = FT260_I2C_READ_REQ;
- rep.length = cpu_to_le16(len);
- rep.address = addr;
- rep.flag = flag;
+ ft260_dbg("rep %#02x addr %#02x len %d rlen %d flag %#x\n",
+ rep.report, rep.address, len, rd_len, flag);
- ft260_dbg("rep %#02x addr %#02x len %d\n", rep.report, rep.address,
- rep.length);
+ reinit_completion(&dev->wait);
- reinit_completion(&dev->wait);
+ dev->read_idx = 0;
+ dev->read_buf = data;
+ dev->read_len = rd_len;
- ret = ft260_hid_output_report(hdev, (u8 *)&rep, sizeof(rep));
- if (ret < 0) {
- hid_err(hdev, "%s: failed to start transaction, ret %d\n",
- __func__, ret);
- return ret;
- }
+ ret = ft260_hid_output_report(hdev, (u8 *)&rep, sizeof(rep));
+ if (ret < 0) {
+ hid_err(hdev, "%s: failed with %d\n", __func__, ret);
+ goto ft260_i2c_read_exit;
+ }
- timeout = msecs_to_jiffies(5000);
- if (!wait_for_completion_timeout(&dev->wait, timeout)) {
- ft260_i2c_reset(hdev);
- return -ETIMEDOUT;
- }
+ timeout = msecs_to_jiffies(5000);
+ if (!wait_for_completion_timeout(&dev->wait, timeout)) {
+ ret = -ETIMEDOUT;
+ ft260_i2c_reset(hdev);
+ goto ft260_i2c_read_exit;
+ }
- ret = ft260_xfer_status(dev);
- if (ret == 0)
- return 0;
+ dev->read_buf = NULL;
- ft260_i2c_reset(hdev);
- return -EIO;
+ if (flag & FT260_FLAG_STOP)
+ bus_busy = FT260_I2C_STATUS_BUS_BUSY;
+
+ ret = ft260_xfer_status(dev, bus_busy);
+ if (ret < 0) {
+ ret = -EIO;
+ ft260_i2c_reset(hdev);
+ goto ft260_i2c_read_exit;
+ }
+
+ len -= rd_len;
+ data += rd_len;
+ flag = 0;
+
+ } while (len > 0);
+
+ft260_i2c_read_exit:
+ dev->read_buf = NULL;
+ return ret;
}
/*
@@ -510,45 +574,37 @@ static int ft260_i2c_read(struct ft260_device *dev, u8 addr, u8 *data,
*/
static int ft260_i2c_write_read(struct ft260_device *dev, struct i2c_msg *msgs)
{
- int len, ret;
- u16 left_len = msgs[1].len;
- u8 *read_buf = msgs[1].buf;
+ int ret;
+ int wr_len = msgs[0].len;
+ int rd_len = msgs[1].len;
+ struct hid_device *hdev = dev->hdev;
u8 addr = msgs[0].addr;
u16 read_off = 0;
- struct hid_device *hdev = dev->hdev;
- if (msgs[0].len > 2) {
- hid_err(hdev, "%s: unsupported wr len: %d\n", __func__,
- msgs[0].len);
+ if (wr_len > 2) {
+ hid_err(hdev, "%s: invalid wr_len: %d\n", __func__, wr_len);
return -EOPNOTSUPP;
}
- memcpy(&read_off, msgs[0].buf, msgs[0].len);
-
- do {
- if (left_len <= FT260_RD_DATA_MAX)
- len = left_len;
+ if (ft260_debug) {
+ if (wr_len == 2)
+ read_off = be16_to_cpu(*(__be16 *)msgs[0].buf);
else
- len = FT260_RD_DATA_MAX;
-
- ft260_dbg("read_off %#x left_len %d len %d\n", read_off,
- left_len, len);
-
- ret = ft260_i2c_write(dev, addr, (u8 *)&read_off, msgs[0].len,
- FT260_FLAG_START);
- if (ret < 0)
- return ret;
+ read_off = *msgs[0].buf;
- ret = ft260_i2c_read(dev, addr, read_buf, len,
- FT260_FLAG_START_STOP);
- if (ret < 0)
- return ret;
+ pr_info("%s: off %#x rlen %d wlen %d\n", __func__,
+ read_off, rd_len, wr_len);
+ }
- left_len -= len;
- read_buf += len;
- read_off += len;
+ ret = ft260_i2c_write(dev, addr, msgs[0].buf, wr_len,
+ FT260_FLAG_START);
+ if (ret < 0)
+ return ret;
- } while (left_len > 0);
+ ret = ft260_i2c_read(dev, addr, msgs[1].buf, rd_len,
+ FT260_FLAG_START_STOP_REPEATED);
+ if (ret < 0)
+ return ret;
return 0;
}
@@ -613,14 +669,6 @@ static int ft260_smbus_xfer(struct i2c_adapter *adapter, u16 addr, u16 flags,
}
switch (size) {
- case I2C_SMBUS_QUICK:
- if (read_write == I2C_SMBUS_READ)
- ret = ft260_i2c_read(dev, addr, &data->byte, 0,
- FT260_FLAG_START_STOP);
- else
- ret = ft260_smbus_write(dev, addr, cmd, NULL, 0,
- FT260_FLAG_START_STOP);
- break;
case I2C_SMBUS_BYTE:
if (read_write == I2C_SMBUS_READ)
ret = ft260_i2c_read(dev, addr, &data->byte, 1,
@@ -703,7 +751,7 @@ smbus_exit:
static u32 ft260_functionality(struct i2c_adapter *adap)
{
- return I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_QUICK |
+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_I2C_BLOCK;
}
@@ -782,7 +830,7 @@ static int ft260_byte_show(struct hid_device *hdev, int id, u8 *cfg, int len,
}
static int ft260_word_show(struct hid_device *hdev, int id, u8 *cfg, int len,
- u16 *field, u8 *buf)
+ __le16 *field, u8 *buf)
{
int ret;
@@ -811,9 +859,9 @@ static int ft260_word_show(struct hid_device *hdev, int id, u8 *cfg, int len,
#define FT260_I2CST_ATTR_SHOW(name) \
FT260_ATTR_SHOW(name, ft260_get_i2c_status_report, \
- FT260_I2C_STATUS, u16, ft260_word_show)
+ FT260_I2C_STATUS, __le16, ft260_word_show)
-#define FT260_ATTR_STORE(name, reptype, id, req, type, func) \
+#define FT260_ATTR_STORE(name, reptype, id, req, type, ctype, func) \
static ssize_t name##_store(struct device *kdev, \
struct device_attribute *attr, \
const char *buf, size_t count) \
@@ -823,7 +871,7 @@ static int ft260_word_show(struct hid_device *hdev, int id, u8 *cfg, int len,
type name; \
int ret; \
\
- if (!func(buf, 10, &name)) { \
+ if (!func(buf, 10, (ctype *)&name)) { \
rep.name = name; \
rep.report = id; \
rep.request = req; \
@@ -839,11 +887,11 @@ static int ft260_word_show(struct hid_device *hdev, int id, u8 *cfg, int len,
#define FT260_BYTE_ATTR_STORE(name, reptype, req) \
FT260_ATTR_STORE(name, reptype, FT260_SYSTEM_SETTINGS, req, \
- u8, kstrtou8)
+ u8, u8, kstrtou8)
#define FT260_WORD_ATTR_STORE(name, reptype, req) \
FT260_ATTR_STORE(name, reptype, FT260_SYSTEM_SETTINGS, req, \
- u16, kstrtou16)
+ __le16, u16, kstrtou16)
FT260_SSTAT_ATTR_SHOW(chip_mode);
static DEVICE_ATTR_RO(chip_mode);
@@ -928,7 +976,7 @@ static int ft260_probe(struct hid_device *hdev, const struct hid_device_id *id)
return ret;
}
- ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
+ ret = hid_hw_start(hdev, 0);
if (ret) {
hid_err(hdev, "failed to start HID HW\n");
return ret;
@@ -955,6 +1003,10 @@ static int ft260_probe(struct hid_device *hdev, const struct hid_device_id *id)
if (ret <= 0)
goto err_hid_close;
+ hid_info(hdev, "USB HID v%x.%02x Device [%s] on %s\n",
+ hdev->version >> 8, hdev->version & 0xff, hdev->name,
+ hdev->phys);
+
hid_set_drvdata(hdev, dev);
dev->hdev = hdev;
dev->adap.owner = THIS_MODULE;
@@ -963,13 +1015,12 @@ static int ft260_probe(struct hid_device *hdev, const struct hid_device_id *id)
dev->adap.quirks = &ft260_i2c_quirks;
dev->adap.dev.parent = &hdev->dev;
snprintf(dev->adap.name, sizeof(dev->adap.name),
- "FT260 usb-i2c bridge on hidraw%d",
- ((struct hidraw *)hdev->hidraw)->minor);
+ "FT260 usb-i2c bridge");
mutex_init(&dev->lock);
init_completion(&dev->wait);
- ret = ft260_xfer_status(dev);
+ ret = ft260_xfer_status(dev, FT260_I2C_STATUS_BUS_BUSY);
if (ret)
ft260_i2c_reset(hdev);
@@ -1022,6 +1073,13 @@ static int ft260_raw_event(struct hid_device *hdev, struct hid_report *report,
ft260_dbg("i2c resp: rep %#02x len %d\n", xfer->report,
xfer->length);
+ if ((dev->read_buf == NULL) ||
+ (xfer->length > dev->read_len - dev->read_idx)) {
+ hid_err(hdev, "unexpected report %#02x, length %d\n",
+ xfer->report, xfer->length);
+ return -1;
+ }
+
memcpy(&dev->read_buf[dev->read_idx], &xfer->data,
xfer->length);
dev->read_idx += xfer->length;
@@ -1030,10 +1088,9 @@ static int ft260_raw_event(struct hid_device *hdev, struct hid_report *report,
complete(&dev->wait);
} else {
- hid_err(hdev, "unknown report: %#02x\n", xfer->report);
- return 0;
+ hid_err(hdev, "unhandled report %#02x\n", xfer->report);
}
- return 1;
+ return 0;
}
static struct hid_driver ft260_driver = {
diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c
index ab57b49a44ed..cf12f17e6533 100644
--- a/drivers/hid/hid-hyperv.c
+++ b/drivers/hid/hid-hyperv.c
@@ -22,9 +22,6 @@ struct hv_input_dev_info {
unsigned short reserved[11];
};
-/* The maximum size of a synthetic input message. */
-#define SYNTHHID_MAX_INPUT_REPORT_SIZE 16
-
/*
* Current version
*
@@ -59,11 +56,6 @@ struct synthhid_msg_hdr {
u32 size;
};
-struct synthhid_msg {
- struct synthhid_msg_hdr header;
- char data[1]; /* Enclosed message */
-};
-
union synthhid_version {
struct {
u16 minor_version;
@@ -99,7 +91,7 @@ struct synthhid_device_info_ack {
struct synthhid_input_report {
struct synthhid_msg_hdr header;
- char buffer[1];
+ char buffer[];
};
#pragma pack(pop)
@@ -118,7 +110,7 @@ enum pipe_prot_msg_type {
struct pipe_prt_msg {
enum pipe_prot_msg_type type;
u32 size;
- char data[1];
+ char data[];
};
struct mousevsc_prt_msg {
@@ -232,7 +224,7 @@ static void mousevsc_on_receive_device_info(struct mousevsc_dev *input_device,
ret = vmbus_sendpacket(input_device->device->channel,
&ack,
- sizeof(struct pipe_prt_msg) - sizeof(unsigned char) +
+ sizeof(struct pipe_prt_msg) +
sizeof(struct synthhid_device_info_ack),
(unsigned long)&ack,
VM_PKT_DATA_INBAND,
@@ -251,7 +243,7 @@ static void mousevsc_on_receive(struct hv_device *device,
struct vmpacket_descriptor *packet)
{
struct pipe_prt_msg *pipe_msg;
- struct synthhid_msg *hid_msg;
+ struct synthhid_msg_hdr *hid_msg_hdr;
struct mousevsc_dev *input_dev = hv_get_drvdata(device);
struct synthhid_input_report *input_report;
size_t len;
@@ -262,25 +254,23 @@ static void mousevsc_on_receive(struct hv_device *device,
if (pipe_msg->type != PIPE_MESSAGE_DATA)
return;
- hid_msg = (struct synthhid_msg *)pipe_msg->data;
+ hid_msg_hdr = (struct synthhid_msg_hdr *)pipe_msg->data;
- switch (hid_msg->header.type) {
+ switch (hid_msg_hdr->type) {
case SYNTH_HID_PROTOCOL_RESPONSE:
/*
* 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 ((pipe_msg->size + sizeof(struct pipe_prt_msg)
- - sizeof(unsigned char))
+ if (struct_size(pipe_msg, data, pipe_msg->size)
> sizeof(struct mousevsc_prt_msg)) {
WARN_ON(1);
break;
}
memcpy(&input_dev->protocol_resp, pipe_msg,
- pipe_msg->size + sizeof(struct pipe_prt_msg) -
- sizeof(unsigned char));
+ struct_size(pipe_msg, data, pipe_msg->size));
complete(&input_dev->wait_event);
break;
@@ -311,7 +301,7 @@ static void mousevsc_on_receive(struct hv_device *device,
break;
default:
pr_err("unsupported hid msg type - type %d len %d\n",
- hid_msg->header.type, hid_msg->header.size);
+ hid_msg_hdr->type, hid_msg_hdr->size);
break;
}
@@ -359,8 +349,7 @@ static int mousevsc_connect_to_vsp(struct hv_device *device)
request->request.version_requested.version = SYNTHHID_INPUT_VERSION;
ret = vmbus_sendpacket(device->channel, request,
- sizeof(struct pipe_prt_msg) -
- sizeof(unsigned char) +
+ sizeof(struct pipe_prt_msg) +
sizeof(struct synthhid_protocol_request),
(unsigned long)request,
VM_PKT_DATA_INBAND,
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 859aeb07542e..3a93cf04147d 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -340,6 +340,7 @@ static enum power_supply_property hidinput_battery_props[] = {
#define HID_BATTERY_QUIRK_PERCENT (1 << 0) /* always reports percent */
#define HID_BATTERY_QUIRK_FEATURE (1 << 1) /* ask for feature report */
#define HID_BATTERY_QUIRK_IGNORE (1 << 2) /* completely ignore the battery */
+#define HID_BATTERY_QUIRK_AVOID_QUERY (1 << 3) /* do not query the battery */
static const struct hid_device_id hid_battery_quirks[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
@@ -373,6 +374,8 @@ static const struct hid_device_id hid_battery_quirks[] = {
HID_BATTERY_QUIRK_IGNORE },
{ HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN),
HID_BATTERY_QUIRK_IGNORE },
+ { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L),
+ HID_BATTERY_QUIRK_AVOID_QUERY },
{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15),
HID_BATTERY_QUIRK_IGNORE },
{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15T_DR100),
@@ -554,6 +557,9 @@ static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
dev->battery_avoid_query = report_type == HID_INPUT_REPORT &&
field->physical == HID_DG_STYLUS;
+ if (quirks & HID_BATTERY_QUIRK_AVOID_QUERY)
+ dev->battery_avoid_query = true;
+
dev->battery = power_supply_register(&dev->dev, psy_desc, &psy_cfg);
if (IS_ERR(dev->battery)) {
error = PTR_ERR(dev->battery);
@@ -1086,6 +1092,9 @@ 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 8a2aac18dcc5..c6e4a96e882e 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -895,7 +895,7 @@ static int hidpp_root_get_protocol_version(struct hidpp_device *hidpp)
ret = hidpp_send_rap_command_sync(hidpp,
REPORT_ID_HIDPP_SHORT,
HIDPP_PAGE_ROOT_IDX,
- CMD_ROOT_GET_PROTOCOL_VERSION,
+ CMD_ROOT_GET_PROTOCOL_VERSION | LINUX_KERNEL_SW_ID,
ping_data, sizeof(ping_data), &response);
if (ret == HIDPP_ERROR_INVALID_SUBID) {
diff --git a/drivers/hid/hid-mcp2221.c b/drivers/hid/hid-mcp2221.c
index de52e9f7bb8c..5886543b17f3 100644
--- a/drivers/hid/hid-mcp2221.c
+++ b/drivers/hid/hid-mcp2221.c
@@ -10,12 +10,14 @@
#include <linux/module.h>
#include <linux/err.h>
#include <linux/mutex.h>
+#include <linux/bitfield.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/hid.h>
#include <linux/hidraw.h>
#include <linux/i2c.h>
#include <linux/gpio/driver.h>
+#include <linux/iio/iio.h>
#include "hid-ids.h"
/* Commands codes in a raw output report */
@@ -30,6 +32,9 @@ enum {
MCP2221_I2C_CANCEL = 0x10,
MCP2221_GPIO_SET = 0x50,
MCP2221_GPIO_GET = 0x51,
+ MCP2221_SET_SRAM_SETTINGS = 0x60,
+ MCP2221_GET_SRAM_SETTINGS = 0x61,
+ MCP2221_READ_FLASH_DATA = 0xb0,
};
/* Response codes in a raw input report */
@@ -89,6 +94,7 @@ struct mcp2221 {
struct i2c_adapter adapter;
struct mutex lock;
struct completion wait_in_report;
+ struct delayed_work init_work;
u8 *rxbuf;
u8 txbuf[64];
int rxbuf_idx;
@@ -97,6 +103,18 @@ struct mcp2221 {
struct gpio_chip *gc;
u8 gp_idx;
u8 gpio_dir;
+ u8 mode[4];
+#if IS_REACHABLE(CONFIG_IIO)
+ struct iio_chan_spec iio_channels[3];
+ u16 adc_values[3];
+ u8 adc_scale;
+ u8 dac_value;
+ u16 dac_scale;
+#endif
+};
+
+struct mcp2221_iio {
+ struct mcp2221 *mcp;
};
/*
@@ -567,6 +585,7 @@ static const struct i2c_algorithm mcp_i2c_algo = {
.functionality = mcp_i2c_func,
};
+#if IS_REACHABLE(CONFIG_GPIOLIB)
static int mcp_gpio_get(struct gpio_chip *gc,
unsigned int offset)
{
@@ -670,6 +689,7 @@ static int mcp_gpio_get_direction(struct gpio_chip *gc,
return GPIO_LINE_DIRECTION_OUT;
}
+#endif
/* Gives current state of i2c engine inside mcp2221 */
static int mcp_get_i2c_eng_state(struct mcp2221 *mcp,
@@ -745,6 +765,9 @@ static int mcp2221_raw_event(struct hid_device *hdev,
break;
}
mcp->status = mcp_get_i2c_eng_state(mcp, data, 8);
+#if IS_REACHABLE(CONFIG_IIO)
+ memcpy(&mcp->adc_values, &data[50], sizeof(mcp->adc_values));
+#endif
break;
default:
mcp->status = -EIO;
@@ -816,6 +839,69 @@ static int mcp2221_raw_event(struct hid_device *hdev,
complete(&mcp->wait_in_report);
break;
+ case MCP2221_SET_SRAM_SETTINGS:
+ switch (data[1]) {
+ case MCP2221_SUCCESS:
+ mcp->status = 0;
+ break;
+ default:
+ mcp->status = -EAGAIN;
+ }
+ complete(&mcp->wait_in_report);
+ break;
+
+ case MCP2221_GET_SRAM_SETTINGS:
+ switch (data[1]) {
+ case MCP2221_SUCCESS:
+ memcpy(&mcp->mode, &data[22], 4);
+#if IS_REACHABLE(CONFIG_IIO)
+ mcp->dac_value = data[6] & GENMASK(4, 0);
+#endif
+ mcp->status = 0;
+ break;
+ default:
+ mcp->status = -EAGAIN;
+ }
+ complete(&mcp->wait_in_report);
+ break;
+
+ case MCP2221_READ_FLASH_DATA:
+ switch (data[1]) {
+ case MCP2221_SUCCESS:
+ mcp->status = 0;
+
+ /* Only handles CHIP SETTINGS subpage currently */
+ if (mcp->txbuf[1] != 0) {
+ mcp->status = -EIO;
+ break;
+ }
+
+#if IS_REACHABLE(CONFIG_IIO)
+ {
+ u8 tmp;
+ /* DAC scale value */
+ tmp = FIELD_GET(GENMASK(7, 6), data[6]);
+ if ((data[6] & BIT(5)) && tmp)
+ mcp->dac_scale = tmp + 4;
+ else
+ mcp->dac_scale = 5;
+
+ /* ADC scale value */
+ tmp = FIELD_GET(GENMASK(4, 3), data[7]);
+ if ((data[7] & BIT(2)) && tmp)
+ mcp->adc_scale = tmp - 1;
+ else
+ mcp->adc_scale = 0;
+ }
+#endif
+
+ break;
+ default:
+ mcp->status = -EAGAIN;
+ }
+ complete(&mcp->wait_in_report);
+ break;
+
default:
mcp->status = -EIO;
complete(&mcp->wait_in_report);
@@ -824,6 +910,190 @@ static int mcp2221_raw_event(struct hid_device *hdev,
return 1;
}
+/* Device resource managed function for HID unregistration */
+static void mcp2221_hid_unregister(void *ptr)
+{
+ struct hid_device *hdev = ptr;
+
+ hid_hw_close(hdev);
+ hid_hw_stop(hdev);
+}
+
+/* This is needed to be sure hid_hw_stop() isn't called twice by the subsystem */
+static void mcp2221_remove(struct hid_device *hdev)
+{
+}
+
+#if IS_REACHABLE(CONFIG_IIO)
+static int mcp2221_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *channel, int *val,
+ int *val2, long mask)
+{
+ struct mcp2221_iio *priv = iio_priv(indio_dev);
+ struct mcp2221 *mcp = priv->mcp;
+ int ret;
+
+ if (mask == IIO_CHAN_INFO_SCALE) {
+ if (channel->output)
+ *val = 1 << mcp->dac_scale;
+ else
+ *val = 1 << mcp->adc_scale;
+
+ return IIO_VAL_INT;
+ }
+
+ mutex_lock(&mcp->lock);
+
+ if (channel->output) {
+ *val = mcp->dac_value;
+ ret = IIO_VAL_INT;
+ } else {
+ /* Read ADC values */
+ ret = mcp_chk_last_cmd_status(mcp);
+
+ if (!ret) {
+ *val = le16_to_cpu((__force __le16) mcp->adc_values[channel->address]);
+ if (*val >= BIT(10))
+ ret = -EINVAL;
+ else
+ ret = IIO_VAL_INT;
+ }
+ }
+
+ mutex_unlock(&mcp->lock);
+
+ return ret;
+}
+
+static int mcp2221_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct mcp2221_iio *priv = iio_priv(indio_dev);
+ struct mcp2221 *mcp = priv->mcp;
+ int ret;
+
+ if (val < 0 || val >= BIT(5))
+ return -EINVAL;
+
+ mutex_lock(&mcp->lock);
+
+ memset(mcp->txbuf, 0, 12);
+ mcp->txbuf[0] = MCP2221_SET_SRAM_SETTINGS;
+ mcp->txbuf[4] = BIT(7) | val;
+
+ ret = mcp_send_data_req_status(mcp, mcp->txbuf, 12);
+ if (!ret)
+ mcp->dac_value = val;
+
+ mutex_unlock(&mcp->lock);
+
+ return ret;
+}
+
+static const struct iio_info mcp2221_info = {
+ .read_raw = &mcp2221_read_raw,
+ .write_raw = &mcp2221_write_raw,
+};
+
+static int mcp_iio_channels(struct mcp2221 *mcp)
+{
+ int idx, cnt = 0;
+ bool dac_created = false;
+
+ /* GP0 doesn't have ADC/DAC alternative function */
+ for (idx = 1; idx < MCP_NGPIO; idx++) {
+ struct iio_chan_spec *chan = &mcp->iio_channels[cnt];
+
+ switch (mcp->mode[idx]) {
+ case 2:
+ chan->address = idx - 1;
+ chan->channel = cnt++;
+ break;
+ case 3:
+ /* GP1 doesn't have DAC alternative function */
+ if (idx == 1 || dac_created)
+ continue;
+ /* DAC1 and DAC2 outputs are connected to the same DAC */
+ dac_created = true;
+ chan->output = 1;
+ cnt++;
+ break;
+ default:
+ continue;
+ };
+
+ chan->type = IIO_VOLTAGE;
+ chan->indexed = 1;
+ chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
+ chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
+ chan->scan_index = -1;
+ }
+
+ return cnt;
+}
+
+static void mcp_init_work(struct work_struct *work)
+{
+ struct iio_dev *indio_dev;
+ struct mcp2221 *mcp = container_of(work, struct mcp2221, init_work.work);
+ struct mcp2221_iio *data;
+ static int retries = 5;
+ int ret, num_channels;
+
+ hid_hw_power(mcp->hdev, PM_HINT_FULLON);
+ mutex_lock(&mcp->lock);
+
+ mcp->txbuf[0] = MCP2221_GET_SRAM_SETTINGS;
+ ret = mcp_send_data_req_status(mcp, mcp->txbuf, 1);
+
+ if (ret == -EAGAIN)
+ goto reschedule_task;
+
+ num_channels = mcp_iio_channels(mcp);
+ if (!num_channels)
+ goto unlock;
+
+ mcp->txbuf[0] = MCP2221_READ_FLASH_DATA;
+ mcp->txbuf[1] = 0;
+ ret = mcp_send_data_req_status(mcp, mcp->txbuf, 2);
+
+ if (ret == -EAGAIN)
+ goto reschedule_task;
+
+ indio_dev = devm_iio_device_alloc(&mcp->hdev->dev, sizeof(*data));
+ if (!indio_dev)
+ goto unlock;
+
+ data = iio_priv(indio_dev);
+ data->mcp = mcp;
+
+ indio_dev->name = "mcp2221";
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &mcp2221_info;
+ indio_dev->channels = mcp->iio_channels;
+ indio_dev->num_channels = num_channels;
+
+ devm_iio_device_register(&mcp->hdev->dev, indio_dev);
+
+unlock:
+ mutex_unlock(&mcp->lock);
+ hid_hw_power(mcp->hdev, PM_HINT_NORMAL);
+
+ return;
+
+reschedule_task:
+ mutex_unlock(&mcp->lock);
+ hid_hw_power(mcp->hdev, PM_HINT_NORMAL);
+
+ if (!retries--)
+ return;
+
+ /* Device is not ready to read SRAM or FLASH data, try again */
+ schedule_delayed_work(&mcp->init_work, msecs_to_jiffies(100));
+}
+#endif
+
static int mcp2221_probe(struct hid_device *hdev,
const struct hid_device_id *id)
{
@@ -849,7 +1119,8 @@ static int mcp2221_probe(struct hid_device *hdev,
ret = hid_hw_open(hdev);
if (ret) {
hid_err(hdev, "can't open device\n");
- goto err_hstop;
+ hid_hw_stop(hdev);
+ return ret;
}
mutex_init(&mcp->lock);
@@ -857,6 +1128,10 @@ static int mcp2221_probe(struct hid_device *hdev,
hid_set_drvdata(hdev, mcp);
mcp->hdev = hdev;
+ ret = devm_add_action_or_reset(&hdev->dev, mcp2221_hid_unregister, hdev);
+ if (ret)
+ return ret;
+
/* Set I2C bus clock diviser */
if (i2c_clk_freq > 400)
i2c_clk_freq = 400;
@@ -873,19 +1148,18 @@ static int mcp2221_probe(struct hid_device *hdev,
"MCP2221 usb-i2c bridge on hidraw%d",
((struct hidraw *)hdev->hidraw)->minor);
- ret = i2c_add_adapter(&mcp->adapter);
+ ret = devm_i2c_add_adapter(&hdev->dev, &mcp->adapter);
if (ret) {
hid_err(hdev, "can't add usb-i2c adapter: %d\n", ret);
- goto err_i2c;
+ return ret;
}
i2c_set_adapdata(&mcp->adapter, mcp);
+#if IS_REACHABLE(CONFIG_GPIOLIB)
/* Setup GPIO chip */
mcp->gc = devm_kzalloc(&hdev->dev, sizeof(*mcp->gc), GFP_KERNEL);
- if (!mcp->gc) {
- ret = -ENOMEM;
- goto err_gc;
- }
+ if (!mcp->gc)
+ return -ENOMEM;
mcp->gc->label = "mcp2221_gpio";
mcp->gc->direction_input = mcp_gpio_direction_input;
@@ -900,26 +1174,15 @@ static int mcp2221_probe(struct hid_device *hdev,
ret = devm_gpiochip_add_data(&hdev->dev, mcp->gc, mcp);
if (ret)
- goto err_gc;
-
- return 0;
-
-err_gc:
- i2c_del_adapter(&mcp->adapter);
-err_i2c:
- hid_hw_close(mcp->hdev);
-err_hstop:
- hid_hw_stop(mcp->hdev);
- return ret;
-}
+ return ret;
+#endif
-static void mcp2221_remove(struct hid_device *hdev)
-{
- struct mcp2221 *mcp = hid_get_drvdata(hdev);
+#if IS_REACHABLE(CONFIG_IIO)
+ INIT_DELAYED_WORK(&mcp->init_work, mcp_init_work);
+ schedule_delayed_work(&mcp->init_work, msecs_to_jiffies(100));
+#endif
- i2c_del_adapter(&mcp->adapter);
- hid_hw_close(mcp->hdev);
- hid_hw_stop(mcp->hdev);
+ return 0;
}
static const struct hid_device_id mcp2221_devices[] = {
diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c
index 0b58763bfd30..7b5aef538044 100644
--- a/drivers/hid/hid-playstation.c
+++ b/drivers/hid/hid-playstation.c
@@ -2,7 +2,7 @@
/*
* HID driver for Sony DualSense(TM) controller.
*
- * Copyright (c) 2020 Sony Interactive Entertainment
+ * Copyright (c) 2020-2022 Sony Interactive Entertainment
*/
#include <linux/bits.h>
@@ -60,8 +60,10 @@ struct ps_calibration_data {
struct ps_led_info {
const char *name;
const char *color;
+ int max_brightness;
enum led_brightness (*brightness_get)(struct led_classdev *cdev);
int (*brightness_set)(struct led_classdev *cdev, enum led_brightness);
+ int (*blink_set)(struct led_classdev *led, unsigned long *on, unsigned long *off);
};
/* Seed values for DualShock4 / DualSense CRC32 for different report types. */
@@ -283,6 +285,225 @@ struct dualsense_output_report {
struct dualsense_output_report_common *common;
};
+#define DS4_INPUT_REPORT_USB 0x01
+#define DS4_INPUT_REPORT_USB_SIZE 64
+#define DS4_INPUT_REPORT_BT 0x11
+#define DS4_INPUT_REPORT_BT_SIZE 78
+#define DS4_OUTPUT_REPORT_USB 0x05
+#define DS4_OUTPUT_REPORT_USB_SIZE 32
+#define DS4_OUTPUT_REPORT_BT 0x11
+#define DS4_OUTPUT_REPORT_BT_SIZE 78
+
+#define DS4_FEATURE_REPORT_CALIBRATION 0x02
+#define DS4_FEATURE_REPORT_CALIBRATION_SIZE 37
+#define DS4_FEATURE_REPORT_CALIBRATION_BT 0x05
+#define DS4_FEATURE_REPORT_CALIBRATION_BT_SIZE 41
+#define DS4_FEATURE_REPORT_FIRMWARE_INFO 0xa3
+#define DS4_FEATURE_REPORT_FIRMWARE_INFO_SIZE 49
+#define DS4_FEATURE_REPORT_PAIRING_INFO 0x12
+#define DS4_FEATURE_REPORT_PAIRING_INFO_SIZE 16
+
+/*
+ * Status of a DualShock4 touch point contact.
+ * Contact IDs, with highest bit set are 'inactive'
+ * and any associated data is then invalid.
+ */
+#define DS4_TOUCH_POINT_INACTIVE BIT(7)
+
+/* Status field of DualShock4 input report. */
+#define DS4_STATUS0_BATTERY_CAPACITY GENMASK(3, 0)
+#define DS4_STATUS0_CABLE_STATE BIT(4)
+/* Battery status within batery_status field. */
+#define DS4_BATTERY_STATUS_FULL 11
+/* Status1 bit2 contains dongle connection state:
+ * 0 = connectd
+ * 1 = disconnected
+ */
+#define DS4_STATUS1_DONGLE_STATE BIT(2)
+
+/* The lower 6 bits of hw_control of the Bluetooth main output report
+ * control the interval at which Dualshock 4 reports data:
+ * 0x00 - 1ms
+ * 0x01 - 1ms
+ * 0x02 - 2ms
+ * 0x3E - 62ms
+ * 0x3F - disabled
+ */
+#define DS4_OUTPUT_HWCTL_BT_POLL_MASK 0x3F
+/* Default to 4ms poll interval, which is same as USB (not adjustable). */
+#define DS4_BT_DEFAULT_POLL_INTERVAL_MS 4
+#define DS4_OUTPUT_HWCTL_CRC32 0x40
+#define DS4_OUTPUT_HWCTL_HID 0x80
+
+/* Flags for DualShock4 output report. */
+#define DS4_OUTPUT_VALID_FLAG0_MOTOR 0x01
+#define DS4_OUTPUT_VALID_FLAG0_LED 0x02
+#define DS4_OUTPUT_VALID_FLAG0_LED_BLINK 0x04
+
+/* DualShock4 hardware limits */
+#define DS4_ACC_RES_PER_G 8192
+#define DS4_ACC_RANGE (4*DS_ACC_RES_PER_G)
+#define DS4_GYRO_RES_PER_DEG_S 1024
+#define DS4_GYRO_RANGE (2048*DS_GYRO_RES_PER_DEG_S)
+#define DS4_LIGHTBAR_MAX_BLINK 255 /* 255 centiseconds */
+#define DS4_TOUCHPAD_WIDTH 1920
+#define DS4_TOUCHPAD_HEIGHT 942
+
+enum dualshock4_dongle_state {
+ DONGLE_DISCONNECTED,
+ DONGLE_CALIBRATING,
+ DONGLE_CONNECTED,
+ DONGLE_DISABLED
+};
+
+struct dualshock4 {
+ struct ps_device base;
+ struct input_dev *gamepad;
+ struct input_dev *sensors;
+ struct input_dev *touchpad;
+
+ /* Calibration data for accelerometer and gyroscope. */
+ struct ps_calibration_data accel_calib_data[3];
+ struct ps_calibration_data gyro_calib_data[3];
+
+ /* Only used on dongle to track state transitions. */
+ enum dualshock4_dongle_state dongle_state;
+ /* Used during calibration. */
+ struct work_struct dongle_hotplug_worker;
+
+ /* Timestamp for sensor data */
+ bool sensor_timestamp_initialized;
+ uint32_t prev_sensor_timestamp;
+ uint32_t sensor_timestamp_us;
+
+ /* Bluetooth poll interval */
+ bool update_bt_poll_interval;
+ uint8_t bt_poll_interval;
+
+ bool update_rumble;
+ uint8_t motor_left;
+ uint8_t motor_right;
+
+ /* Lightbar leds */
+ bool update_lightbar;
+ bool update_lightbar_blink;
+ bool lightbar_enabled; /* For use by global LED control. */
+ uint8_t lightbar_red;
+ uint8_t lightbar_green;
+ uint8_t lightbar_blue;
+ uint8_t lightbar_blink_on; /* In increments of 10ms. */
+ uint8_t lightbar_blink_off; /* In increments of 10ms. */
+ struct led_classdev lightbar_leds[4];
+
+ struct work_struct output_worker;
+ bool output_worker_initialized;
+ void *output_report_dmabuf;
+};
+
+struct dualshock4_touch_point {
+ uint8_t contact;
+ uint8_t x_lo;
+ uint8_t x_hi:4, y_lo:4;
+ uint8_t y_hi;
+} __packed;
+static_assert(sizeof(struct dualshock4_touch_point) == 4);
+
+struct dualshock4_touch_report {
+ uint8_t timestamp;
+ struct dualshock4_touch_point points[2];
+} __packed;
+static_assert(sizeof(struct dualshock4_touch_report) == 9);
+
+/* Main DualShock4 input report excluding any BT/USB specific headers. */
+struct dualshock4_input_report_common {
+ uint8_t x, y;
+ uint8_t rx, ry;
+ uint8_t buttons[3];
+ uint8_t z, rz;
+
+ /* Motion sensors */
+ __le16 sensor_timestamp;
+ uint8_t sensor_temperature;
+ __le16 gyro[3]; /* x, y, z */
+ __le16 accel[3]; /* x, y, z */
+ uint8_t reserved2[5];
+
+ uint8_t status[2];
+ uint8_t reserved3;
+} __packed;
+static_assert(sizeof(struct dualshock4_input_report_common) == 32);
+
+struct dualshock4_input_report_usb {
+ uint8_t report_id; /* 0x01 */
+ struct dualshock4_input_report_common common;
+ uint8_t num_touch_reports;
+ struct dualshock4_touch_report touch_reports[3];
+ uint8_t reserved[3];
+} __packed;
+static_assert(sizeof(struct dualshock4_input_report_usb) == DS4_INPUT_REPORT_USB_SIZE);
+
+struct dualshock4_input_report_bt {
+ uint8_t report_id; /* 0x11 */
+ uint8_t reserved[2];
+ struct dualshock4_input_report_common common;
+ uint8_t num_touch_reports;
+ struct dualshock4_touch_report touch_reports[4]; /* BT has 4 compared to 3 for USB */
+ uint8_t reserved2[2];
+ __le32 crc32;
+} __packed;
+static_assert(sizeof(struct dualshock4_input_report_bt) == DS4_INPUT_REPORT_BT_SIZE);
+
+/* Common data between Bluetooth and USB DualShock4 output reports. */
+struct dualshock4_output_report_common {
+ uint8_t valid_flag0;
+ uint8_t valid_flag1;
+
+ uint8_t reserved;
+
+ uint8_t motor_right;
+ uint8_t motor_left;
+
+ uint8_t lightbar_red;
+ uint8_t lightbar_green;
+ uint8_t lightbar_blue;
+ uint8_t lightbar_blink_on;
+ uint8_t lightbar_blink_off;
+} __packed;
+
+struct dualshock4_output_report_usb {
+ uint8_t report_id; /* 0x5 */
+ struct dualshock4_output_report_common common;
+ uint8_t reserved[21];
+} __packed;
+static_assert(sizeof(struct dualshock4_output_report_usb) == DS4_OUTPUT_REPORT_USB_SIZE);
+
+struct dualshock4_output_report_bt {
+ uint8_t report_id; /* 0x11 */
+ uint8_t hw_control;
+ uint8_t audio_control;
+ struct dualshock4_output_report_common common;
+ uint8_t reserved[61];
+ __le32 crc32;
+} __packed;
+static_assert(sizeof(struct dualshock4_output_report_bt) == DS4_OUTPUT_REPORT_BT_SIZE);
+
+/*
+ * The DualShock4 has a main output report used to control most features. It is
+ * largely the same between Bluetooth and USB except for different headers and CRC.
+ * This structure hide the differences between the two to simplify sending output reports.
+ */
+struct dualshock4_output_report {
+ uint8_t *data; /* Start of data */
+ uint8_t len; /* Size of output report */
+
+ /* Points to Bluetooth data payload in case for a Bluetooth report else NULL. */
+ struct dualshock4_output_report_bt *bt;
+ /* Points to USB data payload in case for a USB report else NULL. */
+ struct dualshock4_output_report_usb *usb;
+ /* Points to common section of report, so past any headers. */
+ struct dualshock4_output_report_common *common;
+};
+
/*
* Common gamepad buttons across DualShock 3 / 4 and DualSense.
* Note: for device with a touchpad, touchpad button is not included
@@ -309,8 +530,11 @@ static const struct {int x; int y; } ps_gamepad_hat_mapping[] = {
{0, 0},
};
+static int dualshock4_get_calibration_data(struct dualshock4 *ds4);
static inline void dualsense_schedule_work(struct dualsense *ds);
+static inline void dualshock4_schedule_work(struct dualshock4 *ds4);
static void dualsense_set_lightbar(struct dualsense *ds, uint8_t red, uint8_t green, uint8_t blue);
+static void dualshock4_set_default_lightbar_colors(struct dualshock4 *ds4);
/*
* Add a new ps_device to ps_devices if it doesn't exist.
@@ -514,7 +738,8 @@ static struct input_dev *ps_gamepad_create(struct hid_device *hdev,
return gamepad;
}
-static int ps_get_report(struct hid_device *hdev, uint8_t report_id, uint8_t *buf, size_t size)
+static int ps_get_report(struct hid_device *hdev, uint8_t report_id, uint8_t *buf, size_t size,
+ bool check_crc)
{
int ret;
@@ -535,7 +760,7 @@ static int ps_get_report(struct hid_device *hdev, uint8_t report_id, uint8_t *bu
return -EINVAL;
}
- if (hdev->bus == BUS_BLUETOOTH) {
+ if (hdev->bus == BUS_BLUETOOTH && check_crc) {
/* Last 4 bytes contains crc32. */
uint8_t crc_offset = size - 4;
uint32_t report_crc = get_unaligned_le32(&buf[crc_offset]);
@@ -554,17 +779,24 @@ static int ps_led_register(struct ps_device *ps_dev, struct led_classdev *led,
{
int ret;
- led->name = devm_kasprintf(&ps_dev->hdev->dev, GFP_KERNEL,
- "%s:%s:%s", ps_dev->input_dev_name, led_info->color, led_info->name);
+ if (led_info->name) {
+ led->name = devm_kasprintf(&ps_dev->hdev->dev, GFP_KERNEL,
+ "%s:%s:%s", ps_dev->input_dev_name, led_info->color, led_info->name);
+ } else {
+ /* Backwards compatible mode for hid-sony, but not compliant with LED class spec. */
+ led->name = devm_kasprintf(&ps_dev->hdev->dev, GFP_KERNEL,
+ "%s:%s", ps_dev->input_dev_name, led_info->color);
+ }
if (!led->name)
return -ENOMEM;
led->brightness = 0;
- led->max_brightness = 1;
+ led->max_brightness = led_info->max_brightness;
led->flags = LED_CORE_SUSPENDRESUME;
led->brightness_get = led_info->brightness_get;
led->brightness_set_blocking = led_info->brightness_set;
+ led->blink_set = led_info->blink_set;
ret = devm_led_classdev_register(&ps_dev->hdev->dev, led);
if (ret) {
@@ -729,7 +961,7 @@ static int dualsense_get_calibration_data(struct dualsense *ds)
return -ENOMEM;
ret = ps_get_report(ds->base.hdev, DS_FEATURE_REPORT_CALIBRATION, buf,
- DS_FEATURE_REPORT_CALIBRATION_SIZE);
+ DS_FEATURE_REPORT_CALIBRATION_SIZE, true);
if (ret) {
hid_err(ds->base.hdev, "Failed to retrieve DualSense calibration info: %d\n", ret);
goto err_free;
@@ -811,7 +1043,7 @@ static int dualsense_get_firmware_info(struct dualsense *ds)
return -ENOMEM;
ret = ps_get_report(ds->base.hdev, DS_FEATURE_REPORT_FIRMWARE_INFO, buf,
- DS_FEATURE_REPORT_FIRMWARE_INFO_SIZE);
+ DS_FEATURE_REPORT_FIRMWARE_INFO_SIZE, true);
if (ret) {
hid_err(ds->base.hdev, "Failed to retrieve DualSense firmware info: %d\n", ret);
goto err_free;
@@ -844,7 +1076,7 @@ static int dualsense_get_mac_address(struct dualsense *ds)
return -ENOMEM;
ret = ps_get_report(ds->base.hdev, DS_FEATURE_REPORT_PAIRING_INFO, buf,
- DS_FEATURE_REPORT_PAIRING_INFO_SIZE);
+ DS_FEATURE_REPORT_PAIRING_INFO_SIZE, true);
if (ret) {
hid_err(ds->base.hdev, "Failed to retrieve DualSense pairing info: %d\n", ret);
goto err_free;
@@ -1317,15 +1549,15 @@ static struct ps_device *dualsense_create(struct hid_device *hdev)
int i, ret;
static const struct ps_led_info player_leds_info[] = {
- { LED_FUNCTION_PLAYER1, "white", dualsense_player_led_get_brightness,
+ { LED_FUNCTION_PLAYER1, "white", 1, dualsense_player_led_get_brightness,
dualsense_player_led_set_brightness },
- { LED_FUNCTION_PLAYER2, "white", dualsense_player_led_get_brightness,
+ { LED_FUNCTION_PLAYER2, "white", 1, dualsense_player_led_get_brightness,
dualsense_player_led_set_brightness },
- { LED_FUNCTION_PLAYER3, "white", dualsense_player_led_get_brightness,
+ { LED_FUNCTION_PLAYER3, "white", 1, dualsense_player_led_get_brightness,
dualsense_player_led_set_brightness },
- { LED_FUNCTION_PLAYER4, "white", dualsense_player_led_get_brightness,
+ { LED_FUNCTION_PLAYER4, "white", 1, dualsense_player_led_get_brightness,
dualsense_player_led_set_brightness },
- { LED_FUNCTION_PLAYER5, "white", dualsense_player_led_get_brightness,
+ { LED_FUNCTION_PLAYER5, "white", 1, dualsense_player_led_get_brightness,
dualsense_player_led_set_brightness }
};
@@ -1465,6 +1697,864 @@ err:
return ERR_PTR(ret);
}
+static void dualshock4_dongle_calibration_work(struct work_struct *work)
+{
+ struct dualshock4 *ds4 = container_of(work, struct dualshock4, dongle_hotplug_worker);
+ unsigned long flags;
+ enum dualshock4_dongle_state dongle_state;
+ int ret;
+
+ ret = dualshock4_get_calibration_data(ds4);
+ if (ret < 0) {
+ /* This call is very unlikely to fail for the dongle. When it
+ * fails we are probably in a very bad state, so mark the
+ * dongle as disabled. We will re-enable the dongle if a new
+ * DS4 hotplug is detect from sony_raw_event as any issues
+ * are likely resolved then (the dongle is quite stupid).
+ */
+ hid_err(ds4->base.hdev, "DualShock 4 USB dongle: calibration failed, disabling device\n");
+ dongle_state = DONGLE_DISABLED;
+ } else {
+ hid_info(ds4->base.hdev, "DualShock 4 USB dongle: calibration completed\n");
+ dongle_state = DONGLE_CONNECTED;
+ }
+
+ spin_lock_irqsave(&ds4->base.lock, flags);
+ ds4->dongle_state = dongle_state;
+ spin_unlock_irqrestore(&ds4->base.lock, flags);
+}
+
+static int dualshock4_get_calibration_data(struct dualshock4 *ds4)
+{
+ struct hid_device *hdev = ds4->base.hdev;
+ short gyro_pitch_bias, gyro_pitch_plus, gyro_pitch_minus;
+ short gyro_yaw_bias, gyro_yaw_plus, gyro_yaw_minus;
+ short gyro_roll_bias, gyro_roll_plus, gyro_roll_minus;
+ short gyro_speed_plus, gyro_speed_minus;
+ short acc_x_plus, acc_x_minus;
+ short acc_y_plus, acc_y_minus;
+ short acc_z_plus, acc_z_minus;
+ int speed_2x;
+ int range_2g;
+ int ret = 0;
+ uint8_t *buf;
+
+ if (ds4->base.hdev->bus == BUS_USB) {
+ int retries;
+
+ buf = kzalloc(DS4_FEATURE_REPORT_CALIBRATION_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ /* We should normally receive the feature report data we asked
+ * for, but hidraw applications such as Steam can issue feature
+ * reports as well. In particular for Dongle reconnects, Steam
+ * and this function are competing resulting in often receiving
+ * data for a different HID report, so retry a few times.
+ */
+ for (retries = 0; retries < 3; retries++) {
+ ret = ps_get_report(hdev, DS4_FEATURE_REPORT_CALIBRATION, buf,
+ DS4_FEATURE_REPORT_CALIBRATION_SIZE, true);
+ if (ret) {
+ if (retries < 2) {
+ hid_warn(hdev, "Retrying DualShock 4 get calibration report (0x02) request\n");
+ continue;
+ } else {
+ ret = -EILSEQ;
+ goto err_free;
+ }
+ hid_err(hdev, "Failed to retrieve DualShock4 calibration info: %d\n", ret);
+ goto err_free;
+ } else {
+ break;
+ }
+ }
+ } else { /* Bluetooth */
+ buf = kzalloc(DS4_FEATURE_REPORT_CALIBRATION_BT_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = ps_get_report(hdev, DS4_FEATURE_REPORT_CALIBRATION_BT, buf,
+ DS4_FEATURE_REPORT_CALIBRATION_BT_SIZE, true);
+ if (ret) {
+ hid_err(hdev, "Failed to retrieve DualShock4 calibration info: %d\n", ret);
+ goto err_free;
+ }
+ }
+
+ gyro_pitch_bias = get_unaligned_le16(&buf[1]);
+ gyro_yaw_bias = get_unaligned_le16(&buf[3]);
+ gyro_roll_bias = get_unaligned_le16(&buf[5]);
+ if (ds4->base.hdev->bus == BUS_USB) {
+ gyro_pitch_plus = get_unaligned_le16(&buf[7]);
+ gyro_pitch_minus = get_unaligned_le16(&buf[9]);
+ gyro_yaw_plus = get_unaligned_le16(&buf[11]);
+ gyro_yaw_minus = get_unaligned_le16(&buf[13]);
+ gyro_roll_plus = get_unaligned_le16(&buf[15]);
+ gyro_roll_minus = get_unaligned_le16(&buf[17]);
+ } else {
+ /* BT + Dongle */
+ gyro_pitch_plus = get_unaligned_le16(&buf[7]);
+ gyro_yaw_plus = get_unaligned_le16(&buf[9]);
+ gyro_roll_plus = get_unaligned_le16(&buf[11]);
+ gyro_pitch_minus = get_unaligned_le16(&buf[13]);
+ gyro_yaw_minus = get_unaligned_le16(&buf[15]);
+ gyro_roll_minus = get_unaligned_le16(&buf[17]);
+ }
+ gyro_speed_plus = get_unaligned_le16(&buf[19]);
+ gyro_speed_minus = get_unaligned_le16(&buf[21]);
+ acc_x_plus = get_unaligned_le16(&buf[23]);
+ acc_x_minus = get_unaligned_le16(&buf[25]);
+ acc_y_plus = get_unaligned_le16(&buf[27]);
+ acc_y_minus = get_unaligned_le16(&buf[29]);
+ acc_z_plus = get_unaligned_le16(&buf[31]);
+ acc_z_minus = get_unaligned_le16(&buf[33]);
+
+ /*
+ * Set gyroscope calibration and normalization parameters.
+ * Data values will be normalized to 1/DS4_GYRO_RES_PER_DEG_S degree/s.
+ */
+ speed_2x = (gyro_speed_plus + gyro_speed_minus);
+ ds4->gyro_calib_data[0].abs_code = ABS_RX;
+ ds4->gyro_calib_data[0].bias = gyro_pitch_bias;
+ ds4->gyro_calib_data[0].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S;
+ ds4->gyro_calib_data[0].sens_denom = gyro_pitch_plus - gyro_pitch_minus;
+
+ ds4->gyro_calib_data[1].abs_code = ABS_RY;
+ ds4->gyro_calib_data[1].bias = gyro_yaw_bias;
+ ds4->gyro_calib_data[1].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S;
+ ds4->gyro_calib_data[1].sens_denom = gyro_yaw_plus - gyro_yaw_minus;
+
+ ds4->gyro_calib_data[2].abs_code = ABS_RZ;
+ ds4->gyro_calib_data[2].bias = gyro_roll_bias;
+ ds4->gyro_calib_data[2].sens_numer = speed_2x*DS4_GYRO_RES_PER_DEG_S;
+ ds4->gyro_calib_data[2].sens_denom = gyro_roll_plus - gyro_roll_minus;
+
+ /*
+ * Set accelerometer calibration and normalization parameters.
+ * Data values will be normalized to 1/DS4_ACC_RES_PER_G g.
+ */
+ range_2g = acc_x_plus - acc_x_minus;
+ ds4->accel_calib_data[0].abs_code = ABS_X;
+ ds4->accel_calib_data[0].bias = acc_x_plus - range_2g / 2;
+ ds4->accel_calib_data[0].sens_numer = 2*DS4_ACC_RES_PER_G;
+ ds4->accel_calib_data[0].sens_denom = range_2g;
+
+ range_2g = acc_y_plus - acc_y_minus;
+ ds4->accel_calib_data[1].abs_code = ABS_Y;
+ ds4->accel_calib_data[1].bias = acc_y_plus - range_2g / 2;
+ ds4->accel_calib_data[1].sens_numer = 2*DS4_ACC_RES_PER_G;
+ ds4->accel_calib_data[1].sens_denom = range_2g;
+
+ range_2g = acc_z_plus - acc_z_minus;
+ ds4->accel_calib_data[2].abs_code = ABS_Z;
+ ds4->accel_calib_data[2].bias = acc_z_plus - range_2g / 2;
+ ds4->accel_calib_data[2].sens_numer = 2*DS4_ACC_RES_PER_G;
+ ds4->accel_calib_data[2].sens_denom = range_2g;
+
+err_free:
+ kfree(buf);
+ return ret;
+}
+
+static int dualshock4_get_firmware_info(struct dualshock4 *ds4)
+{
+ uint8_t *buf;
+ int ret;
+
+ buf = kzalloc(DS4_FEATURE_REPORT_FIRMWARE_INFO_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ /* Note USB and BT support the same feature report, but this report
+ * lacks CRC support, so must be disabled in ps_get_report.
+ */
+ ret = ps_get_report(ds4->base.hdev, DS4_FEATURE_REPORT_FIRMWARE_INFO, buf,
+ DS4_FEATURE_REPORT_FIRMWARE_INFO_SIZE, false);
+ if (ret) {
+ hid_err(ds4->base.hdev, "Failed to retrieve DualShock4 firmware info: %d\n", ret);
+ goto err_free;
+ }
+
+ ds4->base.hw_version = get_unaligned_le16(&buf[35]);
+ ds4->base.fw_version = get_unaligned_le16(&buf[41]);
+
+err_free:
+ kfree(buf);
+ return ret;
+}
+
+static int dualshock4_get_mac_address(struct dualshock4 *ds4)
+{
+ struct hid_device *hdev = ds4->base.hdev;
+ uint8_t *buf;
+ int ret = 0;
+
+ if (hdev->bus == BUS_USB) {
+ buf = kzalloc(DS4_FEATURE_REPORT_PAIRING_INFO_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = ps_get_report(hdev, DS4_FEATURE_REPORT_PAIRING_INFO, buf,
+ DS4_FEATURE_REPORT_PAIRING_INFO_SIZE, false);
+ if (ret) {
+ hid_err(hdev, "Failed to retrieve DualShock4 pairing info: %d\n", ret);
+ goto err_free;
+ }
+
+ memcpy(ds4->base.mac_address, &buf[1], sizeof(ds4->base.mac_address));
+ } else {
+ /* Rely on HIDP for Bluetooth */
+ if (strlen(hdev->uniq) != 17)
+ return -EINVAL;
+
+ ret = sscanf(hdev->uniq, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+ &ds4->base.mac_address[5], &ds4->base.mac_address[4],
+ &ds4->base.mac_address[3], &ds4->base.mac_address[2],
+ &ds4->base.mac_address[1], &ds4->base.mac_address[0]);
+
+ if (ret != sizeof(ds4->base.mac_address))
+ return -EINVAL;
+
+ ret = 0;
+ }
+
+err_free:
+ kfree(buf);
+ return ret;
+}
+
+static enum led_brightness dualshock4_led_get_brightness(struct led_classdev *led)
+{
+ struct hid_device *hdev = to_hid_device(led->dev->parent);
+ struct dualshock4 *ds4 = hid_get_drvdata(hdev);
+ unsigned int led_index;
+
+ led_index = led - ds4->lightbar_leds;
+ switch (led_index) {
+ case 0:
+ return ds4->lightbar_red;
+ case 1:
+ return ds4->lightbar_green;
+ case 2:
+ return ds4->lightbar_blue;
+ case 3:
+ return ds4->lightbar_enabled;
+ }
+
+ return -1;
+}
+
+static int dualshock4_led_set_blink(struct led_classdev *led, unsigned long *delay_on,
+ unsigned long *delay_off)
+{
+ struct hid_device *hdev = to_hid_device(led->dev->parent);
+ struct dualshock4 *ds4 = hid_get_drvdata(hdev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ds4->base.lock, flags);
+
+ if (!*delay_on && !*delay_off) {
+ /* Default to 1 Hz (50 centiseconds on, 50 centiseconds off). */
+ ds4->lightbar_blink_on = 50;
+ ds4->lightbar_blink_off = 50;
+ } else {
+ /* Blink delays in centiseconds. */
+ ds4->lightbar_blink_on = min_t(unsigned long, *delay_on/10, DS4_LIGHTBAR_MAX_BLINK);
+ ds4->lightbar_blink_off = min_t(unsigned long, *delay_off/10, DS4_LIGHTBAR_MAX_BLINK);
+ }
+
+ ds4->update_lightbar_blink = true;
+
+ spin_unlock_irqrestore(&ds4->base.lock, flags);
+
+ dualshock4_schedule_work(ds4);
+
+ *delay_on = ds4->lightbar_blink_on;
+ *delay_off = ds4->lightbar_blink_off;
+
+ return 0;
+}
+
+static int dualshock4_led_set_brightness(struct led_classdev *led, enum led_brightness value)
+{
+ struct hid_device *hdev = to_hid_device(led->dev->parent);
+ struct dualshock4 *ds4 = hid_get_drvdata(hdev);
+ unsigned long flags;
+ unsigned int led_index;
+
+ spin_lock_irqsave(&ds4->base.lock, flags);
+
+ led_index = led - ds4->lightbar_leds;
+ switch (led_index) {
+ case 0:
+ ds4->lightbar_red = value;
+ break;
+ case 1:
+ ds4->lightbar_green = value;
+ break;
+ case 2:
+ ds4->lightbar_blue = value;
+ break;
+ case 3:
+ ds4->lightbar_enabled = !!value;
+ }
+
+ ds4->update_lightbar = true;
+
+ spin_unlock_irqrestore(&ds4->base.lock, flags);
+
+ dualshock4_schedule_work(ds4);
+
+ return 0;
+}
+
+static void dualshock4_init_output_report(struct dualshock4 *ds4,
+ struct dualshock4_output_report *rp, void *buf)
+{
+ struct hid_device *hdev = ds4->base.hdev;
+
+ if (hdev->bus == BUS_BLUETOOTH) {
+ struct dualshock4_output_report_bt *bt = buf;
+
+ memset(bt, 0, sizeof(*bt));
+ bt->report_id = DS4_OUTPUT_REPORT_BT;
+
+ rp->data = buf;
+ rp->len = sizeof(*bt);
+ rp->bt = bt;
+ rp->usb = NULL;
+ rp->common = &bt->common;
+ } else { /* USB */
+ struct dualshock4_output_report_usb *usb = buf;
+
+ memset(usb, 0, sizeof(*usb));
+ usb->report_id = DS4_OUTPUT_REPORT_USB;
+
+ rp->data = buf;
+ rp->len = sizeof(*usb);
+ rp->bt = NULL;
+ rp->usb = usb;
+ rp->common = &usb->common;
+ }
+}
+
+static void dualshock4_output_worker(struct work_struct *work)
+{
+ struct dualshock4 *ds4 = container_of(work, struct dualshock4, output_worker);
+ struct dualshock4_output_report report;
+ struct dualshock4_output_report_common *common;
+ unsigned long flags;
+
+ dualshock4_init_output_report(ds4, &report, ds4->output_report_dmabuf);
+ common = report.common;
+
+ spin_lock_irqsave(&ds4->base.lock, flags);
+
+ if (ds4->update_rumble) {
+ /* Select classic rumble style haptics and enable it. */
+ common->valid_flag0 |= DS4_OUTPUT_VALID_FLAG0_MOTOR;
+ common->motor_left = ds4->motor_left;
+ common->motor_right = ds4->motor_right;
+ ds4->update_rumble = false;
+ }
+
+ if (ds4->update_lightbar) {
+ common->valid_flag0 |= DS4_OUTPUT_VALID_FLAG0_LED;
+ /* Comptabile behavior with hid-sony, which used a dummy global LED to
+ * allow enabling/disabling the lightbar. The global LED maps to
+ * lightbar_enabled.
+ */
+ common->lightbar_red = ds4->lightbar_enabled ? ds4->lightbar_red : 0;
+ common->lightbar_green = ds4->lightbar_enabled ? ds4->lightbar_green : 0;
+ common->lightbar_blue = ds4->lightbar_enabled ? ds4->lightbar_blue : 0;
+ ds4->update_lightbar = false;
+ }
+
+ if (ds4->update_lightbar_blink) {
+ common->valid_flag0 |= DS4_OUTPUT_VALID_FLAG0_LED_BLINK;
+ common->lightbar_blink_on = ds4->lightbar_blink_on;
+ common->lightbar_blink_off = ds4->lightbar_blink_off;
+ ds4->update_lightbar_blink = false;
+ }
+
+ spin_unlock_irqrestore(&ds4->base.lock, flags);
+
+ /* Bluetooth packets need additional flags as well as a CRC in the last 4 bytes. */
+ if (report.bt) {
+ uint32_t crc;
+ uint8_t seed = PS_OUTPUT_CRC32_SEED;
+
+ /* Hardware control flags need to set to let the device know
+ * there is HID data as well as CRC.
+ */
+ report.bt->hw_control = DS4_OUTPUT_HWCTL_HID | DS4_OUTPUT_HWCTL_CRC32;
+
+ if (ds4->update_bt_poll_interval) {
+ report.bt->hw_control |= ds4->bt_poll_interval;
+ ds4->update_bt_poll_interval = false;
+ }
+
+ crc = crc32_le(0xFFFFFFFF, &seed, 1);
+ crc = ~crc32_le(crc, report.data, report.len - 4);
+
+ report.bt->crc32 = cpu_to_le32(crc);
+ }
+
+ hid_hw_output_report(ds4->base.hdev, report.data, report.len);
+}
+
+static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report *report,
+ u8 *data, int size)
+{
+ struct hid_device *hdev = ps_dev->hdev;
+ struct dualshock4 *ds4 = container_of(ps_dev, struct dualshock4, base);
+ struct dualshock4_input_report_common *ds4_report;
+ struct dualshock4_touch_report *touch_reports;
+ uint8_t battery_capacity, num_touch_reports, value;
+ int battery_status, i, j;
+ uint16_t sensor_timestamp;
+ unsigned long flags;
+
+ /*
+ * DualShock4 in USB uses the full HID report for reportID 1, but
+ * Bluetooth uses a minimal HID report for reportID 1 and reports
+ * the full report using reportID 17.
+ */
+ if (hdev->bus == BUS_USB && report->id == DS4_INPUT_REPORT_USB &&
+ size == DS4_INPUT_REPORT_USB_SIZE) {
+ struct dualshock4_input_report_usb *usb = (struct dualshock4_input_report_usb *)data;
+
+ ds4_report = &usb->common;
+ num_touch_reports = usb->num_touch_reports;
+ touch_reports = usb->touch_reports;
+ } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT &&
+ size == DS4_INPUT_REPORT_BT_SIZE) {
+ struct dualshock4_input_report_bt *bt = (struct dualshock4_input_report_bt *)data;
+ uint32_t report_crc = get_unaligned_le32(&bt->crc32);
+
+ /* Last 4 bytes of input report contains CRC. */
+ if (!ps_check_crc32(PS_INPUT_CRC32_SEED, data, size - 4, report_crc)) {
+ hid_err(hdev, "DualShock4 input CRC's check failed\n");
+ return -EILSEQ;
+ }
+
+ ds4_report = &bt->common;
+ num_touch_reports = bt->num_touch_reports;
+ touch_reports = bt->touch_reports;
+ } else {
+ hid_err(hdev, "Unhandled reportID=%d\n", report->id);
+ return -1;
+ }
+
+ input_report_abs(ds4->gamepad, ABS_X, ds4_report->x);
+ input_report_abs(ds4->gamepad, ABS_Y, ds4_report->y);
+ input_report_abs(ds4->gamepad, ABS_RX, ds4_report->rx);
+ input_report_abs(ds4->gamepad, ABS_RY, ds4_report->ry);
+ input_report_abs(ds4->gamepad, ABS_Z, ds4_report->z);
+ input_report_abs(ds4->gamepad, ABS_RZ, ds4_report->rz);
+
+ value = ds4_report->buttons[0] & DS_BUTTONS0_HAT_SWITCH;
+ if (value >= ARRAY_SIZE(ps_gamepad_hat_mapping))
+ value = 8; /* center */
+ input_report_abs(ds4->gamepad, ABS_HAT0X, ps_gamepad_hat_mapping[value].x);
+ input_report_abs(ds4->gamepad, ABS_HAT0Y, ps_gamepad_hat_mapping[value].y);
+
+ input_report_key(ds4->gamepad, BTN_WEST, ds4_report->buttons[0] & DS_BUTTONS0_SQUARE);
+ input_report_key(ds4->gamepad, BTN_SOUTH, ds4_report->buttons[0] & DS_BUTTONS0_CROSS);
+ input_report_key(ds4->gamepad, BTN_EAST, ds4_report->buttons[0] & DS_BUTTONS0_CIRCLE);
+ input_report_key(ds4->gamepad, BTN_NORTH, ds4_report->buttons[0] & DS_BUTTONS0_TRIANGLE);
+ input_report_key(ds4->gamepad, BTN_TL, ds4_report->buttons[1] & DS_BUTTONS1_L1);
+ input_report_key(ds4->gamepad, BTN_TR, ds4_report->buttons[1] & DS_BUTTONS1_R1);
+ input_report_key(ds4->gamepad, BTN_TL2, ds4_report->buttons[1] & DS_BUTTONS1_L2);
+ input_report_key(ds4->gamepad, BTN_TR2, ds4_report->buttons[1] & DS_BUTTONS1_R2);
+ input_report_key(ds4->gamepad, BTN_SELECT, ds4_report->buttons[1] & DS_BUTTONS1_CREATE);
+ input_report_key(ds4->gamepad, BTN_START, ds4_report->buttons[1] & DS_BUTTONS1_OPTIONS);
+ input_report_key(ds4->gamepad, BTN_THUMBL, ds4_report->buttons[1] & DS_BUTTONS1_L3);
+ input_report_key(ds4->gamepad, BTN_THUMBR, ds4_report->buttons[1] & DS_BUTTONS1_R3);
+ input_report_key(ds4->gamepad, BTN_MODE, ds4_report->buttons[2] & DS_BUTTONS2_PS_HOME);
+ input_sync(ds4->gamepad);
+
+ /* Parse and calibrate gyroscope data. */
+ for (i = 0; i < ARRAY_SIZE(ds4_report->gyro); i++) {
+ int raw_data = (short)le16_to_cpu(ds4_report->gyro[i]);
+ int calib_data = mult_frac(ds4->gyro_calib_data[i].sens_numer,
+ raw_data - ds4->gyro_calib_data[i].bias,
+ ds4->gyro_calib_data[i].sens_denom);
+
+ input_report_abs(ds4->sensors, ds4->gyro_calib_data[i].abs_code, calib_data);
+ }
+
+ /* Parse and calibrate accelerometer data. */
+ for (i = 0; i < ARRAY_SIZE(ds4_report->accel); i++) {
+ int raw_data = (short)le16_to_cpu(ds4_report->accel[i]);
+ int calib_data = mult_frac(ds4->accel_calib_data[i].sens_numer,
+ raw_data - ds4->accel_calib_data[i].bias,
+ ds4->accel_calib_data[i].sens_denom);
+
+ input_report_abs(ds4->sensors, ds4->accel_calib_data[i].abs_code, calib_data);
+ }
+
+ /* Convert timestamp (in 5.33us unit) to timestamp_us */
+ sensor_timestamp = le16_to_cpu(ds4_report->sensor_timestamp);
+ if (!ds4->sensor_timestamp_initialized) {
+ ds4->sensor_timestamp_us = DIV_ROUND_CLOSEST(sensor_timestamp*16, 3);
+ ds4->sensor_timestamp_initialized = true;
+ } else {
+ uint16_t delta;
+
+ if (ds4->prev_sensor_timestamp > sensor_timestamp)
+ delta = (U16_MAX - ds4->prev_sensor_timestamp + sensor_timestamp + 1);
+ else
+ delta = sensor_timestamp - ds4->prev_sensor_timestamp;
+ ds4->sensor_timestamp_us += DIV_ROUND_CLOSEST(delta*16, 3);
+ }
+ ds4->prev_sensor_timestamp = sensor_timestamp;
+ input_event(ds4->sensors, EV_MSC, MSC_TIMESTAMP, ds4->sensor_timestamp_us);
+ input_sync(ds4->sensors);
+
+ for (i = 0; i < num_touch_reports; i++) {
+ struct dualshock4_touch_report *touch_report = &touch_reports[i];
+
+ for (j = 0; j < ARRAY_SIZE(touch_report->points); j++) {
+ struct dualshock4_touch_point *point = &touch_report->points[j];
+ bool active = (point->contact & DS4_TOUCH_POINT_INACTIVE) ? false : true;
+
+ input_mt_slot(ds4->touchpad, j);
+ input_mt_report_slot_state(ds4->touchpad, MT_TOOL_FINGER, active);
+
+ if (active) {
+ int x = (point->x_hi << 8) | point->x_lo;
+ int y = (point->y_hi << 4) | point->y_lo;
+
+ input_report_abs(ds4->touchpad, ABS_MT_POSITION_X, x);
+ input_report_abs(ds4->touchpad, ABS_MT_POSITION_Y, y);
+ }
+ }
+ input_mt_sync_frame(ds4->touchpad);
+ input_sync(ds4->touchpad);
+ }
+ input_report_key(ds4->touchpad, BTN_LEFT, ds4_report->buttons[2] & DS_BUTTONS2_TOUCHPAD);
+
+ /*
+ * Interpretation of the battery_capacity data depends on the cable state.
+ * When no cable is connected (bit4 is 0):
+ * - 0:10: percentage in units of 10%.
+ * When a cable is plugged in:
+ * - 0-10: percentage in units of 10%.
+ * - 11: battery is full
+ * - 14: not charging due to Voltage or temperature error
+ * - 15: charge error
+ */
+ if (ds4_report->status[0] & DS4_STATUS0_CABLE_STATE) {
+ uint8_t battery_data = ds4_report->status[0] & DS4_STATUS0_BATTERY_CAPACITY;
+
+ if (battery_data < 10) {
+ /* Take the mid-point for each battery capacity value,
+ * because on the hardware side 0 = 0-9%, 1=10-19%, etc.
+ * This matches official platform behavior, which does
+ * the same.
+ */
+ battery_capacity = battery_data * 10 + 5;
+ battery_status = POWER_SUPPLY_STATUS_CHARGING;
+ } else if (battery_data == 10) {
+ battery_capacity = 100;
+ battery_status = POWER_SUPPLY_STATUS_CHARGING;
+ } else if (battery_data == DS4_BATTERY_STATUS_FULL) {
+ battery_capacity = 100;
+ battery_status = POWER_SUPPLY_STATUS_FULL;
+ } else { /* 14, 15 and undefined values */
+ battery_capacity = 0;
+ battery_status = POWER_SUPPLY_STATUS_UNKNOWN;
+ }
+ } else {
+ uint8_t battery_data = ds4_report->status[0] & DS4_STATUS0_BATTERY_CAPACITY;
+
+ if (battery_data < 10)
+ battery_capacity = battery_data * 10 + 5;
+ else /* 10 */
+ battery_capacity = 100;
+
+ battery_status = POWER_SUPPLY_STATUS_DISCHARGING;
+ }
+
+ spin_lock_irqsave(&ps_dev->lock, flags);
+ ps_dev->battery_capacity = battery_capacity;
+ ps_dev->battery_status = battery_status;
+ spin_unlock_irqrestore(&ps_dev->lock, flags);
+
+ return 0;
+}
+
+static int dualshock4_dongle_parse_report(struct ps_device *ps_dev, struct hid_report *report,
+ u8 *data, int size)
+{
+ struct dualshock4 *ds4 = container_of(ps_dev, struct dualshock4, base);
+ bool connected = false;
+
+ /* The dongle reports data using the main USB report (0x1) no matter whether a controller
+ * is connected with mostly zeros. The report does contain dongle status, which we use to
+ * determine if a controller is connected and if so we forward to the regular DualShock4
+ * parsing code.
+ */
+ if (data[0] == DS4_INPUT_REPORT_USB && size == DS4_INPUT_REPORT_USB_SIZE) {
+ struct dualshock4_input_report_common *ds4_report = (struct dualshock4_input_report_common *)&data[1];
+ unsigned long flags;
+
+ connected = ds4_report->status[1] & DS4_STATUS1_DONGLE_STATE ? false : true;
+
+ if (ds4->dongle_state == DONGLE_DISCONNECTED && connected) {
+ hid_info(ps_dev->hdev, "DualShock 4 USB dongle: controller connected\n");
+
+ dualshock4_set_default_lightbar_colors(ds4);
+
+ spin_lock_irqsave(&ps_dev->lock, flags);
+ ds4->dongle_state = DONGLE_CALIBRATING;
+ spin_unlock_irqrestore(&ps_dev->lock, flags);
+
+ schedule_work(&ds4->dongle_hotplug_worker);
+
+ /* Don't process the report since we don't have
+ * calibration data, but let hidraw have it anyway.
+ */
+ return 0;
+ } else if ((ds4->dongle_state == DONGLE_CONNECTED ||
+ ds4->dongle_state == DONGLE_DISABLED) && !connected) {
+ hid_info(ps_dev->hdev, "DualShock 4 USB dongle: controller disconnected\n");
+
+ spin_lock_irqsave(&ps_dev->lock, flags);
+ ds4->dongle_state = DONGLE_DISCONNECTED;
+ spin_unlock_irqrestore(&ps_dev->lock, flags);
+
+ /* Return 0, so hidraw can get the report. */
+ return 0;
+ } else if (ds4->dongle_state == DONGLE_CALIBRATING ||
+ ds4->dongle_state == DONGLE_DISABLED ||
+ ds4->dongle_state == DONGLE_DISCONNECTED) {
+ /* Return 0, so hidraw can get the report. */
+ return 0;
+ }
+ }
+
+ if (connected)
+ return dualshock4_parse_report(ps_dev, report, data, size);
+
+ return 0;
+}
+
+static int dualshock4_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect)
+{
+ struct hid_device *hdev = input_get_drvdata(dev);
+ struct dualshock4 *ds4 = hid_get_drvdata(hdev);
+ unsigned long flags;
+
+ if (effect->type != FF_RUMBLE)
+ return 0;
+
+ spin_lock_irqsave(&ds4->base.lock, flags);
+ ds4->update_rumble = true;
+ ds4->motor_left = effect->u.rumble.strong_magnitude / 256;
+ ds4->motor_right = effect->u.rumble.weak_magnitude / 256;
+ spin_unlock_irqrestore(&ds4->base.lock, flags);
+
+ dualshock4_schedule_work(ds4);
+ return 0;
+}
+
+static void dualshock4_remove(struct ps_device *ps_dev)
+{
+ struct dualshock4 *ds4 = container_of(ps_dev, struct dualshock4, base);
+ unsigned long flags;
+
+ spin_lock_irqsave(&ds4->base.lock, flags);
+ ds4->output_worker_initialized = false;
+ spin_unlock_irqrestore(&ds4->base.lock, flags);
+
+ cancel_work_sync(&ds4->output_worker);
+
+ if (ps_dev->hdev->product == USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE)
+ cancel_work_sync(&ds4->dongle_hotplug_worker);
+}
+
+static inline void dualshock4_schedule_work(struct dualshock4 *ds4)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ds4->base.lock, flags);
+ if (ds4->output_worker_initialized)
+ schedule_work(&ds4->output_worker);
+ spin_unlock_irqrestore(&ds4->base.lock, flags);
+}
+
+static void dualshock4_set_bt_poll_interval(struct dualshock4 *ds4, uint8_t interval)
+{
+ ds4->bt_poll_interval = interval;
+ ds4->update_bt_poll_interval = true;
+ dualshock4_schedule_work(ds4);
+}
+
+/* Set default lightbar color based on player. */
+static void dualshock4_set_default_lightbar_colors(struct dualshock4 *ds4)
+{
+ /* Use same player colors as PlayStation 4.
+ * Array of colors is in RGB.
+ */
+ static const int player_colors[4][3] = {
+ { 0x00, 0x00, 0x40 }, /* Blue */
+ { 0x40, 0x00, 0x00 }, /* Red */
+ { 0x00, 0x40, 0x00 }, /* Green */
+ { 0x20, 0x00, 0x20 } /* Pink */
+ };
+
+ uint8_t player_id = ds4->base.player_id % ARRAY_SIZE(player_colors);
+
+ ds4->lightbar_enabled = true;
+ ds4->lightbar_red = player_colors[player_id][0];
+ ds4->lightbar_green = player_colors[player_id][1];
+ ds4->lightbar_blue = player_colors[player_id][2];
+
+ ds4->update_lightbar = true;
+ dualshock4_schedule_work(ds4);
+}
+
+static struct ps_device *dualshock4_create(struct hid_device *hdev)
+{
+ struct dualshock4 *ds4;
+ struct ps_device *ps_dev;
+ uint8_t max_output_report_size;
+ int i, ret;
+
+ /* The DualShock4 has an RGB lightbar, which the original hid-sony driver
+ * exposed as a set of 4 LEDs for the 3 color channels and a global control.
+ * Ideally this should have used the multi-color LED class, which didn't exist
+ * yet. In addition the driver used a naming scheme not compliant with the LED
+ * naming spec by using "<mac_address>:<color>", which contained many colons.
+ * We use a more compliant by using "<device_name>:<color>" name now. Ideally
+ * would have been "<device_name>:<color>:indicator", but that would break
+ * existing applications (e.g. Android). Nothing matches against MAC address.
+ */
+ static const struct ps_led_info lightbar_leds_info[] = {
+ { NULL, "red", 255, dualshock4_led_get_brightness, dualshock4_led_set_brightness },
+ { NULL, "green", 255, dualshock4_led_get_brightness, dualshock4_led_set_brightness },
+ { NULL, "blue", 255, dualshock4_led_get_brightness, dualshock4_led_set_brightness },
+ { NULL, "global", 1, dualshock4_led_get_brightness, dualshock4_led_set_brightness,
+ dualshock4_led_set_blink },
+ };
+
+ ds4 = devm_kzalloc(&hdev->dev, sizeof(*ds4), GFP_KERNEL);
+ if (!ds4)
+ return ERR_PTR(-ENOMEM);
+
+ /*
+ * Patch version to allow userspace to distinguish between
+ * hid-generic vs hid-playstation axis and button mapping.
+ */
+ hdev->version |= HID_PLAYSTATION_VERSION_PATCH;
+
+ ps_dev = &ds4->base;
+ ps_dev->hdev = hdev;
+ spin_lock_init(&ps_dev->lock);
+ ps_dev->battery_capacity = 100; /* initial value until parse_report. */
+ ps_dev->battery_status = POWER_SUPPLY_STATUS_UNKNOWN;
+ ps_dev->parse_report = dualshock4_parse_report;
+ ps_dev->remove = dualshock4_remove;
+ INIT_WORK(&ds4->output_worker, dualshock4_output_worker);
+ ds4->output_worker_initialized = true;
+ hid_set_drvdata(hdev, ds4);
+
+ max_output_report_size = sizeof(struct dualshock4_output_report_bt);
+ ds4->output_report_dmabuf = devm_kzalloc(&hdev->dev, max_output_report_size, GFP_KERNEL);
+ if (!ds4->output_report_dmabuf)
+ return ERR_PTR(-ENOMEM);
+
+ if (hdev->product == USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE) {
+ ds4->dongle_state = DONGLE_DISCONNECTED;
+ INIT_WORK(&ds4->dongle_hotplug_worker, dualshock4_dongle_calibration_work);
+
+ /* Override parse report for dongle specific hotplug handling. */
+ ps_dev->parse_report = dualshock4_dongle_parse_report;
+ }
+
+ ret = dualshock4_get_mac_address(ds4);
+ if (ret) {
+ hid_err(hdev, "Failed to get MAC address from DualShock4\n");
+ return ERR_PTR(ret);
+ }
+ snprintf(hdev->uniq, sizeof(hdev->uniq), "%pMR", ds4->base.mac_address);
+
+ ret = dualshock4_get_firmware_info(ds4);
+ if (ret) {
+ hid_err(hdev, "Failed to get firmware info from DualShock4\n");
+ return ERR_PTR(ret);
+ }
+
+ ret = ps_devices_list_add(ps_dev);
+ if (ret)
+ return ERR_PTR(ret);
+
+ ret = dualshock4_get_calibration_data(ds4);
+ if (ret) {
+ hid_err(hdev, "Failed to get calibration data from DualShock4\n");
+ goto err;
+ }
+
+ ds4->gamepad = ps_gamepad_create(hdev, dualshock4_play_effect);
+ if (IS_ERR(ds4->gamepad)) {
+ ret = PTR_ERR(ds4->gamepad);
+ goto err;
+ }
+
+ /* Use gamepad input device name as primary device name for e.g. LEDs */
+ ps_dev->input_dev_name = dev_name(&ds4->gamepad->dev);
+
+ ds4->sensors = ps_sensors_create(hdev, DS4_ACC_RANGE, DS4_ACC_RES_PER_G,
+ DS4_GYRO_RANGE, DS4_GYRO_RES_PER_DEG_S);
+ if (IS_ERR(ds4->sensors)) {
+ ret = PTR_ERR(ds4->sensors);
+ goto err;
+ }
+
+ ds4->touchpad = ps_touchpad_create(hdev, DS4_TOUCHPAD_WIDTH, DS4_TOUCHPAD_HEIGHT, 2);
+ if (IS_ERR(ds4->touchpad)) {
+ ret = PTR_ERR(ds4->touchpad);
+ goto err;
+ }
+
+ ret = ps_device_register_battery(ps_dev);
+ if (ret)
+ goto err;
+
+ for (i = 0; i < ARRAY_SIZE(lightbar_leds_info); i++) {
+ const struct ps_led_info *led_info = &lightbar_leds_info[i];
+
+ ret = ps_led_register(ps_dev, &ds4->lightbar_leds[i], led_info);
+ if (ret < 0)
+ goto err;
+ }
+
+ dualshock4_set_bt_poll_interval(ds4, DS4_BT_DEFAULT_POLL_INTERVAL_MS);
+
+ ret = ps_device_set_player_id(ps_dev);
+ if (ret) {
+ hid_err(hdev, "Failed to assign player id for DualShock4: %d\n", ret);
+ goto err;
+ }
+
+ dualshock4_set_default_lightbar_colors(ds4);
+
+ /*
+ * Reporting hardware and firmware is important as there are frequent updates, which
+ * can change behavior.
+ */
+ hid_info(hdev, "Registered DualShock4 controller hw_version=0x%08x fw_version=0x%08x\n",
+ ds4->base.hw_version, ds4->base.fw_version);
+ return &ds4->base;
+
+err:
+ ps_devices_list_remove(ps_dev);
+ return ERR_PTR(ret);
+}
+
static int ps_raw_event(struct hid_device *hdev, struct hid_report *report,
u8 *data, int size)
{
@@ -1499,7 +2589,16 @@ static int ps_probe(struct hid_device *hdev, const struct hid_device_id *id)
goto err_stop;
}
- if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER ||
+ if (hdev->product == USB_DEVICE_ID_SONY_PS4_CONTROLLER ||
+ hdev->product == USB_DEVICE_ID_SONY_PS4_CONTROLLER_2 ||
+ hdev->product == USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE) {
+ dev = dualshock4_create(hdev);
+ if (IS_ERR(dev)) {
+ hid_err(hdev, "Failed to create dualshock4.\n");
+ ret = PTR_ERR(dev);
+ goto err_close;
+ }
+ } else if (hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER ||
hdev->product == USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) {
dev = dualsense_create(hdev);
if (IS_ERR(dev)) {
@@ -1533,6 +2632,13 @@ static void ps_remove(struct hid_device *hdev)
}
static const struct hid_device_id ps_devices[] = {
+ /* Sony DualShock 4 controllers for PS4 */
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) },
+ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE) },
+ /* Sony DualSense controllers for PS5 */
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) },
{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS5_CONTROLLER_2) },
diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c
index bb1f423f4ace..84e7ba5314d3 100644
--- a/drivers/hid/hid-rmi.c
+++ b/drivers/hid/hid-rmi.c
@@ -326,6 +326,8 @@ static int rmi_input_event(struct hid_device *hdev, u8 *data, int size)
if (!(test_bit(RMI_STARTED, &hdata->flags)))
return 0;
+ pm_wakeup_event(hdev->dev.parent, 0);
+
local_irq_save(flags);
rmi_set_attn_data(rmi_dev, data[1], &data[2], size - 2);
diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-sensor-custom.c
index 32c2306e240d..f444e63e9f36 100644
--- a/drivers/hid/hid-sensor-custom.c
+++ b/drivers/hid/hid-sensor-custom.c
@@ -62,7 +62,7 @@ struct hid_sensor_sample {
u32 raw_len;
} __packed;
-static struct attribute hid_custom_attrs[] = {
+static struct attribute hid_custom_attrs[HID_CUSTOM_TOTAL_ATTRS] = {
{.name = "name", .mode = S_IRUGO},
{.name = "units", .mode = S_IRUGO},
{.name = "unit-expo", .mode = S_IRUGO},
@@ -862,7 +862,7 @@ hid_sensor_register_platform_device(struct platform_device *pdev,
return ERR_PTR(-ENOMEM);
custom_pdev = platform_device_register_data(pdev->dev.parent, dev_name,
- PLATFORM_DEVID_NONE, hsdev,
+ PLATFORM_DEVID_AUTO, hsdev,
sizeof(*hsdev));
kfree(dev_name);
return custom_pdev;
diff --git a/drivers/hid/hid-uclogic-params-test.c b/drivers/hid/hid-uclogic-params-test.c
index 57ef5d3e4b74..bfa7ccb7d1e8 100644
--- a/drivers/hid/hid-uclogic-params-test.c
+++ b/drivers/hid/hid-uclogic-params-test.c
@@ -136,7 +136,7 @@ static void uclogic_parse_ugee_v2_desc_case_desc(struct uclogic_parse_ugee_v2_de
KUNIT_ARRAY_PARAM(uclogic_parse_ugee_v2_desc, uclogic_parse_ugee_v2_desc_cases,
uclogic_parse_ugee_v2_desc_case_desc);
-static void uclogic_parse_ugee_v2_desc_test(struct kunit *test)
+static void hid_test_uclogic_parse_ugee_v2_desc(struct kunit *test)
{
int res;
s32 desc_params[UCLOGIC_RDESC_PH_ID_NUM];
@@ -175,7 +175,7 @@ static void uclogic_parse_ugee_v2_desc_test(struct kunit *test)
}
static struct kunit_case hid_uclogic_params_test_cases[] = {
- KUNIT_CASE_PARAM(uclogic_parse_ugee_v2_desc_test,
+ KUNIT_CASE_PARAM(hid_test_uclogic_parse_ugee_v2_desc,
uclogic_parse_ugee_v2_desc_gen_params),
{}
};
diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c
index 34fa991e6267..cd1233d7e253 100644
--- a/drivers/hid/hid-uclogic-params.c
+++ b/drivers/hid/hid-uclogic-params.c
@@ -18,6 +18,7 @@
#include "usbhid/usbhid.h"
#include "hid-ids.h"
#include <linux/ctype.h>
+#include <linux/string.h>
#include <asm/unaligned.h>
/**
@@ -1212,6 +1213,69 @@ static int uclogic_params_ugee_v2_init_frame_mouse(struct uclogic_params *p)
}
/**
+ * uclogic_params_ugee_v2_has_battery() - check whether a UGEE v2 device has
+ * battery or not.
+ * @hdev: The HID device of the tablet interface.
+ *
+ * Returns:
+ * True if the device has battery, false otherwise.
+ */
+static bool uclogic_params_ugee_v2_has_battery(struct hid_device *hdev)
+{
+ /* The XP-PEN Deco LW vendor, product and version are identical to the
+ * Deco L. The only difference reported by their firmware is the product
+ * name. Add a quirk to support battery reporting on the wireless
+ * version.
+ */
+ if (hdev->vendor == USB_VENDOR_ID_UGEE &&
+ hdev->product == USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_L) {
+ struct usb_device *udev = hid_to_usb_dev(hdev);
+
+ if (strstarts(udev->product, "Deco LW"))
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * uclogic_params_ugee_v2_init_battery() - initialize UGEE v2 battery reporting.
+ * @hdev: The HID device of the tablet interface, cannot be NULL.
+ * @p: Parameters to fill in, cannot be NULL.
+ *
+ * Returns:
+ * Zero, if successful. A negative errno code on error.
+ */
+static int uclogic_params_ugee_v2_init_battery(struct hid_device *hdev,
+ struct uclogic_params *p)
+{
+ int rc = 0;
+
+ if (!hdev || !p)
+ return -EINVAL;
+
+ /* Some tablets contain invalid characters in hdev->uniq, throwing a
+ * "hwmon: '<name>' is not a valid name attribute, please fix" error.
+ * Use the device vendor and product IDs instead.
+ */
+ snprintf(hdev->uniq, sizeof(hdev->uniq), "%x-%x", hdev->vendor,
+ hdev->product);
+
+ rc = uclogic_params_frame_init_with_desc(&p->frame_list[1],
+ uclogic_rdesc_ugee_v2_battery_template_arr,
+ uclogic_rdesc_ugee_v2_battery_template_size,
+ UCLOGIC_RDESC_UGEE_V2_BATTERY_ID);
+ if (rc)
+ return rc;
+
+ p->frame_list[1].suffix = "Battery";
+ p->pen.subreport_list[1].value = 0xf2;
+ p->pen.subreport_list[1].id = UCLOGIC_RDESC_UGEE_V2_BATTERY_ID;
+
+ return rc;
+}
+
+/**
* uclogic_params_ugee_v2_init() - initialize a UGEE graphics tablets by
* discovering their parameters.
*
@@ -1334,6 +1398,15 @@ static int uclogic_params_ugee_v2_init(struct uclogic_params *params,
if (rc)
goto cleanup;
+ /* Initialize the battery interface*/
+ if (uclogic_params_ugee_v2_has_battery(hdev)) {
+ rc = uclogic_params_ugee_v2_init_battery(hdev, &p);
+ if (rc) {
+ hid_err(hdev, "error initializing battery: %d\n", rc);
+ goto cleanup;
+ }
+ }
+
output:
/* Output parameters */
memcpy(params, &p, sizeof(*params));
diff --git a/drivers/hid/hid-uclogic-rdesc-test.c b/drivers/hid/hid-uclogic-rdesc-test.c
index 3971a0854c3e..b429c541bf2f 100644
--- a/drivers/hid/hid-uclogic-rdesc-test.c
+++ b/drivers/hid/hid-uclogic-rdesc-test.c
@@ -187,7 +187,7 @@ static void uclogic_template_case_desc(struct uclogic_template_case *t,
KUNIT_ARRAY_PARAM(uclogic_template, uclogic_template_cases,
uclogic_template_case_desc);
-static void uclogic_template_test(struct kunit *test)
+static void hid_test_uclogic_template(struct kunit *test)
{
__u8 *res;
const struct uclogic_template_case *params = test->param_value;
@@ -203,7 +203,7 @@ static void uclogic_template_test(struct kunit *test)
}
static struct kunit_case hid_uclogic_rdesc_test_cases[] = {
- KUNIT_CASE_PARAM(uclogic_template_test, uclogic_template_gen_params),
+ KUNIT_CASE_PARAM(hid_test_uclogic_template, uclogic_template_gen_params),
{}
};
diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c
index 6b73eb0df6bd..fb40775f5f5b 100644
--- a/drivers/hid/hid-uclogic-rdesc.c
+++ b/drivers/hid/hid-uclogic-rdesc.c
@@ -1035,6 +1035,40 @@ const __u8 uclogic_rdesc_ugee_v2_frame_mouse_template_arr[] = {
const size_t uclogic_rdesc_ugee_v2_frame_mouse_template_size =
sizeof(uclogic_rdesc_ugee_v2_frame_mouse_template_arr);
+/* Fixed report descriptor template for UGEE v2 battery reports */
+const __u8 uclogic_rdesc_ugee_v2_battery_template_arr[] = {
+ 0x05, 0x01, /* Usage Page (Desktop), */
+ 0x09, 0x07, /* Usage (Keypad), */
+ 0xA1, 0x01, /* Collection (Application), */
+ 0x85, UCLOGIC_RDESC_UGEE_V2_BATTERY_ID,
+ /* Report ID, */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x02, /* Report Count (2), */
+ 0x81, 0x01, /* Input (Constant), */
+ 0x05, 0x84, /* Usage Page (Power Device), */
+ 0x05, 0x85, /* Usage Page (Battery System), */
+ 0x09, 0x65, /* Usage Page (AbsoluteStateOfCharge), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x15, 0x00, /* Logical Minimum (0), */
+ 0x26, 0xff, 0x00, /* Logical Maximum (255), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x75, 0x01, /* Report Size (1), */
+ 0x95, 0x01, /* Report Count (1), */
+ 0x15, 0x00, /* Logical Minimum (0), */
+ 0x25, 0x01, /* Logical Maximum (1), */
+ 0x09, 0x44, /* Usage Page (Charging), */
+ 0x81, 0x02, /* Input (Variable), */
+ 0x95, 0x07, /* Report Count (7), */
+ 0x81, 0x01, /* Input (Constant), */
+ 0x75, 0x08, /* Report Size (8), */
+ 0x95, 0x07, /* Report Count (7), */
+ 0x81, 0x01, /* Input (Constant), */
+ 0xC0 /* End Collection */
+};
+const size_t uclogic_rdesc_ugee_v2_battery_template_size =
+ sizeof(uclogic_rdesc_ugee_v2_battery_template_arr);
+
/* Fixed report descriptor for Ugee EX07 frame */
const __u8 uclogic_rdesc_ugee_ex07_frame_arr[] = {
0x05, 0x01, /* Usage Page (Desktop), */
diff --git a/drivers/hid/hid-uclogic-rdesc.h b/drivers/hid/hid-uclogic-rdesc.h
index 0502a0656496..a1f78c07293f 100644
--- a/drivers/hid/hid-uclogic-rdesc.h
+++ b/drivers/hid/hid-uclogic-rdesc.h
@@ -161,6 +161,9 @@ extern const size_t uclogic_rdesc_v2_frame_dial_size;
/* Device ID byte offset in v2 frame dial reports */
#define UCLOGIC_RDESC_V2_FRAME_DIAL_DEV_ID_BYTE 0x4
+/* Report ID for tweaked UGEE v2 battery reports */
+#define UCLOGIC_RDESC_UGEE_V2_BATTERY_ID 0xba
+
/* Fixed report descriptor template for UGEE v2 pen reports */
extern const __u8 uclogic_rdesc_ugee_v2_pen_template_arr[];
extern const size_t uclogic_rdesc_ugee_v2_pen_template_size;
@@ -177,6 +180,10 @@ extern const size_t uclogic_rdesc_ugee_v2_frame_dial_template_size;
extern const __u8 uclogic_rdesc_ugee_v2_frame_mouse_template_arr[];
extern const size_t uclogic_rdesc_ugee_v2_frame_mouse_template_size;
+/* Fixed report descriptor template for UGEE v2 battery reports */
+extern const __u8 uclogic_rdesc_ugee_v2_battery_template_arr[];
+extern const size_t uclogic_rdesc_ugee_v2_battery_template_size;
+
/* Fixed report descriptor for Ugee EX07 frame */
extern const __u8 uclogic_rdesc_ugee_ex07_frame_arr[];
extern const size_t uclogic_rdesc_ugee_ex07_frame_size;
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 4399d6c6afef..09db8111dc26 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -458,6 +458,9 @@ static __u8 wiimote_cmd_read_ext(struct wiimote_data *wdata, __u8 *rmem)
if (rmem[0] == 0x00 && rmem[1] == 0x00 &&
rmem[4] == 0x01 && rmem[5] == 0x03)
return WIIMOTE_EXT_GUITAR;
+ if (rmem[0] == 0x03 && rmem[1] == 0x00 &&
+ rmem[4] == 0x01 && rmem[5] == 0x03)
+ return WIIMOTE_EXT_TURNTABLE;
return WIIMOTE_EXT_UNKNOWN;
}
@@ -495,6 +498,7 @@ static bool wiimote_cmd_map_mp(struct wiimote_data *wdata, __u8 exttype)
case WIIMOTE_EXT_GUITAR:
wmem = 0x07;
break;
+ case WIIMOTE_EXT_TURNTABLE:
case WIIMOTE_EXT_NUNCHUK:
wmem = 0x05;
break;
@@ -1082,6 +1086,7 @@ static const char *wiimote_exttype_names[WIIMOTE_EXT_NUM] = {
[WIIMOTE_EXT_PRO_CONTROLLER] = "Nintendo Wii U Pro Controller",
[WIIMOTE_EXT_DRUMS] = "Nintendo Wii Drums",
[WIIMOTE_EXT_GUITAR] = "Nintendo Wii Guitar",
+ [WIIMOTE_EXT_TURNTABLE] = "Nintendo Wii Turntable"
};
/*
@@ -1669,6 +1674,8 @@ static ssize_t wiimote_ext_show(struct device *dev,
return sprintf(buf, "drums\n");
case WIIMOTE_EXT_GUITAR:
return sprintf(buf, "guitar\n");
+ case WIIMOTE_EXT_TURNTABLE:
+ return sprintf(buf, "turntable\n");
case WIIMOTE_EXT_UNKNOWN:
default:
return sprintf(buf, "unknown\n");
diff --git a/drivers/hid/hid-wiimote-modules.c b/drivers/hid/hid-wiimote-modules.c
index 213c58bf2495..dbccdfa63916 100644
--- a/drivers/hid/hid-wiimote-modules.c
+++ b/drivers/hid/hid-wiimote-modules.c
@@ -2403,6 +2403,230 @@ static const struct wiimod_ops wiimod_guitar = {
.in_ext = wiimod_guitar_in_ext,
};
+/*
+ * Turntable
+ * DJ Hero came with a Turntable Controller that was plugged in
+ * as an extension.
+ * We create a separate device for turntables and report all information via this
+ * input device.
+*/
+
+enum wiimod_turntable_keys {
+ WIIMOD_TURNTABLE_KEY_G_RIGHT,
+ WIIMOD_TURNTABLE_KEY_R_RIGHT,
+ WIIMOD_TURNTABLE_KEY_B_RIGHT,
+ WIIMOD_TURNTABLE_KEY_G_LEFT,
+ WIIMOD_TURNTABLE_KEY_R_LEFT,
+ WIIMOD_TURNTABLE_KEY_B_LEFT,
+ WIIMOD_TURNTABLE_KEY_EUPHORIA,
+ WIIMOD_TURNTABLE_KEY_PLUS,
+ WIIMOD_TURNTABLE_KEY_MINUS,
+ WIIMOD_TURNTABLE_KEY_NUM
+};
+
+static const __u16 wiimod_turntable_map[] = {
+ BTN_1, /* WIIMOD_TURNTABLE_KEY_G_RIGHT */
+ BTN_2, /* WIIMOD_TURNTABLE_KEY_R_RIGHT */
+ BTN_3, /* WIIMOD_TURNTABLE_KEY_B_RIGHT */
+ BTN_4, /* WIIMOD_TURNTABLE_KEY_G_LEFT */
+ BTN_5, /* WIIMOD_TURNTABLE_KEY_R_LEFT */
+ BTN_6, /* WIIMOD_TURNTABLE_KEY_B_LEFT */
+ BTN_7, /* WIIMOD_TURNTABLE_KEY_EUPHORIA */
+ BTN_START, /* WIIMOD_TURNTABLE_KEY_PLUS */
+ BTN_SELECT, /* WIIMOD_TURNTABLE_KEY_MINUS */
+};
+
+static void wiimod_turntable_in_ext(struct wiimote_data *wdata, const __u8 *ext)
+{
+ __u8 be, cs, sx, sy, ed, rtt, rbg, rbr, rbb, ltt, lbg, lbr, lbb, bp, bm;
+ /*
+ * Byte | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ *------+------+-----+-----+-----+-----+------+------+--------+
+ * 0 | RTT<4:3> | SX <5:0> |
+ * 1 | RTT<2:1> | SY <5:0> |
+ *------+------+-----+-----+-----+-----+------+------+--------+
+ * 2 |RTT<0>| ED<4:3> | CS<3:0> | RTT<5> |
+ *------+------+-----+-----+-----+-----+------+------+--------+
+ * 3 | ED<2:0> | LTT<4:0> |
+ *------+------+-----+-----+-----+-----+------+------+--------+
+ * 4 | 0 | 0 | LBR | B- | 0 | B+ | RBR | LTT<5> |
+ *------+------+-----+-----+-----+-----+------+------+--------+
+ * 5 | LBB | 0 | RBG | BE | LBG | RBB | 0 | 0 |
+ *------+------+-----+-----+-----+-----+------+------+--------+
+ * All pressed buttons are 0
+ *
+ * With Motion+ enabled, it will look like this:
+ * Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
+ *------+------+-----+-----+-----+-----+------+------+--------+
+ * 1 | RTT<4:3> | SX <5:1> | 0 |
+ * 2 | RTT<2:1> | SY <5:1> | 0 |
+ *------+------+-----+-----+-----+-----+------+------+--------+
+ * 3 |RTT<0>| ED<4:3> | CS<3:0> | RTT<5> |
+ *------+------+-----+-----+-----+-----+------+------+--------+
+ * 4 | ED<2:0> | LTT<4:0> |
+ *------+------+-----+-----+-----+-----+------+------+--------+
+ * 5 | 0 | 0 | LBR | B- | 0 | B+ | RBR | XXXX |
+ *------+------+-----+-----+-----+-----+------+------+--------+
+ * 6 | LBB | 0 | RBG | BE | LBG | RBB | XXXX | XXXX |
+ *------+------+-----+-----+-----+-----+------+------+--------+
+ */
+
+ be = !(ext[5] & 0x10);
+ cs = ((ext[2] & 0x1e));
+ sx = ext[0] & 0x3f;
+ sy = ext[1] & 0x3f;
+ ed = (ext[3] & 0xe0) >> 5;
+ rtt = ((ext[2] & 0x01) << 5 | (ext[0] & 0xc0) >> 3 | (ext[1] & 0xc0) >> 5 | ( ext[2] & 0x80 ) >> 7);
+ ltt = ((ext[4] & 0x01) << 5 | (ext[3] & 0x1f));
+ rbg = !(ext[5] & 0x20);
+ rbr = !(ext[4] & 0x02);
+ rbb = !(ext[5] & 0x04);
+ lbg = !(ext[5] & 0x08);
+ lbb = !(ext[5] & 0x80);
+ lbr = !(ext[4] & 0x20);
+ bm = !(ext[4] & 0x10);
+ bp = !(ext[4] & 0x04);
+
+ if (wdata->state.flags & WIIPROTO_FLAG_MP_ACTIVE) {
+ ltt = (ext[4] & 0x01) << 5;
+ sx &= 0x3e;
+ sy &= 0x3e;
+ }
+
+ input_report_abs(wdata->extension.input, ABS_X, sx);
+ input_report_abs(wdata->extension.input, ABS_Y, sy);
+ input_report_abs(wdata->extension.input, ABS_HAT0X, rtt);
+ input_report_abs(wdata->extension.input, ABS_HAT1X, ltt);
+ input_report_abs(wdata->extension.input, ABS_HAT2X, cs);
+ input_report_abs(wdata->extension.input, ABS_HAT3X, ed);
+ input_report_key(wdata->extension.input,
+ wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_G_RIGHT],
+ rbg);
+ input_report_key(wdata->extension.input,
+ wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_R_RIGHT],
+ rbr);
+ input_report_key(wdata->extension.input,
+ wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_B_RIGHT],
+ rbb);
+ input_report_key(wdata->extension.input,
+ wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_G_LEFT],
+ lbg);
+ input_report_key(wdata->extension.input,
+ wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_R_LEFT],
+ lbr);
+ input_report_key(wdata->extension.input,
+ wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_B_LEFT],
+ lbb);
+ input_report_key(wdata->extension.input,
+ wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_EUPHORIA],
+ be);
+ input_report_key(wdata->extension.input,
+ wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_PLUS],
+ bp);
+ input_report_key(wdata->extension.input,
+ wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_MINUS],
+ bm);
+
+ input_sync(wdata->extension.input);
+}
+
+static int wiimod_turntable_open(struct input_dev *dev)
+{
+ struct wiimote_data *wdata = input_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->state.flags |= WIIPROTO_FLAG_EXT_USED;
+ wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+
+ return 0;
+}
+
+static void wiimod_turntable_close(struct input_dev *dev)
+{
+ struct wiimote_data *wdata = input_get_drvdata(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&wdata->state.lock, flags);
+ wdata->state.flags &= ~WIIPROTO_FLAG_EXT_USED;
+ wiiproto_req_drm(wdata, WIIPROTO_REQ_NULL);
+ spin_unlock_irqrestore(&wdata->state.lock, flags);
+}
+
+static int wiimod_turntable_probe(const struct wiimod_ops *ops,
+ struct wiimote_data *wdata)
+{
+ int ret, i;
+
+ wdata->extension.input = input_allocate_device();
+ if (!wdata->extension.input)
+ return -ENOMEM;
+
+ input_set_drvdata(wdata->extension.input, wdata);
+ wdata->extension.input->open = wiimod_turntable_open;
+ wdata->extension.input->close = wiimod_turntable_close;
+ wdata->extension.input->dev.parent = &wdata->hdev->dev;
+ wdata->extension.input->id.bustype = wdata->hdev->bus;
+ wdata->extension.input->id.vendor = wdata->hdev->vendor;
+ wdata->extension.input->id.product = wdata->hdev->product;
+ wdata->extension.input->id.version = wdata->hdev->version;
+ wdata->extension.input->name = WIIMOTE_NAME " Turntable";
+
+ set_bit(EV_KEY, wdata->extension.input->evbit);
+ for (i = 0; i < WIIMOD_TURNTABLE_KEY_NUM; ++i)
+ set_bit(wiimod_turntable_map[i],
+ wdata->extension.input->keybit);
+
+ set_bit(EV_ABS, wdata->extension.input->evbit);
+ set_bit(ABS_X, wdata->extension.input->absbit);
+ set_bit(ABS_Y, wdata->extension.input->absbit);
+ set_bit(ABS_HAT0X, wdata->extension.input->absbit);
+ set_bit(ABS_HAT1X, wdata->extension.input->absbit);
+ set_bit(ABS_HAT2X, wdata->extension.input->absbit);
+ set_bit(ABS_HAT3X, wdata->extension.input->absbit);
+ input_set_abs_params(wdata->extension.input,
+ ABS_X, 0, 63, 1, 0);
+ input_set_abs_params(wdata->extension.input,
+ ABS_Y, 63, 0, 1, 0);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT0X, -8, 8, 0, 0);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT1X, -8, 8, 0, 0);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT2X, 0, 31, 1, 1);
+ input_set_abs_params(wdata->extension.input,
+ ABS_HAT3X, 0, 7, 0, 0);
+ ret = input_register_device(wdata->extension.input);
+ if (ret)
+ goto err_free;
+
+ return 0;
+
+err_free:
+ input_free_device(wdata->extension.input);
+ wdata->extension.input = NULL;
+ return ret;
+}
+
+static void wiimod_turntable_remove(const struct wiimod_ops *ops,
+ struct wiimote_data *wdata)
+{
+ if (!wdata->extension.input)
+ return;
+
+ input_unregister_device(wdata->extension.input);
+ wdata->extension.input = NULL;
+}
+
+static const struct wiimod_ops wiimod_turntable = {
+ .flags = 0,
+ .arg = 0,
+ .probe = wiimod_turntable_probe,
+ .remove = wiimod_turntable_remove,
+ .in_ext = wiimod_turntable_in_ext,
+};
+
/*
* Builtin Motion Plus
* This module simply sets the WIIPROTO_FLAG_BUILTIN_MP protocol flag which
@@ -2657,4 +2881,5 @@ const struct wiimod_ops *wiimod_ext_table[WIIMOTE_EXT_NUM] = {
[WIIMOTE_EXT_PRO_CONTROLLER] = &wiimod_pro,
[WIIMOTE_EXT_DRUMS] = &wiimod_drums,
[WIIMOTE_EXT_GUITAR] = &wiimod_guitar,
+ [WIIMOTE_EXT_TURNTABLE] = &wiimod_turntable,
};
diff --git a/drivers/hid/hid-wiimote.h b/drivers/hid/hid-wiimote.h
index ad4ff837f43e..9c12f63f6dd2 100644
--- a/drivers/hid/hid-wiimote.h
+++ b/drivers/hid/hid-wiimote.h
@@ -88,6 +88,7 @@ enum wiimote_exttype {
WIIMOTE_EXT_PRO_CONTROLLER,
WIIMOTE_EXT_DRUMS,
WIIMOTE_EXT_GUITAR,
+ WIIMOTE_EXT_TURNTABLE,
WIIMOTE_EXT_NUM,
};
diff --git a/drivers/hid/i2c-hid/i2c-hid-acpi.c b/drivers/hid/i2c-hid/i2c-hid-acpi.c
index b96ae15e0ad9..375c77c3db74 100644
--- a/drivers/hid/i2c-hid/i2c-hid-acpi.c
+++ b/drivers/hid/i2c-hid/i2c-hid-acpi.c
@@ -105,11 +105,6 @@ static int i2c_hid_acpi_probe(struct i2c_client *client)
acpi_device_fix_up_power(adev);
- if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) {
- device_set_wakeup_capable(dev, true);
- device_set_wakeup_enable(dev, false);
- }
-
return i2c_hid_core_probe(client, &ihid_acpi->ops,
hid_descriptor_address, 0);
}
diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
index 0667b6022c3b..b86b62f97108 100644
--- a/drivers/hid/i2c-hid/i2c-hid-core.c
+++ b/drivers/hid/i2c-hid/i2c-hid-core.c
@@ -26,6 +26,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/pm.h>
+#include <linux/pm_wakeirq.h>
#include <linux/device.h>
#include <linux/wait.h>
#include <linux/err.h>
@@ -112,7 +113,6 @@ struct i2c_hid {
wait_queue_head_t wait; /* For waiting the interrupt */
- bool irq_wake_enabled;
struct mutex reset_lock;
struct i2chid_ops *ops;
@@ -554,7 +554,8 @@ static void i2c_hid_get_input(struct i2c_hid *ihid)
i2c_hid_dbg(ihid, "input: %*ph\n", ret_size, ihid->inbuf);
if (test_bit(I2C_HID_STARTED, &ihid->flags)) {
- pm_wakeup_event(&ihid->client->dev, 0);
+ if (ihid->hid->group != HID_GROUP_RMI)
+ pm_wakeup_event(&ihid->client->dev, 0);
hid_input_report(ihid->hid, HID_INPUT_REPORT,
ihid->inbuf + sizeof(__le16),
@@ -1099,7 +1100,6 @@ static int i2c_hid_core_suspend(struct device *dev)
struct i2c_hid *ihid = i2c_get_clientdata(client);
struct hid_device *hid = ihid->hid;
int ret;
- int wake_status;
ret = hid_driver_suspend(hid, PMSG_SUSPEND);
if (ret < 0)
@@ -1110,16 +1110,8 @@ static int i2c_hid_core_suspend(struct device *dev)
disable_irq(client->irq);
- if (device_may_wakeup(&client->dev)) {
- wake_status = enable_irq_wake(client->irq);
- if (!wake_status)
- ihid->irq_wake_enabled = true;
- else
- hid_warn(hid, "Failed to enable irq wake: %d\n",
- wake_status);
- } else {
+ if (!device_may_wakeup(&client->dev))
i2c_hid_core_power_down(ihid);
- }
return 0;
}
@@ -1130,18 +1122,9 @@ static int i2c_hid_core_resume(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct i2c_hid *ihid = i2c_get_clientdata(client);
struct hid_device *hid = ihid->hid;
- int wake_status;
- if (!device_may_wakeup(&client->dev)) {
+ if (!device_may_wakeup(&client->dev))
i2c_hid_core_power_up(ihid);
- } else if (ihid->irq_wake_enabled) {
- wake_status = disable_irq_wake(client->irq);
- if (!wake_status)
- ihid->irq_wake_enabled = false;
- else
- hid_warn(hid, "Failed to disable irq wake: %d\n",
- wake_status);
- }
enable_irq(client->irq);
diff --git a/drivers/hid/i2c-hid/i2c-hid-of-elan.c b/drivers/hid/i2c-hid/i2c-hid-of-elan.c
index 2d991325e734..76ddc8be1cbb 100644
--- a/drivers/hid/i2c-hid/i2c-hid-of-elan.c
+++ b/drivers/hid/i2c-hid/i2c-hid-of-elan.c
@@ -68,8 +68,7 @@ static void elan_i2c_hid_power_down(struct i2chid_ops *ops)
regulator_disable(ihid_elan->vcc33);
}
-static int i2c_hid_of_elan_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int i2c_hid_of_elan_probe(struct i2c_client *client)
{
struct i2c_hid_of_elan *ihid_elan;
@@ -119,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 = i2c_hid_of_elan_probe,
+ .probe_new = 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 ec6c73f75ffe..29c6cb174032 100644
--- a/drivers/hid/i2c-hid/i2c-hid-of-goodix.c
+++ b/drivers/hid/i2c-hid/i2c-hid-of-goodix.c
@@ -87,8 +87,7 @@ static int ihid_goodix_vdd_notify(struct notifier_block *nb,
return ret;
}
-static int i2c_hid_of_goodix_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int i2c_hid_of_goodix_probe(struct i2c_client *client)
{
struct i2c_hid_of_goodix *ihid_goodix;
int ret;
@@ -167,7 +166,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 = i2c_hid_of_goodix_probe,
+ .probe_new = 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 97a27a803f58..10176568133a 100644
--- a/drivers/hid/i2c-hid/i2c-hid-of.c
+++ b/drivers/hid/i2c-hid/i2c-hid-of.c
@@ -66,8 +66,7 @@ static void i2c_hid_of_power_down(struct i2chid_ops *ops)
ihid_of->supplies);
}
-static int i2c_hid_of_probe(struct i2c_client *client,
- const struct i2c_device_id *dev_id)
+static int i2c_hid_of_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct i2c_hid_of *ihid_of;
@@ -138,7 +137,7 @@ static struct i2c_driver i2c_hid_of_driver = {
.of_match_table = of_match_ptr(i2c_hid_of_match),
},
- .probe = i2c_hid_of_probe,
+ .probe_new = 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/ishtp/client.c b/drivers/hid/intel-ish-hid/ishtp/client.c
index df0a825694f5..2d92fc129ce4 100644
--- a/drivers/hid/intel-ish-hid/ishtp/client.c
+++ b/drivers/hid/intel-ish-hid/ishtp/client.c
@@ -841,7 +841,6 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
unsigned char *buffer = NULL;
struct ishtp_cl_rb *complete_rb = NULL;
unsigned long flags;
- int rb_count;
if (ishtp_hdr->reserved) {
dev_err(dev->devc, "corrupted message header.\n");
@@ -855,9 +854,7 @@ void recv_ishtp_cl_msg(struct ishtp_device *dev,
}
spin_lock_irqsave(&dev->read_list_spinlock, flags);
- rb_count = -1;
list_for_each_entry(rb, &dev->read_list.list, list) {
- ++rb_count;
cl = rb->cl;
if (!cl || !(cl->host_client_id == ishtp_hdr->host_addr &&
cl->fw_client_id == ishtp_hdr->fw_addr) ||
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
index 6c127f061f06..cbe43e2567a7 100644
--- a/drivers/hv/hv_balloon.c
+++ b/drivers/hv/hv_balloon.c
@@ -469,12 +469,16 @@ static bool do_hot_add;
* the specified number of seconds.
*/
static uint pressure_report_delay = 45;
+extern unsigned int page_reporting_order;
+#define HV_MAX_FAILURES 2
/*
* The last time we posted a pressure report to host.
*/
static unsigned long last_post_time;
+static int hv_hypercall_multi_failure;
+
module_param(hot_add, bool, (S_IRUGO | S_IWUSR));
MODULE_PARM_DESC(hot_add, "If set attempt memory hot_add");
@@ -579,6 +583,10 @@ static struct hv_dynmem_device dm_device;
static void post_status(struct hv_dynmem_device *dm);
+static void enable_page_reporting(void);
+
+static void disable_page_reporting(void);
+
#ifdef CONFIG_MEMORY_HOTPLUG
static inline bool has_pfn_is_backed(struct hv_hotadd_state *has,
unsigned long pfn)
@@ -1418,6 +1426,18 @@ static int dm_thread_func(void *dm_dev)
*/
reinit_completion(&dm_device.config_event);
post_status(dm);
+ /*
+ * disable free page reporting if multiple hypercall
+ * failure flag set. It is not done in the page_reporting
+ * callback context as that causes a deadlock between
+ * page_reporting_process() and page_reporting_unregister()
+ */
+ if (hv_hypercall_multi_failure >= HV_MAX_FAILURES) {
+ pr_err("Multiple failures in cold memory discard hypercall, disabling page reporting\n");
+ disable_page_reporting();
+ /* Reset the flag after disabling reporting */
+ hv_hypercall_multi_failure = 0;
+ }
}
return 0;
@@ -1593,20 +1613,20 @@ static void balloon_onchannelcallback(void *context)
}
-/* Hyper-V only supports reporting 2MB pages or higher */
-#define HV_MIN_PAGE_REPORTING_ORDER 9
-#define HV_MIN_PAGE_REPORTING_LEN (HV_HYP_PAGE_SIZE << HV_MIN_PAGE_REPORTING_ORDER)
+#define HV_LARGE_REPORTING_ORDER 9
+#define HV_LARGE_REPORTING_LEN (HV_HYP_PAGE_SIZE << \
+ HV_LARGE_REPORTING_ORDER)
static int hv_free_page_report(struct page_reporting_dev_info *pr_dev_info,
struct scatterlist *sgl, unsigned int nents)
{
unsigned long flags;
struct hv_memory_hint *hint;
- int i;
+ int i, order;
u64 status;
struct scatterlist *sg;
WARN_ON_ONCE(nents > HV_MEMORY_HINT_MAX_GPA_PAGE_RANGES);
- WARN_ON_ONCE(sgl->length < HV_MIN_PAGE_REPORTING_LEN);
+ 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);
if (!hint) {
@@ -1621,21 +1641,53 @@ static int hv_free_page_report(struct page_reporting_dev_info *pr_dev_info,
range = &hint->ranges[i];
range->address_space = 0;
- /* page reporting only reports 2MB pages or higher */
- range->page.largepage = 1;
- range->page.additional_pages =
- (sg->length / HV_MIN_PAGE_REPORTING_LEN) - 1;
- range->page_size = HV_GPA_PAGE_RANGE_PAGE_SIZE_2MB;
- range->base_large_pfn =
- page_to_hvpfn(sg_page(sg)) >> HV_MIN_PAGE_REPORTING_ORDER;
+ order = get_order(sg->length);
+ /*
+ * Hyper-V expects the additional_pages field in the units
+ * of one of these 3 sizes, 4Kbytes, 2Mbytes or 1Gbytes.
+ * This is dictated by the values of the fields page.largesize
+ * and page_size.
+ * This code however, only uses 4Kbytes and 2Mbytes units
+ * and not 1Gbytes unit.
+ */
+
+ /* page reporting for pages 2MB or higher */
+ if (order >= HV_LARGE_REPORTING_ORDER ) {
+ range->page.largepage = 1;
+ range->page_size = HV_GPA_PAGE_RANGE_PAGE_SIZE_2MB;
+ range->base_large_pfn = page_to_hvpfn(
+ sg_page(sg)) >> HV_LARGE_REPORTING_ORDER;
+ range->page.additional_pages =
+ (sg->length / HV_LARGE_REPORTING_LEN) - 1;
+ } else {
+ /* Page reporting for pages below 2MB */
+ range->page.basepfn = page_to_hvpfn(sg_page(sg));
+ range->page.largepage = false;
+ range->page.additional_pages =
+ (sg->length / HV_HYP_PAGE_SIZE) - 1;
+ }
+
}
status = hv_do_rep_hypercall(HV_EXT_CALL_MEMORY_HEAT_HINT, nents, 0,
hint, NULL);
local_irq_restore(flags);
- if ((status & HV_HYPERCALL_RESULT_MASK) != HV_STATUS_SUCCESS) {
+ if (!hv_result_success(status)) {
+
pr_err("Cold memory discard hypercall failed with status %llx\n",
- status);
+ status);
+ if (hv_hypercall_multi_failure > 0)
+ hv_hypercall_multi_failure++;
+
+ if (hv_result(status) == HV_STATUS_INVALID_PARAMETER) {
+ pr_err("Underlying Hyper-V does not support order less than 9. Hypercall failed\n");
+ pr_err("Defaulting to page_reporting_order %d\n",
+ pageblock_order);
+ page_reporting_order = pageblock_order;
+ hv_hypercall_multi_failure++;
+ return -EINVAL;
+ }
+
return -EINVAL;
}
@@ -1646,12 +1698,6 @@ static void enable_page_reporting(void)
{
int ret;
- /* Essentially, validating 'PAGE_REPORTING_MIN_ORDER' is big enough. */
- if (pageblock_order < HV_MIN_PAGE_REPORTING_ORDER) {
- pr_debug("Cold memory discard is only supported on 2MB pages and above\n");
- return;
- }
-
if (!hv_query_ext_cap(HV_EXT_CAPABILITY_MEMORY_COLD_DISCARD_HINT)) {
pr_debug("Cold memory discard hint not supported by Hyper-V\n");
return;
@@ -1659,12 +1705,18 @@ static void enable_page_reporting(void)
BUILD_BUG_ON(PAGE_REPORTING_CAPACITY > HV_MEMORY_HINT_MAX_GPA_PAGE_RANGES);
dm_device.pr_dev_info.report = hv_free_page_report;
+ /*
+ * We let the page_reporting_order parameter decide the order
+ * in the page_reporting code
+ */
+ dm_device.pr_dev_info.order = 0;
ret = page_reporting_register(&dm_device.pr_dev_info);
if (ret < 0) {
dm_device.pr_dev_info.report = NULL;
pr_err("Failed to enable cold memory discard: %d\n", ret);
} else {
- pr_info("Cold memory discard hint enabled\n");
+ pr_info("Cold memory discard hint enabled with order %d\n",
+ page_reporting_order);
}
}
diff --git a/drivers/hv/ring_buffer.c b/drivers/hv/ring_buffer.c
index 59a4aa86d1f3..c6692fd5ab15 100644
--- a/drivers/hv/ring_buffer.c
+++ b/drivers/hv/ring_buffer.c
@@ -280,6 +280,19 @@ void hv_ringbuffer_cleanup(struct hv_ring_buffer_info *ring_info)
ring_info->pkt_buffer_size = 0;
}
+/*
+ * Check if the ring buffer spinlock is available to take or not; used on
+ * atomic contexts, like panic path (see the Hyper-V framebuffer driver).
+ */
+
+bool hv_ringbuffer_spinlock_busy(struct vmbus_channel *channel)
+{
+ struct hv_ring_buffer_info *rinfo = &channel->outbound;
+
+ return spin_is_locked(&rinfo->ring_lock);
+}
+EXPORT_SYMBOL_GPL(hv_ringbuffer_spinlock_busy);
+
/* Write to the ring buffer. */
int hv_ringbuffer_write(struct vmbus_channel *channel,
const struct kvec *kv_list, u32 kv_count,
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index e592c481f7ae..3146710d4ac6 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -25,7 +25,6 @@
#include <linux/sched/task_stack.h>
#include <linux/delay.h>
-#include <linux/notifier.h>
#include <linux/panic_notifier.h>
#include <linux/ptrace.h>
#include <linux/screen_info.h>
@@ -37,6 +36,7 @@
#include <linux/dma-map-ops.h>
#include <linux/pci.h>
#include <clocksource/hyperv_timer.h>
+#include <asm/mshyperv.h>
#include "hyperv_vmbus.h"
struct vmbus_dynid {
@@ -68,53 +68,74 @@ static int hyperv_report_reg(void)
return !sysctl_record_panic_msg || !hv_panic_page;
}
-static int hyperv_panic_event(struct notifier_block *nb, unsigned long val,
+/*
+ * The panic notifier below is responsible solely for unloading the
+ * vmbus connection, which is necessary in a panic event.
+ *
+ * Notice an intrincate relation of this notifier with Hyper-V
+ * framebuffer panic notifier exists - we need vmbus connection alive
+ * there in order to succeed, so we need to order both with each other
+ * [see hvfb_on_panic()] - this is done using notifiers' priorities.
+ */
+static int hv_panic_vmbus_unload(struct notifier_block *nb, unsigned long val,
void *args)
{
- struct pt_regs *regs;
-
vmbus_initiate_unload(true);
-
- /*
- * Hyper-V should be notified only once about a panic. If we will be
- * doing hv_kmsg_dump() with kmsg data later, don't do the notification
- * here.
- */
- if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE
- && hyperv_report_reg()) {
- regs = current_pt_regs();
- hyperv_report_panic(regs, val, false);
- }
return NOTIFY_DONE;
}
+static struct notifier_block hyperv_panic_vmbus_unload_block = {
+ .notifier_call = hv_panic_vmbus_unload,
+ .priority = INT_MIN + 1, /* almost the latest one to execute */
+};
+
+static int hv_die_panic_notify_crash(struct notifier_block *self,
+ unsigned long val, void *args);
+
+static struct notifier_block hyperv_die_report_block = {
+ .notifier_call = hv_die_panic_notify_crash,
+};
+static struct notifier_block hyperv_panic_report_block = {
+ .notifier_call = hv_die_panic_notify_crash,
+};
-static int hyperv_die_event(struct notifier_block *nb, unsigned long val,
- void *args)
+/*
+ * The following callback works both as die and panic notifier; its
+ * goal is to provide panic information to the hypervisor unless the
+ * kmsg dumper is used [see hv_kmsg_dump()], which provides more
+ * information but isn't always available.
+ *
+ * Notice that both the panic/die report notifiers are registered only
+ * if we have the capability HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE set.
+ */
+static int hv_die_panic_notify_crash(struct notifier_block *self,
+ unsigned long val, void *args)
{
- struct die_args *die = args;
- struct pt_regs *regs = die->regs;
+ struct pt_regs *regs;
+ bool is_die;
+
+ /* Don't notify Hyper-V unless we have a die oops event or panic. */
+ if (self == &hyperv_panic_report_block) {
+ is_die = false;
+ regs = current_pt_regs();
+ } else { /* die event */
+ if (val != DIE_OOPS)
+ return NOTIFY_DONE;
- /* Don't notify Hyper-V if the die event is other than oops */
- if (val != DIE_OOPS)
- return NOTIFY_DONE;
+ is_die = true;
+ regs = ((struct die_args *)args)->regs;
+ }
/*
- * Hyper-V should be notified only once about a panic. If we will be
- * doing hv_kmsg_dump() with kmsg data later, don't do the notification
- * here.
+ * Hyper-V should be notified only once about a panic/die. If we will
+ * be calling hv_kmsg_dump() later with kmsg data, don't do the
+ * notification here.
*/
if (hyperv_report_reg())
- hyperv_report_panic(regs, val, true);
+ hyperv_report_panic(regs, val, is_die);
+
return NOTIFY_DONE;
}
-static struct notifier_block hyperv_die_block = {
- .notifier_call = hyperv_die_event,
-};
-static struct notifier_block hyperv_panic_block = {
- .notifier_call = hyperv_panic_event,
-};
-
static const char *fb_mmio_name = "fb_range";
static struct resource *fb_mmio;
static struct resource *hyperv_mmio;
@@ -1538,16 +1559,17 @@ static int vmbus_bus_init(void)
if (hyperv_crash_ctl & HV_CRASH_CTL_CRASH_NOTIFY_MSG)
hv_kmsg_dump_register();
- register_die_notifier(&hyperv_die_block);
+ register_die_notifier(&hyperv_die_report_block);
+ atomic_notifier_chain_register(&panic_notifier_list,
+ &hyperv_panic_report_block);
}
/*
- * Always register the panic notifier because we need to unload
- * the VMbus channel connection to prevent any VMbus
- * activity after the VM panics.
+ * Always register the vmbus unload panic notifier because we
+ * need to shut the VMbus channel connection on panic.
*/
atomic_notifier_chain_register(&panic_notifier_list,
- &hyperv_panic_block);
+ &hyperv_panic_vmbus_unload_block);
vmbus_request_offers();
@@ -2240,7 +2262,7 @@ static acpi_status vmbus_walk_resources(struct acpi_resource *res, void *ctx)
return AE_OK;
}
-static int vmbus_acpi_remove(struct acpi_device *device)
+static void vmbus_acpi_remove(struct acpi_device *device)
{
struct resource *cur_res;
struct resource *next_res;
@@ -2257,8 +2279,6 @@ static int vmbus_acpi_remove(struct acpi_device *device)
kfree(cur_res);
}
}
-
- return 0;
}
static void vmbus_reserve_fb(void)
@@ -2800,15 +2820,17 @@ static void __exit vmbus_exit(void)
if (ms_hyperv.misc_features & HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE) {
kmsg_dump_unregister(&hv_kmsg_dumper);
- unregister_die_notifier(&hyperv_die_block);
+ unregister_die_notifier(&hyperv_die_report_block);
+ atomic_notifier_chain_unregister(&panic_notifier_list,
+ &hyperv_panic_report_block);
}
/*
- * The panic notifier is always registered, hence we should
+ * The vmbus panic notifier is always registered, hence we should
* also unconditionally unregister it here as well.
*/
atomic_notifier_chain_unregister(&panic_notifier_list,
- &hyperv_panic_block);
+ &hyperv_panic_vmbus_unload_block);
free_page((unsigned long)hv_panic_page);
unregister_sysctl_table(hv_ctl_table_hdr);
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 7ac3daaf59ce..3176c33af6c6 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -67,6 +67,14 @@ config SENSORS_ABITUGURU3
This driver can also be built as a module. If so, the module
will be called abituguru3.
+config SENSORS_SMPRO
+ tristate "Ampere's Altra SMpro hardware monitoring driver"
+ depends on MFD_SMPRO
+ help
+ If you say yes here you get support for the thermal, voltage,
+ current and power sensors of Ampere's Altra processor family SoC
+ with SMpro co-processor.
+
config SENSORS_AD7314
tristate "Analog Devices AD7314 and compatibles"
depends on SPI
@@ -799,6 +807,7 @@ config SENSORS_IT87
config SENSORS_JC42
tristate "JEDEC JC42.4 compliant memory module temperature sensors"
depends on I2C
+ select REGMAP_I2C
help
If you say yes here, you get support for JEDEC JC42.4 compliant
temperature sensors, which are used on many DDR3 memory modules for
@@ -1607,6 +1616,17 @@ config SENSORS_NZXT_SMART2
source "drivers/hwmon/occ/Kconfig"
+config SENSORS_OXP
+ tristate "OneXPlayer EC fan control"
+ depends on ACPI
+ depends on X86
+ help
+ If you say yes here you get support for fan readings and control over
+ OneXPlayer handheld devices. Only OneXPlayer mini AMD handheld variant
+ boards are supported.
+
+ Can also be built as a module. In that case it will be called oxp-sensors.
+
config SENSORS_PCF8591
tristate "Philips PCF8591 ADC/DAC"
depends on I2C
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 11d076cad8a2..e2e4e87b282f 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -167,6 +167,7 @@ obj-$(CONFIG_SENSORS_NSA320) += nsa320-hwmon.o
obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o
obj-$(CONFIG_SENSORS_NZXT_KRAKEN2) += nzxt-kraken2.o
obj-$(CONFIG_SENSORS_NZXT_SMART2) += nzxt-smart2.o
+obj-$(CONFIG_SENSORS_OXP) += oxp-sensors.o
obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
@@ -187,6 +188,7 @@ obj-$(CONFIG_SENSORS_SHT4x) += sht4x.o
obj-$(CONFIG_SENSORS_SHTC1) += shtc1.o
obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o
obj-$(CONFIG_SENSORS_SMM665) += smm665.o
+obj-$(CONFIG_SENSORS_SMPRO) += smpro-hwmon.o
obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o
obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
diff --git a/drivers/hwmon/acpi_power_meter.c b/drivers/hwmon/acpi_power_meter.c
index 0962c12eba5a..fa28d447f0df 100644
--- a/drivers/hwmon/acpi_power_meter.c
+++ b/drivers/hwmon/acpi_power_meter.c
@@ -910,12 +910,12 @@ exit:
return res;
}
-static int acpi_power_meter_remove(struct acpi_device *device)
+static void acpi_power_meter_remove(struct acpi_device *device)
{
struct acpi_power_meter_resource *resource;
if (!device || !acpi_driver_data(device))
- return -EINVAL;
+ return;
resource = acpi_driver_data(device);
hwmon_device_unregister(resource->hwmon_dev);
@@ -924,7 +924,6 @@ static int acpi_power_meter_remove(struct acpi_device *device)
free_capabilities(resource);
kfree(resource);
- return 0;
}
static int acpi_power_meter_resume(struct device *dev)
diff --git a/drivers/hwmon/adm1177.c b/drivers/hwmon/adm1177.c
index 0c5dbc5e33b4..be17a26a84f1 100644
--- a/drivers/hwmon/adm1177.c
+++ b/drivers/hwmon/adm1177.c
@@ -26,14 +26,12 @@
/**
* struct adm1177_state - driver instance specific data
* @client: pointer to i2c client
- * @reg: regulator info for the power supply of the device
* @r_sense_uohm: current sense resistor value
* @alert_threshold_ua: current limit for shutdown
* @vrange_high: internal voltage divider
*/
struct adm1177_state {
struct i2c_client *client;
- struct regulator *reg;
u32 r_sense_uohm;
u32 alert_threshold_ua;
bool vrange_high;
@@ -189,13 +187,6 @@ static const struct hwmon_chip_info adm1177_chip_info = {
.info = adm1177_info,
};
-static void adm1177_remove(void *data)
-{
- struct adm1177_state *st = data;
-
- regulator_disable(st->reg);
-}
-
static int adm1177_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
@@ -210,21 +201,9 @@ static int adm1177_probe(struct i2c_client *client)
st->client = client;
- st->reg = devm_regulator_get_optional(&client->dev, "vref");
- if (IS_ERR(st->reg)) {
- if (PTR_ERR(st->reg) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
-
- st->reg = NULL;
- } else {
- ret = regulator_enable(st->reg);
- if (ret)
- return ret;
- ret = devm_add_action_or_reset(&client->dev, adm1177_remove,
- st);
- if (ret)
- return ret;
- }
+ ret = devm_regulator_get_enable_optional(&client->dev, "vref");
+ if (ret == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
if (device_property_read_u32(dev, "shunt-resistor-micro-ohms",
&st->r_sense_uohm))
diff --git a/drivers/hwmon/aht10.c b/drivers/hwmon/aht10.c
index 2d9770cb4401..d76f3441ecf1 100644
--- a/drivers/hwmon/aht10.c
+++ b/drivers/hwmon/aht10.c
@@ -289,8 +289,7 @@ static const struct hwmon_chip_info aht10_chip_info = {
.info = aht10_info,
};
-static int aht10_probe(struct i2c_client *client,
- const struct i2c_device_id *aht10_id)
+static int aht10_probe(struct i2c_client *client)
{
struct device *device = &client->dev;
struct device *hwmon_dev;
@@ -336,7 +335,7 @@ static struct i2c_driver aht10_driver = {
.driver = {
.name = "aht10",
},
- .probe = aht10_probe,
+ .probe_new = aht10_probe,
.id_table = aht10_id,
};
diff --git a/drivers/hwmon/aquacomputer_d5next.c b/drivers/hwmon/aquacomputer_d5next.c
index c51a2678f0eb..9cc10080160b 100644
--- a/drivers/hwmon/aquacomputer_d5next.c
+++ b/drivers/hwmon/aquacomputer_d5next.c
@@ -59,7 +59,7 @@ static u8 secondary_ctrl_report[] = {
0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x34, 0xC6
};
-/* Register offsets for all Aquacomputer devices */
+/* Sensor sizes and offsets for all Aquacomputer devices */
#define AQC_TEMP_SENSOR_SIZE 0x02
#define AQC_TEMP_SENSOR_DISCONNECTED 0x7FFF
#define AQC_FAN_PERCENT_OFFSET 0x00
@@ -68,62 +68,81 @@ static u8 secondary_ctrl_report[] = {
#define AQC_FAN_POWER_OFFSET 0x06
#define AQC_FAN_SPEED_OFFSET 0x08
-/* Register offsets for the D5 Next pump */
-#define D5NEXT_POWER_CYCLES 0x18
-#define D5NEXT_COOLANT_TEMP 0x57
+/* Specs of the D5 Next pump */
#define D5NEXT_NUM_FANS 2
#define D5NEXT_NUM_SENSORS 1
#define D5NEXT_NUM_VIRTUAL_SENSORS 8
-#define D5NEXT_VIRTUAL_SENSORS_START 0x3f
+#define D5NEXT_CTRL_REPORT_SIZE 0x329
+
+/* Sensor report offsets for the D5 Next pump */
+#define D5NEXT_POWER_CYCLES 0x18
+#define D5NEXT_COOLANT_TEMP 0x57
#define D5NEXT_PUMP_OFFSET 0x6c
#define D5NEXT_FAN_OFFSET 0x5f
#define D5NEXT_5V_VOLTAGE 0x39
#define D5NEXT_12V_VOLTAGE 0x37
-#define D5NEXT_CTRL_REPORT_SIZE 0x329
+#define D5NEXT_VIRTUAL_SENSORS_START 0x3f
static u8 d5next_sensor_fan_offsets[] = { D5NEXT_PUMP_OFFSET, D5NEXT_FAN_OFFSET };
-/* Pump and fan speed registers in D5 Next control report (from 0-100%) */
-static u16 d5next_ctrl_fan_offsets[] = { 0x97, 0x42 };
+/* Control report offsets for the D5 Next pump */
+#define D5NEXT_TEMP_CTRL_OFFSET 0x2D /* Temperature sensor offsets location */
+static u16 d5next_ctrl_fan_offsets[] = { 0x97, 0x42 }; /* Pump and fan speed (from 0-100%) */
-/* Register offsets for the Farbwerk RGB controller */
+/* Spec and sensor report offset for the Farbwerk RGB controller */
#define FARBWERK_NUM_SENSORS 4
#define FARBWERK_SENSOR_START 0x2f
-/* Register offsets for the Farbwerk 360 RGB controller */
+/* Specs of the Farbwerk 360 RGB controller */
#define FARBWERK360_NUM_SENSORS 4
-#define FARBWERK360_SENSOR_START 0x32
#define FARBWERK360_NUM_VIRTUAL_SENSORS 16
+#define FARBWERK360_CTRL_REPORT_SIZE 0x682
+
+/* Sensor report offsets for the Farbwerk 360 */
+#define FARBWERK360_SENSOR_START 0x32
#define FARBWERK360_VIRTUAL_SENSORS_START 0x3a
-/* Register offsets for the Octo fan controller */
-#define OCTO_POWER_CYCLES 0x18
+/* Control report offsets for the Farbwerk 360 */
+#define FARBWERK360_TEMP_CTRL_OFFSET 0x8
+
+/* Specs of the Octo fan controller */
#define OCTO_NUM_FANS 8
#define OCTO_NUM_SENSORS 4
-#define OCTO_SENSOR_START 0x3D
#define OCTO_NUM_VIRTUAL_SENSORS 16
-#define OCTO_VIRTUAL_SENSORS_START 0x45
#define OCTO_CTRL_REPORT_SIZE 0x65F
+
+/* Sensor report offsets for the Octo */
+#define OCTO_POWER_CYCLES 0x18
+#define OCTO_SENSOR_START 0x3D
+#define OCTO_VIRTUAL_SENSORS_START 0x45
static u8 octo_sensor_fan_offsets[] = { 0x7D, 0x8A, 0x97, 0xA4, 0xB1, 0xBE, 0xCB, 0xD8 };
-/* Fan speed registers in Octo control report (from 0-100%) */
+/* Control report offsets for the Octo */
+#define OCTO_TEMP_CTRL_OFFSET 0xA
+/* Fan speed offsets (0-100%) */
static u16 octo_ctrl_fan_offsets[] = { 0x5B, 0xB0, 0x105, 0x15A, 0x1AF, 0x204, 0x259, 0x2AE };
-/* Register offsets for the Quadro fan controller */
-#define QUADRO_POWER_CYCLES 0x18
+/* Specs of Quadro fan controller */
#define QUADRO_NUM_FANS 4
#define QUADRO_NUM_SENSORS 4
-#define QUADRO_SENSOR_START 0x34
#define QUADRO_NUM_VIRTUAL_SENSORS 16
-#define QUADRO_VIRTUAL_SENSORS_START 0x3c
#define QUADRO_CTRL_REPORT_SIZE 0x3c1
+
+/* Sensor report offsets for the Quadro */
+#define QUADRO_POWER_CYCLES 0x18
+#define QUADRO_SENSOR_START 0x34
+#define QUADRO_VIRTUAL_SENSORS_START 0x3c
#define QUADRO_FLOW_SENSOR_OFFSET 0x6e
static u8 quadro_sensor_fan_offsets[] = { 0x70, 0x7D, 0x8A, 0x97 };
-/* Fan speed registers in Quadro control report (from 0-100%) */
-static u16 quadro_ctrl_fan_offsets[] = { 0x37, 0x8c, 0xe1, 0x136 };
+/* Control report offsets for the Quadro */
+#define QUADRO_TEMP_CTRL_OFFSET 0xA
+#define QUADRO_FLOW_PULSES_CTRL_OFFSET 0x6
+static u16 quadro_ctrl_fan_offsets[] = { 0x37, 0x8c, 0xe1, 0x136 }; /* Fan speed offsets (0-100%) */
-/* Register offsets for the High Flow Next */
+/* Specs of High Flow Next flow sensor */
#define HIGHFLOWNEXT_NUM_SENSORS 2
+
+/* Sensor report offsets for the High Flow Next */
#define HIGHFLOWNEXT_SENSOR_START 85
#define HIGHFLOWNEXT_FLOW 81
#define HIGHFLOWNEXT_WATER_QUALITY 89
@@ -282,8 +301,10 @@ struct aqc_data {
int temp_sensor_start_offset;
int num_virtual_temp_sensors;
int virtual_temp_sensor_start_offset;
+ u16 temp_ctrl_offset;
u16 power_cycle_count_offset;
u8 flow_sensor_offset;
+ u8 flow_pulses_ctrl_offset;
/* General info, same across all devices */
u32 serial_number[2];
@@ -365,8 +386,8 @@ static int aqc_send_ctrl_data(struct aqc_data *priv)
return ret;
}
-/* Refreshes the control buffer and returns value at offset */
-static int aqc_get_ctrl_val(struct aqc_data *priv, int offset)
+/* Refreshes the control buffer and stores value at offset in val */
+static int aqc_get_ctrl_val(struct aqc_data *priv, int offset, long *val)
{
int ret;
@@ -376,7 +397,7 @@ static int aqc_get_ctrl_val(struct aqc_data *priv, int offset)
if (ret < 0)
goto unlock_and_return;
- ret = get_unaligned_be16(priv->buffer + offset);
+ *val = (s16)get_unaligned_be16(priv->buffer + offset);
unlock_and_return:
mutex_unlock(&priv->mutex);
@@ -393,7 +414,7 @@ static int aqc_set_ctrl_val(struct aqc_data *priv, int offset, long val)
if (ret < 0)
goto unlock_and_return;
- put_unaligned_be16((u16)val, priv->buffer + offset);
+ put_unaligned_be16((s16)val, priv->buffer + offset);
ret = aqc_send_ctrl_data(priv);
@@ -408,8 +429,28 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3
switch (type) {
case hwmon_temp:
+ if (channel < priv->num_temp_sensors) {
+ switch (attr) {
+ case hwmon_temp_label:
+ case hwmon_temp_input:
+ return 0444;
+ case hwmon_temp_offset:
+ if (priv->temp_ctrl_offset != 0)
+ return 0644;
+ break;
+ default:
+ break;
+ }
+ }
+
if (channel < priv->num_temp_sensors + priv->num_virtual_temp_sensors)
- return 0444;
+ switch (attr) {
+ case hwmon_temp_label:
+ case hwmon_temp_input:
+ return 0444;
+ default:
+ break;
+ }
break;
case hwmon_pwm:
if (priv->fan_ctrl_offsets && channel < priv->num_fans) {
@@ -422,20 +463,34 @@ static umode_t aqc_is_visible(const void *data, enum hwmon_sensor_types type, u3
}
break;
case hwmon_fan:
- switch (priv->kind) {
- case highflownext:
- /* Special case to support flow sensor, water quality and conductivity */
- if (channel < 3)
- return 0444;
+ switch (attr) {
+ case hwmon_fan_input:
+ case hwmon_fan_label:
+ switch (priv->kind) {
+ case highflownext:
+ /* Special case to support flow sensor, water quality
+ * and conductivity
+ */
+ if (channel < 3)
+ return 0444;
+ break;
+ case quadro:
+ /* Special case to support flow sensor */
+ if (channel < priv->num_fans + 1)
+ return 0444;
+ break;
+ default:
+ if (channel < priv->num_fans)
+ return 0444;
+ break;
+ }
break;
- case quadro:
- /* Special case to support flow sensor */
- if (channel < priv->num_fans + 1)
- return 0444;
+ case hwmon_fan_pulses:
+ /* Special case for Quadro flow sensor */
+ if (priv->kind == quadro && channel == priv->num_fans)
+ return 0644;
break;
default:
- if (channel < priv->num_fans)
- return 0444;
break;
}
break;
@@ -492,20 +547,46 @@ static int aqc_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
switch (type) {
case hwmon_temp:
- if (priv->temp_input[channel] == -ENODATA)
- return -ENODATA;
+ switch (attr) {
+ case hwmon_temp_input:
+ if (priv->temp_input[channel] == -ENODATA)
+ return -ENODATA;
- *val = priv->temp_input[channel];
+ *val = priv->temp_input[channel];
+ break;
+ case hwmon_temp_offset:
+ ret =
+ aqc_get_ctrl_val(priv, priv->temp_ctrl_offset +
+ channel * AQC_TEMP_SENSOR_SIZE, val);
+ if (ret < 0)
+ return ret;
+
+ *val *= 10;
+ break;
+ default:
+ break;
+ }
break;
case hwmon_fan:
- *val = priv->speed_input[channel];
+ switch (attr) {
+ case hwmon_fan_input:
+ *val = priv->speed_input[channel];
+ break;
+ case hwmon_fan_pulses:
+ ret = aqc_get_ctrl_val(priv, priv->flow_pulses_ctrl_offset, val);
+ if (ret < 0)
+ return ret;
+ break;
+ default:
+ break;
+ }
break;
case hwmon_power:
*val = priv->power_input[channel];
break;
case hwmon_pwm:
if (priv->fan_ctrl_offsets) {
- ret = aqc_get_ctrl_val(priv, priv->fan_ctrl_offsets[channel]);
+ ret = aqc_get_ctrl_val(priv, priv->fan_ctrl_offsets[channel], val);
if (ret < 0)
return ret;
@@ -563,6 +644,33 @@ static int aqc_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,
struct aqc_data *priv = dev_get_drvdata(dev);
switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_offset:
+ /* Limit temp offset to +/- 15K as in the official software */
+ val = clamp_val(val, -15000, 15000) / 10;
+ ret =
+ aqc_set_ctrl_val(priv, priv->temp_ctrl_offset +
+ channel * AQC_TEMP_SENSOR_SIZE, val);
+ if (ret < 0)
+ return ret;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+ break;
+ case hwmon_fan:
+ switch (attr) {
+ case hwmon_fan_pulses:
+ val = clamp_val(val, 10, 1000);
+ ret = aqc_set_ctrl_val(priv, priv->flow_pulses_ctrl_offset, val);
+ if (ret < 0)
+ return ret;
+ break;
+ default:
+ break;
+ }
+ break;
case hwmon_pwm:
switch (attr) {
case hwmon_pwm_input:
@@ -597,10 +705,10 @@ static const struct hwmon_ops aqc_hwmon_ops = {
static const struct hwmon_channel_info *aqc_info[] = {
HWMON_CHANNEL_INFO(temp,
- HWMON_T_INPUT | HWMON_T_LABEL,
- HWMON_T_INPUT | HWMON_T_LABEL,
- HWMON_T_INPUT | HWMON_T_LABEL,
- HWMON_T_INPUT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET,
HWMON_T_INPUT | HWMON_T_LABEL,
HWMON_T_INPUT | HWMON_T_LABEL,
HWMON_T_INPUT | HWMON_T_LABEL,
@@ -622,7 +730,7 @@ static const struct hwmon_channel_info *aqc_info[] = {
HWMON_F_INPUT | HWMON_F_LABEL,
HWMON_F_INPUT | HWMON_F_LABEL,
HWMON_F_INPUT | HWMON_F_LABEL,
- HWMON_F_INPUT | HWMON_F_LABEL,
+ HWMON_F_INPUT | HWMON_F_LABEL | HWMON_F_PULSES,
HWMON_F_INPUT | HWMON_F_LABEL,
HWMON_F_INPUT | HWMON_F_LABEL,
HWMON_F_INPUT | HWMON_F_LABEL),
@@ -847,13 +955,17 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->num_fans = D5NEXT_NUM_FANS;
priv->fan_sensor_offsets = d5next_sensor_fan_offsets;
priv->fan_ctrl_offsets = d5next_ctrl_fan_offsets;
+
priv->num_temp_sensors = D5NEXT_NUM_SENSORS;
priv->temp_sensor_start_offset = D5NEXT_COOLANT_TEMP;
priv->num_virtual_temp_sensors = D5NEXT_NUM_VIRTUAL_SENSORS;
priv->virtual_temp_sensor_start_offset = D5NEXT_VIRTUAL_SENSORS_START;
- priv->power_cycle_count_offset = D5NEXT_POWER_CYCLES;
+ priv->temp_ctrl_offset = D5NEXT_TEMP_CTRL_OFFSET;
+
priv->buffer_size = D5NEXT_CTRL_REPORT_SIZE;
+ priv->power_cycle_count_offset = D5NEXT_POWER_CYCLES;
+
priv->temp_label = label_d5next_temp;
priv->virtual_temp_label = label_virtual_temp_sensors;
priv->speed_label = label_d5next_speeds;
@@ -865,18 +977,24 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->kind = farbwerk;
priv->num_fans = 0;
+
priv->num_temp_sensors = FARBWERK_NUM_SENSORS;
priv->temp_sensor_start_offset = FARBWERK_SENSOR_START;
+
priv->temp_label = label_temp_sensors;
break;
case USB_PRODUCT_ID_FARBWERK360:
priv->kind = farbwerk360;
priv->num_fans = 0;
+
priv->num_temp_sensors = FARBWERK360_NUM_SENSORS;
priv->temp_sensor_start_offset = FARBWERK360_SENSOR_START;
priv->num_virtual_temp_sensors = FARBWERK360_NUM_VIRTUAL_SENSORS;
priv->virtual_temp_sensor_start_offset = FARBWERK360_VIRTUAL_SENSORS_START;
+ priv->temp_ctrl_offset = FARBWERK360_TEMP_CTRL_OFFSET;
+
+ priv->buffer_size = FARBWERK360_CTRL_REPORT_SIZE;
priv->temp_label = label_temp_sensors;
priv->virtual_temp_label = label_virtual_temp_sensors;
@@ -887,13 +1005,17 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->num_fans = OCTO_NUM_FANS;
priv->fan_sensor_offsets = octo_sensor_fan_offsets;
priv->fan_ctrl_offsets = octo_ctrl_fan_offsets;
+
priv->num_temp_sensors = OCTO_NUM_SENSORS;
priv->temp_sensor_start_offset = OCTO_SENSOR_START;
priv->num_virtual_temp_sensors = OCTO_NUM_VIRTUAL_SENSORS;
priv->virtual_temp_sensor_start_offset = OCTO_VIRTUAL_SENSORS_START;
- priv->power_cycle_count_offset = OCTO_POWER_CYCLES;
+ priv->temp_ctrl_offset = OCTO_TEMP_CTRL_OFFSET;
+
priv->buffer_size = OCTO_CTRL_REPORT_SIZE;
+ priv->power_cycle_count_offset = OCTO_POWER_CYCLES;
+
priv->temp_label = label_temp_sensors;
priv->virtual_temp_label = label_virtual_temp_sensors;
priv->speed_label = label_fan_speed;
@@ -907,13 +1029,18 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->num_fans = QUADRO_NUM_FANS;
priv->fan_sensor_offsets = quadro_sensor_fan_offsets;
priv->fan_ctrl_offsets = quadro_ctrl_fan_offsets;
+
priv->num_temp_sensors = QUADRO_NUM_SENSORS;
priv->temp_sensor_start_offset = QUADRO_SENSOR_START;
priv->num_virtual_temp_sensors = QUADRO_NUM_VIRTUAL_SENSORS;
priv->virtual_temp_sensor_start_offset = QUADRO_VIRTUAL_SENSORS_START;
- priv->power_cycle_count_offset = QUADRO_POWER_CYCLES;
+ priv->temp_ctrl_offset = QUADRO_TEMP_CTRL_OFFSET;
+
priv->buffer_size = QUADRO_CTRL_REPORT_SIZE;
+
priv->flow_sensor_offset = QUADRO_FLOW_SENSOR_OFFSET;
+ priv->flow_pulses_ctrl_offset = QUADRO_FLOW_PULSES_CTRL_OFFSET;
+ priv->power_cycle_count_offset = QUADRO_POWER_CYCLES;
priv->temp_label = label_temp_sensors;
priv->virtual_temp_label = label_virtual_temp_sensors;
@@ -926,8 +1053,10 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
priv->kind = highflownext;
priv->num_fans = 0;
+
priv->num_temp_sensors = HIGHFLOWNEXT_NUM_SENSORS;
priv->temp_sensor_start_offset = HIGHFLOWNEXT_SENSOR_START;
+
priv->power_cycle_count_offset = QUADRO_POWER_CYCLES;
priv->temp_label = label_highflownext_temp_sensors;
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c
index ff64a39d56de..d778a2aaefec 100644
--- a/drivers/hwmon/asus_atk0110.c
+++ b/drivers/hwmon/asus_atk0110.c
@@ -187,7 +187,7 @@ struct atk_acpi_input_buf {
};
static int atk_add(struct acpi_device *device);
-static int atk_remove(struct acpi_device *device);
+static void atk_remove(struct acpi_device *device);
static void atk_print_sensor(struct atk_data *data, union acpi_object *obj);
static int atk_read_value(struct atk_sensor_data *sensor, u64 *value);
@@ -1344,7 +1344,7 @@ out:
return err;
}
-static int atk_remove(struct acpi_device *device)
+static void atk_remove(struct acpi_device *device)
{
struct atk_data *data = device->driver_data;
dev_dbg(&device->dev, "removing...\n");
@@ -1359,8 +1359,6 @@ static int atk_remove(struct acpi_device *device)
if (atk_ec_ctl(data, 0))
dev_err(&device->dev, "Failed to disable EC\n");
}
-
- return 0;
}
static int __init atk0110_init(void)
diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c
index 4fd8de8022bc..118297ea1dcf 100644
--- a/drivers/hwmon/atxp1.c
+++ b/drivers/hwmon/atxp1.c
@@ -16,6 +16,7 @@
#include <linux/hwmon.h>
#include <linux/hwmon-vid.h>
#include <linux/err.h>
+#include <linux/kstrtox.h>
#include <linux/mutex.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 9bee4d33fbdf..ca7a9b373bbd 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -55,6 +55,8 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
/*
* Per-Core Temperature Data
+ * @tjmax: The static tjmax value when tjmax cannot be retrieved from
+ * IA32_TEMPERATURE_TARGET MSR.
* @last_updated: The time when the current temperature value was updated
* earlier (in jiffies).
* @cpu_core_id: The CPU Core from which temperature values should be read
@@ -64,11 +66,9 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
* @attr_size: Total number of pre-core attrs displayed in the sysfs.
* @is_pkg_data: If this is 1, the temp_data holds pkgtemp data.
* Otherwise, temp_data holds coretemp data.
- * @valid: If this is 1, the current temperature is valid.
*/
struct temp_data {
int temp;
- int ttarget;
int tjmax;
unsigned long last_updated;
unsigned int cpu;
@@ -76,7 +76,6 @@ struct temp_data {
u32 status_reg;
int attr_size;
bool is_pkg_data;
- bool valid;
struct sensor_device_attribute sd_attrs[TOTAL_ATTRS];
char attr_name[TOTAL_ATTRS][CORETEMP_NAME_LENGTH];
struct attribute *attrs[TOTAL_ATTRS + 1];
@@ -95,85 +94,6 @@ struct platform_data {
struct device_attribute name_attr;
};
-/* Keep track of how many zone pointers we allocated in init() */
-static int max_zones __read_mostly;
-/* Array of zone pointers. Serialized by cpu hotplug lock */
-static struct platform_device **zone_devices;
-
-static ssize_t show_label(struct device *dev,
- struct device_attribute *devattr, char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct platform_data *pdata = dev_get_drvdata(dev);
- struct temp_data *tdata = pdata->core_data[attr->index];
-
- if (tdata->is_pkg_data)
- return sprintf(buf, "Package id %u\n", pdata->pkg_id);
-
- return sprintf(buf, "Core %u\n", tdata->cpu_core_id);
-}
-
-static ssize_t show_crit_alarm(struct device *dev,
- struct device_attribute *devattr, char *buf)
-{
- u32 eax, edx;
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct platform_data *pdata = dev_get_drvdata(dev);
- struct temp_data *tdata = pdata->core_data[attr->index];
-
- mutex_lock(&tdata->update_lock);
- rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx);
- mutex_unlock(&tdata->update_lock);
-
- return sprintf(buf, "%d\n", (eax >> 5) & 1);
-}
-
-static ssize_t show_tjmax(struct device *dev,
- struct device_attribute *devattr, char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct platform_data *pdata = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n", pdata->core_data[attr->index]->tjmax);
-}
-
-static ssize_t show_ttarget(struct device *dev,
- struct device_attribute *devattr, char *buf)
-{
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct platform_data *pdata = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n", pdata->core_data[attr->index]->ttarget);
-}
-
-static ssize_t show_temp(struct device *dev,
- struct device_attribute *devattr, char *buf)
-{
- u32 eax, edx;
- struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
- struct platform_data *pdata = dev_get_drvdata(dev);
- struct temp_data *tdata = pdata->core_data[attr->index];
-
- mutex_lock(&tdata->update_lock);
-
- /* Check whether the time interval has elapsed */
- if (!tdata->valid || time_after(jiffies, tdata->last_updated + HZ)) {
- rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx);
- /*
- * Ignore the valid bit. In all observed cases the register
- * value is either low or zero if the valid bit is 0.
- * Return it instead of reporting an error which doesn't
- * really help at all.
- */
- tdata->temp = tdata->tjmax - ((eax >> 16) & 0x7f) * 1000;
- tdata->valid = true;
- tdata->last_updated = jiffies;
- }
-
- mutex_unlock(&tdata->update_lock);
- return sprintf(buf, "%d\n", tdata->temp);
-}
-
struct tjmax_pci {
unsigned int device;
int tjmax;
@@ -340,20 +260,25 @@ static bool cpu_has_tjmax(struct cpuinfo_x86 *c)
model != 0x36;
}
-static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
+static int get_tjmax(struct temp_data *tdata, struct device *dev)
{
+ struct cpuinfo_x86 *c = &cpu_data(tdata->cpu);
int err;
u32 eax, edx;
u32 val;
+ /* use static tjmax once it is set */
+ if (tdata->tjmax)
+ return tdata->tjmax;
+
/*
* A new feature of current Intel(R) processors, the
* IA32_TEMPERATURE_TARGET contains the TjMax value
*/
- err = rdmsr_safe_on_cpu(id, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
+ err = rdmsr_safe_on_cpu(tdata->cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
if (err) {
if (cpu_has_tjmax(c))
- dev_warn(dev, "Unable to read TjMax from CPU %u\n", id);
+ dev_warn(dev, "Unable to read TjMax from CPU %u\n", tdata->cpu);
} else {
val = (eax >> 16) & 0xff;
/*
@@ -369,14 +294,133 @@ static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev)
if (force_tjmax) {
dev_notice(dev, "TjMax forced to %d degrees C by user\n",
force_tjmax);
- return force_tjmax * 1000;
+ tdata->tjmax = force_tjmax * 1000;
+ } else {
+ /*
+ * An assumption is made for early CPUs and unreadable MSR.
+ * NOTE: the calculated value may not be correct.
+ */
+ tdata->tjmax = adjust_tjmax(c, tdata->cpu, dev);
}
+ return tdata->tjmax;
+}
+
+static int get_ttarget(struct temp_data *tdata, struct device *dev)
+{
+ u32 eax, edx;
+ int tjmax, ttarget_offset, ret;
/*
- * An assumption is made for early CPUs and unreadable MSR.
- * NOTE: the calculated value may not be correct.
+ * ttarget is valid only if tjmax can be retrieved from
+ * MSR_IA32_TEMPERATURE_TARGET
*/
- return adjust_tjmax(c, id, dev);
+ if (tdata->tjmax)
+ return -ENODEV;
+
+ ret = rdmsr_safe_on_cpu(tdata->cpu, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx);
+ if (ret)
+ return ret;
+
+ tjmax = (eax >> 16) & 0xff;
+
+ /* Read the still undocumented bits 8:15 of IA32_TEMPERATURE_TARGET. */
+ ttarget_offset = (eax >> 8) & 0xff;
+
+ return (tjmax - ttarget_offset) * 1000;
+}
+
+/* Keep track of how many zone pointers we allocated in init() */
+static int max_zones __read_mostly;
+/* Array of zone pointers. Serialized by cpu hotplug lock */
+static struct platform_device **zone_devices;
+
+static ssize_t show_label(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct platform_data *pdata = dev_get_drvdata(dev);
+ struct temp_data *tdata = pdata->core_data[attr->index];
+
+ if (tdata->is_pkg_data)
+ return sprintf(buf, "Package id %u\n", pdata->pkg_id);
+
+ return sprintf(buf, "Core %u\n", tdata->cpu_core_id);
+}
+
+static ssize_t show_crit_alarm(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ u32 eax, edx;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct platform_data *pdata = dev_get_drvdata(dev);
+ struct temp_data *tdata = pdata->core_data[attr->index];
+
+ mutex_lock(&tdata->update_lock);
+ rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx);
+ mutex_unlock(&tdata->update_lock);
+
+ return sprintf(buf, "%d\n", (eax >> 5) & 1);
+}
+
+static ssize_t show_tjmax(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct platform_data *pdata = dev_get_drvdata(dev);
+ struct temp_data *tdata = pdata->core_data[attr->index];
+ int tjmax;
+
+ mutex_lock(&tdata->update_lock);
+ tjmax = get_tjmax(tdata, dev);
+ mutex_unlock(&tdata->update_lock);
+
+ return sprintf(buf, "%d\n", tjmax);
+}
+
+static ssize_t show_ttarget(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct platform_data *pdata = dev_get_drvdata(dev);
+ struct temp_data *tdata = pdata->core_data[attr->index];
+ int ttarget;
+
+ mutex_lock(&tdata->update_lock);
+ ttarget = get_ttarget(tdata, dev);
+ mutex_unlock(&tdata->update_lock);
+
+ if (ttarget < 0)
+ return ttarget;
+ return sprintf(buf, "%d\n", ttarget);
+}
+
+static ssize_t show_temp(struct device *dev,
+ struct device_attribute *devattr, char *buf)
+{
+ u32 eax, edx;
+ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+ struct platform_data *pdata = dev_get_drvdata(dev);
+ struct temp_data *tdata = pdata->core_data[attr->index];
+ int tjmax;
+
+ mutex_lock(&tdata->update_lock);
+
+ tjmax = get_tjmax(tdata, dev);
+ /* Check whether the time interval has elapsed */
+ if (time_after(jiffies, tdata->last_updated + HZ)) {
+ rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx);
+ /*
+ * Ignore the valid bit. In all observed cases the register
+ * value is either low or zero if the valid bit is 0.
+ * Return it instead of reporting an error which doesn't
+ * really help at all.
+ */
+ tdata->temp = tjmax - ((eax >> 16) & 0x7f) * 1000;
+ tdata->last_updated = jiffies;
+ }
+
+ mutex_unlock(&tdata->update_lock);
+ return sprintf(buf, "%d\n", tdata->temp);
}
static int create_core_attrs(struct temp_data *tdata, struct device *dev,
@@ -490,23 +534,17 @@ static int create_core_data(struct platform_device *pdev, unsigned int cpu,
if (err)
goto exit_free;
- /* We can access status register. Get Critical Temperature */
- tdata->tjmax = get_tjmax(c, cpu, &pdev->dev);
+ /* Make sure tdata->tjmax is a valid indicator for dynamic/static tjmax */
+ get_tjmax(tdata, &pdev->dev);
/*
- * Read the still undocumented bits 8:15 of IA32_TEMPERATURE_TARGET.
- * The target temperature is available on older CPUs but not in this
- * register. Atoms don't have the register at all.
+ * The target temperature is available on older CPUs but not in the
+ * MSR_IA32_TEMPERATURE_TARGET register. Atoms don't have the register
+ * at all.
*/
- if (c->x86_model > 0xe && c->x86_model != 0x1c) {
- err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET,
- &eax, &edx);
- if (!err) {
- tdata->ttarget
- = tdata->tjmax - ((eax >> 8) & 0xff) * 1000;
+ if (c->x86_model > 0xe && c->x86_model != 0x1c)
+ if (get_ttarget(tdata, &pdev->dev) >= 0)
tdata->attr_size++;
- }
- }
pdata->core_data[attr_no] = tdata;
diff --git a/drivers/hwmon/dell-smm-hwmon.c b/drivers/hwmon/dell-smm-hwmon.c
index 1572b5416015..7ac778aedc68 100644
--- a/drivers/hwmon/dell-smm-hwmon.c
+++ b/drivers/hwmon/dell-smm-hwmon.c
@@ -1447,9 +1447,10 @@ static int __init i8k_init(void)
*/
if (i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG1) &&
i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG2)) {
- pr_err("unable to get SMM Dell signature\n");
if (!force)
return -ENODEV;
+
+ pr_err("Unable to get Dell SMM signature\n");
}
dell_smm_device = platform_create_bundle(&dell_smm_driver, dell_smm_probe, NULL, 0, NULL,
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index 0886abf6ebab..e803d6393b9e 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -269,7 +269,7 @@ static ssize_t update_interval_show(struct device *dev,
struct device_attribute *da, char *buf)
{
struct ds1621_data *data = dev_get_drvdata(dev);
- return scnprintf(buf, PAGE_SIZE, "%hu\n", data->update_interval);
+ return sysfs_emit(buf, "%hu\n", data->update_interval);
}
static ssize_t update_interval_store(struct device *dev,
diff --git a/drivers/hwmon/emc2305.c b/drivers/hwmon/emc2305.c
index aa1f25add0b6..6ad055e5868e 100644
--- a/drivers/hwmon/emc2305.c
+++ b/drivers/hwmon/emc2305.c
@@ -16,7 +16,6 @@ static const unsigned short
emc2305_normal_i2c[] = { 0x27, 0x2c, 0x2d, 0x2e, 0x2f, 0x4c, 0x4d, I2C_CLIENT_END };
#define EMC2305_REG_DRIVE_FAIL_STATUS 0x27
-#define EMC2305_REG_DEVICE 0xfd
#define EMC2305_REG_VENDOR 0xfe
#define EMC2305_FAN_MAX 0xff
#define EMC2305_FAN_MIN 0x00
@@ -172,22 +171,12 @@ static int emc2305_get_max_state(struct thermal_cooling_device *cdev, unsigned l
return 0;
}
-static int emc2305_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
+static int __emc2305_set_cur_state(struct emc2305_data *data, int cdev_idx, unsigned long state)
{
- int cdev_idx, ret;
- struct emc2305_data *data = cdev->devdata;
+ int ret;
struct i2c_client *client = data->client;
u8 val, i;
- if (state > data->max_state)
- return -EINVAL;
-
- cdev_idx = emc2305_get_cdev_idx(cdev);
- if (cdev_idx < 0)
- return cdev_idx;
-
- /* Save thermal state. */
- data->cdev_data[cdev_idx].last_thermal_state = state;
state = max_t(unsigned long, state, data->cdev_data[cdev_idx].last_hwmon_state);
val = EMC2305_PWM_STATE2DUTY(state, data->max_state, EMC2305_FAN_MAX);
@@ -212,6 +201,27 @@ static int emc2305_set_cur_state(struct thermal_cooling_device *cdev, unsigned l
return 0;
}
+static int emc2305_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
+{
+ int cdev_idx, ret;
+ struct emc2305_data *data = cdev->devdata;
+
+ if (state > data->max_state)
+ return -EINVAL;
+
+ cdev_idx = emc2305_get_cdev_idx(cdev);
+ if (cdev_idx < 0)
+ return cdev_idx;
+
+ /* Save thermal state. */
+ data->cdev_data[cdev_idx].last_thermal_state = state;
+ ret = __emc2305_set_cur_state(data, cdev_idx, state);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
static const struct thermal_cooling_device_ops emc2305_cooling_ops = {
.get_max_state = emc2305_get_max_state,
.get_cur_state = emc2305_get_cur_state,
@@ -402,7 +412,7 @@ emc2305_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int ch
*/
if (data->cdev_data[cdev_idx].last_hwmon_state >=
data->cdev_data[cdev_idx].last_thermal_state)
- return emc2305_set_cur_state(data->cdev_data[cdev_idx].cdev,
+ return __emc2305_set_cur_state(data, cdev_idx,
data->cdev_data[cdev_idx].last_hwmon_state);
return 0;
}
@@ -518,13 +528,13 @@ static int emc2305_identify(struct device *dev)
return 0;
}
-static int emc2305_probe(struct i2c_client *client, const struct i2c_device_id *id)
+static int emc2305_probe(struct i2c_client *client)
{
struct i2c_adapter *adapter = client->adapter;
struct device *dev = &client->dev;
struct emc2305_data *data;
struct emc2305_platform_data *pdata;
- int vendor, device;
+ int vendor;
int ret;
int i;
@@ -535,10 +545,6 @@ static int emc2305_probe(struct i2c_client *client, const struct i2c_device_id *
if (vendor != EMC2305_VENDOR)
return -ENODEV;
- device = i2c_smbus_read_byte_data(client, EMC2305_REG_DEVICE);
- if (device != EMC2305_DEVICE)
- return -ENODEV;
-
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@@ -607,7 +613,7 @@ static struct i2c_driver emc2305_driver = {
.driver = {
.name = "emc2305",
},
- .probe = emc2305_probe,
+ .probe_new = emc2305_probe,
.remove = emc2305_remove,
.id_table = emc2305_ids,
.address_list = emc2305_normal_i2c,
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c
index 0a77d6161928..e1f426e86f36 100644
--- a/drivers/hwmon/fschmd.c
+++ b/drivers/hwmon/fschmd.c
@@ -1083,9 +1083,9 @@ static int fschmd_detect(struct i2c_client *client,
static int fschmd_probe(struct i2c_client *client)
{
struct fschmd_data *data;
- const char * const names[7] = { "Poseidon", "Hermes", "Scylla",
+ static const char * const names[7] = { "Poseidon", "Hermes", "Scylla",
"Heracles", "Heimdall", "Hades", "Syleus" };
- const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 };
+ static const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 };
int i, err;
enum chips kind = i2c_match_id(fschmd_id, client)->driver_data;
diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c
index ba408942dbe7..e75db6f64e8c 100644
--- a/drivers/hwmon/gpio-fan.c
+++ b/drivers/hwmon/gpio-fan.c
@@ -14,6 +14,7 @@
#include <linux/irq.h>
#include <linux/platform_device.h>
#include <linux/err.h>
+#include <linux/kstrtox.h>
#include <linux/mutex.h>
#include <linux/hwmon.h>
#include <linux/gpio/consumer.h>
diff --git a/drivers/hwmon/gsc-hwmon.c b/drivers/hwmon/gsc-hwmon.c
index b60ec95b5edb..73e5d92b200b 100644
--- a/drivers/hwmon/gsc-hwmon.c
+++ b/drivers/hwmon/gsc-hwmon.c
@@ -257,13 +257,10 @@ gsc_hwmon_get_devtree_pdata(struct device *dev)
if (nchannels == 0)
return ERR_PTR(-ENODEV);
- pdata = devm_kzalloc(dev,
- sizeof(*pdata) + nchannels * sizeof(*ch),
+ pdata = devm_kzalloc(dev, struct_size(pdata, channels, nchannels),
GFP_KERNEL);
if (!pdata)
return ERR_PTR(-ENOMEM);
- ch = (struct gsc_hwmon_channel *)(pdata + 1);
- pdata->channels = ch;
pdata->nchannels = nchannels;
/* fan controller base address */
@@ -277,6 +274,7 @@ gsc_hwmon_get_devtree_pdata(struct device *dev)
of_node_put(fan);
+ ch = pdata->channels;
/* allocate structures for channels and count instances of each type */
device_for_each_child_node(dev, child) {
if (fwnode_property_read_string(child, "label", &ch->name)) {
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 4218750d5a66..33edb5c02f7d 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -15,6 +15,7 @@
#include <linux/gfp.h>
#include <linux/hwmon.h>
#include <linux/idr.h>
+#include <linux/kstrtox.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/pci.h>
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 7bd154ba351b..9997f76b1f4a 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -69,6 +69,10 @@ static unsigned short force_id;
module_param(force_id, ushort, 0);
MODULE_PARM_DESC(force_id, "Override the detected device ID");
+static bool ignore_resource_conflict;
+module_param(ignore_resource_conflict, bool, 0);
+MODULE_PARM_DESC(ignore_resource_conflict, "Ignore ACPI resource conflict");
+
static struct platform_device *it87_pdev[2];
#define REG_2E 0x2e /* The register to read/write */
@@ -563,6 +567,14 @@ struct it87_data {
s8 auto_temp[NUM_AUTO_PWM][5]; /* [nr][0] is point1_temp_hyst */
};
+/* Board specific settings from DMI matching */
+struct it87_dmi_data {
+ u8 skip_pwm; /* pwm channels to skip for this board */
+};
+
+/* Global for results from DMI matching, if needed */
+static struct it87_dmi_data *dmi_data;
+
static int adc_lsb(const struct it87_data *data, int nr)
{
int lsb;
@@ -2389,7 +2401,6 @@ static int __init it87_find(int sioaddr, unsigned short *address,
{
int err;
u16 chip_type;
- const char *board_vendor, *board_name;
const struct it87_devices *config;
err = superio_enter(sioaddr);
@@ -2397,7 +2408,13 @@ static int __init it87_find(int sioaddr, unsigned short *address,
return err;
err = -ENODEV;
- chip_type = force_id ? force_id : superio_inw(sioaddr, DEVID);
+ chip_type = superio_inw(sioaddr, DEVID);
+ /* check first for a valid chip before forcing chip id */
+ if (chip_type == 0xffff)
+ goto exit;
+
+ if (force_id)
+ chip_type = force_id;
switch (chip_type) {
case IT8705F_DEVID:
@@ -2802,24 +2819,9 @@ static int __init it87_find(int sioaddr, unsigned short *address,
if (sio_data->beep_pin)
pr_info("Beeping is supported\n");
- /* Disable specific features based on DMI strings */
- board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
- board_name = dmi_get_system_info(DMI_BOARD_NAME);
- if (board_vendor && board_name) {
- if (strcmp(board_vendor, "nVIDIA") == 0 &&
- strcmp(board_name, "FN68PT") == 0) {
- /*
- * On the Shuttle SN68PT, FAN_CTL2 is apparently not
- * connected to a fan, but to something else. One user
- * has reported instant system power-off when changing
- * the PWM2 duty cycle, so we disable it.
- * I use the board name string as the trigger in case
- * the same board is ever used in other systems.
- */
- pr_info("Disabling pwm2 due to hardware constraints\n");
- sio_data->skip_pwm = BIT(1);
- }
- }
+ /* Set values based on DMI matches */
+ if (dmi_data)
+ sio_data->skip_pwm |= dmi_data->skip_pwm;
exit:
superio_exit(sioaddr);
@@ -3261,8 +3263,10 @@ static int __init it87_device_add(int index, unsigned short address,
int err;
err = acpi_check_resource_conflict(&res);
- if (err)
- return err;
+ if (err) {
+ if (!ignore_resource_conflict)
+ return err;
+ }
pdev = platform_device_alloc(DRVNAME, address);
if (!pdev)
@@ -3295,6 +3299,46 @@ exit_device_put:
return err;
}
+/* callback function for DMI */
+static int it87_dmi_cb(const struct dmi_system_id *dmi_entry)
+{
+ dmi_data = dmi_entry->driver_data;
+
+ if (dmi_data && dmi_data->skip_pwm)
+ pr_info("Disabling pwm2 due to hardware constraints\n");
+
+ return 1;
+}
+
+/*
+ * On the Shuttle SN68PT, FAN_CTL2 is apparently not
+ * connected to a fan, but to something else. One user
+ * has reported instant system power-off when changing
+ * the PWM2 duty cycle, so we disable it.
+ * I use the board name string as the trigger in case
+ * the same board is ever used in other systems.
+ */
+static struct it87_dmi_data nvidia_fn68pt = {
+ .skip_pwm = BIT(1),
+};
+
+#define IT87_DMI_MATCH_VND(vendor, name, cb, data) \
+ { \
+ .callback = cb, \
+ .matches = { \
+ DMI_EXACT_MATCH(DMI_BOARD_VENDOR, vendor), \
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, name), \
+ }, \
+ .driver_data = data, \
+ }
+
+static const struct dmi_system_id it87_dmi_table[] __initconst = {
+ IT87_DMI_MATCH_VND("nVIDIA", "FN68PT", it87_dmi_cb, &nvidia_fn68pt),
+ { }
+
+};
+MODULE_DEVICE_TABLE(dmi, it87_dmi_table);
+
static int __init sm_it87_init(void)
{
int sioaddr[2] = { REG_2E, REG_4E };
@@ -3307,6 +3351,8 @@ static int __init sm_it87_init(void)
if (err)
return err;
+ dmi_check_system(it87_dmi_table);
+
for (i = 0; i < ARRAY_SIZE(sioaddr); i++) {
memset(&sio_data, 0, sizeof(struct it87_sio_data));
isa_address[i] = 0;
diff --git a/drivers/hwmon/jc42.c b/drivers/hwmon/jc42.c
index 30888feaf589..8523bf974310 100644
--- a/drivers/hwmon/jc42.c
+++ b/drivers/hwmon/jc42.c
@@ -10,6 +10,7 @@
*/
#include <linux/bitops.h>
+#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -19,6 +20,7 @@
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/of.h>
+#include <linux/regmap.h>
/* Addresses to scan */
static const unsigned short normal_i2c[] = {
@@ -36,20 +38,19 @@ static const unsigned short normal_i2c[] = {
#define JC42_REG_SMBUS 0x22 /* NXP and Atmel, possibly others? */
/* Status bits in temperature register */
-#define JC42_ALARM_CRIT_BIT 15
-#define JC42_ALARM_MAX_BIT 14
-#define JC42_ALARM_MIN_BIT 13
+#define JC42_ALARM_CRIT BIT(15)
+#define JC42_ALARM_MAX BIT(14)
+#define JC42_ALARM_MIN BIT(13)
/* Configuration register defines */
-#define JC42_CFG_CRIT_ONLY (1 << 2)
-#define JC42_CFG_TCRIT_LOCK (1 << 6)
-#define JC42_CFG_EVENT_LOCK (1 << 7)
-#define JC42_CFG_SHUTDOWN (1 << 8)
-#define JC42_CFG_HYST_SHIFT 9
-#define JC42_CFG_HYST_MASK (0x03 << 9)
+#define JC42_CFG_CRIT_ONLY BIT(2)
+#define JC42_CFG_TCRIT_LOCK BIT(6)
+#define JC42_CFG_EVENT_LOCK BIT(7)
+#define JC42_CFG_SHUTDOWN BIT(8)
+#define JC42_CFG_HYST_MASK GENMASK(10, 9)
/* Capabilities */
-#define JC42_CAP_RANGE (1 << 2)
+#define JC42_CAP_RANGE BIT(2)
/* Manufacturer IDs */
#define ADT_MANID 0x11d4 /* Analog Devices */
@@ -199,31 +200,14 @@ static struct jc42_chips jc42_chips[] = {
{ STM_MANID, STTS3000_DEVID, STTS3000_DEVID_MASK },
};
-enum temp_index {
- t_input = 0,
- t_crit,
- t_min,
- t_max,
- t_num_temp
-};
-
-static const u8 temp_regs[t_num_temp] = {
- [t_input] = JC42_REG_TEMP,
- [t_crit] = JC42_REG_TEMP_CRITICAL,
- [t_min] = JC42_REG_TEMP_LOWER,
- [t_max] = JC42_REG_TEMP_UPPER,
-};
-
/* Each client has this additional data */
struct jc42_data {
- struct i2c_client *client;
struct mutex update_lock; /* protect register access */
+ struct regmap *regmap;
bool extended; /* true if extended range supported */
bool valid;
- unsigned long last_updated; /* In jiffies */
u16 orig_config; /* original configuration */
u16 config; /* current configuration */
- u16 temp[t_num_temp];/* Temperatures */
};
#define JC42_TEMP_MIN_EXTENDED (-40000)
@@ -248,85 +232,102 @@ static int jc42_temp_from_reg(s16 reg)
return reg * 125 / 2;
}
-static struct jc42_data *jc42_update_device(struct device *dev)
-{
- struct jc42_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
- struct jc42_data *ret = data;
- int i, val;
-
- mutex_lock(&data->update_lock);
-
- if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
- for (i = 0; i < t_num_temp; i++) {
- val = i2c_smbus_read_word_swapped(client, temp_regs[i]);
- if (val < 0) {
- ret = ERR_PTR(val);
- goto abort;
- }
- data->temp[i] = val;
- }
- data->last_updated = jiffies;
- data->valid = true;
- }
-abort:
- mutex_unlock(&data->update_lock);
- return ret;
-}
-
static int jc42_read(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long *val)
{
- struct jc42_data *data = jc42_update_device(dev);
- int temp, hyst;
+ struct jc42_data *data = dev_get_drvdata(dev);
+ unsigned int regval;
+ int ret, temp, hyst;
- if (IS_ERR(data))
- return PTR_ERR(data);
+ mutex_lock(&data->update_lock);
switch (attr) {
case hwmon_temp_input:
- *val = jc42_temp_from_reg(data->temp[t_input]);
- return 0;
+ ret = regmap_read(data->regmap, JC42_REG_TEMP, &regval);
+ if (ret)
+ break;
+
+ *val = jc42_temp_from_reg(regval);
+ break;
case hwmon_temp_min:
- *val = jc42_temp_from_reg(data->temp[t_min]);
- return 0;
+ ret = regmap_read(data->regmap, JC42_REG_TEMP_LOWER, &regval);
+ if (ret)
+ break;
+
+ *val = jc42_temp_from_reg(regval);
+ break;
case hwmon_temp_max:
- *val = jc42_temp_from_reg(data->temp[t_max]);
- return 0;
+ ret = regmap_read(data->regmap, JC42_REG_TEMP_UPPER, &regval);
+ if (ret)
+ break;
+
+ *val = jc42_temp_from_reg(regval);
+ break;
case hwmon_temp_crit:
- *val = jc42_temp_from_reg(data->temp[t_crit]);
- return 0;
+ ret = regmap_read(data->regmap, JC42_REG_TEMP_CRITICAL,
+ &regval);
+ if (ret)
+ break;
+
+ *val = jc42_temp_from_reg(regval);
+ break;
case hwmon_temp_max_hyst:
- temp = jc42_temp_from_reg(data->temp[t_max]);
- hyst = jc42_hysteresis[(data->config & JC42_CFG_HYST_MASK)
- >> JC42_CFG_HYST_SHIFT];
+ ret = regmap_read(data->regmap, JC42_REG_TEMP_UPPER, &regval);
+ if (ret)
+ break;
+
+ temp = jc42_temp_from_reg(regval);
+ hyst = jc42_hysteresis[FIELD_GET(JC42_CFG_HYST_MASK,
+ data->config)];
*val = temp - hyst;
- return 0;
+ break;
case hwmon_temp_crit_hyst:
- temp = jc42_temp_from_reg(data->temp[t_crit]);
- hyst = jc42_hysteresis[(data->config & JC42_CFG_HYST_MASK)
- >> JC42_CFG_HYST_SHIFT];
+ ret = regmap_read(data->regmap, JC42_REG_TEMP_CRITICAL,
+ &regval);
+ if (ret)
+ break;
+
+ temp = jc42_temp_from_reg(regval);
+ hyst = jc42_hysteresis[FIELD_GET(JC42_CFG_HYST_MASK,
+ data->config)];
*val = temp - hyst;
- return 0;
+ break;
case hwmon_temp_min_alarm:
- *val = (data->temp[t_input] >> JC42_ALARM_MIN_BIT) & 1;
- return 0;
+ ret = regmap_read(data->regmap, JC42_REG_TEMP, &regval);
+ if (ret)
+ break;
+
+ *val = FIELD_GET(JC42_ALARM_MIN, regval);
+ break;
case hwmon_temp_max_alarm:
- *val = (data->temp[t_input] >> JC42_ALARM_MAX_BIT) & 1;
- return 0;
+ ret = regmap_read(data->regmap, JC42_REG_TEMP, &regval);
+ if (ret)
+ break;
+
+ *val = FIELD_GET(JC42_ALARM_MAX, regval);
+ break;
case hwmon_temp_crit_alarm:
- *val = (data->temp[t_input] >> JC42_ALARM_CRIT_BIT) & 1;
- return 0;
+ ret = regmap_read(data->regmap, JC42_REG_TEMP, &regval);
+ if (ret)
+ break;
+
+ *val = FIELD_GET(JC42_ALARM_CRIT, regval);
+ break;
default:
- return -EOPNOTSUPP;
+ ret = -EOPNOTSUPP;
+ break;
}
+
+ mutex_unlock(&data->update_lock);
+
+ return ret;
}
static int jc42_write(struct device *dev, enum hwmon_sensor_types type,
u32 attr, int channel, long val)
{
struct jc42_data *data = dev_get_drvdata(dev);
- struct i2c_client *client = data->client;
+ unsigned int regval;
int diff, hyst;
int ret;
@@ -334,21 +335,23 @@ static int jc42_write(struct device *dev, enum hwmon_sensor_types type,
switch (attr) {
case hwmon_temp_min:
- data->temp[t_min] = jc42_temp_to_reg(val, data->extended);
- ret = i2c_smbus_write_word_swapped(client, temp_regs[t_min],
- data->temp[t_min]);
+ ret = regmap_write(data->regmap, JC42_REG_TEMP_LOWER,
+ jc42_temp_to_reg(val, data->extended));
break;
case hwmon_temp_max:
- data->temp[t_max] = jc42_temp_to_reg(val, data->extended);
- ret = i2c_smbus_write_word_swapped(client, temp_regs[t_max],
- data->temp[t_max]);
+ ret = regmap_write(data->regmap, JC42_REG_TEMP_UPPER,
+ jc42_temp_to_reg(val, data->extended));
break;
case hwmon_temp_crit:
- data->temp[t_crit] = jc42_temp_to_reg(val, data->extended);
- ret = i2c_smbus_write_word_swapped(client, temp_regs[t_crit],
- data->temp[t_crit]);
+ ret = regmap_write(data->regmap, JC42_REG_TEMP_CRITICAL,
+ jc42_temp_to_reg(val, data->extended));
break;
case hwmon_temp_crit_hyst:
+ ret = regmap_read(data->regmap, JC42_REG_TEMP_CRITICAL,
+ &regval);
+ if (ret)
+ break;
+
/*
* JC42.4 compliant chips only support four hysteresis values.
* Pick best choice and go from there.
@@ -356,7 +359,7 @@ static int jc42_write(struct device *dev, enum hwmon_sensor_types type,
val = clamp_val(val, (data->extended ? JC42_TEMP_MIN_EXTENDED
: JC42_TEMP_MIN) - 6000,
JC42_TEMP_MAX);
- diff = jc42_temp_from_reg(data->temp[t_crit]) - val;
+ diff = jc42_temp_from_reg(regval) - val;
hyst = 0;
if (diff > 0) {
if (diff < 2250)
@@ -367,10 +370,9 @@ static int jc42_write(struct device *dev, enum hwmon_sensor_types type,
hyst = 3; /* 6.0 degrees C */
}
data->config = (data->config & ~JC42_CFG_HYST_MASK) |
- (hyst << JC42_CFG_HYST_SHIFT);
- ret = i2c_smbus_write_word_swapped(data->client,
- JC42_REG_CONFIG,
- data->config);
+ FIELD_PREP(JC42_CFG_HYST_MASK, hyst);
+ ret = regmap_write(data->regmap, JC42_REG_CONFIG,
+ data->config);
break;
default:
ret = -EOPNOTSUPP;
@@ -470,51 +472,80 @@ static const struct hwmon_chip_info jc42_chip_info = {
.info = jc42_info,
};
+static bool jc42_readable_reg(struct device *dev, unsigned int reg)
+{
+ return (reg >= JC42_REG_CAP && reg <= JC42_REG_DEVICEID) ||
+ reg == JC42_REG_SMBUS;
+}
+
+static bool jc42_writable_reg(struct device *dev, unsigned int reg)
+{
+ return (reg >= JC42_REG_CONFIG && reg <= JC42_REG_TEMP_CRITICAL) ||
+ reg == JC42_REG_SMBUS;
+}
+
+static bool jc42_volatile_reg(struct device *dev, unsigned int reg)
+{
+ return reg == JC42_REG_CONFIG || reg == JC42_REG_TEMP;
+}
+
+static const struct regmap_config jc42_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .val_format_endian = REGMAP_ENDIAN_BIG,
+ .max_register = JC42_REG_SMBUS,
+ .writeable_reg = jc42_writable_reg,
+ .readable_reg = jc42_readable_reg,
+ .volatile_reg = jc42_volatile_reg,
+ .cache_type = REGCACHE_RBTREE,
+};
+
static int jc42_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct device *hwmon_dev;
+ unsigned int config, cap;
struct jc42_data *data;
- int config, cap;
+ int ret;
data = devm_kzalloc(dev, sizeof(struct jc42_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- data->client = client;
+ data->regmap = devm_regmap_init_i2c(client, &jc42_regmap_config);
+ if (IS_ERR(data->regmap))
+ return PTR_ERR(data->regmap);
+
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
- cap = i2c_smbus_read_word_swapped(client, JC42_REG_CAP);
- if (cap < 0)
- return cap;
+ ret = regmap_read(data->regmap, JC42_REG_CAP, &cap);
+ if (ret)
+ return ret;
data->extended = !!(cap & JC42_CAP_RANGE);
if (device_property_read_bool(dev, "smbus-timeout-disable")) {
- int smbus;
-
/*
* Not all chips support this register, but from a
* quick read of various datasheets no chip appears
* incompatible with the below attempt to disable
* the timeout. And the whole thing is opt-in...
*/
- smbus = i2c_smbus_read_word_swapped(client, JC42_REG_SMBUS);
- if (smbus < 0)
- return smbus;
- i2c_smbus_write_word_swapped(client, JC42_REG_SMBUS,
- smbus | SMBUS_STMOUT);
+ ret = regmap_set_bits(data->regmap, JC42_REG_SMBUS,
+ SMBUS_STMOUT);
+ if (ret)
+ return ret;
}
- config = i2c_smbus_read_word_swapped(client, JC42_REG_CONFIG);
- if (config < 0)
- return config;
+ ret = regmap_read(data->regmap, JC42_REG_CONFIG, &config);
+ if (ret)
+ return ret;
data->orig_config = config;
if (config & JC42_CFG_SHUTDOWN) {
config &= ~JC42_CFG_SHUTDOWN;
- i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, config);
+ regmap_write(data->regmap, JC42_REG_CONFIG, config);
}
data->config = config;
@@ -535,7 +566,7 @@ static void jc42_remove(struct i2c_client *client)
config = (data->orig_config & ~JC42_CFG_HYST_MASK)
| (data->config & JC42_CFG_HYST_MASK);
- i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, config);
+ regmap_write(data->regmap, JC42_REG_CONFIG, config);
}
}
@@ -546,8 +577,11 @@ static int jc42_suspend(struct device *dev)
struct jc42_data *data = dev_get_drvdata(dev);
data->config |= JC42_CFG_SHUTDOWN;
- i2c_smbus_write_word_swapped(data->client, JC42_REG_CONFIG,
- data->config);
+ regmap_write(data->regmap, JC42_REG_CONFIG, data->config);
+
+ regcache_cache_only(data->regmap, true);
+ regcache_mark_dirty(data->regmap);
+
return 0;
}
@@ -555,10 +589,13 @@ static int jc42_resume(struct device *dev)
{
struct jc42_data *data = dev_get_drvdata(dev);
+ regcache_cache_only(data->regmap, false);
+
data->config &= ~JC42_CFG_SHUTDOWN;
- i2c_smbus_write_word_swapped(data->client, JC42_REG_CONFIG,
- data->config);
- return 0;
+ regmap_write(data->regmap, JC42_REG_CONFIG, data->config);
+
+ /* Restore cached register values to hardware */
+ return regcache_sync(data->regmap);
}
static const struct dev_pm_ops jc42_dev_pm_ops = {
diff --git a/drivers/hwmon/lm73.c b/drivers/hwmon/lm73.c
index 1346b3b3f463..b6433ae2d75c 100644
--- a/drivers/hwmon/lm73.c
+++ b/drivers/hwmon/lm73.c
@@ -92,7 +92,7 @@ static ssize_t temp_show(struct device *dev, struct device_attribute *da,
/* use integer division instead of equivalent right shift to
guarantee arithmetic shift and preserve the sign */
temp = (((s16) err) * 250) / 32;
- return scnprintf(buf, PAGE_SIZE, "%d\n", temp);
+ return sysfs_emit(buf, "%d\n", temp);
}
static ssize_t convrate_store(struct device *dev, struct device_attribute *da,
@@ -137,7 +137,7 @@ static ssize_t convrate_show(struct device *dev, struct device_attribute *da,
int res;
res = (data->ctrl & LM73_CTRL_RES_MASK) >> LM73_CTRL_RES_SHIFT;
- return scnprintf(buf, PAGE_SIZE, "%hu\n", lm73_convrates[res]);
+ return sysfs_emit(buf, "%hu\n", lm73_convrates[res]);
}
static ssize_t maxmin_alarm_show(struct device *dev,
@@ -154,7 +154,7 @@ static ssize_t maxmin_alarm_show(struct device *dev,
data->ctrl = ctrl;
mutex_unlock(&data->lock);
- return scnprintf(buf, PAGE_SIZE, "%d\n", (ctrl >> attr->index) & 1);
+ return sysfs_emit(buf, "%d\n", (ctrl >> attr->index) & 1);
abort:
mutex_unlock(&data->lock);
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index db595f7d01f8..6498d5acf705 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -103,6 +103,7 @@
#include <linux/interrupt.h>
#include <linux/jiffies.h>
#include <linux/hwmon.h>
+#include <linux/kstrtox.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_device.h>
@@ -2663,11 +2664,6 @@ static void lm90_remove_pec(void *dev)
device_remove_file(dev, &dev_attr_pec);
}
-static void lm90_regulator_disable(void *regulator)
-{
- regulator_disable(regulator);
-}
-
static int lm90_probe_channel_from_dt(struct i2c_client *client,
struct device_node *child,
struct lm90_data *data)
@@ -2749,24 +2745,13 @@ static int lm90_probe(struct i2c_client *client)
struct device *dev = &client->dev;
struct i2c_adapter *adapter = client->adapter;
struct hwmon_channel_info *info;
- struct regulator *regulator;
struct device *hwmon_dev;
struct lm90_data *data;
int err;
- regulator = devm_regulator_get(dev, "vcc");
- if (IS_ERR(regulator))
- return PTR_ERR(regulator);
-
- err = regulator_enable(regulator);
- if (err < 0) {
- dev_err(dev, "Failed to enable regulator: %d\n", err);
- return err;
- }
-
- err = devm_add_action_or_reset(dev, lm90_regulator_disable, regulator);
+ err = devm_regulator_get_enable(dev, "vcc");
if (err)
- return err;
+ return dev_err_probe(dev, err, "Failed to enable regulator\n");
data = devm_kzalloc(dev, sizeof(struct lm90_data), GFP_KERNEL);
if (!data)
diff --git a/drivers/hwmon/ltc2992.c b/drivers/hwmon/ltc2992.c
index 72489d5d7eaf..88514152d930 100644
--- a/drivers/hwmon/ltc2992.c
+++ b/drivers/hwmon/ltc2992.c
@@ -881,7 +881,7 @@ static int ltc2992_parse_dt(struct ltc2992_state *st)
return 0;
}
-static int ltc2992_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
+static int ltc2992_i2c_probe(struct i2c_client *client)
{
struct device *hwmon_dev;
struct ltc2992_state *st;
@@ -927,7 +927,7 @@ static struct i2c_driver ltc2992_i2c_driver = {
.name = "ltc2992",
.of_match_table = ltc2992_of_match,
},
- .probe = ltc2992_i2c_probe,
+ .probe_new = ltc2992_i2c_probe,
.id_table = ltc2992_i2c_id,
};
diff --git a/drivers/hwmon/max127.c b/drivers/hwmon/max127.c
index 402ffdc2f425..0e21e7e6bbd2 100644
--- a/drivers/hwmon/max127.c
+++ b/drivers/hwmon/max127.c
@@ -303,8 +303,7 @@ static const struct hwmon_chip_info max127_chip_info = {
.info = max127_info,
};
-static int max127_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int max127_probe(struct i2c_client *client)
{
int i;
struct device *hwmon_dev;
@@ -340,7 +339,7 @@ static struct i2c_driver max127_driver = {
.driver = {
.name = "max127",
},
- .probe = max127_probe,
+ .probe_new = max127_probe,
.id_table = max127_id,
};
diff --git a/drivers/hwmon/mr75203.c b/drivers/hwmon/mr75203.c
index 394a4c7e46ab..50a8b9c3f94d 100644
--- a/drivers/hwmon/mr75203.c
+++ b/drivers/hwmon/mr75203.c
@@ -11,6 +11,7 @@
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/hwmon.h>
+#include <linux/kstrtox.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
diff --git a/drivers/hwmon/nct6775-platform.c b/drivers/hwmon/nct6775-platform.c
index b34783784213..bf43f73dc835 100644
--- a/drivers/hwmon/nct6775-platform.c
+++ b/drivers/hwmon/nct6775-platform.c
@@ -1043,7 +1043,9 @@ static struct platform_device *pdev[2];
static const char * const asus_wmi_boards[] = {
"PRO H410T",
+ "ProArt B550-CREATOR",
"ProArt X570-CREATOR WIFI",
+ "ProArt Z490-CREATOR 10G",
"Pro B550M-C",
"Pro WS X570-ACE",
"PRIME B360-PLUS",
@@ -1055,8 +1057,10 @@ static const char * const asus_wmi_boards[] = {
"PRIME X570-P",
"PRIME X570-PRO",
"ROG CROSSHAIR VIII DARK HERO",
+ "ROG CROSSHAIR VIII EXTREME",
"ROG CROSSHAIR VIII FORMULA",
"ROG CROSSHAIR VIII HERO",
+ "ROG CROSSHAIR VIII HERO (WI-FI)",
"ROG CROSSHAIR VIII IMPACT",
"ROG STRIX B550-A GAMING",
"ROG STRIX B550-E GAMING",
@@ -1080,8 +1084,11 @@ static const char * const asus_wmi_boards[] = {
"ROG STRIX Z490-G GAMING (WI-FI)",
"ROG STRIX Z490-H GAMING",
"ROG STRIX Z490-I GAMING",
+ "TUF GAMING B550M-E",
+ "TUF GAMING B550M-E (WI-FI)",
"TUF GAMING B550M-PLUS",
"TUF GAMING B550M-PLUS (WI-FI)",
+ "TUF GAMING B550M-PLUS WIFI II",
"TUF GAMING B550-PLUS",
"TUF GAMING B550-PLUS WIFI II",
"TUF GAMING B550-PRO",
diff --git a/drivers/hwmon/occ/Kconfig b/drivers/hwmon/occ/Kconfig
index 35a7070db827..348c21100a37 100644
--- a/drivers/hwmon/occ/Kconfig
+++ b/drivers/hwmon/occ/Kconfig
@@ -6,7 +6,6 @@
config SENSORS_OCC_P8_I2C
tristate "POWER8 OCC through I2C"
depends on I2C
- depends on ARM || ARM64 || COMPILE_TEST
select SENSORS_OCC
help
This option enables support for monitoring sensors provided by the
@@ -21,7 +20,6 @@ config SENSORS_OCC_P8_I2C
config SENSORS_OCC_P9_SBE
tristate "POWER9 OCC through SBE"
depends on FSI_OCC
- depends on ARM || ARM64 || COMPILE_TEST
select SENSORS_OCC
help
This option enables support for monitoring sensors provided by the
diff --git a/drivers/hwmon/oxp-sensors.c b/drivers/hwmon/oxp-sensors.c
new file mode 100644
index 000000000000..f84ec8f8eda9
--- /dev/null
+++ b/drivers/hwmon/oxp-sensors.c
@@ -0,0 +1,284 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Platform driver for OXP Handhelds that expose fan reading and control
+ * via hwmon sysfs.
+ *
+ * Old boards have the same DMI strings and they are told appart by the
+ * boot cpu vendor (Intel/AMD). Currently only AMD boards are supported
+ * but the code is made to be simple to add other handheld boards in the
+ * future.
+ * Fan control is provided via pwm interface in the range [0-255].
+ * Old AMD boards use [0-100] as range in the EC, the written value is
+ * scaled to accommodate for that. Newer boards like the mini PRO and
+ * AOK ZOE are not scaled but have the same EC layout.
+ *
+ * Copyright (C) 2022 Joaquín I. Aramendía <samsagax@gmail.com>
+ */
+
+#include <linux/acpi.h>
+#include <linux/dev_printk.h>
+#include <linux/dmi.h>
+#include <linux/hwmon.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/processor.h>
+
+/* Handle ACPI lock mechanism */
+static u32 oxp_mutex;
+
+#define ACPI_LOCK_DELAY_MS 500
+
+static bool lock_global_acpi_lock(void)
+{
+ return ACPI_SUCCESS(acpi_acquire_global_lock(ACPI_LOCK_DELAY_MS, &oxp_mutex));
+}
+
+static bool unlock_global_acpi_lock(void)
+{
+ return ACPI_SUCCESS(acpi_release_global_lock(oxp_mutex));
+}
+
+enum oxp_board {
+ aok_zoe_a1 = 1,
+ oxp_mini_amd,
+ oxp_mini_amd_pro,
+};
+
+static enum oxp_board board;
+
+#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 */
+
+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},
+ },
+ {
+ .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},
+ },
+ {
+ .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},
+ },
+ {},
+};
+
+/* Helper functions to handle EC read/write */
+static int read_from_ec(u8 reg, int size, long *val)
+{
+ int i;
+ int ret;
+ u8 buffer;
+
+ if (!lock_global_acpi_lock())
+ return -EBUSY;
+
+ *val = 0;
+ for (i = 0; i < size; i++) {
+ ret = ec_read(reg + i, &buffer);
+ if (ret)
+ return ret;
+ *val <<= i * 8;
+ *val += buffer;
+ }
+
+ if (!unlock_global_acpi_lock())
+ return -EBUSY;
+
+ return 0;
+}
+
+static int write_to_ec(const struct device *dev, u8 reg, u8 value)
+{
+ int ret;
+
+ if (!lock_global_acpi_lock())
+ return -EBUSY;
+
+ ret = ec_write(reg, value);
+
+ if (!unlock_global_acpi_lock())
+ return -EBUSY;
+
+ return ret;
+}
+
+static int oxp_pwm_enable(const struct device *dev)
+{
+ return write_to_ec(dev, OXP_SENSOR_PWM_ENABLE_REG, 0x01);
+}
+
+static int oxp_pwm_disable(const struct device *dev)
+{
+ return write_to_ec(dev, OXP_SENSOR_PWM_ENABLE_REG, 0x00);
+}
+
+/* Callbacks for hwmon interface */
+static umode_t oxp_ec_hwmon_is_visible(const void *drvdata,
+ enum hwmon_sensor_types type, u32 attr, int channel)
+{
+ switch (type) {
+ case hwmon_fan:
+ return 0444;
+ case hwmon_pwm:
+ return 0644;
+ default:
+ return 0;
+ }
+}
+
+static int oxp_platform_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ int ret;
+
+ switch (type) {
+ case hwmon_fan:
+ switch (attr) {
+ case hwmon_fan_input:
+ return read_from_ec(OXP_SENSOR_FAN_REG, 2, val);
+ default:
+ break;
+ }
+ break;
+ case hwmon_pwm:
+ switch (attr) {
+ case hwmon_pwm_input:
+ ret = read_from_ec(OXP_SENSOR_PWM_REG, 1, val);
+ if (ret)
+ return ret;
+ if (board == oxp_mini_amd)
+ *val = (*val * 255) / 100;
+ return 0;
+ case hwmon_pwm_enable:
+ return read_from_ec(OXP_SENSOR_PWM_ENABLE_REG, 1, val);
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ return -EOPNOTSUPP;
+}
+
+static int oxp_platform_write(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long val)
+{
+ switch (type) {
+ case hwmon_pwm:
+ switch (attr) {
+ case hwmon_pwm_enable:
+ if (val == 1)
+ return oxp_pwm_enable(dev);
+ else if (val == 0)
+ return oxp_pwm_disable(dev);
+ return -EINVAL;
+ case hwmon_pwm_input:
+ if (val < 0 || val > 255)
+ return -EINVAL;
+ if (board == oxp_mini_amd)
+ val = (val * 100) / 255;
+ return write_to_ec(dev, OXP_SENSOR_PWM_REG, val);
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ return -EOPNOTSUPP;
+}
+
+/* Known sensors in the OXP EC controllers */
+static const struct hwmon_channel_info *oxp_platform_sensors[] = {
+ HWMON_CHANNEL_INFO(fan,
+ HWMON_F_INPUT),
+ HWMON_CHANNEL_INFO(pwm,
+ HWMON_PWM_INPUT | HWMON_PWM_ENABLE),
+ NULL,
+};
+
+static const struct hwmon_ops oxp_ec_hwmon_ops = {
+ .is_visible = oxp_ec_hwmon_is_visible,
+ .read = oxp_platform_read,
+ .write = oxp_platform_write,
+};
+
+static const struct hwmon_chip_info oxp_ec_chip_info = {
+ .ops = &oxp_ec_hwmon_ops,
+ .info = oxp_platform_sensors,
+};
+
+/* Initialization logic */
+static int oxp_platform_probe(struct platform_device *pdev)
+{
+ const struct dmi_system_id *dmi_entry;
+ struct device *dev = &pdev->dev;
+ struct device *hwdev;
+
+ /*
+ * Have to check for AMD processor here because DMI strings are the
+ * same between Intel and AMD boards, the only way to tell them appart
+ * is the CPU.
+ * Intel boards seem to have different EC registers and values to
+ * read/write.
+ */
+ dmi_entry = dmi_first_match(dmi_table);
+ if (!dmi_entry || boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
+ return -ENODEV;
+
+ board = *((enum oxp_board *) dmi_entry->driver_data);
+
+ hwdev = devm_hwmon_device_register_with_info(dev, "oxpec", NULL,
+ &oxp_ec_chip_info, NULL);
+
+ return PTR_ERR_OR_ZERO(hwdev);
+}
+
+static struct platform_driver oxp_platform_driver = {
+ .driver = {
+ .name = "oxp-platform",
+ },
+ .probe = oxp_platform_probe,
+};
+
+static struct platform_device *oxp_platform_device;
+
+static int __init oxp_platform_init(void)
+{
+ oxp_platform_device =
+ platform_create_bundle(&oxp_platform_driver,
+ oxp_platform_probe, NULL, 0, NULL, 0);
+
+ return PTR_ERR_OR_ZERO(oxp_platform_device);
+}
+
+static void __exit oxp_platform_exit(void)
+{
+ platform_device_unregister(oxp_platform_device);
+ platform_driver_unregister(&oxp_platform_driver);
+}
+
+MODULE_DEVICE_TABLE(dmi, dmi_table);
+
+module_init(oxp_platform_init);
+module_exit(oxp_platform_exit);
+
+MODULE_AUTHOR("Joaquín Ignacio Aramendía <samsagax@gmail.com>");
+MODULE_DESCRIPTION("Platform driver that handles EC sensors of OneXPlayer devices");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/pcf8591.c b/drivers/hwmon/pcf8591.c
index af9614e918a4..1dbe209ae13f 100644
--- a/drivers/hwmon/pcf8591.c
+++ b/drivers/hwmon/pcf8591.c
@@ -14,6 +14,7 @@
#include <linux/mutex.h>
#include <linux/err.h>
#include <linux/hwmon.h>
+#include <linux/kstrtox.h>
/* Insmod parameters */
diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c
index 6d2592731ba3..79f480b4425d 100644
--- a/drivers/hwmon/pmbus/ltc2978.c
+++ b/drivers/hwmon/pmbus/ltc2978.c
@@ -23,7 +23,7 @@ enum chips {
/* Managers */
ltc2972, ltc2974, ltc2975, ltc2977, ltc2978, ltc2979, ltc2980,
/* Controllers */
- ltc3880, ltc3882, ltc3883, ltc3884, ltc3886, ltc3887, ltc3889, ltc7880,
+ ltc3880, ltc3882, ltc3883, ltc3884, ltc3886, ltc3887, ltc3889, ltc7132, ltc7880,
/* Modules */
ltm2987, ltm4664, ltm4675, ltm4676, ltm4677, ltm4678, ltm4680, ltm4686,
ltm4700,
@@ -45,15 +45,14 @@ enum chips {
#define LTC2974_MFR_IOUT_PEAK 0xd7
#define LTC2974_MFR_IOUT_MIN 0xd8
-/* LTC3880, LTC3882, LTC3883, LTC3887, LTM4675, and LTM4676 */
+/* LTC3880, LTC3882, LTC3883, LTC3887, LTM4675, LTM4676, LTC7132 */
#define LTC3880_MFR_IOUT_PEAK 0xd7
#define LTC3880_MFR_CLEAR_PEAKS 0xe3
#define LTC3880_MFR_TEMPERATURE2_PEAK 0xf4
-/* LTC3883, LTC3884, LTC3886, LTC3889 and LTC7880 only */
+/* LTC3883, LTC3884, LTC3886, LTC3889, LTC7132, LTC7880 */
#define LTC3883_MFR_IIN_PEAK 0xe1
-
/* LTC2975 only */
#define LTC2975_MFR_IIN_PEAK 0xc4
#define LTC2975_MFR_IIN_MIN 0xc5
@@ -79,10 +78,11 @@ enum chips {
#define LTC3884_ID 0x4C00
#define LTC3886_ID 0x4600
#define LTC3887_ID 0x4700
-#define LTM2987_ID_A 0x8010 /* A/B for two die IDs */
-#define LTM2987_ID_B 0x8020
#define LTC3889_ID 0x4900
+#define LTC7132_ID 0x4CE0
#define LTC7880_ID 0x49E0
+#define LTM2987_ID_A 0x8010 /* A/B for two die IDs */
+#define LTM2987_ID_B 0x8020
#define LTM4664_ID 0x4120
#define LTM4675_ID 0x47a0
#define LTM4676_ID_REV1 0x4400
@@ -547,6 +547,7 @@ static const struct i2c_device_id ltc2978_id[] = {
{"ltc3886", ltc3886},
{"ltc3887", ltc3887},
{"ltc3889", ltc3889},
+ {"ltc7132", ltc7132},
{"ltc7880", ltc7880},
{"ltm2987", ltm2987},
{"ltm4664", ltm4664},
@@ -651,6 +652,8 @@ static int ltc2978_get_id(struct i2c_client *client)
return ltc3887;
else if (chip_id == LTC3889_ID)
return ltc3889;
+ else if (chip_id == LTC7132_ID)
+ return ltc7132;
else if (chip_id == LTC7880_ID)
return ltc7880;
else if (chip_id == LTM2987_ID_A || chip_id == LTM2987_ID_B)
@@ -831,6 +834,7 @@ static int ltc2978_probe(struct i2c_client *client)
case ltc3884:
case ltc3886:
case ltc3889:
+ case ltc7132:
case ltc7880:
case ltm4664:
case ltm4678:
@@ -902,6 +906,7 @@ static const struct of_device_id ltc2978_of_match[] = {
{ .compatible = "lltc,ltc3886" },
{ .compatible = "lltc,ltc3887" },
{ .compatible = "lltc,ltc3889" },
+ { .compatible = "lltc,ltc7132" },
{ .compatible = "lltc,ltc7880" },
{ .compatible = "lltc,ltm2987" },
{ .compatible = "lltc,ltm4664" },
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 7ec04934747e..95e95783972a 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -2827,9 +2827,13 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
if (status < 0)
return status;
- if (pmbus_regulator_is_enabled(rdev) && (status & PB_STATUS_OFF))
- *flags |= REGULATOR_ERROR_FAIL;
+ if (pmbus_regulator_is_enabled(rdev)) {
+ if (status & PB_STATUS_OFF)
+ *flags |= REGULATOR_ERROR_FAIL;
+ if (status & PB_STATUS_POWER_GOOD_N)
+ *flags |= REGULATOR_ERROR_REGULATION_OUT;
+ }
/*
* Unlike most other status bits, PB_STATUS_{IOUT_OC,VOUT_OV} are
* defined strictly as fault indicators (not warnings).
@@ -2851,6 +2855,49 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
return 0;
}
+static int pmbus_regulator_get_status(struct regulator_dev *rdev)
+{
+ struct device *dev = rdev_get_dev(rdev);
+ struct i2c_client *client = to_i2c_client(dev->parent);
+ struct pmbus_data *data = i2c_get_clientdata(client);
+ u8 page = rdev_get_id(rdev);
+ int status, ret;
+
+ mutex_lock(&data->update_lock);
+ status = pmbus_get_status(client, page, PMBUS_STATUS_WORD);
+ if (status < 0) {
+ ret = status;
+ goto unlock;
+ }
+
+ if (status & PB_STATUS_OFF) {
+ ret = REGULATOR_STATUS_OFF;
+ goto unlock;
+ }
+
+ /* If regulator is ON & reports power good then return ON */
+ if (!(status & PB_STATUS_POWER_GOOD_N)) {
+ ret = REGULATOR_STATUS_ON;
+ goto unlock;
+ }
+
+ ret = pmbus_regulator_get_error_flags(rdev, &status);
+ if (ret)
+ goto unlock;
+
+ if (status & (REGULATOR_ERROR_UNDER_VOLTAGE | REGULATOR_ERROR_OVER_CURRENT |
+ REGULATOR_ERROR_REGULATION_OUT | REGULATOR_ERROR_FAIL | REGULATOR_ERROR_OVER_TEMP)) {
+ ret = REGULATOR_STATUS_ERROR;
+ goto unlock;
+ }
+
+ ret = REGULATOR_STATUS_UNDEFINED;
+
+unlock:
+ mutex_unlock(&data->update_lock);
+ return ret;
+}
+
static int pmbus_regulator_get_low_margin(struct i2c_client *client, int page)
{
struct pmbus_data *data = i2c_get_clientdata(client);
@@ -2991,6 +3038,7 @@ const struct regulator_ops pmbus_regulator_ops = {
.disable = pmbus_regulator_disable,
.is_enabled = pmbus_regulator_is_enabled,
.get_error_flags = pmbus_regulator_get_error_flags,
+ .get_status = pmbus_regulator_get_status,
.get_voltage = pmbus_regulator_get_voltage,
.set_voltage = pmbus_regulator_set_voltage,
.list_voltage = pmbus_regulator_list_voltage,
diff --git a/drivers/hwmon/pmbus/q54sj108a2.c b/drivers/hwmon/pmbus/q54sj108a2.c
index fa298b4265a1..d3ba12951324 100644
--- a/drivers/hwmon/pmbus/q54sj108a2.c
+++ b/drivers/hwmon/pmbus/q54sj108a2.c
@@ -8,6 +8,7 @@
#include <linux/debugfs.h>
#include <linux/i2c.h>
+#include <linux/kstrtox.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include "pmbus.h"
diff --git a/drivers/hwmon/sbrmi.c b/drivers/hwmon/sbrmi.c
index 7bf0c3fba75f..8ea5a4d3219f 100644
--- a/drivers/hwmon/sbrmi.c
+++ b/drivers/hwmon/sbrmi.c
@@ -297,8 +297,7 @@ static int sbrmi_get_max_pwr_limit(struct sbrmi_data *data)
return ret;
}
-static int sbrmi_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int sbrmi_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct device *hwmon_dev;
@@ -348,7 +347,7 @@ static struct i2c_driver sbrmi_driver = {
.name = "sbrmi",
.of_match_table = of_match_ptr(sbrmi_of_match),
},
- .probe = sbrmi_probe,
+ .probe_new = sbrmi_probe,
.id_table = sbrmi_id,
};
diff --git a/drivers/hwmon/sbtsi_temp.c b/drivers/hwmon/sbtsi_temp.c
index e35357c48b8e..4c37de846f93 100644
--- a/drivers/hwmon/sbtsi_temp.c
+++ b/drivers/hwmon/sbtsi_temp.c
@@ -199,8 +199,7 @@ static const struct hwmon_chip_info sbtsi_chip_info = {
.info = sbtsi_info,
};
-static int sbtsi_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int sbtsi_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct device *hwmon_dev;
@@ -239,7 +238,7 @@ static struct i2c_driver sbtsi_driver = {
.name = "sbtsi",
.of_match_table = of_match_ptr(sbtsi_of_match),
},
- .probe = sbtsi_probe,
+ .probe_new = sbtsi_probe,
.id_table = sbtsi_id,
};
diff --git a/drivers/hwmon/sht3x.c b/drivers/hwmon/sht3x.c
index 3f279aa1cee5..8305e44d9ab2 100644
--- a/drivers/hwmon/sht3x.c
+++ b/drivers/hwmon/sht3x.c
@@ -320,7 +320,7 @@ static ssize_t temp1_limit_show(struct device *dev,
u8 index = to_sensor_dev_attr(attr)->index;
int temperature_limit = data->temperature_limits[index];
- return scnprintf(buf, PAGE_SIZE, "%d\n", temperature_limit);
+ return sysfs_emit(buf, "%d\n", temperature_limit);
}
static ssize_t humidity1_limit_show(struct device *dev,
@@ -331,7 +331,7 @@ static ssize_t humidity1_limit_show(struct device *dev,
u8 index = to_sensor_dev_attr(attr)->index;
u32 humidity_limit = data->humidity_limits[index];
- return scnprintf(buf, PAGE_SIZE, "%u\n", humidity_limit);
+ return sysfs_emit(buf, "%u\n", humidity_limit);
}
/*
@@ -483,7 +483,7 @@ static ssize_t temp1_alarm_show(struct device *dev,
if (ret)
return ret;
- return scnprintf(buf, PAGE_SIZE, "%d\n", !!(buffer[0] & 0x04));
+ return sysfs_emit(buf, "%d\n", !!(buffer[0] & 0x04));
}
static ssize_t humidity1_alarm_show(struct device *dev,
@@ -498,7 +498,7 @@ static ssize_t humidity1_alarm_show(struct device *dev,
if (ret)
return ret;
- return scnprintf(buf, PAGE_SIZE, "%d\n", !!(buffer[0] & 0x08));
+ return sysfs_emit(buf, "%d\n", !!(buffer[0] & 0x08));
}
static ssize_t heater_enable_show(struct device *dev,
@@ -513,7 +513,7 @@ static ssize_t heater_enable_show(struct device *dev,
if (ret)
return ret;
- return scnprintf(buf, PAGE_SIZE, "%d\n", !!(buffer[0] & 0x20));
+ return sysfs_emit(buf, "%d\n", !!(buffer[0] & 0x20));
}
static ssize_t heater_enable_store(struct device *dev,
@@ -550,7 +550,7 @@ static ssize_t update_interval_show(struct device *dev,
{
struct sht3x_data *data = dev_get_drvdata(dev);
- return scnprintf(buf, PAGE_SIZE, "%u\n",
+ return sysfs_emit(buf, "%u\n",
mode_to_update_interval[data->mode]);
}
diff --git a/drivers/hwmon/sht4x.c b/drivers/hwmon/sht4x.c
index 13ac2d8f22c7..13e042927bf8 100644
--- a/drivers/hwmon/sht4x.c
+++ b/drivers/hwmon/sht4x.c
@@ -232,8 +232,7 @@ static const struct hwmon_chip_info sht4x_chip_info = {
.info = sht4x_info,
};
-static int sht4x_probe(struct i2c_client *client,
- const struct i2c_device_id *sht4x_id)
+static int sht4x_probe(struct i2c_client *client)
{
struct device *device = &client->dev;
struct device *hwmon_dev;
@@ -292,7 +291,7 @@ static struct i2c_driver sht4x_driver = {
.name = "sht4x",
.of_match_table = sht4x_of_match,
},
- .probe = sht4x_probe,
+ .probe_new = sht4x_probe,
.id_table = sht4x_id,
};
diff --git a/drivers/hwmon/smpro-hwmon.c b/drivers/hwmon/smpro-hwmon.c
new file mode 100644
index 000000000000..a76c49dd8438
--- /dev/null
+++ b/drivers/hwmon/smpro-hwmon.c
@@ -0,0 +1,466 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Ampere Computing SoC's SMPro Hardware Monitoring Driver
+ *
+ * Copyright (c) 2022, Ampere Computing LLC
+ */
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/regmap.h>
+
+/* Logical Power Sensor Registers */
+#define SOC_TEMP 0x10
+#define SOC_VRD_TEMP 0x11
+#define DIMM_VRD_TEMP 0x12
+#define CORE_VRD_TEMP 0x13
+#define CH0_DIMM_TEMP 0x14
+#define CH1_DIMM_TEMP 0x15
+#define CH2_DIMM_TEMP 0x16
+#define CH3_DIMM_TEMP 0x17
+#define CH4_DIMM_TEMP 0x18
+#define CH5_DIMM_TEMP 0x19
+#define CH6_DIMM_TEMP 0x1A
+#define CH7_DIMM_TEMP 0x1B
+#define RCA_VRD_TEMP 0x1C
+
+#define CORE_VRD_PWR 0x20
+#define SOC_PWR 0x21
+#define DIMM_VRD1_PWR 0x22
+#define DIMM_VRD2_PWR 0x23
+#define CORE_VRD_PWR_MW 0x26
+#define SOC_PWR_MW 0x27
+#define DIMM_VRD1_PWR_MW 0x28
+#define DIMM_VRD2_PWR_MW 0x29
+#define RCA_VRD_PWR 0x2A
+#define RCA_VRD_PWR_MW 0x2B
+
+#define MEM_HOT_THRESHOLD 0x32
+#define SOC_VR_HOT_THRESHOLD 0x33
+#define CORE_VRD_VOLT 0x34
+#define SOC_VRD_VOLT 0x35
+#define DIMM_VRD1_VOLT 0x36
+#define DIMM_VRD2_VOLT 0x37
+#define RCA_VRD_VOLT 0x38
+
+#define CORE_VRD_CURR 0x39
+#define SOC_VRD_CURR 0x3A
+#define DIMM_VRD1_CURR 0x3B
+#define DIMM_VRD2_CURR 0x3C
+#define RCA_VRD_CURR 0x3D
+
+struct smpro_hwmon {
+ struct regmap *regmap;
+};
+
+struct smpro_sensor {
+ const u8 reg;
+ const u8 reg_ext;
+ const char *label;
+};
+
+static const struct smpro_sensor temperature[] = {
+ {
+ .reg = SOC_TEMP,
+ .label = "temp1 SoC"
+ },
+ {
+ .reg = SOC_VRD_TEMP,
+ .reg_ext = SOC_VR_HOT_THRESHOLD,
+ .label = "temp2 SoC VRD"
+ },
+ {
+ .reg = DIMM_VRD_TEMP,
+ .label = "temp3 DIMM VRD"
+ },
+ {
+ .reg = CORE_VRD_TEMP,
+ .label = "temp4 CORE VRD"
+ },
+ {
+ .reg = CH0_DIMM_TEMP,
+ .reg_ext = MEM_HOT_THRESHOLD,
+ .label = "temp5 CH0 DIMM"
+ },
+ {
+ .reg = CH1_DIMM_TEMP,
+ .reg_ext = MEM_HOT_THRESHOLD,
+ .label = "temp6 CH1 DIMM"
+ },
+ {
+ .reg = CH2_DIMM_TEMP,
+ .reg_ext = MEM_HOT_THRESHOLD,
+ .label = "temp7 CH2 DIMM"
+ },
+ {
+ .reg = CH3_DIMM_TEMP,
+ .reg_ext = MEM_HOT_THRESHOLD,
+ .label = "temp8 CH3 DIMM"
+ },
+ {
+ .reg = CH4_DIMM_TEMP,
+ .reg_ext = MEM_HOT_THRESHOLD,
+ .label = "temp9 CH4 DIMM"
+ },
+ {
+ .reg = CH5_DIMM_TEMP,
+ .reg_ext = MEM_HOT_THRESHOLD,
+ .label = "temp10 CH5 DIMM"
+ },
+ {
+ .reg = CH6_DIMM_TEMP,
+ .reg_ext = MEM_HOT_THRESHOLD,
+ .label = "temp11 CH6 DIMM"
+ },
+ {
+ .reg = CH7_DIMM_TEMP,
+ .reg_ext = MEM_HOT_THRESHOLD,
+ .label = "temp12 CH7 DIMM"
+ },
+ {
+ .reg = RCA_VRD_TEMP,
+ .label = "temp13 RCA VRD"
+ },
+};
+
+static const struct smpro_sensor voltage[] = {
+ {
+ .reg = CORE_VRD_VOLT,
+ .label = "vout0 CORE VRD"
+ },
+ {
+ .reg = SOC_VRD_VOLT,
+ .label = "vout1 SoC VRD"
+ },
+ {
+ .reg = DIMM_VRD1_VOLT,
+ .label = "vout2 DIMM VRD1"
+ },
+ {
+ .reg = DIMM_VRD2_VOLT,
+ .label = "vout3 DIMM VRD2"
+ },
+ {
+ .reg = RCA_VRD_VOLT,
+ .label = "vout4 RCA VRD"
+ },
+};
+
+static const struct smpro_sensor curr_sensor[] = {
+ {
+ .reg = CORE_VRD_CURR,
+ .label = "iout1 CORE VRD"
+ },
+ {
+ .reg = SOC_VRD_CURR,
+ .label = "iout2 SoC VRD"
+ },
+ {
+ .reg = DIMM_VRD1_CURR,
+ .label = "iout3 DIMM VRD1"
+ },
+ {
+ .reg = DIMM_VRD2_CURR,
+ .label = "iout4 DIMM VRD2"
+ },
+ {
+ .reg = RCA_VRD_CURR,
+ .label = "iout5 RCA VRD"
+ },
+};
+
+static const struct smpro_sensor power[] = {
+ {
+ .reg = CORE_VRD_PWR,
+ .reg_ext = CORE_VRD_PWR_MW,
+ .label = "power1 CORE VRD"
+ },
+ {
+ .reg = SOC_PWR,
+ .reg_ext = SOC_PWR_MW,
+ .label = "power2 SoC"
+ },
+ {
+ .reg = DIMM_VRD1_PWR,
+ .reg_ext = DIMM_VRD1_PWR_MW,
+ .label = "power3 DIMM VRD1"
+ },
+ {
+ .reg = DIMM_VRD2_PWR,
+ .reg_ext = DIMM_VRD2_PWR_MW,
+ .label = "power4 DIMM VRD2"
+ },
+ {
+ .reg = RCA_VRD_PWR,
+ .reg_ext = RCA_VRD_PWR_MW,
+ .label = "power5 RCA VRD"
+ },
+};
+
+static int smpro_read_temp(struct device *dev, u32 attr, int channel, long *val)
+{
+ struct smpro_hwmon *hwmon = dev_get_drvdata(dev);
+ unsigned int value;
+ int ret;
+
+ switch (attr) {
+ case hwmon_temp_input:
+ ret = regmap_read(hwmon->regmap, temperature[channel].reg, &value);
+ if (ret)
+ return ret;
+ break;
+ case hwmon_temp_crit:
+ ret = regmap_read(hwmon->regmap, temperature[channel].reg_ext, &value);
+ if (ret)
+ return ret;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ *val = sign_extend32(value, 8) * 1000;
+ return 0;
+}
+
+static int smpro_read_in(struct device *dev, u32 attr, int channel, long *val)
+{
+ struct smpro_hwmon *hwmon = dev_get_drvdata(dev);
+ unsigned int value;
+ int ret;
+
+ switch (attr) {
+ case hwmon_in_input:
+ ret = regmap_read(hwmon->regmap, voltage[channel].reg, &value);
+ if (ret < 0)
+ return ret;
+ /* 15-bit value in 1mV */
+ *val = value & 0x7fff;
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int smpro_read_curr(struct device *dev, u32 attr, int channel, long *val)
+{
+ struct smpro_hwmon *hwmon = dev_get_drvdata(dev);
+ unsigned int value;
+ int ret;
+
+ switch (attr) {
+ case hwmon_curr_input:
+ ret = regmap_read(hwmon->regmap, curr_sensor[channel].reg, &value);
+ if (ret < 0)
+ return ret;
+ /* Scale reported by the hardware is 1mA */
+ *val = value & 0x7fff;
+ return 0;
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int smpro_read_power(struct device *dev, u32 attr, int channel, long *val_pwr)
+{
+ struct smpro_hwmon *hwmon = dev_get_drvdata(dev);
+ unsigned int val = 0, val_mw = 0;
+ int ret;
+
+ switch (attr) {
+ case hwmon_power_input:
+ ret = regmap_read(hwmon->regmap, power[channel].reg, &val);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(hwmon->regmap, power[channel].reg_ext, &val_mw);
+ if (ret)
+ return ret;
+ /* 10-bit value */
+ *val_pwr = (val & 0x3ff) * 1000000 + (val_mw & 0x3ff) * 1000;
+ return 0;
+
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int smpro_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ switch (type) {
+ case hwmon_temp:
+ return smpro_read_temp(dev, attr, channel, val);
+ case hwmon_in:
+ return smpro_read_in(dev, attr, channel, val);
+ case hwmon_power:
+ return smpro_read_power(dev, attr, channel, val);
+ case hwmon_curr:
+ return smpro_read_curr(dev, attr, channel, val);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int smpro_read_string(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, const char **str)
+{
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_label:
+ *str = temperature[channel].label;
+ return 0;
+ default:
+ break;
+ }
+ break;
+
+ case hwmon_in:
+ switch (attr) {
+ case hwmon_in_label:
+ *str = voltage[channel].label;
+ return 0;
+ default:
+ break;
+ }
+ break;
+
+ case hwmon_curr:
+ switch (attr) {
+ case hwmon_curr_label:
+ *str = curr_sensor[channel].label;
+ return 0;
+ default:
+ break;
+ }
+ break;
+
+ case hwmon_power:
+ switch (attr) {
+ case hwmon_power_label:
+ *str = power[channel].label;
+ return 0;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return -EOPNOTSUPP;
+}
+
+static umode_t smpro_is_visible(const void *data, enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ const struct smpro_hwmon *hwmon = data;
+ unsigned int value;
+ int ret;
+
+ switch (type) {
+ case hwmon_temp:
+ switch (attr) {
+ case hwmon_temp_input:
+ case hwmon_temp_label:
+ case hwmon_temp_crit:
+ ret = regmap_read(hwmon->regmap, temperature[channel].reg, &value);
+ if (ret || value == 0xFFFF)
+ return 0;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return 0444;
+}
+
+static const struct hwmon_channel_info *smpro_info[] = {
+ HWMON_CHANNEL_INFO(temp,
+ HWMON_T_INPUT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT,
+ HWMON_T_INPUT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_LABEL,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT,
+ HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_CRIT,
+ HWMON_T_INPUT | HWMON_T_LABEL),
+ HWMON_CHANNEL_INFO(in,
+ HWMON_I_INPUT | HWMON_I_LABEL,
+ HWMON_I_INPUT | HWMON_I_LABEL,
+ HWMON_I_INPUT | HWMON_I_LABEL,
+ HWMON_I_INPUT | HWMON_I_LABEL,
+ HWMON_I_INPUT | HWMON_I_LABEL),
+ HWMON_CHANNEL_INFO(power,
+ HWMON_P_INPUT | HWMON_P_LABEL,
+ HWMON_P_INPUT | HWMON_P_LABEL,
+ HWMON_P_INPUT | HWMON_P_LABEL,
+ HWMON_P_INPUT | HWMON_P_LABEL,
+ HWMON_P_INPUT | HWMON_P_LABEL),
+ HWMON_CHANNEL_INFO(curr,
+ HWMON_C_INPUT | HWMON_C_LABEL,
+ HWMON_C_INPUT | HWMON_C_LABEL,
+ HWMON_C_INPUT | HWMON_C_LABEL,
+ HWMON_C_INPUT | HWMON_C_LABEL,
+ HWMON_C_INPUT | HWMON_C_LABEL),
+ NULL
+};
+
+static const struct hwmon_ops smpro_hwmon_ops = {
+ .is_visible = smpro_is_visible,
+ .read = smpro_read,
+ .read_string = smpro_read_string,
+};
+
+static const struct hwmon_chip_info smpro_chip_info = {
+ .ops = &smpro_hwmon_ops,
+ .info = smpro_info,
+};
+
+static int smpro_hwmon_probe(struct platform_device *pdev)
+{
+ struct smpro_hwmon *hwmon;
+ struct device *hwmon_dev;
+
+ hwmon = devm_kzalloc(&pdev->dev, sizeof(struct smpro_hwmon), GFP_KERNEL);
+ if (!hwmon)
+ return -ENOMEM;
+
+ hwmon->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!hwmon->regmap)
+ return -ENODEV;
+
+ hwmon_dev = devm_hwmon_device_register_with_info(&pdev->dev, "smpro_hwmon",
+ hwmon, &smpro_chip_info, NULL);
+
+ return PTR_ERR_OR_ZERO(hwmon_dev);
+}
+
+static struct platform_driver smpro_hwmon_driver = {
+ .probe = smpro_hwmon_probe,
+ .driver = {
+ .name = "smpro-hwmon",
+ },
+};
+
+module_platform_driver(smpro_hwmon_driver);
+
+MODULE_AUTHOR("Thu Nguyen <thu@os.amperecomputing.com>");
+MODULE_AUTHOR("Quan Nguyen <quan@os.amperecomputing.com>");
+MODULE_DESCRIPTION("Ampere Altra SMPro hwmon driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index 3b7f8922b0d5..b7c6392ba673 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -22,7 +22,6 @@
#include <linux/platform_device.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
-#include <linux/hwmon-vid.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/acpi.h>
diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c
index 2c4646fa8426..5597e1c2d95c 100644
--- a/drivers/hwmon/w83l786ng.c
+++ b/drivers/hwmon/w83l786ng.c
@@ -16,7 +16,6 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
-#include <linux/hwmon-vid.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
#include <linux/mutex.h>
diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c
index f8f8aea15612..c279c4f2c9b7 100644
--- a/drivers/iio/adc/twl4030-madc.c
+++ b/drivers/iio/adc/twl4030-madc.c
@@ -30,6 +30,7 @@
#include <linux/types.h>
#include <linux/gfp.h>
#include <linux/err.h>
+#include <linux/of.h>
#include <linux/regulator/consumer.h>
#include <linux/iio/iio.h>
diff --git a/drivers/infiniband/core/cm_trace.h b/drivers/infiniband/core/cm_trace.h
index e9d282679ef1..944d9071245d 100644
--- a/drivers/infiniband/core/cm_trace.h
+++ b/drivers/infiniband/core/cm_trace.h
@@ -16,7 +16,7 @@
#include <linux/tracepoint.h>
#include <rdma/ib_cm.h>
-#include <trace/events/rdma.h>
+#include <trace/misc/rdma.h>
/*
* enum ib_cm_state, from include/rdma/ib_cm.h
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 26d1772179b8..aacd6254df77 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -3807,7 +3807,7 @@ static int cma_alloc_any_port(enum rdma_ucm_port_space ps,
inet_get_local_port_range(net, &low, &high);
remaining = (high - low) + 1;
- rover = prandom_u32_max(remaining) + low;
+ rover = get_random_u32_inclusive(low, remaining + low - 1);
retry:
if (last_used_port != rover) {
struct rdma_bind_list *bind_list;
diff --git a/drivers/infiniband/core/cma_trace.h b/drivers/infiniband/core/cma_trace.h
index e45264267bcc..47f3c6e4be89 100644
--- a/drivers/infiniband/core/cma_trace.h
+++ b/drivers/infiniband/core/cma_trace.h
@@ -15,7 +15,7 @@
#define _TRACE_RDMA_CMA_H
#include <linux/tracepoint.h>
-#include <trace/events/rdma.h>
+#include <trace/misc/rdma.h>
DECLARE_EVENT_CLASS(cma_fsm_class,
diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c
index 04c04e6d24c3..43b26bc12288 100644
--- a/drivers/infiniband/core/umem_dmabuf.c
+++ b/drivers/infiniband/core/umem_dmabuf.c
@@ -26,7 +26,8 @@ int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf)
if (umem_dmabuf->sgt)
goto wait_fence;
- sgt = dma_buf_map_attachment(umem_dmabuf->attach, DMA_BIDIRECTIONAL);
+ sgt = dma_buf_map_attachment_unlocked(umem_dmabuf->attach,
+ DMA_BIDIRECTIONAL);
if (IS_ERR(sgt))
return PTR_ERR(sgt);
@@ -102,8 +103,8 @@ void ib_umem_dmabuf_unmap_pages(struct ib_umem_dmabuf *umem_dmabuf)
umem_dmabuf->last_sg_trim = 0;
}
- dma_buf_unmap_attachment(umem_dmabuf->attach, umem_dmabuf->sgt,
- DMA_BIDIRECTIONAL);
+ dma_buf_unmap_attachment_unlocked(umem_dmabuf->attach, umem_dmabuf->sgt,
+ DMA_BIDIRECTIONAL);
umem_dmabuf->sgt = NULL;
}
diff --git a/drivers/infiniband/hw/cxgb4/id_table.c b/drivers/infiniband/hw/cxgb4/id_table.c
index 280d61466855..e2188b335e76 100644
--- a/drivers/infiniband/hw/cxgb4/id_table.c
+++ b/drivers/infiniband/hw/cxgb4/id_table.c
@@ -54,7 +54,7 @@ u32 c4iw_id_alloc(struct c4iw_id_table *alloc)
if (obj < alloc->max) {
if (alloc->flags & C4IW_ID_TABLE_F_RANDOM)
- alloc->last += prandom_u32_max(RANDOM_SKIP);
+ alloc->last += get_random_u32_below(RANDOM_SKIP);
else
alloc->last = obj + 1;
if (alloc->last >= alloc->max)
@@ -85,7 +85,7 @@ int c4iw_id_table_alloc(struct c4iw_id_table *alloc, u32 start, u32 num,
alloc->start = start;
alloc->flags = flags;
if (flags & C4IW_ID_TABLE_F_RANDOM)
- alloc->last = prandom_u32_max(RANDOM_SKIP);
+ alloc->last = get_random_u32_below(RANDOM_SKIP);
else
alloc->last = 0;
alloc->max = num;
diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c
index 436372b31431..24c0f0d257fc 100644
--- a/drivers/infiniband/hw/hfi1/init.c
+++ b/drivers/infiniband/hw/hfi1/init.c
@@ -1761,17 +1761,11 @@ int hfi1_create_rcvhdrq(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd)
unsigned amt;
if (!rcd->rcvhdrq) {
- gfp_t gfp_flags;
-
amt = rcvhdrq_size(rcd);
- if (rcd->ctxt < dd->first_dyn_alloc_ctxt || rcd->is_vnic)
- gfp_flags = GFP_KERNEL;
- else
- gfp_flags = GFP_USER;
rcd->rcvhdrq = dma_alloc_coherent(&dd->pcidev->dev, amt,
&rcd->rcvhdrq_dma,
- gfp_flags | __GFP_COMP);
+ GFP_KERNEL);
if (!rcd->rcvhdrq) {
dd_dev_err(dd,
@@ -1785,7 +1779,7 @@ int hfi1_create_rcvhdrq(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd)
rcd->rcvhdrtail_kvaddr = dma_alloc_coherent(&dd->pcidev->dev,
PAGE_SIZE,
&rcd->rcvhdrqtailaddr_dma,
- gfp_flags);
+ GFP_KERNEL);
if (!rcd->rcvhdrtail_kvaddr)
goto bail_free;
}
@@ -1821,20 +1815,11 @@ int hfi1_setup_eagerbufs(struct hfi1_ctxtdata *rcd)
{
struct hfi1_devdata *dd = rcd->dd;
u32 max_entries, egrtop, alloced_bytes = 0;
- gfp_t gfp_flags;
u16 order, idx = 0;
int ret = 0;
u16 round_mtu = roundup_pow_of_two(hfi1_max_mtu);
/*
- * GFP_USER, but without GFP_FS, so buffer cache can be
- * coalesced (we hope); otherwise, even at order 4,
- * heavy filesystem activity makes these fail, and we can
- * use compound pages.
- */
- gfp_flags = __GFP_RECLAIM | __GFP_IO | __GFP_COMP;
-
- /*
* The minimum size of the eager buffers is a groups of MTU-sized
* buffers.
* The global eager_buffer_size parameter is checked against the
@@ -1864,7 +1849,7 @@ int hfi1_setup_eagerbufs(struct hfi1_ctxtdata *rcd)
dma_alloc_coherent(&dd->pcidev->dev,
rcd->egrbufs.rcvtid_size,
&rcd->egrbufs.buffers[idx].dma,
- gfp_flags);
+ GFP_KERNEL);
if (rcd->egrbufs.buffers[idx].addr) {
rcd->egrbufs.buffers[idx].len =
rcd->egrbufs.rcvtid_size;
diff --git a/drivers/infiniband/hw/hns/hns_roce_ah.c b/drivers/infiniband/hw/hns/hns_roce_ah.c
index 480c062dd04f..e77fcc74f15c 100644
--- a/drivers/infiniband/hw/hns/hns_roce_ah.c
+++ b/drivers/infiniband/hw/hns/hns_roce_ah.c
@@ -41,9 +41,8 @@ static inline u16 get_ah_udp_sport(const struct rdma_ah_attr *ah_attr)
u16 sport;
if (!fl)
- sport = prandom_u32_max(IB_ROCE_UDP_ENCAP_VALID_PORT_MAX + 1 -
- IB_ROCE_UDP_ENCAP_VALID_PORT_MIN) +
- IB_ROCE_UDP_ENCAP_VALID_PORT_MIN;
+ sport = get_random_u32_inclusive(IB_ROCE_UDP_ENCAP_VALID_PORT_MIN,
+ IB_ROCE_UDP_ENCAP_VALID_PORT_MAX);
else
sport = rdma_flow_label_to_udp_sport(fl);
diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c
index aea571943768..07386117f21a 100644
--- a/drivers/infiniband/hw/qib/qib_iba6120.c
+++ b/drivers/infiniband/hw/qib/qib_iba6120.c
@@ -2075,7 +2075,7 @@ static void alloc_dummy_hdrq(struct qib_devdata *dd)
dd->cspec->dummy_hdrq = dma_alloc_coherent(&dd->pcidev->dev,
dd->rcd[0]->rcvhdrq_size,
&dd->cspec->dummy_hdrq_phys,
- GFP_ATOMIC | __GFP_COMP);
+ GFP_ATOMIC);
if (!dd->cspec->dummy_hdrq) {
qib_devinfo(dd->pcidev, "Couldn't allocate dummy hdrq\n");
/* fallback to just 0'ing */
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c
index 45211008449f..33667becd52b 100644
--- a/drivers/infiniband/hw/qib/qib_init.c
+++ b/drivers/infiniband/hw/qib/qib_init.c
@@ -1546,18 +1546,14 @@ int qib_create_rcvhdrq(struct qib_devdata *dd, struct qib_ctxtdata *rcd)
if (!rcd->rcvhdrq) {
dma_addr_t phys_hdrqtail;
- gfp_t gfp_flags;
amt = ALIGN(dd->rcvhdrcnt * dd->rcvhdrentsize *
sizeof(u32), PAGE_SIZE);
- gfp_flags = (rcd->ctxt >= dd->first_user_ctxt) ?
- GFP_USER : GFP_KERNEL;
old_node_id = dev_to_node(&dd->pcidev->dev);
set_dev_node(&dd->pcidev->dev, rcd->node_id);
- rcd->rcvhdrq = dma_alloc_coherent(
- &dd->pcidev->dev, amt, &rcd->rcvhdrq_phys,
- gfp_flags | __GFP_COMP);
+ rcd->rcvhdrq = dma_alloc_coherent(&dd->pcidev->dev, amt,
+ &rcd->rcvhdrq_phys, GFP_KERNEL);
set_dev_node(&dd->pcidev->dev, old_node_id);
if (!rcd->rcvhdrq) {
@@ -1577,7 +1573,7 @@ int qib_create_rcvhdrq(struct qib_devdata *dd, struct qib_ctxtdata *rcd)
set_dev_node(&dd->pcidev->dev, rcd->node_id);
rcd->rcvhdrtail_kvaddr = dma_alloc_coherent(
&dd->pcidev->dev, PAGE_SIZE, &phys_hdrqtail,
- gfp_flags);
+ GFP_KERNEL);
set_dev_node(&dd->pcidev->dev, old_node_id);
if (!rcd->rcvhdrtail_kvaddr)
goto bail_free;
@@ -1621,17 +1617,8 @@ int qib_setup_eagerbufs(struct qib_ctxtdata *rcd)
struct qib_devdata *dd = rcd->dd;
unsigned e, egrcnt, egrperchunk, chunk, egrsize, egroff;
size_t size;
- gfp_t gfp_flags;
int old_node_id;
- /*
- * GFP_USER, but without GFP_FS, so buffer cache can be
- * coalesced (we hope); otherwise, even at order 4,
- * heavy filesystem activity makes these fail, and we can
- * use compound pages.
- */
- gfp_flags = __GFP_RECLAIM | __GFP_IO | __GFP_COMP;
-
egrcnt = rcd->rcvegrcnt;
egroff = rcd->rcvegr_tid_base;
egrsize = dd->rcvegrbufsize;
@@ -1663,7 +1650,7 @@ int qib_setup_eagerbufs(struct qib_ctxtdata *rcd)
rcd->rcvegrbuf[e] =
dma_alloc_coherent(&dd->pcidev->dev, size,
&rcd->rcvegrbuf_phys[e],
- gfp_flags);
+ GFP_KERNEL);
set_dev_node(&dd->pcidev->dev, old_node_id);
if (!rcd->rcvegrbuf[e])
goto bail_rcvegrbuf_phys;
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
index 8546b8816524..205fd44a4727 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c
@@ -966,7 +966,7 @@ static void rtrs_clt_init_req(struct rtrs_clt_io_req *req,
refcount_set(&req->ref, 1);
req->mp_policy = clt_path->clt->mp_policy;
- iov_iter_kvec(&iter, READ, vec, 1, usr_len);
+ iov_iter_kvec(&iter, ITER_SOURCE, vec, 1, usr_len);
len = _copy_from_iter(req->iu->buf, usr_len, &iter);
WARN_ON(len != usr_len);
@@ -1517,7 +1517,7 @@ static void rtrs_clt_err_recovery_work(struct work_struct *work)
rtrs_clt_stop_and_destroy_conns(clt_path);
queue_delayed_work(rtrs_wq, &clt_path->reconnect_dwork,
msecs_to_jiffies(delay_ms +
- prandom_u32_max(RTRS_RECONNECT_SEED)));
+ get_random_u32_below(RTRS_RECONNECT_SEED)));
}
static struct rtrs_clt_path *alloc_path(struct rtrs_clt_sess *clt,
diff --git a/drivers/input/input.c b/drivers/input/input.c
index ebb2b7f0f8ff..783961df3626 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -21,6 +21,7 @@
#include <linux/seq_file.h>
#include <linux/poll.h>
#include <linux/device.h>
+#include <linux/kstrtox.h>
#include <linux/mutex.h>
#include <linux/rcupdate.h>
#include "input-compat.h"
@@ -1465,7 +1466,7 @@ static ssize_t inhibited_store(struct device *dev,
ssize_t rv;
bool inhibited;
- if (strtobool(buf, &inhibited))
+ if (kstrtobool(buf, &inhibited))
return -EINVAL;
if (inhibited)
diff --git a/drivers/input/joystick/Kconfig b/drivers/input/joystick/Kconfig
index 9dcf3f51f2dd..04ca3d1c2816 100644
--- a/drivers/input/joystick/Kconfig
+++ b/drivers/input/joystick/Kconfig
@@ -46,6 +46,7 @@ config JOYSTICK_A3D
config JOYSTICK_ADC
tristate "Simple joystick connected over ADC"
depends on IIO
+ select IIO_BUFFER
select IIO_BUFFER_CB
help
Say Y here if you have a simple joystick connected over ADC.
diff --git a/drivers/input/joystick/as5011.c b/drivers/input/joystick/as5011.c
index 2beda29021a3..3b88f0b49e01 100644
--- a/drivers/input/joystick/as5011.c
+++ b/drivers/input/joystick/as5011.c
@@ -212,8 +212,7 @@ static int as5011_configure_chip(struct as5011_device *as5011,
return 0;
}
-static int as5011_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int as5011_probe(struct i2c_client *client)
{
const struct as5011_platform_data *plat_data;
struct as5011_device *as5011;
@@ -349,7 +348,7 @@ static struct i2c_driver as5011_driver = {
.driver = {
.name = "as5011",
},
- .probe = as5011_probe,
+ .probe_new = as5011_probe,
.remove = as5011_remove,
.id_table = as5011_id,
};
diff --git a/drivers/input/joystick/psxpad-spi.c b/drivers/input/joystick/psxpad-spi.c
index a32656064f39..de734a927b4d 100644
--- a/drivers/input/joystick/psxpad-spi.c
+++ b/drivers/input/joystick/psxpad-spi.c
@@ -44,6 +44,8 @@ static const u8 PSX_CMD_POLL[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
+
+#ifdef CONFIG_JOYSTICK_PSXPAD_SPI_FF
/* 0x01, 0x43, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 */
static const u8 PSX_CMD_ENTER_CFG[] = {
0x80, 0xC2, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00
@@ -56,6 +58,7 @@ static const u8 PSX_CMD_EXIT_CFG[] = {
static const u8 PSX_CMD_ENABLE_MOTOR[] = {
0x80, 0xB2, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF
};
+#endif /* CONFIG_JOYSTICK_PSXPAD_SPI_FF */
struct psxpad {
struct spi_device *spi;
@@ -371,7 +374,7 @@ static int psxpad_spi_probe(struct spi_device *spi)
return 0;
}
-static int __maybe_unused psxpad_spi_suspend(struct device *dev)
+static int psxpad_spi_suspend(struct device *dev)
{
struct spi_device *spi = to_spi_device(dev);
struct psxpad *pad = spi_get_drvdata(spi);
@@ -381,7 +384,7 @@ static int __maybe_unused psxpad_spi_suspend(struct device *dev)
return 0;
}
-static SIMPLE_DEV_PM_OPS(psxpad_spi_pm, psxpad_spi_suspend, NULL);
+static DEFINE_SIMPLE_DEV_PM_OPS(psxpad_spi_pm, psxpad_spi_suspend, NULL);
static const struct spi_device_id psxpad_spi_id[] = {
{ "psxpad-spi", 0 },
@@ -392,7 +395,7 @@ MODULE_DEVICE_TABLE(spi, psxpad_spi_id);
static struct spi_driver psxpad_spi_driver = {
.driver = {
.name = "psxpad-spi",
- .pm = &psxpad_spi_pm,
+ .pm = pm_sleep_ptr(&psxpad_spi_pm),
},
.id_table = psxpad_spi_id,
.probe = psxpad_spi_probe,
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index 00292118b79b..84490915ae4d 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -390,7 +390,7 @@ config KEYBOARD_LOCOMO
config KEYBOARD_LPC32XX
tristate "LPC32XX matrix key scanner support"
- depends on ARCH_LPC32XX && OF
+ depends on (ARCH_LPC32XX && OF) || COMPILE_TEST
select INPUT_MATRIXKMAP
help
Say Y here if you want to use NXP LPC32XX SoC key scanner interface,
@@ -487,7 +487,7 @@ config KEYBOARD_NEWTON
config KEYBOARD_NOMADIK
tristate "ST-Ericsson Nomadik SKE keyboard"
- depends on (ARCH_NOMADIK || ARCH_U8500)
+ depends on (ARCH_NOMADIK || ARCH_U8500 || COMPILE_TEST)
select INPUT_MATRIXKMAP
help
Say Y here if you want to use a keypad provided on the SKE controller
@@ -508,7 +508,7 @@ config KEYBOARD_NSPIRE
config KEYBOARD_TEGRA
tristate "NVIDIA Tegra internal matrix keyboard controller support"
- depends on ARCH_TEGRA && OF
+ depends on (ARCH_TEGRA && OF) || COMPILE_TEST
select INPUT_MATRIXKMAP
help
Say Y here if you want to use a matrix keyboard connected directly
@@ -542,7 +542,7 @@ config KEYBOARD_PINEPHONE
config KEYBOARD_PXA27x
tristate "PXA27x/PXA3xx keypad support"
- depends on PXA27x || PXA3xx || ARCH_MMP
+ depends on PXA27x || PXA3xx || ARCH_MMP || COMPILE_TEST
select INPUT_MATRIXKMAP
help
Enable support for PXA27x/PXA3xx keypad controller.
@@ -709,7 +709,7 @@ config KEYBOARD_OMAP4
config KEYBOARD_SPEAR
tristate "ST SPEAR keyboard support"
- depends on PLAT_SPEAR
+ depends on PLAT_SPEAR || COMPILE_TEST
select INPUT_MATRIXKMAP
help
Say Y here if you want to use the SPEAR keyboard.
diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c
index 7cd83c8e7110..72ae5ce72956 100644
--- a/drivers/input/keyboard/adp5588-keys.c
+++ b/drivers/input/keyboard/adp5588-keys.c
@@ -718,8 +718,7 @@ static void adp5588_disable_regulator(void *reg)
regulator_disable(reg);
}
-static int adp5588_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int adp5588_probe(struct i2c_client *client)
{
struct adp5588_kpad *kpad;
struct input_dev *input;
@@ -867,7 +866,7 @@ static struct i2c_driver adp5588_driver = {
.of_match_table = adp5588_of_match,
.pm = pm_sleep_ptr(&adp5588_dev_pm_ops),
},
- .probe = adp5588_probe,
+ .probe_new = adp5588_probe,
.remove = adp5588_remove,
.id_table = adp5588_id,
};
diff --git a/drivers/input/keyboard/adp5589-keys.c b/drivers/input/keyboard/adp5589-keys.c
index bdd264459a97..38d7073863a8 100644
--- a/drivers/input/keyboard/adp5589-keys.c
+++ b/drivers/input/keyboard/adp5589-keys.c
@@ -942,9 +942,9 @@ static void adp5589_clear_config(void *data)
adp5589_write(client, kpad->var->reg(ADP5589_GENERAL_CFG), 0);
}
-static int adp5589_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int adp5589_probe(struct i2c_client *client)
{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct adp5589_kpad *kpad;
const struct adp5589_kpad_platform_data *pdata =
dev_get_platdata(&client->dev);
@@ -1016,7 +1016,7 @@ static int adp5589_probe(struct i2c_client *client,
return 0;
}
-static int __maybe_unused adp5589_suspend(struct device *dev)
+static int adp5589_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct adp5589_kpad *kpad = i2c_get_clientdata(client);
@@ -1027,7 +1027,7 @@ static int __maybe_unused adp5589_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused adp5589_resume(struct device *dev)
+static int adp5589_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct adp5589_kpad *kpad = i2c_get_clientdata(client);
@@ -1038,7 +1038,7 @@ static int __maybe_unused adp5589_resume(struct device *dev)
return 0;
}
-static SIMPLE_DEV_PM_OPS(adp5589_dev_pm_ops, adp5589_suspend, adp5589_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(adp5589_dev_pm_ops, adp5589_suspend, adp5589_resume);
static const struct i2c_device_id adp5589_id[] = {
{"adp5589-keys", ADP5589},
@@ -1052,9 +1052,9 @@ MODULE_DEVICE_TABLE(i2c, adp5589_id);
static struct i2c_driver adp5589_driver = {
.driver = {
.name = KBUILD_MODNAME,
- .pm = &adp5589_dev_pm_ops,
+ .pm = pm_sleep_ptr(&adp5589_dev_pm_ops),
},
- .probe = adp5589_probe,
+ .probe_new = adp5589_probe,
.id_table = adp5589_id,
};
diff --git a/drivers/input/keyboard/cap11xx.c b/drivers/input/keyboard/cap11xx.c
index 7c85343cd32f..79afd0386e3f 100644
--- a/drivers/input/keyboard/cap11xx.c
+++ b/drivers/input/keyboard/cap11xx.c
@@ -321,9 +321,9 @@ static int cap11xx_init_leds(struct device *dev,
}
#endif
-static int cap11xx_i2c_probe(struct i2c_client *i2c_client,
- const struct i2c_device_id *id)
+static int cap11xx_i2c_probe(struct i2c_client *i2c_client)
{
+ const struct i2c_device_id *id = i2c_client_get_device_id(i2c_client);
struct device *dev = &i2c_client->dev;
struct cap11xx_priv *priv;
struct device_node *node;
@@ -503,7 +503,7 @@ static struct i2c_driver cap11xx_i2c_driver = {
.of_match_table = cap11xx_dt_ids,
},
.id_table = cap11xx_i2c_ids,
- .probe = cap11xx_i2c_probe,
+ .probe_new = cap11xx_i2c_probe,
};
module_i2c_driver(cap11xx_i2c_driver);
diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c
index c14136b733a9..6f435125ec03 100644
--- a/drivers/input/keyboard/cros_ec_keyb.c
+++ b/drivers/input/keyboard/cros_ec_keyb.c
@@ -415,7 +415,7 @@ static int cros_ec_keyb_query_switches(struct cros_ec_keyb *ckdev)
*
* Returns 0 if no error or -error upon error.
*/
-static __maybe_unused int cros_ec_keyb_resume(struct device *dev)
+static int cros_ec_keyb_resume(struct device *dev)
{
struct cros_ec_keyb *ckdev = dev_get_drvdata(dev);
@@ -760,7 +760,7 @@ static const struct of_device_id cros_ec_keyb_of_match[] = {
MODULE_DEVICE_TABLE(of, cros_ec_keyb_of_match);
#endif
-static SIMPLE_DEV_PM_OPS(cros_ec_keyb_pm_ops, NULL, cros_ec_keyb_resume);
+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,
@@ -769,7 +769,7 @@ static struct platform_driver cros_ec_keyb_driver = {
.name = "cros-ec-keyb",
.of_match_table = of_match_ptr(cros_ec_keyb_of_match),
.acpi_match_table = ACPI_PTR(cros_ec_keyb_acpi_match),
- .pm = &cros_ec_keyb_pm_ops,
+ .pm = pm_sleep_ptr(&cros_ec_keyb_pm_ops),
},
};
diff --git a/drivers/input/keyboard/cypress-sf.c b/drivers/input/keyboard/cypress-sf.c
index 9a23eed6a4f4..686388f40317 100644
--- a/drivers/input/keyboard/cypress-sf.c
+++ b/drivers/input/keyboard/cypress-sf.c
@@ -168,7 +168,7 @@ static int cypress_sf_probe(struct i2c_client *client)
return 0;
};
-static int __maybe_unused cypress_sf_suspend(struct device *dev)
+static int cypress_sf_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct cypress_sf_data *touchkey = i2c_get_clientdata(client);
@@ -187,7 +187,7 @@ static int __maybe_unused cypress_sf_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused cypress_sf_resume(struct device *dev)
+static int cypress_sf_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct cypress_sf_data *touchkey = i2c_get_clientdata(client);
@@ -205,8 +205,8 @@ static int __maybe_unused cypress_sf_resume(struct device *dev)
return 0;
}
-static SIMPLE_DEV_PM_OPS(cypress_sf_pm_ops,
- cypress_sf_suspend, cypress_sf_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(cypress_sf_pm_ops,
+ cypress_sf_suspend, cypress_sf_resume);
static struct i2c_device_id cypress_sf_id_table[] = {
{ CYPRESS_SF_DEV_NAME, 0 },
@@ -225,7 +225,7 @@ MODULE_DEVICE_TABLE(of, cypress_sf_of_match);
static struct i2c_driver cypress_sf_driver = {
.driver = {
.name = CYPRESS_SF_DEV_NAME,
- .pm = &cypress_sf_pm_ops,
+ .pm = pm_sleep_ptr(&cypress_sf_pm_ops),
.of_match_table = of_match_ptr(cypress_sf_of_match),
},
.id_table = cypress_sf_id_table,
diff --git a/drivers/input/keyboard/dlink-dir685-touchkeys.c b/drivers/input/keyboard/dlink-dir685-touchkeys.c
index a69dcc3bd30c..ddba2bc861da 100644
--- a/drivers/input/keyboard/dlink-dir685-touchkeys.c
+++ b/drivers/input/keyboard/dlink-dir685-touchkeys.c
@@ -59,12 +59,11 @@ static irqreturn_t dir685_tk_irq_thread(int irq, void *data)
return IRQ_HANDLED;
}
-static int dir685_tk_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int dir685_tk_probe(struct i2c_client *client)
{
- struct dir685_touchkeys *tk;
+ static const u8 bl_data[] = { 0xa7, 0x40 };
struct device *dev = &client->dev;
- u8 bl_data[] = { 0xa7, 0x40 };
+ struct dir685_touchkeys *tk;
int err;
int i;
@@ -146,7 +145,7 @@ static struct i2c_driver dir685_tk_i2c_driver = {
.name = "dlink-dir685-touchkeys",
.of_match_table = of_match_ptr(dir685_tk_of_match),
},
- .probe = dir685_tk_probe,
+ .probe_new = dir685_tk_probe,
.id_table = dir685_tk_id,
};
module_i2c_driver(dir685_tk_i2c_driver);
diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c
index f5bf7524722a..55075addcac2 100644
--- a/drivers/input/keyboard/ep93xx_keypad.c
+++ b/drivers/input/keyboard/ep93xx_keypad.c
@@ -178,7 +178,7 @@ static void ep93xx_keypad_close(struct input_dev *pdev)
}
-static int __maybe_unused ep93xx_keypad_suspend(struct device *dev)
+static int ep93xx_keypad_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
@@ -196,7 +196,7 @@ static int __maybe_unused ep93xx_keypad_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused ep93xx_keypad_resume(struct device *dev)
+static int ep93xx_keypad_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct ep93xx_keypad *keypad = platform_get_drvdata(pdev);
@@ -217,8 +217,8 @@ static int __maybe_unused ep93xx_keypad_resume(struct device *dev)
return 0;
}
-static SIMPLE_DEV_PM_OPS(ep93xx_keypad_pm_ops,
- ep93xx_keypad_suspend, ep93xx_keypad_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(ep93xx_keypad_pm_ops,
+ ep93xx_keypad_suspend, ep93xx_keypad_resume);
static void ep93xx_keypad_release_gpio_action(void *_pdev)
{
@@ -318,7 +318,7 @@ static int ep93xx_keypad_remove(struct platform_device *pdev)
static struct platform_driver ep93xx_keypad_driver = {
.driver = {
.name = "ep93xx-keypad",
- .pm = &ep93xx_keypad_pm_ops,
+ .pm = pm_sleep_ptr(&ep93xx_keypad_pm_ops),
},
.probe = ep93xx_keypad_probe,
.remove = ep93xx_keypad_remove,
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index a5dc4ab87fa1..5496482a38c1 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -992,7 +992,7 @@ gpio_keys_disable_wakeup(struct gpio_keys_drvdata *ddata)
}
}
-static int __maybe_unused gpio_keys_suspend(struct device *dev)
+static int gpio_keys_suspend(struct device *dev)
{
struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
struct input_dev *input = ddata->input;
@@ -1012,7 +1012,7 @@ static int __maybe_unused gpio_keys_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused gpio_keys_resume(struct device *dev)
+static int gpio_keys_resume(struct device *dev)
{
struct gpio_keys_drvdata *ddata = dev_get_drvdata(dev);
struct input_dev *input = ddata->input;
@@ -1034,7 +1034,7 @@ static int __maybe_unused gpio_keys_resume(struct device *dev)
return 0;
}
-static SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(gpio_keys_pm_ops, gpio_keys_suspend, gpio_keys_resume);
static void gpio_keys_shutdown(struct platform_device *pdev)
{
@@ -1050,7 +1050,7 @@ static struct platform_driver gpio_keys_device_driver = {
.shutdown = gpio_keys_shutdown,
.driver = {
.name = "gpio-keys",
- .pm = &gpio_keys_pm_ops,
+ .pm = pm_sleep_ptr(&gpio_keys_pm_ops),
.of_match_table = gpio_keys_of_match,
.dev_groups = gpio_keys_groups,
}
diff --git a/drivers/input/keyboard/ipaq-micro-keys.c b/drivers/input/keyboard/ipaq-micro-keys.c
index 13a66a8e3411..7b509bce2b33 100644
--- a/drivers/input/keyboard/ipaq-micro-keys.c
+++ b/drivers/input/keyboard/ipaq-micro-keys.c
@@ -124,7 +124,7 @@ static int micro_key_probe(struct platform_device *pdev)
return 0;
}
-static int __maybe_unused micro_key_suspend(struct device *dev)
+static int micro_key_suspend(struct device *dev)
{
struct ipaq_micro_keys *keys = dev_get_drvdata(dev);
@@ -133,7 +133,7 @@ static int __maybe_unused micro_key_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused micro_key_resume(struct device *dev)
+static int micro_key_resume(struct device *dev)
{
struct ipaq_micro_keys *keys = dev_get_drvdata(dev);
struct input_dev *input = keys->input;
@@ -148,13 +148,13 @@ static int __maybe_unused micro_key_resume(struct device *dev)
return 0;
}
-static SIMPLE_DEV_PM_OPS(micro_key_dev_pm_ops,
- micro_key_suspend, micro_key_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(micro_key_dev_pm_ops,
+ micro_key_suspend, micro_key_resume);
static struct platform_driver micro_key_device_driver = {
.driver = {
.name = "ipaq-micro-keys",
- .pm = &micro_key_dev_pm_ops,
+ .pm = pm_sleep_ptr(&micro_key_dev_pm_ops),
},
.probe = micro_key_probe,
};
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c
index 407dd2ad6302..5df4d5a7ed9e 100644
--- a/drivers/input/keyboard/lm8323.c
+++ b/drivers/input/keyboard/lm8323.c
@@ -615,8 +615,7 @@ static ssize_t lm8323_set_disable(struct device *dev,
}
static DEVICE_ATTR(disable_kp, 0644, lm8323_show_disable, lm8323_set_disable);
-static int lm8323_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int lm8323_probe(struct i2c_client *client)
{
struct lm8323_platform_data *pdata = dev_get_platdata(&client->dev);
struct input_dev *idev;
@@ -771,7 +770,6 @@ static void lm8323_remove(struct i2c_client *client)
kfree(lm);
}
-#ifdef CONFIG_PM_SLEEP
/*
* We don't need to explicitly suspend the chip, as it already switches off
* when there's no activity.
@@ -815,9 +813,8 @@ static int lm8323_resume(struct device *dev)
return 0;
}
-#endif
-static SIMPLE_DEV_PM_OPS(lm8323_pm_ops, lm8323_suspend, lm8323_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(lm8323_pm_ops, lm8323_suspend, lm8323_resume);
static const struct i2c_device_id lm8323_id[] = {
{ "lm8323", 0 },
@@ -827,9 +824,9 @@ static const struct i2c_device_id lm8323_id[] = {
static struct i2c_driver lm8323_i2c_driver = {
.driver = {
.name = "lm8323",
- .pm = &lm8323_pm_ops,
+ .pm = pm_sleep_ptr(&lm8323_pm_ops),
},
- .probe = lm8323_probe,
+ .probe_new = lm8323_probe,
.remove = lm8323_remove,
.id_table = lm8323_id,
};
diff --git a/drivers/input/keyboard/lm8333.c b/drivers/input/keyboard/lm8333.c
index 3052cd6dedac..7457c3220f90 100644
--- a/drivers/input/keyboard/lm8333.c
+++ b/drivers/input/keyboard/lm8333.c
@@ -125,8 +125,7 @@ static irqreturn_t lm8333_irq_thread(int irq, void *data)
return IRQ_HANDLED;
}
-static int lm8333_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int lm8333_probe(struct i2c_client *client)
{
const struct lm8333_platform_data *pdata =
dev_get_platdata(&client->dev);
@@ -219,7 +218,7 @@ static struct i2c_driver lm8333_driver = {
.driver = {
.name = "lm8333",
},
- .probe = lm8333_probe,
+ .probe_new = lm8333_probe,
.remove = lm8333_remove,
.id_table = lm8333_id,
};
diff --git a/drivers/input/keyboard/lpc32xx-keys.c b/drivers/input/keyboard/lpc32xx-keys.c
index 943aeeb0de79..911e1181cd6f 100644
--- a/drivers/input/keyboard/lpc32xx-keys.c
+++ b/drivers/input/keyboard/lpc32xx-keys.c
@@ -264,7 +264,6 @@ static int lpc32xx_kscan_probe(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM_SLEEP
static int lpc32xx_kscan_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -302,10 +301,9 @@ static int lpc32xx_kscan_resume(struct device *dev)
mutex_unlock(&input->mutex);
return retval;
}
-#endif
-static SIMPLE_DEV_PM_OPS(lpc32xx_kscan_pm_ops, lpc32xx_kscan_suspend,
- lpc32xx_kscan_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(lpc32xx_kscan_pm_ops, lpc32xx_kscan_suspend,
+ lpc32xx_kscan_resume);
static const struct of_device_id lpc32xx_kscan_match[] = {
{ .compatible = "nxp,lpc3220-key" },
@@ -317,7 +315,7 @@ static struct platform_driver lpc32xx_kscan_driver = {
.probe = lpc32xx_kscan_probe,
.driver = {
.name = DRV_NAME,
- .pm = &lpc32xx_kscan_pm_ops,
+ .pm = pm_sleep_ptr(&lpc32xx_kscan_pm_ops),
.of_match_table = lpc32xx_kscan_match,
}
};
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
index 7dd3f3eda834..203310727d88 100644
--- a/drivers/input/keyboard/matrix_keypad.c
+++ b/drivers/input/keyboard/matrix_keypad.c
@@ -127,6 +127,9 @@ static void matrix_keypad_scan(struct work_struct *work)
memset(new_state, 0, sizeof(new_state));
+ for (row = 0; row < pdata->num_row_gpios; row++)
+ gpio_direction_input(pdata->row_gpios[row]);
+
/* assert each column and read the row status out */
for (col = 0; col < pdata->num_col_gpios; col++) {
@@ -227,7 +230,6 @@ static void matrix_keypad_stop(struct input_dev *dev)
disable_row_irqs(keypad);
}
-#ifdef CONFIG_PM_SLEEP
static void matrix_keypad_enable_wakeup(struct matrix_keypad *keypad)
{
const struct matrix_keypad_platform_data *pdata = keypad->pdata;
@@ -296,10 +298,9 @@ static int matrix_keypad_resume(struct device *dev)
return 0;
}
-#endif
-static SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops,
- matrix_keypad_suspend, matrix_keypad_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(matrix_keypad_pm_ops,
+ matrix_keypad_suspend, matrix_keypad_resume);
static int matrix_keypad_init_gpio(struct platform_device *pdev,
struct matrix_keypad *keypad)
@@ -574,7 +575,7 @@ static struct platform_driver matrix_keypad_driver = {
.remove = matrix_keypad_remove,
.driver = {
.name = "matrix-keypad",
- .pm = &matrix_keypad_pm_ops,
+ .pm = pm_sleep_ptr(&matrix_keypad_pm_ops),
.of_match_table = of_match_ptr(matrix_keypad_dt_match),
},
};
diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c
index 62ce93462955..b363749d02e2 100644
--- a/drivers/input/keyboard/max7359_keypad.c
+++ b/drivers/input/keyboard/max7359_keypad.c
@@ -155,8 +155,7 @@ static void max7359_initialize(struct i2c_client *client)
max7359_fall_deepsleep(client);
}
-static int max7359_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int max7359_probe(struct i2c_client *client)
{
const struct matrix_keymap_data *keymap_data =
dev_get_platdata(&client->dev);
@@ -243,7 +242,6 @@ static int max7359_probe(struct i2c_client *client,
return 0;
}
-#ifdef CONFIG_PM_SLEEP
static int max7359_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -268,9 +266,8 @@ static int max7359_resume(struct device *dev)
return 0;
}
-#endif
-static SIMPLE_DEV_PM_OPS(max7359_pm, max7359_suspend, max7359_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(max7359_pm, max7359_suspend, max7359_resume);
static const struct i2c_device_id max7359_ids[] = {
{ "max7359", 0 },
@@ -281,9 +278,9 @@ MODULE_DEVICE_TABLE(i2c, max7359_ids);
static struct i2c_driver max7359_i2c_driver = {
.driver = {
.name = "max7359",
- .pm = &max7359_pm,
+ .pm = pm_sleep_ptr(&max7359_pm),
},
- .probe = max7359_probe,
+ .probe_new = max7359_probe,
.id_table = max7359_ids,
};
diff --git a/drivers/input/keyboard/mcs_touchkey.c b/drivers/input/keyboard/mcs_touchkey.c
index ac1637a3389e..d414e19e4559 100644
--- a/drivers/input/keyboard/mcs_touchkey.c
+++ b/drivers/input/keyboard/mcs_touchkey.c
@@ -92,9 +92,9 @@ static irqreturn_t mcs_touchkey_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int mcs_touchkey_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int mcs_touchkey_probe(struct i2c_client *client)
{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
const struct mcs_platform_data *pdata;
struct mcs_touchkey_data *data;
struct input_dev *input_dev;
@@ -213,7 +213,6 @@ static void mcs_touchkey_shutdown(struct i2c_client *client)
data->poweron(false);
}
-#ifdef CONFIG_PM_SLEEP
static int mcs_touchkey_suspend(struct device *dev)
{
struct mcs_touchkey_data *data = dev_get_drvdata(dev);
@@ -243,10 +242,9 @@ static int mcs_touchkey_resume(struct device *dev)
return 0;
}
-#endif
-static SIMPLE_DEV_PM_OPS(mcs_touchkey_pm_ops,
- mcs_touchkey_suspend, mcs_touchkey_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(mcs_touchkey_pm_ops,
+ mcs_touchkey_suspend, mcs_touchkey_resume);
static const struct i2c_device_id mcs_touchkey_id[] = {
{ "mcs5000_touchkey", MCS5000_TOUCHKEY },
@@ -258,9 +256,9 @@ MODULE_DEVICE_TABLE(i2c, mcs_touchkey_id);
static struct i2c_driver mcs_touchkey_driver = {
.driver = {
.name = "mcs_touchkey",
- .pm = &mcs_touchkey_pm_ops,
+ .pm = pm_sleep_ptr(&mcs_touchkey_pm_ops),
},
- .probe = mcs_touchkey_probe,
+ .probe_new = mcs_touchkey_probe,
.remove = mcs_touchkey_remove,
.shutdown = mcs_touchkey_shutdown,
.id_table = mcs_touchkey_id,
diff --git a/drivers/input/keyboard/mpr121_touchkey.c b/drivers/input/keyboard/mpr121_touchkey.c
index 230ab3d50b9e..74ad353462a3 100644
--- a/drivers/input/keyboard/mpr121_touchkey.c
+++ b/drivers/input/keyboard/mpr121_touchkey.c
@@ -230,8 +230,7 @@ err_i2c_write:
return ret;
}
-static int mpr_touchkey_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int mpr_touchkey_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct regulator *vdd_supply;
@@ -341,7 +340,7 @@ static int mpr_touchkey_probe(struct i2c_client *client,
return 0;
}
-static int __maybe_unused mpr_suspend(struct device *dev)
+static int mpr_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -353,7 +352,7 @@ static int __maybe_unused mpr_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused mpr_resume(struct device *dev)
+static int mpr_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct mpr121_touchkey *mpr121 = i2c_get_clientdata(client);
@@ -367,7 +366,7 @@ static int __maybe_unused mpr_resume(struct device *dev)
return 0;
}
-static SIMPLE_DEV_PM_OPS(mpr121_touchkey_pm_ops, mpr_suspend, mpr_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(mpr121_touchkey_pm_ops, mpr_suspend, mpr_resume);
static const struct i2c_device_id mpr121_id[] = {
{ "mpr121_touchkey", 0 },
@@ -386,11 +385,11 @@ MODULE_DEVICE_TABLE(of, mpr121_touchkey_dt_match_table);
static struct i2c_driver mpr_touchkey_driver = {
.driver = {
.name = "mpr121",
- .pm = &mpr121_touchkey_pm_ops,
+ .pm = pm_sleep_ptr(&mpr121_touchkey_pm_ops),
.of_match_table = of_match_ptr(mpr121_touchkey_dt_match_table),
},
.id_table = mpr121_id,
- .probe = mpr_touchkey_probe,
+ .probe_new = mpr_touchkey_probe,
};
module_i2c_driver(mpr_touchkey_driver);
diff --git a/drivers/input/keyboard/mtk-pmic-keys.c b/drivers/input/keyboard/mtk-pmic-keys.c
index 9b34da0ec260..3d4ffa25e3df 100644
--- a/drivers/input/keyboard/mtk-pmic-keys.c
+++ b/drivers/input/keyboard/mtk-pmic-keys.c
@@ -231,7 +231,7 @@ static int mtk_pmic_key_setup(struct mtk_pmic_keys *keys,
return 0;
}
-static int __maybe_unused mtk_pmic_keys_suspend(struct device *dev)
+static int mtk_pmic_keys_suspend(struct device *dev)
{
struct mtk_pmic_keys *keys = dev_get_drvdata(dev);
int index;
@@ -247,7 +247,7 @@ static int __maybe_unused mtk_pmic_keys_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused mtk_pmic_keys_resume(struct device *dev)
+static int mtk_pmic_keys_resume(struct device *dev)
{
struct mtk_pmic_keys *keys = dev_get_drvdata(dev);
int index;
@@ -263,8 +263,8 @@ static int __maybe_unused mtk_pmic_keys_resume(struct device *dev)
return 0;
}
-static SIMPLE_DEV_PM_OPS(mtk_pmic_keys_pm_ops, mtk_pmic_keys_suspend,
- mtk_pmic_keys_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(mtk_pmic_keys_pm_ops, mtk_pmic_keys_suspend,
+ mtk_pmic_keys_resume);
static const struct of_device_id of_mtk_pmic_keys_match_tbl[] = {
{
@@ -387,7 +387,7 @@ static struct platform_driver pmic_keys_pdrv = {
.driver = {
.name = "mtk-pmic-keys",
.of_match_table = of_mtk_pmic_keys_match_tbl,
- .pm = &mtk_pmic_keys_pm_ops,
+ .pm = pm_sleep_ptr(&mtk_pmic_keys_pm_ops),
},
};
diff --git a/drivers/input/keyboard/nomadik-ske-keypad.c b/drivers/input/keyboard/nomadik-ske-keypad.c
index 0d55a95347f1..970f2a671c2e 100644
--- a/drivers/input/keyboard/nomadik-ske-keypad.c
+++ b/drivers/input/keyboard/nomadik-ske-keypad.c
@@ -388,7 +388,6 @@ static int ske_keypad_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM_SLEEP
static int ske_keypad_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -416,15 +415,14 @@ static int ske_keypad_resume(struct device *dev)
return 0;
}
-#endif
-static SIMPLE_DEV_PM_OPS(ske_keypad_dev_pm_ops,
- ske_keypad_suspend, ske_keypad_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(ske_keypad_dev_pm_ops,
+ ske_keypad_suspend, ske_keypad_resume);
static struct platform_driver ske_keypad_driver = {
.driver = {
.name = "nmk-ske-keypad",
- .pm = &ske_keypad_dev_pm_ops,
+ .pm = pm_sleep_ptr(&ske_keypad_dev_pm_ops),
},
.remove = ske_keypad_remove,
};
diff --git a/drivers/input/keyboard/pmic8xxx-keypad.c b/drivers/input/keyboard/pmic8xxx-keypad.c
index 4766c5048ce2..26a005f9ace3 100644
--- a/drivers/input/keyboard/pmic8xxx-keypad.c
+++ b/drivers/input/keyboard/pmic8xxx-keypad.c
@@ -621,7 +621,6 @@ static int pmic8xxx_kp_probe(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM_SLEEP
static int pmic8xxx_kp_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -661,10 +660,9 @@ static int pmic8xxx_kp_resume(struct device *dev)
return 0;
}
-#endif
-static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops,
- pmic8xxx_kp_suspend, pmic8xxx_kp_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops,
+ pmic8xxx_kp_suspend, pmic8xxx_kp_resume);
static const struct of_device_id pm8xxx_match_table[] = {
{ .compatible = "qcom,pm8058-keypad" },
@@ -677,7 +675,7 @@ static struct platform_driver pmic8xxx_kp_driver = {
.probe = pmic8xxx_kp_probe,
.driver = {
.name = "pm8xxx-keypad",
- .pm = &pm8xxx_kp_pm_ops,
+ .pm = pm_sleep_ptr(&pm8xxx_kp_pm_ops),
.of_match_table = pm8xxx_match_table,
},
};
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index a7f8257c8a02..871f858d0ba7 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -660,7 +660,6 @@ static void pxa27x_keypad_close(struct input_dev *dev)
clk_disable_unprepare(keypad->clk);
}
-#ifdef CONFIG_PM_SLEEP
static int pxa27x_keypad_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -706,10 +705,9 @@ static int pxa27x_keypad_resume(struct device *dev)
return ret;
}
-#endif
-static SIMPLE_DEV_PM_OPS(pxa27x_keypad_pm_ops,
- pxa27x_keypad_suspend, pxa27x_keypad_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(pxa27x_keypad_pm_ops,
+ pxa27x_keypad_suspend, pxa27x_keypad_resume);
static int pxa27x_keypad_probe(struct platform_device *pdev)
@@ -830,7 +828,7 @@ static struct platform_driver pxa27x_keypad_driver = {
.driver = {
.name = "pxa27x-keypad",
.of_match_table = of_match_ptr(pxa27x_keypad_dt_match),
- .pm = &pxa27x_keypad_pm_ops,
+ .pm = pm_sleep_ptr(&pxa27x_keypad_pm_ops),
},
};
module_platform_driver(pxa27x_keypad_driver);
diff --git a/drivers/input/keyboard/qt1050.c b/drivers/input/keyboard/qt1050.c
index 403060d05c3b..317fe2b1f827 100644
--- a/drivers/input/keyboard/qt1050.c
+++ b/drivers/input/keyboard/qt1050.c
@@ -547,7 +547,7 @@ static int qt1050_probe(struct i2c_client *client)
return 0;
}
-static int __maybe_unused qt1050_suspend(struct device *dev)
+static int qt1050_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct qt1050_priv *ts = i2c_get_clientdata(client);
@@ -563,7 +563,7 @@ static int __maybe_unused qt1050_suspend(struct device *dev)
device_may_wakeup(dev) ? 125 : 0);
}
-static int __maybe_unused qt1050_resume(struct device *dev)
+static int qt1050_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct qt1050_priv *ts = i2c_get_clientdata(client);
@@ -574,7 +574,7 @@ static int __maybe_unused qt1050_resume(struct device *dev)
return regmap_write(ts->regmap, QT1050_LPMODE, 2);
}
-static SIMPLE_DEV_PM_OPS(qt1050_pm_ops, qt1050_suspend, qt1050_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(qt1050_pm_ops, qt1050_suspend, qt1050_resume);
static const struct of_device_id __maybe_unused qt1050_of_match[] = {
{ .compatible = "microchip,qt1050", },
@@ -586,7 +586,7 @@ static struct i2c_driver qt1050_driver = {
.driver = {
.name = "qt1050",
.of_match_table = of_match_ptr(qt1050_of_match),
- .pm = &qt1050_pm_ops,
+ .pm = pm_sleep_ptr(&qt1050_pm_ops),
},
.probe_new = qt1050_probe,
};
diff --git a/drivers/input/keyboard/qt1070.c b/drivers/input/keyboard/qt1070.c
index 9fcce18b1d65..fabb50bde844 100644
--- a/drivers/input/keyboard/qt1070.c
+++ b/drivers/input/keyboard/qt1070.c
@@ -126,8 +126,7 @@ static irqreturn_t qt1070_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int qt1070_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int qt1070_probe(struct i2c_client *client)
{
struct qt1070_data *data;
struct input_dev *input;
@@ -227,7 +226,6 @@ static void qt1070_remove(struct i2c_client *client)
kfree(data);
}
-#ifdef CONFIG_PM_SLEEP
static int qt1070_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -249,9 +247,8 @@ static int qt1070_resume(struct device *dev)
return 0;
}
-#endif
-static SIMPLE_DEV_PM_OPS(qt1070_pm_ops, qt1070_suspend, qt1070_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(qt1070_pm_ops, qt1070_suspend, qt1070_resume);
static const struct i2c_device_id qt1070_id[] = {
{ "qt1070", 0 },
@@ -271,10 +268,10 @@ static struct i2c_driver qt1070_driver = {
.driver = {
.name = "qt1070",
.of_match_table = of_match_ptr(qt1070_of_match),
- .pm = &qt1070_pm_ops,
+ .pm = pm_sleep_ptr(&qt1070_pm_ops),
},
.id_table = qt1070_id,
- .probe = qt1070_probe,
+ .probe_new = qt1070_probe,
.remove = qt1070_remove,
};
diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c
index 382b1519218c..04d2ee6ff577 100644
--- a/drivers/input/keyboard/qt2160.c
+++ b/drivers/input/keyboard/qt2160.c
@@ -338,8 +338,7 @@ static bool qt2160_identify(struct i2c_client *client)
return true;
}
-static int qt2160_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int qt2160_probe(struct i2c_client *client)
{
struct qt2160_data *qt2160;
struct input_dev *input;
@@ -461,7 +460,7 @@ static struct i2c_driver qt2160_driver = {
},
.id_table = qt2160_idtable,
- .probe = qt2160_probe,
+ .probe_new = qt2160_probe,
.remove = qt2160_remove,
};
diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c
index c155adebf96e..2c00320f739f 100644
--- a/drivers/input/keyboard/sh_keysc.c
+++ b/drivers/input/keyboard/sh_keysc.c
@@ -283,7 +283,6 @@ static int sh_keysc_remove(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM_SLEEP
static int sh_keysc_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -316,17 +315,16 @@ static int sh_keysc_resume(struct device *dev)
return 0;
}
-#endif
-static SIMPLE_DEV_PM_OPS(sh_keysc_dev_pm_ops,
- sh_keysc_suspend, sh_keysc_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(sh_keysc_dev_pm_ops,
+ sh_keysc_suspend, sh_keysc_resume);
static struct platform_driver sh_keysc_device_driver = {
.probe = sh_keysc_probe,
.remove = sh_keysc_remove,
.driver = {
.name = "sh_keysc",
- .pm = &sh_keysc_dev_pm_ops,
+ .pm = pm_sleep_ptr(&sh_keysc_dev_pm_ops),
}
};
module_platform_driver(sh_keysc_device_driver);
diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c
index 9838c79cb288..4bb7c533147c 100644
--- a/drivers/input/keyboard/spear-keyboard.c
+++ b/drivers/input/keyboard/spear-keyboard.c
@@ -284,7 +284,7 @@ static int spear_kbd_remove(struct platform_device *pdev)
return 0;
}
-static int __maybe_unused spear_kbd_suspend(struct device *dev)
+static int spear_kbd_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct spear_kbd *kbd = platform_get_drvdata(pdev);
@@ -337,7 +337,7 @@ static int __maybe_unused spear_kbd_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused spear_kbd_resume(struct device *dev)
+static int spear_kbd_resume(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct spear_kbd *kbd = platform_get_drvdata(pdev);
@@ -364,7 +364,8 @@ static int __maybe_unused spear_kbd_resume(struct device *dev)
return 0;
}
-static SIMPLE_DEV_PM_OPS(spear_kbd_pm_ops, spear_kbd_suspend, spear_kbd_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(spear_kbd_pm_ops,
+ spear_kbd_suspend, spear_kbd_resume);
#ifdef CONFIG_OF
static const struct of_device_id spear_kbd_id_table[] = {
@@ -379,7 +380,7 @@ static struct platform_driver spear_kbd_driver = {
.remove = spear_kbd_remove,
.driver = {
.name = "keyboard",
- .pm = &spear_kbd_pm_ops,
+ .pm = pm_sleep_ptr(&spear_kbd_pm_ops),
.of_match_table = of_match_ptr(spear_kbd_id_table),
},
};
diff --git a/drivers/input/keyboard/st-keyscan.c b/drivers/input/keyboard/st-keyscan.c
index a62bb8fff88c..13735a5e8391 100644
--- a/drivers/input/keyboard/st-keyscan.c
+++ b/drivers/input/keyboard/st-keyscan.c
@@ -212,7 +212,6 @@ static int keyscan_probe(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM_SLEEP
static int keyscan_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -247,9 +246,9 @@ static int keyscan_resume(struct device *dev)
mutex_unlock(&input->mutex);
return retval;
}
-#endif
-static SIMPLE_DEV_PM_OPS(keyscan_dev_pm_ops, keyscan_suspend, keyscan_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(keyscan_dev_pm_ops,
+ keyscan_suspend, keyscan_resume);
static const struct of_device_id keyscan_of_match[] = {
{ .compatible = "st,sti-keyscan" },
@@ -261,7 +260,7 @@ static struct platform_driver keyscan_device_driver = {
.probe = keyscan_probe,
.driver = {
.name = "st-keyscan",
- .pm = &keyscan_dev_pm_ops,
+ .pm = pm_sleep_ptr(&keyscan_dev_pm_ops),
.of_match_table = of_match_ptr(keyscan_of_match),
}
};
diff --git a/drivers/input/keyboard/stmpe-keypad.c b/drivers/input/keyboard/stmpe-keypad.c
index 7bf97285e30c..2c6c53290cc0 100644
--- a/drivers/input/keyboard/stmpe-keypad.c
+++ b/drivers/input/keyboard/stmpe-keypad.c
@@ -9,6 +9,7 @@
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/interrupt.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/input/matrix_keypad.h>
#include <linux/mfd/stmpe.h>
diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c
index 78e55318ccd6..b0d86621c60a 100644
--- a/drivers/input/keyboard/tc3589x-keypad.c
+++ b/drivers/input/keyboard/tc3589x-keypad.c
@@ -455,7 +455,6 @@ static int tc3589x_keypad_probe(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM_SLEEP
static int tc3589x_keypad_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -492,15 +491,14 @@ static int tc3589x_keypad_resume(struct device *dev)
return 0;
}
-#endif
-static SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops,
- tc3589x_keypad_suspend, tc3589x_keypad_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops,
+ tc3589x_keypad_suspend, tc3589x_keypad_resume);
static struct platform_driver tc3589x_keypad_driver = {
.driver = {
.name = "tc3589x-keypad",
- .pm = &tc3589x_keypad_dev_pm_ops,
+ .pm = pm_sleep_ptr(&tc3589x_keypad_dev_pm_ops),
},
.probe = tc3589x_keypad_probe,
};
diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c
index afcdfbb002ff..673b905af6fe 100644
--- a/drivers/input/keyboard/tca6416-keypad.c
+++ b/drivers/input/keyboard/tca6416-keypad.c
@@ -194,9 +194,9 @@ static int tca6416_setup_registers(struct tca6416_keypad_chip *chip)
return 0;
}
-static int tca6416_keypad_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int tca6416_keypad_probe(struct i2c_client *client)
{
+ const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct tca6416_keys_platform_data *pdata;
struct tca6416_keypad_chip *chip;
struct input_dev *input;
@@ -320,7 +320,6 @@ static void tca6416_keypad_remove(struct i2c_client *client)
kfree(chip);
}
-#ifdef CONFIG_PM_SLEEP
static int tca6416_keypad_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
@@ -342,17 +341,16 @@ static int tca6416_keypad_resume(struct device *dev)
return 0;
}
-#endif
-static SIMPLE_DEV_PM_OPS(tca6416_keypad_dev_pm_ops,
- tca6416_keypad_suspend, tca6416_keypad_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(tca6416_keypad_dev_pm_ops,
+ tca6416_keypad_suspend, tca6416_keypad_resume);
static struct i2c_driver tca6416_keypad_driver = {
.driver = {
.name = "tca6416-keypad",
- .pm = &tca6416_keypad_dev_pm_ops,
+ .pm = pm_sleep_ptr(&tca6416_keypad_dev_pm_ops),
},
- .probe = tca6416_keypad_probe,
+ .probe_new = tca6416_keypad_probe,
.remove = tca6416_keypad_remove,
.id_table = tca6416_id,
};
diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c
index 3bbd7e652533..3d7492f38337 100644
--- a/drivers/input/keyboard/tca8418_keypad.c
+++ b/drivers/input/keyboard/tca8418_keypad.c
@@ -259,8 +259,7 @@ static int tca8418_configure(struct tca8418_keypad *keypad_data,
return error;
}
-static int tca8418_keypad_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int tca8418_keypad_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct tca8418_keypad *keypad_data;
@@ -371,7 +370,7 @@ static struct i2c_driver tca8418_keypad_driver = {
.name = "tca8418_keypad",
.of_match_table = tca8418_dt_ids,
},
- .probe = tca8418_keypad_probe,
+ .probe_new = tca8418_keypad_probe,
.id_table = tca8418_id,
};
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index 570fe18c0ce9..1eba06bcf27a 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -713,7 +713,6 @@ static int tegra_kbc_probe(struct platform_device *pdev)
return 0;
}
-#ifdef CONFIG_PM_SLEEP
static void tegra_kbc_set_keypress_interrupt(struct tegra_kbc *kbc, bool enable)
{
u32 val;
@@ -802,15 +801,15 @@ static int tegra_kbc_resume(struct device *dev)
return err;
}
-#endif
-static SIMPLE_DEV_PM_OPS(tegra_kbc_pm_ops, tegra_kbc_suspend, tegra_kbc_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(tegra_kbc_pm_ops,
+ tegra_kbc_suspend, tegra_kbc_resume);
static struct platform_driver tegra_kbc_driver = {
.probe = tegra_kbc_probe,
.driver = {
.name = "tegra-kbc",
- .pm = &tegra_kbc_pm_ops,
+ .pm = pm_sleep_ptr(&tegra_kbc_pm_ops),
.of_match_table = tegra_kbc_of_match,
},
};
diff --git a/drivers/input/keyboard/tm2-touchkey.c b/drivers/input/keyboard/tm2-touchkey.c
index 632cd6c1c8d4..6627e65f06e5 100644
--- a/drivers/input/keyboard/tm2-touchkey.c
+++ b/drivers/input/keyboard/tm2-touchkey.c
@@ -181,8 +181,7 @@ out:
return IRQ_HANDLED;
}
-static int tm2_touchkey_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int tm2_touchkey_probe(struct i2c_client *client)
{
struct device_node *np = client->dev.of_node;
struct tm2_touchkey_data *touchkey;
@@ -298,7 +297,7 @@ static int tm2_touchkey_probe(struct i2c_client *client,
return 0;
}
-static int __maybe_unused tm2_touchkey_suspend(struct device *dev)
+static int tm2_touchkey_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct tm2_touchkey_data *touchkey = i2c_get_clientdata(client);
@@ -309,7 +308,7 @@ static int __maybe_unused tm2_touchkey_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused tm2_touchkey_resume(struct device *dev)
+static int tm2_touchkey_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct tm2_touchkey_data *touchkey = i2c_get_clientdata(client);
@@ -324,8 +323,8 @@ static int __maybe_unused tm2_touchkey_resume(struct device *dev)
return ret;
}
-static SIMPLE_DEV_PM_OPS(tm2_touchkey_pm_ops,
- tm2_touchkey_suspend, tm2_touchkey_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(tm2_touchkey_pm_ops,
+ tm2_touchkey_suspend, tm2_touchkey_resume);
static const struct i2c_device_id tm2_touchkey_id_table[] = {
{ TM2_TOUCHKEY_DEV_NAME, 0 },
@@ -354,10 +353,10 @@ MODULE_DEVICE_TABLE(of, tm2_touchkey_of_match);
static struct i2c_driver tm2_touchkey_driver = {
.driver = {
.name = TM2_TOUCHKEY_DEV_NAME,
- .pm = &tm2_touchkey_pm_ops,
+ .pm = pm_sleep_ptr(&tm2_touchkey_pm_ops),
.of_match_table = of_match_ptr(tm2_touchkey_of_match),
},
- .probe = tm2_touchkey_probe,
+ .probe_new = tm2_touchkey_probe,
.id_table = tm2_touchkey_id_table,
};
module_i2c_driver(tm2_touchkey_driver);
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 9f088900f863..f3cf189c419b 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -107,7 +107,7 @@ config INPUT_ATC260X_ONKEY
config INPUT_ATMEL_CAPTOUCH
tristate "Atmel Capacitive Touch Button Driver"
- depends on OF || COMPILE_TEST
+ depends on OF
depends on I2C
help
Say Y here if an Atmel Capacitive Touch Button device which
@@ -330,7 +330,7 @@ config INPUT_CPCAP_PWRBUTTON
config INPUT_WISTRON_BTNS
tristate "x86 Wistron laptop button interface"
- depends on X86_32
+ depends on X86_32 && !UML
select INPUT_SPARSEKMAP
select NEW_LEDS
select LEDS_CLASS
diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c
index efeef135007a..5ef518a50e63 100644
--- a/drivers/input/misc/ad714x-i2c.c
+++ b/drivers/input/misc/ad714x-i2c.c
@@ -69,8 +69,7 @@ static int ad714x_i2c_read(struct ad714x_chip *chip,
return 0;
}
-static int ad714x_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int ad714x_i2c_probe(struct i2c_client *client)
{
struct ad714x_chip *chip;
@@ -99,7 +98,7 @@ static struct i2c_driver ad714x_i2c_driver = {
.name = "ad714x_captouch",
.pm = &ad714x_i2c_pm,
},
- .probe = ad714x_i2c_probe,
+ .probe_new = ad714x_i2c_probe,
.id_table = ad714x_id,
};
diff --git a/drivers/input/misc/adxl34x-i2c.c b/drivers/input/misc/adxl34x-i2c.c
index 5be636aaa94f..a8ceea36d80a 100644
--- a/drivers/input/misc/adxl34x-i2c.c
+++ b/drivers/input/misc/adxl34x-i2c.c
@@ -74,8 +74,7 @@ static const struct adxl34x_bus_ops adxl34x_i2c_bops = {
.read_block = adxl34x_i2c_read_block,
};
-static int adxl34x_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int adxl34x_i2c_probe(struct i2c_client *client)
{
struct adxl34x *ac;
int error;
@@ -159,7 +158,7 @@ static struct i2c_driver adxl34x_driver = {
.pm = &adxl34x_i2c_pm,
.of_match_table = adxl34x_of_id,
},
- .probe = adxl34x_i2c_probe,
+ .probe_new = adxl34x_i2c_probe,
.remove = adxl34x_i2c_remove,
.id_table = adxl34x_id,
};
diff --git a/drivers/input/misc/apanel.c b/drivers/input/misc/apanel.c
index 7276657ad7ca..f42d3219cdcc 100644
--- a/drivers/input/misc/apanel.c
+++ b/drivers/input/misc/apanel.c
@@ -120,8 +120,7 @@ static int mail_led_set(struct led_classdev *led,
return i2c_smbus_write_word_data(ap->client, 0x10, led_bits);
}
-static int apanel_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int apanel_probe(struct i2c_client *client)
{
struct apanel *ap;
struct input_dev *idev;
@@ -202,7 +201,7 @@ static struct i2c_driver apanel_driver = {
.driver = {
.name = APANEL,
},
- .probe = apanel_probe,
+ .probe_new = apanel_probe,
.shutdown = apanel_shutdown,
.id_table = apanel_id,
};
diff --git a/drivers/input/misc/atlas_btns.c b/drivers/input/misc/atlas_btns.c
index 0e77c40e1966..3c9bbd04e143 100644
--- a/drivers/input/misc/atlas_btns.c
+++ b/drivers/input/misc/atlas_btns.c
@@ -106,7 +106,7 @@ static int atlas_acpi_button_add(struct acpi_device *device)
return err;
}
-static int atlas_acpi_button_remove(struct acpi_device *device)
+static void atlas_acpi_button_remove(struct acpi_device *device)
{
acpi_status status;
@@ -116,8 +116,6 @@ static int atlas_acpi_button_remove(struct acpi_device *device)
pr_err("error removing addr spc handler\n");
input_unregister_device(input_dev);
-
- return 0;
}
static const struct acpi_device_id atlas_device_ids[] = {
diff --git a/drivers/input/misc/atmel_captouch.c b/drivers/input/misc/atmel_captouch.c
index 051aded6815a..d9704b174d3a 100644
--- a/drivers/input/misc/atmel_captouch.c
+++ b/drivers/input/misc/atmel_captouch.c
@@ -161,8 +161,7 @@ out:
/*
* Probe function to setup the device, input system and interrupt
*/
-static int atmel_captouch_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int atmel_captouch_probe(struct i2c_client *client)
{
struct atmel_captouch_device *capdev;
struct device *dev = &client->dev;
@@ -249,7 +248,6 @@ static int atmel_captouch_probe(struct i2c_client *client,
return 0;
}
-#ifdef CONFIG_OF
static const struct of_device_id atmel_captouch_of_id[] = {
{
.compatible = "atmel,captouch",
@@ -257,7 +255,6 @@ static const struct of_device_id atmel_captouch_of_id[] = {
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, atmel_captouch_of_id);
-#endif
static const struct i2c_device_id atmel_captouch_id[] = {
{ "atmel_captouch", 0 },
@@ -266,11 +263,11 @@ static const struct i2c_device_id atmel_captouch_id[] = {
MODULE_DEVICE_TABLE(i2c, atmel_captouch_id);
static struct i2c_driver atmel_captouch_driver = {
- .probe = atmel_captouch_probe,
+ .probe_new = atmel_captouch_probe,
.id_table = atmel_captouch_id,
.driver = {
.name = "atmel_captouch",
- .of_match_table = of_match_ptr(atmel_captouch_of_id),
+ .of_match_table = atmel_captouch_of_id,
},
};
module_i2c_driver(atmel_captouch_driver);
diff --git a/drivers/input/misc/bma150.c b/drivers/input/misc/bma150.c
index 84fe394da7a6..3f9da5c3cb53 100644
--- a/drivers/input/misc/bma150.c
+++ b/drivers/input/misc/bma150.c
@@ -414,8 +414,7 @@ static int bma150_initialize(struct bma150_data *bma150,
return bma150_set_mode(bma150, BMA150_MODE_SLEEP);
}
-static int bma150_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int bma150_probe(struct i2c_client *client)
{
const struct bma150_platform_data *pdata =
dev_get_platdata(&client->dev);
@@ -552,7 +551,7 @@ static struct i2c_driver bma150_driver = {
},
.class = I2C_CLASS_HWMON,
.id_table = bma150_id,
- .probe = bma150_probe,
+ .probe_new = bma150_probe,
.remove = bma150_remove,
};
diff --git a/drivers/input/misc/cma3000_d0x_i2c.c b/drivers/input/misc/cma3000_d0x_i2c.c
index 3b23210c46b7..75442c1230b1 100644
--- a/drivers/input/misc/cma3000_d0x_i2c.c
+++ b/drivers/input/misc/cma3000_d0x_i2c.c
@@ -44,8 +44,7 @@ static const struct cma3000_bus_ops cma3000_i2c_bops = {
.write = cma3000_i2c_set,
};
-static int cma3000_i2c_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int cma3000_i2c_probe(struct i2c_client *client)
{
struct cma3000_accl_data *data;
@@ -100,7 +99,7 @@ static const struct i2c_device_id cma3000_i2c_id[] = {
MODULE_DEVICE_TABLE(i2c, cma3000_i2c_id);
static struct i2c_driver cma3000_i2c_driver = {
- .probe = cma3000_i2c_probe,
+ .probe_new = cma3000_i2c_probe,
.remove = cma3000_i2c_remove,
.id_table = cma3000_i2c_id,
.driver = {
diff --git a/drivers/input/misc/da7280.c b/drivers/input/misc/da7280.c
index b08610d6e575..dcdea33b1a8f 100644
--- a/drivers/input/misc/da7280.c
+++ b/drivers/input/misc/da7280.c
@@ -1140,8 +1140,7 @@ out_err:
return error;
}
-static int da7280_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int da7280_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct da7280_haptic *haptics;
@@ -1322,7 +1321,7 @@ static struct i2c_driver da7280_driver = {
.of_match_table = of_match_ptr(da7280_of_match),
.pm = &da7280_pm_ops,
},
- .probe = da7280_probe,
+ .probe_new = da7280_probe,
.id_table = da7280_i2c_id,
};
module_i2c_driver(da7280_driver);
diff --git a/drivers/input/misc/drv260x.c b/drivers/input/misc/drv260x.c
index 0efe56f49aa9..3a51ee5e935a 100644
--- a/drivers/input/misc/drv260x.c
+++ b/drivers/input/misc/drv260x.c
@@ -457,8 +457,7 @@ static const struct regmap_config drv260x_regmap_config = {
.cache_type = REGCACHE_NONE,
};
-static int drv260x_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int drv260x_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct drv260x_data *haptics;
@@ -654,7 +653,7 @@ static const struct of_device_id drv260x_of_match[] = {
MODULE_DEVICE_TABLE(of, drv260x_of_match);
static struct i2c_driver drv260x_driver = {
- .probe = drv260x_probe,
+ .probe_new = drv260x_probe,
.driver = {
.name = "drv260x-haptics",
.of_match_table = drv260x_of_match,
diff --git a/drivers/input/misc/drv2665.c b/drivers/input/misc/drv2665.c
index 21913e8085d7..c2a2ff980c06 100644
--- a/drivers/input/misc/drv2665.c
+++ b/drivers/input/misc/drv2665.c
@@ -156,8 +156,7 @@ static const struct regmap_config drv2665_regmap_config = {
.cache_type = REGCACHE_NONE,
};
-static int drv2665_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int drv2665_probe(struct i2c_client *client)
{
struct drv2665_data *haptics;
int error;
@@ -298,7 +297,7 @@ MODULE_DEVICE_TABLE(of, drv2665_of_match);
#endif
static struct i2c_driver drv2665_driver = {
- .probe = drv2665_probe,
+ .probe_new = drv2665_probe,
.driver = {
.name = "drv2665-haptics",
.of_match_table = of_match_ptr(drv2665_of_match),
diff --git a/drivers/input/misc/drv2667.c b/drivers/input/misc/drv2667.c
index 3f67b9b010bf..da7ac63dce4c 100644
--- a/drivers/input/misc/drv2667.c
+++ b/drivers/input/misc/drv2667.c
@@ -333,8 +333,7 @@ static const struct regmap_config drv2667_regmap_config = {
.cache_type = REGCACHE_NONE,
};
-static int drv2667_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int drv2667_probe(struct i2c_client *client)
{
struct drv2667_data *haptics;
int error;
@@ -475,7 +474,7 @@ MODULE_DEVICE_TABLE(of, drv2667_of_match);
#endif
static struct i2c_driver drv2667_driver = {
- .probe = drv2667_probe,
+ .probe_new = drv2667_probe,
.driver = {
.name = "drv2667-haptics",
.of_match_table = of_match_ptr(drv2667_of_match),
diff --git a/drivers/input/misc/ibm-panel.c b/drivers/input/misc/ibm-panel.c
index a8fba0054719..3969ffc1bc8d 100644
--- a/drivers/input/misc/ibm-panel.c
+++ b/drivers/input/misc/ibm-panel.c
@@ -119,8 +119,7 @@ static int ibm_panel_i2c_slave_cb(struct i2c_client *client,
return 0;
}
-static int ibm_panel_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
+static int ibm_panel_probe(struct i2c_client *client)
{
struct ibm_panel *panel;
int i;
@@ -190,7 +189,7 @@ static struct i2c_driver ibm_panel_driver = {
.name = DEVICE_NAME,
.of_match_table = ibm_panel_match,
},
- .probe = ibm_panel_probe,
+ .probe_new = ibm_panel_probe,
.remove = ibm_panel_remove,
};
module_i2c_driver(ibm_panel_driver);
diff --git a/drivers/input/misc/iqs7222.c b/drivers/input/misc/iqs7222.c
index ddb863bf63ee..e47ab6c1177f 100644
--- a/drivers/input/misc/iqs7222.c
+++ b/drivers/input/misc/iqs7222.c
@@ -86,7 +86,9 @@ enum iqs7222_reg_key_id {
IQS7222_REG_KEY_TOUCH,
IQS7222_REG_KEY_DEBOUNCE,
IQS7222_REG_KEY_TAP,
+ IQS7222_REG_KEY_TAP_LEGACY,
IQS7222_REG_KEY_AXIAL,
+ IQS7222_REG_KEY_AXIAL_LEGACY,
IQS7222_REG_KEY_WHEEL,
IQS7222_REG_KEY_NO_WHEEL,
IQS7222_REG_KEY_RESERVED
@@ -105,14 +107,14 @@ enum iqs7222_reg_grp_id {
IQS7222_NUM_REG_GRPS
};
-static const char * const iqs7222_reg_grp_names[] = {
+static const char * const iqs7222_reg_grp_names[IQS7222_NUM_REG_GRPS] = {
[IQS7222_REG_GRP_CYCLE] = "cycle",
[IQS7222_REG_GRP_CHAN] = "channel",
[IQS7222_REG_GRP_SLDR] = "slider",
[IQS7222_REG_GRP_GPIO] = "gpio",
};
-static const unsigned int iqs7222_max_cols[] = {
+static const unsigned int iqs7222_max_cols[IQS7222_NUM_REG_GRPS] = {
[IQS7222_REG_GRP_STAT] = IQS7222_MAX_COLS_STAT,
[IQS7222_REG_GRP_CYCLE] = IQS7222_MAX_COLS_CYCLE,
[IQS7222_REG_GRP_GLBL] = IQS7222_MAX_COLS_GLBL,
@@ -202,6 +204,7 @@ struct iqs7222_dev_desc {
int allow_offset;
int event_offset;
int comms_offset;
+ bool legacy_gesture;
struct iqs7222_reg_grp_desc reg_grps[IQS7222_NUM_REG_GRPS];
};
@@ -209,12 +212,70 @@ static const struct iqs7222_dev_desc iqs7222_devs[] = {
{
.prod_num = IQS7222_PROD_NUM_A,
.fw_major = 1,
+ .fw_minor = 13,
+ .sldr_res = U8_MAX * 16,
+ .touch_link = 1768,
+ .allow_offset = 9,
+ .event_offset = 10,
+ .comms_offset = 12,
+ .reg_grps = {
+ [IQS7222_REG_GRP_STAT] = {
+ .base = IQS7222_SYS_STATUS,
+ .num_row = 1,
+ .num_col = 8,
+ },
+ [IQS7222_REG_GRP_CYCLE] = {
+ .base = 0x8000,
+ .num_row = 7,
+ .num_col = 3,
+ },
+ [IQS7222_REG_GRP_GLBL] = {
+ .base = 0x8700,
+ .num_row = 1,
+ .num_col = 3,
+ },
+ [IQS7222_REG_GRP_BTN] = {
+ .base = 0x9000,
+ .num_row = 12,
+ .num_col = 3,
+ },
+ [IQS7222_REG_GRP_CHAN] = {
+ .base = 0xA000,
+ .num_row = 12,
+ .num_col = 6,
+ },
+ [IQS7222_REG_GRP_FILT] = {
+ .base = 0xAC00,
+ .num_row = 1,
+ .num_col = 2,
+ },
+ [IQS7222_REG_GRP_SLDR] = {
+ .base = 0xB000,
+ .num_row = 2,
+ .num_col = 11,
+ },
+ [IQS7222_REG_GRP_GPIO] = {
+ .base = 0xC000,
+ .num_row = 1,
+ .num_col = 3,
+ },
+ [IQS7222_REG_GRP_SYS] = {
+ .base = IQS7222_SYS_SETUP,
+ .num_row = 1,
+ .num_col = 13,
+ },
+ },
+ },
+ {
+ .prod_num = IQS7222_PROD_NUM_A,
+ .fw_major = 1,
.fw_minor = 12,
.sldr_res = U8_MAX * 16,
.touch_link = 1768,
.allow_offset = 9,
.event_offset = 10,
.comms_offset = 12,
+ .legacy_gesture = true,
.reg_grps = {
[IQS7222_REG_GRP_STAT] = {
.base = IQS7222_SYS_STATUS,
@@ -874,6 +935,16 @@ static const struct iqs7222_prop_desc iqs7222_props[] = {
.reg_offset = 9,
.reg_shift = 8,
.reg_width = 8,
+ .val_pitch = 16,
+ .label = "maximum gesture time",
+ },
+ {
+ .name = "azoteq,gesture-max-ms",
+ .reg_grp = IQS7222_REG_GRP_SLDR,
+ .reg_key = IQS7222_REG_KEY_TAP_LEGACY,
+ .reg_offset = 9,
+ .reg_shift = 8,
+ .reg_width = 8,
.val_pitch = 4,
.label = "maximum gesture time",
},
@@ -884,6 +955,16 @@ static const struct iqs7222_prop_desc iqs7222_props[] = {
.reg_offset = 9,
.reg_shift = 3,
.reg_width = 5,
+ .val_pitch = 16,
+ .label = "minimum gesture time",
+ },
+ {
+ .name = "azoteq,gesture-min-ms",
+ .reg_grp = IQS7222_REG_GRP_SLDR,
+ .reg_key = IQS7222_REG_KEY_TAP_LEGACY,
+ .reg_offset = 9,
+ .reg_shift = 3,
+ .reg_width = 5,
.val_pitch = 4,
.label = "minimum gesture time",
},
@@ -898,12 +979,32 @@ static const struct iqs7222_prop_desc iqs7222_props[] = {
.label = "gesture distance",
},
{
+ .name = "azoteq,gesture-dist",
+ .reg_grp = IQS7222_REG_GRP_SLDR,
+ .reg_key = IQS7222_REG_KEY_AXIAL_LEGACY,
+ .reg_offset = 10,
+ .reg_shift = 8,
+ .reg_width = 8,
+ .val_pitch = 16,
+ .label = "gesture distance",
+ },
+ {
.name = "azoteq,gesture-max-ms",
.reg_grp = IQS7222_REG_GRP_SLDR,
.reg_key = IQS7222_REG_KEY_AXIAL,
.reg_offset = 10,
.reg_shift = 0,
.reg_width = 8,
+ .val_pitch = 16,
+ .label = "maximum gesture time",
+ },
+ {
+ .name = "azoteq,gesture-max-ms",
+ .reg_grp = IQS7222_REG_GRP_SLDR,
+ .reg_key = IQS7222_REG_KEY_AXIAL_LEGACY,
+ .reg_offset = 10,
+ .reg_shift = 0,
+ .reg_width = 8,
.val_pitch = 4,
.label = "maximum gesture time",
},
@@ -1567,56 +1668,17 @@ static int iqs7222_gpio_select(struct iqs7222_private *iqs7222,
}
static int iqs7222_parse_props(struct iqs7222_private *iqs7222,
- struct fwnode_handle **child_node,
- int child_index,
+ struct fwnode_handle *reg_grp_node,
+ int reg_grp_index,
enum iqs7222_reg_grp_id reg_grp,
enum iqs7222_reg_key_id reg_key)
{
- u16 *setup = iqs7222_setup(iqs7222, reg_grp, child_index);
+ u16 *setup = iqs7222_setup(iqs7222, reg_grp, reg_grp_index);
struct i2c_client *client = iqs7222->client;
- struct fwnode_handle *reg_grp_node;
- char reg_grp_name[16];
int i;
- switch (reg_grp) {
- case IQS7222_REG_GRP_CYCLE:
- case IQS7222_REG_GRP_CHAN:
- case IQS7222_REG_GRP_SLDR:
- case IQS7222_REG_GRP_GPIO:
- case IQS7222_REG_GRP_BTN:
- /*
- * These groups derive a child node and return it to the caller
- * for additional group-specific processing. In some cases, the
- * child node may have already been derived.
- */
- reg_grp_node = *child_node;
- if (reg_grp_node)
- break;
-
- snprintf(reg_grp_name, sizeof(reg_grp_name), "%s-%d",
- iqs7222_reg_grp_names[reg_grp], child_index);
-
- reg_grp_node = device_get_named_child_node(&client->dev,
- reg_grp_name);
- if (!reg_grp_node)
- return 0;
-
- *child_node = reg_grp_node;
- break;
-
- case IQS7222_REG_GRP_GLBL:
- case IQS7222_REG_GRP_FILT:
- case IQS7222_REG_GRP_SYS:
- /*
- * These groups are not organized beneath a child node, nor are
- * they subject to any additional processing by the caller.
- */
- reg_grp_node = dev_fwnode(&client->dev);
- break;
-
- default:
- return -EINVAL;
- }
+ if (!setup)
+ return 0;
for (i = 0; i < ARRAY_SIZE(iqs7222_props); i++) {
const char *name = iqs7222_props[i].name;
@@ -1686,11 +1748,66 @@ static int iqs7222_parse_props(struct iqs7222_private *iqs7222,
return 0;
}
-static int iqs7222_parse_cycle(struct iqs7222_private *iqs7222, int cycle_index)
+static int iqs7222_parse_event(struct iqs7222_private *iqs7222,
+ struct fwnode_handle *event_node,
+ int reg_grp_index,
+ enum iqs7222_reg_grp_id reg_grp,
+ enum iqs7222_reg_key_id reg_key,
+ u16 event_enable, u16 event_link,
+ unsigned int *event_type,
+ unsigned int *event_code)
+{
+ struct i2c_client *client = iqs7222->client;
+ int error;
+
+ error = iqs7222_parse_props(iqs7222, event_node, reg_grp_index,
+ reg_grp, reg_key);
+ if (error)
+ return error;
+
+ error = iqs7222_gpio_select(iqs7222, event_node, event_enable,
+ event_link);
+ if (error)
+ return error;
+
+ error = fwnode_property_read_u32(event_node, "linux,code", event_code);
+ if (error == -EINVAL) {
+ return 0;
+ } else if (error) {
+ dev_err(&client->dev, "Failed to read %s code: %d\n",
+ fwnode_get_name(event_node), error);
+ return error;
+ }
+
+ if (!event_type) {
+ input_set_capability(iqs7222->keypad, EV_KEY, *event_code);
+ return 0;
+ }
+
+ error = fwnode_property_read_u32(event_node, "linux,input-type",
+ event_type);
+ if (error == -EINVAL) {
+ *event_type = EV_KEY;
+ } else if (error) {
+ dev_err(&client->dev, "Failed to read %s input type: %d\n",
+ fwnode_get_name(event_node), error);
+ return error;
+ } else if (*event_type != EV_KEY && *event_type != EV_SW) {
+ dev_err(&client->dev, "Invalid %s input type: %d\n",
+ fwnode_get_name(event_node), *event_type);
+ return -EINVAL;
+ }
+
+ input_set_capability(iqs7222->keypad, *event_type, *event_code);
+
+ return 0;
+}
+
+static int iqs7222_parse_cycle(struct iqs7222_private *iqs7222,
+ struct fwnode_handle *cycle_node, int cycle_index)
{
u16 *cycle_setup = iqs7222->cycle_setup[cycle_index];
struct i2c_client *client = iqs7222->client;
- struct fwnode_handle *cycle_node = NULL;
unsigned int pins[9];
int error, count, i;
@@ -1698,17 +1815,7 @@ static int iqs7222_parse_cycle(struct iqs7222_private *iqs7222, int cycle_index)
* Each channel shares a cycle with one other channel; the mapping of
* channels to cycles is fixed. Properties defined for a cycle impact
* both channels tied to the cycle.
- */
- error = iqs7222_parse_props(iqs7222, &cycle_node, cycle_index,
- IQS7222_REG_GRP_CYCLE,
- IQS7222_REG_KEY_NONE);
- if (error)
- return error;
-
- if (!cycle_node)
- return 0;
-
- /*
+ *
* Unlike channels which are restricted to a select range of CRx pins
* based on channel number, any cycle can claim any of the device's 9
* CTx pins (CTx0-8).
@@ -1750,11 +1857,11 @@ static int iqs7222_parse_cycle(struct iqs7222_private *iqs7222, int cycle_index)
return 0;
}
-static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
+static int iqs7222_parse_chan(struct iqs7222_private *iqs7222,
+ struct fwnode_handle *chan_node, int chan_index)
{
const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc;
struct i2c_client *client = iqs7222->client;
- struct fwnode_handle *chan_node = NULL;
int num_chan = dev_desc->reg_grps[IQS7222_REG_GRP_CHAN].num_row;
int ext_chan = rounddown(num_chan, 10);
int error, i;
@@ -1762,15 +1869,6 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
u16 *sys_setup = iqs7222->sys_setup;
unsigned int val;
- error = iqs7222_parse_props(iqs7222, &chan_node, chan_index,
- IQS7222_REG_GRP_CHAN,
- IQS7222_REG_KEY_NONE);
- if (error)
- return error;
-
- if (!chan_node)
- return 0;
-
if (dev_desc->allow_offset &&
fwnode_property_present(chan_node, "azoteq,ulp-allow"))
sys_setup[dev_desc->allow_offset] &= ~BIT(chan_index);
@@ -1810,8 +1908,9 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
chan_setup[0] |= IQS7222_CHAN_SETUP_0_REF_MODE_FOLLOW;
chan_setup[4] = val * 42 + 1048;
- if (!fwnode_property_read_u32(chan_node, "azoteq,ref-weight",
- &val)) {
+ error = fwnode_property_read_u32(chan_node, "azoteq,ref-weight",
+ &val);
+ if (!error) {
if (val > U16_MAX) {
dev_err(&client->dev,
"Invalid %s reference weight: %u\n",
@@ -1820,6 +1919,11 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
}
chan_setup[5] = val;
+ } else if (error != -EINVAL) {
+ dev_err(&client->dev,
+ "Failed to read %s reference weight: %d\n",
+ fwnode_get_name(chan_node), error);
+ return error;
}
/*
@@ -1892,21 +1996,10 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
if (!event_node)
continue;
- error = iqs7222_parse_props(iqs7222, &event_node, chan_index,
- IQS7222_REG_GRP_BTN,
- iqs7222_kp_events[i].reg_key);
- if (error)
- return error;
-
- error = iqs7222_gpio_select(iqs7222, event_node,
- BIT(chan_index),
- dev_desc->touch_link - (i ? 0 : 2));
- if (error)
- return error;
-
- if (!fwnode_property_read_u32(event_node,
- "azoteq,timeout-press-ms",
- &val)) {
+ error = fwnode_property_read_u32(event_node,
+ "azoteq,timeout-press-ms",
+ &val);
+ if (!error) {
/*
* The IQS7222B employs a global pair of press timeout
* registers as opposed to channel-specific registers.
@@ -1919,57 +2012,31 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
if (val > U8_MAX * 500) {
dev_err(&client->dev,
"Invalid %s press timeout: %u\n",
- fwnode_get_name(chan_node), val);
+ fwnode_get_name(event_node), val);
+ fwnode_handle_put(event_node);
return -EINVAL;
}
*setup &= ~(U8_MAX << i * 8);
*setup |= (val / 500 << i * 8);
- }
-
- error = fwnode_property_read_u32(event_node, "linux,code",
- &val);
- if (error) {
- dev_err(&client->dev, "Failed to read %s code: %d\n",
- fwnode_get_name(chan_node), error);
+ } else if (error != -EINVAL) {
+ dev_err(&client->dev,
+ "Failed to read %s press timeout: %d\n",
+ fwnode_get_name(event_node), error);
+ fwnode_handle_put(event_node);
return error;
}
- iqs7222->kp_code[chan_index][i] = val;
- iqs7222->kp_type[chan_index][i] = EV_KEY;
-
- if (fwnode_property_present(event_node, "linux,input-type")) {
- error = fwnode_property_read_u32(event_node,
- "linux,input-type",
- &val);
- if (error) {
- dev_err(&client->dev,
- "Failed to read %s input type: %d\n",
- fwnode_get_name(chan_node), error);
- return error;
- }
-
- if (val != EV_KEY && val != EV_SW) {
- dev_err(&client->dev,
- "Invalid %s input type: %u\n",
- fwnode_get_name(chan_node), val);
- return -EINVAL;
- }
-
- iqs7222->kp_type[chan_index][i] = val;
- }
-
- /*
- * Reference channels can opt out of event reporting by using
- * KEY_RESERVED in place of a true key or switch code.
- */
- if (iqs7222->kp_type[chan_index][i] == EV_KEY &&
- iqs7222->kp_code[chan_index][i] == KEY_RESERVED)
- continue;
-
- input_set_capability(iqs7222->keypad,
- iqs7222->kp_type[chan_index][i],
- iqs7222->kp_code[chan_index][i]);
+ error = iqs7222_parse_event(iqs7222, event_node, chan_index,
+ IQS7222_REG_GRP_BTN,
+ iqs7222_kp_events[i].reg_key,
+ BIT(chan_index),
+ dev_desc->touch_link - (i ? 0 : 2),
+ &iqs7222->kp_type[chan_index][i],
+ &iqs7222->kp_code[chan_index][i]);
+ fwnode_handle_put(event_node);
+ if (error)
+ return error;
if (!dev_desc->event_offset)
continue;
@@ -1981,16 +2048,16 @@ static int iqs7222_parse_chan(struct iqs7222_private *iqs7222, int chan_index)
* The following call handles a special pair of properties that apply
* to a channel node, but reside within the button (event) group.
*/
- return iqs7222_parse_props(iqs7222, &chan_node, chan_index,
+ return iqs7222_parse_props(iqs7222, chan_node, chan_index,
IQS7222_REG_GRP_BTN,
IQS7222_REG_KEY_DEBOUNCE);
}
-static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)
+static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222,
+ struct fwnode_handle *sldr_node, int sldr_index)
{
const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc;
struct i2c_client *client = iqs7222->client;
- struct fwnode_handle *sldr_node = NULL;
int num_chan = dev_desc->reg_grps[IQS7222_REG_GRP_CHAN].num_row;
int ext_chan = rounddown(num_chan, 10);
int count, error, reg_offset, i;
@@ -1998,15 +2065,6 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)
u16 *sldr_setup = iqs7222->sldr_setup[sldr_index];
unsigned int chan_sel[4], val;
- error = iqs7222_parse_props(iqs7222, &sldr_node, sldr_index,
- IQS7222_REG_GRP_SLDR,
- IQS7222_REG_KEY_NONE);
- if (error)
- return error;
-
- if (!sldr_node)
- return 0;
-
/*
* Each slider can be spread across 3 to 4 channels. It is possible to
* select only 2 channels, but doing so prevents the slider from using
@@ -2065,8 +2123,9 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)
if (fwnode_property_present(sldr_node, "azoteq,use-prox"))
sldr_setup[4 + reg_offset] -= 2;
- if (!fwnode_property_read_u32(sldr_node, "azoteq,slider-size", &val)) {
- if (!val || val > dev_desc->sldr_res) {
+ error = fwnode_property_read_u32(sldr_node, "azoteq,slider-size", &val);
+ if (!error) {
+ if (val > dev_desc->sldr_res) {
dev_err(&client->dev, "Invalid %s size: %u\n",
fwnode_get_name(sldr_node), val);
return -EINVAL;
@@ -2079,9 +2138,21 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)
sldr_setup[2] |= (val / 16 <<
IQS7222_SLDR_SETUP_2_RES_SHIFT);
}
+ } else if (error != -EINVAL) {
+ dev_err(&client->dev, "Failed to read %s size: %d\n",
+ fwnode_get_name(sldr_node), error);
+ return error;
}
- if (!fwnode_property_read_u32(sldr_node, "azoteq,top-speed", &val)) {
+ if (!(reg_offset ? sldr_setup[3]
+ : sldr_setup[2] & IQS7222_SLDR_SETUP_2_RES_MASK)) {
+ dev_err(&client->dev, "Undefined %s size\n",
+ fwnode_get_name(sldr_node));
+ return -EINVAL;
+ }
+
+ error = fwnode_property_read_u32(sldr_node, "azoteq,top-speed", &val);
+ if (!error) {
if (val > (reg_offset ? U16_MAX : U8_MAX * 4)) {
dev_err(&client->dev, "Invalid %s top speed: %u\n",
fwnode_get_name(sldr_node), val);
@@ -2094,9 +2165,14 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)
sldr_setup[2] &= ~IQS7222_SLDR_SETUP_2_TOP_SPEED_MASK;
sldr_setup[2] |= (val / 4);
}
+ } else if (error != -EINVAL) {
+ dev_err(&client->dev, "Failed to read %s top speed: %d\n",
+ fwnode_get_name(sldr_node), error);
+ return error;
}
- if (!fwnode_property_read_u32(sldr_node, "linux,axis", &val)) {
+ error = fwnode_property_read_u32(sldr_node, "linux,axis", &val);
+ if (!error) {
u16 sldr_max = sldr_setup[3] - 1;
if (!reg_offset) {
@@ -2110,6 +2186,10 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)
input_set_abs_params(iqs7222->keypad, val, 0, sldr_max, 0, 0);
iqs7222->sl_axis[sldr_index] = val;
+ } else if (error != -EINVAL) {
+ dev_err(&client->dev, "Failed to read %s axis: %d\n",
+ fwnode_get_name(sldr_node), error);
+ return error;
}
if (dev_desc->wheel_enable) {
@@ -2130,46 +2210,47 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)
for (i = 0; i < ARRAY_SIZE(iqs7222_sl_events); i++) {
const char *event_name = iqs7222_sl_events[i].name;
struct fwnode_handle *event_node;
+ enum iqs7222_reg_key_id reg_key;
event_node = fwnode_get_named_child_node(sldr_node, event_name);
if (!event_node)
continue;
- error = iqs7222_parse_props(iqs7222, &event_node, sldr_index,
- IQS7222_REG_GRP_SLDR,
- reg_offset ?
- IQS7222_REG_KEY_RESERVED :
- iqs7222_sl_events[i].reg_key);
- if (error)
- return error;
+ /*
+ * Depending on the device, gestures are either offered using
+ * one of two timing resolutions, or are not supported at all.
+ */
+ if (reg_offset)
+ reg_key = IQS7222_REG_KEY_RESERVED;
+ else if (dev_desc->legacy_gesture &&
+ iqs7222_sl_events[i].reg_key == IQS7222_REG_KEY_TAP)
+ reg_key = IQS7222_REG_KEY_TAP_LEGACY;
+ else if (dev_desc->legacy_gesture &&
+ iqs7222_sl_events[i].reg_key == IQS7222_REG_KEY_AXIAL)
+ reg_key = IQS7222_REG_KEY_AXIAL_LEGACY;
+ else
+ reg_key = iqs7222_sl_events[i].reg_key;
/*
* The press/release event does not expose a direct GPIO link,
* but one can be emulated by tying each of the participating
* channels to the same GPIO.
*/
- error = iqs7222_gpio_select(iqs7222, event_node,
+ error = iqs7222_parse_event(iqs7222, event_node, sldr_index,
+ IQS7222_REG_GRP_SLDR, reg_key,
i ? iqs7222_sl_events[i].enable
: sldr_setup[3 + reg_offset],
i ? 1568 + sldr_index * 30
- : sldr_setup[4 + reg_offset]);
+ : sldr_setup[4 + reg_offset],
+ NULL,
+ &iqs7222->sl_code[sldr_index][i]);
+ fwnode_handle_put(event_node);
if (error)
return error;
if (!reg_offset)
sldr_setup[9] |= iqs7222_sl_events[i].enable;
- error = fwnode_property_read_u32(event_node, "linux,code",
- &val);
- if (error) {
- dev_err(&client->dev, "Failed to read %s code: %d\n",
- fwnode_get_name(sldr_node), error);
- return error;
- }
-
- iqs7222->sl_code[sldr_index][i] = val;
- input_set_capability(iqs7222->keypad, EV_KEY, val);
-
if (!dev_desc->event_offset)
continue;
@@ -2190,19 +2271,63 @@ static int iqs7222_parse_sldr(struct iqs7222_private *iqs7222, int sldr_index)
* The following call handles a special pair of properties that shift
* to make room for a wheel enable control in the case of IQS7222C.
*/
- return iqs7222_parse_props(iqs7222, &sldr_node, sldr_index,
+ return iqs7222_parse_props(iqs7222, sldr_node, sldr_index,
IQS7222_REG_GRP_SLDR,
dev_desc->wheel_enable ?
IQS7222_REG_KEY_WHEEL :
IQS7222_REG_KEY_NO_WHEEL);
}
+static int (*iqs7222_parse_extra[IQS7222_NUM_REG_GRPS])
+ (struct iqs7222_private *iqs7222,
+ struct fwnode_handle *reg_grp_node,
+ int reg_grp_index) = {
+ [IQS7222_REG_GRP_CYCLE] = iqs7222_parse_cycle,
+ [IQS7222_REG_GRP_CHAN] = iqs7222_parse_chan,
+ [IQS7222_REG_GRP_SLDR] = iqs7222_parse_sldr,
+};
+
+static int iqs7222_parse_reg_grp(struct iqs7222_private *iqs7222,
+ enum iqs7222_reg_grp_id reg_grp,
+ int reg_grp_index)
+{
+ struct i2c_client *client = iqs7222->client;
+ struct fwnode_handle *reg_grp_node;
+ int error;
+
+ if (iqs7222_reg_grp_names[reg_grp]) {
+ char reg_grp_name[16];
+
+ snprintf(reg_grp_name, sizeof(reg_grp_name), "%s-%d",
+ iqs7222_reg_grp_names[reg_grp], reg_grp_index);
+
+ reg_grp_node = device_get_named_child_node(&client->dev,
+ reg_grp_name);
+ } else {
+ reg_grp_node = fwnode_handle_get(dev_fwnode(&client->dev));
+ }
+
+ if (!reg_grp_node)
+ return 0;
+
+ error = iqs7222_parse_props(iqs7222, reg_grp_node, reg_grp_index,
+ reg_grp, IQS7222_REG_KEY_NONE);
+
+ if (!error && iqs7222_parse_extra[reg_grp])
+ error = iqs7222_parse_extra[reg_grp](iqs7222, reg_grp_node,
+ reg_grp_index);
+
+ fwnode_handle_put(reg_grp_node);
+
+ return error;
+}
+
static int iqs7222_parse_all(struct iqs7222_private *iqs7222)
{
const struct iqs7222_dev_desc *dev_desc = iqs7222->dev_desc;
const struct iqs7222_reg_grp_desc *reg_grps = dev_desc->reg_grps;
u16 *sys_setup = iqs7222->sys_setup;
- int error, i;
+ int error, i, j;
if (dev_desc->allow_offset)
sys_setup[dev_desc->allow_offset] = U16_MAX;
@@ -2210,32 +2335,13 @@ static int iqs7222_parse_all(struct iqs7222_private *iqs7222)
if (dev_desc->event_offset)
sys_setup[dev_desc->event_offset] = IQS7222_EVENT_MASK_ATI;
- for (i = 0; i < reg_grps[IQS7222_REG_GRP_CYCLE].num_row; i++) {
- error = iqs7222_parse_cycle(iqs7222, i);
- if (error)
- return error;
- }
-
- error = iqs7222_parse_props(iqs7222, NULL, 0, IQS7222_REG_GRP_GLBL,
- IQS7222_REG_KEY_NONE);
- if (error)
- return error;
-
for (i = 0; i < reg_grps[IQS7222_REG_GRP_GPIO].num_row; i++) {
- struct fwnode_handle *gpio_node = NULL;
u16 *gpio_setup = iqs7222->gpio_setup[i];
- int j;
gpio_setup[0] &= ~IQS7222_GPIO_SETUP_0_GPIO_EN;
gpio_setup[1] = 0;
gpio_setup[2] = 0;
- error = iqs7222_parse_props(iqs7222, &gpio_node, i,
- IQS7222_REG_GRP_GPIO,
- IQS7222_REG_KEY_NONE);
- if (error)
- return error;
-
if (reg_grps[IQS7222_REG_GRP_GPIO].num_row == 1)
continue;
@@ -2258,29 +2364,21 @@ static int iqs7222_parse_all(struct iqs7222_private *iqs7222)
chan_setup[5] = 0;
}
- for (i = 0; i < reg_grps[IQS7222_REG_GRP_CHAN].num_row; i++) {
- error = iqs7222_parse_chan(iqs7222, i);
- if (error)
- return error;
- }
-
- error = iqs7222_parse_props(iqs7222, NULL, 0, IQS7222_REG_GRP_FILT,
- IQS7222_REG_KEY_NONE);
- if (error)
- return error;
-
for (i = 0; i < reg_grps[IQS7222_REG_GRP_SLDR].num_row; i++) {
u16 *sldr_setup = iqs7222->sldr_setup[i];
sldr_setup[0] &= ~IQS7222_SLDR_SETUP_0_CHAN_CNT_MASK;
+ }
- error = iqs7222_parse_sldr(iqs7222, i);